From dbda92d16f8655044e082930e4e9d244b87fde77 Mon Sep 17 00:00:00 2001 From: "Bu, Yitian" Date: Mon, 18 Feb 2013 12:53:37 +0000 Subject: [PATCH 0001/2900] printk: Fix rq->lock vs logbuf_lock unlock lock inversion commit 07354eb1a74d1 ("locking printk: Annotate logbuf_lock as raw") reintroduced a lock inversion problem which was fixed in commit 0b5e1c5255 ("printk: Release console_sem after logbuf_lock"). This happened probably when fixing up patch rejects. Restore the ordering and unlock logbuf_lock before releasing console_sem. Signed-off-by: ybu Cc: Peter Zijlstra Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/E807E903FE6CBE4D95E420FBFCC273B827413C@nasanexd01h.na.qualcomm.com Signed-off-by: Thomas Gleixner --- kernel/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk.c b/kernel/printk.c index 267ce780abe8..e698e80d8428 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1358,9 +1358,9 @@ static int console_trylock_for_printk(unsigned int cpu) } } logbuf_cpu = UINT_MAX; + raw_spin_unlock(&logbuf_lock); if (wake) up(&console_sem); - raw_spin_unlock(&logbuf_lock); return retval; } -- GitLab From 5abf6c643115aa20905e36b649cbe80ad784f332 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 4 Mar 2013 16:25:46 +0000 Subject: [PATCH 0002/2900] ide: tx4938ide: use module_platform_driver_probe() This patch uses module_platform_driver_probe() macro which makes the code smaller and simpler. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/ide/tx4938ide.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 91d49dd957ef..ede8575ac7d5 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -203,18 +203,7 @@ static struct platform_driver tx4938ide_driver = { .remove = __exit_p(tx4938ide_remove), }; -static int __init tx4938ide_init(void) -{ - return platform_driver_probe(&tx4938ide_driver, tx4938ide_probe); -} - -static void __exit tx4938ide_exit(void) -{ - platform_driver_unregister(&tx4938ide_driver); -} - -module_init(tx4938ide_init); -module_exit(tx4938ide_exit); +module_platform_driver_probe(tx4938ide_driver, tx4938ide_probe); MODULE_DESCRIPTION("TX4938 internal IDE driver"); MODULE_LICENSE("GPL"); -- GitLab From 477c17dba125b9b500763f5437fa5051f75b95bf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 4 Mar 2013 16:26:53 +0000 Subject: [PATCH 0003/2900] ide: tx4939ide: use module_platform_driver_probe() This patch uses module_platform_driver_probe() macro which makes the code smaller and simpler. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/ide/tx4939ide.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index c0ab800b7bb3..4ecdee5eca83 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c @@ -624,18 +624,7 @@ static struct platform_driver tx4939ide_driver = { .resume = tx4939ide_resume, }; -static int __init tx4939ide_init(void) -{ - return platform_driver_probe(&tx4939ide_driver, tx4939ide_probe); -} - -static void __exit tx4939ide_exit(void) -{ - platform_driver_unregister(&tx4939ide_driver); -} - -module_init(tx4939ide_init); -module_exit(tx4939ide_exit); +module_platform_driver_probe(tx4939ide_driver, tx4939ide_probe); MODULE_DESCRIPTION("TX4939 internal IDE driver"); MODULE_LICENSE("GPL"); -- GitLab From bf6b4388c61cf88c6faa19cc45390fd36be8fb66 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 4 Mar 2013 16:27:36 +0000 Subject: [PATCH 0004/2900] ide: gayle: use module_platform_driver_probe() This patch uses module_platform_driver_probe() macro which makes the code smaller and simpler. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/ide/gayle.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index 51beb85250d4..0a8440ae0565 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c @@ -183,20 +183,7 @@ static struct platform_driver amiga_gayle_ide_driver = { }, }; -static int __init amiga_gayle_ide_init(void) -{ - return platform_driver_probe(&amiga_gayle_ide_driver, - amiga_gayle_ide_probe); -} - -module_init(amiga_gayle_ide_init); - -static void __exit amiga_gayle_ide_exit(void) -{ - platform_driver_unregister(&amiga_gayle_ide_driver); -} - -module_exit(amiga_gayle_ide_exit); +module_platform_driver_probe(amiga_gayle_ide_driver, amiga_gayle_ide_probe); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:amiga-gayle-ide"); -- GitLab From 2a456cfbdbcdf8a6a9e041f256f7e859a271a301 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:08 +0000 Subject: [PATCH 0005/2900] Thermal: armada_thermal: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Ezequiel Garcia Acked-by: Ezequiel Garcia Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/armada_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 5b4d75fd7b49..0d02d4edeecb 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -210,7 +210,6 @@ static int armada_thermal_exit(struct platform_device *pdev) platform_get_drvdata(pdev); thermal_zone_device_unregister(armada_thermal); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From aa50c4e49c650692559e2da1f5b49a145098ba71 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:09 +0000 Subject: [PATCH 0006/2900] Thermal: dove_thermal: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Andrew Lunn Acked-by: Andrew Lunn Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/dove_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 4b15a5f270dc..900479e69ccb 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -182,7 +182,6 @@ static int dove_thermal_exit(struct platform_device *pdev) platform_get_drvdata(pdev); thermal_zone_device_unregister(dove_thermal); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From a2071b0b449e6cb725a15932590ee5753c39d282 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:10 +0000 Subject: [PATCH 0007/2900] Thermal: exynos: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/exynos_thermal.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index d20ce9e61403..992ae6e25112 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -1001,7 +1001,6 @@ static int exynos_tmu_probe(struct platform_device *pdev) return 0; err_clk: - platform_set_drvdata(pdev, NULL); clk_unprepare(data->clk); return ret; } @@ -1016,8 +1015,6 @@ static int exynos_tmu_remove(struct platform_device *pdev) clk_unprepare(data->clk); - platform_set_drvdata(pdev, NULL); - return 0; } -- GitLab From 0f3913bd2dce5a756ca2384c963087713762ab66 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:11 +0000 Subject: [PATCH 0008/2900] Thermal: kirkwood: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Nobuhiro Iwamatsu Acked-by: Eduardo Valentin Acked-by: Nobuhiro Iwamatsu Signed-off-by: Zhang Rui --- drivers/thermal/kirkwood_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index dfeceaffbc03..b57a45daf0df 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -108,7 +108,6 @@ static int kirkwood_thermal_exit(struct platform_device *pdev) platform_get_drvdata(pdev); thermal_zone_device_unregister(kirkwood_thermal); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 6135ba36f44069ad789bd9f8d6a75eebc3946eba Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:12 +0000 Subject: [PATCH 0009/2900] Thermal: rcar: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Kuninori Morimoto Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/rcar_thermal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 8d7edd4c8228..63c7c13d79f3 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -487,8 +487,6 @@ static int rcar_thermal_remove(struct platform_device *pdev) rcar_thermal_irq_disable(priv); } - platform_set_drvdata(pdev, NULL); - pm_runtime_put_sync(dev); pm_runtime_disable(dev); -- GitLab From a1cf1150f127f78783f86c695f10337391fc8092 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 3 May 2013 09:57:13 +0000 Subject: [PATCH 0010/2900] Thermal: spear: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Vincenzo Frascino Acked-by: Eduardo Valentin Acked-by: Viresh Kumar Signed-off-by: Zhang Rui --- drivers/thermal/spear_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 3c5ee5607977..1a14eaa1bbd7 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -174,7 +174,6 @@ static int spear_thermal_exit(struct platform_device *pdev) struct spear_thermal_dev *stdev = spear_thermal->devdata; thermal_zone_device_unregister(spear_thermal); - platform_set_drvdata(pdev, NULL); /* Disable SPEAr Thermal Sensor */ actual_mask = readl_relaxed(stdev->thermal_base); -- GitLab From eb48241bb4484e56171fcb5beb39f530a2cd484e Mon Sep 17 00:00:00 2001 From: Zhao Hongjiang Date: Fri, 3 May 2013 18:08:24 +0800 Subject: [PATCH 0011/2900] nfsd: get rid of the unused functions in vfs The fh_lock_parent(), nfsd_truncate(), nfsd_notify_change() and nfsd_sync_dir() fuctions are neither implemented nor used, just remove them. Signed-off-by: Zhao Hongjiang Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 5b5894159f22..8d2b40d71669 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -39,7 +39,6 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); /* nfsd/vfs.c */ -int fh_lock_parent(struct svc_fh *, struct dentry *); int nfsd_racache_init(int); void nfsd_racache_shutdown(void); int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, @@ -92,17 +91,13 @@ __be32 nfsd_remove(struct svc_rqst *, struct svc_fh *, char *, int); __be32 nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type, char *name, int len); -int nfsd_truncate(struct svc_rqst *, struct svc_fh *, - unsigned long size); __be32 nfsd_readdir(struct svc_rqst *, struct svc_fh *, loff_t *, struct readdir_cd *, filldir_t); __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *, struct kstatfs *, int access); -int nfsd_notify_change(struct inode *, struct iattr *); __be32 nfsd_permission(struct svc_rqst *, struct svc_export *, struct dentry *, int); -int nfsd_sync_dir(struct dentry *dp); #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int); -- GitLab From 4f540e29dc20b87d460559bce184d2238237f48b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 7 May 2013 11:57:52 -0400 Subject: [PATCH 0012/2900] nfsd4: store correct client minorversion for >=4.2 This code assumes that any client using exchange_id is using NFSv4.1, but with the introduction of 4.2 that will no longer true. This main effect of this is that client callbacks will use the same minorversion as that used on the exchange_id. Note that clients are forbidden from mixing 4.1 and 4.2 compounds. (See rfc 5661, section 2.7, #13: "A client MUST NOT attempt to use a stateid, filehandle, or similar returned object from the COMPOUND procedure with minor version X for another COMPOUND procedure with minor version Y, where X != Y.") However, we do not currently attempt to enforce this except in the case of mixing zero minor version with non-zero minor versions. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 316ec843dec2..91ead0ed9f11 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1709,7 +1709,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, status = nfserr_jukebox; goto out; } - new->cl_minorversion = 1; + new->cl_minorversion = cstate->minorversion; gen_clid(new, nn); add_to_unconfirmed(new); -- GitLab From 0d422afb892e3f993cf934b76a2c2ef839c446e0 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 8 May 2013 18:05:41 -0400 Subject: [PATCH 0013/2900] security: cap_inode_getsecctx returning garbage We shouldn't be returning success from this function without also filling in the return values ctx and ctxlen. Note currently this doesn't appear to cause bugs since the only inode_getsecctx caller I can find is fs/sysfs/inode.c, which only calls this if security_inode_setsecurity succeeds. Assuming security_inode_setsecurity is set to cap_inode_setsecurity whenever inode_getsecctx is set to cap_inode_getsecctx, this function can never actually called. So I noticed this only because the server labeled NFS patches add a real caller. Acked-by: Serge E. Hallyn Signed-off-by: J. Bruce Fields --- security/capability.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/capability.c b/security/capability.c index 1728d4e375db..83efc90b344d 100644 --- a/security/capability.c +++ b/security/capability.c @@ -843,7 +843,7 @@ static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { - return 0; + return -EOPNOTSUPP; } #ifdef CONFIG_KEYS static int cap_key_alloc(struct key *key, const struct cred *cred, -- GitLab From 4bdc33ed5bd9fbaa243bda6fdccb22674aed6305 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Thu, 2 May 2013 13:18:57 -0400 Subject: [PATCH 0014/2900] NFSDv4.2: Add NFS v4.2 support to the NFS server This enables NFSv4.2 support for the server. To enable this code do the following: echo "+4.2" >/proc/fs/nfsd/versions after the nfsd kernel module is loaded. On its own this does nothing except allow the server to respond to compounds with minorversion set to 2. All the new NFSv4.2 features are optional, so this is perfectly legal. Signed-off-by: Steve Dickson Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 1 + fs/nfsd/nfsd.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 6cd86e0fe450..9aeacddafa3f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1567,6 +1567,7 @@ struct nfsd4_minorversion_ops { static struct nfsd4_minorversion_ops nfsd4_minorversion[] = { [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) }, [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, + [2] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, }; static __be32 diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index c0d93170585d..15e7e1d531f0 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -24,7 +24,7 @@ /* * nfsd version */ -#define NFSD_SUPPORTED_MINOR_VERSION 1 +#define NFSD_SUPPORTED_MINOR_VERSION 2 /* * Maximum blocksizes supported by daemon under various circumstances. */ -- GitLab From bd5f6a344daff10b58dfefad628e4b203edeb831 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 28 Apr 2013 14:05:22 +0300 Subject: [PATCH 0015/2900] iwlwifi: move BUILD_RAxTID to transport It has nothing to do in FW API. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/commands.h | 4 ---- drivers/net/wireless/iwlwifi/pcie/tx.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 95ca026ecc9d..19f3ce7646ab 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h @@ -838,10 +838,6 @@ struct iwl_qosparam_cmd { #define STA_MODIFY_DELBA_TID_MSK 0x10 #define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20 -/* Receiver address (actually, Rx station's index into station table), - * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ -#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) - /* agn */ struct iwl_keyinfo { __le16 key_flags; diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c5e30294c5ac..03ad2f417298 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1045,6 +1045,10 @@ static inline void iwl_pcie_txq_set_inactive(struct iwl_trans *trans, (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } +/* Receiver address (actually, Rx station's index into station table), + * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ +#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) + void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, int sta_id, int tid, int frame_limit, u16 ssn) { -- GitLab From 7df15b1e6f5994115bee369a527b50ec3521a39b Mon Sep 17 00:00:00 2001 From: Hila Gonen Date: Wed, 12 Dec 2012 11:16:19 +0200 Subject: [PATCH 0016/2900] iwlwifi: mvm: Add beacon filtering support Add iwl_beacon_filter_cmd struct, disable and enable beacon filtering as needed. Signed-off-by: Hila Gonen Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- .../net/wireless/iwlwifi/mvm/fw-api-power.h | 76 +++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api.h | 2 + drivers/net/wireless/iwlwifi/mvm/mac80211.c | 20 +++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 12 +++ drivers/net/wireless/iwlwifi/mvm/ops.c | 1 + drivers/net/wireless/iwlwifi/mvm/power.c | 67 ++++++++++++++++ 6 files changed, 178 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 81fe45f46be7..90fdfcda15b6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -117,4 +117,80 @@ struct iwl_powertable_cmd { __le32 lprx_rssi_threshold; } __packed; +/** + * struct iwl_beacon_filter_cmd + * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) + * @id_and_color: MAC contex identifier + * @bf_energy_delta: Used for RSSI filtering, if in 'normal' state. Send beacon + * to driver if delta in Energy values calculated for this and last + * passed beacon is greater than this threshold. Zero value means that + * the Energy change is ignored for beacon filtering, and beacon will + * not be forced to be sent to driver regardless of this delta. Typical + * energy delta 5dB. + * @bf_roaming_energy_delta: Used for RSSI filtering, if in 'roaming' state. + * Send beacon to driver if delta in Energy values calculated for this + * and last passed beacon is greater than this threshold. Zero value + * means that the Energy change is ignored for beacon filtering while in + * Roaming state, typical energy delta 1dB. + * @bf_roaming_state: Used for RSSI filtering. If absolute Energy values + * calculated for current beacon is less than the threshold, use + * Roaming Energy Delta Threshold, otherwise use normal Energy Delta + * Threshold. Typical energy threshold is -72dBm. + * @bf_temperature_delta: Send Beacon to driver if delta in temperature values + * calculated for this and the last passed beacon is greater than this + * threshold. Zero value means that the temperature changeis ignored for + * beacon filtering; beacons will not be forced to be sent to driver + * regardless of whether its temerature has been changed. + * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. + * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed + * for a specific period of time. Units: Beacons. + * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed + * for a longer period of time then this escape-timeout. Units: Beacons. + * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. + */ +struct iwl_beacon_filter_cmd { + u8 bf_energy_delta; + u8 bf_roaming_energy_delta; + u8 bf_roaming_state; + u8 bf_temperature_delta; + u8 bf_enable_beacon_filter; + u8 bf_debug_flag; + __le16 reserved1; + __le32 bf_escape_timer; + __le32 ba_escape_timer; + u8 ba_enable_beacon_abort; + u8 reserved2[3]; +} __packed; + +/* Beacon filtering and beacon abort */ +#define IWL_BF_ENERGY_DELTA_DEFAULT 5 +#define IWL_BF_ENERGY_DELTA_MAX 255 +#define IWL_BF_ENERGY_DELTA_MIN 0 + +#define IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT 1 +#define IWL_BF_ROAMING_ENERGY_DELTA_MAX 255 +#define IWL_BF_ROAMING_ENERGY_DELTA_MIN 0 + +#define IWL_BF_ROAMING_STATE_DEFAULT 72 +#define IWL_BF_ROAMING_STATE_MAX 255 +#define IWL_BF_ROAMING_STATE_MIN 0 + +#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5 +#define IWL_BF_TEMPERATURE_DELTA_MAX 255 +#define IWL_BF_TEMPERATURE_DELTA_MIN 0 + +#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 + +#define IWL_BF_DEBUG_FLAG_DEFAULT 0 + +#define IWL_BF_ESCAPE_TIMER_DEFAULT 50 +#define IWL_BF_ESCAPE_TIMER_MAX 1024 +#define IWL_BF_ESCAPE_TIMER_MIN 0 + +#define IWL_BA_ESCAPE_TIMER_DEFAULT 3 +#define IWL_BA_ESCAPE_TIMER_MAX 1024 +#define IWL_BA_ESCAPE_TIMER_MIN 0 + +#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 + #endif diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 191dcae8ba47..6031dbf83a96 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -170,6 +170,8 @@ enum { BT_COEX_PROT_ENV = 0xcd, BT_PROFILE_NOTIFICATION = 0xce, + REPLY_BEACON_FILTERING_CMD = 0xd2, + REPLY_DEBUG_CMD = 0xf0, DEBUG_LOG_MSG = 0xf7, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index dd158ec571fb..e2cf6d92217b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -530,6 +530,17 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, */ iwl_mvm_power_update_mode(mvm, vif); + /* beacon filtering */ + if (!mvm->bf_allowed_vif && + vif->type == NL80211_IFTYPE_STATION && !vif->p2p){ + mvm->bf_allowed_vif = mvmvif; + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + } + + ret = iwl_mvm_disable_beacon_filter(mvm, vif); + if (ret) + goto out_release; + /* * P2P_DEVICE interface does not have a channel context assigned to it, * so a dedicated PHY context is allocated to it and the corresponding @@ -646,6 +657,11 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); + if (mvm->bf_allowed_vif == mvmvif) { + mvm->bf_allowed_vif = NULL; + vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; + } + iwl_mvm_vif_dbgfs_clean(mvm, vif); /* @@ -984,9 +1000,13 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, mvmvif->phy_ctxt->channel->band); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { + /* enable beacon filtering */ + WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif)); ret = 0; } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { + /* disable beacon filtering */ + WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif)); ret = 0; } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) { diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 8269bc562951..4fc64d50dc50 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -266,6 +266,12 @@ struct iwl_mvm { unsigned long status; + /* + * for beacon filtering - + * currently only one interface can be supported + */ + struct iwl_mvm_vif *bf_allowed_vif; + enum iwl_ucode_type cur_ucode; bool ucode_loaded; bool init_ucode_run; @@ -533,4 +539,10 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, enum ieee80211_rssi_event rssi_event); void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +/* beacon filtering */ +int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); + #endif /* __IWL_MVM_H__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index fe031d304d1e..5bf1eaf9046a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -292,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { CMD(BT_COEX_PROT_ENV), CMD(BT_PROFILE_NOTIFICATION), CMD(BT_CONFIG), + CMD(REPLY_BEACON_FILTERING_CMD), }; #undef CMD diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index ed77e437aac4..30a5c27bd623 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -178,3 +178,70 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, sizeof(cmd), &cmd); } + +static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, + struct iwl_beacon_filter_cmd *cmd) +{ + int ret; + + ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC, + sizeof(struct iwl_beacon_filter_cmd), cmd); + + if (!ret) { + IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", + cmd->ba_enable_beacon_abort); + IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", + cmd->ba_escape_timer); + IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", + cmd->bf_debug_flag); + IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", + cmd->bf_enable_beacon_filter); + IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", + cmd->bf_energy_delta); + IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", + cmd->bf_escape_timer); + IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", + cmd->bf_roaming_energy_delta); + IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", + cmd->bf_roaming_state); + IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", + cmd->bf_temperature_delta); + } + return ret; +} + +int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_beacon_filter_cmd cmd = { + .bf_enable_beacon_filter = 1, + .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, + .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, + .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, + .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, + .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, + .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), + .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT), + .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT, + }; + + if (mvmvif != mvm->bf_allowed_vif || + vif->type != NL80211_IFTYPE_STATION || vif->p2p) + return 0; + + return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); +} + +int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + struct iwl_beacon_filter_cmd cmd = { + .bf_enable_beacon_filter = 0, + }; + + if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) + return 0; + + return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); +} -- GitLab From c571573a027bb65ac415141f919df3c0fa0fedb4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 30 Apr 2013 14:33:04 +0300 Subject: [PATCH 0017/2900] iwlwifi: pcie: prefer to load the firmware in one shot Users complained about allocation failures, so we loaded the firmware in small chunks (PAGE_SIZE). This makes the firmware restart considerably slower. So, always prefer to load it in one shot allocating a big chunk of coherent, and use smaller chunks as a fallback solution. On my laptop, this reduces the fw loading time from 120ms to 20ms. Signed-off-by: Emmanuel Grumbach Reviewed-by: Moshe Island Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/trans.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 50ba0a468f94..e5365196e5fe 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -405,20 +405,27 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, { u8 *v_addr; dma_addr_t p_addr; - u32 offset; + u32 offset, chunk_sz = section->len; int ret = 0; IWL_DEBUG_FW(trans, "[%d] uCode section being loaded...\n", section_num); - v_addr = dma_alloc_coherent(trans->dev, PAGE_SIZE, &p_addr, GFP_KERNEL); - if (!v_addr) - return -ENOMEM; + v_addr = dma_alloc_coherent(trans->dev, chunk_sz, &p_addr, + GFP_KERNEL | __GFP_NOWARN); + if (!v_addr) { + IWL_DEBUG_INFO(trans, "Falling back to small chunks of DMA\n"); + chunk_sz = PAGE_SIZE; + v_addr = dma_alloc_coherent(trans->dev, chunk_sz, + &p_addr, GFP_KERNEL); + if (!v_addr) + return -ENOMEM; + } - for (offset = 0; offset < section->len; offset += PAGE_SIZE) { + for (offset = 0; offset < section->len; offset += chunk_sz) { u32 copy_size; - copy_size = min_t(u32, PAGE_SIZE, section->len - offset); + copy_size = min_t(u32, chunk_sz, section->len - offset); memcpy(v_addr, (u8 *)section->data + offset, copy_size); ret = iwl_pcie_load_firmware_chunk(trans, @@ -432,7 +439,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num, } } - dma_free_coherent(trans->dev, PAGE_SIZE, v_addr, p_addr); + dma_free_coherent(trans->dev, chunk_sz, v_addr, p_addr); return ret; } -- GitLab From fe0f2de30cc3417794517afe45f57e851b3188ae Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 21 Mar 2013 10:23:52 +0200 Subject: [PATCH 0018/2900] iwlwifi: mvm: Loosen the channel context/phy context coupling In current implementation, the phy context is tightly coupled with the channel context. This complicates the possibility of using the same phy context for both netdev interfaces and the P2P Device interface. To loosen this coupling: 1. Manage all the phy contexts in the mvm op mode, and only save the phy context id in the chanctx memory. 2. Reference count the phy contexts and free them only when they are not longer used (both by mac80211 and P2P Device). Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 79 +++++++++++++++++---- drivers/net/wireless/iwlwifi/mvm/mvm.h | 9 ++- drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 73 +++++++++---------- 3 files changed, 105 insertions(+), 56 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e2cf6d92217b..c1ed5c36bf3a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -127,6 +127,17 @@ static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = { }; #endif +static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm) +{ + int i; + + memset(mvm->phy_ctxts, 0, sizeof(mvm->phy_ctxts)); + for (i = 0; i < NUM_PHY_CTX; i++) { + mvm->phy_ctxts[i].id = i; + mvm->phy_ctxts[i].ref = 0; + } +} + int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) { struct ieee80211_hw *hw = mvm->hw; @@ -158,7 +169,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->sta_data_size = sizeof(struct iwl_mvm_sta); hw->vif_data_size = sizeof(struct iwl_mvm_vif); - hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt); + hw->chanctx_data_size = sizeof(u16); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT) | @@ -193,6 +204,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->n_addresses++; } + iwl_mvm_reset_phy_ctxts(mvm); + /* we create the 802.11 header and a max-length SSID element */ hw->wiphy->max_scan_ie_len = mvm->fw->ucode_capa.max_probe_length - 24 - 34; @@ -345,8 +358,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); spin_unlock_bh(&mvm->time_event_lock); - if (vif->type != NL80211_IFTYPE_P2P_DEVICE) - mvmvif->phy_ctxt = NULL; + mvmvif->phy_ctxt = NULL; } static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) @@ -363,6 +375,9 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, iwl_mvm_cleanup_iterator, mvm); + mvm->p2p_device_vif = NULL; + + iwl_mvm_reset_phy_ctxts(mvm); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained)); @@ -456,6 +471,20 @@ static void iwl_mvm_power_update_iterator(void *data, u8 *mac, iwl_mvm_power_update_mode(mvm, vif); } +static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) +{ + u16 i; + + lockdep_assert_held(&mvm->mutex); + + for (i = 0; i < NUM_PHY_CTX; i++) + if (!mvm->phy_ctxts[i].ref) + return &mvm->phy_ctxts[i]; + + IWL_ERR(mvm, "No available PHY context\n"); + return NULL; +} + static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -550,7 +579,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_channel *chan; struct cfg80211_chan_def chandef; - mvmvif->phy_ctxt = &mvm->phy_ctxt_roc; + mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); + if (!mvmvif->phy_ctxt) { + ret = -ENOSPC; + goto out_remove_mac; + } /* * The channel used here isn't relevant as it's @@ -583,7 +616,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, out_unbind: iwl_mvm_binding_remove_vif(mvm, vif); out_remove_phy: - iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt); + iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); out_remove_mac: mvmvif->phy_ctxt = NULL; iwl_mvm_mac_ctxt_remove(mvm, vif); @@ -677,7 +710,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->p2p_device_vif = NULL; iwl_mvm_rm_bcast_sta(mvm, &mvmvif->bcast_sta); iwl_mvm_binding_remove_vif(mvm, vif); - iwl_mvm_phy_ctxt_remove(mvm, mvmvif->phy_ctxt); + iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); mvmvif->phy_ctxt = NULL; } @@ -1172,6 +1205,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, enum ieee80211_roc_type type) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct cfg80211_chan_def chandef; int ret; @@ -1186,7 +1220,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, mutex_lock(&mvm->mutex); cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); - ret = iwl_mvm_phy_ctxt_changed(mvm, &mvm->phy_ctxt_roc, + ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, &chandef, 1, 1); /* Schedule the time events */ @@ -1216,15 +1250,29 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; + u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; + struct iwl_mvm_phy_ctxt *phy_ctxt; int ret; + IWL_DEBUG_MAC80211(mvm, "Add PHY context\n"); + mutex_lock(&mvm->mutex); + phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); + if (!phy_ctxt) { + ret = -ENOSPC; + goto out; + } - IWL_DEBUG_MAC80211(mvm, "Add PHY context\n"); ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def, ctx->rx_chains_static, ctx->rx_chains_dynamic); + if (ret) { + IWL_ERR(mvm, "Failed to add PHY context\n"); + goto out; + } + + *phy_ctxt_id = phy_ctxt->id; +out: mutex_unlock(&mvm->mutex); return ret; } @@ -1233,10 +1281,11 @@ static void iwl_mvm_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; + u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; + struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; mutex_lock(&mvm->mutex); - iwl_mvm_phy_ctxt_remove(mvm, phy_ctxt); + iwl_mvm_phy_ctxt_unref(mvm, phy_ctxt); mutex_unlock(&mvm->mutex); } @@ -1245,7 +1294,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, u32 changed) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; + u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; + struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; mutex_lock(&mvm->mutex); iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, @@ -1259,13 +1309,14 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_phy_ctxt *phyctx = (void *)ctx->drv_priv; + u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; + struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int ret; mutex_lock(&mvm->mutex); - mvmvif->phy_ctxt = phyctx; + mvmvif->phy_ctxt = phy_ctxt; switch (vif->type) { case NL80211_IFTYPE_AP: diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4fc64d50dc50..3505fcafde66 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -109,6 +109,7 @@ extern struct iwl_mvm_mod_params iwlmvm_mod_params; struct iwl_mvm_phy_ctxt { u16 id; u16 color; + u32 ref; /* * TODO: This should probably be removed. Currently here only for rate @@ -318,7 +319,7 @@ struct iwl_mvm { bool prevent_power_down_d3; #endif - struct iwl_mvm_phy_ctxt phy_ctxt_roc; + struct iwl_mvm_phy_ctxt phy_ctxts[NUM_PHY_CTX]; struct list_head time_event_list; spinlock_t time_event_lock; @@ -448,8 +449,10 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, struct cfg80211_chan_def *chandef, u8 chains_static, u8 chains_dynamic); -void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, - struct iwl_mvm_phy_ctxt *ctxt); +void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt); +void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt); /* MAC (virtual interface) programming */ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index a28a1d1f23eb..f80e721eb5d0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c @@ -195,21 +195,6 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, return ret; } - -struct phy_ctx_used_data { - unsigned long used[BITS_TO_LONGS(NUM_PHY_CTX)]; -}; - -static void iwl_mvm_phy_ctx_used_iter(struct ieee80211_hw *hw, - struct ieee80211_chanctx_conf *ctx, - void *_data) -{ - struct phy_ctx_used_data *data = _data; - struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv; - - __set_bit(phy_ctxt->id, data->used); -} - /* * Send a command to add a PHY context based on the current HW configuration. */ @@ -217,34 +202,31 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, struct cfg80211_chan_def *chandef, u8 chains_static, u8 chains_dynamic) { - struct phy_ctx_used_data data = { - .used = { }, - }; - - /* - * If this is a regular PHY context (not the ROC one) - * skip the ROC PHY context's ID. - */ - if (ctxt != &mvm->phy_ctxt_roc) - __set_bit(mvm->phy_ctxt_roc.id, data.used); + int ret; + WARN_ON(ctxt->ref); lockdep_assert_held(&mvm->mutex); - ctxt->color++; - if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { - ieee80211_iter_chan_contexts_atomic( - mvm->hw, iwl_mvm_phy_ctx_used_iter, &data); + ctxt->channel = chandef->chan; + ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, + chains_static, chains_dynamic, + FW_CTXT_ACTION_ADD, 0); - ctxt->id = find_first_zero_bit(data.used, NUM_PHY_CTX); - if (WARN_ONCE(ctxt->id == NUM_PHY_CTX, - "Failed to init PHY context - no free ID!\n")) - return -EIO; - } + if (!ret) + ctxt->ref = 1; + return ret; +} - ctxt->channel = chandef->chan; - return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, - chains_static, chains_dynamic, - FW_CTXT_ACTION_ADD, 0); +/* + * Update the number of references to the given PHY context. This is valid only + * in case the PHY context was already created, i.e., its reference count > 0. + */ +void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) +{ + WARN_ON(!ctxt->ref); + lockdep_assert_held(&mvm->mutex); + + ctxt->ref++; } /* @@ -269,7 +251,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, * Once the command is sent, regardless of success or failure, the context is * marked as invalid */ -void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) +static void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, + struct iwl_mvm_phy_ctxt *ctxt) { struct iwl_phy_context_cmd cmd; int ret; @@ -280,7 +263,19 @@ void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC, sizeof(struct iwl_phy_context_cmd), &cmd); + ctxt->channel = NULL; if (ret) IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n", ctxt->id); } + +void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) +{ + lockdep_assert_held(&mvm->mutex); + + ctxt->ref--; + if (ctxt->ref != 0) + return; + + return iwl_mvm_phy_ctxt_remove(mvm, ctxt); +} -- GitLab From 53a9d61eb74e574aec2db86f63d9809b6116d164 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Sun, 28 Apr 2013 11:55:08 +0300 Subject: [PATCH 0019/2900] iwlwifi: mvm: Change PHY context handling 1. All the phy contexts are added immediately after the firmware is loaded and up. 2. Whenever a PHY context needs to be used, its reference counter is incremented and the PHY context is being configured to the appropriate configuration. 3. When a PHY context is no longer needed, its reference count is decremented. 4. PHY contexts are never removed. Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw.c | 18 +++++++++++- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 28 ++++++------------ drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 32 --------------------- 3 files changed, 25 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index e18c92dd60ec..a4071cf09a24 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -388,6 +388,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) int iwl_mvm_up(struct iwl_mvm *mvm) { int ret, i; + struct ieee80211_channel *chan; + struct cfg80211_chan_def chandef; lockdep_assert_held(&mvm->mutex); @@ -443,8 +445,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (ret) goto error; - IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); + /* Add all the PHY contexts */ + chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; + cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); + for (i = 0; i < NUM_PHY_CTX; i++) { + /* + * The channel used here isn't relevant as it's + * going to be overwritten in the other flows. + * For now use the first channel we have. + */ + ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i], + &chandef, 1, 1); + if (ret) + goto error; + } + IWL_DEBUG_INFO(mvm, "RT uCode started.\n"); return 0; error: iwl_trans_stop_device(mvm->trans); diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c1ed5c36bf3a..d9eabdc6e493 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -576,8 +576,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, * MAC context is bound to it at this stage. */ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { - struct ieee80211_channel *chan; - struct cfg80211_chan_def chandef; mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); if (!mvmvif->phy_ctxt) { @@ -585,21 +583,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, goto out_remove_mac; } - /* - * The channel used here isn't relevant as it's - * going to be overwritten as part of the ROC flow. - * For now use the first channel we have. - */ - chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; - cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); - ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt, - &chandef, 1, 1); - if (ret) - goto out_remove_mac; - + iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); ret = iwl_mvm_binding_add_vif(mvm, vif); if (ret) - goto out_remove_phy; + goto out_unref_phy; ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta); if (ret) @@ -615,7 +602,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, out_unbind: iwl_mvm_binding_remove_vif(mvm, vif); - out_remove_phy: + out_unref_phy: iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); out_remove_mac: mvmvif->phy_ctxt = NULL; @@ -1254,7 +1241,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, struct iwl_mvm_phy_ctxt *phy_ctxt; int ret; - IWL_DEBUG_MAC80211(mvm, "Add PHY context\n"); + IWL_DEBUG_MAC80211(mvm, "Add channel context\n"); mutex_lock(&mvm->mutex); phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); @@ -1263,14 +1250,15 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, goto out; } - ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def, - ctx->rx_chains_static, - ctx->rx_chains_dynamic); + ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, + ctx->rx_chains_static, + ctx->rx_chains_dynamic); if (ret) { IWL_ERR(mvm, "Failed to add PHY context\n"); goto out; } + iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt); *phy_ctxt_id = phy_ctxt->id; out: mutex_unlock(&mvm->mutex); diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index f80e721eb5d0..0ea61aaf7754 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c @@ -212,8 +212,6 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, chains_static, chains_dynamic, FW_CTXT_ACTION_ADD, 0); - if (!ret) - ctxt->ref = 1; return ret; } @@ -223,9 +221,7 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, */ void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) { - WARN_ON(!ctxt->ref); lockdep_assert_held(&mvm->mutex); - ctxt->ref++; } @@ -246,36 +242,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, FW_CTXT_ACTION_MODIFY, 0); } -/* - * Send a command to the FW to remove the given phy context. - * Once the command is sent, regardless of success or failure, the context is - * marked as invalid - */ -static void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, - struct iwl_mvm_phy_ctxt *ctxt) -{ - struct iwl_phy_context_cmd cmd; - int ret; - - lockdep_assert_held(&mvm->mutex); - - iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, FW_CTXT_ACTION_REMOVE, 0); - ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC, - sizeof(struct iwl_phy_context_cmd), - &cmd); - ctxt->channel = NULL; - if (ret) - IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n", - ctxt->id); -} - void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) { lockdep_assert_held(&mvm->mutex); - ctxt->ref--; - if (ctxt->ref != 0) - return; - - return iwl_mvm_phy_ctxt_remove(mvm, ctxt); } -- GitLab From b415210b3a36c414dec646104adf84d3b78d9f99 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 1 May 2013 09:42:06 +0300 Subject: [PATCH 0020/2900] iwlwifi: enable shadow registers for 7000 This will reduce CPU utilization. Instead of waking up the NIC for each Tx manually, the CPU can write to a register that will wake up the NIC automatically. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-7000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 50263e87fe15..26969f5f504a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -102,7 +102,7 @@ static const struct iwl_base_params iwl7000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ + .shadow_reg_enable = true, }; static const struct iwl_ht_params iwl7000_ht_params = { -- GitLab From ce7f9ab381ea1cc4514f462d18a15785de050323 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 11:30:23 +0200 Subject: [PATCH 0021/2900] iwlwifi: mvm: don't assume data section is at 0x800000 In theory, the firmware format allows changing the data section offset. This may not be used today, but there's no reason for the driver to assume the data section is always at 0x800000 as it can know better. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 2053dccefcd6..a12c98be8616 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -147,10 +147,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, /* default is to dump the entire data segment */ if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { - mvm->dbgfs_sram_offset = 0x800000; if (!mvm->ucode_loaded) return -EINVAL; img = &mvm->fw->img[mvm->cur_ucode]; + mvm->dbgfs_sram_offset = + img->sec[IWL_UCODE_SECTION_DATA].offset; mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; } len = mvm->dbgfs_sram_len; -- GitLab From b656fa337141136317589cff9f25832a00bc651c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 11:56:17 +0200 Subject: [PATCH 0022/2900] iwlwifi: pcie: dump stack on NIC error in sync commands Many times, a NIC error is the result of a bad command sent to the device. If the command was sent synchronously, then we'll currently print a message when the command is aborted containing the command. It can be very useful to also see the stack dump though, so also print that. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 03ad2f417298..595df1756b84 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1522,6 +1522,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) { IWL_ERR(trans, "FW error in SYNC CMD %s\n", get_cmd_string(trans_pcie, cmd->id)); + dump_stack(); ret = -EIO; goto cancel; } -- GitLab From bfc824b05bdc4ea0b7702263f91dc3fed7b630eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 6 May 2013 16:06:51 +0200 Subject: [PATCH 0023/2900] iwlwifi: nvm: honour VHT enable flag Some devices don't support VHT (802.11ac) and this is encoded in the data stored in the NVM. Read the flag and use it to set up the VHT capabilities accordingly. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 6199a0a597a6..8f2a4e922346 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -89,6 +89,7 @@ enum nvm_sku_bits { NVM_SKU_CAP_BAND_24GHZ = BIT(0), NVM_SKU_CAP_BAND_52GHZ = BIT(1), NVM_SKU_CAP_11N_ENABLE = BIT(2), + NVM_SKU_CAP_11AC_ENABLE = BIT(3), }; /* radio config bits (actual values from NVM definition) */ @@ -258,8 +259,6 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, struct ieee80211_sta_vht_cap *vht_cap) { - /* For now, assume new devices with NVM are VHT capable */ - vht_cap->vht_supported = true; vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 | @@ -292,7 +291,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, } static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, - struct iwl_nvm_data *data, const __le16 *nvm_sw) + struct iwl_nvm_data *data, const __le16 *nvm_sw, + bool enable_vht) { int n_channels = iwl_init_channel_map(dev, cfg, data, &nvm_sw[NVM_CHANNELS]); @@ -314,7 +314,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_5GHZ); iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); - iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); + if (enable_vht) + iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); if (n_channels != n_used) IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", @@ -380,7 +381,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, data->hw_addr[4] = hw_addr[5]; data->hw_addr[5] = hw_addr[4]; - iwl_init_sbands(dev, cfg, data, nvm_sw); + iwl_init_sbands(dev, cfg, data, nvm_sw, + sku & NVM_SKU_CAP_11AC_ENABLE); data->calib_version = 255; /* TODO: this value will prevent some checks from -- GitLab From 31d385aeea7e26e70409cd6f126c516047bc9f96 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Tue, 2 Apr 2013 10:25:46 +0300 Subject: [PATCH 0024/2900] iwlwifi: mvm: Allow P2P Device to use an existing PHY context The patch is an optimization, that eliminates unnecessary binding context switching and allows the P2P Device MAC to use the same channel as an existing netdev interface. For each ROC call, check if there is already a channel/phy context that can be used for the P2P Device. If such channel is found, unbind the P2P Device from its current phy context, and bind it to the already used channel/phy context. In case that the phy context is shared, and there is a need to change it, create a new phy context, unbind and create a new binding. Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 99 +++++++++++++++++++-- 1 file changed, 92 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index d9eabdc6e493..fe22772f3421 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1194,28 +1194,105 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct cfg80211_chan_def chandef; - int ret; + struct iwl_mvm_phy_ctxt *phy_ctxt; + int ret, i; + + IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, + duration, type); if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); return -EINVAL; } - IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, - duration, type); - mutex_lock(&mvm->mutex); + for (i = 0; i < NUM_PHY_CTX; i++) { + phy_ctxt = &mvm->phy_ctxts[i]; + if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt) + continue; + + if (phy_ctxt->ref && channel == phy_ctxt->channel) { + /* + * Unbind the P2P_DEVICE from the current PHY context, + * and if the PHY context is not used remove it. + */ + ret = iwl_mvm_binding_remove_vif(mvm, vif); + if (WARN(ret, "Failed unbinding P2P_DEVICE\n")) + goto out_unlock; + + iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); + + /* Bind the P2P_DEVICE to the current PHY Context */ + mvmvif->phy_ctxt = phy_ctxt; + + ret = iwl_mvm_binding_add_vif(mvm, vif); + if (WARN(ret, "Failed binding P2P_DEVICE\n")) + goto out_unlock; + + iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); + goto schedule_time_event; + } + } + + /* Need to update the PHY context only if the ROC channel changed */ + if (channel == mvmvif->phy_ctxt->channel) + goto schedule_time_event; + cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); - ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, - &chandef, 1, 1); + /* + * Change the PHY context configuration as it is currently referenced + * only by the P2P Device MAC + */ + if (mvmvif->phy_ctxt->ref == 1) { + ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, + &chandef, 1, 1); + if (ret) + goto out_unlock; + } else { + /* + * The PHY context is shared with other MACs. Need to remove the + * P2P Device from the binding, allocate an new PHY context and + * create a new binding + */ + phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); + if (!phy_ctxt) { + ret = -ENOSPC; + goto out_unlock; + } + + ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef, + 1, 1); + if (ret) { + IWL_ERR(mvm, "Failed to change PHY context\n"); + goto out_unlock; + } + + /* Unbind the P2P_DEVICE from the current PHY context */ + ret = iwl_mvm_binding_remove_vif(mvm, vif); + if (WARN(ret, "Failed unbinding P2P_DEVICE\n")) + goto out_unlock; + + iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); + + /* Bind the P2P_DEVICE to the new allocated PHY context */ + mvmvif->phy_ctxt = phy_ctxt; + + ret = iwl_mvm_binding_add_vif(mvm, vif); + if (WARN(ret, "Failed binding P2P_DEVICE\n")) + goto out_unlock; + + iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); + } + +schedule_time_event: /* Schedule the time events */ ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); +out_unlock: mutex_unlock(&mvm->mutex); IWL_DEBUG_MAC80211(mvm, "leave\n"); - return ret; } @@ -1285,6 +1362,14 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; + if (WARN_ONCE((phy_ctxt->ref > 1) && + (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | + IEEE80211_CHANCTX_CHANGE_RX_CHAINS | + IEEE80211_CHANCTX_CHANGE_RADAR)), + "Cannot change PHY. Ref=%d, changed=0x%X\n", + phy_ctxt->ref, changed)) + return; + mutex_lock(&mvm->mutex); iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, ctx->rx_chains_static, -- GitLab From 93fc64114b994f9ef6901697f9b0de00762680e9 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Tue, 23 Apr 2013 18:19:11 +0300 Subject: [PATCH 0025/2900] iwlwifi: add new 7260 and 3160 series device IDs Add new device IDs and configurations to support all the devices. Signed-off-by: Oren Givon Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-7000.c | 42 +++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-config.h | 6 ++- drivers/net/wireless/iwlwifi/pcie/drv.c | 50 +++++++++++++++++++++-- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 26969f5f504a..c9aae2a2bbbb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -125,7 +125,7 @@ static const struct iwl_ht_params iwl7000_ht_params = { const struct iwl_cfg iwl7260_2ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC7260", + .name = "Intel(R) Dual Band Wireless AC 7260", .fw_name_pre = IWL7260_FW_PRE, IWL_DEVICE_7000, .ht_params = &iwl7000_ht_params, @@ -133,8 +133,44 @@ const struct iwl_cfg iwl7260_2ac_cfg = { .nvm_calib_ver = IWL7260_TX_POWER_VERSION, }; -const struct iwl_cfg iwl3160_ac_cfg = { - .name = "Intel(R) Dual Band Wireless AC3160", +const struct iwl_cfg iwl7260_2n_cfg = { + .name = "Intel(R) Dual Band Wireless N 7260", + .fw_name_pre = IWL7260_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7260_NVM_VERSION, + .nvm_calib_ver = IWL7260_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl7260_n_cfg = { + .name = "Intel(R) Wireless N 7260", + .fw_name_pre = IWL7260_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL7260_NVM_VERSION, + .nvm_calib_ver = IWL7260_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_2ac_cfg = { + .name = "Intel(R) Dual Band Wireless AC 3160", + .fw_name_pre = IWL3160_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL3160_NVM_VERSION, + .nvm_calib_ver = IWL3160_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_2n_cfg = { + .name = "Intel(R) Dual Band Wireless N 3160", + .fw_name_pre = IWL3160_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL3160_NVM_VERSION, + .nvm_calib_ver = IWL3160_TX_POWER_VERSION, +}; + +const struct iwl_cfg iwl3160_n_cfg = { + .name = "Intel(R) Wireless N 3160", .fw_name_pre = IWL3160_FW_PRE, IWL_DEVICE_7000, .ht_params = &iwl7000_ht_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index c38aa8f77554..c3c9268affab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -320,6 +320,10 @@ extern const struct iwl_cfg iwl105_bgn_cfg; extern const struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl135_bgn_cfg; extern const struct iwl_cfg iwl7260_2ac_cfg; -extern const struct iwl_cfg iwl3160_ac_cfg; +extern const struct iwl_cfg iwl7260_2n_cfg; +extern const struct iwl_cfg iwl7260_n_cfg; +extern const struct iwl_cfg iwl3160_2ac_cfg; +extern const struct iwl_cfg iwl3160_2n_cfg; +extern const struct iwl_cfg iwl3160_n_cfg; #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index 8cb53ec2b77b..db7bdd35a9c5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -256,10 +256,54 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { /* 7000 Series */ {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_ac_cfg)}, - {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)}, + +/* 3160 Series */ + {IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, {0} }; -- GitLab From afc66bb734d44ea64cc78ae8d8034886e8cfb2c7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 11:44:16 +0200 Subject: [PATCH 0026/2900] iwlwifi: mvm: optionally store D3 SRAM after resume The D3 image SRAM is overwritten by the runtime image, so it can't be accessed after resume. However, it can be very useful to look at it to know what happened during D3, so add the ability to store the image and make it available in debugfs. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/d3.c | 23 +++++++ drivers/net/wireless/iwlwifi/mvm/debugfs.c | 70 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 ++ drivers/net/wireless/iwlwifi/mvm/ops.c | 4 ++ 4 files changed, 101 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 16bbdcc8627a..63d788aef3f4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1214,6 +1214,26 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, iwl_free_resp(&cmd); } +static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) +{ +#ifdef CONFIG_IWLWIFI_DEBUGFS + const struct fw_img *img = &mvm->fw->img[IWL_UCODE_WOWLAN]; + u32 len = img->sec[IWL_UCODE_SECTION_DATA].len; + u32 offs = img->sec[IWL_UCODE_SECTION_DATA].offset; + + if (!mvm->store_d3_resume_sram) + return; + + if (!mvm->d3_resume_sram) { + mvm->d3_resume_sram = kzalloc(len, GFP_KERNEL); + if (!mvm->d3_resume_sram) + return; + } + + iwl_trans_read_mem_bytes(mvm->trans, offs, mvm->d3_resume_sram, len); +#endif +} + int iwl_mvm_resume(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); @@ -1245,6 +1265,9 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) goto out_unlock; } + /* query SRAM first in case we want event logging */ + iwl_mvm_read_d3_sram(mvm); + iwl_mvm_query_wakeup_reasons(mvm, vif); out_unlock: diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index a12c98be8616..0765827d87a6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -482,6 +482,70 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, return count; } +#ifdef CONFIG_PM_SLEEP +static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + char buf[8] = {}; + int store; + + if (copy_from_user(buf, user_buf, sizeof(buf))) + return -EFAULT; + + if (sscanf(buf, "%d", &store) != 1) + return -EINVAL; + + mvm->store_d3_resume_sram = store; + + return count; +} + +static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + const struct fw_img *img; + int ofs, len, pos = 0; + size_t bufsz, ret; + char *buf; + u8 *ptr = mvm->d3_resume_sram; + + img = &mvm->fw->img[IWL_UCODE_WOWLAN]; + len = img->sec[IWL_UCODE_SECTION_DATA].len; + + bufsz = len * 4 + 256; + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + pos += scnprintf(buf, bufsz, "D3 SRAM capture: %sabled\n", + mvm->store_d3_resume_sram ? "en" : "dis"); + + if (ptr) { + for (ofs = 0; ofs < len; ofs += 16) { + pos += scnprintf(buf + pos, bufsz - pos, + "0x%.4x ", ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos, + bufsz - pos, false); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "(no data captured)\n"); + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + + kfree(buf); + + return ret; +} +#endif + #define MVM_DEBUGFS_READ_FILE_OPS(name) \ static const struct file_operations iwl_dbgfs_##name##_ops = { \ .read = iwl_dbgfs_##name##_read, \ @@ -525,6 +589,9 @@ MVM_DEBUGFS_READ_FILE_OPS(bt_notif); MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); +#ifdef CONFIG_PM_SLEEP +MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); +#endif /* Interface specific debugfs entries */ MVM_DEBUGFS_READ_FILE_OPS(mac_params); @@ -543,6 +610,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); +#ifdef CONFIG_PM_SLEEP + MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); +#endif /* * Create a symlink with mac80211. It will be removed when mac80211 diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 3505fcafde66..712c39ae748f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -344,6 +344,10 @@ struct iwl_mvm { #ifdef CONFIG_PM_SLEEP int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; +#ifdef CONFIG_IWLWIFI_DEBUGFS + bool store_d3_resume_sram; + void *d3_resume_sram; +#endif #endif /* BT-Coex */ diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 5bf1eaf9046a..bb79a8dcf6bb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -443,6 +443,10 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) kfree(mvm->scan_cmd); +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) + kfree(mvm->d3_resume_sram); +#endif + iwl_trans_stop_hw(mvm->trans, true); iwl_phy_db_free(mvm->phy_db); -- GitLab From e28210115b0ff3544b39ee67d8e48dc74b25b6b8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 May 2013 15:55:31 +0200 Subject: [PATCH 0027/2900] iwlwifi: mvm: sanity check context in iwl_mvm_phy_ctxt_unref() In some botched (!) restart scenarios we seem to get here with a NULL PHY context, so warn and exit instead of crashing. Reported-by: Omer Kremer Reviewed-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 0ea61aaf7754..1b4db25d53fb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c @@ -245,5 +245,9 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) { lockdep_assert_held(&mvm->mutex); + + if (WARN_ON_ONCE(!ctxt)) + return; + ctxt->ref--; } -- GitLab From 2423c9c3f0ffffa8f87cbdafe9781273c5d1b6a2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:30 -0700 Subject: [PATCH 0028/2900] blkcg: fix error return path in blkg_create() In blkg_create(), after lookup of parent fails, the control jumps to error path with the error code encoded into @blkg. The error path doesn't use @blkg for the return value. It returns ERR_PTR(ret). Make lookup fail path set @ret instead of @blkg. Note that the parent lookup is guaranteed to succeed at that point and the condition check is purely for sanity and triggers WARN when fails. As such, I don't think it's necessary to mark it for -stable. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index e8918ffaf96d..7fc35f683c4e 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -238,7 +238,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, if (blkcg_parent(blkcg)) { blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false); if (WARN_ON_ONCE(!blkg->parent)) { - blkg = ERR_PTR(-EINVAL); + ret = -EINVAL; goto err_put_css; } blkg_get(blkg->parent); -- GitLab From dd4a4ffc0a4723cd0bef065af549803d256e1f7e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:30 -0700 Subject: [PATCH 0029/2900] blkcg: move blkg_for_each_descendant_pre() to block/blk-cgroup.h blk-throttle hierarchy support will make use of it. Move blkg_for_each_descendant_pre() from block/blk-cgroup.c to block/blk-cgroup.h. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-cgroup.c | 24 ++---------------------- block/blk-cgroup.h | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 7fc35f683c4e..b950306838ad 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -32,26 +32,6 @@ EXPORT_SYMBOL_GPL(blkcg_root); static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS]; -static struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, - struct request_queue *q, bool update_hint); - -/** - * blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants - * @d_blkg: loop cursor pointing to the current descendant - * @pos_cgrp: used for iteration - * @p_blkg: target blkg to walk descendants of - * - * Walk @c_blkg through the descendants of @p_blkg. Must be used with RCU - * read locked. If called under either blkcg or queue lock, the iteration - * is guaranteed to include all and only online blkgs. The caller may - * update @pos_cgrp by calling cgroup_rightmost_descendant() to skip - * subtree. - */ -#define blkg_for_each_descendant_pre(d_blkg, pos_cgrp, p_blkg) \ - cgroup_for_each_descendant_pre((pos_cgrp), (p_blkg)->blkcg->css.cgroup) \ - if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ - (p_blkg)->q, false))) - static bool blkcg_policy_enabled(struct request_queue *q, const struct blkcg_policy *pol) { @@ -158,8 +138,8 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, * @q's bypass state. If @update_hint is %true, the caller should be * holding @q->queue_lock and lookup hint is updated on success. */ -static struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, - struct request_queue *q, bool update_hint) +struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q, + bool update_hint) { struct blkcg_gq *blkg; diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 4e595ee8c915..11f5b92d9a47 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -282,6 +282,26 @@ static inline void blkg_put(struct blkcg_gq *blkg) __blkg_release(blkg); } +struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q, + bool update_hint); + +/** + * blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants + * @d_blkg: loop cursor pointing to the current descendant + * @pos_cgrp: used for iteration + * @p_blkg: target blkg to walk descendants of + * + * Walk @c_blkg through the descendants of @p_blkg. Must be used with RCU + * read locked. If called under either blkcg or queue lock, the iteration + * is guaranteed to include all and only online blkgs. The caller may + * update @pos_cgrp by calling cgroup_rightmost_descendant() to skip + * subtree. + */ +#define blkg_for_each_descendant_pre(d_blkg, pos_cgrp, p_blkg) \ + cgroup_for_each_descendant_pre((pos_cgrp), (p_blkg)->blkcg->css.cgroup) \ + if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ + (p_blkg)->q, false))) + /** * blk_get_rl - get request_list to use * @q: request_queue of interest -- GitLab From aa539cb38f4f1365ad52fed6a857b25f8b4dc06c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0030/2900] blkcg: implement blkg_for_each_descendant_post() This will be used by blk-throttle hierarchy support. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-cgroup.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 11f5b92d9a47..e15f731d2cdd 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -302,6 +302,20 @@ struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q, if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ (p_blkg)->q, false))) +/** + * blkg_for_each_descendant_post - post-order walk of a blkg's descendants + * @d_blkg: loop cursor pointing to the current descendant + * @pos_cgrp: used for iteration + * @p_blkg: target blkg to walk descendants of + * + * Similar to blkg_for_each_descendant_pre() but performs post-order + * traversal instead. Synchronization rules are the same. + */ +#define blkg_for_each_descendant_post(d_blkg, pos_cgrp, p_blkg) \ + cgroup_for_each_descendant_post((pos_cgrp), (p_blkg)->blkcg->css.cgroup) \ + if (((d_blkg) = __blkg_lookup(cgroup_to_blkcg(pos_cgrp), \ + (p_blkg)->q, false))) + /** * blk_get_rl - get request_list to use * @q: request_queue of interest -- GitLab From db61367038dcd222476881cb09fd54661b3cd508 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0031/2900] blkcg: invoke blkcg_policy->pd_init() after parent is linked Currently, when creating a new blkcg_gq, each policy's pd_init_fn() is invoked in blkg_alloc() before the parent is linked. This makes it difficult for policies to perform initializations which are dependent on the parent. This patch moves pd_init_fn() invocations to blkg_create() after the parent blkg is linked where the new blkg is fully initialized. As this means that blkg_free() can't assume that pd's are initialized, pd_exit_fn() invocations are moved to __blkg_release(). This guarantees that pd_exit_fn() is also invoked with fully initialized blkgs with valid parent pointers. This will help implementing hierarchy support in blk-throttle. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-cgroup.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index b950306838ad..6bbe0a939596 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -51,18 +51,8 @@ static void blkg_free(struct blkcg_gq *blkg) if (!blkg) return; - for (i = 0; i < BLKCG_MAX_POLS; i++) { - struct blkcg_policy *pol = blkcg_policy[i]; - struct blkg_policy_data *pd = blkg->pd[i]; - - if (!pd) - continue; - - if (pol && pol->pd_exit_fn) - pol->pd_exit_fn(blkg); - - kfree(pd); - } + for (i = 0; i < BLKCG_MAX_POLS; i++) + kfree(blkg->pd[i]); blk_exit_rl(&blkg->rl); kfree(blkg); @@ -114,10 +104,6 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, blkg->pd[i] = pd; pd->blkg = blkg; pd->plid = i; - - /* invoke per-policy init */ - if (pol->pd_init_fn) - pol->pd_init_fn(blkg); } return blkg; @@ -214,7 +200,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, } blkg = new_blkg; - /* link parent and insert */ + /* link parent */ if (blkcg_parent(blkcg)) { blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false); if (WARN_ON_ONCE(!blkg->parent)) { @@ -224,6 +210,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, blkg_get(blkg->parent); } + /* invoke per-policy init */ + for (i = 0; i < BLKCG_MAX_POLS; i++) { + struct blkcg_policy *pol = blkcg_policy[i]; + + if (blkg->pd[i] && pol->pd_init_fn) + pol->pd_init_fn(blkg); + } + + /* insert */ spin_lock(&blkcg->lock); ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg); if (likely(!ret)) { @@ -381,6 +376,16 @@ static void blkg_rcu_free(struct rcu_head *rcu_head) void __blkg_release(struct blkcg_gq *blkg) { + int i; + + /* tell policies that this one is being freed */ + for (i = 0; i < BLKCG_MAX_POLS; i++) { + struct blkcg_policy *pol = blkcg_policy[i]; + + if (blkg->pd[i] && pol->pd_exit_fn) + pol->pd_exit_fn(blkg); + } + /* release the blkcg and parent blkg refs this blkg has been holding */ css_put(&blkg->blkcg->css); if (blkg->parent) -- GitLab From 2a4fd070ee8561d918a3776388331bb7e92ea59e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0032/2900] blkcg: move bulk of blkcg_gq release operations to the RCU callback Currently, when the last reference of a blkcg_gq is put, all then release operations sans the actual freeing happen directly in blkg_put(). As blkg_put() may be called under queue_lock, all pd_exit_fn()s may be too. This makes it impossible for pd_exit_fn()s to use del_timer_sync() on timers which grab the queue_lock which is an irq-safe lock due to the deadlock possibility described in the comment on top of del_timer_sync(). This can be easily avoided by perfoming the release operations in the RCU callback instead of directly from blkg_put(). This patch moves the blkcg_gq release operations to the RCU callback. As this leaves __blkg_release() with only call_rcu() invocation, blkg_rcu_free() is renamed to __blkg_release_rcu(), exported and call_rcu() invocation is now done directly from blkg_put() instead of going through __blkg_release() which is removed. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-cgroup.c | 34 ++++++++++++++++------------------ block/blk-cgroup.h | 4 ++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 6bbe0a939596..d0747605f56c 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -369,13 +369,17 @@ static void blkg_destroy_all(struct request_queue *q) q->root_rl.blkg = NULL; } -static void blkg_rcu_free(struct rcu_head *rcu_head) -{ - blkg_free(container_of(rcu_head, struct blkcg_gq, rcu_head)); -} - -void __blkg_release(struct blkcg_gq *blkg) +/* + * A group is RCU protected, but having an rcu lock does not mean that one + * can access all the fields of blkg and assume these are valid. For + * example, don't try to follow throtl_data and request queue links. + * + * Having a reference to blkg under an rcu allows accesses to only values + * local to groups like group stats and group rate limits. + */ +void __blkg_release_rcu(struct rcu_head *rcu_head) { + struct blkcg_gq *blkg = container_of(rcu_head, struct blkcg_gq, rcu_head); int i; /* tell policies that this one is being freed */ @@ -388,21 +392,15 @@ void __blkg_release(struct blkcg_gq *blkg) /* release the blkcg and parent blkg refs this blkg has been holding */ css_put(&blkg->blkcg->css); - if (blkg->parent) + if (blkg->parent) { + spin_lock_irq(blkg->q->queue_lock); blkg_put(blkg->parent); + spin_unlock_irq(blkg->q->queue_lock); + } - /* - * A group is freed in rcu manner. But having an rcu lock does not - * mean that one can access all the fields of blkg and assume these - * are valid. For example, don't try to follow throtl_data and - * request queue links. - * - * Having a reference to blkg under an rcu allows acess to only - * values local to groups like group stats and group rate limits - */ - call_rcu(&blkg->rcu_head, blkg_rcu_free); + blkg_free(blkg); } -EXPORT_SYMBOL_GPL(__blkg_release); +EXPORT_SYMBOL_GPL(__blkg_release_rcu); /* * The next function used by blk_queue_for_each_rl(). It's a bit tricky diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index e15f731d2cdd..8056c03a3382 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -266,7 +266,7 @@ static inline void blkg_get(struct blkcg_gq *blkg) blkg->refcnt++; } -void __blkg_release(struct blkcg_gq *blkg); +void __blkg_release_rcu(struct rcu_head *rcu); /** * blkg_put - put a blkg reference @@ -279,7 +279,7 @@ static inline void blkg_put(struct blkcg_gq *blkg) lockdep_assert_held(blkg->q->queue_lock); WARN_ON_ONCE(blkg->refcnt <= 0); if (!--blkg->refcnt) - __blkg_release(blkg); + call_rcu(&blkg->rcu_head, __blkg_release_rcu); } struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q, -- GitLab From 2db6314c213bb21102dd1dad06cfda6a8682d624 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0033/2900] blk-throttle: remove spurious throtl_enqueue_tg() call from throtl_select_dispatch() throtl_select_dispatch() calls throtl_enqueue_tg() right after tg_update_disptime(), which always calls the function anyway. The call is, while harmless, unnecessary. Remove it. This patch doesn't introduce any behavior difference. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 31146225f3d0..3960787358b6 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -816,10 +816,8 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) nr_disp += throtl_dispatch_tg(td, tg, bl); - if (tg->nr_queued[0] || tg->nr_queued[1]) { + if (tg->nr_queued[0] || tg->nr_queued[1]) tg_update_disptime(td, tg); - throtl_enqueue_tg(td, tg); - } if (nr_disp >= throtl_quantum) break; -- GitLab From 632b44935f4c99a61c56f8a6f805a1080ab5a432 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0034/2900] blk-throttle: remove deferred config application mechanism When bps or iops configuration changes, blk-throttle records the new configuration and sets a flag indicating that the config has changed. The flag is checked in the bio dispatch path and applied. This deferred config application was necessary due to limitations in blkcg framework, which haven't existed for quite a while now. This patch removes the deferred config application mechanism and applies new configurations directly from tg_set_conf(), which is simpler. v2: Dropped unnecessary throtl_schedule_delayed_work() call from tg_set_conf() as suggested by Vivek Goyal. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 74 ++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 3960787358b6..7dbd0e695df0 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -85,9 +85,6 @@ struct throtl_grp { unsigned long slice_start[2]; unsigned long slice_end[2]; - /* Some throttle limits got updated for the group */ - int limits_changed; - /* Per cpu stats pointer */ struct tg_stats_cpu __percpu *stats_cpu; @@ -112,8 +109,6 @@ struct throtl_data /* Work for dispatching throttled bios */ struct delayed_work throtl_work; - - int limits_changed; }; /* list and work item to allocate percpu group stats */ @@ -223,7 +218,6 @@ static void throtl_pd_init(struct blkcg_gq *blkg) RB_CLEAR_NODE(&tg->rb_node); bio_list_init(&tg->bio_lists[0]); bio_list_init(&tg->bio_lists[1]); - tg->limits_changed = false; tg->bps[READ] = -1; tg->bps[WRITE] = -1; @@ -826,45 +820,6 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) return nr_disp; } -static void throtl_process_limit_change(struct throtl_data *td) -{ - struct request_queue *q = td->queue; - struct blkcg_gq *blkg, *n; - - if (!td->limits_changed) - return; - - xchg(&td->limits_changed, false); - - throtl_log(td, "limits changed"); - - list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) { - struct throtl_grp *tg = blkg_to_tg(blkg); - - if (!tg->limits_changed) - continue; - - if (!xchg(&tg->limits_changed, false)) - continue; - - throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu" - " riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE], - tg->iops[READ], tg->iops[WRITE]); - - /* - * Restart the slices for both READ and WRITES. It - * might happen that a group's limit are dropped - * suddenly and we don't want to account recently - * dispatched IO with new low rate - */ - throtl_start_new_slice(td, tg, 0); - throtl_start_new_slice(td, tg, 1); - - if (throtl_tg_on_rr(tg)) - tg_update_disptime(td, tg); - } -} - /* Dispatch throttled bios. Should be called without queue lock held. */ static int throtl_dispatch(struct request_queue *q) { @@ -876,8 +831,6 @@ static int throtl_dispatch(struct request_queue *q) spin_lock_irq(q->queue_lock); - throtl_process_limit_change(td); - if (!total_nr_queued(td)) goto out; @@ -925,8 +878,7 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) struct delayed_work *dwork = &td->throtl_work; - /* schedule work if limits changed even if no bio is queued */ - if (total_nr_queued(td) || td->limits_changed) { + if (total_nr_queued(td)) { mod_delayed_work(kthrotld_workqueue, dwork, delay); throtl_log(td, "schedule work. delay=%lu jiffies=%lu", delay, jiffies); @@ -1023,10 +975,25 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, else *(unsigned int *)((void *)tg + cft->private) = ctx.v; - /* XXX: we don't need the following deferred processing */ - xchg(&tg->limits_changed, true); - xchg(&td->limits_changed, true); - throtl_schedule_delayed_work(td, 0); + throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", + tg->bps[READ], tg->bps[WRITE], + tg->iops[READ], tg->iops[WRITE]); + + /* + * We're already holding queue_lock and know @tg is valid. Let's + * apply the new config directly. + * + * Restart the slices for both READ and WRITES. It might happen + * that a group's limit are dropped suddenly and we don't want to + * account recently dispatched IO with new low rate. + */ + throtl_start_new_slice(td, tg, 0); + throtl_start_new_slice(td, tg, 1); + + if (throtl_tg_on_rr(tg)) { + tg_update_disptime(td, tg); + throtl_schedule_next_dispatch(td); + } blkg_conf_finish(&ctx); return 0; @@ -1239,7 +1206,6 @@ int blk_throtl_init(struct request_queue *q) return -ENOMEM; td->tg_service_tree = THROTL_RB_ROOT; - td->limits_changed = false; INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); q->td = td; -- GitLab From cb76199c36a7ccf0947ef4875b32e0940f50d1a8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0035/2900] blk-throttle: collapse throtl_dispatch() into the work function blk-throttle is about to go through major restructuring to support hierarchy. Do cosmetic updates in preparation. * s/throtl_data->throtl_work/throtl_data->dispatch_work/ * s/blk_throtl_work()/blk_throtl_dispatch_work_fn()/ * Collapse throtl_dispatch() into blk_throtl_dispatch_work_fn() This patch is purely cosmetic. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 7dbd0e695df0..0a0bc00059df 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -108,7 +108,7 @@ struct throtl_data unsigned int nr_undestroyed_grps; /* Work for dispatching throttled bios */ - struct delayed_work throtl_work; + struct delayed_work dispatch_work; }; /* list and work item to allocate percpu group stats */ @@ -820,10 +820,12 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) return nr_disp; } -/* Dispatch throttled bios. Should be called without queue lock held. */ -static int throtl_dispatch(struct request_queue *q) +/* work function to dispatch throttled bios */ +void blk_throtl_dispatch_work_fn(struct work_struct *work) { - struct throtl_data *td = q->td; + struct throtl_data *td = container_of(to_delayed_work(work), + struct throtl_data, dispatch_work); + struct request_queue *q = td->queue; unsigned int nr_disp = 0; struct bio_list bio_list_on_stack; struct bio *bio; @@ -859,16 +861,6 @@ static int throtl_dispatch(struct request_queue *q) generic_make_request(bio); blk_finish_plug(&plug); } - return nr_disp; -} - -void blk_throtl_work(struct work_struct *work) -{ - struct throtl_data *td = container_of(work, struct throtl_data, - throtl_work.work); - struct request_queue *q = td->queue; - - throtl_dispatch(q); } /* Call with queue lock held */ @@ -876,7 +868,7 @@ static void throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) { - struct delayed_work *dwork = &td->throtl_work; + struct delayed_work *dwork = &td->dispatch_work; if (total_nr_queued(td)) { mod_delayed_work(kthrotld_workqueue, dwork, delay); @@ -1057,7 +1049,7 @@ static void throtl_shutdown_wq(struct request_queue *q) { struct throtl_data *td = q->td; - cancel_delayed_work_sync(&td->throtl_work); + cancel_delayed_work_sync(&td->dispatch_work); } static struct blkcg_policy blkcg_policy_throtl = { @@ -1206,7 +1198,7 @@ int blk_throtl_init(struct request_queue *q) return -ENOMEM; td->tg_service_tree = THROTL_RB_ROOT; - INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); + INIT_DELAYED_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); q->td = td; td->queue = q; -- GitLab From a9131a27e2a3272df2207277a2be90377ce75fc6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:31 -0700 Subject: [PATCH 0036/2900] blk-throttle: relocate throtl_schedule_delayed_work() Move throtl_schedule_delayed_work() above its first user so that the forward declaration can be removed. This patch is pure relocaiton. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 0a0bc00059df..507b1c608941 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -25,8 +25,6 @@ static struct blkcg_policy blkcg_policy_throtl; /* A workqueue to queue throttle related work */ static struct workqueue_struct *kthrotld_workqueue; -static void throtl_schedule_delayed_work(struct throtl_data *td, - unsigned long delay); struct throtl_rb_root { struct rb_root rb; @@ -398,6 +396,19 @@ static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) __throtl_dequeue_tg(td, tg); } +/* Call with queue lock held */ +static void throtl_schedule_delayed_work(struct throtl_data *td, + unsigned long delay) +{ + struct delayed_work *dwork = &td->dispatch_work; + + if (total_nr_queued(td)) { + mod_delayed_work(kthrotld_workqueue, dwork, delay); + throtl_log(td, "schedule work. delay=%lu jiffies=%lu", + delay, jiffies); + } +} + static void throtl_schedule_next_dispatch(struct throtl_data *td) { struct throtl_rb_root *st = &td->tg_service_tree; @@ -863,20 +874,6 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) } } -/* Call with queue lock held */ -static void -throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) -{ - - struct delayed_work *dwork = &td->dispatch_work; - - if (total_nr_queued(td)) { - mod_delayed_work(kthrotld_workqueue, dwork, delay); - throtl_log(td, "schedule work. delay=%lu jiffies=%lu", - delay, jiffies); - } -} - static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, struct blkg_policy_data *pd, int off) { -- GitLab From 6a525600ffeb9e0d6cbbebda49eb89d6d3408c2b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:32 -0700 Subject: [PATCH 0037/2900] blk-throttle: remove pointless throtl_nr_queued() optimizations throtl_nr_queued() is used in several places to avoid performing certain operations when the throtl_data is empty. This usually is useless as those paths usually aren't traveled if there's no bio queued. * throtl_schedule_delayed_work() skips scheduling dispatch work item if @td doesn't have any bios queued; however, the only case it can be called when @td is empty is from tg_set_conf() which isn't something we should be optimizing for. * throtl_schedule_next_dispatch() takes a quick exit if @td is empty; however, right after that it triggers BUG if the service tree is empty. The two conditions are equivalent and it can just test @st->count for the quick exit. * blk_throtl_dispatch_work_fn() skips dispatch if @td is empty. This work function isn't usually invoked when @td is empty. The only possibility is from tg_set_conf() and when it happens the normal dispatching path can handle empty @td fine. No need to add special skip path. This patch removes the above three unnecessary optimizations, which leave throtl_log() call in blk_throtl_dispatch_work_fn() the only user of throtl_nr_queued(). Remove throtl_nr_queued() and open code it in throtl_log(). I don't think we need td->nr_queued[] at all. Maybe we can remove it later. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 507b1c608941..dbeef303f27b 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -166,11 +166,6 @@ THROTL_TG_FNS(on_rr); #define throtl_log(td, fmt, args...) \ blk_add_trace_msg((td)->queue, "throtl " fmt, ##args) -static inline unsigned int total_nr_queued(struct throtl_data *td) -{ - return td->nr_queued[0] + td->nr_queued[1]; -} - /* * Worker for allocating per cpu stat for tgs. This is scheduled on the * system_wq once there are some groups on the alloc_list waiting for @@ -402,25 +397,18 @@ static void throtl_schedule_delayed_work(struct throtl_data *td, { struct delayed_work *dwork = &td->dispatch_work; - if (total_nr_queued(td)) { - mod_delayed_work(kthrotld_workqueue, dwork, delay); - throtl_log(td, "schedule work. delay=%lu jiffies=%lu", - delay, jiffies); - } + mod_delayed_work(kthrotld_workqueue, dwork, delay); + throtl_log(td, "schedule work. delay=%lu jiffies=%lu", delay, jiffies); } static void throtl_schedule_next_dispatch(struct throtl_data *td) { struct throtl_rb_root *st = &td->tg_service_tree; - /* - * If there are more bios pending, schedule more work. - */ - if (!total_nr_queued(td)) + /* any pending children left? */ + if (!st->count) return; - BUG_ON(!st->count); - update_min_dispatch_time(st); if (time_before_eq(st->min_disptime, jiffies)) @@ -844,14 +832,11 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) spin_lock_irq(q->queue_lock); - if (!total_nr_queued(td)) - goto out; - bio_list_init(&bio_list_on_stack); throtl_log(td, "dispatch nr_queued=%u read=%u write=%u", - total_nr_queued(td), td->nr_queued[READ], - td->nr_queued[WRITE]); + td->nr_queued[READ] + td->nr_queued[WRITE], + td->nr_queued[READ], td->nr_queued[WRITE]); nr_disp = throtl_select_dispatch(td, &bio_list_on_stack); @@ -859,7 +844,7 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) throtl_log(td, "bios disp=%u", nr_disp); throtl_schedule_next_dispatch(td); -out: + spin_unlock_irq(q->queue_lock); /* -- GitLab From c9e0332e877c1a1ccfe4ba315a437c7a8cf6e575 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:32 -0700 Subject: [PATCH 0038/2900] blk-throttle: rename throtl_rb_root to throtl_service_queue throtl_rb_root will be expanded to cover more roles for hierarchy support. Rename it to throtl_service_queue and make its fields more descriptive. * rb -> pending_tree * left -> first_pending * count -> nr_pending * min_disptime -> first_pending_disptime This patch is purely cosmetic. Signed-off-by: Tejun Heo --- block/blk-throttle.c | 84 ++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index dbeef303f27b..b279110ba287 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -26,15 +26,15 @@ static struct blkcg_policy blkcg_policy_throtl; /* A workqueue to queue throttle related work */ static struct workqueue_struct *kthrotld_workqueue; -struct throtl_rb_root { - struct rb_root rb; - struct rb_node *left; - unsigned int count; - unsigned long min_disptime; +struct throtl_service_queue { + struct rb_root pending_tree; /* RB tree of active tgs */ + struct rb_node *first_pending; /* first node in the tree */ + unsigned int nr_pending; /* # queued in the tree */ + unsigned long first_pending_disptime; /* disptime of the first tg */ }; -#define THROTL_RB_ROOT (struct throtl_rb_root) { .rb = RB_ROOT, .left = NULL, \ - .count = 0, .min_disptime = 0} +#define THROTL_SERVICE_QUEUE_INITIALIZER \ + (struct throtl_service_queue){ .pending_tree = RB_ROOT } #define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) @@ -50,7 +50,7 @@ struct throtl_grp { /* must be the first member */ struct blkg_policy_data pd; - /* active throtl group service_tree member */ + /* active throtl group service_queue member */ struct rb_node rb_node; /* @@ -93,7 +93,7 @@ struct throtl_grp { struct throtl_data { /* service tree for active throtl groups */ - struct throtl_rb_root tg_service_tree; + struct throtl_service_queue service_queue; struct request_queue *queue; @@ -296,17 +296,17 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, return tg; } -static struct throtl_grp *throtl_rb_first(struct throtl_rb_root *root) +static struct throtl_grp *throtl_rb_first(struct throtl_service_queue *sq) { /* Service tree is empty */ - if (!root->count) + if (!sq->nr_pending) return NULL; - if (!root->left) - root->left = rb_first(&root->rb); + if (!sq->first_pending) + sq->first_pending = rb_first(&sq->pending_tree); - if (root->left) - return rb_entry_tg(root->left); + if (sq->first_pending) + return rb_entry_tg(sq->first_pending); return NULL; } @@ -317,29 +317,29 @@ static void rb_erase_init(struct rb_node *n, struct rb_root *root) RB_CLEAR_NODE(n); } -static void throtl_rb_erase(struct rb_node *n, struct throtl_rb_root *root) +static void throtl_rb_erase(struct rb_node *n, struct throtl_service_queue *sq) { - if (root->left == n) - root->left = NULL; - rb_erase_init(n, &root->rb); - --root->count; + if (sq->first_pending == n) + sq->first_pending = NULL; + rb_erase_init(n, &sq->pending_tree); + --sq->nr_pending; } -static void update_min_dispatch_time(struct throtl_rb_root *st) +static void update_min_dispatch_time(struct throtl_service_queue *sq) { struct throtl_grp *tg; - tg = throtl_rb_first(st); + tg = throtl_rb_first(sq); if (!tg) return; - st->min_disptime = tg->disptime; + sq->first_pending_disptime = tg->disptime; } -static void -tg_service_tree_add(struct throtl_rb_root *st, struct throtl_grp *tg) +static void tg_service_queue_add(struct throtl_service_queue *sq, + struct throtl_grp *tg) { - struct rb_node **node = &st->rb.rb_node; + struct rb_node **node = &sq->pending_tree.rb_node; struct rb_node *parent = NULL; struct throtl_grp *__tg; unsigned long key = tg->disptime; @@ -358,19 +358,19 @@ tg_service_tree_add(struct throtl_rb_root *st, struct throtl_grp *tg) } if (left) - st->left = &tg->rb_node; + sq->first_pending = &tg->rb_node; rb_link_node(&tg->rb_node, parent, node); - rb_insert_color(&tg->rb_node, &st->rb); + rb_insert_color(&tg->rb_node, &sq->pending_tree); } static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) { - struct throtl_rb_root *st = &td->tg_service_tree; + struct throtl_service_queue *sq = &td->service_queue; - tg_service_tree_add(st, tg); + tg_service_queue_add(sq, tg); throtl_mark_tg_on_rr(tg); - st->count++; + sq->nr_pending++; } static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) @@ -381,7 +381,7 @@ static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) { - throtl_rb_erase(&tg->rb_node, &td->tg_service_tree); + throtl_rb_erase(&tg->rb_node, &td->service_queue); throtl_clear_tg_on_rr(tg); } @@ -403,18 +403,18 @@ static void throtl_schedule_delayed_work(struct throtl_data *td, static void throtl_schedule_next_dispatch(struct throtl_data *td) { - struct throtl_rb_root *st = &td->tg_service_tree; + struct throtl_service_queue *sq = &td->service_queue; /* any pending children left? */ - if (!st->count) + if (!sq->nr_pending) return; - update_min_dispatch_time(st); + update_min_dispatch_time(sq); - if (time_before_eq(st->min_disptime, jiffies)) + if (time_before_eq(sq->first_pending_disptime, jiffies)) throtl_schedule_delayed_work(td, 0); else - throtl_schedule_delayed_work(td, (st->min_disptime - jiffies)); + throtl_schedule_delayed_work(td, sq->first_pending_disptime - jiffies); } static inline void @@ -794,10 +794,10 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) { unsigned int nr_disp = 0; struct throtl_grp *tg; - struct throtl_rb_root *st = &td->tg_service_tree; + struct throtl_service_queue *sq = &td->service_queue; while (1) { - tg = throtl_rb_first(st); + tg = throtl_rb_first(sq); if (!tg) break; @@ -1145,7 +1145,7 @@ void blk_throtl_drain(struct request_queue *q) __releases(q->queue_lock) __acquires(q->queue_lock) { struct throtl_data *td = q->td; - struct throtl_rb_root *st = &td->tg_service_tree; + struct throtl_service_queue *sq = &td->service_queue; struct throtl_grp *tg; struct bio_list bl; struct bio *bio; @@ -1154,7 +1154,7 @@ void blk_throtl_drain(struct request_queue *q) bio_list_init(&bl); - while ((tg = throtl_rb_first(st))) { + while ((tg = throtl_rb_first(sq))) { throtl_dequeue_tg(td, tg); while ((bio = bio_list_peek(&tg->bio_lists[READ]))) @@ -1179,7 +1179,7 @@ int blk_throtl_init(struct request_queue *q) if (!td) return -ENOMEM; - td->tg_service_tree = THROTL_RB_ROOT; + td->service_queue = THROTL_SERVICE_QUEUE_INITIALIZER; INIT_DELAYED_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); q->td = td; -- GitLab From 5b2c16aae0c074c3bb546c4c066ca7064684553c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:32 -0700 Subject: [PATCH 0039/2900] blk-throttle: simplify throtl_grp flag handling blk-throttle is still using function-defining macros to define flag handling functions, which went out style at least a decade ago. Just define the flag as bitmask and use direct bit operations. This patch doesn't make any functional changes. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index b279110ba287..e8ef43d3fab3 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -36,6 +36,10 @@ struct throtl_service_queue { #define THROTL_SERVICE_QUEUE_INITIALIZER \ (struct throtl_service_queue){ .pending_tree = RB_ROOT } +enum tg_state_flags { + THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */ +}; + #define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) /* Per-cpu group stats */ @@ -136,26 +140,6 @@ static inline struct throtl_grp *td_root_tg(struct throtl_data *td) return blkg_to_tg(td->queue->root_blkg); } -enum tg_state_flags { - THROTL_TG_FLAG_on_rr = 0, /* on round-robin busy list */ -}; - -#define THROTL_TG_FNS(name) \ -static inline void throtl_mark_tg_##name(struct throtl_grp *tg) \ -{ \ - (tg)->flags |= (1 << THROTL_TG_FLAG_##name); \ -} \ -static inline void throtl_clear_tg_##name(struct throtl_grp *tg) \ -{ \ - (tg)->flags &= ~(1 << THROTL_TG_FLAG_##name); \ -} \ -static inline int throtl_tg_##name(const struct throtl_grp *tg) \ -{ \ - return ((tg)->flags & (1 << THROTL_TG_FLAG_##name)) != 0; \ -} - -THROTL_TG_FNS(on_rr); - #define throtl_log_tg(td, tg, fmt, args...) do { \ char __pbuf[128]; \ \ @@ -369,25 +353,25 @@ static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) struct throtl_service_queue *sq = &td->service_queue; tg_service_queue_add(sq, tg); - throtl_mark_tg_on_rr(tg); + tg->flags |= THROTL_TG_PENDING; sq->nr_pending++; } static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) { - if (!throtl_tg_on_rr(tg)) + if (!(tg->flags & THROTL_TG_PENDING)) __throtl_enqueue_tg(td, tg); } static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) { throtl_rb_erase(&tg->rb_node, &td->service_queue); - throtl_clear_tg_on_rr(tg); + tg->flags &= ~THROTL_TG_PENDING; } static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) { - if (throtl_tg_on_rr(tg)) + if (tg->flags & THROTL_TG_PENDING) __throtl_dequeue_tg(td, tg); } @@ -964,7 +948,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, throtl_start_new_slice(td, tg, 0); throtl_start_new_slice(td, tg, 1); - if (throtl_tg_on_rr(tg)) { + if (tg->flags & THROTL_TG_PENDING) { tg_update_disptime(td, tg); throtl_schedule_next_dispatch(td); } -- GitLab From 0f3457f60edc57332bf6564fa00d561a4372dcb9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:32 -0700 Subject: [PATCH 0040/2900] blk-throttle: add backlink pointer from throtl_grp to throtl_data Add throtl_grp->td so that the td (throtl_data) a given tg (throtl_grp) belongs to can be determined, and remove @td argument from functions which take both @td and @tg as the former now can be determined from the latter. This generally simplifies the code and removes a number of cases where @td is passed as an argument without being actually used. This will also help hierarchy support implementation. While at it, in multi-line conditions, move the logical operators leading broken lines to the end of the previous line. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 106 +++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index e8ef43d3fab3..a489391f9153 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -57,6 +57,9 @@ struct throtl_grp { /* active throtl group service_queue member */ struct rb_node rb_node; + /* throtl_data this group belongs to */ + struct throtl_data *td; + /* * Dispatch time in jiffies. This is the estimated time when group * will unthrottle and is ready to dispatch more bio. It is used as @@ -140,11 +143,11 @@ static inline struct throtl_grp *td_root_tg(struct throtl_data *td) return blkg_to_tg(td->queue->root_blkg); } -#define throtl_log_tg(td, tg, fmt, args...) do { \ +#define throtl_log_tg(tg, fmt, args...) do { \ char __pbuf[128]; \ \ blkg_path(tg_to_blkg(tg), __pbuf, sizeof(__pbuf)); \ - blk_add_trace_msg((td)->queue, "throtl %s " fmt, __pbuf, ##args); \ + blk_add_trace_msg((tg)->td->queue, "throtl %s " fmt, __pbuf, ##args); \ } while (0) #define throtl_log(td, fmt, args...) \ @@ -193,6 +196,7 @@ static void throtl_pd_init(struct blkcg_gq *blkg) unsigned long flags; RB_CLEAR_NODE(&tg->rb_node); + tg->td = blkg->q->td; bio_list_init(&tg->bio_lists[0]); bio_list_init(&tg->bio_lists[1]); @@ -401,36 +405,34 @@ static void throtl_schedule_next_dispatch(struct throtl_data *td) throtl_schedule_delayed_work(td, sq->first_pending_disptime - jiffies); } -static inline void -throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw) +static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw) { tg->bytes_disp[rw] = 0; tg->io_disp[rw] = 0; tg->slice_start[rw] = jiffies; tg->slice_end[rw] = jiffies + throtl_slice; - throtl_log_tg(td, tg, "[%c] new slice start=%lu end=%lu jiffies=%lu", + throtl_log_tg(tg, "[%c] new slice start=%lu end=%lu jiffies=%lu", rw == READ ? 'R' : 'W', tg->slice_start[rw], tg->slice_end[rw], jiffies); } -static inline void throtl_set_slice_end(struct throtl_data *td, - struct throtl_grp *tg, bool rw, unsigned long jiffy_end) +static inline void throtl_set_slice_end(struct throtl_grp *tg, bool rw, + unsigned long jiffy_end) { tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); } -static inline void throtl_extend_slice(struct throtl_data *td, - struct throtl_grp *tg, bool rw, unsigned long jiffy_end) +static inline void throtl_extend_slice(struct throtl_grp *tg, bool rw, + unsigned long jiffy_end) { tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); - throtl_log_tg(td, tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu", + throtl_log_tg(tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu", rw == READ ? 'R' : 'W', tg->slice_start[rw], tg->slice_end[rw], jiffies); } /* Determine if previously allocated or extended slice is complete or not */ -static bool -throtl_slice_used(struct throtl_data *td, struct throtl_grp *tg, bool rw) +static bool throtl_slice_used(struct throtl_grp *tg, bool rw) { if (time_in_range(jiffies, tg->slice_start[rw], tg->slice_end[rw])) return 0; @@ -439,8 +441,7 @@ throtl_slice_used(struct throtl_data *td, struct throtl_grp *tg, bool rw) } /* Trim the used slices and adjust slice start accordingly */ -static inline void -throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw) +static inline void throtl_trim_slice(struct throtl_grp *tg, bool rw) { unsigned long nr_slices, time_elapsed, io_trim; u64 bytes_trim, tmp; @@ -452,7 +453,7 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw) * renewed. Don't try to trim the slice if slice is used. A new * slice will start when appropriate. */ - if (throtl_slice_used(td, tg, rw)) + if (throtl_slice_used(tg, rw)) return; /* @@ -463,7 +464,7 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw) * is bad because it does not allow new slice to start. */ - throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice); + throtl_set_slice_end(tg, rw, jiffies + throtl_slice); time_elapsed = jiffies - tg->slice_start[rw]; @@ -492,14 +493,14 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw) tg->slice_start[rw] += nr_slices * throtl_slice; - throtl_log_tg(td, tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu" + throtl_log_tg(tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu" " start=%lu end=%lu jiffies=%lu", rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim, tg->slice_start[rw], tg->slice_end[rw], jiffies); } -static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg, - struct bio *bio, unsigned long *wait) +static bool tg_with_in_iops_limit(struct throtl_grp *tg, struct bio *bio, + unsigned long *wait) { bool rw = bio_data_dir(bio); unsigned int io_allowed; @@ -548,8 +549,8 @@ static bool tg_with_in_iops_limit(struct throtl_data *td, struct throtl_grp *tg, return 0; } -static bool tg_with_in_bps_limit(struct throtl_data *td, struct throtl_grp *tg, - struct bio *bio, unsigned long *wait) +static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio, + unsigned long *wait) { bool rw = bio_data_dir(bio); u64 bytes_allowed, extra_bytes, tmp; @@ -600,8 +601,8 @@ static bool tg_no_rule_group(struct throtl_grp *tg, bool rw) { * Returns whether one can dispatch a bio or not. Also returns approx number * of jiffies to wait before this bio is with-in IO rate and can be dispatched */ -static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg, - struct bio *bio, unsigned long *wait) +static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio, + unsigned long *wait) { bool rw = bio_data_dir(bio); unsigned long bps_wait = 0, iops_wait = 0, max_wait = 0; @@ -626,15 +627,15 @@ static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg, * existing slice to make sure it is at least throtl_slice interval * long since now. */ - if (throtl_slice_used(td, tg, rw)) - throtl_start_new_slice(td, tg, rw); + if (throtl_slice_used(tg, rw)) + throtl_start_new_slice(tg, rw); else { if (time_before(tg->slice_end[rw], jiffies + throtl_slice)) - throtl_extend_slice(td, tg, rw, jiffies + throtl_slice); + throtl_extend_slice(tg, rw, jiffies + throtl_slice); } - if (tg_with_in_bps_limit(td, tg, bio, &bps_wait) - && tg_with_in_iops_limit(td, tg, bio, &iops_wait)) { + if (tg_with_in_bps_limit(tg, bio, &bps_wait) && + tg_with_in_iops_limit(tg, bio, &iops_wait)) { if (wait) *wait = 0; return 1; @@ -646,7 +647,7 @@ static bool tg_may_dispatch(struct throtl_data *td, struct throtl_grp *tg, *wait = max_wait; if (time_before(tg->slice_end[rw], jiffies + max_wait)) - throtl_extend_slice(td, tg, rw, jiffies + max_wait); + throtl_extend_slice(tg, rw, jiffies + max_wait); return 0; } @@ -707,10 +708,10 @@ static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg) struct bio *bio; if ((bio = bio_list_peek(&tg->bio_lists[READ]))) - tg_may_dispatch(td, tg, bio, &read_wait); + tg_may_dispatch(tg, bio, &read_wait); if ((bio = bio_list_peek(&tg->bio_lists[WRITE]))) - tg_may_dispatch(td, tg, bio, &write_wait); + tg_may_dispatch(tg, bio, &write_wait); min_wait = min(read_wait, write_wait); disptime = jiffies + min_wait; @@ -721,8 +722,8 @@ static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg) throtl_enqueue_tg(td, tg); } -static void tg_dispatch_one_bio(struct throtl_data *td, struct throtl_grp *tg, - bool rw, struct bio_list *bl) +static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, + struct bio_list *bl) { struct bio *bio; @@ -731,18 +732,17 @@ static void tg_dispatch_one_bio(struct throtl_data *td, struct throtl_grp *tg, /* Drop bio reference on blkg */ blkg_put(tg_to_blkg(tg)); - BUG_ON(td->nr_queued[rw] <= 0); - td->nr_queued[rw]--; + BUG_ON(tg->td->nr_queued[rw] <= 0); + tg->td->nr_queued[rw]--; throtl_charge_bio(tg, bio); bio_list_add(bl, bio); bio->bi_rw |= REQ_THROTTLED; - throtl_trim_slice(td, tg, rw); + throtl_trim_slice(tg, rw); } -static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg, - struct bio_list *bl) +static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) { unsigned int nr_reads = 0, nr_writes = 0; unsigned int max_nr_reads = throtl_grp_quantum*3/4; @@ -751,20 +751,20 @@ static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg, /* Try to dispatch 75% READS and 25% WRITES */ - while ((bio = bio_list_peek(&tg->bio_lists[READ])) - && tg_may_dispatch(td, tg, bio, NULL)) { + while ((bio = bio_list_peek(&tg->bio_lists[READ])) && + tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); nr_reads++; if (nr_reads >= max_nr_reads) break; } - while ((bio = bio_list_peek(&tg->bio_lists[WRITE])) - && tg_may_dispatch(td, tg, bio, NULL)) { + while ((bio = bio_list_peek(&tg->bio_lists[WRITE])) && + tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(td, tg, bio_data_dir(bio), bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); nr_writes++; if (nr_writes >= max_nr_writes) @@ -791,7 +791,7 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) throtl_dequeue_tg(td, tg); - nr_disp += throtl_dispatch_tg(td, tg, bl); + nr_disp += throtl_dispatch_tg(tg, bl); if (tg->nr_queued[0] || tg->nr_queued[1]) tg_update_disptime(td, tg); @@ -933,7 +933,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, else *(unsigned int *)((void *)tg + cft->private) = ctx.v; - throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", + throtl_log_tg(tg, "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE], tg->iops[READ], tg->iops[WRITE]); @@ -945,8 +945,8 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, * that a group's limit are dropped suddenly and we don't want to * account recently dispatched IO with new low rate. */ - throtl_start_new_slice(td, tg, 0); - throtl_start_new_slice(td, tg, 1); + throtl_start_new_slice(tg, 0); + throtl_start_new_slice(tg, 1); if (tg->flags & THROTL_TG_PENDING) { tg_update_disptime(td, tg); @@ -1076,7 +1076,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) } /* Bio is with-in rate limit of group */ - if (tg_may_dispatch(td, tg, bio, NULL)) { + if (tg_may_dispatch(tg, bio, NULL)) { throtl_charge_bio(tg, bio); /* @@ -1090,12 +1090,12 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) * * So keep on trimming slice even if bio is not queued. */ - throtl_trim_slice(td, tg, rw); + throtl_trim_slice(tg, rw); goto out_unlock; } queue_bio: - throtl_log_tg(td, tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu" + throtl_log_tg(tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu" " iodisp=%u iops=%u queued=%d/%d", rw == READ ? 'R' : 'W', tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], @@ -1142,9 +1142,9 @@ void blk_throtl_drain(struct request_queue *q) throtl_dequeue_tg(td, tg); while ((bio = bio_list_peek(&tg->bio_lists[READ]))) - tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); while ((bio = bio_list_peek(&tg->bio_lists[WRITE]))) - tg_dispatch_one_bio(td, tg, bio_data_dir(bio), &bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); } spin_unlock_irq(q->queue_lock); -- GitLab From e2d57e60195a65e2f161ac1229ec9c91935e0240 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:33 -0700 Subject: [PATCH 0041/2900] blk-throttle: pass around throtl_service_queue instead of throtl_data throtl_service_queue will be used as the basic block to implement hierarchy support. Pass around throtl_service_queue *sq instead of throtl_data *td in the following functions which will be used across multiple levels of hierarchy. * [__]throtl_enqueue/dequeue_tg() * throtl_add_bio_tg() * tg_update_disptime() * throtl_select_dispatch() Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 53 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a489391f9153..9660ec8d0375 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -352,31 +352,33 @@ static void tg_service_queue_add(struct throtl_service_queue *sq, rb_insert_color(&tg->rb_node, &sq->pending_tree); } -static void __throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) +static void __throtl_enqueue_tg(struct throtl_service_queue *sq, + struct throtl_grp *tg) { - struct throtl_service_queue *sq = &td->service_queue; - tg_service_queue_add(sq, tg); tg->flags |= THROTL_TG_PENDING; sq->nr_pending++; } -static void throtl_enqueue_tg(struct throtl_data *td, struct throtl_grp *tg) +static void throtl_enqueue_tg(struct throtl_service_queue *sq, + struct throtl_grp *tg) { if (!(tg->flags & THROTL_TG_PENDING)) - __throtl_enqueue_tg(td, tg); + __throtl_enqueue_tg(sq, tg); } -static void __throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) +static void __throtl_dequeue_tg(struct throtl_service_queue *sq, + struct throtl_grp *tg) { - throtl_rb_erase(&tg->rb_node, &td->service_queue); + throtl_rb_erase(&tg->rb_node, sq); tg->flags &= ~THROTL_TG_PENDING; } -static void throtl_dequeue_tg(struct throtl_data *td, struct throtl_grp *tg) +static void throtl_dequeue_tg(struct throtl_service_queue *sq, + struct throtl_grp *tg) { if (tg->flags & THROTL_TG_PENDING) - __throtl_dequeue_tg(td, tg); + __throtl_dequeue_tg(sq, tg); } /* Call with queue lock held */ @@ -689,8 +691,8 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, bio->bi_rw); } -static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg, - struct bio *bio) +static void throtl_add_bio_tg(struct throtl_service_queue *sq, + struct throtl_grp *tg, struct bio *bio) { bool rw = bio_data_dir(bio); @@ -698,11 +700,12 @@ static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg, /* Take a bio reference on tg */ blkg_get(tg_to_blkg(tg)); tg->nr_queued[rw]++; - td->nr_queued[rw]++; - throtl_enqueue_tg(td, tg); + tg->td->nr_queued[rw]++; + throtl_enqueue_tg(sq, tg); } -static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg) +static void tg_update_disptime(struct throtl_service_queue *sq, + struct throtl_grp *tg) { unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime; struct bio *bio; @@ -717,9 +720,9 @@ static void tg_update_disptime(struct throtl_data *td, struct throtl_grp *tg) disptime = jiffies + min_wait; /* Update dispatch time */ - throtl_dequeue_tg(td, tg); + throtl_dequeue_tg(sq, tg); tg->disptime = disptime; - throtl_enqueue_tg(td, tg); + throtl_enqueue_tg(sq, tg); } static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, @@ -774,11 +777,11 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) return nr_reads + nr_writes; } -static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) +static int throtl_select_dispatch(struct throtl_service_queue *sq, + struct bio_list *bl) { unsigned int nr_disp = 0; struct throtl_grp *tg; - struct throtl_service_queue *sq = &td->service_queue; while (1) { tg = throtl_rb_first(sq); @@ -789,12 +792,12 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl) if (time_before(jiffies, tg->disptime)) break; - throtl_dequeue_tg(td, tg); + throtl_dequeue_tg(sq, tg); nr_disp += throtl_dispatch_tg(tg, bl); if (tg->nr_queued[0] || tg->nr_queued[1]) - tg_update_disptime(td, tg); + tg_update_disptime(sq, tg); if (nr_disp >= throtl_quantum) break; @@ -822,7 +825,7 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) td->nr_queued[READ] + td->nr_queued[WRITE], td->nr_queued[READ], td->nr_queued[WRITE]); - nr_disp = throtl_select_dispatch(td, &bio_list_on_stack); + nr_disp = throtl_select_dispatch(&td->service_queue, &bio_list_on_stack); if (nr_disp) throtl_log(td, "bios disp=%u", nr_disp); @@ -949,7 +952,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, throtl_start_new_slice(tg, 1); if (tg->flags & THROTL_TG_PENDING) { - tg_update_disptime(td, tg); + tg_update_disptime(&td->service_queue, tg); throtl_schedule_next_dispatch(td); } @@ -1103,11 +1106,11 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) tg->nr_queued[READ], tg->nr_queued[WRITE]); bio_associate_current(bio); - throtl_add_bio_tg(q->td, tg, bio); + throtl_add_bio_tg(&q->td->service_queue, tg, bio); throttled = true; if (update_disptime) { - tg_update_disptime(td, tg); + tg_update_disptime(&td->service_queue, tg); throtl_schedule_next_dispatch(td); } @@ -1139,7 +1142,7 @@ void blk_throtl_drain(struct request_queue *q) bio_list_init(&bl); while ((tg = throtl_rb_first(sq))) { - throtl_dequeue_tg(td, tg); + throtl_dequeue_tg(sq, tg); while ((bio = bio_list_peek(&tg->bio_lists[READ]))) tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); -- GitLab From 0049af73bb4b74d1407db59caefc5fe057ee434a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:33 -0700 Subject: [PATCH 0042/2900] blk-throttle: reorganize throtl_service_queue passed around as argument throtl_service_queue will be the building block of hierarchy support and will form a tree. This patch updates its usages as arguments to reduce confusion. * When a service queue is used as the parent role - the host of the rbtree - use @parent_sq instead of @sq. * For functions taking both @tg and @parent_sq, reorder them so that the order is (@tg, @parent_sq) not the other way around. This makes the code follow the usual convention of specifying the primary target of the operation as the first argument. This patch doesn't make any functional differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 100 ++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 9660ec8d0375..ebaaaa9f57d6 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -284,17 +284,18 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, return tg; } -static struct throtl_grp *throtl_rb_first(struct throtl_service_queue *sq) +static struct throtl_grp * +throtl_rb_first(struct throtl_service_queue *parent_sq) { /* Service tree is empty */ - if (!sq->nr_pending) + if (!parent_sq->nr_pending) return NULL; - if (!sq->first_pending) - sq->first_pending = rb_first(&sq->pending_tree); + if (!parent_sq->first_pending) + parent_sq->first_pending = rb_first(&parent_sq->pending_tree); - if (sq->first_pending) - return rb_entry_tg(sq->first_pending); + if (parent_sq->first_pending) + return rb_entry_tg(parent_sq->first_pending); return NULL; } @@ -305,29 +306,30 @@ static void rb_erase_init(struct rb_node *n, struct rb_root *root) RB_CLEAR_NODE(n); } -static void throtl_rb_erase(struct rb_node *n, struct throtl_service_queue *sq) +static void throtl_rb_erase(struct rb_node *n, + struct throtl_service_queue *parent_sq) { - if (sq->first_pending == n) - sq->first_pending = NULL; - rb_erase_init(n, &sq->pending_tree); - --sq->nr_pending; + if (parent_sq->first_pending == n) + parent_sq->first_pending = NULL; + rb_erase_init(n, &parent_sq->pending_tree); + --parent_sq->nr_pending; } -static void update_min_dispatch_time(struct throtl_service_queue *sq) +static void update_min_dispatch_time(struct throtl_service_queue *parent_sq) { struct throtl_grp *tg; - tg = throtl_rb_first(sq); + tg = throtl_rb_first(parent_sq); if (!tg) return; - sq->first_pending_disptime = tg->disptime; + parent_sq->first_pending_disptime = tg->disptime; } -static void tg_service_queue_add(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void tg_service_queue_add(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { - struct rb_node **node = &sq->pending_tree.rb_node; + struct rb_node **node = &parent_sq->pending_tree.rb_node; struct rb_node *parent = NULL; struct throtl_grp *__tg; unsigned long key = tg->disptime; @@ -346,39 +348,39 @@ static void tg_service_queue_add(struct throtl_service_queue *sq, } if (left) - sq->first_pending = &tg->rb_node; + parent_sq->first_pending = &tg->rb_node; rb_link_node(&tg->rb_node, parent, node); - rb_insert_color(&tg->rb_node, &sq->pending_tree); + rb_insert_color(&tg->rb_node, &parent_sq->pending_tree); } -static void __throtl_enqueue_tg(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void __throtl_enqueue_tg(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { - tg_service_queue_add(sq, tg); + tg_service_queue_add(tg, parent_sq); tg->flags |= THROTL_TG_PENDING; - sq->nr_pending++; + parent_sq->nr_pending++; } -static void throtl_enqueue_tg(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void throtl_enqueue_tg(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { if (!(tg->flags & THROTL_TG_PENDING)) - __throtl_enqueue_tg(sq, tg); + __throtl_enqueue_tg(tg, parent_sq); } -static void __throtl_dequeue_tg(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void __throtl_dequeue_tg(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { - throtl_rb_erase(&tg->rb_node, sq); + throtl_rb_erase(&tg->rb_node, parent_sq); tg->flags &= ~THROTL_TG_PENDING; } -static void throtl_dequeue_tg(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void throtl_dequeue_tg(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { if (tg->flags & THROTL_TG_PENDING) - __throtl_dequeue_tg(sq, tg); + __throtl_dequeue_tg(tg, parent_sq); } /* Call with queue lock held */ @@ -691,8 +693,8 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, bio->bi_rw); } -static void throtl_add_bio_tg(struct throtl_service_queue *sq, - struct throtl_grp *tg, struct bio *bio) +static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { bool rw = bio_data_dir(bio); @@ -701,11 +703,11 @@ static void throtl_add_bio_tg(struct throtl_service_queue *sq, blkg_get(tg_to_blkg(tg)); tg->nr_queued[rw]++; tg->td->nr_queued[rw]++; - throtl_enqueue_tg(sq, tg); + throtl_enqueue_tg(tg, parent_sq); } -static void tg_update_disptime(struct throtl_service_queue *sq, - struct throtl_grp *tg) +static void tg_update_disptime(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime; struct bio *bio; @@ -720,9 +722,9 @@ static void tg_update_disptime(struct throtl_service_queue *sq, disptime = jiffies + min_wait; /* Update dispatch time */ - throtl_dequeue_tg(sq, tg); + throtl_dequeue_tg(tg, parent_sq); tg->disptime = disptime; - throtl_enqueue_tg(sq, tg); + throtl_enqueue_tg(tg, parent_sq); } static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, @@ -777,14 +779,14 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) return nr_reads + nr_writes; } -static int throtl_select_dispatch(struct throtl_service_queue *sq, +static int throtl_select_dispatch(struct throtl_service_queue *parent_sq, struct bio_list *bl) { unsigned int nr_disp = 0; struct throtl_grp *tg; while (1) { - tg = throtl_rb_first(sq); + tg = throtl_rb_first(parent_sq); if (!tg) break; @@ -792,12 +794,12 @@ static int throtl_select_dispatch(struct throtl_service_queue *sq, if (time_before(jiffies, tg->disptime)) break; - throtl_dequeue_tg(sq, tg); + throtl_dequeue_tg(tg, parent_sq); nr_disp += throtl_dispatch_tg(tg, bl); if (tg->nr_queued[0] || tg->nr_queued[1]) - tg_update_disptime(sq, tg); + tg_update_disptime(tg, parent_sq); if (nr_disp >= throtl_quantum) break; @@ -952,7 +954,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, throtl_start_new_slice(tg, 1); if (tg->flags & THROTL_TG_PENDING) { - tg_update_disptime(&td->service_queue, tg); + tg_update_disptime(tg, &td->service_queue); throtl_schedule_next_dispatch(td); } @@ -1106,11 +1108,11 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) tg->nr_queued[READ], tg->nr_queued[WRITE]); bio_associate_current(bio); - throtl_add_bio_tg(&q->td->service_queue, tg, bio); + throtl_add_bio_tg(bio, tg, &q->td->service_queue); throttled = true; if (update_disptime) { - tg_update_disptime(&td->service_queue, tg); + tg_update_disptime(tg, &td->service_queue); throtl_schedule_next_dispatch(td); } @@ -1132,7 +1134,7 @@ void blk_throtl_drain(struct request_queue *q) __releases(q->queue_lock) __acquires(q->queue_lock) { struct throtl_data *td = q->td; - struct throtl_service_queue *sq = &td->service_queue; + struct throtl_service_queue *parent_sq = &td->service_queue; struct throtl_grp *tg; struct bio_list bl; struct bio *bio; @@ -1141,8 +1143,8 @@ void blk_throtl_drain(struct request_queue *q) bio_list_init(&bl); - while ((tg = throtl_rb_first(sq))) { - throtl_dequeue_tg(sq, tg); + while ((tg = throtl_rb_first(parent_sq))) { + throtl_dequeue_tg(tg, parent_sq); while ((bio = bio_list_peek(&tg->bio_lists[READ]))) tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); -- GitLab From 49a2f1e3f231f6b2ccfc8192f4c395de7fa910a1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:34 -0700 Subject: [PATCH 0043/2900] blk-throttle: add throtl_grp->service_queue Currently, there's single service_queue per queue - throtl_data->service_queue. All active throtl_grp's are queued on the queue and dispatched according to their limits. To support hierarchy, this will be expanded such that active throtl_grp's form a tree anchored at throtl_data->service_queue and chained through each intermediate throtl_grp's service_queue. This patch adds throtl_grp->service_queue to prepare for hierarchy support. The initialization function - throtl_service_queue_init() - is added and replaces the macro initializer. The newly added tg->service_queue isn't used yet. Following patches will do. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index ebaaaa9f57d6..7340440ccfb5 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -33,9 +33,6 @@ struct throtl_service_queue { unsigned long first_pending_disptime; /* disptime of the first tg */ }; -#define THROTL_SERVICE_QUEUE_INITIALIZER \ - (struct throtl_service_queue){ .pending_tree = RB_ROOT } - enum tg_state_flags { THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */ }; @@ -60,6 +57,9 @@ struct throtl_grp { /* throtl_data this group belongs to */ struct throtl_data *td; + /* this group's service queue */ + struct throtl_service_queue service_queue; + /* * Dispatch time in jiffies. This is the estimated time when group * will unthrottle and is ready to dispatch more bio. It is used as @@ -190,11 +190,18 @@ static void tg_stats_alloc_fn(struct work_struct *work) goto alloc_stats; } +/* init a service_queue, assumes the caller zeroed it */ +static void throtl_service_queue_init(struct throtl_service_queue *sq) +{ + sq->pending_tree = RB_ROOT; +} + static void throtl_pd_init(struct blkcg_gq *blkg) { struct throtl_grp *tg = blkg_to_tg(blkg); unsigned long flags; + throtl_service_queue_init(&tg->service_queue); RB_CLEAR_NODE(&tg->rb_node); tg->td = blkg->q->td; bio_list_init(&tg->bio_lists[0]); @@ -1168,8 +1175,8 @@ int blk_throtl_init(struct request_queue *q) if (!td) return -ENOMEM; - td->service_queue = THROTL_SERVICE_QUEUE_INITIALIZER; INIT_DELAYED_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); + throtl_service_queue_init(&td->service_queue); q->td = td; td->queue = q; -- GitLab From 73f0d49a9637a7ec3448a62a0042e35b14ba18a3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:35 -0700 Subject: [PATCH 0044/2900] blk-throttle: move bio_lists[] and friends to throtl_service_queue throtl_service_queues will eventually form a tree which is anchored at throtl_data->service_queue and queue bios will climb the tree to the top service_queue to be executed. This patch moves bio_lists[] and nr_queued[] from throtl_grp to its service_queue to prepare for that. As currently only the throtl_data->service_queue is in use, this patch just ends up moving throtl_grp->bio_lists[] and ->nr_queued[] to throtl_grp->service_queue.bio_lists[] and ->nr_queued[] without making any functional differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 63 +++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 7340440ccfb5..6f57f94c3c57 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -27,6 +27,17 @@ static struct blkcg_policy blkcg_policy_throtl; static struct workqueue_struct *kthrotld_workqueue; struct throtl_service_queue { + /* + * Bios queued directly to this service_queue or dispatched from + * children throtl_grp's. + */ + struct bio_list bio_lists[2]; /* queued bios [READ/WRITE] */ + unsigned int nr_queued[2]; /* number of queued bios */ + + /* + * RB tree of active children throtl_grp's, which are sorted by + * their ->disptime. + */ struct rb_root pending_tree; /* RB tree of active tgs */ struct rb_node *first_pending; /* first node in the tree */ unsigned int nr_pending; /* # queued in the tree */ @@ -69,12 +80,6 @@ struct throtl_grp { unsigned int flags; - /* Two lists for READ and WRITE */ - struct bio_list bio_lists[2]; - - /* Number of queued bios on READ and WRITE lists */ - unsigned int nr_queued[2]; - /* bytes per second rate limits */ uint64_t bps[2]; @@ -193,6 +198,8 @@ static void tg_stats_alloc_fn(struct work_struct *work) /* init a service_queue, assumes the caller zeroed it */ static void throtl_service_queue_init(struct throtl_service_queue *sq) { + bio_list_init(&sq->bio_lists[0]); + bio_list_init(&sq->bio_lists[1]); sq->pending_tree = RB_ROOT; } @@ -204,8 +211,6 @@ static void throtl_pd_init(struct blkcg_gq *blkg) throtl_service_queue_init(&tg->service_queue); RB_CLEAR_NODE(&tg->rb_node); tg->td = blkg->q->td; - bio_list_init(&tg->bio_lists[0]); - bio_list_init(&tg->bio_lists[1]); tg->bps[READ] = -1; tg->bps[WRITE] = -1; @@ -624,7 +629,8 @@ static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio, * this function with a different bio if there are other bios * queued. */ - BUG_ON(tg->nr_queued[rw] && bio != bio_list_peek(&tg->bio_lists[rw])); + BUG_ON(tg->service_queue.nr_queued[rw] && + bio != bio_list_peek(&tg->service_queue.bio_lists[rw])); /* If tg->bps = -1, then BW is unlimited */ if (tg->bps[rw] == -1 && tg->iops[rw] == -1) { @@ -703,12 +709,13 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, struct throtl_service_queue *parent_sq) { + struct throtl_service_queue *sq = &tg->service_queue; bool rw = bio_data_dir(bio); - bio_list_add(&tg->bio_lists[rw], bio); + bio_list_add(&sq->bio_lists[rw], bio); /* Take a bio reference on tg */ blkg_get(tg_to_blkg(tg)); - tg->nr_queued[rw]++; + sq->nr_queued[rw]++; tg->td->nr_queued[rw]++; throtl_enqueue_tg(tg, parent_sq); } @@ -716,13 +723,14 @@ static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, static void tg_update_disptime(struct throtl_grp *tg, struct throtl_service_queue *parent_sq) { + struct throtl_service_queue *sq = &tg->service_queue; unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime; struct bio *bio; - if ((bio = bio_list_peek(&tg->bio_lists[READ]))) + if ((bio = bio_list_peek(&sq->bio_lists[READ]))) tg_may_dispatch(tg, bio, &read_wait); - if ((bio = bio_list_peek(&tg->bio_lists[WRITE]))) + if ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) tg_may_dispatch(tg, bio, &write_wait); min_wait = min(read_wait, write_wait); @@ -737,10 +745,11 @@ static void tg_update_disptime(struct throtl_grp *tg, static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, struct bio_list *bl) { + struct throtl_service_queue *sq = &tg->service_queue; struct bio *bio; - bio = bio_list_pop(&tg->bio_lists[rw]); - tg->nr_queued[rw]--; + bio = bio_list_pop(&sq->bio_lists[rw]); + sq->nr_queued[rw]--; /* Drop bio reference on blkg */ blkg_put(tg_to_blkg(tg)); @@ -756,6 +765,7 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) { + struct throtl_service_queue *sq = &tg->service_queue; unsigned int nr_reads = 0, nr_writes = 0; unsigned int max_nr_reads = throtl_grp_quantum*3/4; unsigned int max_nr_writes = throtl_grp_quantum - max_nr_reads; @@ -763,7 +773,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) /* Try to dispatch 75% READS and 25% WRITES */ - while ((bio = bio_list_peek(&tg->bio_lists[READ])) && + while ((bio = bio_list_peek(&sq->bio_lists[READ])) && tg_may_dispatch(tg, bio, NULL)) { tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); @@ -773,7 +783,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) break; } - while ((bio = bio_list_peek(&tg->bio_lists[WRITE])) && + while ((bio = bio_list_peek(&sq->bio_lists[WRITE])) && tg_may_dispatch(tg, bio, NULL)) { tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); @@ -790,10 +800,10 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq, struct bio_list *bl) { unsigned int nr_disp = 0; - struct throtl_grp *tg; while (1) { - tg = throtl_rb_first(parent_sq); + struct throtl_grp *tg = throtl_rb_first(parent_sq); + struct throtl_service_queue *sq = &tg->service_queue; if (!tg) break; @@ -805,7 +815,7 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq, nr_disp += throtl_dispatch_tg(tg, bl); - if (tg->nr_queued[0] || tg->nr_queued[1]) + if (sq->nr_queued[0] || sq->nr_queued[1]) tg_update_disptime(tg, parent_sq); if (nr_disp >= throtl_quantum) @@ -1043,6 +1053,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) { struct throtl_data *td = q->td; struct throtl_grp *tg; + struct throtl_service_queue *sq; bool rw = bio_data_dir(bio), update_disptime = true; struct blkcg *blkcg; bool throttled = false; @@ -1077,7 +1088,9 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) if (unlikely(!tg)) goto out_unlock; - if (tg->nr_queued[rw]) { + sq = &tg->service_queue; + + if (sq->nr_queued[rw]) { /* * There is already another bio queued in same dir. No * need to update dispatch time. @@ -1112,7 +1125,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) rw == READ ? 'R' : 'W', tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], tg->io_disp[rw], tg->iops[rw], - tg->nr_queued[READ], tg->nr_queued[WRITE]); + sq->nr_queued[READ], sq->nr_queued[WRITE]); bio_associate_current(bio); throtl_add_bio_tg(bio, tg, &q->td->service_queue); @@ -1151,11 +1164,13 @@ void blk_throtl_drain(struct request_queue *q) bio_list_init(&bl); while ((tg = throtl_rb_first(parent_sq))) { + struct throtl_service_queue *sq = &tg->service_queue; + throtl_dequeue_tg(tg, parent_sq); - while ((bio = bio_list_peek(&tg->bio_lists[READ]))) + while ((bio = bio_list_peek(&sq->bio_lists[READ]))) tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); - while ((bio = bio_list_peek(&tg->bio_lists[WRITE]))) + while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); } spin_unlock_irq(q->queue_lock); -- GitLab From 651930bc1c2a2550fde93a8cfa1a201c363a0ca1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:35 -0700 Subject: [PATCH 0045/2900] blk-throttle: dispatch to throtl_data->service_queue.bio_lists[] throtl_service_queues will eventually form a tree which is anchored at throtl_data->service_queue and queue bios will climb the tree to the top service_queue to be executed. This patch makes the dispatch paths in blk_throtl_dispatch_work_fn() and blk_throtl_drain() to dispatch bios to throtl_data->service_queue.bio_lists[] instead of the on-stack bio_lists. This will keep the final dispatch to the top level service_queue share the same mechanism as dispatches through the rest of the hierarchy. As bio's should be issued in a sleepable context, blk_throtl_dispatch_work_fn() transfers all dispatched bio's from the service_queue bio_lists[] into an onstack one before dropping queue_lock and issuing the bio's. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 6f57f94c3c57..154bd63719c5 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -743,7 +743,7 @@ static void tg_update_disptime(struct throtl_grp *tg, } static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, - struct bio_list *bl) + struct throtl_service_queue *parent_sq) { struct throtl_service_queue *sq = &tg->service_queue; struct bio *bio; @@ -757,13 +757,14 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, tg->td->nr_queued[rw]--; throtl_charge_bio(tg, bio); - bio_list_add(bl, bio); + bio_list_add(&parent_sq->bio_lists[rw], bio); bio->bi_rw |= REQ_THROTTLED; throtl_trim_slice(tg, rw); } -static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) +static int throtl_dispatch_tg(struct throtl_grp *tg, + struct throtl_service_queue *parent_sq) { struct throtl_service_queue *sq = &tg->service_queue; unsigned int nr_reads = 0, nr_writes = 0; @@ -776,7 +777,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) while ((bio = bio_list_peek(&sq->bio_lists[READ])) && tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); nr_reads++; if (nr_reads >= max_nr_reads) @@ -786,7 +787,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) while ((bio = bio_list_peek(&sq->bio_lists[WRITE])) && tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(tg, bio_data_dir(bio), bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); nr_writes++; if (nr_writes >= max_nr_writes) @@ -796,8 +797,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, struct bio_list *bl) return nr_reads + nr_writes; } -static int throtl_select_dispatch(struct throtl_service_queue *parent_sq, - struct bio_list *bl) +static int throtl_select_dispatch(struct throtl_service_queue *parent_sq) { unsigned int nr_disp = 0; @@ -813,7 +813,7 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq, throtl_dequeue_tg(tg, parent_sq); - nr_disp += throtl_dispatch_tg(tg, bl); + nr_disp += throtl_dispatch_tg(tg, parent_sq); if (sq->nr_queued[0] || sq->nr_queued[1]) tg_update_disptime(tg, parent_sq); @@ -830,11 +830,13 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) { struct throtl_data *td = container_of(to_delayed_work(work), struct throtl_data, dispatch_work); + struct throtl_service_queue *sq = &td->service_queue; struct request_queue *q = td->queue; unsigned int nr_disp = 0; struct bio_list bio_list_on_stack; struct bio *bio; struct blk_plug plug; + int rw; spin_lock_irq(q->queue_lock); @@ -844,10 +846,15 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) td->nr_queued[READ] + td->nr_queued[WRITE], td->nr_queued[READ], td->nr_queued[WRITE]); - nr_disp = throtl_select_dispatch(&td->service_queue, &bio_list_on_stack); + nr_disp = throtl_select_dispatch(sq); - if (nr_disp) + if (nr_disp) { + for (rw = READ; rw <= WRITE; rw++) { + bio_list_merge(&bio_list_on_stack, &sq->bio_lists[rw]); + bio_list_init(&sq->bio_lists[rw]); + } throtl_log(td, "bios disp=%u", nr_disp); + } throtl_schedule_next_dispatch(td); @@ -1156,27 +1163,26 @@ void blk_throtl_drain(struct request_queue *q) struct throtl_data *td = q->td; struct throtl_service_queue *parent_sq = &td->service_queue; struct throtl_grp *tg; - struct bio_list bl; struct bio *bio; + int rw; queue_lockdep_assert_held(q); - bio_list_init(&bl); - while ((tg = throtl_rb_first(parent_sq))) { struct throtl_service_queue *sq = &tg->service_queue; throtl_dequeue_tg(tg, parent_sq); while ((bio = bio_list_peek(&sq->bio_lists[READ]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio), &bl); + tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); } spin_unlock_irq(q->queue_lock); - while ((bio = bio_list_pop(&bl))) - generic_make_request(bio); + for (rw = READ; rw <= WRITE; rw++) + while ((bio = bio_list_pop(&parent_sq->bio_lists[rw]))) + generic_make_request(bio); spin_lock_irq(q->queue_lock); } -- GitLab From 0e9f4164ba915052918a77ecb2a59822dbfd661c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:35 -0700 Subject: [PATCH 0046/2900] blk-throttle: generalize update_disptime optimization in blk_throtl_bio() When blk_throtl_bio() wants to queue a bio to a tg (throtl_grp), it avoids invoking tg_update_disptime() and throtl_schedule_next_dispatch() if the tg already has bios queued in that direction. As a new bio is appeneded after the existing ones, it can't change the tg's next dispatch time or the parent's dispatch schedule. This optimization is currently open coded in blk_throtl_bio(). Whether the target biolist was occupied was recorded in a local variable and later used to skip disptime update. This patch moves generalizes it so that throtl_add_bio_tg() sets a new flag THROTL_TG_WAS_EMPTY if the biolist was empty before the new bio was added. tg_update_disptime() clears the flag automatically. blk_throtl_bio() is updated to simply test the flag before updating disptime. This patch doesn't make any functional differences now but will enable using the same optimization for recursive dispatch. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 154bd63719c5..ec9397f3eb0a 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -46,6 +46,7 @@ struct throtl_service_queue { enum tg_state_flags { THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */ + THROTL_TG_WAS_EMPTY = 1 << 1, /* bio_lists[] became non-empty */ }; #define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) @@ -712,6 +713,15 @@ static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, struct throtl_service_queue *sq = &tg->service_queue; bool rw = bio_data_dir(bio); + /* + * If @tg doesn't currently have any bios queued in the same + * direction, queueing @bio can change when @tg should be + * dispatched. Mark that @tg was empty. This is automatically + * cleaered on the next tg_update_disptime(). + */ + if (!sq->nr_queued[rw]) + tg->flags |= THROTL_TG_WAS_EMPTY; + bio_list_add(&sq->bio_lists[rw], bio); /* Take a bio reference on tg */ blkg_get(tg_to_blkg(tg)); @@ -740,6 +750,9 @@ static void tg_update_disptime(struct throtl_grp *tg, throtl_dequeue_tg(tg, parent_sq); tg->disptime = disptime; throtl_enqueue_tg(tg, parent_sq); + + /* see throtl_add_bio_tg() */ + tg->flags &= ~THROTL_TG_WAS_EMPTY; } static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, @@ -1061,7 +1074,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) struct throtl_data *td = q->td; struct throtl_grp *tg; struct throtl_service_queue *sq; - bool rw = bio_data_dir(bio), update_disptime = true; + bool rw = bio_data_dir(bio); struct blkcg *blkcg; bool throttled = false; @@ -1097,16 +1110,10 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) sq = &tg->service_queue; - if (sq->nr_queued[rw]) { - /* - * There is already another bio queued in same dir. No - * need to update dispatch time. - */ - update_disptime = false; + /* throtl is FIFO - if other bios are already queued, should queue */ + if (sq->nr_queued[rw]) goto queue_bio; - } - /* Bio is with-in rate limit of group */ if (tg_may_dispatch(tg, bio, NULL)) { throtl_charge_bio(tg, bio); @@ -1138,7 +1145,8 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) throtl_add_bio_tg(bio, tg, &q->td->service_queue); throttled = true; - if (update_disptime) { + /* update @tg's dispatch time if @tg was empty before @bio */ + if (tg->flags & THROTL_TG_WAS_EMPTY) { tg_update_disptime(tg, &td->service_queue); throtl_schedule_next_dispatch(td); } -- GitLab From 77216b0484817817a18aaa6b089dffe49070f7c1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:36 -0700 Subject: [PATCH 0047/2900] blk-throttle: add throtl_service_queue->parent_sq To prepare for hierarchy support, this patch adds throtl_service_queue->service_sq which points to the arent service_queue. Currently, for all service_queues embedded in throtl_grps, it points to throtl_data->service_queue. As throtl_data->service_queue doesn't have a parent its parent_sq is set to NULL. There are a number of functions which take both throtl_grp *tg and throtl_service_queue *parent_sq. With this patch, the parent service_queue can be determined from @tg and the @parent_sq arguments are removed. This patch doesn't make any behavior differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 81 +++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index ec9397f3eb0a..00cfdd05f98f 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -27,6 +27,8 @@ static struct blkcg_policy blkcg_policy_throtl; static struct workqueue_struct *kthrotld_workqueue; struct throtl_service_queue { + struct throtl_service_queue *parent_sq; /* the parent service_queue */ + /* * Bios queued directly to this service_queue or dispatched from * children throtl_grp's. @@ -197,21 +199,24 @@ static void tg_stats_alloc_fn(struct work_struct *work) } /* init a service_queue, assumes the caller zeroed it */ -static void throtl_service_queue_init(struct throtl_service_queue *sq) +static void throtl_service_queue_init(struct throtl_service_queue *sq, + struct throtl_service_queue *parent_sq) { bio_list_init(&sq->bio_lists[0]); bio_list_init(&sq->bio_lists[1]); sq->pending_tree = RB_ROOT; + sq->parent_sq = parent_sq; } static void throtl_pd_init(struct blkcg_gq *blkg) { struct throtl_grp *tg = blkg_to_tg(blkg); + struct throtl_data *td = blkg->q->td; unsigned long flags; - throtl_service_queue_init(&tg->service_queue); + throtl_service_queue_init(&tg->service_queue, &td->service_queue); RB_CLEAR_NODE(&tg->rb_node); - tg->td = blkg->q->td; + tg->td = td; tg->bps[READ] = -1; tg->bps[WRITE] = -1; @@ -339,9 +344,9 @@ static void update_min_dispatch_time(struct throtl_service_queue *parent_sq) parent_sq->first_pending_disptime = tg->disptime; } -static void tg_service_queue_add(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void tg_service_queue_add(struct throtl_grp *tg) { + struct throtl_service_queue *parent_sq = tg->service_queue.parent_sq; struct rb_node **node = &parent_sq->pending_tree.rb_node; struct rb_node *parent = NULL; struct throtl_grp *__tg; @@ -367,33 +372,29 @@ static void tg_service_queue_add(struct throtl_grp *tg, rb_insert_color(&tg->rb_node, &parent_sq->pending_tree); } -static void __throtl_enqueue_tg(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void __throtl_enqueue_tg(struct throtl_grp *tg) { - tg_service_queue_add(tg, parent_sq); + tg_service_queue_add(tg); tg->flags |= THROTL_TG_PENDING; - parent_sq->nr_pending++; + tg->service_queue.parent_sq->nr_pending++; } -static void throtl_enqueue_tg(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void throtl_enqueue_tg(struct throtl_grp *tg) { if (!(tg->flags & THROTL_TG_PENDING)) - __throtl_enqueue_tg(tg, parent_sq); + __throtl_enqueue_tg(tg); } -static void __throtl_dequeue_tg(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void __throtl_dequeue_tg(struct throtl_grp *tg) { - throtl_rb_erase(&tg->rb_node, parent_sq); + throtl_rb_erase(&tg->rb_node, tg->service_queue.parent_sq); tg->flags &= ~THROTL_TG_PENDING; } -static void throtl_dequeue_tg(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void throtl_dequeue_tg(struct throtl_grp *tg) { if (tg->flags & THROTL_TG_PENDING) - __throtl_dequeue_tg(tg, parent_sq); + __throtl_dequeue_tg(tg); } /* Call with queue lock held */ @@ -707,8 +708,7 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, bio->bi_rw); } -static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg) { struct throtl_service_queue *sq = &tg->service_queue; bool rw = bio_data_dir(bio); @@ -727,11 +727,10 @@ static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg, blkg_get(tg_to_blkg(tg)); sq->nr_queued[rw]++; tg->td->nr_queued[rw]++; - throtl_enqueue_tg(tg, parent_sq); + throtl_enqueue_tg(tg); } -static void tg_update_disptime(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static void tg_update_disptime(struct throtl_grp *tg) { struct throtl_service_queue *sq = &tg->service_queue; unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime; @@ -747,16 +746,15 @@ static void tg_update_disptime(struct throtl_grp *tg, disptime = jiffies + min_wait; /* Update dispatch time */ - throtl_dequeue_tg(tg, parent_sq); + throtl_dequeue_tg(tg); tg->disptime = disptime; - throtl_enqueue_tg(tg, parent_sq); + throtl_enqueue_tg(tg); /* see throtl_add_bio_tg() */ tg->flags &= ~THROTL_TG_WAS_EMPTY; } -static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, - struct throtl_service_queue *parent_sq) +static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) { struct throtl_service_queue *sq = &tg->service_queue; struct bio *bio; @@ -770,14 +768,13 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw, tg->td->nr_queued[rw]--; throtl_charge_bio(tg, bio); - bio_list_add(&parent_sq->bio_lists[rw], bio); + bio_list_add(&sq->parent_sq->bio_lists[rw], bio); bio->bi_rw |= REQ_THROTTLED; throtl_trim_slice(tg, rw); } -static int throtl_dispatch_tg(struct throtl_grp *tg, - struct throtl_service_queue *parent_sq) +static int throtl_dispatch_tg(struct throtl_grp *tg) { struct throtl_service_queue *sq = &tg->service_queue; unsigned int nr_reads = 0, nr_writes = 0; @@ -790,7 +787,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, while ((bio = bio_list_peek(&sq->bio_lists[READ])) && tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); + tg_dispatch_one_bio(tg, bio_data_dir(bio)); nr_reads++; if (nr_reads >= max_nr_reads) @@ -800,7 +797,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg, while ((bio = bio_list_peek(&sq->bio_lists[WRITE])) && tg_may_dispatch(tg, bio, NULL)) { - tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); + tg_dispatch_one_bio(tg, bio_data_dir(bio)); nr_writes++; if (nr_writes >= max_nr_writes) @@ -824,12 +821,12 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq) if (time_before(jiffies, tg->disptime)) break; - throtl_dequeue_tg(tg, parent_sq); + throtl_dequeue_tg(tg); - nr_disp += throtl_dispatch_tg(tg, parent_sq); + nr_disp += throtl_dispatch_tg(tg); if (sq->nr_queued[0] || sq->nr_queued[1]) - tg_update_disptime(tg, parent_sq); + tg_update_disptime(tg); if (nr_disp >= throtl_quantum) break; @@ -991,7 +988,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, throtl_start_new_slice(tg, 1); if (tg->flags & THROTL_TG_PENDING) { - tg_update_disptime(tg, &td->service_queue); + tg_update_disptime(tg); throtl_schedule_next_dispatch(td); } @@ -1142,12 +1139,12 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) sq->nr_queued[READ], sq->nr_queued[WRITE]); bio_associate_current(bio); - throtl_add_bio_tg(bio, tg, &q->td->service_queue); + throtl_add_bio_tg(bio, tg); throttled = true; /* update @tg's dispatch time if @tg was empty before @bio */ if (tg->flags & THROTL_TG_WAS_EMPTY) { - tg_update_disptime(tg, &td->service_queue); + tg_update_disptime(tg); throtl_schedule_next_dispatch(td); } @@ -1179,12 +1176,12 @@ void blk_throtl_drain(struct request_queue *q) while ((tg = throtl_rb_first(parent_sq))) { struct throtl_service_queue *sq = &tg->service_queue; - throtl_dequeue_tg(tg, parent_sq); + throtl_dequeue_tg(tg); while ((bio = bio_list_peek(&sq->bio_lists[READ]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); + tg_dispatch_one_bio(tg, bio_data_dir(bio)); while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio), parent_sq); + tg_dispatch_one_bio(tg, bio_data_dir(bio)); } spin_unlock_irq(q->queue_lock); @@ -1205,7 +1202,7 @@ int blk_throtl_init(struct request_queue *q) return -ENOMEM; INIT_DELAYED_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); - throtl_service_queue_init(&td->service_queue); + throtl_service_queue_init(&td->service_queue, NULL); q->td = td; td->queue = q; -- GitLab From fda6f272c77a7acd798bb247fadc4791574e698b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:36 -0700 Subject: [PATCH 0048/2900] blk-throttle: implement sq_to_tg(), sq_to_td() and throtl_log() Now that both throtl_data and throtl_grp embed throtl_service_queue, we can unify throtl_log() and throtl_log_tg(). * sq_to_tg() is added. This returns the throtl_grp a service_queue is embedded in. If the service_queue is the top-level one embedded in throtl_data, NULL is returned. * sq_to_td() is added. A service_queue is always associated with a throtl_data. This function finds the associated td and returns it. * throtl_log() is updated to take throtl_service_queue instead of throtl_data. If the service_queue is one embedded in throtl_grp, it prints the same header as throtl_log_tg() did. If it's one embedded in throtl_data, it behaves the same as before. This renders throtl_log_tg() unnecessary. Removed. This change is necessary for hierarchy support as we're gonna be using the same code paths to dispatch bios to intermediate service_queues embedded in throtl_grps and the top-level service_queue embedded in throtl_data. This patch doesn't make any behavior changes. v2: throtl_log() didn't print a space after blkg path. Updated so that it prints a space after throtl_grp path. Spotted by Vivek. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 110 +++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 29 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 00cfdd05f98f..2875ff66e1b9 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -151,16 +151,65 @@ static inline struct throtl_grp *td_root_tg(struct throtl_data *td) return blkg_to_tg(td->queue->root_blkg); } -#define throtl_log_tg(tg, fmt, args...) do { \ - char __pbuf[128]; \ +/** + * sq_to_tg - return the throl_grp the specified service queue belongs to + * @sq: the throtl_service_queue of interest + * + * Return the throtl_grp @sq belongs to. If @sq is the top-level one + * embedded in throtl_data, %NULL is returned. + */ +static struct throtl_grp *sq_to_tg(struct throtl_service_queue *sq) +{ + if (sq && sq->parent_sq) + return container_of(sq, struct throtl_grp, service_queue); + else + return NULL; +} + +/** + * sq_to_td - return throtl_data the specified service queue belongs to + * @sq: the throtl_service_queue of interest + * + * A service_queue can be embeded in either a throtl_grp or throtl_data. + * Determine the associated throtl_data accordingly and return it. + */ +static struct throtl_data *sq_to_td(struct throtl_service_queue *sq) +{ + struct throtl_grp *tg = sq_to_tg(sq); + + if (tg) + return tg->td; + else + return container_of(sq, struct throtl_data, service_queue); +} + +/** + * throtl_log - log debug message via blktrace + * @sq: the service_queue being reported + * @fmt: printf format string + * @args: printf args + * + * The messages are prefixed with "throtl BLKG_NAME" if @sq belongs to a + * throtl_grp; otherwise, just "throtl". + * + * TODO: this should be made a function and name formatting should happen + * after testing whether blktrace is enabled. + */ +#define throtl_log(sq, fmt, args...) do { \ + struct throtl_grp *__tg = sq_to_tg((sq)); \ + struct throtl_data *__td = sq_to_td((sq)); \ + \ + (void)__td; \ + if ((__tg)) { \ + char __pbuf[128]; \ \ - blkg_path(tg_to_blkg(tg), __pbuf, sizeof(__pbuf)); \ - blk_add_trace_msg((tg)->td->queue, "throtl %s " fmt, __pbuf, ##args); \ + blkg_path(tg_to_blkg(__tg), __pbuf, sizeof(__pbuf)); \ + blk_add_trace_msg(__td->queue, "throtl %s " fmt, __pbuf, ##args); \ + } else { \ + blk_add_trace_msg(__td->queue, "throtl " fmt, ##args); \ + } \ } while (0) -#define throtl_log(td, fmt, args...) \ - blk_add_trace_msg((td)->queue, "throtl " fmt, ##args) - /* * Worker for allocating per cpu stat for tgs. This is scheduled on the * system_wq once there are some groups on the alloc_list waiting for @@ -402,9 +451,10 @@ static void throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) { struct delayed_work *dwork = &td->dispatch_work; + struct throtl_service_queue *sq = &td->service_queue; mod_delayed_work(kthrotld_workqueue, dwork, delay); - throtl_log(td, "schedule work. delay=%lu jiffies=%lu", delay, jiffies); + throtl_log(sq, "schedule work. delay=%lu jiffies=%lu", delay, jiffies); } static void throtl_schedule_next_dispatch(struct throtl_data *td) @@ -429,9 +479,10 @@ static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw) tg->io_disp[rw] = 0; tg->slice_start[rw] = jiffies; tg->slice_end[rw] = jiffies + throtl_slice; - throtl_log_tg(tg, "[%c] new slice start=%lu end=%lu jiffies=%lu", - rw == READ ? 'R' : 'W', tg->slice_start[rw], - tg->slice_end[rw], jiffies); + throtl_log(&tg->service_queue, + "[%c] new slice start=%lu end=%lu jiffies=%lu", + rw == READ ? 'R' : 'W', tg->slice_start[rw], + tg->slice_end[rw], jiffies); } static inline void throtl_set_slice_end(struct throtl_grp *tg, bool rw, @@ -444,9 +495,10 @@ static inline void throtl_extend_slice(struct throtl_grp *tg, bool rw, unsigned long jiffy_end) { tg->slice_end[rw] = roundup(jiffy_end, throtl_slice); - throtl_log_tg(tg, "[%c] extend slice start=%lu end=%lu jiffies=%lu", - rw == READ ? 'R' : 'W', tg->slice_start[rw], - tg->slice_end[rw], jiffies); + throtl_log(&tg->service_queue, + "[%c] extend slice start=%lu end=%lu jiffies=%lu", + rw == READ ? 'R' : 'W', tg->slice_start[rw], + tg->slice_end[rw], jiffies); } /* Determine if previously allocated or extended slice is complete or not */ @@ -511,10 +563,10 @@ static inline void throtl_trim_slice(struct throtl_grp *tg, bool rw) tg->slice_start[rw] += nr_slices * throtl_slice; - throtl_log_tg(tg, "[%c] trim slice nr=%lu bytes=%llu io=%lu" - " start=%lu end=%lu jiffies=%lu", - rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim, - tg->slice_start[rw], tg->slice_end[rw], jiffies); + throtl_log(&tg->service_queue, + "[%c] trim slice nr=%lu bytes=%llu io=%lu start=%lu end=%lu jiffies=%lu", + rw == READ ? 'R' : 'W', nr_slices, bytes_trim, io_trim, + tg->slice_start[rw], tg->slice_end[rw], jiffies); } static bool tg_with_in_iops_limit(struct throtl_grp *tg, struct bio *bio, @@ -852,7 +904,7 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) bio_list_init(&bio_list_on_stack); - throtl_log(td, "dispatch nr_queued=%u read=%u write=%u", + throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", td->nr_queued[READ] + td->nr_queued[WRITE], td->nr_queued[READ], td->nr_queued[WRITE]); @@ -863,7 +915,7 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) bio_list_merge(&bio_list_on_stack, &sq->bio_lists[rw]); bio_list_init(&sq->bio_lists[rw]); } - throtl_log(td, "bios disp=%u", nr_disp); + throtl_log(sq, "bios disp=%u", nr_disp); } throtl_schedule_next_dispatch(td); @@ -972,9 +1024,10 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, else *(unsigned int *)((void *)tg + cft->private) = ctx.v; - throtl_log_tg(tg, "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", - tg->bps[READ], tg->bps[WRITE], - tg->iops[READ], tg->iops[WRITE]); + throtl_log(&tg->service_queue, + "limit change rbps=%llu wbps=%llu riops=%u wiops=%u", + tg->bps[READ], tg->bps[WRITE], + tg->iops[READ], tg->iops[WRITE]); /* * We're already holding queue_lock and know @tg is valid. Let's @@ -1131,12 +1184,11 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) } queue_bio: - throtl_log_tg(tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu" - " iodisp=%u iops=%u queued=%d/%d", - rw == READ ? 'R' : 'W', - tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], - tg->io_disp[rw], tg->iops[rw], - sq->nr_queued[READ], sq->nr_queued[WRITE]); + throtl_log(sq, "[%c] bio. bdisp=%llu sz=%u bps=%llu iodisp=%u iops=%u queued=%d/%d", + rw == READ ? 'R' : 'W', + tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], + tg->io_disp[rw], tg->iops[rw], + sq->nr_queued[READ], sq->nr_queued[WRITE]); bio_associate_current(bio); throtl_add_bio_tg(bio, tg); -- GitLab From 2a0f61e6ecd08d260054bde4b096ff207ce5350f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:36 -0700 Subject: [PATCH 0049/2900] blk-throttle: set REQ_THROTTLED from throtl_charge_bio() and gate stats update with it With proper hierarchy support, a bio can be dispatched multiple times until it reaches the top-level service_queue and we don't want to update dispatch stats at each step. They are local stats and will be kept local. If recursive stats are necessary, they should be implemented separately and definitely not by updating counters recursively on each dispatch. This patch moves REQ_THROTTLED setting to throtl_charge_bio() and gate stats update with it so that dispatch stats are updated only on the first time the bio is charged to a throtl_grp, which will always be the throtl_grp the bio was originally queued to. This means that REQ_THROTTLED would be set even for bios which don't get throttled. As we don't want bios to leave blk-throtl with the flag set, move REQ_THROTLLED clearing to the end of blk_throtl_bio() and clear if the bio is being issued directly. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 2875ff66e1b9..420eaa150d11 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -757,7 +757,22 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) tg->bytes_disp[rw] += bio->bi_size; tg->io_disp[rw]++; - throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, bio->bi_rw); + /* + * REQ_THROTTLED is used to prevent the same bio to be throttled + * more than once as a throttled bio will go through blk-throtl the + * second time when it eventually gets issued. Set it when a bio + * is being charged to a tg. + * + * Dispatch stats aren't recursive and each @bio should only be + * accounted by the @tg it was originally associated with. Let's + * update the stats when setting REQ_THROTTLED for the first time + * which is guaranteed to be for the @bio's original tg. + */ + if (!(bio->bi_rw & REQ_THROTTLED)) { + bio->bi_rw |= REQ_THROTTLED; + throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, + bio->bi_rw); + } } static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg) @@ -821,7 +836,6 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) throtl_charge_bio(tg, bio); bio_list_add(&sq->parent_sq->bio_lists[rw], bio); - bio->bi_rw |= REQ_THROTTLED; throtl_trim_slice(tg, rw); } @@ -1128,10 +1142,9 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) struct blkcg *blkcg; bool throttled = false; - if (bio->bi_rw & REQ_THROTTLED) { - bio->bi_rw &= ~REQ_THROTTLED; + /* see throtl_charge_bio() */ + if (bio->bi_rw & REQ_THROTTLED) goto out; - } /* * A throtl_grp pointer retrieved under rcu can be used to access @@ -1205,6 +1218,13 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) out_unlock_rcu: rcu_read_unlock(); out: + /* + * As multiple blk-throtls may stack in the same issue path, we + * don't want bios to leave with the flag set. Clear the flag if + * being issued. + */ + if (!throttled) + bio->bi_rw &= ~REQ_THROTTLED; return throttled; } -- GitLab From 69df0ab030c94e851b77991c2f5e00bcf5294edc Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:36 -0700 Subject: [PATCH 0050/2900] blk-throttle: separate out throtl_service_queue->pending_timer from throtl_data->dispatch_work Currently, throtl_data->dispatch_work is a delayed_work item which handles both delayed dispatch and issuing bios. The two tasks will be separated to support proper hierarchy. To prepare for that, this patch separates out the timer into throtl_service_queue->pending_timer from throtl_data->dispatch_work and make the latter a work_struct. * As the timer is now per-service_queue, it's initialized and del_sync'd as its corresponding service_queue is created and destroyed. The timer, when triggered, simply schedules throtl_data->dispathc_work for execution. * throtl_schedule_delayed_work() is renamed to throtl_schedule_pending_timer() and takes @sq and @expires now. * Simiarly, throtl_schedule_next_dispatch() now takes @sq, which should be the parent_sq of the service_queue which just got a new bio or updated. As the parent_sq is always the top-level service_queue now, this doesn't change anything at this point. This patch doesn't introduce any behavior differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 68 +++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 420eaa150d11..a8d23f0cf357 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -44,6 +44,7 @@ struct throtl_service_queue { struct rb_node *first_pending; /* first node in the tree */ unsigned int nr_pending; /* # queued in the tree */ unsigned long first_pending_disptime; /* disptime of the first tg */ + struct timer_list pending_timer; /* fires on first_pending_disptime */ }; enum tg_state_flags { @@ -121,7 +122,7 @@ struct throtl_data unsigned int nr_undestroyed_grps; /* Work for dispatching throttled bios */ - struct delayed_work dispatch_work; + struct work_struct dispatch_work; }; /* list and work item to allocate percpu group stats */ @@ -131,6 +132,8 @@ static LIST_HEAD(tg_stats_alloc_list); static void tg_stats_alloc_fn(struct work_struct *); static DECLARE_DELAYED_WORK(tg_stats_alloc_work, tg_stats_alloc_fn); +static void throtl_pending_timer_fn(unsigned long arg); + static inline struct throtl_grp *pd_to_tg(struct blkg_policy_data *pd) { return pd ? container_of(pd, struct throtl_grp, pd) : NULL; @@ -255,6 +258,13 @@ static void throtl_service_queue_init(struct throtl_service_queue *sq, bio_list_init(&sq->bio_lists[1]); sq->pending_tree = RB_ROOT; sq->parent_sq = parent_sq; + setup_timer(&sq->pending_timer, throtl_pending_timer_fn, + (unsigned long)sq); +} + +static void throtl_service_queue_exit(struct throtl_service_queue *sq) +{ + del_timer_sync(&sq->pending_timer); } static void throtl_pd_init(struct blkcg_gq *blkg) @@ -293,6 +303,8 @@ static void throtl_pd_exit(struct blkcg_gq *blkg) spin_unlock_irqrestore(&tg_stats_alloc_lock, flags); free_percpu(tg->stats_cpu); + + throtl_service_queue_exit(&tg->service_queue); } static void throtl_pd_reset_stats(struct blkcg_gq *blkg) @@ -447,19 +459,17 @@ static void throtl_dequeue_tg(struct throtl_grp *tg) } /* Call with queue lock held */ -static void throtl_schedule_delayed_work(struct throtl_data *td, - unsigned long delay) +static void throtl_schedule_pending_timer(struct throtl_service_queue *sq, + unsigned long expires) { - struct delayed_work *dwork = &td->dispatch_work; - struct throtl_service_queue *sq = &td->service_queue; - - mod_delayed_work(kthrotld_workqueue, dwork, delay); - throtl_log(sq, "schedule work. delay=%lu jiffies=%lu", delay, jiffies); + mod_timer(&sq->pending_timer, expires); + throtl_log(sq, "schedule timer. delay=%lu jiffies=%lu", + expires - jiffies, jiffies); } -static void throtl_schedule_next_dispatch(struct throtl_data *td) +static void throtl_schedule_next_dispatch(struct throtl_service_queue *sq) { - struct throtl_service_queue *sq = &td->service_queue; + struct throtl_data *td = sq_to_td(sq); /* any pending children left? */ if (!sq->nr_pending) @@ -467,10 +477,14 @@ static void throtl_schedule_next_dispatch(struct throtl_data *td) update_min_dispatch_time(sq); - if (time_before_eq(sq->first_pending_disptime, jiffies)) - throtl_schedule_delayed_work(td, 0); - else - throtl_schedule_delayed_work(td, sq->first_pending_disptime - jiffies); + /* is the next dispatch time in the future? */ + if (time_after(sq->first_pending_disptime, jiffies)) { + throtl_schedule_pending_timer(sq, sq->first_pending_disptime); + return; + } + + /* kick immediate execution */ + queue_work(kthrotld_workqueue, &td->dispatch_work); } static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw) @@ -901,11 +915,19 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq) return nr_disp; } +static void throtl_pending_timer_fn(unsigned long arg) +{ + struct throtl_service_queue *sq = (void *)arg; + struct throtl_data *td = sq_to_td(sq); + + queue_work(kthrotld_workqueue, &td->dispatch_work); +} + /* work function to dispatch throttled bios */ void blk_throtl_dispatch_work_fn(struct work_struct *work) { - struct throtl_data *td = container_of(to_delayed_work(work), - struct throtl_data, dispatch_work); + struct throtl_data *td = container_of(work, struct throtl_data, + dispatch_work); struct throtl_service_queue *sq = &td->service_queue; struct request_queue *q = td->queue; unsigned int nr_disp = 0; @@ -932,7 +954,7 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) throtl_log(sq, "bios disp=%u", nr_disp); } - throtl_schedule_next_dispatch(td); + throtl_schedule_next_dispatch(sq); spin_unlock_irq(q->queue_lock); @@ -1020,7 +1042,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, struct blkcg *blkcg = cgroup_to_blkcg(cgrp); struct blkg_conf_ctx ctx; struct throtl_grp *tg; - struct throtl_data *td; + struct throtl_service_queue *sq; int ret; ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx); @@ -1028,7 +1050,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, return ret; tg = blkg_to_tg(ctx.blkg); - td = ctx.blkg->q->td; + sq = &tg->service_queue; if (!ctx.v) ctx.v = -1; @@ -1056,7 +1078,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, if (tg->flags & THROTL_TG_PENDING) { tg_update_disptime(tg); - throtl_schedule_next_dispatch(td); + throtl_schedule_next_dispatch(sq->parent_sq); } blkg_conf_finish(&ctx); @@ -1121,7 +1143,7 @@ static void throtl_shutdown_wq(struct request_queue *q) { struct throtl_data *td = q->td; - cancel_delayed_work_sync(&td->dispatch_work); + cancel_work_sync(&td->dispatch_work); } static struct blkcg_policy blkcg_policy_throtl = { @@ -1210,7 +1232,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) /* update @tg's dispatch time if @tg was empty before @bio */ if (tg->flags & THROTL_TG_WAS_EMPTY) { tg_update_disptime(tg); - throtl_schedule_next_dispatch(td); + throtl_schedule_next_dispatch(tg->service_queue.parent_sq); } out_unlock: @@ -1273,7 +1295,7 @@ int blk_throtl_init(struct request_queue *q) if (!td) return -ENOMEM; - INIT_DELAYED_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); + INIT_WORK(&td->dispatch_work, blk_throtl_dispatch_work_fn); throtl_service_queue_init(&td->service_queue, NULL); q->td = td; -- GitLab From 7f52f98c2a83339b89a27d01296354e5dbb90ad0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:37 -0700 Subject: [PATCH 0051/2900] blk-throttle: implement dispatch looping throtl_select_dispatch() only dispatches throtl_quantum bios on each invocation. blk_throtl_dispatch_work_fn() in turn depends on throtl_schedule_next_dispatch() scheduling the next dispatch window immediately so that undue delays aren't incurred. This effectively chains multiple dispatch work item executions back-to-back when there are more than throtl_quantum bios to dispatch on a given tick. There is no reason to finish the current work item just to repeat it immediately. This patch makes throtl_schedule_next_dispatch() return %false without doing anything if the current dispatch window is still open and updates blk_throtl_dispatch_work_fn() repeat dispatching after cpu_relax() on %false return. This change will help implementing hierarchy support as dispatching will be done from pending_timer and immediate reschedule of timer function isn't supported and doesn't make much sense. While this patch changes how dispatch behaves when there are more than throtl_quantum bios to dispatch on a single tick, the behavior change is immaterial. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 82 ++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index a8d23f0cf357..8ee8e4e0a2ba 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -467,24 +467,41 @@ static void throtl_schedule_pending_timer(struct throtl_service_queue *sq, expires - jiffies, jiffies); } -static void throtl_schedule_next_dispatch(struct throtl_service_queue *sq) +/** + * throtl_schedule_next_dispatch - schedule the next dispatch cycle + * @sq: the service_queue to schedule dispatch for + * @force: force scheduling + * + * Arm @sq->pending_timer so that the next dispatch cycle starts on the + * dispatch time of the first pending child. Returns %true if either timer + * is armed or there's no pending child left. %false if the current + * dispatch window is still open and the caller should continue + * dispatching. + * + * If @force is %true, the dispatch timer is always scheduled and this + * function is guaranteed to return %true. This is to be used when the + * caller can't dispatch itself and needs to invoke pending_timer + * unconditionally. Note that forced scheduling is likely to induce short + * delay before dispatch starts even if @sq->first_pending_disptime is not + * in the future and thus shouldn't be used in hot paths. + */ +static bool throtl_schedule_next_dispatch(struct throtl_service_queue *sq, + bool force) { - struct throtl_data *td = sq_to_td(sq); - /* any pending children left? */ if (!sq->nr_pending) - return; + return true; update_min_dispatch_time(sq); /* is the next dispatch time in the future? */ - if (time_after(sq->first_pending_disptime, jiffies)) { + if (force || time_after(sq->first_pending_disptime, jiffies)) { throtl_schedule_pending_timer(sq, sq->first_pending_disptime); - return; + return true; } - /* kick immediate execution */ - queue_work(kthrotld_workqueue, &td->dispatch_work); + /* tell the caller to continue dispatching */ + return false; } static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw) @@ -930,39 +947,47 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) dispatch_work); struct throtl_service_queue *sq = &td->service_queue; struct request_queue *q = td->queue; - unsigned int nr_disp = 0; struct bio_list bio_list_on_stack; struct bio *bio; struct blk_plug plug; - int rw; + bool dispatched = false; + int rw, ret; spin_lock_irq(q->queue_lock); bio_list_init(&bio_list_on_stack); - throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", - td->nr_queued[READ] + td->nr_queued[WRITE], - td->nr_queued[READ], td->nr_queued[WRITE]); + while (true) { + throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", + td->nr_queued[READ] + td->nr_queued[WRITE], + td->nr_queued[READ], td->nr_queued[WRITE]); + + ret = throtl_select_dispatch(sq); + if (ret) { + for (rw = READ; rw <= WRITE; rw++) { + bio_list_merge(&bio_list_on_stack, &sq->bio_lists[rw]); + bio_list_init(&sq->bio_lists[rw]); + } + throtl_log(sq, "bios disp=%u", ret); + dispatched = true; + } - nr_disp = throtl_select_dispatch(sq); + if (throtl_schedule_next_dispatch(sq, false)) + break; - if (nr_disp) { - for (rw = READ; rw <= WRITE; rw++) { - bio_list_merge(&bio_list_on_stack, &sq->bio_lists[rw]); - bio_list_init(&sq->bio_lists[rw]); - } - throtl_log(sq, "bios disp=%u", nr_disp); + /* this dispatch windows is still open, relax and repeat */ + spin_unlock_irq(q->queue_lock); + cpu_relax(); + spin_lock_irq(q->queue_lock); } - throtl_schedule_next_dispatch(sq); - spin_unlock_irq(q->queue_lock); /* * If we dispatched some requests, unplug the queue to make sure * immediate dispatch */ - if (nr_disp) { + if (dispatched) { blk_start_plug(&plug); while((bio = bio_list_pop(&bio_list_on_stack))) generic_make_request(bio); @@ -1078,7 +1103,7 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, if (tg->flags & THROTL_TG_PENDING) { tg_update_disptime(tg); - throtl_schedule_next_dispatch(sq->parent_sq); + throtl_schedule_next_dispatch(sq->parent_sq, true); } blkg_conf_finish(&ctx); @@ -1229,10 +1254,15 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) throtl_add_bio_tg(bio, tg); throttled = true; - /* update @tg's dispatch time if @tg was empty before @bio */ + /* + * Update @tg's dispatch time and force schedule dispatch if @tg + * was empty before @bio. The forced scheduling isn't likely to + * cause undue delay as @bio is likely to be dispatched directly if + * its @tg's disptime is not in the future. + */ if (tg->flags & THROTL_TG_WAS_EMPTY) { tg_update_disptime(tg); - throtl_schedule_next_dispatch(tg->service_queue.parent_sq); + throtl_schedule_next_dispatch(tg->service_queue.parent_sq, true); } out_unlock: -- GitLab From 6e1a5704cbbd244a8db2d7d59215cf9a4c9a0d31 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:37 -0700 Subject: [PATCH 0052/2900] blk-throttle: dispatch from throtl_pending_timer_fn() Currently, blk_throtl_dispatch_work_fn() is responsible for both dispatching bio's from throtl_grp's according to their limits and then issuing the dispatched bios. This patch moves the dispatch part to throtl_pending_timer_fn() so that the work item is kicked iff there are bio's to issue. This is to avoid work item execution at each step when hierarchy support is enabled. bio's will be dispatched towards the top-level service_queue from the timers at each layer and the work item will only be used to issue the bio's which reached the top-level service_queue. While fetching bio's to issue from bio_lists[], blk_throtl_dispatch_work_fn() fetches all READs before WRITEs. While the original code also dispatched READs first, if multiple throtl_grps are dispatched on the same run, WRITEs from throtl_grp which is dispatched first would precede READs from throtl_grps which are dispatched later. While this is a behavior change, given that the previous code already prioritized READs and block layer generally prioritizes and segregates READs from WRITEs, this isn't likely to make any noticeable differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 69 ++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 8ee8e4e0a2ba..918d22240856 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -932,31 +932,26 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq) return nr_disp; } +/** + * throtl_pending_timer_fn - timer function for service_queue->pending_timer + * @arg: the throtl_service_queue being serviced + * + * This timer is armed when a child throtl_grp with active bio's become + * pending and queued on the service_queue's pending_tree and expires when + * the first child throtl_grp should be dispatched. This function + * dispatches bio's from the children throtl_grps and kicks + * throtl_data->dispatch_work if there are bio's ready to be issued. + */ static void throtl_pending_timer_fn(unsigned long arg) { struct throtl_service_queue *sq = (void *)arg; struct throtl_data *td = sq_to_td(sq); - - queue_work(kthrotld_workqueue, &td->dispatch_work); -} - -/* work function to dispatch throttled bios */ -void blk_throtl_dispatch_work_fn(struct work_struct *work) -{ - struct throtl_data *td = container_of(work, struct throtl_data, - dispatch_work); - struct throtl_service_queue *sq = &td->service_queue; struct request_queue *q = td->queue; - struct bio_list bio_list_on_stack; - struct bio *bio; - struct blk_plug plug; bool dispatched = false; - int rw, ret; + int ret; spin_lock_irq(q->queue_lock); - bio_list_init(&bio_list_on_stack); - while (true) { throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", td->nr_queued[READ] + td->nr_queued[WRITE], @@ -964,10 +959,6 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) ret = throtl_select_dispatch(sq); if (ret) { - for (rw = READ; rw <= WRITE; rw++) { - bio_list_merge(&bio_list_on_stack, &sq->bio_lists[rw]); - bio_list_init(&sq->bio_lists[rw]); - } throtl_log(sq, "bios disp=%u", ret); dispatched = true; } @@ -981,13 +972,41 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) spin_lock_irq(q->queue_lock); } + if (dispatched) + queue_work(kthrotld_workqueue, &td->dispatch_work); + spin_unlock_irq(q->queue_lock); +} - /* - * If we dispatched some requests, unplug the queue to make sure - * immediate dispatch - */ - if (dispatched) { +/** + * blk_throtl_dispatch_work_fn - work function for throtl_data->dispatch_work + * @work: work item being executed + * + * This function is queued for execution when bio's reach the bio_lists[] + * of throtl_data->service_queue. Those bio's are ready and issued by this + * function. + */ +void blk_throtl_dispatch_work_fn(struct work_struct *work) +{ + struct throtl_data *td = container_of(work, struct throtl_data, + dispatch_work); + struct throtl_service_queue *td_sq = &td->service_queue; + struct request_queue *q = td->queue; + struct bio_list bio_list_on_stack; + struct bio *bio; + struct blk_plug plug; + int rw; + + bio_list_init(&bio_list_on_stack); + + spin_lock_irq(q->queue_lock); + for (rw = READ; rw <= WRITE; rw++) { + bio_list_merge(&bio_list_on_stack, &td_sq->bio_lists[rw]); + bio_list_init(&td_sq->bio_lists[rw]); + } + spin_unlock_irq(q->queue_lock); + + if (!bio_list_empty(&bio_list_on_stack)) { blk_start_plug(&plug); while((bio = bio_list_pop(&bio_list_on_stack))) generic_make_request(bio); -- GitLab From 2a12f0dcdad1ba7c0e53bbff8e5f6d0ee7a29882 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:37 -0700 Subject: [PATCH 0053/2900] blk-throttle: make blk_throtl_drain() ready for hierarchy The current blk_throtl_drain() assumes that all active throtl_grps are queued on throtl_data->service_queue, which won't be true once hierarchy support is implemented. This patch makes blk_throtl_drain() perform post-order walk of the blkg hierarchy draining each associated throtl_grp, which guarantees that all bios will eventually be pushed to the top-level service_queue in throtl_data. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 51 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 918d22240856..8c6e13359781 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1299,6 +1299,28 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) return throttled; } +/* + * Dispatch all bios from all children tg's queued on @parent_sq. On + * return, @parent_sq is guaranteed to not have any active children tg's + * and all bios from previously active tg's are on @parent_sq->bio_lists[]. + */ +static void tg_drain_bios(struct throtl_service_queue *parent_sq) +{ + struct throtl_grp *tg; + + while ((tg = throtl_rb_first(parent_sq))) { + struct throtl_service_queue *sq = &tg->service_queue; + struct bio *bio; + + throtl_dequeue_tg(tg); + + while ((bio = bio_list_peek(&sq->bio_lists[READ]))) + tg_dispatch_one_bio(tg, bio_data_dir(bio)); + while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) + tg_dispatch_one_bio(tg, bio_data_dir(bio)); + } +} + /** * blk_throtl_drain - drain throttled bios * @q: request_queue to drain throttled bios for @@ -1309,27 +1331,34 @@ void blk_throtl_drain(struct request_queue *q) __releases(q->queue_lock) __acquires(q->queue_lock) { struct throtl_data *td = q->td; - struct throtl_service_queue *parent_sq = &td->service_queue; - struct throtl_grp *tg; + struct blkcg_gq *blkg; + struct cgroup *pos_cgrp; struct bio *bio; int rw; queue_lockdep_assert_held(q); + rcu_read_lock(); - while ((tg = throtl_rb_first(parent_sq))) { - struct throtl_service_queue *sq = &tg->service_queue; + /* + * Drain each tg while doing post-order walk on the blkg tree, so + * that all bios are propagated to td->service_queue. It'd be + * better to walk service_queue tree directly but blkg walk is + * easier. + */ + blkg_for_each_descendant_post(blkg, pos_cgrp, td->queue->root_blkg) + tg_drain_bios(&blkg_to_tg(blkg)->service_queue); - throtl_dequeue_tg(tg); + tg_drain_bios(&td_root_tg(td)->service_queue); - while ((bio = bio_list_peek(&sq->bio_lists[READ]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio)); - while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) - tg_dispatch_one_bio(tg, bio_data_dir(bio)); - } + /* finally, transfer bios from top-level tg's into the td */ + tg_drain_bios(&td->service_queue); + + rcu_read_unlock(); spin_unlock_irq(q->queue_lock); + /* all bios now should be in td->service_queue, issue them */ for (rw = READ; rw <= WRITE; rw++) - while ((bio = bio_list_pop(&parent_sq->bio_lists[rw]))) + while ((bio = bio_list_pop(&td->service_queue.bio_lists[rw]))) generic_make_request(bio); spin_lock_irq(q->queue_lock); -- GitLab From 9e660acffcd1b5adc4ec1ffba0cbb584f86b8907 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0054/2900] blk-throttle: make blk_throtl_bio() ready for hierarchy Currently, blk_throtl_bio() issues the passed in bio directly if it's within limits of its associated tg (throtl_grp). This behavior becomes incorrect with hierarchy support as the bio should be accounted to and throttled by the ancestor throtl_grps too. This patch makes the direct issue path of blk_throtl_bio() to loop until it reaches the top-level service_queue or gets throttled. If the former, the bio can be issued directly; otherwise, it gets queued at the first layer it was above limits. As tg->parent_sq is always the top-level service queue currently, this patch in itself doesn't make any behavior differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 8c6e13359781..52321a42cd78 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1239,12 +1239,16 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) sq = &tg->service_queue; - /* throtl is FIFO - if other bios are already queued, should queue */ - if (sq->nr_queued[rw]) - goto queue_bio; + while (true) { + /* throtl is FIFO - if bios are already queued, should queue */ + if (sq->nr_queued[rw]) + break; - /* Bio is with-in rate limit of group */ - if (tg_may_dispatch(tg, bio, NULL)) { + /* if above limits, break to queue */ + if (!tg_may_dispatch(tg, bio, NULL)) + break; + + /* within limits, let's charge and dispatch directly */ throtl_charge_bio(tg, bio); /* @@ -1259,10 +1263,19 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) * So keep on trimming slice even if bio is not queued. */ throtl_trim_slice(tg, rw); - goto out_unlock; + + /* + * @bio passed through this layer without being throttled. + * Climb up the ladder. If we''re already at the top, it + * can be executed directly. + */ + sq = sq->parent_sq; + tg = sq_to_tg(sq); + if (!tg) + goto out_unlock; } -queue_bio: + /* out-of-limit, queue to @tg */ throtl_log(sq, "[%c] bio. bdisp=%llu sz=%u bps=%llu iodisp=%u iops=%u queued=%d/%d", rw == READ ? 'R' : 'W', tg->bytes_disp[rw], bio->bi_size, tg->bps[rw], -- GitLab From 6bc9c2b464fb89eab705da87aa4284171d942369 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0055/2900] blk-throttle: make tg_dispatch_one_bio() ready for hierarchy tg_dispatch_one_bio() currently assumes that the parent_sq is the top level one and the bio being dispatched is ready to be issued; however, this assumption will be wrong with proper hierarchy support. This patch makes the following changes to make tg_dispatch_on_bio() ready for hiearchy. * throtl_data->nr_queued[] is incremented in blk_throtl_bio() instead of throtl_add_bio_tg() so that throtl_add_bio_tg() can be used to transfer a bio from a child tg to its parent. * tg_dispatch_one_bio() is updated to distinguish whether its parent is another throtl_grp or the throtl_data. If former, the bio is transferred to the parent throtl_grp using throtl_add_bio_tg(). If latter, the bio is ready to be issued and put on the top-level service_queue's bio_lists[] and throtl_data->nr_queued is decremented. As all throtl_grps currently have the top level service_queue as their ->parent_sq, this patch in itself doesn't make any behavior difference. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 52321a42cd78..04202617fda5 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -824,7 +824,6 @@ static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg) /* Take a bio reference on tg */ blkg_get(tg_to_blkg(tg)); sq->nr_queued[rw]++; - tg->td->nr_queued[rw]++; throtl_enqueue_tg(tg); } @@ -855,20 +854,34 @@ static void tg_update_disptime(struct throtl_grp *tg) static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) { struct throtl_service_queue *sq = &tg->service_queue; + struct throtl_service_queue *parent_sq = sq->parent_sq; + struct throtl_grp *parent_tg = sq_to_tg(parent_sq); struct bio *bio; bio = bio_list_pop(&sq->bio_lists[rw]); sq->nr_queued[rw]--; - /* Drop bio reference on blkg */ - blkg_put(tg_to_blkg(tg)); - - BUG_ON(tg->td->nr_queued[rw] <= 0); - tg->td->nr_queued[rw]--; throtl_charge_bio(tg, bio); - bio_list_add(&sq->parent_sq->bio_lists[rw], bio); + + /* + * If our parent is another tg, we just need to transfer @bio to + * the parent using throtl_add_bio_tg(). If our parent is + * @td->service_queue, @bio is ready to be issued. Put it on its + * bio_lists[] and decrease total number queued. The caller is + * responsible for issuing these bios. + */ + if (parent_tg) { + throtl_add_bio_tg(bio, parent_tg); + } else { + bio_list_add(&parent_sq->bio_lists[rw], bio); + BUG_ON(tg->td->nr_queued[rw] <= 0); + tg->td->nr_queued[rw]--; + } throtl_trim_slice(tg, rw); + + /* @bio is transferred to parent, drop its blkg reference */ + blkg_put(tg_to_blkg(tg)); } static int throtl_dispatch_tg(struct throtl_grp *tg) @@ -1283,6 +1296,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) sq->nr_queued[READ], sq->nr_queued[WRITE]); bio_associate_current(bio); + tg->td->nr_queued[rw]++; throtl_add_bio_tg(bio, tg); throttled = true; -- GitLab From 2e48a530a3a7daebd0cc17866304a36d39b611de Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0056/2900] blk-throttle: make throtl_pending_timer_fn() ready for hierarchy throtl_pending_timer_fn() currently assumes that the parent_sq is the top level one and the bio's dispatched are ready to be issued; however, this assumption will be wrong with proper hierarchy support. This patch makes the following changes to make throtl_pending_timer_fn() ready for hiearchy. * If the parent_sq isn't the top-level one, update the parent throtl_grp's dispatch time and schedule the next dispatch as necessary. If the parent's dispatch time is now, repeat the function for the parent throtl_grp. * If the parent_sq is the top-level one, kick issue work_item as before. * The debug message printed by throtl_log() now prints out the service_queue's nr_queued[] instead of the total nr_queued as the latter becomes uninteresting and misleading with hierarchical dispatch. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 04202617fda5..bc65077f6e43 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -952,23 +952,33 @@ static int throtl_select_dispatch(struct throtl_service_queue *parent_sq) * This timer is armed when a child throtl_grp with active bio's become * pending and queued on the service_queue's pending_tree and expires when * the first child throtl_grp should be dispatched. This function - * dispatches bio's from the children throtl_grps and kicks - * throtl_data->dispatch_work if there are bio's ready to be issued. + * dispatches bio's from the children throtl_grps to the parent + * service_queue. + * + * If the parent's parent is another throtl_grp, dispatching is propagated + * by either arming its pending_timer or repeating dispatch directly. If + * the top-level service_tree is reached, throtl_data->dispatch_work is + * kicked so that the ready bio's are issued. */ static void throtl_pending_timer_fn(unsigned long arg) { struct throtl_service_queue *sq = (void *)arg; + struct throtl_grp *tg = sq_to_tg(sq); struct throtl_data *td = sq_to_td(sq); struct request_queue *q = td->queue; - bool dispatched = false; + struct throtl_service_queue *parent_sq; + bool dispatched; int ret; spin_lock_irq(q->queue_lock); +again: + parent_sq = sq->parent_sq; + dispatched = false; while (true) { throtl_log(sq, "dispatch nr_queued=%u read=%u write=%u", - td->nr_queued[READ] + td->nr_queued[WRITE], - td->nr_queued[READ], td->nr_queued[WRITE]); + sq->nr_queued[READ] + sq->nr_queued[WRITE], + sq->nr_queued[READ], sq->nr_queued[WRITE]); ret = throtl_select_dispatch(sq); if (ret) { @@ -985,9 +995,25 @@ static void throtl_pending_timer_fn(unsigned long arg) spin_lock_irq(q->queue_lock); } - if (dispatched) - queue_work(kthrotld_workqueue, &td->dispatch_work); + if (!dispatched) + goto out_unlock; + if (parent_sq) { + /* @parent_sq is another throl_grp, propagate dispatch */ + if (tg->flags & THROTL_TG_WAS_EMPTY) { + tg_update_disptime(tg); + if (!throtl_schedule_next_dispatch(parent_sq, false)) { + /* window is already open, repeat dispatching */ + sq = parent_sq; + tg = sq_to_tg(sq); + goto again; + } + } + } else { + /* reached the top-level, queue issueing */ + queue_work(kthrotld_workqueue, &td->dispatch_work); + } +out_unlock: spin_unlock_irq(q->queue_lock); } -- GitLab From c5cc2070b45333f40a3f99319b83c8caeb62ec05 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0057/2900] blk-throttle: add throtl_qnode for dispatch fairness With flat hierarchy, there's only single level of dispatching happening and fairness beyond that point is the responsibility of the rest of the block layer and driver, which usually works out okay; however, with the planned hierarchy support, service_queue->bio_lists[] can be filled up by bios from a single source. While the limits would still be honored, it'd be very easy to starve IOs from siblings or children. To avoid such starvation, this patch implements throtl_qnode and converts service_queue->bio_lists[] to lists of per-source qnodes which in turn contains the bio's. For example, when a bio is dispatched from a child group, the bio doesn't get queued on ->bio_lists[] directly but it first gets queued on the group's qnode which in turn gets queued on service_queue->queued[]. When dispatching for the upper level, the ->queued[] list is consumed in round-robing order so that the dispatch windows is consumed fairly by all IO sources. There are two ways a bio can come to a throtl_grp - directly queued to the group or dispatched from a child. For the former throtl_grp->qnode_on_self[rw] is used. For the latter, the child's ->qnode_on_parent[rw]. Note that this means that the child which is contributing a bio to its parent should stay pinned until all its bios are dispatched to its grand-parent. This patch moves blkg refcnting from bio add/remove spots to qnode activation/deactivation so that the blkg containing an active qnode is always pinned. As child pins the parent, this is sufficient for keeping the relevant sub-tree pinned while bios are in flight. The starvation issue was spotted by Vivek Goyal. v2: The original patch used the same throtl_grp->qnode_on_self/parent for reads and writes causing RWs to be queued incorrectly if there already are outstanding IOs in the other direction. They should be throtl_grp->qnode_on_self/parent[2] so that READs and WRITEs can use different qnodes. Spotted by Vivek Goyal. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 201 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 176 insertions(+), 25 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index bc65077f6e43..541bd0dabb9a 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -26,6 +26,35 @@ static struct blkcg_policy blkcg_policy_throtl; /* A workqueue to queue throttle related work */ static struct workqueue_struct *kthrotld_workqueue; +/* + * To implement hierarchical throttling, throtl_grps form a tree and bios + * are dispatched upwards level by level until they reach the top and get + * issued. When dispatching bios from the children and local group at each + * level, if the bios are dispatched into a single bio_list, there's a risk + * of a local or child group which can queue many bios at once filling up + * the list starving others. + * + * To avoid such starvation, dispatched bios are queued separately + * according to where they came from. When they are again dispatched to + * the parent, they're popped in round-robin order so that no single source + * hogs the dispatch window. + * + * throtl_qnode is used to keep the queued bios separated by their sources. + * Bios are queued to throtl_qnode which in turn is queued to + * throtl_service_queue and then dispatched in round-robin order. + * + * It's also used to track the reference counts on blkg's. A qnode always + * belongs to a throtl_grp and gets queued on itself or the parent, so + * incrementing the reference of the associated throtl_grp when a qnode is + * queued and decrementing when dequeued is enough to keep the whole blkg + * tree pinned while bios are in flight. + */ +struct throtl_qnode { + struct list_head node; /* service_queue->queued[] */ + struct bio_list bios; /* queued bios */ + struct throtl_grp *tg; /* tg this qnode belongs to */ +}; + struct throtl_service_queue { struct throtl_service_queue *parent_sq; /* the parent service_queue */ @@ -33,7 +62,7 @@ struct throtl_service_queue { * Bios queued directly to this service_queue or dispatched from * children throtl_grp's. */ - struct bio_list bio_lists[2]; /* queued bios [READ/WRITE] */ + struct list_head queued[2]; /* throtl_qnode [READ/WRITE] */ unsigned int nr_queued[2]; /* number of queued bios */ /* @@ -75,6 +104,17 @@ struct throtl_grp { /* this group's service queue */ struct throtl_service_queue service_queue; + /* + * qnode_on_self is used when bios are directly queued to this + * throtl_grp so that local bios compete fairly with bios + * dispatched from children. qnode_on_parent is used when bios are + * dispatched from this throtl_grp into its parent and will compete + * with the sibling qnode_on_parents and the parent's + * qnode_on_self. + */ + struct throtl_qnode qnode_on_self[2]; + struct throtl_qnode qnode_on_parent[2]; + /* * Dispatch time in jiffies. This is the estimated time when group * will unthrottle and is ready to dispatch more bio. It is used as @@ -250,12 +290,95 @@ static void tg_stats_alloc_fn(struct work_struct *work) goto alloc_stats; } +static void throtl_qnode_init(struct throtl_qnode *qn, struct throtl_grp *tg) +{ + INIT_LIST_HEAD(&qn->node); + bio_list_init(&qn->bios); + qn->tg = tg; +} + +/** + * throtl_qnode_add_bio - add a bio to a throtl_qnode and activate it + * @bio: bio being added + * @qn: qnode to add bio to + * @queued: the service_queue->queued[] list @qn belongs to + * + * Add @bio to @qn and put @qn on @queued if it's not already on. + * @qn->tg's reference count is bumped when @qn is activated. See the + * comment on top of throtl_qnode definition for details. + */ +static void throtl_qnode_add_bio(struct bio *bio, struct throtl_qnode *qn, + struct list_head *queued) +{ + bio_list_add(&qn->bios, bio); + if (list_empty(&qn->node)) { + list_add_tail(&qn->node, queued); + blkg_get(tg_to_blkg(qn->tg)); + } +} + +/** + * throtl_peek_queued - peek the first bio on a qnode list + * @queued: the qnode list to peek + */ +static struct bio *throtl_peek_queued(struct list_head *queued) +{ + struct throtl_qnode *qn = list_first_entry(queued, struct throtl_qnode, node); + struct bio *bio; + + if (list_empty(queued)) + return NULL; + + bio = bio_list_peek(&qn->bios); + WARN_ON_ONCE(!bio); + return bio; +} + +/** + * throtl_pop_queued - pop the first bio form a qnode list + * @queued: the qnode list to pop a bio from + * @tg_to_put: optional out argument for throtl_grp to put + * + * Pop the first bio from the qnode list @queued. After popping, the first + * qnode is removed from @queued if empty or moved to the end of @queued so + * that the popping order is round-robin. + * + * When the first qnode is removed, its associated throtl_grp should be put + * too. If @tg_to_put is NULL, this function automatically puts it; + * otherwise, *@tg_to_put is set to the throtl_grp to put and the caller is + * responsible for putting it. + */ +static struct bio *throtl_pop_queued(struct list_head *queued, + struct throtl_grp **tg_to_put) +{ + struct throtl_qnode *qn = list_first_entry(queued, struct throtl_qnode, node); + struct bio *bio; + + if (list_empty(queued)) + return NULL; + + bio = bio_list_pop(&qn->bios); + WARN_ON_ONCE(!bio); + + if (bio_list_empty(&qn->bios)) { + list_del_init(&qn->node); + if (tg_to_put) + *tg_to_put = qn->tg; + else + blkg_put(tg_to_blkg(qn->tg)); + } else { + list_move_tail(&qn->node, queued); + } + + return bio; +} + /* init a service_queue, assumes the caller zeroed it */ static void throtl_service_queue_init(struct throtl_service_queue *sq, struct throtl_service_queue *parent_sq) { - bio_list_init(&sq->bio_lists[0]); - bio_list_init(&sq->bio_lists[1]); + INIT_LIST_HEAD(&sq->queued[0]); + INIT_LIST_HEAD(&sq->queued[1]); sq->pending_tree = RB_ROOT; sq->parent_sq = parent_sq; setup_timer(&sq->pending_timer, throtl_pending_timer_fn, @@ -272,8 +395,14 @@ static void throtl_pd_init(struct blkcg_gq *blkg) struct throtl_grp *tg = blkg_to_tg(blkg); struct throtl_data *td = blkg->q->td; unsigned long flags; + int rw; throtl_service_queue_init(&tg->service_queue, &td->service_queue); + for (rw = READ; rw <= WRITE; rw++) { + throtl_qnode_init(&tg->qnode_on_self[rw], tg); + throtl_qnode_init(&tg->qnode_on_parent[rw], tg); + } + RB_CLEAR_NODE(&tg->rb_node); tg->td = td; @@ -715,7 +844,7 @@ static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio, * queued. */ BUG_ON(tg->service_queue.nr_queued[rw] && - bio != bio_list_peek(&tg->service_queue.bio_lists[rw])); + bio != throtl_peek_queued(&tg->service_queue.queued[rw])); /* If tg->bps = -1, then BW is unlimited */ if (tg->bps[rw] == -1 && tg->iops[rw] == -1) { @@ -806,11 +935,24 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio) } } -static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg) +/** + * throtl_add_bio_tg - add a bio to the specified throtl_grp + * @bio: bio to add + * @qn: qnode to use + * @tg: the target throtl_grp + * + * Add @bio to @tg's service_queue using @qn. If @qn is not specified, + * tg->qnode_on_self[] is used. + */ +static void throtl_add_bio_tg(struct bio *bio, struct throtl_qnode *qn, + struct throtl_grp *tg) { struct throtl_service_queue *sq = &tg->service_queue; bool rw = bio_data_dir(bio); + if (!qn) + qn = &tg->qnode_on_self[rw]; + /* * If @tg doesn't currently have any bios queued in the same * direction, queueing @bio can change when @tg should be @@ -820,9 +962,8 @@ static void throtl_add_bio_tg(struct bio *bio, struct throtl_grp *tg) if (!sq->nr_queued[rw]) tg->flags |= THROTL_TG_WAS_EMPTY; - bio_list_add(&sq->bio_lists[rw], bio); - /* Take a bio reference on tg */ - blkg_get(tg_to_blkg(tg)); + throtl_qnode_add_bio(bio, qn, &sq->queued[rw]); + sq->nr_queued[rw]++; throtl_enqueue_tg(tg); } @@ -833,10 +974,10 @@ static void tg_update_disptime(struct throtl_grp *tg) unsigned long read_wait = -1, write_wait = -1, min_wait = -1, disptime; struct bio *bio; - if ((bio = bio_list_peek(&sq->bio_lists[READ]))) + if ((bio = throtl_peek_queued(&sq->queued[READ]))) tg_may_dispatch(tg, bio, &read_wait); - if ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) + if ((bio = throtl_peek_queued(&sq->queued[WRITE]))) tg_may_dispatch(tg, bio, &write_wait); min_wait = min(read_wait, write_wait); @@ -856,9 +997,16 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) struct throtl_service_queue *sq = &tg->service_queue; struct throtl_service_queue *parent_sq = sq->parent_sq; struct throtl_grp *parent_tg = sq_to_tg(parent_sq); + struct throtl_grp *tg_to_put = NULL; struct bio *bio; - bio = bio_list_pop(&sq->bio_lists[rw]); + /* + * @bio is being transferred from @tg to @parent_sq. Popping a bio + * from @tg may put its reference and @parent_sq might end up + * getting released prematurely. Remember the tg to put and put it + * after @bio is transferred to @parent_sq. + */ + bio = throtl_pop_queued(&sq->queued[rw], &tg_to_put); sq->nr_queued[rw]--; throtl_charge_bio(tg, bio); @@ -871,17 +1019,18 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) * responsible for issuing these bios. */ if (parent_tg) { - throtl_add_bio_tg(bio, parent_tg); + throtl_add_bio_tg(bio, &tg->qnode_on_parent[rw], parent_tg); } else { - bio_list_add(&parent_sq->bio_lists[rw], bio); + throtl_qnode_add_bio(bio, &tg->qnode_on_parent[rw], + &parent_sq->queued[rw]); BUG_ON(tg->td->nr_queued[rw] <= 0); tg->td->nr_queued[rw]--; } throtl_trim_slice(tg, rw); - /* @bio is transferred to parent, drop its blkg reference */ - blkg_put(tg_to_blkg(tg)); + if (tg_to_put) + blkg_put(tg_to_blkg(tg_to_put)); } static int throtl_dispatch_tg(struct throtl_grp *tg) @@ -894,7 +1043,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg) /* Try to dispatch 75% READS and 25% WRITES */ - while ((bio = bio_list_peek(&sq->bio_lists[READ])) && + while ((bio = throtl_peek_queued(&sq->queued[READ])) && tg_may_dispatch(tg, bio, NULL)) { tg_dispatch_one_bio(tg, bio_data_dir(bio)); @@ -904,7 +1053,7 @@ static int throtl_dispatch_tg(struct throtl_grp *tg) break; } - while ((bio = bio_list_peek(&sq->bio_lists[WRITE])) && + while ((bio = throtl_peek_queued(&sq->queued[WRITE])) && tg_may_dispatch(tg, bio, NULL)) { tg_dispatch_one_bio(tg, bio_data_dir(bio)); @@ -1039,10 +1188,9 @@ void blk_throtl_dispatch_work_fn(struct work_struct *work) bio_list_init(&bio_list_on_stack); spin_lock_irq(q->queue_lock); - for (rw = READ; rw <= WRITE; rw++) { - bio_list_merge(&bio_list_on_stack, &td_sq->bio_lists[rw]); - bio_list_init(&td_sq->bio_lists[rw]); - } + for (rw = READ; rw <= WRITE; rw++) + while ((bio = throtl_pop_queued(&td_sq->queued[rw], NULL))) + bio_list_add(&bio_list_on_stack, bio); spin_unlock_irq(q->queue_lock); if (!bio_list_empty(&bio_list_on_stack)) { @@ -1241,6 +1389,7 @@ static struct blkcg_policy blkcg_policy_throtl = { bool blk_throtl_bio(struct request_queue *q, struct bio *bio) { struct throtl_data *td = q->td; + struct throtl_qnode *qn = NULL; struct throtl_grp *tg; struct throtl_service_queue *sq; bool rw = bio_data_dir(bio); @@ -1308,6 +1457,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) * Climb up the ladder. If we''re already at the top, it * can be executed directly. */ + qn = &tg->qnode_on_parent[rw]; sq = sq->parent_sq; tg = sq_to_tg(sq); if (!tg) @@ -1323,7 +1473,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) bio_associate_current(bio); tg->td->nr_queued[rw]++; - throtl_add_bio_tg(bio, tg); + throtl_add_bio_tg(bio, qn, tg); throttled = true; /* @@ -1367,9 +1517,9 @@ static void tg_drain_bios(struct throtl_service_queue *parent_sq) throtl_dequeue_tg(tg); - while ((bio = bio_list_peek(&sq->bio_lists[READ]))) + while ((bio = throtl_peek_queued(&sq->queued[READ]))) tg_dispatch_one_bio(tg, bio_data_dir(bio)); - while ((bio = bio_list_peek(&sq->bio_lists[WRITE]))) + while ((bio = throtl_peek_queued(&sq->queued[WRITE]))) tg_dispatch_one_bio(tg, bio_data_dir(bio)); } } @@ -1411,7 +1561,8 @@ void blk_throtl_drain(struct request_queue *q) /* all bios now should be in td->service_queue, issue them */ for (rw = READ; rw <= WRITE; rw++) - while ((bio = bio_list_pop(&td->service_queue.bio_lists[rw]))) + while ((bio = throtl_pop_queued(&td->service_queue.queued[rw], + NULL))) generic_make_request(bio); spin_lock_irq(q->queue_lock); -- GitLab From 32ee5bc4787dfbdb280b4d81a338dcdd55918c1e Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0058/2900] blk-throttle: Account for child group's start time in parent while bio climbs up With the planned proper hierarchy support, a bio will climb up the tree before actually being dispatched. This makes sure bio is also subjected to parent's throttling limits, if any. It might happen that parent is idle and when bio is transferred to parent, a new slice starts fresh. But that is incorrect as parents wait time should have started when bio was queued in child group and causes IOs to be throttled more than configured as they climb the hierarchy. Given the fact that we have not written hierarchical algorithm in a way where child's and parents time slices are synchronized, we transfer the child's start time to parent if parent was idling. If parent was busy doing dispatch of other bios all this while, this is not an issue. Child's slice start time is passed to parent. Parent looks at its last expired slice start time. If child's start time is after parents old start time, that means parent had been idle and after parent went idle, child had an IO queued. So use child's start time as parent start time. If parent's start time is after child's start time, that means, when IO got queued in child group, parent was not idle. But later it dispatched some IO, its slice got trimmed and then it went idle. After a while child's request got shifted in parent group. In this case use parent's old start time as new start time as that's the duration of slice we did not use. This logic is far from perfect as if there are multiple childs then first child transferring the bio decides the start time while a bio might have queued up even earlier in other child, which is yet to be transferred up to parent. In that case we will lose time and bandwidth in parent. This patch is just an approximation to make situation somewhat better. Signed-off-by: Vivek Goyal Signed-off-by: Tejun Heo --- block/blk-throttle.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 541bd0dabb9a..7477f332c8dc 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -633,6 +633,28 @@ static bool throtl_schedule_next_dispatch(struct throtl_service_queue *sq, return false; } +static inline void throtl_start_new_slice_with_credit(struct throtl_grp *tg, + bool rw, unsigned long start) +{ + tg->bytes_disp[rw] = 0; + tg->io_disp[rw] = 0; + + /* + * Previous slice has expired. We must have trimmed it after last + * bio dispatch. That means since start of last slice, we never used + * that bandwidth. Do try to make use of that bandwidth while giving + * credit. + */ + if (time_after_eq(start, tg->slice_start[rw])) + tg->slice_start[rw] = start; + + tg->slice_end[rw] = jiffies + throtl_slice; + throtl_log(&tg->service_queue, + "[%c] new slice with credit start=%lu end=%lu jiffies=%lu", + rw == READ ? 'R' : 'W', tg->slice_start[rw], + tg->slice_end[rw], jiffies); +} + static inline void throtl_start_new_slice(struct throtl_grp *tg, bool rw) { tg->bytes_disp[rw] = 0; @@ -992,6 +1014,16 @@ static void tg_update_disptime(struct throtl_grp *tg) tg->flags &= ~THROTL_TG_WAS_EMPTY; } +static void start_parent_slice_with_credit(struct throtl_grp *child_tg, + struct throtl_grp *parent_tg, bool rw) +{ + if (throtl_slice_used(parent_tg, rw)) { + throtl_start_new_slice_with_credit(parent_tg, rw, + child_tg->slice_start[rw]); + } + +} + static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) { struct throtl_service_queue *sq = &tg->service_queue; @@ -1020,6 +1052,7 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw) */ if (parent_tg) { throtl_add_bio_tg(bio, &tg->qnode_on_parent[rw], parent_tg); + start_parent_slice_with_credit(tg, parent_tg, rw); } else { throtl_qnode_add_bio(bio, &tg->qnode_on_parent[rw], &parent_sq->queued[rw]); -- GitLab From 693e751e70843c29884cde326016e746fa16073a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0059/2900] blk-throttle: implement throtl_grp->has_rules[] blk_throtl_bio() has a quick exit path for throtl_grps without limits configured. It looks at the bps and iops limits and if both are not configured, the bio is issued immediately. While this is correct in the current flat hierarchy as each throtl_grp behaves completely independently, it would become wrong in proper hierarchy mode. A group without any limits could still be limited by one of its ancestors and bio's queued for such group should not bypass blk-throtl. As having a quick bypass mechanism is beneficial, this patch reimplements the mechanism such that it's correct even with proper hierarchy. throtl_grp->has_rules[] is added. These booleans are updated for the whole subtree whenever a config is updated so that has_rules[] of the whole subtree stays synchronized. They're also updated when a new throtl_grp comes online so that it can't escape the limits of its ancestors. As no throtl_grp has another throtl_grp as parent now, this patch doesn't yet make any behavior differences. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal --- block/blk-throttle.c | 49 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 7477f332c8dc..27f006bb363b 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -124,6 +124,9 @@ struct throtl_grp { unsigned int flags; + /* are there any throtl rules between this group and td? */ + bool has_rules[2]; + /* bytes per second rate limits */ uint64_t bps[2]; @@ -422,6 +425,30 @@ static void throtl_pd_init(struct blkcg_gq *blkg) spin_unlock_irqrestore(&tg_stats_alloc_lock, flags); } +/* + * Set has_rules[] if @tg or any of its parents have limits configured. + * This doesn't require walking up to the top of the hierarchy as the + * parent's has_rules[] is guaranteed to be correct. + */ +static void tg_update_has_rules(struct throtl_grp *tg) +{ + struct throtl_grp *parent_tg = sq_to_tg(tg->service_queue.parent_sq); + int rw; + + for (rw = READ; rw <= WRITE; rw++) + tg->has_rules[rw] = (parent_tg && parent_tg->has_rules[rw]) || + (tg->bps[rw] != -1 || tg->iops[rw] != -1); +} + +static void throtl_pd_online(struct blkcg_gq *blkg) +{ + /* + * We don't want new groups to escape the limits of its ancestors. + * Update has_rules[] after a new group is brought online. + */ + tg_update_has_rules(blkg_to_tg(blkg)); +} + static void throtl_pd_exit(struct blkcg_gq *blkg) { struct throtl_grp *tg = blkg_to_tg(blkg); @@ -843,12 +870,6 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio, return 0; } -static bool tg_no_rule_group(struct throtl_grp *tg, bool rw) { - if (tg->bps[rw] == -1 && tg->iops[rw] == -1) - return 1; - return 0; -} - /* * Returns whether one can dispatch a bio or not. Also returns approx number * of jiffies to wait before this bio is with-in IO rate and can be dispatched @@ -1307,6 +1328,8 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, struct blkg_conf_ctx ctx; struct throtl_grp *tg; struct throtl_service_queue *sq; + struct blkcg_gq *blkg; + struct cgroup *pos_cgrp; int ret; ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, buf, &ctx); @@ -1329,6 +1352,17 @@ static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, tg->bps[READ], tg->bps[WRITE], tg->iops[READ], tg->iops[WRITE]); + /* + * Update has_rules[] flags for the updated tg's subtree. A tg is + * considered to have rules if either the tg itself or any of its + * ancestors has rules. This identifies groups without any + * restrictions in the whole hierarchy and allows them to bypass + * blk-throttle. + */ + tg_update_has_rules(tg); + blkg_for_each_descendant_pre(blkg, pos_cgrp, ctx.blkg) + tg_update_has_rules(blkg_to_tg(blkg)); + /* * We're already holding queue_lock and know @tg is valid. Let's * apply the new config directly. @@ -1415,6 +1449,7 @@ static struct blkcg_policy blkcg_policy_throtl = { .cftypes = throtl_files, .pd_init_fn = throtl_pd_init, + .pd_online_fn = throtl_pd_online, .pd_exit_fn = throtl_pd_exit, .pd_reset_stats_fn = throtl_pd_reset_stats, }; @@ -1442,7 +1477,7 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio) blkcg = bio_blkcg(bio); tg = throtl_lookup_tg(td, blkcg); if (tg) { - if (tg_no_rule_group(tg, rw)) { + if (!tg->has_rules[rw]) { throtl_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, bio->bi_rw); goto out_unlock_rcu; -- GitLab From 9138125beabbb76b4a373d4a619870f6f5d86fc5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 14 May 2013 13:52:38 -0700 Subject: [PATCH 0060/2900] blk-throttle: implement proper hierarchy support With the recent updates, blk-throttle is finally ready for proper hierarchy support. Dispatching now honors service_queue->parent_sq and propagates correctly. The only thing missing is setting ->parent_sq correctly so that throtl_grp hierarchy matches the cgroup hierarchy. This patch updates throtl_pd_init() such that service_queues form the same hierarchy as the cgroup hierarchy if sane_behavior is enabled. As this concludes proper hierarchy support for blkcg, the shameful .broken_hierarchy tag is removed from blkio_subsys. v2: Updated blkio-controller.txt as suggested by Vivek. Signed-off-by: Tejun Heo Acked-by: Vivek Goyal Cc: Li Zefan --- Documentation/cgroups/blkio-controller.txt | 29 +++++++++++----------- block/blk-cgroup.c | 8 ------ block/blk-throttle.c | 22 +++++++++++++++- include/linux/cgroup.h | 2 ++ 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index da272c8f44e7..cd556b914786 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt @@ -94,11 +94,13 @@ Throttling/Upper Limit policy Hierarchical Cgroups ==================== -- Currently only CFQ supports hierarchical groups. For throttling, - cgroup interface does allow creation of hierarchical cgroups and - internally it treats them as flat hierarchy. - If somebody created a hierarchy like as follows. +Both CFQ and throttling implement hierarchy support; however, +throttling's hierarchy support is enabled iff "sane_behavior" is +enabled from cgroup side, which currently is a development option and +not publicly available. + +If somebody created a hierarchy like as follows. root / \ @@ -106,21 +108,20 @@ Hierarchical Cgroups | test3 - CFQ will handle the hierarchy correctly but and throttling will - practically treat all groups at same level. For details on CFQ - hierarchy support, refer to Documentation/block/cfq-iosched.txt. - Throttling will treat the hierarchy as if it looks like the - following. +CFQ by default and throttling with "sane_behavior" will handle the +hierarchy correctly. For details on CFQ hierarchy support, refer to +Documentation/block/cfq-iosched.txt. For throttling, all limits apply +to the whole subtree while all statistics are local to the IOs +directly generated by tasks in that cgroup. + +Throttling without "sane_behavior" enabled from cgroup side will +practically treat all groups at same level as if it looks like the +following. pivot / / \ \ root test1 test2 test3 - Nesting cgroups, while allowed, isn't officially supported and blkio - genereates warning when cgroups nest. Once throttling implements - hierarchy support, hierarchy will be supported and the warning will - be removed. - Various user visible config options =================================== CONFIG_BLK_CGROUP diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index d0747605f56c..290792a13e3c 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -911,14 +911,6 @@ struct cgroup_subsys blkio_subsys = { .subsys_id = blkio_subsys_id, .base_cftypes = blkcg_files, .module = THIS_MODULE, - - /* - * blkio subsystem is utterly broken in terms of hierarchy support. - * It treats all cgroups equally regardless of where they're - * located in the hierarchy - all cgroups are treated as if they're - * right below the root. Fix it and remove the following. - */ - .broken_hierarchy = true, }; EXPORT_SYMBOL_GPL(blkio_subsys); diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 27f006bb363b..08a32dfd3844 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -397,10 +397,30 @@ static void throtl_pd_init(struct blkcg_gq *blkg) { struct throtl_grp *tg = blkg_to_tg(blkg); struct throtl_data *td = blkg->q->td; + struct throtl_service_queue *parent_sq; unsigned long flags; int rw; - throtl_service_queue_init(&tg->service_queue, &td->service_queue); + /* + * If sane_hierarchy is enabled, we switch to properly hierarchical + * behavior where limits on a given throtl_grp are applied to the + * whole subtree rather than just the group itself. e.g. If 16M + * read_bps limit is set on the root group, the whole system can't + * exceed 16M for the device. + * + * If sane_hierarchy is not enabled, the broken flat hierarchy + * behavior is retained where all throtl_grps are treated as if + * they're all separate root groups right below throtl_data. + * Limits of a group don't interact with limits of other groups + * regardless of the position of the group in the hierarchy. + */ + parent_sq = &td->service_queue; + + if (cgroup_sane_behavior(blkg->blkcg->css.cgroup) && blkg->parent) + parent_sq = &blkg_to_tg(blkg->parent)->service_queue; + + throtl_service_queue_init(&tg->service_queue, parent_sq); + for (rw = READ; rw <= WRITE; rw++) { throtl_qnode_init(&tg->qnode_on_self[rw], tg); throtl_qnode_init(&tg->qnode_on_parent[rw], tg); diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 5047355b9a0f..09f1a1408ae0 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -272,6 +272,8 @@ enum { * - memcg: use_hierarchy is on by default and the cgroup file for * the flag is not created. * + * - blkcg: blk-throttle becomes properly hierarchical. + * * The followings are planned changes. * * - release_agent will be disallowed once replacement notification -- GitLab From 18032ca062e621e15683cb61c066ef3dc5414a7b Mon Sep 17 00:00:00 2001 From: David Quigley Date: Thu, 2 May 2013 13:19:10 -0400 Subject: [PATCH 0061/2900] NFSD: Server implementation of MAC Labeling Implement labeled NFS on the server: encoding and decoding, and writing and reading, of file labels. Enabled with CONFIG_NFSD_V4_SECURITY_LABEL. Signed-off-by: Matthew N. Dodd Signed-off-by: Miguel Rodel Felipe Signed-off-by: Phua Eu Gene Signed-off-by: Khin Mi Mi Aung Signed-off-by: J. Bruce Fields --- fs/nfsd/Kconfig | 16 +++++++ fs/nfsd/nfs4proc.c | 41 +++++++++++++++++ fs/nfsd/nfs4xdr.c | 108 +++++++++++++++++++++++++++++++++++++++++---- fs/nfsd/nfsd.h | 18 +++++++- fs/nfsd/vfs.c | 28 ++++++++++++ fs/nfsd/vfs.h | 2 + fs/nfsd/xdr4.h | 4 ++ 7 files changed, 207 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 430b6872806f..dc8f1ef665ce 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -81,6 +81,22 @@ config NFSD_V4 If unsure, say N. +config NFSD_V4_SECURITY_LABEL + bool "Provide Security Label support for NFSv4 server" + depends on NFSD_V4 && SECURITY + help + + Say Y here if you want enable fine-grained security label attribute + support for NFS version 4. Security labels allow security modules like + SELinux and Smack to label files to facilitate enforcement of their policies. + Without this an NFSv4 mount will have the same label on each file. + + If you do not wish to enable fine-grained security labels SELinux or + Smack policies on NFSv4 files, say N. + + WARNING: there is still a chance of backwards-incompatible protocol changes. + For now we recommend "Y" only for developers and testers." + config NFSD_FAULT_INJECTION bool "NFS server manual fault injection" depends on NFSD_V4 && DEBUG_KERNEL diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 27d74a294515..1a1ff247bc59 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -42,6 +42,36 @@ #include "current_stateid.h" #include "netns.h" +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +#include + +static inline void +nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval) +{ + struct inode *inode = resfh->fh_dentry->d_inode; + int status; + + mutex_lock(&inode->i_mutex); + status = security_inode_setsecctx(resfh->fh_dentry, + label->data, label->len); + mutex_unlock(&inode->i_mutex); + + if (status) + /* + * XXX: We should really fail the whole open, but we may + * already have created a new file, so it may be too + * late. For now this seems the least of evils: + */ + bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + + return; +} +#else +static inline void +nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval) +{ } +#endif + #define NFSDDBG_FACILITY NFSDDBG_PROC static u32 nfsd_attrmask[] = { @@ -239,6 +269,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru (u32 *)open->op_verf.data, &open->op_truncate, &open->op_created); + if (!status && open->op_label.len) + nfsd4_security_inode_setsecctx(resfh, &open->op_label, open->op_bmval); + /* * Following rfc 3530 14.2.16, use the returned bitmask * to indicate which attributes we used to store the @@ -637,6 +670,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (status) goto out; + if (create->cr_label.len) + nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval); + if (create->cr_acl != NULL) do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, create->cr_bmval); @@ -916,6 +952,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, setattr->sa_acl); if (status) goto out; + if (setattr->sa_label.len) + status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh, + &setattr->sa_label); + if (status) + goto out; status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, 0, (time_t)0); out: diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 9aeacddafa3f..dfca5121de53 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -55,6 +55,11 @@ #include "cache.h" #include "netns.h" +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +#include +#endif + + #define NFSDDBG_FACILITY NFSDDBG_XDR /* @@ -242,7 +247,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) static __be32 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, - struct iattr *iattr, struct nfs4_acl **acl) + struct iattr *iattr, struct nfs4_acl **acl, + struct xdr_netobj *label) { int expected_len, len = 0; u32 dummy32; @@ -380,6 +386,32 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, goto xdr_error; } } + + label->len = 0; +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL + if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { + READ_BUF(4); + len += 4; + READ32(dummy32); /* lfs: we don't use it */ + READ_BUF(4); + len += 4; + READ32(dummy32); /* pi: we don't use it either */ + READ_BUF(4); + len += 4; + READ32(dummy32); + READ_BUF(dummy32); + if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN) + return nfserr_badlabel; + len += (XDR_QUADLEN(dummy32) << 2); + READMEM(buf, dummy32); + label->data = kzalloc(dummy32 + 1, GFP_KERNEL); + if (!label->data) + return nfserr_jukebox; + defer_free(argp, kfree, label->data); + memcpy(label->data, buf, dummy32); + } +#endif + if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) @@ -576,7 +608,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create return status; status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, - &create->cr_acl); + &create->cr_acl, &create->cr_label); if (status) goto out; @@ -827,7 +859,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) case NFS4_CREATE_UNCHECKED: case NFS4_CREATE_GUARDED: status = nfsd4_decode_fattr(argp, open->op_bmval, - &open->op_iattr, &open->op_acl); + &open->op_iattr, &open->op_acl, &open->op_label); if (status) goto out; break; @@ -841,7 +873,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) READ_BUF(NFS4_VERIFIER_SIZE); COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); status = nfsd4_decode_fattr(argp, open->op_bmval, - &open->op_iattr, &open->op_acl); + &open->op_iattr, &open->op_acl, &open->op_label); if (status) goto out; break; @@ -1063,7 +1095,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta if (status) return status; return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, - &setattr->sa_acl); + &setattr->sa_acl, &setattr->sa_label); } static __be32 @@ -1954,6 +1986,36 @@ nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace, FATTR4_WORD0_RDATTR_ERROR) #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +static inline __be32 +nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) +{ + __be32 *p = *pp; + + if (*buflen < ((XDR_QUADLEN(len) << 2) + 4 + 4 + 4)) + return nfserr_resource; + + /* + * For now we use a 0 here to indicate the null translation; in + * the future we may place a call to translation code here. + */ + if ((*buflen -= 8) < 0) + return nfserr_resource; + + WRITE32(0); /* lfs */ + WRITE32(0); /* pi */ + p = xdr_encode_opaque(p, context, len); + *buflen -= (XDR_QUADLEN(len) << 2) + 4; + + *pp = p; + return 0; +} +#else +static inline __be32 +nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen) +{ return 0; } +#endif + static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) { /* As per referral draft: */ @@ -2013,6 +2075,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, int err; int aclsupport = 0; struct nfs4_acl *acl = NULL; + void *context = NULL; + int contextlen; + bool contextsupport = false; struct nfsd4_compoundres *resp = rqstp->rq_resp; u32 minorversion = resp->cstate.minorversion; struct path path = { @@ -2066,6 +2131,21 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, } } +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL + if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) || + bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) { + err = security_inode_getsecctx(dentry->d_inode, + &context, &contextlen); + contextsupport = (err == 0); + if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { + if (err == -EOPNOTSUPP) + bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL; + else if (err) + goto out_nfserr; + } + } +#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ + if (bmval2) { if ((buflen -= 16) < 0) goto out_resource; @@ -2094,6 +2174,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (!aclsupport) word0 &= ~FATTR4_WORD0_ACL; + if (!contextsupport) + word2 &= ~FATTR4_WORD2_SECURITY_LABEL; if (!word2) { if ((buflen -= 12) < 0) goto out_resource; @@ -2401,6 +2483,12 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, get_parent_attributes(exp, &stat); WRITE64(stat.ino); } + if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) { + status = nfsd4_encode_security_label(rqstp, context, + contextlen, &p, &buflen); + if (status) + goto out; + } if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { WRITE32(3); WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); @@ -2413,6 +2501,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, status = nfs_ok; out: + if (context) + security_release_secctx(context, contextlen); kfree(acl); if (fhp == &tempfh) fh_put(&tempfh); @@ -3177,16 +3267,18 @@ nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 { __be32 *p; - RESERVE_SPACE(12); + RESERVE_SPACE(16); if (nfserr) { - WRITE32(2); + WRITE32(3); + WRITE32(0); WRITE32(0); WRITE32(0); } else { - WRITE32(2); + WRITE32(3); WRITE32(setattr->sa_bmval[0]); WRITE32(setattr->sa_bmval[1]); + WRITE32(setattr->sa_bmval[2]); } ADJUST_ARGS(); return nfserr; diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 15e7e1d531f0..2bbd94e51efc 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -328,6 +328,13 @@ void nfsd_lockd_shutdown(void); #define NFSD4_1_SUPPORTED_ATTRS_WORD2 \ (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT) +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \ + (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL) +#else +#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0 +#endif + static inline u32 nfsd_suppattrs0(u32 minorversion) { return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0 @@ -342,8 +349,11 @@ static inline u32 nfsd_suppattrs1(u32 minorversion) static inline u32 nfsd_suppattrs2(u32 minorversion) { - return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2 - : NFSD4_SUPPORTED_ATTRS_WORD2; + switch (minorversion) { + default: return NFSD4_2_SUPPORTED_ATTRS_WORD2; + case 1: return NFSD4_1_SUPPORTED_ATTRS_WORD2; + case 0: return NFSD4_SUPPORTED_ATTRS_WORD2; + } } /* These will return ERR_INVAL if specified in GETATTR or READDIR. */ @@ -356,7 +366,11 @@ static inline u32 nfsd_suppattrs2(u32 minorversion) #define NFSD_WRITEABLE_ATTRS_WORD1 \ (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +#define NFSD_WRITEABLE_ATTRS_WORD2 FATTR4_WORD2_SECURITY_LABEL +#else #define NFSD_WRITEABLE_ATTRS_WORD2 0 +#endif #define NFSD_SUPPATTR_EXCLCREAT_WORD0 \ NFSD_WRITEABLE_ATTRS_WORD0 diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 84ce601d8063..1e757fa45c40 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_NFSD_V3 #include "xdr3.h" @@ -621,6 +622,33 @@ int nfsd4_is_junction(struct dentry *dentry) return 0; return 1; } +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL +__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct xdr_netobj *label) +{ + __be32 error; + int host_error; + struct dentry *dentry; + + error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR); + if (error) + return error; + + dentry = fhp->fh_dentry; + + mutex_lock(&dentry->d_inode->i_mutex); + host_error = security_inode_setsecctx(dentry, label->data, label->len); + mutex_unlock(&dentry->d_inode->i_mutex); + return nfserrno(host_error); +} +#else +__be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct xdr_netobj *label) +{ + return nfserr_notsupp; +} +#endif + #endif /* defined(CONFIG_NFSD_V4) */ #ifdef CONFIG_NFSD_V3 diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 8d2b40d71669..a4be2e389670 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -55,6 +55,8 @@ int nfsd_mountpoint(struct dentry *, struct svc_export *); __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *, struct nfs4_acl *); int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **); +__be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, + struct xdr_netobj *); #endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create(struct svc_rqst *, struct svc_fh *, char *name, int len, struct iattr *attrs, diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 3b271d2092b6..b3ed6446ed8e 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -40,6 +40,7 @@ #include "state.h" #include "nfsd.h" +#define NFSD4_MAX_SEC_LABEL_LEN 2048 #define NFSD4_MAX_TAGLEN 128 #define XDR_LEN(n) (((n) + 3) & ~3) @@ -118,6 +119,7 @@ struct nfsd4_create { struct iattr cr_iattr; /* request */ struct nfsd4_change_info cr_cinfo; /* response */ struct nfs4_acl *cr_acl; + struct xdr_netobj cr_label; }; #define cr_linklen u.link.namelen #define cr_linkname u.link.name @@ -246,6 +248,7 @@ struct nfsd4_open { struct nfs4_file *op_file; /* used during processing */ struct nfs4_ol_stateid *op_stp; /* used during processing */ struct nfs4_acl *op_acl; + struct xdr_netobj op_label; }; #define op_iattr iattr @@ -330,6 +333,7 @@ struct nfsd4_setattr { u32 sa_bmval[3]; /* request */ struct iattr sa_iattr; /* request */ struct nfs4_acl *sa_acl; + struct xdr_netobj sa_label; }; struct nfsd4_setclientid { -- GitLab From 2fccbd9cc0fdca649b01f1e2d96e5ef85256341a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 24 Sep 2012 15:53:29 -0400 Subject: [PATCH 0062/2900] sunrpc: server back channel needs no rpcbind method XPRT_BOUND is set on server backchannel xprts by xs_setup_bc_tcp() (using xprt_set_bound()), and is never cleared, so ->rpcbind() will never need to be called. Reported-by: "Myklebust, Trond" Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtsock.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ffd50348a509..5d6b0daf743d 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2534,7 +2534,6 @@ static struct rpc_xprt_ops bc_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xprt_release_xprt, .alloc_slot = xprt_alloc_slot, - .rpcbind = xs_local_rpcbind, .buf_alloc = bc_malloc, .buf_free = bc_free, .send_request = bc_send_request, -- GitLab From ba4e55bb67894136489b27372166416cd70b0756 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 15 May 2013 10:27:52 -0400 Subject: [PATCH 0063/2900] nfsd4: fix compile in !CONFIG_NFSD_V4_SECURITY_LABEL case Reported-by: kbuild test robot Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index dfca5121de53..170ea7e1ae25 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2012,7 +2012,7 @@ nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be } #else static inline __be32 -nfsd4_encode_security_label(struct svc_rqst *rqstp, struct dentry *dentry, __be32 **pp, int *buflen) +nfsd4_encode_security_label(struct svc_rqst *rqstp, void *context, int len, __be32 **pp, int *buflen) { return 0; } #endif @@ -2501,8 +2501,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, status = nfs_ok; out: +#ifdef CONFIG_NFSD_V4_SECURITY_LABEL if (context) security_release_secctx(context, contextlen); +#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ kfree(acl); if (fhp == &tempfh) fh_put(&tempfh); -- GitLab From bc441bc8e36e0bcdbf21639fb78e94ffa19ea226 Mon Sep 17 00:00:00 2001 From: Laurent Navet Date: Mon, 13 May 2013 17:27:51 +0200 Subject: [PATCH 0064/2900] drivers: net: can: grcan: use devm_ioremap_resource() Replace a call to deprecated devm_request_and_ioremap by devm_ioremap_resource. dev_err() message is no more needed since it's already displayed in devm_ioremap_resource(). Signed-off-by: Laurent Navet Acked-by: Andreas Larsson Signed-off-by: Marc Kleine-Budde --- drivers/net/can/grcan.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 17fbc7a09224..9e9d0d628e7b 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1683,10 +1683,9 @@ static int grcan_probe(struct platform_device *ofdev) } res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); - base = devm_request_and_ioremap(&ofdev->dev, res); - if (!base) { - dev_err(&ofdev->dev, "couldn't map IO resource\n"); - err = -EADDRNOTAVAIL; + base = devm_ioremap_resource(&ofdev->dev, res); + if (IS_ERR(base)) { + err = PTR_ERR(base); goto exit_error; } -- GitLab From 3e1dd6da1a7af98a795fafa9437679767c605a7b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 7 May 2013 13:11:29 +0900 Subject: [PATCH 0065/2900] net: can: at91_can: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index db52f4414def..556656661d6b 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1393,8 +1393,6 @@ static int at91_can_remove(struct platform_device *pdev) unregister_netdev(dev); - platform_set_drvdata(pdev, NULL); - iounmap(priv->reg_base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- GitLab From 5e946e56231b5c765598cd3103faf3c7a0121812 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 7 May 2013 13:14:13 +0900 Subject: [PATCH 0066/2900] net: can: c_can: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_platform.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index d63b91904f82..6b6130b8bdc4 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -234,7 +234,6 @@ static int c_can_plat_probe(struct platform_device *pdev) return 0; exit_free_device: - platform_set_drvdata(pdev, NULL); free_c_can_dev(dev); exit_iounmap: iounmap(addr); @@ -255,7 +254,6 @@ static int c_can_plat_remove(struct platform_device *pdev) struct resource *mem; unregister_c_can_dev(dev); - platform_set_drvdata(pdev, NULL); free_c_can_dev(dev); iounmap(priv->base); -- GitLab From 688a2e74210cb42eccf59b8cff1433d53ea0b800 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 7 May 2013 13:15:49 +0900 Subject: [PATCH 0067/2900] net: can: flexcan: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 769d29ed106d..4a40a186c8c8 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1127,7 +1127,6 @@ static int flexcan_remove(struct platform_device *pdev) struct resource *mem; unregister_flexcandev(dev); - platform_set_drvdata(pdev, NULL); iounmap(priv->base); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- GitLab From 5727dc6bf5b70dd278e58e26137e2df729b9c107 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 7 May 2013 13:17:38 +0900 Subject: [PATCH 0068/2900] net: can: ti_hecc: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f21fc37ec578..3a349a22d5bc 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -1001,7 +1001,6 @@ static int ti_hecc_remove(struct platform_device *pdev) iounmap(priv->base); release_mem_region(res->start, resource_size(res)); free_candev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 119363c7dc2bcc0c33c255a7b4979c8c0fdc1896 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 22 Apr 2013 16:29:30 +0200 Subject: [PATCH 0069/2900] cfg80211: add support for per-chain signal strength reporting Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 14 +++++++++++++ include/uapi/linux/nl80211.h | 6 ++++++ net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 26b5b692c22b..87f7e1d060ab 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -753,6 +753,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, * @STATION_INFO_LOCAL_PM: @local_pm filled * @STATION_INFO_PEER_PM: @peer_pm filled * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled + * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled + * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -781,6 +783,8 @@ enum station_info_flags { STATION_INFO_NONPEER_PM = 1<<23, STATION_INFO_RX_BYTES64 = 1<<24, STATION_INFO_TX_BYTES64 = 1<<25, + STATION_INFO_CHAIN_SIGNAL = 1<<26, + STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27, }; /** @@ -857,6 +861,8 @@ struct sta_bss_parameters { u16 beacon_interval; }; +#define IEEE80211_MAX_CHAINS 4 + /** * struct station_info - station information * @@ -874,6 +880,9 @@ struct sta_bss_parameters { * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * @signal_avg: Average signal strength, type depends on the wiphy's signal_type. * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. + * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg + * @chain_signal: per-chain signal strength of last received packet in dBm + * @chain_signal_avg: per-chain signal strength average in dBm * @txrate: current unicast bitrate from this station * @rxrate: current unicast bitrate to this station * @rx_packets: packets received from this station @@ -909,6 +918,11 @@ struct station_info { u8 plink_state; s8 signal; s8 signal_avg; + + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; + s8 chain_signal_avg[IEEE80211_MAX_CHAINS]; + struct rate_info txrate; struct rate_info rxrate; u32 rx_packets; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index d1e48b5e348f..cbf1e228650f 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1991,6 +1991,10 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards * non-peer STA + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU + * Contains a nested array of signal strength attributes (u8, dBm) + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average + * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -2020,6 +2024,8 @@ enum nl80211_sta_info { NL80211_STA_INFO_NONPEER_PM, NL80211_STA_INFO_RX_BYTES64, NL80211_STA_INFO_TX_BYTES64, + NL80211_STA_INFO_CHAIN_SIGNAL, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afa283841e8c..f687a8d0d026 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3376,6 +3376,32 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, return true; } +static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal, + int id) +{ + void *attr; + int i = 0; + + if (!mask) + return true; + + attr = nla_nest_start(msg, id); + if (!attr) + return false; + + for (i = 0; i < IEEE80211_MAX_CHAINS; i++) { + if (!(mask & BIT(i))) + continue; + + if (nla_put_u8(msg, i, signal[i])) + return false; + } + + nla_nest_end(msg, attr); + + return true; +} + static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, int flags, struct cfg80211_registered_device *rdev, @@ -3447,6 +3473,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, default: break; } + if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) { + if (!nl80211_put_signal(msg, sinfo->chains, + sinfo->chain_signal, + NL80211_STA_INFO_CHAIN_SIGNAL)) + goto nla_put_failure; + } + if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) { + if (!nl80211_put_signal(msg, sinfo->chains, + sinfo->chain_signal_avg, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) + goto nla_put_failure; + } if (sinfo->filled & STATION_INFO_TX_BITRATE) { if (!nl80211_put_sta_rate(msg, &sinfo->txrate, NL80211_STA_INFO_TX_BITRATE)) -- GitLab From ef0621e805f9ef76eaf31ce6205028fe467e9ca9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 22 Apr 2013 16:29:31 +0200 Subject: [PATCH 0070/2900] mac80211: add support for per-chain signal strength reporting Signed-off-by: Felix Fietkau [fix unit documentation] Signed-off-by: Johannes Berg --- include/net/mac80211.h | 6 ++++++ net/mac80211/cfg.c | 13 ++++++++++++- net/mac80211/rx.c | 14 ++++++++++++++ net/mac80211/sta_info.c | 2 ++ net/mac80211/sta_info.h | 5 +++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 04c2d4670dc6..5953f25e63f5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -850,6 +850,10 @@ enum mac80211_rx_flags { * @signal: signal strength when receiving this frame, either in dBm, in dB or * unspecified depending on the hardware capabilities flags * @IEEE80211_HW_SIGNAL_* + * @chains: bitmask of receive chains for which separate signal strength + * values were filled. + * @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't + * support dB or unspecified units) * @antenna: antenna used * @rate_idx: index of data rate into band's supported rates or MCS index if * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) @@ -881,6 +885,8 @@ struct ieee80211_rx_status { u8 band; u8 antenna; s8 signal; + u8 chains; + s8 chain_signal[IEEE80211_MAX_CHAINS]; u8 ampdu_delimiter_crc; u8 vendor_radiotap_align; u8 vendor_radiotap_oui[3]; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1a89c80e6407..1f51bdfe574a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) struct ieee80211_local *local = sdata->local; struct timespec uptime; u64 packets = 0; - int ac; + int i, ac; sinfo->generation = sdata->local->sta_generation; @@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->signal = (s8)sta->last_signal; sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); } + if (sta->chains) { + sinfo->filled |= STATION_INFO_CHAIN_SIGNAL | + STATION_INFO_CHAIN_SIGNAL_AVG; + + sinfo->chains = sta->chains; + for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { + sinfo->chain_signal[i] = sta->chain_signal_last[i]; + sinfo->chain_signal_avg[i] = + (s8) -ewma_read(&sta->chain_signal_avg[i]); + } + } sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); sta_set_rate_info_rx(sta, &sinfo->rxrate); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c8447af76ead..22e412b0767f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1372,6 +1372,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) struct sk_buff *skb = rx->skb; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int i; if (!sta) return RX_CONTINUE; @@ -1422,6 +1423,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ewma_add(&sta->avg_signal, -status->signal); } + if (status->chains) { + sta->chains = status->chains; + for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { + int signal = status->chain_signal[i]; + + if (!(status->chains & BIT(i))) + continue; + + sta->chain_signal_last[i] = signal; + ewma_add(&sta->chain_signal_avg[i], -signal); + } + } + /* * Change STA power saving mode only at the end of a frame * exchange sequence. diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 11216bc13b27..a04c5671d7fd 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, do_posix_clock_monotonic_gettime(&uptime); sta->last_connected = uptime.tv_sec; ewma_init(&sta->avg_signal, 1024, 8); + for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) + ewma_init(&sta->chain_signal_avg[i], 1024, 8); if (sta_prepare_rate_control(local, sta, gfp)) { kfree(sta); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index adc30045f99e..41c28b977f7c 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -344,6 +344,11 @@ struct sta_info { int last_signal; struct ewma avg_signal; int last_ack_signal; + + u8 chains; + s8 chain_signal_last[IEEE80211_MAX_CHAINS]; + struct ewma chain_signal_avg[IEEE80211_MAX_CHAINS]; + /* Plus 1 for non-QoS frames */ __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; -- GitLab From 55300a13d2ca1d59f659cf00b9d8dc93ea225882 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Tue, 23 Apr 2013 09:54:21 +0300 Subject: [PATCH 0071/2900] cfg80211: add 60GHz regulatory class Add regulatory class for 60GHz band, according to the last specification. Signed-off-by: Vladimir Kondratiev Signed-off-by: Johannes Berg --- net/wireless/util.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/util.c b/net/wireless/util.c index f5ad4d94ba88..b11052be09be 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1169,6 +1169,9 @@ bool ieee80211_operating_class_to_band(u8 operating_class, case 84: *band = IEEE80211_BAND_2GHZ; return true; + case 180: + *band = IEEE80211_BAND_60GHZ; + return true; } return false; -- GitLab From fb4e156886ce6e8309e912d8b370d192330d19d3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 28 Apr 2013 16:22:06 -0700 Subject: [PATCH 0072/2900] nl80211: Add generic netlink module alias for cfg80211/nl80211 To support auto-loading of wireless modules from netlink users, add module alias for nl80211 family. This also adds NL80211_GENL_NAME constant to define the "nl80211" netlink family name as part of uapi. Signed-off-by: Marcel Holtmann Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 2 ++ net/wireless/core.c | 1 + net/wireless/nl80211.c | 8 ++++---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index cbf1e228650f..b48430769eda 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -27,6 +27,8 @@ #include +#define NL80211_GENL_NAME "nl80211" + /** * DOC: Station handling * diff --git a/net/wireless/core.c b/net/wireless/core.c index 84c9ad7e1dca..68f0c96c0565 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -34,6 +34,7 @@ MODULE_AUTHOR("Johannes Berg"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); +MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); /* RCU-protected (and cfg80211_mutex for writers) */ LIST_HEAD(cfg80211_rdev_list); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f687a8d0d026..9cdcd9ec3317 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -37,10 +37,10 @@ static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, /* the netlink family */ static struct genl_family nl80211_fam = { - .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ - .name = "nl80211", /* have users key off the name instead */ - .hdrsize = 0, /* no private header */ - .version = 1, /* no particular meaning now */ + .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ + .name = NL80211_GENL_NAME, /* have users key off the name instead */ + .hdrsize = 0, /* no private header */ + .version = 1, /* no particular meaning now */ .maxattr = NL80211_ATTR_MAX, .netnsok = true, .pre_doit = nl80211_pre_doit, -- GitLab From 03f831a6f7dc02303df20718a4e96821e43b3d0c Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 2 May 2013 07:15:09 -0400 Subject: [PATCH 0073/2900] wireless: fix kerneldoc content in *80211.h files. Make kerneldoc content match header file content, no functional change. Signed-off-by: Robert P. J. Day Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 1 + include/net/mac80211.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 87f7e1d060ab..26e91138a2c6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4167,6 +4167,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver. * * @wdev: the wireless device for which critical protocol is stopped. + * @gfp: allocation flags * * This function can be called by the driver to indicate it has reverted * operation back to normal. One reason could be that the duration given diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5953f25e63f5..c36535e7b291 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1241,7 +1241,7 @@ enum ieee80211_sta_rx_bandwidth { * struct ieee80211_sta_rates - station rate selection table * * @rcu_head: RCU head used for freeing the table on update - * @rates: transmit rates/flags to be used by default. + * @rate: transmit rates/flags to be used by default. * Overriding entries per-packet is possible by using cb tx control. */ struct ieee80211_sta_rates { @@ -1282,7 +1282,7 @@ struct ieee80211_sta_rates { * notifications and capabilities. The value is only valid after * the station moves to associated state. * @smps_mode: current SMPS mode (off, static or dynamic) - * @tx_rates: rate control selection table + * @rates: rate control selection table */ struct ieee80211_sta { u32 supp_rates[IEEE80211_NUM_BANDS]; -- GitLab From 04a161f4609dfa387313456fa7ea469fff12cc0d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 3 May 2013 09:35:35 +0200 Subject: [PATCH 0074/2900] mac80211: fix HT beacon-based channel switch handling When an HT AP is advertising channel switch in a beacon, it doesn't (and shouldn't, according to 802.11-2012 Table 8-20) include a secondary channel offset element. The only possible interpretation is that the previous secondary channel offset remains valid, so use that when switching channel based only on beacon information. VHT requires the Wide Bandwidth Channel Switch subelement to be present in the Channel Switch Wrapper element, so the code for that is probably ok (see 802.11ac Draft 4, 8.4.2.165.) Reported-by: Sujith Manoharan Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 29620bfc7a69..a8016c02a757 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data) static void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, - u64 timestamp, struct ieee802_11_elems *elems) + u64 timestamp, struct ieee802_11_elems *elems, + bool beacon) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, struct cfg80211_chan_def new_vht_chandef = {}; const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; + const struct ieee80211_ht_operation *ht_oper; int secondary_channel_offset = -1; ASSERT_MGD_MTX(ifmgd); @@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, sec_chan_offs = elems->sec_chan_offs; wide_bw_chansw_ie = elems->wide_bw_chansw_ie; + ht_oper = elems->ht_operation; if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_40MHZ)) { sec_chan_offs = NULL; wide_bw_chansw_ie = NULL; + /* only used for bandwidth here */ + ht_oper = NULL; } if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) @@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, return; } - if (sec_chan_offs) { + if (!beacon && sec_chan_offs) { secondary_channel_offset = sec_chan_offs->sec_chan_offs; + } else if (beacon && ht_oper) { + secondary_channel_offset = + ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { - /* if HT is enabled and the IE not present, it's still HT */ + /* + * If it's not a beacon, HT is enabled and the IE not present, + * it's 20 MHz, 802.11-2012 8.5.2.6: + * This element [the Secondary Channel Offset Element] is + * present when switching to a 40 MHz channel. It may be + * present when switching to a 20 MHz channel (in which + * case the secondary channel offset is set to SCN). + */ secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; } @@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, mutex_unlock(&local->iflist_mtx); } - ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); + ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, + elems, true); } @@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, - &elems); + &elems, false); } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { ies_len = skb->len - offsetof(struct ieee80211_mgmt, @@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, - &elems); + &elems, false); } break; } -- GitLab From 4325f6caad98c075b39f0eaaac6693a0dd43f646 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 May 2013 13:09:08 +0200 Subject: [PATCH 0075/2900] wireless: move crypto constants to ieee80211.h mac80211 and the Intel drivers all define crypto constants, move them to ieee80211.h instead. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlegacy/commands.h | 8 --- drivers/net/wireless/iwlwifi/dvm/commands.h | 8 --- drivers/net/wireless/iwlwifi/pcie/tx.c | 6 +- include/linux/ieee80211.h | 9 +++ net/mac80211/aes_ccm.c | 6 +- net/mac80211/key.c | 24 ++++---- net/mac80211/key.h | 15 +---- net/mac80211/rx.c | 12 ++-- net/mac80211/wep.c | 48 ++++++++------- net/mac80211/wpa.c | 68 +++++++++++---------- 10 files changed, 96 insertions(+), 108 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/commands.h b/drivers/net/wireless/iwlegacy/commands.h index 3b6c99400892..048421511988 100644 --- a/drivers/net/wireless/iwlegacy/commands.h +++ b/drivers/net/wireless/iwlegacy/commands.h @@ -1347,14 +1347,6 @@ struct il_rx_mpdu_res_start { #define TX_CMD_SEC_SHIFT 6 #define TX_CMD_SEC_KEY128 0x08 -/* - * security overhead sizes - */ -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define CCMP_MIC_LEN 8 -#define TKIP_ICV_LEN 4 - /* * C_TX = 0x1c (command) */ diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 95ca026ecc9d..174b0f169497 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h @@ -1224,14 +1224,6 @@ struct iwl_rx_mpdu_res_start { #define TX_CMD_SEC_SHIFT 6 #define TX_CMD_SEC_KEY128 0x08 -/* - * security overhead sizes - */ -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define CCMP_MIC_LEN 8 -#define TKIP_ICV_LEN 4 - /* * REPLY_TX = 0x1c (command) */ diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c5e30294c5ac..2878ee99a668 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, switch (sec_ctl & TX_CMD_SEC_MSK) { case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; + len += IEEE80211_CCMP_MIC_LEN; break; case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; + len += IEEE80211_TKIP_ICV_LEN; break; case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; + len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN; break; } diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 06b0ed0154a4..d826e5a84af0 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1829,6 +1829,15 @@ enum ieee80211_key_len { WLAN_KEY_LEN_AES_CMAC = 16, }; +#define IEEE80211_WEP_IV_LEN 4 +#define IEEE80211_WEP_ICV_LEN 4 +#define IEEE80211_CCMP_HDR_LEN 8 +#define IEEE80211_CCMP_MIC_LEN 8 +#define IEEE80211_CCMP_PN_LEN 6 +#define IEEE80211_TKIP_IV_LEN 8 +#define IEEE80211_TKIP_ICV_LEN 4 +#define IEEE80211_CMAC_PN_LEN 6 + /* Public action codes */ enum ieee80211_pub_actioncode { WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4, diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 0785e95c9924..be7614b9ed27 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c @@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, *cpos++ = *pos++ ^ e[i]; } - for (i = 0; i < CCMP_MIC_LEN; i++) + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) mic[i] = b[i] ^ s_0[i]; } @@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, crypto_cipher_encrypt_one(tfm, a, a); } - for (i = 0; i < CCMP_MIC_LEN; i++) { + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) { if ((mic[i] ^ s_0[i]) != a[i]) return -1; } @@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); if (!IS_ERR(tfm)) - crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); + crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP); return tfm; } diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 67059b88fea5..e39cc91d0cf1 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, switch (cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - key->conf.iv_len = WEP_IV_LEN; - key->conf.icv_len = WEP_ICV_LEN; + key->conf.iv_len = IEEE80211_WEP_IV_LEN; + key->conf.icv_len = IEEE80211_WEP_ICV_LEN; break; case WLAN_CIPHER_SUITE_TKIP: - key->conf.iv_len = TKIP_IV_LEN; - key->conf.icv_len = TKIP_ICV_LEN; + key->conf.iv_len = IEEE80211_TKIP_IV_LEN; + key->conf.icv_len = IEEE80211_TKIP_ICV_LEN; if (seq) { for (i = 0; i < IEEE80211_NUM_TIDS; i++) { key->u.tkip.rx[i].iv32 = @@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, spin_lock_init(&key->u.tkip.txlock); break; case WLAN_CIPHER_SUITE_CCMP: - key->conf.iv_len = CCMP_HDR_LEN; - key->conf.icv_len = CCMP_MIC_LEN; + key->conf.iv_len = IEEE80211_CCMP_HDR_LEN; + key->conf.icv_len = IEEE80211_CCMP_MIC_LEN; if (seq) { for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) - for (j = 0; j < CCMP_PN_LEN; j++) + for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++) key->u.ccmp.rx_pn[i][j] = - seq[CCMP_PN_LEN - j - 1]; + seq[IEEE80211_CCMP_PN_LEN - j - 1]; } /* * Initialize AES key state here as an optimization so that @@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, key->conf.iv_len = 0; key->conf.icv_len = sizeof(struct ieee80211_mmie); if (seq) - for (j = 0; j < CMAC_PN_LEN; j++) + for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++) key->u.aes_cmac.rx_pn[j] = - seq[CMAC_PN_LEN - j - 1]; + seq[IEEE80211_CMAC_PN_LEN - j - 1]; /* * Initialize AES key state here as an optimization so that * it does not need to be initialized for every packet. @@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; else pn = key->u.ccmp.rx_pn[tid]; - memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); + memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN); break; case WLAN_CIPHER_SUITE_AES_CMAC: if (WARN_ON(tid != 0)) return; pn = key->u.aes_cmac.rx_pn; - memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN); + memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); break; } } diff --git a/net/mac80211/key.h b/net/mac80211/key.h index e8de3e6d7804..036d57e76a5e 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -19,17 +19,6 @@ #define NUM_DEFAULT_KEYS 4 #define NUM_DEFAULT_MGMT_KEYS 2 -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define ALG_CCMP_KEY_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 -#define TKIP_IV_LEN 8 -#define TKIP_ICV_LEN 4 -#define CMAC_PN_LEN 6 - struct ieee80211_local; struct ieee80211_sub_if_data; struct sta_info; @@ -93,13 +82,13 @@ struct ieee80211_key { * frames and the last counter is used with Robust * Management frames. */ - u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN]; + u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; struct crypto_cipher *tfm; u32 replays; /* dot11RSNAStatsCCMPReplays */ } ccmp; struct { atomic64_t tx_pn; - u8 rx_pn[CMAC_PN_LEN]; + u8 rx_pn[IEEE80211_CMAC_PN_LEN]; struct crypto_cipher *tfm; u32 replays; /* dot11RSNAStatsCMACReplays */ u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 22e412b0767f..6e2c8c5236c4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1622,7 +1622,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) entry->ccmp = 1; memcpy(entry->last_pn, rx->key->u.ccmp.rx_pn[queue], - CCMP_PN_LEN); + IEEE80211_CCMP_PN_LEN); } return RX_QUEUED; } @@ -1641,21 +1641,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) * (IEEE 802.11i, 8.3.3.4.5) */ if (entry->ccmp) { int i; - u8 pn[CCMP_PN_LEN], *rpn; + u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; int queue; if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) return RX_DROP_UNUSABLE; - memcpy(pn, entry->last_pn, CCMP_PN_LEN); - for (i = CCMP_PN_LEN - 1; i >= 0; i--) { + memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); + for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { pn[i]++; if (pn[i]) break; } queue = rx->security_idx; rpn = rx->key->u.ccmp.rx_pn[queue]; - if (memcmp(pn, rpn, CCMP_PN_LEN)) + if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN)) return RX_DROP_UNUSABLE; - memcpy(entry->last_pn, pn, CCMP_PN_LEN); + memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); } skb_pull(rx->skb, ieee80211_hdrlen(fc)); diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index c04d401dae92..6ee2b5863572 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -28,7 +28,7 @@ int ieee80211_wep_init(struct ieee80211_local *local) { /* start WEP IV from a random value */ - get_random_bytes(&local->wep_iv, WEP_IV_LEN); + get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN); local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_tx_tfm)) { @@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || - skb_headroom(skb) < WEP_IV_LEN)) + if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN || + skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) return NULL; hdrlen = ieee80211_hdrlen(hdr->frame_control); - newhdr = skb_push(skb, WEP_IV_LEN); - memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); + newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN); + memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen); /* the HW only needs room for the IV, but not the actual IV */ if (info->control.hw_key && (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) return newhdr + hdrlen; - skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN); + skb_set_network_header(skb, skb_network_offset(skb) + + IEEE80211_WEP_IV_LEN); ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen); return newhdr + hdrlen; } @@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, unsigned int hdrlen; hdrlen = ieee80211_hdrlen(hdr->frame_control); - memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, WEP_IV_LEN); + memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen); + skb_pull(skb, IEEE80211_WEP_IV_LEN); } @@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, put_unaligned(icv, (__le32 *)(data + data_len)); crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + WEP_ICV_LEN; i++) + for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) crypto_cipher_encrypt_one(tfm, data + i, data + i); return 0; @@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, if (!iv) return -1; - len = skb->len - (iv + WEP_IV_LEN - skb->data); + len = skb->len - (iv + IEEE80211_WEP_IV_LEN - skb->data); /* Prepend 24-bit IV to RC4 key */ memcpy(rc4key, iv, 3); @@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, memcpy(rc4key + 3, key, keylen); /* Add room for ICV */ - skb_put(skb, WEP_ICV_LEN); + skb_put(skb, IEEE80211_WEP_ICV_LEN); return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, - iv + WEP_IV_LEN, len); + iv + IEEE80211_WEP_IV_LEN, len); } @@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, return -1; crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + WEP_ICV_LEN; i++) + for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) crypto_cipher_decrypt_one(tfm, data + i, data + i); crc = cpu_to_le32(~crc32_le(~0, data, data_len)); - if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) + if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0) /* ICV mismatch */ return -1; @@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, return -1; hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) + if (skb->len < hdrlen + IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN) return -1; - len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; + len = skb->len - hdrlen - IEEE80211_WEP_IV_LEN - IEEE80211_WEP_ICV_LEN; keyidx = skb->data[hdrlen + 3] >> 6; @@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, memcpy(rc4key + 3, key->conf.key, key->conf.keylen); if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, - skb->data + hdrlen + WEP_IV_LEN, - len)) + skb->data + hdrlen + + IEEE80211_WEP_IV_LEN, len)) ret = -1; /* Trim ICV */ - skb_trim(skb, skb->len - WEP_ICV_LEN); + skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN); /* Remove IV */ - memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, WEP_IV_LEN); + memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen); + skb_pull(skb, IEEE80211_WEP_IV_LEN); return ret; } @@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) return RX_DROP_UNUSABLE; } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { - if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN)) + if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + + IEEE80211_WEP_IV_LEN)) return RX_DROP_UNUSABLE; if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) rx->sta->wep_weak_iv_count++; ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); /* remove ICV */ - if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN)) + if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) return RX_DROP_UNUSABLE; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index c7c6d644486f..c9edfcb7a13b 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) tail = MICHAEL_MIC_LEN; if (!info->control.hw_key) - tail += TKIP_ICV_LEN; + tail += IEEE80211_TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || - skb_headroom(skb) < TKIP_IV_LEN)) + skb_headroom(skb) < IEEE80211_TKIP_IV_LEN)) return TX_DROP; key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; @@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) if (info->control.hw_key) tail = 0; else - tail = TKIP_ICV_LEN; + tail = IEEE80211_TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || - skb_headroom(skb) < TKIP_IV_LEN)) + skb_headroom(skb) < IEEE80211_TKIP_IV_LEN)) return -1; - pos = skb_push(skb, TKIP_IV_LEN); - memmove(pos, pos + TKIP_IV_LEN, hdrlen); - skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN); + pos = skb_push(skb, IEEE80211_TKIP_IV_LEN); + memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen); + skb_set_network_header(skb, skb_network_offset(skb) + + IEEE80211_TKIP_IV_LEN); pos += hdrlen; /* the HW only needs room for the IV, but not the actual IV */ @@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) return 0; /* Add room for ICV */ - skb_put(skb, TKIP_ICV_LEN); + skb_put(skb, IEEE80211_TKIP_ICV_LEN); return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, key, skb, pos, len); @@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; /* Trim ICV */ - skb_trim(skb, skb->len - TKIP_ICV_LEN); + skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN); /* Remove IV */ - memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen); - skb_pull(skb, TKIP_IV_LEN); + memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen); + skb_pull(skb, IEEE80211_TKIP_IV_LEN); return RX_CONTINUE; } @@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, else qos_tid = 0; - data_len = skb->len - hdrlen - CCMP_HDR_LEN; + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; if (encrypted) - data_len -= CCMP_MIC_LEN; + data_len -= IEEE80211_CCMP_MIC_LEN; /* First block, b_0 */ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ @@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, */ b_0[1] = qos_tid | (mgmt << 4); memcpy(&b_0[2], hdr->addr2, ETH_ALEN); - memcpy(&b_0[8], pn, CCMP_PN_LEN); + memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); /* l(m) */ put_unaligned_be16(data_len, &b_0[14]); @@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) if (info->control.hw_key) tail = 0; else - tail = CCMP_MIC_LEN; + tail = IEEE80211_CCMP_MIC_LEN; if (WARN_ON(skb_tailroom(skb) < tail || - skb_headroom(skb) < CCMP_HDR_LEN)) + skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN)) return -1; - pos = skb_push(skb, CCMP_HDR_LEN); - memmove(pos, pos + CCMP_HDR_LEN, hdrlen); - skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN); + pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN); + memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen); + skb_set_network_header(skb, skb_network_offset(skb) + + IEEE80211_CCMP_HDR_LEN); /* the HW only needs room for the IV, but not the actual IV */ if (info->control.hw_key && @@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) if (info->control.hw_key) return 0; - pos += CCMP_HDR_LEN; + pos += IEEE80211_CCMP_HDR_LEN; ccmp_special_blocks(skb, pn, scratch, 0); ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, - pos, skb_put(skb, CCMP_MIC_LEN)); + pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); return 0; } @@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - u8 pn[CCMP_PN_LEN]; + u8 pn[IEEE80211_CCMP_PN_LEN]; int data_len; int queue; @@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) !ieee80211_is_robust_mgmt_frame(hdr)) return RX_CONTINUE; - data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - + IEEE80211_CCMP_MIC_LEN; if (!rx->sta || data_len < 0) return RX_DROP_UNUSABLE; if (status->flag & RX_FLAG_DECRYPTED) { - if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN)) + if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN)) return RX_DROP_UNUSABLE; } else { if (skb_linearize(rx->skb)) @@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) queue = rx->security_idx; - if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { + if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) { key->u.ccmp.replays++; return RX_DROP_UNUSABLE; } @@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) if (ieee80211_aes_ccm_decrypt( key->u.ccmp.tfm, scratch, - skb->data + hdrlen + CCMP_HDR_LEN, data_len, - skb->data + skb->len - CCMP_MIC_LEN, - skb->data + hdrlen + CCMP_HDR_LEN)) + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, + data_len, + skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) return RX_DROP_UNUSABLE; } - memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); + memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); /* Remove CCMP header and MIC */ - if (pskb_trim(skb, skb->len - CCMP_MIC_LEN)) + if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN)) return RX_DROP_UNUSABLE; - memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); - skb_pull(skb, CCMP_HDR_LEN); + memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen); + skb_pull(skb, IEEE80211_CCMP_HDR_LEN); return RX_CONTINUE; } -- GitLab From bd500af223c9aed7083730b7044d53162065e418 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 6 May 2013 21:09:46 +0200 Subject: [PATCH 0076/2900] mac80211: write memcpy differently for smatch There's no real difference between *array and array, but the former confuses smatch so write it differently. The generated code is exactly the same. Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1f51bdfe574a..66989458f5ff 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -739,7 +739,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy, if (sset == ETH_SS_STATS) { sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); - memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats); + memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats); } drv_get_et_strings(sdata, sset, &(data[sz_sta_stats])); } -- GitLab From 7ade7036043e2e8e2831ae189ce5c248386062f1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 13 May 2013 11:37:30 +0200 Subject: [PATCH 0077/2900] cfg80211: use C99 initialisers to simplify code a bit Use C99 initialisers for the auth, deauth and disassoc requests to simplify the code. Signed-off-by: Johannes Berg --- net/wireless/mlme.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 0c7b7dd855f6..c21e32f9549c 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -264,7 +264,16 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, const u8 *sae_data, int sae_data_len) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_auth_request req; + struct cfg80211_auth_request req = { + .ie = ie, + .ie_len = ie_len, + .sae_data = sae_data, + .sae_data_len = sae_data_len, + .auth_type = auth_type, + .key = key, + .key_len = key_len, + .key_idx = key_idx, + }; int err; ASSERT_WDEV_LOCK(wdev); @@ -277,18 +286,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) return -EALREADY; - memset(&req, 0, sizeof(req)); - - req.ie = ie; - req.ie_len = ie_len; - req.sae_data = sae_data; - req.sae_data_len = sae_data_len; - req.auth_type = auth_type; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - req.key = key; - req.key_len = key_len; - req.key_idx = key_idx; if (!req.bss) return -ENOENT; @@ -480,7 +479,12 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_disassoc_request req; + struct cfg80211_disassoc_request req = { + .reason_code = reason, + .local_state_change = local_state_change, + .ie = ie, + .ie_len = ie_len, + }; ASSERT_WDEV_LOCK(wdev); @@ -490,11 +494,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) return -ENOTCONN; - memset(&req, 0, sizeof(req)); - req.reason_code = reason; - req.local_state_change = local_state_change; - req.ie = ie; - req.ie_len = ie_len; if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) req.bss = &wdev->current_bss->pub; else @@ -523,24 +522,21 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, struct net_device *dev) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_deauth_request req; u8 bssid[ETH_ALEN]; + struct cfg80211_deauth_request req = { + .reason_code = WLAN_REASON_DEAUTH_LEAVING, + .bssid = bssid, + }; ASSERT_WDEV_LOCK(wdev); if (!rdev->ops->deauth) return; - memset(&req, 0, sizeof(req)); - req.reason_code = WLAN_REASON_DEAUTH_LEAVING; - req.ie = NULL; - req.ie_len = 0; - if (!wdev->current_bss) return; memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); - req.bssid = bssid; rdev_deauth(rdev, dev, &req); if (wdev->current_bss) { -- GitLab From 6e16d90b5218307db805e6b3e0b06d3946eb8c4c Mon Sep 17 00:00:00 2001 From: Colleen Twitty Date: Wed, 8 May 2013 11:45:59 -0700 Subject: [PATCH 0078/2900] cfg80211: Userspace may inform kernel of mesh auth method. Authentication takes place in userspace, but the beacon is generated in the kernel. Allow userspace to inform the kernel of the authentication method so the appropriate mesh config IE can be set prior to beacon generation when joining the MBSS. Signed-off-by: Colleen Twitty Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 5 +++++ net/wireless/mesh.c | 1 + net/wireless/nl80211.c | 8 ++++++++ 4 files changed, 16 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 26e91138a2c6..32a2f1b20861 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1161,6 +1161,7 @@ struct mesh_config { * @sync_method: which synchronization method to use * @path_sel_proto: which path selection protocol to use * @path_metric: which metric to use + * @auth_id: which authentication method this mesh is using * @ie: vendor information elements (optional) * @ie_len: length of vendor information elements * @is_authenticated: this mesh requires authentication @@ -1179,6 +1180,7 @@ struct mesh_setup { u8 sync_method; u8 path_sel_proto; u8 path_metric; + u8 auth_id; const u8 *ie; u8 ie_len; bool is_authenticated; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b48430769eda..06320713e9c9 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2645,6 +2645,10 @@ enum nl80211_meshconf_params { * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will * implement an MPM which handles peer allocation and state. * + * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication + * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE). + * Default is no authentication method required. + * * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use @@ -2658,6 +2662,7 @@ enum nl80211_mesh_setup_params { NL80211_MESH_SETUP_USERSPACE_AMPE, NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, NL80211_MESH_SETUP_USERSPACE_MPM, + NL80211_MESH_SETUP_AUTH_PROTOCOL, /* keep last */ __NL80211_MESH_SETUP_ATTR_AFTER_LAST, diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0bb93f3061a4..9546ad210550 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -82,6 +82,7 @@ const struct mesh_setup default_mesh_setup = { .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_metric = IEEE80211_PATH_METRIC_AIRTIME, + .auth_id = 0, /* open */ .ie = NULL, .ie_len = 0, .is_secure = false, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9cdcd9ec3317..5f10f7acfa06 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4672,6 +4672,7 @@ static const struct nla_policy [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, + [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 }, [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG }, [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, @@ -4857,6 +4858,13 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, if (setup->is_secure) setup->user_mpm = true; + if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) { + if (!setup->user_mpm) + return -EINVAL; + setup->auth_id = + nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]); + } + return 0; } -- GitLab From 0d4261ad5d0028b26cd88e645b4507eed8aab3f7 Mon Sep 17 00:00:00 2001 From: Colleen Twitty Date: Wed, 8 May 2013 11:46:00 -0700 Subject: [PATCH 0079/2900] mac80211: enable Auth Protocol Identifier on mesh config. Previously the mesh_auth_id was disabled. Instead set the correct mesh authentication bit based on the mesh setup. Signed-off-by: Colleen Twitty Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 1 + net/mac80211/mesh.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 66989458f5ff..eb4219051043 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1746,6 +1746,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pm_id = setup->path_metric; ifmsh->user_mpm = setup->user_mpm; + ifmsh->mesh_auth_id = setup->auth_id; ifmsh->security = IEEE80211_MESH_SEC_NONE; if (setup->is_authenticated) ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6952760881c8..c13db9ad394b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -748,7 +748,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ieee80211_configure_filter(local); ifmsh->mesh_cc_id = 0; /* Disabled */ - ifmsh->mesh_auth_id = 0; /* Disabled */ /* register sync ops from extensible synchronization framework */ ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); ifmsh->adjusting_tbtt = false; -- GitLab From ce85788846ec19dcb7bef0dcbcf83fb64630f426 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Mon, 6 May 2013 17:17:04 +0300 Subject: [PATCH 0080/2900] mac80211: enable power save only if DTIM period is available Generally, the DTIM period is available after a beacon has been received, and if no beacon has been received enabling powersave is problematic anyway for synchronisation. Since some drivers may require the DTIM period for powersave, don't enable powersave until it becomes available in case the scan/association managed to not receive a beacon. Signed-off-by: Alexander Bondar Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a8016c02a757..ef378b9a32ec 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1390,6 +1390,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) IEEE80211_STA_CONNECTION_POLL)) return false; + if (!sdata->vif.bss_conf.dtim_period) + return false; + rcu_read_lock(); sta = sta_info_get(sdata, mgd->bssid); if (sta) @@ -3126,6 +3129,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, } changed |= BSS_CHANGED_DTIM_PERIOD; + ieee80211_recalc_ps_vif(sdata); } if (elems.erp_info) { -- GitLab From 4270b871a266f615440ef716345c9f559f81eb30 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 6 May 2013 10:41:03 +0300 Subject: [PATCH 0081/2900] iwlwifi: mvm: add a missing define in firmware API TX_CMD_SEC_MSK was missing. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 007a93b25bd7..6994232f5726 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h @@ -134,6 +134,7 @@ enum iwl_tx_flags { #define TX_CMD_SEC_WEP 0x01 #define TX_CMD_SEC_CCM 0x02 #define TX_CMD_SEC_TKIP 0x03 +#define TX_CMD_SEC_MSK 0x07 #define TX_CMD_SEC_WEP_KEY_IDX_POS 6 #define TX_CMD_SEC_WEP_KEY_IDX_MSK 0xc0 #define TX_CMD_SEC_KEY128 0x08 -- GitLab From 5b1dbfc3aa26327dede4cf7a88d7c1e71728e024 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Tue, 23 Apr 2013 13:32:35 +0300 Subject: [PATCH 0082/2900] iwlwifi: mvm: Add number of DTIMs to skip New host-device API provides the ability to set the number of DTIMs to skip. Add this parameter to the command and set it (to a sane default value.) Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | 6 +++--- drivers/net/wireless/iwlwifi/mvm/power.c | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 90fdfcda15b6..05e51927b848 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -101,19 +101,19 @@ enum iwl_power_flags { * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to * PSM transition - legacy PM * @sleep_interval: not in use - * @keep_alive_beacons: not in use + * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. * Default: 80dbm */ struct iwl_powertable_cmd { - /* PM_POWER_TABLE_CMD_API_S_VER_5 */ + /* PM_POWER_TABLE_CMD_API_S_VER_6 */ __le16 flags; u8 keep_alive_seconds; u8 debug_flags; __le32 rx_data_timeout; __le32 tx_data_timeout; __le32 sleep_interval[IWL_POWER_VEC_SIZE]; - __le32 keep_alive_beacons; + __le32 num_skip_dtim; __le32 lprx_rssi_threshold; } __packed; diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 30a5c27bd623..6c5dfc9a8d43 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -91,6 +91,9 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, le32_to_cpu(cmd->tx_data_timeout)); IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", cmd->lprx_rssi_threshold); + if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) + IWL_DEBUG_POWER(mvm, "DTIMs to skip = %u\n", + le32_to_cpu(cmd->num_skip_dtim)); } } @@ -135,8 +138,10 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* Check skip over DTIM conditions */ if (!radar_detect && (dtimper <= 10) && - (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) + (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) { cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); + cmd->num_skip_dtim = cpu_to_le32(2); + } /* Check that keep alive period is at least 3 * DTIM */ dtimper_msec = dtimper * vif->bss_conf.beacon_int; -- GitLab From ee1e84225f779386858702872fb299457e7941f9 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Tue, 23 Apr 2013 13:52:10 +0300 Subject: [PATCH 0083/2900] iwlwifi: mvm: configure power management in D3 Configure power management in the D3 firmware by sending the power table command to it when suspending; this uses some values that are more suitable to a low power state. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/d3.c | 4 ++++ drivers/net/wireless/iwlwifi/mvm/power.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 63d788aef3f4..4d3c978b5c76 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1007,6 +1007,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) if (ret) goto out; + ret = iwl_mvm_power_update_mode(mvm, vif); + if (ret) + goto out; + /* must be last -- this switches firmware state */ ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, sizeof(d3_cfg_cmd), &d3_cfg_cmd); diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 6c5dfc9a8d43..f5bdfb71c790 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -138,7 +138,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* Check skip over DTIM conditions */ if (!radar_detect && (dtimper <= 10) && - (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP)) { + (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || + mvm->cur_ucode == IWL_UCODE_WOWLAN)) { cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); cmd->num_skip_dtim = cpu_to_le32(2); } @@ -150,8 +151,13 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC); cmd->keep_alive_seconds = keep_alive; - cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); - cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); + if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { + cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); + cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); + } else { + cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); + cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); + } } int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) -- GitLab From bf0fd5da8afdea8e1b1a2b42b8e9db068fbac96b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 13 May 2013 17:05:27 +0300 Subject: [PATCH 0084/2900] iwlwifi: constify the source buffer of iwl_trans_write_mem Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 ++-- drivers/net/wireless/iwlwifi/pcie/trans.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 7a13790b5bfe..0470334d6a81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -455,7 +455,7 @@ struct iwl_trans_ops { int (*read_mem)(struct iwl_trans *trans, u32 addr, void *buf, int dwords); int (*write_mem)(struct iwl_trans *trans, u32 addr, - void *buf, int dwords); + const void *buf, int dwords); void (*configure)(struct iwl_trans *trans, const struct iwl_trans_config *trans_cfg); void (*set_pmi)(struct iwl_trans *trans, bool state); @@ -761,7 +761,7 @@ static inline u32 iwl_trans_read_mem32(struct iwl_trans *trans, u32 addr) } static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr, - void *buf, int dwords) + const void *buf, int dwords) { return trans->ops->write_mem(trans, addr, buf, dwords); } diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index e5365196e5fe..a785f49df9b1 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -924,11 +924,11 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, } static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, - void *buf, int dwords) + const void *buf, int dwords) { unsigned long flags; int offs, ret = 0; - u32 *vals = buf; + const u32 *vals = buf; if (iwl_trans_grab_nic_access(trans, false, &flags)) { iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr); -- GitLab From 82598b4f43312c01b976e02add9a5205e371f858 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 13 May 2013 21:44:42 +0200 Subject: [PATCH 0085/2900] iwlwifi: mvm: fix NVM parsing error path If NVM parsing fails and returns NULL, we continue in the code flow and eventually crash accessing the NULL pointer. Return an error from iwl_nvm_init() if the parsing failed. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/nvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index b8ec02f89acc..c6c15f21065f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -231,8 +231,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm) if (ret < 0) return ret; - ret = 0; mvm->nvm_data = iwl_parse_nvm_sections(mvm); + if (!mvm->nvm_data) + return -ENODATA; - return ret; + return 0; } -- GitLab From 0db53d005d004336be10807d07fc2cb271a53810 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 13:05:25 +0200 Subject: [PATCH 0086/2900] iwlwifi: reverse DATA/INST section order As the new MVM firmware files package the DATA section first, and debugfs files want to access the DATA and not INST section, reverse the order here. This is only relevant for debugfs code that accesses the SRAM DATA section and uses this constant to access the section. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-fw.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index c4c446d41eb0..f844d5c748c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -106,11 +106,14 @@ enum iwl_ucode_type { /* * enumeration of ucode section. - * This enumeration is used for legacy tlv style (before 16.0 uCode). + * This enumeration is used directly for older firmware (before 16.0). + * For new firmware, there can be up to 4 sections (see below) but the + * first one packaged into the firmware file is the DATA section and + * some debugging code accesses that. */ enum iwl_ucode_sec { - IWL_UCODE_SECTION_INST, IWL_UCODE_SECTION_DATA, + IWL_UCODE_SECTION_INST, }; /* * For 16.0 uCode and above, there is no differentiation between sections, -- GitLab From 07fd7d284dd01b46dea1986cb3bff20dfffe09bd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 14:38:25 +0200 Subject: [PATCH 0087/2900] iwlwifi: nvm: don't print NVM section reads by default These messages aren't really useful, suppress them unless EEPROM debugging is turned on. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/nvm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index c6c15f21065f..ce464a5cca29 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -177,7 +177,8 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section, offset += ret; } - IWL_INFO(mvm, "NVM section %d read completed\n", section); + IWL_DEBUG_EEPROM(mvm->trans->dev, + "NVM section %d read completed\n", section); return offset; } -- GitLab From 1214755c2bfc74b56093ccae797cb295e89d3400 Mon Sep 17 00:00:00 2001 From: Eran Harary Date: Thu, 9 May 2013 08:07:59 +0300 Subject: [PATCH 0088/2900] iwlwifi: support loading NVM data from file Some newer devices will be integrated into the platform more deeply and will not have embedded NVM (EEPROM/OTP). To support such devices the NVM data must be provided by the platform, allow loading the data via request_firmware() and then send it to the device as needed. Signed-off-by: Eran Harary Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-drv.c | 3 + drivers/net/wireless/iwlwifi/iwl-modparams.h | 1 + drivers/net/wireless/iwlwifi/mvm/nvm.c | 198 ++++++++++++++++++- 3 files changed, 194 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 39aad9893e0b..4f886133639a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1234,6 +1234,9 @@ MODULE_PARM_DESC(wd_disable, "Disable stuck queue watchdog timer 0=system default, " "1=disable, 2=enable (default: 0)"); +module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO); +MODULE_PARM_DESC(nvm_file, "NVM file name"); + /* * set bt_coex_active to true, uCode will do kill/defer * every time the priority line is asserted (BT is sending signals on the diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index d6f6c37c09fd..36dfe0919f6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -119,6 +119,7 @@ struct iwl_mod_params { int ant_coupling; bool bt_ch_announce; bool auto_agg; + char *nvm_file; }; #endif /* #__iwl_modparams_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index ce464a5cca29..3f05c6b23874 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -60,6 +60,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ +#include #include "iwl-trans.h" #include "mvm.h" #include "iwl-eeprom-parse.h" @@ -75,20 +76,46 @@ static const int nvm_to_read[] = { }; /* Default NVM size to read */ -#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); +#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024) +#define IWL_MAX_NVM_SECTION_SIZE 6000 -static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd, - u16 offset, u16 length, u16 section) +#define NVM_WRITE_OPCODE 1 +#define NVM_READ_OPCODE 0 + +/* + * prepare the NVM host command w/ the pointers to the nvm buffer + * and send it to fw + */ +static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section, + u16 offset, u16 length, const u8 *data) { - cmd->offset = cpu_to_le16(offset); - cmd->length = cpu_to_le16(length); - cmd->type = cpu_to_le16(section); + struct iwl_nvm_access_cmd nvm_access_cmd = { + .offset = cpu_to_le16(offset), + .length = cpu_to_le16(length), + .type = cpu_to_le16(section), + .op_code = NVM_WRITE_OPCODE, + }; + struct iwl_host_cmd cmd = { + .id = NVM_ACCESS_CMD, + .len = { sizeof(struct iwl_nvm_access_cmd), length }, + .flags = CMD_SYNC, + .data = { &nvm_access_cmd, data }, + /* data may come from vmalloc, so use _DUP */ + .dataflags = { 0, IWL_HCMD_DFL_DUP }, + }; + + return iwl_mvm_send_cmd(mvm, &cmd); } static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, u16 offset, u16 length, u8 *data) { - struct iwl_nvm_access_cmd nvm_access_cmd = {}; + struct iwl_nvm_access_cmd nvm_access_cmd = { + .offset = cpu_to_le16(offset), + .length = cpu_to_le16(length), + .type = cpu_to_le16(section), + .op_code = NVM_READ_OPCODE, + }; struct iwl_nvm_access_resp *nvm_resp; struct iwl_rx_packet *pkt; struct iwl_host_cmd cmd = { @@ -99,7 +126,6 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, int ret, bytes_read, offset_read; u8 *resp_data; - iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section); cmd.len[0] = sizeof(struct iwl_nvm_access_cmd); ret = iwl_mvm_send_cmd(mvm, &cmd); @@ -144,6 +170,30 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, return ret; } +static int iwl_nvm_write_section(struct iwl_mvm *mvm, u16 section, + const u8 *data, u16 length) +{ + int offset = 0; + + /* copy data in chunks of 2k (and remainder if any) */ + + while (offset < length) { + int chunk_size, ret; + + chunk_size = min(IWL_NVM_DEFAULT_CHUNK_SIZE, + length - offset); + + ret = iwl_nvm_write_chunk(mvm, section, offset, + chunk_size, data + offset); + if (ret < 0) + return ret; + + offset += chunk_size; + } + + return 0; +} + /* * Reads an NVM section completely. * NICs prior to 7000 family doesn't have a real NVM, but just read @@ -204,11 +254,143 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib); } +#define MAX_NVM_FILE_LEN 16384 + +/* + * HOW TO CREATE THE NVM FILE FORMAT: + * ------------------------------ + * 1. create hex file, format: + * 3800 -> header + * 0000 -> header + * 5a40 -> data + * + * rev - 6 bit (word1) + * len - 10 bit (word1) + * id - 4 bit (word2) + * rsv - 12 bit (word2) + * + * 2. flip 8bits with 8 bits per line to get the right NVM file format + * + * 3. create binary file from the hex file + * + * 4. save as "iNVM_xxx.bin" under /lib/firmware + */ +static int iwl_mvm_load_external_nvm(struct iwl_mvm *mvm) +{ + int ret, section_id, section_size; + const struct firmware *fw_entry; + const struct { + __le16 word1; + __le16 word2; + u8 data[]; + } *file_sec; + const u8 *eof; + +#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF)) +#define NVM_WORD2_ID(x) (x >> 12) + + /* + * Obtain NVM image via request_firmware. Since we already used + * request_firmware_nowait() for the firmware binary load and only + * get here after that we assume the NVM request can be satisfied + * synchronously. + */ + ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file, + mvm->trans->dev); + if (ret) { + IWL_ERR(mvm, "ERROR: %s isn't available %d\n", + iwlwifi_mod_params.nvm_file, ret); + return ret; + } + + IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n", + iwlwifi_mod_params.nvm_file, fw_entry->size); + + if (fw_entry->size < sizeof(*file_sec)) { + IWL_ERR(mvm, "NVM file too small\n"); + ret = -EINVAL; + goto out; + } + + if (fw_entry->size > MAX_NVM_FILE_LEN) { + IWL_ERR(mvm, "NVM file too large\n"); + ret = -EINVAL; + goto out; + } + + eof = fw_entry->data + fw_entry->size; + + file_sec = (void *)fw_entry->data; + + while (true) { + if (file_sec->data > eof) { + IWL_ERR(mvm, + "ERROR - NVM file too short for section header\n"); + ret = -EINVAL; + break; + } + + /* check for EOF marker */ + if (!file_sec->word1 && !file_sec->word2) { + ret = 0; + break; + } + + section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); + section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); + + if (section_size > IWL_MAX_NVM_SECTION_SIZE) { + IWL_ERR(mvm, "ERROR - section too large (%d)\n", + section_size); + ret = -EINVAL; + break; + } + + if (!section_size) { + IWL_ERR(mvm, "ERROR - section empty\n"); + ret = -EINVAL; + break; + } + + if (file_sec->data + section_size > eof) { + IWL_ERR(mvm, + "ERROR - NVM file too short for section (%d bytes)\n", + section_size); + ret = -EINVAL; + break; + } + + ret = iwl_nvm_write_section(mvm, section_id, file_sec->data, + section_size); + if (ret < 0) { + IWL_ERR(mvm, "iwl_mvm_send_cmd failed: %d\n", ret); + break; + } + + /* advance to the next section */ + file_sec = (void *)(file_sec->data + section_size); + } +out: + release_firmware(fw_entry); + return ret; +} + int iwl_nvm_init(struct iwl_mvm *mvm) { int ret, i, section; u8 *nvm_buffer, *temp; + /* load external NVM if configured */ + if (iwlwifi_mod_params.nvm_file) { + /* move to External NVM flow */ + ret = iwl_mvm_load_external_nvm(mvm); + if (ret) + return ret; + } + + /* Read From FW NVM */ + IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n"); + /* TODO: find correct NVM max size for a section */ nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, GFP_KERNEL); -- GitLab From 4f59334bb4a626b91ea31f2bb3515e6a586ea1ae Mon Sep 17 00:00:00 2001 From: Eran Harary Date: Mon, 13 May 2013 07:53:26 +0300 Subject: [PATCH 0089/2900] iwlwifi: fix initialisation while RF-kill is asserted If RF-kill is asserted while a device is initialized, the firmware INIT image can now be run to retrieve the NVM data and register to mac80211 properly. Previously, the initialisation would fail in this scenario and the driver wouldn't register with mac80211 at all, making the device unusable. Signed-off-by: Eran Harary Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-trans.h | 3 ++- drivers/net/wireless/iwlwifi/mvm/fw.c | 19 +++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/nvm.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/ops.c | 3 ++- drivers/net/wireless/iwlwifi/pcie/tx.c | 3 ++- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0470334d6a81..84f1c8dc9741 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -189,7 +189,8 @@ enum CMD_MODE { CMD_SYNC = 0, CMD_ASYNC = BIT(0), CMD_WANT_SKB = BIT(1), - CMD_ON_DEMAND = BIT(2), + CMD_SEND_IN_RFKILL = BIT(2), + CMD_ON_DEMAND = BIT(3), }; #define DEF_CMD_PAYLOAD_SIZE 320 diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index a4071cf09a24..20ee2812cc9b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -326,6 +326,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); WARN_ON(ret); + /* + * abort after reading the nvm in case RF Kill is on, we will complete + * the init seq later when RF kill will switch to off + */ + if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) { + IWL_DEBUG_RF_KILL(mvm, + "jump over all phy activities due to RF kill\n"); + iwl_remove_notification(&mvm->notif_wait, &calib_wait); + return 1; + } + /* Send TX valid antennas before triggering calibrations */ ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw)); if (ret) @@ -402,8 +413,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ret = iwl_run_init_mvm_ucode(mvm, false); if (ret && !iwlmvm_mod_params.init_dbg) { IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); + /* this can't happen */ + if (WARN_ON(ret > 0)) + ret = -ERFKILL; goto error; } + /* should stop & start HW since that INIT image just loaded */ + iwl_trans_stop_hw(mvm->trans, false); + ret = iwl_trans_start_hw(mvm->trans); + if (ret) + return ret; } if (iwlmvm_mod_params.init_dbg) diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 3f05c6b23874..2cd669c3c47a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -98,7 +98,7 @@ static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section, struct iwl_host_cmd cmd = { .id = NVM_ACCESS_CMD, .len = { sizeof(struct iwl_nvm_access_cmd), length }, - .flags = CMD_SYNC, + .flags = CMD_SYNC | CMD_SEND_IN_RFKILL, .data = { &nvm_access_cmd, data }, /* data may come from vmalloc, so use _DUP */ .dataflags = { 0, IWL_HCMD_DFL_DUP }, @@ -120,7 +120,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, struct iwl_rx_packet *pkt; struct iwl_host_cmd cmd = { .id = NVM_ACCESS_CMD, - .flags = CMD_SYNC | CMD_WANT_SKB, + .flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL, .data = { &nvm_access_cmd, }, }; int ret, bytes_read, offset_read; diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index bb79a8dcf6bb..e3f69a08251d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -396,7 +396,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mutex_lock(&mvm->mutex); err = iwl_run_init_mvm_ucode(mvm, true); mutex_unlock(&mvm->mutex); - if (err && !iwlmvm_mod_params.init_dbg) { + /* returns 0 if successful, 1 if success but in rfkill */ + if (err < 0 && !iwlmvm_mod_params.init_dbg) { IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err); goto out_free; } diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 595df1756b84..bf5f8246385e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1569,7 +1569,8 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) if (test_bit(STATUS_FW_ERROR, &trans_pcie->status)) return -EIO; - if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { + if (!(cmd->flags & CMD_SEND_IN_RFKILL) && + test_bit(STATUS_RFKILL, &trans_pcie->status)) { IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n", cmd->id); return -ERFKILL; -- GitLab From 60191d99a9a472aef07d9e023f47a2503ae51f00 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 13:08:51 +0200 Subject: [PATCH 0090/2900] iwlwifi: mvm: don't store section offset/length in debugfs When different images can (soon) be accessed through this file, storing the section offset/length on first access to the file breaks (or needs manual reset). Avoid this by not storing the offset/length values but using them locally in the function only. That way, the correct values are always used. While at it, correct the check that firmware is loaded. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 0765827d87a6..95871b2d63d1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -145,16 +145,18 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, char *buf; u8 *ptr; + if (!mvm->ucode_loaded) + return -EINVAL; + /* default is to dump the entire data segment */ if (!mvm->dbgfs_sram_offset && !mvm->dbgfs_sram_len) { - if (!mvm->ucode_loaded) - return -EINVAL; img = &mvm->fw->img[mvm->cur_ucode]; - mvm->dbgfs_sram_offset = - img->sec[IWL_UCODE_SECTION_DATA].offset; - mvm->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; + ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; + len = img->sec[IWL_UCODE_SECTION_DATA].len; + } else { + ofs = mvm->dbgfs_sram_offset; + len = mvm->dbgfs_sram_len; } - len = mvm->dbgfs_sram_len; bufsz = len * 4 + 256; buf = kzalloc(bufsz, GFP_KERNEL); @@ -168,12 +170,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, } pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", len); - pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", - mvm->dbgfs_sram_offset); + pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", ofs); - iwl_trans_read_mem_bytes(mvm->trans, - mvm->dbgfs_sram_offset, - ptr, len); + iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len); for (ofs = 0; ofs < len; ofs += 16) { pos += scnprintf(buf + pos, bufsz - pos, "0x%.4x ", ofs); hex_dump_to_buffer(ptr + ofs, 16, 16, 1, buf + pos, -- GitLab From dfcb4c3aacedee6838e436fb575b31e138505203 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 11:44:49 +0200 Subject: [PATCH 0091/2900] iwlwifi: mvm: adjust firmware D3 configuration API The D3 firmware API changed to include a new field, adjust the driver to it to avoid getting an NMI when configuring. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h index 51e015d1dfb2..6f8b2c16ae17 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h @@ -75,13 +75,15 @@ enum iwl_d3_wakeup_flags { * struct iwl_d3_manager_config - D3 manager configuration command * @min_sleep_time: minimum sleep time (in usec) * @wakeup_flags: wakeup flags, see &enum iwl_d3_wakeup_flags + * @wakeup_host_timer: force wakeup after this many seconds * * The structure is used for the D3_CONFIG_CMD command. */ struct iwl_d3_manager_config { __le32 min_sleep_time; __le32 wakeup_flags; -} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_3 */ + __le32 wakeup_host_timer; +} __packed; /* D3_MANAGER_CONFIG_CMD_S_VER_4 */ /* TODO: OFFLOADS_QUERY_API_S_VER_1 */ -- GitLab From d2cf43674e17ca1c16c68d46d987d2f17bf7c371 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 15 May 2013 19:25:55 +0000 Subject: [PATCH 0092/2900] tcp: speedup tcp_fixup_rcvbuf() tcp_fixup_rcvbuf() contains a loop to estimate initial socket rcv space needed for a given mss. With large MTU (like 64K on lo), we can loop ~500 times and consume a lot of cpu cycles. perf top of 200 concurrent netperf -t TCP_CRR 5.62% netperf [kernel.kallsyms] [k] tcp_init_buffer_space 1.71% netperf [kernel.kallsyms] [k] _raw_spin_lock 1.55% netperf [kernel.kallsyms] [k] kmem_cache_free 1.51% netperf [kernel.kallsyms] [k] tcp_transmit_skb 1.50% netperf [kernel.kallsyms] [k] tcp_ack Lets use a 100% factor, and remove the loop. 100% is needed anyway for tcp_adv_win_scale=1 default value, and is also the maximum factor. Refs: commit b49960a05e32 ("tcp: change tcp_adv_win_scale and tcp_rmem[2]") Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 08bbe6096528..b358e8c98607 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -360,9 +360,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk) if (mss > 1460) icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); - rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER); - while (tcp_win_from_space(rcvmem) < mss) - rcvmem += 128; + rcvmem = 2 * SKB_TRUESIZE(mss + MAX_TCP_HEADER); rcvmem *= icwnd; -- GitLab From d6a98c9680a6f885715ce64daa5de73b33d3edd4 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 16 May 2013 01:15:41 +0000 Subject: [PATCH 0093/2900] drivers/net/ethernet/renesas: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 33dc6f2418f2..42e9dd05c936 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2745,11 +2745,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev) if (mdp->cd->tsu) { struct resource *rtsu; rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!rtsu) { - dev_err(&pdev->dev, "Not found TSU resource\n"); - ret = -ENODEV; - goto out_release; - } mdp->tsu_addr = devm_ioremap_resource(&pdev->dev, rtsu); if (IS_ERR(mdp->tsu_addr)) { ret = PTR_ERR(mdp->tsu_addr); -- GitLab From ed8a83a1f4655a31e0080a19f08d896bb29434a9 Mon Sep 17 00:00:00 2001 From: "govindarajulu.v" Date: Thu, 16 May 2013 06:24:41 +0000 Subject: [PATCH 0094/2900] net: 3com: 3c509: remove unnecessary code This patch removes unnecessary #if 0 code from 3c509.c Signed-off-by: govindarajulu.v Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c509.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index adb4bf5eb4b4..ede8daa68275 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -723,25 +723,6 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev) pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n", dev->name, skb->len, inw(ioaddr + EL3_STATUS)); } -#if 0 -#ifndef final_version - { /* Error-checking code, delete someday. */ - ushort status = inw(ioaddr + EL3_STATUS); - if (status & 0x0001 && /* IRQ line active, missed one. */ - inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */ - pr_debug("%s: Missed interrupt, status then %04x now %04x" - " Tx %2.2x Rx %4.4x.\n", dev->name, status, - inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS), - inw(ioaddr + RX_STATUS)); - /* Fake interrupt trigger by masking, acknowledge interrupts. */ - outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); - outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, - ioaddr + EL3_CMD); - outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); - } - } -#endif -#endif /* * We lock the driver against other processors. Note * we don't need to lock versus the IRQ as we suspended -- GitLab From c0ff68f1611d6855a06d672989ad5cfea160a4eb Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 29 Apr 2013 14:15:51 +0200 Subject: [PATCH 0095/2900] kbuild: fix make headers_install when path is too long If headers_install is executed from a deep/long directory structure, the shell's maximum argument length can be execeeded, which breaks the operation with: | make[2]: execvp: /bin/sh: Argument list too long | make[2]: *** Instead of passing each files name with the entire path, I give only the file name without the source path and give this path as a new argument to headers_install.pl. Because there is three possible paths, I have tree input-files list, one per path. Signed-off-by: Nicolas Dichtel Tested-by: Bruce Ashfield Signed-off-by: Michal Marek --- scripts/Makefile.headersinst | 20 ++++++++++++++------ scripts/headers_install.sh | 7 +++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 182084d728c8..8ccf83056a7a 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -47,18 +47,24 @@ header-y := $(filter-out $(generic-y), $(header-y)) all-files := $(header-y) $(genhdr-y) $(wrapper-files) output-files := $(addprefix $(installdir)/, $(all-files)) -input-files := $(foreach hdr, $(header-y), \ +input-files1 := $(foreach hdr, $(header-y), \ $(if $(wildcard $(srcdir)/$(hdr)), \ - $(wildcard $(srcdir)/$(hdr)), \ + $(wildcard $(srcdir)/$(hdr))) \ + ) +input-files1-name := $(notdir $(input-files1)) +input-files2 := $(foreach hdr, $(header-y), \ + $(if $(wildcard $(srcdir)/$(hdr)),, \ $(if $(wildcard $(oldsrcdir)/$(hdr)), \ $(wildcard $(oldsrcdir)/$(hdr)), \ $(error Missing UAPI file $(srcdir)/$(hdr))) \ - )) \ - $(foreach hdr, $(genhdr-y), \ + )) +input-files2-name := $(notdir $(input-files2)) +input-files3 := $(foreach hdr, $(genhdr-y), \ $(if $(wildcard $(gendir)/$(hdr)), \ $(wildcard $(gendir)/$(hdr)), \ $(error Missing generated UAPI file $(gendir)/$(hdr)) \ )) +input-files3-name := $(notdir $(input-files3)) # Work out what needs to be removed oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h)) @@ -72,7 +78,9 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ file$(if $(word 2, $(all-files)),s)) cmd_install = \ - $(CONFIG_SHELL) $< $(installdir) $(input-files); \ + $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(input-files1-name); \ + $(CONFIG_SHELL) $< $(installdir) $(oldsrcdir) $(input-files2-name); \ + $(CONFIG_SHELL) $< $(installdir) $(gendir) $(input-files3-name); \ for F in $(wrapper-files); do \ echo "\#include " > $(installdir)/$$F; \ done; \ @@ -98,7 +106,7 @@ __headersinst: $(subdirs) $(install-file) @: targets += $(install-file) -$(install-file): scripts/headers_install.sh $(input-files) FORCE +$(install-file): scripts/headers_install.sh $(input-files1) $(input-files2) $(input-files3) FORCE $(if $(unwanted),$(call cmd,remove),) $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) $(call if_changed,install) diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh index 643764f53ea7..5de5660cb708 100644 --- a/scripts/headers_install.sh +++ b/scripts/headers_install.sh @@ -2,7 +2,7 @@ if [ $# -lt 1 ] then - echo "Usage: headers_install.sh OUTDIR [FILES...] + echo "Usage: headers_install.sh OUTDIR SRCDIR [FILES...] echo echo "Prepares kernel header files for use by user space, by removing" echo "all compiler.h definitions and #includes, removing any" @@ -10,6 +10,7 @@ then echo "asm/inline/volatile keywords." echo echo "OUTDIR: directory to write each userspace header FILE to." + echo "SRCDIR: source directory where files are picked." echo "FILES: list of header files to operate on." exit 1 @@ -19,6 +20,8 @@ fi OUTDIR="$1" shift +SRCDIR="$1" +shift # Iterate through files listed on command line @@ -34,7 +37,7 @@ do -e 's/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g' \ -e 's/(^|[ \t(])(inline|asm|volatile)([ \t(]|$)/\1__\2__\3/g' \ -e 's@#(ifndef|define|endif[ \t]*/[*])[ \t]*_UAPI@#\1 @' \ - "$i" > "$OUTDIR/$FILE.sed" || exit 1 + "$SRCDIR/$i" > "$OUTDIR/$FILE.sed" || exit 1 scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ "$OUTDIR/$FILE.sed" \ > "$OUTDIR/$FILE" [ $? -gt 1 ] && exit 1 -- GitLab From bfd428daaf619d671f6463bd8c7e4df8107e4775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 17 May 2013 10:42:53 +0000 Subject: [PATCH 0096/2900] net: ethernet: sun: initialize variables directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the code a bit to initialize the variables directly when defining them. Signed-off-by: Emilio López Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunbmac.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 054975939a18..09b4f8c0b199 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -1017,10 +1017,7 @@ static void bigmac_set_multicast(struct net_device *dev) tmp |= BIGMAC_RXCFG_PMISC; sbus_writel(tmp, bregs + BMAC_RXCFG); } else { - u16 hash_table[4]; - - for (i = 0; i < 4; i++) - hash_table[i] = 0; + u16 hash_table[4] = { 0 }; netdev_for_each_mc_addr(ha, dev) { crc = ether_crc_le(6, ha->addr); -- GitLab From 3b0aaef800c0949198fb6304adc7ff1ae7413f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 17 May 2013 10:42:54 +0000 Subject: [PATCH 0097/2900] net: ethernet: apple: initialize variables directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the code a bit to initialize the variables directly when defining them. Signed-off-by: Emilio López Signed-off-by: David S. Miller --- drivers/net/ethernet/apple/bmac.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index f36bbd6d5085..714dcfe3a469 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -1030,14 +1030,12 @@ static void bmac_set_multicast(struct net_device *dev) rx_cfg |= RxPromiscEnable; bmwrite(dev, RXCFG, rx_cfg); } else { - u16 hash_table[4]; + u16 hash_table[4] = { 0 }; rx_cfg = bmread(dev, RXCFG); rx_cfg &= ~RxPromiscEnable; bmwrite(dev, RXCFG, rx_cfg); - for(i = 0; i < 4; i++) hash_table[i] = 0; - netdev_for_each_mc_addr(ha, dev) { crc = ether_crc_le(6, ha->addr); crc >>= 26; -- GitLab From 35e729ac5d5c1a164aee475583cb9830e9707b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 17 May 2013 10:42:55 +0000 Subject: [PATCH 0098/2900] net: ethernet: davicom: dm9000: initialize variables directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the code a bit to initialize the variables directly when defining them. Signed-off-by: Emilio López Signed-off-by: David S. Miller --- drivers/net/ethernet/davicom/dm9000.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 9105465b2a1a..a2408c84bbdd 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -827,7 +827,7 @@ dm9000_hash_table_unlocked(struct net_device *dev) struct netdev_hw_addr *ha; int i, oft; u32 hash_val; - u16 hash_table[4]; + u16 hash_table[4] = { 0, 0, 0, 0x8000 }; /* broadcast address */ u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN; dm9000_dbg(db, 1, "entering %s\n", __func__); @@ -835,13 +835,6 @@ dm9000_hash_table_unlocked(struct net_device *dev) for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) iow(db, oft, dev->dev_addr[i]); - /* Clear Hash Table */ - for (i = 0; i < 4; i++) - hash_table[i] = 0x0; - - /* broadcast address */ - hash_table[3] = 0x8000; - if (dev->flags & IFF_PROMISC) rcr |= RCR_PRMSC; -- GitLab From e998fd413e5e7dac750dfe79c79cbf8f417d41b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= Date: Fri, 17 May 2013 10:42:56 +0000 Subject: [PATCH 0099/2900] net: ethernet: korina: initialize variables directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the code a bit to initialize the variables directly when defining them. Signed-off-by: Emilio López Signed-off-by: David S. Miller --- drivers/net/ethernet/korina.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 5409fe876a44..0b5708520121 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -495,12 +495,9 @@ static void korina_multicast_list(struct net_device *dev) /* Build the hash table */ if (netdev_mc_count(dev) > 4) { - u16 hash_table[4]; + u16 hash_table[4] = { 0 }; u32 crc; - for (i = 0; i < 4; i++) - hash_table[i] = 0; - netdev_for_each_mc_addr(ha, dev) { crc = ether_crc_le(6, ha->addr); crc >>= 26; -- GitLab From 553675fb5e9ce3d71aa6cb527f98cd34793c0dbc Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 16 May 2013 11:35:20 +0000 Subject: [PATCH 0100/2900] vxlan: listen on multiple ports The commit 823aa873bc782f1c51b1ce8ec6da7cfcaf93836e Author: stephen hemminger Date: Sat Apr 27 11:31:57 2013 +0000 vxlan: allow choosing destination port per vxlan introduced per-vxlan UDP port configuration but only did half of the necessary work. It added per vxlan destination for sending, but overlooked the handling of multiple ports for incoming traffic. This patch changes the listening port management to handle multiple incoming UDP ports. The earlier per-namespace structure is now a hash list per namespace. It is also now possible to define the same virtual network id but with different UDP port values which can be useful for migration. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 263 ++++++++++++++++++++++++++++++-------------- 1 file changed, 181 insertions(+), 82 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ba81f3c39a83..80d359c6310b 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -44,6 +44,8 @@ #define VXLAN_VERSION "0.1" +#define PORT_HASH_BITS 8 +#define PORT_HASH_SIZE (1<vni_list[hash_32(id, VNI_HASH_BITS)]; +} + +/* Socket hash table head */ +static inline struct hlist_head *vs_head(struct net *net, __be16 port) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); - return &vn->vni_list[hash_32(id, VNI_HASH_BITS)]; + return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; +} + +/* Find VXLAN socket based on network namespace and UDP port */ +static struct vxlan_sock *vxlan_find_port(struct net *net, __be16 port) +{ + struct vxlan_sock *vs; + + hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { + if (inet_sk(vs->sock->sk)->inet_sport == port) + return vs; + } + return NULL; } /* Look up VNI in a per net namespace table */ -static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id) +static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port) { + struct vxlan_sock *vs; struct vxlan_dev *vxlan; - hlist_for_each_entry_rcu(vxlan, vni_head(net, id), hlist) { + vs = vxlan_find_port(net, port); + if (!vs) + return NULL; + + hlist_for_each_entry_rcu(vxlan, vni_head(vs, id), hlist) { if (vxlan->default_dst.remote_vni == id) return vxlan; } @@ -592,20 +631,18 @@ static void vxlan_snoop(struct net_device *dev, static bool vxlan_group_used(struct vxlan_net *vn, const struct vxlan_dev *this) { - const struct vxlan_dev *vxlan; - unsigned h; + struct vxlan_dev *vxlan; - for (h = 0; h < VNI_HASH_SIZE; ++h) - hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist) { - if (vxlan == this) - continue; + list_for_each_entry(vxlan, &vn->vxlan_list, next) { + if (vxlan == this) + continue; - if (!netif_running(vxlan->dev)) - continue; + if (!netif_running(vxlan->dev)) + continue; - if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip) - return true; - } + if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip) + return true; + } return false; } @@ -615,7 +652,7 @@ static int vxlan_join_group(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct sock *sk = vn->sock->sk; + struct sock *sk = vxlan->vn_sock->sock->sk; struct ip_mreqn mreq = { .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, .imr_ifindex = vxlan->default_dst.remote_ifindex, @@ -643,7 +680,7 @@ static int vxlan_leave_group(struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); int err = 0; - struct sock *sk = vn->sock->sk; + struct sock *sk = vxlan->vn_sock->sock->sk; struct ip_mreqn mreq = { .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, .imr_ifindex = vxlan->default_dst.remote_ifindex, @@ -670,6 +707,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) struct vxlanhdr *vxh; struct vxlan_dev *vxlan; struct pcpu_tstats *stats; + __be16 port; __u32 vni; int err; @@ -693,9 +731,11 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) /* Is this VNI defined? */ vni = ntohl(vxh->vx_vni) >> 8; - vxlan = vxlan_find_vni(sock_net(sk), vni); + port = inet_sk(sk)->inet_sport; + vxlan = vxlan_find_vni(sock_net(sk), vni, port); if (!vxlan) { - netdev_dbg(skb->dev, "unknown vni %d\n", vni); + netdev_dbg(skb->dev, "unknown vni %d port %u\n", + vni, ntohs(port)); goto drop; } @@ -875,7 +915,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) return false; } -static void vxlan_sock_free(struct sk_buff *skb) +static void vxlan_sock_put(struct sk_buff *skb) { sock_put(skb->sk); } @@ -883,13 +923,13 @@ static void vxlan_sock_free(struct sk_buff *skb) /* On transmit, associate with the tunnel socket */ static void vxlan_set_owner(struct net_device *dev, struct sk_buff *skb) { - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct sock *sk = vn->sock->sk; + struct vxlan_dev *vxlan = netdev_priv(dev); + struct sock *sk = vxlan->vn_sock->sock->sk; skb_orphan(skb); sock_hold(sk); skb->sk = sk; - skb->destructor = vxlan_sock_free; + skb->destructor = vxlan_sock_put; } /* Compute source port for outgoing packet @@ -1031,7 +1071,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct vxlan_dev *dst_vxlan; ip_rt_put(rt); - dst_vxlan = vxlan_find_vni(dev_net(dev), vni); + dst_vxlan = vxlan_find_vni(dev_net(dev), vni, dst_port); if (!dst_vxlan) goto tx_error; vxlan_encap_bypass(skb, vxlan, dst_vxlan); @@ -1306,6 +1346,7 @@ static void vxlan_setup(struct net_device *dev) dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); init_timer_deferrable(&vxlan->age_timer); @@ -1390,11 +1431,78 @@ static const struct ethtool_ops vxlan_ethtool_ops = { .get_link = ethtool_op_get_link, }; +static void vxlan_del_work(struct work_struct *work) +{ + struct vxlan_sock *vs = container_of(work, struct vxlan_sock, del_work); + + sk_release_kernel(vs->sock->sk); + kfree_rcu(vs, rcu); +} + +/* Create new listen socket if needed */ +static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) +{ + struct vxlan_sock *vs; + struct sock *sk; + struct sockaddr_in vxlan_addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_ANY), + }; + int rc; + unsigned h; + + vs = kmalloc(sizeof(*vs), GFP_KERNEL); + if (!vs) + return ERR_PTR(-ENOMEM); + + for (h = 0; h < VNI_HASH_SIZE; ++h) + INIT_HLIST_HEAD(&vs->vni_list[h]); + + INIT_WORK(&vs->del_work, vxlan_del_work); + + /* Create UDP socket for encapsulation receive. */ + rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vs->sock); + if (rc < 0) { + pr_debug("UDP socket create failed\n"); + kfree(vs); + return ERR_PTR(rc); + } + + /* Put in proper namespace */ + sk = vs->sock->sk; + sk_change_net(sk, net); + + vxlan_addr.sin_port = port; + + rc = kernel_bind(vs->sock, (struct sockaddr *) &vxlan_addr, + sizeof(vxlan_addr)); + if (rc < 0) { + pr_debug("bind for UDP socket %pI4:%u (%d)\n", + &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); + sk_release_kernel(sk); + kfree(vs); + return ERR_PTR(rc); + } + + /* Disable multicast loopback */ + inet_sk(sk)->mc_loop = 0; + + /* Mark socket as an encapsulation socket. */ + udp_sk(sk)->encap_type = 1; + udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; + udp_encap_enable(); + + vs->refcnt = 1; + return vs; +} + static int vxlan_newlink(struct net *net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { + struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; + struct vxlan_sock *vs; __u32 vni; int err; @@ -1402,10 +1510,6 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, return -EINVAL; vni = nla_get_u32(data[IFLA_VXLAN_ID]); - if (vxlan_find_vni(net, vni)) { - pr_info("duplicate VNI %u\n", vni); - return -EEXIST; - } dst->remote_vni = vni; if (data[IFLA_VXLAN_GROUP]) @@ -1471,22 +1575,58 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, if (data[IFLA_VXLAN_PORT]) vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); + if (vxlan_find_vni(net, vni, vxlan->dst_port)) { + pr_info("duplicate VNI %u\n", vni); + return -EEXIST; + } + + vs = vxlan_find_port(net, vxlan->dst_port); + if (vs) + ++vs->refcnt; + else { + /* Drop lock because socket create acquires RTNL lock */ + rtnl_unlock(); + vs = vxlan_socket_create(net, vxlan->dst_port); + rtnl_lock(); + if (IS_ERR(vs)) + return PTR_ERR(vs); + + hlist_add_head_rcu(&vs->hlist, vs_head(net, vxlan->dst_port)); + } + vxlan->vn_sock = vs; + SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); err = register_netdevice(dev); - if (!err) - hlist_add_head_rcu(&vxlan->hlist, vni_head(net, dst->remote_vni)); + if (err) { + if (--vs->refcnt == 0) { + rtnl_unlock(); + sk_release_kernel(vs->sock->sk); + kfree(vs); + rtnl_lock(); + } + return err; + } - return err; + list_add(&vxlan->next, &vn->vxlan_list); + hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); + + return 0; } static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_sock *vs = vxlan->vn_sock; hlist_del_rcu(&vxlan->hlist); - + list_del(&vxlan->next); unregister_netdevice_queue(dev, head); + + if (--vs->refcnt == 0) { + hlist_del_rcu(&vs->hlist); + schedule_work(&vs->del_work); + } } static size_t vxlan_get_size(const struct net_device *dev) @@ -1572,46 +1712,12 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = { static __net_init int vxlan_init_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); - struct sock *sk; - struct sockaddr_in vxlan_addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_ANY), - }; - int rc; unsigned h; - /* Create UDP socket for encapsulation receive. */ - rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vn->sock); - if (rc < 0) { - pr_debug("UDP socket create failed\n"); - return rc; - } - /* Put in proper namespace */ - sk = vn->sock->sk; - sk_change_net(sk, net); - - vxlan_addr.sin_port = htons(vxlan_port); - - rc = kernel_bind(vn->sock, (struct sockaddr *) &vxlan_addr, - sizeof(vxlan_addr)); - if (rc < 0) { - pr_debug("bind for UDP socket %pI4:%u (%d)\n", - &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc); - sk_release_kernel(sk); - vn->sock = NULL; - return rc; - } - - /* Disable multicast loopback */ - inet_sk(sk)->mc_loop = 0; + INIT_LIST_HEAD(&vn->vxlan_list); - /* Mark socket as an encapsulation socket. */ - udp_sk(sk)->encap_type = 1; - udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; - udp_encap_enable(); - - for (h = 0; h < VNI_HASH_SIZE; ++h) - INIT_HLIST_HEAD(&vn->vni_list[h]); + for (h = 0; h < PORT_HASH_SIZE; ++h) + INIT_HLIST_HEAD(&vn->sock_list[h]); return 0; } @@ -1620,18 +1726,11 @@ static __net_exit void vxlan_exit_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan; - unsigned h; rtnl_lock(); - for (h = 0; h < VNI_HASH_SIZE; ++h) - hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist) - dev_close(vxlan->dev); + list_for_each_entry(vxlan, &vn->vxlan_list, next) + dev_close(vxlan->dev); rtnl_unlock(); - - if (vn->sock) { - sk_release_kernel(vn->sock->sk); - vn->sock = NULL; - } } static struct pernet_operations vxlan_net_ops = { -- GitLab From 18cf1f1270e7f01be5217203c9f46c5d88a54839 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 17:48:07 +0000 Subject: [PATCH 0101/2900] net/usb: r8152: Remove redundant version.h header inclusion version.h header inclusion is not necessary as detected by checkversion.pl. Signed-off-by: Sachin Kamat Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 14e519888631..8e53e4110811 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include -- GitLab From b4236daa410e4e778a938ac1151bf94d94c55efc Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 17:48:08 +0000 Subject: [PATCH 0102/2900] net/usb: r8152: Use module_usb_driver() module_usb_driver() eliminates boilerplate and simplifies the code. Signed-off-by: Sachin Kamat Cc: Realtek linux nic maintainers Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 8e53e4110811..d02bac82fc57 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1748,18 +1748,7 @@ static struct usb_driver rtl8152_driver = { .resume = rtl8152_resume }; -static int __init usb_rtl8152_init(void) -{ - return usb_register(&rtl8152_driver); -} - -static void __exit usb_rtl8152_exit(void) -{ - usb_deregister(&rtl8152_driver); -} - -module_init(usb_rtl8152_init); -module_exit(usb_rtl8152_exit); +module_usb_driver(rtl8152_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -- GitLab From 650c8496702f2910c506ccf66685893302e1796e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 16 May 2013 19:45:30 +0000 Subject: [PATCH 0103/2900] x86: bpf_jit_comp: can call module_free() from any context It looks like we can call module_free()/vfree() from softirq context, so no longer need a wrapper and a work_struct. Signed-off-by: Eric Dumazet Cc: Al Viro Signed-off-by: David S. Miller --- arch/x86/net/bpf_jit_comp.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index f66b54086ce5..c0212db40032 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -717,9 +717,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { - image = module_alloc(max_t(unsigned int, - proglen, - sizeof(struct work_struct))); + image = module_alloc(proglen); if (!image) goto out; } @@ -738,20 +736,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; return; } -static void jit_free_defer(struct work_struct *arg) -{ - module_free(NULL, arg); -} - -/* run from softirq, we must use a work_struct to call - * module_free() from process context - */ void bpf_jit_free(struct sk_filter *fp) { - if (fp->bpf_func != sk_run_filter) { - struct work_struct *work = (struct work_struct *)fp->bpf_func; - - INIT_WORK(work, jit_free_defer); - schedule_work(work); - } + if (fp->bpf_func != sk_run_filter) + module_free(NULL, fp->bpf_func); } -- GitLab From f1db320ec5788d5fcc05c0285bd0980319185497 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 16 May 2013 23:24:28 +0000 Subject: [PATCH 0104/2900] xen-netback: remove dead code The array mmap_pages is never touched in the initialization function. This is remnant of mapping mechanism, which does not exist upstream. In current upstream code this array only tracks usage of pages inside netback. Those pages are allocated when contructing a SKB and passed directly to network subsystem. Signed-off-by: Wei Liu Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 37984e6d4e99..295a9c267df4 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1939,10 +1939,6 @@ static int __init netback_init(void) failed_init: while (--group >= 0) { struct xen_netbk *netbk = &xen_netbk[group]; - for (i = 0; i < MAX_PENDING_REQS; i++) { - if (netbk->mmap_pages[i]) - __free_page(netbk->mmap_pages[i]); - } del_timer(&netbk->net_timer); kthread_stop(netbk->task); } -- GitLab From b103f358d9f6f58658f1a6dc08912ab921dd86f1 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 16 May 2013 23:26:11 +0000 Subject: [PATCH 0105/2900] xen-netback: enable user to unload netback module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enables user to unload netback module, which is useful when user wants to upgrade to a newer netback module without rebooting the host. Netfront cannot handle netback removal event. As we cannot fix all possible frontends we add module get / put along with vif get / put to avoid mis-unloading of netback. To unload netback module, user needs to shutdown all VMs or migrate them to another host or unplug all vifs before hand. Signed-off-by: Wei Liu Acked-by: Ian Campbell ¬ Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/interface.c | 19 ++++++++++++++++++- drivers/net/xen-netback/netback.c | 20 ++++++++++++++++++++ drivers/net/xen-netback/xenbus.c | 5 +++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 9d7f1723dd8f..6102a6c59f4e 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -120,6 +120,7 @@ void xenvif_get(struct xenvif *vif); void xenvif_put(struct xenvif *vif); int xenvif_xenbus_init(void); +void xenvif_xenbus_fini(void); int xenvif_schedulable(struct xenvif *vif); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index d98414168485..82202c2b1bd1 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -316,6 +316,8 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, if (vif->irq) return 0; + __module_get(THIS_MODULE); + err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); if (err < 0) goto err; @@ -343,6 +345,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, err_unmap: xen_netbk_unmap_frontend_rings(vif); err: + module_put(THIS_MODULE); return err; } @@ -360,18 +363,32 @@ void xenvif_carrier_off(struct xenvif *vif) void xenvif_disconnect(struct xenvif *vif) { + /* Disconnect funtion might get called by generic framework + * even before vif connects, so we need to check if we really + * need to do a module_put. + */ + int need_module_put = 0; + if (netif_carrier_ok(vif->dev)) xenvif_carrier_off(vif); atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); - if (vif->irq) + if (vif->irq) { unbind_from_irqhandler(vif->irq, vif); + /* vif->irq is valid, we had a module_get in + * xenvif_connect. + */ + need_module_put = 1; + } unregister_netdev(vif->dev); xen_netbk_unmap_frontend_rings(vif); free_netdev(vif->dev); + + if (need_module_put) + module_put(THIS_MODULE); } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 295a9c267df4..2d9477fd900f 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1949,5 +1949,25 @@ static int __init netback_init(void) module_init(netback_init); +static void __exit netback_fini(void) +{ + int i, j; + + xenvif_xenbus_fini(); + + for (i = 0; i < xen_netbk_group_nr; i++) { + struct xen_netbk *netbk = &xen_netbk[i]; + del_timer_sync(&netbk->net_timer); + kthread_stop(netbk->task); + for (j = 0; j < MAX_PENDING_REQS; j++) { + if (netbk->mmap_pages[i]) + __free_page(netbk->mmap_pages[i]); + } + } + + vfree(xen_netbk); +} +module_exit(netback_fini); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("xen-backend:vif"); diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 410018c4c528..d230c145660c 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -485,3 +485,8 @@ int xenvif_xenbus_init(void) { return xenbus_register_backend(&netback_driver); } + +void xenvif_xenbus_fini(void) +{ + return xenbus_unregister_driver(&netback_driver); +} -- GitLab From 57b354e66b67c4c72468a26d4313d1217ef32e17 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 16 May 2013 23:36:32 +0000 Subject: [PATCH 0106/2900] dev: remove duplicate 'skb->dev = dev' in dev_forward_skb() This was added by commit 59b9997baba5 (Revert "net: maintain namespace isolation between vlan and real device"). In fact, before the initial commit - the one that is reverted -, this statement was not present. 'skb->dev = dev' is already done in eth_type_trans(), which is call just after. Spotted-by: Alain Ritoux Signed-off-by: Nicolas Dichtel Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index fc1e289397f5..18e9730cc4be 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1629,7 +1629,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) return NET_RX_DROP; } skb->skb_iif = 0; - skb->dev = dev; skb_dst_drop(skb); skb->tstamp.tv64 = 0; skb->pkt_type = PACKET_HOST; -- GitLab From 5199dfe531db19f3ac76542753849877e9854441 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 May 2013 12:12:34 +0000 Subject: [PATCH 0107/2900] sparc: bpf_jit_comp: can call module_free() from any context module_free()/vfree() takes care of details, we no longer need a wrapper and a work_struct. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- arch/sparc/net/bpf_jit_comp.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index d36a85ebb5e0..9c7be59e6f5a 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c @@ -785,9 +785,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; break; } if (proglen == oldproglen) { - image = module_alloc(max_t(unsigned int, - proglen, - sizeof(struct work_struct))); + image = module_alloc(proglen); if (!image) goto out; } @@ -806,20 +804,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf]; return; } -static void jit_free_defer(struct work_struct *arg) -{ - module_free(NULL, arg); -} - -/* run from softirq, we must use a work_struct to call - * module_free() from process context - */ void bpf_jit_free(struct sk_filter *fp) { - if (fp->bpf_func != sk_run_filter) { - struct work_struct *work = (struct work_struct *)fp->bpf_func; - - INIT_WORK(work, jit_free_defer); - schedule_work(work); - } + if (fp->bpf_func != sk_run_filter) + module_free(NULL, fp->bpf_func); } -- GitLab From caeaba79009c2ee858c3b2bf8caf922cd719fead Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 16 May 2013 22:32:00 +0000 Subject: [PATCH 0108/2900] ipv6: add support of peer address This patch adds the support of peer address for IPv6. For example, it is possible to specify the remote end of a 6inY tunnel. This was already possible in IPv4: ip addr add ip1 peer ip2 dev dev1 The peer address is specified with IFA_ADDRESS and the local address with IFA_LOCAL (like explained in include/uapi/linux/if_addr.h). Note that the API is not changed, because before this patch, it was not possible to specify two different addresses in IFA_LOCAL and IFA_REMOTE. There is a small change for the dump: if the peer is different from ::, IFA_ADDRESS will contain the peer address instead of the local address. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/if_inet6.h | 1 + net/ipv6/addrconf.c | 64 +++++++++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 100fb8cec17c..0727d0e4af3b 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -74,6 +74,7 @@ struct inet6_ifaddr { bool tokenized; struct rcu_head rcu; + struct in6_addr peer_addr; }; struct ip6_sf_socklist { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d1ab6ab29a55..d684d23bc027 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2402,6 +2402,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg) * Manual configuration of address on an interface */ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, + const struct in6_addr *peer_pfx, unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) { @@ -2457,6 +2458,8 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p ifp->valid_lft = valid_lft; ifp->prefered_lft = prefered_lft; ifp->tstamp = jiffies; + if (peer_pfx) + ifp->peer_addr = *peer_pfx; spin_unlock_bh(&ifp->lock); addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, @@ -2526,7 +2529,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg) return -EFAULT; rtnl_lock(); - err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, + err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL, ireq.ifr6_prefixlen, IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); rtnl_unlock(); @@ -3610,18 +3613,20 @@ static void addrconf_verify(unsigned long foo) rcu_read_unlock_bh(); } -static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) +static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local, + struct in6_addr **peer_pfx) { struct in6_addr *pfx = NULL; + *peer_pfx = NULL; + if (addr) pfx = nla_data(addr); if (local) { if (pfx && nla_memcmp(local, pfx, sizeof(*pfx))) - pfx = NULL; - else - pfx = nla_data(local); + *peer_pfx = pfx; + pfx = nla_data(local); } return pfx; @@ -3639,7 +3644,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) struct net *net = sock_net(skb->sk); struct ifaddrmsg *ifm; struct nlattr *tb[IFA_MAX+1]; - struct in6_addr *pfx; + struct in6_addr *pfx, *peer_pfx; int err; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); @@ -3647,7 +3652,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) return err; ifm = nlmsg_data(nlh); - pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); + pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx); if (pfx == NULL) return -EINVAL; @@ -3705,7 +3710,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) struct net *net = sock_net(skb->sk); struct ifaddrmsg *ifm; struct nlattr *tb[IFA_MAX+1]; - struct in6_addr *pfx; + struct in6_addr *pfx, *peer_pfx; struct inet6_ifaddr *ifa; struct net_device *dev; u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME; @@ -3717,7 +3722,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) return err; ifm = nlmsg_data(nlh); - pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); + pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx); if (pfx == NULL) return -EINVAL; @@ -3745,7 +3750,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh) * It would be best to check for !NLM_F_CREATE here but * userspace alreay relies on not having to provide this. */ - return inet6_addr_add(net, ifm->ifa_index, pfx, + return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx, ifm->ifa_prefixlen, ifa_flags, preferred_lft, valid_lft); } @@ -3802,6 +3807,7 @@ static inline int rt_scope(int ifa_scope) static inline int inet6_ifaddr_msgsize(void) { return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + + nla_total_size(16) /* IFA_LOCAL */ + nla_total_size(16) /* IFA_ADDRESS */ + nla_total_size(sizeof(struct ifa_cacheinfo)); } @@ -3840,13 +3846,22 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, valid = INFINITY_LIFE_TIME; } - if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 || - put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) { - nlmsg_cancel(skb, nlh); - return -EMSGSIZE; - } + if (ipv6_addr_type(&ifa->peer_addr) != IPV6_ADDR_ANY) { + if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 || + nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0) + goto error; + } else + if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0) + goto error; + + if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) + goto error; return nlmsg_end(skb, nlh); + +error: + nlmsg_cancel(skb, nlh); + return -EMSGSIZE; } static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, @@ -4046,7 +4061,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh) struct net *net = sock_net(in_skb->sk); struct ifaddrmsg *ifm; struct nlattr *tb[IFA_MAX+1]; - struct in6_addr *addr = NULL; + struct in6_addr *addr = NULL, *peer; struct net_device *dev = NULL; struct inet6_ifaddr *ifa; struct sk_buff *skb; @@ -4056,7 +4071,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh) if (err < 0) goto errout; - addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); + addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer); if (addr == NULL) { err = -EINVAL; goto errout; @@ -4564,11 +4579,26 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ip6_ins_rt(ifp->rt); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); + if (ipv6_addr_type(&ifp->peer_addr) != IPV6_ADDR_ANY) + addrconf_prefix_route(&ifp->peer_addr, 128, + ifp->idev->dev, 0, 0); break; case RTM_DELADDR: if (ifp->idev->cnf.forwarding) addrconf_leave_anycast(ifp); addrconf_leave_solict(ifp->idev, &ifp->addr); + if (ipv6_addr_type(&ifp->peer_addr) != IPV6_ADDR_ANY) { + struct rt6_info *rt; + struct net_device *dev = ifp->idev->dev; + + rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL, + dev->ifindex, 1); + if (rt) { + dst_hold(&rt->dst); + if (ip6_del_rt(rt)) + dst_free(&rt->dst); + } + } dst_hold(&ifp->rt->dst); if (ip6_del_rt(ifp->rt)) -- GitLab From 3cc7587b30032b7c4dd9610a55a77519e84da7db Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Fri, 17 May 2013 09:10:34 +0000 Subject: [PATCH 0109/2900] Documentation/sysctl/net.txt: fix (attribute removal). This patch removes mentioning the sysfsf net_device weight attribute (class/net//weight) in Documentation/sysctl/net.txt, since the net sysfs weight attribute was removed by the following patch: [NET]: Make NAPI polling independent of struct net_device objects bea3348eef27e6044b6161fd04c3152215f96411 Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 98335b7a5337..c1f8640c2fc8 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -93,8 +93,7 @@ netdev_budget Maximum number of packets taken from all interfaces in one polling cycle (NAPI poll). In one polling cycle interfaces which are registered to polling are -probed in a round-robin manner. The limit of packets in one such probe can be -set per-device via sysfs class/net//weight . +probed in a round-robin manner. netdev_max_backlog ------------------ -- GitLab From 3e59cb0ddfd2c59991f38e89352ad8a3c71b2374 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Fri, 17 May 2013 13:45:05 +0000 Subject: [PATCH 0110/2900] tcp: remove bad timeout logic in fast recovery tcp_timeout_skb() was intended to trigger fast recovery on timeout, unfortunately in reality it often causes spurious retransmission storms during fast recovery. The particular sign is a fast retransmit over the highest sacked sequence (SND.FACK). Currently the RTO timer re-arming (as in RFC6298) offers a nice cushion to avoid spurious timeout: when SND.UNA advances the sender re-arms RTO and extends the timeout by icsk_rto. The sender does not offset the time elapsed since the packet at SND.UNA was sent. But if the next (DUP)ACK arrives later than ~RTTVAR and triggers tcp_fastretrans_alert(), then tcp_timeout_skb() will mark any packet sent before the icsk_rto interval lost, including one that's above the highest sacked sequence. Most likely a large part of scorebard will be marked. If most packets are not lost then the subsequent DUPACKs with new SACK blocks will cause the sender to continue to retransmit packets beyond SND.FACK spuriously. Even if only one packet is lost the sender may falsely retransmit almost the entire window. The situation becomes common in the world of bufferbloat: the RTT continues to grow as the queue builds up but RTTVAR remains small and close to the minimum 200ms. If a data packet is lost and the DUPACK triggered by the next data packet is slightly delayed, then a spurious retransmission storm forms. As the original comment on tcp_timeout_skb() suggests: the usefulness of this feature is questionable. It also wastes cycles walking the sack scoreboard and is actually harmful because of false recovery. It's time to remove this. Signed-off-by: Yuchung Cheng Acked-by: Eric Dumazet Acked-by: Neal Cardwell Acked-by: Nandita Dukkipati Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 - include/net/tcp.h | 1 - net/ipv4/tcp_input.c | 65 +------------------------------------------- 3 files changed, 1 insertion(+), 66 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 5adbc33d1ab3..472120b4fac5 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -246,7 +246,6 @@ struct tcp_sock { /* from STCP, retrans queue hinting */ struct sk_buff* lost_skb_hint; - struct sk_buff *scoreboard_skb_hint; struct sk_buff *retransmit_skb_hint; struct sk_buff_head out_of_order_queue; /* Out of order segments go here */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 5bba80fbd1d9..e1c3723f161f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1193,7 +1193,6 @@ static inline void tcp_mib_init(struct net *net) static inline void tcp_clear_retrans_hints_partial(struct tcp_sock *tp) { tp->lost_skb_hint = NULL; - tp->scoreboard_skb_hint = NULL; } static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b358e8c98607..d7d369428ae4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1255,8 +1255,6 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, if (skb == tp->retransmit_skb_hint) tp->retransmit_skb_hint = prev; - if (skb == tp->scoreboard_skb_hint) - tp->scoreboard_skb_hint = prev; if (skb == tp->lost_skb_hint) { tp->lost_skb_hint = prev; tp->lost_cnt_hint -= tcp_skb_pcount(prev); @@ -1964,20 +1962,6 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag) return true; } -static inline int tcp_skb_timedout(const struct sock *sk, - const struct sk_buff *skb) -{ - return tcp_time_stamp - TCP_SKB_CB(skb)->when > inet_csk(sk)->icsk_rto; -} - -static inline int tcp_head_timedout(const struct sock *sk) -{ - const struct tcp_sock *tp = tcp_sk(sk); - - return tp->packets_out && - tcp_skb_timedout(sk, tcp_write_queue_head(sk)); -} - /* Linux NewReno/SACK/FACK/ECN state machine. * -------------------------------------- * @@ -2084,12 +2068,6 @@ static bool tcp_time_to_recover(struct sock *sk, int flag) if (tcp_dupack_heuristics(tp) > tp->reordering) return true; - /* Trick#3 : when we use RFC2988 timer restart, fast - * retransmit can be triggered by timeout of queue head. - */ - if (tcp_is_fack(tp) && tcp_head_timedout(sk)) - return true; - /* Trick#4: It is still not OK... But will it be useful to delay * recovery more? */ @@ -2126,44 +2104,6 @@ static bool tcp_time_to_recover(struct sock *sk, int flag) return false; } -/* New heuristics: it is possible only after we switched to restart timer - * each time when something is ACKed. Hence, we can detect timed out packets - * during fast retransmit without falling to slow start. - * - * Usefulness of this as is very questionable, since we should know which of - * the segments is the next to timeout which is relatively expensive to find - * in general case unless we add some data structure just for that. The - * current approach certainly won't find the right one too often and when it - * finally does find _something_ it usually marks large part of the window - * right away (because a retransmission with a larger timestamp blocks the - * loop from advancing). -ij - */ -static void tcp_timeout_skbs(struct sock *sk) -{ - struct tcp_sock *tp = tcp_sk(sk); - struct sk_buff *skb; - - if (!tcp_is_fack(tp) || !tcp_head_timedout(sk)) - return; - - skb = tp->scoreboard_skb_hint; - if (tp->scoreboard_skb_hint == NULL) - skb = tcp_write_queue_head(sk); - - tcp_for_write_queue_from(skb, sk) { - if (skb == tcp_send_head(sk)) - break; - if (!tcp_skb_timedout(sk, skb)) - break; - - tcp_skb_mark_lost(tp, skb); - } - - tp->scoreboard_skb_hint = skb; - - tcp_verify_left_out(tp); -} - /* Detect loss in event "A" above by marking head of queue up as lost. * For FACK or non-SACK(Reno) senders, the first "packets" number of segments * are considered lost. For RFC3517 SACK, a segment is considered lost if it @@ -2249,8 +2189,6 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) else if (fast_rexmit) tcp_mark_head_lost(sk, 1, 1); } - - tcp_timeout_skbs(sk); } /* CWND moderation, preventing bursts due to too big ACKs @@ -2842,7 +2780,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, fast_rexmit = 1; } - if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk))) + if (do_lost) tcp_update_scoreboard(sk, fast_rexmit); tcp_cwnd_reduction(sk, newly_acked_sacked, fast_rexmit); tcp_xmit_retransmit_queue(sk); @@ -3075,7 +3013,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, tcp_unlink_write_queue(skb, sk); sk_wmem_free_skb(sk, skb); - tp->scoreboard_skb_hint = NULL; if (skb == tp->retransmit_skb_hint) tp->retransmit_skb_hint = NULL; if (skb == tp->lost_skb_hint) -- GitLab From 314beb9bcabfd6b4542ccbced2402af2c6f6142a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 May 2013 16:37:03 +0000 Subject: [PATCH 0111/2900] x86: bpf_jit_comp: secure bpf jit against spraying attacks hpa bringed into my attention some security related issues with BPF JIT on x86. This patch makes sure the bpf generated code is marked read only, as other kernel text sections. It also splits the unused space (we vmalloc() and only use a fraction of the page) in two parts, so that the generated bpf code not starts at a known offset in the page, but a pseudo random one. Refs: http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html Reported-by: H. Peter Anvin Signed-off-by: Eric Dumazet Reviewed-by: Daniel Borkmann Signed-off-by: David S. Miller --- arch/x86/net/bpf_jit_comp.c | 53 ++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index c0212db40032..79c216aa0e2b 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -12,6 +12,7 @@ #include #include #include +#include /* * Conventions : @@ -144,6 +145,39 @@ static int pkt_type_offset(void) return -1; } +struct bpf_binary_header { + unsigned int pages; + /* Note : for security reasons, bpf code will follow a randomly + * sized amount of int3 instructions + */ + u8 image[]; +}; + +static struct bpf_binary_header *bpf_alloc_binary(unsigned int proglen, + u8 **image_ptr) +{ + unsigned int sz, hole; + struct bpf_binary_header *header; + + /* Most of BPF filters are really small, + * but if some of them fill a page, allow at least + * 128 extra bytes to insert a random section of int3 + */ + sz = round_up(proglen + sizeof(*header) + 128, PAGE_SIZE); + header = module_alloc(sz); + if (!header) + return NULL; + + memset(header, 0xcc, sz); /* fill whole space with int3 instructions */ + + header->pages = sz / PAGE_SIZE; + hole = sz - (proglen + sizeof(*header)); + + /* insert a random number of int3 instructions before BPF code */ + *image_ptr = &header->image[prandom_u32() % hole]; + return header; +} + void bpf_jit_compile(struct sk_filter *fp) { u8 temp[64]; @@ -153,6 +187,7 @@ void bpf_jit_compile(struct sk_filter *fp) int t_offset, f_offset; u8 t_op, f_op, seen = 0, pass; u8 *image = NULL; + struct bpf_binary_header *header = NULL; u8 *func; int pc_ret0 = -1; /* bpf index of first RET #0 instruction (if any) */ unsigned int cleanup_addr; /* epilogue code offset */ @@ -693,7 +728,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; if (unlikely(proglen + ilen > oldproglen)) { pr_err("bpb_jit_compile fatal error\n"); kfree(addrs); - module_free(NULL, image); + module_free(NULL, header); return; } memcpy(image + proglen, temp, ilen); @@ -717,8 +752,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; break; } if (proglen == oldproglen) { - image = module_alloc(proglen); - if (!image) + header = bpf_alloc_binary(proglen, &image); + if (!header) goto out; } oldproglen = proglen; @@ -728,7 +763,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; bpf_jit_dump(flen, proglen, pass, image); if (image) { - bpf_flush_icache(image, image + proglen); + bpf_flush_icache(header, image + proglen); + set_memory_ro((unsigned long)header, header->pages); fp->bpf_func = (void *)image; } out: @@ -738,6 +774,11 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i]; void bpf_jit_free(struct sk_filter *fp) { - if (fp->bpf_func != sk_run_filter) - module_free(NULL, fp->bpf_func); + if (fp->bpf_func != sk_run_filter) { + unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; + struct bpf_binary_header *header = (void *)addr; + + set_memory_rw(addr, header->pages); + module_free(NULL, header); + } } -- GitLab From 164954454a4b1000eb022415654001cceb9259a7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 17 May 2013 16:57:37 +0000 Subject: [PATCH 0112/2900] filter: do not output bpf image address for security reason Do not leak starting address of BPF JIT code for non root users, as it might help intruders to perform an attack. Signed-off-by: Eric Dumazet Cc: Ben Hutchings Cc: Daniel Borkmann Signed-off-by: David S. Miller --- include/linux/filter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/filter.h b/include/linux/filter.h index c050dcc322a4..56a6b7fbb3c6 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -58,10 +58,10 @@ extern void bpf_jit_free(struct sk_filter *fp); static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen, u32 pass, void *image) { - pr_err("flen=%u proglen=%u pass=%u image=%p\n", + pr_err("flen=%u proglen=%u pass=%u image=%pK\n", flen, proglen, pass, image); if (image) - print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_ADDRESS, + print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET, 16, 1, image, proglen, false); } #define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns) -- GitLab From 9e2ecbeb250dee67f4bd06a18637c120b48a4865 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Sat, 18 May 2013 06:26:52 +0000 Subject: [PATCH 0113/2900] tg3: Add ethtool_eee struct and tg3_setup_eee() Add an eee structure and update it with eee settings. This will be used for set/get_eee operations. Add common function tg3_setup_eee() that will be used in the subsequent patches. Reviewed-by: Ben Li Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 91 ++++++++++++++++++----------- drivers/net/ethernet/broadcom/tg3.h | 1 + 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 728d42ab2a76..26804db1f884 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4249,6 +4249,16 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) /* Advertise 1000-BaseT EEE ability */ if (advertise & ADVERTISED_1000baseT_Full) val |= MDIO_AN_EEE_ADV_1000T; + + if (!tp->eee.eee_enabled) { + val = 0; + tp->eee.advertised = 0; + } else { + tp->eee.advertised = advertise & + (ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full); + } + err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); if (err) val = 0; @@ -4613,6 +4623,42 @@ static void tg3_clear_mac_status(struct tg3 *tp) udelay(40); } +static void tg3_setup_eee(struct tg3 *tp) +{ + u32 val; + + val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | + TG3_CPMU_EEE_LNKIDL_UART_IDL; + if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) + val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT; + + tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val); + + tw32_f(TG3_CPMU_EEE_CTRL, + TG3_CPMU_EEE_CTRL_EXIT_20_1_US); + + val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | + (tp->eee.tx_lpi_enabled ? TG3_CPMU_EEEMD_LPI_IN_TX : 0) | + TG3_CPMU_EEEMD_LPI_IN_RX | + TG3_CPMU_EEEMD_EEE_ENABLE; + + if (tg3_asic_rev(tp) != ASIC_REV_5717) + val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; + + if (tg3_flag(tp, ENABLE_APE)) + val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; + + tw32_f(TG3_CPMU_EEE_MODE, tp->eee.eee_enabled ? val : 0); + + tw32_f(TG3_CPMU_EEE_DBTMR1, + TG3_CPMU_DBTMR1_PCIEXIT_2047US | + (tp->eee.tx_lpi_timer & 0xffff)); + + tw32_f(TG3_CPMU_EEE_DBTMR2, + TG3_CPMU_DBTMR2_APE_TX_2047US | + TG3_CPMU_DBTMR2_TXIDXEQ_2047US); +} + static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset) { bool current_link_up; @@ -9448,38 +9494,8 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) tg3_abort_hw(tp, 1); /* Enable MAC control of LPI */ - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) { - val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 | - TG3_CPMU_EEE_LNKIDL_UART_IDL; - if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0) - val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT; - - tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val); - - tw32_f(TG3_CPMU_EEE_CTRL, - TG3_CPMU_EEE_CTRL_EXIT_20_1_US); - - val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET | - TG3_CPMU_EEEMD_LPI_IN_TX | - TG3_CPMU_EEEMD_LPI_IN_RX | - TG3_CPMU_EEEMD_EEE_ENABLE; - - if (tg3_asic_rev(tp) != ASIC_REV_5717) - val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN; - - if (tg3_flag(tp, ENABLE_APE)) - val |= TG3_CPMU_EEEMD_APE_TX_DET_EN; - - tw32_f(TG3_CPMU_EEE_MODE, val); - - tw32_f(TG3_CPMU_EEE_DBTMR1, - TG3_CPMU_DBTMR1_PCIEXIT_2047US | - TG3_CPMU_DBTMR1_LNKIDLE_2047US); - - tw32_f(TG3_CPMU_EEE_DBTMR2, - TG3_CPMU_DBTMR2_APE_TX_2047US | - TG3_CPMU_DBTMR2_TXIDXEQ_2047US); - } + if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) + tg3_setup_eee(tp); if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) { @@ -14946,9 +14962,18 @@ static int tg3_phy_probe(struct tg3 *tp) (tg3_asic_rev(tp) == ASIC_REV_5717 && tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) || (tg3_asic_rev(tp) == ASIC_REV_57765 && - tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0))) + tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0))) { tp->phy_flags |= TG3_PHYFLG_EEE_CAP; + tp->eee.supported = SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full; + tp->eee.advertised = ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full; + tp->eee.eee_enabled = 1; + tp->eee.tx_lpi_enabled = 1; + tp->eee.tx_lpi_timer = TG3_CPMU_DBTMR1_LNKIDLE_2047US; + } + tg3_phy_init_link_config(tp); if (!(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 9b2d3ac2474a..057532c5c56c 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -3371,6 +3371,7 @@ struct tg3 { unsigned int irq_cnt; struct ethtool_coalesce coal; + struct ethtool_eee eee; /* firmware info */ const char *fw_needed; -- GitLab From 400dfbaa8d444a29056b051a3d7082dc611e3b12 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Sat, 18 May 2013 06:26:53 +0000 Subject: [PATCH 0114/2900] tg3: Add tg3_eee_pull_config() function Add tg3_eee_pull_config() to pull the settings from the hardware and populate the eee structure. If Link Flap Avoidance is enabled, we pull the eee settings from the hw so as not to cause a phy reset on eee config mismatch later. This requires moving down tg3_setup_eee() below the tg3_pull_config() to not trample existing settings. Reviewed-by: Ben Li Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 56 ++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 26804db1f884..3e7bc3837ef9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -2320,6 +2320,46 @@ static void tg3_phy_apply_otp(struct tg3 *tp) tg3_phy_toggle_auxctl_smdsp(tp, false); } +static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee) +{ + u32 val; + struct ethtool_eee *dest = &tp->eee; + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) + return; + + if (eee) + dest = eee; + + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, TG3_CL45_D7_EEERES_STAT, &val)) + return; + + /* Pull eee_active */ + if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || + val == TG3_CL45_D7_EEERES_STAT_LP_100TX) { + dest->eee_active = 1; + } else + dest->eee_active = 0; + + /* Pull lp advertised settings */ + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &val)) + return; + dest->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Pull advertised and eee_enabled settings */ + if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val)) + return; + dest->eee_enabled = !!val; + dest->advertised = mmd_eee_adv_to_ethtool_adv_t(val); + + /* Pull tx_lpi_enabled */ + val = tr32(TG3_CPMU_EEE_MODE); + dest->tx_lpi_enabled = !!(val & TG3_CPMU_EEEMD_LPI_IN_TX); + + /* Pull lpi timer value */ + dest->tx_lpi_timer = tr32(TG3_CPMU_EEE_DBTMR1) & 0xffff; +} + static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up) { u32 val; @@ -2343,11 +2383,8 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up) tw32(TG3_CPMU_EEE_CTRL, eeectl); - tg3_phy_cl45_read(tp, MDIO_MMD_AN, - TG3_CL45_D7_EEERES_STAT, &val); - - if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T || - val == TG3_CL45_D7_EEERES_STAT_LP_100TX) + tg3_eee_pull_config(tp, NULL); + if (tp->eee.eee_active) tp->setlpicnt = 2; } @@ -9493,16 +9530,17 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) if (tg3_flag(tp, INIT_COMPLETE)) tg3_abort_hw(tp, 1); - /* Enable MAC control of LPI */ - if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) - tg3_setup_eee(tp); - if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) { tg3_phy_pull_config(tp); + tg3_eee_pull_config(tp, NULL); tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; } + /* Enable MAC control of LPI */ + if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) + tg3_setup_eee(tp); + if (reset_phy) tg3_phy_reset(tp); -- GitLab From 5b6c273ad6c3886f30c7c5df7009e489043c59f3 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Sat, 18 May 2013 06:26:54 +0000 Subject: [PATCH 0115/2900] tg3: Simplify tg3_phy_eee_config_ok() by reusing tg3_eee_pull_config() eee_config_ok() was checking only for mismatch in advertised settings. This patch expands the scope of eee_config_ok() to check for mismatch in the other eee settings. On mismatch we will require a call to tg3_setup_eee() to push the configured settings to the hardware. Reviewed-by: Ben Li Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 31 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3e7bc3837ef9..2e4974823853 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -4540,26 +4540,23 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) static bool tg3_phy_eee_config_ok(struct tg3 *tp) { - u32 val; - u32 tgtadv = 0; - u32 advertising = tp->link_config.advertising; + struct ethtool_eee eee; if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) return true; - if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val)) - return false; - - val &= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T); - - - if (advertising & ADVERTISED_100baseT_Full) - tgtadv |= MDIO_AN_EEE_ADV_100TX; - if (advertising & ADVERTISED_1000baseT_Full) - tgtadv |= MDIO_AN_EEE_ADV_1000T; + tg3_eee_pull_config(tp, &eee); - if (val != tgtadv) - return false; + if (tp->eee.eee_enabled) { + if (tp->eee.advertised != eee.advertised || + tp->eee.tx_lpi_timer != eee.tx_lpi_timer || + tp->eee.tx_lpi_enabled != eee.tx_lpi_enabled) + return false; + } else { + /* EEE is disabled but we're advertising */ + if (eee.advertised) + return false; + } return true; } @@ -4862,8 +4859,10 @@ static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset) */ if (!eee_config_ok && (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) && - !force_reset) + !force_reset) { + tg3_setup_eee(tp); tg3_phy_reset(tp); + } } else { if (!(bmcr & BMCR_ANENABLE) && tp->link_config.speed == current_speed && -- GitLab From 1cbf9eb85a6601b58f01a71ff10299d2bf5d3365 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Sat, 18 May 2013 06:26:55 +0000 Subject: [PATCH 0116/2900] tg3: Implement set/get_eee handlers Reviewed-by: Ben Li Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 53 +++++++++++++++++++++++++++++ drivers/net/ethernet/broadcom/tg3.h | 1 + 2 files changed, 54 insertions(+) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 2e4974823853..fb06aa120293 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -13618,6 +13618,57 @@ static int tg3_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } +static int tg3_set_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) { + netdev_warn(tp->dev, "Board does not support EEE!\n"); + return -EOPNOTSUPP; + } + + if (edata->advertised != tp->eee.advertised) { + netdev_warn(tp->dev, + "Direct manipulation of EEE advertisement is not supported\n"); + return -EINVAL; + } + + if (edata->tx_lpi_timer > TG3_CPMU_DBTMR1_LNKIDLE_MAX) { + netdev_warn(tp->dev, + "Maximal Tx Lpi timer supported is %#x(u)\n", + TG3_CPMU_DBTMR1_LNKIDLE_MAX); + return -EINVAL; + } + + tp->eee = *edata; + + tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED; + tg3_warn_mgmt_link_flap(tp); + + if (netif_running(tp->dev)) { + tg3_full_lock(tp, 0); + tg3_setup_eee(tp); + tg3_phy_reset(tp); + tg3_full_unlock(tp); + } + + return 0; +} + +static int tg3_get_eee(struct net_device *dev, struct ethtool_eee *edata) +{ + struct tg3 *tp = netdev_priv(dev); + + if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) { + netdev_warn(tp->dev, + "Board does not support EEE!\n"); + return -EOPNOTSUPP; + } + + *edata = tp->eee; + return 0; +} + static const struct ethtool_ops tg3_ethtool_ops = { .get_settings = tg3_get_settings, .set_settings = tg3_set_settings, @@ -13651,6 +13702,8 @@ static const struct ethtool_ops tg3_ethtool_ops = { .get_channels = tg3_get_channels, .set_channels = tg3_set_channels, .get_ts_info = tg3_get_ts_info, + .get_eee = tg3_get_eee, + .set_eee = tg3_set_eee, }; static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index 057532c5c56c..2530c20dd823 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -1175,6 +1175,7 @@ #define TG3_CPMU_EEE_DBTMR1 0x000036b4 #define TG3_CPMU_DBTMR1_PCIEXIT_2047US 0x07ff0000 #define TG3_CPMU_DBTMR1_LNKIDLE_2047US 0x000007ff +#define TG3_CPMU_DBTMR1_LNKIDLE_MAX 0x0000ffff #define TG3_CPMU_EEE_DBTMR2 0x000036b8 #define TG3_CPMU_DBTMR2_APE_TX_2047US 0x07ff0000 #define TG3_CPMU_DBTMR2_TXIDXEQ_2047US 0x000007ff -- GitLab From 8802f5790ef3e2e1d907169557e3dd2e0e77d98f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 18 May 2013 07:14:53 +0000 Subject: [PATCH 0117/2900] net-bnx2x: dont reload on GRO change bnx2x_set_features() forces a driver reload if GRO setting is changed. A reload makes the ethernet port unresponsive for about 5 seconds. This is not needed in the common case LRO is enabled, as LRO (TPA_ENABLE_FLAG) has precedence over GRO (GRO_ENABLE_FLAG) Tested: Verified that "ethtool -K eth0 gro {on|off}" doesn't blackout the NIC anymore Google-Bug-Id: 8440442 Signed-off-by: Eric Dumazet Cc: Dmitry Kravkov Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index b8fbe266ab68..6cc5101fa96b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -4599,6 +4599,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features) { struct bnx2x *bp = netdev_priv(dev); u32 flags = bp->flags; + u32 changes; bool bnx2x_reload = false; if (features & NETIF_F_LRO) @@ -4623,10 +4624,16 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features) } } - if (flags ^ bp->flags) { - bp->flags = flags; + changes = flags ^ bp->flags; + + /* if GRO is changed while LRO is enabled, dont force a reload */ + if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG)) + changes &= ~GRO_ENABLE_FLAG; + + if (changes) bnx2x_reload = true; - } + + bp->flags = flags; if (bnx2x_reload) { if (bp->recovery_state == BNX2X_RECOVERY_DONE) -- GitLab From 1e18583adccfc122b5d6415cfe4bf1826c370f4e Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Sat, 18 May 2013 11:50:17 +0000 Subject: [PATCH 0118/2900] ThunderLAN: remove is_eisa flag These 2 places are the only matches for is_eisa in the whole tree. Signed-off-by: Rolf Eike Beer Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/tlan.c | 1 - drivers/net/ethernet/ti/tlan.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 60c400f6d01f..59abfbcd0d55 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -533,7 +533,6 @@ static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev, /* This is a hack. We need to know which board structure * is suited for this adapter */ device_id = inw(ioaddr + EISA_ID2); - priv->is_eisa = 1; if (device_id == 0x20F1) { priv->adapter = &board_info[13]; /* NetFlex-3/E */ priv->adapter_rev = 23; /* TLAN 2.3 */ diff --git a/drivers/net/ethernet/ti/tlan.h b/drivers/net/ethernet/ti/tlan.h index 5fc98a8e4889..2eb33a250788 100644 --- a/drivers/net/ethernet/ti/tlan.h +++ b/drivers/net/ethernet/ti/tlan.h @@ -207,7 +207,6 @@ struct tlan_priv { u8 tlan_full_duplex; spinlock_t lock; u8 link; - u8 is_eisa; struct work_struct tlan_tqueue; u8 neg_be_verbose; }; -- GitLab From c28f692c6f5a836dc628fb6990fb4d3d1859f779 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 10 May 2013 08:17:11 +0000 Subject: [PATCH 0119/2900] drivers/thermal: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Wolfram Sang Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/dove_thermal.c | 11 +---------- drivers/thermal/exynos_thermal.c | 5 ----- drivers/thermal/kirkwood_thermal.c | 7 +------ drivers/thermal/rcar_thermal.c | 6 +----- 4 files changed, 3 insertions(+), 26 deletions(-) diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 4b15a5f270dc..8bf104d8a649 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -134,25 +134,16 @@ static int dove_thermal_probe(struct platform_device *pdev) struct resource *res; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->sensor = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->sensor)) return PTR_ERR(priv->sensor); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } priv->control = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->control)) return PTR_ERR(priv->control); diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index d20ce9e61403..788b1ddcac6c 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -925,11 +925,6 @@ static int exynos_tmu_probe(struct platform_device *pdev) INIT_WORK(&data->irq_work, exynos_tmu_work); data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!data->mem) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENOENT; - } - data->base = devm_ioremap_resource(&pdev->dev, data->mem); if (IS_ERR(data->base)) return PTR_ERR(data->base); diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index dfeceaffbc03..9e4d98eef17a 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -75,16 +75,11 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) struct kirkwood_thermal_priv *priv; struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->sensor = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->sensor)) return PTR_ERR(priv->sensor); diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 8d7edd4c8228..72f50bc0456c 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -389,11 +389,6 @@ static int rcar_thermal_probe(struct platform_device *pdev) * platform has IRQ support. * Then, drier use common register */ - res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); - if (!res) { - dev_err(dev, "Could not get platform resource\n"); - return -ENODEV; - } ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, dev_name(dev), common); @@ -405,6 +400,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) /* * rcar_has_irq_support() will be enabled */ + res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); common->base = devm_ioremap_resource(dev, res); if (IS_ERR(common->base)) return PTR_ERR(common->base); -- GitLab From 253e3ae170d0852620dd9898807a22401d831dc4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 16 May 2013 02:16:20 +0000 Subject: [PATCH 0120/2900] Thermal: spear_thermal: convert to devm_ioremap_resource Use the newly introduced devm_ioremap_resource(). devm_ioremap_resource() provides its own error messages; so all explicit error messages can be removed from the failure code paths. CC: Vincenzo Frascino Signed-off-by: Zhang Rui --- drivers/thermal/spear_thermal.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 3c5ee5607977..b9e21611aece 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -104,7 +104,7 @@ static int spear_thermal_probe(struct platform_device *pdev) struct thermal_zone_device *spear_thermal = NULL; struct spear_thermal_dev *stdev; struct device_node *np = pdev->dev.of_node; - struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct resource *res; int ret = 0, val; if (!np || !of_property_read_u32(np, "st,thermal-flags", &val)) { @@ -112,23 +112,23 @@ static int spear_thermal_probe(struct platform_device *pdev) return -EINVAL; } - if (!stres) { - dev_err(&pdev->dev, "memory resource missing\n"); - return -ENODEV; - } - stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); if (!stdev) { dev_err(&pdev->dev, "kzalloc fail\n"); return -ENOMEM; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource missing\n"); + return -ENODEV; + } + /* Enable thermal sensor */ - stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start, - resource_size(stres)); - if (!stdev->thermal_base) { + stdev->thermal_base = devm_ioremap_resource(dev, res); + if (IS_ERR(stdev->thermal_base)) { dev_err(&pdev->dev, "ioremap failed\n"); - return -ENOMEM; + return PTR_ERR(stdev->thermal_base); } stdev->clk = devm_clk_get(&pdev->dev, NULL); -- GitLab From 7711ece9b31f0f3cf15ca16005dfd78988ea8f7e Mon Sep 17 00:00:00 2001 From: Chris Zankel Date: Mon, 20 May 2013 11:09:13 -0700 Subject: [PATCH 0121/2900] xtensa: fix TLB multihit exceptions - set _PAGE_USER in the pte_clear to avoid having TLB multihit exceptions (see following threads for more details); http://lists.linux-xtensa.org/pipermail/linux-xtensa/Week-of-Mon-20130401/ http://lists.linux-xtensa.org/pipermail/linux-xtensa/Week-of-Mon-20130408/ - improved documentation of the PTE layout - fix PTE mapping for present and 'prot_none' pages for T1050 hw and earlier - fix pte_file offset and size - add check for the correct number of bits for swap type CC: piet.delaney@gmail.com CC: jcmvbkbc@gmail.com Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/pgtable.h | 140 ++++++++++++++++++------------ 1 file changed, 83 insertions(+), 57 deletions(-) diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index d7546c94da52..7e09f7011370 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -5,7 +5,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Copyright (C) 2001 - 2007 Tensilica Inc. + * Copyright (C) 2001 - 2013 Tensilica Inc. */ #ifndef _XTENSA_PGTABLE_H @@ -64,41 +64,82 @@ * Virtual memory area. We keep a distance to other memory regions to be * on the safe side. We also use this area for cache aliasing. */ - #define VMALLOC_START 0xC0000000 #define VMALLOC_END 0xC7FEFFFF #define TLBTEMP_BASE_1 0xC7FF0000 #define TLBTEMP_BASE_2 0xC7FF8000 /* - * Xtensa Linux config PTE layout (when present): - * 31-12: PPN - * 11-6: Software - * 5-4: RING - * 3-0: CA + * For the Xtensa architecture, the PTE layout is as follows: + * + * 31------12 11 10-9 8-6 5-4 3-2 1-0 + * +-----------------------------------------+ + * | | Software | HARDWARE | + * | PPN | ADW | RI |Attribute| + * +-----------------------------------------+ + * pte_none | MBZ | 01 | 11 | 00 | + * +-----------------------------------------+ + * present | PPN | 0 | 00 | ADW | RI | CA | wx | + * +- - - - - - - - - - - - - - - - - - - - -+ + * (PAGE_NONE)| PPN | 0 | 00 | ADW | 01 | 11 | 11 | + * +-----------------------------------------+ + * swap | index | type | 01 | 11 | 00 | + * +- - - - - - - - - - - - - - - - - - - - -+ + * file | file offset | 01 | 11 | 10 | + * +-----------------------------------------+ + * + * For T1050 hardware and earlier the layout differs for present and (PAGE_NONE) + * +-----------------------------------------+ + * present | PPN | 0 | 00 | ADW | RI | CA | w1 | + * +-----------------------------------------+ + * (PAGE_NONE)| PPN | 0 | 00 | ADW | 01 | 01 | 00 | + * +-----------------------------------------+ * - * Similar to the Alpha and MIPS ports, we need to keep track of the ref - * and mod bits in software. We have a software "you can read - * from this page" bit, and a hardware one which actually lets the - * process read from the page. On the same token we have a software - * writable bit and the real hardware one which actually lets the - * process write to the page. + * Legend: + * PPN Physical Page Number + * ADW software: accessed (young) / dirty / writable + * RI ring (0=privileged, 1=user, 2 and 3 are unused) + * CA cache attribute: 00 bypass, 01 writeback, 10 writethrough + * (11 is invalid and used to mark pages that are not present) + * w page is writable (hw) + * x page is executable (hw) + * index swap offset / PAGE_SIZE (bit 11-31: 21 bits -> 8 GB) + * (note that the index is always non-zero) + * type swap type (5 bits -> 32 types) + * file offset 26-bit offset into the file, in increments of PAGE_SIZE * - * See further below for PTE layout for swapped-out pages. + * Notes: + * - (PROT_NONE) is a special case of 'present' but causes an exception for + * any access (read, write, and execute). + * - 'multihit-exception' has the highest priority of all MMU exceptions, + * so the ring must be set to 'RING_USER' even for 'non-present' pages. + * - on older hardware, the exectuable flag was not supported and + * used as a 'valid' flag, so it needs to be always set. + * - we need to keep track of certain flags in software (dirty and young) + * to do this, we use write exceptions and have a separate software w-flag. + * - attribute value 1101 (and 1111 on T1050 and earlier) is reserved */ +#define _PAGE_ATTRIB_MASK 0xf + #define _PAGE_HW_EXEC (1<<0) /* hardware: page is executable */ #define _PAGE_HW_WRITE (1<<1) /* hardware: page is writable */ -#define _PAGE_FILE (1<<1) /* non-linear mapping, if !present */ -#define _PAGE_PROTNONE (3<<0) /* special case for VM_PROT_NONE */ - -/* None of these cache modes include MP coherency: */ #define _PAGE_CA_BYPASS (0<<2) /* bypass, non-speculative */ #define _PAGE_CA_WB (1<<2) /* write-back */ #define _PAGE_CA_WT (2<<2) /* write-through */ #define _PAGE_CA_MASK (3<<2) -#define _PAGE_INVALID (3<<2) +#define _PAGE_CA_INVALID (3<<2) + +/* We use invalid attribute values to distinguish special pte entries */ +#if XCHAL_HW_VERSION_MAJOR < 2000 +#define _PAGE_HW_VALID 0x01 /* older HW needed this bit set */ +#define _PAGE_NONE 0x04 +#else +#define _PAGE_HW_VALID 0x00 +#define _PAGE_NONE 0x0f +#endif +#define _PAGE_FILE (1<<1) /* file mapped page, only if !present */ #define _PAGE_USER (1<<4) /* user access (ring=1) */ @@ -108,19 +149,12 @@ #define _PAGE_DIRTY (1<<7) /* software: page dirty */ #define _PAGE_ACCESSED (1<<8) /* software: page accessed (read) */ -/* On older HW revisions, we always have to set bit 0 */ -#if XCHAL_HW_VERSION_MAJOR < 2000 -# define _PAGE_VALID (1<<0) -#else -# define _PAGE_VALID 0 -#endif - -#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_PRESENT (_PAGE_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) - #ifdef CONFIG_MMU -#define PAGE_NONE __pgprot(_PAGE_INVALID | _PAGE_USER | _PAGE_PROTNONE) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_PRESENT (_PAGE_HW_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) + +#define PAGE_NONE __pgprot(_PAGE_NONE | _PAGE_USER) #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER) #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_HW_EXEC) #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER) @@ -132,9 +166,9 @@ #define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT|_PAGE_HW_WRITE|_PAGE_HW_EXEC) #if (DCACHE_WAY_SIZE > PAGE_SIZE) -# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED) +# define _PAGE_DIRECTORY (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_BYPASS) #else -# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED | _PAGE_CA_WB) +# define _PAGE_DIRECTORY (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_WB) #endif #else /* no mmu */ @@ -202,12 +236,16 @@ static inline void pgtable_cache_init(void) { } /* * pte status. */ -#define pte_none(pte) (pte_val(pte) == _PAGE_INVALID) -#define pte_present(pte) \ - (((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_INVALID) \ - || ((pte_val(pte) & _PAGE_PROTNONE) == _PAGE_PROTNONE)) +# define pte_none(pte) (pte_val(pte) == (_PAGE_CA_INVALID | _PAGE_USER)) +#if XCHAL_HW_VERSION_MAJOR < 2000 +# define pte_present(pte) ((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID) +#else +# define pte_present(pte) \ + (((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID) \ + || ((pte_val(pte) & _PAGE_ATTRIB_MASK) == _PAGE_NONE)) +#endif #define pte_clear(mm,addr,ptep) \ - do { update_pte(ptep, __pte(_PAGE_INVALID)); } while(0) + do { update_pte(ptep, __pte(_PAGE_CA_INVALID | _PAGE_USER)); } while (0) #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK) @@ -328,35 +366,23 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) /* - * Encode and decode a swap entry. - * - * Format of swap pte: - * bit 0 MBZ - * bit 1 page-file (must be zero) - * bits 2 - 3 page hw access mode (must be 11: _PAGE_INVALID) - * bits 4 - 5 ring protection (must be 01: _PAGE_USER) - * bits 6 - 10 swap type (5 bits -> 32 types) - * bits 11 - 31 swap offset / PAGE_SIZE (21 bits -> 8GB) - - * Format of file pte: - * bit 0 MBZ - * bit 1 page-file (must be one: _PAGE_FILE) - * bits 2 - 3 page hw access mode (must be 11: _PAGE_INVALID) - * bits 4 - 5 ring protection (must be 01: _PAGE_USER) - * bits 6 - 31 file offset / PAGE_SIZE + * Encode and decode a swap and file entry. */ +#define SWP_TYPE_BITS 5 +#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS) #define __swp_type(entry) (((entry).val >> 6) & 0x1f) #define __swp_offset(entry) ((entry).val >> 11) #define __swp_entry(type,offs) \ - ((swp_entry_t) {((type) << 6) | ((offs) << 11) | _PAGE_INVALID}) + ((swp_entry_t){((type) << 6) | ((offs) << 11) | \ + _PAGE_CA_INVALID | _PAGE_USER}) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define PTE_FILE_MAX_BITS 28 -#define pte_to_pgoff(pte) (pte_val(pte) >> 4) +#define PTE_FILE_MAX_BITS 26 +#define pte_to_pgoff(pte) (pte_val(pte) >> 6) #define pgoff_to_pte(off) \ - ((pte_t) { ((off) << 4) | _PAGE_INVALID | _PAGE_FILE }) + ((pte_t) { ((off) << 6) | _PAGE_CA_INVALID | _PAGE_FILE | _PAGE_USER }) #endif /* !defined (__ASSEMBLY__) */ -- GitLab From 51fc41a90603eaee7b6d03b6027be8f22fcf8ef9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 18 May 2013 23:34:30 +0400 Subject: [PATCH 0122/2900] xtensa: fix fast_store_prohibited _PAGE_WRITABLE_BIT test Before _PAGE_WRITABLE_BIT test fast_store_prohibited must make sure that PTE is present. Otherwise 'writable' bit is undefined and may be reused in the 'file offset' or 'swap type' PTE fields. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/entry.S | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 5082507d5631..fa94512ff84d 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1792,10 +1792,15 @@ ENTRY(fast_store_prohibited) l32i a0, a0, 0 beqz a0, 2f - /* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/ + /* + * Note that we test _PAGE_WRITABLE_BIT only if PTE is present + * and is not PAGE_NONE. See pgtable.h for possible PTE layouts. + */ _PTE_OFFSET(a0, a1, a4) l32i a4, a0, 0 # read pteval + movi a1, _PAGE_CA_INVALID + ball a4, a1, 2f bbci.l a4, _PAGE_WRITABLE_BIT, 2f movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE -- GitLab From 4fc1ad6f4b4d9214505eda434b1ed3b0bfd16981 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 19 May 2013 10:17:13 +0000 Subject: [PATCH 0123/2900] 3c59x: remove useless VORTEX_PCI() invocations It's suboptimal to invoke quite complex VORTEX_PCI() macro every time we want to get a 'struct pci_dev *' when we already have it in a variable... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c59x.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 072c6f14e8fc..30e74211a755 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -1473,7 +1473,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, if (pdev) { vp->pm_state_valid = 1; - pci_save_state(VORTEX_PCI(vp)); + pci_save_state(pdev); acpi_set_WOL(dev); } retval = register_netdev(dev); @@ -3233,21 +3233,20 @@ static void vortex_remove_one(struct pci_dev *pdev) vp = netdev_priv(dev); if (vp->cb_fn_base) - pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base); + pci_iounmap(pdev, vp->cb_fn_base); unregister_netdev(dev); - if (VORTEX_PCI(vp)) { - pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */ - if (vp->pm_state_valid) - pci_restore_state(VORTEX_PCI(vp)); - pci_disable_device(VORTEX_PCI(vp)); - } + pci_set_power_state(pdev, PCI_D0); /* Go active */ + if (vp->pm_state_valid) + pci_restore_state(pdev); + pci_disable_device(pdev); + /* Should really use issue_and_wait() here */ iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14), vp->ioaddr + EL3_CMD); - pci_iounmap(VORTEX_PCI(vp), vp->ioaddr); + pci_iounmap(pdev, vp->ioaddr); pci_free_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE -- GitLab From a9683c94fe8c8f87fdc8380a2e76506aa1502dcb Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sat, 18 May 2013 09:39:05 +0000 Subject: [PATCH 0124/2900] net: velocity: Rename vptr->dev to vptr->netdev Improve the clarity of the code in preparation for converting the dma functions to generic versions, which require a struct device *. This makes it possible to store a 'struct device *dev' in the velocity_info structure. Signed-off-by: Tony Prisk Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-velocity.c | 66 ++++++++++++------------- drivers/net/ethernet/via/via-velocity.h | 4 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index fb6248956ee2..187eef33df11 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -998,9 +998,9 @@ static void velocity_print_link_status(struct velocity_info *vptr) { if (vptr->mii_status & VELOCITY_LINK_FAIL) { - VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name); + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->netdev->name); } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) { - VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name); + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->netdev->name); if (vptr->mii_status & VELOCITY_SPEED_1000) VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps"); @@ -1014,7 +1014,7 @@ static void velocity_print_link_status(struct velocity_info *vptr) else VELOCITY_PRT(MSG_LEVEL_INFO, " half duplex\n"); } else { - VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->dev->name); + VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link forced", vptr->netdev->name); switch (vptr->options.spd_dpx) { case SPD_DPX_1000_FULL: VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps full duplex\n"); @@ -1319,7 +1319,7 @@ static void velocity_init_registers(struct velocity_info *vptr, case VELOCITY_INIT_RESET: case VELOCITY_INIT_WOL: - netif_stop_queue(vptr->dev); + netif_stop_queue(vptr->netdev); /* * Reset RX to prevent RX pointer not on the 4X location @@ -1332,7 +1332,7 @@ static void velocity_init_registers(struct velocity_info *vptr, if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { velocity_print_link_status(vptr); if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - netif_wake_queue(vptr->dev); + netif_wake_queue(vptr->netdev); } enable_flow_control_ability(vptr); @@ -1354,7 +1354,7 @@ static void velocity_init_registers(struct velocity_info *vptr, mac_eeprom_reload(regs); for (i = 0; i < 6; i++) - writeb(vptr->dev->dev_addr[i], &(regs->PAR[i])); + writeb(vptr->netdev->dev_addr[i], &(regs->PAR[i])); /* * clear Pre_ACPI bit. @@ -1377,7 +1377,7 @@ static void velocity_init_registers(struct velocity_info *vptr, /* * Set packet filter: Receive directed and broadcast address */ - velocity_set_multi(vptr->dev); + velocity_set_multi(vptr->netdev); /* * Enable MII auto-polling @@ -1404,14 +1404,14 @@ static void velocity_init_registers(struct velocity_info *vptr, writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), ®s->CR0Set); mii_status = velocity_get_opt_media_mode(vptr); - netif_stop_queue(vptr->dev); + netif_stop_queue(vptr->netdev); mii_init(vptr, mii_status); if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { velocity_print_link_status(vptr); if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - netif_wake_queue(vptr->dev); + netif_wake_queue(vptr->netdev); } enable_flow_control_ability(vptr); @@ -1474,7 +1474,7 @@ static int velocity_init_dma_rings(struct velocity_info *vptr) rx_ring_size, &pool_dma); if (!pool) { dev_err(&pdev->dev, "%s : DMA memory allocation failed.\n", - vptr->dev->name); + vptr->netdev->name); return -ENOMEM; } @@ -1514,7 +1514,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx) struct rx_desc *rd = &(vptr->rx.ring[idx]); struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]); - rd_info->skb = netdev_alloc_skb(vptr->dev, vptr->rx.buf_sz + 64); + rd_info->skb = netdev_alloc_skb(vptr->netdev, vptr->rx.buf_sz + 64); if (rd_info->skb == NULL) return -ENOMEM; @@ -1620,7 +1620,7 @@ static int velocity_init_rd_ring(struct velocity_info *vptr) if (velocity_rx_refill(vptr) != vptr->options.numrx) { VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR - "%s: failed to allocate RX buffer.\n", vptr->dev->name); + "%s: failed to allocate RX buffer.\n", vptr->netdev->name); velocity_free_rd_ring(vptr); goto out; } @@ -1809,7 +1809,7 @@ static void velocity_error(struct velocity_info *vptr, int status) printk(KERN_ERR "TD structure error TDindex=%hx\n", readw(®s->TDIdx[0])); BYTE_REG_BITS_ON(TXESR_TDSTR, ®s->TXESR); writew(TRDCSR_RUN, ®s->TDCSRClr); - netif_stop_queue(vptr->dev); + netif_stop_queue(vptr->netdev); /* FIXME: port over the pci_device_failed code and use it here */ @@ -1850,10 +1850,10 @@ static void velocity_error(struct velocity_info *vptr, int status) if (linked) { vptr->mii_status &= ~VELOCITY_LINK_FAIL; - netif_carrier_on(vptr->dev); + netif_carrier_on(vptr->netdev); } else { vptr->mii_status |= VELOCITY_LINK_FAIL; - netif_carrier_off(vptr->dev); + netif_carrier_off(vptr->netdev); } velocity_print_link_status(vptr); @@ -1867,9 +1867,9 @@ static void velocity_error(struct velocity_info *vptr, int status) enable_mii_autopoll(regs); if (vptr->mii_status & VELOCITY_LINK_FAIL) - netif_stop_queue(vptr->dev); + netif_stop_queue(vptr->netdev); else - netif_wake_queue(vptr->dev); + netif_wake_queue(vptr->netdev); } if (status & ISR_MIBFI) @@ -1894,7 +1894,7 @@ static int velocity_tx_srv(struct velocity_info *vptr) int idx; int works = 0; struct velocity_td_info *tdinfo; - struct net_device_stats *stats = &vptr->dev->stats; + struct net_device_stats *stats = &vptr->netdev->stats; for (qnum = 0; qnum < vptr->tx.numq; qnum++) { for (idx = vptr->tx.tail[qnum]; vptr->tx.used[qnum] > 0; @@ -1939,9 +1939,9 @@ static int velocity_tx_srv(struct velocity_info *vptr) * Look to see if we should kick the transmit network * layer for more work. */ - if (netif_queue_stopped(vptr->dev) && (full == 0) && + if (netif_queue_stopped(vptr->netdev) && (full == 0) && (!(vptr->mii_status & VELOCITY_LINK_FAIL))) { - netif_wake_queue(vptr->dev); + netif_wake_queue(vptr->netdev); } return works; } @@ -1989,7 +1989,7 @@ static int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size, if (pkt_size < rx_copybreak) { struct sk_buff *new_skb; - new_skb = netdev_alloc_skb_ip_align(vptr->dev, pkt_size); + new_skb = netdev_alloc_skb_ip_align(vptr->netdev, pkt_size); if (new_skb) { new_skb->ip_summed = rx_skb[0]->ip_summed; skb_copy_from_linear_data(*rx_skb, new_skb->data, pkt_size); @@ -2030,14 +2030,14 @@ static inline void velocity_iph_realign(struct velocity_info *vptr, static int velocity_receive_frame(struct velocity_info *vptr, int idx) { void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int); - struct net_device_stats *stats = &vptr->dev->stats; + struct net_device_stats *stats = &vptr->netdev->stats; struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]); struct rx_desc *rd = &(vptr->rx.ring[idx]); int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff; struct sk_buff *skb; if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) { - VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->dev->name); + VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame span multple RDs.\n", vptr->netdev->name); stats->rx_length_errors++; return -EINVAL; } @@ -2075,7 +2075,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) PCI_DMA_FROMDEVICE); skb_put(skb, pkt_len - 4); - skb->protocol = eth_type_trans(skb, vptr->dev); + skb->protocol = eth_type_trans(skb, vptr->netdev); if (rd->rdesc0.RSR & RSR_DETAG) { u16 vid = swab16(le16_to_cpu(rd->rdesc1.PQTAG)); @@ -2100,7 +2100,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) */ static int velocity_rx_srv(struct velocity_info *vptr, int budget_left) { - struct net_device_stats *stats = &vptr->dev->stats; + struct net_device_stats *stats = &vptr->netdev->stats; int rd_curr = vptr->rx.curr; int works = 0; @@ -2292,7 +2292,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) if ((new_mtu < VELOCITY_MIN_MTU) || new_mtu > (VELOCITY_MAX_MTU)) { VELOCITY_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Invalid MTU.\n", - vptr->dev->name); + vptr->netdev->name); ret = -EINVAL; goto out_0; } @@ -2314,7 +2314,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) goto out_0; } - tmp_vptr->dev = dev; + tmp_vptr->netdev = dev; tmp_vptr->pdev = vptr->pdev; tmp_vptr->options = vptr->options; tmp_vptr->tx.numq = vptr->tx.numq; @@ -2692,7 +2692,7 @@ static int velocity_get_pci_info(struct velocity_info *vptr, */ static void velocity_print_info(struct velocity_info *vptr) { - struct net_device *dev = vptr->dev; + struct net_device *dev = vptr->netdev; printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id)); printk(KERN_INFO "%s: Ethernet Address: %pM\n", @@ -2755,7 +2755,7 @@ static int velocity_found1(struct pci_dev *pdev, velocity_init_info(pdev, vptr, info); - vptr->dev = dev; + vptr->netdev = dev; ret = pci_enable_device(pdev); if (ret < 0) @@ -3010,10 +3010,10 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state) struct velocity_info *vptr = netdev_priv(dev); unsigned long flags; - if (!netif_running(vptr->dev)) + if (!netif_running(vptr->netdev)) return 0; - netif_device_detach(vptr->dev); + netif_device_detach(vptr->netdev); spin_lock_irqsave(&vptr->lock, flags); pci_save_state(pdev); @@ -3078,7 +3078,7 @@ static int velocity_resume(struct pci_dev *pdev) unsigned long flags; int i; - if (!netif_running(vptr->dev)) + if (!netif_running(vptr->netdev)) return 0; pci_set_power_state(pdev, PCI_D0); @@ -3101,7 +3101,7 @@ static int velocity_resume(struct pci_dev *pdev) mac_enable_int(vptr->mac_regs); spin_unlock_irqrestore(&vptr->lock, flags); - netif_device_attach(vptr->dev); + netif_device_attach(vptr->netdev); return 0; } diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h index 4cb9f13485e9..ff8d7828aa1b 100644 --- a/drivers/net/ethernet/via/via-velocity.h +++ b/drivers/net/ethernet/via/via-velocity.h @@ -1435,7 +1435,7 @@ struct velocity_opt { struct velocity_info { struct pci_dev *pdev; - struct net_device *dev; + struct net_device *netdev; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u8 ip_addr[4]; @@ -1514,7 +1514,7 @@ static inline int velocity_get_ip(struct velocity_info *vptr) int res = -ENOENT; rcu_read_lock(); - in_dev = __in_dev_get_rcu(vptr->dev); + in_dev = __in_dev_get_rcu(vptr->netdev); if (in_dev != NULL) { ifa = (struct in_ifaddr *) in_dev->ifa_list; if (ifa != NULL) { -- GitLab From e2c41f143fb2db14ad9b644a515c98e6c2e5ea2d Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sat, 18 May 2013 09:39:06 +0000 Subject: [PATCH 0125/2900] net: velocity: Convert to generic dma functions Remove the pci_* dma functions and replace with the more generic versions. In preparation of adding platform support, a new struct device *dev is added to struct velocity_info which can be used by both the pci and platform code. Signed-off-by: Tony Prisk Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-velocity.c | 51 ++++++++++++------------- drivers/net/ethernet/via/via-velocity.h | 1 + 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 187eef33df11..5996cee0ffa7 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1459,7 +1460,6 @@ static int velocity_init_dma_rings(struct velocity_info *vptr) struct velocity_opt *opt = &vptr->options; const unsigned int rx_ring_size = opt->numrx * sizeof(struct rx_desc); const unsigned int tx_ring_size = opt->numtx * sizeof(struct tx_desc); - struct pci_dev *pdev = vptr->pdev; dma_addr_t pool_dma; void *pool; unsigned int i; @@ -1467,13 +1467,13 @@ static int velocity_init_dma_rings(struct velocity_info *vptr) /* * Allocate all RD/TD rings a single pool. * - * pci_alloc_consistent() fulfills the requirement for 64 bytes + * dma_alloc_coherent() fulfills the requirement for 64 bytes * alignment */ - pool = pci_alloc_consistent(pdev, tx_ring_size * vptr->tx.numq + - rx_ring_size, &pool_dma); + pool = dma_alloc_coherent(vptr->dev, tx_ring_size * vptr->tx.numq + + rx_ring_size, &pool_dma, GFP_ATOMIC); if (!pool) { - dev_err(&pdev->dev, "%s : DMA memory allocation failed.\n", + dev_err(vptr->dev, "%s : DMA memory allocation failed.\n", vptr->netdev->name); return -ENOMEM; } @@ -1524,8 +1524,8 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx) */ skb_reserve(rd_info->skb, 64 - ((unsigned long) rd_info->skb->data & 63)); - rd_info->skb_dma = pci_map_single(vptr->pdev, rd_info->skb->data, - vptr->rx.buf_sz, PCI_DMA_FROMDEVICE); + rd_info->skb_dma = dma_map_single(vptr->dev, rd_info->skb->data, + vptr->rx.buf_sz, DMA_FROM_DEVICE); /* * Fill in the descriptor to match @@ -1588,8 +1588,8 @@ static void velocity_free_rd_ring(struct velocity_info *vptr) if (!rd_info->skb) continue; - pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz, - PCI_DMA_FROMDEVICE); + dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz, + DMA_FROM_DEVICE); rd_info->skb_dma = 0; dev_kfree_skb(rd_info->skb); @@ -1670,7 +1670,7 @@ static void velocity_free_dma_rings(struct velocity_info *vptr) const int size = vptr->options.numrx * sizeof(struct rx_desc) + vptr->options.numtx * sizeof(struct tx_desc) * vptr->tx.numq; - pci_free_consistent(vptr->pdev, size, vptr->rx.ring, vptr->rx.pool_dma); + dma_free_coherent(vptr->dev, size, vptr->rx.ring, vptr->rx.pool_dma); } static int velocity_init_rings(struct velocity_info *vptr, int mtu) @@ -1727,8 +1727,8 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, pktlen = max_t(size_t, pktlen, td->td_buf[i].size & ~TD_QUEUE); - pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], - le16_to_cpu(pktlen), PCI_DMA_TODEVICE); + dma_unmap_single(vptr->dev, tdinfo->skb_dma[i], + le16_to_cpu(pktlen), DMA_TO_DEVICE); } } dev_kfree_skb_irq(skb); @@ -1750,8 +1750,8 @@ static void velocity_free_td_ring_entry(struct velocity_info *vptr, if (td_info->skb) { for (i = 0; i < td_info->nskb_dma; i++) { if (td_info->skb_dma[i]) { - pci_unmap_single(vptr->pdev, td_info->skb_dma[i], - td_info->skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(vptr->dev, td_info->skb_dma[i], + td_info->skb->len, DMA_TO_DEVICE); td_info->skb_dma[i] = 0; } } @@ -2029,7 +2029,6 @@ static inline void velocity_iph_realign(struct velocity_info *vptr, */ static int velocity_receive_frame(struct velocity_info *vptr, int idx) { - void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int); struct net_device_stats *stats = &vptr->netdev->stats; struct velocity_rd_info *rd_info = &(vptr->rx.info[idx]); struct rx_desc *rd = &(vptr->rx.ring[idx]); @@ -2047,8 +2046,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) skb = rd_info->skb; - pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma, - vptr->rx.buf_sz, PCI_DMA_FROMDEVICE); + dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma, + vptr->rx.buf_sz, DMA_FROM_DEVICE); /* * Drop frame not meeting IEEE 802.3 @@ -2061,19 +2060,18 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) } } - pci_action = pci_dma_sync_single_for_device; - velocity_rx_csum(rd, skb); if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) { velocity_iph_realign(vptr, skb, pkt_len); - pci_action = pci_unmap_single; rd_info->skb = NULL; + dma_unmap_single(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz, + DMA_FROM_DEVICE); + } else { + dma_sync_single_for_device(vptr->dev, rd_info->skb_dma, + vptr->rx.buf_sz, DMA_FROM_DEVICE); } - pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx.buf_sz, - PCI_DMA_FROMDEVICE); - skb_put(skb, pkt_len - 4); skb->protocol = eth_type_trans(skb, vptr->netdev); @@ -2550,7 +2548,8 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb, * add it to the transmit ring. */ tdinfo->skb = skb; - tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE); + tdinfo->skb_dma[0] = dma_map_single(vptr->dev, skb->data, pktlen, + DMA_TO_DEVICE); td_ptr->tdesc0.len = cpu_to_le16(pktlen); td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]); td_ptr->td_buf[0].pa_high = 0; @@ -2560,7 +2559,7 @@ static netdev_tx_t velocity_xmit(struct sk_buff *skb, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - tdinfo->skb_dma[i + 1] = skb_frag_dma_map(&vptr->pdev->dev, + tdinfo->skb_dma[i + 1] = skb_frag_dma_map(vptr->dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); @@ -2637,6 +2636,7 @@ static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, { memset(vptr, 0, sizeof(struct velocity_info)); + vptr->dev = &pdev->dev; vptr->pdev = pdev; vptr->chip_id = info->chip_id; vptr->tx.numq = info->txqueue; @@ -2744,7 +2744,6 @@ static int velocity_found1(struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); vptr = netdev_priv(dev); - if (first) { printk(KERN_INFO "%s Ver. %s\n", VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION); diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h index ff8d7828aa1b..c38bbaed4d12 100644 --- a/drivers/net/ethernet/via/via-velocity.h +++ b/drivers/net/ethernet/via/via-velocity.h @@ -1434,6 +1434,7 @@ struct velocity_opt { #define GET_RD_BY_IDX(vptr, idx) (vptr->rd_ring[idx]) struct velocity_info { + struct device *dev; struct pci_dev *pdev; struct net_device *netdev; -- GitLab From 6dffbe53fbdcc7bd5f6379fa18264f060b0cf61d Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sat, 18 May 2013 09:39:07 +0000 Subject: [PATCH 0126/2900] net: velocity: Add platform device support to VIA velocity driver Add support for the VIA Velocity network driver to be bound to a OF created platform device. Signed-off-by: Tony Prisk Signed-off-by: David S. Miller --- .../devicetree/bindings/net/via-velocity.txt | 20 + drivers/net/ethernet/via/Kconfig | 3 +- drivers/net/ethernet/via/via-velocity.c | 408 ++++++++++++------ drivers/net/ethernet/via/via-velocity.h | 3 +- 4 files changed, 305 insertions(+), 129 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/via-velocity.txt diff --git a/Documentation/devicetree/bindings/net/via-velocity.txt b/Documentation/devicetree/bindings/net/via-velocity.txt new file mode 100644 index 000000000000..b3db469b1ad7 --- /dev/null +++ b/Documentation/devicetree/bindings/net/via-velocity.txt @@ -0,0 +1,20 @@ +* VIA Velocity 10/100/1000 Network Controller + +Required properties: +- compatible : Should be "via,velocity-vt6110" +- reg : Address and length of the io space +- interrupts : Should contain the controller interrupt line + +Optional properties: +- no-eeprom : PCI network cards use an external EEPROM to store data. Embedded + devices quite often set this data in uboot and do not provide an eeprom. + Specify this option if you have no external eeprom. + +Examples: + +eth0@d8004000 { + compatible = "via,velocity-vt6110"; + reg = <0xd8004000 0x400>; + interrupts = <10>; + no-eeprom; +}; diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig index 68a9ba66feba..6a87097d88c0 100644 --- a/drivers/net/ethernet/via/Kconfig +++ b/drivers/net/ethernet/via/Kconfig @@ -5,7 +5,6 @@ config NET_VENDOR_VIA bool "VIA devices" default y - depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -45,7 +44,7 @@ config VIA_RHINE_MMIO config VIA_VELOCITY tristate "VIA Velocity support" - depends on PCI + depends on (PCI || USE_OF) select CRC32 select CRC_CCITT select NET_CORE diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 5996cee0ffa7..76919948b4ee 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -65,7 +65,11 @@ #include #include #include +#include +#include +#include #include +#include #include #include #include @@ -80,10 +84,24 @@ #include "via-velocity.h" +enum velocity_bus_type { + BUS_PCI, + BUS_PLATFORM, +}; static int velocity_nics; static int msglevel = MSG_LEVEL_INFO; +static void velocity_set_power_state(struct velocity_info *vptr, char state) +{ + void *addr = vptr->mac_regs; + + if (vptr->pdev) + pci_set_power_state(vptr->pdev, state); + else + writeb(state, addr + 0x154); +} + /** * mac_get_cam_mask - Read a CAM mask * @regs: register block for this velocity @@ -362,12 +380,23 @@ static struct velocity_info_tbl chip_info_table[] = { * Describe the PCI device identifiers that we support in this * device driver. Used for hotplug autoloading. */ -static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = { + +static DEFINE_PCI_DEVICE_TABLE(velocity_pci_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) }, { } }; -MODULE_DEVICE_TABLE(pci, velocity_id_table); +MODULE_DEVICE_TABLE(pci, velocity_pci_id_table); + +/** + * Describe the OF device identifiers that we support in this + * device driver. Used for devicetree nodes. + */ +static struct of_device_id velocity_of_ids[] = { + { .compatible = "via,velocity-vt6110", .data = &chip_info_table[0] }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, velocity_of_ids); /** * get_chip_name - identifier to name @@ -385,29 +414,6 @@ static const char *get_chip_name(enum chip_type chip_id) return chip_info_table[i].name; } -/** - * velocity_remove1 - device unplug - * @pdev: PCI device being removed - * - * Device unload callback. Called on an unplug or on module - * unload for each active device that is present. Disconnects - * the device from the network layer and frees all the resources - */ -static void velocity_remove1(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct velocity_info *vptr = netdev_priv(dev); - - unregister_netdev(dev); - iounmap(vptr->mac_regs); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - free_netdev(dev); - - velocity_nics--; -} - /** * velocity_set_int_opt - parser for integer options * @opt: pointer to option value @@ -1181,6 +1187,17 @@ static void mii_init(struct velocity_info *vptr, u32 mii_status) u16 BMCR; switch (PHYID_GET_PHY_ID(vptr->phy_id)) { + case PHYID_ICPLUS_IP101A: + MII_REG_BITS_ON((ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP), + MII_ADVERTISE, vptr->mac_regs); + if (vptr->mii_status & VELOCITY_DUPLEX_FULL) + MII_REG_BITS_ON(TCSR_ECHODIS, MII_SREVISION, + vptr->mac_regs); + else + MII_REG_BITS_OFF(TCSR_ECHODIS, MII_SREVISION, + vptr->mac_regs); + MII_REG_BITS_ON(PLED_LALBE, MII_TPISTATUS, vptr->mac_regs); + break; case PHYID_CICADA_CS8201: /* * Reset to hardware default @@ -1312,6 +1329,7 @@ static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type) { struct mac_regs __iomem *regs = vptr->mac_regs; + struct net_device *netdev = vptr->netdev; int i, mii_status; mac_wol_reset(regs); @@ -1320,7 +1338,7 @@ static void velocity_init_registers(struct velocity_info *vptr, case VELOCITY_INIT_RESET: case VELOCITY_INIT_WOL: - netif_stop_queue(vptr->netdev); + netif_stop_queue(netdev); /* * Reset RX to prevent RX pointer not on the 4X location @@ -1333,7 +1351,7 @@ static void velocity_init_registers(struct velocity_info *vptr, if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { velocity_print_link_status(vptr); if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - netif_wake_queue(vptr->netdev); + netif_wake_queue(netdev); } enable_flow_control_ability(vptr); @@ -1353,9 +1371,11 @@ static void velocity_init_registers(struct velocity_info *vptr, velocity_soft_reset(vptr); mdelay(5); - mac_eeprom_reload(regs); - for (i = 0; i < 6; i++) - writeb(vptr->netdev->dev_addr[i], &(regs->PAR[i])); + if (!vptr->no_eeprom) { + mac_eeprom_reload(regs); + for (i = 0; i < 6; i++) + writeb(netdev->dev_addr[i], regs->PAR + i); + } /* * clear Pre_ACPI bit. @@ -1378,7 +1398,7 @@ static void velocity_init_registers(struct velocity_info *vptr, /* * Set packet filter: Receive directed and broadcast address */ - velocity_set_multi(vptr->netdev); + velocity_set_multi(netdev); /* * Enable MII auto-polling @@ -1405,14 +1425,14 @@ static void velocity_init_registers(struct velocity_info *vptr, writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), ®s->CR0Set); mii_status = velocity_get_opt_media_mode(vptr); - netif_stop_queue(vptr->netdev); + netif_stop_queue(netdev); mii_init(vptr, mii_status); if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) { velocity_print_link_status(vptr); if (!(vptr->mii_status & VELOCITY_LINK_FAIL)) - netif_wake_queue(vptr->netdev); + netif_wake_queue(netdev); } enable_flow_control_ability(vptr); @@ -2233,15 +2253,15 @@ static int velocity_open(struct net_device *dev) goto out; /* Ensure chip is running */ - pci_set_power_state(vptr->pdev, PCI_D0); + velocity_set_power_state(vptr, PCI_D0); velocity_init_registers(vptr, VELOCITY_INIT_COLD); - ret = request_irq(vptr->pdev->irq, velocity_intr, IRQF_SHARED, + ret = request_irq(dev->irq, velocity_intr, IRQF_SHARED, dev->name, dev); if (ret < 0) { /* Power down the chip */ - pci_set_power_state(vptr->pdev, PCI_D3hot); + velocity_set_power_state(vptr, PCI_D3hot); velocity_free_rings(vptr); goto out; } @@ -2314,6 +2334,7 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu) tmp_vptr->netdev = dev; tmp_vptr->pdev = vptr->pdev; + tmp_vptr->dev = vptr->dev; tmp_vptr->options = vptr->options; tmp_vptr->tx.numq = vptr->tx.numq; @@ -2413,7 +2434,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) saving then we need to bring the device back up to talk to it */ if (!netif_running(dev)) - pci_set_power_state(vptr->pdev, PCI_D0); + velocity_set_power_state(vptr, PCI_D0); switch (cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ @@ -2426,7 +2447,7 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ret = -EOPNOTSUPP; } if (!netif_running(dev)) - pci_set_power_state(vptr->pdev, PCI_D3hot); + velocity_set_power_state(vptr, PCI_D3hot); return ret; @@ -2492,7 +2513,7 @@ static int velocity_close(struct net_device *dev) if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) velocity_get_ip(vptr); - free_irq(vptr->pdev->irq, dev); + free_irq(dev->irq, dev); velocity_free_rings(vptr); @@ -2631,13 +2652,9 @@ static const struct net_device_ops velocity_netdev_ops = { * Set up the initial velocity_info struct for the device that has been * discovered. */ -static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, - const struct velocity_info_tbl *info) +static void velocity_init_info(struct velocity_info *vptr, + const struct velocity_info_tbl *info) { - memset(vptr, 0, sizeof(struct velocity_info)); - - vptr->dev = &pdev->dev; - vptr->pdev = pdev; vptr->chip_id = info->chip_id; vptr->tx.numq = info->txqueue; vptr->multicast_limit = MCAM_SIZE; @@ -2652,10 +2669,9 @@ static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, * Retrieve the PCI configuration space data that interests us from * the kernel PCI layer */ -static int velocity_get_pci_info(struct velocity_info *vptr, - struct pci_dev *pdev) +static int velocity_get_pci_info(struct velocity_info *vptr) { - vptr->rev_id = pdev->revision; + struct pci_dev *pdev = vptr->pdev; pci_set_master(pdev); @@ -2678,7 +2694,37 @@ static int velocity_get_pci_info(struct velocity_info *vptr, dev_err(&pdev->dev, "region #1 is too small.\n"); return -EINVAL; } - vptr->pdev = pdev; + + return 0; +} + +/** + * velocity_get_platform_info - retrieve platform info for device + * @vptr: velocity device + * @pdev: platform device it matches + * + * Retrieve the Platform configuration data that interests us + */ +static int velocity_get_platform_info(struct velocity_info *vptr) +{ + struct resource res; + int ret; + + if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL)) + vptr->no_eeprom = 1; + + ret = of_address_to_resource(vptr->dev->of_node, 0, &res); + if (ret) { + dev_err(vptr->dev, "unable to find memory address\n"); + return ret; + } + + vptr->memaddr = res.start; + + if (resource_size(&res) < VELOCITY_IO_SIZE) { + dev_err(vptr->dev, "memory region is too small.\n"); + return -EINVAL; + } return 0; } @@ -2707,21 +2753,22 @@ static u32 velocity_get_link(struct net_device *dev) } /** - * velocity_found1 - set up discovered velocity card + * velocity_probe - set up discovered velocity device * @pdev: PCI device * @ent: PCI device table entry that matched + * @bustype: bus that device is connected to * * Configure a discovered adapter from scratch. Return a negative * errno error code on failure paths. */ -static int velocity_found1(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int velocity_probe(struct device *dev, int irq, + const struct velocity_info_tbl *info, + enum velocity_bus_type bustype) { static int first = 1; - struct net_device *dev; + struct net_device *netdev; int i; const char *drv_string; - const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data]; struct velocity_info *vptr; struct mac_regs __iomem *regs; int ret = -ENOMEM; @@ -2730,19 +2777,18 @@ static int velocity_found1(struct pci_dev *pdev, * can support more than MAX_UNITS. */ if (velocity_nics >= MAX_UNITS) { - dev_notice(&pdev->dev, "already found %d NICs.\n", - velocity_nics); + dev_notice(dev, "already found %d NICs.\n", velocity_nics); return -ENODEV; } - dev = alloc_etherdev(sizeof(struct velocity_info)); - if (!dev) + netdev = alloc_etherdev(sizeof(struct velocity_info)); + if (!netdev) goto out; /* Chain it all together */ - SET_NETDEV_DEV(dev, &pdev->dev); - vptr = netdev_priv(dev); + SET_NETDEV_DEV(netdev, dev); + vptr = netdev_priv(netdev); if (first) { printk(KERN_INFO "%s Ver. %s\n", @@ -2752,41 +2798,41 @@ static int velocity_found1(struct pci_dev *pdev, first = 0; } - velocity_init_info(pdev, vptr, info); + netdev->irq = irq; + vptr->netdev = netdev; + vptr->dev = dev; - vptr->netdev = dev; + velocity_init_info(vptr, info); - ret = pci_enable_device(pdev); - if (ret < 0) - goto err_free_dev; + if (bustype == BUS_PCI) { + vptr->pdev = to_pci_dev(dev); - ret = velocity_get_pci_info(vptr, pdev); - if (ret < 0) { - /* error message already printed */ - goto err_disable; - } - - ret = pci_request_regions(pdev, VELOCITY_NAME); - if (ret < 0) { - dev_err(&pdev->dev, "No PCI resources.\n"); - goto err_disable; + ret = velocity_get_pci_info(vptr); + if (ret < 0) + goto err_free_dev; + } else { + vptr->pdev = NULL; + ret = velocity_get_platform_info(vptr); + if (ret < 0) + goto err_free_dev; } regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE); if (regs == NULL) { ret = -EIO; - goto err_release_res; + goto err_free_dev; } vptr->mac_regs = regs; + vptr->rev_id = readb(®s->rev_id); mac_wol_reset(regs); for (i = 0; i < 6; i++) - dev->dev_addr[i] = readb(®s->PAR[i]); + netdev->dev_addr[i] = readb(®s->PAR[i]); - drv_string = dev_driver_string(&pdev->dev); + drv_string = dev_driver_string(dev); velocity_get_options(&vptr->options, velocity_nics, drv_string); @@ -2807,46 +2853,125 @@ static int velocity_found1(struct pci_dev *pdev, vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs); - dev->netdev_ops = &velocity_netdev_ops; - dev->ethtool_ops = &velocity_ethtool_ops; - netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); + netdev->netdev_ops = &velocity_netdev_ops; + netdev->ethtool_ops = &velocity_ethtool_ops; + netif_napi_add(netdev, &vptr->napi, velocity_poll, + VELOCITY_NAPI_WEIGHT); - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX; - dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_IP_CSUM; + netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_IP_CSUM; - ret = register_netdev(dev); + ret = register_netdev(netdev); if (ret < 0) goto err_iounmap; - if (!velocity_get_link(dev)) { - netif_carrier_off(dev); + if (!velocity_get_link(netdev)) { + netif_carrier_off(netdev); vptr->mii_status |= VELOCITY_LINK_FAIL; } velocity_print_info(vptr); - pci_set_drvdata(pdev, dev); + dev_set_drvdata(vptr->dev, netdev); /* and leave the chip powered down */ - pci_set_power_state(pdev, PCI_D3hot); + velocity_set_power_state(vptr, PCI_D3hot); velocity_nics++; out: return ret; err_iounmap: iounmap(regs); -err_release_res: - pci_release_regions(pdev); -err_disable: - pci_disable_device(pdev); err_free_dev: - free_netdev(dev); + free_netdev(netdev); goto out; } -#ifdef CONFIG_PM +/** + * velocity_remove - device unplug + * @dev: device being removed + * + * Device unload callback. Called on an unplug or on module + * unload for each active device that is present. Disconnects + * the device from the network layer and frees all the resources + */ +static int velocity_remove(struct device *dev) +{ + struct net_device *netdev = dev_get_drvdata(dev); + struct velocity_info *vptr = netdev_priv(netdev); + + unregister_netdev(netdev); + iounmap(vptr->mac_regs); + free_netdev(netdev); + velocity_nics--; + + return 0; +} + +static int velocity_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + const struct velocity_info_tbl *info = + &chip_info_table[ent->driver_data]; + int ret; + + ret = pci_enable_device(pdev); + if (ret < 0) + return ret; + + ret = pci_request_regions(pdev, VELOCITY_NAME); + if (ret < 0) { + dev_err(&pdev->dev, "No PCI resources.\n"); + goto fail1; + } + + ret = velocity_probe(&pdev->dev, pdev->irq, info, BUS_PCI); + if (ret == 0) + return 0; + + pci_release_regions(pdev); +fail1: + pci_disable_device(pdev); + return ret; +} + +static void velocity_pci_remove(struct pci_dev *pdev) +{ + velocity_remove(&pdev->dev); + + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static int velocity_platform_probe(struct platform_device *pdev) +{ + const struct of_device_id *of_id; + const struct velocity_info_tbl *info; + int irq; + + of_id = of_match_device(velocity_of_ids, &pdev->dev); + if (!of_id) + return -EINVAL; + info = of_id->data; + + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!irq) + return -EINVAL; + + return velocity_probe(&pdev->dev, irq, info, BUS_PLATFORM); +} + +static int velocity_platform_remove(struct platform_device *pdev) +{ + velocity_remove(&pdev->dev); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP /** * wol_calc_crc - WOL CRC * @pattern: data pattern @@ -3003,10 +3128,10 @@ static void velocity_save_context(struct velocity_info *vptr, struct velocity_co } -static int velocity_suspend(struct pci_dev *pdev, pm_message_t state) +static int velocity_suspend(struct device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); - struct velocity_info *vptr = netdev_priv(dev); + struct net_device *netdev = dev_get_drvdata(dev); + struct velocity_info *vptr = netdev_priv(netdev); unsigned long flags; if (!netif_running(vptr->netdev)) @@ -3015,20 +3140,23 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(vptr->netdev); spin_lock_irqsave(&vptr->lock, flags); - pci_save_state(pdev); + if (vptr->pdev) + pci_save_state(vptr->pdev); if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) { velocity_get_ip(vptr); velocity_save_context(vptr, &vptr->context); velocity_shutdown(vptr); velocity_set_wol(vptr); - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_set_power_state(pdev, PCI_D3hot); + if (vptr->pdev) + pci_enable_wake(vptr->pdev, PCI_D3hot, 1); + velocity_set_power_state(vptr, PCI_D3hot); } else { velocity_save_context(vptr, &vptr->context); velocity_shutdown(vptr); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + if (vptr->pdev) + pci_disable_device(vptr->pdev); + velocity_set_power_state(vptr, PCI_D3hot); } spin_unlock_irqrestore(&vptr->lock, flags); @@ -3070,19 +3198,22 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity writeb(*((u8 *) (context->mac_reg + i)), ptr + i); } -static int velocity_resume(struct pci_dev *pdev) +static int velocity_resume(struct device *dev) { - struct net_device *dev = pci_get_drvdata(pdev); - struct velocity_info *vptr = netdev_priv(dev); + struct net_device *netdev = dev_get_drvdata(dev); + struct velocity_info *vptr = netdev_priv(netdev); unsigned long flags; int i; if (!netif_running(vptr->netdev)) return 0; - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, 0, 0); - pci_restore_state(pdev); + velocity_set_power_state(vptr, PCI_D0); + + if (vptr->pdev) { + pci_enable_wake(vptr->pdev, 0, 0); + pci_restore_state(vptr->pdev); + } mac_wol_reset(vptr->mac_regs); @@ -3104,23 +3235,34 @@ static int velocity_resume(struct pci_dev *pdev) return 0; } -#endif +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(velocity_pm_ops, velocity_suspend, velocity_resume); /* * Definition for our device driver. The PCI layer interface * uses this to handle all our card discover and plugging */ -static struct pci_driver velocity_driver = { +static struct pci_driver velocity_pci_driver = { .name = VELOCITY_NAME, - .id_table = velocity_id_table, - .probe = velocity_found1, - .remove = velocity_remove1, -#ifdef CONFIG_PM - .suspend = velocity_suspend, - .resume = velocity_resume, -#endif + .id_table = velocity_pci_id_table, + .probe = velocity_pci_probe, + .remove = velocity_pci_remove, + .driver = { + .pm = &velocity_pm_ops, + }, }; +static struct platform_driver velocity_platform_driver = { + .probe = velocity_platform_probe, + .remove = velocity_platform_remove, + .driver = { + .name = "via-velocity", + .owner = THIS_MODULE, + .of_match_table = velocity_of_ids, + .pm = &velocity_pm_ops, + }, +}; /** * velocity_ethtool_up - pre hook for ethtool @@ -3133,7 +3275,7 @@ static int velocity_ethtool_up(struct net_device *dev) { struct velocity_info *vptr = netdev_priv(dev); if (!netif_running(dev)) - pci_set_power_state(vptr->pdev, PCI_D0); + velocity_set_power_state(vptr, PCI_D0); return 0; } @@ -3148,7 +3290,7 @@ static void velocity_ethtool_down(struct net_device *dev) { struct velocity_info *vptr = netdev_priv(dev); if (!netif_running(dev)) - pci_set_power_state(vptr->pdev, PCI_D3hot); + velocity_set_power_state(vptr, PCI_D3hot); } static int velocity_get_settings(struct net_device *dev, @@ -3268,9 +3410,14 @@ static int velocity_set_settings(struct net_device *dev, static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct velocity_info *vptr = netdev_priv(dev); + strlcpy(info->driver, VELOCITY_NAME, sizeof(info->driver)); strlcpy(info->version, VELOCITY_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(vptr->pdev), sizeof(info->bus_info)); + if (vptr->pdev) + strlcpy(info->bus_info, pci_name(vptr->pdev), + sizeof(info->bus_info)); + else + strlcpy(info->bus_info, "platform", sizeof(info->bus_info)); } static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) @@ -3560,13 +3707,20 @@ static void velocity_unregister_notifier(void) */ static int __init velocity_init_module(void) { - int ret; + int ret_pci, ret_platform; velocity_register_notifier(); - ret = pci_register_driver(&velocity_driver); - if (ret < 0) + + ret_pci = pci_register_driver(&velocity_pci_driver); + ret_platform = platform_driver_register(&velocity_platform_driver); + + /* if both_registers failed, remove the notifier */ + if ((ret_pci < 0) && (ret_platform < 0)) { velocity_unregister_notifier(); - return ret; + return ret_pci; + } + + return 0; } /** @@ -3580,7 +3734,9 @@ static int __init velocity_init_module(void) static void __exit velocity_cleanup_module(void) { velocity_unregister_notifier(); - pci_unregister_driver(&velocity_driver); + + pci_unregister_driver(&velocity_pci_driver); + platform_driver_unregister(&velocity_platform_driver); } module_init(velocity_init_module); diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h index c38bbaed4d12..9453bfa9324a 100644 --- a/drivers/net/ethernet/via/via-velocity.h +++ b/drivers/net/ethernet/via/via-velocity.h @@ -1265,7 +1265,7 @@ struct velocity_context { #define PHYID_VT3216_64BIT 0x000FC600UL #define PHYID_MARVELL_1000 0x01410C50UL #define PHYID_MARVELL_1000S 0x01410C40UL - +#define PHYID_ICPLUS_IP101A 0x02430C54UL #define PHYID_REV_ID_MASK 0x0000000FUL #define PHYID_GET_PHY_ID(i) ((i) & ~PHYID_REV_ID_MASK) @@ -1437,6 +1437,7 @@ struct velocity_info { struct device *dev; struct pci_dev *pdev; struct net_device *netdev; + int no_eeprom; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; u8 ip_addr[4]; -- GitLab From 1ca2983aaa01233dc1ea63ef1b483678fcece6c8 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 20 May 2013 01:05:12 +0000 Subject: [PATCH 0127/2900] xen-netfront: avoid leaking resources when setup_netfront fails We should correctly free related resources (grant ref, memory page, evtchn) when setup_netfront fails. Signed-off-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 1db101415069..5770e3b0ba73 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1532,40 +1532,49 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); err = xenbus_grant_ring(dev, virt_to_mfn(txs)); - if (err < 0) { - free_page((unsigned long)txs); - goto fail; - } + if (err < 0) + goto grant_tx_ring_fail; info->tx_ring_ref = err; rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH); if (!rxs) { err = -ENOMEM; xenbus_dev_fatal(dev, err, "allocating rx ring page"); - goto fail; + goto alloc_rx_ring_fail; } SHARED_RING_INIT(rxs); FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); err = xenbus_grant_ring(dev, virt_to_mfn(rxs)); - if (err < 0) { - free_page((unsigned long)rxs); - goto fail; - } + if (err < 0) + goto grant_rx_ring_fail; info->rx_ring_ref = err; err = xenbus_alloc_evtchn(dev, &info->evtchn); if (err) - goto fail; + goto alloc_evtchn_fail; err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, 0, netdev->name, netdev); if (err < 0) - goto fail; + goto bind_fail; netdev->irq = err; return 0; - fail: + /* If we fail to setup netfront, it is safe to just revoke access to + * granted pages because backend is not accessing it at this point. + */ +bind_fail: + xenbus_free_evtchn(dev, info->evtchn); +alloc_evtchn_fail: + gnttab_end_foreign_access_ref(info->rx_ring_ref, 0); +grant_rx_ring_fail: + free_page((unsigned long)rxs); +alloc_rx_ring_fail: + gnttab_end_foreign_access_ref(info->tx_ring_ref, 0); +grant_tx_ring_fail: + free_page((unsigned long)txs); +fail: return err; } -- GitLab From 4a5bddf7ea6b6c5916eccbc2fa1950555073ff48 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 20 May 2013 03:06:17 +0000 Subject: [PATCH 0128/2900] fec: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core) we can rely on device core for handling pinctrl, so remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ca9825ca88c9..2f4b3e028012 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include @@ -1841,7 +1840,6 @@ fec_probe(struct platform_device *pdev) struct resource *r; const struct of_device_id *of_id; static int dev_id; - struct pinctrl *pinctrl; struct regulator *reg_phy; of_id = of_match_device(fec_dt_ids, &pdev->dev); @@ -1891,12 +1889,6 @@ fec_probe(struct platform_device *pdev) fep->phy_interface = ret; } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto failed_pin; - } - fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(fep->clk_ipg)) { ret = PTR_ERR(fep->clk_ipg); @@ -1996,7 +1988,6 @@ fec_probe(struct platform_device *pdev) clk_disable_unprepare(fep->clk_ipg); clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ptp); -failed_pin: failed_clk: failed_ioremap: free_netdev(ndev); -- GitLab From 99bbc70741903c063b3ccad90a3e06fc55df9245 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Mon, 20 May 2013 04:02:32 +0000 Subject: [PATCH 0129/2900] rps: selective flow shedding during softnet overflow A cpu executing the network receive path sheds packets when its input queue grows to netdev_max_backlog. A single high rate flow (such as a spoofed source DoS) can exceed a single cpu processing rate and will degrade throughput of other flows hashed onto the same cpu. This patch adds a more fine grained hashtable. If the netdev backlog is above a threshold, IRQ cpus track the ratio of total traffic of each flow (using 4096 buckets, configurable). The ratio is measured by counting the number of packets per flow over the last 256 packets from the source cpu. Any flow that occupies a large fraction of this (set at 50%) will see packet drop while above the threshold. Tested: Setup is a muli-threaded UDP echo server with network rx IRQ on cpu0, kernel receive (RPS) on cpu0 and application threads on cpus 2--7 each handling 20k req/s. Throughput halves when hit with a 400 kpps antagonist storm. With this patch applied, antagonist overload is dropped and the server processes its complete load. The patch is effective when kernel receive processing is the bottleneck. The above RPS scenario is a extreme, but the same is reached with RFS and sufficient kernel processing (iptables, packet socket tap, ..). Signed-off-by: Willem de Bruijn Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/netdevice.h | 17 ++++++ net/Kconfig | 12 +++++ net/core/dev.c | 48 ++++++++++++++++- net/core/net-procfs.c | 16 +++++- net/core/sysctl_net_core.c | 104 +++++++++++++++++++++++++++++++++++++ 5 files changed, 194 insertions(+), 3 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a94a5a0ab122..7dd535d4b41e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1778,6 +1778,19 @@ static inline int unregister_gifconf(unsigned int family) return register_gifconf(family, NULL); } +#ifdef CONFIG_NET_FLOW_LIMIT +#define FLOW_LIMIT_HISTORY (1 << 8) /* must be ^2 */ +struct sd_flow_limit { + u64 count; + unsigned int num_buckets; + unsigned int history_head; + u16 history[FLOW_LIMIT_HISTORY]; + u8 buckets[]; +}; + +extern int netdev_flow_limit_table_len; +#endif /* CONFIG_NET_FLOW_LIMIT */ + /* * Incoming packets are placed on per-cpu queues */ @@ -1807,6 +1820,10 @@ struct softnet_data { unsigned int dropped; struct sk_buff_head input_pkt_queue; struct napi_struct backlog; + +#ifdef CONFIG_NET_FLOW_LIMIT + struct sd_flow_limit *flow_limit; +#endif }; static inline void input_queue_head_incr(struct softnet_data *sd) diff --git a/net/Kconfig b/net/Kconfig index 2ddc9046868e..08de901415ee 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -259,6 +259,18 @@ config BPF_JIT packet sniffing (libpcap/tcpdump). Note : Admin should enable this feature changing /proc/sys/net/core/bpf_jit_enable +config NET_FLOW_LIMIT + boolean + depends on RPS + default y + ---help--- + The network stack has to drop packets when a receive processing CPU's + backlog reaches netdev_max_backlog. If a few out of many active flows + generate the vast majority of load, drop their traffic earlier to + maintain capacity for the other flows. This feature provides servers + with many clients some protection against DoS by a single (spoofed) + flow that greatly exceeds average workload. + menu "Network testing" config NET_PKTGEN diff --git a/net/core/dev.c b/net/core/dev.c index 18e9730cc4be..7229bc30e509 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3064,6 +3064,46 @@ static int rps_ipi_queued(struct softnet_data *sd) return 0; } +#ifdef CONFIG_NET_FLOW_LIMIT +int netdev_flow_limit_table_len __read_mostly = (1 << 12); +#endif + +static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen) +{ +#ifdef CONFIG_NET_FLOW_LIMIT + struct sd_flow_limit *fl; + struct softnet_data *sd; + unsigned int old_flow, new_flow; + + if (qlen < (netdev_max_backlog >> 1)) + return false; + + sd = &__get_cpu_var(softnet_data); + + rcu_read_lock(); + fl = rcu_dereference(sd->flow_limit); + if (fl) { + new_flow = skb_get_rxhash(skb) & (fl->num_buckets - 1); + old_flow = fl->history[fl->history_head]; + fl->history[fl->history_head] = new_flow; + + fl->history_head++; + fl->history_head &= FLOW_LIMIT_HISTORY - 1; + + if (likely(fl->buckets[old_flow])) + fl->buckets[old_flow]--; + + if (++fl->buckets[new_flow] > (FLOW_LIMIT_HISTORY >> 1)) { + fl->count++; + rcu_read_unlock(); + return true; + } + } + rcu_read_unlock(); +#endif + return false; +} + /* * enqueue_to_backlog is called to queue an skb to a per CPU backlog * queue (may be a remote CPU queue). @@ -3073,13 +3113,15 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu, { struct softnet_data *sd; unsigned long flags; + unsigned int qlen; sd = &per_cpu(softnet_data, cpu); local_irq_save(flags); rps_lock(sd); - if (skb_queue_len(&sd->input_pkt_queue) <= netdev_max_backlog) { + qlen = skb_queue_len(&sd->input_pkt_queue); + if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) { if (skb_queue_len(&sd->input_pkt_queue)) { enqueue: __skb_queue_tail(&sd->input_pkt_queue, skb); @@ -6269,6 +6311,10 @@ static int __init net_dev_init(void) sd->backlog.weight = weight_p; sd->backlog.gro_list = NULL; sd->backlog.gro_count = 0; + +#ifdef CONFIG_NET_FLOW_LIMIT + sd->flow_limit = NULL; +#endif } dev_boot_phase = 0; diff --git a/net/core/net-procfs.c b/net/core/net-procfs.c index 569d355fec3e..2bf83299600a 100644 --- a/net/core/net-procfs.c +++ b/net/core/net-procfs.c @@ -146,11 +146,23 @@ static void softnet_seq_stop(struct seq_file *seq, void *v) static int softnet_seq_show(struct seq_file *seq, void *v) { struct softnet_data *sd = v; + unsigned int flow_limit_count = 0; - seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", +#ifdef CONFIG_NET_FLOW_LIMIT + struct sd_flow_limit *fl; + + rcu_read_lock(); + fl = rcu_dereference(sd->flow_limit); + if (fl) + flow_limit_count = fl->count; + rcu_read_unlock(); +#endif + + seq_printf(seq, + "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", sd->processed, sd->dropped, sd->time_squeeze, 0, 0, 0, 0, 0, /* was fastroute */ - sd->cpu_collision, sd->received_rps); + sd->cpu_collision, sd->received_rps, flow_limit_count); return 0; } diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index cfdb46ab3a7f..741db5fc7806 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -87,6 +87,96 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write, } #endif /* CONFIG_RPS */ +#ifdef CONFIG_NET_FLOW_LIMIT +static DEFINE_MUTEX(flow_limit_update_mutex); + +static int flow_limit_cpu_sysctl(ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct sd_flow_limit *cur; + struct softnet_data *sd; + cpumask_var_t mask; + int i, len, ret = 0; + + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + return -ENOMEM; + + if (write) { + ret = cpumask_parse_user(buffer, *lenp, mask); + if (ret) + goto done; + + mutex_lock(&flow_limit_update_mutex); + len = sizeof(*cur) + netdev_flow_limit_table_len; + for_each_possible_cpu(i) { + sd = &per_cpu(softnet_data, i); + cur = rcu_dereference_protected(sd->flow_limit, + lockdep_is_held(&flow_limit_update_mutex)); + if (cur && !cpumask_test_cpu(i, mask)) { + RCU_INIT_POINTER(sd->flow_limit, NULL); + synchronize_rcu(); + kfree(cur); + } else if (!cur && cpumask_test_cpu(i, mask)) { + cur = kzalloc(len, GFP_KERNEL); + if (!cur) { + /* not unwinding previous changes */ + ret = -ENOMEM; + goto write_unlock; + } + cur->num_buckets = netdev_flow_limit_table_len; + rcu_assign_pointer(sd->flow_limit, cur); + } + } +write_unlock: + mutex_unlock(&flow_limit_update_mutex); + } else { + if (*ppos || !*lenp) { + *lenp = 0; + goto done; + } + + cpumask_clear(mask); + rcu_read_lock(); + for_each_possible_cpu(i) { + sd = &per_cpu(softnet_data, i); + if (rcu_dereference(sd->flow_limit)) + cpumask_set_cpu(i, mask); + } + rcu_read_unlock(); + + len = cpumask_scnprintf(buffer, *lenp, mask); + *lenp = len + 1; + *ppos += len + 1; + } + +done: + free_cpumask_var(mask); + return ret; +} + +static int flow_limit_table_len_sysctl(ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + unsigned int old, *ptr; + int ret; + + mutex_lock(&flow_limit_update_mutex); + + ptr = table->data; + old = *ptr; + ret = proc_dointvec(table, write, buffer, lenp, ppos); + if (!ret && write && !is_power_of_2(*ptr)) { + *ptr = old; + ret = -EINVAL; + } + + mutex_unlock(&flow_limit_update_mutex); + return ret; +} +#endif /* CONFIG_NET_FLOW_LIMIT */ + static struct ctl_table net_core_table[] = { #ifdef CONFIG_NET { @@ -180,6 +270,20 @@ static struct ctl_table net_core_table[] = { .proc_handler = rps_sock_flow_sysctl }, #endif +#ifdef CONFIG_NET_FLOW_LIMIT + { + .procname = "flow_limit_cpu_bitmap", + .mode = 0644, + .proc_handler = flow_limit_cpu_sysctl + }, + { + .procname = "flow_limit_table_len", + .data = &netdev_flow_limit_table_len, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = flow_limit_table_len_sysctl + }, +#endif /* CONFIG_NET_FLOW_LIMIT */ #endif /* CONFIG_NET */ { .procname = "netdev_budget", -- GitLab From 168fc21a971e4bc821a7838ccc39b7bdaf316c11 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 20 May 2013 04:53:38 +0000 Subject: [PATCH 0130/2900] net: ipv6: remove 'next' member from inet6_dev The next pointer within the inet6_dev structure seems not to be used anywhere. So just remove it. Tested with allmodconfig on x86_64. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/net/if_inet6.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 0727d0e4af3b..e07feb456d19 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -193,7 +193,6 @@ struct inet6_dev { struct in6_addr token; struct neigh_parms *nd_parms; - struct inet6_dev *next; struct ipv6_devconf cnf; struct ipv6_devstat stats; unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ -- GitLab From 71cea17ed39fdf1c0634f530ddc6a2c2fc601c2b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 20 May 2013 06:52:26 +0000 Subject: [PATCH 0131/2900] tcp: md5: remove spinlock usage in fast path TCP md5 code uses per cpu variables but protects access to them with a shared spinlock, which is a contention point. [ tcp_md5sig_pool_lock is locked twice per incoming packet ] Makes things much simpler, by allocating crypto structures once, first time a socket needs md5 keys, and not deallocating them as they are really small. Next step would be to allow crypto allocations being done in a NUMA aware way. Signed-off-by: Eric Dumazet Cc: Herbert Xu Signed-off-by: David S. Miller --- include/net/tcp.h | 8 ++-- net/ipv4/tcp.c | 98 +++++++++------------------------------- net/ipv4/tcp_ipv4.c | 10 +--- net/ipv4/tcp_minisocks.c | 6 +-- 4 files changed, 29 insertions(+), 93 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index e1c3723f161f..bf1cc3dced5e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1283,11 +1283,13 @@ static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk, #define tcp_twsk_md5_key(twsk) NULL #endif -extern struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *); -extern void tcp_free_md5sig_pool(void); +extern bool tcp_alloc_md5sig_pool(void); extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void); -extern void tcp_put_md5sig_pool(void); +static inline void tcp_put_md5sig_pool(void) +{ + local_bh_enable(); +} extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *); extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index dcb116dde216..53d9c120fbb8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3095,9 +3095,8 @@ int tcp_gro_complete(struct sk_buff *skb) EXPORT_SYMBOL(tcp_gro_complete); #ifdef CONFIG_TCP_MD5SIG -static unsigned long tcp_md5sig_users; -static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool; -static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); +static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly; +static DEFINE_MUTEX(tcp_md5sig_mutex); static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool) { @@ -3112,30 +3111,14 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool) free_percpu(pool); } -void tcp_free_md5sig_pool(void) -{ - struct tcp_md5sig_pool __percpu *pool = NULL; - - spin_lock_bh(&tcp_md5sig_pool_lock); - if (--tcp_md5sig_users == 0) { - pool = tcp_md5sig_pool; - tcp_md5sig_pool = NULL; - } - spin_unlock_bh(&tcp_md5sig_pool_lock); - if (pool) - __tcp_free_md5sig_pool(pool); -} -EXPORT_SYMBOL(tcp_free_md5sig_pool); - -static struct tcp_md5sig_pool __percpu * -__tcp_alloc_md5sig_pool(struct sock *sk) +static void __tcp_alloc_md5sig_pool(void) { int cpu; struct tcp_md5sig_pool __percpu *pool; pool = alloc_percpu(struct tcp_md5sig_pool); if (!pool) - return NULL; + return; for_each_possible_cpu(cpu) { struct crypto_hash *hash; @@ -3146,53 +3129,27 @@ __tcp_alloc_md5sig_pool(struct sock *sk) per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash; } - return pool; + /* before setting tcp_md5sig_pool, we must commit all writes + * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool() + */ + smp_wmb(); + tcp_md5sig_pool = pool; + return; out_free: __tcp_free_md5sig_pool(pool); - return NULL; } -struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *sk) +bool tcp_alloc_md5sig_pool(void) { - struct tcp_md5sig_pool __percpu *pool; - bool alloc = false; - -retry: - spin_lock_bh(&tcp_md5sig_pool_lock); - pool = tcp_md5sig_pool; - if (tcp_md5sig_users++ == 0) { - alloc = true; - spin_unlock_bh(&tcp_md5sig_pool_lock); - } else if (!pool) { - tcp_md5sig_users--; - spin_unlock_bh(&tcp_md5sig_pool_lock); - cpu_relax(); - goto retry; - } else - spin_unlock_bh(&tcp_md5sig_pool_lock); - - if (alloc) { - /* we cannot hold spinlock here because this may sleep. */ - struct tcp_md5sig_pool __percpu *p; - - p = __tcp_alloc_md5sig_pool(sk); - spin_lock_bh(&tcp_md5sig_pool_lock); - if (!p) { - tcp_md5sig_users--; - spin_unlock_bh(&tcp_md5sig_pool_lock); - return NULL; - } - pool = tcp_md5sig_pool; - if (pool) { - /* oops, it has already been assigned. */ - spin_unlock_bh(&tcp_md5sig_pool_lock); - __tcp_free_md5sig_pool(p); - } else { - tcp_md5sig_pool = pool = p; - spin_unlock_bh(&tcp_md5sig_pool_lock); - } + if (unlikely(!tcp_md5sig_pool)) { + mutex_lock(&tcp_md5sig_mutex); + + if (!tcp_md5sig_pool) + __tcp_alloc_md5sig_pool(); + + mutex_unlock(&tcp_md5sig_mutex); } - return pool; + return tcp_md5sig_pool != NULL; } EXPORT_SYMBOL(tcp_alloc_md5sig_pool); @@ -3209,28 +3166,15 @@ struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) struct tcp_md5sig_pool __percpu *p; local_bh_disable(); - - spin_lock(&tcp_md5sig_pool_lock); - p = tcp_md5sig_pool; - if (p) - tcp_md5sig_users++; - spin_unlock(&tcp_md5sig_pool_lock); - + p = ACCESS_ONCE(tcp_md5sig_pool); if (p) - return this_cpu_ptr(p); + return __this_cpu_ptr(p); local_bh_enable(); return NULL; } EXPORT_SYMBOL(tcp_get_md5sig_pool); -void tcp_put_md5sig_pool(void) -{ - local_bh_enable(); - tcp_free_md5sig_pool(); -} -EXPORT_SYMBOL(tcp_put_md5sig_pool); - int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, const struct tcphdr *th) { diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 719652305a29..d20ede0c9593 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1026,7 +1026,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, key = sock_kmalloc(sk, sizeof(*key), gfp); if (!key) return -ENOMEM; - if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) { + if (!tcp_alloc_md5sig_pool()) { sock_kfree_s(sk, key, sizeof(*key)); return -ENOMEM; } @@ -1044,9 +1044,7 @@ EXPORT_SYMBOL(tcp_md5_do_add); int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) { - struct tcp_sock *tp = tcp_sk(sk); struct tcp_md5sig_key *key; - struct tcp_md5sig_info *md5sig; key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); if (!key) @@ -1054,10 +1052,6 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) hlist_del_rcu(&key->node); atomic_sub(sizeof(*key), &sk->sk_omem_alloc); kfree_rcu(key, rcu); - md5sig = rcu_dereference_protected(tp->md5sig_info, - sock_owned_by_user(sk)); - if (hlist_empty(&md5sig->head)) - tcp_free_md5sig_pool(); return 0; } EXPORT_SYMBOL(tcp_md5_do_del); @@ -1071,8 +1065,6 @@ static void tcp_clear_md5_list(struct sock *sk) md5sig = rcu_dereference_protected(tp->md5sig_info, 1); - if (!hlist_empty(&md5sig->head)) - tcp_free_md5sig_pool(); hlist_for_each_entry_safe(key, n, &md5sig->head, node) { hlist_del_rcu(&key->node); atomic_sub(sizeof(*key), &sk->sk_omem_alloc); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0f0178827259..ab1c08658528 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -317,7 +317,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) key = tp->af_specific->md5_lookup(sk, sk); if (key != NULL) { tcptw->tw_md5_key = kmemdup(key, sizeof(*key), GFP_ATOMIC); - if (tcptw->tw_md5_key && tcp_alloc_md5sig_pool(sk) == NULL) + if (tcptw->tw_md5_key && !tcp_alloc_md5sig_pool()) BUG(); } } while (0); @@ -358,10 +358,8 @@ void tcp_twsk_destructor(struct sock *sk) #ifdef CONFIG_TCP_MD5SIG struct tcp_timewait_sock *twsk = tcp_twsk(sk); - if (twsk->tw_md5_key) { - tcp_free_md5sig_pool(); + if (twsk->tw_md5_key) kfree_rcu(twsk->tw_md5_key, rcu); - } #endif } EXPORT_SYMBOL_GPL(tcp_twsk_destructor); -- GitLab From ed900ffb73e3ab154dff1ae20a2393f24da728df Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 20 May 2013 08:05:50 +0000 Subject: [PATCH 0132/2900] ppc: bpf_jit: can call module_free() from any context Followup patch on module_free()/vfree() that takes care of the rest, so no longer this workaround with work_struct is needed. Signed-off-by: Daniel Borkmann Cc: Al Viro Cc: Matt Evans Signed-off-by: David S. Miller --- arch/powerpc/net/bpf_jit_comp.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index c427ae36374a..bf56e33f8257 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -650,8 +650,7 @@ void bpf_jit_compile(struct sk_filter *fp) proglen = cgctx.idx * 4; alloclen = proglen + FUNCTION_DESCR_SIZE; - image = module_alloc(max_t(unsigned int, alloclen, - sizeof(struct work_struct))); + image = module_alloc(alloclen); if (!image) goto out; @@ -688,20 +687,8 @@ void bpf_jit_compile(struct sk_filter *fp) return; } -static void jit_free_defer(struct work_struct *arg) -{ - module_free(NULL, arg); -} - -/* run from softirq, we must use a work_struct to call - * module_free() from process context - */ void bpf_jit_free(struct sk_filter *fp) { - if (fp->bpf_func != sk_run_filter) { - struct work_struct *work = (struct work_struct *)fp->bpf_func; - - INIT_WORK(work, jit_free_defer); - schedule_work(work); - } + if (fp->bpf_func != sk_run_filter) + module_free(NULL, fp->bpf_func); } -- GitLab From aafc787e41fd8a4d3a4378b028d8d8f8d38d9bb6 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 20 May 2013 08:05:51 +0000 Subject: [PATCH 0133/2900] arm: bpf_jit: can call module_free() from any context Follow-up on module_free()/vfree() that takes care of the rest, so no longer this workaround with work_struct needed. Signed-off-by: Daniel Borkmann Cc: Al Viro Cc: Mircea Gherzan Signed-off-by: David S. Miller --- arch/arm/net/bpf_jit_32.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 1a643ee8e082..f50d223a0bd3 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -900,8 +900,7 @@ void bpf_jit_compile(struct sk_filter *fp) #endif alloc_size = 4 * ctx.idx; - ctx.target = module_alloc(max(sizeof(struct work_struct), - alloc_size)); + ctx.target = module_alloc(alloc_size); if (unlikely(ctx.target == NULL)) goto out; @@ -927,19 +926,8 @@ void bpf_jit_compile(struct sk_filter *fp) return; } -static void bpf_jit_free_worker(struct work_struct *work) -{ - module_free(NULL, work); -} - void bpf_jit_free(struct sk_filter *fp) { - struct work_struct *work; - - if (fp->bpf_func != sk_run_filter) { - work = (struct work_struct *)fp->bpf_func; - - INIT_WORK(work, bpf_jit_free_worker); - schedule_work(work); - } + if (fp->bpf_func != sk_run_filter) + module_free(NULL, fp->bpf_func); } -- GitLab From 0b8bf1baabe56f721d541953f083560d0660d78f Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 20 May 2013 09:16:58 +0000 Subject: [PATCH 0134/2900] net: dm9000: Allow instantiation using device tree This patch adds Device Tree support to dm9000 driver. Signed-off-by: Tomasz Figa Reviewed-by: Sylwester Nawrocki Reviewed-by: Sascha Hauer Signed-off-by: David S. Miller --- .../bindings/net/davicom-dm9000.txt | 26 ++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 1 + drivers/net/ethernet/davicom/dm9000.c | 42 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/davicom-dm9000.txt diff --git a/Documentation/devicetree/bindings/net/davicom-dm9000.txt b/Documentation/devicetree/bindings/net/davicom-dm9000.txt new file mode 100644 index 000000000000..2d39c990e641 --- /dev/null +++ b/Documentation/devicetree/bindings/net/davicom-dm9000.txt @@ -0,0 +1,26 @@ +Davicom DM9000 Fast Ethernet controller + +Required properties: +- compatible = "davicom,dm9000"; +- reg : physical addresses and sizes of registers, must contain 2 entries: + first entry : address register, + second entry : data register. +- interrupt-parent : interrupt controller to which the device is connected +- interrupts : interrupt specifier specific to interrupt controller + +Optional properties: +- local-mac-address : A bytestring of 6 bytes specifying Ethernet MAC address + to use (from firmware or bootloader) +- davicom,no-eeprom : Configuration EEPROM is not available +- davicom,ext-phy : Use external PHY + +Example: + + ethernet@18000000 { + compatible = "davicom,dm9000"; + reg = <0x18000000 0x2 0x18000004 0x2>; + interrupt-parent = <&gpn>; + interrupts = <7 4>; + local-mac-address = [00 00 de ad be ef]; + davicom,no-eeprom; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 6931c4348d24..2fe74e6ec209 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -18,6 +18,7 @@ chrp Common Hardware Reference Platform cirrus Cirrus Logic, Inc. cortina Cortina Systems, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) +davicom DAVICOM Semiconductor, Inc. denx Denx Software Engineering emmicro EM Microelectronic epson Seiko Epson Corp. diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index a2408c84bbdd..dd243a1b03e0 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -1351,6 +1353,31 @@ static const struct net_device_ops dm9000_netdev_ops = { #endif }; +static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev) +{ + struct dm9000_plat_data *pdata; + struct device_node *np = dev->of_node; + const void *mac_addr; + + if (!IS_ENABLED(CONFIG_OF) || !np) + return NULL; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + if (of_find_property(np, "davicom,ext-phy", NULL)) + pdata->flags |= DM9000_PLATF_EXT_PHY; + if (of_find_property(np, "davicom,no-eeprom", NULL)) + pdata->flags |= DM9000_PLATF_NO_EEPROM; + + mac_addr = of_get_mac_address(np); + if (mac_addr) + memcpy(pdata->dev_addr, mac_addr, sizeof(pdata->dev_addr)); + + return pdata; +} + /* * Search DM9000 board, allocate space and register it */ @@ -1366,6 +1393,12 @@ dm9000_probe(struct platform_device *pdev) int i; u32 id_val; + if (!pdata) { + pdata = dm9000_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } + /* Init network device */ ndev = alloc_etherdev(sizeof(struct board_info)); if (!ndev) @@ -1676,11 +1709,20 @@ dm9000_drv_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id dm9000_of_matches[] = { + { .compatible = "davicom,dm9000", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, dm9000_of_matches); +#endif + static struct platform_driver dm9000_driver = { .driver = { .name = "dm9000", .owner = THIS_MODULE, .pm = &dm9000_drv_pm_ops, + .of_match_table = of_match_ptr(dm9000_of_matches), }, .probe = dm9000_probe, .remove = dm9000_drv_remove, -- GitLab From 4b2305826ccd57a8b22d3daff543837ba27cfd43 Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 20 May 2013 10:08:01 +0000 Subject: [PATCH 0135/2900] bna: Clear Driver Config Flags When HW Resets Driver configuration flags are retained across open/stop operations preventing configurations to be set in next open/stop. Setting MTU on a 1020 causes network to fail until a reboot is performed on the host. Clear the flags when configuration resets in hardware. Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bnad.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 07f7ef05c3f2..b78e69e0e52a 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -2624,6 +2624,9 @@ bnad_stop(struct net_device *netdev) bnad_destroy_tx(bnad, 0); bnad_destroy_rx(bnad, 0); + /* These config flags are cleared in the hardware */ + bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI | BNAD_CF_PROMISC); + /* Synchronize mailbox IRQ */ bnad_mbox_irq_sync(bnad); -- GitLab From f489a4ba769ca1d7dd4657a4f68ea93746dd669b Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 20 May 2013 10:08:02 +0000 Subject: [PATCH 0136/2900] bna: Fix Ucast Failure Handling Failure of the UCAST set for base mac address fails when user configures a duplicate mac address that matches that of another vNIC on the same port. The bna does not handle the ucast failure and keeps this address in cache. On disable of the vNIC, bna tries to delete the failed base mac address and the fw asserts. On failure of ucast address, mark ucast address set to false. Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bna.h | 2 ++ drivers/net/ethernet/brocade/bna/bna_enet.c | 7 ++++++- drivers/net/ethernet/brocade/bna/bna_tx_rx.c | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/brocade/bna/bna.h b/drivers/net/ethernet/brocade/bna/bna.h index 25dae757e9c4..f1eafc409bbd 100644 --- a/drivers/net/ethernet/brocade/bna/bna.h +++ b/drivers/net/ethernet/brocade/bna/bna.h @@ -455,6 +455,8 @@ void bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx, void bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr); void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr); +void bna_bfi_rxf_ucast_set_rsp(struct bna_rxf *rxf, + struct bfi_msgq_mhdr *msghdr); /* APIs for BNA */ void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna, diff --git a/drivers/net/ethernet/brocade/bna/bna_enet.c b/drivers/net/ethernet/brocade/bna/bna_enet.c index db14f69d63bc..3ca77fad4851 100644 --- a/drivers/net/ethernet/brocade/bna/bna_enet.c +++ b/drivers/net/ethernet/brocade/bna/bna_enet.c @@ -298,7 +298,6 @@ bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr) case BFI_ENET_I2H_RSS_ENABLE_RSP: case BFI_ENET_I2H_RX_PROMISCUOUS_RSP: case BFI_ENET_I2H_RX_DEFAULT_RSP: - case BFI_ENET_I2H_MAC_UCAST_SET_RSP: case BFI_ENET_I2H_MAC_UCAST_CLR_RSP: case BFI_ENET_I2H_MAC_UCAST_ADD_RSP: case BFI_ENET_I2H_MAC_UCAST_DEL_RSP: @@ -311,6 +310,12 @@ bna_msgq_rsp_handler(void *arg, struct bfi_msgq_mhdr *msghdr) bna_bfi_rxf_cfg_rsp(&rx->rxf, msghdr); break; + case BFI_ENET_I2H_MAC_UCAST_SET_RSP: + bna_rx_from_rid(bna, msghdr->enet_id, rx); + if (rx) + bna_bfi_rxf_ucast_set_rsp(&rx->rxf, msghdr); + break; + case BFI_ENET_I2H_MAC_MCAST_ADD_RSP: bna_rx_from_rid(bna, msghdr->enet_id, rx); if (rx) diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c index ea6f4a036401..57cd1bff59f1 100644 --- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c +++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c @@ -710,6 +710,21 @@ bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr) bfa_fsm_send_event(rxf, RXF_E_FW_RESP); } +void +bna_bfi_rxf_ucast_set_rsp(struct bna_rxf *rxf, + struct bfi_msgq_mhdr *msghdr) +{ + struct bfi_enet_rsp *rsp = + (struct bfi_enet_rsp *)msghdr; + + if (rsp->error) { + /* Clear ucast from cache */ + rxf->ucast_active_set = 0; + } + + bfa_fsm_send_event(rxf, RXF_E_FW_RESP); +} + void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr) -- GitLab From 43c07adaebc34d8c23cdc60128fc7f41088515f7 Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 20 May 2013 10:08:03 +0000 Subject: [PATCH 0137/2900] bna: Enahncement to Identify Default IOC Function User should not be allowed to delete base function of eth port. Add a new field to the bfa ioc attributes structure to indicate if the given ioc is default function on the port or not. Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bfa_defs.h | 3 ++- drivers/net/ethernet/brocade/bna/bfa_ioc.c | 7 ++++--- drivers/net/ethernet/brocade/bna/bfa_ioc.h | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h index e423f82da490..b7d8127c198f 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_defs.h +++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h @@ -164,7 +164,8 @@ struct bfa_ioc_attr { u8 port_mode; /*!< enum bfa_mode */ u8 cap_bm; /*!< capability */ u8 port_mode_cfg; /*!< enum bfa_mode */ - u8 rsvd[4]; /*!< 64bit align */ + u8 def_fn; /*!< 1 if default fn */ + u8 rsvd[3]; /*!< 64bit align */ }; /* Adapter capability mask definition */ diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index f2b73ffa9122..6f3cac060f29 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -2371,7 +2371,7 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr)); ioc_attr->state = bfa_ioc_get_state(ioc); - ioc_attr->port_id = ioc->port_id; + ioc_attr->port_id = bfa_ioc_portid(ioc); ioc_attr->port_mode = ioc->port_mode; ioc_attr->port_mode_cfg = ioc->port_mode_cfg; @@ -2381,8 +2381,9 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); - ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; - ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; + ioc_attr->pci_attr.device_id = bfa_ioc_devid(ioc); + ioc_attr->pci_attr.pcifn = bfa_ioc_pcifn(ioc); + ioc_attr->def_fn = bfa_ioc_is_default(ioc); bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev); } diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h index 63a85e555df8..f04e0aab25b4 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.h +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h @@ -222,6 +222,8 @@ struct bfa_ioc_hwif { #define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) #define bfa_ioc_asic_gen(__ioc) ((__ioc)->asic_gen) +#define bfa_ioc_is_default(__ioc) \ + (bfa_ioc_pcifn(__ioc) == bfa_ioc_portid(__ioc)) #define bfa_ioc_fetch_stats(__ioc, __stats) \ (((__stats)->drv_stats) = (__ioc)->stats) #define bfa_ioc_clr_stats(__ioc) \ -- GitLab From 45e983414334f217c60bd04d39d6f5ec2d8d7bb4 Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 20 May 2013 10:08:04 +0000 Subject: [PATCH 0138/2900] bna: Driver and Firmware Updated Driver and Firmware versions updated to 3.2.21.1. Signed-off-by: Rasesh Mody Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bnad.h | 2 +- drivers/net/ethernet/brocade/bna/cna.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h index c1d0bc059bfd..aefee77523f2 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.h +++ b/drivers/net/ethernet/brocade/bna/bnad.h @@ -71,7 +71,7 @@ struct bnad_rx_ctrl { #define BNAD_NAME "bna" #define BNAD_NAME_LEN 64 -#define BNAD_VERSION "3.1.2.1" +#define BNAD_VERSION "3.2.21.1" #define BNAD_MAILBOX_MSIX_INDEX 0 #define BNAD_MAILBOX_MSIX_VECTORS 1 diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h index 14ca9317c915..c37f706d9992 100644 --- a/drivers/net/ethernet/brocade/bna/cna.h +++ b/drivers/net/ethernet/brocade/bna/cna.h @@ -37,8 +37,8 @@ extern char bfa_version[]; -#define CNA_FW_FILE_CT "ctfw-3.1.0.0.bin" -#define CNA_FW_FILE_CT2 "ct2fw-3.1.0.0.bin" +#define CNA_FW_FILE_CT "ctfw-3.2.1.0.bin" +#define CNA_FW_FILE_CT2 "ct2fw-3.2.1.0.bin" #define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */ #pragma pack(1) -- GitLab From 2c7b49212a86f13697281a4dace2cb96aec71d6b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 19 May 2013 22:53:42 +0000 Subject: [PATCH 0139/2900] phy: fix the use of PHY_IGNORE_INTERRUPT When a PHY device is registered with the special IRQ value PHY_IGNORE_INTERRUPT (-2) it will not properly be handled by the PHY library: - it continues to poll its register, while we do not want this because such PHY link events or register changes are serviced by an Ethernet MAC - it will still try to configure PHY interrupts at the PHY level, such interrupts do not exist at the PHY but at the MAC level - the state machine only handles PHY_POLL, but should also handle PHY_IGNORE_INTERRUPT similarly This patch updates the PHY state machine and initialization paths to account for the specific PHY_IGNORE_INTERRUPT. Based on an earlier patch by Thomas Petazzoni, and reworked to add the missing bits. Add a helper phy_interrupt_is_valid() which specifically tests for a PHY interrupt not to be PHY_POLL or PHY_IGNORE_INTERRUPT and use it throughout the code. Signed-off-by: Thomas Petazzoni Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 9 +++++---- drivers/net/phy/phy_device.c | 7 +++++-- include/linux/phy.h | 12 ++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index c14f14741b3f..3bcf0994d3ba 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -682,7 +682,7 @@ void phy_stop(struct phy_device *phydev) if (PHY_HALTED == phydev->state) goto out_unlock; - if (phydev->irq != PHY_POLL) { + if (phy_interrupt_is_valid(phydev)) { /* Disable PHY Interrupts */ phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); @@ -828,8 +828,9 @@ void phy_state_machine(struct work_struct *work) break; case PHY_RUNNING: /* Only register a CHANGE if we are - * polling */ - if (PHY_POLL == phydev->irq) + * polling or ignoring interrupts + */ + if (!phy_interrupt_is_valid(phydev)) phydev->state = PHY_CHANGELINK; break; case PHY_CHANGELINK: @@ -848,7 +849,7 @@ void phy_state_machine(struct work_struct *work) phydev->adjust_link(phydev->attached_dev); - if (PHY_POLL != phydev->irq) + if (phy_interrupt_is_valid(phydev)) err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); break; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3657b4a29124..8e29d22ba113 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1009,8 +1009,11 @@ static int phy_probe(struct device *dev) phydrv = to_phy_driver(drv); phydev->drv = phydrv; - /* Disable the interrupt if the PHY doesn't support it */ - if (!(phydrv->flags & PHY_HAS_INTERRUPT)) + /* Disable the interrupt if the PHY doesn't support it + * but the interrupt is still a valid one + */ + if (!(phydrv->flags & PHY_HAS_INTERRUPT) && + phy_interrupt_is_valid(phydev)) phydev->irq = PHY_POLL; mutex_lock(&phydev->lock); diff --git a/include/linux/phy.h b/include/linux/phy.h index 9e11039dd7a3..8e4bc8ab692d 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -508,6 +508,18 @@ static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val) return mdiobus_write(phydev->bus, phydev->addr, regnum, val); } +/** + * phy_interrupt_is_valid - Convenience function for testing a given PHY irq + * @phydev: the phy_device struct + * + * NOTE: must be kept in sync with addition/removal of PHY_POLL and + * PHY_IGNORE_INTERRUPT + */ +static inline bool phy_interrupt_is_valid(struct phy_device *phydev) +{ + return phydev->irq != PHY_POLL && phydev->irq != PHY_IGNORE_INTERRUPT; +} + struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, bool is_c45, struct phy_c45_device_ids *c45_ids); struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); -- GitLab From 5ea94e7686a3aa04cc0d01a2d8bd3d0292b3f592 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sun, 19 May 2013 22:53:43 +0000 Subject: [PATCH 0140/2900] phy: add phy_mac_interrupt() to use with PHY_IGNORE_INTERRUPT There is currently no way for an Ethernet MAC driver servicing PHY link interrupts to notify this to the PHY state machine without defining its own state machine. Since most drivers are not so special, introduce a helper: phy_mac_interrupt() which can be called from a link up/down interrupt routine to update the PHY state machine. To avoid code duplication some refactoring has been done to expose the workqueue and its corresponding callback internally. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 14 +++++++++----- drivers/net/phy/phy_device.c | 1 + include/linux/phy.h | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3bcf0994d3ba..2d28a0ef4572 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -419,8 +419,6 @@ int phy_start_aneg(struct phy_device *phydev) EXPORT_SYMBOL(phy_start_aneg); -static void phy_change(struct work_struct *work); - /** * phy_start_machine - start PHY state machine tracking * @phydev: the phy_device struct @@ -565,8 +563,6 @@ int phy_start_interrupts(struct phy_device *phydev) { int err = 0; - INIT_WORK(&phydev->phy_queue, phy_change); - atomic_set(&phydev->irq_disable, 0); if (request_irq(phydev->irq, phy_interrupt, IRQF_SHARED, @@ -623,7 +619,7 @@ EXPORT_SYMBOL(phy_stop_interrupts); * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes * @work: work_struct that describes the work to be done */ -static void phy_change(struct work_struct *work) +void phy_change(struct work_struct *work) { int err; struct phy_device *phydev = @@ -922,6 +918,14 @@ void phy_state_machine(struct work_struct *work) schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ); } +void phy_mac_interrupt(struct phy_device *phydev, int new_link) +{ + cancel_work_sync(&phydev->phy_queue); + phydev->link = new_link; + schedule_work(&phydev->phy_queue); +} +EXPORT_SYMBOL(phy_mac_interrupt); + static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad, int addr) { diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8e29d22ba113..b55aa33a5b8b 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -189,6 +189,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); + INIT_WORK(&dev->phy_queue, phy_change); /* Request the appropriate module unconditionally; don't bother trying to do so only if it isn't already loaded, diff --git a/include/linux/phy.h b/include/linux/phy.h index 8e4bc8ab692d..fdfa11542974 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -557,6 +557,8 @@ void phy_drivers_unregister(struct phy_driver *drv, int n); int phy_driver_register(struct phy_driver *new_driver); int phy_drivers_register(struct phy_driver *new_driver, int n); void phy_state_machine(struct work_struct *work); +void phy_change(struct work_struct *work); +void phy_mac_interrupt(struct phy_device *phydev, int new_link); void phy_start_machine(struct phy_device *phydev, void (*handler)(struct net_device *)); void phy_stop_machine(struct phy_device *phydev); -- GitLab From e80bd1d181ff4601d88cf438817a3a7e84fe6912 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 1 May 2013 01:19:46 +0000 Subject: [PATCH 0141/2900] e1000e: cleanup whitespace Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/e1000e/80003es2lan.c | 24 +++---- drivers/net/ethernet/intel/e1000e/82571.c | 24 +++---- drivers/net/ethernet/intel/e1000e/ethtool.c | 34 +++++----- drivers/net/ethernet/intel/e1000e/hw.h | 34 +++++----- drivers/net/ethernet/intel/e1000e/ich8lan.c | 62 +++++++++---------- drivers/net/ethernet/intel/e1000e/netdev.c | 51 ++++++++------- drivers/net/ethernet/intel/e1000e/nvm.c | 1 - drivers/net/ethernet/intel/e1000e/phy.c | 22 +++---- 8 files changed, 125 insertions(+), 127 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c index b71c8502a2b3..895450e9bb3c 100644 --- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c +++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c @@ -66,17 +66,17 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) s32 ret_val; if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; + phy->type = e1000_phy_none; return 0; } else { phy->ops.power_up = e1000_power_up_phy_copper; phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; } - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - phy->type = e1000_phy_gg82563; + phy->addr = 1; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->reset_delay_us = 100; + phy->type = e1000_phy_gg82563; /* This can only be done after all function pointers are setup. */ ret_val = e1000e_get_phy_id(hw); @@ -98,19 +98,19 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) u32 eecd = er32(EECD); u16 size; - nvm->opcode_bits = 8; - nvm->delay_usec = 1; + nvm->opcode_bits = 8; + nvm->delay_usec = 1; switch (nvm->override) { case e1000_nvm_override_spi_large: - nvm->page_size = 32; + nvm->page_size = 32; nvm->address_bits = 16; break; case e1000_nvm_override_spi_small: - nvm->page_size = 8; + nvm->page_size = 8; nvm->address_bits = 8; break; default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; break; } @@ -128,7 +128,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; - nvm->word_size = 1 << size; + nvm->word_size = 1 << size; return 0; } @@ -859,7 +859,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) /* Transmit Arbitration Control 0 */ reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ + reg &= ~(0xF << 27); /* 30:27 */ if (hw->phy.media_type != e1000_media_type_copper) reg &= ~(1 << 20); ew32(TARC(0), reg); diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 7380442a3829..bef2f103ab03 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -77,24 +77,24 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) return 0; } - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; + phy->addr = 1; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->reset_delay_us = 100; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82571; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_82571; switch (hw->mac.type) { case e1000_82571: case e1000_82572: - phy->type = e1000_phy_igp_2; + phy->type = e1000_phy_igp_2; break; case e1000_82573: - phy->type = e1000_phy_m88; + phy->type = e1000_phy_m88; break; case e1000_82574: case e1000_82583: - phy->type = e1000_phy_bm; + phy->type = e1000_phy_bm; phy->ops.acquire = e1000_get_hw_semaphore_82574; phy->ops.release = e1000_put_hw_semaphore_82574; phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574; @@ -193,7 +193,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) /* EEPROM access above 16k is unsupported */ if (size > 14) size = 14; - nvm->word_size = 1 << size; + nvm->word_size = 1 << size; break; } @@ -339,7 +339,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - static int global_quad_port_a; /* global port a indication */ + static int global_quad_port_a; /* global port a indication */ struct pci_dev *pdev = adapter->pdev; int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; s32 rc; @@ -1178,7 +1178,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) /* Transmit Arbitration Control 0 */ reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ + reg &= ~(0xF << 27); /* 30:27 */ switch (hw->mac.type) { case e1000_82571: case e1000_82572: @@ -1390,7 +1390,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw) ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); if (ret_val) return false; - if (receive_errors == E1000_RECEIVE_ERROR_MAX) { + if (receive_errors == E1000_RECEIVE_ERROR_MAX) { ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); if (ret_val) return false; diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 7c8ca658d553..59c22bf18701 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -244,7 +244,7 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) mac->autoneg = 1; adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ + case SPEED_1000 + DUPLEX_HALF: /* not supported */ default: goto err_inval; } @@ -416,7 +416,7 @@ static void e1000_set_msglevel(struct net_device *netdev, u32 data) static int e1000_get_regs_len(struct net_device __always_unused *netdev) { -#define E1000_REGS_LEN 32 /* overestimate */ +#define E1000_REGS_LEN 32 /* overestimate */ return E1000_REGS_LEN * sizeof(u32); } @@ -433,22 +433,22 @@ static void e1000_get_regs(struct net_device *netdev, regs->version = (1 << 24) | (adapter->pdev->revision << 16) | adapter->pdev->device; - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); + regs_buff[0] = er32(CTRL); + regs_buff[1] = er32(STATUS); - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN(0)); - regs_buff[4] = er32(RDH(0)); - regs_buff[5] = er32(RDT(0)); - regs_buff[6] = er32(RDTR); + regs_buff[2] = er32(RCTL); + regs_buff[3] = er32(RDLEN(0)); + regs_buff[4] = er32(RDH(0)); + regs_buff[5] = er32(RDT(0)); + regs_buff[6] = er32(RDTR); - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDLEN(0)); - regs_buff[9] = er32(TDH(0)); + regs_buff[7] = er32(TCTL); + regs_buff[8] = er32(TDLEN(0)); + regs_buff[9] = er32(TDH(0)); regs_buff[10] = er32(TDT(0)); regs_buff[11] = er32(TIDV); - regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ + regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ /* ethtool doesn't use anything past this point, so all this * code is likely legacy junk for apps that may or may not exist @@ -1379,7 +1379,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) if (hw->phy.media_type == e1000_media_type_copper && hw->phy.type == e1000_phy_m88) { - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ + ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ } else { /* Set the ILOS bit on the fiber Nic if half duplex link is * detected. @@ -1613,7 +1613,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) ew32(TDT(0), k); e1e_flush(); msleep(200); - time = jiffies; /* set the start time for the receive */ + time = jiffies; /* set the start time for the receive */ good_cnt = 0; /* receive the sent packets */ do { @@ -1636,11 +1636,11 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter) */ } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); if (good_cnt != 64) { - ret_val = 13; /* ret_val is the same as mis-compare */ + ret_val = 13; /* ret_val is the same as mis-compare */ break; } if (jiffies >= (time + 20)) { - ret_val = 14; /* error code for time out error */ + ret_val = 14; /* error code for time out error */ break; } } diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index 84850f7a23e4..a6f903a9b773 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -402,13 +402,13 @@ struct e1000_phy_stats { struct e1000_host_mng_dhcp_cookie { u32 signature; - u8 status; - u8 reserved0; + u8 status; + u8 reserved0; u16 vlan_id; u32 reserved1; u16 reserved2; - u8 reserved3; - u8 checksum; + u8 reserved3; + u8 checksum; }; /* Host Interface "Rev 1" */ @@ -427,8 +427,8 @@ struct e1000_host_command_info { /* Host Interface "Rev 2" */ struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; + u8 command_id; + u8 checksum; u16 reserved1; u16 reserved2; u16 command_length; @@ -549,7 +549,7 @@ struct e1000_mac_info { u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; - u8 forced_speed_duplex; + u8 forced_speed_duplex; bool adaptive_ifs; bool has_fwsm; @@ -577,7 +577,7 @@ struct e1000_phy_info { u32 addr; u32 id; - u32 reset_delay_us; /* in usec */ + u32 reset_delay_us; /* in usec */ u32 revision; enum e1000_media_type media_type; @@ -636,11 +636,11 @@ struct e1000_dev_spec_82571 { }; struct e1000_dev_spec_80003es2lan { - bool mdic_wa_enable; + bool mdic_wa_enable; }; struct e1000_shadow_ram { - u16 value; + u16 value; bool modified; }; @@ -660,17 +660,17 @@ struct e1000_hw { void __iomem *hw_addr; void __iomem *flash_address; - struct e1000_mac_info mac; - struct e1000_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; + struct e1000_mac_info mac; + struct e1000_fc_info fc; + struct e1000_phy_info phy; + struct e1000_nvm_info nvm; + struct e1000_bus_info bus; struct e1000_host_mng_dhcp_cookie mng_cookie; union { - struct e1000_dev_spec_82571 e82571; + struct e1000_dev_spec_82571 e82571; struct e1000_dev_spec_80003es2lan e80003es2lan; - struct e1000_dev_spec_ich8lan ich8lan; + struct e1000_dev_spec_ich8lan ich8lan; } dev_spec; }; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index ad9d8f2dd868..9dde390f7e71 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -101,12 +101,12 @@ union ich8_hws_flash_regacc { /* ICH Flash Protected Region */ union ich8_flash_protected_range { struct ich8_pr { - u32 base:13; /* 0:12 Protected Range Base */ - u32 reserved1:2; /* 13:14 Reserved */ - u32 rpe:1; /* 15 Read Protection Enable */ - u32 limit:13; /* 16:28 Protected Range Limit */ - u32 reserved2:2; /* 29:30 Reserved */ - u32 wpe:1; /* 31 Write Protection Enable */ + u32 base:13; /* 0:12 Protected Range Base */ + u32 reserved1:2; /* 13:14 Reserved */ + u32 rpe:1; /* 15 Read Protection Enable */ + u32 limit:13; /* 16:28 Protected Range Limit */ + u32 reserved2:2; /* 29:30 Reserved */ + u32 wpe:1; /* 31 Write Protection Enable */ } range; u32 regval; }; @@ -362,21 +362,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) struct e1000_phy_info *phy = &hw->phy; s32 ret_val; - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.set_page = e1000_set_page_igp; - phy->ops.read_reg = e1000_read_phy_reg_hv; - phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; - phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; - phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.write_reg = e1000_write_phy_reg_hv; - phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; - phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; + phy->addr = 1; + phy->reset_delay_us = 100; + + phy->ops.set_page = e1000_set_page_igp; + phy->ops.read_reg = e1000_read_phy_reg_hv; + phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; + phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; + phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; + phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; + phy->ops.write_reg = e1000_write_phy_reg_hv; + phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; + phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->id = e1000_phy_unknown; @@ -445,11 +445,11 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) s32 ret_val; u16 i = 0; - phy->addr = 1; - phy->reset_delay_us = 100; + phy->addr = 1; + phy->reset_delay_us = 100; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; /* We may need to do this twice - once for IGP and if that fails, * we'll set BM func pointers and try again @@ -457,7 +457,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) ret_val = e1000e_determine_phy_address(hw); if (ret_val) { phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.read_reg = e1000e_read_phy_reg_bm; + phy->ops.read_reg = e1000e_read_phy_reg_bm; ret_val = e1000e_determine_phy_address(hw); if (ret_val) { e_dbg("Cannot determine PHY addr. Erroring out\n"); @@ -560,7 +560,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) /* Clear shadow ram */ for (i = 0; i < nvm->word_size; i++) { dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; + dev_spec->shadow_ram[i].value = 0xFFFF; } return 0; @@ -1012,7 +1012,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) hw->dev_spec.ich8lan.eee_lp_ability = 0; if (!link) - return 0; /* No link detected */ + return 0; /* No link detected */ mac->get_link_status = false; @@ -2816,7 +2816,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, s32 ret_val = -E1000_ERR_NVM; u8 count = 0; - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) + if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) return -E1000_ERR_NVM; flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + @@ -2939,7 +2939,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) * write to bank 0 etc. We also need to erase the segment that * is going to be written */ - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); + ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); if (ret_val) { e_dbg("Could not detect valid bank, assuming bank 0\n"); bank = 0; @@ -4073,7 +4073,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) { u32 reg; u16 data; - u8 retry = 0; + u8 retry = 0; if (hw->phy.type != e1000_phy_igp_3) return; diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a27e3bcc3249..ad5f43476924 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -1196,7 +1196,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && (count < tx_ring->count)) { bool cleaned = false; - rmb(); /* read buffer_info after eop_desc */ + rmb(); /* read buffer_info after eop_desc */ for (; !cleaned; count++) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; @@ -1385,7 +1385,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, skb_put(skb, l1); goto copydone; - } /* if */ + } /* if */ } for (j = 0; j < PS_PAGE_BUFFERS; j++) { @@ -1800,7 +1800,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data) u32 rctl, icr = er32(ICR); if (!icr || test_bit(__E1000_DOWN, &adapter->state)) - return IRQ_NONE; /* Not our interrupt */ + return IRQ_NONE; /* Not our interrupt */ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is * not set, then the adapter didn't send an interrupt @@ -2487,7 +2487,7 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes) else if ((packets < 5) && (bytes > 512)) retval = low_latency; break; - case low_latency: /* 50 usec aka 20000 ints/s */ + case low_latency: /* 50 usec aka 20000 ints/s */ if (bytes > 10000) { /* this if handles the TSO accounting */ if (bytes / packets > 8000) @@ -2502,7 +2502,7 @@ static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes) retval = lowest_latency; } break; - case bulk_latency: /* 250 usec aka 4000 ints/s */ + case bulk_latency: /* 250 usec aka 4000 ints/s */ if (bytes > 25000) { if (packets > 35) retval = low_latency; @@ -2554,7 +2554,7 @@ static void e1000_set_itr(struct e1000_adapter *adapter) new_itr = 70000; break; case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ + new_itr = 20000; /* aka hwitr = ~200 */ break; case bulk_latency: new_itr = 4000; @@ -3104,13 +3104,13 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) /* UPE and MPE will be handled by normal PROMISC logic * in e1000e_set_rx_mode */ - rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ - E1000_RCTL_BAM | /* RX All Bcast Pkts */ - E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ + rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ + E1000_RCTL_BAM | /* RX All Bcast Pkts */ + E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ - rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ - E1000_RCTL_DPF | /* Allow filtered pause */ - E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ + rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ + E1000_RCTL_DPF | /* Allow filtered pause */ + E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ /* Do not mess with E1000_CTRL_VME, it affects transmit as well, * and that breaks VLANs. */ @@ -3799,7 +3799,7 @@ void e1000e_reset(struct e1000_adapter *adapter) hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - adapter->max_frame_size)); - fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ + fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ fc->low_water = fc->high_water - 8; break; case e1000_pchlan: @@ -3808,10 +3808,10 @@ void e1000e_reset(struct e1000_adapter *adapter) */ if (adapter->netdev->mtu > ETH_DATA_LEN) { fc->high_water = 0x3500; - fc->low_water = 0x1500; + fc->low_water = 0x1500; } else { fc->high_water = 0x5000; - fc->low_water = 0x3000; + fc->low_water = 0x3000; } fc->refresh_time = 0x1000; break; @@ -4581,7 +4581,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.crcerrs += er32(CRCERRS); adapter->stats.gprc += er32(GPRC); adapter->stats.gorc += er32(GORCL); - er32(GORCH); /* Clear gorc */ + er32(GORCH); /* Clear gorc */ adapter->stats.bprc += er32(BPRC); adapter->stats.mprc += er32(MPRC); adapter->stats.roc += er32(ROC); @@ -4614,7 +4614,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) adapter->stats.xofftxc += er32(XOFFTXC); adapter->stats.gptc += er32(GPTC); adapter->stats.gotc += er32(GOTCL); - er32(GOTCH); /* Clear gotc */ + er32(GOTCH); /* Clear gotc */ adapter->stats.rnbc += er32(RNBC); adapter->stats.ruc += er32(RUC); @@ -5106,13 +5106,13 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb) context_desc = E1000_CONTEXT_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); + context_desc->lower_setup.ip_fields.ipcss = ipcss; + context_desc->lower_setup.ip_fields.ipcso = ipcso; + context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); context_desc->upper_setup.tcp_fields.tucss = tucss; context_desc->upper_setup.tcp_fields.tucso = tucso; context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); + context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; context_desc->cmd_and_length = cpu_to_le32(cmd_length); @@ -5363,7 +5363,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb) { - struct e1000_hw *hw = &adapter->hw; + struct e1000_hw *hw = &adapter->hw; u16 length, offset; if (vlan_tx_tag_present(skb) && @@ -6259,7 +6259,7 @@ static void e1000_netpoll(struct net_device *netdev) e1000_intr_msi(adapter->pdev->irq, netdev); enable_irq(adapter->pdev->irq); break; - default: /* E1000E_INT_MODE_LEGACY */ + default: /* E1000E_INT_MODE_LEGACY */ disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev); enable_irq(adapter->pdev->irq); @@ -6589,9 +6589,9 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; /* construct the net_device struct */ - netdev->netdev_ops = &e1000e_netdev_ops; + netdev->netdev_ops = &e1000e_netdev_ops; e1000e_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; + netdev->watchdog_timeo = 5 * HZ; netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64); strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); @@ -7034,7 +7034,6 @@ static void __exit e1000_exit_module(void) } module_exit(e1000_exit_module); - MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/intel/e1000e/nvm.c b/drivers/net/ethernet/intel/e1000e/nvm.c index 44ddc0a0ee0e..d70a03906ac0 100644 --- a/drivers/net/ethernet/intel/e1000e/nvm.c +++ b/drivers/net/ethernet/intel/e1000e/nvm.c @@ -117,7 +117,6 @@ static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) u16 data; eecd = er32(EECD); - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); data = 0; diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 59c76a6815a0..da2be59505c0 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -1583,13 +1583,13 @@ s32 e1000e_check_downshift(struct e1000_hw *hw) case e1000_phy_gg82563: case e1000_phy_bm: case e1000_phy_82578: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; + offset = M88E1000_PHY_SPEC_STATUS; + mask = M88E1000_PSSR_DOWNSHIFT; break; case e1000_phy_igp_2: case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; + offset = IGP01E1000_PHY_LINK_HEALTH; + mask = IGP01E1000_PLHR_SS_DOWNGRADE; break; default: /* speed downshift not supported */ @@ -1653,14 +1653,14 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw) if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; + offset = IGP01E1000_PHY_PCS_INIT_REG; + mask = IGP01E1000_PHY_POLARITY_MASK; } else { /* This really only applies to 10Mbps since * there is no polarity for 100Mbps (always 0). */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; + offset = IGP01E1000_PHY_PORT_STATUS; + mask = IGP01E1000_PSSR_POLARITY_REVERSED; } ret_val = e1e_rphy(hw, offset, &data); @@ -1900,7 +1900,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; + s32 ret_val; u16 phy_data; bool link; @@ -2253,7 +2253,7 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) case M88E1011_I_PHY_ID: phy_type = e1000_phy_m88; break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ + case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ phy_type = e1000_phy_igp_2; break; case GG82563_E_PHY_ID: @@ -2317,7 +2317,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw) /* If phy_type is valid, break - we found our * PHY address */ - if (phy_type != e1000_phy_unknown) + if (phy_type != e1000_phy_unknown) return 0; usleep_range(1000, 2000); -- GitLab From 603cdca9805e4f8001cf7ffbd8c539c9fa6674ce Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 1 May 2013 03:48:11 +0000 Subject: [PATCH 0142/2900] e1000e: prevent warning from -Wunused-parameter Signed-off-by: Bruce Allan Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index ad5f43476924..77f81cbb601a 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2673,7 +2673,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight) } static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid) + __always_unused __be16 proto, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -2699,7 +2699,7 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev, } static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid) + __always_unused __be16 proto, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; -- GitLab From 6c1d8b96d09ed8852f5bc11c42374be3232374ce Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Thu, 2 May 2013 02:57:44 +0000 Subject: [PATCH 0143/2900] e1000e: Release mutex lock only if it has been initially acquired This patch fixes the issue of unlocking swflag_mutex for 82574 and 82583 devices regardless of if the hw semaphore has been successfully acquired via e1000_get_hw_semaphore_82574(). With this patch, unlocking mutex now depends on if the hw semaphore was successfully acquired before. And 82574/82583 devices are reset regardless of whether e1000_get_hw_semaphore_82574() returns success or failure. Reported-by: Alexey Khoroshilov Signed-off-by: Akeem G Abodunrin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/82571.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index bef2f103ab03..4c303e2a7cb3 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1003,8 +1003,6 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) default: break; } - if (ret_val) - e_dbg("Cannot acquire MDIO ownership\n"); ctrl = er32(CTRL); @@ -1015,7 +1013,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) switch (hw->mac.type) { case e1000_82574: case e1000_82583: - e1000_put_hw_semaphore_82574(hw); + /* Release mutex only if the hw semaphore is acquired */ + if (!ret_val) + e1000_put_hw_semaphore_82574(hw); break; default: break; -- GitLab From cf7ed221714c36848b257311b316452e274f7e15 Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Fri, 29 Mar 2013 08:22:25 +0000 Subject: [PATCH 0144/2900] igb: Changed LEDs blink mechanism to include designs using cathode This patch addresses the changes needed to make LEDs work properly with negative logic. This implementation uses LED Invert bit to reverse the logic issue that occurred when LEDs are driven by cathode. Keep LEDs blinking for SerDes devices. Also made changes to magic number and the for loop to reduce number of shifts. Signed-off-by: Akeem G Abodunrin Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- .../net/ethernet/intel/igb/e1000_defines.h | 6 ++- drivers/net/ethernet/intel/igb/e1000_mac.c | 37 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index 31a0f82cc650..aa176490ddbc 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -270,8 +270,10 @@ #define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX /* LED Control */ -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_IVRT 0x00000040 #define E1000_LEDCTL_MODE_LED_ON 0xE #define E1000_LEDCTL_MODE_LED_OFF 0xF diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 2559d70a2321..660b7addfbb0 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -1406,15 +1406,34 @@ s32 igb_blink_led(struct e1000_hw *hw) u32 ledctl_blink = 0; u32 i; - /* set the blink bit for each LED that's "on" (0x0E) - * in ledctl_mode2 - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << - (i * 8)); + if (hw->phy.media_type == e1000_media_type_fiber) { + /* always blink LED0 for PCI-E fiber */ + ledctl_blink = E1000_LEDCTL_LED0_BLINK | + (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); + } else { + /* Set the blink bit for each LED that's "on" (0x0E) + * (or "off" if inverted) in ledctl_mode2. The blink + * logic in hardware only works when mode is set to "on" + * so it must be changed accordingly when the mode is + * "off" and inverted. + */ + ledctl_blink = hw->mac.ledctl_mode2; + for (i = 0; i < 32; i += 8) { + u32 mode = (hw->mac.ledctl_mode2 >> i) & + E1000_LEDCTL_LED0_MODE_MASK; + u32 led_default = hw->mac.ledctl_default >> i; + + if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && + (mode == E1000_LEDCTL_MODE_LED_ON)) || + ((led_default & E1000_LEDCTL_LED0_IVRT) && + (mode == E1000_LEDCTL_MODE_LED_OFF))) { + ledctl_blink &= + ~(E1000_LEDCTL_LED0_MODE_MASK << i); + ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_MODE_LED_ON) << i; + } + } + } wr32(E1000_LEDCTL, ledctl_blink); -- GitLab From 20a48412281732ddb75e0ac7d9e0b5406f1b6669 Mon Sep 17 00:00:00 2001 From: Matthew Vick Date: Wed, 24 Apr 2013 07:42:06 +0000 Subject: [PATCH 0145/2900] igb: Add update to last_rx_timestamp in Rx rings In order to support a more accurate check for a PTP Rx hang where the device can no longer timestamp received packets, we need to update, per ring, when the last Rx timestamp was. Because of how the PTP Rx hang logic works, the current logic is valid, but properly updating the ring variable increases the accuracy of the check. Signed-off-by: Matthew Vick Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb.h | 9 +++++++-- drivers/net/ethernet/intel/igb/igb_main.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 9d6c075e232d..a90570755ddc 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -514,13 +514,18 @@ extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va, struct sk_buff *skb); -static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector, +static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring, union e1000_adv_rx_desc *rx_desc, struct sk_buff *skb) { if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) && !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) - igb_ptp_rx_rgtstamp(q_vector, skb); + igb_ptp_rx_rgtstamp(rx_ring->q_vector, skb); + + /* Update the last_rx_timestamp timer in order to enable watchdog check + * for error case of latched timestamp on a dropped packet. + */ + rx_ring->last_rx_timestamp = jiffies; } extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 64cbe0dfe043..2c8f7e04b02b 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -6622,7 +6622,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring, igb_rx_checksum(rx_ring, rx_desc, skb); - igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb); + igb_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) { -- GitLab From 641ac5c0cd46919dc9be4c933f95edae1e4e4163 Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Wed, 24 Apr 2013 16:54:50 +0000 Subject: [PATCH 0146/2900] igb: Support for SFP modules discovery This patch adds support for SFP modules media type discovery for SGMII, which will enable driver to detect supported external PHYs, including 100baseFXSFP module. Signed-off-by: Akeem G Abodunrin Signed-off-by: Carolyn Wyborny Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/e1000_82575.c | 120 ++++++++++++++++- .../net/ethernet/intel/igb/e1000_defines.h | 30 +++-- drivers/net/ethernet/intel/igb/e1000_hw.h | 2 + drivers/net/ethernet/intel/igb/e1000_phy.c | 124 ++++++++++++++++++ drivers/net/ethernet/intel/igb/e1000_phy.h | 20 +++ drivers/net/ethernet/intel/igb/igb_ethtool.c | 34 ++--- 6 files changed, 291 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index ff6a17cb1362..f21a91a299a2 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -401,12 +401,82 @@ static s32 igb_init_mac_params_82575(struct e1000_hw *hw) return 0; } +/** + * igb_set_sfp_media_type_82575 - derives SFP module media type. + * @hw: pointer to the HW structure + * + * The media type is chosen based on SFP module. + * compatibility flags retrieved from SFP ID EEPROM. + **/ +static s32 igb_set_sfp_media_type_82575(struct e1000_hw *hw) +{ + s32 ret_val = E1000_ERR_CONFIG; + u32 ctrl_ext = 0; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; + struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags; + u8 tranceiver_type = 0; + s32 timeout = 3; + + /* Turn I2C interface ON and power on sfp cage */ + ctrl_ext = rd32(E1000_CTRL_EXT); + ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; + wr32(E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); + + wrfl(); + + /* Read SFP module data */ + while (timeout) { + ret_val = igb_read_sfp_data_byte(hw, + E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), + &tranceiver_type); + if (ret_val == 0) + break; + msleep(100); + timeout--; + } + if (ret_val != 0) + goto out; + + ret_val = igb_read_sfp_data_byte(hw, + E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), + (u8 *)eth_flags); + if (ret_val != 0) + goto out; + + /* Check if there is some SFP module plugged and powered */ + if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || + (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { + dev_spec->module_plugged = true; + if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { + hw->phy.media_type = e1000_media_type_internal_serdes; + } else if (eth_flags->e100_base_fx) { + dev_spec->sgmii_active = true; + hw->phy.media_type = e1000_media_type_internal_serdes; + } else if (eth_flags->e1000_base_t) { + dev_spec->sgmii_active = true; + hw->phy.media_type = e1000_media_type_copper; + } else { + hw->phy.media_type = e1000_media_type_unknown; + hw_dbg("PHY module has not been recognized\n"); + goto out; + } + } else { + hw->phy.media_type = e1000_media_type_unknown; + } + ret_val = 0; +out: + /* Restore I2C interface setting */ + wr32(E1000_CTRL_EXT, ctrl_ext); + return ret_val; +} + static s32 igb_get_invariants_82575(struct e1000_hw *hw) { struct e1000_mac_info *mac = &hw->mac; struct e1000_dev_spec_82575 * dev_spec = &hw->dev_spec._82575; s32 ret_val; u32 ctrl_ext = 0; + u32 link_mode = 0; switch (hw->device_id) { case E1000_DEV_ID_82575EB_COPPER: @@ -470,15 +540,55 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) */ hw->phy.media_type = e1000_media_type_copper; dev_spec->sgmii_active = false; + dev_spec->module_plugged = false; ctrl_ext = rd32(E1000_CTRL_EXT); - switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { - case E1000_CTRL_EXT_LINK_MODE_SGMII: - dev_spec->sgmii_active = true; - break; + + link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; + switch (link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: - case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; + break; + case E1000_CTRL_EXT_LINK_MODE_SGMII: + /* Get phy control interface type set (MDIO vs. I2C)*/ + if (igb_sgmii_uses_mdio_82575(hw)) { + hw->phy.media_type = e1000_media_type_copper; + dev_spec->sgmii_active = true; + break; + } + /* fall through for I2C based SGMII */ + case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: + /* read media type from SFP EEPROM */ + ret_val = igb_set_sfp_media_type_82575(hw); + if ((ret_val != 0) || + (hw->phy.media_type == e1000_media_type_unknown)) { + /* If media type was not identified then return media + * type defined by the CTRL_EXT settings. + */ + hw->phy.media_type = e1000_media_type_internal_serdes; + + if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { + hw->phy.media_type = e1000_media_type_copper; + dev_spec->sgmii_active = true; + } + + break; + } + + /* do not change link mode for 100BaseFX */ + if (dev_spec->eth_flags.e100_base_fx) + break; + + /* change current link mode setting */ + ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; + + if (hw->phy.media_type == e1000_media_type_copper) + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; + else + ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; + + wr32(E1000_CTRL_EXT, ctrl_ext); + break; default: break; diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h index aa176490ddbc..aa201abb8ad2 100644 --- a/drivers/net/ethernet/intel/igb/e1000_defines.h +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h @@ -61,20 +61,22 @@ /* Clear Interrupt timers after IMS clear */ /* packet buffer parity error detection enabled */ /* descriptor FIFO parity error detection enable */ -#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ -#define E1000_I2CCMD_REG_ADDR_SHIFT 16 -#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 -#define E1000_I2CCMD_OPCODE_READ 0x08000000 -#define E1000_I2CCMD_OPCODE_WRITE 0x00000000 -#define E1000_I2CCMD_READY 0x20000000 -#define E1000_I2CCMD_ERROR 0x80000000 -#define E1000_MAX_SGMII_PHY_REG_ADDR 255 -#define E1000_I2CCMD_PHY_TIMEOUT 200 -#define E1000_IVAR_VALID 0x80 -#define E1000_GPIE_NSICR 0x00000001 -#define E1000_GPIE_MSIX_MODE 0x00000010 -#define E1000_GPIE_EIAME 0x40000000 -#define E1000_GPIE_PBA 0x80000000 +#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ +#define E1000_I2CCMD_REG_ADDR_SHIFT 16 +#define E1000_I2CCMD_PHY_ADDR_SHIFT 24 +#define E1000_I2CCMD_OPCODE_READ 0x08000000 +#define E1000_I2CCMD_OPCODE_WRITE 0x00000000 +#define E1000_I2CCMD_READY 0x20000000 +#define E1000_I2CCMD_ERROR 0x80000000 +#define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a)) +#define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a)) +#define E1000_MAX_SGMII_PHY_REG_ADDR 255 +#define E1000_I2CCMD_PHY_TIMEOUT 200 +#define E1000_IVAR_VALID 0x80 +#define E1000_GPIE_NSICR 0x00000001 +#define E1000_GPIE_MSIX_MODE 0x00000010 +#define E1000_GPIE_EIAME 0x40000000 +#define E1000_GPIE_PBA 0x80000000 /* Receive Descriptor bit definitions */ #define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 488abb24a54f..94d7866b9c20 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -528,6 +528,8 @@ struct e1000_dev_spec_82575 { bool global_device_reset; bool eee_disable; bool clear_semaphore_once; + struct e1000_sfp_flags eth_flags; + bool module_plugged; }; struct e1000_hw { diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c index 115b0da6e013..1d6a401cc5d4 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.c +++ b/drivers/net/ethernet/intel/igb/e1000_phy.c @@ -340,6 +340,130 @@ s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) return 0; } +/** + * igb_read_sfp_data_byte - Reads SFP module data. + * @hw: pointer to the HW structure + * @offset: byte location offset to be read + * @data: read data buffer pointer + * + * Reads one byte from SFP module data stored + * in SFP resided EEPROM memory or SFP diagnostic area. + * Function should be called with + * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access + * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters + * access + **/ +s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data) +{ + u32 i = 0; + u32 i2ccmd = 0; + u32 data_local = 0; + + if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { + hw_dbg("I2CCMD command address exceeds upper limit\n"); + return -E1000_ERR_PHY; + } + + /* Set up Op-code, EEPROM Address,in the I2CCMD + * register. The MAC will take care of interfacing with the + * EEPROM to retrieve the desired data. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | + E1000_I2CCMD_OPCODE_READ); + + wr32(E1000_I2CCMD, i2ccmd); + + /* Poll the ready bit to see if the I2C read completed */ + for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { + udelay(50); + data_local = rd32(E1000_I2CCMD); + if (data_local & E1000_I2CCMD_READY) + break; + } + if (!(data_local & E1000_I2CCMD_READY)) { + hw_dbg("I2CCMD Read did not complete\n"); + return -E1000_ERR_PHY; + } + if (data_local & E1000_I2CCMD_ERROR) { + hw_dbg("I2CCMD Error bit set\n"); + return -E1000_ERR_PHY; + } + *data = (u8) data_local & 0xFF; + + return 0; +} + +/** + * e1000_write_sfp_data_byte - Writes SFP module data. + * @hw: pointer to the HW structure + * @offset: byte location offset to write to + * @data: data to write + * + * Writes one byte to SFP module data stored + * in SFP resided EEPROM memory or SFP diagnostic area. + * Function should be called with + * E1000_I2CCMD_SFP_DATA_ADDR() for SFP module database access + * E1000_I2CCMD_SFP_DIAG_ADDR() for SFP diagnostics parameters + * access + **/ +s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data) +{ + u32 i = 0; + u32 i2ccmd = 0; + u32 data_local = 0; + + if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) { + hw_dbg("I2CCMD command address exceeds upper limit\n"); + return -E1000_ERR_PHY; + } + /* The programming interface is 16 bits wide + * so we need to read the whole word first + * then update appropriate byte lane and write + * the updated word back. + */ + /* Set up Op-code, EEPROM Address,in the I2CCMD + * register. The MAC will take care of interfacing + * with an EEPROM to write the data given. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | + E1000_I2CCMD_OPCODE_READ); + /* Set a command to read single word */ + wr32(E1000_I2CCMD, i2ccmd); + for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { + udelay(50); + /* Poll the ready bit to see if lastly + * launched I2C operation completed + */ + i2ccmd = rd32(E1000_I2CCMD); + if (i2ccmd & E1000_I2CCMD_READY) { + /* Check if this is READ or WRITE phase */ + if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) == + E1000_I2CCMD_OPCODE_READ) { + /* Write the selected byte + * lane and update whole word + */ + data_local = i2ccmd & 0xFF00; + data_local |= data; + i2ccmd = ((offset << + E1000_I2CCMD_REG_ADDR_SHIFT) | + E1000_I2CCMD_OPCODE_WRITE | data_local); + wr32(E1000_I2CCMD, i2ccmd); + } else { + break; + } + } + } + if (!(i2ccmd & E1000_I2CCMD_READY)) { + hw_dbg("I2CCMD Write did not complete\n"); + return -E1000_ERR_PHY; + } + if (i2ccmd & E1000_I2CCMD_ERROR) { + hw_dbg("I2CCMD Error bit set\n"); + return -E1000_ERR_PHY; + } + return 0; +} + /** * igb_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h index 784fd1c40989..6a0873f2095a 100644 --- a/drivers/net/ethernet/intel/igb/e1000_phy.h +++ b/drivers/net/ethernet/intel/igb/e1000_phy.h @@ -69,6 +69,8 @@ s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); +s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data); +s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data); s32 igb_copper_link_setup_82580(struct e1000_hw *hw); s32 igb_get_phy_info_82580(struct e1000_hw *hw); s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw); @@ -157,4 +159,22 @@ s32 igb_check_polarity_m88(struct e1000_hw *hw); #define GS40G_CS_POWER_DOWN 0x0002 #define GS40G_LINE_LB 0x4000 +/* SFP modules ID memory locations */ +#define E1000_SFF_IDENTIFIER_OFFSET 0x00 +#define E1000_SFF_IDENTIFIER_SFF 0x02 +#define E1000_SFF_IDENTIFIER_SFP 0x03 + +#define E1000_SFF_ETH_FLAGS_OFFSET 0x06 +/* Flags for SFP modules compatible with ETH up to 1Gb */ +struct e1000_sfp_flags { + u8 e1000_base_sx:1; + u8 e1000_base_lx:1; + u8 e1000_base_cx:1; + u8 e1000_base_t:1; + u8 e100_base_lx:1; + u8 e100_base_fx:1; + u8 e10_base_bx10:1; + u8 e10_base_px:1; +}; + #endif diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 7876240fa74e..4e54f847ac92 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -142,6 +142,8 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; + struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; + struct e1000_sfp_flags *eth_flags = &dev_spec->eth_flags; u32 status; if (hw->phy.media_type == e1000_media_type_copper) { @@ -181,30 +183,22 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->phy_address = hw->phy.addr; ecmd->transceiver = XCVR_INTERNAL; } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full | - SUPPORTED_FIBRE | + ecmd->supported = (SUPPORTED_FIBRE | SUPPORTED_Autoneg | SUPPORTED_Pause); - if (hw->mac.type == e1000_i354) - ecmd->supported |= SUPPORTED_2500baseX_Full; - ecmd->advertising = ADVERTISED_FIBRE; - - switch (adapter->link_speed) { - case SPEED_2500: - ecmd->advertising = ADVERTISED_2500baseX_Full; - break; - case SPEED_1000: - ecmd->advertising = ADVERTISED_1000baseT_Full; - break; - case SPEED_100: - ecmd->advertising = ADVERTISED_100baseT_Full; - break; - default: - break; + if (hw->mac.type == e1000_i354) { + ecmd->supported |= SUPPORTED_2500baseX_Full; + ecmd->advertising |= ADVERTISED_2500baseX_Full; + } + if ((eth_flags->e1000_base_lx) || (eth_flags->e1000_base_sx)) { + ecmd->supported |= SUPPORTED_1000baseT_Full; + ecmd->advertising |= ADVERTISED_1000baseT_Full; + } + if (eth_flags->e100_base_fx) { + ecmd->supported |= SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_100baseT_Full; } - if (hw->mac.autoneg == 1) ecmd->advertising |= ADVERTISED_Autoneg; -- GitLab From 373e6978f9c5c05af3b3ec4cd0295b0bfbe11644 Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Fri, 29 Mar 2013 15:22:17 +0000 Subject: [PATCH 0147/2900] igb: SerDes flow control setting This path allows users to get appropriate flow control setting on SerDes devices, based on original implementation for Copper devices. Also, since 100baseFX does not support setting flow control, so exclude it from the setting mechanism. Signed-off-by: Akeem G. Abodunrin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 34 +++++++++++--------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 4e54f847ac92..7b25ee2e81c0 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -164,21 +164,6 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->advertising |= hw->phy.autoneg_advertised; } - if (hw->mac.autoneg != 1) - ecmd->advertising &= ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - - if (hw->fc.requested_mode == e1000_fc_full) - ecmd->advertising |= ADVERTISED_Pause; - else if (hw->fc.requested_mode == e1000_fc_rx_pause) - ecmd->advertising |= (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - else if (hw->fc.requested_mode == e1000_fc_tx_pause) - ecmd->advertising |= ADVERTISED_Asym_Pause; - else - ecmd->advertising &= ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - ecmd->port = PORT_TP; ecmd->phy_address = hw->phy.addr; ecmd->transceiver = XCVR_INTERNAL; @@ -206,6 +191,21 @@ static int igb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->transceiver = XCVR_EXTERNAL; } + if (hw->mac.autoneg != 1) + ecmd->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + + if (hw->fc.requested_mode == e1000_fc_full) + ecmd->advertising |= ADVERTISED_Pause; + else if (hw->fc.requested_mode == e1000_fc_rx_pause) + ecmd->advertising |= (ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + else if (hw->fc.requested_mode == e1000_fc_tx_pause) + ecmd->advertising |= ADVERTISED_Asym_Pause; + else + ecmd->advertising &= ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + status = rd32(E1000_STATUS); if (status & E1000_STATUS_LU) { @@ -386,6 +386,10 @@ static int igb_set_pauseparam(struct net_device *netdev, struct e1000_hw *hw = &adapter->hw; int retval = 0; + /* 100basefx does not support setting link flow control */ + if (hw->dev_spec._82575.eth_flags.e100_base_fx) + return -EINVAL; + adapter->fc_autoneg = pause->autoneg; while (test_and_set_bit(__IGB_RESETTING, &adapter->state)) -- GitLab From 2a0a0f1ea27ac39afd25c741a1ccc53bc5530acf Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 25 Apr 2013 17:22:34 +0000 Subject: [PATCH 0148/2900] igb: Fix set_ethtool function to call update nvm for entire image This patch fixes a problem where we were only checking to update checksum on first part of nvm image. Newer parts have multiple checksum fields and checksum function will accommodate that as long as we call it in the first place for any changes made. Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_ethtool.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 7b25ee2e81c0..85fe7b52f435 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -811,10 +811,8 @@ static int igb_set_eeprom(struct net_device *netdev, ret_val = hw->nvm.ops.write(hw, first_word, last_word - first_word + 1, eeprom_buff); - /* Update the checksum over the first part of the EEPROM if needed - * and flush shadow RAM for 82573 controllers - */ - if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG))) + /* Update the checksum if nvm write succeeded */ + if (ret_val == 0) hw->nvm.ops.update(hw); igb_set_fw_version(adapter); -- GitLab From 41f149a285da21529bc9a0bad323df53b2f17b16 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Tue, 30 Apr 2013 00:21:32 +0000 Subject: [PATCH 0149/2900] igb: Fix possible panic caused by Rx traffic arrival while interface is down This patch reorders disabling napi and irqs during igb_down. This is done to avoid possible panic's found in other Intel drivers when Rx traffic arrives while interface is going down. Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 2c8f7e04b02b..6a0c1b66ce54 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1667,10 +1667,13 @@ void igb_down(struct igb_adapter *adapter) wrfl(); msleep(10); - for (i = 0; i < adapter->num_q_vectors; i++) + igb_irq_disable(adapter); + + for (i = 0; i < adapter->num_q_vectors; i++) { + napi_synchronize(&(adapter->q_vector[i]->napi)); napi_disable(&(adapter->q_vector[i]->napi)); + } - igb_irq_disable(adapter); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); -- GitLab From 6f8b916065596d80843bb7d4f601ef72b3223c54 Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Wed, 1 May 2013 05:44:45 +0000 Subject: [PATCH 0150/2900] igb: Implementation of i210/i211 LED support This patch fixes LED issues with i210 and i211 devices, due to changes in the device registers. Signed-off-by: Akeem G Abodunrin Tested-by: Jeff Pieper Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/e1000_i210.h | 6 +++--- drivers/net/ethernet/intel/igb/e1000_mac.c | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h index bfc08e05c907..5caa332e7556 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.h +++ b/drivers/net/ethernet/intel/igb/e1000_i210.h @@ -82,11 +82,11 @@ enum E1000_INVM_STRUCTURE_TYPE { #define E1000_INVM_MAJOR_SHIFT 4 #define ID_LED_DEFAULT_I210 ((ID_LED_OFF1_ON2 << 8) | \ - (ID_LED_OFF1_OFF2 << 4) | \ - (ID_LED_DEF1_DEF2)) + (ID_LED_DEF1_DEF2 << 4) | \ + (ID_LED_OFF1_OFF2)) #define ID_LED_DEFAULT_I210_SERDES ((ID_LED_DEF1_DEF2 << 8) | \ (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) + (ID_LED_OFF1_ON2)) /* NVM offset defaults for i211 device */ #define NVM_INIT_CTRL_2_DEFAULT_I211 0X7243 diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index 660b7addfbb0..bab556a47fcc 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -1332,7 +1332,13 @@ s32 igb_id_led_init(struct e1000_hw *hw) u16 data, i, temp; const u16 led_mask = 0x0F; - ret_val = igb_valid_led_default(hw, &data); + /* i210 and i211 devices have different LED mechanism */ + if ((hw->mac.type == e1000_i210) || + (hw->mac.type == e1000_i211)) + ret_val = igb_valid_led_default_i210(hw, &data); + else + ret_val = igb_valid_led_default(hw, &data); + if (ret_val) goto out; -- GitLab From f7727c53094bd1122351a14a2087585f46009c04 Mon Sep 17 00:00:00 2001 From: "Akeem G. Abodunrin" Date: Wed, 15 May 2013 07:41:30 +0000 Subject: [PATCH 0151/2900] igb: Removed unused i2c function This patch removes unused i2c function definition. Signed-off-by: Akeem G Abodunrin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index a90570755ddc..15ea8dc9dad3 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -322,11 +322,6 @@ static inline int igb_desc_unused(struct igb_ring *ring) return ring->count + ring->next_to_clean - ring->next_to_use - 1; } -struct igb_i2c_client_list { - struct i2c_client *client; - struct igb_i2c_client_list *next; -}; - #ifdef CONFIG_IGB_HWMON #define IGB_HWMON_TYPE_LOC 0 -- GitLab From e8915bebb4b33c63d6e08161edc3fbda32a840a7 Mon Sep 17 00:00:00 2001 From: Amir Hanania Date: Thu, 18 Apr 2013 04:23:52 +0000 Subject: [PATCH 0152/2900] IXGBE: Set the SW prio_tc values at initialization to the HW setting. Set the SW prio_tc values at initialization to the HW setting. Setting the SW prio_tc default values to be the HW setting by reading the rtrup2tc register. For any TC change we need to reset the device. This will remove the need to reset the device at the first time we call ixgbe_dcbnl_ieee_setets. Signed-off-by: Amir Hanania Tested-by: Jack Morgan Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c | 23 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h | 2 ++ .../ethernet/intel/ixgbe/ixgbe_dcb_82599.h | 1 + .../net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c | 3 +++ 4 files changed, 29 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index 1f2c805684dd..e055e000131b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -380,3 +380,26 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, } return 0; } + +static void ixgbe_dcb_read_rtrup2tc_82599(struct ixgbe_hw *hw, u8 *map) +{ + u32 reg, i; + + reg = IXGBE_READ_REG(hw, IXGBE_RTRUP2TC); + for (i = 0; i < MAX_USER_PRIORITY; i++) + map[i] = IXGBE_RTRUP2TC_UP_MASK & + (reg >> (i * IXGBE_RTRUP2TC_UP_SHIFT)); + return; +} + +void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map) +{ + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + case ixgbe_mac_X540: + ixgbe_dcb_read_rtrup2tc_82599(hw, map); + break; + default: + break; + } +} diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h index 1634de8b627f..fc0a2dd52499 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h @@ -159,6 +159,8 @@ s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, u16 *refill, u16 *max, s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en, u8 *tc_prio); s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *); +void ixgbe_dcb_read_rtrup2tc(struct ixgbe_hw *hw, u8 *map); + /* DCB definitions for credit calculation */ #define DCB_CREDIT_QUANTUM 64 /* DCB Quantum */ #define MAX_CREDIT_REFILL 511 /* 0x1FF * 64B = 32704B */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h index a4ef07631d1e..d71d9ce3e394 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h @@ -45,6 +45,7 @@ /* Receive UP2TC mapping */ #define IXGBE_RTRUP2TC_UP_SHIFT 3 +#define IXGBE_RTRUP2TC_UP_MASK 7 /* Transmit UP2TC mapping */ #define IXGBE_RTTUP2TC_UP_SHIFT 3 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index f3d68f9696ba..edd89a1ef27f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -554,6 +554,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) adapter->ixgbe_ieee_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS; + /* if possible update UP2TC mappings from HW */ + ixgbe_dcb_read_rtrup2tc(&adapter->hw, + adapter->ixgbe_ieee_ets->prio_tc); } for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { -- GitLab From bbcc9fa0afe4f8a36e8777e14f7b016090605306 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 18 Apr 2013 18:35:39 -0300 Subject: [PATCH 0153/2900] [media] mt9p031: Power down the sensor if no supported device has been detected The mt9p031 driver first accesses the I2C device in its .registered() method. While doing that it first powers the device up, but if probing fails, it doesn't power the chip back down. This patch fixes that bug. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9p031.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 28cf95b37285..8de84c0a48dc 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -849,18 +849,18 @@ static int mt9p031_registered(struct v4l2_subdev *subdev) /* Read out the chip version register */ data = mt9p031_read(client, MT9P031_CHIP_VERSION); + mt9p031_power_off(mt9p031); + if (data != MT9P031_CHIP_VERSION_VALUE) { dev_err(&client->dev, "MT9P031 not detected, wrong version " "0x%04x\n", data); return -ENODEV; } - mt9p031_power_off(mt9p031); - dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n", client->addr); - return ret; + return 0; } static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) -- GitLab From 2660a22b55ae9a01c1e1117e9d514427834704bc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 07:57:51 -0300 Subject: [PATCH 0154/2900] [media] mt9p031: Use gpio_is_valid() Replace the manual validity checks for the reset GPIO with the gpio_is_valid() function. Signed-off-by: Laurent Pinchart Reviewed-by: Sylwester Nawrocki Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9p031.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 8de84c0a48dc..bf49899945f8 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -272,7 +272,7 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) static int mt9p031_power_on(struct mt9p031 *mt9p031) { /* Ensure RESET_BAR is low */ - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 0); usleep_range(1000, 2000); } @@ -287,7 +287,7 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031) clk_prepare_enable(mt9p031->clk); /* Now RESET_BAR must be high */ - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 1); usleep_range(1000, 2000); } @@ -297,7 +297,7 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031) static void mt9p031_power_off(struct mt9p031 *mt9p031) { - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 0); usleep_range(1000, 2000); } @@ -1031,7 +1031,7 @@ static int mt9p031_probe(struct i2c_client *client, mt9p031->format.field = V4L2_FIELD_NONE; mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; - if (pdata->reset != -1) { + if (gpio_is_valid(pdata->reset)) { ret = devm_gpio_request_one(&client->dev, pdata->reset, GPIOF_OUT_INIT_LOW, "mt9p031_rst"); if (ret < 0) -- GitLab From 9462550f66dfbbb2eb0961af2c9d2c3e000d9239 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:34:30 -0300 Subject: [PATCH 0155/2900] [media] mt9v032: Free control handler in cleanup paths The control handler must be freed in the probe error path and in the remove handler. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v032.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 3f356cb28256..24ea6fd3ee81 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -830,8 +830,11 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); - if (ret < 0) + + if (ret < 0) { + v4l2_ctrl_handler_free(&mt9v032->ctrls); kfree(mt9v032); + } return ret; } @@ -841,9 +844,11 @@ static int mt9v032_remove(struct i2c_client *client) struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct mt9v032 *mt9v032 = to_mt9v032(subdev); + v4l2_ctrl_handler_free(&mt9v032->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); kfree(mt9v032); + return 0; } -- GitLab From c7e3cc3ca1ff2fe1aeffd2ba642548d79f9a73dc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 10:09:07 -0300 Subject: [PATCH 0156/2900] [media] tvp514x: Fix double free The tvp514x data structure is allocated using devm_kzalloc(). Freeing it explictly would result in a double free. Fix it. Signed-off-by: Laurent Pinchart Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index ab8f3fee7e94..7438e015d879 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1120,7 +1120,6 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret < 0) { v4l2_err(sd, "%s decoder driver failed to register !!\n", sd->name); - kfree(decoder); return ret; } #endif -- GitLab From 95323361e5313733a54771c5059f5b352adbf32c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 11:11:50 -0300 Subject: [PATCH 0157/2900] [media] media: i2c: Convert to gpio_request_one() Replace gpio_request() with gpio_request_one() and remove the associated gpio_direction_output() calls. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7183.c | 14 +++++++------- drivers/media/i2c/m5mols/m5mols_core.c | 6 ++++-- drivers/media/i2c/noon010pc30.c | 8 ++++---- drivers/media/i2c/vs6624.c | 3 +-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 56a1fa4af0fe..2bc032894bae 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -474,9 +474,9 @@ static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) struct adv7183 *decoder = to_adv7183(sd); if (enable) - gpio_direction_output(decoder->oe_pin, 0); + gpio_set_value(decoder->oe_pin, 0); else - gpio_direction_output(decoder->oe_pin, 1); + gpio_set_value(decoder->oe_pin, 1); udelay(1); return 0; } @@ -580,13 +580,15 @@ static int adv7183_probe(struct i2c_client *client, decoder->reset_pin = pin_array[0]; decoder->oe_pin = pin_array[1]; - if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { + if (gpio_request_one(decoder->reset_pin, GPIOF_OUT_INIT_LOW, + "ADV7183 Reset")) { v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); ret = -EBUSY; goto err_free_decoder; } - if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { + if (gpio_request_one(decoder->oe_pin, GPIOF_OUT_INIT_HIGH, + "ADV7183 Output Enable")) { v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); ret = -EBUSY; goto err_free_reset; @@ -619,12 +621,10 @@ static int adv7183_probe(struct i2c_client *client, decoder->input = ADV7183_COMPOSITE4; decoder->output = ADV7183_8BIT_OUT; - gpio_direction_output(decoder->oe_pin, 1); /* reset chip */ - gpio_direction_output(decoder->reset_pin, 0); /* reset pulse width at least 5ms */ mdelay(10); - gpio_direction_output(decoder->reset_pin, 1); + gpio_set_value(decoder->reset_pin, 1); /* wait 5ms before any further i2c writes are performed */ mdelay(5); diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 0b899cb6cda1..f0b870c06376 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -930,6 +930,7 @@ static int m5mols_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct m5mols_platform_data *pdata = client->dev.platform_data; + unsigned long gpio_flags; struct m5mols_info *info; struct v4l2_subdev *sd; int ret; @@ -956,12 +957,13 @@ static int m5mols_probe(struct i2c_client *client, info->pdata = pdata; info->set_power = pdata->set_power; - ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); + gpio_flags = pdata->reset_polarity + ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + ret = gpio_request_one(pdata->gpio_reset, gpio_flags, "M5MOLS_NRST"); if (ret) { dev_err(&client->dev, "Failed to request gpio: %d\n", ret); goto out_free; } - gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); if (ret) { diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 8554b47f993a..a115842ab996 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -746,24 +746,24 @@ static int noon010_probe(struct i2c_client *client, info->curr_win = &noon010_sizes[0]; if (gpio_is_valid(pdata->gpio_nreset)) { - ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST"); + ret = gpio_request_one(pdata->gpio_nreset, GPIOF_OUT_INIT_LOW, + "NOON010PC30 NRST"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); goto np_err; } info->gpio_nreset = pdata->gpio_nreset; - gpio_direction_output(info->gpio_nreset, 0); gpio_export(info->gpio_nreset, 0); } if (gpio_is_valid(pdata->gpio_nstby)) { - ret = gpio_request(pdata->gpio_nstby, "NOON010PC30 NSTBY"); + ret = gpio_request_one(pdata->gpio_nstby, GPIOF_OUT_INIT_LOW, + "NOON010PC30 NSTBY"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); goto np_gpio_err; } info->gpio_nstby = pdata->gpio_nstby; - gpio_direction_output(info->gpio_nstby, 0); gpio_export(info->gpio_nstby, 0); } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index f366fad6269e..6b8c0b7aa488 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -805,12 +805,11 @@ static int vs6624_probe(struct i2c_client *client, if (ce == NULL) return -EINVAL; - ret = gpio_request(*ce, "VS6624 Chip Enable"); + ret = gpio_request_one(*ce, GPIOF_OUT_INIT_HIGH, "VS6624 Chip Enable"); if (ret) { v4l_err(client, "failed to request GPIO %d\n", *ce); return ret; } - gpio_direction_output(*ce, 1); /* wait 100ms before any further i2c writes are performed */ mdelay(100); -- GitLab From c02b211df6fc54e51ee554c27a6736a11255a764 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0158/2900] [media] media: i2c: Convert to devm_kzalloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the managed function the kfree() calls can be removed from the probe error path and the remove handler. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Acked-by: Lad, Prabhakar Acked-by: Andy Shevchenko Reviewed-by: Benoît Thébaudeau Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 8 ++------ drivers/media/i2c/adp1653.c | 5 ++--- drivers/media/i2c/adv7170.c | 3 +-- drivers/media/i2c/adv7175.c | 3 +-- drivers/media/i2c/adv7180.c | 4 +--- drivers/media/i2c/adv7183.c | 8 ++------ drivers/media/i2c/adv7393.c | 8 ++------ drivers/media/i2c/adv7604.c | 11 +++-------- drivers/media/i2c/ak881x.c | 4 +--- drivers/media/i2c/as3645a.c | 7 ++----- drivers/media/i2c/bt819.c | 4 +--- drivers/media/i2c/bt856.c | 3 +-- drivers/media/i2c/bt866.c | 3 +-- drivers/media/i2c/cs5345.c | 4 +--- drivers/media/i2c/cs53l32a.c | 4 +--- drivers/media/i2c/cx25840/cx25840-core.c | 4 +--- drivers/media/i2c/cx25840/cx25840-ir.c | 7 ++----- drivers/media/i2c/ir-kbd-i2c.c | 10 +++------- drivers/media/i2c/ks0127.c | 3 +-- drivers/media/i2c/m52790.c | 3 +-- drivers/media/i2c/m5mols/m5mols_core.c | 8 +++----- drivers/media/i2c/msp3400-driver.c | 5 +---- drivers/media/i2c/mt9m032.c | 4 +--- drivers/media/i2c/mt9t001.c | 4 +--- drivers/media/i2c/mt9v011.c | 6 ++---- drivers/media/i2c/mt9v032.c | 7 ++----- drivers/media/i2c/noon010pc30.c | 5 ++--- drivers/media/i2c/ov7640.c | 5 ++--- drivers/media/i2c/ov7670.c | 5 +---- drivers/media/i2c/saa6588.c | 10 +++------- drivers/media/i2c/saa7110.c | 4 +--- drivers/media/i2c/saa7115.c | 4 +--- drivers/media/i2c/saa7127.c | 4 +--- drivers/media/i2c/saa717x.c | 5 +---- drivers/media/i2c/saa7185.c | 3 +-- drivers/media/i2c/saa7191.c | 4 +--- drivers/media/i2c/sony-btf-mpx.c | 3 +-- drivers/media/i2c/sr030pc30.c | 4 +--- drivers/media/i2c/tda7432.c | 4 +--- drivers/media/i2c/tda9840.c | 3 +-- drivers/media/i2c/tea6415c.c | 3 +-- drivers/media/i2c/tea6420.c | 3 +-- drivers/media/i2c/tlv320aic23b.c | 4 +--- drivers/media/i2c/tvaudio.c | 5 +---- drivers/media/i2c/tvp5150.c | 14 ++++---------- drivers/media/i2c/tw2804.c | 5 +---- drivers/media/i2c/tw9903.c | 5 +---- drivers/media/i2c/tw9906.c | 5 +---- drivers/media/i2c/uda1342.c | 3 +-- drivers/media/i2c/upd64031a.c | 3 +-- drivers/media/i2c/upd64083.c | 3 +-- drivers/media/i2c/vp27smpx.c | 3 +-- drivers/media/i2c/vpx3220.c | 5 ++--- drivers/media/i2c/vs6624.c | 9 ++------- drivers/media/i2c/wm8739.c | 4 +--- drivers/media/i2c/wm8775.c | 4 +--- 56 files changed, 79 insertions(+), 202 deletions(-) diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 58344b6c3a55..15043554cc8b 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -1188,15 +1188,14 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; /* Platform data */ if (pdata == NULL) { v4l_err(client, "No platform data!\n"); - err = -ENODEV; - goto err_free; + return -ENODEV; } memcpy(&state->pdata, pdata, sizeof(state->pdata)); @@ -1276,8 +1275,6 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * media_entity_cleanup(&sd->entity); err_hdl: v4l2_ctrl_handler_free(&state->hdl); -err_free: - kfree(state); return err; } @@ -1302,7 +1299,6 @@ static int ad9389b_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(get_ad9389b_state(sd)); return 0; } diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index ef75abe5984c..873fe1949e98 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -417,7 +417,7 @@ static int adp1653_probe(struct i2c_client *client, if (client->dev.platform_data == NULL) return -ENODEV; - flash = kzalloc(sizeof(*flash), GFP_KERNEL); + flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); if (flash == NULL) return -ENOMEM; @@ -443,7 +443,6 @@ static int adp1653_probe(struct i2c_client *client, free_and_quit: v4l2_ctrl_handler_free(&flash->ctrls); - kfree(flash); return ret; } @@ -455,7 +454,7 @@ static int adp1653_remove(struct i2c_client *client) v4l2_device_unregister_subdev(&flash->subdev); v4l2_ctrl_handler_free(&flash->ctrls); media_entity_cleanup(&flash->subdev.entity); - kfree(flash); + return 0; } diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c index 6bc01fb98ff8..d07689d44354 100644 --- a/drivers/media/i2c/adv7170.c +++ b/drivers/media/i2c/adv7170.c @@ -359,7 +359,7 @@ static int adv7170_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -384,7 +384,6 @@ static int adv7170_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_adv7170(sd)); return 0; } diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c index c7640fab5730..eaefa50b8d28 100644 --- a/drivers/media/i2c/adv7175.c +++ b/drivers/media/i2c/adv7175.c @@ -409,7 +409,7 @@ static int adv7175_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -434,7 +434,6 @@ static int adv7175_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_adv7175(sd)); return 0; } diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index afd561ab190d..3d1456780318 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -555,7 +555,7 @@ static int adv7180_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr, client->adapter->name); - state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) { ret = -ENOMEM; goto err; @@ -582,7 +582,6 @@ static int adv7180_probe(struct i2c_client *client, err_unreg_subdev: mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); - kfree(state); err: printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret); return ret; @@ -607,7 +606,6 @@ static int adv7180_remove(struct i2c_client *client) mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 2bc032894bae..56904174abc3 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -573,7 +573,7 @@ static int adv7183_probe(struct i2c_client *client, if (pin_array == NULL) return -EINVAL; - decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; @@ -583,8 +583,7 @@ static int adv7183_probe(struct i2c_client *client, if (gpio_request_one(decoder->reset_pin, GPIOF_OUT_INIT_LOW, "ADV7183 Reset")) { v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); - ret = -EBUSY; - goto err_free_decoder; + return -EBUSY; } if (gpio_request_one(decoder->oe_pin, GPIOF_OUT_INIT_HIGH, @@ -646,8 +645,6 @@ static int adv7183_probe(struct i2c_client *client, gpio_free(decoder->oe_pin); err_free_reset: gpio_free(decoder->reset_pin); -err_free_decoder: - kfree(decoder); return ret; } @@ -660,7 +657,6 @@ static int adv7183_remove(struct i2c_client *client) v4l2_ctrl_handler_free(sd->ctrl_handler); gpio_free(decoder->oe_pin); gpio_free(decoder->reset_pin); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 3dc6098c7267..ec505098598a 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -410,7 +410,7 @@ static int adv7393_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct adv7393_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -444,16 +444,13 @@ static int adv7393_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_handler_setup(&state->hdl); err = adv7393_initialize(&state->sd); - if (err) { + if (err) v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - } return err; } @@ -464,7 +461,6 @@ static int adv7393_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 31a63c9324fe..4cdcfc96aa56 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1968,7 +1968,7 @@ static int adv7604_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) { v4l_err(client, "Could not allocate adv7604_state memory!\n"); return -ENOMEM; @@ -1977,8 +1977,7 @@ static int adv7604_probe(struct i2c_client *client, /* platform data */ if (!pdata) { v4l_err(client, "No platform data!\n"); - err = -ENODEV; - goto err_state; + return -ENODEV; } memcpy(&state->pdata, pdata, sizeof(state->pdata)); @@ -1991,8 +1990,7 @@ static int adv7604_probe(struct i2c_client *client, if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) { v4l2_info(sd, "not an adv7604 on address 0x%x\n", client->addr << 1); - err = -ENODEV; - goto err_state; + return -ENODEV; } /* control handlers */ @@ -2093,8 +2091,6 @@ static int adv7604_probe(struct i2c_client *client, adv7604_unregister_clients(state); err_hdl: v4l2_ctrl_handler_free(hdl); -err_state: - kfree(state); return err; } @@ -2111,7 +2107,6 @@ static int adv7604_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); adv7604_unregister_clients(to_state(sd)); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index fd47465e4f6a..b918c3f29cbe 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -264,7 +264,7 @@ static int ak881x_probe(struct i2c_client *client, return -EIO; } - ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); + ak881x = devm_kzalloc(&client->dev, sizeof(*ak881x), GFP_KERNEL); if (!ak881x) return -ENOMEM; @@ -282,7 +282,6 @@ static int ak881x_probe(struct i2c_client *client, default: dev_err(&client->dev, "No ak881x chip detected, register read %x\n", data); - kfree(ak881x); return -ENODEV; } @@ -331,7 +330,6 @@ static int ak881x_remove(struct i2c_client *client) struct ak881x *ak881x = to_ak881x(client); v4l2_device_unregister_subdev(&ak881x->subdev); - kfree(ak881x); return 0; } diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c index 58d523f2648f..301084b07887 100644 --- a/drivers/media/i2c/as3645a.c +++ b/drivers/media/i2c/as3645a.c @@ -813,7 +813,7 @@ static int as3645a_probe(struct i2c_client *client, if (client->dev.platform_data == NULL) return -ENODEV; - flash = kzalloc(sizeof(*flash), GFP_KERNEL); + flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); if (flash == NULL) return -ENOMEM; @@ -838,10 +838,8 @@ static int as3645a_probe(struct i2c_client *client, flash->led_mode = V4L2_FLASH_LED_MODE_NONE; done: - if (ret < 0) { + if (ret < 0) v4l2_ctrl_handler_free(&flash->ctrls); - kfree(flash); - } return ret; } @@ -855,7 +853,6 @@ static int as3645a_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&flash->ctrls); media_entity_cleanup(&flash->subdev.entity); mutex_destroy(&flash->power_lock); - kfree(flash); return 0; } diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index 377bf05b1efd..ee9ed67e7910 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -425,7 +425,7 @@ static int bt819_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; sd = &decoder->sd; @@ -476,7 +476,6 @@ static int bt819_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -490,7 +489,6 @@ static int bt819_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c index 7e5bd365c239..7e5011163b62 100644 --- a/drivers/media/i2c/bt856.c +++ b/drivers/media/i2c/bt856.c @@ -216,7 +216,7 @@ static int bt856_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -250,7 +250,6 @@ static int bt856_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_bt856(sd)); return 0; } diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c index 905320b67a1c..9355b924b471 100644 --- a/drivers/media/i2c/bt866.c +++ b/drivers/media/i2c/bt866.c @@ -207,7 +207,7 @@ static int bt866_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -220,7 +220,6 @@ static int bt866_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_bt866(sd)); return 0; } diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index 1d2f7c8512b5..841b9c49dcfa 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -190,7 +190,7 @@ static int cs5345_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -206,7 +206,6 @@ static int cs5345_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } /* set volume/mute */ @@ -227,7 +226,6 @@ static int cs5345_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index b293912206eb..1082fb775ab2 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -175,7 +175,7 @@ static int cs53l32a_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -197,7 +197,6 @@ static int cs53l32a_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -228,7 +227,6 @@ static int cs53l32a_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 12fb9b2eb887..bdfec4c768fe 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -5190,7 +5190,7 @@ static int cx25840_probe(struct i2c_client *client, return -ENODEV; } - state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -5292,7 +5292,6 @@ static int cx25840_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } if (!is_cx2583x(state)) @@ -5317,7 +5316,6 @@ static int cx25840_remove(struct i2c_client *client) cx25840_ir_remove(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index 9ae977b5983a..e6588ee5bdb0 100644 --- a/drivers/media/i2c/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c @@ -1230,16 +1230,14 @@ int cx25840_ir_probe(struct v4l2_subdev *sd) if (!(is_cx23885(state) || is_cx23887(state))) return 0; - ir_state = kzalloc(sizeof(struct cx25840_ir_state), GFP_KERNEL); + ir_state = devm_kzalloc(&state->c->dev, sizeof(*ir_state), GFP_KERNEL); if (ir_state == NULL) return -ENOMEM; spin_lock_init(&ir_state->rx_kfifo_lock); if (kfifo_alloc(&ir_state->rx_kfifo, - CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) { - kfree(ir_state); + CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) return -ENOMEM; - } ir_state->c = state->c; state->ir_state = ir_state; @@ -1273,7 +1271,6 @@ int cx25840_ir_remove(struct v4l2_subdev *sd) cx25840_ir_tx_shutdown(sd); kfifo_free(&ir_state->rx_kfifo); - kfree(ir_state); state->ir_state = NULL; return 0; } diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 8e2f79cb045e..82bf5679da30 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -295,7 +295,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) unsigned short addr = client->addr; int err; - ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); + ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL); if (!ir) return -ENOMEM; @@ -398,10 +398,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) * internally */ rc = rc_allocate_device(); - if (!rc) { - err = -ENOMEM; - goto err_out_free; - } + if (!rc) + return -ENOMEM; } ir->rc = rc; @@ -454,7 +452,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) err_out_free: /* Only frees rc if it were allocated internally */ rc_free_device(rc); - kfree(ir); return err; } @@ -470,7 +467,6 @@ static int ir_remove(struct i2c_client *client) rc_unregister_device(ir->rc); /* free memory */ - kfree(ir); return 0; } diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index 04a6efa37cc3..c7227763240e 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -685,7 +685,7 @@ static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *i client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", client->addr << 1, client->adapter->name); - ks = kzalloc(sizeof(*ks), GFP_KERNEL); + ks = devm_kzalloc(&client->dev, sizeof(*ks), GFP_KERNEL); if (ks == NULL) return -ENOMEM; sd = &ks->sd; @@ -708,7 +708,6 @@ static int ks0127_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */ ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */ - kfree(to_ks0127(sd)); return 0; } diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 39f50fd2b8d2..0d153f3b1a5b 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -174,7 +174,7 @@ static int m52790_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -191,7 +191,6 @@ static int m52790_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index f0b870c06376..08ff082242c3 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -950,7 +950,7 @@ static int m5mols_probe(struct i2c_client *client, return -EINVAL; } - info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -962,7 +962,7 @@ static int m5mols_probe(struct i2c_client *client, ret = gpio_request_one(pdata->gpio_reset, gpio_flags, "M5MOLS_NRST"); if (ret) { dev_err(&client->dev, "Failed to request gpio: %d\n", ret); - goto out_free; + return ret; } ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); @@ -1015,8 +1015,6 @@ static int m5mols_probe(struct i2c_client *client, regulator_bulk_free(ARRAY_SIZE(supplies), supplies); out_gpio: gpio_free(pdata->gpio_reset); -out_free: - kfree(info); return ret; } @@ -1032,7 +1030,7 @@ static int m5mols_remove(struct i2c_client *client) regulator_bulk_free(ARRAY_SIZE(supplies), supplies); gpio_free(info->pdata->gpio_reset); media_entity_cleanup(&sd->entity); - kfree(info); + return 0; } diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 54a9dd394f45..ae92c20790e3 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -707,7 +707,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) return -ENODEV; } - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; @@ -732,7 +732,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); - kfree(state); return -ENODEV; } @@ -827,7 +826,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(state); return err; } @@ -889,7 +887,6 @@ static int msp_remove(struct i2c_client *client) msp_reset(client); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index 8edb3d8f7b90..cca704e02f79 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -730,7 +730,7 @@ static int mt9m032_probe(struct i2c_client *client, if (!client->dev.platform_data) return -ENODEV; - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (sensor == NULL) return -ENOMEM; @@ -860,7 +860,6 @@ static int mt9m032_probe(struct i2c_client *client, v4l2_ctrl_handler_free(&sensor->ctrls); error_sensor: mutex_destroy(&sensor->lock); - kfree(sensor); return ret; } @@ -873,7 +872,6 @@ static int mt9m032_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&sensor->ctrls); media_entity_cleanup(&subdev->entity); mutex_destroy(&sensor->lock); - kfree(sensor); return 0; } diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index 2e189d8b71bb..796463466ef0 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c @@ -740,7 +740,7 @@ static int mt9t001_probe(struct i2c_client *client, if (ret < 0) return ret; - mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL); + mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL); if (!mt9t001) return -ENOMEM; @@ -801,7 +801,6 @@ static int mt9t001_probe(struct i2c_client *client, if (ret < 0) { v4l2_ctrl_handler_free(&mt9t001->ctrls); media_entity_cleanup(&mt9t001->subdev.entity); - kfree(mt9t001); } return ret; @@ -815,7 +814,6 @@ static int mt9t001_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&mt9t001->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); - kfree(mt9t001); return 0; } diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 3f415fd12de3..c64c9d9e253d 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -526,7 +526,7 @@ static int mt9v011_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; - core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); + core = devm_kzalloc(&c->dev, sizeof(struct mt9v011), GFP_KERNEL); if (!core) return -ENOMEM; @@ -539,7 +539,6 @@ static int mt9v011_probe(struct i2c_client *c, (version != MT9V011_REV_B_VERSION)) { v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", version); - kfree(core); return -EINVAL; } @@ -562,7 +561,6 @@ static int mt9v011_probe(struct i2c_client *c, v4l2_err(sd, "control initialization error %d\n", ret); v4l2_ctrl_handler_free(&core->ctrls); - kfree(core); return ret; } core->sd.ctrl_handler = &core->ctrls; @@ -598,7 +596,7 @@ static int mt9v011_remove(struct i2c_client *c) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&core->ctrls); - kfree(to_mt9v011(sd)); + return 0; } diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 24ea6fd3ee81..60c6f6739560 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -744,7 +744,7 @@ static int mt9v032_probe(struct i2c_client *client, return -EIO; } - mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL); + mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL); if (!mt9v032) return -ENOMEM; @@ -831,10 +831,8 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); - if (ret < 0) { + if (ret < 0) v4l2_ctrl_handler_free(&mt9v032->ctrls); - kfree(mt9v032); - } return ret; } @@ -847,7 +845,6 @@ static int mt9v032_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&mt9v032->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); - kfree(mt9v032); return 0; } diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index a115842ab996..d205522e598e 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -712,7 +712,7 @@ static int noon010_probe(struct i2c_client *client, return -EIO; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -796,7 +796,6 @@ static int noon010_probe(struct i2c_client *client, np_err: v4l2_ctrl_handler_free(&info->hdl); v4l2_device_unregister_subdev(sd); - kfree(info); return ret; } @@ -817,7 +816,7 @@ static int noon010_remove(struct i2c_client *client) gpio_free(info->gpio_nstby); media_entity_cleanup(&sd->entity); - kfree(info); + return 0; } diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c index b0cc927e8b19..5e117abaa2eb 100644 --- a/drivers/media/i2c/ov7640.c +++ b/drivers/media/i2c/ov7640.c @@ -59,7 +59,7 @@ static int ov7640_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &ov7640_ops); @@ -71,7 +71,6 @@ static int ov7640_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { v4l_err(client, "error initializing OV7640\n"); - kfree(sd); return -ENODEV; } @@ -84,7 +83,7 @@ static int ov7640_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); + return 0; } diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 617ad3fff4aa..d71602f4fb43 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1552,7 +1552,7 @@ static int ov7670_probe(struct i2c_client *client, struct ov7670_info *info; int ret; - info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (info == NULL) return -ENOMEM; sd = &info->sd; @@ -1590,7 +1590,6 @@ static int ov7670_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - kfree(info); return ret; } v4l_info(client, "chip found @ 0x%02x (%s)\n", @@ -1635,7 +1634,6 @@ static int ov7670_probe(struct i2c_client *client, int err = info->hdl.error; v4l2_ctrl_handler_free(&info->hdl); - kfree(info); return err; } /* @@ -1659,7 +1657,6 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); - kfree(info); return 0; } diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index b4e1ccbd87ec..729e78d94222 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -478,17 +478,15 @@ static int saa6588_probe(struct i2c_client *client, v4l_info(client, "saa6588 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - s = kzalloc(sizeof(*s), GFP_KERNEL); + s = devm_kzalloc(&client->dev, sizeof(*s), GFP_KERNEL); if (s == NULL) return -ENOMEM; s->buf_size = bufblocks * 3; - s->buffer = kmalloc(s->buf_size, GFP_KERNEL); - if (s->buffer == NULL) { - kfree(s); + s->buffer = devm_kzalloc(&client->dev, s->buf_size, GFP_KERNEL); + if (s->buffer == NULL) return -ENOMEM; - } sd = &s->sd; v4l2_i2c_subdev_init(sd, client, &saa6588_ops); spin_lock_init(&s->lock); @@ -516,8 +514,6 @@ static int saa6588_remove(struct i2c_client *client) cancel_delayed_work_sync(&s->work); - kfree(s->buffer); - kfree(s); return 0; } diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index 51cd4c8f0520..e4026aa93f42 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -406,7 +406,7 @@ static int saa7110_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; sd = &decoder->sd; @@ -428,7 +428,6 @@ static int saa7110_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -469,7 +468,6 @@ static int saa7110_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 52c717d977c9..eecb92df5d96 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1614,7 +1614,7 @@ static int saa711x_probe(struct i2c_client *client, v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name, client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -1640,7 +1640,6 @@ static int saa711x_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(state); return err; } v4l2_ctrl_auto_cluster(2, &state->agc, 0, true); @@ -1712,7 +1711,6 @@ static int saa711x_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index 8a47ac10927f..9882c83c1c93 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -752,7 +752,7 @@ static int saa7127_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -767,7 +767,6 @@ static int saa7127_probe(struct i2c_client *client, if ((saa7127_read(sd, 0) & 0xe4) != 0 || (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) { v4l2_dbg(1, debug, sd, "saa7127 not found\n"); - kfree(state); return -ENODEV; } @@ -823,7 +822,6 @@ static int saa7127_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); /* Turn off TV output */ saa7127_set_video_enable(sd, 0); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index cf3a0aa7e45e..71328109642e 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -1262,7 +1262,7 @@ static int saa717x_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; @@ -1276,7 +1276,6 @@ static int saa717x_probe(struct i2c_client *client, id = saa717x_read(sd, 0x5a0); if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); - kfree(decoder); return -ENODEV; } if (id == 0xc2) @@ -1316,7 +1315,6 @@ static int saa717x_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(decoder); return err; } @@ -1353,7 +1351,6 @@ static int saa717x_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c index 2c6b65c76e2b..e95a0edc7f3e 100644 --- a/drivers/media/i2c/saa7185.c +++ b/drivers/media/i2c/saa7185.c @@ -326,7 +326,7 @@ static int saa7185_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; @@ -352,7 +352,6 @@ static int saa7185_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); /* SW: output off is active */ saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); - kfree(encoder); return 0; } diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c index d7d1670e0ca3..84f7899a4044 100644 --- a/drivers/media/i2c/saa7191.c +++ b/drivers/media/i2c/saa7191.c @@ -605,7 +605,7 @@ static int saa7191_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; @@ -615,7 +615,6 @@ static int saa7191_probe(struct i2c_client *client, err = saa7191_write_block(sd, sizeof(initseq), initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); - kfree(decoder); return err; } @@ -636,7 +635,6 @@ static int saa7191_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_saa7191(sd)); return 0; } diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c index 38cbea98764c..efa306165618 100644 --- a/drivers/media/i2c/sony-btf-mpx.c +++ b/drivers/media/i2c/sony-btf-mpx.c @@ -355,7 +355,7 @@ static int sony_btf_mpx_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - t = kzalloc(sizeof(struct sony_btf_mpx), GFP_KERNEL); + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; @@ -374,7 +374,6 @@ static int sony_btf_mpx_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index e9d95bda2ab1..4c5a9ee60c3e 100644 --- a/drivers/media/i2c/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c @@ -820,7 +820,7 @@ static int sr030pc30_probe(struct i2c_client *client, if (ret) return ret; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -841,10 +841,8 @@ static int sr030pc30_probe(struct i2c_client *client, static int sr030pc30_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct sr030pc30_info *info = to_sr030pc30(sd); v4l2_device_unregister_subdev(sd); - kfree(info); return 0; } diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c index 28b5121881f5..72af644fa051 100644 --- a/drivers/media/i2c/tda7432.c +++ b/drivers/media/i2c/tda7432.c @@ -359,7 +359,7 @@ static int tda7432_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; sd = &t->sd; @@ -380,7 +380,6 @@ static int tda7432_probe(struct i2c_client *client, int err = t->hdl.error; v4l2_ctrl_handler_free(&t->hdl); - kfree(t); return err; } v4l2_ctrl_cluster(2, &t->bass); @@ -406,7 +405,6 @@ static int tda7432_remove(struct i2c_client *client) tda7432_set(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&t->hdl); - kfree(t); return 0; } diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index 01441e35d88b..3f1266246ca3 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -184,7 +184,7 @@ static int tda9840_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tda9840_ops); @@ -201,7 +201,6 @@ static int tda9840_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index 3d5b06a5c308..52ebc384e453 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -152,7 +152,7 @@ static int tea6415c_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tea6415c_ops); @@ -164,7 +164,6 @@ static int tea6415c_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 38757217a074..1f869742e3fe 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -125,7 +125,7 @@ static int tea6420_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tea6420_ops); @@ -146,7 +146,6 @@ static int tea6420_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 809a75a558ee..ef87f7b09ea2 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -162,7 +162,7 @@ static int tlv320aic23b_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -191,7 +191,6 @@ static int tlv320aic23b_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_handler_setup(&state->hdl); @@ -205,7 +204,6 @@ static int tlv320aic23b_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index b72a59d3216a..fc69e9c27343 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -1910,7 +1910,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * printk("\n"); } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; sd = &chip->sd; @@ -1930,7 +1930,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * } if (desc->name == NULL) { v4l2_dbg(1, debug, sd, "no matching chip description found\n"); - kfree(chip); return -EIO; } v4l2_info(sd, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); @@ -2001,7 +2000,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * int err = chip->hdl.error; v4l2_ctrl_handler_free(&chip->hdl); - kfree(chip); return err; } /* set controls to the default values */ @@ -2043,7 +2041,6 @@ static int tvaudio_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&chip->hdl); - kfree(chip); return 0; } diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 485159a3c0b7..de9db3bf1ebd 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1152,10 +1152,9 @@ static int tvp5150_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; - core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL); - if (!core) { + core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); + if (!core) return -ENOMEM; - } sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); @@ -1166,7 +1165,7 @@ static int tvp5150_probe(struct i2c_client *c, for (i = 0; i < 4; i++) { res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); if (res < 0) - goto free_core; + return res; tvp5150_id[i] = res; } @@ -1209,7 +1208,7 @@ static int tvp5150_probe(struct i2c_client *c, if (core->hdl.error) { res = core->hdl.error; v4l2_ctrl_handler_free(&core->hdl); - goto free_core; + return res; } v4l2_ctrl_handler_setup(&core->hdl); @@ -1225,10 +1224,6 @@ static int tvp5150_probe(struct i2c_client *c, if (debug > 1) tvp5150_log_status(sd); return 0; - -free_core: - kfree(core); - return res; } static int tvp5150_remove(struct i2c_client *c) @@ -1242,7 +1237,6 @@ static int tvp5150_remove(struct i2c_client *c) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(to_tvp5150(sd)); return 0; } diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c index c5dc2c3bf2d7..41a5c9b31006 100644 --- a/drivers/media/i2c/tw2804.c +++ b/drivers/media/i2c/tw2804.c @@ -368,8 +368,7 @@ static int tw2804_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - state = kzalloc(sizeof(struct tw2804), GFP_KERNEL); - + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -410,7 +409,6 @@ static int tw2804_probe(struct i2c_client *client, err = state->hdl.error; if (err) { v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -427,7 +425,6 @@ static int tw2804_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c index 87880b19d8c3..285b759a5f7f 100644 --- a/drivers/media/i2c/tw9903.c +++ b/drivers/media/i2c/tw9903.c @@ -215,7 +215,7 @@ static int tw9903_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - dec = kzalloc(sizeof(struct tw9903), GFP_KERNEL); + dec = devm_kzalloc(&client->dev, sizeof(*dec), GFP_KERNEL); if (dec == NULL) return -ENOMEM; sd = &dec->sd; @@ -233,7 +233,6 @@ static int tw9903_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(dec); return err; } @@ -242,7 +241,6 @@ static int tw9903_probe(struct i2c_client *client, if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9903\n"); - kfree(dec); return -EINVAL; } @@ -255,7 +253,6 @@ static int tw9903_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&to_state(sd)->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c index accd79e5a7fd..f6bef25bd9ce 100644 --- a/drivers/media/i2c/tw9906.c +++ b/drivers/media/i2c/tw9906.c @@ -183,7 +183,7 @@ static int tw9906_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - dec = kzalloc(sizeof(struct tw9906), GFP_KERNEL); + dec = devm_kzalloc(&client->dev, sizeof(*dec), GFP_KERNEL); if (dec == NULL) return -ENOMEM; sd = &dec->sd; @@ -201,7 +201,6 @@ static int tw9906_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(dec); return err; } @@ -210,7 +209,6 @@ static int tw9906_probe(struct i2c_client *client, if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9906\n"); - kfree(dec); return -EINVAL; } @@ -223,7 +221,6 @@ static int tw9906_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&to_state(sd)->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c index 3af408556d27..081786d176d0 100644 --- a/drivers/media/i2c/uda1342.c +++ b/drivers/media/i2c/uda1342.c @@ -69,7 +69,7 @@ static int uda1342_probe(struct i2c_client *client, dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n", client->addr, adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; @@ -89,7 +89,6 @@ static int uda1342_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index f0a09214c519..4283fc5f39ef 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -230,7 +230,7 @@ static int upd64031a_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -249,7 +249,6 @@ static int upd64031a_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index 343e0215f74c..b2ac56ca22e6 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -202,7 +202,7 @@ static int upd64083_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -221,7 +221,6 @@ static int upd64083_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index e71f139695af..208a095d7bcc 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -169,7 +169,7 @@ static int vp27smpx_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -186,7 +186,6 @@ static int vp27smpx_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 2f67b4c5c823..f02e74b9b1ac 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -499,7 +499,7 @@ static int vpx3220_probe(struct i2c_client *client, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; - decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; sd = &decoder->sd; @@ -521,7 +521,6 @@ static int vpx3220_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -566,7 +565,7 @@ static int vpx3220_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); + return 0; } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index 6b8c0b7aa488..94e284908f39 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -813,11 +813,9 @@ static int vs6624_probe(struct i2c_client *client, /* wait 100ms before any further i2c writes are performed */ mdelay(100); - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); - if (sensor == NULL) { - gpio_free(*ce); + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); + if (sensor == NULL) return -ENOMEM; - } sd = &sensor->sd; v4l2_i2c_subdev_init(sd, client, &vs6624_ops); @@ -865,7 +863,6 @@ static int vs6624_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(sensor); gpio_free(*ce); return err; } @@ -874,7 +871,6 @@ static int vs6624_probe(struct i2c_client *client, ret = v4l2_ctrl_handler_setup(hdl); if (ret) { v4l2_ctrl_handler_free(hdl); - kfree(sensor); gpio_free(*ce); } return ret; @@ -888,7 +884,6 @@ static int vs6624_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); gpio_free(sensor->ce_pin); - kfree(sensor); return 0; } diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index 3bb99e93febe..ac3faa7bab2d 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -220,7 +220,7 @@ static int wm8739_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct wm8739_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -237,7 +237,6 @@ static int wm8739_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_cluster(3, &state->volume); @@ -271,7 +270,6 @@ static int wm8739_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 27c27b4ae238..75ded82d513f 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -241,7 +241,7 @@ static int wm8775_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct wm8775_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -261,7 +261,6 @@ static int wm8775_probe(struct i2c_client *client, err = state->hdl.error; if (err) { v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -319,7 +318,6 @@ static int wm8775_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } -- GitLab From b015ba29ca09b0e3750b4de365d3baf9c5b11450 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0159/2900] [media] media: i2c: Convert to devm_gpio_request_one() Using the managed function the gpio_free() calls can be removed from the probe error path and the remove handler. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7183.c | 24 ++++++++--------------- drivers/media/i2c/m5mols/m5mols_core.c | 9 +++------ drivers/media/i2c/noon010pc30.c | 27 ++++++++------------------ drivers/media/i2c/smiapp/smiapp-core.c | 18 +++++------------ drivers/media/i2c/vs6624.c | 10 +++------- 5 files changed, 27 insertions(+), 61 deletions(-) diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 56904174abc3..42b2dec4ca3a 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -580,17 +580,17 @@ static int adv7183_probe(struct i2c_client *client, decoder->reset_pin = pin_array[0]; decoder->oe_pin = pin_array[1]; - if (gpio_request_one(decoder->reset_pin, GPIOF_OUT_INIT_LOW, - "ADV7183 Reset")) { + if (devm_gpio_request_one(&client->dev, decoder->reset_pin, + GPIOF_OUT_INIT_LOW, "ADV7183 Reset")) { v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); return -EBUSY; } - if (gpio_request_one(decoder->oe_pin, GPIOF_OUT_INIT_HIGH, - "ADV7183 Output Enable")) { + if (devm_gpio_request_one(&client->dev, decoder->oe_pin, + GPIOF_OUT_INIT_HIGH, + "ADV7183 Output Enable")) { v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); - ret = -EBUSY; - goto err_free_reset; + return -EBUSY; } sd = &decoder->sd; @@ -612,7 +612,7 @@ static int adv7183_probe(struct i2c_client *client, ret = hdl->error; v4l2_ctrl_handler_free(hdl); - goto err_free_oe; + return ret; } /* v4l2 doesn't support an autodetect standard, pick PAL as default */ @@ -637,26 +637,18 @@ static int adv7183_probe(struct i2c_client *client, ret = v4l2_ctrl_handler_setup(hdl); if (ret) { v4l2_ctrl_handler_free(hdl); - goto err_free_oe; + return ret; } return 0; -err_free_oe: - gpio_free(decoder->oe_pin); -err_free_reset: - gpio_free(decoder->reset_pin); - return ret; } static int adv7183_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct adv7183 *decoder = to_adv7183(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - gpio_free(decoder->oe_pin); - gpio_free(decoder->reset_pin); return 0; } diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 08ff082242c3..f870d5057e3d 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -959,7 +959,8 @@ static int m5mols_probe(struct i2c_client *client, gpio_flags = pdata->reset_polarity ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - ret = gpio_request_one(pdata->gpio_reset, gpio_flags, "M5MOLS_NRST"); + ret = devm_gpio_request_one(&client->dev, pdata->gpio_reset, gpio_flags, + "M5MOLS_NRST"); if (ret) { dev_err(&client->dev, "Failed to request gpio: %d\n", ret); return ret; @@ -968,7 +969,7 @@ static int m5mols_probe(struct i2c_client *client, ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); if (ret) { dev_err(&client->dev, "Failed to get regulators: %d\n", ret); - goto out_gpio; + return ret; } sd = &info->sd; @@ -1013,22 +1014,18 @@ static int m5mols_probe(struct i2c_client *client, media_entity_cleanup(&sd->entity); out_reg: regulator_bulk_free(ARRAY_SIZE(supplies), supplies); -out_gpio: - gpio_free(pdata->gpio_reset); return ret; } static int m5mols_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct m5mols_info *info = to_m5mols(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); free_irq(client->irq, sd); regulator_bulk_free(ARRAY_SIZE(supplies), supplies); - gpio_free(info->pdata->gpio_reset); media_entity_cleanup(&sd->entity); return 0; diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index d205522e598e..6f81b99ddd1c 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -746,8 +746,9 @@ static int noon010_probe(struct i2c_client *client, info->curr_win = &noon010_sizes[0]; if (gpio_is_valid(pdata->gpio_nreset)) { - ret = gpio_request_one(pdata->gpio_nreset, GPIOF_OUT_INIT_LOW, - "NOON010PC30 NRST"); + ret = devm_gpio_request_one(&client->dev, pdata->gpio_nreset, + GPIOF_OUT_INIT_LOW, + "NOON010PC30 NRST"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); goto np_err; @@ -757,11 +758,12 @@ static int noon010_probe(struct i2c_client *client, } if (gpio_is_valid(pdata->gpio_nstby)) { - ret = gpio_request_one(pdata->gpio_nstby, GPIOF_OUT_INIT_LOW, - "NOON010PC30 NSTBY"); + ret = devm_gpio_request_one(&client->dev, pdata->gpio_nstby, + GPIOF_OUT_INIT_LOW, + "NOON010PC30 NSTBY"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); - goto np_gpio_err; + goto np_err; } info->gpio_nstby = pdata->gpio_nstby; gpio_export(info->gpio_nstby, 0); @@ -773,7 +775,7 @@ static int noon010_probe(struct i2c_client *client, ret = regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES, info->supply); if (ret) - goto np_reg_err; + goto np_err; info->pad.flags = MEDIA_PAD_FL_SOURCE; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; @@ -787,12 +789,6 @@ static int noon010_probe(struct i2c_client *client, np_me_err: regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); -np_reg_err: - if (gpio_is_valid(info->gpio_nstby)) - gpio_free(info->gpio_nstby); -np_gpio_err: - if (gpio_is_valid(info->gpio_nreset)) - gpio_free(info->gpio_nreset); np_err: v4l2_ctrl_handler_free(&info->hdl); v4l2_device_unregister_subdev(sd); @@ -808,13 +804,6 @@ static int noon010_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&info->hdl); regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); - - if (gpio_is_valid(info->gpio_nreset)) - gpio_free(info->gpio_nreset); - - if (gpio_is_valid(info->gpio_nstby)) - gpio_free(info->gpio_nstby); - media_entity_cleanup(&sd->entity); return 0; diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index cae4f4683851..c38545419045 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2383,8 +2383,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) } if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) { - if (gpio_request_one(sensor->platform_data->xshutdown, 0, - "SMIA++ xshutdown") != 0) { + if (devm_gpio_request_one(&client->dev, + sensor->platform_data->xshutdown, 0, + "SMIA++ xshutdown") != 0) { dev_err(&client->dev, "unable to acquire reset gpio %d\n", sensor->platform_data->xshutdown); @@ -2393,10 +2394,8 @@ static int smiapp_registered(struct v4l2_subdev *subdev) } rval = smiapp_power_on(sensor); - if (rval) { - rval = -ENODEV; - goto out_smiapp_power_on; - } + if (rval) + return -ENODEV; rval = smiapp_identify_module(subdev); if (rval) { @@ -2656,11 +2655,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev) out_power_off: smiapp_power_off(sensor); - -out_smiapp_power_on: - if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) - gpio_free(sensor->platform_data->xshutdown); - return rval; } @@ -2858,8 +2852,6 @@ static int smiapp_remove(struct i2c_client *client) v4l2_device_unregister_subdev(&sensor->ssds[i].sd); } smiapp_free_controls(sensor); - if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) - gpio_free(sensor->platform_data->xshutdown); return 0; } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index 94e284908f39..7b55b3ddd80f 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -805,7 +805,8 @@ static int vs6624_probe(struct i2c_client *client, if (ce == NULL) return -EINVAL; - ret = gpio_request_one(*ce, GPIOF_OUT_INIT_HIGH, "VS6624 Chip Enable"); + ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH, + "VS6624 Chip Enable"); if (ret) { v4l_err(client, "failed to request GPIO %d\n", *ce); return ret; @@ -863,27 +864,22 @@ static int vs6624_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - gpio_free(*ce); return err; } /* initialize the hardware to the default control values */ ret = v4l2_ctrl_handler_setup(hdl); - if (ret) { + if (ret) v4l2_ctrl_handler_free(hdl); - gpio_free(*ce); - } return ret; } static int vs6624_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct vs6624 *sensor = to_vs6624(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - gpio_free(sensor->ce_pin); return 0; } -- GitLab From 07e0e5b287421fcc4f4dbe2c0c8bfbc02e23a51e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0160/2900] [media] media: i2c: Convert to devm_regulator_bulk_get() Using the managed function the regulator_bulk_put() calls can be removed from the probe error path and the remove handler. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/m5mols/m5mols_core.c | 8 +++----- drivers/media/i2c/noon010pc30.c | 8 ++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index f870d5057e3d..11f6f871c372 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -966,7 +966,8 @@ static int m5mols_probe(struct i2c_client *client, return ret; } - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); + ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), + supplies); if (ret) { dev_err(&client->dev, "Failed to get regulators: %d\n", ret); return ret; @@ -981,7 +982,7 @@ static int m5mols_probe(struct i2c_client *client, info->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&sd->entity, 1, &info->pad, 0); if (ret < 0) - goto out_reg; + return ret; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; init_waitqueue_head(&info->irq_waitq); @@ -1012,8 +1013,6 @@ static int m5mols_probe(struct i2c_client *client, free_irq(client->irq, sd); out_me: media_entity_cleanup(&sd->entity); -out_reg: - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); return ret; } @@ -1025,7 +1024,6 @@ static int m5mols_remove(struct i2c_client *client) v4l2_ctrl_handler_free(sd->ctrl_handler); free_irq(client->irq, sd); - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); media_entity_cleanup(&sd->entity); return 0; diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 6f81b99ddd1c..2284b02102db 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -772,7 +772,7 @@ static int noon010_probe(struct i2c_client *client, for (i = 0; i < NOON010_NUM_SUPPLIES; i++) info->supply[i].supply = noon010_supply_name[i]; - ret = regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES, + ret = devm_regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES, info->supply); if (ret) goto np_err; @@ -781,14 +781,12 @@ static int noon010_probe(struct i2c_client *client, sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; ret = media_entity_init(&sd->entity, 1, &info->pad, 0); if (ret < 0) - goto np_me_err; + goto np_err; ret = noon010_detect(client, info); if (!ret) return 0; -np_me_err: - regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); np_err: v4l2_ctrl_handler_free(&info->hdl); v4l2_device_unregister_subdev(sd); @@ -802,8 +800,6 @@ static int noon010_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); - - regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); media_entity_cleanup(&sd->entity); return 0; -- GitLab From 736db646b676e20542a98a95968ef806b25b794b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0161/2900] [media] m5mols: Convert to devm_request_irq() Using the managed function the free_irq() calls can be removed from the probe error path and the remove handler. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/m5mols/m5mols_core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 11f6f871c372..8d870b7b43ff 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -988,11 +988,11 @@ static int m5mols_probe(struct i2c_client *client, init_waitqueue_head(&info->irq_waitq); mutex_init(&info->lock); - ret = request_irq(client->irq, m5mols_irq_handler, - IRQF_TRIGGER_RISING, MODULE_NAME, sd); + ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler, + IRQF_TRIGGER_RISING, MODULE_NAME, sd); if (ret) { dev_err(&client->dev, "Interrupt request failed: %d\n", ret); - goto out_me; + goto error; } info->res_type = M5MOLS_RESTYPE_MONITOR; info->ffmt[0] = m5mols_default_ffmt[0]; @@ -1000,7 +1000,7 @@ static int m5mols_probe(struct i2c_client *client, ret = m5mols_sensor_power(info, true); if (ret) - goto out_irq; + goto error; ret = m5mols_fw_start(sd); if (!ret) @@ -1009,9 +1009,7 @@ static int m5mols_probe(struct i2c_client *client, ret = m5mols_sensor_power(info, false); if (!ret) return 0; -out_irq: - free_irq(client->irq, sd); -out_me: +error: media_entity_cleanup(&sd->entity); return ret; } @@ -1022,8 +1020,6 @@ static int m5mols_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - free_irq(client->irq, sd); - media_entity_cleanup(&sd->entity); return 0; -- GitLab From 598d8d1e4c0bd21a992c52fe0adc69e0b3117a41 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0162/2900] [media] s5c73m3: Convert to devm_gpio_request_one() Use the devm_gpio_request_one() managed function to simplify cleanup code paths. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 79 +++++++++--------------- 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index cb52438e53ac..d3e867a7a565 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1511,59 +1511,40 @@ static const struct v4l2_subdev_ops oif_subdev_ops = { .video = &s5c73m3_oif_video_ops, }; -static int s5c73m3_configure_gpio(int nr, int val, const char *name) -{ - unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - int ret; - - if (!gpio_is_valid(nr)) - return 0; - ret = gpio_request_one(nr, flags, name); - if (!ret) - gpio_export(nr, 0); - return ret; -} - -static int s5c73m3_free_gpios(struct s5c73m3 *state) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(state->gpio); i++) { - if (!gpio_is_valid(state->gpio[i].gpio)) - continue; - gpio_free(state->gpio[i].gpio); - state->gpio[i].gpio = -EINVAL; - } - return 0; -} - static int s5c73m3_configure_gpios(struct s5c73m3 *state, const struct s5c73m3_platform_data *pdata) { - const struct s5c73m3_gpio *gpio = &pdata->gpio_stby; + struct device *dev = &state->i2c_client->dev; + const struct s5c73m3_gpio *gpio; + unsigned long flags; int ret; state->gpio[STBY].gpio = -EINVAL; state->gpio[RST].gpio = -EINVAL; - ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_STBY"); - if (ret) { - s5c73m3_free_gpios(state); - return ret; + gpio = &pdata->gpio_stby; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(dev, gpio->gpio, flags, + "S5C73M3_STBY"); + if (ret < 0) + return ret; + + state->gpio[STBY] = *gpio; } - state->gpio[STBY] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); gpio = &pdata->gpio_reset; - ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_RST"); - if (ret) { - s5c73m3_free_gpios(state); - return ret; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(dev, gpio->gpio, flags, + "S5C73M3_RST"); + if (ret < 0) + return ret; + + state->gpio[RST] = *gpio; } - state->gpio[RST] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); return 0; } @@ -1626,10 +1607,11 @@ static int s5c73m3_probe(struct i2c_client *client, state->mclk_frequency = pdata->mclk_frequency; state->bus_type = pdata->bus_type; + state->i2c_client = client; ret = s5c73m3_configure_gpios(state, pdata); if (ret) - goto out_err1; + goto out_err; for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) state->supplies[i].supply = s5c73m3_supply_names[i]; @@ -1638,12 +1620,12 @@ static int s5c73m3_probe(struct i2c_client *client, state->supplies); if (ret) { dev_err(dev, "failed to get regulators\n"); - goto out_err2; + goto out_err; } ret = s5c73m3_init_controls(state); if (ret) - goto out_err2; + goto out_err; state->sensor_pix_size[RES_ISP] = &s5c73m3_isp_resolutions[1]; state->sensor_pix_size[RES_JPEG] = &s5c73m3_jpeg_resolutions[1]; @@ -1659,16 +1641,12 @@ static int s5c73m3_probe(struct i2c_client *client, ret = s5c73m3_register_spi_driver(state); if (ret < 0) - goto out_err2; - - state->i2c_client = client; + goto out_err; v4l2_info(sd, "%s: completed succesfully\n", __func__); return 0; -out_err2: - s5c73m3_free_gpios(state); -out_err1: +out_err: media_entity_cleanup(&sd->entity); return ret; } @@ -1688,7 +1666,6 @@ static int s5c73m3_remove(struct i2c_client *client) media_entity_cleanup(&sensor_sd->entity); s5c73m3_unregister_spi_driver(state); - s5c73m3_free_gpios(state); return 0; } -- GitLab From 31857e54fa5a6e39d2d24dc912135bb0d26a6db9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 2 May 2013 08:29:43 -0300 Subject: [PATCH 0163/2900] [media] s5k6aa: Convert to devm_gpio_request_one() Use the devm_gpio_request_one() managed function to simplify cleanup code paths. Signed-off-by: Laurent Pinchart Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k6aa.c | 73 ++++++++++++++------------------------ 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index bdf5e3db31d1..789c02a6ca1a 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -1491,58 +1491,41 @@ static const struct v4l2_subdev_ops s5k6aa_subdev_ops = { /* * GPIO setup */ -static int s5k6aa_configure_gpio(int nr, int val, const char *name) -{ - unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - int ret; - - if (!gpio_is_valid(nr)) - return 0; - ret = gpio_request_one(nr, flags, name); - if (!ret) - gpio_export(nr, 0); - return ret; -} - -static void s5k6aa_free_gpios(struct s5k6aa *s5k6aa) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s5k6aa->gpio); i++) { - if (!gpio_is_valid(s5k6aa->gpio[i].gpio)) - continue; - gpio_free(s5k6aa->gpio[i].gpio); - s5k6aa->gpio[i].gpio = -EINVAL; - } -} static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa, const struct s5k6aa_platform_data *pdata) { - const struct s5k6aa_gpio *gpio = &pdata->gpio_stby; + struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); + const struct s5k6aa_gpio *gpio; + unsigned long flags; int ret; s5k6aa->gpio[STBY].gpio = -EINVAL; s5k6aa->gpio[RST].gpio = -EINVAL; - ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY"); - if (ret) { - s5k6aa_free_gpios(s5k6aa); - return ret; + gpio = &pdata->gpio_stby; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, + "S5K6AA_STBY"); + if (ret < 0) + return ret; + + s5k6aa->gpio[STBY] = *gpio; } - s5k6aa->gpio[STBY] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); gpio = &pdata->gpio_reset; - ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST"); - if (ret) { - s5k6aa_free_gpios(s5k6aa); - return ret; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, + "S5K6AA_RST"); + if (ret < 0) + return ret; + + s5k6aa->gpio[RST] = *gpio; } - s5k6aa->gpio[RST] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); return 0; } @@ -1593,7 +1576,7 @@ static int s5k6aa_probe(struct i2c_client *client, ret = s5k6aa_configure_gpios(s5k6aa, pdata); if (ret) - goto out_err2; + goto out_err; for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++) s5k6aa->supplies[i].supply = s5k6aa_supply_names[i]; @@ -1602,12 +1585,12 @@ static int s5k6aa_probe(struct i2c_client *client, s5k6aa->supplies); if (ret) { dev_err(&client->dev, "Failed to get regulators\n"); - goto out_err3; + goto out_err; } ret = s5k6aa_initialize_ctrls(s5k6aa); if (ret) - goto out_err3; + goto out_err; s5k6aa_presets_data_init(s5k6aa); @@ -1618,9 +1601,7 @@ static int s5k6aa_probe(struct i2c_client *client, return 0; -out_err3: - s5k6aa_free_gpios(s5k6aa); -out_err2: +out_err: media_entity_cleanup(&s5k6aa->sd.entity); return ret; } @@ -1628,12 +1609,10 @@ static int s5k6aa_probe(struct i2c_client *client, static int s5k6aa_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct s5k6aa *s5k6aa = to_s5k6aa(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); media_entity_cleanup(&sd->entity); - s5k6aa_free_gpios(s5k6aa); return 0; } -- GitLab From 835ab0121adb24ff27729bd3743f1477af00c435 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 12 Apr 2013 09:30:29 -0300 Subject: [PATCH 0164/2900] [media] bttv: Add Adlink MPG24 entry to the bttv cardlist Add a proper card entry for this device, rather than abusing entries that are not-quite-right. Regards, Hans Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/pci/bt8xx/bttv-cards.c | 22 +++++++++++++++++----- drivers/media/pci/bt8xx/bttv.h | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 581f666a76cf..407ab4660dce 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -160,3 +160,4 @@ 159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] 160 -> Tongwei Video Technology TD-3116 [f200:3116] 161 -> Aposonic W-DVR [0279:0228] +162 -> Adlink MPG24 diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index b7dc921e1b91..8d327ff60e37 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -2705,7 +2705,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .has_remote = 1, }, - [BTTV_BOARD_VD012] = { + [BTTV_BOARD_VD012] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012 (bt878)", .video_inputs = 4, @@ -2718,7 +2718,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_VD012_X1] = { + [BTTV_BOARD_VD012_X1] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X1 (bt878)", .video_inputs = 4, @@ -2731,7 +2731,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_VD012_X2] = { + [BTTV_BOARD_VD012_X2] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X2 (bt878)", .video_inputs = 4, @@ -2744,7 +2744,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_GEOVISION_GV800S] = { + [BTTV_BOARD_GEOVISION_GV800S] = { /* Bruno Christo * * GeoVision GV-800(S) has 4 Conexant Fusion 878A: @@ -2771,7 +2771,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .muxsel_hook = gv800s_muxsel, }, - [BTTV_BOARD_GEOVISION_GV800S_SL] = { + [BTTV_BOARD_GEOVISION_GV800S_SL] = { /* Bruno Christo * * GeoVision GV-800(S) has 4 Conexant Fusion 878A: @@ -2808,6 +2808,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, + /* ---- card 0xa0---------------------------------- */ [BTTV_BOARD_TVT_TD3116] = { .name = "Tongwei Video Technology TD-3116", .video_inputs = 16, @@ -2825,6 +2826,17 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = TUNER_ABSENT, }, + [BTTV_BOARD_ADLINK_MPG24] = { + /* Adlink MPG24 */ + .name = "Adlink MPG24", + .video_inputs = 1, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, + .muxsel = MUXSEL(2, 2, 2, 2), + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + }, }; diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index 6139ce26dc2c..f01c9d4c7ec1 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -185,6 +185,7 @@ #define BTTV_BOARD_PV183 0x9f #define BTTV_BOARD_TVT_TD3116 0xa0 #define BTTV_BOARD_APOSONIC_WDVR 0xa1 +#define BTTV_BOARD_ADLINK_MPG24 0xa2 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 -- GitLab From 968bd2e7ca25d630edc0d8e145ab8225af6d585b Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Fri, 12 Apr 2013 19:52:57 -0300 Subject: [PATCH 0165/2900] [media] blackfin: add display support in ppi driver Signed-off-by: Scott Jiang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/blackfin/ppi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index 01b5b501347e..15e9c2bac2b1 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c @@ -266,6 +266,18 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) bfin_write32(®->vcnt, params->height); if (params->int_mask) bfin_write32(®->imsk, params->int_mask & 0xFF); + if (ppi->ppi_control & PORT_DIR) { + u32 hsync_width, vsync_width, vsync_period; + + hsync_width = params->hsync + * params->bpp / params->dlen; + vsync_width = params->vsync * samples_per_line; + vsync_period = samples_per_line * params->frame; + bfin_write32(®->fs1_wlhb, hsync_width); + bfin_write32(®->fs1_paspl, samples_per_line); + bfin_write32(®->fs2_wlvb, vsync_width); + bfin_write32(®->fs2_palpf, vsync_period); + } break; } default: -- GitLab From ead156c427295f8dfad7d4f954122501ca32ab65 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Fri, 12 Apr 2013 19:52:59 -0300 Subject: [PATCH 0166/2900] [media] bfin_capture: add query_dv_timings/enum_dv_timings support More dv_timings ioctl ops are introduced in video core. Add query_dv_timings/enum_dv_timings accordingly. Signed-off-by: Scott Jiang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/blackfin/bfin_capture.c | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 0e55b087076f..03530bc6bdd1 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -649,18 +649,30 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std) return 0; } -static int bcap_g_dv_timings(struct file *file, void *priv, +static int bcap_enum_dv_timings(struct file *file, void *priv, + struct v4l2_enum_dv_timings *timings) +{ + struct bcap_device *bcap_dev = video_drvdata(file); + + return v4l2_subdev_call(bcap_dev->sd, video, + enum_dv_timings, timings); +} + +static int bcap_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct bcap_device *bcap_dev = video_drvdata(file); - int ret; - ret = v4l2_subdev_call(bcap_dev->sd, video, - g_dv_timings, timings); - if (ret < 0) - return ret; + return v4l2_subdev_call(bcap_dev->sd, video, + query_dv_timings, timings); +} - bcap_dev->dv_timings = *timings; +static int bcap_g_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct bcap_device *bcap_dev = video_drvdata(file); + + *timings = bcap_dev->dv_timings; return 0; } @@ -921,6 +933,8 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { .vidioc_g_std = bcap_g_std, .vidioc_s_dv_timings = bcap_s_dv_timings, .vidioc_g_dv_timings = bcap_g_dv_timings, + .vidioc_query_dv_timings = bcap_query_dv_timings, + .vidioc_enum_dv_timings = bcap_enum_dv_timings, .vidioc_reqbufs = bcap_reqbufs, .vidioc_querybuf = bcap_querybuf, .vidioc_qbuf = bcap_qbuf, -- GitLab From cc1088dc0b92723c5e2e4cb5098dfa84a39afaed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 13 Apr 2013 05:25:59 -0300 Subject: [PATCH 0167/2900] [media] media:adv7180: Use dev_pm_ops Use dev_pm_ops instead of the deprecated legacy suspend/resume callbacks. Signed-off-by: Lars-Peter Clausen Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 3d1456780318..04ee1d4a4b93 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -614,9 +614,10 @@ static const struct i2c_device_id adv7180_id[] = { {}, }; -#ifdef CONFIG_PM -static int adv7180_suspend(struct i2c_client *client, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int adv7180_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); int ret; ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, @@ -626,8 +627,9 @@ static int adv7180_suspend(struct i2c_client *client, pm_message_t state) return 0; } -static int adv7180_resume(struct i2c_client *client) +static int adv7180_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct adv7180_state *state = to_state(sd); int ret; @@ -641,6 +643,12 @@ static int adv7180_resume(struct i2c_client *client) return ret; return 0; } + +static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); +#define ADV7180_PM_OPS (&adv7180_pm_ops) + +#else +#define ADV7180_PM_OPS NULL #endif MODULE_DEVICE_TABLE(i2c, adv7180_id); @@ -649,13 +657,10 @@ static struct i2c_driver adv7180_driver = { .driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, + .pm = ADV7180_PM_OPS, }, .probe = adv7180_probe, .remove = adv7180_remove, -#ifdef CONFIG_PM - .suspend = adv7180_suspend, - .resume = adv7180_resume, -#endif .id_table = adv7180_id, }; -- GitLab From ec7c15b58f34015df182e909fbb80674211daf54 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 14 Apr 2013 12:39:09 -0300 Subject: [PATCH 0168/2900] [media] bttv: Add noname Bt848 capture card with 14MHz xtal Add support for noname Bt848 capture-only card (3x composite, 1x S-VHS) with 14MHz crystal: http://www.rainbow-software.org/images/hardware/bt848_.jpg 14MHz PLL was not supported by bttv driver until now. [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-cards.c | 20 +++++++++++++++++++- drivers/media/pci/bt8xx/bttv.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 8d327ff60e37..2ba62f113522 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -131,7 +131,7 @@ MODULE_PARM_DESC(vsfx,"set VSFX pci config bit " "[yet another chipset flaw workaround]"); MODULE_PARM_DESC(latency,"pci latency timer"); MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); -MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); +MODULE_PARM_DESC(pll, "specify installed crystal (0=none, 28=28 MHz, 35=35 MHz, 14=14 MHz)"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore"); MODULE_PARM_DESC(audiodev, "specify audio device:\n" @@ -2837,6 +2837,14 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .pll = PLL_28, }, + [BTTV_BOARD_BT848_CAP_14] = { + .name = "Bt848 Capture 14MHz", + .video_inputs = 4, + .svhs = 2, + .muxsel = MUXSEL(2, 3, 1, 0), + .pll = PLL_14, + .tuner_type = TUNER_ABSENT, + }, }; @@ -3402,6 +3410,10 @@ void bttv_init_card2(struct bttv *btv) btv->pll.pll_ifreq=35468950; btv->pll.pll_crystal=BT848_IFORM_XT1; } + if (PLL_14 == bttv_tvcards[btv->c.type].pll) { + btv->pll.pll_ifreq = 14318181; + btv->pll.pll_crystal = BT848_IFORM_XT0; + } /* insmod options can override */ switch (pll[btv->c.nr]) { case 0: /* none */ @@ -3421,6 +3433,12 @@ void bttv_init_card2(struct bttv *btv) btv->pll.pll_ofreq = 0; btv->pll.pll_crystal = BT848_IFORM_XT1; break; + case 3: /* 14 MHz */ + case 14: + btv->pll.pll_ifreq = 14318181; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; } } btv->pll.pll_current = -1; diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index f01c9d4c7ec1..9d09e303f1dd 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -186,6 +186,7 @@ #define BTTV_BOARD_TVT_TD3116 0xa0 #define BTTV_BOARD_APOSONIC_WDVR 0xa1 #define BTTV_BOARD_ADLINK_MPG24 0xa2 +#define BTTV_BOARD_BT848_CAP_14 0xa3 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 @@ -233,6 +234,7 @@ struct tvcard { #define PLL_NONE 0 #define PLL_28 1 #define PLL_35 2 +#define PLL_14 3 /* i2c audio flags */ unsigned int no_msp34xx:1; -- GitLab From ba9948fb9c3bd220b4766f19aff82c2776a7eb4c Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 14 Apr 2013 17:26:21 -0300 Subject: [PATCH 0169/2900] [media] bttv: Add CyberVision CV06 Add CyberVision CV06 4-camera card (from CyberVision SV card kit): http://www.cybervision.com.tw/products-swcard_kits-sv.html There are some interesting things on the card but they're not supported: 4 LEDs, a connector with 4 IN and 4 OUT pins, RESET IN and RESET OUT connectors, a relay and CyberVision CV8088-SV16 chip Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-cards.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index 2ba62f113522..e564aac0aa30 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -2845,6 +2845,16 @@ struct tvcard bttv_tvcards[] = { .pll = PLL_14, .tuner_type = TUNER_ABSENT, }, + [BTTV_BOARD_CYBERVISION_CV06] = { + .name = "CyberVision CV06 (SV)", + .video_inputs = 4, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .muxsel = MUXSEL(2, 3, 1, 0), + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + }, }; -- GitLab From adf6271281a811dbcf2cb090b2a99a8520f7852b Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Thu, 18 Apr 2013 08:16:08 -0300 Subject: [PATCH 0170/2900] [media] videodev2.h: Make V4L2_PIX_FMT_MPEG4 comment more specific about its usage Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/videodev2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index f40b41c7e108..16c3cf71eb94 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -395,7 +395,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */ #define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */ #define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */ -#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */ #define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */ #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */ #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */ -- GitLab From 012eef7001d4e0bede7122f34a4a6cc13a83c28e Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Fri, 19 Apr 2013 05:53:29 -0300 Subject: [PATCH 0171/2900] [media] media: davinci: vpif: remove unwanted header file inclusion this patch removes unwanted header file inclusion and sorts header alphabetically. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 19 ++++----------- drivers/media/platform/davinci/vpif_capture.h | 5 +--- drivers/media/platform/davinci/vpif_display.c | 23 +++---------------- drivers/media/platform/davinci/vpif_display.h | 5 +--- 4 files changed, 9 insertions(+), 43 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 5f98df1fc8a0..a1b42b037678 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -18,28 +18,17 @@ * TODO : add support for VBI & HBI data service * add static buffer allocation */ -#include -#include + #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include -#include #include -#include -#include + #include +#include -#include "vpif_capture.h" #include "vpif.h" +#include "vpif_capture.h" MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 3d3c1e5cd5d4..0ebb31260369 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -22,11 +22,8 @@ #ifdef __KERNEL__ /* Header files */ -#include -#include -#include #include -#include +#include #include "vpif.h" diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 1b3fb5ca2ad4..d8330567dd57 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -14,33 +14,16 @@ * GNU General Public License for more details. */ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include #include -#include #include -#include -#include - -#include -#include -#include #include +#include -#include "vpif_display.h" #include "vpif.h" +#include "vpif_display.h" MODULE_DESCRIPTION("TI DaVinci VPIF Display driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index a5a18f74395c..5d87fc86e580 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -17,11 +17,8 @@ #define DAVINCIHD_DISPLAY_H /* Header files */ -#include -#include -#include #include -#include +#include #include "vpif.h" -- GitLab From c8f089c9203e0061ecd27030518e7d06fea0edd8 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Fri, 19 Apr 2013 05:53:30 -0300 Subject: [PATCH 0172/2900] [media] media: davinci: vpif_display: move displaying of error to approppraite place this patch moves the displaying out error case "VPIF IRQ request failed\n" when there is actual request_irq() fail. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index d8330567dd57..7b1736842690 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1725,6 +1725,7 @@ static __init int vpif_probe(struct platform_device *pdev) for (j = 0; j < i; j++) free_irq(j, (void *) (&vpif_obj.dev[res_idx]->channel_id)); + vpif_err("VPIF IRQ request failed\n"); goto vpif_int_err; } } @@ -1878,7 +1879,6 @@ static __init int vpif_probe(struct platform_device *pdev) } vpif_int_err: v4l2_device_unregister(&vpif_obj.v4l2_dev); - vpif_err("VPIF IRQ request failed\n"); for (i = 0; i < res_idx; i++) { res = platform_get_resource(pdev, IORESOURCE_IRQ, i); for (j = res->start; j <= res->end; j++) -- GitLab From 05ff7240b0aa1794cebd8b0ecb846ed629fb5da3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Apr 2013 08:57:41 -0300 Subject: [PATCH 0173/2900] [media] CARDLIST.bttv: add new cards Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 2 ++ drivers/media/pci/bt8xx/bttv.h | 1 + 2 files changed, 3 insertions(+) diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 407ab4660dce..f14475011fea 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -161,3 +161,5 @@ 160 -> Tongwei Video Technology TD-3116 [f200:3116] 161 -> Aposonic W-DVR [0279:0228] 162 -> Adlink MPG24 +163 -> Bt848 Capture 14MHz +164 -> CyberVision CV06 (SV) diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index 9d09e303f1dd..df578efe03c9 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -187,6 +187,7 @@ #define BTTV_BOARD_APOSONIC_WDVR 0xa1 #define BTTV_BOARD_ADLINK_MPG24 0xa2 #define BTTV_BOARD_BT848_CAP_14 0xa3 +#define BTTV_BOARD_CYBERVISION_CV06 0xa4 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 -- GitLab From 60bc53d5f7a2b5117fe665c6db1f03ec389f4ae6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 May 2013 08:16:19 -0300 Subject: [PATCH 0174/2900] [media] update saa7134 and tuner cardlists Those are automatically updated using the cardlist script. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + Documentation/video4linux/CARDLIST.tuner | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b3ad68309109..8df17d063499 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -190,3 +190,4 @@ 189 -> Kworld PC150-U [17de:a134] 190 -> Asus My Cinema PS3-100 [1043:48cd] 191 -> Hawell HW-9004V1 +192 -> AverMedia AverTV Satellite Hybrid+FM A706 [1461:2055] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 5b83a3ff15c2..ac8862184962 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -86,6 +86,6 @@ tuner=85 - Philips FQ1236 MK5 tuner=86 - Tena TNF5337 MFD tuner=87 - Xceive 4000 tuner tuner=88 - Xceive 5000C tuner -tuner=89 - Sony PAL+SECAM (BTF-PG472Z) -tuner=90 - Sony NTSC-M-JP (BTF-PK467Z) -tuner=91 - Sony NTSC-M (BTF-PB463Z) +tuner=89 - Sony BTF-PG472Z PAL/SECAM +tuner=90 - Sony BTF-PK467Z NTSC-M-JP +tuner=91 - Sony BTF-PB463Z NTSC-M -- GitLab From 3020bea57fdb950bc6121a51d1e8e7b0a82c2827 Mon Sep 17 00:00:00 2001 From: Jakob Haufe Date: Sat, 13 Apr 2013 11:03:36 -0300 Subject: [PATCH 0175/2900] [media] rc: Add rc-delock-61959 This adds the keytable for the remote that comes with the Delock 61959. NEC protocol with address 0x866b. Signed-off-by: Jakob Haufe Reviewed-by: Antti Palosaari Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/keymaps/Makefile | 1 + drivers/media/rc/keymaps/rc-delock-61959.c | 83 ++++++++++++++++++++++ include/media/rc-map.h | 1 + 3 files changed, 85 insertions(+) create mode 100644 drivers/media/rc/keymaps/rc-delock-61959.c diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 5ab94ea4bc28..b1cde8c0422b 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-budget-ci-old.o \ rc-cinergy-1400.o \ rc-cinergy.o \ + rc-delock-61959.o \ rc-dib0700-nec.o \ rc-dib0700-rc5.o \ rc-digitalnow-tinytwin.o \ diff --git a/drivers/media/rc/keymaps/rc-delock-61959.c b/drivers/media/rc/keymaps/rc-delock-61959.c new file mode 100644 index 000000000000..01bed864f09d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-delock-61959.c @@ -0,0 +1,83 @@ +/* rc-delock-61959.c - Keytable for Delock + * + * Copyright (c) 2013 by Jakob Haufe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +/* + * Keytable for remote provided with Delock 61959 + */ +static struct rc_map_table delock_61959[] = { + { 0x866b16, KEY_POWER2 }, /* Power */ + { 0x866b0c, KEY_POWER }, /* Shut Down */ + + { 0x866b00, KEY_1}, + { 0x866b01, KEY_2}, + { 0x866b02, KEY_3}, + { 0x866b03, KEY_4}, + { 0x866b04, KEY_5}, + { 0x866b05, KEY_6}, + { 0x866b06, KEY_7}, + { 0x866b07, KEY_8}, + { 0x866b08, KEY_9}, + { 0x866b14, KEY_0}, + + { 0x866b0a, KEY_ZOOM}, /* Full Screen */ + { 0x866b10, KEY_CAMERA}, /* Photo */ + { 0x866b0e, KEY_CHANNEL}, /* circular arrow / Recall */ + { 0x866b13, KEY_ESC}, /* Back */ + + { 0x866b20, KEY_UP}, + { 0x866b21, KEY_DOWN}, + { 0x866b42, KEY_LEFT}, + { 0x866b43, KEY_RIGHT}, + { 0x866b0b, KEY_OK}, + + { 0x866b11, KEY_CHANNELUP}, + { 0x866b1b, KEY_CHANNELDOWN}, + + { 0x866b12, KEY_VOLUMEUP}, + { 0x866b48, KEY_VOLUMEDOWN}, + { 0x866b44, KEY_MUTE}, + + { 0x866b1a, KEY_RECORD}, + { 0x866b41, KEY_PLAY}, + { 0x866b40, KEY_STOP}, + { 0x866b19, KEY_PAUSE}, + { 0x866b1c, KEY_FASTFORWARD}, /* >> / FWD */ + { 0x866b1e, KEY_REWIND}, /* << / REW */ + +}; + +static struct rc_map_list delock_61959_map = { + .map = { + .scan = delock_61959, + .size = ARRAY_SIZE(delock_61959), + .rc_type = RC_TYPE_NEC, + .name = RC_MAP_DELOCK_61959, + } +}; + +static int __init init_rc_map_delock_61959(void) +{ + return rc_map_register(&delock_61959_map); +} + +static void __exit exit_rc_map_delock_61959(void) +{ + rc_map_unregister(&delock_61959_map); +} + +module_init(init_rc_map_delock_61959) +module_exit(exit_rc_map_delock_61959) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jakob Haufe "); +MODULE_DESCRIPTION("Delock 61959 remote keytable"); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 5d5d3a30f04a..6628f5d01f52 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -111,6 +111,7 @@ void rc_map_init(void); #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" #define RC_MAP_CINERGY_1400 "rc-cinergy-1400" #define RC_MAP_CINERGY "rc-cinergy" +#define RC_MAP_DELOCK_61959 "rc-delock-61959" #define RC_MAP_DIB0700_NEC_TABLE "rc-dib0700-nec" #define RC_MAP_DIB0700_RC5_TABLE "rc-dib0700-rc5" #define RC_MAP_DIGITALNOW_TINYTWIN "rc-digitalnow-tinytwin" -- GitLab From 7c1dfdb059505fee12eaf089070145febd9e5ecf Mon Sep 17 00:00:00 2001 From: Jakob Haufe Date: Sat, 13 Apr 2013 11:03:37 -0300 Subject: [PATCH 0176/2900] [media] em28xx: Add support for 1b80:e1cc Delock 61959 Hardware is the same as MaxMedia UB425-TC but ships with a different remote. Signed-off-by: Jakob Haufe Reviewed-by: Antti Palosaari Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 16 ++++++++++++++++ drivers/media/usb/em28xx/em28xx-dvb.c | 5 +++-- drivers/media/usb/em28xx/em28xx.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 83bfbe4c980f..927956b4dca7 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -374,6 +374,7 @@ static struct em28xx_reg_seq hauppauge_930c_digital[] = { #endif /* 1b80:e425 MaxMedia UB425-TC + * 1b80:e1cc Delock 61959 * GPIO_6 - demod reset, 0=active * GPIO_7 - LED, 0=active */ @@ -2017,6 +2018,19 @@ struct em28xx_board em28xx_boards[] = { .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, }, + /* 1b80:e1cc Delock 61959 + * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 + * mostly the same as MaxMedia UB-425-TC but different remote */ + [EM2874_BOARD_DELOCK_61959] = { + .name = "Delock 61959", + .tuner_type = TUNER_ABSENT, + .tuner_gpio = maxmedia_ub425_tc, + .has_dvb = 1, + .ir_codes = RC_MAP_DELOCK_61959, + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -2178,6 +2192,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2884_BOARD_PCTV_510E }, { USB_DEVICE(0x2013, 0x0251), .driver_info = EM2884_BOARD_PCTV_520E }, + { USB_DEVICE(0x1b80, 0xe1cc), + .driver_info = EM2874_BOARD_DELOCK_61959 }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index b22f8fed8127..42ede686ab69 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1216,6 +1216,7 @@ static int em28xx_dvb_init(struct em28xx *dev) dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config); break; + case EM2874_BOARD_DELOCK_61959: case EM2874_BOARD_MAXMEDIA_UB425_TC: /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, @@ -1235,8 +1236,8 @@ static int em28xx_dvb_init(struct em28xx *dev) } /* TODO: we need drx-3913k firmware in order to support DVB-T */ - em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ - "driver version\n"); + em28xx_info("MaxMedia UB425-TC/Delock 61959: only DVB-C " \ + "supported by that driver version\n"); break; case EM2884_BOARD_PCTV_510E: diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index a9323b63d8e5..59a95802aa68 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -130,6 +130,7 @@ #define EM2884_BOARD_PCTV_520E 86 #define EM2884_BOARD_TERRATEC_HTC_USB_XS 87 #define EM2884_BOARD_C3TECH_DIGITAL_DUO 88 +#define EM2874_BOARD_DELOCK_61959 89 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 -- GitLab From 849325e331cd196914d1e1a9e19edeaa42e75037 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Fri, 3 May 2013 08:39:25 -0300 Subject: [PATCH 0177/2900] [media] media: davinci: vpbe: fix checkpatch warning for CamelCase This patch fixes checkpatch warning to avoid CamelCase. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpbe_display.c | 2 +- drivers/media/platform/davinci/vpbe_osd.c | 24 +++++++++---------- include/media/davinci/vpbe_osd.h | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 1802f11e939f..1c4ba8965797 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -929,7 +929,7 @@ static int vpbe_display_s_fmt(struct file *file, void *priv, cfg->interlaced = vpbe_dev->current_timings.interlaced; if (V4L2_PIX_FMT_UYVY == pixfmt->pixelformat) - cfg->pixfmt = PIXFMT_YCbCrI; + cfg->pixfmt = PIXFMT_YCBCRI; /* Change of the default pixel format for both video windows */ if (V4L2_PIX_FMT_NV12 == pixfmt->pixelformat) { diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 396a51cbede7..6ed82e8b297b 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c @@ -119,7 +119,7 @@ static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val, #define is_rgb_pixfmt(pixfmt) \ (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888)) #define is_yc_pixfmt(pixfmt) \ - (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \ + (((pixfmt) == PIXFMT_YCBCRI) || ((pixfmt) == PIXFMT_YCRCBI) || \ ((pixfmt) == PIXFMT_NV12)) #define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X #define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5) @@ -360,8 +360,8 @@ static void _osd_enable_color_key(struct osd_state *sd, osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, OSD_TRANSPVALL); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: if (sd->vpbe_type == VPBE_VERSION_3) osd_modify(sd, OSD_TRANSPVALU_Y, colorkey, OSD_TRANSPVALU); @@ -813,8 +813,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, if (osd->vpbe_type == VPBE_VERSION_1) bad_config = !is_vid_win(layer); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: bad_config = !is_vid_win(layer); break; case PIXFMT_RGB888: @@ -950,9 +950,9 @@ static void _osd_set_cbcr_order(struct osd_state *sd, * The caller must ensure that all windows using YC pixfmt use the same * Cb/Cr order. */ - if (pixfmt == PIXFMT_YCbCrI) + if (pixfmt == PIXFMT_YCBCRI) osd_clear(sd, OSD_MODE_CS, OSD_MODE); - else if (pixfmt == PIXFMT_YCrCbI) + else if (pixfmt == PIXFMT_YCRCBI) osd_set(sd, OSD_MODE_CS, OSD_MODE); } @@ -981,8 +981,8 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT); _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT); break; default: @@ -1128,8 +1128,8 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD1); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: winmd |= (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT); break; @@ -1508,7 +1508,7 @@ static int osd_initialize(struct osd_state *osd) _osd_init(osd); /* set default Cb/Cr order */ - osd->yc_pixfmt = PIXFMT_YCbCrI; + osd->yc_pixfmt = PIXFMT_YCBCRI; if (osd->vpbe_type == VPBE_VERSION_3) { /* diff --git a/include/media/davinci/vpbe_osd.h b/include/media/davinci/vpbe_osd.h index 42628fcfe1bd..de59364d7ed2 100644 --- a/include/media/davinci/vpbe_osd.h +++ b/include/media/davinci/vpbe_osd.h @@ -82,9 +82,9 @@ enum osd_pix_format { PIXFMT_4BPP, PIXFMT_8BPP, PIXFMT_RGB565, - PIXFMT_YCbCrI, + PIXFMT_YCBCRI, PIXFMT_RGB888, - PIXFMT_YCrCbI, + PIXFMT_YCRCBI, PIXFMT_NV12, PIXFMT_OSD_ATTR, }; -- GitLab From ccc40ed7555d053f60328e9742e559fb75e85002 Mon Sep 17 00:00:00 2001 From: Leonid Kegulskiy Date: Thu, 25 Apr 2013 05:59:54 -0300 Subject: [PATCH 0178/2900] [media] hdpvr: Removed unnecessary get_video_info() call from hdpvr_device_init() Signed-off-by: Leonid Kegulskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 8247c19d6260..cb694055ba7d 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -220,7 +220,6 @@ static int hdpvr_device_init(struct hdpvr_device *dev) { int ret; u8 *buf; - struct hdpvr_video_info *vidinf; if (device_authorization(dev)) return -EACCES; @@ -242,13 +241,6 @@ static int hdpvr_device_init(struct hdpvr_device *dev) "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); - vidinf = get_video_info(dev); - if (!vidinf) - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no valid video signal or device init failed\n"); - else - kfree(vidinf); - /* enable fan and bling leds */ mutex_lock(&dev->usbc_mutex); buf[0] = 0x1; -- GitLab From f74368769048a803e7a7a3dac6434833f563d3bd Mon Sep 17 00:00:00 2001 From: Leonid Kegulskiy Date: Thu, 25 Apr 2013 05:59:56 -0300 Subject: [PATCH 0179/2900] [media] hdpvr: Added some error handling in hdpvr_start_streaming() Signed-off-by: Leonid Kegulskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 774ba0e820be..cd90ba81a5bb 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -298,8 +298,12 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "encoder start control request returned %d\n", ret); + if (ret < 0) + return ret; - hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + ret = hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + if (ret) + return ret; dev->status = STATUS_STREAMING; -- GitLab From 63eb2ca171fc5e7c11b16dccd3dc087b050b788c Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Fri, 3 May 2013 04:17:19 -0300 Subject: [PATCH 0180/2900] [media] media: i2c: tvp7002: enable TVP7002 decoder for media controller based usage This patch enables tvp7002 decoder driver for media controller based usage by adding v4l2_subdev_pad_ops operations support for enum_mbus_code, set_pad_format, get_pad_format and media_entity_init() on probe and media_entity_cleanup() on remove. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 96 +++++++++++++++++++++++++++++++++++-- include/media/tvp7002.h | 2 + 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 027809cca5f5..270e6997cc76 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -424,6 +424,7 @@ struct tvp7002 { int streaming; const struct tvp7002_timings_definition *current_timings; + struct media_pad pad; }; /* @@ -880,6 +881,65 @@ static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = { .s_ctrl = tvp7002_s_ctrl, }; +/* + * tvp7002_enum_mbus_code() - Enum supported digital video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @code: pointer to subdev enum mbus code struct + * + * Enumerate supported digital video formats for pad. + */ +static int +tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + /* Check requested format index is within range */ + if (code->index != 0) + return -EINVAL; + + code->code = V4L2_MBUS_FMT_YUYV10_1X20; + + return 0; +} + +/* + * tvp7002_get_pad_format() - get video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @fmt: pointer to subdev format struct + * + * get video format for pad. + */ +static int +tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct tvp7002 *tvp7002 = to_tvp7002(sd); + + fmt->format.code = V4L2_MBUS_FMT_YUYV10_1X20; + fmt->format.width = tvp7002->current_timings->timings.bt.width; + fmt->format.height = tvp7002->current_timings->timings.bt.height; + fmt->format.field = tvp7002->current_timings->scanmode; + fmt->format.colorspace = tvp7002->current_timings->color_space; + + return 0; +} + +/* + * tvp7002_set_pad_format() - set video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @fmt: pointer to subdev format struct + * + * set video format for pad. + */ +static int +tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + return tvp7002_get_pad_format(sd, fh, fmt); +} + /* V4L2 core operation handlers */ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { .g_chip_ident = tvp7002_g_chip_ident, @@ -910,10 +970,18 @@ static const struct v4l2_subdev_video_ops tvp7002_video_ops = { .enum_mbus_fmt = tvp7002_enum_mbus_fmt, }; +/* media pad related operation handlers */ +static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = { + .enum_mbus_code = tvp7002_enum_mbus_code, + .get_fmt = tvp7002_get_pad_format, + .set_fmt = tvp7002_set_pad_format, +}; + /* V4L2 top level operation handlers */ static const struct v4l2_subdev_ops tvp7002_ops = { .core = &tvp7002_core_ops, .video = &tvp7002_video_ops, + .pad = &tvp7002_pad_ops, }; /* @@ -993,19 +1061,35 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) timings = device->current_timings->timings; error = tvp7002_s_dv_timings(sd, &timings); +#if defined(CONFIG_MEDIA_CONTROLLER) + strlcpy(sd->name, TVP7002_MODULE_NAME, sizeof(sd->name)); + device->pad.flags = MEDIA_PAD_FL_SOURCE; + device->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + device->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; + + error = media_entity_init(&device->sd.entity, 1, &device->pad, 0); + if (error < 0) + return error; +#endif + v4l2_ctrl_handler_init(&device->hdl, 1); v4l2_ctrl_new_std(&device->hdl, &tvp7002_ctrl_ops, V4L2_CID_GAIN, 0, 255, 1, 0); sd->ctrl_handler = &device->hdl; if (device->hdl.error) { - int err = device->hdl.error; - - v4l2_ctrl_handler_free(&device->hdl); - return err; + error = device->hdl.error; + goto error; } v4l2_ctrl_handler_setup(&device->hdl); return 0; + +error: + v4l2_ctrl_handler_free(&device->hdl); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&device->sd.entity); +#endif + return error; } /* @@ -1022,7 +1106,9 @@ static int tvp7002_remove(struct i2c_client *c) v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" "on address 0x%x\n", c->addr); - +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&device->sd.entity); +#endif v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&device->hdl); return 0; diff --git a/include/media/tvp7002.h b/include/media/tvp7002.h index ee4353459ef5..7123048408d6 100644 --- a/include/media/tvp7002.h +++ b/include/media/tvp7002.h @@ -26,6 +26,8 @@ #ifndef _TVP7002_H_ #define _TVP7002_H_ +#define TVP7002_MODULE_NAME "tvp7002" + /* Platform-dependent data * * clk_polarity: -- GitLab From 88107675fba0b83d45744e9f2414dfea21686f87 Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Fri, 3 May 2013 15:54:57 -0300 Subject: [PATCH 0181/2900] [media] solo6x10: Approximate frame intervals with non-standard denominator Instead of falling back to 1/25 (PAL) or 1/30 (NTSC). Signed-off-by: Ismael Luceno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/solo6x10/solo6x10-v4l2-enc.c | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c index 98e2902afd74..a4c589604b02 100644 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c @@ -996,12 +996,11 @@ static int solo_g_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_captureparm *cp = &sp->parm.capture; cp->capability = V4L2_CAP_TIMEPERFRAME; cp->timeperframe.numerator = solo_enc->interval; - cp->timeperframe.denominator = solo_dev->fps; + cp->timeperframe.denominator = solo_enc->solo_dev->fps; cp->capturemode = 0; /* XXX: Shouldn't we be able to get/set this from videobuf? */ cp->readbuffers = 2; @@ -1009,36 +1008,29 @@ static int solo_g_parm(struct file *file, void *priv, return 0; } +static inline int calc_interval(u8 fps, u32 n, u32 d) +{ + if (!n || !d) + return 1; + if (d == fps) + return n; + n *= fps; + return min(15U, n / d + (n % d >= (fps >> 1))); +} + static int solo_s_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct v4l2_captureparm *cp = &sp->parm.capture; + struct v4l2_fract *t = &sp->parm.capture.timeperframe; + u8 fps = solo_enc->solo_dev->fps; if (vb2_is_streaming(&solo_enc->vidq)) return -EBUSY; - if ((cp->timeperframe.numerator == 0) || - (cp->timeperframe.denominator == 0)) { - /* reset framerate */ - cp->timeperframe.numerator = 1; - cp->timeperframe.denominator = solo_dev->fps; - } - - if (cp->timeperframe.denominator != solo_dev->fps) - cp->timeperframe.denominator = solo_dev->fps; - - if (cp->timeperframe.numerator > 15) - cp->timeperframe.numerator = 15; - - solo_enc->interval = cp->timeperframe.numerator; - - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->readbuffers = 2; - + solo_enc->interval = calc_interval(fps, t->numerator, t->denominator); solo_update_mode(solo_enc); - return 0; + return solo_g_parm(file, priv, sp); } static long solo_enc_default(struct file *file, void *fh, -- GitLab From 5255e4d9dfe2e33a5d68c54f6d1bee28fc5edd66 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Tue, 7 May 2013 17:57:08 -0300 Subject: [PATCH 0182/2900] [media] wl128x: do not call copy_to_user() while holding spinlocks copy_to_user() must not be called with spinlocks held, but it is in fmc_transfer_rds_from_internal_buff(). The patch copies data to tmpbuf, releases spinlock and then passes it to userspace. By the way there is a small unification: replace a couple of hardcoded constants by a macro. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index a002234ed5de..253f307f0b37 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -715,7 +715,7 @@ static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev) struct fm_rdsdata_format rds_fmt; struct fm_rds *rds = &fmdev->rx.rds; unsigned long group_idx, flags; - u8 *rds_data, meta_data, tmpbuf[3]; + u8 *rds_data, meta_data, tmpbuf[FM_RDS_BLK_SIZE]; u8 type, blk_idx; u16 cur_picode; u32 rds_len; @@ -1073,6 +1073,7 @@ int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file, u8 __user *buf, size_t count) { u32 block_count; + u8 tmpbuf[FM_RDS_BLK_SIZE]; unsigned long flags; int ret; @@ -1087,29 +1088,32 @@ int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file, } /* Calculate block count from byte count */ - count /= 3; + count /= FM_RDS_BLK_SIZE; block_count = 0; ret = 0; - spin_lock_irqsave(&fmdev->rds_buff_lock, flags); - while (block_count < count) { - if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) - break; + spin_lock_irqsave(&fmdev->rds_buff_lock, flags); - if (copy_to_user(buf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx], - FM_RDS_BLK_SIZE)) + if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) { + spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); break; - + } + memcpy(tmpbuf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx], + FM_RDS_BLK_SIZE); fmdev->rx.rds.rd_idx += FM_RDS_BLK_SIZE; if (fmdev->rx.rds.rd_idx >= fmdev->rx.rds.buf_size) fmdev->rx.rds.rd_idx = 0; + spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); + + if (copy_to_user(buf, tmpbuf, FM_RDS_BLK_SIZE)) + break; + block_count++; buf += FM_RDS_BLK_SIZE; ret += FM_RDS_BLK_SIZE; } - spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); return ret; } -- GitLab From e090901e48ba75508caaa1b98fdbb65591c1163f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Apr 2013 10:22:47 -0300 Subject: [PATCH 0183/2900] [media] saa7115: move the autodetection code out of the probe function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we're now seeing other variants from chinese clones, like gm1113c, we'll need to add more bits at the detection code. So, move it into a separate function. Signed-off-by: Mauro Carvalho Chehab Tested-by: Jon Arne Jørgensen Tested-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 133 ++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index eecb92df5d96..289f460801db 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1573,46 +1573,103 @@ static const struct v4l2_subdev_ops saa711x_ops = { /* ----------------------------------------------------------------------- */ +/** + * saa711x_detect_chip - Detects the saa711x (or clone) variant + * @client: I2C client structure. + * @id: I2C device ID structure. + * @name: Name of the device to be filled. + * @size: Size of the name var. + * + * Detects the Philips/NXP saa711x chip, or some clone of it. + * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes + * the analog demod. + * If the tuner is not found, it returns -ENODEV. + * If auto-detection is disabled and the tuner doesn't match what it was + * requred, it returns -EINVAL and fills 'name'. + * If the chip is found, it returns the chip ID and fills 'name'. + */ +static int saa711x_detect_chip(struct i2c_client *client, + const struct i2c_device_id *id, + char *name, unsigned size) +{ + char chip_ver[size - 1]; + char chip_id; + int i; + int autodetect; + + autodetect = !id || id->driver_data == 1; + + /* Read the chip version register */ + for (i = 0; i < size - 1; i++) { + i2c_smbus_write_byte_data(client, 0, i); + chip_ver[i] = i2c_smbus_read_byte_data(client, 0); + name[i] = (chip_ver[i] & 0x0f) + '0'; + if (name[i] > '9') + name[i] += 'a' - '9' - 1; + } + name[i] = '\0'; + + /* Check if it is a Philips/NXP chip */ + if (!memcmp(name + 1, "f711", 4)) { + chip_id = name[5]; + snprintf(name, size, "saa711%c", chip_id); + + if (!autodetect && strcmp(name, id->name)) + return -EINVAL; + + switch (chip_id) { + case '1': + if (chip_ver[0] & 0xf0) { + snprintf(name, size, "saa711%ca", chip_id); + v4l_info(client, "saa7111a variant found\n"); + return V4L2_IDENT_SAA7111A; + } + return V4L2_IDENT_SAA7111; + case '3': + return V4L2_IDENT_SAA7113; + case '4': + return V4L2_IDENT_SAA7114; + case '5': + return V4L2_IDENT_SAA7115; + case '8': + return V4L2_IDENT_SAA7118; + default: + v4l2_info(client, + "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n"); + return V4L2_IDENT_SAA7111; + } + } + + /* Chip was not discovered. Return its ID and don't bind */ + v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n", + 16, chip_ver, client->addr << 1); + return -ENODEV; +} + static int saa711x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct saa711x_state *state; struct v4l2_subdev *sd; struct v4l2_ctrl_handler *hdl; - int i; + int ident; char name[17]; - char chip_id; - int autodetect = !id || id->driver_data == 1; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - for (i = 0; i < 0x0f; i++) { - i2c_smbus_write_byte_data(client, 0, i); - name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; - if (name[i] > '9') - name[i] += 'a' - '9' - 1; - } - name[i] = '\0'; - - chip_id = name[5]; - - /* Check whether this chip is part of the saa711x series */ - if (memcmp(name + 1, "f711", 4)) { - v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", - client->addr << 1, name); + ident = saa711x_detect_chip(client, id, name, sizeof(name)); + if (ident == -EINVAL) { + /* Chip exists, but doesn't match */ + v4l_warn(client, "found %s while %s was expected\n", + name, id->name); return -ENODEV; } + if (ident < 0) + return ident; - /* Safety check */ - if (!autodetect && id->name[6] != chip_id) { - v4l_warn(client, "found saa711%c while %s was expected\n", - chip_id, id->name); - } - snprintf(client->name, sizeof(client->name), "saa711%c", chip_id); - v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name, - client->addr << 1, client->adapter->name); + strlcpy(client->name, name, sizeof(client->name)); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) @@ -1648,31 +1705,7 @@ static int saa711x_probe(struct i2c_client *client, state->output = SAA7115_IPORT_ON; state->enable = 1; state->radio = 0; - switch (chip_id) { - case '1': - state->ident = V4L2_IDENT_SAA7111; - if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) { - v4l_info(client, "saa7111a variant found\n"); - state->ident = V4L2_IDENT_SAA7111A; - } - break; - case '3': - state->ident = V4L2_IDENT_SAA7113; - break; - case '4': - state->ident = V4L2_IDENT_SAA7114; - break; - case '5': - state->ident = V4L2_IDENT_SAA7115; - break; - case '8': - state->ident = V4L2_IDENT_SAA7118; - break; - default: - state->ident = V4L2_IDENT_SAA7111; - v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); - break; - } + state->ident = ident; state->audclk_freq = 48000; -- GitLab From b11460b0532dd22830a9f2fcdcad91b790c6b35b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Apr 2013 10:22:48 -0300 Subject: [PATCH 0184/2900] [media] saa7115: add detection code for gm7113c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a code that (auto)detects gm7113c clones. The auto-detection here is not perfect, as, on contrary to what it would be expected by looking into its datasheets some devices would return, instead: saa7115 0-0025: chip 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 @ 0x4a is unknown (found on a device labeled as GM7113C 1145 by Ezequiel Garcia) Signed-off-by: Mauro Carvalho Chehab Tested-by: Jon Arne Jørgensen Tested-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 36 +++++++++++++++++++++++++++++++++ include/media/v4l2-chip-ident.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 289f460801db..ca2a863a6d3e 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1640,6 +1640,36 @@ static int saa711x_detect_chip(struct i2c_client *client, } } + /* Check if it is a gm7113c */ + if (!memcmp(name, "0000", 4)) { + chip_id = 0; + for (i = 0; i < 4; i++) { + chip_id = chip_id << 1; + chip_id |= (chip_ver[i] & 0x80) ? 1 : 0; + } + + /* + * Note: From the datasheet, only versions 1 and 2 + * exists. However, tests on a device labeled as: + * "GM7113C 1145" returned "10" on all 16 chip + * version (reg 0x00) reads. So, we need to also + * accept at least verion 0. For now, let's just + * assume that a device that returns "0000" for + * the lower nibble is a gm7113c. + */ + + strlcpy(name, "gm7113c", size); + + if (!autodetect && strcmp(name, id->name)) + return -EINVAL; + + v4l_dbg(1, debug, client, + "It seems to be a %s chip (%*ph) @ 0x%x.\n", + name, 16, chip_ver, client->addr << 1); + + return V4L2_IDENT_GM7113C; + } + /* Chip was not discovered. Return its ID and don't bind */ v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n", 16, chip_ver, client->addr << 1); @@ -1669,6 +1699,11 @@ static int saa711x_probe(struct i2c_client *client, if (ident < 0) return ident; + if (ident == V4L2_IDENT_GM7113C) { + v4l_warn(client, "%s not yet supported\n", name); + return -ENODEV; + } + strlcpy(client->name, name, sizeof(client->name)); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); @@ -1754,6 +1789,7 @@ static const struct i2c_device_id saa711x_id[] = { { "saa7114", 0 }, { "saa7115", 0 }, { "saa7118", 0 }, + { "gm7113c", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, saa711x_id); diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h index c259b36bf1e9..543f89c18896 100644 --- a/include/media/v4l2-chip-ident.h +++ b/include/media/v4l2-chip-ident.h @@ -52,6 +52,8 @@ enum { V4L2_IDENT_SAA7115 = 105, V4L2_IDENT_SAA7118 = 108, + V4L2_IDENT_GM7113C = 140, + /* module saa7127: reserved range 150-199 */ V4L2_IDENT_SAA7127 = 157, V4L2_IDENT_SAA7129 = 159, -- GitLab From 241d89fce7b084ea9c671a1b895001eb76b4eecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Arne=20J=C3=B8rgensen?= Date: Fri, 10 May 2013 03:52:28 -0300 Subject: [PATCH 0185/2900] [media] saa7115: Add register setup and config for gm7113c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gm7113c chip is similar to the original saa7113 chip, so I try to re-use most of the saa7113 specific setup-/configuration registers. According to the datasheet, the gm7113c chip has not implemented any register-addresses after 0x1f, so I add a new entry to for the chip to the saa711x_has_reg function. The devices I've seen using this chip will fail to get stable video-sync if these registers are not zeroed: R_14_ANAL_ADC_COMPAT_CNTL R_15_VGATE_START_FID_CHG R_16_VGATE_STOP R_17_MISC_VGATE_CONF_AND_MSB The saa711x_set_v4lstd is updated to send a simpler configuration-table to avoid setting these registers. Signed-off-by: Jon Arne Jørgensen Tested-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 47 +++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index ca2a863a6d3e..be32688797e1 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -127,6 +127,8 @@ static int saa711x_has_reg(const int id, const u8 reg) return 0; switch (id) { + case V4L2_IDENT_GM7113C: + return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20; case V4L2_IDENT_SAA7113: return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) && reg != 0x5d && reg < 0x63; @@ -214,7 +216,10 @@ static const unsigned char saa7111_init[] = { 0x00, 0x00 }; -/* SAA7113 init codes */ +/* SAA7113/GM7113C init codes + * It's important that R_14... R_17 == 0x00 + * for the gm7113c chip to deliver stable video + */ static const unsigned char saa7113_init[] = { R_01_INC_DELAY, 0x08, R_02_INPUT_CNTL_1, 0xc2, @@ -448,6 +453,24 @@ static const unsigned char saa7115_cfg_50hz_video[] = { /* ============== SAA7715 VIDEO templates (end) ======= */ +/* ============== GM7113C VIDEO templates ============= */ +static const unsigned char gm7113c_cfg_60hz_video[] = { + R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ + R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */ + + 0x00, 0x00 +}; + +static const unsigned char gm7113c_cfg_50hz_video[] = { + R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */ + R_0E_CHROMA_CNTL_1, 0x07, + + 0x00, 0x00 +}; + +/* ============== GM7113C VIDEO templates (end) ======= */ + + static const unsigned char saa7115_cfg_vbi_on[] = { R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ @@ -932,11 +955,17 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. if (std & V4L2_STD_525_60) { v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); - saa711x_writeregs(sd, saa7115_cfg_60hz_video); + if (state->ident == V4L2_IDENT_GM7113C) + saa711x_writeregs(sd, gm7113c_cfg_60hz_video); + else + saa711x_writeregs(sd, saa7115_cfg_60hz_video); saa711x_set_size(sd, 720, 480); } else { v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); - saa711x_writeregs(sd, saa7115_cfg_50hz_video); + if (state->ident == V4L2_IDENT_GM7113C) + saa711x_writeregs(sd, gm7113c_cfg_50hz_video); + else + saa711x_writeregs(sd, saa7115_cfg_50hz_video); saa711x_set_size(sd, 720, 576); } @@ -949,7 +978,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) 011 NTSC N (3.58MHz) PAL M (3.58MHz) 100 reserved NTSC-Japan (3.58MHz) */ - if (state->ident <= V4L2_IDENT_SAA7113) { + if (state->ident <= V4L2_IDENT_SAA7113 || + state->ident == V4L2_IDENT_GM7113C) { u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; if (std == V4L2_STD_PAL_M) { @@ -1220,7 +1250,8 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, input, output); /* saa7111/3 does not have these inputs */ - if (state->ident <= V4L2_IDENT_SAA7113 && + if ((state->ident <= V4L2_IDENT_SAA7113 || + state->ident == V4L2_IDENT_GM7113C) && (input == SAA7115_COMPOSITE4 || input == SAA7115_COMPOSITE5)) { return -EINVAL; @@ -1699,11 +1730,6 @@ static int saa711x_probe(struct i2c_client *client, if (ident < 0) return ident; - if (ident == V4L2_IDENT_GM7113C) { - v4l_warn(client, "%s not yet supported\n", name); - return -ENODEV; - } - strlcpy(client->name, name, sizeof(client->name)); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); @@ -1753,6 +1779,7 @@ static int saa711x_probe(struct i2c_client *client, case V4L2_IDENT_SAA7111A: saa711x_writeregs(sd, saa7111_init); break; + case V4L2_IDENT_GM7113C: case V4L2_IDENT_SAA7113: saa711x_writeregs(sd, saa7113_init); break; -- GitLab From a0f9354b1a319cb29c331bfd2e5a15d7f9b87fa4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 8 May 2013 17:28:13 -0300 Subject: [PATCH 0186/2900] [media] media/usb: fix kconfig dependencies (a.k.a. Kconfig bool depending on a tristate considered harmful) Fix various build errors when CONFIG_USB=m and media USB drivers are builtin. In this case, CONFIG_USB_ZR364XX=y, CONFIG_VIDEO_PVRUSB2=y, and CONFIG_VIDEO_STK1160=y. This is caused by (from drivers/media/usb/Kconfig): menuconfig MEDIA_USB_SUPPORT bool "Media USB Adapters" depends on USB && MEDIA_SUPPORT =m =y so MEDIA_USB_SUPPORT=y and all following Kconfig 'source' lines are included. By adding an "if USB" guard around most of this file, the needed dependencies are enforced. drivers/built-in.o: In function `zr364xx_start_readpipe': zr364xx.c:(.text+0xc726a): undefined reference to `usb_alloc_urb' zr364xx.c:(.text+0xc72bb): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `zr364xx_stop_readpipe': zr364xx.c:(.text+0xc72fd): undefined reference to `usb_kill_urb' zr364xx.c:(.text+0xc7309): undefined reference to `usb_free_urb' drivers/built-in.o: In function `read_pipe_completion': zr364xx.c:(.text+0xc7acc): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `send_control_msg.constprop.12': zr364xx.c:(.text+0xc7d2f): undefined reference to `usb_control_msg' drivers/built-in.o: In function `pvr2_ctl_timeout': pvrusb2-hdw.c:(.text+0xcadb6): undefined reference to `usb_unlink_urb' pvrusb2-hdw.c:(.text+0xcadcb): undefined reference to `usb_unlink_urb' drivers/built-in.o: In function `pvr2_hdw_create': (.text+0xcc42c): undefined reference to `usb_alloc_urb' drivers/built-in.o: In function `pvr2_hdw_create': (.text+0xcc448): undefined reference to `usb_alloc_urb' drivers/built-in.o: In function `pvr2_hdw_create': (.text+0xcc5f9): undefined reference to `usb_set_interface' drivers/built-in.o: In function `pvr2_hdw_create': (.text+0xcc65a): undefined reference to `usb_free_urb' drivers/built-in.o: In function `pvr2_hdw_create': (.text+0xcc666): undefined reference to `usb_free_urb' drivers/built-in.o: In function `pvr2_send_request_ex.part.22': pvrusb2-hdw.c:(.text+0xccbe3): undefined reference to `usb_submit_urb' pvrusb2-hdw.c:(.text+0xccc83): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `pvr2_hdw_remove_usb_stuff.part.25': pvrusb2-hdw.c:(.text+0xcd3f9): undefined reference to `usb_kill_urb' pvrusb2-hdw.c:(.text+0xcd405): undefined reference to `usb_free_urb' pvrusb2-hdw.c:(.text+0xcd421): undefined reference to `usb_kill_urb' pvrusb2-hdw.c:(.text+0xcd42d): undefined reference to `usb_free_urb' drivers/built-in.o: In function `pvr2_hdw_device_reset': (.text+0xcd658): undefined reference to `usb_lock_device_for_reset' drivers/built-in.o: In function `pvr2_hdw_device_reset': (.text+0xcd664): undefined reference to `usb_reset_device' drivers/built-in.o: In function `pvr2_hdw_cpureset_assert': (.text+0xcd6f9): undefined reference to `usb_control_msg' drivers/built-in.o: In function `pvr2_hdw_cpufw_set_enabled': (.text+0xcd84e): undefined reference to `usb_control_msg' drivers/built-in.o: In function `pvr2_upload_firmware1': pvrusb2-hdw.c:(.text+0xcda47): undefined reference to `usb_clear_halt' pvrusb2-hdw.c:(.text+0xcdb04): undefined reference to `usb_control_msg' drivers/built-in.o: In function `pvr2_upload_firmware2': (.text+0xce7dc): undefined reference to `usb_bulk_msg' drivers/built-in.o: In function `pvr2_stream_buffer_count': pvrusb2-io.c:(.text+0xd2e05): undefined reference to `usb_alloc_urb' pvrusb2-io.c:(.text+0xd2e5b): undefined reference to `usb_kill_urb' pvrusb2-io.c:(.text+0xd2e9f): undefined reference to `usb_free_urb' drivers/built-in.o: In function `pvr2_stream_internal_flush': pvrusb2-io.c:(.text+0xd2f9b): undefined reference to `usb_kill_urb' drivers/built-in.o: In function `pvr2_buffer_queue': (.text+0xd3328): undefined reference to `usb_kill_urb' drivers/built-in.o: In function `pvr2_buffer_queue': (.text+0xd33ea): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `stk1160_read_reg': (.text+0xd3efa): undefined reference to `usb_control_msg' drivers/built-in.o: In function `stk1160_write_reg': (.text+0xd3f4f): undefined reference to `usb_control_msg' drivers/built-in.o: In function `stop_streaming': stk1160-v4l.c:(.text+0xd4997): undefined reference to `usb_set_interface' drivers/built-in.o: In function `start_streaming': stk1160-v4l.c:(.text+0xd4a9f): undefined reference to `usb_set_interface' stk1160-v4l.c:(.text+0xd4afa): undefined reference to `usb_submit_urb' stk1160-v4l.c:(.text+0xd4ba3): undefined reference to `usb_set_interface' drivers/built-in.o: In function `stk1160_isoc_irq': stk1160-video.c:(.text+0xd509b): undefined reference to `usb_submit_urb' drivers/built-in.o: In function `stk1160_cancel_isoc': (.text+0xd50ef): undefined reference to `usb_kill_urb' drivers/built-in.o: In function `stk1160_free_isoc': (.text+0xd5155): undefined reference to `usb_free_coherent' drivers/built-in.o: In function `stk1160_free_isoc': (.text+0xd515d): undefined reference to `usb_free_urb' drivers/built-in.o: In function `stk1160_alloc_isoc': (.text+0xd5278): undefined reference to `usb_alloc_urb' drivers/built-in.o: In function `stk1160_alloc_isoc': (.text+0xd52c2): undefined reference to `usb_alloc_coherent' drivers/built-in.o: In function `stk1160_alloc_isoc': (.text+0xd53c4): undefined reference to `usb_free_urb' drivers/built-in.o: In function `zr364xx_driver_init': zr364xx.c:(.init.text+0x463e): undefined reference to `usb_register_driver' drivers/built-in.o: In function `pvr_init': pvrusb2-main.c:(.init.text+0x4662): undefined reference to `usb_register_driver' drivers/built-in.o: In function `stk1160_usb_driver_init': stk1160-core.c:(.init.text+0x467d): undefined reference to `usb_register_driver' drivers/built-in.o: In function `zr364xx_driver_exit': zr364xx.c:(.exit.text+0x1377): undefined reference to `usb_deregister' drivers/built-in.o: In function `pvr_exit': pvrusb2-main.c:(.exit.text+0x1389): undefined reference to `usb_deregister' drivers/built-in.o: In function `stk1160_usb_driver_exit': stk1160-core.c:(.exit.text+0x13a0): undefined reference to `usb_deregister' Suggested-by: "Yann E. MORIN" Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index 0a7d520636a9..0d8fe005d1f4 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig @@ -1,6 +1,8 @@ +if USB + menuconfig MEDIA_USB_SUPPORT bool "Media USB Adapters" - depends on USB && MEDIA_SUPPORT + depends on MEDIA_SUPPORT help Enable media drivers for USB bus. If you have such devices, say Y. @@ -52,3 +54,4 @@ source "drivers/media/usb/em28xx/Kconfig" endif endif #MEDIA_USB_SUPPORT +endif #USB -- GitLab From 0735647c29bca5f33f38fcf457b3b0e9e5912f51 Mon Sep 17 00:00:00 2001 From: Reinhard Nissl Date: Wed, 8 May 2013 17:54:57 -0300 Subject: [PATCH 0187/2900] [media] stb0899: remove commented value from IQ_SWAP_ON/OFF usages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the enum values have changed recently, the comments are void. Signed-off-by: Reinhard Nißl Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/mantis/mantis_vp1041.c | 2 +- drivers/media/pci/ttpci/budget-av.c | 2 +- drivers/media/pci/ttpci/budget-ci.c | 2 +- drivers/media/usb/dvb-usb/az6027.c | 2 +- drivers/media/usb/dvb-usb/pctv452e.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/pci/mantis/mantis_vp1041.c b/drivers/media/pci/mantis/mantis_vp1041.c index 07aa887a4b4a..07a20748b707 100644 --- a/drivers/media/pci/mantis/mantis_vp1041.c +++ b/drivers/media/pci/mantis/mantis_vp1041.c @@ -273,7 +273,7 @@ struct stb0899_config vp1041_stb0899_config = { .demod_address = 0x68, /* 0xd0 >> 1 */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 1f8b1bb0bf9f..0ba3875af22e 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -1128,7 +1128,7 @@ static struct stb0899_config knc1_dvbs2_config = { // .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_OFF, /* 1 */ + .inversion = IQ_SWAP_OFF, .lo_clk = 76500000, .hi_clk = 90000000, diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 98e524178765..0acf9202103d 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -1280,7 +1280,7 @@ static struct stb0899_config tt3200_config = { .demod_address = 0x68, .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index 91e0119e8a87..ea2d5ee86576 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -264,7 +264,7 @@ struct stb0899_config az6027_stb0899_config = { .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index d1ddfa13de86..449a99605a87 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -828,7 +828,7 @@ static struct stb0899_config stb0899_config = { .block_sync_mode = STB0899_SYNC_FORCED, /* ? */ .xtal_freq = 27000000, /* Assume Hz ? */ - .inversion = IQ_SWAP_ON, /* ? */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, -- GitLab From a242f426108c284049a69710f871cc9f11b13e61 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 9 May 2013 15:03:33 -0300 Subject: [PATCH 0188/2900] [media] videobuf_vm_{open,close} race fixes just use videobuf_queue_lock(map->q) to protect map->count; vm_area_operations ->open() and ->close() are called just under vma->vm_mm->mmap_sem, which doesn't help the drivers at all, since clonal VMAs are normally in different address spaces... Signed-off-by: Al Viro Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf-dma-contig.c | 12 +++++++----- drivers/media/v4l2-core/videobuf-dma-sg.c | 10 ++++++---- drivers/media/v4l2-core/videobuf-vmalloc.c | 10 ++++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c index 67f572c3fba2..8204c8810372 100644 --- a/drivers/media/v4l2-core/videobuf-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf-dma-contig.c @@ -66,11 +66,14 @@ static void __videobuf_dc_free(struct device *dev, static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; - dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", + dev_dbg(q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -82,12 +85,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { struct videobuf_dma_contig_memory *mem; dev_dbg(q->dev, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); /* We need first to cancel streams, before unmapping */ if (q->streaming) @@ -126,8 +128,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma) kfree(map); - videobuf_queue_unlock(q); } + videobuf_queue_unlock(q); } static const struct vm_operations_struct videobuf_vm_ops = { diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 828e7c10bd70..9db674ccdc68 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -338,11 +338,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free); static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -355,10 +358,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -374,9 +376,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q, q->bufs[i]); } - videobuf_queue_unlock(q); kfree(map); } + videobuf_queue_unlock(q); return; } diff --git a/drivers/media/v4l2-core/videobuf-vmalloc.c b/drivers/media/v4l2-core/videobuf-vmalloc.c index 2ff7fcc77b11..1365c651c177 100644 --- a/drivers/media/v4l2-core/videobuf-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf-vmalloc.c @@ -54,11 +54,14 @@ MODULE_LICENSE("GPL"); static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -70,12 +73,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { struct videobuf_vmalloc_memory *mem; dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); /* We need first to cancel streams, before unmapping */ if (q->streaming) @@ -114,8 +116,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma) kfree(map); - videobuf_queue_unlock(q); } + videobuf_queue_unlock(q); return; } -- GitLab From 4c8d558a1403cedd465395d719d13778b0f689f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Alc=C3=A2ntara?= Date: Sat, 11 May 2013 11:53:29 -0300 Subject: [PATCH 0189/2900] [media] smscoreapi: Make Siano firmware load more verbose If firmware load fails, report it as an error. Signed-off-by: Roberto Alcantara Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smscoreapi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 45ac9eea4882..dbe9b4d9b799 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -1154,7 +1154,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, char *fw_filename = smscore_get_fw_filename(coredev, mode); if (!fw_filename) { - sms_info("mode %d not supported on this device", mode); + sms_err("mode %d not supported on this device", mode); return -ENOENT; } sms_debug("Firmware name: %s", fw_filename); @@ -1165,14 +1165,14 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, rc = request_firmware(&fw, fw_filename, coredev->device); if (rc < 0) { - sms_info("failed to open \"%s\"", fw_filename); + sms_err("failed to open firmware file \"%s\"", fw_filename); return rc; } sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size); fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA); if (!fw_buf) { - sms_info("failed to allocate firmware buffer"); + sms_err("failed to allocate firmware buffer"); return -ENOMEM; } memcpy(fw_buf, fw->data, fw->size); -- GitLab From 2a848b2c7fcc8f5cb370a73ec9ca40d32c6cf18c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 17 Apr 2013 08:22:16 -0300 Subject: [PATCH 0190/2900] [media] videobuf-dma-contig: use vm_iomap_memory() vm_iomap_memory() provides a better end user interface than remap_pfn_range(), as it does the needed tests before doing mmap. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf-dma-contig.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c index 8204c8810372..65411adcd0ea 100644 --- a/drivers/media/v4l2-core/videobuf-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf-dma-contig.c @@ -305,14 +305,9 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, goto error; /* Try to remap memory */ - size = vma->vm_end - vma->vm_start; - size = (size < mem->size) ? size : mem->size; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - retval = remap_pfn_range(vma, vma->vm_start, - mem->dma_handle >> PAGE_SHIFT, - size, vma->vm_page_prot); + retval = vm_iomap_memory(vma, vma->vm_start, size); if (retval) { dev_err(q->dev, "mmap: remap failed with error %d. ", retval); -- GitLab From b6040f9706c4c81cc50b50855ed70840f022bebb Mon Sep 17 00:00:00 2001 From: chaoting fan Date: Thu, 28 Mar 2013 22:19:45 +0800 Subject: [PATCH 0191/2900] sunrpc: the cache_detail in cache_is_valid is unused any more The cache_detail(*detail) in function cache_is_valid is not used any more. Signed-off-by: fanchaoting Signed-off-by: J. Bruce Fields --- net/sunrpc/cache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 80fe5c86efd1..3b3f14fc02c5 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -201,7 +201,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) return sunrpc_cache_pipe_upcall(cd, h); } -static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) +static inline int cache_is_valid(struct cache_head *h) { if (!test_bit(CACHE_VALID, &h->flags)) return -EAGAIN; @@ -227,7 +227,7 @@ static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h int rv; write_lock(&detail->hash_lock); - rv = cache_is_valid(detail, h); + rv = cache_is_valid(h); if (rv != -EAGAIN) { write_unlock(&detail->hash_lock); return rv; @@ -260,7 +260,7 @@ int cache_check(struct cache_detail *detail, long refresh_age, age; /* First decide return status as best we can */ - rv = cache_is_valid(detail, h); + rv = cache_is_valid(h); /* now see if we want to start an upcall */ refresh_age = (h->expiry_time - h->last_refresh); @@ -293,7 +293,7 @@ int cache_check(struct cache_detail *detail, * Request was not deferred; handle it as best * we can ourselves: */ - rv = cache_is_valid(detail, h); + rv = cache_is_valid(h); if (rv == -EAGAIN) rv = -ETIMEDOUT; } -- GitLab From 1a9357f443d64aa41e9b0dc414953663a6fcca19 Mon Sep 17 00:00:00 2001 From: Jim Rees Date: Fri, 17 May 2013 17:33:00 -0400 Subject: [PATCH 0192/2900] nfsd: avoid undefined signed overflow In C, signed integer overflow results in undefined behavior, but unsigned overflow wraps around. So do the subtraction first, then cast to signed. Reported-by: Joakim Tjernlund Signed-off-by: Jim Rees Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 91ead0ed9f11..72f0c4e9a942 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3427,7 +3427,7 @@ grace_disallows_io(struct net *net, struct inode *inode) /* Returns true iff a is later than b: */ static bool stateid_generation_after(stateid_t *a, stateid_t *b) { - return (s32)a->si_generation - (s32)b->si_generation > 0; + return (s32)(a->si_generation - b->si_generation) > 0; } static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session) -- GitLab From 6a084d6b3dc200b855ae8a3c6771abe285a3835d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 May 2013 11:36:30 -0300 Subject: [PATCH 0193/2900] [media] saa7115: Don't use a dynamic array At least on s390, gcc complains about that: drivers/media/i2c/saa7115.c: In function 'saa711x_detect_chip.constprop.2': drivers/media/i2c/saa7115.c:1647:1: warning: 'saa711x_detect_chip.constprop.2' uses dynamic stack allocation [enabled by default] While for me the above report seems utterly bogus, as the compiler should be optimizing saa711x_detect_chip, merging it with saa711x_detect_chip and changing: char chip_ver[size - 1]; to char chip_ver[16]; because this function is only called on this code snippet: char name[17]; ... ident = saa711x_detect_chip(client, id, name, sizeof(name)); It seems that gcc is not optimizing it, at least on s390. As getting rid of it is easy, let's do it. Reported-by: kbuild test robot Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index be32688797e1..8316ae448f4c 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1602,6 +1602,8 @@ static const struct v4l2_subdev_ops saa711x_ops = { .vbi = &saa711x_vbi_ops, }; +#define CHIP_VER_SIZE 16 + /* ----------------------------------------------------------------------- */ /** @@ -1609,7 +1611,6 @@ static const struct v4l2_subdev_ops saa711x_ops = { * @client: I2C client structure. * @id: I2C device ID structure. * @name: Name of the device to be filled. - * @size: Size of the name var. * * Detects the Philips/NXP saa711x chip, or some clone of it. * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes @@ -1621,9 +1622,9 @@ static const struct v4l2_subdev_ops saa711x_ops = { */ static int saa711x_detect_chip(struct i2c_client *client, const struct i2c_device_id *id, - char *name, unsigned size) + char *name) { - char chip_ver[size - 1]; + char chip_ver[CHIP_VER_SIZE]; char chip_id; int i; int autodetect; @@ -1631,7 +1632,7 @@ static int saa711x_detect_chip(struct i2c_client *client, autodetect = !id || id->driver_data == 1; /* Read the chip version register */ - for (i = 0; i < size - 1; i++) { + for (i = 0; i < CHIP_VER_SIZE; i++) { i2c_smbus_write_byte_data(client, 0, i); chip_ver[i] = i2c_smbus_read_byte_data(client, 0); name[i] = (chip_ver[i] & 0x0f) + '0'; @@ -1643,7 +1644,7 @@ static int saa711x_detect_chip(struct i2c_client *client, /* Check if it is a Philips/NXP chip */ if (!memcmp(name + 1, "f711", 4)) { chip_id = name[5]; - snprintf(name, size, "saa711%c", chip_id); + snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id); if (!autodetect && strcmp(name, id->name)) return -EINVAL; @@ -1651,7 +1652,7 @@ static int saa711x_detect_chip(struct i2c_client *client, switch (chip_id) { case '1': if (chip_ver[0] & 0xf0) { - snprintf(name, size, "saa711%ca", chip_id); + snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id); v4l_info(client, "saa7111a variant found\n"); return V4L2_IDENT_SAA7111A; } @@ -1689,7 +1690,7 @@ static int saa711x_detect_chip(struct i2c_client *client, * the lower nibble is a gm7113c. */ - strlcpy(name, "gm7113c", size); + strlcpy(name, "gm7113c", CHIP_VER_SIZE); if (!autodetect && strcmp(name, id->name)) return -EINVAL; @@ -1714,13 +1715,13 @@ static int saa711x_probe(struct i2c_client *client, struct v4l2_subdev *sd; struct v4l2_ctrl_handler *hdl; int ident; - char name[17]; + char name[CHIP_VER_SIZE + 1]; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - ident = saa711x_detect_chip(client, id, name, sizeof(name)); + ident = saa711x_detect_chip(client, id, name); if (ident == -EINVAL) { /* Chip exists, but doesn't match */ v4l_warn(client, "found %s while %s was expected\n", -- GitLab From 250a51caa65cc7637f3596300d3591a2c924b32e Mon Sep 17 00:00:00 2001 From: Jakob Normark Date: Sun, 19 May 2013 09:30:23 -0300 Subject: [PATCH 0194/2900] [media] Missing break statement added in smsdvb-main.c Fix missing break that so that n_layers are not accidentally incorrect Kernel version: v3.10-rc1 Signed-off-by: Jakob Normark Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smsdvb-main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 297f1b2f9a32..086262252230 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -140,6 +140,7 @@ static void smsdvb_stats_not_ready(struct dvb_frontend *fe) case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: n_layers = 4; + break; default: n_layers = 1; } -- GitLab From 54ca193310bbd33bdf8b2634b6a3115dd8665013 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:29 +0200 Subject: [PATCH 0195/2900] rt2x00: rt2x00dev: use rt2x00dev->tx->limit The TX data queue is initialized already when the rt2x00lib_probe_hw() function is called. Fetch the number of the queue entries from that instead of using the entry_num field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->tx->limit value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 90dc14336980..b2874675186a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1077,7 +1077,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) */ int kfifo_size = roundup_pow_of_two(rt2x00dev->ops->tx_queues * - rt2x00dev->ops->tx->entry_num * + rt2x00dev->tx->limit * sizeof(u32)); status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size, -- GitLab From 98cd6c718c6e782d3b01e3fc3da00cf18c114586 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:30 +0200 Subject: [PATCH 0196/2900] rt2x00: rt61pci: use rt2x00dev->tx->limit The TX data queue is initialized already when the rt61pci_txdone() function is called. Fetch the number of the queue entries from that instead of using the entry_num field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->tx->limit value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0dc8180e251b..7e1759b3e49a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2175,7 +2175,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * that the TX_STA_FIFO stack has a size of 16. We stick to our * tx ring size for now. */ - for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { + for (i = 0; i < rt2x00dev->tx->limit; i++) { rt2x00mmio_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; -- GitLab From 1cfcbe4cd4033ada0e18051b55e7dcab9bde36e3 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:31 +0200 Subject: [PATCH 0197/2900] rt2x00: rt2800pci: use rt2x00dev->tx->limit The TX data queue is initialized already when the rt2800pci_txstatus_interrupt() function is called. Fetch the number of the queue entries from that instead of using the entry_num field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->tx->limit value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 6f4a861af336..330f1d25726d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1014,7 +1014,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) * Since we have only one producer and one consumer we don't * need to lock the kfifo. */ - for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { + for (i = 0; i < rt2x00dev->tx->limit; i++) { rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) -- GitLab From 3a28c8ac15ecbb6ee93f7c35745f75dee1018cd7 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:32 +0200 Subject: [PATCH 0198/2900] rt2x00: rt2800usb: use rt2x00dev->rx->limit The RX data queue is initialized already when the rt2800_usb_enable_radio() function is called. Fetch the number of the queue entries from that instead of using the entry_num field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->rx->limit value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ac854d75bd6c..c71a48da9a31 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -327,7 +327,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) * this limit so reduce the number to prevent errors. */ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, - ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE) + ((rt2x00dev->rx->limit * DATA_FRAME_SIZE) / 1024) - 3); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); -- GitLab From 0879f8750826f53a9fa1a40695bda01830c9a856 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:33 +0200 Subject: [PATCH 0199/2900] rt2x00: rt2800lib: use rt2x00dev->bcn->winfo_size The beacon data queue is initialized already when the rt2800_clear_beacon_register() function is called. Fetch the size of the TXWI descriptor from that instead of using the winfo_size field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->bcn->winfo_size value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b52d70c75e1a..bddfd6dab3cf 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -840,7 +840,7 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, unsigned int beacon_base) { int i; - const int txwi_desc_size = rt2x00dev->ops->bcn->winfo_size; + const int txwi_desc_size = rt2x00dev->bcn->winfo_size; /* * For the Beacon base registers we only need to clear -- GitLab From e9e433032c83b28b3c41470bf91ecf597a78a3fc Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 1 May 2013 17:17:34 +0200 Subject: [PATCH 0200/2900] rt2x00: rt2x00dev: defer operational mode detection Only do it after the queues are allocated. This will allow to use the 'rt2x00dev->bcn->limit' instead of 'rt2x00dev->ops->bcn->entry_num'. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b2874675186a..6a201725bc50 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1300,23 +1300,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] = (rt2x00dev->ops->max_ap_intf - 1); - /* - * Determine which operating modes are supported, all modes - * which require beaconing, depend on the availability of - * beacon entries. - */ - rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - if (rt2x00dev->ops->bcn->entry_num > 0) - rt2x00dev->hw->wiphy->interface_modes |= - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_WDS); - - rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - /* * Initialize work. */ @@ -1347,6 +1330,23 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) if (retval) goto exit; + /* + * Determine which operating modes are supported, all modes + * which require beaconing, depend on the availability of + * beacon entries. + */ + rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + if (rt2x00dev->ops->bcn->entry_num > 0) + rt2x00dev->hw->wiphy->interface_modes |= + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_WDS); + + rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + /* * Initialize ieee80211 structure. */ -- GitLab From 9483f40d8d01918b399b4e24d0c1111db0afffeb Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 7 May 2013 00:28:50 +0200 Subject: [PATCH 0201/2900] rt2x00pci: Use PCI MSIs whenever possible All PCIe devices must support MSIs, make use of them. Signed-off-by: Jakub Kicinski Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index dc49e525ae5e..76d95deb274b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -105,11 +105,13 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) goto exit_release_regions; } + pci_enable_msi(pci_dev); + hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); if (!hw) { rt2x00_probe_err("Failed to allocate hardware\n"); retval = -ENOMEM; - goto exit_release_regions; + goto exit_disable_msi; } pci_set_drvdata(pci_dev, hw); @@ -150,6 +152,9 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops) exit_free_device: ieee80211_free_hw(hw); +exit_disable_msi: + pci_disable_msi(pci_dev); + exit_release_regions: pci_release_regions(pci_dev); @@ -174,6 +179,8 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) rt2x00pci_free_reg(rt2x00dev); ieee80211_free_hw(hw); + pci_disable_msi(pci_dev); + /* * Free the PCI device data. */ -- GitLab From cf657a2bc50dff0191d55fff4e7b31e7a6a542a5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 8 May 2013 05:03:30 +0530 Subject: [PATCH 0202/2900] ath9k: Remove MAC_DEBUG This option has not been enabled by default in any distribution, has never been enabled in OpenWrt and no developer has asked for this information in a bug report. Dumping pages of random values doesn't help debugging, remove this option (along with the vmalloc() abuse). Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Kconfig | 8 - drivers/net/wireless/ath/ath9k/debug.c | 337 ------------------------- drivers/net/wireless/ath/ath9k/debug.h | 20 -- drivers/net/wireless/ath/ath9k/init.c | 3 - drivers/net/wireless/ath/ath9k/link.c | 1 - drivers/net/wireless/ath/ath9k/main.c | 1 - 6 files changed, 370 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 17507dc8a1e7..ec33c8007b29 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -84,14 +84,6 @@ config ATH9K_DFS_CERTIFIED developed. At this point enabling this option won't do anything except increase code size. -config ATH9K_MAC_DEBUG - bool "Atheros MAC statistics" - depends on ATH9K_DEBUGFS - default y - ---help--- - This option enables collection of statistics for Rx/Tx status - data and some other MAC related statistics - config ATH9K_RATE_CONTROL bool "Atheros ath9k rate control" depends on ATH9K diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index e6307b86363a..fc96ad3a135b 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -738,8 +738,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts, struct ath_txq *txq, unsigned int flags) { -#define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\ - [sc->debug.tsidx].c) int qnum = txq->axq_qnum; TX_STAT_INC(qnum, tx_pkts_all); @@ -771,37 +769,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, TX_STAT_INC(qnum, data_underrun); if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) TX_STAT_INC(qnum, delim_underrun); - -#ifdef CONFIG_ATH9K_MAC_DEBUG - spin_lock(&sc->debug.samp_lock); - TX_SAMP_DBG(jiffies) = jiffies; - TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; - TX_SAMP_DBG(rssi_ctl1) = ts->ts_rssi_ctl1; - TX_SAMP_DBG(rssi_ctl2) = ts->ts_rssi_ctl2; - TX_SAMP_DBG(rssi_ext0) = ts->ts_rssi_ext0; - TX_SAMP_DBG(rssi_ext1) = ts->ts_rssi_ext1; - TX_SAMP_DBG(rssi_ext2) = ts->ts_rssi_ext2; - TX_SAMP_DBG(rateindex) = ts->ts_rateindex; - TX_SAMP_DBG(isok) = !!(ts->ts_status & ATH9K_TXERR_MASK); - TX_SAMP_DBG(rts_fail_cnt) = ts->ts_shortretry; - TX_SAMP_DBG(data_fail_cnt) = ts->ts_longretry; - TX_SAMP_DBG(rssi) = ts->ts_rssi; - TX_SAMP_DBG(tid) = ts->tid; - TX_SAMP_DBG(qid) = ts->qid; - - if (ts->ts_flags & ATH9K_TX_BA) { - TX_SAMP_DBG(ba_low) = ts->ba_low; - TX_SAMP_DBG(ba_high) = ts->ba_high; - } else { - TX_SAMP_DBG(ba_low) = 0; - TX_SAMP_DBG(ba_high) = 0; - } - - sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); -#endif - -#undef TX_SAMP_DBG } static const struct file_operations fops_xmit = { @@ -915,8 +882,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) { #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ -#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ - [sc->debug.rsidx].c) RX_STAT_INC(rx_pkts_all); sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen; @@ -940,27 +905,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) RX_PHY_ERR_INC(rs->rs_phyerr); } -#ifdef CONFIG_ATH9K_MAC_DEBUG - spin_lock(&sc->debug.samp_lock); - RX_SAMP_DBG(jiffies) = jiffies; - RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; - RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1; - RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2; - RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0; - RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1; - RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2; - RX_SAMP_DBG(antenna) = rs->rs_antenna; - RX_SAMP_DBG(rssi) = rs->rs_rssi; - RX_SAMP_DBG(rate) = rs->rs_rate; - RX_SAMP_DBG(is_mybeacon) = rs->is_mybeacon; - - sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock(&sc->debug.samp_lock); - -#endif - #undef RX_PHY_ERR_INC -#undef RX_SAMP_DBG } static const struct file_operations fops_recv = { @@ -1485,283 +1430,6 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; -#ifdef CONFIG_ATH9K_MAC_DEBUG - -void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - unsigned long flags; - int i; - - ath9k_ps_wakeup(sc); - - spin_lock_bh(&sc->debug.samp_lock); - - spin_lock_irqsave(&common->cc_lock, flags); - ath_hw_cycle_counters_update(common); - - ATH_SAMP_DBG(cc.cycles) = common->cc_ani.cycles; - ATH_SAMP_DBG(cc.rx_busy) = common->cc_ani.rx_busy; - ATH_SAMP_DBG(cc.rx_frame) = common->cc_ani.rx_frame; - ATH_SAMP_DBG(cc.tx_frame) = common->cc_ani.tx_frame; - spin_unlock_irqrestore(&common->cc_lock, flags); - - ATH_SAMP_DBG(noise) = ah->noise; - - REG_WRITE_D(ah, AR_MACMISC, - ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | - (AR_MACMISC_MISC_OBS_BUS_1 << - AR_MACMISC_MISC_OBS_BUS_MSB_S))); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - ATH_SAMP_DBG(dma_dbg_reg_vals[i]) = REG_READ_D(ah, - AR_DMADBG_0 + (i * sizeof(u32))); - - ATH_SAMP_DBG(pcu_obs) = REG_READ_D(ah, AR_OBS_BUS_1); - ATH_SAMP_DBG(pcu_cr) = REG_READ_D(ah, AR_CR); - - memcpy(ATH_SAMP_DBG(nfCalHist), sc->caldata.nfCalHist, - sizeof(ATH_SAMP_DBG(nfCalHist))); - - sc->debug.sampidx = (sc->debug.sampidx + 1) % ATH_DBG_MAX_SAMPLES; - spin_unlock_bh(&sc->debug.samp_lock); - ath9k_ps_restore(sc); - -#undef ATH_SAMP_DBG -} - -static int open_file_bb_mac_samps(struct inode *inode, struct file *file) -{ -#define ATH_SAMP_DBG(c) bb_mac_samp[sampidx].c - struct ath_softc *sc = inode->i_private; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ieee80211_conf *conf = &common->hw->conf; - struct ath_dbg_bb_mac_samp *bb_mac_samp; - struct ath9k_nfcal_hist *h; - int i, j, qcuOffset = 0, dcuOffset = 0; - u32 *qcuBase, *dcuBase, size = 30000, len = 0; - u32 sampidx = 0; - u8 *buf; - u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; - u8 nread; - - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) - return -EAGAIN; - - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - bb_mac_samp = vmalloc(sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - if (!bb_mac_samp) { - vfree(buf); - return -ENOMEM; - } - /* Account the current state too */ - ath9k_debug_samp_bb_mac(sc); - - spin_lock_bh(&sc->debug.samp_lock); - memcpy(bb_mac_samp, sc->debug.bb_mac_samp, - sizeof(*bb_mac_samp) * ATH_DBG_MAX_SAMPLES); - len += snprintf(buf + len, size - len, - "Current Sample Index: %d\n", sc->debug.sampidx); - spin_unlock_bh(&sc->debug.samp_lock); - - len += snprintf(buf + len, size - len, - "Raw DMA Debug Dump:\n"); - len += snprintf(buf + len, size - len, "Sample |\t"); - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " DMA Reg%d |\t", i); - len += snprintf(buf + len, size - len, "\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - len += snprintf(buf + len, size - len, "%d\t", sampidx); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) - len += snprintf(buf + len, size - len, " %08x\t", - ATH_SAMP_DBG(dma_dbg_reg_vals[i])); - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, "\n"); - - len += snprintf(buf + len, size - len, - "Sample Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - for (i = 0; i < ATH9K_NUM_QUEUES; i++, - qcuOffset += 4, dcuOffset += 5) { - if (i == 8) { - qcuOffset = 0; - qcuBase++; - } - - if (i == 6) { - dcuOffset = 0; - dcuBase++; - } - if (!sc->debug.stats.txstats[i].queued) - continue; - - len += snprintf(buf + len, size - len, - "%4d %7d %2x %1x %2x %2x\n", - sampidx, i, - (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, - (*qcuBase & (0x8 << qcuOffset)) >> - (qcuOffset + 3), - ATH_SAMP_DBG(dma_dbg_reg_vals[2]) & - (0x7 << (i * 3)) >> (i * 3), - (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); - } - len += snprintf(buf + len, size - len, "\n"); - } - len += snprintf(buf + len, size - len, - "samp qcu_sh qcu_fh qcu_comp dcu_comp dcu_arb dcu_fp " - "ch_idle_dur ch_idle_dur_val txfifo_val0 txfifo_val1 " - "txfifo_dcu0 txfifo_dcu1 pcu_obs AR_CR\n"); - - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - qcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[0]); - dcuBase = &ATH_SAMP_DBG(dma_dbg_reg_vals[4]); - - len += snprintf(buf + len, size - len, "%4d %5x %5x ", sampidx, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x003c0000) >> 18, - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x03c00000) >> 22); - len += snprintf(buf + len, size - len, "%7x %8x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[3]) & 0x1c000000) >> 26, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x3)); - len += snprintf(buf + len, size - len, "%7x %7x ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x06000000) >> 25, - (ATH_SAMP_DBG(dma_dbg_reg_vals[5]) & 0x38000000) >> 27); - len += snprintf(buf + len, size - len, "%7d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x000003fc) >> 2, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000400) >> 10); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00000800) >> 11, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x00001000) >> 12); - len += snprintf(buf + len, size - len, "%12d %12d ", - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x0001e000) >> 13, - (ATH_SAMP_DBG(dma_dbg_reg_vals[6]) & 0x001e0000) >> 17); - len += snprintf(buf + len, size - len, "0x%07x 0x%07x\n", - ATH_SAMP_DBG(pcu_obs), ATH_SAMP_DBG(pcu_cr)); - } - - len += snprintf(buf + len, size - len, - "Sample ChNoise Chain privNF #Reading Readings\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - h = ATH_SAMP_DBG(nfCalHist); - if (!ATH_SAMP_DBG(noise)) - continue; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (!(chainmask & (1 << i)) || - ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) - continue; - - nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - - h[i].invalidNFcount; - len += snprintf(buf + len, size - len, - "%4d %5d %4d\t %d\t %d\t", - sampidx, ATH_SAMP_DBG(noise), - i, h[i].privNF, nread); - for (j = 0; j < nread; j++) - len += snprintf(buf + len, size - len, - " %d", h[i].nfCalBuffer[j]); - len += snprintf(buf + len, size - len, "\n"); - } - } - len += snprintf(buf + len, size - len, "\nCycle counters:\n" - "Sample Total Rxbusy Rxframes Txframes\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - if (!ATH_SAMP_DBG(cc.cycles)) - continue; - len += snprintf(buf + len, size - len, - "%4d %08x %08x %08x %08x\n", - sampidx, ATH_SAMP_DBG(cc.cycles), - ATH_SAMP_DBG(cc.rx_busy), - ATH_SAMP_DBG(cc.rx_frame), - ATH_SAMP_DBG(cc.tx_frame)); - } - - len += snprintf(buf + len, size - len, "Tx status Dump :\n"); - len += snprintf(buf + len, size - len, - "Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb " - "isok rts_fail data_fail rate tid qid " - "ba_low ba_high tx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(ts[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%-14d" - "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d " - "%-9d %-4d %-3d %-3d %08x %08x %-11d\n", - sampidx, - ATH_SAMP_DBG(ts[i].rssi_ctl0), - ATH_SAMP_DBG(ts[i].rssi_ctl1), - ATH_SAMP_DBG(ts[i].rssi_ctl2), - ATH_SAMP_DBG(ts[i].rssi_ext0), - ATH_SAMP_DBG(ts[i].rssi_ext1), - ATH_SAMP_DBG(ts[i].rssi_ext2), - ATH_SAMP_DBG(ts[i].rssi), - ATH_SAMP_DBG(ts[i].isok), - ATH_SAMP_DBG(ts[i].rts_fail_cnt), - ATH_SAMP_DBG(ts[i].data_fail_cnt), - ATH_SAMP_DBG(ts[i].rateindex), - ATH_SAMP_DBG(ts[i].tid), - ATH_SAMP_DBG(ts[i].qid), - ATH_SAMP_DBG(ts[i].ba_low), - ATH_SAMP_DBG(ts[i].ba_high), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(ts[i].jiffies))); - } - } - - len += snprintf(buf + len, size - len, "Rx status Dump :\n"); - len += snprintf(buf + len, size - len, "Sample rssi:- ctl0 ctl1 ctl2 " - "ext0 ext1 ext2 comb beacon ant rate rx_before(ms)\n"); - for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) { - for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) { - if (!ATH_SAMP_DBG(rs[i].jiffies)) - continue; - len += snprintf(buf + len, size - len, "%-14d" - "%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n", - sampidx, - ATH_SAMP_DBG(rs[i].rssi_ctl0), - ATH_SAMP_DBG(rs[i].rssi_ctl1), - ATH_SAMP_DBG(rs[i].rssi_ctl2), - ATH_SAMP_DBG(rs[i].rssi_ext0), - ATH_SAMP_DBG(rs[i].rssi_ext1), - ATH_SAMP_DBG(rs[i].rssi_ext2), - ATH_SAMP_DBG(rs[i].rssi), - ATH_SAMP_DBG(rs[i].is_mybeacon) ? - "True" : "False", - ATH_SAMP_DBG(rs[i].antenna), - ATH_SAMP_DBG(rs[i].rate), - jiffies_to_msecs(jiffies - - ATH_SAMP_DBG(rs[i].jiffies))); - } - } - - vfree(bb_mac_samp); - file->private_data = buf; - - return 0; -#undef ATH_SAMP_DBG -} - -static const struct file_operations fops_samps = { - .open = open_file_bb_mac_samps, - .read = ath9k_debugfs_read_buf, - .release = ath9k_debugfs_release_buf, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#endif - #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2087,11 +1755,6 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("spectral_fft_period", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_spectral_fft_period); - -#ifdef CONFIG_ATH9K_MAC_DEBUG - debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, - &fops_samps); -#endif debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 794a7ec83a24..62da19c6f4e0 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -294,13 +294,6 @@ struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; struct ath_stats stats; -#ifdef CONFIG_ATH9K_MAC_DEBUG - spinlock_t samp_lock; - struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; - u8 sampidx; - u8 tsidx; - u8 rsidx; -#endif }; int ath9k_init_debug(struct ath_hw *ah); @@ -359,17 +352,4 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc, #endif /* CONFIG_ATH9K_DEBUGFS */ -#ifdef CONFIG_ATH9K_MAC_DEBUG - -void ath9k_debug_samp_bb_mac(struct ath_softc *sc); - -#else - -static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc) -{ -} - -#endif - - #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0237b2868961..c7b888f22703 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -613,9 +613,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); -#ifdef CONFIG_ATH9K_MAC_DEBUG - spin_lock_init(&sc->debug.samp_lock); -#endif tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, (unsigned long)sc); diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 849259b07370..cc422a4dfa17 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -418,7 +418,6 @@ void ath_ani_calibrate(unsigned long data) longcal ? "long" : "", shortcal ? "short" : "", aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); - ath9k_debug_samp_bb_mac(sc); ath9k_ps_restore(sc); set_timer: diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6963862a1872..1cbfdd4e4a74 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -193,7 +193,6 @@ static bool ath_prepare_reset(struct ath_softc *sc) ath_stop_ani(sc); del_timer_sync(&sc->rx_poll_timer); - ath9k_debug_samp_bb_mac(sc); ath9k_hw_disable_interrupts(ah); if (!ath_drain_all_txq(sc)) -- GitLab From 73900cb068a2948d636feae0c8bc25cc2d568d6d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 8 May 2013 05:03:31 +0530 Subject: [PATCH 0203/2900] ath9k: Use bitops for scan flag Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 +- drivers/net/wireless/ath/ath9k/main.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8a1888d02070..579ed9c40b3f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -646,6 +646,7 @@ enum sc_op_flags { SC_OP_ANI_RUN, SC_OP_PRIM_STA_VIF, SC_OP_HW_RESET, + SC_OP_SCANNING, }; /* Powersave flags */ @@ -759,7 +760,6 @@ struct ath_softc { struct rchan *rfs_chan_spec_scan; enum spectral_mode spectral_mode; struct ath_spec_scan spec_config; - int scanning; #ifdef CONFIG_PM_SLEEP atomic_t wow_got_bmiss_intr; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1cbfdd4e4a74..ec6524aa5178 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1272,7 +1272,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) curchan->center_freq); } else { /* perform spectral scan if requested. */ - if (sc->scanning && + if (test_bit(SC_OP_SCANNING, &sc->sc_flags) && sc->spectral_mode == SPECTRAL_CHANSCAN) ath9k_spectral_scan_trigger(hw); } @@ -2334,15 +2334,13 @@ static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) static void ath9k_sw_scan_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; - - sc->scanning = 1; + set_bit(SC_OP_SCANNING, &sc->sc_flags); } static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; - - sc->scanning = 0; + clear_bit(SC_OP_SCANNING, &sc->sc_flags); } struct ieee80211_ops ath9k_ops = { -- GitLab From 7ca7c776dbc50cf1394dd95e971e7997a4ec025e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 8 May 2013 05:03:32 +0530 Subject: [PATCH 0204/2900] ath9k: Do not use local_bh_disable in ampdu_action This was added during the early conversion of ampdu_action to a sleeping callback. There is no need to do this - instead, use the normal mutex that is acquired for all callbacks. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index ec6524aa5178..e6a30958e944 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1684,7 +1684,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ath_softc *sc = hw->priv; int ret = 0; - local_bh_disable(); + mutex_lock(&sc->mutex); switch (action) { case IEEE80211_AMPDU_RX_START: @@ -1715,7 +1715,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n"); } - local_bh_enable(); + mutex_unlock(&sc->mutex); return ret; } -- GitLab From 594e65b633e0b76db1d8e7359e4efb2d60fba20d Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 8 May 2013 10:16:46 -0700 Subject: [PATCH 0205/2900] ath9k_htc: Add support for mesh interfaces More specifically, enable AP-style beaconing on mesh ifaces and change the hw capabilities to reflect mesh support. Coexistence with a virtual STA interface was tested as working fine. Signed-off-by: Javier Cardona [rebase, add iface combinations] Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 7 +++++ .../net/wireless/ath/ath9k/htc_drv_beacon.c | 5 +++- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 6 ++-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 29 ++++++++++++++----- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index d3b099d7898b..0085e643132f 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -208,6 +208,9 @@ struct ath9k_htc_target_rx_stats { case NL80211_IFTYPE_AP: \ _priv->num_ap_vif++; \ break; \ + case NL80211_IFTYPE_MESH_POINT: \ + _priv->num_mbss_vif++; \ + break; \ default: \ break; \ } \ @@ -224,6 +227,9 @@ struct ath9k_htc_target_rx_stats { case NL80211_IFTYPE_AP: \ _priv->num_ap_vif--; \ break; \ + case NL80211_IFTYPE_MESH_POINT: \ + _priv->num_mbss_vif--; \ + break; \ default: \ break; \ } \ @@ -450,6 +456,7 @@ struct ath9k_htc_priv { u8 sta_slot; u8 vif_sta_pos[ATH9K_HTC_MAX_VIF]; u8 num_ibss_vif; + u8 num_mbss_vif; u8 num_sta_vif; u8 num_sta_assoc_vif; u8 num_ap_vif; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index f13f458dd656..e0c03bd64182 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -28,7 +28,8 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); - if (priv->ah->opmode == NL80211_IFTYPE_AP) { + if (priv->ah->opmode == NL80211_IFTYPE_AP || + priv->ah->opmode == NL80211_IFTYPE_MESH_POINT) { qi.tqi_aifs = 1; qi.tqi_cwmin = 0; qi.tqi_cwmax = 0; @@ -628,6 +629,7 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, case NL80211_IFTYPE_ADHOC: ath9k_htc_beacon_config_adhoc(priv, cur_conf); break; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: ath9k_htc_beacon_config_ap(priv, cur_conf); break; @@ -649,6 +651,7 @@ void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) case NL80211_IFTYPE_ADHOC: ath9k_htc_beacon_config_adhoc(priv, cur_conf); break; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: ath9k_htc_beacon_config_ap(priv, cur_conf); break; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index a47f5e05fc04..6eb41990f608 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -698,7 +698,8 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT) }, { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) }, + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_MESH_POINT) }, }; static const struct ieee80211_iface_combination if_comb = { @@ -728,7 +729,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT); + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_MESH_POINT); hw->wiphy->iface_combinations = &if_comb; hw->wiphy->n_iface_combinations = 1; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 0743a47cef8f..2a67b57c3ecb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -113,7 +113,9 @@ static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) struct ath9k_htc_priv *priv = data; struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon) + if ((vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) && + bss_conf->enable_beacon) priv->reconfig_beacon = true; if (bss_conf->assoc) { @@ -180,6 +182,8 @@ static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv) priv->ah->opmode = NL80211_IFTYPE_ADHOC; else if (priv->num_ap_vif) priv->ah->opmode = NL80211_IFTYPE_AP; + else if (priv->num_mbss_vif) + priv->ah->opmode = NL80211_IFTYPE_MESH_POINT; else priv->ah->opmode = NL80211_IFTYPE_STATION; @@ -1052,6 +1056,9 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, case NL80211_IFTYPE_AP: hvif.opmode = HTC_M_HOSTAP; break; + case NL80211_IFTYPE_MESH_POINT: + hvif.opmode = HTC_M_WDS; /* close enough */ + break; default: ath_err(common, "Interface type %d not yet supported\n", vif->type); @@ -1084,6 +1091,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, INC_VIF(priv, vif->type); if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT) || (vif->type == NL80211_IFTYPE_ADHOC)) ath9k_htc_assign_bslot(priv, vif); @@ -1134,6 +1142,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, DEC_VIF(priv, vif->type); if ((vif->type == NL80211_IFTYPE_AP) || + vif->type == NL80211_IFTYPE_MESH_POINT || (vif->type == NL80211_IFTYPE_ADHOC)) ath9k_htc_remove_bslot(priv, vif); @@ -1525,9 +1534,10 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { /* * Disable SWBA interrupt only if there are no - * AP/IBSS interfaces. + * concurrent AP/mesh or IBSS interfaces. */ - if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) { + if ((priv->num_ap_vif + priv->num_mbss_vif <= 1) || + priv->num_ibss_vif) { ath_dbg(common, CONFIG, "Beacon disabled for BSS: %pM\n", bss_conf->bssid); @@ -1538,12 +1548,15 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BEACON_INT) { /* - * Reset the HW TSF for the first AP interface. + * Reset the HW TSF for the first AP or mesh interface. */ - if ((priv->ah->opmode == NL80211_IFTYPE_AP) && - (priv->nvifs == 1) && - (priv->num_ap_vif == 1) && - (vif->type == NL80211_IFTYPE_AP)) { + if (priv->nvifs == 1 && + ((priv->ah->opmode == NL80211_IFTYPE_AP && + vif->type == NL80211_IFTYPE_AP && + priv->num_ap_vif == 1) || + (priv->ah->opmode == NL80211_IFTYPE_MESH_POINT && + vif->type == NL80211_IFTYPE_MESH_POINT && + priv->num_mbss_vif == 1))) { set_bit(OP_TSF_RESET, &priv->op_flags); } ath_dbg(common, CONFIG, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 6bd0e92ea2aa..e602c9519709 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -887,7 +887,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) if (priv->rxfilter & FIF_PSPOLL) rfilt |= ATH9K_RX_FILTER_PSPOLL; - if (priv->nvifs > 1) + if (priv->nvifs > 1 || priv->rxfilter & FIF_OTHER_BSS) rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; return rfilt; -- GitLab From bd4a85ee8cd6c80d844d0fc52108aebb9b1120c1 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Wed, 8 May 2013 10:16:47 -0700 Subject: [PATCH 0206/2900] ath9k_htc: Claim support for mgmt frame protection Advertise support for management frame protection in hardware. Signed-off-by: Javier Cardona Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 6eb41990f608..59f64367e8ca 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -722,6 +722,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_REPORTS_TX_ACK_STATUS | + IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; hw->wiphy->interface_modes = -- GitLab From 2664d6665f45ef582583d14929dba1170829042e Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Wed, 8 May 2013 10:16:48 -0700 Subject: [PATCH 0207/2900] ath9k: use ap style beaconing for mesh Chun-Yeow and Javier Lopez contributed these changes to make mesh mode use the more similar AP beaconing mode and queue parameters. Should improve PS performance, interface concurrency (AP modes can coexist), and beacon interval stability. AR9271 (ath9k_htc) mesh interfaces also need to be in AP operating mode. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 8 +++++--- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 2ff570f7f8ff..fd1eebab8647 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -39,7 +39,8 @@ static void ath9k_beaconq_config(struct ath_softc *sc) ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { + if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || + sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) { /* Always burst out beacon and CAB traffic. */ qi.tqi_aifs = 1; qi.tqi_cwmin = 0; @@ -273,7 +274,8 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc) u64 tsf; int slot; - if (sc->sc_ah->opmode != NL80211_IFTYPE_AP) { + if (sc->sc_ah->opmode != NL80211_IFTYPE_AP && + sc->sc_ah->opmode != NL80211_IFTYPE_MESH_POINT) { ath_dbg(common, BEACON, "slot 0, tsf: %llu\n", ath9k_hw_gettsf64(sc->sc_ah)); return 0; @@ -765,10 +767,10 @@ void ath9k_set_beacon(struct ath_softc *sc) switch (sc->sc_ah->opmode) { case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_MESH_POINT: ath9k_beacon_config_ap(sc, cur_conf); break; case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: ath9k_beacon_config_adhoc(sc, cur_conf); break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7f25da8444fe..a263ccc00a47 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1245,10 +1245,10 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) switch (opmode) { case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: set |= AR_STA_ID1_ADHOC; REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); break; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: set |= AR_STA_ID1_STA_AP; /* fall through */ @@ -2246,12 +2246,12 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) switch (ah->opmode) { case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: REG_SET_BIT(ah, AR_TXCFG, AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); flags |= AR_NDP_TIMER_EN; + case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - -- GitLab From 7e594444448f221cff66a9309cbfd17430e463a0 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:32 +0300 Subject: [PATCH 0208/2900] wil6210: 'length' in Tx/Rx descriptors is little endian Hardware uses little endian for the Tx/Rx descriptors field 'length', do appropriate conversions Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/debugfs.c | 8 +++++- drivers/net/wireless/ath/wil6210/txrx.c | 33 ++++++++++++++-------- drivers/net/wireless/ath/wil6210/txrx.h | 4 +-- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 727b1f53e6ad..e8308ec30970 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -418,9 +418,15 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) if (skb) { unsigned char printbuf[16 * 3 + 2]; int i = 0; - int len = skb_headlen(skb); + int len = le16_to_cpu(d->dma.length); void *p = skb->data; + if (len != skb_headlen(skb)) { + seq_printf(s, "!!! len: desc = %d skb = %d\n", + len, skb_headlen(skb)); + len = min_t(int, len, skb_headlen(skb)); + } + seq_printf(s, " len = %d\n", len); while (i < len) { diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 797024507c71..6a20f0a18622 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -106,19 +106,21 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, size_t sz = vring->size * sizeof(vring->va[0]); while (!wil_vring_is_empty(vring)) { + u16 dmalen; if (tx) { volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; dma_addr_t pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); struct sk_buff *skb = vring->ctx[vring->swtail]; + dmalen = le16_to_cpu(d->dma.length); if (skb) { - dma_unmap_single(dev, pa, d->dma.length, + dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); dev_kfree_skb_any(skb); vring->ctx[vring->swtail] = NULL; } else { - dma_unmap_page(dev, pa, d->dma.length, + dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); } vring->swtail = wil_vring_next_tail(vring); @@ -128,8 +130,8 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, dma_addr_t pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); struct sk_buff *skb = vring->ctx[vring->swhead]; - dma_unmap_single(dev, pa, d->dma.length, - DMA_FROM_DEVICE); + dmalen = le16_to_cpu(d->dma.length); + dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); kfree_skb(skb); wil_vring_advance_head(vring, 1); } @@ -175,7 +177,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, /* b11 don't care */ /* error don't care */ d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ - d->dma.length = sz; + d->dma.length = cpu_to_le16(sz); vring->ctx[i] = skb; return 0; @@ -326,6 +328,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, struct sk_buff *skb; dma_addr_t pa; unsigned int sz = RX_BUF_LEN; + u16 dmalen; u8 ftype; u8 ds_bits; @@ -343,10 +346,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); skb = vring->ctx[vring->swhead]; dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); - skb_trim(skb, d->dma.length); d1 = wil_skb_rxdesc(skb); *d1 = *d; + dmalen = le16_to_cpu(d1->dma.length); + skb_trim(skb, dmalen); wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1); @@ -610,7 +614,7 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d, d->dma.b11 = 0/*14 | BIT(7)*/; d->dma.error = 0; d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ - d->dma.length = len; + d->dma.length = cpu_to_le16((u16)len); d->dma.d0 = 0; d->mac.d[0] = 0; d->mac.d[1] = 0; @@ -705,14 +709,17 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, /* unmap what we have mapped */ /* Note: increment @f to operate with positive index */ for (f++; f > 0; f--) { + u16 dmalen; + i = (swhead + f) % vring->size; d = &(vring->va[i].tx); d->dma.status = TX_DMA_STATUS_DU; pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + dmalen = le16_to_cpu(d->dma.length); if (vring->ctx[i]) - dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); + dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); else - dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); + dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); } return -EINVAL; @@ -792,15 +799,17 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) struct vring_tx_desc dd, *d = ⅆ dma_addr_t pa; struct sk_buff *skb; + u16 dmalen; dd = *d1; if (!(d->dma.status & TX_DMA_STATUS_DU)) break; + dmalen = le16_to_cpu(d->dma.length); wil_dbg_txrx(wil, "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", - vring->swtail, d->dma.length, d->dma.status, + vring->swtail, dmalen, d->dma.status, d->dma.error); wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); @@ -815,11 +824,11 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) ndev->stats.tx_errors++; } - dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); + dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); dev_kfree_skb_any(skb); vring->ctx[vring->swtail] = NULL; } else { - dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); + dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); } d->dma.addr_low = 0; d->dma.addr_high = 0; diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index adef12fb2aee..a40aa0bb8b94 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -222,7 +222,7 @@ struct vring_tx_dma { u8 b11; /* 0..6: mac_length; 7:ip_version */ u8 error; /* 0..2: err; 3..7: reserved; */ u8 status; /* 0: used; 1..7; reserved */ - u16 length; + __le16 length; } __packed; /* @@ -321,7 +321,7 @@ struct vring_rx_dma { u8 b11; u8 error; u8 status; - u16 length; + __le16 length; } __packed; struct vring_tx_desc { -- GitLab From e270045b569cc7030abd29857f3a4e7906524ec0 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:33 +0300 Subject: [PATCH 0209/2900] wil6210: Sanity check for reported DMA length If Rx descriptor contains garbage, it is possible to access memory beyond allocated buffer. Check this condition and drop Rx if reported length is unreasonable large Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 6a20f0a18622..92f18215014c 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -349,7 +349,13 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, d1 = wil_skb_rxdesc(skb); *d1 = *d; + wil_vring_advance_head(vring, 1); dmalen = le16_to_cpu(d1->dma.length); + if (dmalen > sz) { + wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); + kfree(skb); + return NULL; + } skb_trim(skb, dmalen); wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1); @@ -362,8 +368,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); - wil_vring_advance_head(vring, 1); - /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; -- GitLab From c0d37713607de33412a3bbf8ad699d2934427696 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:34 +0300 Subject: [PATCH 0210/2900] wil6210: debug dump packet content right after DMA Move packet dump to the earliest location where it is known to have valid data. Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 92f18215014c..eb90be070e50 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -358,6 +358,10 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, } skb_trim(skb, dmalen); + wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, skb_headlen(skb), false); + + wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1); /* use radiotap header only if required */ @@ -472,8 +476,6 @@ void wil_rx_handle(struct wil6210_priv *wil) } wil_dbg_txrx(wil, "%s()\n", __func__); while (NULL != (skb = wil_vring_reap_rx(wil, v))) { - wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, - skb->data, skb_headlen(skb), false); if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { skb->dev = ndev; -- GitLab From 98658095623109bdace46f21bece028c904fb900 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:35 +0300 Subject: [PATCH 0211/2900] wil6210: trace support Trace the following: - WMI cmd/event - log events - interrupts - Tx/Rx Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/Kconfig | 12 + drivers/net/wireless/ath/wil6210/Makefile | 21 +- drivers/net/wireless/ath/wil6210/debug.c | 69 ++++++ drivers/net/wireless/ath/wil6210/interrupt.c | 6 + drivers/net/wireless/ath/wil6210/trace.c | 20 ++ drivers/net/wireless/ath/wil6210/trace.h | 235 +++++++++++++++++++ drivers/net/wireless/ath/wil6210/txrx.c | 10 +- drivers/net/wireless/ath/wil6210/wil6210.h | 10 +- drivers/net/wireless/ath/wil6210/wmi.c | 8 +- 9 files changed, 376 insertions(+), 15 deletions(-) create mode 100644 drivers/net/wireless/ath/wil6210/debug.c create mode 100644 drivers/net/wireless/ath/wil6210/trace.c create mode 100644 drivers/net/wireless/ath/wil6210/trace.h diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index bac3d98a0cfb..5644ac54facc 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -27,3 +27,15 @@ config WIL6210_ISR_COR self-clear when accessed for debug purposes, it makes such monitoring impossible. Say y unless you debug interrupts + +config ATH6KL_TRACING + bool "wil6210 tracing support" + depends on WIL6210 + depends on EVENT_TRACING + default y + ---help--- + Say Y here to enable tracepoints for the wil6210 driver + using the kernel tracing infrastructure. Select this + option if you are interested in debugging the driver. + + If unsure, say Y to make it easier to debug problems. diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index d288eea0a26a..f891d514d881 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile @@ -1,15 +1,20 @@ obj-$(CONFIG_WIL6210) += wil6210.o -wil6210-objs := main.o -wil6210-objs += netdev.o -wil6210-objs += cfg80211.o -wil6210-objs += pcie_bus.o -wil6210-objs += debugfs.o -wil6210-objs += wmi.o -wil6210-objs += interrupt.o -wil6210-objs += txrx.o +wil6210-y := main.o +wil6210-y += netdev.o +wil6210-y += cfg80211.o +wil6210-y += pcie_bus.o +wil6210-y += debugfs.o +wil6210-y += wmi.o +wil6210-y += interrupt.o +wil6210-y += txrx.o +wil6210-y += debug.o +wil6210-$(CONFIG_WIL6210_TRACING) += trace.o ifeq (, $(findstring -W,$(EXTRA_CFLAGS))) subdir-ccflags-y += -Werror endif +# for tracing framework to find trace.h +CFLAGS_trace.o := -I$(src) + subdir-ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c new file mode 100644 index 000000000000..9eeabf4a5879 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/debug.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "wil6210.h" +#include "trace.h" + +int wil_err(struct wil6210_priv *wil, const char *fmt, ...) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = netdev_err(ndev, "%pV", &vaf); + trace_wil6210_log_err(&vaf); + va_end(args); + + return ret; +} + +int wil_info(struct wil6210_priv *wil, const char *fmt, ...) +{ + struct net_device *ndev = wil_to_ndev(wil); + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = netdev_info(ndev, "%pV", &vaf); + trace_wil6210_log_info(&vaf); + va_end(args); + + return ret; +} + +int wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + + va_start(args, fmt); + vaf.va = &args; + trace_wil6210_log_dbg(&vaf); + va_end(args); + + return 0; +} diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index e3c1e7684f9c..5fe985cd3dfd 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -17,6 +17,7 @@ #include #include "wil6210.h" +#include "trace.h" /** * Theory of operation: @@ -168,6 +169,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) HOSTADDR(RGF_DMA_EP_RX_ICR) + offsetof(struct RGF_ICR, ICR)); + trace_wil6210_irq_rx(isr); wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr); if (!isr) { @@ -198,6 +200,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) HOSTADDR(RGF_DMA_EP_TX_ICR) + offsetof(struct RGF_ICR, ICR)); + trace_wil6210_irq_tx(isr); wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr); if (!isr) { @@ -256,6 +259,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) HOSTADDR(RGF_DMA_EP_MISC_ICR) + offsetof(struct RGF_ICR, ICR)); + trace_wil6210_irq_misc(isr); wil_dbg_irq(wil, "ISR MISC 0x%08x\n", isr); if (!isr) { @@ -301,6 +305,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) struct wil6210_priv *wil = cookie; u32 isr = wil->isr_misc; + trace_wil6210_irq_misc_thread(isr); wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); if (isr & ISR_MISC_FW_ERROR) { @@ -408,6 +413,7 @@ static irqreturn_t wil6210_hardirq(int irq, void *cookie) if (wil6210_debug_irq_mask(wil, pseudo_cause)) return IRQ_NONE; + trace_wil6210_irq_pseudo(pseudo_cause); wil_dbg_irq(wil, "Pseudo IRQ 0x%08x\n", pseudo_cause); wil6210_mask_irq_pseudo(wil); diff --git a/drivers/net/wireless/ath/wil6210/trace.c b/drivers/net/wireless/ath/wil6210/trace.c new file mode 100644 index 000000000000..cd2534b9c5aa --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/trace.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h new file mode 100644 index 000000000000..eff1239be53a --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/trace.h @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM wil6210 +#if !defined(WIL6210_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define WIL6210_TRACE_H + +#include +#include "wil6210.h" +#include "txrx.h" + +/* create empty functions when tracing is disabled */ +#if !defined(CONFIG_WIL6210_TRACING) || defined(__CHECKER__) + +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#undef DECLARE_EVENT_CLASS +#define DECLARE_EVENT_CLASS(...) +#undef DEFINE_EVENT +#define DEFINE_EVENT(evt_class, name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif /* !CONFIG_WIL6210_TRACING || defined(__CHECKER__) */ + +DECLARE_EVENT_CLASS(wil6210_wmi, + TP_PROTO(u16 id, void *buf, u16 buf_len), + + TP_ARGS(id, buf, buf_len), + + TP_STRUCT__entry( + __field(u16, id) + __field(u16, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "id 0x%04x len %d", + __entry->id, __entry->buf_len + ) +); + +DEFINE_EVENT(wil6210_wmi, wil6210_wmi_cmd, + TP_PROTO(u16 id, void *buf, u16 buf_len), + TP_ARGS(id, buf, buf_len) +); + +DEFINE_EVENT(wil6210_wmi, wil6210_wmi_event, + TP_PROTO(u16 id, void *buf, u16 buf_len), + TP_ARGS(id, buf, buf_len) +); + +#define WIL6210_MSG_MAX (200) + +DECLARE_EVENT_CLASS(wil6210_log_event, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf), + TP_STRUCT__entry( + __dynamic_array(char, msg, WIL6210_MSG_MAX) + ), + TP_fast_assign( + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + WIL6210_MSG_MAX, + vaf->fmt, + *vaf->va) >= WIL6210_MSG_MAX); + ), + TP_printk("%s", __get_str(msg)) +); + +DEFINE_EVENT(wil6210_log_event, wil6210_log_err, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(wil6210_log_event, wil6210_log_info, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(wil6210_log_event, wil6210_log_dbg, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +#define wil_pseudo_irq_cause(x) __print_flags(x, "|", \ + {BIT_DMA_PSEUDO_CAUSE_RX, "Rx" }, \ + {BIT_DMA_PSEUDO_CAUSE_TX, "Tx" }, \ + {BIT_DMA_PSEUDO_CAUSE_MISC, "Misc" }) + +TRACE_EVENT(wil6210_irq_pseudo, + TP_PROTO(u32 x), + TP_ARGS(x), + TP_STRUCT__entry( + __field(u32, x) + ), + TP_fast_assign( + __entry->x = x; + ), + TP_printk("cause 0x%08x : %s", __entry->x, + wil_pseudo_irq_cause(__entry->x)) +); + +DECLARE_EVENT_CLASS(wil6210_irq, + TP_PROTO(u32 x), + TP_ARGS(x), + TP_STRUCT__entry( + __field(u32, x) + ), + TP_fast_assign( + __entry->x = x; + ), + TP_printk("cause 0x%08x", __entry->x) +); + +DEFINE_EVENT(wil6210_irq, wil6210_irq_rx, + TP_PROTO(u32 x), + TP_ARGS(x) +); + +DEFINE_EVENT(wil6210_irq, wil6210_irq_tx, + TP_PROTO(u32 x), + TP_ARGS(x) +); + +DEFINE_EVENT(wil6210_irq, wil6210_irq_misc, + TP_PROTO(u32 x), + TP_ARGS(x) +); + +DEFINE_EVENT(wil6210_irq, wil6210_irq_misc_thread, + TP_PROTO(u32 x), + TP_ARGS(x) +); + +TRACE_EVENT(wil6210_rx, + TP_PROTO(u16 index, struct vring_rx_desc *d), + TP_ARGS(index, d), + TP_STRUCT__entry( + __field(u16, index) + __field(unsigned int, len) + __field(u8, mid) + __field(u8, cid) + __field(u8, tid) + __field(u8, type) + __field(u8, subtype) + __field(u16, seq) + __field(u8, mcs) + ), + TP_fast_assign( + __entry->index = index; + __entry->len = d->dma.length; + __entry->mid = wil_rxdesc_mid(d); + __entry->cid = wil_rxdesc_cid(d); + __entry->tid = wil_rxdesc_tid(d); + __entry->type = wil_rxdesc_ftype(d); + __entry->subtype = wil_rxdesc_subtype(d); + __entry->seq = wil_rxdesc_seq(d); + __entry->mcs = wil_rxdesc_mcs(d); + ), + TP_printk("index %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x" + " type 0x%1x subtype 0x%1x", __entry->index, __entry->len, + __entry->mid, __entry->cid, __entry->tid, __entry->mcs, + __entry->seq, __entry->type, __entry->subtype) +); + +TRACE_EVENT(wil6210_tx, + TP_PROTO(u8 vring, u16 index, unsigned int len, u8 frags), + TP_ARGS(vring, index, len, frags), + TP_STRUCT__entry( + __field(u8, vring) + __field(u8, frags) + __field(u16, index) + __field(unsigned int, len) + ), + TP_fast_assign( + __entry->vring = vring; + __entry->frags = frags; + __entry->index = index; + __entry->len = len; + ), + TP_printk("vring %d index %d len %d frags %d", + __entry->vring, __entry->index, __entry->len, __entry->frags) +); + +TRACE_EVENT(wil6210_tx_done, + TP_PROTO(u8 vring, u16 index, unsigned int len, u8 err), + TP_ARGS(vring, index, len, err), + TP_STRUCT__entry( + __field(u8, vring) + __field(u8, err) + __field(u16, index) + __field(unsigned int, len) + ), + TP_fast_assign( + __entry->vring = vring; + __entry->index = index; + __entry->len = len; + __entry->err = err; + ), + TP_printk("vring %d index %d len %d err 0x%02x", + __entry->vring, __entry->index, __entry->len, + __entry->err) +); + +#endif /* WIL6210_TRACE_H || TRACE_HEADER_MULTI_READ*/ + +#if defined(CONFIG_WIL6210_TRACING) && !defined(__CHECKER__) +/* we don't want to use include/trace/events */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +/* This part must be outside protection */ +#include +#endif /* defined(CONFIG_WIL6210_TRACING) && !defined(__CHECKER__) */ diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index eb90be070e50..dc183d573c08 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -22,6 +22,7 @@ #include "wil6210.h" #include "wmi.h" #include "txrx.h" +#include "trace.h" static bool rtap_include_phy_info; module_param(rtap_include_phy_info, bool, S_IRUGO); @@ -368,9 +369,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) wil_rx_add_radiotap_header(wil, skb); - wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); + trace_wil6210_rx(vring->swhead, d1); + wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, + d1->dma.length); wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, - (const void *)d, sizeof(*d), false); + (const void *)d1, sizeof(*d1), false); /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) @@ -703,6 +706,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, /* advance swhead */ wil_vring_advance_head(vring, nr_frags + 1); wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); + trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); /* hold reference to skb * to prevent skb release before accounting @@ -813,6 +817,8 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) break; dmalen = le16_to_cpu(d->dma.length); + trace_wil6210_tx_done(ringid, vring->swtail, dmalen, + d->dma.error); wil_dbg_txrx(wil, "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", vring->swtail, dmalen, d->dma.status, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 8f76ecd8a7e5..484446e66c5a 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -267,9 +267,13 @@ struct wil6210_priv { #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) -#define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) -#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) -#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) +int wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); +int wil_err(struct wil6210_priv *wil, const char *fmt, ...); +int wil_info(struct wil6210_priv *wil, const char *fmt, ...); +#define wil_dbg(wil, fmt, arg...) do { \ + netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ + wil_dbg_trace(wil, fmt, ##arg); \ +} while (0) #define wil_dbg_irq(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) #define wil_dbg_txrx(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 45b04e383f9a..5e01f4ee4de7 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -20,6 +20,7 @@ #include "wil6210.h" #include "txrx.h" #include "wmi.h" +#include "trace.h" /** * WMI event receiving - theory of operations @@ -246,6 +247,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) iowrite32(r->head = next_head, wil->csr + HOST_MBOX + offsetof(struct wil6210_mbox_ctl, tx.head)); + trace_wil6210_wmi_cmd(cmdid, buf, len); + /* interrupt to FW */ iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); @@ -635,8 +638,9 @@ void wmi_recv_cmd(struct wil6210_priv *wil) hdr.flags); if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { - wil_dbg_wmi(wil, "WMI event 0x%04x\n", - evt->event.wmi.id); + u16 id = le16_to_cpu(evt->event.wmi.id); + wil_dbg_wmi(wil, "WMI event 0x%04x\n", id); + trace_wil6210_wmi_event(id, &evt->event.wmi, len); } wil_hex_dump_wmi("evt ", DUMP_PREFIX_OFFSET, 16, 1, &evt->event.hdr, sizeof(hdr) + len, true); -- GitLab From e0287c4ab87905dd4a2e45cf791f8e0a87fe602e Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:36 +0300 Subject: [PATCH 0212/2900] wil6210: use NAPI Introduce NAPI for Rx and Tx completion. This fixes packet reordering that happens when Rx handled right in the IRQ: netif_rx puts packet in 'percpu' queue, then network stack fetches packets from 'percpu' queues for processing, with different pattern of queue switching. As result, network stack see packets in different order. This causes hard to understand TCP throughput degradation in about 30min Complete polling if only one packet was processed - this eliminates empty polls that would be otherwise done at the end of each burst Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/interrupt.c | 23 ++++----- drivers/net/wireless/ath/wil6210/main.c | 6 +++ drivers/net/wireless/ath/wil6210/netdev.c | 54 ++++++++++++++++++++ drivers/net/wireless/ath/wil6210/txrx.c | 23 +++++---- drivers/net/wireless/ath/wil6210/wil6210.h | 16 ++++-- 5 files changed, 94 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 5fe985cd3dfd..8205d3e4ab66 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -104,14 +104,14 @@ static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) clear_bit(wil_status_irqen, &wil->status); } -static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) +void wil6210_unmask_irq_tx(struct wil6210_priv *wil) { iowrite32(WIL6210_IMC_TX, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + offsetof(struct RGF_ICR, IMC)); } -static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) +void wil6210_unmask_irq_rx(struct wil6210_priv *wil) { iowrite32(WIL6210_IMC_RX, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + @@ -182,13 +182,14 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { wil_dbg_irq(wil, "RX done\n"); isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; - wil_rx_handle(wil); + wil_dbg_txrx(wil, "NAPI schedule\n"); + napi_schedule(&wil->napi_rx); } if (isr) wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); - wil6210_unmask_irq_rx(wil); + /* Rx IRQ will be enabled when NAPI processing finished */ return IRQ_HANDLED; } @@ -211,23 +212,17 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) wil6210_mask_irq_tx(wil); if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { - uint i; wil_dbg_irq(wil, "TX done\n"); + napi_schedule(&wil->napi_tx); isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; - for (i = 0; i < 24; i++) { - u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); - if (isr & mask) { - isr &= ~mask; - wil_dbg_irq(wil, "TX done(%i)\n", i); - wil_tx_complete(wil, i); - } - } + /* clear also all VRING interrupts */ + isr &= ~(BIT(25) - 1UL); } if (isr) wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); - wil6210_unmask_irq_tx(wil); + /* Tx IRQ will be enabled when NAPI processing finished */ return IRQ_HANDLED; } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index a0478e2f6868..ea49c8a18e15 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -365,6 +365,9 @@ static int __wil_up(struct wil6210_priv *wil) /* Rx VRING. After MAC and beacon */ wil_rx_init(wil); + napi_enable(&wil->napi_rx); + napi_enable(&wil->napi_tx); + return 0; } @@ -381,6 +384,9 @@ int wil_up(struct wil6210_priv *wil) static int __wil_down(struct wil6210_priv *wil) { + napi_disable(&wil->napi_rx); + napi_disable(&wil->napi_tx); + if (wil->scan_request) { cfg80211_scan_done(wil->scan_request, true); wil->scan_request = NULL; diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 098a8ec6b841..29dd1e58cb17 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -40,6 +40,55 @@ static const struct net_device_ops wil_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; +static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) +{ + struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, + napi_rx); + int quota = budget; + int done; + + wil_rx_handle(wil, "a); + done = budget - quota; + + if (done <= 1) { /* burst ends - only one packet processed */ + napi_complete(napi); + wil6210_unmask_irq_rx(wil); + wil_dbg_txrx(wil, "NAPI RX complete\n"); + } + + wil_dbg_txrx(wil, "NAPI RX poll(%d) done %d\n", budget, done); + + return done; +} + +static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) +{ + struct wil6210_priv *wil = container_of(napi, struct wil6210_priv, + napi_tx); + int tx_done = 0; + uint i; + + /* always process ALL Tx complete, regardless budget - it is fast */ + for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { + struct vring *vring = &wil->vring_tx[i]; + + if (!vring->va) + continue; + + tx_done += wil_tx_complete(wil, i); + } + + if (tx_done <= 1) { /* burst ends - only one packet processed */ + napi_complete(napi); + wil6210_unmask_irq_tx(wil); + wil_dbg_txrx(wil, "NAPI TX complete\n"); + } + + wil_dbg_txrx(wil, "NAPI TX poll(%d) done %d\n", budget, tx_done); + + return min(tx_done, budget); +} + void *wil_if_alloc(struct device *dev, void __iomem *csr) { struct net_device *ndev; @@ -81,6 +130,11 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr) SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; + netif_napi_add(ndev, &wil->napi_rx, wil6210_netdev_poll_rx, + WIL6210_NAPI_BUDGET); + netif_napi_add(ndev, &wil->napi_tx, wil6210_netdev_poll_tx, + WIL6210_NAPI_BUDGET); + wil_link_off(wil); return wil; diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index dc183d573c08..bab50117383a 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -440,6 +440,7 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) /* * Pass Rx packet to the netif. Update statistics. + * Called in softirq context (NAPI poll). */ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) { @@ -448,10 +449,7 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) skb_orphan(skb); - if (in_interrupt()) - rc = netif_rx(skb); - else - rc = netif_rx_ni(skb); + rc = netif_receive_skb(skb); if (likely(rc == NET_RX_SUCCESS)) { ndev->stats.rx_packets++; @@ -465,9 +463,9 @@ static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) /** * Proceed all completed skb's from Rx VRING * - * Safe to call from IRQ + * Safe to call from NAPI poll, i.e. softirq with interrupts enabled */ -void wil_rx_handle(struct wil6210_priv *wil) +void wil_rx_handle(struct wil6210_priv *wil, int *quota) { struct net_device *ndev = wil_to_ndev(wil); struct vring *v = &wil->vring_rx; @@ -478,7 +476,8 @@ void wil_rx_handle(struct wil6210_priv *wil) return; } wil_dbg_txrx(wil, "%s()\n", __func__); - while (NULL != (skb = wil_vring_reap_rx(wil, v))) { + while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { + (*quota)--; if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { skb->dev = ndev; @@ -788,17 +787,20 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) /** * Clean up transmitted skb's from the Tx VRING * + * Return number of descriptors cleared + * * Safe to call from IRQ */ -void wil_tx_complete(struct wil6210_priv *wil, int ringid) +int wil_tx_complete(struct wil6210_priv *wil, int ringid) { struct net_device *ndev = wil_to_ndev(wil); struct device *dev = wil_to_dev(wil); struct vring *vring = &wil->vring_tx[ringid]; + int done = 0; if (!vring->va) { wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); - return; + return 0; } wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); @@ -847,7 +849,10 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid) d->dma.length = 0; d->dma.status = TX_DMA_STATUS_DU; vring->swtail = wil_vring_next_tail(vring); + done++; } if (wil_vring_avail_tx(vring) > vring->size/4) netif_tx_wake_all_queues(wil_to_ndev(wil)); + + return done; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 484446e66c5a..2e3c26e1c975 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -34,9 +34,11 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL6210_MEM_SIZE (2*1024*1024UL) -#define WIL6210_RX_RING_SIZE (128) -#define WIL6210_TX_RING_SIZE (128) -#define WIL6210_MAX_TX_RINGS (24) +#define WIL6210_RX_RING_SIZE (128) +#define WIL6210_TX_RING_SIZE (128) +#define WIL6210_MAX_TX_RINGS (24) /* HW limit */ +#define WIL6210_MAX_CID (8) /* HW limit */ +#define WIL6210_NAPI_BUDGET (16) /* arbitrary */ /* Hardware definitions begin */ @@ -239,6 +241,8 @@ struct wil6210_priv { * - consumed in thread by wmi_event_worker */ spinlock_t wmi_ev_lock; + struct napi_struct napi_rx; + struct napi_struct napi_tx; /* DMA related */ struct vring vring_rx; struct vring vring_tx[WIL6210_MAX_TX_RINGS]; @@ -360,10 +364,12 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, void wil_vring_fini_tx(struct wil6210_priv *wil, int id); netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); -void wil_tx_complete(struct wil6210_priv *wil, int ringid); +int wil_tx_complete(struct wil6210_priv *wil, int ringid); +void wil6210_unmask_irq_tx(struct wil6210_priv *wil); /* RX API */ -void wil_rx_handle(struct wil6210_priv *wil); +void wil_rx_handle(struct wil6210_priv *wil, int *quota); +void wil6210_unmask_irq_rx(struct wil6210_priv *wil); int wil_iftype_nl2wmi(enum nl80211_iftype type); -- GitLab From 68ada71e33e7b79f2ce7c6fff5564750a225234a Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:37 +0300 Subject: [PATCH 0213/2900] wil6210: fix remaining use of non-cached copy of tx/rx descriptors - Introduce common code for Tx/Rx descriptor physical address set/parse - Fix endianness for address fields - consistent descriptor naming: '_d' for non-cached memory, 'd' for cached copy - wil_tx_desc_map now modify cached copy, no need for 'volatile' Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 106 ++++++++++++++---------- drivers/net/wireless/ath/wil6210/txrx.h | 28 ++++++- 2 files changed, 84 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index bab50117383a..561314830f21 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -90,8 +90,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) * we can use any */ for (i = 0; i < vring->size; i++) { - volatile struct vring_tx_desc *d = &(vring->va[i].tx); - d->dma.status = TX_DMA_STATUS_DU; + volatile struct vring_tx_desc *_d = &(vring->va[i].tx); + _d->dma.status = TX_DMA_STATUS_DU; } wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, @@ -107,14 +107,19 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, size_t sz = vring->size * sizeof(vring->va[0]); while (!wil_vring_is_empty(vring)) { + dma_addr_t pa; + struct sk_buff *skb; u16 dmalen; + if (tx) { - volatile struct vring_tx_desc *d = + struct vring_tx_desc dd, *d = ⅆ + volatile struct vring_tx_desc *_d = &vring->va[vring->swtail].tx; - dma_addr_t pa = d->dma.addr_low | - ((u64)d->dma.addr_high << 32); - struct sk_buff *skb = vring->ctx[vring->swtail]; + + *d = *_d; + pa = wil_desc_addr(&d->dma.addr); dmalen = le16_to_cpu(d->dma.length); + skb = vring->ctx[vring->swtail]; if (skb) { dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); @@ -126,12 +131,14 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, } vring->swtail = wil_vring_next_tail(vring); } else { /* rx */ - volatile struct vring_rx_desc *d = + struct vring_rx_desc dd, *d = ⅆ + volatile struct vring_rx_desc *_d = &vring->va[vring->swtail].rx; - dma_addr_t pa = d->dma.addr_low | - ((u64)d->dma.addr_high << 32); - struct sk_buff *skb = vring->ctx[vring->swhead]; + + *d = *_d; + pa = wil_desc_addr(&d->dma.addr); dmalen = le16_to_cpu(d->dma.length); + skb = vring->ctx[vring->swhead]; dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); kfree_skb(skb); wil_vring_advance_head(vring, 1); @@ -154,7 +161,8 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, { struct device *dev = wil_to_dev(wil); unsigned int sz = RX_BUF_LEN; - volatile struct vring_rx_desc *d = &(vring->va[i].rx); + struct vring_rx_desc dd, *d = ⅆ + volatile struct vring_rx_desc *_d = &(vring->va[i].rx); dma_addr_t pa; /* TODO align */ @@ -172,13 +180,13 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, } d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; - d->dma.addr_low = lower_32_bits(pa); - d->dma.addr_high = (u16)upper_32_bits(pa); + wil_desc_addr_set(&d->dma.addr, pa); /* ip_length don't care */ /* b11 don't care */ /* error don't care */ d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ d->dma.length = cpu_to_le16(sz); + *_d = *d; vring->ctx[i] = skb; return 0; @@ -324,8 +332,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, { struct device *dev = wil_to_dev(wil); struct net_device *ndev = wil_to_ndev(wil); - volatile struct vring_rx_desc *d; - struct vring_rx_desc *d1; + volatile struct vring_rx_desc *_d; + struct vring_rx_desc *d; struct sk_buff *skb; dma_addr_t pa; unsigned int sz = RX_BUF_LEN; @@ -338,20 +346,27 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, if (wil_vring_is_empty(vring)) return NULL; - d = &(vring->va[vring->swhead].rx); - if (!(d->dma.status & RX_DMA_STATUS_DU)) { + _d = &(vring->va[vring->swhead].rx); + if (!(_d->dma.status & RX_DMA_STATUS_DU)) { /* it is not error, we just reached end of Rx done area */ return NULL; } - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); skb = vring->ctx[vring->swhead]; + d = wil_skb_rxdesc(skb); + *d = *_d; + pa = wil_desc_addr(&d->dma.addr); + vring->ctx[vring->swhead] = NULL; + wil_vring_advance_head(vring, 1); + dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); + dmalen = le16_to_cpu(d->dma.length); + + trace_wil6210_rx(vring->swhead, d); + wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, dmalen); + wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); - d1 = wil_skb_rxdesc(skb); - *d1 = *d; - wil_vring_advance_head(vring, 1); - dmalen = le16_to_cpu(d1->dma.length); if (dmalen > sz) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); kfree(skb); @@ -363,18 +378,12 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, skb->data, skb_headlen(skb), false); - wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1); + wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); /* use radiotap header only if required */ if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) wil_rx_add_radiotap_header(wil, skb); - trace_wil6210_rx(vring->swhead, d1); - wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, - d1->dma.length); - wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, - (const void *)d1, sizeof(*d1), false); - /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; @@ -383,7 +392,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, * Driver should recognize it by frame type, that is found * in Rx descriptor. If type is not data, it is 802.11 frame as is */ - ftype = wil_rxdesc_ftype(d1) << 2; + ftype = wil_rxdesc_ftype(d) << 2; if (ftype != IEEE80211_FTYPE_DATA) { wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); /* TODO: process it */ @@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, return NULL; } - ds_bits = wil_rxdesc_ds_bits(d1); + ds_bits = wil_rxdesc_ds_bits(d); if (ds_bits == 1) { /* * HW bug - in ToDS mode, i.e. Rx on AP side, @@ -612,11 +621,9 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, return NULL; } -static int wil_tx_desc_map(volatile struct vring_tx_desc *d, - dma_addr_t pa, u32 len) +static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len) { - d->dma.addr_low = lower_32_bits(pa); - d->dma.addr_high = (u16)upper_32_bits(pa); + wil_desc_addr_set(&d->dma.addr, pa); d->dma.ip_length = 0; /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ d->dma.b11 = 0/*14 | BIT(7)*/; @@ -642,7 +649,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, struct sk_buff *skb) { struct device *dev = wil_to_dev(wil); - volatile struct vring_tx_desc *d; + struct vring_tx_desc dd, *d = ⅆ + volatile struct vring_tx_desc *_d; u32 swhead = vring->swhead; int avail = wil_vring_avail_tx(vring); int nr_frags = skb_shinfo(skb)->nr_frags; @@ -660,7 +668,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, 1 + nr_frags); return -ENOMEM; } - d = &(vring->va[i].tx); + _d = &(vring->va[i].tx); /* FIXME FW can accept only unicast frames for the peer */ memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); @@ -679,25 +687,30 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, wil_tx_desc_map(d, pa, skb_headlen(skb)); d->mac.d[2] |= ((nr_frags + 1) << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); + if (nr_frags) + *_d = *d; + /* middle segments */ for (f = 0; f < nr_frags; f++) { const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[f]; int len = skb_frag_size(frag); i = (swhead + f + 1) % vring->size; - d = &(vring->va[i].tx); + _d = &(vring->va[i].tx); pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, pa))) goto dma_error; wil_tx_desc_map(d, pa, len); vring->ctx[i] = NULL; + *_d = *d; } /* for the last seg only */ d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); + *_d = *d; wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); @@ -721,9 +734,10 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, u16 dmalen; i = (swhead + f) % vring->size; - d = &(vring->va[i].tx); - d->dma.status = TX_DMA_STATUS_DU; - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + _d = &(vring->va[i].tx); + *d = *_d; + _d->dma.status = TX_DMA_STATUS_DU; + pa = wil_desc_addr(&d->dma.addr); dmalen = le16_to_cpu(d->dma.length); if (vring->ctx[i]) dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE); @@ -806,14 +820,14 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); while (!wil_vring_is_empty(vring)) { - volatile struct vring_tx_desc *d1 = + volatile struct vring_tx_desc *_d = &vring->va[vring->swtail].tx; struct vring_tx_desc dd, *d = ⅆ dma_addr_t pa; struct sk_buff *skb; u16 dmalen; - dd = *d1; + *d = *_d; if (!(d->dma.status & TX_DMA_STATUS_DU)) break; @@ -828,7 +842,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); + pa = wil_desc_addr(&d->dma.addr); skb = vring->ctx[vring->swtail]; if (skb) { if (d->dma.error == 0) { @@ -844,8 +858,8 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) } else { dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE); } - d->dma.addr_low = 0; - d->dma.addr_high = 0; + d->dma.addr.addr_low = 0; + d->dma.addr.addr_high = 0; d->dma.length = 0; d->dma.status = TX_DMA_STATUS_DU; vring->swtail = wil_vring_next_tail(vring); diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index a40aa0bb8b94..23c0781cdb93 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -27,6 +27,28 @@ #define WIL6210_RTAP_SIZE (128) /* Tx/Rx path */ + +/* + * Common representation of physical address in Vring + */ +struct vring_dma_addr { + __le32 addr_low; + __le16 addr_high; +} __packed; + +static inline dma_addr_t wil_desc_addr(struct vring_dma_addr *addr) +{ + return le32_to_cpu(addr->addr_low) | + ((u64)le16_to_cpu(addr->addr_high) << 32); +} + +static inline void wil_desc_addr_set(struct vring_dma_addr *addr, + dma_addr_t pa) +{ + addr->addr_low = cpu_to_le32(lower_32_bits(pa)); + addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa)); +} + /* * Tx descriptor - MAC part * [dword 0] @@ -216,8 +238,7 @@ struct vring_tx_mac { struct vring_tx_dma { u32 d0; - u32 addr_low; - u16 addr_high; + struct vring_dma_addr addr; u8 ip_length; u8 b11; /* 0..6: mac_length; 7:ip_version */ u8 error; /* 0..2: err; 3..7: reserved; */ @@ -315,8 +336,7 @@ struct vring_rx_mac { struct vring_rx_dma { u32 d0; - u32 addr_low; - u16 addr_high; + struct vring_dma_addr addr; u8 ip_length; u8 b11; u8 error; -- GitLab From 224c9c2366efe7f32496c1b7ef82f9b6424817dd Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 12 May 2013 14:43:38 +0300 Subject: [PATCH 0214/2900] wil6210: do not stop Tx queue on packet drop Packet drop may be caused by various flows, like disconnect while Tx packets was queued; this should not lead to stopping of the Tx queue, or all Tx get stalled. Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 561314830f21..082f76bdd5e5 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -791,7 +791,6 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) break; /* goto drop; */ } drop: - netif_tx_stop_all_queues(ndev); ndev->stats.tx_dropped++; dev_kfree_skb_any(skb); -- GitLab From 5179ed7c1bc1d4599f9643f9711c090648602f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 13 May 2013 22:07:51 +0200 Subject: [PATCH 0215/2900] bcma: don't hardcode SPROM length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass it as an argument to all functions. This is requires as newer SPROM revisions have different lengths. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 8934298a638d..5386cddba43e 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -72,12 +72,12 @@ static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus, * R/W ops. **************************************************/ -static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom) +static void bcma_sprom_read(struct bcma_bus *bus, u16 offset, u16 *sprom, + size_t words) { int i; - for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++) - sprom[i] = bcma_read16(bus->drv_cc.core, - offset + (i * 2)); + for (i = 0; i < words; i++) + sprom[i] = bcma_read16(bus->drv_cc.core, offset + (i * 2)); } /************************************************** @@ -124,29 +124,29 @@ static inline u8 bcma_crc8(u8 crc, u8 data) return t[crc ^ data]; } -static u8 bcma_sprom_crc(const u16 *sprom) +static u8 bcma_sprom_crc(const u16 *sprom, size_t words) { int word; u8 crc = 0xFF; - for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) { + for (word = 0; word < words - 1; word++) { crc = bcma_crc8(crc, sprom[word] & 0x00FF); crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8); } - crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF); + crc = bcma_crc8(crc, sprom[words - 1] & 0x00FF); crc ^= 0xFF; return crc; } -static int bcma_sprom_check_crc(const u16 *sprom) +static int bcma_sprom_check_crc(const u16 *sprom, size_t words) { u8 crc; u8 expected_crc; u16 tmp; - crc = bcma_sprom_crc(sprom); - tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC; + crc = bcma_sprom_crc(sprom, words); + tmp = sprom[words - 1] & SSB_SPROM_REVISION_CRC; expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT; if (crc != expected_crc) return -EPROTO; @@ -154,16 +154,16 @@ static int bcma_sprom_check_crc(const u16 *sprom) return 0; } -static int bcma_sprom_valid(const u16 *sprom) +static int bcma_sprom_valid(const u16 *sprom, size_t words) { u16 revision; int err; - err = bcma_sprom_check_crc(sprom); + err = bcma_sprom_check_crc(sprom, words); if (err) return err; - revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV; + revision = sprom[words - 1] & SSB_SPROM_REVISION_REV; if (revision != 8 && revision != 9) { pr_err("Unsupported SPROM revision: %d\n", revision); return -ENOENT; @@ -589,13 +589,13 @@ int bcma_sprom_get(struct bcma_bus *bus) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); bcma_debug(bus, "SPROM offset 0x%x\n", offset); - bcma_sprom_read(bus, offset, sprom); + bcma_sprom_read(bus, offset, sprom, SSB_SPROMSIZE_WORDS_R4); if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); - err = bcma_sprom_valid(sprom); + err = bcma_sprom_valid(sprom, SSB_SPROMSIZE_WORDS_R4); if (err) { bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); -- GitLab From 92eb164258cfce173060d3fe7aaffa2afaf735d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 13 May 2013 22:07:52 +0200 Subject: [PATCH 0216/2900] bcma: prepare for supporting more SPROM sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 5386cddba43e..c96f71c183cd 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -502,7 +502,6 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) case BCMA_CHIP_ID_BCM4331: present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; break; - case BCMA_CHIP_ID_BCM43224: case BCMA_CHIP_ID_BCM43225: /* for these chips OTP is always available */ @@ -550,7 +549,8 @@ int bcma_sprom_get(struct bcma_bus *bus) { u16 offset = BCMA_CC_SPROM; u16 *sprom; - int err = 0; + size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, }; + int i, err = 0; if (!bus->drv_cc.core) return -EOPNOTSUPP; @@ -579,32 +579,37 @@ int bcma_sprom_get(struct bcma_bus *bus) } } - sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16), - GFP_KERNEL); - if (!sprom) - return -ENOMEM; - if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); bcma_debug(bus, "SPROM offset 0x%x\n", offset); - bcma_sprom_read(bus, offset, sprom, SSB_SPROMSIZE_WORDS_R4); + for (i = 0; i < ARRAY_SIZE(sprom_sizes); i++) { + size_t words = sprom_sizes[i]; + + sprom = kcalloc(words, sizeof(u16), GFP_KERNEL); + if (!sprom) + return -ENOMEM; + + bcma_sprom_read(bus, offset, sprom, words); + err = bcma_sprom_valid(sprom, words); + if (!err) + break; + + kfree(sprom); + } if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 || bus->chipinfo.id == BCMA_CHIP_ID_BCM43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); - err = bcma_sprom_valid(sprom, SSB_SPROMSIZE_WORDS_R4); if (err) { - bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); + bcma_warn(bus, "Invalid SPROM read from the PCIe card, trying to use fallback SPROM\n"); err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); - goto out; + } else { + bcma_sprom_extract_r8(bus, sprom); + kfree(sprom); } - bcma_sprom_extract_r8(bus, sprom); - -out: - kfree(sprom); return err; } -- GitLab From 78e578c5b43c4f274305075c68d055c8d6141fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 13 May 2013 22:07:53 +0200 Subject: [PATCH 0217/2900] bcma: support SPROM rev 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is pretty much the same as rev 9, there are just 2 extra fields we know about, but are not used/stored yet anyway. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/sprom.c | 16 +++++++++------- include/linux/ssb/ssb_regs.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index c96f71c183cd..de15b4f4b237 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -154,7 +154,8 @@ static int bcma_sprom_check_crc(const u16 *sprom, size_t words) return 0; } -static int bcma_sprom_valid(const u16 *sprom, size_t words) +static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom, + size_t words) { u16 revision; int err; @@ -164,11 +165,14 @@ static int bcma_sprom_valid(const u16 *sprom, size_t words) return err; revision = sprom[words - 1] & SSB_SPROM_REVISION_REV; - if (revision != 8 && revision != 9) { + if (revision != 8 && revision != 9 && revision != 10) { pr_err("Unsupported SPROM revision: %d\n", revision); return -ENOENT; } + bus->sprom.revision = revision; + bcma_debug(bus, "Found SPROM revision %d\n", revision); + return 0; } @@ -208,9 +212,6 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != ARRAY_SIZE(bus->sprom.core_pwr_info)); - bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & - SSB_SPROM_REVISION_REV; - for (i = 0; i < 3; i++) { v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i]; *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v); @@ -549,7 +550,8 @@ int bcma_sprom_get(struct bcma_bus *bus) { u16 offset = BCMA_CC_SPROM; u16 *sprom; - size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, }; + size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4, + SSB_SPROMSIZE_WORDS_R10, }; int i, err = 0; if (!bus->drv_cc.core) @@ -592,7 +594,7 @@ int bcma_sprom_get(struct bcma_bus *bus) return -ENOMEM; bcma_sprom_read(bus, offset, sprom, words); - err = bcma_sprom_valid(sprom, words); + err = bcma_sprom_valid(bus, sprom, words); if (!err) break; diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h index 3a7256955b10..f9f931c89e3e 100644 --- a/include/linux/ssb/ssb_regs.h +++ b/include/linux/ssb/ssb_regs.h @@ -172,6 +172,7 @@ #define SSB_SPROMSIZE_WORDS_R4 220 #define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16)) #define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16)) +#define SSB_SPROMSIZE_WORDS_R10 230 #define SSB_SPROM_BASE1 0x1000 #define SSB_SPROM_BASE31 0x0800 #define SSB_SPROM_REVISION 0x007E -- GitLab From c56ecf5a7f0f670c0c445a3d2d0bd6c3eda7015c Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:18 -0700 Subject: [PATCH 0218/2900] mwifiex: rename mwifiex_free_adapter() routine in init.c We have two different static routines with name mwifiex_free_adapter(). The routine in main.c actually frees the adapter structure. We will rename other routine in init.c to mwifiex_adapter_cleanup() to avoid confusion. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 9f44fda19db9..58e151edfa09 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -447,17 +447,16 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) } /* - * This function frees the adapter structure. + * This function performs cleanup for adapter structure. * - * The freeing operation is done recursively, by canceling all - * pending commands, freeing the member buffers previously - * allocated (command buffers, scan table buffer, sleep confirm - * command buffer), stopping the timers and calling the cleanup - * routines for every interface, before the actual adapter - * structure is freed. + * The cleanup is done recursively, by canceling all pending + * commands, freeing the member buffers previously allocated + * (command buffers, scan table buffer, sleep confirm command + * buffer), stopping the timers and calling the cleanup routines + * for every interface. */ static void -mwifiex_free_adapter(struct mwifiex_adapter *adapter) +mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) { if (!adapter) { pr_err("%s: adapter is NULL\n", __func__); @@ -733,8 +732,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) } } - /* Free adapter structure */ - mwifiex_free_adapter(adapter); + mwifiex_adapter_cleanup(adapter); spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); -- GitLab From 06041118ef0908b9cae7657a7b734699bcf61a6c Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:19 -0700 Subject: [PATCH 0219/2900] mwifiex: scan delay timer cleanup in unload path Return from scan delay timer routine if surprise_removed flag is true. Also, cancel the timer in unload path. This fixes a crash when scan delay timer accesses structures that have been freed already. Tested with "iwlist mlan0 scan & sleep 1; rmmod mwifiex_sdio" Reported-by: Daniel Drake Tested-by: Daniel Drake Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 58e151edfa09..71bbf1204685 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -59,6 +59,9 @@ static void scan_delay_timer_fn(unsigned long data) struct cmd_ctrl_node *cmd_node, *tmp_node; unsigned long flags; + if (adapter->surprise_removed) + return; + if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { /* * Abort scan operation by cancelling all pending scan @@ -458,11 +461,18 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) static void mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) { + int i; + if (!adapter) { pr_err("%s: adapter is NULL\n", __func__); return; } + for (i = 0; i < adapter->priv_num; i++) { + if (adapter->priv[i]) + del_timer_sync(&adapter->priv[i]->scan_delay_timer); + } + mwifiex_cancel_all_pending_cmd(adapter); /* Free lock variables */ -- GitLab From 75ab753d7704f0bd34e09d5e4081bc73fdddd775 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:20 -0700 Subject: [PATCH 0220/2900] mwifiex: remove global user_scan_cfg variable As the variable is used only for preparation of internal scan commands, we don't need to keep it allocated until the entire scan completes. We will define it as a local variable and free immediately after it's use. New flag 'scan_aborting' is added to handle race between mwifiex_close() and scan handler. Previously user_scan_cfg pointer used to take care of this. This patch fixes a memory leak in mwifiex_cfg80211_scan after running "iwlist mlan0 scan & sleep 1; rmmod mwifiex_sdio". Reported-by: Daniel Drake Tested-by: Daniel Drake Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 31 ++++++++++++++----------- drivers/net/wireless/mwifiex/init.c | 20 ++++++---------- drivers/net/wireless/mwifiex/main.c | 1 + drivers/net/wireless/mwifiex/main.h | 2 +- drivers/net/wireless/mwifiex/scan.c | 22 +++++++----------- 5 files changed, 34 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d3c8ece980d8..fcd293c64118 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1859,6 +1859,7 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, int i, offset, ret; struct ieee80211_channel *chan; struct ieee_types_header *ie; + struct mwifiex_user_scan_cfg *user_scan_cfg; wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); @@ -1869,20 +1870,22 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } - if (priv->user_scan_cfg) { + /* Block scan request if scan operation or scan cleanup when interface + * is disabled is in process + */ + if (priv->scan_request || priv->scan_aborting) { dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); return -EBUSY; } - priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), - GFP_KERNEL); - if (!priv->user_scan_cfg) + user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); + if (!user_scan_cfg) return -ENOMEM; priv->scan_request = request; - priv->user_scan_cfg->num_ssids = request->n_ssids; - priv->user_scan_cfg->ssid_list = request->ssids; + user_scan_cfg->num_ssids = request->n_ssids; + user_scan_cfg->ssid_list = request->ssids; if (request->ie && request->ie_len) { offset = 0; @@ -1902,25 +1905,25 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, for (i = 0; i < min_t(u32, request->n_channels, MWIFIEX_USER_SCAN_CHAN_MAX); i++) { chan = request->channels[i]; - priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value; - priv->user_scan_cfg->chan_list[i].radio_type = chan->band; + user_scan_cfg->chan_list[i].chan_number = chan->hw_value; + user_scan_cfg->chan_list[i].radio_type = chan->band; if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) - priv->user_scan_cfg->chan_list[i].scan_type = + user_scan_cfg->chan_list[i].scan_type = MWIFIEX_SCAN_TYPE_PASSIVE; else - priv->user_scan_cfg->chan_list[i].scan_type = + user_scan_cfg->chan_list[i].scan_type = MWIFIEX_SCAN_TYPE_ACTIVE; - priv->user_scan_cfg->chan_list[i].scan_time = 0; + user_scan_cfg->chan_list[i].scan_time = 0; } - ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); + ret = mwifiex_scan_networks(priv, user_scan_cfg); + kfree(user_scan_cfg); if (ret) { dev_err(priv->adapter->dev, "scan failed: %d\n", ret); + priv->scan_aborting = false; priv->scan_request = NULL; - kfree(priv->user_scan_cfg); - priv->user_scan_cfg = NULL; return ret; } diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 71bbf1204685..1343725f8c4c 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -81,19 +81,13 @@ static void scan_delay_timer_fn(unsigned long data) adapter->empty_tx_q_cnt = 0; spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - if (priv->user_scan_cfg) { - if (priv->scan_request) { - dev_dbg(priv->adapter->dev, - "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } else { - dev_dbg(priv->adapter->dev, - "info: scan already aborted\n"); - } - - kfree(priv->user_scan_cfg); - priv->user_scan_cfg = NULL; + if (priv->scan_request) { + dev_dbg(adapter->dev, "info: aborting scan\n"); + cfg80211_scan_done(priv->scan_request, 1); + priv->scan_request = NULL; + } else { + priv->scan_aborting = false; + dev_dbg(adapter->dev, "info: scan already aborted\n"); } goto done; } diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 121443a0f2a1..eb8518618622 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -436,6 +436,7 @@ mwifiex_close(struct net_device *dev) dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n"); cfg80211_scan_done(priv->scan_request, 1); priv->scan_request = NULL; + priv->scan_aborting = true; } return 0; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 4ef67fca06d3..81251d91491c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -492,7 +492,6 @@ struct mwifiex_private { struct semaphore async_sem; u8 report_scan_result; struct cfg80211_scan_request *scan_request; - struct mwifiex_user_scan_cfg *user_scan_cfg; u8 cfg_bssid[6]; struct wps wps; u8 scan_block; @@ -510,6 +509,7 @@ struct mwifiex_private { u8 ap_11ac_enabled; u32 mgmt_frame_mask; struct mwifiex_roc_cfg roc_cfg; + bool scan_aborting; }; enum mwifiex_ba_status { diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9cf5d8f07df8..7b2566b308c3 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1784,22 +1784,16 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, if (priv->report_scan_result) priv->report_scan_result = false; - if (priv->user_scan_cfg) { - if (priv->scan_request) { - dev_dbg(priv->adapter->dev, - "info: notifying scan done\n"); - cfg80211_scan_done(priv->scan_request, 0); - priv->scan_request = NULL; - } else { - dev_dbg(priv->adapter->dev, - "info: scan already aborted\n"); - } - - kfree(priv->user_scan_cfg); - priv->user_scan_cfg = NULL; + if (priv->scan_request) { + dev_dbg(adapter->dev, "info: notifying scan done\n"); + cfg80211_scan_done(priv->scan_request, 0); + priv->scan_request = NULL; + } else { + priv->scan_aborting = false; + dev_dbg(adapter->dev, "info: scan already aborted\n"); } } else { - if (priv->user_scan_cfg && !priv->scan_request) { + if (priv->scan_aborting && !priv->scan_request) { spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; -- GitLab From 4c1079e1583958b83d7355ccbba686ad08b67015 Mon Sep 17 00:00:00 2001 From: Bing Zhao Date: Fri, 17 May 2013 17:50:21 -0700 Subject: [PATCH 0221/2900] mwifiex: abort remaining scan commands when association started A full-channel scan is split to multiple scan commands in driver before they are sent to firmware. When each scan result is back the SSID entries are parsed and informed to cfg80211 directly. It's observed that sometimes userspace may initiate association as soon as the target AP is found. During the 4-way handshake firmware may go off-channel to scan the remaining channels. This causes the 4-way handshake to fail. Fix it by checking 'scan_block' flag and aborting the remaining scan in this case. 'scan_block' flag is set after association and before 4-way handshake. It gets cleared after 4-way handshake is completed. Tested-by: Jason Abele Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 7b2566b308c3..801b6b728379 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1793,7 +1793,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, dev_dbg(adapter->dev, "info: scan already aborted\n"); } } else { - if (priv->scan_aborting && !priv->scan_request) { + if ((priv->scan_aborting && !priv->scan_request) || + priv->scan_block) { spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; -- GitLab From bdd4d6bf59c046e5a3d1ac67ba7b1c9ea540b6e3 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 17 May 2013 17:50:22 -0700 Subject: [PATCH 0222/2900] mwifiex: avoid deleting all stations during mwifiex_del_sta_entry() During deleting a station entry from associated sta_list, we are supposed to delete entry only for this particular mac address. This patch is a bug fix wherein we were deleting all entries from list; fix this by removing list_for_each_entry_safe() call. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/uap_event.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 21c640d3b579..77fb533ae10a 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -107,18 +107,15 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, */ static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) { - struct mwifiex_sta_node *node, *tmp; + struct mwifiex_sta_node *node; unsigned long flags; spin_lock_irqsave(&priv->sta_list_spinlock, flags); node = mwifiex_get_sta_entry(priv, mac); if (node) { - list_for_each_entry_safe(node, tmp, &priv->sta_list, - list) { - list_del(&node->list); - kfree(node); - } + list_del(&node->list); + kfree(node); } spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); -- GitLab From 0f9e9b8ba72bc75ee6189d0e86639f7e7a494a30 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 17 May 2013 17:50:23 -0700 Subject: [PATCH 0223/2900] mwifiex: add del_station handler This patch adds cfg80211 del_station handler for mwifiex. If bss is not started or there are no stations in associated stations list, no action is taken. If argument received is null/broadcast mac, all stations in associated station list are deauthenticated. Patch also deletes related RxReorder stream and TxBA stream tables for related station. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 46 ++++++++++++++++++++++ drivers/net/wireless/mwifiex/cmdevt.c | 1 + drivers/net/wireless/mwifiex/fw.h | 7 ++++ drivers/net/wireless/mwifiex/main.h | 2 + drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 + drivers/net/wireless/mwifiex/uap_cmd.c | 21 ++++++++++ drivers/net/wireless/mwifiex/uap_event.c | 16 ++++++++ 7 files changed, 95 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index fcd293c64118..af79daa331d0 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1231,6 +1231,51 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, return 0; } +/* cfg80211 operation handler for del_station. + * Function deauthenticates station which value is provided in mac parameter. + * If mac is NULL/broadcast, all stations in associated station list are + * deauthenticated. If bss is not started or there are no stations in + * associated stations list, no action is taken. + */ +static int +mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + struct mwifiex_sta_node *sta_node; + unsigned long flags; + + if (list_empty(&priv->sta_list) || !priv->bss_started) + return 0; + + if (!mac || is_broadcast_ether_addr(mac)) { + wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); + list_for_each_entry(sta_node, &priv->sta_list, list) { + if (mwifiex_send_cmd_sync(priv, + HostCmd_CMD_UAP_STA_DEAUTH, + HostCmd_ACT_GEN_SET, 0, + sta_node->mac_addr)) + return -1; + mwifiex_uap_del_sta_data(priv, sta_node); + } + } else { + wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac); + spin_lock_irqsave(&priv->sta_list_spinlock, flags); + sta_node = mwifiex_get_sta_entry(priv, mac); + spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); + if (sta_node) { + if (mwifiex_send_cmd_sync(priv, + HostCmd_CMD_UAP_STA_DEAUTH, + HostCmd_ACT_GEN_SET, 0, + sta_node->mac_addr)) + return -1; + mwifiex_uap_del_sta_data(priv, sta_node); + } + } + + return 0; +} + static int mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) { @@ -2425,6 +2470,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .change_beacon = mwifiex_cfg80211_change_beacon, .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, .set_antenna = mwifiex_cfg80211_set_antenna, + .del_station = mwifiex_cfg80211_del_station, #ifdef CONFIG_PM .suspend = mwifiex_cfg80211_suspend, .resume = mwifiex_cfg80211_resume, diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 74db0d24a579..4a32f2795c64 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -570,6 +570,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, case HostCmd_CMD_UAP_SYS_CONFIG: case HostCmd_CMD_UAP_BSS_START: case HostCmd_CMD_UAP_BSS_STOP: + case HostCmd_CMD_UAP_STA_DEAUTH: ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, cmd_oid, data_buf, cmd_ptr); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1f7578d553ec..d3c1e01b4fc2 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -279,6 +279,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 #define HostCmd_CMD_UAP_BSS_START 0x00b1 #define HostCmd_CMD_UAP_BSS_STOP 0x00b2 +#define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5 #define HostCmd_CMD_11N_CFG 0x00cd #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf @@ -1197,6 +1198,11 @@ struct host_cmd_ds_amsdu_aggr_ctrl { __le16 curr_buf_size; } __packed; +struct host_cmd_ds_sta_deauth { + u8 mac[ETH_ALEN]; + __le16 reason; +} __packed; + struct mwifiex_ie_types_wmm_param_set { struct mwifiex_ie_types_header header; u8 wmm_ie[1]; @@ -1630,6 +1636,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_802_11_eeprom_access eeprom; struct host_cmd_ds_802_11_subsc_evt subsc_evt; struct host_cmd_ds_sys_config uap_sys_config; + struct host_cmd_ds_sta_deauth sta_deauth; struct host_cmd_11ac_vht_cfg vht_cfg; } params; } __packed; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 81251d91491c..9cf6852f6da3 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -1115,6 +1115,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, struct cfg80211_beacon_data *data); int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); u8 *mwifiex_11d_code_2_region(u8 code); +void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, + struct mwifiex_sta_node *node); extern const struct ethtool_ops mwifiex_ethtool_ops; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 9f990e14966e..c710a1bb05ce 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -978,6 +978,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_UAP_BSS_STOP: priv->bss_started = 0; break; + case HostCmd_CMD_UAP_STA_DEAUTH: + break; case HostCmd_CMD_MEF_CFG: break; default: diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index b04b1db29100..2de882dead0f 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -689,6 +689,23 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action, return 0; } +/* This function prepares AP specific deauth command with mac supplied in + * function parameter. + */ +static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, u8 *mac) +{ + struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth; + + cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH); + memcpy(sta_deauth->mac, mac, ETH_ALEN); + sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); + + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) + + S_DS_GEN); + return 0; +} + /* This function prepares the AP specific commands before sending them * to the firmware. * This is a generic function which calls specific command preparation @@ -710,6 +727,10 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, cmd->command = cpu_to_le16(cmd_no); cmd->size = cpu_to_le16(S_DS_GEN); break; + case HostCmd_CMD_UAP_STA_DEAUTH: + if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) + return -1; + break; default: dev_err(priv->adapter->dev, "PREP_CMD: unknown cmd %#x\n", cmd_no); diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 77fb533ae10a..718066577c6c 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -292,3 +292,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) return 0; } + +/* This function deletes station entry from associated station list. + * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream + * tables created for this station are deleted. + */ +void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, + struct mwifiex_sta_node *node) +{ + if (priv->ap_11n_enabled && node->is_11n_enabled) { + mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr); + mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr); + } + mwifiex_del_sta_entry(priv, node->mac_addr); + + return; +} -- GitLab From 013a492ecf2e6e1dd424d589fb27170e2481733f Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Fri, 17 May 2013 17:50:24 -0700 Subject: [PATCH 0224/2900] mwifiex: replace spin_lock_irqsave with spin_lock and fix warn_on We see this WARN_ON during PCIe unload: WARNING: at kernel/smp.c:382 smp_call_function_many+0x66/0x1e1() This happens because we are doing PCI iounmap operations while holding spinlock via spin_lock_irqsave(). Holding spinlock this way causes disabling IRQs and hence PCI iounmap shows warning on irqs_disabled() check. Use non-irq variant of spin_lock i.e. spin_lock() instead. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 1343725f8c4c..c7f11c0c3bb7 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -687,7 +687,6 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) int ret = -EINPROGRESS; struct mwifiex_private *priv; s32 i; - unsigned long flags; struct sk_buff *skb; /* mwifiex already shutdown */ @@ -722,7 +721,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) } } - spin_lock_irqsave(&adapter->mwifiex_lock, flags); + spin_lock(&adapter->mwifiex_lock); if (adapter->if_ops.data_complete) { while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) { @@ -738,7 +737,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) mwifiex_adapter_cleanup(adapter); - spin_unlock_irqrestore(&adapter->mwifiex_lock, flags); + spin_unlock(&adapter->mwifiex_lock); /* Notify completion */ ret = mwifiex_shutdown_fw_complete(adapter); -- GitLab From 388ec385d5ce4916f0677918a42e592ba423092d Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:25 -0700 Subject: [PATCH 0225/2900] mwifiex: add calibration data download feature User can provide a text file containing calibration data in hex format while loading mwifiex module. It will be downloaded to firmware. eg. insmod mwifiex.ko cal_data_cfg=cal_data.conf Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 10 ++++ drivers/net/wireless/mwifiex/main.c | 13 +++++ drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_cmd.c | 62 ++++++++++++++++++++++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 15 ++++++ 5 files changed, 101 insertions(+) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index d3c1e01b4fc2..d6ada7354c14 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -271,6 +271,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 +#define HostCmd_CMD_CFG_DATA 0x008f #define HostCmd_CMD_VERSION_EXT 0x0097 #define HostCmd_CMD_MEF_CFG 0x009a #define HostCmd_CMD_RSSI_INFO 0x00a4 @@ -465,6 +466,8 @@ enum P2P_MODES { #define MWIFIEX_CRITERIA_UNICAST BIT(1) #define MWIFIEX_CRITERIA_MULTICAST BIT(3) +#define CFG_DATA_TYPE_CAL 2 + struct mwifiex_ie_types_header { __le16 type; __le16 len; @@ -1579,6 +1582,12 @@ struct mwifiex_ie_list { struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; } __packed; +struct host_cmd_ds_802_11_cfg_data { + __le16 action; + __le16 type; + __le16 data_len; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -1638,6 +1647,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_sys_config uap_sys_config; struct host_cmd_ds_sta_deauth sta_deauth; struct host_cmd_11ac_vht_cfg vht_cfg; + struct host_cmd_ds_802_11_cfg_data cfg_data; } params; } __packed; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index eb8518618622..29d83f0c1fb8 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -25,6 +25,8 @@ #define VERSION "1.0" const char driver_version[] = "mwifiex " VERSION " (%s) "; +static char *cal_data_cfg; +module_param(cal_data_cfg, charp, 0); /* * This function registers the device and performs all the necessary @@ -336,6 +338,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) dev_notice(adapter->dev, "WLAN FW is active\n"); + if (cal_data_cfg) { + if ((request_firmware(&adapter->cal_data, cal_data_cfg, + adapter->dev)) < 0) + dev_err(adapter->dev, + "Cal data request_firmware() failed\n"); + } + adapter->init_wait_q_woken = false; ret = mwifiex_init_fw(adapter); if (ret == -1) { @@ -390,6 +399,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) pr_debug("info: %s: unregister device\n", __func__); adapter->if_ops.unregister_dev(adapter); done: + if (adapter->cal_data) { + release_firmware(adapter->cal_data); + adapter->cal_data = NULL; + } release_firmware(adapter->firmware); complete(&adapter->fw_load); return; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 9cf6852f6da3..0832c2437daf 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -730,6 +730,7 @@ struct mwifiex_adapter { u16 max_mgmt_ie_index; u8 scan_delay_cnt; u8 empty_tx_q_cnt; + const struct firmware *cal_data; /* 11AC */ u32 is_hw_11ac_capable; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index b193e25977d2..8ece48580642 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1134,6 +1134,55 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, return 0; } +/* This function parse cal data from ASCII to hex */ +static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst) +{ + u8 *s = src, *d = dst; + + while (s - src < len) { + if (*s && (isspace(*s) || *s == '\t')) { + s++; + continue; + } + if (isxdigit(*s)) { + *d++ = simple_strtol(s, NULL, 16); + s += 2; + } else { + s++; + } + } + + return d - dst; +} + +/* This function prepares command of set_cfg_data. */ +static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action) +{ + struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data; + struct mwifiex_adapter *adapter = priv->adapter; + u32 len, cal_data_offset; + u8 *tmp_cmd = (u8 *)cmd; + + cal_data_offset = S_DS_GEN + sizeof(*cfg_data); + if ((adapter->cal_data->data) && (adapter->cal_data->size > 0)) + len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, + adapter->cal_data->size, + (u8 *)(tmp_cmd + cal_data_offset)); + else + return -1; + + cfg_data->action = cpu_to_le16(cmd_action); + cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL); + cfg_data->data_len = cpu_to_le16(len); + + cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); + cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len); + + return 0; +} + /* * This function prepares the commands before sending them to the firmware. * @@ -1152,6 +1201,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, case HostCmd_CMD_GET_HW_SPEC: ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); break; + case HostCmd_CMD_CFG_DATA: + ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action); + break; case HostCmd_CMD_MAC_CONTROL: ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, data_buf); @@ -1384,6 +1436,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, */ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) { + struct mwifiex_adapter *adapter = priv->adapter; int ret; u16 enable = true; struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; @@ -1404,6 +1457,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; + + /* Download calibration data to firmware */ + if (adapter->cal_data) { + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, + HostCmd_ACT_GEN_SET, 0, NULL); + if (ret) + return -1; + } + /* Read MAC address from HW */ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC, HostCmd_ACT_GEN_GET, 0, NULL); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index c710a1bb05ce..d85df158cc6c 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -818,6 +818,18 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, return 0; } +/* This function handles the command response of set_cfg_data */ +static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp) +{ + if (resp->result != HostCmd_RESULT_OK) { + dev_err(priv->adapter->dev, "Cal data cmd resp failed\n"); + return -1; + } + + return 0; +} + /* * This function handles the command responses. * @@ -841,6 +853,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_GET_HW_SPEC: ret = mwifiex_ret_get_hw_spec(priv, resp); break; + case HostCmd_CMD_CFG_DATA: + ret = mwifiex_ret_cfg_data(priv, resp); + break; case HostCmd_CMD_MAC_CONTROL: break; case HostCmd_CMD_802_11_MAC_ADDRESS: -- GitLab From 5ac253d50bd6d0b092da3d2476368aa857c10ee4 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:26 -0700 Subject: [PATCH 0226/2900] mwifiex: use u32 variables for SDIO read/write port bitmap Currently supported SDIO chipsets (SD87XX) have 16 ports. This change is a prerequisite for new chipset. Signed-off-by: Amitkumar Karwar Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 40 ++++++++++++++--------------- drivers/net/wireless/mwifiex/sdio.h | 10 ++++---- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 363ba31b58bf..7368ee1ee79f 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -486,21 +486,21 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) { struct sdio_mmc_card *card = adapter->card; - u16 rd_bitmap = card->mp_rd_bitmap; + u32 rd_bitmap = card->mp_rd_bitmap; - dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%04x\n", rd_bitmap); + dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap); if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK))) return -1; if (card->mp_rd_bitmap & CTRL_PORT_MASK) { - card->mp_rd_bitmap &= (u16) (~CTRL_PORT_MASK); + card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK); *port = CTRL_PORT; - dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%04x\n", + dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n", *port, card->mp_rd_bitmap); } else { if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) { - card->mp_rd_bitmap &= (u16) + card->mp_rd_bitmap &= (u32) (~(1 << card->curr_rd_port)); *port = card->curr_rd_port; @@ -511,7 +511,7 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) } dev_dbg(adapter->dev, - "data: port=%d mp_rd_bitmap=0x%04x -> 0x%04x\n", + "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", *port, rd_bitmap, card->mp_rd_bitmap); } return 0; @@ -527,15 +527,15 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) { struct sdio_mmc_card *card = adapter->card; - u16 wr_bitmap = card->mp_wr_bitmap; + u32 wr_bitmap = card->mp_wr_bitmap; - dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%04x\n", wr_bitmap); + dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap); if (!(wr_bitmap & card->mp_data_port_mask)) return -1; if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { - card->mp_wr_bitmap &= (u16) (~(1 << card->curr_wr_port)); + card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port)); *port = card->curr_wr_port; if (++card->curr_wr_port == card->mp_end_port) card->curr_wr_port = 1; @@ -545,14 +545,14 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) } if (*port == CTRL_PORT) { - dev_err(adapter->dev, "invalid data port=%d cur port=%d" - " mp_wr_bitmap=0x%04x -> 0x%04x\n", + dev_err(adapter->dev, + "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *port, card->curr_wr_port, wr_bitmap, card->mp_wr_bitmap); return -1; } - dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%04x -> 0x%04x\n", + dev_dbg(adapter->dev, "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *port, wr_bitmap, card->mp_wr_bitmap); return 0; @@ -1024,7 +1024,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, goto rx_curr_single; } - if (card->mp_rd_bitmap & (~((u16) CTRL_PORT_MASK))) { + if (card->mp_rd_bitmap & (~((u32) CTRL_PORT_MASK))) { /* Some more data RX pending */ dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); @@ -1185,9 +1185,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) return ret; if (sdio_ireg & DN_LD_HOST_INT_STATUS) { - card->mp_wr_bitmap = ((u16) card->mp_regs[WR_BITMAP_U]) << 8; - card->mp_wr_bitmap |= (u16) card->mp_regs[WR_BITMAP_L]; - dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%04x\n", + card->mp_wr_bitmap = ((u32) card->mp_regs[WR_BITMAP_U]) << 8; + card->mp_wr_bitmap |= (u32) card->mp_regs[WR_BITMAP_L]; + dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%08x\n", card->mp_wr_bitmap); if (adapter->data_sent && (card->mp_wr_bitmap & card->mp_data_port_mask)) { @@ -1204,7 +1204,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) /* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */ card->mp_wr_bitmap |= - (u16) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; + (u32) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; if (card->mp_wr_bitmap & CTRL_PORT_MASK) adapter->cmd_sent = false; } @@ -1212,9 +1212,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", adapter->cmd_sent, adapter->data_sent); if (sdio_ireg & UP_LD_HOST_INT_STATUS) { - card->mp_rd_bitmap = ((u16) card->mp_regs[RD_BITMAP_U]) << 8; - card->mp_rd_bitmap |= (u16) card->mp_regs[RD_BITMAP_L]; - dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%04x\n", + card->mp_rd_bitmap = ((u32) card->mp_regs[RD_BITMAP_U]) << 8; + card->mp_rd_bitmap |= (u32) card->mp_regs[RD_BITMAP_L]; + dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%08x\n", card->mp_rd_bitmap); while (true) { diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 8cc5468654b4..6588069bfe94 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -261,7 +261,7 @@ struct mwifiex_sdio_mpa_tx { u8 *buf; u32 buf_len; u32 pkt_cnt; - u16 ports; + u32 ports; u16 start_port; u8 enabled; u32 buf_size; @@ -272,7 +272,7 @@ struct mwifiex_sdio_mpa_rx { u8 *buf; u32 buf_len; u32 pkt_cnt; - u16 ports; + u32 ports; u16 start_port; struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; @@ -290,11 +290,11 @@ struct sdio_mmc_card { struct sdio_func *func; struct mwifiex_adapter *adapter; - u16 mp_rd_bitmap; - u16 mp_wr_bitmap; + u32 mp_rd_bitmap; + u32 mp_wr_bitmap; u16 mp_end_port; - u16 mp_data_port_mask; + u32 mp_data_port_mask; u8 curr_rd_port; u8 curr_wr_port; -- GitLab From 05889f825397805bf2d6c40594195ccb8aca7b75 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:50:27 -0700 Subject: [PATCH 0227/2900] mwifiex: store SDIO chip specific information in separate structure Register addresses, firmware name and some macros are specific to a chip. They are stored in a new structure. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 116 ++++++++++++++++------------ drivers/net/wireless/mwifiex/sdio.h | 114 +++++++++++++++++++-------- 2 files changed, 149 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 7368ee1ee79f..022e9fd7197a 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -77,6 +77,15 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + if (id->driver_data) { + struct mwifiex_sdio_device *data = (void *)id->driver_data; + + card->firmware = data->firmware; + card->reg = data->reg; + card->max_ports = data->max_ports; + card->mp_agg_pkt_limit = data->mp_agg_pkt_limit; + } + sdio_claim_host(func); ret = sdio_enable_func(func); sdio_release_host(func); @@ -254,9 +263,12 @@ static int mwifiex_sdio_resume(struct device *dev) /* WLAN IDs */ static const struct sdio_device_id mwifiex_ids[] = { - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786)}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787)}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797)}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786), + .driver_data = (unsigned long) &mwifiex_sdio_sd8786}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787), + .driver_data = (unsigned long) &mwifiex_sdio_sd8787}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797), + .driver_data = (unsigned long) &mwifiex_sdio_sd8797}, {}, }; @@ -410,6 +422,7 @@ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) { u32 reg; + struct sdio_mmc_card *card = adapter->card; adapter->ioport = 0; @@ -434,13 +447,13 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) /* Set Host interrupt reset to read to clear */ if (!mwifiex_read_reg(adapter, HOST_INT_RSR_REG, ®)) mwifiex_write_reg(adapter, HOST_INT_RSR_REG, - reg | SDIO_INT_MASK); + reg | card->reg->sdio_int_mask); else return -1; /* Dnld/Upld ready set to auto reset */ - if (!mwifiex_read_reg(adapter, CARD_MISC_CFG_REG, ®)) - mwifiex_write_reg(adapter, CARD_MISC_CFG_REG, + if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®)) + mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg, reg | AUTO_RE_ENABLE_INT); else return -1; @@ -486,11 +499,12 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) { struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; u32 rd_bitmap = card->mp_rd_bitmap; dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap); - if (!(rd_bitmap & (CTRL_PORT_MASK | DATA_PORT_MASK))) + if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) return -1; if (card->mp_rd_bitmap & CTRL_PORT_MASK) { @@ -504,8 +518,8 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) (~(1 << card->curr_rd_port)); *port = card->curr_rd_port; - if (++card->curr_rd_port == MAX_PORT) - card->curr_rd_port = 1; + if (++card->curr_rd_port == card->max_ports) + card->curr_rd_port = reg->start_rd_port; } else { return -1; } @@ -538,7 +552,7 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port)); *port = card->curr_wr_port; if (++card->curr_wr_port == card->mp_end_port) - card->curr_wr_port = 1; + card->curr_wr_port = card->reg->start_wr_port; } else { adapter->data_sent = true; return -EBUSY; @@ -564,11 +578,12 @@ static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) static int mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) { + struct sdio_mmc_card *card = adapter->card; u32 tries; u32 cs; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) + if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs)) break; else if ((cs & bits) == bits) return 0; @@ -587,12 +602,14 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) static int mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) { + struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; u32 fws0, fws1; - if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) + if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0)) return -1; - if (mwifiex_read_reg(adapter, CARD_FW_STATUS1_REG, &fws1)) + if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1)) return -1; *dat = (u16) ((fws1 << 8) | fws0); @@ -633,8 +650,11 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) */ static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) { + struct sdio_mmc_card *card = adapter->card; + /* Simply write the mask to the register */ - if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, HOST_INT_ENABLE)) { + if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, + card->reg->host_int_enable)) { dev_err(adapter->dev, "enable host interrupt failed\n"); return -1; } @@ -686,6 +706,8 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, struct mwifiex_fw_image *fw) { + struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; int ret; u8 *firmware = fw->fw_buf; u32 firmware_len = fw->fw_len; @@ -727,7 +749,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, break; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_0, + ret = mwifiex_read_reg(adapter, reg->base_0_reg, &base0); if (ret) { dev_err(adapter->dev, @@ -736,7 +758,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, base0, base0); goto done; } - ret = mwifiex_read_reg(adapter, HOST_F1_RD_BASE_1, + ret = mwifiex_read_reg(adapter, reg->base_1_reg, &base1); if (ret) { dev_err(adapter->dev, @@ -828,6 +850,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { + struct sdio_mmc_card *card = adapter->card; int ret = 0; u16 firmware_stat; u32 tries; @@ -849,7 +872,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, if (ret) { if (mwifiex_read_reg - (adapter, CARD_FW_STATUS0_REG, &winner_status)) + (adapter, card->reg->status_reg_0, &winner_status)) winner_status = 0; if (winner_status) @@ -869,9 +892,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) u32 sdio_ireg; unsigned long flags; - if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, - REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, - 0)) { + if (mwifiex_read_data_sync(adapter, card->mp_regs, + card->reg->max_mp_regs, + REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) { dev_err(adapter->dev, "read mp_regs failed\n"); return; } @@ -1167,6 +1190,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; int ret = 0; u8 sdio_ireg; struct sk_buff *skb; @@ -1185,8 +1209,10 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) return ret; if (sdio_ireg & DN_LD_HOST_INT_STATUS) { - card->mp_wr_bitmap = ((u32) card->mp_regs[WR_BITMAP_U]) << 8; - card->mp_wr_bitmap |= (u32) card->mp_regs[WR_BITMAP_L]; + card->mp_wr_bitmap = + ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8; + card->mp_wr_bitmap |= + (u32) card->mp_regs[reg->wr_bitmap_l]; dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%08x\n", card->mp_wr_bitmap); if (adapter->data_sent && @@ -1204,7 +1230,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) /* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */ card->mp_wr_bitmap |= - (u32) card->mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; + (u32) card->mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK; if (card->mp_wr_bitmap & CTRL_PORT_MASK) adapter->cmd_sent = false; } @@ -1212,8 +1238,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", adapter->cmd_sent, adapter->data_sent); if (sdio_ireg & UP_LD_HOST_INT_STATUS) { - card->mp_rd_bitmap = ((u32) card->mp_regs[RD_BITMAP_U]) << 8; - card->mp_rd_bitmap |= (u32) card->mp_regs[RD_BITMAP_L]; + card->mp_rd_bitmap = + ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8; + card->mp_rd_bitmap |= (u32) card->mp_regs[reg->rd_bitmap_l]; dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%08x\n", card->mp_rd_bitmap); @@ -1224,8 +1251,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) "info: no more rd_port available\n"); break; } - len_reg_l = RD_LEN_P0_L + (port << 1); - len_reg_u = RD_LEN_P0_U + (port << 1); + len_reg_l = reg->rd_len_p0_l + (port << 1); + len_reg_u = reg->rd_len_p0_u + (port << 1); rx_len = ((u16) card->mp_regs[len_reg_u]) << 8; rx_len |= (u16) card->mp_regs[len_reg_l]; dev_dbg(adapter->dev, "info: RX: port=%d rx_len=%u\n", @@ -1586,18 +1613,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) adapter->dev = &func->dev; - switch (func->device) { - case SDIO_DEVICE_ID_MARVELL_8786: - strcpy(adapter->fw_name, SD8786_DEFAULT_FW_NAME); - break; - case SDIO_DEVICE_ID_MARVELL_8797: - strcpy(adapter->fw_name, SD8797_DEFAULT_FW_NAME); - break; - case SDIO_DEVICE_ID_MARVELL_8787: - default: - strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME); - break; - } + strcpy(adapter->fw_name, card->firmware); return 0; @@ -1626,6 +1642,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; int ret; u32 sdio_ireg; @@ -1645,27 +1662,27 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) /* Initialize SDIO variables in card */ card->mp_rd_bitmap = 0; card->mp_wr_bitmap = 0; - card->curr_rd_port = 1; - card->curr_wr_port = 1; + card->curr_rd_port = reg->start_rd_port; + card->curr_wr_port = reg->start_wr_port; - card->mp_data_port_mask = DATA_PORT_MASK; + card->mp_data_port_mask = reg->data_port_mask; card->mpa_tx.buf_len = 0; card->mpa_tx.pkt_cnt = 0; card->mpa_tx.start_port = 0; card->mpa_tx.enabled = 1; - card->mpa_tx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; + card->mpa_tx.pkt_aggr_limit = card->mp_agg_pkt_limit; card->mpa_rx.buf_len = 0; card->mpa_rx.pkt_cnt = 0; card->mpa_rx.start_port = 0; card->mpa_rx.enabled = 1; - card->mpa_rx.pkt_aggr_limit = SDIO_MP_AGGR_DEF_PKT_LIMIT; + card->mpa_rx.pkt_aggr_limit = card->mp_agg_pkt_limit; /* Allocate buffers for SDIO MP-A */ - card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); + card->mp_regs = kzalloc(reg->max_mp_regs, GFP_KERNEL); if (!card->mp_regs) return -ENOMEM; @@ -1716,16 +1733,17 @@ static void mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) { struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; int i; card->mp_end_port = port; - card->mp_data_port_mask = DATA_PORT_MASK; + card->mp_data_port_mask = reg->data_port_mask; - for (i = 1; i <= MAX_PORT - card->mp_end_port; i++) - card->mp_data_port_mask &= ~(1 << (MAX_PORT - i)); + for (i = 1; i <= card->max_ports - card->mp_end_port; i++) + card->mp_data_port_mask &= ~(1 << (card->max_ports - i)); - card->curr_wr_port = 1; + card->curr_wr_port = reg->start_wr_port; dev_dbg(adapter->dev, "cmd: mp_end_port %d, data port mask 0x%x\n", port, card->mp_data_port_mask); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 6588069bfe94..0d931f729639 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -37,12 +37,6 @@ #define BYTE_MODE 0 #define REG_PORT 0 -#define RD_BITMAP_L 0x04 -#define RD_BITMAP_U 0x05 -#define WR_BITMAP_L 0x06 -#define WR_BITMAP_U 0x07 -#define RD_LEN_P0_L 0x08 -#define RD_LEN_P0_U 0x09 #define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff @@ -50,12 +44,8 @@ #define CTRL_PORT 0 #define CTRL_PORT_MASK 0x0001 -#define DATA_PORT_MASK 0xfffe -#define MAX_MP_REGS 64 -#define MAX_PORT 16 - -#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 +#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 #define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */ @@ -90,8 +80,6 @@ #define UP_LD_HOST_INT_MASK (0x1U) /* Host Control Registers : Download host interrupt mask */ #define DN_LD_HOST_INT_MASK (0x2U) -/* Enable Host interrupt mask */ -#define HOST_INT_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) /* Disable Host interrupt mask */ #define HOST_INT_DISABLE 0xff @@ -106,7 +94,6 @@ #define HOST_INT_RSR_REG 0x01 /* Host Control Registers : Upload host interrupt RSR */ #define UP_LD_HOST_INT_RSR (0x1U) -#define SDIO_INT_MASK 0x3F /* Host Control Registers : Host interrupt status */ #define HOST_INT_STATUS_REG 0x28 @@ -117,8 +104,6 @@ /* Host Control Registers : Download restart */ #define DN_LD_RESTART (0x1U << 0) -/* Card Control Registers : Card status register */ -#define CARD_STATUS_REG 0x30 /* Card Control Registers : Card I/O ready */ #define CARD_IO_READY (0x1U << 3) /* Card Control Registers : CIS card ready */ @@ -153,20 +138,9 @@ /* Card Control Registers : Power down RSR */ #define POWER_DOWN_RSR (0x1U << 3) -/* Card Control Registers : Miscellaneous Configuration Register */ -#define CARD_MISC_CFG_REG 0x6C - -/* Host F1 read base 0 */ -#define HOST_F1_RD_BASE_0 0x0040 -/* Host F1 read base 1 */ -#define HOST_F1_RD_BASE_1 0x0041 /* Host F1 card ready */ #define HOST_F1_CARD_RDY 0x0020 -/* Firmware status 0 register */ -#define CARD_FW_STATUS0_REG 0x60 -/* Firmware status 1 register */ -#define CARD_FW_STATUS1_REG 0x61 /* Rx length register */ #define CARD_RX_LEN_REG 0x62 /* Rx unit register */ @@ -192,7 +166,8 @@ if (a->mpa_tx.start_port <= port) \ a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \ else \ - a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ + a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+ \ + (a->max_ports - \ a->mp_end_port))); \ a->mpa_tx.pkt_cnt++; \ } while (0) @@ -203,9 +178,9 @@ /* SDIO Tx aggregation port limit ? */ #define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \ - a->mpa_tx.start_port) && (((MAX_PORT - \ + a->mpa_tx.start_port) && (((a->max_ports -\ a->mpa_tx.start_port) + a->curr_wr_port) >= \ - SDIO_MP_AGGR_DEF_PKT_LIMIT)) + a->mp_agg_pkt_limit)) /* Reset SDIO Tx aggregation buffer parameters */ #define MP_TX_AGGR_BUF_RESET(a) do { \ @@ -221,9 +196,9 @@ /* SDIO Tx aggregation port limit ? */ #define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \ - a->mpa_rx.start_port) && (((MAX_PORT - \ + a->mpa_rx.start_port) && (((a->max_ports -\ a->mpa_rx.start_port) + a->curr_rd_port) >= \ - SDIO_MP_AGGR_DEF_PKT_LIMIT)) + a->mp_agg_pkt_limit)) /* SDIO Rx aggregation in progress ? */ #define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) @@ -286,10 +261,36 @@ struct mwifiex_sdio_mpa_rx { int mwifiex_bus_register(void); void mwifiex_bus_unregister(void); +struct mwifiex_sdio_card_reg { + u8 start_rd_port; + u8 start_wr_port; + u8 base_0_reg; + u8 base_1_reg; + u8 poll_reg; + u8 host_int_enable; + u8 status_reg_0; + u8 status_reg_1; + u8 sdio_int_mask; + u32 data_port_mask; + u8 max_mp_regs; + u8 rd_bitmap_l; + u8 rd_bitmap_u; + u8 wr_bitmap_l; + u8 wr_bitmap_u; + u8 rd_len_p0_l; + u8 rd_len_p0_u; + u8 card_misc_cfg_reg; +}; + struct sdio_mmc_card { struct sdio_func *func; struct mwifiex_adapter *adapter; + const char *firmware; + const struct mwifiex_sdio_card_reg *reg; + u8 max_ports; + u8 mp_agg_pkt_limit; + u32 mp_rd_bitmap; u32 mp_wr_bitmap; @@ -305,6 +306,55 @@ struct sdio_mmc_card { struct mwifiex_sdio_mpa_rx mpa_rx; }; +struct mwifiex_sdio_device { + const char *firmware; + const struct mwifiex_sdio_card_reg *reg; + u8 max_ports; + u8 mp_agg_pkt_limit; +}; + +static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { + .start_rd_port = 1, + .start_wr_port = 1, + .base_0_reg = 0x0040, + .base_1_reg = 0x0041, + .poll_reg = 0x30, + .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK, + .status_reg_0 = 0x60, + .status_reg_1 = 0x61, + .sdio_int_mask = 0x3f, + .data_port_mask = 0x0000fffe, + .max_mp_regs = 64, + .rd_bitmap_l = 0x04, + .rd_bitmap_u = 0x05, + .wr_bitmap_l = 0x06, + .wr_bitmap_u = 0x07, + .rd_len_p0_l = 0x08, + .rd_len_p0_u = 0x09, + .card_misc_cfg_reg = 0x6c, +}; + +static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { + .firmware = SD8786_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd87xx, + .max_ports = 16, + .mp_agg_pkt_limit = 8, +}; + +static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { + .firmware = SD8787_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd87xx, + .max_ports = 16, + .mp_agg_pkt_limit = 8, +}; + +static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { + .firmware = SD8797_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd87xx, + .max_ports = 16, + .mp_agg_pkt_limit = 8, +}; + /* * .cmdrsp_complete handler */ -- GitLab From ab93d4ff3693ece926ae73f71a5cc8c37579bc6a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:53:42 -0700 Subject: [PATCH 0228/2900] mwifiex: replace unnecessary u32 variables with u8 in sdio.c Some u32 variables in sdio.c are used to store/pass u8 values. Replace them with u8 variables. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 022e9fd7197a..e4357a6dd8dc 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -294,13 +294,13 @@ static struct sdio_driver mwifiex_sdio = { * This function writes data into SDIO card register. */ static int -mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u32 data) +mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) { struct sdio_mmc_card *card = adapter->card; int ret = -1; sdio_claim_host(card->func); - sdio_writeb(card->func, (u8) data, reg, &ret); + sdio_writeb(card->func, data, reg, &ret); sdio_release_host(card->func); return ret; @@ -310,7 +310,7 @@ mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u32 data) * This function reads data from SDIO card register. */ static int -mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u32 *data) +mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data) { struct sdio_mmc_card *card = adapter->card; int ret = -1; @@ -421,7 +421,7 @@ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) */ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) { - u32 reg; + u8 reg; struct sdio_mmc_card *card = adapter->card; adapter->ioport = 0; @@ -580,7 +580,7 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) { struct sdio_mmc_card *card = adapter->card; u32 tries; - u32 cs; + u8 cs; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs)) @@ -604,7 +604,7 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) { struct sdio_mmc_card *card = adapter->card; const struct mwifiex_sdio_card_reg *reg = card->reg; - u32 fws0, fws1; + u8 fws0, fws1; if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0)) return -1; @@ -625,14 +625,14 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) */ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) { - u32 host_int_mask; + u8 host_int_mask, host_int_disable = HOST_INT_DISABLE; /* Read back the host_int_mask register */ if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) return -1; /* Update with the mask and write back to the register */ - host_int_mask &= ~HOST_INT_DISABLE; + host_int_mask &= ~host_int_disable; if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) { dev_err(adapter->dev, "disable host interrupt failed\n"); @@ -712,7 +712,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, u8 *firmware = fw->fw_buf; u32 firmware_len = fw->fw_len; u32 offset = 0; - u32 base0, base1; + u8 base0, base1; u8 *fwbuf; u16 len = 0; u32 txlen, tx_blocks = 0, tries; @@ -854,7 +854,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, int ret = 0; u16 firmware_stat; u32 tries; - u32 winner_status; + u8 winner_status; /* Wait for firmware initialization event */ for (tries = 0; tries < poll_num; tries++) { @@ -889,7 +889,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) { struct sdio_mmc_card *card = adapter->card; - u32 sdio_ireg; + u8 sdio_ireg; unsigned long flags; if (mwifiex_read_data_sync(adapter, card->mp_regs, @@ -1284,7 +1284,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, port)) { - u32 cr = 0; + u8 cr = 0; dev_err(adapter->dev, "card_to_host_mpa failed:" " int status=%#x\n", sdio_ireg); @@ -1644,7 +1644,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) struct sdio_mmc_card *card = adapter->card; const struct mwifiex_sdio_card_reg *reg = card->reg; int ret; - u32 sdio_ireg; + u8 sdio_ireg; /* * Read the HOST_INT_STATUS_REG for ACK the first interrupt got -- GitLab From e6a520304f6562ee3f57b0ba01e49a458c5eeda2 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:53:56 -0700 Subject: [PATCH 0229/2900] mwifiex: code rearrangement in mwifiex_get_rd_port() Get rid of 'if else' usage by returning in 'if' block. This improves readability by removing indentations. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index e4357a6dd8dc..a18a5b4998d4 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -512,22 +512,23 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) *port = CTRL_PORT; dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n", *port, card->mp_rd_bitmap); - } else { - if (card->mp_rd_bitmap & (1 << card->curr_rd_port)) { - card->mp_rd_bitmap &= (u32) - (~(1 << card->curr_rd_port)); - *port = card->curr_rd_port; + return 0; + } - if (++card->curr_rd_port == card->max_ports) - card->curr_rd_port = reg->start_rd_port; - } else { - return -1; - } + if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port))) + return -1; + + /* We are now handling the SDIO data ports */ + card->mp_rd_bitmap &= (u32)(~(1 << card->curr_rd_port)); + *port = card->curr_rd_port; + + if (++card->curr_rd_port == card->max_ports) + card->curr_rd_port = reg->start_rd_port; + + dev_dbg(adapter->dev, + "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", + *port, rd_bitmap, card->mp_rd_bitmap); - dev_dbg(adapter->dev, - "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", - *port, rd_bitmap, card->mp_rd_bitmap); - } return 0; } -- GitLab From 0fc0d43b979cecda24a30b6af1185984a654521a Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:54:23 -0700 Subject: [PATCH 0230/2900] mwifiex: do port calculations separately This patch rearranges the code for better readability Signed-off-by: Amitkumar Karwar Signed-off-by: Yogesh Ashok Powar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index a18a5b4998d4..99a508b87864 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -539,7 +539,7 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) * increased (provided it does not reach the maximum limit, in which * case it is reset to 1) */ -static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u8 *port) +static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port) { struct sdio_mmc_card *card = adapter->card; u32 wr_bitmap = card->mp_wr_bitmap; @@ -1027,7 +1027,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, s32 f_aggr_cur = 0; struct sk_buff *skb_deaggr; u32 pind; - u32 pkt_len, pkt_type = 0; + u32 pkt_len, pkt_type, mport; u8 *curr_ptr; u32 rx_len = skb->len; @@ -1100,11 +1100,11 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", card->mpa_rx.pkt_cnt); + mport = (adapter->ioport | 0x1000 | + (card->mpa_rx.ports << 4)) + card->mpa_rx.start_port; + if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, - card->mpa_rx.buf_len, - (adapter->ioport | 0x1000 | - (card->mpa_rx.ports << 4)) + - card->mpa_rx.start_port, 1)) + card->mpa_rx.buf_len, mport, 1)) goto error; curr_ptr = card->mpa_rx.buf; @@ -1333,7 +1333,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) * and return. */ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, - u8 *payload, u32 pkt_len, u8 port, + u8 *payload, u32 pkt_len, u32 port, u32 next_pkt_len) { struct sdio_mmc_card *card = adapter->card; @@ -1342,6 +1342,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, s32 f_send_cur_buf = 0; s32 f_precopy_cur_buf = 0; s32 f_postcopy_cur_buf = 0; + u32 mport; if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) { dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n", @@ -1418,11 +1419,10 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", __func__, card->mpa_tx.start_port, card->mpa_tx.ports); + mport = (adapter->ioport | 0x1000 | + (card->mpa_tx.ports << 4)) + card->mpa_tx.start_port; ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, - card->mpa_tx.buf_len, - (adapter->ioport | 0x1000 | - (card->mpa_tx.ports << 4)) + - card->mpa_tx.start_port); + card->mpa_tx.buf_len, mport); MP_TX_AGGR_BUF_RESET(card); } @@ -1462,7 +1462,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, int ret; u32 buf_block_len; u32 blk_size; - u8 port = CTRL_PORT; + u32 port = CTRL_PORT; u8 *payload = (u8 *)skb->data; u32 pkt_len = skb->len; -- GitLab From 248eb4c6533a1409ec7a1eab9359a1befd8bb9c6 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:54:34 -0700 Subject: [PATCH 0231/2900] mwifiex: define a macro for MPA base address As Multiple-Port Aggregation base address value is fixed, we can have a macro for it. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 4 ++-- drivers/net/wireless/mwifiex/sdio.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 99a508b87864..1892e889d41e 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1100,7 +1100,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", card->mpa_rx.pkt_cnt); - mport = (adapter->ioport | 0x1000 | + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | (card->mpa_rx.ports << 4)) + card->mpa_rx.start_port; if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, @@ -1419,7 +1419,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", __func__, card->mpa_tx.start_port, card->mpa_tx.ports); - mport = (adapter->ioport | 0x1000 | + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | (card->mpa_tx.ports << 4)) + card->mpa_tx.start_port; ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, card->mpa_tx.buf_len, mport); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 0d931f729639..e4016d2692d4 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -42,6 +42,7 @@ #define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000 +#define SDIO_MPA_ADDR_BASE 0x1000 #define CTRL_PORT 0 #define CTRL_PORT_MASK 0x0001 -- GitLab From dc468e3d420d9042d18f240196dc72ba0306ee89 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:54:42 -0700 Subject: [PATCH 0232/2900] mwifiex: remove unnecessary macros in sdio.h They are not used in the code. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.h | 51 ----------------------------- 1 file changed, 51 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index e4016d2692d4..339608ba6171 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -66,14 +66,8 @@ /* Host Control Registers : Configuration */ #define CONFIGURATION_REG 0x00 -/* Host Control Registers : Host without Command 53 finish host*/ -#define HOST_TO_CARD_EVENT (0x1U << 3) -/* Host Control Registers : Host without Command 53 finish host */ -#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) /* Host Control Registers : Host power up */ #define HOST_POWER_UP (0x1U << 1) -/* Host Control Registers : Host power down */ -#define HOST_POWER_DOWN (0x1U << 0) /* Host Control Registers : Host interrupt mask */ #define HOST_INT_MASK_REG 0x02 @@ -93,60 +87,15 @@ /* Host Control Registers : Host interrupt RSR */ #define HOST_INT_RSR_REG 0x01 -/* Host Control Registers : Upload host interrupt RSR */ -#define UP_LD_HOST_INT_RSR (0x1U) /* Host Control Registers : Host interrupt status */ #define HOST_INT_STATUS_REG 0x28 -/* Host Control Registers : Upload CRC error */ -#define UP_LD_CRC_ERR (0x1U << 2) -/* Host Control Registers : Upload restart */ -#define UP_LD_RESTART (0x1U << 1) -/* Host Control Registers : Download restart */ -#define DN_LD_RESTART (0x1U << 0) /* Card Control Registers : Card I/O ready */ #define CARD_IO_READY (0x1U << 3) -/* Card Control Registers : CIS card ready */ -#define CIS_CARD_RDY (0x1U << 2) -/* Card Control Registers : Upload card ready */ -#define UP_LD_CARD_RDY (0x1U << 1) /* Card Control Registers : Download card ready */ #define DN_LD_CARD_RDY (0x1U << 0) -/* Card Control Registers : Host interrupt mask register */ -#define HOST_INTERRUPT_MASK_REG 0x34 -/* Card Control Registers : Host power interrupt mask */ -#define HOST_POWER_INT_MASK (0x1U << 3) -/* Card Control Registers : Abort card interrupt mask */ -#define ABORT_CARD_INT_MASK (0x1U << 2) -/* Card Control Registers : Upload card interrupt mask */ -#define UP_LD_CARD_INT_MASK (0x1U << 1) -/* Card Control Registers : Download card interrupt mask */ -#define DN_LD_CARD_INT_MASK (0x1U << 0) - -/* Card Control Registers : Card interrupt status register */ -#define CARD_INTERRUPT_STATUS_REG 0x38 -/* Card Control Registers : Power up interrupt */ -#define POWER_UP_INT (0x1U << 4) -/* Card Control Registers : Power down interrupt */ -#define POWER_DOWN_INT (0x1U << 3) - -/* Card Control Registers : Card interrupt RSR register */ -#define CARD_INTERRUPT_RSR_REG 0x3c -/* Card Control Registers : Power up RSR */ -#define POWER_UP_RSR (0x1U << 4) -/* Card Control Registers : Power down RSR */ -#define POWER_DOWN_RSR (0x1U << 3) - -/* Host F1 card ready */ -#define HOST_F1_CARD_RDY 0x0020 - -/* Rx length register */ -#define CARD_RX_LEN_REG 0x62 -/* Rx unit register */ -#define CARD_RX_UNIT_REG 0x63 - /* Max retry number of CMD53 write */ #define MAX_WRITE_IOMEM_RETRY 2 -- GitLab From c23b7c8f719317983c59b01873b51394fde26907 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 17 May 2013 17:54:51 -0700 Subject: [PATCH 0233/2900] mwifiex: code rearrangement in multiport aggregation path There are some macros defined for multiport aggregation calculations. As we may need to add some more code to accomodate new chipsets, we will change them to inline functions. Also, use dynamic allocation for Rx buffer array. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sdio.c | 17 ++++-- drivers/net/wireless/mwifiex/sdio.h | 83 ++++++++++++++++++----------- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 1892e889d41e..4b196dc97463 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1084,10 +1084,10 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, if (f_aggr_cur) { dev_dbg(adapter->dev, "info: current packet aggregation\n"); /* Curr pkt can be aggregated */ - MP_RX_AGGR_SETUP(card, skb, port); + mp_rx_aggr_setup(card, skb, port); if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || - MP_RX_AGGR_PORT_LIMIT_REACHED(card)) { + mp_rx_aggr_port_limit_reached(card)) { dev_dbg(adapter->dev, "info: %s: aggregated packet " "limit reached\n", __func__); /* No more pkts allowed in Aggr buf, rx it */ @@ -1358,7 +1358,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, __func__); if (MP_TX_AGGR_IN_PROGRESS(card)) { - if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) && + if (!mp_tx_aggr_port_limit_reached(card) && MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { f_precopy_cur_buf = 1; @@ -1371,7 +1371,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, /* No room in Aggr buf, send it */ f_send_aggr_buf = 1; - if (MP_TX_AGGR_PORT_LIMIT_REACHED(card) || + if (mp_tx_aggr_port_limit_reached(card) || !(card->mp_wr_bitmap & (1 << card->curr_wr_port))) f_send_cur_buf = 1; @@ -1410,7 +1410,7 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || - MP_TX_AGGR_PORT_LIMIT_REACHED(card)) + mp_tx_aggr_port_limit_reached(card)) /* No more pkts allowed in Aggr buf, send it */ f_send_aggr_buf = 1; } @@ -1687,6 +1687,11 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) if (!card->mp_regs) return -ENOMEM; + /* Allocate skb pointer buffers */ + card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) * + card->mp_agg_pkt_limit, GFP_KERNEL); + card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) * + card->mp_agg_pkt_limit, GFP_KERNEL); ret = mwifiex_alloc_sdio_mpa_buffers(adapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE, SDIO_MP_RX_AGGR_DEF_BUF_SIZE); @@ -1723,6 +1728,8 @@ static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) struct sdio_mmc_card *card = adapter->card; kfree(card->mp_regs); + kfree(card->mpa_rx.skb_arr); + kfree(card->mpa_rx.len_arr); kfree(card->mpa_tx.buf); kfree(card->mpa_rx.buf); } diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 339608ba6171..597db37a45f9 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -46,8 +46,6 @@ #define CTRL_PORT 0 #define CTRL_PORT_MASK 0x0001 -#define SDIO_MP_AGGR_DEF_PKT_LIMIT 8 - #define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */ /* Multi port RX aggregation buffer size */ @@ -126,12 +124,6 @@ #define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit) -/* SDIO Tx aggregation port limit ? */ -#define MP_TX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_wr_port < \ - a->mpa_tx.start_port) && (((a->max_ports -\ - a->mpa_tx.start_port) + a->curr_wr_port) >= \ - a->mp_agg_pkt_limit)) - /* Reset SDIO Tx aggregation buffer parameters */ #define MP_TX_AGGR_BUF_RESET(a) do { \ a->mpa_tx.pkt_cnt = 0; \ @@ -144,12 +136,6 @@ #define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit) -/* SDIO Tx aggregation port limit ? */ -#define MP_RX_AGGR_PORT_LIMIT_REACHED(a) ((a->curr_rd_port < \ - a->mpa_rx.start_port) && (((a->max_ports -\ - a->mpa_rx.start_port) + a->curr_rd_port) >= \ - a->mp_agg_pkt_limit)) - /* SDIO Rx aggregation in progress ? */ #define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) @@ -157,20 +143,6 @@ #define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \ ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size) -/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ -#define MP_RX_AGGR_SETUP(a, skb, port) do { \ - a->mpa_rx.buf_len += skb->len; \ - if (!a->mpa_rx.pkt_cnt) \ - a->mpa_rx.start_port = port; \ - if (a->mpa_rx.start_port <= port) \ - a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt)); \ - else \ - a->mpa_rx.ports |= (1<<(a->mpa_rx.pkt_cnt+1)); \ - a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ - a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ - a->mpa_rx.pkt_cnt++; \ -} while (0) - /* Reset SDIO Rx aggregation buffer parameters */ #define MP_RX_AGGR_BUF_RESET(a) do { \ a->mpa_rx.pkt_cnt = 0; \ @@ -179,7 +151,6 @@ a->mpa_rx.start_port = 0; \ } while (0) - /* data structure for SDIO MPA TX */ struct mwifiex_sdio_mpa_tx { /* multiport tx aggregation buffer pointer */ @@ -200,8 +171,8 @@ struct mwifiex_sdio_mpa_rx { u32 ports; u16 start_port; - struct sk_buff *skb_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; - u32 len_arr[SDIO_MP_AGGR_DEF_PKT_LIMIT]; + struct sk_buff **skb_arr; + u32 *len_arr; u8 enabled; u32 buf_size; @@ -325,4 +296,54 @@ static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter, return 0; } +static inline bool +mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card) +{ + u8 tmp; + + if (card->curr_rd_port < card->mpa_rx.start_port) { + tmp = card->mp_agg_pkt_limit; + + if (((card->max_ports - card->mpa_rx.start_port) + + card->curr_rd_port) >= tmp) + return true; + } + + return false; +} + +static inline bool +mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) +{ + u16 tmp; + + if (card->curr_wr_port < card->mpa_tx.start_port) { + tmp = card->mp_agg_pkt_limit; + + if (((card->max_ports - card->mpa_tx.start_port) + + card->curr_wr_port) >= tmp) + return true; + } + + return false; +} + +/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ +static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, + struct sk_buff *skb, u8 port) +{ + card->mpa_rx.buf_len += skb->len; + + if (!card->mpa_rx.pkt_cnt) + card->mpa_rx.start_port = port; + + if (card->mpa_rx.start_port <= port) + card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt); + else + card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); + + card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = skb; + card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = skb->len; + card->mpa_rx.pkt_cnt++; +} #endif /* _MWIFIEX_SDIO_H */ -- GitLab From b60186f824330cd85859f5944b9559b0f7df0b4f Mon Sep 17 00:00:00 2001 From: Yogesh Ashok Powar Date: Fri, 17 May 2013 17:54:58 -0700 Subject: [PATCH 0234/2900] mwifiex: add support for Marvell SD8897 chipset Some of the key differences between SD8897 and older chipsets are as follows: a) sdio mpa_rx and mpa_tx ports have been increased from 16 to 32 b) Same is the case with read/write bitmap that one receives from mpa_reg read c) aggregation packet count doubled from 8 to 16 d) Most of key reg addresses are changed e) There is a separate command or control port f) Now command rx/tx_done have new interrupts 1. 'supports_sdio_new_mode' flag is added to handle (a) and (b). 2. (c) and (d) are taken care of by filling chip specific information in global structurei (mwifiex_sdio_sd8897). 3. For older chipsets, port 0 was cmd port and port 1->15 were data port. Therefore we had CTRL_PORT_MASK to differentiate port type. Now these changes are under 'has_control_mask' flag. Signed-off-by: Yogesh Ashok Powar Signed-off-by: Amitkumar Karwar Signed-off-by: Nishant Sarmukadam Signed-off-by: Bing Zhao Signed-off-by: Frank Huang Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/Kconfig | 4 +- drivers/net/wireless/mwifiex/sdio.c | 267 +++++++++++++++++++++------ drivers/net/wireless/mwifiex/sdio.h | 105 ++++++++++- 3 files changed, 315 insertions(+), 61 deletions(-) diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index 4f614aad9ded..f7ff4725506a 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig @@ -3,13 +3,13 @@ config MWIFIEX depends on CFG80211 ---help--- This adds support for wireless adapters based on Marvell - 802.11n chipsets. + 802.11n/ac chipsets. If you choose to build it as a module, it will be called mwifiex. config MWIFIEX_SDIO - tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797" + tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8897" depends on MWIFIEX && MMC select FW_LOADER ---help--- diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 4b196dc97463..5ee5ed02eccd 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -84,6 +84,8 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) card->reg = data->reg; card->max_ports = data->max_ports; card->mp_agg_pkt_limit = data->mp_agg_pkt_limit; + card->supports_sdio_new_mode = data->supports_sdio_new_mode; + card->has_control_mask = data->has_control_mask; } sdio_claim_host(func); @@ -260,6 +262,8 @@ static int mwifiex_sdio_resume(struct device *dev) #define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) /* Device ID for SD8797 */ #define SDIO_DEVICE_ID_MARVELL_8797 (0x9129) +/* Device ID for SD8897 */ +#define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) /* WLAN IDs */ static const struct sdio_device_id mwifiex_ids[] = { @@ -269,6 +273,8 @@ static const struct sdio_device_id mwifiex_ids[] = { .driver_data = (unsigned long) &mwifiex_sdio_sd8787}, {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797), .driver_data = (unsigned long) &mwifiex_sdio_sd8797}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897), + .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, {}, }; @@ -412,7 +418,40 @@ static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) } /* - * This function initializes the IO ports. + * This function is used to initialize IO ports for the + * chipsets supporting SDIO new mode eg SD8897. + */ +static int mwifiex_init_sdio_new_mode(struct mwifiex_adapter *adapter) +{ + u8 reg; + + adapter->ioport = MEM_PORT; + + /* enable sdio new mode */ + if (mwifiex_read_reg(adapter, CARD_CONFIG_2_1_REG, ®)) + return -1; + if (mwifiex_write_reg(adapter, CARD_CONFIG_2_1_REG, + reg | CMD53_NEW_MODE)) + return -1; + + /* Configure cmd port and enable reading rx length from the register */ + if (mwifiex_read_reg(adapter, CMD_CONFIG_0, ®)) + return -1; + if (mwifiex_write_reg(adapter, CMD_CONFIG_0, reg | CMD_PORT_RD_LEN_EN)) + return -1; + + /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is + * completed + */ + if (mwifiex_read_reg(adapter, CMD_CONFIG_1, ®)) + return -1; + if (mwifiex_write_reg(adapter, CMD_CONFIG_1, reg | CMD_PORT_AUTO_EN)) + return -1; + + return 0; +} + +/* This function initializes the IO ports. * * The following operations are performed - * - Read the IO ports (0, 1 and 2) @@ -426,6 +465,12 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) adapter->ioport = 0; + if (card->supports_sdio_new_mode) { + if (mwifiex_init_sdio_new_mode(adapter)) + return -1; + goto cont; + } + /* Read the IO port */ if (!mwifiex_read_reg(adapter, IO_PORT_0_REG, ®)) adapter->ioport |= (reg & 0xff); @@ -441,7 +486,7 @@ static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) adapter->ioport |= ((reg & 0xff) << 16); else return -1; - +cont: pr_debug("info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); /* Set Host interrupt reset to read to clear */ @@ -504,10 +549,16 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) dev_dbg(adapter->dev, "data: mp_rd_bitmap=0x%08x\n", rd_bitmap); - if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) - return -1; + if (card->supports_sdio_new_mode) { + if (!(rd_bitmap & reg->data_port_mask)) + return -1; + } else { + if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) + return -1; + } - if (card->mp_rd_bitmap & CTRL_PORT_MASK) { + if ((card->has_control_mask) && + (card->mp_rd_bitmap & CTRL_PORT_MASK)) { card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK); *port = CTRL_PORT; dev_dbg(adapter->dev, "data: port=%d mp_rd_bitmap=0x%08x\n", @@ -542,24 +593,34 @@ static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port) { struct sdio_mmc_card *card = adapter->card; + const struct mwifiex_sdio_card_reg *reg = card->reg; u32 wr_bitmap = card->mp_wr_bitmap; dev_dbg(adapter->dev, "data: mp_wr_bitmap=0x%08x\n", wr_bitmap); - if (!(wr_bitmap & card->mp_data_port_mask)) + if (card->supports_sdio_new_mode && + !(wr_bitmap & reg->data_port_mask)) { + adapter->data_sent = true; + return -EBUSY; + } else if (!card->supports_sdio_new_mode && + !(wr_bitmap & card->mp_data_port_mask)) { return -1; + } if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port)); *port = card->curr_wr_port; - if (++card->curr_wr_port == card->mp_end_port) - card->curr_wr_port = card->reg->start_wr_port; + if (((card->supports_sdio_new_mode) && + (++card->curr_wr_port == card->max_ports)) || + ((!card->supports_sdio_new_mode) && + (++card->curr_wr_port == card->mp_end_port))) + card->curr_wr_port = reg->start_wr_port; } else { adapter->data_sent = true; return -EBUSY; } - if (*port == CTRL_PORT) { + if ((card->has_control_mask) && (*port == CTRL_PORT)) { dev_err(adapter->dev, "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", *port, card->curr_wr_port, wr_bitmap, @@ -904,6 +965,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) if (sdio_ireg) { /* * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * For SDIO new mode CMD port interrupts + * DN_LD_CMD_PORT_HOST_INT_STATUS and/or + * UP_LD_CMD_PORT_HOST_INT_STATUS * Clear the interrupt status register */ dev_dbg(adapter->dev, "int: sdio_ireg = %#x\n", sdio_ireg); @@ -1031,7 +1095,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, u8 *curr_ptr; u32 rx_len = skb->len; - if (port == CTRL_PORT) { + if ((card->has_control_mask) && (port == CTRL_PORT)) { /* Read the command Resp without aggr */ dev_dbg(adapter->dev, "info: %s: no aggregation for cmd " "response\n", __func__); @@ -1048,7 +1112,10 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, goto rx_curr_single; } - if (card->mp_rd_bitmap & (~((u32) CTRL_PORT_MASK))) { + if ((!card->has_control_mask && (card->mp_rd_bitmap & + card->reg->data_port_mask)) || + (card->has_control_mask && (card->mp_rd_bitmap & + (~((u32) CTRL_PORT_MASK))))) { /* Some more data RX pending */ dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); @@ -1100,8 +1167,25 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "info: do_rx_aggr: num of packets: %d\n", card->mpa_rx.pkt_cnt); - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (card->mpa_rx.ports << 4)) + card->mpa_rx.start_port; + if (card->supports_sdio_new_mode) { + int i; + u32 port_count; + + for (i = 0, port_count = 0; i < card->max_ports; i++) + if (card->mpa_rx.ports & BIT(i)) + port_count++; + + /* Reading data from "start_port + 0" to "start_port + + * port_count -1", so decrease the count by 1 + */ + port_count--; + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | + (port_count << 8)) + card->mpa_rx.start_port; + } else { + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | + (card->mpa_rx.ports << 4)) + + card->mpa_rx.start_port; + } if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, card->mpa_rx.buf_len, mport, 1)) @@ -1200,6 +1284,8 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) u32 rx_blocks; u16 rx_len; unsigned long flags; + u32 bitmap; + u8 cr; spin_lock_irqsave(&adapter->int_lock, flags); sdio_ireg = adapter->int_status; @@ -1209,12 +1295,60 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) if (!sdio_ireg) return ret; + /* Following interrupt is only for SDIO new mode */ + if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent) + adapter->cmd_sent = false; + + /* Following interrupt is only for SDIO new mode */ + if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) { + u32 pkt_type; + + /* read the len of control packet */ + rx_len = card->mp_regs[CMD_RD_LEN_1] << 8; + rx_len |= (u16) card->mp_regs[CMD_RD_LEN_0]; + rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE); + if (rx_len <= INTF_HEADER_LEN || + (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > + MWIFIEX_RX_DATA_BUF_SIZE) + return -1; + rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); + + skb = dev_alloc_skb(rx_len); + if (!skb) + return -1; + + skb_put(skb, rx_len); + + if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data, + skb->len, adapter->ioport | + CMD_PORT_SLCT)) { + dev_err(adapter->dev, + "%s: failed to card_to_host", __func__); + dev_kfree_skb_any(skb); + goto term_cmd; + } + + if ((pkt_type != MWIFIEX_TYPE_CMD) && + (pkt_type != MWIFIEX_TYPE_EVENT)) + dev_err(adapter->dev, + "%s:Received wrong packet on cmd port", + __func__); + + mwifiex_decode_rx_packet(adapter, skb, pkt_type); + } + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { - card->mp_wr_bitmap = - ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8; - card->mp_wr_bitmap |= - (u32) card->mp_regs[reg->wr_bitmap_l]; - dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%08x\n", + bitmap = (u32) card->mp_regs[reg->wr_bitmap_l]; + bitmap |= ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8; + if (card->supports_sdio_new_mode) { + bitmap |= + ((u32) card->mp_regs[reg->wr_bitmap_1l]) << 16; + bitmap |= + ((u32) card->mp_regs[reg->wr_bitmap_1u]) << 24; + } + card->mp_wr_bitmap = bitmap; + + dev_dbg(adapter->dev, "int: DNLD: wr_bitmap=0x%x\n", card->mp_wr_bitmap); if (adapter->data_sent && (card->mp_wr_bitmap & card->mp_data_port_mask)) { @@ -1227,7 +1361,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) /* As firmware will not generate download ready interrupt if the port updated is command port only, cmd_sent should be done for any SDIO interrupt. */ - if (adapter->cmd_sent) { + if (card->has_control_mask && adapter->cmd_sent) { /* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */ card->mp_wr_bitmap |= @@ -1239,10 +1373,16 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n", adapter->cmd_sent, adapter->data_sent); if (sdio_ireg & UP_LD_HOST_INT_STATUS) { - card->mp_rd_bitmap = - ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8; - card->mp_rd_bitmap |= (u32) card->mp_regs[reg->rd_bitmap_l]; - dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%08x\n", + bitmap = (u32) card->mp_regs[reg->rd_bitmap_l]; + bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8; + if (card->supports_sdio_new_mode) { + bitmap |= + ((u32) card->mp_regs[reg->rd_bitmap_1l]) << 16; + bitmap |= + ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24; + } + card->mp_rd_bitmap = bitmap; + dev_dbg(adapter->dev, "int: UPLD: rd_bitmap=0x%x\n", card->mp_rd_bitmap); while (true) { @@ -1285,37 +1425,33 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, port)) { - u8 cr = 0; - dev_err(adapter->dev, "card_to_host_mpa failed:" " int status=%#x\n", sdio_ireg); - if (mwifiex_read_reg(adapter, - CONFIGURATION_REG, &cr)) - dev_err(adapter->dev, - "read CFG reg failed\n"); - - dev_dbg(adapter->dev, - "info: CFG reg val = %d\n", cr); - if (mwifiex_write_reg(adapter, - CONFIGURATION_REG, - (cr | 0x04))) - dev_err(adapter->dev, - "write CFG reg failed\n"); - - dev_dbg(adapter->dev, "info: write success\n"); - if (mwifiex_read_reg(adapter, - CONFIGURATION_REG, &cr)) - dev_err(adapter->dev, - "read CFG reg failed\n"); - - dev_dbg(adapter->dev, - "info: CFG reg val =%x\n", cr); - return -1; + goto term_cmd; } } } return 0; + +term_cmd: + /* terminate cmd */ + if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr)) + dev_err(adapter->dev, "read CFG reg failed\n"); + else + dev_dbg(adapter->dev, "info: CFG reg val = %d\n", cr); + + if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04))) + dev_err(adapter->dev, "write CFG reg failed\n"); + else + dev_dbg(adapter->dev, "info: write success\n"); + + if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr)) + dev_err(adapter->dev, "read CFG reg failed\n"); + else + dev_dbg(adapter->dev, "info: CFG reg val =%x\n", cr); + + return -1; } /* @@ -1344,7 +1480,9 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, s32 f_postcopy_cur_buf = 0; u32 mport; - if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) { + if (!card->mpa_tx.enabled || + (card->has_control_mask && (port == CTRL_PORT)) || + (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) { dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n", __func__); @@ -1419,8 +1557,26 @@ static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n", __func__, card->mpa_tx.start_port, card->mpa_tx.ports); - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (card->mpa_tx.ports << 4)) + card->mpa_tx.start_port; + if (card->supports_sdio_new_mode) { + u32 port_count; + int i; + + for (i = 0, port_count = 0; i < card->max_ports; i++) + if (card->mpa_tx.ports & BIT(i)) + port_count++; + + /* Writing data from "start_port + 0" to "start_port + + * port_count -1", so decrease the count by 1 + */ + port_count--; + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | + (port_count << 8)) + card->mpa_tx.start_port; + } else { + mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | + (card->mpa_tx.ports << 4)) + + card->mpa_tx.start_port; + } + ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, card->mpa_tx.buf_len, mport); @@ -1493,6 +1649,9 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, pkt_len > MWIFIEX_UPLD_SIZE) dev_err(adapter->dev, "%s: payload=%p, nb=%d\n", __func__, payload, pkt_len); + + if (card->supports_sdio_new_mode) + port = CMD_PORT_SLCT; } /* Transfer data to card */ @@ -1748,8 +1907,11 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) card->mp_data_port_mask = reg->data_port_mask; - for (i = 1; i <= card->max_ports - card->mp_end_port; i++) - card->mp_data_port_mask &= ~(1 << (card->max_ports - i)); + if (reg->start_wr_port) { + for (i = 1; i <= card->max_ports - card->mp_end_port; i++) + card->mp_data_port_mask &= + ~(1 << (card->max_ports - i)); + } card->curr_wr_port = reg->start_wr_port; @@ -1857,3 +2019,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); +MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 597db37a45f9..6d51dfdd8251 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -32,6 +32,7 @@ #define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin" #define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" #define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" +#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" #define BLOCK_MODE 1 #define BYTE_MODE 0 @@ -46,6 +47,23 @@ #define CTRL_PORT 0 #define CTRL_PORT_MASK 0x0001 +#define CMD_PORT_UPLD_INT_MASK (0x1U<<6) +#define CMD_PORT_DNLD_INT_MASK (0x1U<<7) +#define HOST_TERM_CMD53 (0x1U << 2) +#define REG_PORT 0 +#define MEM_PORT 0x10000 +#define CMD_RD_LEN_0 0xB4 +#define CMD_RD_LEN_1 0xB5 +#define CARD_CONFIG_2_1_REG 0xCD +#define CMD53_NEW_MODE (0x1U << 0) +#define CMD_CONFIG_0 0xB8 +#define CMD_PORT_RD_LEN_EN (0x1U << 2) +#define CMD_CONFIG_1 0xB9 +#define CMD_PORT_AUTO_EN (0x1U << 0) +#define CMD_PORT_SLCT 0x8000 +#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U) +#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U) + #define SDIO_MP_TX_AGGR_DEF_BUF_SIZE (8192) /* 8K */ /* Multi port RX aggregation buffer size */ @@ -73,6 +91,7 @@ #define UP_LD_HOST_INT_MASK (0x1U) /* Host Control Registers : Download host interrupt mask */ #define DN_LD_HOST_INT_MASK (0x2U) + /* Disable Host interrupt mask */ #define HOST_INT_DISABLE 0xff @@ -196,8 +215,12 @@ struct mwifiex_sdio_card_reg { u8 max_mp_regs; u8 rd_bitmap_l; u8 rd_bitmap_u; + u8 rd_bitmap_1l; + u8 rd_bitmap_1u; u8 wr_bitmap_l; u8 wr_bitmap_u; + u8 wr_bitmap_1l; + u8 wr_bitmap_1u; u8 rd_len_p0_l; u8 rd_len_p0_u; u8 card_misc_cfg_reg; @@ -211,6 +234,8 @@ struct sdio_mmc_card { const struct mwifiex_sdio_card_reg *reg; u8 max_ports; u8 mp_agg_pkt_limit; + bool supports_sdio_new_mode; + bool has_control_mask; u32 mp_rd_bitmap; u32 mp_wr_bitmap; @@ -232,6 +257,8 @@ struct mwifiex_sdio_device { const struct mwifiex_sdio_card_reg *reg; u8 max_ports; u8 mp_agg_pkt_limit; + bool supports_sdio_new_mode; + bool has_control_mask; }; static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { @@ -255,11 +282,39 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { .card_misc_cfg_reg = 0x6c, }; +static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = { + .start_rd_port = 0, + .start_wr_port = 0, + .base_0_reg = 0x60, + .base_1_reg = 0x61, + .poll_reg = 0x50, + .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | + CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, + .status_reg_0 = 0xc0, + .status_reg_1 = 0xc1, + .sdio_int_mask = 0xff, + .data_port_mask = 0xffffffff, + .max_mp_regs = 184, + .rd_bitmap_l = 0x04, + .rd_bitmap_u = 0x05, + .rd_bitmap_1l = 0x06, + .rd_bitmap_1u = 0x07, + .wr_bitmap_l = 0x08, + .wr_bitmap_u = 0x09, + .wr_bitmap_1l = 0x0a, + .wr_bitmap_1u = 0x0b, + .rd_len_p0_l = 0x0c, + .rd_len_p0_u = 0x0d, + .card_misc_cfg_reg = 0xcc, +}; + static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { .firmware = SD8786_DEFAULT_FW_NAME, .reg = &mwifiex_reg_sd87xx, .max_ports = 16, .mp_agg_pkt_limit = 8, + .supports_sdio_new_mode = false, + .has_control_mask = true, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { @@ -267,6 +322,8 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { .reg = &mwifiex_reg_sd87xx, .max_ports = 16, .mp_agg_pkt_limit = 8, + .supports_sdio_new_mode = false, + .has_control_mask = true, }; static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { @@ -274,6 +331,17 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { .reg = &mwifiex_reg_sd87xx, .max_ports = 16, .mp_agg_pkt_limit = 8, + .supports_sdio_new_mode = false, + .has_control_mask = true, +}; + +static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { + .firmware = SD8897_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd8897, + .max_ports = 32, + .mp_agg_pkt_limit = 16, + .supports_sdio_new_mode = true, + .has_control_mask = false, }; /* @@ -302,13 +370,23 @@ mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card) u8 tmp; if (card->curr_rd_port < card->mpa_rx.start_port) { - tmp = card->mp_agg_pkt_limit; + if (card->supports_sdio_new_mode) + tmp = card->mp_end_port >> 1; + else + tmp = card->mp_agg_pkt_limit; if (((card->max_ports - card->mpa_rx.start_port) + card->curr_rd_port) >= tmp) return true; } + if (!card->supports_sdio_new_mode) + return false; + + if ((card->curr_rd_port - card->mpa_rx.start_port) >= + (card->mp_end_port >> 1)) + return true; + return false; } @@ -318,13 +396,23 @@ mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) u16 tmp; if (card->curr_wr_port < card->mpa_tx.start_port) { - tmp = card->mp_agg_pkt_limit; + if (card->supports_sdio_new_mode) + tmp = card->mp_end_port >> 1; + else + tmp = card->mp_agg_pkt_limit; if (((card->max_ports - card->mpa_tx.start_port) + card->curr_wr_port) >= tmp) return true; } + if (!card->supports_sdio_new_mode) + return false; + + if ((card->curr_wr_port - card->mpa_tx.start_port) >= + (card->mp_end_port >> 1)) + return true; + return false; } @@ -337,11 +425,14 @@ static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, if (!card->mpa_rx.pkt_cnt) card->mpa_rx.start_port = port; - if (card->mpa_rx.start_port <= port) - card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt); - else - card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); - + if (card->supports_sdio_new_mode) { + card->mpa_rx.ports |= (1 << port); + } else { + if (card->mpa_rx.start_port <= port) + card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt); + else + card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); + } card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = skb; card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = skb->len; card->mpa_rx.pkt_cnt++; -- GitLab From f91f5f05f99099402b807f2aa346685a0284ba48 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Tue, 21 May 2013 10:42:40 +0800 Subject: [PATCH 0235/2900] drivers/net/wireless/brcm80211/brcmfmac: add missing platform_driver owner set the owner of platform_driver, to ensure that the caller of driver holds a module refernece Signed-off-by: Libo Chen Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 44fa0cdbf97b..11400b39cf0b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -606,7 +606,8 @@ static int brcmf_sdio_pd_remove(struct platform_device *pdev) static struct platform_driver brcmf_sdio_pd = { .remove = brcmf_sdio_pd_remove, .driver = { - .name = BRCMFMAC_SDIO_PDATA_NAME + .name = BRCMFMAC_SDIO_PDATA_NAME, + .owner = THIS_MODULE, } }; -- GitLab From 61c951503be1935f24760ae6c43483c5c9529646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:06 +0000 Subject: [PATCH 0236/2900] net/ethernet/silan/sc92031: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/silan/sc92031.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/ethernet/silan/sc92031.c b/drivers/net/ethernet/silan/sc92031.c index 28f7268f1b88..5eb933c97bba 100644 --- a/drivers/net/ethernet/silan/sc92031.c +++ b/drivers/net/ethernet/silan/sc92031.c @@ -1578,19 +1578,7 @@ static struct pci_driver sc92031_pci_driver = { .resume = sc92031_resume, }; -static int __init sc92031_init(void) -{ - return pci_register_driver(&sc92031_pci_driver); -} - -static void __exit sc92031_exit(void) -{ - pci_unregister_driver(&sc92031_pci_driver); -} - -module_init(sc92031_init); -module_exit(sc92031_exit); - +module_pci_driver(sc92031_pci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cesar Eduardo Barros "); MODULE_DESCRIPTION("Silan SC92031 PCI Fast Ethernet Adapter driver"); -- GitLab From 2c21d6c98813829fad79b17460fd289109a77099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:07 +0000 Subject: [PATCH 0237/2900] net/ethernet/atheros/atl1c/atl1c_main: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- .../net/ethernet/atheros/atl1c/atl1c_main.c | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 0ba900762b13..786a87483298 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -2755,27 +2755,4 @@ static struct pci_driver atl1c_driver = { .driver.pm = &atl1c_pm_ops, }; -/** - * atl1c_init_module - Driver Registration Routine - * - * atl1c_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - */ -static int __init atl1c_init_module(void) -{ - return pci_register_driver(&atl1c_driver); -} - -/** - * atl1c_exit_module - Driver Exit Cleanup Routine - * - * atl1c_exit_module is called just before the driver is removed - * from memory. - */ -static void __exit atl1c_exit_module(void) -{ - pci_unregister_driver(&atl1c_driver); -} - -module_init(atl1c_init_module); -module_exit(atl1c_exit_module); +module_pci_driver(atl1c_driver); -- GitLab From 687df5d489cd1ddf7d2d231bd824f6b687bfb26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:08 +0000 Subject: [PATCH 0238/2900] net/ethernet/atheros/atl1e/atl1e_main: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- .../net/ethernet/atheros/atl1e/atl1e_main.c | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 0688bb82b442..895f5377ad1b 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -2489,27 +2489,4 @@ static struct pci_driver atl1e_driver = { .err_handler = &atl1e_err_handler }; -/** - * atl1e_init_module - Driver Registration Routine - * - * atl1e_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - */ -static int __init atl1e_init_module(void) -{ - return pci_register_driver(&atl1e_driver); -} - -/** - * atl1e_exit_module - Driver Exit Cleanup Routine - * - * atl1e_exit_module is called just before the driver is removed - * from memory. - */ -static void __exit atl1e_exit_module(void) -{ - pci_unregister_driver(&atl1e_driver); -} - -module_init(atl1e_init_module); -module_exit(atl1e_exit_module); +module_pci_driver(atl1e_driver); -- GitLab From c996f4e8f053ddab28fa196e5b18bdd93e8ee3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:09 +0000 Subject: [PATCH 0239/2900] net/ethernet/atheros/atlx/atl1: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atlx/atl1.c | 27 ++---------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index fa0915f3999b..538211d6f7d9 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -3145,31 +3145,6 @@ static struct pci_driver atl1_driver = { .driver.pm = &atl1_pm_ops, }; -/** - * atl1_exit_module - Driver Exit Cleanup Routine - * - * atl1_exit_module is called just before the driver is removed - * from memory. - */ -static void __exit atl1_exit_module(void) -{ - pci_unregister_driver(&atl1_driver); -} - -/** - * atl1_init_module - Driver Registration Routine - * - * atl1_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - */ -static int __init atl1_init_module(void) -{ - return pci_register_driver(&atl1_driver); -} - -module_init(atl1_init_module); -module_exit(atl1_exit_module); - struct atl1_stats { char stat_string[ETH_GSTRING_LEN]; int sizeof_stat; @@ -3705,3 +3680,5 @@ static const struct ethtool_ops atl1_ethtool_ops = { .get_ethtool_stats = atl1_get_ethtool_stats, .get_sset_count = atl1_get_sset_count, }; + +module_pci_driver(atl1_driver); -- GitLab From 52a58f9df12ab03bda432b398a4bdfcc9ed2b414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:10 +0000 Subject: [PATCH 0240/2900] net/ethernet/sis/sis190: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/sis/sis190.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index 9a9c379420d1..02df0894690d 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -1934,15 +1934,4 @@ static struct pci_driver sis190_pci_driver = { .remove = sis190_remove_one, }; -static int __init sis190_init_module(void) -{ - return pci_register_driver(&sis190_pci_driver); -} - -static void __exit sis190_cleanup_module(void) -{ - pci_unregister_driver(&sis190_pci_driver); -} - -module_init(sis190_init_module); -module_exit(sis190_cleanup_module); +module_pci_driver(sis190_pci_driver); -- GitLab From 31d60ebfbe6792068e8951741f92f40bdea97837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:11 +0000 Subject: [PATCH 0241/2900] net/ethernet/dec/tulip/xircom_cb: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Reviewed-by: Grant Grundler Signed-off-by: David S. Miller --- drivers/net/ethernet/dec/tulip/xircom_cb.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/ethernet/dec/tulip/xircom_cb.c b/drivers/net/ethernet/dec/tulip/xircom_cb.c index cdbcd1643141..9b84cb04fe5f 100644 --- a/drivers/net/ethernet/dec/tulip/xircom_cb.c +++ b/drivers/net/ethernet/dec/tulip/xircom_cb.c @@ -1171,16 +1171,4 @@ investigate_write_descriptor(struct net_device *dev, } } -static int __init xircom_init(void) -{ - return pci_register_driver(&xircom_ops); -} - -static void __exit xircom_exit(void) -{ - pci_unregister_driver(&xircom_ops); -} - -module_init(xircom_init) -module_exit(xircom_exit) - +module_pci_driver(xircom_ops); -- GitLab From b6f5721087e72d11ff3daab565afddc5918c024b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:12 +0000 Subject: [PATCH 0242/2900] net/ethernet/toshiba/tc35815: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/toshiba/tc35815.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c index fe256094db35..a971b9cca564 100644 --- a/drivers/net/ethernet/toshiba/tc35815.c +++ b/drivers/net/ethernet/toshiba/tc35815.c @@ -2209,18 +2209,6 @@ MODULE_PARM_DESC(speed, "0:auto, 10:10Mbps, 100:100Mbps"); module_param_named(duplex, options.duplex, int, 0); MODULE_PARM_DESC(duplex, "0:auto, 1:half, 2:full"); -static int __init tc35815_init_module(void) -{ - return pci_register_driver(&tc35815_pci_driver); -} - -static void __exit tc35815_cleanup_module(void) -{ - pci_unregister_driver(&tc35815_pci_driver); -} - -module_init(tc35815_init_module); -module_exit(tc35815_cleanup_module); - +module_pci_driver(tc35815_pci_driver); MODULE_DESCRIPTION("TOSHIBA TC35815 PCI 10M/100M Ethernet driver"); MODULE_LICENSE("GPL"); -- GitLab From 43d426c3f938b9ac21f452fcd22956ed2f526f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:13 +0000 Subject: [PATCH 0243/2900] net/ethernet/icplus/ipg: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/icplus/ipg.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c index 068d78151658..1fde90b96685 100644 --- a/drivers/net/ethernet/icplus/ipg.c +++ b/drivers/net/ethernet/icplus/ipg.c @@ -2298,15 +2298,4 @@ static struct pci_driver ipg_pci_driver = { .remove = ipg_remove, }; -static int __init ipg_init_module(void) -{ - return pci_register_driver(&ipg_pci_driver); -} - -static void __exit ipg_exit_module(void) -{ - pci_unregister_driver(&ipg_pci_driver); -} - -module_init(ipg_init_module); -module_exit(ipg_exit_module); +module_pci_driver(ipg_pci_driver); -- GitLab From e6d20fca76cfe4a36f8dbaac6b3847e6dad63e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:42:14 +0000 Subject: [PATCH 0244/2900] net/ethernet/alteon/acenic: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/alteon/acenic.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index b7894f8af9d1..219be1bf3cfc 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -702,19 +702,6 @@ static struct pci_driver acenic_pci_driver = { .remove = acenic_remove_one, }; -static int __init acenic_init(void) -{ - return pci_register_driver(&acenic_pci_driver); -} - -static void __exit acenic_exit(void) -{ - pci_unregister_driver(&acenic_pci_driver); -} - -module_init(acenic_init); -module_exit(acenic_exit); - static void ace_free_descriptors(struct net_device *dev) { struct ace_private *ap = netdev_priv(dev); @@ -3199,3 +3186,5 @@ static int read_eeprom_byte(struct net_device *dev, unsigned long offset) ap->name, offset); goto out; } + +module_pci_driver(acenic_pci_driver); -- GitLab From 5a4123f39ef14fc7c043f1611ed3b20b69325146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:05 +0000 Subject: [PATCH 0245/2900] net/ethernet/broadcom/bnx2: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 5d204492c603..1a1b23eb13dc 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -8764,18 +8764,4 @@ static struct pci_driver bnx2_pci_driver = { .err_handler = &bnx2_err_handler, }; -static int __init bnx2_init(void) -{ - return pci_register_driver(&bnx2_pci_driver); -} - -static void __exit bnx2_cleanup(void) -{ - pci_unregister_driver(&bnx2_pci_driver); -} - -module_init(bnx2_init); -module_exit(bnx2_cleanup); - - - +module_pci_driver(bnx2_pci_driver); -- GitLab From 8dbb0dc2cb16096efe998c576170e41dc6e8b64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:06 +0000 Subject: [PATCH 0246/2900] net/ethernet/broadcom/tg3: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Acked-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index fb06aa120293..4f0e3fe99e17 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17804,15 +17804,4 @@ static struct pci_driver tg3_driver = { .driver.pm = &tg3_pm_ops, }; -static int __init tg3_init(void) -{ - return pci_register_driver(&tg3_driver); -} - -static void __exit tg3_cleanup(void) -{ - pci_unregister_driver(&tg3_driver); -} - -module_init(tg3_init); -module_exit(tg3_cleanup); +module_pci_driver(tg3_driver); -- GitLab From e0fc4441f98e19d8120f2a385c9e75bc55369b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:07 +0000 Subject: [PATCH 0247/2900] net/ethernet/sgi/ioc3-eth: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/sgi/ioc3-eth.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 7ed08c32a9c5..ffa78432164d 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -1398,16 +1398,6 @@ static struct pci_driver ioc3_driver = { .remove = ioc3_remove_one, }; -static int __init ioc3_init_module(void) -{ - return pci_register_driver(&ioc3_driver); -} - -static void __exit ioc3_cleanup_module(void) -{ - pci_unregister_driver(&ioc3_driver); -} - static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned long data; @@ -1677,9 +1667,7 @@ static void ioc3_set_multicast_list(struct net_device *dev) netif_wake_queue(dev); /* Let us get going again. */ } +module_pci_driver(ioc3_driver); MODULE_AUTHOR("Ralf Baechle "); MODULE_DESCRIPTION("SGI IOC3 Ethernet driver"); MODULE_LICENSE("GPL"); - -module_init(ioc3_init_module); -module_exit(ioc3_cleanup_module); -- GitLab From 70a611debe964ae508d67528d82ca7fa0715f5a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:08 +0000 Subject: [PATCH 0248/2900] net/ethernet/qlogic/qlge/qlge_main: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 50235d201592..e04d471acb10 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -4945,15 +4945,4 @@ static struct pci_driver qlge_driver = { .err_handler = &qlge_err_handler }; -static int __init qlge_init_module(void) -{ - return pci_register_driver(&qlge_driver); -} - -static void __exit qlge_exit(void) -{ - pci_unregister_driver(&qlge_driver); -} - -module_init(qlge_init_module); -module_exit(qlge_exit); +module_pci_driver(qlge_driver); -- GitLab From 5119ad0b7388641815bad0bacdc5133532d24685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:09 +0000 Subject: [PATCH 0249/2900] net/ethernet/sun/sungem: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sungem.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index 5f3f9d52757d..e62df2b81302 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -3028,15 +3028,4 @@ static struct pci_driver gem_driver = { #endif /* CONFIG_PM */ }; -static int __init gem_init(void) -{ - return pci_register_driver(&gem_driver); -} - -static void __exit gem_cleanup(void) -{ - pci_unregister_driver(&gem_driver); -} - -module_init(gem_init); -module_exit(gem_cleanup); +module_pci_driver(gem_driver); -- GitLab From a46e6ccdd1cd557cbb9a24022ee027d09a4bd625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 12:58:10 +0000 Subject: [PATCH 0250/2900] net/ethernet/amd/amd8111e: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/amd8111e.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 8e6b665a6726..bc71aec1159d 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1981,15 +1981,4 @@ static struct pci_driver amd8111e_driver = { .resume = amd8111e_resume }; -static int __init amd8111e_init(void) -{ - return pci_register_driver(&amd8111e_driver); -} - -static void __exit amd8111e_cleanup(void) -{ - pci_unregister_driver(&amd8111e_driver); -} - -module_init(amd8111e_init); -module_exit(amd8111e_cleanup); +module_pci_driver(amd8111e_driver); -- GitLab From ff7150550d9e3d9dd9ceadebbe8ee45e74c1ffdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 13:42:53 +0000 Subject: [PATCH 0251/2900] net/hippi/rrunner: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/hippi/rrunner.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 3c4d6274bb9b..00ed75155ce8 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -1686,15 +1686,4 @@ static struct pci_driver rr_driver = { .remove = rr_remove_one, }; -static int __init rr_init_module(void) -{ - return pci_register_driver(&rr_driver); -} - -static void __exit rr_cleanup_module(void) -{ - pci_unregister_driver(&rr_driver); -} - -module_init(rr_init_module); -module_exit(rr_cleanup_module); +module_pci_driver(rr_driver); -- GitLab From 30d05f9ef7c2caa7efd8ca5c0698ff5e9d5542ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 13:42:54 +0000 Subject: [PATCH 0252/2900] net/fddi/skfp/skfddi: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/skfddi.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index d5bd563ac131..f5d7305a5784 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -2246,15 +2246,4 @@ static struct pci_driver skfddi_pci_driver = { .remove = skfp_remove_one, }; -static int __init skfd_init(void) -{ - return pci_register_driver(&skfddi_pci_driver); -} - -static void __exit skfd_exit(void) -{ - pci_unregister_driver(&skfddi_pci_driver); -} - -module_init(skfd_init); -module_exit(skfd_exit); +module_pci_driver(skfddi_pci_driver); -- GitLab From 65c21912b5b977f32a12336e87fe32f36105b981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 13:42:55 +0000 Subject: [PATCH 0253/2900] net/ethernet/chelsio/cxgb/cxgb2: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. The name of the pci_driver struct had to be changed in order to prevent a build failure. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c index 9624cfe7df57..d7048db9863d 100644 --- a/drivers/net/ethernet/chelsio/cxgb/cxgb2.c +++ b/drivers/net/ethernet/chelsio/cxgb/cxgb2.c @@ -1351,22 +1351,11 @@ static void remove_one(struct pci_dev *pdev) t1_sw_reset(pdev); } -static struct pci_driver driver = { +static struct pci_driver cxgb_pci_driver = { .name = DRV_NAME, .id_table = t1_pci_tbl, .probe = init_one, .remove = remove_one, }; -static int __init t1_init_module(void) -{ - return pci_register_driver(&driver); -} - -static void __exit t1_cleanup_module(void) -{ - pci_unregister_driver(&driver); -} - -module_init(t1_init_module); -module_exit(t1_cleanup_module); +module_pci_driver(cxgb_pci_driver); -- GitLab From 4f45c40f2c018e5c278988521a74fd5ee06fb819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20H=C3=BCwe?= Date: Tue, 21 May 2013 13:42:56 +0000 Subject: [PATCH 0254/2900] net/ethernet/nvidia/forcedeth: Use module_pci_driver to register driver Removing some boilerplate by using module_pci_driver instead of calling register and unregister in the otherwise empty init/exit functions. The name of the pci_driver struct had to be changed in order to prevent a build failure. Signed-off-by: Peter Huewe Signed-off-by: David S. Miller --- drivers/net/ethernet/nvidia/forcedeth.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index b003fe53c8e2..098b96dad66f 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -6340,7 +6340,7 @@ static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { {0,}, }; -static struct pci_driver driver = { +static struct pci_driver forcedeth_pci_driver = { .name = DRV_NAME, .id_table = pci_tbl, .probe = nv_probe, @@ -6349,16 +6349,6 @@ static struct pci_driver driver = { .driver.pm = NV_PM_OPS, }; -static int __init init_nic(void) -{ - return pci_register_driver(&driver); -} - -static void __exit exit_nic(void) -{ - pci_unregister_driver(&driver); -} - module_param(max_interrupt_work, int, 0); MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt"); module_param(optimization_mode, int, 0); @@ -6379,11 +6369,8 @@ module_param(debug_tx_timeout, bool, 0); MODULE_PARM_DESC(debug_tx_timeout, "Dump tx related registers and ring when tx_timeout happens"); +module_pci_driver(forcedeth_pci_driver); MODULE_AUTHOR("Manfred Spraul "); MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); MODULE_LICENSE("GPL"); - MODULE_DEVICE_TABLE(pci, pci_tbl); - -module_init(init_nic); -module_exit(exit_nic); -- GitLab From 1c8ad5bfa2be5025b0c81e3c2decd0574d453ab1 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 21 May 2013 21:52:54 +0000 Subject: [PATCH 0255/2900] bridge: use the bridge IP addr as source addr for querier Quote from Adam: "If it is believed that the use of 0.0.0.0 as the IP address is what is causing strange behaviour on other devices then is there a good reason that a bridge rather than a router shouldn't be the active querier? If not then using the bridge IP address and having the querier enabled by default may be a reasonable solution (provided that our querier obeys the election rules and shuts up if it sees a query from a lower IP address that isn't 0.0.0.0). Just because a device is the elected querier for IGMP doesn't appear to mean it is required to perform any other routing functions." And introduce a new troggle for it, as suggested by Herbert. Suggested-by: Adam Baker Cc: Herbert Xu Cc: Stephen Hemminger Cc: "David S. Miller" Cc: Adam Baker Signed-off-by: Cong Wang Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 5 ++++- net/bridge/br_private.h | 1 + net/bridge/br_sysfs_br.c | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 81f2389f78eb..247514793101 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #if IS_ENABLED(CONFIG_IPV6) #include @@ -381,7 +382,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, iph->frag_off = htons(IP_DF); iph->ttl = 1; iph->protocol = IPPROTO_IGMP; - iph->saddr = 0; + iph->saddr = br->multicast_query_use_ifaddr ? + inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0; iph->daddr = htonl(INADDR_ALLHOSTS_GROUP); ((u8 *)&iph[1])[0] = IPOPT_RA; ((u8 *)&iph[1])[1] = 4; @@ -1618,6 +1620,7 @@ void br_multicast_init(struct net_bridge *br) br->multicast_router = 1; br->multicast_querier = 0; + br->multicast_query_use_ifaddr = 0; br->multicast_last_member_count = 2; br->multicast_startup_query_count = 2; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d2c043a857b6..e260710a01d4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -249,6 +249,7 @@ struct net_bridge u8 multicast_disabled:1; u8 multicast_querier:1; + u8 multicast_query_use_ifaddr:1; u32 hash_elasticity; u32 hash_max; diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 8baa9c08e1a4..394bb96b6087 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -375,6 +375,31 @@ static ssize_t store_multicast_snooping(struct device *d, static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, show_multicast_snooping, store_multicast_snooping); +static ssize_t show_multicast_query_use_ifaddr(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%d\n", br->multicast_query_use_ifaddr); +} + +static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val) +{ + br->multicast_query_use_ifaddr = !!val; + return 0; +} + +static ssize_t +store_multicast_query_use_ifaddr(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_query_use_ifaddr); +} +static DEVICE_ATTR(multicast_query_use_ifaddr, S_IRUGO | S_IWUSR, + show_multicast_query_use_ifaddr, + store_multicast_query_use_ifaddr); + static ssize_t show_multicast_querier(struct device *d, struct device_attribute *attr, char *buf) @@ -734,6 +759,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_multicast_router.attr, &dev_attr_multicast_snooping.attr, &dev_attr_multicast_querier.attr, + &dev_attr_multicast_query_use_ifaddr.attr, &dev_attr_hash_elasticity.attr, &dev_attr_hash_max.attr, &dev_attr_multicast_last_member_count.attr, -- GitLab From 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 21 May 2013 21:52:55 +0000 Subject: [PATCH 0256/2900] bridge: only expire the mdb entry when query is received Currently we arm the expire timer when the mdb entry is added, however, this causes problem when there is no querier sent out after that. So we should only arm the timer when a corresponding query is received, as suggested by Herbert. And he also mentioned "if there is no querier then group subscriptions shouldn't expire. There has to be at least one querier in the network for this thing to work. Otherwise it just degenerates into a non-snooping switch, which is OK." Cc: Herbert Xu Cc: Stephen Hemminger Cc: "David S. Miller" Cc: Adam Baker Signed-off-by: Cong Wang Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 39 ++++++++++++--------------------------- net/bridge/br_private.h | 1 + 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 247514793101..40bda804fbd9 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -617,8 +617,6 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, mp->br = br; mp->addr = *group; - setup_timer(&mp->timer, br_multicast_group_expired, - (unsigned long)mp); hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); mdb->size++; @@ -656,7 +654,6 @@ static int br_multicast_add_group(struct net_bridge *br, struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; - unsigned long now = jiffies; int err; spin_lock(&br->multicast_lock); @@ -671,7 +668,6 @@ static int br_multicast_add_group(struct net_bridge *br, if (!port) { mp->mglist = true; - mod_timer(&mp->timer, now + br->multicast_membership_interval); goto out; } @@ -679,7 +675,7 @@ static int br_multicast_add_group(struct net_bridge *br, (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { if (p->port == port) - goto found; + goto out; if ((unsigned long)p->port < (unsigned long)port) break; } @@ -690,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br, rcu_assign_pointer(*pp, p); br_mdb_notify(br->dev, port, group, RTM_NEWMDB); -found: - mod_timer(&p->timer, now + br->multicast_membership_interval); out: err = 0; @@ -1131,6 +1125,10 @@ static int br_ip4_multicast_query(struct net_bridge *br, if (!mp) goto out; + setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); + mod_timer(&mp->timer, now + br->multicast_membership_interval); + mp->timer_armed = true; + max_delay *= br->multicast_last_member_count; if (mp->mglist && @@ -1205,6 +1203,10 @@ static int br_ip6_multicast_query(struct net_bridge *br, if (!mp) goto out; + setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); + mod_timer(&mp->timer, now + br->multicast_membership_interval); + mp->timer_armed = true; + max_delay *= br->multicast_last_member_count; if (mp->mglist && (timer_pending(&mp->timer) ? @@ -1263,7 +1265,7 @@ static void br_multicast_leave_group(struct net_bridge *br, call_rcu_bh(&p->rcu, br_multicast_free_pg); br_mdb_notify(br->dev, port, group, RTM_DELMDB); - if (!mp->ports && !mp->mglist && + if (!mp->ports && !mp->mglist && mp->timer_armed && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); } @@ -1275,30 +1277,12 @@ static void br_multicast_leave_group(struct net_bridge *br, br->multicast_last_member_interval; if (!port) { - if (mp->mglist && + if (mp->mglist && mp->timer_armed && (timer_pending(&mp->timer) ? time_after(mp->timer.expires, time) : try_to_del_timer_sync(&mp->timer) >= 0)) { mod_timer(&mp->timer, time); } - - goto out; - } - - for (p = mlock_dereference(mp->ports, br); - p != NULL; - p = mlock_dereference(p->next, br)) { - if (p->port != port) - continue; - - if (!hlist_unhashed(&p->mglist) && - (timer_pending(&p->timer) ? - time_after(p->timer.expires, time) : - try_to_del_timer_sync(&p->timer) >= 0)) { - mod_timer(&p->timer, time); - } - - break; } out: @@ -1674,6 +1658,7 @@ void br_multicast_stop(struct net_bridge *br) hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], hlist[ver]) { del_timer(&mp->timer); + mp->timer_armed = false; call_rcu_bh(&mp->rcu, br_multicast_free_group); } } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e260710a01d4..1b0ac95a5c37 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -112,6 +112,7 @@ struct net_bridge_mdb_entry struct timer_list timer; struct br_ip addr; bool mglist; + bool timer_armed; }; struct net_bridge_mdb_htable -- GitLab From 6b7df111ece130fa979a0c4f58e53674c1e47d3e Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 21 May 2013 21:52:56 +0000 Subject: [PATCH 0257/2900] bridge: send query as soon as leave is received Continue sending queries when leave is received if the user marks it as a querier. Cc: Herbert Xu Cc: Stephen Hemminger Cc: "David S. Miller" Cc: Adam Baker Signed-off-by: Cong Wang Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 40bda804fbd9..37a467697967 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1250,6 +1250,32 @@ static void br_multicast_leave_group(struct net_bridge *br, if (!mp) goto out; + if (br->multicast_querier && + !timer_pending(&br->multicast_querier_timer)) { + __br_multicast_send_query(br, port, &mp->addr); + + time = jiffies + br->multicast_last_member_count * + br->multicast_last_member_interval; + mod_timer(port ? &port->multicast_query_timer : + &br->multicast_query_timer, time); + + for (p = mlock_dereference(mp->ports, br); + p != NULL; + p = mlock_dereference(p->next, br)) { + if (p->port != port) + continue; + + if (!hlist_unhashed(&p->mglist) && + (timer_pending(&p->timer) ? + time_after(p->timer.expires, time) : + try_to_del_timer_sync(&p->timer) >= 0)) { + mod_timer(&p->timer, time); + } + + break; + } + } + if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { struct net_bridge_port_group __rcu **pp; -- GitLab From 1cdbcb7957cf9e5f841dbcde9b38fd18a804208b Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Sun, 19 May 2013 15:46:49 +0000 Subject: [PATCH 0258/2900] net: Loosen constraints for recalculating checksum in skb_segment() This is a generic solution to resolve a specific problem that I have observed. If the encapsulation of an skb changes then ability to offload checksums may also change. In particular it may be necessary to perform checksumming in software. An example of such a case is where a non-GRE packet is received but is to be encapsulated and transmitted as GRE. Another example relates to my proposed support for for packets that are non-MPLS when received but MPLS when transmitted. The cost of this change is that the value of the csum variable may be checked when it previously was not. In the case where the csum variable is true this is pure overhead. In the case where the csum variable is false it leads to software checksumming, which I believe also leads to correct checksums in transmitted packets for the cases described above. Further analysis: This patch relies on the return value of can_checksum_protocol() being correct and in turn the return value of skb_network_protocol(), used to provide the protocol parameter of can_checksum_protocol(), being correct. It also relies on the features passed to skb_segment() and in turn to can_checksum_protocol() being correct. I believe that this problem has not been observed for VLANs because it appears that almost all drivers, the exception being xgbe, set vlan_features such that that the checksum offload support for VLAN packets is greater than or equal to that of non-VLAN packets. I wonder if the code in xgbe may be an oversight and the hardware does support checksumming of VLAN packets. If so it may be worth updating the vlan_features of the driver as this patch will force such checksums to be performed in software rather than hardware. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/core/skbuff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index af9185d0be6a..d6298914f4e7 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2853,7 +2853,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) doffset + tnl_hlen); if (fskb != skb_shinfo(skb)->frag_list) - continue; + goto perform_csum_check; if (!sg) { nskb->ip_summed = CHECKSUM_NONE; @@ -2917,6 +2917,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) nskb->len += nskb->data_len; nskb->truesize += nskb->data_len; +perform_csum_check: if (!csum) { nskb->csum = skb_checksum(nskb, doffset, nskb->len - doffset, 0); -- GitLab From f1238261891bea67da845688b7684a3444c61bd9 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 21 May 2013 00:22:37 +0000 Subject: [PATCH 0259/2900] net: smsc911x: don't artificially limit build Currently the SMSC911X driver may only be built for a specific set of architectures, being limited to do so by a Kconfig depends line. This means that if a platform wishes to use the driver, its architecture must be added to the list explicitly, introducing pointless churn. This may have been due to the driver's use of the {read,write}s{b,w,l} functions, which have since been replaced with the more standard io{read,write}{8,16,32}_rep. We can instead depend on HAS_IOMEM, which should prevent build issues while allowing the driver to be built for currently unlisted architectures, including x86 and arm64. This patch removes the explicit list of architectures from the driver's depend line, and replaces it with a dependency on HAS_IOMEM. Signed-off-by: Mark Rutland Cc: David S. Miller Cc: Arnd Bergmann Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index bb4c1674ff99..ff9e99474039 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -97,7 +97,7 @@ config SMC911X config SMSC911X tristate "SMSC LAN911x/LAN921x families embedded ethernet support" - depends on (ARM || SUPERH || BLACKFIN || MIPS || MN10300) + depends on HAS_IOMEM select CRC32 select NET_CORE select MII -- GitLab From 9313eb4be3220054c07a7c34c38764ea1ebcd220 Mon Sep 17 00:00:00 2001 From: Jay Fenlason Date: Tue, 21 May 2013 04:21:28 +0000 Subject: [PATCH 0260/2900] cxgb3: Fix warning about using rcu_dereference when not in a rcu-locked section It is about using rcu_dereference() when not in a rcu-locked section. It only happens on initialization hence fix the initialization to not rcu_dereference() Signed-off-by: Jay Fenlason Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c index 0c96e5fe99cc..4058b856eb71 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c @@ -1246,6 +1246,7 @@ int cxgb3_offload_activate(struct adapter *adapter) struct tid_range stid_range, tid_range; struct mtutab mtutab; unsigned int l2t_capacity; + struct l2t_data *l2td; t = kzalloc(sizeof(*t), GFP_KERNEL); if (!t) @@ -1261,8 +1262,8 @@ int cxgb3_offload_activate(struct adapter *adapter) goto out_free; err = -ENOMEM; - RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity)); - if (!L2DATA(dev)) + l2td = t3_init_l2t(l2t_capacity); + if (!l2td) goto out_free; natids = min(tid_range.num / 2, MAX_ATIDS); @@ -1279,6 +1280,7 @@ int cxgb3_offload_activate(struct adapter *adapter) INIT_LIST_HEAD(&t->list_node); t->dev = dev; + RCU_INIT_POINTER(dev->l2opt, l2td); T3C_DATA(dev) = t; dev->recv = process_rx; dev->neigh_update = t3_l2t_update; @@ -1294,8 +1296,7 @@ int cxgb3_offload_activate(struct adapter *adapter) return 0; out_free_l2t: - t3_free_l2t(L2DATA(dev)); - RCU_INIT_POINTER(dev->l2opt, NULL); + t3_free_l2t(l2td); out_free: kfree(t); return err; -- GitLab From f83331bab149e29fa2c49cf102c0cd8c3f1ce9f9 Mon Sep 17 00:00:00 2001 From: Santosh Rastapur Date: Tue, 21 May 2013 04:21:29 +0000 Subject: [PATCH 0261/2900] cxgb3: Check and handle the dma mapping errors This patch adds checks at approprate places whether *dma_map*() call has succeeded or not. Signed-off-by: Santosh Rastapur Reviewed-by: Jay Fenlason Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/sge.c | 105 ++++++++++++++++++----- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index f12e6b85a653..2fd773e267dc 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -455,6 +455,11 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q, q->pg_chunk.offset = 0; mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, 0, q->alloc_size, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(adapter->pdev, mapping))) { + __free_pages(q->pg_chunk.page, order); + q->pg_chunk.page = NULL; + return -EIO; + } q->pg_chunk.mapping = mapping; } sd->pg_chunk = q->pg_chunk; @@ -949,40 +954,75 @@ static inline unsigned int calc_tx_descs(const struct sk_buff *skb) return flits_to_desc(flits); } + +/* map_skb - map a packet main body and its page fragments + * @pdev: the PCI device + * @skb: the packet + * @addr: placeholder to save the mapped addresses + * + * map the main body of an sk_buff and its page fragments, if any. + */ +static int map_skb(struct pci_dev *pdev, const struct sk_buff *skb, + dma_addr_t *addr) +{ + const skb_frag_t *fp, *end; + const struct skb_shared_info *si; + + *addr = pci_map_single(pdev, skb->data, skb_headlen(skb), + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, *addr)) + goto out_err; + + si = skb_shinfo(skb); + end = &si->frags[si->nr_frags]; + + for (fp = si->frags; fp < end; fp++) { + *++addr = skb_frag_dma_map(&pdev->dev, fp, 0, skb_frag_size(fp), + DMA_TO_DEVICE); + if (pci_dma_mapping_error(pdev, *addr)) + goto unwind; + } + return 0; + +unwind: + while (fp-- > si->frags) + dma_unmap_page(&pdev->dev, *--addr, skb_frag_size(fp), + DMA_TO_DEVICE); + + pci_unmap_single(pdev, addr[-1], skb_headlen(skb), PCI_DMA_TODEVICE); +out_err: + return -ENOMEM; +} + /** - * make_sgl - populate a scatter/gather list for a packet + * write_sgl - populate a scatter/gather list for a packet * @skb: the packet * @sgp: the SGL to populate * @start: start address of skb main body data to include in the SGL * @len: length of skb main body data to include in the SGL - * @pdev: the PCI device + * @addr: the list of the mapped addresses * - * Generates a scatter/gather list for the buffers that make up a packet + * Copies the scatter/gather list for the buffers that make up a packet * and returns the SGL size in 8-byte words. The caller must size the SGL * appropriately. */ -static inline unsigned int make_sgl(const struct sk_buff *skb, +static inline unsigned int write_sgl(const struct sk_buff *skb, struct sg_ent *sgp, unsigned char *start, - unsigned int len, struct pci_dev *pdev) + unsigned int len, const dma_addr_t *addr) { - dma_addr_t mapping; - unsigned int i, j = 0, nfrags; + unsigned int i, j = 0, k = 0, nfrags; if (len) { - mapping = pci_map_single(pdev, start, len, PCI_DMA_TODEVICE); sgp->len[0] = cpu_to_be32(len); - sgp->addr[0] = cpu_to_be64(mapping); - j = 1; + sgp->addr[j++] = cpu_to_be64(addr[k++]); } nfrags = skb_shinfo(skb)->nr_frags; for (i = 0; i < nfrags; i++) { const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - mapping = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), - DMA_TO_DEVICE); sgp->len[j] = cpu_to_be32(skb_frag_size(frag)); - sgp->addr[j] = cpu_to_be64(mapping); + sgp->addr[j] = cpu_to_be64(addr[k++]); j ^= 1; if (j == 0) ++sgp; @@ -1138,7 +1178,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, const struct port_info *pi, unsigned int pidx, unsigned int gen, struct sge_txq *q, unsigned int ndesc, - unsigned int compl) + unsigned int compl, const dma_addr_t *addr) { unsigned int flits, sgl_flits, cntrl, tso_info; struct sg_ent *sgp, sgl[MAX_SKB_FRAGS / 2 + 1]; @@ -1196,7 +1236,7 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, } sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; - sgl_flits = make_sgl(skb, sgp, skb->data, skb_headlen(skb), adap->pdev); + sgl_flits = write_sgl(skb, sgp, skb->data, skb_headlen(skb), addr); write_wr_hdr_sgl(ndesc, skb, d, pidx, q, sgl, flits, sgl_flits, gen, htonl(V_WR_OP(FW_WROPCODE_TUNNEL_TX_PKT) | compl), @@ -1227,6 +1267,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) struct netdev_queue *txq; struct sge_qset *qs; struct sge_txq *q; + dma_addr_t addr[MAX_SKB_FRAGS + 1]; /* * The chip min packet length is 9 octets but play safe and reject @@ -1255,6 +1296,11 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } + if (unlikely(map_skb(adap->pdev, skb, addr) < 0)) { + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + q->in_use += ndesc; if (unlikely(credits - ndesc < q->stop_thres)) { t3_stop_tx_queue(txq, qs, q); @@ -1312,7 +1358,7 @@ netdev_tx_t t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) if (likely(!skb_shared(skb))) skb_orphan(skb); - write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl); + write_tx_pkt_wr(adap, skb, pi, pidx, gen, q, ndesc, compl, addr); check_ring_tx_db(adap, q); return NETDEV_TX_OK; } @@ -1578,7 +1624,8 @@ static void setup_deferred_unmapping(struct sk_buff *skb, struct pci_dev *pdev, */ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, struct sge_txq *q, unsigned int pidx, - unsigned int gen, unsigned int ndesc) + unsigned int gen, unsigned int ndesc, + const dma_addr_t *addr) { unsigned int sgl_flits, flits; struct work_request_hdr *from; @@ -1599,9 +1646,9 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, flits = skb_transport_offset(skb) / 8; sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; - sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb), + sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb), skb->tail - skb->transport_header, - adap->pdev); + addr); if (need_skb_unmap()) { setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); skb->destructor = deferred_unmap_destructor; @@ -1659,6 +1706,11 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); goto again; } + if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) { + spin_unlock(&q->lock); + return NET_XMIT_SUCCESS; + } + gen = q->gen; q->in_use += ndesc; pidx = q->pidx; @@ -1669,7 +1721,7 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); } spin_unlock(&q->lock); - write_ofld_wr(adap, skb, q, pidx, gen, ndesc); + write_ofld_wr(adap, skb, q, pidx, gen, ndesc, (dma_addr_t *)skb->head); check_ring_tx_db(adap, q); return NET_XMIT_SUCCESS; } @@ -1687,6 +1739,7 @@ static void restart_offloadq(unsigned long data) struct sge_txq *q = &qs->txq[TXQ_OFLD]; const struct port_info *pi = netdev_priv(qs->netdev); struct adapter *adap = pi->adapter; + unsigned int written = 0; spin_lock(&q->lock); again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); @@ -1706,10 +1759,14 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); break; } + if (map_skb(adap->pdev, skb, (dma_addr_t *)skb->head)) + break; + gen = q->gen; q->in_use += ndesc; pidx = q->pidx; q->pidx += ndesc; + written += ndesc; if (q->pidx >= q->size) { q->pidx -= q->size; q->gen ^= 1; @@ -1717,7 +1774,8 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); __skb_unlink(skb, &q->sendq); spin_unlock(&q->lock); - write_ofld_wr(adap, skb, q, pidx, gen, ndesc); + write_ofld_wr(adap, skb, q, pidx, gen, ndesc, + (dma_addr_t *)skb->head); spin_lock(&q->lock); } spin_unlock(&q->lock); @@ -1727,8 +1785,9 @@ again: reclaim_completed_tx(adap, q, TX_RECLAIM_CHUNK); set_bit(TXQ_LAST_PKT_DB, &q->flags); #endif wmb(); - t3_write_reg(adap, A_SG_KDOORBELL, - F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); + if (likely(written)) + t3_write_reg(adap, A_SG_KDOORBELL, + F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id)); } /** -- GitLab From ffed61e6fd3a405e79f4d267f22acaee3267fb37 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 21 May 2013 05:44:26 +0000 Subject: [PATCH 0262/2900] fec: Use DIV_ROUND_UP macro Use the standard DIV_ROUND_UP macro in order to provide better readability. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 2f4b3e028012..6b5dc58c56d8 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -242,7 +242,7 @@ static void *swap_buffer(void *bufaddr, int len) int i; unsigned int *buf = bufaddr; - for (i = 0; i < (len + 3) / 4; i++, buf++) + for (i = 0; i < DIV_ROUND_UP(len, 4); i++, buf++) *buf = cpu_to_be32(*buf); return bufaddr; -- GitLab From e43ac79a4bc6ca90de4ba10983b4ca39cd215b4b Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 21 May 2013 08:16:46 +0000 Subject: [PATCH 0263/2900] sch_tbf: segment too big GSO packets If a GSO packet has a length above tbf burst limit, the packet is currently silently dropped. Current way to handle this is to set the device in non GSO/TSO mode, or setting high bursts, and its sub optimal. We can actually segment too big GSO packets, and send individual segments as tbf parameters allow, allowing for better interoperability. Signed-off-by: Eric Dumazet Cc: Ben Hutchings Cc: Jiri Pirko Cc: Jamal Hadi Salim Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/sched/sch_tbf.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index c8388f3c3426..38008b0980d9 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -116,14 +116,57 @@ struct tbf_sched_data { struct qdisc_watchdog watchdog; /* Watchdog timer */ }; + +/* GSO packet is too big, segment it so that tbf can transmit + * each segment in time + */ +static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch) +{ + struct tbf_sched_data *q = qdisc_priv(sch); + struct sk_buff *segs, *nskb; + netdev_features_t features = netif_skb_features(skb); + int ret, nb; + + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + + if (IS_ERR_OR_NULL(segs)) + return qdisc_reshape_fail(skb, sch); + + nb = 0; + while (segs) { + nskb = segs->next; + segs->next = NULL; + if (likely(segs->len <= q->max_size)) { + qdisc_skb_cb(segs)->pkt_len = segs->len; + ret = qdisc_enqueue(segs, q->qdisc); + } else { + ret = qdisc_reshape_fail(skb, sch); + } + if (ret != NET_XMIT_SUCCESS) { + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; + } else { + nb++; + } + segs = nskb; + } + sch->q.qlen += nb; + if (nb > 1) + qdisc_tree_decrease_qlen(sch, 1 - nb); + consume_skb(skb); + return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP; +} + static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct tbf_sched_data *q = qdisc_priv(sch); int ret; - if (qdisc_pkt_len(skb) > q->max_size) + if (qdisc_pkt_len(skb) > q->max_size) { + if (skb_is_gso(skb)) + return tbf_segment(skb, sch); return qdisc_reshape_fail(skb, sch); - + } ret = qdisc_enqueue(skb, q->qdisc); if (ret != NET_XMIT_SUCCESS) { if (net_xmit_drop_count(ret)) -- GitLab From 7996c799ae329fab1b9c8d475fd08883f0499ed9 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 22 May 2013 05:41:06 +0000 Subject: [PATCH 0264/2900] ipv6: use ipv6_addr_any() helper ipv6_addr_any() is a faster way to determine if an addr is ipv6 any addr, no need to compute the addr type. Cc: Nicolas Dichtel Cc: Hideaki YOSHIFUJI Cc: David S. Miller Signed-off-by: Cong Wang Acked-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d684d23bc027..e05269647c2b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3846,7 +3846,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, valid = INFINITY_LIFE_TIME; } - if (ipv6_addr_type(&ifa->peer_addr) != IPV6_ADDR_ANY) { + if (!ipv6_addr_any(&ifa->peer_addr)) { if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 || nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0) goto error; @@ -4579,7 +4579,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ip6_ins_rt(ifp->rt); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); - if (ipv6_addr_type(&ifp->peer_addr) != IPV6_ADDR_ANY) + if (!ipv6_addr_any(&ifp->peer_addr)) addrconf_prefix_route(&ifp->peer_addr, 128, ifp->idev->dev, 0, 0); break; @@ -4587,7 +4587,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) if (ifp->idev->cnf.forwarding) addrconf_leave_anycast(ifp); addrconf_leave_solict(ifp->idev, &ifp->addr); - if (ipv6_addr_type(&ifp->peer_addr) != IPV6_ADDR_ANY) { + if (!ipv6_addr_any(&ifp->peer_addr)) { struct rt6_info *rt; struct net_device *dev = ifp->idev->dev; -- GitLab From 8892475386e819aa50856947948c546ccc964d96 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 22 May 2013 05:52:22 +0000 Subject: [PATCH 0265/2900] ipv6: use ipv6_addr_scope() helper ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK could be replaced by ipv6_addr_scope(), which is slightly faster. Cc: Hideaki YOSHIFUJI Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e05269647c2b..432e084b6b62 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1126,8 +1126,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ift = !max_addresses || ipv6_count_addresses(idev) < max_addresses ? - ipv6_add_addr(idev, &addr, tmp_plen, - ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, + ipv6_add_addr(idev, &addr, tmp_plen, ipv6_addr_scope(&addr), addr_flags) : NULL; if (IS_ERR_OR_NULL(ift)) { in6_ifa_put(ifp); -- GitLab From 27e7190efd5b2f728686a8293af6d9bd34c4e562 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 22 May 2013 11:10:57 +0000 Subject: [PATCH 0266/2900] netfilter: xt_CT: optimize XT_CT_NOTRACK The percpu untracked ct are not currently used for XT_CT_NOTRACK. xt_ct_tg_check()/xt_ct_target() provides a single ct. Thats not optimal as the ct->ct_general.use cache line will bounce among cpus. Use the intended [1] thing : xt_ct_target() should select the percpu object. [1] Refs : commit 5bfddbd46a95c97 ("netfilter: nf_conntrack: IPS_UNTRACKED bit") commit b3c5163fe0193a7 ("netfilter: nf_conntrack: per_cpu untracking") Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_CT.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index a60261cb0e80..da35ac06a975 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -26,6 +26,9 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) if (skb->nfct != NULL) return XT_CONTINUE; + /* special case the untracked ct : we want the percpu object */ + if (!ct) + ct = nf_ct_untracked_get(); atomic_inc(&ct->ct_general.use); skb->nfct = &ct->ct_general; skb->nfctinfo = IP_CT_NEW; @@ -186,8 +189,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, int ret = -EOPNOTSUPP; if (info->flags & XT_CT_NOTRACK) { - ct = nf_ct_untracked_get(); - atomic_inc(&ct->ct_general.use); + ct = NULL; goto out; } @@ -311,7 +313,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, struct nf_conn *ct = info->ct; struct nf_conn_help *help; - if (!nf_ct_is_untracked(ct)) { + if (ct && !nf_ct_is_untracked(ct)) { help = nfct_help(ct); if (help) module_put(help->helper->me); @@ -319,8 +321,8 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, nf_ct_l3proto_module_put(par->family); xt_ct_destroy_timeout(ct); + nf_ct_put(info->ct); } - nf_ct_put(info->ct); } static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) -- GitLab From 00028aa37098168048728acc32ab0206687f2920 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 22 May 2013 11:01:06 +0000 Subject: [PATCH 0267/2900] netfilter: xt_socket: use IP early demux With IP early demux added in linux-3.6, we perform TCP lookup in IP layer before iptables hooks. We can avoid doing a second lookup in xt_socket. Signed-off-by: Eric Dumazet Acked-by: David S. Miller Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_socket.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 63b2bdb59e95..02704245710e 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -107,7 +107,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, { const struct iphdr *iph = ip_hdr(skb); struct udphdr _hdr, *hp = NULL; - struct sock *sk; + struct sock *sk = skb->sk; __be32 uninitialized_var(daddr), uninitialized_var(saddr); __be16 uninitialized_var(dport), uninitialized_var(sport); u8 uninitialized_var(protocol); @@ -155,9 +155,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, } #endif - sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol, - saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); - if (sk != NULL) { + if (!sk) + sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol, + saddr, daddr, sport, dport, + par->in, NFT_LOOKUP_ANY); + if (sk) { bool wildcard; bool transparent = true; @@ -173,7 +175,8 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, (sk->sk_state == TCP_TIME_WAIT && inet_twsk(sk)->tw_transparent)); - xt_socket_put_sk(sk); + if (sk != skb->sk) + xt_socket_put_sk(sk); if (wildcard || !transparent) sk = NULL; @@ -260,7 +263,7 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) { struct ipv6hdr *iph = ipv6_hdr(skb); struct udphdr _hdr, *hp = NULL; - struct sock *sk; + struct sock *sk = skb->sk; struct in6_addr *daddr = NULL, *saddr = NULL; __be16 uninitialized_var(dport), uninitialized_var(sport); int thoff = 0, uninitialized_var(tproto); @@ -291,9 +294,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) return false; } - sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto, - saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); - if (sk != NULL) { + if (!sk) + sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto, + saddr, daddr, sport, dport, + par->in, NFT_LOOKUP_ANY); + if (sk) { bool wildcard; bool transparent = true; @@ -309,7 +314,8 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) (sk->sk_state == TCP_TIME_WAIT && inet_twsk(sk)->tw_transparent)); - xt_socket_put_sk(sk); + if (sk != skb->sk) + xt_socket_put_sk(sk); if (wildcard || !transparent) sk = NULL; -- GitLab From 8bc14d25ffb9dfc242d3a877bb4fe683adb27692 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Thu, 16 May 2013 22:07:22 +0000 Subject: [PATCH 0268/2900] bridge: netfilter: using strlcpy() instead of strncpy() 'name' has already set all zero when it is defined, so not need let strncpy() to pad it again. 'name' is a string, better always let is NUL terminated, so use strlcpy() instead of strncpy(). Signed-off-by: Chen Gang Acked-by: Bart De Schuymer Signed-off-by: Pablo Neira Ayuso --- net/bridge/netfilter/ebtables.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 3d110c4fc787..ac7802428384 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1339,7 +1339,7 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m, /* ebtables expects 32 bytes long names but xt_match names are 29 bytes long. Copy 29 bytes and fill remaining bytes with zeroes. */ - strncpy(name, m->u.match->name, sizeof(name)); + strlcpy(name, m->u.match->name, sizeof(name)); if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) return -EFAULT; return 0; @@ -1351,7 +1351,7 @@ static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, char __user *hlp = ubase + ((char *)w - base); char name[EBT_FUNCTION_MAXNAMELEN] = {}; - strncpy(name, w->u.watcher->name, sizeof(name)); + strlcpy(name, w->u.watcher->name, sizeof(name)); if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN)) return -EFAULT; return 0; @@ -1377,7 +1377,7 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase); if (ret != 0) return ret; - strncpy(name, t->u.target->name, sizeof(name)); + strlcpy(name, t->u.target->name, sizeof(name)); if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) return -EFAULT; return 0; -- GitLab From 6d11cfdba52af08b889fd6d3ee4212930493eb38 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 22 May 2013 22:42:36 +0000 Subject: [PATCH 0269/2900] netfilter: don't panic on error while walking through the init path Don't panic if we hit an error while adding the nf_log or pernet netfilter support, just bail out. Signed-off-by: Pablo Neira Ayuso Acked-by: Gao feng --- include/linux/netfilter.h | 2 +- net/netfilter/core.c | 21 +++++++++++++++------ net/netfilter/nf_log.c | 5 +---- net/socket.c | 4 +++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 0060fde3160e..de70f7b45b68 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -35,7 +35,7 @@ static inline void nf_inet_addr_mask(const union nf_inet_addr *a1, result->all[3] = a1->all[3] & mask->all[3]; } -extern void netfilter_init(void); +extern int netfilter_init(void); /* Largest hook number + 1 */ #define NF_MAX_HOOKS 8 diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 07c865a31a3d..300539db7bb1 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -302,17 +302,26 @@ static struct pernet_operations netfilter_net_ops = { .exit = netfilter_net_exit, }; -void __init netfilter_init(void) +int __init netfilter_init(void) { - int i, h; + int i, h, ret; + for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { for (h = 0; h < NF_MAX_HOOKS; h++) INIT_LIST_HEAD(&nf_hooks[i][h]); } - if (register_pernet_subsys(&netfilter_net_ops) < 0) - panic("cannot create netfilter proc entry"); + ret = register_pernet_subsys(&netfilter_net_ops); + if (ret < 0) + goto err; + + ret = netfilter_log_init(); + if (ret < 0) + goto err_pernet; - if (netfilter_log_init() < 0) - panic("cannot initialize nf_log"); + return 0; +err_pernet: + unregister_pernet_subsys(&netfilter_net_ops); +err: + return ret; } diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 388656d5a9ec..bd5474adcabc 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -368,10 +368,7 @@ static int __net_init nf_log_net_init(struct net *net) return 0; out_sysctl: - /* For init_net: errors will trigger panic, don't unroll on error. */ - if (!net_eq(net, &init_net)) - remove_proc_entry("nf_log", net->nf.proc_netfilter); - + remove_proc_entry("nf_log", net->nf.proc_netfilter); return ret; } diff --git a/net/socket.c b/net/socket.c index 6b94633ca61d..734194d36242 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2612,7 +2612,9 @@ static int __init sock_init(void) */ #ifdef CONFIG_NETFILTER - netfilter_init(); + err = netfilter_init(); + if (err) + goto out; #endif #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING -- GitLab From de94c4591bd606729af1b913d6e98c6c449e42df Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 22 May 2013 22:42:37 +0000 Subject: [PATCH 0270/2900] netfilter: {ipt,ebt}_ULOG: rise warning on deprecation This target has been superseded by NFLOG. Spot a warning so we prepare removal in a couple of years. Signed-off-by: Pablo Neira Ayuso Acked-by: Gao feng --- include/net/netns/x_tables.h | 6 ++++++ net/bridge/netfilter/ebt_ulog.c | 6 ++++++ net/ipv4/netfilter/Kconfig | 2 +- net/ipv4/netfilter/ipt_ULOG.c | 6 ++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h index c24060ee411e..02fe40f8c8fd 100644 --- a/include/net/netns/x_tables.h +++ b/include/net/netns/x_tables.h @@ -15,5 +15,11 @@ struct netns_xt { struct ebt_table *frame_filter; struct ebt_table *frame_nat; #endif +#if IS_ENABLED(CONFIG_IP_NF_TARGET_ULOG) + bool ulog_warn_deprecated; +#endif +#if IS_ENABLED(CONFIG_BRIDGE_EBT_ULOG) + bool ebt_ulog_warn_deprecated; +#endif }; #endif diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index fc1905c51417..2ec6c19ff903 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -267,6 +267,12 @@ static int ebt_ulog_tg_check(const struct xt_tgchk_param *par) { struct ebt_ulog_info *uloginfo = par->targinfo; + if (!par->net->xt.ebt_ulog_warn_deprecated) { + pr_info("ebt_ulog is deprecated and it will be removed soon, " + "use ebt_nflog instead\n"); + par->net->xt.ebt_ulog_warn_deprecated = true; + } + if (uloginfo->nlgroup > 31) return -EINVAL; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index e7916c193932..4e9028017428 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -111,7 +111,7 @@ config IP_NF_TARGET_REJECT To compile it as a module, choose M here. If unsure, say N. config IP_NF_TARGET_ULOG - tristate "ULOG target support" + tristate "ULOG target support (obsolete)" default m if NETFILTER_ADVANCED=n ---help--- diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index f8a222cb6448..c1953d07e2f4 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -325,6 +325,12 @@ static int ulog_tg_check(const struct xt_tgchk_param *par) { const struct ipt_ulog_info *loginfo = par->targinfo; + if (!par->net->xt.ulog_warn_deprecated) { + pr_info("ULOG is deprecated and it will be removed soon, " + "use NFLOG instead\n"); + par->net->xt.ulog_warn_deprecated = true; + } + if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { pr_debug("prefix not null-terminated\n"); return -EINVAL; -- GitLab From f6f3c437d09e2f62533034e67bfb4385191e992c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 22 May 2013 14:50:31 +0900 Subject: [PATCH 0271/2900] sched: add cond_resched_rcu() helper This is intended for use in loops which read data protected by RCU and may have a large number of iterations. Such an example is dumping the list of connections known to IPVS: ip_vs_conn_array() and ip_vs_conn_seq_next(). The benefits are for CONFIG_PREEMPT_RCU=y where we save CPU cycles by moving rcu_read_lock and rcu_read_unlock out of large loops but still allowing the current task to be preempted after every loop iteration for the CONFIG_PREEMPT_RCU=n case. The call to cond_resched() is not needed when CONFIG_PREEMPT_RCU=y. Thanks to Paul E. McKenney for explaining this and for the final version that checks the context with CONFIG_DEBUG_ATOMIC_SLEEP=y for all possible configurations. The function can be empty in the CONFIG_PREEMPT_RCU case, rcu_read_lock and rcu_read_unlock are not needed in this case because the task can be preempted on indication from scheduler. Thanks to Peter Zijlstra for catching this and for his help in trying a solution that changes __might_sleep. Initial cond_resched_rcu_lock() function suggested by Eric Dumazet. Tested-by: Julian Anastasov Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Acked-by: Peter Zijlstra Signed-off-by: Pablo Neira Ayuso --- include/linux/sched.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 178a8d909f14..4ff8da189253 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2444,6 +2444,15 @@ extern int __cond_resched_softirq(void); __cond_resched_softirq(); \ }) +static inline void cond_resched_rcu(void) +{ +#if defined(CONFIG_DEBUG_ATOMIC_SLEEP) || !defined(CONFIG_PREEMPT_RCU) + rcu_read_unlock(); + cond_resched(); + rcu_read_lock(); +#endif +} + /* * Does a critical section need to be broken due to another * task waiting?: (technically does not depend on CONFIG_PREEMPT, -- GitLab From a38e5e230e3f4e7bc9195d3e7a81567c888257ca Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 22 May 2013 14:50:32 +0900 Subject: [PATCH 0272/2900] ipvs: use cond_resched_rcu() helper when walking connections This avoids the situation where walking of a large number of connections may prevent scheduling for a long time while also avoiding excessive calls to rcu_read_unlock() and rcu_read_lock(). Note that in the case of !CONFIG_PREEMPT_RCU this will add a call to cond_resched(). Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Acked-by: Peter Zijlstra Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_conn.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index a083bda322b6..c8c52a98590b 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -975,8 +975,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos) return cp; } } - rcu_read_unlock(); - rcu_read_lock(); + cond_resched_rcu(); } return NULL; @@ -1015,8 +1014,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos) iter->l = &ip_vs_conn_tab[idx]; return cp; } - rcu_read_unlock(); - rcu_read_lock(); + cond_resched_rcu(); } iter->l = NULL; return NULL; @@ -1206,17 +1204,13 @@ void ip_vs_random_dropentry(struct net *net) int idx; struct ip_vs_conn *cp, *cp_c; + rcu_read_lock(); /* * Randomly scan 1/32 of the whole table every second */ for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) { unsigned int hash = net_random() & ip_vs_conn_tab_mask; - /* - * Lock is actually needed in this loop. - */ - rcu_read_lock(); - hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) { if (cp->flags & IP_VS_CONN_F_TEMPLATE) /* connection template */ @@ -1252,8 +1246,9 @@ void ip_vs_random_dropentry(struct net *net) __ip_vs_conn_put(cp); } } - rcu_read_unlock(); + cond_resched_rcu(); } + rcu_read_unlock(); } @@ -1267,11 +1262,8 @@ static void ip_vs_conn_flush(struct net *net) struct netns_ipvs *ipvs = net_ipvs(net); flush_again: + rcu_read_lock(); for (idx = 0; idx < ip_vs_conn_tab_size; idx++) { - /* - * Lock is actually needed in this loop. - */ - rcu_read_lock(); hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) { if (!ip_vs_conn_net_eq(cp, net)) @@ -1286,8 +1278,9 @@ static void ip_vs_conn_flush(struct net *net) __ip_vs_conn_put(cp); } } - rcu_read_unlock(); + cond_resched_rcu(); } + rcu_read_unlock(); /* the counter may be not NULL, because maybe some conn entries are run by slow timer handler or unhashed but still referred */ -- GitLab From eebfc9394ee31b3ef162692c0cd483c1318a4395 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 May 2013 22:17:50 +0200 Subject: [PATCH 0273/2900] iwlwifi: mvm: remove P2P_DEVICE support Unfortunately, advertising P2P_DEVICE support was a little premature, a number of issues came up in testing and have been fixed for 3.10. Rather than try to backport all the different fixes, disable P2P_DEVICE support in the drivers using it. For iwlmvm that implies disabling P2P completely as it can't support P2P operation w/o P2P Device. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index dd158ec571fb..11dc7df8bdf9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -84,15 +84,6 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP), }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO), - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_DEVICE), - }, }; static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { @@ -161,10 +152,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_DEVICE); + BIT(NL80211_IFTYPE_AP); hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | -- GitLab From e3ee68b7b049c5bbfcb78a179c00c373a38ed58c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 May 2013 22:17:50 +0200 Subject: [PATCH 0274/2900] mac80211_hwsim: remove P2P_DEVICE support Unfortunately, advertising P2P_DEVICE support was a little premature, a number of issues came up in testing and have been fixed for 3.10. Rather than try to backport all the different fixes, disable P2P_DEVICE support in the drivers using it. Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cb34c7895f2a..69bbf6fdd2d3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2169,7 +2169,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { #endif BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) }, - { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, }; static struct ieee80211_iface_combination hwsim_if_comb = { @@ -2295,8 +2294,7 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_P2P_DEVICE); + BIT(NL80211_IFTYPE_MESH_POINT); hw->flags = IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_SIGNAL_DBM | -- GitLab From 5f38a11274f0e74ec0e499bc779d355510b39790 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 23 May 2013 23:09:56 +0200 Subject: [PATCH 0275/2900] mac80211: assign AP_VLAN hw queues correctly A lot of code in mac80211 assumes that the hw queues are set up correctly for all interfaces (except for monitor) but this isn't true for AP_VLAN interfaces. Fix this by copying the AP master configuration when an AP VLAN is brought up, after this the AP interface can't change its configuration any more and needs to be brought down to change it, which also forces AP_VLAN interfaces down, so just copying in open() is sufficient. Reported-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 68f51c3af49f..00e2238355f0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -474,6 +474,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) master->control_port_protocol; sdata->control_port_no_encrypt = master->control_port_no_encrypt; + sdata->vif.cab_queue = master->vif.cab_queue; + memcpy(sdata->vif.hw_queue, master->vif.hw_queue, + sizeof(sdata->vif.hw_queue)); break; } case NL80211_IFTYPE_AP: -- GitLab From 4c8a9d4bfaf7dbc7d2168494904d79d22cc01db7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 24 May 2013 01:06:09 +0200 Subject: [PATCH 0276/2900] mac80211: close AP_VLAN interfaces before unregistering all Since Eric's commit efe117ab8 ("Speedup ieee80211_remove_interfaces") there's a bug in mac80211 when it unregisters with AP_VLAN interfaces up. If the AP_VLAN interface was registered after the AP it belongs to (which is the typical case) and then we get into this code path, unregister_netdevice_many() will crash because it isn't prepared to deal with interfaces being closed in the middle of it. Exactly this happens though, because we iterate the list, find the AP master this AP_VLAN belongs to and dev_close() the dependent VLANs. After this, unregister_netdevice_many() won't pick up the fact that the AP_VLAN is already down and will do it again, causing a crash. Cc: stable@vger.kernel.org [2.6.33+] Cc: Eric Dumazet Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 00e2238355f0..ceef64426a8d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1703,6 +1703,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ASSERT_RTNL(); + /* + * Close all AP_VLAN interfaces first, as otherwise they + * might be closed while the AP interface they belong to + * is closed, causing unregister_netdevice_many() to crash. + */ + list_for_each_entry(sdata, &local->interfaces, list) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + dev_close(sdata->dev); + mutex_lock(&local->iflist_mtx); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); -- GitLab From e1f00a69ec26e3eb9847c61c665b8fb3f0c6b477 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 22 May 2013 06:34:45 +0000 Subject: [PATCH 0277/2900] xen-netback: split event channels support for Xen backend driver Netback and netfront only use one event channel to do TX / RX notification, which may cause unnecessary wake-up of processing routines. This patch adds a new feature called feature-split-event-channels to netback, enabling it to handle TX and RX events separately. Netback will use tx_irq to notify guest for TX completion, rx_irq for RX notification. If frontend doesn't support this feature, tx_irq equals to rx_irq. Signed-off-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 13 ++++- drivers/net/xen-netback/interface.c | 85 ++++++++++++++++++++++++----- drivers/net/xen-netback/netback.c | 14 +++-- drivers/net/xen-netback/xenbus.c | 41 +++++++++++--- 4 files changed, 124 insertions(+), 29 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 6102a6c59f4e..8a4d77ee9c5b 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -57,8 +57,12 @@ struct xenvif { u8 fe_dev_addr[6]; - /* Physical parameters of the comms window. */ - unsigned int irq; + /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ + unsigned int tx_irq; + unsigned int rx_irq; + /* Only used when feature-split-event-channels = 1 */ + char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */ + char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ /* List of frontends to notify after a batch of frames sent. */ struct list_head notify_list; @@ -113,7 +117,8 @@ struct xenvif *xenvif_alloc(struct device *parent, unsigned int handle); int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, - unsigned long rx_ring_ref, unsigned int evtchn); + unsigned long rx_ring_ref, unsigned int tx_evtchn, + unsigned int rx_evtchn); void xenvif_disconnect(struct xenvif *vif); void xenvif_get(struct xenvif *vif); @@ -158,4 +163,6 @@ void xenvif_carrier_off(struct xenvif *vif); /* Returns number of ring slots required to send an skb to the frontend */ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); +extern bool separate_tx_rx_irq; + #endif /* __XEN_NETBACK__COMMON_H__ */ diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 82202c2b1bd1..087d2db0389d 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -60,21 +60,39 @@ static int xenvif_rx_schedulable(struct xenvif *vif) return xenvif_schedulable(vif) && !xen_netbk_rx_ring_full(vif); } -static irqreturn_t xenvif_interrupt(int irq, void *dev_id) +static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id) { struct xenvif *vif = dev_id; if (vif->netbk == NULL) - return IRQ_NONE; + return IRQ_HANDLED; xen_netbk_schedule_xenvif(vif); + return IRQ_HANDLED; +} + +static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id) +{ + struct xenvif *vif = dev_id; + + if (vif->netbk == NULL) + return IRQ_HANDLED; + if (xenvif_rx_schedulable(vif)) netif_wake_queue(vif->dev); return IRQ_HANDLED; } +static irqreturn_t xenvif_interrupt(int irq, void *dev_id) +{ + xenvif_tx_interrupt(irq, dev_id); + xenvif_rx_interrupt(irq, dev_id); + + return IRQ_HANDLED; +} + static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); @@ -125,13 +143,17 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) static void xenvif_up(struct xenvif *vif) { xen_netbk_add_xenvif(vif); - enable_irq(vif->irq); + enable_irq(vif->tx_irq); + if (vif->tx_irq != vif->rx_irq) + enable_irq(vif->rx_irq); xen_netbk_check_rx_xenvif(vif); } static void xenvif_down(struct xenvif *vif) { - disable_irq(vif->irq); + disable_irq(vif->tx_irq); + if (vif->tx_irq != vif->rx_irq) + disable_irq(vif->rx_irq); del_timer_sync(&vif->credit_timeout); xen_netbk_deschedule_xenvif(vif); xen_netbk_remove_xenvif(vif); @@ -308,12 +330,13 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, } int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, - unsigned long rx_ring_ref, unsigned int evtchn) + unsigned long rx_ring_ref, unsigned int tx_evtchn, + unsigned int rx_evtchn) { int err = -ENOMEM; /* Already connected through? */ - if (vif->irq) + if (vif->tx_irq) return 0; __module_get(THIS_MODULE); @@ -322,13 +345,37 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, if (err < 0) goto err; - err = bind_interdomain_evtchn_to_irqhandler( - vif->domid, evtchn, xenvif_interrupt, 0, - vif->dev->name, vif); - if (err < 0) - goto err_unmap; - vif->irq = err; - disable_irq(vif->irq); + if (tx_evtchn == rx_evtchn) { + /* feature-split-event-channels == 0 */ + err = bind_interdomain_evtchn_to_irqhandler( + vif->domid, tx_evtchn, xenvif_interrupt, 0, + vif->dev->name, vif); + if (err < 0) + goto err_unmap; + vif->tx_irq = vif->rx_irq = err; + disable_irq(vif->tx_irq); + } else { + /* feature-split-event-channels == 1 */ + snprintf(vif->tx_irq_name, sizeof(vif->tx_irq_name), + "%s-tx", vif->dev->name); + err = bind_interdomain_evtchn_to_irqhandler( + vif->domid, tx_evtchn, xenvif_tx_interrupt, 0, + vif->tx_irq_name, vif); + if (err < 0) + goto err_unmap; + vif->tx_irq = err; + disable_irq(vif->tx_irq); + + snprintf(vif->rx_irq_name, sizeof(vif->rx_irq_name), + "%s-rx", vif->dev->name); + err = bind_interdomain_evtchn_to_irqhandler( + vif->domid, rx_evtchn, xenvif_rx_interrupt, 0, + vif->rx_irq_name, vif); + if (err < 0) + goto err_tx_unbind; + vif->rx_irq = err; + disable_irq(vif->rx_irq); + } xenvif_get(vif); @@ -342,6 +389,9 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, rtnl_unlock(); return 0; +err_tx_unbind: + unbind_from_irqhandler(vif->tx_irq, vif); + vif->tx_irq = 0; err_unmap: xen_netbk_unmap_frontend_rings(vif); err: @@ -375,8 +425,13 @@ void xenvif_disconnect(struct xenvif *vif) atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); - if (vif->irq) { - unbind_from_irqhandler(vif->irq, vif); + if (vif->tx_irq) { + if (vif->tx_irq == vif->rx_irq) + unbind_from_irqhandler(vif->tx_irq, vif); + else { + unbind_from_irqhandler(vif->tx_irq, vif); + unbind_from_irqhandler(vif->rx_irq, vif); + } /* vif->irq is valid, we had a module_get in * xenvif_connect. */ diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 2d9477fd900f..82576fffb452 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -47,6 +47,13 @@ #include #include +/* Provide an option to disable split event channels at load time as + * event channels are limited resource. Split event channels are + * enabled by default. + */ +bool separate_tx_rx_irq = 1; +module_param(separate_tx_rx_irq, bool, 0644); + /* * This is the maximum slots a skb can have. If a guest sends a skb * which exceeds this limit it is considered malicious. @@ -662,7 +669,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) { struct xenvif *vif = NULL, *tmp; s8 status; - u16 irq, flags; + u16 flags; struct xen_netif_rx_response *resp; struct sk_buff_head rxq; struct sk_buff *skb; @@ -771,7 +778,6 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) sco->meta_slots_used); RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret); - irq = vif->irq; if (ret && list_empty(&vif->notify_list)) list_add_tail(&vif->notify_list, ¬ify); @@ -783,7 +789,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) } list_for_each_entry_safe(vif, tmp, ¬ify, notify_list) { - notify_remote_via_irq(vif->irq); + notify_remote_via_irq(vif->rx_irq); list_del_init(&vif->notify_list); } @@ -1762,7 +1768,7 @@ static void make_tx_response(struct xenvif *vif, vif->tx.rsp_prod_pvt = ++i; RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->tx, notify); if (notify) - notify_remote_via_irq(vif->irq); + notify_remote_via_irq(vif->tx_irq); } static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif, diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index d230c145660c..04bd860d16a9 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -122,6 +122,16 @@ static int netback_probe(struct xenbus_device *dev, goto fail; } + /* + * Split event channels support, this is optional so it is not + * put inside the above loop. + */ + err = xenbus_printf(XBT_NIL, dev->nodename, + "feature-split-event-channels", + "%u", separate_tx_rx_irq); + if (err) + pr_debug("Error writing feature-split-event-channels"); + err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) goto fail; @@ -393,21 +403,36 @@ static int connect_rings(struct backend_info *be) struct xenvif *vif = be->vif; struct xenbus_device *dev = be->dev; unsigned long tx_ring_ref, rx_ring_ref; - unsigned int evtchn, rx_copy; + unsigned int tx_evtchn, rx_evtchn, rx_copy; int err; int val; err = xenbus_gather(XBT_NIL, dev->otherend, "tx-ring-ref", "%lu", &tx_ring_ref, - "rx-ring-ref", "%lu", &rx_ring_ref, - "event-channel", "%u", &evtchn, NULL); + "rx-ring-ref", "%lu", &rx_ring_ref, NULL); if (err) { xenbus_dev_fatal(dev, err, - "reading %s/ring-ref and event-channel", + "reading %s/ring-ref", dev->otherend); return err; } + /* Try split event channels first, then single event channel. */ + err = xenbus_gather(XBT_NIL, dev->otherend, + "event-channel-tx", "%u", &tx_evtchn, + "event-channel-rx", "%u", &rx_evtchn, NULL); + if (err < 0) { + err = xenbus_scanf(XBT_NIL, dev->otherend, + "event-channel", "%u", &tx_evtchn); + if (err < 0) { + xenbus_dev_fatal(dev, err, + "reading %s/event-channel(-tx/rx)", + dev->otherend); + return err; + } + rx_evtchn = tx_evtchn; + } + err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u", &rx_copy); if (err == -ENOENT) { @@ -454,11 +479,13 @@ static int connect_rings(struct backend_info *be) vif->csum = !val; /* Map the shared frame, irq etc. */ - err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn); + err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, + tx_evtchn, rx_evtchn); if (err) { xenbus_dev_fatal(dev, err, - "mapping shared-frames %lu/%lu port %u", - tx_ring_ref, rx_ring_ref, evtchn); + "mapping shared-frames %lu/%lu port tx %u rx %u", + tx_ring_ref, rx_ring_ref, + tx_evtchn, rx_evtchn); return err; } return 0; -- GitLab From d634bf2cb96639b7eddb646dc1fc17b1bc6e567f Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 22 May 2013 06:34:46 +0000 Subject: [PATCH 0278/2900] xen-netfront: split event channels support for Xen frontend driver This patch adds a new feature called feature-split-event-channels for netfront, enabling it to handle TX and RX events separately. If netback does not support this feature, it falls back to use single event channel. If netfront fails to setup split event channels, it will try falling back to single event channel. Signed-off-by: Wei Liu Reviewed-by: David Vrabel Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 178 +++++++++++++++++++++++++++++++------ 1 file changed, 149 insertions(+), 29 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 5770e3b0ba73..62238a08cb51 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -85,7 +85,15 @@ struct netfront_info { struct napi_struct napi; - unsigned int evtchn; + /* Split event channels support, tx_* == rx_* when using + * single event channel. + */ + unsigned int tx_evtchn, rx_evtchn; + unsigned int tx_irq, rx_irq; + /* Only used when split event channels support is enabled */ + char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */ + char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ + struct xenbus_device *xbdev; spinlock_t tx_lock; @@ -330,7 +338,7 @@ static void xennet_alloc_rx_buffers(struct net_device *dev) push: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); if (notify) - notify_remote_via_irq(np->netdev->irq); + notify_remote_via_irq(np->rx_irq); } static int xennet_open(struct net_device *dev) @@ -623,7 +631,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify); if (notify) - notify_remote_via_irq(np->netdev->irq); + notify_remote_via_irq(np->tx_irq); u64_stats_update_begin(&stats->syncp); stats->tx_bytes += skb->len; @@ -1254,23 +1262,35 @@ static int xennet_set_features(struct net_device *dev, return 0; } -static irqreturn_t xennet_interrupt(int irq, void *dev_id) +static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id) { - struct net_device *dev = dev_id; - struct netfront_info *np = netdev_priv(dev); + struct netfront_info *np = dev_id; + struct net_device *dev = np->netdev; unsigned long flags; spin_lock_irqsave(&np->tx_lock, flags); + xennet_tx_buf_gc(dev); + spin_unlock_irqrestore(&np->tx_lock, flags); - if (likely(netif_carrier_ok(dev))) { - xennet_tx_buf_gc(dev); - /* Under tx_lock: protects access to rx shared-ring indexes. */ - if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) + return IRQ_HANDLED; +} + +static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id) +{ + struct netfront_info *np = dev_id; + struct net_device *dev = np->netdev; + + if (likely(netif_carrier_ok(dev) && + RING_HAS_UNCONSUMED_RESPONSES(&np->rx))) napi_schedule(&np->napi); - } - spin_unlock_irqrestore(&np->tx_lock, flags); + return IRQ_HANDLED; +} +static irqreturn_t xennet_interrupt(int irq, void *dev_id) +{ + xennet_tx_interrupt(irq, dev_id); + xennet_rx_interrupt(irq, dev_id); return IRQ_HANDLED; } @@ -1451,9 +1471,14 @@ static void xennet_disconnect_backend(struct netfront_info *info) spin_unlock_irq(&info->tx_lock); spin_unlock_bh(&info->rx_lock); - if (info->netdev->irq) - unbind_from_irqhandler(info->netdev->irq, info->netdev); - info->evtchn = info->netdev->irq = 0; + if (info->tx_irq && (info->tx_irq == info->rx_irq)) + unbind_from_irqhandler(info->tx_irq, info); + if (info->tx_irq && (info->tx_irq != info->rx_irq)) { + unbind_from_irqhandler(info->tx_irq, info); + unbind_from_irqhandler(info->rx_irq, info); + } + info->tx_evtchn = info->rx_evtchn = 0; + info->tx_irq = info->rx_irq = 0; /* End access and free the pages */ xennet_end_access(info->tx_ring_ref, info->tx.sring); @@ -1503,12 +1528,82 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[]) return 0; } +static int setup_netfront_single(struct netfront_info *info) +{ + int err; + + err = xenbus_alloc_evtchn(info->xbdev, &info->tx_evtchn); + if (err < 0) + goto fail; + + err = bind_evtchn_to_irqhandler(info->tx_evtchn, + xennet_interrupt, + 0, info->netdev->name, info); + if (err < 0) + goto bind_fail; + info->rx_evtchn = info->tx_evtchn; + info->rx_irq = info->tx_irq = err; + + return 0; + +bind_fail: + xenbus_free_evtchn(info->xbdev, info->tx_evtchn); + info->tx_evtchn = 0; +fail: + return err; +} + +static int setup_netfront_split(struct netfront_info *info) +{ + int err; + + err = xenbus_alloc_evtchn(info->xbdev, &info->tx_evtchn); + if (err < 0) + goto fail; + err = xenbus_alloc_evtchn(info->xbdev, &info->rx_evtchn); + if (err < 0) + goto alloc_rx_evtchn_fail; + + snprintf(info->tx_irq_name, sizeof(info->tx_irq_name), + "%s-tx", info->netdev->name); + err = bind_evtchn_to_irqhandler(info->tx_evtchn, + xennet_tx_interrupt, + 0, info->tx_irq_name, info); + if (err < 0) + goto bind_tx_fail; + info->tx_irq = err; + + snprintf(info->rx_irq_name, sizeof(info->rx_irq_name), + "%s-rx", info->netdev->name); + err = bind_evtchn_to_irqhandler(info->rx_evtchn, + xennet_rx_interrupt, + 0, info->rx_irq_name, info); + if (err < 0) + goto bind_rx_fail; + info->rx_irq = err; + + return 0; + +bind_rx_fail: + unbind_from_irqhandler(info->tx_irq, info); + info->tx_irq = 0; +bind_tx_fail: + xenbus_free_evtchn(info->xbdev, info->rx_evtchn); + info->rx_evtchn = 0; +alloc_rx_evtchn_fail: + xenbus_free_evtchn(info->xbdev, info->tx_evtchn); + info->tx_evtchn = 0; +fail: + return err; +} + static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) { struct xen_netif_tx_sring *txs; struct xen_netif_rx_sring *rxs; int err; struct net_device *netdev = info->netdev; + unsigned int feature_split_evtchn; info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; @@ -1516,6 +1611,12 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) info->tx.sring = NULL; netdev->irq = 0; + err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, + "feature-split-event-channels", "%u", + &feature_split_evtchn); + if (err < 0) + feature_split_evtchn = 0; + err = xen_net_read_mac(dev, netdev->dev_addr); if (err) { xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); @@ -1550,22 +1651,23 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info) goto grant_rx_ring_fail; info->rx_ring_ref = err; - err = xenbus_alloc_evtchn(dev, &info->evtchn); + if (feature_split_evtchn) + err = setup_netfront_split(info); + /* setup single event channel if + * a) feature-split-event-channels == 0 + * b) feature-split-event-channels == 1 but failed to setup + */ + if (!feature_split_evtchn || (feature_split_evtchn && err)) + err = setup_netfront_single(info); + if (err) goto alloc_evtchn_fail; - err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, - 0, netdev->name, netdev); - if (err < 0) - goto bind_fail; - netdev->irq = err; return 0; /* If we fail to setup netfront, it is safe to just revoke access to * granted pages because backend is not accessing it at this point. */ -bind_fail: - xenbus_free_evtchn(dev, info->evtchn); alloc_evtchn_fail: gnttab_end_foreign_access_ref(info->rx_ring_ref, 0); grant_rx_ring_fail: @@ -1610,11 +1712,27 @@ static int talk_to_netback(struct xenbus_device *dev, message = "writing rx ring-ref"; goto abort_transaction; } - err = xenbus_printf(xbt, dev->nodename, - "event-channel", "%u", info->evtchn); - if (err) { - message = "writing event-channel"; - goto abort_transaction; + + if (info->tx_evtchn == info->rx_evtchn) { + err = xenbus_printf(xbt, dev->nodename, + "event-channel", "%u", info->tx_evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + } else { + err = xenbus_printf(xbt, dev->nodename, + "event-channel-tx", "%u", info->tx_evtchn); + if (err) { + message = "writing event-channel-tx"; + goto abort_transaction; + } + err = xenbus_printf(xbt, dev->nodename, + "event-channel-rx", "%u", info->rx_evtchn); + if (err) { + message = "writing event-channel-rx"; + goto abort_transaction; + } } err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u", @@ -1727,7 +1845,9 @@ static int xennet_connect(struct net_device *dev) * packets. */ netif_carrier_on(np->netdev); - notify_remote_via_irq(np->netdev->irq); + notify_remote_via_irq(np->tx_irq); + if (np->tx_irq != np->rx_irq) + notify_remote_via_irq(np->rx_irq); xennet_tx_buf_gc(dev); xennet_alloc_rx_buffers(dev); -- GitLab From a5560a6c17a4af4e8f45d5c1215ba7d5bb0ff109 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 22 May 2013 06:34:47 +0000 Subject: [PATCH 0279/2900] xen: netif.h: document feature-split-event-channels This patch synchronises documentation for feature-split-event-channels from Xen canonical header file. Signed-off-by: Wei Liu Signed-off-by: David S. Miller --- include/xen/interface/io/netif.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h index 3ef3fe05ee99..eb262e3324d2 100644 --- a/include/xen/interface/io/netif.h +++ b/include/xen/interface/io/netif.h @@ -38,6 +38,18 @@ * that it cannot safely queue packets (as it may not be kicked to send them). */ + /* + * "feature-split-event-channels" is introduced to separate guest TX + * and RX notificaion. Backend either doesn't support this feature or + * advertise it via xenstore as 0 (disabled) or 1 (enabled). + * + * To make use of this feature, frontend should allocate two event + * channels for TX and RX, advertise them to backend as + * "event-channel-tx" and "event-channel-rx" respectively. If frontend + * doesn't want to use this feature, it just writes "event-channel" + * node as before. + */ + /* * This is the 'wire' format for packets: * Request 1: xen_netif_tx_request -- XEN_NETTXF_* (any flags) -- GitLab From 3521b419cc21339537266cb1ab9934b041ca08e9 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Wed, 22 May 2013 21:21:49 +0000 Subject: [PATCH 0280/2900] bnx2x: Add Private Flags Support Utilize ethtool's callback `get_priv_flags' - shed more light on the feasibility of devices as storage interfaces. CC: Ben Hutchings Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Acked-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 + .../ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 49 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 3dba2a70a00e..3f4291056e80 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2137,6 +2137,8 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, #define ATTN_HARD_WIRED_MASK 0xff00 #define ATTENTION_ID 4 +#define IS_MF_STORAGE_ONLY(bp) (IS_MF_STORAGE_SD(bp) || \ + IS_MF_FCOE_AFEX(bp)) /* stuff added to make the code fit 80Col */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index ce1a91618677..9e311c4b69f3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1921,6 +1921,19 @@ static const char bnx2x_tests_str_arr[BNX2X_NUM_TESTS_SF][ETH_GSTRING_LEN] = { "link_test (online) " }; +enum { + BNX2X_PRI_FLAG_ISCSI, + BNX2X_PRI_FLAG_FCOE, + BNX2X_PRI_FLAG_STORAGE, + BNX2X_PRI_FLAG_LEN, +}; + +static const char bnx2x_private_arr[BNX2X_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { + "iSCSI offload support", + "FCoE offload support", + "Storage only interface" +}; + static u32 bnx2x_eee_to_adv(u32 eee_adv) { u32 modes = 0; @@ -2978,32 +2991,47 @@ static int bnx2x_num_stat_queues(struct bnx2x *bp) static int bnx2x_get_sset_count(struct net_device *dev, int stringset) { struct bnx2x *bp = netdev_priv(dev); - int i, num_stats; + int i, num_strings = 0; switch (stringset) { case ETH_SS_STATS: if (is_multi(bp)) { - num_stats = bnx2x_num_stat_queues(bp) * - BNX2X_NUM_Q_STATS; + num_strings = bnx2x_num_stat_queues(bp) * + BNX2X_NUM_Q_STATS; } else - num_stats = 0; + num_strings = 0; if (IS_MF_MODE_STAT(bp)) { for (i = 0; i < BNX2X_NUM_STATS; i++) if (IS_FUNC_STAT(i)) - num_stats++; + num_strings++; } else - num_stats += BNX2X_NUM_STATS; + num_strings += BNX2X_NUM_STATS; - return num_stats; + return num_strings; case ETH_SS_TEST: return BNX2X_NUM_TESTS(bp); + case ETH_SS_PRIV_FLAGS: + return BNX2X_PRI_FLAG_LEN; + default: return -EINVAL; } } +static u32 bnx2x_get_private_flags(struct net_device *dev) +{ + struct bnx2x *bp = netdev_priv(dev); + u32 flags = 0; + + flags |= (!(bp->flags & NO_ISCSI_FLAG) ? 1 : 0) << BNX2X_PRI_FLAG_ISCSI; + flags |= (!(bp->flags & NO_FCOE_FLAG) ? 1 : 0) << BNX2X_PRI_FLAG_FCOE; + flags |= (!!IS_MF_STORAGE_ONLY(bp)) << BNX2X_PRI_FLAG_STORAGE; + + return flags; +} + static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { struct bnx2x *bp = netdev_priv(dev); @@ -3045,6 +3073,12 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) start = 4; memcpy(buf, bnx2x_tests_str_arr + start, ETH_GSTRING_LEN * BNX2X_NUM_TESTS(bp)); + break; + + case ETH_SS_PRIV_FLAGS: + memcpy(buf, bnx2x_private_arr, + ETH_GSTRING_LEN * BNX2X_PRI_FLAG_LEN); + break; } } @@ -3445,6 +3479,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .set_pauseparam = bnx2x_set_pauseparam, .self_test = bnx2x_self_test, .get_sset_count = bnx2x_get_sset_count, + .get_priv_flags = bnx2x_get_private_flags, .get_strings = bnx2x_get_strings, .set_phys_id = bnx2x_set_phys_id, .get_ethtool_stats = bnx2x_get_ethtool_stats, -- GitLab From 178135c11611c02161c5b64aeba341d777f2d64d Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 22 May 2013 21:21:50 +0000 Subject: [PATCH 0281/2900] bnx2x: Link-flap avoidance in switch dependent mode As part of the previous unload flow, probed devices will reset the chip in order to clean the remains of the UNDI driver. As a result, it's possible for the FW to toggle the link. This toggling can prove fatal, as long periods without link can cause the filesystem mount to fail as the storage protocol timeouts. This has been observed against particular switches with long link re-establishment time. This patch informs FW during the reset period that the link should not be toggled - the FW will keep it alive until some interface will load and claim the link as its own. Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 ++ .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 10 ++++++++-- .../net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | 2 ++ .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 19 ++++++++++++++++--- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 3f4291056e80..946450d6d988 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1937,6 +1937,8 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, void bnx2x_update_coalesce(struct bnx2x *bp); int bnx2x_get_cur_phy_idx(struct bnx2x *bp); +bool bnx2x_port_after_undi(struct bnx2x *bp); + static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, int wait) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 6cc5101fa96b..f4d1c08c67d3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2183,6 +2183,8 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) /* send load request to mcp and analyze response */ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code) { + u32 param; + /* init fw_seq */ bp->fw_seq = (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & @@ -2195,9 +2197,13 @@ static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code) DRV_PULSE_SEQ_MASK); BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq); + param = DRV_MSG_CODE_LOAD_REQ_WITH_LFA; + + if (IS_MF_SD(bp) && bnx2x_port_after_undi(bp)) + param |= DRV_MSG_CODE_LOAD_REQ_FORCE_LFA; + /* load request */ - (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, - DRV_MSG_CODE_LOAD_REQ_WITH_LFA); + (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, param); /* if mcp fails to respond we must abort */ if (!(*load_code)) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 12f00a40cdf0..5ef3f964e544 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -1323,6 +1323,8 @@ struct drv_func_mb { #define DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET 0x00000002 #define DRV_MSG_CODE_LOAD_REQ_WITH_LFA 0x0000100a + #define DRV_MSG_CODE_LOAD_REQ_FORCE_LFA 0x00002000 + u32 fw_mb_header; #define FW_MSG_CODE_MASK 0xffff0000 #define FW_MSG_CODE_DRV_LOAD_COMMON 0x10100000 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index b4c9dea93a53..649880d2bb1b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9780,6 +9780,21 @@ static bool bnx2x_prev_is_path_marked(struct bnx2x *bp) return rc; } +bool bnx2x_port_after_undi(struct bnx2x *bp) +{ + struct bnx2x_prev_path_list *entry; + bool val; + + down(&bnx2x_prev_sem); + + entry = bnx2x_prev_path_get_entry(bp); + val = !!(entry && (entry->undi & (1 << BP_PORT(bp)))); + + up(&bnx2x_prev_sem); + + return val; +} + static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi) { struct bnx2x_prev_path_list *tmp_list; @@ -10036,7 +10051,6 @@ static int bnx2x_prev_unload(struct bnx2x *bp) { int time_counter = 10; u32 rc, fw, hw_lock_reg, hw_lock_val; - struct bnx2x_prev_path_list *prev_list; BNX2X_DEV_INFO("Entering Previous Unload Flow\n"); /* clear hw from errors which may have resulted from an interrupted @@ -10107,8 +10121,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) } /* Mark function if its port was used to boot from SAN */ - prev_list = bnx2x_prev_path_get_entry(bp); - if (prev_list && (prev_list->undi & (1 << BP_PORT(bp)))) + if (bnx2x_port_after_undi(bp)) bp->link_params.feature_config_flags |= FEATURE_CONFIG_BOOT_FROM_SAN; -- GitLab From e68072ef46bcfb609ea16d45f115896a0dfbd3ff Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Wed, 22 May 2013 21:21:51 +0000 Subject: [PATCH 0282/2900] bnx2x: Wait for MCP validity during AER During PCIe advanced error recovery, the secondary bus reset will cause FW to reset; This will cause the shared memory between it and the driver to be invalidated. During the driver's recovery flow, the driver should not make any assumption on the validity of that memory and instead re-initialize it. This also removes a redundant re-initialization of a previously initialized mutex. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 649880d2bb1b..7ed9cdfa115e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12760,19 +12760,6 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) return 0; } -static void bnx2x_eeh_recover(struct bnx2x *bp) -{ - u32 val; - - mutex_init(&bp->port.phy_mutex); - - - val = SHMEM_RD(bp, validity_map[BP_PORT(bp)]); - if ((val & (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) - != (SHR_MEM_VALIDITY_DEV_INFO | SHR_MEM_VALIDITY_MB)) - BNX2X_ERR("BAD MCP validity signature\n"); -} - /** * bnx2x_io_error_detected - called when PCI error is detected * @pdev: Pointer to PCI device @@ -12841,6 +12828,10 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) if (netif_running(dev)) { BNX2X_ERR("IO slot reset --> driver unload\n"); + + /* MCP should have been reset; Need to wait for validity */ + bnx2x_init_shmem(bp); + if (IS_PF(bp) && SHMEM2_HAS(bp, drv_capabilities_flag)) { u32 v; @@ -12899,8 +12890,6 @@ static void bnx2x_io_resume(struct pci_dev *pdev) rtnl_lock(); - bnx2x_eeh_recover(bp); - bp->fw_seq = SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK; -- GitLab From 84b6f7456e8b88507dd85f988a9d350eb5af0e46 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Wed, 22 May 2013 21:21:52 +0000 Subject: [PATCH 0283/2900] bnx2x: Enable `set_phys_id' for all functions In Multi-function mode, all functions should be able to utilize said function; There's no reason why only the link owner should be able to do so. Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 9e311c4b69f3..32aa88f520dc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3146,11 +3146,6 @@ static int bnx2x_set_phys_id(struct net_device *dev, return -EAGAIN; } - if (!bp->port.pmf) { - DP(BNX2X_MSG_ETHTOOL, "Interface is not pmf\n"); - return -EOPNOTSUPP; - } - switch (state) { case ETHTOOL_ID_ACTIVE: return 1; /* cycle on/off once per second */ -- GitLab From 161f65ba3583b84b4714f21dbee263f99824c516 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 22 May 2013 07:49:34 +0000 Subject: [PATCH 0284/2900] bridge: Set vlan_features to allow offloads on vlans. When vlan device is configured on top of the brige, it does not support any offload capabilities because the bridge device does not initiliaze vlan_fatures. Set vlan_fatures to be equivalent to hw_fatures. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/bridge/br_device.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 967312803e41..75f3239130f8 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -22,6 +22,9 @@ #include #include "br_private.h" +#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \ + NETIF_F_GSO_MASK | NETIF_F_HW_CSUM) + /* net device transmit always called with BH disabled */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -346,12 +349,10 @@ void br_dev_setup(struct net_device *dev) dev->tx_queue_len = 0; dev->priv_flags = IFF_EBRIDGE; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX | - NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_CTAG_TX; - dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_TX; + dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL | + NETIF_F_HW_VLAN_CTAG_TX; + dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX; + dev->vlan_features = COMMON_FEATURES; br->dev = dev; spin_lock_init(&br->lock); -- GitLab From 191cb1f21afd9a7fbaa085ad9b86cb307e9a3891 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Wed, 22 May 2013 07:54:40 +0000 Subject: [PATCH 0285/2900] rps: document flow limit in scaling.txt Explain the mechanism and API of the recently merged rps flow limit patch. Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- Documentation/networking/scaling.txt | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/Documentation/networking/scaling.txt b/Documentation/networking/scaling.txt index 579994afbe06..ca6977f5b2ed 100644 --- a/Documentation/networking/scaling.txt +++ b/Documentation/networking/scaling.txt @@ -163,6 +163,64 @@ and unnecessary. If there are fewer hardware queues than CPUs, then RPS might be beneficial if the rps_cpus for each queue are the ones that share the same memory domain as the interrupting CPU for that queue. +==== RPS Flow Limit + +RPS scales kernel receive processing across CPUs without introducing +reordering. The trade-off to sending all packets from the same flow +to the same CPU is CPU load imbalance if flows vary in packet rate. +In the extreme case a single flow dominates traffic. Especially on +common server workloads with many concurrent connections, such +behavior indicates a problem such as a misconfiguration or spoofed +source Denial of Service attack. + +Flow Limit is an optional RPS feature that prioritizes small flows +during CPU contention by dropping packets from large flows slightly +ahead of those from small flows. It is active only when an RPS or RFS +destination CPU approaches saturation. Once a CPU's input packet +queue exceeds half the maximum queue length (as set by sysctl +net.core.netdev_max_backlog), the kernel starts a per-flow packet +count over the last 256 packets. If a flow exceeds a set ratio (by +default, half) of these packets when a new packet arrives, then the +new packet is dropped. Packets from other flows are still only +dropped once the input packet queue reaches netdev_max_backlog. +No packets are dropped when the input packet queue length is below +the threshold, so flow limit does not sever connections outright: +even large flows maintain connectivity. + +== Interface + +Flow limit is compiled in by default (CONFIG_NET_FLOW_LIMIT), but not +turned on. It is implemented for each CPU independently (to avoid lock +and cache contention) and toggled per CPU by setting the relevant bit +in sysctl net.core.flow_limit_cpu_bitmap. It exposes the same CPU +bitmap interface as rps_cpus (see above) when called from procfs: + + /proc/sys/net/core/flow_limit_cpu_bitmap + +Per-flow rate is calculated by hashing each packet into a hashtable +bucket and incrementing a per-bucket counter. The hash function is +the same that selects a CPU in RPS, but as the number of buckets can +be much larger than the number of CPUs, flow limit has finer-grained +identification of large flows and fewer false positives. The default +table has 4096 buckets. This value can be modified through sysctl + + net.core.flow_limit_table_len + +The value is only consulted when a new table is allocated. Modifying +it does not update active tables. + +== Suggested Configuration + +Flow limit is useful on systems with many concurrent connections, +where a single connection taking up 50% of a CPU indicates a problem. +In such environments, enable the feature on all CPUs that handle +network rx interrupts (as set in /proc/irq/N/smp_affinity). + +The feature depends on the input packet queue length to exceed +the flow limit threshold (50%) + the flow history length (256). +Setting net.core.netdev_max_backlog to either 1000 or 10000 +performed well in experiments. + RFS: Receive Flow Steering ========================== -- GitLab From ee9c799c231324de681eb21e06d8bf4842768b75 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 22 May 2013 23:04:55 +0000 Subject: [PATCH 0286/2900] be2net: refactor HW workarounds in be_xmit() Refactor all TX HW workarounds into a separate routine called be_xmit_workarounds(). Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 62 +++++++++++++-------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a444110b060f..7892361af0ac 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -842,32 +842,27 @@ static int be_vlan_tag_tx_chk(struct be_adapter *adapter, struct sk_buff *skb) return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid; } -static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb) +static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, + struct sk_buff *skb) { - return BE3_chip(adapter) && - be_ipv6_exthdr_check(skb); + return BE3_chip(adapter) && be_ipv6_exthdr_check(skb); } -static netdev_tx_t be_xmit(struct sk_buff *skb, - struct net_device *netdev) +static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, + struct sk_buff *skb, + bool *skip_hw_vlan) { - struct be_adapter *adapter = netdev_priv(netdev); - struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; - struct be_queue_info *txq = &txo->q; - struct iphdr *ip = NULL; - u32 wrb_cnt = 0, copied = 0; - u32 start = txq->head, eth_hdr_len; - bool dummy_wrb, stopped = false; - bool skip_hw_vlan = false; struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; - - eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? - VLAN_ETH_HLEN : ETH_HLEN; + unsigned int eth_hdr_len; + struct iphdr *ip; /* For padded packets, BE HW modifies tot_len field in IP header * incorrecly when VLAN tag is inserted by HW. */ - if (skb->len <= 60 && vlan_tx_tag_present(skb) && is_ipv4_pkt(skb)) { + eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? + VLAN_ETH_HLEN : ETH_HLEN; + if (skb->len <= 60 && vlan_tx_tag_present(skb) && + is_ipv4_pkt(skb)) { ip = (struct iphdr *)ip_hdr(skb); pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); } @@ -877,15 +872,15 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, */ if ((adapter->function_mode & UMC_ENABLED) && veh->h_vlan_proto == htons(ETH_P_8021Q)) - skip_hw_vlan = true; + *skip_hw_vlan = true; /* HW has a bug wherein it will calculate CSUM for VLAN * pkts even though it is disabled. * Manually insert VLAN in pkt. */ if (skb->ip_summed != CHECKSUM_PARTIAL && - vlan_tx_tag_present(skb)) { - skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan); + vlan_tx_tag_present(skb)) { + skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); if (unlikely(!skb)) goto tx_drop; } @@ -895,8 +890,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, * skip HW tagging is not enabled by FW. */ if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) && - (adapter->pvid || adapter->qnq_vid) && - !qnq_async_evt_rcvd(adapter))) + (adapter->pvid || adapter->qnq_vid) && + !qnq_async_evt_rcvd(adapter))) goto tx_drop; /* Manual VLAN tag insertion to prevent: @@ -907,11 +902,31 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, */ if (be_ipv6_tx_stall_chk(adapter, skb) && be_vlan_tag_tx_chk(adapter, skb)) { - skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan); + skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan); if (unlikely(!skb)) goto tx_drop; } + return skb; +tx_drop: + dev_kfree_skb_any(skb); + return NULL; +} + +static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; + struct be_queue_info *txq = &txo->q; + bool dummy_wrb, stopped = false; + u32 wrb_cnt = 0, copied = 0; + bool skip_hw_vlan = false; + u32 start = txq->head; + + skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan); + if (!skb) + return NETDEV_TX_OK; + wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb, @@ -941,7 +956,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, txq->head = start; dev_kfree_skb_any(skb); } -tx_drop: return NETDEV_TX_OK; } -- GitLab From 786677d100600b7f6089bae0d3967c1b901a6141 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 24 May 2013 12:05:45 +0200 Subject: [PATCH 0287/2900] mac80211: add STBC flag for radiotap Some chips can tell us if received frame was encoded with STBC or not. To make this information available in user space we can use updated radiotap specification: http://www.radiotap.org/defined-fields/MCS This patch will set number of STBC encoded spatial streams (Nss). The HAVE_STBC flag should be provided by driver. Signed-off-by: Oleksij Rempel Signed-off-by: Johannes Berg --- include/net/ieee80211_radiotap.h | 7 +++++++ include/net/mac80211.h | 4 ++++ net/mac80211/rx.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index c3999632e616..c6d07cb074bc 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -269,6 +269,7 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 #define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 #define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 +#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 #define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 #define IEEE80211_RADIOTAP_MCS_BW_20 0 @@ -278,6 +279,12 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_MCS_SGI 0x04 #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 +#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 +#define IEEE80211_RADIOTAP_MCS_STBC_1 1 +#define IEEE80211_RADIOTAP_MCS_STBC_2 2 +#define IEEE80211_RADIOTAP_MCS_STBC_3 3 + +#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */ #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c36535e7b291..c9e6fb7417f6 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -805,6 +805,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * on this subframe * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC * is stored in the @ampdu_delimiter_crc field) + * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = BIT(0), @@ -832,8 +833,11 @@ enum mac80211_rx_flags { RX_FLAG_80MHZ = BIT(23), RX_FLAG_80P80MHZ = BIT(24), RX_FLAG_160MHZ = BIT(25), + RX_FLAG_STBC_MASK = BIT(26) | BIT(27), }; +#define RX_FLAG_STBC_SHIFT 26 + /** * struct ieee80211_rx_status - receive status * diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6e2c8c5236c4..7507f7cdd68c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -258,6 +258,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos += 2; if (status->flag & RX_FLAG_HT) { + unsigned int stbc; + rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); *pos++ = local->hw.radiotap_mcs_details; *pos = 0; @@ -267,6 +269,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, *pos |= IEEE80211_RADIOTAP_MCS_BW_40; if (status->flag & RX_FLAG_HT_GF) *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; + stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; + *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; pos++; *pos++ = status->rate_idx; } -- GitLab From a1ef50398deff2f02bad7635fbadda96e8f462e7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:24 +0200 Subject: [PATCH 0288/2900] rt2800: make rt2800_init_bbp return void This function can not fail, we always return 0. Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index bddfd6dab3cf..8de40d63d9b9 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4027,20 +4027,16 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); } -static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) { unsigned int i; u16 eeprom; u8 reg_id; u8 value; - if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || - rt2800_wait_bbp_ready(rt2x00dev))) - return -EACCES; - if (rt2x00_rt(rt2x00dev, RT5592)) { rt2800_init_bbp_5592(rt2x00dev); - return 0; + return; } if (rt2x00_rt(rt2x00dev, RT3352)) { @@ -4337,8 +4333,6 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, reg_id, value); } } - - return 0; } static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev) @@ -5189,9 +5183,11 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) } msleep(1); - if (unlikely(rt2800_init_bbp(rt2x00dev))) + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || + rt2800_wait_bbp_ready(rt2x00dev))) return -EIO; + rt2800_init_bbp(rt2x00dev); rt2800_init_rfcsr(rt2x00dev); if (rt2x00_is_usb(rt2x00dev) && -- GitLab From 39ab3e8b4579384068c5081934464fd3a0dfc344 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:25 +0200 Subject: [PATCH 0289/2900] rt2800: prepare for rt2800_init_bbp spit Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 57 ++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8de40d63d9b9..7e16771b1b1a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3953,6 +3953,34 @@ static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x35); } +static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) +{ +} + +static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) +{ +} + static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) { int ant, div_mode; @@ -4034,7 +4062,34 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) u8 reg_id; u8 value; - if (rt2x00_rt(rt2x00dev, RT5592)) { + switch (rt2x00dev->chip.rt) { + case RT2860: + case RT2872: + case RT2883: + rt2800_init_bbp_28xx(rt2x00dev); + break; + case RT3070: + case RT3071: + case RT3090: + rt2800_init_bbp_30xx(rt2x00dev); + break; + case RT3290: + rt2800_init_bbp_3290(rt2x00dev); + break; + case RT3352: + rt2800_init_bbp_3352(rt2x00dev); + break; + case RT3390: + rt2800_init_bbp_3390(rt2x00dev); + break; + case RT3572: + rt2800_init_bbp_3572(rt2x00dev); + break; + case RT5390: + case RT5392: + rt2800_init_bbp_53xx(rt2x00dev); + break; + case RT5592: rt2800_init_bbp_5592(rt2x00dev); return; } -- GitLab From dae62957ff6d6c45bba02b00623f56e44e62e286 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:26 +0200 Subject: [PATCH 0290/2900] rt2800: add rt2800_init_bbp_305x_soc subroutine New routine for SOC specific BBP initialization, empty for now. Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7e16771b1b1a..ba1a989b6d3b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3953,6 +3953,10 @@ static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x35); } +static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +} + static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) { } @@ -4062,6 +4066,9 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) u8 reg_id; u8 value; + if (rt2800_is_305x_soc(rt2x00dev)) + rt2800_init_bbp_305x_soc(rt2x00dev); + switch (rt2x00dev->chip.rt) { case RT2860: case RT2872: -- GitLab From 29f3a58b9025683e088205f3db9e51d5294957b7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:27 +0200 Subject: [PATCH 0291/2900] rt2800: move 3352 bbp specific code Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ba1a989b6d3b..11030ff57bab 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3971,6 +3971,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 3, 0x00); + rt2800_bbp_write(rt2x00dev, 4, 0x50); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4101,11 +4103,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3352)) { - rt2800_bbp_write(rt2x00dev, 3, 0x00); - rt2800_bbp_write(rt2x00dev, 4, 0x50); - } - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) -- GitLab From c3223573520e73c4aee303a122a9ea6a9342a010 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:28 +0200 Subject: [PATCH 0292/2900] rt2800: move rt2800_bbp4_mac_if_ctrl to proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 11030ff57bab..687abd539dff 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3967,6 +3967,7 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp4_mac_if_ctrl(rt2x00dev); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -3985,6 +3986,7 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp4_mac_if_ctrl(rt2x00dev); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4103,11 +4105,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp4_mac_if_ctrl(rt2x00dev); - if (rt2800_is_305x_soc(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3352) || -- GitLab From b2f8e0bd2624d458cfa4d46a4b49803ef55f7b3f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:29 +0200 Subject: [PATCH 0293/2900] rt2800: initialize BBP_R31 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 687abd539dff..c74105822fd4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3955,6 +3955,7 @@ static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 31, 0x08); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3968,12 +3969,16 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) { rt2800_bbp4_mac_if_ctrl(rt2x00dev); + + rt2800_bbp_write(rt2x00dev, 31, 0x08); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 3, 0x00); rt2800_bbp_write(rt2x00dev, 4, 0x50); + + rt2800_bbp_write(rt2x00dev, 31, 0x08); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -3982,11 +3987,14 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 31, 0x08); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) { rt2800_bbp4_mac_if_ctrl(rt2x00dev); + + rt2800_bbp_write(rt2x00dev, 31, 0x08); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4105,14 +4113,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2800_is_305x_soc(rt2x00dev) || - rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT3572) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 31, 0x08); - if (rt2x00_rt(rt2x00dev, RT3352)) rt2800_bbp_write(rt2x00dev, 47, 0x48); -- GitLab From 3420f797536a52fd78ad8b692045bd7fa6a2ab32 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:30 +0200 Subject: [PATCH 0294/2900] rt2800: initialize BBP_R47 on 3352 subroutine Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c74105822fd4..5259936e2592 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3979,6 +3979,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 4, 0x50); rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 47, 0x48); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4113,9 +4115,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3352)) - rt2800_bbp_write(rt2x00dev, 47, 0x48); - rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); -- GitLab From e379de1297a1edc05250c408af7f474b2a1cbacc Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:31 +0200 Subject: [PATCH 0295/2900] rt2800: initialize BBP_R65 & BBP_R66 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5259936e2592..18c5925e2a61 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3956,14 +3956,21 @@ static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -3971,6 +3978,9 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp4_mac_if_ctrl(rt2x00dev); rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -3981,15 +3991,23 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 31, 0x08); rt2800_bbp_write(rt2x00dev, 47, 0x48); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) { + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -3997,6 +4015,9 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp4_mac_if_ctrl(rt2x00dev); rt2800_bbp_write(rt2x00dev, 31, 0x08); + + rt2800_bbp_write(rt2x00dev, 65, 0x2c); + rt2800_bbp_write(rt2x00dev, 66, 0x38); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4115,9 +4136,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - rt2800_bbp_write(rt2x00dev, 65, 0x2c); - rt2800_bbp_write(rt2x00dev, 66, 0x38); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || -- GitLab From 59dcabb5c12148c2e4d57dfaeea3af2098bd02d2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:32 +0200 Subject: [PATCH 0296/2900] rt2800: initialize BBP_R68 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 18c5925e2a61..54a7690a5031 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3981,6 +3981,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 68, 0x0b); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -3994,6 +3996,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 68, 0x0b); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4018,6 +4022,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 68, 0x0b); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4136,12 +4142,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 68, 0x0b); - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 73, 0x12); -- GitLab From 72ffe1426b47275b464aa946d47b4de10b5e3a8f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:33 +0200 Subject: [PATCH 0297/2900] rt2800: initialize BBP_R69 - BBP_R77 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 62 ++++++++++++++++--------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 54a7690a5031..26feb99a0aa8 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3959,18 +3959,32 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { + rt2800_bbp_write(rt2x00dev, 69, 0x16); + rt2800_bbp_write(rt2x00dev, 73, 0x12); + } else { + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); + } } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -3983,6 +3997,13 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 66, 0x38); rt2800_bbp_write(rt2x00dev, 68, 0x0b); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x13); + rt2800_bbp_write(rt2x00dev, 75, 0x46); + rt2800_bbp_write(rt2x00dev, 76, 0x28); + + rt2800_bbp_write(rt2x00dev, 77, 0x58); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -3998,12 +4019,22 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 66, 0x38); rt2800_bbp_write(rt2x00dev, 68, 0x0b); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x13); + rt2800_bbp_write(rt2x00dev, 75, 0x46); + rt2800_bbp_write(rt2x00dev, 76, 0x28); + + rt2800_bbp_write(rt2x00dev, 77, 0x59); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4012,6 +4043,9 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 65, 0x2c); rt2800_bbp_write(rt2x00dev, 66, 0x38); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x10); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4024,6 +4058,13 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 66, 0x38); rt2800_bbp_write(rt2x00dev, 68, 0x0b); + + rt2800_bbp_write(rt2x00dev, 69, 0x12); + rt2800_bbp_write(rt2x00dev, 73, 0x13); + rt2800_bbp_write(rt2x00dev, 75, 0x46); + rt2800_bbp_write(rt2x00dev, 76, 0x28); + + rt2800_bbp_write(rt2x00dev, 77, 0x59); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4142,27 +4183,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { - rt2800_bbp_write(rt2x00dev, 69, 0x16); - rt2800_bbp_write(rt2x00dev, 73, 0x12); - } else if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_bbp_write(rt2x00dev, 69, 0x12); - rt2800_bbp_write(rt2x00dev, 73, 0x13); - rt2800_bbp_write(rt2x00dev, 75, 0x46); - rt2800_bbp_write(rt2x00dev, 76, 0x28); - - if (rt2x00_rt(rt2x00dev, RT3290)) - rt2800_bbp_write(rt2x00dev, 77, 0x58); - else - rt2800_bbp_write(rt2x00dev, 77, 0x59); - } else { - rt2800_bbp_write(rt2x00dev, 69, 0x12); - rt2800_bbp_write(rt2x00dev, 73, 0x10); - } - rt2800_bbp_write(rt2x00dev, 70, 0x0a); if (rt2x00_rt(rt2x00dev, RT3070) || -- GitLab From 8d97be386415aa771bbe923072da773ff09ad997 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:34 +0200 Subject: [PATCH 0298/2900] rt2800: initialize BBP_R70 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 26feb99a0aa8..8ad20dbb2613 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3962,6 +3962,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x10); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3976,6 +3978,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x10); } + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -3985,6 +3989,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x10); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4004,6 +4010,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 76, 0x28); rt2800_bbp_write(rt2x00dev, 77, 0x58); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4026,6 +4034,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 76, 0x28); rt2800_bbp_write(rt2x00dev, 77, 0x59); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4035,6 +4045,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x10); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4046,6 +4058,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 69, 0x12); rt2800_bbp_write(rt2x00dev, 73, 0x10); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4065,6 +4079,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 76, 0x28); rt2800_bbp_write(rt2x00dev, 77, 0x59); + + rt2800_bbp_write(rt2x00dev, 70, 0x0a); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4183,8 +4199,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - rt2800_bbp_write(rt2x00dev, 70, 0x0a); - if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || -- GitLab From 43f535e2f998c617bbe1622240b2f3290f577d1e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:35 +0200 Subject: [PATCH 0299/2900] rt2800: initialize BBP_R74 - BBP_R80 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 56 +++++++++++++------------ 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8ad20dbb2613..508c9c4dedb4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3964,6 +3964,9 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 73, 0x10); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 78, 0x0e); + rt2800_bbp_write(rt2x00dev, 80, 0x08); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3980,6 +3983,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) } rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 81, 0x37); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -3991,6 +3996,10 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 73, 0x10); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4012,6 +4021,11 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 77, 0x58); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 74, 0x0b); + rt2800_bbp_write(rt2x00dev, 79, 0x18); + rt2800_bbp_write(rt2x00dev, 80, 0x09); + rt2800_bbp_write(rt2x00dev, 81, 0x33); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4036,6 +4050,10 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 77, 0x59); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 78, 0x0e); + rt2800_bbp_write(rt2x00dev, 80, 0x08); + rt2800_bbp_write(rt2x00dev, 81, 0x37); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4047,6 +4065,10 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 73, 0x10); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4060,6 +4082,10 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 73, 0x10); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4081,6 +4107,10 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 77, 0x59); rt2800_bbp_write(rt2x00dev, 70, 0x0a); + + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4199,32 +4229,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3070) || - rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090) || - rt2x00_rt(rt2x00dev, RT3390) || - rt2x00_rt(rt2x00dev, RT3572) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_bbp_write(rt2x00dev, 79, 0x13); - rt2800_bbp_write(rt2x00dev, 80, 0x05); - rt2800_bbp_write(rt2x00dev, 81, 0x33); - } else if (rt2800_is_305x_soc(rt2x00dev)) { - rt2800_bbp_write(rt2x00dev, 78, 0x0e); - rt2800_bbp_write(rt2x00dev, 80, 0x08); - } else if (rt2x00_rt(rt2x00dev, RT3290)) { - rt2800_bbp_write(rt2x00dev, 74, 0x0b); - rt2800_bbp_write(rt2x00dev, 79, 0x18); - rt2800_bbp_write(rt2x00dev, 80, 0x09); - rt2800_bbp_write(rt2x00dev, 81, 0x33); - } else if (rt2x00_rt(rt2x00dev, RT3352)) { - rt2800_bbp_write(rt2x00dev, 78, 0x0e); - rt2800_bbp_write(rt2x00dev, 80, 0x08); - rt2800_bbp_write(rt2x00dev, 81, 0x37); - } else { - rt2800_bbp_write(rt2x00dev, 81, 0x37); - } - rt2800_bbp_write(rt2x00dev, 82, 0x62); if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || -- GitLab From fa1e34243ff3fb1532ca3b817fd9129ee62d6d06 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:36 +0200 Subject: [PATCH 0300/2900] rt2800: initialize BBP_R82 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 508c9c4dedb4..aad340f5750e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3967,6 +3967,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3985,6 +3987,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 70, 0x0a); rt2800_bbp_write(rt2x00dev, 81, 0x37); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4000,6 +4004,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4026,6 +4032,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x18); rt2800_bbp_write(rt2x00dev, 80, 0x09); rt2800_bbp_write(rt2x00dev, 81, 0x33); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4054,6 +4062,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); rt2800_bbp_write(rt2x00dev, 81, 0x37); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4069,6 +4079,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4086,6 +4098,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4111,6 +4125,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 79, 0x13); rt2800_bbp_write(rt2x00dev, 80, 0x05); rt2800_bbp_write(rt2x00dev, 81, 0x33); + + rt2800_bbp_write(rt2x00dev, 82, 0x62); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4229,7 +4245,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - rt2800_bbp_write(rt2x00dev, 82, 0x62); if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) -- GitLab From 885f2414361709f53ed5566e66f3bd88c9ebe2b5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:37 +0200 Subject: [PATCH 0301/2900] rt2800: initialize BBP_R83 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index aad340f5750e..79a95a44e575 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3969,6 +3969,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 80, 0x08); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3989,6 +3991,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x37); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4006,6 +4010,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x33); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4034,6 +4040,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x33); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x7a); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4064,6 +4072,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x37); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4081,6 +4091,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x33); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4100,6 +4112,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x33); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x6a); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4127,6 +4141,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 81, 0x33); rt2800_bbp_write(rt2x00dev, 82, 0x62); + + rt2800_bbp_write(rt2x00dev, 83, 0x7a); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4245,13 +4261,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 83, 0x7a); - else - rt2800_bbp_write(rt2x00dev, 83, 0x6a); - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) rt2800_bbp_write(rt2x00dev, 84, 0x19); else if (rt2x00_rt(rt2x00dev, RT3290) || -- GitLab From 3c20a1229dce70b16f7e0f444d23f9b16e15a7e2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:38 +0200 Subject: [PATCH 0302/2900] rt2800: initialize BBP_R84 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 28 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 79a95a44e575..2f14ede9e959 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3971,6 +3971,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -3993,6 +3995,11 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) + rt2800_bbp_write(rt2x00dev, 84, 0x19); + else + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4012,6 +4019,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4042,6 +4051,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x7a); + + rt2800_bbp_write(rt2x00dev, 84, 0x9a); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4074,6 +4085,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4093,6 +4106,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4114,6 +4129,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x6a); + + rt2800_bbp_write(rt2x00dev, 84, 0x99); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4143,6 +4160,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 83, 0x7a); + + rt2800_bbp_write(rt2x00dev, 84, 0x9a); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4261,15 +4280,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) - rt2800_bbp_write(rt2x00dev, 84, 0x19); - else if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 84, 0x9a); - else - rt2800_bbp_write(rt2x00dev, 84, 0x99); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || -- GitLab From aef9f38b8d1d729935fab916b4581af669baa849 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:39 +0200 Subject: [PATCH 0303/2900] rt2800: initialize BBP_R86 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2f14ede9e959..dafb52b349fb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3973,6 +3973,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x6a); rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x00); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4000,6 +4002,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x19); else rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x00); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4021,6 +4025,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x6a); rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x00); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4053,6 +4059,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x7a); rt2800_bbp_write(rt2x00dev, 84, 0x9a); + + rt2800_bbp_write(rt2x00dev, 86, 0x38); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4087,6 +4095,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x6a); rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x38); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4108,6 +4118,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x6a); rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x00); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4131,6 +4143,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x6a); rt2800_bbp_write(rt2x00dev, 84, 0x99); + + rt2800_bbp_write(rt2x00dev, 86, 0x00); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4162,6 +4176,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 83, 0x7a); rt2800_bbp_write(rt2x00dev, 84, 0x9a); + + rt2800_bbp_write(rt2x00dev, 86, 0x38); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4280,14 +4296,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 86, 0x38); - else - rt2800_bbp_write(rt2x00dev, 86, 0x00); - if (rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 88, 0x90); -- GitLab From 9400fa8745d01e4e0e0ec893620800a96c6138ea Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:40 +0200 Subject: [PATCH 0304/2900] rt2800: initialize BBP_R88 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index dafb52b349fb..1f50bfbfbc25 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4097,6 +4097,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x38); + + rt2800_bbp_write(rt2x00dev, 88, 0x90); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4178,6 +4180,9 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x9a); rt2800_bbp_write(rt2x00dev, 86, 0x38); + + if (rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 88, 0x90); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4296,10 +4301,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 88, 0x90); - rt2800_bbp_write(rt2x00dev, 91, 0x04); if (rt2x00_rt(rt2x00dev, RT3290) || -- GitLab From 7af987420e9cb7d371adda02e880fcb9b9a6affd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:41 +0200 Subject: [PATCH 0305/2900] rt2800: initialize BBP_R91 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1f50bfbfbc25..c5a2ca25b07d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3975,6 +3975,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x00); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4004,6 +4006,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x00); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4027,6 +4031,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x00); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4061,6 +4067,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x9a); rt2800_bbp_write(rt2x00dev, 86, 0x38); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4099,6 +4107,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x38); rt2800_bbp_write(rt2x00dev, 88, 0x90); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4122,6 +4132,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x00); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4147,6 +4159,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 86, 0x00); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4183,6 +4197,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT5392)) rt2800_bbp_write(rt2x00dev, 88, 0x90); + + rt2800_bbp_write(rt2x00dev, 91, 0x04); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4301,8 +4317,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - rt2800_bbp_write(rt2x00dev, 91, 0x04); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || -- GitLab From b4e121d1d2a6a9fb59a900c755d6c1924334cf79 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:42 +0200 Subject: [PATCH 0306/2900] rt2800: initialize BBP_R92 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c5a2ca25b07d..354384726a6c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3977,6 +3977,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x00); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4008,6 +4010,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x00); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4033,6 +4037,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x00); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4069,6 +4075,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x38); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x02); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4109,6 +4117,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 88, 0x90); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x02); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4134,6 +4144,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x00); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4161,6 +4173,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 86, 0x00); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x00); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4199,6 +4213,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 88, 0x90); rt2800_bbp_write(rt2x00dev, 91, 0x04); + + rt2800_bbp_write(rt2x00dev, 92, 0x02); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4317,14 +4333,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 92, 0x02); - else - rt2800_bbp_write(rt2x00dev, 92, 0x00); - if (rt2x00_rt(rt2x00dev, RT5392)) { rt2800_bbp_write(rt2x00dev, 95, 0x9a); rt2800_bbp_write(rt2x00dev, 98, 0x12); -- GitLab From 90fed535614b1fab52f088b98a7dadb45a18d463 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:43 +0200 Subject: [PATCH 0307/2900] rt2800: move initialization of BBP_95 & BBP_98 to 53xx subroutine Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 354384726a6c..d985711df7e7 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4215,6 +4215,11 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x02); + + if (rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_write(rt2x00dev, 95, 0x9a); + rt2800_bbp_write(rt2x00dev, 98, 0x12); + } } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4333,11 +4338,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_bbp_write(rt2x00dev, 95, 0x9a); - rt2800_bbp_write(rt2x00dev, 98, 0x12); - } - if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || -- GitLab From 672d11889834d7f34c70d79831d23020aed9c7ad Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:44 +0200 Subject: [PATCH 0308/2900] rt2800: initialize BBP_R103 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 38 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d985711df7e7..291542f4c84f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3979,6 +3979,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4012,6 +4014,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); + + rt2800_bbp_write(rt2x00dev, 103, 0x00); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4039,6 +4043,13 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); + + if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || + rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || + rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E)) + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + else + rt2800_bbp_write(rt2x00dev, 103, 0x00); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4077,6 +4088,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x02); + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4119,6 +4132,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x02); + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4146,6 +4161,11 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); + + if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + else + rt2800_bbp_write(rt2x00dev, 103, 0x00); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4175,6 +4195,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 91, 0x04); rt2800_bbp_write(rt2x00dev, 92, 0x00); + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4220,6 +4242,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 95, 0x9a); rt2800_bbp_write(rt2x00dev, 98, 0x12); } + + rt2800_bbp_write(rt2x00dev, 103, 0xc0); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4338,20 +4362,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || - rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || - rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || - rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || - rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT3572) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392) || - rt2800_is_305x_soc(rt2x00dev)) - rt2800_bbp_write(rt2x00dev, 103, 0xc0); - else - rt2800_bbp_write(rt2x00dev, 103, 0x00); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT5390) || -- GitLab From 1ad4408a1ea766774a6d4e73ed6a23bcaf9d1d32 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:45 +0200 Subject: [PATCH 0309/2900] rt2800: initialize BBP_R104 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 291542f4c84f..238221372a0e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4090,6 +4090,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x02); rt2800_bbp_write(rt2x00dev, 103, 0xc0); + + rt2800_bbp_write(rt2x00dev, 104, 0x92); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4134,6 +4136,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x02); rt2800_bbp_write(rt2x00dev, 103, 0xc0); + + rt2800_bbp_write(rt2x00dev, 104, 0x92); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4244,6 +4248,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) } rt2800_bbp_write(rt2x00dev, 103, 0xc0); + + rt2800_bbp_write(rt2x00dev, 104, 0x92); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4362,12 +4368,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT3352) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 104, 0x92); - if (rt2800_is_305x_soc(rt2x00dev)) rt2800_bbp_write(rt2x00dev, 105, 0x01); else if (rt2x00_rt(rt2x00dev, RT3290)) -- GitLab From 49d611186a2dfdf8c10e090450a570ba929bd393 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:46 +0200 Subject: [PATCH 0310/2900] rt2800: initialize BBP_R105 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 28 ++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 238221372a0e..0970e40a7cfb 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3981,6 +3981,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x00); rt2800_bbp_write(rt2x00dev, 103, 0xc0); + + rt2800_bbp_write(rt2x00dev, 105, 0x01); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4016,6 +4018,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x00); rt2800_bbp_write(rt2x00dev, 103, 0x00); + + rt2800_bbp_write(rt2x00dev, 105, 0x05); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4050,6 +4054,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); + + rt2800_bbp_write(rt2x00dev, 105, 0x05); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4092,6 +4098,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); rt2800_bbp_write(rt2x00dev, 104, 0x92); + + rt2800_bbp_write(rt2x00dev, 105, 0x1c); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4138,6 +4146,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); rt2800_bbp_write(rt2x00dev, 104, 0x92); + + rt2800_bbp_write(rt2x00dev, 105, 0x34); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4170,6 +4180,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); else rt2800_bbp_write(rt2x00dev, 103, 0x00); + + rt2800_bbp_write(rt2x00dev, 105, 0x05); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4201,6 +4213,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 92, 0x00); rt2800_bbp_write(rt2x00dev, 103, 0xc0); + + rt2800_bbp_write(rt2x00dev, 105, 0x05); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4250,6 +4264,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); rt2800_bbp_write(rt2x00dev, 104, 0x92); + + rt2800_bbp_write(rt2x00dev, 105, 0x3c); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4368,18 +4384,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2800_is_305x_soc(rt2x00dev)) - rt2800_bbp_write(rt2x00dev, 105, 0x01); - else if (rt2x00_rt(rt2x00dev, RT3290)) - rt2800_bbp_write(rt2x00dev, 105, 0x1c); - else if (rt2x00_rt(rt2x00dev, RT3352)) - rt2800_bbp_write(rt2x00dev, 105, 0x34); - else if (rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 105, 0x3c); - else - rt2800_bbp_write(rt2x00dev, 105, 0x05); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390)) rt2800_bbp_write(rt2x00dev, 106, 0x03); -- GitLab From f867085edeab37d5cce62e266615e540cb85ae43 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:47 +0200 Subject: [PATCH 0311/2900] rt2800: initialize BBP_R106 on all subroutines (except 5592) Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0970e40a7cfb..eb44ba80c661 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3983,6 +3983,8 @@ static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); rt2800_bbp_write(rt2x00dev, 105, 0x01); + + rt2800_bbp_write(rt2x00dev, 106, 0x35); } static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) @@ -4020,6 +4022,8 @@ static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); + + rt2800_bbp_write(rt2x00dev, 106, 0x35); } static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) @@ -4056,6 +4060,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); + + rt2800_bbp_write(rt2x00dev, 106, 0x35); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4100,6 +4106,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 104, 0x92); rt2800_bbp_write(rt2x00dev, 105, 0x1c); + + rt2800_bbp_write(rt2x00dev, 106, 0x03); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4148,6 +4156,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 104, 0x92); rt2800_bbp_write(rt2x00dev, 105, 0x34); + + rt2800_bbp_write(rt2x00dev, 106, 0x05); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4182,6 +4192,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); + + rt2800_bbp_write(rt2x00dev, 106, 0x35); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4215,6 +4227,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0xc0); rt2800_bbp_write(rt2x00dev, 105, 0x05); + + rt2800_bbp_write(rt2x00dev, 106, 0x35); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4266,6 +4280,13 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 104, 0x92); rt2800_bbp_write(rt2x00dev, 105, 0x3c); + + if (rt2x00_rt(rt2x00dev, RT5390)) + rt2800_bbp_write(rt2x00dev, 106, 0x03); + else if (rt2x00_rt(rt2x00dev, RT5392)) + rt2800_bbp_write(rt2x00dev, 106, 0x12); + else + WARN_ON(1); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4384,16 +4405,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT5390)) - rt2800_bbp_write(rt2x00dev, 106, 0x03); - else if (rt2x00_rt(rt2x00dev, RT3352)) - rt2800_bbp_write(rt2x00dev, 106, 0x05); - else if (rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 106, 0x12); - else - rt2800_bbp_write(rt2x00dev, 106, 0x35); - if (rt2x00_rt(rt2x00dev, RT3352)) rt2800_bbp_write(rt2x00dev, 120, 0x50); -- GitLab From 46b90d3216af851fe8c1b97a2cac95ee129443a9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:48 +0200 Subject: [PATCH 0312/2900] rt2800: initialize BBP_R120 on 3352 subroutine Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index eb44ba80c661..b860abcfe136 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4158,6 +4158,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x34); rt2800_bbp_write(rt2x00dev, 106, 0x05); + + rt2800_bbp_write(rt2x00dev, 120, 0x50); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4405,9 +4407,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3352)) - rt2800_bbp_write(rt2x00dev, 120, 0x50); - if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) -- GitLab From f2b6777cb631c6d8ec4f8479e34eaec1133659d4 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:49 +0200 Subject: [PATCH 0313/2900] rt2800: initialize BBP_R128 on proper subroutines Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b860abcfe136..0d2c46f42227 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4108,6 +4108,8 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x1c); rt2800_bbp_write(rt2x00dev, 106, 0x03); + + rt2800_bbp_write(rt2x00dev, 128, 0x12); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4289,6 +4291,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x12); else WARN_ON(1); + + rt2800_bbp_write(rt2x00dev, 128, 0x12); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4407,11 +4411,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) - rt2800_bbp_write(rt2x00dev, 128, 0x12); - if (rt2x00_rt(rt2x00dev, RT5392)) { rt2800_bbp_write(rt2x00dev, 134, 0xd0); rt2800_bbp_write(rt2x00dev, 135, 0xf6); -- GitLab From 7291714099627183f0f439de68c9111e1c26c50e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:50 +0200 Subject: [PATCH 0314/2900] rt2800: initialize BBP_R134 & BBP_R135 on 53xx subroutine Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 0d2c46f42227..f54d04e60729 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4293,6 +4293,11 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) WARN_ON(1); rt2800_bbp_write(rt2x00dev, 128, 0x12); + + if (rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_bbp_write(rt2x00dev, 134, 0xd0); + rt2800_bbp_write(rt2x00dev, 135, 0xf6); + } } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4411,11 +4416,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_bbp_write(rt2x00dev, 134, 0xd0); - rt2800_bbp_write(rt2x00dev, 135, 0xf6); - } - if (rt2x00_rt(rt2x00dev, RT3352)) rt2800_bbp_write(rt2x00dev, 137, 0x0f); -- GitLab From b7feb9ba64c53f93412b61351e00663bb24959ef Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:51 +0200 Subject: [PATCH 0315/2900] rt2800: initialize BBP_R104 on 3352 subroutine Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index f54d04e60729..abaa685b25da 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4162,6 +4162,8 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x05); rt2800_bbp_write(rt2x00dev, 120, 0x50); + + rt2800_bbp_write(rt2x00dev, 137, 0x0f); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4416,9 +4418,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3352)) - rt2800_bbp_write(rt2x00dev, 137, 0x0f); - if (rt2x00_rt(rt2x00dev, RT3071) || rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3390) || -- GitLab From 5df1ff3a22ebfd2749092227d7d1ea4599488c4e Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:52 +0200 Subject: [PATCH 0316/2900] rt2800: initialize BBP_R108 on proper subroutines Create helper function and move initialization to subroutines. Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 41 +++++++++++++++---------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index abaa685b25da..d0d65dd23746 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3953,6 +3953,20 @@ static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x35); } +static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev) +{ + u16 eeprom; + u8 value; + + rt2800_bbp_read(rt2x00dev, 138, &value); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) + value |= 0x20; + if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) + value &= ~0x02; + rt2800_bbp_write(rt2x00dev, 138, value); +} + static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) { rt2800_bbp_write(rt2x00dev, 31, 0x08); @@ -4062,6 +4076,10 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); + + if (rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3090)) + rt2800_disable_unused_dac_adc(rt2x00dev); } static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) @@ -4200,6 +4218,8 @@ static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); + + rt2800_disable_unused_dac_adc(rt2x00dev); } static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) @@ -4235,6 +4255,8 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 105, 0x05); rt2800_bbp_write(rt2x00dev, 106, 0x35); + + rt2800_disable_unused_dac_adc(rt2x00dev); } static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) @@ -4300,6 +4322,8 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 134, 0xd0); rt2800_bbp_write(rt2x00dev, 135, 0xf6); } + + rt2800_disable_unused_dac_adc(rt2x00dev); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4418,23 +4442,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3071) || - rt2x00_rt(rt2x00dev, RT3090) || - rt2x00_rt(rt2x00dev, RT3390) || - rt2x00_rt(rt2x00dev, RT3572) || - rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_bbp_read(rt2x00dev, 138, &value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) - value |= 0x20; - if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) - value &= ~0x02; - - rt2800_bbp_write(rt2x00dev, 138, value); - } - if (rt2x00_rt(rt2x00dev, RT3290)) { rt2800_bbp_write(rt2x00dev, 67, 0x24); rt2800_bbp_write(rt2x00dev, 143, 0x04); -- GitLab From c2da5273aefef4dc1a6d114ddc4eb807ea2bea3a Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:53 +0200 Subject: [PATCH 0317/2900] rt2800: move 3352 specific bbp initialization Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 42 ++++++++++++------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d0d65dd23746..2d00fd88075c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4182,6 +4182,26 @@ static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 120, 0x50); rt2800_bbp_write(rt2x00dev, 137, 0x0f); + + rt2800_bbp_write(rt2x00dev, 163, 0xbd); + /* Set ITxBF timeout to 0x9c40=1000msec */ + rt2800_bbp_write(rt2x00dev, 179, 0x02); + rt2800_bbp_write(rt2x00dev, 180, 0x00); + rt2800_bbp_write(rt2x00dev, 182, 0x40); + rt2800_bbp_write(rt2x00dev, 180, 0x01); + rt2800_bbp_write(rt2x00dev, 182, 0x9c); + rt2800_bbp_write(rt2x00dev, 179, 0x00); + /* Reprogram the inband interface to put right values in RXWI */ + rt2800_bbp_write(rt2x00dev, 142, 0x04); + rt2800_bbp_write(rt2x00dev, 143, 0x3b); + rt2800_bbp_write(rt2x00dev, 142, 0x06); + rt2800_bbp_write(rt2x00dev, 143, 0xa0); + rt2800_bbp_write(rt2x00dev, 142, 0x07); + rt2800_bbp_write(rt2x00dev, 143, 0xa1); + rt2800_bbp_write(rt2x00dev, 142, 0x08); + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + + rt2800_bbp_write(rt2x00dev, 148, 0xc8); } static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) @@ -4465,28 +4485,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 3, value); } - if (rt2x00_rt(rt2x00dev, RT3352)) { - rt2800_bbp_write(rt2x00dev, 163, 0xbd); - /* Set ITxBF timeout to 0x9c40=1000msec */ - rt2800_bbp_write(rt2x00dev, 179, 0x02); - rt2800_bbp_write(rt2x00dev, 180, 0x00); - rt2800_bbp_write(rt2x00dev, 182, 0x40); - rt2800_bbp_write(rt2x00dev, 180, 0x01); - rt2800_bbp_write(rt2x00dev, 182, 0x9c); - rt2800_bbp_write(rt2x00dev, 179, 0x00); - /* Reprogram the inband interface to put right values in RXWI */ - rt2800_bbp_write(rt2x00dev, 142, 0x04); - rt2800_bbp_write(rt2x00dev, 143, 0x3b); - rt2800_bbp_write(rt2x00dev, 142, 0x06); - rt2800_bbp_write(rt2x00dev, 143, 0xa0); - rt2800_bbp_write(rt2x00dev, 142, 0x07); - rt2800_bbp_write(rt2x00dev, 143, 0xa1); - rt2800_bbp_write(rt2x00dev, 142, 0x08); - rt2800_bbp_write(rt2x00dev, 143, 0xa2); - - rt2800_bbp_write(rt2x00dev, 148, 0xc8); - } - if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) { int ant, div_mode; -- GitLab From 6addb24eefd36ea4d69dfa6587300943bb037b5d Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:54 +0200 Subject: [PATCH 0318/2900] rt2800: move 3290 specific bbp initialization Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 46 ++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2d00fd88075c..527c11478d9d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4084,6 +4084,8 @@ static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) { + u8 value; + rt2800_bbp4_mac_if_ctrl(rt2x00dev); rt2800_bbp_write(rt2x00dev, 31, 0x08); @@ -4128,6 +4130,27 @@ static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 106, 0x03); rt2800_bbp_write(rt2x00dev, 128, 0x12); + + rt2800_bbp_write(rt2x00dev, 67, 0x24); + rt2800_bbp_write(rt2x00dev, 143, 0x04); + rt2800_bbp_write(rt2x00dev, 142, 0x99); + rt2800_bbp_write(rt2x00dev, 150, 0x30); + rt2800_bbp_write(rt2x00dev, 151, 0x2e); + rt2800_bbp_write(rt2x00dev, 152, 0x20); + rt2800_bbp_write(rt2x00dev, 153, 0x34); + rt2800_bbp_write(rt2x00dev, 154, 0x40); + rt2800_bbp_write(rt2x00dev, 155, 0x3b); + rt2800_bbp_write(rt2x00dev, 253, 0x04); + + rt2800_bbp_read(rt2x00dev, 47, &value); + rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1); + rt2800_bbp_write(rt2x00dev, 47, value); + + /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */ + rt2800_bbp_read(rt2x00dev, 3, &value); + rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1); + rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1); + rt2800_bbp_write(rt2x00dev, 3, value); } static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) @@ -4462,29 +4485,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT3290)) { - rt2800_bbp_write(rt2x00dev, 67, 0x24); - rt2800_bbp_write(rt2x00dev, 143, 0x04); - rt2800_bbp_write(rt2x00dev, 142, 0x99); - rt2800_bbp_write(rt2x00dev, 150, 0x30); - rt2800_bbp_write(rt2x00dev, 151, 0x2e); - rt2800_bbp_write(rt2x00dev, 152, 0x20); - rt2800_bbp_write(rt2x00dev, 153, 0x34); - rt2800_bbp_write(rt2x00dev, 154, 0x40); - rt2800_bbp_write(rt2x00dev, 155, 0x3b); - rt2800_bbp_write(rt2x00dev, 253, 0x04); - - rt2800_bbp_read(rt2x00dev, 47, &value); - rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1); - rt2800_bbp_write(rt2x00dev, 47, value); - - /* Use 5-bit ADC for Acquisition and 8-bit ADC for data */ - rt2800_bbp_read(rt2x00dev, 3, &value); - rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1); - rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1); - rt2800_bbp_write(rt2x00dev, 3, value); - } - if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) { int ant, div_mode; -- GitLab From 32ef8f499262309478f0225f5fc33910e1c8e199 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Sat, 18 May 2013 14:03:55 +0200 Subject: [PATCH 0319/2900] rt2800: move 53xx specific bbp initialization Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 83 ++++++++++++------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 527c11478d9d..ead3a3e746a2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4304,6 +4304,10 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) { + int ant, div_mode; + u16 eeprom; + u8 value; + rt2800_bbp4_mac_if_ctrl(rt2x00dev); rt2800_bbp_write(rt2x00dev, 31, 0x08); @@ -4367,6 +4371,43 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) } rt2800_disable_unused_dac_adc(rt2x00dev); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + div_mode = rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_ANT_DIVERSITY); + ant = (div_mode == 3) ? 1 : 0; + + /* check if this is a Bluetooth combo card */ + if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { + u32 reg; + + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); + rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0); + rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0); + rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0); + if (ant == 0) + rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1); + else if (ant == 1) + rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1); + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + } + + /* This chip has hardware antenna diversity*/ + if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { + rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */ + rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */ + rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */ + } + + rt2800_bbp_read(rt2x00dev, 152, &value); + if (ant == 0) + rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); + else + rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); + rt2800_bbp_write(rt2x00dev, 152, value); + + rt2800_init_freq_calibration(rt2x00dev); } static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) @@ -4485,48 +4526,6 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) return; } - if (rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392)) { - int ant, div_mode; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); - div_mode = rt2x00_get_field16(eeprom, - EEPROM_NIC_CONF1_ANT_DIVERSITY); - ant = (div_mode == 3) ? 1 : 0; - - /* check if this is a Bluetooth combo card */ - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { - u32 reg; - - rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); - rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); - rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0); - rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0); - rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0); - if (ant == 0) - rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1); - else if (ant == 1) - rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1); - rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); - } - - /* This chip has hardware antenna diversity*/ - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { - rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */ - rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */ - rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */ - } - - rt2800_bbp_read(rt2x00dev, 152, &value); - if (ant == 0) - rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); - else - rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); - rt2800_bbp_write(rt2x00dev, 152, value); - - rt2800_init_freq_calibration(rt2x00dev); - } - for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); -- GitLab From 110dea0008c40a20f1ce280b636f87fff58a7403 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 23 May 2013 17:10:43 +0800 Subject: [PATCH 0320/2900] wil6210: use kfree_skb() instead of kfree() Use kfree_skb() instead of kfree() to free sk_buff. Introduced by commit e270045b569cc7030abd29857f3a4e7906524ec0 (wil6210: Sanity check for reported DMA length) Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 082f76bdd5e5..00dffeda983e 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -369,7 +369,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, if (dmalen > sz) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); - kfree(skb); + kfree_skb(skb); return NULL; } skb_trim(skb, dmalen); -- GitLab From bbf71a8f35cf52e97ba129401f82ccefd249c757 Mon Sep 17 00:00:00 2001 From: Nishant Sarmukadam Date: Fri, 24 May 2013 14:42:25 +0530 Subject: [PATCH 0321/2900] mwl8k: Fix the firmware hang issue for 8764 The firmware hang issue is not seen very often, though it is still seen sometimes (once in 12 hours in local tests). The changes in the driver ,to interrupt the firmware, are needed when we detect that firmware is stuck and when the host queues are full and we begin to drop packets. This is to ensure that the firmware does not miss any PPA_RDY interrupts to cause the firmware restart dont miss PPA_READY interrupt for SC2 Signed-off-by: Nishant Sarmukadam Signed-off-by: Yogesh Ashok Powar Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6820fce4016b..a3707fd4ef62 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1548,7 +1548,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) if (!priv->pending_tx_pkts) return 0; - retry = 0; + retry = 1; rc = 0; spin_lock_bh(&priv->tx_lock); @@ -1572,13 +1572,19 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) spin_lock_bh(&priv->tx_lock); - if (timeout) { + if (timeout || !priv->pending_tx_pkts) { WARN_ON(priv->pending_tx_pkts); if (retry) wiphy_notice(hw->wiphy, "tx rings drained\n"); break; } + if (retry) { + mwl8k_tx_start(priv); + retry = 0; + continue; + } + if (priv->pending_tx_pkts < oldcount) { wiphy_notice(hw->wiphy, "waiting for tx rings to drain (%d -> %d pkts)\n", @@ -2055,6 +2061,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, mwl8k_remove_stream(hw, stream); spin_unlock(&priv->stream_lock); } + mwl8k_tx_start(priv); spin_unlock_bh(&priv->tx_lock); pci_unmap_single(priv->pdev, dma, skb->len, PCI_DMA_TODEVICE); -- GitLab From 5e4b6f5698421d94226cc2f80eae6d613c9acef8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 16 May 2013 20:11:08 +0300 Subject: [PATCH 0322/2900] cfg80211: Allow TDLS peer AID to be configured for VHT VHT uses peer AID in the PARTIAL_AID field in TDLS frames. The current design for TDLS is to first add a dummy STA entry before completing TDLS Setup and then update information on this STA entry based on what was received from the peer during the setup exchange. In theory, this could use NL80211_ATTR_STA_AID to set the peer AID just like this is used in AP mode to set the AID of an association station. However, existing cfg80211 validation rules prevent this attribute from being used with set_station operation. To avoid interoperability issues between different kernel and user space version combinations, introduce a new nl80211 attribute for the purpose of setting TDLS peer AID. This attribute can be used in both the new_station and set_station operations. It is not supposed to be allowed to change the AID value during the lifetime of the STA entry, but that validation is left for drivers to do in the change_station callback. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 7 +++++++ net/wireless/nl80211.c | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 06320713e9c9..32b060ea5266 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1431,6 +1431,11 @@ enum nl80211_commands { * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which * the connection should have increased reliability (u16). * + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1729,6 +1734,8 @@ enum nl80211_attrs { NL80211_ATTR_CRIT_PROT_ID, NL80211_ATTR_MAX_CRIT_PROT_DURATION, + NL80211_ATTR_PEER_AID, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5f10f7acfa06..14276af7964b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -378,6 +378,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_MDID] = { .type = NLA_U16 }, [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -3872,6 +3873,8 @@ static int nl80211_set_station_tdls(struct genl_info *info, struct station_parameters *params) { /* Dummy STA entry gets updated once the peer capabilities are known */ + if (info->attrs[NL80211_ATTR_PEER_AID]) + params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) params->ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); @@ -4012,7 +4015,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) return -EINVAL; - if (!info->attrs[NL80211_ATTR_STA_AID]) + if (!info->attrs[NL80211_ATTR_STA_AID] && + !info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); @@ -4023,7 +4027,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (info->attrs[NL80211_ATTR_STA_AID]) + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + else + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); if (!params.aid || params.aid > IEEE80211_MAX_AID) return -EINVAL; -- GitLab From d4a5a48976d12ab340ed34605b5f5049b123d868 Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Mon, 13 May 2013 17:08:04 -0700 Subject: [PATCH 0323/2900] mac80211: Move mesh estab_plinks outside mesh_stats debug group As estab_plinks is not a statistics member, don't show its debug information along with other mesh stat members Signed-off-by: Ashok Nagarajan Signed-off-by: Johannes Berg --- net/mac80211/debugfs_netdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 14abcf44f974..f83074fe6670 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -471,6 +471,8 @@ __IEEE80211_IF_FILE_W(tsf); IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); #ifdef CONFIG_MAC80211_MESH +IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC); + /* Mesh stats attributes */ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); @@ -480,7 +482,6 @@ IEEE80211_IF_FILE(dropped_frames_congestion, u.mesh.mshstats.dropped_frames_congestion, DEC); IEEE80211_IF_FILE(dropped_frames_no_route, u.mesh.mshstats.dropped_frames_no_route, DEC); -IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC); /* Mesh parameters */ IEEE80211_IF_FILE(dot11MeshMaxRetries, @@ -583,6 +584,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) static void add_mesh_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD_MODE(tsf, 0600); + DEBUGFS_ADD_MODE(estab_plinks, 0400); } static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) @@ -598,7 +600,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) MESHSTATS_ADD(dropped_frames_ttl); MESHSTATS_ADD(dropped_frames_no_route); MESHSTATS_ADD(dropped_frames_congestion); - MESHSTATS_ADD(estab_plinks); #undef MESHSTATS_ADD } -- GitLab From b422c6cd7e93bb613030f14d7d8a0cc73f115629 Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Fri, 10 May 2013 17:50:51 -0700 Subject: [PATCH 0324/2900] {cfg,mac}80211: move mandatory rates calculation to cfg80211 Move mandatory rates calculation to cfg80211, shared with non mac80211 drivers. Signed-off-by: Ashok Nagarajan [extend documentation] Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 9 +++++++++ net/mac80211/ibss.c | 10 +++++++--- net/mac80211/ieee80211_i.h | 3 --- net/mac80211/mesh.c | 5 +++-- net/mac80211/util.c | 26 -------------------------- net/wireless/util.c | 23 +++++++++++++++++++++++ 6 files changed, 42 insertions(+), 34 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 32a2f1b20861..58f6302da145 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3005,6 +3005,15 @@ struct ieee80211_rate * ieee80211_get_response_rate(struct ieee80211_supported_band *sband, u32 basic_rates, int bitrate); +/** + * ieee80211_mandatory_rates - get mandatory rates for a given band + * @sband: the band to look for rates in + * + * This function returns a bitmap of the mandatory rates for the given + * band, bits are set according to the rate position in the bitrates array. + */ +u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband); + /* * Radiotap parsing functions -- for controlled injection support * diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 170f9a7fa319..956ba6316da5 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -341,6 +341,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_supported_band *sband; int band; /* @@ -380,8 +381,9 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, sta->last_rx = jiffies; /* make sure mandatory rates are always added */ + sband = local->hw.wiphy->bands[band]; sta->sta.supp_rates[band] = supp_rates | - ieee80211_mandatory_rates(local, band); + ieee80211_mandatory_rates(sband); return ieee80211_ibss_finish_sta(sta, auth); } @@ -492,7 +494,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, prev_rates = sta->sta.supp_rates[band]; /* make sure mandatory rates are always added */ sta->sta.supp_rates[band] = supp_rates | - ieee80211_mandatory_rates(local, band); + ieee80211_mandatory_rates(sband); if (sta->sta.supp_rates[band] != prev_rates) { ibss_dbg(sdata, @@ -624,6 +626,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_supported_band *sband; int band; /* @@ -658,8 +661,9 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, sta->last_rx = jiffies; /* make sure mandatory rates are always added */ + sband = local->hw.wiphy->bands[band]; sta->sta.supp_rates[band] = supp_rates | - ieee80211_mandatory_rates(local, band); + ieee80211_mandatory_rates(sband); spin_lock(&ifibss->incomplete_lock); list_add(&sta->list, &ifibss->incomplete_stations); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 158e6eb188d3..b7cbd4ebf0e0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1505,9 +1505,6 @@ static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); } -u32 ieee80211_mandatory_rates(struct ieee80211_local *local, - enum ieee80211_band band); - void ieee80211_dynamic_ps_enable_work(struct work_struct *work); void ieee80211_dynamic_ps_disable_work(struct work_struct *work); void ieee80211_dynamic_ps_timer(unsigned long data); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c13db9ad394b..c14bb816c6a3 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -741,6 +741,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT; enum ieee80211_band band = ieee80211_get_sdata_band(sdata); + struct ieee80211_supported_band *sband = + sdata->local->hw.wiphy->bands[band]; local->fif_other_bss++; /* mesh ifaces must set allmulti to forward mcast traffic */ @@ -758,8 +760,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.ht_operation_mode = ifmsh->mshcfg.ht_opmode; sdata->vif.bss_conf.enable_beacon = true; - sdata->vif.bss_conf.basic_rates = - ieee80211_mandatory_rates(local, band); + sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband); changed |= ieee80211_mps_local_status_update(sdata); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f87fa468b1f..707953fd8324 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1072,32 +1072,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, ieee80211_set_wmm_default(sdata, true); } -u32 ieee80211_mandatory_rates(struct ieee80211_local *local, - enum ieee80211_band band) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_rate *bitrates; - u32 mandatory_rates; - enum ieee80211_rate_flags mandatory_flag; - int i; - - sband = local->hw.wiphy->bands[band]; - if (WARN_ON(!sband)) - return 1; - - if (band == IEEE80211_BAND_2GHZ) - mandatory_flag = IEEE80211_RATE_MANDATORY_B; - else - mandatory_flag = IEEE80211_RATE_MANDATORY_A; - - bitrates = sband->bitrates; - mandatory_rates = 0; - for (i = 0; i < sband->n_bitrates; i++) - if (bitrates[i].flags & mandatory_flag) - mandatory_rates |= BIT(i); - return mandatory_rates; -} - void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u16 status, const u8 *extra, size_t extra_len, const u8 *da, diff --git a/net/wireless/util.c b/net/wireless/util.c index b11052be09be..0962f107f57f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -33,6 +33,29 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, } EXPORT_SYMBOL(ieee80211_get_response_rate); +u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) +{ + struct ieee80211_rate *bitrates; + u32 mandatory_rates = 0; + enum ieee80211_rate_flags mandatory_flag; + int i; + + if (WARN_ON(!sband)) + return 1; + + if (sband->band == IEEE80211_BAND_2GHZ) + mandatory_flag = IEEE80211_RATE_MANDATORY_B; + else + mandatory_flag = IEEE80211_RATE_MANDATORY_A; + + bitrates = sband->bitrates; + for (i = 0; i < sband->n_bitrates; i++) + if (bitrates[i].flags & mandatory_flag) + mandatory_rates |= BIT(i); + return mandatory_rates; +} +EXPORT_SYMBOL(ieee80211_mandatory_rates); + int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) { /* see 802.11 17.3.8.3.2 and Annex J -- GitLab From 9f419f3851041e0c8170629f0639813dbfc79d5e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 May 2013 21:34:22 +0200 Subject: [PATCH 0325/2900] cfg80211: move cfg80211_get_dev_from_ifindex under wext The function is only used and needed by the wext code for scanning, so move it there. Signed-off-by: Johannes Berg --- net/wireless/core.c | 21 --------------------- net/wireless/core.h | 4 ---- net/wireless/scan.c | 21 +++++++++++++++++++++ 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 58e69d691601..cc49cf11c7a7 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -90,27 +90,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) return &rdev->wiphy; } -struct cfg80211_registered_device * -cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) -{ - struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); - struct net_device *dev; - - mutex_lock(&cfg80211_mutex); - dev = dev_get_by_index(net, ifindex); - if (!dev) - goto out; - if (dev->ieee80211_ptr) { - rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); - mutex_lock(&rdev->mtx); - } else - rdev = ERR_PTR(-ENODEV); - dev_put(dev); - out: - mutex_unlock(&cfg80211_mutex); - return rdev; -} - /* requires cfg80211_mutex to be held */ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname) diff --git a/net/wireless/core.h b/net/wireless/core.h index fd35dae547c4..95b29075a9c8 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -164,10 +164,6 @@ int get_wiphy_idx(struct wiphy *wiphy); /* requires cfg80211_rdev_mutex to be held! */ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); -/* identical to cfg80211_get_dev_from_info but only operate on ifindex */ -extern struct cfg80211_registered_device * -cfg80211_get_dev_from_ifindex(struct net *net, int ifindex); - int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, struct net *net); diff --git a/net/wireless/scan.c b/net/wireless/scan.c index fd99ea495b7e..2ce44a712f13 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1040,6 +1040,27 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) EXPORT_SYMBOL(cfg80211_unlink_bss); #ifdef CONFIG_CFG80211_WEXT +static struct cfg80211_registered_device * +cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) +{ + struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); + struct net_device *dev; + + mutex_lock(&cfg80211_mutex); + dev = dev_get_by_index(net, ifindex); + if (!dev) + goto out; + if (dev->ieee80211_ptr) { + rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); + mutex_lock(&rdev->mtx); + } else + rdev = ERR_PTR(-ENODEV); + dev_put(dev); + out: + mutex_unlock(&cfg80211_mutex); + return rdev; +} + int cfg80211_wext_siwscan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -- GitLab From 73810b77def898b43a97638478692922b7f820eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 May 2013 21:49:02 +0200 Subject: [PATCH 0326/2900] cfg80211: use atomic_t for wiphy counter There's no need to lock, we can just use an atomic_t. Signed-off-by: Johannes Berg --- net/wireless/core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index cc49cf11c7a7..9416b8f55f50 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -289,7 +289,7 @@ static void cfg80211_event_work(struct work_struct *work) struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) { - static int wiphy_counter; + static atomic_t wiphy_counter = ATOMIC_INIT(0); struct cfg80211_registered_device *rdev; int alloc_size; @@ -311,20 +311,15 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) rdev->ops = ops; - mutex_lock(&cfg80211_mutex); - - rdev->wiphy_idx = wiphy_counter++; + rdev->wiphy_idx = atomic_inc_return(&wiphy_counter); if (unlikely(rdev->wiphy_idx < 0)) { - wiphy_counter--; - mutex_unlock(&cfg80211_mutex); /* ugh, wrapped! */ + atomic_dec(&wiphy_counter); kfree(rdev); return NULL; } - mutex_unlock(&cfg80211_mutex); - /* give it a proper name */ dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); -- GitLab From 5fe231e873729fa2f57cdc417d5c1f80871e2d7d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 8 May 2013 21:45:15 +0200 Subject: [PATCH 0327/2900] cfg80211: vastly simplify locking Virtually all code paths in cfg80211 already (need to) hold the RTNL. As such, there's little point in having another four mutexes for various parts of the code, they just cause lock ordering issues (and much of the time, the RTNL and a few of the others need thus be held.) Simplify all this by getting rid of the extra four mutexes and just use the RTNL throughout. Only a few code changes were needed to do this and we can get rid of a work struct for bonus points. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 5 +- net/wireless/core.c | 166 +++++++--------------------------- net/wireless/core.h | 32 +------ net/wireless/debugfs.c | 4 +- net/wireless/ibss.c | 10 +-- net/wireless/mesh.c | 2 - net/wireless/mlme.c | 12 +-- net/wireless/nl80211.c | 178 ++++++++----------------------------- net/wireless/reg.c | 36 +++----- net/wireless/scan.c | 42 ++++----- net/wireless/sme.c | 26 +----- net/wireless/util.c | 11 --- net/wireless/wext-compat.c | 22 +---- net/wireless/wext-sme.c | 18 ---- 14 files changed, 117 insertions(+), 447 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 58f6302da145..5430f70c63b3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1257,6 +1257,7 @@ struct cfg80211_ssid { * @scan_start: time (in jiffies) when the scan started * @wdev: the wireless device to scan for * @aborted: (internal) scan request was notified as aborted + * @notified: (internal) scan request was notified as done or aborted * @no_cck: used to send probe requests at non CCK rate in 2GHz band */ struct cfg80211_scan_request { @@ -1274,7 +1275,7 @@ struct cfg80211_scan_request { /* internal */ struct wiphy *wiphy; unsigned long scan_start; - bool aborted; + bool aborted, notified; bool no_cck; /* keep last */ @@ -2874,8 +2875,6 @@ struct wireless_dev { struct mutex mtx; - struct work_struct cleanup_work; - bool use_4addr, p2p_started; u8 address[ETH_ALEN] __aligned(sizeof(u16)); diff --git a/net/wireless/core.c b/net/wireless/core.c index 9416b8f55f50..5fc642d4071b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -36,12 +36,10 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); -/* RCU-protected (and cfg80211_mutex for writers) */ +/* RCU-protected (and RTNL for writers) */ LIST_HEAD(cfg80211_rdev_list); int cfg80211_rdev_list_generation; -DEFINE_MUTEX(cfg80211_mutex); - /* for debugfs */ static struct dentry *ieee80211_debugfs_dir; @@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, "Disable 40MHz support in the 2.4GHz band"); -/* requires cfg80211_mutex to be held! */ struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) { struct cfg80211_registered_device *result = NULL, *rdev; - assert_cfg80211_lock(); + ASSERT_RTNL(); list_for_each_entry(rdev, &cfg80211_rdev_list, list) { if (rdev->wiphy_idx == wiphy_idx) { @@ -77,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy) return rdev->wiphy_idx; } -/* requires cfg80211_rdev_mutex to be held! */ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) { struct cfg80211_registered_device *rdev; - assert_cfg80211_lock(); + ASSERT_RTNL(); rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); if (!rdev) @@ -90,14 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) return &rdev->wiphy; } -/* requires cfg80211_mutex to be held */ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname) { struct cfg80211_registered_device *rdev2; int wiphy_idx, taken = -1, result, digits; - assert_cfg80211_lock(); + ASSERT_RTNL(); /* prohibit calling the thing phy%d when %d is not its number */ sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); @@ -195,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev) { - lockdep_assert_held(&rdev->devlist_mtx); - lockdep_assert_held(&rdev->sched_scan_mtx); + ASSERT_RTNL(); if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) return; @@ -235,8 +229,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) rtnl_lock(); - /* read-only iteration need not hold the devlist_mtx */ - list_for_each_entry(wdev, &rdev->wdev_list, list) { if (wdev->netdev) { dev_close(wdev->netdev); @@ -245,12 +237,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) /* otherwise, check iftype */ switch (wdev->iftype) { case NL80211_IFTYPE_P2P_DEVICE: - /* but this requires it */ - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); cfg80211_stop_p2p_device(rdev, wdev); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); break; default: break; @@ -278,10 +265,7 @@ static void cfg80211_event_work(struct work_struct *work) event_work); rtnl_lock(); - cfg80211_lock_rdev(rdev); - cfg80211_process_rdev_events(rdev); - cfg80211_unlock_rdev(rdev); rtnl_unlock(); } @@ -323,9 +307,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) /* give it a proper name */ dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); - mutex_init(&rdev->mtx); - mutex_init(&rdev->devlist_mtx); - mutex_init(&rdev->sched_scan_mtx); INIT_LIST_HEAD(&rdev->wdev_list); INIT_LIST_HEAD(&rdev->beacon_registrations); spin_lock_init(&rdev->beacon_registrations_lock); @@ -573,11 +554,11 @@ int wiphy_register(struct wiphy *wiphy) /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); - mutex_lock(&cfg80211_mutex); + rtnl_lock(); res = device_add(&rdev->wiphy.dev); if (res) { - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); return res; } @@ -606,25 +587,18 @@ int wiphy_register(struct wiphy *wiphy) } cfg80211_debugfs_rdev_add(rdev); - mutex_unlock(&cfg80211_mutex); - /* - * due to a locking dependency this has to be outside of the - * cfg80211_mutex lock - */ res = rfkill_register(rdev->rfkill); if (res) { device_del(&rdev->wiphy.dev); - mutex_lock(&cfg80211_mutex); debugfs_remove_recursive(rdev->wiphy.debugfsdir); list_del_rcu(&rdev->list); wiphy_regulatory_deregister(wiphy); - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); return res; } - rtnl_lock(); rdev->wiphy.registered = true; rtnl_unlock(); return 0; @@ -654,25 +628,19 @@ void wiphy_unregister(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - rtnl_lock(); - rdev->wiphy.registered = false; - rtnl_unlock(); - - rfkill_unregister(rdev->rfkill); - - /* protect the device list */ - mutex_lock(&cfg80211_mutex); - wait_event(rdev->dev_wait, ({ int __count; - mutex_lock(&rdev->devlist_mtx); + rtnl_lock(); __count = rdev->opencount; - mutex_unlock(&rdev->devlist_mtx); + rtnl_unlock(); __count == 0; })); - mutex_lock(&rdev->devlist_mtx); + rtnl_lock(); + rdev->wiphy.registered = false; + + rfkill_unregister(rdev->rfkill); + BUG_ON(!list_empty(&rdev->wdev_list)); - mutex_unlock(&rdev->devlist_mtx); /* * First remove the hardware from everywhere, this makes @@ -682,20 +650,6 @@ void wiphy_unregister(struct wiphy *wiphy) list_del_rcu(&rdev->list); synchronize_rcu(); - /* - * Try to grab rdev->mtx. If a command is still in progress, - * hopefully the driver will refuse it since it's tearing - * down the device already. We wait for this command to complete - * before unlinking the item from the list. - * Note: as codified by the BUG_ON above we cannot get here if - * a virtual interface is still present. Hence, we can only get - * to lock contention here if userspace issues a command that - * identified the hardware by wiphy index. - */ - cfg80211_lock_rdev(rdev); - /* nothing */ - cfg80211_unlock_rdev(rdev); - /* * If this device got a regulatory hint tell core its * free to listen now to a new shiny device regulatory hint @@ -705,7 +659,7 @@ void wiphy_unregister(struct wiphy *wiphy) cfg80211_rdev_list_generation++; device_del(&rdev->wiphy.dev); - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); flush_work(&rdev->scan_done_wk); cancel_work_sync(&rdev->conn_work); @@ -723,9 +677,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) struct cfg80211_internal_bss *scan, *tmp; struct cfg80211_beacon_registration *reg, *treg; rfkill_destroy(rdev->rfkill); - mutex_destroy(&rdev->mtx); - mutex_destroy(&rdev->devlist_mtx); - mutex_destroy(&rdev->sched_scan_mtx); list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { list_del(®->list); kfree(reg); @@ -750,36 +701,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) } EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); -static void wdev_cleanup_work(struct work_struct *work) -{ - struct wireless_dev *wdev; - struct cfg80211_registered_device *rdev; - - wdev = container_of(work, struct wireless_dev, cleanup_work); - rdev = wiphy_to_dev(wdev->wiphy); - - mutex_lock(&rdev->sched_scan_mtx); - - if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { - rdev->scan_req->aborted = true; - ___cfg80211_scan_done(rdev, true); - } - - if (WARN_ON(rdev->sched_scan_req && - rdev->sched_scan_req->dev == wdev->netdev)) { - __cfg80211_stop_sched_scan(rdev, false); - } - - mutex_unlock(&rdev->sched_scan_mtx); - - mutex_lock(&rdev->devlist_mtx); - rdev->opencount--; - mutex_unlock(&rdev->devlist_mtx); - wake_up(&rdev->dev_wait); - - dev_put(wdev->netdev); -} - void cfg80211_unregister_wdev(struct wireless_dev *wdev) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -789,8 +710,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) if (WARN_ON(wdev->netdev)) return; - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); list_del_rcu(&wdev->list); rdev->devlist_generation++; @@ -802,8 +721,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) WARN_ON_ONCE(1); break; } - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); } EXPORT_SYMBOL(cfg80211_unregister_wdev); @@ -822,7 +739,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, } void cfg80211_leave(struct cfg80211_registered_device *rdev, - struct wireless_dev *wdev) + struct wireless_dev *wdev) { struct net_device *dev = wdev->netdev; @@ -832,9 +749,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: - mutex_lock(&rdev->sched_scan_mtx); __cfg80211_stop_sched_scan(rdev, false); - mutex_unlock(&rdev->sched_scan_mtx); wdev_lock(wdev); #ifdef CONFIG_CFG80211_WEXT @@ -887,13 +802,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, * are added with nl80211. */ mutex_init(&wdev->mtx); - INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); INIT_LIST_HEAD(&wdev->event_list); spin_lock_init(&wdev->event_lock); INIT_LIST_HEAD(&wdev->mgmt_registrations); spin_lock_init(&wdev->mgmt_registrations_lock); - mutex_lock(&rdev->devlist_mtx); wdev->identifier = ++rdev->wdev_id; list_add_rcu(&wdev->list, &rdev->wdev_list); rdev->devlist_generation++; @@ -906,7 +819,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, } wdev->netdev = dev; wdev->sme_state = CFG80211_SME_IDLE; - mutex_unlock(&rdev->devlist_mtx); #ifdef CONFIG_CFG80211_WEXT wdev->wext.default_key = -1; wdev->wext.default_mgmt_key = -1; @@ -932,26 +844,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, break; case NETDEV_DOWN: cfg80211_update_iface_num(rdev, wdev->iftype, -1); - dev_hold(dev); - queue_work(cfg80211_wq, &wdev->cleanup_work); + if (rdev->scan_req && rdev->scan_req->wdev == wdev) { + if (WARN_ON(!rdev->scan_req->notified)) + rdev->scan_req->aborted = true; + ___cfg80211_scan_done(rdev, true); + } + + if (WARN_ON(rdev->sched_scan_req && + rdev->sched_scan_req->dev == wdev->netdev)) { + __cfg80211_stop_sched_scan(rdev, false); + } + + rdev->opencount--; + wake_up(&rdev->dev_wait); break; case NETDEV_UP: - /* - * If we have a really quick DOWN/UP succession we may - * have this work still pending ... cancel it and see - * if it was pending, in which case we need to account - * for some of the work it would have done. - */ - if (cancel_work_sync(&wdev->cleanup_work)) { - mutex_lock(&rdev->devlist_mtx); - rdev->opencount--; - mutex_unlock(&rdev->devlist_mtx); - dev_put(dev); - } cfg80211_update_iface_num(rdev, wdev->iftype, 1); - cfg80211_lock_rdev(rdev); - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); wdev_lock(wdev); switch (wdev->iftype) { #ifdef CONFIG_CFG80211_WEXT @@ -983,10 +891,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, break; } wdev_unlock(wdev); - mutex_unlock(&rdev->sched_scan_mtx); rdev->opencount++; - mutex_unlock(&rdev->devlist_mtx); - cfg80211_unlock_rdev(rdev); /* * Configure power management to the driver here so that its @@ -1002,12 +907,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, } break; case NETDEV_UNREGISTER: - /* - * NB: cannot take rdev->mtx here because this may be - * called within code protected by it when interfaces - * are removed with nl80211. - */ - mutex_lock(&rdev->devlist_mtx); /* * It is possible to get NETDEV_UNREGISTER * multiple times. To detect that, check @@ -1024,7 +923,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, kfree(wdev->wext.keys); #endif } - mutex_unlock(&rdev->devlist_mtx); /* * synchronise (so that we won't find this netdev * from other code any more) and then clear the list @@ -1044,9 +942,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, return notifier_from_errno(-EOPNOTSUPP); if (rfkill_blocked(rdev->rfkill)) return notifier_from_errno(-ERFKILL); - mutex_lock(&rdev->devlist_mtx); ret = cfg80211_can_add_interface(rdev, wdev->iftype); - mutex_unlock(&rdev->devlist_mtx); if (ret) return notifier_from_errno(ret); break; @@ -1064,12 +960,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net) struct cfg80211_registered_device *rdev; rtnl_lock(); - mutex_lock(&cfg80211_mutex); list_for_each_entry(rdev, &cfg80211_rdev_list, list) { if (net_eq(wiphy_net(&rdev->wiphy), net)) WARN_ON(cfg80211_switch_netns(rdev, &init_net)); } - mutex_unlock(&cfg80211_mutex); rtnl_unlock(); } diff --git a/net/wireless/core.h b/net/wireless/core.h index 95b29075a9c8..d21a0fc01401 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -5,7 +5,6 @@ */ #ifndef __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H -#include #include #include #include @@ -23,11 +22,6 @@ struct cfg80211_registered_device { const struct cfg80211_ops *ops; struct list_head list; - /* we hold this mutex during any call so that - * we cannot do multiple calls at once, and also - * to avoid the deregister call to proceed while - * any call is in progress */ - struct mutex mtx; /* rfkill support */ struct rfkill_ops rfkill_ops; @@ -49,9 +43,7 @@ struct cfg80211_registered_device { /* wiphy index, internal only */ int wiphy_idx; - /* associated wireless interfaces */ - struct mutex devlist_mtx; - /* protected by devlist_mtx or RCU */ + /* associated wireless interfaces, protected by rtnl or RCU */ struct list_head wdev_list; int devlist_generation, wdev_id; int opencount; /* also protected by devlist_mtx */ @@ -75,8 +67,6 @@ struct cfg80211_registered_device { struct work_struct scan_done_wk; struct work_struct sched_scan_results_wk; - struct mutex sched_scan_mtx; - #ifdef CONFIG_NL80211_TESTMODE struct genl_info *testmode_info; #endif @@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) } extern struct workqueue_struct *cfg80211_wq; -extern struct mutex cfg80211_mutex; extern struct list_head cfg80211_rdev_list; extern int cfg80211_rdev_list_generation; -static inline void assert_cfg80211_lock(void) -{ - lockdep_assert_held(&cfg80211_mutex); -} - struct cfg80211_internal_bss { struct list_head list; struct list_head hidden_list; @@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); int get_wiphy_idx(struct wiphy *wiphy); -/* requires cfg80211_rdev_mutex to be held! */ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, struct net *net); -static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev) -{ - mutex_lock(&rdev->mtx); -} - -static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev) -{ - BUG_ON(IS_ERR(rdev) || !rdev); - mutex_unlock(&rdev->mtx); -} - static inline void wdev_lock(struct wireless_dev *wdev) __acquires(wdev) { @@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev) mutex_unlock(&wdev->mtx); } -#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) +#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL() #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 920cabe0461b..90d050036624 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file, if (!buf) return -ENOMEM; - mutex_lock(&cfg80211_mutex); + rtnl_lock(); for (band = 0; band < IEEE80211_NUM_BANDS; band++) { sband = wiphy->bands[band]; @@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file, buf, buf_size, offset); } - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index d80e47194d49..5449c5a6de84 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - mutex_lock(&rdev->devlist_mtx); + ASSERT_RTNL(); + wdev_lock(wdev); err = __cfg80211_join_ibss(rdev, dev, params, connkeys); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, wdev->wext.ibss.channel_fixed = false; } - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = cfg80211_ibss_wext_join(rdev, wdev); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, memcpy(wdev->wext.ibss.ssid, ssid, len); wdev->wext.ibss.ssid_len = len; - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = cfg80211_ibss_wext_join(rdev, wdev); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, } else wdev->wext.ibss.bssid = NULL; - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = cfg80211_ibss_wext_join(rdev, wdev); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 9546ad210550..5dfb289ab761 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -186,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - mutex_lock(&rdev->devlist_mtx); wdev_lock(wdev); err = __cfg80211_join_mesh(rdev, dev, setup, conf); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index c21e32f9549c..68b40f21bc38 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -313,14 +313,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, { int err; - mutex_lock(&rdev->devlist_mtx); + ASSERT_RTNL(); + wdev_lock(dev->ieee80211_ptr); err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, ssid, ssid_len, ie, ie_len, key, key_len, key_idx, sae_data, sae_data_len); wdev_unlock(dev->ieee80211_ptr); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -424,12 +424,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - mutex_lock(&rdev->devlist_mtx); + ASSERT_RTNL(); + wdev_lock(wdev); err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, ssid, ssid_len, req); wdev_unlock(wdev); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -844,7 +844,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) dfs_update_channels_wk); wiphy = &rdev->wiphy; - mutex_lock(&cfg80211_mutex); + rtnl_lock(); for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { sband = wiphy->bands[bandid]; if (!sband) @@ -877,7 +877,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) check_again = true; } } - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); /* reschedule if there are other channels waiting to be cleared again */ if (check_again) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5bcf3a5b6465..74cdb1a0cf31 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) int wiphy_idx = -1; int ifidx = -1; - assert_cfg80211_lock(); + ASSERT_RTNL(); if (!have_ifidx && !have_wdev_id) return ERR_PTR(-EINVAL); @@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) continue; - mutex_lock(&rdev->devlist_mtx); list_for_each_entry(wdev, &rdev->wdev_list, list) { if (have_ifidx && wdev->netdev && wdev->netdev->ifindex == ifidx) { @@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) break; } } - mutex_unlock(&rdev->devlist_mtx); if (result) break; @@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) struct cfg80211_registered_device *rdev = NULL, *tmp; struct net_device *netdev; - assert_cfg80211_lock(); + ASSERT_RTNL(); if (!attrs[NL80211_ATTR_WIPHY] && !attrs[NL80211_ATTR_IFINDEX] && @@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); if (tmp) { /* make sure wdev exists */ - mutex_lock(&tmp->devlist_mtx); list_for_each_entry(wdev, &tmp->wdev_list, list) { if (wdev->identifier != (u32)wdev_id) continue; found = true; break; } - mutex_unlock(&tmp->devlist_mtx); if (!found) tmp = NULL; @@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) /* * This function returns a pointer to the driver * that the genl_info item that is passed refers to. - * If successful, it returns non-NULL and also locks - * the driver's mutex! - * - * This means that you need to call cfg80211_unlock_rdev() - * before being allowed to acquire &cfg80211_mutex! - * - * This is necessary because we need to lock the global - * mutex to get an item off the list safely, and then - * we lock the rdev mutex so it doesn't go away under us. - * - * We don't want to keep cfg80211_mutex locked - * for all the time in order to allow requests on - * other interfaces to go through at the same time. * * The result of this can be a PTR_ERR and hence must * be checked with IS_ERR() for errors. @@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs) static struct cfg80211_registered_device * cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) { - struct cfg80211_registered_device *rdev; - - mutex_lock(&cfg80211_mutex); - rdev = __cfg80211_rdev_from_attrs(netns, info->attrs); - - /* if it is not an error we grab the lock on - * it to assure it won't be going away while - * we operate on it */ - if (!IS_ERR(rdev)) - mutex_lock(&rdev->mtx); - - mutex_unlock(&cfg80211_mutex); - - return rdev; + return __cfg80211_rdev_from_attrs(netns, info->attrs); } /* policy for the attributes */ @@ -456,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, int err; rtnl_lock(); - mutex_lock(&cfg80211_mutex); if (!cb->args[0]) { err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, @@ -485,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, *rdev = wiphy_to_dev(wiphy); *wdev = NULL; - mutex_lock(&(*rdev)->devlist_mtx); list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { if (tmp->identifier == cb->args[1]) { *wdev = tmp; break; } } - mutex_unlock(&(*rdev)->devlist_mtx); if (!*wdev) { err = -ENODEV; @@ -500,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, } } - cfg80211_lock_rdev(*rdev); - - mutex_unlock(&cfg80211_mutex); return 0; out_unlock: - mutex_unlock(&cfg80211_mutex); rtnl_unlock(); return err; } static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) { - cfg80211_unlock_rdev(rdev); rtnl_unlock(); } @@ -1568,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) struct nlattr **tb = nl80211_fam.attrbuf; int res; - mutex_lock(&cfg80211_mutex); + rtnl_lock(); res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, tb, nl80211_fam.maxattr, nl80211_policy); if (res == 0) { @@ -1582,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); netdev = dev_get_by_index(sock_net(skb->sk), ifidx); - if (!netdev) { - mutex_unlock(&cfg80211_mutex); + if (!netdev) return -ENODEV; - } if (netdev->ieee80211_ptr) { dev = wiphy_to_dev( netdev->ieee80211_ptr->wiphy); @@ -1629,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) !skb->len && cb->min_dump_alloc < 4096) { cb->min_dump_alloc = 4096; - mutex_unlock(&cfg80211_mutex); return 1; } idx--; @@ -1638,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) } while (cb->args[1] > 0); break; } - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); cb->args[0] = idx; @@ -1793,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, if (result) return result; - mutex_lock(&rdev->devlist_mtx); switch (iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: @@ -1817,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, default: result = -EINVAL; } - mutex_unlock(&rdev->devlist_mtx); return result; } @@ -1866,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) u32 frag_threshold = 0, rts_threshold = 0; u8 coverage_class = 0; + ASSERT_RTNL(); + /* * Try to find the wiphy and netdev. Normally this * function shouldn't need the netdev, but this is @@ -1875,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) * also passed a netdev to set_wiphy, so that it is * possible to let that go to the right netdev! */ - mutex_lock(&cfg80211_mutex); if (info->attrs[NL80211_ATTR_IFINDEX]) { int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); netdev = dev_get_by_index(genl_info_net(info), ifindex); - if (netdev && netdev->ieee80211_ptr) { + if (netdev && netdev->ieee80211_ptr) rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); - mutex_lock(&rdev->mtx); - } else + else netdev = NULL; } if (!netdev) { rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), info->attrs); - if (IS_ERR(rdev)) { - mutex_unlock(&cfg80211_mutex); + if (IS_ERR(rdev)) return PTR_ERR(rdev); - } wdev = NULL; netdev = NULL; result = 0; - - mutex_lock(&rdev->mtx); } else wdev = netdev->ieee80211_ptr; @@ -1912,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) result = cfg80211_dev_rename( rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); - mutex_unlock(&cfg80211_mutex); - if (result) goto bad_res; @@ -2120,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) } bad_res: - mutex_unlock(&rdev->mtx); if (netdev) dev_put(netdev); return result; @@ -2218,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * struct cfg80211_registered_device *rdev; struct wireless_dev *wdev; - mutex_lock(&cfg80211_mutex); + rtnl_lock(); list_for_each_entry(rdev, &cfg80211_rdev_list, list) { if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) continue; @@ -2228,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * } if_idx = 0; - mutex_lock(&rdev->devlist_mtx); list_for_each_entry(wdev, &rdev->wdev_list, list) { if (if_idx < if_start) { if_idx++; @@ -2237,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, rdev, wdev) < 0) { - mutex_unlock(&rdev->devlist_mtx); goto out; } if_idx++; } - mutex_unlock(&rdev->devlist_mtx); wp_idx++; } out: - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); cb->args[0] = wp_idx; cb->args[1] = if_idx; @@ -2480,11 +2427,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) INIT_LIST_HEAD(&wdev->mgmt_registrations); spin_lock_init(&wdev->mgmt_registrations_lock); - mutex_lock(&rdev->devlist_mtx); wdev->identifier = ++rdev->wdev_id; list_add_rcu(&wdev->list, &rdev->wdev_list); rdev->devlist_generation++; - mutex_unlock(&rdev->devlist_mtx); break; default: break; @@ -2993,8 +2938,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev; bool ret = false; - mutex_lock(&rdev->devlist_mtx); - list_for_each_entry(wdev, &rdev->wdev_list, list) { if (wdev->iftype != NL80211_IFTYPE_AP && wdev->iftype != NL80211_IFTYPE_P2P_GO) @@ -3008,8 +2951,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, break; } - mutex_unlock(&rdev->devlist_mtx); - return ret; } @@ -3171,13 +3112,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.radar_required = true; } - mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, params.chandef.chan, CHAN_MODE_SHARED, radar_detect_width); - mutex_unlock(&rdev->devlist_mtx); - if (err) return err; @@ -4914,18 +4852,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) void *hdr = NULL; struct nlattr *nl_reg_rules; unsigned int i; - int err = -EINVAL; - - mutex_lock(&cfg80211_mutex); if (!cfg80211_regdomain) - goto out; + return -EINVAL; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) { - err = -ENOBUFS; - goto out; - } + if (!msg) + return -ENOBUFS; hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, NL80211_CMD_GET_REG); @@ -4984,8 +4917,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) nla_nest_end(msg, nl_reg_rules); genlmsg_end(msg, hdr); - err = genlmsg_reply(msg, info); - goto out; + return genlmsg_reply(msg, info); nla_put_failure_rcu: rcu_read_unlock(); @@ -4993,10 +4925,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) genlmsg_cancel(msg, hdr); put_failure: nlmsg_free(msg); - err = -EMSGSIZE; -out: - mutex_unlock(&cfg80211_mutex); - return err; + return -EMSGSIZE; } static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) @@ -5062,12 +4991,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) } } - mutex_lock(&cfg80211_mutex); - r = set_regdom(rd); /* set_regdom took ownership */ rd = NULL; - mutex_unlock(&cfg80211_mutex); bad_reg: kfree(rd); @@ -5117,7 +5043,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->scan) return -EOPNOTSUPP; - mutex_lock(&rdev->sched_scan_mtx); if (rdev->scan_req) { err = -EBUSY; goto unlock; @@ -5303,7 +5228,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) } unlock: - mutex_unlock(&rdev->sched_scan_mtx); return err; } @@ -5375,8 +5299,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, if (ie_len > wiphy->max_sched_scan_ie_len) return -EINVAL; - mutex_lock(&rdev->sched_scan_mtx); - if (rdev->sched_scan_req) { err = -EINPROGRESS; goto out; @@ -5544,7 +5466,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, out_free: kfree(request); out: - mutex_unlock(&rdev->sched_scan_mtx); return err; } @@ -5552,17 +5473,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; - int err; if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || !rdev->ops->sched_scan_stop) return -EOPNOTSUPP; - mutex_lock(&rdev->sched_scan_mtx); - err = __cfg80211_stop_sched_scan(rdev, false); - mutex_unlock(&rdev->sched_scan_mtx); - - return err; + return __cfg80211_stop_sched_scan(rdev, false); } static int nl80211_start_radar_detection(struct sk_buff *skb, @@ -5594,12 +5510,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, if (!rdev->ops->start_radar_detection) return -EOPNOTSUPP; - mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, chandef.chan, CHAN_MODE_SHARED, BIT(chandef.width)); if (err) - goto err_locked; + return err; err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); if (!err) { @@ -5607,9 +5522,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, wdev->cac_started = true; wdev->cac_start_time = jiffies; } -err_locked: - mutex_unlock(&rdev->devlist_mtx); - return err; } @@ -6472,6 +6384,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, void *data = NULL; int data_len = 0; + rtnl_lock(); + if (cb->args[0]) { /* * 0 is a valid index, but not valid for args[0], @@ -6483,18 +6397,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb, nl80211_fam.attrbuf, nl80211_fam.maxattr, nl80211_policy); if (err) - return err; + goto out_err; - mutex_lock(&cfg80211_mutex); rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), nl80211_fam.attrbuf); if (IS_ERR(rdev)) { - mutex_unlock(&cfg80211_mutex); - return PTR_ERR(rdev); + err = PTR_ERR(rdev); + goto out_err; } phy_idx = rdev->wiphy_idx; rdev = NULL; - mutex_unlock(&cfg80211_mutex); if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) cb->args[1] = @@ -6506,14 +6418,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb, data_len = nla_len((void *)cb->args[1]); } - mutex_lock(&cfg80211_mutex); rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); if (!rdev) { - mutex_unlock(&cfg80211_mutex); - return -ENOENT; + err = -ENOENT; + goto out_err; } - cfg80211_lock_rdev(rdev); - mutex_unlock(&cfg80211_mutex); if (!rdev->ops->testmode_dump) { err = -EOPNOTSUPP; @@ -6554,7 +6463,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, /* see above */ cb->args[0] = phy_idx + 1; out_err: - cfg80211_unlock_rdev(rdev); + rtnl_unlock(); return err; } @@ -8189,9 +8098,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) if (wdev->p2p_started) return 0; - mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_add_interface(rdev, wdev->iftype); - mutex_unlock(&rdev->devlist_mtx); if (err) return err; @@ -8200,9 +8107,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) return err; wdev->p2p_started = true; - mutex_lock(&rdev->devlist_mtx); rdev->opencount++; - mutex_unlock(&rdev->devlist_mtx); return 0; } @@ -8218,11 +8123,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->stop_p2p_device) return -EOPNOTSUPP; - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); cfg80211_stop_p2p_device(rdev, wdev); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); return 0; } @@ -8365,11 +8266,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, info->user_ptr[0] = rdev; } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || ops->internal_flags & NL80211_FLAG_NEED_WDEV) { - mutex_lock(&cfg80211_mutex); + ASSERT_RTNL(); + wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); if (IS_ERR(wdev)) { - mutex_unlock(&cfg80211_mutex); if (rtnl) rtnl_unlock(); return PTR_ERR(wdev); @@ -8380,7 +8281,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { if (!dev) { - mutex_unlock(&cfg80211_mutex); if (rtnl) rtnl_unlock(); return -EINVAL; @@ -8394,7 +8294,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, if (dev) { if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && !netif_running(dev)) { - mutex_unlock(&cfg80211_mutex); if (rtnl) rtnl_unlock(); return -ENETDOWN; @@ -8403,17 +8302,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, dev_hold(dev); } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { if (!wdev->p2p_started) { - mutex_unlock(&cfg80211_mutex); if (rtnl) rtnl_unlock(); return -ENETDOWN; } } - cfg80211_lock_rdev(rdev); - - mutex_unlock(&cfg80211_mutex); - info->user_ptr[0] = rdev; } @@ -8423,8 +8317,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) { - if (info->user_ptr[0]) - cfg80211_unlock_rdev(info->user_ptr[0]); if (info->user_ptr[1]) { if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { struct wireless_dev *wdev = info->user_ptr[1]; @@ -8446,7 +8338,8 @@ static struct genl_ops nl80211_ops[] = { .dumpit = nl80211_dump_wiphy, .policy = nl80211_policy, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_WIPHY, + .internal_flags = NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL, }, { .cmd = NL80211_CMD_SET_WIPHY, @@ -8461,7 +8354,8 @@ static struct genl_ops nl80211_ops[] = { .dumpit = nl80211_dump_interface, .policy = nl80211_policy, /* can be retrieved by unprivileged users */ - .internal_flags = NL80211_FLAG_NEED_WDEV, + .internal_flags = NL80211_FLAG_NEED_WDEV | + NL80211_FLAG_NEED_RTNL, }, { .cmd = NL80211_CMD_SET_INTERFACE, @@ -8620,6 +8514,7 @@ static struct genl_ops nl80211_ops[] = { .cmd = NL80211_CMD_GET_REG, .doit = nl80211_get_reg, .policy = nl80211_policy, + .internal_flags = NL80211_FLAG_NEED_RTNL, /* can be retrieved by unprivileged users */ }, { @@ -8627,6 +8522,7 @@ static struct genl_ops nl80211_ops[] = { .doit = nl80211_set_reg, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_RTNL, }, { .cmd = NL80211_CMD_REQ_SET_REG, @@ -9082,8 +8978,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg, struct nlattr *nest; int i; - lockdep_assert_held(&rdev->sched_scan_mtx); - if (WARN_ON(!req)) return 0; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index cc35fbaa4578..e76559618588 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -377,7 +377,7 @@ static void reg_regdb_search(struct work_struct *work) const struct ieee80211_regdomain *curdom, *regdom = NULL; int i; - mutex_lock(&cfg80211_mutex); + rtnl_lock(); mutex_lock(®_regdb_search_mutex); while (!list_empty(®_regdb_search_list)) { @@ -402,7 +402,7 @@ static void reg_regdb_search(struct work_struct *work) if (!IS_ERR_OR_NULL(regdom)) set_regdom(regdom); - mutex_unlock(&cfg80211_mutex); + rtnl_unlock(); } static DECLARE_WORK(reg_regdb_work, reg_regdb_search); @@ -1225,7 +1225,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) struct cfg80211_registered_device *rdev; struct wiphy *wiphy; - assert_cfg80211_lock(); + ASSERT_RTNL(); list_for_each_entry(rdev, &cfg80211_rdev_list, list) { wiphy = &rdev->wiphy; @@ -1570,21 +1570,19 @@ static void reg_process_pending_hints(void) { struct regulatory_request *reg_request, *lr; - mutex_lock(&cfg80211_mutex); - mutex_lock(®_mutex); lr = get_last_request(); /* When last_request->processed becomes true this will be rescheduled */ if (lr && !lr->processed) { REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); - goto out; + return; } spin_lock(®_requests_lock); if (list_empty(®_requests_list)) { spin_unlock(®_requests_lock); - goto out; + return; } reg_request = list_first_entry(®_requests_list, @@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void) spin_unlock(®_requests_lock); reg_process_hint(reg_request, reg_request->initiator); - -out: - mutex_unlock(®_mutex); - mutex_unlock(&cfg80211_mutex); } /* Processes beacon hints -- this has nothing to do with country IEs */ @@ -1607,9 +1601,6 @@ static void reg_process_pending_beacon_hints(void) struct cfg80211_registered_device *rdev; struct reg_beacon *pending_beacon, *tmp; - mutex_lock(&cfg80211_mutex); - mutex_lock(®_mutex); - /* This goes through the _pending_ beacon list */ spin_lock_bh(®_pending_beacons_lock); @@ -1626,14 +1617,16 @@ static void reg_process_pending_beacon_hints(void) } spin_unlock_bh(®_pending_beacons_lock); - mutex_unlock(®_mutex); - mutex_unlock(&cfg80211_mutex); } static void reg_todo(struct work_struct *work) { + rtnl_lock(); + mutex_lock(®_mutex); reg_process_pending_hints(); reg_process_pending_beacon_hints(); + mutex_unlock(®_mutex); + rtnl_unlock(); } static void queue_regulatory_request(struct regulatory_request *request) @@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2) } EXPORT_SYMBOL(regulatory_hint); -/* - * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and - * therefore cannot iterate over the rdev list here. - */ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, const u8 *country_ie, u8 country_ie_len) { @@ -1752,7 +1741,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, /* * We will run this only upon a successful connection on cfg80211. * We leave conflict resolution to the workqueue, where can hold - * cfg80211_mutex. + * the RTNL. */ if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && lr->wiphy_idx != WIPHY_IDX_INVALID) @@ -1858,7 +1847,8 @@ static void restore_regulatory_settings(bool reset_user) LIST_HEAD(tmp_reg_req_list); struct cfg80211_registered_device *rdev; - mutex_lock(&cfg80211_mutex); + ASSERT_RTNL(); + mutex_lock(®_mutex); reset_regdomains(true, &world_regdom); @@ -1915,7 +1905,6 @@ static void restore_regulatory_settings(bool reset_user) spin_unlock(®_requests_lock); mutex_unlock(®_mutex); - mutex_unlock(&cfg80211_mutex); REG_DBG_PRINT("Kicking the queue\n"); @@ -2297,7 +2286,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy) mutex_unlock(®_mutex); } -/* Caller must hold cfg80211_mutex */ void wiphy_regulatory_deregister(struct wiphy *wiphy) { struct wiphy *request_wiphy = NULL; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2ce44a712f13..dd01b58fa78c 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) union iwreq_data wrqu; #endif - lockdep_assert_held(&rdev->sched_scan_mtx); + ASSERT_RTNL(); request = rdev->scan_req; @@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) rdev = container_of(wk, struct cfg80211_registered_device, scan_done_wk); - mutex_lock(&rdev->sched_scan_mtx); + rtnl_lock(); ___cfg80211_scan_done(rdev, false); - mutex_unlock(&rdev->sched_scan_mtx); + rtnl_unlock(); } void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) @@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); request->aborted = aborted; + request->notified = true; queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); } EXPORT_SYMBOL(cfg80211_scan_done); @@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) request = rdev->sched_scan_req; - mutex_lock(&rdev->sched_scan_mtx); + rtnl_lock(); /* we don't have sched_scan_req anymore if the scan is stopping */ if (request) { @@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) nl80211_send_sched_scan_results(rdev, request->dev); } - mutex_unlock(&rdev->sched_scan_mtx); + rtnl_unlock(); } void cfg80211_sched_scan_results(struct wiphy *wiphy) @@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) trace_cfg80211_sched_scan_stopped(wiphy); - mutex_lock(&rdev->sched_scan_mtx); + rtnl_lock(); __cfg80211_stop_sched_scan(rdev, true); - mutex_unlock(&rdev->sched_scan_mtx); + rtnl_unlock(); } EXPORT_SYMBOL(cfg80211_sched_scan_stopped); @@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, { struct net_device *dev; - lockdep_assert_held(&rdev->sched_scan_mtx); + ASSERT_RTNL(); if (!rdev->sched_scan_req) return -ENOENT; @@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss); static struct cfg80211_registered_device * cfg80211_get_dev_from_ifindex(struct net *net, int ifindex) { - struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV); + struct cfg80211_registered_device *rdev; struct net_device *dev; - mutex_lock(&cfg80211_mutex); + ASSERT_RTNL(); + dev = dev_get_by_index(net, ifindex); if (!dev) - goto out; - if (dev->ieee80211_ptr) { + return ERR_PTR(-ENODEV); + if (dev->ieee80211_ptr) rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); - mutex_lock(&rdev->mtx); - } else + else rdev = ERR_PTR(-ENODEV); dev_put(dev); - out: - mutex_unlock(&cfg80211_mutex); return rdev; } @@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev, if (IS_ERR(rdev)) return PTR_ERR(rdev); - mutex_lock(&rdev->sched_scan_mtx); if (rdev->scan_req) { err = -EBUSY; goto out; @@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, dev_hold(dev); } out: - mutex_unlock(&rdev->sched_scan_mtx); kfree(creq); - cfg80211_unlock_rdev(rdev); return err; } EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); @@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev, if (IS_ERR(rdev)) return PTR_ERR(rdev); - if (rdev->scan_req) { - res = -EAGAIN; - goto out; - } + if (rdev->scan_req) + return -EAGAIN; res = ieee80211_scan_results(rdev, info, extra, data->length); data->length = 0; @@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev, res = 0; } - out: - cfg80211_unlock_rdev(rdev); return res; } EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 3ed35c345cae..4dbf31407a56 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void) struct wireless_dev *wdev; bool is_all_idle = true; - mutex_lock(&cfg80211_mutex); - /* * All devices must be idle as otherwise if you are actively * scanning some new beacon hints could be learned and would * count as new regulatory hints. */ list_for_each_entry(rdev, &cfg80211_rdev_list, list) { - cfg80211_lock_rdev(rdev); list_for_each_entry(wdev, &rdev->wdev_list, list) { wdev_lock(wdev); if (wdev->sme_state != CFG80211_SME_IDLE) is_all_idle = false; wdev_unlock(wdev); } - cfg80211_unlock_rdev(rdev); } - mutex_unlock(&cfg80211_mutex); - return is_all_idle; } static void disconnect_work(struct work_struct *work) { - if (!cfg80211_is_all_idle()) - return; - - regulatory_hint_disconnect(); + rtnl_lock(); + if (cfg80211_is_all_idle()) + regulatory_hint_disconnect(); + rtnl_unlock(); } static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); @@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) ASSERT_RTNL(); ASSERT_RDEV_LOCK(rdev); ASSERT_WDEV_LOCK(wdev); - lockdep_assert_held(&rdev->sched_scan_mtx); if (rdev->scan_req) return -EBUSY; @@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work) u8 bssid_buf[ETH_ALEN], *bssid = NULL; rtnl_lock(); - cfg80211_lock_rdev(rdev); - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); list_for_each_entry(wdev, &rdev->wdev_list, list) { if (!wdev->netdev) @@ -256,9 +246,6 @@ void cfg80211_conn_work(struct work_struct *work) wdev_unlock(wdev); } - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); - cfg80211_unlock_rdev(rdev); rtnl_unlock(); } @@ -931,14 +918,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, { int err; - mutex_lock(&rdev->devlist_mtx); - /* might request scan - scan_mtx -> wdev_mtx dependency */ - mutex_lock(&rdev->sched_scan_mtx); wdev_lock(dev->ieee80211_ptr); err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); wdev_unlock(dev->ieee80211_ptr); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); return err; } diff --git a/net/wireless/util.c b/net/wireless/util.c index 0962f107f57f..501724257af5 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -808,12 +808,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) ASSERT_RTNL(); ASSERT_RDEV_LOCK(rdev); - mutex_lock(&rdev->devlist_mtx); - list_for_each_entry(wdev, &rdev->wdev_list, list) cfg80211_process_wdev_events(wdev); - - mutex_unlock(&rdev->devlist_mtx); } int cfg80211_change_iface(struct cfg80211_registered_device *rdev, @@ -845,10 +841,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, return -EBUSY; if (ntype != otype && netif_running(dev)) { - mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, ntype); - mutex_unlock(&rdev->devlist_mtx); if (err) return err; @@ -1210,8 +1204,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, if (!beacon_int) return -EINVAL; - mutex_lock(&rdev->devlist_mtx); - list_for_each_entry(wdev, &rdev->wdev_list, list) { if (!wdev->beacon_interval) continue; @@ -1221,8 +1213,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, } } - mutex_unlock(&rdev->devlist_mtx); - return res; } @@ -1246,7 +1236,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, int i, j; ASSERT_RTNL(); - lockdep_assert_held(&rdev->devlist_mtx); if (WARN_ON(hweight32(radar_detect) > 1)) return -EINVAL; diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index d997d0f0c54a..e7c6e862580d 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, struct cfg80211_registered_device *rdev; struct vif_params vifparams; enum nl80211_iftype type; - int ret; rdev = wiphy_to_dev(wdev->wiphy); @@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, memset(&vifparams, 0, sizeof(vifparams)); - cfg80211_lock_rdev(rdev); - ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams); - cfg80211_unlock_rdev(rdev); - - return ret; + return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams); } EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode); @@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, { int err; - /* devlist mutex needed for possible IBSS re-join */ - mutex_lock(&rdev->devlist_mtx); wdev_lock(dev->ieee80211_ptr); err = __cfg80211_set_encryption(rdev, dev, pairwise, addr, remove, tx_key, idx, params); wdev_unlock(dev->ieee80211_ptr); - mutex_unlock(&rdev->devlist_mtx); return err; } @@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, struct cfg80211_chan_def chandef = { .width = NL80211_CHAN_WIDTH_20_NOHT, }; - int freq, err; + int freq; switch (wdev->iftype) { case NL80211_IFTYPE_STATION: @@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); if (!chandef.chan) return -EINVAL; - mutex_lock(&rdev->devlist_mtx); - err = cfg80211_set_monitor_channel(rdev, &chandef); - mutex_unlock(&rdev->devlist_mtx); - return err; + return cfg80211_set_monitor_channel(rdev, &chandef); case NL80211_IFTYPE_MESH_POINT: freq = cfg80211_wext_freq(wdev->wiphy, wextfreq); if (freq < 0) @@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); if (!chandef.chan) return -EINVAL; - mutex_lock(&rdev->devlist_mtx); - err = cfg80211_set_mesh_channel(rdev, wdev, &chandef); - mutex_unlock(&rdev->devlist_mtx); - return err; + return cfg80211_set_mesh_channel(rdev, wdev, &chandef); default: return -EOPNOTSUPP; } diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index e79cb5c0655a..aeefd6817189 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, return -EINVAL; } - cfg80211_lock_rdev(rdev); - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); wdev_lock(wdev); if (wdev->sme_state != CFG80211_SME_IDLE) { @@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, err = cfg80211_mgd_wext_connect(rdev, wdev); out: wdev_unlock(wdev); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); - cfg80211_unlock_rdev(rdev); return err; } @@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, if (len > 0 && ssid[len - 1] == '\0') len--; - cfg80211_lock_rdev(rdev); - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); wdev_lock(wdev); err = 0; @@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, err = cfg80211_mgd_wext_connect(rdev, wdev); out: wdev_unlock(wdev); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); - cfg80211_unlock_rdev(rdev); return err; } @@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) bssid = NULL; - cfg80211_lock_rdev(rdev); - mutex_lock(&rdev->devlist_mtx); - mutex_lock(&rdev->sched_scan_mtx); wdev_lock(wdev); if (wdev->sme_state != CFG80211_SME_IDLE) { @@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, err = cfg80211_mgd_wext_connect(rdev, wdev); out: wdev_unlock(wdev); - mutex_unlock(&rdev->sched_scan_mtx); - mutex_unlock(&rdev->devlist_mtx); - cfg80211_unlock_rdev(rdev); return err; } -- GitLab From 8d61ffa5e01c5f676431d12caba17db164a48a86 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 May 2013 12:32:47 +0200 Subject: [PATCH 0328/2900] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211 Using separate locks in cfg80211 and mac80211 has always caused issues, for example having to unlock in places in mac80211 to call cfg80211, which even needed a framework to make cfg80211 calls after some functions returned etc. Additionally, I suspect some issues people have reported with the cfg80211 state getting confused could be due to such issues, when cfg80211 is asking mac80211 to change state but mac80211 is in the process of telling cfg80211 that the state changed (in another way.) Signed-off-by: Johannes Berg --- Documentation/DocBook/80211.tmpl | 2 - include/net/cfg80211.h | 51 +++-- net/mac80211/cfg.c | 4 +- net/mac80211/debugfs_netdev.c | 10 +- net/mac80211/ht.c | 4 +- net/mac80211/ibss.c | 39 ++-- net/mac80211/ieee80211_i.h | 25 ++- net/mac80211/main.c | 4 +- net/mac80211/mesh.c | 32 +-- net/mac80211/mesh_plink.c | 7 +- net/mac80211/mlme.c | 341 +++++++++++-------------------- net/mac80211/util.c | 4 +- net/wireless/mlme.c | 48 +---- net/wireless/trace.h | 4 +- 14 files changed, 220 insertions(+), 355 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 0f6a3edcd44b..ebe89694cf81 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -132,9 +132,7 @@ !Finclude/net/cfg80211.h cfg80211_send_rx_assoc !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout !Finclude/net/cfg80211.h cfg80211_send_deauth -!Finclude/net/cfg80211.h __cfg80211_send_deauth !Finclude/net/cfg80211.h cfg80211_send_disassoc -!Finclude/net/cfg80211.h __cfg80211_send_disassoc !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_roamed diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5430f70c63b3..9f45d74ce3c2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1867,7 +1867,9 @@ struct cfg80211_update_ft_ies_params { * @get_mpath: get a mesh path for the given parameters * @dump_mpath: dump mesh path callback -- resume dump at index @idx * @join_mesh: join the mesh network with the specified parameters + * (invoked with the wireless_dev mutex held) * @leave_mesh: leave the current mesh network + * (invoked with the wireless_dev mutex held) * * @get_mesh_config: Get the current mesh configuration * @@ -1894,20 +1896,28 @@ struct cfg80211_update_ft_ies_params { * the scan/scan_done bracket too. * * @auth: Request to authenticate with the specified peer + * (invoked with the wireless_dev mutex held) * @assoc: Request to (re)associate with the specified peer + * (invoked with the wireless_dev mutex held) * @deauth: Request to deauthenticate from the specified peer + * (invoked with the wireless_dev mutex held) * @disassoc: Request to disassociate from the specified peer + * (invoked with the wireless_dev mutex held) * * @connect: Connect to the ESS with the specified parameters. When connected, * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. * If the connection fails for some reason, call cfg80211_connect_result() * with the status from the AP. + * (invoked with the wireless_dev mutex held) * @disconnect: Disconnect from the BSS/ESS. + * (invoked with the wireless_dev mutex held) * * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call * cfg80211_ibss_joined(), also call that function when changing BSSID due * to a merge. + * (invoked with the wireless_dev mutex held) * @leave_ibss: Leave the IBSS. + * (invoked with the wireless_dev mutex held) * * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or * MESH mode) @@ -2851,7 +2861,8 @@ struct cfg80211_cached_keys; * by cfg80211 on change_interface * @mgmt_registrations: list of registrations for management frames * @mgmt_registrations_lock: lock for the list - * @mtx: mutex used to lock data in this struct + * @mtx: mutex used to lock data in this struct, may be used by drivers + * and some API functions require it held * @cleanup_work: work struct used for cleanup that can't be done directly * @beacon_interval: beacon interval used on this device for transmitting * beacons, 0 when not valid @@ -3424,7 +3435,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); * This function is called whenever an authentication has been processed in * station mode. The driver is required to call either this function or * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth() - * call. This function may sleep. + * call. This function may sleep. The caller must hold the corresponding wdev's + * mutex. */ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); @@ -3433,7 +3445,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); * @dev: network device * @addr: The MAC address of the device with which the authentication timed out * - * This function may sleep. + * This function may sleep. The caller must hold the corresponding wdev's + * mutex. */ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); @@ -3448,7 +3461,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); * This function is called whenever a (re)association response has been * processed in station mode. The driver is required to call either this * function or cfg80211_send_assoc_timeout() to indicate the result of - * cfg80211_ops::assoc() call. This function may sleep. + * cfg80211_ops::assoc() call. This function may sleep. The caller must hold + * the corresponding wdev's mutex. */ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len); @@ -3458,7 +3472,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, * @dev: network device * @addr: The MAC address of the device with which the association timed out * - * This function may sleep. + * This function may sleep. The caller must hold the corresponding wdev's mutex. */ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); @@ -3470,20 +3484,11 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); * * This function is called whenever deauthentication has been processed in * station mode. This includes both received deauthentication frames and - * locally generated ones. This function may sleep. + * locally generated ones. This function may sleep. The caller must hold the + * corresponding wdev's mutex. */ void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); -/** - * __cfg80211_send_deauth - notification of processed deauthentication - * @dev: network device - * @buf: deauthentication frame (header + body) - * @len: length of the frame data - * - * Like cfg80211_send_deauth(), but doesn't take the wdev lock. - */ -void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); - /** * cfg80211_send_disassoc - notification of processed disassociation * @dev: network device @@ -3492,21 +3497,11 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); * * This function is called whenever disassociation has been processed in * station mode. This includes both received disassociation frames and locally - * generated ones. This function may sleep. + * generated ones. This function may sleep. The caller must hold the + * corresponding wdev's mutex. */ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); -/** - * __cfg80211_send_disassoc - notification of processed disassociation - * @dev: network device - * @buf: disassociation response frame (header + body) - * @len: length of the frame data - * - * Like cfg80211_send_disassoc(), but doesn't take the wdev lock. - */ -void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, - size_t len); - /** * cfg80211_send_unprot_deauth - notification of unprotected deauthentication * @dev: network device diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index eb4219051043..232edf78d5a9 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2318,7 +2318,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode old_req; int err; - lockdep_assert_held(&sdata->u.mgd.mtx); + lockdep_assert_held(&sdata->wdev.mtx); old_req = sdata->u.mgd.req_smps; sdata->u.mgd.req_smps = smps_mode; @@ -2375,9 +2375,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, local->dynamic_ps_forced_timeout = timeout; /* no change, but if automatic follow powersave */ - mutex_lock(&sdata->u.mgd.mtx); __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); - mutex_unlock(&sdata->u.mgd.mtx); if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index f83074fe6670..cafe614ef93d 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; - mutex_lock(&sdata->u.mgd.mtx); + sdata_lock(sdata); err = __ieee80211_request_smps(sdata, smps_mode); - mutex_unlock(&sdata->u.mgd.mtx); + sdata_unlock(sdata); return err; } @@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( case NL80211_IFTYPE_STATION: fc |= cpu_to_le16(IEEE80211_FCTL_TODS); /* BSSID SA DA */ - mutex_lock(&sdata->u.mgd.mtx); + sdata_lock(sdata); if (!sdata->u.mgd.associated) { - mutex_unlock(&sdata->u.mgd.mtx); + sdata_unlock(sdata); dev_kfree_skb(skb); return -ENOTCONN; } memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr->addr3, addr, ETH_ALEN); - mutex_unlock(&sdata->u.mgd.mtx); + sdata_unlock(sdata); break; default: dev_kfree_skb(skb); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index af8cee06e4f3..75dff338f581 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work) container_of(work, struct ieee80211_sub_if_data, u.mgd.request_smps_work); - mutex_lock(&sdata->u.mgd.mtx); + sdata_lock(sdata); __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); - mutex_unlock(&sdata->u.mgd.mtx); + sdata_unlock(sdata); } void ieee80211_request_smps(struct ieee80211_vif *vif, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 956ba6316da5..caa4b4f7f6e4 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct beacon_data *presp; int frame_len; - lockdep_assert_held(&ifibss->mtx); + sdata_assert_lock(sdata); /* Reset own TSF to allow time synchronization work. */ drv_reset_tsf(local, sdata); @@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, } presp = rcu_dereference_protected(ifibss->presp, - lockdep_is_held(&ifibss->mtx)); + lockdep_is_held(&sdata->wdev.mtx)); rcu_assign_pointer(ifibss->presp, NULL); if (presp) kfree_rcu(presp, rcu_head); @@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, const struct cfg80211_bss_ies *ies; u64 tsf; - lockdep_assert_held(&sdata->u.ibss.mtx); + sdata_assert_lock(sdata); if (beacon_int < 10) beacon_int = 10; @@ -410,7 +410,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, struct sta_info *sta; u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - lockdep_assert_held(&sdata->u.ibss.mtx); + sdata_assert_lock(sdata); if (len < 24 + 6) return; @@ -677,7 +677,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) int active = 0; struct sta_info *sta; - lockdep_assert_held(&sdata->u.ibss.mtx); + sdata_assert_lock(sdata); rcu_read_lock(); @@ -703,7 +703,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - lockdep_assert_held(&ifibss->mtx); + sdata_assert_lock(sdata); mod_timer(&ifibss->timer, round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); @@ -734,7 +734,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) u16 capability; int i; - lockdep_assert_held(&ifibss->mtx); + sdata_assert_lock(sdata); if (ifibss->fixed_bssid) { memcpy(bssid, ifibss->bssid, ETH_ALEN); @@ -777,7 +777,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) int active_ibss; u16 capability; - lockdep_assert_held(&ifibss->mtx); + sdata_assert_lock(sdata); active_ibss = ieee80211_sta_active_ibss(sdata); ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss); @@ -847,10 +847,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct beacon_data *presp; u8 *pos, *end; - lockdep_assert_held(&ifibss->mtx); + sdata_assert_lock(sdata); presp = rcu_dereference_protected(ifibss->presp, - lockdep_is_held(&ifibss->mtx)); + lockdep_is_held(&sdata->wdev.mtx)); if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || len < 24 + 2 || !presp) @@ -934,7 +934,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb->data; fc = le16_to_cpu(mgmt->frame_control); - mutex_lock(&sdata->u.ibss.mtx); + sdata_lock(sdata); if (!sdata->u.ibss.ssid_len) goto mgmt_out; /* not ready to merge yet */ @@ -957,7 +957,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, } mgmt_out: - mutex_unlock(&sdata->u.ibss.mtx); + sdata_unlock(sdata); } void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) @@ -965,7 +965,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct sta_info *sta; - mutex_lock(&ifibss->mtx); + sdata_lock(sdata); /* * Work could be scheduled after scan or similar @@ -1001,7 +1001,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) } out: - mutex_unlock(&ifibss->mtx); + sdata_unlock(sdata); } static void ieee80211_ibss_timer(unsigned long data) @@ -1018,7 +1018,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) setup_timer(&ifibss->timer, ieee80211_ibss_timer, (unsigned long) sdata); - mutex_init(&ifibss->mtx); INIT_LIST_HEAD(&ifibss->incomplete_stations); spin_lock_init(&ifibss->incomplete_lock); } @@ -1045,8 +1044,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, { u32 changed = 0; - mutex_lock(&sdata->u.ibss.mtx); - if (params->bssid) { memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); sdata->u.ibss.fixed_bssid = true; @@ -1079,8 +1076,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); sdata->u.ibss.ssid_len = params->ssid_len; - mutex_unlock(&sdata->u.ibss.mtx); - /* * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is * reserved, but an HT STA shall protect HT transmissions as though @@ -1116,8 +1111,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) struct sta_info *sta; struct beacon_data *presp; - mutex_lock(&sdata->u.ibss.mtx); - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1161,7 +1154,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) /* remove beacon */ kfree(sdata->u.ibss.ie); presp = rcu_dereference_protected(ifibss->presp, - lockdep_is_held(&sdata->u.ibss.mtx)); + lockdep_is_held(&sdata->wdev.mtx)); RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); sdata->vif.bss_conf.ibss_joined = false; sdata->vif.bss_conf.ibss_creator = false; @@ -1177,7 +1170,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.ibss.timer); - mutex_unlock(&sdata->u.ibss.mtx); - return 0; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ba3cd284d104..9eed6f1d1614 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -394,7 +394,6 @@ struct ieee80211_if_managed { bool nullfunc_failed; bool connection_loss; - struct mutex mtx; struct cfg80211_bss *associated; struct ieee80211_mgd_auth_data *auth_data; struct ieee80211_mgd_assoc_data *assoc_data; @@ -488,8 +487,6 @@ struct ieee80211_if_managed { struct ieee80211_if_ibss { struct timer_list timer; - struct mutex mtx; - unsigned long last_scan_completed; u32 basic_rates; @@ -580,8 +577,6 @@ struct ieee80211_if_mesh { bool accepting_plinks; int num_gates; struct beacon_data __rcu *beacon; - /* just protects beacon updates for now */ - struct mutex mtx; const u8 *ie; u8 ie_len; enum { @@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) return container_of(p, struct ieee80211_sub_if_data, vif); } +static inline void sdata_lock(struct ieee80211_sub_if_data *sdata) + __acquires(&sdata->wdev.mtx) +{ + mutex_lock(&sdata->wdev.mtx); + __acquire(&sdata->wdev.mtx); +} + +static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata) + __releases(&sdata->wdev.mtx) +{ + mutex_unlock(&sdata->wdev.mtx); + __release(&sdata->wdev.mtx); +} + +static inline void +sdata_assert_lock(struct ieee80211_sub_if_data *sdata) +{ + lockdep_assert_held(&sdata->wdev.mtx); +} + static inline enum ieee80211_band ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8a7bfc47d577..1998f1475267 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, return NOTIFY_DONE; ifmgd = &sdata->u.mgd; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); /* Copy the addresses to the bss_conf list */ ifa = idev->ifa_list; @@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_ARP_FILTER); - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); return NOTIFY_DONE; } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c14bb816c6a3..b3d1fdd46368 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -161,8 +161,11 @@ void mesh_sta_cleanup(struct sta_info *sta) del_timer_sync(&sta->plink_timer); } - if (changed) + if (changed) { + sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); + sdata_unlock(sdata); + } } int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) @@ -577,7 +580,9 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) mesh_path_expire(sdata); changed = mesh_accept_plinks_update(sdata); + sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); + sdata_unlock(sdata); mod_timer(&ifmsh->housekeeping_timer, round_jiffies(jiffies + @@ -697,25 +702,21 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) } static int -ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) +ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata) { struct beacon_data *old_bcn; int ret; - mutex_lock(&ifmsh->mtx); - - old_bcn = rcu_dereference_protected(ifmsh->beacon, - lockdep_is_held(&ifmsh->mtx)); - ret = ieee80211_mesh_build_beacon(ifmsh); + old_bcn = rcu_dereference_protected(sdata->u.mesh.beacon, + lockdep_is_held(&sdata->wdev.mtx)); + ret = ieee80211_mesh_build_beacon(&sdata->u.mesh); if (ret) /* just reuse old beacon */ - goto out; + return ret; if (old_bcn) kfree_rcu(old_bcn, rcu_head); -out: - mutex_unlock(&ifmsh->mtx); - return ret; + return 0; } void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, @@ -726,7 +727,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, BSS_CHANGED_HT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT))) - if (ieee80211_mesh_rebuild_beacon(&sdata->u.mesh)) + if (ieee80211_mesh_rebuild_beacon(sdata)) return; ieee80211_bss_info_change_notify(sdata, changed); } @@ -788,12 +789,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.enable_beacon = false; clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - mutex_lock(&ifmsh->mtx); + sdata_lock(sdata); bcn = rcu_dereference_protected(ifmsh->beacon, - lockdep_is_held(&ifmsh->mtx)); + lockdep_is_held(&sdata->wdev.mtx)); rcu_assign_pointer(ifmsh->beacon, NULL); kfree_rcu(bcn, rcu_head); - mutex_unlock(&ifmsh->mtx); + sdata_unlock(sdata); /* flush STAs and mpaths on this iface */ sta_info_flush(sdata); @@ -1041,7 +1042,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) spin_lock_init(&ifmsh->mesh_preq_queue_lock); spin_lock_init(&ifmsh->sync_offset_lock); RCU_INIT_POINTER(ifmsh->beacon, NULL); - mutex_init(&ifmsh->mtx); sdata->vif.bss_conf.bssid = zero_addr; } diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 09bebed99416..6c4da99bc4fb 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -517,7 +517,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, ieee80211_mps_frame_release(sta, elems); out: rcu_read_unlock(); + sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); + sdata_unlock(sdata); } static void mesh_plink_timer(unsigned long data) @@ -1068,6 +1070,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - if (changed) + if (changed) { + sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); + sdata_unlock(sdata); + } } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1da3d6be8e11..f44f4caa69ee 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -90,41 +90,6 @@ MODULE_PARM_DESC(probe_wait_ms, */ #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 -/* - * All cfg80211 functions have to be called outside a locked - * section so that they can acquire a lock themselves... This - * is much simpler than queuing up things in cfg80211, but we - * do need some indirection for that here. - */ -enum rx_mgmt_action { - /* no action required */ - RX_MGMT_NONE, - - /* caller must call cfg80211_send_deauth() */ - RX_MGMT_CFG80211_DEAUTH, - - /* caller must call cfg80211_send_disassoc() */ - RX_MGMT_CFG80211_DISASSOC, - - /* caller must call cfg80211_send_rx_auth() */ - RX_MGMT_CFG80211_RX_AUTH, - - /* caller must call cfg80211_send_rx_assoc() */ - RX_MGMT_CFG80211_RX_ASSOC, - - /* caller must call cfg80211_send_assoc_timeout() */ - RX_MGMT_CFG80211_ASSOC_TIMEOUT, - - /* used when a processed beacon causes a deauth */ - RX_MGMT_CFG80211_TX_DEAUTH, -}; - -/* utils */ -static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) -{ - lockdep_assert_held(&ifmgd->mtx); -} - /* * We can have multiple work items (and connection probing) * scheduling this timer, but we need to take care to only @@ -135,13 +100,14 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) * has happened -- the work that runs from this timer will * do that. */ -static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout) +static void run_again(struct ieee80211_sub_if_data *sdata, + unsigned long timeout) { - ASSERT_MGD_MTX(ifmgd); + sdata_assert_lock(sdata); - if (!timer_pending(&ifmgd->timer) || - time_before(timeout, ifmgd->timer.expires)) - mod_timer(&ifmgd->timer, timeout); + if (!timer_pending(&sdata->u.mgd.timer) || + time_before(timeout, sdata->u.mgd.timer.expires)) + mod_timer(&sdata->u.mgd.timer, timeout); } void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) @@ -652,7 +618,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) struct ieee80211_channel *chan; u32 rates = 0; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); @@ -962,7 +928,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) if (!ieee80211_sdata_running(sdata)) return; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (!ifmgd->associated) goto out; @@ -985,7 +951,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) IEEE80211_QUEUE_STOP_REASON_CSA); out: ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); } void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) @@ -1036,7 +1002,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, const struct ieee80211_ht_operation *ht_oper; int secondary_channel_offset = -1; - ASSERT_MGD_MTX(ifmgd); + sdata_assert_lock(sdata); if (!cbss) return; @@ -1845,7 +1811,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; u32 changed = 0; - ASSERT_MGD_MTX(ifmgd); + sdata_assert_lock(sdata); if (WARN_ON_ONCE(tx && !frame_buf)) return; @@ -2054,7 +2020,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) } ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); - run_again(ifmgd, ifmgd->probe_timeout); + run_again(sdata, ifmgd->probe_timeout); if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) ieee80211_flush_queues(sdata->local, sdata); } @@ -2068,7 +2034,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, if (!ieee80211_sdata_running(sdata)) return; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (!ifmgd->associated) goto out; @@ -2122,7 +2088,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, ifmgd->probe_send_count = 0; ieee80211_mgd_probe_ap_send(sdata); out: - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); } struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, @@ -2138,7 +2104,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) return NULL; - ASSERT_MGD_MTX(ifmgd); + sdata_assert_lock(sdata); if (ifmgd->associated) cbss = ifmgd->associated; @@ -2171,9 +2137,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (!ifmgd->associated) { - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); return; } @@ -2184,13 +2150,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA); - mutex_unlock(&ifmgd->mtx); - /* - * must be outside lock due to cfg80211, - * but that's not a problem. - */ cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + sdata_unlock(sdata); } static void ieee80211_beacon_connection_loss_work(struct work_struct *work) @@ -2257,7 +2219,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, { struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; - lockdep_assert_held(&sdata->u.mgd.mtx); + sdata_assert_lock(sdata); if (!assoc) { sta_info_destroy_addr(sdata, auth_data->bss->bssid); @@ -2298,27 +2260,26 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, auth_data->key_idx, tx_flags); } -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len) +static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 bssid[ETH_ALEN]; u16 auth_alg, auth_transaction, status_code; struct sta_info *sta; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); if (len < 24 + 6) - return RX_MGMT_NONE; + return; if (!ifmgd->auth_data || ifmgd->auth_data->done) - return RX_MGMT_NONE; + return; memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN); if (!ether_addr_equal(bssid, mgmt->bssid)) - return RX_MGMT_NONE; + return; auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); @@ -2330,14 +2291,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, mgmt->sa, auth_alg, ifmgd->auth_data->algorithm, auth_transaction, ifmgd->auth_data->expected_transaction); - return RX_MGMT_NONE; + return; } if (status_code != WLAN_STATUS_SUCCESS) { sdata_info(sdata, "%pM denied authentication (status %d)\n", mgmt->sa, status_code); ieee80211_destroy_auth_data(sdata, false); - return RX_MGMT_CFG80211_RX_AUTH; + cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + return; } switch (ifmgd->auth_data->algorithm) { @@ -2350,20 +2312,20 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, if (ifmgd->auth_data->expected_transaction != 4) { ieee80211_auth_challenge(sdata, mgmt, len); /* need another frame */ - return RX_MGMT_NONE; + return; } break; default: WARN_ONCE(1, "invalid auth alg %d", ifmgd->auth_data->algorithm); - return RX_MGMT_NONE; + return; } sdata_info(sdata, "authenticated\n"); ifmgd->auth_data->done = true; ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; ifmgd->auth_data->timeout_started = true; - run_again(ifmgd, ifmgd->auth_data->timeout); + run_again(sdata, ifmgd->auth_data->timeout); if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && ifmgd->auth_data->expected_transaction != 2) { @@ -2371,7 +2333,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, * Report auth frame to user space for processing since another * round of Authentication frames is still needed. */ - return RX_MGMT_CFG80211_RX_AUTH; + cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + return; } /* move station state to auth */ @@ -2387,30 +2350,29 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, } mutex_unlock(&sdata->local->sta_mtx); - return RX_MGMT_CFG80211_RX_AUTH; + cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + return; out_err: mutex_unlock(&sdata->local->sta_mtx); /* ignore frame -- wait for timeout */ - return RX_MGMT_NONE; } -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len) +static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; const u8 *bssid = NULL; u16 reason_code; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); if (len < 24 + 2) - return RX_MGMT_NONE; + return; if (!ifmgd->associated || !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) - return RX_MGMT_NONE; + return; bssid = ifmgd->associated->bssid; @@ -2421,25 +2383,24 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - return RX_MGMT_CFG80211_DEAUTH; + cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len); } -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len) +static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u16 reason_code; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); if (len < 24 + 2) - return RX_MGMT_NONE; + return; if (!ifmgd->associated || !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) - return RX_MGMT_NONE; + return; reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); @@ -2448,7 +2409,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - return RX_MGMT_CFG80211_DISASSOC; + cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len); } static void ieee80211_get_rates(struct ieee80211_supported_band *sband, @@ -2498,7 +2459,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, { struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; - lockdep_assert_held(&sdata->u.mgd.mtx); + sdata_assert_lock(sdata); if (!assoc) { sta_info_destroy_addr(sdata, assoc_data->bss->bssid); @@ -2679,10 +2640,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, return true; } -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len, - struct cfg80211_bss **bss) +static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; @@ -2690,13 +2650,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems elems; u8 *pos; bool reassoc; + struct cfg80211_bss *bss; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); if (!assoc_data) - return RX_MGMT_NONE; + return; if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid)) - return RX_MGMT_NONE; + return; /* * AssocResp and ReassocResp have identical structure, so process both @@ -2704,7 +2665,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, */ if (len < 24 + 6) - return RX_MGMT_NONE; + return; reassoc = ieee80211_is_reassoc_req(mgmt->frame_control); capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); @@ -2731,22 +2692,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, assoc_data->timeout = jiffies + msecs_to_jiffies(ms); assoc_data->timeout_started = true; if (ms > IEEE80211_ASSOC_TIMEOUT) - run_again(ifmgd, assoc_data->timeout); - return RX_MGMT_NONE; + run_again(sdata, assoc_data->timeout); + return; } - *bss = assoc_data->bss; + bss = assoc_data->bss; if (status_code != WLAN_STATUS_SUCCESS) { sdata_info(sdata, "%pM denied association (code=%d)\n", mgmt->sa, status_code); ieee80211_destroy_assoc_data(sdata, false); } else { - if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { + if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ ieee80211_destroy_assoc_data(sdata, false); - cfg80211_put_bss(sdata->local->hw.wiphy, *bss); - return RX_MGMT_CFG80211_ASSOC_TIMEOUT; + cfg80211_put_bss(sdata->local->hw.wiphy, bss); + cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); + return; } sdata_info(sdata, "associated\n"); @@ -2758,7 +2720,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_destroy_assoc_data(sdata, true); } - return RX_MGMT_CFG80211_RX_ASSOC; + cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -2772,7 +2734,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; bool need_ps = false; - lockdep_assert_held(&sdata->u.mgd.mtx); + sdata_assert_lock(sdata); if ((sdata->u.mgd.associated && ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || @@ -2831,7 +2793,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ifmgd = &sdata->u.mgd; - ASSERT_MGD_MTX(ifmgd); + sdata_assert_lock(sdata); if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) return; /* ignore ProbeResp to foreign address */ @@ -2856,7 +2818,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ifmgd->auth_data->tries = 0; ifmgd->auth_data->timeout = jiffies; ifmgd->auth_data->timeout_started = true; - run_again(ifmgd, ifmgd->auth_data->timeout); + run_again(sdata, ifmgd->auth_data->timeout); } } @@ -2881,10 +2843,9 @@ static const u64 care_about_ies = (1ULL << WLAN_EID_HT_CAPABILITY) | (1ULL << WLAN_EID_HT_OPERATION); -static enum rx_mgmt_action -ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, size_t len, - u8 *deauth_buf, struct ieee80211_rx_status *rx_status) +static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len, + struct ieee80211_rx_status *rx_status) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; @@ -2899,24 +2860,25 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, u8 erp_value = 0; u32 ncrc; u8 *bssid; + u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); /* Process beacon from the current BSS */ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; if (baselen > len) - return RX_MGMT_NONE; + return; rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); if (!chanctx_conf) { rcu_read_unlock(); - return RX_MGMT_NONE; + return; } if (rx_status->freq != chanctx_conf->def.chan->center_freq) { rcu_read_unlock(); - return RX_MGMT_NONE; + return; } chan = chanctx_conf->def.chan; rcu_read_unlock(); @@ -2943,13 +2905,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, /* continue assoc process */ ifmgd->assoc_data->timeout = jiffies; ifmgd->assoc_data->timeout_started = true; - run_again(ifmgd, ifmgd->assoc_data->timeout); - return RX_MGMT_NONE; + run_again(sdata, ifmgd->assoc_data->timeout); + return; } if (!ifmgd->associated || !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) - return RX_MGMT_NONE; + return; bssid = ifmgd->associated->bssid; /* Track average RSSI from the Beacon frames of the current AP */ @@ -3095,7 +3057,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, } if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) - return RX_MGMT_NONE; + return; ifmgd->beacon_crc = ncrc; ifmgd->beacon_crc_valid = true; @@ -3151,7 +3113,9 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DEAUTH_LEAVING, true, deauth_buf); - return RX_MGMT_CFG80211_TX_DEAUTH; + cfg80211_send_deauth(sdata->dev, deauth_buf, + sizeof(deauth_buf)); + return; } if (sta && elems.opmode_notif) @@ -3168,19 +3132,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, elems.pwr_constr_elem); ieee80211_bss_info_change_notify(sdata, changed); - - return RX_MGMT_NONE; } void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; - struct cfg80211_bss *bss = NULL; - enum rx_mgmt_action rma = RX_MGMT_NONE; - u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN]; u16 fc; struct ieee802_11_elems elems; int ies_len; @@ -3189,28 +3147,27 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb->data; fc = le16_to_cpu(mgmt->frame_control); - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_BEACON: - rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, - deauth_buf, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_PROBE_RESP: ieee80211_rx_mgmt_probe_resp(sdata, skb); break; case IEEE80211_STYPE_AUTH: - rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len); + ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_DEAUTH: - rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); + ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_DISASSOC: - rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); + ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: - rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss); + ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) { @@ -3256,34 +3213,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, } break; } - mutex_unlock(&ifmgd->mtx); - - switch (rma) { - case RX_MGMT_NONE: - /* no action */ - break; - case RX_MGMT_CFG80211_DEAUTH: - cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_DISASSOC: - cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_RX_AUTH: - cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_RX_ASSOC: - cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_ASSOC_TIMEOUT: - cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); - break; - case RX_MGMT_CFG80211_TX_DEAUTH: - cfg80211_send_deauth(sdata->dev, deauth_buf, - sizeof(deauth_buf)); - break; - default: - WARN(1, "unexpected: %d", rma); - } + sdata_unlock(sdata); } static void ieee80211_sta_timer(unsigned long data) @@ -3297,20 +3227,12 @@ static void ieee80211_sta_timer(unsigned long data) static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, u8 *bssid, u8 reason, bool tx) { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, tx, frame_buf); - mutex_unlock(&ifmgd->mtx); - /* - * must be outside lock due to cfg80211, - * but that's not a problem. - */ cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); - - mutex_lock(&ifmgd->mtx); } static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) @@ -3320,7 +3242,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; u32 tx_flags = 0; - lockdep_assert_held(&ifmgd->mtx); + sdata_assert_lock(sdata); if (WARN_ON_ONCE(!auth_data)) return -EINVAL; @@ -3393,7 +3315,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) if (tx_flags == 0) { auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; ifmgd->auth_data->timeout_started = true; - run_again(ifmgd, auth_data->timeout); + run_again(sdata, auth_data->timeout); } else { auth_data->timeout_started = false; } @@ -3406,7 +3328,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; struct ieee80211_local *local = sdata->local; - lockdep_assert_held(&sdata->u.mgd.mtx); + sdata_assert_lock(sdata); assoc_data->tries++; if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { @@ -3430,7 +3352,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; assoc_data->timeout_started = true; - run_again(&sdata->u.mgd, assoc_data->timeout); + run_again(sdata, assoc_data->timeout); } else { assoc_data->timeout_started = false; } @@ -3455,7 +3377,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (ifmgd->status_received) { __le16 fc = ifmgd->status_fc; @@ -3467,7 +3389,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (status_acked) { ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->auth_data->timeout); + run_again(sdata, ifmgd->auth_data->timeout); } else { ifmgd->auth_data->timeout = jiffies - 1; } @@ -3478,7 +3400,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (status_acked) { ifmgd->assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->assoc_data->timeout); + run_again(sdata, ifmgd->assoc_data->timeout); } else { ifmgd->assoc_data->timeout = jiffies - 1; } @@ -3501,12 +3423,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ieee80211_destroy_auth_data(sdata, false); - mutex_unlock(&ifmgd->mtx); cfg80211_send_auth_timeout(sdata->dev, bssid); - mutex_lock(&ifmgd->mtx); } } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started) - run_again(ifmgd, ifmgd->auth_data->timeout); + run_again(sdata, ifmgd->auth_data->timeout); if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started && time_after(jiffies, ifmgd->assoc_data->timeout)) { @@ -3519,12 +3439,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ieee80211_destroy_assoc_data(sdata, false); - mutex_unlock(&ifmgd->mtx); cfg80211_send_assoc_timeout(sdata->dev, bssid); - mutex_lock(&ifmgd->mtx); } } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) - run_again(ifmgd, ifmgd->assoc_data->timeout); + run_again(sdata, ifmgd->assoc_data->timeout); if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL) && @@ -3558,7 +3476,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) false); } } else if (time_is_after_jiffies(ifmgd->probe_timeout)) - run_again(ifmgd, ifmgd->probe_timeout); + run_again(sdata, ifmgd->probe_timeout); else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { mlme_dbg(sdata, "Failed to send nullfunc to AP %pM after %dms, disconnecting\n", @@ -3587,7 +3505,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) } } - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); } static void ieee80211_sta_bcn_mon_timer(unsigned long data) @@ -3648,9 +3566,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (!ifmgd->associated) { - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); return; } @@ -3661,10 +3579,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) ifmgd->associated->bssid, WLAN_REASON_UNSPECIFIED, true); - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); return; } - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); } #endif @@ -3696,8 +3614,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len; ifmgd->p2p_noa_index = -1; - mutex_init(&ifmgd->mtx); - if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; else @@ -4053,8 +3969,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, /* try to authenticate/probe */ - mutex_lock(&ifmgd->mtx); - if ((ifmgd->auth_data && !ifmgd->auth_data->done) || ifmgd->assoc_data) { err = -EBUSY; @@ -4074,8 +3988,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, WLAN_REASON_UNSPECIFIED, false, frame_buf); - __cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); + cfg80211_send_deauth(sdata->dev, frame_buf, + sizeof(frame_buf)); } sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); @@ -4092,8 +4006,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, /* hold our own reference */ cfg80211_ref_bss(local->hw.wiphy, auth_data->bss); - err = 0; - goto out_unlock; + return 0; err_clear: memset(ifmgd->bssid, 0, ETH_ALEN); @@ -4101,9 +4014,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, ifmgd->auth_data = NULL; err_free: kfree(auth_data); - out_unlock: - mutex_unlock(&ifmgd->mtx); - return err; } @@ -4134,8 +4044,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, assoc_data->ssid_len = ssidie[1]; rcu_read_unlock(); - mutex_lock(&ifmgd->mtx); - if (ifmgd->associated) { u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; @@ -4143,8 +4051,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, WLAN_REASON_UNSPECIFIED, false, frame_buf); - __cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); + cfg80211_send_deauth(sdata->dev, frame_buf, + sizeof(frame_buf)); } if (ifmgd->auth_data && !ifmgd->auth_data->done) { @@ -4338,7 +4246,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } rcu_read_unlock(); - run_again(ifmgd, assoc_data->timeout); + run_again(sdata, assoc_data->timeout); if (bss->corrupt_data) { char *corrupt_type = "data"; @@ -4354,17 +4262,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, corrupt_type); } - err = 0; - goto out; + return 0; err_clear: memset(ifmgd->bssid, 0, ETH_ALEN); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; err_free: kfree(assoc_data); - out: - mutex_unlock(&ifmgd->mtx); - return err; } @@ -4376,8 +4280,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, bool tx = !req->local_state_change; bool report_frame = false; - mutex_lock(&ifmgd->mtx); - sdata_info(sdata, "deauthenticating from %pM by local choice (reason=%d)\n", req->bssid, req->reason_code); @@ -4389,7 +4291,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, req->reason_code, tx, frame_buf); ieee80211_destroy_auth_data(sdata, false); - mutex_unlock(&ifmgd->mtx); report_frame = true; goto out; @@ -4401,12 +4302,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, req->reason_code, tx, frame_buf); report_frame = true; } - mutex_unlock(&ifmgd->mtx); out: if (report_frame) - __cfg80211_send_deauth(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_send_deauth(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); return 0; } @@ -4418,18 +4318,14 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, u8 bssid[ETH_ALEN]; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; - mutex_lock(&ifmgd->mtx); - /* * cfg80211 should catch this ... but it's racy since * we can receive a disassoc frame, process it, hand it * to cfg80211 while that's in a locked section already * trying to tell us that the user wants to disconnect. */ - if (ifmgd->associated != req->bss) { - mutex_unlock(&ifmgd->mtx); + if (ifmgd->associated != req->bss) return -ENOLINK; - } sdata_info(sdata, "disassociating from %pM by local choice (reason=%d)\n", @@ -4439,10 +4335,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, req->reason_code, !req->local_state_change, frame_buf); - mutex_unlock(&ifmgd->mtx); - __cfg80211_send_disassoc(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_send_disassoc(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); return 0; } @@ -4462,13 +4357,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) cancel_work_sync(&ifmgd->csa_connection_drop_work); cancel_work_sync(&ifmgd->chswitch_work); - mutex_lock(&ifmgd->mtx); + sdata_lock(sdata); if (ifmgd->assoc_data) ieee80211_destroy_assoc_data(sdata, false); if (ifmgd->auth_data) ieee80211_destroy_auth_data(sdata, false); del_timer_sync(&ifmgd->timer); - mutex_unlock(&ifmgd->mtx); + sdata_unlock(sdata); } void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ffdfe4bc89ad..2a8d759324c2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1581,9 +1581,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (sdata->u.mgd.dtim_period) changed |= BSS_CHANGED_DTIM_PERIOD; - mutex_lock(&sdata->u.mgd.mtx); + sdata_lock(sdata); ieee80211_bss_info_change_notify(sdata, changed); - mutex_unlock(&sdata->u.mgd.mtx); + sdata_unlock(sdata); break; case NL80211_IFTYPE_ADHOC: changed |= BSS_CHANGED_IBSS; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 68b40f21bc38..80ffb0138919 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); trace_cfg80211_send_rx_auth(dev); - wdev_lock(wdev); nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); cfg80211_sme_rx_auth(dev, buf, len); - - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_rx_auth); @@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); trace_cfg80211_send_rx_assoc(dev, bss); - wdev_lock(wdev); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); @@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && cfg80211_sme_failed_reassoc(wdev)) { cfg80211_put_bss(wiphy, bss); - goto out; + return; } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); @@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, * sme will schedule work that does it later. */ cfg80211_put_bss(wiphy, bss); - goto out; + return; } if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { @@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, status_code == WLAN_STATUS_SUCCESS, bss); - out: - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_rx_assoc); -void __cfg80211_send_deauth(struct net_device *dev, - const u8 *buf, size_t len) +void cfg80211_send_deauth(struct net_device *dev, + const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *bssid = mgmt->bssid; bool was_current = false; - trace___cfg80211_send_deauth(dev); + trace_cfg80211_send_deauth(dev); ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && @@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev, false, NULL); } } -EXPORT_SYMBOL(__cfg80211_send_deauth); - -void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - - wdev_lock(wdev); - __cfg80211_send_deauth(dev, buf, len); - wdev_unlock(wdev); -} EXPORT_SYMBOL(cfg80211_send_deauth); -void __cfg80211_send_disassoc(struct net_device *dev, - const u8 *buf, size_t len) +void cfg80211_send_disassoc(struct net_device *dev, + const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, u16 reason_code; bool from_ap; - trace___cfg80211_send_disassoc(dev); + trace_cfg80211_send_disassoc(dev); ASSERT_WDEV_LOCK(wdev); nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); @@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev, from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } -EXPORT_SYMBOL(__cfg80211_send_disassoc); - -void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - - wdev_lock(wdev); - __cfg80211_send_disassoc(dev, buf, len); - wdev_unlock(wdev); -} EXPORT_SYMBOL(cfg80211_send_disassoc); void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) @@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); trace_cfg80211_send_auth_timeout(dev, addr); - wdev_lock(wdev); nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTING) __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_auth_timeout); @@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); trace_cfg80211_send_assoc_timeout(dev, addr); - wdev_lock(wdev); nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); if (wdev->sme_state == CFG80211_SME_CONNECTING) __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); - - wdev_unlock(wdev); } EXPORT_SYMBOL(cfg80211_send_assoc_timeout); diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 5755bc14abbd..23fafeae8a10 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1911,12 +1911,12 @@ TRACE_EVENT(cfg80211_send_rx_assoc, NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) ); -DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth, +DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth, TP_PROTO(struct net_device *netdev), TP_ARGS(netdev) ); -DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc, +DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc, TP_PROTO(struct net_device *netdev), TP_ARGS(netdev) ); -- GitLab From 1cdd59ce8dcfa850ebb8ac2ab000a2ea572d1d69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 May 2013 18:58:00 +0200 Subject: [PATCH 0329/2900] cfg80211: simplify and correct P2P-Device scan check If the driver for some reason successfully finishes scanning while in p2p_stop_device(), cfg80211 will still set it to aborted. Simplify this code using the new 'notified' value and only mark it aborted in case the driver didn't notify cfg80211 at all (in which case we also leak the request to not crash, this is a driver bug.) Signed-off-by: Johannes Berg --- net/wireless/core.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 5fc642d4071b..afcb9ec70adb 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -204,18 +204,15 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, rdev->opencount--; if (rdev->scan_req && rdev->scan_req->wdev == wdev) { - bool busy = work_busy(&rdev->scan_done_wk); - /* - * If the work isn't pending or running (in which case it would - * be waiting for the lock we hold) the driver didn't properly - * cancel the scan when the interface was removed. In this case - * warn and leak the scan request object to not crash later. + * If the scan request wasn't notified as done, set it + * to aborted and leak it after a warning. The driver + * should have notified us that it ended at the latest + * during rdev_stop_p2p_device(). */ - WARN_ON(!busy); - - rdev->scan_req->aborted = true; - ___cfg80211_scan_done(rdev, !busy); + if (WARN_ON(!rdev->scan_req->notified)) + rdev->scan_req->aborted = true; + ___cfg80211_scan_done(rdev, !rdev->scan_req->notified); } } -- GitLab From db2424c58e5962a87888d25d29ceb0873eef6348 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 May 2013 19:07:52 +0200 Subject: [PATCH 0330/2900] regulatory: use RCU in regulatory_hint_11d() Since it just does a quick check of the last regulatory request, the function doesn't have to hold the reg mutex but can use RCU instead. Signed-off-by: Johannes Berg --- net/wireless/reg.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e76559618588..17e5eccb42c8 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1715,20 +1715,18 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, { char alpha2[2]; enum environment_cap env = ENVIRON_ANY; - struct regulatory_request *request, *lr; - - mutex_lock(®_mutex); - lr = get_last_request(); - - if (unlikely(!lr)) - goto out; + struct regulatory_request *request = NULL, *lr; /* IE len must be evenly divisible by 2 */ if (country_ie_len & 0x01) - goto out; + return; if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) - goto out; + return; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return; alpha2[0] = country_ie[0]; alpha2[1] = country_ie[1]; @@ -1738,6 +1736,12 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, else if (country_ie[2] == 'O') env = ENVIRON_OUTDOOR; + rcu_read_lock(); + lr = get_last_request(); + + if (unlikely(!lr)) + goto out; + /* * We will run this only upon a successful connection on cfg80211. * We leave conflict resolution to the workqueue, where can hold @@ -1747,10 +1751,6 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, lr->wiphy_idx != WIPHY_IDX_INVALID) goto out; - request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); - if (!request) - goto out; - request->wiphy_idx = get_wiphy_idx(wiphy); request->alpha2[0] = alpha2[0]; request->alpha2[1] = alpha2[1]; @@ -1758,8 +1758,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, request->country_ie_env = env; queue_regulatory_request(request); + request = NULL; out: - mutex_unlock(®_mutex); + kfree(request); + rcu_read_unlock(); } static void restore_alpha2(char *alpha2, bool reset_user) -- GitLab From 38fd2143fa653f80729800c1d61d4207b91dca42 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 May 2013 19:17:17 +0200 Subject: [PATCH 0331/2900] regulatory: remove reg_mutex The reg_mutex is similar to the ones I just removed in cfg80211 but even less useful since it protects global data, and we hold the RTNL in all places (except module unload) already. Signed-off-by: Johannes Berg --- net/wireless/reg.c | 76 ++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 57 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 17e5eccb42c8..e1d6749234c6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -81,7 +81,10 @@ static struct regulatory_request core_request_world = { .country_ie_env = ENVIRON_ANY, }; -/* Receipt of information from last regulatory request */ +/* + * Receipt of information from last regulatory request, + * protected by RTNL (and can be accessed with RCU protection) + */ static struct regulatory_request __rcu *last_request = (void __rcu *)&core_request_world; @@ -96,39 +99,25 @@ static struct device_type reg_device_type = { * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no * information to give us an alpha2. + * (protected by RTNL, can be read under RCU) */ const struct ieee80211_regdomain __rcu *cfg80211_regdomain; -/* - * Protects static reg.c components: - * - cfg80211_regdomain (if not used with RCU) - * - cfg80211_world_regdom - * - last_request (if not used with RCU) - * - reg_num_devs_support_basehint - */ -static DEFINE_MUTEX(reg_mutex); - /* * Number of devices that registered to the core * that support cellular base station regulatory hints + * (protected by RTNL) */ static int reg_num_devs_support_basehint; -static inline void assert_reg_lock(void) -{ - lockdep_assert_held(®_mutex); -} - static const struct ieee80211_regdomain *get_cfg80211_regdom(void) { - return rcu_dereference_protected(cfg80211_regdomain, - lockdep_is_held(®_mutex)); + return rtnl_dereference(cfg80211_regdomain); } static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) { - return rcu_dereference_protected(wiphy->regd, - lockdep_is_held(®_mutex)); + return rtnl_dereference(wiphy->regd); } static void rcu_free_regdom(const struct ieee80211_regdomain *r) @@ -140,8 +129,7 @@ static void rcu_free_regdom(const struct ieee80211_regdomain *r) static struct regulatory_request *get_last_request(void) { - return rcu_dereference_check(last_request, - lockdep_is_held(®_mutex)); + return rcu_dereference_rtnl(last_request); } /* Used to queue up regulatory hints */ @@ -200,6 +188,7 @@ static const struct ieee80211_regdomain world_regdom = { } }; +/* protected by RTNL */ static const struct ieee80211_regdomain *cfg80211_world_regdom = &world_regdom; @@ -215,7 +204,7 @@ static void reset_regdomains(bool full_reset, const struct ieee80211_regdomain *r; struct regulatory_request *lr; - assert_reg_lock(); + ASSERT_RTNL(); r = get_cfg80211_regdom(); @@ -936,13 +925,7 @@ static bool reg_request_cell_base(struct regulatory_request *request) bool reg_last_request_cell_base(void) { - bool val; - - mutex_lock(®_mutex); - val = reg_request_cell_base(get_last_request()); - mutex_unlock(®_mutex); - - return val; + return reg_request_cell_base(get_last_request()); } #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS @@ -1444,8 +1427,6 @@ static void reg_set_request_processed(void) * what it believes should be the current regulatory domain. * * Returns one of the different reg request treatment values. - * - * Caller must hold ®_mutex */ static enum reg_request_treatment __regulatory_hint(struct wiphy *wiphy, @@ -1622,10 +1603,8 @@ static void reg_process_pending_beacon_hints(void) static void reg_todo(struct work_struct *work) { rtnl_lock(); - mutex_lock(®_mutex); reg_process_pending_hints(); reg_process_pending_beacon_hints(); - mutex_unlock(®_mutex); rtnl_unlock(); } @@ -1851,8 +1830,6 @@ static void restore_regulatory_settings(bool reset_user) ASSERT_RTNL(); - mutex_lock(®_mutex); - reset_regdomains(true, &world_regdom); restore_alpha2(alpha2, reset_user); @@ -1906,8 +1883,6 @@ static void restore_regulatory_settings(bool reset_user) list_splice_tail_init(&tmp_reg_req_list, ®_requests_list); spin_unlock(®_requests_lock); - mutex_unlock(®_mutex); - REG_DBG_PRINT("Kicking the queue\n"); schedule_work(®_work); @@ -2222,7 +2197,6 @@ int set_regdom(const struct ieee80211_regdomain *rd) struct regulatory_request *lr; int r; - mutex_lock(®_mutex); lr = get_last_request(); /* Note that this doesn't update the wiphys, this is done below */ @@ -2232,14 +2206,12 @@ int set_regdom(const struct ieee80211_regdomain *rd) reg_set_request_processed(); kfree(rd); - goto out; + return r; } /* This would make this whole thing pointless */ - if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) { - r = -EINVAL; - goto out; - } + if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) + return -EINVAL; /* update all wiphys now with the new established regulatory domain */ update_all_wiphy_regulatory(lr->initiator); @@ -2250,10 +2222,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) reg_set_request_processed(); - out: - mutex_unlock(®_mutex); - - return r; + return 0; } int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) @@ -2278,14 +2247,10 @@ int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) void wiphy_regulatory_register(struct wiphy *wiphy) { - mutex_lock(®_mutex); - if (!reg_dev_ignore_cell_hint(wiphy)) reg_num_devs_support_basehint++; wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); - - mutex_unlock(®_mutex); } void wiphy_regulatory_deregister(struct wiphy *wiphy) @@ -2293,7 +2258,6 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) struct wiphy *request_wiphy = NULL; struct regulatory_request *lr; - mutex_lock(®_mutex); lr = get_last_request(); if (!reg_dev_ignore_cell_hint(wiphy)) @@ -2306,12 +2270,10 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy) request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); if (!request_wiphy || request_wiphy != wiphy) - goto out; + return; lr->wiphy_idx = WIPHY_IDX_INVALID; lr->country_ie_env = ENVIRON_ANY; -out: - mutex_unlock(®_mutex); } static void reg_timeout_work(struct work_struct *work) @@ -2375,9 +2337,9 @@ void regulatory_exit(void) cancel_delayed_work_sync(®_timeout); /* Lock to suppress warnings */ - mutex_lock(®_mutex); + rtnl_lock(); reset_regdomains(true, NULL); - mutex_unlock(®_mutex); + rtnl_unlock(); dev_set_uevent_suppress(®_pdev->dev, true); -- GitLab From 91bf9b26fc95c505846bc2f744a73b51f2aaee1d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 17:44:01 +0200 Subject: [PATCH 0332/2900] cfg80211: remove some locked wrappers from mlme API By making all the API functions require wdev locking we can clean up the API a bit, getting rid of the locking version of each function. This also decreases the size of cfg80211 by a small amount. Signed-off-by: Johannes Berg --- net/wireless/core.h | 25 ++------- net/wireless/mlme.c | 120 ++++++++--------------------------------- net/wireless/nl80211.c | 34 ++++++++---- net/wireless/sme.c | 40 +++++++------- 4 files changed, 70 insertions(+), 149 deletions(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index d21a0fc01401..c8f87dfd50d3 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -282,38 +282,21 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, struct net_device *dev); /* MLME */ -int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_auth_type auth_type, - const u8 *bssid, - const u8 *ssid, int ssid_len, - const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - const u8 *sae_data, int sae_data_len); int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, - struct net_device *dev, struct ieee80211_channel *chan, - enum nl80211_auth_type auth_type, const u8 *bssid, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_auth_type auth_type, + const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, const u8 *key, int key_len, int key_idx, const u8 *sae_data, int sae_data_len); -int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - const u8 *bssid, - const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req); int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, const u8 *bssid, const u8 *ssid, int ssid_len, struct cfg80211_assoc_request *req); -int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason, - bool local_state_change); int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *bssid, const u8 *ie, int ie_len, u16 reason, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 80ffb0138919..7bde5d9c0003 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -221,15 +221,15 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, EXPORT_SYMBOL(cfg80211_michael_mic_failure); /* some MLME handling for userspace SME */ -int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_auth_type auth_type, - const u8 *bssid, - const u8 *ssid, int ssid_len, - const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - const u8 *sae_data, int sae_data_len) +int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_auth_type auth_type, + const u8 *bssid, + const u8 *ssid, int ssid_len, + const u8 *ie, int ie_len, + const u8 *key, int key_len, int key_idx, + const u8 *sae_data, int sae_data_len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req = { @@ -271,28 +271,6 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, return err; } -int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, - struct net_device *dev, struct ieee80211_channel *chan, - enum nl80211_auth_type auth_type, const u8 *bssid, - const u8 *ssid, int ssid_len, - const u8 *ie, int ie_len, - const u8 *key, int key_len, int key_idx, - const u8 *sae_data, int sae_data_len) -{ - int err; - - ASSERT_RTNL(); - - wdev_lock(dev->ieee80211_ptr); - err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, - ssid, ssid_len, ie, ie_len, - key, key_len, key_idx, - sae_data, sae_data_len); - wdev_unlock(dev->ieee80211_ptr); - - return err; -} - /* Do a logical ht_capa &= ht_capa_mask. */ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, const struct ieee80211_ht_cap *ht_capa_mask) @@ -327,12 +305,12 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, p1[i] &= p2[i]; } -int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - const u8 *bssid, - const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req) +int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + const u8 *bssid, + const u8 *ssid, int ssid_len, + struct cfg80211_assoc_request *req) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; @@ -382,30 +360,10 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, return err; } -int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct ieee80211_channel *chan, - const u8 *bssid, - const u8 *ssid, int ssid_len, - struct cfg80211_assoc_request *req) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; - - ASSERT_RTNL(); - - wdev_lock(wdev); - err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, - ssid, ssid_len, req); - wdev_unlock(wdev); - - return err; -} - -int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason, - bool local_state_change) +int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *bssid, + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_deauth_request req = { @@ -425,26 +383,10 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, return rdev_deauth(rdev, dev, &req); } -int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason, - bool local_state_change) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; - - wdev_lock(wdev); - err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, - local_state_change); - wdev_unlock(wdev); - - return err; -} - -static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason, - bool local_state_change) +int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *bssid, + const u8 *ie, int ie_len, u16 reason, + bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_disassoc_request req = { @@ -470,22 +412,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, return rdev_disassoc(rdev, dev, &req); } -int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, - struct net_device *dev, const u8 *bssid, - const u8 *ie, int ie_len, u16 reason, - bool local_state_change) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - int err; - - wdev_lock(wdev); - err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, - local_state_change); - wdev_unlock(wdev); - - return err; -} - void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, struct net_device *dev) { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 74cdb1a0cf31..49c2f2f511dc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5904,10 +5904,13 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) if (local_state_change) return 0; - return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, - ssid, ssid_len, ie, ie_len, - key.p.key, key.p.key_len, key.idx, - sae_data, sae_data_len); + wdev_lock(dev->ieee80211_ptr); + err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, + ssid, ssid_len, ie, ie_len, + key.p.key, key.p.key_len, key.idx, + sae_data, sae_data_len); + wdev_unlock(dev->ieee80211_ptr); + return err; } static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, @@ -6074,9 +6077,12 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) } err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); - if (!err) + if (!err) { + wdev_lock(dev->ieee80211_ptr); err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, ssid, ssid_len, &req); + wdev_unlock(dev->ieee80211_ptr); + } return err; } @@ -6086,7 +6092,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; const u8 *ie = NULL, *bssid; - int ie_len = 0; + int ie_len = 0, err; u16 reason_code; bool local_state_change; @@ -6121,8 +6127,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; - return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, - local_state_change); + wdev_lock(dev->ieee80211_ptr); + err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, + local_state_change); + wdev_unlock(dev->ieee80211_ptr); + return err; } static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) @@ -6130,7 +6139,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; const u8 *ie = NULL, *bssid; - int ie_len = 0; + int ie_len = 0, err; u16 reason_code; bool local_state_change; @@ -6165,8 +6174,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; - return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, - local_state_change); + wdev_lock(dev->ieee80211_ptr); + err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, + local_state_change); + wdev_unlock(dev->ieee80211_ptr); + return err; } static bool diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 4dbf31407a56..31d67add7424 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -169,13 +169,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) case CFG80211_CONN_AUTHENTICATE_NEXT: BUG_ON(!rdev->ops->auth); wdev->conn->state = CFG80211_CONN_AUTHENTICATING; - return __cfg80211_mlme_auth(rdev, wdev->netdev, - params->channel, params->auth_type, - params->bssid, - params->ssid, params->ssid_len, - NULL, 0, - params->key, params->key_len, - params->key_idx, NULL, 0); + return cfg80211_mlme_auth(rdev, wdev->netdev, + params->channel, params->auth_type, + params->bssid, + params->ssid, params->ssid_len, + NULL, 0, + params->key, params->key_len, + params->key_idx, NULL, 0); case CFG80211_CONN_ASSOCIATE_NEXT: BUG_ON(!rdev->ops->assoc); wdev->conn->state = CFG80211_CONN_ASSOCIATING; @@ -191,19 +191,19 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) req.vht_capa = params->vht_capa; req.vht_capa_mask = params->vht_capa_mask; - err = __cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, - params->bssid, params->ssid, - params->ssid_len, &req); + err = cfg80211_mlme_assoc(rdev, wdev->netdev, params->channel, + params->bssid, params->ssid, + params->ssid_len, &req); if (err) - __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, - NULL, 0, - WLAN_REASON_DEAUTH_LEAVING, - false); + cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, + NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, + false); return err; case CFG80211_CONN_DEAUTH_ASSOC_FAIL: - __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, - NULL, 0, - WLAN_REASON_DEAUTH_LEAVING, false); + cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, + NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, false); /* return an error so that we call __cfg80211_connect_result() */ return -EINVAL; default: @@ -961,7 +961,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, } /* wdev->conn->params.bssid must be set if > SCANNING */ - err = __cfg80211_mlme_deauth(rdev, dev, + err = cfg80211_mlme_deauth(rdev, dev, wdev->conn->params.bssid, NULL, 0, reason, false); if (err) @@ -1018,6 +1018,6 @@ void cfg80211_sme_disassoc(struct net_device *dev, memcpy(bssid, bss->pub.bssid, ETH_ALEN); - __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING, false); + cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, false); } -- GitLab From 83739b03de97049181d711c95200b94a14d3f693 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 17:44:01 +0200 Subject: [PATCH 0333/2900] cfg80211: remove some locked wrappers from sme API By making all the API functions require wdev locking we can clean up the API a bit, getting rid of the locking version of each function. This also decreases the size of cfg80211 by a small amount. Signed-off-by: Johannes Berg --- net/wireless/core.c | 4 ++-- net/wireless/core.h | 11 ++--------- net/wireless/nl80211.c | 10 ++++++++-- net/wireless/sme.c | 41 +++++++---------------------------------- net/wireless/util.c | 2 ++ net/wireless/wext-sme.c | 23 +++++++++++------------ 6 files changed, 32 insertions(+), 59 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index afcb9ec70adb..ee422871fe9e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -755,8 +755,8 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, wdev->wext.ie_len = 0; wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; #endif - __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, true); + cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, true); wdev_unlock(wdev); break; case NL80211_IFTYPE_MESH_POINT: diff --git a/net/wireless/core.h b/net/wireless/core.h index c8f87dfd50d3..b4b4a566626b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -328,18 +328,11 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, const struct ieee80211_vht_cap *vht_capa_mask); /* SME */ -int __cfg80211_connect(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct cfg80211_connect_params *connect, - struct cfg80211_cached_keys *connkeys, - const u8 *prev_bssid); int cfg80211_connect(struct cfg80211_registered_device *rdev, struct net_device *dev, struct cfg80211_connect_params *connect, - struct cfg80211_cached_keys *connkeys); -int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, - struct net_device *dev, u16 reason, - bool wextev); + struct cfg80211_cached_keys *connkeys, + const u8 *prev_bssid); int cfg80211_disconnect(struct cfg80211_registered_device *rdev, struct net_device *dev, u16 reason, bool wextev); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 49c2f2f511dc..a09f36bb957c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6683,7 +6683,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) sizeof(connect.vht_capa)); } - err = cfg80211_connect(rdev, dev, &connect, connkeys); + wdev_lock(dev->ieee80211_ptr); + err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); + wdev_unlock(dev->ieee80211_ptr); if (err) kfree(connkeys); return err; @@ -6694,6 +6696,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; u16 reason; + int ret; if (!info->attrs[NL80211_ATTR_REASON_CODE]) reason = WLAN_REASON_DEAUTH_LEAVING; @@ -6707,7 +6710,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info) dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) return -EOPNOTSUPP; - return cfg80211_disconnect(rdev, dev, reason, true); + wdev_lock(dev->ieee80211_ptr); + ret = cfg80211_disconnect(rdev, dev, reason, true); + wdev_unlock(dev->ieee80211_ptr); + return ret; } static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 31d67add7424..81be95f3be74 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -760,11 +760,11 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, } EXPORT_SYMBOL(cfg80211_disconnected); -int __cfg80211_connect(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct cfg80211_connect_params *connect, - struct cfg80211_cached_keys *connkeys, - const u8 *prev_bssid) +int cfg80211_connect(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_connect_params *connect, + struct cfg80211_cached_keys *connkeys, + const u8 *prev_bssid) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_bss *bss = NULL; @@ -911,22 +911,8 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, } } -int cfg80211_connect(struct cfg80211_registered_device *rdev, - struct net_device *dev, - struct cfg80211_connect_params *connect, - struct cfg80211_cached_keys *connkeys) -{ - int err; - - wdev_lock(dev->ieee80211_ptr); - err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); - wdev_unlock(dev->ieee80211_ptr); - - return err; -} - -int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, - struct net_device *dev, u16 reason, bool wextev) +int cfg80211_disconnect(struct cfg80211_registered_device *rdev, + struct net_device *dev, u16 reason, bool wextev) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; @@ -983,19 +969,6 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, return 0; } -int cfg80211_disconnect(struct cfg80211_registered_device *rdev, - struct net_device *dev, - u16 reason, bool wextev) -{ - int err; - - wdev_lock(dev->ieee80211_ptr); - err = __cfg80211_disconnect(rdev, dev, reason, wextev); - wdev_unlock(dev->ieee80211_ptr); - - return err; -} - void cfg80211_sme_disassoc(struct net_device *dev, struct cfg80211_internal_bss *bss) { diff --git a/net/wireless/util.c b/net/wireless/util.c index 501724257af5..74458b7f61eb 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -858,8 +858,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: + wdev_lock(dev->ieee80211_ptr); cfg80211_disconnect(rdev, dev, WLAN_REASON_DEAUTH_LEAVING, true); + wdev_unlock(dev->ieee80211_ptr); break; case NL80211_IFTYPE_MESH_POINT: /* mesh should be handled? */ diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index aeefd6817189..a53f8404f451 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -54,8 +54,8 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, if (wdev->wext.prev_bssid_valid) prev_bssid = wdev->wext.prev_bssid; - err = __cfg80211_connect(rdev, wdev->netdev, - &wdev->wext.connect, ck, prev_bssid); + err = cfg80211_connect(rdev, wdev->netdev, + &wdev->wext.connect, ck, prev_bssid); if (err) kfree(ck); @@ -100,8 +100,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, /* if SSID set, we'll try right again, avoid event */ if (wdev->wext.connect.ssid_len) event = false; - err = __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, event); + err = cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, event); if (err) goto out; } @@ -199,8 +199,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, /* if SSID set now, we'll try to connect, avoid event */ if (len) event = false; - err = __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, event); + err = cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, event); if (err) goto out; } @@ -288,8 +288,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, ether_addr_equal(bssid, wdev->wext.connect.bssid)) goto out; - err = __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, false); + err = cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, false); if (err) goto out; } @@ -365,8 +365,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev, wdev->wext.ie_len = ie_len; if (wdev->sme_state != CFG80211_SME_IDLE) { - err = __cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, false); + err = cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, false); if (err) goto out; } @@ -402,8 +402,7 @@ int cfg80211_wext_siwmlme(struct net_device *dev, switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: - err = __cfg80211_disconnect(rdev, dev, mlme->reason_code, - true); + err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true); break; default: err = -EOPNOTSUPP; -- GitLab From 2e460fc07ef0ebadfb593b564a8c7fa6559ac3d7 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:22 +0000 Subject: [PATCH 0334/2900] tg3: Split APE driver state change out of boot reset signature update Unlike the boot signature that needs to be set before every reset, the ape state only needs to be updated to tell the firmware that the driver is now taking/releasing control of the hardware. Move the calls to tg3_ape_driver_state_change() to better, more appropriate places. Also, the firmware does not distinguish between SUSPEND and START states anymore. Remove the SUSPEND case in the switch. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index c15a92d012ef..ae808b03affe 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -965,9 +965,6 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind) event = APE_EVENT_STATUS_STATE_UNLOAD; break; - case RESET_KIND_SUSPEND: - event = APE_EVENT_STATUS_STATE_SUSPEND; - break; default: return; } @@ -1739,10 +1736,6 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) break; } } - - if (kind == RESET_KIND_INIT || - kind == RESET_KIND_SUSPEND) - tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -1764,9 +1757,6 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) break; } } - - if (kind == RESET_KIND_SHUTDOWN) - tg3_ape_driver_state_change(tp, kind); } /* tp->lock is held. */ @@ -4206,6 +4196,8 @@ static int tg3_power_down_prepare(struct tg3 *tp) tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + tg3_ape_driver_state_change(tp, RESET_KIND_SHUTDOWN); + return 0; } @@ -11244,6 +11236,9 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, tg3_full_lock(tp, 0); + if (init) + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); + err = tg3_init_hw(tp, reset_phy); if (err) { tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); @@ -13360,11 +13355,13 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, struct tg3 *tp = netdev_priv(dev); bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB; - if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) && - tg3_power_up(tp)) { - etest->flags |= ETH_TEST_FL_FAILED; - memset(data, 1, sizeof(u64) * TG3_NUM_TEST); - return; + if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) { + if (tg3_power_up(tp)) { + etest->flags |= ETH_TEST_FL_FAILED; + memset(data, 1, sizeof(u64) * TG3_NUM_TEST); + return; + } + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); } memset(data, 0, sizeof(u64) * TG3_NUM_TEST); @@ -17670,6 +17667,8 @@ static int tg3_resume(struct device *device) tg3_full_lock(tp, 0); + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); + tg3_flag_set(tp, INIT_COMPLETE); err = tg3_restart_hw(tp, !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN)); @@ -17804,6 +17803,7 @@ static void tg3_io_resume(struct pci_dev *pdev) goto done; tg3_full_lock(tp, 0); + tg3_ape_driver_state_change(tp, RESET_KIND_INIT); tg3_flag_set(tp, INIT_COMPLETE); err = tg3_restart_hw(tp, true); if (err) { -- GitLab From 32ba19efc08a4bd63590310f05da5ce4d8773508 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:23 +0000 Subject: [PATCH 0335/2900] tg3: Simplify ring control block setup The current code calls tg3_set_bdinfo() separately on napi0, followed by a loop that does napi1+. Simplify it by setting bdinfo in the loop for all napi contexts. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 79 +++++++++++++++++------------ 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ae808b03affe..bb1d34c109f5 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -9239,6 +9239,48 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) } } +/* tp->lock is held. */ +static void tg3_tx_rcbs_init(struct tg3 *tp) +{ + int i = 0; + u32 txrcb = NIC_SRAM_SEND_RCB; + + if (tg3_flag(tp, ENABLE_TSS)) + i++; + + for (; i < tp->irq_max; i++, txrcb += TG3_BDINFO_SIZE) { + struct tg3_napi *tnapi = &tp->napi[i]; + + if (!tnapi->tx_ring) + continue; + + tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, + (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT), + NIC_SRAM_TX_BUFFER_DESC); + } +} + +/* tp->lock is held. */ +static void tg3_rx_ret_rcbs_init(struct tg3 *tp) +{ + int i = 0; + u32 rxrcb = NIC_SRAM_RCV_RET_RCB; + + if (tg3_flag(tp, ENABLE_RSS)) + i++; + + for (; i < tp->irq_max; i++, rxrcb += TG3_BDINFO_SIZE) { + struct tg3_napi *tnapi = &tp->napi[i]; + + if (!tnapi->rx_rcb) + continue; + + tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, + (tp->rx_ret_ring_mask + 1) << + BDINFO_FLAGS_MAXLEN_SHIFT, 0); + } +} + /* tp->lock is held. */ static void tg3_rings_reset(struct tg3 *tp) { @@ -9315,9 +9357,6 @@ static void tg3_rings_reset(struct tg3 *tp) tw32_tx_mbox(mbox + i * 8, 0); } - txrcb = NIC_SRAM_SEND_RCB; - rxrcb = NIC_SRAM_RCV_RET_RCB; - /* Clear status block in ram. */ memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); @@ -9327,46 +9366,20 @@ static void tg3_rings_reset(struct tg3 *tp) tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tnapi->status_mapping & 0xffffffff)); - if (tnapi->tx_ring) { - tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - txrcb += TG3_BDINFO_SIZE; - } - - if (tnapi->rx_rcb) { - tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, - (tp->rx_ret_ring_mask + 1) << - BDINFO_FLAGS_MAXLEN_SHIFT, 0); - rxrcb += TG3_BDINFO_SIZE; - } - stblk = HOSTCC_STATBLCK_RING1; for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) { u64 mapping = (u64)tnapi->status_mapping; tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32); tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff); + stblk += 8; /* Clear status block in ram. */ memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); - - if (tnapi->tx_ring) { - tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping, - (TG3_TX_RING_SIZE << - BDINFO_FLAGS_MAXLEN_SHIFT), - NIC_SRAM_TX_BUFFER_DESC); - txrcb += TG3_BDINFO_SIZE; - } - - tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping, - ((tp->rx_ret_ring_mask + 1) << - BDINFO_FLAGS_MAXLEN_SHIFT), 0); - - stblk += 8; - rxrcb += TG3_BDINFO_SIZE; } + + tg3_tx_rcbs_init(tp); + tg3_rx_ret_rcbs_init(tp); } static void tg3_setup_rxbd_thresholds(struct tg3 *tp) -- GitLab From 328947ff2609989fefe6dfd1143cc0787a5ec862 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:24 +0000 Subject: [PATCH 0336/2900] tg3: Make tg3_rings_reset() more concise Simplify the rings reset function and increase readability by moving the control block disable code into separate functions. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 81 +++++++++++++++++------------ 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bb1d34c109f5..693c5f23c3ea 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -9239,6 +9239,28 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec) } } +/* tp->lock is held. */ +static void tg3_tx_rcbs_disable(struct tg3 *tp) +{ + u32 txrcb, limit; + + /* Disable all transmit rings but the first. */ + if (!tg3_flag(tp, 5705_PLUS)) + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; + else if (tg3_flag(tp, 5717_PLUS)) + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; + else if (tg3_flag(tp, 57765_CLASS) || + tg3_asic_rev(tp) == ASIC_REV_5762) + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; + else + limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; + + for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; + txrcb < limit; txrcb += TG3_BDINFO_SIZE) + tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); +} + /* tp->lock is held. */ static void tg3_tx_rcbs_init(struct tg3 *tp) { @@ -9260,6 +9282,29 @@ static void tg3_tx_rcbs_init(struct tg3 *tp) } } +/* tp->lock is held. */ +static void tg3_rx_ret_rcbs_disable(struct tg3 *tp) +{ + u32 rxrcb, limit; + + /* Disable all receive return rings but the first. */ + if (tg3_flag(tp, 5717_PLUS)) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; + else if (!tg3_flag(tp, 5705_PLUS)) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; + else if (tg3_asic_rev(tp) == ASIC_REV_5755 || + tg3_asic_rev(tp) == ASIC_REV_5762 || + tg3_flag(tp, 57765_CLASS)) + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4; + else + limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; + + for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; + rxrcb < limit; rxrcb += TG3_BDINFO_SIZE) + tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS, + BDINFO_FLAGS_DISABLED); +} + /* tp->lock is held. */ static void tg3_rx_ret_rcbs_init(struct tg3 *tp) { @@ -9285,42 +9330,12 @@ static void tg3_rx_ret_rcbs_init(struct tg3 *tp) static void tg3_rings_reset(struct tg3 *tp) { int i; - u32 stblk, txrcb, rxrcb, limit; + u32 stblk; struct tg3_napi *tnapi = &tp->napi[0]; - /* Disable all transmit rings but the first. */ - if (!tg3_flag(tp, 5705_PLUS)) - limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; - else if (tg3_flag(tp, 5717_PLUS)) - limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; - else if (tg3_flag(tp, 57765_CLASS) || - tg3_asic_rev(tp) == ASIC_REV_5762) - limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; - else - limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; - - for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; - txrcb < limit; txrcb += TG3_BDINFO_SIZE) - tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); - - - /* Disable all receive return rings but the first. */ - if (tg3_flag(tp, 5717_PLUS)) - limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17; - else if (!tg3_flag(tp, 5705_PLUS)) - limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; - else if (tg3_asic_rev(tp) == ASIC_REV_5755 || - tg3_asic_rev(tp) == ASIC_REV_5762 || - tg3_flag(tp, 57765_CLASS)) - limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4; - else - limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; + tg3_tx_rcbs_disable(tp); - for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; - rxrcb < limit; rxrcb += TG3_BDINFO_SIZE) - tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS, - BDINFO_FLAGS_DISABLED); + tg3_rx_ret_rcbs_disable(tp); /* Disable interrupts */ tw32_mailbox_f(tp->napi[0].int_mbox, 1); -- GitLab From 4a5f46f2fef13ecfc1f396d0caf75031a7a15422 Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:25 +0000 Subject: [PATCH 0337/2900] tg3: Use descriptive label names in tg3_start Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 693c5f23c3ea..6ab02d6a0eb3 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -11244,7 +11244,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, */ err = tg3_alloc_consistent(tp); if (err) - goto err_out1; + goto out_ints_fini; tg3_napi_init(tp); @@ -11258,7 +11258,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, tnapi = &tp->napi[i]; free_irq(tnapi->irq_vec, tnapi); } - goto err_out2; + goto out_napi_fini; } } @@ -11276,7 +11276,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, tg3_full_unlock(tp); if (err) - goto err_out3; + goto out_free_irq; if (test_irq && tg3_flag(tp, USING_MSI)) { err = tg3_test_msi(tp); @@ -11287,7 +11287,7 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, tg3_free_rings(tp); tg3_full_unlock(tp); - goto err_out2; + goto out_napi_fini; } if (!tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) { @@ -11327,18 +11327,18 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq, return 0; -err_out3: +out_free_irq: for (i = tp->irq_cnt - 1; i >= 0; i--) { struct tg3_napi *tnapi = &tp->napi[i]; free_irq(tnapi->irq_vec, tnapi); } -err_out2: +out_napi_fini: tg3_napi_disable(tp); tg3_napi_fini(tp); tg3_free_consistent(tp); -err_out1: +out_ints_fini: tg3_ints_fini(tp); return err; -- GitLab From 7c10ee32f32644c9efbb3cfebf5fb7cea4b48a2c Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:26 +0000 Subject: [PATCH 0338/2900] tg3: Fix misplaced empty line Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 6ab02d6a0eb3..bd5917d8ffb5 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1311,8 +1311,8 @@ static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) if (err) return err; - if (enable) + if (enable) val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; else val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; -- GitLab From f2068b80ca59d63ca21ee1da829c9fe09f25b08e Mon Sep 17 00:00:00 2001 From: Nithin Sujir Date: Thu, 23 May 2013 11:11:27 +0000 Subject: [PATCH 0339/2900] tg3: Remove unnecessary lock around tg3_flag_set The spinlock was needed when flags used to be a u32 and set/cleared using bit operations. Now that we use the atomic set_bit, this lock isn't needed. Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index bd5917d8ffb5..d7755d849e53 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -6386,9 +6386,7 @@ static void tg3_tx_recover(struct tg3 *tp) "Please report the problem to the driver maintainer " "and include system chipset information.\n"); - spin_lock(&tp->lock); tg3_flag_set(tp, TX_RECOVERY_PENDING); - spin_unlock(&tp->lock); } static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) -- GitLab From a80be5a58ebf29e7ca8a2915debe42295608a20a Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Thu, 23 May 2013 21:04:25 +0000 Subject: [PATCH 0340/2900] qlcnic: Support spoof check config. o Add support for spoof check configuration per VF using iproute2 tool. Signed-off-by: Rajesh Borundia Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 + .../net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 2 ++ .../qlogic/qlcnic/qlcnic_sriov_common.c | 1 + .../ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 36 +++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index aeb26a850679..1e196713c7d3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -449,6 +449,7 @@ static const struct net_device_ops qlcnic_netdev_ops = { .ndo_set_vf_tx_rate = qlcnic_sriov_set_vf_tx_rate, .ndo_get_vf_config = qlcnic_sriov_get_vf_config, .ndo_set_vf_vlan = qlcnic_sriov_set_vf_vlan, + .ndo_set_vf_spoofchk = qlcnic_sriov_set_vf_spoofchk, #endif }; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index d85fbb57c25b..9176cb015732 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h @@ -129,6 +129,7 @@ struct qlcnic_vport { u8 vlan_mode; u16 vlan; u8 qos; + bool spoofchk; u8 mac[6]; }; @@ -225,6 +226,7 @@ int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int); int qlcnic_sriov_get_vf_config(struct net_device *, int , struct ifla_vf_info *); int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8); +int qlcnic_sriov_set_vf_spoofchk(struct net_device *, int, bool); #else static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {} static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 196b2d100407..6262c71bc18f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -187,6 +187,7 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) } sriov->vf_info[i].vp = vp; vp->max_tx_bw = MAX_BW; + vp->spoofchk = true; random_ether_addr(vp->mac); dev_info(&adapter->pdev->dev, "MAC Address %pM is configured for VF %d\n", diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 1a66ccded235..ee0c1d307966 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -580,6 +580,7 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func) struct qlcnic_cmd_args cmd; struct qlcnic_vport *vp; int err, id; + u8 *mac; id = qlcnic_sriov_func_to_index(adapter, func); if (id < 0) @@ -591,6 +592,14 @@ static int qlcnic_sriov_set_vf_acl(struct qlcnic_adapter *adapter, u8 func) return err; cmd.req.arg[1] = 0x3 | func << 16; + if (vp->spoofchk == true) { + mac = vp->mac; + cmd.req.arg[2] |= BIT_1 | BIT_3 | BIT_8; + cmd.req.arg[4] = mac[5] | mac[4] << 8 | mac[3] << 16 | + mac[2] << 24; + cmd.req.arg[5] = mac[1] | mac[0] << 8; + } + if (vp->vlan_mode == QLC_PVID_MODE) { cmd.req.arg[2] |= BIT_6; cmd.req.arg[3] |= vp->vlan << 8; @@ -1767,6 +1776,7 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev, memcpy(&ivi->mac, vp->mac, ETH_ALEN); ivi->vlan = vp->vlan; ivi->qos = vp->qos; + ivi->spoofchk = vp->spoofchk; if (vp->max_tx_bw == MAX_BW) ivi->tx_rate = 0; else @@ -1775,3 +1785,29 @@ int qlcnic_sriov_get_vf_config(struct net_device *netdev, ivi->vf = vf; return 0; } + +int qlcnic_sriov_set_vf_spoofchk(struct net_device *netdev, int vf, bool chk) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_sriov *sriov = adapter->ahw->sriov; + struct qlcnic_vf_info *vf_info; + struct qlcnic_vport *vp; + + if (!qlcnic_sriov_pf_check(adapter)) + return -EOPNOTSUPP; + + if (vf >= sriov->num_vfs) + return -EINVAL; + + vf_info = &sriov->vf_info[vf]; + vp = vf_info->vp; + if (test_bit(QLC_BC_VF_STATE, &vf_info->state)) { + netdev_err(netdev, + "Spoof check change failed for VF %d, as VF driver is loaded. Please unload VF driver and retry the operation\n", + vf); + return -EOPNOTSUPP; + } + + vp->spoofchk = chk; + return 0; +} -- GitLab From 45ef92ed5815883087c984356a85aa3efdb5bcab Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Thu, 23 May 2013 21:04:26 +0000 Subject: [PATCH 0341/2900] qlcnic: Disable INT-x interrupt for 83xx on driver unload o Set HW mask for 8300 Series adapter, in INT-x mode, to stop generating interrupt during driver unload. Signed-off-by: Himanshu Madhani Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index b4ff1e35a11d..9b91d6a231cb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -312,6 +312,11 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter) writel(0, adapter->tgt_mask_reg); } +inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter) +{ + writel(1, adapter->tgt_mask_reg); +} + /* Enable MSI-x and INT-x interrupts */ void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter, struct qlcnic_host_sds_ring *sds_ring) @@ -458,6 +463,9 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter) { u32 num_msix; + if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) + qlcnic_83xx_set_legacy_intr_mask(adapter); + qlcnic_83xx_disable_mbx_intr(adapter); if (adapter->flags & QLCNIC_MSIX_ENABLED) -- GitLab From aa2a80340ce0b4a148ae8878142d17bc793ba2ab Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Thu, 23 May 2013 21:04:27 +0000 Subject: [PATCH 0342/2900] qlcnic: Update IRQ name for 8200 and 8300 Series adapter. o Updated IRQ name for 8200 and 8300 Series adapter as per format used by other multiqueue drivers. Signed-off-by: Himanshu Madhani Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 5 +--- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 23 ++++++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 9b91d6a231cb..9f5683fda801 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -482,7 +482,6 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) { irq_handler_t handler; u32 val; - char name[32]; int err = 0; unsigned long flags = 0; @@ -493,9 +492,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) if (adapter->flags & QLCNIC_MSIX_ENABLED) { handler = qlcnic_83xx_handle_aen; val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector; - snprintf(name, (IFNAMSIZ + 4), - "%s[%s]", "qlcnic", "aen"); - err = request_irq(val, handler, flags, name, adapter); + err = request_irq(val, handler, flags, "qlcnic-MB", adapter); if (err) { dev_err(&adapter->pdev->dev, "failed to register MBX interrupt\n"); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 1e196713c7d3..76b95b48c815 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1396,16 +1396,23 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) for (ring = 0; ring < num_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; if (qlcnic_82xx_check(adapter) && - (ring == (num_sds_rings - 1))) + (ring == (num_sds_rings - 1))) { + if (!(adapter->flags & + QLCNIC_MSIX_ENABLED)) + snprintf(sds_ring->name, + sizeof(sds_ring->name), + "qlcnic"); + else + snprintf(sds_ring->name, + sizeof(sds_ring->name), + "%s-tx-0-rx-%d", + netdev->name, ring); + } else { snprintf(sds_ring->name, sizeof(sds_ring->name), - "qlcnic-%s[Tx0+Rx%d]", - netdev->name, ring); - else - snprintf(sds_ring->name, - sizeof(sds_ring->name), - "qlcnic-%s[Rx%d]", + "%s-rx-%d", netdev->name, ring); + } err = request_irq(sds_ring->irq, handler, flags, sds_ring->name, sds_ring); if (err) @@ -1420,7 +1427,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) ring++) { tx_ring = &adapter->tx_ring[ring]; snprintf(tx_ring->name, sizeof(tx_ring->name), - "qlcnic-%s[Tx%d]", netdev->name, ring); + "%s-tx-%d", netdev->name, ring); err = request_irq(tx_ring->irq, handler, flags, tx_ring->name, tx_ring); if (err) -- GitLab From 7e8fd003c96dda2920a4ba0c32d54780d15dfefc Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Thu, 23 May 2013 21:04:28 +0000 Subject: [PATCH 0343/2900] qlcnic: Remove qlcnic_config_npars module parameter qlcnic_config_npars module parameter is used to configure NPAR operational modes where NPAR function is used for PCI passthrough. Removing this paramter as PCI passthrough is not supported for NPAR functions. Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 - .../ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 21 +++++----------- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 24 ++++--------------- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index c1b693cb3df3..60f310a542da 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -303,7 +303,6 @@ extern int qlcnic_use_msi; extern int qlcnic_use_msi_x; extern int qlcnic_auto_fw_reset; extern int qlcnic_load_fw_file; -extern int qlcnic_config_npars; /* Number of status descriptors to handle per interrupt */ #define MAX_STATUS_HANDLE (64) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index b0c3de9ede03..55e5e1b5ad4f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c @@ -42,27 +42,18 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock) static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) { u8 id; - int i, ret = -EBUSY; + int ret = -EBUSY; u32 data = QLCNIC_MGMT_FUNC; struct qlcnic_hardware_context *ahw = adapter->ahw; if (qlcnic_83xx_lock_driver(adapter)) return ret; - if (qlcnic_config_npars) { - for (i = 0; i < ahw->act_pci_func; i++) { - id = adapter->npars[i].pci_func; - if (id == ahw->pci_func) - continue; - data |= qlcnic_config_npars & - QLC_83XX_SET_FUNC_OPMODE(0x3, id); - } - } else { - data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); - data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) | - QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, - ahw->pci_func); - } + id = ahw->pci_func; + data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); + data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) | + QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id); + QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data); qlcnic_83xx_unlock_driver(adapter); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 76b95b48c815..5b18b0accb06 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -52,10 +52,6 @@ int qlcnic_load_fw_file; MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)"); module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); -int qlcnic_config_npars; -module_param(qlcnic_config_npars, int, 0444); -MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)"); - static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void qlcnic_remove(struct pci_dev *pdev); static int qlcnic_open(struct net_device *netdev); @@ -769,7 +765,7 @@ static int qlcnic_set_function_modes(struct qlcnic_adapter *adapter) { u8 id; - int i, ret = 1; + int ret; u32 data = QLCNIC_MGMT_FUNC; struct qlcnic_hardware_context *ahw = adapter->ahw; @@ -777,20 +773,10 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) if (ret) goto err_lock; - if (qlcnic_config_npars) { - for (i = 0; i < ahw->act_pci_func; i++) { - id = adapter->npars[i].pci_func; - if (id == ahw->pci_func) - continue; - data |= (qlcnic_config_npars & - QLC_DEV_SET_DRV(0xf, id)); - } - } else { - data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); - data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | - (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, - ahw->pci_func)); - } + id = ahw->pci_func; + data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); + data = (data & ~QLC_DEV_SET_DRV(0xf, id)) | + QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, id); QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data); qlcnic_api_unlock(adapter); err_lock: -- GitLab From 1267ff962fc04d33d30b52c5c09201df2b1c1d76 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Thu, 23 May 2013 21:04:29 +0000 Subject: [PATCH 0344/2900] qlcnic: Initialize trans_work and idc_aen_work at VF probe. o work_struct should be initialized before cancel_delayed_work call to destroy it. Signed-off-by: Sucheta Chakraborty Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 6262c71bc18f..bcd200eff981 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -35,6 +35,7 @@ static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *); +static void qlcnic_sriov_process_bc_cmd(struct work_struct *); static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { .read_crb = qlcnic_83xx_read_crb, @@ -179,6 +180,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) spin_lock_init(&vf->rcv_pend.lock); init_completion(&vf->ch_free_cmpl); + INIT_WORK(&vf->trans_work, qlcnic_sriov_process_bc_cmd); + if (qlcnic_sriov_pf_check(adapter)) { vp = kzalloc(sizeof(struct qlcnic_vport), GFP_KERNEL); if (!vp) { @@ -653,6 +656,8 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac) if (qlcnic_read_mac_addr(adapter)) dev_warn(&adapter->pdev->dev, "failed to read mac addr\n"); + INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); + clear_bit(__QLCNIC_RESETTING, &adapter->state); return 0; } @@ -865,7 +870,6 @@ static void qlcnic_sriov_schedule_bc_cmd(struct qlcnic_sriov *sriov, vf->adapter->need_fw_reset) return; - INIT_WORK(&vf->trans_work, func); queue_work(sriov->bc.bc_trans_wq, &vf->trans_work); } -- GitLab From b17f2ccaeea10f30322b9706d8d9b5b39d21f427 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Thu, 23 May 2013 21:04:30 +0000 Subject: [PATCH 0345/2900] qlcnic: Convert nested if-else to switch-case Signed-off-by: Jitendra Kalsaria Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- .../ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index 55e5e1b5ad4f..b5054e1d1710 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c @@ -187,20 +187,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) else priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, ahw->pci_func); - - if (priv_level == QLCNIC_NON_PRIV_FUNC) { + switch (priv_level) { + case QLCNIC_NON_PRIV_FUNC: ahw->op_mode = QLCNIC_NON_PRIV_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; - } else if (priv_level == QLCNIC_PRIV_FUNC) { + break; + case QLCNIC_PRIV_FUNC: ahw->op_mode = QLCNIC_PRIV_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry; nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; - } else if (priv_level == QLCNIC_MGMT_FUNC) { + break; + case QLCNIC_MGMT_FUNC: ahw->op_mode = QLCNIC_MGMT_FUNC; ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; - } else { + break; + default: + dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n"); return -EIO; } @@ -209,8 +213,8 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) else adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; - adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; - adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; + ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; + ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; return 0; } -- GitLab From 4690a7e48ac55cf84fcf214279baf133304d71e4 Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 23 May 2013 21:04:31 +0000 Subject: [PATCH 0346/2900] qlcnic: diagnostics routine changes Test and set diagnostics mode bit before starting diagnostics tests. Stop diagnostics tests if adapter is resetting. Signed-off-by: Sony Chacko Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 12 ++++++++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 28 +++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 60f310a542da..8affec5e6eb8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -931,6 +931,7 @@ struct qlcnic_ipaddr { #define __QLCNIC_SRIOV_ENABLE 10 #define __QLCNIC_SRIOV_CAPABLE 11 #define __QLCNIC_MBX_POLL_ENABLE 12 +#define __QLCNIC_DIAG_MODE 13 #define QLCNIC_INTERRUPT_TEST 1 #define QLCNIC_LOOPBACK_TEST 2 @@ -1476,6 +1477,7 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); /* Functions from qlcnic_ethtool.c */ + int qlcnic_check_loopback_buff(unsigned char *, u8 []); int qlcnic_do_lb_test(struct qlcnic_adapter *, u8); int qlcnic_loopback_test(struct net_device *, u8); @@ -1885,6 +1887,16 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) writel(0xfbff, adapter->tgt_mask_reg); } +static inline int qlcnic_get_diag_lock(struct qlcnic_adapter *adapter) +{ + return test_and_set_bit(__QLCNIC_DIAG_MODE, &adapter->state); +} + +static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter) +{ + clear_bit(__QLCNIC_DIAG_MODE, &adapter->state); +} + extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 9f5683fda801..1e699e6f29c8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -1593,16 +1593,24 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) struct qlcnic_hardware_context *ahw = adapter->ahw; int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings; - QLCDB(adapter, DRV, "%s loopback test in progress\n", - mode == QLCNIC_ILB_MODE ? "internal" : "external"); if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { - dev_warn(&adapter->pdev->dev, - "Loopback test not supported for non privilege function\n"); + netdev_warn(netdev, + "Loopback test not supported in non privileged mode\n"); return ret; } - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { + netdev_info(netdev, "Device is resetting\n"); return -EBUSY; + } + + if (qlcnic_get_diag_lock(adapter)) { + netdev_info(netdev, "Device is in diagnostics mode\n"); + return -EBUSY; + } + + netdev_info(netdev, "%s loopback test in progress\n", + mode == QLCNIC_ILB_MODE ? "internal" : "external"); ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST, max_sds_rings); @@ -1643,7 +1651,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) fail_diag_alloc: adapter->max_sds_rings = max_sds_rings; - clear_bit(__QLCNIC_RESETTING, &adapter->state); + qlcnic_release_diag_lock(adapter); return ret; } @@ -3118,8 +3126,10 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) u8 val; int ret, max_sds_rings = adapter->max_sds_rings; - if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) - return -EIO; + if (qlcnic_get_diag_lock(adapter)) { + netdev_info(netdev, "Device in diagnostics mode\n"); + return -EBUSY; + } ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST, max_sds_rings); @@ -3161,7 +3171,7 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) fail_diag_irq: adapter->max_sds_rings = max_sds_rings; - clear_bit(__QLCNIC_RESETTING, &adapter->state); + qlcnic_release_diag_lock(adapter); return ret; } -- GitLab From 099907fac61c47a67a02edb85d551e91959ecc5b Mon Sep 17 00:00:00 2001 From: Sony Chacko Date: Thu, 23 May 2013 21:04:32 +0000 Subject: [PATCH 0347/2900] qlcnic: modify reset recovery path in diag mode Provide diagnostics routines enough time to unwind before proceeding with reset recovery. Signed-off-by: Sony Chacko Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 6 +++- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 1 + .../ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 35 +++++++++++++++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 8affec5e6eb8..4ff0625a0cef 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1477,7 +1477,6 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); /* Functions from qlcnic_ethtool.c */ - int qlcnic_check_loopback_buff(unsigned char *, u8 []); int qlcnic_do_lb_test(struct qlcnic_adapter *, u8); int qlcnic_loopback_test(struct net_device *, u8); @@ -1897,6 +1896,11 @@ static inline void qlcnic_release_diag_lock(struct qlcnic_adapter *adapter) clear_bit(__QLCNIC_DIAG_MODE, &adapter->state); } +static inline int qlcnic_check_diag_status(struct qlcnic_adapter *adapter) +{ + return test_bit(__QLCNIC_DIAG_MODE, &adapter->state); +} + extern const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index f5db67fc9f55..1bfe283a9412 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -314,6 +314,7 @@ struct qlc_83xx_idc { u8 vnic_state; u8 vnic_wait_limit; u8 quiesce_req; + u8 delay_reset; char **name; }; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 5e7fb1dfb97b..aa26250d7374 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -649,6 +649,7 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) ahw->idc.collect_dump = 0; ahw->reset_context = 0; adapter->tx_timeo_cnt = 0; + ahw->idc.delay_reset = 0; clear_bit(__QLCNIC_RESETTING, &adapter->state); } @@ -883,21 +884,41 @@ static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) int ret = 0; if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { - qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); set_bit(__QLCNIC_RESETTING, &adapter->state); clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) qlcnic_83xx_disable_vnic_mode(adapter, 1); - qlcnic_83xx_idc_detach_driver(adapter); + + if (qlcnic_check_diag_status(adapter)) { + dev_info(&adapter->pdev->dev, + "%s: Wait for diag completion\n", __func__); + adapter->ahw->idc.delay_reset = 1; + return 0; + } else { + qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); + qlcnic_83xx_idc_detach_driver(adapter); + } } - /* Check ACK from other functions */ - ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); - if (ret) { + if (qlcnic_check_diag_status(adapter)) { dev_info(&adapter->pdev->dev, - "%s: Waiting for reset ACK\n", __func__); - return 0; + "%s: Wait for diag completion\n", __func__); + return -1; + } else { + if (adapter->ahw->idc.delay_reset) { + qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); + qlcnic_83xx_idc_detach_driver(adapter); + adapter->ahw->idc.delay_reset = 0; + } + + /* Check for ACK from other functions */ + ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); + if (ret) { + dev_info(&adapter->pdev->dev, + "%s: Waiting for reset ACK\n", __func__); + return -1; + } } /* Transit to INIT state and restart the HW */ -- GitLab From 487042af928c16d2a5b4dd52a9639a03b8b40761 Mon Sep 17 00:00:00 2001 From: Himanshu Madhani Date: Thu, 23 May 2013 21:04:33 +0000 Subject: [PATCH 0348/2900] qlcnic: Implement GET_LED_STATUS command for 82xx adapter. o GET_LED_STATUS command will be used by driver to get current beacon state from 82xx adapter. o Refactored qlcnic_store_beacon() to split 8200 and 8300 specific calls. Signed-off-by: Himanshu Madhani Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 5 + .../net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 1 + .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 15 +++ .../net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 1 + .../net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 122 +++++++++++------- 5 files changed, 98 insertions(+), 46 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 4ff0625a0cef..e6f8beccbf3e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -815,6 +815,7 @@ struct qlcnic_mac_list_s { #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 #define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 +#define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 /* module types */ #define LINKEVENT_MODULE_NOT_PRESENT 1 @@ -912,6 +913,9 @@ struct qlcnic_ipaddr { #define QLCNIC_IS_TSO_CAPABLE(adapter) \ ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) +#define QLCNIC_BEACON_EANBLE 0xC +#define QLCNIC_BEACON_DISABLE 0xD + #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 #define QLCNIC_MSIX_TBL_SPACE 8192 #define QLCNIC_PCI_REG_MSIX_TBL 0x44 @@ -1543,6 +1547,7 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *); int qlcnic_reset_npar_config(struct qlcnic_adapter *); int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16); +int qlcnic_get_beacon_state(struct qlcnic_adapter *, u8 *); int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); int qlcnic_read_mac_addr(struct qlcnic_adapter *); int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 43562c256379..d63b5f728d75 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -37,6 +37,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = { {QLCNIC_CMD_TEMP_SIZE, 4, 4}, {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, {QLCNIC_CMD_SET_DRV_VER, 4, 1}, + {QLCNIC_CMD_GET_LED_STATUS, 4, 2}, }; static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 106a12f2a02f..218978db2963 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -1503,6 +1503,21 @@ int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return rv; } +int qlcnic_get_beacon_state(struct qlcnic_adapter *adapter, u8 *h_state) +{ + struct qlcnic_cmd_args cmd; + int err; + + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LED_STATUS); + if (!err) { + err = qlcnic_issue_cmd(adapter, &cmd); + if (!err) + *h_state = cmd.rsp.arg[1]; + } + qlcnic_free_mbx_args(&cmd); + return err; +} + void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter) { void __iomem *msix_base_addr; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index b6818f4356b9..812fd07baef3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h @@ -87,6 +87,7 @@ enum qlcnic_regs { #define QLCNIC_CMD_CONFIG_VPORT 0x32 #define QLCNIC_CMD_GET_MAC_STATS 0x37 #define QLCNIC_CMD_SET_DRV_VER 0x38 +#define QLCNIC_CMD_GET_LED_STATUS 0x3C #define QLCNIC_CMD_CONFIGURE_RSS 0x41 #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 #define QLCNIC_CMD_CONFIGURE_LED 0x44 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index e7a2fe21b649..025a7192289d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -114,57 +114,51 @@ static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, return 0; } -static ssize_t qlcnic_store_beacon(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) +static int qlcnic_83xx_store_beacon(struct qlcnic_adapter *adapter, + const char *buf, size_t len) { - struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_hardware_context *ahw = adapter->ahw; - int err, max_sds_rings = adapter->max_sds_rings; - u16 beacon; - u8 b_state, b_rate; unsigned long h_beacon; + int err; - if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { - dev_warn(dev, - "LED test not supported in non privileged mode\n"); - return -EOPNOTSUPP; - } + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EIO; - if (qlcnic_83xx_check(adapter) && - !test_bit(__QLCNIC_RESETTING, &adapter->state)) { - if (kstrtoul(buf, 2, &h_beacon)) - return -EINVAL; + if (kstrtoul(buf, 2, &h_beacon)) + return -EINVAL; - if (ahw->beacon_state == h_beacon) - return len; + if (ahw->beacon_state == h_beacon) + return len; - rtnl_lock(); - if (!ahw->beacon_state) { - if (test_and_set_bit(__QLCNIC_LED_ENABLE, - &adapter->state)) { - rtnl_unlock(); - return -EBUSY; - } - } - if (h_beacon) { - err = qlcnic_83xx_config_led(adapter, 1, h_beacon); - if (err) - goto beacon_err; - } else { - err = qlcnic_83xx_config_led(adapter, 0, !h_beacon); - if (err) - goto beacon_err; + rtnl_lock(); + if (!ahw->beacon_state) { + if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { + rtnl_unlock(); + return -EBUSY; } - /* set the current beacon state */ + } + + if (h_beacon) + err = qlcnic_83xx_config_led(adapter, 1, h_beacon); + else + err = qlcnic_83xx_config_led(adapter, 0, !h_beacon); + if (!err) ahw->beacon_state = h_beacon; -beacon_err: - if (!ahw->beacon_state) - clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); - rtnl_unlock(); - return len; - } + if (!ahw->beacon_state) + clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); + + rtnl_unlock(); + return len; +} + +static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, + const char *buf, size_t len) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + int err, max_sds_rings = adapter->max_sds_rings; + u16 beacon; + u8 h_beacon_state, b_state, b_rate; if (len != sizeof(u16)) return QL_STATUS_INVALID_PARAM; @@ -174,16 +168,29 @@ static ssize_t qlcnic_store_beacon(struct device *dev, if (err) return err; - if (adapter->ahw->beacon_state == b_state) + if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) { + err = qlcnic_get_beacon_state(adapter, &h_beacon_state); + if (!err) { + dev_info(&adapter->pdev->dev, + "Failed to get current beacon state\n"); + } else { + if (h_beacon_state == QLCNIC_BEACON_DISABLE) + ahw->beacon_state = 0; + else if (h_beacon_state == QLCNIC_BEACON_EANBLE) + ahw->beacon_state = 2; + } + } + + if (ahw->beacon_state == b_state) return len; rtnl_lock(); - - if (!adapter->ahw->beacon_state) + if (!ahw->beacon_state) { if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { rtnl_unlock(); return -EBUSY; } + } if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { err = -EIO; @@ -206,14 +213,37 @@ static ssize_t qlcnic_store_beacon(struct device *dev, if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) qlcnic_diag_free_res(adapter->netdev, max_sds_rings); - out: - if (!adapter->ahw->beacon_state) +out: + if (!ahw->beacon_state) clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); rtnl_unlock(); return err; } +static ssize_t qlcnic_store_beacon(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int err = 0; + + if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { + dev_warn(dev, + "LED test not supported in non privileged mode\n"); + return -EOPNOTSUPP; + } + + if (qlcnic_82xx_check(adapter)) + err = qlcnic_82xx_store_beacon(adapter, buf, len); + else if (qlcnic_83xx_check(adapter)) + err = qlcnic_83xx_store_beacon(adapter, buf, len); + else + return -EIO; + + return err; +} + static ssize_t qlcnic_show_beacon(struct device *dev, struct device_attribute *attr, char *buf) { -- GitLab From 2343f06a8c9549af27b885d36e26c59771d697f1 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 23 May 2013 21:04:34 +0000 Subject: [PATCH 0349/2900] qlcnic: qlcnic_get_board_name() function cleanup Signed-off-by: Manish Chopra Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 5b18b0accb06..da82f2eb73b4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -862,6 +862,27 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, return 0; } +static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, + int index) +{ + struct pci_dev *pdev = adapter->pdev; + unsigned short subsystem_vendor; + bool ret = true; + + subsystem_vendor = pdev->subsystem_vendor; + + if (pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X || + pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) { + if (qlcnic_boards[index].sub_vendor == subsystem_vendor && + qlcnic_boards[index].sub_device == pdev->subsystem_device) + ret = true; + else + ret = false; + } + + return ret; +} + static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) { struct pci_dev *pdev = adapter->pdev; @@ -869,20 +890,18 @@ static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { if (qlcnic_boards[i].vendor == pdev->vendor && - qlcnic_boards[i].device == pdev->device && - qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor && - qlcnic_boards[i].sub_device == pdev->subsystem_device) { - sprintf(name, "%pM: %s" , - adapter->mac_addr, - qlcnic_boards[i].short_name); - found = 1; - break; + qlcnic_boards[i].device == pdev->device && + qlcnic_validate_subsystem_id(adapter, i)) { + found = 1; + break; } - } if (!found) sprintf(name, "%pM Gigabit Ethernet", adapter->mac_addr); + else + sprintf(name, "%pM: %s" , adapter->mac_addr, + qlcnic_boards[i].short_name); } static void -- GitLab From ee9e8b6c6e167e2400efd26b92b300ff1d3f8e8b Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 23 May 2013 21:04:35 +0000 Subject: [PATCH 0350/2900] qlcnic: Enhance virtual NIC logging Signed-off-by: Manish Chopra Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 1 + .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 36 ++++++++------- .../net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 44 +++++++++---------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index e6f8beccbf3e..00a09573faab 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -442,6 +442,7 @@ struct qlcnic_hardware_context { u16 max_mtu; u32 msg_enable; u16 act_pci_func; + u16 max_pci_func; u32 capabilities; u32 capabilities2; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 1e699e6f29c8..f63a69570256 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -2134,26 +2134,25 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, struct qlcnic_pci_info *pci_info) { + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct device *dev = &adapter->pdev->dev; + struct qlcnic_cmd_args cmd; int i, err = 0, j = 0; u32 temp; - struct qlcnic_cmd_args cmd; qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); err = qlcnic_issue_cmd(adapter, &cmd); - adapter->ahw->act_pci_func = 0; + ahw->act_pci_func = 0; if (err == QLCNIC_RCODE_SUCCESS) { - pci_info->func_count = cmd.rsp.arg[1] & 0xFF; - dev_info(&adapter->pdev->dev, - "%s: total functions = %d\n", - __func__, pci_info->func_count); + ahw->max_pci_func = cmd.rsp.arg[1] & 0xFF; for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { pci_info->id = cmd.rsp.arg[i] & 0xFFFF; pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; i++; pci_info->type = cmd.rsp.arg[i] & 0xFFFF; if (pci_info->type == QLCNIC_TYPE_NIC) - adapter->ahw->act_pci_func++; + ahw->act_pci_func++; temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; pci_info->default_port = temp; i++; @@ -2165,18 +2164,21 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, i++; memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2); i = i + 3; - - dev_info(&adapter->pdev->dev, "%s:\n" - "\tid = %d active = %d type = %d\n" - "\tport = %d min bw = %d max bw = %d\n" - "\tmac_addr = %pM\n", __func__, - pci_info->id, pci_info->active, pci_info->type, - pci_info->default_port, pci_info->tx_min_bw, - pci_info->tx_max_bw, pci_info->mac); + if (ahw->op_mode == QLCNIC_MGMT_FUNC) + dev_info(dev, "id = %d active = %d type = %d\n" + "\tport = %d min bw = %d max bw = %d\n" + "\tmac_addr = %pM\n", pci_info->id, + pci_info->active, pci_info->type, + pci_info->default_port, + pci_info->tx_min_bw, + pci_info->tx_max_bw, pci_info->mac); } + if (ahw->op_mode == QLCNIC_MGMT_FUNC) + dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n", + ahw->max_pci_func, ahw->act_pci_func); + } else { - dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n", - err); + dev_err(dev, "Failed to get PCI Info, error = %d\n", err); err = -EIO; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index d63b5f728d75..9d0ae11589ce 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -883,11 +883,12 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, /* Configure eSwitch for port mirroring */ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, - u8 enable_mirroring, u8 pci_func) + u8 enable_mirroring, u8 pci_func) { + struct device *dev = &adapter->pdev->dev; + struct qlcnic_cmd_args cmd; int err = -EIO; u32 arg1; - struct qlcnic_cmd_args cmd; if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC || !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) @@ -901,13 +902,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, err = qlcnic_issue_cmd(adapter, &cmd); if (err != QLCNIC_RCODE_SUCCESS) - dev_err(&adapter->pdev->dev, - "Failed to configure port mirroring%d on eswitch:%d\n", + dev_err(dev, "Failed to configure port mirroring for vNIC function %d on eSwitch %d\n", pci_func, id); else - dev_info(&adapter->pdev->dev, - "Configured eSwitch %d for port mirroring:%d\n", - id, pci_func); + dev_info(dev, "Configured port mirroring for vNIC function %d on eSwitch %d\n", + pci_func, id); qlcnic_free_mbx_args(&cmd); return err; @@ -1122,14 +1121,13 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, return -EIO; } -static int -__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, - u32 *arg1, u32 *arg2) +static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, + u32 *arg1, u32 *arg2) { - int err = -EIO; + struct device *dev = &adapter->pdev->dev; struct qlcnic_cmd_args cmd; - u8 pci_func; - pci_func = (*arg1 >> 8); + u8 pci_func = *arg1 >> 8; + int err = -EIO; qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); @@ -1140,12 +1138,11 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, qlcnic_free_mbx_args(&cmd); if (err == QLCNIC_RCODE_SUCCESS) - dev_info(&adapter->pdev->dev, - "eSwitch port config for pci func %d\n", pci_func); + dev_info(dev, "Get eSwitch port config for vNIC function %d\n", + pci_func); else - dev_err(&adapter->pdev->dev, - "Failed to get eswitch port config for pci func %d\n", - pci_func); + dev_err(dev, "Failed to get eswitch port config for vNIC function %d\n", + pci_func); return err; } /* Configure eSwitch port @@ -1158,9 +1155,10 @@ op_type = 1 for port vlan_id int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg) { + struct device *dev = &adapter->pdev->dev; + struct qlcnic_cmd_args cmd; int err = -EIO, index; u32 arg1, arg2 = 0; - struct qlcnic_cmd_args cmd; u8 pci_func; if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) @@ -1217,11 +1215,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, qlcnic_free_mbx_args(&cmd); if (err != QLCNIC_RCODE_SUCCESS) - dev_err(&adapter->pdev->dev, - "Failed to configure eswitch pci func %d\n", pci_func); + dev_err(dev, "Failed to configure eswitch for vNIC function %d\n", + pci_func); else - dev_info(&adapter->pdev->dev, - "Configured eSwitch for pci func %d\n", pci_func); + dev_info(dev, "Configured eSwitch for vNIC function %d\n", + pci_func); return err; } -- GitLab From 6a531b7b1989ddef5ee45c619970037eb2374c0d Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Thu, 23 May 2013 21:04:36 +0000 Subject: [PATCH 0351/2900] qlcnic: Update version to 5.2.43 Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 00a09573faab..534e36ed855a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -38,8 +38,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 2 -#define _QLCNIC_LINUX_SUBVERSION 42 -#define QLCNIC_LINUX_VERSIONID "5.2.42" +#define _QLCNIC_LINUX_SUBVERSION 43 +#define QLCNIC_LINUX_VERSIONID "5.2.43" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) -- GitLab From 079956742452494326081349a66942654498cafa Mon Sep 17 00:00:00 2001 From: Zhang Yanfei Date: Mon, 29 Apr 2013 11:55:10 -0700 Subject: [PATCH 0352/2900] ipvs: change type of netns_ipvs->sysctl_sync_qlen_max This member of struct netns_ipvs is calculated from nr_free_buffer_pages so change its type to unsigned long in case of overflow. Also, type of its related proc var sync_qlen_max and the return type of function sysctl_sync_qlen_max() should be changed to unsigned long, too. Besides, the type of ipvs_master_sync_state->sync_queue_len should be changed to unsigned long accordingly. Signed-off-by: Zhang Yanfei Cc: Julian Anastasov Cc: David Miller Signed-off-by: Andrew Morton Signed-off-by: Simon Horman --- include/net/ip_vs.h | 8 ++++---- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4c062ccff9aa..4405886980c7 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -905,7 +905,7 @@ struct ip_vs_app { struct ipvs_master_sync_state { struct list_head sync_queue; struct ip_vs_sync_buff *sync_buff; - int sync_queue_len; + unsigned long sync_queue_len; unsigned int sync_queue_delay; struct task_struct *master_thread; struct delayed_work master_wakeup_work; @@ -998,7 +998,7 @@ struct netns_ipvs { int sysctl_snat_reroute; int sysctl_sync_ver; int sysctl_sync_ports; - int sysctl_sync_qlen_max; + unsigned long sysctl_sync_qlen_max; int sysctl_sync_sock_size; int sysctl_cache_bypass; int sysctl_expire_nodest_conn; @@ -1085,7 +1085,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) return ACCESS_ONCE(ipvs->sysctl_sync_ports); } -static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs) +static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) { return ipvs->sysctl_sync_qlen_max; } @@ -1138,7 +1138,7 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) return 1; } -static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs) +static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) { return IPVS_SYNC_QLEN_MAX; } diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5b142fb16480..70146496e73a 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1716,9 +1716,9 @@ static struct ctl_table vs_vars[] = { }, { .procname = "sync_qlen_max", - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_doulongvec_minmax, }, { .procname = "sync_sock_size", -- GitLab From 6d0bfe22611602f36617bc7aa2ffa1bbb2f54c67 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 22 May 2013 20:17:31 +0000 Subject: [PATCH 0353/2900] net: ipv6: Add IPv6 support to the ping socket. This adds the ability to send ICMPv6 echo requests without a raw socket. The equivalent ability for ICMPv4 was added in 2011. Instead of having separate code paths for IPv4 and IPv6, make most of the code in net/ipv4/ping.c dual-stack and only add a few IPv6-specific bits (like the protocol definition) to a new net/ipv6/ping.c. Hopefully this will reduce divergence and/or duplication of bugs in the future. Caveats: - Setting options via ancillary data (e.g., using IPV6_PKTINFO to specify the outgoing interface) is not yet supported. - There are no separate security settings for IPv4 and IPv6; everything is controlled by /proc/net/ipv4/ping_group_range. - The proc interface does not yet display IPv6 ping sockets properly. Tested with a patched copy of ping6 and using raw socket calls. Compiles and works with all of CONFIG_IPV6={n,m,y}. Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/ipv6.h | 6 + include/net/ping.h | 49 +++- include/net/transp_v6.h | 3 + net/ipv4/icmp.c | 5 +- net/ipv4/ping.c | 557 ++++++++++++++++++++++++++++------------ net/ipv6/Makefile | 2 +- net/ipv6/af_inet6.c | 12 + net/ipv6/icmp.c | 19 +- net/ipv6/ping.c | 216 ++++++++++++++++ 9 files changed, 698 insertions(+), 171 deletions(-) create mode 100644 net/ipv6/ping.c diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0810aa57c780..ab47582f6c0b 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -260,6 +260,12 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len); + +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6); + extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); diff --git a/include/net/ping.h b/include/net/ping.h index 682b5ae9af51..9242fa090d3d 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -13,6 +13,7 @@ #ifndef _PING_H #define _PING_H +#include #include /* PING_HTABLE_SIZE must be power of 2 */ @@ -28,6 +29,18 @@ */ #define GID_T_MAX (((gid_t)~0U) >> 1) +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +struct pingv6_ops { + int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); + int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); + void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict); +}; + struct ping_table { struct hlist_nulls_head hash[PING_HTABLE_SIZE]; rwlock_t lock; @@ -39,10 +52,39 @@ struct ping_iter_state { }; extern struct proto ping_prot; +extern struct ping_table ping_table; +#if IS_ENABLED(CONFIG_IPV6) +extern struct pingv6_ops pingv6_ops; +#endif +struct pingfakehdr { + struct icmphdr icmph; + struct iovec *iov; + sa_family_t family; + __wsum wcheck; +}; -extern void ping_rcv(struct sk_buff *); -extern void ping_err(struct sk_buff *, u32 info); +int ping_get_port(struct sock *sk, unsigned short ident); +void ping_hash(struct sock *sk); +void ping_unhash(struct sock *sk); + +int ping_init_sock(struct sock *sk); +void ping_close(struct sock *sk, long timeout); +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len); +void ping_err(struct sk_buff *skb, int offset, u32 info); +int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, + struct sk_buff *); + +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len); +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len); +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); +void ping_rcv(struct sk_buff *skb); #ifdef CONFIG_PROC_FS extern int __init ping_proc_init(void); @@ -50,6 +92,7 @@ extern void ping_proc_exit(void); #endif void __init ping_init(void); - +int __init pingv6_init(void); +void pingv6_exit(void); #endif /* _PING_H */ diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 938b7fd11204..eb40e71ff2ee 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; @@ -21,6 +22,8 @@ extern int ipv6_frag_init(void); extern void ipv6_frag_exit(void); /* transport protocols */ +extern int pingv6_init(void); +extern void pingv6_exit(void); extern int rawv6_init(void); extern void rawv6_exit(void); extern int udpv6_init(void); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 76e10b47e053..562efd91f457 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -939,7 +939,8 @@ int icmp_rcv(struct sk_buff *skb) void icmp_err(struct sk_buff *skb, u32 info) { struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int offset = iph->ihl<<2; + struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset); int type = icmp_hdr(skb)->type; int code = icmp_hdr(skb)->code; struct net *net = dev_net(skb->dev); @@ -949,7 +950,7 @@ void icmp_err(struct sk_buff *skb, u32 info) * triggered by ICMP_ECHOREPLY which sent from kernel. */ if (icmph->type != ICMP_ECHOREPLY) { - ping_err(skb, info); + ping_err(skb, offset, info); return; } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 7d93d62cd5fd..71f6ad02fa67 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,8 +45,18 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#include +#include +#endif -static struct ping_table ping_table; + +struct ping_table ping_table; +struct pingv6_ops pingv6_ops; +EXPORT_SYMBOL_GPL(pingv6_ops); static u16 ping_port_rover; @@ -58,6 +67,7 @@ static inline int ping_hashfn(struct net *net, unsigned int num, unsigned int ma pr_debug("hash(%d) = %d\n", num, res); return res; } +EXPORT_SYMBOL_GPL(ping_hash); static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, struct net *net, unsigned int num) @@ -65,7 +75,7 @@ static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; } -static int ping_v4_get_port(struct sock *sk, unsigned short ident) +int ping_get_port(struct sock *sk, unsigned short ident) { struct hlist_nulls_node *node; struct hlist_nulls_head *hlist; @@ -103,6 +113,10 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) ping_portaddr_for_each_entry(sk2, node, hlist) { isk2 = inet_sk(sk2); + /* BUG? Why is this reuse and not reuseaddr? ping.c + * doesn't turn off SO_REUSEADDR, and it doesn't expect + * that other ping processes can steal its packets. + */ if ((isk2->inet_num == ident) && (sk2 != sk) && (!sk2->sk_reuse || !sk->sk_reuse)) @@ -125,17 +139,18 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) write_unlock_bh(&ping_table.lock); return 1; } +EXPORT_SYMBOL_GPL(ping_get_port); -static void ping_v4_hash(struct sock *sk) +void ping_hash(struct sock *sk) { - pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); + pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); BUG(); /* "Please do not press this button again." */ } -static void ping_v4_unhash(struct sock *sk) +void ping_unhash(struct sock *sk) { struct inet_sock *isk = inet_sk(sk); - pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); @@ -146,31 +161,61 @@ static void ping_v4_unhash(struct sock *sk) write_unlock_bh(&ping_table.lock); } } +EXPORT_SYMBOL_GPL(ping_unhash); -static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr, - u16 ident, int dif) +static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) { struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); struct sock *sk = NULL; struct inet_sock *isk; struct hlist_nulls_node *hnode; + int dif = skb->dev->ifindex; + + if (skb->protocol == htons(ETH_P_IP)) { + pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", + (int)ident, &ip_hdr(skb)->daddr, dif); +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n", + (int)ident, &ipv6_hdr(skb)->daddr, dif); +#endif + } - pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", - (int)ident, &daddr, dif); read_lock_bh(&ping_table.lock); ping_portaddr_for_each_entry(sk, hnode, hslot) { isk = inet_sk(sk); - pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk, - (int)isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); - pr_debug("iterate\n"); if (isk->inet_num != ident) continue; - if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) - continue; + + if (skb->protocol == htons(ETH_P_IP) && + sk->sk_family == AF_INET) { + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, + (int) isk->inet_num, &isk->inet_rcv_saddr, + sk->sk_bound_dev_if); + + if (isk->inet_rcv_saddr && + isk->inet_rcv_saddr != ip_hdr(skb)->daddr) + continue; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6) && + sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, + (int) isk->inet_num, + &inet6_sk(sk)->rcv_saddr, + sk->sk_bound_dev_if); + + if (!ipv6_addr_any(&np->rcv_saddr) && + !ipv6_addr_equal(&np->rcv_saddr, + &ipv6_hdr(skb)->daddr)) + continue; +#endif + } + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) continue; @@ -200,7 +245,7 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, } -static int ping_init_sock(struct sock *sk) +int ping_init_sock(struct sock *sk) { struct net *net = sock_net(sk); kgid_t group = current_egid(); @@ -225,8 +270,9 @@ static int ping_init_sock(struct sock *sk) return -EACCES; } +EXPORT_SYMBOL_GPL(ping_init_sock); -static void ping_close(struct sock *sk, long timeout) +void ping_close(struct sock *sk, long timeout) { pr_debug("ping_close(sk=%p,sk->num=%u)\n", inet_sk(sk), inet_sk(sk)->inet_num); @@ -234,36 +280,122 @@ static void ping_close(struct sock *sk, long timeout) sk_common_release(sk); } +EXPORT_SYMBOL_GPL(ping_close); + +/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */ +int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + struct sockaddr *uaddr, int addr_len) { + struct net *net = sock_net(sk); + if (sk->sk_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; + int chk_addr_ret; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + + chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr); + + if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) + chk_addr_ret = RTN_LOCAL; + + if ((sysctl_ip_nonlocal_bind == 0 && + isk->freebind == 0 && isk->transparent == 0 && + chk_addr_ret != RTN_LOCAL) || + chk_addr_ret == RTN_MULTICAST || + chk_addr_ret == RTN_BROADCAST) + return -EADDRNOTAVAIL; + +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; + int addr_type, scoped, has_addr; + struct net_device *dev = NULL; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); + + addr_type = ipv6_addr_type(&addr->sin6_addr); + scoped = __ipv6_addr_needs_scope_id(addr_type); + if ((addr_type != IPV6_ADDR_ANY && + !(addr_type & IPV6_ADDR_UNICAST)) || + (scoped && !addr->sin6_scope_id)) + return -EINVAL; + + rcu_read_lock(); + if (addr->sin6_scope_id) { + dev = dev_get_by_index_rcu(net, addr->sin6_scope_id); + if (!dev) { + rcu_read_unlock(); + return -ENODEV; + } + } + has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev, + scoped); + rcu_read_unlock(); + + if (!(isk->freebind || isk->transparent || has_addr || + addr_type == IPV6_ADDR_ANY)) + return -EADDRNOTAVAIL; + + if (scoped) + sk->sk_bound_dev_if = addr->sin6_scope_id; +#endif + } else { + return -EAFNOSUPPORT; + } + return 0; +} +void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) +{ + if (saddr->sa_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *addr = (struct sockaddr_in *) saddr; + isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (saddr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr; + struct ipv6_pinfo *np = inet6_sk(sk); + np->rcv_saddr = np->saddr = addr->sin6_addr; +#endif + } +} + +void ping_clear_saddr(struct sock *sk, int dif) +{ + sk->sk_bound_dev_if = dif; + if (sk->sk_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + isk->inet_rcv_saddr = isk->inet_saddr = 0; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); + memset(&np->saddr, 0, sizeof(np->saddr)); +#endif + } +} /* * We need our own bind because there are no privileged id's == local ports. * Moreover, we don't allow binding to multi- and broadcast addresses. */ -static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct inet_sock *isk = inet_sk(sk); unsigned short snum; - int chk_addr_ret; int err; + int dif = sk->sk_bound_dev_if; - if (addr_len < sizeof(struct sockaddr_in)) - return -EINVAL; - - pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", - sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); - - chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); - if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) - chk_addr_ret = RTN_LOCAL; - - if ((sysctl_ip_nonlocal_bind == 0 && - isk->freebind == 0 && isk->transparent == 0 && - chk_addr_ret != RTN_LOCAL) || - chk_addr_ret == RTN_MULTICAST || - chk_addr_ret == RTN_BROADCAST) - return -EADDRNOTAVAIL; + err = ping_check_bind_addr(sk, isk, uaddr, addr_len); + if (err) + return err; lock_sock(sk); @@ -272,42 +404,50 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) goto out; err = -EADDRINUSE; - isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; - snum = ntohs(addr->sin_port); - if (ping_v4_get_port(sk, snum) != 0) { - isk->inet_saddr = isk->inet_rcv_saddr = 0; + ping_set_saddr(sk, uaddr); + snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port); + if (ping_get_port(sk, snum) != 0) { + ping_clear_saddr(sk, dif); goto out; } - pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n", + pr_debug("after bind(): num = %d, dif = %d\n", (int)isk->inet_num, - &isk->inet_rcv_saddr, (int)sk->sk_bound_dev_if); err = 0; - if (isk->inet_rcv_saddr) + if ((sk->sk_family == AF_INET && isk->inet_rcv_saddr) || + (sk->sk_family == AF_INET6 && + !ipv6_addr_any(&inet6_sk(sk)->rcv_saddr))) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; isk->inet_sport = htons(isk->inet_num); isk->inet_daddr = 0; isk->inet_dport = 0; + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) + memset(&inet6_sk(sk)->daddr, 0, sizeof(inet6_sk(sk)->daddr)); +#endif + sk_dst_reset(sk); out: release_sock(sk); pr_debug("ping_v4_bind -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_bind); /* * Is this a supported type of ICMP message? */ -static inline int ping_supported(int type, int code) +static inline int ping_supported(int family, int type, int code) { - if (type == ICMP_ECHO && code == 0) - return 1; - return 0; + return (family == AF_INET && type == ICMP_ECHO && code == 0) || + (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0); } /* @@ -315,30 +455,42 @@ static inline int ping_supported(int type, int code) * sort of error condition. */ -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); - -void ping_err(struct sk_buff *skb, u32 info) +void ping_err(struct sk_buff *skb, int offset, u32 info) { - struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int family; + struct icmphdr *icmph; struct inet_sock *inet_sock; - int type = icmp_hdr(skb)->type; - int code = icmp_hdr(skb)->code; + int type; + int code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; int err; + if (skb->protocol == htons(ETH_P_IP)) { + family = AF_INET; + type = icmp_hdr(skb)->type; + code = icmp_hdr(skb)->code; + icmph = (struct icmphdr *)(skb->data + offset); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + family = AF_INET6; + type = icmp6_hdr(skb)->icmp6_type; + code = icmp6_hdr(skb)->icmp6_code; + icmph = (struct icmphdr *) (skb->data + offset); + } else { + BUG(); + } + /* We assume the packet has already been checked by icmp_unreach */ - if (!ping_supported(icmph->type, icmph->code)) + if (!ping_supported(family, icmph->type, icmph->code)) return; - pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, - code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n", + skb->protocol, type, code, ntohs(icmph->un.echo.id), + ntohs(icmph->un.echo.sequence)); - sk = ping_v4_lookup(net, iph->daddr, iph->saddr, - ntohs(icmph->un.echo.id), skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk == NULL) { pr_debug("no socket, dropping\n"); return; /* No socket for error */ @@ -349,72 +501,83 @@ void ping_err(struct sk_buff *skb, u32 info) harderr = 0; inet_sock = inet_sk(sk); - switch (type) { - default: - case ICMP_TIME_EXCEEDED: - err = EHOSTUNREACH; - break; - case ICMP_SOURCE_QUENCH: - /* This is not a real error but ping wants to see it. - * Report it with some fake errno. */ - err = EREMOTEIO; - break; - case ICMP_PARAMETERPROB: - err = EPROTO; - harderr = 1; - break; - case ICMP_DEST_UNREACH: - if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - ipv4_sk_update_pmtu(skb, sk, info); - if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { - err = EMSGSIZE; - harderr = 1; - break; + if (skb->protocol == htons(ETH_P_IP)) { + switch (type) { + default: + case ICMP_TIME_EXCEEDED: + err = EHOSTUNREACH; + break; + case ICMP_SOURCE_QUENCH: + /* This is not a real error but ping wants to see it. + * Report it with some fake errno. + */ + err = EREMOTEIO; + break; + case ICMP_PARAMETERPROB: + err = EPROTO; + harderr = 1; + break; + case ICMP_DEST_UNREACH: + if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ + ipv4_sk_update_pmtu(skb, sk, info); + if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { + err = EMSGSIZE; + harderr = 1; + break; + } + goto out; } - goto out; - } - err = EHOSTUNREACH; - if (code <= NR_ICMP_UNREACH) { - harderr = icmp_err_convert[code].fatal; - err = icmp_err_convert[code].errno; + err = EHOSTUNREACH; + if (code <= NR_ICMP_UNREACH) { + harderr = icmp_err_convert[code].fatal; + err = icmp_err_convert[code].errno; + } + break; + case ICMP_REDIRECT: + /* See ICMP_SOURCE_QUENCH */ + ipv4_sk_redirect(skb, sk); + err = EREMOTEIO; + break; } - break; - case ICMP_REDIRECT: - /* See ICMP_SOURCE_QUENCH */ - ipv4_sk_redirect(skb, sk); - err = EREMOTEIO; - break; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + harderr = pingv6_ops.icmpv6_err_convert(type, code, &err); +#endif } /* * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!inet_sock->recverr) { + if ((family == AF_INET && !inet_sock->recverr) || + (family == AF_INET6 && !inet6_sk(sk)->recverr)) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; } else { - ip_icmp_error(sk, skb, err, 0 /* no remote port */, - info, (u8 *)icmph); + if (family == AF_INET) { + ip_icmp_error(sk, skb, err, 0 /* no remote port */, + info, (u8 *)icmph); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + pingv6_ops.ipv6_icmp_error(sk, skb, err, 0, + info, (u8 *)icmph); +#endif + } } sk->sk_err = err; sk->sk_error_report(sk); out: sock_put(sk); } +EXPORT_SYMBOL_GPL(ping_err); /* - * Copy and checksum an ICMP Echo packet from user space into a buffer. + * Copy and checksum an ICMP Echo packet from user space into a buffer + * starting from the payload. */ -struct pingfakehdr { - struct icmphdr icmph; - struct iovec *iov; - __wsum wcheck; -}; - -static int ping_getfrag(void *from, char *to, - int offset, int fraglen, int odd, struct sk_buff *skb) +int ping_getfrag(void *from, char *to, + int offset, int fraglen, int odd, struct sk_buff *skb) { struct pingfakehdr *pfh = (struct pingfakehdr *)from; @@ -425,20 +588,33 @@ static int ping_getfrag(void *from, char *to, pfh->iov, 0, fraglen - sizeof(struct icmphdr), &pfh->wcheck)) return -EFAULT; + } else if (offset < sizeof(struct icmphdr)) { + BUG(); + } else { + if (csum_partial_copy_fromiovecend + (to, pfh->iov, offset - sizeof(struct icmphdr), + fraglen, &pfh->wcheck)) + return -EFAULT; + } - return 0; +#if IS_ENABLED(CONFIG_IPV6) + /* For IPv6, checksum each skb as we go along, as expected by + * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in + * wcheck, it will be finalized in ping_v4_push_pending_frames. + */ + if (pfh->family == AF_INET6) { + skb->csum = pfh->wcheck; + skb->ip_summed = CHECKSUM_NONE; + pfh->wcheck = 0; } - if (offset < sizeof(struct icmphdr)) - BUG(); - if (csum_partial_copy_fromiovecend - (to, pfh->iov, offset - sizeof(struct icmphdr), - fraglen, &pfh->wcheck)) - return -EFAULT; +#endif + return 0; } +EXPORT_SYMBOL_GPL(ping_getfrag); -static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, - struct flowi4 *fl4) +static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, + struct flowi4 *fl4) { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); @@ -450,24 +626,9 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, return ip_push_pending_frames(sk, fl4); } -static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) -{ - struct net *net = sock_net(sk); - struct flowi4 fl4; - struct inet_sock *inet = inet_sk(sk); - struct ipcm_cookie ipc; - struct icmphdr user_icmph; - struct pingfakehdr pfh; - struct rtable *rt = NULL; - struct ip_options_data opt_copy; - int free = 0; - __be32 saddr, daddr, faddr; - u8 tos; - int err; - - pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); - +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len) { + u8 type, code; if (len > 0xFFFF) return -EMSGSIZE; @@ -482,15 +643,53 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* * Fetch the ICMP header provided by the userland. - * iovec is modified! + * iovec is modified! The ICMP header is consumed. */ - - if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, - sizeof(struct icmphdr))) + if (memcpy_fromiovec(user_icmph, msg->msg_iov, icmph_len)) return -EFAULT; - if (!ping_supported(user_icmph.type, user_icmph.code)) + + if (family == AF_INET) { + type = ((struct icmphdr *) user_icmph)->type; + code = ((struct icmphdr *) user_icmph)->code; +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + type = ((struct icmp6hdr *) user_icmph)->icmp6_type; + code = ((struct icmp6hdr *) user_icmph)->icmp6_code; +#endif + } else { + BUG(); + } + + if (!ping_supported(family, type, code)) return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(ping_common_sendmsg); + +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct net *net = sock_net(sk); + struct flowi4 fl4; + struct inet_sock *inet = inet_sk(sk); + struct ipcm_cookie ipc; + struct icmphdr user_icmph; + struct pingfakehdr pfh; + struct rtable *rt = NULL; + struct ip_options_data opt_copy; + int free = 0; + __be32 saddr, daddr, faddr; + u8 tos; + int err; + + pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + /* * Get and verify the address. */ @@ -595,13 +794,14 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; pfh.iov = msg->msg_iov; pfh.wcheck = 0; + pfh.family = AF_INET; err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else - err = ping_push_pending_frames(sk, &pfh, &fl4); + err = ping_v4_push_pending_frames(sk, &pfh, &fl4); release_sock(sk); out: @@ -622,11 +822,13 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } -static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); - struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + int family = sk->sk_family; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; struct sk_buff *skb; int copied, err; @@ -636,11 +838,22 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); + if (addr_len) { + if (family == AF_INET) + *addr_len = sizeof(*sin); + else if (family == AF_INET6 && addr_len) + *addr_len = sizeof(*sin6); + } - if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { + return ip_recv_error(sk, msg, len); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + return pingv6_ops.ipv6_recv_error(sk, msg, len); +#endif + } + } skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -659,15 +872,40 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sock_recv_timestamp(msg, sk, skb); - /* Copy the address. */ - if (sin) { + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { + sin = (struct sockaddr_in *) msg->msg_name; sin->sin_family = AF_INET; sin->sin_port = 0 /* skb->h.uh->source */; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); + +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); + sin6 = (struct sockaddr_in6 *) msg->msg_name; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; + + if (np->sndflow) + sin6->sin6_flowinfo = ip6_flowinfo(ip6); + + if (__ipv6_addr_needs_scope_id( + ipv6_addr_type(&sin6->sin6_addr))) + sin6->sin6_scope_id = IP6CB(skb)->iif; + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); +#endif + } else { + BUG(); } - if (isk->cmsg_flags) - ip_cmsg_recv(msg, skb); + err = copied; done: @@ -676,8 +914,9 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pr_debug("ping_recvmsg -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_recvmsg); -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", inet_sk(sk), inet_sk(sk)->inet_num, skb); @@ -688,6 +927,7 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } return 0; } +EXPORT_SYMBOL_GPL(ping_queue_rcv_skb); /* @@ -698,10 +938,7 @@ void ping_rcv(struct sk_buff *skb) { struct sock *sk; struct net *net = dev_net(skb->dev); - struct iphdr *iph = ip_hdr(skb); struct icmphdr *icmph = icmp_hdr(skb); - __be32 saddr = iph->saddr; - __be32 daddr = iph->daddr; /* We assume the packet has already been checked by icmp_rcv */ @@ -711,8 +948,7 @@ void ping_rcv(struct sk_buff *skb) /* Push ICMP header back */ skb_push(skb, skb->data - (u8 *)icmph); - sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), - skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk != NULL) { pr_debug("rcv on socket %p\n", sk); ping_queue_rcv_skb(sk, skb_get(skb)); @@ -723,6 +959,7 @@ void ping_rcv(struct sk_buff *skb) /* We're called from icmp_rcv(). kfree_skb() is done there. */ } +EXPORT_SYMBOL_GPL(ping_rcv); struct proto ping_prot = { .name = "PING", @@ -733,14 +970,14 @@ struct proto ping_prot = { .disconnect = udp_disconnect, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, - .sendmsg = ping_sendmsg, + .sendmsg = ping_v4_sendmsg, .recvmsg = ping_recvmsg, .bind = ping_bind, .backlog_rcv = ping_queue_rcv_skb, .release_cb = ip4_datagram_release_cb, - .hash = ping_v4_hash, - .unhash = ping_v4_unhash, - .get_port = ping_v4_get_port, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, .obj_size = sizeof(struct inet_sock), }; EXPORT_SYMBOL(ping_prot); diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 9af088d2cdaa..470a9c008e9b 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ - raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index ab5c7ad482cd..a5ac969aeefe 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -840,6 +841,9 @@ static int __init inet6_init(void) if (err) goto out_unregister_udplite_proto; + err = proto_register(&pingv6_prot, 1); + if (err) + goto out_unregister_ping_proto; /* We MUST register RAW sockets before we create the ICMP6, * IGMP6, or NDISC control sockets. @@ -930,6 +934,10 @@ static int __init inet6_init(void) if (err) goto ipv6_packet_fail; + err = pingv6_init(); + if (err) + goto pingv6_fail; + #ifdef CONFIG_SYSCTL err = ipv6_sysctl_register(); if (err) @@ -942,6 +950,8 @@ static int __init inet6_init(void) sysctl_fail: ipv6_packet_cleanup(); #endif +pingv6_fail: + pingv6_exit(); ipv6_packet_fail: tcpv6_exit(); tcpv6_fail: @@ -985,6 +995,8 @@ static int __init inet6_init(void) rtnl_unregister_all(PF_INET6); out_sock_register_fail: rawv6_exit(); +out_unregister_ping_proto: + proto_unregister(&pingv6_prot); out_unregister_raw_proto: proto_unregister(&rawv6_prot); out_unregister_udplite_proto: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4ff0a42b8c7..1d2902e61786 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -57,6 +57,7 @@ #include #include +#include #include #include #include @@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net) static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { + /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ + struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); struct net *net = dev_net(skb->dev); if (type == ICMPV6_PKT_TOOBIG) ip6_update_pmtu(skb, net, info, 0, 0); else if (type == NDISC_REDIRECT) ip6_redirect(skb, net, 0, 0); + + if (!(type & ICMPV6_INFOMSG_MASK)) + if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) + ping_err(skb, offset, info); } static int icmpv6_rcv(struct sk_buff *skb); @@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset) return (*op & 0xC0) == 0x80; } -static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len) { struct sk_buff *skb; struct icmp6hdr *icmp6h; @@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb) static inline void mip6_addr_swap(struct sk_buff *skb) {} #endif -static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, - struct sock *sk, struct flowi6 *fl6) +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6) { struct dst_entry *dst, *dst2; struct flowi6 fl2; @@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb) skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", + LIMIT_NETDEBUG(KERN_DEBUG + "ICMPv6 checksum failed [%pI6c > %pI6c]\n", saddr, daddr); goto csum_error; } @@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb) break; case ICMPV6_ECHO_REPLY: - /* we couldn't care less */ + ping_rcv(skb); break; case ICMPV6_PKT_TOOBIG: diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c new file mode 100644 index 000000000000..a6462d657c15 --- /dev/null +++ b/net/ipv6/ping.c @@ -0,0 +1,216 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * "Ping" sockets + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Based on ipv4/ping.c code. + * + * Authors: Lorenzo Colitti (IPv6 support) + * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6), + * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct proto pingv6_prot = { + .name = "PINGv6", + .owner = THIS_MODULE, + .init = ping_init_sock, + .close = ping_close, + .connect = ip6_datagram_connect, + .disconnect = udp_disconnect, + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .sendmsg = ping_v6_sendmsg, + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, + .obj_size = sizeof(struct raw6_sock), +}; +EXPORT_SYMBOL_GPL(pingv6_prot); + +static struct inet_protosw pingv6_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_ICMPV6, + .prot = &pingv6_prot, + .ops = &inet6_dgram_ops, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, +}; + + +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +{ + return -EAFNOSUPPORT; +} +int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb) +{ + return -EAFNOSUPPORT; +} +int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) +{ + return -EAFNOSUPPORT; +} +void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload) {} +int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict) +{ + return 0; +} + +int __init pingv6_init(void) +{ + pingv6_ops.ipv6_recv_error = ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; + return inet6_register_protosw(&pingv6_protosw); +} + +/* This never gets called because it's not possible to unload the ipv6 module, + * but just in case. + */ +void pingv6_exit(void) +{ + pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; + inet6_unregister_protosw(&pingv6_protosw); +} + +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct icmp6hdr user_icmph; + int addr_type; + struct in6_addr *daddr; + int iif = 0; + struct flowi6 fl6; + int err; + int hlimit; + struct dst_entry *dst; + struct rt6_info *rt; + struct pingfakehdr pfh; + + pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + + if (msg->msg_name) { + struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; + if (msg->msg_namelen < sizeof(struct sockaddr_in6) || + u->sin6_family != AF_INET6) { + return -EINVAL; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { + return -EINVAL; + } + daddr = &(u->sin6_addr); + iif = u->sin6_scope_id; + } else { + if (sk->sk_state != TCP_ESTABLISHED) + return -EDESTADDRREQ; + daddr = &np->daddr; + } + + if (!iif) + iif = sk->sk_bound_dev_if; + + addr_type = ipv6_addr_type(daddr); + if (__ipv6_addr_needs_scope_id(addr_type) && !iif) + return -EINVAL; + if (addr_type & IPV6_ADDR_MAPPED) + return -EINVAL; + + /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ + + memset(&fl6, 0, sizeof(fl6)); + + fl6.flowi6_proto = IPPROTO_ICMPV6; + fl6.saddr = np->saddr; + fl6.daddr = *daddr; + fl6.fl6_icmp_type = user_icmph.icmp6_type; + fl6.fl6_icmp_code = user_icmph.icmp6_code; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 1); + if (IS_ERR(dst)) + return PTR_ERR(dst); + rt = (struct rt6_info *) dst; + + np = inet6_sk(sk); + if (!np) + return -EBADF; + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + pfh.icmph.type = user_icmph.icmp6_type; + pfh.icmph.code = user_icmph.icmp6_code; + pfh.icmph.checksum = 0; + pfh.icmph.un.echo.id = inet->inet_sport; + pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; + pfh.iov = msg->msg_iov; + pfh.wcheck = 0; + pfh.family = AF_INET6; + + if (ipv6_addr_is_multicast(&fl6.daddr)) + hlimit = np->mcast_hops; + else + hlimit = np->hop_limit; + if (hlimit < 0) + hlimit = ip6_dst_hoplimit(dst); + + err = ip6_append_data(sk, ping_getfrag, &pfh, len, + 0, hlimit, + np->tclass, NULL, &fl6, rt, + MSG_DONTWAIT, np->dontfrag); + + if (err) { + ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, + ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, + (struct icmp6hdr *) &pfh.icmph, + len); + } + + return err; +} -- GitLab From 8513fbd880093f00a47e85a552f14ca2de8d84d6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 00:52:31 +0000 Subject: [PATCH 0354/2900] net: ethernet: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Also, unnecessary dev_set_drvdata() is removed, because the driver core clears the driver data to NULL after device_release or on probe failure. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/aeroflex/greth.c | 4 +--- drivers/net/ethernet/amd/sunlance.c | 6 ++---- drivers/net/ethernet/broadcom/sb1250-mac.c | 9 ++++----- drivers/net/ethernet/freescale/fec_mpc52xx.c | 9 ++++----- .../ethernet/freescale/fs_enet/fs_enet-main.c | 5 ++--- .../ethernet/freescale/fs_enet/mii-bitbang.c | 6 ++---- .../net/ethernet/freescale/fs_enet/mii-fec.c | 6 ++---- drivers/net/ethernet/freescale/gianfar.c | 6 ++---- drivers/net/ethernet/freescale/gianfar_ptp.c | 4 ++-- drivers/net/ethernet/freescale/ucc_geth.c | 4 ++-- drivers/net/ethernet/freescale/xgmac_mdio.c | 4 ++-- drivers/net/ethernet/ibm/ehea/ehea_main.c | 4 ++-- drivers/net/ethernet/ibm/emac/mal.c | 6 ++---- drivers/net/ethernet/ibm/emac/rgmii.c | 18 ++++++++---------- drivers/net/ethernet/ibm/emac/tah.c | 14 ++++++-------- drivers/net/ethernet/ibm/emac/zmii.c | 18 ++++++++---------- drivers/net/ethernet/netx-eth.c | 4 +--- drivers/net/ethernet/octeon/octeon_mgmt.c | 4 ++-- drivers/net/ethernet/sun/niu.c | 5 ++--- drivers/net/ethernet/sun/sunhme.c | 4 ++-- drivers/net/ethernet/sun/sunqe.c | 10 ++++------ drivers/net/ethernet/xilinx/ll_temac_main.c | 5 ++--- .../net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++---- 23 files changed, 66 insertions(+), 95 deletions(-) diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 269295403fc4..7ff4b30d55ea 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1565,7 +1565,7 @@ static int greth_of_probe(struct platform_device *ofdev) static int greth_of_remove(struct platform_device *of_dev) { - struct net_device *ndev = dev_get_drvdata(&of_dev->dev); + struct net_device *ndev = platform_get_drvdata(of_dev); struct greth_private *greth = netdev_priv(ndev); /* Free descriptor areas */ @@ -1573,8 +1573,6 @@ static int greth_of_remove(struct platform_device *of_dev) dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys); - dev_set_drvdata(&of_dev->dev, NULL); - if (greth->phy) phy_stop(greth->phy); mdiobus_unregister(greth->mdio); diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index f47b780892e9..ece56831a647 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1470,7 +1470,7 @@ static int sparc_lance_probe_one(struct platform_device *op, goto fail; } - dev_set_drvdata(&op->dev, lp); + platform_set_drvdata(op, lp); printk(KERN_INFO "%s: LANCE %pM\n", dev->name, dev->dev_addr); @@ -1501,7 +1501,7 @@ static int sunlance_sbus_probe(struct platform_device *op) static int sunlance_sbus_remove(struct platform_device *op) { - struct lance_private *lp = dev_get_drvdata(&op->dev); + struct lance_private *lp = platform_get_drvdata(op); struct net_device *net_dev = lp->dev; unregister_netdev(net_dev); @@ -1510,8 +1510,6 @@ static int sunlance_sbus_remove(struct platform_device *op) free_netdev(net_dev); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index e80bfb60c3ef..c2777712da99 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2197,7 +2197,7 @@ static const struct net_device_ops sbmac_netdev_ops = { static int sbmac_init(struct platform_device *pldev, long long base) { - struct net_device *dev = dev_get_drvdata(&pldev->dev); + struct net_device *dev = platform_get_drvdata(pldev); int idx = pldev->id; struct sbmac_softc *sc = netdev_priv(dev); unsigned char *eaddr; @@ -2275,7 +2275,7 @@ static int sbmac_init(struct platform_device *pldev, long long base) dev->name); goto free_mdio; } - dev_set_drvdata(&pldev->dev, sc->mii_bus); + platform_set_drvdata(pldev, sc->mii_bus); err = register_netdev(dev); if (err) { @@ -2300,7 +2300,6 @@ static int sbmac_init(struct platform_device *pldev, long long base) return 0; unreg_mdio: mdiobus_unregister(sc->mii_bus); - dev_set_drvdata(&pldev->dev, NULL); free_mdio: mdiobus_free(sc->mii_bus); uninit_ctx: @@ -2624,7 +2623,7 @@ static int sbmac_probe(struct platform_device *pldev) goto out_unmap; } - dev_set_drvdata(&pldev->dev, dev); + platform_set_drvdata(pldev, dev); SET_NETDEV_DEV(dev, &pldev->dev); sc = netdev_priv(dev); @@ -2649,7 +2648,7 @@ static int sbmac_probe(struct platform_device *pldev) static int __exit sbmac_remove(struct platform_device *pldev) { - struct net_device *dev = dev_get_drvdata(&pldev->dev); + struct net_device *dev = platform_get_drvdata(pldev); struct sbmac_softc *sc = netdev_priv(dev); unregister_netdev(dev); diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 9bc15e2365bb..9947765e90c5 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -981,7 +981,7 @@ static int mpc52xx_fec_probe(struct platform_device *op) goto err_node; /* We're done ! */ - dev_set_drvdata(&op->dev, ndev); + platform_set_drvdata(op, ndev); netdev_info(ndev, "%s MAC %pM\n", op->dev.of_node->full_name, ndev->dev_addr); @@ -1010,7 +1010,7 @@ mpc52xx_fec_remove(struct platform_device *op) struct net_device *ndev; struct mpc52xx_fec_priv *priv; - ndev = dev_get_drvdata(&op->dev); + ndev = platform_get_drvdata(op); priv = netdev_priv(ndev); unregister_netdev(ndev); @@ -1030,14 +1030,13 @@ mpc52xx_fec_remove(struct platform_device *op) free_netdev(ndev); - dev_set_drvdata(&op->dev, NULL); return 0; } #ifdef CONFIG_PM static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state) { - struct net_device *dev = dev_get_drvdata(&op->dev); + struct net_device *dev = platform_get_drvdata(op); if (netif_running(dev)) mpc52xx_fec_close(dev); @@ -1047,7 +1046,7 @@ static int mpc52xx_fec_of_suspend(struct platform_device *op, pm_message_t state static int mpc52xx_fec_of_resume(struct platform_device *op) { - struct net_device *dev = dev_get_drvdata(&op->dev); + struct net_device *dev = platform_get_drvdata(op); mpc52xx_fec_hw_init(dev); mpc52xx_fec_reset_stats(dev); diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c index edc120094c34..8de53a14a6f4 100644 --- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c @@ -1048,7 +1048,7 @@ static int fs_enet_probe(struct platform_device *ofdev) } SET_NETDEV_DEV(ndev, &ofdev->dev); - dev_set_drvdata(&ofdev->dev, ndev); + platform_set_drvdata(ofdev, ndev); fep = netdev_priv(ndev); fep->dev = &ofdev->dev; @@ -1106,7 +1106,6 @@ static int fs_enet_probe(struct platform_device *ofdev) fep->ops->cleanup_data(ndev); out_free_dev: free_netdev(ndev); - dev_set_drvdata(&ofdev->dev, NULL); out_put: of_node_put(fpi->phy_node); out_free_fpi: @@ -1116,7 +1115,7 @@ static int fs_enet_probe(struct platform_device *ofdev) static int fs_enet_remove(struct platform_device *ofdev) { - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); + struct net_device *ndev = platform_get_drvdata(ofdev); struct fs_enet_private *fep = netdev_priv(ndev); unregister_netdev(ndev); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 2bafbd37c247..844ecfa84d17 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -179,7 +179,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) } new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); + platform_set_drvdata(ofdev, new_bus); ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); if (ret) @@ -188,7 +188,6 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) return 0; out_free_irqs: - dev_set_drvdata(&ofdev->dev, NULL); kfree(new_bus->irq); out_unmap_regs: iounmap(bitbang->dir); @@ -202,11 +201,10 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) static int fs_enet_mdio_remove(struct platform_device *ofdev) { - struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); + struct mii_bus *bus = platform_get_drvdata(ofdev); struct bb_info *bitbang = bus->priv; mdiobus_unregister(bus); - dev_set_drvdata(&ofdev->dev, NULL); kfree(bus->irq); free_mdio_bitbang(bus); iounmap(bitbang->dir); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 18e8ef203736..2f1c46a12f05 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -180,7 +180,7 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) } new_bus->parent = &ofdev->dev; - dev_set_drvdata(&ofdev->dev, new_bus); + platform_set_drvdata(ofdev, new_bus); ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); if (ret) @@ -189,7 +189,6 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) return 0; out_free_irqs: - dev_set_drvdata(&ofdev->dev, NULL); kfree(new_bus->irq); out_unmap_regs: iounmap(fec->fecp); @@ -204,11 +203,10 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) static int fs_enet_mdio_remove(struct platform_device *ofdev) { - struct mii_bus *bus = dev_get_drvdata(&ofdev->dev); + struct mii_bus *bus = platform_get_drvdata(ofdev); struct fec_info *fec = bus->priv; mdiobus_unregister(bus); - dev_set_drvdata(&ofdev->dev, NULL); kfree(bus->irq); iounmap(fec->fecp); kfree(fec); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 2375a01715a0..14f06947e70d 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1000,7 +1000,7 @@ static int gfar_probe(struct platform_device *ofdev) spin_lock_init(&priv->bflock); INIT_WORK(&priv->reset_task, gfar_reset_task); - dev_set_drvdata(&ofdev->dev, priv); + platform_set_drvdata(ofdev, priv); regs = priv->gfargrp[0].regs; gfar_detect_errata(priv); @@ -1240,15 +1240,13 @@ static int gfar_probe(struct platform_device *ofdev) static int gfar_remove(struct platform_device *ofdev) { - struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); + struct gfar_private *priv = platform_get_drvdata(ofdev); if (priv->phy_node) of_node_put(priv->phy_node); if (priv->tbi_node) of_node_put(priv->tbi_node); - dev_set_drvdata(&ofdev->dev, NULL); - unregister_netdev(priv->ndev); unmap_group_regs(priv); free_gfar_dev(priv); diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index 083ea2b4d20a..098f133908ae 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -519,7 +519,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) } gfar_phc_index = ptp_clock_index(etsects->clock); - dev_set_drvdata(&dev->dev, etsects); + platform_set_drvdata(dev, etsects); return 0; @@ -537,7 +537,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) static int gianfar_ptp_remove(struct platform_device *dev) { - struct etsects *etsects = dev_get_drvdata(&dev->dev); + struct etsects *etsects = platform_get_drvdata(dev); gfar_write(&etsects->regs->tmr_temask, 0); gfar_write(&etsects->regs->tmr_ctrl, 0); diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index e04c59818f60..3c43dac894ec 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3564,7 +3564,7 @@ static void ucc_geth_timeout(struct net_device *dev) static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) { - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); + struct net_device *ndev = platform_get_drvdata(ofdev); struct ucc_geth_private *ugeth = netdev_priv(ndev); if (!netif_running(ndev)) @@ -3592,7 +3592,7 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) static int ucc_geth_resume(struct platform_device *ofdev) { - struct net_device *ndev = dev_get_drvdata(&ofdev->dev); + struct net_device *ndev = platform_get_drvdata(ofdev); struct ucc_geth_private *ugeth = netdev_priv(ndev); int err; diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c index 418068b941b1..c1b6e7e31aac 100644 --- a/drivers/net/ethernet/freescale/xgmac_mdio.c +++ b/drivers/net/ethernet/freescale/xgmac_mdio.c @@ -227,7 +227,7 @@ static int xgmac_mdio_probe(struct platform_device *pdev) goto err_registration; } - dev_set_drvdata(&pdev->dev, bus); + platform_set_drvdata(pdev, bus); return 0; @@ -242,7 +242,7 @@ static int xgmac_mdio_probe(struct platform_device *pdev) static int xgmac_mdio_remove(struct platform_device *pdev) { - struct mii_bus *bus = dev_get_drvdata(&pdev->dev); + struct mii_bus *bus = platform_get_drvdata(pdev); mdiobus_unregister(bus); iounmap(bus->priv); diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 90ea0b1673ca..0605e76c7edd 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3289,7 +3289,7 @@ static int ehea_probe_adapter(struct platform_device *dev, adapter->pd = EHEA_PD_ID; - dev_set_drvdata(&dev->dev, adapter); + platform_set_drvdata(dev, adapter); /* initialize adapter and ports */ @@ -3360,7 +3360,7 @@ static int ehea_probe_adapter(struct platform_device *dev, static int ehea_remove(struct platform_device *dev) { - struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev); + struct ehea_adapter *adapter = platform_get_drvdata(dev); int i; for (i = 0; i < EHEA_MAX_PORTS; i++) diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c index 610ed223d1db..856ea66c9223 100644 --- a/drivers/net/ethernet/ibm/emac/mal.c +++ b/drivers/net/ethernet/ibm/emac/mal.c @@ -696,7 +696,7 @@ static int mal_probe(struct platform_device *ofdev) /* Advertise this instance to the rest of the world */ wmb(); - dev_set_drvdata(&ofdev->dev, mal); + platform_set_drvdata(ofdev, mal); mal_dbg_register(mal); @@ -722,7 +722,7 @@ static int mal_probe(struct platform_device *ofdev) static int mal_remove(struct platform_device *ofdev) { - struct mal_instance *mal = dev_get_drvdata(&ofdev->dev); + struct mal_instance *mal = platform_get_drvdata(ofdev); MAL_DBG(mal, "remove" NL); @@ -735,8 +735,6 @@ static int mal_remove(struct platform_device *ofdev) "mal%d: commac list is not empty on remove!\n", mal->index); - dev_set_drvdata(&ofdev->dev, NULL); - free_irq(mal->serr_irq, mal); free_irq(mal->txde_irq, mal); free_irq(mal->txeob_irq, mal); diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index 39251765b55d..c47e23d6eeaa 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -95,7 +95,7 @@ static inline u32 rgmii_mode_mask(int mode, int input) int rgmii_attach(struct platform_device *ofdev, int input, int mode) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct rgmii_regs __iomem *p = dev->base; RGMII_DBG(dev, "attach(%d)" NL, input); @@ -124,7 +124,7 @@ int rgmii_attach(struct platform_device *ofdev, int input, int mode) void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct rgmii_regs __iomem *p = dev->base; u32 ssr; @@ -146,7 +146,7 @@ void rgmii_set_speed(struct platform_device *ofdev, int input, int speed) void rgmii_get_mdio(struct platform_device *ofdev, int input) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct rgmii_regs __iomem *p = dev->base; u32 fer; @@ -167,7 +167,7 @@ void rgmii_get_mdio(struct platform_device *ofdev, int input) void rgmii_put_mdio(struct platform_device *ofdev, int input) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct rgmii_regs __iomem *p = dev->base; u32 fer; @@ -188,7 +188,7 @@ void rgmii_put_mdio(struct platform_device *ofdev, int input) void rgmii_detach(struct platform_device *ofdev, int input) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct rgmii_regs __iomem *p; BUG_ON(!dev || dev->users == 0); @@ -214,7 +214,7 @@ int rgmii_get_regs_len(struct platform_device *ofdev) void *rgmii_dump_regs(struct platform_device *ofdev, void *buf) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); struct emac_ethtool_regs_subhdr *hdr = buf; struct rgmii_regs *regs = (struct rgmii_regs *)(hdr + 1); @@ -279,7 +279,7 @@ static int rgmii_probe(struct platform_device *ofdev) (dev->flags & EMAC_RGMII_FLAG_HAS_MDIO) ? "" : "out"); wmb(); - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); return 0; @@ -291,9 +291,7 @@ static int rgmii_probe(struct platform_device *ofdev) static int rgmii_remove(struct platform_device *ofdev) { - struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); - - dev_set_drvdata(&ofdev->dev, NULL); + struct rgmii_instance *dev = platform_get_drvdata(ofdev); WARN_ON(dev->users != 0); diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c index 795f1393e2b6..c231a4a32c4d 100644 --- a/drivers/net/ethernet/ibm/emac/tah.c +++ b/drivers/net/ethernet/ibm/emac/tah.c @@ -25,7 +25,7 @@ int tah_attach(struct platform_device *ofdev, int channel) { - struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); + struct tah_instance *dev = platform_get_drvdata(ofdev); mutex_lock(&dev->lock); /* Reset has been done at probe() time... nothing else to do for now */ @@ -37,7 +37,7 @@ int tah_attach(struct platform_device *ofdev, int channel) void tah_detach(struct platform_device *ofdev, int channel) { - struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); + struct tah_instance *dev = platform_get_drvdata(ofdev); mutex_lock(&dev->lock); --dev->users; @@ -46,7 +46,7 @@ void tah_detach(struct platform_device *ofdev, int channel) void tah_reset(struct platform_device *ofdev) { - struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); + struct tah_instance *dev = platform_get_drvdata(ofdev); struct tah_regs __iomem *p = dev->base; int n; @@ -74,7 +74,7 @@ int tah_get_regs_len(struct platform_device *ofdev) void *tah_dump_regs(struct platform_device *ofdev, void *buf) { - struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); + struct tah_instance *dev = platform_get_drvdata(ofdev); struct emac_ethtool_regs_subhdr *hdr = buf; struct tah_regs *regs = (struct tah_regs *)(hdr + 1); @@ -118,7 +118,7 @@ static int tah_probe(struct platform_device *ofdev) goto err_free; } - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); /* Initialize TAH and enable IPv4 checksum verification, no TSO yet */ tah_reset(ofdev); @@ -137,9 +137,7 @@ static int tah_probe(struct platform_device *ofdev) static int tah_remove(struct platform_device *ofdev) { - struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); - - dev_set_drvdata(&ofdev->dev, NULL); + struct tah_instance *dev = platform_get_drvdata(ofdev); WARN_ON(dev->users != 0); diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index f91202f42125..4cdf286f7ee3 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -84,7 +84,7 @@ static inline u32 zmii_mode_mask(int mode, int input) int zmii_attach(struct platform_device *ofdev, int input, int *mode) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); struct zmii_regs __iomem *p = dev->base; ZMII_DBG(dev, "init(%d, %d)" NL, input, *mode); @@ -150,7 +150,7 @@ int zmii_attach(struct platform_device *ofdev, int input, int *mode) void zmii_get_mdio(struct platform_device *ofdev, int input) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); u32 fer; ZMII_DBG2(dev, "get_mdio(%d)" NL, input); @@ -163,7 +163,7 @@ void zmii_get_mdio(struct platform_device *ofdev, int input) void zmii_put_mdio(struct platform_device *ofdev, int input) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); ZMII_DBG2(dev, "put_mdio(%d)" NL, input); mutex_unlock(&dev->lock); @@ -172,7 +172,7 @@ void zmii_put_mdio(struct platform_device *ofdev, int input) void zmii_set_speed(struct platform_device *ofdev, int input, int speed) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); u32 ssr; mutex_lock(&dev->lock); @@ -193,7 +193,7 @@ void zmii_set_speed(struct platform_device *ofdev, int input, int speed) void zmii_detach(struct platform_device *ofdev, int input) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); BUG_ON(!dev || dev->users == 0); @@ -218,7 +218,7 @@ int zmii_get_regs_len(struct platform_device *ofdev) void *zmii_dump_regs(struct platform_device *ofdev, void *buf) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); + struct zmii_instance *dev = platform_get_drvdata(ofdev); struct emac_ethtool_regs_subhdr *hdr = buf; struct zmii_regs *regs = (struct zmii_regs *)(hdr + 1); @@ -272,7 +272,7 @@ static int zmii_probe(struct platform_device *ofdev) printk(KERN_INFO "ZMII %s initialized\n", ofdev->dev.of_node->full_name); wmb(); - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); return 0; @@ -284,9 +284,7 @@ static int zmii_probe(struct platform_device *ofdev) static int zmii_remove(struct platform_device *ofdev) { - struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); - - dev_set_drvdata(&ofdev->dev, NULL); + struct zmii_instance *dev = platform_get_drvdata(ofdev); WARN_ON(dev->users != 0); diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c index cb9e63831500..5da3ffb61062 100644 --- a/drivers/net/ethernet/netx-eth.c +++ b/drivers/net/ethernet/netx-eth.c @@ -430,11 +430,9 @@ static int netx_eth_drv_probe(struct platform_device *pdev) static int netx_eth_drv_remove(struct platform_device *pdev) { - struct net_device *ndev = dev_get_drvdata(&pdev->dev); + struct net_device *ndev = platform_get_drvdata(pdev); struct netx_eth_priv *priv = netdev_priv(ndev); - platform_set_drvdata(pdev, NULL); - unregister_netdev(ndev); xc_stop(priv->xc); free_xc(priv->xc); diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c index 921729f9c85c..e6e029237a63 100644 --- a/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -1437,7 +1437,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev) SET_NETDEV_DEV(netdev, &pdev->dev); - dev_set_drvdata(&pdev->dev, netdev); + platform_set_drvdata(pdev, netdev); p = netdev_priv(netdev); netif_napi_add(netdev, &p->napi, octeon_mgmt_napi_poll, OCTEON_MGMT_NAPI_WEIGHT); @@ -1559,7 +1559,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev) static int octeon_mgmt_remove(struct platform_device *pdev) { - struct net_device *netdev = dev_get_drvdata(&pdev->dev); + struct net_device *netdev = platform_get_drvdata(pdev); unregister_netdev(netdev); free_netdev(netdev); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 95cff98d8a34..fa322409bff3 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -10108,7 +10108,7 @@ static int niu_of_probe(struct platform_device *op) goto err_out_iounmap; } - dev_set_drvdata(&op->dev, dev); + platform_set_drvdata(op, dev); niu_device_announce(np); @@ -10145,7 +10145,7 @@ static int niu_of_probe(struct platform_device *op) static int niu_of_remove(struct platform_device *op) { - struct net_device *dev = dev_get_drvdata(&op->dev); + struct net_device *dev = platform_get_drvdata(op); if (dev) { struct niu *np = netdev_priv(dev); @@ -10175,7 +10175,6 @@ static int niu_of_remove(struct platform_device *op) niu_put_parent(np); free_netdev(dev); - dev_set_drvdata(&op->dev, NULL); } return 0; } diff --git a/drivers/net/ethernet/sun/sunhme.c b/drivers/net/ethernet/sun/sunhme.c index 436fa9d5a071..171f5b0809c4 100644 --- a/drivers/net/ethernet/sun/sunhme.c +++ b/drivers/net/ethernet/sun/sunhme.c @@ -2506,7 +2506,7 @@ static struct quattro *quattro_sbus_find(struct platform_device *child) struct quattro *qp; op = to_platform_device(parent); - qp = dev_get_drvdata(&op->dev); + qp = platform_get_drvdata(op); if (qp) return qp; @@ -2521,7 +2521,7 @@ static struct quattro *quattro_sbus_find(struct platform_device *child) qp->next = qfe_sbus_list; qfe_sbus_list = qp; - dev_set_drvdata(&op->dev, qp); + platform_set_drvdata(op, qp); } return qp; } diff --git a/drivers/net/ethernet/sun/sunqe.c b/drivers/net/ethernet/sun/sunqe.c index 8182591bc187..b072f4dba033 100644 --- a/drivers/net/ethernet/sun/sunqe.c +++ b/drivers/net/ethernet/sun/sunqe.c @@ -767,7 +767,7 @@ static struct sunqec *get_qec(struct platform_device *child) struct platform_device *op = to_platform_device(child->dev.parent); struct sunqec *qecp; - qecp = dev_get_drvdata(&op->dev); + qecp = platform_get_drvdata(op); if (!qecp) { qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); if (qecp) { @@ -801,7 +801,7 @@ static struct sunqec *get_qec(struct platform_device *child) goto fail; } - dev_set_drvdata(&op->dev, qecp); + platform_set_drvdata(op, qecp); qecp->next_module = root_qec_dev; root_qec_dev = qecp; @@ -902,7 +902,7 @@ static int qec_ether_init(struct platform_device *op) if (res) goto fail; - dev_set_drvdata(&op->dev, qe); + platform_set_drvdata(op, qe); printk(KERN_INFO "%s: qe channel[%d] %pM\n", dev->name, qe->channel, dev->dev_addr); @@ -934,7 +934,7 @@ static int qec_sbus_probe(struct platform_device *op) static int qec_sbus_remove(struct platform_device *op) { - struct sunqe *qp = dev_get_drvdata(&op->dev); + struct sunqe *qp = platform_get_drvdata(op); struct net_device *net_dev = qp->dev; unregister_netdev(net_dev); @@ -948,8 +948,6 @@ static int qec_sbus_remove(struct platform_device *op) free_netdev(net_dev); - dev_set_drvdata(&op->dev, NULL); - return 0; } diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 57c2e5ef2804..58eb4488beff 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1007,7 +1007,7 @@ static int temac_of_probe(struct platform_device *op) return -ENOMEM; ether_setup(ndev); - dev_set_drvdata(&op->dev, ndev); + platform_set_drvdata(op, ndev); SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; @@ -1136,7 +1136,7 @@ static int temac_of_probe(struct platform_device *op) static int temac_of_remove(struct platform_device *op) { - struct net_device *ndev = dev_get_drvdata(&op->dev); + struct net_device *ndev = platform_get_drvdata(op); struct temac_local *lp = netdev_priv(ndev); temac_mdio_teardown(lp); @@ -1145,7 +1145,6 @@ static int temac_of_remove(struct platform_device *op) if (lp->phy_node) of_node_put(lp->phy_node); lp->phy_node = NULL; - dev_set_drvdata(&op->dev, NULL); iounmap(lp->regs); if (lp->sdma_regs) iounmap(lp->sdma_regs); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 24748e8367a1..fb7d1c28a2ea 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1484,7 +1484,7 @@ static int axienet_of_probe(struct platform_device *op) return -ENOMEM; ether_setup(ndev); - dev_set_drvdata(&op->dev, ndev); + platform_set_drvdata(op, ndev); SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ @@ -1622,7 +1622,7 @@ static int axienet_of_probe(struct platform_device *op) static int axienet_of_remove(struct platform_device *op) { - struct net_device *ndev = dev_get_drvdata(&op->dev); + struct net_device *ndev = platform_get_drvdata(op); struct axienet_local *lp = netdev_priv(ndev); axienet_mdio_teardown(lp); @@ -1632,8 +1632,6 @@ static int axienet_of_remove(struct platform_device *op) of_node_put(lp->phy_node); lp->phy_node = NULL; - dev_set_drvdata(&op->dev, NULL); - iounmap(lp->regs); if (lp->dma_regs) iounmap(lp->dma_regs); -- GitLab From 42e52bf9e3ae80fd44b21ddfcd64c54e6db2ff76 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 25 May 2013 04:12:10 +0000 Subject: [PATCH 0355/2900] net: add netnotifier event for upper device change Now when upper device is changed, event is not propagated via RT Netlink to userspace. Userspace might never now about the change. Fix this by adding upper-device-change notifier event. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + net/core/dev.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0ebd63ae2cc8..ea7b6bce9ea0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1593,6 +1593,7 @@ struct packet_offload { #define NETDEV_RELEASE 0x0012 #define NETDEV_NOTIFY_PEERS 0x0013 #define NETDEV_JOIN 0x0014 +#define NETDEV_CHANGEUPPER 0x0015 extern int register_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb); diff --git a/net/core/dev.c b/net/core/dev.c index 7229bc30e509..50c02ded1d69 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4411,7 +4411,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, else list_add_tail_rcu(&upper->list, &dev->upper_dev_list); dev_hold(upper_dev); - + call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); return 0; } @@ -4471,6 +4471,7 @@ void netdev_upper_dev_unlink(struct net_device *dev, list_del_rcu(&upper->list); dev_put(upper_dev); kfree_rcu(upper, rcu); + call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); } EXPORT_SYMBOL(netdev_upper_dev_unlink); -- GitLab From 1f6afc81088a1f5a472b272408730c73b72c68aa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 24 May 2013 15:03:54 +0000 Subject: [PATCH 0356/2900] tcp: remove one indentation level in tcp_rcv_state_process() Remove one level of indentation 'introduced' in commit c3ae62af8e75 (tcp: should drop incoming frames without ACK flag set) if (true) { ... } @acceptable variable is a boolean. This patch is a pure cleanup. Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 269 +++++++++++++++++++++---------------------- 1 file changed, 133 insertions(+), 136 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8230cd6243aa..40614257d2c5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5536,6 +5536,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct inet_connection_sock *icsk = inet_csk(sk); struct request_sock *req; int queued = 0; + bool acceptable; tp->rx_opt.saw_tstamp = 0; @@ -5606,157 +5607,153 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; /* step 5: check the ACK field */ - if (true) { - int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | - FLAG_UPDATE_TS_RECENT) > 0; - - switch (sk->sk_state) { - case TCP_SYN_RECV: - if (acceptable) { - /* Once we leave TCP_SYN_RECV, we no longer - * need req so release it. - */ - if (req) { - tcp_synack_rtt_meas(sk, req); - tp->total_retrans = req->num_retrans; - - reqsk_fastopen_remove(sk, req, false); - } else { - /* Make sure socket is routed, for - * correct metrics. - */ - icsk->icsk_af_ops->rebuild_header(sk); - tcp_init_congestion_control(sk); + acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | + FLAG_UPDATE_TS_RECENT) > 0; - tcp_mtup_init(sk); - tcp_init_buffer_space(sk); - tp->copied_seq = tp->rcv_nxt; - } - smp_mb(); - tcp_set_state(sk, TCP_ESTABLISHED); - sk->sk_state_change(sk); + switch (sk->sk_state) { + case TCP_SYN_RECV: + if (acceptable) { + /* Once we leave TCP_SYN_RECV, we no longer + * need req so release it. + */ + if (req) { + tcp_synack_rtt_meas(sk, req); + tp->total_retrans = req->num_retrans; - /* Note, that this wakeup is only for marginal - * crossed SYN case. Passively open sockets - * are not waked up, because sk->sk_sleep == - * NULL and sk->sk_socket == NULL. + reqsk_fastopen_remove(sk, req, false); + } else { + /* Make sure socket is routed, for + * correct metrics. */ - if (sk->sk_socket) - sk_wake_async(sk, - SOCK_WAKE_IO, POLL_OUT); - - tp->snd_una = TCP_SKB_CB(skb)->ack_seq; - tp->snd_wnd = ntohs(th->window) << - tp->rx_opt.snd_wscale; - tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); - - if (tp->rx_opt.tstamp_ok) - tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; - - if (req) { - /* Re-arm the timer because data may - * have been sent out. This is similar - * to the regular data transmission case - * when new data has just been ack'ed. - * - * (TFO) - we could try to be more - * aggressive and retranmitting any data - * sooner based on when they were sent - * out. - */ - tcp_rearm_rto(sk); - } else - tcp_init_metrics(sk); + icsk->icsk_af_ops->rebuild_header(sk); + tcp_init_congestion_control(sk); - /* Prevent spurious tcp_cwnd_restart() on - * first data packet. + tcp_mtup_init(sk); + tcp_init_buffer_space(sk); + tp->copied_seq = tp->rcv_nxt; + } + smp_mb(); + tcp_set_state(sk, TCP_ESTABLISHED); + sk->sk_state_change(sk); + + /* Note, that this wakeup is only for marginal + * crossed SYN case. Passively open sockets + * are not waked up, because sk->sk_sleep == + * NULL and sk->sk_socket == NULL. + */ + if (sk->sk_socket) + sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); + + tp->snd_una = TCP_SKB_CB(skb)->ack_seq; + tp->snd_wnd = ntohs(th->window) << + tp->rx_opt.snd_wscale; + tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); + + if (tp->rx_opt.tstamp_ok) + tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; + + if (req) { + /* Re-arm the timer because data may + * have been sent out. This is similar + * to the regular data transmission case + * when new data has just been ack'ed. + * + * (TFO) - we could try to be more aggressive + * and retransmitting any data sooner based + * on when they are sent out. */ - tp->lsndtime = tcp_time_stamp; + tcp_rearm_rto(sk); + } else + tcp_init_metrics(sk); - tcp_initialize_rcv_mss(sk); - tcp_fast_path_on(tp); - } else { - return 1; - } - break; + /* Prevent spurious tcp_cwnd_restart() on + * first data packet. + */ + tp->lsndtime = tcp_time_stamp; - case TCP_FIN_WAIT1: - /* If we enter the TCP_FIN_WAIT1 state and we are a - * Fast Open socket and this is the first acceptable - * ACK we have received, this would have acknowledged - * our SYNACK so stop the SYNACK timer. + tcp_initialize_rcv_mss(sk); + tcp_fast_path_on(tp); + } else { + return 1; + } + break; + + case TCP_FIN_WAIT1: + /* If we enter the TCP_FIN_WAIT1 state and we are a + * Fast Open socket and this is the first acceptable + * ACK we have received, this would have acknowledged + * our SYNACK so stop the SYNACK timer. + */ + if (req != NULL) { + /* Return RST if ack_seq is invalid. + * Note that RFC793 only says to generate a + * DUPACK for it but for TCP Fast Open it seems + * better to treat this case like TCP_SYN_RECV + * above. */ - if (req != NULL) { - /* Return RST if ack_seq is invalid. - * Note that RFC793 only says to generate a - * DUPACK for it but for TCP Fast Open it seems - * better to treat this case like TCP_SYN_RECV - * above. - */ - if (!acceptable) + if (!acceptable) + return 1; + /* We no longer need the request sock. */ + reqsk_fastopen_remove(sk, req, false); + tcp_rearm_rto(sk); + } + if (tp->snd_una == tp->write_seq) { + struct dst_entry *dst; + + tcp_set_state(sk, TCP_FIN_WAIT2); + sk->sk_shutdown |= SEND_SHUTDOWN; + + dst = __sk_dst_get(sk); + if (dst) + dst_confirm(dst); + + if (!sock_flag(sk, SOCK_DEAD)) { + /* Wake up lingering close() */ + sk->sk_state_change(sk); + } else { + int tmo; + + if (tp->linger2 < 0 || + (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && + after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { + tcp_done(sk); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); return 1; - /* We no longer need the request sock. */ - reqsk_fastopen_remove(sk, req, false); - tcp_rearm_rto(sk); - } - if (tp->snd_una == tp->write_seq) { - struct dst_entry *dst; - - tcp_set_state(sk, TCP_FIN_WAIT2); - sk->sk_shutdown |= SEND_SHUTDOWN; - - dst = __sk_dst_get(sk); - if (dst) - dst_confirm(dst); - - if (!sock_flag(sk, SOCK_DEAD)) - /* Wake up lingering close() */ - sk->sk_state_change(sk); - else { - int tmo; - - if (tp->linger2 < 0 || - (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && - after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { - tcp_done(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); - return 1; - } + } - tmo = tcp_fin_time(sk); - if (tmo > TCP_TIMEWAIT_LEN) { - inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); - } else if (th->fin || sock_owned_by_user(sk)) { - /* Bad case. We could lose such FIN otherwise. - * It is not a big problem, but it looks confusing - * and not so rare event. We still can lose it now, - * if it spins in bh_lock_sock(), but it is really - * marginal case. - */ - inet_csk_reset_keepalive_timer(sk, tmo); - } else { - tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); - goto discard; - } + tmo = tcp_fin_time(sk); + if (tmo > TCP_TIMEWAIT_LEN) { + inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); + } else if (th->fin || sock_owned_by_user(sk)) { + /* Bad case. We could lose such FIN otherwise. + * It is not a big problem, but it looks confusing + * and not so rare event. We still can lose it now, + * if it spins in bh_lock_sock(), but it is really + * marginal case. + */ + inet_csk_reset_keepalive_timer(sk, tmo); + } else { + tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); + goto discard; } } - break; + } + break; - case TCP_CLOSING: - if (tp->snd_una == tp->write_seq) { - tcp_time_wait(sk, TCP_TIME_WAIT, 0); - goto discard; - } - break; + case TCP_CLOSING: + if (tp->snd_una == tp->write_seq) { + tcp_time_wait(sk, TCP_TIME_WAIT, 0); + goto discard; + } + break; - case TCP_LAST_ACK: - if (tp->snd_una == tp->write_seq) { - tcp_update_metrics(sk); - tcp_done(sk); - goto discard; - } - break; + case TCP_LAST_ACK: + if (tp->snd_una == tp->write_seq) { + tcp_update_metrics(sk); + tcp_done(sk); + goto discard; } + break; } /* step 6: check the URG bit */ -- GitLab From 61eb900352ff731d990d5415ce9f04e4af6a6136 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 24 May 2013 18:36:13 +0000 Subject: [PATCH 0357/2900] tcp: Remove another indentation level in tcp_rcv_state_process case TCP_SYN_RECV: can have another indentation level removed by converting if (acceptable) { ...; } else { return 1; } to if (!acceptable) return 1; ...; Reflow code and comments to fit 80 columns. Another pure cleanup patch. Signed-off-by: Joe Perches Improved-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 110 ++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40614257d2c5..413b480b9329 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5612,70 +5612,62 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, switch (sk->sk_state) { case TCP_SYN_RECV: - if (acceptable) { - /* Once we leave TCP_SYN_RECV, we no longer - * need req so release it. - */ - if (req) { - tcp_synack_rtt_meas(sk, req); - tp->total_retrans = req->num_retrans; + if (!acceptable) + return 1; - reqsk_fastopen_remove(sk, req, false); - } else { - /* Make sure socket is routed, for - * correct metrics. - */ - icsk->icsk_af_ops->rebuild_header(sk); - tcp_init_congestion_control(sk); + /* Once we leave TCP_SYN_RECV, we no longer need req + * so release it. + */ + if (req) { + tcp_synack_rtt_meas(sk, req); + tp->total_retrans = req->num_retrans; - tcp_mtup_init(sk); - tcp_init_buffer_space(sk); - tp->copied_seq = tp->rcv_nxt; - } - smp_mb(); - tcp_set_state(sk, TCP_ESTABLISHED); - sk->sk_state_change(sk); - - /* Note, that this wakeup is only for marginal - * crossed SYN case. Passively open sockets - * are not waked up, because sk->sk_sleep == - * NULL and sk->sk_socket == NULL. - */ - if (sk->sk_socket) - sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); - - tp->snd_una = TCP_SKB_CB(skb)->ack_seq; - tp->snd_wnd = ntohs(th->window) << - tp->rx_opt.snd_wscale; - tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); - - if (tp->rx_opt.tstamp_ok) - tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; - - if (req) { - /* Re-arm the timer because data may - * have been sent out. This is similar - * to the regular data transmission case - * when new data has just been ack'ed. - * - * (TFO) - we could try to be more aggressive - * and retransmitting any data sooner based - * on when they are sent out. - */ - tcp_rearm_rto(sk); - } else - tcp_init_metrics(sk); + reqsk_fastopen_remove(sk, req, false); + } else { + /* Make sure socket is routed, for correct metrics. */ + icsk->icsk_af_ops->rebuild_header(sk); + tcp_init_congestion_control(sk); + + tcp_mtup_init(sk); + tcp_init_buffer_space(sk); + tp->copied_seq = tp->rcv_nxt; + } + smp_mb(); + tcp_set_state(sk, TCP_ESTABLISHED); + sk->sk_state_change(sk); - /* Prevent spurious tcp_cwnd_restart() on - * first data packet. + /* Note, that this wakeup is only for marginal crossed SYN case. + * Passively open sockets are not waked up, because + * sk->sk_sleep == NULL and sk->sk_socket == NULL. + */ + if (sk->sk_socket) + sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT); + + tp->snd_una = TCP_SKB_CB(skb)->ack_seq; + tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; + tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); + + if (tp->rx_opt.tstamp_ok) + tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; + + if (req) { + /* Re-arm the timer because data may have been sent out. + * This is similar to the regular data transmission case + * when new data has just been ack'ed. + * + * (TFO) - we could try to be more aggressive and + * retransmitting any data sooner based on when they + * are sent out. */ - tp->lsndtime = tcp_time_stamp; + tcp_rearm_rto(sk); + } else + tcp_init_metrics(sk); - tcp_initialize_rcv_mss(sk); - tcp_fast_path_on(tp); - } else { - return 1; - } + /* Prevent spurious tcp_cwnd_restart() on first data packet */ + tp->lsndtime = tcp_time_stamp; + + tcp_initialize_rcv_mss(sk); + tcp_fast_path_on(tp); break; case TCP_FIN_WAIT1: -- GitLab From c48b22daa6062fff9eded311b4d6974c29b40487 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 24 May 2013 18:06:58 +0000 Subject: [PATCH 0358/2900] tcp: Remove 2 indentation levels in tcp_rcv_state_process case TCP_FIN_WAIT1 can also be simplified by reversing tests and adding breaks; Add braces after case and move automatic definitions. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 76 +++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 413b480b9329..9579e1a5a144 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5670,7 +5670,10 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, tcp_fast_path_on(tp); break; - case TCP_FIN_WAIT1: + case TCP_FIN_WAIT1: { + struct dst_entry *dst; + int tmo; + /* If we enter the TCP_FIN_WAIT1 state and we are a * Fast Open socket and this is the first acceptable * ACK we have received, this would have acknowledged @@ -5689,48 +5692,47 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, reqsk_fastopen_remove(sk, req, false); tcp_rearm_rto(sk); } - if (tp->snd_una == tp->write_seq) { - struct dst_entry *dst; + if (tp->snd_una != tp->write_seq) + break; - tcp_set_state(sk, TCP_FIN_WAIT2); - sk->sk_shutdown |= SEND_SHUTDOWN; + tcp_set_state(sk, TCP_FIN_WAIT2); + sk->sk_shutdown |= SEND_SHUTDOWN; - dst = __sk_dst_get(sk); - if (dst) - dst_confirm(dst); + dst = __sk_dst_get(sk); + if (dst) + dst_confirm(dst); - if (!sock_flag(sk, SOCK_DEAD)) { - /* Wake up lingering close() */ - sk->sk_state_change(sk); - } else { - int tmo; - - if (tp->linger2 < 0 || - (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && - after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { - tcp_done(sk); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); - return 1; - } + if (!sock_flag(sk, SOCK_DEAD)) { + /* Wake up lingering close() */ + sk->sk_state_change(sk); + break; + } - tmo = tcp_fin_time(sk); - if (tmo > TCP_TIMEWAIT_LEN) { - inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); - } else if (th->fin || sock_owned_by_user(sk)) { - /* Bad case. We could lose such FIN otherwise. - * It is not a big problem, but it looks confusing - * and not so rare event. We still can lose it now, - * if it spins in bh_lock_sock(), but it is really - * marginal case. - */ - inet_csk_reset_keepalive_timer(sk, tmo); - } else { - tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); - goto discard; - } - } + if (tp->linger2 < 0 || + (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && + after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) { + tcp_done(sk); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA); + return 1; + } + + tmo = tcp_fin_time(sk); + if (tmo > TCP_TIMEWAIT_LEN) { + inet_csk_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN); + } else if (th->fin || sock_owned_by_user(sk)) { + /* Bad case. We could lose such FIN otherwise. + * It is not a big problem, but it looks confusing + * and not so rare event. We still can lose it now, + * if it spins in bh_lock_sock(), but it is really + * marginal case. + */ + inet_csk_reset_keepalive_timer(sk, tmo); + } else { + tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); + goto discard; } break; + } case TCP_CLOSING: if (tp->snd_una == tp->write_seq) { -- GitLab From 810e08ee425f8d7327e4b30069a9b2b3dccfc67d Mon Sep 17 00:00:00 2001 From: Fredrik Soderstedt Date: Wed, 17 Apr 2013 13:50:53 +0200 Subject: [PATCH 0359/2900] mmc: core: Only execute tuning for SDR50 and SDR104 Only execute tuning for sd and sdio devices that are using SDR50 or SDR104. Make sure clock is hold during tuning for sdio devices. Signed-off-by: Fredrik Soderstedt Acked-by: Johan Rudholm Acked-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/sd.c | 9 +++++++-- drivers/mmc/core/sdio.c | 12 ++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 9e645e19cec6..8373d2288bb1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -646,8 +646,13 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) if (err) goto out; - /* SPI mode doesn't define CMD19 */ - if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) { + /* + * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and + * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. + */ + if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && + (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || + card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) { mmc_host_clk_hold(card->host); err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 6889a821c1da..444668c210b2 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -563,10 +563,18 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) if (err) goto out; - /* Initialize and start re-tuning timer */ - if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) + /* + * SPI mode doesn't define CMD19 and tuning is only valid for SDR50 and + * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. + */ + if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && + ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || + (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) { + mmc_host_clk_hold(card->host); err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); + mmc_host_clk_release(card->host); + } out: -- GitLab From b689167984bc14ed06c8bcff52ef5eb1fd9cf83b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 18 Apr 2013 11:02:07 +0200 Subject: [PATCH 0360/2900] mmc: core: Re-use code for MMC_CAP2_DETECT_ON_ERR in polling mode Previously the MMC_CAP2_DETECT_ON_ERR was invented for detecting slow card removal. In was never a realy good solution and a proper fix has been merged using gpio debouncing instead. We remove this cap in this patch. Although when using polling card detect mode, the code invented for MMC_CAP2_DETECT_ON_ERR is re-used to complete card removal in an earlier phase. There are no need waiting for the polling timeout to elapse in this case. Signed-off-by: Ulf Hansson Reviewed-by: Kevin Liu Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 5 ++--- include/linux/mmc/host.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c40396f23202..6e4d04df37e0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2325,14 +2325,13 @@ int mmc_detect_card_removed(struct mmc_host *host) * The card will be considered unchanged unless we have been asked to * detect a change or host requires polling to provide card detection. */ - if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) && - !(host->caps2 & MMC_CAP2_DETECT_ON_ERR)) + if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) return ret; host->detect_change = 0; if (!ret) { ret = _mmc_detect_card_removed(host); - if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) { + if (ret && (host->caps & MMC_CAP_NEEDS_POLL)) { /* * Schedule a detect work as soon as possible to let a * rescan handle the card removal. diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index e326ae2882a0..38f60a97b218 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -272,7 +272,6 @@ struct mmc_host { #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) #define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ -#define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */ #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ -- GitLab From 775a9362b5d7e006ff6bbec5cb9c9c9d5a751696 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 18 Apr 2013 15:41:55 +0300 Subject: [PATCH 0361/2900] mmc: card: Adding support for sanitize in eMMC 4.5 The sanitize support is added as a user-app ioctl call, and was removed from the block-device request, since its purpose is to be invoked not via File-System but by a user. This feature deletes the unmap memory region of the eMMC card, by writing to a specific register in the EXT_CSD. unmap region is the memory region that was previously deleted (by erase, trim or discard operation). In order to avoid timeout when sanitizing large-scale cards, the timeout for sanitize operation is 240 seconds. Signed-off-by: Yaniv Gardi Signed-off-by: Maya Erez Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 68 ++++++++++++++++++++++++++------------ drivers/mmc/card/queue.c | 2 +- drivers/mmc/core/core.c | 19 +++++++++++ drivers/mmc/core/mmc_ops.c | 2 ++ include/linux/mmc/core.h | 2 ++ include/linux/mmc/host.h | 1 + 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index dd27b0783d52..80b05b280241 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -58,6 +58,8 @@ MODULE_ALIAS("mmc:block"); #define INAND_CMD38_ARG_SECTRIM1 0x81 #define INAND_CMD38_ARG_SECTRIM2 0x88 #define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */ +#define MMC_SANITIZE_REQ_TIMEOUT 240000 +#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) #define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ (req->cmd_flags & REQ_META)) && \ @@ -408,6 +410,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, return err; } +static int ioctl_do_sanitize(struct mmc_card *card) +{ + int err; + + if (!(mmc_can_sanitize(card) && + (card->host->caps2 & MMC_CAP2_SANITIZE))) { + pr_warn("%s: %s - SANITIZE is not supported\n", + mmc_hostname(card->host), __func__); + err = -EOPNOTSUPP; + goto out; + } + + pr_debug("%s: %s - SANITIZE IN PROGRESS...\n", + mmc_hostname(card->host), __func__); + + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_SANITIZE_START, 1, + MMC_SANITIZE_REQ_TIMEOUT); + + if (err) + pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n", + mmc_hostname(card->host), __func__, err); + + pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host), + __func__); +out: + return err; +} + static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_ioc_cmd __user *ic_ptr) { @@ -510,6 +541,16 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } + if (MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) { + err = ioctl_do_sanitize(card); + + if (err) + pr_err("%s: ioctl_do_sanitize() failed. err = %d", + __func__, err); + + goto cmd_rel_host; + } + mmc_wait_for_req(card->host, &mrq); if (cmd.error) { @@ -939,10 +980,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, { struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg, trim_arg, erase_arg; + unsigned int from, nr, arg; int err = 0, type = MMC_BLK_SECDISCARD; - if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) { + if (!(mmc_can_secure_erase_trim(card))) { err = -EOPNOTSUPP; goto out; } @@ -950,23 +991,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, from = blk_rq_pos(req); nr = blk_rq_sectors(req); - /* The sanitize operation is supported at v4.5 only */ - if (mmc_can_sanitize(card)) { - erase_arg = MMC_ERASE_ARG; - trim_arg = MMC_TRIM_ARG; - } else { - erase_arg = MMC_SECURE_ERASE_ARG; - trim_arg = MMC_SECURE_TRIM1_ARG; - } + if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr)) + arg = MMC_SECURE_TRIM1_ARG; + else + arg = MMC_SECURE_ERASE_ARG; - if (mmc_erase_group_aligned(card, from, nr)) - arg = erase_arg; - else if (mmc_can_trim(card)) - arg = trim_arg; - else { - err = -EINVAL; - goto out; - } retry: if (card->quirks & MMC_QUIRK_INAND_CMD38) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, @@ -1002,9 +1031,6 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, goto out; } - if (mmc_can_sanitize(card)) - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_SANITIZE_START, 1, 0); out_retry: if (err && !mmc_blk_reset(md, card->host, type)) goto retry; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 9447a0e970d1..fa9632eb63f1 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -173,7 +173,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, /* granularity must not be greater than max. discard */ if (card->pref_erase > max_discard) q->limits.discard_granularity = 0; - if (mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card)) + if (mmc_can_secure_erase_trim(card)) queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, q); } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 6e4d04df37e0..48b9fec34737 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -402,6 +402,7 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host, context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; + if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) { err = host->areq->err_check(host->card, @@ -436,6 +437,24 @@ static void mmc_wait_for_req_done(struct mmc_host *host, wait_for_completion(&mrq->completion); cmd = mrq->cmd; + + /* + * If host has timed out waiting for the sanitize + * to complete, card might be still in programming state + * so let's try to bring the card out of programming + * state. + */ + if (cmd->sanitize_busy && cmd->error == -ETIMEDOUT) { + if (!mmc_interrupt_hpi(host->card)) { + pr_warning("%s: %s: Interrupted sanitize\n", + mmc_hostname(host), __func__); + cmd->error = 0; + break; + } else { + pr_err("%s: %s: Failed to interrupt sanitize\n", + mmc_hostname(host), __func__); + } + } if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) break; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 49f04bc9d0eb..124af5238d0a 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -431,6 +431,8 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, cmd.cmd_timeout_ms = timeout_ms; + if (index == EXT_CSD_SANITIZE_START) + cmd.sanitize_busy = true; err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES); if (err) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 39613b9a6fc5..bd06ff566bfc 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -96,6 +96,8 @@ struct mmc_command { */ unsigned int cmd_timeout_ms; /* in milliseconds */ + /* Set this flag only for blocking sanitize request */ + bool sanitize_busy; struct mmc_data *data; /* data segment associated with cmd */ struct mmc_request *mrq; /* associated request */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 38f60a97b218..6f3851533de0 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -280,6 +280,7 @@ struct mmc_host { #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR) #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ +#define MMC_CAP2_SANITIZE (1 << 15) /* Support Sanitize */ mmc_pm_flag_t pm_caps; /* supported pm features */ -- GitLab From ef7aef9ab41d9aa95e9c2e2fdd4b5dbbf890f1d7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 19 Apr 2013 09:25:45 +0800 Subject: [PATCH 0362/2900] mmc: dw_mmc: fix error return code in dw_mci_probe() Fix to return -ENOMEM in alloc workqueue error case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bc3a1bc4940f..0652690f2d66 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2321,8 +2321,10 @@ int dw_mci_probe(struct dw_mci *host) tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); host->card_workqueue = alloc_workqueue("dw-mci-card", WQ_MEM_RECLAIM | WQ_NON_REENTRANT, 1); - if (!host->card_workqueue) + if (!host->card_workqueue) { + ret = -ENOMEM; goto err_dmaunmap; + } INIT_WORK(&host->card_work, dw_mci_work_routine_card); ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host); -- GitLab From 0c5ce16bc11ae3b80d2e3f6caf4483162acb1f62 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 19 Apr 2013 10:11:11 +0800 Subject: [PATCH 0363/2900] mmc: mxs-mmc: fix error return code in mxs_mmc_probe() Fix to return -ENODEV in the request dma error case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Reviewed-by: Marek Vasut Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 4278a1787d08..a09ba6e22136 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -639,6 +639,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) if (!ssp->dmach) { dev_err(mmc_dev(host->mmc), "%s: failed to request dma\n", __func__); + ret = -ENODEV; goto out_clk_put; } -- GitLab From 39b9431b0f371294dd2d1a492cf77f2f17390a1f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 2 May 2013 14:02:36 +0200 Subject: [PATCH 0364/2900] mmc: core: Stop bkops for eMMC only from mmc suspend Move mmc suspend specific operations to be executed from the .suspend callback in the mmc bus_ops. This simplifies the mmc_suspend_host function which is supposed to handle nothing but common suspend tasks. Since eMMC can be considered non-removable there are no need to check for ongoing bkops at PM_SUSPEND_PREPARE notification so remove it. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 22 +--------------------- drivers/mmc/core/mmc.c | 6 ++++++ 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 48b9fec34737..d856871ed6cb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2651,14 +2651,8 @@ int mmc_suspend_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { - if (host->bus_ops->suspend) { - if (mmc_card_doing_bkops(host->card)) { - err = mmc_stop_bkops(host->card); - if (err) - goto out; - } + if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); - } if (err == -ENOSYS || !host->bus_ops->resume) { /* @@ -2682,10 +2676,8 @@ int mmc_suspend_host(struct mmc_host *host) if (!err && !mmc_card_keep_power(host)) mmc_power_off(host); -out: return err; } - EXPORT_SYMBOL(mmc_suspend_host); /** @@ -2740,22 +2732,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, struct mmc_host *host = container_of( notify_block, struct mmc_host, pm_notify); unsigned long flags; - int err = 0; switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: - if (host->card && mmc_card_mmc(host->card) && - mmc_card_doing_bkops(host->card)) { - err = mmc_stop_bkops(host->card); - if (err) { - pr_err("%s: didn't stop bkops\n", - mmc_hostname(host)); - return err; - } - mmc_card_clr_doing_bkops(host->card); - } - spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0cbd1effe960..a0469cf7933f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1411,6 +1411,12 @@ static int mmc_suspend(struct mmc_host *host) mmc_claim_host(host); + if (mmc_card_doing_bkops(host->card)) { + err = mmc_stop_bkops(host->card); + if (err) + goto out; + } + err = mmc_cache_ctrl(host, 0); if (err) goto out; -- GitLab From 12d01d0b813b93e7bde1b5f468b5c85aa8b33590 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 2 May 2013 14:02:37 +0200 Subject: [PATCH 0365/2900] mmc: core: Add bus_ops for runtime pm callbacks SDIO is the only protocol that uses runtime pm for the card device right now. To provide the option for sd and mmc to use runtime pm as well the bus_ops callback are extended with two new functions. One for runtime_suspend and one for runtime_resume. This patch will also implement the callbacks for SDIO to make sure existing functionality is maintained. It also prepares to move away from using the mmc_power_restore_host API, since it is not needed when using runtime PM. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/bus.c | 14 ++++++++++++-- drivers/mmc/core/core.c | 2 +- drivers/mmc/core/core.h | 3 +++ drivers/mmc/core/sdio.c | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index e219c97a02a4..d9e8c2b7f4c5 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -151,15 +151,25 @@ static int mmc_bus_resume(struct device *dev) static int mmc_runtime_suspend(struct device *dev) { struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret = 0; + + if (host->bus_ops->runtime_suspend) + ret = host->bus_ops->runtime_suspend(host); - return mmc_power_save_host(card->host); + return ret; } static int mmc_runtime_resume(struct device *dev) { struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret = 0; + + if (host->bus_ops->runtime_resume) + ret = host->bus_ops->runtime_resume(host); - return mmc_power_restore_host(card->host); + return ret; } static int mmc_runtime_idle(struct device *dev) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d856871ed6cb..dc0cb5929c64 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1478,7 +1478,7 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) * If a host does all the power sequencing itself, ignore the * initial MMC_POWER_UP stage. */ -static void mmc_power_up(struct mmc_host *host) +void mmc_power_up(struct mmc_host *host) { int bit; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index b9f18a2a8874..6242ffb789c4 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -22,6 +22,8 @@ struct mmc_bus_ops { void (*detect)(struct mmc_host *); int (*suspend)(struct mmc_host *); int (*resume)(struct mmc_host *); + int (*runtime_suspend)(struct mmc_host *); + int (*runtime_resume)(struct mmc_host *); int (*power_save)(struct mmc_host *); int (*power_restore)(struct mmc_host *); int (*alive)(struct mmc_host *); @@ -44,6 +46,7 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage); void mmc_set_timing(struct mmc_host *host, unsigned int timing); void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type); +void mmc_power_up(struct mmc_host *host); void mmc_power_off(struct mmc_host *host); void mmc_power_cycle(struct mmc_host *host); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 444668c210b2..1fbbd1bc55ec 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1059,11 +1059,27 @@ static int mmc_sdio_power_restore(struct mmc_host *host) return ret; } +static int mmc_sdio_runtime_suspend(struct mmc_host *host) +{ + /* No references to the card, cut the power to it. */ + mmc_power_off(host); + return 0; +} + +static int mmc_sdio_runtime_resume(struct mmc_host *host) +{ + /* Restore power and re-initialize. */ + mmc_power_up(host); + return mmc_sdio_power_restore(host); +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, .suspend = mmc_sdio_suspend, .resume = mmc_sdio_resume, + .runtime_suspend = mmc_sdio_runtime_suspend, + .runtime_resume = mmc_sdio_runtime_resume, .power_restore = mmc_sdio_power_restore, .alive = mmc_sdio_alive, }; -- GitLab From e94cfef698aae6b209d8918dd319312e4b02118d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 2 May 2013 14:02:38 +0200 Subject: [PATCH 0366/2900] mmc: block: Enable runtime pm for mmc blkdevice Once the mmc blkdevice is being probed, runtime pm will be enabled. By using runtime autosuspend, the power save operations can be done when request inactivity occurs for a certain time. Right now the selected timeout value is set to 3 s. Obviously this value will likely need to be configurable somehow since it needs to be trimmed depending on the power save algorithm. For SD-combo cards, we are still leaving the enablement of runtime PM to the SDIO init sequence since it depends on the capabilities of the SDIO func driver. Moreover, when the blk device is being suspended, we make sure the device will be runtime resumed. The reason for doing this is that we want the host suspend sequence to be unaware of any runtime power save operations done for the card in this phase. Thus it can just handle the suspend as the card is fully powered from a runtime perspective. Finally, this patch prepares to make it possible to move BKOPS handling into the runtime callbacks for the mmc bus_ops. Thus IDLE BKOPS can be accomplished. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 32 ++++++++++++++++++++++++++------ drivers/mmc/core/core.c | 23 +++++++++++++++++++++++ drivers/mmc/core/debugfs.c | 8 ++++---- drivers/mmc/core/mmc.c | 4 ++-- drivers/mmc/core/sd.c | 4 ++-- include/linux/mmc/core.h | 3 +++ 6 files changed, 60 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 80b05b280241..c900d2818aa7 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -224,7 +225,7 @@ static ssize_t power_ro_lock_store(struct device *dev, md = mmc_blk_get(dev_to_disk(dev)); card = md->queue.card; - mmc_claim_host(card->host); + mmc_get_card(card); ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, card->ext_csd.boot_ro_lock | @@ -235,7 +236,7 @@ static ssize_t power_ro_lock_store(struct device *dev, else card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN; - mmc_release_host(card->host); + mmc_put_card(card); if (!ret) { pr_info("%s: Locking boot partition ro until next power on\n", @@ -522,7 +523,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, mrq.cmd = &cmd; - mmc_claim_host(card->host); + mmc_get_card(card); err = mmc_blk_part_switch(card, md); if (err) @@ -599,7 +600,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, } cmd_rel_host: - mmc_release_host(card->host); + mmc_put_card(card); cmd_done: mmc_blk_put(md); @@ -1921,7 +1922,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) if (req && !mq->mqrq_prev->req) /* claim host only for the first request */ - mmc_claim_host(card->host); + mmc_get_card(card); ret = mmc_blk_part_switch(card, md); if (ret) { @@ -1965,7 +1966,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) * In case sepecial request, there is no reentry to * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'. */ - mmc_release_host(card->host); + mmc_put_card(card); return ret; } @@ -2362,6 +2363,19 @@ static int mmc_blk_probe(struct mmc_card *card) if (mmc_add_disk(part_md)) goto out; } + + pm_runtime_set_autosuspend_delay(&card->dev, 3000); + pm_runtime_use_autosuspend(&card->dev); + + /* + * Don't enable runtime PM for SD-combo cards here. Leave that + * decision to be taken during the SDIO init sequence instead. + */ + if (card->type != MMC_TYPE_SD_COMBO) { + pm_runtime_set_active(&card->dev); + pm_runtime_enable(&card->dev); + } + return 0; out: @@ -2375,9 +2389,13 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); mmc_blk_remove_parts(card, md); + pm_runtime_get_sync(&card->dev); mmc_claim_host(card->host); mmc_blk_part_switch(card, md); mmc_release_host(card->host); + if (card->type != MMC_TYPE_SD_COMBO) + pm_runtime_disable(&card->dev); + pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); mmc_set_drvdata(card, NULL); } @@ -2389,6 +2407,7 @@ static int mmc_blk_suspend(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { + pm_runtime_get_sync(&card->dev); mmc_queue_suspend(&md->queue); list_for_each_entry(part_md, &md->part, part) { mmc_queue_suspend(&part_md->queue); @@ -2412,6 +2431,7 @@ static int mmc_blk_resume(struct mmc_card *card) list_for_each_entry(part_md, &md->part, part) { mmc_queue_resume(&part_md->queue); } + pm_runtime_put(&card->dev); } return 0; } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index dc0cb5929c64..0f86144b0c51 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -970,6 +970,29 @@ void mmc_release_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_release_host); +/* + * This is a helper function, which fetches a runtime pm reference for the + * card device and also claims the host. + */ +void mmc_get_card(struct mmc_card *card) +{ + pm_runtime_get_sync(&card->dev); + mmc_claim_host(card->host); +} +EXPORT_SYMBOL(mmc_get_card); + +/* + * This is a helper function, which releases the host and drops the runtime + * pm reference for the card device. + */ +void mmc_put_card(struct mmc_card *card) +{ + mmc_release_host(card->host); + pm_runtime_mark_last_busy(&card->dev); + pm_runtime_put_autosuspend(&card->dev); +} +EXPORT_SYMBOL(mmc_put_card); + /* * Internal function that does the actual ios call to the host driver, * optionally printing some debug output. diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 35c2f85b1956..54829c0ed000 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -258,13 +258,13 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) u32 status; int ret; - mmc_claim_host(card->host); + mmc_get_card(card); ret = mmc_send_status(data, &status); if (!ret) *val = status; - mmc_release_host(card->host); + mmc_put_card(card); return ret; } @@ -291,9 +291,9 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) goto out_free; } - mmc_claim_host(card->host); + mmc_get_card(card); err = mmc_send_ext_csd(card, ext_csd); - mmc_release_host(card->host); + mmc_put_card(card); if (err) goto out_free; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a0469cf7933f..903f38150180 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1380,14 +1380,14 @@ static void mmc_detect(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); - mmc_claim_host(host); + mmc_get_card(host->card); /* * Just check if our card has been removed. */ err = _mmc_detect_card_removed(host); - mmc_release_host(host); + mmc_put_card(host->card); if (err) { mmc_remove(host); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 8373d2288bb1..17fa2d271dd4 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1042,14 +1042,14 @@ static void mmc_sd_detect(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); - mmc_claim_host(host); + mmc_get_card(host->card); /* * Just check if our card has been removed. */ err = _mmc_detect_card_removed(host); - mmc_release_host(host); + mmc_put_card(host->card); if (err) { mmc_sd_remove(host); diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index bd06ff566bfc..443243b241d5 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -190,6 +190,9 @@ extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); extern int mmc_try_claim_host(struct mmc_host *host); +extern void mmc_get_card(struct mmc_card *card); +extern void mmc_put_card(struct mmc_card *card); + extern int mmc_flush_cache(struct mmc_card *); extern int mmc_detect_card_removed(struct mmc_host *host); -- GitLab From c4d770d72492df510077b277f21ac5f0dad9e5eb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 2 May 2013 14:02:39 +0200 Subject: [PATCH 0367/2900] mmc: core: Support aggressive power management for (e)MMC/SD Aggressive power management is suitable when saving power is essential. At request inactivity timeout, aka pm runtime autosuspend timeout, the card will be suspended. Once a new request arrives, the card will be re-initalized and thus the first request will suffer from a latency. This latency is card-specific, experiments has shown in general that SD-cards has quite poor initialization time, around 300ms-1100ms. eMMC is not surprisingly far better but still a couple of hundreds of ms has been observed. Except for the request latency, it is important to know that suspending the card will also prevent the card from executing internal house-keeping operations in idle mode. This could mean degradation in performance. To use this feature make sure the request inactivity timeout is chosen carefully. This has not been done as a part of this patch. Enable this feature by using host cap MMC_CAP_AGGRESSIVE_PM and by setting CONFIG_MMC_UNSAFE_RESUME. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 50 ++++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/sd.c | 49 +++++++++++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 2 +- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 903f38150180..506f4ee84e12 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1454,6 +1454,54 @@ static int mmc_resume(struct mmc_host *host) return err; } + +/* + * Callback for runtime_suspend. + */ +static int mmc_runtime_suspend(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) + return 0; + + mmc_claim_host(host); + + err = mmc_suspend(host); + if (err) { + pr_err("%s: error %d doing aggessive suspend\n", + mmc_hostname(host), err); + goto out; + } + mmc_power_off(host); + +out: + mmc_release_host(host); + return err; +} + +/* + * Callback for runtime_resume. + */ +static int mmc_runtime_resume(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) + return 0; + + mmc_claim_host(host); + + mmc_power_up(host); + err = mmc_resume(host); + if (err) + pr_err("%s: error %d doing aggessive resume\n", + mmc_hostname(host), err); + + mmc_release_host(host); + return 0; +} + static int mmc_power_restore(struct mmc_host *host) { int ret; @@ -1514,6 +1562,8 @@ static const struct mmc_bus_ops mmc_ops_unsafe = { .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, + .runtime_suspend = mmc_runtime_suspend, + .runtime_resume = mmc_runtime_resume, .power_restore = mmc_power_restore, .alive = mmc_alive, }; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 17fa2d271dd4..aeaae7c3b22b 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1100,6 +1100,53 @@ static int mmc_sd_resume(struct mmc_host *host) return err; } +/* + * Callback for runtime_suspend. + */ +static int mmc_sd_runtime_suspend(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) + return 0; + + mmc_claim_host(host); + + err = mmc_sd_suspend(host); + if (err) { + pr_err("%s: error %d doing aggessive suspend\n", + mmc_hostname(host), err); + goto out; + } + mmc_power_off(host); + +out: + mmc_release_host(host); + return err; +} + +/* + * Callback for runtime_resume. + */ +static int mmc_sd_runtime_resume(struct mmc_host *host) +{ + int err; + + if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) + return 0; + + mmc_claim_host(host); + + mmc_power_up(host); + err = mmc_sd_resume(host); + if (err) + pr_err("%s: error %d doing aggessive resume\n", + mmc_hostname(host), err); + + mmc_release_host(host); + return 0; +} + static int mmc_sd_power_restore(struct mmc_host *host) { int ret; @@ -1124,6 +1171,8 @@ static const struct mmc_bus_ops mmc_sd_ops = { static const struct mmc_bus_ops mmc_sd_ops_unsafe = { .remove = mmc_sd_remove, .detect = mmc_sd_detect, + .runtime_suspend = mmc_sd_runtime_suspend, + .runtime_resume = mmc_sd_runtime_resume, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, .power_restore = mmc_sd_power_restore, diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 6f3851533de0..374098bae831 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -239,7 +239,7 @@ struct mmc_host { #define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */ #define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */ #define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */ - +#define MMC_CAP_AGGRESSIVE_PM (1 << 7) /* Suspend (e)MMC/SD at idle */ #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ -- GitLab From 07a682160866e302d696f5c76d74024d575fb79d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Fri, 19 Apr 2013 15:12:11 +0200 Subject: [PATCH 0368/2900] mmc: core: Restructure and simplify code for mmc sleep|awake The mmc_card_sleep|awake APIs are not being used since the support is already properly encapsulated within the suspend sequence. Sleep|awake command is also specific for eMMC. We remove the sleep|awake bus_ops, the mmc_card_sleep|awake APIs and move the code into the mmc specific core instead. This also includes the mmc ops function, mmc_sleepawake. All releated functions have then become static and we have got far less code to maintain. Additionally this patch also simplifies the code from mmc_sleepawake, since it is only used to put the card to sleep and not awake. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 46 ----------------------- drivers/mmc/core/core.h | 2 - drivers/mmc/core/mmc.c | 77 ++++++++++++++++++++------------------ drivers/mmc/core/mmc_ops.c | 34 ----------------- drivers/mmc/core/mmc_ops.h | 1 - include/linux/mmc/host.h | 4 -- 6 files changed, 41 insertions(+), 123 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0f86144b0c51..e9a104b9e4d3 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2550,52 +2550,6 @@ int mmc_power_restore_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_power_restore_host); -int mmc_card_awake(struct mmc_host *host) -{ - int err = -ENOSYS; - - if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) - return 0; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) - err = host->bus_ops->awake(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_awake); - -int mmc_card_sleep(struct mmc_host *host) -{ - int err = -ENOSYS; - - if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) - return 0; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) - err = host->bus_ops->sleep(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_sleep); - -int mmc_card_can_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - - if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) - return 1; - return 0; -} -EXPORT_SYMBOL(mmc_card_can_sleep); - /* * Flush the cache to the non-volatile storage. */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 6242ffb789c4..52a3650307af 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -16,8 +16,6 @@ #define MMC_CMD_RETRIES 3 struct mmc_bus_ops { - int (*awake)(struct mmc_host *); - int (*sleep)(struct mmc_host *); void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); int (*suspend)(struct mmc_host *); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 506f4ee84e12..dd6810eebd3f 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1321,6 +1321,45 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, return err; } +static int mmc_can_sleep(struct mmc_card *card) +{ + return (card && card->ext_csd.rev >= 3); +} + +static int mmc_sleep(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct mmc_card *card = host->card; + int err; + + if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD) + return 0; + + err = mmc_deselect_cards(host); + if (err) + return err; + + cmd.opcode = MMC_SLEEP_AWAKE; + cmd.arg = card->rca << 16; + cmd.arg |= 1 << 15; + + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) + return err; + + /* + * If the host does not wait while the card signals busy, then we will + * will have to wait the sleep/awake timeout. Note, we cannot use the + * SEND_STATUS command to poll the status because that command (and most + * others) is invalid while the card sleeps. + */ + if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); + + return err; +} + static int mmc_can_poweroff_notify(const struct mmc_card *card) { return card && @@ -1423,8 +1462,8 @@ static int mmc_suspend(struct mmc_host *host) if (mmc_can_poweroff_notify(host->card)) err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); - else if (mmc_card_can_sleep(host)) - err = mmc_card_sleep(host); + else if (mmc_can_sleep(host->card)) + err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); @@ -1514,39 +1553,7 @@ static int mmc_power_restore(struct mmc_host *host) return ret; } -static int mmc_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 1); - if (err < 0) - pr_debug("%s: Error %d while putting card into sleep", - mmc_hostname(host), err); - } - - return err; -} - -static int mmc_awake(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 0); - if (err < 0) - pr_debug("%s: Error %d while awaking sleeping card", - mmc_hostname(host), err); - } - - return err; -} - static const struct mmc_bus_ops mmc_ops = { - .awake = mmc_awake, - .sleep = mmc_sleep, .remove = mmc_remove, .detect = mmc_detect, .suspend = NULL, @@ -1556,8 +1563,6 @@ static const struct mmc_bus_ops mmc_ops = { }; static const struct mmc_bus_ops mmc_ops_unsafe = { - .awake = mmc_awake, - .sleep = mmc_sleep, .remove = mmc_remove, .detect = mmc_detect, .suspend = mmc_suspend, diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 124af5238d0a..837fc7386e23 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -59,40 +59,6 @@ int mmc_deselect_cards(struct mmc_host *host) return _mmc_select_card(host, NULL); } -int mmc_card_sleepawake(struct mmc_host *host, int sleep) -{ - struct mmc_command cmd = {0}; - struct mmc_card *card = host->card; - int err; - - if (sleep) - mmc_deselect_cards(host); - - cmd.opcode = MMC_SLEEP_AWAKE; - cmd.arg = card->rca << 16; - if (sleep) - cmd.arg |= 1 << 15; - - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err) - return err; - - /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. - */ - if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) - mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); - - if (!sleep) - err = mmc_select_card(card); - - return err; -} - int mmc_go_idle(struct mmc_host *host) { int err; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 3dd8941c2980..80ae9f4e0293 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_set_crc(struct mmc_host *host, int use_crc); -int mmc_card_sleepawake(struct mmc_host *host, int sleep); int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 374098bae831..2e34ee5cefce 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -425,10 +425,6 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc) } #endif -int mmc_card_awake(struct mmc_host *host); -int mmc_card_sleep(struct mmc_host *host); -int mmc_card_can_sleep(struct mmc_host *host); - int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); /* Module parameter */ -- GitLab From 60443712195bbcbbff9af189bdd9d2c1ef0a5cae Mon Sep 17 00:00:00 2001 From: Fredrik Soderstedt Date: Tue, 23 Apr 2013 16:27:07 +0200 Subject: [PATCH 0369/2900] mmc: core: Fix select power class after resume Use the saved values in card->ext_csd when selecting power class. By doing this the power class will be selected even if mmc_init_card is called with oldcard != NULL, which is the case after a suspend/resume. Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL and power class will not be selected. According to the eMMC specification the POWER_CLASS value is reset after power failure, H/W reset assertion and any CMD0 reset. Signed-off-by: Fredrik Soderstedt Reviewed-by: Johan Rudholm Acked By: Girish K S Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 74 +++++++++++++++++++++++++++------------- include/linux/mmc/card.h | 10 +++++- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index dd6810eebd3f..3a69b947130b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -461,6 +461,24 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) */ card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; card->ext_csd.boot_ro_lockable = true; + + /* Save power class values */ + card->ext_csd.raw_pwr_cl_52_195 = + ext_csd[EXT_CSD_PWR_CL_52_195]; + card->ext_csd.raw_pwr_cl_26_195 = + ext_csd[EXT_CSD_PWR_CL_26_195]; + card->ext_csd.raw_pwr_cl_52_360 = + ext_csd[EXT_CSD_PWR_CL_52_360]; + card->ext_csd.raw_pwr_cl_26_360 = + ext_csd[EXT_CSD_PWR_CL_26_360]; + card->ext_csd.raw_pwr_cl_200_195 = + ext_csd[EXT_CSD_PWR_CL_200_195]; + card->ext_csd.raw_pwr_cl_200_360 = + ext_csd[EXT_CSD_PWR_CL_200_360]; + card->ext_csd.raw_pwr_cl_ddr_52_195 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; + card->ext_csd.raw_pwr_cl_ddr_52_360 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; } if (card->ext_csd.rev >= 5) { @@ -607,7 +625,23 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) (card->ext_csd.raw_sectors[2] == bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && (card->ext_csd.raw_sectors[3] == - bw_ext_csd[EXT_CSD_SEC_CNT + 3])); + bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && + (card->ext_csd.raw_pwr_cl_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && + (card->ext_csd.raw_pwr_cl_26_195 == + bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && + (card->ext_csd.raw_pwr_cl_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && + (card->ext_csd.raw_pwr_cl_26_360 == + bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && + (card->ext_csd.raw_pwr_cl_200_195 == + bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && + (card->ext_csd.raw_pwr_cl_200_360 == + bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && + (card->ext_csd.raw_pwr_cl_ddr_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && + (card->ext_csd.raw_pwr_cl_ddr_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); if (err) err = -EINVAL; @@ -676,11 +710,10 @@ static struct device_type mmc_type = { * mmc_switch command. */ static int mmc_select_powerclass(struct mmc_card *card, - unsigned int bus_width, u8 *ext_csd) + unsigned int bus_width) { int err = 0; - unsigned int pwrclass_val; - unsigned int index = 0; + unsigned int pwrclass_val = 0; struct mmc_host *host; BUG_ON(!card); @@ -688,9 +721,6 @@ static int mmc_select_powerclass(struct mmc_card *card, host = card->host; BUG_ON(!host); - if (ext_csd == NULL) - return 0; - /* Power class selection is supported for versions >= 4.0 */ if (card->csd.mmca_vsn < CSD_SPEC_VER_4) return 0; @@ -702,13 +732,13 @@ static int mmc_select_powerclass(struct mmc_card *card, switch (1 << host->ios.vdd) { case MMC_VDD_165_195: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_195 : - EXT_CSD_PWR_CL_DDR_52_195; + pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + card->ext_csd.raw_pwr_cl_52_195 : + card->ext_csd.raw_pwr_cl_ddr_52_195; else if (host->ios.clock <= 200000000) - index = EXT_CSD_PWR_CL_200_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; break; case MMC_VDD_27_28: case MMC_VDD_28_29: @@ -720,13 +750,13 @@ static int mmc_select_powerclass(struct mmc_card *card, case MMC_VDD_34_35: case MMC_VDD_35_36: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_360 : - EXT_CSD_PWR_CL_DDR_52_360; + pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? + card->ext_csd.raw_pwr_cl_52_360 : + card->ext_csd.raw_pwr_cl_ddr_52_360; else if (host->ios.clock <= 200000000) - index = EXT_CSD_PWR_CL_200_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; break; default: pr_warning("%s: Voltage range not supported " @@ -734,8 +764,6 @@ static int mmc_select_powerclass(struct mmc_card *card, return -EINVAL; } - pwrclass_val = ext_csd[index]; - if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> EXT_CSD_PWR_CL_8BIT_SHIFT; @@ -1131,7 +1159,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; - err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits); if (err) pr_warning("%s: power class selection to bus width %d" " failed\n", mmc_hostname(card->host), @@ -1164,8 +1192,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, bus_width = bus_widths[idx]; if (bus_width == MMC_BUS_WIDTH_1) ddr = 0; /* no DDR for 1-bit width */ - err = mmc_select_powerclass(card, ext_csd_bits[idx][0], - ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits[idx][0]); if (err) pr_warning("%s: power class selection to " "bus width %d failed\n", @@ -1195,8 +1222,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } if (!err && ddr) { - err = mmc_select_powerclass(card, ext_csd_bits[idx][1], - ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits[idx][1]); if (err) pr_warning("%s: power class selection to " "bus width %d ddr %d failed\n", diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f31725ba49f3..6a98f32670b8 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -94,7 +94,11 @@ struct mmc_ext_csd { u8 raw_ext_csd_structure; /* 194 */ u8 raw_card_type; /* 196 */ u8 out_of_int_time; /* 198 */ - u8 raw_s_a_timeout; /* 217 */ + u8 raw_pwr_cl_52_195; /* 200 */ + u8 raw_pwr_cl_26_195; /* 201 */ + u8 raw_pwr_cl_52_360; /* 202 */ + u8 raw_pwr_cl_26_360; /* 203 */ + u8 raw_s_a_timeout; /* 217 */ u8 raw_hc_erase_gap_size; /* 221 */ u8 raw_erase_timeout_mult; /* 223 */ u8 raw_hc_erase_grp_size; /* 224 */ @@ -102,6 +106,10 @@ struct mmc_ext_csd { u8 raw_sec_erase_mult; /* 230 */ u8 raw_sec_feature_support;/* 231 */ u8 raw_trim_mult; /* 232 */ + u8 raw_pwr_cl_200_195; /* 236 */ + u8 raw_pwr_cl_200_360; /* 237 */ + u8 raw_pwr_cl_ddr_52_195; /* 238 */ + u8 raw_pwr_cl_ddr_52_360; /* 239 */ u8 raw_bkops_status; /* 246 */ u8 raw_sectors[4]; /* 212 - 4 bytes */ -- GitLab From fc79a4d6dfa736672281aedbe384ece1f0044756 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 26 Apr 2013 15:35:22 +0900 Subject: [PATCH 0370/2900] mmc: dw_mmc: clear IDSTS register when initialize IDMAC If pending interrupt for IDMAC exists when initialize IDMAC, it will call interrupt handler unnecessarily. Signed-off-by: Joonyoung Shim Acked-by: Seungwon Jeon Reviewed-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0652690f2d66..b10e5e12b2ae 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -51,6 +51,11 @@ #define DW_MCI_DMA_THRESHOLD 16 #ifdef CONFIG_MMC_DW_IDMAC +#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ + SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ + SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ + SDMMC_IDMAC_INT_TI) + struct idmac_desc { u32 des0; /* Control Descriptor */ #define IDMAC_DES0_DIC BIT(1) @@ -433,6 +438,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); /* Mask out interrupts - get Tx & Rx complete only */ + mci_writel(host, IDSTS, IDMAC_INT_CLR); mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); -- GitLab From 03a0675b2a112038a8a5078d8815e3f7356c7064 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 26 Apr 2013 17:47:17 +0200 Subject: [PATCH 0371/2900] mmc: sdhi/tmio: make DMA filter implementation specific So far only the SDHI implementation uses TMIO MMC with DMA. That way a DMA channel filter function, defined in the TMIO driver wasn't a problem. However, such a filter function is DMA controller specific. Since the SDHI glue is only running on systems with the SHDMA DMA controller, the filter function can safely be provided by it. Move it into SDHI. Signed-off-by: Guennadi Liakhovetski Acked-by: Samuel Ortiz Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 9 +++++++++ drivers/mmc/host/tmio_mmc_dma.c | 12 ++---------- include/linux/mfd/tmio.h | 3 +++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index fe90853900b4..e0088d7f5f85 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,13 @@ static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); } +static bool sh_mobile_sdhi_filter(struct dma_chan *chan, void *arg) +{ + dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); + chan->private = arg; + return true; +} + static const struct sh_mobile_sdhi_ops sdhi_ops = { .cd_wakeup = sh_mobile_sdhi_cd_wakeup, }; @@ -191,6 +199,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave; priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave; priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ + priv->dma_priv.filter = sh_mobile_sdhi_filter; mmc_data->dma = &priv->dma_priv; } } diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index fff928604859..dc4b10b9c72a 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -261,14 +261,6 @@ static void tmio_mmc_tasklet_fn(unsigned long arg) spin_unlock_irq(&host->lock); } -/* It might be necessary to make filter MFD specific */ -static bool tmio_mmc_filter(struct dma_chan *chan, void *arg) -{ - dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); - chan->private = arg; - return true; -} - void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) { /* We can only either use DMA for both Tx and Rx or not use it at all */ @@ -281,7 +273,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - host->chan_tx = dma_request_channel(mask, tmio_mmc_filter, + host->chan_tx = dma_request_channel(mask, pdata->dma->filter, pdata->dma->chan_priv_tx); dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, host->chan_tx); @@ -289,7 +281,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat if (!host->chan_tx) return; - host->chan_rx = dma_request_channel(mask, tmio_mmc_filter, + host->chan_rx = dma_request_channel(mask, pdata->dma->filter, pdata->dma->chan_priv_rx); dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, host->chan_rx); diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 99bf3e665997..0990d8a2dbd7 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -81,10 +81,13 @@ int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base); void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state); void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state); +struct dma_chan; + struct tmio_mmc_dma { void *chan_priv_tx; void *chan_priv_rx; int alignment_shift; + bool (*filter)(struct dma_chan *chan, void *arg); }; struct tmio_mmc_host; -- GitLab From eec95ee22611f2207bd991d63a07884de28e6f56 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 26 Apr 2013 17:47:18 +0200 Subject: [PATCH 0372/2900] mmc: sdhi/tmio: switch to using dmaengine_slave_config() This removes the deprecated use of the .private member of struct dma_chan and switches the sdhi / tmio mmc driver to using the dmaengine_slave_config() channel configuration method. Signed-off-by: Guennadi Liakhovetski Acked-by: Samuel Ortiz Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 33 +++++++++++++++---------------- drivers/mmc/host/tmio_mmc_dma.c | 25 +++++++++++++++++++++++ include/linux/mfd/tmio.h | 2 ++ 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index e0088d7f5f85..7f45f62808d4 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -47,8 +46,6 @@ static const struct sh_mobile_sdhi_of_data sh_mobile_sdhi_of_cfg[] = { struct sh_mobile_sdhi { struct clk *clk; struct tmio_mmc_data mmc_data; - struct sh_dmae_slave param_tx; - struct sh_dmae_slave param_rx; struct tmio_mmc_dma dma_priv; }; @@ -125,13 +122,6 @@ static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); } -static bool sh_mobile_sdhi_filter(struct dma_chan *chan, void *arg) -{ - dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg); - chan->private = arg; - return true; -} - static const struct sh_mobile_sdhi_ops sdhi_ops = { .cd_wakeup = sh_mobile_sdhi_cd_wakeup, }; @@ -194,13 +184,22 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) mmc_data->get_cd = sh_mobile_sdhi_get_cd; if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { - priv->param_tx.shdma_slave.slave_id = p->dma_slave_tx; - priv->param_rx.shdma_slave.slave_id = p->dma_slave_rx; - priv->dma_priv.chan_priv_tx = &priv->param_tx.shdma_slave; - priv->dma_priv.chan_priv_rx = &priv->param_rx.shdma_slave; - priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ - priv->dma_priv.filter = sh_mobile_sdhi_filter; - mmc_data->dma = &priv->dma_priv; + struct tmio_mmc_dma *dma_priv = &priv->dma_priv; + + /* + * Yes, we have to provide slave IDs twice to TMIO: + * once as a filter parameter and once for channel + * configuration as an explicit slave ID + */ + dma_priv->chan_priv_tx = (void *)p->dma_slave_tx; + dma_priv->chan_priv_rx = (void *)p->dma_slave_rx; + dma_priv->slave_id_tx = p->dma_slave_tx; + dma_priv->slave_id_rx = p->dma_slave_rx; + + dma_priv->alignment_shift = 1; /* 2-byte alignment */ + dma_priv->filter = shdma_chan_filter; + + mmc_data->dma = dma_priv; } } diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index dc4b10b9c72a..5fcf14f21d20 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -268,7 +268,14 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat return; if (!host->chan_tx && !host->chan_rx) { + struct resource *res = platform_get_resource(host->pdev, + IORESOURCE_MEM, 0); + struct dma_slave_config cfg = {}; dma_cap_mask_t mask; + int ret; + + if (!res) + return; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); @@ -281,6 +288,14 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat if (!host->chan_tx) return; + cfg.slave_id = pdata->dma->slave_id_tx; + cfg.direction = DMA_MEM_TO_DEV; + cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); + cfg.src_addr = 0; + ret = dmaengine_slave_config(host->chan_tx, &cfg); + if (ret < 0) + goto ecfgtx; + host->chan_rx = dma_request_channel(mask, pdata->dma->filter, pdata->dma->chan_priv_rx); dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, @@ -289,6 +304,14 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat if (!host->chan_rx) goto ereqrx; + cfg.slave_id = pdata->dma->slave_id_rx; + cfg.direction = DMA_DEV_TO_MEM; + cfg.src_addr = cfg.dst_addr; + cfg.dst_addr = 0; + ret = dmaengine_slave_config(host->chan_rx, &cfg); + if (ret < 0) + goto ecfgrx; + host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); if (!host->bounce_buf) goto ebouncebuf; @@ -302,9 +325,11 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat return; ebouncebuf: +ecfgrx: dma_release_channel(host->chan_rx); host->chan_rx = NULL; ereqrx: +ecfgtx: dma_release_channel(host->chan_tx); host->chan_tx = NULL; } diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 0990d8a2dbd7..ce3511326f80 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -86,6 +86,8 @@ struct dma_chan; struct tmio_mmc_dma { void *chan_priv_tx; void *chan_priv_rx; + int slave_id_tx; + int slave_id_rx; int alignment_shift; bool (*filter)(struct dma_chan *chan, void *arg); }; -- GitLab From 87ae7bbebd9c9b32ad49dde1742aa68b5a86caf8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 26 Apr 2013 17:47:19 +0200 Subject: [PATCH 0373/2900] mmc: sdhi/tmio: add DT DMA support Add support for initialising DMA from the Device Tree. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 14 +++++++------- drivers/mmc/host/tmio_mmc_dma.c | 19 ++++++++++++------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 7f45f62808d4..cc4c872cc924 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -144,6 +144,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) struct tmio_mmc_host *host; int irq, ret, i = 0; bool multiplexed_isr = true; + struct tmio_mmc_dma *dma_priv; priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_mobile_sdhi), GFP_KERNEL); if (priv == NULL) { @@ -152,6 +153,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) } mmc_data = &priv->mmc_data; + dma_priv = &priv->dma_priv; if (p) { if (p->init) { @@ -184,8 +186,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) mmc_data->get_cd = sh_mobile_sdhi_get_cd; if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) { - struct tmio_mmc_dma *dma_priv = &priv->dma_priv; - /* * Yes, we have to provide slave IDs twice to TMIO: * once as a filter parameter and once for channel @@ -195,14 +195,14 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) dma_priv->chan_priv_rx = (void *)p->dma_slave_rx; dma_priv->slave_id_tx = p->dma_slave_tx; dma_priv->slave_id_rx = p->dma_slave_rx; - - dma_priv->alignment_shift = 1; /* 2-byte alignment */ - dma_priv->filter = shdma_chan_filter; - - mmc_data->dma = dma_priv; } } + dma_priv->alignment_shift = 1; /* 2-byte alignment */ + dma_priv->filter = shdma_chan_filter; + + mmc_data->dma = dma_priv; + /* * All SDHI blocks support 2-byte and larger block sizes in 4-bit * bus width mode. diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 5fcf14f21d20..47bdb8fa341b 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -264,7 +264,8 @@ static void tmio_mmc_tasklet_fn(unsigned long arg) void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata) { /* We can only either use DMA for both Tx and Rx or not use it at all */ - if (!pdata->dma) + if (!pdata->dma || (!host->pdev->dev.of_node && + (!pdata->dma->chan_priv_tx || !pdata->dma->chan_priv_rx))) return; if (!host->chan_tx && !host->chan_rx) { @@ -280,15 +281,17 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - host->chan_tx = dma_request_channel(mask, pdata->dma->filter, - pdata->dma->chan_priv_tx); + host->chan_tx = dma_request_slave_channel_compat(mask, + pdata->dma->filter, pdata->dma->chan_priv_tx, + &host->pdev->dev, "tx"); dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__, host->chan_tx); if (!host->chan_tx) return; - cfg.slave_id = pdata->dma->slave_id_tx; + if (pdata->dma->chan_priv_tx) + cfg.slave_id = pdata->dma->slave_id_tx; cfg.direction = DMA_MEM_TO_DEV; cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift); cfg.src_addr = 0; @@ -296,15 +299,17 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat if (ret < 0) goto ecfgtx; - host->chan_rx = dma_request_channel(mask, pdata->dma->filter, - pdata->dma->chan_priv_rx); + host->chan_rx = dma_request_slave_channel_compat(mask, + pdata->dma->filter, pdata->dma->chan_priv_rx, + &host->pdev->dev, "rx"); dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__, host->chan_rx); if (!host->chan_rx) goto ereqrx; - cfg.slave_id = pdata->dma->slave_id_rx; + if (pdata->dma->chan_priv_rx) + cfg.slave_id = pdata->dma->slave_id_rx; cfg.direction = DMA_DEV_TO_MEM; cfg.src_addr = cfg.dst_addr; cfg.dst_addr = 0; -- GitLab From 5a942b6fee81c6876044099b7622a817e4a74c03 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 17:56:16 +0900 Subject: [PATCH 0374/2900] mmc: atmel-mci: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SIMPLE_DEV_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. drivers/mmc/host/atmel-mci.c:2509:12: warning: 'atmci_suspend' defined but not used [-Wunused-function] drivers/mmc/host/atmel-mci.c:2539:12: warning: 'atmci_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Acked-by: Ludovic Desroches Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aca59d93d5a9..7d8e87ad6d6d 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2504,7 +2504,7 @@ static int __exit atmci_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int atmci_suspend(struct device *dev) { struct atmel_mci *host = dev_get_drvdata(dev); @@ -2559,17 +2559,15 @@ static int atmci_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); -#define ATMCI_PM_OPS (&atmci_pm) -#else -#define ATMCI_PM_OPS NULL #endif +static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); + static struct platform_driver atmci_driver = { .remove = __exit_p(atmci_remove), .driver = { .name = "atmel_mci", - .pm = ATMCI_PM_OPS, + .pm = &atmci_pm, .of_match_table = of_match_ptr(atmci_dt_ids), }, }; -- GitLab From ad82ab65d8abd060b60d99b8559da99c31515a31 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Sun, 26 May 2013 13:59:26 -0400 Subject: [PATCH 0375/2900] mmc: sdhci-pltfm: Allow drivers to set quirks2 from platform data Signed-off-by: Al Cooper Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pltfm.c | 5 ++++- drivers/mmc/host/sdhci-pltfm.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index cd0f1f68e261..77821869e66e 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -150,8 +150,11 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; - if (pdata) + if (pdata) { host->quirks = pdata->quirks; + host->quirks2 = pdata->quirks2; + } + host->irq = platform_get_irq(pdev, 0); if (!request_mem_region(iomem->start, resource_size(iomem), diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 1210ed1b0c60..83d42c60a06f 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -18,6 +18,7 @@ struct sdhci_pltfm_data { const struct sdhci_ops *ops; unsigned int quirks; + unsigned int quirks2; }; struct sdhci_pltfm_host { -- GitLab From 113a87f868b2f2e086790a68e8b9e41d8f0c3295 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 15:05:21 +0900 Subject: [PATCH 0376/2900] mmc: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Sonic Zhang Acked-by: Seungwon Jeon Acked-by: Shawn Guo Acked-by: Adrian Hunter Acked-by: Haojian Zhuang Acked-by: Jaehoon Chung Acked-by: Viresh Kumar Acked-by: Tony Prisk Signed-off-by: Chris Ball --- drivers/mmc/host/android-goldfish.c | 2 -- drivers/mmc/host/atmel-mci.c | 2 -- drivers/mmc/host/au1xmmc.c | 1 - drivers/mmc/host/bfin_sdh.c | 2 -- drivers/mmc/host/davinci_mmc.c | 1 - drivers/mmc/host/dw_mmc-pltfm.c | 1 - drivers/mmc/host/jz4740_mmc.c | 2 -- drivers/mmc/host/mvsdio.c | 1 - drivers/mmc/host/mxcmmc.c | 2 -- drivers/mmc/host/mxs-mmc.c | 2 -- drivers/mmc/host/omap.c | 2 -- drivers/mmc/host/omap_hsmmc.c | 2 -- drivers/mmc/host/pxamci.c | 2 -- drivers/mmc/host/rtsx_pci_sdmmc.c | 2 -- drivers/mmc/host/sdhci-acpi.c | 2 -- drivers/mmc/host/sdhci-pltfm.c | 1 - drivers/mmc/host/sdhci-pxav2.c | 2 -- drivers/mmc/host/sdhci-pxav3.c | 2 -- drivers/mmc/host/sdhci-s3c.c | 1 - drivers/mmc/host/sdhci-spear.c | 2 -- drivers/mmc/host/sh_mmcif.c | 2 -- drivers/mmc/host/tmio_mmc.c | 2 -- drivers/mmc/host/wmt-sdmmc.c | 2 -- 23 files changed, 40 deletions(-) diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index 7780c14704c4..8b4e20a3f16c 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c @@ -546,8 +546,6 @@ static int goldfish_mmc_remove(struct platform_device *pdev) { struct goldfish_mmc_host *host = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - BUG_ON(host == NULL); mmc_remove_host(host->mmc); diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 7d8e87ad6d6d..4aa20531e5f2 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2475,8 +2475,6 @@ static int __exit atmci_remove(struct platform_device *pdev) struct atmel_mci *host = platform_get_drvdata(pdev); unsigned int i; - platform_set_drvdata(pdev, NULL); - if (host->buffer) dma_free_coherent(&pdev->dev, host->buf_size, host->buffer, host->buf_phys_addr); diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 127a8fade4da..df9becdd2e99 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1149,7 +1149,6 @@ static int au1xmmc_remove(struct platform_device *pdev) kfree(host->ioarea); mmc_free_host(host->mmc); - platform_set_drvdata(pdev, NULL); } return 0; } diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index fb4348c5b6ac..94fae2f1baaf 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -621,8 +621,6 @@ static int sdh_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - if (mmc) { struct sdh_host *host = mmc_priv(mmc); diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 3946a0eb3a03..b1b8202242ea 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1406,7 +1406,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) { struct mmc_davinci_host *host = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); if (host) { mmc_davinci_cpufreq_deregister(host); diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 41c27b74b003..37873f101cdb 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -72,7 +72,6 @@ static int dw_mci_pltfm_remove(struct platform_device *pdev) { struct dw_mci *host = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); dw_mci_remove(host); return 0; } diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 2391c6b7a4bb..1c47b3473ce3 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -932,7 +932,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) err_clk_put: clk_put(host->clk); err_free_host: - platform_set_drvdata(pdev, NULL); mmc_free_host(mmc); return ret; @@ -960,7 +959,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) clk_put(host->clk); - platform_set_drvdata(pdev, NULL); mmc_free_host(host->mmc); return 0; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 8960fc846c77..d08fe6ae9bf8 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -827,7 +827,6 @@ static int __exit mvsd_remove(struct platform_device *pdev) clk_disable_unprepare(host->clk); mmc_free_host(mmc); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index d5036353bddc..786448a10f15 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1219,8 +1219,6 @@ static int mxcmci_remove(struct platform_device *pdev) struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxcmci_host *host = mmc_priv(mmc); - platform_set_drvdata(pdev, NULL); - mmc_remove_host(mmc); if (host->vcc) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index a09ba6e22136..c26280469b05 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -709,8 +709,6 @@ static int mxs_mmc_remove(struct platform_device *pdev) mmc_remove_host(mmc); - platform_set_drvdata(pdev, NULL); - if (ssp->dmach) dma_release_channel(ssp->dmach); diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 4254975f931d..4b3e0eb77fe0 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1500,8 +1500,6 @@ static int mmc_omap_remove(struct platform_device *pdev) struct mmc_omap_host *host = platform_get_drvdata(pdev); int i; - platform_set_drvdata(pdev, NULL); - BUG_ON(host == NULL); for (i = 0; i < host->nr_slots; i++) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index eccedc7d06a4..1865321465c4 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2047,7 +2047,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) } err1: iounmap(host->base); - platform_set_drvdata(pdev, NULL); mmc_free_host(mmc); err_alloc: omap_hsmmc_gpio_free(pdata); @@ -2093,7 +2092,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2b2f65ada22e..847b1996ce8e 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -834,8 +834,6 @@ static int pxamci_remove(struct platform_device *pdev) struct mmc_host *mmc = platform_get_drvdata(pdev); int gpio_cd = -1, gpio_ro = -1, gpio_power = -1; - platform_set_drvdata(pdev, NULL); - if (mmc) { struct pxamci_host *host = mmc_priv(mmc); diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index ad13f4240c49..82a35b91cdbc 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1316,8 +1316,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) mmc_remove_host(mmc); mmc_free_host(mmc); - platform_set_drvdata(pdev, NULL); - dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller has been removed\n"); diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 706d9cb1a49e..b1a6588b50fa 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -262,7 +262,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) return 0; err_free: - platform_set_drvdata(pdev, NULL); sdhci_free_host(c->host); return err; } @@ -281,7 +280,6 @@ static int sdhci_acpi_remove(struct platform_device *pdev) dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0); sdhci_remove_host(c->host, dead); - platform_set_drvdata(pdev, NULL); sdhci_free_host(c->host); return 0; diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 77821869e66e..e7762e5e9048 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -200,7 +200,6 @@ void sdhci_pltfm_free(struct platform_device *pdev) iounmap(host->ioaddr); release_mem_region(iomem->start, resource_size(iomem)); sdhci_free_host(host); - platform_set_drvdata(pdev, NULL); } EXPORT_SYMBOL_GPL(sdhci_pltfm_free); diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 6a3f702a38a6..98b5145cef7c 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -253,8 +253,6 @@ static int sdhci_pxav2_remove(struct platform_device *pdev) sdhci_pltfm_free(pdev); kfree(pxa); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 1ae358e0662d..90ee262def69 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -339,8 +339,6 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) sdhci_pltfm_free(pdev); kfree(pxa); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index c6f6246a4933..926aaf6acc67 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -745,7 +745,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) clk_disable_unprepare(sc->clk_io); sdhci_free_host(host); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 7ae5b3ae7bad..2dba9f8d1760 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -258,7 +258,6 @@ static int sdhci_probe(struct platform_device *pdev) return 0; set_drvdata: - platform_set_drvdata(pdev, NULL); sdhci_remove_host(host, 1); free_host: sdhci_free_host(host); @@ -278,7 +277,6 @@ static int sdhci_remove(struct platform_device *pdev) int dead = 0; u32 scratch; - platform_set_drvdata(pdev, NULL); scratch = readl(host->ioaddr + SDHCI_INT_STATUS); if (scratch == (u32)-1) dead = 1; diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index ba76a532ae30..117a1f774720 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1501,8 +1501,6 @@ static int sh_mmcif_remove(struct platform_device *pdev) if (irq[1] >= 0) free_irq(irq[1], host); - platform_set_drvdata(pdev, NULL); - clk_disable(host->hclk); mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 139212e79cde..8860d4d2bc22 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -112,8 +112,6 @@ static int tmio_mmc_remove(struct platform_device *pdev) const struct mfd_cell *cell = mfd_get_cell(pdev); struct mmc_host *mmc = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - if (mmc) { struct tmio_mmc_host *host = mmc_priv(mmc); free_irq(platform_get_irq(pdev, 0), host); diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 442f5766ffca..34231d5168fc 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -927,8 +927,6 @@ static int wmt_mci_remove(struct platform_device *pdev) mmc_free_host(mmc); - platform_set_drvdata(pdev, NULL); - dev_info(&pdev->dev, "WMT MCI device removed\n"); return 0; -- GitLab From f0710a557cb17746b09234f01073a2cdafe4f4a5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 6 May 2013 12:17:32 +0300 Subject: [PATCH 0377/2900] mmc: sdhci: add ability to stay runtime-resumed if the card is powered up If card power is dependent on SD bus power then the host controller must not be runtime suspended while the card is powered up. Add the ability to stay runtime-resumed in that case and enable it with a new quirk SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 35 ++++++++++++++++++++++++++++++++++- include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2ea429c27714..c81c2a289dbd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -58,6 +58,8 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); #ifdef CONFIG_PM_RUNTIME static int sdhci_runtime_pm_get(struct sdhci_host *host); static int sdhci_runtime_pm_put(struct sdhci_host *host); +static void sdhci_runtime_pm_bus_on(struct sdhci_host *host); +static void sdhci_runtime_pm_bus_off(struct sdhci_host *host); #else static inline int sdhci_runtime_pm_get(struct sdhci_host *host) { @@ -67,6 +69,12 @@ static inline int sdhci_runtime_pm_put(struct sdhci_host *host) { return 0; } +static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) +{ +} +static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) +{ +} #endif static void sdhci_dumpregs(struct sdhci_host *host) @@ -192,8 +200,12 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); - if (mask & SDHCI_RESET_ALL) + if (mask & SDHCI_RESET_ALL) { host->clock = 0; + /* Reset-all turns off SD Bus Power */ + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) + sdhci_runtime_pm_bus_off(host); + } /* Wait max 100 ms */ timeout = 100; @@ -1268,6 +1280,8 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) if (pwr == 0) { sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) + sdhci_runtime_pm_bus_off(host); return 0; } @@ -1289,6 +1303,9 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) + sdhci_runtime_pm_bus_on(host); + /* * Some controllers need an extra 10ms delay of 10ms before they * can apply clock after applying power @@ -2625,6 +2642,22 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host) return pm_runtime_put_autosuspend(host->mmc->parent); } +static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) +{ + if (host->runtime_suspended || host->bus_on) + return; + host->bus_on = true; + pm_runtime_get_noresume(host->mmc->parent); +} + +static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) +{ + if (host->runtime_suspended || !host->bus_on) + return; + host->bus_on = false; + pm_runtime_put_noidle(host->mmc->parent); +} + int sdhci_runtime_suspend_host(struct sdhci_host *host) { unsigned long flags; diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index b838ffc49e4a..ba35bdb87d99 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -95,6 +95,7 @@ struct sdhci_host { /* The system physically doesn't support 1.8v, even if the host does */ #define SDHCI_QUIRK2_NO_1_8_V (1<<2) #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) +#define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -139,6 +140,7 @@ struct sdhci_host { u8 pwr; /* Current voltage */ bool runtime_suspended; /* Host is runtime suspended */ + bool bus_on; /* Bus power prevents runtime suspend */ struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ -- GitLab From a61abe6eebfda1add8cb54e6e10384ea747d68a5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 6 May 2013 12:17:33 +0300 Subject: [PATCH 0378/2900] mmc: sdhci-acpi: support runtime PM for ACPI HID 80860F14 SD cards Enable runtime PM for ACPI HID 80860F14 SD cards, adding support for card detect GPIO. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-acpi.c | 64 ++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index b1a6588b50fa..a51e603acbc5 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -101,6 +103,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { + .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_RUNTIME_PM, + .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, }; struct sdhci_acpi_uid_slot { @@ -161,6 +165,57 @@ static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, return slot; } +#ifdef CONFIG_PM_RUNTIME + +static irqreturn_t sdhci_acpi_sd_cd(int irq, void *dev_id) +{ + mmc_detect_change(dev_id, msecs_to_jiffies(200)); + return IRQ_HANDLED; +} + +static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, + struct mmc_host *mmc) +{ + unsigned long flags; + int err, irq; + + if (gpio < 0) { + err = gpio; + goto out; + } + + err = devm_gpio_request_one(dev, gpio, GPIOF_DIR_IN, "sd_cd"); + if (err) + goto out; + + irq = gpio_to_irq(gpio); + if (irq < 0) + goto out_free; + + flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc); + if (err) + goto out_free; + + return 0; + +out_free: + devm_gpio_free(dev, gpio); +out: + dev_warn(dev, "failed to setup card detect wake up\n"); + return err; +} + +#else + +static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, + struct mmc_host *mmc) +{ + return 0; +} + +#endif + static int sdhci_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -171,7 +226,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) struct resource *iomem; resource_size_t len; const char *hid; - int err; + int err, gpio; if (acpi_bus_get_device(handle, &device)) return -ENODEV; @@ -196,6 +251,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (IS_ERR(host)) return PTR_ERR(host); + gpio = acpi_get_gpio_by_index(dev, 0, NULL); + c = sdhci_priv(host); c->host = host; c->slot = sdhci_acpi_get_slot(handle, hid); @@ -251,6 +308,11 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (err) goto err_free; + if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { + if (sdhci_acpi_add_own_cd(dev, gpio, host->mmc)) + c->use_runtime_pm = false; + } + if (c->use_runtime_pm) { pm_runtime_set_active(dev); pm_suspend_ignore_children(dev, 1); -- GitLab From 7396e318b497cd46eb156effa5278126582ddde7 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 6 May 2013 12:17:34 +0300 Subject: [PATCH 0379/2900] mmc: sdhci-pci: support runtime PM for BYT SD cards Add support for runtime PM for BYT SD cards. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 701d06d0e1fb..611331a39fe5 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -332,6 +332,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { }; static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { + .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, + .allow_runtime_pm = true, }; /* O2Micro extra registers */ -- GitLab From 9d5242b19269432ea388d766312ed49f184f83fd Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 25 May 2013 01:46:10 +0000 Subject: [PATCH 0380/2900] netfilter: nfnetlink_queue: avoid peer_portid test The portid is set to NETLINK_CB(skb).portid at create time. The run-time check will always be false. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_queue_core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 2e0e835baf72..cff4449f01d2 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -509,10 +509,6 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue, } spin_lock_bh(&queue->lock); - if (!queue->peer_portid) { - err = -EINVAL; - goto err_out_free_nskb; - } if (queue->queue_total >= queue->queue_maxlen) { if (queue->flags & NFQA_CFG_F_FAIL_OPEN) { failopen = 1; -- GitLab From 8ade62857ef77bdf639185410fbcd811aa700cb2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 May 2013 12:01:26 +0200 Subject: [PATCH 0381/2900] iwlwifi: move D3_CFG_COMPLETE handling into DVM The MVM firmware doesn't communicate this way, it instead assumes D3 configuration is complete after a specific host command (which must be last) has been sent. Handling this bit thus belongs into the firmware API code, i.e. DVM. Signed-off-by: Johannes Berg Reviewed-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 8 ++++++++ drivers/net/wireless/iwlwifi/pcie/trans.c | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cab23af0be9e..700215324af8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -426,6 +426,10 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, if (ret) goto error; + /* let the ucode operate on its own */ + iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + iwl_trans_d3_suspend(priv->trans); goto out; @@ -509,6 +513,10 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) goto out_unlock; } + /* uCode is no longer operating by itself */ + iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR, + CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); + base = priv->device_pointers.error_event_table; if (!iwlagn_hw_valid_rtc_data_addr(base)) { IWL_WARN(priv, "Invalid error table during resume!\n"); diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index a785f49df9b1..0b021305eedf 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -580,10 +580,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) { - /* let the ucode operate on its own */ - iwl_write32(trans, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); - iwl_disable_interrupts(trans); iwl_pcie_disable_ict(trans); @@ -643,9 +639,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, return ret; } - iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); - *status = IWL_D3_STATUS_ALIVE; return 0; } -- GitLab From ee4d5471333c323693f79cdb7b145b40e12baa77 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 May 2013 09:58:27 +0200 Subject: [PATCH 0382/2900] iwlwifi: dvm: rename iwl_lib_ops to iwl_dvm_cfg The next patches will move some more configuration data that isn't needed by mvm into this struct, so rename it now since it won't just be ops. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/agn.h | 14 +++++++------- drivers/net/wireless/iwlwifi/dvm/dev.h | 4 ++-- drivers/net/wireless/iwlwifi/dvm/devices.c | 14 +++++++------- drivers/net/wireless/iwlwifi/dvm/main.c | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 48545ab00311..ff47fce6c58e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h @@ -76,13 +76,13 @@ #define IWL_INVALID_STATION 255 /* device operations */ -extern struct iwl_lib_ops iwl1000_lib; -extern struct iwl_lib_ops iwl2000_lib; -extern struct iwl_lib_ops iwl2030_lib; -extern struct iwl_lib_ops iwl5000_lib; -extern struct iwl_lib_ops iwl5150_lib; -extern struct iwl_lib_ops iwl6000_lib; -extern struct iwl_lib_ops iwl6030_lib; +extern struct iwl_dvm_cfg iwl_dvm_1000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_2000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_2030_cfg; +extern struct iwl_dvm_cfg iwl_dvm_5000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_5150_cfg; +extern struct iwl_dvm_cfg iwl_dvm_6000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_6030_cfg; #define TIME_UNIT 1024 diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 71ea77576d22..beb525cb907a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -568,7 +568,7 @@ struct iwl_hw_params { const struct iwl_sensitivity_ranges *sens; }; -struct iwl_lib_ops { +struct iwl_dvm_cfg { /* set hw dependent parameters */ void (*set_hw_params)(struct iwl_priv *priv); int (*set_channel_switch)(struct iwl_priv *priv, @@ -610,7 +610,7 @@ struct iwl_priv { struct device *dev; /* for debug prints only */ const struct iwl_cfg *cfg; const struct iwl_fw *fw; - const struct iwl_lib_ops *lib; + const struct iwl_dvm_cfg *lib; unsigned long status; spinlock_t sta_lock; diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index c48907c8ab43..5878bbbfc3dd 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -174,7 +174,7 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.sens = &iwl1000_sensitivity; } -struct iwl_lib_ops iwl1000_lib = { +struct iwl_dvm_cfg iwl_dvm_1000_cfg = { .set_hw_params = iwl1000_hw_set_hw_params, .nic_config = iwl1000_nic_config, .temperature = iwlagn_temperature, @@ -232,13 +232,13 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.sens = &iwl2000_sensitivity; } -struct iwl_lib_ops iwl2000_lib = { +struct iwl_dvm_cfg iwl_dvm_2000_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, }; -struct iwl_lib_ops iwl2030_lib = { +struct iwl_dvm_cfg iwl_dvm_2030_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, @@ -420,13 +420,13 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return iwl_dvm_send_cmd(priv, &hcmd); } -struct iwl_lib_ops iwl5000_lib = { +struct iwl_dvm_cfg iwl_dvm_5000_cfg = { .set_hw_params = iwl5000_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwlagn_temperature, }; -struct iwl_lib_ops iwl5150_lib = { +struct iwl_dvm_cfg iwl_dvm_5150_cfg = { .set_hw_params = iwl5150_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwl5150_temperature, @@ -584,14 +584,14 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return err; } -struct iwl_lib_ops iwl6000_lib = { +struct iwl_dvm_cfg iwl_dvm_6000_cfg = { .set_hw_params = iwl6000_hw_set_hw_params, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .temperature = iwlagn_temperature, }; -struct iwl_lib_ops iwl6030_lib = { +struct iwl_dvm_cfg iwl_dvm_6030_cfg = { .set_hw_params = iwl6000_hw_set_hw_params, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 74d7572e7091..0c77222c2c64 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1264,31 +1264,31 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, switch (priv->cfg->device_family) { case IWL_DEVICE_FAMILY_1000: case IWL_DEVICE_FAMILY_100: - priv->lib = &iwl1000_lib; + priv->lib = &iwl_dvm_1000_cfg; break; case IWL_DEVICE_FAMILY_2000: case IWL_DEVICE_FAMILY_105: - priv->lib = &iwl2000_lib; + priv->lib = &iwl_dvm_2000_cfg; break; case IWL_DEVICE_FAMILY_2030: case IWL_DEVICE_FAMILY_135: - priv->lib = &iwl2030_lib; + priv->lib = &iwl_dvm_2030_cfg; break; case IWL_DEVICE_FAMILY_5000: - priv->lib = &iwl5000_lib; + priv->lib = &iwl_dvm_5000_cfg; break; case IWL_DEVICE_FAMILY_5150: - priv->lib = &iwl5150_lib; + priv->lib = &iwl_dvm_5150_cfg; break; case IWL_DEVICE_FAMILY_6000: case IWL_DEVICE_FAMILY_6005: case IWL_DEVICE_FAMILY_6000i: case IWL_DEVICE_FAMILY_6050: case IWL_DEVICE_FAMILY_6150: - priv->lib = &iwl6000_lib; + priv->lib = &iwl_dvm_6000_cfg; break; case IWL_DEVICE_FAMILY_6030: - priv->lib = &iwl6030_lib; + priv->lib = &iwl_dvm_6030_cfg; break; default: break; -- GitLab From 0d8877a10d65f3c9bb84ad150e524d95ebd377fb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 May 2013 10:36:29 +0200 Subject: [PATCH 0383/2900] iwlwifi: move some configuration parameters into DVM There are a number of parameters that aren't really hardware specific but rather define how the DVM firmware is used. Move these into the DVM configuration. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/agn.h | 7 +- drivers/net/wireless/iwlwifi/dvm/calib.c | 8 +- drivers/net/wireless/iwlwifi/dvm/dev.h | 53 +++++++++++- drivers/net/wireless/iwlwifi/dvm/devices.c | 93 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/dvm/lib.c | 20 ++--- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 6 +- drivers/net/wireless/iwlwifi/dvm/main.c | 35 ++++---- drivers/net/wireless/iwlwifi/dvm/power.c | 6 +- drivers/net/wireless/iwlwifi/dvm/rs.c | 8 +- drivers/net/wireless/iwlwifi/dvm/rx.c | 2 +- drivers/net/wireless/iwlwifi/dvm/scan.c | 12 +-- drivers/net/wireless/iwlwifi/dvm/tt.c | 2 +- drivers/net/wireless/iwlwifi/dvm/tx.c | 12 +-- drivers/net/wireless/iwlwifi/dvm/ucode.c | 10 +-- drivers/net/wireless/iwlwifi/iwl-1000.c | 3 - drivers/net/wireless/iwlwifi/iwl-2000.c | 39 +-------- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 - drivers/net/wireless/iwlwifi/iwl-6000.c | 32 +------ drivers/net/wireless/iwlwifi/iwl-7000.c | 9 +- drivers/net/wireless/iwlwifi/iwl-config.h | 43 +--------- 20 files changed, 217 insertions(+), 187 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index ff47fce6c58e..df64a546f52d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h @@ -78,10 +78,13 @@ /* device operations */ extern struct iwl_dvm_cfg iwl_dvm_1000_cfg; extern struct iwl_dvm_cfg iwl_dvm_2000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_105_cfg; extern struct iwl_dvm_cfg iwl_dvm_2030_cfg; extern struct iwl_dvm_cfg iwl_dvm_5000_cfg; extern struct iwl_dvm_cfg iwl_dvm_5150_cfg; extern struct iwl_dvm_cfg iwl_dvm_6000_cfg; +extern struct iwl_dvm_cfg iwl_dvm_6005_cfg; +extern struct iwl_dvm_cfg iwl_dvm_6050_cfg; extern struct iwl_dvm_cfg iwl_dvm_6030_cfg; @@ -291,8 +294,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena); static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) { - return priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist; + return priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist; } #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index d6c4cf2ad7c5..1b0f0d502568 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c @@ -521,7 +521,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv) iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]); - if (priv->cfg->base_params->hd_v2) { + if (priv->lib->hd_v2) { cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] = HD_INA_NON_SQUARE_DET_OFDM_DATA_V2; cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] = @@ -895,7 +895,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, continue; } - delta_g = (priv->cfg->base_params->chain_noise_scale * + delta_g = (priv->lib->chain_noise_scale * ((s32)average_noise[default_chain] - (s32)average_noise[i])) / 1500; @@ -1051,8 +1051,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) return; /* Analyze signal for disconnected antenna */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { /* Disable disconnected antenna algorithm for advanced bt coex, assuming valid antennas are connected */ data->active_chains = priv->nvm_data->valid_rx_ant; diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index beb525cb907a..f1b8df16dbba 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -568,16 +568,61 @@ struct iwl_hw_params { const struct iwl_sensitivity_ranges *sens; }; +/** + * struct iwl_dvm_bt_params - DVM specific BT (coex) parameters + * @advanced_bt_coexist: support advanced bt coexist + * @bt_init_traffic_load: specify initial bt traffic load + * @bt_prio_boost: default bt priority boost value + * @agg_time_limit: maximum number of uSec in aggregation + * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode + */ +struct iwl_dvm_bt_params { + bool advanced_bt_coexist; + u8 bt_init_traffic_load; + u32 bt_prio_boost; + u16 agg_time_limit; + bool bt_sco_disable; + bool bt_session_2; +}; + +/** + * struct iwl_dvm_cfg - DVM firmware specific device configuration + * @set_hw_params: set hardware parameters + * @set_channel_switch: send channel switch command + * @nic_config: apply device specific configuration + * @temperature: read temperature + * @adv_thermal_throttle: support advance thermal throttle + * @support_ct_kill_exit: support ct kill exit condition + * @plcp_delta_threshold: plcp error rate threshold used to trigger + * radio tuning when there is a high receiving plcp error rate + * @chain_noise_scale: default chain noise scale used for gain computation + * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up + * @no_idle_support: do not support idle mode + * @bt_params: pointer to BT parameters + * @need_temp_offset_calib: need to perform temperature offset calibration + * @no_xtal_calib: some devices do not need crystal calibration data, + * don't send it to those + * @temp_offset_v2: support v2 of temperature offset calibration + * @adv_pm: advanced power management + */ struct iwl_dvm_cfg { - /* set hw dependent parameters */ void (*set_hw_params)(struct iwl_priv *priv); int (*set_channel_switch)(struct iwl_priv *priv, struct ieee80211_channel_switch *ch_switch); - /* device specific configuration */ void (*nic_config)(struct iwl_priv *priv); - - /* temperature */ void (*temperature)(struct iwl_priv *priv); + + const struct iwl_dvm_bt_params *bt_params; + s32 chain_noise_scale; + u8 plcp_delta_threshold; + bool adv_thermal_throttle; + bool support_ct_kill_exit; + bool hd_v2; + bool no_idle_support; + bool need_temp_offset_calib; + bool no_xtal_calib; + bool temp_offset_v2; + bool adv_pm; }; struct iwl_wipan_noa_data { diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 5878bbbfc3dd..5a1c2186ea34 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -178,6 +178,9 @@ struct iwl_dvm_cfg iwl_dvm_1000_cfg = { .set_hw_params = iwl1000_hw_set_hw_params, .nic_config = iwl1000_nic_config, .temperature = iwlagn_temperature, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; @@ -236,12 +239,52 @@ struct iwl_dvm_cfg iwl_dvm_2000_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .hd_v2 = true, + .need_temp_offset_calib = true, + .temp_offset_v2 = true, +}; + +struct iwl_dvm_cfg iwl_dvm_105_cfg = { + .set_hw_params = iwl2000_hw_set_hw_params, + .nic_config = iwl2000_nic_config, + .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .hd_v2 = true, + .need_temp_offset_calib = true, + .temp_offset_v2 = true, + .adv_pm = true, +}; + +static const struct iwl_dvm_bt_params iwl2030_bt_params = { + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .advanced_bt_coexist = true, + .agg_time_limit = BT_AGG_THRESHOLD_DEF, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32, + .bt_sco_disable = true, + .bt_session_2 = true, }; struct iwl_dvm_cfg iwl_dvm_2030_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .hd_v2 = true, + .bt_params = &iwl2030_bt_params, + .need_temp_offset_calib = true, + .temp_offset_v2 = true, + .adv_pm = true, }; /* @@ -424,12 +467,19 @@ struct iwl_dvm_cfg iwl_dvm_5000_cfg = { .set_hw_params = iwl5000_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwlagn_temperature, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .no_idle_support = true, }; struct iwl_dvm_cfg iwl_dvm_5150_cfg = { .set_hw_params = iwl5150_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwl5150_temperature, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .no_idle_support = true, + .no_xtal_calib = true, }; @@ -589,6 +639,42 @@ struct iwl_dvm_cfg iwl_dvm_6000_cfg = { .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, +}; + +const struct iwl_dvm_cfg iwl_dvm_6005_cfg = { + .set_hw_params = iwl6000_hw_set_hw_params, + .set_channel_switch = iwl6000_hw_channel_switch, + .nic_config = iwl6000_nic_config, + .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .need_temp_offset_calib = true, +}; + +struct iwl_dvm_cfg iwl_dvm_6050_cfg = { + .set_hw_params = iwl6000_hw_set_hw_params, + .set_channel_switch = iwl6000_hw_channel_switch, + .nic_config = iwl6000_nic_config, + .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1500, +}; + +static const struct iwl_dvm_bt_params iwl6000_bt_params = { + /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ + .advanced_bt_coexist = true, + .agg_time_limit = BT_AGG_THRESHOLD_DEF, + .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, + .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, + .bt_sco_disable = true, }; struct iwl_dvm_cfg iwl_dvm_6030_cfg = { @@ -596,4 +682,11 @@ struct iwl_dvm_cfg iwl_dvm_6030_cfg = { .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, .temperature = iwlagn_temperature, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .bt_params = &iwl6000_bt_params, + .need_temp_offset_calib = true, + .adv_pm = true, }; diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 54f553380aa8..9879550a0fea 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -254,23 +254,23 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != sizeof(basic.bt3_lookup_table)); - if (priv->cfg->bt_params) { + if (priv->lib->bt_params) { /* * newer generation of devices (2000 series and newer) * use the version 2 of the bt command * we need to make sure sending the host command * with correct data structure to avoid uCode assert */ - if (priv->cfg->bt_params->bt_session_2) { + if (priv->lib->bt_params->bt_session_2) { bt_cmd_v2.prio_boost = cpu_to_le32( - priv->cfg->bt_params->bt_prio_boost); + priv->lib->bt_params->bt_prio_boost); bt_cmd_v2.tx_prio_boost = 0; bt_cmd_v2.rx_prio_boost = 0; } else { /* older version only has 8 bits */ - WARN_ON(priv->cfg->bt_params->bt_prio_boost & ~0xFF); + WARN_ON(priv->lib->bt_params->bt_prio_boost & ~0xFF); bt_cmd_v1.prio_boost = - priv->cfg->bt_params->bt_prio_boost; + priv->lib->bt_params->bt_prio_boost; bt_cmd_v1.tx_prio_boost = 0; bt_cmd_v1.rx_prio_boost = 0; } @@ -330,7 +330,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) priv->bt_full_concurrent ? "full concurrency" : "3-wire"); - if (priv->cfg->bt_params->bt_session_2) { + if (priv->lib->bt_params->bt_session_2) { memcpy(&bt_cmd_v2.basic, &basic, sizeof(basic)); ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, @@ -758,8 +758,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv) */ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) { - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && (priv->bt_full_concurrent || priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { /* @@ -830,8 +830,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) else active_chains = priv->nvm_data->valid_rx_ant; - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && (priv->bt_full_concurrent || priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { /* diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 700215324af8..ac7ed3f809a0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1284,8 +1284,8 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211(priv, "enter\n"); mutex_lock(&priv->mutex); - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { if (rssi_event == RSSI_EVENT_LOW) priv->bt_enable_pspoll = true; else if (rssi_event == RSSI_EVENT_HIGH) @@ -1395,7 +1395,7 @@ static int iwl_setup_interface(struct iwl_priv *priv, return err; } - if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist && vif->type == NL80211_IFTYPE_ADHOC) { /* * pretend to have high BT traffic as long as we diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 0c77222c2c64..68f754659570 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -615,7 +615,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv) priv->thermal_throttle.ct_kill_toggle = false; - if (priv->cfg->base_params->support_ct_kill_exit) { + if (priv->lib->support_ct_kill_exit) { adv_cmd.critical_temperature_enter = cpu_to_le32(priv->hw_params.ct_kill_threshold); adv_cmd.critical_temperature_exit = @@ -732,10 +732,10 @@ int iwl_alive_start(struct iwl_priv *priv) } /* download priority table before any calibration request */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { /* Configure Bluetooth device coexistence support */ - if (priv->cfg->bt_params->bt_sco_disable) + if (priv->lib->bt_params->bt_sco_disable) priv->bt_enable_pspoll = false; else priv->bt_enable_pspoll = true; @@ -873,9 +873,9 @@ void iwl_down(struct iwl_priv *priv) priv->bt_status = 0; priv->cur_rssi_ctx = NULL; priv->bt_is_sco = 0; - if (priv->cfg->bt_params) + if (priv->lib->bt_params) priv->bt_traffic_load = - priv->cfg->bt_params->bt_init_traffic_load; + priv->lib->bt_params->bt_init_traffic_load; else priv->bt_traffic_load = 0; priv->bt_full_concurrent = false; @@ -1058,7 +1058,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) iwl_setup_scan_deferred_work(priv); - if (priv->cfg->bt_params) + if (priv->lib->bt_params) iwlagn_bt_setup_deferred_work(priv); init_timer(&priv->statistics_periodic); @@ -1072,7 +1072,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) void iwl_cancel_deferred_work(struct iwl_priv *priv) { - if (priv->cfg->bt_params) + if (priv->lib->bt_params) iwlagn_bt_cancel_deferred_work(priv); cancel_work_sync(&priv->run_time_calib_work); @@ -1098,8 +1098,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->band = IEEE80211_BAND_2GHZ; - priv->plcp_delta_threshold = - priv->cfg->base_params->plcp_delta_threshold; + priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold; priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; @@ -1116,8 +1115,8 @@ static int iwl_init_drv(struct iwl_priv *priv) iwl_init_scan_params(priv); /* init bt coex */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT; priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK; @@ -1267,9 +1266,11 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->lib = &iwl_dvm_1000_cfg; break; case IWL_DEVICE_FAMILY_2000: - case IWL_DEVICE_FAMILY_105: priv->lib = &iwl_dvm_2000_cfg; break; + case IWL_DEVICE_FAMILY_105: + priv->lib = &iwl_dvm_105_cfg; + break; case IWL_DEVICE_FAMILY_2030: case IWL_DEVICE_FAMILY_135: priv->lib = &iwl_dvm_2030_cfg; @@ -1281,11 +1282,15 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->lib = &iwl_dvm_5150_cfg; break; case IWL_DEVICE_FAMILY_6000: - case IWL_DEVICE_FAMILY_6005: case IWL_DEVICE_FAMILY_6000i: + priv->lib = &iwl_dvm_6000_cfg; + break; + case IWL_DEVICE_FAMILY_6005: + priv->lib = &iwl_dvm_6005_cfg; + break; case IWL_DEVICE_FAMILY_6050: case IWL_DEVICE_FAMILY_6150: - priv->lib = &iwl_dvm_6000_cfg; + priv->lib = &iwl_dvm_6050_cfg; break; case IWL_DEVICE_FAMILY_6030: priv->lib = &iwl_dvm_6030_cfg; diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index bd69018d07a9..77cb59712235 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c @@ -163,7 +163,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, u8 skip; u32 slp_itrvl; - if (priv->cfg->adv_pm) { + if (priv->lib->adv_pm) { table = apm_range_2; if (period <= IWL_DTIM_RANGE_1_MAX) table = apm_range_1; @@ -217,7 +217,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; if (iwl_advanced_bt_coexist(priv)) { - if (!priv->cfg->bt_params->bt_sco_disable) + if (!priv->lib->bt_params->bt_sco_disable) cmd->flags |= IWL_POWER_BT_SCO_ENA; else cmd->flags &= ~IWL_POWER_BT_SCO_ENA; @@ -293,7 +293,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, if (priv->wowlan) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper); - else if (!priv->cfg->base_params->no_idle_support && + else if (!priv->lib->no_idle_support && priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (iwl_tt_is_low_power_state(priv)) { diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 907bd6e50aad..94314a8e1029 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -1088,7 +1088,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) rs_program_fix_rate(priv, lq_sta); #endif - if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) + if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -3064,11 +3064,11 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, * overwrite if needed, pass aggregation time limit * to uCode in uSec */ - if (priv && priv->cfg->bt_params && - priv->cfg->bt_params->agg_time_limit && + if (priv && priv->lib->bt_params && + priv->lib->bt_params->agg_time_limit && priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) lq_cmd->agg_params.agg_time_limit = - cpu_to_le16(priv->cfg->bt_params->agg_time_limit); + cpu_to_le16(priv->lib->bt_params->agg_time_limit); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index a4eed2055fdb..2f3fd160ab44 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c @@ -1102,7 +1102,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) iwl_notification_wait_init(&priv->notif_wait); /* Set up BT Rx handlers */ - if (priv->cfg->bt_params) + if (priv->lib->bt_params) iwlagn_bt_rx_handler_setup(priv); } diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c index d69b55866714..8c686a5b90ac 100644 --- a/drivers/net/wireless/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/iwlwifi/dvm/scan.c @@ -801,8 +801,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) * Internal scans are passive, so we can indiscriminately set * the BT ignore flag on 2.4 GHz since it applies to TX only. */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; break; case IEEE80211_BAND_5GHZ: @@ -844,8 +844,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) band = priv->scan_band; if (band == IEEE80211_BAND_2GHZ && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { /* transmit 2.4 GHz probes only on first antenna */ scan_tx_antennas = first_antenna(scan_tx_antennas); } @@ -873,8 +873,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) rx_ant = first_antenna(active_chains); } - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && priv->bt_full_concurrent) { /* operated as 1x1 in full concurrency mode */ rx_ant = first_antenna(rx_ant); diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 03f9bc01c0cc..fbeee081ee2f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c @@ -627,7 +627,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); - if (priv->cfg->base_params->adv_thermal_throttle) { + if (priv->lib->adv_thermal_throttle) { IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n"); tt->restriction = kcalloc(IWL_TI_STATE_MAX, sizeof(struct iwl_tt_restriction), diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index a900aaf47790..353a053b4eb1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -83,8 +83,8 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, else if (ieee80211_is_back_req(fc)) tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; else if (info->band == IEEE80211_BAND_2GHZ && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc) || skb->protocol == cpu_to_be16(ETH_P_PAE))) @@ -202,8 +202,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, rate_flags |= RATE_MCS_CCK_MSK; /* Set up antennas */ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && priv->bt_full_concurrent) { /* operated as 1x1 in full concurrency mode */ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, @@ -986,8 +986,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, * notification again. */ if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 && - priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n"); } diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c index 0a1cdc5e856b..86270b69cd02 100644 --- a/drivers/net/wireless/iwlwifi/dvm/ucode.c +++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c @@ -132,8 +132,8 @@ int iwl_init_alive_start(struct iwl_priv *priv) { int ret; - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist) { + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist) { /* * Tell uCode we are ready to perform calibration * need to perform this before any calibration @@ -155,8 +155,8 @@ int iwl_init_alive_start(struct iwl_priv *priv) * temperature offset calibration is only needed for runtime ucode, * so prepare the value now. */ - if (priv->cfg->need_temp_offset_calib) { - if (priv->cfg->temp_offset_v2) + if (priv->lib->need_temp_offset_calib) { + if (priv->lib->temp_offset_v2) return iwl_set_temperature_offset_calib_v2(priv); else return iwl_set_temperature_offset_calib(priv); @@ -277,7 +277,7 @@ static int iwl_alive_notify(struct iwl_priv *priv) if (ret) return ret; - if (!priv->cfg->no_xtal_calib) { + if (!priv->lib->no_xtal_calib) { ret = iwl_set_Xtal_calib(priv); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index c080ae3070b2..0d2afe098afc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -60,9 +60,6 @@ static const struct iwl_base_params iwl1000_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_1000, .shadow_ram_support = false, .led_compensation = 51, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_WATCHDOG_DISABLED, .max_event_log_size = 128, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index a6ddd2f9fba0..c727ec7c90a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -72,14 +72,9 @@ static const struct iwl_base_params iwl2000_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 51, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ - .hd_v2 = true, }; @@ -90,14 +85,9 @@ static const struct iwl_base_params iwl2030_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_2x00, .shadow_ram_support = true, .led_compensation = 57, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ - .hd_v2 = true, }; static const struct iwl_ht_params iwl2000_ht_params = { @@ -106,16 +96,6 @@ static const struct iwl_ht_params iwl2000_ht_params = { .ht40_bands = BIT(IEEE80211_BAND_2GHZ), }; -static const struct iwl_bt_params iwl2030_bt_params = { - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .advanced_bt_coexist = true, - .agg_time_limit = BT_AGG_THRESHOLD_DEF, - .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32, - .bt_sco_disable = true, - .bt_session_2 = true, -}; - static const struct iwl_eeprom_params iwl20x0_eeprom_params = { .regulatory_bands = { EEPROM_REG_BAND_1_CHANNELS, @@ -137,12 +117,10 @@ static const struct iwl_eeprom_params iwl20x0_eeprom_params = { .device_family = IWL_DEVICE_FAMILY_2000, \ .max_inst_size = IWL60_RTC_INST_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \ - .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ - .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ + .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ + .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .base_params = &iwl2000_base_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ - .need_temp_offset_calib = true, \ - .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl2000_2bgn_cfg = { @@ -168,12 +146,8 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .base_params = &iwl2030_base_params, \ - .bt_params = &iwl2030_bt_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ - .need_temp_offset_calib = true, \ - .temp_offset_v2 = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true + .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl2030_2bgn_cfg = { .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", @@ -193,10 +167,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .base_params = &iwl2000_base_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ - .need_temp_offset_calib = true, \ - .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true, \ .rx_with_siso_diversity = true const struct iwl_cfg iwl105_bgn_cfg = { @@ -222,12 +193,8 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { .nvm_ver = EEPROM_2000_EEPROM_VERSION, \ .nvm_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .base_params = &iwl2030_base_params, \ - .bt_params = &iwl2030_bt_params, \ .eeprom_params = &iwl20x0_eeprom_params, \ - .need_temp_offset_calib = true, \ - .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true, \ .rx_with_siso_diversity = true const struct iwl_cfg iwl135_bgn_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 403f3f224bf6..ecc01e1a61a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -59,11 +59,8 @@ static const struct iwl_base_params iwl5000_base_params = { .num_of_queues = IWLAGN_NUM_QUEUES, .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, .led_compensation = 51, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_WATCHDOG_DISABLED, .max_event_log_size = 512, - .no_idle_support = true, }; static const struct iwl_ht_params iwl5000_ht_params = { @@ -159,7 +156,6 @@ const struct iwl_cfg iwl5350_agn_cfg = { .nvm_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ .base_params = &iwl5000_base_params, \ .eeprom_params = &iwl5000_eeprom_params, \ - .no_xtal_calib = true, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b5ab8d1bcac0..30d45e2fc193 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -82,10 +82,6 @@ static const struct iwl_base_params iwl6000_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 51, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ @@ -98,10 +94,6 @@ static const struct iwl_base_params iwl6050_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_6x50, .shadow_ram_support = true, .led_compensation = 51, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1500, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ @@ -114,10 +106,6 @@ static const struct iwl_base_params iwl6000_g2_base_params = { .max_ll_items = OTP_MAX_LL_ITEMS_6x00, .shadow_ram_support = true, .led_compensation = 57, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ @@ -129,15 +117,6 @@ static const struct iwl_ht_params iwl6000_ht_params = { .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), }; -static const struct iwl_bt_params iwl6000_bt_params = { - /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ - .advanced_bt_coexist = true, - .agg_time_limit = BT_AGG_THRESHOLD_DEF, - .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, - .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, - .bt_sco_disable = true, -}; - static const struct iwl_eeprom_params iwl6000_eeprom_params = { .regulatory_bands = { EEPROM_REG_BAND_1_CHANNELS, @@ -163,7 +142,6 @@ static const struct iwl_eeprom_params iwl6000_eeprom_params = { .nvm_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ .base_params = &iwl6000_g2_base_params, \ .eeprom_params = &iwl6000_eeprom_params, \ - .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl6005_2agn_cfg = { @@ -217,11 +195,8 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ .base_params = &iwl6000_g2_base_params, \ - .bt_params = &iwl6000_bt_params, \ .eeprom_params = &iwl6000_eeprom_params, \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true \ + .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl6030_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN", @@ -256,11 +231,8 @@ const struct iwl_cfg iwl6030_2bg_cfg = { .nvm_ver = EEPROM_6030_EEPROM_VERSION, \ .nvm_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ .base_params = &iwl6000_g2_base_params, \ - .bt_params = &iwl6000_bt_params, \ .eeprom_params = &iwl6000_eeprom_params, \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true + .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index c9aae2a2bbbb..d4f3b4864ab1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -96,10 +96,6 @@ static const struct iwl_base_params iwl7000_base_params = { .pll_cfg_val = 0, .shadow_ram_support = true, .led_compensation = 57, - .adv_thermal_throttle = true, - .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .shadow_reg_enable = true, @@ -118,10 +114,7 @@ static const struct iwl_ht_params iwl7000_ht_params = { .max_inst_size = IWL60_RTC_INST_SIZE, \ .max_data_size = IWL60_RTC_DATA_SIZE, \ .base_params = &iwl7000_base_params, \ - /* TODO: .bt_params? */ \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true \ + .led_mode = IWL_LED_RF_STATE const struct iwl_cfg iwl7260_2ac_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index c3c9268affab..a193832fc790 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -136,17 +136,9 @@ enum iwl_led_mode { * @led_compensation: compensate on the led on/off time per HW according * to the deviation to achieve the desired led frequency. * The detail algorithm is described in iwl-led.c - * @chain_noise_num_beacons: number of beacons used to compute chain noise - * @adv_thermal_throttle: support advance thermal throttle - * @support_ct_kill_exit: support ct kill exit condition - * @plcp_delta_threshold: plcp error rate threshold used to trigger - * radio tuning when there is a high receiving plcp error rate - * @chain_noise_scale: default chain noise scale used for gain computation * @wd_timeout: TX queues watchdog timeout * @max_event_log_size: size of event log buffer size for ucode event logging * @shadow_reg_enable: HW shadow register support - * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up - * @no_idle_support: do not support idle mode */ struct iwl_base_params { int eeprom_size; @@ -157,31 +149,9 @@ struct iwl_base_params { const u16 max_ll_items; const bool shadow_ram_support; u16 led_compensation; - bool adv_thermal_throttle; - bool support_ct_kill_exit; - u8 plcp_delta_threshold; - s32 chain_noise_scale; unsigned int wd_timeout; u32 max_event_log_size; const bool shadow_reg_enable; - const bool hd_v2; - const bool no_idle_support; -}; - -/* - * @advanced_bt_coexist: support advanced bt coexist - * @bt_init_traffic_load: specify initial bt traffic load - * @bt_prio_boost: default bt priority boost value - * @agg_time_limit: maximum number of uSec in aggregation - * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode - */ -struct iwl_bt_params { - bool advanced_bt_coexist; - u8 bt_init_traffic_load; - u32 bt_prio_boost; - u16 agg_time_limit; - bool bt_sco_disable; - bool bt_session_2; }; /* @@ -231,16 +201,10 @@ struct iwl_eeprom_params { * @nvm_calib_ver: NVM calibration version * @lib: pointer to the lib ops * @base_params: pointer to basic parameters - * @ht_params: point to ht patameters - * @bt_params: pointer to bt parameters - * @need_temp_offset_calib: need to perform temperature offset calibration - * @no_xtal_calib: some devices do not need crystal calibration data, - * don't send it to those + * @ht_params: point to ht parameters * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) - * @adv_pm: advance power management * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device - * @temp_offset_v2: support v2 of temperature offset calibration * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -264,15 +228,10 @@ struct iwl_cfg { const struct iwl_base_params *base_params; /* params likely to change within a device family */ const struct iwl_ht_params *ht_params; - const struct iwl_bt_params *bt_params; const struct iwl_eeprom_params *eeprom_params; - const bool need_temp_offset_calib; /* if used set to true */ - const bool no_xtal_calib; enum iwl_led_mode led_mode; - const bool adv_pm; const bool rx_with_siso_diversity; const bool internal_wimax_coex; - const bool temp_offset_v2; }; /* -- GitLab From 129219c0fd234164ebc19e8694641927317eda13 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 17 May 2013 10:38:21 +0200 Subject: [PATCH 0384/2900] iwlwifi: dvm: constify configuration structs The pointer that gets used is already const, so the structs can obviously be const as well. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/agn.h | 20 ++++++++++---------- drivers/net/wireless/iwlwifi/dvm/devices.c | 18 +++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index df64a546f52d..de2c9514bef6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h @@ -76,16 +76,16 @@ #define IWL_INVALID_STATION 255 /* device operations */ -extern struct iwl_dvm_cfg iwl_dvm_1000_cfg; -extern struct iwl_dvm_cfg iwl_dvm_2000_cfg; -extern struct iwl_dvm_cfg iwl_dvm_105_cfg; -extern struct iwl_dvm_cfg iwl_dvm_2030_cfg; -extern struct iwl_dvm_cfg iwl_dvm_5000_cfg; -extern struct iwl_dvm_cfg iwl_dvm_5150_cfg; -extern struct iwl_dvm_cfg iwl_dvm_6000_cfg; -extern struct iwl_dvm_cfg iwl_dvm_6005_cfg; -extern struct iwl_dvm_cfg iwl_dvm_6050_cfg; -extern struct iwl_dvm_cfg iwl_dvm_6030_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_1000_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_2000_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_105_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_2030_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_5000_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_5150_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_6000_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_6005_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_6050_cfg; +extern const struct iwl_dvm_cfg iwl_dvm_6030_cfg; #define TIME_UNIT 1024 diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 5a1c2186ea34..352c6cb7b4f1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -174,7 +174,7 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.sens = &iwl1000_sensitivity; } -struct iwl_dvm_cfg iwl_dvm_1000_cfg = { +const struct iwl_dvm_cfg iwl_dvm_1000_cfg = { .set_hw_params = iwl1000_hw_set_hw_params, .nic_config = iwl1000_nic_config, .temperature = iwlagn_temperature, @@ -235,7 +235,7 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.sens = &iwl2000_sensitivity; } -struct iwl_dvm_cfg iwl_dvm_2000_cfg = { +const struct iwl_dvm_cfg iwl_dvm_2000_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, @@ -248,7 +248,7 @@ struct iwl_dvm_cfg iwl_dvm_2000_cfg = { .temp_offset_v2 = true, }; -struct iwl_dvm_cfg iwl_dvm_105_cfg = { +const struct iwl_dvm_cfg iwl_dvm_105_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, @@ -272,7 +272,7 @@ static const struct iwl_dvm_bt_params iwl2030_bt_params = { .bt_session_2 = true, }; -struct iwl_dvm_cfg iwl_dvm_2030_cfg = { +const struct iwl_dvm_cfg iwl_dvm_2030_cfg = { .set_hw_params = iwl2000_hw_set_hw_params, .nic_config = iwl2000_nic_config, .temperature = iwlagn_temperature, @@ -463,7 +463,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, return iwl_dvm_send_cmd(priv, &hcmd); } -struct iwl_dvm_cfg iwl_dvm_5000_cfg = { +const struct iwl_dvm_cfg iwl_dvm_5000_cfg = { .set_hw_params = iwl5000_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwlagn_temperature, @@ -472,7 +472,7 @@ struct iwl_dvm_cfg iwl_dvm_5000_cfg = { .no_idle_support = true, }; -struct iwl_dvm_cfg iwl_dvm_5150_cfg = { +const struct iwl_dvm_cfg iwl_dvm_5150_cfg = { .set_hw_params = iwl5150_hw_set_hw_params, .set_channel_switch = iwl5000_hw_channel_switch, .temperature = iwl5150_temperature, @@ -634,7 +634,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, return err; } -struct iwl_dvm_cfg iwl_dvm_6000_cfg = { +const struct iwl_dvm_cfg iwl_dvm_6000_cfg = { .set_hw_params = iwl6000_hw_set_hw_params, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, @@ -657,7 +657,7 @@ const struct iwl_dvm_cfg iwl_dvm_6005_cfg = { .need_temp_offset_calib = true, }; -struct iwl_dvm_cfg iwl_dvm_6050_cfg = { +const struct iwl_dvm_cfg iwl_dvm_6050_cfg = { .set_hw_params = iwl6000_hw_set_hw_params, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, @@ -677,7 +677,7 @@ static const struct iwl_dvm_bt_params iwl6000_bt_params = { .bt_sco_disable = true, }; -struct iwl_dvm_cfg iwl_dvm_6030_cfg = { +const struct iwl_dvm_cfg iwl_dvm_6030_cfg = { .set_hw_params = iwl6000_hw_set_hw_params, .set_channel_switch = iwl6000_hw_channel_switch, .nic_config = iwl6000_nic_config, -- GitLab From 071d4990fd9fe6fe27b47f1587ba11db3111c3fd Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Mon, 6 May 2013 13:03:59 +0300 Subject: [PATCH 0385/2900] iwlwifi: mvm: Add beacon abort enablement Beacon abort is used by device to increase idle dwell time when system is idle. This algorithm is on top of beacon filtering feature. Enable beacon abort only if power management is enabled. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- .../net/wireless/iwlwifi/mvm/fw-api-power.h | 9 ++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 + drivers/net/wireless/iwlwifi/mvm/power.c | 121 +++++++++++------- 3 files changed, 86 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 05e51927b848..b6bdfd36bebe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -193,4 +193,13 @@ struct iwl_beacon_filter_cmd { #define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 +#define IWL_BF_CMD_CONFIG_DEFAULTS \ + .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \ + .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \ + .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \ + .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \ + .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \ + .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ + .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) + #endif diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 712c39ae748f..02ba8303a09f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -173,6 +173,8 @@ struct iwl_mvm_vif { bool uploaded; bool ap_active; bool monitor_active; + /* indicate whether beacon filtering is enabled */ + bool bf_enabled; u32 ap_beacon_time; diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index f5bdfb71c790..c818d6d6aee6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -75,6 +75,53 @@ #define POWER_KEEP_ALIVE_PERIOD_SEC 25 +static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, + struct iwl_beacon_filter_cmd *cmd) +{ + int ret; + + ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC, + sizeof(struct iwl_beacon_filter_cmd), cmd); + + if (!ret) { + IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", + cmd->ba_enable_beacon_abort); + IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", + cmd->ba_escape_timer); + IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", + cmd->bf_debug_flag); + IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", + cmd->bf_enable_beacon_filter); + IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", + cmd->bf_energy_delta); + IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", + cmd->bf_escape_timer); + IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", + cmd->bf_roaming_energy_delta); + IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", + cmd->bf_roaming_state); + IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", + cmd->bf_temperature_delta); + } + return ret; +} + +static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, bool enable) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_beacon_filter_cmd cmd = { + IWL_BF_CMD_CONFIG_DEFAULTS, + .bf_enable_beacon_filter = 1, + .ba_enable_beacon_abort = enable, + }; + + if (!mvmvif->bf_enabled) + return 0; + + return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); +} + static void iwl_mvm_power_log(struct iwl_mvm *mvm, struct iwl_powertable_cmd *cmd) { @@ -162,6 +209,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { + int ret; + bool ba_enable; struct iwl_powertable_cmd cmd = {}; if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) @@ -170,8 +219,15 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); - return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, - sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, + sizeof(cmd), &cmd); + if (ret) + return ret; + + ba_enable = !!(cmd.flags & + cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)); + + return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); } int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -190,69 +246,42 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) sizeof(cmd), &cmd); } -static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, - struct iwl_beacon_filter_cmd *cmd) -{ - int ret; - - ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, CMD_SYNC, - sizeof(struct iwl_beacon_filter_cmd), cmd); - - if (!ret) { - IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", - cmd->ba_enable_beacon_abort); - IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", - cmd->ba_escape_timer); - IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", - cmd->bf_debug_flag); - IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", - cmd->bf_enable_beacon_filter); - IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", - cmd->bf_energy_delta); - IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", - cmd->bf_escape_timer); - IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", - cmd->bf_roaming_energy_delta); - IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", - cmd->bf_roaming_state); - IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", - cmd->bf_temperature_delta); - } - return ret; -} - int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_beacon_filter_cmd cmd = { + IWL_BF_CMD_CONFIG_DEFAULTS, .bf_enable_beacon_filter = 1, - .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, - .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, - .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, - .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, - .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, - .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), - .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT), - .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT, }; + int ret; if (mvmvif != mvm->bf_allowed_vif || vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; - return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); + ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); + + if (!ret) + mvmvif->bf_enabled = true; + + return ret; } int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { - struct iwl_beacon_filter_cmd cmd = { - .bf_enable_beacon_filter = 0, - }; + struct iwl_beacon_filter_cmd cmd = {}; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int ret; if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; - return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); + ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); + + if (!ret) + mvmvif->bf_enabled = false; + + return ret; } -- GitLab From f68d18f202d50f60746a8bcce1dc965b2f5035c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 20 May 2013 08:59:31 +0300 Subject: [PATCH 0386/2900] iwlwifi: mvm: use proper scan type for P2P It was set to be FORCED because of a firmware bug which has been fixed. Signed-off-by: Emmanuel Grumbach Reviewed-by: Ilan Peer Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/scan.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 2476e43799d5..2157b0f8ced5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -298,12 +298,6 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, else cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); - /* - * TODO: This is a WA due to a bug in the FW AUX framework that does not - * properly handle time events that fail to be scheduled - */ - cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); - cmd->repeats = cpu_to_le32(1); /* -- GitLab From 4e7dba99c9e606e304f104ce4071d8b5ba93957e Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Wed, 22 May 2013 14:59:10 +0200 Subject: [PATCH 0387/2900] netfilter: Implement RFC 1123 for FTP conntrack The FTP conntrack code currently only accepts the following format for the 227 response for PASV: 227 Entering Passive Mode (148,100,81,40,31,161). It doesn't accept the following format from an obscure server: 227 Data transfer will passively listen to 67,218,99,134,50,144 From RFC 1123: The format of the 227 reply to a PASV command is not well standardized. In particular, an FTP client cannot assume that the parentheses shown on page 40 of RFC-959 will be present (and in fact, Figure 3 on page 43 omits them). Therefore, a User-FTP program that interprets the PASV reply must scan the reply for the first digit of the host and port numbers. This patch adds support for the RFC 1123 clarification by: - Allowing a search filter to specify NUL as the terminator so that try_number will return successfully if the array of numbers has been filled when an unexpected character is encountered. - Using space as the separator for the 227 reply and then scanning for the first digit of the number sequence. The number sequence is parsed out using the existing try_rfc959 but with a NUL terminator. References: https://bugzilla.novell.com/show_bug.cgi?id=466279 References: http://bugzilla.netfilter.org/show_bug.cgi?id=574 Reported-by: Mark Post Signed-off-by: Jeff Mahoney Signed-off-by: Jiri Slaby Cc: Pablo Neira Ayuso Cc: Patrick McHardy Cc: "David S. Miller" Cc: netfilter-devel@vger.kernel.org Cc: netfilter@vger.kernel.org Cc: coreteam@netfilter.org Cc: netdev@vger.kernel.org Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_ftp.c | 73 +++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 6b217074237b..b8a0924064ef 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c @@ -55,10 +55,14 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, struct nf_conntrack_expect *exp); EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); -static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); -static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); +static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, + char, unsigned int *); +static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *, + char, unsigned int *); +static int try_eprt(const char *, size_t, struct nf_conntrack_man *, + char, unsigned int *); static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, - char); + char, unsigned int *); static struct ftp_search { const char *pattern; @@ -66,7 +70,7 @@ static struct ftp_search { char skip; char term; enum nf_ct_ftp_type ftptype; - int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char); + int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char, unsigned int *); } search[IP_CT_DIR_MAX][2] = { [IP_CT_DIR_ORIGINAL] = { { @@ -90,10 +94,8 @@ static struct ftp_search { { .pattern = "227 ", .plen = sizeof("227 ") - 1, - .skip = '(', - .term = ')', .ftptype = NF_CT_FTP_PASV, - .getnum = try_rfc959, + .getnum = try_rfc1123, }, { .pattern = "229 ", @@ -132,8 +134,9 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[], i++; else { /* Unexpected character; true if it's the - terminator and we're finished. */ - if (*data == term && i == array_size - 1) + terminator (or we don't care about one) + and we're finished. */ + if ((*data == term || !term) && i == array_size - 1) return len; pr_debug("Char %u (got %u nums) `%u' unexpected\n", @@ -148,7 +151,8 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[], /* Returns 0, or length of numbers: 192,168,1,1,5,6 */ static int try_rfc959(const char *data, size_t dlen, - struct nf_conntrack_man *cmd, char term) + struct nf_conntrack_man *cmd, char term, + unsigned int *offset) { int length; u_int32_t array[6]; @@ -163,6 +167,33 @@ static int try_rfc959(const char *data, size_t dlen, return length; } +/* + * From RFC 1123: + * The format of the 227 reply to a PASV command is not + * well standardized. In particular, an FTP client cannot + * assume that the parentheses shown on page 40 of RFC-959 + * will be present (and in fact, Figure 3 on page 43 omits + * them). Therefore, a User-FTP program that interprets + * the PASV reply must scan the reply for the first digit + * of the host and port numbers. + */ +static int try_rfc1123(const char *data, size_t dlen, + struct nf_conntrack_man *cmd, char term, + unsigned int *offset) +{ + int i; + for (i = 0; i < dlen; i++) + if (isdigit(data[i])) + break; + + if (i == dlen) + return 0; + + *offset += i; + + return try_rfc959(data + i, dlen - i, cmd, 0, offset); +} + /* Grab port: number up to delimiter */ static int get_port(const char *data, int start, size_t dlen, char delim, __be16 *port) @@ -191,7 +222,7 @@ static int get_port(const char *data, int start, size_t dlen, char delim, /* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, - char term) + char term, unsigned int *offset) { char delim; int length; @@ -239,7 +270,8 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, /* Returns 0, or length of numbers: |||6446| */ static int try_epsv_response(const char *data, size_t dlen, - struct nf_conntrack_man *cmd, char term) + struct nf_conntrack_man *cmd, char term, + unsigned int *offset) { char delim; @@ -261,9 +293,10 @@ static int find_pattern(const char *data, size_t dlen, unsigned int *numlen, struct nf_conntrack_man *cmd, int (*getnum)(const char *, size_t, - struct nf_conntrack_man *, char)) + struct nf_conntrack_man *, char, + unsigned int *)) { - size_t i; + size_t i = plen; pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen); if (dlen == 0) @@ -293,16 +326,18 @@ static int find_pattern(const char *data, size_t dlen, pr_debug("Pattern matches!\n"); /* Now we've found the constant string, try to skip to the 'skip' character */ - for (i = plen; data[i] != skip; i++) - if (i == dlen - 1) return -1; + if (skip) { + for (i = plen; data[i] != skip; i++) + if (i == dlen - 1) return -1; - /* Skip over the last character */ - i++; + /* Skip over the last character */ + i++; + } pr_debug("Skipped up to `%c'!\n", skip); *numoff = i; - *numlen = getnum(data + i, dlen - i, cmd, term); + *numlen = getnum(data + i, dlen - i, cmd, term, numoff); if (!*numlen) return -1; -- GitLab From 99119595d9ff06f74d97d3623fd8a63138f9b287 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 20 May 2013 12:32:39 -0300 Subject: [PATCH 0388/2900] [media] media: fix hdpvr kconfig/build errors Fix hdpvr build errors when CONFIG_I2C=m and VIDEO_V4L2=m and VIDEO_HDPVR=y. drivers/built-in.o: In function `hdpvr_disconnect': hdpvr-core.c:(.text+0xef542): undefined reference to `v4l2_device_disconnect' hdpvr-core.c:(.text+0xef57e): undefined reference to `i2c_del_adapter' hdpvr-core.c:(.text+0xef58a): undefined reference to `video_unregister_device' drivers/built-in.o: In function `hdpvr_delete': (.text+0xef5b9): undefined reference to `video_device_release' drivers/built-in.o: In function `hdpvr_probe': hdpvr-core.c:(.text+0xef63a): undefined reference to `v4l2_device_register' hdpvr-core.c:(.text+0xefd97): undefined reference to `i2c_del_adapter' drivers/built-in.o: In function `hdpvr_s_ctrl': hdpvr-video.c:(.text+0xf03c0): undefined reference to `v4l2_ctrl_activate' drivers/built-in.o: In function `hdpvr_device_release': hdpvr-video.c:(.text+0xf0470): undefined reference to `v4l2_device_unregister' hdpvr-video.c:(.text+0xf0479): undefined reference to `v4l2_ctrl_handler_free' hdpvr-video.c:(.text+0xf048f): undefined reference to `i2c_del_adapter' drivers/built-in.o: In function `hdpvr_open': hdpvr-video.c:(.text+0xf0570): undefined reference to `video_devdata' hdpvr-video.c:(.text+0xf057b): undefined reference to `v4l2_fh_init' hdpvr-video.c:(.text+0xf0583): undefined reference to `v4l2_fh_add' drivers/built-in.o: In function `video_drvdata': hdpvr-video.c:(.text+0xf08a0): undefined reference to `video_devdata' drivers/built-in.o: In function `vidioc_s_dv_timings': hdpvr-video.c:(.text+0xf0d34): undefined reference to `v4l_match_dv_timings' drivers/built-in.o: In function `hdpvr_poll': hdpvr-video.c:(.text+0xf1455): undefined reference to `v4l2_ctrl_poll' drivers/built-in.o: In function `hdpvr_release': hdpvr-video.c:(.text+0xf18f6): undefined reference to `v4l2_fh_release' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1be3): undefined reference to `v4l2_ctrl_handler_init_class' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1c19): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1c42): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1c6b): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1cac): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1cd5): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o:(.text+0xf1cfe): more undefined references to `v4l2_ctrl_new_std' follow drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1d75): undefined reference to `v4l2_ctrl_new_std_menu' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1d9e): undefined reference to `v4l2_ctrl_new_std_menu' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1dc3): undefined reference to `v4l2_ctrl_new_std_menu' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1de5): undefined reference to `v4l2_ctrl_new_std_menu' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1e18): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1e4b): undefined reference to `v4l2_ctrl_new_std' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1e90): undefined reference to `v4l2_ctrl_cluster' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1e98): undefined reference to `v4l2_ctrl_handler_setup' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1ec1): undefined reference to `video_device_alloc' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1f85): undefined reference to `__video_register_device' drivers/built-in.o: In function `hdpvr_register_videodev': (.text+0xf1fac): undefined reference to `v4l2_ctrl_handler_free' drivers/built-in.o: In function `hdpvr_register_ir_tx_i2c': (.text+0xf238f): undefined reference to `i2c_new_device' drivers/built-in.o: In function `hdpvr_register_ir_rx_i2c': (.text+0xf2434): undefined reference to `i2c_new_device' drivers/built-in.o: In function `hdpvr_register_i2c_adapter': (.text+0xf2514): undefined reference to `i2c_add_adapter' drivers/built-in.o:(.rodata+0x1b368): undefined reference to `video_ioctl2' drivers/built-in.o:(.rodata+0x1b690): undefined reference to `v4l2_ctrl_log_status' drivers/built-in.o:(.rodata+0x1b6f8): undefined reference to `v4l2_ctrl_subscribe_event' drivers/built-in.o:(.rodata+0x1b700): undefined reference to `v4l2_event_unsubscribe' Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig index de247f3c7d05..d73d9a1952b4 100644 --- a/drivers/media/usb/hdpvr/Kconfig +++ b/drivers/media/usb/hdpvr/Kconfig @@ -1,7 +1,7 @@ config VIDEO_HDPVR tristate "Hauppauge HD PVR support" - depends on VIDEO_DEV + depends on VIDEO_DEV && VIDEO_V4L2 ---help--- This is a video4linux driver for Hauppauge's HD PVR USB device. -- GitLab From 5dd6946c419a3a553842115665e142d1245fb837 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 01:48:45 -0300 Subject: [PATCH 0389/2900] [media] v4l: vb2: fix error return code in __vb2_init_fileio() Fix to return -EINVAL in the get kernel address error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Reviewed-by: Sakari Ailus Acked-by: Marek Szyprowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 7d833eefaf4e..7bd3ee67727d 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2193,8 +2193,10 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) */ for (i = 0; i < q->num_buffers; i++) { fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); - if (fileio->bufs[i].vaddr == NULL) + if (fileio->bufs[i].vaddr == NULL) { + ret = -EINVAL; goto err_reqbufs; + } fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); } -- GitLab From b2d2cf1015004209d6493f21b99788ded42eac11 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 01:57:23 -0300 Subject: [PATCH 0390/2900] [media] vpif_display: fix error return code in vpif_probe() Fix to return -ENODEV in the subdevice register error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 7b1736842690..5b6f9065b881 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1797,6 +1797,7 @@ static __init int vpif_probe(struct platform_device *pdev) NULL); if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); + err = -ENODEV; goto probe_subdev_out; } -- GitLab From 4fa94e224b84be7b2522a0f5ce5b64124f146fac Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 01:57:37 -0300 Subject: [PATCH 0391/2900] [media] vpif_capture: fix error return code in vpif_probe() Fix to return -ENODEV in the subdevice register error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a1b42b037678..caaf4fedadec 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2159,6 +2159,7 @@ static __init int vpif_probe(struct platform_device *pdev) if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); + err = -ENODEV; goto probe_subdev_out; } v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", -- GitLab From 6ec735df78c63c3623c76e75a975390f60ae0640 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 02:00:10 -0300 Subject: [PATCH 0392/2900] [media] ad9389b: fix error return code in ad9389b_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 15043554cc8b..1d4e4e70e8f8 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -1250,12 +1250,14 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1)); if (state->edid_i2c_client == NULL) { v4l2_err(sd, "failed to register edid i2c client\n"); + err = -ENOMEM; goto err_entity; } state->work_queue = create_singlethread_workqueue(sd->name); if (state->work_queue == NULL) { v4l2_err(sd, "could not create workqueue\n"); + err = -ENOMEM; goto err_unreg; } -- GitLab From d9fdbeff26b87e68d0e7f0d506e3cfc0f2a28d56 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 04:52:16 -0300 Subject: [PATCH 0393/2900] [media] blackfin: fix error return code in bcap_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Scott Jiang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/blackfin/bfin_capture.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 03530bc6bdd1..ca8d56aecfb0 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -974,7 +974,7 @@ static int bcap_probe(struct platform_device *pdev) int ret; config = pdev->dev.platform_data; - if (!config) { + if (!config || !config->num_inputs) { v4l2_err(pdev->dev.driver, "Unable to get board config\n"); return -ENODEV; } @@ -1081,11 +1081,6 @@ static int bcap_probe(struct platform_device *pdev) NULL); if (bcap_dev->sd) { int i; - if (!config->num_inputs) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to work without input\n"); - goto err_unreg_vdev; - } /* update tvnorms from the sub devices */ for (i = 0; i < config->num_inputs; i++) @@ -1093,6 +1088,7 @@ static int bcap_probe(struct platform_device *pdev) } else { v4l2_err(&bcap_dev->v4l2_dev, "Unable to register sub device\n"); + ret = -ENODEV; goto err_unreg_vdev; } -- GitLab From d017650b40b4cb5c4158e3b9af38af164986b022 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 10:00:01 -0300 Subject: [PATCH 0394/2900] [media] sta2x11_vip: fix error return code in sta2x11_vip_init_one() The orig code will release all the resources if v4l2_device_register() failed and return 0. But what we need in this case is to return an negative error code to let the caller known we are failed. So the patch save the return value of v4l2_device_register() to 'ret' and return it when error. Signed-off-by: Wei Yongjun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/sta2x11/sta2x11_vip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 7005695aa4bd..77edc113e485 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -1047,7 +1047,8 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, ret = sta2x11_vip_init_controls(vip); if (ret) goto free_mem; - if (v4l2_device_register(&pdev->dev, &vip->v4l2_dev)) + ret = v4l2_device_register(&pdev->dev, &vip->v4l2_dev); + if (ret) goto free_mem; dev_dbg(&pdev->dev, "BAR #0 at 0x%lx 0x%lx irq %d\n", -- GitLab From 5c75a55e3c2820f2fd7e256e577c1b528567f3ae Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 15 May 2013 17:56:11 -0300 Subject: [PATCH 0395/2900] [media] sony-btf-mpx: Drop needless newline in param description Module parameter descriptions need not be terminated with a newline. Signed-off-by: Jean Delvare Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/sony-btf-mpx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c index efa306165618..32d82320b485 100644 --- a/drivers/media/i2c/sony-btf-mpx.c +++ b/drivers/media/i2c/sony-btf-mpx.c @@ -30,7 +30,7 @@ MODULE_LICENSE("GPL v2"); static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on\n"); +MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on"); /* #define MPX_DEBUG */ -- GitLab From ff29feb9146d1c0020f2ccbb25369582c6a16681 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 20 May 2013 06:02:40 -0300 Subject: [PATCH 0396/2900] [media] videodev2.h: fix typos This patch fixes several typos in videodev2.h file Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/videodev2.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 16c3cf71eb94..2c5e67a45436 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -555,7 +555,7 @@ struct v4l2_jpegcompression { __u32 jpeg_markers; /* Which markers should go into the JPEG * output. Unless you exactly know what * you do, leave them untouched. - * Inluding less markers will make the + * Including less markers will make the * resulting code smaller, but there will * be fewer applications which can read it. * The presence of the APP and COM marker @@ -567,7 +567,7 @@ struct v4l2_jpegcompression { #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * always use APP0 */ }; /* @@ -900,7 +900,7 @@ typedef __u64 v4l2_std_id; /* * "Common" PAL - This macro is there to be compatible with the old * V4L1 concept of "PAL": /BGDKHI. - * Several PAL standards are mising here: /M, /N and /Nc + * Several PAL standards are missing here: /M, /N and /Nc */ #define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ V4L2_STD_PAL_DK |\ @@ -1790,7 +1790,7 @@ struct v4l2_event_subscription { #define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE #define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ #define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ -#define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against ancillary AC97 chip */ #define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ struct v4l2_dbg_match { -- GitLab From 4d601c4ca272959ba837b8279f4873b55caaf619 Mon Sep 17 00:00:00 2001 From: Leonid Kegulskiy Date: Mon, 13 May 2013 07:10:42 -0300 Subject: [PATCH 0397/2900] [media] hdpvr: Removed unnecessary use of kzalloc() in get_video_info() [mchehab@redhat.com: CodingStyle fixes] Signed-off-by: Leonid Kegulskiy Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-control.c | 25 +++++------- drivers/media/usb/hdpvr/hdpvr-video.c | 54 ++++++++++++------------- drivers/media/usb/hdpvr/hdpvr.h | 2 +- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c index ae8f229d1141..df6bcb524d80 100644 --- a/drivers/media/usb/hdpvr/hdpvr-control.c +++ b/drivers/media/usb/hdpvr/hdpvr-control.c @@ -45,20 +45,10 @@ int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) return ret < 0 ? ret : 0; } -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) +int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) { - struct hdpvr_video_info *vidinf = NULL; -#ifdef HDPVR_DEBUG - char print_buf[15]; -#endif int ret; - vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); - if (!vidinf) { - v4l2_err(&dev->v4l2_dev, "out of memory\n"); - goto err; - } - mutex_lock(&dev->usbc_mutex); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), @@ -74,6 +64,7 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) #ifdef HDPVR_DEBUG if (hdpvr_debug & MSG_INFO) { + char print_buf[15]; hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, sizeof(print_buf), 0); v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, @@ -82,12 +73,14 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) #endif mutex_unlock(&dev->usbc_mutex); - if (!vidinf->width || !vidinf->height || !vidinf->fps) { - kfree(vidinf); - vidinf = NULL; + if ((ret > 0 && ret != 5) ||/* fail if unexpected byte count returned */ + !vidinf->width || /* preserve original behavior - */ + !vidinf->height || /* fail if no signal is detected */ + !vidinf->fps) { + ret = -EFAULT; } -err: - return vidinf; + + return ret < 0 ? ret : 0; } int get_input_lines_info(struct hdpvr_device *dev) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index cd90ba81a5bb..2d02b490756b 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -277,20 +277,19 @@ static void hdpvr_transmit_buffers(struct work_struct *work) static int hdpvr_start_streaming(struct hdpvr_device *dev) { int ret; - struct hdpvr_video_info *vidinf; + struct hdpvr_video_info vidinf; if (dev->status == STATUS_STREAMING) return 0; else if (dev->status != STATUS_IDLE) return -EAGAIN; - vidinf = get_video_info(dev); + ret = get_video_info(dev, &vidinf); - if (vidinf) { + if (!ret) { v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "video signal: %dx%d@%dhz\n", vidinf->width, - vidinf->height, vidinf->fps); - kfree(vidinf); + "video signal: %dx%d@%dhz\n", vidinf.width, + vidinf.height, vidinf.fps); /* start streaming 2 request */ ret = usb_control_msg(dev->udev, @@ -610,21 +609,22 @@ static int vidioc_g_std(struct file *file, void *_fh, static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; struct hdpvr_fh *fh = _fh; + int ret; *a = V4L2_STD_ALL; if (dev->options.video_input == HDPVR_COMPONENT) return fh->legacy_mode ? 0 : -ENODATA; - vid_info = get_video_info(dev); - if (vid_info == NULL) + ret = get_video_info(dev, &vid_info); + if (ret) return 0; - if (vid_info->width == 720 && - (vid_info->height == 480 || vid_info->height == 576)) { - *a = (vid_info->height == 480) ? + if (vid_info.width == 720 && + (vid_info.height == 480 || vid_info.height == 576)) { + *a = (vid_info.height == 480) ? V4L2_STD_525_60 : V4L2_STD_625_50; } - kfree(vid_info); + return 0; } @@ -669,7 +669,7 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, { struct hdpvr_device *dev = video_drvdata(file); struct hdpvr_fh *fh = _fh; - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; bool interlaced; int ret = 0; int i; @@ -677,10 +677,10 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, fh->legacy_mode = false; if (dev->options.video_input) return -ENODATA; - vid_info = get_video_info(dev); - if (vid_info == NULL) + ret = get_video_info(dev, &vid_info); + if (ret) return -ENOLCK; - interlaced = vid_info->fps <= 30; + interlaced = vid_info.fps <= 30; for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) { const struct v4l2_bt_timings *bt = &hdpvr_dv_timings[i].bt; unsigned hsize; @@ -692,17 +692,17 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch + bt->height; fps = (unsigned)bt->pixelclock / (hsize * vsize); - if (bt->width != vid_info->width || - bt->height != vid_info->height || + if (bt->width != vid_info.width || + bt->height != vid_info.height || bt->interlaced != interlaced || - (fps != vid_info->fps && fps + 1 != vid_info->fps)) + (fps != vid_info.fps && fps + 1 != vid_info.fps)) continue; *timings = hdpvr_dv_timings[i]; break; } if (i == ARRAY_SIZE(hdpvr_dv_timings)) ret = -ERANGE; - kfree(vid_info); + return ret; } @@ -992,6 +992,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, { struct hdpvr_device *dev = video_drvdata(file); struct hdpvr_fh *fh = _fh; + int ret; /* * The original driver would always returns the current detected @@ -1004,14 +1005,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, * last set format. */ if (fh->legacy_mode) { - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; - vid_info = get_video_info(dev); - if (!vid_info) + ret = get_video_info(dev, &vid_info); + if (ret) return -EFAULT; - f->fmt.pix.width = vid_info->width; - f->fmt.pix.height = vid_info->height; - kfree(vid_info); + f->fmt.pix.width = vid_info.width; + f->fmt.pix.height = vid_info.height; } else { f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index 1478f3d57630..808ea7a0efe5 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h @@ -303,7 +303,7 @@ int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, int hdpvr_config_call(struct hdpvr_device *dev, uint value, unsigned char valbuf); -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); +int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vid_info); /* :0 s b8 81 1800 0003 0003 3 < */ /* :0 0 3 = 0301ff */ -- GitLab From 94204cd4e1452e13ecf5fc6fcec9485e93e8a8f4 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 21 Mar 2013 13:31:53 +0100 Subject: [PATCH 0398/2900] ARM: ux500: select WATCHDOG and MUSB for ux500 Enable ux500 specific USB and watchdog drivers by default on u8500_defconfig. Signed-off-by: Fabio Baltieri Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c037aa1065b7..acb62cf36c70 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -70,6 +70,7 @@ CONFIG_GPIO_TC3589X=y # CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL is not set CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y +CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_AB5500_CORE=y @@ -79,7 +80,13 @@ CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_GPIO=y # CONFIG_HID_SUPPORT is not set +CONFIG_USB=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_UX500=y +CONFIG_USB_PHY=y CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_ETH=m CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_CLKGATE=y -- GitLab From b39ca96c63822a22a1d2f08a247fd49353913fcd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 24 May 2013 08:51:25 +0200 Subject: [PATCH 0399/2900] ARM: ux500: update defconfig base Update the defconfig removing/adding selections due to Kconfig changes, and select some new hardware drivers that have been matured in the tree. For example: - CONFIG_NO_HZ and CONFIG_HIGH_RES_TIMERS come from the make oldconfig changes after the recent changes to how NOHZ is handled. - The U5500 config option is now gone as the machine is deleted. So is the AB5500 driver. - CPU_IDLE selected explicitly. - LP5521 Kconfig has been moved around. - AB8500 core is default-selected, as is the AB8500 USB transciever. - The battery and charging management drivers for the AB8500 are not selected again. - Select the crypto devices that have been shaped up to work properly. Cc: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index acb62cf36c70..da0614abafde 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,6 +1,7 @@ -CONFIG_EXPERIMENTAL=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y @@ -9,10 +10,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_U8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y -CONFIG_MACH_U5500=y CONFIG_MACH_UX500_DT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y CONFIG_NR_CPUS=2 CONFIG_PREEMPT=y @@ -20,6 +18,7 @@ CONFIG_AEABI=y CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM_RUNTIME=y @@ -36,7 +35,6 @@ CONFIG_CAIF=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=65536 -CONFIG_AB8500_PWM=y CONFIG_SENSORS_BH1780=y CONFIG_NETDEVICES=y CONFIG_SMSC911X=y @@ -60,42 +58,33 @@ CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_NOMADIK=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_GPIO_STMPE=y CONFIG_GPIO_TC3589X=y -# CONFIG_POWER_SUPPLY is not set -# CONFIG_AB8500_BM is not set -# CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL is not set CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y -CONFIG_AB5500_CORE=y -CONFIG_AB8500_CORE=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_AB8500=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_GPIO=y -# CONFIG_HID_SUPPORT is not set +CONFIG_REGULATOR_AB8500=y CONFIG_USB=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_UX500=y CONFIG_USB_PHY=y +CONFIG_AB8500_USB=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ETH=m -CONFIG_AB8500_USB=y CONFIG_MMC=y CONFIG_MMC_CLKGATE=y CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_LM3530=y -CONFIG_LEDS_LP5521=y CONFIG_LEDS_GPIO=y +CONFIG_LEDS_LP5521=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_RTC_CLASS=y @@ -115,7 +104,6 @@ CONFIG_EXT4_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_CONFIGFS_FS=m # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y @@ -129,3 +117,7 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO=y # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_DEV_UX500=y +CONFIG_CRYPTO_DEV_UX500_CRYP=y +CONFIG_CRYPTO_DEV_UX500_HASH=y +CONFIG_CRYPTO_DEV_UX500_DEBUG=y -- GitLab From d78b655050bbb917069839d5aa1a051f0d867566 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 24 May 2013 15:28:13 +0200 Subject: [PATCH 0400/2900] ARM: ux500: select SND_SOC_UX500 for ux500 Enable ux500 specific ALSA SoC drivers by default on u8500_defconfig. Signed-off-by: Fabio Baltieri Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index da0614abafde..da353e0755b0 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -69,6 +69,11 @@ CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_AB8500=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_UX500=y +CONFIG_SND_SOC_UX500_MACH_MOP500=y CONFIG_USB=y CONFIG_USB_MUSB_HDRC=y CONFIG_USB_MUSB_UX500=y -- GitLab From abc0fd734e1327a85306457a438a1a23cf7c7925 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 06:45:30 -0300 Subject: [PATCH 0401/2900] [media] media: i2c: tvp7002: remove duplicate define this patch removes duplicate #define TVP7002_MODULE_NAME form the driver file, which was also defined in media/tvp7002.h Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 270e6997cc76..81b4eb40d7a6 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -41,9 +41,6 @@ MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); MODULE_AUTHOR("Santiago Nunez-Corrales "); MODULE_LICENSE("GPL"); -/* Module Name */ -#define TVP7002_MODULE_NAME "tvp7002" - /* I2C retry attempts */ #define I2C_RETRY_COUNT (5) -- GitLab From 19ec93057439cffc3b89910cd356892fbe2172fa Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 06:45:31 -0300 Subject: [PATCH 0402/2900] [media] media: i2c: tvp7002: rearrange description of structure members This patch rearranges the description of field members of struct tvp7002_config. Also as the all the fields where accepting a value either 0/1, made the members as bool. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/tvp7002.h | 44 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/include/media/tvp7002.h b/include/media/tvp7002.h index 7123048408d6..fadb6afe9ef0 100644 --- a/include/media/tvp7002.h +++ b/include/media/tvp7002.h @@ -28,31 +28,27 @@ #define TVP7002_MODULE_NAME "tvp7002" -/* Platform-dependent data - * - * clk_polarity: - * 0 -> data clocked out on rising edge of DATACLK signal - * 1 -> data clocked out on falling edge of DATACLK signal - * hs_polarity: - * 0 -> active low HSYNC output - * 1 -> active high HSYNC output - * sog_polarity: - * 0 -> normal operation - * 1 -> operation with polarity inverted - * vs_polarity: - * 0 -> active low VSYNC output - * 1 -> active high VSYNC output - * fid_polarity: - * 0 -> the field ID output is set to logic 1 for an odd - * field (field 1) and set to logic 0 for an even - * field (field 0). - * 1 -> operation with polarity inverted. +/** + * struct tvp7002_config - Platform dependent data + *@clk_polarity: Clock polarity + * 0 - Data clocked out on rising edge of DATACLK signal + * 1 - Data clocked out on falling edge of DATACLK signal + *@hs_polarity: HSYNC polarity + * 0 - Active low HSYNC output, 1 - Active high HSYNC output + *@vs_polarity: VSYNC Polarity + * 0 - Active low VSYNC output, 1 - Active high VSYNC output + *@fid_polarity: Active-high Field ID polarity. + * 0 - The field ID output is set to logic 1 for an odd field + * (field 1) and set to logic 0 for an even field (field 0). + * 1 - Operation with polarity inverted. + *@sog_polarity: Active high Sync on Green output polarity. + * 0 - Normal operation, 1 - Operation with polarity inverted */ struct tvp7002_config { - u8 clk_polarity; - u8 hs_polarity; - u8 vs_polarity; - u8 fid_polarity; - u8 sog_polarity; + bool clk_polarity; + bool hs_polarity; + bool vs_polarity; + bool fid_polarity; + bool sog_polarity; }; #endif -- GitLab From 6266a9d9b0e9824562c3c5604dd812d3befc72f1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 10 May 2013 08:06:50 -0300 Subject: [PATCH 0403/2900] [media] bw-qcam: fix timestamp handling bw-qcam didn't set the timestamp and it didn't set q->timestamp_type. Tested-by: Borislav Petkov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/parport/bw-qcam.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c index 06231b85e1a9..d12bd33f39cb 100644 --- a/drivers/media/parport/bw-qcam.c +++ b/drivers/media/parport/bw-qcam.c @@ -687,6 +687,7 @@ static int buffer_finish(struct vb2_buffer *vb) parport_release(qcam->pdev); mutex_unlock(&qcam->lock); + v4l2_get_timestamp(&vb->v4l2_buf.timestamp); if (len != size) vb->state = VB2_BUF_STATE_ERROR; vb2_set_plane_payload(vb, 0, len); @@ -964,6 +965,7 @@ static struct qcam *qcam_init(struct parport *port) q->drv_priv = qcam; q->ops = &qcam_video_qops; q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; err = vb2_queue_init(q); if (err < 0) { v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name); -- GitLab From a0c6ae257e416e5cdf7018223500d327d58da2d7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 13 May 2013 05:24:07 -0300 Subject: [PATCH 0404/2900] [media] timblogiw: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/timblogiw.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c index a2f7bdd5104f..99861c631798 100644 --- a/drivers/media/platform/timblogiw.c +++ b/drivers/media/platform/timblogiw.c @@ -834,11 +834,9 @@ static int timblogiw_probe(struct platform_device *pdev) goto err_request; } - return 0; err_request: - platform_set_drvdata(pdev, NULL); v4l2_device_unregister(&lw->v4l2_dev); err_register: kfree(lw); @@ -858,8 +856,6 @@ static int timblogiw_remove(struct platform_device *pdev) kfree(lw); - platform_set_drvdata(pdev, NULL); - return 0; } -- GitLab From d78fe0877867258ac422bc851ee3110f679e1246 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 13 May 2013 05:24:08 -0300 Subject: [PATCH 0405/2900] [media] rc: gpio-ir-recv: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/gpio-ir-recv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 8b82ae9bd686..07aacfa5903d 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -178,7 +178,6 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) return 0; err_request_irq: - platform_set_drvdata(pdev, NULL); rc_unregister_device(rcdev); rcdev = NULL; err_register_rc_device: @@ -196,7 +195,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); - platform_set_drvdata(pdev, NULL); rc_unregister_device(gpio_dev->rcdev); gpio_free(gpio_dev->gpio_nr); kfree(gpio_dev); -- GitLab From dad0e1ce0468d12b50b5735635d9283842ea8de3 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 04:18:22 -0300 Subject: [PATCH 0406/2900] [media] coda: v4l2-compliance fix: add bus_info prefix 'platform' Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 48b8d7af386d..d64908a74000 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -323,7 +323,7 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver)); strlcpy(cap->card, CODA_NAME, sizeof(cap->card)); - strlcpy(cap->bus_info, CODA_NAME, sizeof(cap->bus_info)); + strlcpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); /* * This is only a mem-to-mem video device. The capture and output * device capability flags are left only for backward compatibility -- GitLab From 611cbbfefa2170a281981b67f2fa3f7d498cc518 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 04:19:27 -0300 Subject: [PATCH 0407/2900] [media] coda: use devm_ioremap_resource Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index d64908a74000..421230732051 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1976,17 +1976,9 @@ static int coda_probe(struct platform_device *pdev) return -ENOENT; } - if (devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), CODA_NAME) == NULL) { - dev_err(&pdev->dev, "failed to request memory region\n"); - return -ENOENT; - } - dev->regs_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!dev->regs_base) { - dev_err(&pdev->dev, "failed to ioremap address region\n"); - return -ENOENT; - } + dev->regs_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->regs_base)) + return PTR_ERR(dev->regs_base); /* IRQ */ irq = platform_get_irq(pdev, 0); -- GitLab From 419869c86f9745157fd6398ba65c79fda5982c6f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 07:06:30 -0300 Subject: [PATCH 0408/2900] [media] coda: enable dmabuf support Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 421230732051..2d8e50e1c9b8 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -569,6 +569,14 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } +static int vidioc_expbuf(struct file *file, void *priv, + struct v4l2_exportbuffer *eb) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); +} + static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct coda_ctx *ctx = fh_to_ctx(priv); @@ -609,6 +617,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, + .vidioc_expbuf = vidioc_expbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_streamon = vidioc_streamon, @@ -1422,7 +1431,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &coda_qops; @@ -1434,7 +1443,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &coda_qops; -- GitLab From c4eb1bfcbd7c2591caecda531072efda9e727dfa Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 04:24:16 -0300 Subject: [PATCH 0409/2900] [media] coda: set umask 0644 on debug module param Otherwise module/coda/parameters/coda_debug won't show up in sysfs. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 2d8e50e1c9b8..b1f77d3c8594 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -67,7 +67,7 @@ #define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) static int coda_debug; -module_param(coda_debug, int, 0); +module_param(coda_debug, int, 0644); MODULE_PARM_DESC(coda_debug, "Debug level (0-1)"); enum { -- GitLab From 72720ffc74a58ce27ea237c729f38e6a966f2997 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 10:31:25 -0300 Subject: [PATCH 0410/2900] [media] coda: fix error return value if v4l2_m2m_ctx_init fails Use ret from the outer scope, instead of redefining it in the conditional clause. That way the error value reaches the end of the function as intended. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b1f77d3c8594..aebd17251ba2 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1484,7 +1484,7 @@ static int coda_open(struct file *file) ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &coda_queue_init); if (IS_ERR(ctx->m2m_ctx)) { - int ret = PTR_ERR(ctx->m2m_ctx); + ret = PTR_ERR(ctx->m2m_ctx); v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", __func__, ret); -- GitLab From 39cc029f9c74a9917560c51f1b5dd2ed8c4ede8a Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 21 May 2013 10:32:42 -0300 Subject: [PATCH 0411/2900] [media] coda: do not use v4l2_dev in coda_timeout The timeout delayed work might be scheduled even after the v4l2 device is released. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index aebd17251ba2..efb42b2913ca 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1676,7 +1676,7 @@ static void coda_timeout(struct work_struct *work) complete(&dev->done); - v4l2_err(&dev->v4l2_dev, "CODA PIC_RUN timeout, stopping all streams\n"); + dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n"); mutex_lock(&dev->dev_mutex); list_for_each_entry(ctx, &dev->instances, list) { -- GitLab From 7e89bd9f242930371f89f3d8c32eaf42ea1c74b1 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 01:45:14 -0300 Subject: [PATCH 0412/2900] [media] media: i2c: remove duplicate checks for EPERM in dbg_g/s_register This patch removes check for EPERM in dbg_g/s_register of subdevice drivers as this check is already performed by core. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 4 ---- drivers/media/i2c/adv7183.c | 4 ---- drivers/media/i2c/adv7604.c | 4 ---- drivers/media/i2c/cs5345.c | 4 ---- drivers/media/i2c/cx25840/cx25840-core.c | 4 ---- drivers/media/i2c/m52790.c | 4 ---- drivers/media/i2c/mt9v011.c | 4 ---- drivers/media/i2c/ov7670.c | 4 ---- drivers/media/i2c/saa7115.c | 4 ---- drivers/media/i2c/saa7127.c | 4 ---- drivers/media/i2c/saa717x.c | 4 ---- drivers/media/i2c/ths7303.c | 4 ---- drivers/media/i2c/tvp5150.c | 4 ---- drivers/media/i2c/tvp7002.c | 10 ++-------- drivers/media/i2c/upd64031a.c | 4 ---- drivers/media/i2c/upd64083.c | 4 ---- drivers/media/i2c/vs6624.c | 4 ---- 17 files changed, 2 insertions(+), 72 deletions(-) diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 1d4e4e70e8f8..ade1fec7e040 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -347,8 +347,6 @@ static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = ad9389b_rd(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -360,8 +358,6 @@ static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 42b2dec4ca3a..7c48e22b41a2 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -500,8 +500,6 @@ static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = adv7183_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -513,8 +511,6 @@ static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 4cdcfc96aa56..5528cd15cc67 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -647,8 +647,6 @@ static int adv7604_g_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; switch (reg->reg >> 8) { case 0: @@ -705,8 +703,6 @@ static int adv7604_s_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; switch (reg->reg >> 8) { case 0: io_write(sd, reg->reg & 0xff, reg->val & 0xff); diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index 841b9c49dcfa..2661757c3a8c 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -103,8 +103,6 @@ static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; reg->val = cs5345_read(sd, reg->reg & 0x1f); return 0; @@ -116,8 +114,6 @@ static int cs5345_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index bdfec4c768fe..b81e32f371ae 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -1664,8 +1664,6 @@ static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; reg->val = cx25840_read(client, reg->reg & 0x0fff); return 0; @@ -1677,8 +1675,6 @@ static int cx25840_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 0d153f3b1a5b..3eeb546be6d9 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -87,8 +87,6 @@ static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (reg->reg != 0) return -EINVAL; reg->size = 1; @@ -103,8 +101,6 @@ static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (reg->reg != 0) return -EINVAL; state->input = reg->val & 0x0303; diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index c64c9d9e253d..141919bf77fc 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -411,8 +411,6 @@ static int mt9v011_g_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = mt9v011_read(sd, reg->reg & 0xff); reg->size = 2; @@ -427,8 +425,6 @@ static int mt9v011_s_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index d71602f4fb43..b030279810d3 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1479,8 +1479,6 @@ static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ret = ov7670_read(sd, reg->reg & 0xff, &val); reg->val = val; reg->size = 1; @@ -1493,8 +1491,6 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 8316ae448f4c..18cf0bfaf743 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1464,8 +1464,6 @@ static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa711x_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -1477,8 +1475,6 @@ static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index 9882c83c1c93..d9c388103e7a 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -665,8 +665,6 @@ static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa7127_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -678,8 +676,6 @@ static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index 71328109642e..330a04c58939 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -981,8 +981,6 @@ static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa717x_read(sd, reg->reg); reg->size = 1; return 0; @@ -996,8 +994,6 @@ static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa717x_write(sd, addr, val); return 0; } diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index c4339556a2ea..65853eea09a1 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -236,8 +236,6 @@ static int ths7303_g_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; reg->val = ths7303_read(sd, reg->reg); @@ -251,8 +249,6 @@ static int ths7303_s_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ths7303_write(sd, reg->reg, reg->val); return 0; diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index de9db3bf1ebd..b3cf26628c09 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1054,8 +1054,6 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; res = tvp5150_read(sd, reg->reg & 0xff); if (res < 0) { v4l2_err(sd, "%s: failed with error = %d\n", __func__, res); @@ -1073,8 +1071,6 @@ static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 81b4eb40d7a6..f339e6faca90 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -736,8 +736,7 @@ static int tvp7002_query_dv_timings(struct v4l2_subdev *sd, * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails or - * access to I2C client fails, -EPERM if the call is not allowed - * by disabled CAP_SYS_ADMIN. + * access to I2C client fails. */ static int tvp7002_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -748,8 +747,6 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ret = tvp7002_read(sd, reg->reg & 0xff, &val); reg->val = val; @@ -762,8 +759,7 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. - * Returns zero when successful, -EINVAL if register read fails or - * -EPERM if call not allowed. + * Returns zero when successful, -EINVAL if register read fails. */ static int tvp7002_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) @@ -772,8 +768,6 @@ static int tvp7002_s_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff); } diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 4283fc5f39ef..13a4cf8bebdf 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -168,8 +168,6 @@ static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = upd64031a_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -181,8 +179,6 @@ static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_re if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index b2ac56ca22e6..e296639ab90e 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -126,8 +126,6 @@ static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = upd64083_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -139,8 +137,6 @@ static int upd64083_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_reg if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; upd64083_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index 7b55b3ddd80f..d2209a35c510 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -741,8 +741,6 @@ static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = vs6624_read(sd, reg->reg & 0xffff); reg->size = 1; return 0; @@ -754,8 +752,6 @@ static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); return 0; } -- GitLab From d5f8fb5b46ed07c4e2a6811eff4ae4368652c9ea Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 01:45:15 -0300 Subject: [PATCH 0413/2900] [media] media: dvb-frontends: remove duplicate checks for EPERM in dbg_g/s_register This patch removes check for EPERM in dbg_g/s_register as this check is already performed by core. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/au8522_decoder.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 2099f21e374d..9d159b48e50b 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -529,8 +529,6 @@ static int au8522_g_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = au8522_readreg(state, reg->reg & 0xffff); return 0; } @@ -543,8 +541,6 @@ static int au8522_s_register(struct v4l2_subdev *sd, if (!v4l2_chip_match_i2c_client(client, ®->match)) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; au8522_writereg(state, reg->reg, reg->val & 0xff); return 0; } -- GitLab From 625b35229bc491e837b385b7ce1e2a8eece3db0f Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 01:45:16 -0300 Subject: [PATCH 0414/2900] [media] media: usb: remove duplicate checks for EPERM in vidioc_g/s_register This patch removes check for EPERM in vidioc_g/s_register as this check is already performed by core. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index e11267f35d87..01d1c2d47cb5 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -5173,8 +5173,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, int stat = 0; int okFl = 0; - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.match = *match; req.reg = reg_id; if (setFl) req.val = *val_ptr; -- GitLab From 7eac97d7e714429f7ef1ba5d35f94c07f4c34f8e Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 14 May 2013 01:45:17 -0300 Subject: [PATCH 0415/2900] [media] media: pci: remove duplicate checks for EPERM This patch removes check for EPERM in dbg_g/s_register and vidioc_g/s_register as this check is already performed by core. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 6 ------ drivers/media/pci/cx18/cx18-av-core.c | 4 ---- drivers/media/pci/cx23885/cx23885-ioctl.c | 6 ------ drivers/media/pci/cx23885/cx23888-ir.c | 4 ---- drivers/media/pci/ivtv/ivtv-ioctl.c | 2 -- drivers/media/pci/saa7146/mxb.c | 4 ---- drivers/media/pci/saa7164/saa7164-encoder.c | 6 ------ 7 files changed, 32 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index e7d088413411..a334c94a303d 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1936,9 +1936,6 @@ static int bttv_g_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!v4l2_chip_match_host(®->match)) { /* TODO: subdev errors should not be ignored, this should become a subdev helper function. */ @@ -1960,9 +1957,6 @@ static int bttv_s_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!v4l2_chip_match_host(®->match)) { /* TODO: subdev errors should not be ignored, this should become a subdev helper function. */ diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c index 38b1d64ffc27..ba8caf0fbb85 100644 --- a/drivers/media/pci/cx18/cx18-av-core.c +++ b/drivers/media/pci/cx18/cx18-av-core.c @@ -1258,8 +1258,6 @@ static int cx18_av_g_register(struct v4l2_subdev *sd, return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 4; reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc); return 0; @@ -1274,8 +1272,6 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val); return 0; } diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c index acdb6d58db58..00f51251728b 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.c +++ b/drivers/media/pci/cx23885/cx23885-ioctl.c @@ -138,9 +138,6 @@ int cx23885_g_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { switch (reg->match.addr) { case 0: @@ -186,9 +183,6 @@ int cx23885_s_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { switch (reg->match.addr) { case 0: diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index fa672fe41079..cd98651f3ae6 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -1116,8 +1116,6 @@ static int cx23888_ir_g_register(struct v4l2_subdev *sd, return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 4; reg->val = cx23888_ir_read4(state->dev, addr); return 0; @@ -1135,8 +1133,6 @@ static int cx23888_ir_s_register(struct v4l2_subdev *sd, return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx23888_ir_write4(state->dev, addr, reg->val); return 0; } diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 9cbbce0eaedc..3e281eccdd88 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -715,8 +715,6 @@ static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) { volatile u8 __iomem *reg_start; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (reg >= IVTV_REG_OFFSET && reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) reg_start = itv->reg_mem - IVTV_REG_OFFSET; else if (itv->has_cx23415 && reg >= IVTV_DECODER_OFFSET && diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 71e8bead321b..52cbe7a027cc 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -669,8 +669,6 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (v4l2_chip_match_host(®->match)) { reg->val = saa7146_read(dev, reg->reg); reg->size = 4; @@ -684,8 +682,6 @@ static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_ { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (v4l2_chip_match_host(®->match)) { saa7146_write(dev, reg->reg, reg->val); return 0; diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 0b74fb2300dd..63a72fb71f30 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -1306,9 +1306,6 @@ static int saa7164_g_register(struct file *file, void *fh, struct saa7164_dev *dev = port->dev; dprintk(DBGLVL_ENC, "%s()\n", __func__); - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 0; } @@ -1319,9 +1316,6 @@ static int saa7164_s_register(struct file *file, void *fh, struct saa7164_dev *dev = port->dev; dprintk(DBGLVL_ENC, "%s()\n", __func__); - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return 0; } #endif -- GitLab From 8487662994aaf2b66ab72a096a05b8404daa6eeb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 27 May 2013 14:30:15 +0200 Subject: [PATCH 0416/2900] ARM: ux500: Update MMC configs for u8500 defconfig Enable MMC_UNSAFE_RESUME to be accomplish a proper suspend/resume cycle for SD/SDIO/(e)MMC. ARMMMCI host driver supports clock gating through runtime PM, thus MMC_CLKGATE is not needed. Moreover ARMMMCI can do scatter-gather which means we can explicity disable MMC_BLOCK_BOUNCE, since it's default enabled, to skip unnecessary bounce buffer copying. Signed-off-by: Ulf Hansson Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index da353e0755b0..b2326b019b83 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -83,7 +83,8 @@ CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MUSB_HDRC=y CONFIG_USB_ETH=m CONFIG_MMC=y -CONFIG_MMC_CLKGATE=y +CONFIG_MMC_UNSAFE_RESUME=y +# CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_ARMMMCI=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y -- GitLab From 6abb9cb99f33b20c2f32f18a3ae9cc7543e46edb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 15 May 2013 09:30:07 +0200 Subject: [PATCH 0417/2900] cfg80211: make WoWLAN configuration available to drivers Make the current WoWLAN configuration available to drivers at runtime. This isn't really useful for the normal WoWLAN behaviour and accessing it can also be racy, but drivers may use it for testing the WoWLAN device behaviour while the host stays up & running to observe the device. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++++ net/wireless/core.c | 4 +++- net/wireless/core.h | 21 +++++++++-------- net/wireless/nl80211.c | 53 ++++++++++++++++++++++-------------------- net/wireless/sysfs.c | 8 +++++-- 5 files changed, 52 insertions(+), 38 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9f45d74ce3c2..b3b076a46d50 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2583,6 +2583,9 @@ struct wiphy_wowlan_support { * may request, if implemented. * * @wowlan: WoWLAN support information + * @wowlan_config: current WoWLAN configuration; this should usually not be + * used since access to it is necessarily racy, use the parameter passed + * to the suspend() operation instead. * * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. @@ -2650,6 +2653,7 @@ struct wiphy { #ifdef CONFIG_PM struct wiphy_wowlan_support wowlan; + struct cfg80211_wowlan *wowlan_config; #endif u16 max_remain_on_channel_duration; diff --git a/net/wireless/core.c b/net/wireless/core.c index ee422871fe9e..41cec1776f4f 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -663,8 +663,10 @@ void wiphy_unregister(struct wiphy *wiphy) flush_work(&rdev->event_work); cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); - if (rdev->wowlan && rdev->ops->set_wakeup) +#ifdef CONFIG_PM + if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) rdev_set_wakeup(rdev, false); +#endif cfg80211_rdev_free_wowlan(rdev); } EXPORT_SYMBOL(wiphy_unregister); diff --git a/net/wireless/core.h b/net/wireless/core.h index b4b4a566626b..a65eaf8a84c1 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -74,8 +74,6 @@ struct cfg80211_registered_device { struct work_struct conn_work; struct work_struct event_work; - struct cfg80211_wowlan *wowlan; - struct delayed_work dfs_update_channels_wk; /* netlink port which started critical protocol (0 means not started) */ @@ -96,17 +94,20 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) static inline void cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) { +#ifdef CONFIG_PM int i; - if (!rdev->wowlan) + if (!rdev->wiphy.wowlan_config) return; - for (i = 0; i < rdev->wowlan->n_patterns; i++) - kfree(rdev->wowlan->patterns[i].mask); - kfree(rdev->wowlan->patterns); - if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock) - sock_release(rdev->wowlan->tcp->sock); - kfree(rdev->wowlan->tcp); - kfree(rdev->wowlan); + for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++) + kfree(rdev->wiphy.wowlan_config->patterns[i].mask); + kfree(rdev->wiphy.wowlan_config->patterns); + if (rdev->wiphy.wowlan_config->tcp && + rdev->wiphy.wowlan_config->tcp->sock) + sock_release(rdev->wiphy.wowlan_config->tcp->sock); + kfree(rdev->wiphy.wowlan_config->tcp); + kfree(rdev->wiphy.wowlan_config); +#endif } extern struct workqueue_struct *cfg80211_wq; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a09f36bb957c..fb6abcb359a1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7489,28 +7489,29 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) static int nl80211_send_wowlan_patterns(struct sk_buff *msg, struct cfg80211_registered_device *rdev) { + struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config; struct nlattr *nl_pats, *nl_pat; int i, pat_len; - if (!rdev->wowlan->n_patterns) + if (!wowlan->n_patterns) return 0; nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN); if (!nl_pats) return -ENOBUFS; - for (i = 0; i < rdev->wowlan->n_patterns; i++) { + for (i = 0; i < wowlan->n_patterns; i++) { nl_pat = nla_nest_start(msg, i + 1); if (!nl_pat) return -ENOBUFS; - pat_len = rdev->wowlan->patterns[i].pattern_len; + pat_len = wowlan->patterns[i].pattern_len; if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8), - rdev->wowlan->patterns[i].mask) || + wowlan->patterns[i].mask) || nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, - pat_len, rdev->wowlan->patterns[i].pattern) || + pat_len, wowlan->patterns[i].pattern) || nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, - rdev->wowlan->patterns[i].pkt_offset)) + wowlan->patterns[i].pkt_offset)) return -ENOBUFS; nla_nest_end(msg, nl_pat); } @@ -7573,12 +7574,12 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) !rdev->wiphy.wowlan.tcp) return -EOPNOTSUPP; - if (rdev->wowlan && rdev->wowlan->tcp) { + if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) { /* adjust size to have room for all the data */ - size += rdev->wowlan->tcp->tokens_size + - rdev->wowlan->tcp->payload_len + - rdev->wowlan->tcp->wake_len + - rdev->wowlan->tcp->wake_len / 8; + size += rdev->wiphy.wowlan_config->tcp->tokens_size + + rdev->wiphy.wowlan_config->tcp->payload_len + + rdev->wiphy.wowlan_config->tcp->wake_len + + rdev->wiphy.wowlan_config->tcp->wake_len / 8; } msg = nlmsg_new(size, GFP_KERNEL); @@ -7590,33 +7591,34 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) if (!hdr) goto nla_put_failure; - if (rdev->wowlan) { + if (rdev->wiphy.wowlan_config) { struct nlattr *nl_wowlan; nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); if (!nl_wowlan) goto nla_put_failure; - if ((rdev->wowlan->any && + if ((rdev->wiphy.wowlan_config->any && nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || - (rdev->wowlan->disconnect && + (rdev->wiphy.wowlan_config->disconnect && nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || - (rdev->wowlan->magic_pkt && + (rdev->wiphy.wowlan_config->magic_pkt && nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || - (rdev->wowlan->gtk_rekey_failure && + (rdev->wiphy.wowlan_config->gtk_rekey_failure && nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || - (rdev->wowlan->eap_identity_req && + (rdev->wiphy.wowlan_config->eap_identity_req && nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || - (rdev->wowlan->four_way_handshake && + (rdev->wiphy.wowlan_config->four_way_handshake && nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || - (rdev->wowlan->rfkill_release && + (rdev->wiphy.wowlan_config->rfkill_release && nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) goto nla_put_failure; if (nl80211_send_wowlan_patterns(msg, rdev)) goto nla_put_failure; - if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp)) + if (nl80211_send_wowlan_tcp(msg, + rdev->wiphy.wowlan_config->tcp)) goto nla_put_failure; nla_nest_end(msg, nl_wowlan); @@ -7783,7 +7785,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) struct cfg80211_wowlan *ntrig; struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; int err, i; - bool prev_enabled = rdev->wowlan; + bool prev_enabled = rdev->wiphy.wowlan_config; if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && !rdev->wiphy.wowlan.tcp) @@ -7791,7 +7793,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { cfg80211_rdev_free_wowlan(rdev); - rdev->wowlan = NULL; + rdev->wiphy.wowlan_config = NULL; goto set_wakeup; } @@ -7927,11 +7929,12 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) goto error; } cfg80211_rdev_free_wowlan(rdev); - rdev->wowlan = ntrig; + rdev->wiphy.wowlan_config = ntrig; set_wakeup: - if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) - rdev_set_wakeup(rdev, rdev->wowlan); + if (rdev->ops->set_wakeup && + prev_enabled != !!rdev->wiphy.wowlan_config) + rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config); return 0; error: diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 8f28b9f798d8..360a42c6f694 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -91,6 +91,7 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) cfg80211_leave(rdev, wdev); } +#ifdef CONFIG_PM static int wiphy_suspend(struct device *dev, pm_message_t state) { struct cfg80211_registered_device *rdev = dev_to_rdev(dev); @@ -100,10 +101,10 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) rtnl_lock(); if (rdev->wiphy.registered) { - if (!rdev->wowlan) + if (!rdev->wiphy.wowlan_config) cfg80211_leave_all(rdev); if (rdev->ops->suspend) - ret = rdev_suspend(rdev, rdev->wowlan); + ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config); if (ret == 1) { /* Driver refuse to configure wowlan */ cfg80211_leave_all(rdev); @@ -132,6 +133,7 @@ static int wiphy_resume(struct device *dev) return ret; } +#endif static const void *wiphy_namespace(struct device *d) { @@ -146,8 +148,10 @@ struct class ieee80211_class = { .dev_release = wiphy_dev_release, .dev_attrs = ieee80211_dev_attrs, .dev_uevent = wiphy_uevent, +#ifdef CONFIG_PM .suspend = wiphy_suspend, .resume = wiphy_resume, +#endif .ns_type = &net_ns_type_operations, .namespace = wiphy_namespace, }; -- GitLab From aa3495f7922a51c893b0e4a376a225f02da74c76 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 6 May 2013 12:50:36 +0200 Subject: [PATCH 0418/2900] MAINTAINERS: Update PWM subsystem entry Change email to my private address and use the brand new linux-pwm instead of the generic linux-kernel mailing list. Signed-off-by: Thierry Reding --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 829c0321108b..3200369af150 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6458,8 +6458,8 @@ S: Maintained F: drivers/media/usb/pwc/* PWM SUBSYSTEM -M: Thierry Reding -L: linux-kernel@vger.kernel.org +M: Thierry Reding +L: linux-pwm@vger.kernel.org S: Maintained W: http://gitorious.org/linux-pwm T: git git://gitorious.org/linux-pwm/linux-pwm.git -- GitLab From e7927141ed51d94d6e1267f2ff0362a1f255e007 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 6 May 2013 15:05:54 -0300 Subject: [PATCH 0419/2900] pwm: mxs: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for handling pinctrl. So remove devm_pinctrl_get_select_default() from the driver. Cc: Thierry Reding Cc: Signed-off-by: Fabio Estevam Tested-by: Shawn Guo Signed-off-by: Thierry Reding --- drivers/pwm/pwm-mxs.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 3febdddf71f9..6489a4b75943 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -130,7 +129,6 @@ static int mxs_pwm_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct mxs_pwm_chip *mxs; struct resource *res; - struct pinctrl *pinctrl; int ret; mxs = devm_kzalloc(&pdev->dev, sizeof(*mxs), GFP_KERNEL); @@ -142,10 +140,6 @@ static int mxs_pwm_probe(struct platform_device *pdev) if (IS_ERR(mxs->base)) return PTR_ERR(mxs->base); - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - return PTR_ERR(pinctrl); - mxs->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(mxs->clk)) return PTR_ERR(mxs->clk); -- GitLab From 3db46c939677e32e311d354b619fd552ceafd123 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 14 May 2013 23:00:32 +0000 Subject: [PATCH 0420/2900] thermal: rcar: Fix typo in probe information message Signed-off-by: Laurent Pinchart Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/rcar_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 8d7edd4c8228..3eaca06df617 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -458,7 +458,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, common); - dev_info(dev, "%d sensor proved\n", i); + dev_info(dev, "%d sensor probed\n", i); return 0; -- GitLab From 42a5bf507d7f7ecbf606eb392dd9d2e4d009c36b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 17 May 2013 11:52:02 +0000 Subject: [PATCH 0421/2900] thermal: cut the spaces when user sets policy Setting policy results in invalid value error. % echo "step_wise" > policy % echo: write error: Invalid argument Need clean up of the buffer which "echo" may add based on the arguments, before comparing aganist list of governor names. Signed-off-by: Andy Shevchenko Reported-by: Srinivas Pandruvada Acked-by: Eduardo Valentin Tested-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d755440791b7..1067fb0107b9 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -713,10 +714,13 @@ policy_store(struct device *dev, struct device_attribute *attr, int ret = -EINVAL; struct thermal_zone_device *tz = to_thermal_zone(dev); struct thermal_governor *gov; + char name[THERMAL_NAME_LENGTH]; + + snprintf(name, sizeof(name), "%s", buf); mutex_lock(&thermal_governor_lock); - gov = __find_governor(buf); + gov = __find_governor(strim(name)); if (!gov) goto exit; -- GitLab From 83720d0b79618cd07c955ef1204c9cb0acb614a5 Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Sat, 18 May 2013 09:50:26 +0000 Subject: [PATCH 0422/2900] Thermal: core: Ask .get_trip_temp() to register thermal zone device. This patch adds a requirement needing .get_trip_temp() callback function for registering thermal zone device. This function is used when thermal zone is updated and essential where thermal core handles thermal trip based only polling way not hw interrupt. Signed-off-by: Jonghwa Lee Signed-off-by: MyungJoo Ham Acked-by: Durgadoss R Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 1067fb0107b9..e56ded5984b5 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1628,7 +1628,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, if (!ops || !ops->get_temp) return ERR_PTR(-EINVAL); - if (trips > 0 && !ops->get_trip_type) + if (trips > 0 && (!ops->get_trip_type || !ops->get_trip_temp)) return ERR_PTR(-EINVAL); tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); -- GitLab From c21bec86b6e36143a1fc0be60bbd9dfaebcb88a0 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 16 May 2013 02:16:21 +0000 Subject: [PATCH 0423/2900] Thermal: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. CC: Ezequiel Garcia CC: Vincenzo Frascino Signed-off-by: Zhang Rui Acked-by: Ezequiel Garcia --- drivers/thermal/armada_thermal.c | 10 ---------- drivers/thermal/spear_thermal.c | 13 +++---------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 5b4d75fd7b49..54ffd64ca3f7 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -169,21 +169,11 @@ static int armada_thermal_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - priv->sensor = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->sensor)) return PTR_ERR(priv->sensor); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, "Failed to get platform resource\n"); - return -ENODEV; - } - priv->control = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->control)) return PTR_ERR(priv->control); diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index b9e21611aece..0f37c7279c96 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -118,18 +118,11 @@ static int spear_thermal_probe(struct platform_device *pdev) return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "memory resource missing\n"); - return -ENODEV; - } - /* Enable thermal sensor */ - stdev->thermal_base = devm_ioremap_resource(dev, res); - if (IS_ERR(stdev->thermal_base)) { - dev_err(&pdev->dev, "ioremap failed\n"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + stdev->thermal_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(stdev->thermal_base)) return PTR_ERR(stdev->thermal_base); - } stdev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(stdev->clk)) { -- GitLab From eb982001dbd8546f273f444868a1031cc78b4250 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 15 May 2013 15:46:00 +0000 Subject: [PATCH 0424/2900] thermal: introduce TI SoC thermal driver This patch moves the ti-soc-thermal driver out of the staging tree to the thermal tree. Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: Greg Kroah-Hartman Cc: Zhang Rui Cc: Eduardo Valentin Cc: J Keerthy Cc: Radhesh Fadnis Cc: Cyril Roelandt Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: devel@driverdev.osuosl.org Cc: linux-pm@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- .../devicetree/bindings/thermal}/ti_soc_thermal.txt | 0 drivers/staging/Kconfig | 2 -- drivers/staging/Makefile | 1 - drivers/thermal/Kconfig | 3 +++ drivers/thermal/Makefile | 2 +- drivers/{staging => thermal}/ti-soc-thermal/Kconfig | 0 drivers/{staging => thermal}/ti-soc-thermal/Makefile | 0 drivers/{staging => thermal}/ti-soc-thermal/TODO | 0 .../{staging => thermal}/ti-soc-thermal/omap4-thermal-data.c | 0 drivers/{staging => thermal}/ti-soc-thermal/omap4xxx-bandgap.h | 0 .../{staging => thermal}/ti-soc-thermal/omap5-thermal-data.c | 0 drivers/{staging => thermal}/ti-soc-thermal/omap5xxx-bandgap.h | 0 drivers/{staging => thermal}/ti-soc-thermal/ti-bandgap.c | 0 drivers/{staging => thermal}/ti-soc-thermal/ti-bandgap.h | 0 .../{staging => thermal}/ti-soc-thermal/ti-thermal-common.c | 0 drivers/{staging => thermal}/ti-soc-thermal/ti-thermal.h | 0 16 files changed, 4 insertions(+), 4 deletions(-) rename {drivers/staging/ti-soc-thermal => Documentation/devicetree/bindings/thermal}/ti_soc_thermal.txt (100%) rename drivers/{staging => thermal}/ti-soc-thermal/Kconfig (100%) rename drivers/{staging => thermal}/ti-soc-thermal/Makefile (100%) rename drivers/{staging => thermal}/ti-soc-thermal/TODO (100%) rename drivers/{staging => thermal}/ti-soc-thermal/omap4-thermal-data.c (100%) rename drivers/{staging => thermal}/ti-soc-thermal/omap4xxx-bandgap.h (100%) rename drivers/{staging => thermal}/ti-soc-thermal/omap5-thermal-data.c (100%) rename drivers/{staging => thermal}/ti-soc-thermal/omap5xxx-bandgap.h (100%) rename drivers/{staging => thermal}/ti-soc-thermal/ti-bandgap.c (100%) rename drivers/{staging => thermal}/ti-soc-thermal/ti-bandgap.h (100%) rename drivers/{staging => thermal}/ti-soc-thermal/ti-thermal-common.c (100%) rename drivers/{staging => thermal}/ti-soc-thermal/ti-thermal.h (100%) diff --git a/drivers/staging/ti-soc-thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt similarity index 100% rename from drivers/staging/ti-soc-thermal/ti_soc_thermal.txt rename to Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4e8a1794f50a..79701de74855 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -118,8 +118,6 @@ source "drivers/staging/gdm72xx/Kconfig" source "drivers/staging/csr/Kconfig" -source "drivers/staging/ti-soc-thermal/Kconfig" - source "drivers/staging/silicom/Kconfig" source "drivers/staging/ced1401/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 415772ea306d..f8b740c4ea7e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ obj-$(CONFIG_CSR_WIFI) += csr/ -obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ obj-$(CONFIG_CED1401) += ced1401/ obj-$(CONFIG_DRM_IMX) += imx-drm/ diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 5e3c02554d99..7205c70a46a3 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -169,4 +169,7 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. +menu "Texas Instruments thermal drivers" +source "drivers/thermal/ti-soc-thermal/Kconfig" +endmenu endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index c054d410ac3f..85693941fda0 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -23,4 +23,4 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o - +obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ diff --git a/drivers/staging/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig similarity index 100% rename from drivers/staging/ti-soc-thermal/Kconfig rename to drivers/thermal/ti-soc-thermal/Kconfig diff --git a/drivers/staging/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile similarity index 100% rename from drivers/staging/ti-soc-thermal/Makefile rename to drivers/thermal/ti-soc-thermal/Makefile diff --git a/drivers/staging/ti-soc-thermal/TODO b/drivers/thermal/ti-soc-thermal/TODO similarity index 100% rename from drivers/staging/ti-soc-thermal/TODO rename to drivers/thermal/ti-soc-thermal/TODO diff --git a/drivers/staging/ti-soc-thermal/omap4-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap4-thermal-data.c similarity index 100% rename from drivers/staging/ti-soc-thermal/omap4-thermal-data.c rename to drivers/thermal/ti-soc-thermal/omap4-thermal-data.c diff --git a/drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h similarity index 100% rename from drivers/staging/ti-soc-thermal/omap4xxx-bandgap.h rename to drivers/thermal/ti-soc-thermal/omap4xxx-bandgap.h diff --git a/drivers/staging/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c similarity index 100% rename from drivers/staging/ti-soc-thermal/omap5-thermal-data.c rename to drivers/thermal/ti-soc-thermal/omap5-thermal-data.c diff --git a/drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h b/drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h similarity index 100% rename from drivers/staging/ti-soc-thermal/omap5xxx-bandgap.h rename to drivers/thermal/ti-soc-thermal/omap5xxx-bandgap.h diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c similarity index 100% rename from drivers/staging/ti-soc-thermal/ti-bandgap.c rename to drivers/thermal/ti-soc-thermal/ti-bandgap.c diff --git a/drivers/staging/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h similarity index 100% rename from drivers/staging/ti-soc-thermal/ti-bandgap.h rename to drivers/thermal/ti-soc-thermal/ti-bandgap.h diff --git a/drivers/staging/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c similarity index 100% rename from drivers/staging/ti-soc-thermal/ti-thermal-common.c rename to drivers/thermal/ti-soc-thermal/ti-thermal-common.c diff --git a/drivers/staging/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h similarity index 100% rename from drivers/staging/ti-soc-thermal/ti-thermal.h rename to drivers/thermal/ti-soc-thermal/ti-thermal.h -- GitLab From 794b2e2548ec41d81c5272f883011a13612f2fda Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 15 May 2013 15:46:01 +0000 Subject: [PATCH 0425/2900] MAINTAINERS: update TI SoC thermal driver entry Update driver path and status for TI SoC thermal drivers on MAINTAINERS file. Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3d7782b9f90d..311fb4512826 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8056,8 +8056,8 @@ F: drivers/platform/x86/thinkpad_acpi.c TI BANDGAP AND THERMAL DRIVER M: Eduardo Valentin L: linux-pm@vger.kernel.org -S: Maintained -F: drivers/staging/omap-thermal/ +S: Supported +F: drivers/thermal/ti-soc-thermal/ TI FLASH MEDIA INTERFACE DRIVER M: Alex Dubov -- GitLab From 1d089e09936420611781e2ad09519f9521381fb0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 10:28:08 +0000 Subject: [PATCH 0426/2900] Thermal: armada: Remove redundant use of of_match_ptr 'armada_thermal_id_table' is always compiled in and the driver is dependent on OF. Hence use of of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Cc: Ezequiel Garcia Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/armada_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 5b4d75fd7b49..7c603b854e87 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -221,7 +221,7 @@ static struct platform_driver armada_thermal_driver = { .driver = { .name = "armada_thermal", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(armada_thermal_id_table), + .of_match_table = armada_thermal_id_table, }, }; -- GitLab From e0d68afa92df693928f8e28eb7ae03bd68c50d3b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 10:28:09 +0000 Subject: [PATCH 0427/2900] Thermal: dove: Remove redundant use of of_match_ptr 'dove_thermal_id_table' is always compiled in and the driver is dependent on OF. Hence use of of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Cc: Andrew Lunn Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/dove_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 4b15a5f270dc..d5c029f9344d 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -195,7 +195,7 @@ static struct platform_driver dove_thermal_driver = { .driver = { .name = "dove_thermal", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(dove_thermal_id_table), + .of_match_table = dove_thermal_id_table, }, }; -- GitLab From 90c3194e474fe00240a441a7321b1fe37d3441aa Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 10:28:10 +0000 Subject: [PATCH 0428/2900] Thermal: kirkwood: Remove redundant use of of_match_ptr 'kirkwood_thermal_id_table' is always compiled in and the driver is dependent on OF. Hence use of of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Cc: Nobuhiro Iwamatsu Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/kirkwood_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index dfeceaffbc03..61bbc2605b02 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -121,7 +121,7 @@ static struct platform_driver kirkwood_thermal_driver = { .driver = { .name = "kirkwood_thermal", .owner = THIS_MODULE, - .of_match_table = of_match_ptr(kirkwood_thermal_id_table), + .of_match_table = kirkwood_thermal_id_table, }, }; -- GitLab From 5454f211ddc2a8ebc1eb20aa3866c4e9cf11405f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 16 May 2013 10:28:11 +0000 Subject: [PATCH 0429/2900] Thermal: spear: Remove redundant use of of_match_ptr 'spear_thermal_id_table' is always compiled in and the driver is dependent on OF. Hence use of of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Cc: Vincenzo Frascino Cc: Viresh Kumar Acked-by: Viresh Kumar Acked-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/spear_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index 3c5ee5607977..838aff29b9d8 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -198,7 +198,7 @@ static struct platform_driver spear_thermal_driver = { .name = "spear_thermal", .owner = THIS_MODULE, .pm = &spear_thermal_pm_ops, - .of_match_table = of_match_ptr(spear_thermal_id_table), + .of_match_table = spear_thermal_id_table, }, }; -- GitLab From e09b74d0195496fdc2dbe106eaa55da48873876e Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Mon, 27 May 2013 04:08:26 +0000 Subject: [PATCH 0430/2900] bnx2x: Zero VFs starting MACs Hypervisor/Supervisor should set the VF's MAC prior to its load; Using a randomly generated MAC as a default is a bad practice. Signed-off-by: Ariel Elior Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 7ed9cdfa115e..80982c38ae69 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11406,7 +11406,7 @@ static int bnx2x_init_bp(struct bnx2x *bp) if (rc) return rc; } else { - random_ether_addr(bp->dev->dev_addr); + eth_zero_addr(bp->dev->dev_addr); } bnx2x_set_modes_bitmap(bp); @@ -11865,6 +11865,10 @@ static int bnx2x_validate_addr(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); + /* query the bulletin board for mac address configured by the PF */ + if (IS_VF(bp)) + bnx2x_sample_bulletin(bp); + if (!bnx2x_is_valid_ether_addr(bp, dev->dev_addr)) { BNX2X_ERR("Non-valid Ethernet address\n"); return -EADDRNOTAVAIL; -- GitLab From ca1ee4b259ea8c4f91c84ee4c737338658711272 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Mon, 27 May 2013 04:08:27 +0000 Subject: [PATCH 0431/2900] bnx2x: Add and correct PCI link speed prints This adds the print of the PCI gen3 link speed (8GHz), as well as correcting the same print for 57712 boards (the print erroneously showed a 2.5GHz speed). Signed-off-by: Dmitry Kravkov Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 5 +++ .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 40 ++++++++++++------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 946450d6d988..47b06fc22b97 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2342,4 +2342,9 @@ enum { #define NUM_MACS 8 +enum bnx2x_pci_bus_speed { + BNX2X_PCI_LINK_SPEED_2500 = 2500, + BNX2X_PCI_LINK_SPEED_5000 = 5000, + BNX2X_PCI_LINK_SPEED_8000 = 8000 +}; #endif /* bnx2x.h */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 80982c38ae69..04fa5105ca52 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12111,15 +12111,26 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, return rc; } -static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed) +static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, + enum bnx2x_pci_bus_speed *speed) { - u32 val = 0; + u32 link_speed, val = 0; pci_read_config_dword(bp->pdev, PCICFG_LINK_CONTROL, &val); *width = (val & PCICFG_LINK_WIDTH) >> PCICFG_LINK_WIDTH_SHIFT; - /* return value of 1=2.5GHz 2=5GHz */ - *speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; + link_speed = (val & PCICFG_LINK_SPEED) >> PCICFG_LINK_SPEED_SHIFT; + + switch (link_speed) { + case 3: + *speed = BNX2X_PCI_LINK_SPEED_8000; + break; + case 2: + *speed = BNX2X_PCI_LINK_SPEED_5000; + break; + default: + *speed = BNX2X_PCI_LINK_SPEED_2500; + } } static int bnx2x_check_firmware(struct bnx2x *bp) @@ -12482,7 +12493,8 @@ static int bnx2x_init_one(struct pci_dev *pdev, { struct net_device *dev = NULL; struct bnx2x *bp; - int pcie_width, pcie_speed; + int pcie_width; + enum bnx2x_pci_bus_speed pcie_speed; int rc, max_non_def_sbs; int rx_count, tx_count, rss_count, doorbell_size; int max_cos_est; @@ -12634,15 +12646,15 @@ static int bnx2x_init_one(struct pci_dev *pdev, BNX2X_DEV_INFO("got pcie width %d and speed %d\n", pcie_width, pcie_speed); - BNX2X_DEV_INFO( - "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n", - board_info[ent->driver_data].name, - (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4), - pcie_width, - ((!CHIP_IS_E2(bp) && pcie_speed == 2) || - (CHIP_IS_E2(bp) && pcie_speed == 1)) ? - "5GHz (Gen2)" : "2.5GHz", - dev->base_addr, bp->pdev->irq, dev->dev_addr); + BNX2X_DEV_INFO("%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n", + board_info[ent->driver_data].name, + (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4), + pcie_width, + pcie_speed == BNX2X_PCI_LINK_SPEED_2500 ? "2.5GHz" : + pcie_speed == BNX2X_PCI_LINK_SPEED_5000 ? "5.0GHz" : + pcie_speed == BNX2X_PCI_LINK_SPEED_8000 ? "8.0GHz" : + "Unknown", + dev->base_addr, bp->pdev->irq, dev->dev_addr); return 0; -- GitLab From 70ca5d746cf0c16576cee43fea6a19116ab49d9c Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Mon, 27 May 2013 04:08:28 +0000 Subject: [PATCH 0432/2900] bnx2x: Ack unknown VF messages A PF should ack the firmware when receiving unknown messages through the VF's mailbox. This prevents the VF mailbox from being stuck in case of a VF sending a message unknown to the PF (e.g. VF with more advanced version). Signed-off-by: Ariel Elior Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 928b074d7d80..282606677bca 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -1605,8 +1605,11 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, bnx2x_vf_mbx_resp(bp, vf); } else { /* can't send a response since this VF is unknown to us - * just unlock the channel and be done with. + * just ack the FW to release the mailbox and unlock + * the channel. */ + storm_memset_vf_mbx_ack(bp, vf->abs_vfid); + mmiowb(); bnx2x_unlock_vf_pf_channel(bp, vf, mbx->first_tlv.tl.type); } -- GitLab From 868001946e39627ec439921eeb0f5fa020e1e31d Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Mon, 27 May 2013 04:08:29 +0000 Subject: [PATCH 0433/2900] bnx2x: Count number of possible FCoE interfaces Commit 0eb43b4bb081a1a22574daab9c05286a600dd7fe "bnx2x, bnx2fc: Use per port max exchange resources" has changed the number of available FCoE exchanges, even in scenarios when some of the functions has no FCoE support; This needlessly degraded the available resources. Remedy this by calculating the maximal number of functions that may actually utilize said connection. Signed-off-by: Dmitry Kravkov CC: Bhanu Prakash Gollapudi Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 04fa5105ca52..0a3bb53f3eee 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10795,12 +10795,56 @@ static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func) bp->cnic_eth_dev.fcoe_wwn_node_name_lo = MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower); } + +static int bnx2x_shared_fcoe_funcs(struct bnx2x *bp) +{ + u8 count = 0; + + if (IS_MF(bp)) { + u8 fid; + + /* iterate over absolute function ids for this path: */ + for (fid = BP_PATH(bp); fid < E2_FUNC_MAX * 2; fid += 2) { + if (IS_MF_SD(bp)) { + u32 cfg = MF_CFG_RD(bp, + func_mf_config[fid].config); + + if (!(cfg & FUNC_MF_CFG_FUNC_HIDE) && + ((cfg & FUNC_MF_CFG_PROTOCOL_MASK) == + FUNC_MF_CFG_PROTOCOL_FCOE)) + count++; + } else { + u32 cfg = MF_CFG_RD(bp, + func_ext_config[fid]. + func_cfg); + + if ((cfg & MACP_FUNC_CFG_FLAGS_ENABLED) && + (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)) + count++; + } + } + } else { /* SF */ + int port, port_cnt = CHIP_MODE_IS_4_PORT(bp) ? 2 : 1; + + for (port = 0; port < port_cnt; port++) { + u32 lic = SHMEM_RD(bp, + drv_lic_key[port].max_fcoe_conn) ^ + FW_ENCODE_32BIT_PATTERN; + if (lic) + count++; + } + } + + return count; +} + static void bnx2x_get_fcoe_info(struct bnx2x *bp) { int port = BP_PORT(bp); int func = BP_ABS_FUNC(bp); u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp, drv_lic_key[port].max_fcoe_conn); + u8 num_fcoe_func = bnx2x_shared_fcoe_funcs(bp); if (!CNIC_SUPPORT(bp)) { bp->flags |= NO_FCOE_FLAG; @@ -10814,9 +10858,10 @@ static void bnx2x_get_fcoe_info(struct bnx2x *bp) /* Calculate the number of maximum allowed FCoE tasks */ bp->cnic_eth_dev.max_fcoe_exchanges = MAX_NUM_FCOE_TASKS_PER_ENGINE; - if (IS_MF(bp) || CHIP_MODE_IS_4_PORT(bp)) - bp->cnic_eth_dev.max_fcoe_exchanges /= - MAX_FCOE_FUNCS_PER_ENGINE; + + /* check if FCoE resources must be shared between different functions */ + if (num_fcoe_func) + bp->cnic_eth_dev.max_fcoe_exchanges /= num_fcoe_func; /* Read the WWN: */ if (!IS_MF(bp)) { -- GitLab From b030ed2fdc8a396dba71e4d550236a0f1bb38b40 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 27 May 2013 04:08:30 +0000 Subject: [PATCH 0434/2900] bnx2x: Implement PCI shutdown Implement the PCI shutdown callback to support un-orderly shutdown, i.e., shutdowns in which the remove callback will not be called. Due to the lack of this functionality, when an un-orderly shutdown occurred, it was possible for wake-on-lan to remain disabled. This is now fixed as the callback introduces the correct place in which `system_state' can be queried and wake-on-lan be configured accordingly. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 71 +++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 0a3bb53f3eee..13f814485a36 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12721,17 +12721,11 @@ static int bnx2x_init_one(struct pci_dev *pdev, return rc; } -static void bnx2x_remove_one(struct pci_dev *pdev) +static void __bnx2x_remove(struct pci_dev *pdev, + struct net_device *dev, + struct bnx2x *bp, + bool remove_netdev) { - struct net_device *dev = pci_get_drvdata(pdev); - struct bnx2x *bp; - - if (!dev) { - dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); - return; - } - bp = netdev_priv(dev); - /* Delete storage MAC address */ if (!NO_FCOE(bp)) { rtnl_lock(); @@ -12744,7 +12738,15 @@ static void bnx2x_remove_one(struct pci_dev *pdev) bnx2x_dcbnl_update_applist(bp, true); #endif - unregister_netdev(dev); + /* Close the interface - either directly or implicitly */ + if (remove_netdev) { + unregister_netdev(dev); + } else { + rtnl_lock(); + if (netif_running(dev)) + bnx2x_close(dev); + rtnl_unlock(); + } /* Power on: we can't let PCI layer write to us while we are in D3 */ if (IS_PF(bp)) @@ -12766,6 +12768,12 @@ static void bnx2x_remove_one(struct pci_dev *pdev) if (IS_VF(bp)) bnx2x_vfpf_release(bp); + /* Assumes no further PCIe PM changes will occur */ + if (system_state == SYSTEM_POWER_OFF) { + pci_wake_from_d3(pdev, bp->wol); + pci_set_power_state(pdev, PCI_D3hot); + } + if (bp->regview) iounmap(bp->regview); @@ -12780,7 +12788,8 @@ static void bnx2x_remove_one(struct pci_dev *pdev) } bnx2x_free_mem_bp(bp); - free_netdev(dev); + if (remove_netdev) + free_netdev(dev); if (atomic_read(&pdev->enable_cnt) == 1) pci_release_regions(pdev); @@ -12789,6 +12798,20 @@ static void bnx2x_remove_one(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } +static void bnx2x_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2x *bp; + + if (!dev) { + dev_err(&pdev->dev, "BAD net device from bnx2x_init_one\n"); + return; + } + bp = netdev_priv(dev); + + __bnx2x_remove(pdev, dev, bp, true); +} + static int bnx2x_eeh_nic_unload(struct bnx2x *bp) { bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; @@ -12968,6 +12991,29 @@ static const struct pci_error_handlers bnx2x_err_handler = { .resume = bnx2x_io_resume, }; +static void bnx2x_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnx2x *bp; + + if (!dev) + return; + + bp = netdev_priv(dev); + if (!bp) + return; + + rtnl_lock(); + netif_device_detach(dev); + rtnl_unlock(); + + /* Don't remove the netdevice, as there are scenarios which will cause + * the kernel to hang, e.g., when trying to remove bnx2i while the + * rootfs is mounted from SAN. + */ + __bnx2x_remove(pdev, dev, bp, false); +} + static struct pci_driver bnx2x_pci_driver = { .name = DRV_MODULE_NAME, .id_table = bnx2x_pci_tbl, @@ -12979,6 +13025,7 @@ static struct pci_driver bnx2x_pci_driver = { #ifdef CONFIG_BNX2X_SRIOV .sriov_configure = bnx2x_sriov_configure, #endif + .shutdown = bnx2x_shutdown, }; static int __init bnx2x_init(void) -- GitLab From 3fb43eb20aec3f5ceed5813a035f200dafb51257 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 27 May 2013 04:08:31 +0000 Subject: [PATCH 0435/2900] bnx2x: Change to D3hot only on removal This changes the PCI power management scheme of the bnx2x driver to be similar to those of most network drivers - the driver will now changes the power state into D3hot whenever the driver will be removed, instead of whenever an interface is unloaded. This change enables the driver to access its eeprom via ethtool callbacks even when interfaces are unloaded (such access requires the function to be in D0active). Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 31 ++++++++++++++----- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 3 -- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 32aa88f520dc..263950cddfe2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1381,12 +1381,28 @@ static int bnx2x_nvram_read32(struct bnx2x *bp, u32 offset, u32 *buf, return rc; } +static bool bnx2x_is_nvm_accessible(struct bnx2x *bp) +{ + int rc = 1; + u16 pm = 0; + struct net_device *dev = pci_get_drvdata(bp->pdev); + + if (bp->pm_cap) + rc = pci_read_config_word(bp->pdev, + bp->pm_cap + PCI_PM_CTRL, &pm); + + if ((rc && !netif_running(dev)) || (!rc && ((pm & PCI_D0) != PCI_D0))) + return false; + + return true; +} + static int bnx2x_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *eebuf) { struct bnx2x *bp = netdev_priv(dev); - if (!netif_running(dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return -EAGAIN; @@ -1411,7 +1427,7 @@ static int bnx2x_get_module_eeprom(struct net_device *dev, u8 *user_data = data; unsigned int start_addr = ee->offset, xfer_size = 0; - if (!netif_running(dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return -EAGAIN; @@ -1474,7 +1490,7 @@ static int bnx2x_get_module_info(struct net_device *dev, int phy_idx, rc; u8 sff8472_comp, diag_type; - if (!netif_running(dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return -EAGAIN; @@ -1676,7 +1692,8 @@ static int bnx2x_set_eeprom(struct net_device *dev, int port = BP_PORT(bp); int rc = 0; u32 ext_phy_config; - if (!netif_running(dev)) { + + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return -EAGAIN; @@ -2173,7 +2190,7 @@ static int bnx2x_test_registers(struct bnx2x *bp) { BNX2X_CHIP_MASK_ALL, 0xffffffff, 0, 0x00000000 } }; - if (!netif_running(bp->dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return rc; @@ -2277,7 +2294,7 @@ static int bnx2x_test_memory(struct bnx2x *bp) { NULL, 0xffffffff, {0, 0, 0, 0} } }; - if (!netif_running(bp->dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return rc; @@ -3140,7 +3157,7 @@ static int bnx2x_set_phys_id(struct net_device *dev, { struct bnx2x *bp = netdev_priv(dev); - if (!netif_running(dev)) { + if (!bnx2x_is_nvm_accessible(bp)) { DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM, "cannot access eeprom when the interface is down\n"); return -EAGAIN; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 13f814485a36..f6d0e209c44e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11643,9 +11643,6 @@ static int bnx2x_close(struct net_device *dev) /* Unload the driver, release IRQs */ bnx2x_nic_unload(bp, UNLOAD_CLOSE, false); - /* Power off */ - bnx2x_set_power_state(bp, PCI_D3hot); - return 0; } -- GitLab From eeb65cedd78ebd375608d71d703e6b0b9296efbd Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Sun, 26 May 2013 21:08:36 +0000 Subject: [PATCH 0436/2900] be2net: cleanup be_get_drvinfo() Removing the be_cmd_get_fw_ver() query from be_get_drvinfo() and invoking the same from be_setup() and/or post firmware download. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 1 + drivers/net/ethernet/emulex/benet/be_ethtool.c | 8 ++------ drivers/net/ethernet/emulex/benet/be_main.c | 6 +++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index f544b297c9ab..edce38bf83c9 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -397,6 +397,7 @@ struct be_adapter { u32 cmd_privileges; /* Ethtool knobs and info */ char fw_ver[FW_VER_LEN]; + char fw_on_flash[FW_VER_LEN]; int if_handle; /* Used to configure filtering */ u32 *pmac_id; /* MAC addr handle used by BE card */ u32 beacon_state; /* for set_phys_id */ diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 3d4461adb3b4..f3ee07758198 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -177,19 +177,15 @@ static void be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct be_adapter *adapter = netdev_priv(netdev); - char fw_on_flash[FW_VER_LEN]; - - memset(fw_on_flash, 0 , sizeof(fw_on_flash)); - be_cmd_get_fw_ver(adapter, adapter->fw_ver, fw_on_flash); strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, DRV_VER, sizeof(drvinfo->version)); - if (!memcmp(adapter->fw_ver, fw_on_flash, FW_VER_LEN)) + if (!memcmp(adapter->fw_ver, adapter->fw_on_flash, FW_VER_LEN)) strlcpy(drvinfo->fw_version, adapter->fw_ver, sizeof(drvinfo->fw_version)); else snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), - "%s [%s]", adapter->fw_ver, fw_on_flash); + "%s [%s]", adapter->fw_ver, adapter->fw_on_flash); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3d5e1a8929ae..d1580823c286 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3193,7 +3193,7 @@ static int be_setup(struct be_adapter *adapter) if (status) goto err; - be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL); + be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash); if (adapter->vlans_added) be_vid_config(adapter); @@ -3785,6 +3785,10 @@ int be_load_fw(struct be_adapter *adapter, u8 *fw_file) else status = be_fw_download(adapter, fw); + if (!status) + be_cmd_get_fw_ver(adapter, adapter->fw_ver, + adapter->fw_on_flash); + fw_exit: release_firmware(fw); return status; -- GitLab From 48265667a756ab1c2750048caee3da719a86ebb2 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Sun, 26 May 2013 21:08:47 +0000 Subject: [PATCH 0437/2900] be2net: Pad skb to meet min Tx pkt size in lancer In Lancer, packets that are 32 bytes or less may cause a transmit stall. The work-around is to pad such packets to a 36 byte length. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d1580823c286..26e222f81433 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -848,6 +848,16 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, unsigned int eth_hdr_len; struct iphdr *ip; + /* Lancer ASIC has a bug wherein packets that are 32 bytes or less + * may cause a transmit stall on that port. So the work-around is to + * pad such packets to a 36-byte length. + */ + if (unlikely(lancer_chip(adapter) && skb->len <= 32)) { + if (skb_padto(skb, 36)) + goto tx_drop; + skb->len = 36; + } + /* For padded packets, BE HW modifies tot_len field in IP header * incorrecly when VLAN tag is inserted by HW. */ -- GitLab From 3904dcc4a7af8e28e45a8d123cef3f7653847a51 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Sun, 26 May 2013 21:09:06 +0000 Subject: [PATCH 0438/2900] be2net: Trim padded packets for Lancer For padded packets, Lancer computes incorrect checksum. The workaround is to trim such packets. This workaround is mainly for IPv4 packets. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 26e222f81433..1140a86ff5ea 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -860,10 +860,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, /* For padded packets, BE HW modifies tot_len field in IP header * incorrecly when VLAN tag is inserted by HW. + * For padded packets, Lancer computes incorrect checksum. */ eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? VLAN_ETH_HLEN : ETH_HLEN; - if (skb->len <= 60 && vlan_tx_tag_present(skb) && + if (skb->len <= 60 && + (lancer_chip(adapter) || vlan_tx_tag_present(skb)) && is_ipv4_pkt(skb)) { ip = (struct iphdr *)ip_hdr(skb); pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); -- GitLab From f4e9f3d2fdb141d920c9fd7bd5ea7db348f6d3be Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 27 May 2013 03:48:29 +0000 Subject: [PATCH 0439/2900] fec: Place the phy regulator in the private structure Instead of using a local reg_phy structure, let's put it inside the private structure, so that we are able to have access to the regulator structure even when we are outside fec_probe(). This is in preparation for controlling the FEC PHY regulator in the suspend and resume functions. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/freescale/fec_main.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 9ce5b7185fda..b11cdbcc04ff 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -272,6 +272,7 @@ struct fec_enet_private { int hwts_tx_en; struct timer_list time_keep; struct fec_enet_delayed_work delay_work; + struct regulator *reg_phy; }; void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 0936b26b5e1e..57ac7c3453d6 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1840,7 +1840,6 @@ fec_probe(struct platform_device *pdev) struct resource *r; const struct of_device_id *of_id; static int dev_id; - struct regulator *reg_phy; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) @@ -1919,9 +1918,9 @@ fec_probe(struct platform_device *pdev) clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ptp); - reg_phy = devm_regulator_get(&pdev->dev, "phy"); - if (!IS_ERR(reg_phy)) { - ret = regulator_enable(reg_phy); + fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); + if (!IS_ERR(fep->reg_phy)) { + ret = regulator_enable(fep->reg_phy); if (ret) { dev_err(&pdev->dev, "Failed to enable phy regulator: %d\n", ret); -- GitLab From 7a2bbd8d8e36c4fae7610bb1be96c2ba5ff7553a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 27 May 2013 03:48:30 +0000 Subject: [PATCH 0440/2900] fec: Invert the order of error path sequence Currently when fec_enet_init fails it jumps to 'failed_init' error path, which will attemp to free the interrupts. This is wrong because at this point the interrupts have not even been acquired. Swap failed_init/failed_irq to fix the error path. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 57ac7c3453d6..dc7388ed40e7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1975,13 +1975,13 @@ fec_probe(struct platform_device *pdev) failed_register: fec_enet_mii_remove(fep); failed_mii_init: -failed_init: +failed_irq: for (i = 0; i < FEC_IRQ_NUM; i++) { irq = platform_get_irq(pdev, i); if (irq > 0) free_irq(irq, ndev); } -failed_irq: +failed_init: failed_regulator: clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); -- GitLab From f6a4d607b3fdfaf305f3e78837cb8969d62c249a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 27 May 2013 03:48:31 +0000 Subject: [PATCH 0441/2900] fec: Disable the PHY regulator on error and removal In the case of error during probe, disable the PHY regulator. Do the same in fec_drv_remove(). Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index dc7388ed40e7..58ac0c76441f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1926,6 +1926,8 @@ fec_probe(struct platform_device *pdev) "Failed to enable phy regulator: %d\n", ret); goto failed_regulator; } + } else { + fep->reg_phy = NULL; } fec_reset_phy(pdev); @@ -1982,6 +1984,8 @@ fec_probe(struct platform_device *pdev) free_irq(irq, ndev); } failed_init: + if (fep->reg_phy) + regulator_disable(fep->reg_phy); failed_regulator: clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); @@ -2005,6 +2009,8 @@ fec_drv_remove(struct platform_device *pdev) unregister_netdev(ndev); fec_enet_mii_remove(fep); del_timer_sync(&fep->time_keep); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); clk_disable_unprepare(fep->clk_ptp); if (fep->ptp_clock) ptp_clock_unregister(fep->ptp_clock); -- GitLab From c55284e4ddf3779f52d730bedfa264d35d42e539 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 27 May 2013 03:48:32 +0000 Subject: [PATCH 0442/2900] fec: Remove irqs first During probe the clocks are enabled prior than the acquiring the interrupts. In the remove function we need to do the opposite: first remove the interrupts and then disable the clocks. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 58ac0c76441f..cac667db61be 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2009,6 +2009,11 @@ fec_drv_remove(struct platform_device *pdev) unregister_netdev(ndev); fec_enet_mii_remove(fep); del_timer_sync(&fep->time_keep); + for (i = 0; i < FEC_IRQ_NUM; i++) { + int irq = platform_get_irq(pdev, i); + if (irq > 0) + free_irq(irq, ndev); + } if (fep->reg_phy) regulator_disable(fep->reg_phy); clk_disable_unprepare(fep->clk_ptp); @@ -2017,11 +2022,6 @@ fec_drv_remove(struct platform_device *pdev) clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); - for (i = 0; i < FEC_IRQ_NUM; i++) { - int irq = platform_get_irq(pdev, i); - if (irq > 0) - free_irq(irq, ndev); - } free_netdev(ndev); platform_set_drvdata(pdev, NULL); -- GitLab From 238f7bc74cde96e285e59a84e0c7bbd37faa8c07 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 27 May 2013 03:48:33 +0000 Subject: [PATCH 0443/2900] fec: Handle the regulator in suspend/resume In order to save power, let's disable the regulator in the suspend function and enable it in resume. Tested on a mx28evk board. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index cac667db61be..866b92220c15 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2044,6 +2044,9 @@ fec_suspend(struct device *dev) clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); + return 0; } @@ -2052,6 +2055,13 @@ fec_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); struct fec_enet_private *fep = netdev_priv(ndev); + int ret; + + if (fep->reg_phy) { + ret = regulator_enable(fep->reg_phy); + if (ret) + return ret; + } clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ahb); -- GitLab From dfd93c977d84fef77404b689ef95bc716b313533 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 27 May 2013 19:01:12 +0000 Subject: [PATCH 0444/2900] net: ethernet: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Nicolas Ferre Acked-by: Rob Herring Acked-by: Roland Stigge Acked-by: Mugunthan V N Reviewed-by: H Hartley Sweeten Tested-by: Roland Stigge Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/ne.c | 1 - drivers/net/ethernet/adi/bfin_mac.c | 4 ---- drivers/net/ethernet/amd/au1000_eth.c | 2 -- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 1 - drivers/net/ethernet/cadence/at91_ether.c | 1 - drivers/net/ethernet/cadence/macb.c | 2 -- drivers/net/ethernet/calxeda/xgmac.c | 2 -- drivers/net/ethernet/cirrus/ep93xx_eth.c | 1 - drivers/net/ethernet/davicom/dm9000.c | 2 -- drivers/net/ethernet/ethoc.c | 2 -- drivers/net/ethernet/faraday/ftgmac100.c | 2 -- drivers/net/ethernet/faraday/ftmac100.c | 2 -- drivers/net/ethernet/freescale/fec_main.c | 2 -- drivers/net/ethernet/korina.c | 1 - drivers/net/ethernet/marvell/mv643xx_eth.c | 2 -- drivers/net/ethernet/marvell/mvneta.c | 2 -- drivers/net/ethernet/marvell/pxa168_eth.c | 1 - drivers/net/ethernet/micrel/ks8695net.c | 1 - drivers/net/ethernet/micrel/ks8842.c | 1 - drivers/net/ethernet/micrel/ks8851_mll.c | 1 - drivers/net/ethernet/netx-eth.c | 1 - drivers/net/ethernet/nuvoton/w90p910_ether.c | 2 -- drivers/net/ethernet/nxp/lpc_eth.c | 2 -- drivers/net/ethernet/renesas/sh_eth.c | 1 - drivers/net/ethernet/s6gmac.c | 1 - drivers/net/ethernet/seeq/sgiseeq.c | 1 - drivers/net/ethernet/sgi/meth.c | 1 - drivers/net/ethernet/smsc/smc911x.c | 2 -- drivers/net/ethernet/smsc/smc91x.c | 3 --- drivers/net/ethernet/smsc/smsc911x.c | 2 -- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 -- drivers/net/ethernet/ti/cpsw.c | 1 - drivers/net/ethernet/ti/davinci_emac.c | 2 -- drivers/net/ethernet/tundra/tsi108_eth.c | 1 - drivers/net/ethernet/wiznet/w5100.c | 2 -- drivers/net/ethernet/wiznet/w5300.c | 2 -- drivers/net/ethernet/xscale/ixp4xx_eth.c | 2 -- 37 files changed, 61 deletions(-) diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index 47618e505355..b2e840513735 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -849,7 +849,6 @@ static int ne_drv_remove(struct platform_device *pdev) free_irq(dev->irq, dev); release_region(dev->base_addr, NE_IO_EXTENT); free_netdev(dev); - platform_set_drvdata(pdev, NULL); } return 0; } diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index dada66bfe0d6..e904b3838dcc 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -1719,7 +1719,6 @@ static int bfin_mac_probe(struct platform_device *pdev) mdiobus_unregister(lp->mii_bus); mdiobus_free(lp->mii_bus); out_err_probe_mac: - platform_set_drvdata(pdev, NULL); free_netdev(ndev); return rc; @@ -1732,8 +1731,6 @@ static int bfin_mac_remove(struct platform_device *pdev) bfin_phc_release(lp); - platform_set_drvdata(pdev, NULL); - lp->mii_bus->priv = NULL; unregister_netdev(ndev); @@ -1868,7 +1865,6 @@ static int bfin_mii_bus_remove(struct platform_device *pdev) struct bfin_mii_bus_platform_data *mii_bus_pd = dev_get_platdata(&pdev->dev); - platform_set_drvdata(pdev, NULL); mdiobus_unregister(miibus); kfree(miibus->irq); mdiobus_free(miibus); diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 688aede742c7..ceb45bc963a9 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1301,8 +1301,6 @@ static int au1000_remove(struct platform_device *pdev) int i; struct resource *base, *macen; - platform_set_drvdata(pdev, NULL); - unregister_netdev(dev); mdiobus_unregister(aup->mii_bus); mdiobus_free(aup->mii_bus); diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 0b3e23ec37f7..e46466cb3627 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1847,7 +1847,6 @@ static int bcm_enet_remove(struct platform_device *pdev) clk_disable_unprepare(priv->mac_clk); clk_put(priv->mac_clk); - platform_set_drvdata(pdev, NULL); free_netdev(dev); return 0; } diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index cc9a185f0abb..3f1957158a3b 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -435,7 +435,6 @@ static int at91ether_remove(struct platform_device *pdev) unregister_netdev(dev); clk_disable(lp->pclk); free_netdev(dev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index c89aa41dd448..4465e27ba9d1 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1649,7 +1649,6 @@ static int __init macb_probe(struct platform_device *pdev) err_out_free_dev: free_netdev(dev); err_out: - platform_set_drvdata(pdev, NULL); return err; } @@ -1675,7 +1674,6 @@ static int __exit macb_remove(struct platform_device *pdev) clk_disable_unprepare(bp->pclk); clk_put(bp->pclk); free_netdev(dev); - platform_set_drvdata(pdev, NULL); } return 0; diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 4a1f2fa812ab..7cb148c495c9 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -1790,7 +1790,6 @@ static int xgmac_probe(struct platform_device *pdev) free_netdev(ndev); err_alloc: release_mem_region(res->start, resource_size(res)); - platform_set_drvdata(pdev, NULL); return ret; } @@ -1813,7 +1812,6 @@ static int xgmac_remove(struct platform_device *pdev) free_irq(ndev->irq, ndev); free_irq(priv->pmt_irq, ndev); - platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); netif_napi_del(&priv->napi); diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index 67b0388b6e68..e3d4ec836f8b 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -783,7 +783,6 @@ static int ep93xx_eth_remove(struct platform_device *pdev) dev = platform_get_drvdata(pdev); if (dev == NULL) return 0; - platform_set_drvdata(pdev, NULL); ep = netdev_priv(dev); diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index dd243a1b03e0..a13b312b50f2 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1699,8 +1699,6 @@ dm9000_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - unregister_netdev(ndev); dm9000_release_board(pdev, netdev_priv(ndev)); free_netdev(ndev); /* free device structure */ diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 5722bc61fa58..cf579fb39bc5 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1147,8 +1147,6 @@ static int ethoc_remove(struct platform_device *pdev) struct net_device *netdev = platform_get_drvdata(pdev); struct ethoc *priv = netdev_priv(netdev); - platform_set_drvdata(pdev, NULL); - if (netdev) { netif_napi_del(&priv->napi); phy_disconnect(priv->phy); diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 21b85fb7d05f..934e1ae279f0 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1311,7 +1311,6 @@ static int ftgmac100_probe(struct platform_device *pdev) release_resource(priv->res); err_req_mem: netif_napi_del(&priv->napi); - platform_set_drvdata(pdev, NULL); free_netdev(netdev); err_alloc_etherdev: return err; @@ -1335,7 +1334,6 @@ static int __exit ftgmac100_remove(struct platform_device *pdev) release_resource(priv->res); netif_napi_del(&priv->napi); - platform_set_drvdata(pdev, NULL); free_netdev(netdev); return 0; } diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index a6eda8d83138..4658f4cc1969 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -1149,7 +1149,6 @@ static int ftmac100_probe(struct platform_device *pdev) release_resource(priv->res); err_req_mem: netif_napi_del(&priv->napi); - platform_set_drvdata(pdev, NULL); free_netdev(netdev); err_alloc_etherdev: return err; @@ -1169,7 +1168,6 @@ static int __exit ftmac100_remove(struct platform_device *pdev) release_resource(priv->res); netif_napi_del(&priv->napi); - platform_set_drvdata(pdev, NULL); free_netdev(netdev); return 0; } diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 866b92220c15..9b0c6472bf04 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2024,8 +2024,6 @@ fec_drv_remove(struct platform_device *pdev) clk_disable_unprepare(fep->clk_ipg); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 0b5708520121..64646eb39e8b 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1211,7 +1211,6 @@ static int korina_remove(struct platform_device *pdev) iounmap(lp->rx_dma_regs); iounmap(lp->tx_dma_regs); - platform_set_drvdata(pdev, NULL); unregister_netdev(bif->dev); free_netdev(bif->dev); diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 2ad1494efbb3..afb8bcbe29f8 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2813,8 +2813,6 @@ static int mv643xx_eth_remove(struct platform_device *pdev) free_netdev(mp->dev); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index c96678555233..cd0ea204ac24 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2804,8 +2804,6 @@ static int mvneta_remove(struct platform_device *pdev) irq_dispose_mapping(dev->irq); free_netdev(dev); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 339bb323cb0c..2602cf7ba642 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1602,7 +1602,6 @@ static int pxa168_eth_remove(struct platform_device *pdev) unregister_netdev(dev); cancel_work_sync(&pep->tx_timeout_task); free_netdev(dev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c index b6c60fdef4ff..106eb972f2ac 100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@ -1600,7 +1600,6 @@ ks8695_drv_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ks8695_priv *ksp = netdev_priv(ndev); - platform_set_drvdata(pdev, NULL); netif_napi_del(&ksp->napi); unregister_netdev(ndev); diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index fbcb9e74d7fc..e393d998be89 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -1250,7 +1250,6 @@ static int ks8842_remove(struct platform_device *pdev) iounmap(adapter->hw_addr); free_netdev(netdev); release_mem_region(iomem->start, resource_size(iomem)); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index ddaf138ce0d4..e9b1a830d582 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -1671,7 +1671,6 @@ static int ks8851_remove(struct platform_device *pdev) iounmap(ks->hw_addr); free_netdev(netdev); release_mem_region(iomem->start, resource_size(iomem)); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/netx-eth.c b/drivers/net/ethernet/netx-eth.c index 5da3ffb61062..dc2c6f561e9a 100644 --- a/drivers/net/ethernet/netx-eth.c +++ b/drivers/net/ethernet/netx-eth.c @@ -422,7 +422,6 @@ static int netx_eth_drv_probe(struct platform_device *pdev) exit_free_xc: free_xc(priv->xc); exit_free_netdev: - platform_set_drvdata(pdev, NULL); free_netdev(ndev); exit: return ret; diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index 3df8287b7452..e88bdb1aa669 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -1051,7 +1051,6 @@ static int w90p910_ether_probe(struct platform_device *pdev) clk_put(ether->clk); failed_free_rxirq: free_irq(ether->rxirq, pdev); - platform_set_drvdata(pdev, NULL); failed_free_txirq: free_irq(ether->txirq, pdev); failed_free_io: @@ -1080,7 +1079,6 @@ static int w90p910_ether_remove(struct platform_device *pdev) free_irq(ether->rxirq, dev); del_timer_sync(ðer->check_timer); - platform_set_drvdata(pdev, NULL); free_netdev(dev); return 0; diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 55a5548d6add..a061b93efe66 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1483,7 +1483,6 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) return 0; err_out_unregister_netdev: - platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); err_out_dma_unmap: if (!use_iram_for_net(&pldat->pdev->dev) || @@ -1511,7 +1510,6 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) struct netdata_local *pldat = netdev_priv(ndev); unregister_netdev(ndev); - platform_set_drvdata(pdev, NULL); if (!use_iram_for_net(&pldat->pdev->dev) || pldat->dma_buff_size > lpc32xx_return_iram_size()) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 42e9dd05c936..399a7c968e0d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2803,7 +2803,6 @@ static int sh_eth_drv_remove(struct platform_device *pdev) unregister_netdev(ndev); pm_runtime_disable(&pdev->dev); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/s6gmac.c b/drivers/net/ethernet/s6gmac.c index b6739afeaca1..a99739c5142c 100644 --- a/drivers/net/ethernet/s6gmac.c +++ b/drivers/net/ethernet/s6gmac.c @@ -1040,7 +1040,6 @@ static int s6gmac_remove(struct platform_device *pdev) unregister_netdev(dev); free_irq(dev->irq, dev); free_netdev(dev); - platform_set_drvdata(pdev, NULL); } return 0; } diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c index 0ad5694b41f8..856e523ac936 100644 --- a/drivers/net/ethernet/seeq/sgiseeq.c +++ b/drivers/net/ethernet/seeq/sgiseeq.c @@ -818,7 +818,6 @@ static int __exit sgiseeq_remove(struct platform_device *pdev) dma_free_noncoherent(&pdev->dev, sizeof(*sp->srings), sp->srings, sp->srings_dma); free_netdev(dev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 4bdbaad9932d..9f5f35e041ac 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -863,7 +863,6 @@ static int __exit meth_remove(struct platform_device *pdev) unregister_netdev(dev); free_netdev(dev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 9dd842dbb859..345558fe7367 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -2087,7 +2087,6 @@ static int smc911x_drv_probe(struct platform_device *pdev) ndev->base_addr = res->start; ret = smc911x_probe(ndev); if (ret != 0) { - platform_set_drvdata(pdev, NULL); iounmap(addr); release_both: free_netdev(ndev); @@ -2113,7 +2112,6 @@ static int smc911x_drv_remove(struct platform_device *pdev) struct resource *res; DBG(SMC_DEBUG_FUNC, "--> %s\n", __func__); - platform_set_drvdata(pdev, NULL); unregister_netdev(ndev); diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index dfbf978315df..cde13be7c7de 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -2299,7 +2299,6 @@ static int smc_drv_probe(struct platform_device *pdev) return 0; out_iounmap: - platform_set_drvdata(pdev, NULL); iounmap(addr); out_release_attrib: smc_release_attrib(pdev, ndev); @@ -2319,8 +2318,6 @@ static int smc_drv_remove(struct platform_device *pdev) struct smc_local *lp = netdev_priv(ndev); struct resource *res; - platform_set_drvdata(pdev, NULL); - unregister_netdev(ndev); free_irq(ndev->irq, ndev); diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 3663b9e04a31..a1419211585b 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2284,7 +2284,6 @@ static int smsc911x_drv_remove(struct platform_device *pdev) mdiobus_unregister(pdata->mii_bus); mdiobus_free(pdata->mii_bus); - platform_set_drvdata(pdev, NULL); unregister_netdev(dev); free_irq(dev->irq, dev); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -2539,7 +2538,6 @@ static int smsc911x_drv_probe(struct platform_device *pdev) out_enable_resources_fail: smsc911x_free_resources(pdev); out_request_resources_fail: - platform_set_drvdata(pdev, NULL); iounmap(pdata->ioaddr); free_netdev(dev); out_release_io_1: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 1d3780f55ba2..17bc7827e7ca 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -171,8 +171,6 @@ static int stmmac_pltfr_remove(struct platform_device *pdev) if (priv->plat->exit) priv->plat->exit(pdev); - platform_set_drvdata(pdev, NULL); - return ret; } diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 21a5b291b4b3..89a4c40d6d83 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1940,7 +1940,6 @@ static int cpsw_remove(struct platform_device *pdev) struct cpsw_priv *priv = netdev_priv(ndev); int i; - platform_set_drvdata(pdev, NULL); if (priv->data.dual_emac) unregister_netdev(cpsw_get_slave_ndev(priv, 1)); unregister_netdev(ndev); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 860e15ddfbcb..efb6f65a8be3 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -2037,8 +2037,6 @@ static int davinci_emac_remove(struct platform_device *pdev) dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n"); - platform_set_drvdata(pdev, NULL); - if (priv->txchan) cpdma_chan_destroy(priv->txchan); if (priv->rxchan) diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index 3c69a0460832..01bdc6ca0755 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1682,7 +1682,6 @@ static int tsi108_ether_remove(struct platform_device *pdev) unregister_netdev(dev); tsi108_stop_ethernet(dev); - platform_set_drvdata(pdev, NULL); iounmap(priv->regs); iounmap(priv->phyregs); free_netdev(dev); diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c index a518dcab396e..30fed08d1674 100644 --- a/drivers/net/ethernet/wiznet/w5100.c +++ b/drivers/net/ethernet/wiznet/w5100.c @@ -734,7 +734,6 @@ static int w5100_probe(struct platform_device *pdev) unregister_netdev(ndev); err_register: free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return err; } @@ -750,7 +749,6 @@ static int w5100_remove(struct platform_device *pdev) unregister_netdev(ndev); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c index 6e00e3f94ce4..e92884564e1e 100644 --- a/drivers/net/ethernet/wiznet/w5300.c +++ b/drivers/net/ethernet/wiznet/w5300.c @@ -646,7 +646,6 @@ static int w5300_probe(struct platform_device *pdev) unregister_netdev(ndev); err_register: free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return err; } @@ -662,7 +661,6 @@ static int w5300_remove(struct platform_device *pdev) unregister_netdev(ndev); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 6958a5e87703..3d689fcb7917 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1472,7 +1472,6 @@ static int eth_init_one(struct platform_device *pdev) phy_disconnect(port->phydev); err_free_mem: npe_port_tab[NPE_ID(port->id)] = NULL; - platform_set_drvdata(pdev, NULL); release_resource(port->mem_res); err_npe_rel: npe_release(port->npe); @@ -1489,7 +1488,6 @@ static int eth_remove_one(struct platform_device *pdev) unregister_netdev(dev); phy_disconnect(port->phydev); npe_port_tab[NPE_ID(port->id)] = NULL; - platform_set_drvdata(pdev, NULL); npe_release(port->npe); release_resource(port->mem_res); free_netdev(dev); -- GitLab From bf3a33cec8d8b380647c9bbf17439e0c1695ba43 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 27 May 2013 19:03:49 +0000 Subject: [PATCH 0445/2900] net: irda: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Kuninori Morimoto Signed-off-by: David S. Miller --- drivers/net/irda/bfin_sir.c | 1 - drivers/net/irda/sh_irda.c | 1 - drivers/net/irda/sh_sir.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index 22b4527321b1..c74f384c87d5 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -794,7 +794,6 @@ static int bfin_sir_remove(struct platform_device *pdev) kfree(self->rx_buff.head); free_netdev(dev); kfree(sir_port); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/irda/sh_irda.c b/drivers/net/irda/sh_irda.c index 9448587de453..4455425f1c77 100644 --- a/drivers/net/irda/sh_irda.c +++ b/drivers/net/irda/sh_irda.c @@ -838,7 +838,6 @@ static int sh_irda_remove(struct platform_device *pdev) sh_irda_remove_iobuf(self); iounmap(self->membase); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c index 24aefcd84065..89682b49900f 100644 --- a/drivers/net/irda/sh_sir.c +++ b/drivers/net/irda/sh_sir.c @@ -796,7 +796,6 @@ static int sh_sir_remove(struct platform_device *pdev) sh_sir_remove_iobuf(self); iounmap(self->membase); free_netdev(ndev); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 785ec305b26ee23e0efb834b5cd0dd24070ba1bf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 27 May 2013 19:07:11 +0000 Subject: [PATCH 0446/2900] net: wireless: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wireless/ath/ath5k/ahb.c | 2 -- drivers/net/wireless/ath/ath9k/ahb.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 8e8bcc7a4805..e9bc9e616b69 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -185,7 +185,6 @@ static int ath_ahb_probe(struct platform_device *pdev) err_free_hw: ieee80211_free_hw(hw); - platform_set_drvdata(pdev, NULL); err_iounmap: iounmap(mem); err_out: @@ -221,7 +220,6 @@ static int ath_ahb_remove(struct platform_device *pdev) ath5k_deinit_ah(ah); iounmap(ah->iobase); - platform_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); return 0; diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index d1ff3c246a12..072e4b531067 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -150,7 +150,6 @@ static int ath_ahb_probe(struct platform_device *pdev) free_irq(irq, sc); err_free_hw: ieee80211_free_hw(hw); - platform_set_drvdata(pdev, NULL); return ret; } @@ -164,7 +163,6 @@ static int ath_ahb_remove(struct platform_device *pdev) ath9k_deinit_device(sc); free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); - platform_set_drvdata(pdev, NULL); } return 0; -- GitLab From 1010dcceed9d45dc8a07c50ec93e5d0c1ef7cc24 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 27 May 2013 19:08:17 +0000 Subject: [PATCH 0447/2900] net: wan: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wan/ixp4xx_hss.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index fc9d11d74d60..e7bbdb7af53a 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -1384,7 +1384,6 @@ static int hss_remove_one(struct platform_device *pdev) unregister_hdlc_device(port->netdev); free_netdev(port->netdev); npe_release(port->npe); - platform_set_drvdata(pdev, NULL); kfree(port); return 0; } -- GitLab From 7ec872114251b618adf5a2688de0ca00de63635d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 23 May 2013 01:11:11 +0000 Subject: [PATCH 0448/2900] net: ethtool: disambiguate XCVR_* meaning Add a comment which explains the real meaning of XCVR_INTERNAL (PHY and Ethernet MAC in the same package/die) and XCVR_EXTERNAL (PHY and Ethernet MAC in a different package/die). Most if not all of the drivers setting their transceiver type already do it the way the comment describes it. Signed-off-by: Florian Fainelli Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 0c9b44871df0..38dbafaa5341 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -993,8 +993,8 @@ enum ethtool_sfeatures_retval_bits { #define PORT_OTHER 0xff /* Which transceiver to use. */ -#define XCVR_INTERNAL 0x00 -#define XCVR_EXTERNAL 0x01 +#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */ +#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */ #define XCVR_DUMMY1 0x02 #define XCVR_DUMMY2 0x03 #define XCVR_DUMMY3 0x04 -- GitLab From 4284b6a535a9aab33e5f3c37929143508dd2ee60 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 23 May 2013 01:11:12 +0000 Subject: [PATCH 0449/2900] phy: allow drivers to flag a PHY device as internal libphy currently always reports a PHY as an external transceiver from the ethtool output. This is inaccurate, because some drivers should be able to tell that a PHY device is an internal transceiver of an Ethernet MAC. Add a new flag (PHY_IS_INTERNAL) which can be set by PHY drivers just like other flags, and a corresponding helper: phy_is_internal() which can be used by networking drivers to query if a given PHY device is internal. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 3 ++- drivers/net/phy/phy_device.c | 3 +++ include/linux/phy.h | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 2d28a0ef4572..b2a94e436ed8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -294,7 +294,8 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd) cmd->duplex = phydev->duplex; cmd->port = PORT_MII; cmd->phy_address = phydev->addr; - cmd->transceiver = XCVR_EXTERNAL; + cmd->transceiver = phy_is_internal(phydev) ? + XCVR_INTERNAL : XCVR_EXTERNAL; cmd->autoneg = phydev->autoneg; return 0; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index b55aa33a5b8b..74630e94fa3b 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1017,6 +1017,9 @@ static int phy_probe(struct device *dev) phy_interrupt_is_valid(phydev)) phydev->irq = PHY_POLL; + if (phydrv->flags & PHY_IS_INTERNAL) + phydev->is_internal = true; + mutex_lock(&phydev->lock); /* Start out supporting everything. Eventually, diff --git a/include/linux/phy.h b/include/linux/phy.h index fdfa11542974..ee411b0eef5d 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -49,6 +49,7 @@ #define PHY_HAS_INTERRUPT 0x00000001 #define PHY_HAS_MAGICANEG 0x00000002 +#define PHY_IS_INTERNAL 0x00000004 /* Interface Mode definitions */ typedef enum { @@ -261,6 +262,7 @@ struct phy_c45_device_ids { * phy_id: UID for this device found during discovery * c45_ids: 802.3-c45 Device Identifers if is_c45. * is_c45: Set to true if this phy uses clause 45 addressing. + * is_internal: Set to true if this phy is internal to a MAC. * state: state of the PHY for management purposes * dev_flags: Device-specific flags used by the PHY driver. * addr: Bus address of PHY @@ -298,6 +300,7 @@ struct phy_device { struct phy_c45_device_ids c45_ids; bool is_c45; + bool is_internal; enum phy_state state; @@ -520,6 +523,15 @@ static inline bool phy_interrupt_is_valid(struct phy_device *phydev) return phydev->irq != PHY_POLL && phydev->irq != PHY_IGNORE_INTERRUPT; } +/** + * phy_is_internal - Convenience function for testing if a PHY is internal + * @phydev: the phy_device struct + */ +static inline bool phy_is_internal(struct phy_device *phydev) +{ + return phydev->is_internal; +} + struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, bool is_c45, struct phy_c45_device_ids *c45_ids); struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); -- GitLab From 50ab731e967d65549b11b808f129329dd614e8d9 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 23 May 2013 01:11:13 +0000 Subject: [PATCH 0450/2900] phy: bcm63xx: report Broadcom BCM63xx PHYs as internal The Broadcom BCM63xx PHY driver is for the SoC internal PHYs, flag these as internal PHY devices. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/bcm63xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index 84c7a39b1c65..ac55b0807853 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -78,7 +78,7 @@ static struct phy_driver bcm63xx_driver[] = { .name = "Broadcom BCM63XX (1)", /* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), - .flags = PHY_HAS_INTERRUPT, + .flags = PHY_HAS_INTERRUPT | PHY_IS_INTERNAL, .config_init = bcm63xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, @@ -91,7 +91,7 @@ static struct phy_driver bcm63xx_driver[] = { .phy_id_mask = 0xfffffc00, .name = "Broadcom BCM63XX (2)", .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause), - .flags = PHY_HAS_INTERRUPT, + .flags = PHY_HAS_INTERRUPT | PHY_IS_INTERNAL, .config_init = bcm63xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, -- GitLab From 1a37e412a0225fcba5587f24c0dfc7636efc8b69 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 23 May 2013 21:02:51 +0000 Subject: [PATCH 0451/2900] net: Use 16bits for *_headers fields of struct skbuff In order to mitigate ongoing incresase in the size of struct skbuff use 16 bit integer offsets rather than pointers for inner_*_headers. This appears to reduce the size of struct skbuff from 0xd0 to 0xc0 bytes on x86_64 with the following all unset. CONFIG_XFRM CONFIG_NF_CONNTRACK CONFIG_NF_CONNTRACK_MODULE NET_SKBUFF_NF_DEFRAG_NEEDED CONFIG_BRIDGE_NETFILTER CONFIG_NET_SCHED CONFIG_IPV6_NDISC_NODETYPE CONFIG_NET_DMA CONFIG_NETWORK_SECMARK Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/linux/skbuff.h | 119 +++-------------------------------------- 1 file changed, 6 insertions(+), 113 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2e0ced1af3b1..5663e3592784 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -509,12 +509,12 @@ struct sk_buff { __u32 reserved_tailroom; }; - sk_buff_data_t inner_transport_header; - sk_buff_data_t inner_network_header; - sk_buff_data_t inner_mac_header; - sk_buff_data_t transport_header; - sk_buff_data_t network_header; - sk_buff_data_t mac_header; + __u16 inner_transport_header; + __u16 inner_network_header; + __u16 inner_mac_header; + __u16 transport_header; + __u16 network_header; + __u16 mac_header; /* These elements must be at the end, see alloc_skb() for details. */ sk_buff_data_t tail; sk_buff_data_t end; @@ -1527,7 +1527,6 @@ static inline void skb_reset_mac_len(struct sk_buff *skb) skb->mac_len = skb->network_header - skb->mac_header; } -#ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_inner_transport_header(const struct sk_buff *skb) { @@ -1638,112 +1637,6 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) skb->mac_header += offset; } -#else /* NET_SKBUFF_DATA_USES_OFFSET */ -static inline unsigned char *skb_inner_transport_header(const struct sk_buff - *skb) -{ - return skb->inner_transport_header; -} - -static inline void skb_reset_inner_transport_header(struct sk_buff *skb) -{ - skb->inner_transport_header = skb->data; -} - -static inline void skb_set_inner_transport_header(struct sk_buff *skb, - const int offset) -{ - skb->inner_transport_header = skb->data + offset; -} - -static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb) -{ - return skb->inner_network_header; -} - -static inline void skb_reset_inner_network_header(struct sk_buff *skb) -{ - skb->inner_network_header = skb->data; -} - -static inline void skb_set_inner_network_header(struct sk_buff *skb, - const int offset) -{ - skb->inner_network_header = skb->data + offset; -} - -static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb) -{ - return skb->inner_mac_header; -} - -static inline void skb_reset_inner_mac_header(struct sk_buff *skb) -{ - skb->inner_mac_header = skb->data; -} - -static inline void skb_set_inner_mac_header(struct sk_buff *skb, - const int offset) -{ - skb->inner_mac_header = skb->data + offset; -} -static inline bool skb_transport_header_was_set(const struct sk_buff *skb) -{ - return skb->transport_header != NULL; -} - -static inline unsigned char *skb_transport_header(const struct sk_buff *skb) -{ - return skb->transport_header; -} - -static inline void skb_reset_transport_header(struct sk_buff *skb) -{ - skb->transport_header = skb->data; -} - -static inline void skb_set_transport_header(struct sk_buff *skb, - const int offset) -{ - skb->transport_header = skb->data + offset; -} - -static inline unsigned char *skb_network_header(const struct sk_buff *skb) -{ - return skb->network_header; -} - -static inline void skb_reset_network_header(struct sk_buff *skb) -{ - skb->network_header = skb->data; -} - -static inline void skb_set_network_header(struct sk_buff *skb, const int offset) -{ - skb->network_header = skb->data + offset; -} - -static inline unsigned char *skb_mac_header(const struct sk_buff *skb) -{ - return skb->mac_header; -} - -static inline int skb_mac_header_was_set(const struct sk_buff *skb) -{ - return skb->mac_header != NULL; -} - -static inline void skb_reset_mac_header(struct sk_buff *skb) -{ - skb->mac_header = skb->data; -} - -static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) -{ - skb->mac_header = skb->data + offset; -} -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - static inline void skb_probe_transport_header(struct sk_buff *skb, const int offset_hint) { -- GitLab From 0d89d2035fe063461a5ddb609b2c12e7fb006e44 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 23 May 2013 21:02:52 +0000 Subject: [PATCH 0452/2900] MPLS: Add limited GSO support In the case where a non-MPLS packet is received and an MPLS stack is added it may well be the case that the original skb is GSO but the NIC used for transmit does not support GSO of MPLS packets. The aim of this code is to provide GSO in software for MPLS packets whose skbs are GSO. SKB Usage: When an implementation adds an MPLS stack to a non-MPLS packet it should do the following to skb metadata: * Set skb->inner_protocol to the old non-MPLS ethertype of the packet. skb->inner_protocol is added by this patch. * Set skb->protocol to the new MPLS ethertype of the packet. * Set skb->network_header to correspond to the end of the L3 header, including the MPLS label stack. I have posted a patch, "[PATCH v3.29] datapath: Add basic MPLS support to kernel" which adds MPLS support to the kernel datapath of Open vSwtich. That patch sets the above requirements in datapath/actions.c:push_mpls() and was used to exercise this code. The datapath patch is against the Open vSwtich tree but it is intended that it be added to the Open vSwtich code present in the mainline Linux kernel at some point. Features: I believe that the approach that I have taken is at least partially consistent with the handling of other protocols. Jesse, I understand that you have some ideas here. I am more than happy to change my implementation. This patch adds dev->mpls_features which may be used by devices to advertise features supported for MPLS packets. A new NETIF_F_MPLS_GSO feature is added for devices which support hardware MPLS GSO offload. Currently no devices support this and MPLS GSO always falls back to software. Alternate Implementation: One possible alternate implementation is to teach netif_skb_features() and skb_network_protocol() about MPLS, in a similar way to their understanding of VLANs. I believe this would avoid the need for net/mpls/mpls_gso.c and in particular the calls to __skb_push() and __skb_push() in mpls_gso_segment(). I have decided on the implementation in this patch as it should not introduce any overhead in the case where mpls_gso is not compiled into the kernel or inserted as a module. MPLS GSO suggested by Jesse Gross. Based in part on "v4 GRE: Add TCP segmentation offload for GRE" by Pravin B Shelar. Cc: Jesse Gross Cc: Pravin B Shelar Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/linux/netdev_features.h | 4 +- include/linux/netdevice.h | 2 + include/linux/skbuff.h | 4 ++ net/Kconfig | 1 + net/Makefile | 1 + net/core/dev.c | 4 ++ net/core/ethtool.c | 1 + net/ipv4/af_inet.c | 1 + net/ipv4/tcp.c | 1 + net/ipv4/udp.c | 2 +- net/ipv6/ip6_offload.c | 1 + net/ipv6/udp_offload.c | 3 +- net/mpls/Kconfig | 9 +++ net/mpls/Makefile | 4 ++ net/mpls/mpls_gso.c | 108 ++++++++++++++++++++++++++++++++ 15 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 net/mpls/Kconfig create mode 100644 net/mpls/Makefile create mode 100644 net/mpls/mpls_gso.c diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 09906b7ca47d..a2a89a5c7be5 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -43,8 +43,9 @@ enum { NETIF_F_FSO_BIT, /* ... FCoE segmentation */ NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */ NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ + NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */ /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ - NETIF_F_GSO_UDP_TUNNEL_BIT, + NETIF_F_GSO_MPLS_BIT, NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */ NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */ @@ -107,6 +108,7 @@ enum { #define NETIF_F_RXALL __NETIF_F(RXALL) #define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) +#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) #define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX) #define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ea7b6bce9ea0..6b2bb460d1d7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1088,6 +1088,8 @@ struct net_device { * need to set them appropriately. */ netdev_features_t hw_enc_features; + /* mask of fetures inheritable by MPLS */ + netdev_features_t mpls_features; /* Interface index. Unique device identifier */ int ifindex; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5663e3592784..8f2b830772a8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -319,6 +319,8 @@ enum { SKB_GSO_GRE = 1 << 6, SKB_GSO_UDP_TUNNEL = 1 << 7, + + SKB_GSO_MPLS = 1 << 8, }; #if BITS_PER_LONG > 32 @@ -389,6 +391,7 @@ typedef unsigned char *sk_buff_data_t; * @dropcount: total number of sk_receive_queue overflows * @vlan_proto: vlan encapsulation protocol * @vlan_tci: vlan tag control information + * @inner_protocol: Protocol (encapsulation) * @inner_transport_header: Inner transport layer header (encapsulation) * @inner_network_header: Network layer header (encapsulation) * @inner_mac_header: Link layer header (encapsulation) @@ -509,6 +512,7 @@ struct sk_buff { __u32 reserved_tailroom; }; + __be16 inner_protocol; __u16 inner_transport_header; __u16 inner_network_header; __u16 inner_mac_header; diff --git a/net/Kconfig b/net/Kconfig index 08de901415ee..523e43e6da1b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -218,6 +218,7 @@ source "net/batman-adv/Kconfig" source "net/openvswitch/Kconfig" source "net/vmw_vsock/Kconfig" source "net/netlink/Kconfig" +source "net/mpls/Kconfig" config RPS boolean diff --git a/net/Makefile b/net/Makefile index 091e7b04f301..9492e8cb64e9 100644 --- a/net/Makefile +++ b/net/Makefile @@ -70,3 +70,4 @@ obj-$(CONFIG_BATMAN_ADV) += batman-adv/ obj-$(CONFIG_NFC) += nfc/ obj-$(CONFIG_OPENVSWITCH) += openvswitch/ obj-$(CONFIG_VSOCKETS) += vmw_vsock/ +obj-$(CONFIG_NET_MPLS_GSO) += mpls/ diff --git a/net/core/dev.c b/net/core/dev.c index 50c02ded1d69..2f09cb29cc95 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5277,6 +5277,10 @@ int register_netdevice(struct net_device *dev) */ dev->hw_enc_features |= NETIF_F_SG; + /* Make NETIF_F_SG inheritable to MPLS. + */ + dev->mpls_features |= NETIF_F_SG; + ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); ret = notifier_to_errno(ret); if (ret) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 22efdaa76ebf..4e6f63ade741 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -82,6 +82,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", + [NETIF_F_GSO_MPLS_BIT] = "tx-mpls-segmentation", [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp", diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d01be2a3ae53..b05ae96aec44 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1295,6 +1295,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, SKB_GSO_GRE | SKB_GSO_TCPV6 | SKB_GSO_UDP_TUNNEL | + SKB_GSO_MPLS | 0))) goto out; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d87ce72ca8aa..ba4186e1dca9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2917,6 +2917,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, SKB_GSO_TCP_ECN | SKB_GSO_TCPV6 | SKB_GSO_GRE | + SKB_GSO_MPLS | SKB_GSO_UDP_TUNNEL | 0) || !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0bf5d399a03c..aa5eff46d137 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2381,7 +2381,7 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_UDP_TUNNEL | - SKB_GSO_GRE) || + SKB_GSO_GRE | SKB_GSO_MPLS) || !(type & (SKB_GSO_UDP)))) goto out; diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 71b766ee821d..a263b990ee11 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -98,6 +98,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, SKB_GSO_TCP_ECN | SKB_GSO_GRE | SKB_GSO_UDP_TUNNEL | + SKB_GSO_MPLS | SKB_GSO_TCPV6 | 0))) goto out; diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 3bb3a891a424..76d401a93c7a 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -63,7 +63,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_UDP_TUNNEL | - SKB_GSO_GRE) || + SKB_GSO_GRE | + SKB_GSO_MPLS) || !(type & (SKB_GSO_UDP)))) goto out; diff --git a/net/mpls/Kconfig b/net/mpls/Kconfig new file mode 100644 index 000000000000..37421db88965 --- /dev/null +++ b/net/mpls/Kconfig @@ -0,0 +1,9 @@ +# +# MPLS configuration +# +config NET_MPLS_GSO + tristate "MPLS: GSO support" + help + This is helper module to allow segmentation of non-MPLS GSO packets + that have had MPLS stack entries pushed onto them and thus + become MPLS GSO packets. diff --git a/net/mpls/Makefile b/net/mpls/Makefile new file mode 100644 index 000000000000..0a3c171be537 --- /dev/null +++ b/net/mpls/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for MPLS. +# +obj-y += mpls_gso.o diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c new file mode 100644 index 000000000000..1bec1219ab81 --- /dev/null +++ b/net/mpls/mpls_gso.c @@ -0,0 +1,108 @@ +/* + * MPLS GSO Support + * + * Authors: Simon Horman (horms@verge.net.au) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Based on: GSO portions of net/ipv4/gre.c + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include + +static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, + netdev_features_t features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + netdev_features_t mpls_features; + __be16 mpls_protocol; + + if (unlikely(skb_shinfo(skb)->gso_type & + ~(SKB_GSO_TCPV4 | + SKB_GSO_TCPV6 | + SKB_GSO_UDP | + SKB_GSO_DODGY | + SKB_GSO_TCP_ECN | + SKB_GSO_GRE | + SKB_GSO_MPLS))) + goto out; + + /* Setup inner SKB. */ + mpls_protocol = skb->protocol; + skb->protocol = skb->inner_protocol; + + /* Push back the mac header that skb_mac_gso_segment() has pulled. + * It will be re-pulled by the call to skb_mac_gso_segment() below + */ + __skb_push(skb, skb->mac_len); + + /* Segment inner packet. */ + mpls_features = skb->dev->mpls_features & netif_skb_features(skb); + segs = skb_mac_gso_segment(skb, mpls_features); + + + /* Restore outer protocol. */ + skb->protocol = mpls_protocol; + + /* Re-pull the mac header that the call to skb_mac_gso_segment() + * above pulled. It will be re-pushed after returning + * skb_mac_gso_segment(), an indirect caller of this function. + */ + __skb_push(skb, skb->data - skb_mac_header(skb)); + +out: + return segs; +} + +static int mpls_gso_send_check(struct sk_buff *skb) +{ + return 0; +} + +static struct packet_offload mpls_mc_offload = { + .type = cpu_to_be16(ETH_P_MPLS_MC), + .callbacks = { + .gso_send_check = mpls_gso_send_check, + .gso_segment = mpls_gso_segment, + }, +}; + +static struct packet_offload mpls_uc_offload = { + .type = cpu_to_be16(ETH_P_MPLS_UC), + .callbacks = { + .gso_send_check = mpls_gso_send_check, + .gso_segment = mpls_gso_segment, + }, +}; + +static int __init mpls_gso_init(void) +{ + pr_info("MPLS GSO support\n"); + + dev_add_offload(&mpls_uc_offload); + dev_add_offload(&mpls_mc_offload); + + return 0; +} + +static void __exit mpls_gso_exit(void) +{ + dev_remove_offload(&mpls_uc_offload); + dev_remove_offload(&mpls_mc_offload); +} + +module_init(mpls_gso_init); +module_exit(mpls_gso_exit); + +MODULE_DESCRIPTION("MPLS GSO support"); +MODULE_AUTHOR("Simon Horman (horms@verge.net.au)"); +MODULE_LICENSE("GPL"); -- GitLab From 87227b8b2d4d556a6924ad9af87450fdc3fcd7e3 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 23 May 2013 23:01:22 +0000 Subject: [PATCH 0453/2900] net: micrel : ks8851-ml: add dt support Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- .../devicetree/bindings/net/micrel-ks8851.txt | 9 +++++ drivers/net/ethernet/micrel/ks8851_mll.c | 33 +++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/micrel-ks8851.txt diff --git a/Documentation/devicetree/bindings/net/micrel-ks8851.txt b/Documentation/devicetree/bindings/net/micrel-ks8851.txt new file mode 100644 index 000000000000..11ace3c3d805 --- /dev/null +++ b/Documentation/devicetree/bindings/net/micrel-ks8851.txt @@ -0,0 +1,9 @@ +Micrel KS8851 Ethernet mac + +Required properties: +- compatible = "micrel,ks8851-ml" of parallel interface +- reg : 2 physical address and size of registers for data and command +- interrupts : interrupt connection + +Optional properties: +- local-mac-address : Ethernet mac address to use diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index e9b1a830d582..ac20098b542a 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #define DRV_NAME "ks8851_mll" @@ -1524,6 +1527,13 @@ static int ks_hw_init(struct ks_net *ks) return true; } +#if defined(CONFIG_OF) +static const struct of_device_id ks8851_ml_dt_ids[] = { + { .compatible = "micrel,ks8851-mll" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ks8851_ml_dt_ids); +#endif static int ks8851_probe(struct platform_device *pdev) { @@ -1532,7 +1542,7 @@ static int ks8851_probe(struct platform_device *pdev) struct net_device *netdev; struct ks_net *ks; u16 id, data; - struct ks8851_mll_platform_data *pdata; + const char *mac; io_d = platform_get_resource(pdev, IORESOURCE_MEM, 0); io_c = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -1619,13 +1629,21 @@ static int ks8851_probe(struct platform_device *pdev) ks_wrreg16(ks, KS_OBCR, data | OBCR_ODS_16MA); /* overwriting the default MAC address */ - pdata = pdev->dev.platform_data; - if (!pdata) { - netdev_err(netdev, "No platform data\n"); - err = -ENODEV; - goto err_pdata; + if (pdev->dev.of_node) { + mac = of_get_mac_address(pdev->dev.of_node); + if (mac) + memcpy(ks->mac_addr, mac, ETH_ALEN); + } else { + struct ks8851_mll_platform_data *pdata; + + pdata = pdev->dev.platform_data; + if (!pdata) { + netdev_err(netdev, "No platform data\n"); + err = -ENODEV; + goto err_pdata; + } + memcpy(ks->mac_addr, pdata->mac_addr, ETH_ALEN); } - memcpy(ks->mac_addr, pdata->mac_addr, 6); if (!is_valid_ether_addr(ks->mac_addr)) { /* Use random MAC address if none passed */ eth_random_addr(ks->mac_addr); @@ -1679,6 +1697,7 @@ static struct platform_driver ks8851_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ks8851_ml_dt_ids), }, .probe = ks8851_probe, .remove = ks8851_remove, -- GitLab From da6e378ba918cd0feeb90eeb84d8b42148bb0c82 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Mon, 27 May 2013 19:53:31 +0000 Subject: [PATCH 0454/2900] netpoll: remove return value from netpoll_rx_disable() The netpoll_rx_disable() will always return 0, it is no use and looks wordy, so remove the unnecessary code and get rid of it in _dev_open and _dev_close. Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- include/linux/netpoll.h | 4 ++-- net/core/dev.c | 15 ++++----------- net/core/netpoll.c | 3 +-- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index fa2cb76a7029..f3c7c24bec1c 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -53,10 +53,10 @@ struct netpoll_info { }; #ifdef CONFIG_NETPOLL -extern int netpoll_rx_disable(struct net_device *dev); +extern void netpoll_rx_disable(struct net_device *dev); extern void netpoll_rx_enable(struct net_device *dev); #else -static inline int netpoll_rx_disable(struct net_device *dev) { return 0; } +static inline void netpoll_rx_disable(struct net_device *dev) { return; } static inline void netpoll_rx_enable(struct net_device *dev) { return; } #endif diff --git a/net/core/dev.c b/net/core/dev.c index 2f09cb29cc95..5f747974ac58 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1198,9 +1198,7 @@ static int __dev_open(struct net_device *dev) * If we don't do this there is a chance ndo_poll_controller * or ndo_poll may be running while we open the device */ - ret = netpoll_rx_disable(dev); - if (ret) - return ret; + netpoll_rx_disable(dev); ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev); ret = notifier_to_errno(ret); @@ -1309,9 +1307,7 @@ static int __dev_close(struct net_device *dev) LIST_HEAD(single); /* Temporarily disable netpoll until the interface is down */ - retval = netpoll_rx_disable(dev); - if (retval) - return retval; + netpoll_rx_disable(dev); list_add(&dev->unreg_list, &single); retval = __dev_close_many(&single); @@ -1353,14 +1349,11 @@ static int dev_close_many(struct list_head *head) */ int dev_close(struct net_device *dev) { - int ret = 0; if (dev->flags & IFF_UP) { LIST_HEAD(single); /* Block netpoll rx while the interface is going down */ - ret = netpoll_rx_disable(dev); - if (ret) - return ret; + netpoll_rx_disable(dev); list_add(&dev->unreg_list, &single); dev_close_many(&single); @@ -1368,7 +1361,7 @@ int dev_close(struct net_device *dev) netpoll_rx_enable(dev); } - return ret; + return 0; } EXPORT_SYMBOL(dev_close); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index cec074be8c43..37deedd48bcc 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -247,7 +247,7 @@ static void netpoll_poll_dev(struct net_device *dev) zap_completion_queue(); } -int netpoll_rx_disable(struct net_device *dev) +void netpoll_rx_disable(struct net_device *dev) { struct netpoll_info *ni; int idx; @@ -257,7 +257,6 @@ int netpoll_rx_disable(struct net_device *dev) if (ni) down(&ni->dev_lock); srcu_read_unlock(&netpoll_srcu, idx); - return 0; } EXPORT_SYMBOL(netpoll_rx_disable); -- GitLab From 1a9561a3bd0faaffa14dc20430805a46e311d00e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 27 May 2013 01:51:39 +0000 Subject: [PATCH 0455/2900] net/phy: Use module_spi_driver in spi_ks8995.c module_spi_driver() removes some boilerplate and makes the code simpler. Signed-off-by: Sachin Kamat Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index d11c93e69e03..f3bea1346021 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -354,19 +354,7 @@ static struct spi_driver ks8995_driver = { .remove = ks8995_remove, }; -static int __init ks8995_init(void) -{ - pr_info(DRV_DESC " version " DRV_VERSION "\n"); - - return spi_register_driver(&ks8995_driver); -} -module_init(ks8995_init); - -static void __exit ks8995_exit(void) -{ - spi_unregister_driver(&ks8995_driver); -} -module_exit(ks8995_exit); +module_spi_driver(ks8995_driver); MODULE_DESCRIPTION(DRV_DESC); MODULE_VERSION(DRV_VERSION); -- GitLab From 53edee2cfbcd869371cb720f1c00d85ba7f2566c Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 24 May 2013 00:59:47 +0000 Subject: [PATCH 0456/2900] bonding: allow xmit hash policy change while bond dev is up Since the xmit_hash_policy pointer is always valid and not dependent on anything, we can change it while the bond device is up and running. The only downside would be the out of order packets but that is a small price to pay. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index d7434e0a610e..3d269a52789c 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -383,20 +383,12 @@ static ssize_t bonding_store_xmit_hash(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); - if (bond->dev->flags & IFF_UP) { - pr_err("%s: Interface is up. Unable to update xmit policy.\n", - bond->dev->name); - ret = -EPERM; - goto out; - } - new_value = bond_parse_parm(buf, xmit_hashtype_tbl); if (new_value < 0) { pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n", bond->dev->name, (int)strlen(buf) - 1, buf); ret = -EINVAL; - goto out; } else { bond->params.xmit_policy = new_value; bond_set_mode_ops(bond, bond->params.mode); @@ -404,7 +396,7 @@ static ssize_t bonding_store_xmit_hash(struct device *d, bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value); } -out: + return ret; } static DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, -- GitLab From 3dd17edea018bf37ca1c33685ca0256270ccdb2c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 24 May 2013 07:05:59 +0000 Subject: [PATCH 0457/2900] doc:networking: Fix typo in documentation/networking Correct spelling typo Signed-off-by: Masanari Iida Signed-off-by: David S. Miller --- Documentation/networking/ifenslave.c | 2 +- Documentation/networking/ip-sysctl.txt | 2 +- Documentation/networking/netlink_mmap.txt | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index ac5debb2f16c..9f6a8fff9a78 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c @@ -501,7 +501,7 @@ int main(int argc, char *argv[]) static short mif_flags; -/* Get the inteface configuration from the kernel. */ +/* Get the interface configuration from the kernel. */ static int if_getconfig(char *ifname) { struct ifreq ifr; diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index f98ca633b528..398d0fb1dd0e 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -183,7 +183,7 @@ tcp_early_retrans - INTEGER for triggering fast retransmit when the amount of outstanding data is small and when no previously unsent data can be transmitted (such that limited transmit could be used). Also controls the use of - Tail loss probe (TLP) that converts RTOs occuring due to tail + Tail loss probe (TLP) that converts RTOs occurring due to tail losses into fast recovery (draft-dukkipati-tcpm-tcp-loss-probe-01). Possible values: 0 disables ER diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt index 1c2dab409625..e6088baf109d 100644 --- a/Documentation/networking/netlink_mmap.txt +++ b/Documentation/networking/netlink_mmap.txt @@ -54,7 +54,7 @@ it will use an allocated socket buffer as usual and the contents will be copied to the ring on transmission, nullifying most of the performance gains. Dumps of kernel databases automatically support memory mapped I/O. -Conversion of the transmit path involves changing message contruction to +Conversion of the transmit path involves changing message construction to use memory from the TX ring instead of (usually) a buffer declared on the stack and setting up the frame header approriately. Optionally poll() can be used to wait for free frames in the TX ring. @@ -65,8 +65,8 @@ Structured and definitions for using memory mapped I/O are contained in RX and TX rings ---------------- -Each ring contains a number of continous memory blocks, containing frames of -fixed size dependant on the parameters used for ring setup. +Each ring contains a number of continuous memory blocks, containing frames of +fixed size dependent on the parameters used for ring setup. Ring: [ block 0 ] [ frame 0 ] @@ -80,7 +80,7 @@ Ring: [ block 0 ] [ frame 2 * n + 1 ] The blocks are only visible to the kernel, from the point of view of user-space -the ring just contains the frames in a continous memory zone. +the ring just contains the frames in a continuous memory zone. The ring parameters used for setting up the ring are defined as follows: @@ -91,7 +91,7 @@ struct nl_mmap_req { unsigned int nm_frame_nr; }; -Frames are grouped into blocks, where each block is a continous region of memory +Frames are grouped into blocks, where each block is a continuous region of memory and holds nm_block_size / nm_frame_size frames. The total number of frames in the ring is nm_frame_nr. The following invariants hold: @@ -113,8 +113,8 @@ Some parameters are constrained, specifically: - nm_frame_nr must equal the actual number of frames as specified above. -When the kernel can't allocate phsyically continous memory for a ring block, -it will fall back to use physically discontinous memory. This might affect +When the kernel can't allocate phsyically continuous memory for a ring block, +it will fall back to use physically discontinuous memory. This might affect performance negatively, in order to avoid this the nm_frame_size parameter should be chosen to be as small as possible for the required frame size and the number of blocks should be increased instead. -- GitLab From b1098bbe1b24d5d90cff92fbd716d2ef4bed2cff Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 27 May 2013 15:49:16 +0000 Subject: [PATCH 0458/2900] bonding: remove ifenslave.c from kernel source As Stephen proposed: Since bonding supports configuration via iproute (netlink) and sysfs, I think it is time to purge the old ifenslave code out of Documentation/networking and update the documentation. Suggested-by: Stephen Hemminger Cc: Stephen Hemminger Cc: Jay Vosburgh Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- Documentation/networking/.gitignore | 1 - Documentation/networking/00-INDEX | 2 - Documentation/networking/Makefile | 5 - Documentation/networking/bonding.txt | 54 +- Documentation/networking/ifenslave.c | 1105 -------------------------- 5 files changed, 10 insertions(+), 1157 deletions(-) delete mode 100644 Documentation/networking/ifenslave.c diff --git a/Documentation/networking/.gitignore b/Documentation/networking/.gitignore index 286a5680f490..e69de29bb2d1 100644 --- a/Documentation/networking/.gitignore +++ b/Documentation/networking/.gitignore @@ -1 +0,0 @@ -ifenslave diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index 258d9b92c36f..32dfbd924121 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -88,8 +88,6 @@ gianfar.txt - Gianfar Ethernet Driver. ieee802154.txt - Linux IEEE 802.15.4 implementation, API and drivers -ifenslave.c - - Configure network interfaces for parallel routing (bonding). igb.txt - README for the Intel Gigabit Ethernet Driver (igb). igbvf.txt diff --git a/Documentation/networking/Makefile b/Documentation/networking/Makefile index 24c308dd3fd1..0aa1ac98fc2b 100644 --- a/Documentation/networking/Makefile +++ b/Documentation/networking/Makefile @@ -1,11 +1,6 @@ # kbuild trick to avoid linker error. Can be omitted if a module is built. obj- := dummy.o -# List of programs to build -hostprogs-y := ifenslave - -HOSTCFLAGS_ifenslave.o += -I$(objtree)/usr/include - # Tell kbuild to always build the programs always := $(hostprogs-y) diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index 10a015c384b8..e7454fcc9176 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -104,8 +104,7 @@ Table of Contents ============================== Most popular distro kernels ship with the bonding driver -already available as a module and the ifenslave user level control -program installed and ready for use. If your distro does not, or you +already available as a module. If your distro does not, or you have need to compile bonding from source (e.g., configuring and installing a mainline kernel from kernel.org), you'll need to perform the following steps: @@ -124,46 +123,13 @@ device support" section. It is recommended that you configure the driver as module since it is currently the only way to pass parameters to the driver or configure more than one bonding device. - Build and install the new kernel and modules, then continue -below to install ifenslave. + Build and install the new kernel and modules. -1.2 Install ifenslave Control Utility +1.2 Bonding Control Utility ------------------------------------- - The ifenslave user level control program is included in the -kernel source tree, in the file Documentation/networking/ifenslave.c. -It is generally recommended that you use the ifenslave that -corresponds to the kernel that you are using (either from the same -source tree or supplied with the distro), however, ifenslave -executables from older kernels should function (but features newer -than the ifenslave release are not supported). Running an ifenslave -that is newer than the kernel is not supported, and may or may not -work. - - To install ifenslave, do the following: - -# gcc -Wall -O -I/usr/src/linux/include ifenslave.c -o ifenslave -# cp ifenslave /sbin/ifenslave - - If your kernel source is not in "/usr/src/linux," then replace -"/usr/src/linux/include" in the above with the location of your kernel -source include directory. - - You may wish to back up any existing /sbin/ifenslave, or, for -testing or informal use, tag the ifenslave to the kernel version -(e.g., name the ifenslave executable /sbin/ifenslave-2.6.10). - -IMPORTANT NOTE: - - If you omit the "-I" or specify an incorrect directory, you -may end up with an ifenslave that is incompatible with the kernel -you're trying to build it for. Some distros (e.g., Red Hat from 7.1 -onwards) do not have /usr/include/linux symbolically linked to the -default kernel source include directory. - -SECOND IMPORTANT NOTE: - If you plan to configure bonding using sysfs or using the -/etc/network/interfaces file, you do not need to use ifenslave. + It is recommended to configure bonding via iproute2 (netlink) +or sysfs, the old ifenslave control utility is obsolete. 2. Bonding Driver Options ========================= @@ -851,7 +817,7 @@ resend_igmp ============================== You can configure bonding using either your distro's network -initialization scripts, or manually using either ifenslave or the +initialization scripts, or manually using either iproute2 or the sysfs interface. Distros generally use one of three packages for the network initialization scripts: initscripts, sysconfig or interfaces. Recent versions of these packages have support for bonding, while older @@ -1160,7 +1126,7 @@ not support this method for specifying multiple bonding interfaces; for those instances, see the "Configuring Multiple Bonds Manually" section, below. -3.3 Configuring Bonding Manually with Ifenslave +3.3 Configuring Bonding Manually with iproute2 ----------------------------------------------- This section applies to distros whose network initialization @@ -1171,7 +1137,7 @@ version 8. The general method for these systems is to place the bonding module parameters into a config file in /etc/modprobe.d/ (as appropriate for the installed distro), then add modprobe and/or -ifenslave commands to the system's global init script. The name of +`ip link` commands to the system's global init script. The name of the global init script differs; for sysconfig, it is /etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local. @@ -1183,8 +1149,8 @@ reboots, edit the appropriate file (/etc/init.d/boot.local or modprobe bonding mode=balance-alb miimon=100 modprobe e100 ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up -ifenslave bond0 eth0 -ifenslave bond0 eth1 +ip link set eth0 master bond0 +ip link set eth1 master bond0 Replace the example bonding module parameters and bond0 network configuration (IP address, netmask, etc) with the appropriate diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c deleted file mode 100644 index 9f6a8fff9a78..000000000000 --- a/Documentation/networking/ifenslave.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* Mode: C; - * ifenslave.c: Configure network interfaces for parallel routing. - * - * This program controls the Linux implementation of running multiple - * network interfaces in parallel. - * - * Author: Donald Becker - * Copyright 1994-1996 Donald Becker - * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation. - * - * The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - * Center of Excellence in Space Data and Information Sciences - * Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - * - * Changes : - * - 2000/10/02 Willy Tarreau : - * - few fixes. Master's MAC address is now correctly taken from - * the first device when not previously set ; - * - detach support : call BOND_RELEASE to detach an enslaved interface. - * - give a mini-howto from command-line help : # ifenslave -h - * - * - 2001/02/16 Chad N. Tindel : - * - Master is now brought down before setting the MAC address. In - * the 2.4 kernel you can't change the MAC address while the device is - * up because you get EBUSY. - * - * - 2001/09/13 Takao Indoh - * - Added the ability to change the active interface on a mode 1 bond - * at runtime. - * - * - 2001/10/23 Chad N. Tindel : - * - No longer set the MAC address of the master. The bond device will - * take care of this itself - * - Try the SIOC*** versions of the bonding ioctls before using the - * old versions - * - 2002/02/18 Erik Habbinga : - * - ifr2.ifr_flags was not initialized in the hwaddr_notset case, - * SIOCGIFFLAGS now called before hwaddr_notset test - * - * - 2002/10/31 Tony Cureington : - * - If the master does not have a hardware address when the first slave - * is enslaved, the master is assigned the hardware address of that - * slave - there is a comment in bonding.c stating "ifenslave takes - * care of this now." This corrects the problem of slaves having - * different hardware addresses in active-backup mode when - * multiple interfaces are specified on a single ifenslave command - * (ifenslave bond0 eth0 eth1). - * - * - 2003/03/18 - Tsippy Mendelson and - * Shmulik Hen - * - Moved setting the slave's mac address and openning it, from - * the application to the driver. This enables support of modes - * that need to use the unique mac address of each slave. - * The driver also takes care of closing the slave and restoring its - * original mac address upon release. - * In addition, block possibility of enslaving before the master is up. - * This prevents putting the system in an undefined state. - * - * - 2003/05/01 - Amir Noam - * - Added ABI version control to restore compatibility between - * new/old ifenslave and new/old bonding. - * - Prevent adding an adapter that is already a slave. - * Fixes the problem of stalling the transmission and leaving - * the slave in a down state. - * - * - 2003/05/01 - Shmulik Hen - * - Prevent enslaving if the bond device is down. - * Fixes the problem of leaving the system in unstable state and - * halting when trying to remove the module. - * - Close socket on all abnormal exists. - * - Add versioning scheme that follows that of the bonding driver. - * current version is 1.0.0 as a base line. - * - * - 2003/05/22 - Jay Vosburgh - * - ifenslave -c was broken; it's now fixed - * - Fixed problem with routes vanishing from master during enslave - * processing. - * - * - 2003/05/27 - Amir Noam - * - Fix backward compatibility issues: - * For drivers not using ABI versions, slave was set down while - * it should be left up before enslaving. - * Also, master was not set down and the default set_mac_address() - * would fail and generate an error message in the system log. - * - For opt_c: slave should not be set to the master's setting - * while it is running. It was already set during enslave. To - * simplify things, it is now handled separately. - * - * - 2003/12/01 - Shmulik Hen - * - Code cleanup and style changes - * set version to 1.1.0 - */ - -#define APP_VERSION "1.1.0" -#define APP_RELDATE "December 1, 2003" -#define APP_NAME "ifenslave" - -static char *version = -APP_NAME ".c:v" APP_VERSION " (" APP_RELDATE ")\n" -"o Donald Becker (becker@cesdis.gsfc.nasa.gov).\n" -"o Detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n" -"o 2.4 kernel support added on 2001/02/16 by Chad N. Tindel\n" -" (ctindel at ieee dot org).\n"; - -static const char *usage_msg = -"Usage: ifenslave [-f] [...]\n" -" ifenslave -d [...]\n" -" ifenslave -c \n" -" ifenslave --help\n"; - -static const char *help_msg = -"\n" -" To create a bond device, simply follow these three steps :\n" -" - ensure that the required drivers are properly loaded :\n" -" # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n" -" - assign an IP address to the bond device :\n" -" # ifconfig bond0 netmask broadcast \n" -" - attach all the interfaces you need to the bond device :\n" -" # ifenslave [{-f|--force}] bond0 eth0 [eth1 [eth2]...]\n" -" If bond0 didn't have a MAC address, it will take eth0's. Then, all\n" -" interfaces attached AFTER this assignment will get the same MAC addr.\n" -" (except for ALB/TLB modes)\n" -"\n" -" To set the bond device down and automatically release all the slaves :\n" -" # ifconfig bond0 down\n" -"\n" -" To detach a dead interface without setting the bond device down :\n" -" # ifenslave {-d|--detach} bond0 eth0 [eth1 [eth2]...]\n" -"\n" -" To change active slave :\n" -" # ifenslave {-c|--change-active} bond0 eth0\n" -"\n" -" To show master interface info\n" -" # ifenslave bond0\n" -"\n" -" To show all interfaces info\n" -" # ifenslave {-a|--all-interfaces}\n" -"\n" -" To be more verbose\n" -" # ifenslave {-v|--verbose} ...\n" -"\n" -" # ifenslave {-u|--usage} Show usage\n" -" # ifenslave {-V|--version} Show version\n" -" # ifenslave {-h|--help} This message\n" -"\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef unsigned long long u64; /* hack, so we may include kernel's ethtool.h */ -typedef __uint32_t u32; /* ditto */ -typedef __uint16_t u16; /* ditto */ -typedef __uint8_t u8; /* ditto */ -#include - -struct option longopts[] = { - /* { name has_arg *flag val } */ - {"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */ - {"change-active", 0, 0, 'c'}, /* Change the active slave. */ - {"detach", 0, 0, 'd'}, /* Detach a slave interface. */ - {"force", 0, 0, 'f'}, /* Force the operation. */ - {"help", 0, 0, 'h'}, /* Give help */ - {"usage", 0, 0, 'u'}, /* Give usage */ - {"verbose", 0, 0, 'v'}, /* Report each action taken. */ - {"version", 0, 0, 'V'}, /* Emit version information. */ - { 0, 0, 0, 0} -}; - -/* Command-line flags. */ -unsigned int -opt_a = 0, /* Show-all-interfaces flag. */ -opt_c = 0, /* Change-active-slave flag. */ -opt_d = 0, /* Detach a slave interface. */ -opt_f = 0, /* Force the operation. */ -opt_h = 0, /* Help */ -opt_u = 0, /* Usage */ -opt_v = 0, /* Verbose flag. */ -opt_V = 0; /* Version */ - -int skfd = -1; /* AF_INET socket for ioctl() calls.*/ -int abi_ver = 0; /* userland - kernel ABI version */ -int hwaddr_set = 0; /* Master's hwaddr is set */ -int saved_errno; - -struct ifreq master_mtu, master_flags, master_hwaddr; -struct ifreq slave_mtu, slave_flags, slave_hwaddr; - -struct dev_ifr { - struct ifreq *req_ifr; - char *req_name; - int req_type; -}; - -struct dev_ifr master_ifra[] = { - {&master_mtu, "SIOCGIFMTU", SIOCGIFMTU}, - {&master_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, - {&master_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, - {NULL, "", 0} -}; - -struct dev_ifr slave_ifra[] = { - {&slave_mtu, "SIOCGIFMTU", SIOCGIFMTU}, - {&slave_flags, "SIOCGIFFLAGS", SIOCGIFFLAGS}, - {&slave_hwaddr, "SIOCGIFHWADDR", SIOCGIFHWADDR}, - {NULL, "", 0} -}; - -static void if_print(char *ifname); -static int get_drv_info(char *master_ifname); -static int get_if_settings(char *ifname, struct dev_ifr ifra[]); -static int get_slave_flags(char *slave_ifname); -static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr); -static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr); -static int set_slave_mtu(char *slave_ifname, int mtu); -static int set_if_flags(char *ifname, short flags); -static int set_if_up(char *ifname, short flags); -static int set_if_down(char *ifname, short flags); -static int clear_if_addr(char *ifname); -static int set_if_addr(char *master_ifname, char *slave_ifname); -static int change_active(char *master_ifname, char *slave_ifname); -static int enslave(char *master_ifname, char *slave_ifname); -static int release(char *master_ifname, char *slave_ifname); -#define v_print(fmt, args...) \ - if (opt_v) \ - fprintf(stderr, fmt, ## args ) - -int main(int argc, char *argv[]) -{ - char **spp, *master_ifname, *slave_ifname; - int c, i, rv; - int res = 0; - int exclusive = 0; - - while ((c = getopt_long(argc, argv, "acdfhuvV", longopts, 0)) != EOF) { - switch (c) { - case 'a': opt_a++; exclusive++; break; - case 'c': opt_c++; exclusive++; break; - case 'd': opt_d++; exclusive++; break; - case 'f': opt_f++; exclusive++; break; - case 'h': opt_h++; exclusive++; break; - case 'u': opt_u++; exclusive++; break; - case 'v': opt_v++; break; - case 'V': opt_V++; exclusive++; break; - - case '?': - fprintf(stderr, "%s", usage_msg); - res = 2; - goto out; - } - } - - /* options check */ - if (exclusive > 1) { - fprintf(stderr, "%s", usage_msg); - res = 2; - goto out; - } - - if (opt_v || opt_V) { - printf("%s", version); - if (opt_V) { - res = 0; - goto out; - } - } - - if (opt_u) { - printf("%s", usage_msg); - res = 0; - goto out; - } - - if (opt_h) { - printf("%s", usage_msg); - printf("%s", help_msg); - res = 0; - goto out; - } - - /* Open a basic socket */ - if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - res = 1; - goto out; - } - - if (opt_a) { - if (optind == argc) { - /* No remaining args */ - /* show all interfaces */ - if_print((char *)NULL); - goto out; - } else { - /* Just show usage */ - fprintf(stderr, "%s", usage_msg); - res = 2; - goto out; - } - } - - /* Copy the interface name */ - spp = argv + optind; - master_ifname = *spp++; - - if (master_ifname == NULL) { - fprintf(stderr, "%s", usage_msg); - res = 2; - goto out; - } - - /* exchange abi version with bonding module */ - res = get_drv_info(master_ifname); - if (res) { - fprintf(stderr, - "Master '%s': Error: handshake with driver failed. " - "Aborting\n", - master_ifname); - goto out; - } - - slave_ifname = *spp++; - - if (slave_ifname == NULL) { - if (opt_d || opt_c) { - fprintf(stderr, "%s", usage_msg); - res = 2; - goto out; - } - - /* A single arg means show the - * configuration for this interface - */ - if_print(master_ifname); - goto out; - } - - res = get_if_settings(master_ifname, master_ifra); - if (res) { - /* Probably a good reason not to go on */ - fprintf(stderr, - "Master '%s': Error: get settings failed: %s. " - "Aborting\n", - master_ifname, strerror(res)); - goto out; - } - - /* check if master is indeed a master; - * if not then fail any operation - */ - if (!(master_flags.ifr_flags & IFF_MASTER)) { - fprintf(stderr, - "Illegal operation; the specified interface '%s' " - "is not a master. Aborting\n", - master_ifname); - res = 1; - goto out; - } - - /* check if master is up; if not then fail any operation */ - if (!(master_flags.ifr_flags & IFF_UP)) { - fprintf(stderr, - "Illegal operation; the specified master interface " - "'%s' is not up.\n", - master_ifname); - res = 1; - goto out; - } - - /* Only for enslaving */ - if (!opt_c && !opt_d) { - sa_family_t master_family = master_hwaddr.ifr_hwaddr.sa_family; - unsigned char *hwaddr = - (unsigned char *)master_hwaddr.ifr_hwaddr.sa_data; - - /* The family '1' is ARPHRD_ETHER for ethernet. */ - if (master_family != 1 && !opt_f) { - fprintf(stderr, - "Illegal operation: The specified master " - "interface '%s' is not ethernet-like.\n " - "This program is designed to work with " - "ethernet-like network interfaces.\n " - "Use the '-f' option to force the " - "operation.\n", - master_ifname); - res = 1; - goto out; - } - - /* Check master's hw addr */ - for (i = 0; i < 6; i++) { - if (hwaddr[i] != 0) { - hwaddr_set = 1; - break; - } - } - - if (hwaddr_set) { - v_print("current hardware address of master '%s' " - "is %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "type %d\n", - master_ifname, - hwaddr[0], hwaddr[1], - hwaddr[2], hwaddr[3], - hwaddr[4], hwaddr[5], - master_family); - } - } - - /* Accepts only one slave */ - if (opt_c) { - /* change active slave */ - res = get_slave_flags(slave_ifname); - if (res) { - fprintf(stderr, - "Slave '%s': Error: get flags failed. " - "Aborting\n", - slave_ifname); - goto out; - } - res = change_active(master_ifname, slave_ifname); - if (res) { - fprintf(stderr, - "Master '%s', Slave '%s': Error: " - "Change active failed\n", - master_ifname, slave_ifname); - } - } else { - /* Accept multiple slaves */ - do { - if (opt_d) { - /* detach a slave interface from the master */ - rv = get_slave_flags(slave_ifname); - if (rv) { - /* Can't work with this slave. */ - /* remember the error and skip it*/ - fprintf(stderr, - "Slave '%s': Error: get flags " - "failed. Skipping\n", - slave_ifname); - res = rv; - continue; - } - rv = release(master_ifname, slave_ifname); - if (rv) { - fprintf(stderr, - "Master '%s', Slave '%s': Error: " - "Release failed\n", - master_ifname, slave_ifname); - res = rv; - } - } else { - /* attach a slave interface to the master */ - rv = get_if_settings(slave_ifname, slave_ifra); - if (rv) { - /* Can't work with this slave. */ - /* remember the error and skip it*/ - fprintf(stderr, - "Slave '%s': Error: get " - "settings failed: %s. " - "Skipping\n", - slave_ifname, strerror(rv)); - res = rv; - continue; - } - rv = enslave(master_ifname, slave_ifname); - if (rv) { - fprintf(stderr, - "Master '%s', Slave '%s': Error: " - "Enslave failed\n", - master_ifname, slave_ifname); - res = rv; - } - } - } while ((slave_ifname = *spp++) != NULL); - } - -out: - if (skfd >= 0) { - close(skfd); - } - - return res; -} - -static short mif_flags; - -/* Get the interface configuration from the kernel. */ -static int if_getconfig(char *ifname) -{ - struct ifreq ifr; - int metric, mtu; /* Parameters of the master interface. */ - struct sockaddr dstaddr, broadaddr, netmask; - unsigned char *hwaddr; - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) - return -1; - mif_flags = ifr.ifr_flags; - printf("The result of SIOCGIFFLAGS on %s is %x.\n", - ifname, ifr.ifr_flags); - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) - return -1; - printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n", - ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1], - ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]); - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) - return -1; - - /* Gotta convert from 'char' to unsigned for printf(). */ - hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data; - printf("The result of SIOCGIFHWADDR is type %d " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", - ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1], - hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) { - metric = 0; - } else - metric = ifr.ifr_metric; - printf("The result of SIOCGIFMETRIC is %d\n", metric); - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0) - mtu = 0; - else - mtu = ifr.ifr_mtu; - printf("The result of SIOCGIFMTU is %d\n", mtu); - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) { - memset(&dstaddr, 0, sizeof(struct sockaddr)); - } else - dstaddr = ifr.ifr_dstaddr; - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) { - memset(&broadaddr, 0, sizeof(struct sockaddr)); - } else - broadaddr = ifr.ifr_broadaddr; - - strcpy(ifr.ifr_name, ifname); - if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) { - memset(&netmask, 0, sizeof(struct sockaddr)); - } else - netmask = ifr.ifr_netmask; - - return 0; -} - -static void if_print(char *ifname) -{ - char buff[1024]; - struct ifconf ifc; - struct ifreq *ifr; - int i; - - if (ifname == (char *)NULL) { - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { - perror("SIOCGIFCONF failed"); - return; - } - - ifr = ifc.ifc_req; - for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { - if (if_getconfig(ifr->ifr_name) < 0) { - fprintf(stderr, - "%s: unknown interface.\n", - ifr->ifr_name); - continue; - } - - if (((mif_flags & IFF_UP) == 0) && !opt_a) continue; - /*ife_print(&ife);*/ - } - } else { - if (if_getconfig(ifname) < 0) { - fprintf(stderr, - "%s: unknown interface.\n", ifname); - } - } -} - -static int get_drv_info(char *master_ifname) -{ - struct ifreq ifr; - struct ethtool_drvinfo info; - char *endptr; - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - ifr.ifr_data = (caddr_t)&info; - - info.cmd = ETHTOOL_GDRVINFO; - strncpy(info.driver, "ifenslave", 32); - snprintf(info.fw_version, 32, "%d", BOND_ABI_VERSION); - - if (ioctl(skfd, SIOCETHTOOL, &ifr) < 0) { - if (errno == EOPNOTSUPP) { - goto out; - } - - saved_errno = errno; - v_print("Master '%s': Error: get bonding info failed %s\n", - master_ifname, strerror(saved_errno)); - return 1; - } - - abi_ver = strtoul(info.fw_version, &endptr, 0); - if (*endptr) { - v_print("Master '%s': Error: got invalid string as an ABI " - "version from the bonding module\n", - master_ifname); - return 1; - } - -out: - v_print("ABI ver is %d\n", abi_ver); - - return 0; -} - -static int change_active(char *master_ifname, char *slave_ifname) -{ - struct ifreq ifr; - int res = 0; - - if (!(slave_flags.ifr_flags & IFF_SLAVE)) { - fprintf(stderr, - "Illegal operation: The specified slave interface " - "'%s' is not a slave\n", - slave_ifname); - return 1; - } - - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &ifr) < 0) && - (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &ifr) < 0)) { - saved_errno = errno; - v_print("Master '%s': Error: SIOCBONDCHANGEACTIVE failed: " - "%s\n", - master_ifname, strerror(saved_errno)); - res = 1; - } - - return res; -} - -static int enslave(char *master_ifname, char *slave_ifname) -{ - struct ifreq ifr; - int res = 0; - - if (slave_flags.ifr_flags & IFF_SLAVE) { - fprintf(stderr, - "Illegal operation: The specified slave interface " - "'%s' is already a slave\n", - slave_ifname); - return 1; - } - - res = set_if_down(slave_ifname, slave_flags.ifr_flags); - if (res) { - fprintf(stderr, - "Slave '%s': Error: bring interface down failed\n", - slave_ifname); - return res; - } - - if (abi_ver < 2) { - /* Older bonding versions would panic if the slave has no IP - * address, so get the IP setting from the master. - */ - set_if_addr(master_ifname, slave_ifname); - } else { - res = clear_if_addr(slave_ifname); - if (res) { - fprintf(stderr, - "Slave '%s': Error: clear address failed\n", - slave_ifname); - return res; - } - } - - if (master_mtu.ifr_mtu != slave_mtu.ifr_mtu) { - res = set_slave_mtu(slave_ifname, master_mtu.ifr_mtu); - if (res) { - fprintf(stderr, - "Slave '%s': Error: set MTU failed\n", - slave_ifname); - return res; - } - } - - if (hwaddr_set) { - /* Master already has an hwaddr - * so set it's hwaddr to the slave - */ - if (abi_ver < 1) { - /* The driver is using an old ABI, so - * the application sets the slave's - * hwaddr - */ - res = set_slave_hwaddr(slave_ifname, - &(master_hwaddr.ifr_hwaddr)); - if (res) { - fprintf(stderr, - "Slave '%s': Error: set hw address " - "failed\n", - slave_ifname); - goto undo_mtu; - } - - /* For old ABI the application needs to bring the - * slave back up - */ - res = set_if_up(slave_ifname, slave_flags.ifr_flags); - if (res) { - fprintf(stderr, - "Slave '%s': Error: bring interface " - "down failed\n", - slave_ifname); - goto undo_slave_mac; - } - } - /* The driver is using a new ABI, - * so the driver takes care of setting - * the slave's hwaddr and bringing - * it up again - */ - } else { - /* No hwaddr for master yet, so - * set the slave's hwaddr to it - */ - if (abi_ver < 1) { - /* For old ABI, the master needs to be - * down before setting its hwaddr - */ - res = set_if_down(master_ifname, master_flags.ifr_flags); - if (res) { - fprintf(stderr, - "Master '%s': Error: bring interface " - "down failed\n", - master_ifname); - goto undo_mtu; - } - } - - res = set_master_hwaddr(master_ifname, - &(slave_hwaddr.ifr_hwaddr)); - if (res) { - fprintf(stderr, - "Master '%s': Error: set hw address " - "failed\n", - master_ifname); - goto undo_mtu; - } - - if (abi_ver < 1) { - /* For old ABI, bring the master - * back up - */ - res = set_if_up(master_ifname, master_flags.ifr_flags); - if (res) { - fprintf(stderr, - "Master '%s': Error: bring interface " - "up failed\n", - master_ifname); - goto undo_master_mac; - } - } - - hwaddr_set = 1; - } - - /* Do the real thing */ - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDENSLAVE, &ifr) < 0) && - (ioctl(skfd, BOND_ENSLAVE_OLD, &ifr) < 0)) { - saved_errno = errno; - v_print("Master '%s': Error: SIOCBONDENSLAVE failed: %s\n", - master_ifname, strerror(saved_errno)); - res = 1; - } - - if (res) { - goto undo_master_mac; - } - - return 0; - -/* rollback (best effort) */ -undo_master_mac: - set_master_hwaddr(master_ifname, &(master_hwaddr.ifr_hwaddr)); - hwaddr_set = 0; - goto undo_mtu; -undo_slave_mac: - set_slave_hwaddr(slave_ifname, &(slave_hwaddr.ifr_hwaddr)); -undo_mtu: - set_slave_mtu(slave_ifname, slave_mtu.ifr_mtu); - return res; -} - -static int release(char *master_ifname, char *slave_ifname) -{ - struct ifreq ifr; - int res = 0; - - if (!(slave_flags.ifr_flags & IFF_SLAVE)) { - fprintf(stderr, - "Illegal operation: The specified slave interface " - "'%s' is not a slave\n", - slave_ifname); - return 1; - } - - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - strncpy(ifr.ifr_slave, slave_ifname, IFNAMSIZ); - if ((ioctl(skfd, SIOCBONDRELEASE, &ifr) < 0) && - (ioctl(skfd, BOND_RELEASE_OLD, &ifr) < 0)) { - saved_errno = errno; - v_print("Master '%s': Error: SIOCBONDRELEASE failed: %s\n", - master_ifname, strerror(saved_errno)); - return 1; - } else if (abi_ver < 1) { - /* The driver is using an old ABI, so we'll set the interface - * down to avoid any conflicts due to same MAC/IP - */ - res = set_if_down(slave_ifname, slave_flags.ifr_flags); - if (res) { - fprintf(stderr, - "Slave '%s': Error: bring interface " - "down failed\n", - slave_ifname); - } - } - - /* set to default mtu */ - set_slave_mtu(slave_ifname, 1500); - - return res; -} - -static int get_if_settings(char *ifname, struct dev_ifr ifra[]) -{ - int i; - int res = 0; - - for (i = 0; ifra[i].req_ifr; i++) { - strncpy(ifra[i].req_ifr->ifr_name, ifname, IFNAMSIZ); - res = ioctl(skfd, ifra[i].req_type, ifra[i].req_ifr); - if (res < 0) { - saved_errno = errno; - v_print("Interface '%s': Error: %s failed: %s\n", - ifname, ifra[i].req_name, - strerror(saved_errno)); - - return saved_errno; - } - } - - return 0; -} - -static int get_slave_flags(char *slave_ifname) -{ - int res = 0; - - strncpy(slave_flags.ifr_name, slave_ifname, IFNAMSIZ); - res = ioctl(skfd, SIOCGIFFLAGS, &slave_flags); - if (res < 0) { - saved_errno = errno; - v_print("Slave '%s': Error: SIOCGIFFLAGS failed: %s\n", - slave_ifname, strerror(saved_errno)); - } else { - v_print("Slave %s: flags %04X.\n", - slave_ifname, slave_flags.ifr_flags); - } - - return res; -} - -static int set_master_hwaddr(char *master_ifname, struct sockaddr *hwaddr) -{ - unsigned char *addr = (unsigned char *)hwaddr->sa_data; - struct ifreq ifr; - int res = 0; - - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); - res = ioctl(skfd, SIOCSIFHWADDR, &ifr); - if (res < 0) { - saved_errno = errno; - v_print("Master '%s': Error: SIOCSIFHWADDR failed: %s\n", - master_ifname, strerror(saved_errno)); - return res; - } else { - v_print("Master '%s': hardware address set to " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", - master_ifname, addr[0], addr[1], addr[2], - addr[3], addr[4], addr[5]); - } - - return res; -} - -static int set_slave_hwaddr(char *slave_ifname, struct sockaddr *hwaddr) -{ - unsigned char *addr = (unsigned char *)hwaddr->sa_data; - struct ifreq ifr; - int res = 0; - - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); - memcpy(&(ifr.ifr_hwaddr), hwaddr, sizeof(struct sockaddr)); - res = ioctl(skfd, SIOCSIFHWADDR, &ifr); - if (res < 0) { - saved_errno = errno; - - v_print("Slave '%s': Error: SIOCSIFHWADDR failed: %s\n", - slave_ifname, strerror(saved_errno)); - - if (saved_errno == EBUSY) { - v_print(" The device is busy: it must be idle " - "before running this command.\n"); - } else if (saved_errno == EOPNOTSUPP) { - v_print(" The device does not support setting " - "the MAC address.\n" - " Your kernel likely does not support slave " - "devices.\n"); - } else if (saved_errno == EINVAL) { - v_print(" The device's address type does not match " - "the master's address type.\n"); - } - return res; - } else { - v_print("Slave '%s': hardware address set to " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", - slave_ifname, addr[0], addr[1], addr[2], - addr[3], addr[4], addr[5]); - } - - return res; -} - -static int set_slave_mtu(char *slave_ifname, int mtu) -{ - struct ifreq ifr; - int res = 0; - - ifr.ifr_mtu = mtu; - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); - - res = ioctl(skfd, SIOCSIFMTU, &ifr); - if (res < 0) { - saved_errno = errno; - v_print("Slave '%s': Error: SIOCSIFMTU failed: %s\n", - slave_ifname, strerror(saved_errno)); - } else { - v_print("Slave '%s': MTU set to %d.\n", slave_ifname, mtu); - } - - return res; -} - -static int set_if_flags(char *ifname, short flags) -{ - struct ifreq ifr; - int res = 0; - - ifr.ifr_flags = flags; - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - - res = ioctl(skfd, SIOCSIFFLAGS, &ifr); - if (res < 0) { - saved_errno = errno; - v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n", - ifname, strerror(saved_errno)); - } else { - v_print("Interface '%s': flags set to %04X.\n", ifname, flags); - } - - return res; -} - -static int set_if_up(char *ifname, short flags) -{ - return set_if_flags(ifname, flags | IFF_UP); -} - -static int set_if_down(char *ifname, short flags) -{ - return set_if_flags(ifname, flags & ~IFF_UP); -} - -static int clear_if_addr(char *ifname) -{ - struct ifreq ifr; - int res = 0; - - strncpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_addr.sa_family = AF_INET; - memset(ifr.ifr_addr.sa_data, 0, sizeof(ifr.ifr_addr.sa_data)); - - res = ioctl(skfd, SIOCSIFADDR, &ifr); - if (res < 0) { - saved_errno = errno; - v_print("Interface '%s': Error: SIOCSIFADDR failed: %s\n", - ifname, strerror(saved_errno)); - } else { - v_print("Interface '%s': address cleared\n", ifname); - } - - return res; -} - -static int set_if_addr(char *master_ifname, char *slave_ifname) -{ - struct ifreq ifr; - int res; - unsigned char *ipaddr; - int i; - struct { - char *req_name; - char *desc; - int g_ioctl; - int s_ioctl; - } ifra[] = { - {"IFADDR", "addr", SIOCGIFADDR, SIOCSIFADDR}, - {"DSTADDR", "destination addr", SIOCGIFDSTADDR, SIOCSIFDSTADDR}, - {"BRDADDR", "broadcast addr", SIOCGIFBRDADDR, SIOCSIFBRDADDR}, - {"NETMASK", "netmask", SIOCGIFNETMASK, SIOCSIFNETMASK}, - {NULL, NULL, 0, 0}, - }; - - for (i = 0; ifra[i].req_name; i++) { - strncpy(ifr.ifr_name, master_ifname, IFNAMSIZ); - res = ioctl(skfd, ifra[i].g_ioctl, &ifr); - if (res < 0) { - int saved_errno = errno; - - v_print("Interface '%s': Error: SIOCG%s failed: %s\n", - master_ifname, ifra[i].req_name, - strerror(saved_errno)); - - ifr.ifr_addr.sa_family = AF_INET; - memset(ifr.ifr_addr.sa_data, 0, - sizeof(ifr.ifr_addr.sa_data)); - } - - strncpy(ifr.ifr_name, slave_ifname, IFNAMSIZ); - res = ioctl(skfd, ifra[i].s_ioctl, &ifr); - if (res < 0) { - int saved_errno = errno; - - v_print("Interface '%s': Error: SIOCS%s failed: %s\n", - slave_ifname, ifra[i].req_name, - strerror(saved_errno)); - - } - - ipaddr = (unsigned char *)ifr.ifr_addr.sa_data; - v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n", - slave_ifname, ifra[i].desc, - ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - } - - return 0; -} - -/* - * Local variables: - * version-control: t - * kept-new-versions: 5 - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave" - * End: - */ - -- GitLab From 24c7a381720843f17efb42de81f7e85aefd6f616 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 28 May 2013 06:22:32 +0000 Subject: [PATCH 0459/2900] thermal: cpu_cooling: fix 'descend' check in get_property() The variable 'descend' is initialized as -1 in function get_property(), and will never get any chance to be updated by the following code. if (freq != CPUFREQ_ENTRY_INVALID && descend != -1) descend = !!(freq > table[i].frequency); This makes function get_property() return the wrong frequency for given cooling level if the frequency table is sorted in ascending. Fix it by correcting the 'descend' check in if-condition to 'descend == -1'. Signed-off-by: Shawn Guo Signed-off-by: Zhang Rui --- drivers/thermal/cpu_cooling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index c94bf2e5de62..82e15dbb3ac7 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -167,7 +167,7 @@ static int get_property(unsigned int cpu, unsigned long input, continue; /* get the frequency order */ - if (freq != CPUFREQ_ENTRY_INVALID && descend != -1) + if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) descend = !!(freq > table[i].frequency); freq = table[i].frequency; -- GitLab From 351638e7deeed2ec8ce451b53d33921b3da68f83 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 28 May 2013 01:30:21 +0000 Subject: [PATCH 0460/2900] net: pass info struct via netdevice notifier So far, only net_device * could be passed along with netdevice notifier event. This patch provides a possibility to pass custom structure able to provide info that event listener needs to know. Signed-off-by: Jiri Pirko v2->v3: fix typo on simeth shortened dev_getter shortened notifier_info struct name v1->v2: fix notifier_call parameter in call_netdevice_notifier() Signed-off-by: David S. Miller --- arch/ia64/hp/sim/simeth.c | 2 +- arch/mips/txx9/generic/setup_tx4939.c | 3 +- drivers/infiniband/core/cma.c | 4 +- drivers/infiniband/hw/mlx4/main.c | 2 +- drivers/net/bonding/bond_main.c | 2 +- drivers/net/can/led.c | 4 +- drivers/net/ethernet/broadcom/cnic.c | 2 +- drivers/net/ethernet/marvell/skge.c | 2 +- drivers/net/ethernet/marvell/sky2.c | 2 +- .../ethernet/qlogic/netxen/netxen_nic_main.c | 2 +- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/hamradio/bpqether.c | 7 ++- drivers/net/macvlan.c | 2 +- drivers/net/macvtap.c | 2 +- drivers/net/netconsole.c | 5 +- drivers/net/ppp/pppoe.c | 2 +- drivers/net/team/team.c | 2 +- drivers/net/wan/dlci.c | 2 +- drivers/net/wan/hdlc.c | 2 +- drivers/net/wan/lapbether.c | 2 +- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/fcoe/fcoe_transport.c | 2 +- drivers/staging/csr/netdev.c | 2 +- .../ft1000/ft1000-pcmcia/ft1000_proc.c | 2 +- .../staging/ft1000/ft1000-usb/ft1000_proc.c | 2 +- drivers/staging/silicom/bpctl_mod.c | 2 +- include/linux/netdevice.h | 13 +++++ net/8021q/vlan.c | 2 +- net/appletalk/aarp.c | 2 +- net/appletalk/ddp.c | 2 +- net/atm/clip.c | 4 +- net/atm/mpc.c | 6 +- net/ax25/af_ax25.c | 6 +- net/batman-adv/hard-interface.c | 2 +- net/bridge/br_notify.c | 2 +- net/caif/caif_dev.c | 4 +- net/caif/caif_usb.c | 4 +- net/can/af_can.c | 4 +- net/can/bcm.c | 4 +- net/can/gw.c | 4 +- net/can/raw.c | 4 +- net/core/dev.c | 56 +++++++++++++++---- net/core/drop_monitor.c | 4 +- net/core/dst.c | 2 +- net/core/fib_rules.c | 4 +- net/core/netprio_cgroup.c | 2 +- net/core/pktgen.c | 2 +- net/core/rtnetlink.c | 2 +- net/decnet/af_decnet.c | 4 +- net/ieee802154/6lowpan.c | 5 +- net/ipv4/arp.c | 2 +- net/ipv4/devinet.c | 2 +- net/ipv4/fib_frontend.c | 2 +- net/ipv4/ipmr.c | 2 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 2 +- net/ipv6/addrconf.c | 4 +- net/ipv6/ip6mr.c | 2 +- net/ipv6/ndisc.c | 2 +- net/ipv6/netfilter/ip6t_MASQUERADE.c | 2 +- net/ipv6/route.c | 4 +- net/ipx/af_ipx.c | 2 +- net/iucv/af_iucv.c | 2 +- net/mac80211/iface.c | 5 +- net/netfilter/ipvs/ip_vs_ctl.c | 4 +- net/netfilter/nfnetlink_queue_core.c | 2 +- net/netfilter/xt_TEE.c | 2 +- net/netlabel/netlabel_unlabeled.c | 7 +-- net/netrom/af_netrom.c | 2 +- net/openvswitch/dp_notify.c | 2 +- net/packet/af_packet.c | 5 +- net/phonet/pn_dev.c | 4 +- net/rose/af_rose.c | 6 +- net/sched/act_mirred.c | 2 +- net/tipc/eth_media.c | 4 +- net/tipc/ib_media.c | 4 +- net/wireless/core.c | 5 +- net/x25/af_x25.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- security/selinux/netif.c | 2 +- 80 files changed, 172 insertions(+), 127 deletions(-) diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index c13064e422df..d1b04c4c95e3 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -268,7 +268,7 @@ static __inline__ int dev_is_ethdev(struct net_device *dev) static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct simeth_local *local; struct in_device *in_dev; struct in_ifaddr **ifap = NULL; diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index 729a50991780..b7eccbd17bf7 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -331,7 +331,8 @@ static int tx4939_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) { __u64 bit = 0; if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0)) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 71c2c7116802..34fbc2f60a09 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3269,9 +3269,9 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id } static int cma_netdev_callback(struct notifier_block *self, unsigned long event, - void *ctx) + void *ptr) { - struct net_device *ndev = (struct net_device *)ctx; + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); struct cma_device *cma_dev; struct rdma_id_private *id_priv; int ret = NOTIFY_DONE; diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 23d734349d8e..a188d3178559 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1161,7 +1161,7 @@ static void netdev_removed(struct mlx4_ib_dev *dev, int port) static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct mlx4_ib_dev *ibdev; struct net_device *oldnd; struct mlx4_ib_iboe *iboe; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 29b846cbfb48..f4489d65bf33 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3277,7 +3277,7 @@ static int bond_slave_netdev_event(unsigned long event, static int bond_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *event_dev = (struct net_device *)ptr; + struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); pr_debug("event_dev: %s, event: %lx\n", event_dev ? event_dev->name : "None", diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c index f27fca65dc4a..a3d99a8fd2d1 100644 --- a/drivers/net/can/led.c +++ b/drivers/net/can/led.c @@ -88,9 +88,9 @@ EXPORT_SYMBOL_GPL(devm_can_led_init); /* NETDEV rename notifier to rename the associated led triggers too */ static int can_led_notifier(struct notifier_block *nb, unsigned long msg, - void *data) + void *ptr) { - struct net_device *netdev = data; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct can_priv *priv = safe_candev_priv(netdev); char name[CAN_LED_NAME_SZ]; diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 6b0dc131b20e..d78d4cf140ed 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -5622,7 +5622,7 @@ static void cnic_rcv_netevent(struct cnic_local *cp, unsigned long event, static int cnic_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *netdev = ptr; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct cnic_dev *dev; int new_dev = 0; diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 171f4b3dda07..c896079728e1 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3706,7 +3706,7 @@ static const struct file_operations skge_debug_fops = { static int skge_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct skge_port *skge; struct dentry *d; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index d175bbd3ffd3..e09a8c6f8536 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4642,7 +4642,7 @@ static const struct file_operations sky2_debug_fops = { static int sky2_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct sky2_port *sky2 = netdev_priv(dev); if (dev->netdev_ops->ndo_open != sky2_open || !sky2_debug) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index af951f343ff6..51e13d92761e 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -3311,7 +3311,7 @@ static int netxen_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netxen_adapter *adapter; - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *orig_dev = dev; struct net_device *slave; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index da82f2eb73b4..6bb56d43614b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -3530,7 +3530,7 @@ static int qlcnic_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct qlcnic_adapter *adapter; - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); recheck: if (dev == NULL) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 39e4cb39de29..46cc11d5e205 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2120,7 +2120,7 @@ static void efx_update_name(struct efx_nic *efx) static int efx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *net_dev = ptr; + struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); if (net_dev->netdev_ops == &efx_netdev_ops && event == NETDEV_CHANGENAME) diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 02de6c891670..f91bf0ddf031 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -103,7 +103,7 @@ static struct packet_type bpq_packet_type __read_mostly = { }; static struct notifier_block bpq_dev_notifier = { - .notifier_call =bpq_device_event, + .notifier_call = bpq_device_event, }; @@ -544,9 +544,10 @@ static void bpq_free_device(struct net_device *ndev) /* * Handle device status changes. */ -static int bpq_device_event(struct notifier_block *this,unsigned long event, void *ptr) +static int bpq_device_event(struct notifier_block *this, + unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 1c502bb0c916..edfddc5f61b4 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -921,7 +921,7 @@ static struct rtnl_link_ops macvlan_link_ops = { static int macvlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct macvlan_dev *vlan, *next; struct macvlan_port *port; LIST_HEAD(list_kill); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 59e9605de316..68efb91a5633 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1053,7 +1053,7 @@ EXPORT_SYMBOL_GPL(macvtap_get_socket); static int macvtap_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct macvlan_dev *vlan; struct device *classdev; dev_t devt; diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 59ac143dec25..1d1d0a12765c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -653,12 +653,11 @@ static struct configfs_subsystem netconsole_subsys = { /* Handle network interface device notifications */ static int netconsole_netdev_event(struct notifier_block *this, - unsigned long event, - void *ptr) + unsigned long event, void *ptr) { unsigned long flags; struct netconsole_target *nt; - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); bool stopped = false; if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER || diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index bb07ba94c3aa..5f66e30d9823 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -338,7 +338,7 @@ static void pppoe_flush_dev(struct net_device *dev) static int pppoe_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); /* Only look at sockets that are using this specific device. */ switch (event) { diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 7c43261975bd..9273f48a512b 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2647,7 +2647,7 @@ static void team_port_change_check(struct team_port *port, bool linkup) static int team_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *) ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct team_port *port; port = team_port_get_rtnl(dev); diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 147614ed86aa..70ac59929f80 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -477,7 +477,7 @@ static void dlci_setup(struct net_device *dev) static int dlci_dev_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *) ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (dev_net(dev) != &init_net) return NOTIFY_DONE; diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index a0a932c63d0a..9c33ca918e19 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -99,7 +99,7 @@ static inline void hdlc_proto_stop(struct net_device *dev) static int hdlc_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); hdlc_device *hdlc; unsigned long flags; int on; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index a73b49eb87e3..a33a46fa88dd 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -370,7 +370,7 @@ static int lapbeth_device_event(struct notifier_block *this, unsigned long event, void *ptr) { struct lapbethdev *lapbeth; - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (dev_net(dev) != &init_net) return NOTIFY_DONE; diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 292b24f9bf93..ee721b6cbcdf 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1975,7 +1975,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, { struct fcoe_ctlr_device *cdev; struct fc_lport *lport = NULL; - struct net_device *netdev = ptr; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); struct fcoe_ctlr *ctlr; struct fcoe_interface *fcoe; struct fcoe_port *port; diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index f3a5a53e8631..01adbe0ec53b 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -704,7 +704,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) static int libfcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { - struct net_device *netdev = ptr; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); switch (event) { case NETDEV_UNREGISTER: diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c index a0177d998978..d49cdf84a496 100644 --- a/drivers/staging/csr/netdev.c +++ b/drivers/staging/csr/netdev.c @@ -2891,7 +2891,7 @@ void uf_net_get_name(struct net_device *dev, char *name, int len) */ static int uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) { - struct net_device *netdev = ptr; + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(netdev); unifi_priv_t *priv = NULL; static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c index 94e426e4d98b..b2330f1df7e7 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c @@ -164,7 +164,7 @@ static const struct file_operations ft1000_proc_fops = { static int ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ft1000_info *info; info = netdev_priv(dev); diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c index eca6f0292b4b..5ead942be680 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c @@ -166,7 +166,7 @@ static const struct file_operations ft1000_proc_fops = { static int ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ft1000_info *info; struct proc_dir_entry *ft1000_proc_file; diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index b7e570ccb759..c8ddb99e8526 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -133,7 +133,7 @@ static unsigned long str_to_hex(char *p); static int bp_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); static bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; int dev_num = 0, ret = 0, ret_d = 0, time_left = 0; /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 6b2bb460d1d7..13a34848b5e1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1599,6 +1599,19 @@ struct packet_offload { extern int register_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb); + +struct netdev_notifier_info { + struct net_device *dev; +}; + +static inline struct net_device * +netdev_notifier_info_to_dev(const struct netdev_notifier_info *info) +{ + return info->dev; +} + +extern int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev, + struct netdev_notifier_info *info); extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9424f3718ea7..2fb2d88e8c2e 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -341,7 +341,7 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event) static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct vlan_group *grp; struct vlan_info *vlan_info; int i, flgs; diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 173a2e82f486..690356fa52b9 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c @@ -332,7 +332,7 @@ static void aarp_expire_timeout(unsigned long unused) static int aarp_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); int ct; if (!net_eq(dev_net(dev), &init_net)) diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index ef12839a7cfe..7fee50d637f9 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -644,7 +644,7 @@ static inline void atalk_dev_down(struct net_device *dev) static int ddp_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/atm/clip.c b/net/atm/clip.c index 8ae3a7879335..cce241eb01d9 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -539,9 +539,9 @@ static int clip_create(int number) } static int clip_device_event(struct notifier_block *this, unsigned long event, - void *arg) + void *ptr) { - struct net_device *dev = arg; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/atm/mpc.c b/net/atm/mpc.c index d4cc1be5c364..3af12755cd04 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -998,14 +998,12 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc) } static int mpoa_event_listener(struct notifier_block *mpoa_notifier, - unsigned long event, void *dev_ptr) + unsigned long event, void *ptr) { - struct net_device *dev; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct mpoa_client *mpc; struct lec_priv *priv; - dev = dev_ptr; - if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index e277e38f736b..4b4d2b779ec1 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -111,9 +111,9 @@ static void ax25_kill_by_device(struct net_device *dev) * Handle device status changes. */ static int ax25_device_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; @@ -1974,7 +1974,7 @@ static struct packet_type ax25_packet_type __read_mostly = { }; static struct notifier_block ax25_dev_notifier = { - .notifier_call =ax25_device_event, + .notifier_call = ax25_device_event, }; static int __init ax25_init(void) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 522243aff2f3..b6504eac0ed8 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -595,7 +595,7 @@ void batadv_hardif_remove_interfaces(void) static int batadv_hard_if_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *net_dev = ptr; + struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); struct batadv_hard_iface *hard_iface; struct batadv_hard_iface *primary_if = NULL; struct batadv_priv *bat_priv; diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 1644b3e1f947..3a3f371b2841 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -31,7 +31,7 @@ struct notifier_block br_device_notifier = { */ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_bridge_port *p; struct net_bridge *br; bool changed_addr; diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 1f9ece1a9c34..4dca159435cf 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -352,9 +352,9 @@ EXPORT_SYMBOL(caif_enroll_dev); /* notify Caif of device events */ static int caif_device_notify(struct notifier_block *me, unsigned long what, - void *arg) + void *ptr) { - struct net_device *dev = arg; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct caif_device_entry *caifd = NULL; struct caif_dev_common *caifdev; struct cfcnfg *cfg; diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c index 942e00a425fd..75ed04b78fa4 100644 --- a/net/caif/caif_usb.c +++ b/net/caif/caif_usb.c @@ -121,9 +121,9 @@ static struct packet_type caif_usb_type __read_mostly = { }; static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, - void *arg) + void *ptr) { - struct net_device *dev = arg; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct caif_dev_common common; struct cflayer *layer, *link_support; struct usbnet *usbnet; diff --git a/net/can/af_can.c b/net/can/af_can.c index c4e50852c9f4..3ab8dd2e1282 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -794,9 +794,9 @@ EXPORT_SYMBOL(can_proto_unregister); * af_can notifier to create/remove CAN netdevice specific structs */ static int can_notifier(struct notifier_block *nb, unsigned long msg, - void *data) + void *ptr) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct dev_rcv_lists *d; if (!net_eq(dev_net(dev), &init_net)) diff --git a/net/can/bcm.c b/net/can/bcm.c index 8f113e6ff327..46f20bfafc0e 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1350,9 +1350,9 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock, * notification handler for netdevice status changes */ static int bcm_notifier(struct notifier_block *nb, unsigned long msg, - void *data) + void *ptr) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct bcm_sock *bo = container_of(nb, struct bcm_sock, notifier); struct sock *sk = &bo->sk; struct bcm_op *op; diff --git a/net/can/gw.c b/net/can/gw.c index 3ee690e8c7d3..2f291f961a17 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -445,9 +445,9 @@ static inline void cgw_unregister_filter(struct cgw_job *gwj) } static int cgw_notifier(struct notifier_block *nb, - unsigned long msg, void *data) + unsigned long msg, void *ptr) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/can/raw.c b/net/can/raw.c index 1085e65f848e..641e1c895123 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -239,9 +239,9 @@ static int raw_enable_allfilters(struct net_device *dev, struct sock *sk) } static int raw_notifier(struct notifier_block *nb, - unsigned long msg, void *data) + unsigned long msg, void *ptr) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct raw_sock *ro = container_of(nb, struct raw_sock, notifier); struct sock *sk = &ro->sk; diff --git a/net/core/dev.c b/net/core/dev.c index 5f747974ac58..54fce6006a83 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1391,6 +1391,20 @@ void dev_disable_lro(struct net_device *dev) } EXPORT_SYMBOL(dev_disable_lro); +static void netdev_notifier_info_init(struct netdev_notifier_info *info, + struct net_device *dev) +{ + info->dev = dev; +} + +static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val, + struct net_device *dev) +{ + struct netdev_notifier_info info; + + netdev_notifier_info_init(&info, dev); + return nb->notifier_call(nb, val, &info); +} static int dev_boot_phase = 1; @@ -1423,7 +1437,7 @@ int register_netdevice_notifier(struct notifier_block *nb) goto unlock; for_each_net(net) { for_each_netdev(net, dev) { - err = nb->notifier_call(nb, NETDEV_REGISTER, dev); + err = call_netdevice_notifier(nb, NETDEV_REGISTER, dev); err = notifier_to_errno(err); if (err) goto rollback; @@ -1431,7 +1445,7 @@ int register_netdevice_notifier(struct notifier_block *nb) if (!(dev->flags & IFF_UP)) continue; - nb->notifier_call(nb, NETDEV_UP, dev); + call_netdevice_notifier(nb, NETDEV_UP, dev); } } @@ -1447,10 +1461,11 @@ int register_netdevice_notifier(struct notifier_block *nb) goto outroll; if (dev->flags & IFF_UP) { - nb->notifier_call(nb, NETDEV_GOING_DOWN, dev); - nb->notifier_call(nb, NETDEV_DOWN, dev); + call_netdevice_notifier(nb, NETDEV_GOING_DOWN, + dev); + call_netdevice_notifier(nb, NETDEV_DOWN, dev); } - nb->notifier_call(nb, NETDEV_UNREGISTER, dev); + call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev); } } @@ -1488,10 +1503,11 @@ int unregister_netdevice_notifier(struct notifier_block *nb) for_each_net(net) { for_each_netdev(net, dev) { if (dev->flags & IFF_UP) { - nb->notifier_call(nb, NETDEV_GOING_DOWN, dev); - nb->notifier_call(nb, NETDEV_DOWN, dev); + call_netdevice_notifier(nb, NETDEV_GOING_DOWN, + dev); + call_netdevice_notifier(nb, NETDEV_DOWN, dev); } - nb->notifier_call(nb, NETDEV_UNREGISTER, dev); + call_netdevice_notifier(nb, NETDEV_UNREGISTER, dev); } } unlock: @@ -1500,6 +1516,25 @@ int unregister_netdevice_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(unregister_netdevice_notifier); +/** + * call_netdevice_notifiers_info - call all network notifier blocks + * @val: value passed unmodified to notifier function + * @dev: net_device pointer passed unmodified to notifier function + * @info: notifier information data + * + * Call all network notifier blocks. Parameters and return value + * are as for raw_notifier_call_chain(). + */ + +int call_netdevice_notifiers_info(unsigned long val, struct net_device *dev, + struct netdev_notifier_info *info) +{ + ASSERT_RTNL(); + netdev_notifier_info_init(info, dev); + return raw_notifier_call_chain(&netdev_chain, val, info); +} +EXPORT_SYMBOL(call_netdevice_notifiers_info); + /** * call_netdevice_notifiers - call all network notifier blocks * @val: value passed unmodified to notifier function @@ -1511,8 +1546,9 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); int call_netdevice_notifiers(unsigned long val, struct net_device *dev) { - ASSERT_RTNL(); - return raw_notifier_call_chain(&netdev_chain, val, dev); + struct netdev_notifier_info info; + + return call_netdevice_notifiers_info(val, dev, &info); } EXPORT_SYMBOL(call_netdevice_notifiers); diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index d23b6682f4e9..5e78d44333b9 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -295,9 +295,9 @@ static int net_dm_cmd_trace(struct sk_buff *skb, } static int dropmon_net_event(struct notifier_block *ev_block, - unsigned long event, void *ptr) + unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct dm_hw_stat_delta *new_stat = NULL; struct dm_hw_stat_delta *tmp; diff --git a/net/core/dst.c b/net/core/dst.c index df9cc810ec8e..ca4231ec7347 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -372,7 +372,7 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct dst_entry *dst, *last = NULL; switch (event) { diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index d5a9f8ead0d8..21735440c44a 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -705,9 +705,9 @@ static void detach_rules(struct list_head *rules, struct net_device *dev) static int fib_rules_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct fib_rules_ops *ops; diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 0777d0aa18c3..e533259dce3c 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -261,7 +261,7 @@ struct cgroup_subsys net_prio_subsys = { static int netprio_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct netprio_map *old; /* diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 11f2704c3810..795498fd4587 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1921,7 +1921,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d static int pktgen_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct pktgen_net *pn = net_generic(dev_net(dev), pg_net_id); if (pn->pktgen_exiting) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index a08bd2b7fe3f..49c14451d8ab 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2667,7 +2667,7 @@ static void rtnetlink_rcv(struct sk_buff *skb) static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); switch (event) { case NETDEV_UP: diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index c21f200eed93..dd4d506ef923 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2078,9 +2078,9 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, } static int dn_device_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 55e1fd5b3e56..3b9d5f20bd1c 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -1352,10 +1352,9 @@ static inline void lowpan_netlink_fini(void) } static int lowpan_device_event(struct notifier_block *unused, - unsigned long event, - void *ptr) + unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); LIST_HEAD(del_list); struct lowpan_dev_record *entry, *tmp; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 247ec1951c35..bf574029a183 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1234,7 +1234,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); switch (event) { case NETDEV_CHANGEADDR: diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index dfc39d4d48b7..b047e2d8a614 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1333,7 +1333,7 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev, static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct in_device *in_dev = __in_dev_get_rtnl(dev); ASSERT_RTNL(); diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c7629a209f9d..05a4888dede9 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1038,7 +1038,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct in_device *in_dev; struct net *net = dev_net(dev); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9d9610ae7855..f975399f3522 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1609,7 +1609,7 @@ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct mr_table *mrt; struct vif_device *v; diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 5d5d4d1be9c2..dd5508bde799 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -108,7 +108,7 @@ static int masq_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - const struct net_device *dev = ptr; + const struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); if (event == NETDEV_DOWN) { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 432e084b6b62..bce073b4bbd4 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2826,9 +2826,9 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) } static int addrconf_notify(struct notifier_block *this, unsigned long event, - void *data) + void *ptr) { - struct net_device *dev = (struct net_device *) data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct inet6_dev *idev = __in6_dev_get(dev); int run_pending = 0; int err; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 241fb8ad9fcf..583e8d435f9a 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -1319,7 +1319,7 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc, static int ip6mr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct mr6_table *mrt; struct mif_device *v; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2712ab22a174..a0962697a257 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1568,7 +1568,7 @@ int ndisc_rcv(struct sk_buff *skb) static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct inet6_dev *idev; diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c index 60e9053bab05..b76257cd7e1e 100644 --- a/net/ipv6/netfilter/ip6t_MASQUERADE.c +++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c @@ -71,7 +71,7 @@ static int device_cmp(struct nf_conn *ct, void *ifindex) static int masq_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - const struct net_device *dev = ptr; + const struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); if (event == NETDEV_DOWN) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad0aa6b0b86a..194c3cde1536 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2681,9 +2681,9 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) } static int ip6_route_dev_notify(struct notifier_block *this, - unsigned long event, void *data) + unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index f547a47d381c..7a1e0fc1bd4d 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -330,7 +330,7 @@ static __inline__ void __ipxitf_put(struct ipx_interface *intrfc) static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ipx_interface *i, *tmp; if (!net_eq(dev_net(dev), &init_net)) diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index ae691651b721..168aff5e60de 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -2293,7 +2293,7 @@ static void afiucv_hs_callback_txnotify(struct sk_buff *skb, static int afiucv_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *event_dev = (struct net_device *)ptr; + struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); struct sock *sk; struct iucv_sock *iucv; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 60f1ce5e5e52..d2c3fd178dbe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1717,10 +1717,9 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) } static int netdev_notify(struct notifier_block *nb, - unsigned long state, - void *ndev) + unsigned long state, void *ptr) { - struct net_device *dev = ndev; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ieee80211_sub_if_data *sdata; if (state != NETDEV_CHANGENAME) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 5b142fb16480..7c3ed429789e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1487,9 +1487,9 @@ ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev) * Currently only NETDEV_DOWN is handled to release refs to cached dsts */ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_service *svc; diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 4e27fa035814..0f2ac8f2e7b7 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -800,7 +800,7 @@ static int nfqnl_rcv_dev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index bd93e51d30ac..292934d23482 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -200,7 +200,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) static int tee_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct xt_tee_priv *priv; priv = container_of(this, struct xt_tee_priv, notifier); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 8a6c6ea466d8..af3531926ee0 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -708,7 +708,7 @@ int netlbl_unlhsh_remove(struct net *net, * netlbl_unlhsh_netdev_handler - Network device notification handler * @this: notifier block * @event: the event - * @ptr: the network device (cast to void) + * @ptr: the netdevice notifier info (cast to void) * * Description: * Handle network device events, although at present all we care about is a @@ -717,10 +717,9 @@ int netlbl_unlhsh_remove(struct net *net, * */ static int netlbl_unlhsh_netdev_handler(struct notifier_block *this, - unsigned long event, - void *ptr) + unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct netlbl_unlhsh_iface *iface = NULL; if (!net_eq(dev_net(dev), &init_net)) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index ec0c80fde69f..698814bfa7ad 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -117,7 +117,7 @@ static void nr_kill_by_device(struct net_device *dev) */ static int nr_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c index ef4feec6cd84..c3235675f359 100644 --- a/net/openvswitch/dp_notify.c +++ b/net/openvswitch/dp_notify.c @@ -78,7 +78,7 @@ static int dp_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct ovs_net *ovs_net; - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct vport *vport = NULL; if (!ovs_is_internal_dev(dev)) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8ec1bca7f859..79fe63246b27 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3331,10 +3331,11 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, } -static int packet_notifier(struct notifier_block *this, unsigned long msg, void *data) +static int packet_notifier(struct notifier_block *this, + unsigned long msg, void *ptr) { struct sock *sk; - struct net_device *dev = data; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); rcu_read_lock(); diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 45a7df6575de..56a6146ac94b 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -292,9 +292,9 @@ static void phonet_route_autodel(struct net_device *dev) /* notify Phonet of device events */ static int phonet_device_notify(struct notifier_block *me, unsigned long what, - void *arg) + void *ptr) { - struct net_device *dev = arg; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); switch (what) { case NETDEV_REGISTER: diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 9c8347451597..e98fcfbe6007 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -202,10 +202,10 @@ static void rose_kill_by_device(struct net_device *dev) /* * Handle device status changes. */ -static int rose_device_event(struct notifier_block *this, unsigned long event, - void *ptr) +static int rose_device_event(struct notifier_block *this, + unsigned long event, void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 5d676edc22a6..977c10e0631b 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -243,7 +243,7 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, i static int mirred_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct tcf_mirred *m; if (event == NETDEV_UNREGISTER) diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 120a676a3360..fc60bea63169 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -251,9 +251,9 @@ static void disable_bearer(struct tipc_bearer *tb_ptr) * specified device. */ static int recv_notification(struct notifier_block *nb, unsigned long evt, - void *dv) + void *ptr) { - struct net_device *dev = (struct net_device *)dv; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct eth_bearer *eb_ptr = ð_bearers[0]; struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c index 2a2864c25e15..baa9df4327d9 100644 --- a/net/tipc/ib_media.c +++ b/net/tipc/ib_media.c @@ -244,9 +244,9 @@ static void disable_bearer(struct tipc_bearer *tb_ptr) * specified device. */ static int recv_notification(struct notifier_block *nb, unsigned long evt, - void *dv) + void *ptr) { - struct net_device *dev = (struct net_device *)dv; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct ib_bearer *ib_ptr = &ib_bearers[0]; struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; diff --git a/net/wireless/core.c b/net/wireless/core.c index 73405e00c800..01e41191f1bf 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -886,10 +886,9 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, } static int cfg80211_netdev_notifier_call(struct notifier_block *nb, - unsigned long state, - void *ndev) + unsigned long state, void *ptr) { - struct net_device *dev = ndev; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev; int ret; diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 37ca9694aabe..1d964e23853f 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -224,7 +224,7 @@ static void x25_kill_by_device(struct net_device *dev) static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct x25_neigh *nb; if (!net_eq(dev_net(dev), &init_net)) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 23cea0f74336..536ccc95de89 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2784,7 +2784,7 @@ static void __net_init xfrm_dst_ops_init(struct net *net) static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); switch (event) { case NETDEV_DOWN: diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 47a49d1a6f6a..694e9e43855f 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c @@ -264,7 +264,7 @@ static int sel_netif_avc_callback(u32 event) static int sel_netif_netdev_notifier_handler(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); if (dev_net(dev) != &init_net) return NOTIFY_DONE; -- GitLab From be9efd3653284f2827fd82861e8e9db9a8f726e1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 28 May 2013 01:30:22 +0000 Subject: [PATCH 0461/2900] net: pass changed flags along with NETDEV_CHANGE event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new netdevice notifier infrastructure to pass along changed flags. Signed-off-by: Timo Teräs Signed-off-by: Jiri Pirko v2->v3: shortened notifier_info struct name Signed-off-by: David S. Miller --- include/linux/netdevice.h | 5 +++++ net/core/dev.c | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 13a34848b5e1..850271809a9e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1604,6 +1604,11 @@ struct netdev_notifier_info { struct net_device *dev; }; +struct netdev_notifier_change_info { + struct netdev_notifier_info info; /* must be first */ + unsigned int flags_changed; +}; + static inline struct net_device * netdev_notifier_info_to_dev(const struct netdev_notifier_info *info) { diff --git a/net/core/dev.c b/net/core/dev.c index 54fce6006a83..6eb621cc3b81 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4771,8 +4771,13 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags) } if (dev->flags & IFF_UP && - (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) - call_netdevice_notifiers(NETDEV_CHANGE, dev); + (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) { + struct netdev_notifier_change_info change_info; + + change_info.flags_changed = changes; + call_netdevice_notifiers_info(NETDEV_CHANGE, dev, + &change_info.info); + } } /** -- GitLab From 6c8b4e3ff81b82fc153625e81e60af1d89de2c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 28 May 2013 01:30:23 +0000 Subject: [PATCH 0462/2900] arp: flush arp cache on IFF_NOARP change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IFF_NOARP affects what kind of neighbor entries are created (nud NOARP or nud INCOMPLETE). If the flag changes, flush the arp cache to refresh all entries. Signed-off-by: Timo Teräs Signed-off-by: Jiri Pirko v2->v3: shortened notifier_info struct name Signed-off-by: David S. Miller --- net/ipv4/arp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index bf574029a183..4429b013f269 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1235,12 +1235,18 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_change_info *change_info; switch (event) { case NETDEV_CHANGEADDR: neigh_changeaddr(&arp_tbl, dev); rt_cache_flush(dev_net(dev)); break; + case NETDEV_CHANGE: + change_info = ptr; + if (change_info->flags_changed & IFF_NOARP) + neigh_changeaddr(&arp_tbl, dev); + break; default: break; } -- GitLab From 06ecf24bdf2b7afc6c8fd13de6dba2a96dd331b6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 28 May 2013 13:15:50 -0700 Subject: [PATCH 0463/2900] net: Fix build warnings after mac_header and transport_header became __u16. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/core/skbuff.c: In function ‘__alloc_skb_head’: net/core/skbuff.c:203:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] net/core/skbuff.c: In function ‘__alloc_skb’: net/core/skbuff.c:279:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] net/core/skbuff.c:280:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] net/core/skbuff.c: In function ‘build_skb’: net/core/skbuff.c:348:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] net/core/skbuff.c:349:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] Signed-off-by: David S. Miller --- net/core/skbuff.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d6298914f4e7..f45de077ab9e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -200,7 +200,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node) atomic_set(&skb->users, 1); #ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = ~0U; + skb->mac_header = (__u16) ~0U; #endif out: return skb; @@ -276,8 +276,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, skb_reset_tail_pointer(skb); skb->end = skb->tail + size; #ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = ~0U; - skb->transport_header = ~0U; + skb->mac_header = (__u16) ~0U; + skb->transport_header = (__u16) ~0U; #endif /* make sure we initialize shinfo sequentially */ @@ -345,8 +345,8 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) skb_reset_tail_pointer(skb); skb->end = skb->tail + size; #ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = ~0U; - skb->transport_header = ~0U; + skb->mac_header = (__u16) ~0U; + skb->transport_header = (__u16) ~0U; #endif /* make sure we initialize shinfo sequentially */ -- GitLab From de68d1003d9eb0a5f7d4714315614e4bc956f68e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 9 Mar 2013 23:14:22 +0100 Subject: [PATCH 0464/2900] batman-adv: split batadv_is_wifi_iface() into two functions Previously batadv_is_wifi_iface() did two things at once: looking up a net_device from an interface index, and determining if it is a wifi device. The second part is useful itself when the caller already has a net_device reference. Signed-off-by: Matthias Schiffer Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/hard-interface.c | 84 ++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b6504eac0ed8..d5ec67b63253 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -117,6 +117,58 @@ static int batadv_is_valid_iface(const struct net_device *net_dev) return 1; } +/** + * batadv_is_wifi_netdev - check if the given net_device struct is a wifi + * interface + * @net_device: the device to check + * + * Returns true if the net device is a 802.11 wireless device, false otherwise. + */ +static bool batadv_is_wifi_netdev(struct net_device *net_device) +{ +#ifdef CONFIG_WIRELESS_EXT + /* pre-cfg80211 drivers have to implement WEXT, so it is possible to + * check for wireless_handlers != NULL + */ + if (net_device->wireless_handlers) + return true; +#endif + + /* cfg80211 drivers have to set ieee80211_ptr */ + if (net_device->ieee80211_ptr) + return true; + + return false; +} + +/** + * batadv_is_wifi_iface - check if the given interface represented by ifindex + * is a wifi interface + * @ifindex: interface index to check + * + * Returns true if the interface represented by ifindex is a 802.11 wireless + * device, false otherwise. + */ +bool batadv_is_wifi_iface(int ifindex) +{ + struct net_device *net_device = NULL; + bool ret = false; + + if (ifindex == BATADV_NULL_IFINDEX) + goto out; + + net_device = dev_get_by_index(&init_net, ifindex); + if (!net_device) + goto out; + + ret = batadv_is_wifi_netdev(net_device); + +out: + if (net_device) + dev_put(net_device); + return ret; +} + static struct batadv_hard_iface * batadv_hardif_get_active(const struct net_device *soft_iface) { @@ -657,38 +709,6 @@ static int batadv_hard_if_event(struct notifier_block *this, return NOTIFY_DONE; } -/* This function returns true if the interface represented by ifindex is a - * 802.11 wireless device - */ -bool batadv_is_wifi_iface(int ifindex) -{ - struct net_device *net_device = NULL; - bool ret = false; - - if (ifindex == BATADV_NULL_IFINDEX) - goto out; - - net_device = dev_get_by_index(&init_net, ifindex); - if (!net_device) - goto out; - -#ifdef CONFIG_WIRELESS_EXT - /* pre-cfg80211 drivers have to implement WEXT, so it is possible to - * check for wireless_handlers != NULL - */ - if (net_device->wireless_handlers) - ret = true; - else -#endif - /* cfg80211 drivers have to set ieee80211_ptr */ - if (net_device->ieee80211_ptr) - ret = true; -out: - if (net_device) - dev_put(net_device); - return ret; -} - struct notifier_block batadv_hard_if_notifier = { .notifier_call = batadv_hard_if_event, }; -- GitLab From caf65bfcc5dbabd7222fa45fdcd42ce0783d7a42 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 9 Mar 2013 23:14:23 +0100 Subject: [PATCH 0465/2900] batman-adv: send each broadcast only once on non-wireless interfaces While it makes sense to send each broadcast thrice on 802.11 (WLAN) interfaces as broadcasts are often unreliable on these, there is no reason to do so on other interface types. The increased the overhead can be harmful on low-bandwidth links like VPN connections over slow internet lines, therefore it is better to reduce the number of broadcast packets sent on non-wireless links to one. Signed-off-by: Matthias Schiffer Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/hard-interface.c | 4 ++++ net/batman-adv/main.h | 5 +++++ net/batman-adv/send.c | 5 ++++- net/batman-adv/types.h | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index d5ec67b63253..4a76ed654c92 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -593,6 +593,10 @@ batadv_hardif_add_interface(struct net_device *net_dev) INIT_WORK(&hard_iface->cleanup_work, batadv_hardif_remove_interface_finish); + hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT; + if (batadv_is_wifi_netdev(net_dev)) + hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS; + /* extra reference for return */ atomic_set(&hard_iface->refcount, 2); diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 59a0d6af15c8..ea1a3bafe9c3 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -76,6 +76,11 @@ #define BATADV_LOG_BUF_LEN 8192 /* has to be a power of 2 */ +/* number of packets to send for broadcasts on different interface types */ +#define BATADV_NUM_BCASTS_DEFAULT 1 +#define BATADV_NUM_BCASTS_WIRELESS 3 +#define BATADV_NUM_BCASTS_MAX 3 + /* msecs after which an ARP_REQUEST is sent in broadcast as fallback */ #define ARP_REQ_DELAY 250 /* numbers of originator to contact for any PUT/GET DHT operation */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 263cfd1ccee7..eb16b04d4bee 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -260,6 +260,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) if (hard_iface->soft_iface != soft_iface) continue; + if (forw_packet->num_packets >= hard_iface->num_bcasts) + continue; + /* send a copy of the saved skb */ skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); if (skb1) @@ -271,7 +274,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) forw_packet->num_packets++; /* if we still have some more bcasts to send */ - if (forw_packet->num_packets < 3) { + if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) { _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, msecs_to_jiffies(5)); return; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index aba8364c3689..5f542bdd9a4d 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -61,6 +61,7 @@ struct batadv_hard_iface_bat_iv { * @if_status: status of the interface for batman-adv * @net_dev: pointer to the net_device * @frag_seqno: last fragment sequence number sent by this interface + * @num_bcasts: number of payload re-broadcasts on this interface (ARQ) * @hardif_obj: kobject of the per interface sysfs "mesh" directory * @refcount: number of contexts the object is used * @batman_adv_ptype: packet type describing packets that should be processed by @@ -76,6 +77,7 @@ struct batadv_hard_iface { char if_status; struct net_device *net_dev; atomic_t frag_seqno; + uint8_t num_bcasts; struct kobject *hardif_obj; atomic_t refcount; struct packet_type batman_adv_ptype; -- GitLab From 93178018eb35aaa6ebcb5a136dce7eb3add011ab Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sun, 10 Mar 2013 19:29:15 +0800 Subject: [PATCH 0466/2900] batman-adv: fix typos in kernel doc & comments Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/distributed-arp-table.c | 82 ++++++++++++-------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 239992021b1d..06345d401588 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -45,9 +45,9 @@ static void batadv_dat_start_timer(struct batadv_priv *bat_priv) } /** - * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly + * batadv_dat_entry_free_ref - decrement the dat_entry refcounter and possibly * free it - * @dat_entry: the oentry to free + * @dat_entry: the entry to free */ static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry) { @@ -56,10 +56,10 @@ static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry) } /** - * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not + * batadv_dat_to_purge - check whether a dat_entry has to be purged or not * @dat_entry: the entry to check * - * Returns true if the entry has to be purged now, false otherwise + * Returns true if the entry has to be purged now, false otherwise. */ static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry) { @@ -75,8 +75,8 @@ static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry) * returns a boolean value: true is the entry has to be deleted, * false otherwise * - * Loops over each entry in the DAT local storage and delete it if and only if - * the to_purge function passed as argument returns true + * Loops over each entry in the DAT local storage and deletes it if and only if + * the to_purge function passed as argument returns true. */ static void __batadv_dat_purge(struct batadv_priv *bat_priv, bool (*to_purge)(struct batadv_dat_entry *)) @@ -97,7 +97,7 @@ static void __batadv_dat_purge(struct batadv_priv *bat_priv, spin_lock_bh(list_lock); hlist_for_each_entry_safe(dat_entry, node_tmp, head, hash_entry) { - /* if an helper function has been passed as parameter, + /* if a helper function has been passed as parameter, * ask it if the entry has to be purged or not */ if (to_purge && !to_purge(dat_entry)) @@ -134,7 +134,7 @@ static void batadv_dat_purge(struct work_struct *work) * @node: node in the local table * @data2: second object to compare the node to * - * Returns 1 if the two entry are the same, 0 otherwise + * Returns 1 if the two entries are the same, 0 otherwise. */ static int batadv_compare_dat(const struct hlist_node *node, const void *data2) { @@ -149,7 +149,7 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the hw_src field in the ARP packet + * Returns the value of the hw_src field in the ARP packet. */ static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) { @@ -166,7 +166,7 @@ static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the ip_src field in the ARP packet + * Returns the value of the ip_src field in the ARP packet. */ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) { @@ -178,7 +178,7 @@ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the hw_dst field in the ARP packet + * Returns the value of the hw_dst field in the ARP packet. */ static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) { @@ -190,7 +190,7 @@ static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the ip_dst field in the ARP packet + * Returns the value of the ip_dst field in the ARP packet. */ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) { @@ -202,7 +202,7 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) * @data: data to hash * @size: size of the hash table * - * Returns the selected index in the hash table for the given data + * Returns the selected index in the hash table for the given data. */ static uint32_t batadv_hash_dat(const void *data, uint32_t size) { @@ -224,12 +224,12 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size) } /** - * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash + * batadv_dat_entry_hash_find - look for a given dat_entry in the local hash * table * @bat_priv: the bat priv with all the soft interface information * @ip: search key * - * Returns the dat_entry if found, NULL otherwise + * Returns the dat_entry if found, NULL otherwise. */ static struct batadv_dat_entry * batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip) @@ -343,9 +343,6 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, if (hdr_size == 0) return; - /* if the ARP packet is encapsulated in a batman packet, let's print - * some debug messages - */ unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; switch (unicast_4addr_packet->u.header.packet_type) { @@ -409,7 +406,8 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, * @candidate: orig_node under evaluation * @max_orig_node: last selected candidate * - * Returns true if the node has been elected as next candidate or false othrwise + * Returns true if the node has been elected as next candidate or false + * otherwise. */ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res, int select, batadv_dat_addr_t tmp_max, @@ -472,7 +470,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, */ cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND; - /* iterate over the originator list and find the node with closest + /* iterate over the originator list and find the node with the closest * dat_address which has not been selected yet */ for (i = 0; i < hash->size; i++) { @@ -480,7 +478,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, head, hash_entry) { - /* the dht space is a ring and addresses are unsigned */ + /* the dht space is a ring using unsigned addresses */ tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr + ip_key; @@ -512,7 +510,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, } /** - * batadv_dat_select_candidates - selects the nodes which the DHT message has to + * batadv_dat_select_candidates - select the nodes which the DHT message has to * be sent to * @bat_priv: the bat priv with all the soft interface information * @ip_dst: ipv4 to look up in the DHT @@ -521,7 +519,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, * closest values (from the LEFT, with wrap around if needed) then the hash * value of the key. ip_dst is the key. * - * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM + * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM. */ static struct batadv_dat_candidate * batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) @@ -558,10 +556,11 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) * @ip: the DHT key * @packet_subtype: unicast4addr packet subtype to use * - * In this function the skb is copied by means of pskb_copy() and is sent as - * unicast packet to each of the selected candidates + * This function copies the skb with pskb_copy() and is sent as unicast packet + * to each of the selected candidates. * - * Returns true if the packet is sent to at least one candidate, false otherwise + * Returns true if the packet is sent to at least one candidate, false + * otherwise. */ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, struct sk_buff *skb, __be32 ip, @@ -727,7 +726,7 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) * @skb: packet to analyse * @hdr_size: size of the possible header before the ARP packet in the skb * - * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise + * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise. */ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -754,9 +753,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN); - /* Check whether the ARP packet carries a valid - * IP information - */ + /* check whether the ARP packet carries a valid IP information */ if (arphdr->ar_hrd != htons(ARPHRD_ETHER)) goto out; @@ -784,7 +781,7 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, if (is_zero_ether_addr(hw_src) || is_multicast_ether_addr(hw_src)) goto out; - /* we don't care about the destination MAC address in ARP requests */ + /* don't care about the destination MAC address in ARP requests */ if (arphdr->ar_op != htons(ARPOP_REQUEST)) { hw_dst = batadv_arp_hw_dst(skb, hdr_size); if (is_zero_ether_addr(hw_dst) || @@ -804,8 +801,8 @@ static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, * @skb: packet to check * * Returns true if the message has been sent to the dht candidates, false - * otherwise. In case of true the message has to be enqueued to permit the - * fallback + * otherwise. In case of a positive return value the message has to be enqueued + * to permit the fallback. */ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, struct sk_buff *skb) @@ -867,7 +864,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n"); ret = true; } else { - /* Send the request on the DHT */ + /* Send the request to the DHT */ ret = batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_GET); } @@ -884,7 +881,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, * @skb: packet to check * @hdr_size: size of the encapsulation header * - * Returns true if the request has been answered, false otherwise + * Returns true if the request has been answered, false otherwise. */ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -924,10 +921,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, if (!skb_new) goto out; - /* to preserve backwards compatibility, here the node has to answer - * using the same packet type it received for the request. This is due - * to that if a node is not using the 4addr packet format it may not - * support it. + /* To preserve backwards compatibility, the node has choose the outgoing + * format based on the incoming request packet type. The assumption is + * that a node not using the 4addr packet format doesn't support it. */ if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) err = batadv_unicast_4addr_send_skb(bat_priv, skb_new, @@ -977,7 +973,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); /* Send the ARP reply to the candidates for both the IP addresses that - * the node got within the ARP reply + * the node obtained from the ARP reply */ batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT); batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT); @@ -987,7 +983,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, * DAT storage only * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check - * @hdr_size: siaze of the encapsulation header + * @hdr_size: size of the encapsulation header */ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -1031,11 +1027,11 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, /** * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped - * (because the node has already got the reply via DAT) or not + * (because the node has already obtained the reply via DAT) or not * @bat_priv: the bat priv with all the soft interface information * @forw_packet: the broadcast packet * - * Returns true if the node can drop the packet, false otherwise + * Returns true if the node can drop the packet, false otherwise. */ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet) -- GitLab From 863dd7a82a2fba3e1a094c3d10a9cc8d1afd10d6 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 25 Mar 2013 13:49:46 +0100 Subject: [PATCH 0467/2900] batman-adv: drop useless argument seqno in neighbor creation the sequence number is not stored in struct neigh_node, therefore there is no need to pass such value to the neigh_node creation procedure. At the moment the value is only used by a debug message, but given the fact that the seqno is not related to the neighbor object, it is better to print it elsewhere. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 11 ++++------- net/batman-adv/originator.c | 5 ++--- net/batman-adv/originator.h | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 071f288b77a8..da239c5424b8 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -33,12 +33,11 @@ static struct batadv_neigh_node * batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, struct batadv_orig_node *orig_node, - struct batadv_orig_node *orig_neigh, __be32 seqno) + struct batadv_orig_node *orig_neigh) { struct batadv_neigh_node *neigh_node; - neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, - ntohl(seqno)); + neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr); if (!neigh_node) goto out; @@ -696,8 +695,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, neigh_node = batadv_iv_ogm_neigh_new(if_incoming, ethhdr->h_source, - orig_node, orig_tmp, - batadv_ogm_packet->seqno); + orig_node, orig_tmp); batadv_orig_node_free_ref(orig_tmp); if (!neigh_node) @@ -829,8 +827,7 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, neigh_node = batadv_iv_ogm_neigh_new(if_incoming, orig_neigh_node->orig, orig_neigh_node, - orig_neigh_node, - batadv_ogm_packet->seqno); + orig_neigh_node); if (!neigh_node) goto out; diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index fad1a2093e15..ddf563484798 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -92,7 +92,7 @@ batadv_orig_node_get_router(struct batadv_orig_node *orig_node) struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, - const uint8_t *neigh_addr, uint32_t seqno) + const uint8_t *neigh_addr) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct batadv_neigh_node *neigh_node; @@ -110,8 +110,7 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, atomic_set(&neigh_node->refcount, 2); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Creating new neighbor %pM, initial seqno %d\n", - neigh_addr, seqno); + "Creating new neighbor %pM\n", neigh_addr); out: return neigh_node; diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 734e5a3d8a5b..7887b84a9af4 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -31,7 +31,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, const uint8_t *addr); struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, - const uint8_t *neigh_addr, uint32_t seqno); + const uint8_t *neigh_addr); void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node); struct batadv_neigh_node * batadv_orig_node_get_router(struct batadv_orig_node *orig_node); -- GitLab From d1dc30739c587fe65f4120c045258ab01c79db1b Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 25 Mar 2013 13:54:45 +0100 Subject: [PATCH 0468/2900] batman-adv: slightly improve neighbor creation debug message print the interface along with the new neighbor mac address Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/originator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ddf563484798..f50553a7de62 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -110,7 +110,8 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, atomic_set(&neigh_node->refcount, 2); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Creating new neighbor %pM\n", neigh_addr); + "Creating new neighbor %pM on interface %s\n", neigh_addr, + hard_iface->net_dev->name); out: return neigh_node; -- GitLab From 281581d3e79eaacfcdc0827e9bf990422252ba5c Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 25 Mar 2013 22:27:00 +0100 Subject: [PATCH 0469/2900] batman-adv: don't check the source address twice The source address has already been checked in batadv_check_management_packet() upon packet reception and therefore it does not need to be checked again in ogm_process() Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index da239c5424b8..6d62e2992dfa 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -988,7 +988,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, struct batadv_neigh_node *orig_neigh_router = NULL; int has_directlink_flag; int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; - int is_broadcast = 0, is_bidirect; + int is_bidirect; bool is_single_hop_neigh = false; bool is_from_best_next_hop = false; int is_duplicate, sameseq, simlar_ttl; @@ -1051,9 +1051,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, if (batadv_compare_eth(batadv_ogm_packet->prev_sender, hard_iface->net_dev->dev_addr)) is_my_oldorig = 1; - - if (is_broadcast_ether_addr(ethhdr->h_source)) - is_broadcast = 1; } rcu_read_unlock(); @@ -1071,13 +1068,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, return; } - if (is_broadcast) { - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Drop packet: ignoring all packets with broadcast source addr (sender: %pM)\n", - ethhdr->h_source); - return; - } - if (is_my_orig) { unsigned long *word; int offset; -- GitLab From a3b81b67de6ae0475c0c34c552c059f7bea2f520 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 28 Mar 2013 14:21:12 +0100 Subject: [PATCH 0470/2900] batman-adv: don't check compat version twice Compatibility version is checked upon packet reception before calling any handler. For this reason it does need to be checked once more in the handler itself. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 6d62e2992dfa..38183dc6965d 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1054,13 +1054,6 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, } rcu_read_unlock(); - if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) { - batadv_dbg(BATADV_DBG_BATMAN, bat_priv, - "Drop packet: incompatible batman version (%i)\n", - batadv_ogm_packet->header.version); - return; - } - if (is_my_addr) { batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "Drop packet: received my own broadcast (sender: %pM)\n", -- GitLab From 38dc40ef52d882e08b2af71fc1b5413ac7009952 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 30 Mar 2013 17:22:00 +0100 Subject: [PATCH 0471/2900] batman-adv: do not silently ignore wrong condition Only one neigh_node per orig_node should match a given neighbor address, therefore, if more than one matching neigh_node is found, a WARNING has to be triggered to let the user know that something is wrong in the originator state instead of silently skipping the error. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 38183dc6965d..bd50e0d76aea 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -669,7 +669,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && tmp_neigh_node->if_incoming == if_incoming && atomic_inc_not_zero(&tmp_neigh_node->refcount)) { - if (neigh_node) + if (WARN(neigh_node, "too many matching neigh_nodes")) batadv_neigh_node_free_ref(neigh_node); neigh_node = tmp_neigh_node; continue; -- GitLab From 7db3fc291bb22bf43667b009dd0e701ed4eb7c96 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 2 Apr 2013 12:16:53 +0200 Subject: [PATCH 0472/2900] batman-adv: don't initialise batman_iv private members in hard-interface.c hard-interface.c has to do not contain any routing algorithm specific code. Allocate the hard-interface with kzalloc() and remove any useless and algorithm specific member initialisation Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/hard-interface.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 4a76ed654c92..c478e6bcf89b 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -577,7 +577,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) dev_hold(net_dev); - hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC); + hard_iface = kzalloc(sizeof(*hard_iface), GFP_ATOMIC); if (!hard_iface) goto release_dev; @@ -603,12 +603,6 @@ batadv_hardif_add_interface(struct net_device *net_dev) batadv_check_known_mac_addr(hard_iface->net_dev); list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); - /* This can't be called via a bat_priv callback because - * we have no bat_priv yet. - */ - atomic_set(&hard_iface->bat_iv.ogm_seqno, 1); - hard_iface->bat_iv.ogm_buff = NULL; - return hard_iface; free_if: -- GitLab From 7ed4be9523455a061e62236dc3caa9211cd7edda Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 8 Apr 2013 15:08:18 +0200 Subject: [PATCH 0473/2900] batman-adv: use eth_hdr() when it makes sense Instead of casting the result of skb_mac_header() to "struct ethhdr *" every time, the eth_hdr inline function can be use to beautify the code and improve its readability. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 2 +- net/batman-adv/bridge_loop_avoidance.c | 8 ++++---- net/batman-adv/network-coding.c | 10 +++++----- net/batman-adv/routing.c | 12 ++++++------ net/batman-adv/send.c | 2 +- net/batman-adv/soft-interface.c | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index bd50e0d76aea..ef41be49b314 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1268,7 +1268,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, skb->len + ETH_HLEN); packet_len = skb_headlen(skb); - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); packet_buff = skb->data; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff; diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 379061c72549..082189e2e40d 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -864,7 +864,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, short vid = -1; int ret; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { vhdr = (struct vlan_ethhdr *)ethhdr; @@ -885,7 +885,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, return 0; /* pskb_may_pull() may have modified the pointers, get ethhdr again */ - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); arphdr = (struct arphdr *)((uint8_t *)ethhdr + headlen); /* Check whether the ARP frame carries a valid @@ -1432,7 +1432,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, struct batadv_hard_iface *primary_if; int ret; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) @@ -1539,7 +1539,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid) if (batadv_bla_process_claim(bat_priv, primary_if, skb)) goto handled; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); if (unlikely(atomic_read(&bat_priv->bla.num_requests))) /* don't allow broadcasts while requests are in flight */ diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index e84629ece9b7..0787a34609b9 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1245,7 +1245,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, return; /* Set the mac header as if we actually sent the packet uncoded */ - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN); memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN); @@ -1423,7 +1423,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, { struct batadv_unicast_packet *packet; struct batadv_nc_path *nc_path; - struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); + struct ethhdr *ethhdr = eth_hdr(skb); __be32 packet_id; u8 *payload; @@ -1482,7 +1482,7 @@ void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, struct sk_buff *skb) { - struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); + struct ethhdr *ethhdr = eth_hdr(skb); if (batadv_is_my_mac(bat_priv, ethhdr->h_dest)) return; @@ -1533,7 +1533,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, skb_reset_network_header(skb); /* Reconstruct original mac header */ - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); memcpy(ethhdr, ðhdr_tmp, sizeof(*ethhdr)); /* Select the correct unicast header information based on the location @@ -1677,7 +1677,7 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, return NET_RX_DROP; coded_packet = (struct batadv_coded_packet *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* Verify frame is destined for us */ if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest) && diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index b27a4d792d15..beeab2e8cd66 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -256,7 +256,7 @@ bool batadv_check_management_packet(struct sk_buff *skb, if (unlikely(!pskb_may_pull(skb, header_len))) return false; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* packet with broadcast indication but unicast recipient */ if (!is_broadcast_ether_addr(ethhdr->h_dest)) @@ -392,7 +392,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, if (unlikely(!pskb_may_pull(skb, hdr_size))) goto out; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) @@ -569,7 +569,7 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, if (unlikely(!pskb_may_pull(skb, hdr_size))) return -ENODATA; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* packet with unicast indication but broadcast recipient */ if (is_broadcast_ether_addr(ethhdr->h_dest)) @@ -803,7 +803,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, struct batadv_orig_node *orig_node = NULL; struct batadv_neigh_node *neigh_node = NULL; struct batadv_unicast_packet *unicast_packet; - struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); + struct ethhdr *ethhdr = eth_hdr(skb); int ret = NET_RX_DROP; struct sk_buff *new_skb; @@ -1165,7 +1165,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, if (unlikely(!pskb_may_pull(skb, hdr_size))) goto out; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* packet with broadcast indication but unicast recipient */ if (!is_broadcast_ether_addr(ethhdr->h_dest)) @@ -1265,7 +1265,7 @@ int batadv_recv_vis_packet(struct sk_buff *skb, return NET_RX_DROP; vis_packet = (struct batadv_vis_packet *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); /* not for me */ if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index eb16b04d4bee..ed7072ad84e8 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -61,7 +61,7 @@ int batadv_send_skb_packet(struct sk_buff *skb, skb_reset_mac_header(skb); - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN); memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); ethhdr->h_proto = __constant_htons(ETH_P_BATMAN); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 819dfb006cdf..b26a6cdb934c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -316,7 +316,7 @@ void batadv_interface_rx(struct net_device *soft_iface, skb_pull_rcsum(skb, hdr_size); skb_reset_mac_header(skb); - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = eth_hdr(skb); switch (ntohs(ethhdr->h_proto)) { case ETH_P_8021Q: -- GitLab From 24a5deeb8a198f0a26ae04485d9976c5e414f723 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 8 Apr 2013 09:38:12 +0200 Subject: [PATCH 0474/2900] batman-adv: move ring_buffer helper functions in bat_iv_ogm the two lonely ring_buffer helper functions are used by the bat_iv_ogm module only and therefore they can be moved inside it. Reported-by: Marek Lindner Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/Makefile | 1 - net/batman-adv/bat_iv_ogm.c | 43 +++++++++++++++++++++++++++++- net/batman-adv/ring_buffer.c | 51 ------------------------------------ net/batman-adv/ring_buffer.h | 27 ------------------- 4 files changed, 42 insertions(+), 80 deletions(-) delete mode 100644 net/batman-adv/ring_buffer.c delete mode 100644 net/batman-adv/ring_buffer.h diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index acbac2a9c62f..489bb36f1b94 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile @@ -32,7 +32,6 @@ batman-adv-y += icmp_socket.o batman-adv-y += main.o batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o batman-adv-y += originator.o -batman-adv-y += ring_buffer.o batman-adv-y += routing.o batman-adv-y += send.o batman-adv-y += soft-interface.o diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index ef41be49b314..31c2891c2cd0 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -19,7 +19,6 @@ #include "main.h" #include "translation-table.h" -#include "ring_buffer.h" #include "originator.h" #include "routing.h" #include "gateway_common.h" @@ -29,6 +28,48 @@ #include "bat_algo.h" #include "network-coding.h" +/** + * batadv_ring_buffer_set - update the ring buffer with the given value + * @lq_recv: pointer to the ring buffer + * @lq_index: index to store the value at + * @value: value to store in the ring buffer + */ +static void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, + uint8_t value) +{ + lq_recv[*lq_index] = value; + *lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE; +} + +/** + * batadv_ring_buffer_set - compute the average of all non-zero values stored + * in the given ring buffer + * @lq_recv: pointer to the ring buffer + * + * Returns computed average value. + */ +static uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[]) +{ + const uint8_t *ptr; + uint16_t count = 0, i = 0, sum = 0; + + ptr = lq_recv; + + while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) { + if (*ptr != 0) { + count++; + sum += *ptr; + } + + i++; + ptr++; + } + + if (count == 0) + return 0; + + return (uint8_t)(sum / count); +} static struct batadv_neigh_node * batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, const uint8_t *neigh_addr, diff --git a/net/batman-adv/ring_buffer.c b/net/batman-adv/ring_buffer.c deleted file mode 100644 index ccab0bbdbb59..000000000000 --- a/net/batman-adv/ring_buffer.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - */ - -#include "main.h" -#include "ring_buffer.h" - -void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, - uint8_t value) -{ - lq_recv[*lq_index] = value; - *lq_index = (*lq_index + 1) % BATADV_TQ_GLOBAL_WINDOW_SIZE; -} - -uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[]) -{ - const uint8_t *ptr; - uint16_t count = 0, i = 0, sum = 0; - - ptr = lq_recv; - - while (i < BATADV_TQ_GLOBAL_WINDOW_SIZE) { - if (*ptr != 0) { - count++; - sum += *ptr; - } - - i++; - ptr++; - } - - if (count == 0) - return 0; - - return (uint8_t)(sum / count); -} diff --git a/net/batman-adv/ring_buffer.h b/net/batman-adv/ring_buffer.h deleted file mode 100644 index 3f92ae248e83..000000000000 --- a/net/batman-adv/ring_buffer.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2007-2013 B.A.T.M.A.N. contributors: - * - * Marek Lindner - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - */ - -#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_ -#define _NET_BATMAN_ADV_RING_BUFFER_H_ - -void batadv_ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, - uint8_t value); -uint8_t batadv_ring_buffer_avg(const uint8_t lq_recv[]); - -#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */ -- GitLab From d98966173213704873864c4e5057d823996ae95d Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 17 Apr 2013 17:44:43 +0200 Subject: [PATCH 0475/2900] batman-adv: move batadv_slide_own_bcast_window to bat_iv_ogm.c batadv_slide_own_bcast_window() is used only in bat_iv_ogm.c and it is currently touching only batman_iv specific attributes. Move it into bat_iv_ogm.c and make it static. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 37 ++++++++++++++++++++++++++++++++++++- net/batman-adv/routing.c | 29 ----------------------------- net/batman-adv/routing.h | 1 - 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 31c2891c2cd0..42b7a94d61b3 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -630,6 +630,41 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, if_incoming, 0, batadv_iv_ogm_fwd_send_time()); } +/** + * batadv_iv_ogm_slide_own_bcast_window - bitshift own OGM broadcast windows for + * the given interface + * @hard_iface: the interface for which the windows have to be shifted + */ +static void +batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) +{ + struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct batadv_hashtable *hash = bat_priv->orig_hash; + struct hlist_head *head; + struct batadv_orig_node *orig_node; + unsigned long *word; + uint32_t i; + size_t word_index; + uint8_t *w; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_node, head, hash_entry) { + spin_lock_bh(&orig_node->ogm_cnt_lock); + word_index = hard_iface->if_num * BATADV_NUM_WORDS; + word = &(orig_node->bcast_own[word_index]); + + batadv_bit_get_packet(bat_priv, word, 1, 0); + w = &orig_node->bcast_own_sum[hard_iface->if_num]; + *w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE); + spin_unlock_bh(&orig_node->ogm_cnt_lock); + } + rcu_read_unlock(); + } +} + static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) { struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); @@ -674,7 +709,7 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; } - batadv_slide_own_bcast_window(hard_iface); + batadv_iv_ogm_slide_own_bcast_window(hard_iface); batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, batadv_iv_ogm_emit_send_time(bat_priv)); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index beeab2e8cd66..fad08469767d 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -34,35 +34,6 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, struct batadv_hard_iface *recv_if); -void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface) -{ - struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); - struct batadv_hashtable *hash = bat_priv->orig_hash; - struct hlist_head *head; - struct batadv_orig_node *orig_node; - unsigned long *word; - uint32_t i; - size_t word_index; - uint8_t *w; - - for (i = 0; i < hash->size; i++) { - head = &hash->table[i]; - - rcu_read_lock(); - hlist_for_each_entry_rcu(orig_node, head, hash_entry) { - spin_lock_bh(&orig_node->ogm_cnt_lock); - word_index = hard_iface->if_num * BATADV_NUM_WORDS; - word = &(orig_node->bcast_own[word_index]); - - batadv_bit_get_packet(bat_priv, word, 1, 0); - w = &orig_node->bcast_own_sum[hard_iface->if_num]; - *w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE); - spin_unlock_bh(&orig_node->ogm_cnt_lock); - } - rcu_read_unlock(); - } -} - static void _batadv_update_route(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, struct batadv_neigh_node *neigh_node) diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index 99eeafaba407..72a29bde2010 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -20,7 +20,6 @@ #ifndef _NET_BATMAN_ADV_ROUTING_H_ #define _NET_BATMAN_ADV_ROUTING_H_ -void batadv_slide_own_bcast_window(struct batadv_hard_iface *hard_iface); bool batadv_check_management_packet(struct sk_buff *skb, struct batadv_hard_iface *hard_iface, int header_len); -- GitLab From 3abe4adbfb293e37d2d6f4fe22366534dc2675d9 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 3 Apr 2013 11:15:33 +0200 Subject: [PATCH 0476/2900] batman-adv: refactor batadv_tt_local_event() Instead of passing a generic combination of flags as argument, it is easier to pass the entire tt_common structure (containing the flags already set) plus a bitfield of event flags that will be unified with the already existing ones before inserting the client in the event queue. In this way invocations of the modified function can be simplified. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 9e8748575845..d35b73904e04 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -163,10 +163,19 @@ batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); } +/** + * batadv_tt_local_event - store a local TT event (ADD/DEL) + * @bat_priv: the bat priv with all the soft interface information + * @tt_local_entry: the TT entry involved in the event + * @event_flags: flags to store in the event structure + */ static void batadv_tt_local_event(struct batadv_priv *bat_priv, - const uint8_t *addr, uint8_t flags) + struct batadv_tt_local_entry *tt_local_entry, + uint8_t event_flags) { struct batadv_tt_change_node *tt_change_node, *entry, *safe; + struct batadv_tt_common_entry *common = &tt_local_entry->common; + uint8_t flags = common->flags | event_flags; bool event_removed = false; bool del_op_requested, del_op_entry; @@ -176,7 +185,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, return; tt_change_node->change.flags = flags; - memcpy(tt_change_node->change.addr, addr, ETH_ALEN); + memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); del_op_requested = flags & BATADV_TT_CLIENT_DEL; @@ -184,7 +193,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, spin_lock_bh(&bat_priv->tt.changes_list_lock); list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, list) { - if (!batadv_compare_eth(entry->change.addr, addr)) + if (!batadv_compare_eth(entry->change.addr, common->addr)) continue; /* DEL+ADD in the same orig interval have no effect and can be @@ -332,7 +341,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, } add_event: - batadv_tt_local_event(bat_priv, addr, tt_local->common.flags); + batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS); check_roaming: /* Check whether it is a roaming, but don't do anything if the roaming @@ -529,8 +538,7 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv, struct batadv_tt_local_entry *tt_local_entry, uint16_t flags, const char *message) { - batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, - tt_local_entry->common.flags | flags); + batadv_tt_local_event(bat_priv, tt_local_entry, flags); /* The local client has to be marked as "pending to be removed" but has * to be kept in the table in order to send it in a full table @@ -584,8 +592,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, /* if this client has been added right now, it is possible to * immediately purge it */ - batadv_tt_local_event(bat_priv, tt_local_entry->common.addr, - curr_flags | BATADV_TT_CLIENT_DEL); + batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); hlist_del_rcu(&tt_local_entry->common.hash_entry); batadv_tt_local_entry_free_ref(tt_local_entry); -- GitLab From 41ab6c4891ed4cdd855ae569924acb1da424a614 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 2 Apr 2013 22:28:44 +0200 Subject: [PATCH 0477/2900] batman-adv: don't deal with NET_IP_ALIGN manually Instead of dealing with NET_IP_ALIGN during allocation and headroom reservation, it is possible to use netdev_alloc_skb_ip_align() which transparently allocate and reserve the correct amount of data Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bat_iv_ogm.c | 6 +++--- net/batman-adv/icmp_socket.c | 4 ++-- net/batman-adv/translation-table.c | 20 ++++++++++---------- net/batman-adv/vis.c | 12 ++++++------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 42b7a94d61b3..5b0a043c47c8 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -453,16 +453,16 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, else skb_size = packet_len; - skb_size += ETH_HLEN + NET_IP_ALIGN; + skb_size += ETH_HLEN; - forw_packet_aggr->skb = dev_alloc_skb(skb_size); + forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size); if (!forw_packet_aggr->skb) { if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); kfree(forw_packet_aggr); goto out; } - skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(forw_packet_aggr->skb, ETH_HLEN); INIT_HLIST_NODE(&forw_packet_aggr->list); diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 0ba6c899b2d3..b27508b8085c 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -177,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, if (len >= sizeof(struct batadv_icmp_packet_rr)) packet_len = sizeof(struct batadv_icmp_packet_rr); - skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN); if (!skb) { len = -ENOMEM; goto out; } - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len); if (copy_from_user(icmp_packet, buff, packet_len)) { diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index d35b73904e04..52808c4ae081 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1607,11 +1607,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, tt_tot = tt_len / sizeof(struct batadv_tt_change); len = tt_query_size + tt_len; - skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); if (!skb) goto out; - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len); tt_response->ttvn = ttvn; @@ -1672,11 +1672,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv, if (!tt_req_node) goto out; - skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN); if (!skb) goto out; - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); tt_req_len = sizeof(*tt_request); tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len); @@ -1769,11 +1769,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, tt_tot = tt_len / sizeof(struct batadv_tt_change); len = sizeof(*tt_response) + tt_len; - skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); if (!skb) goto unlock; - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); packet_pos = skb_put(skb, len); tt_response = (struct batadv_tt_query_packet *)packet_pos; tt_response->ttvn = req_ttvn; @@ -1885,11 +1885,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, tt_tot = tt_len / sizeof(struct batadv_tt_change); len = sizeof(*tt_response) + tt_len; - skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); if (!skb) goto unlock; - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); packet_pos = skb_put(skb, len); tt_response = (struct batadv_tt_query_packet *)packet_pos; tt_response->ttvn = req_ttvn; @@ -2219,11 +2219,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, if (!batadv_tt_check_roam_count(bat_priv, client)) goto out; - skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN); + skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); if (!skb) goto out; - skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(skb, ETH_HLEN); roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len); diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index 1625e5793a89..94eaeb521c17 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -392,12 +392,12 @@ batadv_add_packet(struct batadv_priv *bat_priv, return NULL; len = sizeof(*packet) + vis_info_len; - info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN); + info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN); if (!info->skb_packet) { kfree(info); return NULL; } - skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(info->skb_packet, ETH_HLEN); packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len); kref_init(&info->refcount); @@ -854,13 +854,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv) if (!bat_priv->vis.my_info) goto err; - len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE; - len += ETH_HLEN + NET_IP_ALIGN; - bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len); + len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN; + bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL, + len); if (!bat_priv->vis.my_info->skb_packet) goto free_info; - skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN); + skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN); tmp_skb = bat_priv->vis.my_info->skb_packet; packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet)); -- GitLab From d4ff40f683221d46c351cd9ab61f37a6ea5d2444 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 18 Apr 2013 15:13:01 +0200 Subject: [PATCH 0478/2900] batman-adv: pass a 16bit long flag argument to tt_global_add() it may be the case that we want to store some local TT client flags in a global entry, therefore the tt_global_add needs to get a proper argument for this Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/translation-table.c | 19 +++++++++++++++++-- net/batman-adv/translation-table.h | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 52808c4ae081..e272f68e1b08 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -798,10 +798,25 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, batadv_tt_orig_list_entry_free_ref(orig_entry); } -/* caller must hold orig_node refcount */ +/** + * batadv_tt_global_add - add a new TT global entry or update an existing one + * @bat_priv: the bat priv with all the soft interface information + * @orig_node: the originator announcing the client + * @tt_addr: the mac address of the non-mesh client + * @flags: TT flags that have to be set for this non-mesh client + * @ttvn: the tt version number ever announcing this non-mesh client + * + * Add a new TT global entry for the given originator. If the entry already + * exists add a new reference to the given originator (a global entry can have + * references to multiple originators) and adjust the flags attribute to reflect + * the function argument. + * If a TT local entry exists for this non-mesh client remove it. + * + * The caller must hold orig_node refcount. + */ int batadv_tt_global_add(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, - const unsigned char *tt_addr, uint8_t flags, + const unsigned char *tt_addr, uint16_t flags, uint8_t ttvn) { struct batadv_tt_global_entry *tt_global_entry; diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index ab8e683b402f..659a3bb759ce 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -33,7 +33,7 @@ void batadv_tt_global_add_orig(struct batadv_priv *bat_priv, const unsigned char *tt_buff, int tt_buff_len); int batadv_tt_global_add(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, - const unsigned char *addr, uint8_t flags, + const unsigned char *addr, uint16_t flags, uint8_t ttvn); int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, -- GitLab From e54c77f08ec62434ac8b24e402aa7b787cf42198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Fri, 19 Apr 2013 12:06:56 +0200 Subject: [PATCH 0479/2900] batman-adv: Remove unnecessary INIT_HLIST_NODE() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no need to for an explicit hlist_node initialization if it is added to a list right away, like it's the case with the hlist_add_head()s here. Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bat_iv_ogm.c | 2 -- net/batman-adv/send.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 5b0a043c47c8..d07323b3e9b8 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -464,8 +464,6 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, } skb_reserve(forw_packet_aggr->skb, ETH_HLEN); - INIT_HLIST_NODE(&forw_packet_aggr->list); - skb_buff = skb_put(forw_packet_aggr->skb, packet_len); forw_packet_aggr->packet_len = packet_len; memcpy(skb_buff, packet_buff, packet_len); diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index ed7072ad84e8..ce69f458a754 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -152,8 +152,6 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet, unsigned long send_time) { - INIT_HLIST_NODE(&forw_packet->list); - /* add new packet to packet list */ spin_lock_bh(&bat_priv->forw_bcast_list_lock); hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); -- GitLab From aa27c31265f111ff73d948a5846a3f193376491e Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 18 Apr 2013 04:56:03 +0800 Subject: [PATCH 0480/2900] batman-adv: do not print orig nodes without nc neighbors on nc table print Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/network-coding.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 0787a34609b9..22cd51fea730 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1763,6 +1763,13 @@ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset) /* For each orig_node in this bin */ rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, head, hash_entry) { + /* no need to print the orig node if it does not have + * network coding neighbors + */ + if (list_empty(&orig_node->in_coding_list) && + list_empty(&orig_node->out_coding_list)) + continue; + seq_printf(seq, "Node: %pM\n", orig_node->orig); seq_puts(seq, " Ingoing: "); -- GitLab From eb2deb6b39b1597577c1635e9ebf319f1ae02213 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 19 Apr 2013 18:07:00 +0200 Subject: [PATCH 0481/2900] batman-adv: change VID semantic in the BLA code In order to make batman-adv fully vlan aware later, the semantic used for variables storing the VLAN ID values has to be changed in order to be adapted to the new one which will be used batman-adv wide. In particular, the VID has to be an "_unsigned_ short int" and its 4 MSB will be used as a flag bitfield, while the remaining 12 bits are used to store the real VID value Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner Acked-by: Simon Wunderlich --- net/batman-adv/bridge_loop_avoidance.c | 51 ++++++++++++++------------ net/batman-adv/bridge_loop_avoidance.h | 12 +++--- net/batman-adv/main.h | 11 ++++++ net/batman-adv/soft-interface.c | 4 +- net/batman-adv/types.h | 4 +- 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 082189e2e40d..7354063567bd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -180,7 +180,7 @@ static struct batadv_bla_claim */ static struct batadv_bla_backbone_gw * batadv_backbone_hash_find(struct batadv_priv *bat_priv, - uint8_t *addr, short vid) + uint8_t *addr, unsigned short vid) { struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; struct hlist_head *head; @@ -257,7 +257,7 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw) * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...) */ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, - short vid, int claimtype) + unsigned short vid, int claimtype) { struct sk_buff *skb; struct ethhdr *ethhdr; @@ -335,13 +335,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, memcpy(hw_src, mac, ETH_ALEN); memcpy(ethhdr->h_dest, mac, ETH_ALEN); batadv_dbg(BATADV_DBG_BLA, bat_priv, - "bla_send_claim(): REQUEST of %pM to %pMon vid %d\n", + "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", ethhdr->h_source, ethhdr->h_dest, vid); break; } - if (vid != -1) - skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), vid); + if (vid & BATADV_VLAN_HAS_TAG) + skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), + vid & VLAN_VID_MASK); skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, soft_iface); @@ -367,7 +368,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, */ static struct batadv_bla_backbone_gw * batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, - short vid, bool own_backbone) + unsigned short vid, bool own_backbone) { struct batadv_bla_backbone_gw *entry; struct batadv_orig_node *orig_node; @@ -434,7 +435,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, static void batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, - short vid) + unsigned short vid) { struct batadv_bla_backbone_gw *backbone_gw; @@ -456,7 +457,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv, */ static void batadv_bla_answer_request(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, - short vid) + unsigned short vid) { struct hlist_head *head; struct batadv_hashtable *hash; @@ -547,7 +548,7 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, * @backbone_gw: the backbone gateway which claims it */ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, - const uint8_t *mac, const short vid, + const uint8_t *mac, const unsigned short vid, struct batadv_bla_backbone_gw *backbone_gw) { struct batadv_bla_claim *claim; @@ -611,7 +612,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, * given mac address and vid. */ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, - const uint8_t *mac, const short vid) + const uint8_t *mac, const unsigned short vid) { struct batadv_bla_claim search_claim, *claim; @@ -637,7 +638,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, /* check for ANNOUNCE frame, return 1 if handled */ static int batadv_handle_announce(struct batadv_priv *bat_priv, uint8_t *an_addr, uint8_t *backbone_addr, - short vid) + unsigned short vid) { struct batadv_bla_backbone_gw *backbone_gw; uint16_t crc; @@ -685,7 +686,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, static int batadv_handle_request(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, uint8_t *backbone_addr, - struct ethhdr *ethhdr, short vid) + struct ethhdr *ethhdr, unsigned short vid) { /* check for REQUEST frame */ if (!batadv_compare_eth(backbone_addr, ethhdr->h_dest)) @@ -709,7 +710,7 @@ static int batadv_handle_request(struct batadv_priv *bat_priv, static int batadv_handle_unclaim(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, uint8_t *backbone_addr, - uint8_t *claim_addr, short vid) + uint8_t *claim_addr, unsigned short vid) { struct batadv_bla_backbone_gw *backbone_gw; @@ -738,7 +739,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, static int batadv_handle_claim(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, uint8_t *backbone_addr, uint8_t *claim_addr, - short vid) + unsigned short vid) { struct batadv_bla_backbone_gw *backbone_gw; @@ -861,7 +862,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, struct batadv_bla_claim_dst *bla_dst; uint16_t proto; int headlen; - short vid = -1; + unsigned short vid = BATADV_NO_FLAGS; int ret; ethhdr = eth_hdr(skb); @@ -869,6 +870,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { vhdr = (struct vlan_ethhdr *)ethhdr; vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + vid |= BATADV_VLAN_HAS_TAG; proto = ntohs(vhdr->h_vlan_encapsulated_proto); headlen = sizeof(*vhdr); } else { @@ -1358,7 +1360,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb, struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; struct batadv_bla_backbone_gw *backbone_gw; - short vid = -1; + unsigned short vid = BATADV_NO_FLAGS; if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance)) return 0; @@ -1375,6 +1377,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb, vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size); vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; + vid |= BATADV_VLAN_HAS_TAG; } /* see if this originator is a backbone gw for this VLAN */ @@ -1424,8 +1427,8 @@ void batadv_bla_free(struct batadv_priv *bat_priv) * returns 1, otherwise it returns 0 and the caller shall further * process the skb. */ -int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, - bool is_bcast) +int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, + unsigned short vid, bool is_bcast) { struct ethhdr *ethhdr; struct batadv_bla_claim search_claim, *claim = NULL; @@ -1519,7 +1522,8 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, * returns 1, otherwise it returns 0 and the caller shall further * process the skb. */ -int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid) +int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, + unsigned short vid) { struct ethhdr *ethhdr; struct batadv_bla_claim search_claim, *claim = NULL; @@ -1623,7 +1627,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) hlist_for_each_entry_rcu(claim, head, hash_entry) { is_own = batadv_compare_eth(claim->backbone_gw->orig, primary_addr); - seq_printf(seq, " * %pM on % 5d by %pM [%c] (%#.4x)\n", + seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n", claim->addr, claim->vid, claim->backbone_gw->orig, (is_own ? 'x' : ' '), @@ -1676,10 +1680,9 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) if (is_own) continue; - seq_printf(seq, - " * %pM on % 5d % 4i.%03is (%#.4x)\n", - backbone_gw->orig, backbone_gw->vid, - secs, msecs, backbone_gw->crc); + seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n", + backbone_gw->orig, backbone_gw->vid, secs, + msecs, backbone_gw->crc); } rcu_read_unlock(); } diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index dea2fbc5d98d..4b102e71e5bd 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h @@ -21,9 +21,10 @@ #define _NET_BATMAN_ADV_BLA_H_ #ifdef CONFIG_BATMAN_ADV_BLA -int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, - bool is_bcast); -int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid); +int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, + unsigned short vid, bool is_bcast); +int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, + unsigned short vid); int batadv_bla_is_backbone_gw(struct sk_buff *skb, struct batadv_orig_node *orig_node, int hdr_size); int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); @@ -42,13 +43,14 @@ void batadv_bla_free(struct batadv_priv *bat_priv); #else /* ifdef CONFIG_BATMAN_ADV_BLA */ static inline int batadv_bla_rx(struct batadv_priv *bat_priv, - struct sk_buff *skb, short vid, bool is_bcast) + struct sk_buff *skb, unsigned short vid, + bool is_bcast) { return 0; } static inline int batadv_bla_tx(struct batadv_priv *bat_priv, - struct sk_buff *skb, short vid) + struct sk_buff *skb, unsigned short vid) { return 0; } diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index ea1a3bafe9c3..6f25ef29f305 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -162,6 +162,17 @@ enum batadv_uev_type { #include #include "types.h" +/** + * batadv_vlan_flags - flags for the four MSB of any vlan ID field + * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not + */ +enum batadv_vlan_flags { + BATADV_VLAN_HAS_TAG = BIT(15), +}; + +#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \ + (int)(vid & VLAN_VID_MASK) : -1) + extern char batadv_routing_algo[]; extern struct list_head batadv_hardif_list; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index b26a6cdb934c..700d0b49742d 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -154,7 +154,7 @@ static int batadv_interface_tx(struct sk_buff *skb, 0x00, 0x00}; unsigned int header_len = 0; int data_len = skb->len, ret; - short vid __maybe_unused = -1; + unsigned short vid __maybe_unused = BATADV_NO_FLAGS; bool do_bcast = false; uint32_t seqno; unsigned long brd_delay = 1; @@ -303,7 +303,7 @@ void batadv_interface_rx(struct net_device *soft_iface, struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; struct batadv_header *batadv_header = (struct batadv_header *)skb->data; - short vid __maybe_unused = -1; + unsigned short vid __maybe_unused = BATADV_NO_FLAGS; __be16 ethertype = __constant_htons(ETH_P_BATMAN); bool is_bcast; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 5f542bdd9a4d..b2c94e139319 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -642,7 +642,7 @@ struct batadv_socket_packet { #ifdef CONFIG_BATMAN_ADV_BLA struct batadv_bla_backbone_gw { uint8_t orig[ETH_ALEN]; - short vid; + unsigned short vid; struct hlist_node hash_entry; struct batadv_priv *bat_priv; unsigned long lasttime; @@ -665,7 +665,7 @@ struct batadv_bla_backbone_gw { */ struct batadv_bla_claim { uint8_t addr[ETH_ALEN]; - short vid; + unsigned short vid; struct batadv_bla_backbone_gw *backbone_gw; unsigned long lasttime; struct hlist_node hash_entry; -- GitLab From 5f80df6705fcd8153f93bd0e82109dbeb7ff535b Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 19 Apr 2013 18:07:01 +0200 Subject: [PATCH 0482/2900] batman-adv: print the VID properly Since the MSB bits of any vid variable are now used for storing flags, print the vid properly by taking the flags away and printing -1 in case of VID representing no real VLAN. Signed-off-by: Antonio Quartulli Signed-off-by: Marek Lindner --- net/batman-adv/bridge_loop_avoidance.c | 37 +++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 7354063567bd..e9d8e0b3c3d0 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -307,7 +307,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, */ memcpy(ethhdr->h_source, mac, ETH_ALEN); batadv_dbg(BATADV_DBG_BLA, bat_priv, - "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid); + "bla_send_claim(): CLAIM %pM on vid %d\n", mac, + BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_UNCLAIM: /* unclaim frame @@ -316,7 +317,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, memcpy(hw_src, mac, ETH_ALEN); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, - vid); + BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_ANNOUNCE: /* announcement frame @@ -325,7 +326,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, memcpy(hw_src, mac, ETH_ALEN); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", - ethhdr->h_source, vid); + ethhdr->h_source, BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_REQUEST: /* request frame @@ -336,7 +337,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, memcpy(ethhdr->h_dest, mac, ETH_ALEN); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", - ethhdr->h_source, ethhdr->h_dest, vid); + ethhdr->h_source, ethhdr->h_dest, + BATADV_PRINT_VID(vid)); break; } @@ -381,7 +383,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_get_backbone_gw(): not found (%pM, %d), creating new entry\n", - orig, vid); + orig, BATADV_PRINT_VID(vid)); entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) @@ -573,7 +575,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, atomic_set(&claim->refcount, 2); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", - mac, vid); + mac, BATADV_PRINT_VID(vid)); hash_added = batadv_hash_add(bat_priv->bla.claim_hash, batadv_compare_claim, batadv_choose_claim, claim, @@ -592,7 +594,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_add_claim(): changing ownership for %pM, vid %d\n", - mac, vid); + mac, BATADV_PRINT_VID(vid)); claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); batadv_backbone_gw_free_ref(claim->backbone_gw); @@ -623,7 +625,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, return; batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n", - mac, vid); + mac, BATADV_PRINT_VID(vid)); batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim, batadv_choose_claim, claim); @@ -659,12 +661,13 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_BLA, bat_priv, "handle_announce(): ANNOUNCE vid %d (sent by %pM)... CRC = %#.4x\n", - vid, backbone_gw->orig, crc); + BATADV_PRINT_VID(vid), backbone_gw->orig, crc); if (backbone_gw->crc != crc) { batadv_dbg(BATADV_DBG_BLA, backbone_gw->bat_priv, "handle_announce(): CRC FAILED for %pM/%d (my = %#.4x, sent = %#.4x)\n", - backbone_gw->orig, backbone_gw->vid, + backbone_gw->orig, + BATADV_PRINT_VID(backbone_gw->vid), backbone_gw->crc, crc); batadv_bla_send_request(backbone_gw); @@ -700,7 +703,7 @@ static int batadv_handle_request(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_BLA, bat_priv, "handle_request(): REQUEST vid %d (sent by %pM)...\n", - vid, ethhdr->h_source); + BATADV_PRINT_VID(vid), ethhdr->h_source); batadv_bla_answer_request(bat_priv, primary_if, vid); return 1; @@ -728,7 +731,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, /* this must be an UNCLAIM frame */ batadv_dbg(BATADV_DBG_BLA, bat_priv, "handle_unclaim(): UNCLAIM %pM on vid %d (sent by %pM)...\n", - claim_addr, vid, backbone_gw->orig); + claim_addr, BATADV_PRINT_VID(vid), backbone_gw->orig); batadv_bla_del_claim(bat_priv, claim_addr, vid); batadv_backbone_gw_free_ref(backbone_gw); @@ -912,7 +915,8 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, if (ret == 1) batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n", - ethhdr->h_source, vid, hw_src, hw_dst); + ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src, + hw_dst); if (ret < 2) return ret; @@ -947,7 +951,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_process_claim(): ERROR - this looks like a claim frame, but is useless. eth src %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n", - ethhdr->h_source, vid, hw_src, hw_dst); + ethhdr->h_source, BATADV_PRINT_VID(vid), hw_src, hw_dst); return 1; } @@ -1628,7 +1632,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) is_own = batadv_compare_eth(claim->backbone_gw->orig, primary_addr); seq_printf(seq, " * %pM on %5d by %pM [%c] (%#.4x)\n", - claim->addr, claim->vid, + claim->addr, BATADV_PRINT_VID(claim->vid), claim->backbone_gw->orig, (is_own ? 'x' : ' '), claim->backbone_gw->crc); @@ -1681,7 +1685,8 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) continue; seq_printf(seq, " * %pM on %5d %4i.%03is (%#.4x)\n", - backbone_gw->orig, backbone_gw->vid, secs, + backbone_gw->orig, + BATADV_PRINT_VID(backbone_gw->vid), secs, msecs, backbone_gw->crc); } rcu_read_unlock(); -- GitLab From e91ecfc64ad691176be119e627e36cec8564f44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Hundeb=C3=B8ll?= Date: Sat, 20 Apr 2013 13:54:39 +0200 Subject: [PATCH 0483/2900] batman-adv: Move call to batadv_nc_skb_forward() from routing.c to send.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call to batadv_nc_skb_forward() fits better in batadv_send_skb_to_orig(), as this is where the actual next hop is looked up. To let the caller of batadv_send_skb_to_orig() know wether the skb is transmitted, buffered or failed, the return value is changed from boolean to int. Signed-off-by: Martin Hundebøll Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/network-coding.c | 5 ++--- net/batman-adv/network-coding.h | 6 ++---- net/batman-adv/routing.c | 23 +++++++++++++---------- net/batman-adv/send.c | 27 +++++++++++++++++++-------- net/batman-adv/send.h | 6 +++--- net/batman-adv/translation-table.c | 12 +++++++----- net/batman-adv/unicast.c | 2 +- net/batman-adv/vis.c | 7 ++++--- 8 files changed, 51 insertions(+), 37 deletions(-) diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 22cd51fea730..a487d46e0aec 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1359,18 +1359,17 @@ static bool batadv_nc_skb_add_to_path(struct sk_buff *skb, * buffer * @skb: data skb to forward * @neigh_node: next hop to forward packet to - * @ethhdr: pointer to the ethernet header inside the skb * * Returns true if the skb was consumed (encoded packet sent) or false otherwise */ bool batadv_nc_skb_forward(struct sk_buff *skb, - struct batadv_neigh_node *neigh_node, - struct ethhdr *ethhdr) + struct batadv_neigh_node *neigh_node) { const struct net_device *netdev = neigh_node->if_incoming->soft_iface; struct batadv_priv *bat_priv = netdev_priv(netdev); struct batadv_unicast_packet *packet; struct batadv_nc_path *nc_path; + struct ethhdr *ethhdr = eth_hdr(skb); __be32 packet_id; u8 *payload; diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index 4fa6d0caddbd..85a4ec81ad50 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h @@ -36,8 +36,7 @@ void batadv_nc_purge_orig(struct batadv_priv *bat_priv, void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv); void batadv_nc_init_orig(struct batadv_orig_node *orig_node); bool batadv_nc_skb_forward(struct sk_buff *skb, - struct batadv_neigh_node *neigh_node, - struct ethhdr *ethhdr); + struct batadv_neigh_node *neigh_node); void batadv_nc_skb_store_for_decoding(struct batadv_priv *bat_priv, struct sk_buff *skb); void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, @@ -87,8 +86,7 @@ static inline void batadv_nc_init_orig(struct batadv_orig_node *orig_node) } static inline bool batadv_nc_skb_forward(struct sk_buff *skb, - struct batadv_neigh_node *neigh_node, - struct ethhdr *ethhdr) + struct batadv_neigh_node *neigh_node) { return false; } diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index fad08469767d..2f0bd3ffe6e8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -285,7 +285,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, icmp_packet->msg_type = BATADV_ECHO_REPLY; icmp_packet->header.ttl = BATADV_TTL; - if (batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) ret = NET_RX_SUCCESS; out: @@ -333,7 +333,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, icmp_packet->msg_type = BATADV_TTL_EXCEEDED; icmp_packet->header.ttl = BATADV_TTL; - if (batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) ret = NET_RX_SUCCESS; out: @@ -410,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, icmp_packet->header.ttl--; /* route it */ - if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) + if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP) ret = NET_RX_SUCCESS; out: @@ -775,7 +775,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, struct batadv_neigh_node *neigh_node = NULL; struct batadv_unicast_packet *unicast_packet; struct ethhdr *ethhdr = eth_hdr(skb); - int ret = NET_RX_DROP; + int res, ret = NET_RX_DROP; struct sk_buff *new_skb; unicast_packet = (struct batadv_unicast_packet *)skb->data; @@ -835,16 +835,19 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, /* decrement ttl */ unicast_packet->header.ttl--; - /* network code packet if possible */ - if (batadv_nc_skb_forward(skb, neigh_node, ethhdr)) { - ret = NET_RX_SUCCESS; - } else if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) { - ret = NET_RX_SUCCESS; + res = batadv_send_skb_to_orig(skb, orig_node, recv_if); - /* Update stats counter */ + /* translate transmit result into receive result */ + if (res == NET_XMIT_SUCCESS) { + /* skb was transmitted and consumed */ batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, skb->len + ETH_HLEN); + + ret = NET_RX_SUCCESS; + } else if (res == NET_XMIT_POLICED) { + /* skb was buffered and consumed */ + ret = NET_RX_SUCCESS; } out: diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index ce69f458a754..e9ff8d801201 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -96,26 +96,37 @@ int batadv_send_skb_packet(struct sk_buff *skb, * host, NULL can be passed as recv_if and no interface alternating is * attempted. * - * Returns TRUE on success; FALSE otherwise. + * Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or + * NET_XMIT_POLICED if the skb is buffered for later transmit. */ -bool batadv_send_skb_to_orig(struct sk_buff *skb, - struct batadv_orig_node *orig_node, - struct batadv_hard_iface *recv_if) +int batadv_send_skb_to_orig(struct sk_buff *skb, + struct batadv_orig_node *orig_node, + struct batadv_hard_iface *recv_if) { struct batadv_priv *bat_priv = orig_node->bat_priv; struct batadv_neigh_node *neigh_node; + int ret = NET_XMIT_DROP; /* batadv_find_router() increases neigh_nodes refcount if found. */ neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); if (!neigh_node) - return false; + return ret; - /* route it */ - batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + /* try to network code the packet, if it is received on an interface + * (i.e. being forwarded). If the packet originates from this node or if + * network coding fails, then send the packet as usual. + */ + if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) { + ret = NET_XMIT_POLICED; + } else { + batadv_send_skb_packet(skb, neigh_node->if_incoming, + neigh_node->addr); + ret = NET_XMIT_SUCCESS; + } batadv_neigh_node_free_ref(neigh_node); - return true; + return ret; } void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 38e662f619ac..e7b17880fca4 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -23,9 +23,9 @@ int batadv_send_skb_packet(struct sk_buff *skb, struct batadv_hard_iface *hard_iface, const uint8_t *dst_addr); -bool batadv_send_skb_to_orig(struct sk_buff *skb, - struct batadv_orig_node *orig_node, - struct batadv_hard_iface *recv_if); +int batadv_send_skb_to_orig(struct sk_buff *skb, + struct batadv_orig_node *orig_node, + struct batadv_hard_iface *recv_if); void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface); int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, const struct sk_buff *skb, diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index e272f68e1b08..429aeef3d8b2 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1713,7 +1713,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv, batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); - if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL) != NET_XMIT_DROP) ret = 0; out: @@ -1737,7 +1737,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, struct batadv_orig_node *req_dst_orig_node; struct batadv_orig_node *res_dst_orig_node = NULL; uint8_t orig_ttvn, req_ttvn, ttvn; - int ret = false; + int res, ret = false; unsigned char *tt_buff; bool full_table; uint16_t tt_len, tt_tot; @@ -1832,8 +1832,10 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); - if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL)) + res = batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL); + if (res != NET_XMIT_DROP) ret = true; + goto out; unlock: @@ -1947,7 +1949,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); - if (batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) ret = true; goto out; @@ -2260,7 +2262,7 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); - if (batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) ret = 0; out: diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 0bb3b5982f94..dc8b5d4dd636 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -464,7 +464,7 @@ int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv, goto out; } - if (batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) ret = 0; out: diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index 94eaeb521c17..4983340f1943 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -697,7 +697,7 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node; struct batadv_vis_packet *packet; struct sk_buff *skb; - uint32_t i; + uint32_t i, res; packet = (struct batadv_vis_packet *)info->skb_packet->data; @@ -724,7 +724,8 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv, if (!skb) continue; - if (!batadv_send_skb_to_orig(skb, orig_node, NULL)) + res = batadv_send_skb_to_orig(skb, orig_node, NULL); + if (res == NET_XMIT_DROP) kfree_skb(skb); } rcu_read_unlock(); @@ -748,7 +749,7 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv, if (!skb) goto out; - if (!batadv_send_skb_to_orig(skb, orig_node, NULL)) + if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP) kfree_skb(skb); out: -- GitLab From 6715fd3f0538e805b6a769d66823ec16b8b647ac Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sat, 20 Apr 2013 17:15:09 +0200 Subject: [PATCH 0484/2900] batman-adv: Start new development cycle Signed-off-by: Simon Wunderlich Signed-off-by: Antonio Quartulli --- net/batman-adv/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 6f25ef29f305..5e9aebb7d56b 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -26,7 +26,7 @@ #define BATADV_DRIVER_DEVICE "batman-adv" #ifndef BATADV_SOURCE_VERSION -#define BATADV_SOURCE_VERSION "2013.2.0" +#define BATADV_SOURCE_VERSION "2013.3.0" #endif /* B.A.T.M.A.N. parameters */ -- GitLab From 75538c2b85cf22eb9af6adfaf26ed7219025adeb Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 29 May 2013 11:30:50 +0800 Subject: [PATCH 0485/2900] net: always pass struct netdev_notifier_info to netdevice notifiers commit 351638e7deeed2ec8ce451b53d3 (net: pass info struct via netdevice notifier) breaks booting of my KVM guest, this is due to we still forget to pass struct netdev_notifier_info in several places. This patch completes it. Cc: Jiri Pirko Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 ++++++ net/atm/clip.c | 4 +++- net/core/dev.c | 6 ------ net/ipv4/netfilter/ipt_MASQUERADE.c | 5 ++++- net/ipv6/addrconf.c | 7 +++++-- net/ipv6/netfilter/ip6t_MASQUERADE.c | 4 +++- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 850271809a9e..8f967e34142b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1609,6 +1609,12 @@ struct netdev_notifier_change_info { unsigned int flags_changed; }; +static inline void netdev_notifier_info_init(struct netdev_notifier_info *info, + struct net_device *dev) +{ + info->dev = dev; +} + static inline struct net_device * netdev_notifier_info_to_dev(const struct netdev_notifier_info *info) { diff --git a/net/atm/clip.c b/net/atm/clip.c index cce241eb01d9..8215f7cb170b 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -575,6 +575,7 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event, void *ifa) { struct in_device *in_dev; + struct netdev_notifier_info info; in_dev = ((struct in_ifaddr *)ifa)->ifa_dev; /* @@ -583,7 +584,8 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event, */ if (event != NETDEV_UP) return NOTIFY_DONE; - return clip_device_event(this, NETDEV_CHANGE, in_dev->dev); + netdev_notifier_info_init(&info, in_dev->dev); + return clip_device_event(this, NETDEV_CHANGE, &info); } static struct notifier_block clip_dev_notifier = { diff --git a/net/core/dev.c b/net/core/dev.c index 6eb621cc3b81..b2e9057be3bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1391,12 +1391,6 @@ void dev_disable_lro(struct net_device *dev) } EXPORT_SYMBOL(dev_disable_lro); -static void netdev_notifier_info_init(struct netdev_notifier_info *info, - struct net_device *dev) -{ - info->dev = dev; -} - static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val, struct net_device *dev) { diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index dd5508bde799..30e4de940567 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -129,7 +129,10 @@ static int masq_inet_event(struct notifier_block *this, void *ptr) { struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; - return masq_device_event(this, event, dev); + struct netdev_notifier_info info; + + netdev_notifier_info_init(&info, dev); + return masq_device_event(this, event, &info); } static struct notifier_block masq_dev_notifier = { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index bce073b4bbd4..7b34f06af344 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4645,13 +4645,16 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, static void dev_disable_change(struct inet6_dev *idev) { + struct netdev_notifier_info info; + if (!idev || !idev->dev) return; + netdev_notifier_info_init(&info, idev->dev); if (idev->cnf.disable_ipv6) - addrconf_notify(NULL, NETDEV_DOWN, idev->dev); + addrconf_notify(NULL, NETDEV_DOWN, &info); else - addrconf_notify(NULL, NETDEV_UP, idev->dev); + addrconf_notify(NULL, NETDEV_UP, &info); } static void addrconf_disable_change(struct net *net, __s32 newf) diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c index b76257cd7e1e..47bff6107519 100644 --- a/net/ipv6/netfilter/ip6t_MASQUERADE.c +++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c @@ -89,8 +89,10 @@ static int masq_inet_event(struct notifier_block *this, unsigned long event, void *ptr) { struct inet6_ifaddr *ifa = ptr; + struct netdev_notifier_info info; - return masq_device_event(this, event, ifa->idev->dev); + netdev_notifier_info_init(&info, ifa->idev->dev); + return masq_device_event(this, event, &info); } static struct notifier_block masq_inet_notifier = { -- GitLab From 25b6e14881e7861bb720a4624dcaf5f37854fc70 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:23 +0000 Subject: [PATCH 0486/2900] isdn: Correct comparison of skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that the comparison is always between pointers. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 88d657dff474..8b98d53d9976 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp) addinfo[0] = '\0'; /* This check stolen from 2.1.72 dev_queue_xmit_nit() */ - if (p < skb->data || skb->network_header >= skb->tail) { + if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) { /* fall back to old isdn_net_log_packet method() */ char *buf = skb->data; -- GitLab From be8b678c6c63010cd2b0f4f602bd3066f7827fb2 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:24 +0000 Subject: [PATCH 0487/2900] cxgb3: Correct comparisons and calculations using skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that comparisons and calculations are always made using pointers. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/sge.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 2fd773e267dc..46d1efc17527 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -1584,9 +1584,8 @@ static void deferred_unmap_destructor(struct sk_buff *skb) p = dui->addr; if (skb->tail - skb->transport_header) - pci_unmap_single(dui->pdev, *p++, - skb->tail - skb->transport_header, - PCI_DMA_TODEVICE); + pci_unmap_single(dui->pdev, *p++, skb_tail_pointer(skb) - + skb_transport_header(skb), PCI_DMA_TODEVICE); si = skb_shinfo(skb); for (i = 0; i < si->nr_frags; i++) @@ -1647,8 +1646,8 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb, flits = skb_transport_offset(skb) / 8; sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl; sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb), - skb->tail - skb->transport_header, - addr); + skb_tail_pointer(skb) - + skb_transport_header(skb), addr); if (need_skb_unmap()) { setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits); skb->destructor = deferred_unmap_destructor; @@ -1674,7 +1673,7 @@ static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb) flits = skb_transport_offset(skb) / 8; /* headers */ cnt = skb_shinfo(skb)->nr_frags; - if (skb->tail != skb->transport_header) + if (skb_tail_pointer(skb) != skb_transport_header(skb)) cnt++; return flits_to_desc(flits + sgl_len(cnt)); } -- GitLab From ced14f6804a979d1972415bc23f2f8ddb18595dd Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:25 +0000 Subject: [PATCH 0488/2900] net: Correct comparisons and calculations using skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that comparisons and calculations are always made using pointers. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/net/inet_ecn.h | 6 ++++-- net/core/dev.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index aab73757bc4d..3bd22795c3e2 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -134,12 +134,14 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb) { switch (skb->protocol) { case cpu_to_be16(ETH_P_IP): - if (skb->network_header + sizeof(struct iphdr) <= skb->tail) + if (skb_network_header(skb) + sizeof(struct iphdr) <= + skb_tail_pointer(skb)) return IP_ECN_set_ce(ip_hdr(skb)); break; case cpu_to_be16(ETH_P_IPV6): - if (skb->network_header + sizeof(struct ipv6hdr) <= skb->tail) + if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= + skb_tail_pointer(skb)) return IP6_ECN_set_ce(ipv6_hdr(skb)); break; } diff --git a/net/core/dev.c b/net/core/dev.c index b2e9057be3bf..d4d874a25e45 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1724,7 +1724,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb2); if (skb_network_header(skb2) < skb2->data || - skb2->network_header > skb2->tail) { + skb_network_header(skb2) > skb_tail_pointer(skb2)) { net_crit_ratelimited("protocol %04x is buggy, dev %s\n", ntohs(skb2->protocol), dev->name); @@ -3892,7 +3892,7 @@ static void skb_gro_reset_offset(struct sk_buff *skb) NAPI_GRO_CB(skb)->frag0 = NULL; NAPI_GRO_CB(skb)->frag0_len = 0; - if (skb->mac_header == skb->tail && + if (skb_mac_header(skb) == skb_tail_pointer(skb) && pinfo->nr_frags && !PageHighMem(skb_frag_page(frag0))) { NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0); -- GitLab From 29a3cad5c6ae9e7fbf1509d01d39c3c3c38f11f9 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:26 +0000 Subject: [PATCH 0489/2900] ipv6: Correct comparisons and calculations using skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that comparisons and calculations are always made using pointers. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/ipv6/exthdrs_core.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/mcast.c | 5 +++-- net/ipv6/mip6.c | 6 ++++-- net/ipv6/ndisc.c | 9 +++++---- net/ipv6/output_core.c | 3 ++- net/ipv6/raw.c | 3 ++- net/ipv6/route.c | 2 +- 8 files changed, 19 insertions(+), 13 deletions(-) diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index c5e83fae4df4..140748debc4a 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -115,7 +115,7 @@ EXPORT_SYMBOL(ipv6_skip_exthdr); int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) { const unsigned char *nh = skb_network_header(skb); - int packet_len = skb->tail - skb->network_header; + int packet_len = skb_tail_pointer(skb) - skb_network_header(skb); struct ipv6_opt_hdr *hdr; int len; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 1d2902e61786..4b4890bbe16d 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -399,7 +399,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) int err = 0; if ((u8 *)hdr < skb->head || - (skb->network_header + sizeof(*hdr)) > skb->tail) + (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb)) return; /* diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index bfa6cc36ef2a..72c8bfe06bb4 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1409,8 +1409,9 @@ static void mld_sendpack(struct sk_buff *skb) idev = __in6_dev_get(skb->dev); IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); - payload_len = (skb->tail - skb->network_header) - sizeof(*pip6); - mldlen = skb->tail - skb->transport_header; + payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) - + sizeof(*pip6); + mldlen = skb_tail_pointer(skb) - skb_transport_header(skb); pip6->payload_len = htons(payload_len); pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 0f9bdc5ee9f3..9ac01dc9402e 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -268,7 +268,8 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); const unsigned char *nh = skb_network_header(skb); - unsigned int packet_len = skb->tail - skb->network_header; + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); int found_rhdr = 0; *nexthdr = &ipv6_hdr(skb)->nexthdr; @@ -404,7 +405,8 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); const unsigned char *nh = skb_network_header(skb); - unsigned int packet_len = skb->tail - skb->network_header; + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); int found_rhdr = 0; *nexthdr = &ipv6_hdr(skb)->nexthdr; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index a0962697a257..781dd3c99680 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -693,7 +693,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; - u32 ndoptlen = skb->tail - (skb->transport_header + + u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + offsetof(struct nd_msg, opt)); struct ndisc_options ndopts; struct net_device *dev = skb->dev; @@ -853,7 +853,7 @@ static void ndisc_recv_na(struct sk_buff *skb) const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; u8 *lladdr = NULL; - u32 ndoptlen = skb->tail - (skb->transport_header + + u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + offsetof(struct nd_msg, opt)); struct ndisc_options ndopts; struct net_device *dev = skb->dev; @@ -1069,7 +1069,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) __u8 * opt = (__u8 *)(ra_msg + 1); - optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg); + optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - + sizeof(struct ra_msg); if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { ND_PRINTK(2, warn, "RA: source address is not link-local\n"); @@ -1346,7 +1347,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) u8 *hdr; struct ndisc_options ndopts; struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb); - u32 ndoptlen = skb->tail - (skb->transport_header + + u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + offsetof(struct rd_msg, opt)); #ifdef CONFIG_IPV6_NDISC_NODETYPE diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index c2e73e647e44..ab92a3673fbb 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -40,7 +40,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) u16 offset = sizeof(struct ipv6hdr); struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); - unsigned int packet_len = skb->tail - skb->network_header; + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); int found_rhdr = 0; *nexthdr = &ipv6_hdr(skb)->nexthdr; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index eedff8ccded5..4f8886aa8429 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1132,7 +1132,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) spin_lock_bh(&sk->sk_receive_queue.lock); skb = skb_peek(&sk->sk_receive_queue); if (skb != NULL) - amount = skb->tail - skb->transport_header; + amount = skb_tail_pointer(skb) - + skb_transport_header(skb); spin_unlock_bh(&sk->sk_receive_queue.lock); return put_user(amount, (int __user *)arg); } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 194c3cde1536..2b874185ebb2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1649,7 +1649,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu int optlen, on_link; u8 *lladdr; - optlen = skb->tail - skb->transport_header; + optlen = skb_tail_pointer(skb) - skb_transport_header(skb); optlen -= sizeof(*msg); if (optlen < 0) { -- GitLab From f7c0c2ae843b74f8dba55820cb0a3de19c976703 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:27 +0000 Subject: [PATCH 0490/2900] ipv4: Correct comparisons and calculations using skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that comparisons and calculations are always made using pointers. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 3 ++- net/ipv4/igmp.c | 2 +- net/ipv4/tcp.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 562efd91f457..5d0d379b0152 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -503,7 +503,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) iph = ip_hdr(skb_in); if ((u8 *)iph < skb_in->head || - (skb_in->network_header + sizeof(*iph)) > skb_in->tail) + (skb_network_header(skb_in) + sizeof(*iph)) > + skb_tail_pointer(skb_in)) goto out; /* diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d8c232794bcb..450f625361e4 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -363,7 +363,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) static int igmpv3_sendpack(struct sk_buff *skb) { struct igmphdr *pig = igmp_hdr(skb); - const int igmplen = skb->tail - skb->transport_header; + const int igmplen = skb_tail_pointer(skb) - skb_transport_header(skb); pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ba4186e1dca9..1f58594d5a85 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2989,7 +2989,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, swap(gso_skb->truesize, skb->truesize); } - delta = htonl(oldlen + (skb->tail - skb->transport_header) + + delta = htonl(oldlen + (skb_tail_pointer(skb) - + skb_transport_header(skb)) + skb->data_len); th->check = ~csum_fold((__force __wsum)((__force u32)th->check + (__force u32)delta)); -- GitLab From 158874cac61245b84e939c92c53db7000122b7b0 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:28 +0000 Subject: [PATCH 0491/2900] sctp: Correct access to skb->{network, transport}_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case sk_buff_data_t will be a pointer, however, skb->{network,transport}_header is now __u16. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/sctp/input.c | 2 +- net/sctp/ipv6.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index 4b2c83146aa7..e328fe8f93f4 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) struct sctp_association *asoc = NULL; struct sctp_transport *transport; struct inet_sock *inet; - sk_buff_data_t saveip, savesctp; + __be16 saveip, savesctp; int err; struct net *net = dev_net(skb->dev); diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 391a245d5203..8ee553b499ce 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -153,7 +153,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct sctp_association *asoc; struct sctp_transport *transport; struct ipv6_pinfo *np; - sk_buff_data_t saveip, savesctp; + __be16 saveip, savesctp; int err; struct net *net = dev_net(skb->dev); -- GitLab From 7cc461900549fc480eb133948649a1edb7eaaa6f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 28 May 2013 20:34:29 +0000 Subject: [PATCH 0492/2900] net, ipv4, ipv6: Correct assignment of skb->network_header to skb->tail This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer however skb->network_header is now an offset. This patch corrects the problem by adding a wrapper to return skb tail as an offset regardless of the value of NET_SKBUFF_DATA_USES_OFFSET. It seems that skb->tail that this offset may be more than 64k and some care has been taken to treat such cases as an error. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- include/linux/skbuff.h | 9 +++++++++ net/core/netpoll.c | 9 ++++++++- net/core/pktgen.c | 16 ++++++++++++++-- net/ipv4/ipmr.c | 8 +++++++- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 8f2b830772a8..5f931191cf57 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1391,6 +1391,11 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) skb_reset_tail_pointer(skb); skb->tail += offset; } + +static inline unsigned long skb_tail_offset(const struct sk_buff *skb) +{ + return skb->tail; +} #else /* NET_SKBUFF_DATA_USES_OFFSET */ static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb) { @@ -1407,6 +1412,10 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) skb->tail = skb->data + offset; } +static inline unsigned long skb_tail_offset(const struct sk_buff *skb) +{ + return skb->tail - skb->head; +} #endif /* NET_SKBUFF_DATA_USES_OFFSET */ /* diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 37deedd48bcc..688517c7ff17 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -676,6 +676,8 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo spin_lock_irqsave(&npinfo->rx_lock, flags); list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { + unsigned long tail_offset; + if (!ipv6_addr_equal(daddr, &np->local_ip.in6)) continue; @@ -700,7 +702,12 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo hdr->saddr = *saddr; hdr->daddr = *daddr; - send_skb->transport_header = send_skb->tail; + tail_offset = skb_tail_offset(skb); + if (tail_offset > 0xffff) { + kfree_skb(send_skb); + continue; + } + skb_set_network_header(send_skb, tail_offset); skb_put(send_skb, size); icmp6h = (struct icmp6hdr *)skb_transport_header(skb); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 795498fd4587..d2ede89662be 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2642,6 +2642,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ u16 queue_map; + unsigned long tail_offset; if (pkt_dev->nr_labels) protocol = htons(ETH_P_MPLS_UC); @@ -2708,7 +2709,12 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, *vlan_encapsulated_proto = htons(ETH_P_IP); } - skb->network_header = skb->tail; + tail_offset = skb_tail_offset(skb); + if (tail_offset > 0xffff) { + kfree_skb(skb); + return NULL; + } + skb_set_network_header(skb, tail_offset); skb->transport_header = skb->network_header + sizeof(struct iphdr); skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); skb_set_queue_mapping(skb, queue_map); @@ -2775,6 +2781,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ u16 queue_map; + unsigned long tail_offset; if (pkt_dev->nr_labels) protocol = htons(ETH_P_MPLS_UC); @@ -2822,7 +2829,12 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, *vlan_encapsulated_proto = htons(ETH_P_IPV6); } - skb->network_header = skb->tail; + tail_offset = skb_tail_offset(skb); + if (tail_offset > 0xffff) { + kfree_skb(skb); + return NULL; + } + skb_set_network_header(skb, tail_offset); skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); skb_set_queue_mapping(skb, queue_map); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index f975399f3522..df97f0ac1a1c 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -945,6 +945,7 @@ static int ipmr_cache_report(struct mr_table *mrt, struct igmpmsg *msg; struct sock *mroute_sk; int ret; + unsigned long tail_offset; #ifdef CONFIG_IP_PIMSM if (assert == IGMPMSG_WHOLEPKT) @@ -980,7 +981,12 @@ static int ipmr_cache_report(struct mr_table *mrt, /* Copy the IP header */ - skb->network_header = skb->tail; + tail_offset = skb_tail_offset(skb); + if (tail_offset > 0xffff) { + kfree_skb(skb); + return -EINVAL; + } + skb_set_network_header(skb, tail_offset); skb_put(skb, ihl); skb_copy_to_linear_data(skb, pkt->data, ihl); ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */ -- GitLab From 784e4616a40166fc60a1741a2c64155e99fe9247 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 27 May 2013 22:35:51 +0000 Subject: [PATCH 0493/2900] vxlan: remove the unused rcu head from struct vxlan_rdst Cc: Stephen Hemminger Cc: David S. Miller Signed-off-by: Cong Wang Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 5ed64d496f83..289d79a48c82 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -97,7 +97,6 @@ struct vxlan_net { }; struct vxlan_rdst { - struct rcu_head rcu; __be32 remote_ip; __be16 remote_port; u32 remote_vni; -- GitLab From 31fec5aa21d166cf81702a669c1398784b513b8a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 27 May 2013 22:35:52 +0000 Subject: [PATCH 0494/2900] vxlan: use unsigned int instead of unsigned 'unsigned int' is slightly better. Cc: Stephen Hemminger Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 289d79a48c82..6fc962042046 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1269,7 +1269,7 @@ static int vxlan_open(struct net_device *dev) /* Purge the forwarding table */ static void vxlan_flush(struct vxlan_dev *vxlan) { - unsigned h; + unsigned int h; spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { @@ -1333,7 +1333,7 @@ static void vxlan_free(struct net_device *dev) static void vxlan_setup(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); - unsigned h; + unsigned int h; int low, high; eth_hw_addr_random(dev); @@ -1459,7 +1459,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) .sin_addr.s_addr = htonl(INADDR_ANY), }; int rc; - unsigned h; + unsigned int h; vs = kmalloc(sizeof(*vs), GFP_KERNEL); if (!vs) @@ -1722,7 +1722,7 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = { static __net_init int vxlan_init_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); - unsigned h; + unsigned int h; INIT_LIST_HEAD(&vn->vxlan_list); -- GitLab From 7332a13b038be05cf44fcf0cacfdd8aade77b16f Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 27 May 2013 22:35:53 +0000 Subject: [PATCH 0495/2900] vxlan: defer vxlan init as late as possible When vxlan is compiled as builtin, its init code runs before IPv6 init, this could cause problems if we create IPv6 socket in the latter patch. Cc: Stephen Hemminger Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 6fc962042046..8111565c35fc 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1771,7 +1771,7 @@ static int __init vxlan_init_module(void) out1: return rc; } -module_init(vxlan_init_module); +late_initcall(vxlan_init_module); static void __exit vxlan_cleanup_module(void) { -- GitLab From 43547ea669926b2ef8ba62a9def7b2c5728b3cdd Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 27 May 2013 23:14:51 +0000 Subject: [PATCH 0496/2900] bonding: trivial: remove unused parameter from alb_swap_mac_addr() After b924551 ("bonding: fix enslaving in alb mode when link down") we don't need the bond parameter in alb_swap_mac_addr(), so remove it. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index e02cc265723a..a236234d2c27 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1056,7 +1056,7 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[]) * */ -static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct slave *slave2) +static void alb_swap_mac_addr(struct slave *slave1, struct slave *slave2) { u8 tmp_mac_addr[ETH_ALEN]; @@ -1149,7 +1149,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla if (found) { /* locking: needs RTNL and nothing else */ - alb_swap_mac_addr(bond, slave, tmp_slave); + alb_swap_mac_addr(slave, tmp_slave); alb_fasten_mac_swap(bond, slave, tmp_slave); } } @@ -1750,7 +1750,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave /* curr_active_slave must be set before calling alb_swap_mac_addr */ if (swap_slave) { /* swap mac address */ - alb_swap_mac_addr(bond, swap_slave, new_slave); + alb_swap_mac_addr(swap_slave, new_slave); } else { /* set the new_slave to the bond mac address */ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); @@ -1810,7 +1810,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) } if (swap_slave) { - alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); + alb_swap_mac_addr(swap_slave, bond->curr_active_slave); alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); } else { alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr); -- GitLab From d6641ccff9b4d3b0d526e754dceaa4c430f5d24f Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Tue, 28 May 2013 01:26:13 +0000 Subject: [PATCH 0497/2900] bonding: trivial: update the comments to reflect the reality Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_sysfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 3d269a52789c..f8bee4c0cbf1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -231,8 +231,7 @@ static ssize_t bonding_show_slaves(struct device *d, } /* - * Set the slaves in the current bond. The bond interface must be - * up for this to succeed. + * Set the slaves in the current bond. * This is supposed to be only thin wrapper for bond_enslave and bond_release. * All hard work should be done there. */ @@ -363,7 +362,6 @@ static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, /* * Show and set the bonding transmit hash method. - * The bond interface must be down to change the xmit hash policy. */ static ssize_t bonding_show_xmit_hash(struct device *d, struct device_attribute *attr, -- GitLab From 9ee718aa9269cf56040cf12f0f6ac6e0057397b2 Mon Sep 17 00:00:00 2001 From: Eytan Lifshitz Date: Sun, 19 May 2013 19:14:41 +0300 Subject: [PATCH 0498/2900] iwlwifi: mvm: add thermal throttling and CT kill In order to avoid NIC destruction due to high temperature, CT kill will power down the NIC. To avoid this, thermal throttling will decrease throughput to prevent the NIC from reaching the temperature at which CT kill is performed. Signed-off-by: Eytan Lifshitz Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-csr.h | 19 + drivers/net/wireless/iwlwifi/iwl-prph.h | 12 + drivers/net/wireless/iwlwifi/mvm/Makefile | 2 +- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 6 +- drivers/net/wireless/iwlwifi/mvm/fw-api.h | 211 ++++++++ drivers/net/wireless/iwlwifi/mvm/fw.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 5 +- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 4 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 101 +++- drivers/net/wireless/iwlwifi/mvm/ops.c | 18 +- drivers/net/wireless/iwlwifi/mvm/rs.c | 26 + drivers/net/wireless/iwlwifi/mvm/rs.h | 5 + drivers/net/wireless/iwlwifi/mvm/rx.c | 22 + drivers/net/wireless/iwlwifi/mvm/sta.c | 13 +- drivers/net/wireless/iwlwifi/mvm/sta.h | 6 + drivers/net/wireless/iwlwifi/mvm/tt.c | 509 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/utils.c | 31 ++ 17 files changed, 974 insertions(+), 18 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/mvm/tt.c diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 20e845d4da04..a276af476e2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -472,4 +472,23 @@ #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) +/***************************************************************************** + * 7000/3000 series SHR DTS addresses * + *****************************************************************************/ + +/* Diode Results Register Structure: */ +enum dtd_diode_reg { + DTS_DIODE_REG_DIG_VAL = 0x000000FF, /* bits [7:0] */ + DTS_DIODE_REG_VREF_LOW = 0x0000FF00, /* bits [15:8] */ + DTS_DIODE_REG_VREF_HIGH = 0x00FF0000, /* bits [23:16] */ + DTS_DIODE_REG_VREF_ID = 0x03000000, /* bits [25:24] */ + DTS_DIODE_REG_PASS_ONCE = 0x80000000, /* bits [31:31] */ + DTS_DIODE_REG_FLAGS_MSK = 0xFF000000, /* bits [31:24] */ +/* Those are the masks INSIDE the flags bit-field: */ + DTS_DIODE_REG_FLAGS_VREFS_ID_POS = 0, + DTS_DIODE_REG_FLAGS_VREFS_ID = 0x00000003, /* bits [1:0] */ + DTS_DIODE_REG_FLAGS_PASS_ONCE_POS = 7, + DTS_DIODE_REG_FLAGS_PASS_ONCE = 0x00000080, /* bits [7:7] */ +}; + #endif /* !__iwl_csr_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 386f2a7c87cb..ff8cc75c189d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -100,6 +100,18 @@ /* Device system time */ #define DEVICE_SYSTEM_TIME_REG 0xA0206C +/***************************************************************************** + * 7000/3000 series SHR DTS addresses * + *****************************************************************************/ + +#define SHR_MISC_WFM_DTS_EN (0x00a10024) +#define DTSC_CFG_MODE (0x00a10604) +#define DTSC_VREF_AVG (0x00a10648) +#define DTSC_VREF5_AVG (0x00a1064c) +#define DTSC_CFG_MODE_PERIODIC (0x2) +#define DTSC_PTAT_AVG (0x00a10650) + + /** * Tx Scheduler * diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile index 2acc44b40986..ff856e543ae8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/iwlwifi/mvm/Makefile @@ -3,7 +3,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o iwlmvm-y += scan.o time-event.o rs.o iwlmvm-y += power.o bt-coex.o -iwlmvm-y += led.o +iwlmvm-y += led.o tt.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o iwlmvm-$(CONFIG_PM_SLEEP) += d3.o diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 810bfa5f6de0..f03655f303aa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -351,6 +351,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, enum ieee80211_band band; int ave_rssi; + lockdep_assert_held(&mvm->mutex); if (vif->type != NL80211_IFTYPE_STATION) return; @@ -365,7 +366,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, smps_mode = IEEE80211_SMPS_AUTOMATIC; if (band != IEEE80211_BAND_2GHZ) { - ieee80211_request_smps(vif, smps_mode); + iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, + smps_mode); return; } @@ -380,7 +382,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, mvmvif->id, data->notif->bt_status, data->notif->bt_traffic_load, smps_mode); - ieee80211_request_smps(vif, smps_mode); + iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); /* don't reduce the Tx power if in loose scheme */ if (is_loose_coex()) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 733153c3b66c..db6f47406ac2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -139,6 +139,9 @@ enum { /* Power */ POWER_TABLE_CMD = 0x77, + /* Thermal Throttling*/ + REPLY_THERMAL_MNG_BACKOFF = 0x7e, + /* Scanning */ SCAN_REQUEST_CMD = 0x80, SCAN_ABORT_CMD = 0x81, @@ -977,4 +980,212 @@ struct iwl_mcast_filter_cmd { u8 addr_list[0]; } __packed; /* MCAST_FILTERING_CMD_API_S_VER_1 */ +struct mvm_statistics_dbg { + __le32 burst_check; + __le32 burst_count; + __le32 wait_for_silence_timeout_cnt; + __le32 reserved[3]; +} __packed; /* STATISTICS_DEBUG_API_S_VER_2 */ + +struct mvm_statistics_div { + __le32 tx_on_a; + __le32 tx_on_b; + __le32 exec_time; + __le32 probe_time; + __le32 rssi_ant; + __le32 reserved2; +} __packed; /* STATISTICS_SLOW_DIV_API_S_VER_2 */ + +struct mvm_statistics_general_common { + __le32 temperature; /* radio temperature */ + __le32 temperature_m; /* radio voltage */ + struct mvm_statistics_dbg dbg; + __le32 sleep_time; + __le32 slots_out; + __le32 slots_idle; + __le32 ttl_timestamp; + struct mvm_statistics_div div; + __le32 rx_enable_counter; + /* + * num_of_sos_states: + * count the number of times we have to re-tune + * in order to get out of bad PHY status + */ + __le32 num_of_sos_states; +} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ + +struct mvm_statistics_rx_non_phy { + __le32 bogus_cts; /* CTS received when not expecting CTS */ + __le32 bogus_ack; /* ACK received when not expecting ACK */ + __le32 non_bssid_frames; /* number of frames with BSSID that + * doesn't belong to the STA BSSID */ + __le32 filtered_frames; /* count frames that were dumped in the + * filtering process */ + __le32 non_channel_beacons; /* beacons with our bss id but not on + * our serving channel */ + __le32 channel_beacons; /* beacons with our bss id and in our + * serving channel */ + __le32 num_missed_bcon; /* number of missed beacons */ + __le32 adc_rx_saturation_time; /* count in 0.8us units the time the + * ADC was in saturation */ + __le32 ina_detection_search_time;/* total time (in 0.8us) searched + * for INA */ + __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */ + __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */ + __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */ + __le32 interference_data_flag; /* flag for interference data + * availability. 1 when data is + * available. */ + __le32 channel_load; /* counts RX Enable time in uSec */ + __le32 dsp_false_alarms; /* DSP false alarm (both OFDM + * and CCK) counter */ + __le32 beacon_rssi_a; + __le32 beacon_rssi_b; + __le32 beacon_rssi_c; + __le32 beacon_energy_a; + __le32 beacon_energy_b; + __le32 beacon_energy_c; + __le32 num_bt_kills; + __le32 mac_id; + __le32 directed_data_mpdu; +} __packed; /* STATISTICS_RX_NON_PHY_API_S_VER_3 */ + +struct mvm_statistics_rx_phy { + __le32 ina_cnt; + __le32 fina_cnt; + __le32 plcp_err; + __le32 crc32_err; + __le32 overrun_err; + __le32 early_overrun_err; + __le32 crc32_good; + __le32 false_alarm_cnt; + __le32 fina_sync_err_cnt; + __le32 sfd_timeout; + __le32 fina_timeout; + __le32 unresponded_rts; + __le32 rxe_frame_limit_overrun; + __le32 sent_ack_cnt; + __le32 sent_cts_cnt; + __le32 sent_ba_rsp_cnt; + __le32 dsp_self_kill; + __le32 mh_format_err; + __le32 re_acq_main_rssi_sum; + __le32 reserved; +} __packed; /* STATISTICS_RX_PHY_API_S_VER_2 */ + +struct mvm_statistics_rx_ht_phy { + __le32 plcp_err; + __le32 overrun_err; + __le32 early_overrun_err; + __le32 crc32_good; + __le32 crc32_err; + __le32 mh_format_err; + __le32 agg_crc32_good; + __le32 agg_mpdu_cnt; + __le32 agg_cnt; + __le32 unsupport_mcs; +} __packed; /* STATISTICS_HT_RX_PHY_API_S_VER_1 */ + +#define MAX_CHAINS 3 + +struct mvm_statistics_tx_non_phy_agg { + __le32 ba_timeout; + __le32 ba_reschedule_frames; + __le32 scd_query_agg_frame_cnt; + __le32 scd_query_no_agg; + __le32 scd_query_agg; + __le32 scd_query_mismatch; + __le32 frame_not_ready; + __le32 underrun; + __le32 bt_prio_kill; + __le32 rx_ba_rsp_cnt; + __s8 txpower[MAX_CHAINS]; + __s8 reserved; + __le32 reserved2; +} __packed; /* STATISTICS_TX_NON_PHY_AGG_API_S_VER_1 */ + +struct mvm_statistics_tx_channel_width { + __le32 ext_cca_narrow_ch20[1]; + __le32 ext_cca_narrow_ch40[2]; + __le32 ext_cca_narrow_ch80[3]; + __le32 ext_cca_narrow_ch160[4]; + __le32 last_tx_ch_width_indx; + __le32 rx_detected_per_ch_width[4]; + __le32 success_per_ch_width[4]; + __le32 fail_per_ch_width[4]; +}; /* STATISTICS_TX_CHANNEL_WIDTH_API_S_VER_1 */ + +struct mvm_statistics_tx { + __le32 preamble_cnt; + __le32 rx_detected_cnt; + __le32 bt_prio_defer_cnt; + __le32 bt_prio_kill_cnt; + __le32 few_bytes_cnt; + __le32 cts_timeout; + __le32 ack_timeout; + __le32 expected_ack_cnt; + __le32 actual_ack_cnt; + __le32 dump_msdu_cnt; + __le32 burst_abort_next_frame_mismatch_cnt; + __le32 burst_abort_missing_next_frame_cnt; + __le32 cts_timeout_collision; + __le32 ack_or_ba_timeout_collision; + struct mvm_statistics_tx_non_phy_agg agg; + struct mvm_statistics_tx_channel_width channel_width; +} __packed; /* STATISTICS_TX_API_S_VER_4 */ + + +struct mvm_statistics_bt_activity { + __le32 hi_priority_tx_req_cnt; + __le32 hi_priority_tx_denied_cnt; + __le32 lo_priority_tx_req_cnt; + __le32 lo_priority_tx_denied_cnt; + __le32 hi_priority_rx_req_cnt; + __le32 hi_priority_rx_denied_cnt; + __le32 lo_priority_rx_req_cnt; + __le32 lo_priority_rx_denied_cnt; +} __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ + +struct mvm_statistics_general { + struct mvm_statistics_general_common common; + __le32 beacon_filtered; + __le32 missed_beacons; + __s8 beacon_filter_everage_energy; + __s8 beacon_filter_reason; + __s8 beacon_filter_current_energy; + __s8 beacon_filter_reserved; + __le32 beacon_filter_delta_time; + struct mvm_statistics_bt_activity bt_activity; +} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ + +struct mvm_statistics_rx { + struct mvm_statistics_rx_phy ofdm; + struct mvm_statistics_rx_phy cck; + struct mvm_statistics_rx_non_phy general; + struct mvm_statistics_rx_ht_phy ofdm_ht; +} __packed; /* STATISTICS_RX_API_S_VER_3 */ + +/* + * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) + * + * By default, uCode issues this notification after receiving a beacon + * while associated. To disable this behavior, set DISABLE_NOTIF flag in the + * REPLY_STATISTICS_CMD 0x9c, above. + * + * Statistics counters continue to increment beacon after beacon, but are + * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD + * 0x9c with CLEAR_STATS bit set (see above). + * + * uCode also issues this notification during scans. uCode clears statistics + * appropriately so that each notification contains statistics for only the + * one channel that has just been scanned. + */ + +struct iwl_notif_statistics { /* STATISTICS_NTFY_API_S_VER_8 */ + __le32 flag; + struct mvm_statistics_rx rx; + struct mvm_statistics_tx tx; + struct mvm_statistics_general general; +} __packed; + #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 20ee2812cc9b..cd7c0032cc58 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -330,7 +330,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) * abort after reading the nvm in case RF Kill is on, we will complete * the init seq later when RF kill will switch to off */ - if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) { + if (iwl_mvm_is_radio_killed(mvm)) { IWL_DEBUG_RF_KILL(mvm, "jump over all phy activities due to RF kill\n"); iwl_remove_notification(&mvm->notif_wait, &calib_wait); diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index b2cc3d98e0f7..dc5f4ef50198 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -227,7 +227,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, .found_vif = false, }; u32 ac; - int ret; + int ret, i; /* * Allocate a MAC ID and a TSF for this MAC, along with the queues @@ -335,6 +335,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT; mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; + for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) + mvmvif->smps_requests[i] = IEEE80211_SMPS_AUTOMATIC; + return 0; exit_fail: diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c9924c12e0fe..c26f6b504460 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -265,8 +265,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - if (test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status)) { - IWL_DEBUG_DROP(mvm, "Dropping - RF KILL\n"); + if (iwl_mvm_is_radio_killed(mvm)) { + IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n"); goto drop; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e87a321e107..a288552491b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -150,6 +150,12 @@ enum iwl_power_scheme { #define IWL_CONN_MAX_LISTEN_INTERVAL 70 +enum iwl_mvm_smps_type_request { + IWL_MVM_SMPS_REQ_BT_COEX, + IWL_MVM_SMPS_REQ_TT, + NUM_IWL_MVM_SMPS_REQ, +}; + /** * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context * @id: between 0 and 3 @@ -164,6 +170,8 @@ enum iwl_power_scheme { * @bcast_sta: station used for broadcast packets. Used by the following * vifs: P2P_DEVICE, GO and AP. * @beacon_skb: the skb used to hold the AP/GO beacon template + * @smps_requests: the requests of of differents parts of the driver, regard + the desired smps mode. */ struct iwl_mvm_vif { u16 id; @@ -218,6 +226,8 @@ struct iwl_mvm_vif { struct dentry *dbgfs_slink; void *dbgfs_data; #endif + + enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; }; static inline struct iwl_mvm_vif * @@ -226,12 +236,6 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) return (void *)vif->drv_priv; } -enum iwl_mvm_status { - IWL_MVM_STATUS_HW_RFKILL, - IWL_MVM_STATUS_ROC_RUNNING, - IWL_MVM_STATUS_IN_HW_RESTART, -}; - enum iwl_scan_status { IWL_MVM_SCAN_NONE, IWL_MVM_SCAN_OS, @@ -249,6 +253,63 @@ struct iwl_nvm_section { const u8 *data; }; +/* + * Tx-backoff threshold + * @temperature: The threshold in Celsius + * @backoff: The tx-backoff in uSec + */ +struct iwl_tt_tx_backoff { + s32 temperature; + u32 backoff; +}; + +#define TT_TX_BACKOFF_SIZE 6 + +/** + * struct iwl_tt_params - thermal throttling parameters + * @ct_kill_entry: CT Kill entry threshold + * @ct_kill_exit: CT Kill exit threshold + * @ct_kill_duration: The time intervals (in uSec) in which the driver needs + * to checks whether to exit CT Kill. + * @dynamic_smps_entry: Dynamic SMPS entry threshold + * @dynamic_smps_exit: Dynamic SMPS exit threshold + * @tx_protection_entry: TX protection entry threshold + * @tx_protection_exit: TX protection exit threshold + * @tx_backoff: Array of thresholds for tx-backoff , in ascending order. + * @support_ct_kill: Support CT Kill? + * @support_dynamic_smps: Support dynamic SMPS? + * @support_tx_protection: Support tx protection? + * @support_tx_backoff: Support tx-backoff? + */ +struct iwl_tt_params { + s32 ct_kill_entry; + s32 ct_kill_exit; + u32 ct_kill_duration; + s32 dynamic_smps_entry; + s32 dynamic_smps_exit; + s32 tx_protection_entry; + s32 tx_protection_exit; + struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE]; + bool support_ct_kill; + bool support_dynamic_smps; + bool support_tx_protection; + bool support_tx_backoff; +}; + +/** + * struct iwl_mvm_tt_mgnt - Thermal Throttling Management structure + * @ct_kill_exit: worker to exit thermal kill + * @dynamic_smps: Is thermal throttling enabled dynamic_smps? + * @tx_backoff: The current thremal throttling tx backoff in uSec. + * @params: Parameters to configure the thermal throttling algorithm. + */ +struct iwl_mvm_tt_mgmt { + struct delayed_work ct_kill_exit; + bool dynamic_smps; + u32 tx_backoff; + const struct iwl_tt_params *params; +}; + struct iwl_mvm { /* for logger access */ struct device *dev; @@ -356,6 +417,10 @@ struct iwl_mvm { /* BT-Coex */ u8 bt_kill_msk; struct iwl_bt_coex_profile_notif last_bt_notif; + + /* Thermal Throttling and CTkill */ + struct iwl_mvm_tt_mgmt thermal_throttle; + s32 temperature; /* Celsius */ }; /* Extract MVM priv from op_mode and _hw */ @@ -365,6 +430,19 @@ struct iwl_mvm { #define IWL_MAC80211_GET_MVM(_hw) \ IWL_OP_MODE_GET_MVM((struct iwl_op_mode *)((_hw)->priv)) +enum iwl_mvm_status { + IWL_MVM_STATUS_HW_RFKILL, + IWL_MVM_STATUS_HW_CTKILL, + IWL_MVM_STATUS_ROC_RUNNING, + IWL_MVM_STATUS_IN_HW_RESTART, +}; + +static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) +{ + return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status) || + test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); +} + extern const u8 iwl_mvm_ac_to_tx_fifo[]; struct iwl_rate_info { @@ -555,4 +633,15 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +/* SMPS */ +void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + enum iwl_mvm_smps_type_request req_type, + enum ieee80211_smps_mode smps_request); + +/* Thermal management and CT-kill */ +void iwl_mvm_tt_handler(struct iwl_mvm *mvm); +void iwl_mvm_tt_initialize(struct iwl_mvm *mvm); +void iwl_mvm_tt_exit(struct iwl_mvm *mvm); +void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); + #endif /* __IWL_MVM_H__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 7998baca5a8b..8431637e38f2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -222,6 +222,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), + RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), @@ -294,6 +295,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { CMD(BT_CONFIG), CMD(MCAST_FILTER_CMD), CMD(REPLY_BEACON_FILTERING_CMD), + CMD(REPLY_THERMAL_MNG_BACKOFF), }; #undef CMD @@ -394,6 +396,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, if (err) goto out_free; + iwl_mvm_tt_initialize(mvm); + mutex_lock(&mvm->mutex); err = iwl_run_init_mvm_ucode(mvm, true); mutex_unlock(&mvm->mutex); @@ -441,6 +445,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) iwl_mvm_leds_exit(mvm); + iwl_mvm_tt_exit(mvm); + ieee80211_unregister_hw(mvm->hw); kfree(mvm->scan_cmd); @@ -595,6 +601,16 @@ static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) ieee80211_wake_queue(mvm->hw, mq); } +void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) +{ + if (state) + set_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); + else + clear_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); + + wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); +} + static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); @@ -604,7 +620,7 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) else clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); - wiphy_rfkill_set_hw_state(mvm->hw->wiphy, state); + wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); } static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 55334d542e26..6a050c69e7d0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -3080,3 +3080,29 @@ void iwl_mvm_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rs_mvm_ops); } + +/** + * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable + * Tx protection, according to this rquest and previous requests, + * and send the LQ command. + * @lq: The LQ command + * @mvmsta: The station + * @enable: Enable Tx protection? + */ +int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, + struct iwl_mvm_sta *mvmsta, bool enable) +{ + lockdep_assert_held(&mvm->mutex); + + if (enable) { + if (mvmsta->tx_protection == 0) + lq->flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK; + mvmsta->tx_protection++; + } else { + mvmsta->tx_protection--; + if (mvmsta->tx_protection == 0) + lq->flags &= ~LQ_FLAG_SET_STA_TLC_RTS_MSK; + } + + return iwl_mvm_send_lq_cmd(mvm, lq, CMD_ASYNC, false); +} diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 219c6857cc0f..f66155a57238 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -390,4 +390,9 @@ extern int iwl_mvm_rate_control_register(void); */ extern void iwl_mvm_rate_control_unregister(void); +struct iwl_mvm_sta; + +int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, + struct iwl_mvm_sta *mvmsta, bool enable); + #endif /* __rs__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 4dfc21a3e83e..e4930d5027d2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -363,3 +363,25 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, rxb, &rx_status); return 0; } + +/* + * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler + * + * TODO: This handler is implemented partially. + * It only gets the NIC's temperature. + */ +int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_notif_statistics *stats = (void *)&pkt->data; + struct mvm_statistics_general_common *common = &stats->general.common; + + if (mvm->temperature != le32_to_cpu(common->temperature)) { + mvm->temperature = le32_to_cpu(common->temperature); + iwl_mvm_tt_handler(mvm); + } + + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 5c664ed54400..2278858d5658 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -64,6 +64,7 @@ #include "mvm.h" #include "sta.h" +#include "rs.h" static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) { @@ -217,6 +218,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, mvmvif->color); mvm_sta->vif = vif; mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + mvm_sta->tx_protection = 0; + mvm_sta->tt_tx_protection = false; /* HW restart, don't assume the memory has been zeroed */ atomic_set(&mvm->pending_frames[sta_id], 0); @@ -798,21 +801,23 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, min(mvmsta->max_agg_bufsize, buf_size); mvmsta->lq_sta.lq.agg_frame_cnt_limit = mvmsta->max_agg_bufsize; + IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", + sta->addr, tid); + if (mvm->cfg->ht_params->use_rts_for_aggregation) { /* * switch to RTS/CTS if it is the prefer protection * method for HT traffic + * this function also sends the LQ command */ - mvmsta->lq_sta.lq.flags |= LQ_FLAG_SET_STA_TLC_RTS_MSK; + return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, + mvmsta, true); /* * TODO: remove the TLC_RTS flag when we tear down the last * AGG session (agg_tids_count in DVM) */ } - IWL_DEBUG_HT(mvm, "Tx aggregation enabled on ra = %pM tid = %d\n", - sta->addr, tid); - return iwl_mvm_send_lq_cmd(mvm, &mvmsta->lq_sta.lq, CMD_ASYNC, false); } diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index a4ddce77aaae..3efa0a0cc987 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h @@ -275,6 +275,8 @@ struct iwl_mvm_tid_data { * @lock: lock to protect the whole struct. Since %tid_data is access from Tx * and from Tx response flow, it needs a spinlock. * @tid_data: per tid data. Look at %iwl_mvm_tid_data. + * @tx_protection: reference counter for controlling the Tx protection. + * @tt_tx_protection: is thermal throttling enable Tx protection? * * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is placed in that @@ -296,6 +298,10 @@ struct iwl_mvm_sta { #ifdef CONFIG_PM_SLEEP u16 last_seq_ctl; #endif + + /* Temporary, until the new TLC will control the Tx protection */ + s8 tx_protection; + bool tt_tx_protection; }; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c new file mode 100644 index 000000000000..4665fc033c17 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -0,0 +1,509 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "mvm.h" +#include "iwl-config.h" +#include "iwl-io.h" +#include "iwl-csr.h" +#include "iwl-prph.h" + +#define OTP_DTS_DIODE_DEVIATION 96 /*in words*/ +/* VBG - Voltage Band Gap error data (temperature offset) */ +#define OTP_WP_DTS_VBG (OTP_DTS_DIODE_DEVIATION + 2) +#define MEAS_VBG_MIN_VAL 2300 +#define MEAS_VBG_MAX_VAL 3000 +#define MEAS_VBG_DEFAULT_VAL 2700 +#define DTS_DIODE_VALID(flags) (flags & DTS_DIODE_REG_FLAGS_PASS_ONCE) +#define MIN_TEMPERATURE 0 +#define MAX_TEMPERATURE 125 +#define TEMPERATURE_ERROR (MAX_TEMPERATURE + 1) +#define PTAT_DIGITAL_VALUE_MIN_VALUE 0 +#define PTAT_DIGITAL_VALUE_MAX_VALUE 0xFF +#define DTS_VREFS_NUM 5 +static inline u32 DTS_DIODE_GET_VREFS_ID(u32 flags) +{ + return (flags & DTS_DIODE_REG_FLAGS_VREFS_ID) >> + DTS_DIODE_REG_FLAGS_VREFS_ID_POS; +} + +#define CALC_VREFS_MIN_DIFF 43 +#define CALC_VREFS_MAX_DIFF 51 +#define CALC_LUT_SIZE (1 + CALC_VREFS_MAX_DIFF - CALC_VREFS_MIN_DIFF) +#define CALC_LUT_INDEX_OFFSET CALC_VREFS_MIN_DIFF +#define CALC_TEMPERATURE_RESULT_SHIFT_OFFSET 23 + +/* + * @digital_value: The diode's digital-value sampled (temperature/voltage) + * @vref_low: The lower voltage-reference (the vref just below the diode's + * sampled digital-value) + * @vref_high: The higher voltage-reference (the vref just above the diode's + * sampled digital-value) + * @flags: bits[1:0]: The ID of the Vrefs pair (lowVref,highVref) + * bits[6:2]: Reserved. + * bits[7:7]: Indicates completion of at least 1 successful sample + * since last DTS reset. + */ +struct iwl_mvm_dts_diode_bits { + u8 digital_value; + u8 vref_low; + u8 vref_high; + u8 flags; +} __packed; + +union dts_diode_results { + u32 reg_value; + struct iwl_mvm_dts_diode_bits bits; +} __packed; + +static s16 iwl_mvm_dts_get_volt_band_gap(struct iwl_mvm *mvm) +{ + struct iwl_nvm_section calib_sec; + const __le16 *calib; + u16 vbg; + + /* TODO: move parsing to NVM code */ + calib_sec = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION]; + calib = (__le16 *)calib_sec.data; + + vbg = le16_to_cpu(calib[OTP_WP_DTS_VBG]); + + if (vbg < MEAS_VBG_MIN_VAL || vbg > MEAS_VBG_MAX_VAL) + vbg = MEAS_VBG_DEFAULT_VAL; + + return vbg; +} + +static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm) +{ + const u8 *calib; + u8 ptat, pa1, pa2, median; + + /* TODO: move parsing to NVM code */ + calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data; + ptat = calib[OTP_DTS_DIODE_DEVIATION]; + pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1]; + pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2]; + + /* get the median: */ + if (ptat > pa1) { + if (ptat > pa2) + median = (pa1 > pa2) ? pa1 : pa2; + else + median = ptat; + } else { + if (pa1 > pa2) + median = (ptat > pa2) ? ptat : pa2; + else + median = pa1; + } + + return ptat - median; +} + +static u8 iwl_mvm_dts_calibrate_ptat_deviation(struct iwl_mvm *mvm, u8 value) +{ + /* Calibrate the PTAT digital value, based on PTAT deviation data: */ + s16 new_val = value - iwl_mvm_dts_get_ptat_deviation_offset(mvm); + + if (new_val > PTAT_DIGITAL_VALUE_MAX_VALUE) + new_val = PTAT_DIGITAL_VALUE_MAX_VALUE; + else if (new_val < PTAT_DIGITAL_VALUE_MIN_VALUE) + new_val = PTAT_DIGITAL_VALUE_MIN_VALUE; + + return new_val; +} + +static bool dts_get_adjacent_vrefs(struct iwl_mvm *mvm, + union dts_diode_results *avg_ptat) +{ + u8 vrefs_results[DTS_VREFS_NUM]; + u8 low_vref_index = 0, flags; + u32 reg; + + reg = iwl_read_prph(mvm->trans, DTSC_VREF_AVG); + memcpy(vrefs_results, ®, sizeof(reg)); + reg = iwl_read_prph(mvm->trans, DTSC_VREF5_AVG); + vrefs_results[4] = reg & 0xff; + + if (avg_ptat->bits.digital_value < vrefs_results[0] || + avg_ptat->bits.digital_value > vrefs_results[4]) + return false; + + if (avg_ptat->bits.digital_value > vrefs_results[3]) + low_vref_index = 3; + else if (avg_ptat->bits.digital_value > vrefs_results[2]) + low_vref_index = 2; + else if (avg_ptat->bits.digital_value > vrefs_results[1]) + low_vref_index = 1; + + avg_ptat->bits.vref_low = vrefs_results[low_vref_index]; + avg_ptat->bits.vref_high = vrefs_results[low_vref_index + 1]; + flags = avg_ptat->bits.flags; + avg_ptat->bits.flags = + (flags & ~DTS_DIODE_REG_FLAGS_VREFS_ID) | + (low_vref_index & DTS_DIODE_REG_FLAGS_VREFS_ID); + return true; +} + +/* + * return true it the results are valid, and false otherwise. + */ +static bool dts_read_ptat_avg_results(struct iwl_mvm *mvm, + union dts_diode_results *avg_ptat) +{ + u32 reg; + u8 tmp; + + /* fill the diode value and pass_once with avg-reg results */ + reg = iwl_read_prph(mvm->trans, DTSC_PTAT_AVG); + reg &= DTS_DIODE_REG_DIG_VAL | DTS_DIODE_REG_PASS_ONCE; + avg_ptat->reg_value = reg; + + /* calibrate the PTAT digital value */ + tmp = avg_ptat->bits.digital_value; + tmp = iwl_mvm_dts_calibrate_ptat_deviation(mvm, tmp); + avg_ptat->bits.digital_value = tmp; + + /* + * fill vrefs fields, based on the avgVrefs results + * and the diode value + */ + return dts_get_adjacent_vrefs(mvm, avg_ptat) && + DTS_DIODE_VALID(avg_ptat->bits.flags); +} + +static s32 calculate_nic_temperature(union dts_diode_results avg_ptat, + u16 volt_band_gap) +{ + u32 tmp_result; + u8 vrefs_diff; + /* + * For temperature calculation (at the end, shift right by 23) + * LUT[(D2-D1)] = ROUND{ 2^23 / ((D2-D1)*9*10) } + * (D2-D1) == 43 44 45 46 47 48 49 50 51 + */ + static const u16 calc_lut[CALC_LUT_SIZE] = { + 2168, 2118, 2071, 2026, 1983, 1942, 1902, 1864, 1828, + }; + + /* + * The diff between the high and low voltage-references is assumed + * to be strictly be in range of [60,68] + */ + vrefs_diff = avg_ptat.bits.vref_high - avg_ptat.bits.vref_low; + + if (vrefs_diff < CALC_VREFS_MIN_DIFF || + vrefs_diff > CALC_VREFS_MAX_DIFF) + return TEMPERATURE_ERROR; + + /* calculate the result: */ + tmp_result = + vrefs_diff * (DTS_DIODE_GET_VREFS_ID(avg_ptat.bits.flags) + 9); + tmp_result += avg_ptat.bits.digital_value; + tmp_result -= avg_ptat.bits.vref_high; + + /* multiply by the LUT value (based on the diff) */ + tmp_result *= calc_lut[vrefs_diff - CALC_LUT_INDEX_OFFSET]; + + /* + * Get the BandGap (the voltage refereces source) error data + * (temperature offset) + */ + tmp_result *= volt_band_gap; + + /* + * here, tmp_result value can be up to 32-bits. We want to right-shift + * it *without* sign-extend. + */ + tmp_result = tmp_result >> CALC_TEMPERATURE_RESULT_SHIFT_OFFSET; + + /* + * at this point, tmp_result should be in the range: + * 200 <= tmp_result <= 365 + */ + return (s16)tmp_result - 240; +} + +static s32 check_nic_temperature(struct iwl_mvm *mvm) +{ + u16 volt_band_gap; + union dts_diode_results avg_ptat; + + volt_band_gap = iwl_mvm_dts_get_volt_band_gap(mvm); + + /* disable DTS */ + iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0); + + /* SV initialization */ + iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 1); + iwl_write_prph(mvm->trans, DTSC_CFG_MODE, + DTSC_CFG_MODE_PERIODIC); + + /* wait for results */ + msleep(100); + if (!dts_read_ptat_avg_results(mvm, &avg_ptat)) + return TEMPERATURE_ERROR; + + /* disable DTS */ + iwl_write_prph(mvm->trans, SHR_MISC_WFM_DTS_EN, 0); + + return calculate_nic_temperature(avg_ptat, volt_band_gap); +} + +static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm) +{ + u32 duration = mvm->thermal_throttle.params->ct_kill_duration; + + IWL_ERR(mvm, "Enter CT Kill\n"); + iwl_mvm_set_hw_ctkill_state(mvm, true); + schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit, + round_jiffies_relative(duration * HZ)); +} + +static void iwl_mvm_exit_ctkill(struct iwl_mvm *mvm) +{ + IWL_ERR(mvm, "Exit CT Kill\n"); + iwl_mvm_set_hw_ctkill_state(mvm, false); +} + +static void check_exit_ctkill(struct work_struct *work) +{ + struct iwl_mvm_tt_mgmt *tt; + struct iwl_mvm *mvm; + u32 duration; + s32 temp; + + tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); + mvm = container_of(tt, struct iwl_mvm, thermal_throttle); + + duration = tt->params->ct_kill_duration; + + iwl_trans_start_hw(mvm->trans); + temp = check_nic_temperature(mvm); + iwl_trans_stop_hw(mvm->trans, false); + + if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) { + IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n"); + goto reschedule; + } + IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp); + + if (temp <= tt->params->ct_kill_exit) { + iwl_mvm_exit_ctkill(mvm); + return; + } + +reschedule: + schedule_delayed_work(&mvm->thermal_throttle.ct_kill_exit, + round_jiffies(duration * HZ)); +} + +static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm *mvm = _data; + enum ieee80211_smps_mode smps_mode; + + lockdep_assert_held(&mvm->mutex); + + if (mvm->thermal_throttle.dynamic_smps) + smps_mode = IEEE80211_SMPS_DYNAMIC; + else + smps_mode = IEEE80211_SMPS_AUTOMATIC; + + iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode); +} + +static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable) +{ + struct ieee80211_sta *sta; + struct iwl_mvm_sta *mvmsta; + int i, err; + + for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { + sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], + lockdep_is_held(&mvm->mutex)); + if (IS_ERR_OR_NULL(sta)) + continue; + mvmsta = (void *)sta->drv_priv; + if (enable == mvmsta->tt_tx_protection) + continue; + err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, + mvmsta, enable); + if (err) { + IWL_ERR(mvm, "Failed to %s Tx protection\n", + enable ? "enable" : "disable"); + } else { + IWL_DEBUG_TEMP(mvm, "%s Tx protection\n", + enable ? "Enable" : "Disable"); + mvmsta->tt_tx_protection = enable; + } + } +} + +static void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_THERMAL_MNG_BACKOFF, + .len = { sizeof(u32), }, + .data = { &backoff, }, + .flags = CMD_SYNC, + }; + + if (iwl_mvm_send_cmd(mvm, &cmd) == 0) { + IWL_DEBUG_TEMP(mvm, "Set Thermal Tx backoff to: %u\n", + backoff); + mvm->thermal_throttle.tx_backoff = backoff; + } else { + IWL_ERR(mvm, "Failed to change Thermal Tx backoff\n"); + } +} + +void iwl_mvm_tt_handler(struct iwl_mvm *mvm) +{ + const struct iwl_tt_params *params = mvm->thermal_throttle.params; + struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; + s32 temperature = mvm->temperature; + int i; + u32 tx_backoff; + + IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", mvm->temperature); + + if (params->support_ct_kill && temperature >= params->ct_kill_entry) { + iwl_mvm_enter_ctkill(mvm); + return; + } + + if (params->support_dynamic_smps) { + if (!tt->dynamic_smps && + temperature >= params->dynamic_smps_entry) { + IWL_DEBUG_TEMP(mvm, "Enable dynamic SMPS\n"); + tt->dynamic_smps = true; + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_tt_smps_iterator, mvm); + } else if (tt->dynamic_smps && + temperature <= params->dynamic_smps_exit) { + IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n"); + tt->dynamic_smps = false; + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_tt_smps_iterator, mvm); + } + } + + if (params->support_tx_protection) { + if (temperature >= params->tx_protection_entry) + iwl_mvm_tt_tx_protection(mvm, true); + else if (temperature <= params->tx_protection_exit) + iwl_mvm_tt_tx_protection(mvm, false); + } + + if (params->support_tx_backoff) { + tx_backoff = 0; + for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) { + if (temperature < params->tx_backoff[i].temperature) + break; + tx_backoff = params->tx_backoff[i].backoff; + } + if (tt->tx_backoff != tx_backoff) + iwl_mvm_tt_tx_backoff(mvm, tx_backoff); + } +} + +static const struct iwl_tt_params iwl7000_tt_params = { + .ct_kill_entry = 118, + .ct_kill_exit = 96, + .ct_kill_duration = 5, + .dynamic_smps_entry = 114, + .dynamic_smps_exit = 110, + .tx_protection_entry = 114, + .tx_protection_exit = 108, + .tx_backoff = { + {.temperature = 112, .backoff = 200}, + {.temperature = 113, .backoff = 600}, + {.temperature = 114, .backoff = 1200}, + {.temperature = 115, .backoff = 2000}, + {.temperature = 116, .backoff = 4000}, + {.temperature = 117, .backoff = 10000}, + }, + .support_ct_kill = true, + .support_dynamic_smps = true, + .support_tx_protection = true, + .support_tx_backoff = true, +}; + +void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) +{ + struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; + + IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); + tt->params = &iwl7000_tt_params; + INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); +} + +void iwl_mvm_tt_exit(struct iwl_mvm *mvm) +{ + cancel_delayed_work_sync(&mvm->thermal_throttle.ct_kill_exit); + IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n"); +} diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 687b34e387ac..c9b44ab4af07 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -471,3 +471,34 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, return iwl_mvm_send_cmd(mvm, &cmd); } + +/** + * iwl_mvm_update_smps - Get a requst to change the SMPS mode + * @req_type: The part of the driver who call for a change. + * @smps_requests: The request to change the SMPS mode. + * + * Get a requst to change the SMPS mode, + * and change it according to all other requests in the driver. + */ +void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + enum iwl_mvm_smps_type_request req_type, + enum ieee80211_smps_mode smps_request) +{ + struct iwl_mvm_vif *mvmvif; + enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC; + int i; + + lockdep_assert_held(&mvm->mutex); + mvmvif = iwl_mvm_vif_from_mac80211(vif); + mvmvif->smps_requests[req_type] = smps_request; + for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { + if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC) { + smps_mode = IEEE80211_SMPS_STATIC; + break; + } + if (mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) + smps_mode = IEEE80211_SMPS_DYNAMIC; + } + + ieee80211_request_smps(vif, smps_mode); +} -- GitLab From 1bd2d1755054c0cc13e2dc7766f2f2ead7d15444 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Tue, 21 May 2013 14:49:09 +0300 Subject: [PATCH 0499/2900] iwlwifi: mvm: Change number of DTIMs to skip semantics If skip over DTIMs is enabled the driver can specify number of DTIMs to skip. This parameter in host-device API implies number of DTIM periods to skip. For example, to skip one DTIM means sleep over two DTIM periods. Change semantics accordingly. Change this parameter's default value. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | 6 ++++-- drivers/net/wireless/iwlwifi/mvm/power.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index b6bdfd36bebe..d8e19290b0f3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -101,7 +101,9 @@ enum iwl_power_flags { * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to * PSM transition - legacy PM * @sleep_interval: not in use - * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set + * @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag + * is set. For example, if it is required to skip over + * one DTIM, this value need to be set to 2 (DTIM periods). * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled. * Default: 80dbm */ @@ -113,7 +115,7 @@ struct iwl_powertable_cmd { __le32 rx_data_timeout; __le32 tx_data_timeout; __le32 sleep_interval[IWL_POWER_VEC_SIZE]; - __le32 num_skip_dtim; + __le32 skip_dtim_periods; __le32 lprx_rssi_threshold; } __packed; diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index c818d6d6aee6..516e64e7706f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -139,8 +139,8 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", cmd->lprx_rssi_threshold); if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) - IWL_DEBUG_POWER(mvm, "DTIMs to skip = %u\n", - le32_to_cpu(cmd->num_skip_dtim)); + IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", + le32_to_cpu(cmd->skip_dtim_periods)); } } @@ -188,7 +188,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || mvm->cur_ucode == IWL_UCODE_WOWLAN)) { cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); - cmd->num_skip_dtim = cpu_to_le32(2); + cmd->skip_dtim_periods = cpu_to_le32(3); } /* Check that keep alive period is at least 3 * DTIM */ -- GitLab From 9ce4fa7291ff797f04849075a2ee3cf60f752aee Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 22 May 2013 13:16:23 +0300 Subject: [PATCH 0500/2900] iwlwifi: take valid ant for HT caps from TLV I forgot to take them from TLV and took them from the NVM instead. Signed-off-by: Emmanuel Grumbach Reviewed-by: Ilan Peer Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c | 15 ++++++++------- drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 14 ++++++++------ drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | 2 +- drivers/net/wireless/iwlwifi/mvm/nvm.c | 4 +++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c index 600c9fdd7f71..4c887f365908 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c @@ -732,17 +732,16 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data, void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band) + enum ieee80211_band band, + u8 tx_chains, u8 rx_chains) { int max_bit_rate = 0; - u8 rx_chains; - u8 tx_chains; - tx_chains = hweight8(data->valid_tx_ant); + tx_chains = hweight8(tx_chains); if (cfg->rx_with_siso_diversity) rx_chains = 1; else - rx_chains = hweight8(data->valid_rx_ant); + rx_chains = hweight8(rx_chains); if (!(data->sku_cap_11n_enable) || !cfg->ht_params) { ht_info->ht_supported = false; @@ -806,7 +805,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_2GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, + data->valid_tx_ant, data->valid_rx_ant); sband = &data->bands[IEEE80211_BAND_5GHZ]; sband->band = IEEE80211_BAND_5GHZ; @@ -814,7 +814,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_5GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, + data->valid_tx_ant, data->valid_rx_ant); if (n_channels != n_used) IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h index 37f115390b19..d73304a23ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h @@ -133,6 +133,7 @@ int iwl_init_sband_channels(struct iwl_nvm_data *data, void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band); + enum ieee80211_band band, + u8 tx_chains, u8 rx_chains); #endif /* __iwl_eeprom_parse_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 8f2a4e922346..acd2665afb8c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -292,7 +292,7 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *nvm_sw, - bool enable_vht) + bool enable_vht, u8 tx_chains, u8 rx_chains) { int n_channels = iwl_init_channel_map(dev, cfg, data, &nvm_sw[NVM_CHANNELS]); @@ -305,7 +305,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, sband->n_bitrates = N_RATES_24; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_2GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ, + tx_chains, rx_chains); sband = &data->bands[IEEE80211_BAND_5GHZ]; sband->band = IEEE80211_BAND_5GHZ; @@ -313,7 +314,8 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, sband->n_bitrates = N_RATES_52; n_used += iwl_init_sband_channels(data, sband, n_channels, IEEE80211_BAND_5GHZ); - iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); + iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, + tx_chains, rx_chains); if (enable_vht) iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); @@ -325,7 +327,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, - const __le16 *nvm_calib) + const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains) { struct iwl_nvm_data *data; u8 hw_addr[ETH_ALEN]; @@ -381,8 +383,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, data->hw_addr[4] = hw_addr[5]; data->hw_addr[5] = hw_addr[4]; - iwl_init_sbands(dev, cfg, data, nvm_sw, - sku & NVM_SKU_CAP_11AC_ENABLE); + iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE, + tx_chains, rx_chains); data->calib_version = 255; /* TODO: this value will prevent some checks from diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index e57fb989661e..3325059c52d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h @@ -75,6 +75,6 @@ struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, - const __le16 *nvm_calib); + const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains); #endif /* __iwl_nvm_parse_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 2cd669c3c47a..edb94ea31654 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -251,7 +251,9 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) hw = (const __le16 *)sections[NVM_SECTION_TYPE_HW].data; sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; - return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib); + return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, + iwl_fw_valid_tx_ant(mvm->fw), + iwl_fw_valid_rx_ant(mvm->fw)); } #define MAX_NVM_FILE_LEN 16384 -- GitLab From d64048edcd714095a5cf2d7019769d0d94e19892 Mon Sep 17 00:00:00 2001 From: Hila Gonen Date: Wed, 13 Mar 2013 18:00:03 +0200 Subject: [PATCH 0501/2900] iwlwifi: mvm: Add support for connection monitor offload The firmware supports periodic keep alive and beacon monitoring, so advertise connection monitor offload capability by setting IEEE80211_HW_CONNECTION_MONITOR flag. Implement missed beacons notification handler. Call ieee80211_beacon_loss in case of missed beacons, so AP probing by mac80211 can be triggered. Signed-off-by: Hila Gonen Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api.h | 20 +++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 25 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 ++- drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 +++ drivers/net/wireless/iwlwifi/mvm/ops.c | 4 ++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index db6f47406ac2..cbfb3beae783 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -164,6 +164,8 @@ enum { CARD_STATE_CMD = 0xa0, CARD_STATE_NOTIFICATION = 0xa1, + MISSED_BEACONS_NOTIFICATION = 0xa2, + REPLY_RX_PHY_CMD = 0xc0, REPLY_RX_MPDU_CMD = 0xc1, BA_NOTIF = 0xc5, @@ -942,6 +944,24 @@ struct iwl_card_state_notif { __le32 flags; } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ +/** + * struct iwl_missed_beacons_notif - information on missed beacons + * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) + * @mac_id: interface ID + * @consec_missed_beacons_since_last_rx: number of consecutive missed + * beacons since last RX. + * @consec_missed_beacons: number of consecutive missed beacons + * @num_expected_beacons: + * @num_recvd_beacons: + */ +struct iwl_missed_beacons_notif { + __le32 mac_id; + __le32 consec_missed_beacons_since_last_rx; + __le32 consec_missed_beacons; + __le32 num_expected_beacons; + __le32 num_recvd_beacons; +} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */ + /** * struct iwl_set_calib_default_cmd - set default value for calibration. * ( SET_CALIB_DEFAULT_CMD = 0x8e ) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index dc5f4ef50198..b4e8e597d2b7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -1050,3 +1050,28 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, rate); return 0; } + +static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + u16 *id = _data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (mvmvif->id == *id) + ieee80211_beacon_loss(vif); +} + +int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data; + u16 id = (u16)le32_to_cpu(missed_beacons->mac_id); + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_beacon_loss_iterator, + &id); + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c26f6b504460..dc50020d746d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -152,7 +152,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_TIMING_BEACON_ONLY; + IEEE80211_HW_TIMING_BEACON_ONLY | + IEEE80211_HW_CONNECTION_MONITOR; hw->queues = IWL_MVM_FIRST_AGG_QUEUE; hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index a288552491b3..0e7450372f2c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -552,6 +552,9 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, struct iwl_device_cmd *cmd); +int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd); /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 8431637e38f2..d7a199b1cdef 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -227,6 +227,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), + RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif, + false), + RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false), }; #undef RX_HANDLER @@ -289,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { CMD(NET_DETECT_HOTSPOTS_CMD), CMD(NET_DETECT_HOTSPOTS_QUERY_CMD), CMD(CARD_STATE_NOTIFICATION), + CMD(MISSED_BEACONS_NOTIFICATION), CMD(BT_COEX_PRIO_TABLE), CMD(BT_COEX_PROT_ENV), CMD(BT_PROFILE_NOTIFICATION), -- GitLab From b571a69745dc90aec3d0505a7ceac2702a93861b Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Tue, 21 May 2013 14:49:09 +0300 Subject: [PATCH 0502/2900] iwlwifi: mvm: add debugfs for powersave Add debugfs files to control powersave parameters for testing. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 337 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 65 ++++ drivers/net/wireless/iwlwifi/mvm/power.c | 66 ++++ 3 files changed, 468 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 95871b2d63d1..69e0806075a2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -300,6 +300,146 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file, return count; } +static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + enum iwl_dbgfs_pm_mask param, int val) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm; + + dbgfs_pm->mask |= param; + + switch (param) { + case MVM_DEBUGFS_PM_KEEP_ALIVE: { + struct ieee80211_hw *hw = mvm->hw; + int dtimper = hw->conf.ps_dtim_period ?: 1; + int dtimper_msec = dtimper * vif->bss_conf.beacon_int; + + IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); + if (val * MSEC_PER_SEC < 3 * dtimper_msec) { + IWL_WARN(mvm, + "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n", + val * MSEC_PER_SEC, 3 * dtimper_msec); + } + dbgfs_pm->keep_alive_seconds = val; + break; + } + case MVM_DEBUGFS_PM_SKIP_OVER_DTIM: + IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n", + val ? "enabled" : "disabled"); + dbgfs_pm->skip_over_dtim = val; + break; + case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS: + IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val); + dbgfs_pm->skip_dtim_periods = val; + break; + case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT: + IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val); + dbgfs_pm->rx_data_timeout = val; + break; + case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT: + IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val); + dbgfs_pm->tx_data_timeout = val; + break; + case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: + IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); + dbgfs_pm->disable_power_off = val; + break; + } +} + +static ssize_t iwl_dbgfs_pm_params_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->dbgfs_data; + enum iwl_dbgfs_pm_mask param; + char buf[32] = {}; + int val; + int ret; + + if (copy_from_user(buf, user_buf, sizeof(buf))) + return -EFAULT; + + if (!strncmp("keep_alive=", buf, 11)) { + if (sscanf(buf + 11, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_KEEP_ALIVE; + } else if (!strncmp("skip_over_dtim=", buf, 15)) { + if (sscanf(buf + 15, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM; + } else if (!strncmp("skip_dtim_periods=", buf, 18)) { + if (sscanf(buf + 18, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS; + } else if (!strncmp("rx_data_timeout=", buf, 16)) { + if (sscanf(buf + 16, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT; + } else if (!strncmp("tx_data_timeout=", buf, 16)) { + if (sscanf(buf + 16, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT; + } else if (!strncmp("disable_power_off=", buf, 18)) { + if (sscanf(buf + 18, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; + } else { + return -EINVAL; + } + + mutex_lock(&mvm->mutex); + iwl_dbgfs_update_pm(mvm, vif, param, val); + ret = iwl_mvm_power_update_mode(mvm, vif); + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + +static ssize_t iwl_dbgfs_pm_params_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->dbgfs_data; + struct iwl_powertable_cmd cmd = {}; + char buf[256]; + int bufsz = sizeof(buf); + int pos = 0; + + iwl_mvm_power_build_cmd(mvm, vif, &cmd); + + pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n", + (cmd.flags & + cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ? + 0 : 1); + pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n", + le32_to_cpu(cmd.skip_dtim_periods)); + pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", + iwlmvm_mod_params.power_scheme); + pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n", + le16_to_cpu(cmd.flags)); + pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", + cmd.keep_alive_seconds); + + if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { + pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n", + (cmd.flags & + cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? + 1 : 0); + pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n", + le32_to_cpu(cmd.rx_data_timeout)); + pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", + le32_to_cpu(cmd.tx_data_timeout)); + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + static ssize_t iwl_dbgfs_mac_params_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -481,6 +621,191 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, return count; } +static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif, + enum iwl_dbgfs_bf_mask param, int value) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; + + dbgfs_bf->mask |= param; + + switch (param) { + case MVM_DEBUGFS_BF_ENERGY_DELTA: + dbgfs_bf->bf_energy_delta = value; + break; + case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA: + dbgfs_bf->bf_roaming_energy_delta = value; + break; + case MVM_DEBUGFS_BF_ROAMING_STATE: + dbgfs_bf->bf_roaming_state = value; + break; + case MVM_DEBUGFS_BF_TEMPERATURE_DELTA: + dbgfs_bf->bf_temperature_delta = value; + break; + case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: + dbgfs_bf->bf_enable_beacon_filter = value; + break; + case MVM_DEBUGFS_BF_DEBUG_FLAG: + dbgfs_bf->bf_debug_flag = value; + break; + case MVM_DEBUGFS_BF_ESCAPE_TIMER: + dbgfs_bf->bf_escape_timer = value; + break; + case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT: + dbgfs_bf->ba_enable_beacon_abort = value; + break; + case MVM_DEBUGFS_BA_ESCAPE_TIMER: + dbgfs_bf->ba_escape_timer = value; + break; + } +} + +static ssize_t iwl_dbgfs_bf_params_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->dbgfs_data; + enum iwl_dbgfs_bf_mask param; + char buf[256]; + int buf_size; + int value; + int ret = 0; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + if (!strncmp("bf_energy_delta=", buf, 16)) { + if (sscanf(buf+16, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BF_ENERGY_DELTA_MIN || + value > IWL_BF_ENERGY_DELTA_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BF_ENERGY_DELTA; + } else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) { + if (sscanf(buf+24, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN || + value > IWL_BF_ROAMING_ENERGY_DELTA_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA; + } else if (!strncmp("bf_roaming_state=", buf, 17)) { + if (sscanf(buf+17, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BF_ROAMING_STATE_MIN || + value > IWL_BF_ROAMING_STATE_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BF_ROAMING_STATE; + } else if (!strncmp("bf_temperature_delta=", buf, 21)) { + if (sscanf(buf+21, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BF_TEMPERATURE_DELTA_MIN || + value > IWL_BF_TEMPERATURE_DELTA_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA; + } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { + if (sscanf(buf+24, "%d", &value) != 1) + return -EINVAL; + if (value < 0 || value > 1) + return -EINVAL; + param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER; + } else if (!strncmp("bf_debug_flag=", buf, 14)) { + if (sscanf(buf+14, "%d", &value) != 1) + return -EINVAL; + if (value < 0 || value > 1) + return -EINVAL; + param = MVM_DEBUGFS_BF_DEBUG_FLAG; + } else if (!strncmp("bf_escape_timer=", buf, 16)) { + if (sscanf(buf+16, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BF_ESCAPE_TIMER_MIN || + value > IWL_BF_ESCAPE_TIMER_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BF_ESCAPE_TIMER; + } else if (!strncmp("ba_escape_timer=", buf, 16)) { + if (sscanf(buf+16, "%d", &value) != 1) + return -EINVAL; + if (value < IWL_BA_ESCAPE_TIMER_MIN || + value > IWL_BA_ESCAPE_TIMER_MAX) + return -EINVAL; + param = MVM_DEBUGFS_BA_ESCAPE_TIMER; + } else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) { + if (sscanf(buf+23, "%d", &value) != 1) + return -EINVAL; + if (value < 0 || value > 1) + return -EINVAL; + param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT; + } else { + return -EINVAL; + } + + mutex_lock(&mvm->mutex); + iwl_dbgfs_update_bf(vif, param, value); + if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { + ret = iwl_mvm_disable_beacon_filter(mvm, vif); + } else { + if (mvmvif->bf_enabled) + ret = iwl_mvm_enable_beacon_filter(mvm, vif); + else + ret = iwl_mvm_disable_beacon_filter(mvm, vif); + } + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + +static ssize_t iwl_dbgfs_bf_params_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + char buf[256]; + int pos = 0; + const size_t bufsz = sizeof(buf); + struct iwl_beacon_filter_cmd cmd = { + .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, + .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, + .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, + .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, + .bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT, + .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, + .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), + .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT), + .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT, + }; + + iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); + if (mvmvif->bf_enabled) + cmd.bf_enable_beacon_filter = 1; + else + cmd.bf_enable_beacon_filter = 0; + + pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", + cmd.bf_energy_delta); + pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", + cmd.bf_roaming_energy_delta); + pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", + cmd.bf_roaming_state); + pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n", + cmd.bf_temperature_delta); + pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", + cmd.bf_enable_beacon_filter); + pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", + cmd.bf_debug_flag); + pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", + cmd.bf_escape_timer); + pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", + cmd.ba_escape_timer); + pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", + cmd.ba_enable_beacon_abort); + + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + #ifdef CONFIG_PM_SLEEP static ssize_t iwl_dbgfs_d3_sram_write(struct file *file, const char __user *user_buf, @@ -594,6 +919,8 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); /* Interface specific debugfs entries */ MVM_DEBUGFS_READ_FILE_OPS(mac_params); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params); int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) { @@ -647,9 +974,19 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return; } + if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM && + vif->type == NL80211_IFTYPE_STATION && !vif->p2p) + MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, S_IWUSR | + S_IRUSR); + MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR); + if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && + mvmvif == mvm->bf_allowed_vif) + MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, + S_IRUSR | S_IWUSR); + /* * Create symlink for convenience pointing to interface specific * debugfs entries for the driver. For example, under diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 0e7450372f2c..6a3220b6273e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -150,6 +150,54 @@ enum iwl_power_scheme { #define IWL_CONN_MAX_LISTEN_INTERVAL 70 +#ifdef CONFIG_IWLWIFI_DEBUGFS +enum iwl_dbgfs_pm_mask { + MVM_DEBUGFS_PM_KEEP_ALIVE = BIT(0), + MVM_DEBUGFS_PM_SKIP_OVER_DTIM = BIT(1), + MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2), + MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), + MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), + MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), +}; + +struct iwl_dbgfs_pm { + u8 keep_alive_seconds; + u32 rx_data_timeout; + u32 tx_data_timeout; + bool skip_over_dtim; + u8 skip_dtim_periods; + bool disable_power_off; + int mask; +}; + +/* beacon filtering */ + +enum iwl_dbgfs_bf_mask { + MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), + MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), + MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), + MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3), + MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4), + MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5), + MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6), + MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7), + MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8), +}; + +struct iwl_dbgfs_bf { + u8 bf_energy_delta; + u8 bf_roaming_energy_delta; + u8 bf_roaming_state; + u8 bf_temperature_delta; + u8 bf_enable_beacon_filter; + u8 bf_debug_flag; + u32 bf_escape_timer; + u32 ba_escape_timer; + u8 ba_enable_beacon_abort; + int mask; +}; +#endif + enum iwl_mvm_smps_type_request { IWL_MVM_SMPS_REQ_BT_COEX, IWL_MVM_SMPS_REQ_TT, @@ -225,6 +273,8 @@ struct iwl_mvm_vif { struct dentry *dbgfs_dir; struct dentry *dbgfs_slink; void *dbgfs_data; + struct iwl_dbgfs_pm dbgfs_pm; + struct iwl_dbgfs_bf dbgfs_bf; #endif enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; @@ -631,6 +681,21 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); /* beacon filtering */ +#ifdef CONFIG_IWLWIFI_DEBUGFS +void +iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, + struct iwl_beacon_filter_cmd *cmd); +int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm); +#else +static inline void +iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, + struct iwl_beacon_filter_cmd *cmd) +{} +static inline int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm) +{ + return 0; +} +#endif int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 516e64e7706f..67cf24aa72f9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -119,6 +119,7 @@ static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, if (!mvmvif->bf_enabled) return 0; + iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); } @@ -153,6 +154,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int dtimper, dtimper_msec; int keep_alive; bool radar_detect = false; + struct iwl_mvm_vif *mvmvif __maybe_unused = + iwl_mvm_vif_from_mac80211(vif); /* * Regardless of power management state the driver must set @@ -166,6 +169,11 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && + mvmvif->dbgfs_pm.disable_power_off) + cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); +#endif if (!vif->bss_conf.ps) return; @@ -205,6 +213,28 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); } + +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) + cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { + if (mvmvif->dbgfs_pm.skip_over_dtim) + cmd->flags |= + cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); + else + cmd->flags &= + cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK); + } + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT) + cmd->rx_data_timeout = + cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout); + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT) + cmd->tx_data_timeout = + cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) + cmd->skip_dtim_periods = + cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods); +#endif /* CONFIG_IWLWIFI_DEBUGFS */ } int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) @@ -233,6 +263,8 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_powertable_cmd cmd = {}; + struct iwl_mvm_vif *mvmvif __maybe_unused = + iwl_mvm_vif_from_mac80211(vif); if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; @@ -240,12 +272,45 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && + mvmvif->dbgfs_pm.disable_power_off) + cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK); +#endif iwl_mvm_power_log(mvm, &cmd); return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, sizeof(cmd), &cmd); } +#ifdef CONFIG_IWLWIFI_DEBUGFS +void +iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, + struct iwl_beacon_filter_cmd *cmd) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; + + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) + cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta; + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) + cmd->bf_roaming_energy_delta = + dbgfs_bf->bf_roaming_energy_delta; + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) + cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state; + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA) + cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta; + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) + cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag; + if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) + cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); + if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) + cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); + if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) + cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort; +} +#endif + int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -260,6 +325,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; + iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); if (!ret) -- GitLab From e057d3c31bdf87616b415c4b2cbf7310f54b9219 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 28 May 2013 13:01:52 +0200 Subject: [PATCH 0503/2900] cfg80211: support an active monitor interface flag An active monitor interface is one that is used for communication (via injection). It is expected to ACK incoming unicast packets. This is useful for running various 802.11 testing utilities that associate to an AP via injection and manage the state in user space. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 4 ++++ net/wireless/nl80211.c | 10 ++++++++++ 3 files changed, 16 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b3b076a46d50..13b247d26544 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -961,6 +961,7 @@ struct station_info { * @MONITOR_FLAG_CONTROL: pass control frames * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering * @MONITOR_FLAG_COOK_FRAMES: report frames after processing + * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address */ enum monitor_flags { MONITOR_FLAG_FCSFAIL = 1<wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) + return -EOPNOTSUPP; + if (change) err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); else @@ -2395,6 +2400,11 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, &flags); + + if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) && + !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) + return -EOPNOTSUPP; + wdev = rdev_add_virtual_intf(rdev, nla_data(info->attrs[NL80211_ATTR_IFNAME]), type, err ? NULL : &flags, ¶ms); -- GitLab From 31eba5bc56a9324f056d28569a4f89f39c1c3f70 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 28 May 2013 13:01:53 +0200 Subject: [PATCH 0504/2900] mac80211: support active monitor interfaces Support them only if the driver advertises support for them via IEEE80211_HW_SUPPORTS_ACTIVE_MONITOR. Unlike normal monitor interfaces, they are added to the driver, along with their MAC address. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 11 +++++++---- net/mac80211/driver-ops.h | 3 ++- net/mac80211/iface.c | 29 +++++++++++++++++++++++------ net/mac80211/util.c | 6 ++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 232edf78d5a9..9034da16cf1b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -73,16 +73,19 @@ static int ieee80211_change_iface(struct wiphy *wiphy, struct ieee80211_local *local = sdata->local; if (ieee80211_sdata_running(sdata)) { + u32 mask = MONITOR_FLAG_COOK_FRAMES | + MONITOR_FLAG_ACTIVE; + /* - * Prohibit MONITOR_FLAG_COOK_FRAMES to be - * changed while the interface is up. + * Prohibit MONITOR_FLAG_COOK_FRAMES and + * MONITOR_FLAG_ACTIVE to be changed while the + * interface is up. * Else we would need to add a lot of cruft * to update everything: * cooked_mntrs, monitor and all fif_* counters * reconfigure hardware */ - if ((*flags & MONITOR_FLAG_COOK_FRAMES) != - (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) + if ((*flags & mask) != (sdata->u.mntr_flags & mask)) return -EBUSY; ieee80211_adjust_monitor_flags(sdata, -1); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 169664c122e2..b931c96a596f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -146,7 +146,8 @@ static inline int drv_add_interface(struct ieee80211_local *local, if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || (sdata->vif.type == NL80211_IFTYPE_MONITOR && - !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)))) + !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF) && + !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)))) return -EINVAL; trace_drv_add_interface(local, sdata); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ceef64426a8d..7cabaf261fed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -159,7 +159,8 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) +static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, + bool check_dup) { struct ieee80211_sub_if_data *sdata; u64 new, mask, tmp; @@ -179,10 +180,13 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); + if (!check_dup) + return ret; mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) continue; m = sdata->vif.addr; @@ -204,12 +208,17 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sockaddr *sa = addr; + bool check_dup = true; int ret; if (ieee80211_sdata_running(sdata)) return -EBUSY; - ret = ieee80211_verify_mac(sdata->local, sa->sa_data); + if (sdata->vif.type == NL80211_IFTYPE_MONITOR && + !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) + check_dup = false; + + ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup); if (ret) return ret; @@ -541,7 +550,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) break; } - if (local->monitors == 0 && local->open_count == 0) { + if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) { + res = drv_add_interface(local, sdata); + if (res) + goto err_stop; + } else if (local->monitors == 0 && local->open_count == 0) { res = ieee80211_add_virtual_monitor(local); if (res) goto err_stop; @@ -919,7 +932,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->mtx); ieee80211_recalc_idle(local); mutex_unlock(&local->mtx); - break; + + if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) + break; + + /* fall through */ default: if (going_down) drv_remove_interface(local, sdata); @@ -1068,7 +1085,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_start_xmit = ieee80211_monitor_start_xmit, .ndo_set_rx_mode = ieee80211_set_multicast_list, .ndo_change_mtu = ieee80211_change_mtu, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = ieee80211_change_mac, .ndo_select_queue = ieee80211_monitor_select_queue, }; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 2a8d759324c2..89a83770d152 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -560,6 +560,9 @@ void ieee80211_iterate_active_interfaces( list_for_each_entry(sdata, &local->interfaces, list) { switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: + if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) + continue; + break; case NL80211_IFTYPE_AP_VLAN: continue; default: @@ -598,6 +601,9 @@ void ieee80211_iterate_active_interfaces_atomic( list_for_each_entry_rcu(sdata, &local->interfaces, list) { switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: + if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) + continue; + break; case NL80211_IFTYPE_AP_VLAN: continue; default: -- GitLab From bd5e14fb77d9d1dd15f9102759e8c8b31c667488 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 May 2013 09:08:05 +0200 Subject: [PATCH 0505/2900] cfg80211: remove cleanup_work kernel-doc I evidently forgot this when removing the work itself. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 13b247d26544..6dd19593e333 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2869,7 +2869,6 @@ struct cfg80211_cached_keys; * @mgmt_registrations_lock: lock for the list * @mtx: mutex used to lock data in this struct, may be used by drivers * and some API functions require it held - * @cleanup_work: work struct used for cleanup that can't be done directly * @beacon_interval: beacon interval used on this device for transmitting * beacons, 0 when not valid * @address: The address for this device, valid only if @netdev is %NULL -- GitLab From cbb963deed7bbf206f5077ab5742bee00ceefa46 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 29 May 2013 10:22:30 +0300 Subject: [PATCH 0506/2900] net/usb/kalmia: use %*phC to dump small buffers Instead of dereferencing pointer and put values on stack we could use nice %*phC specifier. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- drivers/net/usb/kalmia.c | 45 ++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c index 0192073e53a3..6866eae3e388 100644 --- a/drivers/net/usb/kalmia.c +++ b/drivers/net/usb/kalmia.c @@ -221,12 +221,9 @@ kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) memset(skb_put(skb, padlen), 0, padlen); } - netdev_dbg( - dev->net, - "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.", - content_len, padlen, header_start[0], header_start[1], - header_start[2], header_start[3], header_start[4], - header_start[5]); + netdev_dbg(dev->net, + "Sending package with length %i and padding %i. Header: %6phC.", + content_len, padlen, header_start); return skb; } @@ -263,32 +260,23 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( header_start, EXPECTED_UNKNOWN_HEADER_2, sizeof(EXPECTED_UNKNOWN_HEADER_2))) { - netdev_dbg( - dev->net, - "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_dbg(dev->net, + "Received expected unknown frame header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); } else { - netdev_err( - dev->net, - "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_err(dev->net, + "Received unknown frame header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); return 0; } } else - netdev_dbg( - dev->net, - "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], header_start[2], - header_start[3], header_start[4], header_start[5], - skb->len - KALMIA_HEADER_LENGTH); + netdev_dbg(dev->net, + "Received header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); /* subtract start header and end header */ usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); @@ -310,12 +298,9 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) sizeof(HEADER_END_OF_USB_PACKET)) == 0); if (!is_last) { header_start = skb->data + ether_packet_length; - netdev_dbg( - dev->net, - "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", - header_start[0], header_start[1], - header_start[2], header_start[3], - header_start[4], header_start[5], + netdev_dbg(dev->net, + "End header: %6phC. Package length: %i\n", + header_start, skb->len - KALMIA_HEADER_LENGTH); } } -- GitLab From f4d57941bf89997bad3294f94987caebf2771a33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 28 May 2013 17:24:15 +0200 Subject: [PATCH 0507/2900] mac80211: always send multicast on CAB queue If the driver advertised support for a CAB queue, then we should put all multicast frames there, otherwise sending them can be racy with clients going to sleep while we TX a frame. To avoid this, always TX multicast frames on the multicast queue. It seems like even drivers not using the queue framework might want to do this which would mean also moving the IEEE80211_TX_CTL_SEND_AFTER_DTIM flag assignment, but it also seems that drivers behave differently here so that just moving it wouldn't be a good idea. It'd be better to modify those drivers to use the queue framework. Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9972e07a2f96..34be9336b5d1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -398,13 +398,14 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) if (ieee80211_has_order(hdr->frame_control)) return TX_CONTINUE; + if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + info->hw_queue = tx->sdata->vif.cab_queue; + /* no stations in PS mode */ if (!atomic_read(&ps->num_sta_ps)) return TX_CONTINUE; info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; - if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) - info->hw_queue = tx->sdata->vif.cab_queue; /* device releases frame after DTIM beacon */ if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) -- GitLab From adc2d1225bed4bbf68473e6b5c4b91d2445609cb Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Tue, 28 May 2013 15:17:52 +0300 Subject: [PATCH 0508/2900] wil6210: channel off by 1 WMI commands wants channel index, that is channel - 1 Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 5e01f4ee4de7..a091eb11e392 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -728,7 +728,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) .bcon_interval = cpu_to_le16(bi), .network_type = wmi_nettype, .disable_sec_offload = 1, - .channel = chan, + .channel = chan - 1, }; struct { struct wil6210_mbox_hdr_wmi wmi; -- GitLab From b338f74e33e33616e8fe498b5b09da8a84a7b218 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Tue, 28 May 2013 15:17:53 +0300 Subject: [PATCH 0509/2900] wil6210: Don't use wdev->sme_state sme_state is private wdev's variable. Track connection state internally Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/cfg80211.c | 4 ++++ drivers/net/wireless/ath/wil6210/main.c | 18 ++++++------------ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wmi.c | 3 ++- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index c5d4a87abaaf..4eb05d0818c3 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -322,12 +322,16 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, * FW don't support scan after connection attempt */ set_bit(wil_status_dontscan, &wil->status); + set_bit(wil_status_fwconnecting, &wil->status); rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); if (rc == 0) { /* Connect can take lots of time */ mod_timer(&wil->connect_timer, jiffies + msecs_to_jiffies(2000)); + } else { + clear_bit(wil_status_dontscan, &wil->status); + clear_bit(wil_status_fwconnecting, &wil->status); } out: diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index ea49c8a18e15..c97b864667c5 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -56,27 +56,21 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) { uint i; struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; wil_dbg_misc(wil, "%s()\n", __func__); wil_link_off(wil); - clear_bit(wil_status_fwconnected, &wil->status); - - switch (wdev->sme_state) { - case CFG80211_SME_CONNECTED: - cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, + if (test_bit(wil_status_fwconnected, &wil->status)) { + clear_bit(wil_status_fwconnected, &wil->status); + cfg80211_disconnected(ndev, + WLAN_STATUS_UNSPECIFIED_FAILURE, NULL, 0, GFP_KERNEL); - break; - case CFG80211_SME_CONNECTING: + } else if (test_bit(wil_status_fwconnecting, &wil->status)) { cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); - break; - default: - break; } - + clear_bit(wil_status_fwconnecting, &wil->status); for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) wil_vring_fini_tx(wil, i); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 2e3c26e1c975..373cf656f5b0 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -186,6 +186,7 @@ struct vring { enum { /* for wil6210_priv.status */ wil_status_fwready = 0, + wil_status_fwconnecting, wil_status_fwconnected, wil_status_dontscan, wil_status_reset_done, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index a091eb11e392..527ffb543821 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -409,7 +409,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) if ((wdev->iftype == NL80211_IFTYPE_STATION) || (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { - if (wdev->sme_state != CFG80211_SME_CONNECTING) { + if (!test_bit(wil_status_fwconnecting, &wil->status)) { wil_err(wil, "Not in connecting state\n"); return; } @@ -433,6 +433,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); } + clear_bit(wil_status_fwconnecting, &wil->status); set_bit(wil_status_fwconnected, &wil->status); /* FIXME FW can transmit only ucast frames to peer */ -- GitLab From 9c8426fc79eef00464d33e774085395cac41d091 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 28 May 2013 18:04:44 +0200 Subject: [PATCH 0510/2900] ath9k_hw: fix PA predistortion miscalibration If any bins from the training data are skipped (i != max_index), the calculated compensation curve gets distorted, and the signal will be wildly overamplified. This may be the cause of the reported hardware damage that was caused by PA predistortion (because of which PAPRD was disabled by default). When calculating the x_est, Y, theta values, the use of max_index and i was reversed. i points to the bin index whereas max_index refers to the index of the calculated arrays. Note that PA predistortion is still disabled, it will be re-enabled after it has been properly validated. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 09c1f9da67a0..6343cc91953e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -454,6 +454,8 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) if (accum_cnt <= thresh_accum_cnt) continue; + max_index++; + /* sum(tx amplitude) */ accum_tx = ((data_L[i] >> 16) & 0xffff) | ((data_U[i] & 0x7ff) << 16); @@ -468,20 +470,21 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) accum_tx <<= scale_factor; accum_rx <<= scale_factor; - x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >> - scale_factor; + x_est[max_index] = + (((accum_tx + accum_cnt) / accum_cnt) + 32) >> + scale_factor; - Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> + Y[max_index] = + ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> scale_factor) + - (1 << scale_factor) * max_index + 16; + (1 << scale_factor) * i + 16; if (accum_ang >= (1 << 26)) accum_ang -= 1 << 27; - theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) / - accum_cnt; - - max_index++; + theta[max_index] = + ((accum_ang * (1 << scale_factor)) + accum_cnt) / + accum_cnt; } /* -- GitLab From b6c32f88740013b78eee68a604678b548750510f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 29 May 2013 15:31:40 +0530 Subject: [PATCH 0511/2900] net: wireless: p54spi: Use module_spi_driver macro module_spi_driver() eliminates some boiler plate and makes code simpler. Signed-off-by: Sachin Kamat Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 978e7eb26567..146e6530ae29 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -713,27 +713,7 @@ static struct spi_driver p54spi_driver = { .remove = p54spi_remove, }; -static int __init p54spi_init(void) -{ - int ret; - - ret = spi_register_driver(&p54spi_driver); - if (ret < 0) { - printk(KERN_ERR "failed to register SPI driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit p54spi_exit(void) -{ - spi_unregister_driver(&p54spi_driver); -} - -module_init(p54spi_init); -module_exit(p54spi_exit); +module_spi_driver(p54spi_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter "); -- GitLab From acba7bb3c246618c8af895a548ec1b0d3da050d0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 29 May 2013 15:31:41 +0530 Subject: [PATCH 0512/2900] net: wireless: p54spi: Fix commenting style Make the commenting style consistent with networking block comment style as suggested by checkpatch. Signed-off-by: Sachin Kamat Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54spi.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 146e6530ae29..7fc46f26cf2b 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -42,8 +42,7 @@ MODULE_FIRMWARE("3826.arm"); -/* - * gpios should be handled in board files and provided via platform data, +/* gpios should be handled in board files and provided via platform data, * but because it's currently impossible for p54spi to have a header file * in include/linux, let's use module paramaters for now */ @@ -191,8 +190,7 @@ static int p54spi_request_eeprom(struct ieee80211_hw *dev) const struct firmware *eeprom; int ret; - /* - * allow users to customize their eeprom. + /* allow users to customize their eeprom. */ ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev); @@ -285,8 +283,7 @@ static void p54spi_power_on(struct p54s_priv *priv) gpio_set_value(p54spi_gpio_power, 1); enable_irq(gpio_to_irq(p54spi_gpio_irq)); - /* - * need to wait a while before device can be accessed, the length + /* need to wait a while before device can be accessed, the length * is just a guess */ msleep(10); @@ -365,7 +362,8 @@ static int p54spi_rx(struct p54s_priv *priv) /* Firmware may insert up to 4 padding bytes after the lmac header, * but it does not amend the size of SPI data transfer. * Such packets has correct data size in header, thus referencing - * past the end of allocated skb. Reserve extra 4 bytes for this case */ + * past the end of allocated skb. Reserve extra 4 bytes for this case + */ skb = dev_alloc_skb(len + 4); if (!skb) { p54spi_sleep(priv); @@ -383,7 +381,8 @@ static int p54spi_rx(struct p54s_priv *priv) } p54spi_sleep(priv); /* Put additional bytes to compensate for the possible - * alignment-caused truncation */ + * alignment-caused truncation + */ skb_put(skb, 4); if (p54_rx(priv->hw, skb) == 0) -- GitLab From 5f07d15a77e3098e7286b016247ecca20a0209d4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 29 May 2013 13:04:20 +0300 Subject: [PATCH 0513/2900] mwifiex: dump small buffers with help of %*ph Signed-off-by: Andy Shevchenko Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/join.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 6bcb66e6e97c..122175af18c6 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -919,9 +919,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, memcpy(&priv->curr_bss_params.data_rates, &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates); - dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%02x %02x %02x %02x\n", - adhoc_start->data_rate[0], adhoc_start->data_rate[1], - adhoc_start->data_rate[2], adhoc_start->data_rate[3]); + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: rates=%4ph\n", + adhoc_start->data_rate); dev_dbg(adapter->dev, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); -- GitLab From a910e4a94f6923c8c988565525f017f687bf7205 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 24 May 2013 20:04:38 -0400 Subject: [PATCH 0514/2900] cw1200: add driver for the ST-E CW1100 & CW1200 WLAN chipsets Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- MAINTAINERS | 5 + drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 2 + drivers/net/wireless/cw1200/Kconfig | 46 + drivers/net/wireless/cw1200/Makefile | 24 + drivers/net/wireless/cw1200/bh.c | 616 +++++ drivers/net/wireless/cw1200/bh.h | 28 + drivers/net/wireless/cw1200/cw1200.h | 332 +++ drivers/net/wireless/cw1200/cw1200_sagrad.c | 145 ++ drivers/net/wireless/cw1200/cw1200_sdio.c | 409 ++++ drivers/net/wireless/cw1200/cw1200_spi.c | 480 ++++ drivers/net/wireless/cw1200/debug.c | 664 +++++ drivers/net/wireless/cw1200/debug.h | 98 + drivers/net/wireless/cw1200/fwio.c | 525 ++++ drivers/net/wireless/cw1200/fwio.h | 39 + drivers/net/wireless/cw1200/hwio.c | 311 +++ drivers/net/wireless/cw1200/hwio.h | 247 ++ drivers/net/wireless/cw1200/itp.c | 730 ++++++ drivers/net/wireless/cw1200/itp.h | 144 ++ drivers/net/wireless/cw1200/main.c | 618 +++++ drivers/net/wireless/cw1200/pm.c | 367 +++ drivers/net/wireless/cw1200/pm.h | 38 + drivers/net/wireless/cw1200/queue.c | 583 +++++ drivers/net/wireless/cw1200/queue.h | 116 + drivers/net/wireless/cw1200/sbus.h | 37 + drivers/net/wireless/cw1200/scan.c | 461 ++++ drivers/net/wireless/cw1200/scan.h | 56 + drivers/net/wireless/cw1200/sta.c | 2406 +++++++++++++++++++ drivers/net/wireless/cw1200/sta.h | 123 + drivers/net/wireless/cw1200/txrx.c | 1474 ++++++++++++ drivers/net/wireless/cw1200/txrx.h | 106 + drivers/net/wireless/cw1200/wsm.c | 1884 +++++++++++++++ drivers/net/wireless/cw1200/wsm.h | 1879 +++++++++++++++ include/linux/cw1200_platform.h | 46 + 34 files changed, 15040 insertions(+) create mode 100644 drivers/net/wireless/cw1200/Kconfig create mode 100644 drivers/net/wireless/cw1200/Makefile create mode 100644 drivers/net/wireless/cw1200/bh.c create mode 100644 drivers/net/wireless/cw1200/bh.h create mode 100644 drivers/net/wireless/cw1200/cw1200.h create mode 100644 drivers/net/wireless/cw1200/cw1200_sagrad.c create mode 100644 drivers/net/wireless/cw1200/cw1200_sdio.c create mode 100644 drivers/net/wireless/cw1200/cw1200_spi.c create mode 100644 drivers/net/wireless/cw1200/debug.c create mode 100644 drivers/net/wireless/cw1200/debug.h create mode 100644 drivers/net/wireless/cw1200/fwio.c create mode 100644 drivers/net/wireless/cw1200/fwio.h create mode 100644 drivers/net/wireless/cw1200/hwio.c create mode 100644 drivers/net/wireless/cw1200/hwio.h create mode 100644 drivers/net/wireless/cw1200/itp.c create mode 100644 drivers/net/wireless/cw1200/itp.h create mode 100644 drivers/net/wireless/cw1200/main.c create mode 100644 drivers/net/wireless/cw1200/pm.c create mode 100644 drivers/net/wireless/cw1200/pm.h create mode 100644 drivers/net/wireless/cw1200/queue.c create mode 100644 drivers/net/wireless/cw1200/queue.h create mode 100644 drivers/net/wireless/cw1200/sbus.h create mode 100644 drivers/net/wireless/cw1200/scan.c create mode 100644 drivers/net/wireless/cw1200/scan.h create mode 100644 drivers/net/wireless/cw1200/sta.c create mode 100644 drivers/net/wireless/cw1200/sta.h create mode 100644 drivers/net/wireless/cw1200/txrx.c create mode 100644 drivers/net/wireless/cw1200/txrx.h create mode 100644 drivers/net/wireless/cw1200/wsm.c create mode 100644 drivers/net/wireless/cw1200/wsm.h create mode 100644 include/linux/cw1200_platform.h diff --git a/MAINTAINERS b/MAINTAINERS index 3d7782b9f90d..e5069c223391 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2299,6 +2299,11 @@ M: Jaya Kumar S: Maintained F: sound/pci/cs5535audio/ +CW1200 WLAN driver +M: Solomon Peachy +S: Maintained +F: drivers/net/wireless/cw1200/ + CX18 VIDEO4LINUX DRIVER M: Andy Walls L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f8f0156dff4e..200020eb3005 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -280,5 +280,6 @@ source "drivers/net/wireless/rtlwifi/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/mwifiex/Kconfig" +source "drivers/net/wireless/cw1200/Kconfig" endif # WLAN diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 67156efe14c4..0fab227025be 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -57,3 +57,5 @@ obj-$(CONFIG_MWIFIEX) += mwifiex/ obj-$(CONFIG_BRCMFMAC) += brcm80211/ obj-$(CONFIG_BRCMSMAC) += brcm80211/ + +obj-$(CONFIG_CW1200) += cw1200/ diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig new file mode 100644 index 000000000000..13e36119ae9f --- /dev/null +++ b/drivers/net/wireless/cw1200/Kconfig @@ -0,0 +1,46 @@ +config CW1200 + tristate "CW1200 WLAN support" + depends on MAC80211 && CFG80211 + help + This is a driver for the ST-E CW1100 & CW1200 WLAN chipsets. + This option just enables the driver core, see below for + specific bus support. + +if CW1200 + +config CW1200_WLAN_SDIO + tristate "Support SDIO platforms" + depends on CW1200 && MMC + help + Enable support for the CW1200 connected via an SDIO bus. + +config CW1200_WLAN_SPI + tristate "Support SPI platforms" + depends on CW1200 && SPI + help + Enables support for the CW1200 connected via a SPI bus. + +config CW1200_WLAN_SAGRAD + tristate "Support Sagrad SG901-1091/1098 modules" + depends on CW1200_WLAN_SDIO + help + This provides the platform data glue to support the + Sagrad SG901-1091/1098 modules in their standard SDIO EVK. + It also includes example SPI platform data. + +menu "Driver debug features" + depends on CW1200 && DEBUG_FS + +config CW1200_ETF + bool "Enable CW1200 Engineering Test Framework hooks" + help + If you don't know what this is, just say N. + +config CW1200_ITP + bool "Enable ITP access" + help + If you don't know what this is, just say N. + +endmenu + +endif diff --git a/drivers/net/wireless/cw1200/Makefile b/drivers/net/wireless/cw1200/Makefile new file mode 100644 index 000000000000..c19737276be2 --- /dev/null +++ b/drivers/net/wireless/cw1200/Makefile @@ -0,0 +1,24 @@ +cw1200_core-y := \ + fwio.o \ + txrx.o \ + main.o \ + queue.o \ + hwio.o \ + bh.o \ + wsm.o \ + sta.o \ + scan.o \ + pm.o \ + debug.o +cw1200_core-$(CONFIG_CW1200_ITP) += itp.o + +# CFLAGS_sta.o += -DDEBUG + +cw1200_wlan_sdio-y := cw1200_sdio.o +cw1200_wlan_spi-y := cw1200_spi.o +cw1200_wlan_sagrad-y := cw1200_sagrad.o + +obj-$(CONFIG_CW1200) += cw1200_core.o +obj-$(CONFIG_CW1200_WLAN_SDIO) += cw1200_wlan_sdio.o +obj-$(CONFIG_CW1200_WLAN_SPI) += cw1200_wlan_spi.o +obj-$(CONFIG_CW1200_WLAN_SAGRAD) += cw1200_wlan_sagrad.o diff --git a/drivers/net/wireless/cw1200/bh.c b/drivers/net/wireless/cw1200/bh.c new file mode 100644 index 000000000000..cf7375f92fb3 --- /dev/null +++ b/drivers/net/wireless/cw1200/bh.c @@ -0,0 +1,616 @@ +/* + * Device handling thread implementation for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * ST-Ericsson UMAC CW1200 driver, which is + * Copyright (c) 2010, ST-Ericsson + * Author: Ajitpal Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "cw1200.h" +#include "bh.h" +#include "hwio.h" +#include "wsm.h" +#include "sbus.h" +#include "debug.h" +#include "fwio.h" + +static int cw1200_bh(void *arg); + +#define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4) +/* an SPI message cannot be bigger than (2"12-1)*2 bytes + * "*2" to cvt to bytes */ +#define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2) +#define PIGGYBACK_CTRL_REG (2) +#define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG) + +/* Suspend state privates */ +enum cw1200_bh_pm_state { + CW1200_BH_RESUMED = 0, + CW1200_BH_SUSPEND, + CW1200_BH_SUSPENDED, + CW1200_BH_RESUME, +}; + +typedef int (*cw1200_wsm_handler)(struct cw1200_common *priv, + u8 *data, size_t size); + +static void cw1200_bh_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, bh_work); + cw1200_bh(priv); +} + +int cw1200_register_bh(struct cw1200_common *priv) +{ + int err = 0; + /* Realtime workqueue */ + priv->bh_workqueue = alloc_workqueue("cw1200_bh", + WQ_MEM_RECLAIM | WQ_HIGHPRI + | WQ_CPU_INTENSIVE, 1); + + if (!priv->bh_workqueue) + return -ENOMEM; + + INIT_WORK(&priv->bh_work, cw1200_bh_work); + + pr_debug("[BH] register.\n"); + + atomic_set(&priv->bh_rx, 0); + atomic_set(&priv->bh_tx, 0); + atomic_set(&priv->bh_term, 0); + atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED); + priv->bh_error = 0; + priv->hw_bufs_used = 0; + priv->buf_id_tx = 0; + priv->buf_id_rx = 0; + init_waitqueue_head(&priv->bh_wq); + init_waitqueue_head(&priv->bh_evt_wq); + + err = !queue_work(priv->bh_workqueue, &priv->bh_work); + WARN_ON(err); + return err; +} + +void cw1200_unregister_bh(struct cw1200_common *priv) +{ + atomic_add(1, &priv->bh_term); + wake_up(&priv->bh_wq); + + flush_workqueue(priv->bh_workqueue); + + destroy_workqueue(priv->bh_workqueue); + priv->bh_workqueue = NULL; + + pr_debug("[BH] unregistered.\n"); +} + +void cw1200_irq_handler(struct cw1200_common *priv) +{ + pr_debug("[BH] irq.\n"); + + /* Disable Interrupts! */ + /* NOTE: sbus_ops->lock already held */ + __cw1200_irq_enable(priv, 0); + + if (/* WARN_ON */(priv->bh_error)) + return; + + if (atomic_add_return(1, &priv->bh_rx) == 1) + wake_up(&priv->bh_wq); +} +EXPORT_SYMBOL_GPL(cw1200_irq_handler); + +void cw1200_bh_wakeup(struct cw1200_common *priv) +{ + pr_debug("[BH] wakeup.\n"); + if (priv->bh_error) { + pr_err("[BH] wakeup failed (BH error)\n"); + return; + } + + if (atomic_add_return(1, &priv->bh_tx) == 1) + wake_up(&priv->bh_wq); +} + +int cw1200_bh_suspend(struct cw1200_common *priv) +{ + pr_debug("[BH] suspend.\n"); + if (priv->bh_error) { + wiphy_warn(priv->hw->wiphy, "BH error -- can't suspend\n"); + return -EINVAL; + } + + atomic_set(&priv->bh_suspend, CW1200_BH_SUSPEND); + wake_up(&priv->bh_wq); + return wait_event_timeout(priv->bh_evt_wq, priv->bh_error || + (CW1200_BH_SUSPENDED == atomic_read(&priv->bh_suspend)), + 1 * HZ) ? 0 : -ETIMEDOUT; +} + +int cw1200_bh_resume(struct cw1200_common *priv) +{ + pr_debug("[BH] resume.\n"); + if (priv->bh_error) { + wiphy_warn(priv->hw->wiphy, "BH error -- can't resume\n"); + return -EINVAL; + } + + atomic_set(&priv->bh_suspend, CW1200_BH_RESUME); + wake_up(&priv->bh_wq); + return wait_event_timeout(priv->bh_evt_wq, priv->bh_error || + (CW1200_BH_RESUMED == atomic_read(&priv->bh_suspend)), + 1 * HZ) ? 0 : -ETIMEDOUT; +} + +static inline void wsm_alloc_tx_buffer(struct cw1200_common *priv) +{ + ++priv->hw_bufs_used; +} + +int wsm_release_tx_buffer(struct cw1200_common *priv, int count) +{ + int ret = 0; + int hw_bufs_used = priv->hw_bufs_used; + + priv->hw_bufs_used -= count; + if (WARN_ON(priv->hw_bufs_used < 0)) + ret = -1; + else if (hw_bufs_used >= priv->wsm_caps.input_buffers) + ret = 1; + if (!priv->hw_bufs_used) + wake_up(&priv->bh_evt_wq); + return ret; +} + +static int cw1200_bh_read_ctrl_reg(struct cw1200_common *priv, + u16 *ctrl_reg) +{ + int ret; + + ret = cw1200_reg_read_16(priv, + ST90TDS_CONTROL_REG_ID, ctrl_reg); + if (ret) { + ret = cw1200_reg_read_16(priv, + ST90TDS_CONTROL_REG_ID, ctrl_reg); + if (ret) + pr_err("[BH] Failed to read control register.\n"); + } + + return ret; +} + +static int cw1200_device_wakeup(struct cw1200_common *priv) +{ + u16 ctrl_reg; + int ret; + + pr_debug("[BH] Device wakeup.\n"); + + /* First, set the dpll register */ + ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID, + cw1200_dpll_from_clk(priv->hw_refclk)); + if (WARN_ON(ret)) + return ret; + + /* To force the device to be always-on, the host sets WLAN_UP to 1 */ + ret = cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID, + ST90TDS_CONT_WUP_BIT); + if (WARN_ON(ret)) + return ret; + + ret = cw1200_bh_read_ctrl_reg(priv, &ctrl_reg); + if (WARN_ON(ret)) + return ret; + + /* If the device returns WLAN_RDY as 1, the device is active and will + * remain active. */ + if (ctrl_reg & ST90TDS_CONT_RDY_BIT) { + pr_debug("[BH] Device awake.\n"); + return 1; + } + + return 0; +} + +/* Must be called from BH thraed. */ +void cw1200_enable_powersave(struct cw1200_common *priv, + bool enable) +{ + pr_debug("[BH] Powerave is %s.\n", + enable ? "enabled" : "disabled"); + priv->powersave_enabled = enable; +} + +static int cw1200_bh_rx_helper(struct cw1200_common *priv, + uint16_t *ctrl_reg, + int *tx) +{ + size_t read_len = 0; + struct sk_buff *skb_rx = NULL; + struct wsm_hdr *wsm; + size_t wsm_len; + u16 wsm_id; + u8 wsm_seq; + int rx_resync = 1; + + size_t alloc_len; + u8 *data; + + read_len = (*ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) * 2; + if (!read_len) + return 0; /* No more work */ + + if (WARN_ON((read_len < sizeof(struct wsm_hdr)) || + (read_len > EFFECTIVE_BUF_SIZE))) { + pr_debug("Invalid read len: %zu (%04x)", + read_len, *ctrl_reg); + goto err; + } + + /* Add SIZE of PIGGYBACK reg (CONTROL Reg) + * to the NEXT Message length + 2 Bytes for SKB */ + read_len = read_len + 2; + + alloc_len = priv->sbus_ops->align_size( + priv->sbus_priv, read_len); + + /* Check if not exceeding CW1200 capabilities */ + if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE)) { + pr_debug("Read aligned len: %zu\n", + alloc_len); + } + + skb_rx = dev_alloc_skb(alloc_len); + if (WARN_ON(!skb_rx)) + goto err; + + skb_trim(skb_rx, 0); + skb_put(skb_rx, read_len); + data = skb_rx->data; + if (WARN_ON(!data)) + goto err; + + if (WARN_ON(cw1200_data_read(priv, data, alloc_len))) { + pr_err("rx blew up, len %zu\n", alloc_len); + goto err; + } + + /* Piggyback */ + *ctrl_reg = __le16_to_cpu( + ((__le16 *)data)[alloc_len / 2 - 1]); + + wsm = (struct wsm_hdr *)data; + wsm_len = __le16_to_cpu(wsm->len); + if (WARN_ON(wsm_len > read_len)) + goto err; + + if (priv->wsm_enable_wsm_dumps) + print_hex_dump_bytes("<-- ", + DUMP_PREFIX_NONE, + data, wsm_len); + + wsm_id = __le16_to_cpu(wsm->id) & 0xFFF; + wsm_seq = (__le16_to_cpu(wsm->id) >> 13) & 7; + + skb_trim(skb_rx, wsm_len); + + if (wsm_id == 0x0800) { + wsm_handle_exception(priv, + &data[sizeof(*wsm)], + wsm_len - sizeof(*wsm)); + goto err; + } else if (!rx_resync) { + if (WARN_ON(wsm_seq != priv->wsm_rx_seq)) + goto err; + } + priv->wsm_rx_seq = (wsm_seq + 1) & 7; + rx_resync = 0; + + if (wsm_id & 0x0400) { + int rc = wsm_release_tx_buffer(priv, 1); + if (WARN_ON(rc < 0)) + return rc; + else if (rc > 0) + *tx = 1; + } + + /* cw1200_wsm_rx takes care on SKB livetime */ + if (WARN_ON(wsm_handle_rx(priv, wsm_id, wsm, &skb_rx))) + goto err; + + if (skb_rx) { + dev_kfree_skb(skb_rx); + skb_rx = NULL; + } + + return 0; + +err: + if (skb_rx) { + dev_kfree_skb(skb_rx); + skb_rx = NULL; + } + return -1; +} + +static int cw1200_bh_tx_helper(struct cw1200_common *priv, + int *pending_tx, + int *tx_burst) +{ + size_t tx_len; + u8 *data; + int ret; + struct wsm_hdr *wsm; + + if (priv->device_can_sleep) { + ret = cw1200_device_wakeup(priv); + if (WARN_ON(ret < 0)) { /* Error in wakeup */ + *pending_tx = 1; + return 0; + } else if (ret) { /* Woke up */ + priv->device_can_sleep = false; + } else { /* Did not awake */ + *pending_tx = 1; + return 0; + } + } + + wsm_alloc_tx_buffer(priv); + ret = wsm_get_tx(priv, &data, &tx_len, tx_burst); + if (ret <= 0) { + wsm_release_tx_buffer(priv, 1); + if (WARN_ON(ret < 0)) + return ret; /* Error */ + return 0; /* No work */ + } + + wsm = (struct wsm_hdr *)data; + BUG_ON(tx_len < sizeof(*wsm)); + BUG_ON(__le16_to_cpu(wsm->len) != tx_len); + + atomic_add(1, &priv->bh_tx); + + tx_len = priv->sbus_ops->align_size( + priv->sbus_priv, tx_len); + + /* Check if not exceeding CW1200 capabilities */ + if (WARN_ON_ONCE(tx_len > EFFECTIVE_BUF_SIZE)) + pr_debug("Write aligned len: %zu\n", tx_len); + + wsm->id &= __cpu_to_le16(0xffff ^ WSM_TX_SEQ(WSM_TX_SEQ_MAX)); + wsm->id |= __cpu_to_le16(WSM_TX_SEQ(priv->wsm_tx_seq)); + + if (WARN_ON(cw1200_data_write(priv, data, tx_len))) { + pr_err("tx blew up, len %zu\n", tx_len); + wsm_release_tx_buffer(priv, 1); + return -1; /* Error */ + } + + if (priv->wsm_enable_wsm_dumps) + print_hex_dump_bytes("--> ", + DUMP_PREFIX_NONE, + data, + __le16_to_cpu(wsm->len)); + + wsm_txed(priv, data); + priv->wsm_tx_seq = (priv->wsm_tx_seq + 1) & WSM_TX_SEQ_MAX; + + if (*tx_burst > 1) { + cw1200_debug_tx_burst(priv); + return 1; /* Work remains */ + } + + return 0; +} + +static int cw1200_bh(void *arg) +{ + struct cw1200_common *priv = arg; + int rx, tx, term, suspend; + u16 ctrl_reg = 0; + int tx_allowed; + int pending_tx = 0; + int tx_burst; + long status; + u32 dummy; + int ret; + + for (;;) { + if (!priv->hw_bufs_used && + priv->powersave_enabled && + !priv->device_can_sleep && + !atomic_read(&priv->recent_scan)) { + status = 1 * HZ; + pr_debug("[BH] Device wakedown. No data.\n"); + cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID, 0); + priv->device_can_sleep = true; + } else if (priv->hw_bufs_used) { + /* Interrupt loss detection */ + status = 1 * HZ; + } else { + status = MAX_SCHEDULE_TIMEOUT; + } + + /* Dummy Read for SDIO retry mechanism*/ + if ((priv->hw_type != -1) && + (atomic_read(&priv->bh_rx) == 0) && + (atomic_read(&priv->bh_tx) == 0)) + cw1200_reg_read(priv, ST90TDS_CONFIG_REG_ID, + &dummy, sizeof(dummy)); + + pr_debug("[BH] waiting ...\n"); + status = wait_event_interruptible_timeout(priv->bh_wq, ({ + rx = atomic_xchg(&priv->bh_rx, 0); + tx = atomic_xchg(&priv->bh_tx, 0); + term = atomic_xchg(&priv->bh_term, 0); + suspend = pending_tx ? + 0 : atomic_read(&priv->bh_suspend); + (rx || tx || term || suspend || priv->bh_error); + }), status); + + pr_debug("[BH] - rx: %d, tx: %d, term: %d, suspend: %d, status: %ld\n", + rx, tx, term, suspend, status); + + /* Did an error occur? */ + if ((status < 0 && status != -ERESTARTSYS) || + term || priv->bh_error) { + break; + } + if (!status) { /* wait_event timed out */ + unsigned long timestamp = jiffies; + long timeout; + int pending = 0; + int i; + + /* Check to see if we have any outstanding frames */ + if (priv->hw_bufs_used && (!rx || !tx)) { + wiphy_warn(priv->hw->wiphy, + "Missed interrupt? (%d frames outstanding)\n", + priv->hw_bufs_used); + rx = 1; + + /* Get a timestamp of "oldest" frame */ + for (i = 0; i < 4; ++i) + pending += cw1200_queue_get_xmit_timestamp( + &priv->tx_queue[i], + ×tamp, + priv->pending_frame_id); + + /* Check if frame transmission is timed out. + * Add an extra second with respect to possible + * interrupt loss. + */ + timeout = timestamp + + WSM_CMD_LAST_CHANCE_TIMEOUT + + 1 * HZ - + jiffies; + + /* And terminate BH thread if the frame is "stuck" */ + if (pending && timeout < 0) { + wiphy_warn(priv->hw->wiphy, + "Timeout waiting for TX confirm (%d/%d pending, %ld vs %lu).\n", + priv->hw_bufs_used, pending, + timestamp, jiffies); + break; + } + } else if (!priv->device_can_sleep && + !atomic_read(&priv->recent_scan)) { + pr_debug("[BH] Device wakedown. Timeout.\n"); + cw1200_reg_write_16(priv, + ST90TDS_CONTROL_REG_ID, 0); + priv->device_can_sleep = true; + } + goto done; + } else if (suspend) { + pr_debug("[BH] Device suspend.\n"); + if (priv->powersave_enabled) { + pr_debug("[BH] Device wakedown. Suspend.\n"); + cw1200_reg_write_16(priv, + ST90TDS_CONTROL_REG_ID, 0); + priv->device_can_sleep = true; + } + + atomic_set(&priv->bh_suspend, CW1200_BH_SUSPENDED); + wake_up(&priv->bh_evt_wq); + status = wait_event_interruptible(priv->bh_wq, + CW1200_BH_RESUME == atomic_read(&priv->bh_suspend)); + if (status < 0) { + wiphy_err(priv->hw->wiphy, + "Failed to wait for resume: %ld.\n", + status); + break; + } + pr_debug("[BH] Device resume.\n"); + atomic_set(&priv->bh_suspend, CW1200_BH_RESUMED); + wake_up(&priv->bh_evt_wq); + atomic_add(1, &priv->bh_rx); + goto done; + } + + rx: + tx += pending_tx; + pending_tx = 0; + + if (cw1200_bh_read_ctrl_reg(priv, &ctrl_reg)) + break; + + /* Don't bother trying to rx unless we have data to read */ + if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) { + ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx); + if (ret < 0) + break; + /* Double up here if there's more data.. */ + if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) { + ret = cw1200_bh_rx_helper(priv, &ctrl_reg, &tx); + if (ret < 0) + break; + } + } + + tx: + if (tx) { + tx = 0; + + BUG_ON(priv->hw_bufs_used > priv->wsm_caps.input_buffers); + tx_burst = priv->wsm_caps.input_buffers - priv->hw_bufs_used; + tx_allowed = tx_burst > 0; + + if (!tx_allowed) { + /* Buffers full. Ensure we process tx + * after we handle rx.. + */ + pending_tx = tx; + goto done_rx; + } + ret = cw1200_bh_tx_helper(priv, &pending_tx, &tx_burst); + if (ret < 0) + break; + if (ret > 0) /* More to transmit */ + tx = ret; + + /* Re-read ctrl reg */ + if (cw1200_bh_read_ctrl_reg(priv, &ctrl_reg)) + break; + } + + done_rx: + if (priv->bh_error) + break; + if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) + goto rx; + if (tx) + goto tx; + + done: + /* Re-enable device interrupts */ + priv->sbus_ops->lock(priv->sbus_priv); + __cw1200_irq_enable(priv, 1); + priv->sbus_ops->unlock(priv->sbus_priv); + } + + /* Explicitly disable device interrupts */ + priv->sbus_ops->lock(priv->sbus_priv); + __cw1200_irq_enable(priv, 0); + priv->sbus_ops->unlock(priv->sbus_priv); + + if (!term) { + pr_err("[BH] Fatal error, exiting.\n"); + priv->bh_error = 1; + /* TODO: schedule_work(recovery) */ + } + return 0; +} diff --git a/drivers/net/wireless/cw1200/bh.h b/drivers/net/wireless/cw1200/bh.h new file mode 100644 index 000000000000..af6a4853728f --- /dev/null +++ b/drivers/net/wireless/cw1200/bh.h @@ -0,0 +1,28 @@ +/* + * Device handling thread interface for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_BH_H +#define CW1200_BH_H + +/* extern */ struct cw1200_common; + +int cw1200_register_bh(struct cw1200_common *priv); +void cw1200_unregister_bh(struct cw1200_common *priv); +void cw1200_irq_handler(struct cw1200_common *priv); +void cw1200_bh_wakeup(struct cw1200_common *priv); +int cw1200_bh_suspend(struct cw1200_common *priv); +int cw1200_bh_resume(struct cw1200_common *priv); +/* Must be called from BH thread. */ +void cw1200_enable_powersave(struct cw1200_common *priv, + bool enable); +int wsm_release_tx_buffer(struct cw1200_common *priv, int count); + +#endif /* CW1200_BH_H */ diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h new file mode 100644 index 000000000000..2aa17ca60ba8 --- /dev/null +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -0,0 +1,332 @@ +/* + * Common private data for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on the mac80211 Prism54 code, which is + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_H +#define CW1200_H + +#include +#include +#include +#include +#include + +#include "queue.h" +#include "wsm.h" +#include "scan.h" +#include "txrx.h" +#include "pm.h" + +/* Forward declarations */ +struct sbus_ops; +struct task_struct; +struct cw1200_debug_priv; +struct firmware; + +#ifdef CONFIG_CW1200_ETF +extern int etf_mode; +extern char *etf_firmware; +#endif + +#define CW1200_MAX_CTRL_FRAME_LEN (0x1000) + +#define CW1200_MAX_STA_IN_AP_MODE (5) +#define CW1200_LINK_ID_AFTER_DTIM (CW1200_MAX_STA_IN_AP_MODE + 1) +#define CW1200_LINK_ID_UAPSD (CW1200_MAX_STA_IN_AP_MODE + 2) +#define CW1200_LINK_ID_MAX (CW1200_MAX_STA_IN_AP_MODE + 3) +#define CW1200_MAX_REQUEUE_ATTEMPTS (5) + +#define CW1200_MAX_TID (8) + +#define CW1200_BLOCK_ACK_CNT (30) +#define CW1200_BLOCK_ACK_THLD (800) +#define CW1200_BLOCK_ACK_HIST (3) +#define CW1200_BLOCK_ACK_INTERVAL (1 * HZ / CW1200_BLOCK_ACK_HIST) + +#define CW1200_JOIN_TIMEOUT (1 * HZ) +#define CW1200_AUTH_TIMEOUT (5 * HZ) + +struct cw1200_ht_info { + struct ieee80211_sta_ht_cap ht_cap; + enum nl80211_channel_type channel_type; + u16 operation_mode; +}; + +/* Please keep order */ +enum cw1200_join_status { + CW1200_JOIN_STATUS_PASSIVE = 0, + CW1200_JOIN_STATUS_MONITOR, + CW1200_JOIN_STATUS_JOINING, + CW1200_JOIN_STATUS_PRE_STA, + CW1200_JOIN_STATUS_STA, + CW1200_JOIN_STATUS_IBSS, + CW1200_JOIN_STATUS_AP, +}; + +enum cw1200_link_status { + CW1200_LINK_OFF, + CW1200_LINK_RESERVE, + CW1200_LINK_SOFT, + CW1200_LINK_HARD, + CW1200_LINK_RESET, + CW1200_LINK_RESET_REMAP, +}; + +extern int cw1200_power_mode; +extern const char * const cw1200_fw_types[]; + +struct cw1200_link_entry { + unsigned long timestamp; + enum cw1200_link_status status; + enum cw1200_link_status prev_status; + u8 mac[ETH_ALEN]; + u8 buffered[CW1200_MAX_TID]; + struct sk_buff_head rx_queue; +}; + +struct cw1200_common { + /* interfaces to the rest of the stack */ + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + struct device *pdev; + + /* Statistics */ + struct ieee80211_low_level_stats stats; + + /* Our macaddr */ + u8 mac_addr[ETH_ALEN]; + + /* Hardware interface */ + const struct sbus_ops *sbus_ops; + struct sbus_priv *sbus_priv; + + /* Hardware information */ + enum { + HIF_9000_SILICON_VERSATILE = 0, + HIF_8601_VERSATILE, + HIF_8601_SILICON, + } hw_type; + enum { + CW1200_HW_REV_CUT10 = 10, + CW1200_HW_REV_CUT11 = 11, + CW1200_HW_REV_CUT20 = 20, + CW1200_HW_REV_CUT22 = 22, + CW1X60_HW_REV = 40, + } hw_revision; + int hw_refclk; + bool hw_have_5ghz; + const struct firmware *sdd; + char *sdd_path; + + struct cw1200_debug_priv *debug; + + struct workqueue_struct *workqueue; + struct mutex conf_mutex; + + struct cw1200_queue tx_queue[4]; + struct cw1200_queue_stats tx_queue_stats; + int tx_burst_idx; + + /* firmware/hardware info */ + unsigned int tx_hdr_len; + + /* Radio data */ + int output_power; + + /* BBP/MAC state */ + struct ieee80211_rate *rates; + struct ieee80211_rate *mcs_rates; + struct ieee80211_channel *channel; + struct wsm_edca_params edca; + struct wsm_tx_queue_params tx_queue_params; + struct wsm_mib_association_mode association_mode; + struct wsm_set_bss_params bss_params; + struct cw1200_ht_info ht_info; + struct wsm_set_pm powersave_mode; + struct wsm_set_pm firmware_ps_mode; + int cqm_rssi_thold; + unsigned cqm_rssi_hyst; + bool cqm_use_rssi; + int cqm_beacon_loss_count; + int channel_switch_in_progress; + wait_queue_head_t channel_switch_done; + u8 long_frame_max_tx_count; + u8 short_frame_max_tx_count; + int mode; + bool enable_beacon; + int beacon_int; + bool listening; + struct wsm_rx_filter rx_filter; + struct wsm_mib_multicast_filter multicast_filter; + bool has_multicast_subscription; + bool disable_beacon_filter; + struct work_struct update_filtering_work; + struct work_struct set_beacon_wakeup_period_work; + + u8 ba_rx_tid_mask; + u8 ba_tx_tid_mask; + + struct cw1200_pm_state pm_state; + + struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo; + struct wsm_uapsd_info uapsd_info; + bool setbssparams_done; + bool bt_present; + u8 conf_listen_interval; + u32 listen_interval; + u32 erp_info; + u32 rts_threshold; + + /* BH */ + atomic_t bh_rx; + atomic_t bh_tx; + atomic_t bh_term; + atomic_t bh_suspend; + + struct workqueue_struct *bh_workqueue; + struct work_struct bh_work; + + int bh_error; + wait_queue_head_t bh_wq; + wait_queue_head_t bh_evt_wq; + u8 buf_id_tx; + u8 buf_id_rx; + u8 wsm_rx_seq; + u8 wsm_tx_seq; + int hw_bufs_used; + bool powersave_enabled; + bool device_can_sleep; + + /* Scan status */ + struct cw1200_scan scan; + /* Keep cw1200 awake (WUP = 1) 1 second after each scan to avoid + * FW issue with sleeping/waking up. */ + atomic_t recent_scan; + struct delayed_work clear_recent_scan_work; + + /* WSM */ + struct wsm_startup_ind wsm_caps; + struct mutex wsm_cmd_mux; + struct wsm_buf wsm_cmd_buf; + struct wsm_cmd wsm_cmd; + wait_queue_head_t wsm_cmd_wq; + wait_queue_head_t wsm_startup_done; + int firmware_ready; + atomic_t tx_lock; + + /* WSM debug */ + int wsm_enable_wsm_dumps; + + /* WSM Join */ + enum cw1200_join_status join_status; + u32 pending_frame_id; + bool join_pending; + struct delayed_work join_timeout; + struct work_struct unjoin_work; + struct work_struct join_complete_work; + int join_complete_status; + int join_dtim_period; + bool delayed_unjoin; + + /* TX/RX and security */ + s8 wep_default_key_id; + struct work_struct wep_key_work; + u32 key_map; + struct wsm_add_key keys[WSM_KEY_MAX_INDEX + 1]; + + /* AP powersave */ + u32 link_id_map; + struct cw1200_link_entry link_id_db[CW1200_MAX_STA_IN_AP_MODE]; + struct work_struct link_id_work; + struct delayed_work link_id_gc_work; + u32 sta_asleep_mask; + u32 pspoll_mask; + bool aid0_bit_set; + spinlock_t ps_state_lock; /* Protect power save state */ + bool buffered_multicasts; + bool tx_multicast; + struct work_struct set_tim_work; + struct work_struct set_cts_work; + struct work_struct multicast_start_work; + struct work_struct multicast_stop_work; + struct timer_list mcast_timeout; + + /* WSM events and CQM implementation */ + spinlock_t event_queue_lock; /* Protect event queue */ + struct list_head event_queue; + struct work_struct event_handler; + + struct delayed_work bss_loss_work; + spinlock_t bss_loss_lock; /* Protect BSS loss state */ + int bss_loss_state; + int bss_loss_confirm_id; + int delayed_link_loss; + struct work_struct bss_params_work; + + /* TX rate policy cache */ + struct tx_policy_cache tx_policy_cache; + struct work_struct tx_policy_upload_work; + + /* legacy PS mode switch in suspend */ + int ps_mode_switch_in_progress; + wait_queue_head_t ps_mode_switch_done; + + /* Workaround for WFD testcase 6.1.10*/ + struct work_struct linkid_reset_work; + u8 action_frame_sa[ETH_ALEN]; + u8 action_linkid; + +#ifdef CONFIG_CW1200_ETF + struct sk_buff_head etf_q; +#endif +}; + +struct cw1200_sta_priv { + int link_id; +}; + +/* interfaces for the drivers */ +int cw1200_core_probe(const struct sbus_ops *sbus_ops, + struct sbus_priv *sbus, + struct device *pdev, + struct cw1200_common **pself, + int ref_clk, const u8 *macaddr, + const char *sdd_path, bool have_5ghz); +void cw1200_core_release(struct cw1200_common *self); + +#define FWLOAD_BLOCK_SIZE (1024) + +static inline int cw1200_is_ht(const struct cw1200_ht_info *ht_info) +{ + return ht_info->channel_type != NL80211_CHAN_NO_HT; +} + +static inline int cw1200_ht_greenfield(const struct cw1200_ht_info *ht_info) +{ + return cw1200_is_ht(ht_info) && + (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && + !(ht_info->operation_mode & + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); +} + +static inline int cw1200_ht_ampdu_density(const struct cw1200_ht_info *ht_info) +{ + if (!cw1200_is_ht(ht_info)) + return 0; + return ht_info->ht_cap.ampdu_density; +} + +#endif /* CW1200_H */ diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c new file mode 100644 index 000000000000..a5ada0eda1dd --- /dev/null +++ b/drivers/net/wireless/cw1200/cw1200_sagrad.c @@ -0,0 +1,145 @@ +/* + * Platform glue data for ST-Ericsson CW1200 driver + * + * Copyright (c) 2013, Sagrad, Inc + * Author: Solomon Peachy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +MODULE_AUTHOR("Solomon Peachy "); +MODULE_DESCRIPTION("ST-Ericsson CW1200 Platform glue driver"); +MODULE_LICENSE("GPL"); + +/* Define just one of these. Feel free to customize as needed */ +#define SAGRAD_1091_1098_EVK_SDIO +/* #define SAGRAD_1091_1098_EVK_SPI */ + +#ifdef SAGRAD_1091_1098_EVK_SDIO +#if 0 +static struct resource cw1200_href_resources[] = { + { + .start = 215, /* fix me as appropriate */ + .end = 215, /* ditto */ + .flags = IORESOURCE_IO, + .name = "cw1200_wlan_reset", + }, + { + .start = 216, /* fix me as appropriate */ + .end = 216, /* ditto */ + .flags = IORESOURCE_IO, + .name = "cw1200_wlan_powerup", + }, + { + .start = NOMADIK_GPIO_TO_IRQ(216), /* fix me as appropriate */ + .end = NOMADIK_GPIO_TO_IRQ(216), /* ditto */ + .flags = IORESOURCE_IRQ, + .name = "cw1200_wlan_irq", + }, +}; +#endif + +static int cw1200_power_ctrl(const struct cw1200_platform_data_sdio *pdata, + bool enable) +{ + /* Control 3v3 and 1v8 to hardware as appropriate */ + /* Note this is not needed if it's controlled elsewhere or always on */ + + /* May require delay for power to stabilize */ + return 0; +} + +static int cw1200_clk_ctrl(const struct cw1200_platform_data_sdio *pdata, + bool enable) +{ + /* Turn CLK_32K off and on as appropriate. */ + /* Note this is not needed if it's always on */ + + /* May require delay for clock to stabilize */ + return 0; +} + +static struct cw1200_platform_data_sdio cw1200_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, +#if 0 + .reset = &cw1200_href_resources[0], + .powerup = &cw1200_href_resources[1], + .irq = &cw1200_href_resources[2], +#endif + .power_ctrl = cw1200_power_ctrl, + .clk_ctrl = cw1200_clk_ctrl, +/* .macaddr = ??? */ + .sdd_file = "sdd_sagrad_1091_1098.bin", +}; +#endif + +#ifdef SAGRAD_1091_1098_EVK_SPI +/* Note that this is an example of integrating into your board support file */ +static struct resource cw1200_href_resources[] = { + { + .start = GPIO_RF_RESET, + .end = GPIO_RF_RESET, + .flags = IORESOURCE_IO, + .name = "cw1200_wlan_reset", + }, + { + .start = GPIO_RF_POWERUP, + .end = GPIO_RF_POWERUP, + .flags = IORESOURCE_IO, + .name = "cw1200_wlan_powerup", + }, +}; + +static int cw1200_power_ctrl(const struct cw1200_platform_data_spi *pdata, + bool enable) +{ + /* Control 3v3 and 1v8 to hardware as appropriate */ + /* Note this is not needed if it's controlled elsewhere or always on */ + + /* May require delay for power to stabilize */ + return 0; +} +static int cw1200_clk_ctrl(const struct cw1200_platform_data_spi *pdata, + bool enable) +{ + /* Turn CLK_32K off and on as appropriate. */ + /* Note this is not needed if it's always on */ + + /* May require delay for clock to stabilize */ + return 0; +} + +static struct cw1200_platform_data_spi cw1200_platform_data = { + .ref_clk = 38400, + .spi_bits_per_word = 16, + .reset = &cw1200_href_resources[0], + .powerup = &cw1200_href_resources[1], + .power_ctrl = cw1200_power_ctrl, + .clk_ctrl = cw1200_clk_ctrl, +/* .macaddr = ??? */ + .sdd_file = "sdd_sagrad_1091_1098.bin", +}; +static struct spi_board_info myboard_spi_devices[] __initdata = { + { + .modalias = "cw1200_wlan_spi", + .max_speed_hz = 10000000, /* 52MHz Max */ + .bus_num = 0, + .irq = WIFI_IRQ, + .platform_data = &cw1200_platform_data, + .chip_select = 0, + }, +}; +#endif + + +const void *cw1200_get_platform_data(void) +{ + return &cw1200_platform_data; +} +EXPORT_SYMBOL_GPL(cw1200_get_platform_data); diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c new file mode 100644 index 000000000000..f6e22192d80a --- /dev/null +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -0,0 +1,409 @@ +/* + * Mac80211 SDIO driver for ST-Ericsson CW1200 device + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cw1200.h" +#include "sbus.h" +#include +#include "hwio.h" + +MODULE_AUTHOR("Dmitry Tarnyagin "); +MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SDIO driver"); +MODULE_LICENSE("GPL"); + +#define SDIO_BLOCK_SIZE (512) + +struct sbus_priv { + struct sdio_func *func; + struct cw1200_common *core; + const struct cw1200_platform_data_sdio *pdata; +}; + +#ifndef SDIO_VENDOR_ID_STE +#define SDIO_VENDOR_ID_STE 0x0020 +#endif + +#ifndef SDIO_DEVICE_ID_STE_CW1200 +#define SDIO_DEVICE_ID_STE_CW1200 0x2280 +#endif + +static const struct sdio_device_id cw1200_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) }, + { /* end: all zeroes */ }, +}; + +/* sbus_ops implemetation */ + +static int cw1200_sdio_memcpy_fromio(struct sbus_priv *self, + unsigned int addr, + void *dst, int count) +{ + return sdio_memcpy_fromio(self->func, dst, addr, count); +} + +static int cw1200_sdio_memcpy_toio(struct sbus_priv *self, + unsigned int addr, + const void *src, int count) +{ + return sdio_memcpy_toio(self->func, addr, (void *)src, count); +} + +static void cw1200_sdio_lock(struct sbus_priv *self) +{ + sdio_claim_host(self->func); +} + +static void cw1200_sdio_unlock(struct sbus_priv *self) +{ + sdio_release_host(self->func); +} + +static void cw1200_sdio_irq_handler(struct sdio_func *func) +{ + struct sbus_priv *self = sdio_get_drvdata(func); + + /* note: sdio_host already claimed here. */ + if (self->core) + cw1200_irq_handler(self->core); +} + +static irqreturn_t cw1200_gpio_hardirq(int irq, void *dev_id) +{ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) +{ + struct sbus_priv *self = dev_id; + + if (self->core) { + sdio_claim_host(self->func); + cw1200_irq_handler(self->core); + sdio_release_host(self->func); + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } +} + +static int cw1200_request_irq(struct sbus_priv *self) +{ + int ret; + const struct resource *irq = self->pdata->irq; + u8 cccr; + + cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret); + if (WARN_ON(ret)) + goto err; + + /* Master interrupt enable ... */ + cccr |= BIT(0); + + /* ... for our function */ + cccr |= BIT(self->func->num); + + sdio_f0_writeb(self->func, cccr, SDIO_CCCR_IENx, &ret); + if (WARN_ON(ret)) + goto err; + + ret = enable_irq_wake(irq->start); + if (WARN_ON(ret)) + goto err; + + /* Request the IRQ */ + ret = request_threaded_irq(irq->start, cw1200_gpio_hardirq, + cw1200_gpio_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irq->name, self); + if (WARN_ON(ret)) + goto err; + + return 0; + +err: + return ret; +} + +static int cw1200_sdio_irq_subscribe(struct sbus_priv *self) +{ + int ret = 0; + + pr_debug("SW IRQ subscribe\n"); + sdio_claim_host(self->func); + if (self->pdata->irq) + ret = cw1200_request_irq(self); + else + ret = sdio_claim_irq(self->func, cw1200_sdio_irq_handler); + + sdio_release_host(self->func); + return ret; +} + +static int cw1200_sdio_irq_unsubscribe(struct sbus_priv *self) +{ + int ret = 0; + + pr_debug("SW IRQ unsubscribe\n"); + + if (self->pdata->irq) { + disable_irq_wake(self->pdata->irq->start); + free_irq(self->pdata->irq->start, self); + } else { + sdio_claim_host(self->func); + ret = sdio_release_irq(self->func); + sdio_release_host(self->func); + } + return ret; +} + +static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) +{ + const struct resource *reset = pdata->reset; + + if (reset) { + gpio_set_value(reset->start, 0); + msleep(30); /* Min is 2 * CLK32K cycles */ + gpio_free(reset->start); + } + + if (pdata->power_ctrl) + pdata->power_ctrl(pdata, false); + if (pdata->clk_ctrl) + pdata->clk_ctrl(pdata, false); + + return 0; +} + +static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) +{ + const struct resource *reset = pdata->reset; + const struct resource *powerup = pdata->reset; + + /* Ensure I/Os are pulled low */ + if (reset) { + gpio_request(reset->start, reset->name); + gpio_direction_output(reset->start, 0); + } + if (powerup) { + gpio_request(powerup->start, powerup->name); + gpio_direction_output(powerup->start, 0); + } + if (reset || powerup) + msleep(50); /* Settle time */ + + /* Enable 3v3 and 1v8 to hardware */ + if (pdata->power_ctrl) { + if (pdata->power_ctrl(pdata, true)) { + pr_err("power_ctrl() failed!\n"); + return -1; + } + } + + /* Enable CLK32K */ + if (pdata->clk_ctrl) { + if (pdata->clk_ctrl(pdata, true)) { + pr_err("clk_ctrl() failed!\n"); + return -1; + } + msleep(10); /* Delay until clock is stable for 2 cycles */ + } + + /* Enable POWERUP signal */ + if (powerup) { + gpio_set_value(powerup->start, 1); + msleep(250); /* or more..? */ + } + /* Enable RSTn signal */ + if (reset) { + gpio_set_value(reset->start, 1); + msleep(50); /* Or more..? */ + } + return 0; +} + +static size_t cw1200_sdio_align_size(struct sbus_priv *self, size_t size) +{ + if (self->pdata->no_nptb) + size = round_up(size, SDIO_BLOCK_SIZE); + else + size = sdio_align_size(self->func, size); + + return size; +} + +static int cw1200_sdio_pm(struct sbus_priv *self, bool suspend) +{ + int ret = 0; + + if (self->pdata->irq) + ret = irq_set_irq_wake(self->pdata->irq->start, suspend); + return ret; +} + +static struct sbus_ops cw1200_sdio_sbus_ops = { + .sbus_memcpy_fromio = cw1200_sdio_memcpy_fromio, + .sbus_memcpy_toio = cw1200_sdio_memcpy_toio, + .lock = cw1200_sdio_lock, + .unlock = cw1200_sdio_unlock, + .align_size = cw1200_sdio_align_size, + .power_mgmt = cw1200_sdio_pm, +}; + +/* Probe Function to be called by SDIO stack when device is discovered */ +static int cw1200_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + struct sbus_priv *self; + int status; + + pr_info("cw1200_wlan_sdio: Probe called\n"); + + /* We are only able to handle the wlan function */ + if (func->num != 0x01) + return -ENODEV; + + self = kzalloc(sizeof(*self), GFP_KERNEL); + if (!self) { + pr_err("Can't allocate SDIO sbus_priv.\n"); + return -ENOMEM; + } + + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + + self->pdata = cw1200_get_platform_data(); + self->func = func; + sdio_set_drvdata(func, self); + sdio_claim_host(func); + sdio_enable_func(func); + sdio_release_host(func); + + status = cw1200_sdio_irq_subscribe(self); + + status = cw1200_core_probe(&cw1200_sdio_sbus_ops, + self, &func->dev, &self->core, + self->pdata->ref_clk, + self->pdata->macaddr, + self->pdata->sdd_file, + self->pdata->have_5ghz); + if (status) { + cw1200_sdio_irq_unsubscribe(self); + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + sdio_set_drvdata(func, NULL); + kfree(self); + } + + return status; +} + +/* Disconnect Function to be called by SDIO stack when + * device is disconnected */ +static void cw1200_sdio_disconnect(struct sdio_func *func) +{ + struct sbus_priv *self = sdio_get_drvdata(func); + + if (self) { + cw1200_sdio_irq_unsubscribe(self); + if (self->core) { + cw1200_core_release(self->core); + self->core = NULL; + } + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + sdio_set_drvdata(func, NULL); + kfree(self); + } +} + +static int cw1200_sdio_suspend(struct device *dev) +{ + int ret; + struct sdio_func *func = dev_to_sdio_func(dev); + struct sbus_priv *self = sdio_get_drvdata(func); + + if (!cw1200_can_suspend(self->core)) + return -EAGAIN; + + /* Notify SDIO that CW1200 will remain powered during suspend */ + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) + pr_err("Error setting SDIO pm flags: %i\n", ret); + + return ret; +} + +static int cw1200_sdio_resume(struct device *dev) +{ + return 0; +} + +static const struct dev_pm_ops cw1200_pm_ops = { + .suspend = cw1200_sdio_suspend, + .resume = cw1200_sdio_resume, +}; + +static struct sdio_driver sdio_driver = { + .name = "cw1200_wlan_sdio", + .id_table = cw1200_sdio_ids, + .probe = cw1200_sdio_probe, + .remove = cw1200_sdio_disconnect, + .drv = { + .pm = &cw1200_pm_ops, + } +}; + +/* Init Module function -> Called by insmod */ +static int __init cw1200_sdio_init(void) +{ + const struct cw1200_platform_data_sdio *pdata; + int ret; + + pdata = cw1200_get_platform_data(); + + if (cw1200_sdio_on(pdata)) { + ret = -1; + goto err; + } + + ret = sdio_register_driver(&sdio_driver); + if (ret) + goto err; + + return 0; + +err: + cw1200_sdio_off(pdata); + return ret; +} + +/* Called at Driver Unloading */ +static void __exit cw1200_sdio_exit(void) +{ + const struct cw1200_platform_data_sdio *pdata; + pdata = cw1200_get_platform_data(); + sdio_unregister_driver(&sdio_driver); + cw1200_sdio_off(pdata); +} + + +module_init(cw1200_sdio_init); +module_exit(cw1200_sdio_exit); diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c new file mode 100644 index 000000000000..04af68534854 --- /dev/null +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -0,0 +1,480 @@ +/* + * Mac80211 SPI driver for ST-Ericsson CW1200 device + * + * Copyright (c) 2011, Sagrad Inc. + * Author: Solomon Peachy + * + * Based on cw1200_sdio.c + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cw1200.h" +#include "sbus.h" +#include +#include "hwio.h" + +MODULE_AUTHOR("Solomon Peachy "); +MODULE_DESCRIPTION("mac80211 ST-Ericsson CW1200 SPI driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:cw1200_wlan_spi"); + +/* #define SPI_DEBUG */ + +struct sbus_priv { + struct spi_device *func; + struct cw1200_common *core; + const struct cw1200_platform_data_spi *pdata; + spinlock_t lock; /* Serialize all bus operations */ + int claimed; +}; + +#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2) +#define SET_WRITE 0x7FFF /* usage: and operation */ +#define SET_READ 0x8000 /* usage: or operation */ + +/* + Notes on byte ordering: + LE: B0 B1 B2 B3 + BE: B3 B2 B1 B0 + + Hardware expects 32-bit data to be written as 16-bit BE words: + + B1 B0 B3 B2 + +*/ + +static int cw1200_spi_memcpy_fromio(struct sbus_priv *self, + unsigned int addr, + void *dst, int count) +{ + int ret, i; + uint16_t regaddr; + struct spi_message m; + + struct spi_transfer t_addr = { + .tx_buf = ®addr, + .len = sizeof(regaddr), + }; + struct spi_transfer t_msg = { + .rx_buf = dst, + .len = count, + }; + + regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; + regaddr |= SET_READ; + regaddr |= (count>>1); + regaddr = cpu_to_le16(regaddr); + +#ifdef SPI_DEBUG + pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, + le16_to_cpu(regaddr)); +#endif + +#if defined(__LITTLE_ENDIAN) + /* We have to byteswap if the SPI bus is limited to 8b operation */ + if (self->func->bits_per_word == 8) +#endif + regaddr = swab16(regaddr); + + spi_message_init(&m); + spi_message_add_tail(&t_addr, &m); + spi_message_add_tail(&t_msg, &m); + ret = spi_sync(self->func, &m); + +#ifdef SPI_DEBUG + pr_info("READ : "); + for (i = 0; i < t_addr.len; i++) + printk("%02x ", ((u8 *)t_addr.tx_buf)[i]); + printk(" : "); + for (i = 0; i < t_msg.len; i++) + printk("%02x ", ((u8 *)t_msg.rx_buf)[i]); + printk("\n"); +#endif + +#if defined(__LITTLE_ENDIAN) + /* We have to byteswap if the SPI bus is limited to 8b operation */ + if (self->func->bits_per_word == 8) +#endif + { + uint16_t *buf = (uint16_t *)dst; + for (i = 0; i < ((count + 1) >> 1); i++) + buf[i] = swab16(buf[i]); + } + + return ret; +} + +static int cw1200_spi_memcpy_toio(struct sbus_priv *self, + unsigned int addr, + const void *src, int count) +{ + int rval, i; + uint16_t regaddr; + struct spi_transfer t_addr = { + .tx_buf = ®addr, + .len = sizeof(regaddr), + }; + struct spi_transfer t_msg = { + .tx_buf = src, + .len = count, + }; + struct spi_message m; + + regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; + regaddr &= SET_WRITE; + regaddr |= (count>>1); + regaddr = cpu_to_le16(regaddr); + +#ifdef SPI_DEBUG + pr_info("WRITE: %04d to 0x%02x (%04x)\n", count, addr, + le16_to_cpu(regaddr)); +#endif + +#if defined(__LITTLE_ENDIAN) + /* We have to byteswap if the SPI bus is limited to 8b operation */ + if (self->func->bits_per_word == 8) +#endif + { + uint16_t *buf = (uint16_t *)src; + regaddr = swab16(regaddr); + for (i = 0; i < ((count + 1) >> 1); i++) + buf[i] = swab16(buf[i]); + } + +#ifdef SPI_DEBUG + pr_info("WRITE: "); + for (i = 0; i < t_addr.len; i++) + printk("%02x ", ((u8 *)t_addr.tx_buf)[i]); + printk(" : "); + for (i = 0; i < t_msg.len; i++) + printk("%02x ", ((u8 *)t_msg.tx_buf)[i]); + printk("\n"); +#endif + + spi_message_init(&m); + spi_message_add_tail(&t_addr, &m); + spi_message_add_tail(&t_msg, &m); + rval = spi_sync(self->func, &m); + +#ifdef SPI_DEBUG + pr_info("WROTE: %d\n", m.actual_length); +#endif + +#if defined(__LITTLE_ENDIAN) + /* We have to byteswap if the SPI bus is limited to 8b operation */ + if (self->func->bits_per_word == 8) +#endif + { + uint16_t *buf = (uint16_t *)src; + for (i = 0; i < ((count + 1) >> 1); i++) + buf[i] = swab16(buf[i]); + } + return rval; +} + +static void cw1200_spi_lock(struct sbus_priv *self) +{ + unsigned long flags; + + might_sleep(); + + spin_lock_irqsave(&self->lock, flags); + while (1) { + set_current_state(TASK_UNINTERRUPTIBLE); + if (!self->claimed) + break; + spin_unlock_irqrestore(&self->lock, flags); + schedule(); + spin_lock_irqsave(&self->lock, flags); + } + set_current_state(TASK_RUNNING); + self->claimed = 1; + spin_unlock_irqrestore(&self->lock, flags); + + return; +} + +static void cw1200_spi_unlock(struct sbus_priv *self) +{ + unsigned long flags; + + spin_lock_irqsave(&self->lock, flags); + self->claimed = 0; + spin_unlock_irqrestore(&self->lock, flags); + return; +} + +static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id) +{ + struct sbus_priv *self = dev_id; + + if (self->core) { + cw1200_irq_handler(self->core); + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } +} + +static int cw1200_spi_irq_subscribe(struct sbus_priv *self) +{ + int ret; + + pr_debug("SW IRQ subscribe\n"); + + ret = request_any_context_irq(self->func->irq, cw1200_spi_irq_handler, + IRQF_TRIGGER_HIGH, + "cw1200_wlan_irq", self); + if (WARN_ON(ret < 0)) + goto exit; + + ret = enable_irq_wake(self->func->irq); + if (WARN_ON(ret)) + goto free_irq; + + return 0; + +free_irq: + free_irq(self->func->irq, self); +exit: + return ret; +} + +static int cw1200_spi_irq_unsubscribe(struct sbus_priv *self) +{ + int ret = 0; + + pr_debug("SW IRQ unsubscribe\n"); + disable_irq_wake(self->func->irq); + free_irq(self->func->irq, self); + + return ret; +} + +static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) +{ + const struct resource *reset = pdata->reset; + + if (reset) { + gpio_set_value(reset->start, 0); + msleep(30); /* Min is 2 * CLK32K cycles */ + gpio_free(reset->start); + } + + if (pdata->power_ctrl) + pdata->power_ctrl(pdata, false); + if (pdata->clk_ctrl) + pdata->clk_ctrl(pdata, false); + + return 0; +} + +static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) +{ + const struct resource *reset = pdata->reset; + const struct resource *powerup = pdata->reset; + + /* Ensure I/Os are pulled low */ + if (reset) { + gpio_request(reset->start, reset->name); + gpio_direction_output(reset->start, 0); + } + if (powerup) { + gpio_request(powerup->start, powerup->name); + gpio_direction_output(powerup->start, 0); + } + if (reset || powerup) + msleep(10); /* Settle time? */ + + /* Enable 3v3 and 1v8 to hardware */ + if (pdata->power_ctrl) { + if (pdata->power_ctrl(pdata, true)) { + pr_err("power_ctrl() failed!\n"); + return -1; + } + } + + /* Enable CLK32K */ + if (pdata->clk_ctrl) { + if (pdata->clk_ctrl(pdata, true)) { + pr_err("clk_ctrl() failed!\n"); + return -1; + } + msleep(10); /* Delay until clock is stable for 2 cycles */ + } + + /* Enable POWERUP signal */ + if (powerup) { + gpio_set_value(powerup->start, 1); + msleep(250); /* or more..? */ + } + /* Enable RSTn signal */ + if (reset) { + gpio_set_value(reset->start, 1); + msleep(50); /* Or more..? */ + } + return 0; +} + +static size_t cw1200_spi_align_size(struct sbus_priv *self, size_t size) +{ + return size & 1 ? size + 1 : size; +} + +static int cw1200_spi_pm(struct sbus_priv *self, bool suspend) +{ + return irq_set_irq_wake(self->func->irq, suspend); +} + +static struct sbus_ops cw1200_spi_sbus_ops = { + .sbus_memcpy_fromio = cw1200_spi_memcpy_fromio, + .sbus_memcpy_toio = cw1200_spi_memcpy_toio, + .lock = cw1200_spi_lock, + .unlock = cw1200_spi_unlock, + .align_size = cw1200_spi_align_size, + .power_mgmt = cw1200_spi_pm, +}; + +/* Probe Function to be called by SPI stack when device is discovered */ +static int cw1200_spi_probe(struct spi_device *func) +{ + const struct cw1200_platform_data_spi *plat_data = + func->dev.platform_data; + struct sbus_priv *self; + int status; + + /* Sanity check speed */ + if (func->max_speed_hz > 52000000) + func->max_speed_hz = 52000000; + if (func->max_speed_hz < 1000000) + func->max_speed_hz = 1000000; + + /* Fix up transfer size */ + if (plat_data->spi_bits_per_word) + func->bits_per_word = plat_data->spi_bits_per_word; + if (!func->bits_per_word) + func->bits_per_word = 16; + + /* And finally.. */ + func->mode = SPI_MODE_0; + + pr_info("cw1200_wlan_spi: Probe called (CS %d M %d BPW %d CLK %d)\n", + func->chip_select, func->mode, func->bits_per_word, + func->max_speed_hz); + + if (cw1200_spi_on(plat_data)) { + pr_err("spi_on() failed!\n"); + return -1; + } + + if (spi_setup(func)) { + pr_err("spi_setup() failed!\n"); + return -1; + } + + self = kzalloc(sizeof(*self), GFP_KERNEL); + if (!self) { + pr_err("Can't allocate SPI sbus_priv."); + return -ENOMEM; + } + + self->pdata = plat_data; + self->func = func; + spin_lock_init(&self->lock); + + spi_set_drvdata(func, self); + + status = cw1200_spi_irq_subscribe(self); + + status = cw1200_core_probe(&cw1200_spi_sbus_ops, + self, &func->dev, &self->core, + self->pdata->ref_clk, + self->pdata->macaddr, + self->pdata->sdd_file, + self->pdata->have_5ghz); + + if (status) { + cw1200_spi_irq_unsubscribe(self); + cw1200_spi_off(plat_data); + kfree(self); + } + + return status; +} + +/* Disconnect Function to be called by SPI stack when device is disconnected */ +static int cw1200_spi_disconnect(struct spi_device *func) +{ + struct sbus_priv *self = spi_get_drvdata(func); + + if (self) { + cw1200_spi_irq_unsubscribe(self); + if (self->core) { + cw1200_core_release(self->core); + self->core = NULL; + } + kfree(self); + } + cw1200_spi_off(func->dev.platform_data); + + return 0; +} + +static int cw1200_spi_suspend(struct device *dev, pm_message_t state) +{ + struct sbus_priv *self = spi_get_drvdata(to_spi_device(dev)); + + if (!cw1200_can_suspend(self->core)) + return -EAGAIN; + + /* XXX notify host that we have to keep CW1200 powered on? */ + return 0; +} + +static int cw1200_spi_resume(struct device *dev) +{ + return 0; +} + +static struct spi_driver spi_driver = { + .probe = cw1200_spi_probe, + .remove = cw1200_spi_disconnect, + .driver = { + .name = "cw1200_wlan_spi", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .suspend = cw1200_spi_suspend, + .resume = cw1200_spi_resume, + }, +}; + +/* Init Module function -> Called by insmod */ +static int __init cw1200_spi_init(void) +{ + return spi_register_driver(&spi_driver); +} + +/* Called at Driver Unloading */ +static void __exit cw1200_spi_exit(void) +{ + spi_unregister_driver(&spi_driver); +} + +module_init(cw1200_spi_init); +module_exit(cw1200_spi_exit); diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c new file mode 100644 index 000000000000..b815181802e0 --- /dev/null +++ b/drivers/net/wireless/cw1200/debug.c @@ -0,0 +1,664 @@ +/* + * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers + * DebugFS code + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "cw1200.h" +#include "debug.h" +#include "fwio.h" + +/* join_status */ +static const char * const cw1200_debug_join_status[] = { + "passive", + "monitor", + "station (joining)", + "station (not authenticated yet)", + "station", + "adhoc", + "access point", +}; + +/* WSM_JOIN_PREAMBLE_... */ +static const char * const cw1200_debug_preamble[] = { + "long", + "short", + "long on 1 and 2 Mbps", +}; + + +static const char * const cw1200_debug_link_id[] = { + "OFF", + "REQ", + "SOFT", + "HARD", +}; + +static const char *cw1200_debug_mode(int mode) +{ + switch (mode) { + case NL80211_IFTYPE_UNSPECIFIED: + return "unspecified"; + case NL80211_IFTYPE_MONITOR: + return "monitor"; + case NL80211_IFTYPE_STATION: + return "station"; + case NL80211_IFTYPE_ADHOC: + return "adhoc"; + case NL80211_IFTYPE_MESH_POINT: + return "mesh point"; + case NL80211_IFTYPE_AP: + return "access point"; + case NL80211_IFTYPE_P2P_CLIENT: + return "p2p client"; + case NL80211_IFTYPE_P2P_GO: + return "p2p go"; + default: + return "unsupported"; + } +} + +static void cw1200_queue_status_show(struct seq_file *seq, + struct cw1200_queue *q) +{ + int i; + seq_printf(seq, "Queue %d:\n", q->queue_id); + seq_printf(seq, " capacity: %zu\n", q->capacity); + seq_printf(seq, " queued: %zu\n", q->num_queued); + seq_printf(seq, " pending: %zu\n", q->num_pending); + seq_printf(seq, " sent: %zu\n", q->num_sent); + seq_printf(seq, " locked: %s\n", q->tx_locked_cnt ? "yes" : "no"); + seq_printf(seq, " overfull: %s\n", q->overfull ? "yes" : "no"); + seq_puts(seq, " link map: 0-> "); + for (i = 0; i < q->stats->map_capacity; ++i) + seq_printf(seq, "%.2d ", q->link_map_cache[i]); + seq_printf(seq, "<-%zu\n", q->stats->map_capacity); +} + +static void cw1200_debug_print_map(struct seq_file *seq, + struct cw1200_common *priv, + const char *label, + u32 map) +{ + int i; + seq_printf(seq, "%s0-> ", label); + for (i = 0; i < priv->tx_queue_stats.map_capacity; ++i) + seq_printf(seq, "%s ", (map & BIT(i)) ? "**" : ".."); + seq_printf(seq, "<-%zu\n", priv->tx_queue_stats.map_capacity - 1); +} + +static int cw1200_status_show(struct seq_file *seq, void *v) +{ + int i; + struct list_head *item; + struct cw1200_common *priv = seq->private; + struct cw1200_debug_priv *d = priv->debug; + + seq_puts(seq, "CW1200 Wireless LAN driver status\n"); + seq_printf(seq, "Hardware: %d.%d\n", + priv->wsm_caps.hw_id, + priv->wsm_caps.hw_subid); + seq_printf(seq, "Firmware: %s %d.%d\n", + cw1200_fw_types[priv->wsm_caps.fw_type], + priv->wsm_caps.fw_ver, + priv->wsm_caps.fw_build); + seq_printf(seq, "FW API: %d\n", + priv->wsm_caps.fw_api); + seq_printf(seq, "FW caps: 0x%.4X\n", + priv->wsm_caps.fw_cap); + seq_printf(seq, "FW label: '%s'\n", + priv->wsm_caps.fw_label); + seq_printf(seq, "Mode: %s%s\n", + cw1200_debug_mode(priv->mode), + priv->listening ? " (listening)" : ""); + seq_printf(seq, "Join state: %s\n", + cw1200_debug_join_status[priv->join_status]); + if (priv->channel) + seq_printf(seq, "Channel: %d%s\n", + priv->channel->hw_value, + priv->channel_switch_in_progress ? + " (switching)" : ""); + if (priv->rx_filter.promiscuous) + seq_puts(seq, "Filter: promisc\n"); + else if (priv->rx_filter.fcs) + seq_puts(seq, "Filter: fcs\n"); + if (priv->rx_filter.bssid) + seq_puts(seq, "Filter: bssid\n"); + if (!priv->disable_beacon_filter) + seq_puts(seq, "Filter: beacons\n"); + + if (priv->enable_beacon || + priv->mode == NL80211_IFTYPE_AP || + priv->mode == NL80211_IFTYPE_ADHOC || + priv->mode == NL80211_IFTYPE_MESH_POINT || + priv->mode == NL80211_IFTYPE_P2P_GO) + seq_printf(seq, "Beaconing: %s\n", + priv->enable_beacon ? + "enabled" : "disabled"); + + for (i = 0; i < 4; ++i) + seq_printf(seq, "EDCA(%d): %d, %d, %d, %d, %d\n", i, + priv->edca.params[i].cwmin, + priv->edca.params[i].cwmax, + priv->edca.params[i].aifns, + priv->edca.params[i].txop_limit, + priv->edca.params[i].max_rx_lifetime); + + if (priv->join_status == CW1200_JOIN_STATUS_STA) { + static const char *pm_mode = "unknown"; + switch (priv->powersave_mode.mode) { + case WSM_PSM_ACTIVE: + pm_mode = "off"; + break; + case WSM_PSM_PS: + pm_mode = "on"; + break; + case WSM_PSM_FAST_PS: + pm_mode = "dynamic"; + break; + } + seq_printf(seq, "Preamble: %s\n", + cw1200_debug_preamble[priv->association_mode.preamble]); + seq_printf(seq, "AMPDU spcn: %d\n", + priv->association_mode.mpdu_start_spacing); + seq_printf(seq, "Basic rate: 0x%.8X\n", + le32_to_cpu(priv->association_mode.basic_rate_set)); + seq_printf(seq, "Bss lost: %d beacons\n", + priv->bss_params.beacon_lost_count); + seq_printf(seq, "AID: %d\n", + priv->bss_params.aid); + seq_printf(seq, "Rates: 0x%.8X\n", + priv->bss_params.operational_rate_set); + seq_printf(seq, "Powersave: %s\n", pm_mode); + } + seq_printf(seq, "HT: %s\n", + cw1200_is_ht(&priv->ht_info) ? "on" : "off"); + if (cw1200_is_ht(&priv->ht_info)) { + seq_printf(seq, "Greenfield: %s\n", + cw1200_ht_greenfield(&priv->ht_info) ? "yes" : "no"); + seq_printf(seq, "AMPDU dens: %d\n", + cw1200_ht_ampdu_density(&priv->ht_info)); + } + seq_printf(seq, "RSSI thold: %d\n", + priv->cqm_rssi_thold); + seq_printf(seq, "RSSI hyst: %d\n", + priv->cqm_rssi_hyst); + seq_printf(seq, "Long retr: %d\n", + priv->long_frame_max_tx_count); + seq_printf(seq, "Short retr: %d\n", + priv->short_frame_max_tx_count); + spin_lock_bh(&priv->tx_policy_cache.lock); + i = 0; + list_for_each(item, &priv->tx_policy_cache.used) + ++i; + spin_unlock_bh(&priv->tx_policy_cache.lock); + seq_printf(seq, "RC in use: %d\n", i); + + seq_puts(seq, "\n"); + for (i = 0; i < 4; ++i) { + cw1200_queue_status_show(seq, &priv->tx_queue[i]); + seq_puts(seq, "\n"); + } + + cw1200_debug_print_map(seq, priv, "Link map: ", + priv->link_id_map); + cw1200_debug_print_map(seq, priv, "Asleep map: ", + priv->sta_asleep_mask); + cw1200_debug_print_map(seq, priv, "PSPOLL map: ", + priv->pspoll_mask); + + seq_puts(seq, "\n"); + + for (i = 0; i < CW1200_MAX_STA_IN_AP_MODE; ++i) { + if (priv->link_id_db[i].status) { + seq_printf(seq, "Link %d: %s, %pM\n", + i + 1, + cw1200_debug_link_id[priv->link_id_db[i].status], + priv->link_id_db[i].mac); + } + } + + seq_puts(seq, "\n"); + + seq_printf(seq, "BH status: %s\n", + atomic_read(&priv->bh_term) ? "terminated" : "alive"); + seq_printf(seq, "Pending RX: %d\n", + atomic_read(&priv->bh_rx)); + seq_printf(seq, "Pending TX: %d\n", + atomic_read(&priv->bh_tx)); + if (priv->bh_error) + seq_printf(seq, "BH errcode: %d\n", + priv->bh_error); + seq_printf(seq, "TX bufs: %d x %d bytes\n", + priv->wsm_caps.input_buffers, + priv->wsm_caps.input_buffer_size); + seq_printf(seq, "Used bufs: %d\n", + priv->hw_bufs_used); + seq_printf(seq, "Powermgmt: %s\n", + priv->powersave_enabled ? "on" : "off"); + seq_printf(seq, "Device: %s\n", + priv->device_can_sleep ? "asleep" : "awake"); + + spin_lock(&priv->wsm_cmd.lock); + seq_printf(seq, "WSM status: %s\n", + priv->wsm_cmd.done ? "idle" : "active"); + seq_printf(seq, "WSM cmd: 0x%.4X (%td bytes)\n", + priv->wsm_cmd.cmd, priv->wsm_cmd.len); + seq_printf(seq, "WSM retval: %d\n", + priv->wsm_cmd.ret); + spin_unlock(&priv->wsm_cmd.lock); + + seq_printf(seq, "Datapath: %s\n", + atomic_read(&priv->tx_lock) ? "locked" : "unlocked"); + if (atomic_read(&priv->tx_lock)) + seq_printf(seq, "TXlock cnt: %d\n", + atomic_read(&priv->tx_lock)); + + seq_printf(seq, "TXed: %d\n", + d->tx); + seq_printf(seq, "AGG TXed: %d\n", + d->tx_agg); + seq_printf(seq, "MULTI TXed: %d (%d)\n", + d->tx_multi, d->tx_multi_frames); + seq_printf(seq, "RXed: %d\n", + d->rx); + seq_printf(seq, "AGG RXed: %d\n", + d->rx_agg); + seq_printf(seq, "TX miss: %d\n", + d->tx_cache_miss); + seq_printf(seq, "TX align: %d\n", + d->tx_align); + seq_printf(seq, "TX burst: %d\n", + d->tx_burst); + seq_printf(seq, "TX TTL: %d\n", + d->tx_ttl); + seq_printf(seq, "Scan: %s\n", + atomic_read(&priv->scan.in_progress) ? "active" : "idle"); + + return 0; +} + +static int cw1200_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, &cw1200_status_show, + inode->i_private); +} + +static const struct file_operations fops_status = { + .open = cw1200_status_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int cw1200_counters_show(struct seq_file *seq, void *v) +{ + int ret; + struct cw1200_common *priv = seq->private; + struct wsm_mib_counters_table counters; + + ret = wsm_get_counters_table(priv, &counters); + if (ret) + return ret; + +#define PUT_COUNTER(tab, name) \ + seq_printf(seq, "%s:" tab "%d\n", #name, \ + __le32_to_cpu(counters.name)) + + PUT_COUNTER("\t\t", plcp_errors); + PUT_COUNTER("\t\t", fcs_errors); + PUT_COUNTER("\t\t", tx_packets); + PUT_COUNTER("\t\t", rx_packets); + PUT_COUNTER("\t\t", rx_packet_errors); + PUT_COUNTER("\t", rx_decryption_failures); + PUT_COUNTER("\t\t", rx_mic_failures); + PUT_COUNTER("\t", rx_no_key_failures); + PUT_COUNTER("\t", tx_multicast_frames); + PUT_COUNTER("\t", tx_frames_success); + PUT_COUNTER("\t", tx_frame_failures); + PUT_COUNTER("\t", tx_frames_retried); + PUT_COUNTER("\t", tx_frames_multi_retried); + PUT_COUNTER("\t", rx_frame_duplicates); + PUT_COUNTER("\t\t", rts_success); + PUT_COUNTER("\t\t", rts_failures); + PUT_COUNTER("\t\t", ack_failures); + PUT_COUNTER("\t", rx_multicast_frames); + PUT_COUNTER("\t", rx_frames_success); + PUT_COUNTER("\t", rx_cmac_icv_errors); + PUT_COUNTER("\t\t", rx_cmac_replays); + PUT_COUNTER("\t", rx_mgmt_ccmp_replays); + +#undef PUT_COUNTER + + return 0; +} + +static int cw1200_counters_open(struct inode *inode, struct file *file) +{ + return single_open(file, &cw1200_counters_show, + inode->i_private); +} + +static const struct file_operations fops_counters = { + .open = cw1200_counters_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int cw1200_generic_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#ifdef CONFIG_CW1200_ETF +static int cw1200_etf_out_show(struct seq_file *seq, void *v) +{ + struct cw1200_common *priv = seq->private; + struct sk_buff *skb; + u32 len = 0; + + skb = skb_dequeue(&priv->etf_q); + + if (skb) + len = skb->len; + + seq_write(seq, &len, sizeof(len)); + + if (skb) { + seq_write(seq, skb->data, len); + kfree_skb(skb); + } + + return 0; +} + +static int cw1200_etf_out_open(struct inode *inode, struct file *file) +{ + return single_open(file, &cw1200_etf_out_show, + inode->i_private); +} + +static const struct file_operations fops_etf_out = { + .open = cw1200_etf_out_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +struct etf_req_msg; +static int etf_request(struct cw1200_common *priv, + struct etf_req_msg *msg, u32 len); + +#define MAX_RX_SZE 2600 + +struct etf_in_state { + struct cw1200_common *priv; + u32 total_len; + u8 buf[MAX_RX_SZE]; + u32 written; +}; + +static int cw1200_etf_in_open(struct inode *inode, struct file *file) +{ + struct etf_in_state *etf = kmalloc(sizeof(struct etf_in_state), + GFP_KERNEL); + + if (!etf) + return -ENOMEM; + + etf->written = 0; + etf->total_len = 0; + etf->priv = inode->i_private; + + file->private_data = etf; + + return 0; +} + +static int cw1200_etf_in_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static ssize_t cw1200_etf_in_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct etf_in_state *etf = file->private_data; + + ssize_t written = 0; + + if (!etf->total_len) { + if (count < sizeof(etf->total_len)) { + pr_err("count < sizeof(total_len)\n"); + return -EINVAL; + } + + if (copy_from_user(&etf->total_len, user_buf, + sizeof(etf->total_len))) { + pr_err("copy_from_user (len) failed\n"); + return -EFAULT; + } + + written += sizeof(etf->total_len); + count -= sizeof(etf->total_len); + } + + if (!count) + goto done; + + if (copy_from_user(etf->buf + etf->written, user_buf + written, + count)) { + pr_err("copy_from_user (payload %zu) failed\n", count); + return -EFAULT; + } + + written += count; + etf->written += count; + + if (etf->written >= etf->total_len) { + if (etf_request(etf->priv, (struct etf_req_msg *)etf->buf, + etf->total_len)) { + pr_err("etf_request failed\n"); + return -EIO; + } + } + +done: + return written; +} + +static const struct file_operations fops_etf_in = { + .open = cw1200_etf_in_open, + .release = cw1200_etf_in_release, + .write = cw1200_etf_in_write, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; +#endif /* CONFIG_CW1200_ETF */ + +static ssize_t cw1200_wsm_dumps(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct cw1200_common *priv = file->private_data; + char buf[1]; + + if (!count) + return -EINVAL; + if (copy_from_user(buf, user_buf, 1)) + return -EFAULT; + + if (buf[0] == '1') + priv->wsm_enable_wsm_dumps = 1; + else + priv->wsm_enable_wsm_dumps = 0; + + return count; +} + +static const struct file_operations fops_wsm_dumps = { + .open = cw1200_generic_open, + .write = cw1200_wsm_dumps, + .llseek = default_llseek, +}; + +int cw1200_debug_init(struct cw1200_common *priv) +{ + int ret = -ENOMEM; + struct cw1200_debug_priv *d = kzalloc(sizeof(struct cw1200_debug_priv), + GFP_KERNEL); + priv->debug = d; + if (!d) + return ret; + + d->debugfs_phy = debugfs_create_dir("cw1200", + priv->hw->wiphy->debugfsdir); + if (!d->debugfs_phy) + goto err; + + if (!debugfs_create_file("status", S_IRUSR, d->debugfs_phy, + priv, &fops_status)) + goto err; + + if (!debugfs_create_file("counters", S_IRUSR, d->debugfs_phy, + priv, &fops_counters)) + goto err; + +#ifdef CONFIG_CW1200_ETF + if (etf_mode) { + skb_queue_head_init(&priv->etf_q); + + if (!debugfs_create_file("etf_out", S_IRUSR, d->debugfs_phy, + priv, &fops_etf_out)) + goto err; + if (!debugfs_create_file("etf_in", S_IWUSR, d->debugfs_phy, + priv, &fops_etf_in)) + goto err; + } +#endif /* CONFIG_CW1200_ETF */ + + if (!debugfs_create_file("wsm_dumps", S_IWUSR, d->debugfs_phy, + priv, &fops_wsm_dumps)) + goto err; + + ret = cw1200_itp_init(priv); + if (ret) + goto err; + + return 0; + +err: + priv->debug = NULL; + debugfs_remove_recursive(d->debugfs_phy); + kfree(d); + return ret; +} + +void cw1200_debug_release(struct cw1200_common *priv) +{ + struct cw1200_debug_priv *d = priv->debug; + if (d) { + cw1200_itp_release(priv); + priv->debug = NULL; + kfree(d); + } +} + +#ifdef CONFIG_CW1200_ETF +struct cw1200_sdd { + u8 id; + u8 len; + u8 data[]; +}; + +struct etf_req_msg { + u32 id; + u32 len; + u8 data[]; +}; + +static int parse_sdd_file(struct cw1200_common *priv, u8 *data, u32 length) +{ + struct cw1200_sdd *ie; + + while (length > 0) { + ie = (struct cw1200_sdd *)data; + if (ie->id == SDD_REFERENCE_FREQUENCY_ELT_ID) { + priv->hw_refclk = cpu_to_le16(*((u16 *)ie->data)); + pr_info("Using Reference clock frequency %d KHz\n", + priv->hw_refclk); + break; + } + + length -= ie->len + sizeof(*ie); + data += ie->len + sizeof(*ie); + } + return 0; +} + +char *etf_firmware; + +#define ST90TDS_START_ADAPTER 0x09 /* Loads firmware too */ +#define ST90TDS_STOP_ADAPTER 0x0A +#define ST90TDS_CONFIG_ADAPTER 0x0E /* Send configuration params */ +#define ST90TDS_SBUS_READ 0x13 +#define ST90TDS_SBUS_WRITE 0x14 +#define ST90TDS_GET_DEVICE_OPTION 0x19 +#define ST90TDS_SET_DEVICE_OPTION 0x1A +#define ST90TDS_SEND_SDD 0x1D /* SDD File used to find DPLL */ + +#include "fwio.h" + +static int etf_request(struct cw1200_common *priv, + struct etf_req_msg *msg, + u32 len) +{ + int rval = -1; + switch (msg->id) { + case ST90TDS_START_ADAPTER: + etf_firmware = "cw1200_etf.bin"; + pr_info("ETF_START (len %d, '%s')\n", len, etf_firmware); + rval = cw1200_load_firmware(priv); + break; + case ST90TDS_STOP_ADAPTER: + pr_info("ETF_STOP (unhandled)\n"); + break; + case ST90TDS_SEND_SDD: + pr_info("ETF_SDD\n"); + rval = parse_sdd_file(priv, msg->data, msg->len); + break; + case ST90TDS_CONFIG_ADAPTER: + pr_info("ETF_CONFIG_ADAP (unhandled)\n"); + break; + case ST90TDS_SBUS_READ: + pr_info("ETF_SBUS_READ (unhandled)\n"); + break; + case ST90TDS_SBUS_WRITE: + pr_info("ETF_SBUS_WRITE (unhandled)\n"); + break; + case ST90TDS_SET_DEVICE_OPTION: + pr_info("ETF_SET_DEV_OPT (unhandled)\n"); + break; + default: + pr_info("ETF_PASSTHRU (0x%08x)\n", msg->id); + rval = wsm_raw_cmd(priv, (u8 *)msg, len); + break; + } + + return rval; +} +#endif /* CONFIG_CW1200_ETF */ diff --git a/drivers/net/wireless/cw1200/debug.h b/drivers/net/wireless/cw1200/debug.h new file mode 100644 index 000000000000..1fea5b29a819 --- /dev/null +++ b/drivers/net/wireless/cw1200/debug.h @@ -0,0 +1,98 @@ +/* + * DebugFS code for ST-Ericsson CW1200 mac80211 driver + * + * Copyright (c) 2011, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_DEBUG_H_INCLUDED +#define CW1200_DEBUG_H_INCLUDED + +#include "itp.h" + +struct cw1200_debug_priv { + struct dentry *debugfs_phy; + int tx; + int tx_agg; + int rx; + int rx_agg; + int tx_multi; + int tx_multi_frames; + int tx_cache_miss; + int tx_align; + int tx_ttl; + int tx_burst; + int ba_cnt; + int ba_acc; + int ba_cnt_rx; + int ba_acc_rx; +#ifdef CONFIG_CW1200_ITP + struct cw1200_itp itp; +#endif /* CONFIG_CW1200_ITP */ +}; + +int cw1200_debug_init(struct cw1200_common *priv); +void cw1200_debug_release(struct cw1200_common *priv); + +static inline void cw1200_debug_txed(struct cw1200_common *priv) +{ + ++priv->debug->tx; +} + +static inline void cw1200_debug_txed_agg(struct cw1200_common *priv) +{ + ++priv->debug->tx_agg; +} + +static inline void cw1200_debug_txed_multi(struct cw1200_common *priv, + int count) +{ + ++priv->debug->tx_multi; + priv->debug->tx_multi_frames += count; +} + +static inline void cw1200_debug_rxed(struct cw1200_common *priv) +{ + ++priv->debug->rx; +} + +static inline void cw1200_debug_rxed_agg(struct cw1200_common *priv) +{ + ++priv->debug->rx_agg; +} + +static inline void cw1200_debug_tx_cache_miss(struct cw1200_common *priv) +{ + ++priv->debug->tx_cache_miss; +} + +static inline void cw1200_debug_tx_align(struct cw1200_common *priv) +{ + ++priv->debug->tx_align; +} + +static inline void cw1200_debug_tx_ttl(struct cw1200_common *priv) +{ + ++priv->debug->tx_ttl; +} + +static inline void cw1200_debug_tx_burst(struct cw1200_common *priv) +{ + ++priv->debug->tx_burst; +} + +static inline void cw1200_debug_ba(struct cw1200_common *priv, + int ba_cnt, int ba_acc, + int ba_cnt_rx, int ba_acc_rx) +{ + priv->debug->ba_cnt = ba_cnt; + priv->debug->ba_acc = ba_acc; + priv->debug->ba_cnt_rx = ba_cnt_rx; + priv->debug->ba_acc_rx = ba_acc_rx; +} + +#endif /* CW1200_DEBUG_H_INCLUDED */ diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c new file mode 100644 index 000000000000..ad01cd2a59ec --- /dev/null +++ b/drivers/net/wireless/cw1200/fwio.c @@ -0,0 +1,525 @@ +/* + * Firmware I/O code for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * ST-Ericsson UMAC CW1200 driver which is + * Copyright (c) 2010, ST-Ericsson + * Author: Ajitpal Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "cw1200.h" +#include "fwio.h" +#include "hwio.h" +#include "sbus.h" +#include "bh.h" + +static int cw1200_get_hw_type(u32 config_reg_val, int *major_revision) +{ + int hw_type = -1; + u32 silicon_type = (config_reg_val >> 24) & 0x7; + u32 silicon_vers = (config_reg_val >> 31) & 0x1; + + switch (silicon_type) { + case 0x00: + *major_revision = 1; + hw_type = HIF_9000_SILICON_VERSATILE; + break; + case 0x01: + case 0x02: /* CW1x00 */ + case 0x04: /* CW1x60 */ + *major_revision = silicon_type; + if (silicon_vers) + hw_type = HIF_8601_VERSATILE; + else + hw_type = HIF_8601_SILICON; + break; + default: + break; + } + + return hw_type; +} + +static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) +{ + int ret, block, num_blocks; + unsigned i; + u32 val32; + u32 put = 0, get = 0; + u8 *buf = NULL; + const char *fw_path; + const struct firmware *firmware = NULL; + + /* Macroses are local. */ +#define APB_WRITE(reg, val) \ + do { \ + ret = cw1200_apb_write_32(priv, CW1200_APB(reg), (val)); \ + if (ret < 0) \ + goto error; \ + } while (0) +#define APB_READ(reg, val) \ + do { \ + ret = cw1200_apb_read_32(priv, CW1200_APB(reg), &(val)); \ + if (ret < 0) \ + goto error; \ + } while (0) +#define REG_WRITE(reg, val) \ + do { \ + ret = cw1200_reg_write_32(priv, (reg), (val)); \ + if (ret < 0) \ + goto error; \ + } while (0) +#define REG_READ(reg, val) \ + do { \ + ret = cw1200_reg_read_32(priv, (reg), &(val)); \ + if (ret < 0) \ + goto error; \ + } while (0) + + switch (priv->hw_revision) { + case CW1200_HW_REV_CUT10: + fw_path = FIRMWARE_CUT10; + if (!priv->sdd_path) + priv->sdd_path = SDD_FILE_10; + break; + case CW1200_HW_REV_CUT11: + fw_path = FIRMWARE_CUT11; + if (!priv->sdd_path) + priv->sdd_path = SDD_FILE_11; + break; + case CW1200_HW_REV_CUT20: + fw_path = FIRMWARE_CUT20; + if (!priv->sdd_path) + priv->sdd_path = SDD_FILE_20; + break; + case CW1200_HW_REV_CUT22: + fw_path = FIRMWARE_CUT22; + if (!priv->sdd_path) + priv->sdd_path = SDD_FILE_22; + break; + case CW1X60_HW_REV: + fw_path = FIRMWARE_CW1X60; + if (!priv->sdd_path) + priv->sdd_path = SDD_FILE_CW1X60; + break; + default: + pr_err("Invalid silicon revision %d.\n", priv->hw_revision); + return -EINVAL; + } + + /* Initialize common registers */ + APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, DOWNLOAD_ARE_YOU_HERE); + APB_WRITE(DOWNLOAD_PUT_REG, 0); + APB_WRITE(DOWNLOAD_GET_REG, 0); + APB_WRITE(DOWNLOAD_STATUS_REG, DOWNLOAD_PENDING); + APB_WRITE(DOWNLOAD_FLAGS_REG, 0); + + /* Write the NOP Instruction */ + REG_WRITE(ST90TDS_SRAM_BASE_ADDR_REG_ID, 0xFFF20000); + REG_WRITE(ST90TDS_AHB_DPORT_REG_ID, 0xEAFFFFFE); + + /* Release CPU from RESET */ + REG_READ(ST90TDS_CONFIG_REG_ID, val32); + val32 &= ~ST90TDS_CONFIG_CPU_RESET_BIT; + REG_WRITE(ST90TDS_CONFIG_REG_ID, val32); + + /* Enable Clock */ + val32 &= ~ST90TDS_CONFIG_CPU_CLK_DIS_BIT; + REG_WRITE(ST90TDS_CONFIG_REG_ID, val32); + +#ifdef CONFIG_CW1200_ETF + if (etf_mode) + fw_path = etf_firmware; +#endif + + /* Load a firmware file */ + ret = request_firmware(&firmware, fw_path, priv->pdev); + if (ret) { + pr_err("Can't load firmware file %s.\n", fw_path); + goto error; + } + + buf = kmalloc(DOWNLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); + if (!buf) { + pr_err("Can't allocate firmware load buffer.\n"); + ret = -ENOMEM; + goto error; + } + + /* Check if the bootloader is ready */ + for (i = 0; i < 100; i += 1 + i / 2) { + APB_READ(DOWNLOAD_IMAGE_SIZE_REG, val32); + if (val32 == DOWNLOAD_I_AM_HERE) + break; + mdelay(i); + } /* End of for loop */ + + if (val32 != DOWNLOAD_I_AM_HERE) { + pr_err("Bootloader is not ready.\n"); + ret = -ETIMEDOUT; + goto error; + } + + /* Calculcate number of download blocks */ + num_blocks = (firmware->size - 1) / DOWNLOAD_BLOCK_SIZE + 1; + + /* Updating the length in Download Ctrl Area */ + val32 = firmware->size; /* Explicit cast from size_t to u32 */ + APB_WRITE(DOWNLOAD_IMAGE_SIZE_REG, val32); + + /* Firmware downloading loop */ + for (block = 0; block < num_blocks; block++) { + size_t tx_size; + size_t block_size; + + /* check the download status */ + APB_READ(DOWNLOAD_STATUS_REG, val32); + if (val32 != DOWNLOAD_PENDING) { + pr_err("Bootloader reported error %d.\n", val32); + ret = -EIO; + goto error; + } + + /* loop until put - get <= 24K */ + for (i = 0; i < 100; i++) { + APB_READ(DOWNLOAD_GET_REG, get); + if ((put - get) <= + (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) + break; + mdelay(i); + } + + if ((put - get) > (DOWNLOAD_FIFO_SIZE - DOWNLOAD_BLOCK_SIZE)) { + pr_err("Timeout waiting for FIFO.\n"); + ret = -ETIMEDOUT; + goto error; + } + + /* calculate the block size */ + tx_size = block_size = min((size_t)(firmware->size - put), + (size_t)DOWNLOAD_BLOCK_SIZE); + + memcpy(buf, &firmware->data[put], block_size); + if (block_size < DOWNLOAD_BLOCK_SIZE) { + memset(&buf[block_size], 0, + DOWNLOAD_BLOCK_SIZE - block_size); + tx_size = DOWNLOAD_BLOCK_SIZE; + } + + /* send the block to sram */ + ret = cw1200_apb_write(priv, + CW1200_APB(DOWNLOAD_FIFO_OFFSET + + (put & (DOWNLOAD_FIFO_SIZE - 1))), + buf, tx_size); + if (ret < 0) { + pr_err("Can't write firmware block @ %d!\n", + put & (DOWNLOAD_FIFO_SIZE - 1)); + goto error; + } + + /* update the put register */ + put += block_size; + APB_WRITE(DOWNLOAD_PUT_REG, put); + } /* End of firmware download loop */ + + /* Wait for the download completion */ + for (i = 0; i < 300; i += 1 + i / 2) { + APB_READ(DOWNLOAD_STATUS_REG, val32); + if (val32 != DOWNLOAD_PENDING) + break; + mdelay(i); + } + if (val32 != DOWNLOAD_SUCCESS) { + pr_err("Wait for download completion failed: 0x%.8X\n", val32); + ret = -ETIMEDOUT; + goto error; + } else { + pr_info("Firmware download completed.\n"); + ret = 0; + } + +error: + kfree(buf); + if (firmware) + release_firmware(firmware); + return ret; + +#undef APB_WRITE +#undef APB_READ +#undef REG_WRITE +#undef REG_READ +} + + +static int config_reg_read(struct cw1200_common *priv, u32 *val) +{ + switch (priv->hw_type) { + case HIF_9000_SILICON_VERSATILE: { + u16 val16; + int ret = cw1200_reg_read_16(priv, + ST90TDS_CONFIG_REG_ID, + &val16); + if (ret < 0) + return ret; + *val = val16; + return 0; + } + case HIF_8601_VERSATILE: + case HIF_8601_SILICON: + default: + cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, val); + break; + } + return 0; +} + +static int config_reg_write(struct cw1200_common *priv, u32 val) +{ + switch (priv->hw_type) { + case HIF_9000_SILICON_VERSATILE: + return cw1200_reg_write_16(priv, + ST90TDS_CONFIG_REG_ID, + (u16)val); + case HIF_8601_VERSATILE: + case HIF_8601_SILICON: + default: + return cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val); + break; + } + return 0; +} + +int cw1200_load_firmware(struct cw1200_common *priv) +{ + int ret; + int i; + u32 val32; + u16 val16; + int major_revision = -1; + + /* Read CONFIG Register */ + ret = cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); + if (ret < 0) { + pr_err("Can't read config register.\n"); + goto out; + } + + if (val32 == 0 || val32 == 0xffffffff) { + pr_err("Bad config register value (0x%08x)\n", val32); + ret = -EIO; + goto out; + } + + priv->hw_type = cw1200_get_hw_type(val32, &major_revision); + if (priv->hw_type < 0) { + pr_err("Can't deduce hardware type.\n"); + ret = -ENOTSUPP; + goto out; + } + + /* Set DPLL Reg value, and read back to confirm writes work */ + ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID, + cw1200_dpll_from_clk(priv->hw_refclk)); + if (ret < 0) { + pr_err("Can't write DPLL register.\n"); + goto out; + } + + msleep(20); + + ret = cw1200_reg_read_32(priv, + ST90TDS_TSET_GEN_R_W_REG_ID, &val32); + if (ret < 0) { + pr_err("Can't read DPLL register.\n"); + goto out; + } + + if (val32 != cw1200_dpll_from_clk(priv->hw_refclk)) { + pr_err("Unable to initialise DPLL register. Wrote 0x%.8X, Read 0x%.8X.\n", + cw1200_dpll_from_clk(priv->hw_refclk), val32); + ret = -EIO; + goto out; + } + + /* Set wakeup bit in device */ + ret = cw1200_reg_read_16(priv, ST90TDS_CONTROL_REG_ID, &val16); + if (ret < 0) { + pr_err("set_wakeup: can't read control register.\n"); + goto out; + } + + ret = cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID, + val16 | ST90TDS_CONT_WUP_BIT); + if (ret < 0) { + pr_err("set_wakeup: can't write control register.\n"); + goto out; + } + + /* Wait for wakeup */ + for (i = 0; i < 300; i += (1 + i / 2)) { + ret = cw1200_reg_read_16(priv, + ST90TDS_CONTROL_REG_ID, &val16); + if (ret < 0) { + pr_err("wait_for_wakeup: can't read control register.\n"); + goto out; + } + + if (val16 & ST90TDS_CONT_RDY_BIT) + break; + + msleep(i); + } + + if ((val16 & ST90TDS_CONT_RDY_BIT) == 0) { + pr_err("wait_for_wakeup: device is not responding.\n"); + ret = -ETIMEDOUT; + goto out; + } + + switch (major_revision) { + case 1: + /* CW1200 Hardware detection logic : Check for CUT1.1 */ + ret = cw1200_ahb_read_32(priv, CW1200_CUT_ID_ADDR, &val32); + if (ret) { + pr_err("HW detection: can't read CUT ID.\n"); + goto out; + } + + switch (val32) { + case CW1200_CUT_11_ID_STR: + pr_info("CW1x00 Cut 1.1 silicon detected.\n"); + priv->hw_revision = CW1200_HW_REV_CUT11; + break; + default: + pr_info("CW1x00 Cut 1.0 silicon detected.\n"); + priv->hw_revision = CW1200_HW_REV_CUT10; + break; + } + + /* According to ST-E, CUT<2.0 has busted BA TID0-3. + Just disable it entirely... + */ + priv->ba_rx_tid_mask = 0; + priv->ba_tx_tid_mask = 0; + break; + case 2: { + u32 ar1, ar2, ar3; + ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR, &ar1); + if (ret) { + pr_err("(1) HW detection: can't read CUT ID\n"); + goto out; + } + ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR + 4, &ar2); + if (ret) { + pr_err("(2) HW detection: can't read CUT ID.\n"); + goto out; + } + + ret = cw1200_ahb_read_32(priv, CW1200_CUT2_ID_ADDR + 8, &ar3); + if (ret) { + pr_err("(3) HW detection: can't read CUT ID.\n"); + goto out; + } + + if (ar1 == CW1200_CUT_22_ID_STR1 && + ar2 == CW1200_CUT_22_ID_STR2 && + ar3 == CW1200_CUT_22_ID_STR3) { + pr_info("CW1x00 Cut 2.2 silicon detected.\n"); + priv->hw_revision = CW1200_HW_REV_CUT22; + } else { + pr_info("CW1x00 Cut 2.0 silicon detected.\n"); + priv->hw_revision = CW1200_HW_REV_CUT20; + } + break; + } + case 4: + pr_info("CW1x60 silicon detected.\n"); + priv->hw_revision = CW1X60_HW_REV; + break; + default: + pr_err("Unsupported silicon major revision %d.\n", + major_revision); + ret = -ENOTSUPP; + goto out; + } + + /* Checking for access mode */ + ret = config_reg_read(priv, &val32); + if (ret < 0) { + pr_err("Can't read config register.\n"); + goto out; + } + + if (!(val32 & ST90TDS_CONFIG_ACCESS_MODE_BIT)) { + pr_err("Device is already in QUEUE mode!\n"); + ret = -EINVAL; + goto out; + } + + switch (priv->hw_type) { + case HIF_8601_SILICON: + if (priv->hw_revision == CW1X60_HW_REV) { + pr_err("Can't handle CW1160/1260 firmware load yet.\n"); + ret = -ENOTSUPP; + goto out; + } + ret = cw1200_load_firmware_cw1200(priv); + break; + default: + pr_err("Can't perform firmware load for hw type %d.\n", + priv->hw_type); + ret = -ENOTSUPP; + goto out; + } + if (ret < 0) { + pr_err("Firmware load error.\n"); + goto out; + } + + /* Enable interrupt signalling */ + priv->sbus_ops->lock(priv->sbus_priv); + ret = __cw1200_irq_enable(priv, 1); + priv->sbus_ops->unlock(priv->sbus_priv); + if (ret < 0) + goto unsubscribe; + + /* Configure device for MESSSAGE MODE */ + ret = config_reg_read(priv, &val32); + if (ret < 0) { + pr_err("Can't read config register.\n"); + goto unsubscribe; + } + ret = config_reg_write(priv, val32 & ~ST90TDS_CONFIG_ACCESS_MODE_BIT); + if (ret < 0) { + pr_err("Can't write config register.\n"); + goto unsubscribe; + } + + /* Unless we read the CONFIG Register we are + * not able to get an interrupt + */ + mdelay(10); + config_reg_read(priv, &val32); + +out: + return ret; + +unsubscribe: + /* Disable interrupt signalling */ + priv->sbus_ops->lock(priv->sbus_priv); + ret = __cw1200_irq_enable(priv, 0); + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} diff --git a/drivers/net/wireless/cw1200/fwio.h b/drivers/net/wireless/cw1200/fwio.h new file mode 100644 index 000000000000..ea3099362cdf --- /dev/null +++ b/drivers/net/wireless/cw1200/fwio.h @@ -0,0 +1,39 @@ +/* + * Firmware API for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * ST-Ericsson UMAC CW1200 driver which is + * Copyright (c) 2010, ST-Ericsson + * Author: Ajitpal Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef FWIO_H_INCLUDED +#define FWIO_H_INCLUDED + +#define BOOTLOADER_CW1X60 "boot_cw1x60.bin" +#define FIRMWARE_CW1X60 "wsm_cw1x60.bin" +#define FIRMWARE_CUT22 "wsm_22.bin" +#define FIRMWARE_CUT20 "wsm_20.bin" +#define FIRMWARE_CUT11 "wsm_11.bin" +#define FIRMWARE_CUT10 "wsm_10.bin" +#define SDD_FILE_CW1X60 "sdd_cw1x60.bin" +#define SDD_FILE_22 "sdd_22.bin" +#define SDD_FILE_20 "sdd_20.bin" +#define SDD_FILE_11 "sdd_11.bin" +#define SDD_FILE_10 "sdd_10.bin" + +int cw1200_load_firmware(struct cw1200_common *priv); + +/* SDD definitions */ +#define SDD_PTA_CFG_ELT_ID 0xEB +#define SDD_REFERENCE_FREQUENCY_ELT_ID 0xc5 +u32 cw1200_dpll_from_clk(u16 clk); + +#endif diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c new file mode 100644 index 000000000000..1af7b3d421b2 --- /dev/null +++ b/drivers/net/wireless/cw1200/hwio.c @@ -0,0 +1,311 @@ +/* + * Low-level device IO routines for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * ST-Ericsson UMAC CW1200 driver, which is + * Copyright (c) 2010, ST-Ericsson + * Author: Ajitpal Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#include "cw1200.h" +#include "hwio.h" +#include "sbus.h" + + /* Sdio addr is 4*spi_addr */ +#define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2) +#define SDIO_ADDR17BIT(buf_id, mpf, rfu, reg_id_ofs) \ + ((((buf_id) & 0x1F) << 7) \ + | (((mpf) & 1) << 6) \ + | (((rfu) & 1) << 5) \ + | (((reg_id_ofs) & 0x1F) << 0)) +#define MAX_RETRY 3 + + +static int __cw1200_reg_read(struct cw1200_common *priv, u16 addr, + void *buf, size_t buf_len, int buf_id) +{ + u16 addr_sdio; + u32 sdio_reg_addr_17bit; + + /* Check if buffer is aligned to 4 byte boundary */ + if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) { + pr_err("buffer is not aligned.\n"); + return -EINVAL; + } + + /* Convert to SDIO Register Address */ + addr_sdio = SPI_REG_ADDR_TO_SDIO(addr); + sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio); + + return priv->sbus_ops->sbus_memcpy_fromio(priv->sbus_priv, + sdio_reg_addr_17bit, + buf, buf_len); +} + +static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr, + const void *buf, size_t buf_len, int buf_id) +{ + u16 addr_sdio; + u32 sdio_reg_addr_17bit; + + /* Convert to SDIO Register Address */ + addr_sdio = SPI_REG_ADDR_TO_SDIO(addr); + sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio); + + return priv->sbus_ops->sbus_memcpy_toio(priv->sbus_priv, + sdio_reg_addr_17bit, + buf, buf_len); +} + +static inline int __cw1200_reg_read_32(struct cw1200_common *priv, + u16 addr, u32 *val) +{ + int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); + *val = le32_to_cpu(*val); + return i; +} + +static inline int __cw1200_reg_write_32(struct cw1200_common *priv, + u16 addr, u32 val) +{ + val = cpu_to_le32(val); + return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); +} + +static inline int __cw1200_reg_read_16(struct cw1200_common *priv, + u16 addr, u16 *val) +{ + int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); + *val = le16_to_cpu(*val); + return i; +} + +static inline int __cw1200_reg_write_16(struct cw1200_common *priv, + u16 addr, u16 val) +{ + val = cpu_to_le16(val); + return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); +} + +int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf, + size_t buf_len) +{ + int ret; + priv->sbus_ops->lock(priv->sbus_priv); + ret = __cw1200_reg_read(priv, addr, buf, buf_len, 0); + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int cw1200_reg_write(struct cw1200_common *priv, u16 addr, const void *buf, + size_t buf_len) +{ + int ret; + priv->sbus_ops->lock(priv->sbus_priv); + ret = __cw1200_reg_write(priv, addr, buf, buf_len, 0); + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int cw1200_data_read(struct cw1200_common *priv, void *buf, size_t buf_len) +{ + int ret, retry = 1; + int buf_id_rx = priv->buf_id_rx; + + priv->sbus_ops->lock(priv->sbus_priv); + + while (retry <= MAX_RETRY) { + ret = __cw1200_reg_read(priv, + ST90TDS_IN_OUT_QUEUE_REG_ID, buf, + buf_len, buf_id_rx + 1); + if (!ret) { + buf_id_rx = (buf_id_rx + 1) & 3; + priv->buf_id_rx = buf_id_rx; + break; + } else { + retry++; + mdelay(1); + pr_err("error :[%d]\n", ret); + } + } + + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int cw1200_data_write(struct cw1200_common *priv, const void *buf, + size_t buf_len) +{ + int ret, retry = 1; + int buf_id_tx = priv->buf_id_tx; + + priv->sbus_ops->lock(priv->sbus_priv); + + while (retry <= MAX_RETRY) { + ret = __cw1200_reg_write(priv, + ST90TDS_IN_OUT_QUEUE_REG_ID, buf, + buf_len, buf_id_tx); + if (!ret) { + buf_id_tx = (buf_id_tx + 1) & 31; + priv->buf_id_tx = buf_id_tx; + break; + } else { + retry++; + mdelay(1); + pr_err("error :[%d]\n", ret); + } + } + + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, + size_t buf_len, u32 prefetch, u16 port_addr) +{ + u32 val32 = 0; + int i, ret; + + if ((buf_len / 2) >= 0x1000) { + pr_err("Can't read more than 0xfff words.\n"); + return -EINVAL; + goto out; + } + + priv->sbus_ops->lock(priv->sbus_priv); + /* Write address */ + ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr); + if (ret < 0) { + pr_err("Can't write address register.\n"); + goto out; + } + + /* Read CONFIG Register Value - We will read 32 bits */ + ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); + if (ret < 0) { + pr_err("Can't read config register.\n"); + goto out; + } + + /* Set PREFETCH bit */ + ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, + val32 | prefetch); + if (ret < 0) { + pr_err("Can't write prefetch bit.\n"); + goto out; + } + + /* Check for PRE-FETCH bit to be cleared */ + for (i = 0; i < 20; i++) { + ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); + if (ret < 0) { + pr_err("Can't check prefetch bit.\n"); + goto out; + } + if (!(val32 & prefetch)) + break; + + mdelay(i); + } + + if (val32 & prefetch) { + pr_err("Prefetch bit is not cleared.\n"); + goto out; + } + + /* Read data port */ + ret = __cw1200_reg_read(priv, port_addr, buf, buf_len, 0); + if (ret < 0) { + pr_err("Can't read data port.\n"); + goto out; + } + +out: + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf, + size_t buf_len) +{ + int ret; + + if ((buf_len / 2) >= 0x1000) { + pr_err("Can't write more than 0xfff words.\n"); + return -EINVAL; + } + + priv->sbus_ops->lock(priv->sbus_priv); + + /* Write address */ + ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr); + if (ret < 0) { + pr_err("Can't write address register.\n"); + goto out; + } + + /* Write data port */ + ret = __cw1200_reg_write(priv, ST90TDS_SRAM_DPORT_REG_ID, + buf, buf_len, 0); + if (ret < 0) { + pr_err("Can't write data port.\n"); + goto out; + } + +out: + priv->sbus_ops->unlock(priv->sbus_priv); + return ret; +} + +int __cw1200_irq_enable(struct cw1200_common *priv, int enable) +{ + u32 val32; + u16 val16; + int ret; + + if (HIF_8601_SILICON == priv->hw_type) { + ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); + if (ret < 0) { + pr_err("Can't read config register.\n"); + return ret; + } + + if (enable) + val32 |= ST90TDS_CONF_IRQ_RDY_ENABLE; + else + val32 &= ~ST90TDS_CONF_IRQ_RDY_ENABLE; + + ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val32); + if (ret < 0) { + pr_err("Can't write config register.\n"); + return ret; + } + } else { + ret = __cw1200_reg_read_16(priv, ST90TDS_CONFIG_REG_ID, &val16); + if (ret < 0) { + pr_err("Can't read control register.\n"); + return ret; + } + + if (enable) + val16 |= ST90TDS_CONT_IRQ_RDY_ENABLE; + else + val16 &= ~ST90TDS_CONT_IRQ_RDY_ENABLE; + + ret = __cw1200_reg_write_16(priv, ST90TDS_CONFIG_REG_ID, val16); + if (ret < 0) { + pr_err("Can't write control register.\n"); + return ret; + } + } + return 0; +} diff --git a/drivers/net/wireless/cw1200/hwio.h b/drivers/net/wireless/cw1200/hwio.h new file mode 100644 index 000000000000..7ee73fe32ccf --- /dev/null +++ b/drivers/net/wireless/cw1200/hwio.h @@ -0,0 +1,247 @@ +/* + * Low-level API for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * ST-Ericsson UMAC CW1200 driver which is + * Copyright (c) 2010, ST-Ericsson + * Author: Ajitpal Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_HWIO_H_INCLUDED +#define CW1200_HWIO_H_INCLUDED + +/* extern */ struct cw1200_common; + +#define CW1200_CUT_11_ID_STR (0x302E3830) +#define CW1200_CUT_22_ID_STR1 (0x302e3132) +#define CW1200_CUT_22_ID_STR2 (0x32302e30) +#define CW1200_CUT_22_ID_STR3 (0x3335) +#define CW1200_CUT_ID_ADDR (0xFFF17F90) +#define CW1200_CUT2_ID_ADDR (0xFFF1FF90) + +/* Download control area */ +/* boot loader start address in SRAM */ +#define DOWNLOAD_BOOT_LOADER_OFFSET (0x00000000) +/* 32K, 0x4000 to 0xDFFF */ +#define DOWNLOAD_FIFO_OFFSET (0x00004000) +/* 32K */ +#define DOWNLOAD_FIFO_SIZE (0x00008000) +/* 128 bytes, 0xFF80 to 0xFFFF */ +#define DOWNLOAD_CTRL_OFFSET (0x0000FF80) +#define DOWNLOAD_CTRL_DATA_DWORDS (32-6) + +struct download_cntl_t { + /* size of whole firmware file (including Cheksum), host init */ + u32 image_size; + /* downloading flags */ + u32 flags; + /* No. of bytes put into the download, init & updated by host */ + u32 put; + /* last traced program counter, last ARM reg_pc */ + u32 trace_pc; + /* No. of bytes read from the download, host init, device updates */ + u32 get; + /* r0, boot losader status, host init to pending, device updates */ + u32 status; + /* Extra debug info, r1 to r14 if status=r0=DOWNLOAD_EXCEPTION */ + u32 debug_data[DOWNLOAD_CTRL_DATA_DWORDS]; +}; + +#define DOWNLOAD_IMAGE_SIZE_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, image_size)) +#define DOWNLOAD_FLAGS_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, flags)) +#define DOWNLOAD_PUT_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, put)) +#define DOWNLOAD_TRACE_PC_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, trace_pc)) +#define DOWNLOAD_GET_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, get)) +#define DOWNLOAD_STATUS_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, status)) +#define DOWNLOAD_DEBUG_DATA_REG \ + (DOWNLOAD_CTRL_OFFSET + offsetof(struct download_cntl_t, debug_data)) +#define DOWNLOAD_DEBUG_DATA_LEN (108) + +#define DOWNLOAD_BLOCK_SIZE (1024) + +/* For boot loader detection */ +#define DOWNLOAD_ARE_YOU_HERE (0x87654321) +#define DOWNLOAD_I_AM_HERE (0x12345678) + +/* Download error code */ +#define DOWNLOAD_PENDING (0xFFFFFFFF) +#define DOWNLOAD_SUCCESS (0) +#define DOWNLOAD_EXCEPTION (1) +#define DOWNLOAD_ERR_MEM_1 (2) +#define DOWNLOAD_ERR_MEM_2 (3) +#define DOWNLOAD_ERR_SOFTWARE (4) +#define DOWNLOAD_ERR_FILE_SIZE (5) +#define DOWNLOAD_ERR_CHECKSUM (6) +#define DOWNLOAD_ERR_OVERFLOW (7) +#define DOWNLOAD_ERR_IMAGE (8) +#define DOWNLOAD_ERR_HOST (9) +#define DOWNLOAD_ERR_ABORT (10) + + +#define SYS_BASE_ADDR_SILICON (0) +#define PAC_BASE_ADDRESS_SILICON (SYS_BASE_ADDR_SILICON + 0x09000000) +#define PAC_SHARED_MEMORY_SILICON (PAC_BASE_ADDRESS_SILICON) + +#define CW1200_APB(addr) (PAC_SHARED_MEMORY_SILICON + (addr)) + +/* *************************************************************** +*Device register definitions +*************************************************************** */ +/* WBF - SPI Register Addresses */ +#define ST90TDS_ADDR_ID_BASE (0x0000) +/* 16/32 bits */ +#define ST90TDS_CONFIG_REG_ID (0x0000) +/* 16/32 bits */ +#define ST90TDS_CONTROL_REG_ID (0x0001) +/* 16 bits, Q mode W/R */ +#define ST90TDS_IN_OUT_QUEUE_REG_ID (0x0002) +/* 32 bits, AHB bus R/W */ +#define ST90TDS_AHB_DPORT_REG_ID (0x0003) +/* 16/32 bits */ +#define ST90TDS_SRAM_BASE_ADDR_REG_ID (0x0004) +/* 32 bits, APB bus R/W */ +#define ST90TDS_SRAM_DPORT_REG_ID (0x0005) +/* 32 bits, t_settle/general */ +#define ST90TDS_TSET_GEN_R_W_REG_ID (0x0006) +/* 16 bits, Q mode read, no length */ +#define ST90TDS_FRAME_OUT_REG_ID (0x0007) +#define ST90TDS_ADDR_ID_MAX (ST90TDS_FRAME_OUT_REG_ID) + +/* WBF - Control register bit set */ +/* next o/p length, bit 11 to 0 */ +#define ST90TDS_CONT_NEXT_LEN_MASK (0x0FFF) +#define ST90TDS_CONT_WUP_BIT (BIT(12)) +#define ST90TDS_CONT_RDY_BIT (BIT(13)) +#define ST90TDS_CONT_IRQ_ENABLE (BIT(14)) +#define ST90TDS_CONT_RDY_ENABLE (BIT(15)) +#define ST90TDS_CONT_IRQ_RDY_ENABLE (BIT(14)|BIT(15)) + +/* SPI Config register bit set */ +#define ST90TDS_CONFIG_FRAME_BIT (BIT(2)) +#define ST90TDS_CONFIG_WORD_MODE_BITS (BIT(3)|BIT(4)) +#define ST90TDS_CONFIG_WORD_MODE_1 (BIT(3)) +#define ST90TDS_CONFIG_WORD_MODE_2 (BIT(4)) +#define ST90TDS_CONFIG_ERROR_0_BIT (BIT(5)) +#define ST90TDS_CONFIG_ERROR_1_BIT (BIT(6)) +#define ST90TDS_CONFIG_ERROR_2_BIT (BIT(7)) +/* TBD: Sure??? */ +#define ST90TDS_CONFIG_CSN_FRAME_BIT (BIT(7)) +#define ST90TDS_CONFIG_ERROR_3_BIT (BIT(8)) +#define ST90TDS_CONFIG_ERROR_4_BIT (BIT(9)) +/* QueueM */ +#define ST90TDS_CONFIG_ACCESS_MODE_BIT (BIT(10)) +/* AHB bus */ +#define ST90TDS_CONFIG_AHB_PRFETCH_BIT (BIT(11)) +#define ST90TDS_CONFIG_CPU_CLK_DIS_BIT (BIT(12)) +/* APB bus */ +#define ST90TDS_CONFIG_PRFETCH_BIT (BIT(13)) +/* cpu reset */ +#define ST90TDS_CONFIG_CPU_RESET_BIT (BIT(14)) +#define ST90TDS_CONFIG_CLEAR_INT_BIT (BIT(15)) + +/* For CW1200 the IRQ Enable and Ready Bits are in CONFIG register */ +#define ST90TDS_CONF_IRQ_ENABLE (BIT(16)) +#define ST90TDS_CONF_RDY_ENABLE (BIT(17)) +#define ST90TDS_CONF_IRQ_RDY_ENABLE (BIT(16)|BIT(17)) + +int cw1200_data_read(struct cw1200_common *priv, + void *buf, size_t buf_len); +int cw1200_data_write(struct cw1200_common *priv, + const void *buf, size_t buf_len); + +int cw1200_reg_read(struct cw1200_common *priv, u16 addr, + void *buf, size_t buf_len); +int cw1200_reg_write(struct cw1200_common *priv, u16 addr, + const void *buf, size_t buf_len); + +static inline int cw1200_reg_read_16(struct cw1200_common *priv, + u16 addr, u16 *val) +{ + u32 tmp; + int i; + i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp)); + tmp = le32_to_cpu(tmp); + *val = tmp & 0xffff; + return i; +} + +static inline int cw1200_reg_write_16(struct cw1200_common *priv, + u16 addr, u16 val) +{ + u32 tmp = val; + tmp = cpu_to_le32(tmp); + return cw1200_reg_write(priv, addr, &tmp, sizeof(tmp)); +} + +static inline int cw1200_reg_read_32(struct cw1200_common *priv, + u16 addr, u32 *val) +{ + int i = cw1200_reg_read(priv, addr, val, sizeof(*val)); + *val = le32_to_cpu(*val); + return i; +} + +static inline int cw1200_reg_write_32(struct cw1200_common *priv, + u16 addr, u32 val) +{ + val = cpu_to_le32(val); + return cw1200_reg_write(priv, addr, &val, sizeof(val)); +} + +int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, + size_t buf_len, u32 prefetch, u16 port_addr); +int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf, + size_t buf_len); + +static inline int cw1200_apb_read(struct cw1200_common *priv, u32 addr, + void *buf, size_t buf_len) +{ + return cw1200_indirect_read(priv, addr, buf, buf_len, + ST90TDS_CONFIG_PRFETCH_BIT, + ST90TDS_SRAM_DPORT_REG_ID); +} + +static inline int cw1200_ahb_read(struct cw1200_common *priv, u32 addr, + void *buf, size_t buf_len) +{ + return cw1200_indirect_read(priv, addr, buf, buf_len, + ST90TDS_CONFIG_AHB_PRFETCH_BIT, + ST90TDS_AHB_DPORT_REG_ID); +} + +static inline int cw1200_apb_read_32(struct cw1200_common *priv, + u32 addr, u32 *val) +{ + int i = cw1200_apb_read(priv, addr, val, sizeof(*val)); + *val = le32_to_cpu(*val); + return i; +} + +static inline int cw1200_apb_write_32(struct cw1200_common *priv, + u32 addr, u32 val) +{ + val = cpu_to_le32(val); + return cw1200_apb_write(priv, addr, &val, sizeof(val)); +} +static inline int cw1200_ahb_read_32(struct cw1200_common *priv, + u32 addr, u32 *val) +{ + int i = cw1200_ahb_read(priv, addr, val, sizeof(*val)); + *val = le32_to_cpu(*val); + return i; +} + +#endif /* CW1200_HWIO_H_INCLUDED */ diff --git a/drivers/net/wireless/cw1200/itp.c b/drivers/net/wireless/cw1200/itp.c new file mode 100644 index 000000000000..c0730bb49b75 --- /dev/null +++ b/drivers/net/wireless/cw1200/itp.c @@ -0,0 +1,730 @@ +/* + * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers + * ITP code + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "cw1200.h" +#include "debug.h" +#include "itp.h" +#include "sta.h" + +static int __cw1200_itp_open(struct cw1200_common *priv); +static int __cw1200_itp_close(struct cw1200_common *priv); +static void cw1200_itp_rx_start(struct cw1200_common *priv); +static void cw1200_itp_rx_stop(struct cw1200_common *priv); +static void cw1200_itp_rx_stats(struct cw1200_common *priv); +static void cw1200_itp_rx_reset(struct cw1200_common *priv); +static void cw1200_itp_tx_stop(struct cw1200_common *priv); +static void cw1200_itp_handle(struct cw1200_common *priv, + struct sk_buff *skb); +static void cw1200_itp_err(struct cw1200_common *priv, + int err, + int arg); +static void __cw1200_itp_tx_stop(struct cw1200_common *priv); + +static ssize_t cw1200_itp_read(struct file *file, + char __user *user_buf, size_t count, loff_t *ppos) +{ + struct cw1200_common *priv = file->private_data; + struct cw1200_itp *itp = &priv->debug->itp; + struct sk_buff *skb; + int ret; + + if (skb_queue_empty(&itp->log_queue)) + return 0; + + skb = skb_dequeue(&itp->log_queue); + ret = copy_to_user(user_buf, skb->data, skb->len); + *ppos += skb->len; + skb->data[skb->len] = 0; + pr_debug("[ITP] >>> %s", skb->data); + consume_skb(skb); + + return skb->len - ret; +} + +static ssize_t cw1200_itp_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct cw1200_common *priv = file->private_data; + struct sk_buff *skb; + + if (!count || count > 1024) + return -EINVAL; + skb = dev_alloc_skb(count + 1); + if (!skb) + return -ENOMEM; + skb_trim(skb, 0); + skb_put(skb, count + 1); + if (copy_from_user(skb->data, user_buf, count)) { + kfree_skb(skb); + return -EFAULT; + } + skb->data[count] = 0; + + cw1200_itp_handle(priv, skb); + consume_skb(skb); + return count; +} + +static unsigned int cw1200_itp_poll(struct file *file, poll_table *wait) +{ + struct cw1200_common *priv = file->private_data; + struct cw1200_itp *itp = &priv->debug->itp; + unsigned int mask = 0; + + poll_wait(file, &itp->read_wait, wait); + + if (!skb_queue_empty(&itp->log_queue)) + mask |= POLLIN | POLLRDNORM; + + mask |= POLLOUT | POLLWRNORM; + + return mask; +} + +static int cw1200_itp_open(struct inode *inode, struct file *file) +{ + struct cw1200_common *priv = inode->i_private; + struct cw1200_itp *itp = &priv->debug->itp; + int ret = 0; + + file->private_data = priv; + if (atomic_inc_return(&itp->open_count) == 1) { + ret = __cw1200_itp_open(priv); + if (ret && !atomic_dec_return(&itp->open_count)) + __cw1200_itp_close(priv); + } else { + atomic_dec(&itp->open_count); + ret = -EBUSY; + } + + return ret; +} + +static int cw1200_itp_close(struct inode *inode, struct file *file) +{ + struct cw1200_common *priv = file->private_data; + struct cw1200_itp *itp = &priv->debug->itp; + if (!atomic_dec_return(&itp->open_count)) { + __cw1200_itp_close(priv); + wake_up(&itp->close_wait); + } + return 0; +} + +static const struct file_operations fops_itp = { + .open = cw1200_itp_open, + .read = cw1200_itp_read, + .write = cw1200_itp_write, + .poll = cw1200_itp_poll, + .release = cw1200_itp_close, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static void cw1200_itp_fill_pattern(u8 *data, int size, + enum cw1200_itp_data_modes mode) +{ + if (size <= 0) + return; + + switch (mode) { + default: + case ITP_DATA_ZEROS: + memset(data, 0x0, size); + break; + case ITP_DATA_ONES: + memset(data, 0xff, size); + break; + case ITP_DATA_ZERONES: + memset(data, 0x55, size); + break; + case ITP_DATA_RANDOM: + get_random_bytes(data, size); + break; + } + return; +} + +static void cw1200_itp_tx_work(struct work_struct *work) +{ + struct cw1200_itp *itp = container_of(work, struct cw1200_itp, + tx_work.work); + struct cw1200_common *priv = itp->priv; + atomic_set(&priv->bh_tx, 1); + wake_up(&priv->bh_wq); +} + +static void cw1200_itp_tx_finish(struct work_struct *work) +{ + struct cw1200_itp *itp = container_of(work, struct cw1200_itp, + tx_finish.work); + __cw1200_itp_tx_stop(itp->priv); +} + +int cw1200_itp_init(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + + itp->priv = priv; + atomic_set(&itp->open_count, 0); + atomic_set(&itp->stop_tx, 0); + atomic_set(&itp->awaiting_confirm, 0); + skb_queue_head_init(&itp->log_queue); + spin_lock_init(&itp->tx_lock); + init_waitqueue_head(&itp->read_wait); + init_waitqueue_head(&itp->write_wait); + init_waitqueue_head(&itp->close_wait); + INIT_DELAYED_WORK(&itp->tx_work, cw1200_itp_tx_work); + INIT_DELAYED_WORK(&itp->tx_finish, cw1200_itp_tx_finish); + itp->data = NULL; + itp->hdr_len = WSM_TX_EXTRA_HEADROOM + + sizeof(struct ieee80211_hdr_3addr); + + if (!debugfs_create_file("itp", S_IRUSR | S_IWUSR, + priv->debug->debugfs_phy, priv, &fops_itp)) + return -ENOMEM; + + return 0; +} + +void cw1200_itp_release(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + + wait_event_interruptible(itp->close_wait, + !atomic_read(&itp->open_count)); + + WARN_ON(atomic_read(&itp->open_count)); + + skb_queue_purge(&itp->log_queue); + cw1200_itp_tx_stop(priv); +} + +static int __cw1200_itp_open(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + + if (!priv->vif) + return -EINVAL; + if (priv->join_status) + return -EINVAL; + itp->saved_channel = priv->channel; + if (!priv->channel) + priv->channel = &priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; + wsm_set_bssid_filtering(priv, false); + cw1200_itp_rx_reset(priv); + return 0; +} + +static int __cw1200_itp_close(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + if (atomic_read(&itp->test_mode) == TEST_MODE_RX_TEST) + cw1200_itp_rx_stop(priv); + cw1200_itp_tx_stop(priv); + cw1200_disable_listening(priv); + cw1200_update_filtering(priv); + priv->channel = itp->saved_channel; + return 0; +} + +bool cw1200_is_itp(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + return atomic_read(&itp->open_count) != 0; +} + +static void cw1200_itp_rx_reset(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + itp->rx_cnt = 0; + itp->rx_rssi = 0; + itp->rx_rssi_max = -1000; + itp->rx_rssi_min = 1000; +} + +static void cw1200_itp_rx_start(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + + pr_debug("[ITP] RX start, band = %d, ch = %d\n", + itp->band, itp->ch); + atomic_set(&itp->test_mode, TEST_MODE_RX_TEST); + cw1200_update_listening(priv, false); + priv->channel = &priv->hw-> + wiphy->bands[itp->band]->channels[itp->ch]; + cw1200_update_listening(priv, true); + wsm_set_bssid_filtering(priv, false); +} + +static void cw1200_itp_rx_stop(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + pr_debug("[ITP] RX stop\n"); + atomic_set(&itp->test_mode, TEST_MODE_NO_TEST); + cw1200_itp_rx_reset(priv); +} + +static void cw1200_itp_rx_stats(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + struct sk_buff *skb; + char buf[128]; + int len, ret; + struct wsm_mib_counters_table counters; + + ret = wsm_get_counters_table(priv, &counters); + + if (ret) + cw1200_itp_err(priv, -EBUSY, 20); + + if (!itp->rx_cnt) + len = snprintf(buf, sizeof(buf), "1,0,0,0,0,%d\n", + counters.rx_packet_errors); + else + len = snprintf(buf, sizeof(buf), "1,%d,%ld,%d,%d,%d\n", + itp->rx_cnt, + itp->rx_cnt ? itp->rx_rssi / itp->rx_cnt : 0, + itp->rx_rssi_min, itp->rx_rssi_max, + counters.rx_packet_errors); + + if (len <= 0) { + cw1200_itp_err(priv, -EBUSY, 21); + return; + } + + skb = dev_alloc_skb(len); + if (!skb) { + cw1200_itp_err(priv, -ENOMEM, 22); + return; + } + + itp->rx_cnt = 0; + itp->rx_rssi = 0; + itp->rx_rssi_max = -1000; + itp->rx_rssi_min = 1000; + + skb_trim(skb, 0); + skb_put(skb, len); + + memcpy(skb->data, buf, len); + skb_queue_tail(&itp->log_queue, skb); + wake_up(&itp->read_wait); +} + +static void cw1200_itp_tx_start(struct cw1200_common *priv) +{ + struct wsm_tx *tx; + struct ieee80211_hdr_3addr *hdr; + struct cw1200_itp *itp = &priv->debug->itp; + struct wsm_mib_association_mode assoc_mode = { + .flags = WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE, + .preamble = itp->preamble, + }; + int len; + u8 da_addr[6] = ITP_DEFAULT_DA_ADDR; + + /* Rates index 4 and 5 are not supported */ + if (itp->rate > 3) + itp->rate += 2; + + pr_debug("[ITP] TX start: band = %d, ch = %d, rate = %d, preamble = %d, number = %d, data_mode = %d, interval = %d, power = %d, data_len = %d\n", + itp->band, itp->ch, itp->rate, itp->preamble, + itp->number, itp->data_mode, itp->interval_us, + itp->power, itp->data_len); + + len = itp->hdr_len + itp->data_len; + + itp->data = kmalloc(len, GFP_KERNEL); + tx = (struct wsm_tx *)itp->data; + tx->hdr.len = itp->data_len + itp->hdr_len; + tx->hdr.id = __cpu_to_le16(0x0004 | 1 << 6); + tx->max_tx_rate = itp->rate; + tx->queue_id = 3; + tx->more = 0; + tx->flags = 0xc; + tx->packet_id = 0x55ff55; + tx->reserved = 0; + tx->expire_time = 1; + + if (itp->preamble == ITP_PREAMBLE_GREENFIELD) + tx->ht_tx_parameters = WSM_HT_TX_GREENFIELD; + else if (itp->preamble == ITP_PREAMBLE_MIXED) + tx->ht_tx_parameters = WSM_HT_TX_MIXED; + + hdr = (struct ieee80211_hdr_3addr *)&itp->data[sizeof(struct wsm_tx)]; + memset(hdr, 0, sizeof(*hdr)); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); + memcpy(hdr->addr1, da_addr, ETH_ALEN); + memcpy(hdr->addr2, priv->vif->addr, ETH_ALEN); + memcpy(hdr->addr3, da_addr, ETH_ALEN); + + cw1200_itp_fill_pattern(&itp->data[itp->hdr_len], + itp->data_len, itp->data_mode); + + cw1200_update_listening(priv, false); + priv->channel = &priv->hw->wiphy->bands[itp->band]->channels[itp->ch]; + WARN_ON(wsm_set_output_power(priv, itp->power)); + if (itp->preamble == ITP_PREAMBLE_SHORT || + itp->preamble == ITP_PREAMBLE_LONG) + WARN_ON(wsm_set_association_mode(priv, + &assoc_mode)); + wsm_set_bssid_filtering(priv, false); + cw1200_update_listening(priv, true); + + spin_lock_bh(&itp->tx_lock); + atomic_set(&itp->test_mode, TEST_MODE_TX_TEST); + atomic_set(&itp->awaiting_confirm, 0); + atomic_set(&itp->stop_tx, 0); + atomic_set(&priv->bh_tx, 1); + ktime_get_ts(&itp->last_sent); + wake_up(&priv->bh_wq); + spin_unlock_bh(&itp->tx_lock); +} + +void __cw1200_itp_tx_stop(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + spin_lock_bh(&itp->tx_lock); + kfree(itp->data); + itp->data = NULL; + atomic_set(&itp->test_mode, TEST_MODE_NO_TEST); + spin_unlock_bh(&itp->tx_lock); +} + +static void cw1200_itp_tx_stop(struct cw1200_common *priv) +{ + struct cw1200_itp *itp = &priv->debug->itp; + pr_debug("[ITP] TX stop\n"); + atomic_set(&itp->stop_tx, 1); + flush_workqueue(priv->workqueue); + + /* time for FW to confirm all tx requests */ + msleep(500); + + __cw1200_itp_tx_stop(priv); +} + +static int cw1200_print_fw_version(struct cw1200_common *priv, + u8 *buf, size_t len) +{ + return snprintf(buf, len, "%s %d.%d", + cw1200_fw_types[priv->wsm_caps.fw_type], + priv->wsm_caps.fw_ver, + priv->wsm_caps.fw_build); +} + +static void cw1200_itp_get_version(struct cw1200_common *priv, + enum cw1200_itp_version_type type) +{ + struct cw1200_itp *itp = &priv->debug->itp; + struct sk_buff *skb; + char buf[ITP_BUF_SIZE]; + size_t size = 0; + int len; + pr_debug("[ITP] print %s version\n", + type == ITP_CHIP_ID ? "chip" : "firmware"); + + len = snprintf(buf, ITP_BUF_SIZE, "2,"); + if (len <= 0) { + cw1200_itp_err(priv, -EINVAL, 40); + return; + } + size += len; + + switch (type) { + case ITP_CHIP_ID: + len = cw1200_print_fw_version(priv, buf+size, + ITP_BUF_SIZE - size); + + if (len <= 0) { + cw1200_itp_err(priv, -EINVAL, 41); + return; + } + size += len; + break; + case ITP_FW_VER: + len = snprintf(buf+size, ITP_BUF_SIZE - size, + "%d.%d", priv->wsm_caps.hw_id, + priv->wsm_caps.hw_subid); + if (len <= 0) { + cw1200_itp_err(priv, -EINVAL, 42); + return; + } + size += len; + break; + default: + cw1200_itp_err(priv, -EINVAL, 43); + break; + } + + len = snprintf(buf+size, ITP_BUF_SIZE-size, "\n"); + if (len <= 0) { + cw1200_itp_err(priv, -EINVAL, 44); + return; + } + size += len; + + skb = dev_alloc_skb(size); + if (!skb) { + cw1200_itp_err(priv, -ENOMEM, 45); + return; + } + + skb_trim(skb, 0); + skb_put(skb, size); + + memcpy(skb->data, buf, size); + skb_queue_tail(&itp->log_queue, skb); + wake_up(&itp->read_wait); +} + +int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, + size_t *tx_len, int *burst) +{ + struct cw1200_itp *itp; + struct timespec now; + int time_left_us; + + if (!priv->debug) + return 0; + + itp = &priv->debug->itp; + + if (!itp) + return 0; + + spin_lock_bh(&itp->tx_lock); + if (atomic_read(&itp->test_mode) != TEST_MODE_TX_TEST) + goto out; + + if (atomic_read(&itp->stop_tx)) + goto out; + + if (itp->number == 0) { + atomic_set(&itp->stop_tx, 1); + queue_delayed_work(priv->workqueue, &itp->tx_finish, HZ/10); + goto out; + } + + if (!itp->data) + goto out; + + if (priv->hw_bufs_used >= 2) { + if (!atomic_read(&priv->bh_rx)) + atomic_set(&priv->bh_rx, 1); + atomic_set(&priv->bh_tx, 1); + goto out; + } + + ktime_get_ts(&now); + time_left_us = (itp->last_sent.tv_sec - now.tv_sec)*1000000 + + (itp->last_sent.tv_nsec - now.tv_nsec)/1000 + + itp->interval_us; + + if (time_left_us > ITP_TIME_THRES_US) { + queue_delayed_work(priv->workqueue, &itp->tx_work, + ITP_US_TO_MS(time_left_us)*HZ/1000); + goto out; + } + + if (time_left_us > 50) + udelay(time_left_us); + + if (itp->number > 0) + itp->number--; + + *data = itp->data; + *tx_len = itp->data_len + itp->hdr_len; + + if (itp->data_mode == ITP_DATA_RANDOM) + cw1200_itp_fill_pattern(&itp->data[itp->hdr_len], + itp->data_len, itp->data_mode); + *burst = 2; + atomic_set(&priv->bh_tx, 1); + ktime_get_ts(&itp->last_sent); + atomic_add(1, &itp->awaiting_confirm); + spin_unlock_bh(&itp->tx_lock); + return 1; + +out: + spin_unlock_bh(&itp->tx_lock); + return 0; +} + +bool cw1200_itp_rxed(struct cw1200_common *priv, struct sk_buff *skb) +{ + struct cw1200_itp *itp = &priv->debug->itp; + struct ieee80211_rx_status *rx = IEEE80211_SKB_RXCB(skb); + int signal; + + if (atomic_read(&itp->test_mode) != TEST_MODE_RX_TEST) + return cw1200_is_itp(priv); + if (rx->freq != priv->channel->center_freq) + return true; + + signal = rx->signal; + itp->rx_cnt++; + itp->rx_rssi += signal; + if (itp->rx_rssi_min > rx->signal) + itp->rx_rssi_min = rx->signal; + if (itp->rx_rssi_max < rx->signal) + itp->rx_rssi_max = rx->signal; + + return true; +} + +void cw1200_itp_wake_up_tx(struct cw1200_common *priv) +{ + wake_up(&priv->debug->itp.write_wait); +} + +bool cw1200_itp_tx_running(struct cw1200_common *priv) +{ + if (atomic_read(&priv->debug->itp.awaiting_confirm) || + atomic_read(&priv->debug->itp.test_mode) == + TEST_MODE_TX_TEST) { + atomic_sub(1, &priv->debug->itp.awaiting_confirm); + return true; + } + return false; +} + +static void cw1200_itp_handle(struct cw1200_common *priv, + struct sk_buff *skb) +{ + struct cw1200_itp *itp = &priv->debug->itp; + const struct wiphy *wiphy = priv->hw->wiphy; + int cmd; + int ret; + + pr_debug("[ITP] <<< %s", skb->data); + if (sscanf(skb->data, "%d", &cmd) != 1) { + cw1200_itp_err(priv, -EINVAL, 1); + return; + } + + switch (cmd) { + case 1: /* RX test */ + if (atomic_read(&itp->test_mode)) { + cw1200_itp_err(priv, -EBUSY, 0); + return; + } + ret = sscanf(skb->data, "%d,%d,%d", + &cmd, &itp->band, &itp->ch); + if (ret != 3) { + cw1200_itp_err(priv, -EINVAL, ret + 1); + return; + } + if (itp->band >= 2) { + cw1200_itp_err(priv, -EINVAL, 2); + } else if (!wiphy->bands[itp->band]) { + cw1200_itp_err(priv, -EINVAL, 2); + } else if (itp->ch >= wiphy->bands[itp->band]->n_channels) { + cw1200_itp_err(priv, -EINVAL, 3); + } else { + cw1200_itp_rx_stats(priv); + cw1200_itp_rx_start(priv); + } + break; + case 2: /* RX stat */ + cw1200_itp_rx_stats(priv); + break; + case 3: /* RX/TX stop */ + if (atomic_read(&itp->test_mode) == TEST_MODE_RX_TEST) { + cw1200_itp_rx_stats(priv); + cw1200_itp_rx_stop(priv); + } else if (atomic_read(&itp->test_mode) == TEST_MODE_TX_TEST) { + cw1200_itp_tx_stop(priv); + } else { + cw1200_itp_err(priv, -EBUSY, 0); + } + break; + case 4: /* TX start */ + if (atomic_read(&itp->test_mode) != TEST_MODE_NO_TEST) { + cw1200_itp_err(priv, -EBUSY, 0); + return; + } + ret = sscanf(skb->data, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", + &cmd, &itp->band, &itp->ch, &itp->rate, + &itp->preamble, &itp->number, &itp->data_mode, + &itp->interval_us, &itp->power, &itp->data_len); + if (ret != 10) { + cw1200_itp_err(priv, -EINVAL, ret + 1); + return; + } + if (itp->band >= 2) { + cw1200_itp_err(priv, -EINVAL, 2); + } else if (!wiphy->bands[itp->band]) { + cw1200_itp_err(priv, -EINVAL, 2); + } else if (itp->ch >= wiphy->bands[itp->band]->n_channels) { + cw1200_itp_err(priv, -EINVAL, 3); + } else if (itp->rate >= 20) { + cw1200_itp_err(priv, -EINVAL, 4); + } else if (itp->preamble >= ITP_PREAMBLE_MAX) { + cw1200_itp_err(priv, -EINVAL, 5); + } else if (itp->data_mode >= ITP_DATA_MAX_MODE) { + cw1200_itp_err(priv, -EINVAL, 7); + } else if (itp->data_len < ITP_MIN_DATA_SIZE || + itp->data_len > (priv->wsm_caps.input_buffer_size - itp->hdr_len)) { + cw1200_itp_err(priv, -EINVAL, 8); + } else { + cw1200_itp_tx_start(priv); + } + break; + case 5: + cw1200_itp_get_version(priv, ITP_CHIP_ID); + break; + case 6: + cw1200_itp_get_version(priv, ITP_FW_VER); + break; + } +} + +static void cw1200_itp_err(struct cw1200_common *priv, + int err, int arg) +{ + struct cw1200_itp *itp = &priv->debug->itp; + struct sk_buff *skb; + static char buf[255]; + int len; + + len = snprintf(buf, sizeof(buf), "%d,%d\n", + err, arg); + if (len <= 0) + return; + + skb = dev_alloc_skb(len); + if (!skb) + return; + + skb_trim(skb, 0); + skb_put(skb, len); + + memcpy(skb->data, buf, len); + skb_queue_tail(&itp->log_queue, skb); + wake_up(&itp->read_wait); + + len = sprint_symbol(buf, + (unsigned long)__builtin_return_address(0)); + if (len <= 0) + return; + pr_debug("[ITP] error %d,%d from %s\n", + err, arg, buf); +} diff --git a/drivers/net/wireless/cw1200/itp.h b/drivers/net/wireless/cw1200/itp.h new file mode 100644 index 000000000000..1e9dfb7fcadc --- /dev/null +++ b/drivers/net/wireless/cw1200/itp.h @@ -0,0 +1,144 @@ +/* + * ITP code for ST-Ericsson CW1200 mac80211 driver + * + * Copyright (c) 2011, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_ITP_H_INCLUDED +#define CW1200_ITP_H_INCLUDED + +struct cw200_common; +struct wsm_tx_confirm; +struct dentry; + +#ifdef CONFIG_CW1200_ITP + +/*extern*/ struct ieee80211_channel; + +#define TEST_MODE_NO_TEST (0) +#define TEST_MODE_RX_TEST (1) +#define TEST_MODE_TX_TEST (2) +#define ITP_DEFAULT_DA_ADDR {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} +#define ITP_MIN_DATA_SIZE 6 +#define ITP_MAX_DATA_SIZE 1600 +#define ITP_TIME_THRES_US 10000 +#define ITP_US_TO_MS(x) ((x)/1000) +#define ITP_MS_TO_US(x) ((x)*1000) +#define ITP_BUF_SIZE 255 + + +enum cw1200_itp_data_modes { + ITP_DATA_ZEROS, + ITP_DATA_ONES, + ITP_DATA_ZERONES, + ITP_DATA_RANDOM, + ITP_DATA_MAX_MODE, +}; + +enum cw1200_itp_version_type { + ITP_CHIP_ID, + ITP_FW_VER, +}; + +enum cw1200_itp_preamble_type { + ITP_PREAMBLE_LONG, + ITP_PREAMBLE_SHORT, + ITP_PREAMBLE_OFDM, + ITP_PREAMBLE_MIXED, + ITP_PREAMBLE_GREENFIELD, + ITP_PREAMBLE_MAX, +}; + + +struct cw1200_itp { + struct cw1200_common *priv; + atomic_t open_count; + atomic_t awaiting_confirm; + struct sk_buff_head log_queue; + wait_queue_head_t read_wait; + wait_queue_head_t write_wait; + wait_queue_head_t close_wait; + struct ieee80211_channel *saved_channel; + atomic_t stop_tx; + struct delayed_work tx_work; + struct delayed_work tx_finish; + spinlock_t tx_lock; + struct timespec last_sent; + atomic_t test_mode; + int rx_cnt; + long rx_rssi; + int rx_rssi_max; + int rx_rssi_min; + unsigned band; + unsigned ch; + unsigned rate; + unsigned preamble; + unsigned int number; + unsigned data_mode; + int interval_us; + int power; + u8 *data; + int hdr_len; + int data_len; +}; + +int cw1200_itp_init(struct cw1200_common *priv); +void cw1200_itp_release(struct cw1200_common *priv); + +bool cw1200_is_itp(struct cw1200_common *priv); +bool cw1200_itp_rxed(struct cw1200_common *priv, struct sk_buff *skb); +void cw1200_itp_wake_up_tx(struct cw1200_common *priv); +int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, + size_t *tx_len, int *burst); +bool cw1200_itp_tx_running(struct cw1200_common *priv); + +#else /* CONFIG_CW1200_ITP */ + +static inline int cw1200_itp_init(struct cw1200_common *priv) +{ + return 0; +} + +static inline void cw1200_itp_release(struct cw1200_common *priv) +{ +} + +static inline bool cw1200_is_itp(struct cw1200_common *priv) +{ + return false; +} + +static inline bool cw1200_itp_rxed(struct cw1200_common *priv, + struct sk_buff *skb) +{ + return false; +} + + +static inline void cw1200_itp_consume_txed(struct cw1200_common *priv) +{ +} + +static inline void cw1200_itp_wake_up_tx(struct cw1200_common *priv) +{ +} + +static inline int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, + size_t *tx_len, int *burst) +{ + return 0; +} + +static inline bool cw1200_itp_tx_running(struct cw1200_common *priv) +{ + return false; +} + +#endif /* CONFIG_CW1200_ITP */ + +#endif /* CW1200_ITP_H_INCLUDED */ diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c new file mode 100644 index 000000000000..8426d3d7607e --- /dev/null +++ b/drivers/net/wireless/cw1200/main.c @@ -0,0 +1,618 @@ +/* + * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on: + * Copyright (c) 2006, Michael Wu + * Copyright (c) 2007-2009, Christian Lamparter + * Copyright 2008, Johannes Berg + * + * Based on: + * - the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * - stlc45xx driver + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cw1200.h" +#include "txrx.h" +#include "sbus.h" +#include "fwio.h" +#include "hwio.h" +#include "bh.h" +#include "sta.h" +#include "scan.h" +#include "debug.h" +#include "pm.h" + +MODULE_AUTHOR("Dmitry Tarnyagin "); +MODULE_DESCRIPTION("Softmac ST-Ericsson CW1200 common code"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("cw1200_core"); + +/* Accept MAC address of the form macaddr=0x00,0x80,0xE1,0x30,0x40,0x50 */ +static u8 cw1200_mac_template[ETH_ALEN] = {0x02, 0x80, 0xe1, 0x00, 0x00, 0x00}; +module_param_array_named(macaddr, cw1200_mac_template, byte, NULL, S_IRUGO); +MODULE_PARM_DESC(macaddr, "Override platform_data MAC address"); + +static char *cw1200_sdd_path; +module_param(cw1200_sdd_path, charp, 0644); +MODULE_PARM_DESC(cw1200_sdd_path, "Override platform_data SDD file"); +static int cw1200_refclk; +module_param(cw1200_refclk, int, 0644); +MODULE_PARM_DESC(cw1200_refclk, "Override platform_data reference clock"); + +int cw1200_power_mode = wsm_power_mode_quiescent; +module_param(cw1200_power_mode, int, 0644); +MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode. 0 == active, 1 == doze, 2 == quiescent (default)"); + +#ifdef CONFIG_CW1200_ETF +int etf_mode; +module_param(etf_mode, int, 0644); +MODULE_PARM_DESC(etf_mode, "Enable EngineeringTestingFramework operation"); +#endif + +#define RATETAB_ENT(_rate, _rateid, _flags) \ + { \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ + } + +static struct ieee80211_rate cw1200_rates[] = { + RATETAB_ENT(10, 0, 0), + RATETAB_ENT(20, 1, 0), + RATETAB_ENT(55, 2, 0), + RATETAB_ENT(110, 3, 0), + RATETAB_ENT(60, 6, 0), + RATETAB_ENT(90, 7, 0), + RATETAB_ENT(120, 8, 0), + RATETAB_ENT(180, 9, 0), + RATETAB_ENT(240, 10, 0), + RATETAB_ENT(360, 11, 0), + RATETAB_ENT(480, 12, 0), + RATETAB_ENT(540, 13, 0), +}; + +static struct ieee80211_rate cw1200_mcs_rates[] = { + RATETAB_ENT(65, 14, IEEE80211_TX_RC_MCS), + RATETAB_ENT(130, 15, IEEE80211_TX_RC_MCS), + RATETAB_ENT(195, 16, IEEE80211_TX_RC_MCS), + RATETAB_ENT(260, 17, IEEE80211_TX_RC_MCS), + RATETAB_ENT(390, 18, IEEE80211_TX_RC_MCS), + RATETAB_ENT(520, 19, IEEE80211_TX_RC_MCS), + RATETAB_ENT(585, 20, IEEE80211_TX_RC_MCS), + RATETAB_ENT(650, 21, IEEE80211_TX_RC_MCS), +}; + +#define cw1200_a_rates (cw1200_rates + 4) +#define cw1200_a_rates_size (ARRAY_SIZE(cw1200_rates) - 4) +#define cw1200_g_rates (cw1200_rates + 0) +#define cw1200_g_rates_size (ARRAY_SIZE(cw1200_rates)) +#define cw1200_n_rates (cw1200_mcs_rates) +#define cw1200_n_rates_size (ARRAY_SIZE(cw1200_mcs_rates)) + + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel cw1200_2ghz_chantable[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static struct ieee80211_channel cw1200_5ghz_chantable[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +static struct ieee80211_supported_band cw1200_band_2ghz = { + .channels = cw1200_2ghz_chantable, + .n_channels = ARRAY_SIZE(cw1200_2ghz_chantable), + .bitrates = cw1200_g_rates, + .n_bitrates = cw1200_g_rates_size, + .ht_cap = { + .cap = IEEE80211_HT_CAP_GRN_FLD | + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | + IEEE80211_HT_CAP_MAX_AMSDU, + .ht_supported = 1, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, + .mcs = { + .rx_mask[0] = 0xFF, + .rx_highest = __cpu_to_le16(0x41), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + }, +}; + +static struct ieee80211_supported_band cw1200_band_5ghz = { + .channels = cw1200_5ghz_chantable, + .n_channels = ARRAY_SIZE(cw1200_5ghz_chantable), + .bitrates = cw1200_a_rates, + .n_bitrates = cw1200_a_rates_size, + .ht_cap = { + .cap = IEEE80211_HT_CAP_GRN_FLD | + (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | + IEEE80211_HT_CAP_MAX_AMSDU, + .ht_supported = 1, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, + .mcs = { + .rx_mask[0] = 0xFF, + .rx_highest = __cpu_to_le16(0x41), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + }, +}; + +static const unsigned long cw1200_ttl[] = { + 1 * HZ, /* VO */ + 2 * HZ, /* VI */ + 5 * HZ, /* BE */ + 10 * HZ /* BK */ +}; + +static const struct ieee80211_ops cw1200_ops = { + .start = cw1200_start, + .stop = cw1200_stop, + .add_interface = cw1200_add_interface, + .remove_interface = cw1200_remove_interface, + .change_interface = cw1200_change_interface, + .tx = cw1200_tx, + .hw_scan = cw1200_hw_scan, + .set_tim = cw1200_set_tim, + .sta_notify = cw1200_sta_notify, + .sta_add = cw1200_sta_add, + .sta_remove = cw1200_sta_remove, + .set_key = cw1200_set_key, + .set_rts_threshold = cw1200_set_rts_threshold, + .config = cw1200_config, + .bss_info_changed = cw1200_bss_info_changed, + .prepare_multicast = cw1200_prepare_multicast, + .configure_filter = cw1200_configure_filter, + .conf_tx = cw1200_conf_tx, + .get_stats = cw1200_get_stats, + .ampdu_action = cw1200_ampdu_action, + .flush = cw1200_flush, + .suspend = cw1200_wow_suspend, + .resume = cw1200_wow_resume, + /* Intentionally not offloaded: */ + /*.channel_switch = cw1200_channel_switch, */ + /*.remain_on_channel = cw1200_remain_on_channel, */ + /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel, */ +}; + +int cw1200_ba_rx_tids = -1; +int cw1200_ba_tx_tids = -1; +module_param(cw1200_ba_rx_tids, int, 0644); +module_param(cw1200_ba_tx_tids, int, 0644); +MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs"); +MODULE_PARM_DESC(cw1200_ba_tx_tids, "Block ACK TX TIDs"); + +static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, + const bool have_5ghz) +{ + int i, band; + struct ieee80211_hw *hw; + struct cw1200_common *priv; + + hw = ieee80211_alloc_hw(sizeof(struct cw1200_common), &cw1200_ops); + if (!hw) + return NULL; + + priv = hw->priv; + priv->hw = hw; + priv->hw_type = -1; + priv->mode = NL80211_IFTYPE_UNSPECIFIED; + priv->rates = cw1200_rates; /* TODO: fetch from FW */ + priv->mcs_rates = cw1200_n_rates; + if (cw1200_ba_rx_tids != -1) + priv->ba_rx_tid_mask = cw1200_ba_rx_tids; + else + priv->ba_rx_tid_mask = 0xFF; /* Enable RX BLKACK for all TIDs */ + if (cw1200_ba_tx_tids != -1) + priv->ba_tx_tid_mask = cw1200_ba_tx_tids; + else + priv->ba_tx_tid_mask = 0xff; /* Enable TX BLKACK for all TIDs */ + + hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | + IEEE80211_HW_SUPPORTS_UAPSD | + IEEE80211_HW_CONNECTION_MONITOR | + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | + IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC; + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); + + /* Support only for limited wowlan functionalities */ + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | + WIPHY_WOWLAN_DISCONNECT; + hw->wiphy->wowlan.n_patterns = 0; + + hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; + + hw->channel_change_time = 1000; /* TODO: find actual value */ + hw->queues = 4; + + priv->rts_threshold = -1; + + hw->max_rates = 8; + hw->max_rate_tries = 15; + hw->extra_tx_headroom = WSM_TX_EXTRA_HEADROOM + + 8; /* TKIP IV */ + + hw->sta_data_size = sizeof(struct cw1200_sta_priv); + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &cw1200_band_2ghz; + if (have_5ghz) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &cw1200_band_5ghz; + + /* Channel params have to be cleared before registering wiphy again */ + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + struct ieee80211_supported_band *sband = hw->wiphy->bands[band]; + if (!sband) + continue; + for (i = 0; i < sband->n_channels; i++) { + sband->channels[i].flags = 0; + sband->channels[i].max_antenna_gain = 0; + sband->channels[i].max_power = 30; + } + } + + hw->wiphy->max_scan_ssids = 2; + hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + + if (macaddr) + SET_IEEE80211_PERM_ADDR(hw, (u8 *)macaddr); + else + SET_IEEE80211_PERM_ADDR(hw, cw1200_mac_template); + + /* Fix up mac address if necessary */ + if (hw->wiphy->perm_addr[3] == 0 && + hw->wiphy->perm_addr[4] == 0 && + hw->wiphy->perm_addr[5] == 0) { + get_random_bytes(&hw->wiphy->perm_addr[3], 3); + } + + mutex_init(&priv->wsm_cmd_mux); + mutex_init(&priv->conf_mutex); + priv->workqueue = create_singlethread_workqueue("cw1200_wq"); + sema_init(&priv->scan.lock, 1); + INIT_WORK(&priv->scan.work, cw1200_scan_work); + INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work); + INIT_DELAYED_WORK(&priv->scan.timeout, cw1200_scan_timeout); + INIT_DELAYED_WORK(&priv->clear_recent_scan_work, + cw1200_clear_recent_scan_work); + INIT_DELAYED_WORK(&priv->join_timeout, cw1200_join_timeout); + INIT_WORK(&priv->unjoin_work, cw1200_unjoin_work); + INIT_WORK(&priv->join_complete_work, cw1200_join_complete_work); + INIT_WORK(&priv->wep_key_work, cw1200_wep_key_work); + INIT_WORK(&priv->tx_policy_upload_work, tx_policy_upload_work); + spin_lock_init(&priv->event_queue_lock); + INIT_LIST_HEAD(&priv->event_queue); + INIT_WORK(&priv->event_handler, cw1200_event_handler); + INIT_DELAYED_WORK(&priv->bss_loss_work, cw1200_bss_loss_work); + INIT_WORK(&priv->bss_params_work, cw1200_bss_params_work); + spin_lock_init(&priv->bss_loss_lock); + spin_lock_init(&priv->ps_state_lock); + INIT_WORK(&priv->set_cts_work, cw1200_set_cts_work); + INIT_WORK(&priv->set_tim_work, cw1200_set_tim_work); + INIT_WORK(&priv->multicast_start_work, cw1200_multicast_start_work); + INIT_WORK(&priv->multicast_stop_work, cw1200_multicast_stop_work); + INIT_WORK(&priv->link_id_work, cw1200_link_id_work); + INIT_DELAYED_WORK(&priv->link_id_gc_work, cw1200_link_id_gc_work); + INIT_WORK(&priv->linkid_reset_work, cw1200_link_id_reset); + INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work); + INIT_WORK(&priv->set_beacon_wakeup_period_work, + cw1200_set_beacon_wakeup_period_work); + init_timer(&priv->mcast_timeout); + priv->mcast_timeout.data = (unsigned long)priv; + priv->mcast_timeout.function = cw1200_mcast_timeout; + + if (cw1200_queue_stats_init(&priv->tx_queue_stats, + CW1200_LINK_ID_MAX, + cw1200_skb_dtor, + priv)) { + ieee80211_free_hw(hw); + return NULL; + } + + for (i = 0; i < 4; ++i) { + if (cw1200_queue_init(&priv->tx_queue[i], + &priv->tx_queue_stats, i, 16, + cw1200_ttl[i])) { + for (; i > 0; i--) + cw1200_queue_deinit(&priv->tx_queue[i - 1]); + cw1200_queue_stats_deinit(&priv->tx_queue_stats); + ieee80211_free_hw(hw); + return NULL; + } + } + + init_waitqueue_head(&priv->channel_switch_done); + init_waitqueue_head(&priv->wsm_cmd_wq); + init_waitqueue_head(&priv->wsm_startup_done); + init_waitqueue_head(&priv->ps_mode_switch_done); + wsm_buf_init(&priv->wsm_cmd_buf); + spin_lock_init(&priv->wsm_cmd.lock); + priv->wsm_cmd.done = 1; + tx_policy_init(priv); + + return hw; +} + +static int cw1200_register_common(struct ieee80211_hw *dev) +{ + struct cw1200_common *priv = dev->priv; + int err; + +#ifdef CONFIG_CW1200_ETF + if (etf_mode) + goto done; +#endif + + err = cw1200_pm_init(&priv->pm_state, priv); + if (err) { + pr_err("Cannot init PM. (%d).\n", + err); + return err; + } + + err = ieee80211_register_hw(dev); + if (err) { + pr_err("Cannot register device (%d).\n", + err); + cw1200_pm_deinit(&priv->pm_state); + return err; + } + +#ifdef CONFIG_CW1200_ETF +done: +#endif + cw1200_debug_init(priv); + + pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy)); + return 0; +} + +static void cw1200_free_common(struct ieee80211_hw *dev) +{ + ieee80211_free_hw(dev); +} + +static void cw1200_unregister_common(struct ieee80211_hw *dev) +{ + struct cw1200_common *priv = dev->priv; + int i; + +#ifdef CONFIG_CW1200_ETF + if (!etf_mode) { +#endif + ieee80211_unregister_hw(dev); +#ifdef CONFIG_CW1200_ETF + } +#endif + + del_timer_sync(&priv->mcast_timeout); + cw1200_unregister_bh(priv); + + cw1200_debug_release(priv); + + mutex_destroy(&priv->conf_mutex); + + wsm_buf_deinit(&priv->wsm_cmd_buf); + + destroy_workqueue(priv->workqueue); + priv->workqueue = NULL; + + if (priv->sdd) { + release_firmware(priv->sdd); + priv->sdd = NULL; + } + + for (i = 0; i < 4; ++i) + cw1200_queue_deinit(&priv->tx_queue[i]); + + cw1200_queue_stats_deinit(&priv->tx_queue_stats); + cw1200_pm_deinit(&priv->pm_state); +} + +/* Clock is in KHz */ +u32 cw1200_dpll_from_clk(u16 clk_khz) +{ + switch (clk_khz) { + case 0x32C8: /* 13000 KHz */ + return 0x1D89D241; + case 0x3E80: /* 16000 KHz */ + return 0x000001E1; + case 0x41A0: /* 16800 KHz */ + return 0x124931C1; + case 0x4B00: /* 19200 KHz */ + return 0x00000191; + case 0x5DC0: /* 24000 KHz */ + return 0x00000141; + case 0x6590: /* 26000 KHz */ + return 0x0EC4F121; + case 0x8340: /* 33600 KHz */ + return 0x092490E1; + case 0x9600: /* 38400 KHz */ + return 0x100010C1; + case 0x9C40: /* 40000 KHz */ + return 0x000000C1; + case 0xBB80: /* 48000 KHz */ + return 0x000000A1; + case 0xCB20: /* 52000 KHz */ + return 0x07627091; + default: + pr_err("Unknown Refclk freq (0x%04x), using 2600KHz\n", + clk_khz); + return 0x0EC4F121; + } +} + +int cw1200_core_probe(const struct sbus_ops *sbus_ops, + struct sbus_priv *sbus, + struct device *pdev, + struct cw1200_common **core, + int ref_clk, const u8 *macaddr, + const char *sdd_path, bool have_5ghz) +{ + int err = -EINVAL; + struct ieee80211_hw *dev; + struct cw1200_common *priv; + struct wsm_operational_mode mode = { + .power_mode = cw1200_power_mode, + .disable_more_flag_usage = true, + }; + + dev = cw1200_init_common(macaddr, have_5ghz); + if (!dev) + goto err; + + priv = dev->priv; + priv->hw_refclk = ref_clk; + if (cw1200_refclk) + priv->hw_refclk = cw1200_refclk; + + priv->sdd_path = (char *)sdd_path; + if (cw1200_sdd_path) + priv->sdd_path = cw1200_sdd_path; + + priv->sbus_ops = sbus_ops; + priv->sbus_priv = sbus; + priv->pdev = pdev; + SET_IEEE80211_DEV(priv->hw, pdev); + + /* Pass struct cw1200_common back up */ + *core = priv; + + err = cw1200_register_bh(priv); + if (err) + goto err1; + +#ifdef CONFIG_CW1200_ETF + if (etf_mode) + goto skip_fw; +#endif + + err = cw1200_load_firmware(priv); + if (err) + goto err2; + + if (wait_event_interruptible_timeout(priv->wsm_startup_done, + priv->firmware_ready, + 3*HZ) <= 0) { + /* TODO: Need to find how to reset device + in QUEUE mode properly. + */ + pr_err("Timeout waiting on device startup\n"); + err = -ETIMEDOUT; + goto err2; + } + + /* Set low-power mode. */ + wsm_set_operational_mode(priv, &mode); + + /* Enable multi-TX confirmation */ + wsm_use_multi_tx_conf(priv, true); + +#ifdef CONFIG_CW1200_ETF +skip_fw: +#endif + err = cw1200_register_common(dev); + if (err) + goto err2; + + return err; + +err2: + cw1200_unregister_bh(priv); +err1: + cw1200_free_common(dev); +err: + *core = NULL; + return err; +} +EXPORT_SYMBOL_GPL(cw1200_core_probe); + +void cw1200_core_release(struct cw1200_common *self) +{ + /* Disable device interrupts */ + self->sbus_ops->lock(self->sbus_priv); + __cw1200_irq_enable(self, 0); + self->sbus_ops->unlock(self->sbus_priv); + + /* And then clean up */ + cw1200_unregister_common(self->hw); + cw1200_free_common(self->hw); + return; +} +EXPORT_SYMBOL_GPL(cw1200_core_release); diff --git a/drivers/net/wireless/cw1200/pm.c b/drivers/net/wireless/cw1200/pm.c new file mode 100644 index 000000000000..79edfb93b292 --- /dev/null +++ b/drivers/net/wireless/cw1200/pm.c @@ -0,0 +1,367 @@ +/* + * Mac80211 power management API for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2011, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include "cw1200.h" +#include "pm.h" +#include "sta.h" +#include "bh.h" +#include "sbus.h" + +#define CW1200_BEACON_SKIPPING_MULTIPLIER 3 + +struct cw1200_udp_port_filter { + struct wsm_udp_port_filter_hdr hdr; + /* Up to 4 filters are allowed. */ + struct wsm_udp_port_filter filters[WSM_MAX_FILTER_ELEMENTS]; +} __packed; + +struct cw1200_ether_type_filter { + struct wsm_ether_type_filter_hdr hdr; + /* Up to 4 filters are allowed. */ + struct wsm_ether_type_filter filters[WSM_MAX_FILTER_ELEMENTS]; +} __packed; + +static struct cw1200_udp_port_filter cw1200_udp_port_filter_on = { + .hdr.num = 2, + .filters = { + [0] = { + .action = WSM_FILTER_ACTION_FILTER_OUT, + .type = WSM_FILTER_PORT_TYPE_DST, + .port = __cpu_to_le16(67), /* DHCP Bootps */ + }, + [1] = { + .action = WSM_FILTER_ACTION_FILTER_OUT, + .type = WSM_FILTER_PORT_TYPE_DST, + .port = __cpu_to_le16(68), /* DHCP Bootpc */ + }, + } +}; + +static struct wsm_udp_port_filter_hdr cw1200_udp_port_filter_off = { + .num = 0, +}; + +#ifndef ETH_P_WAPI +#define ETH_P_WAPI 0x88B4 +#endif + +static struct cw1200_ether_type_filter cw1200_ether_type_filter_on = { + .hdr.num = 4, + .filters = { + [0] = { + .action = WSM_FILTER_ACTION_FILTER_IN, + .type = __cpu_to_le16(ETH_P_IP), + }, + [1] = { + .action = WSM_FILTER_ACTION_FILTER_IN, + .type = __cpu_to_le16(ETH_P_PAE), + }, + [2] = { + .action = WSM_FILTER_ACTION_FILTER_IN, + .type = __cpu_to_le16(ETH_P_WAPI), + }, + [3] = { + .action = WSM_FILTER_ACTION_FILTER_IN, + .type = __cpu_to_le16(ETH_P_ARP), + }, + }, +}; + +static struct wsm_ether_type_filter_hdr cw1200_ether_type_filter_off = { + .num = 0, +}; + +/* private */ +struct cw1200_suspend_state { + unsigned long bss_loss_tmo; + unsigned long join_tmo; + unsigned long direct_probe; + unsigned long link_id_gc; + bool beacon_skipping; + u8 prev_ps_mode; +}; + +static void cw1200_pm_stay_awake_tmo(unsigned long arg) +{ + /* XXX what's the point of this ? */ +} + +int cw1200_pm_init(struct cw1200_pm_state *pm, + struct cw1200_common *priv) +{ + spin_lock_init(&pm->lock); + + init_timer(&pm->stay_awake); + pm->stay_awake.data = (unsigned long)pm; + pm->stay_awake.function = cw1200_pm_stay_awake_tmo; + + return 0; +} + +void cw1200_pm_deinit(struct cw1200_pm_state *pm) +{ + del_timer_sync(&pm->stay_awake); +} + +void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, + unsigned long tmo) +{ + long cur_tmo; + spin_lock_bh(&pm->lock); + cur_tmo = pm->stay_awake.expires - jiffies; + if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo) + mod_timer(&pm->stay_awake, jiffies + tmo); + spin_unlock_bh(&pm->lock); +} + +static long cw1200_suspend_work(struct delayed_work *work) +{ + int ret = cancel_delayed_work(work); + long tmo; + if (ret > 0) { + /* Timer is pending */ + tmo = work->timer.expires - jiffies; + if (tmo < 0) + tmo = 0; + } else { + tmo = -1; + } + return tmo; +} + +static int cw1200_resume_work(struct cw1200_common *priv, + struct delayed_work *work, + unsigned long tmo) +{ + if ((long)tmo < 0) + return 1; + + return queue_delayed_work(priv->workqueue, work, tmo); +} + +int cw1200_can_suspend(struct cw1200_common *priv) +{ + if (atomic_read(&priv->bh_rx)) { + wiphy_dbg(priv->hw->wiphy, "Suspend interrupted.\n"); + return 0; + } + return 1; +} +EXPORT_SYMBOL_GPL(cw1200_can_suspend); + +int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) +{ + struct cw1200_common *priv = hw->priv; + struct cw1200_pm_state *pm_state = &priv->pm_state; + struct cw1200_suspend_state *state; + int ret; + + spin_lock_bh(&pm_state->lock); + ret = timer_pending(&pm_state->stay_awake); + spin_unlock_bh(&pm_state->lock); + if (ret) + return -EAGAIN; + + /* Do not suspend when datapath is not idle */ + if (priv->tx_queue_stats.num_queued) + return -EBUSY; + + /* Make sure there is no configuration requests in progress. */ + if (!mutex_trylock(&priv->conf_mutex)) + return -EBUSY; + + /* Ensure pending operations are done. + * Note also that wow_suspend must return in ~2.5sec, before + * watchdog is triggered. + */ + if (priv->channel_switch_in_progress) + goto revert1; + + /* Do not suspend when join is pending */ + if (priv->join_pending) + goto revert1; + + /* Do not suspend when scanning */ + if (down_trylock(&priv->scan.lock)) + goto revert1; + + /* Lock TX. */ + wsm_lock_tx_async(priv); + + /* Wait to avoid possible race with bh code. + * But do not wait too long... + */ + if (wait_event_timeout(priv->bh_evt_wq, + !priv->hw_bufs_used, HZ / 10) <= 0) + goto revert2; + + /* Set UDP filter */ + wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_on.hdr); + + /* Set ethernet frame type filter */ + wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_on.hdr); + + /* Allocate state */ + state = kzalloc(sizeof(struct cw1200_suspend_state), GFP_KERNEL); + if (!state) + goto revert3; + + /* Change to legacy PS while going to suspend */ + if (!priv->vif->p2p && + priv->join_status == CW1200_JOIN_STATUS_STA && + priv->powersave_mode.mode != WSM_PSM_PS) { + state->prev_ps_mode = priv->powersave_mode.mode; + priv->powersave_mode.mode = WSM_PSM_PS; + cw1200_set_pm(priv, &priv->powersave_mode); + if (wait_event_interruptible_timeout(priv->ps_mode_switch_done, + !priv->ps_mode_switch_in_progress, 1*HZ) <= 0) { + goto revert3; + } + } + + /* Store delayed work states. */ + state->bss_loss_tmo = + cw1200_suspend_work(&priv->bss_loss_work); + state->join_tmo = + cw1200_suspend_work(&priv->join_timeout); + state->direct_probe = + cw1200_suspend_work(&priv->scan.probe_work); + state->link_id_gc = + cw1200_suspend_work(&priv->link_id_gc_work); + + cancel_delayed_work_sync(&priv->clear_recent_scan_work); + atomic_set(&priv->recent_scan, 0); + + /* Enable beacon skipping */ + if (priv->join_status == CW1200_JOIN_STATUS_STA && + priv->join_dtim_period && + !priv->has_multicast_subscription) { + state->beacon_skipping = true; + wsm_set_beacon_wakeup_period(priv, + priv->join_dtim_period, + CW1200_BEACON_SKIPPING_MULTIPLIER * priv->join_dtim_period); + } + + /* Stop serving thread */ + if (cw1200_bh_suspend(priv)) + goto revert4; + + ret = timer_pending(&priv->mcast_timeout); + if (ret) + goto revert5; + + /* Store suspend state */ + pm_state->suspend_state = state; + + /* Enable IRQ wake */ + ret = priv->sbus_ops->power_mgmt(priv->sbus_priv, true); + if (ret) { + wiphy_err(priv->hw->wiphy, + "PM request failed: %d. WoW is disabled.\n", ret); + cw1200_wow_resume(hw); + return -EBUSY; + } + + /* Force resume if event is coming from the device. */ + if (atomic_read(&priv->bh_rx)) { + cw1200_wow_resume(hw); + return -EAGAIN; + } + + return 0; + +revert5: + WARN_ON(cw1200_bh_resume(priv)); +revert4: + cw1200_resume_work(priv, &priv->bss_loss_work, + state->bss_loss_tmo); + cw1200_resume_work(priv, &priv->join_timeout, + state->join_tmo); + cw1200_resume_work(priv, &priv->scan.probe_work, + state->direct_probe); + cw1200_resume_work(priv, &priv->link_id_gc_work, + state->link_id_gc); + kfree(state); +revert3: + wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off); + wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off); +revert2: + wsm_unlock_tx(priv); + up(&priv->scan.lock); +revert1: + mutex_unlock(&priv->conf_mutex); + return -EBUSY; +} + +int cw1200_wow_resume(struct ieee80211_hw *hw) +{ + struct cw1200_common *priv = hw->priv; + struct cw1200_pm_state *pm_state = &priv->pm_state; + struct cw1200_suspend_state *state; + + state = pm_state->suspend_state; + pm_state->suspend_state = NULL; + + /* Disable IRQ wake */ + priv->sbus_ops->power_mgmt(priv->sbus_priv, false); + + /* Scan.lock must be released before BH is resumed other way + * in case when BSS_LOST command arrived the processing of the + * command will be delayed. + */ + up(&priv->scan.lock); + + /* Resume BH thread */ + WARN_ON(cw1200_bh_resume(priv)); + + /* Restores previous PS mode */ + if (!priv->vif->p2p && priv->join_status == CW1200_JOIN_STATUS_STA) { + priv->powersave_mode.mode = state->prev_ps_mode; + cw1200_set_pm(priv, &priv->powersave_mode); + } + + if (state->beacon_skipping) { + wsm_set_beacon_wakeup_period(priv, priv->beacon_int * + priv->join_dtim_period > + MAX_BEACON_SKIP_TIME_MS ? 1 : + priv->join_dtim_period, 0); + state->beacon_skipping = false; + } + + /* Resume delayed work */ + cw1200_resume_work(priv, &priv->bss_loss_work, + state->bss_loss_tmo); + cw1200_resume_work(priv, &priv->join_timeout, + state->join_tmo); + cw1200_resume_work(priv, &priv->scan.probe_work, + state->direct_probe); + cw1200_resume_work(priv, &priv->link_id_gc_work, + state->link_id_gc); + + /* Remove UDP port filter */ + wsm_set_udp_port_filter(priv, &cw1200_udp_port_filter_off); + + /* Remove ethernet frame type filter */ + wsm_set_ether_type_filter(priv, &cw1200_ether_type_filter_off); + + /* Unlock datapath */ + wsm_unlock_tx(priv); + + /* Unlock configuration mutex */ + mutex_unlock(&priv->conf_mutex); + + /* Free memory */ + kfree(state); + + return 0; +} diff --git a/drivers/net/wireless/cw1200/pm.h b/drivers/net/wireless/cw1200/pm.h new file mode 100644 index 000000000000..516d9671dd1e --- /dev/null +++ b/drivers/net/wireless/cw1200/pm.h @@ -0,0 +1,38 @@ +/* + * Mac80211 power management interface for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2011, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef PM_H_INCLUDED +#define PM_H_INCLUDED + +/* ******************************************************************** */ +/* mac80211 API */ + +/* extern */ struct cw1200_common; +/* private */ struct cw1200_suspend_state; + +struct cw1200_pm_state { + struct cw1200_suspend_state *suspend_state; + struct timer_list stay_awake; + struct platform_device *pm_dev; + spinlock_t lock; /* Protect access */ +}; + +int cw1200_pm_init(struct cw1200_pm_state *pm, + struct cw1200_common *priv); +void cw1200_pm_deinit(struct cw1200_pm_state *pm); +void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, + unsigned long tmo); +int cw1200_wow_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan); +int cw1200_wow_resume(struct ieee80211_hw *hw); +int cw1200_can_suspend(struct cw1200_common *priv); + +#endif diff --git a/drivers/net/wireless/cw1200/queue.c b/drivers/net/wireless/cw1200/queue.c new file mode 100644 index 000000000000..8510454d5db1 --- /dev/null +++ b/drivers/net/wireless/cw1200/queue.c @@ -0,0 +1,583 @@ +/* + * O(1) TX queue with built-in allocator for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include "queue.h" +#include "cw1200.h" +#include "debug.h" + +/* private */ struct cw1200_queue_item +{ + struct list_head head; + struct sk_buff *skb; + u32 packet_id; + unsigned long queue_timestamp; + unsigned long xmit_timestamp; + struct cw1200_txpriv txpriv; + u8 generation; +}; + +static inline void __cw1200_queue_lock(struct cw1200_queue *queue) +{ + struct cw1200_queue_stats *stats = queue->stats; + if (queue->tx_locked_cnt++ == 0) { + pr_debug("[TX] Queue %d is locked.\n", + queue->queue_id); + ieee80211_stop_queue(stats->priv->hw, queue->queue_id); + } +} + +static inline void __cw1200_queue_unlock(struct cw1200_queue *queue) +{ + struct cw1200_queue_stats *stats = queue->stats; + BUG_ON(!queue->tx_locked_cnt); + if (--queue->tx_locked_cnt == 0) { + pr_debug("[TX] Queue %d is unlocked.\n", + queue->queue_id); + ieee80211_wake_queue(stats->priv->hw, queue->queue_id); + } +} + +static inline void cw1200_queue_parse_id(u32 packet_id, u8 *queue_generation, + u8 *queue_id, u8 *item_generation, + u8 *item_id) +{ + *item_id = (packet_id >> 0) & 0xFF; + *item_generation = (packet_id >> 8) & 0xFF; + *queue_id = (packet_id >> 16) & 0xFF; + *queue_generation = (packet_id >> 24) & 0xFF; +} + +static inline u32 cw1200_queue_mk_packet_id(u8 queue_generation, u8 queue_id, + u8 item_generation, u8 item_id) +{ + return ((u32)item_id << 0) | + ((u32)item_generation << 8) | + ((u32)queue_id << 16) | + ((u32)queue_generation << 24); +} + +static void cw1200_queue_post_gc(struct cw1200_queue_stats *stats, + struct list_head *gc_list) +{ + struct cw1200_queue_item *item, *tmp; + + list_for_each_entry_safe(item, tmp, gc_list, head) { + list_del(&item->head); + stats->skb_dtor(stats->priv, item->skb, &item->txpriv); + kfree(item); + } +} + +static void cw1200_queue_register_post_gc(struct list_head *gc_list, + struct cw1200_queue_item *item) +{ + struct cw1200_queue_item *gc_item; + gc_item = kmalloc(sizeof(struct cw1200_queue_item), + GFP_ATOMIC); + BUG_ON(!gc_item); + memcpy(gc_item, item, sizeof(struct cw1200_queue_item)); + list_add_tail(&gc_item->head, gc_list); +} + +static void __cw1200_queue_gc(struct cw1200_queue *queue, + struct list_head *head, + bool unlock) +{ + struct cw1200_queue_stats *stats = queue->stats; + struct cw1200_queue_item *item = NULL, *tmp; + bool wakeup_stats = false; + + list_for_each_entry_safe(item, tmp, &queue->queue, head) { + if (jiffies - item->queue_timestamp < queue->ttl) + break; + --queue->num_queued; + --queue->link_map_cache[item->txpriv.link_id]; + spin_lock_bh(&stats->lock); + --stats->num_queued; + if (!--stats->link_map_cache[item->txpriv.link_id]) + wakeup_stats = true; + spin_unlock_bh(&stats->lock); + cw1200_debug_tx_ttl(stats->priv); + cw1200_queue_register_post_gc(head, item); + item->skb = NULL; + list_move_tail(&item->head, &queue->free_pool); + } + + if (wakeup_stats) + wake_up(&stats->wait_link_id_empty); + + if (queue->overfull) { + if (queue->num_queued <= (queue->capacity >> 1)) { + queue->overfull = false; + if (unlock) + __cw1200_queue_unlock(queue); + } else if (item) { + unsigned long tmo = item->queue_timestamp + queue->ttl; + mod_timer(&queue->gc, tmo); + cw1200_pm_stay_awake(&stats->priv->pm_state, + tmo - jiffies); + } + } +} + +static void cw1200_queue_gc(unsigned long arg) +{ + LIST_HEAD(list); + struct cw1200_queue *queue = + (struct cw1200_queue *)arg; + + spin_lock_bh(&queue->lock); + __cw1200_queue_gc(queue, &list, true); + spin_unlock_bh(&queue->lock); + cw1200_queue_post_gc(queue->stats, &list); +} + +int cw1200_queue_stats_init(struct cw1200_queue_stats *stats, + size_t map_capacity, + cw1200_queue_skb_dtor_t skb_dtor, + struct cw1200_common *priv) +{ + memset(stats, 0, sizeof(*stats)); + stats->map_capacity = map_capacity; + stats->skb_dtor = skb_dtor; + stats->priv = priv; + spin_lock_init(&stats->lock); + init_waitqueue_head(&stats->wait_link_id_empty); + + stats->link_map_cache = kzalloc(sizeof(int) * map_capacity, + GFP_KERNEL); + if (!stats->link_map_cache) + return -ENOMEM; + + return 0; +} + +int cw1200_queue_init(struct cw1200_queue *queue, + struct cw1200_queue_stats *stats, + u8 queue_id, + size_t capacity, + unsigned long ttl) +{ + size_t i; + + memset(queue, 0, sizeof(*queue)); + queue->stats = stats; + queue->capacity = capacity; + queue->queue_id = queue_id; + queue->ttl = ttl; + INIT_LIST_HEAD(&queue->queue); + INIT_LIST_HEAD(&queue->pending); + INIT_LIST_HEAD(&queue->free_pool); + spin_lock_init(&queue->lock); + init_timer(&queue->gc); + queue->gc.data = (unsigned long)queue; + queue->gc.function = cw1200_queue_gc; + + queue->pool = kzalloc(sizeof(struct cw1200_queue_item) * capacity, + GFP_KERNEL); + if (!queue->pool) + return -ENOMEM; + + queue->link_map_cache = kzalloc(sizeof(int) * stats->map_capacity, + GFP_KERNEL); + if (!queue->link_map_cache) { + kfree(queue->pool); + queue->pool = NULL; + return -ENOMEM; + } + + for (i = 0; i < capacity; ++i) + list_add_tail(&queue->pool[i].head, &queue->free_pool); + + return 0; +} + +int cw1200_queue_clear(struct cw1200_queue *queue) +{ + int i; + LIST_HEAD(gc_list); + struct cw1200_queue_stats *stats = queue->stats; + struct cw1200_queue_item *item, *tmp; + + spin_lock_bh(&queue->lock); + queue->generation++; + list_splice_tail_init(&queue->queue, &queue->pending); + list_for_each_entry_safe(item, tmp, &queue->pending, head) { + WARN_ON(!item->skb); + cw1200_queue_register_post_gc(&gc_list, item); + item->skb = NULL; + list_move_tail(&item->head, &queue->free_pool); + } + queue->num_queued = 0; + queue->num_pending = 0; + + spin_lock_bh(&stats->lock); + for (i = 0; i < stats->map_capacity; ++i) { + stats->num_queued -= queue->link_map_cache[i]; + stats->link_map_cache[i] -= queue->link_map_cache[i]; + queue->link_map_cache[i] = 0; + } + spin_unlock_bh(&stats->lock); + if (queue->overfull) { + queue->overfull = false; + __cw1200_queue_unlock(queue); + } + spin_unlock_bh(&queue->lock); + wake_up(&stats->wait_link_id_empty); + cw1200_queue_post_gc(stats, &gc_list); + return 0; +} + +void cw1200_queue_stats_deinit(struct cw1200_queue_stats *stats) +{ + kfree(stats->link_map_cache); + stats->link_map_cache = NULL; +} + +void cw1200_queue_deinit(struct cw1200_queue *queue) +{ + cw1200_queue_clear(queue); + del_timer_sync(&queue->gc); + INIT_LIST_HEAD(&queue->free_pool); + kfree(queue->pool); + kfree(queue->link_map_cache); + queue->pool = NULL; + queue->link_map_cache = NULL; + queue->capacity = 0; +} + +size_t cw1200_queue_get_num_queued(struct cw1200_queue *queue, + u32 link_id_map) +{ + size_t ret; + int i, bit; + size_t map_capacity = queue->stats->map_capacity; + + if (!link_id_map) + return 0; + + spin_lock_bh(&queue->lock); + if (link_id_map == (u32)-1) { + ret = queue->num_queued - queue->num_pending; + } else { + ret = 0; + for (i = 0, bit = 1; i < map_capacity; ++i, bit <<= 1) { + if (link_id_map & bit) + ret += queue->link_map_cache[i]; + } + } + spin_unlock_bh(&queue->lock); + return ret; +} + +int cw1200_queue_put(struct cw1200_queue *queue, + struct sk_buff *skb, + struct cw1200_txpriv *txpriv) +{ + int ret = 0; + LIST_HEAD(gc_list); + struct cw1200_queue_stats *stats = queue->stats; + + if (txpriv->link_id >= queue->stats->map_capacity) + return -EINVAL; + + spin_lock_bh(&queue->lock); + if (!WARN_ON(list_empty(&queue->free_pool))) { + struct cw1200_queue_item *item = list_first_entry( + &queue->free_pool, struct cw1200_queue_item, head); + BUG_ON(item->skb); + + list_move_tail(&item->head, &queue->queue); + item->skb = skb; + item->txpriv = *txpriv; + item->generation = 0; + item->packet_id = cw1200_queue_mk_packet_id(queue->generation, + queue->queue_id, + item->generation, + item - queue->pool); + item->queue_timestamp = jiffies; + + ++queue->num_queued; + ++queue->link_map_cache[txpriv->link_id]; + + spin_lock_bh(&stats->lock); + ++stats->num_queued; + ++stats->link_map_cache[txpriv->link_id]; + spin_unlock_bh(&stats->lock); + + /* TX may happen in parallel sometimes. + * Leave extra queue slots so we don't overflow. + */ + if (queue->overfull == false && + queue->num_queued >= + (queue->capacity - (num_present_cpus() - 1))) { + queue->overfull = true; + __cw1200_queue_lock(queue); + mod_timer(&queue->gc, jiffies); + } + } else { + ret = -ENOENT; + } + spin_unlock_bh(&queue->lock); + return ret; +} + +int cw1200_queue_get(struct cw1200_queue *queue, + u32 link_id_map, + struct wsm_tx **tx, + struct ieee80211_tx_info **tx_info, + const struct cw1200_txpriv **txpriv) +{ + int ret = -ENOENT; + struct cw1200_queue_item *item; + struct cw1200_queue_stats *stats = queue->stats; + bool wakeup_stats = false; + + spin_lock_bh(&queue->lock); + list_for_each_entry(item, &queue->queue, head) { + if (link_id_map & BIT(item->txpriv.link_id)) { + ret = 0; + break; + } + } + + if (!WARN_ON(ret)) { + *tx = (struct wsm_tx *)item->skb->data; + *tx_info = IEEE80211_SKB_CB(item->skb); + *txpriv = &item->txpriv; + (*tx)->packet_id = __cpu_to_le32(item->packet_id); + list_move_tail(&item->head, &queue->pending); + ++queue->num_pending; + --queue->link_map_cache[item->txpriv.link_id]; + item->xmit_timestamp = jiffies; + + spin_lock_bh(&stats->lock); + --stats->num_queued; + if (!--stats->link_map_cache[item->txpriv.link_id]) + wakeup_stats = true; + spin_unlock_bh(&stats->lock); + } + spin_unlock_bh(&queue->lock); + if (wakeup_stats) + wake_up(&stats->wait_link_id_empty); + return ret; +} + +int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id) +{ + int ret = 0; + u8 queue_generation, queue_id, item_generation, item_id; + struct cw1200_queue_item *item; + struct cw1200_queue_stats *stats = queue->stats; + + cw1200_queue_parse_id(packet_id, &queue_generation, &queue_id, + &item_generation, &item_id); + + item = &queue->pool[item_id]; + + spin_lock_bh(&queue->lock); + BUG_ON(queue_id != queue->queue_id); + if (queue_generation != queue->generation) { + ret = -ENOENT; + } else if (item_id >= (unsigned) queue->capacity) { + WARN_ON(1); + ret = -EINVAL; + } else if (item->generation != item_generation) { + WARN_ON(1); + ret = -ENOENT; + } else { + --queue->num_pending; + ++queue->link_map_cache[item->txpriv.link_id]; + + spin_lock_bh(&stats->lock); + ++stats->num_queued; + ++stats->link_map_cache[item->txpriv.link_id]; + spin_unlock_bh(&stats->lock); + + item->generation = ++item_generation; + item->packet_id = cw1200_queue_mk_packet_id(queue_generation, + queue_id, + item_generation, + item_id); + list_move(&item->head, &queue->queue); + } + spin_unlock_bh(&queue->lock); + return ret; +} + +int cw1200_queue_requeue_all(struct cw1200_queue *queue) +{ + struct cw1200_queue_item *item, *tmp; + struct cw1200_queue_stats *stats = queue->stats; + spin_lock_bh(&queue->lock); + + list_for_each_entry_safe_reverse(item, tmp, &queue->pending, head) { + --queue->num_pending; + ++queue->link_map_cache[item->txpriv.link_id]; + + spin_lock_bh(&stats->lock); + ++stats->num_queued; + ++stats->link_map_cache[item->txpriv.link_id]; + spin_unlock_bh(&stats->lock); + + ++item->generation; + item->packet_id = cw1200_queue_mk_packet_id(queue->generation, + queue->queue_id, + item->generation, + item - queue->pool); + list_move(&item->head, &queue->queue); + } + spin_unlock_bh(&queue->lock); + + return 0; +} + +int cw1200_queue_remove(struct cw1200_queue *queue, u32 packet_id) +{ + int ret = 0; + u8 queue_generation, queue_id, item_generation, item_id; + struct cw1200_queue_item *item; + struct cw1200_queue_stats *stats = queue->stats; + struct sk_buff *gc_skb = NULL; + struct cw1200_txpriv gc_txpriv; + + cw1200_queue_parse_id(packet_id, &queue_generation, &queue_id, + &item_generation, &item_id); + + item = &queue->pool[item_id]; + + spin_lock_bh(&queue->lock); + BUG_ON(queue_id != queue->queue_id); + if (queue_generation != queue->generation) { + ret = -ENOENT; + } else if (item_id >= (unsigned) queue->capacity) { + WARN_ON(1); + ret = -EINVAL; + } else if (item->generation != item_generation) { + WARN_ON(1); + ret = -ENOENT; + } else { + gc_txpriv = item->txpriv; + gc_skb = item->skb; + item->skb = NULL; + --queue->num_pending; + --queue->num_queued; + ++queue->num_sent; + ++item->generation; + /* Do not use list_move_tail here, but list_move: + * try to utilize cache row. + */ + list_move(&item->head, &queue->free_pool); + + if (queue->overfull && + (queue->num_queued <= (queue->capacity >> 1))) { + queue->overfull = false; + __cw1200_queue_unlock(queue); + } + } + spin_unlock_bh(&queue->lock); + + if (gc_skb) + stats->skb_dtor(stats->priv, gc_skb, &gc_txpriv); + + return ret; +} + +int cw1200_queue_get_skb(struct cw1200_queue *queue, u32 packet_id, + struct sk_buff **skb, + const struct cw1200_txpriv **txpriv) +{ + int ret = 0; + u8 queue_generation, queue_id, item_generation, item_id; + struct cw1200_queue_item *item; + cw1200_queue_parse_id(packet_id, &queue_generation, &queue_id, + &item_generation, &item_id); + + item = &queue->pool[item_id]; + + spin_lock_bh(&queue->lock); + BUG_ON(queue_id != queue->queue_id); + if (queue_generation != queue->generation) { + ret = -ENOENT; + } else if (item_id >= (unsigned) queue->capacity) { + WARN_ON(1); + ret = -EINVAL; + } else if (item->generation != item_generation) { + WARN_ON(1); + ret = -ENOENT; + } else { + *skb = item->skb; + *txpriv = &item->txpriv; + } + spin_unlock_bh(&queue->lock); + return ret; +} + +void cw1200_queue_lock(struct cw1200_queue *queue) +{ + spin_lock_bh(&queue->lock); + __cw1200_queue_lock(queue); + spin_unlock_bh(&queue->lock); +} + +void cw1200_queue_unlock(struct cw1200_queue *queue) +{ + spin_lock_bh(&queue->lock); + __cw1200_queue_unlock(queue); + spin_unlock_bh(&queue->lock); +} + +bool cw1200_queue_get_xmit_timestamp(struct cw1200_queue *queue, + unsigned long *timestamp, + u32 pending_frame_id) +{ + struct cw1200_queue_item *item; + bool ret; + + spin_lock_bh(&queue->lock); + ret = !list_empty(&queue->pending); + if (ret) { + list_for_each_entry(item, &queue->pending, head) { + if (item->packet_id != pending_frame_id) + if (time_before(item->xmit_timestamp, + *timestamp)) + *timestamp = item->xmit_timestamp; + } + } + spin_unlock_bh(&queue->lock); + return ret; +} + +bool cw1200_queue_stats_is_empty(struct cw1200_queue_stats *stats, + u32 link_id_map) +{ + bool empty = true; + + spin_lock_bh(&stats->lock); + if (link_id_map == (u32)-1) { + empty = stats->num_queued == 0; + } else { + int i; + for (i = 0; i < stats->map_capacity; ++i) { + if (link_id_map & BIT(i)) { + if (stats->link_map_cache[i]) { + empty = false; + break; + } + } + } + } + spin_unlock_bh(&stats->lock); + + return empty; +} diff --git a/drivers/net/wireless/cw1200/queue.h b/drivers/net/wireless/cw1200/queue.h new file mode 100644 index 000000000000..119f9c79c14e --- /dev/null +++ b/drivers/net/wireless/cw1200/queue.h @@ -0,0 +1,116 @@ +/* + * O(1) TX queue with built-in allocator for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_QUEUE_H_INCLUDED +#define CW1200_QUEUE_H_INCLUDED + +/* private */ struct cw1200_queue_item; + +/* extern */ struct sk_buff; +/* extern */ struct wsm_tx; +/* extern */ struct cw1200_common; +/* extern */ struct ieee80211_tx_queue_stats; +/* extern */ struct cw1200_txpriv; + +/* forward */ struct cw1200_queue_stats; + +typedef void (*cw1200_queue_skb_dtor_t)(struct cw1200_common *priv, + struct sk_buff *skb, + const struct cw1200_txpriv *txpriv); + +struct cw1200_queue { + struct cw1200_queue_stats *stats; + size_t capacity; + size_t num_queued; + size_t num_pending; + size_t num_sent; + struct cw1200_queue_item *pool; + struct list_head queue; + struct list_head free_pool; + struct list_head pending; + int tx_locked_cnt; + int *link_map_cache; + bool overfull; + spinlock_t lock; /* Protect queue entry */ + u8 queue_id; + u8 generation; + struct timer_list gc; + unsigned long ttl; +}; + +struct cw1200_queue_stats { + spinlock_t lock; /* Protect stats entry */ + int *link_map_cache; + int num_queued; + size_t map_capacity; + wait_queue_head_t wait_link_id_empty; + cw1200_queue_skb_dtor_t skb_dtor; + struct cw1200_common *priv; +}; + +struct cw1200_txpriv { + u8 link_id; + u8 raw_link_id; + u8 tid; + u8 rate_id; + u8 offset; +}; + +int cw1200_queue_stats_init(struct cw1200_queue_stats *stats, + size_t map_capacity, + cw1200_queue_skb_dtor_t skb_dtor, + struct cw1200_common *priv); +int cw1200_queue_init(struct cw1200_queue *queue, + struct cw1200_queue_stats *stats, + u8 queue_id, + size_t capacity, + unsigned long ttl); +int cw1200_queue_clear(struct cw1200_queue *queue); +void cw1200_queue_stats_deinit(struct cw1200_queue_stats *stats); +void cw1200_queue_deinit(struct cw1200_queue *queue); + +size_t cw1200_queue_get_num_queued(struct cw1200_queue *queue, + u32 link_id_map); +int cw1200_queue_put(struct cw1200_queue *queue, + struct sk_buff *skb, + struct cw1200_txpriv *txpriv); +int cw1200_queue_get(struct cw1200_queue *queue, + u32 link_id_map, + struct wsm_tx **tx, + struct ieee80211_tx_info **tx_info, + const struct cw1200_txpriv **txpriv); +int cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id); +int cw1200_queue_requeue_all(struct cw1200_queue *queue); +int cw1200_queue_remove(struct cw1200_queue *queue, + u32 packet_id); +int cw1200_queue_get_skb(struct cw1200_queue *queue, u32 packet_id, + struct sk_buff **skb, + const struct cw1200_txpriv **txpriv); +void cw1200_queue_lock(struct cw1200_queue *queue); +void cw1200_queue_unlock(struct cw1200_queue *queue); +bool cw1200_queue_get_xmit_timestamp(struct cw1200_queue *queue, + unsigned long *timestamp, + u32 pending_frame_id); + +bool cw1200_queue_stats_is_empty(struct cw1200_queue_stats *stats, + u32 link_id_map); + +static inline u8 cw1200_queue_get_queue_id(u32 packet_id) +{ + return (packet_id >> 16) & 0xFF; +} + +static inline u8 cw1200_queue_get_generation(u32 packet_id) +{ + return (packet_id >> 8) & 0xFF; +} + +#endif /* CW1200_QUEUE_H_INCLUDED */ diff --git a/drivers/net/wireless/cw1200/sbus.h b/drivers/net/wireless/cw1200/sbus.h new file mode 100644 index 000000000000..603fd25eaa4a --- /dev/null +++ b/drivers/net/wireless/cw1200/sbus.h @@ -0,0 +1,37 @@ +/* + * Common sbus abstraction layer interface for cw1200 wireless driver + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_SBUS_H +#define CW1200_SBUS_H + +/* + * sbus priv forward definition. + * Implemented and instantiated in particular modules. + */ +struct sbus_priv; + +void cw1200_irq_handler(struct cw1200_common *priv); + +/* This MUST be wrapped with sbus_ops->lock/unlock! */ +int __cw1200_irq_enable(struct cw1200_common *priv, int enable); + +struct sbus_ops { + int (*sbus_memcpy_fromio)(struct sbus_priv *self, unsigned int addr, + void *dst, int count); + int (*sbus_memcpy_toio)(struct sbus_priv *self, unsigned int addr, + const void *src, int count); + void (*lock)(struct sbus_priv *self); + void (*unlock)(struct sbus_priv *self); + size_t (*align_size)(struct sbus_priv *self, size_t size); + int (*power_mgmt)(struct sbus_priv *self, bool suspend); +}; + +#endif /* CW1200_SBUS_H */ diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c new file mode 100644 index 000000000000..ee3c19037aac --- /dev/null +++ b/drivers/net/wireless/cw1200/scan.c @@ -0,0 +1,461 @@ +/* + * Scan implementation for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include "cw1200.h" +#include "scan.h" +#include "sta.h" +#include "pm.h" + +static void cw1200_scan_restart_delayed(struct cw1200_common *priv); + +static int cw1200_scan_start(struct cw1200_common *priv, struct wsm_scan *scan) +{ + int ret, i; + int tmo = 2000; + + switch (priv->join_status) { + case CW1200_JOIN_STATUS_PRE_STA: + case CW1200_JOIN_STATUS_JOINING: + return -EBUSY; + default: + break; + } + + wiphy_dbg(priv->hw->wiphy, "[SCAN] hw req, type %d, %d channels, flags: 0x%x.\n", + scan->type, scan->num_channels, scan->flags); + + for (i = 0; i < scan->num_channels; ++i) + tmo += scan->ch[i].max_chan_time + 10; + + cancel_delayed_work_sync(&priv->clear_recent_scan_work); + atomic_set(&priv->scan.in_progress, 1); + atomic_set(&priv->recent_scan, 1); + cw1200_pm_stay_awake(&priv->pm_state, tmo * HZ / 1000); + queue_delayed_work(priv->workqueue, &priv->scan.timeout, + tmo * HZ / 1000); + ret = wsm_scan(priv, scan); + if (ret) { + atomic_set(&priv->scan.in_progress, 0); + cancel_delayed_work_sync(&priv->scan.timeout); + cw1200_scan_restart_delayed(priv); + } + return ret; +} + +int cw1200_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req) +{ + struct cw1200_common *priv = hw->priv; + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST, + }; + int i, ret; + + if (!priv->vif) + return -EINVAL; + + /* Scan when P2P_GO corrupt firmware MiniAP mode */ + if (priv->join_status == CW1200_JOIN_STATUS_AP) + return -EOPNOTSUPP; + + if (req->n_ssids == 1 && !req->ssids[0].ssid_len) + req->n_ssids = 0; + + wiphy_dbg(hw->wiphy, "[SCAN] Scan request for %d SSIDs.\n", + req->n_ssids); + + if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) + return -EINVAL; + + frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0, + req->ie_len); + if (!frame.skb) + return -ENOMEM; + + if (req->ie_len) + memcpy(skb_put(frame.skb, req->ie_len), req->ie, req->ie_len); + + /* will be unlocked in cw1200_scan_work() */ + down(&priv->scan.lock); + mutex_lock(&priv->conf_mutex); + + ret = wsm_set_template_frame(priv, &frame); + if (!ret) { + /* Host want to be the probe responder. */ + ret = wsm_set_probe_responder(priv, true); + } + if (ret) { + mutex_unlock(&priv->conf_mutex); + up(&priv->scan.lock); + dev_kfree_skb(frame.skb); + return ret; + } + + wsm_lock_tx(priv); + + BUG_ON(priv->scan.req); + priv->scan.req = req; + priv->scan.n_ssids = 0; + priv->scan.status = 0; + priv->scan.begin = &req->channels[0]; + priv->scan.curr = priv->scan.begin; + priv->scan.end = &req->channels[req->n_channels]; + priv->scan.output_power = priv->output_power; + + for (i = 0; i < req->n_ssids; ++i) { + struct wsm_ssid *dst = &priv->scan.ssids[priv->scan.n_ssids]; + memcpy(&dst->ssid[0], req->ssids[i].ssid, sizeof(dst->ssid)); + dst->length = req->ssids[i].ssid_len; + ++priv->scan.n_ssids; + } + + mutex_unlock(&priv->conf_mutex); + + if (frame.skb) + dev_kfree_skb(frame.skb); + queue_work(priv->workqueue, &priv->scan.work); + return 0; +} + +void cw1200_scan_work(struct work_struct *work) +{ + struct cw1200_common *priv = container_of(work, struct cw1200_common, + scan.work); + struct ieee80211_channel **it; + struct wsm_scan scan = { + .type = WSM_SCAN_TYPE_FOREGROUND, + .flags = WSM_SCAN_FLAG_SPLIT_METHOD, + }; + bool first_run = (priv->scan.begin == priv->scan.curr && + priv->scan.begin != priv->scan.end); + int i; + + if (first_run) { + /* Firmware gets crazy if scan request is sent + * when STA is joined but not yet associated. + * Force unjoin in this case. + */ + if (cancel_delayed_work_sync(&priv->join_timeout) > 0) + cw1200_join_timeout(&priv->join_timeout.work); + } + + mutex_lock(&priv->conf_mutex); + + if (first_run) { + if (priv->join_status == CW1200_JOIN_STATUS_STA && + !(priv->powersave_mode.mode & WSM_PSM_PS)) { + struct wsm_set_pm pm = priv->powersave_mode; + pm.mode = WSM_PSM_PS; + cw1200_set_pm(priv, &pm); + } else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) { + /* FW bug: driver has to restart p2p-dev mode + * after scan + */ + cw1200_disable_listening(priv); + } + } + + if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) { + if (priv->scan.output_power != priv->output_power) + wsm_set_output_power(priv, priv->output_power * 10); + if (priv->join_status == CW1200_JOIN_STATUS_STA && + !(priv->powersave_mode.mode & WSM_PSM_PS)) + cw1200_set_pm(priv, &priv->powersave_mode); + + if (priv->scan.status < 0) + wiphy_dbg(priv->hw->wiphy, "[SCAN] Scan failed (%d).\n", + priv->scan.status); + else if (priv->scan.req) + wiphy_dbg(priv->hw->wiphy, + "[SCAN] Scan completed.\n"); + else + wiphy_dbg(priv->hw->wiphy, + "[SCAN] Scan canceled.\n"); + + priv->scan.req = NULL; + cw1200_scan_restart_delayed(priv); + wsm_unlock_tx(priv); + mutex_unlock(&priv->conf_mutex); + ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0); + up(&priv->scan.lock); + return; + } else { + struct ieee80211_channel *first = *priv->scan.curr; + for (it = priv->scan.curr + 1, i = 1; + it != priv->scan.end && i < WSM_SCAN_MAX_NUM_OF_CHANNELS; + ++it, ++i) { + if ((*it)->band != first->band) + break; + if (((*it)->flags ^ first->flags) & + IEEE80211_CHAN_PASSIVE_SCAN) + break; + if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + (*it)->max_power != first->max_power) + break; + } + scan.band = first->band; + + if (priv->scan.req->no_cck) + scan.max_tx_rate = WSM_TRANSMIT_RATE_6; + else + scan.max_tx_rate = WSM_TRANSMIT_RATE_1; + scan.num_probes = + (first->flags & IEEE80211_CHAN_PASSIVE_SCAN) ? 0 : 2; + scan.num_ssids = priv->scan.n_ssids; + scan.ssids = &priv->scan.ssids[0]; + scan.num_channels = it - priv->scan.curr; + /* TODO: Is it optimal? */ + scan.probe_delay = 100; + /* It is not stated in WSM specification, however + * FW team says that driver may not use FG scan + * when joined. + */ + if (priv->join_status == CW1200_JOIN_STATUS_STA) { + scan.type = WSM_SCAN_TYPE_BACKGROUND; + scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND; + } + scan.ch = kzalloc( + sizeof(struct wsm_scan_ch) * (it - priv->scan.curr), + GFP_KERNEL); + if (!scan.ch) { + priv->scan.status = -ENOMEM; + goto fail; + } + for (i = 0; i < scan.num_channels; ++i) { + scan.ch[i].number = priv->scan.curr[i]->hw_value; + if (priv->scan.curr[i]->flags & IEEE80211_CHAN_PASSIVE_SCAN) { + scan.ch[i].min_chan_time = 50; + scan.ch[i].max_chan_time = 100; + } else { + scan.ch[i].min_chan_time = 10; + scan.ch[i].max_chan_time = 25; + } + } + if (!(first->flags & IEEE80211_CHAN_PASSIVE_SCAN) && + priv->scan.output_power != first->max_power) { + priv->scan.output_power = first->max_power; + wsm_set_output_power(priv, + priv->scan.output_power * 10); + } + priv->scan.status = cw1200_scan_start(priv, &scan); + kfree(scan.ch); + if (priv->scan.status) + goto fail; + priv->scan.curr = it; + } + mutex_unlock(&priv->conf_mutex); + return; + +fail: + priv->scan.curr = priv->scan.end; + mutex_unlock(&priv->conf_mutex); + queue_work(priv->workqueue, &priv->scan.work); + return; +} + +static void cw1200_scan_restart_delayed(struct cw1200_common *priv) +{ + /* FW bug: driver has to restart p2p-dev mode after scan. */ + if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) { + cw1200_enable_listening(priv); + cw1200_update_filtering(priv); + } + + if (priv->delayed_unjoin) { + priv->delayed_unjoin = false; + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + } else if (priv->delayed_link_loss) { + wiphy_dbg(priv->hw->wiphy, "[CQM] Requeue BSS loss.\n"); + priv->delayed_link_loss = 0; + cw1200_cqm_bssloss_sm(priv, 1, 0, 0); + } +} + +static void cw1200_scan_complete(struct cw1200_common *priv) +{ + queue_delayed_work(priv->workqueue, &priv->clear_recent_scan_work, HZ); + if (priv->scan.direct_probe) { + wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe complete.\n"); + cw1200_scan_restart_delayed(priv); + priv->scan.direct_probe = 0; + up(&priv->scan.lock); + wsm_unlock_tx(priv); + } else { + cw1200_scan_work(&priv->scan.work); + } +} + +void cw1200_scan_failed_cb(struct cw1200_common *priv) +{ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + /* STA is stopped. */ + return; + + if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) { + priv->scan.status = -EIO; + queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0); + } +} + + +void cw1200_scan_complete_cb(struct cw1200_common *priv, + struct wsm_scan_complete *arg) +{ + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + /* STA is stopped. */ + return; + + if (cancel_delayed_work_sync(&priv->scan.timeout) > 0) { + priv->scan.status = 1; + queue_delayed_work(priv->workqueue, &priv->scan.timeout, 0); + } +} + +void cw1200_clear_recent_scan_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, + clear_recent_scan_work.work); + atomic_xchg(&priv->recent_scan, 0); +} + +void cw1200_scan_timeout(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, scan.timeout.work); + if (atomic_xchg(&priv->scan.in_progress, 0)) { + if (priv->scan.status > 0) { + priv->scan.status = 0; + } else if (!priv->scan.status) { + wiphy_warn(priv->hw->wiphy, + "Timeout waiting for scan complete notification.\n"); + priv->scan.status = -ETIMEDOUT; + priv->scan.curr = priv->scan.end; + wsm_stop_scan(priv); + } + cw1200_scan_complete(priv); + } +} + +void cw1200_probe_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, scan.probe_work.work); + u8 queue_id = cw1200_queue_get_queue_id(priv->pending_frame_id); + struct cw1200_queue *queue = &priv->tx_queue[queue_id]; + const struct cw1200_txpriv *txpriv; + struct wsm_tx *wsm; + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_PROBE_REQUEST, + }; + struct wsm_ssid ssids[1] = {{ + .length = 0, + } }; + struct wsm_scan_ch ch[1] = {{ + .min_chan_time = 0, + .max_chan_time = 10, + } }; + struct wsm_scan scan = { + .type = WSM_SCAN_TYPE_FOREGROUND, + .num_probes = 1, + .probe_delay = 0, + .num_channels = 1, + .ssids = ssids, + .ch = ch, + }; + u8 *ies; + size_t ies_len; + int ret; + + wiphy_dbg(priv->hw->wiphy, "[SCAN] Direct probe work.\n"); + + mutex_lock(&priv->conf_mutex); + if (down_trylock(&priv->scan.lock)) { + /* Scan is already in progress. Requeue self. */ + schedule(); + queue_delayed_work(priv->workqueue, + &priv->scan.probe_work, HZ / 10); + mutex_unlock(&priv->conf_mutex); + return; + } + + /* Make sure we still have a pending probe req */ + if (cw1200_queue_get_skb(queue, priv->pending_frame_id, + &frame.skb, &txpriv)) { + up(&priv->scan.lock); + mutex_unlock(&priv->conf_mutex); + wsm_unlock_tx(priv); + return; + } + wsm = (struct wsm_tx *)frame.skb->data; + scan.max_tx_rate = wsm->max_tx_rate; + scan.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; + if (priv->join_status == CW1200_JOIN_STATUS_STA || + priv->join_status == CW1200_JOIN_STATUS_IBSS) { + scan.type = WSM_SCAN_TYPE_BACKGROUND; + scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND; + } + ch[0].number = priv->channel->hw_value; + + skb_pull(frame.skb, txpriv->offset); + + ies = &frame.skb->data[sizeof(struct ieee80211_hdr_3addr)]; + ies_len = frame.skb->len - sizeof(struct ieee80211_hdr_3addr); + + if (ies_len) { + u8 *ssidie = + (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len); + if (ssidie && ssidie[1] && ssidie[1] <= sizeof(ssids[0].ssid)) { + u8 *nextie = &ssidie[2 + ssidie[1]]; + /* Remove SSID from the IE list. It has to be provided + * as a separate argument in cw1200_scan_start call + */ + + /* Store SSID localy */ + ssids[0].length = ssidie[1]; + memcpy(ssids[0].ssid, &ssidie[2], ssids[0].length); + scan.num_ssids = 1; + + /* Remove SSID from IE list */ + ssidie[1] = 0; + memmove(&ssidie[2], nextie, &ies[ies_len] - nextie); + skb_trim(frame.skb, frame.skb->len - ssids[0].length); + } + } + + /* FW bug: driver has to restart p2p-dev mode after scan */ + if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) + cw1200_disable_listening(priv); + ret = wsm_set_template_frame(priv, &frame); + priv->scan.direct_probe = 1; + if (!ret) { + wsm_flush_tx(priv); + ret = cw1200_scan_start(priv, &scan); + } + mutex_unlock(&priv->conf_mutex); + + skb_push(frame.skb, txpriv->offset); + if (!ret) + IEEE80211_SKB_CB(frame.skb)->flags |= IEEE80211_TX_STAT_ACK; + BUG_ON(cw1200_queue_remove(queue, priv->pending_frame_id)); + + if (ret) { + priv->scan.direct_probe = 0; + up(&priv->scan.lock); + wsm_unlock_tx(priv); + } + + return; +} diff --git a/drivers/net/wireless/cw1200/scan.h b/drivers/net/wireless/cw1200/scan.h new file mode 100644 index 000000000000..5a8296ccfa82 --- /dev/null +++ b/drivers/net/wireless/cw1200/scan.h @@ -0,0 +1,56 @@ +/* + * Scan interface for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef SCAN_H_INCLUDED +#define SCAN_H_INCLUDED + +#include +#include "wsm.h" + +/* external */ struct sk_buff; +/* external */ struct cfg80211_scan_request; +/* external */ struct ieee80211_channel; +/* external */ struct ieee80211_hw; +/* external */ struct work_struct; + +struct cw1200_scan { + struct semaphore lock; + struct work_struct work; + struct delayed_work timeout; + struct cfg80211_scan_request *req; + struct ieee80211_channel **begin; + struct ieee80211_channel **curr; + struct ieee80211_channel **end; + struct wsm_ssid ssids[WSM_SCAN_MAX_NUM_OF_SSIDS]; + int output_power; + int n_ssids; + int status; + atomic_t in_progress; + /* Direct probe requests workaround */ + struct delayed_work probe_work; + int direct_probe; +}; + +int cw1200_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req); +void cw1200_scan_work(struct work_struct *work); +void cw1200_scan_timeout(struct work_struct *work); +void cw1200_clear_recent_scan_work(struct work_struct *work); +void cw1200_scan_complete_cb(struct cw1200_common *priv, + struct wsm_scan_complete *arg); +void cw1200_scan_failed_cb(struct cw1200_common *priv); + +/* ******************************************************************** */ +/* Raw probe requests TX workaround */ +void cw1200_probe_work(struct work_struct *work); + +#endif diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c new file mode 100644 index 000000000000..679c55f15c67 --- /dev/null +++ b/drivers/net/wireless/cw1200/sta.c @@ -0,0 +1,2406 @@ +/* + * Mac80211 STA API for ST-Ericsson CW1200 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "cw1200.h" +#include "sta.h" +#include "fwio.h" +#include "bh.h" +#include "debug.h" + +#ifndef ERP_INFO_BYTE_OFFSET +#define ERP_INFO_BYTE_OFFSET 2 +#endif + +static void cw1200_do_join(struct cw1200_common *priv); +static void cw1200_do_unjoin(struct cw1200_common *priv); + +static int cw1200_upload_beacon(struct cw1200_common *priv); +static int cw1200_upload_pspoll(struct cw1200_common *priv); +static int cw1200_upload_null(struct cw1200_common *priv); +static int cw1200_upload_qosnull(struct cw1200_common *priv); +static int cw1200_start_ap(struct cw1200_common *priv); +static int cw1200_update_beaconing(struct cw1200_common *priv); +static int cw1200_enable_beaconing(struct cw1200_common *priv, + bool enable); +static void __cw1200_sta_notify(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + enum sta_notify_cmd notify_cmd, + int link_id); +static int __cw1200_flush(struct cw1200_common *priv, bool drop); + +static inline void __cw1200_free_event_queue(struct list_head *list) +{ + struct cw1200_wsm_event *event, *tmp; + list_for_each_entry_safe(event, tmp, list, link) { + list_del(&event->link); + kfree(event); + } +} + +/* ******************************************************************** */ +/* STA API */ + +int cw1200_start(struct ieee80211_hw *dev) +{ + struct cw1200_common *priv = dev->priv; + int ret = 0; + + cw1200_pm_stay_awake(&priv->pm_state, HZ); + + mutex_lock(&priv->conf_mutex); + + /* default EDCA */ + WSM_EDCA_SET(&priv->edca, 0, 0x0002, 0x0003, 0x0007, 47, 0xc8, false); + WSM_EDCA_SET(&priv->edca, 1, 0x0002, 0x0007, 0x000f, 94, 0xc8, false); + WSM_EDCA_SET(&priv->edca, 2, 0x0003, 0x000f, 0x03ff, 0, 0xc8, false); + WSM_EDCA_SET(&priv->edca, 3, 0x0007, 0x000f, 0x03ff, 0, 0xc8, false); + ret = wsm_set_edca_params(priv, &priv->edca); + if (ret) + goto out; + + ret = cw1200_set_uapsd_param(priv, &priv->edca); + if (ret) + goto out; + + priv->setbssparams_done = false; + + memcpy(priv->mac_addr, dev->wiphy->perm_addr, ETH_ALEN); + priv->mode = NL80211_IFTYPE_MONITOR; + priv->wep_default_key_id = -1; + + priv->cqm_beacon_loss_count = 10; + + ret = cw1200_setup_mac(priv); + if (ret) + goto out; + +out: + mutex_unlock(&priv->conf_mutex); + return ret; +} + +void cw1200_stop(struct ieee80211_hw *dev) +{ + struct cw1200_common *priv = dev->priv; + LIST_HEAD(list); + int i; + + wsm_lock_tx(priv); + + while (down_trylock(&priv->scan.lock)) { + /* Scan is in progress. Force it to stop. */ + priv->scan.req = NULL; + schedule(); + } + up(&priv->scan.lock); + + cancel_delayed_work_sync(&priv->scan.probe_work); + cancel_delayed_work_sync(&priv->scan.timeout); + cancel_delayed_work_sync(&priv->clear_recent_scan_work); + cancel_delayed_work_sync(&priv->join_timeout); + cw1200_cqm_bssloss_sm(priv, 0, 0, 0); + cancel_work_sync(&priv->unjoin_work); + cancel_delayed_work_sync(&priv->link_id_gc_work); + flush_workqueue(priv->workqueue); + del_timer_sync(&priv->mcast_timeout); + mutex_lock(&priv->conf_mutex); + priv->mode = NL80211_IFTYPE_UNSPECIFIED; + priv->listening = false; + + spin_lock(&priv->event_queue_lock); + list_splice_init(&priv->event_queue, &list); + spin_unlock(&priv->event_queue_lock); + __cw1200_free_event_queue(&list); + + + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + priv->join_pending = false; + + for (i = 0; i < 4; i++) + cw1200_queue_clear(&priv->tx_queue[i]); + mutex_unlock(&priv->conf_mutex); + tx_policy_clean(priv); + + /* HACK! */ + if (atomic_xchg(&priv->tx_lock, 1) != 1) + pr_debug("[STA] TX is force-unlocked due to stop request.\n"); + + wsm_unlock_tx(priv); + atomic_xchg(&priv->tx_lock, 0); /* for recovery to work */ +} + +static int cw1200_bssloss_mitigation = 1; +module_param(cw1200_bssloss_mitigation, int, 0644); +MODULE_PARM_DESC(cw1200_bssloss_mitigation, "BSS Loss mitigation. 0 == disabled, 1 == enabled (default)"); + + +void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv, + int init, int good, int bad) +{ + int tx = 0; + + priv->delayed_link_loss = 0; + cancel_work_sync(&priv->bss_params_work); + + pr_debug("[STA] CQM BSSLOSS_SM: state: %d init %d good %d bad: %d txlock: %d uj: %d\n", + priv->bss_loss_state, + init, good, bad, + atomic_read(&priv->tx_lock), + priv->delayed_unjoin); + + /* If we have a pending unjoin */ + if (priv->delayed_unjoin) + return; + + if (init) { + queue_delayed_work(priv->workqueue, + &priv->bss_loss_work, + HZ); + priv->bss_loss_state = 0; + + /* Skip the confimration procedure in P2P case */ + if (!priv->vif->p2p && !atomic_read(&priv->tx_lock)) + tx = 1; + } else if (good) { + cancel_delayed_work_sync(&priv->bss_loss_work); + priv->bss_loss_state = 0; + queue_work(priv->workqueue, &priv->bss_params_work); + } else if (bad) { + /* XXX Should we just keep going until we time out? */ + if (priv->bss_loss_state < 3) + tx = 1; + } else { + cancel_delayed_work_sync(&priv->bss_loss_work); + priv->bss_loss_state = 0; + } + + /* Bypass mitigation if it's disabled */ + if (!cw1200_bssloss_mitigation) + tx = 0; + + /* Spit out a NULL packet to our AP if necessary */ + if (tx) { + struct sk_buff *skb; + + priv->bss_loss_state++; + + skb = ieee80211_nullfunc_get(priv->hw, priv->vif); + WARN_ON(!skb); + if (skb) + cw1200_tx(priv->hw, NULL, skb); + } +} + +int cw1200_add_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + int ret; + struct cw1200_common *priv = dev->priv; + /* __le32 auto_calibration_mode = __cpu_to_le32(1); */ + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | + IEEE80211_VIF_SUPPORTS_CQM_RSSI; + + mutex_lock(&priv->conf_mutex); + + if (priv->mode != NL80211_IFTYPE_MONITOR) { + mutex_unlock(&priv->conf_mutex); + return -EOPNOTSUPP; + } + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + priv->mode = vif->type; + break; + default: + mutex_unlock(&priv->conf_mutex); + return -EOPNOTSUPP; + } + + priv->vif = vif; + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); + ret = cw1200_setup_mac(priv); + /* Enable auto-calibration */ + /* Exception in subsequent channel switch; disabled. + * wsm_write_mib(priv, WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE, + * &auto_calibration_mode, sizeof(auto_calibration_mode)); + */ + + mutex_unlock(&priv->conf_mutex); + return ret; +} + +void cw1200_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct cw1200_common *priv = dev->priv; + struct wsm_reset reset = { + .reset_statistics = true, + }; + int i; + + mutex_lock(&priv->conf_mutex); + switch (priv->join_status) { + case CW1200_JOIN_STATUS_JOINING: + case CW1200_JOIN_STATUS_PRE_STA: + case CW1200_JOIN_STATUS_STA: + case CW1200_JOIN_STATUS_IBSS: + wsm_lock_tx(priv); + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + break; + case CW1200_JOIN_STATUS_AP: + for (i = 0; priv->link_id_map; ++i) { + if (priv->link_id_map & BIT(i)) { + reset.link_id = i; + wsm_reset(priv, &reset); + priv->link_id_map &= ~BIT(i); + } + } + memset(priv->link_id_db, 0, sizeof(priv->link_id_db)); + priv->sta_asleep_mask = 0; + priv->enable_beacon = false; + priv->tx_multicast = false; + priv->aid0_bit_set = false; + priv->buffered_multicasts = false; + priv->pspoll_mask = 0; + reset.link_id = 0; + wsm_reset(priv, &reset); + break; + case CW1200_JOIN_STATUS_MONITOR: + cw1200_update_listening(priv, false); + break; + default: + break; + } + priv->vif = NULL; + priv->mode = NL80211_IFTYPE_MONITOR; + memset(priv->mac_addr, 0, ETH_ALEN); + memset(&priv->p2p_ps_modeinfo, 0, sizeof(priv->p2p_ps_modeinfo)); + cw1200_free_keys(priv); + cw1200_setup_mac(priv); + priv->listening = false; + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + if (!__cw1200_flush(priv, true)) + wsm_unlock_tx(priv); + + mutex_unlock(&priv->conf_mutex); +} + +int cw1200_change_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type, + bool p2p) +{ + int ret = 0; + pr_debug("change_interface new: %d (%d), old: %d (%d)\n", new_type, + p2p, vif->type, vif->p2p); + + if (new_type != vif->type || vif->p2p != p2p) { + cw1200_remove_interface(dev, vif); + vif->type = new_type; + vif->p2p = p2p; + ret = cw1200_add_interface(dev, vif); + } + + return ret; +} + +int cw1200_config(struct ieee80211_hw *dev, u32 changed) +{ + int ret = 0; + struct cw1200_common *priv = dev->priv; + struct ieee80211_conf *conf = &dev->conf; + + pr_debug("CONFIG CHANGED: %08x\n", changed); + + down(&priv->scan.lock); + mutex_lock(&priv->conf_mutex); + /* TODO: IEEE80211_CONF_CHANGE_QOS */ + /* TODO: IEEE80211_CONF_CHANGE_LISTEN_INTERVAL */ + + if (changed & IEEE80211_CONF_CHANGE_POWER) { + priv->output_power = conf->power_level; + pr_debug("[STA] TX power: %d\n", priv->output_power); + wsm_set_output_power(priv, priv->output_power * 10); + } + + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) && + (priv->channel != conf->chandef.chan)) { + struct ieee80211_channel *ch = conf->chandef.chan; + struct wsm_switch_channel channel = { + .channel_number = ch->hw_value, + }; + pr_debug("[STA] Freq %d (wsm ch: %d).\n", + ch->center_freq, ch->hw_value); + + /* __cw1200_flush() implicitly locks tx, if successful */ + if (!__cw1200_flush(priv, false)) { + if (!wsm_switch_channel(priv, &channel)) { + ret = wait_event_timeout(priv->channel_switch_done, + !priv->channel_switch_in_progress, + 3 * HZ); + if (ret) { + /* Already unlocks if successful */ + priv->channel = ch; + ret = 0; + } else { + ret = -ETIMEDOUT; + } + } else { + /* Unlock if switch channel fails */ + wsm_unlock_tx(priv); + } + } + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + if (!(conf->flags & IEEE80211_CONF_PS)) + priv->powersave_mode.mode = WSM_PSM_ACTIVE; + else if (conf->dynamic_ps_timeout <= 0) + priv->powersave_mode.mode = WSM_PSM_PS; + else + priv->powersave_mode.mode = WSM_PSM_FAST_PS; + + /* Firmware requires that value for this 1-byte field must + * be specified in units of 500us. Values above the 128ms + * threshold are not supported. + */ + if (conf->dynamic_ps_timeout >= 0x80) + priv->powersave_mode.fast_psm_idle_period = 0xFF; + else + priv->powersave_mode.fast_psm_idle_period = + conf->dynamic_ps_timeout << 1; + + if (priv->join_status == CW1200_JOIN_STATUS_STA && + priv->bss_params.aid) + cw1200_set_pm(priv, &priv->powersave_mode); + } + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + /* TBD: It looks like it's transparent + * there's a monitor interface present -- use this + * to determine for example whether to calculate + * timestamps for packets or not, do not use instead + * of filter flags! + */ + } + + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + struct wsm_operational_mode mode = { + .power_mode = cw1200_power_mode, + .disable_more_flag_usage = true, + }; + + wsm_lock_tx(priv); + /* Disable p2p-dev mode forced by TX request */ + if ((priv->join_status == CW1200_JOIN_STATUS_MONITOR) && + (conf->flags & IEEE80211_CONF_IDLE) && + !priv->listening) { + cw1200_disable_listening(priv); + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + } + wsm_set_operational_mode(priv, &mode); + wsm_unlock_tx(priv); + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + pr_debug("[STA] Retry limits: %d (long), %d (short).\n", + conf->long_frame_max_tx_count, + conf->short_frame_max_tx_count); + spin_lock_bh(&priv->tx_policy_cache.lock); + priv->long_frame_max_tx_count = conf->long_frame_max_tx_count; + priv->short_frame_max_tx_count = + (conf->short_frame_max_tx_count < 0x0F) ? + conf->short_frame_max_tx_count : 0x0F; + priv->hw->max_rate_tries = priv->short_frame_max_tx_count; + spin_unlock_bh(&priv->tx_policy_cache.lock); + } + mutex_unlock(&priv->conf_mutex); + up(&priv->scan.lock); + return ret; +} + +void cw1200_update_filtering(struct cw1200_common *priv) +{ + int ret; + bool bssid_filtering = !priv->rx_filter.bssid; + bool is_p2p = priv->vif && priv->vif->p2p; + bool is_sta = priv->vif && NL80211_IFTYPE_STATION == priv->vif->type; + + static struct wsm_beacon_filter_control bf_ctrl; + static struct wsm_mib_beacon_filter_table bf_tbl = { + .entry[0].ie_id = WLAN_EID_VENDOR_SPECIFIC, + .entry[0].flags = WSM_BEACON_FILTER_IE_HAS_CHANGED | + WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | + WSM_BEACON_FILTER_IE_HAS_APPEARED, + .entry[0].oui[0] = 0x50, + .entry[0].oui[1] = 0x6F, + .entry[0].oui[2] = 0x9A, + .entry[1].ie_id = WLAN_EID_HT_OPERATION, + .entry[1].flags = WSM_BEACON_FILTER_IE_HAS_CHANGED | + WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | + WSM_BEACON_FILTER_IE_HAS_APPEARED, + .entry[2].ie_id = WLAN_EID_ERP_INFO, + .entry[2].flags = WSM_BEACON_FILTER_IE_HAS_CHANGED | + WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | + WSM_BEACON_FILTER_IE_HAS_APPEARED, + }; + + if (priv->join_status == CW1200_JOIN_STATUS_PASSIVE) + return; + else if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) + bssid_filtering = false; + + if (priv->disable_beacon_filter) { + bf_ctrl.enabled = 0; + bf_ctrl.bcn_count = 1; + bf_tbl.num = __cpu_to_le32(0); + } else if (is_p2p || !is_sta) { + bf_ctrl.enabled = WSM_BEACON_FILTER_ENABLE | + WSM_BEACON_FILTER_AUTO_ERP; + bf_ctrl.bcn_count = 0; + bf_tbl.num = __cpu_to_le32(2); + } else { + bf_ctrl.enabled = WSM_BEACON_FILTER_ENABLE; + bf_ctrl.bcn_count = 0; + bf_tbl.num = __cpu_to_le32(3); + } + + /* + * When acting as p2p client being connected to p2p GO, in order to + * receive frames from a different p2p device, turn off bssid filter. + * + * WARNING: FW dependency! + * This can only be used with FW WSM371 and its successors. + * In that FW version even with bssid filter turned off, + * device will block most of the unwanted frames. + */ + if (is_p2p) + bssid_filtering = false; + + ret = wsm_set_rx_filter(priv, &priv->rx_filter); + if (!ret) + ret = wsm_set_beacon_filter_table(priv, &bf_tbl); + if (!ret) + ret = wsm_beacon_filter_control(priv, &bf_ctrl); + if (!ret) + ret = wsm_set_bssid_filtering(priv, bssid_filtering); + if (!ret) + ret = wsm_set_multicast_filter(priv, &priv->multicast_filter); + if (ret) + wiphy_err(priv->hw->wiphy, + "Update filtering failed: %d.\n", ret); + return; +} + +void cw1200_update_filtering_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, + update_filtering_work); + + cw1200_update_filtering(priv); +} + +void cw1200_set_beacon_wakeup_period_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, + set_beacon_wakeup_period_work); + + wsm_set_beacon_wakeup_period(priv, + priv->beacon_int * priv->join_dtim_period > + MAX_BEACON_SKIP_TIME_MS ? 1 : + priv->join_dtim_period, 0); +} + +u64 cw1200_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list) +{ + static u8 broadcast_ipv6[ETH_ALEN] = { + 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 + }; + static u8 broadcast_ipv4[ETH_ALEN] = { + 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01 + }; + struct cw1200_common *priv = hw->priv; + struct netdev_hw_addr *ha; + int count = 0; + + /* Disable multicast filtering */ + priv->has_multicast_subscription = false; + memset(&priv->multicast_filter, 0x00, sizeof(priv->multicast_filter)); + + if (netdev_hw_addr_list_count(mc_list) > WSM_MAX_GRP_ADDRTABLE_ENTRIES) + return 0; + + /* Enable if requested */ + netdev_hw_addr_list_for_each(ha, mc_list) { + pr_debug("[STA] multicast: %pM\n", ha->addr); + memcpy(&priv->multicast_filter.macaddrs[count], + ha->addr, ETH_ALEN); + if (memcmp(ha->addr, broadcast_ipv4, ETH_ALEN) && + memcmp(ha->addr, broadcast_ipv6, ETH_ALEN)) + priv->has_multicast_subscription = true; + count++; + } + + if (count) { + priv->multicast_filter.enable = __cpu_to_le32(1); + priv->multicast_filter.num_addrs = __cpu_to_le32(count); + } + + return netdev_hw_addr_list_count(mc_list); +} + +void cw1200_configure_filter(struct ieee80211_hw *dev, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct cw1200_common *priv = dev->priv; + bool listening = !!(*total_flags & + (FIF_PROMISC_IN_BSS | + FIF_OTHER_BSS | + FIF_BCN_PRBRESP_PROMISC | + FIF_PROBE_REQ)); + + *total_flags &= FIF_PROMISC_IN_BSS | + FIF_OTHER_BSS | + FIF_FCSFAIL | + FIF_BCN_PRBRESP_PROMISC | + FIF_PROBE_REQ; + + down(&priv->scan.lock); + mutex_lock(&priv->conf_mutex); + + priv->rx_filter.promiscuous = (*total_flags & FIF_PROMISC_IN_BSS) + ? 1 : 0; + priv->rx_filter.bssid = (*total_flags & (FIF_OTHER_BSS | + FIF_PROBE_REQ)) ? 1 : 0; + priv->rx_filter.fcs = (*total_flags & FIF_FCSFAIL) ? 1 : 0; + priv->disable_beacon_filter = !(*total_flags & + (FIF_BCN_PRBRESP_PROMISC | + FIF_PROMISC_IN_BSS | + FIF_PROBE_REQ)); + if (priv->listening != listening) { + priv->listening = listening; + wsm_lock_tx(priv); + cw1200_update_listening(priv, listening); + wsm_unlock_tx(priv); + } + cw1200_update_filtering(priv); + mutex_unlock(&priv->conf_mutex); + up(&priv->scan.lock); +} + +int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, + u16 queue, const struct ieee80211_tx_queue_params *params) +{ + struct cw1200_common *priv = dev->priv; + int ret = 0; + /* To prevent re-applying PM request OID again and again*/ + bool old_uapsd_flags; + + mutex_lock(&priv->conf_mutex); + + if (queue < dev->queues) { + old_uapsd_flags = priv->uapsd_info.uapsd_flags; + + WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0); + ret = wsm_set_tx_queue_params(priv, + &priv->tx_queue_params.params[queue], queue); + if (ret) { + ret = -EINVAL; + goto out; + } + + WSM_EDCA_SET(&priv->edca, queue, params->aifs, + params->cw_min, params->cw_max, + params->txop, 0xc8, + params->uapsd); + ret = wsm_set_edca_params(priv, &priv->edca); + if (ret) { + ret = -EINVAL; + goto out; + } + + if (priv->mode == NL80211_IFTYPE_STATION) { + ret = cw1200_set_uapsd_param(priv, &priv->edca); + if (!ret && priv->setbssparams_done && + (priv->join_status == CW1200_JOIN_STATUS_STA) && + (old_uapsd_flags != priv->uapsd_info.uapsd_flags)) + ret = cw1200_set_pm(priv, &priv->powersave_mode); + } + } else { + ret = -EINVAL; + } + +out: + mutex_unlock(&priv->conf_mutex); + return ret; +} + +int cw1200_get_stats(struct ieee80211_hw *dev, + struct ieee80211_low_level_stats *stats) +{ + struct cw1200_common *priv = dev->priv; + + memcpy(stats, &priv->stats, sizeof(*stats)); + return 0; +} + +int cw1200_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg) +{ + struct wsm_set_pm pm = *arg; + + if (priv->uapsd_info.uapsd_flags != 0) + pm.mode &= ~WSM_PSM_FAST_PS_FLAG; + + if (memcmp(&pm, &priv->firmware_ps_mode, + sizeof(struct wsm_set_pm))) { + priv->firmware_ps_mode = pm; + return wsm_set_pm(priv, &pm); + } else { + return 0; + } +} + +int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + int ret = -EOPNOTSUPP; + struct cw1200_common *priv = dev->priv; + struct ieee80211_key_seq seq; + + mutex_lock(&priv->conf_mutex); + + if (cmd == SET_KEY) { + u8 *peer_addr = NULL; + int pairwise = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? + 1 : 0; + int idx = cw1200_alloc_key(priv); + struct wsm_add_key *wsm_key = &priv->keys[idx]; + + if (idx < 0) { + ret = -EINVAL; + goto finally; + } + + if (sta) + peer_addr = sta->addr; + + key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + if (key->keylen > 16) { + cw1200_free_key(priv, idx); + ret = -EINVAL; + goto finally; + } + + if (pairwise) { + wsm_key->type = WSM_KEY_TYPE_WEP_PAIRWISE; + memcpy(wsm_key->wep_pairwise.peer, + peer_addr, ETH_ALEN); + memcpy(wsm_key->wep_pairwise.keydata, + &key->key[0], key->keylen); + wsm_key->wep_pairwise.keylen = key->keylen; + } else { + wsm_key->type = WSM_KEY_TYPE_WEP_DEFAULT; + memcpy(wsm_key->wep_group.keydata, + &key->key[0], key->keylen); + wsm_key->wep_group.keylen = key->keylen; + wsm_key->wep_group.keyid = key->keyidx; + } + break; + case WLAN_CIPHER_SUITE_TKIP: + ieee80211_get_key_rx_seq(key, 0, &seq); + if (pairwise) { + wsm_key->type = WSM_KEY_TYPE_TKIP_PAIRWISE; + memcpy(wsm_key->tkip_pairwise.peer, + peer_addr, ETH_ALEN); + memcpy(wsm_key->tkip_pairwise.keydata, + &key->key[0], 16); + memcpy(wsm_key->tkip_pairwise.tx_mic_key, + &key->key[16], 8); + memcpy(wsm_key->tkip_pairwise.rx_mic_key, + &key->key[24], 8); + } else { + size_t mic_offset = + (priv->mode == NL80211_IFTYPE_AP) ? + 16 : 24; + wsm_key->type = WSM_KEY_TYPE_TKIP_GROUP; + memcpy(wsm_key->tkip_group.keydata, + &key->key[0], 16); + memcpy(wsm_key->tkip_group.rx_mic_key, + &key->key[mic_offset], 8); + + wsm_key->tkip_group.rx_seqnum[0] = seq.tkip.iv16 & 0xff; + wsm_key->tkip_group.rx_seqnum[1] = (seq.tkip.iv16 >> 8) & 0xff; + wsm_key->tkip_group.rx_seqnum[2] = seq.tkip.iv32 & 0xff; + wsm_key->tkip_group.rx_seqnum[3] = (seq.tkip.iv32 >> 8) & 0xff; + wsm_key->tkip_group.rx_seqnum[4] = (seq.tkip.iv32 >> 16) & 0xff; + wsm_key->tkip_group.rx_seqnum[5] = (seq.tkip.iv32 >> 24) & 0xff; + wsm_key->tkip_group.rx_seqnum[6] = 0; + wsm_key->tkip_group.rx_seqnum[7] = 0; + + wsm_key->tkip_group.keyid = key->keyidx; + } + break; + case WLAN_CIPHER_SUITE_CCMP: + ieee80211_get_key_rx_seq(key, 0, &seq); + if (pairwise) { + wsm_key->type = WSM_KEY_TYPE_AES_PAIRWISE; + memcpy(wsm_key->aes_pairwise.peer, + peer_addr, ETH_ALEN); + memcpy(wsm_key->aes_pairwise.keydata, + &key->key[0], 16); + } else { + wsm_key->type = WSM_KEY_TYPE_AES_GROUP; + memcpy(wsm_key->aes_group.keydata, + &key->key[0], 16); + + wsm_key->aes_group.rx_seqnum[0] = seq.ccmp.pn[5]; + wsm_key->aes_group.rx_seqnum[1] = seq.ccmp.pn[4]; + wsm_key->aes_group.rx_seqnum[2] = seq.ccmp.pn[3]; + wsm_key->aes_group.rx_seqnum[3] = seq.ccmp.pn[2]; + wsm_key->aes_group.rx_seqnum[4] = seq.ccmp.pn[1]; + wsm_key->aes_group.rx_seqnum[5] = seq.ccmp.pn[0]; + wsm_key->aes_group.rx_seqnum[6] = 0; + wsm_key->aes_group.rx_seqnum[7] = 0; + wsm_key->aes_group.keyid = key->keyidx; + } + break; + case WLAN_CIPHER_SUITE_SMS4: + if (pairwise) { + wsm_key->type = WSM_KEY_TYPE_WAPI_PAIRWISE; + memcpy(wsm_key->wapi_pairwise.peer, + peer_addr, ETH_ALEN); + memcpy(wsm_key->wapi_pairwise.keydata, + &key->key[0], 16); + memcpy(wsm_key->wapi_pairwise.mic_key, + &key->key[16], 16); + wsm_key->wapi_pairwise.keyid = key->keyidx; + } else { + wsm_key->type = WSM_KEY_TYPE_WAPI_GROUP; + memcpy(wsm_key->wapi_group.keydata, + &key->key[0], 16); + memcpy(wsm_key->wapi_group.mic_key, + &key->key[16], 16); + wsm_key->wapi_group.keyid = key->keyidx; + } + break; + default: + pr_warn("Unhandled key type %d\n", key->cipher); + cw1200_free_key(priv, idx); + ret = -EOPNOTSUPP; + goto finally; + } + ret = wsm_add_key(priv, wsm_key); + if (!ret) + key->hw_key_idx = idx; + else + cw1200_free_key(priv, idx); + } else if (cmd == DISABLE_KEY) { + struct wsm_remove_key wsm_key = { + .index = key->hw_key_idx, + }; + + if (wsm_key.index > WSM_KEY_MAX_INDEX) { + ret = -EINVAL; + goto finally; + } + + cw1200_free_key(priv, wsm_key.index); + ret = wsm_remove_key(priv, &wsm_key); + } else { + pr_warn("Unhandled key command %d\n", cmd); + } + +finally: + mutex_unlock(&priv->conf_mutex); + return ret; +} + +void cw1200_wep_key_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, wep_key_work); + u8 queue_id = cw1200_queue_get_queue_id(priv->pending_frame_id); + struct cw1200_queue *queue = &priv->tx_queue[queue_id]; + __le32 wep_default_key_id = __cpu_to_le32( + priv->wep_default_key_id); + + pr_debug("[STA] Setting default WEP key: %d\n", + priv->wep_default_key_id); + wsm_flush_tx(priv); + wsm_write_mib(priv, WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID, + &wep_default_key_id, sizeof(wep_default_key_id)); + cw1200_queue_requeue(queue, priv->pending_frame_id); + wsm_unlock_tx(priv); +} + +int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + int ret = 0; + __le32 val32; + struct cw1200_common *priv = hw->priv; + + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + return 0; + + if (value != (u32) -1) + val32 = __cpu_to_le32(value); + else + val32 = 0; /* disabled */ + + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) { + /* device is down, can _not_ set threshold */ + ret = -ENODEV; + goto out; + } + + if (priv->rts_threshold == value) + goto out; + + pr_debug("[STA] Setting RTS threshold: %d\n", + priv->rts_threshold); + + /* mutex_lock(&priv->conf_mutex); */ + ret = wsm_write_mib(priv, WSM_MIB_ID_DOT11_RTS_THRESHOLD, + &val32, sizeof(val32)); + if (!ret) + priv->rts_threshold = value; + /* mutex_unlock(&priv->conf_mutex); */ + +out: + return ret; +} + +/* If successful, LOCKS the TX queue! */ +static int __cw1200_flush(struct cw1200_common *priv, bool drop) +{ + int i, ret; + + for (;;) { + /* TODO: correct flush handling is required when dev_stop. + * Temporary workaround: 2s + */ + if (drop) { + for (i = 0; i < 4; ++i) + cw1200_queue_clear(&priv->tx_queue[i]); + } else { + ret = wait_event_timeout( + priv->tx_queue_stats.wait_link_id_empty, + cw1200_queue_stats_is_empty( + &priv->tx_queue_stats, -1), + 2 * HZ); + } + + if (!drop && ret <= 0) { + ret = -ETIMEDOUT; + break; + } else { + ret = 0; + } + + wsm_lock_tx(priv); + if (!cw1200_queue_stats_is_empty(&priv->tx_queue_stats, -1)) { + /* Highly unlikely: WSM requeued frames. */ + wsm_unlock_tx(priv); + continue; + } + break; + } + return ret; +} + +void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop) +{ + struct cw1200_common *priv = hw->priv; + + switch (priv->mode) { + case NL80211_IFTYPE_MONITOR: + drop = true; + break; + case NL80211_IFTYPE_AP: + if (!priv->enable_beacon) + drop = true; + break; + } + + if (!__cw1200_flush(priv, drop)) + wsm_unlock_tx(priv); + + return; +} + +/* ******************************************************************** */ +/* WSM callbacks */ + +void cw1200_free_event_queue(struct cw1200_common *priv) +{ + LIST_HEAD(list); + + spin_lock(&priv->event_queue_lock); + list_splice_init(&priv->event_queue, &list); + spin_unlock(&priv->event_queue_lock); + + __cw1200_free_event_queue(&list); +} + +void cw1200_event_handler(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, event_handler); + struct cw1200_wsm_event *event; + LIST_HEAD(list); + + spin_lock(&priv->event_queue_lock); + list_splice_init(&priv->event_queue, &list); + spin_unlock(&priv->event_queue_lock); + + list_for_each_entry(event, &list, link) { + switch (event->evt.id) { + case WSM_EVENT_ERROR: + pr_err("Unhandled WSM Error from LMAC\n"); + break; + case WSM_EVENT_BSS_LOST: + pr_debug("[CQM] BSS lost.\n"); + cancel_work_sync(&priv->unjoin_work); + if (!down_trylock(&priv->scan.lock)) { + cw1200_cqm_bssloss_sm(priv, 1, 0, 0); + up(&priv->scan.lock); + } else { + /* Scan is in progress. Delay reporting. + * Scan complete will trigger bss_loss_work + */ + priv->delayed_link_loss = 1; + /* Also start a watchdog. */ + queue_delayed_work(priv->workqueue, + &priv->bss_loss_work, 5*HZ); + } + break; + case WSM_EVENT_BSS_REGAINED: + pr_debug("[CQM] BSS regained.\n"); + cw1200_cqm_bssloss_sm(priv, 0, 0, 0); + cancel_work_sync(&priv->unjoin_work); + break; + case WSM_EVENT_RADAR_DETECTED: + wiphy_info(priv->hw->wiphy, "radar pulse detected\n"); + break; + case WSM_EVENT_RCPI_RSSI: + { + /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 + * RSSI = RCPI / 2 - 110 + */ + int rcpiRssi = (int)(event->evt.data & 0xFF); + int cqm_evt; + if (priv->cqm_use_rssi) + rcpiRssi = (s8)rcpiRssi; + else + rcpiRssi = rcpiRssi / 2 - 110; + + cqm_evt = (rcpiRssi <= priv->cqm_rssi_thold) ? + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; + pr_debug("[CQM] RSSI event: %d.\n", rcpiRssi); + ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, + GFP_KERNEL); + break; + } + case WSM_EVENT_BT_INACTIVE: + pr_warn("Unhandled BT INACTIVE from LMAC\n"); + break; + case WSM_EVENT_BT_ACTIVE: + pr_warn("Unhandled BT ACTIVE from LMAC\n"); + break; + } + } + __cw1200_free_event_queue(&list); +} + +void cw1200_bss_loss_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, bss_loss_work.work); + + pr_debug("[CQM] Reporting connection loss.\n"); + wsm_lock_tx(priv); + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); +} + +void cw1200_bss_params_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, bss_params_work); + mutex_lock(&priv->conf_mutex); + + priv->bss_params.reset_beacon_loss = 1; + wsm_set_bss_params(priv, &priv->bss_params); + priv->bss_params.reset_beacon_loss = 0; + + mutex_unlock(&priv->conf_mutex); +} + +/* ******************************************************************** */ +/* Internal API */ + +/* + * This function is called to Parse the SDD file + * to extract listen_interval and PTA related information + * sdd is a TLV: u8 id, u8 len, u8 data[] + */ +static int cw1200_parse_sdd_file(struct cw1200_common *priv) +{ + const u8 *p = priv->sdd->data; + int ret = 0; + + while (p + 2 <= priv->sdd->data + priv->sdd->size) { + if (p + p[1] + 2 > priv->sdd->data + priv->sdd->size) { + pr_warn("Malformed sdd structure\n"); + return -1; + } + switch (p[0]) { + case SDD_PTA_CFG_ELT_ID: { + u16 v; + if (p[1] < 4) { + pr_warn("SDD_PTA_CFG_ELT_ID malformed\n"); + ret = -1; + break; + } + v = le16_to_cpu(*((u16 *)(p + 2))); + if (!v) /* non-zero means this is enabled */ + break; + + v = le16_to_cpu(*((u16 *)(p + 4))); + priv->conf_listen_interval = (v >> 7) & 0x1F; + pr_debug("PTA found; Listen Interval %d\n", + priv->conf_listen_interval); + break; + } + case SDD_REFERENCE_FREQUENCY_ELT_ID: { + u16 clk = le16_to_cpu(*((u16 *)(p + 2))); + if (clk != priv->hw_refclk) + pr_warn("SDD file doesn't match configured refclk (%d vs %d)\n", + clk, priv->hw_refclk); + break; + } + default: + break; + } + p += p[1] + 2; + } + + if (!priv->bt_present) { + pr_debug("PTA element NOT found.\n"); + priv->conf_listen_interval = 0; + } + return ret; +} + +int cw1200_setup_mac(struct cw1200_common *priv) +{ + int ret = 0; + + /* NOTE: There is a bug in FW: it reports signal + * as RSSI if RSSI subscription is enabled. + * It's not enough to set WSM_RCPI_RSSI_USE_RSSI. + * + * NOTE2: RSSI based reports have been switched to RCPI, since + * FW has a bug and RSSI reported values are not stable, + * what can leads to signal level oscilations in user-end applications + */ + struct wsm_rcpi_rssi_threshold threshold = { + .rssiRcpiMode = WSM_RCPI_RSSI_THRESHOLD_ENABLE | + WSM_RCPI_RSSI_DONT_USE_UPPER | + WSM_RCPI_RSSI_DONT_USE_LOWER, + .rollingAverageCount = 16, + }; + + struct wsm_configuration cfg = { + .dot11StationId = &priv->mac_addr[0], + }; + + /* Remember the decission here to make sure, we will handle + * the RCPI/RSSI value correctly on WSM_EVENT_RCPI_RSS + */ + if (threshold.rssiRcpiMode & WSM_RCPI_RSSI_USE_RSSI) + priv->cqm_use_rssi = true; + + if (!priv->sdd) { + ret = request_firmware(&priv->sdd, priv->sdd_path, priv->pdev); + if (ret) { + pr_err("Can't load sdd file %s.\n", priv->sdd_path); + return ret; + } + cw1200_parse_sdd_file(priv); + } + + cfg.dpdData = priv->sdd->data; + cfg.dpdData_size = priv->sdd->size; + ret = wsm_configuration(priv, &cfg); + if (ret) + return ret; + + /* Configure RSSI/SCPI reporting as RSSI. */ + wsm_set_rcpi_rssi_threshold(priv, &threshold); + + return 0; +} + +static void cw1200_join_complete(struct cw1200_common *priv) +{ + pr_debug("[STA] Join complete (%d)\n", priv->join_complete_status); + + priv->join_pending = false; + if (priv->join_complete_status) { + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + cw1200_update_listening(priv, priv->listening); + cw1200_do_unjoin(priv); + ieee80211_connection_loss(priv->vif); + } else { + if (priv->mode == NL80211_IFTYPE_ADHOC) + priv->join_status = CW1200_JOIN_STATUS_IBSS; + else + priv->join_status = CW1200_JOIN_STATUS_PRE_STA; + } + wsm_unlock_tx(priv); /* Clearing the lock held before do_join() */ +} + +void cw1200_join_complete_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, join_complete_work); + mutex_lock(&priv->conf_mutex); + cw1200_join_complete(priv); + mutex_unlock(&priv->conf_mutex); +} + +void cw1200_join_complete_cb(struct cw1200_common *priv, + struct wsm_join_complete *arg) +{ + pr_debug("[STA] cw1200_join_complete_cb called, status=%d.\n", + arg->status); + + if (cancel_delayed_work(&priv->join_timeout)) { + priv->join_complete_status = arg->status; + queue_work(priv->workqueue, &priv->join_complete_work); + } +} + +/* MUST be called with tx_lock held! It will be unlocked for us. */ +static void cw1200_do_join(struct cw1200_common *priv) +{ + const u8 *bssid; + struct ieee80211_bss_conf *conf = &priv->vif->bss_conf; + struct cfg80211_bss *bss = NULL; + struct wsm_protected_mgmt_policy mgmt_policy; + struct wsm_join join = { + .mode = conf->ibss_joined ? + WSM_JOIN_MODE_IBSS : WSM_JOIN_MODE_BSS, + .preamble_type = WSM_JOIN_PREAMBLE_LONG, + .probe_for_join = 1, + .atim_window = 0, + .basic_rate_set = cw1200_rate_mask_to_wsm(priv, + conf->basic_rates), + }; + if (delayed_work_pending(&priv->join_timeout)) { + pr_warn("[STA] - Join request already pending, skipping..\n"); + wsm_unlock_tx(priv); + return; + } + + if (priv->join_status) + cw1200_do_unjoin(priv); + + bssid = priv->vif->bss_conf.bssid; + + bss = cfg80211_get_bss(priv->hw->wiphy, priv->channel, + bssid, NULL, 0, 0, 0); + + if (!bss && !conf->ibss_joined) { + wsm_unlock_tx(priv); + return; + } + + mutex_lock(&priv->conf_mutex); + + /* Under the conf lock: check scan status and + * bail out if it is in progress. + */ + if (atomic_read(&priv->scan.in_progress)) { + wsm_unlock_tx(priv); + goto done_put; + } + + priv->join_pending = true; + + /* Sanity check basic rates */ + if (!join.basic_rate_set) + join.basic_rate_set = 7; + + /* Sanity check beacon interval */ + if (!priv->beacon_int) + priv->beacon_int = 1; + + join.beacon_interval = priv->beacon_int; + + /* BT Coex related changes */ + if (priv->bt_present) { + if (((priv->conf_listen_interval * 100) % + priv->beacon_int) == 0) + priv->listen_interval = + ((priv->conf_listen_interval * 100) / + priv->beacon_int); + else + priv->listen_interval = + ((priv->conf_listen_interval * 100) / + priv->beacon_int + 1); + } + + if (priv->hw->conf.ps_dtim_period) + priv->join_dtim_period = priv->hw->conf.ps_dtim_period; + join.dtim_period = priv->join_dtim_period; + + join.channel_number = priv->channel->hw_value; + join.band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; + + memcpy(join.bssid, bssid, sizeof(join.bssid)); + + pr_debug("[STA] Join BSSID: %pM DTIM: %d, interval: %d\n", + join.bssid, + join.dtim_period, priv->beacon_int); + + if (!conf->ibss_joined) { + const u8 *ssidie; + rcu_read_lock(); + ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); + if (ssidie) { + join.ssid_len = ssidie[1]; + memcpy(join.ssid, &ssidie[2], join.ssid_len); + } + rcu_read_unlock(); + } + + if (priv->vif->p2p) { + join.flags |= WSM_JOIN_FLAGS_P2P_GO; + join.basic_rate_set = + cw1200_rate_mask_to_wsm(priv, 0xFF0); + } + + /* Enable asynchronous join calls */ + if (!conf->ibss_joined) { + join.flags |= WSM_JOIN_FLAGS_FORCE; + join.flags |= WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND; + } + + wsm_flush_tx(priv); + + /* Stay Awake for Join and Auth Timeouts and a bit more */ + cw1200_pm_stay_awake(&priv->pm_state, + CW1200_JOIN_TIMEOUT + CW1200_AUTH_TIMEOUT); + + cw1200_update_listening(priv, false); + + /* Turn on Block ACKs */ + wsm_set_block_ack_policy(priv, priv->ba_tx_tid_mask, + priv->ba_rx_tid_mask); + + /* Set up timeout */ + if (join.flags & WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND) { + priv->join_status = CW1200_JOIN_STATUS_JOINING; + queue_delayed_work(priv->workqueue, + &priv->join_timeout, + CW1200_JOIN_TIMEOUT); + } + + /* 802.11w protected mgmt frames */ + mgmt_policy.protectedMgmtEnable = 0; + mgmt_policy.unprotectedMgmtFramesAllowed = 1; + mgmt_policy.encryptionForAuthFrame = 1; + wsm_set_protected_mgmt_policy(priv, &mgmt_policy); + + /* Perform actual join */ + if (wsm_join(priv, &join)) { + pr_err("[STA] cw1200_join_work: wsm_join failed!\n"); + cancel_delayed_work_sync(&priv->join_timeout); + cw1200_update_listening(priv, priv->listening); + /* Tx lock still held, unjoin will clear it. */ + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + } else { + if (!(join.flags & WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND)) + cw1200_join_complete(priv); /* Will clear tx_lock */ + + /* Upload keys */ + cw1200_upload_keys(priv); + + /* Due to beacon filtering it is possible that the + * AP's beacon is not known for the mac80211 stack. + * Disable filtering temporary to make sure the stack + * receives at least one + */ + priv->disable_beacon_filter = true; + } + cw1200_update_filtering(priv); + +done_put: + mutex_unlock(&priv->conf_mutex); + if (bss) + cfg80211_put_bss(priv->hw->wiphy, bss); +} + +void cw1200_join_timeout(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, join_timeout.work); + pr_debug("[WSM] Join timed out.\n"); + wsm_lock_tx(priv); + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); +} + +static void cw1200_do_unjoin(struct cw1200_common *priv) +{ + struct wsm_reset reset = { + .reset_statistics = true, + }; + + cancel_delayed_work_sync(&priv->join_timeout); + + mutex_lock(&priv->conf_mutex); + priv->join_pending = false; + + if (atomic_read(&priv->scan.in_progress)) { + if (priv->delayed_unjoin) + wiphy_dbg(priv->hw->wiphy, "Delayed unjoin is already scheduled.\n"); + else + priv->delayed_unjoin = true; + goto done; + } + + priv->delayed_link_loss = false; + + if (!priv->join_status) + goto done; + + if (priv->join_status > CW1200_JOIN_STATUS_IBSS) { + wiphy_err(priv->hw->wiphy, "Unexpected: join status: %d\n", + priv->join_status); + BUG_ON(1); + } + + cancel_work_sync(&priv->update_filtering_work); + cancel_work_sync(&priv->set_beacon_wakeup_period_work); + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + + /* Unjoin is a reset. */ + wsm_flush_tx(priv); + wsm_keep_alive_period(priv, 0); + wsm_reset(priv, &reset); + wsm_set_output_power(priv, priv->output_power * 10); + priv->join_dtim_period = 0; + cw1200_setup_mac(priv); + cw1200_free_event_queue(priv); + cancel_work_sync(&priv->event_handler); + cw1200_update_listening(priv, priv->listening); + cw1200_cqm_bssloss_sm(priv, 0, 0, 0); + + /* Disable Block ACKs */ + wsm_set_block_ack_policy(priv, 0, 0); + + priv->disable_beacon_filter = false; + cw1200_update_filtering(priv); + memset(&priv->association_mode, 0, + sizeof(priv->association_mode)); + memset(&priv->bss_params, 0, sizeof(priv->bss_params)); + priv->setbssparams_done = false; + memset(&priv->firmware_ps_mode, 0, + sizeof(priv->firmware_ps_mode)); + + pr_debug("[STA] Unjoin completed.\n"); + +done: + mutex_unlock(&priv->conf_mutex); +} + +void cw1200_unjoin_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, unjoin_work); + + cw1200_do_unjoin(priv); + + /* Tell the stack we're dead */ + ieee80211_connection_loss(priv->vif); + + wsm_unlock_tx(priv); +} + +int cw1200_enable_listening(struct cw1200_common *priv) +{ + struct wsm_start start = { + .mode = WSM_START_MODE_P2P_DEV, + .band = WSM_PHY_BAND_2_4G, + .beacon_interval = 100, + .dtim_period = 1, + .probe_delay = 0, + .basic_rate_set = 0x0F, + }; + + if (priv->channel) { + start.band = priv->channel->band == IEEE80211_BAND_5GHZ ? + WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G; + start.channel_number = priv->channel->hw_value; + } else { + start.band = WSM_PHY_BAND_2_4G; + start.channel_number = 1; + } + + return wsm_start(priv, &start); +} + +int cw1200_disable_listening(struct cw1200_common *priv) +{ + int ret; + struct wsm_reset reset = { + .reset_statistics = true, + }; + ret = wsm_reset(priv, &reset); + return ret; +} + +void cw1200_update_listening(struct cw1200_common *priv, bool enabled) +{ + if (enabled) { + if (priv->join_status == CW1200_JOIN_STATUS_PASSIVE) { + if (!cw1200_enable_listening(priv)) + priv->join_status = CW1200_JOIN_STATUS_MONITOR; + wsm_set_probe_responder(priv, true); + } + } else { + if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) { + if (!cw1200_disable_listening(priv)) + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + wsm_set_probe_responder(priv, false); + } + } +} + +int cw1200_set_uapsd_param(struct cw1200_common *priv, + const struct wsm_edca_params *arg) +{ + int ret; + u16 uapsd_flags = 0; + + /* Here's the mapping AC [queue, bit] + * VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0] + */ + + if (arg->uapsd_enable[0]) + uapsd_flags |= 1 << 3; + + if (arg->uapsd_enable[1]) + uapsd_flags |= 1 << 2; + + if (arg->uapsd_enable[2]) + uapsd_flags |= 1 << 1; + + if (arg->uapsd_enable[3]) + uapsd_flags |= 1; + + /* Currently pseudo U-APSD operation is not supported, so setting + * MinAutoTriggerInterval, MaxAutoTriggerInterval and + * AutoTriggerStep to 0 + */ + + priv->uapsd_info.uapsd_flags = cpu_to_le16(uapsd_flags); + priv->uapsd_info.min_auto_trigger_interval = 0; + priv->uapsd_info.max_auto_trigger_interval = 0; + priv->uapsd_info.auto_trigger_step = 0; + + ret = wsm_set_uapsd_info(priv, &priv->uapsd_info); + return ret; +} + +/* ******************************************************************** */ +/* AP API */ + +int cw1200_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct cw1200_common *priv = hw->priv; + struct cw1200_sta_priv *sta_priv = + (struct cw1200_sta_priv *)&sta->drv_priv; + struct cw1200_link_entry *entry; + struct sk_buff *skb; + + if (priv->mode != NL80211_IFTYPE_AP) + return 0; + + sta_priv->link_id = cw1200_find_link_id(priv, sta->addr); + if (WARN_ON(!sta_priv->link_id)) { + wiphy_info(priv->hw->wiphy, + "[AP] No more link IDs available.\n"); + return -ENOENT; + } + + entry = &priv->link_id_db[sta_priv->link_id - 1]; + spin_lock_bh(&priv->ps_state_lock); + if ((sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) == + IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) + priv->sta_asleep_mask |= BIT(sta_priv->link_id); + entry->status = CW1200_LINK_HARD; + while ((skb = skb_dequeue(&entry->rx_queue))) + ieee80211_rx_irqsafe(priv->hw, skb); + spin_unlock_bh(&priv->ps_state_lock); + return 0; +} + +int cw1200_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct cw1200_common *priv = hw->priv; + struct cw1200_sta_priv *sta_priv = + (struct cw1200_sta_priv *)&sta->drv_priv; + struct cw1200_link_entry *entry; + + if (priv->mode != NL80211_IFTYPE_AP || !sta_priv->link_id) + return 0; + + entry = &priv->link_id_db[sta_priv->link_id - 1]; + spin_lock_bh(&priv->ps_state_lock); + entry->status = CW1200_LINK_RESERVE; + entry->timestamp = jiffies; + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, &priv->link_id_work) <= 0) + wsm_unlock_tx(priv); + spin_unlock_bh(&priv->ps_state_lock); + flush_workqueue(priv->workqueue); + return 0; +} + +static void __cw1200_sta_notify(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + enum sta_notify_cmd notify_cmd, + int link_id) +{ + struct cw1200_common *priv = dev->priv; + u32 bit, prev; + + /* Zero link id means "for all link IDs" */ + if (link_id) + bit = BIT(link_id); + else if (WARN_ON_ONCE(notify_cmd != STA_NOTIFY_AWAKE)) + bit = 0; + else + bit = priv->link_id_map; + prev = priv->sta_asleep_mask & bit; + + switch (notify_cmd) { + case STA_NOTIFY_SLEEP: + if (!prev) { + if (priv->buffered_multicasts && + !priv->sta_asleep_mask) + queue_work(priv->workqueue, + &priv->multicast_start_work); + priv->sta_asleep_mask |= bit; + } + break; + case STA_NOTIFY_AWAKE: + if (prev) { + priv->sta_asleep_mask &= ~bit; + priv->pspoll_mask &= ~bit; + if (priv->tx_multicast && link_id && + !priv->sta_asleep_mask) + queue_work(priv->workqueue, + &priv->multicast_stop_work); + cw1200_bh_wakeup(priv); + } + break; + } +} + +void cw1200_sta_notify(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + enum sta_notify_cmd notify_cmd, + struct ieee80211_sta *sta) +{ + struct cw1200_common *priv = dev->priv; + struct cw1200_sta_priv *sta_priv = + (struct cw1200_sta_priv *)&sta->drv_priv; + + spin_lock_bh(&priv->ps_state_lock); + __cw1200_sta_notify(dev, vif, notify_cmd, sta_priv->link_id); + spin_unlock_bh(&priv->ps_state_lock); +} + +static void cw1200_ps_notify(struct cw1200_common *priv, + int link_id, bool ps) +{ + if (link_id > CW1200_MAX_STA_IN_AP_MODE) + return; + + pr_debug("%s for LinkId: %d. STAs asleep: %.8X\n", + ps ? "Stop" : "Start", + link_id, priv->sta_asleep_mask); + + __cw1200_sta_notify(priv->hw, priv->vif, + ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, link_id); +} + +static int cw1200_set_tim_impl(struct cw1200_common *priv, bool aid0_bit_set) +{ + struct sk_buff *skb; + struct wsm_update_ie update_ie = { + .what = WSM_UPDATE_IE_BEACON, + .count = 1, + }; + u16 tim_offset, tim_length; + + pr_debug("[AP] mcast: %s.\n", aid0_bit_set ? "ena" : "dis"); + + skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, + &tim_offset, &tim_length); + if (!skb) { + if (!__cw1200_flush(priv, true)) + wsm_unlock_tx(priv); + return -ENOENT; + } + + if (tim_offset && tim_length >= 6) { + /* Ignore DTIM count from mac80211: + * firmware handles DTIM internally. + */ + skb->data[tim_offset + 2] = 0; + + /* Set/reset aid0 bit */ + if (aid0_bit_set) + skb->data[tim_offset + 4] |= 1; + else + skb->data[tim_offset + 4] &= ~1; + } + + update_ie.ies = &skb->data[tim_offset]; + update_ie.length = tim_length; + wsm_update_ie(priv, &update_ie); + + dev_kfree_skb(skb); + + return 0; +} + +void cw1200_set_tim_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, set_tim_work); + (void)cw1200_set_tim_impl(priv, priv->aid0_bit_set); +} + +int cw1200_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, + bool set) +{ + struct cw1200_common *priv = dev->priv; + queue_work(priv->workqueue, &priv->set_tim_work); + return 0; +} + +void cw1200_set_cts_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, set_cts_work); + + u8 erp_ie[3] = {WLAN_EID_ERP_INFO, 0x1, 0}; + struct wsm_update_ie update_ie = { + .what = WSM_UPDATE_IE_BEACON, + .count = 1, + .ies = erp_ie, + .length = 3, + }; + u32 erp_info; + __le32 use_cts_prot; + mutex_lock(&priv->conf_mutex); + erp_info = priv->erp_info; + mutex_unlock(&priv->conf_mutex); + use_cts_prot = + erp_info & WLAN_ERP_USE_PROTECTION ? + __cpu_to_le32(1) : 0; + + erp_ie[ERP_INFO_BYTE_OFFSET] = erp_info; + + pr_debug("[STA] ERP information 0x%x\n", erp_info); + + wsm_write_mib(priv, WSM_MIB_ID_NON_ERP_PROTECTION, + &use_cts_prot, sizeof(use_cts_prot)); + wsm_update_ie(priv, &update_ie); + + return; +} + +static int cw1200_set_btcoexinfo(struct cw1200_common *priv) +{ + struct wsm_override_internal_txrate arg; + int ret = 0; + + if (priv->mode == NL80211_IFTYPE_STATION) { + /* Plumb PSPOLL and NULL template */ + cw1200_upload_pspoll(priv); + cw1200_upload_null(priv); + cw1200_upload_qosnull(priv); + } else { + return 0; + } + + memset(&arg, 0, sizeof(struct wsm_override_internal_txrate)); + + if (!priv->vif->p2p) { + /* STATION mode */ + if (priv->bss_params.operational_rate_set & ~0xF) { + pr_debug("[STA] STA has ERP rates\n"); + /* G or BG mode */ + arg.internalTxRate = (__ffs( + priv->bss_params.operational_rate_set & ~0xF)); + } else { + pr_debug("[STA] STA has non ERP rates\n"); + /* B only mode */ + arg.internalTxRate = (__ffs(priv->association_mode.basic_rate_set)); + } + arg.nonErpInternalTxRate = (__ffs(priv->association_mode.basic_rate_set)); + } else { + /* P2P mode */ + arg.internalTxRate = (__ffs(priv->bss_params.operational_rate_set & ~0xF)); + arg.nonErpInternalTxRate = (__ffs(priv->bss_params.operational_rate_set & ~0xF)); + } + + pr_debug("[STA] BTCOEX_INFO MODE %d, internalTxRate : %x, nonErpInternalTxRate: %x\n", + priv->mode, + arg.internalTxRate, + arg.nonErpInternalTxRate); + + ret = wsm_write_mib(priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE, + &arg, sizeof(arg)); + + return ret; +} + +void cw1200_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct cw1200_common *priv = dev->priv; + bool do_join = false; + + mutex_lock(&priv->conf_mutex); + + pr_debug("BSS CHANGED: %08x\n", changed); + + /* TODO: BSS_CHANGED_QOS */ + /* TODO: BSS_CHANGED_TXPOWER */ + + if (changed & BSS_CHANGED_ARP_FILTER) { + struct wsm_mib_arp_ipv4_filter filter = {0}; + int i; + + pr_debug("[STA] BSS_CHANGED_ARP_FILTER cnt: %d\n", + info->arp_addr_cnt); + + /* Currently only one IP address is supported by firmware. + * In case of more IPs arp filtering will be disabled. + */ + if (info->arp_addr_cnt > 0 && + info->arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) { + for (i = 0; i < info->arp_addr_cnt; i++) { + filter.ipv4addrs[i] = info->arp_addr_list[i]; + pr_debug("[STA] addr[%d]: 0x%X\n", + i, filter.ipv4addrs[i]); + } + filter.enable = __cpu_to_le32(1); + } + + pr_debug("[STA] arp ip filter enable: %d\n", + __le32_to_cpu(filter.enable)); + + wsm_set_arp_ipv4_filter(priv, &filter); + } + + if (changed & + (BSS_CHANGED_BEACON | + BSS_CHANGED_AP_PROBE_RESP | + BSS_CHANGED_BSSID | + BSS_CHANGED_SSID | + BSS_CHANGED_IBSS)) { + pr_debug("BSS_CHANGED_BEACON\n"); + priv->beacon_int = info->beacon_int; + cw1200_update_beaconing(priv); + cw1200_upload_beacon(priv); + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) { + pr_debug("BSS_CHANGED_BEACON_ENABLED (%d)\n", info->enable_beacon); + + if (priv->enable_beacon != info->enable_beacon) { + cw1200_enable_beaconing(priv, info->enable_beacon); + priv->enable_beacon = info->enable_beacon; + } + } + + if (changed & BSS_CHANGED_BEACON_INT) { + pr_debug("CHANGED_BEACON_INT\n"); + if (info->ibss_joined) + do_join = true; + else if (priv->join_status == CW1200_JOIN_STATUS_AP) + cw1200_update_beaconing(priv); + } + + /* assoc/disassoc, or maybe AID changed */ + if (changed & BSS_CHANGED_ASSOC) { + wsm_lock_tx(priv); + priv->wep_default_key_id = -1; + wsm_unlock_tx(priv); + } + + if (changed & BSS_CHANGED_BSSID) { + pr_debug("BSS_CHANGED_BSSID\n"); + do_join = true; + } + + if (changed & + (BSS_CHANGED_ASSOC | + BSS_CHANGED_BSSID | + BSS_CHANGED_IBSS | + BSS_CHANGED_BASIC_RATES | + BSS_CHANGED_HT)) { + pr_debug("BSS_CHANGED_ASSOC\n"); + if (info->assoc) { + if (priv->join_status < CW1200_JOIN_STATUS_PRE_STA) { + ieee80211_connection_loss(vif); + mutex_unlock(&priv->conf_mutex); + return; + } else if (priv->join_status == CW1200_JOIN_STATUS_PRE_STA) { + priv->join_status = CW1200_JOIN_STATUS_STA; + } + } else { + do_join = true; + } + + if (info->assoc || info->ibss_joined) { + struct ieee80211_sta *sta = NULL; + u32 val = 0; + + if (info->dtim_period) + priv->join_dtim_period = info->dtim_period; + priv->beacon_int = info->beacon_int; + + rcu_read_lock(); + + if (info->bssid && !info->ibss_joined) + sta = ieee80211_find_sta(vif, info->bssid); + if (sta) { + priv->ht_info.ht_cap = sta->ht_cap; + priv->bss_params.operational_rate_set = + cw1200_rate_mask_to_wsm(priv, + sta->supp_rates[priv->channel->band]); + priv->ht_info.channel_type = cfg80211_get_chandef_type(&dev->conf.chandef); + priv->ht_info.operation_mode = info->ht_operation_mode; + } else { + memset(&priv->ht_info, 0, + sizeof(priv->ht_info)); + priv->bss_params.operational_rate_set = -1; + } + rcu_read_unlock(); + + /* Non Greenfield stations present */ + if (priv->ht_info.operation_mode & + IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) + val |= WSM_NON_GREENFIELD_STA_PRESENT; + + /* Set HT protection method */ + val |= (priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2; + + /* TODO: + * STBC_param.dual_cts + * STBC_param.LSIG_TXOP_FILL + */ + + val = cpu_to_le32(val); + wsm_write_mib(priv, WSM_MIB_ID_SET_HT_PROTECTION, + &val, sizeof(val)); + + priv->association_mode.greenfield = + cw1200_ht_greenfield(&priv->ht_info); + priv->association_mode.flags = + WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES | + WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE | + WSM_ASSOCIATION_MODE_USE_HT_MODE | + WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET | + WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING; + priv->association_mode.preamble = + info->use_short_preamble ? + WSM_JOIN_PREAMBLE_SHORT : + WSM_JOIN_PREAMBLE_LONG; + priv->association_mode.basic_rate_set = __cpu_to_le32( + cw1200_rate_mask_to_wsm(priv, + info->basic_rates)); + priv->association_mode.mpdu_start_spacing = + cw1200_ht_ampdu_density(&priv->ht_info); + + cw1200_cqm_bssloss_sm(priv, 0, 0, 0); + cancel_work_sync(&priv->unjoin_work); + + priv->bss_params.beacon_lost_count = priv->cqm_beacon_loss_count; + priv->bss_params.aid = info->aid; + + if (priv->join_dtim_period < 1) + priv->join_dtim_period = 1; + + pr_debug("[STA] DTIM %d, interval: %d\n", + priv->join_dtim_period, priv->beacon_int); + pr_debug("[STA] Preamble: %d, Greenfield: %d, Aid: %d, Rates: 0x%.8X, Basic: 0x%.8X\n", + priv->association_mode.preamble, + priv->association_mode.greenfield, + priv->bss_params.aid, + priv->bss_params.operational_rate_set, + priv->association_mode.basic_rate_set); + wsm_set_association_mode(priv, &priv->association_mode); + + if (!info->ibss_joined) { + wsm_keep_alive_period(priv, 30 /* sec */); + wsm_set_bss_params(priv, &priv->bss_params); + priv->setbssparams_done = true; + cw1200_set_beacon_wakeup_period_work(&priv->set_beacon_wakeup_period_work); + cw1200_set_pm(priv, &priv->powersave_mode); + } + if (priv->vif->p2p) { + pr_debug("[STA] Setting p2p powersave configuration.\n"); + wsm_set_p2p_ps_modeinfo(priv, + &priv->p2p_ps_modeinfo); + } + if (priv->bt_present) + cw1200_set_btcoexinfo(priv); + } else { + memset(&priv->association_mode, 0, + sizeof(priv->association_mode)); + memset(&priv->bss_params, 0, sizeof(priv->bss_params)); + } + } + + /* ERP Protection */ + if (changed & (BSS_CHANGED_ASSOC | + BSS_CHANGED_ERP_CTS_PROT | + BSS_CHANGED_ERP_PREAMBLE)) { + u32 prev_erp_info = priv->erp_info; + if (info->use_cts_prot) + priv->erp_info |= WLAN_ERP_USE_PROTECTION; + else if (!(prev_erp_info & WLAN_ERP_NON_ERP_PRESENT)) + priv->erp_info &= ~WLAN_ERP_USE_PROTECTION; + + if (info->use_short_preamble) + priv->erp_info |= WLAN_ERP_BARKER_PREAMBLE; + else + priv->erp_info &= ~WLAN_ERP_BARKER_PREAMBLE; + + pr_debug("[STA] ERP Protection: %x\n", priv->erp_info); + + if (prev_erp_info != priv->erp_info) + queue_work(priv->workqueue, &priv->set_cts_work); + } + + /* ERP Slottime */ + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_SLOT)) { + __le32 slot_time = info->use_short_slot ? + __cpu_to_le32(9) : __cpu_to_le32(20); + pr_debug("[STA] Slot time: %d us.\n", + __le32_to_cpu(slot_time)); + wsm_write_mib(priv, WSM_MIB_ID_DOT11_SLOT_TIME, + &slot_time, sizeof(slot_time)); + } + + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_CQM)) { + struct wsm_rcpi_rssi_threshold threshold = { + .rollingAverageCount = 8, + }; + pr_debug("[CQM] RSSI threshold subscribe: %d +- %d\n", + info->cqm_rssi_thold, info->cqm_rssi_hyst); + priv->cqm_rssi_thold = info->cqm_rssi_thold; + priv->cqm_rssi_hyst = info->cqm_rssi_hyst; + + if (info->cqm_rssi_thold || info->cqm_rssi_hyst) { + /* RSSI subscription enabled */ + /* TODO: It's not a correct way of setting threshold. + * Upper and lower must be set equal here and adjusted + * in callback. However current implementation is much + * more relaible and stable. + */ + + /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 + * RSSI = RCPI / 2 - 110 + */ + if (priv->cqm_use_rssi) { + threshold.upperThreshold = + info->cqm_rssi_thold + info->cqm_rssi_hyst; + threshold.lowerThreshold = + info->cqm_rssi_thold; + threshold.rssiRcpiMode |= WSM_RCPI_RSSI_USE_RSSI; + } else { + threshold.upperThreshold = (info->cqm_rssi_thold + info->cqm_rssi_hyst + 110) * 2; + threshold.lowerThreshold = (info->cqm_rssi_thold + 110) * 2; + } + threshold.rssiRcpiMode |= WSM_RCPI_RSSI_THRESHOLD_ENABLE; + } else { + /* There is a bug in FW, see sta.c. We have to enable + * dummy subscription to get correct RSSI values. + */ + threshold.rssiRcpiMode |= + WSM_RCPI_RSSI_THRESHOLD_ENABLE | + WSM_RCPI_RSSI_DONT_USE_UPPER | + WSM_RCPI_RSSI_DONT_USE_LOWER; + if (priv->cqm_use_rssi) + threshold.rssiRcpiMode |= WSM_RCPI_RSSI_USE_RSSI; + } + wsm_set_rcpi_rssi_threshold(priv, &threshold); + } + mutex_unlock(&priv->conf_mutex); + + if (do_join) { + wsm_lock_tx(priv); + cw1200_do_join(priv); /* Will unlock it for us */ + } +} + +void cw1200_multicast_start_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, multicast_start_work); + long tmo = priv->join_dtim_period * + (priv->beacon_int + 20) * HZ / 1024; + + cancel_work_sync(&priv->multicast_stop_work); + + if (!priv->aid0_bit_set) { + wsm_lock_tx(priv); + cw1200_set_tim_impl(priv, true); + priv->aid0_bit_set = true; + mod_timer(&priv->mcast_timeout, jiffies + tmo); + wsm_unlock_tx(priv); + } +} + +void cw1200_multicast_stop_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, multicast_stop_work); + + if (priv->aid0_bit_set) { + del_timer_sync(&priv->mcast_timeout); + wsm_lock_tx(priv); + priv->aid0_bit_set = false; + cw1200_set_tim_impl(priv, false); + wsm_unlock_tx(priv); + } +} + +void cw1200_mcast_timeout(unsigned long arg) +{ + struct cw1200_common *priv = + (struct cw1200_common *)arg; + + wiphy_warn(priv->hw->wiphy, + "Multicast delivery timeout.\n"); + spin_lock_bh(&priv->ps_state_lock); + priv->tx_multicast = priv->aid0_bit_set && + priv->buffered_multicasts; + if (priv->tx_multicast) + cw1200_bh_wakeup(priv); + spin_unlock_bh(&priv->ps_state_lock); +} + +int cw1200_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size) +{ + /* Aggregation is implemented fully in firmware, + * including block ack negotiation. Do not allow + * mac80211 stack to do anything: it interferes with + * the firmware. + */ + + /* Note that we still need this function stubbed. */ + return -ENOTSUPP; +} + +/* ******************************************************************** */ +/* WSM callback */ +void cw1200_suspend_resume(struct cw1200_common *priv, + struct wsm_suspend_resume *arg) +{ + pr_debug("[AP] %s: %s\n", + arg->stop ? "stop" : "start", + arg->multicast ? "broadcast" : "unicast"); + + if (arg->multicast) { + bool cancel_tmo = false; + spin_lock_bh(&priv->ps_state_lock); + if (arg->stop) { + priv->tx_multicast = false; + } else { + /* Firmware sends this indication every DTIM if there + * is a STA in powersave connected. There is no reason + * to suspend, following wakeup will consume much more + * power than it could be saved. + */ + cw1200_pm_stay_awake(&priv->pm_state, + priv->join_dtim_period * + (priv->beacon_int + 20) * HZ / 1024); + priv->tx_multicast = (priv->aid0_bit_set && + priv->buffered_multicasts); + if (priv->tx_multicast) { + cancel_tmo = true; + cw1200_bh_wakeup(priv); + } + } + spin_unlock_bh(&priv->ps_state_lock); + if (cancel_tmo) + del_timer_sync(&priv->mcast_timeout); + } else { + spin_lock_bh(&priv->ps_state_lock); + cw1200_ps_notify(priv, arg->link_id, arg->stop); + spin_unlock_bh(&priv->ps_state_lock); + if (!arg->stop) + cw1200_bh_wakeup(priv); + } + return; +} + +/* ******************************************************************** */ +/* AP privates */ + +static int cw1200_upload_beacon(struct cw1200_common *priv) +{ + int ret = 0; + struct ieee80211_mgmt *mgmt; + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_BEACON, + }; + + u16 tim_offset; + u16 tim_len; + + if (priv->mode == NL80211_IFTYPE_STATION || + priv->mode == NL80211_IFTYPE_MONITOR || + priv->mode == NL80211_IFTYPE_UNSPECIFIED) + goto done; + + if (priv->vif->p2p) + frame.rate = WSM_TRANSMIT_RATE_6; + + frame.skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, + &tim_offset, &tim_len); + if (!frame.skb) + return -ENOMEM; + + ret = wsm_set_template_frame(priv, &frame); + + if (ret) + goto done; + + /* TODO: Distill probe resp; remove TIM + * and any other beacon-specific IEs + */ + mgmt = (void *)frame.skb->data; + mgmt->frame_control = + __cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); + + frame.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE; + if (priv->vif->p2p) { + ret = wsm_set_probe_responder(priv, true); + } else { + ret = wsm_set_template_frame(priv, &frame); + wsm_set_probe_responder(priv, false); + } + +done: + dev_kfree_skb(frame.skb); + + return ret; +} + +static int cw1200_upload_pspoll(struct cw1200_common *priv) +{ + int ret = 0; + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_PS_POLL, + .rate = 0xFF, + }; + + + frame.skb = ieee80211_pspoll_get(priv->hw, priv->vif); + if (!frame.skb) + return -ENOMEM; + + ret = wsm_set_template_frame(priv, &frame); + + dev_kfree_skb(frame.skb); + + return ret; +} + +static int cw1200_upload_null(struct cw1200_common *priv) +{ + int ret = 0; + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_NULL, + .rate = 0xFF, + }; + + frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif); + if (!frame.skb) + return -ENOMEM; + + ret = wsm_set_template_frame(priv, &frame); + + dev_kfree_skb(frame.skb); + + return ret; +} + +static int cw1200_upload_qosnull(struct cw1200_common *priv) +{ + int ret = 0; + /* TODO: This needs to be implemented + + struct wsm_template_frame frame = { + .frame_type = WSM_FRAME_TYPE_QOS_NULL, + .rate = 0xFF, + }; + + frame.skb = ieee80211_qosnullfunc_get(priv->hw, priv->vif); + if (!frame.skb) + return -ENOMEM; + + ret = wsm_set_template_frame(priv, &frame); + + dev_kfree_skb(frame.skb); + + */ + return ret; +} + +static int cw1200_enable_beaconing(struct cw1200_common *priv, + bool enable) +{ + struct wsm_beacon_transmit transmit = { + .enable_beaconing = enable, + }; + + return wsm_beacon_transmit(priv, &transmit); +} + +static int cw1200_start_ap(struct cw1200_common *priv) +{ + int ret; + struct ieee80211_bss_conf *conf = &priv->vif->bss_conf; + struct wsm_start start = { + .mode = priv->vif->p2p ? + WSM_START_MODE_P2P_GO : WSM_START_MODE_AP, + .band = (priv->channel->band == IEEE80211_BAND_5GHZ) ? + WSM_PHY_BAND_5G : WSM_PHY_BAND_2_4G, + .channel_number = priv->channel->hw_value, + .beacon_interval = conf->beacon_int, + .dtim_period = conf->dtim_period, + .preamble = conf->use_short_preamble ? + WSM_JOIN_PREAMBLE_SHORT : + WSM_JOIN_PREAMBLE_LONG, + .probe_delay = 100, + .basic_rate_set = cw1200_rate_mask_to_wsm(priv, + conf->basic_rates), + }; + struct wsm_operational_mode mode = { + .power_mode = cw1200_power_mode, + .disable_more_flag_usage = true, + }; + + memset(start.ssid, 0, sizeof(start.ssid)); + if (!conf->hidden_ssid) { + start.ssid_len = conf->ssid_len; + memcpy(start.ssid, conf->ssid, start.ssid_len); + } + + priv->beacon_int = conf->beacon_int; + priv->join_dtim_period = conf->dtim_period; + + memset(&priv->link_id_db, 0, sizeof(priv->link_id_db)); + + pr_debug("[AP] ch: %d(%d), bcn: %d(%d), brt: 0x%.8X, ssid: %.*s.\n", + start.channel_number, start.band, + start.beacon_interval, start.dtim_period, + start.basic_rate_set, + start.ssid_len, start.ssid); + ret = wsm_start(priv, &start); + if (!ret) + ret = cw1200_upload_keys(priv); + if (!ret && priv->vif->p2p) { + pr_debug("[AP] Setting p2p powersave configuration.\n"); + wsm_set_p2p_ps_modeinfo(priv, &priv->p2p_ps_modeinfo); + } + if (!ret) { + wsm_set_block_ack_policy(priv, 0, 0); + priv->join_status = CW1200_JOIN_STATUS_AP; + cw1200_update_filtering(priv); + } + wsm_set_operational_mode(priv, &mode); + return ret; +} + +static int cw1200_update_beaconing(struct cw1200_common *priv) +{ + struct ieee80211_bss_conf *conf = &priv->vif->bss_conf; + struct wsm_reset reset = { + .link_id = 0, + .reset_statistics = true, + }; + + if (priv->mode == NL80211_IFTYPE_AP) { + /* TODO: check if changed channel, band */ + if (priv->join_status != CW1200_JOIN_STATUS_AP || + priv->beacon_int != conf->beacon_int) { + pr_debug("ap restarting\n"); + wsm_lock_tx(priv); + if (priv->join_status != CW1200_JOIN_STATUS_PASSIVE) + wsm_reset(priv, &reset); + priv->join_status = CW1200_JOIN_STATUS_PASSIVE; + cw1200_start_ap(priv); + wsm_unlock_tx(priv); + } else + pr_debug("ap started join_status: %d\n", + priv->join_status); + } + return 0; +} diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h new file mode 100644 index 000000000000..35babb62cc6a --- /dev/null +++ b/drivers/net/wireless/cw1200/sta.h @@ -0,0 +1,123 @@ +/* + * Mac80211 STA interface for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef STA_H_INCLUDED +#define STA_H_INCLUDED + +/* ******************************************************************** */ +/* mac80211 API */ + +int cw1200_start(struct ieee80211_hw *dev); +void cw1200_stop(struct ieee80211_hw *dev); +int cw1200_add_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif); +void cw1200_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif); +int cw1200_change_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type, + bool p2p); +int cw1200_config(struct ieee80211_hw *dev, u32 changed); +void cw1200_configure_filter(struct ieee80211_hw *dev, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast); +int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, + u16 queue, const struct ieee80211_tx_queue_params *params); +int cw1200_get_stats(struct ieee80211_hw *dev, + struct ieee80211_low_level_stats *stats); +int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); + +int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value); + +void cw1200_flush(struct ieee80211_hw *hw, u32 queues, bool drop); + +u64 cw1200_prepare_multicast(struct ieee80211_hw *hw, + struct netdev_hw_addr_list *mc_list); + +int cw1200_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg); + +/* ******************************************************************** */ +/* WSM callbacks */ + +void cw1200_join_complete_cb(struct cw1200_common *priv, + struct wsm_join_complete *arg); + +/* ******************************************************************** */ +/* WSM events */ + +void cw1200_free_event_queue(struct cw1200_common *priv); +void cw1200_event_handler(struct work_struct *work); +void cw1200_bss_loss_work(struct work_struct *work); +void cw1200_bss_params_work(struct work_struct *work); +void cw1200_keep_alive_work(struct work_struct *work); +void cw1200_tx_failure_work(struct work_struct *work); + +void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv, int init, int good, + int bad); +static inline void cw1200_cqm_bssloss_sm(struct cw1200_common *priv, + int init, int good, int bad) +{ + spin_lock(&priv->bss_loss_lock); + __cw1200_cqm_bssloss_sm(priv, init, good, bad); + spin_unlock(&priv->bss_loss_lock); +} + +/* ******************************************************************** */ +/* Internal API */ + +int cw1200_setup_mac(struct cw1200_common *priv); +void cw1200_join_timeout(struct work_struct *work); +void cw1200_unjoin_work(struct work_struct *work); +void cw1200_join_complete_work(struct work_struct *work); +void cw1200_wep_key_work(struct work_struct *work); +void cw1200_update_listening(struct cw1200_common *priv, bool enabled); +void cw1200_update_filtering(struct cw1200_common *priv); +void cw1200_update_filtering_work(struct work_struct *work); +void cw1200_set_beacon_wakeup_period_work(struct work_struct *work); +int cw1200_enable_listening(struct cw1200_common *priv); +int cw1200_disable_listening(struct cw1200_common *priv); +int cw1200_set_uapsd_param(struct cw1200_common *priv, + const struct wsm_edca_params *arg); +void cw1200_ba_work(struct work_struct *work); +void cw1200_ba_timer(unsigned long arg); + +/* AP stuffs */ +int cw1200_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, + bool set); +int cw1200_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int cw1200_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void cw1200_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, + enum sta_notify_cmd notify_cmd, + struct ieee80211_sta *sta); +void cw1200_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed); +int cw1200_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size); + +void cw1200_suspend_resume(struct cw1200_common *priv, + struct wsm_suspend_resume *arg); +void cw1200_set_tim_work(struct work_struct *work); +void cw1200_set_cts_work(struct work_struct *work); +void cw1200_multicast_start_work(struct work_struct *work); +void cw1200_multicast_stop_work(struct work_struct *work); +void cw1200_mcast_timeout(unsigned long arg); + +#endif diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c new file mode 100644 index 000000000000..0e40890e1993 --- /dev/null +++ b/drivers/net/wireless/cw1200/txrx.c @@ -0,0 +1,1474 @@ +/* + * Datapath implementation for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "cw1200.h" +#include "wsm.h" +#include "bh.h" +#include "sta.h" +#include "debug.h" + +#define CW1200_INVALID_RATE_ID (0xFF) + +static int cw1200_handle_action_rx(struct cw1200_common *priv, + struct sk_buff *skb); +static const struct ieee80211_rate * +cw1200_get_tx_rate(const struct cw1200_common *priv, + const struct ieee80211_tx_rate *rate); + +/* ******************************************************************** */ +/* TX queue lock / unlock */ + +static inline void cw1200_tx_queues_lock(struct cw1200_common *priv) +{ + int i; + for (i = 0; i < 4; ++i) + cw1200_queue_lock(&priv->tx_queue[i]); +} + +static inline void cw1200_tx_queues_unlock(struct cw1200_common *priv) +{ + int i; + for (i = 0; i < 4; ++i) + cw1200_queue_unlock(&priv->tx_queue[i]); +} + +/* ******************************************************************** */ +/* TX policy cache implementation */ + +static void tx_policy_dump(struct tx_policy *policy) +{ + pr_debug("[TX policy] %.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X %.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X %.1X%.1X%.1X%.1X%.1X%.1X%.1X%.1X: %d\n", + policy->raw[0] & 0x0F, policy->raw[0] >> 4, + policy->raw[1] & 0x0F, policy->raw[1] >> 4, + policy->raw[2] & 0x0F, policy->raw[2] >> 4, + policy->raw[3] & 0x0F, policy->raw[3] >> 4, + policy->raw[4] & 0x0F, policy->raw[4] >> 4, + policy->raw[5] & 0x0F, policy->raw[5] >> 4, + policy->raw[6] & 0x0F, policy->raw[6] >> 4, + policy->raw[7] & 0x0F, policy->raw[7] >> 4, + policy->raw[8] & 0x0F, policy->raw[8] >> 4, + policy->raw[9] & 0x0F, policy->raw[9] >> 4, + policy->raw[10] & 0x0F, policy->raw[10] >> 4, + policy->raw[11] & 0x0F, policy->raw[11] >> 4, + policy->defined); +} + +static void tx_policy_build(const struct cw1200_common *priv, + /* [out] */ struct tx_policy *policy, + struct ieee80211_tx_rate *rates, size_t count) +{ + int i, j; + unsigned limit = priv->short_frame_max_tx_count; + unsigned total = 0; + BUG_ON(rates[0].idx < 0); + memset(policy, 0, sizeof(*policy)); + + /* minstrel is buggy a little bit, so distille + * incoming rates first. */ + + /* Sort rates in descending order. */ + for (i = 1; i < count; ++i) { + if (rates[i].idx < 0) { + count = i; + break; + } + if (rates[i].idx > rates[i - 1].idx) { + struct ieee80211_tx_rate tmp = rates[i - 1]; + rates[i - 1] = rates[i]; + rates[i] = tmp; + } + } + + /* Eliminate duplicates. */ + total = rates[0].count; + for (i = 0, j = 1; j < count; ++j) { + if (rates[j].idx == rates[i].idx) { + rates[i].count += rates[j].count; + } else if (rates[j].idx > rates[i].idx) { + break; + } else { + ++i; + if (i != j) + rates[i] = rates[j]; + } + total += rates[j].count; + } + count = i + 1; + + /* Re-fill policy trying to keep every requested rate and with + * respect to the global max tx retransmission count. */ + if (limit < count) + limit = count; + if (total > limit) { + for (i = 0; i < count; ++i) { + int left = count - i - 1; + if (rates[i].count > limit - left) + rates[i].count = limit - left; + limit -= rates[i].count; + } + } + + /* HACK!!! Device has problems (at least) switching from + * 54Mbps CTS to 1Mbps. This switch takes enormous amount + * of time (100-200 ms), leading to valuable throughput drop. + * As a workaround, additional g-rates are injected to the + * policy. + */ + if (count == 2 && !(rates[0].flags & IEEE80211_TX_RC_MCS) && + rates[0].idx > 4 && rates[0].count > 2 && + rates[1].idx < 2) { + /* ">> 1" is an equivalent of "/ 2", but faster */ + int mid_rate = (rates[0].idx + 4) >> 1; + + /* Decrease number of retries for the initial rate */ + rates[0].count -= 2; + + if (mid_rate != 4) { + /* Keep fallback rate at 1Mbps. */ + rates[3] = rates[1]; + + /* Inject 1 transmission on lowest g-rate */ + rates[2].idx = 4; + rates[2].count = 1; + rates[2].flags = rates[1].flags; + + /* Inject 1 transmission on mid-rate */ + rates[1].idx = mid_rate; + rates[1].count = 1; + + /* Fallback to 1 Mbps is a really bad thing, + * so let's try to increase probability of + * successful transmission on the lowest g rate + * even more */ + if (rates[0].count >= 3) { + --rates[0].count; + ++rates[2].count; + } + + /* Adjust amount of rates defined */ + count += 2; + } else { + /* Keep fallback rate at 1Mbps. */ + rates[2] = rates[1]; + + /* Inject 2 transmissions on lowest g-rate */ + rates[1].idx = 4; + rates[1].count = 2; + + /* Adjust amount of rates defined */ + count += 1; + } + } + + policy->defined = cw1200_get_tx_rate(priv, &rates[0])->hw_value + 1; + + for (i = 0; i < count; ++i) { + register unsigned rateid, off, shift, retries; + + rateid = cw1200_get_tx_rate(priv, &rates[i])->hw_value; + off = rateid >> 3; /* eq. rateid / 8 */ + shift = (rateid & 0x07) << 2; /* eq. (rateid % 8) * 4 */ + + retries = rates[i].count; + if (retries > 0x0F) { + rates[i].count = 0x0f; + retries = 0x0F; + } + policy->tbl[off] |= __cpu_to_le32(retries << shift); + policy->retry_count += retries; + } + + pr_debug("[TX policy] Policy (%zu): %d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n", + count, + rates[0].idx, rates[0].count, + rates[1].idx, rates[1].count, + rates[2].idx, rates[2].count, + rates[3].idx, rates[3].count, + rates[4].idx, rates[4].count); +} + +static inline bool tx_policy_is_equal(const struct tx_policy *wanted, + const struct tx_policy *cached) +{ + size_t count = wanted->defined >> 1; + if (wanted->defined > cached->defined) + return false; + if (count) { + if (memcmp(wanted->raw, cached->raw, count)) + return false; + } + if (wanted->defined & 1) { + if ((wanted->raw[count] & 0x0F) != (cached->raw[count] & 0x0F)) + return false; + } + return true; +} + +static int tx_policy_find(struct tx_policy_cache *cache, + const struct tx_policy *wanted) +{ + /* O(n) complexity. Not so good, but there's only 8 entries in + * the cache. + * Also lru helps to reduce search time. */ + struct tx_policy_cache_entry *it; + /* First search for policy in "used" list */ + list_for_each_entry(it, &cache->used, link) { + if (tx_policy_is_equal(wanted, &it->policy)) + return it - cache->cache; + } + /* Then - in "free list" */ + list_for_each_entry(it, &cache->free, link) { + if (tx_policy_is_equal(wanted, &it->policy)) + return it - cache->cache; + } + return -1; +} + +static inline void tx_policy_use(struct tx_policy_cache *cache, + struct tx_policy_cache_entry *entry) +{ + ++entry->policy.usage_count; + list_move(&entry->link, &cache->used); +} + +static inline int tx_policy_release(struct tx_policy_cache *cache, + struct tx_policy_cache_entry *entry) +{ + int ret = --entry->policy.usage_count; + if (!ret) + list_move(&entry->link, &cache->free); + return ret; +} + +void tx_policy_clean(struct cw1200_common *priv) +{ + int idx, locked; + struct tx_policy_cache *cache = &priv->tx_policy_cache; + struct tx_policy_cache_entry *entry; + + cw1200_tx_queues_lock(priv); + spin_lock_bh(&cache->lock); + locked = list_empty(&cache->free); + + for (idx = 0; idx < TX_POLICY_CACHE_SIZE; idx++) { + entry = &cache->cache[idx]; + /* Policy usage count should be 0 at this time as all queues + should be empty */ + if (WARN_ON(entry->policy.usage_count)) { + entry->policy.usage_count = 0; + list_move(&entry->link, &cache->free); + } + memset(&entry->policy, 0, sizeof(entry->policy)); + } + if (locked) + cw1200_tx_queues_unlock(priv); + + cw1200_tx_queues_unlock(priv); + spin_unlock_bh(&cache->lock); +} + +/* ******************************************************************** */ +/* External TX policy cache API */ + +void tx_policy_init(struct cw1200_common *priv) +{ + struct tx_policy_cache *cache = &priv->tx_policy_cache; + int i; + + memset(cache, 0, sizeof(*cache)); + + spin_lock_init(&cache->lock); + INIT_LIST_HEAD(&cache->used); + INIT_LIST_HEAD(&cache->free); + + for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i) + list_add(&cache->cache[i].link, &cache->free); +} + +static int tx_policy_get(struct cw1200_common *priv, + struct ieee80211_tx_rate *rates, + size_t count, bool *renew) +{ + int idx; + struct tx_policy_cache *cache = &priv->tx_policy_cache; + struct tx_policy wanted; + + tx_policy_build(priv, &wanted, rates, count); + + spin_lock_bh(&cache->lock); + if (WARN_ON_ONCE(list_empty(&cache->free))) { + spin_unlock_bh(&cache->lock); + return CW1200_INVALID_RATE_ID; + } + idx = tx_policy_find(cache, &wanted); + if (idx >= 0) { + pr_debug("[TX policy] Used TX policy: %d\n", idx); + *renew = false; + } else { + struct tx_policy_cache_entry *entry; + *renew = true; + /* If policy is not found create a new one + * using the oldest entry in "free" list */ + entry = list_entry(cache->free.prev, + struct tx_policy_cache_entry, link); + entry->policy = wanted; + idx = entry - cache->cache; + pr_debug("[TX policy] New TX policy: %d\n", idx); + tx_policy_dump(&entry->policy); + } + tx_policy_use(cache, &cache->cache[idx]); + if (list_empty(&cache->free)) { + /* Lock TX queues. */ + cw1200_tx_queues_lock(priv); + } + spin_unlock_bh(&cache->lock); + return idx; +} + +static void tx_policy_put(struct cw1200_common *priv, int idx) +{ + int usage, locked; + struct tx_policy_cache *cache = &priv->tx_policy_cache; + + spin_lock_bh(&cache->lock); + locked = list_empty(&cache->free); + usage = tx_policy_release(cache, &cache->cache[idx]); + if (locked && !usage) { + /* Unlock TX queues. */ + cw1200_tx_queues_unlock(priv); + } + spin_unlock_bh(&cache->lock); +} + +static int tx_policy_upload(struct cw1200_common *priv) +{ + struct tx_policy_cache *cache = &priv->tx_policy_cache; + int i; + struct wsm_set_tx_rate_retry_policy arg = { + .num = 0, + }; + spin_lock_bh(&cache->lock); + + /* Upload only modified entries. */ + for (i = 0; i < TX_POLICY_CACHE_SIZE; ++i) { + struct tx_policy *src = &cache->cache[i].policy; + if (src->retry_count && !src->uploaded) { + struct wsm_tx_rate_retry_policy *dst = + &arg.tbl[arg.num]; + dst->index = i; + dst->short_retries = priv->short_frame_max_tx_count; + dst->long_retries = priv->long_frame_max_tx_count; + + dst->flags = WSM_TX_RATE_POLICY_FLAG_TERMINATE_WHEN_FINISHED | + WSM_TX_RATE_POLICY_FLAG_COUNT_INITIAL_TRANSMIT; + memcpy(dst->rate_count_indices, src->tbl, + sizeof(dst->rate_count_indices)); + src->uploaded = 1; + ++arg.num; + } + } + spin_unlock_bh(&cache->lock); + cw1200_debug_tx_cache_miss(priv); + pr_debug("[TX policy] Upload %d policies\n", arg.num); + return wsm_set_tx_rate_retry_policy(priv, &arg); +} + +void tx_policy_upload_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, tx_policy_upload_work); + + pr_debug("[TX] TX policy upload.\n"); + tx_policy_upload(priv); + + wsm_unlock_tx(priv); + cw1200_tx_queues_unlock(priv); +} + +/* ******************************************************************** */ +/* cw1200 TX implementation */ + +struct cw1200_txinfo { + struct sk_buff *skb; + unsigned queue; + struct ieee80211_tx_info *tx_info; + const struct ieee80211_rate *rate; + struct ieee80211_hdr *hdr; + size_t hdrlen; + const u8 *da; + struct cw1200_sta_priv *sta_priv; + struct ieee80211_sta *sta; + struct cw1200_txpriv txpriv; +}; + +u32 cw1200_rate_mask_to_wsm(struct cw1200_common *priv, u32 rates) +{ + u32 ret = 0; + int i; + for (i = 0; i < 32; ++i) { + if (rates & BIT(i)) + ret |= BIT(priv->rates[i].hw_value); + } + return ret; +} + +static const struct ieee80211_rate * +cw1200_get_tx_rate(const struct cw1200_common *priv, + const struct ieee80211_tx_rate *rate) +{ + if (rate->idx < 0) + return NULL; + if (rate->flags & IEEE80211_TX_RC_MCS) + return &priv->mcs_rates[rate->idx]; + return &priv->hw->wiphy->bands[priv->channel->band]-> + bitrates[rate->idx]; +} + +static int +cw1200_tx_h_calc_link_ids(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + if (t->sta && t->sta_priv->link_id) + t->txpriv.raw_link_id = + t->txpriv.link_id = + t->sta_priv->link_id; + else if (priv->mode != NL80211_IFTYPE_AP) + t->txpriv.raw_link_id = + t->txpriv.link_id = 0; + else if (is_multicast_ether_addr(t->da)) { + if (priv->enable_beacon) { + t->txpriv.raw_link_id = 0; + t->txpriv.link_id = CW1200_LINK_ID_AFTER_DTIM; + } else { + t->txpriv.raw_link_id = 0; + t->txpriv.link_id = 0; + } + } else { + t->txpriv.link_id = cw1200_find_link_id(priv, t->da); + if (!t->txpriv.link_id) + t->txpriv.link_id = cw1200_alloc_link_id(priv, t->da); + if (!t->txpriv.link_id) { + wiphy_err(priv->hw->wiphy, + "No more link IDs available.\n"); + return -ENOENT; + } + t->txpriv.raw_link_id = t->txpriv.link_id; + } + if (t->txpriv.raw_link_id) + priv->link_id_db[t->txpriv.raw_link_id - 1].timestamp = + jiffies; + if (t->sta && (t->sta->uapsd_queues & BIT(t->queue))) + t->txpriv.link_id = CW1200_LINK_ID_UAPSD; + return 0; +} + +static void +cw1200_tx_h_pm(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + if (ieee80211_is_auth(t->hdr->frame_control)) { + u32 mask = ~BIT(t->txpriv.raw_link_id); + spin_lock_bh(&priv->ps_state_lock); + priv->sta_asleep_mask &= mask; + priv->pspoll_mask &= mask; + spin_unlock_bh(&priv->ps_state_lock); + } +} + +static void +cw1200_tx_h_calc_tid(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + if (ieee80211_is_data_qos(t->hdr->frame_control)) { + u8 *qos = ieee80211_get_qos_ctl(t->hdr); + t->txpriv.tid = qos[0] & IEEE80211_QOS_CTL_TID_MASK; + } else if (ieee80211_is_data(t->hdr->frame_control)) { + t->txpriv.tid = 0; + } +} + +static int +cw1200_tx_h_crypt(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + if (!t->tx_info->control.hw_key || + !ieee80211_has_protected(t->hdr->frame_control)) + return 0; + + t->hdrlen += t->tx_info->control.hw_key->iv_len; + skb_put(t->skb, t->tx_info->control.hw_key->icv_len); + + if (t->tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) + skb_put(t->skb, 8); /* MIC space */ + + return 0; +} + +static int +cw1200_tx_h_align(struct cw1200_common *priv, + struct cw1200_txinfo *t, + u8 *flags) +{ + size_t offset = (size_t)t->skb->data & 3; + + if (!offset) + return 0; + + if (offset & 1) { + wiphy_err(priv->hw->wiphy, + "Bug: attempt to transmit a frame with wrong alignment: %zu\n", + offset); + return -EINVAL; + } + + if (skb_headroom(t->skb) < offset) { + wiphy_err(priv->hw->wiphy, + "Bug: no space allocated for DMA alignment. headroom: %d\n", + skb_headroom(t->skb)); + return -ENOMEM; + } + skb_push(t->skb, offset); + t->hdrlen += offset; + t->txpriv.offset += offset; + *flags |= WSM_TX_2BYTES_SHIFT; + cw1200_debug_tx_align(priv); + return 0; +} + +static int +cw1200_tx_h_action(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + struct ieee80211_mgmt *mgmt = + (struct ieee80211_mgmt *)t->hdr; + if (ieee80211_is_action(t->hdr->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_BACK) + return 1; + else + return 0; +} + +/* Add WSM header */ +static struct wsm_tx * +cw1200_tx_h_wsm(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + struct wsm_tx *wsm; + + if (skb_headroom(t->skb) < sizeof(struct wsm_tx)) { + wiphy_err(priv->hw->wiphy, + "Bug: no space allocated for WSM header. headroom: %d\n", + skb_headroom(t->skb)); + return NULL; + } + + wsm = (struct wsm_tx *)skb_push(t->skb, sizeof(struct wsm_tx)); + t->txpriv.offset += sizeof(struct wsm_tx); + memset(wsm, 0, sizeof(*wsm)); + wsm->hdr.len = __cpu_to_le16(t->skb->len); + wsm->hdr.id = __cpu_to_le16(0x0004); + wsm->queue_id = wsm_queue_id_to_wsm(t->queue); + return wsm; +} + +/* BT Coex specific handling */ +static void +cw1200_tx_h_bt(struct cw1200_common *priv, + struct cw1200_txinfo *t, + struct wsm_tx *wsm) +{ + u8 priority = 0; + + if (!priv->bt_present) + return; + + if (ieee80211_is_nullfunc(t->hdr->frame_control)) { + priority = WSM_EPTA_PRIORITY_MGT; + } else if (ieee80211_is_data(t->hdr->frame_control)) { + /* Skip LLC SNAP header (+6) */ + u8 *payload = &t->skb->data[t->hdrlen]; + u16 *ethertype = (u16 *)&payload[6]; + if (*ethertype == __be16_to_cpu(ETH_P_PAE)) + priority = WSM_EPTA_PRIORITY_EAPOL; + } else if (ieee80211_is_assoc_req(t->hdr->frame_control) || + ieee80211_is_reassoc_req(t->hdr->frame_control)) { + struct ieee80211_mgmt *mgt_frame = + (struct ieee80211_mgmt *)t->hdr; + + if (mgt_frame->u.assoc_req.listen_interval < + priv->listen_interval) { + pr_debug("Modified Listen Interval to %d from %d\n", + priv->listen_interval, + mgt_frame->u.assoc_req.listen_interval); + /* Replace listen interval derieved from + * the one read from SDD */ + mgt_frame->u.assoc_req.listen_interval = + priv->listen_interval; + } + } + + if (!priority) { + if (ieee80211_is_action(t->hdr->frame_control)) + priority = WSM_EPTA_PRIORITY_ACTION; + else if (ieee80211_is_mgmt(t->hdr->frame_control)) + priority = WSM_EPTA_PRIORITY_MGT; + else if ((wsm->queue_id == WSM_QUEUE_VOICE)) + priority = WSM_EPTA_PRIORITY_VOICE; + else if ((wsm->queue_id == WSM_QUEUE_VIDEO)) + priority = WSM_EPTA_PRIORITY_VIDEO; + else + priority = WSM_EPTA_PRIORITY_DATA; + } + + pr_debug("[TX] EPTA priority %d.\n", priority); + + wsm->flags |= priority << 1; +} + +static int +cw1200_tx_h_rate_policy(struct cw1200_common *priv, + struct cw1200_txinfo *t, + struct wsm_tx *wsm) +{ + bool tx_policy_renew = false; + + t->txpriv.rate_id = tx_policy_get(priv, + t->tx_info->control.rates, IEEE80211_TX_MAX_RATES, + &tx_policy_renew); + if (t->txpriv.rate_id == CW1200_INVALID_RATE_ID) + return -EFAULT; + + wsm->flags |= t->txpriv.rate_id << 4; + + t->rate = cw1200_get_tx_rate(priv, + &t->tx_info->control.rates[0]), + wsm->max_tx_rate = t->rate->hw_value; + if (t->rate->flags & IEEE80211_TX_RC_MCS) { + if (cw1200_ht_greenfield(&priv->ht_info)) + wsm->ht_tx_parameters |= + __cpu_to_le32(WSM_HT_TX_GREENFIELD); + else + wsm->ht_tx_parameters |= + __cpu_to_le32(WSM_HT_TX_MIXED); + } + + if (tx_policy_renew) { + pr_debug("[TX] TX policy renew.\n"); + /* It's not so optimal to stop TX queues every now and then. + * Better to reimplement task scheduling with + * a counter. TODO. */ + wsm_lock_tx_async(priv); + cw1200_tx_queues_lock(priv); + if (queue_work(priv->workqueue, + &priv->tx_policy_upload_work) <= 0) { + cw1200_tx_queues_unlock(priv); + wsm_unlock_tx(priv); + } + } + return 0; +} + +static bool +cw1200_tx_h_pm_state(struct cw1200_common *priv, + struct cw1200_txinfo *t) +{ + int was_buffered = 1; + + if (t->txpriv.link_id == CW1200_LINK_ID_AFTER_DTIM && + !priv->buffered_multicasts) { + priv->buffered_multicasts = true; + if (priv->sta_asleep_mask) + queue_work(priv->workqueue, + &priv->multicast_start_work); + } + + if (t->txpriv.raw_link_id && t->txpriv.tid < CW1200_MAX_TID) + was_buffered = priv->link_id_db[t->txpriv.raw_link_id - 1].buffered[t->txpriv.tid]++; + + return !was_buffered; +} + +/* ******************************************************************** */ + +void cw1200_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct cw1200_common *priv = dev->priv; + struct cw1200_txinfo t = { + .skb = skb, + .queue = skb_get_queue_mapping(skb), + .tx_info = IEEE80211_SKB_CB(skb), + .hdr = (struct ieee80211_hdr *)skb->data, + .txpriv.tid = CW1200_MAX_TID, + .txpriv.rate_id = CW1200_INVALID_RATE_ID, + }; + struct ieee80211_sta *sta; + struct wsm_tx *wsm; + bool tid_update = 0; + u8 flags = 0; + int ret; + + if (priv->bh_error) + goto drop; + + t.hdrlen = ieee80211_hdrlen(t.hdr->frame_control); + t.da = ieee80211_get_DA(t.hdr); + if (control) { + t.sta = control->sta; + t.sta_priv = (struct cw1200_sta_priv *)&t.sta->drv_priv; + } + + if (WARN_ON(t.queue >= 4)) + goto drop; + + ret = cw1200_tx_h_calc_link_ids(priv, &t); + if (ret) + goto drop; + + pr_debug("[TX] TX %d bytes (queue: %d, link_id: %d (%d)).\n", + skb->len, t.queue, t.txpriv.link_id, + t.txpriv.raw_link_id); + + cw1200_tx_h_pm(priv, &t); + cw1200_tx_h_calc_tid(priv, &t); + ret = cw1200_tx_h_crypt(priv, &t); + if (ret) + goto drop; + ret = cw1200_tx_h_align(priv, &t, &flags); + if (ret) + goto drop; + ret = cw1200_tx_h_action(priv, &t); + if (ret) + goto drop; + wsm = cw1200_tx_h_wsm(priv, &t); + if (!wsm) { + ret = -ENOMEM; + goto drop; + } + wsm->flags |= flags; + cw1200_tx_h_bt(priv, &t, wsm); + ret = cw1200_tx_h_rate_policy(priv, &t, wsm); + if (ret) + goto drop; + + rcu_read_lock(); + sta = rcu_dereference(t.sta); + + spin_lock_bh(&priv->ps_state_lock); + { + tid_update = cw1200_tx_h_pm_state(priv, &t); + BUG_ON(cw1200_queue_put(&priv->tx_queue[t.queue], + t.skb, &t.txpriv)); + } + spin_unlock_bh(&priv->ps_state_lock); + + if (tid_update && sta) + ieee80211_sta_set_buffered(sta, t.txpriv.tid, true); + + rcu_read_unlock(); + + cw1200_bh_wakeup(priv); + + return; + +drop: + cw1200_skb_dtor(priv, skb, &t.txpriv); + return; +} + +/* ******************************************************************** */ + +static int cw1200_handle_action_rx(struct cw1200_common *priv, + struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt = (void *)skb->data; + + /* Filter block ACK negotiation: fully controlled by firmware */ + if (mgmt->u.action.category == WLAN_CATEGORY_BACK) + return 1; + + return 0; +} + +static int cw1200_handle_pspoll(struct cw1200_common *priv, + struct sk_buff *skb) +{ + struct ieee80211_sta *sta; + struct ieee80211_pspoll *pspoll = (struct ieee80211_pspoll *)skb->data; + int link_id = 0; + u32 pspoll_mask = 0; + int drop = 1; + int i; + + if (priv->join_status != CW1200_JOIN_STATUS_AP) + goto done; + if (memcmp(priv->vif->addr, pspoll->bssid, ETH_ALEN)) + goto done; + + rcu_read_lock(); + sta = ieee80211_find_sta(priv->vif, pspoll->ta); + if (sta) { + struct cw1200_sta_priv *sta_priv; + sta_priv = (struct cw1200_sta_priv *)&sta->drv_priv; + link_id = sta_priv->link_id; + pspoll_mask = BIT(sta_priv->link_id); + } + rcu_read_unlock(); + if (!link_id) + goto done; + + priv->pspoll_mask |= pspoll_mask; + drop = 0; + + /* Do not report pspols if data for given link id is + * queued already. */ + for (i = 0; i < 4; ++i) { + if (cw1200_queue_get_num_queued(&priv->tx_queue[i], + pspoll_mask)) { + cw1200_bh_wakeup(priv); + drop = 1; + break; + } + } + pr_debug("[RX] PSPOLL: %s\n", drop ? "local" : "fwd"); +done: + return drop; +} + +/* ******************************************************************** */ + +void cw1200_tx_confirm_cb(struct cw1200_common *priv, + int link_id, + struct wsm_tx_confirm *arg) +{ + u8 queue_id = cw1200_queue_get_queue_id(arg->packet_id); + struct cw1200_queue *queue = &priv->tx_queue[queue_id]; + struct sk_buff *skb; + const struct cw1200_txpriv *txpriv; + + pr_debug("[TX] TX confirm: %d, %d.\n", + arg->status, arg->ack_failures); + + if (cw1200_itp_tx_running(priv)) + return; + + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) { + /* STA is stopped. */ + return; + } + + if (WARN_ON(queue_id >= 4)) + return; + + if (arg->status) + pr_debug("TX failed: %d.\n", arg->status); + + if ((arg->status == WSM_REQUEUE) && + (arg->flags & WSM_TX_STATUS_REQUEUE)) { + /* "Requeue" means "implicit suspend" */ + struct wsm_suspend_resume suspend = { + .link_id = link_id, + .stop = 1, + .multicast = !link_id, + }; + cw1200_suspend_resume(priv, &suspend); + wiphy_warn(priv->hw->wiphy, "Requeue for link_id %d (try %d). STAs asleep: 0x%.8X\n", + link_id, + cw1200_queue_get_generation(arg->packet_id) + 1, + priv->sta_asleep_mask); + cw1200_queue_requeue(queue, arg->packet_id); + spin_lock_bh(&priv->ps_state_lock); + if (!link_id) { + priv->buffered_multicasts = true; + if (priv->sta_asleep_mask) { + queue_work(priv->workqueue, + &priv->multicast_start_work); + } + } + spin_unlock_bh(&priv->ps_state_lock); + } else if (!cw1200_queue_get_skb(queue, arg->packet_id, + &skb, &txpriv)) { + struct ieee80211_tx_info *tx = IEEE80211_SKB_CB(skb); + int tx_count = arg->ack_failures; + u8 ht_flags = 0; + int i; + + if (cw1200_ht_greenfield(&priv->ht_info)) + ht_flags |= IEEE80211_TX_RC_GREEN_FIELD; + + spin_lock(&priv->bss_loss_lock); + if (priv->bss_loss_state && + arg->packet_id == priv->bss_loss_confirm_id) { + if (arg->status) { + /* Recovery failed */ + __cw1200_cqm_bssloss_sm(priv, 0, 0, 1); + } else { + /* Recovery succeeded */ + __cw1200_cqm_bssloss_sm(priv, 0, 1, 0); + } + } + spin_unlock(&priv->bss_loss_lock); + + if (!arg->status) { + tx->flags |= IEEE80211_TX_STAT_ACK; + ++tx_count; + cw1200_debug_txed(priv); + if (arg->flags & WSM_TX_STATUS_AGGREGATION) { + /* Do not report aggregation to mac80211: + * it confuses minstrel a lot. */ + /* tx->flags |= IEEE80211_TX_STAT_AMPDU; */ + cw1200_debug_txed_agg(priv); + } + } else { + if (tx_count) + ++tx_count; + } + + for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) { + if (tx->status.rates[i].count >= tx_count) { + tx->status.rates[i].count = tx_count; + break; + } + tx_count -= tx->status.rates[i].count; + if (tx->status.rates[i].flags & IEEE80211_TX_RC_MCS) + tx->status.rates[i].flags |= ht_flags; + } + + for (++i; i < IEEE80211_TX_MAX_RATES; ++i) { + tx->status.rates[i].count = 0; + tx->status.rates[i].idx = -1; + } + + /* Pull off any crypto trailers that we added on */ + if (tx->control.hw_key) { + skb_trim(skb, skb->len - tx->control.hw_key->icv_len); + if (tx->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) + skb_trim(skb, skb->len - 8); /* MIC space */ + } + cw1200_queue_remove(queue, arg->packet_id); + } + /* XXX TODO: Only wake if there are pending transmits.. */ + cw1200_bh_wakeup(priv); +} + +static void cw1200_notify_buffered_tx(struct cw1200_common *priv, + struct sk_buff *skb, int link_id, int tid) +{ + struct ieee80211_sta *sta; + struct ieee80211_hdr *hdr; + u8 *buffered; + u8 still_buffered = 0; + + if (link_id && tid < CW1200_MAX_TID) { + buffered = priv->link_id_db + [link_id - 1].buffered; + + spin_lock_bh(&priv->ps_state_lock); + if (!WARN_ON(!buffered[tid])) + still_buffered = --buffered[tid]; + spin_unlock_bh(&priv->ps_state_lock); + + if (!still_buffered && tid < CW1200_MAX_TID) { + hdr = (struct ieee80211_hdr *)skb->data; + rcu_read_lock(); + sta = ieee80211_find_sta(priv->vif, hdr->addr1); + if (sta) + ieee80211_sta_set_buffered(sta, tid, false); + rcu_read_unlock(); + } + } +} + +void cw1200_skb_dtor(struct cw1200_common *priv, + struct sk_buff *skb, + const struct cw1200_txpriv *txpriv) +{ + skb_pull(skb, txpriv->offset); + if (txpriv->rate_id != CW1200_INVALID_RATE_ID) { + cw1200_notify_buffered_tx(priv, skb, + txpriv->raw_link_id, txpriv->tid); + tx_policy_put(priv, txpriv->rate_id); + } + if (!cw1200_is_itp(priv)) + ieee80211_tx_status(priv->hw, skb); +} + +void cw1200_rx_cb(struct cw1200_common *priv, + struct wsm_rx *arg, + int link_id, + struct sk_buff **skb_p) +{ + struct sk_buff *skb = *skb_p; + struct ieee80211_rx_status *hdr = IEEE80211_SKB_RXCB(skb); + struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct cw1200_link_entry *entry = NULL; + unsigned long grace_period; + + bool early_data = false; + bool p2p = priv->vif && priv->vif->p2p; + size_t hdrlen; + hdr->flag = 0; + + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) { + /* STA is stopped. */ + goto drop; + } + + if (link_id && link_id <= CW1200_MAX_STA_IN_AP_MODE) { + entry = &priv->link_id_db[link_id - 1]; + if (entry->status == CW1200_LINK_SOFT && + ieee80211_is_data(frame->frame_control)) + early_data = true; + entry->timestamp = jiffies; + } else if (p2p && + ieee80211_is_action(frame->frame_control) && + (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) { + pr_debug("[RX] Going to MAP&RESET link ID\n"); + WARN_ON(work_pending(&priv->linkid_reset_work)); + memcpy(&priv->action_frame_sa[0], + ieee80211_get_SA(frame), ETH_ALEN); + priv->action_linkid = 0; + schedule_work(&priv->linkid_reset_work); + } + + if (link_id && p2p && + ieee80211_is_action(frame->frame_control) && + (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) { + /* Link ID already exists for the ACTION frame. + * Reset and Remap */ + WARN_ON(work_pending(&priv->linkid_reset_work)); + memcpy(&priv->action_frame_sa[0], + ieee80211_get_SA(frame), ETH_ALEN); + priv->action_linkid = link_id; + schedule_work(&priv->linkid_reset_work); + } + if (arg->status) { + if (arg->status == WSM_STATUS_MICFAILURE) { + pr_debug("[RX] MIC failure.\n"); + hdr->flag |= RX_FLAG_MMIC_ERROR; + } else if (arg->status == WSM_STATUS_NO_KEY_FOUND) { + pr_debug("[RX] No key found.\n"); + goto drop; + } else { + pr_debug("[RX] Receive failure: %d.\n", + arg->status); + goto drop; + } + } + + if (skb->len < sizeof(struct ieee80211_pspoll)) { + wiphy_warn(priv->hw->wiphy, "Mailformed SDU rx'ed. Size is lesser than IEEE header.\n"); + goto drop; + } + + if (ieee80211_is_pspoll(frame->frame_control)) + if (cw1200_handle_pspoll(priv, skb)) + goto drop; + + hdr->mactime = 0; /* Not supported by WSM */ + hdr->band = ((arg->channel_number & 0xff00) || + (arg->channel_number > 14)) ? + IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; + hdr->freq = ieee80211_channel_to_frequency( + arg->channel_number, + hdr->band); + + if (arg->rx_rate >= 14) { + hdr->flag |= RX_FLAG_HT; + hdr->rate_idx = arg->rx_rate - 14; + } else if (arg->rx_rate >= 4) { + hdr->rate_idx = arg->rx_rate - 2; + } else { + hdr->rate_idx = arg->rx_rate; + } + + hdr->signal = (s8)arg->rcpi_rssi; + hdr->antenna = 0; + + hdrlen = ieee80211_hdrlen(frame->frame_control); + + if (WSM_RX_STATUS_ENCRYPTION(arg->flags)) { + size_t iv_len = 0, icv_len = 0; + + hdr->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED; + + /* Oops... There is no fast way to ask mac80211 about + * IV/ICV lengths. Even defineas are not exposed.*/ + switch (WSM_RX_STATUS_ENCRYPTION(arg->flags)) { + case WSM_RX_STATUS_WEP: + iv_len = 4 /* WEP_IV_LEN */; + icv_len = 4 /* WEP_ICV_LEN */; + break; + case WSM_RX_STATUS_TKIP: + iv_len = 8 /* TKIP_IV_LEN */; + icv_len = 4 /* TKIP_ICV_LEN */ + + 8 /*MICHAEL_MIC_LEN*/; + hdr->flag |= RX_FLAG_MMIC_STRIPPED; + break; + case WSM_RX_STATUS_AES: + iv_len = 8 /* CCMP_HDR_LEN */; + icv_len = 8 /* CCMP_MIC_LEN */; + break; + case WSM_RX_STATUS_WAPI: + iv_len = 18 /* WAPI_HDR_LEN */; + icv_len = 16 /* WAPI_MIC_LEN */; + break; + default: + pr_warn("Unknown encryption type %d\n", + WSM_RX_STATUS_ENCRYPTION(arg->flags)); + goto drop; + } + + /* Firmware strips ICV in case of MIC failure. */ + if (arg->status == WSM_STATUS_MICFAILURE) + icv_len = 0; + + if (skb->len < hdrlen + iv_len + icv_len) { + wiphy_warn(priv->hw->wiphy, "Malformed SDU rx'ed. Size is lesser than crypto headers.\n"); + goto drop; + } + + /* Remove IV, ICV and MIC */ + skb_trim(skb, skb->len - icv_len); + memmove(skb->data + iv_len, skb->data, hdrlen); + skb_pull(skb, iv_len); + } + + /* Remove TSF from the end of frame */ + if (arg->flags & WSM_RX_STATUS_TSF_INCLUDED) { + memcpy(&hdr->mactime, skb->data + skb->len - 8, 8); + hdr->mactime = le64_to_cpu(hdr->mactime); + if (skb->len >= 8) + skb_trim(skb, skb->len - 8); + } + + cw1200_debug_rxed(priv); + if (arg->flags & WSM_RX_STATUS_AGGREGATE) + cw1200_debug_rxed_agg(priv); + + if (ieee80211_is_action(frame->frame_control) && + (arg->flags & WSM_RX_STATUS_ADDRESS1)) { + if (cw1200_handle_action_rx(priv, skb)) + return; + } else if (ieee80211_is_beacon(frame->frame_control) && + !arg->status && + !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid, + ETH_ALEN)) { + const u8 *tim_ie; + u8 *ies = ((struct ieee80211_mgmt *) + (skb->data))->u.beacon.variable; + size_t ies_len = skb->len - (ies - (u8 *)(skb->data)); + + tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len); + if (tim_ie) { + struct ieee80211_tim_ie *tim = + (struct ieee80211_tim_ie *)&tim_ie[2]; + + if (priv->join_dtim_period != tim->dtim_period) { + priv->join_dtim_period = tim->dtim_period; + queue_work(priv->workqueue, + &priv->set_beacon_wakeup_period_work); + } + } + + /* Disable beacon filter once we're associated... */ + if (priv->disable_beacon_filter && + (priv->vif->bss_conf.assoc || + priv->vif->bss_conf.ibss_joined)) { + priv->disable_beacon_filter = false; + queue_work(priv->workqueue, + &priv->update_filtering_work); + } + } + + /* Stay awake after frame is received to give + * userspace chance to react and acquire appropriate + * wakelock. */ + if (ieee80211_is_auth(frame->frame_control)) + grace_period = 5 * HZ; + else if (ieee80211_is_deauth(frame->frame_control)) + grace_period = 5 * HZ; + else + grace_period = 1 * HZ; + cw1200_pm_stay_awake(&priv->pm_state, grace_period); + + if (cw1200_itp_rxed(priv, skb)) { + consume_skb(skb); + } else if (early_data) { + spin_lock_bh(&priv->ps_state_lock); + /* Double-check status with lock held */ + if (entry->status == CW1200_LINK_SOFT) + skb_queue_tail(&entry->rx_queue, skb); + else + ieee80211_rx_irqsafe(priv->hw, skb); + spin_unlock_bh(&priv->ps_state_lock); + } else { + ieee80211_rx_irqsafe(priv->hw, skb); + } + *skb_p = NULL; + + return; + +drop: + /* TODO: update failure counters */ + return; +} + +/* ******************************************************************** */ +/* Security */ + +int cw1200_alloc_key(struct cw1200_common *priv) +{ + int idx; + + idx = ffs(~priv->key_map) - 1; + if (idx < 0 || idx > WSM_KEY_MAX_INDEX) + return -1; + + priv->key_map |= BIT(idx); + priv->keys[idx].index = idx; + return idx; +} + +void cw1200_free_key(struct cw1200_common *priv, int idx) +{ + BUG_ON(!(priv->key_map & BIT(idx))); + memset(&priv->keys[idx], 0, sizeof(priv->keys[idx])); + priv->key_map &= ~BIT(idx); +} + +void cw1200_free_keys(struct cw1200_common *priv) +{ + memset(&priv->keys, 0, sizeof(priv->keys)); + priv->key_map = 0; +} + +int cw1200_upload_keys(struct cw1200_common *priv) +{ + int idx, ret = 0; + for (idx = 0; idx <= WSM_KEY_MAX_INDEX; ++idx) + if (priv->key_map & BIT(idx)) { + ret = wsm_add_key(priv, &priv->keys[idx]); + if (ret < 0) + break; + } + return ret; +} + +/* Workaround for WFD test case 6.1.10 */ +void cw1200_link_id_reset(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, linkid_reset_work); + int temp_linkid; + + if (!priv->action_linkid) { + /* In GO mode we can receive ACTION frames without a linkID */ + temp_linkid = cw1200_alloc_link_id(priv, + &priv->action_frame_sa[0]); + WARN_ON(!temp_linkid); + if (temp_linkid) { + /* Make sure we execute the WQ */ + flush_workqueue(priv->workqueue); + /* Release the link ID */ + spin_lock_bh(&priv->ps_state_lock); + priv->link_id_db[temp_linkid - 1].prev_status = + priv->link_id_db[temp_linkid - 1].status; + priv->link_id_db[temp_linkid - 1].status = + CW1200_LINK_RESET; + spin_unlock_bh(&priv->ps_state_lock); + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, + &priv->link_id_work) <= 0) + wsm_unlock_tx(priv); + } + } else { + spin_lock_bh(&priv->ps_state_lock); + priv->link_id_db[priv->action_linkid - 1].prev_status = + priv->link_id_db[priv->action_linkid - 1].status; + priv->link_id_db[priv->action_linkid - 1].status = + CW1200_LINK_RESET_REMAP; + spin_unlock_bh(&priv->ps_state_lock); + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, &priv->link_id_work) <= 0) + wsm_unlock_tx(priv); + flush_workqueue(priv->workqueue); + } +} + +int cw1200_find_link_id(struct cw1200_common *priv, const u8 *mac) +{ + int i, ret = 0; + spin_lock_bh(&priv->ps_state_lock); + for (i = 0; i < CW1200_MAX_STA_IN_AP_MODE; ++i) { + if (!memcmp(mac, priv->link_id_db[i].mac, ETH_ALEN) && + priv->link_id_db[i].status) { + priv->link_id_db[i].timestamp = jiffies; + ret = i + 1; + break; + } + } + spin_unlock_bh(&priv->ps_state_lock); + return ret; +} + +int cw1200_alloc_link_id(struct cw1200_common *priv, const u8 *mac) +{ + int i, ret = 0; + unsigned long max_inactivity = 0; + unsigned long now = jiffies; + + spin_lock_bh(&priv->ps_state_lock); + for (i = 0; i < CW1200_MAX_STA_IN_AP_MODE; ++i) { + if (!priv->link_id_db[i].status) { + ret = i + 1; + break; + } else if (priv->link_id_db[i].status != CW1200_LINK_HARD && + !priv->tx_queue_stats.link_map_cache[i + 1]) { + unsigned long inactivity = + now - priv->link_id_db[i].timestamp; + if (inactivity < max_inactivity) + continue; + max_inactivity = inactivity; + ret = i + 1; + } + } + if (ret) { + struct cw1200_link_entry *entry = &priv->link_id_db[ret - 1]; + pr_debug("[AP] STA added, link_id: %d\n", ret); + entry->status = CW1200_LINK_RESERVE; + memcpy(&entry->mac, mac, ETH_ALEN); + memset(&entry->buffered, 0, CW1200_MAX_TID); + skb_queue_head_init(&entry->rx_queue); + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, &priv->link_id_work) <= 0) + wsm_unlock_tx(priv); + } else { + wiphy_info(priv->hw->wiphy, + "[AP] Early: no more link IDs available.\n"); + } + + spin_unlock_bh(&priv->ps_state_lock); + return ret; +} + +void cw1200_link_id_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, link_id_work); + wsm_flush_tx(priv); + cw1200_link_id_gc_work(&priv->link_id_gc_work.work); + wsm_unlock_tx(priv); +} + +void cw1200_link_id_gc_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, link_id_gc_work.work); + struct wsm_reset reset = { + .reset_statistics = false, + }; + struct wsm_map_link map_link = { + .link_id = 0, + }; + unsigned long now = jiffies; + unsigned long next_gc = -1; + long ttl; + bool need_reset; + u32 mask; + int i; + + if (priv->join_status != CW1200_JOIN_STATUS_AP) + return; + + wsm_lock_tx(priv); + spin_lock_bh(&priv->ps_state_lock); + for (i = 0; i < CW1200_MAX_STA_IN_AP_MODE; ++i) { + need_reset = false; + mask = BIT(i + 1); + if (priv->link_id_db[i].status == CW1200_LINK_RESERVE || + (priv->link_id_db[i].status == CW1200_LINK_HARD && + !(priv->link_id_map & mask))) { + if (priv->link_id_map & mask) { + priv->sta_asleep_mask &= ~mask; + priv->pspoll_mask &= ~mask; + need_reset = true; + } + priv->link_id_map |= mask; + if (priv->link_id_db[i].status != CW1200_LINK_HARD) + priv->link_id_db[i].status = CW1200_LINK_SOFT; + memcpy(map_link.mac_addr, priv->link_id_db[i].mac, + ETH_ALEN); + spin_unlock_bh(&priv->ps_state_lock); + if (need_reset) { + reset.link_id = i + 1; + wsm_reset(priv, &reset); + } + map_link.link_id = i + 1; + wsm_map_link(priv, &map_link); + next_gc = min(next_gc, CW1200_LINK_ID_GC_TIMEOUT); + spin_lock_bh(&priv->ps_state_lock); + } else if (priv->link_id_db[i].status == CW1200_LINK_SOFT) { + ttl = priv->link_id_db[i].timestamp - now + + CW1200_LINK_ID_GC_TIMEOUT; + if (ttl <= 0) { + need_reset = true; + priv->link_id_db[i].status = CW1200_LINK_OFF; + priv->link_id_map &= ~mask; + priv->sta_asleep_mask &= ~mask; + priv->pspoll_mask &= ~mask; + memset(map_link.mac_addr, 0, ETH_ALEN); + spin_unlock_bh(&priv->ps_state_lock); + reset.link_id = i + 1; + wsm_reset(priv, &reset); + spin_lock_bh(&priv->ps_state_lock); + } else { + next_gc = min_t(unsigned long, next_gc, ttl); + } + } else if (priv->link_id_db[i].status == CW1200_LINK_RESET || + priv->link_id_db[i].status == + CW1200_LINK_RESET_REMAP) { + int status = priv->link_id_db[i].status; + priv->link_id_db[i].status = + priv->link_id_db[i].prev_status; + priv->link_id_db[i].timestamp = now; + reset.link_id = i + 1; + spin_unlock_bh(&priv->ps_state_lock); + wsm_reset(priv, &reset); + if (status == CW1200_LINK_RESET_REMAP) { + memcpy(map_link.mac_addr, + priv->link_id_db[i].mac, + ETH_ALEN); + map_link.link_id = i + 1; + wsm_map_link(priv, &map_link); + next_gc = min(next_gc, + CW1200_LINK_ID_GC_TIMEOUT); + } + spin_lock_bh(&priv->ps_state_lock); + } + if (need_reset) { + skb_queue_purge(&priv->link_id_db[i].rx_queue); + pr_debug("[AP] STA removed, link_id: %d\n", + reset.link_id); + } + } + spin_unlock_bh(&priv->ps_state_lock); + if (next_gc != -1) + queue_delayed_work(priv->workqueue, + &priv->link_id_gc_work, next_gc); + wsm_unlock_tx(priv); +} diff --git a/drivers/net/wireless/cw1200/txrx.h b/drivers/net/wireless/cw1200/txrx.h new file mode 100644 index 000000000000..492a4e14213b --- /dev/null +++ b/drivers/net/wireless/cw1200/txrx.h @@ -0,0 +1,106 @@ +/* + * Datapath interface for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_TXRX_H +#define CW1200_TXRX_H + +#include + +/* extern */ struct ieee80211_hw; +/* extern */ struct sk_buff; +/* extern */ struct wsm_tx; +/* extern */ struct wsm_rx; +/* extern */ struct wsm_tx_confirm; +/* extern */ struct cw1200_txpriv; + +struct tx_policy { + union { + __le32 tbl[3]; + u8 raw[12]; + }; + u8 defined; + u8 usage_count; + u8 retry_count; + u8 uploaded; +}; + +struct tx_policy_cache_entry { + struct tx_policy policy; + struct list_head link; +}; + +#define TX_POLICY_CACHE_SIZE (8) +struct tx_policy_cache { + struct tx_policy_cache_entry cache[TX_POLICY_CACHE_SIZE]; + struct list_head used; + struct list_head free; + spinlock_t lock; /* Protect policy cache */ +}; + +/* ******************************************************************** */ +/* TX policy cache */ +/* Intention of TX policy cache is an overcomplicated WSM API. + * Device does not accept per-PDU tx retry sequence. + * It uses "tx retry policy id" instead, so driver code has to sync + * linux tx retry sequences with a retry policy table in the device. + */ +void tx_policy_init(struct cw1200_common *priv); +void tx_policy_upload_work(struct work_struct *work); +void tx_policy_clean(struct cw1200_common *priv); + +/* ******************************************************************** */ +/* TX implementation */ + +u32 cw1200_rate_mask_to_wsm(struct cw1200_common *priv, + u32 rates); +void cw1200_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb); +void cw1200_skb_dtor(struct cw1200_common *priv, + struct sk_buff *skb, + const struct cw1200_txpriv *txpriv); + +/* ******************************************************************** */ +/* WSM callbacks */ + +void cw1200_tx_confirm_cb(struct cw1200_common *priv, + int link_id, + struct wsm_tx_confirm *arg); +void cw1200_rx_cb(struct cw1200_common *priv, + struct wsm_rx *arg, + int link_id, + struct sk_buff **skb_p); + +/* ******************************************************************** */ +/* Timeout */ + +void cw1200_tx_timeout(struct work_struct *work); + +/* ******************************************************************** */ +/* Security */ +int cw1200_alloc_key(struct cw1200_common *priv); +void cw1200_free_key(struct cw1200_common *priv, int idx); +void cw1200_free_keys(struct cw1200_common *priv); +int cw1200_upload_keys(struct cw1200_common *priv); + +/* ******************************************************************** */ +/* Workaround for WFD test case 6.1.10 */ +void cw1200_link_id_reset(struct work_struct *work); + +#define CW1200_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ)) + +int cw1200_find_link_id(struct cw1200_common *priv, const u8 *mac); +int cw1200_alloc_link_id(struct cw1200_common *priv, const u8 *mac); +void cw1200_link_id_work(struct work_struct *work); +void cw1200_link_id_gc_work(struct work_struct *work); + + +#endif /* CW1200_TXRX_H */ diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c new file mode 100644 index 000000000000..4db6cc16879c --- /dev/null +++ b/drivers/net/wireless/cw1200/wsm.c @@ -0,0 +1,1884 @@ +/* + * WSM host interface (HI) implementation for + * ST-Ericsson CW1200 mac80211 drivers. + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include "cw1200.h" +#include "wsm.h" +#include "bh.h" +#include "sta.h" +#include "debug.h" +#include "itp.h" + +#define WSM_CMD_TIMEOUT (2 * HZ) /* With respect to interrupt loss */ +#define WSM_CMD_START_TIMEOUT (7 * HZ) +#define WSM_CMD_RESET_TIMEOUT (3 * HZ) /* 2 sec. timeout was observed. */ +#define WSM_CMD_MAX_TIMEOUT (3 * HZ) + +#define WSM_SKIP(buf, size) \ + do { \ + if ((buf)->data + size > (buf)->end) \ + goto underflow; \ + (buf)->data += size; \ + } while (0) + +#define WSM_GET(buf, ptr, size) \ + do { \ + if ((buf)->data + size > (buf)->end) \ + goto underflow; \ + memcpy(ptr, (buf)->data, size); \ + (buf)->data += size; \ + } while (0) + +#define __WSM_GET(buf, type, cvt) \ + ({ \ + type val; \ + if ((buf)->data + sizeof(type) > (buf)->end) \ + goto underflow; \ + val = cvt(*(type *)(buf)->data); \ + (buf)->data += sizeof(type); \ + val; \ + }) + +#define WSM_GET8(buf) __WSM_GET(buf, u8, (u8)) +#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu) +#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu) + +#define WSM_PUT(buf, ptr, size) \ + do { \ + if ((buf)->data + size > (buf)->end) \ + if (wsm_buf_reserve((buf), size)) \ + goto nomem; \ + memcpy((buf)->data, ptr, size); \ + (buf)->data += size; \ + } while (0) + +#define __WSM_PUT(buf, val, type, cvt) \ + do { \ + if ((buf)->data + sizeof(type) > (buf)->end) \ + if (wsm_buf_reserve((buf), sizeof(type))) \ + goto nomem; \ + *(type *)(buf)->data = cvt(val); \ + (buf)->data += sizeof(type); \ + } while (0) + +#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8)) +#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16) +#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32) + +static void wsm_buf_reset(struct wsm_buf *buf); +static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size); + +static int wsm_cmd_send(struct cw1200_common *priv, + struct wsm_buf *buf, + void *arg, u16 cmd, long tmo); + +#define wsm_cmd_lock(__priv) mutex_lock(&((__priv)->wsm_cmd_mux)) +#define wsm_cmd_unlock(__priv) mutex_unlock(&((__priv)->wsm_cmd_mux)) + +/* ******************************************************************** */ +/* WSM API implementation */ + +static int wsm_generic_confirm(struct cw1200_common *priv, + void *arg, + struct wsm_buf *buf) +{ + u32 status = WSM_GET32(buf); + if (status != WSM_STATUS_SUCCESS) + return -EINVAL; + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +int wsm_configuration(struct cw1200_common *priv, struct wsm_configuration *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT32(buf, arg->dot11MaxTransmitMsduLifeTime); + WSM_PUT32(buf, arg->dot11MaxReceiveLifeTime); + WSM_PUT32(buf, arg->dot11RtsThreshold); + + /* DPD block. */ + WSM_PUT16(buf, arg->dpdData_size + 12); + WSM_PUT16(buf, 1); /* DPD version */ + WSM_PUT(buf, arg->dot11StationId, ETH_ALEN); + WSM_PUT16(buf, 5); /* DPD flags */ + WSM_PUT(buf, arg->dpdData, arg->dpdData_size); + + ret = wsm_cmd_send(priv, buf, arg, + WSM_CONFIGURATION_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +static int wsm_configuration_confirm(struct cw1200_common *priv, + struct wsm_configuration *arg, + struct wsm_buf *buf) +{ + int i; + int status; + + status = WSM_GET32(buf); + if (WARN_ON(status != WSM_STATUS_SUCCESS)) + return -EINVAL; + + WSM_GET(buf, arg->dot11StationId, ETH_ALEN); + arg->dot11FrequencyBandsSupported = WSM_GET8(buf); + WSM_SKIP(buf, 1); + arg->supportedRateMask = WSM_GET32(buf); + for (i = 0; i < 2; ++i) { + arg->txPowerRange[i].min_power_level = WSM_GET32(buf); + arg->txPowerRange[i].max_power_level = WSM_GET32(buf); + arg->txPowerRange[i].stepping = WSM_GET32(buf); + } + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +/* ******************************************************************** */ + +int wsm_reset(struct cw1200_common *priv, const struct wsm_reset *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + u16 cmd = WSM_RESET_REQ_ID | WSM_TX_LINK_ID(arg->link_id); + + wsm_cmd_lock(priv); + + WSM_PUT32(buf, arg->reset_statistics ? 0 : 1); + ret = wsm_cmd_send(priv, buf, NULL, cmd, WSM_CMD_RESET_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +struct wsm_mib { + u16 mib_id; + void *buf; + size_t buf_size; +}; + +int wsm_read_mib(struct cw1200_common *priv, u16 mib_id, void *_buf, + size_t buf_size) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + struct wsm_mib mib_buf = { + .mib_id = mib_id, + .buf = _buf, + .buf_size = buf_size, + }; + wsm_cmd_lock(priv); + + WSM_PUT16(buf, mib_id); + WSM_PUT16(buf, 0); + + ret = wsm_cmd_send(priv, buf, &mib_buf, + WSM_READ_MIB_REQ_ID, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +static int wsm_read_mib_confirm(struct cw1200_common *priv, + struct wsm_mib *arg, + struct wsm_buf *buf) +{ + u16 size; + if (WARN_ON(WSM_GET32(buf) != WSM_STATUS_SUCCESS)) + return -EINVAL; + + if (WARN_ON(WSM_GET16(buf) != arg->mib_id)) + return -EINVAL; + + size = WSM_GET16(buf); + if (size > arg->buf_size) + size = arg->buf_size; + + WSM_GET(buf, arg->buf, size); + arg->buf_size = size; + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +/* ******************************************************************** */ + +int wsm_write_mib(struct cw1200_common *priv, u16 mib_id, void *_buf, + size_t buf_size) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + struct wsm_mib mib_buf = { + .mib_id = mib_id, + .buf = _buf, + .buf_size = buf_size, + }; + + wsm_cmd_lock(priv); + + WSM_PUT16(buf, mib_id); + WSM_PUT16(buf, buf_size); + WSM_PUT(buf, _buf, buf_size); + + ret = wsm_cmd_send(priv, buf, &mib_buf, + WSM_WRITE_MIB_REQ_ID, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +static int wsm_write_mib_confirm(struct cw1200_common *priv, + struct wsm_mib *arg, + struct wsm_buf *buf) +{ + int ret; + + ret = wsm_generic_confirm(priv, arg, buf); + if (ret) + return ret; + + if (arg->mib_id == WSM_MIB_ID_OPERATIONAL_POWER_MODE) { + /* OperationalMode: update PM status. */ + const char *p = arg->buf; + cw1200_enable_powersave(priv, (p[0] & 0x0F) ? true : false); + } + return 0; +} + +/* ******************************************************************** */ + +int wsm_scan(struct cw1200_common *priv, const struct wsm_scan *arg) +{ + int i; + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + if (arg->num_channels > 48) + return -EINVAL; + + if (arg->num_ssids > 2) + return -EINVAL; + + if (arg->band > 1) + return -EINVAL; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->band); + WSM_PUT8(buf, arg->type); + WSM_PUT8(buf, arg->flags); + WSM_PUT8(buf, arg->max_tx_rate); + WSM_PUT32(buf, arg->auto_scan_interval); + WSM_PUT8(buf, arg->num_probes); + WSM_PUT8(buf, arg->num_channels); + WSM_PUT8(buf, arg->num_ssids); + WSM_PUT8(buf, arg->probe_delay); + + for (i = 0; i < arg->num_channels; ++i) { + WSM_PUT16(buf, arg->ch[i].number); + WSM_PUT16(buf, 0); + WSM_PUT32(buf, arg->ch[i].min_chan_time); + WSM_PUT32(buf, arg->ch[i].max_chan_time); + WSM_PUT32(buf, 0); + } + + for (i = 0; i < arg->num_ssids; ++i) { + WSM_PUT32(buf, arg->ssids[i].length); + WSM_PUT(buf, &arg->ssids[i].ssid[0], + sizeof(arg->ssids[i].ssid)); + } + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_START_SCAN_REQ_ID, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_stop_scan(struct cw1200_common *priv) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + wsm_cmd_lock(priv); + ret = wsm_cmd_send(priv, buf, NULL, + WSM_STOP_SCAN_REQ_ID, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; +} + + +static int wsm_tx_confirm(struct cw1200_common *priv, + struct wsm_buf *buf, + int link_id) +{ + struct wsm_tx_confirm tx_confirm; + + tx_confirm.packet_id = WSM_GET32(buf); + tx_confirm.status = WSM_GET32(buf); + tx_confirm.tx_rate = WSM_GET8(buf); + tx_confirm.ack_failures = WSM_GET8(buf); + tx_confirm.flags = WSM_GET16(buf); + tx_confirm.media_delay = WSM_GET32(buf); + tx_confirm.tx_queue_delay = WSM_GET32(buf); + + cw1200_tx_confirm_cb(priv, link_id, &tx_confirm); + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +static int wsm_multi_tx_confirm(struct cw1200_common *priv, + struct wsm_buf *buf, int link_id) +{ + int ret; + int count; + int i; + + count = WSM_GET32(buf); + if (WARN_ON(count <= 0)) + return -EINVAL; + + if (count > 1) { + /* We already released one buffer, now for the rest */ + ret = wsm_release_tx_buffer(priv, count - 1); + if (ret < 0) + return ret; + else if (ret > 0) + cw1200_bh_wakeup(priv); + } + + cw1200_debug_txed_multi(priv, count); + for (i = 0; i < count; ++i) { + ret = wsm_tx_confirm(priv, buf, link_id); + if (ret) + return ret; + } + return ret; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +/* ******************************************************************** */ + +static int wsm_join_confirm(struct cw1200_common *priv, + struct wsm_join_cnf *arg, + struct wsm_buf *buf) +{ + arg->status = WSM_GET32(buf); + if (WARN_ON(arg->status) != WSM_STATUS_SUCCESS) + return -EINVAL; + + arg->min_power_level = WSM_GET32(buf); + arg->max_power_level = WSM_GET32(buf); + + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +int wsm_join(struct cw1200_common *priv, struct wsm_join *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + struct wsm_join_cnf resp; + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->mode); + WSM_PUT8(buf, arg->band); + WSM_PUT16(buf, arg->channel_number); + WSM_PUT(buf, &arg->bssid[0], sizeof(arg->bssid)); + WSM_PUT16(buf, arg->atim_window); + WSM_PUT8(buf, arg->preamble_type); + WSM_PUT8(buf, arg->probe_for_join); + WSM_PUT8(buf, arg->dtim_period); + WSM_PUT8(buf, arg->flags); + WSM_PUT32(buf, arg->ssid_len); + WSM_PUT(buf, &arg->ssid[0], sizeof(arg->ssid)); + WSM_PUT32(buf, arg->beacon_interval); + WSM_PUT32(buf, arg->basic_rate_set); + + priv->tx_burst_idx = -1; + ret = wsm_cmd_send(priv, buf, &resp, + WSM_JOIN_REQ_ID, WSM_CMD_TIMEOUT); + /* TODO: Update state based on resp.min|max_power_level */ + + priv->join_complete_status = resp.status; + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_set_bss_params(struct cw1200_common *priv, + const struct wsm_set_bss_params *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, (arg->reset_beacon_loss ? 0x1 : 0)); + WSM_PUT8(buf, arg->beacon_lost_count); + WSM_PUT16(buf, arg->aid); + WSM_PUT32(buf, arg->operational_rate_set); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_SET_BSS_PARAMS_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_add_key(struct cw1200_common *priv, const struct wsm_add_key *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT(buf, arg, sizeof(*arg)); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_ADD_KEY_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_remove_key(struct cw1200_common *priv, const struct wsm_remove_key *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->index); + WSM_PUT8(buf, 0); + WSM_PUT16(buf, 0); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_REMOVE_KEY_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_set_tx_queue_params(struct cw1200_common *priv, + const struct wsm_set_tx_queue_params *arg, u8 id) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + u8 queue_id_to_wmm_aci[] = {3, 2, 0, 1}; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, queue_id_to_wmm_aci[id]); + WSM_PUT8(buf, 0); + WSM_PUT8(buf, arg->ackPolicy); + WSM_PUT8(buf, 0); + WSM_PUT32(buf, arg->maxTransmitLifetime); + WSM_PUT16(buf, arg->allowedMediumTime); + WSM_PUT16(buf, 0); + + ret = wsm_cmd_send(priv, buf, NULL, 0x0012, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_set_edca_params(struct cw1200_common *priv, + const struct wsm_edca_params *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + /* Implemented according to specification. */ + + WSM_PUT16(buf, arg->params[3].cwmin); + WSM_PUT16(buf, arg->params[2].cwmin); + WSM_PUT16(buf, arg->params[1].cwmin); + WSM_PUT16(buf, arg->params[0].cwmin); + + WSM_PUT16(buf, arg->params[3].cwmax); + WSM_PUT16(buf, arg->params[2].cwmax); + WSM_PUT16(buf, arg->params[1].cwmax); + WSM_PUT16(buf, arg->params[0].cwmax); + + WSM_PUT8(buf, arg->params[3].aifns); + WSM_PUT8(buf, arg->params[2].aifns); + WSM_PUT8(buf, arg->params[1].aifns); + WSM_PUT8(buf, arg->params[0].aifns); + + WSM_PUT16(buf, arg->params[3].txop_limit); + WSM_PUT16(buf, arg->params[2].txop_limit); + WSM_PUT16(buf, arg->params[1].txop_limit); + WSM_PUT16(buf, arg->params[0].txop_limit); + + WSM_PUT32(buf, arg->params[3].max_rx_lifetime); + WSM_PUT32(buf, arg->params[2].max_rx_lifetime); + WSM_PUT32(buf, arg->params[1].max_rx_lifetime); + WSM_PUT32(buf, arg->params[0].max_rx_lifetime); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_EDCA_PARAMS_REQ_ID, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_switch_channel(struct cw1200_common *priv, + const struct wsm_switch_channel *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->mode); + WSM_PUT8(buf, arg->switch_count); + WSM_PUT16(buf, arg->channel_number); + + priv->channel_switch_in_progress = 1; + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_SWITCH_CHANNEL_REQ_ID, WSM_CMD_TIMEOUT); + if (ret) + priv->channel_switch_in_progress = 0; + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + priv->ps_mode_switch_in_progress = 1; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->mode); + WSM_PUT8(buf, arg->fast_psm_idle_period); + WSM_PUT8(buf, arg->ap_psm_change_period); + WSM_PUT8(buf, arg->min_auto_pspoll_period); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_SET_PM_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_start(struct cw1200_common *priv, const struct wsm_start *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT8(buf, arg->mode); + WSM_PUT8(buf, arg->band); + WSM_PUT16(buf, arg->channel_number); + WSM_PUT32(buf, arg->ct_window); + WSM_PUT32(buf, arg->beacon_interval); + WSM_PUT8(buf, arg->dtim_period); + WSM_PUT8(buf, arg->preamble); + WSM_PUT8(buf, arg->probe_delay); + WSM_PUT8(buf, arg->ssid_len); + WSM_PUT(buf, arg->ssid, sizeof(arg->ssid)); + WSM_PUT32(buf, arg->basic_rate_set); + + priv->tx_burst_idx = -1; + ret = wsm_cmd_send(priv, buf, NULL, + WSM_START_REQ_ID, WSM_CMD_START_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_beacon_transmit(struct cw1200_common *priv, + const struct wsm_beacon_transmit *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT32(buf, arg->enable_beaconing ? 1 : 0); + + ret = wsm_cmd_send(priv, buf, NULL, + WSM_BEACON_TRANSMIT_REQ_ID, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_start_find(struct cw1200_common *priv) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + ret = wsm_cmd_send(priv, buf, NULL, 0x0019, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; +} + +/* ******************************************************************** */ + +int wsm_stop_find(struct cw1200_common *priv) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + ret = wsm_cmd_send(priv, buf, NULL, 0x001A, WSM_CMD_TIMEOUT); + wsm_cmd_unlock(priv); + return ret; +} + +/* ******************************************************************** */ + +int wsm_map_link(struct cw1200_common *priv, const struct wsm_map_link *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + u16 cmd = 0x001C | WSM_TX_LINK_ID(arg->link_id); + + wsm_cmd_lock(priv); + + WSM_PUT(buf, &arg->mac_addr[0], sizeof(arg->mac_addr)); + WSM_PUT16(buf, 0); + + ret = wsm_cmd_send(priv, buf, NULL, cmd, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ + +int wsm_update_ie(struct cw1200_common *priv, + const struct wsm_update_ie *arg) +{ + int ret; + struct wsm_buf *buf = &priv->wsm_cmd_buf; + + wsm_cmd_lock(priv); + + WSM_PUT16(buf, arg->what); + WSM_PUT16(buf, arg->count); + WSM_PUT(buf, arg->ies, arg->length); + + ret = wsm_cmd_send(priv, buf, NULL, 0x001B, WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} + +/* ******************************************************************** */ +int wsm_set_probe_responder(struct cw1200_common *priv, bool enable) +{ + priv->rx_filter.probeResponder = enable; + return wsm_set_rx_filter(priv, &priv->rx_filter); +} + +/* ******************************************************************** */ +/* WSM indication events implementation */ +const char * const cw1200_fw_types[] = { + "ETF", + "WFM", + "WSM", + "HI test", + "Platform test" +}; + +static int wsm_startup_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + priv->wsm_caps.input_buffers = WSM_GET16(buf); + priv->wsm_caps.input_buffer_size = WSM_GET16(buf); + priv->wsm_caps.hw_id = WSM_GET16(buf); + priv->wsm_caps.hw_subid = WSM_GET16(buf); + priv->wsm_caps.status = WSM_GET16(buf); + priv->wsm_caps.fw_cap = WSM_GET16(buf); + priv->wsm_caps.fw_type = WSM_GET16(buf); + priv->wsm_caps.fw_api = WSM_GET16(buf); + priv->wsm_caps.fw_build = WSM_GET16(buf); + priv->wsm_caps.fw_ver = WSM_GET16(buf); + WSM_GET(buf, priv->wsm_caps.fw_label, sizeof(priv->wsm_caps.fw_label)); + priv->wsm_caps.fw_label[sizeof(priv->wsm_caps.fw_label) - 1] = 0; /* Do not trust FW too much... */ + + if (WARN_ON(priv->wsm_caps.status)) + return -EINVAL; + + if (WARN_ON(priv->wsm_caps.fw_type > 4)) + return -EINVAL; + + pr_info("CW1200 WSM init done.\n" + " Input buffers: %d x %d bytes\n" + " Hardware: %d.%d\n" + " %s firmware [%s], ver: %d, build: %d," + " api: %d, cap: 0x%.4X\n", + priv->wsm_caps.input_buffers, + priv->wsm_caps.input_buffer_size, + priv->wsm_caps.hw_id, priv->wsm_caps.hw_subid, + cw1200_fw_types[priv->wsm_caps.fw_type], + priv->wsm_caps.fw_label, priv->wsm_caps.fw_ver, + priv->wsm_caps.fw_build, + priv->wsm_caps.fw_api, priv->wsm_caps.fw_cap); + + /* Disable unsupported frequency bands */ + if (!(priv->wsm_caps.fw_cap & 0x1)) + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + if (!(priv->wsm_caps.fw_cap & 0x2)) + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + + priv->firmware_ready = 1; + wake_up(&priv->wsm_startup_done); + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +static int wsm_receive_indication(struct cw1200_common *priv, + int link_id, + struct wsm_buf *buf, + struct sk_buff **skb_p) +{ + struct wsm_rx rx; + struct ieee80211_hdr *hdr; + size_t hdr_len; + __le16 fctl; + + rx.status = WSM_GET32(buf); + rx.channel_number = WSM_GET16(buf); + rx.rx_rate = WSM_GET8(buf); + rx.rcpi_rssi = WSM_GET8(buf); + rx.flags = WSM_GET32(buf); + + /* FW Workaround: Drop probe resp or + beacon when RSSI is 0 + */ + hdr = (struct ieee80211_hdr *)(*skb_p)->data; + + if (!rx.rcpi_rssi && + (ieee80211_is_probe_resp(hdr->frame_control) || + ieee80211_is_beacon(hdr->frame_control))) + return 0; + + /* If no RSSI subscription has been made, + * convert RCPI to RSSI here + */ + if (!priv->cqm_use_rssi) + rx.rcpi_rssi = rx.rcpi_rssi / 2 - 110; + + fctl = *(__le16 *)buf->data; + hdr_len = buf->data - buf->begin; + skb_pull(*skb_p, hdr_len); + if (!rx.status && ieee80211_is_deauth(fctl)) { + if (priv->join_status == CW1200_JOIN_STATUS_STA) { + /* Shedule unjoin work */ + pr_debug("[WSM] Issue unjoin command (RX).\n"); + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, + &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + } + } + cw1200_rx_cb(priv, &rx, link_id, skb_p); + if (*skb_p) + skb_push(*skb_p, hdr_len); + + return 0; + +underflow: + return -EINVAL; +} + +static int wsm_event_indication(struct cw1200_common *priv, struct wsm_buf *buf) +{ + int first; + struct cw1200_wsm_event *event; + + if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) { + /* STA is stopped. */ + return 0; + } + + event = kzalloc(sizeof(struct cw1200_wsm_event), GFP_KERNEL); + + event->evt.id = __le32_to_cpu(WSM_GET32(buf)); + event->evt.data = __le32_to_cpu(WSM_GET32(buf)); + + pr_debug("[WSM] Event: %d(%d)\n", + event->evt.id, event->evt.data); + + spin_lock(&priv->event_queue_lock); + first = list_empty(&priv->event_queue); + list_add_tail(&event->link, &priv->event_queue); + spin_unlock(&priv->event_queue_lock); + + if (first) + queue_work(priv->workqueue, &priv->event_handler); + + return 0; + +underflow: + kfree(event); + return -EINVAL; +} + +static int wsm_channel_switch_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + WARN_ON(WSM_GET32(buf)); + + priv->channel_switch_in_progress = 0; + wake_up(&priv->channel_switch_done); + + wsm_unlock_tx(priv); + + return 0; + +underflow: + return -EINVAL; +} + +static int wsm_set_pm_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + /* TODO: Check buf (struct wsm_set_pm_complete) for validity */ + if (priv->ps_mode_switch_in_progress) { + priv->ps_mode_switch_in_progress = 0; + wake_up(&priv->ps_mode_switch_done); + } + return 0; +} + +static int wsm_scan_started(struct cw1200_common *priv, void *arg, + struct wsm_buf *buf) +{ + u32 status = WSM_GET32(buf); + if (status != WSM_STATUS_SUCCESS) { + cw1200_scan_failed_cb(priv); + return -EINVAL; + } + return 0; + +underflow: + WARN_ON(1); + return -EINVAL; +} + +static int wsm_scan_complete_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + struct wsm_scan_complete arg; + arg.status = WSM_GET32(buf); + arg.psm = WSM_GET8(buf); + arg.num_channels = WSM_GET8(buf); + cw1200_scan_complete_cb(priv, &arg); + + return 0; + +underflow: + return -EINVAL; +} + +static int wsm_join_complete_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + struct wsm_join_complete arg; + arg.status = WSM_GET32(buf); + pr_debug("[WSM] Join complete indication, status: %d\n", arg.status); + cw1200_join_complete_cb(priv, &arg); + + return 0; + +underflow: + return -EINVAL; +} + +static int wsm_find_complete_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + pr_warn("Implement find_complete_indication\n"); + return 0; +} + +static int wsm_ba_timeout_indication(struct cw1200_common *priv, + struct wsm_buf *buf) +{ + u32 dummy; + u8 tid; + u8 dummy2; + u8 addr[ETH_ALEN]; + + dummy = WSM_GET32(buf); + tid = WSM_GET8(buf); + dummy2 = WSM_GET8(buf); + WSM_GET(buf, addr, ETH_ALEN); + + pr_info("BlockACK timeout, tid %d, addr %pM\n", + tid, addr); + + return 0; + +underflow: + return -EINVAL; +} + +static int wsm_suspend_resume_indication(struct cw1200_common *priv, + int link_id, struct wsm_buf *buf) +{ + u32 flags; + struct wsm_suspend_resume arg; + + flags = WSM_GET32(buf); + arg.link_id = link_id; + arg.stop = !(flags & 1); + arg.multicast = !!(flags & 8); + arg.queue = (flags >> 1) & 3; + + cw1200_suspend_resume(priv, &arg); + + return 0; + +underflow: + return -EINVAL; +} + + +/* ******************************************************************** */ +/* WSM TX */ + +static int wsm_cmd_send(struct cw1200_common *priv, + struct wsm_buf *buf, + void *arg, u16 cmd, long tmo) +{ + size_t buf_len = buf->data - buf->begin; + int ret; + + /* Don't bother if we're dead. */ + if (priv->bh_error) { + ret = 0; + goto done; + } + + /* Block until the cmd buffer is completed. Tortuous. */ + spin_lock(&priv->wsm_cmd.lock); + while (!priv->wsm_cmd.done) { + spin_unlock(&priv->wsm_cmd.lock); + spin_lock(&priv->wsm_cmd.lock); + } + priv->wsm_cmd.done = 0; + spin_unlock(&priv->wsm_cmd.lock); + + if (cmd == WSM_WRITE_MIB_REQ_ID || + cmd == WSM_READ_MIB_REQ_ID) + pr_debug("[WSM] >>> 0x%.4X [MIB: 0x%.4X] (%zu)\n", + cmd, __le16_to_cpu(((__le16 *)buf->begin)[2]), + buf_len); + else + pr_debug("[WSM] >>> 0x%.4X (%zu)\n", cmd, buf_len); + + /* + * Due to buggy SPI on CW1200, we need to + * pad the message by a few bytes to ensure + * that it's completely received. + */ +#ifdef CONFIG_CW1200_ETF + if (!etf_mode) +#endif + buf_len += 4; + + /* Fill HI message header */ + /* BH will add sequence number */ + ((__le16 *)buf->begin)[0] = __cpu_to_le16(buf_len); + ((__le16 *)buf->begin)[1] = __cpu_to_le16(cmd); + + spin_lock(&priv->wsm_cmd.lock); + BUG_ON(priv->wsm_cmd.ptr); + priv->wsm_cmd.ptr = buf->begin; + priv->wsm_cmd.len = buf_len; + priv->wsm_cmd.arg = arg; + priv->wsm_cmd.cmd = cmd; + spin_unlock(&priv->wsm_cmd.lock); + + cw1200_bh_wakeup(priv); + + /* Wait for command completion */ + ret = wait_event_timeout(priv->wsm_cmd_wq, + priv->wsm_cmd.done, tmo); + + if (!ret && !priv->wsm_cmd.done) { + spin_lock(&priv->wsm_cmd.lock); + priv->wsm_cmd.done = 1; + priv->wsm_cmd.ptr = NULL; + spin_unlock(&priv->wsm_cmd.lock); + if (priv->bh_error) { + /* Return ok to help system cleanup */ + ret = 0; + } else { + pr_err("CMD req (0x%04x) stuck in firmware, killing BH\n", priv->wsm_cmd.cmd); + print_hex_dump_bytes("REQDUMP: ", DUMP_PREFIX_NONE, + buf->begin, buf_len); + pr_err("Outstanding outgoing frames: %d\n", priv->hw_bufs_used); + + /* Kill BH thread to report the error to the top layer. */ + atomic_add(1, &priv->bh_term); + wake_up(&priv->bh_wq); + ret = -ETIMEDOUT; + } + } else { + spin_lock(&priv->wsm_cmd.lock); + BUG_ON(!priv->wsm_cmd.done); + ret = priv->wsm_cmd.ret; + spin_unlock(&priv->wsm_cmd.lock); + } +done: + wsm_buf_reset(buf); + return ret; +} + +#ifdef CONFIG_CW1200_ETF +int wsm_raw_cmd(struct cw1200_common *priv, u8 *data, size_t len) +{ + struct wsm_buf *buf = &priv->wsm_cmd_buf; + int ret; + + u16 *cmd = (u16 *)(data + 2); + + wsm_cmd_lock(priv); + + WSM_PUT(buf, data + 4, len - 4); /* Skip over header (u16+u16) */ + + ret = wsm_cmd_send(priv, buf, NULL, __le16_to_cpu(*cmd), WSM_CMD_TIMEOUT); + + wsm_cmd_unlock(priv); + return ret; + +nomem: + wsm_cmd_unlock(priv); + return -ENOMEM; +} +#endif /* CONFIG_CW1200_ETF */ + +/* ******************************************************************** */ +/* WSM TX port control */ + +void wsm_lock_tx(struct cw1200_common *priv) +{ + wsm_cmd_lock(priv); + if (atomic_add_return(1, &priv->tx_lock) == 1) { + if (wsm_flush_tx(priv)) + pr_debug("[WSM] TX is locked.\n"); + } + wsm_cmd_unlock(priv); +} + +void wsm_lock_tx_async(struct cw1200_common *priv) +{ + if (atomic_add_return(1, &priv->tx_lock) == 1) + pr_debug("[WSM] TX is locked (async).\n"); +} + +bool wsm_flush_tx(struct cw1200_common *priv) +{ + unsigned long timestamp = jiffies; + bool pending = false; + long timeout; + int i; + + /* Flush must be called with TX lock held. */ + BUG_ON(!atomic_read(&priv->tx_lock)); + + /* First check if we really need to do something. + * It is safe to use unprotected access, as hw_bufs_used + * can only decrements. + */ + if (!priv->hw_bufs_used) + return true; + + if (priv->bh_error) { + /* In case of failure do not wait for magic. */ + pr_err("[WSM] Fatal error occured, will not flush TX.\n"); + return false; + } else { + /* Get a timestamp of "oldest" frame */ + for (i = 0; i < 4; ++i) + pending |= cw1200_queue_get_xmit_timestamp( + &priv->tx_queue[i], + ×tamp, 0xffffffff); + /* If there's nothing pending, we're good */ + if (!pending) + return true; + + timeout = timestamp + WSM_CMD_LAST_CHANCE_TIMEOUT - jiffies; + if (timeout < 0 || wait_event_timeout(priv->bh_evt_wq, + !priv->hw_bufs_used, + timeout) <= 0) { + /* Hmmm... Not good. Frame had stuck in firmware. */ + priv->bh_error = 1; + wiphy_err(priv->hw->wiphy, "[WSM] TX Frames (%d) stuck in firmware, killing BH\n", priv->hw_bufs_used); + wake_up(&priv->bh_wq); + return false; + } + + /* Ok, everything is flushed. */ + return true; + } +} + +void wsm_unlock_tx(struct cw1200_common *priv) +{ + int tx_lock; + tx_lock = atomic_sub_return(1, &priv->tx_lock); + BUG_ON(tx_lock < 0); + + if (tx_lock == 0) { + if (!priv->bh_error) + cw1200_bh_wakeup(priv); + pr_debug("[WSM] TX is unlocked.\n"); + } +} + +/* ******************************************************************** */ +/* WSM RX */ + +int wsm_handle_exception(struct cw1200_common *priv, u8 *data, size_t len) +{ + struct wsm_buf buf; + u32 reason; + u32 reg[18]; + char fname[48]; + unsigned int i; + + static const char * const reason_str[] = { + "undefined instruction", + "prefetch abort", + "data abort", + "unknown error", + }; + + buf.begin = buf.data = data; + buf.end = &buf.begin[len]; + + reason = WSM_GET32(&buf); + for (i = 0; i < ARRAY_SIZE(reg); ++i) + reg[i] = WSM_GET32(&buf); + WSM_GET(&buf, fname, sizeof(fname)); + + if (reason < 4) + wiphy_err(priv->hw->wiphy, + "Firmware exception: %s.\n", + reason_str[reason]); + else + wiphy_err(priv->hw->wiphy, + "Firmware assert at %.*s, line %d\n", + (int) sizeof(fname), fname, reg[1]); + + for (i = 0; i < 12; i += 4) + wiphy_err(priv->hw->wiphy, + "R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X, R%d: 0x%.8X,\n", + i + 0, reg[i + 0], i + 1, reg[i + 1], + i + 2, reg[i + 2], i + 3, reg[i + 3]); + wiphy_err(priv->hw->wiphy, + "R12: 0x%.8X, SP: 0x%.8X, LR: 0x%.8X, PC: 0x%.8X,\n", + reg[i + 0], reg[i + 1], reg[i + 2], reg[i + 3]); + i += 4; + wiphy_err(priv->hw->wiphy, + "CPSR: 0x%.8X, SPSR: 0x%.8X\n", + reg[i + 0], reg[i + 1]); + + print_hex_dump_bytes("R1: ", DUMP_PREFIX_NONE, + fname, sizeof(fname)); + return 0; + +underflow: + wiphy_err(priv->hw->wiphy, "Firmware exception.\n"); + print_hex_dump_bytes("Exception: ", DUMP_PREFIX_NONE, + data, len); + return -EINVAL; +} + +int wsm_handle_rx(struct cw1200_common *priv, u16 id, + struct wsm_hdr *wsm, struct sk_buff **skb_p) +{ + int ret = 0; + struct wsm_buf wsm_buf; + int link_id = (id >> 6) & 0x0F; + + /* Strip link id. */ + id &= ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX); + + wsm_buf.begin = (u8 *)&wsm[0]; + wsm_buf.data = (u8 *)&wsm[1]; + wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)]; + + pr_debug("[WSM] <<< 0x%.4X (%td)\n", id, + wsm_buf.end - wsm_buf.begin); + +#ifdef CONFIG_CW1200_ETF + if (etf_mode) { + struct sk_buff *skb = alloc_skb(wsm_buf.end - wsm_buf.begin, GFP_KERNEL); + + /* Strip out Sequence num before passing up */ + wsm->id = __le16_to_cpu(wsm->id); + wsm->id &= 0x0FFF; + wsm->id = __cpu_to_le16(wsm->id); + + memcpy(skb_put(skb, wsm_buf.end - wsm_buf.begin), + wsm_buf.begin, + wsm_buf.end - wsm_buf.begin); + skb_queue_tail(&priv->etf_q, skb); + + /* Special case for startup */ + if (id == WSM_STARTUP_IND_ID) { + wsm_startup_indication(priv, &wsm_buf); + } else if (id & 0x0400) { + spin_lock(&priv->wsm_cmd.lock); + priv->wsm_cmd.done = 1; + spin_unlock(&priv->wsm_cmd.lock); + wake_up(&priv->wsm_cmd_wq); + } + + goto out; + } +#endif + + if (id == WSM_TX_CONFIRM_IND_ID) { + ret = wsm_tx_confirm(priv, &wsm_buf, link_id); + } else if (id == WSM_MULTI_TX_CONFIRM_ID) { + ret = wsm_multi_tx_confirm(priv, &wsm_buf, link_id); + } else if (id & 0x0400) { + void *wsm_arg; + u16 wsm_cmd; + + /* Do not trust FW too much. Protection against repeated + * response and race condition removal (see above). + */ + spin_lock(&priv->wsm_cmd.lock); + wsm_arg = priv->wsm_cmd.arg; + wsm_cmd = priv->wsm_cmd.cmd & + ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX); + priv->wsm_cmd.cmd = 0xFFFF; + spin_unlock(&priv->wsm_cmd.lock); + + if (WARN_ON((id & ~0x0400) != wsm_cmd)) { + /* Note that any non-zero is a fatal retcode. */ + ret = -EINVAL; + goto out; + } + + /* Note that wsm_arg can be NULL in case of timeout in + * wsm_cmd_send(). + */ + + switch (id) { + case WSM_READ_MIB_RESP_ID: + if (wsm_arg) + ret = wsm_read_mib_confirm(priv, wsm_arg, + &wsm_buf); + break; + case WSM_WRITE_MIB_RESP_ID: + if (wsm_arg) + ret = wsm_write_mib_confirm(priv, wsm_arg, + &wsm_buf); + break; + case WSM_START_SCAN_RESP_ID: + if (wsm_arg) + ret = wsm_scan_started(priv, wsm_arg, &wsm_buf); + break; + case WSM_CONFIGURATION_RESP_ID: + if (wsm_arg) + ret = wsm_configuration_confirm(priv, wsm_arg, + &wsm_buf); + break; + case WSM_JOIN_RESP_ID: + if (wsm_arg) + ret = wsm_join_confirm(priv, wsm_arg, &wsm_buf); + break; + case WSM_STOP_SCAN_RESP_ID: + case WSM_RESET_RESP_ID: + case WSM_ADD_KEY_RESP_ID: + case WSM_REMOVE_KEY_RESP_ID: + case WSM_SET_PM_RESP_ID: + case WSM_SET_BSS_PARAMS_RESP_ID: + case 0x0412: /* set_tx_queue_params */ + case WSM_EDCA_PARAMS_RESP_ID: + case WSM_SWITCH_CHANNEL_RESP_ID: + case WSM_START_RESP_ID: + case WSM_BEACON_TRANSMIT_RESP_ID: + case 0x0419: /* start_find */ + case 0x041A: /* stop_find */ + case 0x041B: /* update_ie */ + case 0x041C: /* map_link */ + WARN_ON(wsm_arg != NULL); + ret = wsm_generic_confirm(priv, wsm_arg, &wsm_buf); + if (ret) { + wiphy_warn(priv->hw->wiphy, + "wsm_generic_confirm failed for request 0x%04x.\n", + id & ~0x0400); + + /* often 0x407 and 0x410 occur, this means we're dead.. */ + if (priv->join_status >= CW1200_JOIN_STATUS_JOINING) { + wsm_lock_tx(priv); + if (queue_work(priv->workqueue, &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + } + } + break; + default: + wiphy_warn(priv->hw->wiphy, + "Unrecognized confirmation 0x%04x\n", + id & ~0x0400); + } + + spin_lock(&priv->wsm_cmd.lock); + priv->wsm_cmd.ret = ret; + priv->wsm_cmd.done = 1; + spin_unlock(&priv->wsm_cmd.lock); + + ret = 0; /* Error response from device should ne stop BH. */ + + wake_up(&priv->wsm_cmd_wq); + } else if (id & 0x0800) { + switch (id) { + case WSM_STARTUP_IND_ID: + ret = wsm_startup_indication(priv, &wsm_buf); + break; + case WSM_RECEIVE_IND_ID: + ret = wsm_receive_indication(priv, link_id, + &wsm_buf, skb_p); + break; + case 0x0805: + ret = wsm_event_indication(priv, &wsm_buf); + break; + case WSM_SCAN_COMPLETE_IND_ID: + ret = wsm_scan_complete_indication(priv, &wsm_buf); + break; + case 0x0808: + ret = wsm_ba_timeout_indication(priv, &wsm_buf); + break; + case 0x0809: + ret = wsm_set_pm_indication(priv, &wsm_buf); + break; + case 0x080A: + ret = wsm_channel_switch_indication(priv, &wsm_buf); + break; + case 0x080B: + ret = wsm_find_complete_indication(priv, &wsm_buf); + break; + case 0x080C: + ret = wsm_suspend_resume_indication(priv, + link_id, &wsm_buf); + break; + case 0x080F: + ret = wsm_join_complete_indication(priv, &wsm_buf); + break; + default: + pr_warn("Unrecognised WSM ID %04x\n", id); + } + } else { + WARN_ON(1); + ret = -EINVAL; + } +out: + return ret; +} + +static bool wsm_handle_tx_data(struct cw1200_common *priv, + struct wsm_tx *wsm, + const struct ieee80211_tx_info *tx_info, + const struct cw1200_txpriv *txpriv, + struct cw1200_queue *queue) +{ + bool handled = false; + const struct ieee80211_hdr *frame = + (struct ieee80211_hdr *)&((u8 *)wsm)[txpriv->offset]; + __le16 fctl = frame->frame_control; + enum { + do_probe, + do_drop, + do_wep, + do_tx, + } action = do_tx; + + switch (priv->mode) { + case NL80211_IFTYPE_STATION: + if (priv->join_status == CW1200_JOIN_STATUS_MONITOR) + action = do_tx; + else if (priv->join_status < CW1200_JOIN_STATUS_PRE_STA) + action = do_drop; + break; + case NL80211_IFTYPE_AP: + if (!priv->join_status) { + action = do_drop; + } else if (!(BIT(txpriv->raw_link_id) & + (BIT(0) | priv->link_id_map))) { + wiphy_warn(priv->hw->wiphy, + "A frame with expired link id is dropped.\n"); + action = do_drop; + } + if (cw1200_queue_get_generation(wsm->packet_id) > + CW1200_MAX_REQUEUE_ATTEMPTS) { + /* HACK!!! WSM324 firmware has tendency to requeue + * multicast frames in a loop, causing performance + * drop and high power consumption of the driver. + * In this situation it is better just to drop + * the problematic frame. + */ + wiphy_warn(priv->hw->wiphy, + "Too many attempts to requeue a frame; dropped.\n"); + action = do_drop; + } + break; + case NL80211_IFTYPE_ADHOC: + if (priv->join_status != CW1200_JOIN_STATUS_IBSS) + action = do_drop; + break; + case NL80211_IFTYPE_MESH_POINT: + action = do_tx; /* TODO: Test me! */ + break; + case NL80211_IFTYPE_MONITOR: + default: + action = do_drop; + break; + } + + if (action == do_tx) { + if (ieee80211_is_nullfunc(fctl)) { + spin_lock(&priv->bss_loss_lock); + if (priv->bss_loss_state) { + priv->bss_loss_confirm_id = wsm->packet_id; + wsm->queue_id = WSM_QUEUE_VOICE; + } + spin_unlock(&priv->bss_loss_lock); + } else if (ieee80211_is_probe_req(fctl)) { + action = do_probe; + } else if (ieee80211_is_deauth(fctl) && + priv->mode != NL80211_IFTYPE_AP) { + pr_debug("[WSM] Issue unjoin command due to tx deauth.\n"); + wsm_lock_tx_async(priv); + if (queue_work(priv->workqueue, + &priv->unjoin_work) <= 0) + wsm_unlock_tx(priv); + } else if (ieee80211_has_protected(fctl) && + tx_info->control.hw_key && + tx_info->control.hw_key->keyidx != priv->wep_default_key_id && + (tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_WEP40 || + tx_info->control.hw_key->cipher == WLAN_CIPHER_SUITE_WEP104)) { + action = do_wep; + } + } + + switch (action) { + case do_probe: + /* An interesting FW "feature". Device filters probe responses. + * The easiest way to get it back is to convert + * probe request into WSM start_scan command. + */ + pr_debug("[WSM] Convert probe request to scan.\n"); + wsm_lock_tx_async(priv); + priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); + if (queue_delayed_work(priv->workqueue, + &priv->scan.probe_work, 0) <= 0) + wsm_unlock_tx(priv); + handled = true; + break; + case do_drop: + pr_debug("[WSM] Drop frame (0x%.4X).\n", fctl); + BUG_ON(cw1200_queue_remove(queue, + __le32_to_cpu(wsm->packet_id))); + handled = true; + break; + case do_wep: + pr_debug("[WSM] Issue set_default_wep_key.\n"); + wsm_lock_tx_async(priv); + priv->wep_default_key_id = tx_info->control.hw_key->keyidx; + priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); + if (queue_work(priv->workqueue, &priv->wep_key_work) <= 0) + wsm_unlock_tx(priv); + handled = true; + break; + case do_tx: + pr_debug("[WSM] Transmit frame.\n"); + break; + default: + /* Do nothing */ + break; + } + return handled; +} + +static int cw1200_get_prio_queue(struct cw1200_common *priv, + u32 link_id_map, int *total) +{ + static const int urgent = BIT(CW1200_LINK_ID_AFTER_DTIM) | + BIT(CW1200_LINK_ID_UAPSD); + struct wsm_edca_queue_params *edca; + unsigned score, best = -1; + int winner = -1; + int queued; + int i; + + /* search for a winner using edca params */ + for (i = 0; i < 4; ++i) { + queued = cw1200_queue_get_num_queued(&priv->tx_queue[i], + link_id_map); + if (!queued) + continue; + *total += queued; + edca = &priv->edca.params[i]; + score = ((edca->aifns + edca->cwmin) << 16) + + ((edca->cwmax - edca->cwmin) * + (get_random_int() & 0xFFFF)); + if (score < best && (winner < 0 || i != 3)) { + best = score; + winner = i; + } + } + + /* override winner if bursting */ + if (winner >= 0 && priv->tx_burst_idx >= 0 && + winner != priv->tx_burst_idx && + !cw1200_queue_get_num_queued( + &priv->tx_queue[winner], + link_id_map & urgent) && + cw1200_queue_get_num_queued( + &priv->tx_queue[priv->tx_burst_idx], + link_id_map)) + winner = priv->tx_burst_idx; + + return winner; +} + +static int wsm_get_tx_queue_and_mask(struct cw1200_common *priv, + struct cw1200_queue **queue_p, + u32 *tx_allowed_mask_p, + bool *more) +{ + int idx; + u32 tx_allowed_mask; + int total = 0; + + /* Search for a queue with multicast frames buffered */ + if (priv->tx_multicast) { + tx_allowed_mask = BIT(CW1200_LINK_ID_AFTER_DTIM); + idx = cw1200_get_prio_queue(priv, + tx_allowed_mask, &total); + if (idx >= 0) { + *more = total > 1; + goto found; + } + } + + /* Search for unicast traffic */ + tx_allowed_mask = ~priv->sta_asleep_mask; + tx_allowed_mask |= BIT(CW1200_LINK_ID_UAPSD); + if (priv->sta_asleep_mask) { + tx_allowed_mask |= priv->pspoll_mask; + tx_allowed_mask &= ~BIT(CW1200_LINK_ID_AFTER_DTIM); + } else { + tx_allowed_mask |= BIT(CW1200_LINK_ID_AFTER_DTIM); + } + idx = cw1200_get_prio_queue(priv, + tx_allowed_mask, &total); + if (idx < 0) + return -ENOENT; + +found: + *queue_p = &priv->tx_queue[idx]; + *tx_allowed_mask_p = tx_allowed_mask; + return 0; +} + +int wsm_get_tx(struct cw1200_common *priv, u8 **data, + size_t *tx_len, int *burst) +{ + struct wsm_tx *wsm = NULL; + struct ieee80211_tx_info *tx_info; + struct cw1200_queue *queue = NULL; + int queue_num; + u32 tx_allowed_mask = 0; + const struct cw1200_txpriv *txpriv = NULL; + int count = 0; + + /* More is used only for broadcasts. */ + bool more = false; + +#ifdef CONFIG_CW1200_ITP + count = cw1200_itp_get_tx(priv, data, tx_len, burst); + if (count) + return count; +#endif + + if (priv->wsm_cmd.ptr) { /* CMD request */ + ++count; + spin_lock(&priv->wsm_cmd.lock); + BUG_ON(!priv->wsm_cmd.ptr); + *data = priv->wsm_cmd.ptr; + *tx_len = priv->wsm_cmd.len; + *burst = 1; + spin_unlock(&priv->wsm_cmd.lock); + } else { + for (;;) { + int ret; + + if (atomic_add_return(0, &priv->tx_lock)) + break; + + spin_lock_bh(&priv->ps_state_lock); + + ret = wsm_get_tx_queue_and_mask(priv, &queue, + &tx_allowed_mask, &more); + queue_num = queue - priv->tx_queue; + + if (priv->buffered_multicasts && + (ret || !more) && + (priv->tx_multicast || !priv->sta_asleep_mask)) { + priv->buffered_multicasts = false; + if (priv->tx_multicast) { + priv->tx_multicast = false; + queue_work(priv->workqueue, + &priv->multicast_stop_work); + } + } + + spin_unlock_bh(&priv->ps_state_lock); + + if (ret) + break; + + if (cw1200_queue_get(queue, + tx_allowed_mask, + &wsm, &tx_info, &txpriv)) + continue; + + if (wsm_handle_tx_data(priv, wsm, + tx_info, txpriv, queue)) + continue; /* Handled by WSM */ + + wsm->hdr.id &= __cpu_to_le16( + ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX)); + wsm->hdr.id |= cpu_to_le16( + WSM_TX_LINK_ID(txpriv->raw_link_id)); + priv->pspoll_mask &= ~BIT(txpriv->raw_link_id); + + *data = (u8 *)wsm; + *tx_len = __le16_to_cpu(wsm->hdr.len); + + /* allow bursting if txop is set */ + if (priv->edca.params[queue_num].txop_limit) + *burst = min(*burst, + (int)cw1200_queue_get_num_queued(queue, tx_allowed_mask) + 1); + else + *burst = 1; + + /* store index of bursting queue */ + if (*burst > 1) + priv->tx_burst_idx = queue_num; + else + priv->tx_burst_idx = -1; + + if (more) { + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *) + &((u8 *)wsm)[txpriv->offset]; + /* more buffered multicast/broadcast frames + * ==> set MoreData flag in IEEE 802.11 header + * to inform PS STAs + */ + hdr->frame_control |= + cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } + + pr_debug("[WSM] >>> 0x%.4X (%zu) %p %c\n", + 0x0004, *tx_len, *data, + wsm->more ? 'M' : ' '); + ++count; + break; + } + } + + return count; +} + +void wsm_txed(struct cw1200_common *priv, u8 *data) +{ + if (data == priv->wsm_cmd.ptr) { + spin_lock(&priv->wsm_cmd.lock); + priv->wsm_cmd.ptr = NULL; + spin_unlock(&priv->wsm_cmd.lock); + } +} + +/* ******************************************************************** */ +/* WSM buffer */ + +void wsm_buf_init(struct wsm_buf *buf) +{ + BUG_ON(buf->begin); + buf->begin = kmalloc(FWLOAD_BLOCK_SIZE, GFP_KERNEL | GFP_DMA); + buf->end = buf->begin ? &buf->begin[FWLOAD_BLOCK_SIZE] : buf->begin; + wsm_buf_reset(buf); +} + +void wsm_buf_deinit(struct wsm_buf *buf) +{ + kfree(buf->begin); + buf->begin = buf->data = buf->end = NULL; +} + +static void wsm_buf_reset(struct wsm_buf *buf) +{ + if (buf->begin) { + buf->data = &buf->begin[4]; + *(u32 *)buf->begin = 0; + } else { + buf->data = buf->begin; + } +} + +static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size) +{ + size_t pos = buf->data - buf->begin; + size_t size = pos + extra_size; + + size = round_up(size, FWLOAD_BLOCK_SIZE); + + buf->begin = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA); + if (buf->begin) { + buf->data = &buf->begin[pos]; + buf->end = &buf->begin[size]; + return 0; + } else { + buf->end = buf->data = buf->begin; + return -ENOMEM; + } +} diff --git a/drivers/net/wireless/cw1200/wsm.h b/drivers/net/wireless/cw1200/wsm.h new file mode 100644 index 000000000000..8d902d6a7dc4 --- /dev/null +++ b/drivers/net/wireless/cw1200/wsm.h @@ -0,0 +1,1879 @@ +/* + * WSM host interface (HI) interface for ST-Ericsson CW1200 mac80211 drivers + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * Based on CW1200 UMAC WSM API, which is + * Copyright (C) ST-Ericsson SA 2010 + * Author: Stewart Mathers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_WSM_H_INCLUDED +#define CW1200_WSM_H_INCLUDED + +#include + +struct cw1200_common; + +/* Bands */ +/* Radio band 2.412 -2.484 GHz. */ +#define WSM_PHY_BAND_2_4G (0) + +/* Radio band 4.9375-5.8250 GHz. */ +#define WSM_PHY_BAND_5G (1) + +/* Transmit rates */ +/* 1 Mbps ERP-DSSS */ +#define WSM_TRANSMIT_RATE_1 (0) + +/* 2 Mbps ERP-DSSS */ +#define WSM_TRANSMIT_RATE_2 (1) + +/* 5.5 Mbps ERP-CCK */ +#define WSM_TRANSMIT_RATE_5 (2) + +/* 11 Mbps ERP-CCK */ +#define WSM_TRANSMIT_RATE_11 (3) + +/* 22 Mbps ERP-PBCC (Not supported) */ +/* #define WSM_TRANSMIT_RATE_22 (4) */ + +/* 33 Mbps ERP-PBCC (Not supported) */ +/* #define WSM_TRANSMIT_RATE_33 (5) */ + +/* 6 Mbps (3 Mbps) ERP-OFDM, BPSK coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_6 (6) + +/* 9 Mbps (4.5 Mbps) ERP-OFDM, BPSK coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_9 (7) + +/* 12 Mbps (6 Mbps) ERP-OFDM, QPSK coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_12 (8) + +/* 18 Mbps (9 Mbps) ERP-OFDM, QPSK coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_18 (9) + +/* 24 Mbps (12 Mbps) ERP-OFDM, 16QAM coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_24 (10) + +/* 36 Mbps (18 Mbps) ERP-OFDM, 16QAM coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_36 (11) + +/* 48 Mbps (24 Mbps) ERP-OFDM, 64QAM coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_48 (12) + +/* 54 Mbps (27 Mbps) ERP-OFDM, 64QAM coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_54 (13) + +/* 6.5 Mbps HT-OFDM, BPSK coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_HT_6 (14) + +/* 13 Mbps HT-OFDM, QPSK coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_HT_13 (15) + +/* 19.5 Mbps HT-OFDM, QPSK coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_HT_19 (16) + +/* 26 Mbps HT-OFDM, 16QAM coding rate 1/2 */ +#define WSM_TRANSMIT_RATE_HT_26 (17) + +/* 39 Mbps HT-OFDM, 16QAM coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_HT_39 (18) + +/* 52 Mbps HT-OFDM, 64QAM coding rate 2/3 */ +#define WSM_TRANSMIT_RATE_HT_52 (19) + +/* 58.5 Mbps HT-OFDM, 64QAM coding rate 3/4 */ +#define WSM_TRANSMIT_RATE_HT_58 (20) + +/* 65 Mbps HT-OFDM, 64QAM coding rate 5/6 */ +#define WSM_TRANSMIT_RATE_HT_65 (21) + +/* Scan types */ +/* Foreground scan */ +#define WSM_SCAN_TYPE_FOREGROUND (0) + +/* Background scan */ +#define WSM_SCAN_TYPE_BACKGROUND (1) + +/* Auto scan */ +#define WSM_SCAN_TYPE_AUTO (2) + +/* Scan flags */ +/* Forced background scan means if the station cannot */ +/* enter the power-save mode, it shall force to perform a */ +/* background scan. Only valid when ScanType is */ +/* background scan. */ +#define WSM_SCAN_FLAG_FORCE_BACKGROUND (BIT(0)) + +/* The WLAN device scans one channel at a time so */ +/* that disturbance to the data traffic is minimized. */ +#define WSM_SCAN_FLAG_SPLIT_METHOD (BIT(1)) + +/* Preamble Type. Long if not set. */ +#define WSM_SCAN_FLAG_SHORT_PREAMBLE (BIT(2)) + +/* 11n Tx Mode. Mixed if not set. */ +#define WSM_SCAN_FLAG_11N_GREENFIELD (BIT(3)) + +/* Scan constraints */ +/* Maximum number of channels to be scanned. */ +#define WSM_SCAN_MAX_NUM_OF_CHANNELS (48) + +/* The maximum number of SSIDs that the device can scan for. */ +#define WSM_SCAN_MAX_NUM_OF_SSIDS (2) + +/* Power management modes */ +/* 802.11 Active mode */ +#define WSM_PSM_ACTIVE (0) + +/* 802.11 PS mode */ +#define WSM_PSM_PS BIT(0) + +/* Fast Power Save bit */ +#define WSM_PSM_FAST_PS_FLAG BIT(7) + +/* Dynamic aka Fast power save */ +#define WSM_PSM_FAST_PS (BIT(0) | BIT(7)) + +/* Undetermined */ +/* Note : Undetermined status is reported when the */ +/* NULL data frame used to advertise the PM mode to */ +/* the AP at Pre or Post Background Scan is not Acknowledged */ +#define WSM_PSM_UNKNOWN BIT(1) + +/* Queue IDs */ +/* best effort/legacy */ +#define WSM_QUEUE_BEST_EFFORT (0) + +/* background */ +#define WSM_QUEUE_BACKGROUND (1) + +/* video */ +#define WSM_QUEUE_VIDEO (2) + +/* voice */ +#define WSM_QUEUE_VOICE (3) + +/* HT TX parameters */ +/* Non-HT */ +#define WSM_HT_TX_NON_HT (0) + +/* Mixed format */ +#define WSM_HT_TX_MIXED (1) + +/* Greenfield format */ +#define WSM_HT_TX_GREENFIELD (2) + +/* STBC allowed */ +#define WSM_HT_TX_STBC (BIT(7)) + +/* EPTA prioirty flags for BT Coex */ +/* default epta priority */ +#define WSM_EPTA_PRIORITY_DEFAULT 4 +/* use for normal data */ +#define WSM_EPTA_PRIORITY_DATA 4 +/* use for connect/disconnect/roaming*/ +#define WSM_EPTA_PRIORITY_MGT 5 +/* use for action frames */ +#define WSM_EPTA_PRIORITY_ACTION 5 +/* use for AC_VI data */ +#define WSM_EPTA_PRIORITY_VIDEO 5 +/* use for AC_VO data */ +#define WSM_EPTA_PRIORITY_VOICE 6 +/* use for EAPOL exchange */ +#define WSM_EPTA_PRIORITY_EAPOL 7 + +/* TX status */ +/* Frame was sent aggregated */ +/* Only valid for WSM_SUCCESS status. */ +#define WSM_TX_STATUS_AGGREGATION (BIT(0)) + +/* Host should requeue this frame later. */ +/* Valid only when status is WSM_REQUEUE. */ +#define WSM_TX_STATUS_REQUEUE (BIT(1)) + +/* Normal Ack */ +#define WSM_TX_STATUS_NORMAL_ACK (0<<2) + +/* No Ack */ +#define WSM_TX_STATUS_NO_ACK (1<<2) + +/* No explicit acknowledgement */ +#define WSM_TX_STATUS_NO_EXPLICIT_ACK (2<<2) + +/* Block Ack */ +/* Only valid for WSM_SUCCESS status. */ +#define WSM_TX_STATUS_BLOCK_ACK (3<<2) + +/* RX status */ +/* Unencrypted */ +#define WSM_RX_STATUS_UNENCRYPTED (0<<0) + +/* WEP */ +#define WSM_RX_STATUS_WEP (1<<0) + +/* TKIP */ +#define WSM_RX_STATUS_TKIP (2<<0) + +/* AES */ +#define WSM_RX_STATUS_AES (3<<0) + +/* WAPI */ +#define WSM_RX_STATUS_WAPI (4<<0) + +/* Macro to fetch encryption subfield. */ +#define WSM_RX_STATUS_ENCRYPTION(status) ((status) & 0x07) + +/* Frame was part of an aggregation */ +#define WSM_RX_STATUS_AGGREGATE (BIT(3)) + +/* Frame was first in the aggregation */ +#define WSM_RX_STATUS_AGGREGATE_FIRST (BIT(4)) + +/* Frame was last in the aggregation */ +#define WSM_RX_STATUS_AGGREGATE_LAST (BIT(5)) + +/* Indicates a defragmented frame */ +#define WSM_RX_STATUS_DEFRAGMENTED (BIT(6)) + +/* Indicates a Beacon frame */ +#define WSM_RX_STATUS_BEACON (BIT(7)) + +/* Indicates STA bit beacon TIM field */ +#define WSM_RX_STATUS_TIM (BIT(8)) + +/* Indicates Beacon frame's virtual bitmap contains multicast bit */ +#define WSM_RX_STATUS_MULTICAST (BIT(9)) + +/* Indicates frame contains a matching SSID */ +#define WSM_RX_STATUS_MATCHING_SSID (BIT(10)) + +/* Indicates frame contains a matching BSSI */ +#define WSM_RX_STATUS_MATCHING_BSSI (BIT(11)) + +/* Indicates More bit set in Framectl field */ +#define WSM_RX_STATUS_MORE_DATA (BIT(12)) + +/* Indicates frame received during a measurement process */ +#define WSM_RX_STATUS_MEASUREMENT (BIT(13)) + +/* Indicates frame received as an HT packet */ +#define WSM_RX_STATUS_HT (BIT(14)) + +/* Indicates frame received with STBC */ +#define WSM_RX_STATUS_STBC (BIT(15)) + +/* Indicates Address 1 field matches dot11StationId */ +#define WSM_RX_STATUS_ADDRESS1 (BIT(16)) + +/* Indicates Group address present in the Address 1 field */ +#define WSM_RX_STATUS_GROUP (BIT(17)) + +/* Indicates Broadcast address present in the Address 1 field */ +#define WSM_RX_STATUS_BROADCAST (BIT(18)) + +/* Indicates group key used with encrypted frames */ +#define WSM_RX_STATUS_GROUP_KEY (BIT(19)) + +/* Macro to fetch encryption key index. */ +#define WSM_RX_STATUS_KEY_IDX(status) (((status >> 20)) & 0x0F) + +/* Indicates TSF inclusion after 802.11 frame body */ +#define WSM_RX_STATUS_TSF_INCLUDED (BIT(24)) + +/* Frame Control field starts at Frame offset + 2 */ +#define WSM_TX_2BYTES_SHIFT (BIT(7)) + +/* Join mode */ +/* IBSS */ +#define WSM_JOIN_MODE_IBSS (0) + +/* BSS */ +#define WSM_JOIN_MODE_BSS (1) + +/* PLCP preamble type */ +/* For long preamble */ +#define WSM_JOIN_PREAMBLE_LONG (0) + +/* For short preamble (Long for 1Mbps) */ +#define WSM_JOIN_PREAMBLE_SHORT (1) + +/* For short preamble (Long for 1 and 2Mbps) */ +#define WSM_JOIN_PREAMBLE_SHORT_2 (2) + +/* Join flags */ +/* Unsynchronized */ +#define WSM_JOIN_FLAGS_UNSYNCRONIZED BIT(0) +/* The BSS owner is a P2P GO */ +#define WSM_JOIN_FLAGS_P2P_GO BIT(1) +/* Force to join BSS with the BSSID and the + * SSID specified without waiting for beacons. The + * ProbeForJoin parameter is ignored. */ +#define WSM_JOIN_FLAGS_FORCE BIT(2) +/* Give probe request/response higher + * priority over the BT traffic */ +#define WSM_JOIN_FLAGS_PRIO BIT(3) +/* Issue immediate join confirmation and use + * join complete to notify about completion */ +#define WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND BIT(5) + +/* Key types */ +#define WSM_KEY_TYPE_WEP_DEFAULT (0) +#define WSM_KEY_TYPE_WEP_PAIRWISE (1) +#define WSM_KEY_TYPE_TKIP_GROUP (2) +#define WSM_KEY_TYPE_TKIP_PAIRWISE (3) +#define WSM_KEY_TYPE_AES_GROUP (4) +#define WSM_KEY_TYPE_AES_PAIRWISE (5) +#define WSM_KEY_TYPE_WAPI_GROUP (6) +#define WSM_KEY_TYPE_WAPI_PAIRWISE (7) + +/* Key indexes */ +#define WSM_KEY_MAX_INDEX (10) + +/* ACK policy */ +#define WSM_ACK_POLICY_NORMAL (0) +#define WSM_ACK_POLICY_NO_ACK (1) + +/* Start modes */ +#define WSM_START_MODE_AP (0) /* Mini AP */ +#define WSM_START_MODE_P2P_GO (1) /* P2P GO */ +#define WSM_START_MODE_P2P_DEV (2) /* P2P device */ + +/* SetAssociationMode MIB flags */ +#define WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE (BIT(0)) +#define WSM_ASSOCIATION_MODE_USE_HT_MODE (BIT(1)) +#define WSM_ASSOCIATION_MODE_USE_BASIC_RATE_SET (BIT(2)) +#define WSM_ASSOCIATION_MODE_USE_MPDU_START_SPACING (BIT(3)) +#define WSM_ASSOCIATION_MODE_SNOOP_ASSOC_FRAMES (BIT(4)) + +/* RcpiRssiThreshold MIB flags */ +#define WSM_RCPI_RSSI_THRESHOLD_ENABLE (BIT(0)) +#define WSM_RCPI_RSSI_USE_RSSI (BIT(1)) +#define WSM_RCPI_RSSI_DONT_USE_UPPER (BIT(2)) +#define WSM_RCPI_RSSI_DONT_USE_LOWER (BIT(3)) + +/* Update-ie constants */ +#define WSM_UPDATE_IE_BEACON (BIT(0)) +#define WSM_UPDATE_IE_PROBE_RESP (BIT(1)) +#define WSM_UPDATE_IE_PROBE_REQ (BIT(2)) + +/* WSM events */ +/* Error */ +#define WSM_EVENT_ERROR (0) + +/* BSS lost */ +#define WSM_EVENT_BSS_LOST (1) + +/* BSS regained */ +#define WSM_EVENT_BSS_REGAINED (2) + +/* Radar detected */ +#define WSM_EVENT_RADAR_DETECTED (3) + +/* RCPI or RSSI threshold triggered */ +#define WSM_EVENT_RCPI_RSSI (4) + +/* BT inactive */ +#define WSM_EVENT_BT_INACTIVE (5) + +/* BT active */ +#define WSM_EVENT_BT_ACTIVE (6) + +/* MIB IDs */ +/* 4.1 dot11StationId */ +#define WSM_MIB_ID_DOT11_STATION_ID 0x0000 + +/* 4.2 dot11MaxtransmitMsduLifeTime */ +#define WSM_MIB_ID_DOT11_MAX_TRANSMIT_LIFTIME 0x0001 + +/* 4.3 dot11MaxReceiveLifeTime */ +#define WSM_MIB_ID_DOT11_MAX_RECEIVE_LIFETIME 0x0002 + +/* 4.4 dot11SlotTime */ +#define WSM_MIB_ID_DOT11_SLOT_TIME 0x0003 + +/* 4.5 dot11GroupAddressesTable */ +#define WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE 0x0004 +#define WSM_MAX_GRP_ADDRTABLE_ENTRIES 8 + +/* 4.6 dot11WepDefaultKeyId */ +#define WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID 0x0005 + +/* 4.7 dot11CurrentTxPowerLevel */ +#define WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL 0x0006 + +/* 4.8 dot11RTSThreshold */ +#define WSM_MIB_ID_DOT11_RTS_THRESHOLD 0x0007 + +/* 4.9 NonErpProtection */ +#define WSM_MIB_ID_NON_ERP_PROTECTION 0x1000 + +/* 4.10 ArpIpAddressesTable */ +#define WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE 0x1001 +#define WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES 1 + +/* 4.11 TemplateFrame */ +#define WSM_MIB_ID_TEMPLATE_FRAME 0x1002 + +/* 4.12 RxFilter */ +#define WSM_MIB_ID_RX_FILTER 0x1003 + +/* 4.13 BeaconFilterTable */ +#define WSM_MIB_ID_BEACON_FILTER_TABLE 0x1004 + +/* 4.14 BeaconFilterEnable */ +#define WSM_MIB_ID_BEACON_FILTER_ENABLE 0x1005 + +/* 4.15 OperationalPowerMode */ +#define WSM_MIB_ID_OPERATIONAL_POWER_MODE 0x1006 + +/* 4.16 BeaconWakeUpPeriod */ +#define WSM_MIB_ID_BEACON_WAKEUP_PERIOD 0x1007 + +/* 4.17 RcpiRssiThreshold */ +#define WSM_MIB_ID_RCPI_RSSI_THRESHOLD 0x1009 + +/* 4.18 StatisticsTable */ +#define WSM_MIB_ID_STATISTICS_TABLE 0x100A + +/* 4.19 IbssPsConfig */ +#define WSM_MIB_ID_IBSS_PS_CONFIG 0x100B + +/* 4.20 CountersTable */ +#define WSM_MIB_ID_COUNTERS_TABLE 0x100C + +/* 4.21 BlockAckPolicy */ +#define WSM_MIB_ID_BLOCK_ACK_POLICY 0x100E + +/* 4.22 OverrideInternalTxRate */ +#define WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE 0x100F + +/* 4.23 SetAssociationMode */ +#define WSM_MIB_ID_SET_ASSOCIATION_MODE 0x1010 + +/* 4.24 UpdateEptaConfigData */ +#define WSM_MIB_ID_UPDATE_EPTA_CONFIG_DATA 0x1011 + +/* 4.25 SelectCcaMethod */ +#define WSM_MIB_ID_SELECT_CCA_METHOD 0x1012 + +/* 4.26 SetUpasdInformation */ +#define WSM_MIB_ID_SET_UAPSD_INFORMATION 0x1013 + +/* 4.27 SetAutoCalibrationMode WBF00004073 */ +#define WSM_MIB_ID_SET_AUTO_CALIBRATION_MODE 0x1015 + +/* 4.28 SetTxRateRetryPolicy */ +#define WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY 0x1016 + +/* 4.29 SetHostMessageTypeFilter */ +#define WSM_MIB_ID_SET_HOST_MSG_TYPE_FILTER 0x1017 + +/* 4.30 P2PFindInfo */ +#define WSM_MIB_ID_P2P_FIND_INFO 0x1018 + +/* 4.31 P2PPsModeInfo */ +#define WSM_MIB_ID_P2P_PS_MODE_INFO 0x1019 + +/* 4.32 SetEtherTypeDataFrameFilter */ +#define WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER 0x101A + +/* 4.33 SetUDPPortDataFrameFilter */ +#define WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER 0x101B + +/* 4.34 SetMagicDataFrameFilter */ +#define WSM_MIB_ID_SET_MAGIC_DATAFRAME_FILTER 0x101C + +/* 4.35 P2PDeviceInfo */ +#define WSM_MIB_ID_P2P_DEVICE_INFO 0x101D + +/* 4.36 SetWCDMABand */ +#define WSM_MIB_ID_SET_WCDMA_BAND 0x101E + +/* 4.37 GroupTxSequenceCounter */ +#define WSM_MIB_ID_GRP_SEQ_COUNTER 0x101F + +/* 4.38 ProtectedMgmtPolicy */ +#define WSM_MIB_ID_PROTECTED_MGMT_POLICY 0x1020 + +/* 4.39 SetHtProtection */ +#define WSM_MIB_ID_SET_HT_PROTECTION 0x1021 + +/* 4.40 GPIO Command */ +#define WSM_MIB_ID_GPIO_COMMAND 0x1022 + +/* 4.41 TSF Counter Value */ +#define WSM_MIB_ID_TSF_COUNTER 0x1023 + +/* Test Purposes Only */ +#define WSM_MIB_ID_BLOCK_ACK_INFO 0x100D + +/* 4.42 UseMultiTxConfMessage */ +#define WSM_MIB_USE_MULTI_TX_CONF 0x1024 + +/* 4.43 Keep-alive period */ +#define WSM_MIB_ID_KEEP_ALIVE_PERIOD 0x1025 + +/* 4.44 Disable BSSID filter */ +#define WSM_MIB_ID_DISABLE_BSSID_FILTER 0x1026 + +/* Frame template types */ +#define WSM_FRAME_TYPE_PROBE_REQUEST (0) +#define WSM_FRAME_TYPE_BEACON (1) +#define WSM_FRAME_TYPE_NULL (2) +#define WSM_FRAME_TYPE_QOS_NULL (3) +#define WSM_FRAME_TYPE_PS_POLL (4) +#define WSM_FRAME_TYPE_PROBE_RESPONSE (5) + +#define WSM_FRAME_GREENFIELD (0x80) /* See 4.11 */ + +/* Status */ +/* The WSM firmware has completed a request */ +/* successfully. */ +#define WSM_STATUS_SUCCESS (0) + +/* This is a generic failure code if other error codes do */ +/* not apply. */ +#define WSM_STATUS_FAILURE (1) + +/* A request contains one or more invalid parameters. */ +#define WSM_INVALID_PARAMETER (2) + +/* The request cannot perform because the device is in */ +/* an inappropriate mode. */ +#define WSM_ACCESS_DENIED (3) + +/* The frame received includes a decryption error. */ +#define WSM_STATUS_DECRYPTFAILURE (4) + +/* A MIC failure is detected in the received packets. */ +#define WSM_STATUS_MICFAILURE (5) + +/* The transmit request failed due to retry limit being */ +/* exceeded. */ +#define WSM_STATUS_RETRY_EXCEEDED (6) + +/* The transmit request failed due to MSDU life time */ +/* being exceeded. */ +#define WSM_STATUS_TX_LIFETIME_EXCEEDED (7) + +/* The link to the AP is lost. */ +#define WSM_STATUS_LINK_LOST (8) + +/* No key was found for the encrypted frame */ +#define WSM_STATUS_NO_KEY_FOUND (9) + +/* Jammer was detected when transmitting this frame */ +#define WSM_STATUS_JAMMER_DETECTED (10) + +/* The message should be requeued later. */ +/* This is applicable only to Transmit */ +#define WSM_REQUEUE (11) + +/* Advanced filtering options */ +#define WSM_MAX_FILTER_ELEMENTS (4) + +#define WSM_FILTER_ACTION_IGNORE (0) +#define WSM_FILTER_ACTION_FILTER_IN (1) +#define WSM_FILTER_ACTION_FILTER_OUT (2) + +#define WSM_FILTER_PORT_TYPE_DST (0) +#define WSM_FILTER_PORT_TYPE_SRC (1) + +/* Actual header of WSM messages */ +struct wsm_hdr { + __le16 len; + __le16 id; +}; + +#define WSM_TX_SEQ_MAX (7) +#define WSM_TX_SEQ(seq) \ + ((seq & WSM_TX_SEQ_MAX) << 13) +#define WSM_TX_LINK_ID_MAX (0x0F) +#define WSM_TX_LINK_ID(link_id) \ + ((link_id & WSM_TX_LINK_ID_MAX) << 6) + +#define MAX_BEACON_SKIP_TIME_MS 1000 + +#define WSM_CMD_LAST_CHANCE_TIMEOUT (HZ * 3 / 2) + +/* ******************************************************************** */ +/* WSM capability */ + +#define WSM_STARTUP_IND_ID 0x0801 + +struct wsm_startup_ind { + u16 input_buffers; + u16 input_buffer_size; + u16 status; + u16 hw_id; + u16 hw_subid; + u16 fw_cap; + u16 fw_type; + u16 fw_api; + u16 fw_build; + u16 fw_ver; + char fw_label[128]; + u32 config[4]; +}; + +/* ******************************************************************** */ +/* WSM commands */ + +/* 3.1 */ +#define WSM_CONFIGURATION_REQ_ID 0x0009 +#define WSM_CONFIGURATION_RESP_ID 0x0409 + +struct wsm_tx_power_range { + int min_power_level; + int max_power_level; + u32 stepping; +}; + +struct wsm_configuration { + /* [in] */ u32 dot11MaxTransmitMsduLifeTime; + /* [in] */ u32 dot11MaxReceiveLifeTime; + /* [in] */ u32 dot11RtsThreshold; + /* [in, out] */ u8 *dot11StationId; + /* [in] */ const void *dpdData; + /* [in] */ size_t dpdData_size; + /* [out] */ u8 dot11FrequencyBandsSupported; + /* [out] */ u32 supportedRateMask; + /* [out] */ struct wsm_tx_power_range txPowerRange[2]; +}; + +int wsm_configuration(struct cw1200_common *priv, + struct wsm_configuration *arg); + +/* 3.3 */ +#define WSM_RESET_REQ_ID 0x000A +#define WSM_RESET_RESP_ID 0x040A +struct wsm_reset { + /* [in] */ int link_id; + /* [in] */ bool reset_statistics; +}; + +int wsm_reset(struct cw1200_common *priv, const struct wsm_reset *arg); + +/* 3.5 */ +#define WSM_READ_MIB_REQ_ID 0x0005 +#define WSM_READ_MIB_RESP_ID 0x0405 +int wsm_read_mib(struct cw1200_common *priv, u16 mib_id, void *buf, + size_t buf_size); + +/* 3.7 */ +#define WSM_WRITE_MIB_REQ_ID 0x0006 +#define WSM_WRITE_MIB_RESP_ID 0x0406 +int wsm_write_mib(struct cw1200_common *priv, u16 mib_id, void *buf, + size_t buf_size); + +/* 3.9 */ +#define WSM_START_SCAN_REQ_ID 0x0007 +#define WSM_START_SCAN_RESP_ID 0x0407 + +struct wsm_ssid { + u8 ssid[32]; + u32 length; +}; + +struct wsm_scan_ch { + u16 number; + u32 min_chan_time; + u32 max_chan_time; + u32 tx_power_level; +}; + +struct wsm_scan { + /* WSM_PHY_BAND_... */ + u8 band; + + /* WSM_SCAN_TYPE_... */ + u8 type; + + /* WSM_SCAN_FLAG_... */ + u8 flags; + + /* WSM_TRANSMIT_RATE_... */ + u8 max_tx_rate; + + /* Interval period in TUs that the device shall the re- */ + /* execute the requested scan. Max value supported by the device */ + /* is 256s. */ + u32 auto_scan_interval; + + /* Number of probe requests (per SSID) sent to one (1) */ + /* channel. Zero (0) means that none is send, which */ + /* means that a passive scan is to be done. Value */ + /* greater than zero (0) means that an active scan is to */ + /* be done. */ + u32 num_probes; + + /* Number of channels to be scanned. */ + /* Maximum value is WSM_SCAN_MAX_NUM_OF_CHANNELS. */ + u8 num_channels; + + /* Number of SSID provided in the scan command (this */ + /* is zero (0) in broadcast scan) */ + /* The maximum number of SSIDs is WSM_SCAN_MAX_NUM_OF_SSIDS. */ + u8 num_ssids; + + /* The delay time (in microseconds) period */ + /* before sending a probe-request. */ + u8 probe_delay; + + /* SSIDs to be scanned [numOfSSIDs]; */ + struct wsm_ssid *ssids; + + /* Channels to be scanned [numOfChannels]; */ + struct wsm_scan_ch *ch; +}; + +int wsm_scan(struct cw1200_common *priv, const struct wsm_scan *arg); + +/* 3.11 */ +#define WSM_STOP_SCAN_REQ_ID 0x0008 +#define WSM_STOP_SCAN_RESP_ID 0x0408 +int wsm_stop_scan(struct cw1200_common *priv); + +/* 3.13 */ +#define WSM_SCAN_COMPLETE_IND_ID 0x0806 +struct wsm_scan_complete { + /* WSM_STATUS_... */ + u32 status; + + /* WSM_PSM_... */ + u8 psm; + + /* Number of channels that the scan operation completed. */ + u8 num_channels; +}; + +/* 3.14 */ +#define WSM_TX_CONFIRM_IND_ID 0x0404 +#define WSM_MULTI_TX_CONFIRM_ID 0x041E + +struct wsm_tx_confirm { + /* Packet identifier used in wsm_tx. */ + u32 packet_id; + + /* WSM_STATUS_... */ + u32 status; + + /* WSM_TRANSMIT_RATE_... */ + u8 tx_rate; + + /* The number of times the frame was transmitted */ + /* without receiving an acknowledgement. */ + u8 ack_failures; + + /* WSM_TX_STATUS_... */ + u16 flags; + + /* The total time in microseconds that the frame spent in */ + /* the WLAN device before transmission as completed. */ + u32 media_delay; + + /* The total time in microseconds that the frame spent in */ + /* the WLAN device before transmission was started. */ + u32 tx_queue_delay; +}; + +/* 3.15 */ +typedef void (*wsm_tx_confirm_cb) (struct cw1200_common *priv, + struct wsm_tx_confirm *arg); + +/* Note that ideology of wsm_tx struct is different against the rest of + * WSM API. wsm_hdr is /not/ a caller-adapted struct to be used as an input + * argument for WSM call, but a prepared bytestream to be sent to firmware. + * It is filled partly in cw1200_tx, partly in low-level WSM code. + * Please pay attention once again: ideology is different. + * + * Legend: + * - [in]: cw1200_tx must fill this field. + * - [wsm]: the field is filled by low-level WSM. + */ +struct wsm_tx { + /* common WSM header */ + struct wsm_hdr hdr; + + /* Packet identifier that meant to be used in completion. */ + __le32 packet_id; + + /* WSM_TRANSMIT_RATE_... */ + u8 max_tx_rate; + + /* WSM_QUEUE_... */ + u8 queue_id; + + /* True: another packet is pending on the host for transmission. */ + u8 more; + + /* Bit 0 = 0 - Start expiry time from first Tx attempt (default) */ + /* Bit 0 = 1 - Start expiry time from receipt of Tx Request */ + /* Bits 3:1 - PTA Priority */ + /* Bits 6:4 - Tx Rate Retry Policy */ + /* Bit 7 - Reserved */ + u8 flags; + + /* Should be 0. */ + __le32 reserved; + + /* The elapsed time in TUs, after the initial transmission */ + /* of an MSDU, after which further attempts to transmit */ + /* the MSDU shall be terminated. Overrides the global */ + /* dot11MaxTransmitMsduLifeTime setting [optional] */ + /* Device will set the default value if this is 0. */ + __le32 expire_time; + + /* WSM_HT_TX_... */ + __le32 ht_tx_parameters; +}; + +/* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */ +#define WSM_TX_EXTRA_HEADROOM (28) + +/* 3.16 */ +#define WSM_RECEIVE_IND_ID 0x0804 + +struct wsm_rx { + /* WSM_STATUS_... */ + __le32 status; + + /* Specifies the channel of the received packet. */ + __le16 channel_number; + + /* WSM_TRANSMIT_RATE_... */ + u8 rx_rate; + + /* This value is expressed in signed Q8.0 format for */ + /* RSSI and unsigned Q7.1 format for RCPI. */ + u8 rcpi_rssi; + + /* WSM_RX_STATUS_... */ + __le32 flags; + + /* Payload */ + u8 data[0]; +} __packed; + +/* = sizeof(generic hi hdr) + sizeof(wsm hdr) */ +#define WSM_RX_EXTRA_HEADROOM (16) + +typedef void (*wsm_rx_cb) (struct cw1200_common *priv, struct wsm_rx *arg, + struct sk_buff **skb_p); + +/* 3.17 */ +struct wsm_event { + /* WSM_STATUS_... */ + /* [out] */ u32 id; + + /* Indication parameters. */ + /* For error indication, this shall be a 32-bit WSM status. */ + /* For RCPI or RSSI indication, this should be an 8-bit */ + /* RCPI or RSSI value. */ + /* [out] */ u32 data; +}; + +struct cw1200_wsm_event { + struct list_head link; + struct wsm_event evt; +}; + +/* 3.18 - 3.22 */ +/* Measurement. Skipped for now. Irrelevent. */ + +typedef void (*wsm_event_cb) (struct cw1200_common *priv, + struct wsm_event *arg); + +/* 3.23 */ +#define WSM_JOIN_REQ_ID 0x000B +#define WSM_JOIN_RESP_ID 0x040B + +struct wsm_join { + /* WSM_JOIN_MODE_... */ + u8 mode; + + /* WSM_PHY_BAND_... */ + u8 band; + + /* Specifies the channel number to join. The channel */ + /* number will be mapped to an actual frequency */ + /* according to the band */ + u16 channel_number; + + /* Specifies the BSSID of the BSS or IBSS to be joined */ + /* or the IBSS to be started. */ + u8 bssid[6]; + + /* ATIM window of IBSS */ + /* When ATIM window is zero the initiated IBSS does */ + /* not support power saving. */ + u16 atim_window; + + /* WSM_JOIN_PREAMBLE_... */ + u8 preamble_type; + + /* Specifies if a probe request should be send with the */ + /* specified SSID when joining to the network. */ + u8 probe_for_join; + + /* DTIM Period (In multiples of beacon interval) */ + u8 dtim_period; + + /* WSM_JOIN_FLAGS_... */ + u8 flags; + + /* Length of the SSID */ + u32 ssid_len; + + /* Specifies the SSID of the IBSS to join or start */ + u8 ssid[32]; + + /* Specifies the time between TBTTs in TUs */ + u32 beacon_interval; + + /* A bit mask that defines the BSS basic rate set. */ + u32 basic_rate_set; +}; + +struct wsm_join_cnf { + u32 status; + + /* Minimum transmission power level in units of 0.1dBm */ + u32 min_power_level; + + /* Maximum transmission power level in units of 0.1dBm */ + u32 max_power_level; +}; + +int wsm_join(struct cw1200_common *priv, struct wsm_join *arg); + +/* 3.24 */ +struct wsm_join_complete { + /* WSM_STATUS_... */ + u32 status; +}; + +/* 3.25 */ +#define WSM_SET_PM_REQ_ID 0x0010 +#define WSM_SET_PM_RESP_ID 0x0410 +struct wsm_set_pm { + /* WSM_PSM_... */ + u8 mode; + + /* in unit of 500us; 0 to use default */ + u8 fast_psm_idle_period; + + /* in unit of 500us; 0 to use default */ + u8 ap_psm_change_period; + + /* in unit of 500us; 0 to disable auto-pspoll */ + u8 min_auto_pspoll_period; +}; + +int wsm_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg); + +/* 3.27 */ +struct wsm_set_pm_complete { + u8 psm; /* WSM_PSM_... */ +}; + +/* 3.28 */ +#define WSM_SET_BSS_PARAMS_REQ_ID 0x0011 +#define WSM_SET_BSS_PARAMS_RESP_ID 0x0411 +struct wsm_set_bss_params { + /* This resets the beacon loss counters only */ + u8 reset_beacon_loss; + + /* The number of lost consecutive beacons after which */ + /* the WLAN device should indicate the BSS-Lost event */ + /* to the WLAN host driver. */ + u8 beacon_lost_count; + + /* The AID received during the association process. */ + u16 aid; + + /* The operational rate set mask */ + u32 operational_rate_set; +}; + +int wsm_set_bss_params(struct cw1200_common *priv, + const struct wsm_set_bss_params *arg); + +/* 3.30 */ +#define WSM_ADD_KEY_REQ_ID 0x000C +#define WSM_ADD_KEY_RESP_ID 0x040C +struct wsm_add_key { + u8 type; /* WSM_KEY_TYPE_... */ + u8 index; /* Key entry index: 0 -- WSM_KEY_MAX_INDEX */ + u16 reserved; + union { + struct { + u8 peer[6]; /* MAC address of the + * peer station */ + u8 reserved; + u8 keylen; /* Key length in bytes */ + u8 keydata[16]; /* Key data */ + } __packed wep_pairwise; + struct { + u8 keyid; /* Unique per key identifier + * (0..3) */ + u8 keylen; /* Key length in bytes */ + u16 reserved; + u8 keydata[16]; /* Key data */ + } __packed wep_group; + struct { + u8 peer[6]; /* MAC address of the + * peer station */ + u16 reserved; + u8 keydata[16]; /* TKIP key data */ + u8 rx_mic_key[8]; /* Rx MIC key */ + u8 tx_mic_key[8]; /* Tx MIC key */ + } __packed tkip_pairwise; + struct { + u8 keydata[16]; /* TKIP key data */ + u8 rx_mic_key[8]; /* Rx MIC key */ + u8 keyid; /* Key ID */ + u8 reserved[3]; + u8 rx_seqnum[8]; /* Receive Sequence Counter */ + } __packed tkip_group; + struct { + u8 peer[6]; /* MAC address of the + * peer station */ + u16 reserved; + u8 keydata[16]; /* AES key data */ + } __packed aes_pairwise; + struct { + u8 keydata[16]; /* AES key data */ + u8 keyid; /* Key ID */ + u8 reserved[3]; + u8 rx_seqnum[8]; /* Receive Sequence Counter */ + } __packed aes_group; + struct { + u8 peer[6]; /* MAC address of the + * peer station */ + u8 keyid; /* Key ID */ + u8 reserved; + u8 keydata[16]; /* WAPI key data */ + u8 mic_key[16]; /* MIC key data */ + } __packed wapi_pairwise; + struct { + u8 keydata[16]; /* WAPI key data */ + u8 mic_key[16]; /* MIC key data */ + u8 keyid; /* Key ID */ + u8 reserved[3]; + } __packed wapi_group; + } __packed; +} __packed; + +int wsm_add_key(struct cw1200_common *priv, const struct wsm_add_key *arg); + +/* 3.32 */ +#define WSM_REMOVE_KEY_REQ_ID 0x000D +#define WSM_REMOVE_KEY_RESP_ID 0x040D +struct wsm_remove_key { + u8 index; /* Key entry index : 0-10 */ +}; + +int wsm_remove_key(struct cw1200_common *priv, + const struct wsm_remove_key *arg); + +/* 3.34 */ +struct wsm_set_tx_queue_params { + /* WSM_ACK_POLICY_... */ + u8 ackPolicy; + + /* Medium Time of TSPEC (in 32us units) allowed per */ + /* One Second Averaging Period for this queue. */ + u16 allowedMediumTime; + + /* dot11MaxTransmitMsduLifetime to be used for the */ + /* specified queue. */ + u32 maxTransmitLifetime; +}; + +struct wsm_tx_queue_params { + /* NOTE: index is a linux queue id. */ + struct wsm_set_tx_queue_params params[4]; +}; + + +#define WSM_TX_QUEUE_SET(queue_params, queue, ack_policy, allowed_time,\ + max_life_time) \ +do { \ + struct wsm_set_tx_queue_params *p = &(queue_params)->params[queue]; \ + p->ackPolicy = (ack_policy); \ + p->allowedMediumTime = (allowed_time); \ + p->maxTransmitLifetime = (max_life_time); \ +} while (0) + +int wsm_set_tx_queue_params(struct cw1200_common *priv, + const struct wsm_set_tx_queue_params *arg, u8 id); + +/* 3.36 */ +#define WSM_EDCA_PARAMS_REQ_ID 0x0013 +#define WSM_EDCA_PARAMS_RESP_ID 0x0413 +struct wsm_edca_queue_params { + /* CWmin (in slots) for the access class. */ + __le16 cwmin; + + /* CWmax (in slots) for the access class. */ + __le16 cwmax; + + /* AIFS (in slots) for the access class. */ + __le16 aifns; + + /* TX OP Limit (in microseconds) for the access class. */ + __le16 txop_limit; + + /* dot11MaxReceiveLifetime to be used for the specified */ + /* the access class. Overrides the global */ + /* dot11MaxReceiveLifetime value */ + __le32 max_rx_lifetime; +} __packed; + +struct wsm_edca_params { + /* NOTE: index is a linux queue id. */ + struct wsm_edca_queue_params params[4]; + bool uapsd_enable[4]; +}; + +#define TXOP_UNIT 32 +#define WSM_EDCA_SET(__edca, __queue, __aifs, __cw_min, __cw_max, __txop, __lifetime,\ + __uapsd) \ + do { \ + struct wsm_edca_queue_params *p = &(__edca)->params[__queue]; \ + p->cwmin = (__cw_min); \ + p->cwmax = (__cw_max); \ + p->aifns = (__aifs); \ + p->txop_limit = ((__txop) * TXOP_UNIT); \ + p->max_rx_lifetime = (__lifetime); \ + (__edca)->uapsd_enable[__queue] = (__uapsd); \ + } while (0) + +int wsm_set_edca_params(struct cw1200_common *priv, + const struct wsm_edca_params *arg); + +int wsm_set_uapsd_param(struct cw1200_common *priv, + const struct wsm_edca_params *arg); + +/* 3.38 */ +/* Set-System info. Skipped for now. Irrelevent. */ + +/* 3.40 */ +#define WSM_SWITCH_CHANNEL_REQ_ID 0x0016 +#define WSM_SWITCH_CHANNEL_RESP_ID 0x0416 + +struct wsm_switch_channel { + /* 1 - means the STA shall not transmit any further */ + /* frames until the channel switch has completed */ + u8 mode; + + /* Number of TBTTs until channel switch occurs. */ + /* 0 - indicates switch shall occur at any time */ + /* 1 - occurs immediately before the next TBTT */ + u8 switch_count; + + /* The new channel number to switch to. */ + /* Note this is defined as per section 2.7. */ + u16 channel_number; +}; + +int wsm_switch_channel(struct cw1200_common *priv, + const struct wsm_switch_channel *arg); + +typedef void (*wsm_channel_switch_cb) (struct cw1200_common *priv); + +#define WSM_START_REQ_ID 0x0017 +#define WSM_START_RESP_ID 0x0417 + +struct wsm_start { + /* WSM_START_MODE_... */ + /* [in] */ u8 mode; + + /* WSM_PHY_BAND_... */ + /* [in] */ u8 band; + + /* Channel number */ + /* [in] */ u16 channel_number; + + /* Client Traffic window in units of TU */ + /* Valid only when mode == ..._P2P */ + /* [in] */ u32 ct_window; + + /* Interval between two consecutive */ + /* beacon transmissions in TU. */ + /* [in] */ u32 beacon_interval; + + /* DTIM period in terms of beacon intervals */ + /* [in] */ u8 dtim_period; + + /* WSM_JOIN_PREAMBLE_... */ + /* [in] */ u8 preamble; + + /* The delay time (in microseconds) period */ + /* before sending a probe-request. */ + /* [in] */ u8 probe_delay; + + /* Length of the SSID */ + /* [in] */ u8 ssid_len; + + /* SSID of the BSS or P2P_GO to be started now. */ + /* [in] */ u8 ssid[32]; + + /* The basic supported rates for the MiniAP. */ + /* [in] */ u32 basic_rate_set; +}; + +int wsm_start(struct cw1200_common *priv, const struct wsm_start *arg); + +#define WSM_BEACON_TRANSMIT_REQ_ID 0x0018 +#define WSM_BEACON_TRANSMIT_RESP_ID 0x0418 + +struct wsm_beacon_transmit { + /* 1: enable; 0: disable */ + /* [in] */ u8 enable_beaconing; +}; + +int wsm_beacon_transmit(struct cw1200_common *priv, + const struct wsm_beacon_transmit *arg); + +int wsm_start_find(struct cw1200_common *priv); + +int wsm_stop_find(struct cw1200_common *priv); + +typedef void (*wsm_find_complete_cb) (struct cw1200_common *priv, u32 status); + +struct wsm_suspend_resume { + /* See 3.52 */ + /* Link ID */ + /* [out] */ int link_id; + /* Stop sending further Tx requests down to device for this link */ + /* [out] */ bool stop; + /* Transmit multicast Frames */ + /* [out] */ bool multicast; + /* The AC on which Tx to be suspended /resumed. */ + /* This is applicable only for U-APSD */ + /* WSM_QUEUE_... */ + /* [out] */ int queue; +}; + +typedef void (*wsm_suspend_resume_cb) (struct cw1200_common *priv, + struct wsm_suspend_resume *arg); + +/* 3.54 Update-IE request. */ +struct wsm_update_ie { + /* WSM_UPDATE_IE_... */ + /* [in] */ u16 what; + /* [in] */ u16 count; + /* [in] */ u8 *ies; + /* [in] */ size_t length; +}; + +int wsm_update_ie(struct cw1200_common *priv, + const struct wsm_update_ie *arg); + +/* 3.56 */ +struct wsm_map_link { + /* MAC address of the remote device */ + /* [in] */ u8 mac_addr[6]; + /* [in] */ u8 link_id; +}; + +int wsm_map_link(struct cw1200_common *priv, const struct wsm_map_link *arg); + +/* ******************************************************************** */ +/* MIB shortcats */ + +static inline int wsm_set_output_power(struct cw1200_common *priv, + int power_level) +{ + __le32 val = __cpu_to_le32(power_level); + return wsm_write_mib(priv, WSM_MIB_ID_DOT11_CURRENT_TX_POWER_LEVEL, + &val, sizeof(val)); +} + +static inline int wsm_set_beacon_wakeup_period(struct cw1200_common *priv, + unsigned dtim_interval, + unsigned listen_interval) +{ + struct { + u8 numBeaconPeriods; + u8 reserved; + __le16 listenInterval; + } val = { + dtim_interval, 0, __cpu_to_le16(listen_interval) + }; + + if (dtim_interval > 0xFF || listen_interval > 0xFFFF) + return -EINVAL; + else + return wsm_write_mib(priv, WSM_MIB_ID_BEACON_WAKEUP_PERIOD, + &val, sizeof(val)); +} + +struct wsm_rcpi_rssi_threshold { + u8 rssiRcpiMode; /* WSM_RCPI_RSSI_... */ + u8 lowerThreshold; + u8 upperThreshold; + u8 rollingAverageCount; +}; + +static inline int wsm_set_rcpi_rssi_threshold(struct cw1200_common *priv, + struct wsm_rcpi_rssi_threshold *arg) +{ + return wsm_write_mib(priv, WSM_MIB_ID_RCPI_RSSI_THRESHOLD, arg, + sizeof(*arg)); +} + +struct wsm_mib_counters_table { + __le32 plcp_errors; + __le32 fcs_errors; + __le32 tx_packets; + __le32 rx_packets; + __le32 rx_packet_errors; + __le32 rx_decryption_failures; + __le32 rx_mic_failures; + __le32 rx_no_key_failures; + __le32 tx_multicast_frames; + __le32 tx_frames_success; + __le32 tx_frame_failures; + __le32 tx_frames_retried; + __le32 tx_frames_multi_retried; + __le32 rx_frame_duplicates; + __le32 rts_success; + __le32 rts_failures; + __le32 ack_failures; + __le32 rx_multicast_frames; + __le32 rx_frames_success; + __le32 rx_cmac_icv_errors; + __le32 rx_cmac_replays; + __le32 rx_mgmt_ccmp_replays; +} __packed; + +static inline int wsm_get_counters_table(struct cw1200_common *priv, + struct wsm_mib_counters_table *arg) +{ + return wsm_read_mib(priv, WSM_MIB_ID_COUNTERS_TABLE, + arg, sizeof(*arg)); +} + +static inline int wsm_get_station_id(struct cw1200_common *priv, u8 *mac) +{ + return wsm_read_mib(priv, WSM_MIB_ID_DOT11_STATION_ID, mac, ETH_ALEN); +} + +struct wsm_rx_filter { + bool promiscuous; + bool bssid; + bool fcs; + bool probeResponder; +}; + +static inline int wsm_set_rx_filter(struct cw1200_common *priv, + const struct wsm_rx_filter *arg) +{ + __le32 val = 0; + if (arg->promiscuous) + val |= __cpu_to_le32(BIT(0)); + if (arg->bssid) + val |= __cpu_to_le32(BIT(1)); + if (arg->fcs) + val |= __cpu_to_le32(BIT(2)); + if (arg->probeResponder) + val |= __cpu_to_le32(BIT(3)); + return wsm_write_mib(priv, WSM_MIB_ID_RX_FILTER, &val, sizeof(val)); +} + +int wsm_set_probe_responder(struct cw1200_common *priv, bool enable); + +#define WSM_BEACON_FILTER_IE_HAS_CHANGED BIT(0) +#define WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT BIT(1) +#define WSM_BEACON_FILTER_IE_HAS_APPEARED BIT(2) + +struct wsm_beacon_filter_table_entry { + u8 ie_id; + u8 flags; + u8 oui[3]; + u8 match_data[3]; +} __packed; + +struct wsm_mib_beacon_filter_table { + __le32 num; + struct wsm_beacon_filter_table_entry entry[10]; +} __packed; + +static inline int wsm_set_beacon_filter_table(struct cw1200_common *priv, + struct wsm_mib_beacon_filter_table *ft) +{ + size_t size = __le32_to_cpu(ft->num) * + sizeof(struct wsm_beacon_filter_table_entry) + + sizeof(__le32); + + return wsm_write_mib(priv, WSM_MIB_ID_BEACON_FILTER_TABLE, ft, size); +} + +#define WSM_BEACON_FILTER_ENABLE BIT(0) /* Enable/disable beacon filtering */ +#define WSM_BEACON_FILTER_AUTO_ERP BIT(1) /* If 1 FW will handle ERP IE changes internally */ + +struct wsm_beacon_filter_control { + int enabled; + int bcn_count; +}; + +static inline int wsm_beacon_filter_control(struct cw1200_common *priv, + struct wsm_beacon_filter_control *arg) +{ + struct { + __le32 enabled; + __le32 bcn_count; + } val; + val.enabled = __cpu_to_le32(arg->enabled); + val.bcn_count = __cpu_to_le32(arg->bcn_count); + return wsm_write_mib(priv, WSM_MIB_ID_BEACON_FILTER_ENABLE, &val, + sizeof(val)); +} + +enum wsm_power_mode { + wsm_power_mode_active = 0, + wsm_power_mode_doze = 1, + wsm_power_mode_quiescent = 2, +}; + +struct wsm_operational_mode { + enum wsm_power_mode power_mode; + int disable_more_flag_usage; + int perform_ant_diversity; +}; + +static inline int wsm_set_operational_mode(struct cw1200_common *priv, + const struct wsm_operational_mode *arg) +{ + u8 val = arg->power_mode; + if (arg->disable_more_flag_usage) + val |= BIT(4); + if (arg->perform_ant_diversity) + val |= BIT(5); + return wsm_write_mib(priv, WSM_MIB_ID_OPERATIONAL_POWER_MODE, &val, + sizeof(val)); +} + +struct wsm_template_frame { + u8 frame_type; + u8 rate; + struct sk_buff *skb; +}; + +static inline int wsm_set_template_frame(struct cw1200_common *priv, + struct wsm_template_frame *arg) +{ + int ret; + u8 *p = skb_push(arg->skb, 4); + p[0] = arg->frame_type; + p[1] = arg->rate; + ((u16 *)p)[1] = __cpu_to_le16(arg->skb->len - 4); + ret = wsm_write_mib(priv, WSM_MIB_ID_TEMPLATE_FRAME, p, arg->skb->len); + skb_pull(arg->skb, 4); + return ret; +} + + +struct wsm_protected_mgmt_policy { + bool protectedMgmtEnable; + bool unprotectedMgmtFramesAllowed; + bool encryptionForAuthFrame; +}; + +static inline int wsm_set_protected_mgmt_policy(struct cw1200_common *priv, + struct wsm_protected_mgmt_policy *arg) +{ + __le32 val = 0; + int ret; + if (arg->protectedMgmtEnable) + val |= __cpu_to_le32(BIT(0)); + if (arg->unprotectedMgmtFramesAllowed) + val |= __cpu_to_le32(BIT(1)); + if (arg->encryptionForAuthFrame) + val |= __cpu_to_le32(BIT(2)); + ret = wsm_write_mib(priv, WSM_MIB_ID_PROTECTED_MGMT_POLICY, + &val, sizeof(val)); + return ret; +} + +struct wsm_mib_block_ack_policy { + u8 tx_tid; + u8 reserved1; + u8 rx_tid; + u8 reserved2; +} __packed; + +static inline int wsm_set_block_ack_policy(struct cw1200_common *priv, + u8 tx_tid_policy, + u8 rx_tid_policy) +{ + struct wsm_mib_block_ack_policy val = { + .tx_tid = tx_tid_policy, + .rx_tid = rx_tid_policy, + }; + return wsm_write_mib(priv, WSM_MIB_ID_BLOCK_ACK_POLICY, &val, + sizeof(val)); +} + +struct wsm_mib_association_mode { + u8 flags; /* WSM_ASSOCIATION_MODE_... */ + u8 preamble; /* WSM_JOIN_PREAMBLE_... */ + u8 greenfield; /* 1 for greenfield */ + u8 mpdu_start_spacing; + __le32 basic_rate_set; +} __packed; + +static inline int wsm_set_association_mode(struct cw1200_common *priv, + struct wsm_mib_association_mode *arg) +{ + return wsm_write_mib(priv, WSM_MIB_ID_SET_ASSOCIATION_MODE, arg, + sizeof(*arg)); +} + +#define WSM_TX_RATE_POLICY_FLAG_TERMINATE_WHEN_FINISHED BIT(2) +#define WSM_TX_RATE_POLICY_FLAG_COUNT_INITIAL_TRANSMIT BIT(3) +struct wsm_tx_rate_retry_policy { + u8 index; + u8 short_retries; + u8 long_retries; + /* BIT(2) - Terminate retries when Tx rate retry policy + * finishes. + * BIT(3) - Count initial frame transmission as part of + * rate retry counting but not as a retry + * attempt */ + u8 flags; + u8 rate_recoveries; + u8 reserved[3]; + __le32 rate_count_indices[3]; +} __packed; + +struct wsm_set_tx_rate_retry_policy { + u8 num; + u8 reserved[3]; + struct wsm_tx_rate_retry_policy tbl[8]; +} __packed; + +static inline int wsm_set_tx_rate_retry_policy(struct cw1200_common *priv, + struct wsm_set_tx_rate_retry_policy *arg) +{ + size_t size = 4 + arg->num * sizeof(struct wsm_tx_rate_retry_policy); + return wsm_write_mib(priv, WSM_MIB_ID_SET_TX_RATE_RETRY_POLICY, arg, + size); +} + +/* 4.32 SetEtherTypeDataFrameFilter */ +struct wsm_ether_type_filter_hdr { + u8 num; /* Up to WSM_MAX_FILTER_ELEMENTS */ + u8 reserved[3]; +} __packed; + +struct wsm_ether_type_filter { + u8 action; /* WSM_FILTER_ACTION_XXX */ + u8 reserved; + __le16 type; /* Type of ethernet frame */ +} __packed; + +static inline int wsm_set_ether_type_filter(struct cw1200_common *priv, + struct wsm_ether_type_filter_hdr *arg) +{ + size_t size = sizeof(struct wsm_ether_type_filter_hdr) + + arg->num * sizeof(struct wsm_ether_type_filter); + return wsm_write_mib(priv, WSM_MIB_ID_SET_ETHERTYPE_DATAFRAME_FILTER, + arg, size); +} + +/* 4.33 SetUDPPortDataFrameFilter */ +struct wsm_udp_port_filter_hdr { + u8 num; /* Up to WSM_MAX_FILTER_ELEMENTS */ + u8 reserved[3]; +} __packed; + +struct wsm_udp_port_filter { + u8 action; /* WSM_FILTER_ACTION_XXX */ + u8 type; /* WSM_FILTER_PORT_TYPE_XXX */ + __le16 port; /* Port number */ +} __packed; + +static inline int wsm_set_udp_port_filter(struct cw1200_common *priv, + struct wsm_udp_port_filter_hdr *arg) +{ + size_t size = sizeof(struct wsm_udp_port_filter_hdr) + + arg->num * sizeof(struct wsm_udp_port_filter); + return wsm_write_mib(priv, WSM_MIB_ID_SET_UDPPORT_DATAFRAME_FILTER, + arg, size); +} + +/* Undocumented MIBs: */ +/* 4.35 P2PDeviceInfo */ +#define D11_MAX_SSID_LEN (32) + +struct wsm_p2p_device_type { + __le16 categoryId; + u8 oui[4]; + __le16 subCategoryId; +} __packed; + +struct wsm_p2p_device_info { + struct wsm_p2p_device_type primaryDevice; + u8 reserved1[3]; + u8 devNameSize; + u8 localDevName[D11_MAX_SSID_LEN]; + u8 reserved2[3]; + u8 numSecDevSupported; + struct wsm_p2p_device_type secondaryDevices[0]; +} __packed; + +/* 4.36 SetWCDMABand - WO */ +struct wsm_cdma_band { + u8 WCDMA_Band; + u8 reserved[3]; +} __packed; + +/* 4.37 GroupTxSequenceCounter - RO */ +struct wsm_group_tx_seq { + __le32 bits_47_16; + __le16 bits_15_00; + __le16 reserved; +} __packed; + +/* 4.39 SetHtProtection - WO */ +#define WSM_DUAL_CTS_PROT_ENB (1 << 0) +#define WSM_NON_GREENFIELD_STA_PRESENT (1 << 1) +#define WSM_HT_PROT_MODE__NO_PROT (0 << 2) +#define WSM_HT_PROT_MODE__NON_MEMBER (1 << 2) +#define WSM_HT_PROT_MODE__20_MHZ (2 << 2) +#define WSM_HT_PROT_MODE__NON_HT_MIXED (3 << 2) +#define WSM_LSIG_TXOP_PROT_FULL (1 << 4) +#define WSM_LARGE_L_LENGTH_PROT (1 << 5) + +struct wsm_ht_protection { + __le32 flags; +} __packed; + +/* 4.40 GPIO Command - R/W */ +#define WSM_GPIO_COMMAND_SETUP 0 +#define WSM_GPIO_COMMAND_READ 1 +#define WSM_GPIO_COMMAND_WRITE 2 +#define WSM_GPIO_COMMAND_RESET 3 +#define WSM_GPIO_ALL_PINS 0xFF + +struct wsm_gpio_command { + u8 GPIO_Command; + u8 pin; + __le16 config; +} __packed; + +/* 4.41 TSFCounter - RO */ +struct wsm_tsf_counter { + __le64 TSF_Counter; +} __packed; + +/* 4.43 Keep alive period */ +struct wsm_keep_alive_period { + __le16 keepAlivePeriod; + u8 reserved[2]; +} __packed; + +static inline int wsm_keep_alive_period(struct cw1200_common *priv, + int period) +{ + struct wsm_keep_alive_period arg = { + .keepAlivePeriod = __cpu_to_le16(period), + }; + return wsm_write_mib(priv, WSM_MIB_ID_KEEP_ALIVE_PERIOD, + &arg, sizeof(arg)); +}; + +/* BSSID filtering */ +struct wsm_set_bssid_filtering { + u8 filter; + u8 reserved[3]; +} __packed; + +static inline int wsm_set_bssid_filtering(struct cw1200_common *priv, + bool enabled) +{ + struct wsm_set_bssid_filtering arg = { + .filter = !enabled, + }; + return wsm_write_mib(priv, WSM_MIB_ID_DISABLE_BSSID_FILTER, + &arg, sizeof(arg)); +} + +/* Multicast filtering - 4.5 */ +struct wsm_mib_multicast_filter { + __le32 enable; + __le32 num_addrs; + u8 macaddrs[WSM_MAX_GRP_ADDRTABLE_ENTRIES][ETH_ALEN]; +} __packed; + +static inline int wsm_set_multicast_filter(struct cw1200_common *priv, + struct wsm_mib_multicast_filter *fp) +{ + return wsm_write_mib(priv, WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE, + fp, sizeof(*fp)); +} + +/* ARP IPv4 filtering - 4.10 */ +struct wsm_mib_arp_ipv4_filter { + __le32 enable; + __be32 ipv4addrs[WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES]; +} __packed; + +static inline int wsm_set_arp_ipv4_filter(struct cw1200_common *priv, + struct wsm_mib_arp_ipv4_filter *fp) +{ + return wsm_write_mib(priv, WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE, + fp, sizeof(*fp)); +} + +/* P2P Power Save Mode Info - 4.31 */ +struct wsm_p2p_ps_modeinfo { + u8 oppPsCTWindow; + u8 count; + u8 reserved; + u8 dtimCount; + __le32 duration; + __le32 interval; + __le32 startTime; +} __packed; + +static inline int wsm_set_p2p_ps_modeinfo(struct cw1200_common *priv, + struct wsm_p2p_ps_modeinfo *mi) +{ + return wsm_write_mib(priv, WSM_MIB_ID_P2P_PS_MODE_INFO, + mi, sizeof(*mi)); +} + +static inline int wsm_get_p2p_ps_modeinfo(struct cw1200_common *priv, + struct wsm_p2p_ps_modeinfo *mi) +{ + return wsm_read_mib(priv, WSM_MIB_ID_P2P_PS_MODE_INFO, + mi, sizeof(*mi)); +} + +/* UseMultiTxConfMessage */ + +static inline int wsm_use_multi_tx_conf(struct cw1200_common *priv, + bool enabled) +{ + __le32 arg = enabled ? __cpu_to_le32(1) : 0; + + return wsm_write_mib(priv, WSM_MIB_USE_MULTI_TX_CONF, + &arg, sizeof(arg)); +} + + +/* 4.26 SetUpasdInformation */ +struct wsm_uapsd_info { + __le16 uapsd_flags; + __le16 min_auto_trigger_interval; + __le16 max_auto_trigger_interval; + __le16 auto_trigger_step; +}; + +static inline int wsm_set_uapsd_info(struct cw1200_common *priv, + struct wsm_uapsd_info *arg) +{ + return wsm_write_mib(priv, WSM_MIB_ID_SET_UAPSD_INFORMATION, + arg, sizeof(*arg)); +} + +/* 4.22 OverrideInternalTxRate */ +struct wsm_override_internal_txrate { + u8 internalTxRate; + u8 nonErpInternalTxRate; + u8 reserved[2]; +} __packed; + +static inline int wsm_set_override_internal_txrate(struct cw1200_common *priv, + struct wsm_override_internal_txrate *arg) +{ + return wsm_write_mib(priv, WSM_MIB_ID_OVERRIDE_INTERNAL_TX_RATE, + arg, sizeof(*arg)); +} + +/* ******************************************************************** */ +/* WSM TX port control */ + +void wsm_lock_tx(struct cw1200_common *priv); +void wsm_lock_tx_async(struct cw1200_common *priv); +bool wsm_flush_tx(struct cw1200_common *priv); +void wsm_unlock_tx(struct cw1200_common *priv); + +/* ******************************************************************** */ +/* WSM / BH API */ + +int wsm_handle_exception(struct cw1200_common *priv, u8 *data, size_t len); +int wsm_handle_rx(struct cw1200_common *priv, u16 id, struct wsm_hdr *wsm, + struct sk_buff **skb_p); + +/* ******************************************************************** */ +/* wsm_buf API */ + +struct wsm_buf { + u8 *begin; + u8 *data; + u8 *end; +}; + +void wsm_buf_init(struct wsm_buf *buf); +void wsm_buf_deinit(struct wsm_buf *buf); + +/* ******************************************************************** */ +/* wsm_cmd API */ + +struct wsm_cmd { + spinlock_t lock; /* Protect structure from multiple access */ + int done; + u8 *ptr; + size_t len; + void *arg; + int ret; + u16 cmd; +}; + +/* ******************************************************************** */ +/* WSM TX buffer access */ + +int wsm_get_tx(struct cw1200_common *priv, u8 **data, + size_t *tx_len, int *burst); +void wsm_txed(struct cw1200_common *priv, u8 *data); + +/* ******************************************************************** */ +/* Queue mapping: WSM <---> linux */ +/* Linux: VO VI BE BK */ +/* WSM: BE BK VI VO */ + +static inline u8 wsm_queue_id_to_linux(u8 queue_id) +{ + static const u8 queue_mapping[] = { + 2, 3, 1, 0 + }; + return queue_mapping[queue_id]; +} + +static inline u8 wsm_queue_id_to_wsm(u8 queue_id) +{ + static const u8 queue_mapping[] = { + 3, 2, 0, 1 + }; + return queue_mapping[queue_id]; +} + + +#ifdef CONFIG_CW1200_ETF +int wsm_raw_cmd(struct cw1200_common *priv, u8 *data, size_t len); +#endif + +#endif /* CW1200_HWIO_H_INCLUDED */ diff --git a/include/linux/cw1200_platform.h b/include/linux/cw1200_platform.h new file mode 100644 index 000000000000..c168fa512347 --- /dev/null +++ b/include/linux/cw1200_platform.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Dmitry Tarnyagin + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef CW1200_PLAT_H_INCLUDED +#define CW1200_PLAT_H_INCLUDED + +struct cw1200_platform_data_spi { + u8 spi_bits_per_word; /* REQUIRED */ + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + bool have_5ghz; + const struct resource *reset; /* GPIO to RSTn signal */ + const struct resource *powerup; /* GPIO to POWERUP signal */ + int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + +struct cw1200_platform_data_sdio { + u16 ref_clk; /* REQUIRED (in KHz) */ + + /* All others are optional */ + const struct resource *irq; /* if using GPIO for IRQ */ + bool have_5ghz; + bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ + const struct resource *reset; /* GPIO to RSTn signal */ + const struct resource *powerup; /* GPIO to POWERUP signal */ + int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control 3v3 / 1v8 supply */ + int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, + bool enable); /* Control CLK32K */ + const u8 *macaddr; /* if NULL, use cw1200_mac_template module parameter */ + const char *sdd_file; /* if NULL, will use default for detected hw type */ +}; + +const void *cw1200_get_platform_data(void); + +#endif /* CW1200_PLAT_H_INCLUDED */ -- GitLab From debff6184c32149bd08cfecfafbebb96201be37d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 14 May 2013 13:53:45 +0200 Subject: [PATCH 0515/2900] iwlwifi: mvm: implement D3 testing For testing the D3 (WoWLAN) firmware, it is useful to be able to run the firmware with instrumentation while the host isn't sleeping and can poke at the firmware debug logging etc. Implement this by a debugfs file. When the file is opened the D3 firmware is loaded and all regular commands are blocked. While the file is being read, poll the firmware's PME status flag and report EOF once it changes to non-zero. When it is closed, do (most of) the resume processing. This lets a user just "cat" the file. Pressing Ctrl-C to kill the cat process will resume the firwmare as though the platform resumed for non-wireless reason and when the firmware wants to wake up reading from the file automatically completes. Unlike in real suspend, only disable interrupts and don't reset the TX/RX hardware while in the test mode. This is a workaround for some interrupt problems that happen only when the PCIe link isn't fully reset (presumably by changing the PCI config space registers which the core PCI code does.) Note that while regular operations are blocked from sending commands to the firmware, they could still be made and cause strange mac80211 issues. Therefore, while using this testing feature you need to be careful to not try to disconnect, roam or similar, and will see warnings for such attempts. Als note that this requires an upcoming firmware change to tell the driver the location of the PME status flag in SRAM. D3 test will fail if the firmware doesn't report the pointer. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 4 +- drivers/net/wireless/iwlwifi/iwl-trans.h | 14 +- drivers/net/wireless/iwlwifi/mvm/d3.c | 149 ++++++++++++++++++-- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 1 + drivers/net/wireless/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 3 +- drivers/net/wireless/iwlwifi/mvm/utils.c | 10 ++ drivers/net/wireless/iwlwifi/pcie/trans.c | 19 ++- 8 files changed, 182 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index ac7ed3f809a0..c0039a992909 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -430,7 +430,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); - iwl_trans_d3_suspend(priv->trans); + iwl_trans_d3_suspend(priv->trans, false); goto out; @@ -504,7 +504,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - ret = iwl_trans_d3_resume(priv->trans, &d3_status); + ret = iwl_trans_d3_resume(priv->trans, &d3_status, false); if (ret) goto out_unlock; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 84f1c8dc9741..be4b2ac3dbbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -428,8 +428,9 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*stop_device)(struct iwl_trans *trans); - void (*d3_suspend)(struct iwl_trans *trans); - int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status); + void (*d3_suspend)(struct iwl_trans *trans, bool test); + int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, + bool test); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); @@ -588,17 +589,18 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) trans->state = IWL_TRANS_NO_FW; } -static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) +static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) { might_sleep(); - trans->ops->d3_suspend(trans); + trans->ops->d3_suspend(trans, test); } static inline int iwl_trans_d3_resume(struct iwl_trans *trans, - enum iwl_d3_status *status) + enum iwl_d3_status *status, + bool test) { might_sleep(); - return trans->ops->d3_resume(trans, status); + return trans->ops->d3_resume(trans, status, test); } static inline int iwl_trans_send_cmd(struct iwl_trans *trans, diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 4d3c978b5c76..7a2ef3f013fd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -63,6 +63,7 @@ #include #include +#include #include #include #include @@ -756,7 +757,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; } -int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) +static int __iwl_mvm_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan, + bool test) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data suspend_iter_data = { @@ -769,7 +772,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; - struct iwl_d3_manager_config d3_cfg_cmd = { + struct iwl_d3_manager_config d3_cfg_cmd_data = { /* * Program the minimum sleep time to 10 seconds, as many * platforms have issues processing a wakeup signal while @@ -777,17 +780,30 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) */ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), }; + struct iwl_host_cmd d3_cfg_cmd = { + .id = D3_CONFIG_CMD, + .flags = CMD_SYNC | CMD_WANT_SKB, + .data[0] = &d3_cfg_cmd_data, + .len[0] = sizeof(d3_cfg_cmd_data), + }; struct wowlan_key_data key_data = { .use_rsc_tsc = false, .tkip = &tkip_cmd, .use_tkip = false, }; int ret, i; + int len __maybe_unused; u16 seq; u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; - if (WARN_ON(!wowlan)) + if (!wowlan) { + /* + * mac80211 shouldn't get here, but for D3 test + * it doesn't warrant a warning + */ + WARN_ON(!test); return -EINVAL; + } key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); if (!key_data.rsc_tsc) @@ -1012,14 +1028,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) goto out; /* must be last -- this switches firmware state */ - ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, - sizeof(d3_cfg_cmd), &d3_cfg_cmd); + ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); if (ret) goto out; +#ifdef CONFIG_IWLWIFI_DEBUGFS + len = le32_to_cpu(d3_cfg_cmd.resp_pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK; + if (len >= sizeof(u32) * 2) { + mvm->d3_test_pme_ptr = + le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); + } else if (test) { + /* in test mode we require the pointer */ + ret = -EIO; + goto out; + } +#endif + iwl_free_resp(&d3_cfg_cmd); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); - iwl_trans_d3_suspend(mvm->trans); + iwl_trans_d3_suspend(mvm->trans, test); out: mvm->aux_sta.sta_id = old_aux_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; @@ -1034,6 +1062,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) return ret; } +int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) +{ + return __iwl_mvm_suspend(hw, wowlan, false); +} + static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -1238,9 +1271,8 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) #endif } -int iwl_mvm_resume(struct ieee80211_hw *hw) +static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data resume_iter_data = { .mvm = mvm, }; @@ -1260,7 +1292,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) vif = resume_iter_data.vif; - ret = iwl_trans_d3_resume(mvm->trans, &d3_status); + ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); if (ret) goto out_unlock; @@ -1277,7 +1309,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) out_unlock: mutex_unlock(&mvm->mutex); - if (vif) + if (!test && vif) ieee80211_resume_disconnect(vif); /* return 1 to reconfigure the device */ @@ -1285,9 +1317,106 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) return 1; } +int iwl_mvm_resume(struct ieee80211_hw *hw) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + return __iwl_mvm_resume(mvm, false); +} + void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); device_set_wakeup_enable(mvm->trans->dev, enabled); } + +#ifdef CONFIG_IWLWIFI_DEBUGFS +static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) +{ + struct iwl_mvm *mvm = inode->i_private; + int err; + + if (mvm->d3_test_active) + return -EBUSY; + + file->private_data = inode->i_private; + + ieee80211_stop_queues(mvm->hw); + synchronize_net(); + + /* start pseudo D3 */ + rtnl_lock(); + err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); + rtnl_unlock(); + if (err > 0) + err = -EINVAL; + if (err) { + ieee80211_wake_queues(mvm->hw); + return err; + } + mvm->d3_test_active = true; + return 0; +} + +static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + u32 pme_asserted; + + while (true) { + pme_asserted = iwl_trans_read_mem32(mvm->trans, + mvm->d3_test_pme_ptr); + if (pme_asserted) + break; + if (msleep_interruptible(100)) + break; + } + + return 0; +} + +static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + if (vif->type == NL80211_IFTYPE_STATION) + ieee80211_connection_loss(vif); +} + +static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) +{ + struct iwl_mvm *mvm = inode->i_private; + int remaining_time = 10; + + mvm->d3_test_active = false; + __iwl_mvm_resume(mvm, true); + iwl_abort_notification_waits(&mvm->notif_wait); + ieee80211_restart_hw(mvm->hw); + + /* wait for restart and disconnect all interfaces */ + while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && + remaining_time > 0) { + remaining_time--; + msleep(1000); + } + + if (remaining_time == 0) + IWL_ERR(mvm, "Timed out waiting for HW restart to finish!\n"); + + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_d3_test_disconn_work_iter, NULL); + + ieee80211_wake_queues(mvm->hw); + + return 0; +} + +const struct file_operations iwl_dbgfs_d3_test_ops = { + .llseek = no_llseek, + .open = iwl_mvm_d3_test_open, + .read = iwl_mvm_d3_test_read, + .release = iwl_mvm_d3_test_release, +}; +#endif diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 69e0806075a2..b7643c16201f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -938,6 +938,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); + MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); #endif /* diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 6a3220b6273e..384259baf525 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -459,8 +459,10 @@ struct iwl_mvm { #ifdef CONFIG_PM_SLEEP int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; #ifdef CONFIG_IWLWIFI_DEBUGFS + bool d3_test_active; bool store_d3_resume_sram; void *d3_resume_sram; + u32 d3_test_pme_ptr; #endif #endif @@ -669,6 +671,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw, struct inet6_dev *idev); void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int idx); +extern const struct file_operations iwl_dbgfs_d3_test_ops; /* BT Coex */ int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm); diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c index 1b4db25d53fb..a8652ddd6bed 100644 --- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c @@ -204,7 +204,8 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, { int ret; - WARN_ON(ctxt->ref); + WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && + ctxt->ref); lockdep_assert_held(&mvm->mutex); ctxt->channel = chandef->chan; diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index c9b44ab4af07..1e1332839e4a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -76,6 +76,11 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd) { int ret; +#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) + if (WARN_ON(mvm->d3_test_active)) + return -EIO; +#endif + /* * Synchronous commands from this op-mode must hold * the mutex, this ensures we don't try to send two @@ -125,6 +130,11 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd, lockdep_assert_held(&mvm->mutex); +#if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) + if (WARN_ON(mvm->d3_test_active)) + return -EIO; +#endif + /* * Only synchronous commands can wait for status, * we use WANT_SKB so the caller can't. diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 0b021305eedf..197dbe0a868c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -578,9 +578,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) clear_bit(STATUS_RFKILL, &trans_pcie->status); } -static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) +static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) { iwl_disable_interrupts(trans); + + /* + * in testing mode, the host stays awake and the + * hardware won't be reset (not even partially) + */ + if (test) + return; + iwl_pcie_disable_ict(trans); iwl_clear_bit(trans, CSR_GP_CNTRL, @@ -599,11 +607,18 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans) } static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, - enum iwl_d3_status *status) + enum iwl_d3_status *status, + bool test) { u32 val; int ret; + if (test) { + iwl_enable_interrupts(trans); + *status = IWL_D3_STATUS_ALIVE; + return 0; + } + iwl_pcie_set_pwr(trans, false); val = iwl_read32(trans, CSR_RESET); -- GitLab From ab276103357637fb26cc851369b5abbdc42afbf4 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 24 May 2013 12:18:30 +0200 Subject: [PATCH 0516/2900] ath9k: remove useless flag conversation. some flags used only outside of ath9k - In this case we can use "enum mac80211_rx_flags" and pass it upstream without extra conversation. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 5 +++-- drivers/net/wireless/ath/ath9k/mac.c | 11 +++++++---- drivers/net/wireless/ath/ath9k/mac.h | 1 + drivers/net/wireless/ath/ath9k/recv.c | 5 +---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 301bf72c53bf..5163abd3937c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -469,6 +469,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_status = 0; rxs->rs_flags = 0; + rxs->flag = 0; rxs->rs_datalen = rxsp->status2 & AR_DataLen; rxs->rs_tstamp = rxsp->status3; @@ -493,8 +494,8 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); - rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0; - rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0; + rxs->flag |= (rxsp->status4 & AR_GI) ? RX_FLAG_SHORT_GI : 0; + rxs->flag |= (rxsp->status4 & AR_2040) ? RX_FLAG_40MHZ : 0; rxs->evm0 = rxsp->status6; rxs->evm1 = rxsp->status7; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 498fee04afa0..a52081d73bef 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -547,6 +547,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, rs->rs_status = 0; rs->rs_flags = 0; + rs->flag = 0; rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen; rs->rs_tstamp = ads.AR_RcvTimestamp; @@ -586,10 +587,12 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, rs->rs_moreaggr = (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); - rs->rs_flags = - (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; - rs->rs_flags |= - (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; + + /* directly mapped flags for ieee80211_rx_status */ + rs->flag |= + (ads.ds_rxstatus3 & AR_GI) ? RX_FLAG_SHORT_GI : 0; + rs->flag |= + (ads.ds_rxstatus3 & AR_2040) ? RX_FLAG_40MHZ : 0; if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 5865f92998e1..3f1e7754a1a7 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -149,6 +149,7 @@ struct ath_rx_status { u32 evm2; u32 evm3; u32 evm4; + u32 flag; /* see enum mac80211_rx_flags */ }; struct ath_htc_rx_status { diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 8be2b5d8c155..b4b758deb30e 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -868,10 +868,7 @@ static int ath9k_process_rate(struct ath_common *common, if (rx_stats->rs_rate & 0x80) { /* HT rate */ rxs->flag |= RX_FLAG_HT; - if (rx_stats->rs_flags & ATH9K_RX_2040) - rxs->flag |= RX_FLAG_40MHZ; - if (rx_stats->rs_flags & ATH9K_RX_GI) - rxs->flag |= RX_FLAG_SHORT_GI; + rxs->flag |= rx_stats->flag; rxs->rate_idx = rx_stats->rs_rate & 0x7f; return 0; } -- GitLab From b0a1ae976d6cd40ff90ba87883e17eb2610dae3d Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Fri, 24 May 2013 20:30:59 +0200 Subject: [PATCH 0517/2900] ath9k: check for Rx-STBC flag and pass it to ieee80211 This patch make use of STBC flag in DMA RX descriptor. Only devices after ar9280 can provide this information. If card support it we will set HAVE_STBC flag, to show clint programm thet STBC is supported but not received. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 10 ++++++++-- drivers/net/wireless/ath/ath9k/mac.c | 5 +++++ drivers/net/wireless/ath/ath9k/mac.h | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c7b888f22703..0536d442b068 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "ath9k.h" @@ -766,8 +767,13 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_RC_TABLE; - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) - hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + + if (AR_SREV_9280_20_OR_LATER(ah)) + hw->radiotap_mcs_details |= + IEEE80211_RADIOTAP_MCS_HAVE_STBC; + } if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index a52081d73bef..d055e389abfc 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -593,6 +593,11 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, (ads.ds_rxstatus3 & AR_GI) ? RX_FLAG_SHORT_GI : 0; rs->flag |= (ads.ds_rxstatus3 & AR_2040) ? RX_FLAG_40MHZ : 0; + if (AR_SREV_9280_20_OR_LATER(ah)) + rs->flag |= + (ads.ds_rxstatus3 & AR_STBC) ? + /* we can only Nss=1 STBC */ + (1 << RX_FLAG_STBC_SHIFT) : 0; if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 3f1e7754a1a7..b02dfce964b4 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -534,7 +534,8 @@ struct ar5416_desc { #define AR_2040 0x00000002 #define AR_Parallel40 0x00000004 #define AR_Parallel40_S 2 -#define AR_RxStatusRsvd30 0x000000f8 +#define AR_STBC 0x00000008 /* on ar9280 and later */ +#define AR_RxStatusRsvd30 0x000000f0 #define AR_RxAntenna 0xffffff00 #define AR_RxAntenna_S 8 -- GitLab From 4e17b87e792ed19e75a96eea618b90510265120c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 29 May 2013 22:22:05 -0400 Subject: [PATCH 0518/2900] cw1200: Fix compile with CONFIG_PM=n Intel's 0-day kernel build tester caught this build failure. This patch properly wraps everything that depends on CONFIG_PM. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/Makefile | 2 +- drivers/net/wireless/cw1200/cw1200_sdio.c | 4 ++++ drivers/net/wireless/cw1200/cw1200_spi.c | 4 ++++ drivers/net/wireless/cw1200/main.c | 10 ++++++++++ drivers/net/wireless/cw1200/pm.h | 11 ++++++++--- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/cw1200/Makefile b/drivers/net/wireless/cw1200/Makefile index c19737276be2..1aa3682066e0 100644 --- a/drivers/net/wireless/cw1200/Makefile +++ b/drivers/net/wireless/cw1200/Makefile @@ -8,9 +8,9 @@ cw1200_core-y := \ wsm.o \ sta.o \ scan.o \ - pm.o \ debug.o cw1200_core-$(CONFIG_CW1200_ITP) += itp.o +cw1200_core-$(CONFIG_PM) += pm.o # CFLAGS_sta.o += -DDEBUG diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index f6e22192d80a..2059a31815f3 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -334,6 +334,7 @@ static void cw1200_sdio_disconnect(struct sdio_func *func) } } +#ifdef CONFIG_PM static int cw1200_sdio_suspend(struct device *dev) { int ret; @@ -360,15 +361,18 @@ static const struct dev_pm_ops cw1200_pm_ops = { .suspend = cw1200_sdio_suspend, .resume = cw1200_sdio_resume, }; +#endif static struct sdio_driver sdio_driver = { .name = "cw1200_wlan_sdio", .id_table = cw1200_sdio_ids, .probe = cw1200_sdio_probe, .remove = cw1200_sdio_disconnect, +#ifdef CONFIG_PM .drv = { .pm = &cw1200_pm_ops, } +#endif }; /* Init Module function -> Called by insmod */ diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 04af68534854..b957d4a01c52 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -436,6 +436,7 @@ static int cw1200_spi_disconnect(struct spi_device *func) return 0; } +#ifdef CONFIG_PM static int cw1200_spi_suspend(struct device *dev, pm_message_t state) { struct sbus_priv *self = spi_get_drvdata(to_spi_device(dev)); @@ -451,6 +452,7 @@ static int cw1200_spi_resume(struct device *dev) { return 0; } +#endif static struct spi_driver spi_driver = { .probe = cw1200_spi_probe, @@ -459,8 +461,10 @@ static struct spi_driver spi_driver = { .name = "cw1200_wlan_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, +#ifdef CONFIG_PM .suspend = cw1200_spi_suspend, .resume = cw1200_spi_resume, +#endif }, }; diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index 8426d3d7607e..ef4b0b915f87 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c @@ -234,8 +234,10 @@ static const struct ieee80211_ops cw1200_ops = { .get_stats = cw1200_get_stats, .ampdu_action = cw1200_ampdu_action, .flush = cw1200_flush, +#ifdef CONFIG_PM .suspend = cw1200_wow_suspend, .resume = cw1200_wow_resume, +#endif /* Intentionally not offloaded: */ /*.channel_switch = cw1200_channel_switch, */ /*.remain_on_channel = cw1200_remain_on_channel, */ @@ -292,10 +294,12 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); +#ifdef CONFIG_PM /* Support only for limited wowlan functionalities */ hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY | WIPHY_WOWLAN_DISCONNECT; hw->wiphy->wowlan.n_patterns = 0; +#endif hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; @@ -419,18 +423,22 @@ static int cw1200_register_common(struct ieee80211_hw *dev) goto done; #endif +#ifdef CONFIG_PM err = cw1200_pm_init(&priv->pm_state, priv); if (err) { pr_err("Cannot init PM. (%d).\n", err); return err; } +#endif err = ieee80211_register_hw(dev); if (err) { pr_err("Cannot register device (%d).\n", err); +#ifdef CONFIG_PM cw1200_pm_deinit(&priv->pm_state); +#endif return err; } @@ -482,7 +490,9 @@ static void cw1200_unregister_common(struct ieee80211_hw *dev) cw1200_queue_deinit(&priv->tx_queue[i]); cw1200_queue_stats_deinit(&priv->tx_queue_stats); +#ifdef CONFIG_PM cw1200_pm_deinit(&priv->pm_state); +#endif } /* Clock is in KHz */ diff --git a/drivers/net/wireless/cw1200/pm.h b/drivers/net/wireless/cw1200/pm.h index 516d9671dd1e..3ed90ff22bb8 100644 --- a/drivers/net/wireless/cw1200/pm.h +++ b/drivers/net/wireless/cw1200/pm.h @@ -25,14 +25,19 @@ struct cw1200_pm_state { spinlock_t lock; /* Protect access */ }; +#ifdef CONFIG_PM int cw1200_pm_init(struct cw1200_pm_state *pm, struct cw1200_common *priv); void cw1200_pm_deinit(struct cw1200_pm_state *pm); -void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, - unsigned long tmo); int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); int cw1200_wow_resume(struct ieee80211_hw *hw); int cw1200_can_suspend(struct cw1200_common *priv); - +void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, + unsigned long tmo); +#else +static inline void cw1200_pm_stay_awake(struct cw1200_pm_state *pm, + unsigned long tmo) { +} +#endif #endif -- GitLab From 4696d477d8dd23ad990d716a90d08cb149c2e861 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 30 May 2013 19:41:11 +0800 Subject: [PATCH 0519/2900] cw1200: remove duplicated include from wsm.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/wsm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index 4db6cc16879c..f3fd9b218724 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include -- GitLab From c0dc79d607c39f5f6c6fd6cc8119b81639a6d6f3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 30 May 2013 19:42:35 +0800 Subject: [PATCH 0520/2900] cw1200: convert to use simple_open() This removes an open coded simple_open() function and replaces file operations references to the function with simple_open() instead. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/debug.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index b815181802e0..eb40c9c61a51 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -357,12 +357,6 @@ static const struct file_operations fops_counters = { .owner = THIS_MODULE, }; -static int cw1200_generic_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - #ifdef CONFIG_CW1200_ETF static int cw1200_etf_out_show(struct seq_file *seq, void *v) { @@ -511,7 +505,7 @@ static ssize_t cw1200_wsm_dumps(struct file *file, } static const struct file_operations fops_wsm_dumps = { - .open = cw1200_generic_open, + .open = simple_open, .write = cw1200_wsm_dumps, .llseek = default_llseek, }; -- GitLab From d071c0430c6ae42fedec78f1ec2e37603adb8c78 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 30 May 2013 19:42:54 +0800 Subject: [PATCH 0521/2900] cw1200: use module_spi_driver to simplify the code module_spi_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_spi.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index b957d4a01c52..feb541bb507c 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -468,17 +468,4 @@ static struct spi_driver spi_driver = { }, }; -/* Init Module function -> Called by insmod */ -static int __init cw1200_spi_init(void) -{ - return spi_register_driver(&spi_driver); -} - -/* Called at Driver Unloading */ -static void __exit cw1200_spi_exit(void) -{ - spi_unregister_driver(&spi_driver); -} - -module_init(cw1200_spi_init); -module_exit(cw1200_spi_exit); +module_spi_driver(spi_driver); -- GitLab From 3e817f086f06069a23b797ee2279bbae638d5edc Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 30 May 2013 19:43:13 +0800 Subject: [PATCH 0522/2900] cw1200: remove unused including Remove including that don't need it. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200.h | 1 - drivers/net/wireless/cw1200/cw1200_sdio.c | 1 - drivers/net/wireless/cw1200/cw1200_spi.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h index 2aa17ca60ba8..e9424e635883 100644 --- a/drivers/net/wireless/cw1200/cw1200.h +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -19,7 +19,6 @@ #define CW1200_H #include -#include #include #include #include diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 2059a31815f3..863510d062fb 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -9,7 +9,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index feb541bb507c..75adef0c0cfd 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -13,7 +13,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include -- GitLab From dc7551cbf7744ef7374c3f3c46817413ad4bcc40 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 30 May 2013 09:51:34 +0000 Subject: [PATCH 0523/2900] netxen_nic: Log driver version with firmware version Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 51e13d92761e..2294cd2293b1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -860,9 +860,9 @@ netxen_check_options(struct netxen_adapter *adapter) adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0; } - dev_info(&pdev->dev, "firmware v%d.%d.%d [%s]\n", - fw_major, fw_minor, fw_build, - adapter->ahw.cut_through ? "cut-through" : "legacy"); + dev_info(&pdev->dev, "Driver v%s, firmware v%d.%d.%d [%s]\n", + NETXEN_NIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build, + adapter->ahw.cut_through ? "cut-through" : "legacy"); if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); -- GitLab From b08a92bb7381ff03d4101bcc61e65120bc690a4f Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 30 May 2013 09:51:35 +0000 Subject: [PATCH 0524/2900] netxen_nic: Log proper error message in case of mismatched adapter type o log "Unknown" board name and "Unknown" serial number in case of mismatched adapter type found. This will avoid weird characters logs when an adapter is in bad state or corrupted. Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 10 +++++++--- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 322a36b76727..e5ab1ecb4bb2 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -1855,7 +1855,7 @@ static const struct netxen_brdinfo netxen_boards[] = { #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards) -static inline void get_brd_name_by_type(u32 type, char *name) +static inline int netxen_nic_get_brd_name_by_type(u32 type, char *name) { int i, found = 0; for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { @@ -1864,10 +1864,14 @@ static inline void get_brd_name_by_type(u32 type, char *name) found = 1; break; } + } + if (!found) { + strcpy(name, "Unknown"); + return -EINVAL; } - if (!found) - name = "Unknown"; + + return 0; } static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 2294cd2293b1..558df468f2e4 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -841,7 +841,9 @@ netxen_check_options(struct netxen_adapter *adapter) } if (adapter->portnum == 0) { - get_brd_name_by_type(adapter->ahw.board_type, brd_name); + if (netxen_nic_get_brd_name_by_type(adapter->ahw.board_type, + brd_name)) + strcpy(serial_num, "Unknown"); pr_info("%s: %s Board S/N %s Chip rev 0x%x\n", module_name(THIS_MODULE), -- GitLab From a120e864676548454f8d061e7d8a2e68c908a794 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 30 May 2013 09:51:36 +0000 Subject: [PATCH 0525/2900] netxen_nic: netxen_setup_intr() function code cleanup Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- .../ethernet/qlogic/netxen/netxen_nic_main.c | 77 +++++++++++-------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 558df468f2e4..927ae9f801fb 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -593,47 +593,43 @@ static const struct net_device_ops netxen_netdev_ops = { }; static void -netxen_setup_intr(struct netxen_adapter *adapter) +netxen_initialize_interrupt_registers(struct netxen_adapter *adapter) { struct netxen_legacy_intr_set *legacy_intrp; - struct pci_dev *pdev = adapter->pdev; - int err, num_msix; - - if (adapter->rss_supported) { - num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? - MSIX_ENTRIES_PER_ADAPTER : 2; - } else - num_msix = 1; - - adapter->max_sds_rings = 1; - - adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); + u32 tgt_status_reg, int_state_reg; if (adapter->ahw.revision_id >= NX_P3_B0) legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; else legacy_intrp = &legacy_intr[0]; + tgt_status_reg = legacy_intrp->tgt_status_reg; + int_state_reg = ISR_INT_STATE_REG; + adapter->int_vec_bit = legacy_intrp->int_vec_bit; - adapter->tgt_status_reg = netxen_get_ioaddr(adapter, - legacy_intrp->tgt_status_reg); + adapter->tgt_status_reg = netxen_get_ioaddr(adapter, tgt_status_reg); adapter->tgt_mask_reg = netxen_get_ioaddr(adapter, - legacy_intrp->tgt_mask_reg); + legacy_intrp->tgt_mask_reg); adapter->pci_int_reg = netxen_get_ioaddr(adapter, - legacy_intrp->pci_int_reg); + legacy_intrp->pci_int_reg); adapter->isr_int_vec = netxen_get_ioaddr(adapter, ISR_INT_VECTOR); if (adapter->ahw.revision_id >= NX_P3_B1) adapter->crb_int_state_reg = netxen_get_ioaddr(adapter, - ISR_INT_STATE_REG); + int_state_reg); else adapter->crb_int_state_reg = netxen_get_ioaddr(adapter, - CRB_INT_VECTOR); + CRB_INT_VECTOR); +} - netxen_set_msix_bit(pdev, 0); +static int netxen_setup_msi_interrupts(struct netxen_adapter *adapter, + int num_msix) +{ + struct pci_dev *pdev = adapter->pdev; + u32 value; + int err; if (adapter->msix_supported) { - netxen_init_msix_entries(adapter, num_msix); err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); if (err == 0) { @@ -644,26 +640,45 @@ netxen_setup_intr(struct netxen_adapter *adapter) adapter->max_sds_rings = num_msix; dev_info(&pdev->dev, "using msi-x interrupts\n"); - return; + return 0; } - - if (err > 0) - pci_disable_msix(pdev); - /* fall through for msi */ } if (use_msi && !pci_enable_msi(pdev)) { + value = msi_tgt_status[adapter->ahw.pci_func]; adapter->flags |= NETXEN_NIC_MSI_ENABLED; - adapter->tgt_status_reg = netxen_get_ioaddr(adapter, - msi_tgt_status[adapter->ahw.pci_func]); - dev_info(&pdev->dev, "using msi interrupts\n"); + adapter->tgt_status_reg = netxen_get_ioaddr(adapter, value); adapter->msix_entries[0].vector = pdev->irq; - return; + dev_info(&pdev->dev, "using msi interrupts\n"); + return 0; } - dev_info(&pdev->dev, "using legacy interrupts\n"); + return -EIO; +} + +static void netxen_setup_intr(struct netxen_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + int num_msix; + + if (adapter->rss_supported) + num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? + MSIX_ENTRIES_PER_ADAPTER : 2; + else + num_msix = 1; + + adapter->max_sds_rings = 1; + adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); + + netxen_initialize_interrupt_registers(adapter); + netxen_set_msix_bit(pdev, 0); + + if (!netxen_setup_msi_interrupts(adapter, num_msix)) + return; + adapter->msix_entries[0].vector = pdev->irq; + dev_info(&pdev->dev, "using legacy interrupts\n"); } static void -- GitLab From b37eb210c076b0465fcb8d14694fcce3f267ac63 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 30 May 2013 09:51:37 +0000 Subject: [PATCH 0526/2900] netxen_nic: Avoid mixed mode interrupts o Adapters do not support co-existence of INTx Interrupt with MSI-X or MSI among multiple functions. Prevent attaching of a function during normal load, if adapter gets into mixed mode of interrupts Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- .../ethernet/qlogic/netxen/netxen_nic_hdr.h | 3 ++ .../ethernet/qlogic/netxen/netxen_nic_main.c | 50 ++++++++++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h index 28e076960bcb..32c790659f9c 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h @@ -734,6 +734,9 @@ enum { #define NIC_CRB_BASE_2 (NETXEN_CAM_RAM(0x700)) #define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) #define NETXEN_NIC_REG_2(X) (NIC_CRB_BASE_2+(X)) +#define NETXEN_INTR_MODE_REG NETXEN_NIC_REG(0x44) +#define NETXEN_MSI_MODE 0x1 +#define NETXEN_INTX_MODE 0x2 #define NX_CDRP_CRB_OFFSET (NETXEN_NIC_REG(0x18)) #define NX_ARG1_CRB_OFFSET (NETXEN_NIC_REG(0x1c)) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 927ae9f801fb..20c7b3c12b56 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -592,6 +592,22 @@ static const struct net_device_ops netxen_netdev_ops = { #endif }; +static inline bool netxen_function_zero(struct pci_dev *pdev) +{ + return (PCI_FUNC(pdev->devfn) == 0) ? true : false; +} + +static inline void netxen_set_interrupt_mode(struct netxen_adapter *adapter, + u32 mode) +{ + NXWR32(adapter, NETXEN_INTR_MODE_REG, mode); +} + +static inline u32 netxen_get_interrupt_mode(struct netxen_adapter *adapter) +{ + return NXRD32(adapter, NETXEN_INTR_MODE_REG); +} + static void netxen_initialize_interrupt_registers(struct netxen_adapter *adapter) { @@ -654,10 +670,11 @@ static int netxen_setup_msi_interrupts(struct netxen_adapter *adapter, return 0; } + dev_err(&pdev->dev, "Failed to acquire MSI-X/MSI interrupt vector\n"); return -EIO; } -static void netxen_setup_intr(struct netxen_adapter *adapter) +static int netxen_setup_intr(struct netxen_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; int num_msix; @@ -674,11 +691,24 @@ static void netxen_setup_intr(struct netxen_adapter *adapter) netxen_initialize_interrupt_registers(adapter); netxen_set_msix_bit(pdev, 0); - if (!netxen_setup_msi_interrupts(adapter, num_msix)) - return; + if (netxen_function_zero(pdev)) { + if (!netxen_setup_msi_interrupts(adapter, num_msix)) + netxen_set_interrupt_mode(adapter, NETXEN_MSI_MODE); + else + netxen_set_interrupt_mode(adapter, NETXEN_INTX_MODE); + } else { + if (netxen_get_interrupt_mode(adapter) == NETXEN_MSI_MODE && + netxen_setup_msi_interrupts(adapter, num_msix)) { + dev_err(&pdev->dev, "Co-existence of MSI-X/MSI and INTx interrupts is not supported\n"); + return -EIO; + } + } - adapter->msix_entries[0].vector = pdev->irq; - dev_info(&pdev->dev, "using legacy interrupts\n"); + if (!NETXEN_IS_MSI_FAMILY(adapter)) { + adapter->msix_entries[0].vector = pdev->irq; + dev_info(&pdev->dev, "using legacy interrupts\n"); + } + return 0; } static void @@ -1525,7 +1555,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_nic_clear_stats(adapter); - netxen_setup_intr(adapter); + err = netxen_setup_intr(adapter); + + if (err) { + dev_err(&adapter->pdev->dev, + "Failed to setup interrupts, error = %d\n", err); + goto err_out_disable_msi; + } err = netxen_setup_netdev(adapter, netdev); if (err) @@ -1613,7 +1649,7 @@ static void netxen_nic_remove(struct pci_dev *pdev) clear_bit(__NX_RESETTING, &adapter->state); netxen_teardown_intr(adapter); - + netxen_set_interrupt_mode(adapter, 0); netxen_remove_diag_entries(adapter); netxen_cleanup_pci_map(adapter); -- GitLab From 90648153754cc1ca2eb08cd19c7b13354a795183 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Thu, 30 May 2013 09:51:38 +0000 Subject: [PATCH 0527/2900] netxen_nic: Update version to 4.0.81 Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index e5ab1ecb4bb2..3fe09ab2d7c9 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 80 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.80" +#define _NETXEN_NIC_LINUX_SUBVERSION 81 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.81" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) -- GitLab From ccfecdfe16a872ed3e8322ea48e34502568eb849 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:03 +0000 Subject: [PATCH 0528/2900] net: emaclite: Report failures in mdio setup Be more verbose when any problem happens. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 919b983114e9..a16dc3508998 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -852,8 +852,10 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) /* Don't register the MDIO bus if the phy_node or its parent node * can't be found. */ - if (!np) + if (!np) { + dev_err(dev, "Failed to register mdio bus.\n"); return -ENODEV; + } /* Enable the MDIO bus by asserting the enable bit in MDIO Control * register. @@ -862,8 +864,10 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) XEL_MDIOCTRL_MDIOEN_MASK); bus = mdiobus_alloc(); - if (!bus) + if (!bus) { + dev_err(dev, "Failed to allocal mdiobus\n"); return -ENOMEM; + } of_address_to_resource(np, 0, &res); snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", @@ -879,8 +883,10 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) lp->mii_bus = bus; rc = of_mdiobus_register(bus, np); - if (rc) + if (rc) { + dev_err(dev, "Failed to register mdio bus.\n"); goto err_register; + } return 0; -- GitLab From e0a3bc65448c01289a74329ddf6c84d8c0594e59 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:04 +0000 Subject: [PATCH 0529/2900] net: emaclite: Support multiple phys connected to one MDIO bus For system which contains at least two ethernet IP where one IP manage MDIO bus with several PHYs. Example dts node: ethernet_mac0: ethernet@81000000 { compatible = "xlnx,xps-ethernetlite-1.00.a"; device_type = "network"; interrupt-parent = <&xps_intc_0>; interrupts = < 1 0 >; local-mac-address = [ 00 0a 35 00 db bb ]; phy-handle = <ðernet_mac0_phy0>; reg = < 0x81000000 0x10000 >; xlnx,duplex = <0x1>; xlnx,family = "spartan3e"; xlnx,include-internal-loopback = <0x0>; xlnx,include-mdio = <0x1>; xlnx,rx-ping-pong = <0x0>; xlnx,tx-ping-pong = <0x0>; ethernet_mac0_mdio { #address-cells = <1>; #size-cells = <0>; ethernet_mac0_phy0: phy@1 { reg = <0x1>; } ; ethernet_mac0_phy1: phy@3 { reg = <0x3>; } ; } ; } ; ethernet_mac2: ethernet@81040000 { compatible = "xlnx,xps-ethernetlite-1.00.a"; device_type = "network"; interrupt-parent = <&xps_intc_0>; interrupts = < 11 0 >; local-mac-address = [ 00 0a 35 00 db bb ]; phy-handle = <ðernet_mac0_phy1>; reg = < 0x81040000 0x10000 >; xlnx,duplex = <0x1>; xlnx,family = "spartan3e"; xlnx,include-internal-loopback = <0x0>; xlnx,include-mdio = <0x0>; xlnx,rx-ping-pong = <0x0>; xlnx,tx-ping-pong = <0x0>; } ; Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index a16dc3508998..fcd1e0b46103 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -848,6 +848,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) int rc; struct resource res; struct device_node *np = of_get_parent(lp->phy_node); + struct device_node *npp; /* Don't register the MDIO bus if the phy_node or its parent node * can't be found. @@ -856,6 +857,17 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) dev_err(dev, "Failed to register mdio bus.\n"); return -ENODEV; } + npp = of_get_parent(np); + + of_address_to_resource(npp, 0, &res); + if (lp->ndev->mem_start != res.start) { + struct phy_device *phydev; + phydev = of_phy_find_device(lp->phy_node); + if (!phydev) + dev_info(dev, + "MDIO of the phy is not registered yet\n"); + return 0; + } /* Enable the MDIO bus by asserting the enable bit in MDIO Control * register. @@ -869,7 +881,6 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) return -ENOMEM; } - of_address_to_resource(np, 0, &res); snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", (unsigned long long)res.start); bus->priv = lp; -- GitLab From 3fb99fa7c7d2310791bf39929285da44b201fd40 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:05 +0000 Subject: [PATCH 0530/2900] net: emaclite: Let's make xemaclite_adjust_link static xemaclite_adjust_link is used locally. It removes sparse warning: drivers/net/ethernet/xilinx/xilinx_emaclite.c:916:6: warning: symbol 'xemaclite_adjust_link' was not declared. Should it be static? Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index fcd1e0b46103..93bb14e04d84 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -913,7 +913,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) * There's nothing in the Emaclite device to be configured when the link * state changes. We just print the status. */ -void xemaclite_adjust_link(struct net_device *ndev) +static void xemaclite_adjust_link(struct net_device *ndev) { struct net_local *lp = netdev_priv(ndev); struct phy_device *phy = lp->phy_dev; -- GitLab From 123c1407af877b9b036b852b77013a6f9f6049b0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:06 +0000 Subject: [PATCH 0531/2900] net: emaclite: Do not use microblaze and ppc IO functions Emaclite can be used on ARM zynq where in_be32/out_be32 IO functions are not present. Use standard __raw_readl/__raw_writel IO functions instead. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 138 +++++++++--------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 93bb14e04d84..9227ed7bce10 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -159,34 +159,32 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata) u32 reg_data; /* Enable the Tx interrupts for the first Buffer */ - reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET); - out_be32(drvdata->base_addr + XEL_TSR_OFFSET, - reg_data | XEL_TSR_XMIT_IE_MASK); + reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); + __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, + drvdata->base_addr + XEL_TSR_OFFSET); /* Enable the Tx interrupts for the second Buffer if * configured in HW */ if (drvdata->tx_ping_pong != 0) { - reg_data = in_be32(drvdata->base_addr + + reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); - out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET, - reg_data | XEL_TSR_XMIT_IE_MASK); + __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK, + drvdata->base_addr + XEL_BUFFER_OFFSET + + XEL_TSR_OFFSET); } /* Enable the Rx interrupts for the first buffer */ - out_be32(drvdata->base_addr + XEL_RSR_OFFSET, - XEL_RSR_RECV_IE_MASK); + __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET); /* Enable the Rx interrupts for the second Buffer if * configured in HW */ if (drvdata->rx_ping_pong != 0) { - out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_RSR_OFFSET, - XEL_RSR_RECV_IE_MASK); + __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET); } /* Enable the Global Interrupt Enable */ - out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK); + __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); } /** @@ -201,37 +199,37 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata) u32 reg_data; /* Disable the Global Interrupt Enable */ - out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK); + __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET); /* Disable the Tx interrupts for the first buffer */ - reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET); - out_be32(drvdata->base_addr + XEL_TSR_OFFSET, - reg_data & (~XEL_TSR_XMIT_IE_MASK)); + reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET); + __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), + drvdata->base_addr + XEL_TSR_OFFSET); /* Disable the Tx interrupts for the second Buffer * if configured in HW */ if (drvdata->tx_ping_pong != 0) { - reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + + reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); - out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_TSR_OFFSET, - reg_data & (~XEL_TSR_XMIT_IE_MASK)); + __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK), + drvdata->base_addr + XEL_BUFFER_OFFSET + + XEL_TSR_OFFSET); } /* Disable the Rx interrupts for the first buffer */ - reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET); - out_be32(drvdata->base_addr + XEL_RSR_OFFSET, - reg_data & (~XEL_RSR_RECV_IE_MASK)); + reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET); + __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), + drvdata->base_addr + XEL_RSR_OFFSET); /* Disable the Rx interrupts for the second buffer * if configured in HW */ if (drvdata->rx_ping_pong != 0) { - reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + + reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET); - out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET + - XEL_RSR_OFFSET, - reg_data & (~XEL_RSR_RECV_IE_MASK)); + __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK), + drvdata->base_addr + XEL_BUFFER_OFFSET + + XEL_RSR_OFFSET); } } @@ -351,7 +349,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, byte_count = ETH_FRAME_LEN; /* Check if the expected buffer is available */ - reg_data = in_be32(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) == 0) { @@ -364,7 +362,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, addr = (void __iomem __force *)((u32 __force)addr ^ XEL_BUFFER_OFFSET); - reg_data = in_be32(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK)) != 0) @@ -375,15 +373,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data, /* Write the frame to the buffer */ xemaclite_aligned_write(data, (u32 __force *) addr, byte_count); - out_be32(addr + XEL_TPLR_OFFSET, (byte_count & XEL_TPLR_LENGTH_MASK)); + __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK), + addr + XEL_TPLR_OFFSET); /* Update the Tx Status Register to indicate that there is a * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which * is used by the interrupt handler to check whether a frame * has been transmitted */ - reg_data = in_be32(addr + XEL_TSR_OFFSET); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK); - out_be32(addr + XEL_TSR_OFFSET, reg_data); + __raw_writel(reg_data, addr + XEL_TSR_OFFSET); return 0; } @@ -408,7 +407,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use); /* Verify which buffer has valid data */ - reg_data = in_be32(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) { if (drvdata->rx_ping_pong != 0) @@ -425,14 +424,14 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) return 0; /* No data was available */ /* Verify that buffer has valid data */ - reg_data = in_be32(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); if ((reg_data & XEL_RSR_RECV_DONE_MASK) != XEL_RSR_RECV_DONE_MASK) return 0; /* No data was available */ } /* Get the protocol type of the ethernet frame that arrived */ - proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET + + proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & XEL_RPLR_LENGTH_MASK); @@ -441,7 +440,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) { if (proto_type == ETH_P_IP) { - length = ((ntohl(in_be32(addr + + length = ((ntohl(__raw_readl(addr + XEL_HEADER_IP_LENGTH_OFFSET + XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) & @@ -463,9 +462,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) data, length); /* Acknowledge the frame */ - reg_data = in_be32(addr + XEL_RSR_OFFSET); + reg_data = __raw_readl(addr + XEL_RSR_OFFSET); reg_data &= ~XEL_RSR_RECV_DONE_MASK; - out_be32(addr + XEL_RSR_OFFSET, reg_data); + __raw_writel(reg_data, addr + XEL_RSR_OFFSET); return length; } @@ -492,14 +491,14 @@ static void xemaclite_update_address(struct net_local *drvdata, xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN); - out_be32(addr + XEL_TPLR_OFFSET, ETH_ALEN); + __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET); /* Update the MAC address in the EmacLite */ - reg_data = in_be32(addr + XEL_TSR_OFFSET); - out_be32(addr + XEL_TSR_OFFSET, reg_data | XEL_TSR_PROG_MAC_ADDR); + reg_data = __raw_readl(addr + XEL_TSR_OFFSET); + __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET); /* Wait for EmacLite to finish with the MAC address update */ - while ((in_be32(addr + XEL_TSR_OFFSET) & + while ((__raw_readl(addr + XEL_TSR_OFFSET) & XEL_TSR_PROG_MAC_ADDR) != 0) ; } @@ -669,31 +668,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id) u32 tx_status; /* Check if there is Rx Data available */ - if ((in_be32(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) || - (in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) + if ((__raw_readl(base_addr + XEL_RSR_OFFSET) & + XEL_RSR_RECV_DONE_MASK) || + (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK)) xemaclite_rx_handler(dev); /* Check if the Transmission for the first buffer is completed */ - tx_status = in_be32(base_addr + XEL_TSR_OFFSET); + tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET); if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; - out_be32(base_addr + XEL_TSR_OFFSET, tx_status); + __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET); tx_complete = true; } /* Check if the Transmission for the second buffer is completed */ - tx_status = in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); + tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) && (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) { tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK; - out_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, - tx_status); + __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET + + XEL_TSR_OFFSET); tx_complete = true; } @@ -726,7 +726,7 @@ static int xemaclite_mdio_wait(struct net_local *lp) /* wait for the MDIO interface to not be busy or timeout after some time. */ - while (in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET) & + while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) & XEL_MDIOCTRL_MDIOSTS_MASK) { if (end - jiffies <= 0) { WARN_ON(1); @@ -762,17 +762,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg) * MDIO Address register. Set the Status bit in the MDIO Control * register to start a MDIO read transaction. */ - ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET); - out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET, - XEL_MDIOADDR_OP_MASK | - ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg)); - out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, - ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK); + ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); + __raw_writel(XEL_MDIOADDR_OP_MASK | + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), + lp->base_addr + XEL_MDIOADDR_OFFSET); + __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); if (xemaclite_mdio_wait(lp)) return -ETIMEDOUT; - rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET); + rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET); dev_dbg(&lp->ndev->dev, "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n", @@ -809,13 +809,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, * Data register. Finally, set the Status bit in the MDIO Control * register to start a MDIO write transaction. */ - ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET); - out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET, - ~XEL_MDIOADDR_OP_MASK & - ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg)); - out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val); - out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, - ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK); + ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET); + __raw_writel(~XEL_MDIOADDR_OP_MASK & + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg), + lp->base_addr + XEL_MDIOADDR_OFFSET); + __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET); + __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); return 0; } @@ -872,8 +872,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) /* Enable the MDIO bus by asserting the enable bit in MDIO Control * register. */ - out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, - XEL_MDIOCTRL_MDIOEN_MASK); + __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, + lp->base_addr + XEL_MDIOCTRL_OFFSET); bus = mdiobus_alloc(); if (!bus) { @@ -1197,8 +1197,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) dev_warn(dev, "No MAC address found\n"); /* Clear the Tx CSR's in case this is a restart */ - out_be32(lp->base_addr + XEL_TSR_OFFSET, 0); - out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0); + __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET); + __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET); /* Set the MAC address in the EmacLite device */ xemaclite_update_address(lp, ndev->dev_addr); -- GitLab From 1156ee88dd3992bbacd5e4c659530f9d18c07378 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:07 +0000 Subject: [PATCH 0532/2900] net: emaclite: Enable emaclite for Xilinx Arm Zynq platform Enable emaclite for Xilinx ARM Zynq platform. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 122d60c0481b..7b90a5eba099 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_XILINX bool "Xilinx devices" default y - depends on PPC || PPC32 || MICROBLAZE + depends on PPC || PPC32 || MICROBLAZE || ARCH_ZYNQ ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from @@ -20,7 +20,7 @@ if NET_VENDOR_XILINX config XILINX_EMACLITE tristate "Xilinx 10/100 Ethernet Lite support" - depends on (PPC32 || MICROBLAZE) + depends on (PPC32 || MICROBLAZE || ARCH_ZYNQ) select PHYLIB ---help--- This driver supports the 10/100 Ethernet Lite from Xilinx. -- GitLab From 9e7c414350a6fa4e5f9b7e5f7e074fa75ba850c3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 00:28:08 +0000 Subject: [PATCH 0533/2900] net: emaclite: Update driver header Correct email address and years. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 9227ed7bce10..aa14d8adcecb 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -2,9 +2,9 @@ * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device. * * This is a new flat driver which is based on the original emac_lite - * driver from John Williams . + * driver from John Williams . * - * 2007-2009 (c) Xilinx, Inc. + * 2007 - 2013 (c) Xilinx, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the -- GitLab From cec753f5dd103fcfef28c1d1c942395000abe15e Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:43 +0000 Subject: [PATCH 0534/2900] net: mv643xx_eth: use phy_disconnect instead of phy_detach Using a separated mdio bus driver with mvmdio, phy_detach on network device removal will not stop the phy and finally lead to NULL pointer dereference in mvmdio due to non-existent network device. Use phy_disconnect instead to properly stop phy device from accessing network device prior removal of the network device. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index afb8bcbe29f8..8124464af83c 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2805,7 +2805,7 @@ static int mv643xx_eth_remove(struct platform_device *pdev) unregister_netdev(mp->dev); if (mp->phy != NULL) - phy_detach(mp->phy); + phy_disconnect(mp->phy); cancel_work_sync(&mp->tx_timeout_task); if (!IS_ERR(mp->clk)) -- GitLab From 65a6f969fd1af549111b1667d9ca857e3cc649eb Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:44 +0000 Subject: [PATCH 0535/2900] net: mv643xx_eth: use managed devm_ioremap for port registers Make use of managed devm_ioremap and remove corresponding iounmap. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 8124464af83c..3417847b8485 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2470,7 +2470,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (msp == NULL) return -ENOMEM; - msp->base = ioremap(res->start, resource_size(res)); + msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (msp->base == NULL) return -ENOMEM; @@ -2498,7 +2498,6 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) { struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); - iounmap(msp->base); if (!IS_ERR(msp->clk)) clk_disable_unprepare(msp->clk); -- GitLab From 5f292354e7ff69afbe9a272ef997b8f3edaf860a Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:45 +0000 Subject: [PATCH 0536/2900] net: mv643xx_eth: add phy_node to platform_data struct This adds a struct device_node pointer for a phy passed by phandle to mv643xx_eth node. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- include/linux/mv643xx_eth.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/mv643xx_eth.h b/include/linux/mv643xx_eth.h index 141d395bbb5f..6e8215b15998 100644 --- a/include/linux/mv643xx_eth.h +++ b/include/linux/mv643xx_eth.h @@ -30,6 +30,7 @@ struct mv643xx_eth_shared_platform_data { #define MV643XX_ETH_PHY_ADDR(x) (0x80 | (x)) #define MV643XX_ETH_PHY_NONE 0xff +struct device_node; struct mv643xx_eth_platform_data { /* * Pointer back to our parent instance, and our port number. @@ -41,6 +42,7 @@ struct mv643xx_eth_platform_data { * Whether a PHY is present, and if yes, at which address. */ int phy_addr; + struct device_node *phy_node; /* * Use this MAC address if it is valid, overriding the -- GitLab From cc9d459894b0927d3f9280b07b308cec2576ad80 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:46 +0000 Subject: [PATCH 0537/2900] net: mv643xx_eth: use of_phy_connect if phy_node present This connects to a phy node passed to the port device instead of probing the phy by phy_addr. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 25 ++++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 3417847b8485..4f17d398a8ae 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -60,6 +60,7 @@ #include #include #include +#include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.4"; @@ -2715,17 +2716,27 @@ static int mv643xx_eth_probe(struct platform_device *pdev) netif_set_real_num_tx_queues(dev, mp->txq_count); netif_set_real_num_rx_queues(dev, mp->rxq_count); - if (pd->phy_addr != MV643XX_ETH_PHY_NONE) { + err = 0; + if (pd->phy_node) { + mp->phy = of_phy_connect(mp->dev, pd->phy_node, + mv643xx_eth_adjust_link, 0, + PHY_INTERFACE_MODE_GMII); + if (!mp->phy) + err = -ENODEV; + } else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) { mp->phy = phy_scan(mp, pd->phy_addr); - if (IS_ERR(mp->phy)) { + if (IS_ERR(mp->phy)) err = PTR_ERR(mp->phy); - if (err == -ENODEV) - err = -EPROBE_DEFER; - goto out; - } - phy_init(mp, pd->speed, pd->duplex); + else + phy_init(mp, pd->speed, pd->duplex); } + if (err == -ENODEV) { + err = -EPROBE_DEFER; + goto out; + } + if (err) + goto out; SET_ETHTOOL_OPS(dev, &mv643xx_eth_ethtool_ops); -- GitLab From cb85215ffc34479188d0ec25a56352f05ad672ce Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:47 +0000 Subject: [PATCH 0538/2900] net: mv643xx_eth: proper initialization for Kirkwood SoCs Ethernet controllers found on Kirkwood SoCs not only suffer from loosing MAC address register contents on clock gating but also some important registers are reset to values that would break ethernet. This patch clears the CLK125_BYPASS_EN bit for DT enabled Kirkwood only by using of_device_is_compatible() instead of #ifdefs. Non-DT Kirkwood is not affected as it installs a clock gating workaround because of the MAC address issue above. Other Orion SoCs do not suffer from register reset, do not have the bit in question, or do not have the register at all. Moreover, system controllers on PPC using this driver should also be protected from clearing that bit. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 4f17d398a8ae..1b31d752ff90 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -116,6 +116,8 @@ static char mv643xx_eth_driver_version[] = "1.4"; #define LINK_UP 0x00000002 #define TXQ_COMMAND 0x0048 #define TXQ_FIX_PRIO_CONF 0x004c +#define PORT_SERIAL_CONTROL1 0x004c +#define CLK125_BYPASS_EN 0x00000010 #define TX_BW_RATE 0x0050 #define TX_BW_MTU 0x0058 #define TX_BW_BURST 0x005c @@ -2701,6 +2703,15 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->dev = dev; + /* Kirkwood resets some registers on gated clocks. Especially + * CLK125_BYPASS_EN must be cleared but is not available on + * all other SoCs/System Controllers using this driver. + */ + if (of_device_is_compatible(pdev->dev.of_node, + "marvell,kirkwood-eth-port")) + wrlp(mp, PORT_SERIAL_CONTROL1, + rdlp(mp, PORT_SERIAL_CONTROL1) & ~CLK125_BYPASS_EN); + /* * Start with a default rate, and if there is a clock, allow * it to override the default. -- GitLab From 76723bca2802eb80990a5fefa179662e2e561d66 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Wed, 29 May 2013 09:32:48 +0000 Subject: [PATCH 0539/2900] net: mv643xx_eth: add DT parsing support This adds device tree parsing support for the shared driver of mv643xx_eth. As the bindings are slightly different from current PPC bindings new binding documentation is also added. Following PPC-style device setup, the shared driver now also adds port platform_devices and sets up port platform_data. Signed-off-by: Sebastian Hesselbarth Signed-off-by: David S. Miller --- .../bindings/net/marvell-orion-net.txt | 85 ++++++++++ drivers/net/ethernet/marvell/mv643xx_eth.c | 153 +++++++++++++++++- 2 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/marvell-orion-net.txt diff --git a/Documentation/devicetree/bindings/net/marvell-orion-net.txt b/Documentation/devicetree/bindings/net/marvell-orion-net.txt new file mode 100644 index 000000000000..a73b79f227e1 --- /dev/null +++ b/Documentation/devicetree/bindings/net/marvell-orion-net.txt @@ -0,0 +1,85 @@ +Marvell Orion/Discovery ethernet controller +============================================= + +The Marvell Discovery ethernet controller can be found on Marvell Orion SoCs +(Kirkwood, Dove, Orion5x, and Discovery Innovation) and as part of Marvell +Discovery system controller chips (mv64[345]60). + +The Discovery ethernet controller is described with two levels of nodes. The +first level describes the ethernet controller itself and the second level +describes up to 3 ethernet port nodes within that controller. The reason for +the multiple levels is that the port registers are interleaved within a single +set of controller registers. Each port node describes port-specific properties. + +Note: The above separation is only true for Discovery system controllers. +For Orion SoCs we stick to the separation, although there each controller has +only one port associated. Multiple ports are implemented as multiple single-port +controllers. As Kirkwood has some issues with proper initialization after reset, +an extra compatible string is added for it. + +* Ethernet controller node + +Required controller properties: + - #address-cells: shall be 1. + - #size-cells: shall be 0. + - compatible: shall be one of "marvell,orion-eth", "marvell,kirkwood-eth". + - reg: address and length of the controller registers. + +Optional controller properties: + - clocks: phandle reference to the controller clock. + - marvell,tx-checksum-limit: max tx packet size for hardware checksum. + +* Ethernet port node + +Required port properties: + - device_type: shall be "network". + - compatible: shall be one of "marvell,orion-eth-port", + "marvell,kirkwood-eth-port". + - reg: port number relative to ethernet controller, shall be 0, 1, or 2. + - interrupts: port interrupt. + - local-mac-address: 6 bytes MAC address. + +Optional port properties: + - marvell,tx-queue-size: size of the transmit ring buffer. + - marvell,tx-sram-addr: address of transmit descriptor buffer located in SRAM. + - marvell,tx-sram-size: size of transmit descriptor buffer located in SRAM. + - marvell,rx-queue-size: size of the receive ring buffer. + - marvell,rx-sram-addr: address of receive descriptor buffer located in SRAM. + - marvell,rx-sram-size: size of receive descriptor buffer located in SRAM. + +and + + - phy-handle: phandle reference to ethernet PHY. + +or + + - speed: port speed if no PHY connected. + - duplex: port mode if no PHY connected. + +* Node example: + +mdio-bus { + ... + ethphy: ethernet-phy@8 { + device_type = "ethernet-phy"; + ... + }; +}; + +eth: ethernet-controller@72000 { + compatible = "marvell,orion-eth"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x72000 0x2000>; + clocks = <&gate_clk 2>; + marvell,tx-checksum-limit = <1600>; + + ethernet@0 { + device_type = "network"; + compatible = "marvell,orion-eth-port"; + reg = <0>; + interrupts = <29>; + phy-handle = <ðphy>; + local-mac-address = [00 00 00 00 00 00]; + }; +}; diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 1b31d752ff90..23ea7b6e23f1 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -60,6 +60,9 @@ #include #include #include +#include +#include +#include #include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; @@ -2453,13 +2456,148 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp) } } +#if defined(CONFIG_OF) +static const struct of_device_id mv643xx_eth_shared_ids[] = { + { .compatible = "marvell,orion-eth", }, + { .compatible = "marvell,kirkwood-eth", }, + { } +}; +MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids); +#endif + +#if defined(CONFIG_OF) && !defined(CONFIG_MV64X60) +#define mv643xx_eth_property(_np, _name, _v) \ + do { \ + u32 tmp; \ + if (!of_property_read_u32(_np, "marvell," _name, &tmp)) \ + _v = tmp; \ + } while (0) + +static struct platform_device *port_platdev[3]; + +static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, + struct device_node *pnp) +{ + struct platform_device *ppdev; + struct mv643xx_eth_platform_data ppd; + struct resource res; + const char *mac_addr; + int ret; + + memset(&ppd, 0, sizeof(ppd)); + ppd.shared = pdev; + + memset(&res, 0, sizeof(res)); + if (!of_irq_to_resource(pnp, 0, &res)) { + dev_err(&pdev->dev, "missing interrupt on %s\n", pnp->name); + return -EINVAL; + } + + if (of_property_read_u32(pnp, "reg", &ppd.port_number)) { + dev_err(&pdev->dev, "missing reg property on %s\n", pnp->name); + return -EINVAL; + } + + if (ppd.port_number >= 3) { + dev_err(&pdev->dev, "invalid reg property on %s\n", pnp->name); + return -EINVAL; + } + + mac_addr = of_get_mac_address(pnp); + if (mac_addr) + memcpy(ppd.mac_addr, mac_addr, 6); + + mv643xx_eth_property(pnp, "tx-queue-size", ppd.tx_queue_size); + mv643xx_eth_property(pnp, "tx-sram-addr", ppd.tx_sram_addr); + mv643xx_eth_property(pnp, "tx-sram-size", ppd.tx_sram_size); + mv643xx_eth_property(pnp, "rx-queue-size", ppd.rx_queue_size); + mv643xx_eth_property(pnp, "rx-sram-addr", ppd.rx_sram_addr); + mv643xx_eth_property(pnp, "rx-sram-size", ppd.rx_sram_size); + + ppd.phy_node = of_parse_phandle(pnp, "phy-handle", 0); + if (!ppd.phy_node) { + ppd.phy_addr = MV643XX_ETH_PHY_NONE; + of_property_read_u32(pnp, "speed", &ppd.speed); + of_property_read_u32(pnp, "duplex", &ppd.duplex); + } + + ppdev = platform_device_alloc(MV643XX_ETH_NAME, ppd.port_number); + if (!ppdev) + return -ENOMEM; + ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + ret = platform_device_add_resources(ppdev, &res, 1); + if (ret) + goto port_err; + + ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd)); + if (ret) + goto port_err; + + ret = platform_device_add(ppdev); + if (ret) + goto port_err; + + port_platdev[ppd.port_number] = ppdev; + + return 0; + +port_err: + platform_device_put(ppdev); + return ret; +} + +static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) +{ + struct mv643xx_eth_shared_platform_data *pd; + struct device_node *pnp, *np = pdev->dev.of_node; + int ret; + + /* bail out if not registered from DT */ + if (!np) + return 0; + + pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + pdev->dev.platform_data = pd; + + mv643xx_eth_property(np, "tx-checksum-limit", pd->tx_csum_limit); + + for_each_available_child_of_node(np, pnp) { + ret = mv643xx_eth_shared_of_add_port(pdev, pnp); + if (ret) + return ret; + } + return 0; +} + +static void mv643xx_eth_shared_of_remove(void) +{ + int n; + + for (n = 0; n < 3; n++) { + platform_device_del(port_platdev[n]); + port_platdev[n] = NULL; + } +} +#else +static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) +{ + return 0 +} + +#define mv643xx_eth_shared_of_remove() +#endif + static int mv643xx_eth_shared_probe(struct platform_device *pdev) { static int mv643xx_eth_version_printed; - struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; + struct mv643xx_eth_shared_platform_data *pd; struct mv643xx_eth_shared_private *msp; const struct mbus_dram_target_info *dram; struct resource *res; + int ret; if (!mv643xx_eth_version_printed++) pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n", @@ -2472,6 +2610,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL); if (msp == NULL) return -ENOMEM; + platform_set_drvdata(pdev, msp); msp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (msp->base == NULL) @@ -2488,12 +2627,15 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev) if (dram) mv643xx_eth_conf_mbus_windows(msp, dram); + ret = mv643xx_eth_shared_of_probe(pdev); + if (ret) + return ret; + pd = pdev->dev.platform_data; + msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ? pd->tx_csum_limit : 9 * 1024; infer_hw_params(msp); - platform_set_drvdata(pdev, msp); - return 0; } @@ -2501,9 +2643,9 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) { struct mv643xx_eth_shared_private *msp = platform_get_drvdata(pdev); + mv643xx_eth_shared_of_remove(); if (!IS_ERR(msp->clk)) clk_disable_unprepare(msp->clk); - return 0; } @@ -2513,6 +2655,7 @@ static struct platform_driver mv643xx_eth_shared_driver = { .driver = { .name = MV643XX_ETH_SHARED_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mv643xx_eth_shared_ids), }, }; @@ -2721,6 +2864,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev) if (!IS_ERR(mp->clk)) { clk_prepare_enable(mp->clk); mp->t_clk = clk_get_rate(mp->clk); + } else if (!IS_ERR(mp->shared->clk)) { + mp->t_clk = clk_get_rate(mp->shared->clk); } set_params(mp, pd); -- GitLab From 6804973ffb4288bba14d53223e2fbb2bbd1d2e1b Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 29 May 2013 14:20:11 +0000 Subject: [PATCH 0540/2900] tcp: consolidate PRR packet accounting This patch series fixes an undo bug in fast recovery: the sender mistakenly undos the cwnd too early but continues fast retransmits until all pending data are acked. This also multiplies the SNMP stat PARTIALUNDO events by the degree of the network reordering. The first patch prepares the fix by consolidating the accounting of newly_acked_sacked in tcp_cwnd_reduction(), instead of updating newly_acked_sacked everytime sacked_out is adjusted. Also pass acked and prior_unsacked as const type because they are readonly in the rest of recovery processing. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 45 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9579e1a5a144..86b5fa72ff9e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2430,12 +2430,14 @@ static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh) TCP_ECN_queue_cwr(tp); } -static void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked, +static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, int fast_rexmit) { struct tcp_sock *tp = tcp_sk(sk); int sndcnt = 0; int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp); + int newly_acked_sacked = prior_unsacked - + (tp->packets_out - tp->sacked_out); tp->prr_delivered += newly_acked_sacked; if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) { @@ -2492,7 +2494,7 @@ static void tcp_try_keep_open(struct sock *sk) } } -static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked) +static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked) { struct tcp_sock *tp = tcp_sk(sk); @@ -2509,7 +2511,7 @@ static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked) if (inet_csk(sk)->icsk_ca_state != TCP_CA_Open) tcp_moderate_cwnd(tp); } else { - tcp_cwnd_reduction(sk, newly_acked_sacked, 0); + tcp_cwnd_reduction(sk, prior_unsacked, 0); } } @@ -2678,15 +2680,14 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) * It does _not_ decide what to send, it is made in function * tcp_xmit_retransmit_queue(). */ -static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int prior_sacked, int prior_packets, +static void tcp_fastretrans_alert(struct sock *sk, const int acked, + const int prior_unsacked, bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); - int newly_acked_sacked = 0; int fast_rexmit = 0; if (WARN_ON(!tp->packets_out && tp->sacked_out)) @@ -2739,9 +2740,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (tcp_is_reno(tp) && is_dupack) tcp_add_reno_sack(sk); } else - do_lost = tcp_try_undo_partial(sk, pkts_acked); - newly_acked_sacked = prior_packets - tp->packets_out + - tp->sacked_out - prior_sacked; + do_lost = tcp_try_undo_partial(sk, acked); break; case TCP_CA_Loss: tcp_process_loss(sk, flag, is_dupack); @@ -2755,14 +2754,12 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } - newly_acked_sacked = prior_packets - tp->packets_out + - tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); if (!tcp_time_to_recover(sk, flag)) { - tcp_try_to_open(sk, flag, newly_acked_sacked); + tcp_try_to_open(sk, flag, prior_unsacked); return; } @@ -2784,7 +2781,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (do_lost) tcp_update_scoreboard(sk, fast_rexmit); - tcp_cwnd_reduction(sk, newly_acked_sacked, fast_rexmit); + tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit); tcp_xmit_retransmit_queue(sk); } @@ -3268,9 +3265,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) u32 prior_in_flight; u32 prior_fackets; int prior_packets = tp->packets_out; - int prior_sacked = tp->sacked_out; - int pkts_acked = 0; - int previous_packets_out = 0; + const int prior_unsacked = tp->packets_out - tp->sacked_out; + int acked = 0; /* Number of packets newly acked */ /* If the ack is older than previous acks * then we can probably ignore it. @@ -3345,18 +3341,17 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) goto no_queue; /* See if we can take anything off of the retransmit queue. */ - previous_packets_out = tp->packets_out; + acked = tp->packets_out; flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); - - pkts_acked = previous_packets_out - tp->packets_out; + acked -= tp->packets_out; if (tcp_ack_is_dubious(sk, flag)) { /* Advance CWND, if state allows this. */ if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - prior_packets, is_dupack, flag); + tcp_fastretrans_alert(sk, acked, prior_unsacked, + is_dupack, flag); } else { if (flag & FLAG_DATA_ACKED) tcp_cong_avoid(sk, ack, prior_in_flight); @@ -3378,8 +3373,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - prior_packets, is_dupack, flag); + tcp_fastretrans_alert(sk, acked, prior_unsacked, + is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than * it needs to be for normal retransmission. @@ -3401,8 +3396,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) */ if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); - tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - prior_packets, is_dupack, flag); + tcp_fastretrans_alert(sk, acked, prior_unsacked, + is_dupack, flag); } SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); -- GitLab From 6a63df46a7363833a0dc0c431027f522b3487972 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 29 May 2013 14:20:12 +0000 Subject: [PATCH 0541/2900] tcp: refactor undo functions Refactor and relocate various functions or variables to prepare the undo fix. Remove some unused function arguments. Rename tcp_undo_cwr to tcp_undo_cwnd_reduction to be consistent with the rest of CWR related function names. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 97 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 86b5fa72ff9e..fcb668d1860d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2243,10 +2243,23 @@ static void DBGUNDO(struct sock *sk, const char *msg) #define DBGUNDO(x...) do { } while (0) #endif -static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh) +static void tcp_undo_cwnd_reduction(struct sock *sk, const bool undo_ssthresh, + bool unmark_loss) { struct tcp_sock *tp = tcp_sk(sk); + if (unmark_loss) { + struct sk_buff *skb; + + tcp_for_write_queue(skb, sk) { + if (skb == tcp_send_head(sk)) + break; + TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; + } + tp->lost_out = 0; + tcp_clear_all_retrans_hints(tp); + } + if (tp->prior_ssthresh) { const struct inet_connection_sock *icsk = inet_csk(sk); @@ -2263,6 +2276,9 @@ static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh) tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); } tp->snd_cwnd_stamp = tcp_time_stamp; + + if (undo_ssthresh) + tp->undo_marker = 0; } static inline bool tcp_may_undo(const struct tcp_sock *tp) @@ -2282,14 +2298,13 @@ static bool tcp_try_undo_recovery(struct sock *sk) * or our original transmission succeeded. */ DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans"); - tcp_undo_cwr(sk, true); + tcp_undo_cwnd_reduction(sk, true, false); if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) mib_idx = LINUX_MIB_TCPLOSSUNDO; else mib_idx = LINUX_MIB_TCPFULLUNDO; NET_INC_STATS_BH(sock_net(sk), mib_idx); - tp->undo_marker = 0; } if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) { /* Hold old state until something *above* high_seq @@ -2309,8 +2324,7 @@ static void tcp_try_undo_dsack(struct sock *sk) if (tp->undo_marker && !tp->undo_retrans) { DBGUNDO(sk, "D-SACK"); - tcp_undo_cwr(sk, true); - tp->undo_marker = 0; + tcp_undo_cwnd_reduction(sk, true, false); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); } } @@ -2344,60 +2358,20 @@ static bool tcp_any_retrans_done(const struct sock *sk) return false; } -/* Undo during fast recovery after partial ACK. */ - -static int tcp_try_undo_partial(struct sock *sk, int acked) -{ - struct tcp_sock *tp = tcp_sk(sk); - /* Partial ACK arrived. Force Hoe's retransmit. */ - int failed = tcp_is_reno(tp) || (tcp_fackets_out(tp) > tp->reordering); - - if (tcp_may_undo(tp)) { - /* Plain luck! Hole if filled with delayed - * packet, rather than with a retransmit. - */ - if (!tcp_any_retrans_done(sk)) - tp->retrans_stamp = 0; - - tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); - - DBGUNDO(sk, "Hoe"); - tcp_undo_cwr(sk, false); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); - - /* So... Do not make Hoe's retransmit yet. - * If the first packet was delayed, the rest - * ones are most probably delayed as well. - */ - failed = 0; - } - return failed; -} - /* Undo during loss recovery after partial ACK or using F-RTO. */ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) { struct tcp_sock *tp = tcp_sk(sk); if (frto_undo || tcp_may_undo(tp)) { - struct sk_buff *skb; - tcp_for_write_queue(skb, sk) { - if (skb == tcp_send_head(sk)) - break; - TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; - } - - tcp_clear_all_retrans_hints(tp); + tcp_undo_cwnd_reduction(sk, true, true); DBGUNDO(sk, "partial loss"); - tp->lost_out = 0; - tcp_undo_cwr(sk, true); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); if (frto_undo) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSPURIOUSRTOS); inet_csk(sk)->icsk_retransmits = 0; - tp->undo_marker = 0; if (frto_undo || tcp_is_sack(tp)) tcp_set_ca_state(sk, TCP_CA_Open); return true; @@ -2669,6 +2643,35 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) tcp_xmit_retransmit_queue(sk); } +/* Undo during fast recovery after partial ACK. */ +static bool tcp_try_undo_partial(struct sock *sk, int acked) +{ + struct tcp_sock *tp = tcp_sk(sk); + /* Partial ACK arrived. Force Hoe's retransmit. */ + bool failed = tcp_is_reno(tp) || (tcp_fackets_out(tp) > tp->reordering); + + if (tcp_may_undo(tp)) { + /* Plain luck! Hole if filled with delayed + * packet, rather than with a retransmit. + */ + if (!tcp_any_retrans_done(sk)) + tp->retrans_stamp = 0; + + tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); + + DBGUNDO(sk, "Hoe"); + tcp_undo_cwnd_reduction(sk, false, false); + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); + + /* So... Do not make Hoe's retransmit yet. + * If the first packet was delayed, the rest + * ones are most probably delayed as well. + */ + failed = false; + } + return failed; +} + /* Process an event, which can update packets-in-flight not trivially. * Main goal of this function is to calculate new estimate for left_out, * taking into account both packets sitting in receiver's buffer and @@ -2686,7 +2689,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); - int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && + bool do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); int fast_rexmit = 0; -- GitLab From 7026b912f97d912476dff5465ed9a127be094208 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 29 May 2013 14:20:13 +0000 Subject: [PATCH 0542/2900] tcp: fix undo on partial ack in recovery Upon detecting spurious fast retransmit via timestamps during recovery, use PRR to clock out new data packet instead of retransmission. Once all retransmission are proven spurious, the sender then reverts the cwnd reduction and congestion state to open or disorder. The current code does the opposite: it undoes cwnd as soon as any retransmission is spurious and continues to retransmit until all data are acked. This nullifies the point to undo the cwnd because the sender is still retransmistting spuriously. This patch fixes it. The undo_ssthresh argument of tcp_undo_cwnd_reductiuon() is no longer needed and is removed. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 59 +++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fcb668d1860d..c35b22751982 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2243,8 +2243,7 @@ static void DBGUNDO(struct sock *sk, const char *msg) #define DBGUNDO(x...) do { } while (0) #endif -static void tcp_undo_cwnd_reduction(struct sock *sk, const bool undo_ssthresh, - bool unmark_loss) +static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss) { struct tcp_sock *tp = tcp_sk(sk); @@ -2268,7 +2267,7 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, const bool undo_ssthresh, else tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1); - if (undo_ssthresh && tp->prior_ssthresh > tp->snd_ssthresh) { + if (tp->prior_ssthresh > tp->snd_ssthresh) { tp->snd_ssthresh = tp->prior_ssthresh; TCP_ECN_withdraw_cwr(tp); } @@ -2276,9 +2275,7 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, const bool undo_ssthresh, tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); } tp->snd_cwnd_stamp = tcp_time_stamp; - - if (undo_ssthresh) - tp->undo_marker = 0; + tp->undo_marker = 0; } static inline bool tcp_may_undo(const struct tcp_sock *tp) @@ -2298,7 +2295,7 @@ static bool tcp_try_undo_recovery(struct sock *sk) * or our original transmission succeeded. */ DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans"); - tcp_undo_cwnd_reduction(sk, true, false); + tcp_undo_cwnd_reduction(sk, false); if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) mib_idx = LINUX_MIB_TCPLOSSUNDO; else @@ -2324,7 +2321,7 @@ static void tcp_try_undo_dsack(struct sock *sk) if (tp->undo_marker && !tp->undo_retrans) { DBGUNDO(sk, "D-SACK"); - tcp_undo_cwnd_reduction(sk, true, false); + tcp_undo_cwnd_reduction(sk, false); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); } } @@ -2364,7 +2361,7 @@ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) struct tcp_sock *tp = tcp_sk(sk); if (frto_undo || tcp_may_undo(tp)) { - tcp_undo_cwnd_reduction(sk, true, true); + tcp_undo_cwnd_reduction(sk, true); DBGUNDO(sk, "partial loss"); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); @@ -2644,32 +2641,37 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) } /* Undo during fast recovery after partial ACK. */ -static bool tcp_try_undo_partial(struct sock *sk, int acked) +static bool tcp_try_undo_partial(struct sock *sk, const int acked, + const int prior_unsacked) { struct tcp_sock *tp = tcp_sk(sk); - /* Partial ACK arrived. Force Hoe's retransmit. */ - bool failed = tcp_is_reno(tp) || (tcp_fackets_out(tp) > tp->reordering); - if (tcp_may_undo(tp)) { + if (tp->undo_marker && tcp_packet_delayed(tp)) { /* Plain luck! Hole if filled with delayed * packet, rather than with a retransmit. */ + tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); + + /* We are getting evidence that the reordering degree is higher + * than we realized. If there are no retransmits out then we + * can undo. Otherwise we clock out new packets but do not + * mark more packets lost or retransmit more. + */ + if (tp->retrans_out) { + tcp_cwnd_reduction(sk, prior_unsacked, 0); + return true; + } + if (!tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; - tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); - - DBGUNDO(sk, "Hoe"); - tcp_undo_cwnd_reduction(sk, false, false); + DBGUNDO(sk, "partial recovery"); + tcp_undo_cwnd_reduction(sk, true); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); - - /* So... Do not make Hoe's retransmit yet. - * If the first packet was delayed, the rest - * ones are most probably delayed as well. - */ - failed = false; + tcp_try_keep_open(sk); + return true; } - return failed; + return false; } /* Process an event, which can update packets-in-flight not trivially. @@ -2742,8 +2744,13 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, if (!(flag & FLAG_SND_UNA_ADVANCED)) { if (tcp_is_reno(tp) && is_dupack) tcp_add_reno_sack(sk); - } else - do_lost = tcp_try_undo_partial(sk, acked); + } else { + if (tcp_try_undo_partial(sk, acked, prior_unsacked)) + return; + /* Partial ACK arrived. Force fast retransmit. */ + do_lost = tcp_is_reno(tp) || + tcp_fackets_out(tp) > tp->reordering; + } break; case TCP_CA_Loss: tcp_process_loss(sk, flag, is_dupack); -- GitLab From c7d9d6a185a7ea383b719b79c428d34ec1470275 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Wed, 29 May 2013 14:20:14 +0000 Subject: [PATCH 0543/2900] tcp: undo on DSACK during recovery If the receiver supports DSACK, sender can detect false recoveries and revert cwnd reductions triggered by either severe network reordering or concurrent reordering and loss event. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c35b22751982..907311c9a012 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2315,7 +2315,7 @@ static bool tcp_try_undo_recovery(struct sock *sk) } /* Try to undo cwnd reduction, because D-SACKs acked all retransmitted data */ -static void tcp_try_undo_dsack(struct sock *sk) +static bool tcp_try_undo_dsack(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); @@ -2323,7 +2323,9 @@ static void tcp_try_undo_dsack(struct sock *sk) DBGUNDO(sk, "D-SACK"); tcp_undo_cwnd_reduction(sk, false); NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); + return true; } + return false; } /* We can clear retrans_stamp when there are no retransmissions in the @@ -2751,6 +2753,10 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, do_lost = tcp_is_reno(tp) || tcp_fackets_out(tp) > tp->reordering; } + if (tcp_try_undo_dsack(sk)) { + tcp_try_keep_open(sk); + return; + } break; case TCP_CA_Loss: tcp_process_loss(sk, flag, is_dupack); -- GitLab From 2a8626d1efaf031a65157bc99a01bb93b52a92d7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 20:08:23 +0000 Subject: [PATCH 0544/2900] phy: Clean coding style in vitesse phy - Remove trailing white space - Remove spaces before tag - Fix comments Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/phy/vitesse.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 3492b5391273..d6e988f69a7d 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -44,12 +44,12 @@ #define MII_VSC8244_ISTAT_DUPLEX 0x1000 /* Vitesse Auxiliary Control/Status Register */ -#define MII_VSC8244_AUX_CONSTAT 0x1c -#define MII_VSC8244_AUXCONSTAT_INIT 0x0000 -#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 -#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 -#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 -#define MII_VSC8244_AUXCONSTAT_100 0x0008 +#define MII_VSC8244_AUX_CONSTAT 0x1c +#define MII_VSC8244_AUXCONSTAT_INIT 0x0000 +#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 +#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 +#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 +#define MII_VSC8244_AUXCONSTAT_100 0x0008 #define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */ #define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004 @@ -100,9 +100,8 @@ static int vsc824x_config_init(struct phy_device *phydev) static int vsc824x_ack_interrupt(struct phy_device *phydev) { int err = 0; - - /* - * Don't bother to ACK the interrupts if interrupts + + /* Don't bother to ACK the interrupts if interrupts * are disabled. The 824x cannot clear the interrupts * if they are disabled. */ @@ -122,8 +121,7 @@ static int vsc82xx_config_intr(struct phy_device *phydev) MII_VSC8244_IMASK_MASK : MII_VSC8221_IMASK_MASK); else { - /* - * The Vitesse PHY cannot clear the interrupt + /* The Vitesse PHY cannot clear the interrupt * once it has disabled them, so we clear them first */ err = phy_read(phydev, MII_VSC8244_ISTAT); @@ -146,7 +144,8 @@ static int vsc8221_config_init(struct phy_device *phydev) return err; /* Perhaps we should set EXT_CON1 based on the interface? - Options are 802.3Z SerDes or SGMII */ + * Options are 802.3Z SerDes or SGMII + */ } /* Vitesse 824x */ -- GitLab From 5a1cebd8f4371bf08bf20a4de5a28d2b3f03c17d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 20:08:24 +0000 Subject: [PATCH 0545/2900] phy: Add Vitesse 8211 phy ID Phy is compatible with Vitesse 8221. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/phy/vitesse.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index d6e988f69a7d..69b482bce7d2 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -56,6 +56,7 @@ #define PHY_ID_VSC8244 0x000fc6c0 #define PHY_ID_VSC8221 0x000fc550 +#define PHY_ID_VSC8211 0x000fc4b0 MODULE_DESCRIPTION("Vitesse PHY driver"); MODULE_AUTHOR("Kriston Carson"); @@ -175,6 +176,19 @@ static struct phy_driver vsc82xx_driver[] = { .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, .driver = { .owner = THIS_MODULE,}, +}, { + /* Vitesse 8211 */ + .phy_id = PHY_ID_VSC8211, + .phy_id_mask = 0x000ffff0, + .name = "Vitesse VSC8211", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc8221_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc82xx_config_intr, + .driver = { .owner = THIS_MODULE,}, } }; static int __init vsc82xx_init(void) @@ -195,6 +209,7 @@ module_exit(vsc82xx_exit); static struct mdio_device_id __maybe_unused vitesse_tbl[] = { { PHY_ID_VSC8244, 0x000fffc0 }, { PHY_ID_VSC8221, 0x000ffff0 }, + { PHY_ID_VSC8211, 0x000ffff0 }, { } }; -- GitLab From f5e1cabf46ed21c736453e38d6ddeadb926fbfea Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 20:08:25 +0000 Subject: [PATCH 0546/2900] phy: Use macros instead of hardcoded values in marvell phy driver Use macros from linux/marvell_phy.h instead of duplicate magic phy ID in the driver. Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 202fe1ff1987..371353c81f3c 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -958,15 +958,15 @@ module_init(marvell_init); module_exit(marvell_exit); static struct mdio_device_id __maybe_unused marvell_tbl[] = { - { 0x01410c60, 0xfffffff0 }, - { 0x01410c90, 0xfffffff0 }, - { 0x01410cc0, 0xfffffff0 }, - { 0x01410e10, 0xfffffff0 }, - { 0x01410cb0, 0xfffffff0 }, - { 0x01410cd0, 0xfffffff0 }, - { 0x01410e50, 0xfffffff0 }, - { 0x01410e30, 0xfffffff0 }, - { 0x01410e90, 0xfffffff0 }, + { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, { } }; -- GitLab From 3da09a5154edb92fe74c266a4fa900bcbed6d44c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 20:08:26 +0000 Subject: [PATCH 0547/2900] phy: Add Marvell 88E1116R phy ID This phy is on Xilinx ZC702 zynq development board. Signed-off-by: Anirudha Sarangi Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 65 +++++++++++++++++++++++++++++++++++++ include/linux/marvell_phy.h | 1 + 2 files changed, 66 insertions(+) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 371353c81f3c..df5a9f6d2864 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -116,6 +116,8 @@ #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 #define MII_M1011_PHY_STATUS_LINK 0x0400 +#define MII_M1116R_CONTROL_REG_MAC 21 + MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); @@ -372,6 +374,55 @@ static int m88e1318_config_aneg(struct phy_device *phydev) return m88e1121_config_aneg(phydev); } +static int m88e1116r_config_init(struct phy_device *phydev) +{ + int temp; + int err; + + temp = phy_read(phydev, MII_BMCR); + temp |= BMCR_RESET; + err = phy_write(phydev, MII_BMCR, temp); + if (err < 0) + return err; + + mdelay(500); + + err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); + if (err < 0) + return err; + + temp = phy_read(phydev, MII_M1011_PHY_SCR); + temp |= (7 << 12); /* max number of gigabit attempts */ + temp |= (1 << 11); /* enable downshift */ + temp |= MII_M1011_PHY_SCR_AUTO_CROSS; + err = phy_write(phydev, MII_M1011_PHY_SCR, temp); + if (err < 0) + return err; + + err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 2); + if (err < 0) + return err; + temp = phy_read(phydev, MII_M1116R_CONTROL_REG_MAC); + temp |= (1 << 5); + temp |= (1 << 4); + err = phy_write(phydev, MII_M1116R_CONTROL_REG_MAC, temp); + if (err < 0) + return err; + err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); + if (err < 0) + return err; + + temp = phy_read(phydev, MII_BMCR); + temp |= BMCR_RESET; + err = phy_write(phydev, MII_BMCR, temp); + if (err < 0) + return err; + + mdelay(500); + + return 0; +} + static int m88e1111_config_init(struct phy_device *phydev) { int err; @@ -940,6 +991,19 @@ static struct phy_driver marvell_drivers[] = { .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E1116R, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1116R", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1116r_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = { .owner = THIS_MODULE }, + }, }; static int __init marvell_init(void) @@ -967,6 +1031,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, { } }; diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index dd3c34ebca9a..ec41025cb86e 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -14,6 +14,7 @@ #define MARVELL_PHY_ID_88E1149R 0x01410e50 #define MARVELL_PHY_ID_88E1240 0x01410e30 #define MARVELL_PHY_ID_88E1318S 0x01410e90 +#define MARVELL_PHY_ID_88E1116R 0x01410e40 /* struct phy_device dev_flags definitions */ #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001 -- GitLab From 10e24caa98b6dd0d3d8b783453d5c07aa4e9af0c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 30 May 2013 20:08:27 +0000 Subject: [PATCH 0548/2900] phy: Add Marvell 88E1510 phy ID Add support for this new phy ID. Signed-off-by: Rick Hoover Signed-off-by: Steven Wang Signed-off-by: Lars-Peter Clausen Signed-off-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 25 +++++++++++++++++++++++++ include/linux/marvell_phy.h | 1 + 2 files changed, 26 insertions(+) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index df5a9f6d2864..2e91477362d4 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -374,6 +374,17 @@ static int m88e1318_config_aneg(struct phy_device *phydev) return m88e1121_config_aneg(phydev); } +static int m88e1510_config_aneg(struct phy_device *phydev) +{ + int err; + + err = m88e1318_config_aneg(phydev); + if (err < 0) + return err; + + return marvell_of_reg_init(phydev); +} + static int m88e1116r_config_init(struct phy_device *phydev) { int temp; @@ -1004,6 +1015,19 @@ static struct phy_driver marvell_drivers[] = { .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E1510, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1510", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &m88e1510_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .driver = { .owner = THIS_MODULE }, + }, }; static int __init marvell_init(void) @@ -1032,6 +1056,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK }, { } }; diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index ec41025cb86e..8e9a029e093d 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -15,6 +15,7 @@ #define MARVELL_PHY_ID_88E1240 0x01410e30 #define MARVELL_PHY_ID_88E1318S 0x01410e90 #define MARVELL_PHY_ID_88E1116R 0x01410e40 +#define MARVELL_PHY_ID_88E1510 0x01410dd0 /* struct phy_device dev_flags definitions */ #define MARVELL_PHY_M1145_FLAGS_RESISTANCE 0x00000001 -- GitLab From 3c15a0fb61e743bc72e2d7e01e968f0247a8be8b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 May 2013 10:17:19 +0200 Subject: [PATCH 0549/2900] Revert "iwlwifi: mvm: remove P2P_DEVICE support" This reverts commit eebfc9394ee31b3ef162692c0cd483c1318a4395. This wasn't intended to be included here, my mistake. I accidentally merged a mac80211 fixes tree here that had this change, when it wasn't even intended to be there. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 11dc7df8bdf9..dd158ec571fb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -84,6 +84,15 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP), }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), + }, }; static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { @@ -152,7 +161,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->chanctx_data_size = sizeof(struct iwl_mvm_phy_ctxt); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_DEVICE); hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | -- GitLab From a8cd57b3042446250f19daf98d120802dffc768d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 May 2013 10:17:49 +0200 Subject: [PATCH 0550/2900] Revert "mac80211_hwsim: remove P2P_DEVICE support" This reverts commit e3ee68b7b049c5bbfcb78a179c00c373a38ed58c. This wasn't intended to be included here, my mistake. I accidentally merged a mac80211 fixes tree here that had this change, when it wasn't even intended to be there. Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 69bbf6fdd2d3..cb34c7895f2a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2169,6 +2169,7 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { #endif BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }, }; static struct ieee80211_iface_combination hwsim_if_comb = { @@ -2294,7 +2295,8 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_P2P_DEVICE); hw->flags = IEEE80211_HW_MFP_CAPABLE | IEEE80211_HW_SIGNAL_DBM | -- GitLab From b431becc35a9d25c4a0220fa2c4cf9b9f1dc8bac Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 30 May 2013 00:22:43 +0000 Subject: [PATCH 0551/2900] net, jme: remove redundant D0 power state set pci_enable_device() will set device power state to D0, so it's no need to do it again in jme_init_one(). Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index 070a6f1a0577..7fbe6abf6054 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -3148,7 +3148,6 @@ jme_init_one(struct pci_dev *pdev, jme->mii_if.mdio_write = jme_mdio_write; jme_clear_pm(jme); - pci_set_power_state(jme->pdev, PCI_D0); device_set_wakeup_enable(&pdev->dev, true); jme_set_phyfifo_5level(jme); -- GitLab From e4afed373eefb91a80e69075fbcd5438c2d36283 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 30 May 2013 00:26:09 +0000 Subject: [PATCH 0552/2900] qlcnic: remove redundant D0 power state set pci_enable_device() will set device power state to D0, so it's no need to do it again in qlcnic_attach_func(). Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 6bb56d43614b..0ae88355ad51 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -3232,7 +3232,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev) if (err) return err; - pci_set_power_state(pdev, PCI_D0); pci_set_master(pdev); pci_restore_state(pdev); -- GitLab From 311503bb2119788ac88c406e0893351a2bb0705e Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 30 May 2013 00:27:06 +0000 Subject: [PATCH 0553/2900] tulip: remove redundant D0 power state set pci_enable_device() will set device power state to D0, so it's no need to do it again in tulip_init_one(). Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/dec/tulip/tulip_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 1e9443d9fb57..c94152f1c6be 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -1410,12 +1410,6 @@ static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return i; } - /* The chip will fail to enter a low-power state later unless - * first explicitly commanded into D0 */ - if (pci_set_power_state(pdev, PCI_D0)) { - pr_notice("Failed to set power state to D0\n"); - } - irq = pdev->irq; /* alloc_etherdev ensures aligned and zeroed private structures */ -- GitLab From aef6de511a2aea78098e0d507ad7280d38b6b019 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 30 May 2013 20:36:11 +0000 Subject: [PATCH 0554/2900] sctp: Correct byte order of access to skb->{network, transport}_header Corrects an byte order conflict introduced by "sctp: Correct access to skb->{network, transport}_header". All the values in question are host byte order. Reported-by: Ben Hutchings Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/sctp/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/input.c b/net/sctp/input.c index e328fe8f93f4..6533d81a638d 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) struct sctp_association *asoc = NULL; struct sctp_transport *transport; struct inet_sock *inet; - __be16 saveip, savesctp; + __u16 saveip, savesctp; int err; struct net *net = dev_net(skb->dev); -- GitLab From 0e748234293f5f2caa8dbd152caba5efb754c707 Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Wed, 29 May 2013 13:50:05 -0700 Subject: [PATCH 0555/2900] mmc: sdhci: Add size for caller in init+register Add a param to allow users of sdhci_pltfm to allocate private space in calls to sdhci_pltfm_init+sdhci_pltfm_register. This is implemented in the same way as sdhci does for its users. None of the users have been migrated yet and are passing in zero to retain their private allocation. - todo: migrate clients to using allocation this way - todo: remove priv variable once migration is complete Also removed unused variable in sdhci_pltfm_init fn Signed-off-by: Christian Daudt Acked-by: Arnd Bergmann Reviewed-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-bcm2835.c | 2 +- drivers/mmc/host/sdhci-cns3xxx.c | 2 +- drivers/mmc/host/sdhci-dove.c | 2 +- drivers/mmc/host/sdhci-esdhc-imx.c | 2 +- drivers/mmc/host/sdhci-of-esdhc.c | 2 +- drivers/mmc/host/sdhci-of-hlwd.c | 2 +- drivers/mmc/host/sdhci-pltfm.c | 17 +++++++++-------- drivers/mmc/host/sdhci-pltfm.h | 13 +++++++++++-- drivers/mmc/host/sdhci-pxav2.c | 2 +- drivers/mmc/host/sdhci-pxav3.c | 2 +- drivers/mmc/host/sdhci-tegra.c | 2 +- 11 files changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index d49bc958c8ba..0584a1c788b8 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c @@ -148,7 +148,7 @@ static int bcm2835_sdhci_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; int ret; - host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata); + host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 8ebb6b650f3f..f2cc26633cb2 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -96,7 +96,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { static int sdhci_cns3xxx_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata); + return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); } static int sdhci_cns3xxx_remove(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 15e7803040f1..8424839660f8 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -130,7 +130,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) gpio_direction_input(priv->gpio_cd); } - host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata); + host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err_sdhci_pltfm_init; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d5f0d59e1310..98f46704baa6 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -503,7 +503,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) int err; struct pltfm_imx_data *imx_data; - host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata); + host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 5e68adc2461e..37e668f5b992 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -262,7 +262,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { static int sdhci_esdhc_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata); + return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata, 0); } static int sdhci_esdhc_remove(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 200a6a9fa805..57c514a81ca5 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c @@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { static int sdhci_hlwd_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata); + return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); } static int sdhci_hlwd_remove(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index e7762e5e9048..e2065a44dffc 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -115,10 +115,10 @@ void sdhci_get_of_property(struct platform_device *pdev) {} EXPORT_SYMBOL_GPL(sdhci_get_of_property); struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata) + const struct sdhci_pltfm_data *pdata, + size_t priv_size) { struct sdhci_host *host; - struct sdhci_pltfm_host *pltfm_host; struct device_node *np = pdev->dev.of_node; struct resource *iomem; int ret; @@ -134,17 +134,17 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, /* Some PCI-based MFD need the parent here */ if (pdev->dev.parent != &platform_bus && !np) - host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); + host = sdhci_alloc_host(pdev->dev.parent, + sizeof(struct sdhci_pltfm_host) + priv_size); else - host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); + host = sdhci_alloc_host(&pdev->dev, + sizeof(struct sdhci_pltfm_host) + priv_size); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } - pltfm_host = sdhci_priv(host); - host->hw_name = dev_name(&pdev->dev); if (pdata && pdata->ops) host->ops = pdata->ops; @@ -204,12 +204,13 @@ void sdhci_pltfm_free(struct platform_device *pdev) EXPORT_SYMBOL_GPL(sdhci_pltfm_free); int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata) + const struct sdhci_pltfm_data *pdata, + size_t priv_size) { struct sdhci_host *host; int ret = 0; - host = sdhci_pltfm_init(pdev, pdata); + host = sdhci_pltfm_init(pdev, pdata, priv_size); if (IS_ERR(host)) return PTR_ERR(host); diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 83d42c60a06f..e15ced79f7ed 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -28,6 +28,8 @@ struct sdhci_pltfm_host { /* migrate from sdhci_of_host */ unsigned int clock; u16 xfer_mode_shadow; + + unsigned long private[0] ____cacheline_aligned; }; #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER @@ -92,15 +94,22 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg) extern void sdhci_get_of_property(struct platform_device *pdev); extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata); + const struct sdhci_pltfm_data *pdata, + size_t priv_size); extern void sdhci_pltfm_free(struct platform_device *pdev); extern int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata); + const struct sdhci_pltfm_data *pdata, + size_t priv_size); extern int sdhci_pltfm_unregister(struct platform_device *pdev); extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); +static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) +{ + return (void *)host->private; +} + #ifdef CONFIG_PM extern const struct dev_pm_ops sdhci_pltfm_pmops; #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 98b5145cef7c..d51e061ec576 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -175,7 +175,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) if (!pxa) return -ENOMEM; - host = sdhci_pltfm_init(pdev, NULL); + host = sdhci_pltfm_init(pdev, NULL, 0); if (IS_ERR(host)) { kfree(pxa); return PTR_ERR(host); diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 90ee262def69..56d9bee93d8f 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -230,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) if (!pxa) return -ENOMEM; - host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata); + host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0); if (IS_ERR(host)) { kfree(pxa); return PTR_ERR(host); diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index e0dba74cff98..c8b058283a06 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -231,7 +231,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) return -EINVAL; soc_data = match->data; - host = sdhci_pltfm_init(pdev, soc_data->pdata); + host = sdhci_pltfm_init(pdev, soc_data->pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); -- GitLab From c3f1dbaf6e281642848b78fe101764170c15f168 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 31 May 2013 13:15:38 +0000 Subject: [PATCH 0556/2900] net: Update RFS target at poll for tcp/udp The current state of affairs is that read()/write() will setup RFS (Receive Flow Steering) for internet protocol sockets while poll()/epoll() does not. When poll() gets called with a TCP or UDP socket, we should update the flow target. This permits to RFS (if enabled) to select the appropriate CPU for following incoming packets. Note: Only connected UDP sockets can benefit from RFS. Signed-off-by: David Majnemer Signed-off-by: Eric Dumazet Cc: Paul Turner Cc: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 ++ net/ipv4/udp.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1f58594d5a85..b5d4ad988053 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -436,6 +436,8 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) struct sock *sk = sock->sk; const struct tcp_sock *tp = tcp_sk(sk); + sock_rps_record_flow(sk); + sock_poll_wait(file, sk_sleep(sk), wait); if (sk->sk_state == TCP_LISTEN) return inet_csk_listen_poll(sk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index aa5eff46d137..c7338ec79cc0 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1967,6 +1967,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) unsigned int mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; + sock_rps_record_flow(sk); + /* Check for false positives due to checksum errors */ if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk)) -- GitLab From db8caf3dbc77599dc90f4ea0a803cd1d97116f30 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 31 May 2013 11:18:10 +0000 Subject: [PATCH 0557/2900] gro: should aggregate frames without DF GRO on IPv4 doesn't aggregate frames if they don't have DF bit set. Some servers use IP_MTU_DISCOVER/IP_PMTUDISC_PROBE, so linux receivers are unable to aggregate this kind of traffic. The right thing to do is to allow aggregation as long as the DF bit has same value on all segments. bnx2x LRO does this correctly. Signed-off-by: Eric Dumazet Cc: Jerry Chu Cc: Herbert Xu Cc: Ben Hutchings Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index b05ae96aec44..9c090c7daea1 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1385,7 +1385,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, goto out_unlock; id = ntohl(*(__be32 *)&iph->id); - flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF)); + flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); id >>= 16; for (p = *head; p; p = p->next) { @@ -1407,6 +1407,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, NAPI_GRO_CB(p)->flush |= (iph->ttl ^ iph2->ttl) | (iph->tos ^ iph2->tos) | + ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) | ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); NAPI_GRO_CB(p)->flush |= flush; -- GitLab From 938177e9f3e0238c1712210f7bb6def38a5c8d7f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 30 May 2013 16:39:29 +0000 Subject: [PATCH 0558/2900] netfilter: Correct calculation using skb->tail and skb-network_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->network_header will be an offset from head. This is corrected by using wrappers that ensure that calculations are always made using pointers. Reported-by: Stephen Rothwell Reported-by: Chen Gang Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/netfilter/nf_nat_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index 5fea563afe30..85e20a919081 100644 --- a/net/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c @@ -104,7 +104,7 @@ static void mangle_contents(struct sk_buff *skb, /* move post-replacement */ memmove(data + match_offset + rep_len, data + match_offset + match_len, - skb->tail - (skb->network_header + dataoff + + skb_tail_pointer(skb) - (skb_network_header(skb) + dataoff + match_offset + match_len)); /* insert data from buffer */ -- GitLab From 35d0461061f27eeb62de63174959edbbb9e434de Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 29 May 2013 15:16:05 +0800 Subject: [PATCH 0559/2900] net: clean up skb headers code commit 1a37e412a0225fcba5587 (net: Use 16bits for *_headers fields of struct skbuff) converts skb->*_header to u16, some #if NET_SKBUFF_DATA_USES_OFFSET are now useless, and to be safe, we could just use "X = (typeof(X)) ~0U;" as suggested by David. Cc: David S. Miller Cc: Simon Horman Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- net/core/skbuff.c | 16 +++++----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 5f931191cf57..b9997907a0f1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1593,7 +1593,7 @@ static inline void skb_set_inner_mac_header(struct sk_buff *skb, } static inline bool skb_transport_header_was_set(const struct sk_buff *skb) { - return skb->transport_header != ~0U; + return skb->transport_header != (typeof(skb->transport_header))~0U; } static inline unsigned char *skb_transport_header(const struct sk_buff *skb) @@ -1636,7 +1636,7 @@ static inline unsigned char *skb_mac_header(const struct sk_buff *skb) static inline int skb_mac_header_was_set(const struct sk_buff *skb) { - return skb->mac_header != ~0U; + return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index f45de077ab9e..6b1b52c5593b 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -199,9 +199,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node) skb->truesize = sizeof(struct sk_buff); atomic_set(&skb->users, 1); -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = (__u16) ~0U; -#endif + skb->mac_header = (typeof(skb->mac_header))~0U; out: return skb; } @@ -275,10 +273,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, skb->data = data; skb_reset_tail_pointer(skb); skb->end = skb->tail + size; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = (__u16) ~0U; - skb->transport_header = (__u16) ~0U; -#endif + skb->mac_header = (typeof(skb->mac_header))~0U; + skb->transport_header = (typeof(skb->transport_header))~0U; /* make sure we initialize shinfo sequentially */ shinfo = skb_shinfo(skb); @@ -344,10 +340,8 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) skb->data = data; skb_reset_tail_pointer(skb); skb->end = skb->tail + size; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->mac_header = (__u16) ~0U; - skb->transport_header = (__u16) ~0U; -#endif + skb->mac_header = (typeof(skb->mac_header))~0U; + skb->transport_header = (typeof(skb->transport_header))~0U; /* make sure we initialize shinfo sequentially */ shinfo = skb_shinfo(skb); -- GitLab From bf3d6a8f791b2a81279b9ce3201b4970f6fbe51a Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 May 2013 23:48:15 +0000 Subject: [PATCH 0560/2900] iptunnel: specify protocol outside IP header Before this patch, ip_tunnel_xmit() was using the field protocol from the IP header passed into argument. There is no functional change, this patch prepares the support of IPv4 over IPv4 for module sit. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 2 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_tunnel.c | 4 ++-- net/ipv4/ipip.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 4b6f0b28f41f..40b4dfce01fc 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -101,7 +101,7 @@ int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn); void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, - const struct iphdr *tnl_params); + const struct iphdr *tnl_params, const u8 protocol); int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2a83591492dd..a982657d05e7 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -429,7 +429,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, return; } - ip_tunnel_xmit(skb, dev, tnl_params); + ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); } static netdev_tx_t ipgre_xmit(struct sk_buff *skb, diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index e4147ec1665a..b89095c1518f 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -487,7 +487,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, EXPORT_SYMBOL_GPL(ip_tunnel_rcv); void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, - const struct iphdr *tnl_params) + const struct iphdr *tnl_params, const u8 protocol) { struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *inner_iph; @@ -670,7 +670,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, iph->version = 4; iph->ihl = sizeof(struct iphdr) >> 2; iph->frag_off = df; - iph->protocol = tnl_params->protocol; + iph->protocol = protocol; iph->tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); iph->daddr = fl4.daddr; iph->saddr = fl4.saddr; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 77bfcce64fe5..9df7ecd393f2 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -222,7 +222,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->encapsulation = 1; } - ip_tunnel_xmit(skb, dev, tiph); + ip_tunnel_xmit(skb, dev, tiph, tiph->protocol); return NETDEV_TX_OK; tx_error: -- GitLab From 32b8a8e59c9c8fa56051d6e9ab2924e469ac4d92 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 27 May 2013 23:48:16 +0000 Subject: [PATCH 0561/2900] sit: add IPv4 over IPv4 support This patch adds the support of IPv4 over Ipv4 for the module sit. The gain of this feature is to be able to have 4in4 and 6in4 over the same interface instead of having one interface for 6in4 and another for 4in4 even if encapsulation addresses are the same. To avoid conflicting with ipip module, sit IPv4 over IPv4 protocol is registered with a smaller priority. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv4/xfrm4_tunnel.c | 2 +- net/ipv6/sit.c | 119 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 4 deletions(-) diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 05a5df2febc9..06347dbd32c1 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c @@ -63,7 +63,7 @@ static int xfrm_tunnel_err(struct sk_buff *skb, u32 info) static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { .handler = xfrm_tunnel_rcv, .err_handler = xfrm_tunnel_err, - .priority = 2, + .priority = 3, }; #if IS_ENABLED(CONFIG_IPV6) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 335363478bbf..6b9c1f128eaf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -577,6 +577,10 @@ static int ipip6_rcv(struct sk_buff *skb) if (tunnel != NULL) { struct pcpu_tstats *tstats; + if (tunnel->parms.iph.protocol != IPPROTO_IPV6 && + tunnel->parms.iph.protocol != 0) + goto out; + secpath_reset(skb); skb->mac_header = skb->network_header; skb_reset_network_header(skb); @@ -629,6 +633,35 @@ static int ipip6_rcv(struct sk_buff *skb) return 0; } +static const struct tnl_ptk_info tpi = { + /* no tunnel info required for ipip. */ + .proto = htons(ETH_P_IP), +}; + +static int ipip_rcv(struct sk_buff *skb) +{ + const struct iphdr *iph = ip_hdr(skb); + struct ip_tunnel *tunnel; + + tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, + iph->saddr, iph->daddr); + if (tunnel != NULL) { + if (tunnel->parms.iph.protocol != IPPROTO_IPIP && + tunnel->parms.iph.protocol != 0) + goto drop; + + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto drop; + return ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); + } + + return 1; + +drop: + kfree_skb(skb); + return 0; +} + /* * If the IPv6 address comes from 6rd / 6to4 (RFC 3056) addr space this function * stores the embedded IPv4 address in v4dst and returns true. @@ -877,6 +910,43 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + const struct iphdr *tiph = &tunnel->parms.iph; + + if (likely(!skb->encapsulation)) { + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } + + ip_tunnel_xmit(skb, dev, tiph, IPPROTO_IPIP); + return NETDEV_TX_OK; +} + +static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + switch (skb->protocol) { + case htons(ETH_P_IP): + ipip_tunnel_xmit(skb, dev); + break; + case htons(ETH_P_IPV6): + ipip6_tunnel_xmit(skb, dev); + break; + default: + goto tx_err; + } + + return NETDEV_TX_OK; + +tx_err: + dev->stats.tx_errors++; + dev_kfree_skb(skb); + return NETDEV_TX_OK; + +} + static void ipip6_tunnel_bind_dev(struct net_device *dev) { struct net_device *tdev = NULL; @@ -1027,7 +1097,11 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) goto done; err = -EINVAL; - if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPV6 || + if (p.iph.protocol != IPPROTO_IPV6 && + p.iph.protocol != IPPROTO_IPIP && + p.iph.protocol != 0) + goto done; + if (p.iph.version != 4 || p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) goto done; if (p.iph.ttl) @@ -1164,7 +1238,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) static const struct net_device_ops ipip6_netdev_ops = { .ndo_uninit = ipip6_tunnel_uninit, - .ndo_start_xmit = ipip6_tunnel_xmit, + .ndo_start_xmit = sit_tunnel_xmit, .ndo_do_ioctl = ipip6_tunnel_ioctl, .ndo_change_mtu = ipip6_tunnel_change_mtu, .ndo_get_stats64 = ip_tunnel_get_stats64, @@ -1232,6 +1306,22 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) return 0; } +static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + u8 proto; + + if (!data) + return 0; + + proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); + if (proto != IPPROTO_IPV6 && + proto != IPPROTO_IPIP && + proto != 0) + return -EINVAL; + + return 0; +} + static void ipip6_netlink_parms(struct nlattr *data[], struct ip_tunnel_parm *parms) { @@ -1268,6 +1358,10 @@ static void ipip6_netlink_parms(struct nlattr *data[], if (data[IFLA_IPTUN_FLAGS]) parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]); + + if (data[IFLA_IPTUN_PROTO]) + parms->iph.protocol = nla_get_u8(data[IFLA_IPTUN_PROTO]); + } #ifdef CONFIG_IPV6_SIT_6RD @@ -1391,6 +1485,8 @@ static size_t ipip6_get_size(const struct net_device *dev) nla_total_size(1) + /* IFLA_IPTUN_FLAGS */ nla_total_size(2) + + /* IFLA_IPTUN_PROTO */ + nla_total_size(1) + #ifdef CONFIG_IPV6_SIT_6RD /* IFLA_IPTUN_6RD_PREFIX */ nla_total_size(sizeof(struct in6_addr)) + @@ -1416,6 +1512,7 @@ static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) || nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, !!(parm->iph.frag_off & htons(IP_DF))) || + nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->iph.protocol) || nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags)) goto nla_put_failure; @@ -1445,6 +1542,7 @@ static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = { [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 }, + [IFLA_IPTUN_PROTO] = { .type = NLA_U8 }, #ifdef CONFIG_IPV6_SIT_6RD [IFLA_IPTUN_6RD_PREFIX] = { .len = sizeof(struct in6_addr) }, [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NLA_U32 }, @@ -1459,6 +1557,7 @@ static struct rtnl_link_ops sit_link_ops __read_mostly = { .policy = ipip6_policy, .priv_size = sizeof(struct ip_tunnel), .setup = ipip6_tunnel_setup, + .validate = ipip6_validate, .newlink = ipip6_newlink, .changelink = ipip6_changelink, .get_size = ipip6_get_size, @@ -1471,6 +1570,12 @@ static struct xfrm_tunnel sit_handler __read_mostly = { .priority = 1, }; +static struct xfrm_tunnel ipip_handler __read_mostly = { + .handler = ipip_rcv, + .err_handler = ipip6_err, + .priority = 2, +}; + static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) { int prio; @@ -1553,6 +1658,7 @@ static void __exit sit_cleanup(void) { rtnl_link_unregister(&sit_link_ops); xfrm4_tunnel_deregister(&sit_handler, AF_INET6); + xfrm4_tunnel_deregister(&ipip_handler, AF_INET); unregister_pernet_device(&sit_net_ops); rcu_barrier(); /* Wait for completion of call_rcu()'s */ @@ -1569,9 +1675,14 @@ static int __init sit_init(void) return err; err = xfrm4_tunnel_register(&sit_handler, AF_INET6); if (err < 0) { - pr_info("%s: can't add protocol\n", __func__); + pr_info("%s: can't register ip6ip4\n", __func__); goto xfrm_tunnel_failed; } + err = xfrm4_tunnel_register(&ipip_handler, AF_INET); + if (err < 0) { + pr_info("%s: can't register ip4ip4\n", __func__); + goto xfrm_tunnel4_failed; + } err = rtnl_link_register(&sit_link_ops); if (err < 0) goto rtnl_link_failed; @@ -1580,6 +1691,8 @@ static int __init sit_init(void) return err; rtnl_link_failed: + xfrm4_tunnel_deregister(&ipip_handler, AF_INET); +xfrm_tunnel4_failed: xfrm4_tunnel_deregister(&sit_handler, AF_INET6); xfrm_tunnel_failed: unregister_pernet_device(&sit_net_ops); -- GitLab From 2cc70ba4cf5f97a7cf08063d2fae693d36b462eb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 28 May 2013 04:07:21 +0000 Subject: [PATCH 0562/2900] phy: add reverse MII PHY connection type The PHY library currently does not know about the the reverse MII connection type. Add it to the list of supported PHY modes and update of_get_phy_mode() to support it and look for the string "rev-mii". Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/of/of_net.c | 1 + include/linux/phy.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c index ffab033d207e..ea174c8ee34b 100644 --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c @@ -22,6 +22,7 @@ static const char *phy_modes[] = { [PHY_INTERFACE_MODE_GMII] = "gmii", [PHY_INTERFACE_MODE_SGMII] = "sgmii", [PHY_INTERFACE_MODE_TBI] = "tbi", + [PHY_INTERFACE_MODE_REVMII] = "rev-mii", [PHY_INTERFACE_MODE_RMII] = "rmii", [PHY_INTERFACE_MODE_RGMII] = "rgmii", [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id", diff --git a/include/linux/phy.h b/include/linux/phy.h index ee411b0eef5d..64ab823f7b74 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -58,6 +58,7 @@ typedef enum { PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_SGMII, PHY_INTERFACE_MODE_TBI, + PHY_INTERFACE_MODE_REVMII, PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_RGMII_ID, -- GitLab From 492205050d77bcc4f85f6dc0da6b6fdbca1d6ff7 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 30 May 2013 03:49:20 +0000 Subject: [PATCH 0563/2900] net: Add EMAC ethernet driver found on Allwinner A10 SoC's The Allwinner A10 has an ethernet controller that seem to be developped internally by them. The exact feature set of this controller is unknown, since there is no public documentation for this IP, and this driver is mostly the one published by Allwinner that has been heavily cleaned up. Signed-off-by: Stefan Roese Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- .../bindings/net/allwinner,sun4i-emac.txt | 22 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/allwinner/Kconfig | 36 + drivers/net/ethernet/allwinner/Makefile | 5 + drivers/net/ethernet/allwinner/sun4i-emac.c | 960 ++++++++++++++++++ drivers/net/ethernet/allwinner/sun4i-emac.h | 108 ++ 7 files changed, 1133 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt create mode 100644 drivers/net/ethernet/allwinner/Kconfig create mode 100644 drivers/net/ethernet/allwinner/Makefile create mode 100644 drivers/net/ethernet/allwinner/sun4i-emac.c create mode 100644 drivers/net/ethernet/allwinner/sun4i-emac.h diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt new file mode 100644 index 000000000000..b90bfcd138ff --- /dev/null +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-emac.txt @@ -0,0 +1,22 @@ +* Allwinner EMAC ethernet controller + +Required properties: +- compatible: should be "allwinner,sun4i-emac". +- reg: address and length of the register set for the device. +- interrupts: interrupt for the device +- phy: A phandle to a phy node defining the PHY address (as the reg + property, a single integer). +- clocks: A phandle to the reference clock for this device + +Optional properties: +- (local-)mac-address: mac address to be used by this driver + +Example: + +emac: ethernet@01c0b000 { + compatible = "allwinner,sun4i-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <55>; + clocks = <&ahb_gates 17>; + phy = <&phy0>; +}; diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ed956e08d38b..18fd6fbeb109 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -20,6 +20,7 @@ config SUNGEM_PHY source "drivers/net/ethernet/3com/Kconfig" source "drivers/net/ethernet/adaptec/Kconfig" source "drivers/net/ethernet/aeroflex/Kconfig" +source "drivers/net/ethernet/allwinner/Kconfig" source "drivers/net/ethernet/alteon/Kconfig" source "drivers/net/ethernet/amd/Kconfig" source "drivers/net/ethernet/apple/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 8268d85f9448..009da27b6e26 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_NET_VENDOR_3COM) += 3com/ obj-$(CONFIG_NET_VENDOR_8390) += 8390/ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/ obj-$(CONFIG_GRETH) += aeroflex/ +obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ obj-$(CONFIG_NET_VENDOR_AMD) += amd/ obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig new file mode 100644 index 000000000000..66d35324f31e --- /dev/null +++ b/drivers/net/ethernet/allwinner/Kconfig @@ -0,0 +1,36 @@ +# +# Allwinner device configuration +# + +config NET_VENDOR_ALLWINNER + bool "Allwinner devices" + default y + depends on ARCH_SUNXI + ---help--- + If you have a network (Ethernet) card belonging to this + class, say Y and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly + affect the kernel: saying N will just cause the configurator + to skip all the questions about Allwinner cards. If you say Y, + you will be asked for your specific card in the following + questions. + +if NET_VENDOR_ALLWINNER + +config SUN4I_EMAC + tristate "Allwinner A10 EMAC support" + depends on ARCH_SUNXI + depends on OF + select CRC32 + select NET_CORE + select MII + select PHYLIB + ---help--- + Support for Allwinner A10 EMAC ethernet driver. + + To compile this driver as a module, choose M here. The module + will be called sun4i-emac. + +endif # NET_VENDOR_ALLWINNER diff --git a/drivers/net/ethernet/allwinner/Makefile b/drivers/net/ethernet/allwinner/Makefile new file mode 100644 index 000000000000..03129f796514 --- /dev/null +++ b/drivers/net/ethernet/allwinner/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Allwinner device drivers. +# + +obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c new file mode 100644 index 000000000000..b411344e719e --- /dev/null +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -0,0 +1,960 @@ +/* + * Allwinner EMAC Fast Ethernet driver for Linux. + * + * Copyright 2012-2013 Stefan Roese + * Copyright 2013 Maxime Ripard + * + * Based on the Linux driver provided by Allwinner: + * Copyright (C) 1997 Sten Wang + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sun4i-emac.h" + +#define DRV_NAME "sun4i-emac" +#define DRV_VERSION "1.02" + +#define EMAC_MAX_FRAME_LEN 0x0600 + +/* Transmit timeout, default 5 seconds. */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +/* EMAC register address locking. + * + * The EMAC uses an address register to control where data written + * to the data register goes. This means that the address register + * must be preserved over interrupts or similar calls. + * + * During interrupt and other critical calls, a spinlock is used to + * protect the system, but the calls themselves save the address + * in the address register in case they are interrupting another + * access to the device. + * + * For general accesses a lock is provided so that calls which are + * allowed to sleep are serialised so that the address register does + * not need to be saved. This lock also serves to serialise access + * to the EEPROM and PHY access registers which are shared between + * these two devices. + */ + +/* The driver supports the original EMACE, and now the two newer + * devices, EMACA and EMACB. + */ + +struct emac_board_info { + struct clk *clk; + struct device *dev; + struct platform_device *pdev; + spinlock_t lock; + void __iomem *membase; + u32 msg_enable; + struct net_device *ndev; + struct sk_buff *skb_last; + u16 tx_fifo_stat; + + int emacrx_completed_flag; + + struct phy_device *phy_dev; + struct device_node *phy_node; + unsigned int link; + unsigned int speed; + unsigned int duplex; + + phy_interface_t phy_interface; +}; + +static void emac_update_speed(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + unsigned int reg_val; + + /* set EMAC SPEED, depend on PHY */ + reg_val = readl(db->membase + EMAC_MAC_SUPP_REG); + reg_val &= ~(0x1 << 8); + if (db->speed == SPEED_100) + reg_val |= 1 << 8; + writel(reg_val, db->membase + EMAC_MAC_SUPP_REG); +} + +static void emac_update_duplex(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + unsigned int reg_val; + + /* set duplex depend on phy */ + reg_val = readl(db->membase + EMAC_MAC_CTL1_REG); + reg_val &= ~EMAC_MAC_CTL1_DUPLEX_EN; + if (db->duplex) + reg_val |= EMAC_MAC_CTL1_DUPLEX_EN; + writel(reg_val, db->membase + EMAC_MAC_CTL1_REG); +} + +static void emac_handle_link_change(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + struct phy_device *phydev = db->phy_dev; + unsigned long flags; + int status_change = 0; + + if (phydev->link) { + if (db->speed != phydev->speed) { + spin_lock_irqsave(&db->lock, flags); + db->speed = phydev->speed; + emac_update_speed(dev); + spin_unlock_irqrestore(&db->lock, flags); + status_change = 1; + } + + if (db->duplex != phydev->duplex) { + spin_lock_irqsave(&db->lock, flags); + db->duplex = phydev->duplex; + emac_update_duplex(dev); + spin_unlock_irqrestore(&db->lock, flags); + status_change = 1; + } + } + + if (phydev->link != db->link) { + if (!phydev->link) { + db->speed = 0; + db->duplex = -1; + } + db->link = phydev->link; + + status_change = 1; + } + + if (status_change) + phy_print_status(phydev); +} + +static int emac_mdio_probe(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + + /* to-do: PHY interrupts are currently not supported */ + + /* attach the mac to the phy */ + db->phy_dev = of_phy_connect(db->ndev, db->phy_node, + &emac_handle_link_change, 0, + db->phy_interface); + if (!db->phy_dev) { + netdev_err(db->ndev, "could not find the PHY\n"); + return -ENODEV; + } + + /* mask with MAC supported features */ + db->phy_dev->supported &= PHY_BASIC_FEATURES; + db->phy_dev->advertising = db->phy_dev->supported; + + db->link = 0; + db->speed = 0; + db->duplex = -1; + + return 0; +} + +static void emac_mdio_remove(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + + phy_disconnect(db->phy_dev); + db->phy_dev = NULL; +} + +static void emac_reset(struct emac_board_info *db) +{ + dev_dbg(db->dev, "resetting device\n"); + + /* RESET device */ + writel(0, db->membase + EMAC_CTL_REG); + udelay(200); + writel(EMAC_CTL_RESET, db->membase + EMAC_CTL_REG); + udelay(200); +} + +static void emac_outblk_32bit(void __iomem *reg, void *data, int count) +{ + writesl(reg, data, round_up(count, 4) / 4); +} + +static void emac_inblk_32bit(void __iomem *reg, void *data, int count) +{ + readsl(reg, data, round_up(count, 4) / 4); +} + +static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct emac_board_info *dm = netdev_priv(dev); + struct phy_device *phydev = dm->phy_dev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, rq, cmd); +} + +/* ethtool ops */ +static void emac_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(DRV_NAME)); + strlcpy(info->version, DRV_VERSION, sizeof(DRV_VERSION)); + strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info)); +} + +static int emac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct emac_board_info *dm = netdev_priv(dev); + struct phy_device *phydev = dm->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_gset(phydev, cmd); +} + +static int emac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct emac_board_info *dm = netdev_priv(dev); + struct phy_device *phydev = dm->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_sset(phydev, cmd); +} + +static const struct ethtool_ops emac_ethtool_ops = { + .get_drvinfo = emac_get_drvinfo, + .get_settings = emac_get_settings, + .set_settings = emac_set_settings, + .get_link = ethtool_op_get_link, +}; + +unsigned int emac_setup(struct net_device *ndev) +{ + struct emac_board_info *db = netdev_priv(ndev); + unsigned int reg_val; + + /* set up TX */ + reg_val = readl(db->membase + EMAC_TX_MODE_REG); + + writel(reg_val | EMAC_TX_MODE_ABORTED_FRAME_EN, + db->membase + EMAC_TX_MODE_REG); + + /* set up RX */ + reg_val = readl(db->membase + EMAC_RX_CTL_REG); + + writel(reg_val | EMAC_RX_CTL_PASS_LEN_OOR_EN | + EMAC_RX_CTL_ACCEPT_UNICAST_EN | EMAC_RX_CTL_DA_FILTER_EN | + EMAC_RX_CTL_ACCEPT_MULTICAST_EN | + EMAC_RX_CTL_ACCEPT_BROADCAST_EN, + db->membase + EMAC_RX_CTL_REG); + + /* set MAC */ + /* set MAC CTL0 */ + reg_val = readl(db->membase + EMAC_MAC_CTL0_REG); + writel(reg_val | EMAC_MAC_CTL0_RX_FLOW_CTL_EN | + EMAC_MAC_CTL0_TX_FLOW_CTL_EN, + db->membase + EMAC_MAC_CTL0_REG); + + /* set MAC CTL1 */ + reg_val = readl(db->membase + EMAC_MAC_CTL1_REG); + reg_val |= EMAC_MAC_CTL1_LEN_CHECK_EN; + reg_val |= EMAC_MAC_CTL1_CRC_EN; + reg_val |= EMAC_MAC_CTL1_PAD_EN; + writel(reg_val, db->membase + EMAC_MAC_CTL1_REG); + + /* set up IPGT */ + writel(EMAC_MAC_IPGT_FULL_DUPLEX, db->membase + EMAC_MAC_IPGT_REG); + + /* set up IPGR */ + writel((EMAC_MAC_IPGR_IPG1 << 8) | EMAC_MAC_IPGR_IPG2, + db->membase + EMAC_MAC_IPGR_REG); + + /* set up Collison window */ + writel((EMAC_MAC_CLRT_COLLISION_WINDOW << 8) | EMAC_MAC_CLRT_RM, + db->membase + EMAC_MAC_CLRT_REG); + + /* set up Max Frame Length */ + writel(EMAC_MAX_FRAME_LEN, + db->membase + EMAC_MAC_MAXF_REG); + + return 0; +} + +unsigned int emac_powerup(struct net_device *ndev) +{ + struct emac_board_info *db = netdev_priv(ndev); + unsigned int reg_val; + + /* initial EMAC */ + /* flush RX FIFO */ + reg_val = readl(db->membase + EMAC_RX_CTL_REG); + reg_val |= 0x8; + writel(reg_val, db->membase + EMAC_RX_CTL_REG); + udelay(1); + + /* initial MAC */ + /* soft reset MAC */ + reg_val = readl(db->membase + EMAC_MAC_CTL0_REG); + reg_val &= ~EMAC_MAC_CTL0_SOFT_RESET; + writel(reg_val, db->membase + EMAC_MAC_CTL0_REG); + + /* set MII clock */ + reg_val = readl(db->membase + EMAC_MAC_MCFG_REG); + reg_val &= (~(0xf << 2)); + reg_val |= (0xD << 2); + writel(reg_val, db->membase + EMAC_MAC_MCFG_REG); + + /* clear RX counter */ + writel(0x0, db->membase + EMAC_RX_FBC_REG); + + /* disable all interrupt and clear interrupt status */ + writel(0, db->membase + EMAC_INT_CTL_REG); + reg_val = readl(db->membase + EMAC_INT_STA_REG); + writel(reg_val, db->membase + EMAC_INT_STA_REG); + + udelay(1); + + /* set up EMAC */ + emac_setup(ndev); + + /* set mac_address to chip */ + writel(ndev->dev_addr[0] << 16 | ndev->dev_addr[1] << 8 | ndev-> + dev_addr[2], db->membase + EMAC_MAC_A1_REG); + writel(ndev->dev_addr[3] << 16 | ndev->dev_addr[4] << 8 | ndev-> + dev_addr[5], db->membase + EMAC_MAC_A0_REG); + + mdelay(1); + + return 0; +} + +static int emac_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct emac_board_info *db = netdev_priv(dev); + + if (netif_running(dev)) + return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + + writel(dev->dev_addr[0] << 16 | dev->dev_addr[1] << 8 | dev-> + dev_addr[2], db->membase + EMAC_MAC_A1_REG); + writel(dev->dev_addr[3] << 16 | dev->dev_addr[4] << 8 | dev-> + dev_addr[5], db->membase + EMAC_MAC_A0_REG); + + return 0; +} + +/* Initialize emac board */ +static void emac_init_device(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + unsigned long flags; + unsigned int reg_val; + + spin_lock_irqsave(&db->lock, flags); + + emac_update_speed(dev); + emac_update_duplex(dev); + + /* enable RX/TX */ + reg_val = readl(db->membase + EMAC_CTL_REG); + writel(reg_val | EMAC_CTL_RESET | EMAC_CTL_TX_EN | EMAC_CTL_RX_EN, + db->membase + EMAC_CTL_REG); + + /* enable RX/TX0/RX Hlevel interrup */ + reg_val = readl(db->membase + EMAC_INT_CTL_REG); + reg_val |= (0xf << 0) | (0x01 << 8); + writel(reg_val, db->membase + EMAC_INT_CTL_REG); + + spin_unlock_irqrestore(&db->lock, flags); +} + +/* Our watchdog timed out. Called by the networking layer */ +static void emac_timeout(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + unsigned long flags; + + if (netif_msg_timer(db)) + dev_err(db->dev, "tx time out.\n"); + + /* Save previous register address */ + spin_lock_irqsave(&db->lock, flags); + + netif_stop_queue(dev); + emac_reset(db); + emac_init_device(dev); + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); + + /* Restore previous register address */ + spin_unlock_irqrestore(&db->lock, flags); +} + +/* Hardware start transmission. + * Send a packet to media from the upper layer. + */ +static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + unsigned long channel; + unsigned long flags; + + channel = db->tx_fifo_stat & 3; + if (channel == 3) + return 1; + + channel = (channel == 1 ? 1 : 0); + + spin_lock_irqsave(&db->lock, flags); + + writel(channel, db->membase + EMAC_TX_INS_REG); + + emac_outblk_32bit(db->membase + EMAC_TX_IO_DATA_REG, + skb->data, skb->len); + dev->stats.tx_bytes += skb->len; + + db->tx_fifo_stat |= 1 << channel; + /* TX control: First packet immediately send, second packet queue */ + if (channel == 0) { + /* set TX len */ + writel(skb->len, db->membase + EMAC_TX_PL0_REG); + /* start translate from fifo to phy */ + writel(readl(db->membase + EMAC_TX_CTL0_REG) | 1, + db->membase + EMAC_TX_CTL0_REG); + + /* save the time stamp */ + dev->trans_start = jiffies; + } else if (channel == 1) { + /* set TX len */ + writel(skb->len, db->membase + EMAC_TX_PL1_REG); + /* start translate from fifo to phy */ + writel(readl(db->membase + EMAC_TX_CTL1_REG) | 1, + db->membase + EMAC_TX_CTL1_REG); + + /* save the time stamp */ + dev->trans_start = jiffies; + } + + if ((db->tx_fifo_stat & 3) == 3) { + /* Second packet */ + netif_stop_queue(dev); + } + + spin_unlock_irqrestore(&db->lock, flags); + + /* free this SKB */ + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + +/* EMAC interrupt handler + * receive the packet to upper layer, free the transmitted packet + */ +static void emac_tx_done(struct net_device *dev, struct emac_board_info *db, + unsigned int tx_status) +{ + /* One packet sent complete */ + db->tx_fifo_stat &= ~(tx_status & 3); + if (3 == (tx_status & 3)) + dev->stats.tx_packets += 2; + else + dev->stats.tx_packets++; + + if (netif_msg_tx_done(db)) + dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); + + netif_wake_queue(dev); +} + +/* Received a packet and pass to upper layer + */ +static void emac_rx(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + struct sk_buff *skb; + u8 *rdptr; + bool good_packet; + static int rxlen_last; + unsigned int reg_val; + u32 rxhdr, rxstatus, rxcount, rxlen; + + /* Check packet ready or not */ + while (1) { + /* race warning: the first packet might arrive with + * the interrupts disabled, but the second will fix + * it + */ + rxcount = readl(db->membase + EMAC_RX_FBC_REG); + + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "RXCount: %x\n", rxcount); + + if ((db->skb_last != NULL) && (rxlen_last > 0)) { + dev->stats.rx_bytes += rxlen_last; + + /* Pass to upper layer */ + db->skb_last->protocol = eth_type_trans(db->skb_last, + dev); + netif_rx(db->skb_last); + dev->stats.rx_packets++; + db->skb_last = NULL; + rxlen_last = 0; + + reg_val = readl(db->membase + EMAC_RX_CTL_REG); + reg_val &= ~EMAC_RX_CTL_DMA_EN; + writel(reg_val, db->membase + EMAC_RX_CTL_REG); + } + + if (!rxcount) { + db->emacrx_completed_flag = 1; + reg_val = readl(db->membase + EMAC_INT_CTL_REG); + reg_val |= (0xf << 0) | (0x01 << 8); + writel(reg_val, db->membase + EMAC_INT_CTL_REG); + + /* had one stuck? */ + rxcount = readl(db->membase + EMAC_RX_FBC_REG); + if (!rxcount) + return; + } + + reg_val = readl(db->membase + EMAC_RX_IO_DATA_REG); + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "receive header: %x\n", reg_val); + if (reg_val != EMAC_UNDOCUMENTED_MAGIC) { + /* disable RX */ + reg_val = readl(db->membase + EMAC_CTL_REG); + writel(reg_val & ~EMAC_CTL_RX_EN, + db->membase + EMAC_CTL_REG); + + /* Flush RX FIFO */ + reg_val = readl(db->membase + EMAC_RX_CTL_REG); + writel(reg_val | (1 << 3), + db->membase + EMAC_RX_CTL_REG); + + do { + reg_val = readl(db->membase + EMAC_RX_CTL_REG); + } while (reg_val & (1 << 3)); + + /* enable RX */ + reg_val = readl(db->membase + EMAC_CTL_REG); + writel(reg_val | EMAC_CTL_RX_EN, + db->membase + EMAC_CTL_REG); + reg_val = readl(db->membase + EMAC_INT_CTL_REG); + reg_val |= (0xf << 0) | (0x01 << 8); + writel(reg_val, db->membase + EMAC_INT_CTL_REG); + + db->emacrx_completed_flag = 1; + + return; + } + + /* A packet ready now & Get status/length */ + good_packet = true; + + emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG, + &rxhdr, sizeof(rxhdr)); + + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr))); + + rxlen = EMAC_RX_IO_DATA_LEN(rxhdr); + rxstatus = EMAC_RX_IO_DATA_STATUS(rxhdr); + + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "RX: status %02x, length %04x\n", + rxstatus, rxlen); + + /* Packet Status check */ + if (rxlen < 0x40) { + good_packet = false; + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "RX: Bad Packet (runt)\n"); + } + + if (unlikely(!(rxstatus & EMAC_RX_IO_DATA_STATUS_OK))) { + good_packet = false; + + if (rxstatus & EMAC_RX_IO_DATA_STATUS_CRC_ERR) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "crc error\n"); + dev->stats.rx_crc_errors++; + } + + if (rxstatus & EMAC_RX_IO_DATA_STATUS_LEN_ERR) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "length error\n"); + dev->stats.rx_length_errors++; + } + } + + /* Move data from EMAC */ + skb = dev_alloc_skb(rxlen + 4); + if (good_packet && skb) { + skb_reserve(skb, 2); + rdptr = (u8 *) skb_put(skb, rxlen - 4); + + /* Read received packet from RX SRAM */ + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "RxLen %x\n", rxlen); + + emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG, + rdptr, rxlen); + dev->stats.rx_bytes += rxlen; + + /* Pass to upper layer */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->stats.rx_packets++; + } + } +} + +static irqreturn_t emac_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct emac_board_info *db = netdev_priv(dev); + int int_status; + unsigned long flags; + unsigned int reg_val; + + /* A real interrupt coming */ + + /* holders of db->lock must always block IRQs */ + spin_lock_irqsave(&db->lock, flags); + + /* Disable all interrupts */ + writel(0, db->membase + EMAC_INT_CTL_REG); + + /* Got EMAC interrupt status */ + /* Got ISR */ + int_status = readl(db->membase + EMAC_INT_STA_REG); + /* Clear ISR status */ + writel(int_status, db->membase + EMAC_INT_STA_REG); + + if (netif_msg_intr(db)) + dev_dbg(db->dev, "emac interrupt %02x\n", int_status); + + /* Received the coming packet */ + if ((int_status & 0x100) && (db->emacrx_completed_flag == 1)) { + /* carrier lost */ + db->emacrx_completed_flag = 0; + emac_rx(dev); + } + + /* Transmit Interrupt check */ + if (int_status & (0x01 | 0x02)) + emac_tx_done(dev, db, int_status); + + if (int_status & (0x04 | 0x08)) + netdev_info(dev, " ab : %x\n", int_status); + + /* Re-enable interrupt mask */ + if (db->emacrx_completed_flag == 1) { + reg_val = readl(db->membase + EMAC_INT_CTL_REG); + reg_val |= (0xf << 0) | (0x01 << 8); + writel(reg_val, db->membase + EMAC_INT_CTL_REG); + } + spin_unlock_irqrestore(&db->lock, flags); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Used by netconsole + */ +static void emac_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + emac_interrupt(dev->irq, dev); + enable_irq(dev->irq); +} +#endif + +/* Open the interface. + * The interface is opened whenever "ifconfig" actives it. + */ +static int emac_open(struct net_device *dev) +{ + struct emac_board_info *db = netdev_priv(dev); + int ret; + + if (netif_msg_ifup(db)) + dev_dbg(db->dev, "enabling %s\n", dev->name); + + if (devm_request_irq(db->dev, dev->irq, &emac_interrupt, + 0, dev->name, dev)) + return -EAGAIN; + + /* Initialize EMAC board */ + emac_reset(db); + emac_init_device(dev); + + ret = emac_mdio_probe(dev); + if (ret < 0) { + netdev_err(dev, "cannot probe MDIO bus\n"); + return ret; + } + + phy_start(db->phy_dev); + netif_start_queue(dev); + + return 0; +} + +static void emac_shutdown(struct net_device *dev) +{ + unsigned int reg_val; + struct emac_board_info *db = netdev_priv(dev); + + /* Disable all interrupt */ + writel(0, db->membase + EMAC_INT_CTL_REG); + + /* clear interupt status */ + reg_val = readl(db->membase + EMAC_INT_STA_REG); + writel(reg_val, db->membase + EMAC_INT_STA_REG); + + /* Disable RX/TX */ + reg_val = readl(db->membase + EMAC_CTL_REG); + reg_val &= ~(EMAC_CTL_TX_EN | EMAC_CTL_RX_EN | EMAC_CTL_RESET); + writel(reg_val, db->membase + EMAC_CTL_REG); +} + +/* Stop the interface. + * The interface is stopped when it is brought. + */ +static int emac_stop(struct net_device *ndev) +{ + struct emac_board_info *db = netdev_priv(ndev); + + if (netif_msg_ifdown(db)) + dev_dbg(db->dev, "shutting down %s\n", ndev->name); + + netif_stop_queue(ndev); + netif_carrier_off(ndev); + + phy_stop(db->phy_dev); + + emac_mdio_remove(ndev); + + emac_shutdown(ndev); + + return 0; +} + +static const struct net_device_ops emac_netdev_ops = { + .ndo_open = emac_open, + .ndo_stop = emac_stop, + .ndo_start_xmit = emac_start_xmit, + .ndo_tx_timeout = emac_timeout, + .ndo_do_ioctl = emac_ioctl, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = emac_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = emac_poll_controller, +#endif +}; + +/* Search EMAC board, allocate space and register it + */ +static int emac_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct emac_board_info *db; + struct net_device *ndev; + int ret = 0; + const char *mac_addr; + + ndev = alloc_etherdev(sizeof(struct emac_board_info)); + if (!ndev) { + dev_err(&pdev->dev, "could not allocate device.\n"); + return -ENOMEM; + } + + SET_NETDEV_DEV(ndev, &pdev->dev); + + db = netdev_priv(ndev); + memset(db, 0, sizeof(*db)); + + db->dev = &pdev->dev; + db->ndev = ndev; + db->pdev = pdev; + + spin_lock_init(&db->lock); + + db->membase = of_iomap(np, 0); + if (!db->membase) { + dev_err(&pdev->dev, "failed to remap registers\n"); + return -ENOMEM; + goto out; + } + + /* fill in parameters for net-dev structure */ + ndev->base_addr = (unsigned long)db->membase; + ndev->irq = irq_of_parse_and_map(np, 0); + if (ndev->irq == -ENXIO) { + netdev_err(ndev, "No irq resource\n"); + ret = ndev->irq; + goto out; + } + + db->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(db->clk)) + goto out; + + clk_prepare_enable(db->clk); + + db->phy_node = of_parse_phandle(np, "phy", 0); + if (!db->phy_node) { + dev_err(&pdev->dev, "no associated PHY\n"); + ret = -ENODEV; + goto out; + } + + /* Read MAC-address from DT */ + mac_addr = of_get_mac_address(np); + if (mac_addr) + memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); + + /* Check if the MAC address is valid, if not get a random one */ + if (!is_valid_ether_addr(ndev->dev_addr)) { + eth_hw_addr_random(ndev); + dev_warn(&pdev->dev, "using random MAC address %pM\n", + ndev->dev_addr); + } + + db->emacrx_completed_flag = 1; + emac_powerup(ndev); + emac_reset(db); + + ether_setup(ndev); + + ndev->netdev_ops = &emac_netdev_ops; + ndev->watchdog_timeo = msecs_to_jiffies(watchdog); + ndev->ethtool_ops = &emac_ethtool_ops; + +#ifdef CONFIG_NET_POLL_CONTROLLER + ndev->poll_controller = &emac_poll_controller; +#endif + + platform_set_drvdata(pdev, ndev); + + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(ndev); + + ret = register_netdev(ndev); + if (ret) { + dev_err(&pdev->dev, "Registering netdev failed!\n"); + ret = -ENODEV; + goto out; + } + + dev_info(&pdev->dev, "%s: at %p, IRQ %d MAC: %pM\n", + ndev->name, db->membase, ndev->irq, ndev->dev_addr); + + return 0; + +out: + dev_err(db->dev, "not found (%d).\n", ret); + + free_netdev(ndev); + + return ret; +} + +static int emac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + free_netdev(ndev); + + dev_dbg(&pdev->dev, "released and freed device\n"); + return 0; +} + +static int emac_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + netif_carrier_off(ndev); + netif_device_detach(ndev); + emac_shutdown(ndev); + + return 0; +} + +static int emac_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + struct emac_board_info *db = netdev_priv(ndev); + + emac_reset(db); + emac_init_device(ndev); + netif_device_attach(ndev); + + return 0; +} + +static const struct of_device_id emac_of_match[] = { + {.compatible = "allwinner,sun4i-emac",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, emac_of_match); + +static struct platform_driver emac_driver = { + .driver = { + .name = "sun4i-emac", + .of_match_table = emac_of_match, + }, + .probe = emac_probe, + .remove = emac_remove, + .suspend = emac_suspend, + .resume = emac_resume, +}; + +module_platform_driver(emac_driver); + +MODULE_AUTHOR("Stefan Roese "); +MODULE_AUTHOR("Maxime Ripard "); +MODULE_DESCRIPTION("Allwinner A10 emac network driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.h b/drivers/net/ethernet/allwinner/sun4i-emac.h new file mode 100644 index 000000000000..38c72d9ec600 --- /dev/null +++ b/drivers/net/ethernet/allwinner/sun4i-emac.h @@ -0,0 +1,108 @@ +/* + * Allwinner EMAC Fast Ethernet driver for Linux. + * + * Copyright 2012 Stefan Roese + * Copyright 2013 Maxime Ripard + * + * Based on the Linux driver provided by Allwinner: + * Copyright (C) 1997 Sten Wang + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef _SUN4I_EMAC_H_ +#define _SUN4I_EMAC_H_ + +#define EMAC_CTL_REG (0x00) +#define EMAC_CTL_RESET (1 << 0) +#define EMAC_CTL_TX_EN (1 << 1) +#define EMAC_CTL_RX_EN (1 << 2) +#define EMAC_TX_MODE_REG (0x04) +#define EMAC_TX_MODE_ABORTED_FRAME_EN (1 << 0) +#define EMAC_TX_MODE_DMA_EN (1 << 1) +#define EMAC_TX_FLOW_REG (0x08) +#define EMAC_TX_CTL0_REG (0x0c) +#define EMAC_TX_CTL1_REG (0x10) +#define EMAC_TX_INS_REG (0x14) +#define EMAC_TX_PL0_REG (0x18) +#define EMAC_TX_PL1_REG (0x1c) +#define EMAC_TX_STA_REG (0x20) +#define EMAC_TX_IO_DATA_REG (0x24) +#define EMAC_TX_IO_DATA1_REG (0x28) +#define EMAC_TX_TSVL0_REG (0x2c) +#define EMAC_TX_TSVH0_REG (0x30) +#define EMAC_TX_TSVL1_REG (0x34) +#define EMAC_TX_TSVH1_REG (0x38) +#define EMAC_RX_CTL_REG (0x3c) +#define EMAC_RX_CTL_AUTO_DRQ_EN (1 << 1) +#define EMAC_RX_CTL_DMA_EN (1 << 2) +#define EMAC_RX_CTL_PASS_ALL_EN (1 << 4) +#define EMAC_RX_CTL_PASS_CTL_EN (1 << 5) +#define EMAC_RX_CTL_PASS_CRC_ERR_EN (1 << 6) +#define EMAC_RX_CTL_PASS_LEN_ERR_EN (1 << 7) +#define EMAC_RX_CTL_PASS_LEN_OOR_EN (1 << 8) +#define EMAC_RX_CTL_ACCEPT_UNICAST_EN (1 << 16) +#define EMAC_RX_CTL_DA_FILTER_EN (1 << 17) +#define EMAC_RX_CTL_ACCEPT_MULTICAST_EN (1 << 20) +#define EMAC_RX_CTL_HASH_FILTER_EN (1 << 21) +#define EMAC_RX_CTL_ACCEPT_BROADCAST_EN (1 << 22) +#define EMAC_RX_CTL_SA_FILTER_EN (1 << 24) +#define EMAC_RX_CTL_SA_FILTER_INVERT_EN (1 << 25) +#define EMAC_RX_HASH0_REG (0x40) +#define EMAC_RX_HASH1_REG (0x44) +#define EMAC_RX_STA_REG (0x48) +#define EMAC_RX_IO_DATA_REG (0x4c) +#define EMAC_RX_IO_DATA_LEN(x) (x & 0xffff) +#define EMAC_RX_IO_DATA_STATUS(x) ((x >> 16) & 0xffff) +#define EMAC_RX_IO_DATA_STATUS_CRC_ERR (1 << 4) +#define EMAC_RX_IO_DATA_STATUS_LEN_ERR (3 << 5) +#define EMAC_RX_IO_DATA_STATUS_OK (1 << 7) +#define EMAC_RX_FBC_REG (0x50) +#define EMAC_INT_CTL_REG (0x54) +#define EMAC_INT_STA_REG (0x58) +#define EMAC_MAC_CTL0_REG (0x5c) +#define EMAC_MAC_CTL0_RX_FLOW_CTL_EN (1 << 2) +#define EMAC_MAC_CTL0_TX_FLOW_CTL_EN (1 << 3) +#define EMAC_MAC_CTL0_SOFT_RESET (1 << 15) +#define EMAC_MAC_CTL1_REG (0x60) +#define EMAC_MAC_CTL1_DUPLEX_EN (1 << 0) +#define EMAC_MAC_CTL1_LEN_CHECK_EN (1 << 1) +#define EMAC_MAC_CTL1_HUGE_FRAME_EN (1 << 2) +#define EMAC_MAC_CTL1_DELAYED_CRC_EN (1 << 3) +#define EMAC_MAC_CTL1_CRC_EN (1 << 4) +#define EMAC_MAC_CTL1_PAD_EN (1 << 5) +#define EMAC_MAC_CTL1_PAD_CRC_EN (1 << 6) +#define EMAC_MAC_CTL1_AD_SHORT_FRAME_EN (1 << 7) +#define EMAC_MAC_CTL1_BACKOFF_DIS (1 << 12) +#define EMAC_MAC_IPGT_REG (0x64) +#define EMAC_MAC_IPGT_HALF_DUPLEX (0x12) +#define EMAC_MAC_IPGT_FULL_DUPLEX (0x15) +#define EMAC_MAC_IPGR_REG (0x68) +#define EMAC_MAC_IPGR_IPG1 (0x0c) +#define EMAC_MAC_IPGR_IPG2 (0x12) +#define EMAC_MAC_CLRT_REG (0x6c) +#define EMAC_MAC_CLRT_COLLISION_WINDOW (0x37) +#define EMAC_MAC_CLRT_RM (0x0f) +#define EMAC_MAC_MAXF_REG (0x70) +#define EMAC_MAC_SUPP_REG (0x74) +#define EMAC_MAC_TEST_REG (0x78) +#define EMAC_MAC_MCFG_REG (0x7c) +#define EMAC_MAC_A0_REG (0x98) +#define EMAC_MAC_A1_REG (0x9c) +#define EMAC_MAC_A2_REG (0xa0) +#define EMAC_SAFX_L_REG0 (0xa4) +#define EMAC_SAFX_H_REG0 (0xa8) +#define EMAC_SAFX_L_REG1 (0xac) +#define EMAC_SAFX_H_REG1 (0xb0) +#define EMAC_SAFX_L_REG2 (0xb4) +#define EMAC_SAFX_H_REG2 (0xb8) +#define EMAC_SAFX_L_REG3 (0xbc) +#define EMAC_SAFX_H_REG3 (0xc0) + +#define EMAC_PHY_DUPLEX (1 << 8) + +#define EMAC_EEPROM_MAGIC (0x444d394b) +#define EMAC_UNDOCUMENTED_MAGIC (0x0143414d) +#endif /* _SUN4I_EMAC_H_ */ -- GitLab From 4bdcb1dd9feb03608e12cfa46aba385035af8ea5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 30 May 2013 03:49:21 +0000 Subject: [PATCH 0564/2900] net: Add MDIO bus driver for the Allwinner EMAC This patch adds a separate driver for the MDIO interface of the Allwinner ethernet controllers. Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- .../bindings/net/allwinner,sun4i-mdio.txt | 26 +++ drivers/net/phy/Kconfig | 10 + drivers/net/phy/Makefile | 1 + drivers/net/phy/mdio-sun4i.c | 194 ++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt create mode 100644 drivers/net/phy/mdio-sun4i.c diff --git a/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt new file mode 100644 index 000000000000..00b9f9a3ec1d --- /dev/null +++ b/Documentation/devicetree/bindings/net/allwinner,sun4i-mdio.txt @@ -0,0 +1,26 @@ +* Allwinner A10 MDIO Ethernet Controller interface + +Required properties: +- compatible: should be "allwinner,sun4i-mdio". +- reg: address and length of the register set for the device. + +Optional properties: +- phy-supply: phandle to a regulator if the PHY needs one + +Example at the SoC level: +mdio@01c0b080 { + compatible = "allwinner,sun4i-mdio"; + reg = <0x01c0b080 0x14>; + #address-cells = <1>; + #size-cells = <0>; +}; + +And at the board level: + +mdio@01c0b080 { + phy-supply = <®_emac_3v3>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 1e11f2bfd9ce..3a316b30089f 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -144,6 +144,16 @@ config MDIO_OCTEON If in doubt, say Y. +config MDIO_SUN4I + tristate "Allwinner sun4i MDIO interface support" + depends on ARCH_SUNXI + select REGULATOR + select REGULATOR_FIXED_VOLTAGE + help + This driver supports the MDIO interface found in the network + interface units of the Allwinner SoC that have an EMAC (A10, + A12, A10s, etc.) + config MDIO_BUS_MUX tristate depends on OF_MDIO diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 9645e389a58d..23a2ab2e847e 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_AMD_PHY) += amd.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o +obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c new file mode 100644 index 000000000000..61d3f4ebf52e --- /dev/null +++ b/drivers/net/phy/mdio-sun4i.c @@ -0,0 +1,194 @@ +/* + * Allwinner EMAC MDIO interface driver + * + * Copyright 2012-2013 Stefan Roese + * Copyright 2013 Maxime Ripard + * + * Based on the Linux driver provided by Allwinner: + * Copyright (C) 1997 Sten Wang + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EMAC_MAC_MCMD_REG (0x00) +#define EMAC_MAC_MADR_REG (0x04) +#define EMAC_MAC_MWTD_REG (0x08) +#define EMAC_MAC_MRDD_REG (0x0c) +#define EMAC_MAC_MIND_REG (0x10) +#define EMAC_MAC_SSRR_REG (0x14) + +#define MDIO_TIMEOUT (msecs_to_jiffies(100)) + +struct sun4i_mdio_data { + void __iomem *membase; + struct regulator *regulator; +}; + +static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct sun4i_mdio_data *data = bus->priv; + unsigned long start_jiffies; + int value; + + /* issue the phy address and reg */ + writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); + /* pull up the phy io line */ + writel(0x1, data->membase + EMAC_MAC_MCMD_REG); + + /* Wait read complete */ + start_jiffies = jiffies; + while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { + if (time_after(start_jiffies, + start_jiffies + MDIO_TIMEOUT)) + return -ETIMEDOUT; + msleep(1); + } + + /* push down the phy io line */ + writel(0x0, data->membase + EMAC_MAC_MCMD_REG); + /* and read data */ + value = readl(data->membase + EMAC_MAC_MRDD_REG); + + return value; +} + +static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) +{ + struct sun4i_mdio_data *data = bus->priv; + unsigned long start_jiffies; + + /* issue the phy address and reg */ + writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); + /* pull up the phy io line */ + writel(0x1, data->membase + EMAC_MAC_MCMD_REG); + + /* Wait read complete */ + start_jiffies = jiffies; + while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { + if (time_after(start_jiffies, + start_jiffies + MDIO_TIMEOUT)) + return -ETIMEDOUT; + msleep(1); + } + + /* push down the phy io line */ + writel(0x0, data->membase + EMAC_MAC_MCMD_REG); + /* and write data */ + writel(value, data->membase + EMAC_MAC_MWTD_REG); + + return 0; +} + +static int sun4i_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static int sun4i_mdio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct mii_bus *bus; + struct sun4i_mdio_data *data; + int ret, i; + + bus = mdiobus_alloc_size(sizeof(*data)); + if (!bus) + return -ENOMEM; + + bus->name = "sun4i_mii_bus"; + bus->read = &sun4i_mdio_read; + bus->write = &sun4i_mdio_write; + bus->reset = &sun4i_mdio_reset; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); + bus->parent = &pdev->dev; + + bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!bus->irq) { + ret = -ENOMEM; + goto err_out_free_mdiobus; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + bus->irq[i] = PHY_POLL; + + data = bus->priv; + data->membase = of_iomap(np, 0); + if (!data->membase) { + ret = -ENOMEM; + goto err_out_free_mdio_irq; + } + + data->regulator = devm_regulator_get(&pdev->dev, "phy"); + if (IS_ERR(data->regulator)) { + if (PTR_ERR(data->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + dev_info(&pdev->dev, "no regulator found\n"); + } else { + ret = regulator_enable(data->regulator); + if (ret) + goto err_out_free_mdio_irq; + } + + ret = of_mdiobus_register(bus, np); + if (ret < 0) + goto err_out_disable_regulator; + + platform_set_drvdata(pdev, bus); + + return 0; + +err_out_disable_regulator: + regulator_disable(data->regulator); +err_out_free_mdio_irq: + kfree(bus->irq); +err_out_free_mdiobus: + mdiobus_free(bus); + return ret; +} + +static int sun4i_mdio_remove(struct platform_device *pdev) +{ + struct mii_bus *bus = platform_get_drvdata(pdev); + + mdiobus_unregister(bus); + kfree(bus->irq); + mdiobus_free(bus); + + return 0; +} + +static const struct of_device_id sun4i_mdio_dt_ids[] = { + { .compatible = "allwinner,sun4i-mdio" }, + { } +}; +MODULE_DEVICE_TABLE(of, sun4i_mdio_dt_ids); + +static struct platform_driver sun4i_mdio_driver = { + .probe = sun4i_mdio_probe, + .remove = sun4i_mdio_remove, + .driver = { + .name = "sun4i-mdio", + .of_match_table = sun4i_mdio_dt_ids, + }, +}; + +module_platform_driver(sun4i_mdio_driver); + +MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver"); +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); -- GitLab From b21da664120b1c8332fc5059a1e7c1462dd26433 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 30 May 2013 03:49:22 +0000 Subject: [PATCH 0565/2900] ARM: sun4i: Add muxing options for the ethernet controller The EMAC only has one pinset available for muxing, so hopefully, we cover all cases. Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- arch/arm/boot/dts/sun4i-a10.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index e7ef619a70a2..ff1f41fc6eba 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -199,6 +199,17 @@ allwinner,drive = <0>; allwinner,pull = <0>; }; + + emac_pins_a: emac0@0 { + allwinner,pins = "PA0", "PA1", "PA2", + "PA3", "PA4", "PA5", "PA6", + "PA7", "PA8", "PA9", "PA10", + "PA11", "PA12", "PA13", "PA14", + "PA15", "PA16"; + allwinner,function = "emac"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; }; timer@01c20c00 { -- GitLab From e38afcb33ff4b472254c8f6f140699e002c44d84 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 30 May 2013 03:49:23 +0000 Subject: [PATCH 0566/2900] ARM: sunxi: Add EMAC controller node to sun4i DTSI Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- arch/arm/boot/dts/sun4i-a10.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index ff1f41fc6eba..983da33bebaa 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -163,6 +163,22 @@ reg = <0x01c20000 0x300000>; ranges; + emac: ethernet@01c0b000 { + compatible = "allwinner,sun4i-emac"; + reg = <0x01c0b000 0x1000>; + interrupts = <55>; + clocks = <&ahb_gates 17>; + status = "disabled"; + }; + + mdio@01c0b080 { + compatible = "allwinner,sun4i-mdio"; + reg = <0x01c0b080 0x14>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + intc: interrupt-controller@01c20400 { compatible = "allwinner,sun4i-ic"; reg = <0x01c20400 0x400>; -- GitLab From e5a84bac5d6797c64541f87e7a567d56699bbb74 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 30 May 2013 03:49:24 +0000 Subject: [PATCH 0567/2900] ARM: cubieboard: Enable ethernet (EMAC) support in dts Signed-off-by: Stefan Roese Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts index b70fe0db6bb7..e752b570b4ec 100644 --- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts @@ -27,6 +27,21 @@ }; soc@01c20000 { + emac: ethernet@01c0b000 { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy1>; + status = "okay"; + }; + + mdio@01c0b080 { + status = "okay"; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + pinctrl@01c20800 { led_pins_cubieboard: led_pins@0 { allwinner,pins = "PH20", "PH21"; -- GitLab From d97a079a79a7dcbc2470572b41cd1f07a16d8b7f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 30 May 2013 03:49:25 +0000 Subject: [PATCH 0568/2900] ARM: sunxi: Add EMAC Controller to Hackberry dt The Hackberry has a PHY that needs to be powered up through a GPIO, so we need to use a fixed regulator here. Signed-off-by: Maxime Ripard Tested-by: Richard Genoud Signed-off-by: David S. Miller --- arch/arm/boot/dts/sun4i-a10-hackberry.dts | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts index b9efac100c85..3514b37d66bc 100644 --- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts +++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts @@ -23,10 +23,51 @@ }; soc@01c20000 { + emac: ethernet@01c0b000 { + pinctrl-names = "default"; + pinctrl-0 = <&emac_pins_a>; + phy = <&phy0>; + status = "okay"; + }; + + mdio@01c0b080 { + phy-supply = <®_emac_3v3>; + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + + pio: pinctrl@01c20800 { + pinctrl-names = "default"; + pinctrl-0 = <&hackberry_hogs>; + + hackberry_hogs: hogs@0 { + allwinner,pins = "PH19"; + allwinner,function = "gpio_out"; + allwinner,drive = <0>; + allwinner,pull = <0>; + }; + }; + uart0: serial@01c28000 { pinctrl-names = "default"; pinctrl-0 = <&uart0_pins_a>; status = "okay"; }; }; + + regulators { + compatible = "simple-bus"; + + reg_emac_3v3: emac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "emac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + gpio = <&pio 7 19 0>; + }; + }; }; -- GitLab From 28a19fe60f4f31cbd349f8473f0483aa7500acf5 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Wed, 29 May 2013 20:22:01 +0000 Subject: [PATCH 0569/2900] drivers: net: davinci_cpdma: remove CRC bytes from skb added by CPDMA Additional 4 bytes found in the skb is the CRC calculated by the CPDMA hardware, check the CRC bit in CPDMA status field of Descriptor and remove the CRC length from the skb. This extra 4 byte can be seen when capturing packets using tcpdump. This has been tested in TI816x platform. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_cpdma.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 49dfd592ac1e..a377bc727740 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -64,6 +64,7 @@ #define CPDMA_DESC_TO_PORT_EN BIT(20) #define CPDMA_TO_PORT_SHIFT 16 #define CPDMA_DESC_PORT_MASK (BIT(18) | BIT(17) | BIT(16)) +#define CPDMA_DESC_CRC_LEN 4 #define CPDMA_TEARDOWN_VALUE 0xfffffffc @@ -798,6 +799,10 @@ static int __cpdma_chan_process(struct cpdma_chan *chan) status = -EBUSY; goto unlock_ret; } + + if (status & CPDMA_DESC_PASS_CRC) + outlen -= CPDMA_DESC_CRC_LEN; + status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE | CPDMA_DESC_PORT_MASK); -- GitLab From 5c510811547f88522b00623417b97d9fba85a06b Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Thu, 30 May 2013 02:52:23 +0000 Subject: [PATCH 0570/2900] be2net: Implement initiate FW dump feature for Lancer Added code to initiate FW dump via ethtool. Driver checks if the previous dump has been cleared before initiating the dump. It doesn't initiate the dump if it is not cleared. Signed-off-by: Kalesh AP Signed-off-by: Somnath Kotur Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 3 + drivers/net/ethernet/emulex/benet/be_cmds.c | 66 +++++++++++++++++++ drivers/net/ethernet/emulex/benet/be_cmds.h | 3 + .../net/ethernet/emulex/benet/be_ethtool.c | 29 ++++++++ drivers/net/ethernet/emulex/benet/be_hw.h | 2 + drivers/net/ethernet/emulex/benet/be_main.c | 37 +---------- 6 files changed, 105 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index edce38bf83c9..fcc30a2d831b 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -332,6 +332,9 @@ enum vf_state { #define BE_VF_UC_PMAC_COUNT 2 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) +/* Ethtool set_dump flags */ +#define LANCER_INITIATE_FW_DUMP 0x1 + struct phy_info { u8 transceiver; u8 autoneg; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index a236ecd27cf3..4d0ec3649a63 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -3255,6 +3255,72 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, return status; } +static int lancer_wait_idle(struct be_adapter *adapter) +{ +#define SLIPORT_IDLE_TIMEOUT 30 + u32 reg_val; + int status = 0, i; + + for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { + reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); + if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) + break; + + ssleep(1); + } + + if (i == SLIPORT_IDLE_TIMEOUT) + status = -1; + + return status; +} + +int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask) +{ + int status = 0; + + status = lancer_wait_idle(adapter); + if (status) + return status; + + iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET); + + return status; +} + +/* Routine to check whether dump image is present or not */ +bool dump_present(struct be_adapter *adapter) +{ + u32 sliport_status = 0; + + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + return !!(sliport_status & SLIPORT_STATUS_DIP_MASK); +} + +int lancer_initiate_dump(struct be_adapter *adapter) +{ + int status; + + /* give firmware reset and diagnostic dump */ + status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK | + PHYSDEV_CONTROL_DD_MASK); + if (status < 0) { + dev_err(&adapter->pdev->dev, "Firmware reset failed\n"); + return status; + } + + status = lancer_wait_idle(adapter); + if (status) + return status; + + if (!dump_present(adapter)) { + dev_err(&adapter->pdev->dev, "Dump image not present\n"); + return -1; + } + + return 0; +} + /* Uses sync mcc */ int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 025bdb0d1764..5228d88c5a02 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, struct be_dma_mem *cmd, struct be_fat_conf_params *cfgs); extern int lancer_wait_ready(struct be_adapter *adapter); +extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask); +extern int lancer_initiate_dump(struct be_adapter *adapter); +extern bool dump_present(struct be_adapter *adapter); extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); extern int be_cmd_get_func_config(struct be_adapter *adapter); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index f3ee07758198..4f8c941217cc 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -669,6 +669,34 @@ be_set_phys_id(struct net_device *netdev, return 0; } +static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct device *dev = &adapter->pdev->dev; + int status; + + if (!lancer_chip(adapter)) { + dev_err(dev, "FW dump not supported\n"); + return -EOPNOTSUPP; + } + + if (dump_present(adapter)) { + dev_err(dev, "Previous dump not cleared, not forcing dump\n"); + return 0; + } + + switch (dump->flag) { + case LANCER_INITIATE_FW_DUMP: + status = lancer_initiate_dump(adapter); + if (!status) + dev_info(dev, "F/w dump initiated successfully\n"); + break; + default: + dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag); + return -EINVAL; + } + return status; +} static void be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) @@ -1106,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = { .set_pauseparam = be_set_pauseparam, .get_strings = be_get_stat_strings, .set_phys_id = be_set_phys_id, + .set_dump = be_set_dump, .get_msglevel = be_get_msg_level, .set_msglevel = be_set_msg_level, .get_sset_count = be_get_sset_count, diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 3c1099b47f2a..0311d9bfe858 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -53,10 +53,12 @@ #define PHYSDEV_CONTROL_OFFSET 0x414 #define SLIPORT_STATUS_ERR_MASK 0x80000000 +#define SLIPORT_STATUS_DIP_MASK 0x02000000 #define SLIPORT_STATUS_RN_MASK 0x01000000 #define SLIPORT_STATUS_RDY_MASK 0x00800000 #define SLI_PORT_CONTROL_IP_MASK 0x08000000 #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 +#define PHYSDEV_CONTROL_DD_MASK 0x00000004 #define PHYSDEV_CONTROL_INP_MASK 0x40000000 #define SLIPORT_ERROR_NO_RESOURCE1 0x2 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 1140a86ff5ea..5d9044e4afe2 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3551,40 +3551,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter, return 0; } -static int lancer_wait_idle(struct be_adapter *adapter) -{ -#define SLIPORT_IDLE_TIMEOUT 30 - u32 reg_val; - int status = 0, i; - - for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { - reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); - if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) - break; - - ssleep(1); - } - - if (i == SLIPORT_IDLE_TIMEOUT) - status = -1; - - return status; -} - -static int lancer_fw_reset(struct be_adapter *adapter) -{ - int status = 0; - - status = lancer_wait_idle(adapter); - if (status) - return status; - - iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db + - PHYSDEV_CONTROL_OFFSET); - - return status; -} - static int lancer_fw_download(struct be_adapter *adapter, const struct firmware *fw) { @@ -3662,7 +3628,8 @@ static int lancer_fw_download(struct be_adapter *adapter, } if (change_status == LANCER_FW_RESET_NEEDED) { - status = lancer_fw_reset(adapter); + status = lancer_physdev_ctrl(adapter, + PHYSDEV_CONTROL_FW_RESET_MASK); if (status) { dev_err(&adapter->pdev->dev, "Adapter busy for FW reset.\n" -- GitLab From e69972f52bdc4bc384a21a6561d5673b4a94e989 Mon Sep 17 00:00:00 2001 From: Jay Hernandez Date: Thu, 30 May 2013 03:24:14 +0000 Subject: [PATCH 0571/2900] cxgb4: Force uninitialized state if FW_ON_ADAPTER is < FW_VERSION and we're the MASTER_PF Forcing uninitialized state allows us to upgrade and reinitialize the adapter. FW_VERSION_T4 = 1.4.0.0 FW_VERSION_T5 = 0.0.0.0 At this point driver supports above and greater than above version of firmware. If it doesn't find the required firmware version than it forces the adapter to be reinitialized as shown below. 1) If FW_ON_ADAPTER < FW_VERSION and we're the MASTER_PF force uninitialized state and a FW upgrade if available. - If FW_ON_ADAPTER < /lib/firmware/cxgb4/t*fw.bin we will update the adapters FW. - If FW_ON_ADAPTER >= /lib/firmware/cxgb4/t*fw.bin don't upgrade FW. - If upgrade_fw() fails force reinitialization of the adapter anyways, it might still work. Either way forcing the uninitialized state allows cxgb4 reinitialize FW. 2) If FW_ON_ADAPTER >= FW_VERSION driver follows normal path. Signed-off-by: Jay Hernandez Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 2 +- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 27 +++++++++++++++++-- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 9 +++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 681804b30a3f..2aafb809e067 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -51,7 +51,7 @@ #include "t4_hw.h" #define FW_VERSION_MAJOR 1 -#define FW_VERSION_MINOR 1 +#define FW_VERSION_MINOR 4 #define FW_VERSION_MICRO 0 #define FW_VERSION_MAJOR_T5 0 diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 3cd397d60434..5a3256b083f2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -4842,8 +4842,17 @@ static int adap_init0(struct adapter *adap) * is excessively mismatched relative to the driver.) */ ret = t4_check_fw_version(adap); + + /* The error code -EFAULT is returned by t4_check_fw_version() if + * firmware on adapter < supported firmware. If firmware on adapter + * is too old (not supported by driver) and we're the MASTER_PF set + * adapter state to DEV_STATE_UNINIT to force firmware upgrade + * and reinitialization. + */ + if ((adap->flags & MASTER_PF) && ret == -EFAULT) + state = DEV_STATE_UNINIT; if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { - if (ret == -EINVAL || ret > 0) { + if (ret == -EINVAL || ret == -EFAULT || ret > 0) { if (upgrade_fw(adap) >= 0) { /* * Note that the chip was reset as part of the @@ -4852,7 +4861,21 @@ static int adap_init0(struct adapter *adap) */ reset = 0; ret = t4_check_fw_version(adap); - } + } else + if (ret == -EFAULT) { + /* + * Firmware is old but still might + * work if we force reinitialization + * of the adapter. Ignoring FW upgrade + * failure. + */ + dev_warn(adap->pdev_dev, + "Ignoring firmware upgrade " + "failure, and forcing driver " + "to reinitialize the " + "adapter.\n"); + ret = 0; + } } if (ret < 0) return ret; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index d02d4e8c4417..bff89a437b76 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -938,6 +938,15 @@ int t4_check_fw_version(struct adapter *adapter) memcpy(adapter->params.api_vers, api_vers, sizeof(adapter->params.api_vers)); + if (major < exp_major || (major == exp_major && minor < exp_minor) || + (major == exp_major && minor == exp_minor && micro < exp_micro)) { + dev_err(adapter->pdev_dev, + "Card has firmware version %u.%u.%u, minimum " + "supported firmware is %u.%u.%u.\n", major, minor, + micro, exp_major, exp_minor, exp_micro); + return -EFAULT; + } + if (major != exp_major) { /* major mismatch - fail */ dev_err(adapter->pdev_dev, "card FW has major version %u, driver wants %u\n", -- GitLab From ab1ef141161c158360fab671e72226cffb5f9774 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Tue, 19 Mar 2013 09:48:35 +0530 Subject: [PATCH 0572/2900] ath6kl: Check wmi ready event status before validating abi version There is no point to check firmware ABI version when the driver fails to wait for WMI_READY event during the boot time. For such failures, the driver should assume the firmware is not booted and start doing cleanup. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 40ffee6184fd..6a67881f94d6 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1696,10 +1696,16 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) test_bit(WMI_READY, &ar->flag), WMI_TIMEOUT); + if (timeleft <= 0) { + clear_bit(WMI_READY, &ar->flag); + ath6kl_err("wmi is not ready or wait was interrupted: %ld\n", + timeleft); + ret = -EIO; + goto err_htc_stop; + } ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); - if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { ath6kl_info("%s %s fw %s api %d%s\n", ar->hw.name, @@ -1718,12 +1724,6 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) goto err_htc_stop; } - if (!timeleft || signal_pending(current)) { - ath6kl_err("wmi is not ready or wait was interrupted\n"); - ret = -EIO; - goto err_htc_stop; - } - ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__); /* communicate the wmi protocol verision to the target */ -- GitLab From ade983307453cf6043454dd9ac08abab5193d704 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 25 Apr 2013 16:31:22 +0300 Subject: [PATCH 0573/2900] wireless: ath6kl: re-use native helper to parse MAC There is native mac_pton() function which helps to parse MAC. Signed-off-by: Andy Shevchenko Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index fe38b836cb26..dbfd17d0a5fa 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1240,20 +1240,14 @@ static ssize_t ath6kl_force_roam_write(struct file *file, char buf[20]; size_t len; u8 bssid[ETH_ALEN]; - int i; - int addr[ETH_ALEN]; len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; - if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) - != ETH_ALEN) + if (!mac_pton(buf, bssid)) return -EINVAL; - for (i = 0; i < ETH_ALEN; i++) - bssid[i] = addr[i]; ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid); if (ret) -- GitLab From 0b3d3ff15fa67b5417aae67bdc6252c001b2631d Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 15 May 2013 10:22:10 +0530 Subject: [PATCH 0574/2900] ath6kl: Rename USB driver's suspend/resume/reset_resume Rename USB driver's suspend/resume/reset_resume callbacks with 'pm' prefix. This is necessary to differentiate it from cfg80211/hif suspend/resume/reset_resume callbacks. Cc: Sivanesan Rajapupathi Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/usb.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index bed0d337712d..cf488f8f049d 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -1152,7 +1152,7 @@ static void ath6kl_usb_remove(struct usb_interface *interface) #ifdef CONFIG_PM -static int ath6kl_usb_suspend(struct usb_interface *interface, +static int ath6kl_usb_pm_suspend(struct usb_interface *interface, pm_message_t message) { struct ath6kl_usb *device; @@ -1162,7 +1162,7 @@ static int ath6kl_usb_suspend(struct usb_interface *interface, return 0; } -static int ath6kl_usb_resume(struct usb_interface *interface) +static int ath6kl_usb_pm_resume(struct usb_interface *interface) { struct ath6kl_usb *device; device = usb_get_intfdata(interface); @@ -1175,7 +1175,7 @@ static int ath6kl_usb_resume(struct usb_interface *interface) return 0; } -static int ath6kl_usb_reset_resume(struct usb_interface *intf) +static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) { if (usb_get_intfdata(intf)) ath6kl_usb_remove(intf); @@ -1184,9 +1184,9 @@ static int ath6kl_usb_reset_resume(struct usb_interface *intf) #else -#define ath6kl_usb_suspend NULL -#define ath6kl_usb_resume NULL -#define ath6kl_usb_reset_resume NULL +#define ath6kl_usb_pm_suspend NULL +#define ath6kl_usb_pm_resume NULL +#define ath6kl_usb_pm_reset_resume NULL #endif @@ -1201,9 +1201,9 @@ MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); static struct usb_driver ath6kl_usb_driver = { .name = "ath6kl_usb", .probe = ath6kl_usb_probe, - .suspend = ath6kl_usb_suspend, - .resume = ath6kl_usb_resume, - .reset_resume = ath6kl_usb_reset_resume, + .suspend = ath6kl_usb_pm_suspend, + .resume = ath6kl_usb_pm_resume, + .reset_resume = ath6kl_usb_pm_reset_resume, .disconnect = ath6kl_usb_remove, .id_table = ath6kl_usb_ids, .supports_autosuspend = true, -- GitLab From 8c40e4e0e158aca76c657533ae57fa3e33655778 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 15 May 2013 10:22:24 +0530 Subject: [PATCH 0575/2900] ath6kl: Fix a suspend/resume crash in AR6004 USB cfg80211 suspend/resume callbacks are not yet implemented for AR6004 USB. Introduce dummy handlers for these to avoid NULL pointer dereference. Cc: Sivanesan Rajapupathi Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/usb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index cf488f8f049d..f38ff6a6255e 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -1061,6 +1061,22 @@ static void ath6kl_usb_cleanup_scatter(struct ath6kl *ar) return; } +static int ath6kl_usb_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) +{ + /* + * cfg80211 suspend/WOW currently not supported for USB. + */ + return 0; +} + +static int ath6kl_usb_resume(struct ath6kl *ar) +{ + /* + * cfg80211 resume currently not supported for USB. + */ + return 0; +} + static const struct ath6kl_hif_ops ath6kl_usb_ops = { .diag_read32 = ath6kl_usb_diag_read32, .diag_write32 = ath6kl_usb_diag_write32, @@ -1074,6 +1090,8 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = { .pipe_map_service = ath6kl_usb_map_service_pipe, .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, .cleanup_scatter = ath6kl_usb_cleanup_scatter, + .suspend = ath6kl_usb_suspend, + .resume = ath6kl_usb_resume, }; /* ath6kl usb driver registered functions */ -- GitLab From 37291fc61253cd34db40b7a60be4497db776db41 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Apr 2013 14:02:34 +0200 Subject: [PATCH 0576/2900] ath6kl: Unify sg_sz and buf_sz in ath6kl_sdio_alloc_prep_scat_req() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sg_sz and buf_sz are initialized and used in a mutual exclusive way. However, some versions of gcc are not smart enough to see this: drivers/net/wireless/ath/ath6kl/sdio.c: In function ‘ath6kl_sdio_alloc_prep_scat_req’: drivers/net/wireless/ath/ath6kl/sdio.c:338: warning: ‘sg_sz’ may be used uninitialized in this function Unify the sg_sz and buf_sz variables into a single size variable to kill the compiler warning. Signed-off-by: Geert Uytterhoeven Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index fb141454c6d2..7126bdd4236c 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -345,17 +345,17 @@ static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio, { struct hif_scatter_req *s_req; struct bus_request *bus_req; - int i, scat_req_sz, scat_list_sz, sg_sz, buf_sz; + int i, scat_req_sz, scat_list_sz, size; u8 *virt_buf; scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item); scat_req_sz = sizeof(*s_req) + scat_list_sz; if (!virt_scat) - sg_sz = sizeof(struct scatterlist) * n_scat_entry; + size = sizeof(struct scatterlist) * n_scat_entry; else - buf_sz = 2 * L1_CACHE_BYTES + - ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER; + size = 2 * L1_CACHE_BYTES + + ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER; for (i = 0; i < n_scat_req; i++) { /* allocate the scatter request */ @@ -364,7 +364,7 @@ static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio, return -ENOMEM; if (virt_scat) { - virt_buf = kzalloc(buf_sz, GFP_KERNEL); + virt_buf = kzalloc(size, GFP_KERNEL); if (!virt_buf) { kfree(s_req); return -ENOMEM; @@ -374,7 +374,7 @@ static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio, (u8 *)L1_CACHE_ALIGN((unsigned long)virt_buf); } else { /* allocate sglist */ - s_req->sgentries = kzalloc(sg_sz, GFP_KERNEL); + s_req->sgentries = kzalloc(size, GFP_KERNEL); if (!s_req->sgentries) { kfree(s_req); -- GitLab From ada7c19e6d27bf4bb6a242960ac6e76f9f21cdd7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 31 May 2013 14:32:55 +0000 Subject: [PATCH 0577/2900] bnx2x: use XPS if possible for bnx2x_select_queue instead of pure hash The bnx2x_select_queue() was using __skb_tx_hash() to select the transmit queue, totally ignoring XPS settings, while XPS can help performance quite significantly, so change the bnx2x_select_queue() to use __dev_pick_tx() instead which will use XPS if configured. Based on patches from Ying Cai and Havard Skinnemoen Reported-by: govindarajulu.v Signed-off-by: Eric Dumazet Cc: Havard Skinnemoen Cc: Ying Cai Cc: Eilon Greenstein Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index c80f1d26f40d..3651f6d449eb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1829,7 +1829,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb) } /* select a non-FCoE queue */ - return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp)); + return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); } void bnx2x_set_num_queues(struct bnx2x *bp) -- GitLab From d76a611187c4840a4a45fb3f493f9b63c19df4ca Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 2 Jun 2013 00:06:17 +0000 Subject: [PATCH 0578/2900] bnx2x: Semantic change of empty lines This patch removes unnecessary blank lines and adds a few where such are needed (between variable declarations and code) Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 23 ------- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 +--- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 3 - .../net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | 11 --- .../net/ethernet/broadcom/bnx2x/bnx2x_dcb.h | 3 - .../net/ethernet/broadcom/bnx2x/bnx2x_dump.h | 1 - .../ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 4 -- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 68 +------------------ .../net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 30 -------- .../net/ethernet/broadcom/bnx2x/bnx2x_sp.h | 1 - .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 1 - .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 1 - .../net/ethernet/broadcom/bnx2x/bnx2x_stats.c | 1 - .../net/ethernet/broadcom/bnx2x/bnx2x_stats.h | 4 -- 14 files changed, 3 insertions(+), 160 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 47b06fc22b97..0c1104f30de6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -34,12 +34,10 @@ #define BCM_DCBNL #endif - #include "bnx2x_hsi.h" #include "../cnic_if.h" - #define BNX2X_MIN_MSIX_VEC_CNT(bp) ((bp)->min_msix_vec_cnt) #include @@ -114,7 +112,6 @@ do { \ #define BNX2X_ERROR(fmt, ...) \ pr_err("[%s:%d]" fmt, __func__, __LINE__, ##__VA_ARGS__) - /* before we have a dev->name use dev_info() */ #define BNX2X_DEV_INFO(fmt, ...) \ do { \ @@ -147,7 +144,6 @@ do { \ #define U64_HI(x) ((u32)(((u64)(x)) >> 32)) #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) - #define REG_ADDR(bp, offset) ((bp->regview) + (offset)) #define REG_RD(bp, offset) readl(REG_ADDR(bp, offset)) @@ -387,7 +383,6 @@ union db_prod { #define BIT_VEC64_ELEM_SHIFT 6 #define BIT_VEC64_ELEM_MASK ((u64)BIT_VEC64_ELEM_SZ - 1) - #define __BIT_VEC64_SET_BIT(el, bit) \ do { \ el = ((el) | ((u64)0x1 << (bit))); \ @@ -398,7 +393,6 @@ union db_prod { el = ((el) & (~((u64)0x1 << (bit)))); \ } while (0) - #define BIT_VEC64_SET_BIT(vec64, idx) \ __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \ (idx) & BIT_VEC64_ELEM_MASK) @@ -419,8 +413,6 @@ union db_prod { /*******************************************************/ - - /* Number of u64 elements in SGE mask array */ #define RX_SGE_MASK_LEN (NUM_RX_SGE / BIT_VEC64_ELEM_SZ) #define RX_SGE_MASK_LEN_MASK (RX_SGE_MASK_LEN - 1) @@ -580,12 +572,10 @@ struct bnx2x_fastpath { txdata_ptr[FIRST_TX_COS_INDEX] \ ->var) - #define IS_ETH_FP(fp) ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp)) #define IS_FCOE_FP(fp) ((fp)->index == FCOE_IDX((fp)->bp)) #define IS_FCOE_IDX(idx) ((idx) == FCOE_IDX(bp)) - /* MC hsi */ #define MAX_FETCH_BD 13 /* HW max BDs per packet */ #define RX_COPY_THRESH 92 @@ -693,12 +683,10 @@ struct bnx2x_fastpath { FW_DROP_LEVEL(bp)) #define RCQ_TH_HI(bp) (RCQ_TH_LO(bp) + DROPLESS_FC_HEADROOM) - /* This is needed for determining of last_max */ #define SUB_S16(a, b) (s16)((s16)(a) - (s16)(b)) #define SUB_S32(a, b) (s32)((s32)(a) - (s32)(b)) - #define BNX2X_SWCID_SHIFT 17 #define BNX2X_SWCID_MASK ((0x1 << BNX2X_SWCID_SHIFT) - 1) @@ -723,7 +711,6 @@ struct bnx2x_fastpath { DPM_TRIGER_TYPE); \ } while (0) - /* TX CSUM helpers */ #define SKB_CS_OFF(skb) (offsetof(struct tcphdr, check) - \ skb->csum_offset) @@ -766,7 +753,6 @@ struct bnx2x_fastpath { #define BNX2X_RX_SUM_FIX(cqe) \ BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags) - #define FP_USB_FUNC_OFF \ offsetof(struct cstorm_status_block_u, func) #define FP_CSB_FUNC_OFF \ @@ -1068,7 +1054,6 @@ struct bnx2x_slowpath { struct eth_classify_rules_ramrod_data e2; } mac_rdata; - union { struct tstorm_eth_mac_filter_config e1x; struct eth_filter_rules_ramrod_data e2; @@ -1119,7 +1104,6 @@ struct bnx2x_slowpath { #define bnx2x_sp_mapping(bp, var) \ (bp->slowpath_mapping + offsetof(struct bnx2x_slowpath, var)) - /* attn group wiring */ #define MAX_DYNAMIC_ATTN_GRPS 8 @@ -1225,7 +1209,6 @@ enum { BNX2X_SP_RTNL_HYPERVISOR_VLAN, }; - struct bnx2x_prev_path_list { struct list_head list; u8 bus; @@ -1755,7 +1738,6 @@ extern int num_queues; #define FUNC_FLG_SPQ 0x0010 #define FUNC_FLG_LEADING 0x0020 /* PF only */ - struct bnx2x_func_init_params { /* dma */ dma_addr_t fw_stat_map; /* valid iff FUNC_FLG_STATS */ @@ -1853,9 +1835,6 @@ struct bnx2x_func_init_params { #define skip_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx)) - - - /** * bnx2x_set_mac_one - configure a single MAC address * @@ -2000,7 +1979,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, #define UNLOAD_CLOSE 1 #define UNLOAD_RECOVERY 2 - /* DMAE command defines */ #define DMAE_TIMEOUT -1 #define DMAE_PCI_ERROR -2 /* E2 and onward */ @@ -2102,7 +2080,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, #define SP_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct eth_spe)) #define MAX_SP_DESC_CNT (SP_DESC_CNT - 1) - #define BNX2X_BTR 4 #define MAX_SPQ_PENDING 8 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 3651f6d449eb..b28aaf170755 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -165,7 +165,6 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE); - nbd = le16_to_cpu(tx_start_bd->nbd) - 1; #ifdef BNX2X_STOP_ON_ERROR if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) { @@ -733,7 +732,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, dev_kfree_skb_any(skb); } - /* put new data in bin */ rx_buf->data = new_data; @@ -899,7 +897,6 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) cqe_fp); goto next_rx; - } queue = cqe->end_agg_cqe.queue_index; tpa_info = &fp->tpa_info[queue]; @@ -1004,7 +1001,6 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) le16_to_cpu(cqe_fp->vlan_tag)); napi_gro_receive(&fp->napi, skb); - next_rx: rx_buf->data = NULL; @@ -2322,10 +2318,10 @@ static void bnx2x_nic_load_afex_dcc(struct bnx2x *bp, int load_code) static void bnx2x_bz_fp(struct bnx2x *bp, int index) { struct bnx2x_fastpath *fp = &bp->fp[index]; - int cos; struct napi_struct orig_napi = fp->napi; struct bnx2x_agg_info *orig_tpa_info = fp->tpa_info; + /* bzero bnx2x_fastpath contents */ if (fp->tpa_info) memset(fp->tpa_info, 0, ETH_MAX_AGGREGATION_QUEUES_E1H_E2 * @@ -2435,7 +2431,6 @@ int bnx2x_load_cnic(struct bnx2x *bp) if (bp->state == BNX2X_STATE_OPEN) bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD); - DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n"); return 0; @@ -2961,7 +2956,6 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bnx2x_set_reset_global(bp); } - /* The last driver must disable a "close the gate" if there is no * parity attention or "process kill" pending. */ @@ -4480,7 +4474,6 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) alloc_err: bnx2x_free_mem_bp(bp); return -ENOMEM; - } int bnx2x_reload_if_running(struct net_device *dev) @@ -4522,7 +4515,6 @@ int bnx2x_get_cur_phy_idx(struct bnx2x *bp) } return sel_phy_idx; - } int bnx2x_get_link_cfg_idx(struct bnx2x *bp) { @@ -4739,7 +4731,6 @@ int bnx2x_resume(struct pci_dev *pdev) return rc; } - void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt, u32 cid) { @@ -4757,7 +4748,6 @@ static void storm_memset_hc_timeout(struct bnx2x *bp, u8 port, u8 fw_sb_id, u8 sb_index, u8 ticks) { - u32 addr = BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index); REG_WR8(bp, addr, ticks); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 151675d66b0d..f62ffc11ac54 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -22,7 +22,6 @@ #include #include - #include "bnx2x.h" #include "bnx2x_sriov.h" @@ -1171,7 +1170,6 @@ static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx) static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp) { - /* the 'first' id is allocated for the cnic */ return bp->base_fw_ndsb; } @@ -1181,7 +1179,6 @@ static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp) return bp->igu_base_sb; } - static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp) { struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 4b077a7f16af..2689f28010fd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -253,7 +253,6 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp, memset(&pg_help_data, 0, sizeof(struct pg_help_data)); - if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR)) DP(BNX2X_MSG_DCB, "DCBX_LOCAL_ETS_ERROR\n"); @@ -298,7 +297,6 @@ static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp, static void bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp, struct dcbx_pfc_feature *pfc, u32 error) { - if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR)) DP(BNX2X_MSG_DCB, "DCBX_LOCAL_PFC_ERROR\n"); @@ -367,7 +365,6 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp, struct lldp_remote_mib *remote_mib ; struct lldp_local_mib *local_mib; - switch (read_mib_type) { case DCBX_READ_LOCAL_MIB: mib_size = sizeof(struct lldp_local_mib); @@ -629,7 +626,6 @@ static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp) return 0; } - #ifdef BCM_DCBNL static inline u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent) @@ -896,13 +892,11 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, } af->app.default_pri = (u8)dp->admin_default_priority; - } /* Write the data. */ bnx2x_write_data(bp, (u32 *)&admin_mib, offset, sizeof(struct lldp_admin_mib)); - } void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled) @@ -1181,7 +1175,6 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, BNX2X_ERR("dcbx error: Both groups must have priorities\n"); } - #ifndef POWER_OF_2 #define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1)))) #endif @@ -1524,7 +1517,6 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params( } } - static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp, struct pg_help_data *help_data, struct dcbx_ets_feature *ets, @@ -1533,7 +1525,6 @@ static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x *bp, u32 pri_join_mask, u8 num_of_dif_pri) { - /* default E2 settings */ cos_data->num_of_cos = DCBX_COS_MAX_NUM_E2; @@ -1629,7 +1620,6 @@ static u8 bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x *bp, u8 num_spread_of_entries, u8 strict_app_pris) { - if (bnx2x_dcbx_spread_strict_pri(bp, cos_data, entry, num_spread_of_entries, strict_app_pris)) { @@ -1876,7 +1866,6 @@ void bnx2x_dcbx_pmf_update(struct bnx2x *bp) * dcbx negotiation. */ bnx2x_dcbx_update_tc_mapping(bp); - } } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h index d153f44cf8f9..125bd1b6586f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.h @@ -134,8 +134,6 @@ enum { #define PFC_BRB1_REG_HIGH_LLFC_LOW_THRESHOLD 130 #define PFC_BRB1_REG_HIGH_LLFC_HIGH_THRESHOLD 170 - - struct cos_entry_help_data { u32 pri_join_mask; u32 cos_bw; @@ -170,7 +168,6 @@ struct cos_help_data { (!(IS_DCBX_PFC_PRI_ONLY_NON_PAUSE((bp), (pg_pri)) || \ IS_DCBX_PFC_PRI_ONLY_PAUSE((bp), (pg_pri)))) - struct pg_entry_help_data { u8 num_of_dif_pri; u8 pg; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index bff5e33eaa14..219dd84d4bf5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -28,7 +28,6 @@ #define DRV_DUMP_USTORM_WAITP_ADDRESS 0x338a80 #define DRV_DUMP_CSTORM_WAITP_ADDRESS 0x238a80 - /* Possible Chips */ #define DUMP_CHIP_E1 1 #define DUMP_CHIP_E1H 2 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 263950cddfe2..91978eb166ea 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -733,7 +733,6 @@ static bool bnx2x_is_reg_in_chip(struct bnx2x *bp, return false; } - static bool bnx2x_is_wreg_in_chip(struct bnx2x *bp, const struct wreg_addr *wreg_info) { @@ -3071,7 +3070,6 @@ static void bnx2x_get_strings(struct net_device *dev, u32 stringset, u8 *buf) } } - for (i = 0, j = 0; i < BNX2X_NUM_STATS; i++) { if (IS_MF_MODE_STAT(bp) && IS_PORT_STAT(i)) continue; @@ -3194,7 +3192,6 @@ static int bnx2x_set_phys_id(struct net_device *dev, static int bnx2x_get_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) { - switch (info->flow_type) { case TCP_V4_FLOW: case TCP_V6_FLOW: @@ -3430,7 +3427,6 @@ static int bnx2x_set_channels(struct net_device *dev, { struct bnx2x *bp = netdev_priv(dev); - DP(BNX2X_MSG_ETHTOOL, "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n", channels->rx_count, channels->tx_count, channels->other_count, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f6d0e209c44e..5081990daea0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -93,7 +93,6 @@ MODULE_FIRMWARE(FW_FILE_NAME_E1); MODULE_FIRMWARE(FW_FILE_NAME_E1H); MODULE_FIRMWARE(FW_FILE_NAME_E2); - int num_queues; module_param(num_queues, int, 0); MODULE_PARM_DESC(num_queues, @@ -122,8 +121,6 @@ static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, " Default debug msglevel"); - - struct workqueue_struct *bnx2x_wq; struct bnx2x_mac_vals { @@ -917,7 +914,6 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int) sp_sb_data.p_func.vf_valid, sp_sb_data.state); - for_each_eth_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; int loop; @@ -1290,7 +1286,6 @@ void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count) for (i = 0; i < ARRAY_SIZE(cmd_regs); i++) bnx2x_pbf_pN_cmd_flushed(bp, &cmd_regs[i], poll_count); - /* Verify the transmission buffers are flushed P0, P1, P4 */ for (i = 0; i < ARRAY_SIZE(buf_regs); i++) bnx2x_pbf_pN_buf_flushed(bp, &buf_regs[i], poll_count); @@ -1305,11 +1300,9 @@ void bnx2x_tx_hw_flushed(struct bnx2x *bp, u32 poll_count) #define OP_GEN_AGG_VECT(index) \ (((index) << SDM_OP_GEN_AGG_VECT_IDX_SHIFT) & SDM_OP_GEN_AGG_VECT_IDX) - int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, u32 poll_cnt) { u32 op_gen_command = 0; - u32 comp_addr = BAR_CSTRORM_INTMEM + CSTORM_FINAL_CLEANUP_COMPLETE_OFFSET(clnup_func); int ret = 0; @@ -1352,7 +1345,6 @@ u8 bnx2x_is_pcie_pending(struct pci_dev *dev) */ static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt) { - /* wait for CFC PF usage-counter to zero (includes all the VFs) */ if (bnx2x_flr_clnup_poll_hw_counter(bp, CFC_REG_NUM_LCIDS_INSIDE_PF, @@ -1360,7 +1352,6 @@ static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt) poll_cnt)) return 1; - /* Wait for DQ PF usage-counter to zero (until DQ cleanup) */ if (bnx2x_flr_clnup_poll_hw_counter(bp, DORQ_REG_PF_USAGE_CNT, @@ -1991,7 +1982,6 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource) return 0; } - int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port) { /* The GPIO should be swapped if swap register is set and active */ @@ -2347,7 +2337,6 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes) return rc; } - /* Calculates the sum of vn_min_rates. It's needed for further normalizing of the min_rates. Returns: @@ -2419,7 +2408,6 @@ static void bnx2x_calc_vn_max(struct bnx2x *bp, int vn, input->vnic_max_rate[vn] = vn_max_rate; } - static int bnx2x_get_cmng_fns_mode(struct bnx2x *bp) { if (CHIP_REV_IS_SLOW(bp)) @@ -2901,7 +2889,6 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) return rc; } - static void storm_memset_func_cfg(struct bnx2x *bp, struct tstorm_eth_function_common_config *tcfg, u16 abs_fid) @@ -3006,7 +2993,6 @@ static unsigned long bnx2x_get_q_flags(struct bnx2x *bp, if (IS_MF_AFEX(bp)) __set_bit(BNX2X_Q_FLG_SILENT_VLAN_REM, &flags); - return flags | bnx2x_get_common_flags(bp, fp, true); } @@ -3196,7 +3182,6 @@ static void bnx2x_pf_init(struct bnx2x *bp) storm_memset_eq_data(bp, &eq_data, BP_FUNC(bp)); } - static void bnx2x_e1h_disable(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -3540,10 +3525,8 @@ static bool bnx2x_is_contextless_ramrod(int cmd, int cmd_type) return true; else return false; - } - /** * bnx2x_sp_post - place a single command on an SP ring * @@ -3615,7 +3598,6 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, else atomic_dec(&bp->cq_spq_left); - DP(BNX2X_MSG_SP, "SPQE[%x] (%x:%x) (cmd, common?) (%d,%d) hw_cid %x data (%x:%x) type(0x%x) left (CQ, EQ) (%x,%x)\n", bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping), @@ -3836,7 +3818,6 @@ static void bnx2x_fan_failure(struct bnx2x *bp) set_bit(BNX2X_SP_RTNL_FAN_FAILURE, &bp->sp_rtnl_state); smp_mb__after_clear_bit(); schedule_delayed_work(&bp->sp_rtnl_task, 0); - } static void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) @@ -4591,7 +4572,6 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print) return bnx2x_parity_attn(bp, global, print, attn.sig); } - static void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn) { u32 val; @@ -4643,7 +4623,6 @@ static void bnx2x_attn_int_deasserted4(struct bnx2x *bp, u32 attn) (u32)(attn & (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR))); } - } static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) @@ -4878,7 +4857,6 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp, BNX2X_ERR("Failed to schedule new commands: %d\n", rc); else if (rc > 0) DP(BNX2X_MSG_SP, "Scheduled next pending commands...\n"); - } static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start); @@ -5075,8 +5053,6 @@ static void bnx2x_eq_int(struct bnx2x *bp) if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL)) break; - - goto next_spqe; case EVENT_RING_OPCODE_STOP_TRAFFIC: @@ -5265,7 +5241,6 @@ static void bnx2x_sp_task(struct work_struct *work) /* ack status block only if something was actually handled */ bnx2x_ack_sb(bp, bp->igu_dsb_id, ATTENTION_ID, le16_to_cpu(bp->def_att_idx), IGU_INT_ENABLE, 1); - } /* must be called after the EQ processing (since eq leads to sriov @@ -5316,7 +5291,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) /* end of slow path */ - void bnx2x_drv_pulse(struct bnx2x *bp) { SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb, @@ -5382,7 +5356,6 @@ static void bnx2x_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) else for (i = 0; i < len; i++) REG_WR8(bp, addr + i, fill); - } /* helper: writes FP SP data to FW - data_size in dwords */ @@ -5461,10 +5434,8 @@ static void bnx2x_zero_sp_sb(struct bnx2x *bp) bnx2x_fill(bp, BAR_CSTRORM_INTMEM + CSTORM_SP_SYNC_BLOCK_OFFSET(func), 0, CSTORM_SP_SYNC_BLOCK_SIZE); - } - static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm, int igu_sb_id, int igu_seg_id) { @@ -5474,7 +5445,6 @@ static void bnx2x_setup_ndsb_state_machine(struct hc_status_block_sm *hc_sm, hc_sm->time_to_expire = 0xFFFFFFFF; } - /* allocates state machine ids. */ static void bnx2x_map_sb_state_machines(struct hc_index_data *index_data) { @@ -6001,6 +5971,7 @@ static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp) for_each_tx_queue_cnic(bp, i) bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]); } + static void bnx2x_init_tx_rings(struct bnx2x *bp) { int i; @@ -6772,7 +6743,6 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) bnx2x_init_block(bp, BLOCK_QM, PHASE_COMMON); - /* QM queues pointers table */ bnx2x_qm_init_ptr_table(bp, bp->qm_cid_count, INITOP_SET); @@ -7013,7 +6983,6 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) u32 low, high; u32 val; - DP(NETIF_MSG_HW, "starting port init port %d\n", port); REG_WR(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, 0); @@ -7078,7 +7047,6 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) BRB1_REG_MAC_GUARANTIED_1 : BRB1_REG_MAC_GUARANTIED_0), 40); - bnx2x_init_block(bp, BLOCK_PRS, init_phase); if (CHIP_IS_E3B0(bp)) { if (IS_MF_AFEX(bp)) { @@ -7275,7 +7243,6 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, bool is_pf) while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt) msleep(20); - if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) { DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: idu_sb_id %d offset %d bit %d (cnt %d)\n", @@ -7295,7 +7262,6 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func) bnx2x_ilt_wr(bp, i, 0); } - static void bnx2x_init_searcher(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -7331,7 +7297,6 @@ static int bnx2x_reset_nic_mode(struct bnx2x *bp) int rc, i, port = BP_PORT(bp); int vlan_en = 0, mac_en[NUM_MACS]; - /* Close input from network */ if (bp->mf_mode == SINGLE_FUNCTION) { bnx2x_set_rx_filter(&bp->link_params, 0); @@ -7480,7 +7445,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) /* Set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); DP(NETIF_MSG_IFUP, "NIC MODE configrued\n"); - } if (!CHIP_IS_E1x(bp)) { @@ -7734,7 +7698,6 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) return 0; } - void bnx2x_free_mem_cnic(struct bnx2x *bp) { bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE); @@ -7779,7 +7742,6 @@ void bnx2x_free_mem(struct bnx2x *bp) bnx2x_iov_free_mem(bp); } - int bnx2x_alloc_mem_cnic(struct bnx2x *bp) { if (!CHIP_IS_E1x(bp)) @@ -8068,7 +8030,6 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) ilt_client->page_size, ilt_client->flags, ilog2(ilt_client->page_size >> 12)); - } if (CNIC_SUPPORT(bp)) { @@ -8124,7 +8085,6 @@ void bnx2x_ilt_set_info(struct bnx2x *bp) static void bnx2x_pf_q_prep_init(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct bnx2x_queue_init_params *init_params) { - u8 cos; int cxt_index, cxt_offset; @@ -8205,7 +8165,6 @@ static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp, return bnx2x_queue_state_change(bp, q_params); } - /** * bnx2x_setup_queue - setup queue * @@ -8254,7 +8213,6 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp, DP(NETIF_MSG_IFUP, "init complete\n"); - /* Now move the Queue to the SETUP state... */ memset(setup_params, 0, sizeof(*setup_params)); @@ -8315,7 +8273,6 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index) /* We want to wait for completion in this context */ __set_bit(RAMROD_COMP_WAIT, &q_params.ramrod_flags); - /* close tx-only connections */ for (tx_index = FIRST_TX_ONLY_COS_INDEX; tx_index < fp->max_cos; @@ -8369,7 +8326,6 @@ static int bnx2x_stop_queue(struct bnx2x *bp, int index) return bnx2x_queue_state_change(bp, &q_params); } - static void bnx2x_reset_func(struct bnx2x *bp) { int port = BP_PORT(bp); @@ -8740,7 +8696,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link) bnx2x_iov_chip_cleanup(bp); - /* * Send the UNLOAD_REQUEST to the MCP. This will return if * this function should perform FUNC, PORT or COMMON HW @@ -8813,7 +8768,6 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link) if (rc) BNX2X_ERR("HW_RESET failed\n"); - /* Report UNLOAD_DONE to MCP */ bnx2x_send_unload_done(bp, keep_link); } @@ -9179,7 +9133,6 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global) if (!CHIP_IS_E1x(bp) && bnx2x_er_poll_igu_vq(bp)) return -EAGAIN; - /* TBD: Indicate that "process kill" is in progress to MCP */ /* Clear "unprepared" bit */ @@ -9647,7 +9600,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; REG_WR(bp, vals->bmac_addr, wb_data[0]); REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); - } BNX2X_DEV_INFO("Disable emac Rx\n"); vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; @@ -9681,7 +9633,6 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, if (mac_stopped) msleep(20); - } #define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4)) @@ -9854,7 +9805,6 @@ static int bnx2x_do_flr(struct bnx2x *bp) u16 status; struct pci_dev *dev = bp->pdev; - if (CHIP_IS_E1x(bp)) { BNX2X_DEV_INFO("FLR not supported in E1/E1H\n"); return -EINVAL; @@ -10001,7 +9951,6 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) if (!timer_count) BNX2X_ERR("Failed to empty BRB, hope for the best\n"); - } /* No packets are in the pipeline, path is ready for reset */ @@ -10205,8 +10154,6 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp) bnx2x_init_shmem(bp); - - bp->common.shmem2_base = REG_RD(bp, (BP_PATH(bp) ? MISC_REG_GENERIC_CR_1 : MISC_REG_GENERIC_CR_0)); @@ -10467,7 +10414,6 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) if (!(bp->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full; - } BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0], @@ -10778,7 +10724,6 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp) */ if (!bp->cnic_eth_dev.max_iscsi_conn) bp->flags |= no_flags; - } static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func) @@ -11442,7 +11387,6 @@ static int bnx2x_init_bp(struct bnx2x *bp) mutex_init(&bp->fw_mb_mutex); spin_lock_init(&bp->stats_lock); - INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task); INIT_DELAYED_WORK(&bp->period_task, bnx2x_period_task); @@ -11475,7 +11419,6 @@ static int bnx2x_init_bp(struct bnx2x *bp) bnx2x_prev_unload(bp); } - if (CHIP_REV_IS_FPGA(bp)) dev_err(&bp->pdev->dev, "FPGA detected\n"); @@ -11558,7 +11501,6 @@ static int bnx2x_init_bp(struct bnx2x *bp) return rc; } - /**************************************************************************** * General service functions ****************************************************************************/ @@ -12397,7 +12339,6 @@ static void bnx2x_release_firmware(struct bnx2x *bp) bp->firmware = NULL; } - static struct bnx2x_func_sp_drv_ops bnx2x_func_sp_drv = { .init_hw_cmn_chip = bnx2x_init_hw_common_chip, .init_hw_cmn = bnx2x_init_hw_common, @@ -12676,7 +12617,6 @@ static int bnx2x_init_one(struct pci_dev *pdev, } BNX2X_DEV_INFO("device name after netdev register %s\n", dev->name); - if (!NO_FCOE(bp)) { /* Add storage MAC address */ rtnl_lock(); @@ -13048,6 +12988,7 @@ static int __init bnx2x_init(void) static void __exit bnx2x_cleanup(void) { struct list_head *pos, *q; + pci_unregister_driver(&bnx2x_pci_driver); destroy_workqueue(bnx2x_wq); @@ -13103,7 +13044,6 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count) BUG_ON(bp->cnic_spq_pending < count); bp->cnic_spq_pending -= count; - for (; bp->cnic_kwq_pending; bp->cnic_kwq_pending--) { u16 type = (le16_to_cpu(bp->cnic_kwq_cons->hdr.type) & SPE_HDR_CONN_TYPE) >> @@ -13276,7 +13216,6 @@ static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err) bnx2x_cnic_sp_post(bp, 0); } - /* Called with netif_addr_lock_bh() taken. * Sets an rx_mode config for an iSCSI ETH client. * Doesn't block. @@ -13317,7 +13256,6 @@ static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start) } } - static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) { struct bnx2x *bp = netdev_priv(dev); @@ -13505,7 +13443,6 @@ void bnx2x_setup_cnic_info(struct bnx2x *bp) { struct cnic_eth_dev *cp = &bp->cnic_eth_dev; - cp->ctx_tbl_offset = FUNC_ILT_BASE(BP_FUNC(bp)) + bnx2x_cid_ilt_lines(bp); cp->starting_cid = bnx2x_cid_ilt_lines(bp) * ILT_PAGE_CIDS; @@ -13541,7 +13478,6 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops, BNX2X_ERR("CNIC-related load failed\n"); return rc; } - } bp->cnic_enabled = true; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 32a9609cc98b..1f9dbb2f1756 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -142,7 +142,6 @@ static inline int bnx2x_exe_queue_add(struct bnx2x *bp, spin_unlock_bh(&o->lock); return rc; - } static inline void __bnx2x_exe_queue_reset_pending( @@ -163,13 +162,11 @@ static inline void __bnx2x_exe_queue_reset_pending( static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp, struct bnx2x_exe_queue_obj *o) { - spin_lock_bh(&o->lock); __bnx2x_exe_queue_reset_pending(bp, o); spin_unlock_bh(&o->lock); - } /** @@ -308,7 +305,6 @@ static inline int bnx2x_state_wait(struct bnx2x *bp, int state, /* can take a while if any port is running */ int cnt = 5000; - if (CHIP_REV_IS_EMUL(bp)) cnt *= 20; @@ -456,7 +452,6 @@ static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, DP(BNX2X_MSG_SP, "copied element number %d to address %p element was:\n", counter, next); next += stride + size; - } } return counter * ETH_ALEN; @@ -518,7 +513,6 @@ static int bnx2x_check_vlan_mac_add(struct bnx2x *bp, return 0; } - /* check_del() callbacks */ static struct bnx2x_vlan_mac_registry_elem * bnx2x_check_mac_del(struct bnx2x *bp, @@ -609,7 +603,6 @@ static bool bnx2x_check_move_always_err( return false; } - static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o) { struct bnx2x_raw_obj *raw = &o->raw; @@ -626,7 +619,6 @@ static inline u8 bnx2x_vlan_mac_get_rx_tx_flag(struct bnx2x_vlan_mac_obj *o) return rx_tx_flag; } - void bnx2x_set_mac_in_nig(struct bnx2x *bp, bool add, unsigned char *dev_addr, int index) { @@ -707,7 +699,6 @@ static inline void bnx2x_vlan_mac_set_rdata_hdr_e2(u32 cid, int type, hdr->rule_cnt = (u8)rule_cnt; } - /* hw_config() callbacks */ static void bnx2x_set_one_mac_e2(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, @@ -960,7 +951,6 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp, u16 vlan = elem->cmd_data.vlan_mac.u.vlan_mac.vlan; u8 *mac = elem->cmd_data.vlan_mac.u.vlan_mac.mac; - /* Reset the ramrod data buffer for the first rule */ if (rule_idx == 0) memset(data, 0, sizeof(*data)); @@ -1818,8 +1808,6 @@ int bnx2x_config_vlan_mac( return rc; } - - /** * bnx2x_vlan_mac_del_all - delete elements with given vlan_mac_flags spec * @@ -1934,7 +1922,6 @@ static inline void bnx2x_init_vlan_mac_common(struct bnx2x_vlan_mac_obj *o, state, pstate, type); } - void bnx2x_init_mac_obj(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *mac_obj, u8 cl_id, u32 cid, u8 func_id, void *rdata, @@ -2092,7 +2079,6 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp, bnx2x_execute_vlan_mac, bnx2x_exeq_get_vlan_mac); } - } /* RX_MODE verbs: DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */ @@ -2245,7 +2231,6 @@ static inline void bnx2x_rx_mode_set_cmd_state_e2(struct bnx2x *bp, } cmd->state = cpu_to_le16(state); - } static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, @@ -2286,7 +2271,6 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, false); } - /* * If FCoE Queue configuration has been requested configure the Rx and * internal switching modes for this queue in separate rules. @@ -2909,7 +2893,6 @@ static int bnx2x_mcast_validate_e2(struct bnx2x *bp, default: BNX2X_ERR("Unknown command: %d\n", cmd); return -EINVAL; - } /* Increase the total number of MACs pending to be configured */ @@ -3223,7 +3206,6 @@ static int bnx2x_mcast_validate_e1(struct bnx2x *bp, default: BNX2X_ERR("Unknown command: %d\n", cmd); return -EINVAL; - } /* We want to ensure that commands are executed one by one for 57710. @@ -3342,7 +3324,6 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1( return -1; } - static inline int bnx2x_mcast_handle_pending_cmds_e1( struct bnx2x *bp, struct bnx2x_mcast_ramrod_params *p) { @@ -3352,7 +3333,6 @@ static inline int bnx2x_mcast_handle_pending_cmds_e1( union bnx2x_mcast_config_data cfg_data = {NULL}; int cnt = 0; - /* If nothing to be done - return */ if (list_empty(&o->pending_cmds_head)) return 0; @@ -3550,7 +3530,6 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp, /* Ramrod completion is pending */ return 1; } - } static int bnx2x_mcast_get_registry_size_exact(struct bnx2x_mcast_obj *o) @@ -3848,7 +3827,6 @@ static bool bnx2x_credit_pool_always_true(struct bnx2x_credit_pool_obj *o, return true; } - static bool bnx2x_credit_pool_get_entry( struct bnx2x_credit_pool_obj *o, int *offset) @@ -4018,7 +3996,6 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp, /* this should never happen! Block MAC operations. */ bnx2x_init_credit_pool(p, 0, 0); } - } } @@ -4215,7 +4192,6 @@ int bnx2x_config_rss(struct bnx2x *bp, return rc; } - void bnx2x_init_rss_config_obj(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, u8 cl_id, u32 cid, u8 func_id, u8 engine_id, @@ -4288,7 +4264,6 @@ int bnx2x_queue_state_change(struct bnx2x *bp, return !!test_bit(pending_bit, pending); } - static int bnx2x_queue_set_pending(struct bnx2x_queue_sp_obj *obj, struct bnx2x_queue_state_params *params) { @@ -4403,7 +4378,6 @@ static void bnx2x_q_fill_init_general_data(struct bnx2x *bp, gen_data->mtu = cpu_to_le16(params->mtu); gen_data->func_id = o->func_id; - gen_data->cos = params->cos; gen_data->traffic_type = @@ -4530,7 +4504,6 @@ static void bnx2x_q_fill_init_rx_data(struct bnx2x_queue_sp_obj *o, cpu_to_le16(params->silent_removal_value); rx_data->silent_vlan_mask = cpu_to_le16(params->silent_removal_mask); - } /* initialize the general, tx and rx parts of a queue object */ @@ -4706,7 +4679,6 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp, ¶ms->params.tx_only; u8 cid_index = tx_only_params->cid_index; - if (cid_index >= o->max_cos) { BNX2X_ERR("queue[%d]: cid_index (%d) is out of range\n", o->cl_id, cid_index); @@ -4816,7 +4788,6 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp, return -EINVAL; } - /* Clear the ramrod data */ memset(rdata, 0, sizeof(*rdata)); @@ -5636,7 +5607,6 @@ static inline void bnx2x_func_reset_cmn(struct bnx2x *bp, drv->reset_hw_cmn(bp); } - static inline int bnx2x_func_hw_reset(struct bnx2x *bp, struct bnx2x_func_state_params *params) { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 43c00bc84a08..c4fffe0faba0 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -1377,7 +1377,6 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp, struct bnx2x_credit_pool_obj *p, u8 func_id, u8 func_num); - /****************** RSS CONFIGURATION ****************/ void bnx2x_init_rss_config_obj(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 2ce7c7471367..ea492c7a96a1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -3024,7 +3024,6 @@ void bnx2x_unlock_vf_pf_channel(struct bnx2x *bp, struct bnx2x_virtf *vf, int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param) { - struct bnx2x *bp = netdev_priv(pci_get_drvdata(dev)); DP(BNX2X_MSG_IOV, "bnx2x_sriov_configure called with %d, BNX2X_NR_VIRTFN(bp) was %d\n", diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index d67ddc554c0f..039792299c3b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -722,7 +722,6 @@ u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp, struct pf_vf_bulletin_content *bulletin); int bnx2x_post_vf_bulletin(struct bnx2x *bp, int vf); - enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); /* VF side vfpf channel functions */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index 2ca3d94fcec2..98366abd02bd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -1002,7 +1002,6 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp) qstats->valid_bytes_received_lo = qstats->total_bytes_received_lo; - UPDATE_EXTEND_TSTAT(rcv_ucast_pkts, total_unicast_packets_received); UPDATE_EXTEND_TSTAT(rcv_mcast_pkts, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index d117f472816c..853824d258e8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -40,7 +40,6 @@ struct nig_stats { u32 egress_mac_pkt1_hi; }; - enum bnx2x_stats_event { STATS_EVENT_PMF = 0, STATS_EVENT_LINK_UP, @@ -208,7 +207,6 @@ struct bnx2x_eth_stats { u32 eee_tx_lpi; }; - struct bnx2x_eth_q_stats { u32 total_unicast_bytes_received_hi; u32 total_unicast_bytes_received_lo; @@ -331,7 +329,6 @@ struct bnx2x_fw_port_stats_old { u32 mac_discard; }; - /**************************************************************************** * Macros ****************************************************************************/ @@ -536,7 +533,6 @@ struct bnx2x_fw_port_stats_old { SUB_EXTEND_64(qstats->t##_hi, qstats->t##_lo, diff); \ } while (0) - /* forward */ struct bnx2x; -- GitLab From 16a5fd9265e757121bb5f1b9ad757836f370e76c Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 2 Jun 2013 00:06:18 +0000 Subject: [PATCH 0579/2900] bnx2x: Revise comments and alignment This patch correct various typos, fix comments conventions and adds/removes a few comments. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 25 +- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 48 ++-- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 4 +- .../net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | 37 +-- .../net/ethernet/broadcom/bnx2x/bnx2x_dump.h | 6 - .../ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 10 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 81 +++--- .../net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 254 ++++++++---------- .../net/ethernet/broadcom/bnx2x/bnx2x_sp.h | 54 ++-- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 29 +- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 +- .../net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 8 +- 12 files changed, 251 insertions(+), 307 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 0c1104f30de6..8f551cf7bb30 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -362,7 +362,7 @@ union db_prod { /* * Number of required SGEs is the sum of two: * 1. Number of possible opened aggregations (next packet for - * these aggregations will probably consume SGE immidiatelly) + * these aggregations will probably consume SGE immediately) * 2. Rest of BRB blocks divided by 2 (block will consume new SGE only * after placement on BD for new TPA aggregation) * @@ -486,10 +486,10 @@ struct bnx2x_fastpath { struct napi_struct napi; union host_hc_status_block status_blk; - /* chip independed shortcuts into sb structure */ + /* chip independent shortcuts into sb structure */ __le16 *sb_index_values; __le16 *sb_running_index; - /* chip independed shortcut into rx_prods_offset memory */ + /* chip independent shortcut into rx_prods_offset memory */ u32 ustorm_rx_prods_offset; u32 rx_buf_size; @@ -603,7 +603,7 @@ struct bnx2x_fastpath { * START_BD(splitted) - includes unpaged data segment for GSO * PARSING_BD - for TSO and CSUM data * PARSING_BD2 - for encapsulation data - * Frag BDs - decribes pages for frags + * Frag BDs - describes pages for frags */ #define BDS_PER_TX_PKT 4 #define MAX_BDS_PER_TX_PKT (MAX_SKB_FRAGS + BDS_PER_TX_PKT) @@ -886,14 +886,14 @@ struct bnx2x_common { #define CHIP_IS_E3A0(bp) (CHIP_IS_E3(bp) && \ (CHIP_REV(bp) == CHIP_REV_Ax)) /* This define is used in two main places: - * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher + * 1. In the early stages of nic_load, to know if to configure Parser / Searcher * to nic-only mode or to offload mode. Offload mode is configured if either the * chip is E1x (where MIC_MODE register is not applicable), or if cnic already * registered for this port (which means that the user wants storage services). * 2. During cnic-related load, to know if offload mode is already configured in - * the HW or needs to be configrued. + * the HW or needs to be configured. * Since the transition from nic-mode to offload-mode in HW causes traffic - * coruption, nic-mode is configured only in ports on which storage services + * corruption, nic-mode is configured only in ports on which storage services * where never requested. */ #define CONFIGURE_NIC_MODE(bp) (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp)) @@ -994,14 +994,14 @@ extern struct workqueue_struct *bnx2x_wq; * If the maximum number of FP-SB available is X then: * a. If CNIC is supported it consumes 1 FP-SB thus the max number of * regular L2 queues is Y=X-1 - * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor) + * b. In MF mode the actual number of L2 queues is Y= (X-1/MF_factor) * c. If the FCoE L2 queue is supported the actual number of L2 queues * is Y+1 * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for * slow-path interrupts) or Y+2 if CNIC is supported (one additional * FP interrupt context for the CNIC). * e. The number of HW context (CID count) is always X or X+1 if FCoE - * L2 queue is supported. the cid for the FCoE L2 queue is always X. + * L2 queue is supported. The cid for the FCoE L2 queue is always X. */ /* fast-path interrupt contexts E1x */ @@ -1568,7 +1568,7 @@ struct bnx2x { struct mutex cnic_mutex; struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj; - /* Start index of the "special" (CNIC related) L2 cleints */ + /* Start index of the "special" (CNIC related) L2 clients */ u8 cnic_base_cl_id; int dmae_ready; @@ -1682,7 +1682,7 @@ struct bnx2x { /* operation indication for the sp_rtnl task */ unsigned long sp_rtnl_state; - /* DCBX Negotation results */ + /* DCBX Negotiation results */ struct dcbx_features dcbx_local_feat; u32 dcbx_error; @@ -2042,7 +2042,8 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, #define DMAE_LEN32_WR_MAX(bp) (CHIP_IS_E1(bp) ? 0x400 : 0x2000) #define DMAE_COMP_VAL 0x60d0d0ae /* E2 and on - upper bit - indicates eror */ + * indicates error + */ #define MAX_DMAE_C_PER_PORT 8 #define INIT_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index b28aaf170755..ef7fed52891a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -124,7 +124,7 @@ static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); /* Queue pointer cannot be re-set on an fp-basis, as moving pointer - * backward along the array could cause memory to be overriden + * backward along the array could cause memory to be overridden */ for (cos = 1; cos < bp->max_cos; cos++) { for (i = 0; i < old_eth_num - delta; i++) { @@ -258,7 +258,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) smp_mb(); if (unlikely(netif_tx_queue_stopped(txq))) { - /* Taking tx_lock() is needed to prevent reenabling the queue + /* Taking tx_lock() is needed to prevent re-enabling the queue * while it's empty. This could have happen if rx_action() gets * suspended in bnx2x_tx_int() after the condition before * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()): @@ -571,7 +571,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, return err; } - /* Unmap the page as we r going to pass it to the stack */ + /* Unmap the page as we're going to pass it to the stack */ dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(&old_rx_pg, mapping), SGE_PAGES, DMA_FROM_DEVICE); @@ -1114,7 +1114,7 @@ static void bnx2x_fill_report_data(struct bnx2x *bp, memset(data, 0, sizeof(*data)); - /* Fill the report data: efective line speed */ + /* Fill the report data: effective line speed */ data->line_speed = line_speed; /* Link is down */ @@ -1157,7 +1157,7 @@ void bnx2x_link_report(struct bnx2x *bp) * * @bp: driver handle * - * None atomic inmlementation. + * None atomic implementation. * Should be called under the phy_lock. */ void __bnx2x_link_report(struct bnx2x *bp) @@ -1300,7 +1300,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) "mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size); if (!fp->disable_tpa) { - /* Fill the per-aggregtion pool */ + /* Fill the per-aggregation pool */ for (i = 0; i < MAX_AGG_QS(bp); i++) { struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i]; @@ -1858,7 +1858,7 @@ void bnx2x_set_num_queues(struct bnx2x *bp) * * If the actual number of Tx queues (for each CoS) is less than 16 then there * will be the holes at the end of each group of 16 ETh L2 indices (0..15, - * 16..31,...) with indicies that are not coupled with any real Tx queue. + * 16..31,...) with indices that are not coupled with any real Tx queue. * * The proper configuration of skb->queue_mapping is handled by * bnx2x_select_queue() and __skb_tx_hash(). @@ -1920,7 +1920,7 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp) ETH_OVREHEAD + mtu + BNX2X_FW_RX_ALIGN_END; - /* Note : rx_buf_size doesnt take into account NET_SKB_PAD */ + /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */ if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE) fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD; else @@ -1933,7 +1933,7 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp) int i; u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp); - /* Prepare the initial contents fo the indirection table if RSS is + /* Prepare the initial contents for the indirection table if RSS is * enabled */ for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++) @@ -2011,7 +2011,7 @@ static int bnx2x_init_hw(struct bnx2x *bp, u32 load_code) /* * Cleans the object that have internal lists without sending - * ramrods. Should be run when interrutps are disabled. + * ramrods. Should be run when interrupts are disabled. */ void bnx2x_squeeze_objects(struct bnx2x *bp) { @@ -2347,8 +2347,7 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index) fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos * BNX2X_NUM_ETH_QUEUES(bp) + index]; - /* - * set the tpa flag for each queue. The tpa flag determines the queue + /* set the tpa flag for each queue. The tpa flag determines the queue * minimal size so it must be set prior to queue memory allocation */ fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG || @@ -2473,6 +2472,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; + /* zero the structure w/o any lock, before SP handler is initialized */ memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link)); __set_bit(BNX2X_LINK_REPORT_LINK_DOWN, &bp->last_reported_link.link_report_flags); @@ -2537,8 +2537,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } /* configure multi cos mappings in kernel. - * this configuration may be overriden by a multi class queue discipline - * or by a dcbx negotiation result. + * this configuration may be overridden by a multi class queue + * discipline or by a dcbx negotiation result. */ bnx2x_setup_tc(bp->dev, bp->max_cos); @@ -2697,7 +2697,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* Start the Tx */ switch (load_mode) { case LOAD_NORMAL: - /* Tx queue should be only reenabled */ + /* Tx queue should be only re-enabled */ netif_tx_wake_all_queues(bp->dev); break; @@ -2842,7 +2842,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) } /* Nothing to do during unload if previous bnx2x_nic_load() - * have not completed succesfully - all resourses are released. + * have not completed successfully - all resources are released. * * we can get here only after unsuccessful ndo_* callback, during which * dev->IFF_UP flag is still on. @@ -2891,10 +2891,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) /* Send the UNLOAD_REQUEST to the MCP */ bnx2x_send_unload_req(bp, unload_mode); - /* - * Prevent transactions to host from the functions on the + /* Prevent transactions to host from the functions on the * engine that doesn't reset global blocks in case of global - * attention once gloabl blocks are reset and gates are opened + * attention once global blocks are reset and gates are opened * (the engine which leader will perform the recovery * last). */ @@ -2915,7 +2914,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) } /* - * At this stage no more interrupts will arrive so we may safly clean + * At this stage no more interrupts will arrive so we may safely clean * the queueable objects here in case they failed to get cleaned so far. */ if (IS_PF(bp)) @@ -3587,7 +3586,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) DP(NETIF_MSG_TX_QUEUED, "indices: txq %d, fp %d, txdata %d\n", txq_index, fp_index, txdata_index); */ - /* enable this debug print to view the tranmission details + /* enable this debug print to view the transmission details DP(NETIF_MSG_TX_QUEUED, "transmitting packet cid %d fp index %d txdata_index %d tx_data ptr %p fp pointer %p\n", txdata->cid, fp_index, txdata_index, txdata, fp); */ @@ -3970,7 +3969,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc) /* setup tc must be called under rtnl lock */ ASSERT_RTNL(); - /* no traffic classes requested. aborting */ + /* no traffic classes requested. Aborting */ if (!num_tc) { netdev_reset_tc(dev); return 0; @@ -3997,8 +3996,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc) prio, bp->prio_to_cos[prio]); } - - /* Use this configuration to diffrentiate tc0 from other COSes + /* Use this configuration to differentiate tc0 from other COSes This can be used for ets or pfc, and save the effort of setting up a multio class queue disc or negotiating DCBX with a switch netdev_set_prio_tc_map(dev, 0, 0); @@ -4629,7 +4627,7 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features) changes = flags ^ bp->flags; - /* if GRO is changed while LRO is enabled, dont force a reload */ + /* if GRO is changed while LRO is enabled, don't force a reload */ if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG)) changes &= ~GRO_ENABLE_FLAG; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index f62ffc11ac54..4a643d7b9b22 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1331,8 +1331,8 @@ static inline bool bnx2x_mtu_allows_gro(int mtu) int fpp = SGE_PAGE_SIZE / (mtu - ETH_MAX_TPA_HEADER_SIZE); /* - * 1. number of frags should not grow above MAX_SKB_FRAGS - * 2. frag must fit the page + * 1. Number of frags should not grow above MAX_SKB_FRAGS + * 2. Frag must fit the page */ return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 2689f28010fd..210614e37b9b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -687,7 +687,7 @@ static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x *bp) } /* setup tc must be called under rtnl lock, but we can't take it here - * as we are handling an attetntion on a work queue which must be + * as we are handling an attention on a work queue which must be * flushed at some rtnl-locked contexts (e.g. if down) */ if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC, &bp->sp_rtnl_state)) @@ -707,7 +707,7 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) */ bnx2x_dcbnl_update_applist(bp, true); - /* Read rmeote mib if dcbx is in the FW */ + /* Read remote mib if dcbx is in the FW */ if (bnx2x_dcbx_read_shmem_remote_mib(bp)) return; #endif @@ -738,7 +738,7 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state) bnx2x_dcbx_update_tc_mapping(bp); /* - * allow other funtions to update their netdevices + * allow other functions to update their netdevices * accordingly */ if (IS_MF(bp)) @@ -860,7 +860,7 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp, i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i)); } - /*For IEEE admin_recommendation_bw_precentage + /*For IEEE admin_recommendation_bw_percentage *For IEEE admin_recommendation_ets_pg */ af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap; for (i = 0; i < DCBX_CONFIG_MAX_APP_PROTOCOL; i++) { @@ -1070,7 +1070,7 @@ static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp, bool pg_found = false; u32 i, traf_type, add_traf_type, add_pg; u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority; - struct pg_entry_help_data *data = help_data->data; /*shotcut*/ + struct pg_entry_help_data *data = help_data->data; /*shortcut*/ /* Set to invalid */ for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) @@ -1166,7 +1166,8 @@ static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp, DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry)); else /* If we join a group and one is strict - * than the bw rulls */ + * than the bw rules + */ cos_data->data[entry].strict = BNX2X_DCBX_STRICT_COS_HIGHEST; } @@ -1277,7 +1278,7 @@ static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x *bp, } else { /* If there are only pauseable priorities or * only non-pauseable,* the lower priorities go - * to the first queue and the higherpriorities go + * to the first queue and the higher priorities go * to the second queue. */ cos_data->data[0].pausable = @@ -1477,7 +1478,7 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params( * queue and one priority goes to the second queue. * * We will join this two cases: - * if one is BW limited it will go to the secoend queue + * if one is BW limited it will go to the second queue * otherwise the last priority will get it */ @@ -1497,7 +1498,8 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params( false == b_found_strict) /* last entry will be handled separately * If no priority is strict than last - * enty goes to last queue.*/ + * entry goes to last queue. + */ entry = 1; cos_data->data[entry].pri_join_mask |= pri_tested; @@ -1509,7 +1511,8 @@ static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params( b_found_strict = true; cos_data->data[1].pri_join_mask |= pri_tested; /* If we join a group and one is strict - * than the bw rulls */ + * than the bw rules + */ cos_data->data[1].strict = BNX2X_DCBX_STRICT_COS_HIGHEST; } @@ -1838,7 +1841,7 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp, void bnx2x_dcbx_pmf_update(struct bnx2x *bp) { - /* if we need to syncronize DCBX result from prev PMF + /* if we need to synchronize DCBX result from prev PMF * read it from shmem and update bp and netdev accordingly */ if (SHMEM2_HAS(bp, drv_flags) && @@ -1932,14 +1935,14 @@ static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio, return; /** - * bw_pct ingnored - band-width percentage devision between user + * bw_pct ignored - band-width percentage devision between user * priorities within the same group is not * standard and hence not supported * - * prio_type igonred - priority levels within the same group are not + * prio_type ignored - priority levels within the same group are not * standard and hence are not supported. According * to the standard pgid 15 is dedicated to strict - * prioirty traffic (on the port level). + * priority traffic (on the port level). * * up_map ignored */ @@ -1984,14 +1987,14 @@ static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio, DP(BNX2X_MSG_DCB, "prio = %d\n", prio); /** - * bw_pct ingnored - band-width percentage devision between user + * bw_pct ignored - band-width percentage devision between user * priorities within the same group is not * standard and hence not supported * - * prio_type igonred - priority levels within the same group are not + * prio_type ignored - priority levels within the same group are not * standard and hence are not supported. According * to the standard pgid 15 is dedicated to strict - * prioirty traffic (on the port level). + * priority traffic (on the port level). * * up_map ignored */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h index 219dd84d4bf5..12eb4baee9f6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h @@ -13,12 +13,6 @@ * consent. */ - -/* This struct holds a signature to ensure the dump returned from the driver - * match the meta data file inserted to grc_dump.tcl - * The signature is time stamp, diag version and grc_dump version - */ - #ifndef BNX2X_DUMP_H #define BNX2X_DUMP_H diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 91978eb166ea..72b1b59294b4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -320,7 +320,7 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) speed = ethtool_cmd_speed(cmd); - /* If recieved a request for an unknown duplex, assume full*/ + /* If received a request for an unknown duplex, assume full*/ if (cmd->duplex == DUPLEX_UNKNOWN) cmd->duplex = DUPLEX_FULL; @@ -849,7 +849,7 @@ static int __bnx2x_get_preset_regs(struct bnx2x *bp, u32 *p, u32 preset) /* Paged registers are supported in E2 & E3 only */ if (CHIP_IS_E2(bp) || CHIP_IS_E3(bp)) { - /* Read "paged" registes */ + /* Read "paged" registers */ bnx2x_read_pages_regs(bp, p, preset); } @@ -1154,8 +1154,8 @@ static int bnx2x_get_eeprom_len(struct net_device *dev) return bp->common.flash_size; } -/* Per pf misc lock must be aquired before the per port mcp lock. Otherwise, had - * we done things the other way around, if two pfs from the same port would +/* Per pf misc lock must be acquired before the per port mcp lock. Otherwise, + * had we done things the other way around, if two pfs from the same port would * attempt to access nvram at the same time, we could run into a scenario such * as: * pf A takes the port lock. @@ -2070,7 +2070,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata) EEE_MODE_OVERRIDE_NVRAM | EEE_MODE_OUTPUT_TIME; - /* Restart link to propogate changes */ + /* Restart link to propagate changes */ if (netif_running(dev)) { bnx2x_stats_handle(bp, STATS_EVENT_STOP); bnx2x_force_link_reset(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 5081990daea0..82f3696437c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -808,8 +808,8 @@ static void bnx2x_hc_int_disable(struct bnx2x *bp) u32 val = REG_RD(bp, addr); /* in E1 we must use only PCI configuration space to disable - * MSI/MSIX capablility - * It's forbitten to disable IGU_PF_CONF_MSI_MSIX_EN in HC block + * MSI/MSIX capability + * It's forbidden to disable IGU_PF_CONF_MSI_MSIX_EN in HC block */ if (CHIP_IS_E1(bp)) { /* Since IGU_PF_CONF_MSI_MSIX_EN still always on @@ -1012,7 +1012,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int) hc_sm_p[j].timer_value); } - /* Indecies data */ + /* Indices data */ for (j = 0; j < loop; j++) { pr_cont("INDEX[%d] flags (0x%x) timeout (0x%x)\n", j, hc_index_p[j].flags, @@ -1107,7 +1107,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int) * bnx2x_pf_flr_clnup() is called during nic_load in the per function HW * initialization. */ -#define FLR_WAIT_USEC 10000 /* 10 miliseconds */ +#define FLR_WAIT_USEC 10000 /* 10 milliseconds */ #define FLR_WAIT_INTERVAL 50 /* usec */ #define FLR_POLL_CNT (FLR_WAIT_USEC/FLR_WAIT_INTERVAL) /* 200 */ @@ -1327,7 +1327,7 @@ int bnx2x_send_final_clnup(struct bnx2x *bp, u8 clnup_func, u32 poll_cnt) bnx2x_panic(); return 1; } - /* Zero completion for nxt FLR */ + /* Zero completion for next FLR */ REG_WR(bp, comp_addr, 0); return ret; @@ -2343,7 +2343,7 @@ u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes) sum of vn_min_rates. or 0 - if all the min_rates are 0. - In the later case fainess algorithm should be deactivated. + In the later case fairness algorithm should be deactivated. If not all min_rates are zero then those that are zeroes will be set to 1. */ static void bnx2x_calc_vn_min(struct bnx2x *bp, @@ -2423,7 +2423,7 @@ void bnx2x_read_mf_cfg(struct bnx2x *bp) int vn, n = (CHIP_MODE_IS_4_PORT(bp) ? 2 : 1); if (BP_NOMCP(bp)) - return; /* what should be the default bvalue in this case */ + return; /* what should be the default value in this case */ /* For 2 port configuration the absolute function number formula * is: @@ -2922,7 +2922,7 @@ void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) } /** - * bnx2x_get_tx_only_flags - Return common flags + * bnx2x_get_common_flags - Return common flags * * @bp device handle * @fp queue handle @@ -3110,7 +3110,7 @@ static void bnx2x_pf_tx_q_prep(struct bnx2x *bp, txq_init->fw_sb_id = fp->fw_sb_id; /* - * set the tss leading client id for TX classfication == + * set the tss leading client id for TX classification == * leading RSS client id */ txq_init->tss_leading_cl_id = bnx2x_fp(bp, 0, cl_id); @@ -3197,7 +3197,7 @@ static void bnx2x_e1h_enable(struct bnx2x *bp) REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1); - /* Tx queue should be only reenabled */ + /* Tx queue should be only re-enabled */ netif_tx_wake_all_queues(bp->dev); /* @@ -3591,7 +3591,7 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid, /* * It's ok if the actual decrement is issued towards the memory * somewhere between the spin_lock and spin_unlock. Thus no - * more explict memory barrier is needed. + * more explicit memory barrier is needed. */ if (common) atomic_dec(&bp->eq_spq_left); @@ -3660,7 +3660,7 @@ static u16 bnx2x_update_dsb_idx(struct bnx2x *bp) rc |= BNX2X_DEF_SB_IDX; } - /* Do not reorder: indecies reading should complete before handling */ + /* Do not reorder: indices reading should complete before handling */ barrier(); return rc; } @@ -3809,8 +3809,7 @@ static void bnx2x_fan_failure(struct bnx2x *bp) netdev_err(bp->dev, "Fan Failure on Network Controller has caused the driver to shutdown the card to prevent permanent damage.\n" "Please contact OEM Support for assistance\n"); - /* - * Schedule device reset (unload) + /* Schedule device reset (unload) * This is due to some boards consuming sufficient power when driver is * up to overheat if fan fails. */ @@ -4987,7 +4986,7 @@ static void bnx2x_eq_int(struct bnx2x *bp) hw_cons = le16_to_cpu(*bp->eq_cons_sb); /* The hw_cos range is 1-255, 257 - the sw_cons range is 0-254, 256. - * when we get the the next-page we nned to adjust so the loop + * when we get the next-page we need to adjust so the loop * condition below will be met. The next element is the size of a * regular element and hence incrementing by 1 */ @@ -5194,7 +5193,7 @@ static void bnx2x_sp_task(struct work_struct *work) DP(BNX2X_MSG_SP, "sp task invoked\n"); - /* make sure the atomic interupt_occurred has been written */ + /* make sure the atomic interrupt_occurred has been written */ smp_rmb(); if (atomic_read(&bp->interrupt_occurred)) { @@ -5670,7 +5669,7 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp) bp->eq_cons = 0; bp->eq_prod = NUM_EQ_DESC; bp->eq_cons_sb = BNX2X_EQ_INDEX; - /* we want a warning message before it gets rought... */ + /* we want a warning message before it gets wrought... */ atomic_set(&bp->eq_spq_left, min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1); } @@ -5754,7 +5753,7 @@ static int bnx2x_fill_accept_flags(struct bnx2x *bp, u32 rx_mode, break; case BNX2X_RX_MODE_PROMISC: - /* According to deffinition of SI mode, iface in promisc mode + /* According to definition of SI mode, iface in promisc mode * should receive matched and unmatched (in resolution of port) * unicast packets. */ @@ -5897,7 +5896,7 @@ static void bnx2x_init_eth_fp(struct bnx2x *bp, int fp_idx) /* init shortcut */ fp->ustorm_rx_prods_offset = bnx2x_rx_ustorm_prods_offset(fp); - /* Setup SB indicies */ + /* Setup SB indices */ fp->rx_cons_sb = BNX2X_RX_SB_INDEX; /* Configure Queue State object */ @@ -6652,7 +6651,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp) * stay set) * f. If this is VNIC 3 of a port then also init * first_timers_ilt_entry to zero and last_timers_ilt_entry - * to the last enrty in the ILT. + * to the last entry in the ILT. * * Notes: * Currently the PF error in the PGLC is non recoverable. @@ -7118,8 +7117,8 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) bnx2x_init_block(bp, BLOCK_MISC_AEU, init_phase); /* init aeu_mask_attn_func_0/1: - * - SF mode: bits 3-7 are masked. only bits 0-2 are in use - * - MF mode: bit 3 is masked. bits 0-2 are in use as in SF + * - SF mode: bits 3-7 are masked. Only bits 0-2 are in use + * - MF mode: bit 3 is masked. Bits 0-2 are in use as in SF * bits 4-7 are used for "per vn group attention" */ val = IS_MF(bp) ? 0xF7 : 0x7; /* Enable DCBX attention for all but E1 */ @@ -7371,7 +7370,7 @@ int bnx2x_init_hw_func_cnic(struct bnx2x *bp) bnx2x_ilt_init_op_cnic(bp, INITOP_SET); if (CONFIGURE_NIC_MODE(bp)) { - /* Configrue searcher as part of function hw init */ + /* Configure searcher as part of function hw init */ bnx2x_init_searcher(bp); /* Reset NIC mode */ @@ -7641,7 +7640,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) } bnx2x_igu_clear_sb(bp, bp->igu_dsb_id); - /* !!! these should become driver const once + /* !!! These should become driver const once rf-tool supports split-68 const */ REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_LSB, 0); REG_WR(bp, IGU_REG_SB_INT_BEFORE_MASK_MSB, 0); @@ -7755,7 +7754,7 @@ int bnx2x_alloc_mem_cnic(struct bnx2x *bp) host_hc_status_block_e1x)); if (CONFIGURE_NIC_MODE(bp) && !bp->t2) - /* allocate searcher T2 table, as it wan't allocated before */ + /* allocate searcher T2 table, as it wasn't allocated before */ BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ); /* write address to which L5 should insert its values */ @@ -8093,7 +8092,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp, __set_bit(BNX2X_Q_FLG_HC, &init_params->rx.flags); __set_bit(BNX2X_Q_FLG_HC, &init_params->tx.flags); - /* If HC is supporterd, enable host coalescing in the transition + /* If HC is supported, enable host coalescing in the transition * to INIT state. */ __set_bit(BNX2X_Q_FLG_HC_EN, &init_params->rx.flags); @@ -8579,14 +8578,14 @@ static int bnx2x_func_wait_started(struct bnx2x *bp) /* * (assumption: No Attention from MCP at this stage) - * PMF probably in the middle of TXdisable/enable transaction + * PMF probably in the middle of TX disable/enable transaction * 1. Sync IRS for default SB - * 2. Sync SP queue - this guarantes us that attention handling started - * 3. Wait, that TXdisable/enable transaction completes + * 2. Sync SP queue - this guarantees us that attention handling started + * 3. Wait, that TX disable/enable transaction completes * - * 1+2 guranty that if DCBx attention was scheduled it already changed - * pending bit of transaction from STARTED-->TX_STOPPED, if we alredy - * received complettion for the transaction the state is TX_STOPPED. + * 1+2 guarantee that if DCBx attention was scheduled it already changed + * pending bit of transaction from STARTED-->TX_STOPPED, if we already + * received completion for the transaction the state is TX_STOPPED. * State will return to STARTED after completion of TX_STOPPED-->STARTED * transaction. */ @@ -8705,7 +8704,7 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link) /* * (assumption: No Attention from MCP at this stage) - * PMF probably in the middle of TXdisable/enable transaction + * PMF probably in the middle of TX disable/enable transaction */ rc = bnx2x_func_wait_started(bp); if (rc) { @@ -9320,7 +9319,7 @@ static void bnx2x_parity_recover(struct bnx2x *bp) * the first leader that performs a * leader_reset() reset the global blocks in * order to clear global attentions. Otherwise - * the the gates will remain closed for that + * the gates will remain closed for that * engine. */ if (load_status || @@ -10056,7 +10055,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) break; } - /* non-common reply from MCP night require looping */ + /* non-common reply from MCP might require looping */ rc = bnx2x_prev_unload_uncommon(bp); if (rc != BNX2X_PREV_WAIT_NEEDED) break; @@ -11034,7 +11033,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp) } else { bp->common.int_block = INT_BLOCK_IGU; - /* do not allow device reset during IGU info preocessing */ + /* do not allow device reset during IGU info processing */ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET); val = REG_RD(bp, IGU_REG_BLOCK_CONFIGURATION); @@ -11113,7 +11112,7 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp) E1H_FUNC_MAX * sizeof(struct drv_func_mb); /* * get mf configuration: - * 1. existence of MF configuration + * 1. Existence of MF configuration * 2. MAC address must be legal (check only upper bytes) * for Switch-Independent mode; * OVLAN must be legal for Switch-Dependent mode @@ -11490,7 +11489,7 @@ static int bnx2x_init_bp(struct bnx2x *bp) /* We need at least one default status block for slow-path events, * second status block for the L2 queue, and a third status block for - * CNIC if supproted. + * CNIC if supported. */ if (CNIC_SUPPORT(bp)) bp->min_msix_vec_cnt = 3; @@ -12874,7 +12873,7 @@ static pci_ers_result_t bnx2x_io_slot_reset(struct pci_dev *pdev) bnx2x_prev_unload(bp); - /* We should have resetted the engine, so It's fair to + /* We should have reseted the engine, so It's fair to * assume the FW will no longer write to the bnx2x driver. */ bnx2x_squeeze_objects(bp); @@ -12993,7 +12992,7 @@ static void __exit bnx2x_cleanup(void) destroy_workqueue(bnx2x_wq); - /* Free globablly allocated resources */ + /* Free globally allocated resources */ list_for_each_safe(pos, q, &bnx2x_prev_list) { struct bnx2x_prev_path_list *tmp = list_entry(pos, struct bnx2x_prev_path_list, list); @@ -13016,7 +13015,7 @@ module_exit(bnx2x_cleanup); * @bp: driver handle * @set: set or clear the CAM entry * - * This function will wait until the ramdord completion returns. + * This function will wait until the ramrod completion returns. * Return 0 if success, -ENODEV if ramrod doesn't return. */ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 1f9dbb2f1756..8f03c984550f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -35,9 +35,9 @@ /** * bnx2x_exe_queue_init - init the Exe Queue object * - * @o: poiter to the object + * @o: pointer to the object * @exe_len: length - * @owner: poiter to the owner + * @owner: pointer to the owner * @validate: validate function pointer * @optimize: optimize function pointer * @exec: execute function pointer @@ -176,7 +176,7 @@ static inline void bnx2x_exe_queue_reset_pending(struct bnx2x *bp, * @o: queue * @ramrod_flags: flags * - * (Atomicy is ensured using the exe_queue->lock). + * (Atomicity is ensured using the exe_queue->lock). */ static inline int bnx2x_exe_queue_step(struct bnx2x *bp, struct bnx2x_exe_queue_obj *o, @@ -189,8 +189,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp, spin_lock_bh(&o->lock); - /* - * Next step should not be performed until the current is finished, + /* Next step should not be performed until the current is finished, * unless a DRV_CLEAR_ONLY bit is set. In this case we just want to * properly clear object internals without sending any command to the FW * which also implies there won't be any completion to clear the @@ -206,8 +205,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp, } } - /* - * Run through the pending commands list and create a next + /* Run through the pending commands list and create a next * execution chunk. */ while (!list_empty(&o->exe_queue)) { @@ -217,8 +215,7 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp, if (cur_len + elem->cmd_len <= o->exe_chunk_len) { cur_len += elem->cmd_len; - /* - * Prevent from both lists being empty when moving an + /* Prevent from both lists being empty when moving an * element. This will allow the call of * bnx2x_exe_queue_empty() without locking. */ @@ -238,14 +235,12 @@ static inline int bnx2x_exe_queue_step(struct bnx2x *bp, rc = o->execute(bp, o->owner, &o->pending_comp, ramrod_flags); if (rc < 0) - /* - * In case of an error return the commands back to the queue - * and reset the pending_comp. + /* In case of an error return the commands back to the queue + * and reset the pending_comp. */ list_splice_init(&o->pending_comp, &o->exe_queue); else if (!rc) - /* - * If zero is returned, means there are no outstanding pending + /* If zero is returned, means there are no outstanding pending * completions and we may dismiss the pending list. */ __bnx2x_exe_queue_reset_pending(bp, o); @@ -685,7 +680,7 @@ static inline void bnx2x_vlan_mac_set_cmd_hdr_e2(struct bnx2x *bp, * * @cid: connection id * @type: BNX2X_FILTER_XXX_PENDING - * @hdr: poiter to header to setup + * @hdr: pointer to header to setup * @rule_cnt: * * currently we always configure one rule and echo field to contain a CID and an @@ -714,8 +709,7 @@ static void bnx2x_set_one_mac_e2(struct bnx2x *bp, unsigned long *vlan_mac_flags = &elem->cmd_data.vlan_mac.vlan_mac_flags; u8 *mac = elem->cmd_data.vlan_mac.u.mac.mac; - /* - * Set LLH CAM entry: currently only iSCSI and ETH macs are + /* Set LLH CAM entry: currently only iSCSI and ETH macs are * relevant. In addition, current implementation is tuned for a * single ETH MAC. * @@ -870,8 +864,7 @@ static void bnx2x_set_one_mac_e1x(struct bnx2x *bp, struct bnx2x_raw_obj *raw = &o->raw; struct mac_configuration_cmd *config = (struct mac_configuration_cmd *)(raw->rdata); - /* - * 57710 and 57711 do not support MOVE command, + /* 57710 and 57711 do not support MOVE command, * so it's either ADD or DEL */ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ? @@ -959,7 +952,7 @@ static void bnx2x_set_one_vlan_mac_e2(struct bnx2x *bp, bnx2x_vlan_mac_set_cmd_hdr_e2(bp, o, add, CLASSIFY_RULE_OPCODE_PAIR, &rule_entry->pair.header); - /* Set VLAN and MAC themselvs */ + /* Set VLAN and MAC themselves */ rule_entry->pair.vlan = cpu_to_le16(vlan); bnx2x_set_fw_mac_addr(&rule_entry->pair.mac_msb, &rule_entry->pair.mac_mid, @@ -1011,8 +1004,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp, struct bnx2x_raw_obj *raw = &o->raw; struct mac_configuration_cmd *config = (struct mac_configuration_cmd *)(raw->rdata); - /* - * 57710 and 57711 do not support MOVE command, + /* 57710 and 57711 do not support MOVE command, * so it's either ADD or DEL */ bool add = (elem->cmd_data.vlan_mac.cmd == BNX2X_VLAN_MAC_ADD) ? @@ -1036,7 +1028,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp, * * @bp: device handle * @p: command parameters - * @ppos: pointer to the cooky + * @ppos: pointer to the cookie * * reconfigure next MAC/VLAN/VLAN-MAC element from the * previously configured elements list. @@ -1044,7 +1036,7 @@ static void bnx2x_set_one_vlan_mac_e1h(struct bnx2x *bp, * from command parameters only RAMROD_COMP_WAIT bit in ramrod_flags is taken * into an account * - * pointer to the cooky - that should be given back in the next call to make + * pointer to the cookie - that should be given back in the next call to make * function handle the next element. If *ppos is set to NULL it will restart the * iterator. If returned *ppos == NULL this means that the last element has been * handled. @@ -1092,8 +1084,7 @@ static int bnx2x_vlan_mac_restore(struct bnx2x *bp, return bnx2x_config_vlan_mac(bp, p); } -/* - * bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a +/* bnx2x_exeq_get_mac/bnx2x_exeq_get_vlan/bnx2x_exeq_get_vlan_mac return a * pointer to an element with a specific criteria and NULL if such an element * hasn't been found. */ @@ -1177,8 +1168,7 @@ static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp, return rc; } - /* - * Check if there is a pending ADD command for this + /* Check if there is a pending ADD command for this * MAC/VLAN/VLAN-MAC. Return an error if there is. */ if (exeq->get(exeq, elem)) { @@ -1186,8 +1176,7 @@ static inline int bnx2x_validate_vlan_mac_add(struct bnx2x *bp, return -EEXIST; } - /* - * TODO: Check the pending MOVE from other objects where this + /* TODO: Check the pending MOVE from other objects where this * object is a destination object. */ @@ -1230,8 +1219,7 @@ static inline int bnx2x_validate_vlan_mac_del(struct bnx2x *bp, return -EEXIST; } - /* - * Check if there are pending DEL or MOVE commands for this + /* Check if there are pending DEL or MOVE commands for this * MAC/VLAN/VLAN-MAC. Return an error if so. */ memcpy(&query_elem, elem, sizeof(query_elem)); @@ -1282,8 +1270,7 @@ static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp, struct bnx2x_exe_queue_obj *src_exeq = &src_o->exe_queue; struct bnx2x_exe_queue_obj *dest_exeq = &dest_o->exe_queue; - /* - * Check if we can perform this operation based on the current registry + /* Check if we can perform this operation based on the current registry * state. */ if (!src_o->check_move(bp, src_o, dest_o, @@ -1292,8 +1279,7 @@ static inline int bnx2x_validate_vlan_mac_move(struct bnx2x *bp, return -EINVAL; } - /* - * Check if there is an already pending DEL or MOVE command for the + /* Check if there is an already pending DEL or MOVE command for the * source object or ADD command for a destination object. Return an * error if so. */ @@ -1382,7 +1368,7 @@ static int bnx2x_remove_vlan_mac(struct bnx2x *bp, } /** - * bnx2x_wait_vlan_mac - passivly wait for 5 seconds until all work completes. + * bnx2x_wait_vlan_mac - passively wait for 5 seconds until all work completes. * * @bp: device handle * @o: bnx2x_vlan_mac_obj @@ -1540,9 +1526,8 @@ static inline int bnx2x_vlan_mac_get_registry_elem( /* Get a new CAM offset */ if (!o->get_cam_offset(o, ®_elem->cam_offset)) { - /* - * This shell never happen, because we have checked the - * CAM availiability in the 'validate'. + /* This shall never happen, because we have checked the + * CAM availability in the 'validate'. */ WARN_ON(1); kfree(reg_elem); @@ -1589,8 +1574,7 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp, struct bnx2x_vlan_mac_registry_elem *reg_elem; enum bnx2x_vlan_mac_cmd cmd; - /* - * If DRIVER_ONLY execution is requested, cleanup a registry + /* If DRIVER_ONLY execution is requested, cleanup a registry * and exit. Otherwise send a ramrod to FW. */ if (!drv_only) { @@ -1599,11 +1583,10 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp, /* Set pending */ r->set_pending(r); - /* Fill tha ramrod data */ + /* Fill the ramrod data */ list_for_each_entry(elem, exe_chunk, link) { cmd = elem->cmd_data.vlan_mac.cmd; - /* - * We will add to the target object in MOVE command, so + /* We will add to the target object in MOVE command, so * change the object for a CAM search. */ if (cmd == BNX2X_VLAN_MAC_MOVE) @@ -1636,12 +1619,11 @@ static int bnx2x_execute_vlan_mac(struct bnx2x *bp, idx++; } - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ rc = bnx2x_sp_post(bp, o->ramrod_cmd, r->cid, @@ -1756,8 +1738,7 @@ int bnx2x_config_vlan_mac( return rc; } - /* - * If nothing will be executed further in this iteration we want to + /* If nothing will be executed further in this iteration we want to * return PENDING if there are pending commands */ if (!bnx2x_exe_queue_empty(&o->exe_queue)) @@ -1776,13 +1757,11 @@ int bnx2x_config_vlan_mac( return rc; } - /* - * RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set + /* RAMROD_COMP_WAIT is a superset of RAMROD_EXEC. If it was set * then user want to wait until the last command is done. */ if (test_bit(RAMROD_COMP_WAIT, &p->ramrod_flags)) { - /* - * Wait maximum for the current exe_queue length iterations plus + /* Wait maximum for the current exe_queue length iterations plus * one (for the current pending command). */ int max_iterations = bnx2x_exe_queue_length(&o->exe_queue) + 1; @@ -1817,7 +1796,7 @@ int bnx2x_config_vlan_mac( * @ramrod_flags: execution flags to be used for this deletion * * if the last operation has completed successfully and there are no - * moreelements left, positive value if the last operation has completed + * more elements left, positive value if the last operation has completed * successfully and there are more previously configured elements, negative * value is current operation has failed. */ @@ -1858,8 +1837,7 @@ static int bnx2x_vlan_mac_del_all(struct bnx2x *bp, p.ramrod_flags = *ramrod_flags; p.user_req.cmd = BNX2X_VLAN_MAC_DEL; - /* - * Add all but the last VLAN-MAC to the execution queue without actually + /* Add all but the last VLAN-MAC to the execution queue without actually * execution anything. */ __clear_bit(RAMROD_COMP_WAIT, &p.ramrod_flags); @@ -2035,8 +2013,7 @@ void bnx2x_init_vlan_mac_obj(struct bnx2x *bp, /* CAM pool handling */ vlan_mac_obj->get_credit = bnx2x_get_credit_vlan_mac; vlan_mac_obj->put_credit = bnx2x_put_credit_vlan_mac; - /* - * CAM offset is relevant for 57710 and 57711 chips only which have a + /* CAM offset is relevant for 57710 and 57711 chips only which have a * single CAM for both MACs and VLAN-MAC pairs. So the offset * will be taken from MACs' pool object only. */ @@ -2103,12 +2080,12 @@ static int bnx2x_set_rx_mode_e1x(struct bnx2x *bp, struct tstorm_eth_mac_filter_config *mac_filters = (struct tstorm_eth_mac_filter_config *)p->rdata; - /* initial seeting is drop-all */ + /* initial setting is drop-all */ u8 drop_all_ucast = 1, drop_all_mcast = 1; u8 accp_all_ucast = 0, accp_all_bcast = 0, accp_all_mcast = 0; u8 unmatched_unicast = 0; - /* In e1x there we only take into account rx acceot flag since tx switching + /* In e1x there we only take into account rx accept flag since tx switching * isn't enabled. */ if (test_bit(BNX2X_ACCEPT_UNICAST, &p->rx_accept_flags)) /* accept matched ucast */ @@ -2271,8 +2248,7 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, false); } - /* - * If FCoE Queue configuration has been requested configure the Rx and + /* If FCoE Queue configuration has been requested configure the Rx and * internal switching modes for this queue in separate rules. * * FCoE queue shell never be set to ACCEPT_ALL packets of any sort: @@ -2308,8 +2284,7 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, } } - /* - * Set the ramrod header (most importantly - number of rules to + /* Set the ramrod header (most importantly - number of rules to * configure). */ bnx2x_rx_mode_set_rdata_hdr_e2(p->cid, &data->header, rule_idx); @@ -2318,12 +2293,11 @@ static int bnx2x_set_rx_mode_e2(struct bnx2x *bp, data->header.rule_cnt, p->rx_accept_flags, p->tx_accept_flags); - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ /* Send a ramrod */ @@ -2460,7 +2434,7 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp, cur_mac = (struct bnx2x_mcast_mac_elem *) ((u8 *)new_cmd + sizeof(*new_cmd)); - /* Push the MACs of the current command into the pendig command + /* Push the MACs of the current command into the pending command * MACs list: FIFO */ list_for_each_entry(pos, &p->mcast_list, link) { @@ -3017,20 +2991,18 @@ static int bnx2x_mcast_setup_e2(struct bnx2x *bp, if (!o->total_pending_num) bnx2x_mcast_refresh_registry_e2(bp, o); - /* - * If CLEAR_ONLY was requested - don't send a ramrod and clear + /* If CLEAR_ONLY was requested - don't send a ramrod and clear * RAMROD_PENDING status immediately. */ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { raw->clear_pending(raw); return 0; } else { - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ /* Send a ramrod */ @@ -3104,7 +3076,7 @@ static inline void bnx2x_mcast_hdl_restore_e1h(struct bnx2x *bp, } } -/* On 57711 we write the multicast MACs' aproximate match +/* On 57711 we write the multicast MACs' approximate match * table by directly into the TSTORM's internal RAM. So we don't * really need to handle any tricks to make it work. */ @@ -3227,7 +3199,7 @@ static void bnx2x_mcast_revert_e1(struct bnx2x *bp, /* If current command hasn't been handled yet and we are * here means that it's meant to be dropped and we have to - * update the number of outstandling MACs accordingly. + * update the number of outstanding MACs accordingly. */ if (p->mcast_list_len) o->total_pending_num -= o->max_cmd_len; @@ -3503,20 +3475,18 @@ static int bnx2x_mcast_setup_e1(struct bnx2x *bp, if (rc) return rc; - /* - * If CLEAR_ONLY was requested - don't send a ramrod and clear + /* If CLEAR_ONLY was requested - don't send a ramrod and clear * RAMROD_PENDING status immediately. */ if (test_bit(RAMROD_DRV_CLR_ONLY, &p->ramrod_flags)) { raw->clear_pending(raw); return 0; } else { - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ /* Send a ramrod */ @@ -3977,8 +3947,7 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp, } else { - /* - * CAM credit is equaly divided between all active functions + /* CAM credit is equaly divided between all active functions * on the PATH. */ if ((func_num > 0)) { @@ -3987,8 +3956,7 @@ void bnx2x_init_mac_credit_pool(struct bnx2x *bp, else cam_sz = BNX2X_CAM_SIZE_EMUL; - /* - * No need for CAM entries handling for 57712 and + /* No need for CAM entries handling for 57712 and * newer. */ bnx2x_init_credit_pool(p, -1, cam_sz); @@ -4005,14 +3973,12 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp, u8 func_num) { if (CHIP_IS_E1x(bp)) { - /* - * There is no VLAN credit in HW on 57710 and 57711 only + /* There is no VLAN credit in HW on 57710 and 57711 only * MAC / MAC-VLAN can be set */ bnx2x_init_credit_pool(p, 0, -1); } else { - /* - * CAM credit is equaly divided between all active functions + /* CAM credit is equally divided between all active functions * on the PATH. */ if (func_num > 0) { @@ -4028,7 +3994,7 @@ void bnx2x_init_vlan_credit_pool(struct bnx2x *bp, /** * bnx2x_debug_print_ind_table - prints the indirection table configuration. * - * @bp: driver hanlde + * @bp: driver handle * @p: pointer to rss configuration * * Prints it when NETIF_MSG_IFUP debug level is configured. @@ -4141,12 +4107,11 @@ static int bnx2x_setup_rss(struct bnx2x *bp, data->capabilities |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY; } - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ /* Send a ramrod */ @@ -4312,7 +4277,7 @@ static int bnx2x_queue_comp_cmd(struct bnx2x *bp, } if (o->next_tx_only >= o->max_cos) - /* >= becuase tx only must always be smaller than cos since the + /* >= because tx only must always be smaller than cos since the * primary connection supports COS 0 */ BNX2X_ERR("illegal value for next tx_only: %d. max cos was %d", @@ -4625,12 +4590,11 @@ static inline int bnx2x_q_send_setup_e1x(struct bnx2x *bp, /* Fill the ramrod data */ bnx2x_q_fill_setup_data_cmn(bp, params, rdata); - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], @@ -4654,12 +4618,11 @@ static inline int bnx2x_q_send_setup_e2(struct bnx2x *bp, bnx2x_q_fill_setup_data_cmn(bp, params, rdata); bnx2x_q_fill_setup_data_e2(bp, params, rdata); - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ return bnx2x_sp_post(bp, ramrod, o->cids[BNX2X_PRIMARY_CID_INDEX], @@ -4699,12 +4662,11 @@ static inline int bnx2x_q_send_setup_tx_only(struct bnx2x *bp, o->cids[cid_index], rdata->general.client_id, rdata->general.sp_client_id, rdata->general.cos); - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ return bnx2x_sp_post(bp, ramrod, o->cids[cid_index], @@ -4733,7 +4695,7 @@ static void bnx2x_q_fill_update_data(struct bnx2x *bp, test_bit(BNX2X_Q_UPDATE_IN_VLAN_REM_CHNG, ¶ms->update_flags); - /* Outer VLAN sripping */ + /* Outer VLAN stripping */ data->outer_vlan_removal_enable_flg = test_bit(BNX2X_Q_UPDATE_OUT_VLAN_REM, ¶ms->update_flags); data->outer_vlan_removal_change_flg = @@ -4794,12 +4756,11 @@ static inline int bnx2x_q_send_update(struct bnx2x *bp, /* Fill the ramrod data */ bnx2x_q_fill_update_data(bp, o, update_params, rdata); - /* - * No need for an explicit memory barrier here as long we would - * need to ensure the ordering of writing to the SPQ element - * and updating of the SPQ producer which involves a memory - * read and we will have to put a full memory barrier there - * (inside bnx2x_sp_post()). + /* No need for an explicit memory barrier here as long we would + * need to ensure the ordering of writing to the SPQ element + * and updating of the SPQ producer which involves a memory + * read and we will have to put a full memory barrier there + * (inside bnx2x_sp_post()). */ return bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_UPDATE, @@ -5009,8 +4970,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, ¶ms->params.update; u8 next_tx_only = o->num_tx_only; - /* - * Forget all pending for completion commands if a driver only state + /* Forget all pending for completion commands if a driver only state * transition has been requested. */ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { @@ -5018,8 +4978,7 @@ static int bnx2x_queue_chk_transition(struct bnx2x *bp, o->next_state = BNX2X_Q_STATE_MAX; } - /* - * Don't allow a next state transition if we are in the middle of + /* Don't allow a next state transition if we are in the middle of * the previous one. */ if (o->pending) { @@ -5228,8 +5187,7 @@ enum bnx2x_func_state bnx2x_func_get_state(struct bnx2x *bp, if (o->pending) return BNX2X_F_STATE_MAX; - /* - * unsure the order of reading of o->pending and o->state + /* unsure the order of reading of o->pending and o->state * o->pending should be read first */ rmb(); @@ -5327,8 +5285,7 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, enum bnx2x_func_state state = o->state, next_state = BNX2X_F_STATE_MAX; enum bnx2x_func_cmd cmd = params->cmd; - /* - * Forget all pending for completion commands if a driver only state + /* Forget all pending for completion commands if a driver only state * transition has been requested. */ if (test_bit(RAMROD_DRV_CLR_ONLY, ¶ms->ramrod_flags)) { @@ -5336,8 +5293,7 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp, o->next_state = BNX2X_F_STATE_MAX; } - /* - * Don't allow a next state transition if we are in the middle of + /* Don't allow a next state transition if we are in the middle of * the previous one. */ if (o->pending) @@ -5510,7 +5466,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp, goto init_err; } - /* Handle the beginning of COMMON_XXX pases separatelly... */ + /* Handle the beginning of COMMON_XXX pases separately... */ switch (load_code) { case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP: rc = bnx2x_func_init_cmn_chip(bp, drv); @@ -5544,7 +5500,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp, init_err: drv->gunzip_end(bp); - /* In case of success, complete the comand immediatelly: no ramrods + /* In case of success, complete the command immediately: no ramrods * have been sent. */ if (!rc) @@ -5569,7 +5525,7 @@ static inline void bnx2x_func_reset_func(struct bnx2x *bp, } /** - * bnx2x_func_reset_port - reser HW at port stage + * bnx2x_func_reset_port - reset HW at port stage * * @bp: device handle * @drv: @@ -5591,7 +5547,7 @@ static inline void bnx2x_func_reset_port(struct bnx2x *bp, } /** - * bnx2x_func_reset_cmn - reser HW at common stage + * bnx2x_func_reset_cmn - reset HW at common stage * * @bp: device handle * @drv: @@ -5633,7 +5589,7 @@ static inline int bnx2x_func_hw_reset(struct bnx2x *bp, break; } - /* Complete the comand immediatelly: no ramrods have been sent. */ + /* Complete the command immediately: no ramrods have been sent. */ o->complete_cmd(bp, o, BNX2X_F_CMD_HW_RESET); return 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index c4fffe0faba0..798dfe996733 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -34,8 +34,7 @@ enum { RAMROD_RESTORE, /* Execute the next command now */ RAMROD_EXEC, - /* - * Don't add a new command and continue execution of posponed + /* Don't add a new command and continue execution of postponed * commands. If not set a new command will be added to the * pending commands list. */ @@ -129,8 +128,7 @@ enum bnx2x_vlan_mac_cmd { struct bnx2x_vlan_mac_data { /* Requested command: BNX2X_VLAN_MAC_XX */ enum bnx2x_vlan_mac_cmd cmd; - /* - * used to contain the data related vlan_mac_flags bits from + /* used to contain the data related vlan_mac_flags bits from * ramrod parameters. */ unsigned long vlan_mac_flags; @@ -190,14 +188,10 @@ typedef struct bnx2x_exeq_elem * struct bnx2x_exeq_elem *elem); struct bnx2x_exe_queue_obj { - /* - * Commands pending for an execution. - */ + /* Commands pending for an execution. */ struct list_head exe_queue; - /* - * Commands pending for an completion. - */ + /* Commands pending for an completion. */ struct list_head pending_comp; spinlock_t lock; @@ -245,14 +239,13 @@ struct bnx2x_exe_queue_obj { }; /***************** Classification verbs: Set/Del MAC/VLAN/VLAN-MAC ************/ /* - * Element in the VLAN_MAC registry list having all currenty configured + * Element in the VLAN_MAC registry list having all currently configured * rules. */ struct bnx2x_vlan_mac_registry_elem { struct list_head link; - /* - * Used to store the cam offset used for the mac/vlan/vlan-mac. + /* Used to store the cam offset used for the mac/vlan/vlan-mac. * Relevant for 57710 and 57711 only. VLANs and MACs share the * same CAM for these chips. */ @@ -310,7 +303,7 @@ struct bnx2x_vlan_mac_obj { * @param n number of elements to get * @param buf buffer preallocated by caller into which elements * will be copied. Note elements are 4-byte aligned - * so buffer size must be able to accomodate the + * so buffer size must be able to accommodate the * aligned elements. * * @return number of copied bytes @@ -395,7 +388,7 @@ struct bnx2x_vlan_mac_obj { * @param bp * @param p Command parameters (RAMROD_COMP_WAIT bit in * ramrod_flags is only taken into an account) - * @param ppos a pointer to the cooky that should be given back in the + * @param ppos a pointer to the cookie that should be given back in the * next call to make function handle the next element. If * *ppos is set to NULL it will restart the iterator. * If returned *ppos == NULL this means that the last @@ -408,7 +401,7 @@ struct bnx2x_vlan_mac_obj { struct bnx2x_vlan_mac_registry_elem **ppos); /** - * Should be called on a completion arival. + * Should be called on a completion arrival. * * @param bp * @param o @@ -447,7 +440,7 @@ void bnx2x_set_mac_in_nig(struct bnx2x *bp, /** RX_MODE verbs:DROP_ALL/ACCEPT_ALL/ACCEPT_ALL_MULTI/ACCEPT_ALL_VLAN/NORMAL */ -/* RX_MODE ramrod spesial flags: set in rx_mode_flags field in +/* RX_MODE ramrod special flags: set in rx_mode_flags field in * a bnx2x_rx_mode_ramrod_params. */ enum { @@ -475,8 +468,7 @@ struct bnx2x_rx_mode_ramrod_params { unsigned long ramrod_flags; unsigned long rx_mode_flags; - /* - * rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to + /* rdata is either a pointer to eth_filter_rules_ramrod_data(e2) or to * a tstorm_eth_mac_filter_config (e1x). */ void *rdata; @@ -646,12 +638,11 @@ struct bnx2x_credit_pool_obj { /* Maximum allowed credit. put() will check against it. */ int pool_sz; - /* - * Allocate a pool table statically. + /* Allocate a pool table statically. * - * Currently the mamimum allowed size is MAX_MAC_CREDIT_E2(272) + * Currently the maximum allowed size is MAX_MAC_CREDIT_E2(272) * - * The set bit in the table will mean that the entry is available. + * The set bit in the table will mean that the entry is available. */ #define BNX2X_POOL_VEC_SIZE (MAX_MAC_CREDIT_E2 / 64) u64 pool_mirror[BNX2X_POOL_VEC_SIZE]; @@ -832,7 +823,7 @@ enum { BNX2X_Q_FLG_TUN_INC_INNER_IP_ID }; -/* Queue type options: queue type may be a compination of below. */ +/* Queue type options: queue type may be a combination of below. */ enum bnx2x_q_type { /** TODO: Consider moving both these flags into the init() * ramrod params. @@ -1002,10 +993,9 @@ struct bnx2x_queue_sp_obj { u8 cl_id; u8 func_id; - /* - * number of traffic classes supported by queue. - * The primary connection of the queue suppotrs the first traffic - * class. Any further traffic class is suppoted by a tx-only + /* number of traffic classes supported by queue. + * The primary connection of the queue supports the first traffic + * class. Any further traffic class is supported by a tx-only * connection. * * Therefore max_cos is also a number of valid entries in the cids @@ -1021,7 +1011,7 @@ struct bnx2x_queue_sp_obj { /* BNX2X_Q_CMD_XX bits. This object implements "one * pending" paradigm but for debug and tracing purposes it's - * more convinient to have different bits for different + * more convenient to have different bits for different * commands. */ unsigned long pending; @@ -1210,7 +1200,7 @@ struct bnx2x_func_sp_obj { /* BNX2X_FUNC_CMD_XX bits. This object implements "one * pending" paradigm but for debug and tracing purposes it's - * more convinient to have different bits for different + * more convenient to have different bits for different * commands. */ unsigned long pending; @@ -1329,7 +1319,7 @@ void bnx2x_init_rx_mode_obj(struct bnx2x *bp, * * @p: Command parameters * - * Return: 0 - if operation was successfull and there is no pending completions, + * Return: 0 - if operation was successful and there is no pending completions, * positive number - if there are pending completions, * negative - if there were errors */ @@ -1361,7 +1351,7 @@ void bnx2x_init_mcast_obj(struct bnx2x *bp, * the current command will be enqueued to the tail of the * pending commands list. * - * Return: 0 is operation was successfull and there are no pending completions, + * Return: 0 is operation was successful and there are no pending completions, * negative if there were errors, positive if there are pending * completions. */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index ea492c7a96a1..b2ab288aaf76 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1341,7 +1341,7 @@ int bnx2x_vfop_qdown_cmd(struct bnx2x *bp, */ /* internal vf enable - until vf is enabled internally all transactions - * are blocked. this routine should always be called last with pretend. + * are blocked. This routine should always be called last with pretend. */ static void bnx2x_vf_enable_internal(struct bnx2x *bp, u8 enable) { @@ -1743,7 +1743,7 @@ void bnx2x_iov_init_dq(struct bnx2x *bp) REG_WR(bp, DORQ_REG_VF_TYPE_MIN_MCID_0, 0); REG_WR(bp, DORQ_REG_VF_TYPE_MAX_MCID_0, 0x1ffff); - /* set the number of VF alllowed doorbells to the full DQ range */ + /* set the number of VF allowed doorbells to the full DQ range */ REG_WR(bp, DORQ_REG_VF_NORM_MAX_CID_COUNT, 0x20000); /* set the VF doorbell threshold */ @@ -2403,7 +2403,7 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem) /* extract vf and rxq index from vf_cid - relies on the following: * 1. vfid on cid reflects the true abs_vfid - * 2. the max number of VFs (per path) is 64 + * 2. The max number of VFs (per path) is 64 */ qidx = cid & ((1 << BNX2X_VF_CID_WND)-1); abs_vfid = (cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1); @@ -2461,7 +2461,7 @@ static struct bnx2x_virtf *bnx2x_vf_by_cid(struct bnx2x *bp, int vf_cid) { /* extract the vf from vf_cid - relies on the following: * 1. vfid on cid reflects the true abs_vfid - * 2. the max number of VFs (per path) is 64 + * 2. The max number of VFs (per path) is 64 */ int abs_vfid = (vf_cid >> BNX2X_VF_CID_WND) & (BNX2X_MAX_NUM_OF_VFS-1); return bnx2x_vf_by_abs_fid(bp, abs_vfid); @@ -2480,7 +2480,7 @@ void bnx2x_iov_set_queue_sp_obj(struct bnx2x *bp, int vf_cid, if (vf) { /* extract queue index from vf_cid - relies on the following: * 1. vfid on cid reflects the true abs_vfid - * 2. the max number of VFs (per path) is 64 + * 2. The max number of VFs (per path) is 64 */ int q_index = vf_cid & ((1 << BNX2X_VF_CID_WND)-1); *q_obj = &bnx2x_vfq(vf, q_index, sp_obj); @@ -2705,7 +2705,7 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, } /* static allocation: - * the global maximum number are fixed per VF. fail the request if + * the global maximum number are fixed per VF. Fail the request if * requested number exceed these globals */ if (!bnx2x_vf_chk_avail_resc(bp, vf, resc)) { @@ -2890,7 +2890,7 @@ int bnx2x_vfop_close_cmd(struct bnx2x *bp, return -ENOMEM; } -/* VF release can be called either: 1. the VF was acquired but +/* VF release can be called either: 1. The VF was acquired but * not enabled 2. the vf was enabled or in the process of being * enabled */ @@ -3140,7 +3140,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx, /* mac configured by ndo so its in bulletin board */ memcpy(&ivi->mac, bulletin->mac, ETH_ALEN); else - /* funtion has not been loaded yet. Show mac as 0s */ + /* function has not been loaded yet. Show mac as 0s */ memset(&ivi->mac, 0, ETH_ALEN); /* vlan */ @@ -3148,7 +3148,7 @@ int bnx2x_get_vf_config(struct net_device *dev, int vfidx, /* vlan configured by ndo so its in bulletin board */ memcpy(&ivi->vlan, &bulletin->vlan, VLAN_HLEN); else - /* funtion has not been loaded yet. Show vlans as 0s */ + /* function has not been loaded yet. Show vlans as 0s */ memset(&ivi->vlan, 0, VLAN_HLEN); } @@ -3188,7 +3188,7 @@ int bnx2x_set_vf_mac(struct net_device *dev, int vfidx, u8 *mac) return -EINVAL; } - /* update PF's copy of the VF's bulletin. will no longer accept mac + /* update PF's copy of the VF's bulletin. Will no longer accept mac * configuration requests from vf unless match this mac */ bulletin->valid_bitmap |= 1 << MAC_ADDR_VALID; @@ -3357,8 +3357,11 @@ int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos) return 0; } -/* crc is the first field in the bulletin board. compute the crc over the - * entire bulletin board excluding the crc field itself +/* crc is the first field in the bulletin board. Compute the crc over the + * entire bulletin board excluding the crc field itself. Use the length field + * as the Bulletin Board was posted by a PF with possibly a different version + * from the vf which will sample it. Therefore, the length is computed by the + * PF and the used blindly by the VF. */ u32 bnx2x_crc_vf_bulletin(struct bnx2x *bp, struct pf_vf_bulletin_content *bulletin) @@ -3451,7 +3454,7 @@ int bnx2x_open_epilog(struct bnx2x *bp) * register_netdevice which must have rtnl lock taken. As we are holding * the lock right now, that could only work if the probe would not take * the lock. However, as the probe of the vf may be called from other - * contexts as well (such as passthrough to vm failes) it can't assume + * contexts as well (such as passthrough to vm fails) it can't assume * the lock is being held for it. Using delayed work here allows the * probe code to simply take the lock (i.e. wait for it to be released * if it is being held). We only want to do this if the number of VFs diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 039792299c3b..3e7cb8341841 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -197,7 +197,7 @@ struct bnx2x_virtf { u8 state; #define VF_FREE 0 /* VF ready to be acquired holds no resc */ -#define VF_ACQUIRED 1 /* VF aquired, but not initalized */ +#define VF_ACQUIRED 1 /* VF acquired, but not initialized */ #define VF_ENABLED 2 /* VF Enabled */ #define VF_RESET 3 /* VF FLR'd, pending cleanup */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 282606677bca..f55fa0725680 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -233,7 +233,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count) attempts++; - /* test whether the PF accepted our request. If not, humble the + /* test whether the PF accepted our request. If not, humble * the request and try again. */ if (bp->acquire_resp.hdr.status == PFVF_STATUS_SUCCESS) { @@ -787,7 +787,7 @@ static inline void bnx2x_set_vf_mbxs_valid(struct bnx2x *bp) storm_memset_vf_mbx_valid(bp, bnx2x_vf(bp, i, abs_vfid)); } -/* enable vf_pf mailbox (aka vf-pf-chanell) */ +/* enable vf_pf mailbox (aka vf-pf-channel) */ void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid) { bnx2x_vf_flr_clnup_epilog(bp, abs_vfid); @@ -1072,7 +1072,7 @@ static void bnx2x_vf_mbx_set_q_flags(struct bnx2x *bp, u32 mbx_q_flags, if (mbx_q_flags & VFPF_QUEUE_FLG_DHC) __set_bit(BNX2X_Q_FLG_DHC, sp_q_flags); - /* outer vlan removal is set according to the PF's multi fuction mode */ + /* outer vlan removal is set according to PF's multi function mode */ if (IS_MF_SD(bp)) __set_bit(BNX2X_Q_FLG_OV, sp_q_flags); } @@ -1104,7 +1104,7 @@ static void bnx2x_vf_mbx_setup_q(struct bnx2x *bp, struct bnx2x_virtf *vf, struct bnx2x_queue_init_params *init_p; struct bnx2x_queue_setup_params *setup_p; - /* reinit the VF operation context */ + /* re-init the VF operation context */ memset(&vf->op_params.qctor, 0 , sizeof(vf->op_params.qctor)); setup_p = &vf->op_params.qctor.prep_qsetup; init_p = &vf->op_params.qctor.qstate.params.init; -- GitLab From 3cdeec22e40264e40d34d8242b4ce7461329a80a Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 2 Jun 2013 00:06:19 +0000 Subject: [PATCH 0580/2900] bnx2x: Semantic removal and beautification This patch introduces several small changes to the driver, none which actually change any flow: 1. Removes prototypes of unexisting functions and unused defines. 2. Fixes alignment and spacing issues. 3. Changes numeric usage into constants. 4. Remove unnecessary parenthesis. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 3 -- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 32 ++++++++----------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 4a643d7b9b22..68fefa8d97a5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -493,9 +493,6 @@ void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value); /* Error handling */ void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl); -/* validate currect fw is loaded */ -bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err); - /* dev_close main block */ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 82f3696437c2..28b8fd5460d7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -102,8 +102,6 @@ static int disable_tpa; module_param(disable_tpa, int, 0); MODULE_PARM_DESC(disable_tpa, " Disable the TPA (LRO) feature"); -#define INT_MODE_INTx 1 -#define INT_MODE_MSI 2 int int_mode; module_param(int_mode, int, 0); MODULE_PARM_DESC(int_mode, " Force interrupt mode other than MSI-X " @@ -3068,7 +3066,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp, * placed on the BD (not including paddings). */ rxq_init->buf_sz = fp->rx_buf_size - BNX2X_FW_RX_ALIGN_START - - BNX2X_FW_RX_ALIGN_END - IP_HEADER_ALIGNMENT_PADDING; + BNX2X_FW_RX_ALIGN_END - IP_HEADER_ALIGNMENT_PADDING; rxq_init->cl_qzone_id = fp->cl_qzone_id; rxq_init->tpa_agg_sz = tpa_agg_size; @@ -3619,15 +3617,14 @@ static int bnx2x_acquire_alr(struct bnx2x *bp) might_sleep(); for (j = 0; j < 1000; j++) { - val = (1UL << 31); - REG_WR(bp, GRCBASE_MCP + 0x9c, val); - val = REG_RD(bp, GRCBASE_MCP + 0x9c); - if (val & (1L << 31)) + REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, MCPR_ACCESS_LOCK_LOCK); + val = REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK); + if (val & MCPR_ACCESS_LOCK_LOCK) break; msleep(5); } - if (!(val & (1L << 31))) { + if (!(val & MCPR_ACCESS_LOCK_LOCK)) { BNX2X_ERR("Cannot acquire MCP access lock register\n"); rc = -EBUSY; } @@ -3638,7 +3635,7 @@ static int bnx2x_acquire_alr(struct bnx2x *bp) /* release split MCP access lock register */ static void bnx2x_release_alr(struct bnx2x *bp) { - REG_WR(bp, GRCBASE_MCP + 0x9c, 0); + REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0); } #define BNX2X_DEF_SB_ATT_IDX 0x0001 @@ -4086,7 +4083,7 @@ static void bnx2x_clear_reset_global(struct bnx2x *bp) */ static bool bnx2x_reset_is_global(struct bnx2x *bp) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); DP(NETIF_MSG_HW, "GEN_REG_VAL=0x%08x\n", val); return (val & BNX2X_GLOBAL_RESET_BIT) ? true : false; @@ -4137,7 +4134,7 @@ void bnx2x_set_reset_in_progress(struct bnx2x *bp) */ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine) { - u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); + u32 val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); u32 bit = engine ? BNX2X_PATH1_RST_IN_PROG_BIT : BNX2X_PATH0_RST_IN_PROG_BIT; @@ -6013,11 +6010,6 @@ void bnx2x_pre_irq_nic_init(struct bnx2x *bp) bnx2x_init_rx_rings(bp); bnx2x_init_tx_rings(bp); - if (IS_VF(bp)) { - bnx2x_memset_stats(bp); - return; - } - if (IS_PF(bp)) { /* Initialize MOD_ABS interrupts */ bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id, @@ -6028,6 +6020,8 @@ void bnx2x_pre_irq_nic_init(struct bnx2x *bp) bnx2x_init_def_sb(bp); bnx2x_update_dsb_idx(bp); bnx2x_init_sp_ring(bp); + } else { + bnx2x_memset_stats(bp); } } @@ -10011,7 +10005,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) : (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8); - hw_lock_val = (REG_RD(bp, hw_lock_reg)); + hw_lock_val = REG_RD(bp, hw_lock_reg); if (hw_lock_val) { if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) { BNX2X_DEV_INFO("Release Previously held NVRAM lock\n"); @@ -10026,7 +10020,7 @@ static int bnx2x_prev_unload(struct bnx2x *bp) if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) { BNX2X_DEV_INFO("Release previously held alr\n"); - REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0); + bnx2x_release_alr(bp); } do { @@ -11878,7 +11872,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { .ndo_setup_tc = bnx2x_setup_tc, #ifdef CONFIG_BNX2X_SRIOV .ndo_set_vf_mac = bnx2x_set_vf_mac, - .ndo_set_vf_vlan = bnx2x_set_vf_vlan, + .ndo_set_vf_vlan = bnx2x_set_vf_vlan, .ndo_get_vf_config = bnx2x_get_vf_config, #endif #ifdef NETDEV_FCOE_WWNN -- GitLab From 6bf07b8e3666257c5172ab1681b377e547747d9b Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 2 Jun 2013 00:06:20 +0000 Subject: [PATCH 0581/2900] bnx2x: Revise prints This patch revises many bnx2x prints - mainly fixing print typos and adding some new debug prints (mostly for parity issues). Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 1 - .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 8 +- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 16 +- .../net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | 4 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 257 +++++++++++++----- .../net/ethernet/broadcom/bnx2x/bnx2x_reg.h | 6 + .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 6 +- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 +- .../net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 8 +- 9 files changed, 224 insertions(+), 84 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 8f551cf7bb30..f76597e5fa55 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1900,7 +1900,6 @@ u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type, void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae, u8 src_type, u8 dst_type); int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae); -void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl); /* FLR related routines */ u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ef7fed52891a..14b5acd8eafc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2162,10 +2162,10 @@ static int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) bp->fw_stats_data_mapping = bp->fw_stats_mapping + bp->fw_stats_req_sz; - DP(BNX2X_MSG_SP, "statistics request base address set to %x %x", + DP(BNX2X_MSG_SP, "statistics request base address set to %x %x\n", U64_HI(bp->fw_stats_req_mapping), U64_LO(bp->fw_stats_req_mapping)); - DP(BNX2X_MSG_SP, "statistics data base address set to %x %x", + DP(BNX2X_MSG_SP, "statistics data base address set to %x %x\n", U64_HI(bp->fw_stats_data_mapping), U64_LO(bp->fw_stats_data_mapping)); return 0; @@ -2240,7 +2240,7 @@ int bnx2x_nic_load_analyze_req(struct bnx2x *bp, u32 load_code) /* abort nic load if version mismatch */ if (my_fw != loaded_fw) { - BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. aborting\n", + BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n", loaded_fw, my_fw); return -EBUSY; } @@ -3977,7 +3977,7 @@ int bnx2x_setup_tc(struct net_device *dev, u8 num_tc) /* requested to support too many traffic classes */ if (num_tc > bp->max_cos) { - BNX2X_ERR("support for too many traffic classes requested: %d. max supported is %d\n", + BNX2X_ERR("support for too many traffic classes requested: %d. Max supported is %d\n", num_tc, bp->max_cos); return -EINVAL; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 68fefa8d97a5..650bb52155a8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -49,13 +49,15 @@ extern int int_mode; } \ } while (0) -#define BNX2X_PCI_ALLOC(x, y, size) \ -do { \ - x = dma_alloc_coherent(&bp->pdev->dev, size, y, \ - GFP_KERNEL | __GFP_ZERO); \ - if (x == NULL) \ - goto alloc_mem_err; \ -} while (0) +#define BNX2X_PCI_ALLOC(x, y, size) \ + do { \ + x = dma_alloc_coherent(&bp->pdev->dev, size, y, \ + GFP_KERNEL | __GFP_ZERO); \ + if (x == NULL) \ + goto alloc_mem_err; \ + DP(NETIF_MSG_HW, "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n", \ + (unsigned long long)(*y), x); \ + } while (0) #define BNX2X_ALLOC(x, size) \ do { \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 210614e37b9b..0c94df47e0e8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c @@ -2381,7 +2381,7 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid, *flags |= DCB_FEATCFG_ERROR; break; default: - BNX2X_ERR("Non valid featrue-ID\n"); + BNX2X_ERR("Non valid feature-ID\n"); rval = 1; break; } @@ -2422,7 +2422,7 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid, flags & DCB_FEATCFG_WILLING ? 1 : 0; break; default: - BNX2X_ERR("Non valid featrue-ID\n"); + BNX2X_ERR("Non valid feature-ID\n"); rval = 1; break; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 28b8fd5460d7..60ff1aaba6dc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -371,9 +371,11 @@ static u32 bnx2x_reg_rd_ind(struct bnx2x *bp, u32 addr) #define DMAE_DP_DST_PCI "pci dst_addr [%x:%08x]" #define DMAE_DP_DST_NONE "dst_addr [none]" -void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl) +static void bnx2x_dp_dmae(struct bnx2x *bp, + struct dmae_command *dmae, int msglvl) { u32 src_type = dmae->opcode & DMAE_COMMAND_SRC; + int i; switch (dmae->opcode & DMAE_COMMAND_DST) { case DMAE_CMD_DST_PCI: @@ -429,6 +431,10 @@ void bnx2x_dp_dmae(struct bnx2x *bp, struct dmae_command *dmae, int msglvl) dmae->comp_val); break; } + + for (i = 0; i < (sizeof(struct dmae_command)/4); i++) + DP(msglvl, "DMAE RAW [%02d]: 0x%08x\n", + i, *(((u32 *)dmae) + i)); } /* copy command into DMAE command memory and set DMAE command go */ @@ -503,8 +509,9 @@ int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae) int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 4000; int rc = 0; - /* - * Lock the dmae channel. Disable BHs to prevent a dead-lock + bnx2x_dp_dmae(bp, dmae, BNX2X_MSG_DMAE); + + /* Lock the dmae channel. Disable BHs to prevent a dead-lock * as long as this code is called both from syscall context and * from ndo_set_rx_mode() flow that may be called from BH. */ @@ -543,6 +550,7 @@ int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae) void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, u32 len32) { + int rc; struct dmae_command dmae; if (!bp->dmae_ready) { @@ -566,11 +574,16 @@ void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr, dmae.len = len32; /* issue the command and wait for completion */ - bnx2x_issue_dmae_with_comp(bp, &dmae); + rc = bnx2x_issue_dmae_with_comp(bp, &dmae); + if (rc) { + BNX2X_ERR("DMAE returned failure %d\n", rc); + bnx2x_panic(); + } } void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) { + int rc; struct dmae_command dmae; if (!bp->dmae_ready) { @@ -598,7 +611,11 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) dmae.len = len32; /* issue the command and wait for completion */ - bnx2x_issue_dmae_with_comp(bp, &dmae); + rc = bnx2x_issue_dmae_with_comp(bp, &dmae); + if (rc) { + BNX2X_ERR("DMAE returned failure %d\n", rc); + bnx2x_panic(); + }; } static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, @@ -834,7 +851,7 @@ static void bnx2x_hc_int_disable(struct bnx2x *bp) REG_WR(bp, addr, val); if (REG_RD(bp, addr) != val) - BNX2X_ERR("BUG! proper val not read from IGU!\n"); + BNX2X_ERR("BUG! Proper val not read from IGU!\n"); } static void bnx2x_igu_int_disable(struct bnx2x *bp) @@ -852,7 +869,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp) REG_WR(bp, IGU_REG_PF_CONFIGURATION, val); if (REG_RD(bp, IGU_REG_PF_CONFIGURATION) != val) - BNX2X_ERR("BUG! proper val not read from IGU!\n"); + BNX2X_ERR("BUG! Proper val not read from IGU!\n"); } static void bnx2x_int_disable(struct bnx2x *bp) @@ -1021,6 +1038,7 @@ void bnx2x_panic_dump(struct bnx2x *bp, bool disable_int) #ifdef BNX2X_STOP_ON_ERROR /* event queue */ + BNX2X_ERR("eq cons %x prod %x\n", bp->eq_cons, bp->eq_prod); for (i = 0; i < NUM_EQ_DESC; i++) { u32 *data = (u32 *)&bp->eq_ring[i].message.data; @@ -1379,7 +1397,7 @@ static int bnx2x_poll_hw_usage_counters(struct bnx2x *bp, u32 poll_cnt) /* Wait DMAE PF usage counter to zero */ if (bnx2x_flr_clnup_poll_hw_counter(bp, dmae_reg_go_c[INIT_DMAE_C(bp)], - "DMAE dommand register timed out", + "DMAE command register timed out", poll_cnt)) return 1; @@ -1759,7 +1777,7 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe) break; case (RAMROD_CMD_ID_ETH_TERMINATE): - DP(BNX2X_MSG_SP, "got MULTI[%d] teminate ramrod\n", cid); + DP(BNX2X_MSG_SP, "got MULTI[%d] terminate ramrod\n", cid); drv_cmd = BNX2X_Q_CMD_TERMINATE; break; @@ -1971,8 +1989,8 @@ int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource) /* Validating that the resource is currently taken */ lock_status = REG_RD(bp, hw_lock_control_reg); if (!(lock_status & resource_bit)) { - BNX2X_ERR("lock_status 0x%x resource_bit 0x%x. unlock was called but lock wasn't taken!\n", - lock_status, resource_bit); + BNX2X_ERR("lock_status 0x%x resource_bit 0x%x. Unlock was called but lock wasn't taken!\n", + lock_status, resource_bit); return -EFAULT; } @@ -4237,13 +4255,18 @@ static bool bnx2x_get_load_status(struct bnx2x *bp, int engine) return val != 0; } +static void _print_parity(struct bnx2x *bp, u32 reg) +{ + pr_cont(" [0x%08x] ", REG_RD(bp, reg)); +} + static void _print_next_block(int idx, const char *blk) { pr_cont("%s%s", idx ? ", " : "", blk); } -static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num, - bool print) +static int bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig, + int par_num, bool print) { int i = 0; u32 cur_bit = 0; @@ -4252,33 +4275,54 @@ static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num, if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "BRB"); + _print_parity(bp, + BRB1_REG_BRB1_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "PARSER"); + _print_parity(bp, PRS_REG_PRS_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "TSDM"); + _print_parity(bp, + TSDM_REG_TSDM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "SEARCHER"); + _print_parity(bp, SRC_REG_SRC_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "TCM"); + _print_parity(bp, + TCM_REG_TCM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "TSEMI"); + _print_parity(bp, + TSEM_REG_TSEM_PRTY_STS_0); + _print_parity(bp, + TSEM_REG_TSEM_PRTY_STS_1); + } break; case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "XPB"); + _print_parity(bp, GRCBASE_XPB + + PB_REG_PB_PRTY_STS); + } break; } @@ -4290,8 +4334,9 @@ static int bnx2x_check_blocks_with_parity0(u32 sig, int par_num, return par_num; } -static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num, - bool *global, bool print) +static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig, + int par_num, bool *global, + bool print) { int i = 0; u32 cur_bit = 0; @@ -4300,37 +4345,66 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num, if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "PBF"); + _print_parity(bp, PBF_REG_PBF_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "QM"); + _print_parity(bp, QM_REG_QM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "TM"); + _print_parity(bp, TM_REG_TM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "XSDM"); + _print_parity(bp, + XSDM_REG_XSDM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "XCM"); + _print_parity(bp, XCM_REG_XCM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "XSEMI"); + _print_parity(bp, + XSEM_REG_XSEM_PRTY_STS_0); + _print_parity(bp, + XSEM_REG_XSEM_PRTY_STS_1); + } break; case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "DOORBELLQ"); + _print_parity(bp, + DORQ_REG_DORQ_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "NIG"); + if (CHIP_IS_E1x(bp)) { + _print_parity(bp, + NIG_REG_NIG_PRTY_STS); + } else { + _print_parity(bp, + NIG_REG_NIG_PRTY_STS_0); + _print_parity(bp, + NIG_REG_NIG_PRTY_STS_1); + } + } break; case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR: if (print) @@ -4339,32 +4413,52 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num, *global = true; break; case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "DEBUG"); + _print_parity(bp, DBG_REG_DBG_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "USDM"); + _print_parity(bp, + USDM_REG_USDM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "UCM"); + _print_parity(bp, UCM_REG_UCM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "USEMI"); + _print_parity(bp, + USEM_REG_USEM_PRTY_STS_0); + _print_parity(bp, + USEM_REG_USEM_PRTY_STS_1); + } break; case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "UPB"); + _print_parity(bp, GRCBASE_UPB + + PB_REG_PB_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "CSDM"); + _print_parity(bp, + CSDM_REG_CSDM_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "CCM"); + _print_parity(bp, CCM_REG_CCM_PRTY_STS); + } break; } @@ -4376,8 +4470,8 @@ static int bnx2x_check_blocks_with_parity1(u32 sig, int par_num, return par_num; } -static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num, - bool print) +static int bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig, + int par_num, bool print) { int i = 0; u32 cur_bit = 0; @@ -4386,12 +4480,23 @@ static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num, if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "CSEMI"); + _print_parity(bp, + CSEM_REG_CSEM_PRTY_STS_0); + _print_parity(bp, + CSEM_REG_CSEM_PRTY_STS_1); + } break; case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "PXP"); + _print_parity(bp, PXP_REG_PXP_PRTY_STS); + _print_parity(bp, + PXP2_REG_PXP2_PRTY_STS_0); + _print_parity(bp, + PXP2_REG_PXP2_PRTY_STS_1); + } break; case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR: if (print) @@ -4399,24 +4504,42 @@ static int bnx2x_check_blocks_with_parity2(u32 sig, int par_num, "PXPPCICLOCKCLIENT"); break; case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "CFC"); + _print_parity(bp, + CFC_REG_CFC_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "CDU"); + _print_parity(bp, CDU_REG_CDU_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "DMAE"); + _print_parity(bp, + DMAE_REG_DMAE_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "IGU"); + if (CHIP_IS_E1x(bp)) + _print_parity(bp, + HC_REG_HC_PRTY_STS); + else + _print_parity(bp, + IGU_REG_IGU_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "MISC"); + _print_parity(bp, + MISC_REG_MISC_PRTY_STS); + } break; } @@ -4470,8 +4593,8 @@ static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num, return par_num; } -static int bnx2x_check_blocks_with_parity4(u32 sig, int par_num, - bool print) +static int bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig, + int par_num, bool print) { int i = 0; u32 cur_bit = 0; @@ -4480,12 +4603,18 @@ static int bnx2x_check_blocks_with_parity4(u32 sig, int par_num, if (sig & cur_bit) { switch (cur_bit) { case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "PGLUE_B"); + _print_parity(bp, + PGLUE_B_REG_PGLUE_B_PRTY_STS); + } break; case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR: - if (print) + if (print) { _print_next_block(par_num++, "ATC"); + _print_parity(bp, + ATC_REG_ATC_PRTY_STS); + } break; } @@ -4516,15 +4645,15 @@ static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print, if (print) netdev_err(bp->dev, "Parity errors detected in blocks: "); - par_num = bnx2x_check_blocks_with_parity0( + par_num = bnx2x_check_blocks_with_parity0(bp, sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print); - par_num = bnx2x_check_blocks_with_parity1( + par_num = bnx2x_check_blocks_with_parity1(bp, sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print); - par_num = bnx2x_check_blocks_with_parity2( + par_num = bnx2x_check_blocks_with_parity2(bp, sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print); par_num = bnx2x_check_blocks_with_parity3( sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print); - par_num = bnx2x_check_blocks_with_parity4( + par_num = bnx2x_check_blocks_with_parity4(bp, sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print); if (print) @@ -7437,7 +7566,7 @@ static int bnx2x_init_hw_func(struct bnx2x *bp) } else { /* Set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); - DP(NETIF_MSG_IFUP, "NIC MODE configrued\n"); + DP(NETIF_MSG_IFUP, "NIC MODE configured\n"); } if (!CHIP_IS_E1x(bp)) { @@ -8609,7 +8738,7 @@ static int bnx2x_func_wait_started(struct bnx2x *bp) struct bnx2x_func_state_params func_params = {NULL}; DP(NETIF_MSG_IFDOWN, - "Hmmm... unexpected function state! Forcing STARTED-->TX_ST0PPED-->STARTED\n"); + "Hmmm... Unexpected function state! Forcing STARTED-->TX_ST0PPED-->STARTED\n"); func_params.f_obj = &bp->func_obj; __set_bit(RAMROD_DRV_CLR_ONLY, @@ -9426,14 +9555,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) return; } - /* if stop on error is defined no recovery flows should be executed */ + if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) { #ifdef BNX2X_STOP_ON_ERROR - BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n" - "you will need to reboot when done\n"); - goto sp_rtnl_not_reset; + BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n" + "you will need to reboot when done\n"); + goto sp_rtnl_not_reset; #endif - - if (unlikely(bp->recovery_state != BNX2X_RECOVERY_DONE)) { /* * Clear all pending SP commands as we are going to reset the * function anyway. @@ -9448,6 +9575,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) } if (test_and_clear_bit(BNX2X_SP_RTNL_TX_TIMEOUT, &bp->sp_rtnl_state)) { +#ifdef BNX2X_STOP_ON_ERROR + BNX2X_ERR("recovery flow called but STOP_ON_ERROR defined so reset not done to allow debug dump,\n" + "you will need to reboot when done\n"); + goto sp_rtnl_not_reset; +#endif + /* * Clear all pending SP commands as we are going to reset the * function anyway. diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h index d22bc40091ec..8e627b886d7b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h @@ -35,6 +35,8 @@ #define ATC_REG_ATC_INT_STS_CLR 0x1101c0 /* [RW 5] Parity mask register #0 read/write */ #define ATC_REG_ATC_PRTY_MASK 0x1101d8 +/* [R 5] Parity register #0 read */ +#define ATC_REG_ATC_PRTY_STS 0x1101cc /* [RC 5] Parity register #0 read clear */ #define ATC_REG_ATC_PRTY_STS_CLR 0x1101d0 /* [RW 19] Interrupt mask register #0 read/write */ @@ -2750,6 +2752,8 @@ #define PBF_REG_PBF_INT_STS 0x1401c8 /* [RW 20] Parity mask register #0 read/write */ #define PBF_REG_PBF_PRTY_MASK 0x1401e4 +/* [R 28] Parity register #0 read */ +#define PBF_REG_PBF_PRTY_STS 0x1401d8 /* [RC 20] Parity register #0 read clear */ #define PBF_REG_PBF_PRTY_STS_CLR 0x1401dc /* [RW 16] The Ethernet type value for L2 tag 0 */ @@ -4517,6 +4521,8 @@ #define TM_REG_TM_INT_STS 0x1640f0 /* [RW 7] Parity mask register #0 read/write */ #define TM_REG_TM_PRTY_MASK 0x16410c +/* [R 7] Parity register #0 read */ +#define TM_REG_TM_PRTY_STS 0x164100 /* [RC 7] Parity register #0 read clear */ #define TM_REG_TM_PRTY_STS_CLR 0x164104 /* [RW 8] The event id for aggregated interrupt 0 */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index b2ab288aaf76..8a556dd888d5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1620,7 +1620,7 @@ static void bnx2x_vf_flr_clnup(struct bnx2x *bp, struct bnx2x_virtf *prev_vf) i++) ; - DP(BNX2X_MSG_IOV, "next vf to cleanup: %d. num of vfs: %d\n", i, + DP(BNX2X_MSG_IOV, "next vf to cleanup: %d. Num of vfs: %d\n", i, BNX2X_NR_VIRTFN(bp)); if (i < BNX2X_NR_VIRTFN(bp)) { @@ -3031,7 +3031,7 @@ int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs_param) /* HW channel is only operational when PF is up */ if (bp->state != BNX2X_STATE_OPEN) { - BNX2X_ERR("VF num configurtion via sysfs not supported while PF is down"); + BNX2X_ERR("VF num configuration via sysfs not supported while PF is down\n"); return -EINVAL; } @@ -3391,7 +3391,7 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp) if (bulletin.crc == bnx2x_crc_vf_bulletin(bp, &bulletin)) break; - BNX2X_ERR("bad crc on bulletin board. contained %x computed %x\n", + BNX2X_ERR("bad crc on bulletin board. Contained %x computed %x\n", bulletin.crc, bnx2x_crc_vf_bulletin(bp, &bulletin)); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 3e7cb8341841..f08c604a4fbd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -496,7 +496,7 @@ enum { else if ((next) == VFOP_VERIFY_PEND) \ BNX2X_ERR("expected pending\n"); \ else { \ - DP(BNX2X_MSG_IOV, "no ramrod. scheduling\n"); \ + DP(BNX2X_MSG_IOV, "no ramrod. Scheduling\n"); \ atomic_set(&vf->op_in_progress, 1); \ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); \ return; \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index f55fa0725680..861809d3154b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -333,7 +333,7 @@ int bnx2x_vfpf_release(struct bnx2x *bp) DP(BNX2X_MSG_SP, "vf released\n"); } else { /* PF reports error */ - BNX2X_ERR("PF failed our release request - are we out of sync? response status: %d\n", + BNX2X_ERR("PF failed our release request - are we out of sync? Response status: %d\n", resp->hdr.status); rc = -EAGAIN; goto out; @@ -844,7 +844,6 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf, dmae.dst_addr_hi = vf_addr_hi; } dmae.len = len32; - bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_DMAE); /* issue the command and wait for completion */ return bnx2x_issue_dmae_with_comp(bp, &dmae); @@ -1588,8 +1587,9 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf, * support them. Or this may be because someone wrote a crappy * VF driver and is sending garbage over the channel. */ - BNX2X_ERR("unknown TLV. type %d length %d. first 20 bytes of mailbox buffer:\n", - mbx->first_tlv.tl.type, mbx->first_tlv.tl.length); + BNX2X_ERR("unknown TLV. type %d length %d vf->state was %d. first 20 bytes of mailbox buffer:\n", + mbx->first_tlv.tl.type, mbx->first_tlv.tl.length, + vf->state); for (i = 0; i < 20; i++) DP_CONT(BNX2X_MSG_IOV, "%x ", mbx->msg->req.tlv_buf_size.tlv_buffer[i]); -- GitLab From 639d65b85592cf31eca24f33ff00e309ebbf0d2b Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 2 Jun 2013 00:06:21 +0000 Subject: [PATCH 0582/2900] bnx2x: semi-Semantic changes This patch includes a few changes that change the driver's flow without truly changing anything in its functionality - use usleep_range for short sleeps instead of msleep and initialize Tx consumer during initialization for better information during errors. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 60ff1aaba6dc..658b9fd0275f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1954,7 +1954,7 @@ int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource) if (lock_status & resource_bit) return 0; - msleep(5); + usleep_range(5000, 10000); } BNX2X_ERR("Timeout\n"); return -EAGAIN; @@ -3640,7 +3640,7 @@ static int bnx2x_acquire_alr(struct bnx2x *bp) if (val & MCPR_ACCESS_LOCK_LOCK) break; - msleep(5); + usleep_range(5000, 10000); } if (!(val & MCPR_ACCESS_LOCK_LOCK)) { BNX2X_ERR("Cannot acquire MCP access lock register\n"); @@ -6078,6 +6078,8 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata) BCM_PAGE_SIZE*(i % NUM_TX_RINGS))); } + *txdata->tx_cons_sb = cpu_to_le16(0); + SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1); txdata->tx_db.data.zero_fill1 = 0; txdata->tx_db.data.prod = 0; @@ -6329,7 +6331,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) if (val == 0x10) break; - msleep(10); + usleep_range(10000, 20000); count--; } if (val != 0x10) { @@ -6344,7 +6346,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) if (val == 1) break; - msleep(10); + usleep_range(10000, 20000); count--; } if (val != 0x1) { @@ -6385,7 +6387,7 @@ static int bnx2x_int_mem_test(struct bnx2x *bp) if (val == 0xb0) break; - msleep(10); + usleep_range(10000, 20000); count--; } if (val != 0xb0) { @@ -8500,7 +8502,7 @@ static void bnx2x_reset_func(struct bnx2x *bp) * scan to complete */ for (i = 0; i < 200; i++) { - msleep(10); + usleep_range(10000, 20000); if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4)) break; } -- GitLab From 829a5071ccf040b78bd93286a218580c66833b00 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sat, 1 Jun 2013 23:02:26 +0000 Subject: [PATCH 0583/2900] bnx2x: fix a power state test If PCIe supports PM capabilities, bnx2x will always claim eeprom is accessible as PCI_D0 is zero. Reported-by: Dan Carpenter Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 72b1b59294b4..7c6faebb1838 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1390,7 +1390,8 @@ static bool bnx2x_is_nvm_accessible(struct bnx2x *bp) rc = pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pm); - if ((rc && !netif_running(dev)) || (!rc && ((pm & PCI_D0) != PCI_D0))) + if ((rc && !netif_running(dev)) || + (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != PCI_D0))) return false; return true; -- GitLab From 387aa65a89434abe3128d36d1a6fc3842c94905d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 27 May 2013 20:46:31 +0000 Subject: [PATCH 0584/2900] ipv4: properly refresh rtable entries on pmtu/redirect events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 05ab86c5 (xfrm4: Invalidate all ipv4 routes on IPsec pmtu events). Flushing all cached entries is not needed. Instead, invalidate only the related next hop dsts to recheck for the added next hop exception where needed. This also fixes a subtle race due to bumping generation id's before updating the pmtu. Cc: Steffen Klassert Signed-off-by: Timo Teräs Signed-off-by: David S. Miller --- net/ipv4/ah4.c | 7 ++---- net/ipv4/esp4.c | 7 ++---- net/ipv4/ipcomp.c | 7 ++---- net/ipv4/route.c | 63 ++++++++++++++++++++++++++++------------------- 4 files changed, 43 insertions(+), 41 deletions(-) diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 2e7f1948216f..717902669d2f 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -419,12 +419,9 @@ static void ah4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { - atomic_inc(&flow_cache_genid); - rt_genid_bump(net); - + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); - } else + else ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); xfrm_state_put(x); } diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4cfe34d4cc96..ab3d814bc80a 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -502,12 +502,9 @@ static void esp4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { - atomic_inc(&flow_cache_genid); - rt_genid_bump(net); - + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); - } else + else ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); xfrm_state_put(x); } diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 59cb8c769056..826be4cb482a 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -47,12 +47,9 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) if (!x) return; - if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { - atomic_inc(&flow_cache_genid); - rt_genid_bump(net); - + if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); - } else + else ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); xfrm_state_put(x); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 550781a17b34..561a37833d86 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -594,11 +594,25 @@ static inline u32 fnhe_hashfun(__be32 daddr) return hval & (FNHE_HASH_SIZE - 1); } +static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe) +{ + rt->rt_pmtu = fnhe->fnhe_pmtu; + rt->dst.expires = fnhe->fnhe_expires; + + if (fnhe->fnhe_gw) { + rt->rt_flags |= RTCF_REDIRECTED; + rt->rt_gateway = fnhe->fnhe_gw; + rt->rt_uses_gateway = 1; + } +} + static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, u32 pmtu, unsigned long expires) { struct fnhe_hash_bucket *hash; struct fib_nh_exception *fnhe; + struct rtable *rt; + unsigned int i; int depth; u32 hval = fnhe_hashfun(daddr); @@ -627,8 +641,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_gw = gw; if (pmtu) { fnhe->fnhe_pmtu = pmtu; - fnhe->fnhe_expires = expires; + fnhe->fnhe_expires = max(1UL, expires); } + /* Update all cached dsts too */ + rt = rcu_dereference(fnhe->fnhe_rth); + if (rt) + fill_route_from_fnhe(rt, fnhe); } else { if (depth > FNHE_RECLAIM_DEPTH) fnhe = fnhe_oldest(hash); @@ -644,6 +662,18 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_gw = gw; fnhe->fnhe_pmtu = pmtu; fnhe->fnhe_expires = expires; + + /* Exception created; mark the cached routes for the nexthop + * stale, so anyone caching it rechecks if this exception + * applies to them. + */ + for_each_possible_cpu(i) { + struct rtable __rcu **prt; + prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i); + rt = rcu_dereference(*prt); + if (rt) + rt->dst.obsolete = DST_OBSOLETE_KILL; + } } fnhe->fnhe_stamp = jiffies; @@ -917,13 +947,6 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; - if (!rt->rt_pmtu) { - dst->obsolete = DST_OBSOLETE_KILL; - } else { - rt->rt_pmtu = mtu; - dst->expires = max(1UL, jiffies + ip_rt_mtu_expires); - } - rcu_read_lock(); if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); @@ -1063,11 +1086,11 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) * DST_OBSOLETE_FORCE_CHK which forces validation calls down * into this function always. * - * When a PMTU/redirect information update invalidates a - * route, this is indicated by setting obsolete to - * DST_OBSOLETE_KILL. + * When a PMTU/redirect information update invalidates a route, + * this is indicated by setting obsolete to DST_OBSOLETE_KILL or + * DST_OBSOLETE_DEAD by dst_free(). */ - if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt)) + if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt)) return NULL; return dst; } @@ -1215,20 +1238,8 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, fnhe->fnhe_pmtu = 0; fnhe->fnhe_expires = 0; } - if (fnhe->fnhe_pmtu) { - unsigned long expires = fnhe->fnhe_expires; - unsigned long diff = expires - jiffies; - - if (time_before(jiffies, expires)) { - rt->rt_pmtu = fnhe->fnhe_pmtu; - dst_set_expires(&rt->dst, diff); - } - } - if (fnhe->fnhe_gw) { - rt->rt_flags |= RTCF_REDIRECTED; - rt->rt_gateway = fnhe->fnhe_gw; - rt->rt_uses_gateway = 1; - } else if (!rt->rt_gateway) + fill_route_from_fnhe(rt, fnhe); + if (!rt->rt_gateway) rt->rt_gateway = daddr; rcu_assign_pointer(fnhe->fnhe_rth, rt); -- GitLab From f016229e303c294afac721de4cd4427e634950ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 27 May 2013 20:46:32 +0000 Subject: [PATCH 0585/2900] ipv4: rate limit updating of next hop exceptions with same pmtu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tunnel devices call update_pmtu for each packet sent, this causes contention on the fnhe_lock. Ignore the pmtu update if pmtu is not actually changed, and there is still plenty of time before the entry expires. Signed-off-by: Timo Teräs Signed-off-by: David S. Miller --- net/ipv4/route.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 561a37833d86..a4082be1b9b4 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -947,6 +947,10 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) if (mtu < ip_rt_min_pmtu) mtu = ip_rt_min_pmtu; + if (rt->rt_pmtu == mtu && + time_before(jiffies, dst->expires - ip_rt_mtu_expires / 2)) + return; + rcu_read_lock(); if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { struct fib_nh *nh = &FIB_RES_NH(res); -- GitLab From 5aad1de5ea2c260b4cd2f70b70e146d55dbbc528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 27 May 2013 20:46:33 +0000 Subject: [PATCH 0586/2900] ipv4: use separate genid for next hop exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 13d82bf5 (ipv4: Fix flushing of cached routing informations) added the support to flush learned pmtu information. However, using rt_genid is quite heavy as it is bumped on route add/change and multicast events amongst other places. These can happen quite often, especially if using dynamic routing protocols. While this is ok with routes (as they are just recreated locally), the pmtu information is learned from remote systems and the icmp notification can come with long delays. It is worthy to have separate genid to avoid excessive pmtu resets. Cc: Steffen Klassert Signed-off-by: Timo Teräs Signed-off-by: David S. Miller --- include/net/ip_fib.h | 1 + include/net/net_namespace.h | 11 +++++++++++ net/ipv4/route.c | 12 ++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e49db91593a9..44424e9dab2a 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -51,6 +51,7 @@ struct rtable; struct fib_nh_exception { struct fib_nh_exception __rcu *fnhe_next; + int fnhe_genid; __be32 fnhe_daddr; u32 fnhe_pmtu; __be32 fnhe_gw; diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index b17697827482..495bc57f292c 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -118,6 +118,7 @@ struct net { struct netns_ipvs *ipvs; struct sock *diag_nlsk; atomic_t rt_genid; + atomic_t fnhe_genid; }; /* @@ -340,4 +341,14 @@ static inline void rt_genid_bump(struct net *net) atomic_inc(&net->rt_genid); } +static inline int fnhe_genid(struct net *net) +{ + return atomic_read(&net->fnhe_genid); +} + +static inline void fnhe_genid_bump(struct net *net) +{ + atomic_inc(&net->fnhe_genid); +} + #endif /* __NET_NET_NAMESPACE_H */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index a4082be1b9b4..403e28302869 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -658,6 +658,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_next = hash->chain; rcu_assign_pointer(hash->chain, fnhe); } + fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev)); fnhe->fnhe_daddr = daddr; fnhe->fnhe_gw = gw; fnhe->fnhe_pmtu = pmtu; @@ -1236,8 +1237,11 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { + int genid = fnhe_genid(dev_net(rt->dst.dev)); struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); - if (orig && rt_is_expired(orig)) { + + if (fnhe->fnhe_genid != genid) { + fnhe->fnhe_genid = genid; fnhe->fnhe_gw = 0; fnhe->fnhe_pmtu = 0; fnhe->fnhe_expires = 0; @@ -2443,8 +2447,11 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { + struct net *net = (struct net *)__ctl->extra1; + if (write) { - rt_cache_flush((struct net *)__ctl->extra1); + rt_cache_flush(net); + fnhe_genid_bump(net); return 0; } @@ -2619,6 +2626,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = { static __net_init int rt_genid_init(struct net *net) { atomic_set(&net->rt_genid, 0); + atomic_set(&net->fnhe_genid, 0); get_random_bytes(&net->ipv4.dev_addr_genid, sizeof(net->ipv4.dev_addr_genid)); return 0; -- GitLab From bd118b6e9509a19bfb82925152d9ae8fa398d567 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 29 May 2013 04:13:54 +0000 Subject: [PATCH 0587/2900] ibm-ethernet: delete stale MCA and duplicate PSERIES dependency MCA support has been removed but this dependency escaped removal. Also, there is a duplicate PPC_PSERIES dependency that appeared when the ethernet drivers were separated into vendor/model specific directories, so we remove that here as well. Reported-by: Robert de Rooy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig index 6529d31595a7..563a1ac71dbc 100644 --- a/drivers/net/ethernet/ibm/Kconfig +++ b/drivers/net/ethernet/ibm/Kconfig @@ -5,8 +5,7 @@ config NET_VENDOR_IBM bool "IBM devices" default y - depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \ - (IBMEBUS && SPARSEMEM) + depends on PPC_PSERIES || PPC_DCR || (IBMEBUS && SPARSEMEM) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from -- GitLab From 08578d8d4eb76b7afe314fa03abe167761462fe4 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 3 Jun 2013 00:23:25 +0000 Subject: [PATCH 0588/2900] ] icmp: fix icmp_unreach() comment. ICMP_PARAMETERPROB is handled by icmp_unreach(); This patch adds ICMP_PARAMETERPROB to the list of ICMP message types handled by icmp_unreach(). Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 5d0d379b0152..2864ca33bedc 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -658,7 +658,8 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) } /* - * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH. + * Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and + * ICMP_PARAMETERPROB. */ static void icmp_unreach(struct sk_buff *skb) -- GitLab From 9a99d4a50cb8ce516adf0f2436138d4c8e6e4535 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 2 Jun 2013 15:00:52 +0000 Subject: [PATCH 0589/2900] icmp: avoid allocating large struct on stack struct icmp_bxm is a large struct, reduce stack usage by allocating it on heap. Cc: Eric Dumazet Cc: Joe Perches Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 2864ca33bedc..5f7d11a45871 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -482,7 +482,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) { struct iphdr *iph; int room; - struct icmp_bxm icmp_param; + struct icmp_bxm *icmp_param; struct rtable *rt = skb_rtable(skb_in); struct ipcm_cookie ipc; struct flowi4 fl4; @@ -558,9 +558,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } } + icmp_param = kmalloc(sizeof(*icmp_param), GFP_ATOMIC); + if (!icmp_param) + return; + sk = icmp_xmit_lock(net); if (sk == NULL) - return; + goto out_free; /* * Construct source address and options. @@ -586,7 +590,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) IPTOS_PREC_INTERNETCONTROL) : iph->tos; - if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in)) + if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb_in)) goto out_unlock; @@ -594,19 +598,19 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) * Prepare data for ICMP header. */ - icmp_param.data.icmph.type = type; - icmp_param.data.icmph.code = code; - icmp_param.data.icmph.un.gateway = info; - icmp_param.data.icmph.checksum = 0; - icmp_param.skb = skb_in; - icmp_param.offset = skb_network_offset(skb_in); + icmp_param->data.icmph.type = type; + icmp_param->data.icmph.code = code; + icmp_param->data.icmph.un.gateway = info; + icmp_param->data.icmph.checksum = 0; + icmp_param->skb = skb_in; + icmp_param->offset = skb_network_offset(skb_in); inet_sk(sk)->tos = tos; ipc.addr = iph->saddr; - ipc.opt = &icmp_param.replyopts.opt; + ipc.opt = &icmp_param->replyopts.opt; ipc.tx_flags = 0; rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, - type, code, &icmp_param); + type, code, icmp_param); if (IS_ERR(rt)) goto out_unlock; @@ -618,19 +622,21 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) room = dst_mtu(&rt->dst); if (room > 576) room = 576; - room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; + room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.opt.optlen; room -= sizeof(struct icmphdr); - icmp_param.data_len = skb_in->len - icmp_param.offset; - if (icmp_param.data_len > room) - icmp_param.data_len = room; - icmp_param.head_len = sizeof(struct icmphdr); + icmp_param->data_len = skb_in->len - icmp_param->offset; + if (icmp_param->data_len > room) + icmp_param->data_len = room; + icmp_param->head_len = sizeof(struct icmphdr); - icmp_push_reply(&icmp_param, &fl4, &ipc, &rt); + icmp_push_reply(icmp_param, &fl4, &ipc, &rt); ende: ip_rt_put(rt); out_unlock: icmp_xmit_unlock(sk); +out_free: + kfree(icmp_param); out:; } EXPORT_SYMBOL(icmp_send); -- GitLab From 0672f0ab57dc71958542ac41e5a7ccb6a382a8f3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 31 May 2013 21:18:55 +0000 Subject: [PATCH 0590/2900] net: can: replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/can/at91_can.c | 2 +- drivers/net/can/janz-ican3.c | 2 +- drivers/net/can/slcan.c | 2 +- drivers/net/can/softing/softing_main.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 556656661d6b..ce8421ac453a 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1220,7 +1220,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev, goto out; } - err = strict_strtoul(buf, 0, &can_id); + err = kstrtoul(buf, 0, &can_id); if (err) { ret = err; goto out; diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index c4bc1d2e2033..36bd6fa1c7f3 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1734,7 +1734,7 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, unsigned long enable; int ret; - if (strict_strtoul(buf, 0, &enable)) + if (kstrtoul(buf, 0, &enable)) return -EINVAL; ret = ican3_set_termination(mod, enable); diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 06b7e097d36e..874188ba06f7 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -161,7 +161,7 @@ static void slc_bump(struct slcan *sl) sl->rbuff[dlc_pos] = 0; /* terminate can_id string */ - if (strict_strtoul(sl->rbuff+1, 16, &ultmp)) + if (kstrtoul(sl->rbuff+1, 16, &ultmp)) return; cf.can_id = ultmp; diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 3a2b45601ec2..65eef1eea2e2 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -594,7 +594,7 @@ static ssize_t store_output(struct device *dev, struct device_attribute *attr, unsigned long val; int ret; - ret = strict_strtoul(buf, 0, &val); + ret = kstrtoul(buf, 0, &val); if (ret < 0) return ret; val &= 0xFF; -- GitLab From 67d6bfa6863c8535445e1dcdb3385e3a05cd32a7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 31 May 2013 21:21:35 +0000 Subject: [PATCH 0591/2900] net: ethernet: replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 ++-- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 20c7b3c12b56..c401b0b4353d 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -2774,7 +2774,7 @@ netxen_store_bridged_mode(struct device *dev, if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) goto err_out; - if (strict_strtoul(buf, 2, &new)) + if (kstrtoul(buf, 2, &new)) goto err_out; if (!netxen_config_bridged_mode(adapter, !!new)) @@ -2813,7 +2813,7 @@ netxen_store_diag_mode(struct device *dev, struct netxen_adapter *adapter = dev_get_drvdata(dev); unsigned long new; - if (strict_strtoul(buf, 2, &new)) + if (kstrtoul(buf, 2, &new)) return -EINVAL; if (!!new != !!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 025a7192289d..7ec030abdf07 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -47,7 +47,7 @@ static ssize_t qlcnic_store_bridged_mode(struct device *dev, if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) goto err_out; - if (strict_strtoul(buf, 2, &new)) + if (kstrtoul(buf, 2, &new)) goto err_out; if (!qlcnic_config_bridged_mode(adapter, !!new)) @@ -77,7 +77,7 @@ static ssize_t qlcnic_store_diag_mode(struct device *dev, struct qlcnic_adapter *adapter = dev_get_drvdata(dev); unsigned long new; - if (strict_strtoul(buf, 2, &new)) + if (kstrtoul(buf, 2, &new)) return -EINVAL; if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) -- GitLab From 27d7f47756f40fb1bc3159e09217f740f5c5b5b1 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 31 May 2013 21:24:06 +0000 Subject: [PATCH 0592/2900] net: wireless: replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/net/wireless/ath/ath9k/debug.c | 14 +++++++------- drivers/net/wireless/ath/ath9k/dfs_debug.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_debug.c | 2 +- drivers/net/wireless/iwlegacy/3945-mac.c | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 4 ++-- drivers/net/wireless/libertas/mesh.c | 2 +- drivers/net/wireless/rtlwifi/base.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index b37eb8d38811..51cc0fa5cd3e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -69,7 +69,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) + if (kstrtoul(buf, 0, &mask)) return -EINVAL; common->debug_mask = mask; @@ -114,7 +114,7 @@ static ssize_t write_file_tx_chainmask(struct file *file, const char __user *use return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) + if (kstrtoul(buf, 0, &mask)) return -EINVAL; ah->txchainmask = mask; @@ -157,7 +157,7 @@ static ssize_t write_file_rx_chainmask(struct file *file, const char __user *use return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) + if (kstrtoul(buf, 0, &mask)) return -EINVAL; ah->rxchainmask = mask; @@ -200,7 +200,7 @@ static ssize_t write_file_disable_ani(struct file *file, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &disable_ani)) + if (kstrtoul(buf, 0, &disable_ani)) return -EINVAL; common->disable_ani = !!disable_ani; @@ -253,7 +253,7 @@ static ssize_t write_file_ant_diversity(struct file *file, goto exit; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &antenna_diversity)) + if (kstrtoul(buf, 0, &antenna_diversity)) return -EINVAL; common->antenna_diversity = !!antenna_diversity; @@ -1278,7 +1278,7 @@ static ssize_t write_file_regidx(struct file *file, const char __user *user_buf, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, ®idx)) + if (kstrtoul(buf, 0, ®idx)) return -EINVAL; sc->debug.regidx = regidx; @@ -1323,7 +1323,7 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, ®val)) + if (kstrtoul(buf, 0, ®val)) return -EINVAL; ath9k_ps_wakeup(sc); diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c index b7611b7bbe43..3c6e4138a95d 100644 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c @@ -96,7 +96,7 @@ static ssize_t write_file_dfs(struct file *file, const char __user *user_buf, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &val)) + if (kstrtoul(buf, 0, &val)) return -EINVAL; if (val == DFS_STATS_RESET_MAGIC) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 87110de577ef..d08ef24e9696 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -471,7 +471,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) + if (kstrtoul(buf, 0, &mask)) return -EINVAL; common->debug_mask = mask; diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b37a582ccbe7..dce5e8f030b2 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3119,7 +3119,7 @@ il3945_store_debug_level(struct device *d, struct device_attribute *attr, unsigned long val; int ret; - ret = strict_strtoul(buf, 0, &val); + ret = kstrtoul(buf, 0, &val); if (ret) IL_INFO("%s is not in hex or decimal form.\n", buf); else diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 9a95045c97b6..3c4899b7c1ab 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -4567,7 +4567,7 @@ il4965_store_debug_level(struct device *d, struct device_attribute *attr, unsigned long val; int ret; - ret = strict_strtoul(buf, 0, &val); + ret = kstrtoul(buf, 0, &val); if (ret) IL_ERR("%s is not in hex or decimal form.\n", buf); else @@ -4614,7 +4614,7 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr, unsigned long val; int ret; - ret = strict_strtoul(buf, 10, &val); + ret = kstrtoul(buf, 10, &val); if (ret) IL_INFO("%s is not in decimal form.\n", buf); else { diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 3e81264db81e..efae07e05c80 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -240,7 +240,7 @@ static ssize_t lbs_prb_rsp_limit_set(struct device *dev, memset(&mesh_access, 0, sizeof(mesh_access)); mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); - if (!strict_strtoul(buf, 10, &retry_limit)) + if (!kstrtoul(buf, 10, &retry_limit)) return -ENOTSUPP; if (retry_limit > 15) return -ENOTSUPP; diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index af59dd5718e1..8053f775d392 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1817,7 +1817,7 @@ static ssize_t rtl_store_debug_level(struct device *d, unsigned long val; int ret; - ret = strict_strtoul(buf, 0, &val); + ret = kstrtoul(buf, 0, &val); if (ret) { printk(KERN_DEBUG "%s is not in hex or decimal form.\n", buf); } else { -- GitLab From 6b1ea4b299ca19a7a2713b38366ac2829fe55883 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 31 May 2013 21:35:23 +0000 Subject: [PATCH 0593/2900] ssb: sprom: replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Signed-off-by: David S. Miller --- drivers/ssb/sprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index a3b23644b0fb..e753fbe302a7 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c @@ -54,7 +54,7 @@ static int hex2sprom(u16 *sprom, const char *dump, size_t len, while (cnt < sprom_size_words) { memcpy(tmp, dump, 4); dump += 4; - err = strict_strtoul(tmp, 16, &parsed); + err = kstrtoul(tmp, 16, &parsed); if (err) return err; sprom[cnt++] = swab16((u16)parsed); -- GitLab From 5865fc1b6a99bc7dcf245770c2735577b8596b6e Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Sun, 2 Jun 2013 21:36:21 +0000 Subject: [PATCH 0594/2900] tg3: remove redundant pm init code Pci_enable_device() will set device pm state to D0, so it's no need to do it again in tg3_init_one(). Acked-by: Michael Chan Signed-off-by: Yijing Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index d7755d849e53..3cfae0e49207 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17195,7 +17195,7 @@ static int tg3_init_one(struct pci_dev *pdev, { struct net_device *dev; struct tg3 *tp; - int i, err, pm_cap; + int i, err; u32 sndmbx, rcvmbx, intmbx; char str[40]; u64 dma_mask, persist_dma_mask; @@ -17217,25 +17217,10 @@ static int tg3_init_one(struct pci_dev *pdev, pci_set_master(pdev); - /* Find power-management capability. */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap == 0) { - dev_err(&pdev->dev, - "Cannot find Power Management capability, aborting\n"); - err = -EIO; - goto err_out_free_res; - } - - err = pci_set_power_state(pdev, PCI_D0); - if (err) { - dev_err(&pdev->dev, "Transition to D0 failed, aborting\n"); - goto err_out_free_res; - } - dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS); if (!dev) { err = -ENOMEM; - goto err_out_power_down; + goto err_out_free_res; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -17243,7 +17228,7 @@ static int tg3_init_one(struct pci_dev *pdev, tp = netdev_priv(dev); tp->pdev = pdev; tp->dev = dev; - tp->pm_cap = pm_cap; + tp->pm_cap = pdev->pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; tp->irq_sync = 1; @@ -17581,9 +17566,6 @@ static int tg3_init_one(struct pci_dev *pdev, err_out_free_dev: free_netdev(dev); -err_out_power_down: - pci_set_power_state(pdev, PCI_D3hot); - err_out_free_res: pci_release_regions(pdev); -- GitLab From 4d7f7635f75da2924916946cb7ac49c5603b44c7 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 20 May 2013 10:06:18 -0300 Subject: [PATCH 0595/2900] can: flexcan: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core) we can rely on device core for handling pinctrl, so remove devm_pinctrl_get_select_default() from the driver. Cc: Marc Kleine-Budde Cc: Signed-off-by: Fabio Estevam Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 4a40a186c8c8..a93cdb29fb3f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -37,7 +37,6 @@ #include #include #include -#include #define DRV_NAME "flexcan" @@ -1004,16 +1003,11 @@ static int flexcan_probe(struct platform_device *pdev) struct flexcan_priv *priv; struct resource *mem; struct clk *clk_ipg = NULL, *clk_per = NULL; - struct pinctrl *pinctrl; void __iomem *base; resource_size_t mem_size; int err, irq; u32 clock_freq = 0; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - return PTR_ERR(pinctrl); - if (pdev->dev.of_node) of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_freq); -- GitLab From 588e7a8e123da07b6ffe87f156e25afc1c3d7cce Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 20 May 2013 15:43:43 -0300 Subject: [PATCH 0596/2900] can: flexcan: Use SIMPLE_DEV_PM_OPS Using SIMPLE_DEV_PM_OPS can make the code smaller and simpler. Also change CONFIG_PM to CONFIG_PM_SLEEP. Signed-off-by: Fabio Estevam Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index a93cdb29fb3f..f873b9f8d4d4 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1131,10 +1131,10 @@ static int flexcan_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int flexcan_suspend(struct platform_device *pdev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int flexcan_suspend(struct device *device) { - struct net_device *dev = platform_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); flexcan_chip_disable(priv); @@ -1148,9 +1148,9 @@ static int flexcan_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int flexcan_resume(struct platform_device *pdev) +static int flexcan_resume(struct device *device) { - struct net_device *dev = platform_get_drvdata(pdev); + struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); priv->can.state = CAN_STATE_ERROR_ACTIVE; @@ -1162,21 +1162,19 @@ static int flexcan_resume(struct platform_device *pdev) return 0; } -#else -#define flexcan_suspend NULL -#define flexcan_resume NULL -#endif +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume); static struct platform_driver flexcan_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .pm = &flexcan_pm_ops, .of_match_table = flexcan_of_match, }, .probe = flexcan_probe, .remove = flexcan_remove, - .suspend = flexcan_suspend, - .resume = flexcan_resume, .id_table = flexcan_id_table, }; -- GitLab From 4c4726faed6cf0c7545ac6523de4cc66acd0a61d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 15 May 2013 09:32:36 +0200 Subject: [PATCH 0597/2900] can: flexcan: remove HAVE_CAN_FLEXCAN Kconfig symbol This patch removes the Kconfig symbol HAVE_CAN_FLEXCAN from arch/{arm,powerpc} and allowing compilation unconditionally on all arm and powerpc platforms. This brings a bigger compile time coverage and removes the following dependency warning found by Arnd Bergmann: warning: (SOC_IMX28 && SOC_IMX25 && SOC_IMX35 && IMX_HAVE_PLATFORM_FLEXCAN && SOC_IMX53 && SOC_IMX6Q) selects HAVE_CAN_FLEXCAN which has unmet direct dependencies (NET && CAN && CAN_DEV) Acked-by: Arnd Bergmann Acked-by: Benjamin Herrenschmidt Acked-by: Shawn Guo Signed-off-by: Marc Kleine-Budde --- arch/arm/mach-imx/Kconfig | 4 ---- arch/arm/mach-imx/devices/Kconfig | 1 - arch/arm/mach-mxs/Kconfig | 1 - arch/powerpc/Kconfig | 1 - drivers/net/can/Kconfig | 5 +---- 5 files changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index ba44328464f3..af8e109953d1 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -111,7 +111,6 @@ config SOC_IMX25 select ARCH_MXC_IOMUX_V3 select COMMON_CLK select CPU_ARM926T - select HAVE_CAN_FLEXCAN if CAN select MXC_AVIC config SOC_IMX27 @@ -137,7 +136,6 @@ config SOC_IMX35 select ARCH_MXC_IOMUX_V3 select COMMON_CLK select CPU_V6K - select HAVE_CAN_FLEXCAN if CAN select HAVE_EPIT select MXC_AVIC select SMP_ON_UP if SMP @@ -776,7 +774,6 @@ comment "Device tree only" config SOC_IMX53 bool "i.MX53 support" - select HAVE_CAN_FLEXCAN if CAN select HAVE_IMX_SRC select IMX_HAVE_PLATFORM_IMX2_WDT select PINCTRL @@ -799,7 +796,6 @@ config SOC_IMX6Q select CPU_V7 select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if LOCAL_TIMERS - select HAVE_CAN_FLEXCAN if CAN select HAVE_IMX_ANATOP select HAVE_IMX_GPC select HAVE_IMX_MMDC diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig index 3dd2b1b041d1..68c74fb0373c 100644 --- a/arch/arm/mach-imx/devices/Kconfig +++ b/arch/arm/mach-imx/devices/Kconfig @@ -4,7 +4,6 @@ config IMX_HAVE_PLATFORM_FEC config IMX_HAVE_PLATFORM_FLEXCAN bool - select HAVE_CAN_FLEXCAN if CAN config IMX_HAVE_PLATFORM_FSL_USB2_UDC bool diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index 4dc2fbba0ecd..ce6e7d606a7c 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -11,7 +11,6 @@ config SOC_IMX28 select ARM_AMBA select ARM_CPU_SUSPEND if PM select CPU_ARM926T - select HAVE_CAN_FLEXCAN if CAN select HAVE_PWM select PINCTRL_IMX28 diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c33e3ad2c8fd..7754c6b8c453 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -674,7 +674,6 @@ config SBUS config FSL_SOC bool - select HAVE_CAN_FLEXCAN if NET && CAN config FSL_PCI bool diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index e456b70933c2..3c069472eb8b 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -102,12 +102,9 @@ config CAN_JANZ_ICAN3 This driver can also be built as a module. If so, the module will be called janz-ican3.ko. -config HAVE_CAN_FLEXCAN - bool - config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" - depends on HAVE_CAN_FLEXCAN + depends on ARM || PPC ---help--- Say Y here if you want to support for Freescale FlexCAN. -- GitLab From 00e4bbc8cd7efac66caa4ce6bcf5f02e944184f6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:47:58 +0900 Subject: [PATCH 0598/2900] net: can: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Also, unnecessary dev_set_drvdata() is removed, because the driver core clears the driver data to NULL after device_release or on probe failure. Signed-off-by: Jingoo Han Signed-off-by: Marc Kleine-Budde --- drivers/net/can/bfin_can.c | 10 ++++------ drivers/net/can/cc770/cc770_isa.c | 5 ++--- drivers/net/can/cc770/cc770_platform.c | 4 ++-- drivers/net/can/grcan.c | 5 ++--- drivers/net/can/mscan/mpc5xxx_can.c | 10 ++++------ drivers/net/can/sja1000/sja1000_isa.c | 5 ++--- drivers/net/can/sja1000/sja1000_of_platform.c | 6 ++---- drivers/net/can/sja1000/sja1000_platform.c | 5 ++--- 8 files changed, 20 insertions(+), 30 deletions(-) diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index d4a15e82bfc0..a2700d25ff0e 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -580,7 +580,7 @@ static int bfin_can_probe(struct platform_device *pdev) priv->pin_list = pdata; priv->can.clock.freq = get_sclk(); - dev_set_drvdata(&pdev->dev, dev); + platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); dev->flags |= IFF_ECHO; /* we support local echo */ @@ -613,7 +613,7 @@ static int bfin_can_probe(struct platform_device *pdev) static int bfin_can_remove(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct bfin_can_priv *priv = netdev_priv(dev); struct resource *res; @@ -621,8 +621,6 @@ static int bfin_can_remove(struct platform_device *pdev) unregister_candev(dev); - dev_set_drvdata(&pdev->dev, NULL); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); @@ -635,7 +633,7 @@ static int bfin_can_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct bfin_can_priv *priv = netdev_priv(dev); struct bfin_can_regs __iomem *reg = priv->membase; int timeout = BFIN_CAN_TIMEOUT; @@ -658,7 +656,7 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg) static int bfin_can_resume(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct bfin_can_priv *priv = netdev_priv(dev); struct bfin_can_regs __iomem *reg = priv->membase; diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c index 8eaaac81f320..87a47c0cfd49 100644 --- a/drivers/net/can/cc770/cc770_isa.c +++ b/drivers/net/can/cc770/cc770_isa.c @@ -265,7 +265,7 @@ static int cc770_isa_probe(struct platform_device *pdev) else priv->clkout = COR_DEFAULT; - dev_set_drvdata(&pdev->dev, dev); + platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); err = register_cc770dev(dev); @@ -293,12 +293,11 @@ static int cc770_isa_probe(struct platform_device *pdev) static int cc770_isa_remove(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); int idx = pdev->id; unregister_cc770dev(dev); - dev_set_drvdata(&pdev->dev, NULL); if (mem[idx]) { iounmap(priv->reg_base); diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index d0f6bfc45aea..034bdd816a60 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -216,7 +216,7 @@ static int cc770_platform_probe(struct platform_device *pdev) priv->reg_base, dev->irq, priv->can.clock.freq, priv->cpu_interface, priv->bus_config, priv->clkout); - dev_set_drvdata(&pdev->dev, dev); + platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); err = register_cc770dev(dev); @@ -240,7 +240,7 @@ static int cc770_platform_probe(struct platform_device *pdev) static int cc770_platform_remove(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); struct resource *mem; diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 9e9d0d628e7b..6aa737a24393 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1646,7 +1646,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev, if (err) goto exit_free_candev; - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); /* Reset device to allow bit-timing to be set. No need to call * grcan_reset at this stage. That is done in grcan_open. @@ -1715,13 +1715,12 @@ static int grcan_probe(struct platform_device *ofdev) static int grcan_remove(struct platform_device *ofdev) { - struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct net_device *dev = platform_get_drvdata(ofdev); struct grcan_priv *priv = netdev_priv(dev); unregister_candev(dev); /* Will in turn call grcan_close */ irq_dispose_mapping(dev->irq); - dev_set_drvdata(&ofdev->dev, NULL); netif_napi_del(&priv->napi); free_candev(dev); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 668850e441dc..5b0ee8ef5885 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -302,7 +302,7 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) goto exit_free_mscan; } - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", priv->reg_base, dev->irq, priv->can.clock.freq); @@ -321,11 +321,9 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) static int mpc5xxx_can_remove(struct platform_device *ofdev) { - struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct net_device *dev = platform_get_drvdata(ofdev); struct mscan_priv *priv = netdev_priv(dev); - dev_set_drvdata(&ofdev->dev, NULL); - unregister_mscandev(dev); iounmap(priv->reg_base); irq_dispose_mapping(dev->irq); @@ -338,7 +336,7 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev) static struct mscan_regs saved_regs; static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state) { - struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct net_device *dev = platform_get_drvdata(ofdev); struct mscan_priv *priv = netdev_priv(dev); struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; @@ -349,7 +347,7 @@ static int mpc5xxx_can_suspend(struct platform_device *ofdev, pm_message_t state static int mpc5xxx_can_resume(struct platform_device *ofdev) { - struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct net_device *dev = platform_get_drvdata(ofdev); struct mscan_priv *priv = netdev_priv(dev); struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 5c8da4661489..06a282397fff 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -197,7 +197,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) else priv->cdr = CDR_DEFAULT; - dev_set_drvdata(&pdev->dev, dev); + platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); err = register_sja1000dev(dev); @@ -225,12 +225,11 @@ static int sja1000_isa_probe(struct platform_device *pdev) static int sja1000_isa_remove(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct sja1000_priv *priv = netdev_priv(dev); int idx = pdev->id; unregister_sja1000dev(dev); - dev_set_drvdata(&pdev->dev, NULL); if (mem[idx]) { iounmap(priv->reg_base); diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 8e0c4a001939..31ad33911167 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -72,13 +72,11 @@ static void sja1000_ofp_write_reg(const struct sja1000_priv *priv, static int sja1000_ofp_remove(struct platform_device *ofdev) { - struct net_device *dev = dev_get_drvdata(&ofdev->dev); + struct net_device *dev = platform_get_drvdata(ofdev); struct sja1000_priv *priv = netdev_priv(dev); struct device_node *np = ofdev->dev.of_node; struct resource res; - dev_set_drvdata(&ofdev->dev, NULL); - unregister_sja1000dev(dev); free_sja1000dev(dev); iounmap(priv->reg_base); @@ -181,7 +179,7 @@ static int sja1000_ofp_probe(struct platform_device *ofdev) priv->reg_base, dev->irq, priv->can.clock.freq, priv->ocr, priv->cdr); - dev_set_drvdata(&ofdev->dev, dev); + platform_set_drvdata(ofdev, dev); SET_NETDEV_DEV(dev, &ofdev->dev); err = register_sja1000dev(dev); diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 21619bb5b869..8e259c541036 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -135,7 +135,7 @@ static int sp_probe(struct platform_device *pdev) break; } - dev_set_drvdata(&pdev->dev, dev); + platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); err = register_sja1000dev(dev); @@ -161,12 +161,11 @@ static int sp_probe(struct platform_device *pdev) static int sp_remove(struct platform_device *pdev) { - struct net_device *dev = dev_get_drvdata(&pdev->dev); + struct net_device *dev = platform_get_drvdata(pdev); struct sja1000_priv *priv = netdev_priv(dev); struct resource *res; unregister_sja1000dev(dev); - dev_set_drvdata(&pdev->dev, NULL); if (priv->reg_base) iounmap(priv->reg_base); -- GitLab From ed405be5cb5e8e494e8dcd83b6eb1add34dc752a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 Jun 2013 13:51:59 +0200 Subject: [PATCH 0599/2900] mac80211: fix sdata locking around __ieee80211_request_smps My cfg80211/mac80211 locking unification broke the sdata locking in ieee80211_set_power_mgmt, it needs to acquire the lock for __ieee80211_request_smps(). Add the locking. Reported-by: Jakub Kicinski Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9034da16cf1b..30622101d3b5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2378,7 +2378,9 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, local->dynamic_ps_forced_timeout = timeout; /* no change, but if automatic follow powersave */ + sdata_lock(sdata); __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); + sdata_unlock(sdata); if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); -- GitLab From 866403a7bdd3941cbb4e2085d8ac368dcabe800c Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 31 May 2013 17:41:47 -0700 Subject: [PATCH 0600/2900] mac80211: don't check local mesh TTL on TX nl80211 has already verified the mesh TTL on setting the mesh config, so no need to check it again in mac80211. Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 34be9336b5d1..4105d0ca963e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1790,12 +1790,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, break; #ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT: - if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { - /* Do not send frames with mesh_ttl == 0 */ - sdata->u.mesh.mshstats.dropped_frames_ttl++; - goto fail_rcu; - } - if (!is_multicast_ether_addr(skb->data)) { struct sta_info *next_hop; bool mpp_lookup = true; -- GitLab From e05ecccdf752122a439b03c3190458d2c8f0bac6 Mon Sep 17 00:00:00 2001 From: Jacob Minshall Date: Wed, 29 May 2013 14:32:36 -0700 Subject: [PATCH 0601/2900] mac80211: set mesh formation field properly Cap max peerings at 63 in accordance with IEEE-2012 8.4.2.100.7. Triggers a beacon regeneration every time the number of peerings changes. Previously this would only happen if the "accepting peerings" bit changed. Signed-off-by: Jacob Minshall Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 1 + net/mac80211/mesh.c | 3 +-- net/mac80211/mesh.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d826e5a84af0..b0dc87a2a376 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -146,6 +146,7 @@ static inline u16 ieee80211_sn_sub(u16 sn1, u16 sn2) #define IEEE80211_MAX_RTS_THRESHOLD 2353 #define IEEE80211_MAX_AID 2007 #define IEEE80211_MAX_TIM_LEN 251 +#define IEEE80211_MAX_MESH_PEERINGS 63 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section 6.2.1.1.2. diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b3d1fdd46368..73a597bad6e0 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -274,8 +274,7 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, *pos++ = ifmsh->mesh_auth_id; /* Mesh Formation Info - number of neighbors */ neighbors = atomic_read(&ifmsh->estab_plinks); - /* Number of neighbor mesh STAs or 15 whichever is smaller */ - neighbors = (neighbors > 15) ? 15 : neighbors; + neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS); *pos++ = neighbors << 1; /* Mesh capability */ *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index da158774eebb..8b4d9a3e9eee 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -324,14 +324,14 @@ static inline u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_inc(&sdata->u.mesh.estab_plinks); - return mesh_accept_plinks_update(sdata); + return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON; } static inline u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_dec(&sdata->u.mesh.estab_plinks); - return mesh_accept_plinks_update(sdata); + return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON; } static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) -- GitLab From 964dc9e2c3aaccacacd40640964a58544fb5769a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 Jun 2013 17:25:34 +0200 Subject: [PATCH 0602/2900] cfg80211: take WoWLAN support information out of wiphy struct There's no need to take up the space for devices that don't support WoWLAN, and most drivers can even make the support data static const (except where it's modified at runtime.) Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 24 +++++---- drivers/net/wireless/ath/ath9k/init.c | 20 ++++---- drivers/net/wireless/iwlwifi/dvm/dev.h | 3 ++ drivers/net/wireless/iwlwifi/dvm/mac80211.c | 17 ++++--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 26 +++++----- drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/mwifiex/cfg80211.c | 16 ++++-- drivers/net/wireless/ti/wlcore/main.c | 19 ++++--- include/net/cfg80211.h | 2 +- net/mac80211/main.c | 3 +- net/wireless/core.c | 20 +++++--- net/wireless/nl80211.c | 56 ++++++++++----------- 12 files changed, 115 insertions(+), 92 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5c9736a94e54..f7995b2b12a4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3679,6 +3679,20 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, return NULL; } +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support ath6kl_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE, + .n_patterns = WOW_MAX_FILTERS_PER_LIST, + .pattern_min_len = 1, + .pattern_max_len = WOW_PATTERN_SIZE, +}; +#endif + int ath6kl_cfg80211_init(struct ath6kl *ar) { struct wiphy *wiphy = ar->wiphy; @@ -3772,15 +3786,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); #ifdef CONFIG_PM - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | - WIPHY_WOWLAN_EAP_IDENTITY_REQ | - WIPHY_WOWLAN_4WAY_HANDSHAKE; - wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; - wiphy->wowlan.pattern_min_len = 1; - wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; + wiphy->wowlan = &ath6kl_wowlan_support; #endif wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0237b2868961..f993362e9e13 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -755,6 +755,15 @@ static const struct ieee80211_iface_combination if_comb[] = { } }; +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support ath9k_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, + .n_patterns = MAX_NUM_USER_PATTERN, + .pattern_min_len = 1, + .pattern_max_len = MAX_PATTERN_SIZE, +}; +#endif + void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; @@ -797,15 +806,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) #ifdef CONFIG_PM_SLEEP if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && - device_can_wakeup(sc->dev)) { - - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT; - hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN; - hw->wiphy->wowlan.pattern_min_len = 1; - hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE; - - } + device_can_wakeup(sc->dev)) + hw->wiphy->wowlan = &ath9k_wowlan_support; atomic_set(&sc->wow_sleep_proc_intr, -1); atomic_set(&sc->wow_got_bmiss_intr, -1); diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index 71ea77576d22..e71acfd344aa 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -870,6 +870,9 @@ struct iwl_priv { __le64 replay_ctr; __le16 last_seq_ctl; bool have_rekey_data; +#ifdef CONFIG_PM_SLEEP + struct wiphy_wowlan_support wowlan_support; +#endif /* device_pointers: pointers to ucode event tables */ struct { diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cab23af0be9e..661b5e71aac8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -208,20 +208,21 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, priv->trans->ops->d3_suspend && priv->trans->ops->d3_resume && device_can_wakeup(priv->trans->dev)) { - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_EAP_IDENTITY_REQ | - WIPHY_WOWLAN_RFKILL_RELEASE; + priv->wowlan_support.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_RFKILL_RELEASE; if (!iwlwifi_mod_params.sw_crypto) - hw->wiphy->wowlan.flags |= + priv->wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | WIPHY_WOWLAN_GTK_REKEY_FAILURE; - hw->wiphy->wowlan.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; - hw->wiphy->wowlan.pattern_min_len = + priv->wowlan_support.n_patterns = IWLAGN_WOWLAN_MAX_PATTERNS; + priv->wowlan_support.pattern_min_len = IWLAGN_WOWLAN_MIN_PATTERN_LEN; - hw->wiphy->wowlan.pattern_max_len = + priv->wowlan_support.pattern_max_len = IWLAGN_WOWLAN_MAX_PATTERN_LEN; + hw->wiphy->wowlan = &priv->wowlan_support; } #endif diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index dd158ec571fb..827fa641490f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -222,20 +222,20 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_resume && device_can_wakeup(mvm->trans->dev)) { - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_EAP_IDENTITY_REQ | - WIPHY_WOWLAN_RFKILL_RELEASE; + mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_RFKILL_RELEASE; if (!iwlwifi_mod_params.sw_crypto) - hw->wiphy->wowlan.flags |= - WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | - WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_4WAY_HANDSHAKE; - - hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; - hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; - hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; - hw->wiphy->wowlan.tcp = &iwl_mvm_wowlan_tcp_support; + mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_4WAY_HANDSHAKE; + + mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; + mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; + mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN; + mvm->wowlan.tcp = &iwl_mvm_wowlan_tcp_support; + hw->wiphy->wowlan = &mvm->wowlan; } #endif diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 8269bc562951..b62a948658ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -336,6 +336,7 @@ struct iwl_mvm { struct ieee80211_vif *p2p_device_vif; #ifdef CONFIG_PM_SLEEP + struct wiphy_wowlan_support wowlan; int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; #endif diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index e42b266a023a..60077895adff 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2426,6 +2426,16 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { #endif }; +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mwifiex_wowlan_support = { + .flags = WIPHY_WOWLAN_MAGIC_PKT, + .n_patterns = MWIFIEX_MAX_FILTERS, + .pattern_min_len = 1, + .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, + .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, +}; +#endif + /* * This function registers the device with CFG802.11 subsystem. * @@ -2483,11 +2493,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); #ifdef CONFIG_PM - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; - wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS; - wiphy->wowlan.pattern_min_len = 1; - wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN; - wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN; + wiphy->wowlan = &mwifiex_wowlan_support; #endif wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 953111a502ee..796928ba875f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -6018,6 +6018,15 @@ int wlcore_free_hw(struct wl1271 *wl) } EXPORT_SYMBOL_GPL(wlcore_free_hw); +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support wlcore_wowlan_support = { + .flags = WIPHY_WOWLAN_ANY, + .n_patterns = WL1271_MAX_RX_FILTERS, + .pattern_min_len = 1, + .pattern_max_len = WL1271_RX_FILTER_MAX_PATTERN_SIZE, +}; +#endif + static void wlcore_nvs_cb(const struct firmware *fw, void *context) { struct wl1271 *wl = context; @@ -6071,14 +6080,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) if (!ret) { wl->irq_wake_enabled = true; device_init_wakeup(wl->dev, 1); - if (pdata->pwr_in_suspend) { - wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; - wl->hw->wiphy->wowlan.n_patterns = - WL1271_MAX_RX_FILTERS; - wl->hw->wiphy->wowlan.pattern_min_len = 1; - wl->hw->wiphy->wowlan.pattern_max_len = - WL1271_RX_FILTER_MAX_PATTERN_SIZE; - } + if (pdata->pwr_in_suspend) + wl->hw->wiphy->wowlan = &wlcore_wowlan_support; } #endif disable_irq(wl->irq); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6dd19593e333..6169fca216b4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2654,7 +2654,7 @@ struct wiphy { u32 hw_version; #ifdef CONFIG_PM - struct wiphy_wowlan_support wowlan; + const struct wiphy_wowlan_support *wowlan; struct cfg80211_wowlan *wowlan_config; #endif diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1998f1475267..626c83c042d7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -686,8 +686,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) return -EINVAL; #ifdef CONFIG_PM - if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && - (!local->ops->suspend || !local->ops->resume)) + if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume)) return -EINVAL; #endif diff --git a/net/wireless/core.c b/net/wireless/core.c index 41cec1776f4f..f553b9484c1e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -449,8 +449,13 @@ int wiphy_register(struct wiphy *wiphy) u16 ifmodes = wiphy->interface_modes; #ifdef CONFIG_PM - if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && - !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY))) + if (WARN_ON(wiphy->wowlan && + (wiphy->wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && + !(wiphy->wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY))) + return -EINVAL; + if (WARN_ON(wiphy->wowlan && + !wiphy->wowlan->flags && !wiphy->wowlan->n_patterns && + !wiphy->wowlan->tcp)) return -EINVAL; #endif @@ -540,12 +545,11 @@ int wiphy_register(struct wiphy *wiphy) } #ifdef CONFIG_PM - if (rdev->wiphy.wowlan.n_patterns) { - if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len || - rdev->wiphy.wowlan.pattern_min_len > - rdev->wiphy.wowlan.pattern_max_len)) - return -EINVAL; - } + if (WARN_ON(rdev->wiphy.wowlan && rdev->wiphy.wowlan->n_patterns && + (!rdev->wiphy.wowlan->pattern_min_len || + rdev->wiphy.wowlan->pattern_min_len > + rdev->wiphy.wowlan->pattern_max_len))) + return -EINVAL; #endif /* check and set up bitrates */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 31d265f36d2c..7ee9af3283a8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -908,7 +908,7 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, struct sk_buff *msg) { - const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; + const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan->tcp; struct nlattr *nl_tcp; if (!tcp) @@ -951,37 +951,37 @@ static int nl80211_send_wowlan(struct sk_buff *msg, { struct nlattr *nl_wowlan; - if (!dev->wiphy.wowlan.flags && !dev->wiphy.wowlan.n_patterns) + if (!dev->wiphy.wowlan) return 0; nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); if (!nl_wowlan) return -ENOBUFS; - if (((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) && + if (((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_ANY) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_DISCONNECT) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_EAP_IDENTITY_REQ) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_4WAY_HANDSHAKE) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || - ((dev->wiphy.wowlan.flags & WIPHY_WOWLAN_RFKILL_RELEASE) && + ((dev->wiphy.wowlan->flags & WIPHY_WOWLAN_RFKILL_RELEASE) && nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) return -ENOBUFS; - if (dev->wiphy.wowlan.n_patterns) { + if (dev->wiphy.wowlan->n_patterns) { struct nl80211_wowlan_pattern_support pat = { - .max_patterns = dev->wiphy.wowlan.n_patterns, - .min_pattern_len = dev->wiphy.wowlan.pattern_min_len, - .max_pattern_len = dev->wiphy.wowlan.pattern_max_len, - .max_pkt_offset = dev->wiphy.wowlan.max_pkt_offset, + .max_patterns = dev->wiphy.wowlan->n_patterns, + .min_pattern_len = dev->wiphy.wowlan->pattern_min_len, + .max_pattern_len = dev->wiphy.wowlan->pattern_max_len, + .max_pkt_offset = dev->wiphy.wowlan->max_pkt_offset, }; if (nla_put(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, @@ -7580,8 +7580,7 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) void *hdr; u32 size = NLMSG_DEFAULT_SIZE; - if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && - !rdev->wiphy.wowlan.tcp) + if (!rdev->wiphy.wowlan) return -EOPNOTSUPP; if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) { @@ -7654,7 +7653,7 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, u32 data_size, wake_size, tokens_size = 0, wake_mask_size; int err, port; - if (!rdev->wiphy.wowlan.tcp) + if (!rdev->wiphy.wowlan->tcp) return -EINVAL; err = nla_parse(tb, MAX_NL80211_WOWLAN_TCP, @@ -7674,16 +7673,16 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, return -EINVAL; data_size = nla_len(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD]); - if (data_size > rdev->wiphy.wowlan.tcp->data_payload_max) + if (data_size > rdev->wiphy.wowlan->tcp->data_payload_max) return -EINVAL; if (nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) > - rdev->wiphy.wowlan.tcp->data_interval_max || + rdev->wiphy.wowlan->tcp->data_interval_max || nla_get_u32(tb[NL80211_WOWLAN_TCP_DATA_INTERVAL]) == 0) return -EINVAL; wake_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_PAYLOAD]); - if (wake_size > rdev->wiphy.wowlan.tcp->wake_payload_max) + if (wake_size > rdev->wiphy.wowlan->tcp->wake_payload_max) return -EINVAL; wake_mask_size = nla_len(tb[NL80211_WOWLAN_TCP_WAKE_MASK]); @@ -7698,13 +7697,13 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, if (!tok->len || tokens_size % tok->len) return -EINVAL; - if (!rdev->wiphy.wowlan.tcp->tok) + if (!rdev->wiphy.wowlan->tcp->tok) return -EINVAL; - if (tok->len > rdev->wiphy.wowlan.tcp->tok->max_len) + if (tok->len > rdev->wiphy.wowlan->tcp->tok->max_len) return -EINVAL; - if (tok->len < rdev->wiphy.wowlan.tcp->tok->min_len) + if (tok->len < rdev->wiphy.wowlan->tcp->tok->min_len) return -EINVAL; - if (tokens_size > rdev->wiphy.wowlan.tcp->tok->bufsize) + if (tokens_size > rdev->wiphy.wowlan->tcp->tok->bufsize) return -EINVAL; if (tok->offset + tok->len > data_size) return -EINVAL; @@ -7712,7 +7711,7 @@ static int nl80211_parse_wowlan_tcp(struct cfg80211_registered_device *rdev, if (tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]) { seq = nla_data(tb[NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ]); - if (!rdev->wiphy.wowlan.tcp->seq) + if (!rdev->wiphy.wowlan->tcp->seq) return -EINVAL; if (seq->len == 0 || seq->len > 4) return -EINVAL; @@ -7793,12 +7792,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; struct cfg80211_wowlan new_triggers = {}; struct cfg80211_wowlan *ntrig; - struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; + const struct wiphy_wowlan_support *wowlan = rdev->wiphy.wowlan; int err, i; bool prev_enabled = rdev->wiphy.wowlan_config; - if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns && - !rdev->wiphy.wowlan.tcp) + if (!wowlan) return -EOPNOTSUPP; if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) { -- GitLab From fb1fcf1779bba4c034635cc8916261a6744584a9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:53 -0300 Subject: [PATCH 0603/2900] [media] coda: fix ENC_SEQ_OPTION for CODA7 GAMMA_OFFSET is different between CodaDx6 and CODA7. Also, this is a bitfield. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 10 ++++++++-- drivers/media/platform/coda.h | 8 ++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index efb42b2913ca..1f3ab53670f8 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1129,8 +1129,14 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET; coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA); - value = (CODA_DEFAULT_GAMMA > 0) << CODA_OPTION_GAMMA_OFFSET; - value |= (0 & CODA_OPTION_SLICEREPORT_MASK) << CODA_OPTION_SLICEREPORT_OFFSET; + if (CODA_DEFAULT_GAMMA > 0) { + if (dev->devtype->product == CODA_DX6) + value = 1 << CODADX6_OPTION_GAMMA_OFFSET; + else + value = 1 << CODA7_OPTION_GAMMA_OFFSET; + } else { + value = 0; + } coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); if (dst_fourcc == V4L2_PIX_FMT_H264) { diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index f3f5e43c1ac2..3c350acd5faa 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h @@ -96,16 +96,12 @@ #define CODA_CMD_ENC_SEQ_BB_START 0x180 #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 #define CODA_CMD_ENC_SEQ_OPTION 0x188 -#define CODA_OPTION_GAMMA_OFFSET 7 -#define CODA_OPTION_GAMMA_MASK 0x01 +#define CODA7_OPTION_GAMMA_OFFSET 8 +#define CODADX6_OPTION_GAMMA_OFFSET 7 #define CODA_OPTION_LIMITQP_OFFSET 6 -#define CODA_OPTION_LIMITQP_MASK 0x01 #define CODA_OPTION_RCINTRAQP_OFFSET 5 -#define CODA_OPTION_RCINTRAQP_MASK 0x01 #define CODA_OPTION_FMO_OFFSET 4 -#define CODA_OPTION_FMO_MASK 0x01 #define CODA_OPTION_SLICEREPORT_OFFSET 1 -#define CODA_OPTION_SLICEREPORT_MASK 0x01 #define CODA_CMD_ENC_SEQ_COD_STD 0x18c #define CODA_STD_MPEG4 0 #define CODA_STD_H263 1 -- GitLab From 47cf0c61aaf47f9940d3eccc64e870d7f8013590 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:54 -0300 Subject: [PATCH 0604/2900] [media] coda: frame stride must be a multiple of 8 Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 1f3ab53670f8..b53c74855702 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -422,8 +422,9 @@ static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, W_ALIGN, &f->fmt.pix.height, MIN_H, MAX_H, H_ALIGN, S_ALIGN); - f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); - f->fmt.pix.sizeimage = f->fmt.pix.width * + /* Frame stride must be multiple of 8 */ + f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8); + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height * 3 / 2; } else { /*encoded formats h.264/mpeg4 */ f->fmt.pix.bytesperline = 0; -- GitLab From f609222a051037ebcbb9c15c90f456c77a23be13 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:55 -0300 Subject: [PATCH 0605/2900] [media] coda: stop setting bytesused in buf_prepare The application must have filled the bytesused field, don't overwrite it here. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index b53c74855702..109b9389c0c9 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -869,8 +869,6 @@ static int coda_buf_prepare(struct vb2_buffer *vb) return -EINVAL; } - vb2_set_plane_payload(vb, 0, q_data->sizeimage); - return 0; } -- GitLab From 9acf7693b7487b5dc744030a1aaa3a20dd8df495 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:56 -0300 Subject: [PATCH 0606/2900] [media] coda: clear registers in coda_hw_init Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 109b9389c0c9..ba99e2fb0f85 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1753,6 +1753,10 @@ static int coda_hw_init(struct coda_dev *dev) } } + /* Clear registers */ + for (i = 0; i < 64; i++) + coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); + /* Tell the BIT where to find everything it needs */ coda_write(dev, dev->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); -- GitLab From 911373cca1b45571b62938f8f19cec24cb102471 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 1 Jun 2013 08:08:42 -0400 Subject: [PATCH 0607/2900] cw1200: Rename 'sbus' to 'hwbus' This avoids problems when building on SPARC targets due to the driver calling the bus abstraction layer 'sbus'. Not that any SBUS-sporting SPARC targets are likely to have an SDIO controller, but this is the correct thing to do. See http://kisskb.ellerman.id.au/kisskb/buildresult/8846508/ Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/bh.c | 20 +++++------ drivers/net/wireless/cw1200/cw1200.h | 10 +++--- drivers/net/wireless/cw1200/cw1200_sdio.c | 44 +++++++++++------------ drivers/net/wireless/cw1200/cw1200_spi.c | 38 ++++++++++---------- drivers/net/wireless/cw1200/fwio.c | 10 +++--- drivers/net/wireless/cw1200/hwbus.h | 33 +++++++++++++++++ drivers/net/wireless/cw1200/hwio.c | 30 ++++++++-------- drivers/net/wireless/cw1200/main.c | 14 ++++---- drivers/net/wireless/cw1200/pm.c | 6 ++-- drivers/net/wireless/cw1200/sbus.h | 37 ------------------- 10 files changed, 119 insertions(+), 123 deletions(-) create mode 100644 drivers/net/wireless/cw1200/hwbus.h delete mode 100644 drivers/net/wireless/cw1200/sbus.h diff --git a/drivers/net/wireless/cw1200/bh.c b/drivers/net/wireless/cw1200/bh.c index cf7375f92fb3..324b57001da0 100644 --- a/drivers/net/wireless/cw1200/bh.c +++ b/drivers/net/wireless/cw1200/bh.c @@ -23,7 +23,7 @@ #include "bh.h" #include "hwio.h" #include "wsm.h" -#include "sbus.h" +#include "hwbus.h" #include "debug.h" #include "fwio.h" @@ -103,7 +103,7 @@ void cw1200_irq_handler(struct cw1200_common *priv) pr_debug("[BH] irq.\n"); /* Disable Interrupts! */ - /* NOTE: sbus_ops->lock already held */ + /* NOTE: hwbus_ops->lock already held */ __cw1200_irq_enable(priv, 0); if (/* WARN_ON */(priv->bh_error)) @@ -265,8 +265,8 @@ static int cw1200_bh_rx_helper(struct cw1200_common *priv, * to the NEXT Message length + 2 Bytes for SKB */ read_len = read_len + 2; - alloc_len = priv->sbus_ops->align_size( - priv->sbus_priv, read_len); + alloc_len = priv->hwbus_ops->align_size( + priv->hwbus_priv, read_len); /* Check if not exceeding CW1200 capabilities */ if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE)) { @@ -384,8 +384,8 @@ static int cw1200_bh_tx_helper(struct cw1200_common *priv, atomic_add(1, &priv->bh_tx); - tx_len = priv->sbus_ops->align_size( - priv->sbus_priv, tx_len); + tx_len = priv->hwbus_ops->align_size( + priv->hwbus_priv, tx_len); /* Check if not exceeding CW1200 capabilities */ if (WARN_ON_ONCE(tx_len > EFFECTIVE_BUF_SIZE)) @@ -597,15 +597,15 @@ static int cw1200_bh(void *arg) done: /* Re-enable device interrupts */ - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); __cw1200_irq_enable(priv, 1); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); } /* Explicitly disable device interrupts */ - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); __cw1200_irq_enable(priv, 0); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); if (!term) { pr_err("[BH] Fatal error, exiting.\n"); diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h index e9424e635883..95320f2b25eb 100644 --- a/drivers/net/wireless/cw1200/cw1200.h +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -30,7 +30,7 @@ #include "pm.h" /* Forward declarations */ -struct sbus_ops; +struct hwbus_ops; struct task_struct; struct cw1200_debug_priv; struct firmware; @@ -109,8 +109,8 @@ struct cw1200_common { u8 mac_addr[ETH_ALEN]; /* Hardware interface */ - const struct sbus_ops *sbus_ops; - struct sbus_priv *sbus_priv; + const struct hwbus_ops *hwbus_ops; + struct hwbus_priv *hwbus_priv; /* Hardware information */ enum { @@ -298,8 +298,8 @@ struct cw1200_sta_priv { }; /* interfaces for the drivers */ -int cw1200_core_probe(const struct sbus_ops *sbus_ops, - struct sbus_priv *sbus, +int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, + struct hwbus_priv *hwbus, struct device *pdev, struct cw1200_common **pself, int ref_clk, const u8 *macaddr, diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 863510d062fb..78c3bc55cd0b 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -19,7 +19,7 @@ #include #include "cw1200.h" -#include "sbus.h" +#include "hwbus.h" #include #include "hwio.h" @@ -29,7 +29,7 @@ MODULE_LICENSE("GPL"); #define SDIO_BLOCK_SIZE (512) -struct sbus_priv { +struct hwbus_priv { struct sdio_func *func; struct cw1200_common *core; const struct cw1200_platform_data_sdio *pdata; @@ -48,35 +48,35 @@ static const struct sdio_device_id cw1200_sdio_ids[] = { { /* end: all zeroes */ }, }; -/* sbus_ops implemetation */ +/* hwbus_ops implemetation */ -static int cw1200_sdio_memcpy_fromio(struct sbus_priv *self, +static int cw1200_sdio_memcpy_fromio(struct hwbus_priv *self, unsigned int addr, void *dst, int count) { return sdio_memcpy_fromio(self->func, dst, addr, count); } -static int cw1200_sdio_memcpy_toio(struct sbus_priv *self, +static int cw1200_sdio_memcpy_toio(struct hwbus_priv *self, unsigned int addr, const void *src, int count) { return sdio_memcpy_toio(self->func, addr, (void *)src, count); } -static void cw1200_sdio_lock(struct sbus_priv *self) +static void cw1200_sdio_lock(struct hwbus_priv *self) { sdio_claim_host(self->func); } -static void cw1200_sdio_unlock(struct sbus_priv *self) +static void cw1200_sdio_unlock(struct hwbus_priv *self) { sdio_release_host(self->func); } static void cw1200_sdio_irq_handler(struct sdio_func *func) { - struct sbus_priv *self = sdio_get_drvdata(func); + struct hwbus_priv *self = sdio_get_drvdata(func); /* note: sdio_host already claimed here. */ if (self->core) @@ -90,7 +90,7 @@ static irqreturn_t cw1200_gpio_hardirq(int irq, void *dev_id) static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) { - struct sbus_priv *self = dev_id; + struct hwbus_priv *self = dev_id; if (self->core) { sdio_claim_host(self->func); @@ -102,7 +102,7 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) } } -static int cw1200_request_irq(struct sbus_priv *self) +static int cw1200_request_irq(struct hwbus_priv *self) { int ret; const struct resource *irq = self->pdata->irq; @@ -140,7 +140,7 @@ static int cw1200_request_irq(struct sbus_priv *self) return ret; } -static int cw1200_sdio_irq_subscribe(struct sbus_priv *self) +static int cw1200_sdio_irq_subscribe(struct hwbus_priv *self) { int ret = 0; @@ -155,7 +155,7 @@ static int cw1200_sdio_irq_subscribe(struct sbus_priv *self) return ret; } -static int cw1200_sdio_irq_unsubscribe(struct sbus_priv *self) +static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self) { int ret = 0; @@ -237,7 +237,7 @@ static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) return 0; } -static size_t cw1200_sdio_align_size(struct sbus_priv *self, size_t size) +static size_t cw1200_sdio_align_size(struct hwbus_priv *self, size_t size) { if (self->pdata->no_nptb) size = round_up(size, SDIO_BLOCK_SIZE); @@ -247,7 +247,7 @@ static size_t cw1200_sdio_align_size(struct sbus_priv *self, size_t size) return size; } -static int cw1200_sdio_pm(struct sbus_priv *self, bool suspend) +static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend) { int ret = 0; @@ -256,9 +256,9 @@ static int cw1200_sdio_pm(struct sbus_priv *self, bool suspend) return ret; } -static struct sbus_ops cw1200_sdio_sbus_ops = { - .sbus_memcpy_fromio = cw1200_sdio_memcpy_fromio, - .sbus_memcpy_toio = cw1200_sdio_memcpy_toio, +static struct hwbus_ops cw1200_sdio_hwbus_ops = { + .hwbus_memcpy_fromio = cw1200_sdio_memcpy_fromio, + .hwbus_memcpy_toio = cw1200_sdio_memcpy_toio, .lock = cw1200_sdio_lock, .unlock = cw1200_sdio_unlock, .align_size = cw1200_sdio_align_size, @@ -269,7 +269,7 @@ static struct sbus_ops cw1200_sdio_sbus_ops = { static int cw1200_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { - struct sbus_priv *self; + struct hwbus_priv *self; int status; pr_info("cw1200_wlan_sdio: Probe called\n"); @@ -280,7 +280,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, self = kzalloc(sizeof(*self), GFP_KERNEL); if (!self) { - pr_err("Can't allocate SDIO sbus_priv.\n"); + pr_err("Can't allocate SDIO hwbus_priv.\n"); return -ENOMEM; } @@ -295,7 +295,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, status = cw1200_sdio_irq_subscribe(self); - status = cw1200_core_probe(&cw1200_sdio_sbus_ops, + status = cw1200_core_probe(&cw1200_sdio_hwbus_ops, self, &func->dev, &self->core, self->pdata->ref_clk, self->pdata->macaddr, @@ -317,7 +317,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, * device is disconnected */ static void cw1200_sdio_disconnect(struct sdio_func *func) { - struct sbus_priv *self = sdio_get_drvdata(func); + struct hwbus_priv *self = sdio_get_drvdata(func); if (self) { cw1200_sdio_irq_unsubscribe(self); @@ -338,7 +338,7 @@ static int cw1200_sdio_suspend(struct device *dev) { int ret; struct sdio_func *func = dev_to_sdio_func(dev); - struct sbus_priv *self = sdio_get_drvdata(func); + struct hwbus_priv *self = sdio_get_drvdata(func); if (!cw1200_can_suspend(self->core)) return -EAGAIN; diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 75adef0c0cfd..75efe54e495f 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -24,7 +24,7 @@ #include #include "cw1200.h" -#include "sbus.h" +#include "hwbus.h" #include #include "hwio.h" @@ -35,7 +35,7 @@ MODULE_ALIAS("spi:cw1200_wlan_spi"); /* #define SPI_DEBUG */ -struct sbus_priv { +struct hwbus_priv { struct spi_device *func; struct cw1200_common *core; const struct cw1200_platform_data_spi *pdata; @@ -58,7 +58,7 @@ struct sbus_priv { */ -static int cw1200_spi_memcpy_fromio(struct sbus_priv *self, +static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, unsigned int addr, void *dst, int count) { @@ -119,7 +119,7 @@ static int cw1200_spi_memcpy_fromio(struct sbus_priv *self, return ret; } -static int cw1200_spi_memcpy_toio(struct sbus_priv *self, +static int cw1200_spi_memcpy_toio(struct hwbus_priv *self, unsigned int addr, const void *src, int count) { @@ -187,7 +187,7 @@ static int cw1200_spi_memcpy_toio(struct sbus_priv *self, return rval; } -static void cw1200_spi_lock(struct sbus_priv *self) +static void cw1200_spi_lock(struct hwbus_priv *self) { unsigned long flags; @@ -209,7 +209,7 @@ static void cw1200_spi_lock(struct sbus_priv *self) return; } -static void cw1200_spi_unlock(struct sbus_priv *self) +static void cw1200_spi_unlock(struct hwbus_priv *self) { unsigned long flags; @@ -221,7 +221,7 @@ static void cw1200_spi_unlock(struct sbus_priv *self) static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id) { - struct sbus_priv *self = dev_id; + struct hwbus_priv *self = dev_id; if (self->core) { cw1200_irq_handler(self->core); @@ -231,7 +231,7 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id) } } -static int cw1200_spi_irq_subscribe(struct sbus_priv *self) +static int cw1200_spi_irq_subscribe(struct hwbus_priv *self) { int ret; @@ -255,7 +255,7 @@ static int cw1200_spi_irq_subscribe(struct sbus_priv *self) return ret; } -static int cw1200_spi_irq_unsubscribe(struct sbus_priv *self) +static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) { int ret = 0; @@ -331,19 +331,19 @@ static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) return 0; } -static size_t cw1200_spi_align_size(struct sbus_priv *self, size_t size) +static size_t cw1200_spi_align_size(struct hwbus_priv *self, size_t size) { return size & 1 ? size + 1 : size; } -static int cw1200_spi_pm(struct sbus_priv *self, bool suspend) +static int cw1200_spi_pm(struct hwbus_priv *self, bool suspend) { return irq_set_irq_wake(self->func->irq, suspend); } -static struct sbus_ops cw1200_spi_sbus_ops = { - .sbus_memcpy_fromio = cw1200_spi_memcpy_fromio, - .sbus_memcpy_toio = cw1200_spi_memcpy_toio, +static struct hwbus_ops cw1200_spi_hwbus_ops = { + .hwbus_memcpy_fromio = cw1200_spi_memcpy_fromio, + .hwbus_memcpy_toio = cw1200_spi_memcpy_toio, .lock = cw1200_spi_lock, .unlock = cw1200_spi_unlock, .align_size = cw1200_spi_align_size, @@ -355,7 +355,7 @@ static int cw1200_spi_probe(struct spi_device *func) { const struct cw1200_platform_data_spi *plat_data = func->dev.platform_data; - struct sbus_priv *self; + struct hwbus_priv *self; int status; /* Sanity check speed */ @@ -389,7 +389,7 @@ static int cw1200_spi_probe(struct spi_device *func) self = kzalloc(sizeof(*self), GFP_KERNEL); if (!self) { - pr_err("Can't allocate SPI sbus_priv."); + pr_err("Can't allocate SPI hwbus_priv."); return -ENOMEM; } @@ -401,7 +401,7 @@ static int cw1200_spi_probe(struct spi_device *func) status = cw1200_spi_irq_subscribe(self); - status = cw1200_core_probe(&cw1200_spi_sbus_ops, + status = cw1200_core_probe(&cw1200_spi_hwbus_ops, self, &func->dev, &self->core, self->pdata->ref_clk, self->pdata->macaddr, @@ -420,7 +420,7 @@ static int cw1200_spi_probe(struct spi_device *func) /* Disconnect Function to be called by SPI stack when device is disconnected */ static int cw1200_spi_disconnect(struct spi_device *func) { - struct sbus_priv *self = spi_get_drvdata(func); + struct hwbus_priv *self = spi_get_drvdata(func); if (self) { cw1200_spi_irq_unsubscribe(self); @@ -438,7 +438,7 @@ static int cw1200_spi_disconnect(struct spi_device *func) #ifdef CONFIG_PM static int cw1200_spi_suspend(struct device *dev, pm_message_t state) { - struct sbus_priv *self = spi_get_drvdata(to_spi_device(dev)); + struct hwbus_priv *self = spi_get_drvdata(to_spi_device(dev)); if (!cw1200_can_suspend(self->core)) return -EAGAIN; diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index ad01cd2a59ec..427c9f24b94e 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c @@ -22,7 +22,7 @@ #include "cw1200.h" #include "fwio.h" #include "hwio.h" -#include "sbus.h" +#include "hwbus.h" #include "bh.h" static int cw1200_get_hw_type(u32 config_reg_val, int *major_revision) @@ -489,9 +489,9 @@ int cw1200_load_firmware(struct cw1200_common *priv) } /* Enable interrupt signalling */ - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); ret = __cw1200_irq_enable(priv, 1); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); if (ret < 0) goto unsubscribe; @@ -518,8 +518,8 @@ int cw1200_load_firmware(struct cw1200_common *priv) unsubscribe: /* Disable interrupt signalling */ - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); ret = __cw1200_irq_enable(priv, 0); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } diff --git a/drivers/net/wireless/cw1200/hwbus.h b/drivers/net/wireless/cw1200/hwbus.h new file mode 100644 index 000000000000..8b2fc831c3de --- /dev/null +++ b/drivers/net/wireless/cw1200/hwbus.h @@ -0,0 +1,33 @@ +/* + * Common hwbus abstraction layer interface for cw1200 wireless driver + * + * Copyright (c) 2010, ST-Ericsson + * Author: Dmitry Tarnyagin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CW1200_HWBUS_H +#define CW1200_HWBUS_H + +struct hwbus_priv; + +void cw1200_irq_handler(struct cw1200_common *priv); + +/* This MUST be wrapped with hwbus_ops->lock/unlock! */ +int __cw1200_irq_enable(struct cw1200_common *priv, int enable); + +struct hwbus_ops { + int (*hwbus_memcpy_fromio)(struct hwbus_priv *self, unsigned int addr, + void *dst, int count); + int (*hwbus_memcpy_toio)(struct hwbus_priv *self, unsigned int addr, + const void *src, int count); + void (*lock)(struct hwbus_priv *self); + void (*unlock)(struct hwbus_priv *self); + size_t (*align_size)(struct hwbus_priv *self, size_t size); + int (*power_mgmt)(struct hwbus_priv *self, bool suspend); +}; + +#endif /* CW1200_HWBUS_H */ diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c index 1af7b3d421b2..142f45efa204 100644 --- a/drivers/net/wireless/cw1200/hwio.c +++ b/drivers/net/wireless/cw1200/hwio.c @@ -18,7 +18,7 @@ #include "cw1200.h" #include "hwio.h" -#include "sbus.h" +#include "hwbus.h" /* Sdio addr is 4*spi_addr */ #define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2) @@ -46,7 +46,7 @@ static int __cw1200_reg_read(struct cw1200_common *priv, u16 addr, addr_sdio = SPI_REG_ADDR_TO_SDIO(addr); sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio); - return priv->sbus_ops->sbus_memcpy_fromio(priv->sbus_priv, + return priv->hwbus_ops->hwbus_memcpy_fromio(priv->hwbus_priv, sdio_reg_addr_17bit, buf, buf_len); } @@ -61,7 +61,7 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr, addr_sdio = SPI_REG_ADDR_TO_SDIO(addr); sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio); - return priv->sbus_ops->sbus_memcpy_toio(priv->sbus_priv, + return priv->hwbus_ops->hwbus_memcpy_toio(priv->hwbus_priv, sdio_reg_addr_17bit, buf, buf_len); } @@ -100,9 +100,9 @@ int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf, size_t buf_len) { int ret; - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); ret = __cw1200_reg_read(priv, addr, buf, buf_len, 0); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } @@ -110,9 +110,9 @@ int cw1200_reg_write(struct cw1200_common *priv, u16 addr, const void *buf, size_t buf_len) { int ret; - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); ret = __cw1200_reg_write(priv, addr, buf, buf_len, 0); - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } @@ -121,7 +121,7 @@ int cw1200_data_read(struct cw1200_common *priv, void *buf, size_t buf_len) int ret, retry = 1; int buf_id_rx = priv->buf_id_rx; - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); while (retry <= MAX_RETRY) { ret = __cw1200_reg_read(priv, @@ -138,7 +138,7 @@ int cw1200_data_read(struct cw1200_common *priv, void *buf, size_t buf_len) } } - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } @@ -148,7 +148,7 @@ int cw1200_data_write(struct cw1200_common *priv, const void *buf, int ret, retry = 1; int buf_id_tx = priv->buf_id_tx; - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); while (retry <= MAX_RETRY) { ret = __cw1200_reg_write(priv, @@ -165,7 +165,7 @@ int cw1200_data_write(struct cw1200_common *priv, const void *buf, } } - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } @@ -181,7 +181,7 @@ int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, goto out; } - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); /* Write address */ ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr); if (ret < 0) { @@ -230,7 +230,7 @@ int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, } out: - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } @@ -244,7 +244,7 @@ int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf, return -EINVAL; } - priv->sbus_ops->lock(priv->sbus_priv); + priv->hwbus_ops->lock(priv->hwbus_priv); /* Write address */ ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr); @@ -262,7 +262,7 @@ int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf, } out: - priv->sbus_ops->unlock(priv->sbus_priv); + priv->hwbus_ops->unlock(priv->hwbus_priv); return ret; } diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index ef4b0b915f87..2ea1bada7207 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c @@ -31,7 +31,7 @@ #include "cw1200.h" #include "txrx.h" -#include "sbus.h" +#include "hwbus.h" #include "fwio.h" #include "hwio.h" #include "bh.h" @@ -528,8 +528,8 @@ u32 cw1200_dpll_from_clk(u16 clk_khz) } } -int cw1200_core_probe(const struct sbus_ops *sbus_ops, - struct sbus_priv *sbus, +int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, + struct hwbus_priv *hwbus, struct device *pdev, struct cw1200_common **core, int ref_clk, const u8 *macaddr, @@ -556,8 +556,8 @@ int cw1200_core_probe(const struct sbus_ops *sbus_ops, if (cw1200_sdd_path) priv->sdd_path = cw1200_sdd_path; - priv->sbus_ops = sbus_ops; - priv->sbus_priv = sbus; + priv->hwbus_ops = hwbus_ops; + priv->hwbus_priv = hwbus; priv->pdev = pdev; SET_IEEE80211_DEV(priv->hw, pdev); @@ -616,9 +616,9 @@ EXPORT_SYMBOL_GPL(cw1200_core_probe); void cw1200_core_release(struct cw1200_common *self) { /* Disable device interrupts */ - self->sbus_ops->lock(self->sbus_priv); + self->hwbus_ops->lock(self->hwbus_priv); __cw1200_irq_enable(self, 0); - self->sbus_ops->unlock(self->sbus_priv); + self->hwbus_ops->unlock(self->hwbus_priv); /* And then clean up */ cw1200_unregister_common(self->hw); diff --git a/drivers/net/wireless/cw1200/pm.c b/drivers/net/wireless/cw1200/pm.c index 79edfb93b292..b37abb9f0453 100644 --- a/drivers/net/wireless/cw1200/pm.c +++ b/drivers/net/wireless/cw1200/pm.c @@ -15,7 +15,7 @@ #include "pm.h" #include "sta.h" #include "bh.h" -#include "sbus.h" +#include "hwbus.h" #define CW1200_BEACON_SKIPPING_MULTIPLIER 3 @@ -264,7 +264,7 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) pm_state->suspend_state = state; /* Enable IRQ wake */ - ret = priv->sbus_ops->power_mgmt(priv->sbus_priv, true); + ret = priv->hwbus_ops->power_mgmt(priv->hwbus_priv, true); if (ret) { wiphy_err(priv->hw->wiphy, "PM request failed: %d. WoW is disabled.\n", ret); @@ -313,7 +313,7 @@ int cw1200_wow_resume(struct ieee80211_hw *hw) pm_state->suspend_state = NULL; /* Disable IRQ wake */ - priv->sbus_ops->power_mgmt(priv->sbus_priv, false); + priv->hwbus_ops->power_mgmt(priv->hwbus_priv, false); /* Scan.lock must be released before BH is resumed other way * in case when BSS_LOST command arrived the processing of the diff --git a/drivers/net/wireless/cw1200/sbus.h b/drivers/net/wireless/cw1200/sbus.h deleted file mode 100644 index 603fd25eaa4a..000000000000 --- a/drivers/net/wireless/cw1200/sbus.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Common sbus abstraction layer interface for cw1200 wireless driver - * - * Copyright (c) 2010, ST-Ericsson - * Author: Dmitry Tarnyagin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef CW1200_SBUS_H -#define CW1200_SBUS_H - -/* - * sbus priv forward definition. - * Implemented and instantiated in particular modules. - */ -struct sbus_priv; - -void cw1200_irq_handler(struct cw1200_common *priv); - -/* This MUST be wrapped with sbus_ops->lock/unlock! */ -int __cw1200_irq_enable(struct cw1200_common *priv, int enable); - -struct sbus_ops { - int (*sbus_memcpy_fromio)(struct sbus_priv *self, unsigned int addr, - void *dst, int count); - int (*sbus_memcpy_toio)(struct sbus_priv *self, unsigned int addr, - const void *src, int count); - void (*lock)(struct sbus_priv *self); - void (*unlock)(struct sbus_priv *self); - size_t (*align_size)(struct sbus_priv *self, size_t size); - int (*power_mgmt)(struct sbus_priv *self, bool suspend); -}; - -#endif /* CW1200_SBUS_H */ -- GitLab From c992219825823cad5e11fab3854eb93df2e9ffa1 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 09:53:01 -0400 Subject: [PATCH 0608/2900] cw1200: move platform_data header to correct location. (As suggested by Arnd Bergmann) Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sagrad.c | 2 +- drivers/net/wireless/cw1200/cw1200_sdio.c | 2 +- drivers/net/wireless/cw1200/cw1200_spi.c | 2 +- include/linux/{ => platform_data}/cw1200_platform.h | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename include/linux/{ => platform_data}/cw1200_platform.h (100%) diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c index a5ada0eda1dd..14c2a186b493 100644 --- a/drivers/net/wireless/cw1200/cw1200_sagrad.c +++ b/drivers/net/wireless/cw1200/cw1200_sagrad.c @@ -10,7 +10,7 @@ */ #include -#include +#include MODULE_AUTHOR("Solomon Peachy "); MODULE_DESCRIPTION("ST-Ericsson CW1200 Platform glue driver"); diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 78c3bc55cd0b..9f25ec5641fe 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -20,7 +20,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Dmitry Tarnyagin "); diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 75efe54e495f..940e0947a5dc 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -25,7 +25,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Solomon Peachy "); diff --git a/include/linux/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h similarity index 100% rename from include/linux/cw1200_platform.h rename to include/linux/platform_data/cw1200_platform.h -- GitLab From 7b19bc2ca92ddda8f8e128593a2d523092ab4b14 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 09:53:02 -0400 Subject: [PATCH 0609/2900] cw1200: Reference correct 'powerup' GPIO signal. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sdio.c | 2 +- drivers/net/wireless/cw1200/cw1200_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 9f25ec5641fe..0a882ca89bbb 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -193,7 +193,7 @@ static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) { const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->reset; + const struct resource *powerup = pdata->powerup; /* Ensure I/Os are pulled low */ if (reset) { diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 940e0947a5dc..da5d24cc67db 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -287,7 +287,7 @@ static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) { const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->reset; + const struct resource *powerup = pdata->powerup; /* Ensure I/Os are pulled low */ if (reset) { -- GitLab From 6dd64a304eff76ca7dd41bf63df55efa965fa9ec Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 09:53:03 -0400 Subject: [PATCH 0610/2900] cw1200: Replace use of 'struct resource' with 'int' for GPIO fields. The only advantage of 'struct resource' is that it lets us assign names as part of the platform data. Unfortunately since we are using platform data, we are already limited to a single instance of each driver, rendering this moot. So, replace the struct resources with ints, resulting in cleaner code. This was based on a suggestion from Arnd Bergmann. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sagrad.c | 49 ++---------------- drivers/net/wireless/cw1200/cw1200_sdio.c | 50 ++++++++----------- drivers/net/wireless/cw1200/cw1200_spi.c | 33 ++++++------ include/linux/platform_data/cw1200_platform.h | 12 ++--- 4 files changed, 47 insertions(+), 97 deletions(-) diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c index 14c2a186b493..3f884ac96ccc 100644 --- a/drivers/net/wireless/cw1200/cw1200_sagrad.c +++ b/drivers/net/wireless/cw1200/cw1200_sagrad.c @@ -21,29 +21,6 @@ MODULE_LICENSE("GPL"); /* #define SAGRAD_1091_1098_EVK_SPI */ #ifdef SAGRAD_1091_1098_EVK_SDIO -#if 0 -static struct resource cw1200_href_resources[] = { - { - .start = 215, /* fix me as appropriate */ - .end = 215, /* ditto */ - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_reset", - }, - { - .start = 216, /* fix me as appropriate */ - .end = 216, /* ditto */ - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_powerup", - }, - { - .start = NOMADIK_GPIO_TO_IRQ(216), /* fix me as appropriate */ - .end = NOMADIK_GPIO_TO_IRQ(216), /* ditto */ - .flags = IORESOURCE_IRQ, - .name = "cw1200_wlan_irq", - }, -}; -#endif - static int cw1200_power_ctrl(const struct cw1200_platform_data_sdio *pdata, bool enable) { @@ -68,9 +45,9 @@ static struct cw1200_platform_data_sdio cw1200_platform_data = { .ref_clk = 38400, .have_5ghz = false, #if 0 - .reset = &cw1200_href_resources[0], - .powerup = &cw1200_href_resources[1], - .irq = &cw1200_href_resources[2], + .reset = GPIO_RF_RESET, /* Replace as appropriate */ + .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ + .irq = GPIO_TO_IRQ(GPIO_RF_IRQ), /* Replace as appropriate */ #endif .power_ctrl = cw1200_power_ctrl, .clk_ctrl = cw1200_clk_ctrl, @@ -80,22 +57,6 @@ static struct cw1200_platform_data_sdio cw1200_platform_data = { #endif #ifdef SAGRAD_1091_1098_EVK_SPI -/* Note that this is an example of integrating into your board support file */ -static struct resource cw1200_href_resources[] = { - { - .start = GPIO_RF_RESET, - .end = GPIO_RF_RESET, - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_reset", - }, - { - .start = GPIO_RF_POWERUP, - .end = GPIO_RF_POWERUP, - .flags = IORESOURCE_IO, - .name = "cw1200_wlan_powerup", - }, -}; - static int cw1200_power_ctrl(const struct cw1200_platform_data_spi *pdata, bool enable) { @@ -118,8 +79,8 @@ static int cw1200_clk_ctrl(const struct cw1200_platform_data_spi *pdata, static struct cw1200_platform_data_spi cw1200_platform_data = { .ref_clk = 38400, .spi_bits_per_word = 16, - .reset = &cw1200_href_resources[0], - .powerup = &cw1200_href_resources[1], + .reset = GPIO_RF_RESET, /* Replace as appropriate */ + .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ .power_ctrl = cw1200_power_ctrl, .clk_ctrl = cw1200_clk_ctrl, /* .macaddr = ??? */ diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 0a882ca89bbb..574cf727567c 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -105,7 +105,6 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id) static int cw1200_request_irq(struct hwbus_priv *self) { int ret; - const struct resource *irq = self->pdata->irq; u8 cccr; cccr = sdio_f0_readb(self->func, SDIO_CCCR_IENx, &ret); @@ -122,15 +121,15 @@ static int cw1200_request_irq(struct hwbus_priv *self) if (WARN_ON(ret)) goto err; - ret = enable_irq_wake(irq->start); + ret = enable_irq_wake(self->pdata->irq); if (WARN_ON(ret)) goto err; /* Request the IRQ */ - ret = request_threaded_irq(irq->start, cw1200_gpio_hardirq, + ret = request_threaded_irq(self->pdata->irq, cw1200_gpio_hardirq, cw1200_gpio_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - irq->name, self); + "cw1200_wlan_irq", self); if (WARN_ON(ret)) goto err; @@ -162,8 +161,8 @@ static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self) pr_debug("SW IRQ unsubscribe\n"); if (self->pdata->irq) { - disable_irq_wake(self->pdata->irq->start); - free_irq(self->pdata->irq->start, self); + disable_irq_wake(self->pdata->irq); + free_irq(self->pdata->irq, self); } else { sdio_claim_host(self->func); ret = sdio_release_irq(self->func); @@ -174,12 +173,10 @@ static int cw1200_sdio_irq_unsubscribe(struct hwbus_priv *self) static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) { - const struct resource *reset = pdata->reset; - - if (reset) { - gpio_set_value(reset->start, 0); + if (pdata->reset) { + gpio_set_value(pdata->reset, 0); msleep(30); /* Min is 2 * CLK32K cycles */ - gpio_free(reset->start); + gpio_free(pdata->reset); } if (pdata->power_ctrl) @@ -192,20 +189,17 @@ static int cw1200_sdio_off(const struct cw1200_platform_data_sdio *pdata) static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) { - const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->powerup; - /* Ensure I/Os are pulled low */ - if (reset) { - gpio_request(reset->start, reset->name); - gpio_direction_output(reset->start, 0); + if (pdata->reset) { + gpio_request(pdata->reset, "cw1200_wlan_reset"); + gpio_direction_output(pdata->reset, 0); } - if (powerup) { - gpio_request(powerup->start, powerup->name); - gpio_direction_output(powerup->start, 0); + if (pdata->powerup) { + gpio_request(pdata->powerup, "cw1200_wlan_powerup"); + gpio_direction_output(pdata->powerup, 0); } - if (reset || powerup) - msleep(50); /* Settle time */ + if (pdata->reset || pdata->powerup) + msleep(10); /* Settle time? */ /* Enable 3v3 and 1v8 to hardware */ if (pdata->power_ctrl) { @@ -225,13 +219,13 @@ static int cw1200_sdio_on(const struct cw1200_platform_data_sdio *pdata) } /* Enable POWERUP signal */ - if (powerup) { - gpio_set_value(powerup->start, 1); + if (pdata->powerup) { + gpio_set_value(pdata->powerup, 1); msleep(250); /* or more..? */ } /* Enable RSTn signal */ - if (reset) { - gpio_set_value(reset->start, 1); + if (pdata->reset) { + gpio_set_value(pdata->reset, 1); msleep(50); /* Or more..? */ } return 0; @@ -252,7 +246,7 @@ static int cw1200_sdio_pm(struct hwbus_priv *self, bool suspend) int ret = 0; if (self->pdata->irq) - ret = irq_set_irq_wake(self->pdata->irq->start, suspend); + ret = irq_set_irq_wake(self->pdata->irq, suspend); return ret; } @@ -274,7 +268,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, pr_info("cw1200_wlan_sdio: Probe called\n"); - /* We are only able to handle the wlan function */ + /* We are only able to handle the wlan function */ if (func->num != 0x01) return -ENODEV; diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index da5d24cc67db..d8dc7c6bb96d 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -268,12 +268,10 @@ static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) { - const struct resource *reset = pdata->reset; - - if (reset) { - gpio_set_value(reset->start, 0); + if (pdata->reset) { + gpio_set_value(pdata->reset, 0); msleep(30); /* Min is 2 * CLK32K cycles */ - gpio_free(reset->start); + gpio_free(pdata->reset); } if (pdata->power_ctrl) @@ -286,19 +284,16 @@ static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) { - const struct resource *reset = pdata->reset; - const struct resource *powerup = pdata->powerup; - /* Ensure I/Os are pulled low */ - if (reset) { - gpio_request(reset->start, reset->name); - gpio_direction_output(reset->start, 0); + if (pdata->reset) { + gpio_request(pdata->reset, "cw1200_wlan_reset"); + gpio_direction_output(pdata->reset, 0); } - if (powerup) { - gpio_request(powerup->start, powerup->name); - gpio_direction_output(powerup->start, 0); + if (pdata->powerup) { + gpio_request(pdata->powerup, "cw1200_wlan_powerup"); + gpio_direction_output(pdata->powerup, 0); } - if (reset || powerup) + if (pdata->reset || pdata->powerup) msleep(10); /* Settle time? */ /* Enable 3v3 and 1v8 to hardware */ @@ -319,13 +314,13 @@ static int cw1200_spi_on(const struct cw1200_platform_data_spi *pdata) } /* Enable POWERUP signal */ - if (powerup) { - gpio_set_value(powerup->start, 1); + if (pdata->powerup) { + gpio_set_value(pdata->powerup, 1); msleep(250); /* or more..? */ } /* Enable RSTn signal */ - if (reset) { - gpio_set_value(reset->start, 1); + if (pdata->reset) { + gpio_set_value(pdata->reset, 1); msleep(50); /* Or more..? */ } return 0; diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h index c168fa512347..4454c16ea3e5 100644 --- a/include/linux/platform_data/cw1200_platform.h +++ b/include/linux/platform_data/cw1200_platform.h @@ -14,8 +14,8 @@ struct cw1200_platform_data_spi { /* All others are optional */ bool have_5ghz; - const struct resource *reset; /* GPIO to RSTn signal */ - const struct resource *powerup; /* GPIO to POWERUP signal */ + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ int (*power_ctrl)(const struct cw1200_platform_data_spi *pdata, bool enable); /* Control 3v3 / 1v8 supply */ int (*clk_ctrl)(const struct cw1200_platform_data_spi *pdata, @@ -28,11 +28,11 @@ struct cw1200_platform_data_sdio { u16 ref_clk; /* REQUIRED (in KHz) */ /* All others are optional */ - const struct resource *irq; /* if using GPIO for IRQ */ bool have_5ghz; - bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ - const struct resource *reset; /* GPIO to RSTn signal */ - const struct resource *powerup; /* GPIO to POWERUP signal */ + bool no_nptb; /* SDIO hardware does not support non-power-of-2-blocksizes */ + int reset; /* GPIO to RSTn signal (0 disables) */ + int powerup; /* GPIO to POWERUP signal (0 disables) */ + int irq; /* IRQ line or 0 to use SDIO IRQ */ int (*power_ctrl)(const struct cw1200_platform_data_sdio *pdata, bool enable); /* Control 3v3 / 1v8 supply */ int (*clk_ctrl)(const struct cw1200_platform_data_sdio *pdata, -- GitLab From 7c0b6f49dbea0b09b1de8aa5c942af9c2ad8b54c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 11:35:31 -0400 Subject: [PATCH 0611/2900] cw1200: Rework SDIO platform support to prevent build problems. Based on discussions with And Bergmann, this patch changes the SDIO platform code to default to supporting the Sagrad devices, allowing for it to be overridden in board setup code. This renders the cw1200_sagrad module suplerflous, so it is now removed. It also moves the documentation that was in the cw1200_sagrad source to the platform header. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/Kconfig | 17 ++- drivers/net/wireless/cw1200/Makefile | 2 - drivers/net/wireless/cw1200/cw1200_sagrad.c | 106 ------------------ drivers/net/wireless/cw1200/cw1200_sdio.c | 26 ++++- include/linux/platform_data/cw1200_platform.h | 37 +++++- 5 files changed, 66 insertions(+), 122 deletions(-) delete mode 100644 drivers/net/wireless/cw1200/cw1200_sagrad.c diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig index 13e36119ae9f..7a585d4e9c8e 100644 --- a/drivers/net/wireless/cw1200/Kconfig +++ b/drivers/net/wireless/cw1200/Kconfig @@ -13,20 +13,19 @@ config CW1200_WLAN_SDIO depends on CW1200 && MMC help Enable support for the CW1200 connected via an SDIO bus. + By default this driver only supports the Sagrad SG901-1091/1098 EVK + and similar designs that utilize a hardware reset circuit. To + support different CW1200 SDIO designs you will need to override + the default platform data by calling cw1200_sdio_set_platform_data() + in your board setup file. config CW1200_WLAN_SPI tristate "Support SPI platforms" depends on CW1200 && SPI help - Enables support for the CW1200 connected via a SPI bus. - -config CW1200_WLAN_SAGRAD - tristate "Support Sagrad SG901-1091/1098 modules" - depends on CW1200_WLAN_SDIO - help - This provides the platform data glue to support the - Sagrad SG901-1091/1098 modules in their standard SDIO EVK. - It also includes example SPI platform data. + Enables support for the CW1200 connected via a SPI bus. You will + need to add appropriate platform data glue in your board setup + file. menu "Driver debug features" depends on CW1200 && DEBUG_FS diff --git a/drivers/net/wireless/cw1200/Makefile b/drivers/net/wireless/cw1200/Makefile index 1aa3682066e0..bc6cbf91f26e 100644 --- a/drivers/net/wireless/cw1200/Makefile +++ b/drivers/net/wireless/cw1200/Makefile @@ -16,9 +16,7 @@ cw1200_core-$(CONFIG_PM) += pm.o cw1200_wlan_sdio-y := cw1200_sdio.o cw1200_wlan_spi-y := cw1200_spi.o -cw1200_wlan_sagrad-y := cw1200_sagrad.o obj-$(CONFIG_CW1200) += cw1200_core.o obj-$(CONFIG_CW1200_WLAN_SDIO) += cw1200_wlan_sdio.o obj-$(CONFIG_CW1200_WLAN_SPI) += cw1200_wlan_spi.o -obj-$(CONFIG_CW1200_WLAN_SAGRAD) += cw1200_wlan_sagrad.o diff --git a/drivers/net/wireless/cw1200/cw1200_sagrad.c b/drivers/net/wireless/cw1200/cw1200_sagrad.c deleted file mode 100644 index 3f884ac96ccc..000000000000 --- a/drivers/net/wireless/cw1200/cw1200_sagrad.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Platform glue data for ST-Ericsson CW1200 driver - * - * Copyright (c) 2013, Sagrad, Inc - * Author: Solomon Peachy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -MODULE_AUTHOR("Solomon Peachy "); -MODULE_DESCRIPTION("ST-Ericsson CW1200 Platform glue driver"); -MODULE_LICENSE("GPL"); - -/* Define just one of these. Feel free to customize as needed */ -#define SAGRAD_1091_1098_EVK_SDIO -/* #define SAGRAD_1091_1098_EVK_SPI */ - -#ifdef SAGRAD_1091_1098_EVK_SDIO -static int cw1200_power_ctrl(const struct cw1200_platform_data_sdio *pdata, - bool enable) -{ - /* Control 3v3 and 1v8 to hardware as appropriate */ - /* Note this is not needed if it's controlled elsewhere or always on */ - - /* May require delay for power to stabilize */ - return 0; -} - -static int cw1200_clk_ctrl(const struct cw1200_platform_data_sdio *pdata, - bool enable) -{ - /* Turn CLK_32K off and on as appropriate. */ - /* Note this is not needed if it's always on */ - - /* May require delay for clock to stabilize */ - return 0; -} - -static struct cw1200_platform_data_sdio cw1200_platform_data = { - .ref_clk = 38400, - .have_5ghz = false, -#if 0 - .reset = GPIO_RF_RESET, /* Replace as appropriate */ - .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ - .irq = GPIO_TO_IRQ(GPIO_RF_IRQ), /* Replace as appropriate */ -#endif - .power_ctrl = cw1200_power_ctrl, - .clk_ctrl = cw1200_clk_ctrl, -/* .macaddr = ??? */ - .sdd_file = "sdd_sagrad_1091_1098.bin", -}; -#endif - -#ifdef SAGRAD_1091_1098_EVK_SPI -static int cw1200_power_ctrl(const struct cw1200_platform_data_spi *pdata, - bool enable) -{ - /* Control 3v3 and 1v8 to hardware as appropriate */ - /* Note this is not needed if it's controlled elsewhere or always on */ - - /* May require delay for power to stabilize */ - return 0; -} -static int cw1200_clk_ctrl(const struct cw1200_platform_data_spi *pdata, - bool enable) -{ - /* Turn CLK_32K off and on as appropriate. */ - /* Note this is not needed if it's always on */ - - /* May require delay for clock to stabilize */ - return 0; -} - -static struct cw1200_platform_data_spi cw1200_platform_data = { - .ref_clk = 38400, - .spi_bits_per_word = 16, - .reset = GPIO_RF_RESET, /* Replace as appropriate */ - .powerup = GPIO_RF_POWERUP, /* Replace as appropriate */ - .power_ctrl = cw1200_power_ctrl, - .clk_ctrl = cw1200_clk_ctrl, -/* .macaddr = ??? */ - .sdd_file = "sdd_sagrad_1091_1098.bin", -}; -static struct spi_board_info myboard_spi_devices[] __initdata = { - { - .modalias = "cw1200_wlan_spi", - .max_speed_hz = 10000000, /* 52MHz Max */ - .bus_num = 0, - .irq = WIFI_IRQ, - .platform_data = &cw1200_platform_data, - .chip_select = 0, - }, -}; -#endif - - -const void *cw1200_get_platform_data(void) -{ - return &cw1200_platform_data; -} -EXPORT_SYMBOL_GPL(cw1200_get_platform_data); diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 574cf727567c..4b3148e47ee7 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -29,6 +29,21 @@ MODULE_LICENSE("GPL"); #define SDIO_BLOCK_SIZE (512) +/* Default platform data for Sagrad modules */ +static struct cw1200_platform_data_sdio sagrad_109x_evk_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, + .sdd_file = "sdd_sagrad_1091_1098.bin", +}; + +/* Allow platform data to be overridden */ +static struct cw1200_platform_data_sdio *global_plat_data = &sagrad_109x_evk_platform_data; + +void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata) +{ + global_plat_data = pdata; +} + struct hwbus_priv { struct sdio_func *func; struct cw1200_common *core; @@ -261,7 +276,7 @@ static struct hwbus_ops cw1200_sdio_hwbus_ops = { /* Probe Function to be called by SDIO stack when device is discovered */ static int cw1200_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) + const struct sdio_device_id *id) { struct hwbus_priv *self; int status; @@ -280,7 +295,7 @@ static int cw1200_sdio_probe(struct sdio_func *func, func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - self->pdata = cw1200_get_platform_data(); + self->pdata = global_plat_data; /* FIXME */ self->func = func; sdio_set_drvdata(func, self); sdio_claim_host(func); @@ -374,7 +389,8 @@ static int __init cw1200_sdio_init(void) const struct cw1200_platform_data_sdio *pdata; int ret; - pdata = cw1200_get_platform_data(); + /* FIXME -- this won't support multiple devices */ + pdata = global_plat_data; if (cw1200_sdio_on(pdata)) { ret = -1; @@ -396,7 +412,9 @@ static int __init cw1200_sdio_init(void) static void __exit cw1200_sdio_exit(void) { const struct cw1200_platform_data_sdio *pdata; - pdata = cw1200_get_platform_data(); + + /* FIXME -- this won't support multiple devices */ + pdata = global_plat_data; sdio_unregister_driver(&sdio_driver); cw1200_sdio_off(pdata); } diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/cw1200_platform.h index 4454c16ea3e5..c6fbc3ce4ab0 100644 --- a/include/linux/platform_data/cw1200_platform.h +++ b/include/linux/platform_data/cw1200_platform.h @@ -41,6 +41,41 @@ struct cw1200_platform_data_sdio { const char *sdd_file; /* if NULL, will use default for detected hw type */ }; -const void *cw1200_get_platform_data(void); + +/* An example of SPI support in your board setup file: + + static struct cw1200_platform_data_spi cw1200_platform_data = { + .ref_clk = 38400, + .spi_bits_per_word = 16, + .reset = GPIO_RF_RESET, + .powerup = GPIO_RF_POWERUP, + .macaddr = wifi_mac_addr, + .sdd_file = "sdd_sagrad_1091_1098.bin", + }; + static struct spi_board_info myboard_spi_devices[] __initdata = { + { + .modalias = "cw1200_wlan_spi", + .max_speed_hz = 52000000, + .bus_num = 0, + .irq = WIFI_IRQ, + .platform_data = &cw1200_platform_data, + .chip_select = 0, + }, + }; + + */ + +/* An example of SDIO support in your board setup file: + + static struct cw1200_platform_data_sdio my_cw1200_platform_data = { + .ref_clk = 38400, + .have_5ghz = false, + .sdd_file = "sdd_myplatform.bin", + }; + cw1200_sdio_set_platform_data(&my_cw1200_platform_data); + + */ + +void __init cw1200_sdio_set_platform_data(struct cw1200_platform_data_sdio *pdata); #endif /* CW1200_PLAT_H_INCLUDED */ -- GitLab From 4da2a54a842db6921289e3e25b0739531a594dea Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 2 Jun 2013 11:35:32 -0400 Subject: [PATCH 0612/2900] cw1200: rename the cw1200 platform definition header My previous patch just moved the file, but it also needed to be renamed to conform to proper conventions. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200_sdio.c | 2 +- drivers/net/wireless/cw1200/cw1200_spi.c | 2 +- include/linux/platform_data/{cw1200_platform.h => net-cw1200.h} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename include/linux/platform_data/{cw1200_platform.h => net-cw1200.h} (100%) diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index 4b3148e47ee7..bb1f405315e4 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -20,7 +20,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Dmitry Tarnyagin "); diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index d8dc7c6bb96d..e58f0a5bafa9 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -25,7 +25,7 @@ #include "cw1200.h" #include "hwbus.h" -#include +#include #include "hwio.h" MODULE_AUTHOR("Solomon Peachy "); diff --git a/include/linux/platform_data/cw1200_platform.h b/include/linux/platform_data/net-cw1200.h similarity index 100% rename from include/linux/platform_data/cw1200_platform.h rename to include/linux/platform_data/net-cw1200.h -- GitLab From ec26bcc055994f7963f65197f8595f76291c6bff Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 28 May 2013 13:01:54 +0200 Subject: [PATCH 0613/2900] ath9k: advertise support for active monitor interfaces Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0536d442b068..db483b473a4c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -778,6 +778,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; + hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | -- GitLab From bda96e8c6a751d8f57a5564e18adf33f2a2d857e Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 30 May 2013 18:21:29 +0800 Subject: [PATCH 0614/2900] net, ipw2x00: remove redundant D0 power state set Pci_enable_device() will set device power state to D0, so it's no need to do it again in ipw2100_pci_init_one(). Signed-off-by: Yijing Wang Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2100.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 15920aaa5dd6..f8ab193009cd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6242,8 +6242,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, if ((val & 0x0000ff00) != 0) pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff); - pci_set_power_state(pci_dev, PCI_D0); - if (!ipw2100_hw_is_adapter_in_system(dev)) { printk(KERN_WARNING DRV_NAME "Device not found via register read.\n"); -- GitLab From 74a97755f2c2687207e3b1e9e77765b475f7e4e4 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:23 +0530 Subject: [PATCH 0615/2900] ath9k: Return early for invalid rates Process and update the internal RSSI average, which is used by ANI, after verifying that the received frame has valid rate information. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b4b758deb30e..865e043e8aa6 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -955,11 +955,11 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, if (rx_stats->rs_more) return 0; - ath9k_process_rssi(common, hw, hdr, rx_stats); - if (ath9k_process_rate(common, hw, rx_stats, rx_status)) return -EINVAL; + ath9k_process_rssi(common, hw, hdr, rx_stats); + rx_status->band = hw->conf.chandef.chan->band; rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->signal = ah->noise + rx_stats->rs_rssi; -- GitLab From 846e438f5ffec6d5508478bba2b9245a1f358df3 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:24 +0530 Subject: [PATCH 0616/2900] ath9k: Enable WoW only for AR9462 The only card with which WoW has been tested and verified is AR9462. Do not enable it for all cards since WoW is really quirky and needs to be tested properly with each chip. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 4 - .../net/wireless/ath/ath9k/ar9002_initvals.h | 14 -- drivers/net/wireless/ath/ath9k/hw.c | 9 +- drivers/net/wireless/ath/ath9k/hw.h | 9 +- drivers/net/wireless/ath/ath9k/init.c | 4 - drivers/net/wireless/ath/ath9k/main.c | 34 +--- drivers/net/wireless/ath/ath9k/wow.c | 168 +++--------------- 7 files changed, 35 insertions(+), 207 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 830daa12feb6..8dc2d089cdef 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -38,10 +38,6 @@ static int ar9002_hw_init_mode_regs(struct ath_hw *ah) else INIT_INI_ARRAY(&ah->iniPcieSerdes, ar9280PciePhy_clkreq_always_on_L1_9280); -#ifdef CONFIG_PM_SLEEP - INIT_INI_ARRAY(&ah->iniPcieSerdesWow, - ar9280PciePhy_awow); -#endif if (AR_SREV_9287_11_OR_LATER(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index beb6162cf97c..4d18c66a6790 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -925,20 +925,6 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { {0x00004044, 0x00000000}, }; -static const u32 ar9280PciePhy_awow[][2] = { - /* Addr allmodes */ - {0x00004040, 0x9248fd00}, - {0x00004040, 0x24924924}, - {0x00004040, 0xa8000019}, - {0x00004040, 0x13160820}, - {0x00004040, 0xe5980560}, - {0x00004040, 0xc01dcffd}, - {0x00004040, 0x1aaabe41}, - {0x00004040, 0xbe105554}, - {0x00004040, 0x00043007}, - {0x00004044, 0x00000000}, -}; - static const u32 ar9285Modes_9285_1_2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a263ccc00a47..6587d0503a69 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2595,13 +2595,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_RTT; } - if (AR_SREV_9280_20_OR_LATER(ah)) { - pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE | - ATH9K_HW_WOW_PATTERN_MATCH_EXACT; - - if (AR_SREV_9280(ah)) - pCap->hw_caps |= ATH9K_HW_WOW_PATTERN_MATCH_DWORD; - } + if (AR_SREV_9462(ah)) + pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE; if (AR_SREV_9300_20_OR_LATER(ah) && ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ae3034374bc4..e3c39971632a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -246,9 +246,7 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_MCI = BIT(15), ATH9K_HW_CAP_DFS = BIT(16), ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), - ATH9K_HW_WOW_PATTERN_MATCH_EXACT = BIT(18), - ATH9K_HW_WOW_PATTERN_MATCH_DWORD = BIT(19), - ATH9K_HW_CAP_PAPRD = BIT(20), + ATH9K_HW_CAP_PAPRD = BIT(18), }; /* @@ -882,9 +880,6 @@ struct ath_hw { struct ar5416IniArray iniBank6; struct ar5416IniArray iniAddac; struct ar5416IniArray iniPcieSerdes; -#ifdef CONFIG_PM_SLEEP - struct ar5416IniArray iniPcieSerdesWow; -#endif struct ar5416IniArray iniPcieSerdesLowPower; struct ar5416IniArray iniModesFastClock; struct ar5416IniArray iniAdditional; @@ -1165,8 +1160,6 @@ static inline void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) } #endif - - #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index db483b473a4c..979bde3b8f9e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -800,21 +800,17 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; #ifdef CONFIG_PM_SLEEP - if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && device_can_wakeup(sc->dev)) { - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT; hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN; hw->wiphy->wowlan.pattern_min_len = 1; hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE; - } atomic_set(&sc->wow_sleep_proc_intr, -1); atomic_set(&sc->wow_got_bmiss_intr, -1); - #endif hw->queues = 4; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a1630d1ee3c9..cc5a98b8d187 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2003,7 +2003,6 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_capabilities *pcaps = &ah->caps; int pattern_count = 0; int i, byte_cnt; u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; @@ -2073,36 +2072,9 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) /* Create Disassociate pattern mask */ - if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_EXACT) { - - if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_DWORD) { - /* - * for AR9280, because of hardware limitation, the - * first 4 bytes have to be matched for all patterns. - * the mask for disassociation and de-auth pattern - * matching need to enable the first 4 bytes. - * also the duration field needs to be filled. - */ - dis_deauth_mask[0] = 0xf0; - - /* - * fill in duration field - FIXME: what is the exact value ? - */ - dis_deauth_pattern[2] = 0xff; - dis_deauth_pattern[3] = 0xff; - } else { - dis_deauth_mask[0] = 0xfe; - } - - dis_deauth_mask[1] = 0x03; - dis_deauth_mask[2] = 0xc0; - } else { - dis_deauth_mask[0] = 0xef; - dis_deauth_mask[1] = 0x3f; - dis_deauth_mask[2] = 0x00; - dis_deauth_mask[3] = 0xfc; - } + dis_deauth_mask[0] = 0xfe; + dis_deauth_mask[1] = 0x03; + dis_deauth_mask[2] = 0xc0; ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 9f8563091bea..81c88dd606dc 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c @@ -34,17 +34,6 @@ const char *ath9k_hw_wow_event_to_string(u32 wow_event) } EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); -static void ath9k_hw_config_serdes_wow_sleep(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < ah->iniPcieSerdesWow.ia_rows; i++) - REG_WRITE(ah, INI_RA(&ah->iniPcieSerdesWow, i, 0), - INI_RA(&ah->iniPcieSerdesWow, i, 1)); - - usleep_range(1000, 1500); -} - static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -58,15 +47,8 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW)); return; - } else { - if (!AR_SREV_9300_20_OR_LATER(ah)) - REG_WRITE(ah, AR_RXDP, 0x0); } - /* AR9280 WoW has sleep issue, do not set it to sleep */ - if (AR_SREV_9280_20(ah)) - return; - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); } @@ -84,27 +66,16 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) /* set the transmit buffer */ ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); - - if (!(AR_SREV_9300_20_OR_LATER(ah))) - ctl[0] += (KAL_ANTENNA_MODE << 25); - ctl[1] = 0; ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */ ctl[4] = 0; ctl[7] = (ah->txchainmask) << 2; - - if (AR_SREV_9300_20_OR_LATER(ah)) - ctl[2] = 0xf << 16; /* tx_tries 0 */ - else - ctl[2] = 0x7 << 16; /* tx_tries 0 */ - + ctl[2] = 0xf << 16; /* tx_tries 0 */ for (i = 0; i < KAL_NUM_DESC_WORDS; i++) REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); - /* for AR9300 family 13 descriptor words */ - if (AR_SREV_9300_20_OR_LATER(ah)) - REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); + REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) | (KAL_TO_DS << 8) | (KAL_DURATION_ID << 16); @@ -183,9 +154,6 @@ void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT); - if (!AR_SREV_9285_12_OR_LATER(ah)) - return; - if (pattern_count < 4) { /* Pattern 0-3 uses AR_WOW_LENGTH1 register */ set = (pattern_len & AR_WOW_LENGTH_MAX) << @@ -207,6 +175,7 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) { u32 wow_status = 0; u32 val = 0, rval; + /* * read the WoW status register to know * the wakeup reason @@ -223,19 +192,14 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) val &= ah->wow_event_mask; if (val) { - if (val & AR_WOW_MAGIC_PAT_FOUND) wow_status |= AH_WOW_MAGIC_PATTERN_EN; - if (AR_WOW_PATTERN_FOUND(val)) wow_status |= AH_WOW_USER_PATTERN_EN; - if (val & AR_WOW_KEEP_ALIVE_FAIL) wow_status |= AH_WOW_LINK_CHANGE; - if (val & AR_WOW_BEACON_FAIL) wow_status |= AH_WOW_BEACON_MISS; - } /* @@ -254,17 +218,6 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) REG_WRITE(ah, AR_WOW_PATTERN, AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN))); - /* - * tie reset register for AR9002 family of chipsets - * NB: not tieing it back might have some repurcussions. - */ - - if (!AR_SREV_9300_20_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_WA, AR_WA_UNTIE_RESET_EN | - AR_WA_POR_SHORT | AR_WA_RESET_EN); - } - - /* * restore the beacon threshold to init value */ @@ -277,8 +230,7 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) * reset to our Chip's Power On Reset so that any PCI-E * reset from the bus will not reset our chip */ - - if (AR_SREV_9280_20_OR_LATER(ah) && ah->is_pciexpress) + if (ah->is_pciexpress) ath9k_hw_configpcipowersave(ah, false); ah->wow_event_mask = 0; @@ -298,7 +250,6 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) * are from the 'pattern_enable' in this function and * 'pattern_count' of ath9k_hw_wow_apply_pattern() */ - wow_event_mask = ah->wow_event_mask; /* @@ -306,50 +257,15 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) * WOW sleep, we do want the Reset from the PCI-E to disturb * our hw state */ - if (ah->is_pciexpress) { - /* * we need to untie the internal POR (power-on-reset) * to the external PCI-E reset. We also need to tie * the PCI-E Phy reset to the PCI-E reset. */ - - if (AR_SREV_9300_20_OR_LATER(ah)) { - set = AR_WA_RESET_EN | AR_WA_POR_SHORT; - clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; - REG_RMW(ah, AR_WA, set, clr); - } else { - if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) - set = AR9285_WA_DEFAULT; - else - set = AR9280_WA_DEFAULT; - - /* - * In AR9280 and AR9285, bit 14 in WA register - * (disable L1) should only be set when device - * enters D3 state and be cleared when device - * comes back to D0 - */ - - if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) - set |= AR_WA_D3_L1_DISABLE; - - clr = AR_WA_UNTIE_RESET_EN; - set |= AR_WA_RESET_EN | AR_WA_POR_SHORT; - REG_RMW(ah, AR_WA, set, clr); - - /* - * for WoW sleep, we reprogram the SerDes so that the - * PLL and CLK REQ are both enabled. This uses more - * power but otherwise WoW sleep is unstable and the - * chip may disappear. - */ - - if (AR_SREV_9285_12_OR_LATER(ah)) - ath9k_hw_config_serdes_wow_sleep(ah); - - } + set = AR_WA_RESET_EN | AR_WA_POR_SHORT; + clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE; + REG_RMW(ah, AR_WA, set, clr); } /* @@ -378,7 +294,6 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) * Program default values for pattern backoff, aifs/slot/KAL count, * beacon miss timeout, KAL timeout, etc. */ - set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF); REG_SET_BIT(ah, AR_WOW_PATTERN, set); @@ -398,7 +313,7 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) /* * Keep alive timo in ms except AR9280 */ - if (!pattern_enable || AR_SREV_9280(ah)) + if (!pattern_enable) set = AR_WOW_KEEP_ALIVE_NEVER; else set = KAL_TIMEOUT * 32; @@ -420,7 +335,6 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) /* * Configure MAC WoW Registers */ - set = 0; /* Send keep alive timeouts anyway */ clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; @@ -430,16 +344,9 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) else set = AR_WOW_KEEP_ALIVE_FAIL_DIS; - /* - * FIXME: For now disable keep alive frame - * failure. This seems to sometimes trigger - * unnecessary wake up with AR9485 chipsets. - */ set = AR_WOW_KEEP_ALIVE_FAIL_DIS; - REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr); - /* * we are relying on a bmiss failure. ensure we have * enough threshold to prevent false positives @@ -473,14 +380,8 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) set |= AR_WOW_MAC_INTR_EN; REG_RMW(ah, AR_WOW_PATTERN, set, clr); - /* - * For AR9285 and later version of chipsets - * enable WoW pattern match for packets less - * than 256 bytes for all patterns - */ - if (AR_SREV_9285_12_OR_LATER(ah)) - REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, - AR_WOW_PATTERN_SUPPORTED); + REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, + AR_WOW_PATTERN_SUPPORTED); /* * Set the power states appropriately and enable PME @@ -488,43 +389,32 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) clr = 0; set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA; - /* - * This is needed for AR9300 chipsets to wake-up - * the host. - */ - if (AR_SREV_9300_20_OR_LATER(ah)) - clr = AR_PCIE_PM_CTRL_ENA; + clr = AR_PCIE_PM_CTRL_ENA; REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { - /* - * this is needed to prevent the chip waking up - * the host within 3-4 seconds with certain - * platform/BIOS. The fix is to enable - * D1 & D3 to match original definition and - * also match the OTP value. Anyway this - * is more related to SW WOW. - */ - clr = AR_PMCTRL_PWR_STATE_D1D3; - REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); - - set = AR_PMCTRL_PWR_STATE_D1D3_REAL; - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); - } - + /* + * this is needed to prevent the chip waking up + * the host within 3-4 seconds with certain + * platform/BIOS. The fix is to enable + * D1 & D3 to match original definition and + * also match the OTP value. Anyway this + * is more related to SW WOW. + */ + clr = AR_PMCTRL_PWR_STATE_D1D3; + REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); + set = AR_PMCTRL_PWR_STATE_D1D3_REAL; + REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); - if (AR_SREV_9300_20_OR_LATER(ah)) { - /* to bring down WOW power low margin */ - set = BIT(13); - REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); - /* HW WoW */ - clr = BIT(5); - REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); - } + /* to bring down WOW power low margin */ + set = BIT(13); + REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set); + /* HW WoW */ + clr = BIT(5); + REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr); ath9k_hw_set_powermode_wow_sleep(ah); ah->wow_event_mask = wow_event_mask; -- GitLab From 380013fc9442f65d5b898fc168e9994049ea2937 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:25 +0530 Subject: [PATCH 0617/2900] ath9k: Remove unused structure ath_dbg_bb_mac_samp Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.h | 39 -------------------------- 1 file changed, 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 62da19c6f4e0..9719378f7c73 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -251,45 +251,6 @@ struct ath_stats { u32 reset[__RESET_TYPE_MAX]; }; -#define ATH_DBG_MAX_SAMPLES 10 -struct ath_dbg_bb_mac_samp { - u32 dma_dbg_reg_vals[ATH9K_NUM_DMA_DEBUG_REGS]; - u32 pcu_obs, pcu_cr, noise; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool isok; - u8 rts_fail_cnt; - u8 data_fail_cnt; - u8 rateindex; - u8 qid; - u8 tid; - u32 ba_low; - u32 ba_high; - } ts[ATH_DBG_MAX_SAMPLES]; - struct { - u64 jiffies; - int8_t rssi_ctl0; - int8_t rssi_ctl1; - int8_t rssi_ctl2; - int8_t rssi_ext0; - int8_t rssi_ext1; - int8_t rssi_ext2; - int8_t rssi; - bool is_mybeacon; - u8 antenna; - u8 rate; - } rs[ATH_DBG_MAX_SAMPLES]; - struct ath_cycle_counters cc; - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; -}; - struct ath9k_debug { struct dentry *debugfs_phy; u32 regidx; -- GitLab From e323300d9741d44e6543ece3659671742f93acba Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:26 +0530 Subject: [PATCH 0618/2900] ath9k: Simplify ANI initialization The check "enable_ani" is not required since it is always set to true and the logic for disabling/enabling ANI via debugfs is done at a higher layer. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 13 +++++-------- drivers/net/wireless/ath/ath9k/ani.h | 4 ---- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 ++---- drivers/net/wireless/ath/ath9k/hw.c | 4 +--- drivers/net/wireless/ath/ath9k/hw.h | 2 -- drivers/net/wireless/ath/ath9k/link.c | 8 ++------ 6 files changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 7ecd40f07a74..734e72db039a 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -118,7 +118,7 @@ static void ath9k_ani_restart(struct ath_hw *ah) { struct ar5416AniState *aniState; - if (!DO_ANI(ah)) + if (!ah->curchan) return; aniState = &ah->curchan->ani; @@ -195,7 +195,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) { struct ar5416AniState *aniState; - if (!DO_ANI(ah)) + if (!ah->curchan) return; aniState = &ah->curchan->ani; @@ -251,7 +251,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) { struct ar5416AniState *aniState; - if (!DO_ANI(ah)) + if (!ah->curchan) return; aniState = &ah->curchan->ani; @@ -297,7 +297,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) struct ath_common *common = ath9k_hw_common(ah); int ofdm_nil, cck_nil; - if (!DO_ANI(ah)) + if (!ah->curchan) return; BUG_ON(aniState == NULL); @@ -415,7 +415,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) struct ath_common *common = ath9k_hw_common(ah); u32 ofdmPhyErrRate, cckPhyErrRate; - if (!DO_ANI(ah)) + if (!ah->curchan) return; aniState = &ah->curchan->ani; @@ -524,9 +524,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah) ah->aniperiod = ATH9K_ANI_PERIOD; ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL; - if (ah->config.enable_ani) - ah->proc_phyerr |= HAL_PROCESS_ANI; - ath9k_ani_restart(ah); ath9k_enable_mib_counters(ah); } diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index dddb1361039a..07079f28f830 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -17,10 +17,6 @@ #ifndef ANI_H #define ANI_H -#define HAL_PROCESS_ANI 0x00000001 - -#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan) - #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) /* units are errors per second */ diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 2a67b57c3ecb..34869c2405aa 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -814,8 +814,7 @@ void ath9k_htc_ani_work(struct work_struct *work) } /* Verify whether we must check ANI */ - if (ah->config.enable_ani && - (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -845,8 +844,7 @@ void ath9k_htc_ani_work(struct work_struct *work) * short calibration and long calibration. */ cal_interval = ATH_LONG_CALINTERVAL; - if (ah->config.enable_ani) - cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); + cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); if (!common->ani.caldone) cal_interval = min(cal_interval, (u32)short_cal_interval); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6587d0503a69..a13f6cea2ba7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -452,7 +452,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.pcie_clock_req = 0; ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; - ah->config.enable_ani = true; for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { ah->config.spurchans[i][0] = AR_NO_SPUR; @@ -549,8 +548,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - if (ah->config.enable_ani) - ath9k_hw_ani_init(ah); + ath9k_hw_ani_init(ah); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e3c39971632a..301b19ed7664 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -289,7 +289,6 @@ struct ath9k_ops_config { u32 ofdm_trig_high; u32 cck_trig_high; u32 cck_trig_low; - u32 enable_ani; u32 enable_paprd; int serialize_regmode; bool rx_intr_mitigation; @@ -852,7 +851,6 @@ struct ath_hw { u32 globaltxtimeout; /* ANI */ - u32 proc_phyerr; u32 aniperiod; enum ath9k_ani_cmd ani_function; u32 ani_skip_count; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index cc422a4dfa17..fff5d3ccc663 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -390,9 +390,7 @@ void ath_ani_calibrate(unsigned long data) } /* Verify whether we must check ANI */ - if (sc->sc_ah->config.enable_ani - && (timestamp - common->ani.checkani_timer) >= - ah->config.ani_poll_interval) { + if ((timestamp - common->ani.checkani_timer) >= ah->config.ani_poll_interval) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -427,9 +425,7 @@ void ath_ani_calibrate(unsigned long data) * short calibration and long calibration. */ cal_interval = ATH_LONG_CALINTERVAL; - if (sc->sc_ah->config.enable_ani) - cal_interval = min(cal_interval, - (u32)ah->config.ani_poll_interval); + cal_interval = min(cal_interval, (u32)ah->config.ani_poll_interval); if (!common->ani.caldone) cal_interval = min(cal_interval, (u32)short_cal_interval); -- GitLab From 4f4395c692fd74f6ebfb99892e5da3842f70d4c3 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:27 +0530 Subject: [PATCH 0619/2900] ath9k: Set ofdmWeakSigDetect directly The macros ATH9K_ANI_USE_OFDM_WEAK_SIG can be removed. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 6 +----- drivers/net/wireless/ath/ath9k/ani.h | 6 +----- drivers/net/wireless/ath/ath9k/ar5008_phy.c | 2 +- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 734e72db039a..ba0bad6728bb 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -505,14 +505,10 @@ void ath9k_hw_ani_init(struct ath_hw *ah) struct ar5416AniState *ani = &chan->ani; ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; - ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false; - ani->ofdmsTurn = true; - - ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; + ani->ofdmWeakSigDetect = true; ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; } diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 07079f28f830..c585e053ce68 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -34,11 +34,7 @@ #define ATH9K_ANI_CCK_TRIG_LOW 300 #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 -#define ATH9K_ANI_USE_OFDM_WEAK_SIG true -#define ATH9K_ANI_CCK_WEAK_SIG_THR false - #define ATH9K_ANI_SPUR_IMMUNE_LVL 3 - #define ATH9K_ANI_FIRSTEP_LVL 2 #define ATH9K_ANI_RSSI_THR_HIGH 40 @@ -107,7 +103,7 @@ struct ar5416AniState { u8 mrcCCK; u8 spurImmunityLevel; u8 firstepLevel; - u8 ofdmWeakSigDetect; + bool ofdmWeakSigDetect; u32 listenTime; u32 ofdmPhyErrCount; u32 cckPhyErrCount; diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 391da5ad6a99..92b79a2a003d 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -1251,7 +1251,7 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) /* these levels just got reset to defaults by the INI */ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; + aniState->ofdmWeakSigDetect = true; aniState->mrcCCK = false; /* not available on pre AR9003 */ } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 2bf6548dd143..94b22cb84535 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1213,7 +1213,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) /* these levels just got reset to defaults by the INI */ aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG; + aniState->ofdmWeakSigDetect = true; aniState->mrcCCK = true; } -- GitLab From 6e4d291eec82c682d82d02cd275a6ec511f9b203 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:28 +0530 Subject: [PATCH 0620/2900] ath9k: Print ANI statistics in debugfs Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.h | 2 - drivers/net/wireless/ath/ath9k/debug.c | 81 ++++++++++++++++++++------ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index c585e053ce68..78b9fa9f6455 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -111,8 +111,6 @@ struct ar5416AniState { }; struct ar5416Stats { - u32 ast_ani_niup; - u32 ast_ani_nidown; u32 ast_ani_spurup; u32 ast_ani_spurdown; u32 ast_ani_ofdmon; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index fc96ad3a135b..7852f6e59964 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -173,25 +173,69 @@ static const struct file_operations fops_rx_chainmask = { .llseek = default_llseek, }; -static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf, +static ssize_t read_file_ani(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - char buf[32]; - unsigned int len; + struct ath_hw *ah = sc->sc_ah; + unsigned int len = 0, size = 1024; + ssize_t retval = 0; + char *buf; - len = sprintf(buf, "%d\n", common->disable_ani); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + if (common->disable_ani) { + len += snprintf(buf + len, size - len, "%s: %s\n", + "ANI", "DISABLED"); + goto exit; + } + + len += snprintf(buf + len, size - len, "%15s: %s\n", + "ANI", "ENABLED"); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "ANI RESET", ah->stats.ast_ani_reset); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "SPUR UP", ah->stats.ast_ani_spurup); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "SPUR DOWN", ah->stats.ast_ani_spurup); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "MRC-CCK ON", ah->stats.ast_ani_ccklow); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "MRC-CCK OFF", ah->stats.ast_ani_cckhigh); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "FIR-STEP UP", ah->stats.ast_ani_stepup); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "FIR-STEP DOWN", ah->stats.ast_ani_stepdown); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs); + len += snprintf(buf + len, size - len, "%15s: %u\n", + "CCK ERRORS", ah->stats.ast_ani_cckerrs); +exit: + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; } -static ssize_t write_file_disable_ani(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) +static ssize_t write_file_ani(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - unsigned long disable_ani; + unsigned long ani; char buf[32]; ssize_t len; @@ -200,12 +244,15 @@ static ssize_t write_file_disable_ani(struct file *file, return -EFAULT; buf[len] = '\0'; - if (strict_strtoul(buf, 0, &disable_ani)) + if (strict_strtoul(buf, 0, &ani)) + return -EINVAL; + + if (ani < 0 || ani > 1) return -EINVAL; - common->disable_ani = !!disable_ani; + common->disable_ani = !ani; - if (disable_ani) { + if (common->disable_ani) { clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); ath_stop_ani(sc); } else { @@ -215,9 +262,9 @@ static ssize_t write_file_disable_ani(struct file *file, return count; } -static const struct file_operations fops_disable_ani = { - .read = read_file_disable_ani, - .write = write_file_disable_ani, +static const struct file_operations fops_ani = { + .read = read_file_ani, + .write = write_file_ani, .open = simple_open, .owner = THIS_MODULE, .llseek = default_llseek, @@ -1719,8 +1766,8 @@ int ath9k_init_debug(struct ath_hw *ah) sc->debug.debugfs_phy, sc, &fops_rx_chainmask); debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_tx_chainmask); - debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR, - sc->debug.debugfs_phy, sc, &fops_disable_ani); + debugfs_create_file("ani", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_ani); debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->config.enable_paprd); debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, -- GitLab From c24bd3620c50cc8f1d13935c95003f41339a748d Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 3 Jun 2013 09:19:29 +0530 Subject: [PATCH 0621/2900] ath9k: Do not maintain ANI state per-channel ANI state can be maintained globally instead of per-channel. This reduces memory usage and since default values are used during a scan run, per-channel state is not required. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 40 +++++++++------------ drivers/net/wireless/ath/ath9k/ar5008_phy.c | 4 +-- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 +-- drivers/net/wireless/ath/ath9k/hw.h | 2 +- 4 files changed, 22 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index ba0bad6728bb..e91725bf401c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -121,7 +121,7 @@ static void ath9k_ani_restart(struct ath_hw *ah) if (!ah->curchan) return; - aniState = &ah->curchan->ani; + aniState = &ah->ani; aniState->listenTime = 0; ENABLE_REGWRITE_BUFFER(ah); @@ -143,7 +143,7 @@ static void ath9k_ani_restart(struct ath_hw *ah) static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, bool scan) { - struct ar5416AniState *aniState = &ah->curchan->ani; + struct ar5416AniState *aniState = &ah->ani; struct ath_common *common = ath9k_hw_common(ah); const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; @@ -198,7 +198,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) if (!ah->curchan) return; - aniState = &ah->curchan->ani; + aniState = &ah->ani; if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false); @@ -210,7 +210,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, bool scan) { - struct ar5416AniState *aniState = &ah->curchan->ani; + struct ar5416AniState *aniState = &ah->ani; struct ath_common *common = ath9k_hw_common(ah); const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; @@ -254,7 +254,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) if (!ah->curchan) return; - aniState = &ah->curchan->ani; + aniState = &ah->ani; if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1, @@ -269,7 +269,7 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) { struct ar5416AniState *aniState; - aniState = &ah->curchan->ani; + aniState = &ah->ani; /* lower OFDM noise immunity */ if (aniState->ofdmNoiseImmunityLevel > 0 && @@ -292,7 +292,7 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) */ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) { - struct ar5416AniState *aniState = &ah->curchan->ani; + struct ar5416AniState *aniState = &ah->ani; struct ath9k_channel *chan = ah->curchan; struct ath_common *common = ath9k_hw_common(ah); int ofdm_nil, cck_nil; @@ -380,7 +380,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - struct ar5416AniState *aniState = &ah->curchan->ani; + struct ar5416AniState *aniState = &ah->ani; u32 phyCnt1, phyCnt2; int32_t listenTime; @@ -418,7 +418,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) if (!ah->curchan) return; - aniState = &ah->curchan->ani; + aniState = &ah->ani; if (!ath9k_hw_ani_read_counters(ah)) return; @@ -490,28 +490,22 @@ EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); void ath9k_hw_ani_init(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); - int i; + struct ar5416AniState *ani = &ah->ani; ath_dbg(common, ANI, "Initialize ANI\n"); ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; - ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH; ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW; - for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { - struct ath9k_channel *chan = &ah->channels[i]; - struct ar5416AniState *ani = &chan->ani; - - ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; - ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false; - ani->ofdmsTurn = true; - ani->ofdmWeakSigDetect = true; - ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; - ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; - } + ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; + ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL; + ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false; + ani->ofdmsTurn = true; + ani->ofdmWeakSigDetect = true; + ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; + ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL; /* * since we expect some ongoing maintenance on the tables, let's sanity diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 92b79a2a003d..d1acfe98918a 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -931,7 +931,7 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; - struct ar5416AniState *aniState = &chan->ani; + struct ar5416AniState *aniState = &ah->ani; s32 value, value2; switch (cmd & ah->ani_function) { @@ -1207,7 +1207,7 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; - struct ar5416AniState *aniState = &chan->ani; + struct ar5416AniState *aniState = &ah->ani; struct ath9k_ani_default *iniDef; u32 val; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 94b22cb84535..0d053503b8bf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -904,7 +904,7 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; - struct ar5416AniState *aniState = &chan->ani; + struct ar5416AniState *aniState = &ah->ani; s32 value, value2; switch (cmd & ah->ani_function) { @@ -1172,7 +1172,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) struct ath9k_ani_default *iniDef; u32 val; - aniState = &ah->curchan->ani; + aniState = &ah->ani; iniDef = &aniState->iniDef; ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 301b19ed7664..7d259b7dc254 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -420,7 +420,6 @@ struct ath9k_hw_cal_data { struct ath9k_channel { struct ieee80211_channel *chan; - struct ar5416AniState ani; u16 channel; u32 channelFlags; u32 chanmode; @@ -854,6 +853,7 @@ struct ath_hw { u32 aniperiod; enum ath9k_ani_cmd ani_function; u32 ani_skip_count; + struct ar5416AniState ani; #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT struct ath_btcoex_hw btcoex_hw; -- GitLab From 99e94940697adec4f84758adb2db71f4a82c7ba5 Mon Sep 17 00:00:00 2001 From: John Greene Date: Mon, 3 Jun 2013 09:47:39 -0400 Subject: [PATCH 0622/2900] brcmsmac: Reduce log spam in heavy tx, make err print in debug Move message to debug mode to reduce log spam under heavy tx (iperf) load. This message prints in ht debug mode only: brcms_c_ampdu_dotxstatus_complete: Pkt tx suppressed, illegal channel possibly 153 Signed-off-by: John Greene Acked-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 1585cc5bf866..bd982856d385 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -900,7 +900,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, if (supr_status) { update_rate = false; if (supr_status == TX_STATUS_SUPR_BADCH) { - brcms_err(wlc->hw->d11core, + brcms_dbg_ht(wlc->hw->d11core, "%s: Pkt tx suppressed, illegal channel possibly %d\n", __func__, CHSPEC_CHANNEL( wlc->default_bss->chanspec)); -- GitLab From cbe8933143a62e0ced2d48183cdbdbdc38659338 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 31 May 2013 16:09:06 +0100 Subject: [PATCH 0623/2900] ARM: ux500: Enable HIGHMEM in the u8500 defconfig In order to utilise all of the memory located on ux500 based devices we have to enable HIGHMEM. Without it the kernel truncates memory down to what's left after the PAGE_OFFSET has been applied, which doesn't leave an awful lot, especially if we're running large rootfs' such as full Linux desktop distributions or Android. Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/configs/u8500_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index b2326b019b83..a0025dc13021 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -1,3 +1,4 @@ +CONFIG_HIGHMEM=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_NO_HZ=y -- GitLab From d6d23de2786edca61fb9813ff7cdc7d2543d08a7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 4 Jun 2013 12:15:42 +0200 Subject: [PATCH 0624/2900] mac80211: add a tx control flag to indicate PS-Poll/uAPSD response Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- include/net/mac80211.h | 3 +++ net/mac80211/sta_info.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1f0014bd4d87..cb37f82d8d09 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -460,6 +460,8 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it * would be fragmented by size (this is optional, only used for * monitor injection). + * @IEEE80211_TX_CTL_PS_RESPONSE: This frame is a response to a poll + * frame (PS-Poll or uAPSD). * * Note: If you have to add new flags to the enumeration, then don't * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. @@ -495,6 +497,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STATUS_EOSP = BIT(28), IEEE80211_TX_CTL_USE_MINRATE = BIT(29), IEEE80211_TX_CTL_DONTFRAG = BIT(30), + IEEE80211_TX_CTL_PS_RESPONSE = BIT(31), }; #define IEEE80211_TX_CTL_STBC_SHIFT 23 diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a04c5671d7fd..b4297982d34a 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1132,6 +1132,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, * ends the poll/service period. */ info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | + IEEE80211_TX_CTL_PS_RESPONSE | IEEE80211_TX_STATUS_EOSP | IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -1269,7 +1270,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, * STA may still remain is PS mode after this frame * exchange. */ - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; + info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | + IEEE80211_TX_CTL_PS_RESPONSE; /* * Use MoreData flag to indicate whether there are -- GitLab From 9c90a9f64c21b0a3983655c9c08cf98489057a43 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 4 Jun 2013 12:46:03 +0200 Subject: [PATCH 0625/2900] nl80211: remove bogus genlmsg_end() error checking genlmsg_end() can't return an error since it returns the skb length so remove checks treating the return value as an error code. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7ee9af3283a8..ce949e38178c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9848,7 +9848,6 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct sk_buff *msg; void *hdr; - int err; u32 nlportid = ACCESS_ONCE(wdev->ap_unexpected_nlportid); if (!nlportid) @@ -9869,12 +9868,7 @@ static bool __nl80211_unexpected_frame(struct net_device *dev, u8 cmd, nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) goto nla_put_failure; - err = genlmsg_end(msg, hdr); - if (err < 0) { - nlmsg_free(msg); - return true; - } - + genlmsg_end(msg, hdr); genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); return true; @@ -10317,10 +10311,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, if (nl80211_send_chandef(msg, chandef)) goto nla_put_failure; - if (genlmsg_end(msg, hdr) < 0) { - nlmsg_free(msg); - return; - } + genlmsg_end(msg, hdr); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, gfp); @@ -10386,7 +10377,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct sk_buff *msg; void *hdr; - int err; trace_cfg80211_probe_status(dev, addr, cookie, acked); @@ -10408,11 +10398,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr, (acked && nla_put_flag(msg, NL80211_ATTR_ACK))) goto nla_put_failure; - err = genlmsg_end(msg, hdr); - if (err < 0) { - nlmsg_free(msg); - return; - } + genlmsg_end(msg, hdr); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, gfp); @@ -10478,7 +10464,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct sk_buff *msg; void *hdr; - int err, size = 200; + int size = 200; trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup); @@ -10564,9 +10550,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, nla_nest_end(msg, reasons); } - err = genlmsg_end(msg, hdr); - if (err < 0) - goto free_msg; + genlmsg_end(msg, hdr); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, gfp); @@ -10586,7 +10570,6 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct sk_buff *msg; void *hdr; - int err; trace_cfg80211_tdls_oper_request(wdev->wiphy, dev, peer, oper, reason_code); @@ -10609,11 +10592,7 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) goto nla_put_failure; - err = genlmsg_end(msg, hdr); - if (err < 0) { - nlmsg_free(msg); - return; - } + genlmsg_end(msg, hdr); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, gfp); @@ -10671,7 +10650,6 @@ void cfg80211_ft_event(struct net_device *netdev, struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct sk_buff *msg; void *hdr; - int err; trace_cfg80211_ft_event(wiphy, netdev, ft_event); @@ -10697,11 +10675,7 @@ void cfg80211_ft_event(struct net_device *netdev, nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, ft_event->ric_ies); - err = genlmsg_end(msg, hdr); - if (err < 0) { - nlmsg_free(msg); - return; - } + genlmsg_end(msg, hdr); genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); -- GitLab From ff40b425f04144771920b79672d6691910c7def7 Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Tue, 4 Jun 2013 12:44:52 +0200 Subject: [PATCH 0626/2900] mac80211: set IEEE80211_TX_CTL_REQ_TX_STATUS on nullframes The connection monitor needs to know the tx status of nullframes to work properly. Signed-off-by: Pontus Fuchs Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f44f4caa69ee..9950e13f641b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -880,6 +880,10 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | IEEE80211_TX_INTFL_OFFCHAN_TX_OK; + + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL)) IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; -- GitLab From 6ff57cf88807dd81300b5b9c623dc5eb6422b9f6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 May 2013 00:55:00 +0200 Subject: [PATCH 0627/2900] cfg80211/mac80211: clean up cfg80211 SME APIs Do some cleanups in the cfg80211 SME APIs, which are only used by mac80211. Most of these functions get a frame passed, and there isn't really any reason to export multiple functions as cfg80211 can check the frame type instead, do that. Additionally, the API functions have confusing names like cfg80211_send_...() which was meant to indicate that it sends an event to userspace, but gets a bit confusing when there's both TX and RX and they're not all clearly labeled. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 91 +++++++++++++++++------------------------- net/mac80211/mlme.c | 44 ++++++++++---------- net/mac80211/rx.c | 26 +++++------- net/wireless/mlme.c | 86 ++++++++++++++++++++++++--------------- net/wireless/nl80211.c | 30 ++++++-------- net/wireless/trace.h | 46 +++++++++++++++------ 6 files changed, 170 insertions(+), 153 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6169fca216b4..195330d4ef34 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3432,59 +3432,66 @@ void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); /** - * cfg80211_send_rx_auth - notification of processed authentication + * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame * @dev: network device * @buf: authentication frame (header + body) * @len: length of the frame data * - * This function is called whenever an authentication has been processed in - * station mode. The driver is required to call either this function or - * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth() - * call. This function may sleep. The caller must hold the corresponding wdev's - * mutex. + * This function is called whenever an authentication, disassociation or + * deauthentication frame has been received and processed in station mode. + * After being asked to authenticate via cfg80211_ops::auth() the driver must + * call either this function or cfg80211_auth_timeout(). + * After being asked to associate via cfg80211_ops::assoc() the driver must + * call either this function or cfg80211_auth_timeout(). + * While connected, the driver must calls this for received and processed + * disassociation and deauthentication frames. If the frame couldn't be used + * because it was unprotected, the driver must call the function + * cfg80211_rx_unprot_mlme_mgmt() instead. + * + * This function may sleep. The caller must hold the corresponding wdev's mutex. */ -void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); +void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len); /** - * cfg80211_send_auth_timeout - notification of timed out authentication + * cfg80211_auth_timeout - notification of timed out authentication * @dev: network device * @addr: The MAC address of the device with which the authentication timed out * * This function may sleep. The caller must hold the corresponding wdev's * mutex. */ -void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); +void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr); /** - * cfg80211_send_rx_assoc - notification of processed association + * cfg80211_rx_assoc_resp - notification of processed association response * @dev: network device - * @bss: the BSS struct association was requested for, the struct reference - * is owned by cfg80211 after this call - * @buf: (re)association response frame (header + body) + * @bss: the BSS that association was requested with, ownership of the pointer + * moves to cfg80211 in this call + * @buf: authentication frame (header + body) * @len: length of the frame data * - * This function is called whenever a (re)association response has been - * processed in station mode. The driver is required to call either this - * function or cfg80211_send_assoc_timeout() to indicate the result of - * cfg80211_ops::assoc() call. This function may sleep. The caller must hold - * the corresponding wdev's mutex. + * After being asked to associate via cfg80211_ops::assoc() the driver must + * call either this function or cfg80211_auth_timeout(). + * + * This function may sleep. The caller must hold the corresponding wdev's mutex. */ -void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, +void cfg80211_rx_assoc_resp(struct net_device *dev, + struct cfg80211_bss *bss, const u8 *buf, size_t len); /** - * cfg80211_send_assoc_timeout - notification of timed out association + * cfg80211_assoc_timeout - notification of timed out association * @dev: network device * @addr: The MAC address of the device with which the association timed out * * This function may sleep. The caller must hold the corresponding wdev's mutex. */ -void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); +void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr); /** - * cfg80211_send_deauth - notification of processed deauthentication + * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame * @dev: network device - * @buf: deauthentication frame (header + body) + * @buf: 802.11 frame (header + body) * @len: length of the frame data * * This function is called whenever deauthentication has been processed in @@ -3492,46 +3499,20 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); * locally generated ones. This function may sleep. The caller must hold the * corresponding wdev's mutex. */ -void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); +void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len); /** - * cfg80211_send_disassoc - notification of processed disassociation - * @dev: network device - * @buf: disassociation response frame (header + body) - * @len: length of the frame data - * - * This function is called whenever disassociation has been processed in - * station mode. This includes both received disassociation frames and locally - * generated ones. This function may sleep. The caller must hold the - * corresponding wdev's mutex. - */ -void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); - -/** - * cfg80211_send_unprot_deauth - notification of unprotected deauthentication + * cfg80211_rx_unprot_mlme_mgmt - notification of unprotected mlme mgmt frame * @dev: network device * @buf: deauthentication frame (header + body) * @len: length of the frame data * - * This function is called whenever a received Deauthentication frame has been - * dropped in station mode because of MFP being used but the Deauthentication - * frame was not protected. This function may sleep. - */ -void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, - size_t len); - -/** - * cfg80211_send_unprot_disassoc - notification of unprotected disassociation - * @dev: network device - * @buf: disassociation frame (header + body) - * @len: length of the frame data - * - * This function is called whenever a received Disassociation frame has been - * dropped in station mode because of MFP being used but the Disassociation + * This function is called whenever a received deauthentication or dissassoc + * frame has been dropped in station mode because of MFP being used but the * frame was not protected. This function may sleep. */ -void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, - size_t len); +void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, + const u8 *buf, size_t len); /** * cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9950e13f641b..df8170a80a56 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2155,7 +2155,8 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA); - cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); sdata_unlock(sdata); } @@ -2302,7 +2303,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, sdata_info(sdata, "%pM denied authentication (status %d)\n", mgmt->sa, status_code); ieee80211_destroy_auth_data(sdata, false); - cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); return; } @@ -2337,7 +2338,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, * Report auth frame to user space for processing since another * round of Authentication frames is still needed. */ - cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); return; } @@ -2354,7 +2355,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, } mutex_unlock(&sdata->local->sta_mtx); - cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); + cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); return; out_err: mutex_unlock(&sdata->local->sta_mtx); @@ -2387,7 +2388,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len); + cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); } @@ -2413,7 +2414,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); - cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len); + cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); } static void ieee80211_get_rates(struct ieee80211_supported_band *sband, @@ -2711,7 +2712,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* oops -- internal error -- send timeout for now */ ieee80211_destroy_assoc_data(sdata, false); cfg80211_put_bss(sdata->local->hw.wiphy, bss); - cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); + cfg80211_assoc_timeout(sdata->dev, mgmt->bssid); return; } sdata_info(sdata, "associated\n"); @@ -2724,7 +2725,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_destroy_assoc_data(sdata, true); } - cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len); + cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -3117,8 +3118,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DEAUTH_LEAVING, true, deauth_buf); - cfg80211_send_deauth(sdata->dev, deauth_buf, - sizeof(deauth_buf)); + cfg80211_tx_mlme_mgmt(sdata->dev, deauth_buf, + sizeof(deauth_buf)); return; } @@ -3236,7 +3237,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, tx, frame_buf); - cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); } static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) @@ -3427,7 +3429,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ieee80211_destroy_auth_data(sdata, false); - cfg80211_send_auth_timeout(sdata->dev, bssid); + cfg80211_auth_timeout(sdata->dev, bssid); } } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started) run_again(sdata, ifmgd->auth_data->timeout); @@ -3443,7 +3445,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ieee80211_destroy_assoc_data(sdata, false); - cfg80211_send_assoc_timeout(sdata->dev, bssid); + cfg80211_assoc_timeout(sdata->dev, bssid); } } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) run_again(sdata, ifmgd->assoc_data->timeout); @@ -3992,8 +3994,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, WLAN_REASON_UNSPECIFIED, false, frame_buf); - cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + sizeof(frame_buf)); } sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); @@ -4055,8 +4057,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, WLAN_REASON_UNSPECIFIED, false, frame_buf); - cfg80211_send_deauth(sdata->dev, frame_buf, - sizeof(frame_buf)); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + sizeof(frame_buf)); } if (ifmgd->auth_data && !ifmgd->auth_data->done) { @@ -4309,8 +4311,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, out: if (report_frame) - cfg80211_send_deauth(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); return 0; } @@ -4340,8 +4342,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, req->reason_code, !req->local_state_change, frame_buf); - cfg80211_send_disassoc(sdata->dev, frame_buf, - IEEE80211_DEAUTH_FRAME_LEN); + cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, + IEEE80211_DEAUTH_FRAME_LEN); return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bdd7b4a719e9..23dbcfc69b3b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1747,27 +1747,21 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) if (unlikely(!ieee80211_has_protected(fc) && ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && rx->key)) { - if (ieee80211_is_deauth(fc)) - cfg80211_send_unprot_deauth(rx->sdata->dev, - rx->skb->data, - rx->skb->len); - else if (ieee80211_is_disassoc(fc)) - cfg80211_send_unprot_disassoc(rx->sdata->dev, - rx->skb->data, - rx->skb->len); + if (ieee80211_is_deauth(fc) || + ieee80211_is_disassoc(fc)) + cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, + rx->skb->data, + rx->skb->len); return -EACCES; } /* BIP does not use Protected field, so need to check MMIE */ if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && ieee80211_get_mmie_keyidx(rx->skb) < 0)) { - if (ieee80211_is_deauth(fc)) - cfg80211_send_unprot_deauth(rx->sdata->dev, - rx->skb->data, - rx->skb->len); - else if (ieee80211_is_disassoc(fc)) - cfg80211_send_unprot_disassoc(rx->sdata->dev, - rx->skb->data, - rx->skb->len); + if (ieee80211_is_deauth(fc) || + ieee80211_is_disassoc(fc)) + cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, + rx->skb->data, + rx->skb->len); return -EACCES; } /* diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 7bde5d9c0003..4b9c2be0d56d 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -18,20 +18,7 @@ #include "rdev-ops.h" -void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - - trace_cfg80211_send_rx_auth(dev); - - nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); - cfg80211_sme_rx_auth(dev, buf, len); -} -EXPORT_SYMBOL(cfg80211_send_rx_auth); - -void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, +void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len) { u16 status_code; @@ -84,10 +71,10 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, status_code, status_code == WLAN_STATUS_SUCCESS, bss); } -EXPORT_SYMBOL(cfg80211_send_rx_assoc); +EXPORT_SYMBOL(cfg80211_rx_assoc_resp); -void cfg80211_send_deauth(struct net_device *dev, - const u8 *buf, size_t len) +static void cfg80211_process_deauth(struct net_device *dev, + const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -96,9 +83,6 @@ void cfg80211_send_deauth(struct net_device *dev, const u8 *bssid = mgmt->bssid; bool was_current = false; - trace_cfg80211_send_deauth(dev); - ASSERT_WDEV_LOCK(wdev); - if (wdev->current_bss && ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_unhold_bss(wdev->current_bss); @@ -123,10 +107,9 @@ void cfg80211_send_deauth(struct net_device *dev, false, NULL); } } -EXPORT_SYMBOL(cfg80211_send_deauth); -void cfg80211_send_disassoc(struct net_device *dev, - const u8 *buf, size_t len) +static void cfg80211_process_disassoc(struct net_device *dev, + const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -136,9 +119,6 @@ void cfg80211_send_disassoc(struct net_device *dev, u16 reason_code; bool from_ap; - trace_cfg80211_send_disassoc(dev); - ASSERT_WDEV_LOCK(wdev); - nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); if (wdev->sme_state != CFG80211_SME_CONNECTED) @@ -153,15 +133,38 @@ void cfg80211_send_disassoc(struct net_device *dev, } else WARN_ON(1); - reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); } -EXPORT_SYMBOL(cfg80211_send_disassoc); -void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) +void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct ieee80211_mgmt *mgmt = (void *)buf; + + ASSERT_WDEV_LOCK(wdev); + + trace_cfg80211_rx_mlme_mgmt(dev, buf, len); + + if (WARN_ON(len < 2)) + return; + + if (ieee80211_is_auth(mgmt->frame_control)) { + nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); + cfg80211_sme_rx_auth(dev, buf, len); + } else if (ieee80211_is_deauth(mgmt->frame_control)) { + cfg80211_process_deauth(dev, buf, len); + } else if (ieee80211_is_disassoc(mgmt->frame_control)) { + cfg80211_process_disassoc(dev, buf, len); + } +} +EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt); + +void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -175,9 +178,9 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); } -EXPORT_SYMBOL(cfg80211_send_auth_timeout); +EXPORT_SYMBOL(cfg80211_auth_timeout); -void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) +void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; @@ -191,7 +194,26 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); } -EXPORT_SYMBOL(cfg80211_send_assoc_timeout); +EXPORT_SYMBOL(cfg80211_assoc_timeout); + +void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct ieee80211_mgmt *mgmt = (void *)buf; + + ASSERT_WDEV_LOCK(wdev); + + trace_cfg80211_tx_mlme_mgmt(dev, buf, len); + + if (WARN_ON(len < 2)) + return; + + if (ieee80211_is_deauth(mgmt->frame_control)) + cfg80211_process_deauth(dev, buf, len); + else + cfg80211_process_disassoc(dev, buf, len); +} +EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt); void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, enum nl80211_key_type key_type, int key_id, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ce949e38178c..444f5effb77f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9313,31 +9313,27 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, NL80211_CMD_DISASSOCIATE, gfp); } -void cfg80211_send_unprot_deauth(struct net_device *dev, const u8 *buf, - size_t len) +void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, + size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + const struct ieee80211_mgmt *mgmt = (void *)buf; + u32 cmd; - trace_cfg80211_send_unprot_deauth(dev); - nl80211_send_mlme_event(rdev, dev, buf, len, - NL80211_CMD_UNPROT_DEAUTHENTICATE, GFP_ATOMIC); -} -EXPORT_SYMBOL(cfg80211_send_unprot_deauth); + if (WARN_ON(len < 2)) + return; -void cfg80211_send_unprot_disassoc(struct net_device *dev, const u8 *buf, - size_t len) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + if (ieee80211_is_deauth(mgmt->frame_control)) + cmd = NL80211_CMD_UNPROT_DEAUTHENTICATE; + else + cmd = NL80211_CMD_UNPROT_DISASSOCIATE; - trace_cfg80211_send_unprot_disassoc(dev); - nl80211_send_mlme_event(rdev, dev, buf, len, - NL80211_CMD_UNPROT_DISASSOCIATE, GFP_ATOMIC); + trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); + nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC); } -EXPORT_SYMBOL(cfg80211_send_unprot_disassoc); +EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev, struct net_device *netdev, int cmd, diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 23fafeae8a10..e1534baf2ebb 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1911,24 +1911,46 @@ TRACE_EVENT(cfg80211_send_rx_assoc, NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) ); -DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth, - TP_PROTO(struct net_device *netdev), - TP_ARGS(netdev) +DECLARE_EVENT_CLASS(netdev_frame_event, + TP_PROTO(struct net_device *netdev, const u8 *buf, int len), + TP_ARGS(netdev, buf, len), + TP_STRUCT__entry( + NETDEV_ENTRY + __dynamic_array(u8, frame, len) + ), + TP_fast_assign( + NETDEV_ASSIGN; + memcpy(__get_dynamic_array(frame), buf, len); + ), + TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x", + NETDEV_PR_ARG, + le16_to_cpup((__le16 *)__get_dynamic_array(frame))) ); -DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc, - TP_PROTO(struct net_device *netdev), - TP_ARGS(netdev) +DEFINE_EVENT(netdev_frame_event, cfg80211_rx_unprot_mlme_mgmt, + TP_PROTO(struct net_device *netdev, const u8 *buf, int len), + TP_ARGS(netdev, buf, len) ); -DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_deauth, - TP_PROTO(struct net_device *netdev), - TP_ARGS(netdev) +DEFINE_EVENT(netdev_frame_event, cfg80211_rx_mlme_mgmt, + TP_PROTO(struct net_device *netdev, const u8 *buf, int len), + TP_ARGS(netdev, buf, len) ); -DEFINE_EVENT(netdev_evt_only, cfg80211_send_unprot_disassoc, - TP_PROTO(struct net_device *netdev), - TP_ARGS(netdev) +TRACE_EVENT(cfg80211_tx_mlme_mgmt, + TP_PROTO(struct net_device *netdev, const u8 *buf, int len), + TP_ARGS(netdev, buf, len), + TP_STRUCT__entry( + NETDEV_ENTRY + __dynamic_array(u8, frame, len) + ), + TP_fast_assign( + NETDEV_ASSIGN; + memcpy(__get_dynamic_array(frame), buf, len); + ), + TP_printk(NETDEV_PR_FMT ", ftype:0x%.2x", + NETDEV_PR_ARG, + le16_to_cpup((__le16 *)__get_dynamic_array(frame))) ); DECLARE_EVENT_CLASS(netdev_mac_evt, -- GitLab From ceca7b7121795ef81bd598a240d53a925662d0c1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 16 May 2013 00:55:45 +0200 Subject: [PATCH 0628/2900] cfg80211: separate internal SME implementation The current internal SME implementation in cfg80211 is very mixed up with the MLME handling, which has been causing issues for a long time. There are three things that the implementation has to provide: * a basic SME implementation for nl80211's connect() call (for drivers implementing auth/assoc, which is really just mac80211) and wireless extensions * MLME events for the userspace SME * SME events (connected, disconnected etc.) for all different SME implementation possibilities (driver, cfg80211 and userspace) To achieve these goals it isn't necessary to track the software SME's connection status outside of it's state (which is the part that caused many issues.) Instead, track it only in the SME data (wdev->conn) and in the general case only track whether the wdev is connected or not (via wdev->current_bss.) Also separate the internal implementation to not have callbacks from the SME events, but rather call it from the API functions that the driver (or rather mac80211) calls. This separates the code better. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 5 - net/wireless/core.c | 1 - net/wireless/core.h | 30 +-- net/wireless/ibss.c | 6 - net/wireless/mlme.c | 191 +++++--------- net/wireless/nl80211.c | 5 +- net/wireless/sme.c | 542 +++++++++++++++++++--------------------- net/wireless/wext-sme.c | 8 +- 8 files changed, 335 insertions(+), 453 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 195330d4ef34..5b208064f1bd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2898,11 +2898,6 @@ struct wireless_dev { /* currently used for IBSS and SME - might be rearranged later */ u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len, mesh_id_len, mesh_id_up_len; - enum { - CFG80211_SME_IDLE, - CFG80211_SME_CONNECTING, - CFG80211_SME_CONNECTED, - } sme_state; struct cfg80211_conn *conn; struct cfg80211_cached_keys *connect_keys; diff --git a/net/wireless/core.c b/net/wireless/core.c index f553b9484c1e..221e76b53a97 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -821,7 +821,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, pr_err("failed to add phy80211 symlink to netdev!\n"); } wdev->netdev = dev; - wdev->sme_state = CFG80211_SME_IDLE; #ifdef CONFIG_CFG80211_WEXT wdev->wext.default_key = -1; wdev->wext.default_mgmt_key = -1; diff --git a/net/wireless/core.h b/net/wireless/core.h index a65eaf8a84c1..a6b45bf00f33 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -308,11 +308,6 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, bool local_state_change); void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, struct net_device *dev); -void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, - const u8 *resp_ie, size_t resp_ie_len, - u16 status, bool wextev, - struct cfg80211_bss *bss); int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, u16 frame_type, const u8 *match_data, int match_len); @@ -328,12 +323,19 @@ void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, const struct ieee80211_vht_cap *vht_capa_mask); -/* SME */ +/* SME events */ int cfg80211_connect(struct cfg80211_registered_device *rdev, struct net_device *dev, struct cfg80211_connect_params *connect, struct cfg80211_cached_keys *connkeys, const u8 *prev_bssid); +void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, + u16 status, bool wextev, + struct cfg80211_bss *bss); +void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, + size_t ie_len, u16 reason, bool from_ap); int cfg80211_disconnect(struct cfg80211_registered_device *rdev, struct net_device *dev, u16 reason, bool wextev); @@ -344,21 +346,21 @@ void __cfg80211_roamed(struct wireless_dev *wdev, int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev); +/* SME implementation */ void cfg80211_conn_work(struct work_struct *work); -void cfg80211_sme_failed_assoc(struct wireless_dev *wdev); -bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); +void cfg80211_sme_scan_done(struct net_device *dev); +bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status); +void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len); +void cfg80211_sme_disassoc(struct wireless_dev *wdev); +void cfg80211_sme_deauth(struct wireless_dev *wdev); +void cfg80211_sme_auth_timeout(struct wireless_dev *wdev); +void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev); /* internal helpers */ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr); -void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, - size_t ie_len, u16 reason, bool from_ap); -void cfg80211_sme_scan_done(struct net_device *dev); -void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); -void cfg80211_sme_disassoc(struct net_device *dev, - struct cfg80211_internal_bss *bss); void __cfg80211_scan_done(struct work_struct *wk); void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); void __cfg80211_sched_scan_results(struct work_struct *wk); diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 5449c5a6de84..39bff7d36768 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -43,7 +43,6 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); - wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_upload_connect_keys(wdev); nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, @@ -64,8 +63,6 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) trace_cfg80211_ibss_joined(dev, bssid); - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); - ev = kzalloc(sizeof(*ev), gfp); if (!ev) return; @@ -120,7 +117,6 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, #ifdef CONFIG_CFG80211_WEXT wdev->wext.ibss.chandef = params->chandef; #endif - wdev->sme_state = CFG80211_SME_CONNECTING; err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan, params->channel_fixed @@ -134,7 +130,6 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, err = rdev_join_ibss(rdev, dev, params); if (err) { wdev->connect_keys = NULL; - wdev->sme_state = CFG80211_SME_IDLE; return err; } @@ -186,7 +181,6 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) } wdev->current_bss = NULL; - wdev->sme_state = CFG80211_SME_IDLE; wdev->ssid_len = 0; #ifdef CONFIG_CFG80211_WEXT if (!nowext) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 4b9c2be0d56d..a61a44bc6cf0 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -21,129 +21,85 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, const u8 *buf, size_t len) { - u16 status_code; struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; u8 *ie = mgmt->u.assoc_resp.variable; int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); + u16 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); trace_cfg80211_send_rx_assoc(dev, bss); - status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); - /* * This is a bit of a hack, we don't notify userspace of * a (re-)association reply if we tried to send a reassoc * and got a reject -- we only try again with an assoc * frame instead of reassoc. */ - if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && - cfg80211_sme_failed_reassoc(wdev)) { + if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { cfg80211_put_bss(wiphy, bss); return; } nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); - - if (status_code != WLAN_STATUS_SUCCESS && wdev->conn) { - cfg80211_sme_failed_assoc(wdev); - /* - * do not call connect_result() now because the - * sme will schedule work that does it later. - */ - cfg80211_put_bss(wiphy, bss); - return; - } - - if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { - /* - * This is for the userspace SME, the CONNECTING - * state will be changed to CONNECTED by - * __cfg80211_connect_result() below. - */ - wdev->sme_state = CFG80211_SME_CONNECTING; - } - - /* this consumes the bss reference */ + /* update current_bss etc., consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, status_code == WLAN_STATUS_SUCCESS, bss); } EXPORT_SYMBOL(cfg80211_rx_assoc_resp); -static void cfg80211_process_deauth(struct net_device *dev, +static void cfg80211_process_auth(struct wireless_dev *wdev, + const u8 *buf, size_t len) +{ + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + nl80211_send_rx_auth(rdev, wdev->netdev, buf, len, GFP_KERNEL); + cfg80211_sme_rx_auth(wdev, buf, len); +} + +static void cfg80211_process_deauth(struct wireless_dev *wdev, const u8 *buf, size_t len) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - bool was_current = false; - - if (wdev->current_bss && - ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wiphy, &wdev->current_bss->pub); - wdev->current_bss = NULL; - was_current = true; - } + u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); + bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); - nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); + nl80211_send_deauth(rdev, wdev->netdev, buf, len, GFP_KERNEL); - if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) { - u16 reason_code; - bool from_ap; - - reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); + if (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) + return; - from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); - __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); - } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { - __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - false, NULL); - } + __cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap); + cfg80211_sme_deauth(wdev); } -static void cfg80211_process_disassoc(struct net_device *dev, +static void cfg80211_process_disassoc(struct wireless_dev *wdev, const u8 *buf, size_t len) { - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; - u16 reason_code; - bool from_ap; + u16 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); + bool from_ap = !ether_addr_equal(mgmt->sa, wdev->netdev->dev_addr); - nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); + nl80211_send_disassoc(rdev, wdev->netdev, buf, len, GFP_KERNEL); - if (wdev->sme_state != CFG80211_SME_CONNECTED) + if (WARN_ON(!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return; - if (wdev->current_bss && - ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { - cfg80211_sme_disassoc(dev, wdev->current_bss); - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wiphy, &wdev->current_bss->pub); - wdev->current_bss = NULL; - } else - WARN_ON(1); - - reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); - - from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); - __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); + __cfg80211_disconnected(wdev->netdev, NULL, 0, reason_code, from_ap); + cfg80211_sme_disassoc(wdev); } void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (void *)buf; ASSERT_WDEV_LOCK(wdev); @@ -153,14 +109,12 @@ void cfg80211_rx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) if (WARN_ON(len < 2)) return; - if (ieee80211_is_auth(mgmt->frame_control)) { - nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); - cfg80211_sme_rx_auth(dev, buf, len); - } else if (ieee80211_is_deauth(mgmt->frame_control)) { - cfg80211_process_deauth(dev, buf, len); - } else if (ieee80211_is_disassoc(mgmt->frame_control)) { - cfg80211_process_disassoc(dev, buf, len); - } + if (ieee80211_is_auth(mgmt->frame_control)) + cfg80211_process_auth(wdev, buf, len); + else if (ieee80211_is_deauth(mgmt->frame_control)) + cfg80211_process_deauth(wdev, buf, len); + else if (ieee80211_is_disassoc(mgmt->frame_control)) + cfg80211_process_disassoc(wdev, buf, len); } EXPORT_SYMBOL(cfg80211_rx_mlme_mgmt); @@ -173,10 +127,7 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr) trace_cfg80211_send_auth_timeout(dev, addr); nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); - if (wdev->sme_state == CFG80211_SME_CONNECTING) - __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - false, NULL); + cfg80211_sme_auth_timeout(wdev); } EXPORT_SYMBOL(cfg80211_auth_timeout); @@ -189,10 +140,7 @@ void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr) trace_cfg80211_send_assoc_timeout(dev, addr); nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); - if (wdev->sme_state == CFG80211_SME_CONNECTING) - __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - false, NULL); + cfg80211_sme_assoc_timeout(wdev); } EXPORT_SYMBOL(cfg80211_assoc_timeout); @@ -209,9 +157,9 @@ void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) return; if (ieee80211_is_deauth(mgmt->frame_control)) - cfg80211_process_deauth(dev, buf, len); + cfg80211_process_deauth(wdev, buf, len); else - cfg80211_process_disassoc(dev, buf, len); + cfg80211_process_disassoc(wdev, buf, len); } EXPORT_SYMBOL(cfg80211_tx_mlme_mgmt); @@ -336,21 +284,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - bool was_connected = false; ASSERT_WDEV_LOCK(wdev); - if (wdev->current_bss && req->prev_bssid && - ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) { - /* - * Trying to reassociate: Allow this to proceed and let the old - * association to be dropped when the new one is completed. - */ - if (wdev->sme_state == CFG80211_SME_CONNECTED) { - was_connected = true; - wdev->sme_state = CFG80211_SME_CONNECTING; - } - } else if (wdev->current_bss) + if (wdev->current_bss && + (!req->prev_bssid || !ether_addr_equal(wdev->current_bss->pub.bssid, + req->prev_bssid))) return -EALREADY; cfg80211_oper_and_ht_capa(&req->ht_capa_mask, @@ -360,11 +299,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (!req->bss) { - if (was_connected) - wdev->sme_state = CFG80211_SME_CONNECTED; + if (!req->bss) return -ENOENT; - } err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED); if (err) @@ -373,11 +309,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, err = rdev_assoc(rdev, dev, req); out: - if (err) { - if (was_connected) - wdev->sme_state = CFG80211_SME_CONNECTED; + if (err) cfg80211_put_bss(&rdev->wiphy, req->bss); - } return err; } @@ -398,8 +331,9 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, ASSERT_WDEV_LOCK(wdev); - if (local_state_change && (!wdev->current_bss || - !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) + if (local_state_change && + (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return 0; return rdev_deauth(rdev, dev, &req); @@ -417,13 +351,11 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, .ie = ie, .ie_len = ie_len, }; + int err; ASSERT_WDEV_LOCK(wdev); - if (wdev->sme_state != CFG80211_SME_CONNECTED) - return -ENOTCONN; - - if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) + if (!wdev->current_bss) return -ENOTCONN; if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) @@ -431,7 +363,13 @@ int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, else return -ENOTCONN; - return rdev_disassoc(rdev, dev, &req); + err = rdev_disassoc(rdev, dev, &req); + if (err) + return err; + + /* driver should have reported the disassoc */ + WARN_ON(wdev->current_bss); + return 0; } void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, @@ -439,10 +377,6 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; u8 bssid[ETH_ALEN]; - struct cfg80211_deauth_request req = { - .reason_code = WLAN_REASON_DEAUTH_LEAVING, - .bssid = bssid, - }; ASSERT_WDEV_LOCK(wdev); @@ -453,13 +387,8 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, return; memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); - rdev_deauth(rdev, dev, &req); - - if (wdev->current_bss) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&rdev->wiphy, &wdev->current_bss->pub); - wdev->current_bss = NULL; - } + cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, + WLAN_REASON_DEAUTH_LEAVING, false); } struct cfg80211_mgmt_registration { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 444f5effb77f..88e820b73674 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -800,12 +800,9 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) case NL80211_IFTYPE_MESH_POINT: break; case NL80211_IFTYPE_ADHOC: - if (!wdev->current_bss) - return -ENOLINK; - break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: - if (wdev->sme_state != CFG80211_SME_CONNECTED) + if (!wdev->current_bss) return -ENOLINK; break; default: diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 81be95f3be74..ae7e2cbf45cb 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -1,5 +1,7 @@ /* - * SME code for cfg80211's connect emulation. + * SME code for cfg80211 + * both driver SME event handling and the SME implementation + * (for nl80211's connect() and wext) * * Copyright 2009 Johannes Berg * Copyright (C) 2009 Intel Corporation. All rights reserved. @@ -18,18 +20,24 @@ #include "reg.h" #include "rdev-ops.h" +/* + * Software SME in cfg80211, using auth/assoc/deauth calls to the + * driver. This is is for implementing nl80211's connect/disconnect + * and wireless extensions (if configured.) + */ + struct cfg80211_conn { struct cfg80211_connect_params params; /* these are sub-states of the _CONNECTING sme_state */ enum { - CFG80211_CONN_IDLE, CFG80211_CONN_SCANNING, CFG80211_CONN_SCAN_AGAIN, CFG80211_CONN_AUTHENTICATE_NEXT, CFG80211_CONN_AUTHENTICATING, CFG80211_CONN_ASSOCIATE_NEXT, CFG80211_CONN_ASSOCIATING, - CFG80211_CONN_DEAUTH_ASSOC_FAIL, + CFG80211_CONN_DEAUTH, + CFG80211_CONN_CONNECTED, } state; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 *ie; @@ -37,39 +45,16 @@ struct cfg80211_conn { bool auto_auth, prev_bssid_valid; }; -static bool cfg80211_is_all_idle(void) +static void cfg80211_sme_free(struct wireless_dev *wdev) { - struct cfg80211_registered_device *rdev; - struct wireless_dev *wdev; - bool is_all_idle = true; - - /* - * All devices must be idle as otherwise if you are actively - * scanning some new beacon hints could be learned and would - * count as new regulatory hints. - */ - list_for_each_entry(rdev, &cfg80211_rdev_list, list) { - list_for_each_entry(wdev, &rdev->wdev_list, list) { - wdev_lock(wdev); - if (wdev->sme_state != CFG80211_SME_IDLE) - is_all_idle = false; - wdev_unlock(wdev); - } - } - - return is_all_idle; -} + if (!wdev->conn) + return; -static void disconnect_work(struct work_struct *work) -{ - rtnl_lock(); - if (cfg80211_is_all_idle()) - regulatory_hint_disconnect(); - rtnl_unlock(); + kfree(wdev->conn->ie); + kfree(wdev->conn); + wdev->conn = NULL; } -static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); - static int cfg80211_conn_scan(struct wireless_dev *wdev) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -164,6 +149,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) params = &wdev->conn->params; switch (wdev->conn->state) { + case CFG80211_CONN_SCANNING: + /* didn't find it during scan ... */ + return -ENOENT; case CFG80211_CONN_SCAN_AGAIN: return cfg80211_conn_scan(wdev); case CFG80211_CONN_AUTHENTICATE_NEXT: @@ -200,12 +188,11 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) WLAN_REASON_DEAUTH_LEAVING, false); return err; - case CFG80211_CONN_DEAUTH_ASSOC_FAIL: + case CFG80211_CONN_DEAUTH: cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, WLAN_REASON_DEAUTH_LEAVING, false); - /* return an error so that we call __cfg80211_connect_result() */ - return -EINVAL; + return 0; default: return 0; } @@ -229,7 +216,8 @@ void cfg80211_conn_work(struct work_struct *work) wdev_unlock(wdev); continue; } - if (wdev->sme_state != CFG80211_SME_CONNECTING || !wdev->conn) { + if (!wdev->conn || + wdev->conn->state == CFG80211_CONN_CONNECTED) { wdev_unlock(wdev); continue; } @@ -237,12 +225,14 @@ void cfg80211_conn_work(struct work_struct *work) memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN); bssid = bssid_buf; } - if (cfg80211_conn_do_work(wdev)) + if (cfg80211_conn_do_work(wdev)) { __cfg80211_connect_result( wdev->netdev, bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, false, NULL); + cfg80211_sme_free(wdev); + } wdev_unlock(wdev); } @@ -286,9 +276,6 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) ASSERT_WDEV_LOCK(wdev); - if (wdev->sme_state != CFG80211_SME_CONNECTING) - return; - if (!wdev->conn) return; @@ -297,20 +284,10 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) return; bss = cfg80211_get_conn_bss(wdev); - if (bss) { + if (bss) cfg80211_put_bss(&rdev->wiphy, bss); - } else { - /* not found */ - if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) - schedule_work(&rdev->conn_work); - else - __cfg80211_connect_result( - wdev->netdev, - wdev->conn->params.bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - false, NULL); - } + else + schedule_work(&rdev->conn_work); } void cfg80211_sme_scan_done(struct net_device *dev) @@ -322,10 +299,8 @@ void cfg80211_sme_scan_done(struct net_device *dev) wdev_unlock(wdev); } -void cfg80211_sme_rx_auth(struct net_device *dev, - const u8 *buf, size_t len) +void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len) { - struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; @@ -333,11 +308,7 @@ void cfg80211_sme_rx_auth(struct net_device *dev, ASSERT_WDEV_LOCK(wdev); - /* should only RX auth frames when connecting */ - if (wdev->sme_state != CFG80211_SME_CONNECTING) - return; - - if (WARN_ON(!wdev->conn)) + if (!wdev->conn || wdev->conn->state == CFG80211_CONN_CONNECTED) return; if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG && @@ -366,46 +337,226 @@ void cfg80211_sme_rx_auth(struct net_device *dev, wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; schedule_work(&rdev->conn_work); } else if (status_code != WLAN_STATUS_SUCCESS) { - __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, + __cfg80211_connect_result(wdev->netdev, mgmt->bssid, + NULL, 0, NULL, 0, status_code, false, NULL); - } else if (wdev->sme_state == CFG80211_SME_CONNECTING && - wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { + } else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; schedule_work(&rdev->conn_work); } } -bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev) +bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status) { - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - if (WARN_ON(!wdev->conn)) + if (!wdev->conn) return false; - if (!wdev->conn->prev_bssid_valid) + if (status == WLAN_STATUS_SUCCESS) { + wdev->conn->state = CFG80211_CONN_CONNECTED; return false; + } - /* - * Some stupid APs don't accept reassoc, so we - * need to fall back to trying regular assoc. - */ - wdev->conn->prev_bssid_valid = false; - wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; + if (wdev->conn->prev_bssid_valid) { + /* + * Some stupid APs don't accept reassoc, so we + * need to fall back to trying regular assoc; + * return true so no event is sent to userspace. + */ + wdev->conn->prev_bssid_valid = false; + wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; + schedule_work(&rdev->conn_work); + return true; + } + + wdev->conn->state = CFG80211_CONN_DEAUTH; schedule_work(&rdev->conn_work); + return false; +} - return true; +void cfg80211_sme_deauth(struct wireless_dev *wdev) +{ + cfg80211_sme_free(wdev); } -void cfg80211_sme_failed_assoc(struct wireless_dev *wdev) +void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) { - struct wiphy *wiphy = wdev->wiphy; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + cfg80211_sme_free(wdev); +} - wdev->conn->state = CFG80211_CONN_DEAUTH_ASSOC_FAIL; +void cfg80211_sme_disassoc(struct wireless_dev *wdev) +{ + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + if (!wdev->conn) + return; + + wdev->conn->state = CFG80211_CONN_DEAUTH; schedule_work(&rdev->conn_work); } +void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) +{ + cfg80211_sme_disassoc(wdev); +} + +static int cfg80211_sme_connect(struct wireless_dev *wdev, + struct cfg80211_connect_params *connect, + const u8 *prev_bssid) +{ + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct cfg80211_bss *bss; + int err; + + if (!rdev->ops->auth || !rdev->ops->assoc) + return -EOPNOTSUPP; + + if (wdev->current_bss) + return -EALREADY; + + if (WARN_ON(wdev->conn)) + return -EINPROGRESS; + + wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); + if (!wdev->conn) + return -ENOMEM; + + /* + * Copy all parameters, and treat explicitly IEs, BSSID, SSID. + */ + memcpy(&wdev->conn->params, connect, sizeof(*connect)); + if (connect->bssid) { + wdev->conn->params.bssid = wdev->conn->bssid; + memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN); + } + + if (connect->ie) { + wdev->conn->ie = kmemdup(connect->ie, connect->ie_len, + GFP_KERNEL); + wdev->conn->params.ie = wdev->conn->ie; + if (!wdev->conn->ie) { + kfree(wdev->conn); + wdev->conn = NULL; + return -ENOMEM; + } + } + + if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { + wdev->conn->auto_auth = true; + /* start with open system ... should mostly work */ + wdev->conn->params.auth_type = + NL80211_AUTHTYPE_OPEN_SYSTEM; + } else { + wdev->conn->auto_auth = false; + } + + wdev->conn->params.ssid = wdev->ssid; + wdev->conn->params.ssid_len = connect->ssid_len; + + /* see if we have the bss already */ + bss = cfg80211_get_conn_bss(wdev); + + if (prev_bssid) { + memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN); + wdev->conn->prev_bssid_valid = true; + } + + /* we're good if we have a matching bss struct */ + if (bss) { + wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; + err = cfg80211_conn_do_work(wdev); + cfg80211_put_bss(wdev->wiphy, bss); + } else { + /* otherwise we'll need to scan for the AP first */ + err = cfg80211_conn_scan(wdev); + + /* + * If we can't scan right now, then we need to scan again + * after the current scan finished, since the parameters + * changed (unless we find a good AP anyway). + */ + if (err == -EBUSY) { + err = 0; + wdev->conn->state = CFG80211_CONN_SCAN_AGAIN; + } + } + + if (err) + cfg80211_sme_free(wdev); + + return err; +} + +static int cfg80211_sme_disconnect(struct wireless_dev *wdev, u16 reason) +{ + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + int err; + + if (!wdev->conn) + return 0; + + if (!rdev->ops->deauth) + return -EOPNOTSUPP; + + if (wdev->conn->state == CFG80211_CONN_SCANNING || + wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) { + err = 0; + goto out; + } + + /* wdev->conn->params.bssid must be set if > SCANNING */ + err = cfg80211_mlme_deauth(rdev, wdev->netdev, + wdev->conn->params.bssid, + NULL, 0, reason, false); + out: + cfg80211_sme_free(wdev); + return err; +} + +/* + * code shared for in-device and software SME + */ + +static bool cfg80211_is_all_idle(void) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + bool is_all_idle = true; + + /* + * All devices must be idle as otherwise if you are actively + * scanning some new beacon hints could be learned and would + * count as new regulatory hints. + */ + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + list_for_each_entry(wdev, &rdev->wdev_list, list) { + wdev_lock(wdev); + if (wdev->conn || wdev->current_bss) + is_all_idle = false; + wdev_unlock(wdev); + } + } + + return is_all_idle; +} + +static void disconnect_work(struct work_struct *work) +{ + rtnl_lock(); + if (cfg80211_is_all_idle()) + regulatory_hint_disconnect(); + rtnl_unlock(); +} + +static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); + + +/* + * API calls for drivers implementing connect/disconnect and + * SME event handling + */ + void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, @@ -424,9 +575,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) return; - if (wdev->sme_state != CFG80211_SME_CONNECTING) - return; - nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, @@ -463,15 +611,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, wdev->current_bss = NULL; } - if (wdev->conn) - wdev->conn->state = CFG80211_CONN_IDLE; - if (status != WLAN_STATUS_SUCCESS) { - wdev->sme_state = CFG80211_SME_IDLE; - if (wdev->conn) - kfree(wdev->conn->ie); - kfree(wdev->conn); - wdev->conn = NULL; kfree(wdev->connect_keys); wdev->connect_keys = NULL; wdev->ssid_len = 0; @@ -480,21 +620,16 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, } if (!bss) - bss = cfg80211_get_bss(wdev->wiphy, - wdev->conn ? wdev->conn->params.channel : - NULL, - bssid, + bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (WARN_ON(!bss)) return; cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); - wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_upload_connect_keys(wdev); rcu_read_lock(); @@ -530,8 +665,6 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, struct cfg80211_event *ev; unsigned long flags; - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); - ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); if (!ev) return; @@ -572,13 +705,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) goto out; - if (wdev->sme_state != CFG80211_SME_CONNECTED) - goto out; - - /* internal error -- how did we get to CONNECTED w/o BSS? */ - if (WARN_ON(!wdev->current_bss)) { + if (WARN_ON(!wdev->current_bss)) goto out; - } cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); @@ -628,8 +756,6 @@ void cfg80211_roamed(struct net_device *dev, struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_bss *bss; - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); - bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); @@ -651,8 +777,6 @@ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_event *ev; unsigned long flags; - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); - if (WARN_ON(!bss)) return; @@ -694,25 +818,14 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) return; - if (wdev->sme_state != CFG80211_SME_CONNECTED) - return; - if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); } wdev->current_bss = NULL; - wdev->sme_state = CFG80211_SME_IDLE; wdev->ssid_len = 0; - if (wdev->conn) { - kfree(wdev->conn->ie); - wdev->conn->ie = NULL; - kfree(wdev->conn); - wdev->conn = NULL; - } - nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); /* @@ -741,8 +854,6 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, struct cfg80211_event *ev; unsigned long flags; - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); - ev = kzalloc(sizeof(*ev) + ie_len, gfp); if (!ev) return; @@ -760,6 +871,9 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, } EXPORT_SYMBOL(cfg80211_disconnected); +/* + * API calls for nl80211/wext compatibility code + */ int cfg80211_connect(struct cfg80211_registered_device *rdev, struct net_device *dev, struct cfg80211_connect_params *connect, @@ -767,14 +881,10 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, const u8 *prev_bssid) { struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_bss *bss = NULL; int err; ASSERT_WDEV_LOCK(wdev); - if (wdev->sme_state != CFG80211_SME_IDLE) - return -EALREADY; - if (WARN_ON(wdev->connect_keys)) { kfree(wdev->connect_keys); wdev->connect_keys = NULL; @@ -810,105 +920,22 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, } } - if (!rdev->ops->connect) { - if (!rdev->ops->auth || !rdev->ops->assoc) - return -EOPNOTSUPP; - - if (WARN_ON(wdev->conn)) - return -EINPROGRESS; - - wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); - if (!wdev->conn) - return -ENOMEM; - - /* - * Copy all parameters, and treat explicitly IEs, BSSID, SSID. - */ - memcpy(&wdev->conn->params, connect, sizeof(*connect)); - if (connect->bssid) { - wdev->conn->params.bssid = wdev->conn->bssid; - memcpy(wdev->conn->bssid, connect->bssid, ETH_ALEN); - } + wdev->connect_keys = connkeys; + memcpy(wdev->ssid, connect->ssid, connect->ssid_len); + wdev->ssid_len = connect->ssid_len; - if (connect->ie) { - wdev->conn->ie = kmemdup(connect->ie, connect->ie_len, - GFP_KERNEL); - wdev->conn->params.ie = wdev->conn->ie; - if (!wdev->conn->ie) { - kfree(wdev->conn); - wdev->conn = NULL; - return -ENOMEM; - } - } - - if (connect->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { - wdev->conn->auto_auth = true; - /* start with open system ... should mostly work */ - wdev->conn->params.auth_type = - NL80211_AUTHTYPE_OPEN_SYSTEM; - } else { - wdev->conn->auto_auth = false; - } - - memcpy(wdev->ssid, connect->ssid, connect->ssid_len); - wdev->ssid_len = connect->ssid_len; - wdev->conn->params.ssid = wdev->ssid; - wdev->conn->params.ssid_len = connect->ssid_len; - - /* see if we have the bss already */ - bss = cfg80211_get_conn_bss(wdev); - - wdev->sme_state = CFG80211_SME_CONNECTING; - wdev->connect_keys = connkeys; - - if (prev_bssid) { - memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN); - wdev->conn->prev_bssid_valid = true; - } - - /* we're good if we have a matching bss struct */ - if (bss) { - wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; - err = cfg80211_conn_do_work(wdev); - cfg80211_put_bss(wdev->wiphy, bss); - } else { - /* otherwise we'll need to scan for the AP first */ - err = cfg80211_conn_scan(wdev); - /* - * If we can't scan right now, then we need to scan again - * after the current scan finished, since the parameters - * changed (unless we find a good AP anyway). - */ - if (err == -EBUSY) { - err = 0; - wdev->conn->state = CFG80211_CONN_SCAN_AGAIN; - } - } - if (err) { - kfree(wdev->conn->ie); - kfree(wdev->conn); - wdev->conn = NULL; - wdev->sme_state = CFG80211_SME_IDLE; - wdev->connect_keys = NULL; - wdev->ssid_len = 0; - } - - return err; - } else { - wdev->sme_state = CFG80211_SME_CONNECTING; - wdev->connect_keys = connkeys; + if (!rdev->ops->connect) + err = cfg80211_sme_connect(wdev, connect, prev_bssid); + else err = rdev_connect(rdev, dev, connect); - if (err) { - wdev->connect_keys = NULL; - wdev->sme_state = CFG80211_SME_IDLE; - return err; - } - memcpy(wdev->ssid, connect->ssid, connect->ssid_len); - wdev->ssid_len = connect->ssid_len; - - return 0; + if (err) { + wdev->connect_keys = NULL; + wdev->ssid_len = 0; + return err; } + + return 0; } int cfg80211_disconnect(struct cfg80211_registered_device *rdev, @@ -919,78 +946,17 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, ASSERT_WDEV_LOCK(wdev); - if (wdev->sme_state == CFG80211_SME_IDLE) - return -EINVAL; - kfree(wdev->connect_keys); wdev->connect_keys = NULL; - if (!rdev->ops->disconnect) { - if (!rdev->ops->deauth) - return -EOPNOTSUPP; - - /* was it connected by userspace SME? */ - if (!wdev->conn) { - cfg80211_mlme_down(rdev, dev); - goto disconnect; - } - - if (wdev->sme_state == CFG80211_SME_CONNECTING && - (wdev->conn->state == CFG80211_CONN_SCANNING || - wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) { - wdev->sme_state = CFG80211_SME_IDLE; - kfree(wdev->conn->ie); - kfree(wdev->conn); - wdev->conn = NULL; - wdev->ssid_len = 0; - return 0; - } - - /* wdev->conn->params.bssid must be set if > SCANNING */ - err = cfg80211_mlme_deauth(rdev, dev, - wdev->conn->params.bssid, - NULL, 0, reason, false); - if (err) - return err; + if (wdev->conn) { + err = cfg80211_sme_disconnect(wdev, reason); + } else if (!rdev->ops->disconnect) { + cfg80211_mlme_down(rdev, dev); + err = 0; } else { err = rdev_disconnect(rdev, dev, reason); - if (err) - return err; } - disconnect: - if (wdev->sme_state == CFG80211_SME_CONNECTED) - __cfg80211_disconnected(dev, NULL, 0, 0, false); - else if (wdev->sme_state == CFG80211_SME_CONNECTING) - __cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - wextev, NULL); - - return 0; -} - -void cfg80211_sme_disassoc(struct net_device *dev, - struct cfg80211_internal_bss *bss) -{ - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - u8 bssid[ETH_ALEN]; - - ASSERT_WDEV_LOCK(wdev); - - if (!wdev->conn) - return; - - if (wdev->conn->state == CFG80211_CONN_IDLE) - return; - - /* - * Ok, so the association was made by this SME -- we don't - * want it any more so deauthenticate too. - */ - - memcpy(bssid, bss->pub.bssid, ETH_ALEN); - - cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, - WLAN_REASON_DEAUTH_LEAVING, false); + return err; } diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index a53f8404f451..14c9a2583ba0 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -89,7 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, wdev_lock(wdev); - if (wdev->sme_state != CFG80211_SME_IDLE) { + if (wdev->conn) { bool event = true; if (wdev->wext.connect.channel == chan) { @@ -188,7 +188,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, err = 0; - if (wdev->sme_state != CFG80211_SME_IDLE) { + if (wdev->conn) { bool event = true; if (wdev->wext.connect.ssid && len && @@ -277,7 +277,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, wdev_lock(wdev); - if (wdev->sme_state != CFG80211_SME_IDLE) { + if (wdev->conn) { err = 0; /* both automatic */ if (!bssid && !wdev->wext.connect.bssid) @@ -364,7 +364,7 @@ int cfg80211_wext_siwgenie(struct net_device *dev, wdev->wext.ie = ie; wdev->wext.ie_len = ie_len; - if (wdev->sme_state != CFG80211_SME_IDLE) { + if (wdev->conn) { err = cfg80211_disconnect(rdev, dev, WLAN_REASON_DEAUTH_LEAVING, false); if (err) -- GitLab From 6767583175c98d1bf93d45f6a4c61e4a25ee1ea3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 29 May 2013 09:09:30 +0300 Subject: [PATCH 0629/2900] iwlwifi: mvm: fix the LUT for BT Coex There was a typo in the Loose LUT for BT Coex. Fix that. Reported-by: Roi Cohen Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index f03655f303aa..9a4d94a1f90d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -174,7 +174,7 @@ static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaeaaaaaa), + cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), -- GitLab From e96d551f4bc6a13942aa5837ca6739c61d540945 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 28 May 2013 21:31:50 +0300 Subject: [PATCH 0630/2900] iwlwifi: mvm: limit the length of the AMPDU when BT is running This holds for existing BA agreements. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/rs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 6a050c69e7d0..7dfc212c4f0e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2782,6 +2782,13 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm, lq_cmd->agg_time_limit = cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); + + /* + * overwrite if needed, pass aggregation time limit + * to uCode in uSec - This is racy - but heh, at least it helps... + */ + if (mvm && BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) + lq_cmd->agg_time_limit = cpu_to_le16(1200); } static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -- GitLab From 7c8e4159bac47354ea9eee40ac7a0f713c0be5db Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 28 May 2013 21:36:16 +0300 Subject: [PATCH 0631/2900] iwlwifi: mvm: don't start BA agreement when BT is active Otherwise WiFi would kill BT. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/rs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 7dfc212c4f0e..20269994d8db 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -401,6 +401,17 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, load = rs_tl_get_load(lq_data, tid); + /* + * Don't create TX aggregation sessions when in high + * BT traffic, as they would just be disrupted by BT. + */ + if (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 2) { + IWL_DEBUG_COEX(mvm, "BT traffic (%d), no aggregation allowed\n", + BT_MBOX_MSG(&mvm->last_bt_notif, + 3, TRAFFIC_LOAD)); + return ret; + } + if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); -- GitLab From 36946ce69abe8b5c7043708f832ca179dd6e4f64 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 28 May 2013 23:12:47 +0300 Subject: [PATCH 0632/2900] iwlwifi: mvm: don't enable MIMO when BT is active Another step in the rate control / BT Coex integration Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/rs.c | 97 ++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/mvm/rs.h | 12 ++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 20269994d8db..d6beec765d65 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1530,6 +1530,29 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, u8 update_search_tbl_counter = 0; int ret; + switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) + tbl->action = IWL_SISO_SWITCH_MIMO2_AB; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + valid_tx_ant = + first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); + if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) + tbl->action = IWL_SISO_SWITCH_ANTENNA1; + break; + default: + IWL_ERR(mvm, "Invalid BT load %d", + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); + break; + } + start_action = tbl->action; while (1) { lq_sta->action_counter++; @@ -1543,7 +1566,9 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm, tx_chains_num <= 2)) break; - if (window->success_ratio >= IWL_RS_GOOD_RATIO) + if (window->success_ratio >= IWL_RS_GOOD_RATIO && + BT_MBOX_MSG(&mvm->last_bt_notif, 3, + TRAFFIC_LOAD) == 0) break; memcpy(search_tbl, tbl, sz); @@ -1665,6 +1690,28 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm, u8 update_search_tbl_counter = 0; int ret; + switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action != IWL_MIMO2_SWITCH_SISO_A) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_MIMO2_SWITCH_SISO_B || + tbl->action == IWL_MIMO2_SWITCH_SISO_C) + tbl->action = IWL_MIMO2_SWITCH_SISO_A; + break; + default: + IWL_ERR(mvm, "Invalid BT load %d", + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); + break; + } + start_action = tbl->action; while (1) { lq_sta->action_counter++; @@ -1802,6 +1849,28 @@ static int rs_move_mimo3_to_other(struct iwl_mvm *mvm, int ret; u8 update_search_tbl_counter = 0; + switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { + case IWL_BT_COEX_TRAFFIC_LOAD_NONE: + /* nothing */ + break; + case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: + case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: + /* avoid antenna B and MIMO */ + if (tbl->action != IWL_MIMO3_SWITCH_SISO_A) + tbl->action = IWL_MIMO3_SWITCH_SISO_A; + break; + case IWL_BT_COEX_TRAFFIC_LOAD_LOW: + /* avoid antenna B unless MIMO */ + if (tbl->action == IWL_MIMO3_SWITCH_SISO_B || + tbl->action == IWL_MIMO3_SWITCH_SISO_C) + tbl->action = IWL_MIMO3_SWITCH_SISO_A; + break; + default: + IWL_ERR(mvm, "Invalid BT load %d", + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)); + break; + } + start_action = tbl->action; while (1) { lq_sta->action_counter++; @@ -2313,6 +2382,32 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, (current_tpt > (100 * tbl->expected_tpt[low])))) scale_action = 0; + if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= + IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && + (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { + if (lq_sta->last_bt_traffic > + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { + /* + * don't set scale_action, don't want to scale up if + * the rate scale doesn't otherwise think that is a + * good idea. + */ + } else if (lq_sta->last_bt_traffic <= + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { + scale_action = -1; + } + } + lq_sta->last_bt_traffic = + BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); + + if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= + IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && + (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) { + /* search for a new modulation */ + rs_stay_in_table(lq_sta, true); + goto lq_update; + } + switch (scale_action) { case -1: /* Decrease starting rate, update uCode's rate table */ diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index f66155a57238..cff4f6da7733 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -358,6 +358,18 @@ struct iwl_lq_sta { u8 last_bt_traffic; }; +enum iwl_bt_coex_profile_traffic_load { + IWL_BT_COEX_TRAFFIC_LOAD_NONE = 0, + IWL_BT_COEX_TRAFFIC_LOAD_LOW = 1, + IWL_BT_COEX_TRAFFIC_LOAD_HIGH = 2, + IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS = 3, +/* + * There are no more even though below is a u8, the + * indication from the BT device only has two bits. + */ +}; + + static inline u8 num_of_ant(u8 mask) { return !!((mask) & ANT_A) + -- GitLab From 1094fa2646385a3bdbcdac5f2f270836d998b255 Mon Sep 17 00:00:00 2001 From: Eran Harary Date: Sun, 2 Jun 2013 12:40:34 +0300 Subject: [PATCH 0633/2900] iwlwifi: don't return -ERFKILL if SEND_IF_RFKILL is set When CMD_SEND_IN_RFKILL is set, it is perfectly legitimate to send a host command while RFKILL is asserted. In this case, the host command sending functions should return 0 even if RFKILL is asserted. Signed-off-by: Eran Harary Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index a35c6aefbc3e..f65da1984d91 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1527,7 +1527,8 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, goto cancel; } - if (test_bit(STATUS_RFKILL, &trans_pcie->status)) { + if (!(cmd->flags & CMD_SEND_IN_RFKILL) && + test_bit(STATUS_RFKILL, &trans_pcie->status)) { IWL_DEBUG_RF_KILL(trans, "RFKILL in SYNC CMD... no rsp\n"); ret = -ERFKILL; goto cancel; -- GitLab From 8d683b79487c40d2a74ab9c484bde1929e016579 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 30 May 2013 07:31:01 +0300 Subject: [PATCH 0634/2900] iwlwifi: mvm: Fix quota command settings According to the FW implementation, the quota command should have a valid entry for each active binding (where 'active' in this context means that the binding is known to the FW). In case the binding should not get any quota, the 'quota' should be set to zero. Not setting an 0 quota for an active binding when all the MACs in the binding are idle, i.e., not associated in case of managed interface, will result in preventing the FW scheduler from entering IDLE state and the FW from transitioning to low PS. Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/quota.c | 25 +++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c index a1e3e923ea3e..29d49cf0fdb2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/iwlwifi/mvm/quota.c @@ -169,27 +169,34 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) num_active_bindings++; } - if (!num_active_bindings) - goto send_cmd; - - quota = IWL_MVM_MAX_QUOTA / num_active_bindings; - quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings; + quota = 0; + quota_rem = 0; + if (num_active_bindings) { + quota = IWL_MVM_MAX_QUOTA / num_active_bindings; + quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings; + } for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { - if (data.n_interfaces[i] <= 0) + if (data.colors[i] < 0) continue; cmd.quotas[idx].id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(i, data.colors[i])); - cmd.quotas[idx].quota = cpu_to_le32(quota); - cmd.quotas[idx].max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA); + + if (data.n_interfaces[i] <= 0) { + cmd.quotas[idx].quota = cpu_to_le32(0); + cmd.quotas[idx].max_duration = cpu_to_le32(0); + } else { + cmd.quotas[idx].quota = cpu_to_le32(quota); + cmd.quotas[idx].max_duration = + cpu_to_le32(IWL_MVM_MAX_QUOTA); + } idx++; } /* Give the remainder of the session to the first binding */ le32_add_cpu(&cmd.quotas[0].quota, quota_rem); -send_cmd: ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC, sizeof(cmd), &cmd); if (ret) -- GitLab From 497b49d2f690cdfaae5292e30ea5cd9bb469090c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 2 Jun 2013 20:54:48 +0300 Subject: [PATCH 0635/2900] iwlwifi: mvm: reorder Rx handler for performance purposes Since SCAN related handlers are much less likely than beacon related handlers, reorder between them. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/ops.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index d7a199b1cdef..af79a14063a9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -215,15 +215,16 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false), RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false), RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), - RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), - - RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), - RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false), RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true), + RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), + + RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), + RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), + RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), -- GitLab From 86a91ec757338edbce51de5dabd7afb0366f485c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 26 May 2013 20:47:53 +0300 Subject: [PATCH 0636/2900] iwlwifi: mvm: correctly configure MCAST in AP mode The AP mode needs to use the MCAST fifo for the MCAST frames sent after the DTIM. This fifo needs to be configured with the same parameters as the VOICE FIFO. A separate SCD queue is mapped to this fifo - the cab_queue (cab stands for Content After Beacon). This queue isn't connected to any station, but rather to the MAC context. This queue should (and is already) be set as the MCAST queue - this is part of the of MAC context command. Signed-off-by: Emmanuel Grumbach Reviewed-by: Ilan Peer Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h | 8 +++++++- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 6 +++++- drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h index d68640ea41d4..98b1feb43d38 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h @@ -71,7 +71,13 @@ #define MAC_INDEX_MIN_DRIVER 0 #define NUM_MAC_INDEX_DRIVER MAC_INDEX_AUX -#define AC_NUM 4 /* Number of access categories */ +enum iwl_ac { + AC_BK, + AC_BE, + AC_VI, + AC_VO, + AC_NUM, +}; /** * enum iwl_mac_protection_flags - MAC context flags diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index b4e8e597d2b7..46c7c0507c25 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -365,7 +365,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) break; case NL80211_IFTYPE_AP: iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue, - IWL_MVM_TX_FIFO_VO); + IWL_MVM_TX_FIFO_MCAST); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) @@ -553,6 +553,10 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]); } + /* in AP mode, the MCAST FIFO takes the EDCA params from VO */ + if (vif->type == NL80211_IFTYPE_AP) + cmd->ac[AC_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST); + if (vif->bss_conf.qos) cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA); diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 384259baf525..4e10aae71038 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -88,6 +88,7 @@ enum iwl_mvm_tx_fifo { IWL_MVM_TX_FIFO_BE, IWL_MVM_TX_FIFO_VI, IWL_MVM_TX_FIFO_VO, + IWL_MVM_TX_FIFO_MCAST = 5, }; extern struct ieee80211_ops iwl_mvm_hw_ops; -- GitLab From 4bf881f5d55c2bb704771287613c8807ef181b3c Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Wed, 29 May 2013 10:19:50 +0300 Subject: [PATCH 0637/2900] iwlwifi: mvm: Change location of vif_count verification for PM Currently vif_count verification for power management enablement appear in different places. Move these verifications to one place in iwl_mvm_update_power_mode(). Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 32 ++++----------------- drivers/net/wireless/iwlwifi/mvm/power.c | 11 +++++++ 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 12337aac2947..c13559b4b4fd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -597,21 +597,11 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, mvmvif->phy_ctxt = NULL; iwl_mvm_mac_ctxt_remove(mvm, vif); out_release: - /* - * TODO: remove this temporary code. - * Currently MVM FW supports power management only on single MAC. - * Check if only one additional interface remains after releasing - * current one. Update power mode on the remaining interface. - */ if (vif->type != NL80211_IFTYPE_P2P_DEVICE) mvm->vif_count--; - IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", - mvm->vif_count); - if (mvm->vif_count == 1) { - ieee80211_iterate_active_interfaces( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_power_update_iterator, mvm); - } + ieee80211_iterate_active_interfaces( + mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_power_update_iterator, mvm); iwl_mvm_mac_ctxt_release(mvm, vif); out_unlock: mutex_unlock(&mvm->mutex); @@ -781,19 +771,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); } else if (changes & BSS_CHANGED_PS) { - /* - * TODO: remove this temporary code. - * Currently MVM FW supports power management only on single - * MAC. Avoid power mode update if more than one interface - * is active. - */ - IWL_DEBUG_MAC80211(mvm, "Currently %d interfaces active\n", - mvm->vif_count); - if (mvm->vif_count == 1) { - ret = iwl_mvm_power_update_mode(mvm, vif); - if (ret) - IWL_ERR(mvm, "failed to update power mode\n"); - } + ret = iwl_mvm_power_update_mode(mvm, vif); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); } } diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 67cf24aa72f9..6cb98ce96ac4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -246,6 +246,17 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) return 0; + /* + * TODO: The following vif_count verification is temporary condition. + * Avoid power mode update if more than one interface is currently + * active. Remove this condition when FW will support power management + * on multiple MACs. + */ + IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n", + mvm->vif_count); + if (mvm->vif_count > 1) + return 0; + iwl_mvm_power_build_cmd(mvm, vif, &cmd); iwl_mvm_power_log(mvm, &cmd); -- GitLab From 3430140ad9da9ec1caaf800af6b0378351919f9c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 4 Jun 2013 14:35:07 +0200 Subject: [PATCH 0638/2900] regulatory: use proper enum return value get_reg_request_treatment() returns 0 in one case but is defined to return an enum, use the proper value REG_REQ_OK. Signed-off-by: Johannes Berg --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e1d6749234c6..5a24c986f34b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1345,7 +1345,7 @@ get_reg_request_treatment(struct wiphy *wiphy, return REG_REQ_OK; return REG_REQ_ALREADY_SET; } - return 0; + return REG_REQ_OK; case NL80211_REGDOM_SET_BY_DRIVER: if (lr->initiator == NL80211_REGDOM_SET_BY_CORE) { if (regdom_changes(pending_request->alpha2)) -- GitLab From 75698b17ac3b681f4345a9be48b147381d17266d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 31 May 2013 15:05:47 +0000 Subject: [PATCH 0639/2900] Clean up indentation in net/ipv6/transp_v6.h Reduce the indentation of most of the functions and make it a bit more consistent. This allows longer function and arg names to be consistently indented without wrapping. Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/transp_v6.h | 70 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index eb40e71ff2ee..2d9d0e3115b9 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -7,47 +7,47 @@ * IPv6 transport protocols */ -extern struct proto rawv6_prot; -extern struct proto udpv6_prot; -extern struct proto udplitev6_prot; -extern struct proto tcpv6_prot; -extern struct proto pingv6_prot; +extern struct proto rawv6_prot; +extern struct proto udpv6_prot; +extern struct proto udplitev6_prot; +extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; /* extension headers */ -extern int ipv6_exthdrs_init(void); -extern void ipv6_exthdrs_exit(void); -extern int ipv6_frag_init(void); -extern void ipv6_frag_exit(void); +extern int ipv6_exthdrs_init(void); +extern void ipv6_exthdrs_exit(void); +extern int ipv6_frag_init(void); +extern void ipv6_frag_exit(void); /* transport protocols */ -extern int pingv6_init(void); -extern void pingv6_exit(void); -extern int rawv6_init(void); -extern void rawv6_exit(void); -extern int udpv6_init(void); -extern void udpv6_exit(void); -extern int udplitev6_init(void); -extern void udplitev6_exit(void); -extern int tcpv6_init(void); -extern void tcpv6_exit(void); - -extern int udpv6_connect(struct sock *sk, - struct sockaddr *uaddr, - int addr_len); - -extern int ip6_datagram_recv_ctl(struct sock *sk, - struct msghdr *msg, - struct sk_buff *skb); - -extern int ip6_datagram_send_ctl(struct net *net, - struct sock *sk, - struct msghdr *msg, - struct flowi6 *fl6, - struct ipv6_txoptions *opt, - int *hlimit, int *tclass, - int *dontfrag); +extern int pingv6_init(void); +extern void pingv6_exit(void); +extern int rawv6_init(void); +extern void rawv6_exit(void); +extern int udpv6_init(void); +extern void udpv6_exit(void); +extern int udplitev6_init(void); +extern void udplitev6_exit(void); +extern int tcpv6_init(void); +extern void tcpv6_exit(void); + +extern int udpv6_connect(struct sock *sk, + struct sockaddr *uaddr, + int addr_len); + +extern int ip6_datagram_recv_ctl(struct sock *sk, + struct msghdr *msg, + struct sk_buff *skb); + +extern int ip6_datagram_send_ctl(struct net *net, + struct sock *sk, + struct msghdr *msg, + struct flowi6 *fl6, + struct ipv6_txoptions *opt, + int *hlimit, int *tclass, + int *dontfrag); #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) -- GitLab From 17ef66afc0bdbbdc5c526db5e24bdd2dc3df1205 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 31 May 2013 15:05:48 +0000 Subject: [PATCH 0640/2900] net: ipv6: Unify {raw,udp}6_sock_seq_show. udp6_sock_seq_show and raw6_sock_seq_show are identical, except the UDP version displays ports and the raw version displays the protocol. Refactor most of the code in these two functions into a new common ip6_dgram_sock_seq_show function, in preparation for using it to display ICMPv6 sockets as well. Also reduce the indentation in parts of include/net/transp_v6.h to improve readability. Compiles and displays reasonable results with CONFIG_IPV6={n,m,y} Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/transp_v6.h | 13 +++++++++++ net/ipv6/datagram.c | 27 +++++++++++++++++++++++ net/ipv6/raw.c | 45 +++++++------------------------------ net/ipv6/udp.c | 49 ++++++++--------------------------------- 4 files changed, 57 insertions(+), 77 deletions(-) diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 2d9d0e3115b9..6dddc08f27c9 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -49,6 +49,12 @@ extern int ip6_datagram_send_ctl(struct net *net, int *hlimit, int *tclass, int *dontfrag); +extern void ip6_dgram_sock_seq_show(struct seq_file *seq, + struct sock *sp, + __u16 srcp, + __u16 destp, + int bucket); + #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) /* @@ -58,4 +64,11 @@ extern const struct inet_connection_sock_af_ops ipv4_specific; extern void inet6_destroy_sock(struct sock *sk); +#define IPV6_SEQ_DGRAM_HEADER \ + " sl " \ + "local_address " \ + "remote_address " \ + "st tx_queue rx_queue tr tm->when retrnsmt" \ + " uid timeout inode ref pointer drops\n" + #endif diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 4b56cbbc7890..197e6f4a2b74 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -879,3 +879,30 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, return err; } EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl); + +void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, + __u16 srcp, __u16 destp, int bucket) +{ + struct ipv6_pinfo *np = inet6_sk(sp); + const struct in6_addr *dest, *src; + + dest = &np->daddr; + src = &np->rcv_saddr; + seq_printf(seq, + "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", + bucket, + src->s6_addr32[0], src->s6_addr32[1], + src->s6_addr32[2], src->s6_addr32[3], srcp, + dest->s6_addr32[0], dest->s6_addr32[1], + dest->s6_addr32[2], dest->s6_addr32[3], destp, + sp->sk_state, + sk_wmem_alloc_get(sp), + sk_rmem_alloc_get(sp), + 0, 0L, 0, + from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), + 0, + sock_i_ino(sp), + atomic_read(&sp->sk_refcnt), sp, + atomic_read(&sp->sk_drops)); +} diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4f8886aa8429..c45f7a5c36e9 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1227,45 +1227,16 @@ struct proto rawv6_prot = { }; #ifdef CONFIG_PROC_FS -static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) -{ - struct ipv6_pinfo *np = inet6_sk(sp); - const struct in6_addr *dest, *src; - __u16 destp, srcp; - - dest = &np->daddr; - src = &np->rcv_saddr; - destp = 0; - srcp = inet_sk(sp)->inet_num; - seq_printf(seq, - "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", - i, - src->s6_addr32[0], src->s6_addr32[1], - src->s6_addr32[2], src->s6_addr32[3], srcp, - dest->s6_addr32[0], dest->s6_addr32[1], - dest->s6_addr32[2], dest->s6_addr32[3], destp, - sp->sk_state, - sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), - 0, 0L, 0, - from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), - 0, - sock_i_ino(sp), - atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); -} - static int raw6_seq_show(struct seq_file *seq, void *v) { - if (v == SEQ_START_TOKEN) - seq_printf(seq, - " sl " - "local_address " - "remote_address " - "st tx_queue rx_queue tr tm->when retrnsmt" - " uid timeout inode ref pointer drops\n"); - else - raw6_sock_seq_show(seq, v, raw_seq_private(seq)->bucket); + if (v == SEQ_START_TOKEN) { + seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); + } else { + struct sock *sp = v; + __u16 srcp = inet_sk(sp)->inet_num; + ip6_dgram_sock_seq_show(seq, v, srcp, 0, + raw_seq_private(seq)->bucket); + } return 0; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 42923b14dfa6..b5808539cd5c 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1359,48 +1359,17 @@ static const struct inet6_protocol udpv6_protocol = { /* ------------------------------------------------------------------------ */ #ifdef CONFIG_PROC_FS - -static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket) -{ - struct inet_sock *inet = inet_sk(sp); - struct ipv6_pinfo *np = inet6_sk(sp); - const struct in6_addr *dest, *src; - __u16 destp, srcp; - - dest = &np->daddr; - src = &np->rcv_saddr; - destp = ntohs(inet->inet_dport); - srcp = ntohs(inet->inet_sport); - seq_printf(seq, - "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", - bucket, - src->s6_addr32[0], src->s6_addr32[1], - src->s6_addr32[2], src->s6_addr32[3], srcp, - dest->s6_addr32[0], dest->s6_addr32[1], - dest->s6_addr32[2], dest->s6_addr32[3], destp, - sp->sk_state, - sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), - 0, 0L, 0, - from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), - 0, - sock_i_ino(sp), - atomic_read(&sp->sk_refcnt), sp, - atomic_read(&sp->sk_drops)); -} - int udp6_seq_show(struct seq_file *seq, void *v) { - if (v == SEQ_START_TOKEN) - seq_printf(seq, - " sl " - "local_address " - "remote_address " - "st tx_queue rx_queue tr tm->when retrnsmt" - " uid timeout inode ref pointer drops\n"); - else - udp6_sock_seq_show(seq, v, ((struct udp_iter_state *)seq->private)->bucket); + if (v == SEQ_START_TOKEN) { + seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); + } else { + int bucket = ((struct udp_iter_state *)seq->private)->bucket; + struct inet_sock *inet = inet_sk(v); + __u16 srcp = ntohs(inet->inet_sport); + __u16 destp = ntohs(inet->inet_dport); + ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); + } return 0; } -- GitLab From 8cc785f6f429c2a3fb81745dc142cbd72a462c4a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 31 May 2013 15:05:49 +0000 Subject: [PATCH 0641/2900] net: ipv4: make the ping /proc code AF-independent Introduce a ping_seq_afinfo structure (similar to its UDP equivalent) and use it to make some of the ping /proc functions address-family independent. Rename the remaining ping /proc functions from ping_* to ping_v4_*. Compiles and displays reasonable results with CONFIG_IPV6={n,m,y} Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/ping.h | 8 +++++ net/ipv4/ping.c | 73 +++++++++++++++++++++++++++++----------------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/include/net/ping.h b/include/net/ping.h index 9242fa090d3d..b9282f019804 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -49,6 +49,7 @@ struct ping_table { struct ping_iter_state { struct seq_net_private p; int bucket; + sa_family_t family; }; extern struct proto ping_prot; @@ -87,6 +88,13 @@ int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); void ping_rcv(struct sk_buff *skb); #ifdef CONFIG_PROC_FS +struct ping_seq_afinfo { + char *name; + sa_family_t family; + const struct file_operations *seq_fops; + const struct seq_operations seq_ops; +}; + extern int __init ping_proc_init(void); extern void ping_proc_exit(void); #endif diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 71f6ad02fa67..8c2da9b8cd86 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -1001,7 +1001,8 @@ static struct sock *ping_get_first(struct seq_file *seq, int start) continue; sk_nulls_for_each(sk, node, hslot) { - if (net_eq(sock_net(sk), net)) + if (net_eq(sock_net(sk), net) && + sk->sk_family == state->family) goto found; } } @@ -1034,16 +1035,23 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) return pos ? NULL : sk; } -static void *ping_seq_start(struct seq_file *seq, loff_t *pos) +static void *ping_seq_start(struct seq_file *seq, loff_t *pos, + sa_family_t family) { struct ping_iter_state *state = seq->private; state->bucket = 0; + state->family = family; read_lock_bh(&ping_table.lock); return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN; } +static void *ping_v4_seq_start(struct seq_file *seq, loff_t *pos) +{ + return ping_seq_start(seq, pos, AF_INET); +} + static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; @@ -1062,7 +1070,7 @@ static void ping_seq_stop(struct seq_file *seq, void *v) read_unlock_bh(&ping_table.lock); } -static void ping_format_sock(struct sock *sp, struct seq_file *f, +static void ping_v4_format_sock(struct sock *sp, struct seq_file *f, int bucket, int *len) { struct inet_sock *inet = inet_sk(sp); @@ -1083,7 +1091,7 @@ static void ping_format_sock(struct sock *sp, struct seq_file *f, atomic_read(&sp->sk_drops), len); } -static int ping_seq_show(struct seq_file *seq, void *v) +static int ping_v4_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) seq_printf(seq, "%-127s\n", @@ -1094,22 +1102,23 @@ static int ping_seq_show(struct seq_file *seq, void *v) struct ping_iter_state *state = seq->private; int len; - ping_format_sock(v, seq, state->bucket, &len); + ping_v4_format_sock(v, seq, state->bucket, &len); seq_printf(seq, "%*s\n", 127 - len, ""); } return 0; } -static const struct seq_operations ping_seq_ops = { - .show = ping_seq_show, - .start = ping_seq_start, +static const struct seq_operations ping_v4_seq_ops = { + .show = ping_v4_seq_show, + .start = ping_v4_seq_start, .next = ping_seq_next, .stop = ping_seq_stop, }; static int ping_seq_open(struct inode *inode, struct file *file) { - return seq_open_net(inode, file, &ping_seq_ops, + struct ping_seq_afinfo *afinfo = PDE_DATA(inode); + return seq_open_net(inode, file, &afinfo->seq_ops, sizeof(struct ping_iter_state)); } @@ -1120,46 +1129,58 @@ static const struct file_operations ping_seq_fops = { .release = seq_release_net, }; -static int ping_proc_register(struct net *net) +static struct ping_seq_afinfo ping_v4_seq_afinfo = { + .name = "icmp", + .family = AF_INET, + .seq_fops = &ping_seq_fops, + .seq_ops = { + .start = ping_v4_seq_start, + .show = ping_v4_seq_show, + .next = ping_seq_next, + .stop = ping_seq_stop, + }, +}; + +static int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo) { struct proc_dir_entry *p; - int rc = 0; - - p = proc_create("icmp", S_IRUGO, net->proc_net, &ping_seq_fops); + p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net, + afinfo->seq_fops, afinfo); if (!p) - rc = -ENOMEM; - return rc; + return -ENOMEM; + return 0; } -static void ping_proc_unregister(struct net *net) +static void ping_proc_unregister(struct net *net, + struct ping_seq_afinfo *afinfo) { - remove_proc_entry("icmp", net->proc_net); + remove_proc_entry(afinfo->name, net->proc_net); } -static int __net_init ping_proc_init_net(struct net *net) +static int __net_init ping_v4_proc_init_net(struct net *net) { - return ping_proc_register(net); + return ping_proc_register(net, &ping_v4_seq_afinfo); } -static void __net_exit ping_proc_exit_net(struct net *net) +static void __net_exit ping_v4_proc_exit_net(struct net *net) { - ping_proc_unregister(net); + ping_proc_unregister(net, &ping_v4_seq_afinfo); } -static struct pernet_operations ping_net_ops = { - .init = ping_proc_init_net, - .exit = ping_proc_exit_net, +static struct pernet_operations ping_v4_net_ops = { + .init = ping_v4_proc_init_net, + .exit = ping_v4_proc_exit_net, }; int __init ping_proc_init(void) { - return register_pernet_subsys(&ping_net_ops); + return register_pernet_subsys(&ping_v4_net_ops); } void ping_proc_exit(void) { - unregister_pernet_subsys(&ping_net_ops); + unregister_pernet_subsys(&ping_v4_net_ops); } #endif -- GitLab From d862e546142328d18377a4704be97f2ae301847a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 31 May 2013 15:05:50 +0000 Subject: [PATCH 0642/2900] net: ipv6: Implement /proc/net/icmp6. The format is based on /proc/net/icmp and /proc/net/{udp,raw}6. Compiles and displays reasonable results with CONFIG_IPV6={n,m,y} Couldn't figure out how to test without CONFIG_PROC_FS enabled. Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/ping.h | 8 ++++ net/ipv4/ping.c | 21 ++++++---- net/ipv6/ping.c | 102 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/include/net/ping.h b/include/net/ping.h index b9282f019804..db04802f1673 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -95,6 +95,14 @@ struct ping_seq_afinfo { const struct seq_operations seq_ops; }; +extern const struct file_operations ping_seq_fops; + +void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family); +void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos); +void ping_seq_stop(struct seq_file *seq, void *v); +int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo); +void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo); + extern int __init ping_proc_init(void); extern void ping_proc_exit(void); #endif diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 8c2da9b8cd86..3552a45a6f86 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -1035,8 +1035,7 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) return pos ? NULL : sk; } -static void *ping_seq_start(struct seq_file *seq, loff_t *pos, - sa_family_t family) +void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family) { struct ping_iter_state *state = seq->private; state->bucket = 0; @@ -1046,13 +1045,14 @@ static void *ping_seq_start(struct seq_file *seq, loff_t *pos, return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN; } +EXPORT_SYMBOL_GPL(ping_seq_start); static void *ping_v4_seq_start(struct seq_file *seq, loff_t *pos) { return ping_seq_start(seq, pos, AF_INET); } -static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) +void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; @@ -1064,11 +1064,13 @@ static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) ++*pos; return sk; } +EXPORT_SYMBOL_GPL(ping_seq_next); -static void ping_seq_stop(struct seq_file *seq, void *v) +void ping_seq_stop(struct seq_file *seq, void *v) { read_unlock_bh(&ping_table.lock); } +EXPORT_SYMBOL_GPL(ping_seq_stop); static void ping_v4_format_sock(struct sock *sp, struct seq_file *f, int bucket, int *len) @@ -1122,12 +1124,13 @@ static int ping_seq_open(struct inode *inode, struct file *file) sizeof(struct ping_iter_state)); } -static const struct file_operations ping_seq_fops = { +const struct file_operations ping_seq_fops = { .open = ping_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release_net, }; +EXPORT_SYMBOL_GPL(ping_seq_fops); static struct ping_seq_afinfo ping_v4_seq_afinfo = { .name = "icmp", @@ -1141,7 +1144,7 @@ static struct ping_seq_afinfo ping_v4_seq_afinfo = { }, }; -static int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo) +int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo) { struct proc_dir_entry *p; p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net, @@ -1150,13 +1153,13 @@ static int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo) return -ENOMEM; return 0; } +EXPORT_SYMBOL_GPL(ping_proc_register); -static void ping_proc_unregister(struct net *net, - struct ping_seq_afinfo *afinfo) +void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo) { remove_proc_entry(afinfo->name, net->proc_net); } - +EXPORT_SYMBOL_GPL(ping_proc_unregister); static int __net_init ping_v4_proc_init_net(struct net *net) { diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index a6462d657c15..62ac5f2e0aaf 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -78,29 +78,6 @@ int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, return 0; } -int __init pingv6_init(void) -{ - pingv6_ops.ipv6_recv_error = ipv6_recv_error; - pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl; - pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; - pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; - pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; - return inet6_register_protosw(&pingv6_protosw); -} - -/* This never gets called because it's not possible to unload the ipv6 module, - * but just in case. - */ -void pingv6_exit(void) -{ - pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; - pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl; - pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; - pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; - pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; - inet6_unregister_protosw(&pingv6_protosw); -} - int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { @@ -214,3 +191,82 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, return err; } + +#ifdef CONFIG_PROC_FS +static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos) +{ + return ping_seq_start(seq, pos, AF_INET6); +} + +int ping_v6_seq_show(struct seq_file *seq, void *v) +{ + if (v == SEQ_START_TOKEN) { + seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); + } else { + int bucket = ((struct ping_iter_state *) seq->private)->bucket; + struct inet_sock *inet = inet_sk(v); + __u16 srcp = ntohs(inet->inet_sport); + __u16 destp = ntohs(inet->inet_dport); + ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket); + } + return 0; +} + +static struct ping_seq_afinfo ping_v6_seq_afinfo = { + .name = "icmp6", + .family = AF_INET6, + .seq_fops = &ping_seq_fops, + .seq_ops = { + .start = ping_v6_seq_start, + .show = ping_v6_seq_show, + .next = ping_seq_next, + .stop = ping_seq_stop, + }, +}; + +static int __net_init ping_v6_proc_init_net(struct net *net) +{ + return ping_proc_register(net, &ping_v6_seq_afinfo); +} + +static void __net_init ping_v6_proc_exit_net(struct net *net) +{ + return ping_proc_unregister(net, &ping_v6_seq_afinfo); +} + +static struct pernet_operations ping_v6_net_ops = { + .init = ping_v6_proc_init_net, + .exit = ping_v6_proc_exit_net, +}; +#endif + +int __init pingv6_init(void) +{ +#ifdef CONFIG_PROC_FS + int ret = register_pernet_subsys(&ping_v6_net_ops); + if (ret) + return ret; +#endif + pingv6_ops.ipv6_recv_error = ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; + return inet6_register_protosw(&pingv6_protosw); +} + +/* This never gets called because it's not possible to unload the ipv6 module, + * but just in case. + */ +void pingv6_exit(void) +{ + pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; +#ifdef CONFIG_PROC_FS + unregister_pernet_subsys(&ping_v6_net_ops); +#endif + inet6_unregister_protosw(&pingv6_protosw); +} -- GitLab From 256c90dedf538c59c70e65ba1a1340ce793c5b37 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 4 Jun 2013 19:21:08 +0200 Subject: [PATCH 0643/2900] cfg80211: fix potential deadlock regression My big locking cleanups caused a problem by registering the rfkill instance with the RTNL held, while the callback also acquires the RTNL. This potentially causes a deadlock since the two locks used (rfkill mutex and RTNL) can be acquired in two different orders. Fix this by (un)registering rfkill without holding the RTNL. This needs to be done after the device struct is registered, but that can also be done w/o holding the RTNL. Signed-off-by: Johannes Berg --- net/wireless/core.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 221e76b53a97..99d86ddb6331 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -555,14 +555,18 @@ int wiphy_register(struct wiphy *wiphy) /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); - rtnl_lock(); res = device_add(&rdev->wiphy.dev); + if (res) + return res; + + res = rfkill_register(rdev->rfkill); if (res) { - rtnl_unlock(); + device_del(&rdev->wiphy.dev); return res; } + rtnl_lock(); /* set up regulatory info */ wiphy_regulatory_register(wiphy); @@ -589,17 +593,6 @@ int wiphy_register(struct wiphy *wiphy) cfg80211_debugfs_rdev_add(rdev); - res = rfkill_register(rdev->rfkill); - if (res) { - device_del(&rdev->wiphy.dev); - - debugfs_remove_recursive(rdev->wiphy.debugfsdir); - list_del_rcu(&rdev->list); - wiphy_regulatory_deregister(wiphy); - rtnl_unlock(); - return res; - } - rdev->wiphy.registered = true; rtnl_unlock(); return 0; @@ -636,11 +629,11 @@ void wiphy_unregister(struct wiphy *wiphy) rtnl_unlock(); __count == 0; })); + rfkill_unregister(rdev->rfkill); + rtnl_lock(); rdev->wiphy.registered = false; - rfkill_unregister(rdev->rfkill); - BUG_ON(!list_empty(&rdev->wdev_list)); /* -- GitLab From 9b881963c1c81f965f89a3e89b1aa5557f67ee30 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 4 Jun 2013 22:23:36 +0200 Subject: [PATCH 0644/2900] cfg80211: make wiphy index start at 0 again The change to use atomic_inc_return() for assigning the wiphy index made the first wiphy index 1 instead of 0. This is fine, but we all habitually type "phy0" when we're testing, so make it go back to 0 instead of 1 by subtracting 1 from the index. Signed-off-by: Johannes Berg --- net/wireless/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/wireless/core.c b/net/wireless/core.c index 99d86ddb6331..4224e7554a76 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -301,6 +301,9 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) return NULL; } + /* atomic_inc_return makes it start at 1, make it start at 0 */ + rdev->wiphy_idx--; + /* give it a proper name */ dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); -- GitLab From 317420ab2370d7999ec6c324bc30b34dc57fe9d8 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:04 +0000 Subject: [PATCH 0645/2900] drivers: net: phy: at803x code cleanup on register and unregister driver Make use of phy_drivers_register/phy_drivers_unregister to register/unregister multiple phy drivers in a single module. Cc: Matus Ujhelyi Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 45cbc10de01c..a1063e1bfc90 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -108,8 +108,9 @@ static int at803x_config_init(struct phy_device *phydev) return 0; } -/* ATHEROS 8035 */ -static struct phy_driver at8035_driver = { +static struct phy_driver at803x_driver[] = { +{ + /* ATHEROS 8035 */ .phy_id = 0x004dd072, .name = "Atheros 8035 ethernet", .phy_id_mask = 0xffffffef, @@ -121,10 +122,8 @@ static struct phy_driver at8035_driver = { .driver = { .owner = THIS_MODULE, }, -}; - -/* ATHEROS 8030 */ -static struct phy_driver at8030_driver = { +}, { + /* ATHEROS 8030 */ .phy_id = 0x004dd076, .name = "Atheros 8030 ethernet", .phy_id_mask = 0xffffffef, @@ -136,32 +135,18 @@ static struct phy_driver at8030_driver = { .driver = { .owner = THIS_MODULE, }, -}; +} }; static int __init atheros_init(void) { - int ret; - - ret = phy_driver_register(&at8035_driver); - if (ret) - goto err1; - - ret = phy_driver_register(&at8030_driver); - if (ret) - goto err2; - - return 0; - -err2: - phy_driver_unregister(&at8035_driver); -err1: - return ret; + return phy_drivers_register(at803x_driver, + ARRAY_SIZE(at803x_driver)); } static void __exit atheros_exit(void) { - phy_driver_unregister(&at8035_driver); - phy_driver_unregister(&at8030_driver); + return phy_drivers_unregister(at803x_driver, + ARRAY_SIZE(at803x_driver)); } module_init(atheros_init); -- GitLab From ea13c9ee855cc60973458d1adeee9b35f0466a29 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:05 +0000 Subject: [PATCH 0646/2900] drivers: net: phy: at803x: seperate wol specific code to wol standard apis WOL is initilized in phy config_init, but there are standard apis (set_wol/get_wol) for WOL in phy frame work. So this patch moves WOL specific code from config_init to wol standard apis. Cc: Matus Ujhelyi Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 64 ++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index a1063e1bfc90..63444b7b7013 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -32,10 +32,13 @@ MODULE_DESCRIPTION("Atheros 803x PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); MODULE_LICENSE("GPL"); -static void at803x_set_wol_mac_addr(struct phy_device *phydev) +static int at803x_set_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) { struct net_device *ndev = phydev->attached_dev; const u8 *mac; + int ret; + u32 value; unsigned int i, offsets[] = { AT803X_LOC_MAC_ADDR_32_47_OFFSET, AT803X_LOC_MAC_ADDR_16_31_OFFSET, @@ -43,30 +46,60 @@ static void at803x_set_wol_mac_addr(struct phy_device *phydev) }; if (!ndev) - return; + return -ENODEV; - mac = (const u8 *) ndev->dev_addr; + if (wol->wolopts & WAKE_MAGIC) { + mac = (const u8 *) ndev->dev_addr; - if (!is_valid_ether_addr(mac)) - return; + if (!is_valid_ether_addr(mac)) + return -EFAULT; - for (i = 0; i < 3; i++) { - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + for (i = 0; i < 3; i++) { + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, AT803X_DEVICE_ADDR); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, offsets[i]); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, AT803X_FUNC_DATA); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + } + + value = phy_read(phydev, AT803X_INTR_ENABLE); + value |= AT803X_WOL_ENABLE; + ret = phy_write(phydev, AT803X_INTR_ENABLE, value); + if (ret) + return ret; + value = phy_read(phydev, AT803X_INTR_STATUS); + } else { + value = phy_read(phydev, AT803X_INTR_ENABLE); + value &= (~AT803X_WOL_ENABLE); + ret = phy_write(phydev, AT803X_INTR_ENABLE, value); + if (ret) + return ret; + value = phy_read(phydev, AT803X_INTR_STATUS); } + + return ret; +} + +static void at803x_get_wol(struct phy_device *phydev, + struct ethtool_wolinfo *wol) +{ + u32 value; + + wol->supported = WAKE_MAGIC; + wol->wolopts = 0; + + value = phy_read(phydev, AT803X_INTR_ENABLE); + if (value & AT803X_WOL_ENABLE) + wol->wolopts |= WAKE_MAGIC; } static int at803x_config_init(struct phy_device *phydev) { int val; u32 features; - int status; features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | SUPPORTED_FIBRE | SUPPORTED_BNC; @@ -100,11 +133,6 @@ static int at803x_config_init(struct phy_device *phydev) phydev->supported = features; phydev->advertising = features; - /* enable WOL */ - at803x_set_wol_mac_addr(phydev); - status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); - status = phy_read(phydev, AT803X_INTR_STATUS); - return 0; } @@ -115,6 +143,8 @@ static struct phy_driver at803x_driver[] = { .name = "Atheros 8035 ethernet", .phy_id_mask = 0xffffffef, .config_init = at803x_config_init, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_aneg = &genphy_config_aneg, @@ -128,6 +158,8 @@ static struct phy_driver at803x_driver[] = { .name = "Atheros 8030 ethernet", .phy_id_mask = 0xffffffef, .config_init = at803x_config_init, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .config_aneg = &genphy_config_aneg, -- GitLab From 1ca6d1b1aef4628ff0fe458135ddb008d134ad8f Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:06 +0000 Subject: [PATCH 0647/2900] drivers: net: phy: at803x: add interface mode support This patch adds support for RGMII TX delay configuration on Atheros 803X, this can be enabled in debug registers. With this patch, PHY_INTERFACE_MODE_RGMII_TXID modes are now supported. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 63444b7b7013..dda07edf4173 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -27,6 +27,10 @@ #define AT803X_MMD_ACCESS_CONTROL 0x0D #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E #define AT803X_FUNC_DATA 0x4003 +#define AT803X_DEBUG_ADDR 0x1D +#define AT803X_DEBUG_DATA 0x1E +#define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05 +#define AT803X_DEBUG_RGMII_TX_CLK_DLY BIT(8) MODULE_DESCRIPTION("Atheros 803x PHY driver"); MODULE_AUTHOR("Matus Ujhelyi"); @@ -99,6 +103,7 @@ static void at803x_get_wol(struct phy_device *phydev, static int at803x_config_init(struct phy_device *phydev) { int val; + int ret; u32 features; features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | @@ -133,6 +138,17 @@ static int at803x_config_init(struct phy_device *phydev) phydev->supported = features; phydev->advertising = features; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { + ret = phy_write(phydev, AT803X_DEBUG_ADDR, + AT803X_DEBUG_SYSTEM_MODE_CTRL); + if (ret) + return ret; + ret = phy_write(phydev, AT803X_DEBUG_DATA, + AT803X_DEBUG_RGMII_TX_CLK_DLY); + if (ret) + return ret; + } + return 0; } -- GitLab From 05d7cce8fe11758868f60fc03a83b638700901d8 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:07 +0000 Subject: [PATCH 0648/2900] drivers: net: phy: at803x: add support for AT8031 This patch adds support for Atheros 8031 phy driver. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index dda07edf4173..1f7091b3c27c 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -183,6 +183,21 @@ static struct phy_driver at803x_driver[] = { .driver = { .owner = THIS_MODULE, }, +}, { + /* ATHEROS 8031 */ + .phy_id = 0x004dd074, + .name = "Atheros 8031 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .set_wol = at803x_set_wol, + .get_wol = at803x_get_wol, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, } }; static int __init atheros_init(void) -- GitLab From b40fbbfc05a5a63e8d4fbc8fdb5f0e78e8627ae4 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:08 +0000 Subject: [PATCH 0649/2900] ARM: OMAP2+: omap2plus_defconfig: Enable Atheros support Enable Atheros 803X phy driver support in defconfig which is present in AM335x EVM and EVM Starter Kit. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 435d69b83e32..aa2100919ee5 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -283,3 +283,4 @@ CONFIG_SOC_OMAP5=y CONFIG_TI_DAVINCI_MDIO=y CONFIG_TI_DAVINCI_CPDMA=y CONFIG_TI_CPSW=y +CONFIG_AT803X_PHY=y -- GitLab From f6655d697b85f75d2a1f4f6a03dd2d4c3549e321 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:09 +0000 Subject: [PATCH 0650/2900] ARM: dts: AM33XX: Add CPSW phy_id device tree data to am335x-evmsk Add phy_id device tree data to am335x-evmsk device to bring up CPSW ethernet present on am335x starter kit. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- arch/arm/boot/dts/am335x-evmsk.dts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index f67c360844f4..acbcac340975 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -248,3 +248,11 @@ }; }; }; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; +}; -- GitLab From c5ceea7a2813fecded01567383cca4d6855164ab Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:10 +0000 Subject: [PATCH 0651/2900] drivers: net: ethernet: cpsw: add phy-mode support to cpsw driver Adding phy-mode support to cpsw driver and updating the cpsw binding documentation. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/cpsw.txt | 6 ++++++ drivers/net/ethernet/ti/cpsw.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt index 4f2ca6b4a182..05d660e4ac64 100644 --- a/Documentation/devicetree/bindings/net/cpsw.txt +++ b/Documentation/devicetree/bindings/net/cpsw.txt @@ -28,6 +28,8 @@ Optional properties: Slave Properties: Required properties: - phy_id : Specifies slave phy id +- phy-mode : The interface between the SoC and the PHY (a string + that of_get_phy_mode() can understand) - mac-address : Specifies slave MAC address Optional properties: @@ -58,11 +60,13 @@ Examples: cpts_clock_shift = <29>; cpsw_emac0: slave@0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; cpsw_emac1: slave@1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; @@ -84,11 +88,13 @@ Examples: cpts_clock_shift = <29>; cpsw_emac0: slave@0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; cpsw_emac1: slave@1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; /* Filled in by U-Boot */ mac-address = [ 00 00 00 00 00 00 ]; }; diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 89a4c40d6d83..a45f64eef870 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1554,6 +1554,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, if (mac_addr) memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); + slave_data->phy_if = of_get_phy_mode(slave_node); + if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", &prop)) { -- GitLab From 6d75afe2916adf9e9de6862275cdf89b9b7e4d0e Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 3 Jun 2013 20:10:11 +0000 Subject: [PATCH 0652/2900] ARM: dts: AM33XX: Add phy-mode to CPSW node Adding phy-mode to CPSW node for beaglebone, EVM and EVMsk. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- arch/arm/boot/dts/am335x-bone.dts | 2 ++ arch/arm/boot/dts/am335x-evm.dts | 2 ++ arch/arm/boot/dts/am335x-evmsk.dts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts index 5302f79c05b7..4b5a8e065dcb 100644 --- a/arch/arm/boot/dts/am335x-bone.dts +++ b/arch/arm/boot/dts/am335x-bone.dts @@ -131,8 +131,10 @@ &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "mii"; }; &cpsw_emac1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "mii"; }; diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index 0423298a26fe..814ee037fd51 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -239,8 +239,10 @@ &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; }; &cpsw_emac1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; }; diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts index acbcac340975..4297899a2470 100644 --- a/arch/arm/boot/dts/am335x-evmsk.dts +++ b/arch/arm/boot/dts/am335x-evmsk.dts @@ -251,8 +251,10 @@ &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii-txid"; }; &cpsw_emac1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; }; -- GitLab From ebd4687af732a903f6822bb129d2f3a7d830e798 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Sat, 1 Jun 2013 16:23:15 +0000 Subject: [PATCH 0653/2900] xfrm: simplify the exit path of xfrm_output_one() Clean up unnecessary assignment and jump. While there, fix up the label name. Signed-off-by: Jean Sacren Signed-off-by: David S. Miller --- net/xfrm/xfrm_output.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 0cf003dfa8fc..eb4a84288648 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -89,7 +89,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) err = x->type->output(x, skb); if (err == -EINPROGRESS) - goto out_exit; + goto out; resume: if (err) { @@ -107,15 +107,14 @@ static int xfrm_output_one(struct sk_buff *skb, int err) x = dst->xfrm; } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); - err = 0; + return 0; -out_exit: - return err; error: spin_unlock_bh(&x->lock); error_nolock: kfree_skb(skb); - goto out_exit; +out: + return err; } int xfrm_output_resume(struct sk_buff *skb, int err) -- GitLab From 0e9649c143eb9d7ecaaef221fd411e5c747f97ce Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Sat, 1 Jun 2013 16:23:16 +0000 Subject: [PATCH 0654/2900] net: do not manually initialize enumerators Clean up unnecessary initialization of enumerators as the compiler takes care of that. Signed-off-by: Jean Sacren Signed-off-by: David S. Miller --- include/linux/net.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/net.h b/include/linux/net.h index 99c9f0c103c2..4f27575ce1d6 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -79,9 +79,9 @@ enum sock_type { #endif /* ARCH_HAS_SOCKET_TYPES */ enum sock_shutdown_cmd { - SHUT_RD = 0, - SHUT_WR = 1, - SHUT_RDWR = 2, + SHUT_RD, + SHUT_WR, + SHUT_RDWR, }; struct socket_wq { -- GitLab From 4960c2c6fa252d2e90796074427db3f2297b523b Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Sat, 1 Jun 2013 16:23:17 +0000 Subject: [PATCH 0655/2900] Kconfig: remove dangling references to the deleted file Commit 202dc3fc599c1dded235d3b448d9ca924252e354 (Documentation: remove obsolete networking/multicast.txt file) deleted the obsolete file. After the file has been removed, clean up a couple of places where references to the deleted file were made so that users wouldn't be confused when they consult the Help menu. Signed-off-by: Jean Sacren Signed-off-by: David S. Miller --- net/ipv4/Kconfig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 8603ca827104..37cf1a6ea3ad 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -9,10 +9,7 @@ config IP_MULTICAST intend to participate in the MBONE, a high bandwidth network on top of the Internet which carries audio and video broadcasts. More information about the MBONE is on the WWW at - . Information about the multicast - capabilities of the various network cards is contained in - . For most people, it's - safe to say N. + . For most people, it's safe to say N. config IP_ADVANCED_ROUTER bool "IP: advanced router" @@ -223,10 +220,8 @@ config IP_MROUTE packets that have several destination addresses. It is needed on the MBONE, a high bandwidth network on top of the Internet which carries audio and video broadcasts. In order to do that, you would most - likely run the program mrouted. Information about the multicast - capabilities of the various network cards is contained in - . If you haven't heard - about it, you don't need it. + likely run the program mrouted. If you haven't heard about it, you + don't need it. config IP_MROUTE_MULTIPLE_TABLES bool "IP: multicast policy routing" -- GitLab From f145b67f24e6855a026fbe9c9f1df97412044d1d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 2 Jun 2013 07:04:26 +0000 Subject: [PATCH 0656/2900] transp_v6.h: style neatening Use a more current code style. Remove extern from function prototypes. Align function arguments and reflow to 80 cols. Use network comment styles. Signed-off-by: Joe Perches cc: Lorenzo Colitti , Signed-off-by: David S. Miller --- include/net/transp_v6.h | 89 +++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 6dddc08f27c9..48660e50ae90 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -3,72 +3,57 @@ #include -/* - * IPv6 transport protocols - */ - -extern struct proto rawv6_prot; -extern struct proto udpv6_prot; -extern struct proto udplitev6_prot; -extern struct proto tcpv6_prot; -extern struct proto pingv6_prot; +/* IPv6 transport protocols */ +extern struct proto rawv6_prot; +extern struct proto udpv6_prot; +extern struct proto udplitev6_prot; +extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; /* extension headers */ -extern int ipv6_exthdrs_init(void); -extern void ipv6_exthdrs_exit(void); -extern int ipv6_frag_init(void); -extern void ipv6_frag_exit(void); +int ipv6_exthdrs_init(void); +void ipv6_exthdrs_exit(void); +int ipv6_frag_init(void); +void ipv6_frag_exit(void); /* transport protocols */ -extern int pingv6_init(void); -extern void pingv6_exit(void); -extern int rawv6_init(void); -extern void rawv6_exit(void); -extern int udpv6_init(void); -extern void udpv6_exit(void); -extern int udplitev6_init(void); -extern void udplitev6_exit(void); -extern int tcpv6_init(void); -extern void tcpv6_exit(void); +int pingv6_init(void); +void pingv6_exit(void); +int rawv6_init(void); +void rawv6_exit(void); +int udpv6_init(void); +void udpv6_exit(void); +int udplitev6_init(void); +void udplitev6_exit(void); +int tcpv6_init(void); +void tcpv6_exit(void); -extern int udpv6_connect(struct sock *sk, - struct sockaddr *uaddr, - int addr_len); +int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); -extern int ip6_datagram_recv_ctl(struct sock *sk, - struct msghdr *msg, - struct sk_buff *skb); +int ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); -extern int ip6_datagram_send_ctl(struct net *net, - struct sock *sk, - struct msghdr *msg, - struct flowi6 *fl6, - struct ipv6_txoptions *opt, - int *hlimit, int *tclass, - int *dontfrag); +int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, + struct flowi6 *fl6, struct ipv6_txoptions *opt, + int *hlimit, int *tclass, int *dontfrag); -extern void ip6_dgram_sock_seq_show(struct seq_file *seq, - struct sock *sp, - __u16 srcp, - __u16 destp, - int bucket); +void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, + __u16 srcp, __u16 destp, int bucket); -#define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) +#define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006) -/* - * address family specific functions - */ +/* address family specific functions */ extern const struct inet_connection_sock_af_ops ipv4_specific; -extern void inet6_destroy_sock(struct sock *sk); +void inet6_destroy_sock(struct sock *sk); -#define IPV6_SEQ_DGRAM_HEADER \ - " sl " \ - "local_address " \ - "remote_address " \ - "st tx_queue rx_queue tr tm->when retrnsmt" \ - " uid timeout inode ref pointer drops\n" +#define IPV6_SEQ_DGRAM_HEADER \ + " sl " \ + "local_address " \ + "remote_address " \ + "st tx_queue rx_queue tr tm->when retrnsmt" \ + " uid timeout inode ref pointer drops\n" #endif -- GitLab From f1362e378ab27844f968f1f390e33b6c77861ec0 Mon Sep 17 00:00:00 2001 From: "Jens Renner \\(EFE\\)" Date: Sun, 2 Jun 2013 05:19:06 +0000 Subject: [PATCH 0657/2900] net: emaclite: Fix typo in error message s/allocal/allocate/ Signed-off-by: Jens Renner Acked-by: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index aa14d8adcecb..aaadf7e551df 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -877,7 +877,7 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) bus = mdiobus_alloc(); if (!bus) { - dev_err(dev, "Failed to allocal mdiobus\n"); + dev_err(dev, "Failed to allocate mdiobus\n"); return -ENOMEM; } -- GitLab From 430f03cde2fb9596d8b562824471e298a8080df9 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Sun, 2 Jun 2013 20:43:55 +0000 Subject: [PATCH 0658/2900] net: mark netdev_create_hash __net_init netdev_create_hash() is only called from netdev_init() which is marked __net_init. Signed-off-by: Baruch Siach Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index d4d874a25e45..9c18557f93c6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6088,7 +6088,7 @@ netdev_features_t netdev_increment_features(netdev_features_t all, } EXPORT_SYMBOL(netdev_increment_features); -static struct hlist_head *netdev_create_hash(void) +static struct hlist_head * __net_init netdev_create_hash(void) { int i; struct hlist_head *hash; -- GitLab From c26d6b46da3ee86fa8a864347331e5513ca84c2b Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 2 Jun 2013 22:43:52 +0000 Subject: [PATCH 0659/2900] ping: always initialize ->sin6_scope_id and ->sin6_flowinfo If we don't need scope id, we should initialize it to zero. Same for ->sin6_flowinfo. Cc: Lorenzo Colitti Cc: David S. Miller Signed-off-by: Cong Wang Acked-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv4/ping.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 3552a45a6f86..1f1b2dd90277 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -892,12 +892,12 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sin6->sin6_port = 0; sin6->sin6_addr = ip6->saddr; + sin6->sin6_flowinfo = 0; if (np->sndflow) sin6->sin6_flowinfo = ip6_flowinfo(ip6); - if (__ipv6_addr_needs_scope_id( - ipv6_addr_type(&sin6->sin6_addr))) - sin6->sin6_scope_id = IP6CB(skb)->iif; + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); if (inet6_sk(sk)->rxopt.all) pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); -- GitLab From 600fed5e97afca10356952e334f362e82fc71466 Mon Sep 17 00:00:00 2001 From: Yan Burman Date: Mon, 3 Jun 2013 02:03:34 +0000 Subject: [PATCH 0660/2900] net/ethtool: Fix comment regarding location of dev_ethtool() call Signed-off-by: Yan Burman Signed-off-by: David S. Miller --- net/core/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 4e6f63ade741..cd23d314d68a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1414,7 +1414,7 @@ static int ethtool_get_module_eeprom(struct net_device *dev, modinfo.eeprom_len); } -/* The main entry point in this file. Called from net/core/dev.c */ +/* The main entry point in this file. Called from net/core/dev_ioctl.c */ int dev_ethtool(struct net *net, struct ifreq *ifr) { -- GitLab From ff20877ab3be42cf9c21a9b0173db690aa3165b0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2013 03:11:24 +0000 Subject: [PATCH 0661/2900] net: mv643xx_eth: add missing semicolon 76723bca28 "net: mv643xx_eth: add DT parsing support" added a dummy mv643xx_eth_shared_of_probe() fallback function with a typo. This adds the missing semicolon so we can build without CONFIG_OF again, and changes both dummy functions to the more conventional "static inline" syntax, which can avoid potential problems with the empty macro. Signed-off-by: Arnd Bergmann Cc: Sebastian Hesselbarth Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 23ea7b6e23f1..c7f9fb33ce95 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2582,12 +2582,14 @@ static void mv643xx_eth_shared_of_remove(void) } } #else -static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) +static inline int mv643xx_eth_shared_of_probe(struct platform_device *pdev) { - return 0 + return 0; } -#define mv643xx_eth_shared_of_remove() +static inline void mv643xx_eth_shared_of_remove(void) +{ +} #endif static int mv643xx_eth_shared_probe(struct platform_device *pdev) -- GitLab From 93baf4c615584fa02c21aa78f305428fc7060656 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 3 Jun 2013 03:36:52 +0000 Subject: [PATCH 0662/2900] net: sun4i-emac: fix a typo in emac_probe() Just fixed a typo in emac_probe(). Signed-off-by: Wei Yongjun Acked-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/sun4i-emac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index b411344e719e..26083cdc25ab 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -821,7 +821,7 @@ static int emac_probe(struct platform_device *pdev) db->membase = of_iomap(np, 0); if (!db->membase) { dev_err(&pdev->dev, "failed to remap registers\n"); - return -ENOMEM; + ret = -ENOMEM; goto out; } -- GitLab From 8cc3e439ab920703264a62e1b19559b39e20d77e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 4 Jun 2013 04:52:23 +0000 Subject: [PATCH 0663/2900] net: mvneta: read MAC address from hardware when available This patch improves the logic used by the mvneta driver to find a MAC address for a particular interface. Until now, it was only looking at the Device Tree, and if no address was found, was falling back to generating a random MAC address. This patch adds the intermediate solution of reading the MAC address from the hardware registers, in case it has been set by the bootloader. So the order is now: 1) MAC address from the Device Tree 2) MAC address from the hardware registers 3) Random MAC address This requires moving the MAC address initialization a little bit later in the ->probe() code, because it now requires the hardware registers to be remapped. Signed-off-by: Thomas Petazzoni Cc: Sergei Shtylyov Cc: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 44 +++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index cd0ea204ac24..712779fb12b7 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2251,6 +2251,21 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) return 0; } +/* Get mac address */ +static void mvneta_get_mac_addr(struct mvneta_port *pp, unsigned char *addr) +{ + u32 mac_addr_l, mac_addr_h; + + mac_addr_l = mvreg_read(pp, MVNETA_MAC_ADDR_LOW); + mac_addr_h = mvreg_read(pp, MVNETA_MAC_ADDR_HIGH); + addr[0] = (mac_addr_h >> 24) & 0xFF; + addr[1] = (mac_addr_h >> 16) & 0xFF; + addr[2] = (mac_addr_h >> 8) & 0xFF; + addr[3] = mac_addr_h & 0xFF; + addr[4] = (mac_addr_l >> 8) & 0xFF; + addr[5] = mac_addr_l & 0xFF; +} + /* Handle setting mac address */ static int mvneta_set_mac_addr(struct net_device *dev, void *addr) { @@ -2667,7 +2682,9 @@ static int mvneta_probe(struct platform_device *pdev) u32 phy_addr; struct mvneta_port *pp; struct net_device *dev; - const char *mac_addr; + const char *dt_mac_addr; + char hw_mac_addr[ETH_ALEN]; + const char *mac_from; int phy_mode; int err; @@ -2703,13 +2720,6 @@ static int mvneta_probe(struct platform_device *pdev) goto err_free_irq; } - mac_addr = of_get_mac_address(dn); - - if (!mac_addr || !is_valid_ether_addr(mac_addr)) - eth_hw_addr_random(dev); - else - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); - dev->tx_queue_len = MVNETA_MAX_TXD; dev->watchdog_timeo = 5 * HZ; dev->netdev_ops = &mvneta_netdev_ops; @@ -2740,6 +2750,21 @@ static int mvneta_probe(struct platform_device *pdev) clk_prepare_enable(pp->clk); + dt_mac_addr = of_get_mac_address(dn); + if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) { + mac_from = "device tree"; + memcpy(dev->dev_addr, dt_mac_addr, ETH_ALEN); + } else { + mvneta_get_mac_addr(pp, hw_mac_addr); + if (is_valid_ether_addr(hw_mac_addr)) { + mac_from = "hardware"; + memcpy(dev->dev_addr, hw_mac_addr, ETH_ALEN); + } else { + mac_from = "random"; + eth_hw_addr_random(dev); + } + } + pp->tx_done_timer.data = (unsigned long)dev; pp->tx_ring_size = MVNETA_MAX_TXD; @@ -2772,7 +2797,8 @@ static int mvneta_probe(struct platform_device *pdev) goto err_deinit; } - netdev_info(dev, "mac: %pM\n", dev->dev_addr); + netdev_info(dev, "Using %s mac address %pM\n", mac_from, + dev->dev_addr); platform_set_drvdata(pdev, pp->dev); -- GitLab From e6309cff76a6adc0010609d45d34173e524a546d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 3 Jun 2013 07:54:55 +0000 Subject: [PATCH 0664/2900] net/mlx4: use one page fragment per incoming frame mlx4 driver has a suboptimal memory allocation strategy for regular MTU=1500 frames, as it uses two page fragments : One of 512 bytes and one of 1024 bytes. This makes GRO less effective, as each GSO packet contains 8 MSS instead of 16 MSS. Performance of a single TCP flow gains 25 % increase with the following patch. Before patch : A:~# netperf -H 192.168.0.2 -Cc MIGRATED TCP STREAM TEST ... Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 87380 16384 16384 10.00 13798.47 3.06 4.20 0.436 0.598 After patch : A:~# netperf -H 192.68.0.2 -Cc MIGRATED TCP STREAM TEST ... Recv Send Send Utilization Service Demand Socket Socket Message Elapsed Send Recv Send Recv Size Size Size Time Throughput local remote local remote bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB 87380 16384 16384 10.00 17273.80 3.44 4.19 0.391 0.477 Signed-off-by: Eric Dumazet Cc: Amir Vadai Acked-By: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index b1d7657b2bf5..b1f51c1f635c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -98,11 +98,11 @@ #define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384) #define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE) -/* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU +/* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU * and 4K allocations) */ enum { - FRAG_SZ0 = 512 - NET_IP_ALIGN, - FRAG_SZ1 = 1024, + FRAG_SZ0 = 1536 - NET_IP_ALIGN, + FRAG_SZ1 = 4096, FRAG_SZ2 = 4096, FRAG_SZ3 = MLX4_EN_ALLOC_SIZE }; -- GitLab From c08355fb61fb064d141b8bd156145d326f33022f Mon Sep 17 00:00:00 2001 From: "govindarajulu.v" Date: Mon, 3 Jun 2013 08:07:42 +0000 Subject: [PATCH 0665/2900] mlx4: use __netdev_pick_tx instead of __skb_tx_hash in mlx4_en_select_queue mlx4_en_select_queue() uses __skb_tx_hash to select the transmit queue. XPS settings are ignored by this. Instead, we can use __netdev_pick_tx to select the transmit queue. Compile test only. Signed-off-by: govindarajulu.v Acked-By: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 4e6877a032a8..7c492382da09 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -544,7 +544,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb) if (vlan_tx_tag_present(skb)) up = vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT; - return __skb_tx_hash(dev, skb, rings_p_up) + up * rings_p_up; + return __netdev_pick_tx(dev, skb) % rings_p_up + up * rings_p_up; } static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt) -- GitLab From 10e179e364beafc23d837e81cf98d99720f42551 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2013 11:36:50 +0000 Subject: [PATCH 0666/2900] net: sun4i-emac: remove erroneous assignment The newly added sun4i-emac driver causes a build error when CONFIG_NET_POLL_CONTROLLER is set, because it attempts to assign a pointer to netdev->poll_controller, which has been replaced with ops->ndo_poll_controller in 2.6.31! The correct assignment is present as well, so we just need to remove the wrong one. Signed-off-by: Arnd Bergmann Cc: Stefan Roese Cc: Maxime Ripard Cc: Richard Genoud Acked-by: Stefan Roese Acked-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/sun4i-emac.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 26083cdc25ab..0bb2f4af9952 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -869,10 +869,6 @@ static int emac_probe(struct platform_device *pdev) ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->ethtool_ops = &emac_ethtool_ops; -#ifdef CONFIG_NET_POLL_CONTROLLER - ndev->poll_controller = &emac_poll_controller; -#endif - platform_set_drvdata(pdev, ndev); /* Carrier starts down, phylib will bring it up */ -- GitLab From 525cebedb32a87fa48584bc44e14170beb2c10d1 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 3 Jun 2013 11:49:23 +0000 Subject: [PATCH 0667/2900] pktgen: Fix position of ip and udp header skb_set_network_header() expects an offset based on the data pointer whereas skb_tail_offset() also includes the headroom. This resulted in the ip header being written in a wrong location. Use return values of skb_put() directly and rely on skb->len to set mac, network, and transport header. Cc: Simon Horman Cc: Daniel Borkmann Assisted-by: Daniel Borkmann Signed-off-by: Thomas Graf Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/core/pktgen.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index d2ede89662be..303412d8332b 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2642,7 +2642,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ u16 queue_map; - unsigned long tail_offset; if (pkt_dev->nr_labels) protocol = htons(ETH_P_MPLS_UC); @@ -2709,20 +2708,15 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, *vlan_encapsulated_proto = htons(ETH_P_IP); } - tail_offset = skb_tail_offset(skb); - if (tail_offset > 0xffff) { - kfree_skb(skb); - return NULL; - } - skb_set_network_header(skb, tail_offset); - skb->transport_header = skb->network_header + sizeof(struct iphdr); - skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, skb->len); + iph = (struct iphdr *) skb_put(skb, sizeof(struct iphdr)); + + skb_set_transport_header(skb, skb->len); + udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr)); skb_set_queue_mapping(skb, queue_map); skb->priority = pkt_dev->skb_priority; - iph = ip_hdr(skb); - udph = udp_hdr(skb); - memcpy(eth, pkt_dev->hh, 12); *(__be16 *) & eth[12] = protocol; @@ -2752,8 +2746,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, iph->check = 0; iph->check = ip_fast_csum((void *)iph, iph->ihl); skb->protocol = protocol; - skb->mac_header = (skb->network_header - ETH_HLEN - - pkt_dev->pkt_overhead); skb->dev = odev; skb->pkt_type = PACKET_HOST; pktgen_finalize_skb(pkt_dev, skb, datalen); @@ -2781,7 +2773,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ u16 queue_map; - unsigned long tail_offset; if (pkt_dev->nr_labels) protocol = htons(ETH_P_MPLS_UC); @@ -2829,18 +2820,14 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, *vlan_encapsulated_proto = htons(ETH_P_IPV6); } - tail_offset = skb_tail_offset(skb); - if (tail_offset > 0xffff) { - kfree_skb(skb); - return NULL; - } - skb_set_network_header(skb, tail_offset); - skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); - skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); + skb_set_mac_header(skb, 0); + skb_set_network_header(skb, skb->len); + iph = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); + + skb_set_transport_header(skb, skb->len); + udph = (struct udphdr *) skb_put(skb, sizeof(struct udphdr)); skb_set_queue_mapping(skb, queue_map); skb->priority = pkt_dev->skb_priority; - iph = ipv6_hdr(skb); - udph = udp_hdr(skb); memcpy(eth, pkt_dev->hh, 12); *(__be16 *) ð[12] = protocol; @@ -2875,8 +2862,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, iph->daddr = pkt_dev->cur_in6_daddr; iph->saddr = pkt_dev->cur_in6_saddr; - skb->mac_header = (skb->network_header - ETH_HLEN - - pkt_dev->pkt_overhead); skb->protocol = protocol; skb->dev = odev; skb->pkt_type = PACKET_HOST; -- GitLab From 00f97da17a0c8d656d0c9a60b1d7f38735f69817 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Mon, 3 Jun 2013 16:31:36 +0000 Subject: [PATCH 0668/2900] netpoll: fix position of network header Similar to the problem in pktgen, netpoll uses skb_tail_offset() too, as the code is copied from pktgen. Also use return values of skb_put() directly, this will simiplify the code. Reported-by: Thomas Graf Cc: Thomas Graf Cc: Daniel Borkmann Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/core/netpoll.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 688517c7ff17..03c8ec3edc72 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -676,8 +676,6 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo spin_lock_irqsave(&npinfo->rx_lock, flags); list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { - unsigned long tail_offset; - if (!ipv6_addr_equal(daddr, &np->local_ip.in6)) continue; @@ -691,30 +689,20 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo send_skb->dev = skb->dev; skb_reset_network_header(send_skb); - skb_put(send_skb, sizeof(struct ipv6hdr)); - hdr = ipv6_hdr(send_skb); - + hdr = (struct ipv6hdr *) skb_put(send_skb, sizeof(struct ipv6hdr)); *(__be32*)hdr = htonl(0x60000000); - hdr->payload_len = htons(size); hdr->nexthdr = IPPROTO_ICMPV6; hdr->hop_limit = 255; hdr->saddr = *saddr; hdr->daddr = *daddr; - tail_offset = skb_tail_offset(skb); - if (tail_offset > 0xffff) { - kfree_skb(send_skb); - continue; - } - skb_set_network_header(send_skb, tail_offset); - skb_put(send_skb, size); - - icmp6h = (struct icmp6hdr *)skb_transport_header(skb); + icmp6h = (struct icmp6hdr *) skb_put(send_skb, sizeof(struct icmp6hdr)); icmp6h->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; icmp6h->icmp6_router = 0; icmp6h->icmp6_solicited = 1; - target = (struct in6_addr *)(skb_transport_header(send_skb) + sizeof(struct icmp6hdr)); + + target = (struct in6_addr *) skb_put(send_skb, sizeof(struct in6_addr)); *target = msg->target; icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, size, IPPROTO_ICMPV6, -- GitLab From 15dd16c233b6d5ceea3a00f18d7c42902d0ac6b6 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Mon, 3 Jun 2013 22:11:16 +0000 Subject: [PATCH 0669/2900] cxgb3: Correct comparisons and calculations using skb->tail and skb-transport_header This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer whereas skb->transport_header will be an offset from head. This is corrected by using wrappers that ensure that comparisons and calculations are always made using pointers. Cc: Simon Horman Signed-off-by: Li RongQing Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/sge.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/sge.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 46d1efc17527..687ec4a8bb48 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -1583,7 +1583,7 @@ static void deferred_unmap_destructor(struct sk_buff *skb) dui = (struct deferred_unmap_info *)skb->head; p = dui->addr; - if (skb->tail - skb->transport_header) + if (skb_tail_pointer(skb) - skb_transport_header(skb)) pci_unmap_single(dui->pdev, *p++, skb_tail_pointer(skb) - skb_transport_header(skb), PCI_DMA_TODEVICE); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 2bfbb206b35a..ac311f5f3eb9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -1294,7 +1294,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb) flits = skb_transport_offset(skb) / 8U; /* headers */ cnt = skb_shinfo(skb)->nr_frags; - if (skb->tail != skb->transport_header) + if (skb_tail_pointer(skb) != skb_transport_header(skb)) cnt++; return flits + sgl_len(cnt); } -- GitLab From 7a3e2585f2fd543ac7284a1f09641628f730f720 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 4 Jun 2013 00:03:27 +0000 Subject: [PATCH 0670/2900] net: emaclite: Use platform resource table Read data directly from platform recource table and do not use of_irq_to_resource(). Also use devm_request_and_ioremap() for probe functions simplification. Signed-off-by: Michal Simek Acked-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 67 ++++++------------- 1 file changed, 22 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index aaadf7e551df..c4d8aeffb4ba 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1074,13 +1074,14 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev) * This function un maps the IO region of the Emaclite device and frees the net * device. */ -static void xemaclite_remove_ndev(struct net_device *ndev) +static void xemaclite_remove_ndev(struct net_device *ndev, + struct platform_device *pdev) { if (ndev) { struct net_local *lp = netdev_priv(ndev); if (lp->base_addr) - iounmap((void __iomem __force *) (lp->base_addr)); + devm_iounmap(&pdev->dev, lp->base_addr); free_netdev(ndev); } } @@ -1126,8 +1127,7 @@ static struct net_device_ops xemaclite_netdev_ops; */ static int xemaclite_of_probe(struct platform_device *ofdev) { - struct resource r_irq; /* Interrupt resources */ - struct resource r_mem; /* IO mem resources */ + struct resource *res; struct net_device *ndev = NULL; struct net_local *lp = NULL; struct device *dev = &ofdev->dev; @@ -1137,20 +1137,6 @@ static int xemaclite_of_probe(struct platform_device *ofdev) dev_info(dev, "Device Tree Probing\n"); - /* Get iospace for the device */ - rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem); - if (rc) { - dev_err(dev, "invalid address\n"); - return rc; - } - - /* Get IRQ for the device */ - rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq); - if (!rc) { - dev_err(dev, "no IRQ found\n"); - return rc; - } - /* Create an ethernet device instance */ ndev = alloc_etherdev(sizeof(struct net_local)); if (!ndev) @@ -1159,29 +1145,25 @@ static int xemaclite_of_probe(struct platform_device *ofdev) dev_set_drvdata(dev, ndev); SET_NETDEV_DEV(ndev, &ofdev->dev); - ndev->irq = r_irq.start; - ndev->mem_start = r_mem.start; - ndev->mem_end = r_mem.end; - lp = netdev_priv(ndev); lp->ndev = ndev; - if (!request_mem_region(ndev->mem_start, - ndev->mem_end - ndev->mem_start + 1, - DRIVER_NAME)) { - dev_err(dev, "Couldn't lock memory region at %p\n", - (void *)ndev->mem_start); - rc = -EBUSY; - goto error2; + /* Get IRQ for the device */ + res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "no IRQ found\n"); + goto error; } - /* Get the virtual base address for the device */ - lp->base_addr = ioremap(r_mem.start, resource_size(&r_mem)); - if (NULL == lp->base_addr) { - dev_err(dev, "EmacLite: Could not allocate iomem\n"); - rc = -EIO; - goto error1; - } + ndev->irq = res->start; + + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + lp->base_addr = devm_request_and_ioremap(&ofdev->dev, res); + if (!lp->base_addr) + goto error; + + ndev->mem_start = res->start; + ndev->mem_end = res->end; spin_lock_init(&lp->reset_lock); lp->next_tx_buf_to_use = 0x0; @@ -1219,7 +1201,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev) if (rc) { dev_err(dev, "Cannot register network device, aborting\n"); - goto error1; + goto error; } dev_info(dev, @@ -1228,11 +1210,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) (unsigned int __force)lp->base_addr, ndev->irq); return 0; -error1: - release_mem_region(ndev->mem_start, resource_size(&r_mem)); - -error2: - xemaclite_remove_ndev(ndev); +error: + xemaclite_remove_ndev(ndev, ofdev); return rc; } @@ -1267,9 +1246,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev) of_node_put(lp->phy_node); lp->phy_node = NULL; - release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1); - - xemaclite_remove_ndev(ndev); + xemaclite_remove_ndev(ndev, of_dev); dev_set_drvdata(dev, NULL); return 0; -- GitLab From aff5c3557cf72fcad913d8b4b44b055a4e034bb5 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Jun 2013 00:31:19 +0000 Subject: [PATCH 0671/2900] net: sun4i-emac: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Stefan Roese Cc: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/sun4i-emac.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 0bb2f4af9952..e9c8dbe4c88f 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -898,8 +898,6 @@ static int emac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - unregister_netdev(ndev); free_netdev(ndev); -- GitLab From 11a164a04382d735230b01f4cc46ad78a7c4abf6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 4 Jun 2013 00:31:20 +0000 Subject: [PATCH 0672/2900] net: sun4i-emac: Staticize local symbols Some symbols referenced only in this file are made static. Signed-off-by: Sachin Kamat Cc: Stefan Roese Cc: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/sun4i-emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index e9c8dbe4c88f..50b853a79d77 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -258,7 +258,7 @@ static const struct ethtool_ops emac_ethtool_ops = { .get_link = ethtool_op_get_link, }; -unsigned int emac_setup(struct net_device *ndev) +static unsigned int emac_setup(struct net_device *ndev) { struct emac_board_info *db = netdev_priv(ndev); unsigned int reg_val; @@ -310,7 +310,7 @@ unsigned int emac_setup(struct net_device *ndev) return 0; } -unsigned int emac_powerup(struct net_device *ndev) +static unsigned int emac_powerup(struct net_device *ndev) { struct emac_board_info *db = netdev_priv(ndev); unsigned int reg_val; -- GitLab From 482a9c74fa17c5d584995c19e1a36eaf710d1193 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Mon, 3 Jun 2013 17:29:33 +0300 Subject: [PATCH 0673/2900] mac80211: fix powersave bug and clean up ieee80211_rx_bss_info ieee80211_rx_bss_info() deals with dtim_period setting and PS update when associated. Move all these to another locations cleaning this function. Also, the current implementation is buggy because when it calls ieee80211_recalc_ps() bss_conf->dtim_period is notset properly yet and thus nothing will happen. Signed-off-by: Alexander Bondar Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index df8170a80a56..aa5cd2e138be 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2737,24 +2737,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, int freq; struct ieee80211_bss *bss; struct ieee80211_channel *channel; - bool need_ps = false; sdata_assert_lock(sdata); - if ((sdata->u.mgd.associated && - ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || - (sdata->u.mgd.assoc_data && - ether_addr_equal(mgmt->bssid, - sdata->u.mgd.assoc_data->bss->bssid))) { - /* not previously set so we may need to recalc */ - need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period; - - if (elems->tim && !elems->parse_error) { - const struct ieee80211_tim_ie *tim_ie = elems->tim; - sdata->u.mgd.dtim_period = tim_ie->dtim_period; - } - } - if (elems->ds_params) freq = ieee80211_channel_to_frequency(elems->ds_params[0], rx_status->band); @@ -2775,12 +2760,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) return; - if (need_ps) { - mutex_lock(&local->iflist_mtx); - ieee80211_recalc_ps(local, -1); - mutex_unlock(&local->iflist_mtx); - } - ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems, true); @@ -2894,6 +2873,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, len - baselen, false, &elems); ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + if (elems.tim && !elems.parse_error) { + const struct ieee80211_tim_ie *tim_ie = elems.tim; + ifmgd->dtim_period = tim_ie->dtim_period; + } ifmgd->assoc_data->have_beacon = true; ifmgd->assoc_data->need_beacon = false; if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { @@ -3096,6 +3079,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, } changed |= BSS_CHANGED_DTIM_PERIOD; + + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); + ieee80211_recalc_ps_vif(sdata); } -- GitLab From 5ec42ecf497f9c5e55fbe57e894efc5ce91c47cd Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Mon, 27 May 2013 13:49:03 +0300 Subject: [PATCH 0674/2900] iwlwifi: mvm: enable PM always in unassociated mode In unassociated BSS STA mode FW verifies both power save and power management flags to decide on switching power off. The driver currently sets power management flag according to mac80211 decision. As result, in unassociated mode power management flag is down and power consumption is high. Change power management enablement. When unassociated in BPS and LP power save modes enable power management regardless of mac80211 decision. Rely on mac80211 decision if associated. Add power management state update during associated/disassociated modes transitions. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 +++ drivers/net/wireless/iwlwifi/mvm/power.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c13559b4b4fd..f2976901b1d5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -763,6 +763,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, if (ret) IWL_ERR(mvm, "failed to update quotas\n"); } + ret = iwl_mvm_power_update_mode(mvm, vif); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); } else if (changes & BSS_CHANGED_DTIM_PERIOD) { /* * We received a beacon _after_ association so diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 6cb98ce96ac4..3760a33ca3a4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -168,6 +168,8 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return; cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); + if (!vif->bss_conf.assoc) + cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); #ifdef CONFIG_IWLWIFI_DEBUGFS if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && -- GitLab From 9116a3683902583a302ac5dcb283416d504d9bb4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 2 Jun 2013 19:54:01 +0300 Subject: [PATCH 0675/2900] iwlwifi: mvm: fix MCAST in AP mode In multicast, there is no retries nor RTS since there is no specific recipient that can ACK or send CTS. This means that we must not use the rate scale table for multicast frames. This true for any frame that doesn't have a valid ieee80211_sta pointer. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index f212f16502ff..a830eb6cc411 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -175,7 +175,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, * table is controlled by LINK_QUALITY commands */ - if (ieee80211_is_data(fc)) { + if (ieee80211_is_data(fc) && sta) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE); return; -- GitLab From fded313ec045024d4f769ce6b3e41fe343c167b0 Mon Sep 17 00:00:00 2001 From: Eytan Lifshitz Date: Tue, 4 Jun 2013 12:28:51 +0300 Subject: [PATCH 0676/2900] iwlwifi: mvm: don't request SMPS on non-STA iface The Thermal Throttling code could do that, fix it. Signed-off-by: Eytan Lifshitz Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/tt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 4665fc033c17..a7e3b8ddf22b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -371,6 +371,9 @@ static void iwl_mvm_tt_smps_iterator(void *_data, u8 *mac, else smps_mode = IEEE80211_SMPS_AUTOMATIC; + if (vif->type != NL80211_IFTYPE_STATION) + return; + iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT, smps_mode); } -- GitLab From 989c6505cdda587f87573bb6828f23964dd3d19b Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Thu, 16 May 2013 17:34:17 +0300 Subject: [PATCH 0677/2900] mac80211: Use suitable semantics for beacon availability indication Currently beacon availability upon association is marked by have_beacon flag of assoc_data structure that becomes unavailable when association completes. However beacon availability indication is required also after association to inform a driver. Currently dtim_period parameter is used for this purpose. Move have_beacon flag to another structure, persistant throughout a interface's life cycle. Use suitable sematics for beacon availability indication. Signed-off-by: Alexander Bondar [fix another instance of BSS_CHANGED_DTIM_PERIOD in docs] Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- include/net/mac80211.h | 8 ++++---- net/mac80211/ieee80211_i.h | 3 ++- net/mac80211/mlme.c | 20 +++++++++++--------- net/mac80211/util.c | 5 +++-- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b807ddac650c..c942eb0bbbeb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -785,7 +785,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, if (ret) IWL_ERR(mvm, "failed to update quotas\n"); } - } else if (changes & BSS_CHANGED_DTIM_PERIOD) { + } else if (changes & BSS_CHANGED_BEACON_INFO) { /* * We received a beacon _after_ association so * remove the session protection. diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cb37f82d8d09..a405a7a9775c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -217,8 +217,8 @@ struct ieee80211_chanctx_conf { * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) * changed (currently only in P2P client mode, GO mode will be later) - * @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when - * it becomes valid, managed mode only) + * @BSS_CHANGED_BEACON_INFO: Data from the AP's beacon became available: + * currently dtim_period only is under consideration. * @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed, * note that this is only called when it changes after the channel * context had been assigned. @@ -244,7 +244,7 @@ enum ieee80211_bss_change { BSS_CHANGED_PS = 1<<17, BSS_CHANGED_TXPOWER = 1<<18, BSS_CHANGED_P2P_PS = 1<<19, - BSS_CHANGED_DTIM_PERIOD = 1<<20, + BSS_CHANGED_BEACON_INFO = 1<<20, BSS_CHANGED_BANDWIDTH = 1<<21, /* when adding here, make sure to change ieee80211_reconfig */ @@ -288,7 +288,7 @@ enum ieee80211_rssi_event { * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag * @dtim_period: num of beacons before the next DTIM, for beaconing, * valid in station mode only if after the driver was notified - * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. + * with the %BSS_CHANGED_BEACON_INFO flag, will be non-zero then. * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old * as it may have been received during scanning long ago). If the * HW flag %IEEE80211_HW_TIMING_BEACON_ONLY is set, then this can diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9eed6f1d1614..7a6f1a0207ec 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -366,7 +366,7 @@ struct ieee80211_mgd_assoc_data { u8 ssid_len; u8 supp_rates_len; bool wmm, uapsd; - bool have_beacon, need_beacon; + bool need_beacon; bool synced; bool timeout_started; @@ -404,6 +404,7 @@ struct ieee80211_if_managed { bool powersave; /* powersave requested for this iface */ bool broken_ap; /* AP is broken -- turn off powersave */ + bool have_beacon; u8 dtim_period; enum ieee80211_smps_mode req_smps, /* requested smps mode */ driver_smps_mode; /* smps mode request */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index aa5cd2e138be..ad9bb9e10cbb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1360,7 +1360,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) IEEE80211_STA_CONNECTION_POLL)) return false; - if (!sdata->vif.bss_conf.dtim_period) + if (!mgd->have_beacon) return false; rcu_read_lock(); @@ -1771,7 +1771,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); - if (sdata->u.mgd.assoc_data->have_beacon) { + if (sdata->u.mgd.have_beacon) { /* * If the AP is buggy we may get here with no DTIM period * known, so assume it's 1 which is the only safe assumption @@ -1779,7 +1779,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, * probably just won't work at all. */ bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; - bss_info_changed |= BSS_CHANGED_DTIM_PERIOD; + bss_info_changed |= BSS_CHANGED_BEACON_INFO; } else { bss_conf->dtim_period = 0; } @@ -1903,6 +1903,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.chswitch_timer); sdata->vif.bss_conf.dtim_period = 0; + ifmgd->have_beacon = false; ifmgd->flags = 0; ieee80211_vif_release_channel(sdata); @@ -2877,7 +2878,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, const struct ieee80211_tim_ie *tim_ie = elems.tim; ifmgd->dtim_period = tim_ie->dtim_period; } - ifmgd->assoc_data->have_beacon = true; + ifmgd->have_beacon = true; ifmgd->assoc_data->need_beacon = false; if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { sdata->vif.bss_conf.sync_tsf = @@ -3059,7 +3060,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, * If we haven't had a beacon before, tell the driver about the * DTIM period (and beacon timing if desired) now. */ - if (!bss_conf->dtim_period) { + if (!ifmgd->have_beacon) { /* a few bogus AP send dtim_period = 0 or no TIM IE */ if (elems.tim) bss_conf->dtim_period = elems.tim->dtim_period ?: 1; @@ -3078,7 +3079,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.sync_dtim_count = 0; } - changed |= BSS_CHANGED_DTIM_PERIOD; + changed |= BSS_CHANGED_BEACON_INFO; + ifmgd->have_beacon = true; mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); @@ -3424,8 +3426,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started && time_after(jiffies, ifmgd->assoc_data->timeout)) { - if ((ifmgd->assoc_data->need_beacon && - !ifmgd->assoc_data->have_beacon) || + if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || ieee80211_do_assoc(sdata)) { u8 bssid[ETH_ALEN]; @@ -4193,6 +4194,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->assoc_data = assoc_data; ifmgd->dtim_period = 0; + ifmgd->have_beacon = false; err = ieee80211_prep_connection(sdata, req->bss, true); if (err) @@ -4224,7 +4226,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->dtim_period = tim->dtim_period; dtim_count = tim->dtim_count; } - assoc_data->have_beacon = true; + ifmgd->have_beacon = true; assoc_data->timeout = jiffies; assoc_data->timeout_started = true; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 89a83770d152..5a6c1351d1d3 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1584,8 +1584,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) BSS_CHANGED_ARP_FILTER | BSS_CHANGED_PS; - if (sdata->u.mgd.dtim_period) - changed |= BSS_CHANGED_DTIM_PERIOD; + /* Re-send beacon info report to the driver */ + if (sdata->u.mgd.have_beacon) + changed |= BSS_CHANGED_BEACON_INFO; sdata_lock(sdata); ieee80211_bss_info_change_notify(sdata, changed); -- GitLab From 780b40df12cf0161d8ccc5381940e04584793933 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 Jun 2013 09:32:50 +0200 Subject: [PATCH 0678/2900] wireless: fix kernel-doc Some kernel-doc fixes for forgotten fields and renamed things. Signed-off-by: Johannes Berg --- Documentation/DocBook/80211.tmpl | 11 +++++------ include/net/cfg80211.h | 11 ++++++++++- net/mac80211/sta_info.h | 3 +++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index ebe89694cf81..49267ea97568 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -127,12 +127,11 @@ !Finclude/net/cfg80211.h cfg80211_ibss_params !Finclude/net/cfg80211.h cfg80211_connect_params !Finclude/net/cfg80211.h cfg80211_pmksa -!Finclude/net/cfg80211.h cfg80211_send_rx_auth -!Finclude/net/cfg80211.h cfg80211_send_auth_timeout -!Finclude/net/cfg80211.h cfg80211_send_rx_assoc -!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout -!Finclude/net/cfg80211.h cfg80211_send_deauth -!Finclude/net/cfg80211.h cfg80211_send_disassoc +!Finclude/net/cfg80211.h cfg80211_rx_mlme_mgmt +!Finclude/net/cfg80211.h cfg80211_auth_timeout +!Finclude/net/cfg80211.h cfg80211_rx_assoc_resp +!Finclude/net/cfg80211.h cfg80211_assoc_timeout +!Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_roamed diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5b208064f1bd..855c76ccff38 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2853,7 +2853,7 @@ struct cfg80211_cached_keys; * @current_bss: (private) Used by the internal configuration code * @channel: (private) Used by the internal configuration code to track * the user-set AP, monitor and WDS channel - * @preset_chan: (private) Used by the internal configuration code to + * @preset_chandef: (private) Used by the internal configuration code to * track the channel to be used for AP later * @bssid: (private) Used by the internal configuration code * @ssid: (private) Used by the internal configuration code @@ -2875,6 +2875,15 @@ struct cfg80211_cached_keys; * @p2p_started: true if this is a P2P Device that has been started * @cac_started: true if DFS channel availability check has been started * @cac_start_time: timestamp (jiffies) when the dfs state was entered. + * @ps: powersave mode is enabled + * @ps_timeout: dynamic powersave timeout + * @ap_unexpected_nlportid: (private) netlink port ID of application + * registered for unexpected class 3 frames (AP mode) + * @conn: (private) cfg80211 software SME connection state machine data + * @connect_keys: (private) keys to set after connection is established + * @ibss_fixed: (private) IBSS is using fixed BSSID + * @event_list: (private) list for internal event processing + * @event_lock: (private) lock for event list */ struct wireless_dev { struct wiphy *wiphy; diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 41c28b977f7c..bd12fc54266c 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -297,6 +297,9 @@ struct sta_ampdu_mlme { * @rcu_head: RCU head used for freeing this station struct * @cur_max_bandwidth: maximum bandwidth to use for TX to the station, * taken from HT/VHT capabilities or VHT operating mode notification + * @chains: chains ever used for RX from this station + * @chain_signal_last: last signal (per chain) + * @chain_signal_avg: signal average (per chain) */ struct sta_info { /* General information, mostly static */ -- GitLab From 9cefbbc9c8f9abe0bc514dcfca46e8051ee84050 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 4 Jun 2013 22:22:15 +0000 Subject: [PATCH 0679/2900] netfilter: nfnetlink_queue: cleanup copy_range usage For every packet queued, we check if configured copy_range is 0, and treat that as 'copy entire packet'. We can move this check to the queue configuration, and can set copy_range appropriately. Also, convert repetitive '0xffff - NLA_HDRLEN' to a macro. [ queue initialization still used 0xffff, although its harmless since the initial setting is overwritten on queue config ] Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_queue_core.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index cff4449f01d2..3c4218141d70 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -41,6 +41,14 @@ #define NFQNL_QMAX_DEFAULT 1024 +/* We're using struct nlattr which has 16bit nla_len. Note that nla_len + * includes the header length. Thus, the maximum packet length that we + * support is 65531 bytes. We send truncated packets if the specified length + * is larger than that. Userspace can check for presence of NFQA_CAP_LEN + * attribute to detect truncation. + */ +#define NFQNL_MAX_COPY_RANGE (0xffff - NLA_HDRLEN) + struct nfqnl_instance { struct hlist_node hlist; /* global list of queues */ struct rcu_head rcu; @@ -122,7 +130,7 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, inst->queue_num = queue_num; inst->peer_portid = portid; inst->queue_maxlen = NFQNL_QMAX_DEFAULT; - inst->copy_range = 0xffff; + inst->copy_range = NFQNL_MAX_COPY_RANGE; inst->copy_mode = NFQNL_COPY_NONE; spin_lock_init(&inst->lock); INIT_LIST_HEAD(&inst->queue_list); @@ -333,10 +341,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, return NULL; data_len = ACCESS_ONCE(queue->copy_range); - if (data_len == 0 || data_len > entskb->len) + if (data_len > entskb->len) data_len = entskb->len; - if (!entskb->head_frag || skb_headlen(entskb) < L1_CACHE_BYTES || skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS) @@ -727,13 +734,8 @@ nfqnl_set_mode(struct nfqnl_instance *queue, case NFQNL_COPY_PACKET: queue->copy_mode = mode; - /* We're using struct nlattr which has 16bit nla_len. Note that - * nla_len includes the header length. Thus, the maximum packet - * length that we support is 65531 bytes. We send truncated - * packets if the specified length is larger than that. - */ - if (range > 0xffff - NLA_HDRLEN) - queue->copy_range = 0xffff - NLA_HDRLEN; + if (range == 0 || range > NFQNL_MAX_COPY_RANGE) + queue->copy_range = NFQNL_MAX_COPY_RANGE; else queue->copy_range = range; break; -- GitLab From 7f87712c0152511a1842698ad8dca425fee2dc4f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 4 Jun 2013 22:22:16 +0000 Subject: [PATCH 0680/2900] netfilter: nfnetlink_queue: only add CAP_LEN attr when needed CAP_LEN contains the size of the network packet we're queueing to userspace, i.e. normally it is the same as the NFQA_PAYLOAD attribute len. Include it only in the unlikely case when NFQA_PAYLOAD is truncated due to copy_range limitations. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink_queue_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 3c4218141d70..eb2cde836b9a 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -472,7 +472,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) goto nla_put_failure; - if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) + if (cap_len > data_len && + nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) goto nla_put_failure; if (nfqnl_put_packet_info(skb, entskb)) -- GitLab From 87962c4db7f594c377d8b0b5a5f563e5f0b5d5d0 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 15 May 2013 19:02:06 +0400 Subject: [PATCH 0681/2900] xtensa: flush TLB entries for pages of non-current mm correctly Sometimes under high memory pressure one process gets a page of another process, which manifests itself with an invalid instruction exception. This happens because flush_tlb_page fails to clear TLB entries when called with vma that does not belong to current mm, because it does not set RASID appropriately. When page reclaiming mechanism swaps physical pages out replacing their PTEs with none or swap PTEs, it calls flush_tlb_page. Later physical page may be reused elsewhere, but the stale TLB mapping still refers to it, allowing process that owned the mapping to see the new state of that physical page. Put ASID of the mm that owns vma to the RASID to fix that issue. Also replace otherwise meaningless local_save_flags with local_irq_save. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/mm/tlb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index 5411aa67c68e..743346150eea 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c @@ -64,7 +64,7 @@ void flush_tlb_mm(struct mm_struct *mm) { if (mm == current->active_mm) { unsigned long flags; - local_save_flags(flags); + local_irq_save(flags); __get_new_mmu_context(mm); __load_mmu_context(mm); local_irq_restore(flags); @@ -94,7 +94,7 @@ void flush_tlb_range (struct vm_area_struct *vma, printk("[tlbrange<%02lx,%08lx,%08lx>]\n", (unsigned long)mm->context, start, end); #endif - local_save_flags(flags); + local_irq_save(flags); if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) { int oldpid = get_rasid_register(); @@ -128,9 +128,10 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) if(mm->context == NO_CONTEXT) return; - local_save_flags(flags); + local_irq_save(flags); oldpid = get_rasid_register(); + set_rasid_register(ASID_INSERT(mm->context)); if (vma->vm_flags & VM_EXEC) invalidate_itlb_mapping(page); -- GitLab From 28622c5353cb30d6ad8f6ef008e46103f1083f5c Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 23 May 2013 10:58:18 +0300 Subject: [PATCH 0682/2900] xtensa: tell git to ignore generated files Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/boot/.gitignore | 2 ++ arch/xtensa/boot/boot-elf/.gitignore | 1 + arch/xtensa/kernel/.gitignore | 1 + 3 files changed, 4 insertions(+) create mode 100644 arch/xtensa/boot/.gitignore create mode 100644 arch/xtensa/boot/boot-elf/.gitignore create mode 100644 arch/xtensa/kernel/.gitignore diff --git a/arch/xtensa/boot/.gitignore b/arch/xtensa/boot/.gitignore new file mode 100644 index 000000000000..38177c7ebcab --- /dev/null +++ b/arch/xtensa/boot/.gitignore @@ -0,0 +1,2 @@ +uImage +zImage.redboot diff --git a/arch/xtensa/boot/boot-elf/.gitignore b/arch/xtensa/boot/boot-elf/.gitignore new file mode 100644 index 000000000000..5ff8fbb8561b --- /dev/null +++ b/arch/xtensa/boot/boot-elf/.gitignore @@ -0,0 +1 @@ +boot.lds diff --git a/arch/xtensa/kernel/.gitignore b/arch/xtensa/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/xtensa/kernel/.gitignore @@ -0,0 +1 @@ +vmlinux.lds -- GitLab From 214fe80fcba6df6be28d6ea66762d203d84842c4 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 27 May 2013 12:23:52 +0300 Subject: [PATCH 0683/2900] xtensa: remove unused platform_init_irq() Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/platform.h | 5 ----- arch/xtensa/kernel/platform.c | 1 - 2 files changed, 6 deletions(-) diff --git a/arch/xtensa/include/asm/platform.h b/arch/xtensa/include/asm/platform.h index ec098b68fb9a..32e98f27ce97 100644 --- a/arch/xtensa/include/asm/platform.h +++ b/arch/xtensa/include/asm/platform.h @@ -29,11 +29,6 @@ extern void platform_init(bp_tag_t*); */ extern void platform_setup (char **); -/* - * platform_init_irq is called from init_IRQ. - */ -extern void platform_init_irq (void); - /* * platform_restart is called to restart the system. */ diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 2bd6c351f37c..da827cbb2f59 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -29,7 +29,6 @@ */ _F(void, setup, (char** cmd), { }); -_F(void, init_irq, (void), { }); _F(void, restart, (void), { while(1); }); _F(void, halt, (void), { while(1); }); _F(void, power_off, (void), { while(1); }); -- GitLab From 54c0af9f1a1bfe9639666aea789dae6a37a741cf Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 27 May 2013 09:11:59 +0300 Subject: [PATCH 0684/2900] xtensa: xtfpga: fix section mismatch platform_calibrate_ccount() calls update_clock_frequency() which is in .init section. However, platform_calibrate_ccount() itself is only called from .init (i.e., time_init()). Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/xtfpga/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 96ef8eeb064e..c7ce62ff73f7 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -163,7 +163,7 @@ void platform_heartbeat(void) #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT -void platform_calibrate_ccount(void) +void __init platform_calibrate_ccount(void) { long clk_freq = 0; #ifdef CONFIG_OF -- GitLab From b5514786ec3257c8703fc7f29bdf98b42253ee39 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 27 May 2013 19:57:01 +0800 Subject: [PATCH 0685/2900] arch: xtensa: include: asm: compiling issue, need cmpxchg64() defined. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiling with 'allmodconfig', some of drivers need cmpxchg64(), xtensa does not supply 64-bit implementation for 'xchg', so use the 'generic' implementation. e.g. (for next-20130527 tree): drivers/block/blockconsole.c:164:2: error: implicit declaration of function ‘cmpxchg64’ [-Werror=implicit-function-declaration] Signed-off-by: Chen Gang Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/cmpxchg.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index d9ab131bc1aa..370b26f38414 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h @@ -93,6 +93,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ (unsigned long)(n), sizeof(*(ptr)))) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) +#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) /* * xchg_u32 -- GitLab From dc2bffa77a2866a451126cf3146abb9787edce78 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 27 May 2013 18:58:24 +0400 Subject: [PATCH 0686/2900] xtensa: ISS: fix section mismatch in iss_net_setup iss_net_setup is only called from __setup, so it should be marked __init. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 7d0fea6d7f20..56f88b7afe2f 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -700,7 +700,7 @@ struct iss_net_init { #define ERR KERN_ERR "iss_net_setup: " -static int iss_net_setup(char *str) +static int __init iss_net_setup(char *str) { struct iss_net_private *device = NULL; struct iss_net_init *new; -- GitLab From fd95ee7380ae973c6f11b897af6ef9d253a1df9e Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 27 May 2013 19:45:58 +0400 Subject: [PATCH 0687/2900] xtensa: fix section mismatch in pcibios_fixup_bus Remove __init annotation from pcibios_fixup_bus as is called from pci_scan_child_bus which is not __init. Also fix a couple of minor build warnings. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/pci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 126c18839409..5b3403388d7f 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -77,9 +77,9 @@ pcibios_align_resource(void *data, const struct resource *res, if (res->flags & IORESOURCE_IO) { if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", pci_name(dev), - dev->resource - res, size); + pr_err("PCI: I/O Region %s/%d too large (%u bytes)\n", + pci_name(dev), dev->resource - res, + size); } if (start & 0x300) @@ -174,7 +174,7 @@ static int __init pcibios_init(void) struct pci_controller *pci_ctrl; struct list_head resources; struct pci_bus *bus; - int next_busno = 0, i; + int next_busno = 0; printk("PCI: Probing PCI hardware\n"); @@ -197,7 +197,7 @@ static int __init pcibios_init(void) subsys_initcall(pcibios_init); -void __init pcibios_fixup_bus(struct pci_bus *bus) +void pcibios_fixup_bus(struct pci_bus *bus) { if (bus->parent) { /* This is a subordinate bridge */ -- GitLab From 21d1101f013c12d1dd78cfdf263d619c80975b47 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 5 Jun 2013 14:32:08 -0500 Subject: [PATCH 0688/2900] jfs: fix sparse warning in fs/jfs/xattr.c CHECK fs/jfs/xattr.c fs/jfs/xattr.c:1092:5: warning: symbol 'jfs_initxattrs' was not declared. Should it be static? Signed-off-by: Dave Kleikamp --- fs/jfs/xattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 42d67f9757bf..86ce028f2566 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -1089,8 +1089,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name) } #ifdef CONFIG_JFS_SECURITY -int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, - void *fs_info) +static int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, + void *fs_info) { const struct xattr *xattr; tid_t *tid = fs_info; -- GitLab From eb8630d7d2fd13589e6a7a3ae2fe1f75f867fbed Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 4 Jun 2013 16:39:15 -0700 Subject: [PATCH 0689/2900] jfs: Update jfs_error Use a more current logging style. Add __printf format and argument verification. Remove embedded function names from formats. Add %pf, __builtin_return_address(0) to jfs_error. Add newlines to formats for kernel style consistency. (One format already had an erroneous newline) Coalesce formats and align arguments. Object size reduced ~1KiB. $ size fs/jfs/built-in.o* text data bss dec hex filename 201891 35488 63936 301315 49903 fs/jfs/built-in.o.new 202821 35488 64192 302501 49da5 fs/jfs/built-in.o.old Signed-off-by: Joe Perches Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dmap.c | 70 ++++++++++++++++------------------------- fs/jfs/jfs_dtree.c | 37 +++++++++++----------- fs/jfs/jfs_extent.c | 2 +- fs/jfs/jfs_imap.c | 69 +++++++++++++++++----------------------- fs/jfs/jfs_metapage.c | 5 ++- fs/jfs/jfs_superblock.h | 1 + fs/jfs/jfs_txnmgr.c | 2 +- fs/jfs/jfs_xtree.c | 62 ++++++++++++++++++------------------ fs/jfs/namei.c | 2 +- fs/jfs/resize.c | 2 +- fs/jfs/super.c | 22 +++++++------ fs/jfs/xattr.c | 4 +-- 12 files changed, 126 insertions(+), 152 deletions(-) diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 9a55f53be5ff..370d7b6c5942 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -346,8 +346,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n", (unsigned long long) blkno, (unsigned long long) nblocks); - jfs_error(ip->i_sb, - "dbFree: block to be freed is outside the map"); + jfs_error(ip->i_sb, "block to be freed is outside the map\n"); return -EIO; } @@ -384,7 +383,7 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) /* free the blocks. */ if ((rc = dbFreeDmap(bmp, dp, blkno, nb))) { - jfs_error(ip->i_sb, "dbFree: error in block map\n"); + jfs_error(ip->i_sb, "error in block map\n"); release_metapage(mp); IREAD_UNLOCK(ipbmap); return (rc); @@ -441,8 +440,7 @@ dbUpdatePMap(struct inode *ipbmap, printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n", (unsigned long long) blkno, (unsigned long long) nblocks); - jfs_error(ipbmap->i_sb, - "dbUpdatePMap: blocks are outside the map"); + jfs_error(ipbmap->i_sb, "blocks are outside the map\n"); return -EIO; } @@ -726,7 +724,7 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) /* the hint should be within the map */ if (hint >= mapSize) { - jfs_error(ip->i_sb, "dbAlloc: the hint is outside the map"); + jfs_error(ip->i_sb, "the hint is outside the map\n"); return -EIO; } @@ -1057,8 +1055,7 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) bmp = sbi->bmap; if (lastblkno < 0 || lastblkno >= bmp->db_mapsize) { IREAD_UNLOCK(ipbmap); - jfs_error(ip->i_sb, - "dbExtend: the block is outside the filesystem"); + jfs_error(ip->i_sb, "the block is outside the filesystem\n"); return -EIO; } @@ -1134,8 +1131,7 @@ static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno, u32 mask; if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocNext: Corrupt dmap page"); + jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n"); return -EIO; } @@ -1265,8 +1261,7 @@ dbAllocNear(struct bmap * bmp, s8 *leaf; if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocNear: Corrupt dmap page"); + jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n"); return -EIO; } @@ -1381,8 +1376,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) */ if (l2nb > bmp->db_agl2size) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: allocation request is larger than the " - "allocation group size"); + "allocation request is larger than the allocation group size\n"); return -EIO; } @@ -1417,7 +1411,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) (unsigned long long) blkno, (unsigned long long) nblocks); jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: dbAllocCtl failed in free AG"); + "dbAllocCtl failed in free AG\n"); } return (rc); } @@ -1433,8 +1427,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) budmin = dcp->budmin; if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: Corrupt dmapctl page"); + jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n"); release_metapage(mp); return -EIO; } @@ -1475,7 +1468,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) } if (n == 4) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: failed descending stree"); + "failed descending stree\n"); release_metapage(mp); return -EIO; } @@ -1515,8 +1508,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) &blkno))) { if (rc == -ENOSPC) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: control page " - "inconsistent"); + "control page inconsistent\n"); return -EIO; } return (rc); @@ -1528,7 +1520,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results); if (rc == -ENOSPC) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAG: unable to allocate blocks"); + "unable to allocate blocks\n"); rc = -EIO; } return (rc); @@ -1587,8 +1579,7 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results) */ rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results); if (rc == -ENOSPC) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocAny: unable to allocate blocks"); + jfs_error(bmp->db_ipbmap->i_sb, "unable to allocate blocks\n"); return -EIO; } return (rc); @@ -1652,8 +1643,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) range_cnt = min_t(u64, max_ranges + 1, 32 * 1024); totrim = kmalloc(sizeof(struct range2trim) * range_cnt, GFP_NOFS); if (totrim == NULL) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbDiscardAG: no memory for trim array"); + jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n"); IWRITE_UNLOCK(ipbmap); return 0; } @@ -1682,8 +1672,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) nblocks = 1 << l2nb; } else { /* Trim any already allocated blocks */ - jfs_error(bmp->db_ipbmap->i_sb, - "dbDiscardAG: -EIO"); + jfs_error(bmp->db_ipbmap->i_sb, "-EIO\n"); break; } @@ -1761,7 +1750,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) { jfs_error(bmp->db_ipbmap->i_sb, - "dbFindCtl: Corrupt dmapctl page"); + "Corrupt dmapctl page\n"); release_metapage(mp); return -EIO; } @@ -1782,7 +1771,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno) if (rc) { if (lev != level) { jfs_error(bmp->db_ipbmap->i_sb, - "dbFindCtl: dmap inconsistent"); + "dmap inconsistent\n"); return -EIO; } return -ENOSPC; @@ -1906,7 +1895,7 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) if (dp->tree.stree[ROOT] != L2BPERDMAP) { release_metapage(mp); jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocCtl: the dmap is not all free"); + "the dmap is not all free\n"); rc = -EIO; goto backout; } @@ -1953,7 +1942,7 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) * to indicate that we have leaked blocks. */ jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocCtl: I/O Error: Block Leakage."); + "I/O Error: Block Leakage\n"); continue; } dp = (struct dmap *) mp->data; @@ -1965,8 +1954,7 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results) * to indicate that we have leaked blocks. */ release_metapage(mp); - jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocCtl: Block Leakage."); + jfs_error(bmp->db_ipbmap->i_sb, "Block Leakage\n"); continue; } @@ -2263,8 +2251,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, for (; nwords > 0; nwords -= nw) { if (leaf[word] < BUDMIN) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAllocBits: leaf page " - "corrupt"); + "leaf page corrupt\n"); break; } @@ -2536,8 +2523,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) dcp = (struct dmapctl *) mp->data; if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) { - jfs_error(bmp->db_ipbmap->i_sb, - "dbAdjCtl: Corrupt dmapctl page"); + jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n"); release_metapage(mp); return -EIO; } @@ -2638,8 +2624,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) assert(level == bmp->db_maxlevel); if (bmp->db_maxfreebud != oldroot) { jfs_error(bmp->db_ipbmap->i_sb, - "dbAdjCtl: the maximum free buddy is " - "not the old root"); + "the maximum free buddy is not the old root\n"); } bmp->db_maxfreebud = dcp->stree[ROOT]; } @@ -3481,7 +3466,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) p = BMAPBLKNO + nbperpage; /* L2 page */ l2mp = read_metapage(ipbmap, p, PSIZE, 0); if (!l2mp) { - jfs_error(ipbmap->i_sb, "dbExtendFS: L2 page could not be read"); + jfs_error(ipbmap->i_sb, "L2 page could not be read\n"); return -EIO; } l2dcp = (struct dmapctl *) l2mp->data; @@ -3646,8 +3631,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) } } /* for each L1 in a L2 */ - jfs_error(ipbmap->i_sb, - "dbExtendFS: function has not returned as expected"); + jfs_error(ipbmap->i_sb, "function has not returned as expected\n"); errout: if (l0mp) release_metapage(l0mp); @@ -3717,7 +3701,7 @@ void dbFinalizeBmap(struct inode *ipbmap) } if (bmp->db_agpref >= bmp->db_numag) { jfs_error(ipbmap->i_sb, - "cannot find ag with average freespace"); + "cannot find ag with average freespace\n"); } } diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 0ddbeceafc62..c89424e71a0a 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -124,21 +124,21 @@ struct dtsplit { #define DT_PAGE(IP, MP) BT_PAGE(IP, MP, dtpage_t, i_dtroot) /* get page buffer for specified block address */ -#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC)\ -{\ - BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot)\ - if (!(RC))\ - {\ - if (((P)->header.nextindex > (((BN)==0)?DTROOTMAXSLOT:(P)->header.maxslot)) ||\ - ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT)))\ - {\ - BT_PUTPAGE(MP);\ - jfs_error((IP)->i_sb, "DT_GETPAGE: dtree page corrupt");\ - MP = NULL;\ - RC = -EIO;\ - }\ - }\ -} +#define DT_GETPAGE(IP, BN, MP, SIZE, P, RC) \ +do { \ + BT_GETPAGE(IP, BN, MP, dtpage_t, SIZE, P, RC, i_dtroot); \ + if (!(RC)) { \ + if (((P)->header.nextindex > \ + (((BN) == 0) ? DTROOTMAXSLOT : (P)->header.maxslot)) || \ + ((BN) && ((P)->header.maxslot > DTPAGEMAXSLOT))) { \ + BT_PUTPAGE(MP); \ + jfs_error((IP)->i_sb, \ + "DT_GETPAGE: dtree page corrupt\n"); \ + MP = NULL; \ + RC = -EIO; \ + } \ + } \ +} while (0) /* for consistency */ #define DT_PUTPAGE(MP) BT_PUTPAGE(MP) @@ -776,7 +776,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data, /* Something's corrupted, mark filesystem dirty so * chkdsk will fix it. */ - jfs_error(sb, "stack overrun in dtSearch!"); + jfs_error(sb, "stack overrun!\n"); BT_STACK_DUMP(btstack); rc = -EIO; goto out; @@ -3252,8 +3252,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) /* Sanity Check */ if (d_namleft == 0) { jfs_error(ip->i_sb, - "JFS:Dtree error: ino = " - "%ld, bn=%Ld, index = %d", + "JFS:Dtree error: ino = %ld, bn=%lld, index = %d\n", (long)ip->i_ino, (long long)bn, i); @@ -3373,7 +3372,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack) */ if (BT_STACK_FULL(btstack)) { DT_PUTPAGE(mp); - jfs_error(ip->i_sb, "dtReadFirst: btstack overrun"); + jfs_error(ip->i_sb, "btstack overrun\n"); BT_STACK_DUMP(btstack); return -EIO; } diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c index e5fe8506ed16..2ae7d59ab10a 100644 --- a/fs/jfs/jfs_extent.c +++ b/fs/jfs/jfs_extent.c @@ -388,7 +388,7 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp) if ((rc == 0) && xlen) { if (xlen != nbperpage) { - jfs_error(ip->i_sb, "extHint: corrupt xtree"); + jfs_error(ip->i_sb, "corrupt xtree\n"); rc = -EIO; } XADaddress(xp, xaddr); diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index f7e042b63ddb..f321986e73d2 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -386,7 +386,7 @@ int diRead(struct inode *ip) dp += rel_inode; if (ip->i_ino != le32_to_cpu(dp->di_number)) { - jfs_error(ip->i_sb, "diRead: i_ino != di_number"); + jfs_error(ip->i_sb, "i_ino != di_number\n"); rc = -EIO; } else if (le32_to_cpu(dp->di_nlink) == 0) rc = -ESTALE; @@ -625,7 +625,7 @@ int diWrite(tid_t tid, struct inode *ip) if (!addressPXD(&(jfs_ip->ixpxd)) || (lengthPXD(&(jfs_ip->ixpxd)) != JFS_IP(ipimap)->i_imap->im_nbperiext)) { - jfs_error(ip->i_sb, "diWrite: ixpxd invalid"); + jfs_error(ip->i_sb, "ixpxd invalid\n"); return -EIO; } @@ -893,8 +893,7 @@ int diFree(struct inode *ip) if (iagno >= imap->im_nextiag) { print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4, imap, 32, 0); - jfs_error(ip->i_sb, - "diFree: inum = %d, iagno = %d, nextiag = %d", + jfs_error(ip->i_sb, "inum = %d, iagno = %d, nextiag = %d\n", (uint) inum, iagno, imap->im_nextiag); return -EIO; } @@ -930,15 +929,14 @@ int diFree(struct inode *ip) mask = HIGHORDER >> bitno; if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { - jfs_error(ip->i_sb, - "diFree: wmap shows inode already free"); + jfs_error(ip->i_sb, "wmap shows inode already free\n"); } if (!addressPXD(&iagp->inoext[extno])) { release_metapage(mp); IREAD_UNLOCK(ipimap); AG_UNLOCK(imap, agno); - jfs_error(ip->i_sb, "diFree: invalid inoext"); + jfs_error(ip->i_sb, "invalid inoext\n"); return -EIO; } @@ -950,7 +948,7 @@ int diFree(struct inode *ip) release_metapage(mp); IREAD_UNLOCK(ipimap); AG_UNLOCK(imap, agno); - jfs_error(ip->i_sb, "diFree: numfree > numinos"); + jfs_error(ip->i_sb, "numfree > numinos\n"); return -EIO; } /* @@ -1199,7 +1197,7 @@ int diFree(struct inode *ip) * for the inode being freed. */ if (iagp->pmap[extno] != 0) { - jfs_error(ip->i_sb, "diFree: the pmap does not show inode free"); + jfs_error(ip->i_sb, "the pmap does not show inode free\n"); } iagp->wmap[extno] = 0; PXDlength(&iagp->inoext[extno], 0); @@ -1518,8 +1516,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) release_metapage(mp); AG_UNLOCK(imap, agno); jfs_error(ip->i_sb, - "diAlloc: can't find free bit " - "in wmap"); + "can't find free bit in wmap\n"); return -EIO; } @@ -1660,7 +1657,7 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip) numinos = imap->im_agctl[agno].numinos; if (numfree > numinos) { - jfs_error(ip->i_sb, "diAllocAG: numfree > numinos"); + jfs_error(ip->i_sb, "numfree > numinos\n"); return -EIO; } @@ -1811,8 +1808,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) if (!iagp->nfreeinos) { IREAD_UNLOCK(imap->im_ipimap); release_metapage(mp); - jfs_error(ip->i_sb, - "diAllocIno: nfreeinos = 0, but iag on freelist"); + jfs_error(ip->i_sb, "nfreeinos = 0, but iag on freelist\n"); return -EIO; } @@ -1824,7 +1820,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) IREAD_UNLOCK(imap->im_ipimap); release_metapage(mp); jfs_error(ip->i_sb, - "diAllocIno: free inode not found in summary map"); + "free inode not found in summary map\n"); return -EIO; } @@ -1839,7 +1835,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) if (rem >= EXTSPERSUM) { IREAD_UNLOCK(imap->im_ipimap); release_metapage(mp); - jfs_error(ip->i_sb, "diAllocIno: no free extent found"); + jfs_error(ip->i_sb, "no free extent found\n"); return -EIO; } extno = (sword << L2EXTSPERSUM) + rem; @@ -1850,7 +1846,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) if (rem >= INOSPEREXT) { IREAD_UNLOCK(imap->im_ipimap); release_metapage(mp); - jfs_error(ip->i_sb, "diAllocIno: free inode not found"); + jfs_error(ip->i_sb, "free inode not found\n"); return -EIO; } @@ -1936,7 +1932,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP); if ((rc = diIAGRead(imap, iagno, &mp))) { IREAD_UNLOCK(imap->im_ipimap); - jfs_error(ip->i_sb, "diAllocExt: error reading iag"); + jfs_error(ip->i_sb, "error reading iag\n"); return rc; } iagp = (struct iag *) mp->data; @@ -1948,8 +1944,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) if (sword >= SMAPSZ) { release_metapage(mp); IREAD_UNLOCK(imap->im_ipimap); - jfs_error(ip->i_sb, - "diAllocExt: free ext summary map not found"); + jfs_error(ip->i_sb, "free ext summary map not found\n"); return -EIO; } if (~iagp->extsmap[sword]) @@ -1962,7 +1957,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip) if (rem >= EXTSPERSUM) { release_metapage(mp); IREAD_UNLOCK(imap->im_ipimap); - jfs_error(ip->i_sb, "diAllocExt: free extent not found"); + jfs_error(ip->i_sb, "free extent not found\n"); return -EIO; } extno = (sword << L2EXTSPERSUM) + rem; @@ -2081,8 +2076,7 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino) if (bmp) release_metapage(bmp); - jfs_error(imap->im_ipimap->i_sb, - "diAllocBit: iag inconsistent"); + jfs_error(imap->im_ipimap->i_sb, "iag inconsistent\n"); return -EIO; } @@ -2189,7 +2183,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) /* better have free extents. */ if (!iagp->nfreeexts) { - jfs_error(imap->im_ipimap->i_sb, "diNewExt: no free extents"); + jfs_error(imap->im_ipimap->i_sb, "no free extents\n"); return -EIO; } @@ -2261,7 +2255,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno) } if (ciagp == NULL) { jfs_error(imap->im_ipimap->i_sb, - "diNewExt: ciagp == NULL"); + "ciagp == NULL\n"); rc = -EIO; goto error_out; } @@ -2498,7 +2492,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) IWRITE_UNLOCK(ipimap); IAGFREE_UNLOCK(imap); jfs_error(imap->im_ipimap->i_sb, - "diNewIAG: ipimap->i_size is wrong"); + "ipimap->i_size is wrong\n"); return -EIO; } @@ -2758,8 +2752,7 @@ diUpdatePMap(struct inode *ipimap, iagno = INOTOIAG(inum); /* make sure that the iag is contained within the map */ if (iagno >= imap->im_nextiag) { - jfs_error(ipimap->i_sb, - "diUpdatePMap: the iag is outside the map"); + jfs_error(ipimap->i_sb, "the iag is outside the map\n"); return -EIO; } /* read the iag */ @@ -2788,13 +2781,13 @@ diUpdatePMap(struct inode *ipimap, */ if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { jfs_error(ipimap->i_sb, - "diUpdatePMap: inode %ld not marked as " - "allocated in wmap!", inum); + "inode %ld not marked as allocated in wmap!\n", + inum); } if (!(le32_to_cpu(iagp->pmap[extno]) & mask)) { jfs_error(ipimap->i_sb, - "diUpdatePMap: inode %ld not marked as " - "allocated in pmap!", inum); + "inode %ld not marked as allocated in pmap!\n", + inum); } /* update the bitmap for the extent of the freed inode */ iagp->pmap[extno] &= cpu_to_le32(~mask); @@ -2809,15 +2802,13 @@ diUpdatePMap(struct inode *ipimap, if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { release_metapage(mp); jfs_error(ipimap->i_sb, - "diUpdatePMap: the inode is not allocated in " - "the working map"); + "the inode is not allocated in the working map\n"); return -EIO; } if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) { release_metapage(mp); jfs_error(ipimap->i_sb, - "diUpdatePMap: the inode is not free in the " - "persistent map"); + "the inode is not free in the persistent map\n"); return -EIO; } /* update the bitmap for the extent of the allocated inode */ @@ -2909,8 +2900,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) iagp = (struct iag *) bp->data; if (le32_to_cpu(iagp->iagnum) != i) { release_metapage(bp); - jfs_error(ipimap->i_sb, - "diExtendFs: unexpected value of iagnum"); + jfs_error(ipimap->i_sb, "unexpected value of iagnum\n"); return -EIO; } @@ -2986,8 +2976,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) if (xnuminos != atomic_read(&imap->im_numinos) || xnumfree != atomic_read(&imap->im_numfree)) { - jfs_error(ipimap->i_sb, - "diExtendFs: numinos or numfree incorrect"); + jfs_error(ipimap->i_sb, "numinos or numfree incorrect\n"); return -EIO; } diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 6740d34cd82b..6052c0d39382 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -646,7 +646,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, if (mp) { if (mp->logical_size != size) { jfs_error(inode->i_sb, - "__get_metapage: mp->logical_size != size"); + "get_mp->logical_size != size\n"); jfs_err("logical_size = %d, size = %d", mp->logical_size, size); dump_stack(); @@ -657,8 +657,7 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, if (test_bit(META_discard, &mp->flag)) { if (!new) { jfs_error(inode->i_sb, - "__get_metapage: using a " - "discarded metapage"); + "using a discarded metapage\n"); discard_metapage(mp); goto unlock; } diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h index 884fc21ab8ee..04847b8d3070 100644 --- a/fs/jfs/jfs_superblock.h +++ b/fs/jfs/jfs_superblock.h @@ -108,6 +108,7 @@ struct jfs_superblock { extern int readSuper(struct super_block *, struct buffer_head **); extern int updateSuper(struct super_block *, uint); +__printf(2, 3) extern void jfs_error(struct super_block *, const char *, ...); extern int jfs_mount(struct super_block *); extern int jfs_mount_rw(struct super_block *, int); diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 5fcc02eaa64c..564c4f279ac6 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -2684,7 +2684,7 @@ void txAbort(tid_t tid, int dirty) * mark filesystem dirty */ if (dirty) - jfs_error(tblk->sb, "txAbort"); + jfs_error(tblk->sb, "\n"); return; } diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index 6c50871e6220..5ad7748860ce 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -64,22 +64,23 @@ /* get page buffer for specified block address */ /* ToDo: Replace this ugly macro with a function */ -#define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)\ -{\ - BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\ - if (!(RC))\ - {\ - if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) ||\ - (le16_to_cpu((P)->header.nextindex) > le16_to_cpu((P)->header.maxentry)) ||\ - (le16_to_cpu((P)->header.maxentry) > (((BN)==0)?XTROOTMAXSLOT:PSIZE>>L2XTSLOTSIZE)))\ - {\ - jfs_error((IP)->i_sb, "XT_GETPAGE: xtree page corrupt");\ - BT_PUTPAGE(MP);\ - MP = NULL;\ - RC = -EIO;\ - }\ - }\ -} +#define XT_GETPAGE(IP, BN, MP, SIZE, P, RC) \ +do { \ + BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot); \ + if (!(RC)) { \ + if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) || \ + (le16_to_cpu((P)->header.nextindex) > \ + le16_to_cpu((P)->header.maxentry)) || \ + (le16_to_cpu((P)->header.maxentry) > \ + (((BN) == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE))) { \ + jfs_error((IP)->i_sb, \ + "XT_GETPAGE: xtree page corrupt\n"); \ + BT_PUTPAGE(MP); \ + MP = NULL; \ + RC = -EIO; \ + } \ + } \ +} while (0) /* for consistency */ #define XT_PUTPAGE(MP) BT_PUTPAGE(MP) @@ -499,7 +500,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, /* push (bn, index) of the parent page/entry */ if (BT_STACK_FULL(btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtSearch!"); + jfs_error(ip->i_sb, "stack overrun!\n"); XT_PUTPAGE(mp); return -EIO; } @@ -1385,7 +1386,7 @@ int xtExtend(tid_t tid, /* transaction id */ if (cmp != 0) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent"); + jfs_error(ip->i_sb, "xtSearch did not find extent\n"); return -EIO; } @@ -1393,7 +1394,7 @@ int xtExtend(tid_t tid, /* transaction id */ xad = &p->xad[index]; if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtExtend: extension is not contiguous"); + jfs_error(ip->i_sb, "extension is not contiguous\n"); return -EIO; } @@ -1552,7 +1553,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", if (cmp != 0) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtTailgate: couldn't find extent"); + jfs_error(ip->i_sb, "couldn't find extent\n"); return -EIO; } @@ -1560,8 +1561,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", nextindex = le16_to_cpu(p->header.nextindex); if (index != nextindex - 1) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, - "xtTailgate: the entry found is not the last entry"); + jfs_error(ip->i_sb, "the entry found is not the last entry\n"); return -EIO; } @@ -1734,7 +1734,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if (cmp != 0) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtUpdate: Could not find extent"); + jfs_error(ip->i_sb, "Could not find extent\n"); return -EIO; } @@ -1758,7 +1758,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) (nxoff + nxlen > xoff + xlen)) { XT_PUTPAGE(mp); jfs_error(ip->i_sb, - "xtUpdate: nXAD in not completely contained within XAD"); + "nXAD in not completely contained within XAD\n"); return -EIO; } @@ -1907,7 +1907,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if (xoff >= nxoff) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtUpdate: xoff >= nxoff"); + jfs_error(ip->i_sb, "xoff >= nxoff\n"); return -EIO; } /* #endif _JFS_WIP_COALESCE */ @@ -2048,14 +2048,13 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if (cmp != 0) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, "xtUpdate: xtSearch failed"); + jfs_error(ip->i_sb, "xtSearch failed\n"); return -EIO; } if (index0 != index) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, - "xtUpdate: unexpected value of index"); + jfs_error(ip->i_sb, "unexpected value of index\n"); return -EIO; } } @@ -3650,7 +3649,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) getChild: /* save current parent entry for the child page */ if (BT_STACK_FULL(&btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtTruncate!"); + jfs_error(ip->i_sb, "stack overrun!\n"); XT_PUTPAGE(mp); return -EIO; } @@ -3751,8 +3750,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) if (cmp != 0) { XT_PUTPAGE(mp); - jfs_error(ip->i_sb, - "xtTruncate_pmap: did not find extent"); + jfs_error(ip->i_sb, "did not find extent\n"); return -EIO; } } else { @@ -3851,7 +3849,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) getChild: /* save current parent entry for the child page */ if (BT_STACK_FULL(&btstack)) { - jfs_error(ip->i_sb, "stack overrun in xtTruncate_pmap!"); + jfs_error(ip->i_sb, "stack overrun!\n"); XT_PUTPAGE(mp); return -EIO; } diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 3b91a7ad6086..eb9799bb367c 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1176,7 +1176,7 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (!S_ISDIR(old_ip->i_mode) && new_ip) IWRITE_UNLOCK(new_ip); jfs_error(new_ip->i_sb, - "jfs_rename: new_ip->i_nlink != 0"); + "new_ip->i_nlink != 0\n"); return -EIO; } tblk = tid_to_tblock(tid); diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 8d0c1c7c0820..90b3bc21e9b0 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c @@ -530,7 +530,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) goto resume; error_out: - jfs_error(sb, "jfs_extendfs"); + jfs_error(sb, "\n"); resume: /* diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 788e0a9c1fb0..6669aa2042c3 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -92,16 +92,20 @@ static void jfs_handle_error(struct super_block *sb) /* nothing is done for continue beyond marking the superblock dirty */ } -void jfs_error(struct super_block *sb, const char * function, ...) +void jfs_error(struct super_block *sb, const char *fmt, ...) { - static char error_buf[256]; + struct va_format vaf; va_list args; - va_start(args, function); - vsnprintf(error_buf, sizeof(error_buf), function, args); - va_end(args); + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; - pr_err("ERROR: (device %s): %s\n", sb->s_id, error_buf); + pr_err("ERROR: (device %s): %pf: %pV\n", + sb->s_id, __builtin_return_address(0), &vaf); + + va_end(args); jfs_handle_error(sb); } @@ -617,7 +621,7 @@ static int jfs_freeze(struct super_block *sb) txQuiesce(sb); rc = lmLogShutdown(log); if (rc) { - jfs_error(sb, "jfs_freeze: lmLogShutdown failed"); + jfs_error(sb, "lmLogShutdown failed\n"); /* let operations fail rather than hang */ txResume(sb); @@ -646,12 +650,12 @@ static int jfs_unfreeze(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) { rc = updateSuper(sb, FM_MOUNT); if (rc) { - jfs_error(sb, "jfs_unfreeze: updateSuper failed"); + jfs_error(sb, "updateSuper failed\n"); goto out; } rc = lmLogInit(log); if (rc) - jfs_error(sb, "jfs_unfreeze: lmLogInit failed"); + jfs_error(sb, "lmLogInit failed\n"); out: txResume(sb); } diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 86ce028f2566..d3472f4cd530 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -382,7 +382,7 @@ static int ea_read(struct inode *ip, struct jfs_ea_list *ealist) nbytes = sizeDXD(&ji->ea); if (!nbytes) { - jfs_error(sb, "ea_read: nbytes is 0"); + jfs_error(sb, "nbytes is 0\n"); return -EIO; } @@ -482,7 +482,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) current_blocks = 0; } else { if (!(ji->ea.flag & DXD_EXTENT)) { - jfs_error(sb, "ea_get: invalid ea.flag)"); + jfs_error(sb, "invalid ea.flag\n"); return -EIO; } current_blocks = (ea_size + sb->s_blocksize - 1) >> -- GitLab From 4c4d41f200db375b2d2cc6d0a1de0606c8266398 Mon Sep 17 00:00:00 2001 From: Fan Du Date: Thu, 6 Jun 2013 10:15:54 +0800 Subject: [PATCH 0690/2900] xfrm: add LINUX_MIB_XFRMACQUIREERROR statistic counter When host ping its peer, ICMP echo request packet triggers IPsec policy, then host negotiates SA secret with its peer. After IKE installed SA for OUT direction, but before SA for IN direction installed, host get ICMP echo reply from its peer. At the time being, the SA state for IN direction could be XFRM_STATE_ACQ, then the received packet will be dropped after adding LINUX_MIB_XFRMINSTATEINVALID statistic. Adding a LINUX_MIB_XFRMACQUIREERROR statistic counter for such scenario when SA in larval state is much clearer for user than LINUX_MIB_XFRMINSTATEINVALID which indicates the SA is totally bad. Signed-off-by: Fan Du Signed-off-by: Steffen Klassert --- include/uapi/linux/snmp.h | 1 + net/xfrm/xfrm_input.c | 5 +++++ net/xfrm/xfrm_proc.c | 1 + 3 files changed, 7 insertions(+) diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index df2e8b4f9c03..ea17542ff321 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h @@ -287,6 +287,7 @@ enum LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */ + LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */ __LINUX_MIB_XFRMMAX }; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index ab2bb42fe094..88843996f935 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -163,6 +163,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) skb->sp->xvec[skb->sp->len++] = x; spin_lock(&x->lock); + if (unlikely(x->km.state == XFRM_STATE_ACQ)) { + XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); + goto drop_unlock; + } + if (unlikely(x->km.state != XFRM_STATE_VALID)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEINVALID); goto drop_unlock; diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index c721b0d9ab8b..80cd1e55b834 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -44,6 +44,7 @@ static const struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR), SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR), SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID), + SNMP_MIB_ITEM("XfrmAcquireError", LINUX_MIB_XFRMACQUIREERROR), SNMP_MIB_SENTINEL }; -- GitLab From b22ffdcd25d67a07f2b5a75a7805826bfe8597f1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 22 Apr 2013 10:29:26 +0200 Subject: [PATCH 0691/2900] mmc: tmio: postpone controller reset during resume When resuming, the tmio_mmc_host_resume() function is run when the controller might still be powered down. Issuing a reset command to it at that time has no effect. This patch postpones resetting the controller until the first powering-up .set_ios() call. Reported-by: Nguyen Viet Dung Signed-off-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.h | 1 + drivers/mmc/host/tmio_mmc_pio.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index d857f5c6e7d9..759d8f4f130c 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -85,6 +85,7 @@ struct tmio_mmc_host { unsigned long last_req_ts; struct mutex ios_lock; /* protect set_ios() context */ bool native_hotplug; + bool resuming; }; int tmio_mmc_host_probe(struct tmio_mmc_host **host, diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f508ecb5b8a7..435cc4d2520f 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -862,6 +862,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (!host->power) { tmio_mmc_clk_update(mmc); pm_runtime_get_sync(dev); + if (host->resuming) { + tmio_mmc_reset(host); + host->resuming = false; + } } tmio_mmc_set_clock(host, ios->clock); if (!host->power) { @@ -1154,10 +1158,10 @@ int tmio_mmc_host_resume(struct device *dev) struct mmc_host *mmc = dev_get_drvdata(dev); struct tmio_mmc_host *host = mmc_priv(mmc); - tmio_mmc_reset(host); tmio_mmc_enable_dma(host, true); /* The MMC core will perform the complete set up */ + host->resuming = true; return mmc_resume_host(mmc); } EXPORT_SYMBOL(tmio_mmc_host_resume); -- GitLab From 19f1ba51c79f133aec3ce558b8292e3b081363f3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 15 May 2013 07:50:51 +0200 Subject: [PATCH 0692/2900] mmc: sh_mmcif: don't clear masked interrupts Masking events on MMCIF means that an occurrence of the masked event won't raise an interrupt, but the event bit will still be set in the interrupt status register. If simultaneously a different event occurs which was enabled, both flags will be set. However, only the unmasked event bit should be cleared in the status register in such a case. Clearing also the masked bit can lead to lost interrupts, which indeed can be observed on the armadillo800eva r8a7740 board with an eMMC chip. The problem has been introduced by the recent "mmc: sh_mmcif: simplify IRQ processing" patch. Fix the problem by only clearing enabled interrupts. Signed-off-by: Guennadi Liakhovetski Tested-by: Nguyen Viet Dung Tested-by: Kuninori Morimoto Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 117a1f774720..8ef5efad45d0 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1244,7 +1244,8 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) u32 state; state = sh_mmcif_readl(host->addr, MMCIF_CE_INT); - sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state); + sh_mmcif_writel(host->addr, MMCIF_CE_INT, + ~(state & sh_mmcif_readl(host->addr, MMCIF_CE_INT_MASK))); sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN); if (state & ~MASK_CLEAN) -- GitLab From e83b7a8acc420923cbe8a30901d9eb60677f54fb Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 6 Jun 2013 16:35:44 +0200 Subject: [PATCH 0693/2900] mmc: tmio: fix unbalanced power-on calls with clock-gating enabled With MMC clock gating enabled the MMC core currently calls MMC host driver's .set_ios() method with .power_mode == MMC_POWER_ON and the clock value set either to 0 or to the target rate. The tmio MMC driver then wrongly translates the latter calls to card slot power-on requests, even when the slot already was on. This patch fixes the driver to avoid needlessly incrementing power-supplying regulator's use count. Signed-off-by: Guennadi Liakhovetski Tested-by: Laurent Pinchart Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc.h | 20 ++++++++++++++++++-- drivers/mmc/host/tmio_mmc_pio.c | 27 +++++++++++++++++---------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 759d8f4f130c..86fd21e00099 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -40,6 +40,22 @@ struct tmio_mmc_data; +/* + * We differentiate between the following 3 power states: + * 1. card slot powered off, controller stopped. This is used, when either there + * is no card in the slot, or the card really has to be powered down. + * 2. card slot powered on, controller stopped. This is used, when a card is in + * the slot, but no activity is currently taking place. This is a power- + * saving mode with card-state preserved. This state can be entered, e.g. + * when MMC clock-gating is used. + * 3. card slot powered on, controller running. This is the actual active state. + */ +enum tmio_mmc_power { + TMIO_MMC_OFF_STOP, /* card power off, controller stopped */ + TMIO_MMC_ON_STOP, /* card power on, controller stopped */ + TMIO_MMC_ON_RUN, /* card power on, controller running */ +}; + struct tmio_mmc_host { void __iomem *ctl; unsigned long bus_shift; @@ -48,8 +64,8 @@ struct tmio_mmc_host { struct mmc_data *data; struct mmc_host *mmc; - /* Controller power state */ - bool power; + /* Controller and card power state */ + enum tmio_mmc_power power; /* Callbacks for clock / power control */ void (*set_pwr)(struct platform_device *host, int state); diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 435cc4d2520f..67d96428e62a 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -859,7 +859,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * is kept positive, so no suspending actually takes place. */ if (ios->power_mode == MMC_POWER_ON && ios->clock) { - if (!host->power) { + if (host->power != TMIO_MMC_ON_RUN) { tmio_mmc_clk_update(mmc); pm_runtime_get_sync(dev); if (host->resuming) { @@ -868,27 +868,34 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } tmio_mmc_set_clock(host, ios->clock); - if (!host->power) { + if (host->power == TMIO_MMC_OFF_STOP) /* power up SD card and the bus */ tmio_mmc_power_on(host, ios->vdd); - host->power = true; - } + host->power = TMIO_MMC_ON_RUN; /* start bus clock */ tmio_mmc_clk_start(host); } else if (ios->power_mode != MMC_POWER_UP) { - if (host->power) { - struct tmio_mmc_data *pdata = host->pdata; - if (ios->power_mode == MMC_POWER_OFF) + struct tmio_mmc_data *pdata = host->pdata; + unsigned int old_power = host->power; + + if (old_power != TMIO_MMC_OFF_STOP) { + if (ios->power_mode == MMC_POWER_OFF) { tmio_mmc_power_off(host); + host->power = TMIO_MMC_OFF_STOP; + } else { + host->power = TMIO_MMC_ON_STOP; + } + } + + if (old_power == TMIO_MMC_ON_RUN) { tmio_mmc_clk_stop(host); - host->power = false; pm_runtime_put(dev); if (pdata->clk_disable) pdata->clk_disable(host->pdev); } } - if (host->power) { + if (host->power != TMIO_MMC_OFF_STOP) { switch (ios->bus_width) { case MMC_BUS_WIDTH_1: sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0); @@ -1029,7 +1036,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, mmc->caps & MMC_CAP_NONREMOVABLE || mmc->slot.cd_irq >= 0); - _host->power = false; + _host->power = TMIO_MMC_OFF_STOP; pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume(&pdev->dev); if (ret < 0) -- GitLab From b9ec2744128d0940342b236e9018614ba8848118 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 6 Jun 2013 16:35:48 +0200 Subject: [PATCH 0694/2900] mmc: tmio: reset the controller after power-up This fixes two reported problems: 1. after a system resume the controller isn't functioning until a command runs on a timeout and a controller reset is performed. 2. if a card is ejected during a running write operation, its re-insertion isn't detected. Reported-by: Nguyen Viet Dung Reported-by: Nguyen Hong Ky Signed-off-by: Guennadi Liakhovetski Tested-by: Nguyen Viet Dung Tested-by: Nguyen Hong Ky Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc_pio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index 67d96428e62a..f29470835a4f 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -867,6 +867,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->resuming = false; } } + if (host->power == TMIO_MMC_OFF_STOP) + tmio_mmc_reset(host); tmio_mmc_set_clock(host, ios->clock); if (host->power == TMIO_MMC_OFF_STOP) /* power up SD card and the bus */ @@ -1186,7 +1188,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) struct mmc_host *mmc = dev_get_drvdata(dev); struct tmio_mmc_host *host = mmc_priv(mmc); - tmio_mmc_reset(host); tmio_mmc_enable_dma(host, true); return 0; -- GitLab From 41d5ffeb9d12f760722f00ba0756389d32435124 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:43:16 +0000 Subject: [PATCH 0695/2900] sh_eth: remove #ifdef around EDSR and GECMR bit definitions Remove #ifdef around 'enum EDSR_BIT' and 'enum GECMR_BIT', replacing it with the comments on which SoCs these registers exist. SH7757 also has EDSR, so add a comment about it to 'enum EDSR_BIT'. Signed-off-by: Nobuhiro Iwamatsu [Sergei: folded in the former patch #2, updated the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 1ddc9f235bcb..8daba1d70539 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -166,19 +166,16 @@ enum { /* * Register's bits */ -#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) ||\ - defined(CONFIG_ARCH_R8A7740) -/* EDSR */ +/* EDSR : sh7734, sh7757, sh7763, and r8a7740 only */ enum EDSR_BIT { EDSR_ENT = 0x01, EDSR_ENR = 0x02, }; #define EDSR_ENALL (EDSR_ENT|EDSR_ENR) -/* GECMR */ +/* GECMR : sh7734, sh7763 and r8a7740 only */ enum GECMR_BIT { GECMR_10 = 0x0, GECMR_100 = 0x04, GECMR_1000 = 0x01, }; -#endif /* EDMR */ enum DMAC_M_BIT { -- GitLab From ddcd91c6b8ec60a6bd5d3691d2cfaf4447215da1 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:44:27 +0000 Subject: [PATCH 0696/2900] sh_eth: use EDSR_ENALL to set EDSR Use now always available EDSR_ENALL instead of the bare number to set EDSR. Signed-off-by: Nobuhiro Iwamatsu [Sergei: added the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 399a7c968e0d..8b7ff6a03699 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -523,7 +523,7 @@ static int sh_eth_reset(struct net_device *ndev) int ret = 0; if (sh_eth_is_gether(mdp)) { - sh_eth_write(ndev, 0x03, EDSR); + sh_eth_write(ndev, EDSR_ENALL, EDSR); sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); -- GitLab From 04b0ed2ad49834fe47d3c4171ad189c688a222b9 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:45:25 +0000 Subject: [PATCH 0697/2900] sh_eth: remove duplicate sh_eth_set_duplex() definitions Remove all the duplicate definitions of sh_eth_set_duplex() under different #ifdef's, leaving only one outside the #ifdef's. We have to annotate it with '__maybe_unused' since it's called not from all SoC #ifdef blocks. Signed-off-by: Nobuhiro Iwamatsu [Sergei: annotated sh_eth_set_duplex() as '__maybe_unused', added the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 59 +++------------------------ 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 8b7ff6a03699..856ea881b45c 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -341,10 +341,7 @@ static void sh_eth_select_mii(struct net_device *ndev) } #endif -/* There is CPU dependent code */ -#if defined(CONFIG_ARCH_R8A7778) || defined(CONFIG_ARCH_R8A7779) -#define SH_ETH_RESET_DEFAULT 1 -static void sh_eth_set_duplex(struct net_device *ndev) +static void __maybe_unused sh_eth_set_duplex(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -354,6 +351,9 @@ static void sh_eth_set_duplex(struct net_device *ndev) sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); } +/* There is CPU dependent code */ +#if defined(CONFIG_ARCH_R8A7778) || defined(CONFIG_ARCH_R8A7779) +#define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -391,15 +391,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { }; #elif defined(CONFIG_CPU_SUBTYPE_SH7724) #define SH_ETH_RESET_DEFAULT 1 -static void sh_eth_set_duplex(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); -} static void sh_eth_set_rate(struct net_device *ndev) { @@ -443,16 +434,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { #define SH_ETH_HAS_TSU 1 static int sh_eth_check_reset(struct net_device *ndev); -static void sh_eth_set_duplex(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); -} - static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -552,16 +533,6 @@ static int sh_eth_reset(struct net_device *ndev) return ret; } -static void sh_eth_set_duplex_giga(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); -} - static void sh_eth_set_rate_giga(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -584,7 +555,7 @@ static void sh_eth_set_rate_giga(struct net_device *ndev) /* SH7757(GETHERC) */ static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { .chip_reset = sh_eth_chip_reset_giga, - .set_duplex = sh_eth_set_duplex_giga, + .set_duplex = sh_eth_set_duplex, .set_rate = sh_eth_set_rate_giga, .ecsr_value = ECSR_ICD | ECSR_MPD, @@ -634,16 +605,6 @@ static void sh_eth_chip_reset(struct net_device *ndev) mdelay(1); } -static void sh_eth_set_duplex(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); -} - static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -771,16 +732,6 @@ static int sh_eth_reset(struct net_device *ndev) return ret; } -static void sh_eth_set_duplex(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - if (mdp->duplex) /* Full */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR); - else /* Half */ - sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR); -} - static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); -- GitLab From 9f86134155047720a3685cda21467f68695152d2 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:48:09 +0000 Subject: [PATCH 0698/2900] sh_eth: remove SH_ETH_HAS_TSU Remove SH_ETH_HAS_TSU #define's and #ifdef's. Set three 'struct net_device_ops' methods that depend on the presence of TSU basing on the 'tsu' field of 'struct sh_eth_cpu_data'. Signed-off-by: Nobuhiro Iwamatsu [Sergei: made two method assignments one-liners, added the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 856ea881b45c..f8d60947fa72 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -431,7 +431,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { }; #elif defined(CONFIG_CPU_SUBTYPE_SH7757) #define SH_ETH_HAS_BOTH_MODULES 1 -#define SH_ETH_HAS_TSU 1 static int sh_eth_check_reset(struct net_device *ndev); static void sh_eth_set_rate(struct net_device *ndev) @@ -592,7 +591,6 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) } #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) -#define SH_ETH_HAS_TSU 1 static int sh_eth_check_reset(struct net_device *ndev); static void sh_eth_reset_hw_crc(struct net_device *ndev); @@ -693,7 +691,6 @@ static void sh_eth_reset_hw_crc(struct net_device *ndev) } #elif defined(CONFIG_ARCH_R8A7740) -#define SH_ETH_HAS_TSU 1 static int sh_eth_check_reset(struct net_device *ndev); static void sh_eth_chip_reset(struct net_device *ndev) @@ -791,7 +788,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { }; #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) #define SH_ETH_RESET_DEFAULT 1 -#define SH_ETH_HAS_TSU 1 static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .tsu = 1, @@ -2105,7 +2101,6 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, return phy_mii_ioctl(phydev, rq, cmd); } -#if defined(SH_ETH_HAS_TSU) /* For TSU_POSTn. Please refer to the manual about this (strange) bitfields */ static void *sh_eth_tsu_get_post_reg_offset(struct sh_eth_private *mdp, int entry) @@ -2448,7 +2443,6 @@ static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, return 0; } -#endif /* SH_ETH_HAS_TSU */ /* SuperH's TSU register init function */ static void sh_eth_tsu_init(struct sh_eth_private *mdp) @@ -2587,16 +2581,11 @@ static const u16 *sh_eth_get_register_offset(int register_type) return reg_offset; } -static const struct net_device_ops sh_eth_netdev_ops = { +static struct net_device_ops sh_eth_netdev_ops = { .ndo_open = sh_eth_open, .ndo_stop = sh_eth_close, .ndo_start_xmit = sh_eth_start_xmit, .ndo_get_stats = sh_eth_get_stats, -#if defined(SH_ETH_HAS_TSU) - .ndo_set_rx_mode = sh_eth_set_multicast_list, - .ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid, -#endif .ndo_tx_timeout = sh_eth_tx_timeout, .ndo_do_ioctl = sh_eth_do_ioctl, .ndo_validate_addr = eth_validate_addr, @@ -2677,6 +2666,13 @@ static int sh_eth_drv_probe(struct platform_device *pdev) sh_eth_set_default_cpu_data(mdp->cd); /* set function */ + if (mdp->cd->tsu) { + sh_eth_netdev_ops.ndo_set_rx_mode = sh_eth_set_multicast_list; + sh_eth_netdev_ops.ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid; + sh_eth_netdev_ops.ndo_vlan_rx_kill_vid = + sh_eth_vlan_rx_kill_vid; + } + ndev->netdev_ops = &sh_eth_netdev_ops; SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops); ndev->watchdog_timeo = TX_TIMEOUT; -- GitLab From 5b3dfd13ae8bdebea67c02612fe282baff850bb0 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:49:30 +0000 Subject: [PATCH 0699/2900] sh_eth: add IRQ flags to 'struct sh_eth_cpu_data' The driver supports some SH and SH-Mobile SOCs. There are SOCs with two or more Ethernet devices, for these we need to pass IRQF_SHARED to request_irq(). Add the 'irq_flags' field to the 'struct sh_eth_cpu_data' instead of #ifdef'fery. Signed-off-by: Nobuhiro Iwamatsu [Sergei: properly aligned request_irq() call continuation line, reworded the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 13 +++++-------- drivers/net/ethernet/renesas/sh_eth.h | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f8d60947fa72..d0151d02416f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -462,6 +462,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, + .irq_flags = IRQF_SHARED, .apr = 1, .mpr = 1, .tpauser = 1, @@ -570,6 +571,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { .fdr_value = 0x0000072f, .rmcr_value = 0x00000001, + .irq_flags = IRQF_SHARED, .apr = 1, .mpr = 1, .tpauser = 1, @@ -650,6 +652,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { #if defined(CONFIG_CPU_SUBTYPE_SH7734) .hw_crc = 1, .select_mii = 1, +#else + .irq_flags = IRQF_SHARED, #endif }; @@ -1908,14 +1912,7 @@ static int sh_eth_open(struct net_device *ndev) pm_runtime_get_sync(&mdp->pdev->dev); ret = request_irq(ndev->irq, sh_eth_interrupt, -#if defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_CPU_SUBTYPE_SH7764) || \ - defined(CONFIG_CPU_SUBTYPE_SH7757) - IRQF_SHARED, -#else - 0, -#endif - ndev->name, ndev); + mdp->cd->irq_flags, ndev->name, ndev); if (ret) { dev_err(&ndev->dev, "Can not assign IRQ number\n"); return ret; diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 8daba1d70539..729e77e66f19 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -463,6 +463,7 @@ struct sh_eth_cpu_data { unsigned long tx_error_check; /* hardware features */ + unsigned long irq_flags; /* IRQ configuration flags */ unsigned no_psr:1; /* EtherC DO NOT have PSR */ unsigned apr:1; /* EtherC have APR */ unsigned mpr:1; /* EtherC have MPR */ -- GitLab From b7feacf1ee6944fc571802d58dcffaf13b4fb4cc Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:50:30 +0000 Subject: [PATCH 0700/2900] sh_eth: remove #ifdef around sh_eth_select_mii() We can simply remove #ifdef'fery around sh_eth_select_mii(). We have to annotate it with '__maybe_unused' then. Signed-off-by: Nobuhiro Iwamatsu [Sergei: added the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d0151d02416f..2234a945ae5b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -313,10 +313,7 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { [TSU_ADRL31] = 0x01fc, }; -#if defined(CONFIG_CPU_SUBTYPE_SH7734) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) || \ - defined(CONFIG_ARCH_R8A7740) -static void sh_eth_select_mii(struct net_device *ndev) +static void __maybe_unused sh_eth_select_mii(struct net_device *ndev) { u32 value = 0x0; struct sh_eth_private *mdp = netdev_priv(ndev); @@ -339,7 +336,6 @@ static void sh_eth_select_mii(struct net_device *ndev) sh_eth_write(ndev, value, RMII_MII); } -#endif static void __maybe_unused sh_eth_set_duplex(struct net_device *ndev) { -- GitLab From dabdde9ea77d4a77094726c82468a3bd767fb29b Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:51:39 +0000 Subject: [PATCH 0701/2900] sh_eth: consolidate sh_eth_reset() This driver has sh_eth_reset() function for each SoC and this function is almost always the same, except for the several a bit different variations for Gigabit Ethernet. Consolidate every variation into a single function -- which allows us to get rid of some more #ifdef'fery. Signed-off-by: Nobuhiro Iwamatsu [Sergei: moved the new sh_eth_reset() and sh_eth_is_gether() up to decrease the patch size, fixed function call continuation lines' indentation, reworded the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 176 ++++++++------------------ 1 file changed, 51 insertions(+), 125 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 2234a945ae5b..d190c1e0b0c0 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -313,6 +313,14 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = { [TSU_ADRL31] = 0x01fc, }; +static int sh_eth_is_gether(struct sh_eth_private *mdp) +{ + if (mdp->reg_offset == sh_eth_offset_gigabit) + return 1; + else + return 0; +} + static void __maybe_unused sh_eth_select_mii(struct net_device *ndev) { u32 value = 0x0; @@ -349,7 +357,6 @@ static void __maybe_unused sh_eth_set_duplex(struct net_device *ndev) /* There is CPU dependent code */ #if defined(CONFIG_ARCH_R8A7778) || defined(CONFIG_ARCH_R8A7779) -#define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -386,7 +393,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .hw_swap = 1, }; #elif defined(CONFIG_CPU_SUBTYPE_SH7724) -#define SH_ETH_RESET_DEFAULT 1 static void sh_eth_set_rate(struct net_device *ndev) { @@ -427,7 +433,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { }; #elif defined(CONFIG_CPU_SUBTYPE_SH7757) #define SH_ETH_HAS_BOTH_MODULES 1 -static int sh_eth_check_reset(struct net_device *ndev); static void sh_eth_set_rate(struct net_device *ndev) { @@ -493,42 +498,6 @@ static void sh_eth_chip_reset_giga(struct net_device *ndev) } } -static int sh_eth_is_gether(struct sh_eth_private *mdp); -static int sh_eth_reset(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - int ret = 0; - - if (sh_eth_is_gether(mdp)) { - sh_eth_write(ndev, EDSR_ENALL, EDSR); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, - EDMR); - - ret = sh_eth_check_reset(ndev); - if (ret) - goto out; - - /* Table Init */ - sh_eth_write(ndev, 0x0, TDLAR); - sh_eth_write(ndev, 0x0, TDFAR); - sh_eth_write(ndev, 0x0, TDFXR); - sh_eth_write(ndev, 0x0, TDFFR); - sh_eth_write(ndev, 0x0, RDLAR); - sh_eth_write(ndev, 0x0, RDFAR); - sh_eth_write(ndev, 0x0, RDFXR); - sh_eth_write(ndev, 0x0, RDFFR); - } else { - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, - EDMR); - mdelay(3); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, - EDMR); - } - -out: - return ret; -} - static void sh_eth_set_rate_giga(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -589,8 +558,6 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) } #elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) -static int sh_eth_check_reset(struct net_device *ndev); -static void sh_eth_reset_hw_crc(struct net_device *ndev); static void sh_eth_chip_reset(struct net_device *ndev) { @@ -653,45 +620,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { #endif }; -static int sh_eth_reset(struct net_device *ndev) -{ - int ret = 0; - - sh_eth_write(ndev, EDSR_ENALL, EDSR); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); - - ret = sh_eth_check_reset(ndev); - if (ret) - goto out; - - /* Table Init */ - sh_eth_write(ndev, 0x0, TDLAR); - sh_eth_write(ndev, 0x0, TDFAR); - sh_eth_write(ndev, 0x0, TDFXR); - sh_eth_write(ndev, 0x0, TDFFR); - sh_eth_write(ndev, 0x0, RDLAR); - sh_eth_write(ndev, 0x0, RDFAR); - sh_eth_write(ndev, 0x0, RDFXR); - sh_eth_write(ndev, 0x0, RDFFR); - - /* Reset HW CRC register */ - sh_eth_reset_hw_crc(ndev); - - /* Select MII mode */ - if (sh_eth_my_cpu_data.select_mii) - sh_eth_select_mii(ndev); -out: - return ret; -} - -static void sh_eth_reset_hw_crc(struct net_device *ndev) -{ - if (sh_eth_my_cpu_data.hw_crc) - sh_eth_write(ndev, 0x0, CSMR); -} #elif defined(CONFIG_ARCH_R8A7740) -static int sh_eth_check_reset(struct net_device *ndev); static void sh_eth_chip_reset(struct net_device *ndev) { @@ -704,31 +634,6 @@ static void sh_eth_chip_reset(struct net_device *ndev) sh_eth_select_mii(ndev); } -static int sh_eth_reset(struct net_device *ndev) -{ - int ret = 0; - - sh_eth_write(ndev, EDSR_ENALL, EDSR); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR); - - ret = sh_eth_check_reset(ndev); - if (ret) - goto out; - - /* Table Init */ - sh_eth_write(ndev, 0x0, TDLAR); - sh_eth_write(ndev, 0x0, TDFAR); - sh_eth_write(ndev, 0x0, TDFXR); - sh_eth_write(ndev, 0x0, TDFFR); - sh_eth_write(ndev, 0x0, RDLAR); - sh_eth_write(ndev, 0x0, RDFAR); - sh_eth_write(ndev, 0x0, RDFXR); - sh_eth_write(ndev, 0x0, RDFFR); - -out: - return ret; -} - static void sh_eth_set_rate(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -777,7 +682,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { }; #elif defined(CONFIG_CPU_SUBTYPE_SH7619) -#define SH_ETH_RESET_DEFAULT 1 static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, @@ -787,7 +691,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .hw_swap = 1, }; #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) -#define SH_ETH_RESET_DEFAULT 1 static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .tsu = 1, @@ -822,17 +725,6 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd) cd->tx_error_check = DEFAULT_TX_ERROR_CHECK; } -#if defined(SH_ETH_RESET_DEFAULT) -/* Chip Reset */ -static int sh_eth_reset(struct net_device *ndev) -{ - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR); - mdelay(3); - sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR); - - return 0; -} -#else static int sh_eth_check_reset(struct net_device *ndev) { int ret = 0; @@ -850,7 +742,49 @@ static int sh_eth_check_reset(struct net_device *ndev) } return ret; } -#endif + +static int sh_eth_reset(struct net_device *ndev) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + int ret = 0; + + if (sh_eth_is_gether(mdp)) { + sh_eth_write(ndev, EDSR_ENALL, EDSR); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, + EDMR); + + ret = sh_eth_check_reset(ndev); + if (ret) + goto out; + + /* Table Init */ + sh_eth_write(ndev, 0x0, TDLAR); + sh_eth_write(ndev, 0x0, TDFAR); + sh_eth_write(ndev, 0x0, TDFXR); + sh_eth_write(ndev, 0x0, TDFFR); + sh_eth_write(ndev, 0x0, RDLAR); + sh_eth_write(ndev, 0x0, RDFAR); + sh_eth_write(ndev, 0x0, RDFXR); + sh_eth_write(ndev, 0x0, RDFFR); + + /* Reset HW CRC register */ + if (mdp->cd->hw_crc) + sh_eth_write(ndev, 0x0, CSMR); + + /* Select MII mode */ + if (mdp->cd->select_mii) + sh_eth_select_mii(ndev); + } else { + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, + EDMR); + mdelay(3); + sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, + EDMR); + } + +out: + return ret; +} #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) static void sh_eth_set_receive_align(struct sk_buff *skb) @@ -926,14 +860,6 @@ static void read_mac_address(struct net_device *ndev, unsigned char *mac) } } -static int sh_eth_is_gether(struct sh_eth_private *mdp) -{ - if (mdp->reg_offset == sh_eth_offset_gigabit) - return 1; - else - return 0; -} - static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp) { if (sh_eth_is_gether(mdp)) -- GitLab From 540ad1b888ad9564520c1c8c48ad675f76ffce62 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 6 Jun 2013 09:52:37 +0000 Subject: [PATCH 0702/2900] sh_eth: enclose PM code into #ifdef CONFIG_PM Put '#ifdef CONFIG_PM' around sh_eth_runtime_nop() and 'sh_eth_dev_pm_ops'. Add '#define SH_ETH_PM_OPS' to facilitate initialization of driver's 'pm' field depending on whether CONFIG_PM is enabled. Signed-off-by: Nobuhiro Iwamatsu [Sergei: added the changelog, reworded the subject, changing the prefix.] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d190c1e0b0c0..0699b1ec7e32 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2673,6 +2673,7 @@ static int sh_eth_drv_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM static int sh_eth_runtime_nop(struct device *dev) { /* @@ -2686,17 +2687,21 @@ static int sh_eth_runtime_nop(struct device *dev) return 0; } -static struct dev_pm_ops sh_eth_dev_pm_ops = { +static const struct dev_pm_ops sh_eth_dev_pm_ops = { .runtime_suspend = sh_eth_runtime_nop, .runtime_resume = sh_eth_runtime_nop, }; +#define SH_ETH_PM_OPS (&sh_eth_dev_pm_ops) +#else +#define SH_ETH_PM_OPS NULL +#endif static struct platform_driver sh_eth_driver = { .probe = sh_eth_drv_probe, .remove = sh_eth_drv_remove, .driver = { .name = CARDNAME, - .pm = &sh_eth_dev_pm_ops, + .pm = SH_ETH_PM_OPS, }, }; -- GitLab From 1b44791ab4ed27e6fa69f5dfa81b0fd48b1d050d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 4 Jun 2013 21:57:11 +0000 Subject: [PATCH 0703/2900] net/macb: increase RX buffer size for GEM Macb Ethernet controller requires a RX buffer of 128 bytes. It is highly sub-optimal for Gigabit-capable GEM that is able to use a bigger DMA buffer. Change this constant and associated macros with data stored in the private structure. RX DMA buffer size has to be multiple of 64 bytes as indicated in DMA Configuration Register specification. Signed-off-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 45 ++++++++++++++++++++++++----- drivers/net/ethernet/cadence/macb.h | 1 + 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 4465e27ba9d1..aab7bb22b1d0 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -32,7 +32,9 @@ #include "macb.h" -#define RX_BUFFER_SIZE 128 +#define MACB_RX_BUFFER_SIZE 128 +#define GEM_RX_BUFFER_SIZE 2048 +#define RX_BUFFER_MULTIPLE 64 /* bytes */ #define RX_RING_SIZE 512 /* must be power of 2 */ #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE) @@ -92,7 +94,7 @@ static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index) static void *macb_rx_buffer(struct macb *bp, unsigned int index) { - return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index); + return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index); } void macb_set_hwaddr(struct macb *bp) @@ -575,7 +577,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, skb_put(skb, len); for (frag = first_frag; ; frag++) { - unsigned int frag_len = RX_BUFFER_SIZE; + unsigned int frag_len = bp->rx_buffer_size; if (offset + frag_len > len) { BUG_ON(frag != last_frag); @@ -583,7 +585,7 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, } skb_copy_to_linear_data_offset(skb, offset, macb_rx_buffer(bp, frag), frag_len); - offset += RX_BUFFER_SIZE; + offset += bp->rx_buffer_size; desc = macb_rx_desc(bp, frag); desc->addr &= ~MACB_BIT(RX_USED); @@ -870,6 +872,30 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static void macb_init_rx_buffer_size(struct macb *bp) +{ + if (!macb_is_gem(bp)) { + bp->rx_buffer_size = MACB_RX_BUFFER_SIZE; + } else { + bp->rx_buffer_size = GEM_RX_BUFFER_SIZE; + + if (bp->rx_buffer_size > PAGE_SIZE) { + netdev_warn(bp->dev, + "RX buffer cannot be bigger than PAGE_SIZE, shrinking\n"); + bp->rx_buffer_size = PAGE_SIZE; + } + if (bp->rx_buffer_size % RX_BUFFER_MULTIPLE) { + netdev_warn(bp->dev, + "RX buffer must be multiple of %d bytes, shrinking\n", + RX_BUFFER_MULTIPLE); + bp->rx_buffer_size = + rounddown(bp->rx_buffer_size, RX_BUFFER_MULTIPLE); + } + bp->rx_buffer_size = max(RX_BUFFER_MULTIPLE, GEM_RX_BUFFER_SIZE); + } +} + + static void macb_free_consistent(struct macb *bp) { if (bp->tx_skb) { @@ -888,7 +914,7 @@ static void macb_free_consistent(struct macb *bp) } if (bp->rx_buffers) { dma_free_coherent(&bp->pdev->dev, - RX_RING_SIZE * RX_BUFFER_SIZE, + RX_RING_SIZE * bp->rx_buffer_size, bp->rx_buffers, bp->rx_buffers_dma); bp->rx_buffers = NULL; } @@ -921,7 +947,7 @@ static int macb_alloc_consistent(struct macb *bp) "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); - size = RX_RING_SIZE * RX_BUFFER_SIZE; + size = RX_RING_SIZE * bp->rx_buffer_size; bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, &bp->rx_buffers_dma, GFP_KERNEL); if (!bp->rx_buffers) @@ -946,7 +972,7 @@ static void macb_init_rings(struct macb *bp) for (i = 0; i < RX_RING_SIZE; i++) { bp->rx_ring[i].addr = addr; bp->rx_ring[i].ctrl = 0; - addr += RX_BUFFER_SIZE; + addr += bp->rx_buffer_size; } bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); @@ -1056,7 +1082,7 @@ static void macb_configure_dma(struct macb *bp) if (macb_is_gem(bp)) { dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L); - dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64); + dmacfg |= GEM_BF(RXBS, bp->rx_buffer_size / RX_BUFFER_MULTIPLE); dmacfg |= GEM_BF(FBLDO, 16); dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L); dmacfg &= ~GEM_BIT(ENDIA); @@ -1244,6 +1270,9 @@ static int macb_open(struct net_device *dev) if (!bp->phy_dev) return -EAGAIN; + /* RX buffers initialization */ + macb_init_rx_buffer_size(bp); + err = macb_alloc_consistent(bp); if (err) { netdev_err(dev, "Unable to allocate DMA memory (error %d)\n", diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 548c0ecae869..9b5e19f8b61d 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -551,6 +551,7 @@ struct macb { unsigned int rx_tail; struct macb_dma_desc *rx_ring; void *rx_buffers; + size_t rx_buffer_size; unsigned int tx_head, tx_tail; struct macb_dma_desc *tx_ring; -- GitLab From 4df95131ea803bcb94f472d465c73ed57015c470 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 4 Jun 2013 21:57:12 +0000 Subject: [PATCH 0704/2900] net/macb: change RX path for GEM GEM is able to adapt its DMA buffer size, so change the RX path to take advantage of this possibility and remove all kind of memcpy in this path. This modification introduces function pointers for managing differences between MACB and GEM adapter type. Signed-off-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 308 +++++++++++++++++++++++----- drivers/net/ethernet/cadence/macb.h | 13 ++ 2 files changed, 272 insertions(+), 49 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index aab7bb22b1d0..f7e21f278e05 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -33,7 +33,6 @@ #include "macb.h" #define MACB_RX_BUFFER_SIZE 128 -#define GEM_RX_BUFFER_SIZE 2048 #define RX_BUFFER_MULTIPLE 64 /* bytes */ #define RX_RING_SIZE 512 /* must be power of 2 */ #define RX_RING_BYTES (sizeof(struct macb_dma_desc) * RX_RING_SIZE) @@ -530,6 +529,155 @@ static void macb_tx_interrupt(struct macb *bp) netif_wake_queue(bp->dev); } +static void gem_rx_refill(struct macb *bp) +{ + unsigned int entry; + struct sk_buff *skb; + struct macb_dma_desc *desc; + dma_addr_t paddr; + + while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) { + u32 addr, ctrl; + + entry = macb_rx_ring_wrap(bp->rx_prepared_head); + desc = &bp->rx_ring[entry]; + + /* Make hw descriptor updates visible to CPU */ + rmb(); + + addr = desc->addr; + ctrl = desc->ctrl; + bp->rx_prepared_head++; + + if ((addr & MACB_BIT(RX_USED))) + continue; + + if (bp->rx_skbuff[entry] == NULL) { + /* allocate sk_buff for this free entry in ring */ + skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size); + if (unlikely(skb == NULL)) { + netdev_err(bp->dev, + "Unable to allocate sk_buff\n"); + break; + } + bp->rx_skbuff[entry] = skb; + + /* now fill corresponding descriptor entry */ + paddr = dma_map_single(&bp->pdev->dev, skb->data, + bp->rx_buffer_size, DMA_FROM_DEVICE); + + if (entry == RX_RING_SIZE - 1) + paddr |= MACB_BIT(RX_WRAP); + bp->rx_ring[entry].addr = paddr; + bp->rx_ring[entry].ctrl = 0; + + /* properly align Ethernet header */ + skb_reserve(skb, NET_IP_ALIGN); + } + } + + /* Make descriptor updates visible to hardware */ + wmb(); + + netdev_vdbg(bp->dev, "rx ring: prepared head %d, tail %d\n", + bp->rx_prepared_head, bp->rx_tail); +} + +/* Mark DMA descriptors from begin up to and not including end as unused */ +static void discard_partial_frame(struct macb *bp, unsigned int begin, + unsigned int end) +{ + unsigned int frag; + + for (frag = begin; frag != end; frag++) { + struct macb_dma_desc *desc = macb_rx_desc(bp, frag); + desc->addr &= ~MACB_BIT(RX_USED); + } + + /* Make descriptor updates visible to hardware */ + wmb(); + + /* + * When this happens, the hardware stats registers for + * whatever caused this is updated, so we don't have to record + * anything. + */ +} + +static int gem_rx(struct macb *bp, int budget) +{ + unsigned int len; + unsigned int entry; + struct sk_buff *skb; + struct macb_dma_desc *desc; + int count = 0; + + while (count < budget) { + u32 addr, ctrl; + + entry = macb_rx_ring_wrap(bp->rx_tail); + desc = &bp->rx_ring[entry]; + + /* Make hw descriptor updates visible to CPU */ + rmb(); + + addr = desc->addr; + ctrl = desc->ctrl; + + if (!(addr & MACB_BIT(RX_USED))) + break; + + desc->addr &= ~MACB_BIT(RX_USED); + bp->rx_tail++; + count++; + + if (!(ctrl & MACB_BIT(RX_SOF) && ctrl & MACB_BIT(RX_EOF))) { + netdev_err(bp->dev, + "not whole frame pointed by descriptor\n"); + bp->stats.rx_dropped++; + break; + } + skb = bp->rx_skbuff[entry]; + if (unlikely(!skb)) { + netdev_err(bp->dev, + "inconsistent Rx descriptor chain\n"); + bp->stats.rx_dropped++; + break; + } + /* now everything is ready for receiving packet */ + bp->rx_skbuff[entry] = NULL; + len = MACB_BFEXT(RX_FRMLEN, ctrl); + + netdev_vdbg(bp->dev, "gem_rx %u (len %u)\n", entry, len); + + skb_put(skb, len); + addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, addr)); + dma_unmap_single(&bp->pdev->dev, addr, + len, DMA_FROM_DEVICE); + + skb->protocol = eth_type_trans(skb, bp->dev); + skb_checksum_none_assert(skb); + + bp->stats.rx_packets++; + bp->stats.rx_bytes += skb->len; + +#if defined(DEBUG) && defined(VERBOSE_DEBUG) + netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n", + skb->len, skb->csum); + print_hex_dump(KERN_DEBUG, " mac: ", DUMP_PREFIX_ADDRESS, 16, 1, + skb->mac_header, 16, true); + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_ADDRESS, 16, 1, + skb->data, 32, true); +#endif + + netif_receive_skb(skb); + } + + gem_rx_refill(bp); + + return count; +} + static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int last_frag) { @@ -608,27 +756,6 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, return 0; } -/* Mark DMA descriptors from begin up to and not including end as unused */ -static void discard_partial_frame(struct macb *bp, unsigned int begin, - unsigned int end) -{ - unsigned int frag; - - for (frag = begin; frag != end; frag++) { - struct macb_dma_desc *desc = macb_rx_desc(bp, frag); - desc->addr &= ~MACB_BIT(RX_USED); - } - - /* Make descriptor updates visible to hardware */ - wmb(); - - /* - * When this happens, the hardware stats registers for - * whatever caused this is updated, so we don't have to record - * anything. - */ -} - static int macb_rx(struct macb *bp, int budget) { int received = 0; @@ -689,7 +816,7 @@ static int macb_poll(struct napi_struct *napi, int budget) netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n", (unsigned long)status, budget); - work_done = macb_rx(bp, budget); + work_done = bp->macbgem_ops.mog_rx(bp, budget); if (work_done < budget) { napi_complete(napi); @@ -872,29 +999,63 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static void macb_init_rx_buffer_size(struct macb *bp) +static void macb_init_rx_buffer_size(struct macb *bp, size_t size) { if (!macb_is_gem(bp)) { bp->rx_buffer_size = MACB_RX_BUFFER_SIZE; } else { - bp->rx_buffer_size = GEM_RX_BUFFER_SIZE; + bp->rx_buffer_size = size; - if (bp->rx_buffer_size > PAGE_SIZE) { - netdev_warn(bp->dev, - "RX buffer cannot be bigger than PAGE_SIZE, shrinking\n"); - bp->rx_buffer_size = PAGE_SIZE; - } if (bp->rx_buffer_size % RX_BUFFER_MULTIPLE) { - netdev_warn(bp->dev, - "RX buffer must be multiple of %d bytes, shrinking\n", + netdev_dbg(bp->dev, + "RX buffer must be multiple of %d bytes, expanding\n", RX_BUFFER_MULTIPLE); bp->rx_buffer_size = - rounddown(bp->rx_buffer_size, RX_BUFFER_MULTIPLE); + roundup(bp->rx_buffer_size, RX_BUFFER_MULTIPLE); } - bp->rx_buffer_size = max(RX_BUFFER_MULTIPLE, GEM_RX_BUFFER_SIZE); } + + netdev_dbg(bp->dev, "mtu [%u] rx_buffer_size [%Zu]\n", + bp->dev->mtu, bp->rx_buffer_size); } +static void gem_free_rx_buffers(struct macb *bp) +{ + struct sk_buff *skb; + struct macb_dma_desc *desc; + dma_addr_t addr; + int i; + + if (!bp->rx_skbuff) + return; + + for (i = 0; i < RX_RING_SIZE; i++) { + skb = bp->rx_skbuff[i]; + + if (skb == NULL) + continue; + + desc = &bp->rx_ring[i]; + addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr)); + dma_unmap_single(&bp->pdev->dev, addr, skb->len, + DMA_FROM_DEVICE); + dev_kfree_skb_any(skb); + skb = NULL; + } + + kfree(bp->rx_skbuff); + bp->rx_skbuff = NULL; +} + +static void macb_free_rx_buffers(struct macb *bp) +{ + if (bp->rx_buffers) { + dma_free_coherent(&bp->pdev->dev, + RX_RING_SIZE * bp->rx_buffer_size, + bp->rx_buffers, bp->rx_buffers_dma); + bp->rx_buffers = NULL; + } +} static void macb_free_consistent(struct macb *bp) { @@ -902,6 +1063,7 @@ static void macb_free_consistent(struct macb *bp) kfree(bp->tx_skb); bp->tx_skb = NULL; } + bp->macbgem_ops.mog_free_rx_buffers(bp); if (bp->rx_ring) { dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES, bp->rx_ring, bp->rx_ring_dma); @@ -912,12 +1074,37 @@ static void macb_free_consistent(struct macb *bp) bp->tx_ring, bp->tx_ring_dma); bp->tx_ring = NULL; } - if (bp->rx_buffers) { - dma_free_coherent(&bp->pdev->dev, - RX_RING_SIZE * bp->rx_buffer_size, - bp->rx_buffers, bp->rx_buffers_dma); - bp->rx_buffers = NULL; - } +} + +static int gem_alloc_rx_buffers(struct macb *bp) +{ + int size; + + size = RX_RING_SIZE * sizeof(struct sk_buff *); + bp->rx_skbuff = kzalloc(size, GFP_KERNEL); + if (!bp->rx_skbuff) + return -ENOMEM; + else + netdev_dbg(bp->dev, + "Allocated %d RX struct sk_buff entries at %p\n", + RX_RING_SIZE, bp->rx_skbuff); + return 0; +} + +static int macb_alloc_rx_buffers(struct macb *bp) +{ + int size; + + size = RX_RING_SIZE * bp->rx_buffer_size; + bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, + &bp->rx_buffers_dma, GFP_KERNEL); + if (!bp->rx_buffers) + return -ENOMEM; + else + netdev_dbg(bp->dev, + "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); + return 0; } static int macb_alloc_consistent(struct macb *bp) @@ -947,14 +1134,8 @@ static int macb_alloc_consistent(struct macb *bp) "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); - size = RX_RING_SIZE * bp->rx_buffer_size; - bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, - &bp->rx_buffers_dma, GFP_KERNEL); - if (!bp->rx_buffers) + if (bp->macbgem_ops.mog_alloc_rx_buffers(bp)) goto out_err; - netdev_dbg(bp->dev, - "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", - size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); return 0; @@ -963,6 +1144,21 @@ static int macb_alloc_consistent(struct macb *bp) return -ENOMEM; } +static void gem_init_rings(struct macb *bp) +{ + int i; + + for (i = 0; i < TX_RING_SIZE; i++) { + bp->tx_ring[i].addr = 0; + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + } + bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); + + bp->rx_tail = bp->rx_prepared_head = bp->tx_head = bp->tx_tail = 0; + + gem_rx_refill(bp); +} + static void macb_init_rings(struct macb *bp) { int i; @@ -1259,6 +1455,7 @@ EXPORT_SYMBOL_GPL(macb_set_rx_mode); static int macb_open(struct net_device *dev) { struct macb *bp = netdev_priv(dev); + size_t bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN; int err; netdev_dbg(bp->dev, "open\n"); @@ -1271,7 +1468,7 @@ static int macb_open(struct net_device *dev) return -EAGAIN; /* RX buffers initialization */ - macb_init_rx_buffer_size(bp); + macb_init_rx_buffer_size(bp, bufsz); err = macb_alloc_consistent(bp); if (err) { @@ -1282,7 +1479,7 @@ static int macb_open(struct net_device *dev) napi_enable(&bp->napi); - macb_init_rings(bp); + bp->macbgem_ops.mog_init_rings(bp); macb_init_hw(bp); /* schedule a link state check */ @@ -1601,6 +1798,19 @@ static int __init macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; + /* setup appropriated routines according to adapter type */ + if (macb_is_gem(bp)) { + bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers; + bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers; + bp->macbgem_ops.mog_init_rings = gem_init_rings; + bp->macbgem_ops.mog_rx = gem_rx; + } else { + bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers; + bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers; + bp->macbgem_ops.mog_init_rings = macb_init_rings; + bp->macbgem_ops.mog_rx = macb_rx; + } + /* Set MII management clock divider */ config = macb_mdc_clk_div(bp); config |= macb_dbw(bp); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 9b5e19f8b61d..f4076155bed7 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -545,11 +545,22 @@ struct gem_stats { u32 rx_udp_checksum_errors; }; +struct macb; + +struct macb_or_gem_ops { + int (*mog_alloc_rx_buffers)(struct macb *bp); + void (*mog_free_rx_buffers)(struct macb *bp); + void (*mog_init_rings)(struct macb *bp); + int (*mog_rx)(struct macb *bp, int budget); +}; + struct macb { void __iomem *regs; unsigned int rx_tail; + unsigned int rx_prepared_head; struct macb_dma_desc *rx_ring; + struct sk_buff **rx_skbuff; void *rx_buffers; size_t rx_buffer_size; @@ -574,6 +585,8 @@ struct macb { dma_addr_t tx_ring_dma; dma_addr_t rx_buffers_dma; + struct macb_or_gem_ops macbgem_ops; + struct mii_bus *mii_bus; struct phy_device *phy_dev; unsigned int link; -- GitLab From 6c1d7a1c77e98ff53cd58687251c13c5985024ab Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:16:30 +0900 Subject: [PATCH 0705/2900] 88pm860x_battery: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/88pm860x_battery.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c index d338c1c4e8c8..dfcda3a49403 100644 --- a/drivers/power/88pm860x_battery.c +++ b/drivers/power/88pm860x_battery.c @@ -992,7 +992,6 @@ static int pm860x_battery_remove(struct platform_device *pdev) free_irq(info->irq_batt, info); free_irq(info->irq_cc, info); power_supply_unregister(&info->battery); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 71c29b3a89ea49c1f07c85518a9e75bf530673cd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:17:24 +0900 Subject: [PATCH 0706/2900] 88pm860x_charger: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/88pm860x_charger.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c index 36fb4b5a4b0d..ffff66b1c1aa 100644 --- a/drivers/power/88pm860x_charger.c +++ b/drivers/power/88pm860x_charger.c @@ -722,7 +722,6 @@ static int pm860x_charger_remove(struct platform_device *pdev) struct pm860x_charger_info *info = platform_get_drvdata(pdev); int i; - platform_set_drvdata(pdev, NULL); power_supply_unregister(&info->usb); free_irq(info->irq[0], info); for (i = 0; i < info->irq_nums; i++) -- GitLab From ddeeb8f973bbe3bebac78e78c234ff18bfb00bf0 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:20:15 +0900 Subject: [PATCH 0707/2900] ab8500_bm: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Anton Vorontsov --- drivers/power/ab8500_btemp.c | 1 - drivers/power/ab8500_charger.c | 2 -- drivers/power/ab8500_fg.c | 1 - drivers/power/abx500_chargalg.c | 1 - 4 files changed, 5 deletions(-) diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index d412d34bf3df..7f9a4547dccd 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -1045,7 +1045,6 @@ static int ab8500_btemp_remove(struct platform_device *pdev) flush_scheduled_work(); power_supply_unregister(&di->btemp_psy); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index a558318b169c..f098fdafee9f 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c @@ -3425,8 +3425,6 @@ static int ab8500_charger_remove(struct platform_device *pdev) if (di->ac_chg.enabled && !di->ac_chg.external) power_supply_unregister(&di->ac_chg.psy); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index c5391f5c372d..1263638b102d 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -3070,7 +3070,6 @@ static int ab8500_fg_remove(struct platform_device *pdev) flush_scheduled_work(); ab8500_fg_sysfs_psy_remove_attrs(di->fg_psy.dev); power_supply_unregister(&di->fg_psy); - platform_set_drvdata(pdev, NULL); return ret; } diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 9863e423602c..6d2723664a01 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -2035,7 +2035,6 @@ static int abx500_chargalg_remove(struct platform_device *pdev) destroy_workqueue(di->chargalg_wq); power_supply_unregister(&di->chargalg_psy); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 30cf74b94166b2cdeaa8e0439161e339f17e1012 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:21:16 +0900 Subject: [PATCH 0708/2900] bq27x00_battery: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/bq27x00_battery.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 26037ca7efb4..b309713b63bc 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -966,7 +966,6 @@ static int bq27000_battery_probe(struct platform_device *pdev) return 0; err_free: - platform_set_drvdata(pdev, NULL); kfree(di); return ret; @@ -978,7 +977,6 @@ static int bq27000_battery_remove(struct platform_device *pdev) bq27x00_powersupply_unregister(di); - platform_set_drvdata(pdev, NULL); kfree(di); return 0; -- GitLab From 6fe6a40a83716166ac55e7f60053f59563d53878 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:22:00 +0900 Subject: [PATCH 0709/2900] gpio-charger: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/gpio-charger.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index e9883eeeee76..4e858a23568f 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c @@ -155,8 +155,6 @@ static int gpio_charger_remove(struct platform_device *pdev) gpio_free(gpio_charger->pdata->gpio); - platform_set_drvdata(pdev, NULL); - return 0; } -- GitLab From 8ff3fb2902dd5d3c953f907906a413b18d9d150a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:22:41 +0900 Subject: [PATCH 0710/2900] jz4740-battery: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/jz4740-battery.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c index c675553d4647..d9686aa9270a 100644 --- a/drivers/power/jz4740-battery.c +++ b/drivers/power/jz4740-battery.c @@ -292,7 +292,7 @@ static int jz_battery_probe(struct platform_device *pdev) jz_battery); if (ret) { dev_err(&pdev->dev, "Failed to request irq %d\n", ret); - goto err; + return ret; } disable_irq(jz_battery->irq); @@ -349,8 +349,6 @@ static int jz_battery_probe(struct platform_device *pdev) gpio_free(jz_battery->pdata->gpio_charge); err_free_irq: free_irq(jz_battery->irq, jz_battery); -err: - platform_set_drvdata(pdev, NULL); return ret; } -- GitLab From f70d739ada3298fd613d738c0a1c8b10cef63bdf Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:23:45 +0900 Subject: [PATCH 0711/2900] rx51_battery: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/rx51_battery.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c index cbde1d6d3228..8a6288d87056 100644 --- a/drivers/power/rx51_battery.c +++ b/drivers/power/rx51_battery.c @@ -216,10 +216,8 @@ static int rx51_battery_probe(struct platform_device *pdev) di->bat.get_property = rx51_battery_get_property; ret = power_supply_register(di->dev, &di->bat); - if (ret) { - platform_set_drvdata(pdev, NULL); + if (ret) return ret; - } return 0; } @@ -229,7 +227,6 @@ static int rx51_battery_remove(struct platform_device *pdev) struct rx51_device_info *di = platform_get_drvdata(pdev); power_supply_unregister(&di->bat); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 0f1e0169e08e1645a8406ab84286ebaf19c5cce5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:24:33 +0900 Subject: [PATCH 0712/2900] twl4030_charger: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/twl4030_charger.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index bed458172dd2..be98e70380f9 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c @@ -594,7 +594,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) fail_register_usb: power_supply_unregister(&bci->ac); fail_register_ac: - platform_set_drvdata(pdev, NULL); kfree(bci); return ret; @@ -622,7 +621,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) free_irq(bci->irq_chg, bci); power_supply_unregister(&bci->usb); power_supply_unregister(&bci->ac); - platform_set_drvdata(pdev, NULL); kfree(bci); return 0; -- GitLab From 17b4565b308ed31fa20b59842c75e685a101dc8a Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Fri, 10 May 2013 07:17:51 +0000 Subject: [PATCH 0713/2900] lp8727_charger: Support the device tree feature The interrupt and charging parameters are configurable in the device tree structure. In the board test, a GPIO is used for handling LP8727 interrupts. The device tree binding documentation is added also. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Anton Vorontsov --- .../bindings/power_supply/lp8727_charger.txt | 44 ++++++++++++ drivers/power/lp8727_charger.c | 68 +++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 Documentation/devicetree/bindings/power_supply/lp8727_charger.txt diff --git a/Documentation/devicetree/bindings/power_supply/lp8727_charger.txt b/Documentation/devicetree/bindings/power_supply/lp8727_charger.txt new file mode 100644 index 000000000000..2246bc5c874b --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/lp8727_charger.txt @@ -0,0 +1,44 @@ +Binding for TI/National Semiconductor LP8727 Charger + +Required properties: +- compatible: "ti,lp8727" +- reg: I2C slave address 27h + +Optional properties: +- interrupt-parent: interrupt controller node (see interrupt binding[0]) +- interrupts: interrupt specifier (see interrupt binding[0]) +- debounce-ms: interrupt debounce time. (u32) + +AC and USB charging parameters +- charger-type: "ac" or "usb" (string) +- eoc-level: value of 'enum lp8727_eoc_level' (u8) +- charging-current: value of 'enum lp8727_ichg' (u8) + +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt + +Example) + +lp8727@27 { + compatible = "ti,lp8727"; + reg = <0x27>; + + /* GPIO 134 is used for LP8728 interrupt pin */ + interrupt-parent = <&gpio5>; /* base = 128 */ + interrupts = <6 0x2>; /* offset = 6, falling edge type */ + + debounce-ms = <300>; + + /* AC charger: 5% EOC and 500mA charging current */ + ac { + charger-type = "ac"; + eoc-level = /bits/ 8 <0>; + charging-current = /bits/ 8 <4>; + }; + + /* USB charger: 10% EOC and 400mA charging current */ + usb { + charger-type = "usb"; + eoc-level = /bits/ 8 <1>; + charging-current = /bits/ 8 <2>; + }; +}; diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c index 5ef41b819172..32de636dcd73 100644 --- a/drivers/power/lp8727_charger.c +++ b/drivers/power/lp8727_charger.c @@ -16,6 +16,7 @@ #include #include #include +#include #define LP8788_NUM_INTREGS 2 #define DEFAULT_DEBOUNCE_MSEC 270 @@ -481,6 +482,60 @@ static void lp8727_unregister_psy(struct lp8727_chg *pchg) power_supply_unregister(&psy->batt); } +#ifdef CONFIG_OF +static struct lp8727_chg_param +*lp8727_parse_charge_pdata(struct device *dev, struct device_node *np) +{ + struct lp8727_chg_param *param; + + param = devm_kzalloc(dev, sizeof(*param), GFP_KERNEL); + if (!param) + goto out; + + of_property_read_u8(np, "eoc-level", (u8 *)¶m->eoc_level); + of_property_read_u8(np, "charging-current", (u8 *)¶m->ichg); +out: + return param; +} + +static int lp8727_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct device_node *child; + struct lp8727_platform_data *pdata; + const char *type; + + /* If charging parameter is not defined, just skip parsing the dt */ + if (of_get_child_count(np) == 0) + goto out; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec); + + for_each_child_of_node(np, child) { + of_property_read_string(child, "charger-type", &type); + + if (!strcmp(type, "ac")) + pdata->ac = lp8727_parse_charge_pdata(dev, child); + + if (!strcmp(type, "usb")) + pdata->usb = lp8727_parse_charge_pdata(dev, child); + } + + dev->platform_data = pdata; +out: + return 0; +} +#else +static int lp8727_parse_dt(struct device *dev) +{ + return 0; +} +#endif + static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) { struct lp8727_chg *pchg; @@ -489,6 +544,12 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -EIO; + if (cl->dev.of_node) { + ret = lp8727_parse_dt(&cl->dev); + if (ret) + return ret; + } + pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL); if (!pchg) return -ENOMEM; @@ -531,6 +592,12 @@ static int lp8727_remove(struct i2c_client *cl) return 0; } +static const struct of_device_id lp8727_dt_ids[] = { + { .compatible = "ti,lp8727", }, + { } +}; +MODULE_DEVICE_TABLE(of, lp8727_dt_ids); + static const struct i2c_device_id lp8727_ids[] = { {"lp8727", 0}, { } @@ -540,6 +607,7 @@ MODULE_DEVICE_TABLE(i2c, lp8727_ids); static struct i2c_driver lp8727_driver = { .driver = { .name = "lp8727", + .of_match_table = of_match_ptr(lp8727_dt_ids), }, .probe = lp8727_probe, .remove = lp8727_remove, -- GitLab From df311333a8c13f3ffe2537a4ff507887208cb863 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 16 May 2013 17:31:00 +0800 Subject: [PATCH 0714/2900] pm2301_charger: Fix NULL pointer dereference Add checking pl_data in probe, this prevent possible NULL pointer dereference. Also fix NULL pointer deference in dev_err when allocate memory for pm2 fails. Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Anton Vorontsov --- drivers/power/pm2301_charger.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index fef56e2041b3..bb346becd7b4 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c @@ -1007,9 +1007,14 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, u8 val; int i; + if (!pl_data) { + dev_err(&i2c_client->dev, "No platform data supplied\n"); + return -EINVAL; + } + pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); if (!pm2) { - dev_err(pm2->dev, "pm2xxx_charger allocation failed\n"); + dev_err(&i2c_client->dev, "pm2xxx_charger allocation failed\n"); return -ENOMEM; } -- GitLab From c509a62c9469e2787bcacc7aba454d555732b0b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 16 May 2013 21:17:04 +0800 Subject: [PATCH 0715/2900] pm2301_charger: Return error if create_singlethread_workqueue fails Return error instead of 0 if create_singlethread_workqueue call fails. Signed-off-by: Axel Lin Acked-by: Linus Walleij Signed-off-by: Anton Vorontsov --- drivers/power/pm2301_charger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index bb346becd7b4..1c0bfcbae062 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c @@ -1075,9 +1075,9 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, pm2->ac_chg.external = true; /* Create a work queue for the charger */ - pm2->charger_wq = - create_singlethread_workqueue("pm2xxx_charger_wq"); + pm2->charger_wq = create_singlethread_workqueue("pm2xxx_charger_wq"); if (pm2->charger_wq == NULL) { + ret = -ENOMEM; dev_err(pm2->dev, "failed to create work queue\n"); goto free_device_info; } -- GitLab From e08358792422ef0b78d7c81f333fc0803fb41cd4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:34:39 +0900 Subject: [PATCH 0716/2900] power: Use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Signed-off-by: Anton Vorontsov --- drivers/power/intel_mid_battery.c | 2 +- drivers/power/tps65090-charger.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index 18d136b443ee..4520811168ad 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -756,7 +756,7 @@ static int platform_pmic_battery_probe(struct platform_device *pdev) static int platform_pmic_battery_remove(struct platform_device *pdev) { - struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev); + struct pmic_power_module_info *pbi = platform_get_drvdata(pdev); free_irq(pbi->irq, pbi); cancel_delayed_work_sync(&pbi->monitor_battery); diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index 9fbca310a2ad..77ab8561fa34 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c @@ -218,7 +218,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) return -ENOMEM; } - dev_set_drvdata(&pdev->dev, cdata); + platform_set_drvdata(pdev, cdata); cdata->dev = &pdev->dev; cdata->pdata = pdata; @@ -291,7 +291,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) static int tps65090_charger_remove(struct platform_device *pdev) { - struct tps65090_charger *cdata = dev_get_drvdata(&pdev->dev); + struct tps65090_charger *cdata = platform_get_drvdata(pdev); devm_free_irq(cdata->dev, cdata->irq, cdata); power_supply_unregister(&cdata->ac); -- GitLab From d211c6e82435dfa4ae9f4d80bb2ee75930bde5d4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 25 May 2013 01:41:44 +0800 Subject: [PATCH 0717/2900] generic-adc-battery: Fix checking if none of the channels are supported If none of the channels are supported, index is 0. Also ensure to return error code instead of 0 in goto second_mem_fail path. Signed-off-by: Axel Lin Acked-by: anish kumar Signed-off-by: Anton Vorontsov --- drivers/power/generic-adc-battery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c index 8cb5d7f67ace..59a1421f9288 100644 --- a/drivers/power/generic-adc-battery.c +++ b/drivers/power/generic-adc-battery.c @@ -299,8 +299,10 @@ static int gab_probe(struct platform_device *pdev) } /* none of the channels are supported so let's bail out */ - if (index == ARRAY_SIZE(gab_chan_name)) + if (index == 0) { + ret = -ENODEV; goto second_mem_fail; + } /* * Total number of properties is equal to static properties -- GitLab From 4b43eb67ae246b9a846c46e5ff96ea0212ae7a51 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 3 Jun 2013 18:05:05 +0900 Subject: [PATCH 0718/2900] power_supply: Replace strict_strtoul() with kstrtoul() The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Reviewed-by: Andy Shevchenko Signed-off-by: Anton Vorontsov --- drivers/power/ab8500_fg.c | 6 +++--- drivers/power/pcf50633-charger.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 1263638b102d..754970717c31 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -2465,9 +2465,9 @@ static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf, size_t count) { unsigned long charge_full; - ssize_t ret = -EINVAL; + ssize_t ret; - ret = strict_strtoul(buf, 10, &charge_full); + ret = kstrtoul(buf, 10, &charge_full); dev_dbg(di->dev, "Ret %zd charge_full %lu", ret, charge_full); @@ -2489,7 +2489,7 @@ static ssize_t charge_now_store(struct ab8500_fg *di, const char *buf, unsigned long charge_now; ssize_t ret; - ret = strict_strtoul(buf, 10, &charge_now); + ret = kstrtoul(buf, 10, &charge_now); dev_dbg(di->dev, "Ret %zd charge_now %lu was %d", ret, charge_now, di->bat_cap.prev_mah); diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 17fd77f24b2a..771c4f0fb8ac 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c @@ -191,9 +191,9 @@ static ssize_t set_usblim(struct device *dev, unsigned long ma; int ret; - ret = strict_strtoul(buf, 10, &ma); + ret = kstrtoul(buf, 10, &ma); if (ret) - return -EINVAL; + return ret; pcf50633_mbc_usb_curlim_set(mbc->pcf, ma); @@ -228,9 +228,9 @@ static ssize_t set_chglim(struct device *dev, if (!mbc->pcf->pdata->charger_reference_current_ma) return -ENODEV; - ret = strict_strtoul(buf, 10, &ma); + ret = kstrtoul(buf, 10, &ma); if (ret) - return -EINVAL; + return ret; mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; if (mbcc5 > 255) -- GitLab From 3594f4c0d7bc51e3a7e6d73c44e368ae079e42f3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 6 Jun 2013 13:52:21 -0700 Subject: [PATCH 0719/2900] charger-manager: Ensure event is not used as format string The exposed interface for cm_notify_event() could result in the event msg string being parsed as a format string. Make sure it is only used as a literal string. Signed-off-by: Kees Cook Cc: stable@vger.kernel.org Cc: Anton Vorontsov Cc: David Woodhouse Signed-off-by: Anton Vorontsov --- drivers/power/charger-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index fefc39fe42be..98de1ddce458 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -450,7 +450,7 @@ static void uevent_notify(struct charger_manager *cm, const char *event) strncpy(env_str, event, UEVENT_BUF_SIZE); kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE); - dev_info(cm->dev, event); + dev_info(cm->dev, "%s", event); } /** -- GitLab From d70a3f887a38cb0acc7233a1d05f15c2b6e0be2b Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 6 Jun 2013 14:08:13 +0000 Subject: [PATCH 0720/2900] doc: packet: simplify tpacket example code This patch simplifies the tpacket_v3 example code a bit by getting rid of unecessary macro wrappers, removing some debugging code so that it is more to the point, and also adds a header comment. Now this example code is the very minimum one needs to start from when dealing with tpacket_v3 and ~100 lines smaller than before. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- Documentation/networking/packet_mmap.txt | 133 +++++------------------ 1 file changed, 28 insertions(+), 105 deletions(-) diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 23dd80e82b8e..8572796b1eb6 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -704,6 +704,12 @@ So it seems to be a good candidate to be used with packet fanout. Minimal example code by Daniel Borkmann based on Chetan Loke's lolpcap (compile it with gcc -Wall -O2 blob.c, and try things like "./a.out eth0", etc.): +/* Written from scratch, but kernel-to-user space API usage + * dissected from lolpcap: + * Copyright 2011, Chetan Loke + * License: GPL, version 2.0 + */ + #include #include #include @@ -722,27 +728,6 @@ it with gcc -Wall -O2 blob.c, and try things like "./a.out eth0", etc.): #include #include -#define BLOCK_SIZE (1 << 22) -#define FRAME_SIZE 2048 - -#define NUM_BLOCKS 64 -#define NUM_FRAMES ((BLOCK_SIZE * NUM_BLOCKS) / FRAME_SIZE) - -#define BLOCK_RETIRE_TOV_IN_MS 64 -#define BLOCK_PRIV_AREA_SZ 13 - -#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) - -#define BLOCK_STATUS(x) ((x)->h1.block_status) -#define BLOCK_NUM_PKTS(x) ((x)->h1.num_pkts) -#define BLOCK_O2FP(x) ((x)->h1.offset_to_first_pkt) -#define BLOCK_LEN(x) ((x)->h1.blk_len) -#define BLOCK_SNUM(x) ((x)->h1.seq_num) -#define BLOCK_O2PRIV(x) ((x)->offset_to_priv) -#define BLOCK_PRIV(x) ((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x))) -#define BLOCK_HDR_LEN (ALIGN_8(sizeof(struct block_desc))) -#define BLOCK_PLUS_PRIV(sz_pri) (BLOCK_HDR_LEN + ALIGN_8((sz_pri))) - #ifndef likely # define likely(x) __builtin_expect(!!(x), 1) #endif @@ -765,7 +750,7 @@ struct ring { static unsigned long packets_total = 0, bytes_total = 0; static sig_atomic_t sigint = 0; -void sighandler(int num) +static void sighandler(int num) { sigint = 1; } @@ -774,6 +759,8 @@ static int setup_socket(struct ring *ring, char *netdev) { int err, i, fd, v = TPACKET_V3; struct sockaddr_ll ll; + unsigned int blocksiz = 1 << 22, framesiz = 1 << 11; + unsigned int blocknum = 64; fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (fd < 0) { @@ -788,13 +775,12 @@ static int setup_socket(struct ring *ring, char *netdev) } memset(&ring->req, 0, sizeof(ring->req)); - ring->req.tp_block_size = BLOCK_SIZE; - ring->req.tp_frame_size = FRAME_SIZE; - ring->req.tp_block_nr = NUM_BLOCKS; - ring->req.tp_frame_nr = NUM_FRAMES; - ring->req.tp_retire_blk_tov = BLOCK_RETIRE_TOV_IN_MS; - ring->req.tp_sizeof_priv = BLOCK_PRIV_AREA_SZ; - ring->req.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH; + ring->req.tp_block_size = blocksiz; + ring->req.tp_frame_size = framesiz; + ring->req.tp_block_nr = blocknum; + ring->req.tp_frame_nr = (blocksiz * blocknum) / framesiz; + ring->req.tp_retire_blk_tov = 60; + ring->req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; err = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &ring->req, sizeof(ring->req)); @@ -804,8 +790,7 @@ static int setup_socket(struct ring *ring, char *netdev) } ring->map = mmap(NULL, ring->req.tp_block_size * ring->req.tp_block_nr, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, - fd, 0); + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); if (ring->map == MAP_FAILED) { perror("mmap"); exit(1); @@ -835,58 +820,6 @@ static int setup_socket(struct ring *ring, char *netdev) return fd; } -#ifdef __checked -static uint64_t prev_block_seq_num = 0; - -void assert_block_seq_num(struct block_desc *pbd) -{ - if (unlikely(prev_block_seq_num + 1 != BLOCK_SNUM(pbd))) { - printf("prev_block_seq_num:%"PRIu64", expected seq:%"PRIu64" != " - "actual seq:%"PRIu64"\n", prev_block_seq_num, - prev_block_seq_num + 1, (uint64_t) BLOCK_SNUM(pbd)); - exit(1); - } - - prev_block_seq_num = BLOCK_SNUM(pbd); -} - -static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) -{ - if (BLOCK_NUM_PKTS(pbd)) { - if (unlikely(bytes != BLOCK_LEN(pbd))) { - printf("block:%u with %upackets, expected len:%u != actual len:%u\n", - block_num, BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd)); - exit(1); - } - } else { - if (unlikely(BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ))) { - printf("block:%u, expected len:%lu != actual len:%u\n", - block_num, BLOCK_HDR_LEN, BLOCK_LEN(pbd)); - exit(1); - } - } -} - -static void assert_block_header(struct block_desc *pbd, const int block_num) -{ - uint32_t block_status = BLOCK_STATUS(pbd); - - if (unlikely((block_status & TP_STATUS_USER) == 0)) { - printf("block:%u, not in TP_STATUS_USER\n", block_num); - exit(1); - } - - assert_block_seq_num(pbd); -} -#else -static inline void assert_block_header(struct block_desc *pbd, const int block_num) -{ -} -static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) -{ -} -#endif - static void display(struct tpacket3_hdr *ppd) { struct ethhdr *eth = (struct ethhdr *) ((uint8_t *) ppd + ppd->tp_mac); @@ -916,37 +849,27 @@ static void display(struct tpacket3_hdr *ppd) static void walk_block(struct block_desc *pbd, const int block_num) { - int num_pkts = BLOCK_NUM_PKTS(pbd), i; + int num_pkts = pbd->h1.num_pkts, i; unsigned long bytes = 0; - unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ); struct tpacket3_hdr *ppd; - assert_block_header(pbd, block_num); - - ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd)); + ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + + pbd->h1.offset_to_first_pkt); for (i = 0; i < num_pkts; ++i) { bytes += ppd->tp_snaplen; - if (ppd->tp_next_offset) - bytes_with_padding += ppd->tp_next_offset; - else - bytes_with_padding += ALIGN_8(ppd->tp_snaplen + ppd->tp_mac); - display(ppd); - ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + ppd->tp_next_offset); - __sync_synchronize(); + ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + + ppd->tp_next_offset); } - assert_block_len(pbd, bytes_with_padding, block_num); - packets_total += num_pkts; bytes_total += bytes; } -void flush_block(struct block_desc *pbd) +static void flush_block(struct block_desc *pbd) { - BLOCK_STATUS(pbd) = TP_STATUS_KERNEL; - __sync_synchronize(); + pbd->h1.block_status = TP_STATUS_KERNEL; } static void teardown_socket(struct ring *ring, int fd) @@ -962,7 +885,7 @@ int main(int argc, char **argp) socklen_t len; struct ring ring; struct pollfd pfd; - unsigned int block_num = 0; + unsigned int block_num = 0, blocks = 64; struct block_desc *pbd; struct tpacket_stats_v3 stats; @@ -984,15 +907,15 @@ int main(int argc, char **argp) while (likely(!sigint)) { pbd = (struct block_desc *) ring.rd[block_num].iov_base; -retry_block: - if ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) { + + if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { poll(&pfd, 1, -1); - goto retry_block; + continue; } walk_block(pbd, block_num); flush_block(pbd); - block_num = (block_num + 1) % NUM_BLOCKS; + block_num = (block_num + 1) % blocks; } len = sizeof(stats); -- GitLab From 350e7805706e11fef0bda2ab4b5cd5a0881480b9 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 6 Jun 2013 14:08:31 +0000 Subject: [PATCH 0721/2900] net: vlan: minor: remove unused HAVE_VLAN_PUT_TAG Remove the definition of HAVE_VLAN_PUT_TAG since it's not used or exported anywhere. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 52bd03b38962..7a9c8cf31659 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -243,8 +243,6 @@ static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, return skb; } -#define HAVE_VLAN_PUT_TAG - /** * vlan_put_tag - inserts VLAN tag according to device features * @skb: skbuff to tag -- GitLab From 5ee98591577aa63dbb9e78a0d142abc86b9063d0 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 7 Jun 2013 05:11:45 +0000 Subject: [PATCH 0722/2900] net: minor: tcp: use tcp_skb_mss helper in tcp_tso_segment We have the minimal inline helper tcp_skb_mss to access skb_shinfo(skb)->gso_size, so also use it here to get mss. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b5d4ad988053..6a1cf95abc98 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2905,7 +2905,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, oldlen = (u16)~skb->len; __skb_pull(skb, thlen); - mss = skb_shinfo(skb)->gso_size; + mss = tcp_skb_mss(skb); if (unlikely(skb->len <= mss)) goto out; @@ -3071,7 +3071,7 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) flush |= *(u32 *)((u8 *)th + i) ^ *(u32 *)((u8 *)th2 + i); - mss = skb_shinfo(p)->gso_size; + mss = tcp_skb_mss(p); flush |= (len - 1) >= mss; flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); -- GitLab From 28850dc7c71da9d0c0e39246e9ff6913f41f8d0a Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 7 Jun 2013 05:11:46 +0000 Subject: [PATCH 0723/2900] net: tcp: move GRO/GSO functions to tcp_offload Would be good to make things explicit and move those functions to a new file called tcp_offload.c, thus make this similar to tcpv6_offload.c. While moving all related functions into tcp_offload.c, we can also make some of them static, since they are only used there. Also, add an explicit registration function. Suggested-by: Eric Dumazet Signed-off-by: Daniel Borkmann Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 9 +- net/ipv4/Makefile | 2 +- net/ipv4/af_inet.c | 13 +- net/ipv4/tcp.c | 241 ------------------------------ net/ipv4/tcp_ipv4.c | 66 +------- net/ipv4/tcp_offload.c | 332 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 341 insertions(+), 322 deletions(-) create mode 100644 net/ipv4/tcp_offload.c diff --git a/include/net/tcp.h b/include/net/tcp.h index bf1cc3dced5e..0d637e9403a5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1541,15 +1541,14 @@ extern struct request_sock_ops tcp6_request_sock_ops; extern void tcp_v4_destroy_sock(struct sock *sk); -extern int tcp_v4_gso_send_check(struct sk_buff *skb); extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, netdev_features_t features); extern struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb); -extern struct sk_buff **tcp4_gro_receive(struct sk_buff **head, - struct sk_buff *skb); extern int tcp_gro_complete(struct sk_buff *skb); -extern int tcp4_gro_complete(struct sk_buff *skb); + +extern void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, + __be32 daddr); #ifdef CONFIG_PROC_FS extern int tcp4_proc_init(void); @@ -1584,6 +1583,8 @@ struct tcp_request_sock_ops { #endif }; +extern int tcpv4_offload_init(void); + extern void tcp_v4_init(void); extern void tcp_init(void); diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 089cb9f36387..4d3e138c564f 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -8,7 +8,7 @@ obj-y := route.o inetpeer.o protocol.o \ inet_timewait_sock.o inet_connection_sock.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \ - datagram.o raw.o udp.o udplite.o \ + tcp_offload.o datagram.o raw.o udp.o udplite.o \ arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o \ inet_fragment.o ping.o diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 9c090c7daea1..7b514290efc6 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1559,15 +1559,6 @@ static const struct net_protocol tcp_protocol = { .netns_ok = 1, }; -static const struct net_offload tcp_offload = { - .callbacks = { - .gso_send_check = tcp_v4_gso_send_check, - .gso_segment = tcp_tso_segment, - .gro_receive = tcp4_gro_receive, - .gro_complete = tcp4_gro_complete, - }, -}; - static const struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, @@ -1683,8 +1674,8 @@ static int __init ipv4_offload_init(void) */ if (inet_add_offload(&udp_offload, IPPROTO_UDP) < 0) pr_crit("%s: Cannot add UDP protocol offload\n", __func__); - if (inet_add_offload(&tcp_offload, IPPROTO_TCP) < 0) - pr_crit("%s: Cannot add TCP protocol offlaod\n", __func__); + if (tcpv4_offload_init() < 0) + pr_crit("%s: Cannot add TCP protocol offload\n", __func__); dev_add_offload(&ip_packet_offload); return 0; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 6a1cf95abc98..bc4246940f6c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2877,247 +2877,6 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_tcp_getsockopt); #endif -struct sk_buff *tcp_tso_segment(struct sk_buff *skb, - netdev_features_t features) -{ - struct sk_buff *segs = ERR_PTR(-EINVAL); - struct tcphdr *th; - unsigned int thlen; - unsigned int seq; - __be32 delta; - unsigned int oldlen; - unsigned int mss; - struct sk_buff *gso_skb = skb; - __sum16 newcheck; - bool ooo_okay, copy_destructor; - - if (!pskb_may_pull(skb, sizeof(*th))) - goto out; - - th = tcp_hdr(skb); - thlen = th->doff * 4; - if (thlen < sizeof(*th)) - goto out; - - if (!pskb_may_pull(skb, thlen)) - goto out; - - oldlen = (u16)~skb->len; - __skb_pull(skb, thlen); - - mss = tcp_skb_mss(skb); - if (unlikely(skb->len <= mss)) - goto out; - - if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { - /* Packet is from an untrusted source, reset gso_segs. */ - int type = skb_shinfo(skb)->gso_type; - - if (unlikely(type & - ~(SKB_GSO_TCPV4 | - SKB_GSO_DODGY | - SKB_GSO_TCP_ECN | - SKB_GSO_TCPV6 | - SKB_GSO_GRE | - SKB_GSO_MPLS | - SKB_GSO_UDP_TUNNEL | - 0) || - !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) - goto out; - - skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); - - segs = NULL; - goto out; - } - - copy_destructor = gso_skb->destructor == tcp_wfree; - ooo_okay = gso_skb->ooo_okay; - /* All segments but the first should have ooo_okay cleared */ - skb->ooo_okay = 0; - - segs = skb_segment(skb, features); - if (IS_ERR(segs)) - goto out; - - /* Only first segment might have ooo_okay set */ - segs->ooo_okay = ooo_okay; - - delta = htonl(oldlen + (thlen + mss)); - - skb = segs; - th = tcp_hdr(skb); - seq = ntohl(th->seq); - - newcheck = ~csum_fold((__force __wsum)((__force u32)th->check + - (__force u32)delta)); - - do { - th->fin = th->psh = 0; - th->check = newcheck; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - th->check = - csum_fold(csum_partial(skb_transport_header(skb), - thlen, skb->csum)); - - seq += mss; - if (copy_destructor) { - skb->destructor = gso_skb->destructor; - skb->sk = gso_skb->sk; - /* {tcp|sock}_wfree() use exact truesize accounting : - * sum(skb->truesize) MUST be exactly be gso_skb->truesize - * So we account mss bytes of 'true size' for each segment. - * The last segment will contain the remaining. - */ - skb->truesize = mss; - gso_skb->truesize -= mss; - } - skb = skb->next; - th = tcp_hdr(skb); - - th->seq = htonl(seq); - th->cwr = 0; - } while (skb->next); - - /* Following permits TCP Small Queues to work well with GSO : - * The callback to TCP stack will be called at the time last frag - * is freed at TX completion, and not right now when gso_skb - * is freed by GSO engine - */ - if (copy_destructor) { - swap(gso_skb->sk, skb->sk); - swap(gso_skb->destructor, skb->destructor); - swap(gso_skb->truesize, skb->truesize); - } - - delta = htonl(oldlen + (skb_tail_pointer(skb) - - skb_transport_header(skb)) + - skb->data_len); - th->check = ~csum_fold((__force __wsum)((__force u32)th->check + - (__force u32)delta)); - if (skb->ip_summed != CHECKSUM_PARTIAL) - th->check = csum_fold(csum_partial(skb_transport_header(skb), - thlen, skb->csum)); - -out: - return segs; -} -EXPORT_SYMBOL(tcp_tso_segment); - -struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) -{ - struct sk_buff **pp = NULL; - struct sk_buff *p; - struct tcphdr *th; - struct tcphdr *th2; - unsigned int len; - unsigned int thlen; - __be32 flags; - unsigned int mss = 1; - unsigned int hlen; - unsigned int off; - int flush = 1; - int i; - - off = skb_gro_offset(skb); - hlen = off + sizeof(*th); - th = skb_gro_header_fast(skb, off); - if (skb_gro_header_hard(skb, hlen)) { - th = skb_gro_header_slow(skb, hlen, off); - if (unlikely(!th)) - goto out; - } - - thlen = th->doff * 4; - if (thlen < sizeof(*th)) - goto out; - - hlen = off + thlen; - if (skb_gro_header_hard(skb, hlen)) { - th = skb_gro_header_slow(skb, hlen, off); - if (unlikely(!th)) - goto out; - } - - skb_gro_pull(skb, thlen); - - len = skb_gro_len(skb); - flags = tcp_flag_word(th); - - for (; (p = *head); head = &p->next) { - if (!NAPI_GRO_CB(p)->same_flow) - continue; - - th2 = tcp_hdr(p); - - if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { - NAPI_GRO_CB(p)->same_flow = 0; - continue; - } - - goto found; - } - - goto out_check_final; - -found: - flush = NAPI_GRO_CB(p)->flush; - flush |= (__force int)(flags & TCP_FLAG_CWR); - flush |= (__force int)((flags ^ tcp_flag_word(th2)) & - ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); - flush |= (__force int)(th->ack_seq ^ th2->ack_seq); - for (i = sizeof(*th); i < thlen; i += 4) - flush |= *(u32 *)((u8 *)th + i) ^ - *(u32 *)((u8 *)th2 + i); - - mss = tcp_skb_mss(p); - - flush |= (len - 1) >= mss; - flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); - - if (flush || skb_gro_receive(head, skb)) { - mss = 1; - goto out_check_final; - } - - p = *head; - th2 = tcp_hdr(p); - tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); - -out_check_final: - flush = len < mss; - flush |= (__force int)(flags & (TCP_FLAG_URG | TCP_FLAG_PSH | - TCP_FLAG_RST | TCP_FLAG_SYN | - TCP_FLAG_FIN)); - - if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) - pp = head; - -out: - NAPI_GRO_CB(skb)->flush |= flush; - - return pp; -} -EXPORT_SYMBOL(tcp_gro_receive); - -int tcp_gro_complete(struct sk_buff *skb) -{ - struct tcphdr *th = tcp_hdr(skb); - - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct tcphdr, check); - skb->ip_summed = CHECKSUM_PARTIAL; - - skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count; - - if (th->cwr) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - return 0; -} -EXPORT_SYMBOL(tcp_gro_complete); - #ifdef CONFIG_TCP_MD5SIG static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly; static DEFINE_MUTEX(tcp_md5sig_mutex); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index d20ede0c9593..289039b4d8de 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -545,8 +545,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) sock_put(sk); } -static void __tcp_v4_send_check(struct sk_buff *skb, - __be32 saddr, __be32 daddr) +void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr) { struct tcphdr *th = tcp_hdr(skb); @@ -571,23 +570,6 @@ void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(tcp_v4_send_check); -int tcp_v4_gso_send_check(struct sk_buff *skb) -{ - const struct iphdr *iph; - struct tcphdr *th; - - if (!pskb_may_pull(skb, sizeof(*th))) - return -EINVAL; - - iph = ip_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - skb->ip_summed = CHECKSUM_PARTIAL; - __tcp_v4_send_check(skb, iph->saddr, iph->daddr); - return 0; -} - /* * This routine will send an RST to the other tcp. * @@ -2795,52 +2777,6 @@ void tcp4_proc_exit(void) } #endif /* CONFIG_PROC_FS */ -struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) -{ - const struct iphdr *iph = skb_gro_network_header(skb); - __wsum wsum; - __sum16 sum; - - switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: - if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, - skb->csum)) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - } -flush: - NAPI_GRO_CB(skb)->flush = 1; - return NULL; - - case CHECKSUM_NONE: - wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, - skb_gro_len(skb), IPPROTO_TCP, 0); - sum = csum_fold(skb_checksum(skb, - skb_gro_offset(skb), - skb_gro_len(skb), - wsum)); - if (sum) - goto flush; - - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - } - - return tcp_gro_receive(head, skb); -} - -int tcp4_gro_complete(struct sk_buff *skb) -{ - const struct iphdr *iph = ip_hdr(skb); - struct tcphdr *th = tcp_hdr(skb); - - th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), - iph->saddr, iph->daddr, 0); - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - - return tcp_gro_complete(skb); -} - struct proto tcp_prot = { .name = "TCP", .owner = THIS_MODULE, diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c new file mode 100644 index 000000000000..3a7525e6c086 --- /dev/null +++ b/net/ipv4/tcp_offload.c @@ -0,0 +1,332 @@ +/* + * IPV4 GSO/GRO offload support + * Linux INET implementation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TCPv4 GSO/GRO support + */ + +#include +#include +#include + +struct sk_buff *tcp_tso_segment(struct sk_buff *skb, + netdev_features_t features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + struct tcphdr *th; + unsigned int thlen; + unsigned int seq; + __be32 delta; + unsigned int oldlen; + unsigned int mss; + struct sk_buff *gso_skb = skb; + __sum16 newcheck; + bool ooo_okay, copy_destructor; + + if (!pskb_may_pull(skb, sizeof(*th))) + goto out; + + th = tcp_hdr(skb); + thlen = th->doff * 4; + if (thlen < sizeof(*th)) + goto out; + + if (!pskb_may_pull(skb, thlen)) + goto out; + + oldlen = (u16)~skb->len; + __skb_pull(skb, thlen); + + mss = tcp_skb_mss(skb); + if (unlikely(skb->len <= mss)) + goto out; + + if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { + /* Packet is from an untrusted source, reset gso_segs. */ + int type = skb_shinfo(skb)->gso_type; + + if (unlikely(type & + ~(SKB_GSO_TCPV4 | + SKB_GSO_DODGY | + SKB_GSO_TCP_ECN | + SKB_GSO_TCPV6 | + SKB_GSO_GRE | + SKB_GSO_MPLS | + SKB_GSO_UDP_TUNNEL | + 0) || + !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) + goto out; + + skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); + + segs = NULL; + goto out; + } + + copy_destructor = gso_skb->destructor == tcp_wfree; + ooo_okay = gso_skb->ooo_okay; + /* All segments but the first should have ooo_okay cleared */ + skb->ooo_okay = 0; + + segs = skb_segment(skb, features); + if (IS_ERR(segs)) + goto out; + + /* Only first segment might have ooo_okay set */ + segs->ooo_okay = ooo_okay; + + delta = htonl(oldlen + (thlen + mss)); + + skb = segs; + th = tcp_hdr(skb); + seq = ntohl(th->seq); + + newcheck = ~csum_fold((__force __wsum)((__force u32)th->check + + (__force u32)delta)); + + do { + th->fin = th->psh = 0; + th->check = newcheck; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + th->check = + csum_fold(csum_partial(skb_transport_header(skb), + thlen, skb->csum)); + + seq += mss; + if (copy_destructor) { + skb->destructor = gso_skb->destructor; + skb->sk = gso_skb->sk; + /* {tcp|sock}_wfree() use exact truesize accounting : + * sum(skb->truesize) MUST be exactly be gso_skb->truesize + * So we account mss bytes of 'true size' for each segment. + * The last segment will contain the remaining. + */ + skb->truesize = mss; + gso_skb->truesize -= mss; + } + skb = skb->next; + th = tcp_hdr(skb); + + th->seq = htonl(seq); + th->cwr = 0; + } while (skb->next); + + /* Following permits TCP Small Queues to work well with GSO : + * The callback to TCP stack will be called at the time last frag + * is freed at TX completion, and not right now when gso_skb + * is freed by GSO engine + */ + if (copy_destructor) { + swap(gso_skb->sk, skb->sk); + swap(gso_skb->destructor, skb->destructor); + swap(gso_skb->truesize, skb->truesize); + } + + delta = htonl(oldlen + (skb_tail_pointer(skb) - + skb_transport_header(skb)) + + skb->data_len); + th->check = ~csum_fold((__force __wsum)((__force u32)th->check + + (__force u32)delta)); + if (skb->ip_summed != CHECKSUM_PARTIAL) + th->check = csum_fold(csum_partial(skb_transport_header(skb), + thlen, skb->csum)); +out: + return segs; +} +EXPORT_SYMBOL(tcp_tso_segment); + +struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb) +{ + struct sk_buff **pp = NULL; + struct sk_buff *p; + struct tcphdr *th; + struct tcphdr *th2; + unsigned int len; + unsigned int thlen; + __be32 flags; + unsigned int mss = 1; + unsigned int hlen; + unsigned int off; + int flush = 1; + int i; + + off = skb_gro_offset(skb); + hlen = off + sizeof(*th); + th = skb_gro_header_fast(skb, off); + if (skb_gro_header_hard(skb, hlen)) { + th = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!th)) + goto out; + } + + thlen = th->doff * 4; + if (thlen < sizeof(*th)) + goto out; + + hlen = off + thlen; + if (skb_gro_header_hard(skb, hlen)) { + th = skb_gro_header_slow(skb, hlen, off); + if (unlikely(!th)) + goto out; + } + + skb_gro_pull(skb, thlen); + + len = skb_gro_len(skb); + flags = tcp_flag_word(th); + + for (; (p = *head); head = &p->next) { + if (!NAPI_GRO_CB(p)->same_flow) + continue; + + th2 = tcp_hdr(p); + + if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { + NAPI_GRO_CB(p)->same_flow = 0; + continue; + } + + goto found; + } + + goto out_check_final; + +found: + flush = NAPI_GRO_CB(p)->flush; + flush |= (__force int)(flags & TCP_FLAG_CWR); + flush |= (__force int)((flags ^ tcp_flag_word(th2)) & + ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); + flush |= (__force int)(th->ack_seq ^ th2->ack_seq); + for (i = sizeof(*th); i < thlen; i += 4) + flush |= *(u32 *)((u8 *)th + i) ^ + *(u32 *)((u8 *)th2 + i); + + mss = tcp_skb_mss(p); + + flush |= (len - 1) >= mss; + flush |= (ntohl(th2->seq) + skb_gro_len(p)) ^ ntohl(th->seq); + + if (flush || skb_gro_receive(head, skb)) { + mss = 1; + goto out_check_final; + } + + p = *head; + th2 = tcp_hdr(p); + tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); + +out_check_final: + flush = len < mss; + flush |= (__force int)(flags & (TCP_FLAG_URG | TCP_FLAG_PSH | + TCP_FLAG_RST | TCP_FLAG_SYN | + TCP_FLAG_FIN)); + + if (p && (!NAPI_GRO_CB(skb)->same_flow || flush)) + pp = head; + +out: + NAPI_GRO_CB(skb)->flush |= flush; + + return pp; +} +EXPORT_SYMBOL(tcp_gro_receive); + +int tcp_gro_complete(struct sk_buff *skb) +{ + struct tcphdr *th = tcp_hdr(skb); + + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct tcphdr, check); + skb->ip_summed = CHECKSUM_PARTIAL; + + skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count; + + if (th->cwr) + skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; + + return 0; +} +EXPORT_SYMBOL(tcp_gro_complete); + +static int tcp_v4_gso_send_check(struct sk_buff *skb) +{ + const struct iphdr *iph; + struct tcphdr *th; + + if (!pskb_may_pull(skb, sizeof(*th))) + return -EINVAL; + + iph = ip_hdr(skb); + th = tcp_hdr(skb); + + th->check = 0; + skb->ip_summed = CHECKSUM_PARTIAL; + __tcp_v4_send_check(skb, iph->saddr, iph->daddr); + return 0; +} + +static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) +{ + const struct iphdr *iph = skb_gro_network_header(skb); + __wsum wsum; + __sum16 sum; + + switch (skb->ip_summed) { + case CHECKSUM_COMPLETE: + if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr, + skb->csum)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } +flush: + NAPI_GRO_CB(skb)->flush = 1; + return NULL; + + case CHECKSUM_NONE: + wsum = csum_tcpudp_nofold(iph->saddr, iph->daddr, + skb_gro_len(skb), IPPROTO_TCP, 0); + sum = csum_fold(skb_checksum(skb, + skb_gro_offset(skb), + skb_gro_len(skb), + wsum)); + if (sum) + goto flush; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } + + return tcp_gro_receive(head, skb); +} + +static int tcp4_gro_complete(struct sk_buff *skb) +{ + const struct iphdr *iph = ip_hdr(skb); + struct tcphdr *th = tcp_hdr(skb); + + th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), + iph->saddr, iph->daddr, 0); + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + + return tcp_gro_complete(skb); +} + +static const struct net_offload tcpv4_offload = { + .callbacks = { + .gso_send_check = tcp_v4_gso_send_check, + .gso_segment = tcp_tso_segment, + .gro_receive = tcp4_gro_receive, + .gro_complete = tcp4_gro_complete, + }, +}; + +int __init tcpv4_offload_init(void) +{ + return inet_add_offload(&tcpv4_offload, IPPROTO_TCP); +} -- GitLab From ca162a82f56921442f5db72a3a472010e5a62c4b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 7 Jun 2013 10:48:00 +0000 Subject: [PATCH 0724/2900] fec: Only pass pdev in fec_ptp_init() Passing pdev in fec_ptp_init() is enough, since we can get ndev locally. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 2 +- drivers/net/ethernet/freescale/fec_main.c | 2 +- drivers/net/ethernet/freescale/fec_ptp.c | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index b11cdbcc04ff..e3ed6c5ae801 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -275,7 +275,7 @@ struct fec_enet_private { struct regulator *reg_phy; }; -void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev); +void fec_ptp_init(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index c42c42a0cc57..fa4a68fc01cb 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1945,7 +1945,7 @@ fec_probe(struct platform_device *pdev) fec_reset_phy(pdev); if (fep->bufdesc_ex) - fec_ptp_init(ndev, pdev); + fec_ptp_init(pdev); ret = fec_enet_init(ndev); if (ret) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 25fc960cbf0e..5007e4f9fff9 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -347,8 +347,9 @@ static void fec_time_keep(unsigned long _data) * cyclecounter init routine and exits. */ -void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev) +void fec_ptp_init(struct platform_device *pdev) { + struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); fep->ptp_caps.owner = THIS_MODULE; -- GitLab From 303d1cbf610eef31e039efc2e8da30cf94cf5ebc Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Fri, 31 May 2013 11:57:30 +0000 Subject: [PATCH 0725/2900] bonding: Convert hw addr handling to sync/unsync, support ucast addresses This patch converts bonding to use the dev_uc/mc_sync and dev_uc/mc_sync_multiple functions for updating the hardware addresses of bonding slaves. The existing functions to add or remove addresses are removed, and their functionality is replaced with calls to dev_mc_sync or dev_mc_sync_multiple, depending upon the bonding mode. Calls to dev_uc_sync and dev_uc_sync_multiple are also added, so that unicast addresses added to a bond will be properly synced with its slaves. Various functions are renamed to better reflect the new situation, and relevant comments are updated. Signed-off-by: Jay Vosburgh Cc: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 168 ++++++++------------------------ drivers/net/bonding/bonding.h | 1 - 2 files changed, 43 insertions(+), 126 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f4489d65bf33..4953f66a29a4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -706,45 +706,6 @@ static int bond_set_allmulti(struct bonding *bond, int inc) return err; } -/* - * Add a Multicast address to slaves - * according to mode - */ -static void bond_mc_add(struct bonding *bond, void *addr) -{ - if (USES_PRIMARY(bond->params.mode)) { - /* write lock already acquired */ - if (bond->curr_active_slave) - dev_mc_add(bond->curr_active_slave->dev, addr); - } else { - struct slave *slave; - int i; - - bond_for_each_slave(bond, slave, i) - dev_mc_add(slave->dev, addr); - } -} - -/* - * Remove a multicast address from slave - * according to mode - */ -static void bond_mc_del(struct bonding *bond, void *addr) -{ - if (USES_PRIMARY(bond->params.mode)) { - /* write lock already acquired */ - if (bond->curr_active_slave) - dev_mc_del(bond->curr_active_slave->dev, addr); - } else { - struct slave *slave; - int i; - bond_for_each_slave(bond, slave, i) { - dev_mc_del(slave->dev, addr); - } - } -} - - static void __bond_resend_igmp_join_requests(struct net_device *dev) { struct in_device *in_dev; @@ -803,17 +764,15 @@ static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) bond_resend_igmp_join_requests(bond); } -/* - * flush all members of flush->mc_list from device dev->mc_list +/* Flush bond's hardware addresses from slave */ -static void bond_mc_list_flush(struct net_device *bond_dev, +static void bond_hw_addr_flush(struct net_device *bond_dev, struct net_device *slave_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct netdev_hw_addr *ha; - netdev_for_each_mc_addr(ha, bond_dev) - dev_mc_del(slave_dev, ha->addr); + dev_uc_unsync(slave_dev, bond_dev); + dev_mc_unsync(slave_dev, bond_dev); if (bond->params.mode == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ @@ -825,22 +784,14 @@ static void bond_mc_list_flush(struct net_device *bond_dev, /*--------------------------- Active slave change ---------------------------*/ -/* - * Update the mc list and multicast-related flags for the new and - * old active slaves (if any) according to the multicast mode, and - * promiscuous flags unconditionally. +/* Update the hardware address list and promisc/allmulti for the new and + * old active slaves (if any). Modes that are !USES_PRIMARY keep all + * slaves up date at all times; only the USES_PRIMARY modes need to call + * this function to swap these settings during a failover. */ -static void bond_mc_swap(struct bonding *bond, struct slave *new_active, - struct slave *old_active) +static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, + struct slave *old_active) { - struct netdev_hw_addr *ha; - - if (!USES_PRIMARY(bond->params.mode)) - /* nothing to do - mc list is already up-to-date on - * all slaves - */ - return; - if (old_active) { if (bond->dev->flags & IFF_PROMISC) dev_set_promiscuity(old_active->dev, -1); @@ -848,10 +799,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, if (bond->dev->flags & IFF_ALLMULTI) dev_set_allmulti(old_active->dev, -1); - netif_addr_lock_bh(bond->dev); - netdev_for_each_mc_addr(ha, bond->dev) - dev_mc_del(old_active->dev, ha->addr); - netif_addr_unlock_bh(bond->dev); + bond_hw_addr_flush(bond->dev, old_active->dev); } if (new_active) { @@ -863,8 +811,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, dev_set_allmulti(new_active->dev, 1); netif_addr_lock_bh(bond->dev); - netdev_for_each_mc_addr(ha, bond->dev) - dev_mc_add(new_active->dev, ha->addr); + dev_uc_sync(new_active->dev, bond->dev); + dev_mc_sync(new_active->dev, bond->dev); netif_addr_unlock_bh(bond->dev); } } @@ -1083,7 +1031,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) } if (USES_PRIMARY(bond->params.mode)) - bond_mc_swap(bond, new_active, old_active); + bond_hw_addr_swap(bond, new_active, old_active); if (bond_is_lb(bond)) { bond_alb_handle_active_change(bond, new_active); @@ -1526,7 +1474,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) struct bonding *bond = netdev_priv(bond_dev); const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct slave *new_slave = NULL; - struct netdev_hw_addr *ha; struct sockaddr addr; int link_reporting; int res = 0; @@ -1706,10 +1653,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_close; } - /* If the mode USES_PRIMARY, then the new slave gets the - * master's promisc (and mc) settings only if it becomes the - * curr_active_slave, and that is taken care of later when calling - * bond_change_active() + /* If the mode USES_PRIMARY, then the following is handled by + * bond_change_active_slave(). */ if (!USES_PRIMARY(bond->params.mode)) { /* set promiscuity level to new slave */ @@ -1727,9 +1672,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } netif_addr_lock_bh(bond_dev); - /* upload master's mc_list to new slave */ - netdev_for_each_mc_addr(ha, bond_dev) - dev_mc_add(slave_dev, ha->addr); + + dev_mc_sync_multiple(slave_dev, bond_dev); + dev_uc_sync_multiple(slave_dev, bond_dev); + netif_addr_unlock_bh(bond_dev); } @@ -1908,11 +1854,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_destroy_slave_symlinks(bond_dev, slave_dev); err_detach: - if (!USES_PRIMARY(bond->params.mode)) { - netif_addr_lock_bh(bond_dev); - bond_mc_list_flush(bond_dev, slave_dev); - netif_addr_unlock_bh(bond_dev); - } + if (!USES_PRIMARY(bond->params.mode)) + bond_hw_addr_flush(bond_dev, slave_dev); + bond_del_vlans_from_slave(bond, slave_dev); write_lock_bh(&bond->lock); bond_detach_slave(bond, new_slave); @@ -2107,9 +2051,8 @@ static int __bond_release_one(struct net_device *bond_dev, bond_del_vlans_from_slave(bond, slave_dev); - /* If the mode USES_PRIMARY, then we should only remove its - * promisc and mc settings if it was the curr_active_slave, but that was - * already taken care of above when we detached the slave + /* If the mode USES_PRIMARY, then this cases was handled above by + * bond_change_active_slave(..., NULL) */ if (!USES_PRIMARY(bond->params.mode)) { /* unset promiscuity level from slave */ @@ -2120,10 +2063,7 @@ static int __bond_release_one(struct net_device *bond_dev, if (bond_dev->flags & IFF_ALLMULTI) dev_set_allmulti(slave_dev, -1); - /* flush master's mc_list from slave */ - netif_addr_lock_bh(bond_dev); - bond_mc_list_flush(bond_dev, slave_dev); - netif_addr_unlock_bh(bond_dev); + bond_hw_addr_flush(bond_dev, slave_dev); } bond_upper_dev_unlink(bond_dev, slave_dev); @@ -3660,19 +3600,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd return res; } -static bool bond_addr_in_mc_list(unsigned char *addr, - struct netdev_hw_addr_list *list, - int addrlen) -{ - struct netdev_hw_addr *ha; - - netdev_hw_addr_list_for_each(ha, list) - if (!memcmp(ha->addr, addr, addrlen)) - return true; - - return false; -} - static void bond_change_rx_flags(struct net_device *bond_dev, int change) { struct bonding *bond = netdev_priv(bond_dev); @@ -3686,35 +3613,29 @@ static void bond_change_rx_flags(struct net_device *bond_dev, int change) bond_dev->flags & IFF_ALLMULTI ? 1 : -1); } -static void bond_set_multicast_list(struct net_device *bond_dev) +static void bond_set_rx_mode(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct netdev_hw_addr *ha; - bool found; + struct slave *slave; + int i; read_lock(&bond->lock); - /* looking for addresses to add to slaves' mc list */ - netdev_for_each_mc_addr(ha, bond_dev) { - found = bond_addr_in_mc_list(ha->addr, &bond->mc_list, - bond_dev->addr_len); - if (!found) - bond_mc_add(bond, ha->addr); - } - - /* looking for addresses to delete from slaves' list */ - netdev_hw_addr_list_for_each(ha, &bond->mc_list) { - found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc, - bond_dev->addr_len); - if (!found) - bond_mc_del(bond, ha->addr); + if (USES_PRIMARY(bond->params.mode)) { + read_lock(&bond->curr_slave_lock); + slave = bond->curr_active_slave; + if (slave) { + dev_uc_sync(slave->dev, bond_dev); + dev_mc_sync(slave->dev, bond_dev); + } + read_unlock(&bond->curr_slave_lock); + } else { + bond_for_each_slave(bond, slave, i) { + dev_uc_sync_multiple(slave->dev, bond_dev); + dev_mc_sync_multiple(slave->dev, bond_dev); + } } - /* save master's multicast list */ - __hw_addr_flush(&bond->mc_list); - __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc, - bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST); - read_unlock(&bond->lock); } @@ -4321,7 +4242,7 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_get_stats64 = bond_get_stats, .ndo_do_ioctl = bond_do_ioctl, .ndo_change_rx_flags = bond_change_rx_flags, - .ndo_set_rx_mode = bond_set_multicast_list, + .ndo_set_rx_mode = bond_set_rx_mode, .ndo_change_mtu = bond_change_mtu, .ndo_set_mac_address = bond_set_mac_address, .ndo_neigh_setup = bond_neigh_setup, @@ -4426,8 +4347,6 @@ static void bond_uninit(struct net_device *bond_dev) bond_debug_unregister(bond); - __hw_addr_flush(&bond->mc_list); - list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) { list_del(&vlan->vlan_list); kfree(vlan); @@ -4838,7 +4757,6 @@ static int bond_init(struct net_device *bond_dev) bond->dev_addr_from_first = true; } - __hw_addr_init(&bond->mc_list); return 0; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 2baec24388b1..b38609b967b7 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -231,7 +231,6 @@ struct bonding { char proc_file_name[IFNAMSIZ]; #endif /* CONFIG_PROC_FS */ struct list_head bond_list; - struct netdev_hw_addr_list mc_list; int (*xmit_hash_policy)(struct sk_buff *, int); u16 rr_tx_counter; struct ad_bond_info ad_info; -- GitLab From 1b5acd292336da029535de010af568533df9b665 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Fri, 31 May 2013 11:57:31 +0000 Subject: [PATCH 0726/2900] bonding: disallow change of MAC if fail_over_mac enabled Currently, if fail_over_mac is set to active, then attempts to change the MAC of the bond itself silently fail. However, if fail_over_mac is set to follow, changes are permitted. Permitting the bond's MAC to change with fail_over_mac=follow will disrupt the follow functionality, which normally controls the assignment of MAC address to the bond and its slaves, and can cause multiple ports to be assigned the same MAC address. which will interfere with the functioning of the device (where the device here is a virtualization-aware card for s390, qeth). Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4953f66a29a4..bc1246f6f86a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3780,11 +3780,10 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) pr_debug("bond=%p, name=%s\n", bond, bond_dev ? bond_dev->name : "None"); - /* - * If fail_over_mac is set to active, do nothing and return - * success. Returning an error causes ifenslave to fail. + /* If fail_over_mac is enabled, do nothing and return success. + * Returning an error causes ifenslave to fail. */ - if (bond->params.fail_over_mac == BOND_FOM_ACTIVE) + if (bond->params.fail_over_mac) return 0; if (!is_valid_ether_addr(sa->sa_data)) -- GitLab From c05cdb1b864f548c0c3d8ae3b51264e6739a69b1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 3 Jun 2013 09:46:28 +0000 Subject: [PATCH 0727/2900] netlink: allow large data transfers from user-space I can hit ENOBUFS in the sendmsg() path with a large batch that is composed of many netlink messages. Here that limit is 8 MBytes of skbuff data area as kmalloc does not manage to get more than that. While discussing atomic rule-set for nftables with Patrick McHardy, we decided to put all rule-set updates that need to be applied atomically in one single batch to simplify the existing approach. However, as explained above, the existing netlink code limits us to a maximum of ~20000 rules that fit in one single batch without hitting ENOBUFS. iptables does not have such limitation as it is using vmalloc. This patch adds netlink_alloc_large_skb() which is only used in the netlink_sendmsg() path. It uses alloc_skb if the memory requested is <= one memory page, that should be the common case for most subsystems, else vmalloc for higher memory allocations. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d0b3dd60d386..68c167374394 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -750,6 +750,10 @@ static void netlink_skb_destructor(struct sk_buff *skb) skb->head = NULL; } #endif + if (is_vmalloc_addr(skb->head)) { + vfree(skb->head); + skb->head = NULL; + } if (skb->sk != NULL) sock_rfree(skb); } @@ -1420,6 +1424,35 @@ struct sock *netlink_getsockbyfilp(struct file *filp) return sock; } +static struct sk_buff *netlink_alloc_large_skb(unsigned int size) +{ + struct sk_buff *skb; + void *data; + + if (size <= NLMSG_GOODSIZE) + return alloc_skb(size, GFP_KERNEL); + + skb = alloc_skb_head(GFP_KERNEL); + if (skb == NULL) + return NULL; + + data = vmalloc(size); + if (data == NULL) + goto err; + + skb->head = data; + skb->data = data; + skb_reset_tail_pointer(skb); + skb->end = skb->tail + size; + skb->len = 0; + skb->destructor = netlink_skb_destructor; + + return skb; +err: + kfree_skb(skb); + return NULL; +} + /* * Attach a skb to a netlink socket. * The caller must hold a reference to the destination socket. On error, the @@ -1510,7 +1543,7 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation) return skb; delta = skb->end - skb->tail; - if (delta * 2 < skb->truesize) + if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize) return skb; if (skb_shared(skb)) { @@ -2096,7 +2129,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; - skb = alloc_skb(len, GFP_KERNEL); + skb = netlink_alloc_large_skb(len); if (skb == NULL) goto out; -- GitLab From fc8b14d338f6265533a8f82db1325fa112b530ba Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 1 Jun 2013 11:39:36 +0200 Subject: [PATCH 0728/2900] eCryptfs: Cocci spatch "memdup.spatch" Signed-off-by: Thomas Meyer Signed-off-by: Tyler Hicks --- fs/ecryptfs/messaging.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 49ff8ea08f1c..e57380e5f6bd 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -247,14 +247,13 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon, goto unlock; } msg_size = (sizeof(*msg) + msg->data_len); - msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL); + msg_ctx->msg = kmemdup(msg, msg_size, GFP_KERNEL); if (!msg_ctx->msg) { rc = -ENOMEM; printk(KERN_ERR "%s: Failed to allocate [%zd] bytes of " "GFP_KERNEL memory\n", __func__, msg_size); goto unlock; } - memcpy(msg_ctx->msg, msg, msg_size); msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; wake_up_process(msg_ctx->task); rc = 0; -- GitLab From 12003e5b18ca33807b3f9448309ec92184192b85 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Tue, 16 Apr 2013 23:21:24 -0700 Subject: [PATCH 0729/2900] eCryptfs: Use entire helper page during page crypto operations When encrypting eCryptfs pages and decrypting pages from the lower filesystem, utilize the entire helper page rather than only the first 4096 bytes. This only affects architectures where PAGE_CACHE_SIZE is larger than 4096 bytes. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index f71ec125290d..e8976c004669 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -450,10 +450,11 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0, - page, (extent_offset - * crypt_stat->extent_size), - crypt_stat->extent_size, extent_iv); + rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, + extent_offset * crypt_stat->extent_size, + page, + extent_offset * crypt_stat->extent_size, + crypt_stat->extent_size, extent_iv); if (rc < 0) { printk(KERN_ERR "%s: Error attempting to encrypt page with " "page->index = [%ld], extent_offset = [%ld]; " @@ -520,8 +521,9 @@ int ecryptfs_encrypt_page(struct page *page) * (PAGE_CACHE_SIZE / crypt_stat->extent_size)) + extent_offset), crypt_stat); - rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, - offset, crypt_stat->extent_size); + rc = ecryptfs_write_lower(ecryptfs_inode, (enc_extent_virt + + extent_offset * crypt_stat->extent_size), + offset, crypt_stat->extent_size); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting " "to write lower page; rc = [%d]" @@ -558,10 +560,10 @@ static int ecryptfs_decrypt_extent(struct page *page, goto out; } rc = ecryptfs_decrypt_page_offset(crypt_stat, page, - (extent_offset - * crypt_stat->extent_size), - enc_extent_page, 0, - crypt_stat->extent_size, extent_iv); + extent_offset * crypt_stat->extent_size, + enc_extent_page, + extent_offset * crypt_stat->extent_size, + crypt_stat->extent_size, extent_iv); if (rc < 0) { printk(KERN_ERR "%s: Error attempting to decrypt to page with " "page->index = [%ld], extent_offset = [%ld]; " @@ -620,9 +622,10 @@ int ecryptfs_decrypt_page(struct page *page) &offset, ((page->index * (PAGE_CACHE_SIZE / crypt_stat->extent_size)) + extent_offset), crypt_stat); - rc = ecryptfs_read_lower(enc_extent_virt, offset, - crypt_stat->extent_size, - ecryptfs_inode); + rc = ecryptfs_read_lower((enc_extent_virt + + extent_offset * crypt_stat->extent_size), + offset, crypt_stat->extent_size, + ecryptfs_inode); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting " "to read lower page; rc = [%d]" -- GitLab From 0f89617623fed9541ead9497043e907466848a9f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 15 Apr 2013 16:16:24 -0700 Subject: [PATCH 0730/2900] eCryptfs: Read/write entire page during page IO When reading and writing encrypted pages, perform IO using the entire page all at once rather than 4096 bytes at a time. This only affects architectures where PAGE_CACHE_SIZE is larger than 4096 bytes. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 66 +++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index e8976c004669..4185584594f5 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -490,6 +490,7 @@ int ecryptfs_encrypt_page(struct page *page) char *enc_extent_virt; struct page *enc_extent_page = NULL; loff_t extent_offset; + loff_t lower_offset; int rc = 0; ecryptfs_inode = page->mapping->host; @@ -503,12 +504,10 @@ int ecryptfs_encrypt_page(struct page *page) "encrypted extent\n"); goto out; } - enc_extent_virt = kmap(enc_extent_page); + for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - loff_t offset; - rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page, extent_offset); if (rc) { @@ -516,25 +515,24 @@ int ecryptfs_encrypt_page(struct page *page) "rc = [%d]\n", __func__, rc); goto out; } - ecryptfs_lower_offset_for_extent( - &offset, ((((loff_t)page->index) - * (PAGE_CACHE_SIZE - / crypt_stat->extent_size)) - + extent_offset), crypt_stat); - rc = ecryptfs_write_lower(ecryptfs_inode, (enc_extent_virt + - extent_offset * crypt_stat->extent_size), - offset, crypt_stat->extent_size); - if (rc < 0) { - ecryptfs_printk(KERN_ERR, "Error attempting " - "to write lower page; rc = [%d]" - "\n", rc); - goto out; - } + } + + ecryptfs_lower_offset_for_extent(&lower_offset, + page->index * (PAGE_CACHE_SIZE / crypt_stat->extent_size), + crypt_stat); + enc_extent_virt = kmap(enc_extent_page); + rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset, + PAGE_CACHE_SIZE); + kunmap(enc_extent_page); + if (rc < 0) { + ecryptfs_printk(KERN_ERR, + "Error attempting to write lower page; rc = [%d]\n", + rc); + goto out; } rc = 0; out: if (enc_extent_page) { - kunmap(enc_extent_page); __free_page(enc_extent_page); } return rc; @@ -599,6 +597,7 @@ int ecryptfs_decrypt_page(struct page *page) char *enc_extent_virt; struct page *enc_extent_page = NULL; unsigned long extent_offset; + loff_t lower_offset; int rc = 0; ecryptfs_inode = page->mapping->host; @@ -612,26 +611,24 @@ int ecryptfs_decrypt_page(struct page *page) "encrypted extent\n"); goto out; } + + ecryptfs_lower_offset_for_extent(&lower_offset, + page->index * (PAGE_CACHE_SIZE / crypt_stat->extent_size), + crypt_stat); enc_extent_virt = kmap(enc_extent_page); + rc = ecryptfs_read_lower(enc_extent_virt, lower_offset, PAGE_CACHE_SIZE, + ecryptfs_inode); + kunmap(enc_extent_page); + if (rc < 0) { + ecryptfs_printk(KERN_ERR, + "Error attempting to read lower page; rc = [%d]\n", + rc); + goto out; + } + for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - loff_t offset; - - ecryptfs_lower_offset_for_extent( - &offset, ((page->index * (PAGE_CACHE_SIZE - / crypt_stat->extent_size)) - + extent_offset), crypt_stat); - rc = ecryptfs_read_lower((enc_extent_virt + - extent_offset * crypt_stat->extent_size), - offset, crypt_stat->extent_size, - ecryptfs_inode); - if (rc < 0) { - ecryptfs_printk(KERN_ERR, "Error attempting " - "to read lower page; rc = [%d]" - "\n", rc); - goto out; - } rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page, extent_offset); if (rc) { @@ -642,7 +639,6 @@ int ecryptfs_decrypt_page(struct page *page) } out: if (enc_extent_page) { - kunmap(enc_extent_page); __free_page(enc_extent_page); } return rc; -- GitLab From 24d15266bd86b7961f309a962fa3aa177a78c49f Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 15 Apr 2013 17:28:09 -0700 Subject: [PATCH 0731/2900] eCryptfs: Simplify lower file offset calculation Now that lower filesystem IO operations occur for complete PAGE_CACHE_SIZE bytes, the calculation for converting an eCryptfs extent index into a lower file offset can be simplified. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 4185584594f5..3547708fb4e1 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -407,15 +407,15 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, } /** - * ecryptfs_lower_offset_for_extent + * lower_offset_for_page * * Convert an eCryptfs page index into a lower byte offset */ -static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num, - struct ecryptfs_crypt_stat *crypt_stat) +static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, + struct page *page) { - (*offset) = ecryptfs_lower_header_size(crypt_stat) - + (crypt_stat->extent_size * extent_num); + return ecryptfs_lower_header_size(crypt_stat) + + (page->index << PAGE_CACHE_SHIFT); } /** @@ -517,9 +517,7 @@ int ecryptfs_encrypt_page(struct page *page) } } - ecryptfs_lower_offset_for_extent(&lower_offset, - page->index * (PAGE_CACHE_SIZE / crypt_stat->extent_size), - crypt_stat); + lower_offset = lower_offset_for_page(crypt_stat, page); enc_extent_virt = kmap(enc_extent_page); rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset, PAGE_CACHE_SIZE); @@ -612,9 +610,7 @@ int ecryptfs_decrypt_page(struct page *page) goto out; } - ecryptfs_lower_offset_for_extent(&lower_offset, - page->index * (PAGE_CACHE_SIZE / crypt_stat->extent_size), - crypt_stat); + lower_offset = lower_offset_for_page(crypt_stat, page); enc_extent_virt = kmap(enc_extent_page); rc = ecryptfs_read_lower(enc_extent_virt, lower_offset, PAGE_CACHE_SIZE, ecryptfs_inode); -- GitLab From 28916d1ac1dd658773717e8eddc7c4ceeefc19b8 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 15 Apr 2013 16:37:27 -0700 Subject: [PATCH 0732/2900] eCryptfs: Accept one offset parameter in page offset crypto functions There is no longer a need to accept different offset values for the source and destination pages when encrypting/decrypting an extent in an eCryptfs page. The two offsets can be collapsed into a single parameter. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 3547708fb4e1..ec640ebcdea8 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -39,14 +39,12 @@ static int ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv); + struct page *dst_page, struct page *src_page, + int offset, int size, unsigned char *iv); static int ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv); + struct page *dst_page, struct page *src_page, + int offset, int size, unsigned char *iv); /** * ecryptfs_to_hex @@ -450,9 +448,7 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, - extent_offset * crypt_stat->extent_size, - page, + rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, page, extent_offset * crypt_stat->extent_size, crypt_stat->extent_size, extent_iv); if (rc < 0) { @@ -555,9 +551,7 @@ static int ecryptfs_decrypt_extent(struct page *page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = ecryptfs_decrypt_page_offset(crypt_stat, page, - extent_offset * crypt_stat->extent_size, - enc_extent_page, + rc = ecryptfs_decrypt_page_offset(crypt_stat, page, enc_extent_page, extent_offset * crypt_stat->extent_size, crypt_stat->extent_size, extent_iv); if (rc < 0) { @@ -716,9 +710,8 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, * ecryptfs_encrypt_page_offset * @crypt_stat: The cryptographic context * @dst_page: The page to encrypt into - * @dst_offset: The offset in the page to encrypt into * @src_page: The page to encrypt from - * @src_offset: The offset in the page to encrypt from + * @offset: The byte offset into the dst_page and src_page * @size: The number of bytes to encrypt * @iv: The initialization vector to use for the encryption * @@ -726,17 +719,16 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, */ static int ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv) + struct page *dst_page, struct page *src_page, + int offset, int size, unsigned char *iv) { struct scatterlist src_sg, dst_sg; sg_init_table(&src_sg, 1); sg_init_table(&dst_sg, 1); - sg_set_page(&src_sg, src_page, size, src_offset); - sg_set_page(&dst_sg, dst_page, size, dst_offset); + sg_set_page(&src_sg, src_page, size, offset); + sg_set_page(&dst_sg, dst_page, size, offset); return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); } @@ -744,9 +736,8 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, * ecryptfs_decrypt_page_offset * @crypt_stat: The cryptographic context * @dst_page: The page to decrypt into - * @dst_offset: The offset in the page to decrypt into * @src_page: The page to decrypt from - * @src_offset: The offset in the page to decrypt from + * @offset: The byte offset into the dst_page and src_page * @size: The number of bytes to decrypt * @iv: The initialization vector to use for the decryption * @@ -754,17 +745,16 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, */ static int ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, int dst_offset, - struct page *src_page, int src_offset, int size, - unsigned char *iv) + struct page *dst_page, struct page *src_page, + int offset, int size, unsigned char *iv) { struct scatterlist src_sg, dst_sg; sg_init_table(&src_sg, 1); - sg_set_page(&src_sg, src_page, size, src_offset); + sg_set_page(&src_sg, src_page, size, offset); sg_init_table(&dst_sg, 1); - sg_set_page(&dst_sg, dst_page, size, dst_offset); + sg_set_page(&dst_sg, dst_page, size, offset); return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); } -- GitLab From 9c6043f41222b448a314b0b8370f33b579f777ea Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Sat, 6 Apr 2013 00:41:48 -0700 Subject: [PATCH 0733/2900] eCryptfs: Decrypt pages in-place When reading in a page, eCryptfs would allocate a helper page, fill it with encrypted data from the lower filesytem, and then decrypt the data from the encrypted page and store the result in the eCryptfs page cache page. The crypto API supports in-place crypto operations which means that the allocation of the helper page is unnecessary when decrypting. This patch gets rid of the unneeded page allocation by reading encrypted data from the lower filesystem directly into the page cache page. The page cache page is then decrypted in-place. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index ec640ebcdea8..35b409bda841 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -586,8 +586,7 @@ int ecryptfs_decrypt_page(struct page *page) { struct inode *ecryptfs_inode; struct ecryptfs_crypt_stat *crypt_stat; - char *enc_extent_virt; - struct page *enc_extent_page = NULL; + char *page_virt; unsigned long extent_offset; loff_t lower_offset; int rc = 0; @@ -596,19 +595,12 @@ int ecryptfs_decrypt_page(struct page *page) crypt_stat = &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); - enc_extent_page = alloc_page(GFP_USER); - if (!enc_extent_page) { - rc = -ENOMEM; - ecryptfs_printk(KERN_ERR, "Error allocating memory for " - "encrypted extent\n"); - goto out; - } lower_offset = lower_offset_for_page(crypt_stat, page); - enc_extent_virt = kmap(enc_extent_page); - rc = ecryptfs_read_lower(enc_extent_virt, lower_offset, PAGE_CACHE_SIZE, + page_virt = kmap(page); + rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_CACHE_SIZE, ecryptfs_inode); - kunmap(enc_extent_page); + kunmap(page); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting to read lower page; rc = [%d]\n", @@ -619,7 +611,7 @@ int ecryptfs_decrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page, + rc = ecryptfs_decrypt_extent(page, crypt_stat, page, extent_offset); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " @@ -628,9 +620,6 @@ int ecryptfs_decrypt_page(struct page *page) } } out: - if (enc_extent_page) { - __free_page(enc_extent_page); - } return rc; } -- GitLab From 00a699400a707953368e970b37bb8765fdb08015 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Fri, 5 Apr 2013 23:26:22 -0700 Subject: [PATCH 0734/2900] eCryptfs: Combine encrypt_scatterlist() and decrypt_scatterlist() These two functions are identical except for a debug printk and whether they call crypto_ablkcipher_encrypt() or crypto_ablkcipher_decrypt(), so they can be safely merged if the caller can indicate if encryption or decryption should occur. The debug printk is useless so it is removed. Two new #define's are created to indicate if an ENCRYPT or DECRYPT operation is desired. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 106 ++++++++----------------------------------- 1 file changed, 20 insertions(+), 86 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 35b409bda841..fb54a0182f2e 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -37,6 +37,9 @@ #include #include "ecryptfs_kernel.h" +#define DECRYPT 0 +#define ENCRYPT 1 + static int ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, struct page *dst_page, struct page *src_page, @@ -334,19 +337,20 @@ static void extent_crypt_complete(struct crypto_async_request *req, int rc) } /** - * encrypt_scatterlist + * crypt_scatterlist * @crypt_stat: Pointer to the crypt_stat struct to initialize. - * @dest_sg: Destination of encrypted data - * @src_sg: Data to be encrypted - * @size: Length of data to be encrypted - * @iv: iv to use during encryption + * @dest_sg: Destination of the data after performing the crypto operation + * @src_sg: Data to be encrypted or decrypted + * @size: Length of data + * @iv: IV to use + * @op: ENCRYPT or DECRYPT to indicate the desired operation * - * Returns the number of bytes encrypted; negative value on error + * Returns the number of bytes encrypted or decrypted; negative value on error */ -static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, - struct scatterlist *dest_sg, - struct scatterlist *src_sg, int size, - unsigned char *iv) +static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, + struct scatterlist *dest_sg, + struct scatterlist *src_sg, int size, + unsigned char *iv, int op) { struct ablkcipher_request *req = NULL; struct extent_crypt_result ecr; @@ -389,9 +393,9 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, crypt_stat->flags |= ECRYPTFS_KEY_SET; } mutex_unlock(&crypt_stat->cs_tfm_mutex); - ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv); - rc = crypto_ablkcipher_encrypt(req); + rc = op == ENCRYPT ? crypto_ablkcipher_encrypt(req) : + crypto_ablkcipher_decrypt(req); if (rc == -EINPROGRESS || rc == -EBUSY) { struct extent_crypt_result *ecr = req->base.data; @@ -623,78 +627,6 @@ int ecryptfs_decrypt_page(struct page *page) return rc; } -/** - * decrypt_scatterlist - * @crypt_stat: Cryptographic context - * @dest_sg: The destination scatterlist to decrypt into - * @src_sg: The source scatterlist to decrypt from - * @size: The number of bytes to decrypt - * @iv: The initialization vector to use for the decryption - * - * Returns the number of bytes decrypted; negative value on error - */ -static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, - struct scatterlist *dest_sg, - struct scatterlist *src_sg, int size, - unsigned char *iv) -{ - struct ablkcipher_request *req = NULL; - struct extent_crypt_result ecr; - int rc = 0; - - BUG_ON(!crypt_stat || !crypt_stat->tfm - || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); - if (unlikely(ecryptfs_verbosity > 0)) { - ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", - crypt_stat->key_size); - ecryptfs_dump_hex(crypt_stat->key, - crypt_stat->key_size); - } - - init_completion(&ecr.completion); - - mutex_lock(&crypt_stat->cs_tfm_mutex); - req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); - if (!req) { - mutex_unlock(&crypt_stat->cs_tfm_mutex); - rc = -ENOMEM; - goto out; - } - - ablkcipher_request_set_callback(req, - CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - extent_crypt_complete, &ecr); - /* Consider doing this once, when the file is opened */ - if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { - rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); - if (rc) { - ecryptfs_printk(KERN_ERR, - "Error setting key; rc = [%d]\n", - rc); - mutex_unlock(&crypt_stat->cs_tfm_mutex); - rc = -EINVAL; - goto out; - } - crypt_stat->flags |= ECRYPTFS_KEY_SET; - } - mutex_unlock(&crypt_stat->cs_tfm_mutex); - ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); - ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv); - rc = crypto_ablkcipher_decrypt(req); - if (rc == -EINPROGRESS || rc == -EBUSY) { - struct extent_crypt_result *ecr = req->base.data; - - wait_for_completion(&ecr->completion); - rc = ecr->rc; - INIT_COMPLETION(ecr->completion); - } -out: - ablkcipher_request_free(req); - return rc; - -} - /** * ecryptfs_encrypt_page_offset * @crypt_stat: The cryptographic context @@ -718,7 +650,8 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, sg_set_page(&src_sg, src_page, size, offset); sg_set_page(&dst_sg, dst_page, size, offset); - return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); + return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, + size, iv, ENCRYPT); } /** @@ -745,7 +678,8 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, sg_init_table(&dst_sg, 1); sg_set_page(&dst_sg, dst_page, size, offset); - return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); + return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, + size, iv, DECRYPT); } #define ECRYPTFS_MAX_SCATTERLIST_LEN 4 -- GitLab From a8ca90e2071edb3d3f3272ae73d73411f0b70b54 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Fri, 5 Apr 2013 23:37:51 -0700 Subject: [PATCH 0735/2900] eCryptfs: Combine page_offset crypto functions Combine ecryptfs_encrypt_page_offset() and ecryptfs_decrypt_page_offset(). These two functions are functionally identical so they can be safely merged if the caller can indicate whether an encryption or decryption operation should occur. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 69 ++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 51 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index fb54a0182f2e..609efc01d5c2 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -40,14 +40,9 @@ #define DECRYPT 0 #define ENCRYPT 1 -static int -ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv); -static int -ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, +static int crypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv); + int offset, int size, unsigned char *iv, int op); /** * ecryptfs_to_hex @@ -452,9 +447,9 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, page, - extent_offset * crypt_stat->extent_size, - crypt_stat->extent_size, extent_iv); + rc = crypt_page_offset(crypt_stat, enc_extent_page, page, + (extent_offset * crypt_stat->extent_size), + crypt_stat->extent_size, extent_iv, ENCRYPT); if (rc < 0) { printk(KERN_ERR "%s: Error attempting to encrypt page with " "page->index = [%ld], extent_offset = [%ld]; " @@ -555,9 +550,9 @@ static int ecryptfs_decrypt_extent(struct page *page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = ecryptfs_decrypt_page_offset(crypt_stat, page, enc_extent_page, - extent_offset * crypt_stat->extent_size, - crypt_stat->extent_size, extent_iv); + rc = crypt_page_offset(crypt_stat, page, enc_extent_page, + (extent_offset * crypt_stat->extent_size), + crypt_stat->extent_size, extent_iv, DECRYPT); if (rc < 0) { printk(KERN_ERR "%s: Error attempting to decrypt to page with " "page->index = [%ld], extent_offset = [%ld]; " @@ -628,20 +623,20 @@ int ecryptfs_decrypt_page(struct page *page) } /** - * ecryptfs_encrypt_page_offset + * crypt_page_offset * @crypt_stat: The cryptographic context - * @dst_page: The page to encrypt into - * @src_page: The page to encrypt from + * @dst_page: The page to write the result into + * @src_page: The page to read from * @offset: The byte offset into the dst_page and src_page - * @size: The number of bytes to encrypt - * @iv: The initialization vector to use for the encryption + * @size: The number of bytes of data + * @iv: The initialization vector to use for the crypto operation + * @op: ENCRYPT or DECRYPT to indicate the desired operation * - * Returns the number of bytes encrypted + * Returns the number of bytes encrypted or decrypted */ -static int -ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, +static int crypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv) + int offset, int size, unsigned char *iv, int op) { struct scatterlist src_sg, dst_sg; @@ -650,36 +645,8 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, sg_set_page(&src_sg, src_page, size, offset); sg_set_page(&dst_sg, dst_page, size, offset); - return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, - size, iv, ENCRYPT); -} - -/** - * ecryptfs_decrypt_page_offset - * @crypt_stat: The cryptographic context - * @dst_page: The page to decrypt into - * @src_page: The page to decrypt from - * @offset: The byte offset into the dst_page and src_page - * @size: The number of bytes to decrypt - * @iv: The initialization vector to use for the decryption - * - * Returns the number of bytes decrypted - */ -static int -ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv) -{ - struct scatterlist src_sg, dst_sg; - - sg_init_table(&src_sg, 1); - sg_set_page(&src_sg, src_page, size, offset); - - sg_init_table(&dst_sg, 1); - sg_set_page(&dst_sg, dst_page, size, offset); - return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, - size, iv, DECRYPT); + return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv, op); } #define ECRYPTFS_MAX_SCATTERLIST_LEN 4 -- GitLab From d78de618962d1e9d28c602e3c75991fe9c94e961 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Sat, 6 Apr 2013 00:08:48 -0700 Subject: [PATCH 0736/2900] eCryptfs: Merge ecryptfs_encrypt_extent() and ecryptfs_decrypt_extent() They are identical except if the src_page or dst_page index is used, so they can be merged safely if page_index is conditionally assigned. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 74 ++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 609efc01d5c2..9845d2fd2506 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -416,28 +416,29 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, } /** - * ecryptfs_encrypt_extent - * @enc_extent_page: Allocated page into which to encrypt the data in - * @page + * crypt_extent + * @dst_page: The page to write the result into * @crypt_stat: crypt_stat containing cryptographic context for the * encryption operation - * @page: Page containing plaintext data extent to encrypt + * @src_page: The page to read from * @extent_offset: Page extent offset for use in generating IV + * @op: ENCRYPT or DECRYPT to indicate the desired operation * - * Encrypts one extent of data. + * Encrypts or decrypts one extent of data. * * Return zero on success; non-zero otherwise */ -static int ecryptfs_encrypt_extent(struct page *enc_extent_page, - struct ecryptfs_crypt_stat *crypt_stat, - struct page *page, - unsigned long extent_offset) +static int crypt_extent(struct page *dst_page, + struct ecryptfs_crypt_stat *crypt_stat, + struct page *src_page, + unsigned long extent_offset, int op) { + pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index; loff_t extent_base; char extent_iv[ECRYPTFS_MAX_IV_BYTES]; int rc; - extent_base = (((loff_t)page->index) + extent_base = (((loff_t)page_index) * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); rc = ecryptfs_derive_iv(extent_iv, crypt_stat, (extent_base + extent_offset)); @@ -447,14 +448,13 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = crypt_page_offset(crypt_stat, enc_extent_page, page, + rc = crypt_page_offset(crypt_stat, dst_page, src_page, (extent_offset * crypt_stat->extent_size), - crypt_stat->extent_size, extent_iv, ENCRYPT); + crypt_stat->extent_size, extent_iv, op); if (rc < 0) { - printk(KERN_ERR "%s: Error attempting to encrypt page with " - "page->index = [%ld], extent_offset = [%ld]; " - "rc = [%d]\n", __func__, page->index, extent_offset, - rc); + printk(KERN_ERR "%s: Error attempting to crypt page with " + "page_index = [%ld], extent_offset = [%ld]; " + "rc = [%d]\n", __func__, page_index, extent_offset, rc); goto out; } rc = 0; @@ -503,8 +503,8 @@ int ecryptfs_encrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page, - extent_offset); + rc = crypt_extent(enc_extent_page, crypt_stat, page, + extent_offset, ENCRYPT); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " "rc = [%d]\n", __func__, rc); @@ -531,40 +531,6 @@ int ecryptfs_encrypt_page(struct page *page) return rc; } -static int ecryptfs_decrypt_extent(struct page *page, - struct ecryptfs_crypt_stat *crypt_stat, - struct page *enc_extent_page, - unsigned long extent_offset) -{ - loff_t extent_base; - char extent_iv[ECRYPTFS_MAX_IV_BYTES]; - int rc; - - extent_base = (((loff_t)page->index) - * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); - rc = ecryptfs_derive_iv(extent_iv, crypt_stat, - (extent_base + extent_offset)); - if (rc) { - ecryptfs_printk(KERN_ERR, "Error attempting to derive IV for " - "extent [0x%.16llx]; rc = [%d]\n", - (unsigned long long)(extent_base + extent_offset), rc); - goto out; - } - rc = crypt_page_offset(crypt_stat, page, enc_extent_page, - (extent_offset * crypt_stat->extent_size), - crypt_stat->extent_size, extent_iv, DECRYPT); - if (rc < 0) { - printk(KERN_ERR "%s: Error attempting to decrypt to page with " - "page->index = [%ld], extent_offset = [%ld]; " - "rc = [%d]\n", __func__, page->index, extent_offset, - rc); - goto out; - } - rc = 0; -out: - return rc; -} - /** * ecryptfs_decrypt_page * @page: Page mapped from the eCryptfs inode for the file; data read @@ -610,8 +576,8 @@ int ecryptfs_decrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = ecryptfs_decrypt_extent(page, crypt_stat, page, - extent_offset); + rc = crypt_extent(page, crypt_stat, page, + extent_offset, DECRYPT); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " "rc = [%d]\n", __func__, rc); -- GitLab From 406c93df09ae7a345b510cf6619f881b42a3d553 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Mon, 15 Apr 2013 17:49:31 -0700 Subject: [PATCH 0737/2900] eCryptfs: Collapse crypt_page_offset() into crypt_extent() crypt_page_offset() simply initialized the two scatterlists and called crypt_scatterlist() so it is simple enough to move into the only function that calls it. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 50 +++++++++++++------------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 9845d2fd2506..9947388ccd8d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -40,10 +40,6 @@ #define DECRYPT 0 #define ENCRYPT 1 -static int crypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv, int op); - /** * ecryptfs_to_hex * @dst: Buffer to take hex character representation of contents of @@ -436,10 +432,11 @@ static int crypt_extent(struct page *dst_page, pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index; loff_t extent_base; char extent_iv[ECRYPTFS_MAX_IV_BYTES]; + struct scatterlist src_sg, dst_sg; + size_t extent_size = crypt_stat->extent_size; int rc; - extent_base = (((loff_t)page_index) - * (PAGE_CACHE_SIZE / crypt_stat->extent_size)); + extent_base = (((loff_t)page_index) * (PAGE_CACHE_SIZE / extent_size)); rc = ecryptfs_derive_iv(extent_iv, crypt_stat, (extent_base + extent_offset)); if (rc) { @@ -448,9 +445,17 @@ static int crypt_extent(struct page *dst_page, (unsigned long long)(extent_base + extent_offset), rc); goto out; } - rc = crypt_page_offset(crypt_stat, dst_page, src_page, - (extent_offset * crypt_stat->extent_size), - crypt_stat->extent_size, extent_iv, op); + + sg_init_table(&src_sg, 1); + sg_init_table(&dst_sg, 1); + + sg_set_page(&src_sg, src_page, extent_size, + extent_offset * extent_size); + sg_set_page(&dst_sg, dst_page, extent_size, + extent_offset * extent_size); + + rc = crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, extent_size, + extent_iv, op); if (rc < 0) { printk(KERN_ERR "%s: Error attempting to crypt page with " "page_index = [%ld], extent_offset = [%ld]; " @@ -588,33 +593,6 @@ int ecryptfs_decrypt_page(struct page *page) return rc; } -/** - * crypt_page_offset - * @crypt_stat: The cryptographic context - * @dst_page: The page to write the result into - * @src_page: The page to read from - * @offset: The byte offset into the dst_page and src_page - * @size: The number of bytes of data - * @iv: The initialization vector to use for the crypto operation - * @op: ENCRYPT or DECRYPT to indicate the desired operation - * - * Returns the number of bytes encrypted or decrypted - */ -static int crypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, - struct page *dst_page, struct page *src_page, - int offset, int size, unsigned char *iv, int op) -{ - struct scatterlist src_sg, dst_sg; - - sg_init_table(&src_sg, 1); - sg_init_table(&dst_sg, 1); - - sg_set_page(&src_sg, src_page, size, offset); - sg_set_page(&dst_sg, dst_page, size, offset); - - return crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv, op); -} - #define ECRYPTFS_MAX_SCATTERLIST_LEN 4 /** -- GitLab From 0df5ed65c14e2c36ed842fcff58118662009f1a1 Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Thu, 23 May 2013 12:08:40 -0700 Subject: [PATCH 0738/2900] eCryptfs: Make extent and scatterlist crypt function parameters similar The 'dest' abbreviation is only used in crypt_scatterlist(), while all other functions in crypto.c use 'dst' so dest_sg should be renamed to dst_sg. The crypt_stat parameter is typically the first parameter in internal eCryptfs functions so crypt_stat and dst_page should be swapped in crypt_extent(). Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 9947388ccd8d..46a6f6a4a705 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -330,7 +330,7 @@ static void extent_crypt_complete(struct crypto_async_request *req, int rc) /** * crypt_scatterlist * @crypt_stat: Pointer to the crypt_stat struct to initialize. - * @dest_sg: Destination of the data after performing the crypto operation + * @dst_sg: Destination of the data after performing the crypto operation * @src_sg: Data to be encrypted or decrypted * @size: Length of data * @iv: IV to use @@ -339,7 +339,7 @@ static void extent_crypt_complete(struct crypto_async_request *req, int rc) * Returns the number of bytes encrypted or decrypted; negative value on error */ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, - struct scatterlist *dest_sg, + struct scatterlist *dst_sg, struct scatterlist *src_sg, int size, unsigned char *iv, int op) { @@ -384,7 +384,7 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, crypt_stat->flags |= ECRYPTFS_KEY_SET; } mutex_unlock(&crypt_stat->cs_tfm_mutex); - ablkcipher_request_set_crypt(req, src_sg, dest_sg, size, iv); + ablkcipher_request_set_crypt(req, src_sg, dst_sg, size, iv); rc = op == ENCRYPT ? crypto_ablkcipher_encrypt(req) : crypto_ablkcipher_decrypt(req); if (rc == -EINPROGRESS || rc == -EBUSY) { @@ -413,9 +413,9 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, /** * crypt_extent - * @dst_page: The page to write the result into * @crypt_stat: crypt_stat containing cryptographic context for the * encryption operation + * @dst_page: The page to write the result into * @src_page: The page to read from * @extent_offset: Page extent offset for use in generating IV * @op: ENCRYPT or DECRYPT to indicate the desired operation @@ -424,8 +424,8 @@ static loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, * * Return zero on success; non-zero otherwise */ -static int crypt_extent(struct page *dst_page, - struct ecryptfs_crypt_stat *crypt_stat, +static int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat, + struct page *dst_page, struct page *src_page, unsigned long extent_offset, int op) { @@ -508,7 +508,7 @@ int ecryptfs_encrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = crypt_extent(enc_extent_page, crypt_stat, page, + rc = crypt_extent(crypt_stat, enc_extent_page, page, extent_offset, ENCRYPT); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " @@ -581,7 +581,7 @@ int ecryptfs_decrypt_page(struct page *page) for (extent_offset = 0; extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size); extent_offset++) { - rc = crypt_extent(page, crypt_stat, page, + rc = crypt_extent(crypt_stat, page, page, extent_offset, DECRYPT); if (rc) { printk(KERN_ERR "%s: Error encrypting extent; " -- GitLab From e8b265e8ba322a01bb746504f6f64b5506853eac Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Fri, 7 Jun 2013 20:16:19 +0000 Subject: [PATCH 0739/2900] doc:networking: Fix default value (icmp_ignore_bogus_error_responses). This patch fixes icmp_ignore_bogus_error_responses default value to be 1 instead of FALSE. It is initialized to 1 in icmp_sk_init(). Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 398d0fb1dd0e..9cea5d3b3c50 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -729,7 +729,7 @@ icmp_ignore_bogus_error_responses - BOOLEAN frames. Such violations are normally logged via a kernel warning. If this is set to TRUE, the kernel will not give such warnings, which will avoid log file clutter. - Default: FALSE + Default: 1 icmp_errors_use_inbound_ifaddr - BOOLEAN -- GitLab From afe391ad4b05f8f00ca955e165f3b37b480506b7 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:54:02 +0000 Subject: [PATCH 0740/2900] sh_eth: create initial ID table We are trying to get away from the current driver's scheme of identifying a SoC based on #ifdef's and the platform device ID table matching seems to be a good replacement -- we can use the 'driver_data' field of 'struct platform_device_id' as a pointer to a 'struct sh_eth_cpu_data'. Start by creating the initial table with driver's name as the only entry without the driver data. Check the driver data in the probe() method and if it's not NULL override 'mdp->cd' from it. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 0699b1ec7e32..cf062de40b65 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2519,6 +2519,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) struct net_device *ndev = NULL; struct sh_eth_private *mdp = NULL; struct sh_eth_plat_data *pd = pdev->dev.platform_data; + const struct platform_device_id *id = platform_get_device_id(pdev); /* get base addr */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2582,6 +2583,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev) #else mdp->cd = &sh_eth_my_cpu_data; #endif + if (id->driver_data) + mdp->cd = (struct sh_eth_cpu_data *)id->driver_data; sh_eth_set_default_cpu_data(mdp->cd); /* set function */ @@ -2696,9 +2699,16 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { #define SH_ETH_PM_OPS NULL #endif +static struct platform_device_id sh_eth_id_table[] = { + { CARDNAME }, + { } +}; +MODULE_DEVICE_TABLE(platform, sh_eth_id_table); + static struct platform_driver sh_eth_driver = { .probe = sh_eth_drv_probe, .remove = sh_eth_drv_remove, + .id_table = sh_eth_id_table, .driver = { .name = CARDNAME, .pm = SH_ETH_PM_OPS, -- GitLab From 7bbe150d8c57c59689c8c50fd7b9915f4a7e10da Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:55:08 +0000 Subject: [PATCH 0741/2900] sh_eth: get SH771x support out of #ifdef Get the SH771[02] data in the driver out of #ifdef by adding "sh771x-ether" to the platform driver's ID table. Change the Ether platform device's name in the SH platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/sh/boards/mach-se/770x/setup.c | 8 ++++---- drivers/net/ethernet/renesas/sh_eth.c | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/sh/boards/mach-se/770x/setup.c b/arch/sh/boards/mach-se/770x/setup.c index 9759d6ba7ffb..658326f44df8 100644 --- a/arch/sh/boards/mach-se/770x/setup.c +++ b/arch/sh/boards/mach-se/770x/setup.c @@ -128,8 +128,8 @@ static struct resource sh_eth0_resources[] = { }; static struct platform_device sh_eth0_device = { - .name = "sh-eth", - .id = 0, + .name = "sh771x-ether", + .id = 0, .dev = { .platform_data = PHY_ID, }, @@ -151,8 +151,8 @@ static struct resource sh_eth1_resources[] = { }; static struct platform_device sh_eth1_device = { - .name = "sh-eth", - .id = 1, + .name = "sh771x-ether", + .id = 1, .dev = { .platform_data = PHY_ID, }, diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index cf062de40b65..f26546aa1792 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -690,12 +690,12 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tpauser = 1, .hw_swap = 1, }; -#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +#endif + +static struct sh_eth_cpu_data sh771x_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .tsu = 1, }; -#endif static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd) { @@ -2700,6 +2700,7 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { #endif static struct platform_device_id sh_eth_id_table[] = { + { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, { CARDNAME }, { } }; -- GitLab From c18a79abe31f555ec3b363b5b8c1d003230053b6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:56:05 +0000 Subject: [PATCH 0742/2900] sh_eth: get SH7619 support out of #ifdef Get the SH7619 data in the driver out of #ifdef by adding "sh7619-ether" to the platform driver's ID table. Change the Ether platform device's name in the SH platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/sh/kernel/cpu/sh2/setup-sh7619.c | 4 ++-- drivers/net/ethernet/renesas/sh_eth.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index e0b740c831c7..bb11e1925178 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -124,8 +124,8 @@ static struct resource eth_resources[] = { }; static struct platform_device eth_device = { - .name = "sh-eth", - .id = -1, + .name = "sh7619-ether", + .id = -1, .dev = { .platform_data = (void *)1, }, diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f26546aa1792..e0568a9352e5 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -680,9 +680,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tsu = 1, .select_mii = 1, }; +#endif -#elif defined(CONFIG_CPU_SUBTYPE_SH7619) -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +static struct sh_eth_cpu_data sh7619_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .apr = 1, @@ -690,7 +690,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tpauser = 1, .hw_swap = 1, }; -#endif static struct sh_eth_cpu_data sh771x_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, @@ -2700,6 +2699,7 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { #endif static struct platform_device_id sh_eth_id_table[] = { + { "sh7619-ether", (kernel_ulong_t)&sh7619_data }, { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, { CARDNAME }, { } -- GitLab From e5c9b4cd665106d9b5397114ea81a53059410b6a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:57:12 +0000 Subject: [PATCH 0743/2900] sh_eth: get R8A7740 support out of #ifdef Get the R8A7740 code/data in the driver out of #ifdef by adding "r8a7740-gether" to the platform driver's ID table. Change the GEther platform device's name in the ARM platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/arm/mach-shmobile/board-armadillo800eva.c | 2 +- arch/arm/mach-shmobile/clock-r8a7740.c | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 16 +++++++--------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index b85b2882dbd0..2b04c8011e13 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -377,7 +377,7 @@ static struct resource sh_eth_resources[] = { }; static struct platform_device sh_eth_device = { - .name = "sh-eth", + .name = "r8a7740-gether", .id = -1, .dev = { .platform_data = &sh_eth_platdata, diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index c0d39aa6de50..ae93f94d15bd 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -591,7 +591,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]), CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), - CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]), + CLKDEV_DEV_ID("r8a7740-gether", &mstp_clks[MSTP309]), CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index e0568a9352e5..da620ecd4151 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -619,11 +619,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .irq_flags = IRQF_SHARED, #endif }; +#endif - -#elif defined(CONFIG_ARCH_R8A7740) - -static void sh_eth_chip_reset(struct net_device *ndev) +static void sh_eth_chip_reset_r8a7740(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -634,7 +632,7 @@ static void sh_eth_chip_reset(struct net_device *ndev) sh_eth_select_mii(ndev); } -static void sh_eth_set_rate(struct net_device *ndev) +static void sh_eth_set_rate_gether(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -654,10 +652,10 @@ static void sh_eth_set_rate(struct net_device *ndev) } /* R8A7740 */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { - .chip_reset = sh_eth_chip_reset, +static struct sh_eth_cpu_data r8a7740_data = { + .chip_reset = sh_eth_chip_reset_r8a7740, .set_duplex = sh_eth_set_duplex, - .set_rate = sh_eth_set_rate, + .set_rate = sh_eth_set_rate_gether, .ecsr_value = ECSR_ICD | ECSR_MPD, .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, @@ -680,7 +678,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tsu = 1, .select_mii = 1, }; -#endif static struct sh_eth_cpu_data sh7619_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, @@ -2701,6 +2698,7 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { static struct platform_device_id sh_eth_id_table[] = { { "sh7619-ether", (kernel_ulong_t)&sh7619_data }, { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, + { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data }, { CARDNAME }, { } }; -- GitLab From f5d12767c8fd77e29d3d6771de59fd9ac3e540bb Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:58:18 +0000 Subject: [PATCH 0744/2900] sh_eth: get SH77{34|63} support out of #ifdef Get the SH77{34|63} specific code/data in the driver out of #ifdef by adding "sh7734-gether" and "sh7763-gether" to the platform driver's ID table. Note that we have to split the 'struct sh_eth_cpu_data' instance into two due to #ifdef inside it; note that we can kill the duplicate sh_eth_set_rate_gether(). Change the GEther platform device's name in the SH platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/sh/boards/board-espt.c | 2 +- arch/sh/boards/mach-sh7763rdp/setup.c | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7734.c | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 67 ++++++++++++++------------ 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c index d71a0bcf8145..4d94dff9015c 100644 --- a/arch/sh/boards/board-espt.c +++ b/arch/sh/boards/board-espt.c @@ -85,7 +85,7 @@ static struct sh_eth_plat_data sh7763_eth_pdata = { }; static struct platform_device espt_eth_device = { - .name = "sh-eth", + .name = "sh7763-gether", .resource = sh_eth_resources, .num_resources = ARRAY_SIZE(sh_eth_resources), .dev = { diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c index b7c75298dfb5..50ba481fa240 100644 --- a/arch/sh/boards/mach-sh7763rdp/setup.c +++ b/arch/sh/boards/mach-sh7763rdp/setup.c @@ -93,7 +93,7 @@ static struct sh_eth_plat_data sh7763_eth_pdata = { }; static struct platform_device sh7763rdp_eth_device = { - .name = "sh-eth", + .name = "sh7763-gether", .resource = sh_eth_resources, .num_resources = ARRAY_SIZE(sh_eth_resources), .dev = { diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c index deb683abacf0..ed9501519ab3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c @@ -238,7 +238,7 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("adc0", &mstp_clks[MSTP313]), CLKDEV_CON_ID("mtu0", &mstp_clks[MSTP312]), CLKDEV_CON_ID("iebus0", &mstp_clks[MSTP304]), - CLKDEV_DEV_ID("sh-eth.0", &mstp_clks[MSTP114]), + CLKDEV_DEV_ID("sh7734-gether.0", &mstp_clks[MSTP114]), CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP303]), CLKDEV_CON_ID("hif0", &mstp_clks[MSTP302]), CLKDEV_CON_ID("stif0", &mstp_clks[MSTP301]), diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index da620ecd4151..6d44a43e5884 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -556,8 +556,7 @@ static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) else return &sh_eth_my_cpu_data; } - -#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763) +#endif static void sh_eth_chip_reset(struct net_device *ndev) { @@ -568,7 +567,7 @@ static void sh_eth_chip_reset(struct net_device *ndev) mdelay(1); } -static void sh_eth_set_rate(struct net_device *ndev) +static void sh_eth_set_rate_gether(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -587,11 +586,40 @@ static void sh_eth_set_rate(struct net_device *ndev) } } -/* sh7763 */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +/* SH7734 */ +static struct sh_eth_cpu_data sh7734_data = { .chip_reset = sh_eth_chip_reset, .set_duplex = sh_eth_set_duplex, - .set_rate = sh_eth_set_rate, + .set_rate = sh_eth_set_rate_gether, + + .ecsr_value = ECSR_ICD | ECSR_MPD, + .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, + .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, + + .tx_check = EESR_TC1 | EESR_FTC, + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ + EESR_ECI, + .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ + EESR_TFE, + + .apr = 1, + .mpr = 1, + .tpauser = 1, + .bculr = 1, + .hw_swap = 1, + .no_trimd = 1, + .no_ade = 1, + .tsu = 1, + .hw_crc = 1, + .select_mii = 1, +}; + +/* SH7763 */ +static struct sh_eth_cpu_data sh7763_data = { + .chip_reset = sh_eth_chip_reset, + .set_duplex = sh_eth_set_duplex, + .set_rate = sh_eth_set_rate_gether, .ecsr_value = ECSR_ICD | ECSR_MPD, .ecsipr_value = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP, @@ -612,14 +640,8 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .no_trimd = 1, .no_ade = 1, .tsu = 1, -#if defined(CONFIG_CPU_SUBTYPE_SH7734) - .hw_crc = 1, - .select_mii = 1, -#else .irq_flags = IRQF_SHARED, -#endif }; -#endif static void sh_eth_chip_reset_r8a7740(struct net_device *ndev) { @@ -632,25 +654,6 @@ static void sh_eth_chip_reset_r8a7740(struct net_device *ndev) sh_eth_select_mii(ndev); } -static void sh_eth_set_rate_gether(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - - switch (mdp->speed) { - case 10: /* 10BASE */ - sh_eth_write(ndev, GECMR_10, GECMR); - break; - case 100:/* 100BASE */ - sh_eth_write(ndev, GECMR_100, GECMR); - break; - case 1000: /* 1000BASE */ - sh_eth_write(ndev, GECMR_1000, GECMR); - break; - default: - break; - } -} - /* R8A7740 */ static struct sh_eth_cpu_data r8a7740_data = { .chip_reset = sh_eth_chip_reset_r8a7740, @@ -2698,6 +2701,8 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { static struct platform_device_id sh_eth_id_table[] = { { "sh7619-ether", (kernel_ulong_t)&sh7619_data }, { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, + { "sh7734-gether", (kernel_ulong_t)&sh7734_data }, + { "sh7763-gether", (kernel_ulong_t)&sh7763_data }, { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data }, { CARDNAME }, { } -- GitLab From 24549e2a0f33628b5160eac16c6aebf1cfaf22f1 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 13:59:21 +0000 Subject: [PATCH 0745/2900] sh_eth: get SH7757 support out of #ifdef Get the SH7757 code/data in the driver out of #ifdef by adding "sh7757-ether" and "sh7757-gether" to the platform driver's ID table. Note that we can remove SH_ETH_HAS_BOTH_MODULES and sh_eth_get_cpu_data(). Change the Ether/GEther platform devices' names in the SH platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/sh/boards/board-sh7757lcr.c | 8 ++++---- drivers/net/ethernet/renesas/sh_eth.c | 28 ++++++++------------------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index 41f86702eb9f..4f114d1cd019 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -82,7 +82,7 @@ static struct sh_eth_plat_data sh7757_eth0_pdata = { }; static struct platform_device sh7757_eth0_device = { - .name = "sh-eth", + .name = "sh7757-ether", .resource = sh_eth0_resources, .id = 0, .num_resources = ARRAY_SIZE(sh_eth0_resources), @@ -111,7 +111,7 @@ static struct sh_eth_plat_data sh7757_eth1_pdata = { }; static struct platform_device sh7757_eth1_device = { - .name = "sh-eth", + .name = "sh7757-ether", .resource = sh_eth1_resources, .id = 1, .num_resources = ARRAY_SIZE(sh_eth1_resources), @@ -157,7 +157,7 @@ static struct sh_eth_plat_data sh7757_eth_giga0_pdata = { }; static struct platform_device sh7757_eth_giga0_device = { - .name = "sh-eth", + .name = "sh7757-gether", .resource = sh_eth_giga0_resources, .id = 2, .num_resources = ARRAY_SIZE(sh_eth_giga0_resources), @@ -192,7 +192,7 @@ static struct sh_eth_plat_data sh7757_eth_giga1_pdata = { }; static struct platform_device sh7757_eth_giga1_device = { - .name = "sh-eth", + .name = "sh7757-gether", .resource = sh_eth_giga1_resources, .id = 3, .num_resources = ARRAY_SIZE(sh_eth_giga1_resources), diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 6d44a43e5884..9860fc028f3d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -431,10 +431,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .rpadir = 1, .rpadir_value = 0x00020000, /* NET_IP_ALIGN assumed to be 2 */ }; -#elif defined(CONFIG_CPU_SUBTYPE_SH7757) -#define SH_ETH_HAS_BOTH_MODULES 1 +#endif -static void sh_eth_set_rate(struct net_device *ndev) +static void sh_eth_set_rate_sh7757(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -451,9 +450,9 @@ static void sh_eth_set_rate(struct net_device *ndev) } /* SH7757 */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { - .set_duplex = sh_eth_set_duplex, - .set_rate = sh_eth_set_rate, +static struct sh_eth_cpu_data sh7757_data = { + .set_duplex = sh_eth_set_duplex, + .set_rate = sh_eth_set_rate_sh7757, .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .rmcr_value = 0x00000001, @@ -518,7 +517,7 @@ static void sh_eth_set_rate_giga(struct net_device *ndev) } /* SH7757(GETHERC) */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { +static struct sh_eth_cpu_data sh7757_data_giga = { .chip_reset = sh_eth_chip_reset_giga, .set_duplex = sh_eth_set_duplex, .set_rate = sh_eth_set_rate_giga, @@ -549,15 +548,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { .tsu = 1, }; -static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp) -{ - if (sh_eth_is_gether(mdp)) - return &sh_eth_my_cpu_data_giga; - else - return &sh_eth_my_cpu_data; -} -#endif - static void sh_eth_chip_reset(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -2577,11 +2567,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) mdp->reg_offset = sh_eth_get_register_offset(pd->register_type); /* set cpu data */ -#if defined(SH_ETH_HAS_BOTH_MODULES) - mdp->cd = sh_eth_get_cpu_data(mdp); -#else mdp->cd = &sh_eth_my_cpu_data; -#endif if (id->driver_data) mdp->cd = (struct sh_eth_cpu_data *)id->driver_data; sh_eth_set_default_cpu_data(mdp->cd); @@ -2702,6 +2688,8 @@ static struct platform_device_id sh_eth_id_table[] = { { "sh7619-ether", (kernel_ulong_t)&sh7619_data }, { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, { "sh7734-gether", (kernel_ulong_t)&sh7734_data }, + { "sh7757-ether", (kernel_ulong_t)&sh7757_data }, + { "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga }, { "sh7763-gether", (kernel_ulong_t)&sh7763_data }, { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data }, { CARDNAME }, -- GitLab From 9c3beaabb951d672b1534c7f56f84054b088f879 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 14:03:37 +0000 Subject: [PATCH 0746/2900] sh_eth: get SH7724 support out of #ifdef Get the SH7724 code/data in the driver out of #ifdef by adding "r8a7724-ether" to the platform driver's ID table. Change the Ether platform device's name in the SH platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/sh/boards/mach-ecovec24/setup.c | 4 ++-- arch/sh/boards/mach-se/7724/setup.c | 4 ++-- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 764530c85aa9..61fade0ffa96 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -165,8 +165,8 @@ static struct sh_eth_plat_data sh_eth_plat = { }; static struct platform_device sh_eth_device = { - .name = "sh-eth", - .id = 0, + .name = "sh7724-ether", + .id = 0, .dev = { .platform_data = &sh_eth_plat, }, diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 4010e63e82d8..b70180ef3e29 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -380,8 +380,8 @@ static struct sh_eth_plat_data sh_eth_plat = { }; static struct platform_device sh_eth_device = { - .name = "sh-eth", - .id = 0, + .name = "sh7724-ether", + .id = 0, .dev = { .platform_data = &sh_eth_plat, }, diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 5f30f805d2f2..0128af3399b7 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -329,7 +329,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC0]), CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[HWBLK_IIC1]), CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[HWBLK_MMC]), - CLKDEV_DEV_ID("sh-eth.0", &mstp_clks[HWBLK_ETHER]), + CLKDEV_DEV_ID("sh7724-ether.0", &mstp_clks[HWBLK_ETHER]), CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]), CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]), CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]), diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 9860fc028f3d..143e22e1b329 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -392,9 +392,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tpauser = 1, .hw_swap = 1, }; -#elif defined(CONFIG_CPU_SUBTYPE_SH7724) +#endif -static void sh_eth_set_rate(struct net_device *ndev) +static void sh_eth_set_rate_sh7724(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -411,9 +411,9 @@ static void sh_eth_set_rate(struct net_device *ndev) } /* SH7724 */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +static struct sh_eth_cpu_data sh7724_data = { .set_duplex = sh_eth_set_duplex, - .set_rate = sh_eth_set_rate, + .set_rate = sh_eth_set_rate_sh7724, .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD, .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP, @@ -431,7 +431,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .rpadir = 1, .rpadir_value = 0x00020000, /* NET_IP_ALIGN assumed to be 2 */ }; -#endif static void sh_eth_set_rate_sh7757(struct net_device *ndev) { @@ -2687,6 +2686,7 @@ static const struct dev_pm_ops sh_eth_dev_pm_ops = { static struct platform_device_id sh_eth_id_table[] = { { "sh7619-ether", (kernel_ulong_t)&sh7619_data }, { "sh771x-ether", (kernel_ulong_t)&sh771x_data }, + { "sh7724-ether", (kernel_ulong_t)&sh7724_data }, { "sh7734-gether", (kernel_ulong_t)&sh7734_data }, { "sh7757-ether", (kernel_ulong_t)&sh7757_data }, { "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga }, -- GitLab From 589ebdef7e3107401bf96a9c660753d397329ee9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 14:05:59 +0000 Subject: [PATCH 0747/2900] sh_eth: get R8A777x support out of #ifdef Get the R-Car code/data in the driver out of #ifdef by adding "r8a777x-ether" to the platfrom driver's ID table; since it's the last #ifdef, we remove CARDNAME from the ID table and no longer check the driver data before assigning it to 'mdp->cd'... Change the Ether platform device's name in the ARM platform code accordingly. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- arch/arm/mach-shmobile/clock-r8a7778.c | 2 +- arch/arm/mach-shmobile/clock-r8a7779.c | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 14 +++++--------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c index cd6855290b1f..9614b07254b2 100644 --- a/arch/arm/mach-shmobile/clock-r8a7778.c +++ b/arch/arm/mach-shmobile/clock-r8a7778.c @@ -77,7 +77,7 @@ static struct clk mstp_clks[MSTP_NR] = { static struct clk_lookup lookups[] = { /* MSTP32 clocks */ - CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ + CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */ diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 31d5cd4d9787..2f7e5245a690 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -163,7 +163,7 @@ static struct clk_lookup lookups[] = { /* MSTP32 clocks */ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */ - CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP114]), /* Ether */ + CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */ CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */ CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */ CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */ diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 143e22e1b329..cff697118119 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -356,8 +356,7 @@ static void __maybe_unused sh_eth_set_duplex(struct net_device *ndev) } /* There is CPU dependent code */ -#if defined(CONFIG_ARCH_R8A7778) || defined(CONFIG_ARCH_R8A7779) -static void sh_eth_set_rate(struct net_device *ndev) +static void sh_eth_set_rate_r8a777x(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); @@ -374,9 +373,9 @@ static void sh_eth_set_rate(struct net_device *ndev) } /* R8A7778/9 */ -static struct sh_eth_cpu_data sh_eth_my_cpu_data = { +static struct sh_eth_cpu_data r8a777x_data = { .set_duplex = sh_eth_set_duplex, - .set_rate = sh_eth_set_rate, + .set_rate = sh_eth_set_rate_r8a777x, .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD, .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP, @@ -392,7 +391,6 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .tpauser = 1, .hw_swap = 1, }; -#endif static void sh_eth_set_rate_sh7724(struct net_device *ndev) { @@ -2566,9 +2564,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) mdp->reg_offset = sh_eth_get_register_offset(pd->register_type); /* set cpu data */ - mdp->cd = &sh_eth_my_cpu_data; - if (id->driver_data) - mdp->cd = (struct sh_eth_cpu_data *)id->driver_data; + mdp->cd = (struct sh_eth_cpu_data *)id->driver_data; sh_eth_set_default_cpu_data(mdp->cd); /* set function */ @@ -2692,7 +2688,7 @@ static struct platform_device_id sh_eth_id_table[] = { { "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga }, { "sh7763-gether", (kernel_ulong_t)&sh7763_data }, { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data }, - { CARDNAME }, + { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data }, { } }; MODULE_DEVICE_TABLE(platform, sh_eth_id_table); -- GitLab From eb770bf430bc1d4e1d23af353a80cfae2b237e66 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 7 Jun 2013 14:07:13 +0000 Subject: [PATCH 0748/2900] sh_eth: remove dependencies from Kconfig Since dependence on the certain SoCs is no longer necessary to compile the driver, remove the dependency list from its Kconfig entry which is a popular demand anyway... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/Kconfig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index bed9841d728c..267eac054fa4 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -4,12 +4,6 @@ config SH_ETH tristate "Renesas SuperH Ethernet support" - depends on (SUPERH || ARCH_SHMOBILE) && \ - (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \ - CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \ - CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ - CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || \ - ARCH_R8A7778 || ARCH_R8A7779) select CRC32 select NET_CORE select MII -- GitLab From e403d295817cf9f8be3110eb7ee1a03981287495 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 7 Jun 2013 23:40:41 -0700 Subject: [PATCH 0749/2900] sh_eth: Fix warnings on 64-bit. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't cast a plain integer to a pointer. drivers/net/ethernet/renesas/sh_eth.c: In function ‘sh_eth_chip_reset_giga’: drivers/net/ethernet/renesas/sh_eth.c:482:22: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/net/ethernet/renesas/sh_eth.c:483:22: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/net/ethernet/renesas/sh_eth.c:492:22: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/net/ethernet/renesas/sh_eth.c:493:22: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index cff697118119..43d8490cfe0d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -469,7 +469,7 @@ static struct sh_eth_cpu_data sh7757_data = { .rpadir_value = 2 << 16, }; -#define SH_GIGA_ETH_BASE 0xfee00000 +#define SH_GIGA_ETH_BASE 0xfee00000UL #define GIGA_MALR(port) (SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8) #define GIGA_MAHR(port) (SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0) static void sh_eth_chip_reset_giga(struct net_device *ndev) -- GitLab From ed0483fa06e0efb86a82e382a00dbad02b62807c Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:33 +0000 Subject: [PATCH 0750/2900] macvtap: fix a possible race between queue selection and changing queues Complier may generate codes that re-read the vlan->numvtaps during macvtap_get_queue(). This may lead a race if vlan->numvtaps were changed in the same time and which can lead unexpected result (e.g. very huge value). We need prevent the compiler from generating such codes by adding an ACCESS_ONCE() to make sure vlan->numvtaps were only read once. Acked-by: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 68efb91a5633..5e485e307424 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -172,7 +172,7 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, { struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *tap = NULL; - int numvtaps = vlan->numvtaps; + int numvtaps = ACCESS_ONCE(vlan->numvtaps); __u32 rxq; if (!numvtaps) -- GitLab From 89cee917deb5bf0dc9da269a38622588d06cb6be Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:34 +0000 Subject: [PATCH 0751/2900] macvtap: do not add self to waitqueue if doing a nonblock read There's no need to add self to waitqueue if doing a nonblock read. This could help to avoid the spinlock contention. Acked-by: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5e485e307424..8949631c080c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -845,7 +845,9 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, ssize_t ret = 0; while (len) { - prepare_to_wait(sk_sleep(&q->sk), &wait, TASK_INTERRUPTIBLE); + if (!noblock) + prepare_to_wait(sk_sleep(&q->sk), &wait, + TASK_INTERRUPTIBLE); /* Read frames from the queue */ skb = skb_dequeue(&q->sk.sk_receive_queue); @@ -867,7 +869,8 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, break; } - finish_wait(sk_sleep(&q->sk), &wait); + if (!noblock) + finish_wait(sk_sleep(&q->sk), &wait); return ret; } -- GitLab From 1d2f41ed23343e083566339574807ca7ea75dbba Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:35 +0000 Subject: [PATCH 0752/2900] macvlan: switch to use IS_ENABLED() Acked-by: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- include/linux/if_macvlan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 84dde1dd1da4..e47ad46a477c 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -8,7 +8,7 @@ #include #include -#if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE) +#if IS_ENABLED(CONFIG_MACVTAP) struct socket *macvtap_get_socket(struct file *); #else #include -- GitLab From 8f475a318aaa37f0168a8ab99f2faa251e5638de Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:36 +0000 Subject: [PATCH 0753/2900] macvtap: introduce macvtap_get_vlan() Factor out the device holding logic to a macvtap_get_vlan(), this will be also used by multiqueue API. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 8949631c080c..d18130b3fe0d 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -893,6 +893,24 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, return ret; } +static struct macvlan_dev *macvtap_get_vlan(struct macvtap_queue *q) +{ + struct macvlan_dev *vlan; + + rcu_read_lock_bh(); + vlan = rcu_dereference_bh(q->vlan); + if (vlan) + dev_hold(vlan->dev); + rcu_read_unlock_bh(); + + return vlan; +} + +static void macvtap_put_vlan(struct macvlan_dev *vlan) +{ + dev_put(vlan->dev); +} + /* * provide compatibility with generic tun/tap interface */ @@ -924,12 +942,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return ret; case TUNGETIFF: - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); - if (vlan) - dev_hold(vlan->dev); - rcu_read_unlock_bh(); - + vlan = macvtap_get_vlan(q); if (!vlan) return -ENOLINK; @@ -937,7 +950,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) || put_user(q->flags, &ifr->ifr_flags)) ret = -EFAULT; - dev_put(vlan->dev); + macvtap_put_vlan(vlan); return ret; case TUNGETFEATURES: -- GitLab From f0afce01aa639e5164cf73f063b81a8b95619c3a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:37 +0000 Subject: [PATCH 0754/2900] macvlan: change the max number of queues to 16 Macvtap should be at least compatible with tap, so change the max number to 16. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/linux/if_macvlan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index e47ad46a477c..62d8bda67874 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -50,7 +50,7 @@ struct macvlan_pcpu_stats { * Maximum times a macvtap device can be opened. This can be used to * configure the number of receive queue, e.g. for multiqueue virtio. */ -#define MAX_MACVTAP_QUEUES (NR_CPUS < 16 ? NR_CPUS : 16) +#define MAX_MACVTAP_QUEUES 16 #define MACVLAN_MC_FILTER_BITS 8 #define MACVLAN_MC_FILTER_SZ (1 << MACVLAN_MC_FILTER_BITS) -- GitLab From 376b1aabe1f53aad80615d05ddb8c43670be6a5c Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:38 +0000 Subject: [PATCH 0755/2900] macvtap: eliminate linear search Linear search were used in both get_slot() and macvtap_get_queue(), this is because: - macvtap didn't reshuffle the array of taps when create or destroy a queue, so when adding a new queue, macvtap must do linear search to find a location for the new queue. This will also complicate the TUNSETQUEUE implementation for multiqueue API. - the queue itself didn't track the queue index, so the we must do a linear search in the array to find the location of a existed queue. The solution is straightforward: reshuffle the array and introduce a queue_index to macvtap_queue. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 64 ++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 44 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index d18130b3fe0d..5ccba99b15f4 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -44,6 +44,7 @@ struct macvtap_queue { struct macvlan_dev __rcu *vlan; struct file *file; unsigned int flags; + u16 queue_index; }; static struct proto macvtap_proto = { @@ -84,30 +85,10 @@ static const struct proto_ops macvtap_socket_ops; */ static DEFINE_SPINLOCK(macvtap_lock); -/* - * get_slot: return a [unused/occupied] slot in vlan->taps[]: - * - if 'q' is NULL, return the first empty slot; - * - otherwise, return the slot this pointer occupies. - */ -static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q) -{ - int i; - - for (i = 0; i < MAX_MACVTAP_QUEUES; i++) { - if (rcu_dereference_protected(vlan->taps[i], - lockdep_is_held(&macvtap_lock)) == q) - return i; - } - - /* Should never happen */ - BUG_ON(1); -} - static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); - int index; int err = -EBUSY; spin_lock(&macvtap_lock); @@ -115,12 +96,12 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, goto out; err = 0; - index = get_slot(vlan, NULL); rcu_assign_pointer(q->vlan, vlan); - rcu_assign_pointer(vlan->taps[index], q); + rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); sock_hold(&q->sk); q->file = file; + q->queue_index = vlan->numvtaps; file->private_data = q; vlan->numvtaps++; @@ -140,15 +121,22 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, */ static void macvtap_put_queue(struct macvtap_queue *q) { + struct macvtap_queue *nq; struct macvlan_dev *vlan; spin_lock(&macvtap_lock); vlan = rcu_dereference_protected(q->vlan, lockdep_is_held(&macvtap_lock)); if (vlan) { - int index = get_slot(vlan, q); + int index = q->queue_index; + BUG_ON(index >= vlan->numvtaps); + + nq = rcu_dereference_protected(vlan->taps[vlan->numvtaps - 1], + lockdep_is_held(&macvtap_lock)); + rcu_assign_pointer(vlan->taps[index], nq); + nq->queue_index = index; - RCU_INIT_POINTER(vlan->taps[index], NULL); + RCU_INIT_POINTER(vlan->taps[vlan->numvtaps - 1], NULL); RCU_INIT_POINTER(q->vlan, NULL); sock_put(&q->sk); --vlan->numvtaps; @@ -182,8 +170,7 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, rxq = skb_get_rxhash(skb); if (rxq) { tap = rcu_dereference(vlan->taps[rxq % numvtaps]); - if (tap) - goto out; + goto out; } if (likely(skb_rx_queue_recorded(skb))) { @@ -193,17 +180,10 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, rxq -= numvtaps; tap = rcu_dereference(vlan->taps[rxq]); - if (tap) - goto out; - } - - /* Everything failed - find first available queue */ - for (rxq = 0; rxq < MAX_MACVTAP_QUEUES; rxq++) { - tap = rcu_dereference(vlan->taps[rxq]); - if (tap) - break; + goto out; } + tap = rcu_dereference(vlan->taps[0]); out: return tap; } @@ -219,19 +199,15 @@ static void macvtap_del_queues(struct net_device *dev) struct macvtap_queue *q, *qlist[MAX_MACVTAP_QUEUES]; int i, j = 0; - /* macvtap_put_queue can free some slots, so go through all slots */ spin_lock(&macvtap_lock); - for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) { + for (i = 0; i < vlan->numvtaps; i++) { q = rcu_dereference_protected(vlan->taps[i], lockdep_is_held(&macvtap_lock)); - if (q) { - qlist[j++] = q; - RCU_INIT_POINTER(vlan->taps[i], NULL); - RCU_INIT_POINTER(q->vlan, NULL); - vlan->numvtaps--; - } + BUG_ON(q == NULL); + qlist[j++] = q; + RCU_INIT_POINTER(vlan->taps[i], NULL); + RCU_INIT_POINTER(q->vlan, NULL); } - BUG_ON(vlan->numvtaps != 0); /* guarantee that any future macvtap_set_queue will fail */ vlan->numvtaps = MAX_MACVTAP_QUEUES; spin_unlock(&macvtap_lock); -- GitLab From 815f236d622721b54f3963ba59dad98b02cdeabf Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:39 +0000 Subject: [PATCH 0756/2900] macvtap: add TUNSETQUEUE ioctl This patch adds TUNSETQUEUE ioctl to let userspace can temporarily disable or enable a queue of macvtap. This is used to be compatible at API layer of tuntap to simplify the userspace to manage the queues. This is done through introducing a linked list to track all taps while using vlan->taps array to only track active taps. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 135 +++++++++++++++++++++++++++++++------ include/linux/if_macvlan.h | 4 ++ 2 files changed, 120 insertions(+), 19 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5ccba99b15f4..d2d1d5578b61 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -45,6 +45,8 @@ struct macvtap_queue { struct file *file; unsigned int flags; u16 queue_index; + bool enabled; + struct list_head next; }; static struct proto macvtap_proto = { @@ -85,14 +87,36 @@ static const struct proto_ops macvtap_socket_ops; */ static DEFINE_SPINLOCK(macvtap_lock); -static int macvtap_set_queue(struct net_device *dev, struct file *file, +static int macvtap_enable_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + int err = -EINVAL; + + spin_lock(&macvtap_lock); + + if (q->enabled) + goto out; + + err = 0; + rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); + q->queue_index = vlan->numvtaps; + q->enabled = true; + + vlan->numvtaps++; +out: + spin_unlock(&macvtap_lock); + return err; +} + +static int macvtap_set_queue(struct net_device *dev, struct file *file, + struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); int err = -EBUSY; spin_lock(&macvtap_lock); - if (vlan->numvtaps == MAX_MACVTAP_QUEUES) + if (vlan->numqueues == MAX_MACVTAP_QUEUES) goto out; err = 0; @@ -102,15 +126,57 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, q->file = file; q->queue_index = vlan->numvtaps; + q->enabled = true; file->private_data = q; + list_add_tail(&q->next, &vlan->queue_list); vlan->numvtaps++; + vlan->numqueues++; out: spin_unlock(&macvtap_lock); return err; } +static int __macvtap_disable_queue(struct macvtap_queue *q) +{ + struct macvlan_dev *vlan; + struct macvtap_queue *nq; + + vlan = rcu_dereference_protected(q->vlan, + lockdep_is_held(&macvtap_lock)); + + if (!q->enabled) + return -EINVAL; + + if (vlan) { + int index = q->queue_index; + BUG_ON(index >= vlan->numvtaps); + nq = rcu_dereference_protected(vlan->taps[vlan->numvtaps - 1], + lockdep_is_held(&macvtap_lock)); + nq->queue_index = index; + + rcu_assign_pointer(vlan->taps[index], nq); + RCU_INIT_POINTER(vlan->taps[vlan->numvtaps - 1], NULL); + q->enabled = false; + + vlan->numvtaps--; + } + + return 0; +} + +static int macvtap_disable_queue(struct macvtap_queue *q) +{ + int err; + + spin_lock(&macvtap_lock); + err = __macvtap_disable_queue(q); + spin_unlock(&macvtap_lock); + + return err; +} + /* * The file owning the queue got closed, give up both * the reference that the files holds as well as the @@ -121,25 +187,19 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, */ static void macvtap_put_queue(struct macvtap_queue *q) { - struct macvtap_queue *nq; struct macvlan_dev *vlan; spin_lock(&macvtap_lock); vlan = rcu_dereference_protected(q->vlan, lockdep_is_held(&macvtap_lock)); if (vlan) { - int index = q->queue_index; - BUG_ON(index >= vlan->numvtaps); - - nq = rcu_dereference_protected(vlan->taps[vlan->numvtaps - 1], - lockdep_is_held(&macvtap_lock)); - rcu_assign_pointer(vlan->taps[index], nq); - nq->queue_index = index; + if (q->enabled) + BUG_ON(__macvtap_disable_queue(q)); - RCU_INIT_POINTER(vlan->taps[vlan->numvtaps - 1], NULL); + vlan->numqueues--; RCU_INIT_POINTER(q->vlan, NULL); sock_put(&q->sk); - --vlan->numvtaps; + list_del_init(&q->next); } spin_unlock(&macvtap_lock); @@ -160,6 +220,11 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, { struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *tap = NULL; + /* Access to taps array is protected by rcu, but access to numvtaps + * isn't. Below we use it to lookup a queue, but treat it as a hint + * and validate that the result isn't NULL - in case we are + * racing against queue removal. + */ int numvtaps = ACCESS_ONCE(vlan->numvtaps); __u32 rxq; @@ -196,18 +261,22 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, static void macvtap_del_queues(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); - struct macvtap_queue *q, *qlist[MAX_MACVTAP_QUEUES]; + struct macvtap_queue *q, *tmp, *qlist[MAX_MACVTAP_QUEUES]; int i, j = 0; spin_lock(&macvtap_lock); - for (i = 0; i < vlan->numvtaps; i++) { - q = rcu_dereference_protected(vlan->taps[i], - lockdep_is_held(&macvtap_lock)); - BUG_ON(q == NULL); + list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) { + list_del_init(&q->next); qlist[j++] = q; - RCU_INIT_POINTER(vlan->taps[i], NULL); RCU_INIT_POINTER(q->vlan, NULL); + if (q->enabled) + vlan->numvtaps--; + vlan->numqueues--; } + for (i = 0; i < vlan->numvtaps; i++) + RCU_INIT_POINTER(vlan->taps[i], NULL); + BUG_ON(vlan->numvtaps); + BUG_ON(vlan->numqueues); /* guarantee that any future macvtap_set_queue will fail */ vlan->numvtaps = MAX_MACVTAP_QUEUES; spin_unlock(&macvtap_lock); @@ -298,6 +367,9 @@ static int macvtap_newlink(struct net *src_net, struct nlattr *tb[], struct nlattr *data[]) { + struct macvlan_dev *vlan = netdev_priv(dev); + INIT_LIST_HEAD(&vlan->queue_list); + /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ @@ -887,6 +959,25 @@ static void macvtap_put_vlan(struct macvlan_dev *vlan) dev_put(vlan->dev); } +static int macvtap_ioctl_set_queue(struct file *file, unsigned int flags) +{ + struct macvtap_queue *q = file->private_data; + struct macvlan_dev *vlan; + int ret; + + vlan = macvtap_get_vlan(q); + if (!vlan) + return -EINVAL; + + if (flags & IFF_ATTACH_QUEUE) + ret = macvtap_enable_queue(vlan->dev, file, q); + else if (flags & IFF_DETACH_QUEUE) + ret = macvtap_disable_queue(q); + + macvtap_put_vlan(vlan); + return ret; +} + /* * provide compatibility with generic tun/tap interface */ @@ -910,7 +1001,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return -EFAULT; ret = 0; - if ((u & ~IFF_VNET_HDR) != (IFF_NO_PI | IFF_TAP)) + if ((u & ~(IFF_VNET_HDR | IFF_MULTI_QUEUE)) != + (IFF_NO_PI | IFF_TAP)) ret = -EINVAL; else q->flags = u; @@ -929,6 +1021,11 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, macvtap_put_vlan(vlan); return ret; + case TUNSETQUEUE: + if (get_user(u, &ifr->ifr_flags)) + return -EFAULT; + return macvtap_ioctl_set_queue(file, u); + case TUNGETFEATURES: if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR, up)) return -EFAULT; diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 62d8bda67874..19121331a5ed 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -69,8 +69,12 @@ struct macvlan_dev { u16 flags; int (*receive)(struct sk_buff *skb); int (*forward)(struct net_device *dev, struct sk_buff *skb); + /* This array tracks active taps. */ struct macvtap_queue *taps[MAX_MACVTAP_QUEUES]; + /* This list tracks all taps (both enabled and disabled) */ + struct list_head queue_list; int numvtaps; + int numqueues; int minor; }; -- GitLab From df09b36f2225b84571b3d5eda2e2683412320713 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jun 2013 23:54:40 +0000 Subject: [PATCH 0757/2900] macvtap: enable multiqueue flag To notify the userspace about our capability of multiqueue. Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index d2d1d5578b61..992151ce08a4 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -31,10 +31,6 @@ * macvtap_proto is used to allocate queues through the sock allocation * mechanism. * - * TODO: multiqueue support is currently not implemented, even though - * macvtap is basically prepared for that. We will need to add this - * here as well as in virtio-net and qemu to get line rate on 10gbit - * adapters from a guest. */ struct macvtap_queue { struct sock sk; @@ -1027,7 +1023,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return macvtap_ioctl_set_queue(file, u); case TUNGETFEATURES: - if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR, up)) + if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR | + IFF_MULTI_QUEUE, up)) return -EFAULT; return 0; -- GitLab From d0d04b78f403b0bcfe03315e16b50d196610720d Mon Sep 17 00:00:00 2001 From: Zhouping Liu Date: Thu, 16 May 2013 11:36:23 +0800 Subject: [PATCH 0758/2900] mm, slab: moved kmem_cache_alloc_node comment to correct place After several fixing about kmem_cache_alloc_node(), its comment was splitted. This patch moved it on top of kmem_cache_alloc_node() definition. Signed-off-by: Zhouping Liu Signed-off-by: Pekka Enberg --- mm/slab.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index a98f8db93670..273a5ac2ade3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3340,18 +3340,6 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, return obj; } -/** - * kmem_cache_alloc_node - Allocate an object on the specified node - * @cachep: The cache to allocate from. - * @flags: See kmalloc(). - * @nodeid: node number of the target node. - * @caller: return address of caller, used for debug information - * - * Identical to kmem_cache_alloc but it will allocate memory on the given - * node, which can improve the performance for cpu bound structures. - * - * Fallback to other node is possible if __GFP_THISNODE is not set. - */ static __always_inline void * slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, unsigned long caller) @@ -3645,6 +3633,17 @@ EXPORT_SYMBOL(kmem_cache_alloc_trace); #endif #ifdef CONFIG_NUMA +/** + * kmem_cache_alloc_node - Allocate an object on the specified node + * @cachep: The cache to allocate from. + * @flags: See kmalloc(). + * @nodeid: node number of the target node. + * + * Identical to kmem_cache_alloc but it will allocate memory on the given + * node, which can improve the performance for cpu bound structures. + * + * Fallback to other node is possible if __GFP_THISNODE is not set. + */ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) { void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_); -- GitLab From 86eda90eaa0ed380794d8c0a5c8ab3913cdea8e2 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:57 -0300 Subject: [PATCH 0759/2900] [media] coda: simplify parameter buffer setup code Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 51 ++++++++++++++++------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index ba99e2fb0f85..366318d87887 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -905,21 +905,34 @@ static void coda_free_framebuffers(struct coda_ctx *ctx) } } +static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) +{ + struct coda_dev *dev = ctx->dev; + u32 *p = ctx->parabuf.vaddr; + + if (dev->devtype->product == CODA_DX6) + p[index] = value; + else + p[index ^ 1] = value; +} + static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) { struct coda_dev *dev = ctx->dev; int height = q_data->height; - int width = q_data->width; - u32 *p; + dma_addr_t paddr; + int ysize; int i; + ysize = round_up(q_data->width, 8) * height; + /* Allocate frame buffers */ ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS; for (i = 0; i < ctx->num_internal_frames; i++) { ctx->internal_frames[i].size = q_data->sizeimage; if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6) - ctx->internal_frames[i].size += width / 2 * height / 2; + ctx->internal_frames[i].size += ysize/4; ctx->internal_frames[i].vaddr = dma_alloc_coherent( &dev->plat_dev->dev, ctx->internal_frames[i].size, &ctx->internal_frames[i].paddr, GFP_KERNEL); @@ -930,32 +943,14 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d } /* Register frame buffers in the parameter buffer */ - p = ctx->parabuf.vaddr; + for (i = 0; i < ctx->num_internal_frames; i++) { + paddr = ctx->internal_frames[i].paddr; + coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */ + coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ + coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ - if (dev->devtype->product == CODA_DX6) { - for (i = 0; i < ctx->num_internal_frames; i++) { - p[i * 3] = ctx->internal_frames[i].paddr; /* Y */ - p[i * 3 + 1] = p[i * 3] + width * height; /* Cb */ - p[i * 3 + 2] = p[i * 3 + 1] + width / 2 * height / 2; /* Cr */ - } - } else { - for (i = 0; i < ctx->num_internal_frames; i += 2) { - p[i * 3 + 1] = ctx->internal_frames[i].paddr; /* Y */ - p[i * 3] = p[i * 3 + 1] + width * height; /* Cb */ - p[i * 3 + 3] = p[i * 3] + (width / 2) * (height / 2); /* Cr */ - - if (fourcc == V4L2_PIX_FMT_H264) - p[96 + i + 1] = p[i * 3 + 3] + (width / 2) * (height / 2); - - if (i + 1 < ctx->num_internal_frames) { - p[i * 3 + 2] = ctx->internal_frames[i+1].paddr; /* Y */ - p[i * 3 + 5] = p[i * 3 + 2] + width * height ; /* Cb */ - p[i * 3 + 4] = p[i * 3 + 5] + (width / 2) * (height / 2); /* Cr */ - - if (fourcc == V4L2_PIX_FMT_H264) - p[96 + i] = p[i * 3 + 4] + (width / 2) * (height / 2); - } - } + if (dev->devtype->product != CODA_DX6 && fourcc == V4L2_PIX_FMT_H264) + coda_parabuf_write(ctx, 96 + i, ctx->internal_frames[i].paddr + ysize + ysize/4 + ysize/4); } return 0; -- GitLab From b96904e50a70618e2c3d44d267706728ca741a4c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:58 -0300 Subject: [PATCH 0760/2900] [media] coda: per-product list of codecs instead of list of formats This patch adds a list of supported codecs per device type which is used to determine the allowed pixel formats and maximum frame sizes depending on the possible codecs. It allows frame sizes larger than 720 x 576 on CODA7 and adds support for the YVU420 (planar YUV 4:2:0 with switched Cb and Cr) format. Other uncompressed formats that could be added in the future are the chroma interleaved NV12 and NV21 formats and the multiplanar variants YUV420M, YVU420M, NV12M, and NV21M. Further, rawstreamon is renamed to streamon_out and compstreamon is renamed to streamon_cap in preparation for decoding support. The maximum encoded frame buffer size is increased to 1 MiB. Instead of tracking inst_type and codec across S_FMT calls, set the codec and inst_type in start_streaming. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 345 +++++++++++++++++++--------------- drivers/media/platform/coda.h | 3 +- 2 files changed, 194 insertions(+), 154 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 366318d87887..9b7b69e2fa9f 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -49,16 +49,14 @@ #define CODA_MAX_FRAMEBUFFERS 2 -#define MAX_W 720 -#define MAX_H 576 -#define CODA_MAX_FRAME_SIZE 0x90000 +#define MAX_W 8192 +#define MAX_H 8192 +#define CODA_MAX_FRAME_SIZE 0x100000 #define FMO_SLICE_SAVE_BUF_SIZE (32) #define CODA_DEFAULT_GAMMA 4096 #define MIN_W 176 #define MIN_H 144 -#define MAX_W 720 -#define MAX_H 576 #define S_ALIGN 1 /* multiple of 2 */ #define W_ALIGN 1 /* multiple of 2 */ @@ -75,11 +73,6 @@ enum { V4L2_M2M_DST = 1, }; -enum coda_fmt_type { - CODA_FMT_ENC, - CODA_FMT_RAW, -}; - enum coda_inst_type { CODA_INST_ENCODER, CODA_INST_DECODER, @@ -93,14 +86,21 @@ enum coda_product { struct coda_fmt { char *name; u32 fourcc; - enum coda_fmt_type type; +}; + +struct coda_codec { + u32 mode; + u32 src_fourcc; + u32 dst_fourcc; + u32 max_w; + u32 max_h; }; struct coda_devtype { char *firmware; enum coda_product product; - struct coda_fmt *formats; - unsigned int num_formats; + struct coda_codec *codecs; + unsigned int num_codecs; size_t workbuf_size; }; @@ -109,7 +109,7 @@ struct coda_q_data { unsigned int width; unsigned int height; unsigned int sizeimage; - struct coda_fmt *fmt; + unsigned int fourcc; }; struct coda_aux_buf { @@ -164,11 +164,12 @@ struct coda_ctx { struct coda_dev *dev; struct list_head list; int aborting; - int rawstreamon; - int compstreamon; + int streamon_out; + int streamon_cap; u32 isequence; struct coda_q_data q_data[2]; enum coda_inst_type inst_type; + struct coda_codec *codec; enum v4l2_colorspace colorspace; struct coda_params params; struct v4l2_m2m_ctx *m2m_ctx; @@ -257,62 +258,89 @@ static struct coda_q_data *get_q_data(struct coda_ctx *ctx, } /* - * Add one array of supported formats for each version of Coda: - * i.MX27 -> codadx6 - * i.MX51 -> coda7 - * i.MX6 -> coda960 + * Array of all formats supported by any version of Coda: */ -static struct coda_fmt codadx6_formats[] = { +static struct coda_fmt coda_formats[] = { { - .name = "YUV 4:2:0 Planar", + .name = "YUV 4:2:0 Planar, YCbCr", .fourcc = V4L2_PIX_FMT_YUV420, - .type = CODA_FMT_RAW, - }, - { - .name = "H264 Encoded Stream", - .fourcc = V4L2_PIX_FMT_H264, - .type = CODA_FMT_ENC, - }, - { - .name = "MPEG4 Encoded Stream", - .fourcc = V4L2_PIX_FMT_MPEG4, - .type = CODA_FMT_ENC, }, -}; - -static struct coda_fmt coda7_formats[] = { { - .name = "YUV 4:2:0 Planar", - .fourcc = V4L2_PIX_FMT_YUV420, - .type = CODA_FMT_RAW, + .name = "YUV 4:2:0 Planar, YCrCb", + .fourcc = V4L2_PIX_FMT_YVU420, }, { .name = "H264 Encoded Stream", .fourcc = V4L2_PIX_FMT_H264, - .type = CODA_FMT_ENC, }, { .name = "MPEG4 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG4, - .type = CODA_FMT_ENC, }, }; -static struct coda_fmt *find_format(struct coda_dev *dev, struct v4l2_format *f) +#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \ + { mode, src_fourcc, dst_fourcc, max_w, max_h } + +/* + * Arrays of codecs supported by each given version of Coda: + * i.MX27 -> codadx6 + * i.MX5x -> coda7 + * i.MX6 -> coda960 + * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants + */ +static struct coda_codec codadx6_codecs[] = { + CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), + CODA_CODEC(CODADX6_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576), +}; + +static struct coda_codec coda7_codecs[] = { + CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), + CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), +}; + +static bool coda_format_is_yuv(u32 fourcc) +{ + switch (fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + return true; + default: + return false; + } +} + +/* + * Normalize all supported YUV 4:2:0 formats to the value used in the codec + * tables. + */ +static u32 coda_format_normalize_yuv(u32 fourcc) +{ + return coda_format_is_yuv(fourcc) ? V4L2_PIX_FMT_YUV420 : fourcc; +} + +static struct coda_codec *coda_find_codec(struct coda_dev *dev, int src_fourcc, + int dst_fourcc) { - struct coda_fmt *formats = dev->devtype->formats; - int num_formats = dev->devtype->num_formats; - unsigned int k; + struct coda_codec *codecs = dev->devtype->codecs; + int num_codecs = dev->devtype->num_codecs; + int k; + + src_fourcc = coda_format_normalize_yuv(src_fourcc); + dst_fourcc = coda_format_normalize_yuv(dst_fourcc); + if (src_fourcc == dst_fourcc) + return NULL; - for (k = 0; k < num_formats; k++) { - if (formats[k].fourcc == f->fmt.pix.pixelformat) + for (k = 0; k < num_codecs; k++) { + if (codecs[k].src_fourcc == src_fourcc && + codecs[k].dst_fourcc == dst_fourcc) break; } - if (k == num_formats) + if (k == num_codecs) return NULL; - return &formats[k]; + return &codecs[k]; } /* @@ -337,17 +365,34 @@ static int vidioc_querycap(struct file *file, void *priv, } static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, - enum coda_fmt_type type) + enum v4l2_buf_type type) { struct coda_ctx *ctx = fh_to_ctx(priv); - struct coda_dev *dev = ctx->dev; - struct coda_fmt *formats = dev->devtype->formats; + struct coda_codec *codecs = ctx->dev->devtype->codecs; + struct coda_fmt *formats = coda_formats; struct coda_fmt *fmt; - int num_formats = dev->devtype->num_formats; - int i, num = 0; + int num_codecs = ctx->dev->devtype->num_codecs; + int num_formats = ARRAY_SIZE(coda_formats); + int i, k, num = 0; for (i = 0; i < num_formats; i++) { - if (formats[i].type == type) { + /* Both uncompressed formats are always supported */ + if (coda_format_is_yuv(formats[i].fourcc)) { + if (num == f->index) + break; + ++num; + continue; + } + /* Compressed formats may be supported, check the codec list */ + for (k = 0; k < num_codecs; k++) { + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + formats[i].fourcc == codecs[k].dst_fourcc) + break; + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + formats[i].fourcc == codecs[k].src_fourcc) + break; + } + if (k < num_codecs) { if (num == f->index) break; ++num; @@ -368,13 +413,13 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return enum_fmt(priv, f, CODA_FMT_ENC); + return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE); } static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return enum_fmt(priv, f, CODA_FMT_RAW); + return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT); } static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) @@ -390,10 +435,10 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) q_data = get_q_data(ctx, f->type); f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = q_data->fmt->fourcc; + f->fmt.pix.pixelformat = q_data->fourcc; f->fmt.pix.width = q_data->width; f->fmt.pix.height = q_data->height; - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) + if (coda_format_is_yuv(f->fmt.pix.pixelformat)) f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); else /* encoded formats h.264/mpeg4 */ f->fmt.pix.bytesperline = 0; @@ -404,8 +449,9 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) +static int vidioc_try_fmt(struct coda_codec *codec, struct v4l2_format *f) { + unsigned int max_w, max_h; enum v4l2_field field; field = f->fmt.pix.field; @@ -418,10 +464,18 @@ static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) * if any of the dimensions is unsupported */ f->fmt.pix.field = field; - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { - v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, - W_ALIGN, &f->fmt.pix.height, - MIN_H, MAX_H, H_ALIGN, S_ALIGN); + if (codec) { + max_w = codec->max_w; + max_h = codec->max_h; + } else { + max_w = MAX_W; + max_h = MAX_H; + } + v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, + W_ALIGN, &f->fmt.pix.height, + MIN_H, max_h, H_ALIGN, S_ALIGN); + + if (coda_format_is_yuv(f->fmt.pix.pixelformat)) { /* Frame stride must be multiple of 8 */ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8); f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * @@ -437,57 +491,38 @@ static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - int ret; - struct coda_fmt *fmt; struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_codec *codec = NULL; - fmt = find_format(ctx->dev, f); - /* - * Since decoding support is not implemented yet do not allow - * CODA_FMT_RAW formats in the capture interface. - */ - if (!fmt || !(fmt->type == CODA_FMT_ENC)) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264; + /* Determine codec by the encoded format */ + codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, + f->fmt.pix.pixelformat); f->fmt.pix.colorspace = ctx->colorspace; - ret = vidioc_try_fmt(ctx->dev, f); - if (ret < 0) - return ret; - - return 0; + return vidioc_try_fmt(codec, f); } static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct coda_ctx *ctx = fh_to_ctx(priv); - struct coda_fmt *fmt; - int ret; + struct coda_codec *codec; - fmt = find_format(ctx->dev, f); - /* - * Since decoding support is not implemented yet do not allow - * CODA_FMT formats in the capture interface. - */ - if (!fmt || !(fmt->type == CODA_FMT_RAW)) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + /* Determine codec by encoded format, returns NULL if raw or invalid */ + codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, + V4L2_PIX_FMT_YUV420); if (!f->fmt.pix.colorspace) f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - ret = vidioc_try_fmt(ctx->dev, f); - if (ret < 0) - return ret; - - return 0; + return vidioc_try_fmt(codec, f); } static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) { struct coda_q_data *q_data; struct vb2_queue *vq; - int ret; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) @@ -502,18 +537,14 @@ static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) return -EBUSY; } - ret = vidioc_try_fmt(ctx->dev, f); - if (ret) - return ret; - - q_data->fmt = find_format(ctx->dev, f); + q_data->fourcc = f->fmt.pix.pixelformat; q_data->width = f->fmt.pix.width; q_data->height = f->fmt.pix.height; q_data->sizeimage = f->fmt.pix.sizeimage; v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %d\n", - f->type, q_data->width, q_data->height, q_data->fmt->fourcc); + f->type, q_data->width, q_data->height, q_data->fourcc); return 0; } @@ -521,13 +552,14 @@ static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct coda_ctx *ctx = fh_to_ctx(priv); int ret; ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret) return ret; - return vidioc_s_fmt(fh_to_ctx(priv), f); + return vidioc_s_fmt(ctx, f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, @@ -644,7 +676,7 @@ static void coda_device_run(void *m2m_priv) dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); - dst_fourcc = q_data_dst->fmt->fourcc; + dst_fourcc = q_data_dst->fourcc; src_buf->v4l2_buf.sequence = ctx->isequence; dst_buf->v4l2_buf.sequence = ctx->isequence; @@ -726,9 +758,20 @@ static void coda_device_run(void *m2m_priv) picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); - picture_cb = picture_y + q_data_src->width * q_data_src->height; - picture_cr = picture_cb + q_data_src->width / 2 * - q_data_src->height / 2; + switch (q_data_src->fourcc) { + case V4L2_PIX_FMT_YVU420: + /* Switch Cb and Cr for YVU420 format */ + picture_cr = picture_y + q_data_src->width * q_data_src->height; + picture_cb = picture_cr + q_data_src->width / 2 * + q_data_src->height / 2; + break; + case V4L2_PIX_FMT_YUV420: + default: + picture_cb = picture_y + q_data_src->width * q_data_src->height; + picture_cr = picture_cb + q_data_src->width / 2 * + q_data_src->height / 2; + break; + } coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); @@ -810,7 +853,12 @@ static struct v4l2_m2m_ops coda_m2m_ops = { static void set_default_params(struct coda_ctx *ctx) { - struct coda_dev *dev = ctx->dev; + int max_w; + int max_h; + + ctx->codec = &ctx->dev->devtype->codecs[0]; + max_w = ctx->codec->max_w; + max_h = ctx->codec->max_h; ctx->params.codec_mode = CODA_MODE_INVALID; ctx->colorspace = V4L2_COLORSPACE_REC709; @@ -818,13 +866,13 @@ static void set_default_params(struct coda_ctx *ctx) ctx->aborting = 0; /* Default formats for output and input queues */ - ctx->q_data[V4L2_M2M_SRC].fmt = &dev->devtype->formats[0]; - ctx->q_data[V4L2_M2M_DST].fmt = &dev->devtype->formats[1]; - ctx->q_data[V4L2_M2M_SRC].width = MAX_W; - ctx->q_data[V4L2_M2M_SRC].height = MAX_H; - ctx->q_data[V4L2_M2M_SRC].sizeimage = (MAX_W * MAX_H * 3) / 2; - ctx->q_data[V4L2_M2M_DST].width = MAX_W; - ctx->q_data[V4L2_M2M_DST].height = MAX_H; + ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->codec->src_fourcc; + ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc; + ctx->q_data[V4L2_M2M_SRC].width = max_w; + ctx->q_data[V4L2_M2M_SRC].height = max_h; + ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; + ctx->q_data[V4L2_M2M_DST].width = max_w; + ctx->q_data[V4L2_M2M_DST].height = max_h; ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; } @@ -990,37 +1038,36 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) return -EINVAL; if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - ctx->rawstreamon = 1; + ctx->streamon_out = 1; else - ctx->compstreamon = 1; + ctx->streamon_cap = 1; - /* Don't start the coda unless both queues are on */ - if (!(ctx->rawstreamon & ctx->compstreamon)) - return 0; + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + if (ctx->streamon_out) { + if (coda_format_is_yuv(q_data_src->fourcc)) + ctx->inst_type = CODA_INST_ENCODER; + else + ctx->inst_type = CODA_INST_DECODER; + } if (coda_isbusy(dev)) if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) return -EBUSY; - ctx->gopcounter = ctx->params.gop_size - 1; + /* Don't start the coda unless both queues are on */ + if (!(ctx->streamon_out & ctx->streamon_cap)) + return 0; - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + ctx->gopcounter = ctx->params.gop_size - 1; buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); bitstream_size = q_data_dst->sizeimage; - dst_fourcc = q_data_dst->fmt->fourcc; - - /* Find out whether coda must encode or decode */ - if (q_data_src->fmt->type == CODA_FMT_RAW && - q_data_dst->fmt->type == CODA_FMT_ENC) { - ctx->inst_type = CODA_INST_ENCODER; - } else if (q_data_src->fmt->type == CODA_FMT_ENC && - q_data_dst->fmt->type == CODA_FMT_RAW) { - ctx->inst_type = CODA_INST_DECODER; - v4l2_err(v4l2_dev, "decoding not supported.\n"); - return -EINVAL; - } else { + dst_fourcc = q_data_dst->fourcc; + + ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc, + q_data_dst->fourcc); + if (!ctx->codec) { v4l2_err(v4l2_dev, "couldn't tell instance type.\n"); return -EINVAL; } @@ -1051,31 +1098,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) switch (dev->devtype->product) { case CODA_DX6: value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET; + value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; break; default: value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; + value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; } - value |= (q_data_src->height & CODA_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); coda_write(dev, ctx->params.framerate, CODA_CMD_ENC_SEQ_SRC_F_RATE); + ctx->params.codec_mode = ctx->codec->mode; switch (dst_fourcc) { case V4L2_PIX_FMT_MPEG4: - if (dev->devtype->product == CODA_DX6) - ctx->params.codec_mode = CODADX6_MODE_ENCODE_MP4; - else - ctx->params.codec_mode = CODA7_MODE_ENCODE_MP4; - coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); break; case V4L2_PIX_FMT_H264: - if (dev->devtype->product == CODA_DX6) - ctx->params.codec_mode = CODADX6_MODE_ENCODE_H264; - else - ctx->params.codec_mode = CODA7_MODE_ENCODE_H264; - coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA); break; @@ -1274,15 +1313,15 @@ static int coda_stop_streaming(struct vb2_queue *q) if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "%s: output\n", __func__); - ctx->rawstreamon = 0; + ctx->streamon_out = 0; } else { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "%s: capture\n", __func__); - ctx->compstreamon = 0; + ctx->streamon_cap = 0; } /* Don't stop the coda unless both queues are off */ - if (ctx->rawstreamon || ctx->compstreamon) + if (ctx->streamon_out || ctx->streamon_cap) return 0; if (coda_isbusy(dev)) { @@ -1915,16 +1954,16 @@ enum coda_platform { static const struct coda_devtype coda_devdata[] = { [CODA_IMX27] = { - .firmware = "v4l-codadx6-imx27.bin", - .product = CODA_DX6, - .formats = codadx6_formats, - .num_formats = ARRAY_SIZE(codadx6_formats), + .firmware = "v4l-codadx6-imx27.bin", + .product = CODA_DX6, + .codecs = codadx6_codecs, + .num_codecs = ARRAY_SIZE(codadx6_codecs), }, [CODA_IMX53] = { - .firmware = "v4l-coda7541-imx53.bin", - .product = CODA_7541, - .formats = coda7_formats, - .num_formats = ARRAY_SIZE(coda7_formats), + .firmware = "v4l-coda7541-imx53.bin", + .product = CODA_7541, + .codecs = coda7_codecs, + .num_codecs = ARRAY_SIZE(coda7_codecs), }, }; diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index 3c350acd5faa..ace0bf0a3b9c 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h @@ -113,7 +113,8 @@ #define CODADX6_PICWIDTH_OFFSET 10 #define CODADX6_PICWIDTH_MASK 0x3ff #define CODA_PICHEIGHT_OFFSET 0 -#define CODA_PICHEIGHT_MASK 0x3ff +#define CODADX6_PICHEIGHT_MASK 0x3ff +#define CODA7_PICHEIGHT_MASK 0xffff #define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 #define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 #define CODA_MP4PARAM_VERID_OFFSET 6 -- GitLab From d35167a1d69ae027615d4345a678555bf1c6fed6 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:42:59 -0300 Subject: [PATCH 0761/2900] [media] coda: add coda_encode_header helper function In preparation for CODA7541 and CODA960 multi-stream support and for replacement of the completion with a mutex lock, consolidate the header encoding in a helper function. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 112 ++++++++++++++++------------------ 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 9b7b69e2fa9f..34d6fd6c0517 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1022,6 +1022,28 @@ static int coda_h264_padding(int size, char *p) return nal_size; } +static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, + int header_code, u8 *header, int *size) +{ + struct coda_dev *dev = ctx->dev; + int ret; + + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), + CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, vb2_plane_size(buf, 0), CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); + ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); + return ret; + } + *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(header, vb2_plane_vaddr(buf, 0), *size); + + return 0; +} + static int coda_start_streaming(struct vb2_queue *q, unsigned int count) { struct coda_ctx *ctx = vb2_get_drv_priv(q); @@ -1032,7 +1054,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) struct vb2_buffer *buf; u32 dst_fourcc; u32 value; - int ret; + int ret = 0; if (count < 1) return -EINVAL; @@ -1219,33 +1241,22 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) * Get SPS in the first frame and copy it to an * intermediate buffer. */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_H264_SPS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[0]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, + &ctx->vpu_header[0][0], + &ctx->vpu_header_size[0]); + if (ret < 0) + goto out; /* * Get PPS in the first frame and copy it to an * intermediate buffer. */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_H264_PPS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[1]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, + &ctx->vpu_header[1][0], + &ctx->vpu_header_size[1]); + if (ret < 0) + goto out; + /* * Length of H.264 headers is variable and thus it might not be * aligned for the coda to append the encoded frame. In that is @@ -1261,48 +1272,31 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) * Get VOS in the first frame and copy it to an * intermediate buffer */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VOS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[0]); - - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VIS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[1]); - - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VOL, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[2] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[2][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[2]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, + &ctx->vpu_header[0][0], + &ctx->vpu_header_size[0]); + if (ret < 0) + goto out; + + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, + &ctx->vpu_header[1][0], + &ctx->vpu_header_size[1]); + if (ret < 0) + goto out; + + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, + &ctx->vpu_header[2][0], + &ctx->vpu_header_size[2]); + if (ret < 0) + goto out; break; default: /* No more formats need to save headers at the moment */ break; } - return 0; +out: + return ret; } static int coda_stop_streaming(struct vb2_queue *q) -- GitLab From fcb62825e7289f937f4af26a741e3af8da9242de Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:43:00 -0300 Subject: [PATCH 0762/2900] [media] coda: replace completion with mutex Not only do we need to wait for job completion when we want to call a command on the CODA in start/stop_streaming, we also need to make sure that a new job doesn't start before the command finished. Use a mutex to lock the coda command handling. On timeout, the device_run job must be marked as finished and the mutex released, as otherwise coda_release will block. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 66 +++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 34d6fd6c0517..f9c4014ee40c 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -137,12 +137,12 @@ struct coda_dev { spinlock_t irqlock; struct mutex dev_mutex; + struct mutex coda_mutex; struct v4l2_m2m_dev *m2m_dev; struct vb2_alloc_ctx *alloc_ctx; struct list_head instances; unsigned long instance_mask; struct delayed_work timeout; - struct completion done; }; struct coda_params { @@ -672,6 +672,8 @@ static void coda_device_run(void *m2m_priv) u32 pic_stream_buffer_addr, pic_stream_buffer_size; u32 dst_fourcc; + mutex_lock(&dev->coda_mutex); + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); @@ -792,7 +794,6 @@ static void coda_device_run(void *m2m_priv) /* 1 second timeout in case CODA locks up */ schedule_delayed_work(&dev->timeout, HZ); - INIT_COMPLETION(dev->done); coda_command_async(ctx, CODA_COMMAND_PIC_RUN); } @@ -1072,10 +1073,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) ctx->inst_type = CODA_INST_DECODER; } - if (coda_isbusy(dev)) - if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) - return -EBUSY; - /* Don't start the coda unless both queues are on */ if (!(ctx->streamon_out & ctx->streamon_cap)) return 0; @@ -1098,6 +1095,9 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) v4l2_err(v4l2_dev, "coda is not initialized.\n"); return -EFAULT; } + + mutex_lock(&dev->coda_mutex); + coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx)); coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx)); @@ -1143,7 +1143,8 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) default: v4l2_err(v4l2_dev, "dst format (0x%08x) invalid.\n", dst_fourcc); - return -EINVAL; + ret = -EINVAL; + goto out; } switch (ctx->params.slice_mode) { @@ -1206,17 +1207,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) } } - if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { + ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); + if (ret < 0) { v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); - return -ETIMEDOUT; + goto out; } - if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) - return -EFAULT; + if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { + v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); + ret = -EFAULT; + goto out; + } ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); - if (ret < 0) - return ret; + if (ret < 0) { + v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); + goto out; + } coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); @@ -1228,9 +1235,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); } - if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { + ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); + if (ret < 0) { v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); - return -ETIMEDOUT; + goto out; } /* Save stream headers */ @@ -1296,6 +1304,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) } out: + mutex_unlock(&dev->coda_mutex); return ret; } @@ -1318,15 +1327,9 @@ static int coda_stop_streaming(struct vb2_queue *q) if (ctx->streamon_out || ctx->streamon_cap) return 0; - if (coda_isbusy(dev)) { - if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) { - v4l2_warn(&dev->v4l2_dev, - "%s: timeout, sending SEQ_END anyway\n", __func__); - } - } - cancel_delayed_work(&dev->timeout); + mutex_lock(&dev->coda_mutex); v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s: sent command 'SEQ_END' to coda\n", __func__); if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { @@ -1334,6 +1337,7 @@ static int coda_stop_streaming(struct vb2_queue *q) "CODA_COMMAND_SEQ_END failed\n"); return -ETIMEDOUT; } + mutex_unlock(&dev->coda_mutex); coda_free_framebuffers(ctx); @@ -1629,12 +1633,14 @@ static irqreturn_t coda_irq_handler(int irq, void *data) ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); if (ctx == NULL) { v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); + mutex_unlock(&dev->coda_mutex); return IRQ_HANDLED; } if (ctx->aborting) { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "task has been aborted\n"); + mutex_unlock(&dev->coda_mutex); return IRQ_HANDLED; } @@ -1644,8 +1650,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data) return IRQ_NONE; } - complete(&dev->done); - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); @@ -1693,6 +1697,8 @@ static irqreturn_t coda_irq_handler(int irq, void *data) (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? "KEYFRAME" : "PFRAME"); + mutex_unlock(&dev->coda_mutex); + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); return IRQ_HANDLED; @@ -1704,11 +1710,6 @@ static void coda_timeout(struct work_struct *work) struct coda_dev *dev = container_of(to_delayed_work(work), struct coda_dev, timeout); - if (completion_done(&dev->done)) - return; - - complete(&dev->done); - dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n"); mutex_lock(&dev->dev_mutex); @@ -1717,6 +1718,10 @@ static void coda_timeout(struct work_struct *work) v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); } mutex_unlock(&dev->dev_mutex); + + mutex_unlock(&dev->coda_mutex); + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); } static u32 coda_supported_firmwares[] = { @@ -1999,8 +2004,6 @@ static int coda_probe(struct platform_device *pdev) spin_lock_init(&dev->irqlock); INIT_LIST_HEAD(&dev->instances); INIT_DELAYED_WORK(&dev->timeout, coda_timeout); - init_completion(&dev->done); - complete(&dev->done); dev->plat_dev = pdev; dev->clk_per = devm_clk_get(&pdev->dev, "per"); @@ -2054,6 +2057,7 @@ static int coda_probe(struct platform_device *pdev) return ret; mutex_init(&dev->dev_mutex); + mutex_init(&dev->coda_mutex); pdev_id = of_id ? of_id->data : platform_get_device_id(pdev); -- GitLab From 3e748268f391eaf46fe547eb3e51bfec387a63c5 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 23 May 2013 10:43:01 -0300 Subject: [PATCH 0763/2900] [media] coda: do not call v4l2_m2m_job_finish from .job_abort If we just declare the job finished here while the CODA is still running, the call to v4l2_m2m_ctx_release in coda_release, which is supposed to wait for a running job to finish, will return immediately and free memory that the CODA is still using. Just set the 'aborting' flag and let coda_irq_handler deal with it. Signed-off-by: Philipp Zabel Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index f9c4014ee40c..c4566c447774 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -812,6 +812,12 @@ static int coda_job_ready(void *m2m_priv) return 0; } + if (ctx->aborting) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "not ready: aborting\n"); + return 0; + } + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "job ready\n"); return 1; @@ -820,14 +826,11 @@ static int coda_job_ready(void *m2m_priv) static void coda_job_abort(void *priv) { struct coda_ctx *ctx = priv; - struct coda_dev *dev = ctx->dev; ctx->aborting = 1; v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Aborting task\n"); - - v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); } static void coda_lock(void *m2m_priv) -- GitLab From afcf44c786765b4eee44eea39ac0fddbbb830926 Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Mon, 15 Apr 2013 16:01:51 -0300 Subject: [PATCH 0764/2900] [media] uvcvideo: quirk PROBE_DEF for Dell Studio / OmniVision webcam BugLink: https://bugs.launchpad.net/bugs/1168430 OminiVision webcam 0x05a9:0x264a (in Dell Studio Hybrid 140g) needs the same UVC_QUIRK_PROBE_DEF as other OmniVision model to be recognized consistently. Signed-off-by: Kamal Mostafa Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 5dbefa68b1d2..17bd48d16e5a 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2163,6 +2163,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Dell Studio Hybrid 140g (OmniVision webcam) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x05a9, + .idProduct = 0x264a, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, /* Apple Built-In iSight */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- GitLab From c2a273b24f2c82184cc0f04ba3a61da51c84724b Mon Sep 17 00:00:00 2001 From: Joseph Salisbury Date: Wed, 15 May 2013 17:38:48 -0300 Subject: [PATCH 0765/2900] [media] uvcvideo: quirk PROBE_DEF for Alienware X51 OmniVision webcam BugLink: http://bugs.launchpad.net/bugs/1180409 OminiVision webcam 0x05a9:0x2643 needs the same UVC_QUIRK_PROBE_DEF as other OmniVision models to work properly. Signed-off-by: Joseph Salisbury Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 17bd48d16e5a..a7e64af5f82e 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2163,6 +2163,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Dell Alienware X51 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x05a9, + .idProduct = 0x2643, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, /* Dell Studio Hybrid 140g (OmniVision webcam) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -- GitLab From 17706f5653a90ff277b5b36c2eb60ff872df5e7a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 25 Apr 2013 22:28:51 -0300 Subject: [PATCH 0766/2900] [media] uvcvideo: Fix open/close race condition Maintaining the users count using an atomic variable makes sure that access to the counter won't be racy, but doesn't serialize access to the operations protected by the counter. This creates a race condition that could result in the status URB being submitted multiple times. Use a mutex to protect the users count and serialize access to the status start and stop operations. Reported-by: Shawn Nematbakhsh Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 23 +++++++++++++++++------ drivers/media/usb/uvc/uvc_status.c | 21 ++------------------- drivers/media/usb/uvc/uvc_v4l2.c | 14 ++++++++++---- drivers/media/usb/uvc/uvcvideo.h | 7 +++---- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index a7e64af5f82e..81695d48c13e 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1836,8 +1836,8 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); atomic_set(&dev->nstreams, 0); - atomic_set(&dev->users, 0); atomic_set(&dev->nmappings, 0); + mutex_init(&dev->lock); dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); @@ -1950,8 +1950,13 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) /* Controls are cached on the fly so they don't need to be saved. */ if (intf->cur_altsetting->desc.bInterfaceSubClass == - UVC_SC_VIDEOCONTROL) - return uvc_status_suspend(dev); + UVC_SC_VIDEOCONTROL) { + mutex_lock(&dev->lock); + if (dev->users) + uvc_status_stop(dev); + mutex_unlock(&dev->lock); + return 0; + } list_for_each_entry(stream, &dev->streams, list) { if (stream->intf == intf) @@ -1973,14 +1978,20 @@ static int __uvc_resume(struct usb_interface *intf, int reset) if (intf->cur_altsetting->desc.bInterfaceSubClass == UVC_SC_VIDEOCONTROL) { - if (reset) { - int ret = uvc_ctrl_resume_device(dev); + int ret = 0; + if (reset) { + ret = uvc_ctrl_resume_device(dev); if (ret < 0) return ret; } - return uvc_status_resume(dev); + mutex_lock(&dev->lock); + if (dev->users) + ret = uvc_status_start(dev, GFP_NOIO); + mutex_unlock(&dev->lock); + + return ret; } list_for_each_entry(stream, &dev->streams, list) { diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index b7492775e6ae..f552ab997956 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -206,32 +206,15 @@ void uvc_status_cleanup(struct uvc_device *dev) uvc_input_cleanup(dev); } -int uvc_status_start(struct uvc_device *dev) +int uvc_status_start(struct uvc_device *dev, gfp_t flags) { if (dev->int_urb == NULL) return 0; - return usb_submit_urb(dev->int_urb, GFP_KERNEL); + return usb_submit_urb(dev->int_urb, flags); } void uvc_status_stop(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); } - -int uvc_status_suspend(struct uvc_device *dev) -{ - if (atomic_read(&dev->users)) - usb_kill_urb(dev->int_urb); - - return 0; -} - -int uvc_status_resume(struct uvc_device *dev) -{ - if (dev->int_urb == NULL || atomic_read(&dev->users) == 0) - return 0; - - return usb_submit_urb(dev->int_urb, GFP_NOIO); -} - diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index b2dc32623a71..3afff92804d3 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -498,16 +498,20 @@ static int uvc_v4l2_open(struct file *file) return -ENOMEM; } - if (atomic_inc_return(&stream->dev->users) == 1) { - ret = uvc_status_start(stream->dev); + mutex_lock(&stream->dev->lock); + if (stream->dev->users == 0) { + ret = uvc_status_start(stream->dev, GFP_KERNEL); if (ret < 0) { - atomic_dec(&stream->dev->users); + mutex_unlock(&stream->dev->lock); usb_autopm_put_interface(stream->dev->intf); kfree(handle); return ret; } } + stream->dev->users++; + mutex_unlock(&stream->dev->lock); + v4l2_fh_init(&handle->vfh, stream->vdev); v4l2_fh_add(&handle->vfh); handle->chain = stream->chain; @@ -538,8 +542,10 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; - if (atomic_dec_return(&stream->dev->users) == 0) + mutex_lock(&stream->dev->lock); + if (--stream->dev->users == 0) uvc_status_stop(stream->dev); + mutex_unlock(&stream->dev->lock); usb_autopm_put_interface(stream->dev->intf); return 0; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index af505fdd9b3f..9e35982d099a 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -514,7 +514,8 @@ struct uvc_device { char name[32]; enum uvc_device_state state; - atomic_t users; + struct mutex lock; /* Protects users */ + unsigned int users; atomic_t nmappings; /* Video control interface */ @@ -660,10 +661,8 @@ void uvc_video_clock_update(struct uvc_streaming *stream, /* Status */ extern int uvc_status_init(struct uvc_device *dev); extern void uvc_status_cleanup(struct uvc_device *dev); -extern int uvc_status_start(struct uvc_device *dev); +extern int uvc_status_start(struct uvc_device *dev, gfp_t flags); extern void uvc_status_stop(struct uvc_device *dev); -extern int uvc_status_suspend(struct uvc_device *dev); -extern int uvc_status_resume(struct uvc_device *dev); /* Controls */ extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops; -- GitLab From 4d8d5d92cb239142d888c7844db2b078e14d4213 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 2 Jun 2013 13:52:17 -0300 Subject: [PATCH 0767/2900] [media] dib8000: Fix dib8000_set_frontend() never setting ret MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb-frontends/dib8000.c: In function ‘dib8000_set_frontend’: drivers/media/dvb-frontends/dib8000.c:3556: warning: ‘ret’ is used uninitialized in this function Remove the variable and return zero instead. Signed-off-by: Geert Uytterhoeven Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/dib8000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index a54182dd0e91..90536147bf04 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3406,7 +3406,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; - int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER; + int l, i, active, time, time_slave = FE_CALLBACK_TIME_NEVER; u8 exit_condition, index_frontend; u32 delay, callback_time; @@ -3553,7 +3553,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) } } - return ret; + return 0; } static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) -- GitLab From 4aab0398e003ac2effae98ba66a012ed715967ba Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Sun, 2 Jun 2013 14:26:15 -0300 Subject: [PATCH 0768/2900] [media] r820t: do not double-free fe->tuner_priv in r820t_release() fe->tuner_priv is already freed by hybrid_tuner_release_state(). Signed-off-by: Gianluca Gennari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 4835021aa3b6..64f97389d5b0 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -2256,7 +2256,6 @@ static int r820t_release(struct dvb_frontend *fe) mutex_unlock(&r820t_list_mutex); - kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; -- GitLab From 703e60655ca520c5380d8c83a9db0d5e9b906856 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 1 Jun 2013 05:53:10 -0300 Subject: [PATCH 0769/2900] [media] dma-buf: Cocci spatch "ptr_ret.spatch" Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab --- drivers/base/dma-buf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 08fe897c0b4c..6687ba741879 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -680,10 +680,7 @@ int dma_buf_debugfs_create_file(const char *name, d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir, write, &dma_buf_debug_fops); - if (IS_ERR(d)) - return PTR_ERR(d); - - return 0; + return PTR_RET(d); } #else static inline int dma_buf_init_debugfs(void) -- GitLab From ccac68f9818d0ff5c4cde26590a7f284285c724e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 14:37:06 -0300 Subject: [PATCH 0770/2900] [media] stb0899: sign extend raw CRL_FREQ value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contrary to the chip's specs, the register's value is signed, so we need to sign extend the value before using it in calculations like when determining the offset frequency. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 117a56926dca..bd9dbd70af0f 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -1487,6 +1487,10 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) /* Store signal parameters */ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); + /* sign extend 30 bit value before using it in calculations */ + if (offsetfreq & (1 << 29)) + offsetfreq |= -1 << 30; + offsetfreq = offsetfreq / ((1 << 30) / 1000); offsetfreq *= (internal->master_clk / 1000000); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); -- GitLab From 2eeed77fd1f54eb8cd34f409381eb7be2da4bc51 Mon Sep 17 00:00:00 2001 From: Zoran Turalija Date: Sun, 2 Jun 2013 14:40:51 -0300 Subject: [PATCH 0771/2900] [media] stb0899: allow minimum symbol rate of 1000000 This makes minimum symbol rate driver capabilities on par with windows driver, and allows tuning on linux to transponders that have symbol rate below 5000000, too. Patch was tested successfully on Eutelsat 16A transponders that became reachable with it (1000000 < symbol rate < 5000000): * DVB/S 12507050 V 2532000 3/4 * DVB/S2 12574000 V 4355000 3/4 8PSK * DVB/S 12593000 V 2500000 2/3 * DVB/S 12596940 V 2848000 2/3 * DVB/S 12600750 V 2500000 1/2 * DVB/S 12675590 H 4248000 3/4 Signed-off-by: Zoran Turalija Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index cc278b3d6d5a..527f5c3e0be9 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1581,7 +1581,7 @@ static struct dvb_frontend_ops stb0899_ops = { .frequency_max = 2150000, .frequency_stepsize = 0, .frequency_tolerance = 0, - .symbol_rate_min = 5000000, + .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | -- GitLab From fa64cfd2fc8b66918e7889deeaec87d77fb96f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 14:52:02 -0300 Subject: [PATCH 0772/2900] [media] stb0899: enable auto inversion handling unconditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that current inversion handling addresses only the signal routing on the PCB, i. e. IQ signals are either swapped or not. But when the device is operated in a Satellite Channel Router (SCR) environment, an additional inversion is required due to the way how the SCR works. Therefore it makes sense to me to always enable auto inversion handling and drop the enum value IQ_SWAP_AUTO. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 63 ++++++++++------------ drivers/media/dvb-frontends/stb0899_drv.h | 1 - 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index bd9dbd70af0f..14d720ba1207 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -1373,9 +1373,6 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) case IQ_SWAP_ON: STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); break; - case IQ_SWAP_AUTO: /* use last successful search first */ - STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); - break; } stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); stb0899_dvbs2_reacquire(state); @@ -1405,41 +1402,39 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) } if (internal->status != DVBS2_FEC_LOCK) { - if (internal->inversion == IQ_SWAP_AUTO) { - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); - iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); - /* IQ Spectrum Inversion */ - STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); - stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); - /* start acquistion process */ - stb0899_dvbs2_reacquire(state); + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); + iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); + /* IQ Spectrum Inversion */ + STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); + stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); + /* start acquistion process */ + stb0899_dvbs2_reacquire(state); + + /* Wait for demod lock (UWP and CSM) */ + internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); + if (internal->status == DVBS2_DEMOD_LOCK) { + i = 0; + /* Demod Locked, check FEC */ + internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); + /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ + while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { + /* Read the frequency offset*/ + offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - /* Wait for demod lock (UWP and CSM) */ - internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); - if (internal->status == DVBS2_DEMOD_LOCK) { - i = 0; - /* Demod Locked, check FEC */ - internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); - /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ - while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { - /* Read the frequency offset*/ - offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - - /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); - STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); - stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); - - stb0899_dvbs2_reacquire(state); - internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); - i++; - } + /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); + STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); + stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); + + stb0899_dvbs2_reacquire(state); + internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); + i++; } + } /* - if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) - pParams->IQLocked = !iqSpectrum; + if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) + pParams->IQLocked = !iqSpectrum; */ - } } if (internal->status == DVBS2_FEC_LOCK) { dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !"); diff --git a/drivers/media/dvb-frontends/stb0899_drv.h b/drivers/media/dvb-frontends/stb0899_drv.h index 8d26ff6eb1db..1ddad6a8cc07 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.h +++ b/drivers/media/dvb-frontends/stb0899_drv.h @@ -47,7 +47,6 @@ struct stb0899_s2_reg { enum stb0899_inversion { IQ_SWAP_OFF = 0, IQ_SWAP_ON, - IQ_SWAP_AUTO }; #define STB0899_GPIO00 0xf140 -- GitLab From 069ebbfc9eb7bef5e9780c508d8bc378bfea3e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 14:52:43 -0300 Subject: [PATCH 0773/2900] [media] stb0899: fix inversion enum values to match usage with CFR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Throughout the zig-zag-implementations, inversion is taken into account when reading and writing the CFR register, which contains the derotator frequency. As swapping IQ signals changes the sign of that register for example, the idea is to compensate that sign change by multiplying the register value with the inversion enum value. The current enum values 0 and 1 for IQ_SWAP_OFF and IQ_SWAP_ON don't work in the case IQ_SWAP_OFF, due to the multiplication by zero (I've only found a single device which actually uses IQ_SWAP_OFF in it's config). I've changed the enum values to +1 and -1 to accommodate to the intended usage. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 4 ++-- drivers/media/dvb-frontends/stb0899_drv.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 14d720ba1207..e0d31a2ea578 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -444,7 +444,7 @@ static enum stb0899_status stb0899_check_range(struct stb0899_state *state) int range_offst, tp_freq; range_offst = internal->srch_range / 2000; - tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000; + tp_freq = internal->freq - (internal->derot_freq * internal->mclk) / 1000; if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) { internal->status = RANGEOK; @@ -638,7 +638,7 @@ enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state) "RANGE OK ! derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000); + internal->freq = params->freq - ((internal->derot_freq * internal->mclk) / 1000); reg = stb0899_read_reg(state, STB0899_PLPARM); internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); dprintk(state->verbose, FE_DEBUG, 1, diff --git a/drivers/media/dvb-frontends/stb0899_drv.h b/drivers/media/dvb-frontends/stb0899_drv.h index 1ddad6a8cc07..139264d19263 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.h +++ b/drivers/media/dvb-frontends/stb0899_drv.h @@ -45,8 +45,8 @@ struct stb0899_s2_reg { }; enum stb0899_inversion { - IQ_SWAP_OFF = 0, - IQ_SWAP_ON, + IQ_SWAP_OFF = +1, /* inversion affects the sign of e. g. */ + IQ_SWAP_ON = -1, /* the derotator frequency register */ }; #define STB0899_GPIO00 0xf140 -- GitLab From 55b3318b3a49488a14ccfceffde668d548c4e427 Mon Sep 17 00:00:00 2001 From: Zoran Turalija Date: Sun, 2 Jun 2013 14:56:33 -0300 Subject: [PATCH 0774/2900] [media] stb0899: allow minimum symbol rate of 2000000 Looks like product datasheets for tuners containing STB0899 are suggesting specification for min. symbol rate of 2MS/s. Some specs found here, all suggesting 2MS/s for min. symbol rate: Comtech DVBS2-6899 http://comtech.sg1002.myweb.hinet.net/pdf/dvbs2-6899.pdf TechniSat SkyStar HD2 http://www.scaistar.com/skystar2/skystarhd2.htm Azurewave AD-SP400 http://www.pulsat.com/products/AzureWave-AD%252dSP400-High-Definition-PC-Card.html New patch: This makes minimum symbol rate driver capabilities on par with some accessible datasheet specifications*, and allows tuning on linux to transponders that have symbol rate between 2000000-5000000, too. Patch was tested successfully on Eutelsat 16A transponders that became reachable with it (2000000 < symbol rate < 5000000): * DVB/S 12507050 V 2532000 3/4 * DVB/S2 12574000 V 4355000 3/4 8PSK * DVB/S 12593000 V 2500000 2/3 * DVB/S 12596940 V 2848000 2/3 * DVB/S 12600750 V 2500000 1/2 * DVB/S 12675590 H 4248000 3/4 (*) Datasheet: http://comtech.sg1002.myweb.hinet.net/pdf/dvbs2-6899.pdf Maximum Symbol Rate QPSK/LDPC/PCH: 20-30Mbps 8PSK/LDPC/BCH: 10-30Mbps DVB: 2-45Mbps ^--------- min. symbol rate Signed-off-by: Zoran Turalija Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 527f5c3e0be9..b3ccd3dbbda1 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1581,7 +1581,7 @@ static struct dvb_frontend_ops stb0899_ops = { .frequency_max = 2150000, .frequency_stepsize = 0, .frequency_tolerance = 0, - .symbol_rate_min = 1000000, + .symbol_rate_min = 2000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | -- GitLab From 0c1d2b14d09b862ccd6300d774eb579161635710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 14:59:00 -0300 Subject: [PATCH 0775/2900] [media] stb0899: store successful inversion for next run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Usually, inversion doesn't change in a system. Storing the last successful inversion value speeds up tuning of DVB-S2 transponders. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 8 +++++++- drivers/media/dvb-frontends/stb0899_drv.c | 5 ++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index e0d31a2ea578..4b49efb67931 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -1488,9 +1488,15 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) offsetfreq = offsetfreq / ((1 << 30) / 1000); offsetfreq *= (internal->master_clk / 1000000); + + /* store current inversion for next run */ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) - offsetfreq *= -1; + internal->inversion = IQ_SWAP_ON; + else + internal->inversion = IQ_SWAP_OFF; + + offsetfreq *= internal->inversion; internal->freq = internal->freq - offsetfreq; internal->srate = stb0899_dvbs2_get_srate(state); diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index b3ccd3dbbda1..82391feb6839 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1618,19 +1618,18 @@ static struct dvb_frontend_ops stb0899_ops = { struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c) { struct stb0899_state *state = NULL; - enum stb0899_inversion inversion; state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL); if (state == NULL) goto error; - inversion = config->inversion; state->verbose = &verbose; state->config = config; state->i2c = i2c; state->frontend.ops = stb0899_ops; state->frontend.demodulator_priv = state; - state->internal.inversion = inversion; + /* use configured inversion as default -- we'll later autodetect inversion */ + state->internal.inversion = config->inversion; stb0899_wakeup(&state->frontend); if (stb0899_get_dev_id(state) == -ENODEV) { -- GitLab From b71e2c4cd89929a1160f3a8657135a802cc23df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 15:01:18 -0300 Subject: [PATCH 0776/2900] [media] stb0899: store autodetected inversion while tuning in non S2 mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In non S2 mode, the device is able to autodetect inversion. So let's store it for tuning to S2 transponders. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 4b49efb67931..4ce542c2db4b 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -425,6 +425,14 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if (internal->status == DATAOK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ + + /* store autodetected IQ swapping as default for DVB-S2 tuning */ + reg = stb0899_read_reg(state, STB0899_IQSWAP); + if (STB0899_GETFIELD(SYM, reg)) + internal->inversion = IQ_SWAP_ON; + else + internal->inversion = IQ_SWAP_OFF; + internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq); } -- GitLab From 25e529e6dab50049dcb45151407bd874ae6f5315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 15:02:05 -0300 Subject: [PATCH 0777/2900] [media] stb0899: use autodetected inversion instead of configured inversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency, it is necessary to use the autodetected inversion instead of the configured one. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 4ce542c2db4b..a338e06defd1 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -226,8 +226,8 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) next_loop--; if (next_loop) { - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } internal->direction = -internal->direction; /* Change zigzag direction */ @@ -235,7 +235,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) if (internal->status == TIMINGOK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq); } @@ -306,8 +306,8 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) STB0899_SETFIELD_VAL(CFD_ON, reg, 1); stb0899_write_reg(state, STB0899_CFD, reg); - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } } @@ -317,7 +317,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) if (internal->status == CARRIEROK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq); } else { internal->derot_freq = last_derot_freq; @@ -412,8 +412,8 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) STB0899_SETFIELD_VAL(CFD_ON, reg, 1); stb0899_write_reg(state, STB0899_CFD, reg); - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ stb0899_check_carrier(state); @@ -433,7 +433,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) else internal->inversion = IQ_SWAP_OFF; - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq); } -- GitLab From 7db462cdf6352af6d1ff85e52ffa82539f1c11e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 2 Jun 2013 15:03:13 -0300 Subject: [PATCH 0778/2900] [media] stb0899: sign of CRL_FREQ doesn't depend on inversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contrary to CFR (derotator frequency), which changes signedness depending on inversion, CRL_FREQ does not. Signed-off-by: Reinhard Nißl Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_algo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index a338e06defd1..93596e0e640b 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -1504,9 +1504,7 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) else internal->inversion = IQ_SWAP_OFF; - offsetfreq *= internal->inversion; - - internal->freq = internal->freq - offsetfreq; + internal->freq = internal->freq + offsetfreq; internal->srate = stb0899_dvbs2_get_srate(state); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); -- GitLab From a7fab8511169bd28ba0a00501afd12fc8a1a2c61 Mon Sep 17 00:00:00 2001 From: Alessandro Miceli Date: Fri, 3 May 2013 15:58:21 -0300 Subject: [PATCH 0779/2900] [media] Add support for 'Digital Dual TV Receiver CTVDIGDUAL v2 Tested on a MIPSel box with 3.3.6 kernel The kernel output when the device will be detected follows: usbcore: registered new interface driver dvb_usb_it913x it913x: Chip Version=01 Chip Type=9135 it913x: Remote propriety (raw) mode it913x: Dual mode=3 Tuner Type=38 it913x: Chip Version=01 Chip Type=9135 usb 2-1: dvb_usb_v2: found a 'Digital Dual TV Receiver CTVDIGDUAL_V2' in cold state usb 2-1: dvb_usb_v2: downloading firmware from file 'dvb-usb-it9137-01.fw' it913x: FRM Starting Firmware Download it913x: FRM Firmware Download Completed - Resetting Device it913x: Chip Version=01 Chip Type=9135 it913x: Firmware Version 204147968 usb 2-1: dvb_usb_v2: found a 'Digital Dual TV Receiver CTVDIGDUAL_V2' in warm state usb 2-1: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer DVB: registering new adapter (Digital Dual TV Receiver CTVDIGDUAL_V2) it913x-fe: ADF table value :00 it913x-fe: Crystal Frequency :12000000 Adc Frequency :20250000 ADC X2: 00 it913x-fe: Tuner LNA type :38 usb 2-1: DVB: registering adapter 1 frontend 0 (Digital Dual TV Receiver CTVDIGDUAL_V2_1)... usb 2-1: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer DVB: registering new adapter (Digital Dual TV Receiver CTVDIGDUAL_V2) it913x-fe: ADF table value :00 it913x-fe: Crystal Frequency :12000000 Adc Frequency :20250000 ADC X2: 00 it913x-fe: Tuner LNA type :38 usb 2-1: DVB: registering adapter 2 frontend 0 (Digital Dual TV Receiver CTVDIGDUAL_V2_2)... usb 2-1: dvb_usb_v2: 'Digital Dual TV Receiver CTVDIGDUAL_V2' successfully initialized and connected RC part not tested Signed-off-by: Alessandro Miceli Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/it913x.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 335a8f4695b4..2e0709a66f8f 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -367,4 +367,5 @@ #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 +#define USB_PID_CTVDIGDUAL_V2 0xe410 #endif diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c index e48cdeb9df41..1cb6899cf797 100644 --- a/drivers/media/usb/dvb-usb-v2/it913x.c +++ b/drivers/media/usb/dvb-usb-v2/it913x.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); static int dvb_usb_it913x_firmware; module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); -MODULE_PARM_DESC(firmware, "set firmware 0=auto"\ +MODULE_PARM_DESC(firmware, "set firmware 0=auto "\ "1=IT9137 2=IT9135 V1 3=IT9135 V2"); #define FW_IT9137 "dvb-usb-it9137-01.fw" #define FW_IT9135_V1 "dvb-usb-it9135-01.fw" @@ -796,6 +796,9 @@ static const struct usb_device_id it913x_id_table[] = { { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, &it913x_properties, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, + &it913x_properties, "Digital Dual TV Receiver CTVDIGDUAL_V2", + RC_MAP_IT913X_V1) }, {} /* Terminating entry */ }; -- GitLab From 3b98c347838d0a62476ea4c55daf5c315f56cbbb Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 11 Mar 2013 19:05:39 -0300 Subject: [PATCH 0780/2900] [media] af9035: implement I2C adapter read operation Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index b638fc1cd574..cfcf79b5978a 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -268,11 +268,29 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, memcpy(&buf[5], msg[0].buf, msg[0].len); ret = af9035_ctrl_msg(d, &req); } + } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { + if (msg[0].len > 40) { + /* TODO: correct limits > 40 */ + ret = -EOPNOTSUPP; + } else { + /* I2C */ + u8 buf[5]; + struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + buf, msg[0].len, msg[0].buf }; + req.mbox |= ((msg[0].addr & 0x80) >> 3); + buf[0] = msg[0].len; + buf[1] = msg[0].addr << 1; + buf[2] = 0x00; /* reg addr len */ + buf[3] = 0x00; /* reg addr MSB */ + buf[4] = 0x00; /* reg addr LSB */ + ret = af9035_ctrl_msg(d, &req); + } } else { /* - * We support only two kind of I2C transactions: - * 1) 1 x read + 1 x write + * We support only three kind of I2C transactions: + * 1) 1 x read + 1 x write (repeated start) * 2) 1 x write + * 3) 1 x read */ ret = -EOPNOTSUPP; } -- GitLab From cb9114e9633c2afd029ac88ed73eb2a0b8f14edf Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 3 Jun 2013 18:42:14 -0300 Subject: [PATCH 0781/2900] [media] af9035: make checkpatch.pl happy! Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index cfcf79b5978a..7d3b3c210e5f 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -91,9 +91,10 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) checksum = af9035_checksum(state->buf, rlen - 2); tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; if (tmp_checksum != checksum) { - dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \ - "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd, - tmp_checksum, checksum); + dev_err(&d->udev->dev, + "%s: command=%02x checksum mismatch (%04x != %04x)\n", + KBUILD_MODNAME, req->cmd, tmp_checksum, + checksum); ret = -EIO; goto exit; } @@ -400,9 +401,10 @@ static int af9035_download_firmware_old(struct dvb_usb_device *d, hdr_checksum = fw->data[fw->size - i + 5] << 8; hdr_checksum |= fw->data[fw->size - i + 6] << 0; - dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ - "checksum=%04x\n", __func__, hdr_core, hdr_addr, - hdr_data_len, hdr_checksum); + dev_dbg(&d->udev->dev, + "%s: core=%d addr=%04x data_len=%d checksum=%04x\n", + __func__, hdr_core, hdr_addr, hdr_data_len, + hdr_checksum); if (((hdr_core != 1) && (hdr_core != 2)) || (hdr_data_len > i)) { @@ -507,7 +509,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, u8 rbuf[4]; u8 tmp; struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; - struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; dev_dbg(&d->udev->dev, "%s:\n", __func__); /* @@ -1218,9 +1220,9 @@ static int af9035_init(struct dvb_usb_device *d) { 0x80f9a4, 0x00, 0x01 }, }; - dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ - "packet_size=%02x\n", __func__, - d->udev->speed, frame_size, packet_size); + dev_dbg(&d->udev->dev, + "%s: USB speed=%d frame_size=%04x packet_size=%02x\n", + __func__, d->udev->speed, frame_size, packet_size); /* init endpoints */ for (i = 0; i < ARRAY_SIZE(tab); i++) { @@ -1495,7 +1497,7 @@ static const struct usb_device_id af9035_id_table[] = { &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, &af9035_props, "Asus U3100Mini Plus", NULL) }, - { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, /* IT9135 devices */ #if 0 -- GitLab From e8292e28e3543fec62406551a026fcc0f2ca3cff Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 3 Jun 2013 18:50:43 -0300 Subject: [PATCH 0782/2900] [media] af9035: minor log writing changes Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 7d3b3c210e5f..e855ee6c86b5 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -55,7 +55,7 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", - __func__, req->wlen, req->rlen); + KBUILD_MODNAME, req->wlen, req->rlen); ret = -EINVAL; goto exit; } @@ -336,8 +336,8 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) dev_info(&d->udev->dev, "%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n", - __func__, state->prechip_version, state->chip_version, - state->chip_type); + KBUILD_MODNAME, state->prechip_version, + state->chip_version, state->chip_type); if (state->chip_type == 0x9135) { if (state->chip_version == 0x02) -- GitLab From d716ef46fbb9de22de09516ecff990fe4e7799e3 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Mon, 3 Jun 2013 19:39:51 -0300 Subject: [PATCH 0783/2900] [media] af9035: correct TS mode handling Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 14 ++++++++------ drivers/media/usb/dvb-usb-v2/af9035.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index e855ee6c86b5..1ea17dc2a76e 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -518,11 +518,11 @@ static int af9035_download_firmware(struct dvb_usb_device *d, * which is done by master demod. * Master feeds also clock and controls power via GPIO. */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); if (ret < 0) goto err; - if (tmp) { + if (tmp == 1 || tmp == 3) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -640,13 +640,15 @@ static int af9035_read_config(struct dvb_usb_device *d) } /* check if there is dual tuners */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); if (ret < 0) goto err; - state->dual_mode = tmp; - dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", __func__, - state->dual_mode); + if (tmp == 1 || tmp == 3) + state->dual_mode = true; + + dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, + tmp, state->dual_mode); if (state->dual_mode) { /* read 2nd demodulator I2C address */ diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index b5827ca3a01e..a1c68d829b8c 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -100,8 +100,13 @@ static const u32 clock_lut_it9135[] = { * eeprom is memory mapped as read only. Writing that memory mapped address * will not corrupt eeprom. * - * eeprom has value 0x00 single mode and 0x03 for dual mode as far as I have - * seen to this day. + * TS mode: + * 0 TS + * 1 DCA + PIP + * 3 PIP + * n DCA + * + * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. */ #define EEPROM_BASE_AF9035 0x42fd @@ -109,7 +114,7 @@ static const u32 clock_lut_it9135[] = { #define EEPROM_SHIFT 0x10 #define EEPROM_IR_MODE 0x10 -#define EEPROM_DUAL_MODE 0x29 +#define EEPROM_TS_MODE 0x29 #define EEPROM_2ND_DEMOD_ADDR 0x2a #define EEPROM_IR_TYPE 0x2c #define EEPROM_1_IF_L 0x30 -- GitLab From 1bddf1b3ac021feb9dafcc2c6ef7018453e22589 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 3 Jun 2013 05:16:13 -0300 Subject: [PATCH 0784/2900] [media] media: Rename media_entity_remote_source to media_entity_remote_pad Function media_entity_remote_source actually returns the remote pad to the given one, regardless if this is the source or the sink pad. Name media_entity_remote_pad is more adequate for this function. Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Acked-by: Sakari Ailus Acked-by: Sylwester Nawrocki Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/media-framework.txt | 2 +- drivers/media/media-entity.c | 13 ++++++------- drivers/media/platform/exynos4-is/fimc-capture.c | 6 +++--- drivers/media/platform/exynos4-is/fimc-lite.c | 4 ++-- drivers/media/platform/exynos4-is/media-dev.c | 2 +- drivers/media/platform/omap3isp/isp.c | 6 +++--- drivers/media/platform/omap3isp/ispccdc.c | 2 +- drivers/media/platform/omap3isp/ispccp2.c | 2 +- drivers/media/platform/omap3isp/ispcsi2.c | 2 +- drivers/media/platform/omap3isp/ispvideo.c | 6 +++--- drivers/media/platform/s3c-camif/camif-capture.c | 2 +- drivers/staging/media/davinci_vpfe/vpfe_video.c | 12 ++++++------ include/media/media-entity.h | 2 +- 13 files changed, 30 insertions(+), 31 deletions(-) diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 77bd0a42f19d..3702eff30db3 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -265,7 +265,7 @@ connected to another pad through an enabled link media_entity_find_link(struct media_pad *source, struct media_pad *sink); - media_entity_remote_source(struct media_pad *pad); + media_entity_remote_pad(struct media_pad *pad); Refer to the kerneldoc documentation for more information. diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e1cd13283407..0438209d020a 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -560,17 +560,16 @@ media_entity_find_link(struct media_pad *source, struct media_pad *sink) EXPORT_SYMBOL_GPL(media_entity_find_link); /** - * media_entity_remote_source - Find the source pad at the remote end of a link - * @pad: Sink pad at the local end of the link + * media_entity_remote_pad - Find the pad at the remote end of a link + * @pad: Pad at the local end of the link * - * Search for a remote source pad connected to the given sink pad by iterating - * over all links originating or terminating at that pad until an enabled link - * is found. + * Search for a remote pad connected to the given pad by iterating over all + * links originating or terminating at that pad until an enabled link is found. * * Return a pointer to the pad at the remote end of the first found enabled * link, or NULL if no enabled link has been found. */ -struct media_pad *media_entity_remote_source(struct media_pad *pad) +struct media_pad *media_entity_remote_pad(struct media_pad *pad) { unsigned int i; @@ -590,4 +589,4 @@ struct media_pad *media_entity_remote_source(struct media_pad *pad) return NULL; } -EXPORT_SYMBOL_GPL(media_entity_remote_source); +EXPORT_SYMBOL_GPL(media_entity_remote_pad); diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 528f41369364..a8b9b06d96aa 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -773,7 +773,7 @@ static struct media_entity *fimc_pipeline_get_head(struct media_entity *me) struct media_pad *pad = &me->pads[0]; while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) { - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (!pad) break; me = pad->entity; @@ -845,7 +845,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, return ret; } - pad = media_entity_remote_source(&me->pads[sfmt.pad]); + pad = media_entity_remote_pad(&me->pads[sfmt.pad]); if (!pad) return -EINVAL; me = pad->entity; @@ -1146,7 +1146,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) if (p->flags & MEDIA_PAD_FL_SINK) { sink_pad = p; - src_pad = media_entity_remote_source(sink_pad); + src_pad = media_entity_remote_pad(sink_pad); if (src_pad) break; } diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 14bb7bc8adbe..2f11ae4fd4a4 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -139,7 +139,7 @@ static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me) while (pad->flags & MEDIA_PAD_FL_SINK) { /* source pad */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -786,7 +786,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc) return -EPIPE; } /* Retrieve format at the source pad */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 15ef8f28239b..396e06e14a17 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -62,7 +62,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_pad *spad = &me->pads[i]; if (!(spad->flags & MEDIA_PAD_FL_SINK)) continue; - pad = media_entity_remote_source(spad); + pad = media_entity_remote_pad(spad); if (pad) break; } diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1d7dbd5c0fba..4c4bd3d1a2bc 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -877,7 +877,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe, if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -967,7 +967,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe) if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -1083,7 +1083,7 @@ static int isp_pipeline_is_last(struct media_entity *me) pipe = to_isp_pipeline(me); if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED) return 0; - pad = media_entity_remote_source(&pipe->output->pad); + pad = media_entity_remote_pad(&pipe->output->pad); return pad->entity == me; } diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 60e60aa64fb4..907a205da5a5 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -1120,7 +1120,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) u32 syn_mode; u32 ccdc_pattern; - pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]); + pad = media_entity_remote_pad(&ccdc->pads[CCDC_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); if (ccdc->input == CCDC_INPUT_PARALLEL) pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv) diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index c5d84c977e29..13982b0ab560 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -360,7 +360,7 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2) ccp2_pwr_cfg(ccp2); - pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]); + pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); pdata = sensor->host_priv; diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index 783f4b05b153..6db245d84bbb 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -573,7 +573,7 @@ static int csi2_configure(struct isp_csi2_device *csi2) if (csi2->contexts[0].enabled || csi2->ctrl.if_enable) return -EBUSY; - pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]); + pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); pdata = sensor->host_priv; diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 8dac17511e61..a908d006f527 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -219,7 +219,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad) { struct media_pad *remote; - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); if (remote == NULL || media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) @@ -314,7 +314,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe) * entity can be found, and stop checking the pipeline if the * source entity isn't a subdev. */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL) return -EPIPE; @@ -901,7 +901,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, continue; /* ISP entities have always sink pad == 0. Find source. */ - source_pad = media_entity_remote_source(&ents[i]->pads[0]); + source_pad = media_entity_remote_pad(&ents[i]->pads[0]); if (source_pad == NULL) continue; diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 70438a0f62ae..40b298ab87f1 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -845,7 +845,7 @@ static int camif_pipeline_validate(struct camif_dev *camif) int ret; /* Retrieve format at the sensor subdev source pad */ - pad = media_entity_remote_source(&camif->pads[0]); + pad = media_entity_remote_pad(&camif->pads[0]); if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) return -EPIPE; diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index ba913f1d955b..cb5410b390ef 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -39,7 +39,7 @@ static struct media_entity *vpfe_get_input_entity struct vpfe_device *vpfe_dev = video->vpfe_dev; struct media_pad *remote; - remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]); + remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); if (remote == NULL) { pr_err("Invalid media connection to isif/ccdc\n"); return NULL; @@ -56,7 +56,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) struct media_pad *remote; int i; - remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]); + remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); if (remote == NULL) { pr_err("Invalid media connection to isif/ccdc\n"); return -EINVAL; @@ -89,7 +89,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) static struct v4l2_subdev * vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad) { - struct media_pad *remote = media_entity_remote_source(&video->pad); + struct media_pad *remote = media_entity_remote_pad(&video->pad); if (remote == NULL || remote->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) return NULL; @@ -114,7 +114,7 @@ __vpfe_video_get_format(struct vpfe_video_device *video, return -EINVAL; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); fmt.pad = remote->index; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); @@ -245,7 +245,7 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) return -EPIPE; /* Retrieve the source format */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || pad->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -667,7 +667,7 @@ static int vpfe_enum_fmt(struct file *file, void *priv, return -EINVAL; } /* get the remote pad */ - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); if (remote == NULL) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote pad for video node\n"); diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 0c16f518ee09..4eefedcaa66d 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -132,7 +132,7 @@ int __media_entity_setup_link(struct media_link *link, u32 flags); int media_entity_setup_link(struct media_link *link, u32 flags); struct media_link *media_entity_find_link(struct media_pad *source, struct media_pad *sink); -struct media_pad *media_entity_remote_source(struct media_pad *pad); +struct media_pad *media_entity_remote_pad(struct media_pad *pad); struct media_entity *media_entity_get(struct media_entity *entity); void media_entity_put(struct media_entity *entity); -- GitLab From 1e41413f9869c4a688b2f937ff50584bd62eeb31 Mon Sep 17 00:00:00 2001 From: Rodrigo Tartajo Date: Sat, 20 Apr 2013 20:02:12 -0300 Subject: [PATCH 0785/2900] [media] rtl2832u: restore ir remote control support Hi, This patch uses the driver from openpli[1] as a template to restore the remote control support. I had to divert from the original to use the in kernel rc protocol decoder. The key repetition does, not seem to work but I cant find the problem in the driver. As a raw rc provider, no key table is hardcoded. Rodrigo. [1]: https://aur.archlinux.org/packages/dvb-usb-rtl2832u-openpli/?comments=all Signed-off-by: Rodrigo Tartajo Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 +- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 83 +++++++++++++++++++++---- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 11 ++++ 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 658c6d47fdff..399916bd588f 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -140,7 +140,7 @@ struct dvb_usb_rc { int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*query) (struct dvb_usb_device *d); unsigned int interval; - const enum rc_driver_type driver_type; + enum rc_driver_type driver_type; bool bulk_mode; }; diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 22015fe1a0f3..e592662ccc06 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1249,11 +1249,21 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, #if IS_ENABLED(CONFIG_RC_CORE) static int rtl2832u_rc_query(struct dvb_usb_device *d) { +#define TICSAT38KHZTONS(x) ((x) * (1000000000/38000)) int ret, i; struct rtl28xxu_priv *priv = d->priv; u8 buf[128]; int len; - struct rtl28xxu_reg_val rc_nec_tab[] = { + struct ir_raw_event ev; //encode single ir event (pulse or space) + struct rtl28xxu_xreg_val rc_sys_init_tab[] = { + { SYS_DEMOD_CTL1, OP_AND, 0xfb }, + { SYS_DEMOD_CTL1, OP_AND, 0xf7 }, + { USB_CTRL, OP_OR , 0x20 }, + { SYS_SYS1, OP_AND, 0xf7 }, + { SYS_GPIO_OUT_EN, OP_OR , 0x08 }, + { SYS_GPIO_OUT_VAL, OP_OR , 0x08 }, + }; // system hard init + struct rtl28xxu_reg_val rc_init_tab[] = { { IR_RX_CTRL, 0x20 }, { IR_RX_BUF_CTRL, 0x80 }, { IR_RX_IF, 0xff }, @@ -1268,13 +1278,40 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) { IR_MAX_H_TOL_LEN, 0x1e }, { IR_MAX_L_TOL_LEN, 0x1e }, { IR_RX_CTRL, 0x80 }, - }; + }; // hard init + struct rtl28xxu_reg_val rc_reinit_tab[] = { + { IR_RX_CTRL, 0x20 }, + { IR_RX_BUF_CTRL, 0x80 }, + { IR_RX_IF, 0xff }, + { IR_RX_IE, 0xff }, + { IR_RX_CTRL, 0x80 }, + }; // reinit IR + struct rtl28xxu_reg_val rc_clear_tab[] = { + { IR_RX_IF, 0x03 }, + { IR_RX_BUF_CTRL, 0x80 }, + { IR_RX_CTRL, 0x80 }, + }; // clear reception /* init remote controller */ if (!priv->rc_active) { - for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, - rc_nec_tab[i].val); + for (i = 0; i < ARRAY_SIZE(rc_sys_init_tab); i++) { + ret = rtl28xx_rd_reg(d, rc_sys_init_tab[i].reg, &buf[0]); + if (ret) + goto err; + if (rc_sys_init_tab[i].op == OP_AND) { + buf[0] &= rc_sys_init_tab[i].mask; + } + else {//OP_OR + buf[0] |= rc_sys_init_tab[i].mask; + } + ret = rtl28xx_wr_reg(d, rc_sys_init_tab[i].reg, + buf[0]); + if (ret) + goto err; + } + for (i = 0; i < ARRAY_SIZE(rc_init_tab); i++) { + ret = rtl28xx_wr_reg(d, rc_init_tab[i].reg, + rc_init_tab[i].val); if (ret) goto err; } @@ -1286,7 +1323,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; if (buf[0] != 0x83) - goto exit; + goto err; ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); if (ret) @@ -1295,26 +1332,48 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) len = buf[0]; ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); - /* TODO: pass raw IR to Kernel IR decoder */ + /* pass raw IR to Kernel IR decoder */ + init_ir_raw_event(&ev); + ir_raw_event_reset(d->rc_dev); + ev.pulse=1; + for(i=0; true; ++i) { // conver count to time + if (i >= len || !(buf[i] & 0x80) != !(ev.pulse)) {//end or transition pulse/space: flush + ir_raw_event_store(d->rc_dev, &ev); + ev.duration = 0; + } + if (i >= len) + break; + ev.pulse = buf[i] >> 7; + ev.duration += TICSAT38KHZTONS(((u32)(buf[i] & 0x7F)) << 1); + } + ir_raw_event_handle(d->rc_dev); - ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03); - ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); - ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); + for (i = 0; i < ARRAY_SIZE(rc_clear_tab); i++) { + ret = rtl28xx_wr_reg(d, rc_clear_tab[i].reg, + rc_clear_tab[i].val); + if (ret) + goto err; + } -exit: return ret; err: + for (i = 0; i < ARRAY_SIZE(rc_reinit_tab); i++) { + ret = rtl28xx_wr_reg(d, rc_reinit_tab[i].reg, + rc_reinit_tab[i].val); + } dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; +#undef TICSAT38KHZTONS } static int rtl2832u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_BIT_NEC; + rc->allowed_protos = RC_BIT_ALL; rc->query = rtl2832u_rc_query; rc->interval = 400; + rc->driver_type = RC_DRIVER_IR_RAW; return 0; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 533a33127289..0177b3871ba4 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -97,6 +97,17 @@ struct rtl28xxu_reg_val { u8 val; }; +enum OP{ + OP_AND =0, + OP_OR +}; + +struct rtl28xxu_xreg_val { + u16 reg; + u8 op; + u8 mask; +}; + /* * memory map * -- GitLab From f39fac3e409322d23261e89374a7d9daecfd6acb Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 09:17:03 -0300 Subject: [PATCH 0786/2900] [media] rtl28xxu: reimplement rtl2832u remote controller Thanks to Rodrigo for original implementation! Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 152 +++++++++--------------- drivers/media/usb/dvb-usb-v2/rtl28xxu.h | 9 +- 2 files changed, 58 insertions(+), 103 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index e592662ccc06..416701167434 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1114,17 +1114,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; } else { - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val |= 0x0c; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); - if (ret) - goto err; - /* set output values */ ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); if (ret) @@ -1249,72 +1238,44 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, #if IS_ENABLED(CONFIG_RC_CORE) static int rtl2832u_rc_query(struct dvb_usb_device *d) { -#define TICSAT38KHZTONS(x) ((x) * (1000000000/38000)) - int ret, i; + int ret, i, len; struct rtl28xxu_priv *priv = d->priv; + struct ir_raw_event ev; u8 buf[128]; - int len; - struct ir_raw_event ev; //encode single ir event (pulse or space) - struct rtl28xxu_xreg_val rc_sys_init_tab[] = { - { SYS_DEMOD_CTL1, OP_AND, 0xfb }, - { SYS_DEMOD_CTL1, OP_AND, 0xf7 }, - { USB_CTRL, OP_OR , 0x20 }, - { SYS_SYS1, OP_AND, 0xf7 }, - { SYS_GPIO_OUT_EN, OP_OR , 0x08 }, - { SYS_GPIO_OUT_VAL, OP_OR , 0x08 }, - }; // system hard init - struct rtl28xxu_reg_val rc_init_tab[] = { - { IR_RX_CTRL, 0x20 }, - { IR_RX_BUF_CTRL, 0x80 }, - { IR_RX_IF, 0xff }, - { IR_RX_IE, 0xff }, - { IR_MAX_DURATION0, 0xd0 }, - { IR_MAX_DURATION1, 0x07 }, - { IR_IDLE_LEN0, 0xc0 }, - { IR_IDLE_LEN1, 0x00 }, - { IR_GLITCH_LEN, 0x03 }, - { IR_RX_CLK, 0x09 }, - { IR_RX_CFG, 0x1c }, - { IR_MAX_H_TOL_LEN, 0x1e }, - { IR_MAX_L_TOL_LEN, 0x1e }, - { IR_RX_CTRL, 0x80 }, - }; // hard init - struct rtl28xxu_reg_val rc_reinit_tab[] = { - { IR_RX_CTRL, 0x20 }, - { IR_RX_BUF_CTRL, 0x80 }, - { IR_RX_IF, 0xff }, - { IR_RX_IE, 0xff }, - { IR_RX_CTRL, 0x80 }, - }; // reinit IR - struct rtl28xxu_reg_val rc_clear_tab[] = { - { IR_RX_IF, 0x03 }, - { IR_RX_BUF_CTRL, 0x80 }, - { IR_RX_CTRL, 0x80 }, - }; // clear reception + static const struct rtl28xxu_reg_val_mask refresh_tab[] = { + {IR_RX_IF, 0x03, 0xff}, + {IR_RX_BUF_CTRL, 0x80, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, + }; /* init remote controller */ if (!priv->rc_active) { - for (i = 0; i < ARRAY_SIZE(rc_sys_init_tab); i++) { - ret = rtl28xx_rd_reg(d, rc_sys_init_tab[i].reg, &buf[0]); - if (ret) - goto err; - if (rc_sys_init_tab[i].op == OP_AND) { - buf[0] &= rc_sys_init_tab[i].mask; - } - else {//OP_OR - buf[0] |= rc_sys_init_tab[i].mask; - } - ret = rtl28xx_wr_reg(d, rc_sys_init_tab[i].reg, - buf[0]); - if (ret) - goto err; - } - for (i = 0; i < ARRAY_SIZE(rc_init_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_init_tab[i].reg, - rc_init_tab[i].val); + static const struct rtl28xxu_reg_val_mask init_tab[] = { + {SYS_DEMOD_CTL1, 0x00, 0x04}, + {SYS_DEMOD_CTL1, 0x00, 0x08}, + {USB_CTRL, 0x20, 0x20}, + {SYS_GPIO_DIR, 0x00, 0x08}, + {SYS_GPIO_OUT_EN, 0x08, 0x08}, + {SYS_GPIO_OUT_VAL, 0x08, 0x08}, + {IR_MAX_DURATION0, 0xd0, 0xff}, + {IR_MAX_DURATION1, 0x07, 0xff}, + {IR_IDLE_LEN0, 0xc0, 0xff}, + {IR_IDLE_LEN1, 0x00, 0xff}, + {IR_GLITCH_LEN, 0x03, 0xff}, + {IR_RX_CLK, 0x09, 0xff}, + {IR_RX_CFG, 0x1c, 0xff}, + {IR_MAX_H_TOL_LEN, 0x1e, 0xff}, + {IR_MAX_L_TOL_LEN, 0x1e, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, + }; + + for (i = 0; i < ARRAY_SIZE(init_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, + init_tab[i].val, init_tab[i].mask); if (ret) goto err; } + priv->rc_active = true; } @@ -1323,57 +1284,56 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; if (buf[0] != 0x83) - goto err; + goto exit; ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]); if (ret) goto err; len = buf[0]; - ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); - /* pass raw IR to Kernel IR decoder */ - init_ir_raw_event(&ev); - ir_raw_event_reset(d->rc_dev); - ev.pulse=1; - for(i=0; true; ++i) { // conver count to time - if (i >= len || !(buf[i] & 0x80) != !(ev.pulse)) {//end or transition pulse/space: flush - ir_raw_event_store(d->rc_dev, &ev); - ev.duration = 0; - } - if (i >= len) - break; - ev.pulse = buf[i] >> 7; - ev.duration += TICSAT38KHZTONS(((u32)(buf[i] & 0x7F)) << 1); - } - ir_raw_event_handle(d->rc_dev); + /* read raw code from hw */ + ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + if (ret) + goto err; - for (i = 0; i < ARRAY_SIZE(rc_clear_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_clear_tab[i].reg, - rc_clear_tab[i].val); + /* let hw receive new code */ + for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, + refresh_tab[i].val, refresh_tab[i].mask); if (ret) goto err; } + /* pass data to Kernel IR decoder */ + init_ir_raw_event(&ev); + + for (i = 0; i < len; i++) { + ev.pulse = buf[i] >> 7; + ev.duration = 50800 * (buf[i] & 0x7f); + ir_raw_event_store_with_filter(d->rc_dev, &ev); + } + + /* 'flush' ir_raw_event_store_with_filter() */ + ir_raw_event_set_idle(d->rc_dev, true); + ir_raw_event_handle(d->rc_dev); +exit: return ret; err: - for (i = 0; i < ARRAY_SIZE(rc_reinit_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_reinit_tab[i].reg, - rc_reinit_tab[i].val); - } dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret); return ret; -#undef TICSAT38KHZTONS } static int rtl2832u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - rc->map_name = RC_MAP_EMPTY; + /* load empty to enable rc */ + if (!rc->map_name) + rc->map_name = RC_MAP_EMPTY; rc->allowed_protos = RC_BIT_ALL; + rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 400; - rc->driver_type = RC_DRIVER_IR_RAW; return 0; } diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 0177b3871ba4..729b3540c2f9 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -97,14 +97,9 @@ struct rtl28xxu_reg_val { u8 val; }; -enum OP{ - OP_AND =0, - OP_OR -}; - -struct rtl28xxu_xreg_val { +struct rtl28xxu_reg_val_mask { u16 reg; - u8 op; + u8 val; u8 mask; }; -- GitLab From 5a18664e49549762d09e771ad02111d2c2721dc8 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 16:50:54 -0300 Subject: [PATCH 0787/2900] [media] rtl28xxu: remove redundant IS_ENABLED macro Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 416701167434..8bbc6abc9d35 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1231,11 +1231,7 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, return 0; } -#else - #define rtl2831u_get_rc_config NULL -#endif -#if IS_ENABLED(CONFIG_RC_CORE) static int rtl2832u_rc_query(struct dvb_usb_device *d) { int ret, i, len; @@ -1338,7 +1334,8 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d, return 0; } #else - #define rtl2832u_get_rc_config NULL +#define rtl2831u_get_rc_config NULL +#define rtl2832u_get_rc_config NULL #endif static const struct dvb_usb_device_properties rtl2831u_props = { -- GitLab From 6c5a4065ebb785bd60fdab4eebbf6582177d563a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ustek?= Date: Tue, 14 May 2013 19:42:11 -0300 Subject: [PATCH 0788/2900] [media] rtl28xxu: Add USB ID for Leadtek WinFast DTV Dongle mini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USB ID 0413:6a03 is Leadtek WinFast DTV Dongle mini. Decoder Realtek RTL2832U and tuner Infineon TUA9001. Signed-off-by: Miroslav Šustek Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 8bbc6abc9d35..0045b198a537 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1424,6 +1424,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl2832u_props, "Compro VideoMate U620F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, &rtl2832u_props, "MaxMedia HU394-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, + &rtl2832u_props, "WinFast DTV Dongle mini", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); -- GitLab From 7dc0a0163498f922aa00051d0d8d438926d4d249 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 17:01:25 -0300 Subject: [PATCH 0789/2900] [media] rtl28xxu: correct some device names ... just because I want to be perfect ;) Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 0045b198a537..93313f70621c 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1419,13 +1419,13 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393, &rtl2832u_props, "GIGABYTE U7300", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104, - &rtl2832u_props, "Digivox Micro Hd", NULL) }, + &rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) }, { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, &rtl2832u_props, "Compro VideoMate U620F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, &rtl2832u_props, "MaxMedia HU394-T", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, - &rtl2832u_props, "WinFast DTV Dongle mini", NULL) }, + &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); -- GitLab From bc6fc53de8935031078c50b8a06324aeaf1b4034 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 17:24:06 -0300 Subject: [PATCH 0790/2900] [media] rtl28xxu: map remote for TerraTec Cinergy T Stick Black Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 93313f70621c..04da6be4de27 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1395,7 +1395,7 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, - &rtl2832u_props, "TerraTec Cinergy T Stick Black", NULL) }, + &rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, -- GitLab From 526ca8dc6ad844550e037841bd5f7090db9e1d4f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 18:26:54 -0300 Subject: [PATCH 0791/2900] [media] rtl28xxu: use masked reg write where possible Use masked register write inside rtl2832u_power_ctrl(). Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 72 ++++++------------------- 1 file changed, 16 insertions(+), 56 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 04da6be4de27..6f5a3d0c818f 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1041,67 +1041,34 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff) static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - u8 val; dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); if (onoff) { - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - val |= 0x08; - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); - if (ret) - goto err; - - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); - if (ret) - goto err; - - /* demod control */ - /* PLL enable */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); + /* GPIO3=1, GPIO4=0 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); if (ret) goto err; - /* bit 7 to 1 */ - val |= 0x80; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* suspend? */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); if (ret) goto err; - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); + /* enable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); if (ret) goto err; - val |= 0x20; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable reset */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); if (ret) goto err; mdelay(5); - /*enable ADC_Q and ADC_I */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val |= 0x48; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* enable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48); if (ret) goto err; @@ -1114,25 +1081,18 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; } else { - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - val |= 0x10; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + /* GPIO4=1 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); if (ret) goto err; - /* demod control */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); + /* disable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48); if (ret) goto err; - val &= 0x37; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); if (ret) goto err; -- GitLab From c6be75264b15cdabf067f8b78e954d26f6bab2a4 Mon Sep 17 00:00:00 2001 From: Alessandro Miceli Date: Tue, 4 Jun 2013 16:10:34 -0300 Subject: [PATCH 0792/2900] [media] Add support for Crypto Redi PC50A device (rtl2832u + FC0012 tuner) The device has been tested on a MIPSel box with kernel 3.1.1 and backported media_tree drivers The kernel detects the device with the following output: usbcore: registered new interface driver dvb_usb_rtl28xxu usb 1-2: dvb_usb_v2: found a 'Crypto Redi PC50A' in warm state usb 1-2: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer DVB: registering new adapter (Crypto Redi PC50A) usb 1-2: DVB: registering adapter 1 frontend 0 (Realtek RTL2832 (DVB-T))... i2c i2c-4: fc0012: Fitipower FC0012 successfully identified usb 1-2: dvb_usb_v2: 'Crypto Redi PC50A' successfully initialized and connected [crope@iki.fi: fix trivial merge conflict] Signed-off-by: Alessandro Miceli Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 2e0709a66f8f..886da16e14f2 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -367,5 +367,6 @@ #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 +#define USB_PID_CPYTO_REDI_PC50A 0xa803 #define USB_PID_CTVDIGDUAL_V2 0xe410 #endif diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 6f5a3d0c818f..a49abe4fa75b 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1386,6 +1386,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl2832u_props, "MaxMedia HU394-T", NULL) }, { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, + { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, + &rtl2832u_props, "Crypto Redi PC50A", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); -- GitLab From 7df272563aa3ffc201ddfe2431de9bb7456e3ea6 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 4 Jun 2013 19:43:30 -0300 Subject: [PATCH 0793/2900] [media] rtl28xxu: correct latest device name Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index a49abe4fa75b..9a3c044fda3b 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1387,7 +1387,7 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, - &rtl2832u_props, "Crypto Redi PC50A", NULL) }, + &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); -- GitLab From b5e9eb6f529b5741322d1981bb176785f115d446 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:43 -0300 Subject: [PATCH 0794/2900] [media] drxk_hard: don't re-implement log10 X-Patchwork-Delegate: mchehab@redhat.com Log10 routine is already defined at dvb_math.h and provides a good enough approximation for 100 x log10(). So, instead of reinventing the wheel, use the already existing function. While here, don't use CamelCase on the function name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 104 ++---------------------- 1 file changed, 8 insertions(+), 96 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index ec24d71e153d..41b637534ed4 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -34,6 +34,7 @@ #include "dvb_frontend.h" #include "drxk.h" #include "drxk_hard.h" +#include "dvb_math.h" static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode); static int PowerDownQAM(struct drxk_state *state); @@ -201,98 +202,9 @@ static inline u32 Frac28a(u32 a, u32 c) return Q1; } -static u32 Log10Times100(u32 x) +static inline u32 log10times100(u32 value) { - static const u8 scale = 15; - static const u8 indexWidth = 5; - u8 i = 0; - u32 y = 0; - u32 d = 0; - u32 k = 0; - u32 r = 0; - /* - log2lut[n] = (1< 0; k--) { - if (x & (((u32) 1) << scale)) - break; - x <<= 1; - } - } else { - for (k = scale; k < 31; k++) { - if ((x & (((u32) (-1)) << (scale + 1))) == 0) - break; - x >>= 1; - } - } - /* - Now x has binary point between bit[scale] and bit[scale-1] - and 1.0 <= x < 2.0 */ - - /* correction for divison: log(x) = log(x/y)+log(y) */ - y = k * ((((u32) 1) << scale) * 200); - - /* remove integer part */ - x &= ((((u32) 1) << scale) - 1); - /* get index */ - i = (u8) (x >> (scale - indexWidth)); - /* compute delta (x - a) */ - d = x & ((((u32) 1) << (scale - indexWidth)) - 1); - /* compute log, multiplication (d* (..)) must be within range ! */ - y += log2lut[i] + - ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth)); - /* Conver to log10() */ - y /= 108853; /* (log2(10) << scale) */ - r = (y >> 1); - /* rounding */ - if (y & ((u32) 1)) - r++; - return r; + return (100L * intlog10(value)) >> 24; } /****************************************************************************/ @@ -2530,8 +2442,8 @@ static int GetQAMSignalToNoise(struct drxk_state *state, } if (qamSlErrPower > 0) { - qamSlMer = Log10Times100(qamSlSigPower) - - Log10Times100((u32) qamSlErrPower); + qamSlMer = log10times100(qamSlSigPower) - + log10times100((u32) qamSlErrPower); } *pSignalToNoise = qamSlMer; @@ -2620,12 +2532,12 @@ static int GetDVBTSignalToNoise(struct drxk_state *state, */ /* log(x) x = 9bits * 9bits->18 bits */ - a = Log10Times100(EqRegTdTpsPwrOfs * + a = log10times100(EqRegTdTpsPwrOfs * EqRegTdTpsPwrOfs); /* log(x) x = 16bits * 7bits->23 bits */ - b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt); + b = log10times100(EqRegTdReqSmbCnt * tpsCnt); /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ - c = Log10Times100(SqrErrIQ); + c = log10times100(SqrErrIQ); iMER = a + b - c; } -- GitLab From cd7a67a4f18047ca7b8ce2f48b4c540d69c9b793 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:44 -0300 Subject: [PATCH 0795/2900] [media] drxk_hard: Don't use CamelCase X-Patchwork-Delegate: mchehab@redhat.com Thare are lots of CamelCase warnings produced by checkpatch.pl. This weren't fixed at the time the driver got submitted due to the lack of manpower do to such cleanup. Now that I have one script that automates this task, cleans it. That makes the driver almost checkpatch-compliant, except for 80 column warnings. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk.h | 2 +- drivers/media/dvb-frontends/drxk_hard.c | 2558 +++++++++++------------ drivers/media/dvb-frontends/drxk_hard.h | 248 +-- 3 files changed, 1404 insertions(+), 1404 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index e6667189ddce..f22eb9f13ad5 100644 --- a/drivers/media/dvb-frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h @@ -8,7 +8,7 @@ /** * struct drxk_config - Configure the initial parameters for DRX-K * - * @adr: I2C Address of the DRX-K + * @adr: I2C address of the DRX-K * @parallel_ts: True means that the device uses parallel TS, * Serial otherwise. * @dynamic_clk: True means that the clock will be dynamically diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 41b637534ed4..d2b331a46a6d 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -36,34 +36,34 @@ #include "drxk_hard.h" #include "dvb_math.h" -static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode); -static int PowerDownQAM(struct drxk_state *state); -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode); -static int SetQAMStandard(struct drxk_state *state, - enum OperationMode oMode); -static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset); -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode); -static int DVBTStart(struct drxk_state *state); -static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset); -static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus); -static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus); -static int SwitchAntennaToQAM(struct drxk_state *state); -static int SwitchAntennaToDVBT(struct drxk_state *state); - -static bool IsDVBT(struct drxk_state *state) +static int power_down_dvbt(struct drxk_state *state, bool set_power_mode); +static int power_down_qam(struct drxk_state *state); +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int set_qam_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset); +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int dvbt_start(struct drxk_state *state); +static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset); +static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status); +static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status); +static int switch_antenna_to_qam(struct drxk_state *state); +static int switch_antenna_to_dvbt(struct drxk_state *state); + +static bool is_dvbt(struct drxk_state *state) { - return state->m_OperationMode == OM_DVBT; + return state->m_operation_mode == OM_DVBT; } -static bool IsQAM(struct drxk_state *state) +static bool is_qam(struct drxk_state *state) { - return state->m_OperationMode == OM_QAM_ITU_A || - state->m_OperationMode == OM_QAM_ITU_B || - state->m_OperationMode == OM_QAM_ITU_C; + return state->m_operation_mode == OM_QAM_ITU_A || + state->m_operation_mode == OM_QAM_ITU_B || + state->m_operation_mode == OM_QAM_ITU_C; } #define NOA1ROM 0 @@ -432,55 +432,55 @@ static int write32(struct drxk_state *state, u32 reg, u32 data) return write32_flags(state, reg, data, 0); } -static int write_block(struct drxk_state *state, u32 Address, - const int BlockSize, const u8 pBlock[]) +static int write_block(struct drxk_state *state, u32 address, + const int block_size, const u8 p_block[]) { - int status = 0, BlkSize = BlockSize; - u8 Flags = 0; + int status = 0, blk_size = block_size; + u8 flags = 0; if (state->single_master) - Flags |= 0xC0; - - while (BlkSize > 0) { - int Chunk = BlkSize > state->m_ChunkSize ? - state->m_ChunkSize : BlkSize; - u8 *AdrBuf = &state->Chunk[0]; - u32 AdrLength = 0; - - if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) { - AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01); - AdrBuf[1] = ((Address >> 16) & 0xFF); - AdrBuf[2] = ((Address >> 24) & 0xFF); - AdrBuf[3] = ((Address >> 7) & 0xFF); - AdrBuf[2] |= Flags; - AdrLength = 4; - if (Chunk == state->m_ChunkSize) - Chunk -= 2; + flags |= 0xC0; + + while (blk_size > 0) { + int chunk = blk_size > state->m_chunk_size ? + state->m_chunk_size : blk_size; + u8 *adr_buf = &state->chunk[0]; + u32 adr_length = 0; + + if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) { + adr_buf[0] = (((address << 1) & 0xFF) | 0x01); + adr_buf[1] = ((address >> 16) & 0xFF); + adr_buf[2] = ((address >> 24) & 0xFF); + adr_buf[3] = ((address >> 7) & 0xFF); + adr_buf[2] |= flags; + adr_length = 4; + if (chunk == state->m_chunk_size) + chunk -= 2; } else { - AdrBuf[0] = ((Address << 1) & 0xFF); - AdrBuf[1] = (((Address >> 16) & 0x0F) | - ((Address >> 18) & 0xF0)); - AdrLength = 2; + adr_buf[0] = ((address << 1) & 0xFF); + adr_buf[1] = (((address >> 16) & 0x0F) | + ((address >> 18) & 0xF0)); + adr_length = 2; } - memcpy(&state->Chunk[AdrLength], pBlock, Chunk); - dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags); + memcpy(&state->chunk[adr_length], p_block, chunk); + dprintk(2, "(0x%08x, 0x%02x)\n", address, flags); if (debug > 1) { int i; - if (pBlock) - for (i = 0; i < Chunk; i++) - printk(KERN_CONT " %02x", pBlock[i]); + if (p_block) + for (i = 0; i < chunk; i++) + printk(KERN_CONT " %02x", p_block[i]); printk(KERN_CONT "\n"); } status = i2c_write(state, state->demod_address, - &state->Chunk[0], Chunk + AdrLength); + &state->chunk[0], chunk + adr_length); if (status < 0) { printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", - __func__, Address); + __func__, address); break; } - pBlock += Chunk; - Address += (Chunk >> 1); - BlkSize -= Chunk; + p_block += chunk; + address += (chunk >> 1); + blk_size -= chunk; } return status; } @@ -489,11 +489,11 @@ static int write_block(struct drxk_state *state, u32 Address, #define DRXK_MAX_RETRIES_POWERUP 20 #endif -static int PowerUpDevice(struct drxk_state *state) +static int power_up_device(struct drxk_state *state) { int status; u8 data = 0; - u16 retryCount = 0; + u16 retry_count = 0; dprintk(1, "\n"); @@ -504,14 +504,14 @@ static int PowerUpDevice(struct drxk_state *state) status = i2c_write(state, state->demod_address, &data, 1); msleep(10); - retryCount++; + retry_count++; if (status < 0) continue; status = i2c_read1(state, state->demod_address, &data); } while (status < 0 && - (retryCount < DRXK_MAX_RETRIES_POWERUP)); - if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP) + (retry_count < DRXK_MAX_RETRIES_POWERUP)); + if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP) goto error; } @@ -527,7 +527,7 @@ static int PowerUpDevice(struct drxk_state *state) if (status < 0) goto error; - state->m_currentPowerMode = DRX_POWER_UP; + state->m_current_power_mode = DRX_POWER_UP; error: if (status < 0) @@ -543,106 +543,106 @@ static int init_state(struct drxk_state *state) * FIXME: most (all?) of the values bellow should be moved into * struct drxk_config, as they are probably board-specific */ - u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulVSBIfAgcOutputLevel = 0; - u32 ulVSBIfAgcMinLevel = 0; - u32 ulVSBIfAgcMaxLevel = 0x7FFF; - u32 ulVSBIfAgcSpeed = 3; - - u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulVSBRfAgcOutputLevel = 0; - u32 ulVSBRfAgcMinLevel = 0; - u32 ulVSBRfAgcMaxLevel = 0x7FFF; - u32 ulVSBRfAgcSpeed = 3; - u32 ulVSBRfAgcTop = 9500; - u32 ulVSBRfAgcCutOffCurrent = 4000; - - u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulATVIfAgcOutputLevel = 0; - u32 ulATVIfAgcMinLevel = 0; - u32 ulATVIfAgcMaxLevel = 0; - u32 ulATVIfAgcSpeed = 3; - - u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF; - u32 ulATVRfAgcOutputLevel = 0; - u32 ulATVRfAgcMinLevel = 0; - u32 ulATVRfAgcMaxLevel = 0; - u32 ulATVRfAgcTop = 9500; - u32 ulATVRfAgcCutOffCurrent = 4000; - u32 ulATVRfAgcSpeed = 3; + u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_vsb_if_agc_output_level = 0; + u32 ul_vsb_if_agc_min_level = 0; + u32 ul_vsb_if_agc_max_level = 0x7FFF; + u32 ul_vsb_if_agc_speed = 3; + + u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_vsb_rf_agc_output_level = 0; + u32 ul_vsb_rf_agc_min_level = 0; + u32 ul_vsb_rf_agc_max_level = 0x7FFF; + u32 ul_vsb_rf_agc_speed = 3; + u32 ul_vsb_rf_agc_top = 9500; + u32 ul_vsb_rf_agc_cut_off_current = 4000; + + u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_atv_if_agc_output_level = 0; + u32 ul_atv_if_agc_min_level = 0; + u32 ul_atv_if_agc_max_level = 0; + u32 ul_atv_if_agc_speed = 3; + + u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF; + u32 ul_atv_rf_agc_output_level = 0; + u32 ul_atv_rf_agc_min_level = 0; + u32 ul_atv_rf_agc_max_level = 0; + u32 ul_atv_rf_agc_top = 9500; + u32 ul_atv_rf_agc_cut_off_current = 4000; + u32 ul_atv_rf_agc_speed = 3; u32 ulQual83 = DEFAULT_MER_83; u32 ulQual93 = DEFAULT_MER_93; - u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; - u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ /* io_pad_cfg_mode output mode is drive always */ /* io_pad_cfg_drive is set to power 2 (23 mA) */ - u32 ulGPIOCfg = 0x0113; - u32 ulInvertTSClock = 0; - u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; - u32 ulDVBTBitrate = 50000000; - u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; + u32 ul_gpio_cfg = 0x0113; + u32 ul_invert_ts_clock = 0; + u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; + u32 ul_dvbt_bitrate = 50000000; + u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; - u32 ulInsertRSByte = 0; + u32 ul_insert_rs_byte = 0; - u32 ulRfMirror = 1; - u32 ulPowerDown = 0; + u32 ul_rf_mirror = 1; + u32 ul_power_down = 0; dprintk(1, "\n"); - state->m_hasLNA = false; - state->m_hasDVBT = false; - state->m_hasDVBC = false; - state->m_hasATV = false; - state->m_hasOOB = false; - state->m_hasAudio = false; + state->m_has_lna = false; + state->m_has_dvbt = false; + state->m_has_dvbc = false; + state->m_has_atv = false; + state->m_has_oob = false; + state->m_has_audio = false; - if (!state->m_ChunkSize) - state->m_ChunkSize = 124; + if (!state->m_chunk_size) + state->m_chunk_size = 124; - state->m_oscClockFreq = 0; - state->m_smartAntInverted = false; - state->m_bPDownOpenBridge = false; + state->m_osc_clock_freq = 0; + state->m_smart_ant_inverted = false; + state->m_b_p_down_open_bridge = false; /* real system clock frequency in kHz */ - state->m_sysClockFreq = 151875; + state->m_sys_clock_freq = 151875; /* Timing div, 250ns/Psys */ /* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */ - state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) * + state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000; /* Clipping */ - if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) - state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; - state->m_HICfgWakeUpKey = (state->demod_address << 1); + if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) + state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; + state->m_hi_cfg_wake_up_key = (state->demod_address << 1); /* port/bridge/power down ctrl */ - state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - state->m_bPowerDown = (ulPowerDown != 0); + state->m_b_power_down = (ul_power_down != 0); - state->m_DRXK_A3_PATCH_CODE = false; + state->m_drxk_a3_patch_code = false; /* Init AGC and PGA parameters */ /* VSB IF */ - state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode); - state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel); - state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel); - state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel); - state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed); - state->m_vsbPgaCfg = 140; + state->m_vsb_if_agc_cfg.ctrl_mode = (ul_vsb_if_agc_mode); + state->m_vsb_if_agc_cfg.output_level = (ul_vsb_if_agc_output_level); + state->m_vsb_if_agc_cfg.min_output_level = (ul_vsb_if_agc_min_level); + state->m_vsb_if_agc_cfg.max_output_level = (ul_vsb_if_agc_max_level); + state->m_vsb_if_agc_cfg.speed = (ul_vsb_if_agc_speed); + state->m_vsb_pga_cfg = 140; /* VSB RF */ - state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode); - state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel); - state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel); - state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel); - state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed); - state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop); - state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent); - state->m_vsbPreSawCfg.reference = 0x07; - state->m_vsbPreSawCfg.usePreSaw = true; + state->m_vsb_rf_agc_cfg.ctrl_mode = (ul_vsb_rf_agc_mode); + state->m_vsb_rf_agc_cfg.output_level = (ul_vsb_rf_agc_output_level); + state->m_vsb_rf_agc_cfg.min_output_level = (ul_vsb_rf_agc_min_level); + state->m_vsb_rf_agc_cfg.max_output_level = (ul_vsb_rf_agc_max_level); + state->m_vsb_rf_agc_cfg.speed = (ul_vsb_rf_agc_speed); + state->m_vsb_rf_agc_cfg.top = (ul_vsb_rf_agc_top); + state->m_vsb_rf_agc_cfg.cut_off_current = (ul_vsb_rf_agc_cut_off_current); + state->m_vsb_pre_saw_cfg.reference = 0x07; + state->m_vsb_pre_saw_cfg.use_pre_saw = true; state->m_Quality83percent = DEFAULT_MER_83; state->m_Quality93percent = DEFAULT_MER_93; @@ -652,127 +652,127 @@ static int init_state(struct drxk_state *state) } /* ATV IF */ - state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode); - state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel); - state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel); - state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel); - state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed); + state->m_atv_if_agc_cfg.ctrl_mode = (ul_atv_if_agc_mode); + state->m_atv_if_agc_cfg.output_level = (ul_atv_if_agc_output_level); + state->m_atv_if_agc_cfg.min_output_level = (ul_atv_if_agc_min_level); + state->m_atv_if_agc_cfg.max_output_level = (ul_atv_if_agc_max_level); + state->m_atv_if_agc_cfg.speed = (ul_atv_if_agc_speed); /* ATV RF */ - state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode); - state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel); - state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel); - state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel); - state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed); - state->m_atvRfAgcCfg.top = (ulATVRfAgcTop); - state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent); - state->m_atvPreSawCfg.reference = 0x04; - state->m_atvPreSawCfg.usePreSaw = true; + state->m_atv_rf_agc_cfg.ctrl_mode = (ul_atv_rf_agc_mode); + state->m_atv_rf_agc_cfg.output_level = (ul_atv_rf_agc_output_level); + state->m_atv_rf_agc_cfg.min_output_level = (ul_atv_rf_agc_min_level); + state->m_atv_rf_agc_cfg.max_output_level = (ul_atv_rf_agc_max_level); + state->m_atv_rf_agc_cfg.speed = (ul_atv_rf_agc_speed); + state->m_atv_rf_agc_cfg.top = (ul_atv_rf_agc_top); + state->m_atv_rf_agc_cfg.cut_off_current = (ul_atv_rf_agc_cut_off_current); + state->m_atv_pre_saw_cfg.reference = 0x04; + state->m_atv_pre_saw_cfg.use_pre_saw = true; /* DVBT RF */ - state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; - state->m_dvbtRfAgcCfg.outputLevel = 0; - state->m_dvbtRfAgcCfg.minOutputLevel = 0; - state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF; - state->m_dvbtRfAgcCfg.top = 0x2100; - state->m_dvbtRfAgcCfg.cutOffCurrent = 4000; - state->m_dvbtRfAgcCfg.speed = 1; + state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; + state->m_dvbt_rf_agc_cfg.output_level = 0; + state->m_dvbt_rf_agc_cfg.min_output_level = 0; + state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF; + state->m_dvbt_rf_agc_cfg.top = 0x2100; + state->m_dvbt_rf_agc_cfg.cut_off_current = 4000; + state->m_dvbt_rf_agc_cfg.speed = 1; /* DVBT IF */ - state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; - state->m_dvbtIfAgcCfg.outputLevel = 0; - state->m_dvbtIfAgcCfg.minOutputLevel = 0; - state->m_dvbtIfAgcCfg.maxOutputLevel = 9000; - state->m_dvbtIfAgcCfg.top = 13424; - state->m_dvbtIfAgcCfg.cutOffCurrent = 0; - state->m_dvbtIfAgcCfg.speed = 3; - state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30; - state->m_dvbtIfAgcCfg.IngainTgtMax = 30000; + state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; + state->m_dvbt_if_agc_cfg.output_level = 0; + state->m_dvbt_if_agc_cfg.min_output_level = 0; + state->m_dvbt_if_agc_cfg.max_output_level = 9000; + state->m_dvbt_if_agc_cfg.top = 13424; + state->m_dvbt_if_agc_cfg.cut_off_current = 0; + state->m_dvbt_if_agc_cfg.speed = 3; + state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30; + state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000; /* state->m_dvbtPgaCfg = 140; */ - state->m_dvbtPreSawCfg.reference = 4; - state->m_dvbtPreSawCfg.usePreSaw = false; + state->m_dvbt_pre_saw_cfg.reference = 4; + state->m_dvbt_pre_saw_cfg.use_pre_saw = false; /* QAM RF */ - state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; - state->m_qamRfAgcCfg.outputLevel = 0; - state->m_qamRfAgcCfg.minOutputLevel = 6023; - state->m_qamRfAgcCfg.maxOutputLevel = 27000; - state->m_qamRfAgcCfg.top = 0x2380; - state->m_qamRfAgcCfg.cutOffCurrent = 4000; - state->m_qamRfAgcCfg.speed = 3; + state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; + state->m_qam_rf_agc_cfg.output_level = 0; + state->m_qam_rf_agc_cfg.min_output_level = 6023; + state->m_qam_rf_agc_cfg.max_output_level = 27000; + state->m_qam_rf_agc_cfg.top = 0x2380; + state->m_qam_rf_agc_cfg.cut_off_current = 4000; + state->m_qam_rf_agc_cfg.speed = 3; /* QAM IF */ - state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; - state->m_qamIfAgcCfg.outputLevel = 0; - state->m_qamIfAgcCfg.minOutputLevel = 0; - state->m_qamIfAgcCfg.maxOutputLevel = 9000; - state->m_qamIfAgcCfg.top = 0x0511; - state->m_qamIfAgcCfg.cutOffCurrent = 0; - state->m_qamIfAgcCfg.speed = 3; - state->m_qamIfAgcCfg.IngainTgtMax = 5119; - state->m_qamIfAgcCfg.FastClipCtrlDelay = 50; - - state->m_qamPgaCfg = 140; - state->m_qamPreSawCfg.reference = 4; - state->m_qamPreSawCfg.usePreSaw = false; - - state->m_OperationMode = OM_NONE; - state->m_DrxkState = DRXK_UNINITIALIZED; + state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; + state->m_qam_if_agc_cfg.output_level = 0; + state->m_qam_if_agc_cfg.min_output_level = 0; + state->m_qam_if_agc_cfg.max_output_level = 9000; + state->m_qam_if_agc_cfg.top = 0x0511; + state->m_qam_if_agc_cfg.cut_off_current = 0; + state->m_qam_if_agc_cfg.speed = 3; + state->m_qam_if_agc_cfg.ingain_tgt_max = 5119; + state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50; + + state->m_qam_pga_cfg = 140; + state->m_qam_pre_saw_cfg.reference = 4; + state->m_qam_pre_saw_cfg.use_pre_saw = false; + + state->m_operation_mode = OM_NONE; + state->m_drxk_state = DRXK_UNINITIALIZED; /* MPEG output configuration */ - state->m_enableMPEGOutput = true; /* If TRUE; enable MPEG ouput */ - state->m_insertRSByte = false; /* If TRUE; insert RS byte */ - state->m_invertDATA = false; /* If TRUE; invert DATA signals */ - state->m_invertERR = false; /* If TRUE; invert ERR signal */ - state->m_invertSTR = false; /* If TRUE; invert STR signals */ - state->m_invertVAL = false; /* If TRUE; invert VAL signals */ - state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ + state->m_enable_mpeg_output = true; /* If TRUE; enable MPEG ouput */ + state->m_insert_rs_byte = false; /* If TRUE; insert RS byte */ + state->m_invert_data = false; /* If TRUE; invert DATA signals */ + state->m_invert_err = false; /* If TRUE; invert ERR signal */ + state->m_invert_str = false; /* If TRUE; invert STR signals */ + state->m_invert_val = false; /* If TRUE; invert VAL signals */ + state->m_invert_clk = (ul_invert_ts_clock != 0); /* If TRUE; invert CLK signals */ /* If TRUE; static MPEG clockrate will be used; otherwise clockrate will adapt to the bitrate of the TS */ - state->m_DVBTBitrate = ulDVBTBitrate; - state->m_DVBCBitrate = ulDVBCBitrate; + state->m_dvbt_bitrate = ul_dvbt_bitrate; + state->m_dvbc_bitrate = ul_dvbc_bitrate; - state->m_TSDataStrength = (ulTSDataStrength & 0x07); + state->m_ts_data_strength = (ul_ts_data_strength & 0x07); /* Maximum bitrate in b/s in case static clockrate is selected */ - state->m_mpegTsStaticBitrate = 19392658; - state->m_disableTEIhandling = false; + state->m_mpeg_ts_static_bitrate = 19392658; + state->m_disable_te_ihandling = false; - if (ulInsertRSByte) - state->m_insertRSByte = true; + if (ul_insert_rs_byte) + state->m_insert_rs_byte = true; - state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; - if (ulMpegLockTimeOut < 10000) - state->m_MpegLockTimeOut = ulMpegLockTimeOut; - state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; - if (ulDemodLockTimeOut < 10000) - state->m_DemodLockTimeOut = ulDemodLockTimeOut; + state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + if (ul_mpeg_lock_time_out < 10000) + state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out; + state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + if (ul_demod_lock_time_out < 10000) + state->m_demod_lock_time_out = ul_demod_lock_time_out; /* QAM defaults */ - state->m_Constellation = DRX_CONSTELLATION_AUTO; - state->m_qamInterleaveMode = DRXK_QAM_I12_J17; - state->m_fecRsPlen = 204 * 8; /* fecRsPlen annex A */ - state->m_fecRsPrescale = 1; + state->m_constellation = DRX_CONSTELLATION_AUTO; + state->m_qam_interleave_mode = DRXK_QAM_I12_J17; + state->m_fec_rs_plen = 204 * 8; /* fecRsPlen annex A */ + state->m_fec_rs_prescale = 1; - state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM; - state->m_agcFastClipCtrlDelay = 0; + state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM; + state->m_agcfast_clip_ctrl_delay = 0; - state->m_GPIOCfg = (ulGPIOCfg); + state->m_gpio_cfg = (ul_gpio_cfg); - state->m_bPowerDown = false; - state->m_currentPowerMode = DRX_POWER_DOWN; + state->m_b_power_down = false; + state->m_current_power_mode = DRX_POWER_DOWN; - state->m_rfmirror = (ulRfMirror == 0); - state->m_IfAgcPol = false; + state->m_rfmirror = (ul_rf_mirror == 0); + state->m_if_agc_pol = false; return 0; } -static int DRXX_Open(struct drxk_state *state) +static int drxx_open(struct drxk_state *state) { int status = 0; u32 jtag = 0; @@ -804,10 +804,10 @@ static int DRXX_Open(struct drxk_state *state) return status; } -static int GetDeviceCapabilities(struct drxk_state *state) +static int get_device_capabilities(struct drxk_state *state) { - u16 sioPdrOhwCfg = 0; - u32 sioTopJtagidLo = 0; + u16 sio_pdr_ohw_cfg = 0; + u32 sio_top_jtagid_lo = 0; int status; const char *spin = ""; @@ -821,28 +821,28 @@ static int GetDeviceCapabilities(struct drxk_state *state) status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); if (status < 0) goto error; - status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg); + status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg); if (status < 0) goto error; status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); if (status < 0) goto error; - switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { + switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { case 0: /* ignore (bypass ?) */ break; case 1: /* 27 MHz */ - state->m_oscClockFreq = 27000; + state->m_osc_clock_freq = 27000; break; case 2: /* 20.25 MHz */ - state->m_oscClockFreq = 20250; + state->m_osc_clock_freq = 20250; break; case 3: /* 4 MHz */ - state->m_oscClockFreq = 20250; + state->m_osc_clock_freq = 20250; break; default: printk(KERN_ERR "drxk: Clock Frequency is unknown\n"); @@ -852,150 +852,150 @@ static int GetDeviceCapabilities(struct drxk_state *state) Determine device capabilities Based on pinning v14 */ - status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo); + status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo); if (status < 0) goto error; - printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo); + printk(KERN_INFO "drxk: status = 0x%08x\n", sio_top_jtagid_lo); /* driver 0.9.0 */ - switch ((sioTopJtagidLo >> 29) & 0xF) { + switch ((sio_top_jtagid_lo >> 29) & 0xF) { case 0: - state->m_deviceSpin = DRXK_SPIN_A1; + state->m_device_spin = DRXK_SPIN_A1; spin = "A1"; break; case 2: - state->m_deviceSpin = DRXK_SPIN_A2; + state->m_device_spin = DRXK_SPIN_A2; spin = "A2"; break; case 3: - state->m_deviceSpin = DRXK_SPIN_A3; + state->m_device_spin = DRXK_SPIN_A3; spin = "A3"; break; default: - state->m_deviceSpin = DRXK_SPIN_UNKNOWN; + state->m_device_spin = DRXK_SPIN_UNKNOWN; status = -EINVAL; printk(KERN_ERR "drxk: Spin %d unknown\n", - (sioTopJtagidLo >> 29) & 0xF); + (sio_top_jtagid_lo >> 29) & 0xF); goto error2; } - switch ((sioTopJtagidLo >> 12) & 0xFF) { + switch ((sio_top_jtagid_lo >> 12) & 0xFF) { case 0x13: /* typeId = DRX3913K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = false; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = false; - state->m_hasGPIO1 = false; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = false; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = false; + state->m_has_gpio1 = false; + state->m_has_irqn = false; break; case 0x15: /* typeId = DRX3915K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x16: /* typeId = DRX3916K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x18: /* typeId = DRX3918K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x21: /* typeId = DRX3921K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x23: /* typeId = DRX3923K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x25: /* typeId = DRX3925K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x26: /* typeId = DRX3926K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; default: printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n", - ((sioTopJtagidLo >> 12) & 0xFF)); + ((sio_top_jtagid_lo >> 12) & 0xFF)); status = -EINVAL; goto error2; } printk(KERN_INFO "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", - ((sioTopJtagidLo >> 12) & 0xFF), spin, - state->m_oscClockFreq / 1000, - state->m_oscClockFreq % 1000); + ((sio_top_jtagid_lo >> 12) & 0xFF), spin, + state->m_osc_clock_freq / 1000, + state->m_osc_clock_freq % 1000); error: if (status < 0) @@ -1005,7 +1005,7 @@ static int GetDeviceCapabilities(struct drxk_state *state) return status; } -static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) +static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) { int status; bool powerdown_cmd; @@ -1021,24 +1021,24 @@ static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) powerdown_cmd = (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) && - ((state->m_HICfgCtrl) & + ((state->m_hi_cfg_ctrl) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); if (powerdown_cmd == false) { /* Wait until command rdy */ - u32 retryCount = 0; - u16 waitCmd; + u32 retry_count = 0; + u16 wait_cmd; do { msleep(1); - retryCount += 1; + retry_count += 1; status = read16(state, SIO_HI_RA_RAM_CMD__A, - &waitCmd); - } while ((status < 0) && (retryCount < DRXK_MAX_RETRIES) - && (waitCmd != 0)); + &wait_cmd); + } while ((status < 0) && (retry_count < DRXK_MAX_RETRIES) + && (wait_cmd != 0)); if (status < 0) goto error; - status = read16(state, SIO_HI_RA_RAM_RES__A, pResult); + status = read16(state, SIO_HI_RA_RAM_RES__A, p_result); } error: if (status < 0) @@ -1047,7 +1047,7 @@ static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) return status; } -static int HI_CfgCommand(struct drxk_state *state) +static int hi_cfg_command(struct drxk_state *state) { int status; @@ -1055,29 +1055,29 @@ static int HI_CfgCommand(struct drxk_state *state) mutex_lock(&state->mutex); - status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout); + status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_hi_cfg_timeout); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl); + status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_hi_cfg_ctrl); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey); + status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_hi_cfg_wake_up_key); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay); + status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_hi_cfg_bridge_delay); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_hi_cfg_timing_div); if (status < 0) goto error; status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; - status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); + status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); if (status < 0) goto error; - state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; error: mutex_unlock(&state->mutex); if (status < 0) @@ -1085,28 +1085,28 @@ static int HI_CfgCommand(struct drxk_state *state) return status; } -static int InitHI(struct drxk_state *state) +static int init_hi(struct drxk_state *state) { dprintk(1, "\n"); - state->m_HICfgWakeUpKey = (state->demod_address << 1); - state->m_HICfgTimeout = 0x96FF; + state->m_hi_cfg_wake_up_key = (state->demod_address << 1); + state->m_hi_cfg_timeout = 0x96FF; /* port/bridge/power down ctrl */ - state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - return HI_CfgCommand(state); + return hi_cfg_command(state); } -static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) +static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) { int status = -1; - u16 sioPdrMclkCfg = 0; - u16 sioPdrMdxCfg = 0; + u16 sio_pdr_mclk_cfg = 0; + u16 sio_pdr_mdx_cfg = 0; u16 err_cfg = 0; dprintk(1, ": mpeg %s, %s mode\n", - mpegEnable ? "enable" : "disable", - state->m_enableParallel ? "parallel" : "serial"); + mpeg_enable ? "enable" : "disable", + state->m_enable_parallel ? "parallel" : "serial"); /* stop lock indicator process */ status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); @@ -1118,7 +1118,7 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; - if (mpegEnable == false) { + if (mpeg_enable == false) { /* Set MPEG TS pads to inputmode */ status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); if (status < 0) @@ -1158,19 +1158,19 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) goto error; } else { /* Enable MPEG output */ - sioPdrMdxCfg = - ((state->m_TSDataStrength << + sio_pdr_mdx_cfg = + ((state->m_ts_data_strength << SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); - sioPdrMclkCfg = ((state->m_TSClockkStrength << + sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength << SIO_PDR_MCLK_CFG_DRIVE__B) | 0x0003); - status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; if (state->enable_merr_cfg) - err_cfg = sioPdrMdxCfg; + err_cfg = sio_pdr_mdx_cfg; status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); if (status < 0) @@ -1179,31 +1179,31 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; - if (state->m_enableParallel == true) { + if (state->m_enable_parallel == true) { /* paralel -> enable MD1 to MD7 */ - status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD2_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD3_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD4_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD5_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD6_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD7_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; } else { - sioPdrMdxCfg = ((state->m_TSDataStrength << + sio_pdr_mdx_cfg = ((state->m_ts_data_strength << SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); /* serial -> disable MD1 to MD7 */ @@ -1229,10 +1229,10 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; } - status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg); + status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; } @@ -1248,17 +1248,17 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) return status; } -static int MPEGTSDisable(struct drxk_state *state) +static int mpegts_disable(struct drxk_state *state) { dprintk(1, "\n"); - return MPEGTSConfigurePins(state, false); + return mpegts_configure_pins(state, false); } -static int BLChainCmd(struct drxk_state *state, - u16 romOffset, u16 nrOfElements, u32 timeOut) +static int bl_chain_cmd(struct drxk_state *state, + u16 rom_offset, u16 nr_of_elements, u32 time_out) { - u16 blStatus = 0; + u16 bl_status = 0; int status; unsigned long end; @@ -1267,26 +1267,26 @@ static int BLChainCmd(struct drxk_state *state, status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN); if (status < 0) goto error; - status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset); + status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset); if (status < 0) goto error; - status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements); + status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements); if (status < 0) goto error; status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); if (status < 0) goto error; - end = jiffies + msecs_to_jiffies(timeOut); + end = jiffies + msecs_to_jiffies(time_out); do { msleep(1); - status = read16(state, SIO_BL_STATUS__A, &blStatus); + status = read16(state, SIO_BL_STATUS__A, &bl_status); if (status < 0) goto error; - } while ((blStatus == 0x1) && + } while ((bl_status == 0x1) && ((time_is_after_jiffies(end)))); - if (blStatus == 0x1) { + if (bl_status == 0x1) { printk(KERN_ERR "drxk: SIO not ready\n"); status = -EINVAL; goto error2; @@ -1300,13 +1300,13 @@ static int BLChainCmd(struct drxk_state *state, } -static int DownloadMicrocode(struct drxk_state *state, - const u8 pMCImage[], u32 Length) +static int download_microcode(struct drxk_state *state, + const u8 p_mc_image[], u32 length) { - const u8 *pSrc = pMCImage; - u32 Address; - u16 nBlocks; - u16 BlockSize; + const u8 *p_src = p_mc_image; + u32 address; + u16 n_blocks; + u16 block_size; u32 offset = 0; u32 i; int status = 0; @@ -1316,114 +1316,114 @@ static int DownloadMicrocode(struct drxk_state *state, /* down the drain (we don't care about MAGIC_WORD) */ #if 0 /* For future reference */ - Drain = (pSrc[0] << 8) | pSrc[1]; + drain = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); - nBlocks = (pSrc[0] << 8) | pSrc[1]; - pSrc += sizeof(u16); + n_blocks = (p_src[0] << 8) | p_src[1]; + p_src += sizeof(u16); offset += sizeof(u16); - for (i = 0; i < nBlocks; i += 1) { - Address = (pSrc[0] << 24) | (pSrc[1] << 16) | - (pSrc[2] << 8) | pSrc[3]; - pSrc += sizeof(u32); + for (i = 0; i < n_blocks; i += 1) { + address = (p_src[0] << 24) | (p_src[1] << 16) | + (p_src[2] << 8) | p_src[3]; + p_src += sizeof(u32); offset += sizeof(u32); - BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); - pSrc += sizeof(u16); + block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); #if 0 /* For future reference */ - Flags = (pSrc[0] << 8) | pSrc[1]; + flags = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); #if 0 /* For future reference */ - BlockCRC = (pSrc[0] << 8) | pSrc[1]; + block_crc = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); - if (offset + BlockSize > Length) { + if (offset + block_size > length) { printk(KERN_ERR "drxk: Firmware is corrupted.\n"); return -EINVAL; } - status = write_block(state, Address, BlockSize, pSrc); + status = write_block(state, address, block_size, p_src); if (status < 0) { printk(KERN_ERR "drxk: Error %d while loading firmware\n", status); break; } - pSrc += BlockSize; - offset += BlockSize; + p_src += block_size; + offset += block_size; } return status; } -static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable) +static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) { int status; u16 data = 0; - u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; - u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; + u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; + u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; unsigned long end; dprintk(1, "\n"); if (enable == false) { - desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; - desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; + desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; + desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; } status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); - if (status >= 0 && data == desiredStatus) { + if (status >= 0 && data == desired_status) { /* tokenring already has correct status */ return status; } /* Disable/enable dvbt tokenring bridge */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl); end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); do { status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); - if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end)) + if ((status >= 0 && data == desired_status) || time_is_after_jiffies(end)) break; msleep(1); } while (1); - if (data != desiredStatus) { + if (data != desired_status) { printk(KERN_ERR "drxk: SIO not ready\n"); return -EINVAL; } return status; } -static int MPEGTSStop(struct drxk_state *state) +static int mpegts_stop(struct drxk_state *state) { int status = 0; - u16 fecOcSncMode = 0; - u16 fecOcIprMode = 0; + u16 fec_oc_snc_mode = 0; + u16 fec_oc_ipr_mode = 0; dprintk(1, "\n"); /* Gracefull shutdown (byte boundaries) */ - status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; - fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M; - status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M; + status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); if (status < 0) goto error; /* Suppress MCLK during absence of data */ - status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode); + status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode); if (status < 0) goto error; - fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; - status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode); + fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; + status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode); error: if (status < 0) @@ -1433,13 +1433,13 @@ static int MPEGTSStop(struct drxk_state *state) } static int scu_command(struct drxk_state *state, - u16 cmd, u8 parameterLen, - u16 *parameter, u8 resultLen, u16 *result) + u16 cmd, u8 parameter_len, + u16 *parameter, u8 result_len, u16 *result) { #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15 #error DRXK register mapping no longer compatible with this routine! #endif - u16 curCmd = 0; + u16 cur_cmd = 0; int status = -EINVAL; unsigned long end; u8 buffer[34]; @@ -1449,8 +1449,8 @@ static int scu_command(struct drxk_state *state, dprintk(1, "\n"); - if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) || - ((resultLen > 0) && (result == NULL))) { + if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) || + ((result_len > 0) && (result == NULL))) { printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } @@ -1459,7 +1459,7 @@ static int scu_command(struct drxk_state *state, /* assume that the command register is ready since it is checked afterwards */ - for (ii = parameterLen - 1; ii >= 0; ii -= 1) { + for (ii = parameter_len - 1; ii >= 0; ii -= 1) { buffer[cnt++] = (parameter[ii] & 0xFF); buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF); } @@ -1467,26 +1467,26 @@ static int scu_command(struct drxk_state *state, buffer[cnt++] = ((cmd >> 8) & 0xFF); write_block(state, SCU_RAM_PARAM_0__A - - (parameterLen - 1), cnt, buffer); + (parameter_len - 1), cnt, buffer); /* Wait until SCU has processed command */ end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); do { msleep(1); - status = read16(state, SCU_RAM_COMMAND__A, &curCmd); + status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); if (status < 0) goto error; - } while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); - if (curCmd != DRX_SCU_READY) { + } while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); + if (cur_cmd != DRX_SCU_READY) { printk(KERN_ERR "drxk: SCU not ready\n"); status = -EIO; goto error2; } /* read results */ - if ((resultLen > 0) && (result != NULL)) { + if ((result_len > 0) && (result != NULL)) { s16 err; int ii; - for (ii = resultLen - 1; ii >= 0; ii -= 1) { + for (ii = result_len - 1; ii >= 0; ii -= 1) { status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]); if (status < 0) goto error; @@ -1529,7 +1529,7 @@ static int scu_command(struct drxk_state *state, return status; } -static int SetIqmAf(struct drxk_state *state, bool active) +static int set_iqm_af(struct drxk_state *state, bool active) { u16 data = 0; int status; @@ -1563,10 +1563,10 @@ static int SetIqmAf(struct drxk_state *state, bool active) return status; } -static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) +static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) { int status = 0; - u16 sioCcPwdMode = 0; + u16 sio_cc_pwd_mode = 0; dprintk(1, "\n"); @@ -1576,19 +1576,19 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) switch (*mode) { case DRX_POWER_UP: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; break; case DRXK_POWER_DOWN_OFDM: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM; break; case DRXK_POWER_DOWN_CORE: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; break; case DRXK_POWER_DOWN_PLL: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; break; case DRX_POWER_DOWN: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; break; default: /* Unknow sleep mode */ @@ -1596,15 +1596,15 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) } /* If already in requested power mode, do nothing */ - if (state->m_currentPowerMode == *mode) + if (state->m_current_power_mode == *mode) return 0; /* For next steps make sure to start from DRX_POWER_UP mode */ - if (state->m_currentPowerMode != DRX_POWER_UP) { - status = PowerUpDevice(state); + if (state->m_current_power_mode != DRX_POWER_UP) { + status = power_up_device(state); if (status < 0) goto error; - status = DVBTEnableOFDMTokenRing(state, true); + status = dvbt_enable_ofdm_token_ring(state, true); if (status < 0) goto error; } @@ -1621,31 +1621,31 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) /* Power down device */ /* stop all comm_exec */ /* Stop and power down previous standard */ - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_DVBT: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownDVBT(state, false); + status = power_down_dvbt(state, false); if (status < 0) goto error; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownQAM(state); + status = power_down_qam(state); if (status < 0) goto error; break; default: break; } - status = DVBTEnableOFDMTokenRing(state, false); + status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error; - status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode); + status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); @@ -1653,14 +1653,14 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) goto error; if (*mode != DRXK_POWER_DOWN_OFDM) { - state->m_HICfgCtrl |= + state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; - status = HI_CfgCommand(state); + status = hi_cfg_command(state); if (status < 0) goto error; } } - state->m_currentPowerMode = *mode; + state->m_current_power_mode = *mode; error: if (status < 0) @@ -1669,10 +1669,10 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) return status; } -static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) +static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) { - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; - u16 cmdResult = 0; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; + u16 cmd_result = 0; u16 data = 0; int status; @@ -1683,11 +1683,11 @@ static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) goto error; if (data == SCU_COMM_EXEC_ACTIVE) { /* Send OFDM stop command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* Send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); if (status < 0) goto error; } @@ -1704,13 +1704,13 @@ static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) goto error; /* powerdown AFE */ - status = SetIqmAf(state, false); + status = set_iqm_af(state, false); if (status < 0) goto error; /* powerdown to OFDM mode */ - if (setPowerMode) { - status = CtrlPowerMode(state, &powerMode); + if (set_power_mode) { + status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error; } @@ -1720,8 +1720,8 @@ static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) return status; } -static int SetOperationMode(struct drxk_state *state, - enum OperationMode oMode) +static int setoperation_mode(struct drxk_state *state, + enum operation_mode o_mode) { int status = 0; @@ -1738,31 +1738,31 @@ static int SetOperationMode(struct drxk_state *state, goto error; /* Device is already at the required mode */ - if (state->m_OperationMode == oMode) + if (state->m_operation_mode == o_mode) return 0; - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { /* OM_NONE was added for start up */ case OM_NONE: break; case OM_DVBT: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownDVBT(state, true); + status = power_down_dvbt(state, true); if (status < 0) goto error; - state->m_OperationMode = OM_NONE; + state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownQAM(state); + status = power_down_qam(state); if (status < 0) goto error; - state->m_OperationMode = OM_NONE; + state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_B: default: @@ -1773,20 +1773,20 @@ static int SetOperationMode(struct drxk_state *state, /* Power up new standard */ - switch (oMode) { + switch (o_mode) { case OM_DVBT: dprintk(1, ": DVB-T\n"); - state->m_OperationMode = oMode; - status = SetDVBTStandard(state, oMode); + state->m_operation_mode = o_mode; + status = set_dvbt_standard(state, o_mode); if (status < 0) goto error; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: dprintk(1, ": DVB-C Annex %c\n", - (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C'); - state->m_OperationMode = oMode; - status = SetQAMStandard(state, oMode); + (state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C'); + state->m_operation_mode = o_mode; + status = set_qam_standard(state, o_mode); if (status < 0) goto error; break; @@ -1800,47 +1800,47 @@ static int SetOperationMode(struct drxk_state *state, return status; } -static int Start(struct drxk_state *state, s32 offsetFreq, - s32 IntermediateFrequency) +static int start(struct drxk_state *state, s32 offset_freq, + s32 intermediate_frequency) { int status = -EINVAL; - u16 IFreqkHz; - s32 OffsetkHz = offsetFreq / 1000; + u16 i_freqk_hz; + s32 offsetk_hz = offset_freq / 1000; dprintk(1, "\n"); - if (state->m_DrxkState != DRXK_STOPPED && - state->m_DrxkState != DRXK_DTV_STARTED) + if (state->m_drxk_state != DRXK_STOPPED && + state->m_drxk_state != DRXK_DTV_STARTED) goto error; - state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON); + state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON); - if (IntermediateFrequency < 0) { - state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect; - IntermediateFrequency = -IntermediateFrequency; + if (intermediate_frequency < 0) { + state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect; + intermediate_frequency = -intermediate_frequency; } - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_QAM_ITU_A: case OM_QAM_ITU_C: - IFreqkHz = (IntermediateFrequency / 1000); - status = SetQAM(state, IFreqkHz, OffsetkHz); + i_freqk_hz = (intermediate_frequency / 1000); + status = set_qam(state, i_freqk_hz, offsetk_hz); if (status < 0) goto error; - state->m_DrxkState = DRXK_DTV_STARTED; + state->m_drxk_state = DRXK_DTV_STARTED; break; case OM_DVBT: - IFreqkHz = (IntermediateFrequency / 1000); - status = MPEGTSStop(state); + i_freqk_hz = (intermediate_frequency / 1000); + status = mpegts_stop(state); if (status < 0) goto error; - status = SetDVBT(state, IFreqkHz, OffsetkHz); + status = set_dvbt(state, i_freqk_hz, offsetk_hz); if (status < 0) goto error; - status = DVBTStart(state); + status = dvbt_start(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_DTV_STARTED; + state->m_drxk_state = DRXK_DTV_STARTED; break; default: break; @@ -1851,34 +1851,34 @@ static int Start(struct drxk_state *state, s32 offsetFreq, return status; } -static int ShutDown(struct drxk_state *state) +static int shut_down(struct drxk_state *state) { dprintk(1, "\n"); - MPEGTSStop(state); + mpegts_stop(state); return 0; } -static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status = -EINVAL; dprintk(1, "\n"); - if (pLockStatus == NULL) + if (p_lock_status == NULL) goto error; - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; /* define the SCU command code */ - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_QAM_ITU_A: case OM_QAM_ITU_B: case OM_QAM_ITU_C: - status = GetQAMLockStatus(state, pLockStatus); + status = get_qam_lock_status(state, p_lock_status); break; case OM_DVBT: - status = GetDVBTLockStatus(state, pLockStatus); + status = get_dvbt_lock_status(state, p_lock_status); break; default: break; @@ -1889,18 +1889,18 @@ static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus) return status; } -static int MPEGTSStart(struct drxk_state *state) +static int mpegts_start(struct drxk_state *state) { int status; - u16 fecOcSncMode = 0; + u16 fec_oc_snc_mode = 0; /* Allow OC to sync again */ - status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; - fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; - status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; + status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); if (status < 0) goto error; status = write16(state, FEC_OC_SNC_UNLOCK__A, 1); @@ -1910,7 +1910,7 @@ static int MPEGTSStart(struct drxk_state *state) return status; } -static int MPEGTSDtoInit(struct drxk_state *state) +static int mpegts_dto_init(struct drxk_state *state) { int status; @@ -1957,63 +1957,63 @@ static int MPEGTSDtoInit(struct drxk_state *state) return status; } -static int MPEGTSDtoSetup(struct drxk_state *state, - enum OperationMode oMode) +static int mpegts_dto_setup(struct drxk_state *state, + enum operation_mode o_mode) { int status; - u16 fecOcRegMode = 0; /* FEC_OC_MODE register value */ - u16 fecOcRegIprMode = 0; /* FEC_OC_IPR_MODE register value */ - u16 fecOcDtoMode = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcFctMode = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcDtoPeriod = 2; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcDtoBurstLen = 188; /* FEC_OC_IPR_INVERT register value */ - u32 fecOcRcnCtlRate = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcTmdMode = 0; - u16 fecOcTmdIntUpdRate = 0; - u32 maxBitRate = 0; - bool staticCLK = false; + u16 fec_oc_reg_mode = 0; /* FEC_OC_MODE register value */ + u16 fec_oc_reg_ipr_mode = 0; /* FEC_OC_IPR_MODE register value */ + u16 fec_oc_dto_mode = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_fct_mode = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_dto_period = 2; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_dto_burst_len = 188; /* FEC_OC_IPR_INVERT register value */ + u32 fec_oc_rcn_ctl_rate = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_tmd_mode = 0; + u16 fec_oc_tmd_int_upd_rate = 0; + u32 max_bit_rate = 0; + bool static_clk = false; dprintk(1, "\n"); /* Check insertion of the Reed-Solomon parity bytes */ - status = read16(state, FEC_OC_MODE__A, &fecOcRegMode); + status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode); if (status < 0) goto error; - status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode); + status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode); if (status < 0) goto error; - fecOcRegMode &= (~FEC_OC_MODE_PARITY__M); - fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); - if (state->m_insertRSByte == true) { + fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); + fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); + if (state->m_insert_rs_byte == true) { /* enable parity symbol forward */ - fecOcRegMode |= FEC_OC_MODE_PARITY__M; + fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; /* MVAL disable during parity bytes */ - fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; + fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; /* TS burst length to 204 */ - fecOcDtoBurstLen = 204; + fec_oc_dto_burst_len = 204; } /* Check serial or parrallel output */ - fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); - if (state->m_enableParallel == false) { + fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); + if (state->m_enable_parallel == false) { /* MPEG data output is serial -> set ipr_mode[0] */ - fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M; + fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; } - switch (oMode) { + switch (o_mode) { case OM_DVBT: - maxBitRate = state->m_DVBTBitrate; - fecOcTmdMode = 3; - fecOcRcnCtlRate = 0xC00000; - staticCLK = state->m_DVBTStaticCLK; + max_bit_rate = state->m_dvbt_bitrate; + fec_oc_tmd_mode = 3; + fec_oc_rcn_ctl_rate = 0xC00000; + static_clk = state->m_dvbt_static_clk; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: - fecOcTmdMode = 0x0004; - fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ - maxBitRate = state->m_DVBCBitrate; - staticCLK = state->m_DVBCStaticCLK; + fec_oc_tmd_mode = 0x0004; + fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */ + max_bit_rate = state->m_dvbc_bitrate; + static_clk = state->m_dvbc_static_clk; break; default: status = -EINVAL; @@ -2022,83 +2022,83 @@ static int MPEGTSDtoSetup(struct drxk_state *state, goto error; /* Configure DTO's */ - if (staticCLK) { - u32 bitRate = 0; + if (static_clk) { + u32 bit_rate = 0; /* Rational DTO for MCLK source (static MCLK rate), Dynamic DTO for optimal grouping (avoid intra-packet gaps), DTO offset enable to sync TS burst with MSTRT */ - fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M | + fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M); - fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M | + fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M); /* Check user defined bitrate */ - bitRate = maxBitRate; - if (bitRate > 75900000UL) { /* max is 75.9 Mb/s */ - bitRate = 75900000UL; + bit_rate = max_bit_rate; + if (bit_rate > 75900000UL) { /* max is 75.9 Mb/s */ + bit_rate = 75900000UL; } /* Rational DTO period: dto_period = (Fsys / bitrate) - 2 - Result should be floored, + result should be floored, to make sure >= requested bitrate */ - fecOcDtoPeriod = (u16) (((state->m_sysClockFreq) - * 1000) / bitRate); - if (fecOcDtoPeriod <= 2) - fecOcDtoPeriod = 0; + fec_oc_dto_period = (u16) (((state->m_sys_clock_freq) + * 1000) / bit_rate); + if (fec_oc_dto_period <= 2) + fec_oc_dto_period = 0; else - fecOcDtoPeriod -= 2; - fecOcTmdIntUpdRate = 8; + fec_oc_dto_period -= 2; + fec_oc_tmd_int_upd_rate = 8; } else { - /* (commonAttr->staticCLK == false) => dynamic mode */ - fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M; - fecOcFctMode = FEC_OC_FCT_MODE__PRE; - fecOcTmdIntUpdRate = 5; + /* (commonAttr->static_clk == false) => dynamic mode */ + fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M; + fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE; + fec_oc_tmd_int_upd_rate = 5; } /* Write appropriate registers with requested configuration */ - status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen); + status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len); if (status < 0) goto error; - status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod); + status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period); if (status < 0) goto error; - status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode); + status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode); + status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_MODE__A, fecOcRegMode); + status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode); + status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode); if (status < 0) goto error; /* Rate integration settings */ - status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate); + status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate); if (status < 0) goto error; - status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate); + status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fec_oc_tmd_int_upd_rate); if (status < 0) goto error; - status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode); + status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int MPEGTSConfigurePolarity(struct drxk_state *state) +static int mpegts_configure_polarity(struct drxk_state *state) { - u16 fecOcRegIprInvert = 0; + u16 fec_oc_reg_ipr_invert = 0; /* Data mask for the output data byte */ - u16 InvertDataMask = + u16 invert_data_mask = FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | @@ -2107,40 +2107,40 @@ static int MPEGTSConfigurePolarity(struct drxk_state *state) dprintk(1, "\n"); /* Control selective inversion of output bits */ - fecOcRegIprInvert &= (~(InvertDataMask)); - if (state->m_invertDATA == true) - fecOcRegIprInvert |= InvertDataMask; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M)); - if (state->m_invertERR == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); - if (state->m_invertSTR == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); - if (state->m_invertVAL == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); - if (state->m_invertCLK == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M; - - return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert); + fec_oc_reg_ipr_invert &= (~(invert_data_mask)); + if (state->m_invert_data == true) + fec_oc_reg_ipr_invert |= invert_data_mask; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); + if (state->m_invert_err == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); + if (state->m_invert_str == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); + if (state->m_invert_val == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); + if (state->m_invert_clk == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; + + return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); } #define SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000 -static int SetAgcRf(struct drxk_state *state, - struct SCfgAgc *pAgcCfg, bool isDTV) +static int set_agc_rf(struct drxk_state *state, + struct s_cfg_agc *p_agc_cfg, bool is_dtv) { int status = -EINVAL; u16 data = 0; - struct SCfgAgc *pIfAgcSettings; + struct s_cfg_agc *p_if_agc_settings; dprintk(1, "\n"); - if (pAgcCfg == NULL) + if (p_agc_cfg == NULL) goto error; - switch (pAgcCfg->ctrlMode) { + switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO: /* Enable RF AGC DAC */ status = read16(state, IQM_AF_STDBY__A, &data); @@ -2158,7 +2158,7 @@ static int SetAgcRf(struct drxk_state *state, data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; /* Polarity */ - if (state->m_RfAgcPol) + if (state->m_rf_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; @@ -2172,7 +2172,7 @@ static int SetAgcRf(struct drxk_state *state, goto error; data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; - data |= (~(pAgcCfg->speed << + data |= (~(p_agc_cfg->speed << SCU_RAM_AGC_KI_RED_RAGC_RED__B) & SCU_RAM_AGC_KI_RED_RAGC_RED__M); @@ -2180,30 +2180,30 @@ static int SetAgcRf(struct drxk_state *state, if (status < 0) goto error; - if (IsDVBT(state)) - pIfAgcSettings = &state->m_dvbtIfAgcCfg; - else if (IsQAM(state)) - pIfAgcSettings = &state->m_qamIfAgcCfg; + if (is_dvbt(state)) + p_if_agc_settings = &state->m_dvbt_if_agc_cfg; + else if (is_qam(state)) + p_if_agc_settings = &state->m_qam_if_agc_cfg; else - pIfAgcSettings = &state->m_atvIfAgcCfg; - if (pIfAgcSettings == NULL) { + p_if_agc_settings = &state->m_atv_if_agc_cfg; + if (p_if_agc_settings == NULL) { status = -EINVAL; goto error; } /* Set TOP, only if IF-AGC is in AUTO mode */ - if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO) - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top); + if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->top); if (status < 0) goto error; /* Cut-Off current */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, p_agc_cfg->cut_off_current); if (status < 0) goto error; /* Max. output level */ - status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel); + status = write16(state, SCU_RAM_AGC_RF_MAX__A, p_agc_cfg->max_output_level); if (status < 0) goto error; @@ -2224,7 +2224,7 @@ static int SetAgcRf(struct drxk_state *state, if (status < 0) goto error; data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; - if (state->m_RfAgcPol) + if (state->m_rf_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; @@ -2238,7 +2238,7 @@ static int SetAgcRf(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2275,16 +2275,16 @@ static int SetAgcRf(struct drxk_state *state, #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000 -static int SetAgcIf(struct drxk_state *state, - struct SCfgAgc *pAgcCfg, bool isDTV) +static int set_agc_if(struct drxk_state *state, + struct s_cfg_agc *p_agc_cfg, bool is_dtv) { u16 data = 0; int status = 0; - struct SCfgAgc *pRfAgcSettings; + struct s_cfg_agc *p_rf_agc_settings; dprintk(1, "\n"); - switch (pAgcCfg->ctrlMode) { + switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO: /* Enable IF AGC DAC */ @@ -2304,7 +2304,7 @@ static int SetAgcIf(struct drxk_state *state, data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; /* Polarity */ - if (state->m_IfAgcPol) + if (state->m_if_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; @@ -2317,7 +2317,7 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; - data |= (~(pAgcCfg->speed << + data |= (~(p_agc_cfg->speed << SCU_RAM_AGC_KI_RED_IAGC_RED__B) & SCU_RAM_AGC_KI_RED_IAGC_RED__M); @@ -2325,14 +2325,14 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; - if (IsQAM(state)) - pRfAgcSettings = &state->m_qamRfAgcCfg; + if (is_qam(state)) + p_rf_agc_settings = &state->m_qam_rf_agc_cfg; else - pRfAgcSettings = &state->m_atvRfAgcCfg; - if (pRfAgcSettings == NULL) + p_rf_agc_settings = &state->m_atv_rf_agc_cfg; + if (p_rf_agc_settings == NULL) return -1; /* Restore TOP */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_rf_agc_settings->top); if (status < 0) goto error; break; @@ -2356,7 +2356,7 @@ static int SetAgcIf(struct drxk_state *state, data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; /* Polarity */ - if (state->m_IfAgcPol) + if (state->m_if_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; @@ -2365,7 +2365,7 @@ static int SetAgcIf(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2390,33 +2390,33 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; break; - } /* switch (agcSettingsIf->ctrlMode) */ + } /* switch (agcSettingsIf->ctrl_mode) */ /* always set the top to support configurations without if-loop */ - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int GetQAMSignalToNoise(struct drxk_state *state, - s32 *pSignalToNoise) +static int get_qam_signal_to_noise(struct drxk_state *state, + s32 *p_signal_to_noise) { int status = 0; - u16 qamSlErrPower = 0; /* accum. error between + u16 qam_sl_err_power = 0; /* accum. error between raw and sliced symbols */ - u32 qamSlSigPower = 0; /* used for MER, depends of + u32 qam_sl_sig_power = 0; /* used for MER, depends of QAM modulation */ - u32 qamSlMer = 0; /* QAM MER */ + u32 qam_sl_mer = 0; /* QAM MER */ dprintk(1, "\n"); /* MER calculation */ /* get the register value needed for MER */ - status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower); + status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); if (status < 0) { printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return -EINVAL; @@ -2424,124 +2424,124 @@ static int GetQAMSignalToNoise(struct drxk_state *state, switch (state->props.modulation) { case QAM_16: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; break; case QAM_32: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; break; case QAM_64: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; break; case QAM_128: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; break; default: case QAM_256: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; break; } - if (qamSlErrPower > 0) { - qamSlMer = log10times100(qamSlSigPower) - - log10times100((u32) qamSlErrPower); + if (qam_sl_err_power > 0) { + qam_sl_mer = log10times100(qam_sl_sig_power) - + log10times100((u32) qam_sl_err_power); } - *pSignalToNoise = qamSlMer; + *p_signal_to_noise = qam_sl_mer; return status; } -static int GetDVBTSignalToNoise(struct drxk_state *state, - s32 *pSignalToNoise) +static int get_dvbt_signal_to_noise(struct drxk_state *state, + s32 *p_signal_to_noise) { int status; - u16 regData = 0; - u32 EqRegTdSqrErrI = 0; - u32 EqRegTdSqrErrQ = 0; - u16 EqRegTdSqrErrExp = 0; - u16 EqRegTdTpsPwrOfs = 0; - u16 EqRegTdReqSmbCnt = 0; - u32 tpsCnt = 0; - u32 SqrErrIQ = 0; + u16 reg_data = 0; + u32 eq_reg_td_sqr_err_i = 0; + u32 eq_reg_td_sqr_err_q = 0; + u16 eq_reg_td_sqr_err_exp = 0; + u16 eq_reg_td_tps_pwr_ofs = 0; + u16 eq_reg_td_req_smb_cnt = 0; + u32 tps_cnt = 0; + u32 sqr_err_iq = 0; u32 a = 0; u32 b = 0; u32 c = 0; - u32 iMER = 0; - u16 transmissionParams = 0; + u32 i_mer = 0; + u16 transmission_params = 0; dprintk(1, "\n"); - status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs); + status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &eq_reg_td_tps_pwr_ofs); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt); + status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &eq_reg_td_req_smb_cnt); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &eq_reg_td_sqr_err_exp); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®Data); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®_data); if (status < 0) goto error; /* Extend SQR_ERR_I operational range */ - EqRegTdSqrErrI = (u32) regData; - if ((EqRegTdSqrErrExp > 11) && - (EqRegTdSqrErrI < 0x00000FFFUL)) { - EqRegTdSqrErrI += 0x00010000UL; + eq_reg_td_sqr_err_i = (u32) reg_data; + if ((eq_reg_td_sqr_err_exp > 11) && + (eq_reg_td_sqr_err_i < 0x00000FFFUL)) { + eq_reg_td_sqr_err_i += 0x00010000UL; } - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®Data); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®_data); if (status < 0) goto error; /* Extend SQR_ERR_Q operational range */ - EqRegTdSqrErrQ = (u32) regData; - if ((EqRegTdSqrErrExp > 11) && - (EqRegTdSqrErrQ < 0x00000FFFUL)) - EqRegTdSqrErrQ += 0x00010000UL; + eq_reg_td_sqr_err_q = (u32) reg_data; + if ((eq_reg_td_sqr_err_exp > 11) && + (eq_reg_td_sqr_err_q < 0x00000FFFUL)) + eq_reg_td_sqr_err_q += 0x00010000UL; - status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams); + status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmission_params); if (status < 0) goto error; /* Check input data for MER */ /* MER calculation (in 0.1 dB) without math.h */ - if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0)) - iMER = 0; - else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) { + if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0)) + i_mer = 0; + else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) { /* No error at all, this must be the HW reset value * Apparently no first measurement yet * Set MER to 0.0 */ - iMER = 0; + i_mer = 0; } else { - SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) << - EqRegTdSqrErrExp; - if ((transmissionParams & + sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) << + eq_reg_td_sqr_err_exp; + if ((transmission_params & OFDM_SC_RA_RAM_OP_PARAM_MODE__M) == OFDM_SC_RA_RAM_OP_PARAM_MODE_2K) - tpsCnt = 17; + tps_cnt = 17; else - tpsCnt = 68; + tps_cnt = 68; /* IMER = 100 * log10 (x) - where x = (EqRegTdTpsPwrOfs^2 * - EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ + where x = (eq_reg_td_tps_pwr_ofs^2 * + eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq => IMER = a + b -c - where a = 100 * log10 (EqRegTdTpsPwrOfs^2) - b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt) - c = 100 * log10 (SqrErrIQ) + where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2) + b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt) + c = 100 * log10 (sqr_err_iq) */ /* log(x) x = 9bits * 9bits->18 bits */ - a = log10times100(EqRegTdTpsPwrOfs * - EqRegTdTpsPwrOfs); + a = log10times100(eq_reg_td_tps_pwr_ofs * + eq_reg_td_tps_pwr_ofs); /* log(x) x = 16bits * 7bits->23 bits */ - b = log10times100(EqRegTdReqSmbCnt * tpsCnt); + b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt); /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ - c = log10times100(SqrErrIQ); + c = log10times100(sqr_err_iq); - iMER = a + b - c; + i_mer = a + b - c; } - *pSignalToNoise = iMER; + *p_signal_to_noise = i_mer; error: if (status < 0) @@ -2549,17 +2549,17 @@ static int GetDVBTSignalToNoise(struct drxk_state *state, return status; } -static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) +static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) { dprintk(1, "\n"); - *pSignalToNoise = 0; - switch (state->m_OperationMode) { + *p_signal_to_noise = 0; + switch (state->m_operation_mode) { case OM_DVBT: - return GetDVBTSignalToNoise(state, pSignalToNoise); + return get_dvbt_signal_to_noise(state, p_signal_to_noise); case OM_QAM_ITU_A: case OM_QAM_ITU_C: - return GetQAMSignalToNoise(state, pSignalToNoise); + return get_qam_signal_to_noise(state, p_signal_to_noise); default: break; } @@ -2567,7 +2567,7 @@ static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) } #if 0 -static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) +static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) { /* SNR Values for quasi errorfree reception rom Nordig 2.2 */ int status = 0; @@ -2592,102 +2592,102 @@ static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) 225, /* 64-QAM 7/8 */ }; - *pQuality = 0; + *p_quality = 0; do { - s32 SignalToNoise = 0; - u16 Constellation = 0; - u16 CodeRate = 0; - u32 SignalToNoiseRel; - u32 BERQuality; + s32 signal_to_noise = 0; + u16 constellation = 0; + u16 code_rate = 0; + u32 signal_to_noise_rel; + u32 ber_quality; - status = GetDVBTSignalToNoise(state, &SignalToNoise); + status = get_dvbt_signal_to_noise(state, &signal_to_noise); if (status < 0) break; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &constellation); if (status < 0) break; - Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; + constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &code_rate); if (status < 0) break; - CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; + code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; - if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || - CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) + if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || + code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) break; - SignalToNoiseRel = SignalToNoise - - QE_SN[Constellation * 5 + CodeRate]; - BERQuality = 100; - - if (SignalToNoiseRel < -70) - *pQuality = 0; - else if (SignalToNoiseRel < 30) - *pQuality = ((SignalToNoiseRel + 70) * - BERQuality) / 100; + signal_to_noise_rel = signal_to_noise - + QE_SN[constellation * 5 + code_rate]; + ber_quality = 100; + + if (signal_to_noise_rel < -70) + *p_quality = 0; + else if (signal_to_noise_rel < 30) + *p_quality = ((signal_to_noise_rel + 70) * + ber_quality) / 100; else - *pQuality = BERQuality; + *p_quality = ber_quality; } while (0); return 0; }; -static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality) +static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality) { int status = 0; - *pQuality = 0; + *p_quality = 0; dprintk(1, "\n"); do { - u32 SignalToNoise = 0; - u32 BERQuality = 100; - u32 SignalToNoiseRel = 0; + u32 signal_to_noise = 0; + u32 ber_quality = 100; + u32 signal_to_noise_rel = 0; - status = GetQAMSignalToNoise(state, &SignalToNoise); + status = get_qam_signal_to_noise(state, &signal_to_noise); if (status < 0) break; switch (state->props.modulation) { case QAM_16: - SignalToNoiseRel = SignalToNoise - 200; + signal_to_noise_rel = signal_to_noise - 200; break; case QAM_32: - SignalToNoiseRel = SignalToNoise - 230; + signal_to_noise_rel = signal_to_noise - 230; break; /* Not in NorDig */ case QAM_64: - SignalToNoiseRel = SignalToNoise - 260; + signal_to_noise_rel = signal_to_noise - 260; break; case QAM_128: - SignalToNoiseRel = SignalToNoise - 290; + signal_to_noise_rel = signal_to_noise - 290; break; default: case QAM_256: - SignalToNoiseRel = SignalToNoise - 320; + signal_to_noise_rel = signal_to_noise - 320; break; } - if (SignalToNoiseRel < -70) - *pQuality = 0; - else if (SignalToNoiseRel < 30) - *pQuality = ((SignalToNoiseRel + 70) * - BERQuality) / 100; + if (signal_to_noise_rel < -70) + *p_quality = 0; + else if (signal_to_noise_rel < 30) + *p_quality = ((signal_to_noise_rel + 70) * + ber_quality) / 100; else - *pQuality = BERQuality; + *p_quality = ber_quality; } while (0); return status; } -static int GetQuality(struct drxk_state *state, s32 *pQuality) +static int get_quality(struct drxk_state *state, s32 *p_quality) { dprintk(1, "\n"); - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_DVBT: - return GetDVBTQuality(state, pQuality); + return get_dvbt_quality(state, p_quality); case OM_QAM_ITU_A: - return GetDVBCQuality(state, pQuality); + return get_dvbc_quality(state, p_quality); default: break; } @@ -2709,15 +2709,15 @@ static int GetQuality(struct drxk_state *state, s32 *pQuality) #define DRXDAP_FASI_ADDR2BANK(addr) (((addr) >> 16) & 0x3F) #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF) -static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) +static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) { int status = -EINVAL; dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return 0; - if (state->m_DrxkState == DRXK_POWERED_DOWN) + if (state->m_drxk_state == DRXK_POWERED_DOWN) goto error; if (state->no_i2c_bridge) @@ -2726,7 +2726,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; - if (bEnableBridge) { + if (b_enable_bridge) { status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); if (status < 0) goto error; @@ -2736,7 +2736,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) goto error; } - status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); + status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); error: if (status < 0) @@ -2744,30 +2744,30 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) return status; } -static int SetPreSaw(struct drxk_state *state, - struct SCfgPreSaw *pPreSawCfg) +static int set_pre_saw(struct drxk_state *state, + struct s_cfg_pre_saw *p_pre_saw_cfg) { int status = -EINVAL; dprintk(1, "\n"); - if ((pPreSawCfg == NULL) - || (pPreSawCfg->reference > IQM_AF_PDREF__M)) + if ((p_pre_saw_cfg == NULL) + || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M)) goto error; - status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference); + status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, - u16 romOffset, u16 nrOfElements, u32 timeOut) +static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, + u16 rom_offset, u16 nr_of_elements, u32 time_out) { - u16 blStatus = 0; - u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF); - u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF); + u16 bl_status = 0; + u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF); + u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF); int status; unsigned long end; @@ -2783,23 +2783,23 @@ static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, status = write16(state, SIO_BL_TGT_ADDR__A, offset); if (status < 0) goto error; - status = write16(state, SIO_BL_SRC_ADDR__A, romOffset); + status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset); if (status < 0) goto error; - status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements); + status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements); if (status < 0) goto error; status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); if (status < 0) goto error; - end = jiffies + msecs_to_jiffies(timeOut); + end = jiffies + msecs_to_jiffies(time_out); do { - status = read16(state, SIO_BL_STATUS__A, &blStatus); + status = read16(state, SIO_BL_STATUS__A, &bl_status); if (status < 0) goto error; - } while ((blStatus == 0x1) && time_is_after_jiffies(end)); - if (blStatus == 0x1) { + } while ((bl_status == 0x1) && time_is_after_jiffies(end)); + if (bl_status == 0x1) { printk(KERN_ERR "drxk: SIO not ready\n"); status = -EINVAL; goto error2; @@ -2813,14 +2813,14 @@ static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, } -static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) +static int adc_sync_measurement(struct drxk_state *state, u16 *count) { u16 data = 0; int status; dprintk(1, "\n"); - /* Start measurement */ + /* start measurement */ status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE); if (status < 0) goto error; @@ -2851,38 +2851,38 @@ static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) return status; } -static int ADCSynchronization(struct drxk_state *state) +static int adc_synchronization(struct drxk_state *state) { u16 count = 0; int status; dprintk(1, "\n"); - status = ADCSyncMeasurement(state, &count); + status = adc_sync_measurement(state, &count); if (status < 0) goto error; if (count == 1) { /* Try sampling on a diffrent edge */ - u16 clkNeg = 0; + u16 clk_neg = 0; - status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); + status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); if (status < 0) goto error; - if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) == + if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) == IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { - clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); - clkNeg |= + clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); + clk_neg |= IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG; } else { - clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); - clkNeg |= + clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); + clk_neg |= IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS; } - status = write16(state, IQM_AF_CLKNEG__A, clkNeg); + status = write16(state, IQM_AF_CLKNEG__A, clk_neg); if (status < 0) goto error; - status = ADCSyncMeasurement(state, &count); + status = adc_sync_measurement(state, &count); if (status < 0) goto error; } @@ -2895,21 +2895,21 @@ static int ADCSynchronization(struct drxk_state *state) return status; } -static int SetFrequencyShifter(struct drxk_state *state, - u16 intermediateFreqkHz, - s32 tunerFreqOffset, bool isDTV) +static int set_frequency_shifter(struct drxk_state *state, + u16 intermediate_freqk_hz, + s32 tuner_freq_offset, bool is_dtv) { - bool selectPosImage = false; - u32 rfFreqResidual = tunerFreqOffset; - u32 fmFrequencyShift = 0; - bool tunerMirror = !state->m_bMirrorFreqSpect; - u32 adcFreq; - bool adcFlip; + bool select_pos_image = false; + u32 rf_freq_residual = tuner_freq_offset; + u32 fm_frequency_shift = 0; + bool tuner_mirror = !state->m_b_mirror_freq_spect; + u32 adc_freq; + bool adc_flip; int status; - u32 ifFreqActual; - u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3); - u32 frequencyShift; - bool imageToSelect; + u32 if_freq_actual; + u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3); + u32 frequency_shift; + bool image_to_select; dprintk(1, "\n"); @@ -2917,121 +2917,121 @@ static int SetFrequencyShifter(struct drxk_state *state, Program frequency shifter No need to account for mirroring on RF */ - if (isDTV) { - if ((state->m_OperationMode == OM_QAM_ITU_A) || - (state->m_OperationMode == OM_QAM_ITU_C) || - (state->m_OperationMode == OM_DVBT)) - selectPosImage = true; + if (is_dtv) { + if ((state->m_operation_mode == OM_QAM_ITU_A) || + (state->m_operation_mode == OM_QAM_ITU_C) || + (state->m_operation_mode == OM_DVBT)) + select_pos_image = true; else - selectPosImage = false; + select_pos_image = false; } - if (tunerMirror) + if (tuner_mirror) /* tuner doesn't mirror */ - ifFreqActual = intermediateFreqkHz + - rfFreqResidual + fmFrequencyShift; + if_freq_actual = intermediate_freqk_hz + + rf_freq_residual + fm_frequency_shift; else /* tuner mirrors */ - ifFreqActual = intermediateFreqkHz - - rfFreqResidual - fmFrequencyShift; - if (ifFreqActual > samplingFrequency / 2) { + if_freq_actual = intermediate_freqk_hz - + rf_freq_residual - fm_frequency_shift; + if (if_freq_actual > sampling_frequency / 2) { /* adc mirrors */ - adcFreq = samplingFrequency - ifFreqActual; - adcFlip = true; + adc_freq = sampling_frequency - if_freq_actual; + adc_flip = true; } else { /* adc doesn't mirror */ - adcFreq = ifFreqActual; - adcFlip = false; + adc_freq = if_freq_actual; + adc_flip = false; } - frequencyShift = adcFreq; - imageToSelect = state->m_rfmirror ^ tunerMirror ^ - adcFlip ^ selectPosImage; - state->m_IqmFsRateOfs = - Frac28a((frequencyShift), samplingFrequency); + frequency_shift = adc_freq; + image_to_select = state->m_rfmirror ^ tuner_mirror ^ + adc_flip ^ select_pos_image; + state->m_iqm_fs_rate_ofs = + Frac28a((frequency_shift), sampling_frequency); - if (imageToSelect) - state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1; + if (image_to_select) + state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1; /* Program frequency shifter with tuner offset compensation */ - /* frequencyShift += tunerFreqOffset; TODO */ + /* frequency_shift += tuner_freq_offset; TODO */ status = write32(state, IQM_FS_RATE_OFS_LO__A, - state->m_IqmFsRateOfs); + state->m_iqm_fs_rate_ofs); if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int InitAGC(struct drxk_state *state, bool isDTV) +static int init_agc(struct drxk_state *state, bool is_dtv) { - u16 ingainTgt = 0; - u16 ingainTgtMin = 0; - u16 ingainTgtMax = 0; - u16 clpCyclen = 0; - u16 clpSumMin = 0; - u16 clpDirTo = 0; - u16 snsSumMin = 0; - u16 snsSumMax = 0; - u16 clpSumMax = 0; - u16 snsDirTo = 0; - u16 kiInnergainMin = 0; - u16 ifIaccuHiTgt = 0; - u16 ifIaccuHiTgtMin = 0; - u16 ifIaccuHiTgtMax = 0; + u16 ingain_tgt = 0; + u16 ingain_tgt_min = 0; + u16 ingain_tgt_max = 0; + u16 clp_cyclen = 0; + u16 clp_sum_min = 0; + u16 clp_dir_to = 0; + u16 sns_sum_min = 0; + u16 sns_sum_max = 0; + u16 clp_sum_max = 0; + u16 sns_dir_to = 0; + u16 ki_innergain_min = 0; + u16 if_iaccu_hi_tgt = 0; + u16 if_iaccu_hi_tgt_min = 0; + u16 if_iaccu_hi_tgt_max = 0; u16 data = 0; - u16 fastClpCtrlDelay = 0; - u16 clpCtrlMode = 0; + u16 fast_clp_ctrl_delay = 0; + u16 clp_ctrl_mode = 0; int status = 0; dprintk(1, "\n"); /* Common settings */ - snsSumMax = 1023; - ifIaccuHiTgtMin = 2047; - clpCyclen = 500; - clpSumMax = 1023; + sns_sum_max = 1023; + if_iaccu_hi_tgt_min = 2047; + clp_cyclen = 500; + clp_sum_max = 1023; /* AGCInit() not available for DVBT; init done in microcode */ - if (!IsQAM(state)) { - printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode); + if (!is_qam(state)) { + printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_operation_mode); return -EINVAL; } /* FIXME: Analog TV AGC require different settings */ /* Standard specific settings */ - clpSumMin = 8; - clpDirTo = (u16) -9; - clpCtrlMode = 0; - snsSumMin = 8; - snsDirTo = (u16) -9; - kiInnergainMin = (u16) -1030; - ifIaccuHiTgtMax = 0x2380; - ifIaccuHiTgt = 0x2380; - ingainTgtMin = 0x0511; - ingainTgt = 0x0511; - ingainTgtMax = 5119; - fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay; + clp_sum_min = 8; + clp_dir_to = (u16) -9; + clp_ctrl_mode = 0; + sns_sum_min = 8; + sns_dir_to = (u16) -9; + ki_innergain_min = (u16) -1030; + if_iaccu_hi_tgt_max = 0x2380; + if_iaccu_hi_tgt = 0x2380; + ingain_tgt_min = 0x0511; + ingain_tgt = 0x0511; + ingain_tgt_max = 5119; + fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay; - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay); + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fast_clp_ctrl_delay); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode); + status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, if_iaccu_hi_tgt_max); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); @@ -3046,20 +3046,20 @@ static int InitAGC(struct drxk_state *state, bool isDTV) status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax); + status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax); + status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin); + status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, if_iaccu_hi_tgt); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen); + status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); if (status < 0) goto error; @@ -3076,16 +3076,16 @@ static int InitAGC(struct drxk_state *state, bool isDTV) status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin); + status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin); + status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo); + status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo); + status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff); @@ -3149,34 +3149,34 @@ static int InitAGC(struct drxk_state *state, bool isDTV) return status; } -static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr) +static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) { int status; dprintk(1, "\n"); - if (packetErr == NULL) + if (packet_err == NULL) status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); else - status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr); + status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packet_err); if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int DVBTScCommand(struct drxk_state *state, +static int dvbt_sc_command(struct drxk_state *state, u16 cmd, u16 subcmd, u16 param0, u16 param1, u16 param2, u16 param3, u16 param4) { - u16 curCmd = 0; - u16 errCode = 0; - u16 retryCnt = 0; - u16 scExec = 0; + u16 cur_cmd = 0; + u16 err_code = 0; + u16 retry_cnt = 0; + u16 sc_exec = 0; int status; dprintk(1, "\n"); - status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec); - if (scExec != 1) { + status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec); + if (sc_exec != 1) { /* SC is not running */ status = -EINVAL; } @@ -3184,13 +3184,13 @@ static int DVBTScCommand(struct drxk_state *state, goto error; /* Wait until sc is ready to receive command */ - retryCnt = 0; + retry_cnt = 0; do { msleep(1); - status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); - retryCnt++; - } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); - if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); + retry_cnt++; + } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); + if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error; /* Write sub-command */ @@ -3236,18 +3236,18 @@ static int DVBTScCommand(struct drxk_state *state, goto error; /* Wait until sc is ready processing command */ - retryCnt = 0; + retry_cnt = 0; do { msleep(1); - status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); - retryCnt++; - } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); - if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); + retry_cnt++; + } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); + if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error; /* Check for illegal cmd */ - status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode); - if (errCode == 0xFFFF) { + status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code); + if (err_code == 0xFFFF) { /* illegal command */ status = -EINVAL; } @@ -3283,19 +3283,19 @@ static int DVBTScCommand(struct drxk_state *state, return status; } -static int PowerUpDVBT(struct drxk_state *state) +static int power_up_dvbt(struct drxk_state *state) { - enum DRXPowerMode powerMode = DRX_POWER_UP; + enum drx_power_mode power_mode = DRX_POWER_UP; int status; dprintk(1, "\n"); - status = CtrlPowerMode(state, &powerMode); + status = ctrl_power_mode(state, &power_mode); if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) +static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) { int status; @@ -3310,7 +3310,7 @@ static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) } #define DEFAULT_FR_THRES_8K 4000 -static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) +static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) { int status; @@ -3330,8 +3330,8 @@ static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) return status; } -static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, - struct DRXKCfgDvbtEchoThres_t *echoThres) +static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, + struct drxk_cfg_dvbt_echo_thres_t *echo_thres) { u16 data = 0; int status; @@ -3341,16 +3341,16 @@ static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, if (status < 0) goto error; - switch (echoThres->fftMode) { + switch (echo_thres->fft_mode) { case DRX_FFTMODE_2K: data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M; - data |= ((echoThres->threshold << + data |= ((echo_thres->threshold << OFDM_SC_RA_RAM_ECHO_THRES_2K__B) & (OFDM_SC_RA_RAM_ECHO_THRES_2K__M)); break; case DRX_FFTMODE_8K: data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M; - data |= ((echoThres->threshold << + data |= ((echo_thres->threshold << OFDM_SC_RA_RAM_ECHO_THRES_8K__B) & (OFDM_SC_RA_RAM_ECHO_THRES_8K__M)); break; @@ -3365,8 +3365,8 @@ static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, return status; } -static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, - enum DRXKCfgDvbtSqiSpeed *speed) +static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, + enum drxk_cfg_dvbt_sqi_speed *speed) { int status = -EINVAL; @@ -3398,29 +3398,29 @@ static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, * Called in DVBTSetStandard * */ -static int DVBTActivatePresets(struct drxk_state *state) +static int dvbt_activate_presets(struct drxk_state *state) { int status; bool setincenable = false; bool setfrenable = true; - struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K }; - struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K }; + struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K }; + struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K }; dprintk(1, "\n"); - status = DVBTCtrlSetIncEnable(state, &setincenable); + status = dvbt_ctrl_set_inc_enable(state, &setincenable); if (status < 0) goto error; - status = DVBTCtrlSetFrEnable(state, &setfrenable); + status = dvbt_ctrl_set_fr_enable(state, &setfrenable); if (status < 0) goto error; - status = DVBTCtrlSetEchoThreshold(state, &echoThres2k); + status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k); if (status < 0) goto error; - status = DVBTCtrlSetEchoThreshold(state, &echoThres8k); + status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbt_if_agc_cfg.ingain_tgt_max); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -3437,25 +3437,25 @@ static int DVBTActivatePresets(struct drxk_state *state) * For ROM code channel filter taps are loaded from the bootloader. For microcode * the DVB-T taps from the drxk_filters.h are used. */ -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode) +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode) { - u16 cmdResult = 0; + u16 cmd_result = 0; u16 data = 0; int status; dprintk(1, "\n"); - PowerUpDVBT(state); + power_up_dvbt(state); /* added antenna switch */ - SwitchAntennaToDVBT(state); + switch_antenna_to_dvbt(state); /* send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* send OFDM setenv command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3487,7 +3487,7 @@ static int SetDVBTStandard(struct drxk_state *state, status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); if (status < 0) goto error; - status = SetIqmAf(state, true); + status = set_iqm_af(state, true); if (status < 0) goto error; @@ -3530,7 +3530,7 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); if (status < 0) goto error; @@ -3549,10 +3549,10 @@ static int SetDVBTStandard(struct drxk_state *state, goto error; /* IQM will not be reset from here, sync ADC and update/init AGC */ - status = ADCSynchronization(state); + status = adc_synchronization(state); if (status < 0) goto error; - status = SetPreSaw(state, &state->m_dvbtPreSawCfg); + status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg); if (status < 0) goto error; @@ -3561,10 +3561,10 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true); + status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true); if (status < 0) goto error; - status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true); + status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true); if (status < 0) goto error; @@ -3582,9 +3582,9 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - if (!state->m_DRXK_A3_ROM_CODE) { - /* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay */ - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay); + if (!state->m_drxk_a3_rom_code) { + /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */ + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); if (status < 0) goto error; } @@ -3619,11 +3619,11 @@ static int SetDVBTStandard(struct drxk_state *state, goto error; /* Setup MPEG bus */ - status = MPEGTSDtoSetup(state, OM_DVBT); + status = mpegts_dto_setup(state, OM_DVBT); if (status < 0) goto error; /* Set DVBT Presets */ - status = DVBTActivatePresets(state); + status = dvbt_activate_presets(state); if (status < 0) goto error; @@ -3635,25 +3635,25 @@ static int SetDVBTStandard(struct drxk_state *state, /*============================================================================*/ /** -* \brief Start dvbt demodulating for channel. +* \brief start dvbt demodulating for channel. * \param demod instance of demodulator. * \return DRXStatus_t. */ -static int DVBTStart(struct drxk_state *state) +static int dvbt_start(struct drxk_state *state) { u16 param1; int status; - /* DRXKOfdmScCmd_t scCmd; */ + /* drxk_ofdm_sc_cmd_t scCmd; */ dprintk(1, "\n"); - /* Start correct processes to get in lock */ + /* start correct processes to get in lock */ /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */ param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN; - status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); + status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); if (status < 0) goto error; - /* Start FEC OC */ - status = MPEGTSStart(state); + /* start FEC OC */ + status = mpegts_start(state); if (status < 0) goto error; status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); @@ -3674,20 +3674,20 @@ static int DVBTStart(struct drxk_state *state) * \return DRXStatus_t. * // original DVBTSetChannel() */ -static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset) +static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset) { - u16 cmdResult = 0; - u16 transmissionParams = 0; - u16 operationMode = 0; - u32 iqmRcRateOfs = 0; + u16 cmd_result = 0; + u16 transmission_params = 0; + u16 operation_mode = 0; + u32 iqm_rc_rate_ofs = 0; u32 bandwidth = 0; u16 param1; int status; - dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset); + dprintk(1, "IF =%d, TFO = %d\n", intermediate_freqk_hz, tuner_freq_offset); - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3716,13 +3716,13 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.transmission_mode) { case TRANSMISSION_MODE_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; /* fall through , try first guess DRX_FFTMODE_8K */ case TRANSMISSION_MODE_8K: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; case TRANSMISSION_MODE_2K: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; break; } @@ -3730,19 +3730,19 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.guard_interval) { default: case GUARD_INTERVAL_AUTO: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; /* fall through , try first guess DRX_GUARD_1DIV4 */ case GUARD_INTERVAL_1_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; case GUARD_INTERVAL_1_32: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; break; case GUARD_INTERVAL_1_16: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; break; case GUARD_INTERVAL_1_8: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; break; } @@ -3751,18 +3751,18 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, case HIERARCHY_AUTO: case HIERARCHY_NONE: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ - /* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ + /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ /* break; */ case HIERARCHY_1: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; case HIERARCHY_2: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; break; case HIERARCHY_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; break; } @@ -3771,16 +3771,16 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.modulation) { case QAM_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; /* fall through , try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; case QPSK: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; break; case QAM_16: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; break; } #if 0 @@ -3788,13 +3788,13 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, /* Priority (only for hierarchical channels) */ switch (channel->priority) { case DRX_PRIORITY_LOW: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; - WR16(devAddr, OFDM_EC_SB_PRIOR__A, + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; + WR16(dev_addr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_LO); break; case DRX_PRIORITY_HIGH: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; - WR16(devAddr, OFDM_EC_SB_PRIOR__A, + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; + WR16(dev_addr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI)); break; case DRX_PRIORITY_UNKNOWN: /* fall through */ @@ -3804,7 +3804,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, } #else /* Set Priorty high */ - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI); if (status < 0) goto error; @@ -3814,22 +3814,22 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.code_rate_HP) { case FEC_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; /* fall through , try first guess DRX_CODERATE_2DIV3 */ case FEC_2_3: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; case FEC_1_2: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; break; case FEC_3_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; break; case FEC_5_6: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; break; case FEC_7_8: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; break; } @@ -3906,7 +3906,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; } - if (iqmRcRateOfs == 0) { + if (iqm_rc_rate_ofs == 0) { /* Now compute IQM_RC_RATE_OFS (((SysFreq/BandWidth)/2)/2) -1) * 2^23) => @@ -3916,36 +3916,36 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, /* assert (MAX(sysClk)/MIN(bandwidth) < 16) => assert(MAX(sysClk) < 16*MIN(bandwidth)) => assert(109714272 > 48000000) = true so Frac 28 can be used */ - iqmRcRateOfs = Frac28a((u32) - ((state->m_sysClockFreq * + iqm_rc_rate_ofs = Frac28a((u32) + ((state->m_sys_clock_freq * 1000) / 3), bandwidth); /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ - if ((iqmRcRateOfs & 0x7fL) >= 0x40) - iqmRcRateOfs += 0x80L; - iqmRcRateOfs = iqmRcRateOfs >> 7; + if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40) + iqm_rc_rate_ofs += 0x80L; + iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7; /* ((SysFreq / BandWidth) * (2^21)) - (2^23) */ - iqmRcRateOfs = iqmRcRateOfs - (1 << 23); + iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23); } - iqmRcRateOfs &= + iqm_rc_rate_ofs &= ((((u32) IQM_RC_RATE_OFS_HI__M) << IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M); - status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs); + status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs); if (status < 0) goto error; /* Bandwidth setting done */ #if 0 - status = DVBTSetFrequencyShift(demod, channel, tunerOffset); + status = dvbt_set_frequency_shift(demod, channel, tuner_offset); if (status < 0) goto error; #endif - status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true); if (status < 0) goto error; - /*== Start SC, write channel settings to SC ===============================*/ + /*== start SC, write channel settings to SC ===============================*/ /* Activate SCU to enable SCU commands */ status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); @@ -3961,7 +3961,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3971,13 +3971,13 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, OFDM_SC_RA_RAM_OP_AUTO_CONST__M | OFDM_SC_RA_RAM_OP_AUTO_HIER__M | OFDM_SC_RA_RAM_OP_AUTO_RATE__M); - status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, - 0, transmissionParams, param1, 0, 0, 0); + status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, + 0, transmission_params, param1, 0, 0, 0); if (status < 0) goto error; - if (!state->m_DRXK_A3_ROM_CODE) - status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed); + if (!state->m_drxk_a3_rom_code) + status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -3995,7 +3995,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, * \return DRXStatus_t. * */ -static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status; const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M | @@ -4003,32 +4003,32 @@ static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M); const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M; - u16 ScRaRamLock = 0; - u16 ScCommExec = 0; + u16 sc_ra_ram_lock = 0; + u16 sc_comm_exec = 0; dprintk(1, "\n"); - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; /* driver 0.9.0 */ /* Check if SC is running */ - status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec); + status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec); if (status < 0) goto end; - if (ScCommExec == OFDM_SC_COMM_EXEC_STOP) + if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP) goto end; - status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock); + status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock); if (status < 0) goto end; - if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) - *pLockStatus = MPEG_LOCK; - else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) - *pLockStatus = FEC_LOCK; - else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) - *pLockStatus = DEMOD_LOCK; - else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) - *pLockStatus = NEVER_LOCK; + if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask) + *p_lock_status = MPEG_LOCK; + else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask) + *p_lock_status = FEC_LOCK; + else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask) + *p_lock_status = DEMOD_LOCK; + else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) + *p_lock_status = NEVER_LOCK; end: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -4036,13 +4036,13 @@ static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) return status; } -static int PowerUpQAM(struct drxk_state *state) +static int power_up_qam(struct drxk_state *state) { - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; int status; dprintk(1, "\n"); - status = CtrlPowerMode(state, &powerMode); + status = ctrl_power_mode(state, &power_mode); if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -4051,10 +4051,10 @@ static int PowerUpQAM(struct drxk_state *state) /** Power Down QAM */ -static int PowerDownQAM(struct drxk_state *state) +static int power_down_qam(struct drxk_state *state) { u16 data = 0; - u16 cmdResult; + u16 cmd_result; int status = 0; dprintk(1, "\n"); @@ -4070,12 +4070,12 @@ static int PowerDownQAM(struct drxk_state *state) status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); if (status < 0) goto error; } /* powerdown AFE */ - status = SetIqmAf(state, false); + status = set_iqm_af(state, false); error: if (status < 0) @@ -4097,20 +4097,20 @@ static int PowerDownQAM(struct drxk_state *state) * The implementation does not check this. * */ -static int SetQAMMeasurement(struct drxk_state *state, - enum EDrxkConstellation modulation, - u32 symbolRate) +static int set_qam_measurement(struct drxk_state *state, + enum e_drxk_constellation modulation, + u32 symbol_rate) { - u32 fecBitsDesired = 0; /* BER accounting period */ - u32 fecRsPeriodTotal = 0; /* Total period */ - u16 fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ - u16 fecRsPeriod = 0; /* Value for corresponding I2C register */ + u32 fec_bits_desired = 0; /* BER accounting period */ + u32 fec_rs_period_total = 0; /* Total period */ + u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ + u16 fec_rs_period = 0; /* Value for corresponding I2C register */ int status = 0; dprintk(1, "\n"); - fecRsPrescale = 1; - /* fecBitsDesired = symbolRate [kHz] * + fec_rs_prescale = 1; + /* fec_bits_desired = symbol_rate [kHz] * FrameLenght [ms] * (modulation + 1) * SyncLoss (== 1) * @@ -4118,19 +4118,19 @@ static int SetQAMMeasurement(struct drxk_state *state, */ switch (modulation) { case DRX_CONSTELLATION_QAM16: - fecBitsDesired = 4 * symbolRate; + fec_bits_desired = 4 * symbol_rate; break; case DRX_CONSTELLATION_QAM32: - fecBitsDesired = 5 * symbolRate; + fec_bits_desired = 5 * symbol_rate; break; case DRX_CONSTELLATION_QAM64: - fecBitsDesired = 6 * symbolRate; + fec_bits_desired = 6 * symbol_rate; break; case DRX_CONSTELLATION_QAM128: - fecBitsDesired = 7 * symbolRate; + fec_bits_desired = 7 * symbol_rate; break; case DRX_CONSTELLATION_QAM256: - fecBitsDesired = 8 * symbolRate; + fec_bits_desired = 8 * symbol_rate; break; default: status = -EINVAL; @@ -4138,40 +4138,40 @@ static int SetQAMMeasurement(struct drxk_state *state, if (status < 0) goto error; - fecBitsDesired /= 1000; /* symbolRate [Hz] -> symbolRate [kHz] */ - fecBitsDesired *= 500; /* meas. period [ms] */ + fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ + fec_bits_desired *= 500; /* meas. period [ms] */ /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */ - /* fecRsPeriodTotal = fecBitsDesired / 1632 */ - fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1; /* roughly ceil */ + /* fec_rs_period_total = fec_bits_desired / 1632 */ + fec_rs_period_total = (fec_bits_desired / 1632UL) + 1; /* roughly ceil */ - /* fecRsPeriodTotal = fecRsPrescale * fecRsPeriod */ - fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16); - if (fecRsPrescale == 0) { + /* fec_rs_period_total = fec_rs_prescale * fec_rs_period */ + fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16); + if (fec_rs_prescale == 0) { /* Divide by zero (though impossible) */ status = -EINVAL; if (status < 0) goto error; } - fecRsPeriod = - ((u16) fecRsPeriodTotal + - (fecRsPrescale >> 1)) / fecRsPrescale; + fec_rs_period = + ((u16) fec_rs_period_total + + (fec_rs_prescale >> 1)) / fec_rs_prescale; /* write corresponding registers */ - status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod); + status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period); if (status < 0) goto error; - status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale); + status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale); if (status < 0) goto error; - status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod); + status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int SetQAM16(struct drxk_state *state) +static int set_qam16(struct drxk_state *state) { int status = 0; @@ -4364,7 +4364,7 @@ static int SetQAM16(struct drxk_state *state) * \param demod instance of demod. * \return DRXStatus_t. */ -static int SetQAM32(struct drxk_state *state) +static int set_qam32(struct drxk_state *state) { int status = 0; @@ -4559,7 +4559,7 @@ static int SetQAM32(struct drxk_state *state) * \param demod instance of demod. * \return DRXStatus_t. */ -static int SetQAM64(struct drxk_state *state) +static int set_qam64(struct drxk_state *state) { int status = 0; @@ -4753,7 +4753,7 @@ static int SetQAM64(struct drxk_state *state) * \param demod: instance of demod. * \return DRXStatus_t. */ -static int SetQAM128(struct drxk_state *state) +static int set_qam128(struct drxk_state *state) { int status = 0; @@ -4949,7 +4949,7 @@ static int SetQAM128(struct drxk_state *state) * \param demod: instance of demod. * \return DRXStatus_t. */ -static int SetQAM256(struct drxk_state *state) +static int set_qam256(struct drxk_state *state) { int status = 0; @@ -5144,10 +5144,10 @@ static int SetQAM256(struct drxk_state *state) * \param channel: pointer to channel data. * \return DRXStatus_t. */ -static int QAMResetQAM(struct drxk_state *state) +static int qam_reset_qam(struct drxk_state *state) { int status; - u16 cmdResult; + u16 cmd_result; dprintk(1, "\n"); /* Stop QAM comstate->m_exec */ @@ -5155,7 +5155,7 @@ static int QAMResetQAM(struct drxk_state *state) if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -5170,18 +5170,18 @@ static int QAMResetQAM(struct drxk_state *state) * \param channel: pointer to channel data. * \return DRXStatus_t. */ -static int QAMSetSymbolrate(struct drxk_state *state) +static int qam_set_symbolrate(struct drxk_state *state) { - u32 adcFrequency = 0; - u32 symbFreq = 0; - u32 iqmRcRate = 0; + u32 adc_frequency = 0; + u32 symb_freq = 0; + u32 iqm_rc_rate = 0; u16 ratesel = 0; - u32 lcSymbRate = 0; + u32 lc_symb_rate = 0; int status; dprintk(1, "\n"); /* Select & calculate correct IQM rate */ - adcFrequency = (state->m_sysClockFreq * 1000) / 3; + adc_frequency = (state->m_sys_clock_freq * 1000) / 3; ratesel = 0; /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */ if (state->props.symbol_rate <= 1188750) @@ -5197,34 +5197,34 @@ static int QAMSetSymbolrate(struct drxk_state *state) /* IqmRcRate = ((Fadc / (symbolrate * (4<props.symbol_rate * (1 << ratesel); - if (symbFreq == 0) { + symb_freq = state->props.symbol_rate * (1 << ratesel); + if (symb_freq == 0) { /* Divide by zero */ status = -EINVAL; goto error; } - iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) + - (Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) - + iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) + + (Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) - (1 << 23); - status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate); + status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate); if (status < 0) goto error; - state->m_iqmRcRate = iqmRcRate; + state->m_iqm_rc_rate = iqm_rc_rate; /* - LcSymbFreq = round (.125 * symbolrate / adcFreq * (1<<15)) + LcSymbFreq = round (.125 * symbolrate / adc_freq * (1<<15)) */ - symbFreq = state->props.symbol_rate; - if (adcFrequency == 0) { + symb_freq = state->props.symbol_rate; + if (adc_frequency == 0) { /* Divide by zero */ status = -EINVAL; goto error; } - lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) + - (Frac28a((symbFreq % adcFrequency), adcFrequency) >> + lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) + + (Frac28a((symb_freq % adc_frequency), adc_frequency) >> 16); - if (lcSymbRate > 511) - lcSymbRate = 511; - status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate); + if (lc_symb_rate > 511) + lc_symb_rate = 511; + status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate); error: if (status < 0) @@ -5241,34 +5241,34 @@ static int QAMSetSymbolrate(struct drxk_state *state) * \return DRXStatus_t. */ -static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status; - u16 Result[2] = { 0, 0 }; + u16 result[2] = { 0, 0 }; dprintk(1, "\n"); - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, - Result); + result); if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); - if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { + if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { /* 0x0000 NOT LOCKED */ - } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { + } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { /* 0x4000 DEMOD LOCKED */ - *pLockStatus = DEMOD_LOCK; - } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { + *p_lock_status = DEMOD_LOCK; + } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { /* 0x8000 DEMOD + FEC LOCKED (system lock) */ - *pLockStatus = MPEG_LOCK; + *p_lock_status = MPEG_LOCK; } else { /* 0xC000 NEVER LOCKED */ /* (system will never be able to lock to the signal) */ /* TODO: check this, intermediate & standard specific lock states are not taken into account here */ - *pLockStatus = NEVER_LOCK; + *p_lock_status = NEVER_LOCK; } return status; } @@ -5280,52 +5280,52 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) #define QAM_LOCKRANGE__M 0x10 #define QAM_LOCKRANGE_NORMAL 0x10 -static int QAMDemodulatorCommand(struct drxk_state *state, - int numberOfParameters) +static int qam_demodulator_command(struct drxk_state *state, + int number_of_parameters) { int status; - u16 cmdResult; - u16 setParamParameters[4] = { 0, 0, 0, 0 }; + u16 cmd_result; + u16 set_param_parameters[4] = { 0, 0, 0, 0 }; - setParamParameters[0] = state->m_Constellation; /* modulation */ - setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ + set_param_parameters[0] = state->m_constellation; /* modulation */ + set_param_parameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ - if (numberOfParameters == 2) { - u16 setEnvParameters[1] = { 0 }; + if (number_of_parameters == 2) { + u16 set_env_parameters[1] = { 0 }; - if (state->m_OperationMode == OM_QAM_ITU_C) - setEnvParameters[0] = QAM_TOP_ANNEX_C; + if (state->m_operation_mode == OM_QAM_ITU_C) + set_env_parameters[0] = QAM_TOP_ANNEX_C; else - setEnvParameters[0] = QAM_TOP_ANNEX_A; + set_env_parameters[0] = QAM_TOP_ANNEX_A; status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, - 1, setEnvParameters, 1, &cmdResult); + 1, set_env_parameters, 1, &cmd_result); if (status < 0) goto error; status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, - numberOfParameters, setParamParameters, - 1, &cmdResult); - } else if (numberOfParameters == 4) { - if (state->m_OperationMode == OM_QAM_ITU_C) - setParamParameters[2] = QAM_TOP_ANNEX_C; + number_of_parameters, set_param_parameters, + 1, &cmd_result); + } else if (number_of_parameters == 4) { + if (state->m_operation_mode == OM_QAM_ITU_C) + set_param_parameters[2] = QAM_TOP_ANNEX_C; else - setParamParameters[2] = QAM_TOP_ANNEX_A; + set_param_parameters[2] = QAM_TOP_ANNEX_A; - setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); + set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON); /* Env parameters */ /* check for LOCKRANGE Extented */ - /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ + /* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */ status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, - numberOfParameters, setParamParameters, - 1, &cmdResult); + number_of_parameters, set_param_parameters, + 1, &cmd_result); } else { printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter " - "count %d\n", numberOfParameters); + "count %d\n", number_of_parameters); status = -EINVAL; } @@ -5336,12 +5336,12 @@ static int QAMDemodulatorCommand(struct drxk_state *state, return status; } -static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset) +static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset) { int status; - u16 cmdResult; - int qamDemodParamCount = state->qam_demod_parameter_count; + u16 cmd_result; + int qam_demod_param_count = state->qam_demod_parameter_count; dprintk(1, "\n"); /* @@ -5356,7 +5356,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP); if (status < 0) goto error; - status = QAMResetQAM(state); + status = qam_reset_qam(state); if (status < 0) goto error; @@ -5365,27 +5365,27 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * -set params; resets IQM,QAM,FEC HW; initializes some * SCU variables */ - status = QAMSetSymbolrate(state); + status = qam_set_symbolrate(state); if (status < 0) goto error; /* Set params */ switch (state->props.modulation) { case QAM_256: - state->m_Constellation = DRX_CONSTELLATION_QAM256; + state->m_constellation = DRX_CONSTELLATION_QAM256; break; case QAM_AUTO: case QAM_64: - state->m_Constellation = DRX_CONSTELLATION_QAM64; + state->m_constellation = DRX_CONSTELLATION_QAM64; break; case QAM_16: - state->m_Constellation = DRX_CONSTELLATION_QAM16; + state->m_constellation = DRX_CONSTELLATION_QAM16; break; case QAM_32: - state->m_Constellation = DRX_CONSTELLATION_QAM32; + state->m_constellation = DRX_CONSTELLATION_QAM32; break; case QAM_128: - state->m_Constellation = DRX_CONSTELLATION_QAM128; + state->m_constellation = DRX_CONSTELLATION_QAM128; break; default: status = -EINVAL; @@ -5398,8 +5398,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * the correct command. */ if (state->qam_demod_parameter_count == 4 || !state->qam_demod_parameter_count) { - qamDemodParamCount = 4; - status = QAMDemodulatorCommand(state, qamDemodParamCount); + qam_demod_param_count = 4; + status = qam_demodulator_command(state, qam_demod_param_count); } /* Use the 2-parameter command if it was requested or if we're @@ -5407,8 +5407,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * failed. */ if (state->qam_demod_parameter_count == 2 || (!state->qam_demod_parameter_count && status < 0)) { - qamDemodParamCount = 2; - status = QAMDemodulatorCommand(state, qamDemodParamCount); + qam_demod_param_count = 2; + status = qam_demodulator_command(state, qam_demod_param_count); } if (status < 0) { @@ -5421,13 +5421,13 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, } else if (!state->qam_demod_parameter_count) { dprintk(1, "Auto-probing the correct QAM demodulator command " "parameters was successful - using %d parameters.\n", - qamDemodParamCount); + qam_demod_param_count); /* * One of our commands was successful. We don't need to * auto-probe anymore, now that we got the correct command. */ - state->qam_demod_parameter_count = qamDemodParamCount; + state->qam_demod_parameter_count = qam_demod_param_count; } /* @@ -5435,16 +5435,16 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * signal setup modulation independent registers */ #if 0 - status = SetFrequency(channel, tunerFreqOffset)); + status = set_frequency(channel, tuner_freq_offset)); if (status < 0) goto error; #endif - status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true); if (status < 0) goto error; /* Setup BER measurement */ - status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate); + status = set_qam_measurement(state, state->m_constellation, state->props.symbol_rate); if (status < 0) goto error; @@ -5529,20 +5529,20 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, /* STEP 4: modulation specific setup */ switch (state->props.modulation) { case QAM_16: - status = SetQAM16(state); + status = set_qam16(state); break; case QAM_32: - status = SetQAM32(state); + status = set_qam32(state); break; case QAM_AUTO: case QAM_64: - status = SetQAM64(state); + status = set_qam64(state); break; case QAM_128: - status = SetQAM128(state); + status = set_qam128(state); break; case QAM_256: - status = SetQAM256(state); + status = set_qam256(state); break; default: status = -EINVAL; @@ -5559,12 +5559,12 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, /* Re-configure MPEG output, requires knowledge of channel bitrate */ /* extAttr->currentChannel.modulation = channel->modulation; */ /* extAttr->currentChannel.symbolrate = channel->symbolrate; */ - status = MPEGTSDtoSetup(state, state->m_OperationMode); + status = mpegts_dto_setup(state, state->m_operation_mode); if (status < 0) goto error; - /* Start processes */ - status = MPEGTSStart(state); + /* start processes */ + status = mpegts_start(state); if (status < 0) goto error; status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); @@ -5578,7 +5578,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -5591,8 +5591,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, return status; } -static int SetQAMStandard(struct drxk_state *state, - enum OperationMode oMode) +static int set_qam_standard(struct drxk_state *state, + enum operation_mode o_mode) { int status; #ifdef DRXK_QAM_TAPS @@ -5604,14 +5604,14 @@ static int SetQAMStandard(struct drxk_state *state, dprintk(1, "\n"); /* added antenna switch */ - SwitchAntennaToQAM(state); + switch_antenna_to_qam(state); /* Ensure correct power-up mode */ - status = PowerUpQAM(state); + status = power_up_qam(state); if (status < 0) goto error; /* Reset QAM block */ - status = QAMResetQAM(state); + status = qam_reset_qam(state); if (status < 0) goto error; @@ -5626,15 +5626,15 @@ static int SetQAMStandard(struct drxk_state *state, /* Upload IQM Channel Filter settings by boot loader from ROM table */ - switch (oMode) { + switch (o_mode) { case OM_QAM_ITU_A: - status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); break; case OM_QAM_ITU_C: - status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); if (status < 0) goto error; - status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); break; default: status = -EINVAL; @@ -5705,7 +5705,7 @@ static int SetQAMStandard(struct drxk_state *state, goto error; /* turn on IQMAF. Must be done before setAgc**() */ - status = SetIqmAf(state, true); + status = set_iqm_af(state, true); if (status < 0) goto error; status = write16(state, IQM_AF_START_LOCK__A, 0x01); @@ -5713,7 +5713,7 @@ static int SetQAMStandard(struct drxk_state *state, goto error; /* IQM will not be reset from here, sync ADC and update/init AGC */ - status = ADCSynchronization(state); + status = adc_synchronization(state); if (status < 0) goto error; @@ -5730,18 +5730,18 @@ static int SetQAMStandard(struct drxk_state *state, /* No more resets of the IQM, current standard correctly set => now AGCs can be configured. */ - status = InitAGC(state, true); + status = init_agc(state, true); if (status < 0) goto error; - status = SetPreSaw(state, &(state->m_qamPreSawCfg)); + status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg)); if (status < 0) goto error; /* Configure AGC's */ - status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true); + status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true); if (status < 0) goto error; - status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true); + status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true); if (status < 0) goto error; @@ -5753,7 +5753,7 @@ static int SetQAMStandard(struct drxk_state *state, return status; } -static int WriteGPIO(struct drxk_state *state) +static int write_gpio(struct drxk_state *state) { int status; u16 value = 0; @@ -5769,10 +5769,10 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; - if (state->m_hasSAWSW) { - if (state->UIO_mask & 0x0001) { /* UIO-1 */ + if (state->m_has_sawsw) { + if (state->uio_mask & 0x0001) { /* UIO-1 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_gpio_cfg); if (status < 0) goto error; @@ -5780,7 +5780,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0001) == 0) + if ((state->m_gpio & 0x0001) == 0) value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ else value |= 0x8000; /* write one to 15th bit - 1st UIO */ @@ -5789,9 +5789,9 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; } - if (state->UIO_mask & 0x0002) { /* UIO-2 */ + if (state->uio_mask & 0x0002) { /* UIO-2 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_gpio_cfg); if (status < 0) goto error; @@ -5799,7 +5799,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0002) == 0) + if ((state->m_gpio & 0x0002) == 0) value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ else value |= 0x4000; /* write one to 14th bit - 2st UIO */ @@ -5808,9 +5808,9 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; } - if (state->UIO_mask & 0x0004) { /* UIO-3 */ + if (state->uio_mask & 0x0004) { /* UIO-3 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_gpio_cfg); if (status < 0) goto error; @@ -5818,7 +5818,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0004) == 0) + if ((state->m_gpio & 0x0004) == 0) value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ else value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ @@ -5836,7 +5836,7 @@ static int WriteGPIO(struct drxk_state *state) return status; } -static int SwitchAntennaToQAM(struct drxk_state *state) +static int switch_antenna_to_qam(struct drxk_state *state) { int status = 0; bool gpio_state; @@ -5846,22 +5846,22 @@ static int SwitchAntennaToQAM(struct drxk_state *state) if (!state->antenna_gpio) return 0; - gpio_state = state->m_GPIO & state->antenna_gpio; + gpio_state = state->m_gpio & state->antenna_gpio; if (state->antenna_dvbt ^ gpio_state) { /* Antenna is on DVB-T mode. Switch */ if (state->antenna_dvbt) - state->m_GPIO &= ~state->antenna_gpio; + state->m_gpio &= ~state->antenna_gpio; else - state->m_GPIO |= state->antenna_gpio; - status = WriteGPIO(state); + state->m_gpio |= state->antenna_gpio; + status = write_gpio(state); } if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); return status; } -static int SwitchAntennaToDVBT(struct drxk_state *state) +static int switch_antenna_to_dvbt(struct drxk_state *state) { int status = 0; bool gpio_state; @@ -5871,15 +5871,15 @@ static int SwitchAntennaToDVBT(struct drxk_state *state) if (!state->antenna_gpio) return 0; - gpio_state = state->m_GPIO & state->antenna_gpio; + gpio_state = state->m_gpio & state->antenna_gpio; if (!(state->antenna_dvbt ^ gpio_state)) { /* Antenna is on DVB-C mode. Switch */ if (state->antenna_dvbt) - state->m_GPIO |= state->antenna_gpio; + state->m_gpio |= state->antenna_gpio; else - state->m_GPIO &= ~state->antenna_gpio; - status = WriteGPIO(state); + state->m_gpio &= ~state->antenna_gpio; + status = write_gpio(state); } if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -5887,7 +5887,7 @@ static int SwitchAntennaToDVBT(struct drxk_state *state) } -static int PowerDownDevice(struct drxk_state *state) +static int power_down_device(struct drxk_state *state) { /* Power down to requested mode */ /* Backup some register settings */ @@ -5898,14 +5898,14 @@ static int PowerDownDevice(struct drxk_state *state) int status; dprintk(1, "\n"); - if (state->m_bPDownOpenBridge) { + if (state->m_b_p_down_open_bridge) { /* Open I2C bridge before power down of DRXK */ status = ConfigureI2CBridge(state, true); if (status < 0) goto error; } /* driver 0.9.0 */ - status = DVBTEnableOFDMTokenRing(state, false); + status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error; @@ -5915,8 +5915,8 @@ static int PowerDownDevice(struct drxk_state *state) status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; - state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; - status = HI_CfgCommand(state); + state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + status = hi_cfg_command(state); error: if (status < 0) printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); @@ -5927,16 +5927,16 @@ static int PowerDownDevice(struct drxk_state *state) static int init_drxk(struct drxk_state *state) { int status = 0, n = 0; - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; - u16 driverVersion; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; + u16 driver_version; dprintk(1, "\n"); - if ((state->m_DrxkState == DRXK_UNINITIALIZED)) { + if ((state->m_drxk_state == DRXK_UNINITIALIZED)) { drxk_i2c_lock(state); - status = PowerUpDevice(state); + status = power_up_device(state); if (status < 0) goto error; - status = DRXX_Open(state); + status = drxx_open(state); if (status < 0) goto error; /* Soft reset of OFDM-, sys- and osc-clockdomain */ @@ -5948,29 +5948,29 @@ static int init_drxk(struct drxk_state *state) goto error; /* TODO is this needed, if yes how much delay in worst case scenario */ msleep(1); - state->m_DRXK_A3_PATCH_CODE = true; - status = GetDeviceCapabilities(state); + state->m_drxk_a3_patch_code = true; + status = get_device_capabilities(state); if (status < 0) goto error; /* Bridge delay, uses oscilator clock */ /* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */ /* SDA brdige delay */ - state->m_HICfgBridgeDelay = - (u16) ((state->m_oscClockFreq / 1000) * + state->m_hi_cfg_bridge_delay = + (u16) ((state->m_osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) / 1000; /* Clipping */ - if (state->m_HICfgBridgeDelay > + if (state->m_hi_cfg_bridge_delay > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) { - state->m_HICfgBridgeDelay = + state->m_hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; } /* SCL bridge delay, same as SDA for now */ - state->m_HICfgBridgeDelay += - state->m_HICfgBridgeDelay << + state->m_hi_cfg_bridge_delay += + state->m_hi_cfg_bridge_delay << SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B; - status = InitHI(state); + status = init_hi(state); if (status < 0) goto error; /* disable various processes */ @@ -5985,7 +5985,7 @@ static int init_drxk(struct drxk_state *state) } /* disable MPEG port */ - status = MPEGTSDisable(state); + status = mpegts_disable(state); if (status < 0) goto error; @@ -6006,12 +6006,12 @@ static int init_drxk(struct drxk_state *state) status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE); if (status < 0) goto error; - status = BLChainCmd(state, 0, 6, 100); + status = bl_chain_cmd(state, 0, 6, 100); if (status < 0) goto error; if (state->fw) { - status = DownloadMicrocode(state, state->fw->data, + status = download_microcode(state, state->fw->data, state->fw->size); if (status < 0) goto error; @@ -6026,14 +6026,14 @@ static int init_drxk(struct drxk_state *state) status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error; - status = DRXX_Open(state); + status = drxx_open(state); if (status < 0) goto error; /* added for test */ msleep(30); - powerMode = DRXK_POWER_DOWN_OFDM; - status = CtrlPowerMode(state, &powerMode); + power_mode = DRXK_POWER_DOWN_OFDM; + status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error; @@ -6043,20 +6043,20 @@ static int init_drxk(struct drxk_state *state) Not using SCU command interface for SCU register access since no microcode may be present. */ - driverVersion = + driver_version = (((DRXK_VERSION_MAJOR / 100) % 10) << 12) + (((DRXK_VERSION_MAJOR / 10) % 10) << 8) + ((DRXK_VERSION_MAJOR % 10) << 4) + (DRXK_VERSION_MINOR % 10); - status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion); + status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driver_version); if (status < 0) goto error; - driverVersion = + driver_version = (((DRXK_VERSION_PATCH / 1000) % 10) << 12) + (((DRXK_VERSION_PATCH / 100) % 10) << 8) + (((DRXK_VERSION_PATCH / 10) % 10) << 4) + (DRXK_VERSION_PATCH % 10); - status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion); + status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driver_version); if (status < 0) goto error; @@ -6069,7 +6069,7 @@ static int init_drxk(struct drxk_state *state) before calling DRX_Open. This solution requires changes to RF AGC speed to be done via the CTRL function after calling DRX_Open */ - /* m_dvbtRfAgcCfg.speed = 3; */ + /* m_dvbt_rf_agc_cfg.speed = 3; */ /* Reset driver debug flags to 0 */ status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0); @@ -6082,42 +6082,42 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; /* MPEGTS functions are still the same */ - status = MPEGTSDtoInit(state); + status = mpegts_dto_init(state); if (status < 0) goto error; - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = MPEGTSConfigurePolarity(state); + status = mpegts_configure_polarity(state); if (status < 0) goto error; - status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput); + status = mpegts_configure_pins(state, state->m_enable_mpeg_output); if (status < 0) goto error; /* added: configure GPIO */ - status = WriteGPIO(state); + status = write_gpio(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_STOPPED; + state->m_drxk_state = DRXK_STOPPED; - if (state->m_bPowerDown) { - status = PowerDownDevice(state); + if (state->m_b_power_down) { + status = power_down_device(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_POWERED_DOWN; + state->m_drxk_state = DRXK_POWERED_DOWN; } else - state->m_DrxkState = DRXK_STOPPED; + state->m_drxk_state = DRXK_STOPPED; /* Initialize the supported delivery systems */ n = 0; - if (state->m_hasDVBC) { + if (state->m_has_dvbc) { state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; strlcat(state->frontend.ops.info.name, " DVB-C", sizeof(state->frontend.ops.info.name)); } - if (state->m_hasDVBT) { + if (state->m_has_dvbt) { state->frontend.ops.delsys[n++] = SYS_DVBT; strlcat(state->frontend.ops.info.name, " DVB-T", sizeof(state->frontend.ops.info.name)); @@ -6126,7 +6126,7 @@ static int init_drxk(struct drxk_state *state) } error: if (status < 0) { - state->m_DrxkState = DRXK_NO_DEV; + state->m_drxk_state = DRXK_NO_DEV; drxk_i2c_unlock(state); printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); } @@ -6182,12 +6182,12 @@ static int drxk_sleep(struct dvb_frontend *fe) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return 0; - ShutDown(state); + shut_down(state); return 0; } @@ -6197,7 +6197,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) dprintk(1, ": %s\n", enable ? "enable" : "disable"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; return ConfigureI2CBridge(state, enable ? true : false); @@ -6212,10 +6212,10 @@ static int drxk_set_parameters(struct dvb_frontend *fe) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; if (!fe->ops.tuner_ops.get_if_frequency) { @@ -6235,22 +6235,22 @@ static int drxk_set_parameters(struct dvb_frontend *fe) state->props = *p; if (old_delsys != delsys) { - ShutDown(state); + shut_down(state); switch (delsys) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: - if (!state->m_hasDVBC) + if (!state->m_has_dvbc) return -EINVAL; state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false; if (state->m_itut_annex_c) - SetOperationMode(state, OM_QAM_ITU_C); + setoperation_mode(state, OM_QAM_ITU_C); else - SetOperationMode(state, OM_QAM_ITU_A); + setoperation_mode(state, OM_QAM_ITU_A); break; case SYS_DVBT: - if (!state->m_hasDVBT) + if (!state->m_has_dvbt) return -EINVAL; - SetOperationMode(state, OM_DVBT); + setoperation_mode(state, OM_DVBT); break; default: return -EINVAL; @@ -6258,7 +6258,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe) } fe->ops.tuner_ops.get_if_frequency(fe, &IF); - Start(state, 0, IF); + start(state, 0, IF); /* After set_frontend, stats aren't avaliable */ p->strength.stat[0].scale = FE_SCALE_RELATIVE; @@ -6278,31 +6278,31 @@ static int drxk_set_parameters(struct dvb_frontend *fe) static int get_strength(struct drxk_state *state, u64 *strength) { int status; - struct SCfgAgc rfAgc, ifAgc; - u32 totalGain = 0; + struct s_cfg_agc rf_agc, if_agc; + u32 total_gain = 0; u32 atten = 0; - u32 agcRange = 0; + u32 agc_range = 0; u16 scu_lvl = 0; u16 scu_coc = 0; /* FIXME: those are part of the tuner presets */ - u16 tunerRfGain = 50; /* Default value on az6007 driver */ - u16 tunerIfGain = 40; /* Default value on az6007 driver */ + u16 tuner_rf_gain = 50; /* Default value on az6007 driver */ + u16 tuner_if_gain = 40; /* Default value on az6007 driver */ *strength = 0; - if (IsDVBT(state)) { - rfAgc = state->m_dvbtRfAgcCfg; - ifAgc = state->m_dvbtIfAgcCfg; - } else if (IsQAM(state)) { - rfAgc = state->m_qamRfAgcCfg; - ifAgc = state->m_qamIfAgcCfg; + if (is_dvbt(state)) { + rf_agc = state->m_dvbt_rf_agc_cfg; + if_agc = state->m_dvbt_if_agc_cfg; + } else if (is_qam(state)) { + rf_agc = state->m_qam_rf_agc_cfg; + if_agc = state->m_qam_if_agc_cfg; } else { - rfAgc = state->m_atvRfAgcCfg; - ifAgc = state->m_atvIfAgcCfg; + rf_agc = state->m_atv_rf_agc_cfg; + if_agc = state->m_atv_if_agc_cfg; } - if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { - /* SCU outputLevel */ + if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { + /* SCU output_level */ status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); if (status < 0) return status; @@ -6313,54 +6313,54 @@ static int get_strength(struct drxk_state *state, u64 *strength) return status; if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) - rfAgc.outputLevel = scu_lvl + scu_coc; + rf_agc.output_level = scu_lvl + scu_coc; else - rfAgc.outputLevel = 0xffff; + rf_agc.output_level = 0xffff; /* Take RF gain into account */ - totalGain += tunerRfGain; + total_gain += tuner_rf_gain; /* clip output value */ - if (rfAgc.outputLevel < rfAgc.minOutputLevel) - rfAgc.outputLevel = rfAgc.minOutputLevel; - if (rfAgc.outputLevel > rfAgc.maxOutputLevel) - rfAgc.outputLevel = rfAgc.maxOutputLevel; + if (rf_agc.output_level < rf_agc.min_output_level) + rf_agc.output_level = rf_agc.min_output_level; + if (rf_agc.output_level > rf_agc.max_output_level) + rf_agc.output_level = rf_agc.max_output_level; - agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel); - if (agcRange > 0) { + agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level); + if (agc_range > 0) { atten += 100UL * - ((u32)(tunerRfGain)) * - ((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel)) - / agcRange; + ((u32)(tuner_rf_gain)) * + ((u32)(rf_agc.output_level - rf_agc.min_output_level)) + / agc_range; } } - if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { + if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, - &ifAgc.outputLevel); + &if_agc.output_level); if (status < 0) return status; status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, - &ifAgc.top); + &if_agc.top); if (status < 0) return status; /* Take IF gain into account */ - totalGain += (u32) tunerIfGain; + total_gain += (u32) tuner_if_gain; /* clip output value */ - if (ifAgc.outputLevel < ifAgc.minOutputLevel) - ifAgc.outputLevel = ifAgc.minOutputLevel; - if (ifAgc.outputLevel > ifAgc.maxOutputLevel) - ifAgc.outputLevel = ifAgc.maxOutputLevel; + if (if_agc.output_level < if_agc.min_output_level) + if_agc.output_level = if_agc.min_output_level; + if (if_agc.output_level > if_agc.max_output_level) + if_agc.output_level = if_agc.max_output_level; - agcRange = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel); - if (agcRange > 0) { + agc_range = (u32) (if_agc.max_output_level - if_agc.min_output_level); + if (agc_range > 0) { atten += 100UL * - ((u32)(tunerIfGain)) * - ((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel)) - / agcRange; + ((u32)(tuner_if_gain)) * + ((u32)(if_agc.output_level - if_agc.min_output_level)) + / agc_range; } } @@ -6368,8 +6368,8 @@ static int get_strength(struct drxk_state *state, u64 *strength) * Convert to 0..65535 scale. * If it can't be measured (AGC is disabled), just show 100%. */ - if (totalGain > 0) - *strength = (65535UL * atten / totalGain / 100); + if (total_gain > 0) + *strength = (65535UL * atten / total_gain / 100); else *strength = 65535; @@ -6392,14 +6392,14 @@ static int drxk_get_stats(struct dvb_frontend *fe) u32 pkt_error_count; s32 cnr; - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; /* get status */ state->fe_status = 0; - GetLockStatus(state, &stat); + get_lock_status(state, &stat); if (stat == MPEG_LOCK) state->fe_status |= 0x1f; if (stat == FEC_LOCK) @@ -6415,7 +6415,7 @@ static int drxk_get_stats(struct dvb_frontend *fe) if (stat >= DEMOD_LOCK) { - GetSignalToNoise(state, &cnr); + get_signal_to_noise(state, &cnr); c->cnr.stat[0].svalue = cnr * 100; c->cnr.stat[0].scale = FE_SCALE_DECIBEL; } else { @@ -6522,9 +6522,9 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; *strength = c->strength.stat[0].uvalue; @@ -6538,12 +6538,12 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; - GetSignalToNoise(state, &snr2); + get_signal_to_noise(state, &snr2); /* No negative SNR, clip to zero */ if (snr2 < 0) @@ -6559,12 +6559,12 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; - DVBTQAMGetAccPktErr(state, &err); + dvbtqam_get_acc_pkt_err(state, &err); *ucblocks = (u32) err; return 0; } @@ -6577,9 +6577,9 @@ static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_t dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; switch (p->delivery_system) { @@ -6649,36 +6649,36 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->no_i2c_bridge = config->no_i2c_bridge; state->antenna_gpio = config->antenna_gpio; state->antenna_dvbt = config->antenna_dvbt; - state->m_ChunkSize = config->chunk_size; + state->m_chunk_size = config->chunk_size; state->enable_merr_cfg = config->enable_merr_cfg; if (config->dynamic_clk) { - state->m_DVBTStaticCLK = 0; - state->m_DVBCStaticCLK = 0; + state->m_dvbt_static_clk = 0; + state->m_dvbc_static_clk = 0; } else { - state->m_DVBTStaticCLK = 1; - state->m_DVBCStaticCLK = 1; + state->m_dvbt_static_clk = 1; + state->m_dvbc_static_clk = 1; } if (config->mpeg_out_clk_strength) - state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; + state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07; else - state->m_TSClockkStrength = 0x06; + state->m_ts_clockk_strength = 0x06; if (config->parallel_ts) - state->m_enableParallel = true; + state->m_enable_parallel = true; else - state->m_enableParallel = false; + state->m_enable_parallel = false; /* NOTE: as more UIO bits will be used, add them to the mask */ - state->UIO_mask = config->antenna_gpio; + state->uio_mask = config->antenna_gpio; /* Default gpio to DVB-C */ if (!state->antenna_dvbt && state->antenna_gpio) - state->m_GPIO |= state->antenna_gpio; + state->m_gpio |= state->antenna_gpio; else - state->m_GPIO &= ~state->antenna_gpio; + state->m_gpio &= ~state->antenna_gpio; mutex_init(&state->mutex); diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index b8424f15f9a6..db87a6d75720 100644 --- a/drivers/media/dvb-frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h @@ -46,7 +46,7 @@ #define IQM_RC_ADJ_SEL_B_QAM 0x1 #define IQM_RC_ADJ_SEL_B_VSB 0x2 -enum OperationMode { +enum operation_mode { OM_NONE, OM_QAM_ITU_A, OM_QAM_ITU_B, @@ -54,7 +54,7 @@ enum OperationMode { OM_DVBT }; -enum DRXPowerMode { +enum drx_power_mode { DRX_POWER_UP = 0, DRX_POWER_MODE_1, DRX_POWER_MODE_2, @@ -93,8 +93,8 @@ enum DRXPowerMode { #endif -enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; -enum EDrxkState { +enum agc_ctrl_mode { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; +enum e_drxk_state { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, @@ -103,7 +103,7 @@ enum EDrxkState { DRXK_NO_DEV /* If drxk init failed */ }; -enum EDrxkCoefArrayIndex { +enum e_drxk_coef_array_index { DRXK_COEF_IDX_MN = 0, DRXK_COEF_IDX_FM , DRXK_COEF_IDX_L , @@ -113,13 +113,13 @@ enum EDrxkCoefArrayIndex { DRXK_COEF_IDX_I , DRXK_COEF_IDX_MAX }; -enum EDrxkSifAttenuation { +enum e_drxk_sif_attenuation { DRXK_SIF_ATTENUATION_0DB, DRXK_SIF_ATTENUATION_3DB, DRXK_SIF_ATTENUATION_6DB, DRXK_SIF_ATTENUATION_9DB }; -enum EDrxkConstellation { +enum e_drxk_constellation { DRX_CONSTELLATION_BPSK = 0, DRX_CONSTELLATION_QPSK, DRX_CONSTELLATION_PSK8, @@ -133,7 +133,7 @@ enum EDrxkConstellation { DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, DRX_CONSTELLATION_AUTO = DRX_AUTO }; -enum EDrxkInterleaveMode { +enum e_drxk_interleave_mode { DRXK_QAM_I12_J17 = 16, DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN }; @@ -144,14 +144,14 @@ enum { DRXK_SPIN_UNKNOWN }; -enum DRXKCfgDvbtSqiSpeed { +enum drxk_cfg_dvbt_sqi_speed { DRXK_DVBT_SQI_SPEED_FAST = 0, DRXK_DVBT_SQI_SPEED_MEDIUM, DRXK_DVBT_SQI_SPEED_SLOW, DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN } ; -enum DRXFftmode_t { +enum drx_fftmode_t { DRX_FFTMODE_2K = 0, DRX_FFTMODE_4K, DRX_FFTMODE_8K, @@ -159,40 +159,40 @@ enum DRXFftmode_t { DRX_FFTMODE_AUTO = DRX_AUTO }; -enum DRXMPEGStrWidth_t { +enum drxmpeg_str_width_t { DRX_MPEG_STR_WIDTH_1, DRX_MPEG_STR_WIDTH_8 }; -enum DRXQamLockRange_t { +enum drx_qam_lock_range_t { DRX_QAM_LOCKRANGE_NORMAL, DRX_QAM_LOCKRANGE_EXTENDED }; -struct DRXKCfgDvbtEchoThres_t { +struct drxk_cfg_dvbt_echo_thres_t { u16 threshold; - enum DRXFftmode_t fftMode; + enum drx_fftmode_t fft_mode; } ; -struct SCfgAgc { - enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */ - u16 outputLevel; /* range dependent on AGC */ - u16 minOutputLevel; /* range dependent on AGC */ - u16 maxOutputLevel; /* range dependent on AGC */ +struct s_cfg_agc { + enum agc_ctrl_mode ctrl_mode; /* off, user, auto */ + u16 output_level; /* range dependent on AGC */ + u16 min_output_level; /* range dependent on AGC */ + u16 max_output_level; /* range dependent on AGC */ u16 speed; /* range dependent on AGC */ u16 top; /* rf-agc take over point */ - u16 cutOffCurrent; /* rf-agc is accelerated if output current + u16 cut_off_current; /* rf-agc is accelerated if output current is below cut-off current */ - u16 IngainTgtMax; - u16 FastClipCtrlDelay; + u16 ingain_tgt_max; + u16 fast_clip_ctrl_delay; }; -struct SCfgPreSaw { +struct s_cfg_pre_saw { u16 reference; /* pre SAW reference value, range 0 .. 31 */ - bool usePreSaw; /* TRUE algorithms must use pre SAW sense */ + bool use_pre_saw; /* TRUE algorithms must use pre SAW sense */ }; -struct DRXKOfdmScCmd_t { +struct drxk_ofdm_sc_cmd_t { u16 cmd; /**< Command number */ u16 subcmd; /**< Sub-command parameter*/ u16 param0; /**< General purpous param */ @@ -213,121 +213,121 @@ struct drxk_state { struct mutex mutex; - u32 m_Instance; /**< Channel 1,2,3 or 4 */ - - int m_ChunkSize; - u8 Chunk[256]; - - bool m_hasLNA; - bool m_hasDVBT; - bool m_hasDVBC; - bool m_hasAudio; - bool m_hasATV; - bool m_hasOOB; - bool m_hasSAWSW; /**< TRUE if mat_tx is available */ - bool m_hasGPIO1; /**< TRUE if mat_rx is available */ - bool m_hasGPIO2; /**< TRUE if GPIO is available */ - bool m_hasIRQN; /**< TRUE if IRQN is available */ - u16 m_oscClockFreq; - u16 m_HICfgTimingDiv; - u16 m_HICfgBridgeDelay; - u16 m_HICfgWakeUpKey; - u16 m_HICfgTimeout; - u16 m_HICfgCtrl; - s32 m_sysClockFreq; /**< system clock frequency in kHz */ - - enum EDrxkState m_DrxkState; /**< State of Drxk (init,stopped,started) */ - enum OperationMode m_OperationMode; /**< digital standards */ - struct SCfgAgc m_vsbRfAgcCfg; /**< settings for VSB RF-AGC */ - struct SCfgAgc m_vsbIfAgcCfg; /**< settings for VSB IF-AGC */ - u16 m_vsbPgaCfg; /**< settings for VSB PGA */ - struct SCfgPreSaw m_vsbPreSawCfg; /**< settings for pre SAW sense */ + u32 m_instance; /**< Channel 1,2,3 or 4 */ + + int m_chunk_size; + u8 chunk[256]; + + bool m_has_lna; + bool m_has_dvbt; + bool m_has_dvbc; + bool m_has_audio; + bool m_has_atv; + bool m_has_oob; + bool m_has_sawsw; /* TRUE if mat_tx is available */ + bool m_has_gpio1; /* TRUE if mat_rx is available */ + bool m_has_gpio2; /* TRUE if GPIO is available */ + bool m_has_irqn; /* TRUE if IRQN is available */ + u16 m_osc_clock_freq; + u16 m_hi_cfg_timing_div; + u16 m_hi_cfg_bridge_delay; + u16 m_hi_cfg_wake_up_key; + u16 m_hi_cfg_timeout; + u16 m_hi_cfg_ctrl; + s32 m_sys_clock_freq; /**< system clock frequency in kHz */ + + enum e_drxk_state m_drxk_state; /**< State of Drxk (init,stopped,started) */ + enum operation_mode m_operation_mode; /**< digital standards */ + struct s_cfg_agc m_vsb_rf_agc_cfg; /**< settings for VSB RF-AGC */ + struct s_cfg_agc m_vsb_if_agc_cfg; /**< settings for VSB IF-AGC */ + u16 m_vsb_pga_cfg; /**< settings for VSB PGA */ + struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /**< settings for pre SAW sense */ s32 m_Quality83percent; /**< MER level (*0.1 dB) for 83% quality indication */ s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ - bool m_smartAntInverted; - bool m_bDebugEnableBridge; - bool m_bPDownOpenBridge; /**< only open DRXK bridge before power-down once it has been accessed */ - bool m_bPowerDown; /**< Power down when not used */ - - u32 m_IqmFsRateOfs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ - - bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */ - bool m_insertRSByte; /**< If TRUE, insert RS byte */ - bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */ - bool m_invertDATA; /**< If TRUE, invert DATA signals */ - bool m_invertERR; /**< If TRUE, invert ERR signal */ - bool m_invertSTR; /**< If TRUE, invert STR signals */ - bool m_invertVAL; /**< If TRUE, invert VAL signals */ - bool m_invertCLK; /**< If TRUE, invert CLK signals */ - bool m_DVBCStaticCLK; - bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will + bool m_smart_ant_inverted; + bool m_b_debug_enable_bridge; + bool m_b_p_down_open_bridge; /**< only open DRXK bridge before power-down once it has been accessed */ + bool m_b_power_down; /**< Power down when not used */ + + u32 m_iqm_fs_rate_ofs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ + + bool m_enable_mpeg_output; /**< If TRUE, enable MPEG output */ + bool m_insert_rs_byte; /**< If TRUE, insert RS byte */ + bool m_enable_parallel; /**< If TRUE, parallel out otherwise serial */ + bool m_invert_data; /**< If TRUE, invert DATA signals */ + bool m_invert_err; /**< If TRUE, invert ERR signal */ + bool m_invert_str; /**< If TRUE, invert STR signals */ + bool m_invert_val; /**< If TRUE, invert VAL signals */ + bool m_invert_clk; /**< If TRUE, invert CLK signals */ + bool m_dvbc_static_clk; + bool m_dvbt_static_clk; /**< If TRUE, static MPEG clockrate will be used, otherwise clockrate will adapt to the bitrate of the TS */ - u32 m_DVBTBitrate; - u32 m_DVBCBitrate; + u32 m_dvbt_bitrate; + u32 m_dvbc_bitrate; - u8 m_TSDataStrength; - u8 m_TSClockkStrength; + u8 m_ts_data_strength; + u8 m_ts_clockk_strength; bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ - enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width */ - u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case + enum drxmpeg_str_width_t m_width_str; /**< MPEG start width */ + u32 m_mpeg_ts_static_bitrate; /**< Maximum bitrate in b/s in case static clockrate is selected */ - /* LARGE_INTEGER m_StartTime; */ /**< Contains the time of the last demod start */ - s32 m_MpegLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ - s32 m_DemodLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ - - bool m_disableTEIhandling; - - bool m_RfAgcPol; - bool m_IfAgcPol; - - struct SCfgAgc m_atvRfAgcCfg; /**< settings for ATV RF-AGC */ - struct SCfgAgc m_atvIfAgcCfg; /**< settings for ATV IF-AGC */ - struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */ - bool m_phaseCorrectionBypass; - s16 m_atvTopVidPeak; - u16 m_atvTopNoiseTh; - enum EDrxkSifAttenuation m_sifAttenuation; - bool m_enableCVBSOutput; - bool m_enableSIFOutput; - bool m_bMirrorFreqSpect; - enum EDrxkConstellation m_Constellation; /**< Constellation type of the channel */ - u32 m_CurrSymbolRate; /**< Current QAM symbol rate */ - struct SCfgAgc m_qamRfAgcCfg; /**< settings for QAM RF-AGC */ - struct SCfgAgc m_qamIfAgcCfg; /**< settings for QAM IF-AGC */ - u16 m_qamPgaCfg; /**< settings for QAM PGA */ - struct SCfgPreSaw m_qamPreSawCfg; /**< settings for QAM pre SAW sense */ - enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */ - u16 m_fecRsPlen; - u16 m_fecRsPrescale; - - enum DRXKCfgDvbtSqiSpeed m_sqiSpeed; - - u16 m_GPIO; - u16 m_GPIOCfg; - - struct SCfgAgc m_dvbtRfAgcCfg; /**< settings for QAM RF-AGC */ - struct SCfgAgc m_dvbtIfAgcCfg; /**< settings for QAM IF-AGC */ - struct SCfgPreSaw m_dvbtPreSawCfg; /**< settings for QAM pre SAW sense */ - - u16 m_agcFastClipCtrlDelay; - bool m_adcCompPassed; + /* LARGE_INTEGER m_startTime; */ /**< Contains the time of the last demod start */ + s32 m_mpeg_lock_time_out; /**< WaitForLockStatus Timeout (counts from start time) */ + s32 m_demod_lock_time_out; /**< WaitForLockStatus Timeout (counts from start time) */ + + bool m_disable_te_ihandling; + + bool m_rf_agc_pol; + bool m_if_agc_pol; + + struct s_cfg_agc m_atv_rf_agc_cfg; /**< settings for ATV RF-AGC */ + struct s_cfg_agc m_atv_if_agc_cfg; /**< settings for ATV IF-AGC */ + struct s_cfg_pre_saw m_atv_pre_saw_cfg; /**< settings for ATV pre SAW sense */ + bool m_phase_correction_bypass; + s16 m_atv_top_vid_peak; + u16 m_atv_top_noise_th; + enum e_drxk_sif_attenuation m_sif_attenuation; + bool m_enable_cvbs_output; + bool m_enable_sif_output; + bool m_b_mirror_freq_spect; + enum e_drxk_constellation m_constellation; /**< constellation type of the channel */ + u32 m_curr_symbol_rate; /**< Current QAM symbol rate */ + struct s_cfg_agc m_qam_rf_agc_cfg; /**< settings for QAM RF-AGC */ + struct s_cfg_agc m_qam_if_agc_cfg; /**< settings for QAM IF-AGC */ + u16 m_qam_pga_cfg; /**< settings for QAM PGA */ + struct s_cfg_pre_saw m_qam_pre_saw_cfg; /**< settings for QAM pre SAW sense */ + enum e_drxk_interleave_mode m_qam_interleave_mode; /**< QAM Interleave mode */ + u16 m_fec_rs_plen; + u16 m_fec_rs_prescale; + + enum drxk_cfg_dvbt_sqi_speed m_sqi_speed; + + u16 m_gpio; + u16 m_gpio_cfg; + + struct s_cfg_agc m_dvbt_rf_agc_cfg; /**< settings for QAM RF-AGC */ + struct s_cfg_agc m_dvbt_if_agc_cfg; /**< settings for QAM IF-AGC */ + struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /**< settings for QAM pre SAW sense */ + + u16 m_agcfast_clip_ctrl_delay; + bool m_adc_comp_passed; u16 m_adcCompCoef[64]; - u16 m_adcState; + u16 m_adc_state; u8 *m_microcode; int m_microcode_length; - bool m_DRXK_A3_ROM_CODE; - bool m_DRXK_A3_PATCH_CODE; + bool m_drxk_a3_rom_code; + bool m_drxk_a3_patch_code; bool m_rfmirror; - u8 m_deviceSpin; - u32 m_iqmRcRate; + u8 m_device_spin; + u32 m_iqm_rc_rate; - enum DRXPowerMode m_currentPowerMode; + enum drx_power_mode m_current_power_mode; /* when true, avoids other devices to use the I2C bus */ bool drxk_i2c_exclusive_lock; @@ -337,7 +337,7 @@ struct drxk_state { * at struct drxk_config. */ - u16 UIO_mask; /* Bits used by UIO */ + u16 uio_mask; /* Bits used by UIO */ bool enable_merr_cfg; bool single_master; -- GitLab From 3a4398f58c0a7b70b7debe36fd95cf37e9b2c0a1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:45 -0300 Subject: [PATCH 0796/2900] [media] drxk_hard: use pr_info/pr_warn/pr_err/... macros X-Patchwork-Delegate: mchehab@redhat.com replace all occurrences of printk(KERN_* by pr_info/pr_warn/pr_err/pr_debug/pr_cont macros. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 182 ++++++++++++------------ 1 file changed, 89 insertions(+), 93 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index d2b331a46a6d..552bce5d8f92 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -21,6 +21,8 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -264,7 +266,7 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) status = -EIO; if (status < 0) - printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr); + pr_err("i2c write error at addr 0x%02x\n", adr); return status; } @@ -287,7 +289,7 @@ static int i2c_read(struct drxk_state *state, if (status >= 0) status = -EIO; - printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr); + pr_err("i2c read error at addr 0x%02x\n", adr); return status; } if (debug > 2) { @@ -474,7 +476,7 @@ static int write_block(struct drxk_state *state, u32 address, status = i2c_write(state, state->demod_address, &state->chunk[0], chunk + adr_length); if (status < 0) { - printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", + pr_err("%s: i2c write error at addr 0x%02x\n", __func__, address); break; } @@ -531,7 +533,7 @@ static int power_up_device(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -800,7 +802,7 @@ static int drxx_open(struct drxk_state *state) status = write16(state, SIO_TOP_COMM_KEY__A, key); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -845,7 +847,7 @@ static int get_device_capabilities(struct drxk_state *state) state->m_osc_clock_freq = 20250; break; default: - printk(KERN_ERR "drxk: Clock Frequency is unknown\n"); + pr_err("Clock Frequency is unknown\n"); return -EINVAL; } /* @@ -856,7 +858,7 @@ static int get_device_capabilities(struct drxk_state *state) if (status < 0) goto error; - printk(KERN_INFO "drxk: status = 0x%08x\n", sio_top_jtagid_lo); + pr_info("status = 0x%08x\n", sio_top_jtagid_lo); /* driver 0.9.0 */ switch ((sio_top_jtagid_lo >> 29) & 0xF) { @@ -875,8 +877,7 @@ static int get_device_capabilities(struct drxk_state *state) default: state->m_device_spin = DRXK_SPIN_UNKNOWN; status = -EINVAL; - printk(KERN_ERR "drxk: Spin %d unknown\n", - (sio_top_jtagid_lo >> 29) & 0xF); + pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF); goto error2; } switch ((sio_top_jtagid_lo >> 12) & 0xFF) { @@ -985,21 +986,20 @@ static int get_device_capabilities(struct drxk_state *state) state->m_has_irqn = false; break; default: - printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n", + pr_err("DeviceID 0x%02x not supported\n", ((sio_top_jtagid_lo >> 12) & 0xFF)); status = -EINVAL; goto error2; } - printk(KERN_INFO - "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", + pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", ((sio_top_jtagid_lo >> 12) & 0xFF), spin, state->m_osc_clock_freq / 1000, state->m_osc_clock_freq % 1000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: return status; @@ -1042,7 +1042,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1081,7 +1081,7 @@ static int hi_cfg_command(struct drxk_state *state) error: mutex_unlock(&state->mutex); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1244,7 +1244,7 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1287,13 +1287,13 @@ static int bl_chain_cmd(struct drxk_state *state, ((time_is_after_jiffies(end)))); if (bl_status == 0x1) { - printk(KERN_ERR "drxk: SIO not ready\n"); + pr_err("SIO not ready\n"); status = -EINVAL; goto error2; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; @@ -1349,13 +1349,13 @@ static int download_microcode(struct drxk_state *state, offset += sizeof(u16); if (offset + block_size > length) { - printk(KERN_ERR "drxk: Firmware is corrupted.\n"); + pr_err("Firmware is corrupted.\n"); return -EINVAL; } status = write_block(state, address, block_size, p_src); if (status < 0) { - printk(KERN_ERR "drxk: Error %d while loading firmware\n", status); + pr_err("Error %d while loading firmware\n", status); break; } p_src += block_size; @@ -1395,7 +1395,7 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) msleep(1); } while (1); if (data != desired_status) { - printk(KERN_ERR "drxk: SIO not ready\n"); + pr_err("SIO not ready\n"); return -EINVAL; } return status; @@ -1427,7 +1427,7 @@ static int mpegts_stop(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1451,7 +1451,7 @@ static int scu_command(struct drxk_state *state, if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) || ((result_len > 0) && (result == NULL))) { - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1477,7 +1477,7 @@ static int scu_command(struct drxk_state *state, goto error; } while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); if (cur_cmd != DRX_SCU_READY) { - printk(KERN_ERR "drxk: SCU not ready\n"); + pr_err("SCU not ready\n"); status = -EIO; goto error2; } @@ -1515,7 +1515,7 @@ static int scu_command(struct drxk_state *state, sprintf(errname, "ERROR: %d\n", err); p = errname; } - printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd); + pr_err("%s while sending cmd 0x%04x with params:", p, cmd); print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt); status = -EINVAL; goto error2; @@ -1523,7 +1523,7 @@ static int scu_command(struct drxk_state *state, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; @@ -1559,7 +1559,7 @@ static int set_iqm_af(struct drxk_state *state, bool active) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1664,7 +1664,7 @@ static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1716,7 +1716,7 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1796,7 +1796,7 @@ static int setoperation_mode(struct drxk_state *state, } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1847,7 +1847,7 @@ static int start(struct drxk_state *state, s32 offset_freq, } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1885,7 +1885,7 @@ static int get_lock_status(struct drxk_state *state, u32 *p_lock_status) } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1906,7 +1906,7 @@ static int mpegts_start(struct drxk_state *state) status = write16(state, FEC_OC_SNC_UNLOCK__A, 1); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1952,7 +1952,7 @@ static int mpegts_dto_init(struct drxk_state *state) status = write16(state, FEC_OC_SNC_HWM__A, 12); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2089,7 +2089,7 @@ static int mpegts_dto_setup(struct drxk_state *state, status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2269,7 +2269,7 @@ static int set_agc_rf(struct drxk_state *state, } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2397,7 +2397,7 @@ static int set_agc_if(struct drxk_state *state, status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2418,7 +2418,7 @@ static int get_qam_signal_to_noise(struct drxk_state *state, /* get the register value needed for MER */ status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); if (status < 0) { - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return -EINVAL; } @@ -2545,7 +2545,7 @@ static int get_dvbt_signal_to_noise(struct drxk_state *state, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2740,7 +2740,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2758,7 +2758,7 @@ static int set_pre_saw(struct drxk_state *state, status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2800,13 +2800,13 @@ static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, goto error; } while ((bl_status == 0x1) && time_is_after_jiffies(end)); if (bl_status == 0x1) { - printk(KERN_ERR "drxk: SIO not ready\n"); + pr_err("SIO not ready\n"); status = -EINVAL; goto error2; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; @@ -2847,7 +2847,7 @@ static int adc_sync_measurement(struct drxk_state *state, u16 *count) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2891,7 +2891,7 @@ static int adc_synchronization(struct drxk_state *state) status = -EINVAL; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2957,7 +2957,7 @@ static int set_frequency_shifter(struct drxk_state *state, status = write32(state, IQM_FS_RATE_OFS_LO__A, state->m_iqm_fs_rate_ofs); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -2992,7 +2992,8 @@ static int init_agc(struct drxk_state *state, bool is_dtv) /* AGCInit() not available for DVBT; init done in microcode */ if (!is_qam(state)) { - printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_operation_mode); + pr_err("%s: mode %d is not DVB-C\n", + __func__, state->m_operation_mode); return -EINVAL; } @@ -3145,7 +3146,7 @@ static int init_agc(struct drxk_state *state, bool is_dtv) status = write16(state, SCU_RAM_AGC_KI__A, data); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3159,7 +3160,7 @@ static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) else status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packet_err); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3279,7 +3280,7 @@ static int dvbt_sc_command(struct drxk_state *state, } /* switch (cmd->cmd) */ error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3291,7 +3292,7 @@ static int power_up_dvbt(struct drxk_state *state) dprintk(1, "\n"); status = ctrl_power_mode(state, &power_mode); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3305,7 +3306,7 @@ static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) else status = write16(state, IQM_CF_BYPASSDET__A, 1); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3325,7 +3326,7 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3361,7 +3362,7 @@ static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3384,7 +3385,7 @@ static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, (u16) *speed); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3423,7 +3424,7 @@ static int dvbt_activate_presets(struct drxk_state *state) status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbt_if_agc_cfg.ingain_tgt_max); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3629,7 +3630,7 @@ static int set_dvbt_standard(struct drxk_state *state, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3661,7 +3662,7 @@ static int dvbt_start(struct drxk_state *state) goto error; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3980,7 +3981,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4031,7 +4032,7 @@ static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) *p_lock_status = NEVER_LOCK; end: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4044,7 +4045,7 @@ static int power_up_qam(struct drxk_state *state) dprintk(1, "\n"); status = ctrl_power_mode(state, &power_mode); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4079,7 +4080,7 @@ static int power_down_qam(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4167,7 +4168,7 @@ static int set_qam_measurement(struct drxk_state *state, status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4353,7 +4354,7 @@ static int set_qam16(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4548,7 +4549,7 @@ static int set_qam32(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4741,7 +4742,7 @@ static int set_qam64(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4937,7 +4938,7 @@ static int set_qam128(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5132,7 +5133,7 @@ static int set_qam256(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5158,7 +5159,7 @@ static int qam_reset_qam(struct drxk_state *state) status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5228,7 +5229,7 @@ static int qam_set_symbolrate(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5253,7 +5254,7 @@ static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, result); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { /* 0x0000 NOT LOCKED */ @@ -5324,15 +5325,14 @@ static int qam_demodulator_command(struct drxk_state *state, number_of_parameters, set_param_parameters, 1, &cmd_result); } else { - printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter " - "count %d\n", number_of_parameters); + pr_warn("Unknown QAM demodulator parameter count %d\n", + number_of_parameters); status = -EINVAL; } error: if (status < 0) - printk(KERN_WARNING "drxk: Warning %d on %s\n", - status, __func__); + pr_warn("Warning %d on %s\n", status, __func__); return status; } @@ -5587,7 +5587,7 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5749,7 +5749,7 @@ static int set_qam_standard(struct drxk_state *state, status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5832,7 +5832,7 @@ static int write_gpio(struct drxk_state *state) status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5857,7 +5857,7 @@ static int switch_antenna_to_qam(struct drxk_state *state) status = write_gpio(state); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5882,7 +5882,7 @@ static int switch_antenna_to_dvbt(struct drxk_state *state) status = write_gpio(state); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5919,7 +5919,7 @@ static int power_down_device(struct drxk_state *state) status = hi_cfg_command(state); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -6060,7 +6060,7 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; - printk(KERN_INFO "DRXK driver version %d.%d.%d\n", + pr_info("DRXK driver version %d.%d.%d\n", DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR, DRXK_VERSION_PATCH); @@ -6128,7 +6128,7 @@ static int init_drxk(struct drxk_state *state) if (status < 0) { state->m_drxk_state = DRXK_NO_DEV; drxk_i2c_unlock(state); - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); } return status; @@ -6141,11 +6141,9 @@ static void load_firmware_cb(const struct firmware *fw, dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded"); if (!fw) { - printk(KERN_ERR - "drxk: Could not load firmware file %s.\n", + pr_err("Could not load firmware file %s.\n", state->microcode_name); - printk(KERN_INFO - "drxk: Copy %s to your hotplug directory!\n", + pr_info("Copy %s to your hotplug directory!\n", state->microcode_name); state->microcode_name = NULL; @@ -6219,8 +6217,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe) return -EAGAIN; if (!fe->ops.tuner_ops.get_if_frequency) { - printk(KERN_ERR - "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); + pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); return -EINVAL; } @@ -6704,8 +6701,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, GFP_KERNEL, state, load_firmware_cb); if (status < 0) { - printk(KERN_ERR - "drxk: failed to request a firmware\n"); + pr_err("failed to request a firmware\n"); return NULL; } } @@ -6733,11 +6729,11 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - printk(KERN_INFO "drxk: frontend initialized.\n"); + pr_info("frontend initialized.\n"); return &state->frontend; error: - printk(KERN_ERR "drxk: not found\n"); + pr_err("not found\n"); kfree(state); return NULL; } -- GitLab From 0fb220f2a5cb85365d1ecf11e931d57109955782 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:46 -0300 Subject: [PATCH 0797/2900] [media] drxk_hard: don't split strings across lines X-Patchwork-Delegate: mchehab@redhat.com WARNING: quoted string split across lines #5416: FILE: media/dvb-frontends/drxk_hard.c:5416: + dprintk(1, "Could not set demodulator parameters. Make " + "sure qam_demod_parameter_count (%d) is correct for " WARNING: quoted string split across lines #5423: FILE: media/dvb-frontends/drxk_hard.c:5423: + dprintk(1, "Auto-probing the correct QAM demodulator command " + "parameters was successful - using %d parameters.\n", Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 552bce5d8f92..fdbe23a00478 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -168,7 +168,7 @@ MODULE_PARM_DESC(debug, "enable debug messages"); #define dprintk(level, fmt, arg...) do { \ if (debug >= level) \ - printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg); \ + pr_debug(fmt, ##arg); \ } while (0) @@ -258,8 +258,8 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) if (debug > 2) { int i; for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", data[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02x", data[i]); + pr_cont("\n"); } status = drxk_i2c_transfer(state, &msg, 1); if (status >= 0 && status != 1) @@ -285,7 +285,7 @@ static int i2c_read(struct drxk_state *state, status = drxk_i2c_transfer(state, msgs, 2); if (status != 2) { if (debug > 2) - printk(KERN_CONT ": ERROR!\n"); + pr_cont(": ERROR!\n"); if (status >= 0) status = -EIO; @@ -296,11 +296,11 @@ static int i2c_read(struct drxk_state *state, int i; dprintk(2, ": read from"); for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", msg[i]); - printk(KERN_CONT ", value = "); + pr_cont(" %02x", msg[i]); + pr_cont(", value = "); for (i = 0; i < alen; i++) - printk(KERN_CONT " %02x", answ[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02x", answ[i]); + pr_cont("\n"); } return 0; } @@ -470,8 +470,8 @@ static int write_block(struct drxk_state *state, u32 address, int i; if (p_block) for (i = 0; i < chunk; i++) - printk(KERN_CONT " %02x", p_block[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02x", p_block[i]); + pr_cont("\n"); } status = i2c_write(state, state->demod_address, &state->chunk[0], chunk + adr_length); @@ -5412,15 +5412,15 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, } if (status < 0) { - dprintk(1, "Could not set demodulator parameters. Make " - "sure qam_demod_parameter_count (%d) is correct for " - "your firmware (%s).\n", + dprintk(1, "Could not set demodulator parameters.\n"); + dprintk(1, + "Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n", state->qam_demod_parameter_count, state->microcode_name); goto error; } else if (!state->qam_demod_parameter_count) { - dprintk(1, "Auto-probing the correct QAM demodulator command " - "parameters was successful - using %d parameters.\n", + dprintk(1, + "Auto-probing the QAM command parameters was successful - using %d parameters.\n", qam_demod_param_count); /* -- GitLab From b72852baa0776f6ed416d54cd94b7804f0587f81 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:47 -0300 Subject: [PATCH 0798/2900] [media] drxk_hard: use usleep_range() X-Patchwork-Delegate: mchehab@redhat.com Fixes the following checkpatch.pl warnings: WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(10); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); WARNING: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt + msleep(1); Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index fdbe23a00478..1fd74f2ed3e2 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -505,7 +505,7 @@ static int power_up_device(struct drxk_state *state) data = 0; status = i2c_write(state, state->demod_address, &data, 1); - msleep(10); + usleep_range(10000, 11000); retry_count++; if (status < 0) continue; @@ -1017,7 +1017,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) if (status < 0) goto error; if (cmd == SIO_HI_RA_RAM_CMD_RESET) - msleep(1); + usleep_range(1000, 2000); powerdown_cmd = (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) && @@ -1030,7 +1030,7 @@ static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) u16 wait_cmd; do { - msleep(1); + usleep_range(1000, 2000); retry_count += 1; status = read16(state, SIO_HI_RA_RAM_CMD__A, &wait_cmd); @@ -1279,7 +1279,7 @@ static int bl_chain_cmd(struct drxk_state *state, end = jiffies + msecs_to_jiffies(time_out); do { - msleep(1); + usleep_range(1000, 2000); status = read16(state, SIO_BL_STATUS__A, &bl_status); if (status < 0) goto error; @@ -1392,7 +1392,7 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); if ((status >= 0 && data == desired_status) || time_is_after_jiffies(end)) break; - msleep(1); + usleep_range(1000, 2000); } while (1); if (data != desired_status) { pr_err("SIO not ready\n"); @@ -1471,7 +1471,7 @@ static int scu_command(struct drxk_state *state, /* Wait until SCU has processed command */ end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); do { - msleep(1); + usleep_range(1000, 2000); status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); if (status < 0) goto error; @@ -3187,7 +3187,7 @@ static int dvbt_sc_command(struct drxk_state *state, /* Wait until sc is ready to receive command */ retry_cnt = 0; do { - msleep(1); + usleep_range(1000, 2000); status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); retry_cnt++; } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); @@ -3239,7 +3239,7 @@ static int dvbt_sc_command(struct drxk_state *state, /* Wait until sc is ready processing command */ retry_cnt = 0; do { - msleep(1); + usleep_range(1000, 2000); status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); retry_cnt++; } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); @@ -5947,7 +5947,7 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; /* TODO is this needed, if yes how much delay in worst case scenario */ - msleep(1); + usleep_range(1000, 2000); state->m_drxk_a3_patch_code = true; status = get_device_capabilities(state); if (status < 0) -- GitLab From 57b8b0035725db6b1a4f7bb815b3dc244942b04d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:48 -0300 Subject: [PATCH 0799/2900] [media] drxk_hard.h: Remove some alien comment markups X-Patchwork-Delegate: mchehab@redhat.com The comments markup language used on Kernel is defined at: Documentation/kernel-doc-nano-HOWTO.txt Remove invalid markups from the header file. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.h | 106 ++++++++++++------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index db87a6d75720..e77d9f098c93 100644 --- a/drivers/media/dvb-frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h @@ -77,17 +77,17 @@ enum drx_power_mode { }; -/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */ +/* Intermediate power mode for DRXK, power down OFDM clock domain */ #ifndef DRXK_POWER_DOWN_OFDM #define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1 #endif -/** /brief Intermediate power mode for DRXK, power down core (sysclk) */ +/* Intermediate power mode for DRXK, power down core (sysclk) */ #ifndef DRXK_POWER_DOWN_CORE #define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9 #endif -/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */ +/* Intermediate power mode for DRXK, power down pll (only osc runs) */ #ifndef DRXK_POWER_DOWN_PLL #define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10 #endif @@ -193,13 +193,13 @@ struct s_cfg_pre_saw { }; struct drxk_ofdm_sc_cmd_t { - u16 cmd; /**< Command number */ - u16 subcmd; /**< Sub-command parameter*/ - u16 param0; /**< General purpous param */ - u16 param1; /**< General purpous param */ - u16 param2; /**< General purpous param */ - u16 param3; /**< General purpous param */ - u16 param4; /**< General purpous param */ + u16 cmd; /* Command number */ + u16 subcmd; /* Sub-command parameter*/ + u16 param0; /* General purpous param */ + u16 param1; /* General purpous param */ + u16 param2; /* General purpous param */ + u16 param3; /* General purpous param */ + u16 param4; /* General purpous param */ }; struct drxk_state { @@ -213,7 +213,7 @@ struct drxk_state { struct mutex mutex; - u32 m_instance; /**< Channel 1,2,3 or 4 */ + u32 m_instance; /* Channel 1,2,3 or 4 */ int m_chunk_size; u8 chunk[256]; @@ -234,33 +234,33 @@ struct drxk_state { u16 m_hi_cfg_wake_up_key; u16 m_hi_cfg_timeout; u16 m_hi_cfg_ctrl; - s32 m_sys_clock_freq; /**< system clock frequency in kHz */ - - enum e_drxk_state m_drxk_state; /**< State of Drxk (init,stopped,started) */ - enum operation_mode m_operation_mode; /**< digital standards */ - struct s_cfg_agc m_vsb_rf_agc_cfg; /**< settings for VSB RF-AGC */ - struct s_cfg_agc m_vsb_if_agc_cfg; /**< settings for VSB IF-AGC */ - u16 m_vsb_pga_cfg; /**< settings for VSB PGA */ - struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /**< settings for pre SAW sense */ - s32 m_Quality83percent; /**< MER level (*0.1 dB) for 83% quality indication */ - s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ + s32 m_sys_clock_freq; /* system clock frequency in kHz */ + + enum e_drxk_state m_drxk_state; /* State of Drxk (init,stopped,started) */ + enum operation_mode m_operation_mode; /* digital standards */ + struct s_cfg_agc m_vsb_rf_agc_cfg; /* settings for VSB RF-AGC */ + struct s_cfg_agc m_vsb_if_agc_cfg; /* settings for VSB IF-AGC */ + u16 m_vsb_pga_cfg; /* settings for VSB PGA */ + struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /* settings for pre SAW sense */ + s32 m_Quality83percent; /* MER level (*0.1 dB) for 83% quality indication */ + s32 m_Quality93percent; /* MER level (*0.1 dB) for 93% quality indication */ bool m_smart_ant_inverted; bool m_b_debug_enable_bridge; - bool m_b_p_down_open_bridge; /**< only open DRXK bridge before power-down once it has been accessed */ - bool m_b_power_down; /**< Power down when not used */ - - u32 m_iqm_fs_rate_ofs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ - - bool m_enable_mpeg_output; /**< If TRUE, enable MPEG output */ - bool m_insert_rs_byte; /**< If TRUE, insert RS byte */ - bool m_enable_parallel; /**< If TRUE, parallel out otherwise serial */ - bool m_invert_data; /**< If TRUE, invert DATA signals */ - bool m_invert_err; /**< If TRUE, invert ERR signal */ - bool m_invert_str; /**< If TRUE, invert STR signals */ - bool m_invert_val; /**< If TRUE, invert VAL signals */ - bool m_invert_clk; /**< If TRUE, invert CLK signals */ + bool m_b_p_down_open_bridge; /* only open DRXK bridge before power-down once it has been accessed */ + bool m_b_power_down; /* Power down when not used */ + + u32 m_iqm_fs_rate_ofs; /* frequency shift as written to DRXK register (28bit fixpoint) */ + + bool m_enable_mpeg_output; /* If TRUE, enable MPEG output */ + bool m_insert_rs_byte; /* If TRUE, insert RS byte */ + bool m_enable_parallel; /* If TRUE, parallel out otherwise serial */ + bool m_invert_data; /* If TRUE, invert DATA signals */ + bool m_invert_err; /* If TRUE, invert ERR signal */ + bool m_invert_str; /* If TRUE, invert STR signals */ + bool m_invert_val; /* If TRUE, invert VAL signals */ + bool m_invert_clk; /* If TRUE, invert CLK signals */ bool m_dvbc_static_clk; - bool m_dvbt_static_clk; /**< If TRUE, static MPEG clockrate will + bool m_dvbt_static_clk; /* If TRUE, static MPEG clockrate will be used, otherwise clockrate will adapt to the bitrate of the TS */ u32 m_dvbt_bitrate; @@ -271,22 +271,22 @@ struct drxk_state { bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ - enum drxmpeg_str_width_t m_width_str; /**< MPEG start width */ - u32 m_mpeg_ts_static_bitrate; /**< Maximum bitrate in b/s in case + enum drxmpeg_str_width_t m_width_str; /* MPEG start width */ + u32 m_mpeg_ts_static_bitrate; /* Maximum bitrate in b/s in case static clockrate is selected */ - /* LARGE_INTEGER m_startTime; */ /**< Contains the time of the last demod start */ - s32 m_mpeg_lock_time_out; /**< WaitForLockStatus Timeout (counts from start time) */ - s32 m_demod_lock_time_out; /**< WaitForLockStatus Timeout (counts from start time) */ + /* LARGE_INTEGER m_startTime; */ /* Contains the time of the last demod start */ + s32 m_mpeg_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ + s32 m_demod_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ bool m_disable_te_ihandling; bool m_rf_agc_pol; bool m_if_agc_pol; - struct s_cfg_agc m_atv_rf_agc_cfg; /**< settings for ATV RF-AGC */ - struct s_cfg_agc m_atv_if_agc_cfg; /**< settings for ATV IF-AGC */ - struct s_cfg_pre_saw m_atv_pre_saw_cfg; /**< settings for ATV pre SAW sense */ + struct s_cfg_agc m_atv_rf_agc_cfg; /* settings for ATV RF-AGC */ + struct s_cfg_agc m_atv_if_agc_cfg; /* settings for ATV IF-AGC */ + struct s_cfg_pre_saw m_atv_pre_saw_cfg; /* settings for ATV pre SAW sense */ bool m_phase_correction_bypass; s16 m_atv_top_vid_peak; u16 m_atv_top_noise_th; @@ -294,13 +294,13 @@ struct drxk_state { bool m_enable_cvbs_output; bool m_enable_sif_output; bool m_b_mirror_freq_spect; - enum e_drxk_constellation m_constellation; /**< constellation type of the channel */ - u32 m_curr_symbol_rate; /**< Current QAM symbol rate */ - struct s_cfg_agc m_qam_rf_agc_cfg; /**< settings for QAM RF-AGC */ - struct s_cfg_agc m_qam_if_agc_cfg; /**< settings for QAM IF-AGC */ - u16 m_qam_pga_cfg; /**< settings for QAM PGA */ - struct s_cfg_pre_saw m_qam_pre_saw_cfg; /**< settings for QAM pre SAW sense */ - enum e_drxk_interleave_mode m_qam_interleave_mode; /**< QAM Interleave mode */ + enum e_drxk_constellation m_constellation; /* constellation type of the channel */ + u32 m_curr_symbol_rate; /* Current QAM symbol rate */ + struct s_cfg_agc m_qam_rf_agc_cfg; /* settings for QAM RF-AGC */ + struct s_cfg_agc m_qam_if_agc_cfg; /* settings for QAM IF-AGC */ + u16 m_qam_pga_cfg; /* settings for QAM PGA */ + struct s_cfg_pre_saw m_qam_pre_saw_cfg; /* settings for QAM pre SAW sense */ + enum e_drxk_interleave_mode m_qam_interleave_mode; /* QAM Interleave mode */ u16 m_fec_rs_plen; u16 m_fec_rs_prescale; @@ -309,9 +309,9 @@ struct drxk_state { u16 m_gpio; u16 m_gpio_cfg; - struct s_cfg_agc m_dvbt_rf_agc_cfg; /**< settings for QAM RF-AGC */ - struct s_cfg_agc m_dvbt_if_agc_cfg; /**< settings for QAM IF-AGC */ - struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /**< settings for QAM pre SAW sense */ + struct s_cfg_agc m_dvbt_rf_agc_cfg; /* settings for QAM RF-AGC */ + struct s_cfg_agc m_dvbt_if_agc_cfg; /* settings for QAM IF-AGC */ + struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /* settings for QAM pre SAW sense */ u16 m_agcfast_clip_ctrl_delay; bool m_adc_comp_passed; -- GitLab From d5687ab520d6cf8bf60d8c44932eeb0a1829a75c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:49 -0300 Subject: [PATCH 0800/2900] [media] drxk_hard.h: don't use more than 80 columns X-Patchwork-Delegate: mchehab@redhat.com Almost all 80-col warnings are related to comments. There's one, however, that it is due to a one-line enum declaration for enum agc_ctrl_mode. Break it into one line per enumered data. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index e77d9f098c93..bae9c71dc3e9 100644 --- a/drivers/media/dvb-frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h @@ -93,7 +93,12 @@ enum drx_power_mode { #endif -enum agc_ctrl_mode { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; +enum agc_ctrl_mode { + DRXK_AGC_CTRL_AUTO = 0, + DRXK_AGC_CTRL_USER, + DRXK_AGC_CTRL_OFF +}; + enum e_drxk_state { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, -- GitLab From 949dd08d92cdbbe7f2560f06ac297eee54b7ea49 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:50 -0300 Subject: [PATCH 0801/2900] [media] drxk_hard: remove needless parenthesis X-Patchwork-Delegate: mchehab@redhat.com There are several places where: state->var = (some_var) The parenthesis there are doing nothing but making it harder to read and breaking the 80 columns soft limits. Just get rid of it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 1fd74f2ed3e2..7f4b5145a8aa 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -628,21 +628,21 @@ static int init_state(struct drxk_state *state) /* Init AGC and PGA parameters */ /* VSB IF */ - state->m_vsb_if_agc_cfg.ctrl_mode = (ul_vsb_if_agc_mode); - state->m_vsb_if_agc_cfg.output_level = (ul_vsb_if_agc_output_level); - state->m_vsb_if_agc_cfg.min_output_level = (ul_vsb_if_agc_min_level); - state->m_vsb_if_agc_cfg.max_output_level = (ul_vsb_if_agc_max_level); - state->m_vsb_if_agc_cfg.speed = (ul_vsb_if_agc_speed); + state->m_vsb_if_agc_cfg.ctrl_mode = ul_vsb_if_agc_mode; + state->m_vsb_if_agc_cfg.output_level = ul_vsb_if_agc_output_level; + state->m_vsb_if_agc_cfg.min_output_level = ul_vsb_if_agc_min_level; + state->m_vsb_if_agc_cfg.max_output_level = ul_vsb_if_agc_max_level; + state->m_vsb_if_agc_cfg.speed = ul_vsb_if_agc_speed; state->m_vsb_pga_cfg = 140; /* VSB RF */ - state->m_vsb_rf_agc_cfg.ctrl_mode = (ul_vsb_rf_agc_mode); - state->m_vsb_rf_agc_cfg.output_level = (ul_vsb_rf_agc_output_level); - state->m_vsb_rf_agc_cfg.min_output_level = (ul_vsb_rf_agc_min_level); - state->m_vsb_rf_agc_cfg.max_output_level = (ul_vsb_rf_agc_max_level); - state->m_vsb_rf_agc_cfg.speed = (ul_vsb_rf_agc_speed); - state->m_vsb_rf_agc_cfg.top = (ul_vsb_rf_agc_top); - state->m_vsb_rf_agc_cfg.cut_off_current = (ul_vsb_rf_agc_cut_off_current); + state->m_vsb_rf_agc_cfg.ctrl_mode = ul_vsb_rf_agc_mode; + state->m_vsb_rf_agc_cfg.output_level = ul_vsb_rf_agc_output_level; + state->m_vsb_rf_agc_cfg.min_output_level = ul_vsb_rf_agc_min_level; + state->m_vsb_rf_agc_cfg.max_output_level = ul_vsb_rf_agc_max_level; + state->m_vsb_rf_agc_cfg.speed = ul_vsb_rf_agc_speed; + state->m_vsb_rf_agc_cfg.top = ul_vsb_rf_agc_top; + state->m_vsb_rf_agc_cfg.cut_off_current = ul_vsb_rf_agc_cut_off_current; state->m_vsb_pre_saw_cfg.reference = 0x07; state->m_vsb_pre_saw_cfg.use_pre_saw = true; @@ -654,20 +654,20 @@ static int init_state(struct drxk_state *state) } /* ATV IF */ - state->m_atv_if_agc_cfg.ctrl_mode = (ul_atv_if_agc_mode); - state->m_atv_if_agc_cfg.output_level = (ul_atv_if_agc_output_level); - state->m_atv_if_agc_cfg.min_output_level = (ul_atv_if_agc_min_level); - state->m_atv_if_agc_cfg.max_output_level = (ul_atv_if_agc_max_level); - state->m_atv_if_agc_cfg.speed = (ul_atv_if_agc_speed); + state->m_atv_if_agc_cfg.ctrl_mode = ul_atv_if_agc_mode; + state->m_atv_if_agc_cfg.output_level = ul_atv_if_agc_output_level; + state->m_atv_if_agc_cfg.min_output_level = ul_atv_if_agc_min_level; + state->m_atv_if_agc_cfg.max_output_level = ul_atv_if_agc_max_level; + state->m_atv_if_agc_cfg.speed = ul_atv_if_agc_speed; /* ATV RF */ - state->m_atv_rf_agc_cfg.ctrl_mode = (ul_atv_rf_agc_mode); - state->m_atv_rf_agc_cfg.output_level = (ul_atv_rf_agc_output_level); - state->m_atv_rf_agc_cfg.min_output_level = (ul_atv_rf_agc_min_level); - state->m_atv_rf_agc_cfg.max_output_level = (ul_atv_rf_agc_max_level); - state->m_atv_rf_agc_cfg.speed = (ul_atv_rf_agc_speed); - state->m_atv_rf_agc_cfg.top = (ul_atv_rf_agc_top); - state->m_atv_rf_agc_cfg.cut_off_current = (ul_atv_rf_agc_cut_off_current); + state->m_atv_rf_agc_cfg.ctrl_mode = ul_atv_rf_agc_mode; + state->m_atv_rf_agc_cfg.output_level = ul_atv_rf_agc_output_level; + state->m_atv_rf_agc_cfg.min_output_level = ul_atv_rf_agc_min_level; + state->m_atv_rf_agc_cfg.max_output_level = ul_atv_rf_agc_max_level; + state->m_atv_rf_agc_cfg.speed = ul_atv_rf_agc_speed; + state->m_atv_rf_agc_cfg.top = ul_atv_rf_agc_top; + state->m_atv_rf_agc_cfg.cut_off_current = ul_atv_rf_agc_cut_off_current; state->m_atv_pre_saw_cfg.reference = 0x04; state->m_atv_pre_saw_cfg.use_pre_saw = true; @@ -764,7 +764,7 @@ static int init_state(struct drxk_state *state) state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM; state->m_agcfast_clip_ctrl_delay = 0; - state->m_gpio_cfg = (ul_gpio_cfg); + state->m_gpio_cfg = ul_gpio_cfg; state->m_b_power_down = false; state->m_current_power_mode = DRX_POWER_DOWN; -- GitLab From ab5060cdb8829c0503b7be2b239b52e9a25063b4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 28 Apr 2013 11:47:51 -0300 Subject: [PATCH 0802/2900] [media] drxk_hard: Remove most 80-cols checkpatch warnings X-Patchwork-Delegate: mchehab@redhat.com There are a few cases where breaking the code into separate lines make it worse to read. However, on several places, breaking it to make checkpatch.pl happier is OK and improves code readability. So, break longer lines where that won't cause harm. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxk_hard.c | 406 ++++++++++++++++-------- 1 file changed, 275 insertions(+), 131 deletions(-) diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 7f4b5145a8aa..082014de6875 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -189,8 +189,10 @@ static inline u32 Frac28a(u32 a, u32 c) u32 R0 = 0; R0 = (a % c) << 4; /* 32-28 == 4 shifts possible at max */ - Q1 = a / c; /* integer part, only the 4 least significant bits - will be visible in the result */ + Q1 = a / c; /* + * integer part, only the 4 least significant + * bits will be visible in the result + */ /* division using radix 16, 7 nibbles in the result */ for (i = 0; i < 7; i++) { @@ -783,7 +785,8 @@ static int drxx_open(struct drxk_state *state) dprintk(1, "\n"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; /* Check device id */ @@ -817,7 +820,8 @@ static int get_device_capabilities(struct drxk_state *state) /* driver 0.9.0 */ /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); @@ -1055,22 +1059,28 @@ static int hi_cfg_command(struct drxk_state *state) mutex_lock(&state->mutex); - status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_hi_cfg_timeout); + status = write16(state, SIO_HI_RA_RAM_PAR_6__A, + state->m_hi_cfg_timeout); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_hi_cfg_ctrl); + status = write16(state, SIO_HI_RA_RAM_PAR_5__A, + state->m_hi_cfg_ctrl); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_hi_cfg_wake_up_key); + status = write16(state, SIO_HI_RA_RAM_PAR_4__A, + state->m_hi_cfg_wake_up_key); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_hi_cfg_bridge_delay); + status = write16(state, SIO_HI_RA_RAM_PAR_3__A, + state->m_hi_cfg_bridge_delay); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_hi_cfg_timing_div); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + state->m_hi_cfg_timing_div); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + status = write16(state, SIO_HI_RA_RAM_PAR_1__A, + SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); @@ -1109,7 +1119,8 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) state->m_enable_parallel ? "parallel" : "serial"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; @@ -1181,25 +1192,32 @@ static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) if (state->m_enable_parallel == true) { /* paralel -> enable MD1 to MD7 */ - status = write16(state, SIO_PDR_MD1_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD1_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD2_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD2_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD3_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD3_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD4_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD4_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD5_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD5_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD6_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD6_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD7_CFG__A, sio_pdr_mdx_cfg); + status = write16(state, SIO_PDR_MD7_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; } else { @@ -1390,7 +1408,8 @@ static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); do { status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); - if ((status >= 0 && data == desired_status) || time_is_after_jiffies(end)) + if ((status >= 0 && data == desired_status) + || time_is_after_jiffies(end)) break; usleep_range(1000, 2000); } while (1); @@ -1487,7 +1506,8 @@ static int scu_command(struct drxk_state *state, int ii; for (ii = result_len - 1; ii >= 0; ii -= 1) { - status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]); + status = read16(state, SCU_RAM_PARAM_0__A - ii, + &result[ii]); if (status < 0) goto error; } @@ -1683,11 +1703,17 @@ static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) goto error; if (data == SCU_COMM_EXEC_ACTIVE) { /* Send OFDM stop command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* Send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; } @@ -1733,7 +1759,8 @@ static int setoperation_mode(struct drxk_state *state, */ /* disable HW lock indicator */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; @@ -2083,7 +2110,8 @@ static int mpegts_dto_setup(struct drxk_state *state, status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate); if (status < 0) goto error; - status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fec_oc_tmd_int_upd_rate); + status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, + fec_oc_tmd_int_upd_rate); if (status < 0) goto error; status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); @@ -2193,17 +2221,21 @@ static int set_agc_rf(struct drxk_state *state, /* Set TOP, only if IF-AGC is in AUTO mode */ if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->top); + status = write16(state, + SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_agc_cfg->top); if (status < 0) goto error; /* Cut-Off current */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, p_agc_cfg->cut_off_current); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, + p_agc_cfg->cut_off_current); if (status < 0) goto error; /* Max. output level */ - status = write16(state, SCU_RAM_AGC_RF_MAX__A, p_agc_cfg->max_output_level); + status = write16(state, SCU_RAM_AGC_RF_MAX__A, + p_agc_cfg->max_output_level); if (status < 0) goto error; @@ -2238,7 +2270,8 @@ static int set_agc_rf(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, p_agc_cfg->output_level); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, + p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2332,7 +2365,8 @@ static int set_agc_if(struct drxk_state *state, if (p_rf_agc_settings == NULL) return -1; /* Restore TOP */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_rf_agc_settings->top); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_rf_agc_settings->top); if (status < 0) goto error; break; @@ -2365,7 +2399,8 @@ static int set_agc_if(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, p_agc_cfg->output_level); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2470,16 +2505,20 @@ static int get_dvbt_signal_to_noise(struct drxk_state *state, dprintk(1, "\n"); - status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &eq_reg_td_tps_pwr_ofs); + status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, + &eq_reg_td_tps_pwr_ofs); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &eq_reg_td_req_smb_cnt); + status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, + &eq_reg_td_req_smb_cnt); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &eq_reg_td_sqr_err_exp); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, + &eq_reg_td_sqr_err_exp); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®_data); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, + ®_data); if (status < 0) goto error; /* Extend SQR_ERR_I operational range */ @@ -2497,7 +2536,8 @@ static int get_dvbt_signal_to_noise(struct drxk_state *state, (eq_reg_td_sqr_err_q < 0x00000FFFUL)) eq_reg_td_sqr_err_q += 0x00010000UL; - status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmission_params); + status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, + &transmission_params); if (status < 0) goto error; @@ -2604,12 +2644,14 @@ static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) status = get_dvbt_signal_to_noise(state, &signal_to_noise); if (status < 0) break; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &constellation); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, + &constellation); if (status < 0) break; constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &code_rate); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, + &code_rate); if (status < 0) break; code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; @@ -2723,15 +2765,18 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) if (state->no_i2c_bridge) return 0; - status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + status = write16(state, SIO_HI_RA_RAM_PAR_1__A, + SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; if (b_enable_bridge) { - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); if (status < 0) goto error; } else { - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); if (status < 0) goto error; } @@ -3013,7 +3058,8 @@ static int init_agc(struct drxk_state *state, bool is_dtv) ingain_tgt_max = 5119; fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay; - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fast_clp_ctrl_delay); + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, + fast_clp_ctrl_delay); if (status < 0) goto error; @@ -3029,10 +3075,12 @@ static int init_agc(struct drxk_state *state, bool is_dtv) status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, if_iaccu_hi_tgt_min); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, + if_iaccu_hi_tgt_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, if_iaccu_hi_tgt_max); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + if_iaccu_hi_tgt_max); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); @@ -3054,10 +3102,12 @@ static int init_agc(struct drxk_state *state, bool is_dtv) if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, ki_innergain_min); + status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, + ki_innergain_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, if_iaccu_hi_tgt); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, + if_iaccu_hi_tgt); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); @@ -3158,7 +3208,8 @@ static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) if (packet_err == NULL) status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); else - status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packet_err); + status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, + packet_err); if (status < 0) pr_err("Error %d on %s\n", status, __func__); return status; @@ -3332,7 +3383,7 @@ static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) } static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, - struct drxk_cfg_dvbt_echo_thres_t *echo_thres) + struct drxk_cfg_dvbt_echo_thres_t *echo_thres) { u16 data = 0; int status; @@ -3421,7 +3472,8 @@ static int dvbt_activate_presets(struct drxk_state *state) status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbt_if_agc_cfg.ingain_tgt_max); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, + state->m_dvbt_if_agc_cfg.ingain_tgt_max); error: if (status < 0) pr_err("Error %d on %s\n", status, __func__); @@ -3451,12 +3503,17 @@ static int set_dvbt_standard(struct drxk_state *state, /* added antenna switch */ switch_antenna_to_dvbt(state); /* send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* send OFDM setenv command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3510,7 +3567,7 @@ static int set_dvbt_standard(struct drxk_state *state, status = write16(state, IQM_RC_STRETCH__A, 16); if (status < 0) goto error; - status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ + status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ if (status < 0) goto error; status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */ @@ -3531,7 +3588,8 @@ static int set_dvbt_standard(struct drxk_state *state, if (status < 0) goto error; - status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, + DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); if (status < 0) goto error; @@ -3585,7 +3643,8 @@ static int set_dvbt_standard(struct drxk_state *state, if (!state->m_drxk_a3_rom_code) { /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */ - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, + state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); if (status < 0) goto error; } @@ -3650,7 +3709,9 @@ static int dvbt_start(struct drxk_state *state) /* start correct processes to get in lock */ /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */ param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN; - status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); + status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, + OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, + 0, 0, 0); if (status < 0) goto error; /* start FEC OC */ @@ -3686,9 +3747,12 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, u16 param1; int status; - dprintk(1, "IF =%d, TFO = %d\n", intermediate_freqk_hz, tuner_freq_offset); + dprintk(1, "IF =%d, TFO = %d\n", + intermediate_freqk_hz, tuner_freq_offset); - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3711,7 +3775,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, if (status < 0) goto error; - /*== Write channel settings to device =====================================*/ + /*== Write channel settings to device ================================*/ /* mode */ switch (state->props.transmission_mode) { @@ -3834,71 +3898,92 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, break; } - /* SAW filter selection: normaly not necesarry, but if wanted - the application can select a SAW filter via the driver by using UIOs */ + /* + * SAW filter selection: normaly not necesarry, but if wanted + * the application can select a SAW filter via the driver by + * using UIOs + */ + /* First determine real bandwidth (Hz) */ /* Also set delay for impulse noise cruncher */ - /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed - by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC - functions */ + /* + * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is + * changed by SC for fix for some 8K,1/8 guard but is restored by + * InitEC and ResetEC functions + */ switch (state->props.bandwidth_hz) { case 0: state->props.bandwidth_hz = 8000000; /* fall though */ case 8000000: bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 3052); if (status < 0) goto error; /* cochannel protection for PAL 8 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; case 7000000: bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 3491); if (status < 0) goto error; /* cochannel protection for PAL 7 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 8); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 8); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 4); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; case 6000000: bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 4073); if (status < 0) goto error; /* cochannel protection for NTSC 6 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 19); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 19); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 14); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; @@ -3914,13 +3999,16 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, ((SysFreq / BandWidth) * (2^21)) - (2^23) */ /* (SysFreq / BandWidth) * (2^28) */ - /* assert (MAX(sysClk)/MIN(bandwidth) < 16) - => assert(MAX(sysClk) < 16*MIN(bandwidth)) - => assert(109714272 > 48000000) = true so Frac 28 can be used */ + /* + * assert (MAX(sysClk)/MIN(bandwidth) < 16) + * => assert(MAX(sysClk) < 16*MIN(bandwidth)) + * => assert(109714272 > 48000000) = true + * so Frac 28 can be used + */ iqm_rc_rate_ofs = Frac28a((u32) ((state->m_sys_clock_freq * 1000) / 3), bandwidth); - /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ + /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40) iqm_rc_rate_ofs += 0x80L; iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7; @@ -3942,11 +4030,12 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, if (status < 0) goto error; #endif - status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, + tuner_freq_offset, true); if (status < 0) goto error; - /*== start SC, write channel settings to SC ===============================*/ + /*== start SC, write channel settings to SC ==========================*/ /* Activate SCU to enable SCU commands */ status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); @@ -3962,7 +4051,9 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_START, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -4071,7 +4162,9 @@ static int power_down_qam(struct drxk_state *state) status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; } @@ -4139,7 +4232,7 @@ static int set_qam_measurement(struct drxk_state *state, if (status < 0) goto error; - fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ + fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ fec_bits_desired *= 500; /* meas. period [ms] */ /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */ @@ -4162,7 +4255,8 @@ static int set_qam_measurement(struct drxk_state *state, status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period); if (status < 0) goto error; - status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fec_rs_prescale); + status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, + fec_rs_prescale); if (status < 0) goto error; status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); @@ -4228,7 +4322,8 @@ static int set_qam16(struct drxk_state *state) goto error; /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM16); if (status < 0) goto error; @@ -4424,7 +4519,8 @@ static int set_qam32(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM32); if (status < 0) goto error; @@ -4617,7 +4713,8 @@ static int set_qam64(struct drxk_state *state) goto error; /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM64); if (status < 0) goto error; @@ -4813,7 +4910,8 @@ static int set_qam128(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM128); if (status < 0) goto error; @@ -5008,7 +5106,8 @@ static int set_qam256(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM256); if (status < 0) goto error; @@ -5156,7 +5255,9 @@ static int qam_reset_qam(struct drxk_state *state) if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); error: if (status < 0) pr_err("Error %d on %s\n", status, __func__); @@ -5267,8 +5368,10 @@ static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) } else { /* 0xC000 NEVER LOCKED */ /* (system will never be able to lock to the signal) */ - /* TODO: check this, intermediate & standard specific lock states are not - taken into account here */ + /* + * TODO: check this, intermediate & standard specific lock + * states are not taken into account here + */ *p_lock_status = NEVER_LOCK; } return status; @@ -5300,13 +5403,15 @@ static int qam_demodulator_command(struct drxk_state *state, set_env_parameters[0] = QAM_TOP_ANNEX_A; status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, set_env_parameters, 1, &cmd_result); if (status < 0) goto error; status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, number_of_parameters, set_param_parameters, 1, &cmd_result); } else if (number_of_parameters == 4) { @@ -5321,7 +5426,8 @@ static int qam_demodulator_command(struct drxk_state *state, /* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */ status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, number_of_parameters, set_param_parameters, 1, &cmd_result); } else { @@ -5439,12 +5545,14 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, if (status < 0) goto error; #endif - status = set_frequency_shifter(state, intermediate_freqk_hz, tuner_freq_offset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, + tuner_freq_offset, true); if (status < 0) goto error; /* Setup BER measurement */ - status = set_qam_measurement(state, state->m_constellation, state->props.symbol_rate); + status = set_qam_measurement(state, state->m_constellation, + state->props.symbol_rate); if (status < 0) goto error; @@ -5517,7 +5625,8 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, goto error; /* Mirroring, QAM-block starting point not inverted */ - status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS); + status = write16(state, QAM_SY_SP_INV__A, + QAM_SY_SP_INV_SPECTRUM_INV_DIS); if (status < 0) goto error; @@ -5578,7 +5687,9 @@ static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, goto error; /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmd_result); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_START, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -5628,13 +5739,22 @@ static int set_qam_standard(struct drxk_state *state, boot loader from ROM table */ switch (o_mode) { case OM_QAM_ITU_A: - status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, + DRXK_BLCC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); break; case OM_QAM_ITU_C: - status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, + DRXK_BL_ROM_OFFSET_TAPS_ITU_C, + DRXK_BLDC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); if (status < 0) goto error; - status = bl_direct_cmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, + IQM_CF_TAP_IM0__A, + DRXK_BL_ROM_OFFSET_TAPS_ITU_C, + DRXK_BLDC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); break; default: status = -EINVAL; @@ -5642,13 +5762,14 @@ static int set_qam_standard(struct drxk_state *state, if (status < 0) goto error; - status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B)); + status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B); if (status < 0) goto error; status = write16(state, IQM_CF_SYMMETRIC__A, 0); if (status < 0) goto error; - status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); + status = write16(state, IQM_CF_MIDTAP__A, + ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); if (status < 0) goto error; @@ -5760,7 +5881,8 @@ static int write_gpio(struct drxk_state *state) dprintk(1, "\n"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; @@ -5772,7 +5894,8 @@ static int write_gpio(struct drxk_state *state) if (state->m_has_sawsw) { if (state->uio_mask & 0x0001) { /* UIO-1 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_gpio_cfg); + status = write16(state, SIO_PDR_SMA_TX_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5791,7 +5914,8 @@ static int write_gpio(struct drxk_state *state) } if (state->uio_mask & 0x0002) { /* UIO-2 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_gpio_cfg); + status = write16(state, SIO_PDR_SMA_RX_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5810,7 +5934,8 @@ static int write_gpio(struct drxk_state *state) } if (state->uio_mask & 0x0004) { /* UIO-3 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_gpio_cfg); + status = write16(state, SIO_PDR_GPIO_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5909,7 +6034,8 @@ static int power_down_device(struct drxk_state *state) if (status < 0) goto error; - status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK); + status = write16(state, SIO_CC_PWD_MODE__A, + SIO_CC_PWD_MODE_LEVEL_CLOCK); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); @@ -5940,13 +6066,19 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; /* Soft reset of OFDM-, sys- and osc-clockdomain */ - status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M); + status = write16(state, SIO_CC_SOFT_RST__A, + SIO_CC_SOFT_RST_OFDM__M + | SIO_CC_SOFT_RST_SYS__M + | SIO_CC_SOFT_RST_OSC__M); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; - /* TODO is this needed, if yes how much delay in worst case scenario */ + /* + * TODO is this needed? If yes, how much delay in + * worst case scenario + */ usleep_range(1000, 2000); state->m_drxk_a3_patch_code = true; status = get_device_capabilities(state); @@ -5979,7 +6111,8 @@ static int init_drxk(struct drxk_state *state) && !(state->m_DRXK_A2_ROM_CODE)) #endif { - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; } @@ -5998,12 +6131,14 @@ static int init_drxk(struct drxk_state *state) goto error; /* enable token-ring bus through OFDM block for possible ucode upload */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, + SIO_OFDM_SH_OFDM_RING_ENABLE_ON); if (status < 0) goto error; /* include boot loader section */ - status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE); + status = write16(state, SIO_BL_COMM_EXEC__A, + SIO_BL_COMM_EXEC_ACTIVE); if (status < 0) goto error; status = bl_chain_cmd(state, 0, 6, 100); @@ -6018,7 +6153,8 @@ static int init_drxk(struct drxk_state *state) } /* disable token-ring bus through OFDM block for possible ucode upload */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, + SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); if (status < 0) goto error; @@ -6048,7 +6184,8 @@ static int init_drxk(struct drxk_state *state) (((DRXK_VERSION_MAJOR / 10) % 10) << 8) + ((DRXK_VERSION_MAJOR % 10) << 4) + (DRXK_VERSION_MINOR % 10); - status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driver_version); + status = write16(state, SCU_RAM_DRIVER_VER_HI__A, + driver_version); if (status < 0) goto error; driver_version = @@ -6056,7 +6193,8 @@ static int init_drxk(struct drxk_state *state) (((DRXK_VERSION_PATCH / 100) % 10) << 8) + (((DRXK_VERSION_PATCH / 10) % 10) << 4) + (DRXK_VERSION_PATCH % 10); - status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driver_version); + status = write16(state, SCU_RAM_DRIVER_VER_LO__A, + driver_version); if (status < 0) goto error; @@ -6064,10 +6202,13 @@ static int init_drxk(struct drxk_state *state) DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR, DRXK_VERSION_PATCH); - /* Dirty fix of default values for ROM/PATCH microcode - Dirty because this fix makes it impossible to setup suitable values - before calling DRX_Open. This solution requires changes to RF AGC speed - to be done via the CTRL function after calling DRX_Open */ + /* + * Dirty fix of default values for ROM/PATCH microcode + * Dirty because this fix makes it impossible to setup + * suitable values before calling DRX_Open. This solution + * requires changes to RF AGC speed to be done via the CTRL + * function after calling DRX_Open + */ /* m_dvbt_rf_agc_cfg.speed = 3; */ @@ -6238,7 +6379,8 @@ static int drxk_set_parameters(struct dvb_frontend *fe) case SYS_DVBC_ANNEX_C: if (!state->m_has_dvbc) return -EINVAL; - state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false; + state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? + true : false; if (state->m_itut_annex_c) setoperation_mode(state, OM_QAM_ITU_C); else @@ -6352,7 +6494,7 @@ static int get_strength(struct drxk_state *state, u64 *strength) if (if_agc.output_level > if_agc.max_output_level) if_agc.output_level = if_agc.max_output_level; - agc_range = (u32) (if_agc.max_output_level - if_agc.min_output_level); + agc_range = (u32)(if_agc.max_output_level - if_agc.min_output_level); if (agc_range > 0) { atten += 100UL * ((u32)(tuner_if_gain)) * @@ -6433,9 +6575,11 @@ static int drxk_get_stats(struct dvb_frontend *fe) /* BER measurement is valid if at least FEC lock is achieved */ - /* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written - to set nr of symbols or bits over which - to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */ + /* + * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be + * written to set nr of symbols or bits over which to measure + * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). + */ /* Read registers for post/preViterbi BER calculation */ status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); @@ -6566,8 +6710,8 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings - *sets) +static int drxk_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *sets) { struct drxk_state *state = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; -- GitLab From 94a87157cde95d38b9cdf1116e4f0fd93f6d25df Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 9 Jun 2013 18:15:00 +0200 Subject: [PATCH 0803/2900] firewire: introduce fw_driver.probe and .remove methods FireWire upper layer drivers are converted from generic struct driver.probe() and .remove() to bus-specific struct fw_driver.probe() and .remove(). The new .probe() adds a const struct ieee1394_device_id *id argument, indicating the entry in the driver's device identifiers table which matched the fw_unit to be probed. This new argument is used by the snd-firewire-speakers driver to look up device-specific parameters and methods. There is at least one other FireWire audio driver currently in development in which this will be useful too. The new .remove() drops the unused error return code. Although all in-tree drivers are being converted to the new methods, support for the old methods is left in place in this commit. This allows public developer trees to merge this commit and then move to the new fw_driver methods. Signed-off-by: Stefan Richter Acked-by: Clemens Ladisch (for sound/firewire/) Cc: Peter Hurley (for drivers/staging/fwserial/) --- drivers/firewire/core-device.c | 45 +++++++++--- drivers/firewire/net.c | 50 +++++++------ drivers/firewire/sbp2.c | 17 ++--- drivers/media/firewire/firedtv-fw.c | 19 +++-- drivers/staging/fwserial/fwserial.c | 14 ++-- include/linux/firewire.h | 2 + sound/firewire/isight.c | 44 ++++++------ sound/firewire/scs1x.c | 39 +++++----- sound/firewire/speakers.c | 106 +++++++++++----------------- 9 files changed, 166 insertions(+), 170 deletions(-) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 664a6ff0a823..c152edd6cd3a 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -165,25 +165,50 @@ static bool match_ids(const struct ieee1394_device_id *id_table, int *id) return (match & id_table->match_flags) == id_table->match_flags; } -static bool is_fw_unit(struct device *dev); - -static int fw_unit_match(struct device *dev, struct device_driver *drv) +static const struct ieee1394_device_id *unit_match(struct device *dev, + struct device_driver *drv) { const struct ieee1394_device_id *id_table = container_of(drv, struct fw_driver, driver)->id_table; int id[] = {0, 0, 0, 0}; - /* We only allow binding to fw_units. */ - if (!is_fw_unit(dev)) - return 0; - get_modalias_ids(fw_unit(dev), id); for (; id_table->match_flags != 0; id_table++) if (match_ids(id_table, id)) - return 1; + return id_table; - return 0; + return NULL; +} + +static bool is_fw_unit(struct device *dev); + +static int fw_unit_match(struct device *dev, struct device_driver *drv) +{ + /* We only allow binding to fw_units. */ + return is_fw_unit(dev) && unit_match(dev, drv) != NULL; +} + +static int fw_unit_probe(struct device *dev) +{ + struct fw_driver *driver = + container_of(dev->driver, struct fw_driver, driver); + + if (driver->probe) + return driver->probe(fw_unit(dev), unit_match(dev, dev->driver)); + else + return driver->driver.probe(dev); +} + +static int fw_unit_remove(struct device *dev) +{ + struct fw_driver *driver = + container_of(dev->driver, struct fw_driver, driver); + + if (driver->remove) + return driver->remove(fw_unit(dev)), 0; + else + return driver->driver.remove(dev); } static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) @@ -213,6 +238,8 @@ static int fw_unit_uevent(struct device *dev, struct kobj_uevent_env *env) struct bus_type fw_bus_type = { .name = "firewire", .match = fw_unit_match, + .probe = fw_unit_probe, + .remove = fw_unit_remove, }; EXPORT_SYMBOL(fw_bus_type); diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 815b0fcbe918..6b895986dc22 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -1440,9 +1440,9 @@ static int fwnet_add_peer(struct fwnet_device *dev, return 0; } -static int fwnet_probe(struct device *_dev) +static int fwnet_probe(struct fw_unit *unit, + const struct ieee1394_device_id *id) { - struct fw_unit *unit = fw_unit(_dev); struct fw_device *device = fw_parent_device(unit); struct fw_card *card = device->card; struct net_device *net; @@ -1526,6 +1526,24 @@ static int fwnet_probe(struct device *_dev) return ret; } +/* + * FIXME abort partially sent fragmented datagrams, + * discard partially received fragmented datagrams + */ +static void fwnet_update(struct fw_unit *unit) +{ + struct fw_device *device = fw_parent_device(unit); + struct fwnet_peer *peer = dev_get_drvdata(&unit->device); + int generation; + + generation = device->generation; + + spin_lock_irq(&peer->dev->lock); + peer->node_id = device->node_id; + peer->generation = generation; + spin_unlock_irq(&peer->dev->lock); +} + static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev) { struct fwnet_partial_datagram *pd, *pd_next; @@ -1542,9 +1560,9 @@ static void fwnet_remove_peer(struct fwnet_peer *peer, struct fwnet_device *dev) kfree(peer); } -static int fwnet_remove(struct device *_dev) +static void fwnet_remove(struct fw_unit *unit) { - struct fwnet_peer *peer = dev_get_drvdata(_dev); + struct fwnet_peer *peer = dev_get_drvdata(&unit->device); struct fwnet_device *dev = peer->dev; struct net_device *net; int i; @@ -1569,26 +1587,6 @@ static int fwnet_remove(struct device *_dev) } mutex_unlock(&fwnet_device_mutex); - - return 0; -} - -/* - * FIXME abort partially sent fragmented datagrams, - * discard partially received fragmented datagrams - */ -static void fwnet_update(struct fw_unit *unit) -{ - struct fw_device *device = fw_parent_device(unit); - struct fwnet_peer *peer = dev_get_drvdata(&unit->device); - int generation; - - generation = device->generation; - - spin_lock_irq(&peer->dev->lock); - peer->node_id = device->node_id; - peer->generation = generation; - spin_unlock_irq(&peer->dev->lock); } static const struct ieee1394_device_id fwnet_id_table[] = { @@ -1614,10 +1612,10 @@ static struct fw_driver fwnet_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = fwnet_probe, - .remove = fwnet_remove, }, + .probe = fwnet_probe, .update = fwnet_update, + .remove = fwnet_remove, .id_table = fwnet_id_table, }; diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 47674b913843..281029daf98c 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1128,11 +1128,10 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, } static struct scsi_host_template scsi_driver_template; -static int sbp2_remove(struct device *dev); +static void sbp2_remove(struct fw_unit *unit); -static int sbp2_probe(struct device *dev) +static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) { - struct fw_unit *unit = fw_unit(dev); struct fw_device *device = fw_parent_device(unit); struct sbp2_target *tgt; struct sbp2_logical_unit *lu; @@ -1196,7 +1195,7 @@ static int sbp2_probe(struct device *dev) return 0; fail_remove: - sbp2_remove(dev); + sbp2_remove(unit); return -ENOMEM; fail_shost_put: @@ -1222,9 +1221,8 @@ static void sbp2_update(struct fw_unit *unit) } } -static int sbp2_remove(struct device *dev) +static void sbp2_remove(struct fw_unit *unit) { - struct fw_unit *unit = fw_unit(dev); struct fw_device *device = fw_parent_device(unit); struct sbp2_target *tgt = dev_get_drvdata(&unit->device); struct sbp2_logical_unit *lu, *next; @@ -1261,10 +1259,9 @@ static int sbp2_remove(struct device *dev) kfree(lu); } scsi_remove_host(shost); - dev_notice(dev, "released target %d:0:0\n", shost->host_no); + dev_notice(&unit->device, "released target %d:0:0\n", shost->host_no); scsi_host_put(shost); - return 0; } #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e @@ -1285,10 +1282,10 @@ static struct fw_driver sbp2_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = sbp2_probe, - .remove = sbp2_remove, }, + .probe = sbp2_probe, .update = sbp2_update, + .remove = sbp2_remove, .id_table = sbp2_id_table, }; diff --git a/drivers/media/firewire/firedtv-fw.c b/drivers/media/firewire/firedtv-fw.c index e24ec539a5fd..247f0e7cb5f7 100644 --- a/drivers/media/firewire/firedtv-fw.c +++ b/drivers/media/firewire/firedtv-fw.c @@ -248,7 +248,7 @@ static const char * const model_names[] = { /* Adjust the template string if models with longer names appear. */ #define MAX_MODEL_NAME_LEN sizeof("FireDTV ????") -static int node_probe(struct device *dev) +static int node_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) { struct firedtv *fdtv; char name[MAX_MODEL_NAME_LEN]; @@ -258,8 +258,8 @@ static int node_probe(struct device *dev) if (!fdtv) return -ENOMEM; - dev_set_drvdata(dev, fdtv); - fdtv->device = dev; + dev_set_drvdata(&unit->device, fdtv); + fdtv->device = &unit->device; fdtv->isochannel = -1; fdtv->voltage = 0xff; fdtv->tone = 0xff; @@ -269,7 +269,7 @@ static int node_probe(struct device *dev) mutex_init(&fdtv->demux_mutex); INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); - name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL, + name_len = fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)); for (i = ARRAY_SIZE(model_names); --i; ) if (strlen(model_names[i]) <= name_len && @@ -277,7 +277,7 @@ static int node_probe(struct device *dev) break; fdtv->type = i; - err = fdtv_register_rc(fdtv, dev); + err = fdtv_register_rc(fdtv, &unit->device); if (err) goto fail_free; @@ -307,9 +307,9 @@ static int node_probe(struct device *dev) return err; } -static int node_remove(struct device *dev) +static void node_remove(struct fw_unit *unit) { - struct firedtv *fdtv = dev_get_drvdata(dev); + struct firedtv *fdtv = dev_get_drvdata(&unit->device); fdtv_dvb_unregister(fdtv); @@ -320,7 +320,6 @@ static int node_remove(struct device *dev) fdtv_unregister_rc(fdtv); kfree(fdtv); - return 0; } static void node_update(struct fw_unit *unit) @@ -391,10 +390,10 @@ static struct fw_driver fdtv_driver = { .owner = THIS_MODULE, .name = "firedtv", .bus = &fw_bus_type, - .probe = node_probe, - .remove = node_remove, }, + .probe = node_probe, .update = node_update, + .remove = node_remove, .id_table = fdtv_id_table, }; diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index e5818a1c2262..a8399f9c9392 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -2438,9 +2438,9 @@ static int fwserial_create(struct fw_unit *unit) * last peer for a given fw_card triggering the destruction of the same * fw_serial for the same fw_card. */ -static int fwserial_probe(struct device *dev) +static int fwserial_probe(struct fw_unit *unit, + const struct ieee1394_device_id *id) { - struct fw_unit *unit = fw_unit(dev); struct fw_serial *serial; int err; @@ -2462,9 +2462,9 @@ static int fwserial_probe(struct device *dev) * specific fw_card). If this is the last peer being removed, then trigger * the destruction of the underlying TTYs. */ -static int fwserial_remove(struct device *dev) +static void fwserial_remove(struct fw_unit *unit) { - struct fwtty_peer *peer = dev_get_drvdata(dev); + struct fwtty_peer *peer = dev_get_drvdata(&unit->device); struct fw_serial *serial = peer->serial; int i; @@ -2484,8 +2484,6 @@ static int fwserial_remove(struct device *dev) kref_put(&serial->kref, fwserial_destroy); } mutex_unlock(&fwserial_list_mutex); - - return 0; } /** @@ -2530,10 +2528,10 @@ static struct fw_driver fwserial_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = fwserial_probe, - .remove = fwserial_remove, }, + .probe = fwserial_probe, .update = fwserial_update, + .remove = fwserial_remove, .id_table = fwserial_id_table, }; diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 191501afd7fb..3b0e820375ab 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -251,8 +251,10 @@ struct ieee1394_device_id; struct fw_driver { struct device_driver driver; + int (*probe)(struct fw_unit *unit, const struct ieee1394_device_id *id); /* Called when the parent device sits through a bus reset. */ void (*update)(struct fw_unit *unit); + void (*remove)(struct fw_unit *unit); const struct ieee1394_device_id *id_table; }; diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index d428ffede4f3..58a5afefdc69 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -626,9 +626,9 @@ static u64 get_unit_base(struct fw_unit *unit) return 0; } -static int isight_probe(struct device *unit_dev) +static int isight_probe(struct fw_unit *unit, + const struct ieee1394_device_id *id) { - struct fw_unit *unit = fw_unit(unit_dev); struct fw_device *fw_dev = fw_parent_device(unit); struct snd_card *card; struct isight *isight; @@ -637,7 +637,7 @@ static int isight_probe(struct device *unit_dev) err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*isight), &card); if (err < 0) return err; - snd_card_set_dev(card, unit_dev); + snd_card_set_dev(card, &unit->device); isight = card->private_data; isight->card = card; @@ -674,7 +674,7 @@ static int isight_probe(struct device *unit_dev) if (err < 0) goto error; - dev_set_drvdata(unit_dev, isight); + dev_set_drvdata(&unit->device, isight); return 0; @@ -686,23 +686,6 @@ static int isight_probe(struct device *unit_dev) return err; } -static int isight_remove(struct device *dev) -{ - struct isight *isight = dev_get_drvdata(dev); - - isight_pcm_abort(isight); - - snd_card_disconnect(isight->card); - - mutex_lock(&isight->mutex); - isight_stop_streaming(isight); - mutex_unlock(&isight->mutex); - - snd_card_free_when_closed(isight->card); - - return 0; -} - static void isight_bus_reset(struct fw_unit *unit) { struct isight *isight = dev_get_drvdata(&unit->device); @@ -716,6 +699,21 @@ static void isight_bus_reset(struct fw_unit *unit) } } +static void isight_remove(struct fw_unit *unit) +{ + struct isight *isight = dev_get_drvdata(&unit->device); + + isight_pcm_abort(isight); + + snd_card_disconnect(isight->card); + + mutex_lock(&isight->mutex); + isight_stop_streaming(isight); + mutex_unlock(&isight->mutex); + + snd_card_free_when_closed(isight->card); +} + static const struct ieee1394_device_id isight_id_table[] = { { .match_flags = IEEE1394_MATCH_SPECIFIER_ID | @@ -732,10 +730,10 @@ static struct fw_driver isight_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = isight_probe, - .remove = isight_remove, }, + .probe = isight_probe, .update = isight_bus_reset, + .remove = isight_remove, .id_table = isight_id_table, }; diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c index 844a555c3b1e..1f5920d6eacc 100644 --- a/sound/firewire/scs1x.c +++ b/sound/firewire/scs1x.c @@ -384,9 +384,8 @@ static void scs_card_free(struct snd_card *card) kfree(scs->buffer); } -static int scs_probe(struct device *unit_dev) +static int scs_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) { - struct fw_unit *unit = fw_unit(unit_dev); struct fw_device *fw_dev = fw_parent_device(unit); struct snd_card *card; struct scs *scs; @@ -395,7 +394,7 @@ static int scs_probe(struct device *unit_dev) err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card); if (err < 0) return err; - snd_card_set_dev(card, unit_dev); + snd_card_set_dev(card, &unit->device); scs = card->private_data; scs->card = card; @@ -440,7 +439,7 @@ static int scs_probe(struct device *unit_dev) if (err < 0) goto err_card; - dev_set_drvdata(unit_dev, scs); + dev_set_drvdata(&unit->device, scs); return 0; @@ -451,9 +450,20 @@ static int scs_probe(struct device *unit_dev) return err; } -static int scs_remove(struct device *dev) +static void scs_update(struct fw_unit *unit) { - struct scs *scs = dev_get_drvdata(dev); + struct scs *scs = dev_get_drvdata(&unit->device); + __be64 data; + + data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | + scs->hss_handler.offset); + snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, + HSS1394_ADDRESS, &data, 8); +} + +static void scs_remove(struct fw_unit *unit) +{ + struct scs *scs = dev_get_drvdata(&unit->device); snd_card_disconnect(scs->card); @@ -465,19 +475,6 @@ static int scs_remove(struct device *dev) tasklet_kill(&scs->tasklet); snd_card_free_when_closed(scs->card); - - return 0; -} - -static void scs_update(struct fw_unit *unit) -{ - struct scs *scs = dev_get_drvdata(&unit->device); - __be64 data; - - data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | - scs->hss_handler.offset); - snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, - HSS1394_ADDRESS, &data, 8); } static const struct ieee1394_device_id scs_id_table[] = { @@ -506,10 +503,10 @@ static struct fw_driver scs_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = scs_probe, - .remove = scs_remove, }, + .probe = scs_probe, .update = scs_update, + .remove = scs_remove, .id_table = scs_id_table, }; diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index d6846557f270..2c6386503940 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c @@ -663,45 +663,9 @@ static void fwspk_card_free(struct snd_card *card) mutex_destroy(&fwspk->mutex); } -static const struct device_info *fwspk_detect(struct fw_device *dev) +static int fwspk_probe(struct fw_unit *unit, + const struct ieee1394_device_id *id) { - static const struct device_info griffin_firewave = { - .driver_name = "FireWave", - .short_name = "FireWave", - .long_name = "Griffin FireWave Surround", - .pcm_constraints = firewave_constraints, - .mixer_channels = 6, - .mute_fb_id = 0x01, - .volume_fb_id = 0x02, - }; - static const struct device_info lacie_speakers = { - .driver_name = "FWSpeakers", - .short_name = "FireWire Speakers", - .long_name = "LaCie FireWire Speakers", - .pcm_constraints = lacie_speakers_constraints, - .mixer_channels = 1, - .mute_fb_id = 0x01, - .volume_fb_id = 0x01, - }; - struct fw_csr_iterator i; - int key, value; - - fw_csr_iterator_init(&i, dev->config_rom); - while (fw_csr_iterator_next(&i, &key, &value)) - if (key == CSR_VENDOR) - switch (value) { - case VENDOR_GRIFFIN: - return &griffin_firewave; - case VENDOR_LACIE: - return &lacie_speakers; - } - - return NULL; -} - -static int fwspk_probe(struct device *unit_dev) -{ - struct fw_unit *unit = fw_unit(unit_dev); struct fw_device *fw_dev = fw_parent_device(unit); struct snd_card *card; struct fwspk *fwspk; @@ -711,17 +675,13 @@ static int fwspk_probe(struct device *unit_dev) err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card); if (err < 0) return err; - snd_card_set_dev(card, unit_dev); + snd_card_set_dev(card, &unit->device); fwspk = card->private_data; fwspk->card = card; mutex_init(&fwspk->mutex); fwspk->unit = fw_unit_get(unit); - fwspk->device_info = fwspk_detect(fw_dev); - if (!fwspk->device_info) { - err = -ENODEV; - goto err_unit; - } + fwspk->device_info = (const struct device_info *)id->driver_data; err = cmp_connection_init(&fwspk->connection, unit, 0); if (err < 0) @@ -756,7 +716,7 @@ static int fwspk_probe(struct device *unit_dev) if (err < 0) goto error; - dev_set_drvdata(unit_dev, fwspk); + dev_set_drvdata(&unit->device, fwspk); return 0; @@ -770,22 +730,6 @@ static int fwspk_probe(struct device *unit_dev) return err; } -static int fwspk_remove(struct device *dev) -{ - struct fwspk *fwspk = dev_get_drvdata(dev); - - amdtp_out_stream_pcm_abort(&fwspk->stream); - snd_card_disconnect(fwspk->card); - - mutex_lock(&fwspk->mutex); - fwspk_stop_stream(fwspk); - mutex_unlock(&fwspk->mutex); - - snd_card_free_when_closed(fwspk->card); - - return 0; -} - static void fwspk_bus_reset(struct fw_unit *unit) { struct fwspk *fwspk = dev_get_drvdata(&unit->device); @@ -803,6 +747,40 @@ static void fwspk_bus_reset(struct fw_unit *unit) amdtp_out_stream_update(&fwspk->stream); } +static void fwspk_remove(struct fw_unit *unit) +{ + struct fwspk *fwspk = dev_get_drvdata(&unit->device); + + amdtp_out_stream_pcm_abort(&fwspk->stream); + snd_card_disconnect(fwspk->card); + + mutex_lock(&fwspk->mutex); + fwspk_stop_stream(fwspk); + mutex_unlock(&fwspk->mutex); + + snd_card_free_when_closed(fwspk->card); +} + +static const struct device_info griffin_firewave = { + .driver_name = "FireWave", + .short_name = "FireWave", + .long_name = "Griffin FireWave Surround", + .pcm_constraints = firewave_constraints, + .mixer_channels = 6, + .mute_fb_id = 0x01, + .volume_fb_id = 0x02, +}; + +static const struct device_info lacie_speakers = { + .driver_name = "FWSpeakers", + .short_name = "FireWire Speakers", + .long_name = "LaCie FireWire Speakers", + .pcm_constraints = lacie_speakers_constraints, + .mixer_channels = 1, + .mute_fb_id = 0x01, + .volume_fb_id = 0x01, +}; + static const struct ieee1394_device_id fwspk_id_table[] = { { .match_flags = IEEE1394_MATCH_VENDOR_ID | @@ -813,6 +791,7 @@ static const struct ieee1394_device_id fwspk_id_table[] = { .model_id = 0x00f970, .specifier_id = SPECIFIER_1394TA, .version = VERSION_AVC, + .driver_data = (kernel_ulong_t)&griffin_firewave, }, { .match_flags = IEEE1394_MATCH_VENDOR_ID | @@ -823,6 +802,7 @@ static const struct ieee1394_device_id fwspk_id_table[] = { .model_id = 0x00f970, .specifier_id = SPECIFIER_1394TA, .version = VERSION_AVC, + .driver_data = (kernel_ulong_t)&lacie_speakers, }, { } }; @@ -833,10 +813,10 @@ static struct fw_driver fwspk_driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, .bus = &fw_bus_type, - .probe = fwspk_probe, - .remove = fwspk_remove, }, + .probe = fwspk_probe, .update = fwspk_bus_reset, + .remove = fwspk_remove, .id_table = fwspk_id_table, }; -- GitLab From bcabcfd2e09ceb8599a33001e812e7cbad00fc4d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 9 Jun 2013 18:15:00 +0200 Subject: [PATCH 0804/2900] firewire: remove support of fw_driver.driver.probe and .remove methods After all IEEE 1394 high-level drivers being converted to bus-specific .probe/.remove methods, remove support of the obsolete generic methods. Signed-off-by: Stefan Richter --- drivers/firewire/core-device.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index c152edd6cd3a..de4aa409abe2 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -194,10 +194,7 @@ static int fw_unit_probe(struct device *dev) struct fw_driver *driver = container_of(dev->driver, struct fw_driver, driver); - if (driver->probe) - return driver->probe(fw_unit(dev), unit_match(dev, dev->driver)); - else - return driver->driver.probe(dev); + return driver->probe(fw_unit(dev), unit_match(dev, dev->driver)); } static int fw_unit_remove(struct device *dev) @@ -205,10 +202,7 @@ static int fw_unit_remove(struct device *dev) struct fw_driver *driver = container_of(dev->driver, struct fw_driver, driver); - if (driver->remove) - return driver->remove(fw_unit(dev)), 0; - else - return driver->driver.remove(dev); + return driver->remove(fw_unit(dev)), 0; } static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size) -- GitLab From 9d5e2a023eee96b2326f9b0830a753b400917280 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 9 Jun 2013 09:41:23 -0700 Subject: [PATCH 0805/2900] MAINTAINERS: Update email address for Anton Vorontsov Old email addresses seem to gradually stop working so people are getting bounces. This patch updates my email address. Suggested-by: Andy Shevchenko Signed-off-by: Anton Vorontsov --- MAINTAINERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f35a259a6564..9e63f919922f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -742,7 +742,7 @@ S: Maintained F: arch/arm/mach-highbank/ ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT -M: Anton Vorontsov +M: Anton Vorontsov S: Maintained F: arch/arm/mach-cns3xxx/ T: git git://git.infradead.org/users/cbou/linux-cns3xxx.git @@ -6314,7 +6314,7 @@ F: include/linux/timer* F: kernel/*timer* POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS -M: Anton Vorontsov +M: Anton Vorontsov M: David Woodhouse T: git git://git.infradead.org/battery-2.6.git S: Maintained @@ -6424,7 +6424,7 @@ S: Maintained F: drivers/block/ps3vram.c PSTORE FILESYSTEM -M: Anton Vorontsov +M: Anton Vorontsov M: Colin Cross M: Kees Cook M: Tony Luck @@ -7122,7 +7122,7 @@ F: drivers/mmc/host/sdhci.* F: drivers/mmc/host/sdhci-pltfm.[ch] SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF) -M: Anton Vorontsov +M: Anton Vorontsov L: linuxppc-dev@lists.ozlabs.org L: linux-mmc@vger.kernel.org S: Maintained -- GitLab From e24142178fc2f60824af4312d326edacdcd667a3 Mon Sep 17 00:00:00 2001 From: Andrew Chew Date: Thu, 6 Jun 2013 14:12:43 -0700 Subject: [PATCH 0806/2900] tps65090-charger: Fix AC detect The VACG interrupt was not being enabled. Thus, interrupts were never generated when AC status changes. In addition, interrupts were never cleared after taking and processing the interrupt. Added the register offset for the INTR_MASK register, since this is needed to unmask the VACG interrupt. Enabled the VACG interrupt in tps65090_config_charger(). Cleared interrupts after processing, in tps65090_charger_isr(). Also removed unused variable "enable" in tps65090_enable_charging(), and fixed a typo in one of the dev_err() prints. Signed-off-by: Andrew Chew Tested-by: Rhyland Klein Acked-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/tps65090-charger.c | 35 +++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index 77ab8561fa34..e628f9813e08 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c @@ -27,6 +27,7 @@ #include #define TPS65090_REG_INTR_STS 0x00 +#define TPS65090_REG_INTR_MASK 0x02 #define TPS65090_REG_CG_CTRL0 0x04 #define TPS65090_REG_CG_CTRL1 0x05 #define TPS65090_REG_CG_CTRL2 0x06 @@ -67,8 +68,7 @@ static int tps65090_low_chrg_current(struct tps65090_charger *charger) return 0; } -static int tps65090_enable_charging(struct tps65090_charger *charger, - uint8_t enable) +static int tps65090_enable_charging(struct tps65090_charger *charger) { int ret; uint8_t ctrl0 = 0; @@ -84,7 +84,7 @@ static int tps65090_enable_charging(struct tps65090_charger *charger, ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL0, (ctrl0 | TPS65090_CHARGER_ENABLE)); if (ret < 0) { - dev_err(charger->dev, "%s(): error reading in register 0x%x\n", + dev_err(charger->dev, "%s(): error writing in register 0x%x\n", __func__, TPS65090_REG_CG_CTRL0); return ret; } @@ -93,6 +93,7 @@ static int tps65090_enable_charging(struct tps65090_charger *charger, static int tps65090_config_charger(struct tps65090_charger *charger) { + uint8_t intrmask = 0; int ret; if (charger->pdata->enable_low_current_chrg) { @@ -104,6 +105,23 @@ static int tps65090_config_charger(struct tps65090_charger *charger) } } + /* Enable the VACG interrupt for AC power detect */ + ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_MASK, + &intrmask); + if (ret < 0) { + dev_err(charger->dev, "%s(): error reading in register 0x%x\n", + __func__, TPS65090_REG_INTR_MASK); + return ret; + } + + ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_MASK, + (intrmask | TPS65090_VACG)); + if (ret < 0) { + dev_err(charger->dev, "%s(): error writing in register 0x%x\n", + __func__, TPS65090_REG_CG_CTRL0); + return ret; + } + return 0; } @@ -146,7 +164,7 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id) } if (intrsts & TPS65090_VACG) { - ret = tps65090_enable_charging(charger, 1); + ret = tps65090_enable_charging(charger); if (ret < 0) return IRQ_HANDLED; charger->ac_online = 1; @@ -154,6 +172,13 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id) charger->ac_online = 0; } + /* Clear interrupts. */ + ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_STS, 0x00); + if (ret < 0) { + dev_err(charger->dev, "%s(): Error in writing reg 0x%x\n", + __func__, TPS65090_REG_INTR_STS); + } + if (charger->prev_ac_online != charger->ac_online) power_supply_changed(&charger->ac); @@ -270,7 +295,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) } if (status1 != 0) { - ret = tps65090_enable_charging(cdata, 1); + ret = tps65090_enable_charging(cdata); if (ret < 0) { dev_err(cdata->dev, "error enabling charger\n"); goto fail_free_irq; -- GitLab From e5409cbd8c0bf44f65e7528635cf05ed298e0c61 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 6 Jun 2013 18:25:12 -0700 Subject: [PATCH 0807/2900] charger-manager: Add missing newlines, fix a couple of typos, add pr_fmt Make sure that dev_ calls are newline terminated. Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt to prefix all pr_ calls with "charger-manager: " Fix a couple of typos. Fix formats with terminating n that should be \n. Coalesce formats for easier grep. Align arguments to open parenthesis for these dev_ calls. Add missing spaces after coalescing multiple string segments. Signed-off-by: Joe Perches Acked-by: Kees Cook Signed-off-by: Anton Vorontsov --- drivers/power/charger-manager.c | 137 +++++++++++++------------------- 1 file changed, 57 insertions(+), 80 deletions(-) diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 98de1ddce458..ba420292628e 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -12,6 +12,8 @@ * published by the Free Software Foundation. **/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -195,8 +197,8 @@ static bool is_charging(struct charger_manager *cm) cm->charger_stat[i], POWER_SUPPLY_PROP_ONLINE, &val); if (ret) { - dev_warn(cm->dev, "Cannot read ONLINE value from %s.\n", - cm->desc->psy_charger_stat[i]); + dev_warn(cm->dev, "Cannot read ONLINE value from %s\n", + cm->desc->psy_charger_stat[i]); continue; } if (val.intval == 0) @@ -210,8 +212,8 @@ static bool is_charging(struct charger_manager *cm) cm->charger_stat[i], POWER_SUPPLY_PROP_STATUS, &val); if (ret) { - dev_warn(cm->dev, "Cannot read STATUS value from %s.\n", - cm->desc->psy_charger_stat[i]); + dev_warn(cm->dev, "Cannot read STATUS value from %s\n", + cm->desc->psy_charger_stat[i]); continue; } if (val.intval == POWER_SUPPLY_STATUS_FULL || @@ -289,7 +291,7 @@ static bool is_polling_required(struct charger_manager *cm) return is_charging(cm); default: dev_warn(cm->dev, "Incorrect polling_mode (%d)\n", - cm->desc->polling_mode); + cm->desc->polling_mode); } return false; @@ -331,9 +333,8 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) err = regulator_enable(desc->charger_regulators[i].consumer); if (err < 0) { - dev_warn(cm->dev, - "Cannot enable %s regulator\n", - desc->charger_regulators[i].regulator_name); + dev_warn(cm->dev, "Cannot enable %s regulator\n", + desc->charger_regulators[i].regulator_name); } } } else { @@ -350,9 +351,8 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) err = regulator_disable(desc->charger_regulators[i].consumer); if (err < 0) { - dev_warn(cm->dev, - "Cannot disable %s regulator\n", - desc->charger_regulators[i].regulator_name); + dev_warn(cm->dev, "Cannot disable %s regulator\n", + desc->charger_regulators[i].regulator_name); } } @@ -365,9 +365,8 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) desc->charger_regulators[i].consumer)) { regulator_force_disable( desc->charger_regulators[i].consumer); - dev_warn(cm->dev, - "Disable regulator(%s) forcibly.\n", - desc->charger_regulators[i].regulator_name); + dev_warn(cm->dev, "Disable regulator(%s) forcibly\n", + desc->charger_regulators[i].regulator_name); } } } @@ -450,7 +449,7 @@ static void uevent_notify(struct charger_manager *cm, const char *event) strncpy(env_str, event, UEVENT_BUF_SIZE); kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE); - dev_info(cm->dev, "%s", event); + dev_info(cm->dev, "%s\n", event); } /** @@ -478,7 +477,7 @@ static void fullbatt_vchk(struct work_struct *work) err = get_batt_uV(cm, &batt_uV); if (err) { - dev_err(cm->dev, "%s: get_batt_uV error(%d).\n", __func__, err); + dev_err(cm->dev, "%s: get_batt_uV error(%d)\n", __func__, err); return; } @@ -486,7 +485,7 @@ static void fullbatt_vchk(struct work_struct *work) if (diff < 0) return; - dev_info(cm->dev, "VBATT dropped %duV after full-batt.\n", diff); + dev_info(cm->dev, "VBATT dropped %duV after full-batt\n", diff); if (diff > desc->fullbatt_vchkdrop_uV) { try_charger_restart(cm); @@ -519,7 +518,7 @@ static int check_charging_duration(struct charger_manager *cm) duration = curr - cm->charging_start_time; if (duration > desc->charging_max_duration_ms) { - dev_info(cm->dev, "Charging duration exceed %lldms", + dev_info(cm->dev, "Charging duration exceed %lldms\n", desc->charging_max_duration_ms); uevent_notify(cm, "Discharging"); try_charger_enable(cm, false); @@ -530,9 +529,9 @@ static int check_charging_duration(struct charger_manager *cm) if (duration > desc->charging_max_duration_ms && is_ext_pwr_online(cm)) { - dev_info(cm->dev, "DisCharging duration exceed %lldms", + dev_info(cm->dev, "Discharging duration exceed %lldms\n", desc->discharging_max_duration_ms); - uevent_notify(cm, "Recharing"); + uevent_notify(cm, "Recharging"); try_charger_enable(cm, true); ret = true; } @@ -579,7 +578,7 @@ static bool _cm_monitor(struct charger_manager *cm) */ } else if (!cm->emergency_stop && check_charging_duration(cm)) { dev_dbg(cm->dev, - "Charging/Discharging duration is out of range"); + "Charging/Discharging duration is out of range\n"); /* * Check dropped voltage of battery. If battery voltage is more * dropped than fullbatt_vchkdrop_uV after fully charged state, @@ -595,7 +594,7 @@ static bool _cm_monitor(struct charger_manager *cm) */ } else if (!cm->emergency_stop && is_full_charged(cm) && cm->charger_enabled) { - dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n"); + dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n"); uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]); try_charger_enable(cm, false); @@ -725,7 +724,7 @@ static void fullbatt_handler(struct charger_manager *cm) cm->fullbatt_vchk_jiffies_at = 1; out: - dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged.\n"); + dev_info(cm->dev, "EVENT_HANDLE: Battery Fully Charged\n"); uevent_notify(cm, default_event_names[CM_EVENT_BATT_FULL]); } @@ -972,7 +971,7 @@ static bool cm_setup_timer(void) mutex_unlock(&cm_list_mtx); if (wakeup_ms < UINT_MAX && wakeup_ms > 0) { - pr_info("Charger Manager wakeup timer: %u ms.\n", wakeup_ms); + pr_info("Charger Manager wakeup timer: %u ms\n", wakeup_ms); if (rtc_dev) { struct rtc_wkalrm tmp; unsigned long time, now; @@ -1005,8 +1004,7 @@ static bool cm_setup_timer(void) ret = false; } - pr_info("Waking up after %lu secs.\n", - time - now); + pr_info("Waking up after %lu secs\n", time - now); rtc_time_to_tm(time, &tmp.time); rtc_set_alarm(rtc_dev, &tmp); @@ -1101,7 +1099,7 @@ int setup_charger_manager(struct charger_global_desc *gd) g_desc = NULL; if (!gd->rtc_only_wakeup) { - pr_err("The callback rtc_only_wakeup is not given.\n"); + pr_err("The callback rtc_only_wakeup is not given\n"); return -EINVAL; } @@ -1112,7 +1110,7 @@ int setup_charger_manager(struct charger_global_desc *gd) /* Retry at probe. RTC may be not registered yet */ } } else { - pr_warn("No wakeup timer is given for charger manager." + pr_warn("No wakeup timer is given for charger manager. " "In-suspend monitoring won't work.\n"); } @@ -1138,13 +1136,13 @@ static void charger_extcon_work(struct work_struct *work) cable->min_uA, cable->max_uA); if (ret < 0) { pr_err("Cannot set current limit of %s (%s)\n", - cable->charger->regulator_name, cable->name); + cable->charger->regulator_name, cable->name); return; } pr_info("Set current limit of %s : %duA ~ %duA\n", - cable->charger->regulator_name, - cable->min_uA, cable->max_uA); + cable->charger->regulator_name, + cable->min_uA, cable->max_uA); } try_charger_enable(cable->cm, cable->attached); @@ -1210,9 +1208,8 @@ static int charger_extcon_init(struct charger_manager *cm, ret = extcon_register_interest(&cable->extcon_dev, cable->extcon_name, cable->name, &cable->nb); if (ret < 0) { - pr_info("Cannot register extcon_dev for %s(cable: %s).\n", - cable->extcon_name, - cable->name); + pr_info("Cannot register extcon_dev for %s(cable: %s)\n", + cable->extcon_name, cable->name); ret = -EINVAL; } @@ -1243,8 +1240,8 @@ static int charger_manager_register_extcon(struct charger_manager *cm) charger->consumer = regulator_get(cm->dev, charger->regulator_name); if (charger->consumer == NULL) { - dev_err(cm->dev, "Cannot find charger(%s)n", - charger->regulator_name); + dev_err(cm->dev, "Cannot find charger(%s)\n", + charger->regulator_name); ret = -EINVAL; goto err; } @@ -1255,8 +1252,8 @@ static int charger_manager_register_extcon(struct charger_manager *cm) ret = charger_extcon_init(cm, cable); if (ret < 0) { - dev_err(cm->dev, "Cannot initialize charger(%s)n", - charger->regulator_name); + dev_err(cm->dev, "Cannot initialize charger(%s)\n", + charger->regulator_name); goto err; } cable->charger = charger; @@ -1347,10 +1344,8 @@ static ssize_t charger_externally_control_store(struct device *dev, } } else { dev_warn(cm->dev, - "'%s' regulator should be controlled " - "in charger-manager because charger-manager " - "must need at least one charger for charging\n", - charger->regulator_name); + "'%s' regulator should be controlled in charger-manager because charger-manager must need at least one charger for charging\n", + charger->regulator_name); } return count; @@ -1386,8 +1381,6 @@ static int charger_manager_register_sysfs(struct charger_manager *cm) snprintf(buf, 10, "charger.%d", i); str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); if (!str) { - dev_err(cm->dev, "Cannot allocate memory: %s\n", - charger->regulator_name); ret = -ENOMEM; goto err; } @@ -1423,26 +1416,21 @@ static int charger_manager_register_sysfs(struct charger_manager *cm) !chargers_externally_control) chargers_externally_control = 0; - dev_info(cm->dev, "'%s' regulator's externally_control" - "is %d\n", charger->regulator_name, - charger->externally_control); + dev_info(cm->dev, "'%s' regulator's externally_control is %d\n", + charger->regulator_name, charger->externally_control); ret = sysfs_create_group(&cm->charger_psy.dev->kobj, &charger->attr_g); if (ret < 0) { - dev_err(cm->dev, "Cannot create sysfs entry" - "of %s regulator\n", - charger->regulator_name); + dev_err(cm->dev, "Cannot create sysfs entry of %s regulator\n", + charger->regulator_name); ret = -EINVAL; goto err; } } if (chargers_externally_control) { - dev_err(cm->dev, "Cannot register regulator because " - "charger-manager must need at least " - "one charger for charging battery\n"); - + dev_err(cm->dev, "Cannot register regulator because charger-manager must need at least one charger for charging battery\n"); ret = -EINVAL; goto err; } @@ -1463,7 +1451,7 @@ static int charger_manager_probe(struct platform_device *pdev) rtc_dev = rtc_class_open(g_desc->rtc_name); if (IS_ERR_OR_NULL(rtc_dev)) { rtc_dev = NULL; - dev_err(&pdev->dev, "Cannot get RTC %s.\n", + dev_err(&pdev->dev, "Cannot get RTC %s\n", g_desc->rtc_name); ret = -ENODEV; goto err_alloc; @@ -1471,14 +1459,13 @@ static int charger_manager_probe(struct platform_device *pdev) } if (!desc) { - dev_err(&pdev->dev, "No platform data (desc) found.\n"); + dev_err(&pdev->dev, "No platform data (desc) found\n"); ret = -ENODEV; goto err_alloc; } cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL); if (!cm) { - dev_err(&pdev->dev, "Cannot allocate memory.\n"); ret = -ENOMEM; goto err_alloc; } @@ -1487,7 +1474,6 @@ static int charger_manager_probe(struct platform_device *pdev) cm->dev = &pdev->dev; cm->desc = kmemdup(desc, sizeof(struct charger_desc), GFP_KERNEL); if (!cm->desc) { - dev_err(&pdev->dev, "Cannot allocate memory.\n"); ret = -ENOMEM; goto err_alloc_desc; } @@ -1498,33 +1484,28 @@ static int charger_manager_probe(struct platform_device *pdev) * Users may intentionally ignore those two features. */ if (desc->fullbatt_uV == 0) { - dev_info(&pdev->dev, "Ignoring full-battery voltage threshold" - " as it is not supplied."); + dev_info(&pdev->dev, "Ignoring full-battery voltage threshold as it is not supplied\n"); } if (!desc->fullbatt_vchkdrop_ms || !desc->fullbatt_vchkdrop_uV) { - dev_info(&pdev->dev, "Disabling full-battery voltage drop " - "checking mechanism as it is not supplied."); + dev_info(&pdev->dev, "Disabling full-battery voltage drop checking mechanism as it is not supplied\n"); desc->fullbatt_vchkdrop_ms = 0; desc->fullbatt_vchkdrop_uV = 0; } if (desc->fullbatt_soc == 0) { - dev_info(&pdev->dev, "Ignoring full-battery soc(state of" - " charge) threshold as it is not" - " supplied."); + dev_info(&pdev->dev, "Ignoring full-battery soc(state of charge) threshold as it is not supplied\n"); } if (desc->fullbatt_full_capacity == 0) { - dev_info(&pdev->dev, "Ignoring full-battery full capacity" - " threshold as it is not supplied."); + dev_info(&pdev->dev, "Ignoring full-battery full capacity threshold as it is not supplied\n"); } if (!desc->charger_regulators || desc->num_charger_regulators < 1) { ret = -EINVAL; - dev_err(&pdev->dev, "charger_regulators undefined.\n"); + dev_err(&pdev->dev, "charger_regulators undefined\n"); goto err_no_charger; } if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) { - dev_err(&pdev->dev, "No power supply defined.\n"); + dev_err(&pdev->dev, "No power supply defined\n"); ret = -EINVAL; goto err_no_charger_stat; } @@ -1544,9 +1525,8 @@ static int charger_manager_probe(struct platform_device *pdev) cm->charger_stat[i] = power_supply_get_by_name( desc->psy_charger_stat[i]); if (!cm->charger_stat[i]) { - dev_err(&pdev->dev, "Cannot find power supply " - "\"%s\"\n", - desc->psy_charger_stat[i]); + dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", + desc->psy_charger_stat[i]); ret = -ENODEV; goto err_chg_stat; } @@ -1555,7 +1535,7 @@ static int charger_manager_probe(struct platform_device *pdev) cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge); if (!cm->fuel_gauge) { dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", - desc->psy_fuel_gauge); + desc->psy_fuel_gauge); ret = -ENODEV; goto err_chg_stat; } @@ -1575,9 +1555,7 @@ static int charger_manager_probe(struct platform_device *pdev) if (!desc->charging_max_duration_ms || !desc->discharging_max_duration_ms) { - dev_info(&pdev->dev, "Cannot limit charging duration " - "checking mechanism to prevent overcharge/overheat " - "and control discharging duration"); + dev_info(&pdev->dev, "Cannot limit charging duration checking mechanism to prevent overcharge/overheat and control discharging duration\n"); desc->charging_max_duration_ms = 0; desc->discharging_max_duration_ms = 0; } @@ -1598,7 +1576,6 @@ static int charger_manager_probe(struct platform_device *pdev) NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL); if (!cm->charger_psy.properties) { - dev_err(&pdev->dev, "Cannot allocate for psy properties.\n"); ret = -ENOMEM; goto err_chg_stat; } @@ -1636,8 +1613,8 @@ static int charger_manager_probe(struct platform_device *pdev) ret = power_supply_register(NULL, &cm->charger_psy); if (ret) { - dev_err(&pdev->dev, "Cannot register charger-manager with" - " name \"%s\".\n", cm->charger_psy.name); + dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", + cm->charger_psy.name); goto err_register; } @@ -1948,7 +1925,7 @@ void cm_notify_event(struct power_supply *psy, enum cm_event_types type, uevent_notify(cm, msg ? msg : default_event_names[type]); break; default: - dev_err(cm->dev, "%s type not specified.\n", __func__); + dev_err(cm->dev, "%s: type not specified\n", __func__); break; } } -- GitLab From 77f0b9d2ff0c8ff7b36033dfc5b29dab7a0ebd9a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 3 Jun 2013 22:27:17 +0200 Subject: [PATCH 0808/2900] pwm: devm: alloc correct pointer size The allocated object should be the size of what the pointer is pointing to and not the size of the pointer itself. Signed-off-by: Wolfram Sang Reviewed-by: Andy Shevchenko Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 32221cb0cbe7..0cf0f65eb037 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -694,7 +694,7 @@ struct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) { struct pwm_device **ptr, *pwm; - ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL); + ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return ERR_PTR(-ENOMEM); @@ -724,7 +724,7 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np, { struct pwm_device **ptr, *pwm; - ptr = devres_alloc(devm_pwm_release, sizeof(**ptr), GFP_KERNEL); + ptr = devres_alloc(devm_pwm_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return ERR_PTR(-ENOMEM); -- GitLab From ad194288355a9e4b76c7404d3d5ecbeec8c532a9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Jun 2013 13:27:06 +0200 Subject: [PATCH 0809/2900] iwlwifi: mvm: remove iwl_mvm_dbgfs_set_fw_dbg_log declaration This function doesn't actually exist, remove its declaration. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e10aae71038..ad39a22f79fa 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -689,16 +689,11 @@ void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, struct iwl_beacon_filter_cmd *cmd); -int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm); #else static inline void iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, struct iwl_beacon_filter_cmd *cmd) {} -static inline int iwl_mvm_dbgfs_set_fw_dbg_log(struct iwl_mvm *mvm) -{ - return 0; -} #endif int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -- GitLab From 6e7582bf35b8a5a330fd08b398ae445bac86917a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 17 May 2013 14:45:08 +0000 Subject: [PATCH 0810/2900] MIPS: PowerTV: use free_reserved_area() to simplify code Use common help function free_reserved_area() to simplify code. Signed-off-by: Jiang Liu Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: Andrew Morton Cc: Jiang Liu Cc: David Rientjes Cc: Wen Congyang Cc: Mel Gorman Cc: Minchan Kim Cc: KAMEZAWA Hiroyuki Cc: Michal Hocko Cc: James Bottomley Cc: Sergei Shtylyov Cc: David Howells Cc: Mark Salter Cc: Jianguo Wu Cc: linux-mm@kvack.org Cc: linux-arch@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5248/ Signed-off-by: Ralf Baechle --- arch/mips/powertv/asic/asic_devices.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c index d38b095fd0d0..9f64c2387808 100644 --- a/arch/mips/powertv/asic/asic_devices.c +++ b/arch/mips/powertv/asic/asic_devices.c @@ -529,17 +529,8 @@ EXPORT_SYMBOL(asic_resource_get); */ void platform_release_memory(void *ptr, int size) { - unsigned long addr; - unsigned long end; - - addr = ((unsigned long)ptr + (PAGE_SIZE - 1)) & PAGE_MASK; - end = ((unsigned long)ptr + size) & PAGE_MASK; - - for (; addr < end; addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(__va(addr))); - init_page_count(virt_to_page(__va(addr))); - free_page((unsigned long)__va(addr)); - } + free_reserved_area((unsigned long)ptr, (unsigned long)(ptr + size), + -1, NULL); } EXPORT_SYMBOL(platform_release_memory); -- GitLab From 9ddebc46e70b434e485060f7c1b53c5b848a6c8c Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 22 May 2013 15:10:46 +0000 Subject: [PATCH 0811/2900] MIPS: OCTEON: Rename Kconfig CAVIUM_OCTEON_REFERENCE_BOARD to CAVIUM_OCTEON_SOC CAVIUM_OCTEON_SOC most place we used to use CPU_CAVIUM_OCTEON. This allows us to CPU_CAVIUM_OCTEON in places where we have no OCTEON SOC. Remove CAVIUM_OCTEON_SIMULATOR as it doesn't really do anything, we can get the same configuration with CAVIUM_OCTEON_SOC. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: linux-ide@vger.kernel.org Cc: linux-edac@vger.kernel.org Cc: linux-i2c@vger.kernel.org Cc: netdev@vger.kernel.org Cc: spi-devel-general@lists.sourceforge.net Cc: devel@driverdev.osuosl.org Cc: linux-usb@vger.kernel.org Acked-by: Greg Kroah-Hartman Acked-by: Wolfram Sang Acked-by: Mauro Carvalho Chehab Patchwork: https://patchwork.linux-mips.org/patch/5295/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 19 ++----------------- arch/mips/cavium-octeon/Kconfig | 6 +++++- arch/mips/cavium-octeon/Platform | 8 ++++---- arch/mips/configs/cavium_octeon_defconfig | 2 +- arch/mips/pci/Makefile | 4 ++-- drivers/ata/Kconfig | 2 +- drivers/char/hw_random/Kconfig | 2 +- drivers/edac/Kconfig | 6 +++--- drivers/i2c/busses/Kconfig | 2 +- drivers/net/ethernet/octeon/Kconfig | 2 +- drivers/net/phy/Kconfig | 2 +- drivers/spi/Kconfig | 2 +- drivers/staging/octeon/Kconfig | 2 +- drivers/usb/host/Kconfig | 4 ++-- drivers/watchdog/Kconfig | 2 +- 15 files changed, 27 insertions(+), 38 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7a58ab933b20..ade99730ef3b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -735,23 +735,8 @@ config WR_PPMC This enables support for the Wind River MIPS32 4KC PPMC evaluation board, which is based on GT64120 bridge chip. -config CAVIUM_OCTEON_SIMULATOR - bool "Cavium Networks Octeon Simulator" - select CEVT_R4K - select 64BIT_PHYS_ADDR - select DMA_COHERENT - select SYS_SUPPORTS_64BIT_KERNEL - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_HOTPLUG_CPU - select SYS_HAS_CPU_CAVIUM_OCTEON - select HOLES_IN_ZONE - help - The Octeon simulator is software performance model of the Cavium - Octeon Processor. It supports simulating Octeon processors on x86 - hardware. - -config CAVIUM_OCTEON_REFERENCE_BOARD - bool "Cavium Networks Octeon reference board" +config CAVIUM_OCTEON_SOC + bool "Cavium Networks Octeon SoC based boards" select CEVT_R4K select 64BIT_PHYS_ADDR select DMA_COHERENT diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index 75a6df7fd265..a12444a5f1b5 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -10,6 +10,10 @@ config CAVIUM_CN63XXP1 non-CN63XXP1 hardware, so it is recommended to select "n" unless it is known the workarounds are needed. +endif # CPU_CAVIUM_OCTEON + +if CAVIUM_OCTEON_SOC + config CAVIUM_OCTEON_2ND_KERNEL bool "Build the kernel to be used as a 2nd kernel on the same chip" default "n" @@ -103,4 +107,4 @@ config OCTEON_ILM To compile this driver as a module, choose M here. The module will be called octeon-ilm -endif # CPU_CAVIUM_OCTEON +endif # CAVIUM_OCTEON_SOC diff --git a/arch/mips/cavium-octeon/Platform b/arch/mips/cavium-octeon/Platform index 1e43ccf1a792..8a301cb12d68 100644 --- a/arch/mips/cavium-octeon/Platform +++ b/arch/mips/cavium-octeon/Platform @@ -1,11 +1,11 @@ # # Cavium Octeon # -platform-$(CONFIG_CPU_CAVIUM_OCTEON) += cavium-octeon/ -cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += \ +platform-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon/ +cflags-$(CONFIG_CAVIUM_OCTEON_SOC) += \ -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000 +load-$(CONFIG_CAVIUM_OCTEON_SOC) += 0xffffffff84100000 else -load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 +load-$(CONFIG_CAVIUM_OCTEON_SOC) += 0xffffffff81100000 endif diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index 014ba4bbba7d..1888e5f4d598 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig @@ -1,4 +1,4 @@ -CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y +CONFIG_CAVIUM_OCTEON_SOC=y CONFIG_CAVIUM_CN63XXP1=y CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 CONFIG_SPARSEMEM_MANUAL=y diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 2cb1d315d225..fa3bcd233138 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -54,10 +54,10 @@ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o -obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o +obj-$(CONFIG_CAVIUM_OCTEON_SOC) += pci-octeon.o pcie-octeon.o obj-$(CONFIG_CPU_XLR) += pci-xlr.o obj-$(CONFIG_CPU_XLP) += pci-xlp.o ifdef CONFIG_PCI_MSI -obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o +obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o endif diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index a5a3ebcbdd2c..dc20774bd647 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -160,7 +160,7 @@ config PDC_ADMA config PATA_OCTEON_CF tristate "OCTEON Boot Bus Compact Flash support" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC help This option enables a polled compact flash driver for use with compact flash cards attached to the OCTEON boot bus. diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 2f9dbf7568fb..40a865449f35 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -167,7 +167,7 @@ config HW_RANDOM_OMAP config HW_RANDOM_OCTEON tristate "Octeon Random Number Generator support" - depends on HW_RANDOM && CPU_CAVIUM_OCTEON + depends on HW_RANDOM && CAVIUM_OCTEON_SOC default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index e443f2c1dfd1..923d2e82a289 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -349,21 +349,21 @@ config EDAC_OCTEON_PC config EDAC_OCTEON_L2C tristate "Cavium Octeon Secondary Caches (L2C)" - depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON + depends on EDAC_MM_EDAC && CAVIUM_OCTEON_SOC help Support for error detection and correction on the Cavium Octeon family of SOCs. config EDAC_OCTEON_LMC tristate "Cavium Octeon DRAM Memory Controller (LMC)" - depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON + depends on EDAC_MM_EDAC && CAVIUM_OCTEON_SOC help Support for error detection and correction on the Cavium Octeon family of SOCs. config EDAC_OCTEON_PCI tristate "Cavium Octeon PCI Controller" - depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON + depends on EDAC_MM_EDAC && PCI && CAVIUM_OCTEON_SOC help Support for error detection and correction on the Cavium Octeon family of SOCs. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 631736e2e7ed..a8fff7700624 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -726,7 +726,7 @@ config I2C_VERSATILE config I2C_OCTEON tristate "Cavium OCTEON I2C bus support" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC help Say yes if you want to support the I2C serial bus on Cavium OCTEON SOC. diff --git a/drivers/net/ethernet/octeon/Kconfig b/drivers/net/ethernet/octeon/Kconfig index 3de52ffd2872..a7aa28054cc1 100644 --- a/drivers/net/ethernet/octeon/Kconfig +++ b/drivers/net/ethernet/octeon/Kconfig @@ -4,7 +4,7 @@ config OCTEON_MGMT_ETHERNET tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC select PHYLIB select MDIO_OCTEON default y diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 1e11f2bfd9ce..84461e8824f7 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -135,7 +135,7 @@ config MDIO_GPIO config MDIO_OCTEON tristate "Support for MDIO buses on Octeon SOCs" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC default y help diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 92a9345d7a6b..20158978866f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -266,7 +266,7 @@ config SPI_OC_TINY config SPI_OCTEON tristate "Cavium OCTEON SPI controller" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC help SPI host driver for the hardware found on some Cavium OCTEON SOCs. diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 9493128e5fd2..6e1d5f8d3ec1 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,6 +1,6 @@ config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CPU_CAVIUM_OCTEON && NETDEVICES + depends on CAVIUM_OCTEON_SOC && NETDEVICES select PHYLIB select MDIO_OCTEON help diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 344d5e2f87d7..54c121580738 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -285,7 +285,7 @@ config USB_EHCI_HCD_PLATFORM config USB_OCTEON_EHCI bool "Octeon on-chip EHCI support" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC default n select USB_EHCI_BIG_ENDIAN_MMIO help @@ -480,7 +480,7 @@ config USB_OHCI_HCD_PLATFORM config USB_OCTEON_OHCI bool "Octeon on-chip OHCI support" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC default USB_OCTEON_EHCI select USB_OHCI_BIG_ENDIAN_MMIO select USB_OHCI_LITTLE_ENDIAN diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e89fc3133972..9d03af1c596f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1072,7 +1072,7 @@ config TXX9_WDT config OCTEON_WDT tristate "Cavium OCTEON SOC family Watchdog Timer" - depends on CPU_CAVIUM_OCTEON + depends on CAVIUM_OCTEON_SOC default y select EXPORT_UASM if OCTEON_WDT = m help -- GitLab From 02a49d5144c58a2b9826946934533a7a9f28c2ec Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 22 May 2013 20:46:23 +0000 Subject: [PATCH 0812/2900] MIPS: Octeon: Remove vestiges of CONFIG_CAVIUM_DECODE_RSL This config option doesn't exist any more, remove the leftover code for it too. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5302/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 01b1b3f94feb..0acc8ef86907 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -40,12 +40,6 @@ #include #include -#ifdef CONFIG_CAVIUM_DECODE_RSL -extern void cvmx_interrupt_rsl_decode(void); -extern int __cvmx_interrupt_ecc_report_single_bit_errors; -extern void cvmx_interrupt_rsl_enable(void); -#endif - extern struct plat_smp_ops octeon_smp_ops; #ifdef CONFIG_PCI @@ -462,18 +456,6 @@ static void octeon_halt(void) octeon_kill_core(NULL); } -/** - * Handle all the error condition interrupts that might occur. - * - */ -#ifdef CONFIG_CAVIUM_DECODE_RSL -static irqreturn_t octeon_rlm_interrupt(int cpl, void *dev_id) -{ - cvmx_interrupt_rsl_decode(); - return IRQ_HANDLED; -} -#endif - /** * Return a string representing the system type * @@ -1064,15 +1046,6 @@ void prom_free_prom_memory(void) panic("Core-14449 WAR not in place (%04x).\n" "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).", insn); } -#ifdef CONFIG_CAVIUM_DECODE_RSL - cvmx_interrupt_rsl_enable(); - - /* Add an interrupt handler for general failures. */ - if (request_irq(OCTEON_IRQ_RML, octeon_rlm_interrupt, IRQF_SHARED, - "RML/RSL", octeon_rlm_interrupt)) { - panic("Unable to request_irq(OCTEON_IRQ_RML)"); - } -#endif } int octeon_prune_device_tree(void); -- GitLab From 0ec315121c8391a14bbeb5eecc146c470dfc00cb Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 22 May 2013 20:46:44 +0000 Subject: [PATCH 0813/2900] MIPS: OCTEON: Get rid of CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED When you turn it off, the kernel is unusable, so get rid of the option and always allow unaligned access. The Octeon specific memcpy intentionally does unaligned accesses and it must not fault. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5303/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/Kconfig | 11 ----------- .../asm/mach-cavium-octeon/kernel-entry-init.h | 7 +------ 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index a12444a5f1b5..227705d9d5ae 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -23,17 +23,6 @@ config CAVIUM_OCTEON_2ND_KERNEL with this option to be run at the same time as one built without this option. -config CAVIUM_OCTEON_HW_FIX_UNALIGNED - bool "Enable hardware fixups of unaligned loads and stores" - default "y" - help - Configure the Octeon hardware to automatically fix unaligned loads - and stores. Normally unaligned accesses are fixed using a kernel - exception handler. This option enables the hardware automatic fixups, - which requires only an extra 3 cycles. Disable this option if you - are running code that relies on address exceptions on unaligned - accesses. - config CAVIUM_OCTEON_CVMSEG_SIZE int "Number of L1 cache lines reserved for CVMSEG memory" range 0 54 diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h index 1e7dbb192657..1668ee57acb9 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h @@ -34,15 +34,10 @@ ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE dmtc0 v0, CP0_CVMMEMCTL_REG # Write the cavium mem control register dmfc0 v0, CP0_CVMCTL_REG # Read the cavium control register -#ifdef CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED # Disable unaligned load/store support but leave HW fixup enabled + # Needed for octeon specific memcpy or v0, v0, 0x5001 xor v0, v0, 0x1001 -#else - # Disable unaligned load/store and HW fixup support - or v0, v0, 0x5001 - xor v0, v0, 0x5001 -#endif # Read the processor ID register mfc0 v1, CP0_PRID_REG # Disable instruction prefetching (Octeon Pass1 errata) -- GitLab From 90a6fb120d9c039b108d37405b0e8ba2258403bf Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 26 May 2013 06:51:49 +0000 Subject: [PATCH 0814/2900] MIPS: Lantiq: Use strlcpy() instead of strncpy(). 'compatible' is used by strlen() in __of_device_is_compatible(). Ensure strings are always '\0' terminated. 'of_ids is not a structure in "include/uapi/*", so no need to initialize it completly; using strlcpy() instead of strncpy() will do. Signed-off-by: Chen Gang Acked-by: John Crispin Cc: linux-mips@linux-mips.org Cc: Linux-Arch Patchwork: https://patchwork.linux-mips.org/patch/5329/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/prom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c index 9f9e875967aa..49c460370285 100644 --- a/arch/mips/lantiq/prom.c +++ b/arch/mips/lantiq/prom.c @@ -112,7 +112,7 @@ int __init plat_of_setup(void) if (!of_have_populated_dt()) panic("device tree not present"); - strncpy(of_ids[0].compatible, soc_info.compatible, + strlcpy(of_ids[0].compatible, soc_info.compatible, sizeof(of_ids[0].compatible)); strncpy(of_ids[1].compatible, "simple-bus", sizeof(of_ids[1].compatible)); -- GitLab From 24b1944fc6b7be857c81f0cb0ff264c57b85ee29 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 26 May 2013 07:01:46 +0000 Subject: [PATCH 0815/2900] MIPS: Ralink: Use strlcpy() instead of strncpy(). 'compatible' is used by strlen() in __of_device_is_compatible(). Ensure strings are always '\0' terminated. 'of_ids is not a structure in "include/uapi/*", so no need to initialize it completly; using strlcpy() instead of strncpy() will do. Signed-off-by: Chen Gang Acked-by: John Crispin Cc: juhosg@openwrt.org Cc: linux-mips@linux-mips.org Cc: Linux-Arch Patchwork: https://patchwork.linux-mips.org/patch/5330/ Signed-off-by: Ralf Baechle --- arch/mips/ralink/of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 6b5f3406f414..f25ea5b45051 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -104,7 +104,7 @@ static int __init plat_of_setup(void) if (!of_have_populated_dt()) panic("device tree not present"); - strncpy(of_ids[0].compatible, soc_info.compatible, len); + strlcpy(of_ids[0].compatible, soc_info.compatible, len); strncpy(of_ids[1].compatible, "palmbus", len); if (of_platform_populate(NULL, of_ids, NULL, NULL)) -- GitLab From 41c8366be83a7c868c5281ad8d9e6715c1564351 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 26 May 2013 07:06:06 +0000 Subject: [PATCH 0816/2900] MIPS: using strlcpy() instead of strncpy() Ensure strings are always '\0' terminated. Or in the next pr_info() shit may hit the fan. Signed-off-by: Chen Gang Acked-by: John Crispin Cc: david.daney@cavium.com Cc: linux-mips@linux-mips.org Cc: Linux-Arch Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5331/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/prom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 5712bb532245..7e954042f252 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -30,7 +30,7 @@ __init void mips_set_machine_name(const char *name) if (name == NULL) return; - strncpy(mips_machine_name, name, sizeof(mips_machine_name)); + strlcpy(mips_machine_name, name, sizeof(mips_machine_name)); pr_info("MIPS: machine is %s\n", mips_get_machine_name()); } -- GitLab From e7f3b48af7be9f8007a224663a5b91340626fed5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 29 May 2013 01:02:18 +0200 Subject: [PATCH 0817/2900] MIPS: Cleanup flags in syscall flags handlers. This will simplify further modifications. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/thread_info.h | 2 ++ arch/mips/kernel/scall32-o32.S | 2 +- arch/mips/kernel/scall64-64.S | 2 +- arch/mips/kernel/scall64-n32.S | 2 +- arch/mips/kernel/scall64-o32.S | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 895320e25662..cdea4f65b944 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -131,6 +131,8 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_FPUBOUND (1< yes diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index 97a5909a61cf..be6627ead619 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -54,7 +54,7 @@ NESTED(handle_sys64, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, syscall_trace_entry diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index edcb6594e7b5..cab150789c8d 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -47,7 +47,7 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, n32_syscall_trace_entry diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 74f485d3c0ef..37605dc8eef7 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -81,7 +81,7 @@ NESTED(handle_sys, PT_SIZE, sp) PTR 4b, bad_stack .previous - li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, trace_a_syscall -- GitLab From c3fc5cd5c5a5f4738776a965a020a32c1a37c8fd Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 29 May 2013 01:07:19 +0200 Subject: [PATCH 0818/2900] MIPS: Implement HAVE_CONTEXT_TRACKING. This enables support for CONFIG_NO_HZ_FULL. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + arch/mips/include/asm/thread_info.h | 11 +++-- arch/mips/kernel/cpu-bugs64.c | 5 ++ arch/mips/kernel/ptrace.c | 12 +++++ arch/mips/kernel/signal.c | 5 ++ arch/mips/kernel/traps.c | 74 +++++++++++++++++++++++------ arch/mips/kernel/unaligned.c | 4 ++ arch/mips/mm/fault.c | 15 +++++- 8 files changed, 108 insertions(+), 19 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ade99730ef3b..87ddac9477fa 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1,6 +1,7 @@ config MIPS bool default y + select HAVE_CONTEXT_TRACKING select HAVE_GENERIC_DMA_COHERENT select HAVE_IDE select HAVE_OPROFILE diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index cdea4f65b944..61215a34acc6 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -109,6 +109,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ +#define TIF_NOHZ 19 /* in adaptive nohz mode */ #define TIF_FIXADE 20 /* Fix address errors in software */ #define TIF_LOGADE 21 /* Log address errors to syslog */ #define TIF_32BIT_REGS 22 /* also implies 16/32 fprs */ @@ -124,6 +125,7 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SECCOMP (1< #include #include #include @@ -171,8 +172,12 @@ static volatile int daddi_ov __cpuinitdata; asmlinkage void __init do_daddi_ov(struct pt_regs *regs) { + enum ctx_state prev_state; + + prev_state = exception_enter(); daddi_ov = 1; regs->cp0_epc += 4; + exception_exit(prev_state); } static inline void check_daddi(void) diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9c6299c733a3..8ae1ebef8b71 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -15,6 +15,7 @@ * binaries. */ #include +#include #include #include #include @@ -534,6 +535,8 @@ static inline int audit_arch(void) */ asmlinkage void syscall_trace_enter(struct pt_regs *regs) { + user_exit(); + /* do the secure computing check first */ secure_computing_strict(regs->regs[2]); @@ -570,6 +573,13 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs) */ asmlinkage void syscall_trace_leave(struct pt_regs *regs) { + /* + * We may come here right after calling schedule_user() + * or do_notify_resume(), in which case we can be in RCU + * user mode. + */ + user_exit(); + audit_syscall_exit(regs); if (!(current->ptrace & PT_PTRACED)) @@ -592,4 +602,6 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) send_sig(current->exit_code, current, 1); current->exit_code = 0; } + + user_enter(); } diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index fd3ef2c2afbc..2f285abc76d5 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -8,6 +8,7 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include +#include #include #include #include @@ -573,6 +574,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, { local_irq_enable(); + user_exit(); + /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs); @@ -581,6 +584,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } + + user_enter(); } #ifdef CONFIG_SMP diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a75ae40184aa..beba1e616b6e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -13,6 +13,7 @@ */ #include #include +#include #include #include #include @@ -423,7 +424,9 @@ asmlinkage void do_be(struct pt_regs *regs) const struct exception_table_entry *fixup = NULL; int data = regs->cp0_cause & 4; int action = MIPS_BE_FATAL; + enum ctx_state prev_state; + prev_state = exception_enter(); /* XXX For now. Fixme, this searches the wrong table ... */ if (data && !user_mode(regs)) fixup = search_dbe_tables(exception_epc(regs)); @@ -436,11 +439,11 @@ asmlinkage void do_be(struct pt_regs *regs) switch (action) { case MIPS_BE_DISCARD: - return; + goto out; case MIPS_BE_FIXUP: if (fixup) { regs->cp0_epc = fixup->nextinsn; - return; + goto out; } break; default: @@ -455,10 +458,13 @@ asmlinkage void do_be(struct pt_regs *regs) field, regs->cp0_epc, field, regs->regs[31]); if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS) == NOTIFY_STOP) - return; + goto out; die_if_kernel("Oops", regs); force_sig(SIGBUS, current); + +out: + exception_exit(prev_state); } /* @@ -673,8 +679,10 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode) asmlinkage void do_ov(struct pt_regs *regs) { + enum ctx_state prev_state; siginfo_t info; + prev_state = exception_enter(); die_if_kernel("Integer overflow", regs); info.si_code = FPE_INTOVF; @@ -682,6 +690,7 @@ asmlinkage void do_ov(struct pt_regs *regs) info.si_errno = 0; info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); + exception_exit(prev_state); } int process_fpemu_return(int sig, void __user *fault_addr) @@ -713,11 +722,13 @@ int process_fpemu_return(int sig, void __user *fault_addr) */ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { + enum ctx_state prev_state; siginfo_t info = {0}; + prev_state = exception_enter(); if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE) == NOTIFY_STOP) - return; + goto out; die_if_kernel("FP exception in kernel code", regs); if (fcr31 & FPU_CSR_UNI_X) { @@ -753,7 +764,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) /* If something went wrong, signal */ process_fpemu_return(sig, fault_addr); - return; + goto out; } else if (fcr31 & FPU_CSR_INV_X) info.si_code = FPE_FLTINV; else if (fcr31 & FPU_CSR_DIV_X) @@ -770,6 +781,9 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) info.si_errno = 0; info.si_addr = (void __user *) regs->cp0_epc; force_sig_info(SIGFPE, &info, current); + +out: + exception_exit(prev_state); } static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, @@ -835,9 +849,11 @@ static void do_trap_or_bp(struct pt_regs *regs, unsigned int code, asmlinkage void do_bp(struct pt_regs *regs) { unsigned int opcode, bcode; + enum ctx_state prev_state; unsigned long epc; u16 instr[2]; + prev_state = exception_enter(); if (get_isa16_mode(regs->cp0_epc)) { /* Calculate EPC. */ epc = exception_epc(regs); @@ -852,7 +868,7 @@ asmlinkage void do_bp(struct pt_regs *regs) goto out_sigsegv; bcode = (instr[0] >> 6) & 0x3f; do_trap_or_bp(regs, bcode, "Break"); - return; + goto out; } } else { if (__get_user(opcode, (unsigned int __user *) exception_epc(regs))) @@ -876,12 +892,12 @@ asmlinkage void do_bp(struct pt_regs *regs) switch (bcode) { case BRK_KPROBE_BP: if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) - return; + goto out; else break; case BRK_KPROBE_SSTEPBP: if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP) - return; + goto out; else break; default: @@ -889,18 +905,24 @@ asmlinkage void do_bp(struct pt_regs *regs) } do_trap_or_bp(regs, bcode, "Break"); + +out: + exception_exit(prev_state); return; out_sigsegv: force_sig(SIGSEGV, current); + goto out; } asmlinkage void do_tr(struct pt_regs *regs) { u32 opcode, tcode = 0; + enum ctx_state prev_state; u16 instr[2]; unsigned long epc = msk_isa16_mode(exception_epc(regs)); + prev_state = exception_enter(); if (get_isa16_mode(regs->cp0_epc)) { if (__get_user(instr[0], (u16 __user *)(epc + 0)) || __get_user(instr[1], (u16 __user *)(epc + 2))) @@ -918,10 +940,14 @@ asmlinkage void do_tr(struct pt_regs *regs) } do_trap_or_bp(regs, tcode, "Trap"); + +out: + exception_exit(prev_state); return; out_sigsegv: force_sig(SIGSEGV, current); + goto out; } asmlinkage void do_ri(struct pt_regs *regs) @@ -929,17 +955,19 @@ asmlinkage void do_ri(struct pt_regs *regs) unsigned int __user *epc = (unsigned int __user *)exception_epc(regs); unsigned long old_epc = regs->cp0_epc; unsigned long old31 = regs->regs[31]; + enum ctx_state prev_state; unsigned int opcode = 0; int status = -1; + prev_state = exception_enter(); if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL) == NOTIFY_STOP) - return; + goto out; die_if_kernel("Reserved instruction in kernel code", regs); if (unlikely(compute_return_epc(regs) < 0)) - return; + goto out; if (get_isa16_mode(regs->cp0_epc)) { unsigned short mmop[2] = { 0 }; @@ -974,6 +1002,9 @@ asmlinkage void do_ri(struct pt_regs *regs) regs->regs[31] = old31; force_sig(status, current); } + +out: + exception_exit(prev_state); } /* @@ -1040,6 +1071,7 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, asmlinkage void do_cpu(struct pt_regs *regs) { + enum ctx_state prev_state; unsigned int __user *epc; unsigned long old_epc, old31; unsigned int opcode; @@ -1047,6 +1079,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) int status; unsigned long __maybe_unused flags; + prev_state = exception_enter(); die_if_kernel("do_cpu invoked from kernel context!", regs); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; @@ -1060,7 +1093,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) status = -1; if (unlikely(compute_return_epc(regs) < 0)) - return; + goto out; if (get_isa16_mode(regs->cp0_epc)) { unsigned short mmop[2] = { 0 }; @@ -1093,7 +1126,7 @@ asmlinkage void do_cpu(struct pt_regs *regs) force_sig(status, current); } - return; + goto out; case 3: /* @@ -1131,19 +1164,26 @@ asmlinkage void do_cpu(struct pt_regs *regs) mt_ase_fp_affinity(); } - return; + goto out; case 2: raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); - return; + goto out; } force_sig(SIGILL, current); + +out: + exception_exit(prev_state); } asmlinkage void do_mdmx(struct pt_regs *regs) { + enum ctx_state prev_state; + + prev_state = exception_enter(); force_sig(SIGILL, current); + exception_exit(prev_state); } /* @@ -1151,8 +1191,10 @@ asmlinkage void do_mdmx(struct pt_regs *regs) */ asmlinkage void do_watch(struct pt_regs *regs) { + enum ctx_state prev_state; u32 cause; + prev_state = exception_enter(); /* * Clear WP (bit 22) bit of cause register so we don't loop * forever. @@ -1174,13 +1216,16 @@ asmlinkage void do_watch(struct pt_regs *regs) mips_clear_watch_registers(); local_irq_enable(); } + exception_exit(prev_state); } asmlinkage void do_mcheck(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); int multi_match = regs->cp0_status & ST0_TS; + enum ctx_state prev_state; + prev_state = exception_enter(); show_regs(regs); if (multi_match) { @@ -1202,6 +1247,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs) panic("Caught Machine Check exception - %scaused by multiple " "matching entries in the TLB.", (multi_match) ? "" : "not "); + exception_exit(prev_state); } asmlinkage void do_mt(struct pt_regs *regs) diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 203d8857070d..3eaa02aa8ae0 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -72,6 +72,7 @@ * A store crossing a page boundary might be executed only partially. * Undo the partial store in this case. */ +#include #include #include #include @@ -1550,9 +1551,11 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr) } asmlinkage void do_ade(struct pt_regs *regs) { + enum ctx_state prev_state; unsigned int __user *pc; mm_segment_t seg; + prev_state = exception_enter(); perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->cp0_badvaddr); /* @@ -1628,6 +1631,7 @@ asmlinkage void do_ade(struct pt_regs *regs) /* * XXX On return from the signal handler we should advance the epc */ + exception_exit(prev_state); } #ifdef CONFIG_DEBUG_FS diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 0fead53d1c26..85df1cd8d446 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -5,6 +5,7 @@ * * Copyright (C) 1995 - 2000 by Ralf Baechle */ +#include #include #include #include @@ -32,8 +33,8 @@ * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long write, - unsigned long address) +static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long address) { struct vm_area_struct * vma = NULL; struct task_struct *tsk = current; @@ -312,3 +313,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ } #endif } + +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long write, unsigned long address) +{ + enum ctx_state prev_state; + + prev_state = exception_enter(); + __do_page_fault(regs, write, address); + exception_exit(prev_state); +} -- GitLab From cc2588eabbe46820a86e55fccec8b741e15f647f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 4 Jun 2013 07:44:50 -0700 Subject: [PATCH 0819/2900] cw1200: hwio: Remove an unnecessary goto goto after return is wrong. The other code in this block needs to set an error value then goto an error release block. This one doesn't need to release anything and was likely a copy/paste remainder. Signed-off-by: Joe Perches Acked-By: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/hwio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c index 142f45efa204..dad3fb331818 100644 --- a/drivers/net/wireless/cw1200/hwio.c +++ b/drivers/net/wireless/cw1200/hwio.c @@ -178,7 +178,6 @@ int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, if ((buf_len / 2) >= 0x1000) { pr_err("Can't read more than 0xfff words.\n"); return -EINVAL; - goto out; } priv->hwbus_ops->lock(priv->hwbus_priv); -- GitLab From aa63e18e3ddad4eb15d4af34ae66e7f4dcc7a6d0 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 4 Jun 2013 23:37:05 -0400 Subject: [PATCH 0820/2900] cw1200: Sanity-check arguments in copy_from_user() The optional debugfs interface to the vendor's engineering tools wasn't bounds checking at all, which made it trivial to perform a buffer overflow if this interface was compiled in and then explicitly enabled at runtime. This patch checks both the length supplied as part of the data to ensure it is sane, and also the amount of data compared to the remaining buffer space. If either is too large, fail immediately. (This bug was spotted by Dan Carpenter ) Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/debug.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index eb40c9c61a51..1596b7042cbd 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -397,13 +397,13 @@ struct etf_req_msg; static int etf_request(struct cw1200_common *priv, struct etf_req_msg *msg, u32 len); -#define MAX_RX_SZE 2600 +#define MAX_RX_SIZE 2600 struct etf_in_state { struct cw1200_common *priv; - u32 total_len; - u8 buf[MAX_RX_SZE]; - u32 written; + u16 total_len; + u16 written; + u8 buf[MAX_RX_SIZE]; }; static int cw1200_etf_in_open(struct inode *inode, struct file *file) @@ -448,6 +448,11 @@ static ssize_t cw1200_etf_in_write(struct file *file, return -EFAULT; } + if (etf->total_len > MAX_RX_SIZE) { + pr_err("requested length > MAX_RX_SIZE\n"); + return -EINVAL; + } + written += sizeof(etf->total_len); count -= sizeof(etf->total_len); } @@ -455,6 +460,11 @@ static ssize_t cw1200_etf_in_write(struct file *file, if (!count) goto done; + if (count > (etf->total_len - written)) { + pr_err("Tried to write > MAX_RX_SIZE\n"); + return -EINVAL; + } + if (copy_from_user(etf->buf + etf->written, user_buf + written, count)) { pr_err("copy_from_user (payload %zu) failed\n", count); -- GitLab From f28bc92c9530fe39eccfcff392879f19bd234578 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Jun 2013 10:43:00 +0300 Subject: [PATCH 0821/2900] cw1200: read beyond end of array in debug code This has only one caller and rates[] is an array with IEEE80211_TX_MAX_RATES (4) elements. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/txrx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c index 0e40890e1993..a2547473ec5c 100644 --- a/drivers/net/wireless/cw1200/txrx.c +++ b/drivers/net/wireless/cw1200/txrx.c @@ -190,13 +190,12 @@ static void tx_policy_build(const struct cw1200_common *priv, policy->retry_count += retries; } - pr_debug("[TX policy] Policy (%zu): %d:%d, %d:%d, %d:%d, %d:%d, %d:%d\n", + pr_debug("[TX policy] Policy (%zu): %d:%d, %d:%d, %d:%d, %d:%d\n", count, rates[0].idx, rates[0].count, rates[1].idx, rates[1].count, rates[2].idx, rates[2].count, - rates[3].idx, rates[3].count, - rates[4].idx, rates[4].count); + rates[3].idx, rates[3].count); } static inline bool tx_policy_is_equal(const struct tx_policy *wanted, -- GitLab From f7a01cac7305391433d609bd23241e4138e2fb84 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Jun 2013 03:57:46 -0700 Subject: [PATCH 0822/2900] cw1200: handle allocation failure in wsm_event_indication() Check for allocation failures and return -ENOMEM. The caller already expects it. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/wsm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index f3fd9b218724..3ab25f661793 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -929,6 +929,8 @@ static int wsm_event_indication(struct cw1200_common *priv, struct wsm_buf *buf) } event = kzalloc(sizeof(struct cw1200_wsm_event), GFP_KERNEL); + if (!event) + return -ENOMEM; event->evt.id = __le32_to_cpu(WSM_GET32(buf)); event->evt.data = __le32_to_cpu(WSM_GET32(buf)); -- GitLab From ec71997eff2231098212a99934c0fb987a9e6b04 Mon Sep 17 00:00:00 2001 From: Yunlian Jiang Date: Fri, 31 May 2013 14:45:21 -0700 Subject: [PATCH 0823/2900] rtlwifi: initialize local array and set value. GCC 4.8 is spitting out uninitialized-variable warnings against "drivers/net/wireless/rtlwifi/rtl8192de/dm.c". drivers/net/wireless/rtlwifi/rtl8192de/dm.c:941:31: error: 'ofdm_index_old[1]' may be used uninitialized in this function [-Werror=maybe-uninitialized] rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; This patch adds initialization to the variable and properly sets its value. Signed-off-by: Yunlian Jiang Acked-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192de/dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 19a765532603..47875ba09ff8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c @@ -842,7 +842,7 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( long val_y, ele_c = 0; u8 ofdm_index[2]; s8 cck_index = 0; - u8 ofdm_index_old[2]; + u8 ofdm_index_old[2] = {0, 0}; s8 cck_index_old = 0; u8 index; int i; -- GitLab From 10af87c3d99112b3ca279cadd874cd542e4f6699 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 3 Jun 2013 23:39:53 +0200 Subject: [PATCH 0824/2900] rt2x00: rt2x00queue: initialize data_queue fields earlier Support for rt2800 device is broken since my 'rt2x00: rt2x00dev: use rt2x00dev->tx->limit' patch. The changelog of that commit says that the TX data queue is initialized already when the rt2x00lib_probe_hw() function is called. However as Jakub noticed it, this statement is not correct. The queue->limit field is initialized in the rt2x00queue_alloc_entries routine and that is not yet called when rt2x00lib_probe_hw() runs. Because the value of tx->limit contains zero, the driver tries to allocate a kernel fifo with zero size and kfifo_alloc rejects that with -EINVAL. PCI: Enabling device 0000:01:00.0 (0000 -> 0002) ieee80211 phy1: rt2x00_set_rt: Info - RT chipset 3071, rev 021c detected ieee80211 phy1: rt2x00_set_rf: Info - RF chipset 0008 detected ieee80211 phy1: rt2x00lib_probe_dev: Error - Failed to initialize hw rt2800pci: probe of 0000:01:00.0 failed with error -22 Move the data_queue field initialization from the rt2x00queue_alloc_entries routine into the rt2x00queue_init function. The initialization code is not strictly related to the allocation, and the change ensures that the queue_data fields can be used in the probe routines. The patch also introduces a helper function in order to be able to get the correct data_queue_desc structure for a given queue. This helper is only needed temporarily and it will be removed later. Reported-by: Jakub Kicinski Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 44 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 2c12311467a9..5efbbbdca701 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1170,12 +1170,6 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, rt2x00queue_reset(queue); - queue->limit = qdesc->entry_num; - queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); - queue->data_size = qdesc->data_size; - queue->desc_size = qdesc->desc_size; - queue->winfo_size = qdesc->winfo_size; - /* * Allocate all queue entries. */ @@ -1284,9 +1278,38 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) } } +static const struct data_queue_desc * +rt2x00queue_get_qdesc_by_qid(struct rt2x00_dev *rt2x00dev, + enum data_queue_qid qid) +{ + switch (qid) { + case QID_RX: + return rt2x00dev->ops->rx; + + case QID_AC_BE: + case QID_AC_BK: + case QID_AC_VO: + case QID_AC_VI: + return rt2x00dev->ops->tx; + + case QID_BEACON: + return rt2x00dev->ops->bcn; + + case QID_ATIM: + return rt2x00dev->ops->atim; + + default: + break; + } + + return NULL; +} + static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { + const struct data_queue_desc *qdesc; + mutex_init(&queue->status_lock); spin_lock_init(&queue->tx_lock); spin_lock_init(&queue->index_lock); @@ -1297,6 +1320,15 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, queue->aifs = 2; queue->cw_min = 5; queue->cw_max = 10; + + qdesc = rt2x00queue_get_qdesc_by_qid(rt2x00dev, qid); + BUG_ON(!qdesc); + + queue->limit = qdesc->entry_num; + queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); + queue->data_size = qdesc->data_size; + queue->desc_size = qdesc->desc_size; + queue->winfo_size = qdesc->winfo_size; } int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) -- GitLab From 7260aac97447a2b2cb9e8684d1162118c4426354 Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Tue, 4 Jun 2013 22:53:33 +0100 Subject: [PATCH 0825/2900] bcm63xx_enet: implement reset autoneg ethtool callback Implement the rset_nway ethtool callback which uses libphy generic autonegotiation restart function. Signed-off-by: Maxime Bizon Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index e46466cb3627..bc1a9948892b 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1328,6 +1328,20 @@ static void bcm_enet_get_ethtool_stats(struct net_device *netdev, mutex_unlock(&priv->mib_update_lock); } +static int bcm_enet_nway_reset(struct net_device *dev) +{ + struct bcm_enet_priv *priv; + + priv = netdev_priv(dev); + if (priv->has_phy) { + if (!priv->phydev) + return -ENODEV; + return genphy_restart_aneg(priv->phydev); + } + + return -EOPNOTSUPP; +} + static int bcm_enet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -1470,6 +1484,7 @@ static const struct ethtool_ops bcm_enet_ethtool_ops = { .get_strings = bcm_enet_get_strings, .get_sset_count = bcm_enet_get_sset_count, .get_ethtool_stats = bcm_enet_get_ethtool_stats, + .nway_reset = bcm_enet_nway_reset, .get_settings = bcm_enet_get_settings, .set_settings = bcm_enet_set_settings, .get_drvinfo = bcm_enet_get_drvinfo, -- GitLab From 0ae99b5fede6f3a8d252d50bb4aba29544295219 Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Tue, 4 Jun 2013 22:53:34 +0100 Subject: [PATCH 0826/2900] bcm63xx_enet: split DMA channel register accesses The current bcm63xx_enet driver always uses bcmenet_shared_base whenever it needs to access DMA channel configuration space or access the DMA channel state RAM. Split these register in 3 parts to be more accurate: - global DMA configuration - per DMA channel configuration space - per DMA channel state RAM space This is preliminary to support new chips where the global DMA configuration remains the same, but there is a varying number of DMA channels located at a different memory offset. Signed-off-by: Maxime Bizon Signed-off-by: Jonas Gorski Signed-off-by: David S. Miller --- arch/mips/bcm63xx/dev-enet.c | 23 ++- .../include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 +- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 139 +++++++++++------- 3 files changed, 105 insertions(+), 61 deletions(-) diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c index 39c23366c5c7..df5bf6686942 100644 --- a/arch/mips/bcm63xx/dev-enet.c +++ b/arch/mips/bcm63xx/dev-enet.c @@ -19,6 +19,16 @@ static struct resource shared_res[] = { .end = -1, /* filled at runtime */ .flags = IORESOURCE_MEM, }, + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, }; static struct platform_device bcm63xx_enet_shared_device = { @@ -110,10 +120,15 @@ int __init bcm63xx_enet_register(int unit, if (!shared_device_registered) { shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); shared_res[0].end = shared_res[0].start; - if (BCMCPU_IS_6338()) - shared_res[0].end += (RSET_ENETDMA_SIZE / 2) - 1; - else - shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; + shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; + + shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); + shared_res[1].end = shared_res[1].start; + shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1; + + shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); + shared_res[2].end = shared_res[2].start; + shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1; ret = platform_device_register(&bcm63xx_enet_shared_device); if (ret) diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 336228990808..9981f4f0e42f 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -173,7 +173,9 @@ enum bcm63xx_regs_set { #define BCM_6358_RSET_SPI_SIZE 1804 #define BCM_6368_RSET_SPI_SIZE 1804 #define RSET_ENET_SIZE 2048 -#define RSET_ENETDMA_SIZE 2048 +#define RSET_ENETDMA_SIZE 256 +#define RSET_ENETDMAC_SIZE(chans) (16 * (chans)) +#define RSET_ENETDMAS_SIZE(chans) (16 * (chans)) #define RSET_ENETSW_SIZE 65536 #define RSET_UART_SIZE 24 #define RSET_UDC_SIZE 256 diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index bc1a9948892b..edaf76dc2487 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -41,8 +41,8 @@ static int copybreak __read_mostly = 128; module_param(copybreak, int, 0); MODULE_PARM_DESC(copybreak, "Receive copy threshold"); -/* io memory shared between all devices */ -static void __iomem *bcm_enet_shared_base; +/* io registers memory shared between all devices */ +static void __iomem *bcm_enet_shared_base[3]; /* * io helpers to access mac registers @@ -63,13 +63,35 @@ static inline void enet_writel(struct bcm_enet_priv *priv, */ static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off) { - return bcm_readl(bcm_enet_shared_base + off); + return bcm_readl(bcm_enet_shared_base[0] + off); } static inline void enet_dma_writel(struct bcm_enet_priv *priv, u32 val, u32 off) { - bcm_writel(val, bcm_enet_shared_base + off); + bcm_writel(val, bcm_enet_shared_base[0] + off); +} + +static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off) +{ + return bcm_readl(bcm_enet_shared_base[1] + off); +} + +static inline void enet_dmac_writel(struct bcm_enet_priv *priv, + u32 val, u32 off) +{ + bcm_writel(val, bcm_enet_shared_base[1] + off); +} + +static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off) +{ + return bcm_readl(bcm_enet_shared_base[2] + off); +} + +static inline void enet_dmas_writel(struct bcm_enet_priv *priv, + u32 val, u32 off) +{ + bcm_writel(val, bcm_enet_shared_base[2] + off); } /* @@ -353,8 +375,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) bcm_enet_refill_rx(dev); /* kick rx dma */ - enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, - ENETDMA_CHANCFG_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, + ENETDMAC_CHANCFG_REG(priv->rx_chan)); } return processed; @@ -429,10 +451,10 @@ static int bcm_enet_poll(struct napi_struct *napi, int budget) dev = priv->net_dev; /* ack interrupts */ - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IR_REG(priv->rx_chan)); - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IR_REG(priv->tx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->tx_chan)); /* reclaim sent skb */ tx_work_done = bcm_enet_tx_reclaim(dev, 0); @@ -451,10 +473,10 @@ static int bcm_enet_poll(struct napi_struct *napi, int budget) napi_complete(napi); /* restore rx/tx interrupt */ - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IRMASK_REG(priv->rx_chan)); - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->tx_chan)); return rx_work_done; } @@ -497,8 +519,8 @@ static irqreturn_t bcm_enet_isr_dma(int irq, void *dev_id) priv = netdev_priv(dev); /* mask rx/tx interrupts */ - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); napi_schedule(&priv->napi); @@ -557,8 +579,8 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); /* kick tx dma */ - enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, - ENETDMA_CHANCFG_REG(priv->tx_chan)); + enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, + ENETDMAC_CHANCFG_REG(priv->tx_chan)); /* stop queue if no more desc available */ if (!priv->tx_desc_count) @@ -833,8 +855,8 @@ static int bcm_enet_open(struct net_device *dev) /* mask all interrupts and request them */ enet_writel(priv, 0, ENET_IRMASK_REG); - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev); if (ret) @@ -919,28 +941,28 @@ static int bcm_enet_open(struct net_device *dev) } /* write rx & tx ring addresses */ - enet_dma_writel(priv, priv->rx_desc_dma, - ENETDMA_RSTART_REG(priv->rx_chan)); - enet_dma_writel(priv, priv->tx_desc_dma, - ENETDMA_RSTART_REG(priv->tx_chan)); + enet_dmas_writel(priv, priv->rx_desc_dma, + ENETDMAS_RSTART_REG(priv->rx_chan)); + enet_dmas_writel(priv, priv->tx_desc_dma, + ENETDMAS_RSTART_REG(priv->tx_chan)); /* clear remaining state ram for rx & tx channel */ - enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->tx_chan)); - enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->tx_chan)); - enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan)); /* set max rx/tx length */ enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG); enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG); /* set dma maximum burst len */ - enet_dma_writel(priv, BCMENET_DMA_MAXBURST, - ENETDMA_MAXBURST_REG(priv->rx_chan)); - enet_dma_writel(priv, BCMENET_DMA_MAXBURST, - ENETDMA_MAXBURST_REG(priv->tx_chan)); + enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, + ENETDMAC_MAXBURST_REG(priv->rx_chan)); + enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, + ENETDMAC_MAXBURST_REG(priv->tx_chan)); /* set correct transmit fifo watermark */ enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG); @@ -958,26 +980,26 @@ static int bcm_enet_open(struct net_device *dev) val |= ENET_CTL_ENABLE_MASK; enet_writel(priv, val, ENET_CTL_REG); enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); - enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK, - ENETDMA_CHANCFG_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, + ENETDMAC_CHANCFG_REG(priv->rx_chan)); /* watch "mib counters about to overflow" interrupt */ enet_writel(priv, ENET_IR_MIB, ENET_IR_REG); enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG); /* watch "packet transferred" interrupt in rx and tx */ - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IR_REG(priv->rx_chan)); - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IR_REG(priv->tx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->tx_chan)); /* make sure we enable napi before rx interrupt */ napi_enable(&priv->napi); - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IRMASK_REG(priv->rx_chan)); - enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK, - ENETDMA_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->tx_chan)); if (priv->has_phy) phy_start(priv->phydev); @@ -1057,14 +1079,14 @@ static void bcm_enet_disable_dma(struct bcm_enet_priv *priv, int chan) { int limit; - enet_dma_writel(priv, 0, ENETDMA_CHANCFG_REG(chan)); + enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan)); limit = 1000; do { u32 val; - val = enet_dma_readl(priv, ENETDMA_CHANCFG_REG(chan)); - if (!(val & ENETDMA_CHANCFG_EN_MASK)) + val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan)); + if (!(val & ENETDMAC_CHANCFG_EN_MASK)) break; udelay(1); } while (limit--); @@ -1090,8 +1112,8 @@ static int bcm_enet_stop(struct net_device *dev) /* mask all interrupts */ enet_writel(priv, 0, ENET_IRMASK_REG); - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan)); - enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); /* make sure no mib update is scheduled */ cancel_work_sync(&priv->mib_update_task); @@ -1636,7 +1658,7 @@ static int bcm_enet_probe(struct platform_device *pdev) /* stop if shared driver failed, assume driver->probe will be * called in the same order we register devices (correct ?) */ - if (!bcm_enet_shared_base) + if (!bcm_enet_shared_base[0]) return -ENODEV; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1881,14 +1903,19 @@ struct platform_driver bcm63xx_enet_driver = { static int bcm_enet_shared_probe(struct platform_device *pdev) { struct resource *res; + void __iomem *p[3]; + unsigned int i; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base)); - bcm_enet_shared_base = devm_request_and_ioremap(&pdev->dev, res); - if (!bcm_enet_shared_base) - return -ENOMEM; + for (i = 0; i < 3; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + p[i] = devm_ioremap_resource(&pdev->dev, res); + if (!p[i]) + return -ENOMEM; + } + + memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base)); return 0; } -- GitLab From 6f00a0229627ca189529cad3f9154ac2f9e5c7db Mon Sep 17 00:00:00 2001 From: Maxime Bizon Date: Tue, 4 Jun 2013 22:53:35 +0100 Subject: [PATCH 0827/2900] bcm63xx_enet: add support for Broadcom BCM63xx integrated gigabit switch Newer Broadcom BCM63xx SoCs: 6328, 6362 and 6368 have an integrated switch which needs to be driven slightly differently from the traditional external switches. This patch introduces changes in arch/mips/bcm63xx in order to: - register a bcm63xx_enetsw driver instead of bcm63xx_enet driver - update DMA channels configuration & state RAM base addresses - add a new platform data configuration knob to define the number of ports per switch/device and force link on some ports - define the required switch registers On the driver side, the following changes are required: - the switch ports need to be polled to ensure the link is up and running and RX/TX can properly work - basic switch configuration needs to be performed for the switch to forward packets to the CPU - update the MIB counters since the integrated Signed-off-by: Maxime Bizon Signed-off-by: Jonas Gorski Signed-off-by: David S. Miller --- arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 + arch/mips/bcm63xx/dev-enet.c | 113 +- .../asm/mach-bcm63xx/bcm63xx_dev_enet.h | 28 + .../include/asm/mach-bcm63xx/bcm63xx_regs.h | 50 + .../include/asm/mach-bcm63xx/board_bcm963xx.h | 2 + drivers/net/ethernet/broadcom/bcm63xx_enet.c | 995 +++++++++++++++++- drivers/net/ethernet/broadcom/bcm63xx_enet.h | 71 ++ 7 files changed, 1205 insertions(+), 58 deletions(-) diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index a9505c4867e8..9c0ddafafb6c 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -845,6 +845,10 @@ int __init board_register_devices(void) !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr)) bcm63xx_enet_register(1, &board.enet1); + if (board.has_enetsw && + !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr)) + bcm63xx_enetsw_register(&board.enetsw); + if (board.has_usbd) bcm63xx_usbd_register(&board.usbd); diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c index df5bf6686942..6cbaee0f6d70 100644 --- a/arch/mips/bcm63xx/dev-enet.c +++ b/arch/mips/bcm63xx/dev-enet.c @@ -104,6 +104,64 @@ static struct platform_device bcm63xx_enet1_device = { }, }; +static struct resource enetsw_res[] = { + { + /* start & end filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + /* start filled at runtime */ + .flags = IORESOURCE_IRQ, + }, + { + /* start filled at runtime */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct bcm63xx_enetsw_platform_data enetsw_pd; + +static struct platform_device bcm63xx_enetsw_device = { + .name = "bcm63xx_enetsw", + .num_resources = ARRAY_SIZE(enetsw_res), + .resource = enetsw_res, + .dev = { + .platform_data = &enetsw_pd, + }, +}; + +static int __init register_shared(void) +{ + int ret, chan_count; + + if (shared_device_registered) + return 0; + + shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); + shared_res[0].end = shared_res[0].start; + shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; + + if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) + chan_count = 32; + else + chan_count = 16; + + shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); + shared_res[1].end = shared_res[1].start; + shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1; + + shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); + shared_res[2].end = shared_res[2].start; + shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1; + + ret = platform_device_register(&bcm63xx_enet_shared_device); + if (ret) + return ret; + shared_device_registered = 1; + + return 0; +} + int __init bcm63xx_enet_register(int unit, const struct bcm63xx_enet_platform_data *pd) { @@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int unit, if (unit == 1 && BCMCPU_IS_6338()) return -ENODEV; - if (!shared_device_registered) { - shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); - shared_res[0].end = shared_res[0].start; - shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; - - shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC); - shared_res[1].end = shared_res[1].start; - shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1; - - shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS); - shared_res[2].end = shared_res[2].start; - shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1; - - ret = platform_device_register(&bcm63xx_enet_shared_device); - if (ret) - return ret; - shared_device_registered = 1; - } + ret = register_shared(); + if (ret) + return ret; if (unit == 0) { enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0); @@ -175,3 +218,37 @@ int __init bcm63xx_enet_register(int unit, return ret; return 0; } + +int __init +bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd) +{ + int ret; + + if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368()) + return -ENODEV; + + ret = register_shared(); + if (ret) + return ret; + + enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW); + enetsw_res[0].end = enetsw_res[0].start; + enetsw_res[0].end += RSET_ENETSW_SIZE - 1; + enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0); + enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0); + if (!enetsw_res[2].start) + enetsw_res[2].start = -1; + + memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd)); + + if (BCMCPU_IS_6328()) + enetsw_pd.num_ports = ENETSW_PORTS_6328; + else if (BCMCPU_IS_6362() || BCMCPU_IS_6368()) + enetsw_pd.num_ports = ENETSW_PORTS_6368; + + ret = platform_device_register(&bcm63xx_enetsw_device); + if (ret) + return ret; + + return 0; +} diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h index d53f611184b9..118e3c938841 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h @@ -39,7 +39,35 @@ struct bcm63xx_enet_platform_data { int phy_id, int reg, int val)); }; +/* + * on board ethernet switch platform data + */ +#define ENETSW_MAX_PORT 8 +#define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */ +#define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */ + +#define ENETSW_RGMII_PORT0 4 + +struct bcm63xx_enetsw_port { + int used; + int phy_id; + + int bypass_link; + int force_speed; + int force_duplex_full; + + const char *name; +}; + +struct bcm63xx_enetsw_platform_data { + char mac_addr[ETH_ALEN]; + int num_ports; + struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT]; +}; + int __init bcm63xx_enet_register(int unit, const struct bcm63xx_enet_platform_data *pd); +int bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd); + #endif /* ! BCM63XX_DEV_ENET_H_ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 3203fe49b34d..0a2121abb1a6 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -830,10 +830,60 @@ * _REG relative to RSET_ENETSW *************************************************************************/ +/* Port traffic control */ +#define ENETSW_PTCTRL_REG(x) (0x0 + (x)) +#define ENETSW_PTCTRL_RXDIS_MASK (1 << 0) +#define ENETSW_PTCTRL_TXDIS_MASK (1 << 1) + +/* Switch mode register */ +#define ENETSW_SWMODE_REG (0xb) +#define ENETSW_SWMODE_FWD_EN_MASK (1 << 1) + +/* IMP override Register */ +#define ENETSW_IMPOV_REG (0xe) +#define ENETSW_IMPOV_FORCE_MASK (1 << 7) +#define ENETSW_IMPOV_TXFLOW_MASK (1 << 5) +#define ENETSW_IMPOV_RXFLOW_MASK (1 << 4) +#define ENETSW_IMPOV_1000_MASK (1 << 3) +#define ENETSW_IMPOV_100_MASK (1 << 2) +#define ENETSW_IMPOV_FDX_MASK (1 << 1) +#define ENETSW_IMPOV_LINKUP_MASK (1 << 0) + +/* Port override Register */ +#define ENETSW_PORTOV_REG(x) (0x58 + (x)) +#define ENETSW_PORTOV_ENABLE_MASK (1 << 6) +#define ENETSW_PORTOV_TXFLOW_MASK (1 << 5) +#define ENETSW_PORTOV_RXFLOW_MASK (1 << 4) +#define ENETSW_PORTOV_1000_MASK (1 << 3) +#define ENETSW_PORTOV_100_MASK (1 << 2) +#define ENETSW_PORTOV_FDX_MASK (1 << 1) +#define ENETSW_PORTOV_LINKUP_MASK (1 << 0) + +/* MDIO control register */ +#define ENETSW_MDIOC_REG (0xb0) +#define ENETSW_MDIOC_EXT_MASK (1 << 16) +#define ENETSW_MDIOC_REG_SHIFT 20 +#define ENETSW_MDIOC_PHYID_SHIFT 25 +#define ENETSW_MDIOC_RD_MASK (1 << 30) +#define ENETSW_MDIOC_WR_MASK (1 << 31) + +/* MDIO data register */ +#define ENETSW_MDIOD_REG (0xb4) + +/* Global Management Configuration Register */ +#define ENETSW_GMCR_REG (0x200) +#define ENETSW_GMCR_RST_MIB_MASK (1 << 0) + /* MIB register */ #define ENETSW_MIB_REG(x) (0x2800 + (x) * 4) #define ENETSW_MIB_REG_COUNT 47 +/* Jumbo control register port mask register */ +#define ENETSW_JMBCTL_PORT_REG (0x4004) + +/* Jumbo control mib good frame register */ +#define ENETSW_JMBCTL_MAXSIZE_REG (0x4008) + /************************************************************************* * _REG relative to RSET_OHCI_PRIV diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h index 682bcf3b492a..d9aee1a833f3 100644 --- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h +++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h @@ -24,6 +24,7 @@ struct board_info { /* enabled feature/device */ unsigned int has_enet0:1; unsigned int has_enet1:1; + unsigned int has_enetsw:1; unsigned int has_pci:1; unsigned int has_pccard:1; unsigned int has_ohci0:1; @@ -36,6 +37,7 @@ struct board_info { /* ethernet config */ struct bcm63xx_enet_platform_data enet0; struct bcm63xx_enet_platform_data enet1; + struct bcm63xx_enetsw_platform_data enetsw; /* USB config */ struct bcm63xx_usbd_platform_data usbd; diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index edaf76dc2487..fbbfc4acd53f 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -59,8 +59,43 @@ static inline void enet_writel(struct bcm_enet_priv *priv, } /* - * io helpers to access shared registers + * io helpers to access switch registers */ +static inline u32 enetsw_readl(struct bcm_enet_priv *priv, u32 off) +{ + return bcm_readl(priv->base + off); +} + +static inline void enetsw_writel(struct bcm_enet_priv *priv, + u32 val, u32 off) +{ + bcm_writel(val, priv->base + off); +} + +static inline u16 enetsw_readw(struct bcm_enet_priv *priv, u32 off) +{ + return bcm_readw(priv->base + off); +} + +static inline void enetsw_writew(struct bcm_enet_priv *priv, + u16 val, u32 off) +{ + bcm_writew(val, priv->base + off); +} + +static inline u8 enetsw_readb(struct bcm_enet_priv *priv, u32 off) +{ + return bcm_readb(priv->base + off); +} + +static inline void enetsw_writeb(struct bcm_enet_priv *priv, + u8 val, u32 off) +{ + bcm_writeb(val, priv->base + off); +} + + +/* io helpers to access shared registers */ static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off) { return bcm_readl(bcm_enet_shared_base[0] + off); @@ -218,7 +253,6 @@ static int bcm_enet_refill_rx(struct net_device *dev) if (!skb) break; priv->rx_skb[desc_idx] = skb; - p = dma_map_single(&priv->pdev->dev, skb->data, priv->rx_skb_size, DMA_FROM_DEVICE); @@ -321,7 +355,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) } /* recycle packet if it's marked as bad */ - if (unlikely(len_stat & DMADESC_ERR_MASK)) { + if (!priv->enet_is_sw && + unlikely(len_stat & DMADESC_ERR_MASK)) { dev->stats.rx_errors++; if (len_stat & DMADESC_OVSIZE_MASK) @@ -552,6 +587,26 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out_unlock; } + /* pad small packets sent on a switch device */ + if (priv->enet_is_sw && skb->len < 64) { + int needed = 64 - skb->len; + char *data; + + if (unlikely(skb_tailroom(skb) < needed)) { + struct sk_buff *nskb; + + nskb = skb_copy_expand(skb, 0, needed, GFP_ATOMIC); + if (!nskb) { + ret = NETDEV_TX_BUSY; + goto out_unlock; + } + dev_kfree_skb(skb); + skb = nskb; + } + data = skb_put(skb, needed); + memset(data, 0, needed); + } + /* point to the next available desc */ desc = &priv->tx_desc_cpu[priv->tx_curr_desc]; priv->tx_skb[priv->tx_curr_desc] = skb; @@ -959,9 +1014,9 @@ static int bcm_enet_open(struct net_device *dev) enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG); /* set dma maximum burst len */ - enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, + enet_dmac_writel(priv, priv->dma_maxburst, ENETDMAC_MAXBURST_REG(priv->rx_chan)); - enet_dmac_writel(priv, BCMENET_DMA_MAXBURST, + enet_dmac_writel(priv, priv->dma_maxburst, ENETDMAC_MAXBURST_REG(priv->tx_chan)); /* set correct transmit fifo watermark */ @@ -1567,7 +1622,7 @@ static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu) * it's appended */ priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN, - BCMENET_DMA_MAXBURST * 4); + priv->dma_maxburst * 4); return 0; } @@ -1674,6 +1729,9 @@ static int bcm_enet_probe(struct platform_device *pdev) return -ENOMEM; priv = netdev_priv(dev); + priv->enet_is_sw = false; + priv->dma_maxburst = BCMENET_DMA_MAXBURST; + ret = compute_hw_mtu(priv, dev->mtu); if (ret) goto out; @@ -1898,60 +1956,916 @@ struct platform_driver bcm63xx_enet_driver = { }; /* - * reserve & remap memory space shared between all macs + * switch mii access callbacks */ -static int bcm_enet_shared_probe(struct platform_device *pdev) +static int bcmenet_sw_mdio_read(struct bcm_enet_priv *priv, + int ext, int phy_id, int location) { - struct resource *res; - void __iomem *p[3]; - unsigned int i; + u32 reg; + int ret; - memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base)); + spin_lock_bh(&priv->enetsw_mdio_lock); + enetsw_writel(priv, 0, ENETSW_MDIOC_REG); - for (i = 0; i < 3; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - p[i] = devm_ioremap_resource(&pdev->dev, res); - if (!p[i]) - return -ENOMEM; - } + reg = ENETSW_MDIOC_RD_MASK | + (phy_id << ENETSW_MDIOC_PHYID_SHIFT) | + (location << ENETSW_MDIOC_REG_SHIFT); - memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base)); + if (ext) + reg |= ENETSW_MDIOC_EXT_MASK; - return 0; + enetsw_writel(priv, reg, ENETSW_MDIOC_REG); + udelay(50); + ret = enetsw_readw(priv, ENETSW_MDIOD_REG); + spin_unlock_bh(&priv->enetsw_mdio_lock); + return ret; } -static int bcm_enet_shared_remove(struct platform_device *pdev) +static void bcmenet_sw_mdio_write(struct bcm_enet_priv *priv, + int ext, int phy_id, int location, + uint16_t data) { - return 0; + u32 reg; + + spin_lock_bh(&priv->enetsw_mdio_lock); + enetsw_writel(priv, 0, ENETSW_MDIOC_REG); + + reg = ENETSW_MDIOC_WR_MASK | + (phy_id << ENETSW_MDIOC_PHYID_SHIFT) | + (location << ENETSW_MDIOC_REG_SHIFT); + + if (ext) + reg |= ENETSW_MDIOC_EXT_MASK; + + reg |= data; + + enetsw_writel(priv, reg, ENETSW_MDIOC_REG); + udelay(50); + spin_unlock_bh(&priv->enetsw_mdio_lock); +} + +static inline int bcm_enet_port_is_rgmii(int portid) +{ + return portid >= ENETSW_RGMII_PORT0; } /* - * this "shared" driver is needed because both macs share a single - * address space + * enet sw PHY polling */ -struct platform_driver bcm63xx_enet_shared_driver = { - .probe = bcm_enet_shared_probe, - .remove = bcm_enet_shared_remove, - .driver = { - .name = "bcm63xx_enet_shared", - .owner = THIS_MODULE, - }, -}; +static void swphy_poll_timer(unsigned long data) +{ + struct bcm_enet_priv *priv = (struct bcm_enet_priv *)data; + unsigned int i; + + for (i = 0; i < priv->num_ports; i++) { + struct bcm63xx_enetsw_port *port; + int val, j, up, advertise, lpa, lpa2, speed, duplex, media; + int external_phy = bcm_enet_port_is_rgmii(i); + u8 override; + + port = &priv->used_ports[i]; + if (!port->used) + continue; + + if (port->bypass_link) + continue; + + /* dummy read to clear */ + for (j = 0; j < 2; j++) + val = bcmenet_sw_mdio_read(priv, external_phy, + port->phy_id, MII_BMSR); + + if (val == 0xffff) + continue; + + up = (val & BMSR_LSTATUS) ? 1 : 0; + if (!(up ^ priv->sw_port_link[i])) + continue; + + priv->sw_port_link[i] = up; + + /* link changed */ + if (!up) { + dev_info(&priv->pdev->dev, "link DOWN on %s\n", + port->name); + enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK, + ENETSW_PORTOV_REG(i)); + enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK | + ENETSW_PTCTRL_TXDIS_MASK, + ENETSW_PTCTRL_REG(i)); + continue; + } + + advertise = bcmenet_sw_mdio_read(priv, external_phy, + port->phy_id, MII_ADVERTISE); + + lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, + MII_LPA); + + lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, + MII_STAT1000); + + /* figure out media and duplex from advertise and LPA values */ + media = mii_nway_result(lpa & advertise); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + if (lpa2 & LPA_1000FULL) + duplex = 1; + + if (lpa2 & (LPA_1000FULL | LPA_1000HALF)) + speed = 1000; + else { + if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) + speed = 100; + else + speed = 10; + } + + dev_info(&priv->pdev->dev, + "link UP on %s, %dMbps, %s-duplex\n", + port->name, speed, duplex ? "full" : "half"); + + override = ENETSW_PORTOV_ENABLE_MASK | + ENETSW_PORTOV_LINKUP_MASK; + + if (speed == 1000) + override |= ENETSW_IMPOV_1000_MASK; + else if (speed == 100) + override |= ENETSW_IMPOV_100_MASK; + if (duplex) + override |= ENETSW_IMPOV_FDX_MASK; + + enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i)); + enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i)); + } + + priv->swphy_poll.expires = jiffies + HZ; + add_timer(&priv->swphy_poll); +} /* - * entry point + * open callback, allocate dma rings & buffers and start rx operation */ -static int __init bcm_enet_init(void) +static int bcm_enetsw_open(struct net_device *dev) { - int ret; + struct bcm_enet_priv *priv; + struct device *kdev; + int i, ret; + unsigned int size; + void *p; + u32 val; - ret = platform_driver_register(&bcm63xx_enet_shared_driver); - if (ret) - return ret; + priv = netdev_priv(dev); + kdev = &priv->pdev->dev; - ret = platform_driver_register(&bcm63xx_enet_driver); + /* mask all interrupts and request them */ + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + + ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, + IRQF_DISABLED, dev->name, dev); if (ret) - platform_driver_unregister(&bcm63xx_enet_shared_driver); + goto out_freeirq; + + if (priv->irq_tx != -1) { + ret = request_irq(priv->irq_tx, bcm_enet_isr_dma, + IRQF_DISABLED, dev->name, dev); + if (ret) + goto out_freeirq_rx; + } + + /* allocate rx dma ring */ + size = priv->rx_ring_size * sizeof(struct bcm_enet_desc); + p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL); + if (!p) { + dev_err(kdev, "cannot allocate rx ring %u\n", size); + ret = -ENOMEM; + goto out_freeirq_tx; + } + + memset(p, 0, size); + priv->rx_desc_alloc_size = size; + priv->rx_desc_cpu = p; + + /* allocate tx dma ring */ + size = priv->tx_ring_size * sizeof(struct bcm_enet_desc); + p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL); + if (!p) { + dev_err(kdev, "cannot allocate tx ring\n"); + ret = -ENOMEM; + goto out_free_rx_ring; + } + + memset(p, 0, size); + priv->tx_desc_alloc_size = size; + priv->tx_desc_cpu = p; + + priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size, + GFP_KERNEL); + if (!priv->tx_skb) { + dev_err(kdev, "cannot allocate rx skb queue\n"); + ret = -ENOMEM; + goto out_free_tx_ring; + } + + priv->tx_desc_count = priv->tx_ring_size; + priv->tx_dirty_desc = 0; + priv->tx_curr_desc = 0; + spin_lock_init(&priv->tx_lock); + + /* init & fill rx ring with skbs */ + priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size, + GFP_KERNEL); + if (!priv->rx_skb) { + dev_err(kdev, "cannot allocate rx skb queue\n"); + ret = -ENOMEM; + goto out_free_tx_skb; + } + + priv->rx_desc_count = 0; + priv->rx_dirty_desc = 0; + priv->rx_curr_desc = 0; + + /* disable all ports */ + for (i = 0; i < priv->num_ports; i++) { + enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK, + ENETSW_PORTOV_REG(i)); + enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK | + ENETSW_PTCTRL_TXDIS_MASK, + ENETSW_PTCTRL_REG(i)); + + priv->sw_port_link[i] = 0; + } + + /* reset mib */ + val = enetsw_readb(priv, ENETSW_GMCR_REG); + val |= ENETSW_GMCR_RST_MIB_MASK; + enetsw_writeb(priv, val, ENETSW_GMCR_REG); + mdelay(1); + val &= ~ENETSW_GMCR_RST_MIB_MASK; + enetsw_writeb(priv, val, ENETSW_GMCR_REG); + mdelay(1); + + /* force CPU port state */ + val = enetsw_readb(priv, ENETSW_IMPOV_REG); + val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK; + enetsw_writeb(priv, val, ENETSW_IMPOV_REG); + + /* enable switch forward engine */ + val = enetsw_readb(priv, ENETSW_SWMODE_REG); + val |= ENETSW_SWMODE_FWD_EN_MASK; + enetsw_writeb(priv, val, ENETSW_SWMODE_REG); + + /* enable jumbo on all ports */ + enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG); + enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG); + + /* initialize flow control buffer allocation */ + enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, + ENETDMA_BUFALLOC_REG(priv->rx_chan)); + + if (bcm_enet_refill_rx(dev)) { + dev_err(kdev, "cannot allocate rx skb queue\n"); + ret = -ENOMEM; + goto out; + } + + /* write rx & tx ring addresses */ + enet_dmas_writel(priv, priv->rx_desc_dma, + ENETDMAS_RSTART_REG(priv->rx_chan)); + enet_dmas_writel(priv, priv->tx_desc_dma, + ENETDMAS_RSTART_REG(priv->tx_chan)); + + /* clear remaining state ram for rx & tx channel */ + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan)); + + /* set dma maximum burst len */ + enet_dmac_writel(priv, priv->dma_maxburst, + ENETDMAC_MAXBURST_REG(priv->rx_chan)); + enet_dmac_writel(priv, priv->dma_maxburst, + ENETDMAC_MAXBURST_REG(priv->tx_chan)); + + /* set flow control low/high threshold to 1/3 / 2/3 */ + val = priv->rx_ring_size / 3; + enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan)); + val = (priv->rx_ring_size * 2) / 3; + enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan)); + + /* all set, enable mac and interrupts, start dma engine and + * kick rx dma channel + */ + wmb(); + enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, + ENETDMAC_CHANCFG_REG(priv->rx_chan)); + + /* watch "packet transferred" interrupt in rx and tx */ + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IR_REG(priv->tx_chan)); + + /* make sure we enable napi before rx interrupt */ + napi_enable(&priv->napi); + + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, + ENETDMAC_IRMASK_REG(priv->tx_chan)); + + netif_carrier_on(dev); + netif_start_queue(dev); + + /* apply override config for bypass_link ports here. */ + for (i = 0; i < priv->num_ports; i++) { + struct bcm63xx_enetsw_port *port; + u8 override; + port = &priv->used_ports[i]; + if (!port->used) + continue; + + if (!port->bypass_link) + continue; + + override = ENETSW_PORTOV_ENABLE_MASK | + ENETSW_PORTOV_LINKUP_MASK; + + switch (port->force_speed) { + case 1000: + override |= ENETSW_IMPOV_1000_MASK; + break; + case 100: + override |= ENETSW_IMPOV_100_MASK; + break; + case 10: + break; + default: + pr_warn("invalid forced speed on port %s: assume 10\n", + port->name); + break; + } + + if (port->force_duplex_full) + override |= ENETSW_IMPOV_FDX_MASK; + + + enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i)); + enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i)); + } + + /* start phy polling timer */ + init_timer(&priv->swphy_poll); + priv->swphy_poll.function = swphy_poll_timer; + priv->swphy_poll.data = (unsigned long)priv; + priv->swphy_poll.expires = jiffies; + add_timer(&priv->swphy_poll); + return 0; + +out: + for (i = 0; i < priv->rx_ring_size; i++) { + struct bcm_enet_desc *desc; + + if (!priv->rx_skb[i]) + continue; + + desc = &priv->rx_desc_cpu[i]; + dma_unmap_single(kdev, desc->address, priv->rx_skb_size, + DMA_FROM_DEVICE); + kfree_skb(priv->rx_skb[i]); + } + kfree(priv->rx_skb); + +out_free_tx_skb: + kfree(priv->tx_skb); + +out_free_tx_ring: + dma_free_coherent(kdev, priv->tx_desc_alloc_size, + priv->tx_desc_cpu, priv->tx_desc_dma); + +out_free_rx_ring: + dma_free_coherent(kdev, priv->rx_desc_alloc_size, + priv->rx_desc_cpu, priv->rx_desc_dma); + +out_freeirq_tx: + if (priv->irq_tx != -1) + free_irq(priv->irq_tx, dev); + +out_freeirq_rx: + free_irq(priv->irq_rx, dev); + +out_freeirq: + return ret; +} + +/* stop callback */ +static int bcm_enetsw_stop(struct net_device *dev) +{ + struct bcm_enet_priv *priv; + struct device *kdev; + int i; + + priv = netdev_priv(dev); + kdev = &priv->pdev->dev; + + del_timer_sync(&priv->swphy_poll); + netif_stop_queue(dev); + napi_disable(&priv->napi); + del_timer_sync(&priv->rx_timeout); + + /* mask all interrupts */ + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + + /* disable dma & mac */ + bcm_enet_disable_dma(priv, priv->tx_chan); + bcm_enet_disable_dma(priv, priv->rx_chan); + + /* force reclaim of all tx buffers */ + bcm_enet_tx_reclaim(dev, 1); + + /* free the rx skb ring */ + for (i = 0; i < priv->rx_ring_size; i++) { + struct bcm_enet_desc *desc; + + if (!priv->rx_skb[i]) + continue; + + desc = &priv->rx_desc_cpu[i]; + dma_unmap_single(kdev, desc->address, priv->rx_skb_size, + DMA_FROM_DEVICE); + kfree_skb(priv->rx_skb[i]); + } + + /* free remaining allocated memory */ + kfree(priv->rx_skb); + kfree(priv->tx_skb); + dma_free_coherent(kdev, priv->rx_desc_alloc_size, + priv->rx_desc_cpu, priv->rx_desc_dma); + dma_free_coherent(kdev, priv->tx_desc_alloc_size, + priv->tx_desc_cpu, priv->tx_desc_dma); + if (priv->irq_tx != -1) + free_irq(priv->irq_tx, dev); + free_irq(priv->irq_rx, dev); + + return 0; +} + +/* try to sort out phy external status by walking the used_port field + * in the bcm_enet_priv structure. in case the phy address is not + * assigned to any physical port on the switch, assume it is external + * (and yell at the user). + */ +static int bcm_enetsw_phy_is_external(struct bcm_enet_priv *priv, int phy_id) +{ + int i; + + for (i = 0; i < priv->num_ports; ++i) { + if (!priv->used_ports[i].used) + continue; + if (priv->used_ports[i].phy_id == phy_id) + return bcm_enet_port_is_rgmii(i); + } + + printk_once(KERN_WARNING "bcm63xx_enet: could not find a used port with phy_id %i, assuming phy is external\n", + phy_id); + return 1; +} + +/* can't use bcmenet_sw_mdio_read directly as we need to sort out + * external/internal status of the given phy_id first. + */ +static int bcm_enetsw_mii_mdio_read(struct net_device *dev, int phy_id, + int location) +{ + struct bcm_enet_priv *priv; + + priv = netdev_priv(dev); + return bcmenet_sw_mdio_read(priv, + bcm_enetsw_phy_is_external(priv, phy_id), + phy_id, location); +} + +/* can't use bcmenet_sw_mdio_write directly as we need to sort out + * external/internal status of the given phy_id first. + */ +static void bcm_enetsw_mii_mdio_write(struct net_device *dev, int phy_id, + int location, + int val) +{ + struct bcm_enet_priv *priv; + + priv = netdev_priv(dev); + bcmenet_sw_mdio_write(priv, bcm_enetsw_phy_is_external(priv, phy_id), + phy_id, location, val); +} + +static int bcm_enetsw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct mii_if_info mii; + + mii.dev = dev; + mii.mdio_read = bcm_enetsw_mii_mdio_read; + mii.mdio_write = bcm_enetsw_mii_mdio_write; + mii.phy_id = 0; + mii.phy_id_mask = 0x3f; + mii.reg_num_mask = 0x1f; + return generic_mii_ioctl(&mii, if_mii(rq), cmd, NULL); + +} + +static const struct net_device_ops bcm_enetsw_ops = { + .ndo_open = bcm_enetsw_open, + .ndo_stop = bcm_enetsw_stop, + .ndo_start_xmit = bcm_enet_start_xmit, + .ndo_change_mtu = bcm_enet_change_mtu, + .ndo_do_ioctl = bcm_enetsw_ioctl, +}; + + +static const struct bcm_enet_stats bcm_enetsw_gstrings_stats[] = { + { "rx_packets", DEV_STAT(rx_packets), -1 }, + { "tx_packets", DEV_STAT(tx_packets), -1 }, + { "rx_bytes", DEV_STAT(rx_bytes), -1 }, + { "tx_bytes", DEV_STAT(tx_bytes), -1 }, + { "rx_errors", DEV_STAT(rx_errors), -1 }, + { "tx_errors", DEV_STAT(tx_errors), -1 }, + { "rx_dropped", DEV_STAT(rx_dropped), -1 }, + { "tx_dropped", DEV_STAT(tx_dropped), -1 }, + + { "tx_good_octets", GEN_STAT(mib.tx_gd_octets), ETHSW_MIB_RX_GD_OCT }, + { "tx_unicast", GEN_STAT(mib.tx_unicast), ETHSW_MIB_RX_BRDCAST }, + { "tx_broadcast", GEN_STAT(mib.tx_brdcast), ETHSW_MIB_RX_BRDCAST }, + { "tx_multicast", GEN_STAT(mib.tx_mult), ETHSW_MIB_RX_MULT }, + { "tx_64_octets", GEN_STAT(mib.tx_64), ETHSW_MIB_RX_64 }, + { "tx_65_127_oct", GEN_STAT(mib.tx_65_127), ETHSW_MIB_RX_65_127 }, + { "tx_128_255_oct", GEN_STAT(mib.tx_128_255), ETHSW_MIB_RX_128_255 }, + { "tx_256_511_oct", GEN_STAT(mib.tx_256_511), ETHSW_MIB_RX_256_511 }, + { "tx_512_1023_oct", GEN_STAT(mib.tx_512_1023), ETHSW_MIB_RX_512_1023}, + { "tx_1024_1522_oct", GEN_STAT(mib.tx_1024_max), + ETHSW_MIB_RX_1024_1522 }, + { "tx_1523_2047_oct", GEN_STAT(mib.tx_1523_2047), + ETHSW_MIB_RX_1523_2047 }, + { "tx_2048_4095_oct", GEN_STAT(mib.tx_2048_4095), + ETHSW_MIB_RX_2048_4095 }, + { "tx_4096_8191_oct", GEN_STAT(mib.tx_4096_8191), + ETHSW_MIB_RX_4096_8191 }, + { "tx_8192_9728_oct", GEN_STAT(mib.tx_8192_9728), + ETHSW_MIB_RX_8192_9728 }, + { "tx_oversize", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR }, + { "tx_oversize_drop", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR_DISC }, + { "tx_dropped", GEN_STAT(mib.tx_drop), ETHSW_MIB_RX_DROP }, + { "tx_undersize", GEN_STAT(mib.tx_underrun), ETHSW_MIB_RX_UND }, + { "tx_pause", GEN_STAT(mib.tx_pause), ETHSW_MIB_RX_PAUSE }, + + { "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETHSW_MIB_TX_ALL_OCT }, + { "rx_broadcast", GEN_STAT(mib.rx_brdcast), ETHSW_MIB_TX_BRDCAST }, + { "rx_multicast", GEN_STAT(mib.rx_mult), ETHSW_MIB_TX_MULT }, + { "rx_unicast", GEN_STAT(mib.rx_unicast), ETHSW_MIB_TX_MULT }, + { "rx_pause", GEN_STAT(mib.rx_pause), ETHSW_MIB_TX_PAUSE }, + { "rx_dropped", GEN_STAT(mib.rx_drop), ETHSW_MIB_TX_DROP_PKTS }, + +}; + +#define BCM_ENETSW_STATS_LEN \ + (sizeof(bcm_enetsw_gstrings_stats) / sizeof(struct bcm_enet_stats)) + +static void bcm_enetsw_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) +{ + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) { + memcpy(data + i * ETH_GSTRING_LEN, + bcm_enetsw_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + } + break; + } +} + +static int bcm_enetsw_get_sset_count(struct net_device *netdev, + int string_set) +{ + switch (string_set) { + case ETH_SS_STATS: + return BCM_ENETSW_STATS_LEN; + default: + return -EINVAL; + } +} + +static void bcm_enetsw_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + strncpy(drvinfo->driver, bcm_enet_driver_name, 32); + strncpy(drvinfo->version, bcm_enet_driver_version, 32); + strncpy(drvinfo->fw_version, "N/A", 32); + strncpy(drvinfo->bus_info, "bcm63xx", 32); + drvinfo->n_stats = BCM_ENETSW_STATS_LEN; +} + +static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, + u64 *data) +{ + struct bcm_enet_priv *priv; + int i; + + priv = netdev_priv(netdev); + + for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) { + const struct bcm_enet_stats *s; + u32 lo, hi; + char *p; + int reg; + + s = &bcm_enetsw_gstrings_stats[i]; + + reg = s->mib_reg; + if (reg == -1) + continue; + + lo = enetsw_readl(priv, ENETSW_MIB_REG(reg)); + p = (char *)priv + s->stat_offset; + + if (s->sizeof_stat == sizeof(u64)) { + hi = enetsw_readl(priv, ENETSW_MIB_REG(reg + 1)); + *(u64 *)p = ((u64)hi << 32 | lo); + } else { + *(u32 *)p = lo; + } + } + + for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) { + const struct bcm_enet_stats *s; + char *p; + + s = &bcm_enetsw_gstrings_stats[i]; + + if (s->mib_reg == -1) + p = (char *)&netdev->stats + s->stat_offset; + else + p = (char *)priv + s->stat_offset; + + data[i] = (s->sizeof_stat == sizeof(u64)) ? + *(u64 *)p : *(u32 *)p; + } +} + +static void bcm_enetsw_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bcm_enet_priv *priv; + + priv = netdev_priv(dev); + + /* rx/tx ring is actually only limited by memory */ + ering->rx_max_pending = 8192; + ering->tx_max_pending = 8192; + ering->rx_mini_max_pending = 0; + ering->rx_jumbo_max_pending = 0; + ering->rx_pending = priv->rx_ring_size; + ering->tx_pending = priv->tx_ring_size; +} + +static int bcm_enetsw_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bcm_enet_priv *priv; + int was_running; + + priv = netdev_priv(dev); + + was_running = 0; + if (netif_running(dev)) { + bcm_enetsw_stop(dev); + was_running = 1; + } + + priv->rx_ring_size = ering->rx_pending; + priv->tx_ring_size = ering->tx_pending; + + if (was_running) { + int err; + + err = bcm_enetsw_open(dev); + if (err) + dev_close(dev); + } + return 0; +} + +static struct ethtool_ops bcm_enetsw_ethtool_ops = { + .get_strings = bcm_enetsw_get_strings, + .get_sset_count = bcm_enetsw_get_sset_count, + .get_ethtool_stats = bcm_enetsw_get_ethtool_stats, + .get_drvinfo = bcm_enetsw_get_drvinfo, + .get_ringparam = bcm_enetsw_get_ringparam, + .set_ringparam = bcm_enetsw_set_ringparam, +}; + +/* allocate netdevice, request register memory and register device. */ +static int bcm_enetsw_probe(struct platform_device *pdev) +{ + struct bcm_enet_priv *priv; + struct net_device *dev; + struct bcm63xx_enetsw_platform_data *pd; + struct resource *res_mem; + int ret, irq_rx, irq_tx; + + /* stop if shared driver failed, assume driver->probe will be + * called in the same order we register devices (correct ?) + */ + if (!bcm_enet_shared_base[0]) + return -ENODEV; + + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq_rx = platform_get_irq(pdev, 0); + irq_tx = platform_get_irq(pdev, 1); + if (!res_mem || irq_rx < 0) + return -ENODEV; + + ret = 0; + dev = alloc_etherdev(sizeof(*priv)); + if (!dev) + return -ENOMEM; + priv = netdev_priv(dev); + memset(priv, 0, sizeof(*priv)); + + /* initialize default and fetch platform data */ + priv->enet_is_sw = true; + priv->irq_rx = irq_rx; + priv->irq_tx = irq_tx; + priv->rx_ring_size = BCMENET_DEF_RX_DESC; + priv->tx_ring_size = BCMENET_DEF_TX_DESC; + priv->dma_maxburst = BCMENETSW_DMA_MAXBURST; + + pd = pdev->dev.platform_data; + if (pd) { + memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN); + memcpy(priv->used_ports, pd->used_ports, + sizeof(pd->used_ports)); + priv->num_ports = pd->num_ports; + } + + ret = compute_hw_mtu(priv, dev->mtu); + if (ret) + goto out; + + if (!request_mem_region(res_mem->start, resource_size(res_mem), + "bcm63xx_enetsw")) { + ret = -EBUSY; + goto out; + } + + priv->base = ioremap(res_mem->start, resource_size(res_mem)); + if (priv->base == NULL) { + ret = -ENOMEM; + goto out_release_mem; + } + + priv->mac_clk = clk_get(&pdev->dev, "enetsw"); + if (IS_ERR(priv->mac_clk)) { + ret = PTR_ERR(priv->mac_clk); + goto out_unmap; + } + clk_enable(priv->mac_clk); + + priv->rx_chan = 0; + priv->tx_chan = 1; + spin_lock_init(&priv->rx_lock); + + /* init rx timeout (used for oom) */ + init_timer(&priv->rx_timeout); + priv->rx_timeout.function = bcm_enet_refill_rx_timer; + priv->rx_timeout.data = (unsigned long)dev; + + /* register netdevice */ + dev->netdev_ops = &bcm_enetsw_ops; + netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16); + SET_ETHTOOL_OPS(dev, &bcm_enetsw_ethtool_ops); + SET_NETDEV_DEV(dev, &pdev->dev); + + spin_lock_init(&priv->enetsw_mdio_lock); + + ret = register_netdev(dev); + if (ret) + goto out_put_clk; + + netif_carrier_off(dev); + platform_set_drvdata(pdev, dev); + priv->pdev = pdev; + priv->net_dev = dev; + + return 0; + +out_put_clk: + clk_put(priv->mac_clk); + +out_unmap: + iounmap(priv->base); + +out_release_mem: + release_mem_region(res_mem->start, resource_size(res_mem)); +out: + free_netdev(dev); + return ret; +} + + +/* exit func, stops hardware and unregisters netdevice */ +static int bcm_enetsw_remove(struct platform_device *pdev) +{ + struct bcm_enet_priv *priv; + struct net_device *dev; + struct resource *res; + + /* stop netdevice */ + dev = platform_get_drvdata(pdev); + priv = netdev_priv(dev); + unregister_netdev(dev); + + /* release device resources */ + iounmap(priv->base); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + platform_set_drvdata(pdev, NULL); + free_netdev(dev); + return 0; +} + +struct platform_driver bcm63xx_enetsw_driver = { + .probe = bcm_enetsw_probe, + .remove = bcm_enetsw_remove, + .driver = { + .name = "bcm63xx_enetsw", + .owner = THIS_MODULE, + }, +}; + +/* reserve & remap memory space shared between all macs */ +static int bcm_enet_shared_probe(struct platform_device *pdev) +{ + struct resource *res; + void __iomem *p[3]; + unsigned int i; + + memset(bcm_enet_shared_base, 0, sizeof(bcm_enet_shared_base)); + + for (i = 0; i < 3; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + p[i] = devm_ioremap_resource(&pdev->dev, res); + if (!p[i]) + return -ENOMEM; + } + + memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base)); + + return 0; +} + +static int bcm_enet_shared_remove(struct platform_device *pdev) +{ + return 0; +} + +/* this "shared" driver is needed because both macs share a single + * address space + */ +struct platform_driver bcm63xx_enet_shared_driver = { + .probe = bcm_enet_shared_probe, + .remove = bcm_enet_shared_remove, + .driver = { + .name = "bcm63xx_enet_shared", + .owner = THIS_MODULE, + }, +}; + +/* entry point */ +static int __init bcm_enet_init(void) +{ + int ret; + + ret = platform_driver_register(&bcm63xx_enet_shared_driver); + if (ret) + return ret; + + ret = platform_driver_register(&bcm63xx_enet_driver); + if (ret) + platform_driver_unregister(&bcm63xx_enet_shared_driver); + + ret = platform_driver_register(&bcm63xx_enetsw_driver); + if (ret) { + platform_driver_unregister(&bcm63xx_enet_driver); + platform_driver_unregister(&bcm63xx_enet_shared_driver); + } return ret; } @@ -1959,6 +2873,7 @@ static int __init bcm_enet_init(void) static void __exit bcm_enet_exit(void) { platform_driver_unregister(&bcm63xx_enet_driver); + platform_driver_unregister(&bcm63xx_enetsw_driver); platform_driver_unregister(&bcm63xx_enet_shared_driver); } diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.h b/drivers/net/ethernet/broadcom/bcm63xx_enet.h index 133d5857b9e2..721ffbaef8d2 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h @@ -18,6 +18,7 @@ /* maximum burst len for dma (4 bytes unit) */ #define BCMENET_DMA_MAXBURST 16 +#define BCMENETSW_DMA_MAXBURST 8 /* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value * must be low enough so that a DMA transfer of above burst length can @@ -84,11 +85,60 @@ #define ETH_MIB_RX_CNTRL 54 +/* + * SW MIB Counters register definitions +*/ +#define ETHSW_MIB_TX_ALL_OCT 0 +#define ETHSW_MIB_TX_DROP_PKTS 2 +#define ETHSW_MIB_TX_QOS_PKTS 3 +#define ETHSW_MIB_TX_BRDCAST 4 +#define ETHSW_MIB_TX_MULT 5 +#define ETHSW_MIB_TX_UNI 6 +#define ETHSW_MIB_TX_COL 7 +#define ETHSW_MIB_TX_1_COL 8 +#define ETHSW_MIB_TX_M_COL 9 +#define ETHSW_MIB_TX_DEF 10 +#define ETHSW_MIB_TX_LATE 11 +#define ETHSW_MIB_TX_EX_COL 12 +#define ETHSW_MIB_TX_PAUSE 14 +#define ETHSW_MIB_TX_QOS_OCT 15 + +#define ETHSW_MIB_RX_ALL_OCT 17 +#define ETHSW_MIB_RX_UND 19 +#define ETHSW_MIB_RX_PAUSE 20 +#define ETHSW_MIB_RX_64 21 +#define ETHSW_MIB_RX_65_127 22 +#define ETHSW_MIB_RX_128_255 23 +#define ETHSW_MIB_RX_256_511 24 +#define ETHSW_MIB_RX_512_1023 25 +#define ETHSW_MIB_RX_1024_1522 26 +#define ETHSW_MIB_RX_OVR 27 +#define ETHSW_MIB_RX_JAB 28 +#define ETHSW_MIB_RX_ALIGN 29 +#define ETHSW_MIB_RX_CRC 30 +#define ETHSW_MIB_RX_GD_OCT 31 +#define ETHSW_MIB_RX_DROP 33 +#define ETHSW_MIB_RX_UNI 34 +#define ETHSW_MIB_RX_MULT 35 +#define ETHSW_MIB_RX_BRDCAST 36 +#define ETHSW_MIB_RX_SA_CHANGE 37 +#define ETHSW_MIB_RX_FRAG 38 +#define ETHSW_MIB_RX_OVR_DISC 39 +#define ETHSW_MIB_RX_SYM 40 +#define ETHSW_MIB_RX_QOS_PKTS 41 +#define ETHSW_MIB_RX_QOS_OCT 42 +#define ETHSW_MIB_RX_1523_2047 44 +#define ETHSW_MIB_RX_2048_4095 45 +#define ETHSW_MIB_RX_4096_8191 46 +#define ETHSW_MIB_RX_8192_9728 47 + + struct bcm_enet_mib_counters { u64 tx_gd_octets; u32 tx_gd_pkts; u32 tx_all_octets; u32 tx_all_pkts; + u32 tx_unicast; u32 tx_brdcast; u32 tx_mult; u32 tx_64; @@ -97,7 +147,12 @@ struct bcm_enet_mib_counters { u32 tx_256_511; u32 tx_512_1023; u32 tx_1024_max; + u32 tx_1523_2047; + u32 tx_2048_4095; + u32 tx_4096_8191; + u32 tx_8192_9728; u32 tx_jab; + u32 tx_drop; u32 tx_ovr; u32 tx_frag; u32 tx_underrun; @@ -114,6 +169,7 @@ struct bcm_enet_mib_counters { u32 rx_all_octets; u32 rx_all_pkts; u32 rx_brdcast; + u32 rx_unicast; u32 rx_mult; u32 rx_64; u32 rx_65_127; @@ -197,6 +253,9 @@ struct bcm_enet_priv { /* number of dma desc in tx ring */ int tx_ring_size; + /* maximum dma burst size */ + int dma_maxburst; + /* cpu view of rx dma ring */ struct bcm_enet_desc *tx_desc_cpu; @@ -269,6 +328,18 @@ struct bcm_enet_priv { /* maximum hardware transmit/receive size */ unsigned int hw_mtu; + + bool enet_is_sw; + + /* port mapping for switch devices */ + int num_ports; + struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT]; + int sw_port_link[ENETSW_MAX_PORT]; + + /* used to poll switch port state */ + struct timer_list swphy_poll; + spinlock_t enetsw_mdio_lock; }; + #endif /* ! BCM63XX_ENET_H_ */ -- GitLab From af12fa6e46aa651e7b86a4c4117b562518fef184 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:39:41 +0300 Subject: [PATCH 0828/2900] net: add napi_id and hash Adds a napi_id and a hashing mechanism to lookup a napi by id. This will be used by subsequent patches to implement low latency Ethernet device polling. Based on a code sample by Eric Dumazet. Signed-off-by: Eliezer Tamir Signed-off-by: Eric Dumazet Tested-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/linux/netdevice.h | 29 +++++++++++++++++++ net/core/dev.c | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8f967e34142b..39bbd462d68e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -324,12 +324,15 @@ struct napi_struct { struct sk_buff *gro_list; struct sk_buff *skb; struct list_head dev_list; + struct hlist_node napi_hash_node; + unsigned int napi_id; }; enum { NAPI_STATE_SCHED, /* Poll is scheduled */ NAPI_STATE_DISABLE, /* Disable pending */ NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */ + NAPI_STATE_HASHED, /* In NAPI hash */ }; enum gro_result { @@ -445,6 +448,32 @@ static inline bool napi_reschedule(struct napi_struct *napi) extern void __napi_complete(struct napi_struct *n); extern void napi_complete(struct napi_struct *n); +/** + * napi_by_id - lookup a NAPI by napi_id + * @napi_id: hashed napi_id + * + * lookup @napi_id in napi_hash table + * must be called under rcu_read_lock() + */ +extern struct napi_struct *napi_by_id(unsigned int napi_id); + +/** + * napi_hash_add - add a NAPI to global hashtable + * @napi: napi context + * + * generate a new napi_id and store a @napi under it in napi_hash + */ +extern void napi_hash_add(struct napi_struct *napi); + +/** + * napi_hash_del - remove a NAPI from global table + * @napi: napi context + * + * Warning: caller must observe rcu grace period + * before freeing memory containing @napi + */ +extern void napi_hash_del(struct napi_struct *napi); + /** * napi_disable - prevent NAPI from scheduling * @n: napi context diff --git a/net/core/dev.c b/net/core/dev.c index 9c18557f93c6..fa007dba6beb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -129,6 +129,7 @@ #include #include #include +#include #include "net-sysfs.h" @@ -166,6 +167,12 @@ static struct list_head offload_base __read_mostly; DEFINE_RWLOCK(dev_base_lock); EXPORT_SYMBOL(dev_base_lock); +/* protects napi_hash addition/deletion and napi_gen_id */ +static DEFINE_SPINLOCK(napi_hash_lock); + +static unsigned int napi_gen_id; +static DEFINE_HASHTABLE(napi_hash, 8); + seqcount_t devnet_rename_seq; static inline void dev_base_seq_inc(struct net *net) @@ -4136,6 +4143,58 @@ void napi_complete(struct napi_struct *n) } EXPORT_SYMBOL(napi_complete); +/* must be called under rcu_read_lock(), as we dont take a reference */ +struct napi_struct *napi_by_id(unsigned int napi_id) +{ + unsigned int hash = napi_id % HASH_SIZE(napi_hash); + struct napi_struct *napi; + + hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node) + if (napi->napi_id == napi_id) + return napi; + + return NULL; +} +EXPORT_SYMBOL_GPL(napi_by_id); + +void napi_hash_add(struct napi_struct *napi) +{ + if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) { + + spin_lock(&napi_hash_lock); + + /* 0 is not a valid id, we also skip an id that is taken + * we expect both events to be extremely rare + */ + napi->napi_id = 0; + while (!napi->napi_id) { + napi->napi_id = ++napi_gen_id; + if (napi_by_id(napi->napi_id)) + napi->napi_id = 0; + } + + hlist_add_head_rcu(&napi->napi_hash_node, + &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]); + + spin_unlock(&napi_hash_lock); + } +} +EXPORT_SYMBOL_GPL(napi_hash_add); + +/* Warning : caller is responsible to make sure rcu grace period + * is respected before freeing memory containing @napi + */ +void napi_hash_del(struct napi_struct *napi) +{ + spin_lock(&napi_hash_lock); + + if (test_and_clear_bit(NAPI_STATE_HASHED, &napi->state)) + hlist_del_rcu(&napi->napi_hash_node); + + spin_unlock(&napi_hash_lock); +} +EXPORT_SYMBOL_GPL(napi_hash_del); + void netif_napi_add(struct net_device *dev, struct napi_struct *napi, int (*poll)(struct napi_struct *, int), int weight) { -- GitLab From 060212928670593fb89243640bf05cf89560b023 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:39:50 +0300 Subject: [PATCH 0829/2900] net: add low latency socket poll Adds an ndo_ll_poll method and the code that supports it. This method can be used by low latency applications to busy-poll Ethernet device queues directly from the socket code. sysctl_net_ll_poll controls how many microseconds to poll. Default is zero (disabled). Individual protocol support will be added by subsequent patches. Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Eliezer Tamir Acked-by: Eric Dumazet Tested-by: Willem de Bruijn Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 7 ++ include/linux/netdevice.h | 3 + include/linux/skbuff.h | 8 +- include/net/ll_poll.h | 148 +++++++++++++++++++++++++++++++++++ include/net/sock.h | 4 + include/uapi/linux/snmp.h | 1 + net/Kconfig | 12 +++ net/core/skbuff.c | 4 + net/core/sock.c | 6 ++ net/core/sysctl_net_core.c | 10 +++ net/ipv4/proc.c | 1 + net/socket.c | 6 ++ 12 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 include/net/ll_poll.h diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index c1f8640c2fc8..85ab72dcdc3c 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -50,6 +50,13 @@ The maximum number of packets that kernel can handle on a NAPI interrupt, it's a Per-CPU variable. Default: 64 +low_latency_poll +---------------- +Low latency busy poll timeout. (needs CONFIG_NET_LL_RX_POLL) +Approximate time in us to spin waiting for packets on the device queue. +Recommended value is 50. May increase power usage. +Default: 0 (off) + rmem_default ------------ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 39bbd462d68e..2ecb96d9a1e5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -971,6 +971,9 @@ struct net_device_ops { struct netpoll_info *info, gfp_t gfp); void (*ndo_netpoll_cleanup)(struct net_device *dev); +#endif +#ifdef CONFIG_NET_LL_RX_POLL + int (*ndo_ll_poll)(struct napi_struct *dev); #endif int (*ndo_set_vf_mac)(struct net_device *dev, int queue, u8 *mac); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 9995834d2cb6..400d82ae2b03 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -386,6 +386,7 @@ typedef unsigned char *sk_buff_data_t; * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS * @dma_cookie: a cookie to one of several possible DMA operations * done by skb DMA functions + * @napi_id: id of the NAPI struct this skb came from * @secmark: security marking * @mark: Generic packet mark * @dropcount: total number of sk_receive_queue overflows @@ -500,8 +501,11 @@ struct sk_buff { /* 7/9 bit hole (depending on ndisc_nodetype presence) */ kmemcheck_bitfield_end(flags2); -#ifdef CONFIG_NET_DMA - dma_cookie_t dma_cookie; +#if defined CONFIG_NET_DMA || defined CONFIG_NET_LL_RX_POLL + union { + unsigned int napi_id; + dma_cookie_t dma_cookie; + }; #endif #ifdef CONFIG_NETWORK_SECMARK __u32 secmark; diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h new file mode 100644 index 000000000000..bc262f88173f --- /dev/null +++ b/include/net/ll_poll.h @@ -0,0 +1,148 @@ +/* + * Low Latency Sockets + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + * Author: Eliezer Tamir + * + * Contact Information: + * e1000-devel Mailing List + */ + +/* + * For now this depends on CONFIG_X86_TSC + */ + +#ifndef _LINUX_NET_LL_POLL_H +#define _LINUX_NET_LL_POLL_H + +#include +#include + +#ifdef CONFIG_NET_LL_RX_POLL + +struct napi_struct; +extern unsigned long sysctl_net_ll_poll __read_mostly; + +/* return values from ndo_ll_poll */ +#define LL_FLUSH_FAILED -1 +#define LL_FLUSH_BUSY -2 + +/* we don't mind a ~2.5% imprecision */ +#define TSC_MHZ (tsc_khz >> 10) + +static inline cycles_t ll_end_time(void) +{ + return TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll) + get_cycles(); +} + +static inline bool sk_valid_ll(struct sock *sk) +{ + return sysctl_net_ll_poll && sk->sk_napi_id && + !need_resched() && !signal_pending(current); +} + +static inline bool can_poll_ll(cycles_t end_time) +{ + return !time_after((unsigned long)get_cycles(), + (unsigned long)end_time); +} + +static inline bool sk_poll_ll(struct sock *sk, int nonblock) +{ + cycles_t end_time = ll_end_time(); + const struct net_device_ops *ops; + struct napi_struct *napi; + int rc = false; + + /* + * rcu read lock for napi hash + * bh so we don't race with net_rx_action + */ + rcu_read_lock_bh(); + + napi = napi_by_id(sk->sk_napi_id); + if (!napi) + goto out; + + ops = napi->dev->netdev_ops; + if (!ops->ndo_ll_poll) + goto out; + + do { + + rc = ops->ndo_ll_poll(napi); + + if (rc == LL_FLUSH_FAILED) + break; /* permanent failure */ + + if (rc > 0) + /* local bh are disabled so it is ok to use _BH */ + NET_ADD_STATS_BH(sock_net(sk), + LINUX_MIB_LOWLATENCYRXPACKETS, rc); + + } while (skb_queue_empty(&sk->sk_receive_queue) + && can_poll_ll(end_time) && !nonblock); + + rc = !skb_queue_empty(&sk->sk_receive_queue); +out: + rcu_read_unlock_bh(); + return rc; +} + +/* used in the NIC receive handler to mark the skb */ +static inline void skb_mark_ll(struct sk_buff *skb, struct napi_struct *napi) +{ + skb->napi_id = napi->napi_id; +} + +/* used in the protocol hanlder to propagate the napi_id to the socket */ +static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) +{ + sk->sk_napi_id = skb->napi_id; +} + +#else /* CONFIG_NET_LL_RX_POLL */ + +static inline cycles_t ll_end_time(void) +{ + return 0; +} + +static inline bool sk_valid_ll(struct sock *sk) +{ + return false; +} + +static inline bool sk_poll_ll(struct sock *sk, int nonblock) +{ + return false; +} + +static inline void skb_mark_ll(struct sk_buff *skb, struct napi_struct *napi) +{ +} + +static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) +{ +} + +static inline bool can_poll_ll(cycles_t end_time) +{ + return false; +} + +#endif /* CONFIG_NET_LL_RX_POLL */ +#endif /* _LINUX_NET_LL_POLL_H */ diff --git a/include/net/sock.h b/include/net/sock.h index 66772cf8c3c5..ac8e1818380c 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -229,6 +229,7 @@ struct cg_proto; * @sk_omem_alloc: "o" is "option" or "other" * @sk_wmem_queued: persistent queue size * @sk_forward_alloc: space allocated forward + * @sk_napi_id: id of the last napi context to receive data for sk * @sk_allocation: allocation mode * @sk_sndbuf: size of send buffer in bytes * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, @@ -324,6 +325,9 @@ struct sock { int sk_forward_alloc; #ifdef CONFIG_RPS __u32 sk_rxhash; +#endif +#ifdef CONFIG_NET_LL_RX_POLL + unsigned int sk_napi_id; #endif atomic_t sk_drops; int sk_rcvbuf; diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index df2e8b4f9c03..26cbf76f8058 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h @@ -253,6 +253,7 @@ enum LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */ + LINUX_MIB_LOWLATENCYRXPACKETS, /* LowLatencyRxPackets */ __LINUX_MIB_MAX }; diff --git a/net/Kconfig b/net/Kconfig index 523e43e6da1b..d6a9ce6e1800 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -243,6 +243,18 @@ config NETPRIO_CGROUP Cgroup subsystem for use in assigning processes to network priorities on a per-interface basis +config NET_LL_RX_POLL + bool "Low Latency Receive Poll" + depends on X86_TSC + default n + ---help--- + Support Low Latency Receive Queue Poll. + (For network card drivers which support this option.) + When waiting for data in read or poll call directly into the the device driver + to flush packets which may be pending on the device queues into the stack. + + If unsure, say N. + config BQL boolean depends on SYSFS diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 73f57a0e1523..4a4181e16c1a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -733,6 +733,10 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->vlan_tci = old->vlan_tci; skb_copy_secmark(new, old); + +#ifdef CONFIG_NET_LL_RX_POLL + new->napi_id = old->napi_id; +#endif } /* diff --git a/net/core/sock.c b/net/core/sock.c index 88868a9d21da..788c0da5eed1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -139,6 +139,8 @@ #include #endif +#include + static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); @@ -2284,6 +2286,10 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_stamp = ktime_set(-1L, 0); +#ifdef CONFIG_NET_LL_RX_POLL + sk->sk_napi_id = 0; +#endif + /* * Before updating sk_refcnt, we must commit prior changes to memory * (Documentation/RCU/rculist_nulls.txt for details) diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 741db5fc7806..4b48f39582b0 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -19,6 +19,7 @@ #include #include #include +#include static int one = 1; @@ -284,6 +285,15 @@ static struct ctl_table net_core_table[] = { .proc_handler = flow_limit_table_len_sysctl }, #endif /* CONFIG_NET_FLOW_LIMIT */ +#ifdef CONFIG_NET_LL_RX_POLL + { + .procname = "low_latency_poll", + .data = &sysctl_net_ll_poll, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax + }, +#endif #endif /* CONFIG_NET */ { .procname = "netdev_budget", diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 2a5bf86d2415..6577a1149a47 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -273,6 +273,7 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD), SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), + SNMP_MIB_ITEM("LowLatencyRxPackets", LINUX_MIB_LOWLATENCYRXPACKETS), SNMP_MIB_SENTINEL }; diff --git a/net/socket.c b/net/socket.c index 3ebdcb805c51..21fd29f63ed2 100644 --- a/net/socket.c +++ b/net/socket.c @@ -104,6 +104,12 @@ #include #include #include +#include + +#ifdef CONFIG_NET_LL_RX_POLL +unsigned long sysctl_net_ll_poll __read_mostly; +EXPORT_SYMBOL_GPL(sysctl_net_ll_poll); +#endif static int sock_no_open(struct inode *irrelevant, struct file *dontcare); static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, -- GitLab From a5b50476f77a8fcc8055c955720d05a7c2d9c532 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:40:00 +0300 Subject: [PATCH 0830/2900] udp: add low latency socket poll support Add upport for busy-polling on UDP sockets. In __udp[46]_lib_rcv add a call to sk_mark_ll() to copy the napi_id from the skb into the sk. This is done at the earliest possible moment, right after we identify which socket this skb is for. In __skb_recv_datagram When there is no data and the user tries to read we busy poll. Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Eliezer Tamir Acked-by: Eric Dumazet Tested-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/core/datagram.c | 4 ++++ net/ipv4/udp.c | 6 +++++- net/ipv6/udp.c | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/net/core/datagram.c b/net/core/datagram.c index b71423db7785..9cbaba98ce4c 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -56,6 +56,7 @@ #include #include #include +#include /* * Is a socket 'connection oriented' ? @@ -207,6 +208,9 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, } spin_unlock_irqrestore(&queue->lock, cpu_flags); + if (sk_valid_ll(sk) && sk_poll_ll(sk, flags & MSG_DONTWAIT)) + continue; + /* User doesn't want to wait */ error = -EAGAIN; if (!timeo) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c7338ec79cc0..2955b25aee6d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -109,6 +109,7 @@ #include #include #include +#include #include "udp_impl.h" struct udp_table udp_table __read_mostly; @@ -1709,7 +1710,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable); if (sk != NULL) { - int ret = udp_queue_rcv_skb(sk, skb); + int ret; + + sk_mark_ll(sk, skb); + ret = udp_queue_rcv_skb(sk, skb); sock_put(sk); /* a return value > 0 means to resubmit the input, but diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b5808539cd5c..f77e34c5a0e2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -841,7 +842,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, */ sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); if (sk != NULL) { - int ret = udpv6_queue_rcv_skb(sk, skb); + int ret; + + sk_mark_ll(sk, skb); + ret = udpv6_queue_rcv_skb(sk, skb); sock_put(sk); /* a return value > 0 means to resubmit the input, but -- GitLab From d30e383bb856f614ddb5bbbb5a7d3f86240e41ec Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:40:10 +0300 Subject: [PATCH 0831/2900] tcp: add low latency socket poll support. Adds low latency socket poll support for TCP. In tcp_v[46]_rcv() add a call to sk_mark_ll() to copy the napi_id from the skb to the sk. In tcp_recvmsg(), when there is no data in the socket we busy-poll. This is a good example of how to add busy-poll support to more protocols. Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Eliezer Tamir Acked-by: Eric Dumazet Tested-by: Willem de Bruijn Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 5 +++++ net/ipv4/tcp_ipv4.c | 2 ++ net/ipv6/tcp_ipv6.c | 2 ++ 3 files changed, 9 insertions(+) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index bc4246940f6c..46ed9afd1f5e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -279,6 +279,7 @@ #include #include +#include int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; @@ -1553,6 +1554,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct sk_buff *skb; u32 urg_hole = 0; + if (sk_valid_ll(sk) && skb_queue_empty(&sk->sk_receive_queue) + && (sk->sk_state == TCP_ESTABLISHED)) + sk_poll_ll(sk, nonblock); + lock_sock(sk); err = -ENOTCONN; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 289039b4d8de..1063bb83e342 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include @@ -1993,6 +1994,7 @@ int tcp_v4_rcv(struct sk_buff *skb) if (sk_filter(sk, skb)) goto discard_and_relse; + sk_mark_ll(sk, skb); skb->dev = NULL; bh_lock_sock_nested(sk); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0a17ed9eaf39..5cffa5c3e6b8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -63,6 +63,7 @@ #include #include #include +#include #include @@ -1498,6 +1499,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (sk_filter(sk, skb)) goto discard_and_relse; + sk_mark_ll(sk, skb); skb->dev = NULL; bh_lock_sock_nested(sk); -- GitLab From 5a85e737f30ce7b939a34d93cca816400342208c Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:40:20 +0300 Subject: [PATCH 0832/2900] ixgbe: add support for ndo_ll_poll Add the ixgbe driver code implementing ndo_ll_poll. Adds ndo_ll_poll method and locking between it and the napi poll. When receiving a packet we use skb_mark_ll to record the napi it came from. Add each napi to the napi_hash right after netif_napi_add(). Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Eliezer Tamir Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 120 ++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 63 +++++++-- 3 files changed, 177 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index ca932387a80f..e9d98629b583 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -52,6 +52,8 @@ #include #endif +#include + /* common prefix used by pr_<> macros */ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -356,9 +358,127 @@ struct ixgbe_q_vector { struct rcu_head rcu; /* to avoid race with update stats on free */ char name[IFNAMSIZ + 9]; +#ifdef CONFIG_NET_LL_RX_POLL + unsigned int state; +#define IXGBE_QV_STATE_IDLE 0 +#define IXGBE_QV_STATE_NAPI 1 /* NAPI owns this QV */ +#define IXGBE_QV_STATE_POLL 2 /* poll owns this QV */ +#define IXGBE_QV_LOCKED (IXGBE_QV_STATE_NAPI | IXGBE_QV_STATE_POLL) +#define IXGBE_QV_STATE_NAPI_YIELD 4 /* NAPI yielded this QV */ +#define IXGBE_QV_STATE_POLL_YIELD 8 /* poll yielded this QV */ +#define IXGBE_QV_YIELD (IXGBE_QV_STATE_NAPI_YIELD | IXGBE_QV_STATE_POLL_YIELD) +#define IXGBE_QV_USER_PEND (IXGBE_QV_STATE_POLL | IXGBE_QV_STATE_POLL_YIELD) + spinlock_t lock; +#endif /* CONFIG_NET_LL_RX_POLL */ + /* for dynamic allocation of rings associated with this q_vector */ struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp; }; +#ifdef CONFIG_NET_LL_RX_POLL +static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector) +{ + + spin_lock_init(&q_vector->lock); + q_vector->state = IXGBE_QV_STATE_IDLE; +} + +/* called from the device poll routine to get ownership of a q_vector */ +static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector) +{ + int rc = true; + spin_lock(&q_vector->lock); + if (q_vector->state & IXGBE_QV_LOCKED) { + WARN_ON(q_vector->state & IXGBE_QV_STATE_NAPI); + q_vector->state |= IXGBE_QV_STATE_NAPI_YIELD; + rc = false; + } else + /* we don't care if someone yielded */ + q_vector->state = IXGBE_QV_STATE_NAPI; + spin_unlock(&q_vector->lock); + return rc; +} + +/* returns true is someone tried to get the qv while napi had it */ +static inline bool ixgbe_qv_unlock_napi(struct ixgbe_q_vector *q_vector) +{ + int rc = false; + spin_lock(&q_vector->lock); + WARN_ON(q_vector->state & (IXGBE_QV_STATE_POLL | + IXGBE_QV_STATE_NAPI_YIELD)); + + if (q_vector->state & IXGBE_QV_STATE_POLL_YIELD) + rc = true; + q_vector->state = IXGBE_QV_STATE_IDLE; + spin_unlock(&q_vector->lock); + return rc; +} + +/* called from ixgbe_low_latency_poll() */ +static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector) +{ + int rc = true; + spin_lock_bh(&q_vector->lock); + if ((q_vector->state & IXGBE_QV_LOCKED)) { + q_vector->state |= IXGBE_QV_STATE_POLL_YIELD; + rc = false; + } else + /* preserve yield marks */ + q_vector->state |= IXGBE_QV_STATE_POLL; + spin_unlock_bh(&q_vector->lock); + return rc; +} + +/* returns true if someone tried to get the qv while it was locked */ +static inline bool ixgbe_qv_unlock_poll(struct ixgbe_q_vector *q_vector) +{ + int rc = false; + spin_lock_bh(&q_vector->lock); + WARN_ON(q_vector->state & (IXGBE_QV_STATE_NAPI)); + + if (q_vector->state & IXGBE_QV_STATE_POLL_YIELD) + rc = true; + q_vector->state = IXGBE_QV_STATE_IDLE; + spin_unlock_bh(&q_vector->lock); + return rc; +} + +/* true if a socket is polling, even if it did not get the lock */ +static inline bool ixgbe_qv_ll_polling(struct ixgbe_q_vector *q_vector) +{ + WARN_ON(!(q_vector->state & IXGBE_QV_LOCKED)); + return q_vector->state & IXGBE_QV_USER_PEND; +} +#else /* CONFIG_NET_LL_RX_POLL */ +static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector) +{ +} + +static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector) +{ + return true; +} + +static inline bool ixgbe_qv_unlock_napi(struct ixgbe_q_vector *q_vector) +{ + return false; +} + +static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector) +{ + return false; +} + +static inline bool ixgbe_qv_unlock_poll(struct ixgbe_q_vector *q_vector) +{ + return false; +} + +static inline bool ixgbe_qv_ll_polling(struct ixgbe_q_vector *q_vector) +{ + return false; +} +#endif /* CONFIG_NET_LL_RX_POLL */ + #ifdef CONFIG_IXGBE_HWMON #define IXGBE_HWMON_TYPE_LOC 0 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index ef5f7a678ce1..90b4e1089ecc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -811,6 +811,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, /* initialize NAPI */ netif_napi_add(adapter->netdev, &q_vector->napi, ixgbe_poll, 64); + napi_hash_add(&q_vector->napi); /* tie q_vector and adapter together */ adapter->q_vector[v_idx] = q_vector; @@ -931,6 +932,7 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx) adapter->rx_ring[ring->queue_index] = NULL; adapter->q_vector[v_idx] = NULL; + napi_hash_del(&q_vector->napi); netif_napi_del(&q_vector->napi); /* diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index d30fbdd81fca..9a7dc405e7ed 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1504,7 +1504,9 @@ static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector, { struct ixgbe_adapter *adapter = q_vector->adapter; - if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) + if (ixgbe_qv_ll_polling(q_vector)) + netif_receive_skb(skb); + else if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) napi_gro_receive(&q_vector->napi, skb); else netif_rx(skb); @@ -1892,9 +1894,9 @@ static struct sk_buff *ixgbe_fetch_rx_buffer(struct ixgbe_ring *rx_ring, * expensive overhead for IOMMU access this provides a means of avoiding * it by maintaining the mapping of the page to the syste. * - * Returns true if all work is completed without reaching budget + * Returns amount of work completed **/ -static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, +static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, const int budget) { @@ -1976,6 +1978,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, } #endif /* IXGBE_FCOE */ + skb_mark_ll(skb, &q_vector->napi); ixgbe_rx_skb(q_vector, skb); /* update budget accounting */ @@ -1992,9 +1995,37 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (cleaned_count) ixgbe_alloc_rx_buffers(rx_ring, cleaned_count); - return (total_rx_packets < budget); + return total_rx_packets; } +#ifdef CONFIG_NET_LL_RX_POLL +/* must be called with local_bh_disable()d */ +static int ixgbe_low_latency_recv(struct napi_struct *napi) +{ + struct ixgbe_q_vector *q_vector = + container_of(napi, struct ixgbe_q_vector, napi); + struct ixgbe_adapter *adapter = q_vector->adapter; + struct ixgbe_ring *ring; + int found = 0; + + if (test_bit(__IXGBE_DOWN, &adapter->state)) + return LL_FLUSH_FAILED; + + if (!ixgbe_qv_lock_poll(q_vector)) + return LL_FLUSH_BUSY; + + ixgbe_for_each_ring(ring, q_vector->rx) { + found = ixgbe_clean_rx_irq(q_vector, ring, 4); + if (found) + break; + } + + ixgbe_qv_unlock_poll(q_vector); + + return found; +} +#endif /* CONFIG_NET_LL_RX_POLL */ + /** * ixgbe_configure_msix - Configure MSI-X hardware * @adapter: board private structure @@ -2550,6 +2581,9 @@ int ixgbe_poll(struct napi_struct *napi, int budget) ixgbe_for_each_ring(ring, q_vector->tx) clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring); + if (!ixgbe_qv_lock_napi(q_vector)) + return budget; + /* attempt to distribute budget to each queue fairly, but don't allow * the budget to go below 1 because we'll exit polling */ if (q_vector->rx.count > 1) @@ -2558,9 +2592,10 @@ int ixgbe_poll(struct napi_struct *napi, int budget) per_ring_budget = budget; ixgbe_for_each_ring(ring, q_vector->rx) - clean_complete &= ixgbe_clean_rx_irq(q_vector, ring, - per_ring_budget); + clean_complete &= (ixgbe_clean_rx_irq(q_vector, ring, + per_ring_budget) < per_ring_budget); + ixgbe_qv_unlock_napi(q_vector); /* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget; @@ -3747,16 +3782,25 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) { int q_idx; - for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) + for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) { + ixgbe_qv_init_lock(adapter->q_vector[q_idx]); napi_enable(&adapter->q_vector[q_idx]->napi); + } } static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter) { int q_idx; - for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) + local_bh_disable(); /* for ixgbe_qv_lock_napi() */ + for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) { napi_disable(&adapter->q_vector[q_idx]->napi); + while (!ixgbe_qv_lock_napi(adapter->q_vector[q_idx])) { + pr_info("QV %d locked\n", q_idx); + mdelay(1); + } + } + local_bh_enable(); } #ifdef CONFIG_IXGBE_DCB @@ -7177,6 +7221,9 @@ static const struct net_device_ops ixgbe_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbe_netpoll, #endif +#ifdef CONFIG_NET_LL_RX_POLL + .ndo_ll_poll = ixgbe_low_latency_recv, +#endif #ifdef IXGBE_FCOE .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, .ndo_fcoe_ddp_target = ixgbe_fcoe_ddp_target, -- GitLab From 7e15b90ff9b796d14aa0d1aabc0dbb54632c673c Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 10 Jun 2013 11:40:31 +0300 Subject: [PATCH 0833/2900] ixgbe: add extra stats for ndo_ll_poll Add additional statistics to the ixgbe driver for ndo_ll_poll Defined under LL_EXTENDED_STATS Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 14 +++++++ .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 40 +++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +++ 3 files changed, 60 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index e9d98629b583..fb098b46c6a6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -54,6 +54,9 @@ #include +#ifdef CONFIG_NET_LL_RX_POLL +#define LL_EXTENDED_STATS +#endif /* common prefix used by pr_<> macros */ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -184,6 +187,11 @@ struct ixgbe_rx_buffer { struct ixgbe_queue_stats { u64 packets; u64 bytes; +#ifdef LL_EXTENDED_STATS + u64 yields; + u64 misses; + u64 cleaned; +#endif /* LL_EXTENDED_STATS */ }; struct ixgbe_tx_queue_stats { @@ -391,6 +399,9 @@ static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector) WARN_ON(q_vector->state & IXGBE_QV_STATE_NAPI); q_vector->state |= IXGBE_QV_STATE_NAPI_YIELD; rc = false; +#ifdef LL_EXTENDED_STATS + q_vector->tx.ring->stats.yields++; +#endif } else /* we don't care if someone yielded */ q_vector->state = IXGBE_QV_STATE_NAPI; @@ -421,6 +432,9 @@ static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector) if ((q_vector->state & IXGBE_QV_LOCKED)) { q_vector->state |= IXGBE_QV_STATE_POLL_YIELD; rc = false; +#ifdef LL_EXTENDED_STATS + q_vector->rx.ring->stats.yields++; +#endif } else /* preserve yield marks */ q_vector->state |= IXGBE_QV_STATE_POLL; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index d3754722adb4..24e2e7aafda2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1054,6 +1054,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, data[i] = 0; data[i+1] = 0; i += 2; +#ifdef LL_EXTENDED_STATS + data[i] = 0; + data[i+1] = 0; + data[i+2] = 0; + i += 3; +#endif continue; } @@ -1063,6 +1069,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, data[i+1] = ring->stats.bytes; } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); i += 2; +#ifdef LL_EXTENDED_STATS + data[i] = ring->stats.yields; + data[i+1] = ring->stats.misses; + data[i+2] = ring->stats.cleaned; + i += 3; +#endif } for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) { ring = adapter->rx_ring[j]; @@ -1070,6 +1082,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, data[i] = 0; data[i+1] = 0; i += 2; +#ifdef LL_EXTENDED_STATS + data[i] = 0; + data[i+1] = 0; + data[i+2] = 0; + i += 3; +#endif continue; } @@ -1079,6 +1097,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, data[i+1] = ring->stats.bytes; } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); i += 2; +#ifdef LL_EXTENDED_STATS + data[i] = ring->stats.yields; + data[i+1] = ring->stats.misses; + data[i+2] = ring->stats.cleaned; + i += 3; +#endif } for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) { @@ -1115,12 +1139,28 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset, p += ETH_GSTRING_LEN; sprintf(p, "tx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; +#ifdef LL_EXTENDED_STATS + sprintf(p, "tx_q_%u_napi_yield", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_q_%u_misses", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_q_%u_cleaned", i); + p += ETH_GSTRING_LEN; +#endif /* LL_EXTENDED_STATS */ } for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) { sprintf(p, "rx_queue_%u_packets", i); p += ETH_GSTRING_LEN; sprintf(p, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; +#ifdef LL_EXTENDED_STATS + sprintf(p, "rx_q_%u_ll_poll_yield", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_q_%u_misses", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_q_%u_cleaned", i); + p += ETH_GSTRING_LEN; +#endif /* LL_EXTENDED_STATS */ } for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { sprintf(p, "tx_pb_%u_pxon", i); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9a7dc405e7ed..047ebaaf0141 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2016,6 +2016,12 @@ static int ixgbe_low_latency_recv(struct napi_struct *napi) ixgbe_for_each_ring(ring, q_vector->rx) { found = ixgbe_clean_rx_irq(q_vector, ring, 4); +#ifdef LL_EXTENDED_STATS + if (found) + ring->stats.cleaned += found; + else + ring->stats.misses++; +#endif if (found) break; } -- GitLab From 30f3a40f9a2a2869a560a9cb9ef488d10c803e14 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 5 Jun 2013 20:14:10 +0800 Subject: [PATCH 0834/2900] net: remove last caller of skb_tail_offset() and itself Similar to the following commits: commit 00f97da17a0c8d656d0c9 (netpoll: fix position of network header) commit 525cebedb32a87fa48584 (pktgen: Fix position of ip and udp header) using skb_tail_offset() seems not correct since the offset is based on head pointer. With the last caller removed, skb_tail_offset() can be killed finally. Cc: Thomas Graf Cc: Daniel Borkmann Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/skbuff.h | 8 -------- net/ipv4/ipmr.c | 8 +------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 400d82ae2b03..a7393adea0b5 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1396,10 +1396,6 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) skb->tail += offset; } -static inline unsigned long skb_tail_offset(const struct sk_buff *skb) -{ - return skb->tail; -} #else /* NET_SKBUFF_DATA_USES_OFFSET */ static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb) { @@ -1416,10 +1412,6 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) skb->tail = skb->data + offset; } -static inline unsigned long skb_tail_offset(const struct sk_buff *skb) -{ - return skb->tail - skb->head; -} #endif /* NET_SKBUFF_DATA_USES_OFFSET */ /* diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index df97f0ac1a1c..132a09664704 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -945,7 +945,6 @@ static int ipmr_cache_report(struct mr_table *mrt, struct igmpmsg *msg; struct sock *mroute_sk; int ret; - unsigned long tail_offset; #ifdef CONFIG_IP_PIMSM if (assert == IGMPMSG_WHOLEPKT) @@ -981,12 +980,7 @@ static int ipmr_cache_report(struct mr_table *mrt, /* Copy the IP header */ - tail_offset = skb_tail_offset(skb); - if (tail_offset > 0xffff) { - kfree_skb(skb); - return -EINVAL; - } - skb_set_network_header(skb, tail_offset); + skb_set_network_header(skb, skb->len); skb_put(skb, ihl); skb_copy_to_linear_data(skb, pkt->data, ihl); ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */ -- GitLab From 9ba18891f75535eca3ef53138b48970eb60f5255 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 5 Jun 2013 10:08:00 -0400 Subject: [PATCH 0835/2900] bridge: Add flag to control mac learning. Allow user to control whether mac learning is enabled on the port. By default, mac learning is enabled. Disabling mac learning will cause new dynamic FDB entries to not be created for a particular port. Signed-off-by: Vlad Yasevich Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 1 + net/bridge/br_if.c | 2 +- net/bridge/br_input.c | 6 ++++-- net/bridge/br_netlink.c | 6 +++++- net/bridge/br_private.h | 1 + net/bridge/br_sysfs_if.c | 2 ++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index b05823cae784..8643809d8417 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -221,6 +221,7 @@ enum { IFLA_BRPORT_GUARD, /* bpdu guard */ IFLA_BRPORT_PROTECT, /* root port protection */ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + IFLA_BRPORT_LEARNING, /* mac learning */ __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4cdba60926ff..2c08911df578 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -221,7 +221,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->path_cost = port_cost(dev); p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; - p->flags = 0; + p->flags = BR_LEARNING; br_init_port(p); p->state = BR_STATE_DISABLED; br_stp_port_timer_init(p); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 828e2bcc1f52..7e993667d4bf 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -75,7 +75,8 @@ int br_handle_frame_finish(struct sk_buff *skb) /* insert into forwarding database after filtering to avoid spoofing */ br = p->br; - br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); + if (p->flags & BR_LEARNING) + br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) && br_multicast_rcv(br, p, skb)) @@ -142,7 +143,8 @@ static int br_handle_local_finish(struct sk_buff *skb) u16 vid = 0; br_vlan_get_tag(skb, &vid); - br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); + if (p->flags & BR_LEARNING) + br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); return 0; /* process further */ } diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 8e3abf564798..ce902bf8a618 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -30,6 +30,7 @@ static inline size_t br_port_info_size(void) + nla_total_size(1) /* IFLA_BRPORT_GUARD */ + nla_total_size(1) /* IFLA_BRPORT_PROTECT */ + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */ + + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ + 0; } @@ -56,7 +57,8 @@ static int br_port_fill_attrs(struct sk_buff *skb, nla_put_u8(skb, IFLA_BRPORT_MODE, mode) || nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) || nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) || - nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE))) + nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)) || + nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING))) return -EMSGSIZE; return 0; @@ -281,6 +283,7 @@ static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = { [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, + [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, }; /* Change the state of the port and notify spanning tree */ @@ -328,6 +331,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK); + br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING); if (tb[IFLA_BRPORT_COST]) { err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1b0ac95a5c37..04d7f43508f7 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -158,6 +158,7 @@ struct net_bridge_port #define BR_ROOT_BLOCK 0x00000004 #define BR_MULTICAST_FAST_LEAVE 0x00000008 #define BR_ADMIN_COST 0x00000010 +#define BR_LEARNING 0x00000020 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING u32 multicast_startup_queries_sent; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index a1ef1b6e14dc..707f3628e9cd 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -158,6 +158,7 @@ static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); +BRPORT_ATTR_FLAG(learning, BR_LEARNING); #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -195,6 +196,7 @@ static const struct brport_attribute *brport_attrs[] = { &brport_attr_hairpin_mode, &brport_attr_bpdu_guard, &brport_attr_root_block, + &brport_attr_learning, #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &brport_attr_multicast_router, &brport_attr_multicast_fast_leave, -- GitLab From 867a59436fc35593ae0e0efcd56cc6d2f8506586 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Wed, 5 Jun 2013 10:08:01 -0400 Subject: [PATCH 0836/2900] bridge: Add a flag to control unicast packet flood. Add a flag to control flood of unicast traffic. By default, flood is on and the bridge will flood unicast traffic if it doesn't know the destination. When the flag is turned off, unicast traffic without an FDB will not be forwarded to the specified port. Signed-off-by: Vlad Yasevich Reviewed-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/uapi/linux/if_link.h | 1 + net/bridge/br_device.c | 8 ++++---- net/bridge/br_forward.c | 14 +++++++++----- net/bridge/br_if.c | 2 +- net/bridge/br_input.c | 9 ++++++--- net/bridge/br_netlink.c | 6 +++++- net/bridge/br_private.h | 6 ++++-- net/bridge/br_sysfs_if.c | 2 ++ 8 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 8643809d8417..da05a2698cb5 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -222,6 +222,7 @@ enum { IFLA_BRPORT_PROTECT, /* root port protection */ IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ IFLA_BRPORT_LEARNING, /* mac learning */ + IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 75f3239130f8..2ef66781fedb 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -58,10 +58,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_pull(skb, ETH_HLEN); if (is_broadcast_ether_addr(dest)) - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, false); else if (is_multicast_ether_addr(dest)) { if (unlikely(netpoll_tx_running(dev))) { - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, false); goto out; } if (br_multicast_rcv(br, NULL, skb)) { @@ -73,11 +73,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) br_multicast_deliver(mdst, skb); else - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, false); } else if ((dst = __br_fdb_get(br, dest, vid)) != NULL) br_deliver(dst->dst, skb); else - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, true); out: rcu_read_unlock(); diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 092b20e4ee4c..4b81b1471789 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -174,7 +174,8 @@ static struct net_bridge_port *maybe_deliver( static void br_flood(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb0, void (*__packet_hook)(const struct net_bridge_port *p, - struct sk_buff *skb)) + struct sk_buff *skb), + bool unicast) { struct net_bridge_port *p; struct net_bridge_port *prev; @@ -182,6 +183,9 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, prev = NULL; list_for_each_entry_rcu(p, &br->port_list, list) { + /* Do not flood unicast traffic to ports that turn it off */ + if (unicast && !(p->flags & BR_FLOOD)) + continue; prev = maybe_deliver(prev, p, skb, __packet_hook); if (IS_ERR(prev)) goto out; @@ -203,16 +207,16 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, /* called with rcu_read_lock */ -void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) +void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast) { - br_flood(br, skb, NULL, __br_deliver); + br_flood(br, skb, NULL, __br_deliver, unicast); } /* called under bridge lock */ void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, - struct sk_buff *skb2) + struct sk_buff *skb2, bool unicast) { - br_flood(br, skb, skb2, __br_forward); + br_flood(br, skb, skb2, __br_forward, unicast); } #ifdef CONFIG_BRIDGE_IGMP_SNOOPING diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 2c08911df578..5623be6b9ecd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -221,7 +221,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->path_cost = port_cost(dev); p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; - p->flags = BR_LEARNING; + p->flags = BR_LEARNING | BR_FLOOD; br_init_port(p); p->state = BR_STATE_DISABLED; br_stp_port_timer_init(p); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 7e993667d4bf..1b8b8b824cd7 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -65,6 +65,7 @@ int br_handle_frame_finish(struct sk_buff *skb) struct net_bridge_fdb_entry *dst; struct net_bridge_mdb_entry *mdst; struct sk_buff *skb2; + bool unicast = true; u16 vid = 0; if (!p || p->state == BR_STATE_DISABLED) @@ -95,9 +96,10 @@ int br_handle_frame_finish(struct sk_buff *skb) dst = NULL; - if (is_broadcast_ether_addr(dest)) + if (is_broadcast_ether_addr(dest)) { skb2 = skb; - else if (is_multicast_ether_addr(dest)) { + unicast = false; + } else if (is_multicast_ether_addr(dest)) { mdst = br_mdb_get(br, skb, vid); if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { if ((mdst && mdst->mglist) || @@ -110,6 +112,7 @@ int br_handle_frame_finish(struct sk_buff *skb) } else skb2 = skb; + unicast = false; br->dev->stats.multicast++; } else if ((dst = __br_fdb_get(br, dest, vid)) && dst->is_local) { @@ -123,7 +126,7 @@ int br_handle_frame_finish(struct sk_buff *skb) dst->used = jiffies; br_forward(dst->dst, skb, skb2); } else - br_flood_forward(br, skb, skb2); + br_flood_forward(br, skb, skb2, unicast); } if (skb2) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index ce902bf8a618..1fc30abd3a52 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -31,6 +31,7 @@ static inline size_t br_port_info_size(void) + nla_total_size(1) /* IFLA_BRPORT_PROTECT */ + nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */ + nla_total_size(1) /* IFLA_BRPORT_LEARNING */ + + nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */ + 0; } @@ -58,7 +59,8 @@ static int br_port_fill_attrs(struct sk_buff *skb, nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) || nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) || nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)) || - nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING))) + nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) || + nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, !!(p->flags & BR_FLOOD))) return -EMSGSIZE; return 0; @@ -284,6 +286,7 @@ static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = { [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 }, + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 }, }; /* Change the state of the port and notify spanning tree */ @@ -332,6 +335,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK); br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING); + br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD); if (tb[IFLA_BRPORT_COST]) { err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 04d7f43508f7..3be89b3ce17b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -159,6 +159,7 @@ struct net_bridge_port #define BR_MULTICAST_FAST_LEAVE 0x00000008 #define BR_ADMIN_COST 0x00000010 #define BR_LEARNING 0x00000020 +#define BR_FLOOD 0x00000040 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING u32 multicast_startup_queries_sent; @@ -414,9 +415,10 @@ extern int br_dev_queue_push_xmit(struct sk_buff *skb); extern void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0); extern int br_forward_finish(struct sk_buff *skb); -extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); +extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, + bool unicast); extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, - struct sk_buff *skb2); + struct sk_buff *skb2, bool unicast); /* br_if.c */ extern void br_port_carrier_check(struct net_bridge_port *p); diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 707f3628e9cd..2a2cdb756d51 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -159,6 +159,7 @@ BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); BRPORT_ATTR_FLAG(learning, BR_LEARNING); +BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD); #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -197,6 +198,7 @@ static const struct brport_attribute *brport_attrs[] = { &brport_attr_bpdu_guard, &brport_attr_root_block, &brport_attr_learning, + &brport_attr_unicast_flood, #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &brport_attr_multicast_router, &brport_attr_multicast_fast_leave, -- GitLab From 8249152c472e10c18936b774737fd58c60335154 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Thu, 6 Jun 2013 14:35:18 +0800 Subject: [PATCH 0837/2900] xen-netfront: use skb_partial_csum_set() to simplify the codes use skb_partial_csum_set() to simplify the codes Cc: Jason Wang Signed-off-by: Li RongQing Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 62238a08cb51..76a22365d4e9 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -858,7 +858,6 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np, static int checksum_setup(struct net_device *dev, struct sk_buff *skb) { struct iphdr *iph; - unsigned char *th; int err = -EPROTO; int recalculate_partial_csum = 0; @@ -883,27 +882,27 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb) goto out; iph = (void *)skb->data; - th = skb->data + 4 * iph->ihl; - if (th >= skb_tail_pointer(skb)) - goto out; - skb->csum_start = th - skb->head; switch (iph->protocol) { case IPPROTO_TCP: - skb->csum_offset = offsetof(struct tcphdr, check); + if (!skb_partial_csum_set(skb, 4 * iph->ihl, + offsetof(struct tcphdr, check))) + goto out; if (recalculate_partial_csum) { - struct tcphdr *tcph = (struct tcphdr *)th; + struct tcphdr *tcph = tcp_hdr(skb); tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - iph->ihl*4, IPPROTO_TCP, 0); } break; case IPPROTO_UDP: - skb->csum_offset = offsetof(struct udphdr, check); + if (!skb_partial_csum_set(skb, 4 * iph->ihl, + offsetof(struct udphdr, check))) + goto out; if (recalculate_partial_csum) { - struct udphdr *udph = (struct udphdr *)th; + struct udphdr *udph = udp_hdr(skb); udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len - iph->ihl*4, IPPROTO_UDP, 0); @@ -917,9 +916,6 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb) goto out; } - if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb)) - goto out; - err = 0; out: -- GitLab From da12c90e099789a63073fc82a19542ce54d4efb9 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 6 Jun 2013 14:49:11 +0800 Subject: [PATCH 0838/2900] netlink: Add compare function for netlink_table As we know, netlink sockets are private resource of net namespace, they can communicate with each other only when they in the same net namespace. this works well until we try to add namespace support for other subsystems which use netlink. Don't like ipv4 and route table.., it is not suited to make these subsytems belong to net namespace, Such as audit and crypto subsystems,they are more suitable to user namespace. So we must have the ability to make the netlink sockets in same user namespace can communicate with each other. This patch adds a new function pointer "compare" for netlink_table, we can decide if the netlink sockets can communicate with each other through this netlink_table self-defined compare function. The behavior isn't changed if we don't provide the compare function for netlink_table. Signed-off-by: Gao feng Acked-by: Serge E. Hallyn Signed-off-by: David S. Miller --- include/linux/netlink.h | 1 + net/netlink/af_netlink.c | 33 +++++++++++++++++++++++++-------- net/netlink/af_netlink.h | 1 + 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 6358da5eeee8..f78b430f4af5 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -46,6 +46,7 @@ struct netlink_kernel_cfg { void (*input)(struct sk_buff *skb); struct mutex *cb_mutex; void (*bind)(int group); + bool (*compare)(struct net *net, struct sock *sk); }; extern struct sock *__netlink_kernel_create(struct net *net, int unit, diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 68c167374394..9b6b115e008f 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -858,16 +858,23 @@ netlink_unlock_table(void) wake_up(&nl_table_wait); } +static bool netlink_compare(struct net *net, struct sock *sk) +{ + return net_eq(sock_net(sk), net); +} + static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) { - struct nl_portid_hash *hash = &nl_table[protocol].hash; + struct netlink_table *table = &nl_table[protocol]; + struct nl_portid_hash *hash = &table->hash; struct hlist_head *head; struct sock *sk; read_lock(&nl_table_lock); head = nl_portid_hashfn(hash, portid); sk_for_each(sk, head) { - if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->portid == portid)) { + if (table->compare(net, sk) && + (nlk_sk(sk)->portid == portid)) { sock_hold(sk); goto found; } @@ -980,7 +987,8 @@ netlink_update_listeners(struct sock *sk) static int netlink_insert(struct sock *sk, struct net *net, u32 portid) { - struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash; + struct netlink_table *table = &nl_table[sk->sk_protocol]; + struct nl_portid_hash *hash = &table->hash; struct hlist_head *head; int err = -EADDRINUSE; struct sock *osk; @@ -990,7 +998,8 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid) head = nl_portid_hashfn(hash, portid); len = 0; sk_for_each(osk, head) { - if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->portid == portid)) + if (table->compare(net, osk) && + (nlk_sk(osk)->portid == portid)) break; len++; } @@ -1165,6 +1174,7 @@ static int netlink_release(struct socket *sock) kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].bind = NULL; + nl_table[sk->sk_protocol].compare = NULL; nl_table[sk->sk_protocol].flags = 0; nl_table[sk->sk_protocol].registered = 0; } @@ -1187,7 +1197,8 @@ static int netlink_autobind(struct socket *sock) { struct sock *sk = sock->sk; struct net *net = sock_net(sk); - struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash; + struct netlink_table *table = &nl_table[sk->sk_protocol]; + struct nl_portid_hash *hash = &table->hash; struct hlist_head *head; struct sock *osk; s32 portid = task_tgid_vnr(current); @@ -1199,7 +1210,7 @@ static int netlink_autobind(struct socket *sock) netlink_table_grab(); head = nl_portid_hashfn(hash, portid); sk_for_each(osk, head) { - if (!net_eq(sock_net(osk), net)) + if (!table->compare(net, osk)) continue; if (nlk_sk(osk)->portid == portid) { /* Bind collision, search negative portid values. */ @@ -2315,9 +2326,12 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, rcu_assign_pointer(nl_table[unit].listeners, listeners); nl_table[unit].cb_mutex = cb_mutex; nl_table[unit].module = module; + nl_table[unit].compare = netlink_compare; if (cfg) { nl_table[unit].bind = cfg->bind; nl_table[unit].flags = cfg->flags; + if (cfg->compare) + nl_table[unit].compare = cfg->compare; } nl_table[unit].registered = 1; } else { @@ -2740,6 +2754,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *s; struct nl_seq_iter *iter; + struct net *net; int i, j; ++*pos; @@ -2747,11 +2762,12 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) return netlink_seq_socket_idx(seq, 0); + net = seq_file_net(seq); iter = seq->private; s = v; do { s = sk_next(s); - } while (s && sock_net(s) != seq_file_net(seq)); + } while (s && !nl_table[s->sk_protocol].compare(net, s)); if (s) return s; @@ -2763,7 +2779,8 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) for (; j <= hash->mask; j++) { s = sk_head(&hash->table[j]); - while (s && sock_net(s) != seq_file_net(seq)) + + while (s && !nl_table[s->sk_protocol].compare(net, s)) s = sk_next(s); if (s) { iter->link = i; diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index ed8522265f4e..eaa88d187cdc 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h @@ -73,6 +73,7 @@ struct netlink_table { struct mutex *cb_mutex; struct module *module; void (*bind)(int group); + bool (*compare)(struct net *net, struct sock *sock); int registered; }; -- GitLab From b41abb42bf62a85a32c41dab873220598a6ee266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Pan=28=E6=BD=98=E5=8D=AB=E5=B9=B3=29?= Date: Thu, 6 Jun 2013 21:27:21 +0800 Subject: [PATCH 0839/2900] net: pass correct parameter to skb_headers_offset_update() Since commit 1a37e412a022(net: Use 16bits for *_headers fields of struct skbuff), skb->*_header are relative to skb->head, so copy_skb_header() should not call skb_headers_offset_update() now, and we should pass correct parameter to skb_headers_offset_update() in pskb_expand_head() and skb_copy_expand(). Signed-off-by: Weiping Pan Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- net/core/skbuff.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4a4181e16c1a..edf37578e21e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -909,18 +909,8 @@ static void skb_headers_offset_update(struct sk_buff *skb, int off) static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) { -#ifndef NET_SKBUFF_DATA_USES_OFFSET - /* - * Shift between the two data areas in bytes - */ - unsigned long offset = new->data - old->data; -#endif - __copy_skb_header(new, old); -#ifndef NET_SKBUFF_DATA_USES_OFFSET - skb_headers_offset_update(new, offset); -#endif skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; @@ -1112,7 +1102,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, skb->end = skb->head + size; #endif skb->tail += off; - skb_headers_offset_update(skb, off); + skb_headers_offset_update(skb, nhead); /* Only adjust this if it actually is csum_start rather than csum */ if (skb->ip_summed == CHECKSUM_PARTIAL) skb->csum_start += nhead; @@ -1207,9 +1197,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, off = newheadroom - oldheadroom; if (n->ip_summed == CHECKSUM_PARTIAL) n->csum_start += off; -#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_headers_offset_update(n, off); -#endif return n; } -- GitLab From 45203a3b380cee28f570475c0d28c169f908c209 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Jun 2013 08:43:22 -0700 Subject: [PATCH 0840/2900] net_sched: add 64bit rate estimators struct gnet_stats_rate_est contains u32 fields, so the bytes per second field can wrap at 34360Mbit. Add a new gnet_stats_rate_est64 structure to get 64bit bps/pps fields, and switch the kernel to use this structure natively. This structure is dumped to user space as a new attribute : TCA_STATS_RATE_EST64 Old tc command will now display the capped bps (to 34360Mbit), instead of wrapped values, and updated tc command will display correct information. Old tc command output, after patch : eric:~# tc -s -d qd sh dev lo qdisc pfifo 8001: root refcnt 2 limit 1000p Sent 80868245400 bytes 1978837 pkt (dropped 0, overlimits 0 requeues 0) rate 34360Mbit 189696pps backlog 0b 0p requeues 0 This patch carefully reorganizes "struct Qdisc" layout to get optimal performance on SMP. Signed-off-by: Eric Dumazet Cc: Ben Hutchings Signed-off-by: David S. Miller --- include/net/act_api.h | 2 +- include/net/gen_stats.h | 10 +++++----- include/net/netfilter/xt_rateest.h | 2 +- include/net/sch_generic.h | 13 +++++++------ include/uapi/linux/gen_stats.h | 11 +++++++++++ net/core/gen_estimator.c | 12 ++++++------ net/core/gen_stats.c | 22 +++++++++++++++++----- net/netfilter/xt_rateest.c | 2 +- net/sched/sch_cbq.c | 2 +- net/sched/sch_drr.c | 2 +- net/sched/sch_hfsc.c | 2 +- net/sched/sch_htb.c | 2 +- net/sched/sch_qfq.c | 2 +- 13 files changed, 54 insertions(+), 30 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 06ef7e926a66..b8ffac7b6bab 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -18,7 +18,7 @@ struct tcf_common { struct tcf_t tcfc_tm; struct gnet_stats_basic_packed tcfc_bstats; struct gnet_stats_queue tcfc_qstats; - struct gnet_stats_rate_est tcfc_rate_est; + struct gnet_stats_rate_est64 tcfc_rate_est; spinlock_t tcfc_lock; struct rcu_head tcfc_rcu; }; diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index a79b6cfb02a8..cf8439ba4d11 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -30,7 +30,7 @@ extern int gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b); extern int gnet_stats_copy_rate_est(struct gnet_dump *d, const struct gnet_stats_basic_packed *b, - struct gnet_stats_rate_est *r); + struct gnet_stats_rate_est64 *r); extern int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q); extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); @@ -38,13 +38,13 @@ extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); extern int gnet_stats_finish_copy(struct gnet_dump *d); extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est, + struct gnet_stats_rate_est64 *rate_est, spinlock_t *stats_lock, struct nlattr *opt); extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est); + struct gnet_stats_rate_est64 *rate_est); extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est, + struct gnet_stats_rate_est64 *rate_est, spinlock_t *stats_lock, struct nlattr *opt); extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, - const struct gnet_stats_rate_est *rate_est); + const struct gnet_stats_rate_est64 *rate_est); #endif diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h index 5a2978d1cb22..495c71f66e7e 100644 --- a/include/net/netfilter/xt_rateest.h +++ b/include/net/netfilter/xt_rateest.h @@ -6,7 +6,7 @@ struct xt_rateest { struct gnet_stats_basic_packed bstats; spinlock_t lock; /* keep rstats and lock on same cache line to speedup xt_rateest_mt() */ - struct gnet_stats_rate_est rstats; + struct gnet_stats_rate_est64 rstats; /* following fields not accessed in hot path */ struct hlist_node list; diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e7f4e21cc3e1..df5676029827 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -58,14 +58,12 @@ struct Qdisc { * multiqueue device. */ #define TCQ_F_WARN_NONWC (1 << 16) - int padded; + u32 limit; const struct Qdisc_ops *ops; struct qdisc_size_table __rcu *stab; struct list_head list; u32 handle; u32 parent; - atomic_t refcnt; - struct gnet_stats_rate_est rate_est; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); @@ -76,8 +74,9 @@ struct Qdisc { */ struct Qdisc *__parent; struct netdev_queue *dev_queue; - struct Qdisc *next_sched; + struct gnet_stats_rate_est64 rate_est; + struct Qdisc *next_sched; struct sk_buff *gso_skb; /* * For performance sake on SMP, we put highly modified fields at the end @@ -88,8 +87,10 @@ struct Qdisc { unsigned int __state; struct gnet_stats_queue qstats; struct rcu_head rcu_head; - spinlock_t busylock; - u32 limit; + int padded; + atomic_t refcnt; + + spinlock_t busylock ____cacheline_aligned_in_smp; }; static inline bool qdisc_is_running(const struct Qdisc *qdisc) diff --git a/include/uapi/linux/gen_stats.h b/include/uapi/linux/gen_stats.h index 552c8a0a12d1..6487317ea619 100644 --- a/include/uapi/linux/gen_stats.h +++ b/include/uapi/linux/gen_stats.h @@ -9,6 +9,7 @@ enum { TCA_STATS_RATE_EST, TCA_STATS_QUEUE, TCA_STATS_APP, + TCA_STATS_RATE_EST64, __TCA_STATS_MAX, }; #define TCA_STATS_MAX (__TCA_STATS_MAX - 1) @@ -37,6 +38,16 @@ struct gnet_stats_rate_est { __u32 pps; }; +/** + * struct gnet_stats_rate_est64 - rate estimator + * @bps: current byte rate + * @pps: current packet rate + */ +struct gnet_stats_rate_est64 { + __u64 bps; + __u64 pps; +}; + /** * struct gnet_stats_queue - queuing statistics * @qlen: queue length diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index d9d198aa9fed..6b5b6e7013ca 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -82,7 +82,7 @@ struct gen_estimator { struct list_head list; struct gnet_stats_basic_packed *bstats; - struct gnet_stats_rate_est *rate_est; + struct gnet_stats_rate_est64 *rate_est; spinlock_t *stats_lock; int ewma_log; u64 last_bytes; @@ -167,7 +167,7 @@ static void gen_add_node(struct gen_estimator *est) static struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats, - const struct gnet_stats_rate_est *rate_est) + const struct gnet_stats_rate_est64 *rate_est) { struct rb_node *p = est_root.rb_node; @@ -203,7 +203,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats * */ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est, + struct gnet_stats_rate_est64 *rate_est, spinlock_t *stats_lock, struct nlattr *opt) { @@ -258,7 +258,7 @@ EXPORT_SYMBOL(gen_new_estimator); * Note : Caller should respect an RCU grace period before freeing stats_lock */ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est) + struct gnet_stats_rate_est64 *rate_est) { struct gen_estimator *e; @@ -290,7 +290,7 @@ EXPORT_SYMBOL(gen_kill_estimator); * Returns 0 on success or a negative error code. */ int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, - struct gnet_stats_rate_est *rate_est, + struct gnet_stats_rate_est64 *rate_est, spinlock_t *stats_lock, struct nlattr *opt) { gen_kill_estimator(bstats, rate_est); @@ -306,7 +306,7 @@ EXPORT_SYMBOL(gen_replace_estimator); * Returns true if estimator is active, and false if not. */ bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, - const struct gnet_stats_rate_est *rate_est) + const struct gnet_stats_rate_est64 *rate_est) { bool res; diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index ddedf211e588..9d3d9e78397b 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -143,18 +143,30 @@ EXPORT_SYMBOL(gnet_stats_copy_basic); int gnet_stats_copy_rate_est(struct gnet_dump *d, const struct gnet_stats_basic_packed *b, - struct gnet_stats_rate_est *r) + struct gnet_stats_rate_est64 *r) { + struct gnet_stats_rate_est est; + int res; + if (b && !gen_estimator_active(b, r)) return 0; + est.bps = min_t(u64, UINT_MAX, r->bps); + /* we have some time before reaching 2^32 packets per second */ + est.pps = r->pps; + if (d->compat_tc_stats) { - d->tc_stats.bps = r->bps; - d->tc_stats.pps = r->pps; + d->tc_stats.bps = est.bps; + d->tc_stats.pps = est.pps; } - if (d->tail) - return gnet_stats_copy(d, TCA_STATS_RATE_EST, r, sizeof(*r)); + if (d->tail) { + res = gnet_stats_copy(d, TCA_STATS_RATE_EST, &est, sizeof(est)); + if (res < 0 || est.bps == r->bps) + return res; + /* emit 64bit stats only if needed */ + return gnet_stats_copy(d, TCA_STATS_RATE_EST64, r, sizeof(*r)); + } return 0; } diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c index ed0db15ab00e..7720b036d76a 100644 --- a/net/netfilter/xt_rateest.c +++ b/net/netfilter/xt_rateest.c @@ -18,7 +18,7 @@ static bool xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct xt_rateest_match_info *info = par->matchinfo; - struct gnet_stats_rate_est *r; + struct gnet_stats_rate_est64 *r; u_int32_t bps1, bps2, pps1, pps2; bool ret = true; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 1bc210ffcba2..71a568862557 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -130,7 +130,7 @@ struct cbq_class { psched_time_t penalized; struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; + struct gnet_stats_rate_est64 rate_est; struct tc_cbq_xstats xstats; struct tcf_proto *filter_list; diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 759b308d1a8d..8302717ea303 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -25,7 +25,7 @@ struct drr_class { struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; + struct gnet_stats_rate_est64 rate_est; struct list_head alist; struct Qdisc *qdisc; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 9facea03faeb..c4075610502c 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -114,7 +114,7 @@ struct hfsc_class { struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; + struct gnet_stats_rate_est64 rate_est; unsigned int level; /* class level in hierarchy */ struct tcf_proto *filter_list; /* filter list */ unsigned int filter_cnt; /* filter count */ diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index adaedd79389c..162fb800754c 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -78,7 +78,7 @@ struct htb_class { /* general class parameters */ struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; + struct gnet_stats_rate_est64 rate_est; struct tc_htb_xstats xstats; /* our special stats */ int refcnt; /* usage count of this class */ diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index d51852bba01c..7c195d972bf0 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -138,7 +138,7 @@ struct qfq_class { struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; + struct gnet_stats_rate_est64 rate_est; struct Qdisc *qdisc; struct list_head alist; /* Link for active-classes list. */ struct qfq_aggregate *agg; /* Parent aggregate. */ -- GitLab From ecccd072b07e7fd09c54d0f86f9374e2645cde97 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Mon, 10 Jun 2013 13:17:21 -0700 Subject: [PATCH 0841/2900] mac80211: fix mesh deadlock The patch "cfg80211/mac80211: use cfg80211 wdev mutex in mac80211" introduced several deadlocks by converting the ifmsh->mtx to wdev->mtx. Solve these by: 1. drop the cancel_work_sync() in ieee80211_stop_mesh(). Instead make the mesh work conditional on whether the mesh is running or not. 2. lock the mesh work with sdata_lock() to protect beacon updates and prevent races with wdev->mesh_id_len or cfg80211. Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 29 +++++++++++++++++------------ net/mac80211/mesh_plink.c | 7 +------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 73a597bad6e0..d5faf91632c1 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -579,9 +579,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) mesh_path_expire(sdata); changed = mesh_accept_plinks_update(sdata); - sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); - sdata_unlock(sdata); mod_timer(&ifmsh->housekeeping_timer, round_jiffies(jiffies + @@ -788,12 +786,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.enable_beacon = false; clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - sdata_lock(sdata); bcn = rcu_dereference_protected(ifmsh->beacon, lockdep_is_held(&sdata->wdev.mtx)); rcu_assign_pointer(ifmsh->beacon, NULL); kfree_rcu(bcn, rcu_head); - sdata_unlock(sdata); /* flush STAs and mpaths on this iface */ sta_info_flush(sdata); @@ -806,14 +802,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); del_timer_sync(&sdata->u.mesh.mesh_path_timer); - /* - * If the timer fired while we waited for it, it will have - * requeued the work. Now the work will be running again - * but will not rearm the timer again because it checks - * whether the interface is running, which, at this point, - * it no longer is. - */ - cancel_work_sync(&sdata->work); local->fif_other_bss--; atomic_dec(&local->iff_allmultis); @@ -954,6 +942,12 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; u16 stype; + sdata_lock(sdata); + + /* mesh already went down */ + if (!sdata->wdev.mesh_id_len) + goto out; + rx_status = IEEE80211_SKB_RXCB(skb); mgmt = (struct ieee80211_mgmt *) skb->data; stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; @@ -971,12 +965,20 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); break; } +out: + sdata_unlock(sdata); } void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + sdata_lock(sdata); + + /* mesh already went down */ + if (!sdata->wdev.mesh_id_len) + goto out; + if (ifmsh->preq_queue_len && time_after(jiffies, ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) @@ -996,6 +998,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) mesh_sync_adjust_tbtt(sdata); + +out: + sdata_unlock(sdata); } void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 6c4da99bc4fb..09bebed99416 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -517,9 +517,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, ieee80211_mps_frame_release(sta, elems); out: rcu_read_unlock(); - sdata_lock(sdata); ieee80211_mbss_info_change_notify(sdata, changed); - sdata_unlock(sdata); } static void mesh_plink_timer(unsigned long data) @@ -1070,9 +1068,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, rcu_read_unlock(); - if (changed) { - sdata_lock(sdata); + if (changed) ieee80211_mbss_info_change_notify(sdata, changed); - sdata_unlock(sdata); - } } -- GitLab From a0a2af765543a96bdf188ec57dd201e708195302 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 3 Jun 2013 18:10:45 +0200 Subject: [PATCH 0842/2900] nl80211: add kernel-doc for NL80211_FEATURE_ACTIVE_MONITOR Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- include/uapi/linux/nl80211.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 5920715278c2..1f0019d4cce6 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -3579,6 +3579,10 @@ enum nl80211_ap_sme_features { * Peering Management entity which may be implemented by registering for * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is * still generated by the driver. + * @NL80211_FEATURE_ACTIVE_MONITOR: This driver supports an active monitor + * interface. An active monitor interface behaves like a normal monitor + * interface, but gets added to the driver. It ensures that incoming + * unicast packets directed at the configured interface address get ACKed. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, -- GitLab From 8e7c053853b7d299e8a2b8733659b0df8eee51f7 Mon Sep 17 00:00:00 2001 From: Colleen Twitty Date: Mon, 3 Jun 2013 09:53:39 -0700 Subject: [PATCH 0843/2900] {nl,cfg}80211: make peer link expiration time configurable If a STA has a peer that it hasn't seen any tx activity from for a certain length of time, the peer link is expired. This means the inactive STA is removed from the list of peers and that STA is not considered a peer again unless it re-peers. Previously, this inactivity time was always 30 minutes. Now, add it to the mesh configuration and allow it to be configured. Retain 30 minutes as a default value. Signed-off-by: Colleen Twitty Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++++ include/uapi/linux/nl80211.h | 5 +++++ net/wireless/mesh.c | 2 ++ net/wireless/nl80211.c | 8 +++++++- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 855c76ccff38..31ca11672ca8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1124,6 +1124,9 @@ struct bss_parameters { * setting for new peer links. * @dot11MeshAwakeWindowDuration: The duration in TUs the STA will remain awake * after transmitting its beacon. + * @plink_timeout: If no tx activity is seen from a STA we've established + * peering with for longer than this time (in seconds), then remove it + * from the STA's list of peers. Default is 30 minutes. */ struct mesh_config { u16 dot11MeshRetryTimeout; @@ -1153,6 +1156,7 @@ struct mesh_config { u16 dot11MeshHWMPconfirmationInterval; enum nl80211_mesh_power_mode power_mode; u16 dot11MeshAwakeWindowDuration; + u32 plink_timeout; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 1f0019d4cce6..ca6facf4df0c 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2577,6 +2577,10 @@ enum nl80211_mesh_power_mode { * * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) * + * @NL80211_MESHCONF_PLINK_TIMEOUT: If no tx activity is seen from a STA we've + * established peering with for longer than this time (in seconds), then + * remove it from the STA's list of peers. Default is 30 minutes. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -2608,6 +2612,7 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, NL80211_MESHCONF_POWER_MODE, NL80211_MESHCONF_AWAKE_WINDOW, + NL80211_MESHCONF_PLINK_TIMEOUT, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 5dfb289ab761..0daaf72e1b81 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -18,6 +18,7 @@ #define MESH_PATH_TO_ROOT_TIMEOUT 6000 #define MESH_ROOT_INTERVAL 5000 #define MESH_ROOT_CONFIRMATION_INTERVAL 2000 +#define MESH_DEFAULT_PLINK_TIMEOUT 1800 /* timeout in seconds */ /* * Minimum interval between two consecutive PREQs originated by the same @@ -75,6 +76,7 @@ const struct mesh_config default_mesh_config = { .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, .power_mode = NL80211_MESH_POWER_ACTIVE, .dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW, + .plink_timeout = MESH_DEFAULT_PLINK_TIMEOUT, }; const struct mesh_setup default_mesh_setup = { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 88e820b73674..8aa83c04d4eb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4575,7 +4575,9 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE, cur_params.power_mode) || nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW, - cur_params.dot11MeshAwakeWindowDuration)) + cur_params.dot11MeshAwakeWindowDuration) || + nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, + cur_params.plink_timeout)) goto nla_put_failure; nla_nest_end(msg, pinfoattr); genlmsg_end(msg, hdr); @@ -4616,6 +4618,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, + [NL80211_MESHCONF_PLINK_TIMEOUT] = { .type = NLA_U32 }, }; static const struct nla_policy @@ -4753,6 +4756,9 @@ do { \ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, 0, 65535, mask, NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 1, 0xffffffff, + mask, NL80211_MESHCONF_PLINK_TIMEOUT, + nla_get_u32); if (mask_out) *mask_out = mask; -- GitLab From 66de671374f003467b5ef7c65ecbe1930480c8c9 Mon Sep 17 00:00:00 2001 From: Colleen Twitty Date: Mon, 3 Jun 2013 09:53:40 -0700 Subject: [PATCH 0844/2900] mac80211: expire mesh peers based on mesh configuration The time it takes to see the peer link expire may differ by a minute since sta_expire() is run once a minute as a mesh housekeeping task. Signed-off-by: Colleen Twitty Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 2 ++ net/mac80211/mesh.c | 2 +- net/mac80211/mesh.h | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 30622101d3b5..344a57968079 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1871,6 +1871,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask)) conf->dot11MeshAwakeWindowDuration = nconf->dot11MeshAwakeWindowDuration; + if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask)) + conf->plink_timeout = nconf->plink_timeout; ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); return 0; } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d5faf91632c1..4ee527f78677 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -575,7 +575,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; u32 changed; - ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + ieee80211_sta_expire(sdata, ifmsh->mshcfg.plink_timeout * HZ); mesh_path_expire(sdata); changed = mesh_accept_plinks_update(sdata); diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8b4d9a3e9eee..01a28bca6e9b 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -188,7 +188,6 @@ struct mesh_rmc { u32 idx_mask; }; -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) #define MESH_PATH_EXPIRE (600 * HZ) -- GitLab From ffb3cf3000aa12facdccbdfcb10bfebda7199209 Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Mon, 3 Jun 2013 10:33:36 -0700 Subject: [PATCH 0845/2900] {nl,mac,cfg}80211: Allow user to configure basic rates for mesh Currently mesh uses mandatory rates as the default basic rates. Allow basic rates to be configured during mesh join. Basic rates are applied only if channel is also provided with mesh join command. Signed-off-by: Ashok Nagarajan [some whitespace fixes, refuse basic rates w/o channel] Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ net/mac80211/cfg.c | 1 + net/mac80211/mesh.c | 4 ---- net/wireless/mesh.c | 10 ++++++++++ net/wireless/nl80211.c | 17 +++++++++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 31ca11672ca8..6a43c34ce96f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1176,6 +1176,7 @@ struct mesh_config { * @dtim_period: DTIM period to use * @beacon_interval: beacon interval to use * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] + * @basic_rates: basic rates to use when creating the mesh * * These parameters are fixed when the mesh is created. */ @@ -1195,6 +1196,7 @@ struct mesh_setup { u8 dtim_period; u16 beacon_interval; int mcast_rate[IEEE80211_NUM_BANDS]; + u32 basic_rates; }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 344a57968079..cd6f35f6e714 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1759,6 +1759,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, /* mcast rate setting in Mesh Node */ memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, sizeof(setup->mcast_rate)); + sdata->vif.bss_conf.basic_rates = setup->basic_rates; sdata->vif.bss_conf.beacon_int = setup->beacon_interval; sdata->vif.bss_conf.dtim_period = setup->dtim_period; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 4ee527f78677..6c33af482df4 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -738,9 +738,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) BSS_CHANGED_HT | BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BEACON_INT; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); - struct ieee80211_supported_band *sband = - sdata->local->hw.wiphy->bands[band]; local->fif_other_bss++; /* mesh ifaces must set allmulti to forward mcast traffic */ @@ -758,7 +755,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.ht_operation_mode = ifmsh->mshcfg.ht_opmode; sdata->vif.bss_conf.enable_beacon = true; - sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband); changed |= ieee80211_mps_local_status_update(sdata); diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 0daaf72e1b81..30c49202ee4d 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -162,6 +162,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, setup->chandef.center_freq1 = setup->chandef.chan->center_freq; } + /* + * check if basic rates are available otherwise use mandatory rates as + * basic rates + */ + if (!setup->basic_rates) { + struct ieee80211_supported_band *sband = + rdev->wiphy.bands[setup->chandef.chan->band]; + setup->basic_rates = ieee80211_mandatory_rates(sband); + } + if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) return -EINVAL; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8aa83c04d4eb..687cb6497598 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7487,6 +7487,23 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) setup.chandef.chan = NULL; } + if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { + u8 *rates = nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); + int n_rates = + nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); + struct ieee80211_supported_band *sband; + + if (!setup.chandef.chan) + return -EINVAL; + + sband = rdev->wiphy.bands[setup.chandef.chan->band]; + + err = ieee80211_get_ratemask(sband, rates, n_rates, + &setup.basic_rates); + if (err) + return err; + } + return cfg80211_join_mesh(rdev, dev, &setup, &cfg); } -- GitLab From 3d124ea27ae2fc895f81725f0b4c7f3d9c733df4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 27 May 2013 18:24:02 +0300 Subject: [PATCH 0846/2900] cfg80211: fix VHT TDLS peer AID verification I (Johannes) accidentally applied the first version of the patch ("Allow TDLS peer AID to be configured for VHT"). Now apply just the changes between v1 and v2 to get the AID verification and prefer the new attribute over the old one. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 687cb6497598..7183410fcd41 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3972,10 +3972,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - if (info->attrs[NL80211_ATTR_STA_AID]) - params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); - else + if (info->attrs[NL80211_ATTR_PEER_AID]) params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); + else + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); if (!params.aid || params.aid > IEEE80211_MAX_AID) return -EINVAL; @@ -4027,7 +4027,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD; /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; /* but don't bother the driver with it */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); @@ -4053,7 +4054,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) return -EINVAL; /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; break; case NL80211_IFTYPE_STATION: -- GitLab From f7aeb6fb1a3d6b09623b169518314bc7869fffec Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Jun 2013 14:20:00 +0200 Subject: [PATCH 0847/2900] mac80211: make mgmt_tx accept a NULL channel cfg80211 passes a NULL channel to mgmt_tx if the frame has to be sent on the one currently in use by the device. Make the implementation of mgmt_tx correctly handle this case. Fail if offchan is required. Signed-off-by: Antonio Quartulli [fix RCU locking] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index cd6f35f6e714..64cf294c2b96 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2841,6 +2841,12 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return -EOPNOTSUPP; } + /* configurations requiring offchan cannot work if no channel has been + * specified + */ + if (need_offchan && !chan) + return -EINVAL; + mutex_lock(&local->mtx); /* Check if the operating channel is the requested channel */ @@ -2850,10 +2856,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (chanctx_conf) - need_offchan = chan != chanctx_conf->def.chan; - else + if (chanctx_conf) { + need_offchan = chan && (chan != chanctx_conf->def.chan); + } else if (!chan) { + ret = -EINVAL; + rcu_read_unlock(); + goto out_unlock; + } else { need_offchan = true; + } rcu_read_unlock(); } -- GitLab From c2ff8cad64233b539c71a27e2a6e324001143ef0 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Jun 2013 14:20:01 +0200 Subject: [PATCH 0848/2900] brcm80211: make mgmt_tx in brcmfmac accept a NULL channel cfg80211 passes a NULL channel to mgmt_tx if the frame has to be sent on the one currently in use by the device. Make the implementation of mgmt_tx correctly handle this case Cc: brcm80211-dev-list@broadcom.com Acked-by: Arend van Spriel Signed-off-by: Antonio Quartulli Signed-off-by: Johannes Berg --- .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 6d758f285352..8bd256ba66ab 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3917,6 +3917,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, struct brcmf_fil_af_params_le *af_params; bool ack; s32 chan_nr; + u32 freq; brcmf_dbg(TRACE, "Enter\n"); @@ -3929,6 +3930,8 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return -EPERM; } + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + if (ieee80211_is_probe_resp(mgmt->frame_control)) { /* Right now the only reason to get a probe response */ /* is for p2p listen response or for p2p GO from */ @@ -3944,7 +3947,6 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; ie_len = len - ie_offset; - vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; err = brcmf_vif_set_mgmt_ie(vif, @@ -3968,8 +3970,15 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN); /* Add the length exepted for 802.11 header */ action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN); - /* Add the channel */ - chan_nr = ieee80211_frequency_to_channel(chan->center_freq); + /* Add the channel. Use the one specified as parameter if any or + * the current one (got from the firmware) otherwise + */ + if (chan) + freq = chan->center_freq; + else + brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL, + &freq); + chan_nr = ieee80211_frequency_to_channel(freq); af_params->channel = cpu_to_le32(chan_nr); memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], -- GitLab From bfd634d01e02071404e3e36e3946728009ed023f Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Jun 2013 14:20:02 +0200 Subject: [PATCH 0849/2900] ath6kl: make mgmt_tx accept a NULL channel cfg80211 passes a NULL channel to mgmt_tx if the frame has to be sent on the one currently in use by the device. Make the implementation of mgmt_tx correctly handle this case Cc: Nicolas Cavallari Acked-by: Kalle Valo Signed-off-by: Antonio Quartulli Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index f7995b2b12a4..2437ad26949d 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3175,10 +3175,21 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, { struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev); struct ath6kl *ar = ath6kl_priv(vif->ndev); - u32 id; + u32 id, freq; const struct ieee80211_mgmt *mgmt; bool more_data, queued; + /* default to the current channel, but use the one specified as argument + * if any + */ + freq = vif->ch_hint; + if (chan) + freq = chan->center_freq; + + /* never send freq zero to the firmware */ + if (WARN_ON(freq == 0)) + return -EINVAL; + mgmt = (const struct ieee80211_mgmt *) buf; if (vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) && ieee80211_is_probe_resp(mgmt->frame_control) && @@ -3188,8 +3199,7 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * command to allow the target to fill in the generic IEs. */ *cookie = 0; /* TX status not supported */ - return ath6kl_send_go_probe_resp(vif, buf, len, - chan->center_freq); + return ath6kl_send_go_probe_resp(vif, buf, len, freq); } id = vif->send_action_id++; @@ -3205,17 +3215,14 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, /* AP mode Power saving processing */ if (vif->nw_type == AP_NETWORK) { - queued = ath6kl_mgmt_powersave_ap(vif, - id, chan->center_freq, - wait, buf, - len, &more_data, no_cck); + queued = ath6kl_mgmt_powersave_ap(vif, id, freq, wait, buf, len, + &more_data, no_cck); if (queued) return 0; } - return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id, - chan->center_freq, wait, - buf, len, no_cck); + return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id, freq, + wait, buf, len, no_cck); } static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, -- GitLab From ea141b75ae29636b5c9e9d2e2e77b3dd1ab4c934 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 11 Jun 2013 14:20:03 +0200 Subject: [PATCH 0850/2900] nl80211: allow sending CMD_FRAME without specifying any frequency Users may want to send a frame on the current channel without specifying it. This is particularly useful for the correct implementation of the IBSS/RSN support in wpa_supplicant which requires to receive and send AUTH frames. Make mgmt_tx pass a NULL channel to the driver if none has been specified by the user. Signed-off-by: Antonio Quartulli Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7183410fcd41..398ce2c59686 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7147,6 +7147,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) return -EOPNOTSUPP; switch (wdev->iftype) { + case NL80211_IFTYPE_P2P_DEVICE: + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) + return -EINVAL; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_P2P_CLIENT: @@ -7154,7 +7157,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_P2P_GO: - case NL80211_IFTYPE_P2P_DEVICE: break; default: return -EOPNOTSUPP; @@ -7182,9 +7184,18 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); - err = nl80211_parse_chandef(rdev, info, &chandef); - if (err) - return err; + /* get the channel if any has been specified, otherwise pass NULL to + * the driver. The latter will use the current one + */ + chandef.chan = NULL; + if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { + err = nl80211_parse_chandef(rdev, info, &chandef); + if (err) + return err; + } + + if (!chandef.chan && offchan) + return -EINVAL; if (!dont_wait_for_ack) { msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -- GitLab From 5a5f1efc8f5bce01773c6b769d7912a15e8eee07 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 11 Jun 2013 08:02:55 +0000 Subject: [PATCH 0851/2900] MIPS: kernel: mcount.S: Drop FRAME_POINTER codepath CONFIG_FRAME_POINTER is not selectable for MIPS so this codepath was never executed. Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5440/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/mcount.S | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S index 33d067148e61..a03e93c4a946 100644 --- a/arch/mips/kernel/mcount.S +++ b/arch/mips/kernel/mcount.S @@ -168,14 +168,10 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra) #endif /* arg3: Get frame pointer of current stack */ -#ifdef CONFIG_FRAME_POINTER - move a2, fp -#else /* ! CONFIG_FRAME_POINTER */ #ifdef CONFIG_64BIT PTR_LA a2, PT_SIZE(sp) #else PTR_LA a2, (PT_SIZE+8)(sp) -#endif #endif jal prepare_ftrace_return -- GitLab From 940d0ac9dbe3fb9d4806e96f006286c2e476deed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 11 Jun 2013 16:51:03 +0200 Subject: [PATCH 0852/2900] cfg80211: fix rtnl leak in wiphy dump error cases In two wiphy dump error cases, most often when the dump allocation must be increased, the RTNL is leaked. This quickly results in a complete system lockup. Release the RTNL correctly. Reported-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 398ce2c59686..e4028197b75d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1541,8 +1541,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); netdev = dev_get_by_index(sock_net(skb->sk), ifidx); - if (!netdev) + if (!netdev) { + rtnl_unlock(); return -ENODEV; + } if (netdev->ieee80211_ptr) { dev = wiphy_to_dev( netdev->ieee80211_ptr->wiphy); @@ -1586,6 +1588,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) !skb->len && cb->min_dump_alloc < 4096) { cb->min_dump_alloc = 4096; + rtnl_unlock(); return 1; } idx--; -- GitLab From fa8eeae102570dfdf3fd14347a0671cff8a2cfe4 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 11 Jun 2013 09:49:38 -0400 Subject: [PATCH 0853/2900] cw1200: Remove "ITP" debug subsystem. This can live on as an out-of-tree patch for those that care. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/Kconfig | 5 - drivers/net/wireless/cw1200/Makefile | 1 - drivers/net/wireless/cw1200/debug.c | 6 +- drivers/net/wireless/cw1200/debug.h | 5 - drivers/net/wireless/cw1200/itp.c | 730 --------------------------- drivers/net/wireless/cw1200/itp.h | 144 ------ drivers/net/wireless/cw1200/txrx.c | 10 +- drivers/net/wireless/cw1200/wsm.c | 7 - 8 files changed, 3 insertions(+), 905 deletions(-) delete mode 100644 drivers/net/wireless/cw1200/itp.c delete mode 100644 drivers/net/wireless/cw1200/itp.h diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig index 7a585d4e9c8e..fc1b472460c8 100644 --- a/drivers/net/wireless/cw1200/Kconfig +++ b/drivers/net/wireless/cw1200/Kconfig @@ -35,11 +35,6 @@ config CW1200_ETF help If you don't know what this is, just say N. -config CW1200_ITP - bool "Enable ITP access" - help - If you don't know what this is, just say N. - endmenu endif diff --git a/drivers/net/wireless/cw1200/Makefile b/drivers/net/wireless/cw1200/Makefile index bc6cbf91f26e..b086aac6547a 100644 --- a/drivers/net/wireless/cw1200/Makefile +++ b/drivers/net/wireless/cw1200/Makefile @@ -9,7 +9,6 @@ cw1200_core-y := \ sta.o \ scan.o \ debug.o -cw1200_core-$(CONFIG_CW1200_ITP) += itp.o cw1200_core-$(CONFIG_PM) += pm.o # CFLAGS_sta.o += -DDEBUG diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index 1596b7042cbd..ac9c219c6330 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -559,10 +559,6 @@ int cw1200_debug_init(struct cw1200_common *priv) priv, &fops_wsm_dumps)) goto err; - ret = cw1200_itp_init(priv); - if (ret) - goto err; - return 0; err: @@ -576,7 +572,7 @@ void cw1200_debug_release(struct cw1200_common *priv) { struct cw1200_debug_priv *d = priv->debug; if (d) { - cw1200_itp_release(priv); + debugfs_remove_recursive(d->debugfs_phy); priv->debug = NULL; kfree(d); } diff --git a/drivers/net/wireless/cw1200/debug.h b/drivers/net/wireless/cw1200/debug.h index 1fea5b29a819..b525aba53bfc 100644 --- a/drivers/net/wireless/cw1200/debug.h +++ b/drivers/net/wireless/cw1200/debug.h @@ -12,8 +12,6 @@ #ifndef CW1200_DEBUG_H_INCLUDED #define CW1200_DEBUG_H_INCLUDED -#include "itp.h" - struct cw1200_debug_priv { struct dentry *debugfs_phy; int tx; @@ -30,9 +28,6 @@ struct cw1200_debug_priv { int ba_acc; int ba_cnt_rx; int ba_acc_rx; -#ifdef CONFIG_CW1200_ITP - struct cw1200_itp itp; -#endif /* CONFIG_CW1200_ITP */ }; int cw1200_debug_init(struct cw1200_common *priv); diff --git a/drivers/net/wireless/cw1200/itp.c b/drivers/net/wireless/cw1200/itp.c deleted file mode 100644 index c0730bb49b75..000000000000 --- a/drivers/net/wireless/cw1200/itp.c +++ /dev/null @@ -1,730 +0,0 @@ -/* - * mac80211 glue code for mac80211 ST-Ericsson CW1200 drivers - * ITP code - * - * Copyright (c) 2010, ST-Ericsson - * Author: Dmitry Tarnyagin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "cw1200.h" -#include "debug.h" -#include "itp.h" -#include "sta.h" - -static int __cw1200_itp_open(struct cw1200_common *priv); -static int __cw1200_itp_close(struct cw1200_common *priv); -static void cw1200_itp_rx_start(struct cw1200_common *priv); -static void cw1200_itp_rx_stop(struct cw1200_common *priv); -static void cw1200_itp_rx_stats(struct cw1200_common *priv); -static void cw1200_itp_rx_reset(struct cw1200_common *priv); -static void cw1200_itp_tx_stop(struct cw1200_common *priv); -static void cw1200_itp_handle(struct cw1200_common *priv, - struct sk_buff *skb); -static void cw1200_itp_err(struct cw1200_common *priv, - int err, - int arg); -static void __cw1200_itp_tx_stop(struct cw1200_common *priv); - -static ssize_t cw1200_itp_read(struct file *file, - char __user *user_buf, size_t count, loff_t *ppos) -{ - struct cw1200_common *priv = file->private_data; - struct cw1200_itp *itp = &priv->debug->itp; - struct sk_buff *skb; - int ret; - - if (skb_queue_empty(&itp->log_queue)) - return 0; - - skb = skb_dequeue(&itp->log_queue); - ret = copy_to_user(user_buf, skb->data, skb->len); - *ppos += skb->len; - skb->data[skb->len] = 0; - pr_debug("[ITP] >>> %s", skb->data); - consume_skb(skb); - - return skb->len - ret; -} - -static ssize_t cw1200_itp_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct cw1200_common *priv = file->private_data; - struct sk_buff *skb; - - if (!count || count > 1024) - return -EINVAL; - skb = dev_alloc_skb(count + 1); - if (!skb) - return -ENOMEM; - skb_trim(skb, 0); - skb_put(skb, count + 1); - if (copy_from_user(skb->data, user_buf, count)) { - kfree_skb(skb); - return -EFAULT; - } - skb->data[count] = 0; - - cw1200_itp_handle(priv, skb); - consume_skb(skb); - return count; -} - -static unsigned int cw1200_itp_poll(struct file *file, poll_table *wait) -{ - struct cw1200_common *priv = file->private_data; - struct cw1200_itp *itp = &priv->debug->itp; - unsigned int mask = 0; - - poll_wait(file, &itp->read_wait, wait); - - if (!skb_queue_empty(&itp->log_queue)) - mask |= POLLIN | POLLRDNORM; - - mask |= POLLOUT | POLLWRNORM; - - return mask; -} - -static int cw1200_itp_open(struct inode *inode, struct file *file) -{ - struct cw1200_common *priv = inode->i_private; - struct cw1200_itp *itp = &priv->debug->itp; - int ret = 0; - - file->private_data = priv; - if (atomic_inc_return(&itp->open_count) == 1) { - ret = __cw1200_itp_open(priv); - if (ret && !atomic_dec_return(&itp->open_count)) - __cw1200_itp_close(priv); - } else { - atomic_dec(&itp->open_count); - ret = -EBUSY; - } - - return ret; -} - -static int cw1200_itp_close(struct inode *inode, struct file *file) -{ - struct cw1200_common *priv = file->private_data; - struct cw1200_itp *itp = &priv->debug->itp; - if (!atomic_dec_return(&itp->open_count)) { - __cw1200_itp_close(priv); - wake_up(&itp->close_wait); - } - return 0; -} - -static const struct file_operations fops_itp = { - .open = cw1200_itp_open, - .read = cw1200_itp_read, - .write = cw1200_itp_write, - .poll = cw1200_itp_poll, - .release = cw1200_itp_close, - .llseek = default_llseek, - .owner = THIS_MODULE, -}; - -static void cw1200_itp_fill_pattern(u8 *data, int size, - enum cw1200_itp_data_modes mode) -{ - if (size <= 0) - return; - - switch (mode) { - default: - case ITP_DATA_ZEROS: - memset(data, 0x0, size); - break; - case ITP_DATA_ONES: - memset(data, 0xff, size); - break; - case ITP_DATA_ZERONES: - memset(data, 0x55, size); - break; - case ITP_DATA_RANDOM: - get_random_bytes(data, size); - break; - } - return; -} - -static void cw1200_itp_tx_work(struct work_struct *work) -{ - struct cw1200_itp *itp = container_of(work, struct cw1200_itp, - tx_work.work); - struct cw1200_common *priv = itp->priv; - atomic_set(&priv->bh_tx, 1); - wake_up(&priv->bh_wq); -} - -static void cw1200_itp_tx_finish(struct work_struct *work) -{ - struct cw1200_itp *itp = container_of(work, struct cw1200_itp, - tx_finish.work); - __cw1200_itp_tx_stop(itp->priv); -} - -int cw1200_itp_init(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - - itp->priv = priv; - atomic_set(&itp->open_count, 0); - atomic_set(&itp->stop_tx, 0); - atomic_set(&itp->awaiting_confirm, 0); - skb_queue_head_init(&itp->log_queue); - spin_lock_init(&itp->tx_lock); - init_waitqueue_head(&itp->read_wait); - init_waitqueue_head(&itp->write_wait); - init_waitqueue_head(&itp->close_wait); - INIT_DELAYED_WORK(&itp->tx_work, cw1200_itp_tx_work); - INIT_DELAYED_WORK(&itp->tx_finish, cw1200_itp_tx_finish); - itp->data = NULL; - itp->hdr_len = WSM_TX_EXTRA_HEADROOM + - sizeof(struct ieee80211_hdr_3addr); - - if (!debugfs_create_file("itp", S_IRUSR | S_IWUSR, - priv->debug->debugfs_phy, priv, &fops_itp)) - return -ENOMEM; - - return 0; -} - -void cw1200_itp_release(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - - wait_event_interruptible(itp->close_wait, - !atomic_read(&itp->open_count)); - - WARN_ON(atomic_read(&itp->open_count)); - - skb_queue_purge(&itp->log_queue); - cw1200_itp_tx_stop(priv); -} - -static int __cw1200_itp_open(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - - if (!priv->vif) - return -EINVAL; - if (priv->join_status) - return -EINVAL; - itp->saved_channel = priv->channel; - if (!priv->channel) - priv->channel = &priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0]; - wsm_set_bssid_filtering(priv, false); - cw1200_itp_rx_reset(priv); - return 0; -} - -static int __cw1200_itp_close(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - if (atomic_read(&itp->test_mode) == TEST_MODE_RX_TEST) - cw1200_itp_rx_stop(priv); - cw1200_itp_tx_stop(priv); - cw1200_disable_listening(priv); - cw1200_update_filtering(priv); - priv->channel = itp->saved_channel; - return 0; -} - -bool cw1200_is_itp(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - return atomic_read(&itp->open_count) != 0; -} - -static void cw1200_itp_rx_reset(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - itp->rx_cnt = 0; - itp->rx_rssi = 0; - itp->rx_rssi_max = -1000; - itp->rx_rssi_min = 1000; -} - -static void cw1200_itp_rx_start(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - - pr_debug("[ITP] RX start, band = %d, ch = %d\n", - itp->band, itp->ch); - atomic_set(&itp->test_mode, TEST_MODE_RX_TEST); - cw1200_update_listening(priv, false); - priv->channel = &priv->hw-> - wiphy->bands[itp->band]->channels[itp->ch]; - cw1200_update_listening(priv, true); - wsm_set_bssid_filtering(priv, false); -} - -static void cw1200_itp_rx_stop(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - pr_debug("[ITP] RX stop\n"); - atomic_set(&itp->test_mode, TEST_MODE_NO_TEST); - cw1200_itp_rx_reset(priv); -} - -static void cw1200_itp_rx_stats(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - struct sk_buff *skb; - char buf[128]; - int len, ret; - struct wsm_mib_counters_table counters; - - ret = wsm_get_counters_table(priv, &counters); - - if (ret) - cw1200_itp_err(priv, -EBUSY, 20); - - if (!itp->rx_cnt) - len = snprintf(buf, sizeof(buf), "1,0,0,0,0,%d\n", - counters.rx_packet_errors); - else - len = snprintf(buf, sizeof(buf), "1,%d,%ld,%d,%d,%d\n", - itp->rx_cnt, - itp->rx_cnt ? itp->rx_rssi / itp->rx_cnt : 0, - itp->rx_rssi_min, itp->rx_rssi_max, - counters.rx_packet_errors); - - if (len <= 0) { - cw1200_itp_err(priv, -EBUSY, 21); - return; - } - - skb = dev_alloc_skb(len); - if (!skb) { - cw1200_itp_err(priv, -ENOMEM, 22); - return; - } - - itp->rx_cnt = 0; - itp->rx_rssi = 0; - itp->rx_rssi_max = -1000; - itp->rx_rssi_min = 1000; - - skb_trim(skb, 0); - skb_put(skb, len); - - memcpy(skb->data, buf, len); - skb_queue_tail(&itp->log_queue, skb); - wake_up(&itp->read_wait); -} - -static void cw1200_itp_tx_start(struct cw1200_common *priv) -{ - struct wsm_tx *tx; - struct ieee80211_hdr_3addr *hdr; - struct cw1200_itp *itp = &priv->debug->itp; - struct wsm_mib_association_mode assoc_mode = { - .flags = WSM_ASSOCIATION_MODE_USE_PREAMBLE_TYPE, - .preamble = itp->preamble, - }; - int len; - u8 da_addr[6] = ITP_DEFAULT_DA_ADDR; - - /* Rates index 4 and 5 are not supported */ - if (itp->rate > 3) - itp->rate += 2; - - pr_debug("[ITP] TX start: band = %d, ch = %d, rate = %d, preamble = %d, number = %d, data_mode = %d, interval = %d, power = %d, data_len = %d\n", - itp->band, itp->ch, itp->rate, itp->preamble, - itp->number, itp->data_mode, itp->interval_us, - itp->power, itp->data_len); - - len = itp->hdr_len + itp->data_len; - - itp->data = kmalloc(len, GFP_KERNEL); - tx = (struct wsm_tx *)itp->data; - tx->hdr.len = itp->data_len + itp->hdr_len; - tx->hdr.id = __cpu_to_le16(0x0004 | 1 << 6); - tx->max_tx_rate = itp->rate; - tx->queue_id = 3; - tx->more = 0; - tx->flags = 0xc; - tx->packet_id = 0x55ff55; - tx->reserved = 0; - tx->expire_time = 1; - - if (itp->preamble == ITP_PREAMBLE_GREENFIELD) - tx->ht_tx_parameters = WSM_HT_TX_GREENFIELD; - else if (itp->preamble == ITP_PREAMBLE_MIXED) - tx->ht_tx_parameters = WSM_HT_TX_MIXED; - - hdr = (struct ieee80211_hdr_3addr *)&itp->data[sizeof(struct wsm_tx)]; - memset(hdr, 0, sizeof(*hdr)); - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); - memcpy(hdr->addr1, da_addr, ETH_ALEN); - memcpy(hdr->addr2, priv->vif->addr, ETH_ALEN); - memcpy(hdr->addr3, da_addr, ETH_ALEN); - - cw1200_itp_fill_pattern(&itp->data[itp->hdr_len], - itp->data_len, itp->data_mode); - - cw1200_update_listening(priv, false); - priv->channel = &priv->hw->wiphy->bands[itp->band]->channels[itp->ch]; - WARN_ON(wsm_set_output_power(priv, itp->power)); - if (itp->preamble == ITP_PREAMBLE_SHORT || - itp->preamble == ITP_PREAMBLE_LONG) - WARN_ON(wsm_set_association_mode(priv, - &assoc_mode)); - wsm_set_bssid_filtering(priv, false); - cw1200_update_listening(priv, true); - - spin_lock_bh(&itp->tx_lock); - atomic_set(&itp->test_mode, TEST_MODE_TX_TEST); - atomic_set(&itp->awaiting_confirm, 0); - atomic_set(&itp->stop_tx, 0); - atomic_set(&priv->bh_tx, 1); - ktime_get_ts(&itp->last_sent); - wake_up(&priv->bh_wq); - spin_unlock_bh(&itp->tx_lock); -} - -void __cw1200_itp_tx_stop(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - spin_lock_bh(&itp->tx_lock); - kfree(itp->data); - itp->data = NULL; - atomic_set(&itp->test_mode, TEST_MODE_NO_TEST); - spin_unlock_bh(&itp->tx_lock); -} - -static void cw1200_itp_tx_stop(struct cw1200_common *priv) -{ - struct cw1200_itp *itp = &priv->debug->itp; - pr_debug("[ITP] TX stop\n"); - atomic_set(&itp->stop_tx, 1); - flush_workqueue(priv->workqueue); - - /* time for FW to confirm all tx requests */ - msleep(500); - - __cw1200_itp_tx_stop(priv); -} - -static int cw1200_print_fw_version(struct cw1200_common *priv, - u8 *buf, size_t len) -{ - return snprintf(buf, len, "%s %d.%d", - cw1200_fw_types[priv->wsm_caps.fw_type], - priv->wsm_caps.fw_ver, - priv->wsm_caps.fw_build); -} - -static void cw1200_itp_get_version(struct cw1200_common *priv, - enum cw1200_itp_version_type type) -{ - struct cw1200_itp *itp = &priv->debug->itp; - struct sk_buff *skb; - char buf[ITP_BUF_SIZE]; - size_t size = 0; - int len; - pr_debug("[ITP] print %s version\n", - type == ITP_CHIP_ID ? "chip" : "firmware"); - - len = snprintf(buf, ITP_BUF_SIZE, "2,"); - if (len <= 0) { - cw1200_itp_err(priv, -EINVAL, 40); - return; - } - size += len; - - switch (type) { - case ITP_CHIP_ID: - len = cw1200_print_fw_version(priv, buf+size, - ITP_BUF_SIZE - size); - - if (len <= 0) { - cw1200_itp_err(priv, -EINVAL, 41); - return; - } - size += len; - break; - case ITP_FW_VER: - len = snprintf(buf+size, ITP_BUF_SIZE - size, - "%d.%d", priv->wsm_caps.hw_id, - priv->wsm_caps.hw_subid); - if (len <= 0) { - cw1200_itp_err(priv, -EINVAL, 42); - return; - } - size += len; - break; - default: - cw1200_itp_err(priv, -EINVAL, 43); - break; - } - - len = snprintf(buf+size, ITP_BUF_SIZE-size, "\n"); - if (len <= 0) { - cw1200_itp_err(priv, -EINVAL, 44); - return; - } - size += len; - - skb = dev_alloc_skb(size); - if (!skb) { - cw1200_itp_err(priv, -ENOMEM, 45); - return; - } - - skb_trim(skb, 0); - skb_put(skb, size); - - memcpy(skb->data, buf, size); - skb_queue_tail(&itp->log_queue, skb); - wake_up(&itp->read_wait); -} - -int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, - size_t *tx_len, int *burst) -{ - struct cw1200_itp *itp; - struct timespec now; - int time_left_us; - - if (!priv->debug) - return 0; - - itp = &priv->debug->itp; - - if (!itp) - return 0; - - spin_lock_bh(&itp->tx_lock); - if (atomic_read(&itp->test_mode) != TEST_MODE_TX_TEST) - goto out; - - if (atomic_read(&itp->stop_tx)) - goto out; - - if (itp->number == 0) { - atomic_set(&itp->stop_tx, 1); - queue_delayed_work(priv->workqueue, &itp->tx_finish, HZ/10); - goto out; - } - - if (!itp->data) - goto out; - - if (priv->hw_bufs_used >= 2) { - if (!atomic_read(&priv->bh_rx)) - atomic_set(&priv->bh_rx, 1); - atomic_set(&priv->bh_tx, 1); - goto out; - } - - ktime_get_ts(&now); - time_left_us = (itp->last_sent.tv_sec - now.tv_sec)*1000000 + - (itp->last_sent.tv_nsec - now.tv_nsec)/1000 + - itp->interval_us; - - if (time_left_us > ITP_TIME_THRES_US) { - queue_delayed_work(priv->workqueue, &itp->tx_work, - ITP_US_TO_MS(time_left_us)*HZ/1000); - goto out; - } - - if (time_left_us > 50) - udelay(time_left_us); - - if (itp->number > 0) - itp->number--; - - *data = itp->data; - *tx_len = itp->data_len + itp->hdr_len; - - if (itp->data_mode == ITP_DATA_RANDOM) - cw1200_itp_fill_pattern(&itp->data[itp->hdr_len], - itp->data_len, itp->data_mode); - *burst = 2; - atomic_set(&priv->bh_tx, 1); - ktime_get_ts(&itp->last_sent); - atomic_add(1, &itp->awaiting_confirm); - spin_unlock_bh(&itp->tx_lock); - return 1; - -out: - spin_unlock_bh(&itp->tx_lock); - return 0; -} - -bool cw1200_itp_rxed(struct cw1200_common *priv, struct sk_buff *skb) -{ - struct cw1200_itp *itp = &priv->debug->itp; - struct ieee80211_rx_status *rx = IEEE80211_SKB_RXCB(skb); - int signal; - - if (atomic_read(&itp->test_mode) != TEST_MODE_RX_TEST) - return cw1200_is_itp(priv); - if (rx->freq != priv->channel->center_freq) - return true; - - signal = rx->signal; - itp->rx_cnt++; - itp->rx_rssi += signal; - if (itp->rx_rssi_min > rx->signal) - itp->rx_rssi_min = rx->signal; - if (itp->rx_rssi_max < rx->signal) - itp->rx_rssi_max = rx->signal; - - return true; -} - -void cw1200_itp_wake_up_tx(struct cw1200_common *priv) -{ - wake_up(&priv->debug->itp.write_wait); -} - -bool cw1200_itp_tx_running(struct cw1200_common *priv) -{ - if (atomic_read(&priv->debug->itp.awaiting_confirm) || - atomic_read(&priv->debug->itp.test_mode) == - TEST_MODE_TX_TEST) { - atomic_sub(1, &priv->debug->itp.awaiting_confirm); - return true; - } - return false; -} - -static void cw1200_itp_handle(struct cw1200_common *priv, - struct sk_buff *skb) -{ - struct cw1200_itp *itp = &priv->debug->itp; - const struct wiphy *wiphy = priv->hw->wiphy; - int cmd; - int ret; - - pr_debug("[ITP] <<< %s", skb->data); - if (sscanf(skb->data, "%d", &cmd) != 1) { - cw1200_itp_err(priv, -EINVAL, 1); - return; - } - - switch (cmd) { - case 1: /* RX test */ - if (atomic_read(&itp->test_mode)) { - cw1200_itp_err(priv, -EBUSY, 0); - return; - } - ret = sscanf(skb->data, "%d,%d,%d", - &cmd, &itp->band, &itp->ch); - if (ret != 3) { - cw1200_itp_err(priv, -EINVAL, ret + 1); - return; - } - if (itp->band >= 2) { - cw1200_itp_err(priv, -EINVAL, 2); - } else if (!wiphy->bands[itp->band]) { - cw1200_itp_err(priv, -EINVAL, 2); - } else if (itp->ch >= wiphy->bands[itp->band]->n_channels) { - cw1200_itp_err(priv, -EINVAL, 3); - } else { - cw1200_itp_rx_stats(priv); - cw1200_itp_rx_start(priv); - } - break; - case 2: /* RX stat */ - cw1200_itp_rx_stats(priv); - break; - case 3: /* RX/TX stop */ - if (atomic_read(&itp->test_mode) == TEST_MODE_RX_TEST) { - cw1200_itp_rx_stats(priv); - cw1200_itp_rx_stop(priv); - } else if (atomic_read(&itp->test_mode) == TEST_MODE_TX_TEST) { - cw1200_itp_tx_stop(priv); - } else { - cw1200_itp_err(priv, -EBUSY, 0); - } - break; - case 4: /* TX start */ - if (atomic_read(&itp->test_mode) != TEST_MODE_NO_TEST) { - cw1200_itp_err(priv, -EBUSY, 0); - return; - } - ret = sscanf(skb->data, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - &cmd, &itp->band, &itp->ch, &itp->rate, - &itp->preamble, &itp->number, &itp->data_mode, - &itp->interval_us, &itp->power, &itp->data_len); - if (ret != 10) { - cw1200_itp_err(priv, -EINVAL, ret + 1); - return; - } - if (itp->band >= 2) { - cw1200_itp_err(priv, -EINVAL, 2); - } else if (!wiphy->bands[itp->band]) { - cw1200_itp_err(priv, -EINVAL, 2); - } else if (itp->ch >= wiphy->bands[itp->band]->n_channels) { - cw1200_itp_err(priv, -EINVAL, 3); - } else if (itp->rate >= 20) { - cw1200_itp_err(priv, -EINVAL, 4); - } else if (itp->preamble >= ITP_PREAMBLE_MAX) { - cw1200_itp_err(priv, -EINVAL, 5); - } else if (itp->data_mode >= ITP_DATA_MAX_MODE) { - cw1200_itp_err(priv, -EINVAL, 7); - } else if (itp->data_len < ITP_MIN_DATA_SIZE || - itp->data_len > (priv->wsm_caps.input_buffer_size - itp->hdr_len)) { - cw1200_itp_err(priv, -EINVAL, 8); - } else { - cw1200_itp_tx_start(priv); - } - break; - case 5: - cw1200_itp_get_version(priv, ITP_CHIP_ID); - break; - case 6: - cw1200_itp_get_version(priv, ITP_FW_VER); - break; - } -} - -static void cw1200_itp_err(struct cw1200_common *priv, - int err, int arg) -{ - struct cw1200_itp *itp = &priv->debug->itp; - struct sk_buff *skb; - static char buf[255]; - int len; - - len = snprintf(buf, sizeof(buf), "%d,%d\n", - err, arg); - if (len <= 0) - return; - - skb = dev_alloc_skb(len); - if (!skb) - return; - - skb_trim(skb, 0); - skb_put(skb, len); - - memcpy(skb->data, buf, len); - skb_queue_tail(&itp->log_queue, skb); - wake_up(&itp->read_wait); - - len = sprint_symbol(buf, - (unsigned long)__builtin_return_address(0)); - if (len <= 0) - return; - pr_debug("[ITP] error %d,%d from %s\n", - err, arg, buf); -} diff --git a/drivers/net/wireless/cw1200/itp.h b/drivers/net/wireless/cw1200/itp.h deleted file mode 100644 index 1e9dfb7fcadc..000000000000 --- a/drivers/net/wireless/cw1200/itp.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ITP code for ST-Ericsson CW1200 mac80211 driver - * - * Copyright (c) 2011, ST-Ericsson - * Author: Dmitry Tarnyagin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef CW1200_ITP_H_INCLUDED -#define CW1200_ITP_H_INCLUDED - -struct cw200_common; -struct wsm_tx_confirm; -struct dentry; - -#ifdef CONFIG_CW1200_ITP - -/*extern*/ struct ieee80211_channel; - -#define TEST_MODE_NO_TEST (0) -#define TEST_MODE_RX_TEST (1) -#define TEST_MODE_TX_TEST (2) -#define ITP_DEFAULT_DA_ADDR {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} -#define ITP_MIN_DATA_SIZE 6 -#define ITP_MAX_DATA_SIZE 1600 -#define ITP_TIME_THRES_US 10000 -#define ITP_US_TO_MS(x) ((x)/1000) -#define ITP_MS_TO_US(x) ((x)*1000) -#define ITP_BUF_SIZE 255 - - -enum cw1200_itp_data_modes { - ITP_DATA_ZEROS, - ITP_DATA_ONES, - ITP_DATA_ZERONES, - ITP_DATA_RANDOM, - ITP_DATA_MAX_MODE, -}; - -enum cw1200_itp_version_type { - ITP_CHIP_ID, - ITP_FW_VER, -}; - -enum cw1200_itp_preamble_type { - ITP_PREAMBLE_LONG, - ITP_PREAMBLE_SHORT, - ITP_PREAMBLE_OFDM, - ITP_PREAMBLE_MIXED, - ITP_PREAMBLE_GREENFIELD, - ITP_PREAMBLE_MAX, -}; - - -struct cw1200_itp { - struct cw1200_common *priv; - atomic_t open_count; - atomic_t awaiting_confirm; - struct sk_buff_head log_queue; - wait_queue_head_t read_wait; - wait_queue_head_t write_wait; - wait_queue_head_t close_wait; - struct ieee80211_channel *saved_channel; - atomic_t stop_tx; - struct delayed_work tx_work; - struct delayed_work tx_finish; - spinlock_t tx_lock; - struct timespec last_sent; - atomic_t test_mode; - int rx_cnt; - long rx_rssi; - int rx_rssi_max; - int rx_rssi_min; - unsigned band; - unsigned ch; - unsigned rate; - unsigned preamble; - unsigned int number; - unsigned data_mode; - int interval_us; - int power; - u8 *data; - int hdr_len; - int data_len; -}; - -int cw1200_itp_init(struct cw1200_common *priv); -void cw1200_itp_release(struct cw1200_common *priv); - -bool cw1200_is_itp(struct cw1200_common *priv); -bool cw1200_itp_rxed(struct cw1200_common *priv, struct sk_buff *skb); -void cw1200_itp_wake_up_tx(struct cw1200_common *priv); -int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, - size_t *tx_len, int *burst); -bool cw1200_itp_tx_running(struct cw1200_common *priv); - -#else /* CONFIG_CW1200_ITP */ - -static inline int cw1200_itp_init(struct cw1200_common *priv) -{ - return 0; -} - -static inline void cw1200_itp_release(struct cw1200_common *priv) -{ -} - -static inline bool cw1200_is_itp(struct cw1200_common *priv) -{ - return false; -} - -static inline bool cw1200_itp_rxed(struct cw1200_common *priv, - struct sk_buff *skb) -{ - return false; -} - - -static inline void cw1200_itp_consume_txed(struct cw1200_common *priv) -{ -} - -static inline void cw1200_itp_wake_up_tx(struct cw1200_common *priv) -{ -} - -static inline int cw1200_itp_get_tx(struct cw1200_common *priv, u8 **data, - size_t *tx_len, int *burst) -{ - return 0; -} - -static inline bool cw1200_itp_tx_running(struct cw1200_common *priv) -{ - return false; -} - -#endif /* CONFIG_CW1200_ITP */ - -#endif /* CW1200_ITP_H_INCLUDED */ diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c index a2547473ec5c..451d74625f90 100644 --- a/drivers/net/wireless/cw1200/txrx.c +++ b/drivers/net/wireless/cw1200/txrx.c @@ -861,9 +861,6 @@ void cw1200_tx_confirm_cb(struct cw1200_common *priv, pr_debug("[TX] TX confirm: %d, %d.\n", arg->status, arg->ack_failures); - if (cw1200_itp_tx_running(priv)) - return; - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) { /* STA is stopped. */ return; @@ -1001,8 +998,7 @@ void cw1200_skb_dtor(struct cw1200_common *priv, txpriv->raw_link_id, txpriv->tid); tx_policy_put(priv, txpriv->rate_id); } - if (!cw1200_is_itp(priv)) - ieee80211_tx_status(priv->hw, skb); + ieee80211_tx_status(priv->hw, skb); } void cw1200_rx_cb(struct cw1200_common *priv, @@ -1205,9 +1201,7 @@ void cw1200_rx_cb(struct cw1200_common *priv, grace_period = 1 * HZ; cw1200_pm_stay_awake(&priv->pm_state, grace_period); - if (cw1200_itp_rxed(priv, skb)) { - consume_skb(skb); - } else if (early_data) { + if (early_data) { spin_lock_bh(&priv->ps_state_lock); /* Double-check status with lock held */ if (entry->status == CW1200_LINK_SOFT) diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index 3ab25f661793..e99f34e7604d 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -21,7 +21,6 @@ #include "bh.h" #include "sta.h" #include "debug.h" -#include "itp.h" #define WSM_CMD_TIMEOUT (2 * HZ) /* With respect to interrupt loss */ #define WSM_CMD_START_TIMEOUT (7 * HZ) @@ -1733,12 +1732,6 @@ int wsm_get_tx(struct cw1200_common *priv, u8 **data, /* More is used only for broadcasts. */ bool more = false; -#ifdef CONFIG_CW1200_ITP - count = cw1200_itp_get_tx(priv, data, tx_len, burst); - if (count) - return count; -#endif - if (priv->wsm_cmd.ptr) { /* CMD request */ ++count; spin_lock(&priv->wsm_cmd.lock); -- GitLab From 19db577868e94c80dc9a569d937109f95c34d0f4 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 11 Jun 2013 09:49:39 -0400 Subject: [PATCH 0854/2900] cw1200: Eliminate the ETF debug/engineering code. This is only really useful for people who are bringing up new hardware designs and have access to the proprietary vendor tools that interface with this mode. It'll live out of tree until it's rewritten to use a less kludgy interface. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/Kconfig | 10 -- drivers/net/wireless/cw1200/cw1200.h | 9 - drivers/net/wireless/cw1200/debug.c | 236 --------------------------- drivers/net/wireless/cw1200/fwio.c | 5 - drivers/net/wireless/cw1200/main.c | 30 +--- drivers/net/wireless/cw1200/wsm.c | 56 +------ drivers/net/wireless/cw1200/wsm.h | 5 - 7 files changed, 2 insertions(+), 349 deletions(-) diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig index fc1b472460c8..0880742eab17 100644 --- a/drivers/net/wireless/cw1200/Kconfig +++ b/drivers/net/wireless/cw1200/Kconfig @@ -27,14 +27,4 @@ config CW1200_WLAN_SPI need to add appropriate platform data glue in your board setup file. -menu "Driver debug features" - depends on CW1200 && DEBUG_FS - -config CW1200_ETF - bool "Enable CW1200 Engineering Test Framework hooks" - help - If you don't know what this is, just say N. - -endmenu - endif diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h index 95320f2b25eb..91ff7f19c4f0 100644 --- a/drivers/net/wireless/cw1200/cw1200.h +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -35,11 +35,6 @@ struct task_struct; struct cw1200_debug_priv; struct firmware; -#ifdef CONFIG_CW1200_ETF -extern int etf_mode; -extern char *etf_firmware; -#endif - #define CW1200_MAX_CTRL_FRAME_LEN (0x1000) #define CW1200_MAX_STA_IN_AP_MODE (5) @@ -287,10 +282,6 @@ struct cw1200_common { struct work_struct linkid_reset_work; u8 action_frame_sa[ETH_ALEN]; u8 action_linkid; - -#ifdef CONFIG_CW1200_ETF - struct sk_buff_head etf_q; -#endif }; struct cw1200_sta_priv { diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index ac9c219c6330..e323b4d54338 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -357,144 +357,6 @@ static const struct file_operations fops_counters = { .owner = THIS_MODULE, }; -#ifdef CONFIG_CW1200_ETF -static int cw1200_etf_out_show(struct seq_file *seq, void *v) -{ - struct cw1200_common *priv = seq->private; - struct sk_buff *skb; - u32 len = 0; - - skb = skb_dequeue(&priv->etf_q); - - if (skb) - len = skb->len; - - seq_write(seq, &len, sizeof(len)); - - if (skb) { - seq_write(seq, skb->data, len); - kfree_skb(skb); - } - - return 0; -} - -static int cw1200_etf_out_open(struct inode *inode, struct file *file) -{ - return single_open(file, &cw1200_etf_out_show, - inode->i_private); -} - -static const struct file_operations fops_etf_out = { - .open = cw1200_etf_out_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -struct etf_req_msg; -static int etf_request(struct cw1200_common *priv, - struct etf_req_msg *msg, u32 len); - -#define MAX_RX_SIZE 2600 - -struct etf_in_state { - struct cw1200_common *priv; - u16 total_len; - u16 written; - u8 buf[MAX_RX_SIZE]; -}; - -static int cw1200_etf_in_open(struct inode *inode, struct file *file) -{ - struct etf_in_state *etf = kmalloc(sizeof(struct etf_in_state), - GFP_KERNEL); - - if (!etf) - return -ENOMEM; - - etf->written = 0; - etf->total_len = 0; - etf->priv = inode->i_private; - - file->private_data = etf; - - return 0; -} - -static int cw1200_etf_in_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - return 0; -} - -static ssize_t cw1200_etf_in_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct etf_in_state *etf = file->private_data; - - ssize_t written = 0; - - if (!etf->total_len) { - if (count < sizeof(etf->total_len)) { - pr_err("count < sizeof(total_len)\n"); - return -EINVAL; - } - - if (copy_from_user(&etf->total_len, user_buf, - sizeof(etf->total_len))) { - pr_err("copy_from_user (len) failed\n"); - return -EFAULT; - } - - if (etf->total_len > MAX_RX_SIZE) { - pr_err("requested length > MAX_RX_SIZE\n"); - return -EINVAL; - } - - written += sizeof(etf->total_len); - count -= sizeof(etf->total_len); - } - - if (!count) - goto done; - - if (count > (etf->total_len - written)) { - pr_err("Tried to write > MAX_RX_SIZE\n"); - return -EINVAL; - } - - if (copy_from_user(etf->buf + etf->written, user_buf + written, - count)) { - pr_err("copy_from_user (payload %zu) failed\n", count); - return -EFAULT; - } - - written += count; - etf->written += count; - - if (etf->written >= etf->total_len) { - if (etf_request(etf->priv, (struct etf_req_msg *)etf->buf, - etf->total_len)) { - pr_err("etf_request failed\n"); - return -EIO; - } - } - -done: - return written; -} - -static const struct file_operations fops_etf_in = { - .open = cw1200_etf_in_open, - .release = cw1200_etf_in_release, - .write = cw1200_etf_in_write, - .llseek = default_llseek, - .owner = THIS_MODULE, -}; -#endif /* CONFIG_CW1200_ETF */ - static ssize_t cw1200_wsm_dumps(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -542,19 +404,6 @@ int cw1200_debug_init(struct cw1200_common *priv) priv, &fops_counters)) goto err; -#ifdef CONFIG_CW1200_ETF - if (etf_mode) { - skb_queue_head_init(&priv->etf_q); - - if (!debugfs_create_file("etf_out", S_IRUSR, d->debugfs_phy, - priv, &fops_etf_out)) - goto err; - if (!debugfs_create_file("etf_in", S_IWUSR, d->debugfs_phy, - priv, &fops_etf_in)) - goto err; - } -#endif /* CONFIG_CW1200_ETF */ - if (!debugfs_create_file("wsm_dumps", S_IWUSR, d->debugfs_phy, priv, &fops_wsm_dumps)) goto err; @@ -577,88 +426,3 @@ void cw1200_debug_release(struct cw1200_common *priv) kfree(d); } } - -#ifdef CONFIG_CW1200_ETF -struct cw1200_sdd { - u8 id; - u8 len; - u8 data[]; -}; - -struct etf_req_msg { - u32 id; - u32 len; - u8 data[]; -}; - -static int parse_sdd_file(struct cw1200_common *priv, u8 *data, u32 length) -{ - struct cw1200_sdd *ie; - - while (length > 0) { - ie = (struct cw1200_sdd *)data; - if (ie->id == SDD_REFERENCE_FREQUENCY_ELT_ID) { - priv->hw_refclk = cpu_to_le16(*((u16 *)ie->data)); - pr_info("Using Reference clock frequency %d KHz\n", - priv->hw_refclk); - break; - } - - length -= ie->len + sizeof(*ie); - data += ie->len + sizeof(*ie); - } - return 0; -} - -char *etf_firmware; - -#define ST90TDS_START_ADAPTER 0x09 /* Loads firmware too */ -#define ST90TDS_STOP_ADAPTER 0x0A -#define ST90TDS_CONFIG_ADAPTER 0x0E /* Send configuration params */ -#define ST90TDS_SBUS_READ 0x13 -#define ST90TDS_SBUS_WRITE 0x14 -#define ST90TDS_GET_DEVICE_OPTION 0x19 -#define ST90TDS_SET_DEVICE_OPTION 0x1A -#define ST90TDS_SEND_SDD 0x1D /* SDD File used to find DPLL */ - -#include "fwio.h" - -static int etf_request(struct cw1200_common *priv, - struct etf_req_msg *msg, - u32 len) -{ - int rval = -1; - switch (msg->id) { - case ST90TDS_START_ADAPTER: - etf_firmware = "cw1200_etf.bin"; - pr_info("ETF_START (len %d, '%s')\n", len, etf_firmware); - rval = cw1200_load_firmware(priv); - break; - case ST90TDS_STOP_ADAPTER: - pr_info("ETF_STOP (unhandled)\n"); - break; - case ST90TDS_SEND_SDD: - pr_info("ETF_SDD\n"); - rval = parse_sdd_file(priv, msg->data, msg->len); - break; - case ST90TDS_CONFIG_ADAPTER: - pr_info("ETF_CONFIG_ADAP (unhandled)\n"); - break; - case ST90TDS_SBUS_READ: - pr_info("ETF_SBUS_READ (unhandled)\n"); - break; - case ST90TDS_SBUS_WRITE: - pr_info("ETF_SBUS_WRITE (unhandled)\n"); - break; - case ST90TDS_SET_DEVICE_OPTION: - pr_info("ETF_SET_DEV_OPT (unhandled)\n"); - break; - default: - pr_info("ETF_PASSTHRU (0x%08x)\n", msg->id); - rval = wsm_raw_cmd(priv, (u8 *)msg, len); - break; - } - - return rval; -} -#endif /* CONFIG_CW1200_ETF */ diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index 427c9f24b94e..acdff0f7f952 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c @@ -139,11 +139,6 @@ static int cw1200_load_firmware_cw1200(struct cw1200_common *priv) val32 &= ~ST90TDS_CONFIG_CPU_CLK_DIS_BIT; REG_WRITE(ST90TDS_CONFIG_REG_ID, val32); -#ifdef CONFIG_CW1200_ETF - if (etf_mode) - fw_path = etf_firmware; -#endif - /* Load a firmware file */ ret = request_firmware(&firmware, fw_path, priv->pdev); if (ret) { diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index 2ea1bada7207..9f9adb4fbfb8 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c @@ -61,12 +61,6 @@ int cw1200_power_mode = wsm_power_mode_quiescent; module_param(cw1200_power_mode, int, 0644); MODULE_PARM_DESC(cw1200_power_mode, "WSM power mode. 0 == active, 1 == doze, 2 == quiescent (default)"); -#ifdef CONFIG_CW1200_ETF -int etf_mode; -module_param(etf_mode, int, 0644); -MODULE_PARM_DESC(etf_mode, "Enable EngineeringTestingFramework operation"); -#endif - #define RATETAB_ENT(_rate, _rateid, _flags) \ { \ .bitrate = (_rate), \ @@ -418,11 +412,6 @@ static int cw1200_register_common(struct ieee80211_hw *dev) struct cw1200_common *priv = dev->priv; int err; -#ifdef CONFIG_CW1200_ETF - if (etf_mode) - goto done; -#endif - #ifdef CONFIG_PM err = cw1200_pm_init(&priv->pm_state, priv); if (err) { @@ -442,9 +431,6 @@ static int cw1200_register_common(struct ieee80211_hw *dev) return err; } -#ifdef CONFIG_CW1200_ETF -done: -#endif cw1200_debug_init(priv); pr_info("Registered as '%s'\n", wiphy_name(dev->wiphy)); @@ -461,13 +447,7 @@ static void cw1200_unregister_common(struct ieee80211_hw *dev) struct cw1200_common *priv = dev->priv; int i; -#ifdef CONFIG_CW1200_ETF - if (!etf_mode) { -#endif - ieee80211_unregister_hw(dev); -#ifdef CONFIG_CW1200_ETF - } -#endif + ieee80211_unregister_hw(dev); del_timer_sync(&priv->mcast_timeout); cw1200_unregister_bh(priv); @@ -568,11 +548,6 @@ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, if (err) goto err1; -#ifdef CONFIG_CW1200_ETF - if (etf_mode) - goto skip_fw; -#endif - err = cw1200_load_firmware(priv); if (err) goto err2; @@ -594,9 +569,6 @@ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, /* Enable multi-TX confirmation */ wsm_use_multi_tx_conf(priv, true); -#ifdef CONFIG_CW1200_ETF -skip_fw: -#endif err = cw1200_register_common(dev); if (err) goto err2; diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index e99f34e7604d..d185f29efb7e 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -1111,10 +1111,7 @@ static int wsm_cmd_send(struct cw1200_common *priv, * pad the message by a few bytes to ensure * that it's completely received. */ -#ifdef CONFIG_CW1200_ETF - if (!etf_mode) -#endif - buf_len += 4; + buf_len += 4; /* Fill HI message header */ /* BH will add sequence number */ @@ -1165,29 +1162,6 @@ static int wsm_cmd_send(struct cw1200_common *priv, return ret; } -#ifdef CONFIG_CW1200_ETF -int wsm_raw_cmd(struct cw1200_common *priv, u8 *data, size_t len) -{ - struct wsm_buf *buf = &priv->wsm_cmd_buf; - int ret; - - u16 *cmd = (u16 *)(data + 2); - - wsm_cmd_lock(priv); - - WSM_PUT(buf, data + 4, len - 4); /* Skip over header (u16+u16) */ - - ret = wsm_cmd_send(priv, buf, NULL, __le16_to_cpu(*cmd), WSM_CMD_TIMEOUT); - - wsm_cmd_unlock(priv); - return ret; - -nomem: - wsm_cmd_unlock(priv); - return -ENOMEM; -} -#endif /* CONFIG_CW1200_ETF */ - /* ******************************************************************** */ /* WSM TX port control */ @@ -1343,34 +1317,6 @@ int wsm_handle_rx(struct cw1200_common *priv, u16 id, pr_debug("[WSM] <<< 0x%.4X (%td)\n", id, wsm_buf.end - wsm_buf.begin); -#ifdef CONFIG_CW1200_ETF - if (etf_mode) { - struct sk_buff *skb = alloc_skb(wsm_buf.end - wsm_buf.begin, GFP_KERNEL); - - /* Strip out Sequence num before passing up */ - wsm->id = __le16_to_cpu(wsm->id); - wsm->id &= 0x0FFF; - wsm->id = __cpu_to_le16(wsm->id); - - memcpy(skb_put(skb, wsm_buf.end - wsm_buf.begin), - wsm_buf.begin, - wsm_buf.end - wsm_buf.begin); - skb_queue_tail(&priv->etf_q, skb); - - /* Special case for startup */ - if (id == WSM_STARTUP_IND_ID) { - wsm_startup_indication(priv, &wsm_buf); - } else if (id & 0x0400) { - spin_lock(&priv->wsm_cmd.lock); - priv->wsm_cmd.done = 1; - spin_unlock(&priv->wsm_cmd.lock); - wake_up(&priv->wsm_cmd_wq); - } - - goto out; - } -#endif - if (id == WSM_TX_CONFIRM_IND_ID) { ret = wsm_tx_confirm(priv, &wsm_buf, link_id); } else if (id == WSM_MULTI_TX_CONFIRM_ID) { diff --git a/drivers/net/wireless/cw1200/wsm.h b/drivers/net/wireless/cw1200/wsm.h index 8d902d6a7dc4..4689dffa3d89 100644 --- a/drivers/net/wireless/cw1200/wsm.h +++ b/drivers/net/wireless/cw1200/wsm.h @@ -1871,9 +1871,4 @@ static inline u8 wsm_queue_id_to_wsm(u8 queue_id) return queue_mapping[queue_id]; } - -#ifdef CONFIG_CW1200_ETF -int wsm_raw_cmd(struct cw1200_common *priv, u8 *data, size_t len); -#endif - #endif /* CW1200_HWIO_H_INCLUDED */ -- GitLab From 8b3e7be437a6b62118d0485ad971e724afe23fdf Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 11 Jun 2013 09:49:40 -0400 Subject: [PATCH 0855/2900] cw1200: Fix an assorted pile of checkpatch warnings. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/bh.c | 9 ++-- drivers/net/wireless/cw1200/cw1200.h | 3 +- drivers/net/wireless/cw1200/cw1200_sdio.c | 3 +- drivers/net/wireless/cw1200/cw1200_spi.c | 4 +- drivers/net/wireless/cw1200/hwio.h | 5 +-- drivers/net/wireless/cw1200/sta.c | 30 ++++++------- drivers/net/wireless/cw1200/txrx.c | 43 ++++++++++-------- drivers/net/wireless/cw1200/wsm.c | 3 +- drivers/net/wireless/cw1200/wsm.h | 55 +++++++++++------------ 9 files changed, 80 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/cw1200/bh.c b/drivers/net/wireless/cw1200/bh.c index 324b57001da0..c1ec2a4dd8c0 100644 --- a/drivers/net/wireless/cw1200/bh.c +++ b/drivers/net/wireless/cw1200/bh.c @@ -31,7 +31,8 @@ static int cw1200_bh(void *arg); #define DOWNLOAD_BLOCK_SIZE_WR (0x1000 - 4) /* an SPI message cannot be bigger than (2"12-1)*2 bytes - * "*2" to cvt to bytes */ + * "*2" to cvt to bytes + */ #define MAX_SZ_RD_WR_BUFFERS (DOWNLOAD_BLOCK_SIZE_WR*2) #define PIGGYBACK_CTRL_REG (2) #define EFFECTIVE_BUF_SIZE (MAX_SZ_RD_WR_BUFFERS - PIGGYBACK_CTRL_REG) @@ -217,7 +218,8 @@ static int cw1200_device_wakeup(struct cw1200_common *priv) return ret; /* If the device returns WLAN_RDY as 1, the device is active and will - * remain active. */ + * remain active. + */ if (ctrl_reg & ST90TDS_CONT_RDY_BIT) { pr_debug("[BH] Device awake.\n"); return 1; @@ -262,7 +264,8 @@ static int cw1200_bh_rx_helper(struct cw1200_common *priv, } /* Add SIZE of PIGGYBACK reg (CONTROL Reg) - * to the NEXT Message length + 2 Bytes for SKB */ + * to the NEXT Message length + 2 Bytes for SKB + */ read_len = read_len + 2; alloc_len = priv->hwbus_ops->align_size( diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h index 91ff7f19c4f0..243e96353d13 100644 --- a/drivers/net/wireless/cw1200/cw1200.h +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -207,7 +207,8 @@ struct cw1200_common { /* Scan status */ struct cw1200_scan scan; /* Keep cw1200 awake (WUP = 1) 1 second after each scan to avoid - * FW issue with sleeping/waking up. */ + * FW issue with sleeping/waking up. + */ atomic_t recent_scan; struct delayed_work clear_recent_scan_work; diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c index bb1f405315e4..ebdcdf44f155 100644 --- a/drivers/net/wireless/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/cw1200/cw1200_sdio.c @@ -323,7 +323,8 @@ static int cw1200_sdio_probe(struct sdio_func *func, } /* Disconnect Function to be called by SDIO stack when - * device is disconnected */ + * device is disconnected + */ static void cw1200_sdio_disconnect(struct sdio_func *func) { struct hwbus_priv *self = sdio_get_drvdata(func); diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index e58f0a5bafa9..953bd1904d3d 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -47,15 +47,13 @@ struct hwbus_priv { #define SET_WRITE 0x7FFF /* usage: and operation */ #define SET_READ 0x8000 /* usage: or operation */ -/* - Notes on byte ordering: +/* Notes on byte ordering: LE: B0 B1 B2 B3 BE: B3 B2 B1 B0 Hardware expects 32-bit data to be written as 16-bit BE words: B1 B0 B3 B2 - */ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, diff --git a/drivers/net/wireless/cw1200/hwio.h b/drivers/net/wireless/cw1200/hwio.h index 7ee73fe32ccf..563329cfead6 100644 --- a/drivers/net/wireless/cw1200/hwio.h +++ b/drivers/net/wireless/cw1200/hwio.h @@ -97,9 +97,8 @@ struct download_cntl_t { #define CW1200_APB(addr) (PAC_SHARED_MEMORY_SILICON + (addr)) -/* *************************************************************** -*Device register definitions -*************************************************************** */ +/* Device register definitions */ + /* WBF - SPI Register Addresses */ #define ST90TDS_ADDR_ID_BASE (0x0000) /* 16/32 bits */ diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index 679c55f15c67..4cd0352b508d 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -483,15 +483,14 @@ void cw1200_update_filtering(struct cw1200_common *priv) bf_tbl.num = __cpu_to_le32(3); } - /* - * When acting as p2p client being connected to p2p GO, in order to - * receive frames from a different p2p device, turn off bssid filter. - * - * WARNING: FW dependency! - * This can only be used with FW WSM371 and its successors. - * In that FW version even with bssid filter turned off, - * device will block most of the unwanted frames. - */ + /* When acting as p2p client being connected to p2p GO, in order to + * receive frames from a different p2p device, turn off bssid filter. + * + * WARNING: FW dependency! + * This can only be used with FW WSM371 and its successors. + * In that FW version even with bssid filter turned off, + * device will block most of the unwanted frames. + */ if (is_p2p) bssid_filtering = false; @@ -1015,17 +1014,17 @@ void cw1200_event_handler(struct work_struct *work) /* RSSI: signed Q8.0, RCPI: unsigned Q7.1 * RSSI = RCPI / 2 - 110 */ - int rcpiRssi = (int)(event->evt.data & 0xFF); + int rcpi_rssi = (int)(event->evt.data & 0xFF); int cqm_evt; if (priv->cqm_use_rssi) - rcpiRssi = (s8)rcpiRssi; + rcpi_rssi = (s8)rcpi_rssi; else - rcpiRssi = rcpiRssi / 2 - 110; + rcpi_rssi = rcpi_rssi / 2 - 110; - cqm_evt = (rcpiRssi <= priv->cqm_rssi_thold) ? + cqm_evt = (rcpi_rssi <= priv->cqm_rssi_thold) ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW : NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; - pr_debug("[CQM] RSSI event: %d.\n", rcpiRssi); + pr_debug("[CQM] RSSI event: %d.\n", rcpi_rssi); ieee80211_cqm_rssi_notify(priv->vif, cqm_evt, GFP_KERNEL); break; @@ -1068,8 +1067,7 @@ void cw1200_bss_params_work(struct work_struct *work) /* ******************************************************************** */ /* Internal API */ -/* - * This function is called to Parse the SDD file +/* This function is called to Parse the SDD file * to extract listen_interval and PTA related information * sdd is a TLV: u8 id, u8 len, u8 data[] */ diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c index 451d74625f90..44ca10cb0d39 100644 --- a/drivers/net/wireless/cw1200/txrx.c +++ b/drivers/net/wireless/cw1200/txrx.c @@ -75,9 +75,6 @@ static void tx_policy_build(const struct cw1200_common *priv, BUG_ON(rates[0].idx < 0); memset(policy, 0, sizeof(*policy)); - /* minstrel is buggy a little bit, so distille - * incoming rates first. */ - /* Sort rates in descending order. */ for (i = 1; i < count; ++i) { if (rates[i].idx < 0) { @@ -108,7 +105,8 @@ static void tx_policy_build(const struct cw1200_common *priv, count = i + 1; /* Re-fill policy trying to keep every requested rate and with - * respect to the global max tx retransmission count. */ + * respect to the global max tx retransmission count. + */ if (limit < count) limit = count; if (total > limit) { @@ -129,7 +127,6 @@ static void tx_policy_build(const struct cw1200_common *priv, if (count == 2 && !(rates[0].flags & IEEE80211_TX_RC_MCS) && rates[0].idx > 4 && rates[0].count > 2 && rates[1].idx < 2) { - /* ">> 1" is an equivalent of "/ 2", but faster */ int mid_rate = (rates[0].idx + 4) >> 1; /* Decrease number of retries for the initial rate */ @@ -151,7 +148,8 @@ static void tx_policy_build(const struct cw1200_common *priv, /* Fallback to 1 Mbps is a really bad thing, * so let's try to increase probability of * successful transmission on the lowest g rate - * even more */ + * even more + */ if (rates[0].count >= 3) { --rates[0].count; ++rates[2].count; @@ -220,7 +218,8 @@ static int tx_policy_find(struct tx_policy_cache *cache, { /* O(n) complexity. Not so good, but there's only 8 entries in * the cache. - * Also lru helps to reduce search time. */ + * Also lru helps to reduce search time. + */ struct tx_policy_cache_entry *it; /* First search for policy in "used" list */ list_for_each_entry(it, &cache->used, link) { @@ -264,7 +263,8 @@ void tx_policy_clean(struct cw1200_common *priv) for (idx = 0; idx < TX_POLICY_CACHE_SIZE; idx++) { entry = &cache->cache[idx]; /* Policy usage count should be 0 at this time as all queues - should be empty */ + should be empty + */ if (WARN_ON(entry->policy.usage_count)) { entry->policy.usage_count = 0; list_move(&entry->link, &cache->free); @@ -319,7 +319,8 @@ static int tx_policy_get(struct cw1200_common *priv, struct tx_policy_cache_entry *entry; *renew = true; /* If policy is not found create a new one - * using the oldest entry in "free" list */ + * using the oldest entry in "free" list + */ entry = list_entry(cache->free.prev, struct tx_policy_cache_entry, link); entry->policy = wanted; @@ -612,7 +613,8 @@ cw1200_tx_h_bt(struct cw1200_common *priv, priv->listen_interval, mgt_frame->u.assoc_req.listen_interval); /* Replace listen interval derieved from - * the one read from SDD */ + * the one read from SDD + */ mgt_frame->u.assoc_req.listen_interval = priv->listen_interval; } @@ -667,7 +669,8 @@ cw1200_tx_h_rate_policy(struct cw1200_common *priv, pr_debug("[TX] TX policy renew.\n"); /* It's not so optimal to stop TX queues every now and then. * Better to reimplement task scheduling with - * a counter. TODO. */ + * a counter. TODO. + */ wsm_lock_tx_async(priv); cw1200_tx_queues_lock(priv); if (queue_work(priv->workqueue, @@ -832,8 +835,7 @@ static int cw1200_handle_pspoll(struct cw1200_common *priv, priv->pspoll_mask |= pspoll_mask; drop = 0; - /* Do not report pspols if data for given link id is - * queued already. */ + /* Do not report pspols if data for given link id is queued already. */ for (i = 0; i < 4; ++i) { if (cw1200_queue_get_num_queued(&priv->tx_queue[i], pspoll_mask)) { @@ -924,7 +926,8 @@ void cw1200_tx_confirm_cb(struct cw1200_common *priv, cw1200_debug_txed(priv); if (arg->flags & WSM_TX_STATUS_AGGREGATION) { /* Do not report aggregation to mac80211: - * it confuses minstrel a lot. */ + * it confuses minstrel a lot. + */ /* tx->flags |= IEEE80211_TX_STAT_AMPDU; */ cw1200_debug_txed_agg(priv); } @@ -1044,7 +1047,8 @@ void cw1200_rx_cb(struct cw1200_common *priv, ieee80211_is_action(frame->frame_control) && (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)) { /* Link ID already exists for the ACTION frame. - * Reset and Remap */ + * Reset and Remap + */ WARN_ON(work_pending(&priv->linkid_reset_work)); memcpy(&priv->action_frame_sa[0], ieee80211_get_SA(frame), ETH_ALEN); @@ -1074,7 +1078,6 @@ void cw1200_rx_cb(struct cw1200_common *priv, if (cw1200_handle_pspoll(priv, skb)) goto drop; - hdr->mactime = 0; /* Not supported by WSM */ hdr->band = ((arg->channel_number & 0xff00) || (arg->channel_number > 14)) ? IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; @@ -1102,7 +1105,8 @@ void cw1200_rx_cb(struct cw1200_common *priv, hdr->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED; /* Oops... There is no fast way to ask mac80211 about - * IV/ICV lengths. Even defineas are not exposed.*/ + * IV/ICV lengths. Even defineas are not exposed. + */ switch (WSM_RX_STATUS_ENCRYPTION(arg->flags)) { case WSM_RX_STATUS_WEP: iv_len = 4 /* WEP_IV_LEN */; @@ -1149,6 +1153,8 @@ void cw1200_rx_cb(struct cw1200_common *priv, hdr->mactime = le64_to_cpu(hdr->mactime); if (skb->len >= 8) skb_trim(skb, skb->len - 8); + } else { + hdr->mactime = 0; } cw1200_debug_rxed(priv); @@ -1192,7 +1198,8 @@ void cw1200_rx_cb(struct cw1200_common *priv, /* Stay awake after frame is received to give * userspace chance to react and acquire appropriate - * wakelock. */ + * wakelock. + */ if (ieee80211_is_auth(frame->frame_control)) grace_period = 5 * HZ; else if (ieee80211_is_deauth(frame->frame_control)) diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index d185f29efb7e..d95094fdcc50 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -1106,8 +1106,7 @@ static int wsm_cmd_send(struct cw1200_common *priv, else pr_debug("[WSM] >>> 0x%.4X (%zu)\n", cmd, buf_len); - /* - * Due to buggy SPI on CW1200, we need to + /* Due to buggy SPI on CW1200, we need to * pad the message by a few bytes to ensure * that it's completely received. */ diff --git a/drivers/net/wireless/cw1200/wsm.h b/drivers/net/wireless/cw1200/wsm.h index 4689dffa3d89..2816171f7a1d 100644 --- a/drivers/net/wireless/cw1200/wsm.h +++ b/drivers/net/wireless/cw1200/wsm.h @@ -314,13 +314,16 @@ struct cw1200_common; #define WSM_JOIN_FLAGS_P2P_GO BIT(1) /* Force to join BSS with the BSSID and the * SSID specified without waiting for beacons. The - * ProbeForJoin parameter is ignored. */ + * ProbeForJoin parameter is ignored. + */ #define WSM_JOIN_FLAGS_FORCE BIT(2) /* Give probe request/response higher - * priority over the BT traffic */ + * priority over the BT traffic + */ #define WSM_JOIN_FLAGS_PRIO BIT(3) /* Issue immediate join confirmation and use - * join complete to notify about completion */ + * join complete to notify about completion + */ #define WSM_JOIN_FLAGS_FORCE_WITH_COMPLETE_IND BIT(5) /* Key types */ @@ -1015,22 +1018,19 @@ struct wsm_add_key { u16 reserved; union { struct { - u8 peer[6]; /* MAC address of the - * peer station */ + u8 peer[6]; /* MAC address of the peer station */ u8 reserved; u8 keylen; /* Key length in bytes */ u8 keydata[16]; /* Key data */ } __packed wep_pairwise; struct { - u8 keyid; /* Unique per key identifier - * (0..3) */ + u8 keyid; /* Unique per key identifier (0..3) */ u8 keylen; /* Key length in bytes */ u16 reserved; u8 keydata[16]; /* Key data */ } __packed wep_group; struct { - u8 peer[6]; /* MAC address of the - * peer station */ + u8 peer[6]; /* MAC address of the peer station */ u16 reserved; u8 keydata[16]; /* TKIP key data */ u8 rx_mic_key[8]; /* Rx MIC key */ @@ -1044,8 +1044,7 @@ struct wsm_add_key { u8 rx_seqnum[8]; /* Receive Sequence Counter */ } __packed tkip_group; struct { - u8 peer[6]; /* MAC address of the - * peer station */ + u8 peer[6]; /* MAC address of the peer station */ u16 reserved; u8 keydata[16]; /* AES key data */ } __packed aes_pairwise; @@ -1056,8 +1055,7 @@ struct wsm_add_key { u8 rx_seqnum[8]; /* Receive Sequence Counter */ } __packed aes_group; struct { - u8 peer[6]; /* MAC address of the - * peer station */ + u8 peer[6]; /* MAC address of the peer station */ u8 keyid; /* Key ID */ u8 reserved; u8 keydata[16]; /* WAPI key data */ @@ -1550,7 +1548,8 @@ struct wsm_tx_rate_retry_policy { * finishes. * BIT(3) - Count initial frame transmission as part of * rate retry counting but not as a retry - * attempt */ + * attempt + */ u8 flags; u8 rate_recoveries; u8 reserved[3]; @@ -1618,24 +1617,24 @@ static inline int wsm_set_udp_port_filter(struct cw1200_common *priv, #define D11_MAX_SSID_LEN (32) struct wsm_p2p_device_type { - __le16 categoryId; + __le16 category_id; u8 oui[4]; - __le16 subCategoryId; + __le16 subcategory_id; } __packed; struct wsm_p2p_device_info { struct wsm_p2p_device_type primaryDevice; u8 reserved1[3]; - u8 devNameSize; - u8 localDevName[D11_MAX_SSID_LEN]; + u8 devname_size; + u8 local_devname[D11_MAX_SSID_LEN]; u8 reserved2[3]; - u8 numSecDevSupported; - struct wsm_p2p_device_type secondaryDevices[0]; + u8 num_secdev_supported; + struct wsm_p2p_device_type secdevs[0]; } __packed; /* 4.36 SetWCDMABand - WO */ struct wsm_cdma_band { - u8 WCDMA_Band; + u8 wcdma_band; u8 reserved[3]; } __packed; @@ -1668,19 +1667,19 @@ struct wsm_ht_protection { #define WSM_GPIO_ALL_PINS 0xFF struct wsm_gpio_command { - u8 GPIO_Command; + u8 command; u8 pin; __le16 config; } __packed; /* 4.41 TSFCounter - RO */ struct wsm_tsf_counter { - __le64 TSF_Counter; + __le64 tsf_counter; } __packed; /* 4.43 Keep alive period */ struct wsm_keep_alive_period { - __le16 keepAlivePeriod; + __le16 period; u8 reserved[2]; } __packed; @@ -1688,7 +1687,7 @@ static inline int wsm_keep_alive_period(struct cw1200_common *priv, int period) { struct wsm_keep_alive_period arg = { - .keepAlivePeriod = __cpu_to_le16(period), + .period = __cpu_to_le16(period), }; return wsm_write_mib(priv, WSM_MIB_ID_KEEP_ALIVE_PERIOD, &arg, sizeof(arg)); @@ -1739,13 +1738,13 @@ static inline int wsm_set_arp_ipv4_filter(struct cw1200_common *priv, /* P2P Power Save Mode Info - 4.31 */ struct wsm_p2p_ps_modeinfo { - u8 oppPsCTWindow; + u8 opp_ps_ct_window; u8 count; u8 reserved; - u8 dtimCount; + u8 dtim_count; __le32 duration; __le32 interval; - __le32 startTime; + __le32 start_time; } __packed; static inline int wsm_set_p2p_ps_modeinfo(struct cw1200_common *priv, -- GitLab From 45fcac1aad5d092f46fc95230aad818abb221b34 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 30 Apr 2013 00:00:19 +0200 Subject: [PATCH 0856/2900] mfd: Move ssbi driver into drivers/mfd There is no reason for ssbi to have its own top-level driver directory when the only users of this interface are all MFD drivers. The only mainline driver using it at the moment (PM8921) is marked broken and in fact does not compile. I have verified that fixing the trivial build breakage in pm8921 links in the new ssbi code just fine, but that can be a separate patch. Signed-off-by: Arnd Bergmann Acked-by: Greg Kroah-Hartman Acked-by: Nicolas Pitre Acked-by: David Brown Signed-off-by: Samuel Ortiz --- drivers/Kconfig | 2 -- drivers/Makefile | 1 - drivers/mfd/Kconfig | 3 ++- drivers/mfd/Makefile | 2 +- drivers/{ssbi => mfd}/ssbi.c | 0 drivers/ssbi/Kconfig | 16 ---------------- drivers/ssbi/Makefile | 1 - 7 files changed, 3 insertions(+), 22 deletions(-) rename drivers/{ssbi => mfd}/ssbi.c (100%) delete mode 100644 drivers/ssbi/Kconfig delete mode 100644 drivers/ssbi/Makefile diff --git a/drivers/Kconfig b/drivers/Kconfig index 9953a42809ec..b8ec9cf1cfb2 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -52,8 +52,6 @@ source "drivers/i2c/Kconfig" source "drivers/spi/Kconfig" -source "drivers/ssbi/Kconfig" - source "drivers/hsi/Kconfig" source "drivers/pps/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 130abc1dfd65..bbf3810d0d49 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -117,7 +117,6 @@ obj-y += firmware/ obj-$(CONFIG_CRYPTO) += crypto/ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_ARCH_SHMOBILE) += sh/ -obj-$(CONFIG_SSBI) += ssbi/ ifndef CONFIG_ARCH_USES_GETTIMEOFFSET obj-y += clocksource/ endif diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d54e985748b7..013b094f0f9e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -419,7 +419,8 @@ config MFD_PM8XXX config MFD_PM8921_CORE tristate "Qualcomm PM8921 PMIC chip" - depends on SSBI && BROKEN + depends on (ARCH_MSM || HEXAGON) + depends on BROKEN select MFD_CORE select MFD_PM8XXX help diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 718e94a2a9a7..31d0f97d6e50 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -140,7 +140,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o -obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o +obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o ssbi.o obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o obj-$(CONFIG_MFD_TPS65090) += tps65090.o diff --git a/drivers/ssbi/ssbi.c b/drivers/mfd/ssbi.c similarity index 100% rename from drivers/ssbi/ssbi.c rename to drivers/mfd/ssbi.c diff --git a/drivers/ssbi/Kconfig b/drivers/ssbi/Kconfig deleted file mode 100644 index 1ae4040afedd..000000000000 --- a/drivers/ssbi/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -# -# SSBI bus support -# - -menu "Qualcomm MSM SSBI bus support" - -config SSBI - tristate "Qualcomm Single-wire Serial Bus Interface (SSBI)" - help - If you say yes to this option, support will be included for the - built-in SSBI interface on Qualcomm MSM family processors. - - This is required for communicating with Qualcomm PMICs and - other devices that have the SSBI interface. - -endmenu diff --git a/drivers/ssbi/Makefile b/drivers/ssbi/Makefile deleted file mode 100644 index 38fb70c31caf..000000000000 --- a/drivers/ssbi/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_SSBI) += ssbi.o -- GitLab From 15447a46a56a6d191af76ba0e3155c9b1877f596 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Wed, 15 May 2013 18:00:48 +0300 Subject: [PATCH 0857/2900] mfd: sec-core: Remove explicit call to mfd_remove_devices In case mfd_add_devices will fail, it will call to mfd_remove_devices by itself and return non-zero value. Signed-off-by: Leon Romanovsky Signed-off-by: Samuel Ortiz --- drivers/mfd/sec-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 77ee26ef5941..cc896d1c1cdd 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -230,13 +230,12 @@ static int sec_pmic_probe(struct i2c_client *i2c, BUG(); } - if (ret < 0) + if (ret) goto err; return ret; err: - mfd_remove_devices(sec_pmic->dev); sec_irq_exit(sec_pmic); i2c_unregister_device(sec_pmic->rtc); return ret; -- GitLab From 9032eabdd3fcfc00aa513a9eef54002cbabb8c9a Mon Sep 17 00:00:00 2001 From: Roger Tseng Date: Fri, 19 Apr 2013 21:52:42 +0800 Subject: [PATCH 0858/2900] mfd: rtsx: Add support for RTL8411B Adding support of model RTL8411B. Since the model is similar to RTL8411, differences are implemented in rtl8411.c. Signed-off-by: Roger Tseng Signed-off-by: Samuel Ortiz --- drivers/mfd/rtl8411.c | 132 +++++++++++++++++++++++++++++++++++ drivers/mfd/rtsx_pcr.c | 5 ++ drivers/mfd/rtsx_pcr.h | 1 + include/linux/mfd/rtsx_pci.h | 1 + 4 files changed, 139 insertions(+) diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 2a2d31687b72..c436bf27e78d 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -35,12 +35,33 @@ static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr) return val & 0x0F; } +static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) +{ + u8 val = 0; + + rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val); + + if (val & 0x2) + return 1; + else + return 0; +} + static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) { return rtsx_pci_write_register(pcr, CD_PAD_CTL, CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); } +static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) +{ + if (rtl8411b_is_qfn48(pcr)) + rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5); + + return rtsx_pci_write_register(pcr, CD_PAD_CTL, + CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); +} + static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) { return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); @@ -214,6 +235,20 @@ static const struct pcr_ops rtl8411_pcr_ops = { .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, }; +static const struct pcr_ops rtl8411b_pcr_ops = { + .extra_init_hw = rtl8411b_extra_init_hw, + .optimize_phy = NULL, + .turn_on_led = rtl8411_turn_on_led, + .turn_off_led = rtl8411_turn_off_led, + .enable_auto_blink = rtl8411_enable_auto_blink, + .disable_auto_blink = rtl8411_disable_auto_blink, + .card_power_on = rtl8411_card_power_on, + .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8411_switch_output_voltage, + .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, +}; + /* SD Pull Control Enable: * SD_DAT[3:0] ==> pull up * SD_CD ==> pull up @@ -276,6 +311,74 @@ static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = { 0, }; +static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + +static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = { + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), + RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), + 0, +}; + void rtl8411_init_params(struct rtsx_pcr *pcr) { pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; @@ -288,3 +391,32 @@ void rtl8411_init_params(struct rtsx_pcr *pcr) pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl; pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl; } + +void rtl8411b_init_params(struct rtsx_pcr *pcr) +{ + pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; + pcr->num_slots = 2; + pcr->ops = &rtl8411b_pcr_ops; + + pcr->ic_version = rtl8411_get_ic_version(pcr); + + if (rtl8411b_is_qfn48(pcr)) { + pcr->sd_pull_ctl_enable_tbl = + rtl8411b_qfn48_sd_pull_ctl_enable_tbl; + pcr->sd_pull_ctl_disable_tbl = + rtl8411b_qfn48_sd_pull_ctl_disable_tbl; + pcr->ms_pull_ctl_enable_tbl = + rtl8411b_qfn48_ms_pull_ctl_enable_tbl; + pcr->ms_pull_ctl_disable_tbl = + rtl8411b_qfn48_ms_pull_ctl_disable_tbl; + } else { + pcr->sd_pull_ctl_enable_tbl = + rtl8411b_qfn64_sd_pull_ctl_enable_tbl; + pcr->sd_pull_ctl_disable_tbl = + rtl8411b_qfn64_sd_pull_ctl_disable_tbl; + pcr->ms_pull_ctl_enable_tbl = + rtl8411b_qfn64_ms_pull_ctl_enable_tbl; + pcr->ms_pull_ctl_disable_tbl = + rtl8411b_qfn64_ms_pull_ctl_disable_tbl; + } +} diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index e968c01ca2ac..dd186c4103c1 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c @@ -57,6 +57,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = { { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { 0, } }; @@ -1038,6 +1039,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr) case 0x5249: rts5249_init_params(pcr); break; + + case 0x5287: + rtl8411b_init_params(pcr); + break; } dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h index 55fcfc25c4e4..c0cac7e8972f 100644 --- a/drivers/mfd/rtsx_pcr.h +++ b/drivers/mfd/rtsx_pcr.h @@ -33,5 +33,6 @@ void rts5229_init_params(struct rtsx_pcr *pcr); void rtl8411_init_params(struct rtsx_pcr *pcr); void rts5227_init_params(struct rtsx_pcr *pcr); void rts5249_init_params(struct rtsx_pcr *pcr); +void rtl8411b_init_params(struct rtsx_pcr *pcr); #endif diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 86bc635f8385..7a9f7089435d 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h @@ -575,6 +575,7 @@ #define CARD_PWR_CTL 0xFD50 #define CARD_CLK_SWITCH 0xFD51 +#define RTL8411B_PACKAGE_MODE 0xFD51 #define CARD_SHARE_MODE 0xFD52 #define CARD_DRIVE_SEL 0xFD53 #define CARD_STOP 0xFD54 -- GitLab From 032fa16d453c562c93b118e1c3e65f183c5f55cc Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 23 Apr 2013 16:19:10 +0300 Subject: [PATCH 0859/2900] mfd: twl-core: Convert to module_i2c_driver() Shift TWL initialization to module/device init layer, because I2C now is not initialized on subsys init layer and shifted to module/device init layer instead. The I2C <--> TWL dependency should be resolved in drivers/Makefile now. Cc: Santosh Shilimkar Signed-off-by: Grygorii Strashko Signed-off-by: Samuel Ortiz --- drivers/mfd/twl-core.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 89ab4d970643..8d9bc10c5312 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -1305,17 +1305,7 @@ static struct i2c_driver twl_driver = { .remove = twl_remove, }; -static int __init twl_init(void) -{ - return i2c_add_driver(&twl_driver); -} -subsys_initcall(twl_init); - -static void __exit twl_exit(void) -{ - i2c_del_driver(&twl_driver); -} -module_exit(twl_exit); +module_i2c_driver(twl_driver); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_DESCRIPTION("I2C Core interface for TWL"); -- GitLab From 8477128fe0c3c455e9dfb1ba7ad7e6d09489d33c Mon Sep 17 00:00:00 2001 From: James Ralston Date: Thu, 9 May 2013 12:38:53 -0700 Subject: [PATCH 0860/2900] mfd: lpc_ich: Add support for Intel Avoton SoC This patch adds the LPC Controller Device IDs for Watchdog and GPIO for Intel Avoton SoC, to the lpc_ich driver. Signed-off-by: James Ralston Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 9f12f91d6296..330cd44771be 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -51,6 +51,7 @@ * document number TBD : Lynx Point * document number TBD : Lynx Point-LP * document number TBD : Wellsburg + * document number TBD : Avoton SoC */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -207,6 +208,7 @@ enum lpc_chipsets { LPC_LPT, /* Lynx Point */ LPC_LPT_LP, /* Lynx Point-LP */ LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ }; struct lpc_ich_info lpc_chipset_info[] = { @@ -491,6 +493,10 @@ struct lpc_ich_info lpc_chipset_info[] = { .name = "Wellsburg", .iTCO_version = 2, }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 1, + }, }; /* @@ -704,6 +710,10 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); -- GitLab From 7d71cf29416a8c5f11e98d507054a01b9cb71ff5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:04:25 +0900 Subject: [PATCH 0861/2900] mfd: intel_msic: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Acked-by: Mika Westerberg Signed-off-by: Samuel Ortiz --- drivers/mfd/intel_msic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c index d8d5137f9717..4f2462f0963e 100644 --- a/drivers/mfd/intel_msic.c +++ b/drivers/mfd/intel_msic.c @@ -438,7 +438,6 @@ static int intel_msic_remove(struct platform_device *pdev) struct intel_msic *msic = platform_get_drvdata(pdev); intel_msic_remove_devices(msic); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 9f74f5b541c2994c7cad4c450323913bff67fab7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:05:43 +0900 Subject: [PATCH 0862/2900] mfd: jz4740-adc: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/jz4740-adc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index e80587f1a792..01e86ce438f1 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -294,7 +294,6 @@ static int jz4740_adc_probe(struct platform_device *pdev) err_clk_put: clk_put(adc->clk); err_iounmap: - platform_set_drvdata(pdev, NULL); iounmap(adc->base); err_release_mem_region: release_mem_region(adc->mem->start, resource_size(adc->mem)); @@ -317,8 +316,6 @@ static int jz4740_adc_remove(struct platform_device *pdev) clk_put(adc->clk); - platform_set_drvdata(pdev, NULL); - return 0; } -- GitLab From 96ac2d1a3a352ce1f4d669ad222677ba2ed76271 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:06:31 +0900 Subject: [PATCH 0863/2900] mfd: twl4030-audio: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-audio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index d2ab222138c2..a31fba96ef43 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c @@ -261,10 +261,8 @@ static int twl4030_audio_probe(struct platform_device *pdev) ret = -ENODEV; } - if (ret) { - platform_set_drvdata(pdev, NULL); + if (ret) twl4030_audio_dev = NULL; - } return ret; } @@ -272,7 +270,6 @@ static int twl4030_audio_probe(struct platform_device *pdev) static int twl4030_audio_remove(struct platform_device *pdev) { mfd_remove_devices(&pdev->dev); - platform_set_drvdata(pdev, NULL); twl4030_audio_dev = NULL; return 0; -- GitLab From c3d6a0a3194092aec01a579a60a791c4afc47411 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:08:08 +0900 Subject: [PATCH 0864/2900] mfd: twl4030-madc: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-madc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c index 42bd3ea5df3c..1ea54d4d003a 100644 --- a/drivers/mfd/twl4030-madc.c +++ b/drivers/mfd/twl4030-madc.c @@ -775,12 +775,10 @@ static int twl4030_madc_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING, "twl4030_madc", madc); if (ret) { dev_dbg(&pdev->dev, "could not request irq\n"); - goto err_irq; + goto err_i2c; } twl4030_madc = madc; return 0; -err_irq: - platform_set_drvdata(pdev, NULL); err_i2c: twl4030_madc_set_current_generator(madc, 0, 0); err_current_generator: @@ -796,7 +794,6 @@ static int twl4030_madc_remove(struct platform_device *pdev) struct twl4030_madc_data *madc = platform_get_drvdata(pdev); free_irq(platform_get_irq(pdev, 0), madc); - platform_set_drvdata(pdev, NULL); twl4030_madc_set_current_generator(madc, 0, 0); twl4030_madc_set_power(madc, 0); kfree(madc); -- GitLab From 3b87b4eb536d454ae506dc68144936a169fdcf94 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:09:57 +0900 Subject: [PATCH 0865/2900] mfd: mcp-sa11x0: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/mcp-sa11x0.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index f99d6299ec24..13198d937e36 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c @@ -225,8 +225,6 @@ static int mcp_sa11x0_probe(struct platform_device *dev) if (ret == 0) return 0; - platform_set_drvdata(dev, NULL); - err_ioremap: iounmap(m->base1); iounmap(m->base0); @@ -252,7 +250,6 @@ static int mcp_sa11x0_remove(struct platform_device *dev) mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0); mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1); - platform_set_drvdata(dev, NULL); mcp_host_del(mcp); iounmap(m->base1); iounmap(m->base0); -- GitLab From 3b69f59bef86498e38d8153cc08138de74da8ea6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:12:24 +0900 Subject: [PATCH 0866/2900] mfd: t7l66xb: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/t7l66xb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index b32940ec9034..a21bff283a98 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -422,7 +422,6 @@ static int t7l66xb_remove(struct platform_device *dev) iounmap(t7l66xb->scr); release_resource(&t7l66xb->rscr); mfd_remove_devices(&dev->dev); - platform_set_drvdata(dev, NULL); kfree(t7l66xb); return ret; -- GitLab From ae8574864b52cae1e35e7881737b5e08036f0fa1 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:13:05 +0900 Subject: [PATCH 0867/2900] mfd: tc6387xb: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/tc6387xb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 366f7b906278..65c425a517c5 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -217,7 +217,6 @@ static int tc6387xb_remove(struct platform_device *dev) release_resource(&tc6387xb->rscr); clk_disable(tc6387xb->clk32k); clk_put(tc6387xb->clk32k); - platform_set_drvdata(dev, NULL); kfree(tc6387xb); return 0; -- GitLab From fa67d4ebc7e492e07bd2d3bf2937dfae2bb514bd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 6 May 2013 13:14:14 +0900 Subject: [PATCH 0868/2900] mfd: tc6393xb: Remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/tc6393xb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 15e1463e5e13..a563dfa3cf87 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -756,7 +756,6 @@ static int tc6393xb_remove(struct platform_device *dev) clk_disable(tc6393xb->clk); iounmap(tc6393xb->scr); release_resource(&tc6393xb->rscr); - platform_set_drvdata(dev, NULL); clk_put(tc6393xb->clk); kfree(tc6393xb); -- GitLab From fc83f586adf3b86ff7046478497b4a53b2220be8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 6 May 2013 09:46:29 +0200 Subject: [PATCH 0869/2900] mfd: cros_ec: Fix Kconfig typo - s/ned/need/ Acked-by: Simon Glass Signed-off-by: Geert Uytterhoeven Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 013b094f0f9e..c6eb930fb54d 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -53,7 +53,7 @@ config MFD_CROS_EC help If you say Y here you get support for the ChromeOS Embedded Controller (EC) providing keyboard, battery and power services. - You also ned to enable the driver for the bus you are using. The + You also need to enable the driver for the bus you are using. The protocol for talking to the EC is defined by the bus driver. config MFD_CROS_EC_I2C -- GitLab From 7c8844481a1c16c10fa9be4ce95be5725aed6ce3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 6 May 2013 16:12:56 +0100 Subject: [PATCH 0870/2900] mfd: wm8994: Emulate level triggered interrupts if required The interrupt controller on the wm8994 series of devices requires a level triggered parent. If one is not available but a GPIO is available for the interrupt then emulate. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-irq.c | 100 +++++++++++++++++++++++++++++-- include/linux/mfd/wm8994/core.h | 2 + include/linux/mfd/wm8994/pdata.h | 5 ++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index a050e56a9bbd..d3a184a240f5 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -14,10 +14,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -138,6 +140,55 @@ static struct regmap_irq_chip wm8994_irq_chip = { .runtime_pm = true, }; +static void wm8994_edge_irq_enable(struct irq_data *data) +{ +} + +static void wm8994_edge_irq_disable(struct irq_data *data) +{ +} + +static struct irq_chip wm8994_edge_irq_chip = { + .name = "wm8994_edge", + .irq_disable = wm8994_edge_irq_disable, + .irq_enable = wm8994_edge_irq_enable, +}; + +static irqreturn_t wm8994_edge_irq(int irq, void *data) +{ + struct wm8994 *wm8994 = data; + + while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio)) + handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0)); + + return IRQ_HANDLED; +} + +static int wm8994_edge_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct wm8994 *wm8994 = h->host_data; + + irq_set_chip_data(virq, wm8994); + irq_set_chip_and_handler(virq, &wm8994_edge_irq_chip, handle_edge_irq); + irq_set_nested_thread(virq, 1); + + /* ARM needs us to explicitly flag the IRQ as valid + * and will set them noprobe when we do so. */ +#ifdef CONFIG_ARM + set_irq_flags(virq, IRQF_VALID); +#else + irq_set_noprobe(virq); +#endif + + return 0; +} + +static struct irq_domain_ops wm8994_edge_irq_ops = { + .map = wm8994_edge_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + int wm8994_irq_init(struct wm8994 *wm8994) { int ret; @@ -156,10 +207,51 @@ int wm8994_irq_init(struct wm8994 *wm8994) if (pdata->irq_flags) irqflags = pdata->irq_flags; - ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, - irqflags, - wm8994->irq_base, &wm8994_irq_chip, - &wm8994->irq_data); + /* use a GPIO for edge triggered controllers */ + if (irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { + if (gpio_to_irq(pdata->irq_gpio) != wm8994->irq) { + dev_warn(wm8994->dev, "IRQ %d is not GPIO %d (%d)\n", + wm8994->irq, pdata->irq_gpio, + gpio_to_irq(pdata->irq_gpio)); + wm8994->irq = gpio_to_irq(pdata->irq_gpio); + } + + ret = devm_gpio_request_one(wm8994->dev, pdata->irq_gpio, + GPIOF_IN, "WM8994 IRQ"); + + if (ret != 0) { + dev_err(wm8994->dev, "Failed to get IRQ GPIO: %d\n", + ret); + return ret; + } + + wm8994->edge_irq = irq_domain_add_linear(NULL, 1, + &wm8994_edge_irq_ops, + wm8994); + + ret = regmap_add_irq_chip(wm8994->regmap, + irq_create_mapping(wm8994->edge_irq, + 0), + IRQF_ONESHOT, + wm8994->irq_base, &wm8994_irq_chip, + &wm8994->irq_data); + if (ret != 0) { + dev_err(wm8994->dev, "Failed to get IRQ: %d\n", + ret); + return ret; + } + + ret = request_threaded_irq(wm8994->irq, + NULL, wm8994_edge_irq, + irqflags, + "WM8994 edge", wm8994); + } else { + ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, + irqflags, + wm8994->irq_base, &wm8994_irq_chip, + &wm8994->irq_data); + } + if (ret != 0) { dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret); return ret; diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h index ae5c249530b4..40854ac0ba3d 100644 --- a/include/linux/mfd/wm8994/core.h +++ b/include/linux/mfd/wm8994/core.h @@ -29,6 +29,7 @@ enum wm8994_type { struct regulator_dev; struct regulator_bulk_data; +struct irq_domain; #define WM8994_NUM_GPIO_REGS 11 #define WM8994_NUM_LDO_REGS 2 @@ -73,6 +74,7 @@ struct wm8994 { int irq; struct regmap_irq_chip_data *irq_data; + struct irq_domain *edge_irq; /* Used over suspend/resume */ bool suspended; diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 68e776594889..90e9bf86e643 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -223,6 +223,11 @@ struct wm8994_pdata { * lines is mastered. */ int max_channels_clocked[WM8994_NUM_AIF]; + + /** + * GPIO for the IRQ pin if host only supports edge triggering + */ + int irq_gpio; }; #endif -- GitLab From c0fa7e104bbae5286f4fcf359f66a536f849c040 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 10 May 2013 10:11:59 -0700 Subject: [PATCH 0871/2900] mfd: max77687: Add registration of max77686-clk The MAX77686 clock driver has been in-tree for over 6 months, but never actually enabled through the MFD registration before. Add it to the table so the device will probe and configure properly. Signed-off-by: Olof Johansson Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 1cbb17609c8b..5bd24670e1b6 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -37,6 +37,7 @@ static struct mfd_cell max77686_devs[] = { { .name = "max77686-pmic", }, { .name = "max77686-rtc", }, + { .name = "max77686-clk", }, }; static struct regmap_config max77686_regmap_config = { -- GitLab From 404d5df42a812b81ec87b76cc3d2e492434e9ff7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 12 May 2013 20:05:48 +0200 Subject: [PATCH 0872/2900] mfd: jz4740-adc: Use clk_prepare_enable/clk_disable_unprepare In preparation to switching the jz4740 clk driver to the common clk framework update the clk enable/disable calls to clk_prepare_enable/clk_disable_unprepare. Signed-off-by: Lars-Peter Clausen Signed-off-by: Samuel Ortiz --- drivers/mfd/jz4740-adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 01e86ce438f1..3c0e8cf6916b 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c @@ -86,13 +86,13 @@ static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc) static inline void jz4740_adc_clk_enable(struct jz4740_adc *adc) { if (atomic_inc_return(&adc->clk_ref) == 1) - clk_enable(adc->clk); + clk_prepare_enable(adc->clk); } static inline void jz4740_adc_clk_disable(struct jz4740_adc *adc) { if (atomic_dec_return(&adc->clk_ref) == 0) - clk_disable(adc->clk); + clk_disable_unprepare(adc->clk); } static inline void jz4740_adc_set_enabled(struct jz4740_adc *adc, int engine, -- GitLab From f7d3210e8b45eea8561c08d35502d2baca07593a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 17 May 2013 00:53:42 +0200 Subject: [PATCH 0873/2900] MAINTAINERS: Add Lee Jones as the MFD co-maintainer Lee Jones from Linaro offered to help me with maitaining the MFD drivers. Also, fix the MFD tree URLs. Signed-off-by: Samuel Ortiz --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 250dc970c62d..39fd4e794b1e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5432,7 +5432,9 @@ F: include/media/mt9v032.h MULTIFUNCTION DEVICES (MFD) M: Samuel Ortiz -T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git +M: Lee Jones +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git S: Supported F: drivers/mfd/ -- GitLab From 629d0fa0da40958809e6577350c903b9368ef672 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 10 Jun 2013 13:42:40 +0300 Subject: [PATCH 0874/2900] iwlwifi: mvm: remove unused wait_for_ba field Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/sta.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index 3efa0a0cc987..94b265eb32b8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h @@ -250,7 +250,6 @@ enum iwl_mvm_agg_state { * the first packet to be sent in legacy HW queue in Tx AGG stop flow. * Basically when next_reclaimed reaches ssn, we can tell mac80211 that * we are ready to finish the Tx AGG stop / start flow. - * @wait_for_ba: Expect block-ack before next Tx reply */ struct iwl_mvm_tid_data { u16 seq_number; @@ -260,7 +259,6 @@ struct iwl_mvm_tid_data { enum iwl_mvm_agg_state state; u16 txq_id; u16 ssn; - bool wait_for_ba; }; /** -- GitLab From 0742a75a72ee52a7424554a1d49882dd9db195e3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 10 Jun 2013 14:10:33 +0300 Subject: [PATCH 0875/2900] iwlwifi: mvm: fix irrelevant comment This code moved and is now far away from the code that takes the mutex. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f2976901b1d5..795f65cf6332 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -639,8 +639,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, * By now, all the AC queues are empty. The AGG queues are * empty too. We already got all the Tx responses for all the * packets in the queues. The drain work can have been - * triggered. Flush it. This work item takes the mutex, so kill - * it before we take it. + * triggered. Flush it. */ flush_work(&mvm->sta_drained_wk); } -- GitLab From 476a9e09cbe37bad93de6e460b76f89f3ad22c9b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 11 Jun 2013 15:17:21 +0300 Subject: [PATCH 0876/2900] iwlwifi: ignore 0-length PHY DB sections This can happen during development but can cause problems, WARN (once) and go on. Signed-off-by: Emmanuel Grumbach Reviewed-by: Guy Cohen Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-phy-db.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 25745daa0d5d..84acb4deca8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c @@ -413,6 +413,9 @@ static int iwl_phy_db_send_all_channel_groups( if (!entry) return -EINVAL; + if (WARN_ON_ONCE(!entry->size)) + continue; + /* Send the requested PHY DB section */ err = iwl_send_phy_db_cmd(phy_db, type, -- GitLab From 565f5a942b0391b528c5fc6f3c535900f4617816 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 Jun 2013 17:36:26 +0200 Subject: [PATCH 0877/2900] iwlwifi: include export.h instead of module.h We only need EXPORT_SYMBOL_GPL, none of the other things from module.h, so only include export.h. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-drv.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h index 7d1450916308..429337a2b9a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/iwlwifi/iwl-drv.h @@ -62,8 +62,7 @@ #ifndef __iwl_drv_h__ #define __iwl_drv_h__ - -#include +#include /* for all modules */ #define DRV_NAME "iwlwifi" -- GitLab From 5af01772ee1d6e96849adf728ff837bd71b119c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Jun 2013 12:59:24 +0300 Subject: [PATCH 0878/2900] iwlwifi: mvm: properly tell the fw that a STA is awake The firmware API wasn't being used correctly, fix that. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/sta.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 2278858d5658..f986eb50c4a4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -1292,17 +1292,11 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, struct iwl_mvm_add_sta_cmd cmd = { .add_modify = STA_MODE_MODIFY, .sta_id = mvmsta->sta_id, - .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, - .sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE), + .station_flags_msk = cpu_to_le32(STA_FLG_PS), .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), }; int ret; - /* - * Same modify mask for sleep_tx_count and sleep_state_flags but this - * should be fine since if we set the STA as "awake", then - * sleep_tx_count is not relevant. - */ ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); -- GitLab From 837fb69f10588caafc883c4473a864660e1403ce Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 9 Jun 2013 13:00:12 +0300 Subject: [PATCH 0879/2900] iwlwifi: mvm: don't set the MCAST queue in STA's queue list The MCAST queue should be enabled after DTIM only. According to fw API, the MCAST must not be attached to any station, but should appear in the mcast_qid of the AP's mac context only. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 5 +---- drivers/net/wireless/iwlwifi/mvm/sta.c | 3 --- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 46c7c0507c25..273b0cc197ab 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -193,14 +193,11 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { - u32 qmask, ac; + u32 qmask = 0, ac; if (vif->type == NL80211_IFTYPE_P2P_DEVICE) return BIT(IWL_MVM_OFFCHANNEL_QUEUE); - qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ? - BIT(vif->cab_queue) : 0; - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) qmask |= BIT(vif->hw_queue[ac]); diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index f986eb50c4a4..62fe5209093b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -229,9 +229,6 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]); - if (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) - mvm_sta->tfd_queue_msk |= BIT(vif->cab_queue); - /* for HW restart - need to reset the seq_number etc... */ memset(mvm_sta->tid_data, 0, sizeof(mvm_sta->tid_data)); -- GitLab From 8eb3871076875f247483f4a1fe6713e6d440c53e Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Sat, 1 Jun 2013 20:17:18 +0300 Subject: [PATCH 0880/2900] iwlwifi: mvm: Update the supported interface combinations iwlmvm does not support concurrent operation of AP with P2P Client/GO. Update the interface limits to reflect that iwlmvm supports only concurrent operation of station with AP and P2P Client/GO. Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 1767a8849591..f091cf24b96c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -81,12 +81,12 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { { .max = 1, - .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP), + .types = BIT(NL80211_IFTYPE_STATION), }, { .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + .types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO), }, { -- GitLab From ad71d889b88055e61e3970a6744a271a51a94f42 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 30 Apr 2013 15:46:14 -0400 Subject: [PATCH 0881/2900] tracing: Add function probe to trigger a ftrace dump to console Add the "dump" command to have the ftrace buffer dumped to console if a function is hit. This is useful when debugging a tripple fault, where you have an idea of a function that is called just before the tripple fault occurs, and can tell ftrace to dump its content out to the console before it continues. Format is: :dump echo 'bad_address:dump' > /debug/tracing/set_ftrace_filter To remove this: echo '!bad_address:dump' > /debug/tracing/set_ftrace_filter Requested-by: Luis Claudio R. Goncalves Signed-off-by: Steven Rostedt --- Documentation/trace/ftrace.txt | 7 ++++ kernel/trace/trace_functions.c | 59 +++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index bfe8c29b1f1d..cc9ec57e157c 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -2430,6 +2430,13 @@ The following commands are supported: echo '!schedule:disable_event:sched:sched_switch' > \ set_ftrace_filter +- dump + When the function is hit, it will dump the contents of the ftrace + ring buffer to the console. This is useful if you need to debug + something, and want to dump the trace when a certain function + is hit. Perhaps its a function that is called before a tripple + fault happens and does not allow you to get a regular dump. + trace_pipe ---------- diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index c4d6d7191988..d7c8719734b8 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c @@ -290,6 +290,13 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data) trace_dump_stack(STACK_SKIP); } +static void +ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data) +{ + if (update_count(data)) + ftrace_dump(DUMP_ALL); +} + static int ftrace_probe_print(const char *name, struct seq_file *m, unsigned long ip, void *data) @@ -327,6 +334,13 @@ ftrace_stacktrace_print(struct seq_file *m, unsigned long ip, return ftrace_probe_print("stacktrace", m, ip, data); } +static int +ftrace_dump_print(struct seq_file *m, unsigned long ip, + struct ftrace_probe_ops *ops, void *data) +{ + return ftrace_probe_print("dump", m, ip, data); +} + static struct ftrace_probe_ops traceon_count_probe_ops = { .func = ftrace_traceon_count, .print = ftrace_traceon_print, @@ -342,6 +356,11 @@ static struct ftrace_probe_ops stacktrace_count_probe_ops = { .print = ftrace_stacktrace_print, }; +static struct ftrace_probe_ops dump_probe_ops = { + .func = ftrace_dump_probe, + .print = ftrace_dump_print, +}; + static struct ftrace_probe_ops traceon_probe_ops = { .func = ftrace_traceon, .print = ftrace_traceon_print, @@ -425,6 +444,19 @@ ftrace_stacktrace_callback(struct ftrace_hash *hash, param, enable); } +static int +ftrace_dump_callback(struct ftrace_hash *hash, + char *glob, char *cmd, char *param, int enable) +{ + struct ftrace_probe_ops *ops; + + ops = &dump_probe_ops; + + /* Only dump once. */ + return ftrace_trace_probe_callback(ops, hash, glob, cmd, + "1", enable); +} + static struct ftrace_func_command ftrace_traceon_cmd = { .name = "traceon", .func = ftrace_trace_onoff_callback, @@ -440,6 +472,11 @@ static struct ftrace_func_command ftrace_stacktrace_cmd = { .func = ftrace_stacktrace_callback, }; +static struct ftrace_func_command ftrace_dump_cmd = { + .name = "dump", + .func = ftrace_dump_callback, +}; + static int __init init_func_cmd_traceon(void) { int ret; @@ -450,13 +487,25 @@ static int __init init_func_cmd_traceon(void) ret = register_ftrace_command(&ftrace_traceon_cmd); if (ret) - unregister_ftrace_command(&ftrace_traceoff_cmd); + goto out_free_traceoff; ret = register_ftrace_command(&ftrace_stacktrace_cmd); - if (ret) { - unregister_ftrace_command(&ftrace_traceoff_cmd); - unregister_ftrace_command(&ftrace_traceon_cmd); - } + if (ret) + goto out_free_traceon; + + ret = register_ftrace_command(&ftrace_dump_cmd); + if (ret) + goto out_free_stacktrace; + + return 0; + + out_free_stacktrace: + unregister_ftrace_command(&ftrace_stacktrace_cmd); + out_free_traceon: + unregister_ftrace_command(&ftrace_traceon_cmd); + out_free_traceoff: + unregister_ftrace_command(&ftrace_traceoff_cmd); + return ret; } #else -- GitLab From 90e3c03c3a09a7b176b3fe59d78f5d9755ac8e37 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 30 Apr 2013 19:00:46 -0400 Subject: [PATCH 0882/2900] tracing: Add function probe to trigger a ftrace dump of current CPU trace Add the "cpudump" command to have the current CPU ftrace buffer dumped to console if a function is hit. This is useful when debugging a tripple fault, where you have an idea of a function that is called just before the tripple fault occurs, and can tell ftrace to dump its content out to the console before it continues. This differs from the "dump" command as it only dumps the content of the ring buffer for the currently executing CPU, and does not show the contents of the other CPUs. Format is: :cpudump echo 'bad_address:cpudump' > /debug/tracing/set_ftrace_filter To remove this: echo '!bad_address:cpudump' > /debug/tracing/set_ftrace_filter Signed-off-by: Steven Rostedt --- Documentation/trace/ftrace.txt | 6 +++++ kernel/trace/trace_functions.c | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index cc9ec57e157c..b937c6e2163c 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -2437,6 +2437,12 @@ The following commands are supported: is hit. Perhaps its a function that is called before a tripple fault happens and does not allow you to get a regular dump. +- cpudump + When the function is hit, it will dump the contents of the ftrace + ring buffer for the current CPU to the console. Unlike the "dump" + command, it only prints out the contents of the ring buffer for the + CPU that executed the function that triggered the dump. + trace_pipe ---------- diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index d7c8719734b8..b863f93b30f3 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c @@ -297,6 +297,14 @@ ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data) ftrace_dump(DUMP_ALL); } +/* Only dump the current CPU buffer. */ +static void +ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, void **data) +{ + if (update_count(data)) + ftrace_dump(DUMP_ORIG); +} + static int ftrace_probe_print(const char *name, struct seq_file *m, unsigned long ip, void *data) @@ -341,6 +349,13 @@ ftrace_dump_print(struct seq_file *m, unsigned long ip, return ftrace_probe_print("dump", m, ip, data); } +static int +ftrace_cpudump_print(struct seq_file *m, unsigned long ip, + struct ftrace_probe_ops *ops, void *data) +{ + return ftrace_probe_print("cpudump", m, ip, data); +} + static struct ftrace_probe_ops traceon_count_probe_ops = { .func = ftrace_traceon_count, .print = ftrace_traceon_print, @@ -361,6 +376,11 @@ static struct ftrace_probe_ops dump_probe_ops = { .print = ftrace_dump_print, }; +static struct ftrace_probe_ops cpudump_probe_ops = { + .func = ftrace_cpudump_probe, + .print = ftrace_cpudump_print, +}; + static struct ftrace_probe_ops traceon_probe_ops = { .func = ftrace_traceon, .print = ftrace_traceon_print, @@ -457,6 +477,19 @@ ftrace_dump_callback(struct ftrace_hash *hash, "1", enable); } +static int +ftrace_cpudump_callback(struct ftrace_hash *hash, + char *glob, char *cmd, char *param, int enable) +{ + struct ftrace_probe_ops *ops; + + ops = &cpudump_probe_ops; + + /* Only dump once. */ + return ftrace_trace_probe_callback(ops, hash, glob, cmd, + "1", enable); +} + static struct ftrace_func_command ftrace_traceon_cmd = { .name = "traceon", .func = ftrace_trace_onoff_callback, @@ -477,6 +510,11 @@ static struct ftrace_func_command ftrace_dump_cmd = { .func = ftrace_dump_callback, }; +static struct ftrace_func_command ftrace_cpudump_cmd = { + .name = "cpudump", + .func = ftrace_cpudump_callback, +}; + static int __init init_func_cmd_traceon(void) { int ret; @@ -497,8 +535,14 @@ static int __init init_func_cmd_traceon(void) if (ret) goto out_free_stacktrace; + ret = register_ftrace_command(&ftrace_cpudump_cmd); + if (ret) + goto out_free_dump; + return 0; + out_free_dump: + unregister_ftrace_command(&ftrace_dump_cmd); out_free_stacktrace: unregister_ftrace_command(&ftrace_stacktrace_cmd); out_free_traceon: -- GitLab From 8092e808a31839c502a52d391b15f31c1d8764f5 Mon Sep 17 00:00:00 2001 From: Harsh Prateek Bora Date: Fri, 24 May 2013 12:52:17 +0530 Subject: [PATCH 0883/2900] tracing/trivial: Consolidate error return condition Consolidate the checks for !enabled and !param to return -EINVAL in event_enable_func(). Link: http://lkml.kernel.org/r/1369380137-12452-1-git-send-email-harsh@linux.vnet.ibm.com Signed-off-by: Harsh Prateek Bora Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 27963e2bf4bf..db086f172cf5 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2011,10 +2011,7 @@ event_enable_func(struct ftrace_hash *hash, int ret; /* hash funcs only work with set_ftrace_filter */ - if (!enabled) - return -EINVAL; - - if (!param) + if (!enabled || !param) return -EINVAL; system = strsep(¶m, ":"); -- GitLab From 238ae93d699d59876b470bf6455de22bcfaa9a1b Mon Sep 17 00:00:00 2001 From: Wang YanQing Date: Sun, 26 May 2013 16:52:01 +0800 Subject: [PATCH 0884/2900] tracing: Fix file mode of free_buffer Commit 4f271a2a60c748599b30bb4dafff30d770439b96 (tracing: Add a proc file to stop tracing and free buffer) implement a method to free up ring buffer in kernel memory in the release code path of free_buffer's fd. Then we don't need read/write support for free_buffer, indeed we just have a dummy write fop, and don't implement read fop. So the 0200 is more reasonable file mode for free_buffer than the current file mode 0644. Link: http://lkml.kernel.org/r/20130526085201.GA3183@udknight Acked-by: Vaibhav Nagarnaik Acked-by: David Sharp Signed-off-by: Wang YanQing Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1a41023a1f88..5f4a09c12e0b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -5935,7 +5935,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer) trace_create_file("buffer_total_size_kb", 0444, d_tracer, tr, &tracing_total_entries_fops); - trace_create_file("free_buffer", 0644, d_tracer, + trace_create_file("free_buffer", 0200, d_tracer, tr, &tracing_free_buffer_fops); trace_create_file("trace_marker", 0220, d_tracer, -- GitLab From 7614c3dc74733dff4b0e774f7a894b9ea6ec508c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 28 May 2013 20:01:16 -0400 Subject: [PATCH 0885/2900] ftrace: Use schedule_on_each_cpu() as a heavy synchronize_sched() The function tracer uses preempt_disable/enable_notrace() for synchronization between reading registered ftrace_ops and unregistering them. Most of the ftrace_ops are global permanent structures that do not require this synchronization. That is, ops may be added and removed from the hlist but are never freed, and wont hurt if a synchronization is missed. But this is not true for dynamically created ftrace_ops or control_ops, which are used by the perf function tracing. The problem here is that the function tracer can be used to trace kernel/user context switches as well as going to and from idle. Basically, it can be used to trace blind spots of the RCU subsystem. This means that even though preempt_disable() is done, a synchronize_sched() will ignore CPUs that haven't made it out of user space or idle. These can include functions that are being traced just before entering or exiting the kernel sections. To implement the RCU synchronization, instead of using synchronize_sched() the use of schedule_on_each_cpu() is performed. This means that when a dynamically allocated ftrace_ops, or a control ops is being unregistered, all CPUs must be touched and execute a ftrace_sync() stub function via the work queues. This will rip CPUs out from idle or in dynamic tick mode. This only happens when a user disables perf function tracing or other dynamically allocated function tracers, but it allows us to continue to debug RCU and context tracking with function tracing. Link: http://lkml.kernel.org/r/1369785676.15552.55.camel@gandalf.local.home Cc: "Paul E. McKenney" Cc: Tejun Heo Cc: Ingo Molnar Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Acked-by: Paul E. McKenney Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6c508ff33c62..800a8a2fbddb 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -413,6 +413,17 @@ static int __register_ftrace_function(struct ftrace_ops *ops) return 0; } +static void ftrace_sync(struct work_struct *work) +{ + /* + * This function is just a stub to implement a hard force + * of synchronize_sched(). This requires synchronizing + * tasks even in userspace and idle. + * + * Yes, function tracing is rude. + */ +} + static int __unregister_ftrace_function(struct ftrace_ops *ops) { int ret; @@ -440,8 +451,12 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) * so there'll be no new users. We must ensure * all current users are done before we free * the control data. + * Note synchronize_sched() is not enough, as we + * use preempt_disable() to do RCU, but the function + * tracer can be called where RCU is not active + * (before user_exit()). */ - synchronize_sched(); + schedule_on_each_cpu(ftrace_sync); control_ops_free(ops); } } else @@ -456,9 +471,13 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) /* * Dynamic ops may be freed, we must make sure that all * callers are done before leaving this function. + * + * Again, normal synchronize_sched() is not good enough. + * We need to do a hard force of sched synchronization. */ if (ops->flags & FTRACE_OPS_FL_DYNAMIC) - synchronize_sched(); + schedule_on_each_cpu(ftrace_sync); + return 0; } -- GitLab From 1b3d0623cd9da35fe1d52281ed06c2ff543cd660 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 7 Jun 2013 17:02:53 +0800 Subject: [PATCH 0886/2900] ftrace: Remove ftrace_regex_lseek() This is a leftover after ftrace_regex_lseek() was renamed to ftrace_filter_lseek() and then ftrace_filter_lseek() was moved out side of CONFIG_DYNAMIC_FTRACE. Link: http://lkml.kernel.org/r/51B1A1BD.40905@huawei.com Signed-off-by: Li Zefan Signed-off-by: Steven Rostedt --- include/linux/ftrace.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 99d0fbcbaf79..e48ed1d7876d 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -566,10 +566,6 @@ static inline ssize_t ftrace_filter_write(struct file *file, const char __user * size_t cnt, loff_t *ppos) { return -ENODEV; } static inline ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos) { return -ENODEV; } -static inline loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence) -{ - return -ENODEV; -} static inline int ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; } #endif /* CONFIG_DYNAMIC_FTRACE */ -- GitLab From aaf6ac0f0871cb7fc0f28f3a00edf329bc7adc29 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 7 Jun 2013 15:07:48 +0900 Subject: [PATCH 0887/2900] tracing: Do not call kmem_cache_free() on allocation failure There's no point calling it when _alloc() failed. Link: http://lkml.kernel.org/r/1370585268-29169-1-git-send-email-namhyung@kernel.org Signed-off-by: Namhyung Kim Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index db086f172cf5..f57b01574a30 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -97,7 +97,7 @@ static int __trace_define_field(struct list_head *head, const char *type, field = kmem_cache_alloc(field_cachep, GFP_TRACE); if (!field) - goto err; + return -ENOMEM; field->name = name; field->type = type; @@ -114,11 +114,6 @@ static int __trace_define_field(struct list_head *head, const char *type, list_add(&field->link, head); return 0; - -err: - kmem_cache_free(field_cachep, field); - - return -ENOMEM; } int trace_define_field(struct ftrace_event_call *call, const char *type, -- GitLab From 130d3d68b52097c7ae081109f700b02776adcb9c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Jun 2013 13:56:19 -0700 Subject: [PATCH 0888/2900] net_sched: psched_ratecfg_precompute() improvements Before allowing 64bits bytes rates, refactor psched_ratecfg_precompute() to get better comments and increased accuracy. rate_bps field is renamed to rate_bytes_ps, as we only have to worry about bytes per second. Signed-off-by: Eric Dumazet Cc: Ben Greear Signed-off-by: David S. Miller --- include/net/sch_generic.h | 4 ++-- net/sched/sch_generic.c | 44 ++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index df5676029827..6eab63363e59 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -680,7 +680,7 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask, #endif struct psched_ratecfg { - u64 rate_bps; + u64 rate_bytes_ps; /* bytes per second */ u32 mult; u16 overhead; u8 shift; @@ -698,7 +698,7 @@ static inline void psched_ratecfg_getrate(struct tc_ratespec *res, const struct psched_ratecfg *r) { memset(res, 0, sizeof(*res)); - res->rate = r->rate_bps >> 3; + res->rate = r->rate_bytes_ps; res->overhead = r->overhead; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 20224086cc28..4626cef4b76e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -901,37 +901,33 @@ void dev_shutdown(struct net_device *dev) void psched_ratecfg_precompute(struct psched_ratecfg *r, const struct tc_ratespec *conf) { - u64 factor; - u64 mult; - int shift; - memset(r, 0, sizeof(*r)); r->overhead = conf->overhead; - r->rate_bps = (u64)conf->rate << 3; + r->rate_bytes_ps = conf->rate; r->mult = 1; /* - * Calibrate mult, shift so that token counting is accurate - * for smallest packet size (64 bytes). Token (time in ns) is - * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps. It will - * work as long as the smallest packet transfer time can be - * accurately represented in nanosec. + * The deal here is to replace a divide by a reciprocal one + * in fast path (a reciprocal divide is a multiply and a shift) + * + * Normal formula would be : + * time_in_ns = (NSEC_PER_SEC * len) / rate_bps + * + * We compute mult/shift to use instead : + * time_in_ns = (len * mult) >> shift; + * + * We try to get the highest possible mult value for accuracy, + * but have to make sure no overflows will ever happen. */ - if (r->rate_bps > 0) { - /* - * Higher shift gives better accuracy. Find the largest - * shift such that mult fits in 32 bits. - */ - for (shift = 0; shift < 16; shift++) { - r->shift = shift; - factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); - mult = div64_u64(factor, r->rate_bps); - if (mult > UINT_MAX) + if (r->rate_bytes_ps > 0) { + u64 factor = NSEC_PER_SEC; + + for (;;) { + r->mult = div64_u64(factor, r->rate_bytes_ps); + if (r->mult & (1U << 31) || factor & (1ULL << 63)) break; + factor <<= 1; + r->shift++; } - - r->shift = shift - 1; - factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); - r->mult = div64_u64(factor, r->rate_bps); } } EXPORT_SYMBOL(psched_ratecfg_precompute); -- GitLab From 64153ce0a7b61b2a5cacb01805cbf670142339e9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Jun 2013 14:53:16 -0700 Subject: [PATCH 0889/2900] net_sched: htb: do not setup default rate estimators With a thousand htb classes, est_timer() spends ~5 million cpu cycles and throws out cpu cache, because each htb class has a default rate estimator (est 4sec 16sec). Most users do not use default rate estimators, so switch htb to not setup ones. Add a module parameter (htb_rate_est) so that users relying on this default rate estimator can revert the behavior. echo 1 >/sys/module/sch_htb/parameters/htb_rate_est Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 162fb800754c..1a3655a606c1 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -65,6 +65,10 @@ static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis f module_param (htb_hysteresis, int, 0640); MODULE_PARM_DESC(htb_hysteresis, "Hysteresis mode, less CPU load, less accurate"); +static int htb_rate_est = 0; /* htb classes have a default rate estimator */ +module_param(htb_rate_est, int, 0640); +MODULE_PARM_DESC(htb_rate_est, "setup a default rate estimator (4sec 16sec) for htb classes"); + /* used internaly to keep status of single class */ enum htb_cmode { HTB_CANT_SEND, /* class can't send and can't borrow */ @@ -1366,12 +1370,14 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, if (!cl) goto failure; - err = gen_new_estimator(&cl->bstats, &cl->rate_est, - qdisc_root_sleeping_lock(sch), - tca[TCA_RATE] ? : &est.nla); - if (err) { - kfree(cl); - goto failure; + if (htb_rate_est || tca[TCA_RATE]) { + err = gen_new_estimator(&cl->bstats, &cl->rate_est, + qdisc_root_sleeping_lock(sch), + tca[TCA_RATE] ? : &est.nla); + if (err) { + kfree(cl); + goto failure; + } } cl->refcnt = 1; -- GitLab From e9897071350bd9d94a56b5b6f79c85b1a98fc7e7 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 7 Jun 2013 08:48:57 -0700 Subject: [PATCH 0890/2900] igmp: hash a hash table to speedup ip_check_mc_rcu() After IP route cache removal, multicast applications using a lot of multicast addresses hit a O(N) behavior in ip_check_mc_rcu() Add a per in_device hash table to get faster lookup. This hash table is created only if the number of items in mc_list is above 4. Reported-by: Shawn Bohrer Signed-off-by: Eric Dumazet Tested-by: Shawn Bohrer Reviewed-by: Cong Wang Signed-off-by: David S. Miller --- include/linux/igmp.h | 1 + include/linux/inetdevice.h | 5 +++ net/ipv4/devinet.c | 1 + net/ipv4/igmp.c | 73 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 7f2bf1518480..e3362b5f13e8 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -84,6 +84,7 @@ struct ip_mc_list { struct ip_mc_list *next; struct ip_mc_list __rcu *next_rcu; }; + struct ip_mc_list __rcu *next_hash; struct timer_list timer; int users; atomic_t refcnt; diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index ea1e3b863890..b99cd23f3474 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -50,12 +50,17 @@ struct ipv4_devconf { DECLARE_BITMAP(state, IPV4_DEVCONF_MAX); }; +#define MC_HASH_SZ_LOG 9 + struct in_device { struct net_device *dev; atomic_t refcnt; int dead; struct in_ifaddr *ifa_list; /* IP ifaddr chain */ + struct ip_mc_list __rcu *mc_list; /* IP multicast filter chain */ + struct ip_mc_list __rcu * __rcu *mc_hash; + int mc_count; /* Number of installed mcasts */ spinlock_t mc_tomb_lock; struct ip_mc_list *mc_tomb; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index b047e2d8a614..3469506c106d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -215,6 +215,7 @@ void in_dev_finish_destroy(struct in_device *idev) WARN_ON(idev->ifa_list); WARN_ON(idev->mc_list); + kfree(rcu_dereference_protected(idev->mc_hash, 1)); #ifdef NET_REFCNT_DEBUG pr_debug("%s: %p=%s\n", __func__, idev, dev ? dev->name : "NIL"); #endif diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 450f625361e4..f72011df9c59 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1217,6 +1217,57 @@ static void igmp_group_added(struct ip_mc_list *im) * Multicast list managers */ +static u32 ip_mc_hash(const struct ip_mc_list *im) +{ + return hash_32((u32)im->multiaddr, MC_HASH_SZ_LOG); +} + +static void ip_mc_hash_add(struct in_device *in_dev, + struct ip_mc_list *im) +{ + struct ip_mc_list __rcu **mc_hash; + u32 hash; + + mc_hash = rtnl_dereference(in_dev->mc_hash); + if (mc_hash) { + hash = ip_mc_hash(im); + im->next_hash = rtnl_dereference(mc_hash[hash]); + rcu_assign_pointer(mc_hash[hash], im); + return; + } + + /* do not use a hash table for small number of items */ + if (in_dev->mc_count < 4) + return; + + mc_hash = kzalloc(sizeof(struct ip_mc_list *) << MC_HASH_SZ_LOG, + GFP_KERNEL); + if (!mc_hash) + return; + + for_each_pmc_rtnl(in_dev, im) { + hash = ip_mc_hash(im); + im->next_hash = rtnl_dereference(mc_hash[hash]); + RCU_INIT_POINTER(mc_hash[hash], im); + } + + rcu_assign_pointer(in_dev->mc_hash, mc_hash); +} + +static void ip_mc_hash_remove(struct in_device *in_dev, + struct ip_mc_list *im) +{ + struct ip_mc_list __rcu **mc_hash = rtnl_dereference(in_dev->mc_hash); + struct ip_mc_list *aux; + + if (!mc_hash) + return; + mc_hash += ip_mc_hash(im); + while ((aux = rtnl_dereference(*mc_hash)) != im) + mc_hash = &aux->next_hash; + *mc_hash = im->next_hash; +} + /* * A socket has joined a multicast group on device dev. @@ -1258,6 +1309,8 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) in_dev->mc_count++; rcu_assign_pointer(in_dev->mc_list, im); + ip_mc_hash_add(in_dev, im); + #ifdef CONFIG_IP_MULTICAST igmpv3_del_delrec(in_dev, im->multiaddr); #endif @@ -1314,6 +1367,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) ip = &i->next_rcu) { if (i->multiaddr == addr) { if (--i->users == 0) { + ip_mc_hash_remove(in_dev, i); *ip = i->next_rcu; in_dev->mc_count--; igmp_group_dropped(i); @@ -2321,12 +2375,25 @@ void ip_mc_drop_socket(struct sock *sk) int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto) { struct ip_mc_list *im; + struct ip_mc_list __rcu **mc_hash; struct ip_sf_list *psf; int rv = 0; - for_each_pmc_rcu(in_dev, im) { - if (im->multiaddr == mc_addr) - break; + mc_hash = rcu_dereference(in_dev->mc_hash); + if (mc_hash) { + u32 hash = hash_32((u32)mc_addr, MC_HASH_SZ_LOG); + + for (im = rcu_dereference(mc_hash[hash]); + im != NULL; + im = rcu_dereference(im->next_hash)) { + if (im->multiaddr == mc_addr) + break; + } + } else { + for_each_pmc_rcu(in_dev, im) { + if (im->multiaddr == mc_addr) + break; + } } if (im && proto == IPPROTO_IGMP) { rv = 1; -- GitLab From 946d3bd7231be3b6202759ea0bea59989ae28c4a Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Fri, 7 Jun 2013 12:34:43 -0500 Subject: [PATCH 0891/2900] igmp: remove unnecessary in_device member zeroing ip_mc_init_dev() is passed a freshly kzalloc'd in_device so it is unnecessary to explicitly zero out the members. Signed-off-by: Shawn Bohrer Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index f72011df9c59..a09190ddffba 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1435,13 +1435,9 @@ void ip_mc_init_dev(struct in_device *in_dev) { ASSERT_RTNL(); - in_dev->mc_tomb = NULL; #ifdef CONFIG_IP_MULTICAST - in_dev->mr_gq_running = 0; setup_timer(&in_dev->mr_gq_timer, igmp_gq_timer_expire, (unsigned long)in_dev); - in_dev->mr_ifc_count = 0; - in_dev->mc_count = 0; setup_timer(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, (unsigned long)in_dev); in_dev->mr_qrv = IGMP_Unsolicited_Report_Count; -- GitLab From da5bab079f9b7d90ba234965a14914ace55e45e9 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sat, 8 Jun 2013 12:56:03 +0200 Subject: [PATCH 0892/2900] net: udp4: move GSO functions to udp_offload Similarly to TCP offloading and UDPv6 offloading, move all related UDPv4 functions to udp_offload.c to make things more explicit. Also, by this, we can make those functions static. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/net/udp.h | 7 +-- net/ipv4/Makefile | 2 +- net/ipv4/af_inet.c | 9 +--- net/ipv4/udp.c | 75 +------------------------------ net/ipv4/udp_offload.c | 100 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 85 deletions(-) create mode 100644 net/ipv4/udp_offload.c diff --git a/include/net/udp.h b/include/net/udp.h index 065f379c6503..b30a71a51839 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -187,6 +187,8 @@ extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int udp_disconnect(struct sock *sk, int flags); extern unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait); +extern struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, + netdev_features_t features); extern int udp_lib_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, @@ -262,11 +264,10 @@ extern int udp4_proc_init(void); extern void udp4_proc_exit(void); #endif +extern int udpv4_offload_init(void); + extern void udp_init(void); -extern int udp4_ufo_send_check(struct sk_buff *skb); -extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, - netdev_features_t features); extern void udp_encap_enable(void); #if IS_ENABLED(CONFIG_IPV6) extern void udpv6_encap_enable(void); diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 4d3e138c564f..7fcf8101d85f 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -9,7 +9,7 @@ obj-y := route.o inetpeer.o protocol.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \ tcp_offload.o datagram.o raw.o udp.o udplite.o \ - arp.o icmp.o devinet.o af_inet.o igmp.o \ + udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o \ inet_fragment.o ping.o diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7b514290efc6..5598b06d62db 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1566,13 +1566,6 @@ static const struct net_protocol udp_protocol = { .netns_ok = 1, }; -static const struct net_offload udp_offload = { - .callbacks = { - .gso_send_check = udp4_ufo_send_check, - .gso_segment = udp4_ufo_fragment, - }, -}; - static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, .err_handler = icmp_err, @@ -1672,7 +1665,7 @@ static int __init ipv4_offload_init(void) /* * Add offloads */ - if (inet_add_offload(&udp_offload, IPPROTO_UDP) < 0) + if (udpv4_offload_init() < 0) pr_crit("%s: Cannot add UDP protocol offload\n", __func__); if (tcpv4_offload_init() < 0) pr_crit("%s: Cannot add TCP protocol offload\n", __func__); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2955b25aee6d..f65bc32c0266 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2290,29 +2290,8 @@ void __init udp_init(void) sysctl_udp_wmem_min = SK_MEM_QUANTUM; } -int udp4_ufo_send_check(struct sk_buff *skb) -{ - if (!pskb_may_pull(skb, sizeof(struct udphdr))) - return -EINVAL; - - if (likely(!skb->encapsulation)) { - const struct iphdr *iph; - struct udphdr *uh; - - iph = ip_hdr(skb); - uh = udp_hdr(skb); - - uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, - IPPROTO_UDP, 0); - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct udphdr, check); - skb->ip_summed = CHECKSUM_PARTIAL; - } - return 0; -} - -static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, - netdev_features_t features) +struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, + netdev_features_t features) { struct sk_buff *segs = ERR_PTR(-EINVAL); int mac_len = skb->mac_len; @@ -2371,53 +2350,3 @@ static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, out: return segs; } - -struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, - netdev_features_t features) -{ - struct sk_buff *segs = ERR_PTR(-EINVAL); - unsigned int mss; - mss = skb_shinfo(skb)->gso_size; - if (unlikely(skb->len <= mss)) - goto out; - - if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { - /* Packet is from an untrusted source, reset gso_segs. */ - int type = skb_shinfo(skb)->gso_type; - - if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | - SKB_GSO_UDP_TUNNEL | - SKB_GSO_GRE | SKB_GSO_MPLS) || - !(type & (SKB_GSO_UDP)))) - goto out; - - skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); - - segs = NULL; - goto out; - } - - /* Fragment the skb. IP headers of the fragments are updated in - * inet_gso_segment() - */ - if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) - segs = skb_udp_tunnel_segment(skb, features); - else { - int offset; - __wsum csum; - - /* Do software UFO. Complete and fill in the UDP checksum as - * HW cannot do checksum of UDP packets sent as multiple - * IP fragments. - */ - offset = skb_checksum_start_offset(skb); - csum = skb_checksum(skb, offset, skb->len - offset, 0); - offset += skb->csum_offset; - *(__sum16 *)(skb->data + offset) = csum_fold(csum); - skb->ip_summed = CHECKSUM_NONE; - - segs = skb_segment(skb, features); - } -out: - return segs; -} diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c new file mode 100644 index 000000000000..f35eccaa855e --- /dev/null +++ b/net/ipv4/udp_offload.c @@ -0,0 +1,100 @@ +/* + * IPV4 GSO/GRO offload support + * Linux INET implementation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * UDPv4 GSO support + */ + +#include +#include +#include + +static int udp4_ufo_send_check(struct sk_buff *skb) +{ + if (!pskb_may_pull(skb, sizeof(struct udphdr))) + return -EINVAL; + + if (likely(!skb->encapsulation)) { + const struct iphdr *iph; + struct udphdr *uh; + + iph = ip_hdr(skb); + uh = udp_hdr(skb); + + uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, + IPPROTO_UDP, 0); + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); + skb->ip_summed = CHECKSUM_PARTIAL; + } + + return 0; +} + +static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, + netdev_features_t features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + unsigned int mss; + + mss = skb_shinfo(skb)->gso_size; + if (unlikely(skb->len <= mss)) + goto out; + + if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { + /* Packet is from an untrusted source, reset gso_segs. */ + int type = skb_shinfo(skb)->gso_type; + + if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | + SKB_GSO_UDP_TUNNEL | + SKB_GSO_GRE | SKB_GSO_MPLS) || + !(type & (SKB_GSO_UDP)))) + goto out; + + skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); + + segs = NULL; + goto out; + } + + /* Fragment the skb. IP headers of the fragments are updated in + * inet_gso_segment() + */ + if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) + segs = skb_udp_tunnel_segment(skb, features); + else { + int offset; + __wsum csum; + + /* Do software UFO. Complete and fill in the UDP checksum as + * HW cannot do checksum of UDP packets sent as multiple + * IP fragments. + */ + offset = skb_checksum_start_offset(skb); + csum = skb_checksum(skb, offset, skb->len - offset, 0); + offset += skb->csum_offset; + *(__sum16 *)(skb->data + offset) = csum_fold(csum); + skb->ip_summed = CHECKSUM_NONE; + + segs = skb_segment(skb, features); + } +out: + return segs; +} + +static const struct net_offload udpv4_offload = { + .callbacks = { + .gso_send_check = udp4_ufo_send_check, + .gso_segment = udp4_ufo_fragment, + }, +}; + +int __init udpv4_offload_init(void) +{ + return inet_add_offload(&udpv4_offload, IPPROTO_UDP); +} -- GitLab From 7a6e288d2745611bef5b614acf19644283765732 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sat, 8 Jun 2013 14:18:16 +0200 Subject: [PATCH 0893/2900] pktgen: ipv6: numa: consolidate skb allocation to pktgen_alloc_skb We currently allow for numa-node aware skb allocation only within the fill_packet_ipv4() path, but not in fill_packet_ipv6(). Consolidate that code to a common allocation helper to enable numa-node aware skb allocation for ipv6, and use it in both paths. This also makes both functions a bit more readable. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/core/pktgen.c | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 303412d8332b..9640972ec50e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2627,6 +2627,29 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, pgh->tv_usec = htonl(timestamp.tv_usec); } +static struct sk_buff *pktgen_alloc_skb(struct net_device *dev, + struct pktgen_dev *pkt_dev, + unsigned int extralen) +{ + struct sk_buff *skb = NULL; + unsigned int size = pkt_dev->cur_pkt_size + 64 + extralen + + pkt_dev->pkt_overhead; + + if (pkt_dev->flags & F_NODE) { + int node = pkt_dev->node >= 0 ? pkt_dev->node : numa_node_id(); + + skb = __alloc_skb(NET_SKB_PAD + size, GFP_NOWAIT, 0, node); + if (likely(skb)) { + skb_reserve(skb, NET_SKB_PAD); + skb->dev = dev; + } + } else { + skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); + } + + return skb; +} + static struct sk_buff *fill_packet_ipv4(struct net_device *odev, struct pktgen_dev *pkt_dev) { @@ -2657,32 +2680,13 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, datalen = (odev->hard_header_len + 16) & ~0xf; - if (pkt_dev->flags & F_NODE) { - int node; - - if (pkt_dev->node >= 0) - node = pkt_dev->node; - else - node = numa_node_id(); - - skb = __alloc_skb(NET_SKB_PAD + pkt_dev->cur_pkt_size + 64 - + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT, 0, node); - if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD); - skb->dev = odev; - } - } - else - skb = __netdev_alloc_skb(odev, - pkt_dev->cur_pkt_size + 64 - + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); - + skb = pktgen_alloc_skb(odev, pkt_dev, datalen); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } - prefetchw(skb->data); + prefetchw(skb->data); skb_reserve(skb, datalen); /* Reserve for ethernet and IP header */ @@ -2786,15 +2790,13 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, mod_cur_headers(pkt_dev); queue_map = pkt_dev->cur_queue_map; - skb = __netdev_alloc_skb(odev, - pkt_dev->cur_pkt_size + 64 - + 16 + pkt_dev->pkt_overhead, GFP_NOWAIT); + skb = pktgen_alloc_skb(odev, pkt_dev, 16); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } - prefetchw(skb->data); + prefetchw(skb->data); skb_reserve(skb, 16); /* Reserve for ethernet and IP header */ -- GitLab From 3f8b96379a820318db37f7b6e81e6e459ad56efe Mon Sep 17 00:00:00 2001 From: Hong zhi guo Date: Sun, 9 Jun 2013 20:15:20 +0800 Subject: [PATCH 0894/2900] veth: remove redundant call of dev_alloc_name it's called in the following register_netdevice. No need to call it here. Tested with "ip link add type veth" and "ip link add xxx%d type veth". Signed-off-by: Hong Zhiguo Signed-off-by: David S. Miller --- drivers/net/veth.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 177f911f5946..da866523cf20 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -379,12 +379,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, else snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d"); - if (strchr(dev->name, '%')) { - err = dev_alloc_name(dev, dev->name); - if (err < 0) - goto err_alloc_name; - } - err = register_netdevice(dev); if (err < 0) goto err_register_dev; @@ -404,7 +398,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, err_register_dev: /* nothing to do */ -err_alloc_name: err_configure_peer: unregister_netdevice(peer); return err; -- GitLab From afd6eae13cc4229e25d59334cdc46d042b24a4a5 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 10 Jun 2013 00:16:52 +0400 Subject: [PATCH 0895/2900] 3c59x: consolidate error cleanup in vortex_init_one() The PCI driver's probe() method duplicates the error cleanup code each time it has to do error exit. Consolidate the error cleanup code in one place and use *goto* to jump to the right places. Signed-off-by: Sergei Shtylyov Acked-by: Steffen Klassert Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c59x.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 30e74211a755..ad5272b348f0 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -1012,10 +1012,8 @@ static int vortex_init_one(struct pci_dev *pdev, goto out; rc = pci_request_regions(pdev, DRV_NAME); - if (rc < 0) { - pci_disable_device(pdev); - goto out; - } + if (rc < 0) + goto out_disable; unit = vortex_cards_found; @@ -1032,23 +1030,24 @@ static int vortex_init_one(struct pci_dev *pdev, if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ ioaddr = pci_iomap(pdev, 0, 0); if (!ioaddr) { - pci_release_regions(pdev); - pci_disable_device(pdev); rc = -ENOMEM; - goto out; + goto out_release; } rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq, ent->driver_data, unit); - if (rc < 0) { - pci_iounmap(pdev, ioaddr); - pci_release_regions(pdev); - pci_disable_device(pdev); - goto out; - } + if (rc < 0) + goto out_iounmap; vortex_cards_found++; + goto out; +out_iounmap: + pci_iounmap(pdev, ioaddr); +out_release: + pci_release_regions(pdev); +out_disable: + pci_disable_device(pdev); out: return rc; } -- GitLab From 941e173a538c58f7f60e3f70ab0e35d51563405b Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 10 Jun 2013 17:05:05 +0530 Subject: [PATCH 0896/2900] net: fec: Convert to use devm_ioremap_resource Commit 75096579c3ac ("lib: devres: Introduce devm_ioremap_resource()") introduced devm_ioremap_resource() and deprecated the use of devm_request_and_ioremap(). Signed-off-by: Tushar Behera CC: netdev@vger.kernel.org CC: "David S. Miller" Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index fa4a68fc01cb..c540055e4f4f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1876,17 +1876,17 @@ fec_probe(struct platform_device *pdev) (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT)) fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG; - fep->hwp = devm_request_and_ioremap(&pdev->dev, r); + fep->hwp = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(fep->hwp)) { + ret = PTR_ERR(fep->hwp); + goto failed_ioremap; + } + fep->pdev = pdev; fep->dev_id = dev_id++; fep->bufdesc_ex = 0; - if (!fep->hwp) { - ret = -ENOMEM; - goto failed_ioremap; - } - platform_set_drvdata(pdev, ndev); ret = of_get_phy_mode(pdev->dev.of_node); -- GitLab From eed5d29d7818cc7a84e60123555cae154e5b4a73 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 10 Jun 2013 17:05:06 +0530 Subject: [PATCH 0897/2900] net: emaclite: Convert to use devm_ioremap_resource Commit 75096579c3ac ("lib: devres: Introduce devm_ioremap_resource()") introduced devm_ioremap_resource() and deprecated the use of devm_request_and_ioremap(). Signed-off-by: Tushar Behera CC: netdev@vger.kernel.org CC: "David S. Miller" CC: Michal Simek Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 1cd131bde680..fd4dbdae5331 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1159,9 +1159,11 @@ static int xemaclite_of_probe(struct platform_device *ofdev) ndev->irq = res->start; res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); - lp->base_addr = devm_request_and_ioremap(&ofdev->dev, res); - if (!lp->base_addr) + lp->base_addr = devm_ioremap_resource(&ofdev->dev, res); + if (IS_ERR(lp->base_addr)) { + rc = PTR_ERR(lp->base_addr); goto error; + } ndev->mem_start = res->start; ndev->mem_end = res->end; -- GitLab From 32766fff24a761079636bb96c389411d24a334c6 Mon Sep 17 00:00:00 2001 From: Tushar Behera Date: Mon, 10 Jun 2013 17:05:07 +0530 Subject: [PATCH 0898/2900] net: can: Convert to use devm_ioremap_resource Commit 75096579c3ac ("lib: devres: Introduce devm_ioremap_resource()") introduced devm_ioremap_resource() and deprecated the use of devm_request_and_ioremap(). Signed-off-by: Tushar Behera CC: netdev@vger.kernel.org CC: linux-can@vger.kernel.org CC: Marc Kleine-Budde CC: Wolfgang Grandegger Acked-by: Marc Kleine-Budde Signed-off-by: David S. Miller --- drivers/net/can/c_can/c_can_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 6b6130b8bdc4..b918c7329426 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -201,8 +201,8 @@ static int c_can_plat_probe(struct platform_device *pdev) priv->instance = pdev->id; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->raminit_ctrlreg = devm_request_and_ioremap(&pdev->dev, res); - if (!priv->raminit_ctrlreg || priv->instance < 0) + priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) dev_info(&pdev->dev, "control memory is not used for raminit\n"); else priv->raminit = c_can_hw_raminit; -- GitLab From dffebd2c5cd528a136b276a2a75c56222312d7a4 Mon Sep 17 00:00:00 2001 From: Narendra K Date: Mon, 10 Jun 2013 19:34:03 +0530 Subject: [PATCH 0899/2900] doc:networking: Update comment for dev_id field in netdevice.h This patch updates the comment for 'dev_id' field in 'include/linux/netdevice.h' to reflect the intended usage of 'dev_id'. References: http://marc.info/?l=linux-netdev&m=136992115300526&w=2 References: http://marc.info/?l=linux-netdev&m=137062569014612&w=2 Signed-off-by: Narendra K Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2ecb96d9a1e5..e5d65573b4d6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1174,8 +1174,10 @@ struct net_device { unsigned char addr_assign_type; /* hw address assignment type */ unsigned char addr_len; /* hardware address length */ unsigned char neigh_priv_len; - unsigned short dev_id; /* for shared network cards */ - + unsigned short dev_id; /* Used to differentiate devices + * that share the same link + * layer address + */ spinlock_t addr_list_lock; struct netdev_hw_addr_list uc; /* Unicast mac addresses */ struct netdev_hw_addr_list mc; /* Multicast mac addresses */ -- GitLab From 6c31ff366c1116823e77019bae3e92e9d77a49f4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 10 Jun 2013 17:42:23 +0200 Subject: [PATCH 0900/2900] team: remove synchronize_rcu() called during queue override change This patch removes synchronize_rcu() from function __team_queue_override_port_del(). That can be done because it is ok to do list_del_rcu() and list_add_tail_rcu() on the same list_head member without calling synchronize_rcu() in between. A bit of refactoring needed to be done because INIT_LIST_HEAD needed to be removed (to not kill the forward pointer) as well. Signed-off-by: Jiri Pirko Acked-by: Flavio Leitner Signed-off-by: David S. Miller --- drivers/net/team/team.c | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 04e9adb748c5..9cbe09df7765 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -725,9 +725,9 @@ static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb) static void __team_queue_override_port_del(struct team *team, struct team_port *port) { + if (!port->queue_id) + return; list_del_rcu(&port->qom_list); - synchronize_rcu(); - INIT_LIST_HEAD(&port->qom_list); } static bool team_queue_override_port_has_gt_prio_than(struct team_port *port, @@ -749,9 +749,8 @@ static void __team_queue_override_port_add(struct team *team, struct list_head *qom_list; struct list_head *node; - if (!port->queue_id || !team_port_enabled(port)) + if (!port->queue_id) return; - qom_list = __team_get_qom_list(team, port->queue_id); node = qom_list; list_for_each_entry(cur, qom_list, qom_list) { @@ -768,7 +767,7 @@ static void __team_queue_override_enabled_check(struct team *team) bool enabled = false; list_for_each_entry(port, &team->port_list, list) { - if (!list_empty(&port->qom_list)) { + if (port->queue_id) { enabled = true; break; } @@ -780,14 +779,44 @@ static void __team_queue_override_enabled_check(struct team *team) team->queue_override_enabled = enabled; } -static void team_queue_override_port_refresh(struct team *team, - struct team_port *port) +static void team_queue_override_port_prio_changed(struct team *team, + struct team_port *port) { + if (!port->queue_id || team_port_enabled(port)) + return; __team_queue_override_port_del(team, port); __team_queue_override_port_add(team, port); __team_queue_override_enabled_check(team); } +static void team_queue_override_port_change_queue_id(struct team *team, + struct team_port *port, + u16 new_queue_id) +{ + if (team_port_enabled(port)) { + __team_queue_override_port_del(team, port); + port->queue_id = new_queue_id; + __team_queue_override_port_add(team, port); + __team_queue_override_enabled_check(team); + } else { + port->queue_id = new_queue_id; + } +} + +static void team_queue_override_port_add(struct team *team, + struct team_port *port) +{ + __team_queue_override_port_add(team, port); + __team_queue_override_enabled_check(team); +} + +static void team_queue_override_port_del(struct team *team, + struct team_port *port) +{ + __team_queue_override_port_del(team, port); + __team_queue_override_enabled_check(team); +} + /**************** * Port handling @@ -819,7 +848,7 @@ static void team_port_enable(struct team *team, hlist_add_head_rcu(&port->hlist, team_port_index_hash(team, port->index)); team_adjust_ops(team); - team_queue_override_port_refresh(team, port); + team_queue_override_port_add(team, port); if (team->ops.port_enabled) team->ops.port_enabled(team, port); } @@ -848,7 +877,7 @@ static void team_port_disable(struct team *team, hlist_del_rcu(&port->hlist); __reconstruct_port_hlist(team, port->index); port->index = -1; - team_queue_override_port_refresh(team, port); + team_queue_override_port_del(team, port); __team_adjust_ops(team, team->en_port_count - 1); /* * Wait until readers see adjusted ops. This ensures that @@ -1259,9 +1288,12 @@ static int team_priority_option_set(struct team *team, struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; + s32 priority = ctx->data.s32_val; - port->priority = ctx->data.s32_val; - team_queue_override_port_refresh(team, port); + if (port->priority == priority) + return 0; + port->priority = priority; + team_queue_override_port_prio_changed(team, port); return 0; } @@ -1278,17 +1310,16 @@ static int team_queue_id_option_set(struct team *team, struct team_gsetter_ctx *ctx) { struct team_port *port = ctx->info->port; + u16 new_queue_id = ctx->data.u32_val; - if (port->queue_id == ctx->data.u32_val) + if (port->queue_id == new_queue_id) return 0; - if (ctx->data.u32_val >= team->dev->real_num_tx_queues) + if (new_queue_id >= team->dev->real_num_tx_queues) return -EINVAL; - port->queue_id = ctx->data.u32_val; - team_queue_override_port_refresh(team, port); + team_queue_override_port_change_queue_id(team, port, new_queue_id); return 0; } - static const struct team_option team_options[] = { { .name = "mode", -- GitLab From d80b35beac78b52faad2359adf6a6b14e2725e51 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 10 Jun 2013 17:42:24 +0200 Subject: [PATCH 0901/2900] team: use kfree_rcu instead of synchronize_rcu in team_port_dev Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/team/team.c | 3 +-- include/linux/if_team.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 9cbe09df7765..488ed4f535e5 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1192,8 +1192,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev) team_port_set_orig_dev_addr(port); dev_set_mtu(port_dev, port->orig.mtu); - synchronize_rcu(); - kfree(port); + kfree_rcu(port, rcu); netdev_info(dev, "Port device %s removed\n", portname); __team_compute_features(team); diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 4474557904f6..705459524706 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -69,6 +69,7 @@ struct team_port { s32 priority; /* lower number ~ higher priority */ u16 queue_id; struct list_head qom_list; /* node in queue override mapping list */ + struct rcu_head rcu; long mode_priv[0]; }; -- GitLab From 735d381fa57c573935d35a24ea271ec99897ac63 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 10 Jun 2013 17:42:25 +0200 Subject: [PATCH 0902/2900] team: remove synchronize_rcu() called during port disable Check the unlikely case of team->en_port_count == 0 before modulo operation. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/team/team.c | 20 +++++--------------- drivers/net/team/team_mode_loadbalance.c | 3 +-- drivers/net/team/team_mode_roundrobin.c | 3 ++- include/linux/if_team.h | 10 ++++++++++ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 488ed4f535e5..e46fef38685b 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -525,31 +525,26 @@ static void team_set_no_mode(struct team *team) team->mode = &__team_no_mode; } -static void __team_adjust_ops(struct team *team, int en_port_count) +static void team_adjust_ops(struct team *team) { /* * To avoid checks in rx/tx skb paths, ensure here that non-null and * correct ops are always set. */ - if (!en_port_count || !team_is_mode_set(team) || + if (!team->en_port_count || !team_is_mode_set(team) || !team->mode->ops->transmit) team->ops.transmit = team_dummy_transmit; else team->ops.transmit = team->mode->ops->transmit; - if (!en_port_count || !team_is_mode_set(team) || + if (!team->en_port_count || !team_is_mode_set(team) || !team->mode->ops->receive) team->ops.receive = team_dummy_receive; else team->ops.receive = team->mode->ops->receive; } -static void team_adjust_ops(struct team *team) -{ - __team_adjust_ops(team, team->en_port_count); -} - /* * We can benefit from the fact that it's ensured no port is present * at the time of mode change. Therefore no packets are in fly so there's no @@ -877,14 +872,9 @@ static void team_port_disable(struct team *team, hlist_del_rcu(&port->hlist); __reconstruct_port_hlist(team, port->index); port->index = -1; - team_queue_override_port_del(team, port); - __team_adjust_ops(team, team->en_port_count - 1); - /* - * Wait until readers see adjusted ops. This ensures that - * readers never see team->en_port_count == 0 - */ - synchronize_rcu(); team->en_port_count--; + team_queue_override_port_del(team, port); + team_adjust_ops(team); } #define TEAM_VLAN_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | \ diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index cdc31b5ea15e..829a9cd2b4da 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -112,9 +112,8 @@ static struct team_port *lb_hash_select_tx_port(struct team *team, struct sk_buff *skb, unsigned char hash) { - int port_index; + int port_index = team_num_to_port_index(team, hash); - port_index = hash % team->en_port_count; return team_get_port_by_index_rcu(team, port_index); } diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c index d268e4de781b..90311c7375fb 100644 --- a/drivers/net/team/team_mode_roundrobin.c +++ b/drivers/net/team/team_mode_roundrobin.c @@ -30,7 +30,8 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) struct team_port *port; int port_index; - port_index = rr_priv(team)->sent_packets++ % team->en_port_count; + port_index = team_num_to_port_index(team, + rr_priv(team)->sent_packets++); port = team_get_port_by_index_rcu(team, port_index); port = team_get_first_port_txable_rcu(team, port); if (unlikely(!port)) diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 705459524706..b662045a81c0 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -229,6 +229,16 @@ static inline struct team_port *team_get_port_by_index(struct team *team, return port; return NULL; } + +static inline int team_num_to_port_index(struct team *team, int num) +{ + int en_port_count = ACCESS_ONCE(team->en_port_count); + + if (unlikely(!en_port_count)) + return 0; + return num % en_port_count; +} + static inline struct team_port *team_get_port_by_index_rcu(struct team *team, int port_index) { -- GitLab From 503b47eafc39cb28db7b694aa0bb9276adccb89c Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 10 Jun 2013 18:58:16 +0300 Subject: [PATCH 0903/2900] ipv4: remove is_data also from ip_options documentation. commit ef722495c8867aacc1db0675a6737e5cf1e72e07 ( [IPV4]: Remove unused ip_options->is_data) removed the unused is_data member from ip_options struct. This patch removes is_data also from the documentation of the ip_options struct. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/inet_sock.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 7235ae73a1e8..b21a7f06d6a4 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -32,7 +32,6 @@ * * @faddr - Saved first hop address * @nexthop - Saved nexthop address in LSRR and SSRR - * @is_data - Options in __data, rather than skb * @is_strictroute - Strict source route * @srr_is_hit - Packet destination addr was our one * @is_changed - IP checksum more not valid -- GitLab From 6602041b8343fcdb6433cc72ca6cb6c2e189da6d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 10 Jun 2013 18:03:17 +0100 Subject: [PATCH 0904/2900] sfc: Store port number in private data, not net_device::dev_id We should not use net_device::dev_id to indicate the port number, as this affects the way the local part of IPv6 addresses is normally generated. This field was intended for use where multiple devices may share a single assigned MAC address and need to have different IPv6 addresses. Siena's two ports each have their own MAC addresses. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/net_driver.h | 3 ++- drivers/net/ethernet/sfc/siena.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 39d6bd77f015..9a2914cfd345 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -784,6 +784,7 @@ struct efx_nic { char name[IFNAMSIZ]; struct pci_dev *pci_dev; + unsigned int port_num; const struct efx_nic_type *type; int legacy_irq; bool legacy_irq_enabled; @@ -916,7 +917,7 @@ static inline int efx_dev_registered(struct efx_nic *efx) static inline unsigned int efx_port_num(struct efx_nic *efx) { - return efx->net_dev->dev_id; + return efx->port_num; } /** diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 51669244d154..8c91775e3c5f 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -304,7 +304,7 @@ static int siena_probe_nic(struct efx_nic *efx) } efx_reado(efx, ®, FR_AZ_CS_DEBUG); - efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; + efx->port_num = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; efx_mcdi_init(efx); -- GitLab From 5eaedf31319d5f80eaaee1eec8dd18c0b452f0d1 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 10 Jun 2013 20:19:48 +0300 Subject: [PATCH 0905/2900] gianfar: Add backwards compatible Single Queue mode polling Older Single Queue (SQ_SG_MODE) devices like TSEC (i.e. mpc83xx) don't feature the frame receive indication bits (RXF) in RSTAT. For these and for the rest of the SQ_SG_MODE devices, provide the appropiate polling routine that handles a single pair of Rx/Tx BD rings, removing the overhead incurred by the multiple queues/ multiple interrupt group devices (veTSEC/ eTSEC2.0 devices). So this is primarily a fix for the TSEC devices. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 51 +++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 14f06947e70d..8d2db7b808b7 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -128,6 +128,7 @@ static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); static void gfar_configure_serdes(struct net_device *dev); static int gfar_poll(struct napi_struct *napi, int budget); +static int gfar_poll_sq(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void gfar_netpoll(struct net_device *dev); #endif @@ -1038,9 +1039,13 @@ static int gfar_probe(struct platform_device *ofdev) dev->ethtool_ops = &gfar_ethtool_ops; /* Register for napi ...We are registering NAPI for each grp */ - for (i = 0; i < priv->num_grps; i++) - netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, + if (priv->mode == SQ_SG_MODE) + netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq, GFAR_DEV_WEIGHT); + else + for (i = 0; i < priv->num_grps; i++) + netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll, + GFAR_DEV_WEIGHT); if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) { dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | @@ -2823,6 +2828,48 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) return howmany; } +static int gfar_poll_sq(struct napi_struct *napi, int budget) +{ + struct gfar_priv_grp *gfargrp = + container_of(napi, struct gfar_priv_grp, napi); + struct gfar __iomem *regs = gfargrp->regs; + struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0]; + struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0]; + int work_done = 0; + + /* Clear IEVENT, so interrupts aren't called again + * because of the packets that have already arrived + */ + gfar_write(®s->ievent, IEVENT_RTX_MASK); + + /* run Tx cleanup to completion */ + if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) + gfar_clean_tx_ring(tx_queue); + + work_done = gfar_clean_rx_ring(rx_queue, budget); + + if (work_done < budget) { + napi_complete(napi); + /* Clear the halt bit in RSTAT */ + gfar_write(®s->rstat, gfargrp->rstat); + + gfar_write(®s->imask, IMASK_DEFAULT); + + /* If we are coalescing interrupts, update the timer + * Otherwise, clear it + */ + gfar_write(®s->txic, 0); + if (likely(tx_queue->txcoalescing)) + gfar_write(®s->txic, tx_queue->txic); + + gfar_write(®s->rxic, 0); + if (unlikely(rx_queue->rxcoalescing)) + gfar_write(®s->rxic, rx_queue->rxic); + } + + return work_done; +} + static int gfar_poll(struct napi_struct *napi, int budget) { struct gfar_priv_grp *gfargrp = -- GitLab From 8796f9c5656dedd186eda88c07db6a58d1985938 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 7 Jun 2013 18:26:42 +0200 Subject: [PATCH 0906/2900] pwm: atmel-tcb: prepare clk before calling enable Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to avoid common clk framework warnings. Signed-off-by: Boris BREZILLON Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel-tcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 0a7b6582edb1..09be626a61a0 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -76,7 +76,7 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip, if (!tcbpwm) return -ENOMEM; - ret = clk_enable(tc->clk[group]); + ret = clk_prepare_enable(tc->clk[group]); if (ret) { devm_kfree(chip->dev, tcbpwm); return ret; @@ -124,7 +124,7 @@ static void atmel_tcb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) struct atmel_tcb_pwm_device *tcbpwm = pwm_get_chip_data(pwm); struct atmel_tc *tc = tcbpwmc->tc; - clk_disable(tc->clk[pwm->hwpwm / 2]); + clk_disable_unprepare(tc->clk[pwm->hwpwm / 2]); tcbpwmc->pwms[pwm->hwpwm] = NULL; devm_kfree(chip->dev, tcbpwm); } -- GitLab From 88b613e6234def882b0b601bf831bf89af2e27f0 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Thu, 30 May 2013 09:50:12 +0200 Subject: [PATCH 0907/2900] pwm: add pca9685 driver Add pwm driver for the NXP pca9685 16 channel pwm-led controller. The driver is really barebones at this stage. E.g. the OE' pin and therefore the corresponding registers are not supported. The driver was tested on a HW where this pin is tied to GND. Signed-off-by: Steffen Trumtrar [thierry.reding@gmail.com: style and whitespace cleanups] Signed-off-by: Thierry Reding --- .../bindings/pwm/nxp,pca9685-pwm.txt | 27 ++ drivers/pwm/Kconfig | 9 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-pca9685.c | 298 ++++++++++++++++++ 4 files changed, 335 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt create mode 100644 drivers/pwm/pwm-pca9685.c diff --git a/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt b/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt new file mode 100644 index 000000000000..1e3dfe7a4894 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/nxp,pca9685-pwm.txt @@ -0,0 +1,27 @@ +NXP PCA9685 16-channel 12-bit PWM LED controller +================================================ + +Required properties: + - compatible: "nxp,pca9685-pwm" + - #pwm-cells: should be 2. The first cell specifies the per-chip index + of the PWM to use and the second cell is the period in nanoseconds. + The index 16 is the ALLCALL channel, that sets all PWM channels at the same + time. + +Optional properties: + - invert (bool): boolean to enable inverted logic + - open-drain (bool): boolean to configure outputs with open-drain structure; + if omitted use totem-pole structure + +Example: + +For LEDs that are directly connected to the PCA, the following setting is +applicable: + +pca: pca@41 { + compatible = "nxp,pca9685-pwm"; + #pwm-cells = <2>; + reg = <0x41>; + invert; + open-drain; +}; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 115b64453493..d3fe3205d296 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -97,6 +97,15 @@ config PWM_MXS To compile this driver as a module, choose M here: the module will be called pwm-mxs. +config PWM_PCA9685 + tristate "NXP PCA9685 PWM driver" + depends on OF && REGMAP_I2C + help + Generic PWM framework driver for NXP PCA9685 LED controller. + + To compile this driver as a module, choose M here: the module + will be called pwm-pca9685. + config PWM_PUV3 tristate "PKUnity NetBook-0916 PWM support" depends on ARCH_PUV3 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 94ba21e24bd6..b3afc0a1800b 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_IMX) += pwm-imx.o obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o obj-$(CONFIG_PWM_MXS) += pwm-mxs.o +obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o obj-$(CONFIG_PWM_PXA) += pwm-pxa.o obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c new file mode 100644 index 000000000000..2afc9043550a --- /dev/null +++ b/drivers/pwm/pwm-pca9685.c @@ -0,0 +1,298 @@ +/* + * Driver for PCA9685 16-channel 12-bit PWM LED controller + * + * Copyright (C) 2013 Steffen Trumtrar + * + * based on the pwm-twl-led.c driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#define PCA9685_MODE1 0x00 +#define PCA9685_MODE2 0x01 +#define PCA9685_SUBADDR1 0x02 +#define PCA9685_SUBADDR2 0x03 +#define PCA9685_SUBADDR3 0x04 +#define PCA9685_ALLCALLADDR 0x05 +#define PCA9685_LEDX_ON_L 0x06 +#define PCA9685_LEDX_ON_H 0x07 +#define PCA9685_LEDX_OFF_L 0x08 +#define PCA9685_LEDX_OFF_H 0x09 + +#define PCA9685_ALL_LED_ON_L 0xFA +#define PCA9685_ALL_LED_ON_H 0xFB +#define PCA9685_ALL_LED_OFF_L 0xFC +#define PCA9685_ALL_LED_OFF_H 0xFD +#define PCA9685_PRESCALE 0xFE + +#define PCA9685_NUMREGS 0xFF +#define PCA9685_MAXCHAN 0x10 + +#define LED_FULL (1 << 4) +#define MODE1_SLEEP (1 << 4) +#define MODE2_INVRT (1 << 4) +#define MODE2_OUTDRV (1 << 2) + +#define LED_N_ON_H(N) (PCA9685_LEDX_ON_H + (4 * (N))) +#define LED_N_ON_L(N) (PCA9685_LEDX_ON_L + (4 * (N))) +#define LED_N_OFF_H(N) (PCA9685_LEDX_OFF_H + (4 * (N))) +#define LED_N_OFF_L(N) (PCA9685_LEDX_OFF_L + (4 * (N))) + +struct pca9685 { + struct pwm_chip chip; + struct regmap *regmap; + int active_cnt; +}; + +static inline struct pca9685 *to_pca(struct pwm_chip *chip) +{ + return container_of(chip, struct pca9685, chip); +} + +static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct pca9685 *pca = to_pca(chip); + unsigned long long duty; + unsigned int reg; + + if (duty_ns < 1) { + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_H; + else + reg = LED_N_OFF_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, LED_FULL); + + return 0; + } + + if (duty_ns == period_ns) { + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_ON_H; + else + reg = LED_N_ON_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, LED_FULL); + + return 0; + } + + duty = 4096 * (unsigned long long)duty_ns; + duty = DIV_ROUND_UP_ULL(duty, period_ns); + + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_L; + else + reg = LED_N_OFF_L(pwm->hwpwm); + + regmap_write(pca->regmap, reg, (int)duty & 0xff); + + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_H; + else + reg = LED_N_OFF_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, ((int)duty >> 8) & 0xf); + + return 0; +} + +static int pca9685_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pca9685 *pca = to_pca(chip); + unsigned int reg; + + /* + * The PWM subsystem does not support a pre-delay. + * So, set the ON-timeout to 0 + */ + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_ON_L; + else + reg = LED_N_ON_L(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0); + + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_ON_H; + else + reg = LED_N_ON_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0); + + /* + * Clear the full-off bit. + * It has precedence over the others and must be off. + */ + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_H; + else + reg = LED_N_OFF_H(pwm->hwpwm); + + regmap_update_bits(pca->regmap, reg, LED_FULL, 0x0); + + return 0; +} + +static void pca9685_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pca9685 *pca = to_pca(chip); + unsigned int reg; + + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_H; + else + reg = LED_N_OFF_H(pwm->hwpwm); + + regmap_write(pca->regmap, reg, LED_FULL); + + /* Clear the LED_OFF counter. */ + if (pwm->hwpwm >= PCA9685_MAXCHAN) + reg = PCA9685_ALL_LED_OFF_L; + else + reg = LED_N_OFF_L(pwm->hwpwm); + + regmap_write(pca->regmap, reg, 0x0); +} + +static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pca9685 *pca = to_pca(chip); + + if (pca->active_cnt++ == 0) + return regmap_update_bits(pca->regmap, PCA9685_MODE1, + MODE1_SLEEP, 0x0); + + return 0; +} + +static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pca9685 *pca = to_pca(chip); + + if (--pca->active_cnt == 0) + regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, + 0x1); +} + +static const struct pwm_ops pca9685_pwm_ops = { + .enable = pca9685_pwm_enable, + .disable = pca9685_pwm_disable, + .config = pca9685_pwm_config, + .request = pca9685_pwm_request, + .free = pca9685_pwm_free, +}; + +static struct regmap_config pca9685_regmap_i2c_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = PCA9685_NUMREGS, + .cache_type = REGCACHE_NONE, +}; + +static int pca9685_pwm_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *np = client->dev.of_node; + struct pca9685 *pca; + int ret; + int mode2; + + pca = devm_kzalloc(&client->dev, sizeof(*pca), GFP_KERNEL); + if (!pca) + return -ENOMEM; + + pca->regmap = devm_regmap_init_i2c(client, &pca9685_regmap_i2c_config); + if (IS_ERR(pca->regmap)) { + ret = PTR_ERR(pca->regmap); + dev_err(&client->dev, "Failed to initialize register map: %d\n", + ret); + return ret; + } + + i2c_set_clientdata(client, pca); + + regmap_read(pca->regmap, PCA9685_MODE2, &mode2); + + if (of_property_read_bool(np, "invert")) + mode2 |= MODE2_INVRT; + else + mode2 &= ~MODE2_INVRT; + + if (of_property_read_bool(np, "open-drain")) + mode2 &= ~MODE2_OUTDRV; + else + mode2 |= MODE2_OUTDRV; + + regmap_write(pca->regmap, PCA9685_MODE2, mode2); + + /* clear all "full off" bits */ + regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, 0); + regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, 0); + + pca->chip.ops = &pca9685_pwm_ops; + /* add an extra channel for ALL_LED */ + pca->chip.npwm = PCA9685_MAXCHAN + 1; + + pca->chip.dev = &client->dev; + pca->chip.base = -1; + pca->chip.can_sleep = true; + + return pwmchip_add(&pca->chip); +} + +static int pca9685_pwm_remove(struct i2c_client *client) +{ + struct pca9685 *pca = i2c_get_clientdata(client); + + regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, 0x1); + + return pwmchip_remove(&pca->chip); +} + +static const struct i2c_device_id pca9685_id[] = { + { "pca9685", 0 }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(i2c, pca9685_id); + +static const struct of_device_id pca9685_dt_ids[] = { + { .compatible = "nxp,pca9685-pwm", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pca9685_dt_ids); + +static struct i2c_driver pca9685_i2c_driver = { + .driver = { + .name = "pca9685-pwm", + .owner = THIS_MODULE, + .of_match_table = pca9685_dt_ids, + }, + .probe = pca9685_pwm_probe, + .remove = pca9685_pwm_remove, + .id_table = pca9685_id, +}; + +module_i2c_driver(pca9685_i2c_driver); + +MODULE_AUTHOR("Steffen Trumtrar "); +MODULE_DESCRIPTION("PWM driver for PCA9685"); +MODULE_LICENSE("GPL"); -- GitLab From 3dd0a909479c1d372341d749b4ff94cd638b57da Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 12 Jun 2013 13:18:29 +0200 Subject: [PATCH 0908/2900] pwm: Fill in missing .owner fields Some drivers don't set the .owner fields of the struct device_driver or struct pwm_ops, which causes the module usage count to become wrong. Signed-off-by: Thierry Reding --- drivers/pwm/pwm-atmel-tcb.c | 1 + drivers/pwm/pwm-bfin.c | 1 + drivers/pwm/pwm-imx.c | 1 + drivers/pwm/pwm-lpc32xx.c | 1 + drivers/pwm/pwm-mxs.c | 1 + drivers/pwm/pwm-pca9685.c | 1 + drivers/pwm/pwm-puv3.c | 1 + drivers/pwm/pwm-spear.c | 1 + drivers/pwm/pwm-tegra.c | 1 + 9 files changed, 9 insertions(+) diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 09be626a61a0..ba6ce01035e4 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -434,6 +434,7 @@ MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids); static struct platform_driver atmel_tcb_pwm_driver = { .driver = { .name = "atmel-tcb-pwm", + .owner = THIS_MODULE, .of_match_table = atmel_tcb_pwm_dt_ids, }, .probe = atmel_tcb_pwm_probe, diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c index 7631ef194de7..9985d830e554 100644 --- a/drivers/pwm/pwm-bfin.c +++ b/drivers/pwm/pwm-bfin.c @@ -149,6 +149,7 @@ static int bfin_pwm_remove(struct platform_device *pdev) static struct platform_driver bfin_pwm_driver = { .driver = { .name = "bfin-pwm", + .owner = THIS_MODULE, }, .probe = bfin_pwm_probe, .remove = bfin_pwm_remove, diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c index c938bae18812..2b7c4f88b461 100644 --- a/drivers/pwm/pwm-imx.c +++ b/drivers/pwm/pwm-imx.c @@ -295,6 +295,7 @@ static int imx_pwm_remove(struct platform_device *pdev) static struct platform_driver imx_pwm_driver = { .driver = { .name = "imx-pwm", + .owner = THIS_MODULE, .of_match_table = of_match_ptr(imx_pwm_dt_ids), }, .probe = imx_pwm_probe, diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c index 8272883c0d05..efb6c7bf8750 100644 --- a/drivers/pwm/pwm-lpc32xx.c +++ b/drivers/pwm/pwm-lpc32xx.c @@ -171,6 +171,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_pwm_dt_ids); static struct platform_driver lpc32xx_pwm_driver = { .driver = { .name = "lpc32xx-pwm", + .owner = THIS_MODULE, .of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids), }, .probe = lpc32xx_pwm_probe, diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c index 6489a4b75943..2c77b81da7c4 100644 --- a/drivers/pwm/pwm-mxs.c +++ b/drivers/pwm/pwm-mxs.c @@ -182,6 +182,7 @@ MODULE_DEVICE_TABLE(of, mxs_pwm_dt_ids); static struct platform_driver mxs_pwm_driver = { .driver = { .name = "mxs-pwm", + .owner = THIS_MODULE, .of_match_table = of_match_ptr(mxs_pwm_dt_ids), }, .probe = mxs_pwm_probe, diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 2afc9043550a..c9f9e65415f3 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -199,6 +199,7 @@ static const struct pwm_ops pca9685_pwm_ops = { .config = pca9685_pwm_config, .request = pca9685_pwm_request, .free = pca9685_pwm_free, + .owner = THIS_MODULE, }; static struct regmap_config pca9685_regmap_i2c_config = { diff --git a/drivers/pwm/pwm-puv3.c b/drivers/pwm/pwm-puv3.c index ed6007b27585..a9a28083f245 100644 --- a/drivers/pwm/pwm-puv3.c +++ b/drivers/pwm/pwm-puv3.c @@ -146,6 +146,7 @@ static int pwm_remove(struct platform_device *pdev) static struct platform_driver puv3_pwm_driver = { .driver = { .name = "PKUnity-v3-PWM", + .owner = THIS_MODULE, }, .probe = pwm_probe, .remove = pwm_remove, diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 6d99e2cbdc73..a54d21401431 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -259,6 +259,7 @@ MODULE_DEVICE_TABLE(of, spear_pwm_of_match); static struct platform_driver spear_pwm_driver = { .driver = { .name = "spear-pwm", + .owner = THIS_MODULE, .of_match_table = spear_pwm_of_match, }, .probe = spear_pwm_probe, diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index a5402933001f..74298c561c4e 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -239,6 +239,7 @@ MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); static struct platform_driver tegra_pwm_driver = { .driver = { .name = "tegra-pwm", + .owner = THIS_MODULE, .of_match_table = tegra_pwm_of_match, }, .probe = tegra_pwm_probe, -- GitLab From a9bce1b03c2199e66d36cda8aac675338bc074a7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:13:47 +0200 Subject: [PATCH 0909/2900] mfd: input: iio: ti_am335x_adc: use one structure for ti_tscadc_dev The mfd driver creates platform data for the child devices and it is the ti_tscadc_dev struct. This struct is copied for the two devices. The copy of the structure makes a common lock in this structure a little less usefull. Therefore the platform data is not a pointer to the structure and the same structure is used. While doing the change I noticed that the suspend/resume code assumes the wrong pointer for ti_tscadc_dev and this has been fixed as well. Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 5 +++-- drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++------- drivers/mfd/ti_am335x_tscadc.c | 8 ++++---- include/linux/mfd/ti_am335x_tscadc.h | 7 +++++++ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 5f9a7e7d3135..9db352e413e4 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -140,7 +140,7 @@ static int tiadc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct tiadc_device *adc_dev; - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); struct mfd_tscadc_board *pdata; int err; @@ -205,9 +205,10 @@ static int tiadc_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct tiadc_device *adc_dev = iio_priv(indio_dev); - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; + struct ti_tscadc_dev *tscadc_dev; unsigned int idle; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (!device_may_wakeup(tscadc_dev->dev)) { idle = tiadc_readl(adc_dev, REG_CTRL); idle &= ~(CNTRLREG_TSCSSENB); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 51e7b87827a4..16077d3d80ba 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -262,7 +262,7 @@ static int titsc_probe(struct platform_device *pdev) { struct titsc *ts_dev; struct input_dev *input_dev; - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); struct mfd_tscadc_board *pdata; int err; @@ -329,8 +329,8 @@ static int titsc_probe(struct platform_device *pdev) static int titsc_remove(struct platform_device *pdev) { - struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = platform_get_drvdata(pdev); + u32 steps; free_irq(ts_dev->irq, ts_dev); @@ -344,10 +344,11 @@ static int titsc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int titsc_suspend(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; unsigned int idle; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { idle = titsc_readl(ts_dev, REG_IRQENABLE); titsc_writel(ts_dev, REG_IRQENABLE, @@ -359,9 +360,10 @@ static int titsc_suspend(struct device *dev) static int titsc_resume(struct device *dev) { - struct ti_tscadc_dev *tscadc_dev = dev->platform_data; - struct titsc *ts_dev = tscadc_dev->tsc; + struct titsc *ts_dev = dev_get_drvdata(dev); + struct ti_tscadc_dev *tscadc_dev; + tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev)); if (device_may_wakeup(tscadc_dev->dev)) { titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e9f3fb510b44..772ea2adb539 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -176,14 +176,14 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSC Cell */ cell = &tscadc->cells[TSC_CELL]; cell->name = "tsc"; - cell->platform_data = tscadc; - cell->pdata_size = sizeof(*tscadc); + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); /* ADC Cell */ cell = &tscadc->cells[ADC_CELL]; cell->name = "tiadc"; - cell->platform_data = tscadc; - cell->pdata_size = sizeof(*tscadc); + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, TSCADC_CELLS, NULL, 0, NULL); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index c79ad5d2f271..8114e4e8b91b 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -149,4 +149,11 @@ struct ti_tscadc_dev { struct adc_device *adc; }; +static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) +{ + struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data; + + return *tscadc_dev; +} + #endif -- GitLab From abeccee40320245a2a6a006dc8466a703cbd1d5e Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:05 +0000 Subject: [PATCH 0910/2900] input: ti_am33x_tsc: Step enable bits made configurable Current code has hard coded value written to step enable bits. Now the bits are updated based on how many steps are needed to be configured got from platform data. The user needs to take care not to exceed the count more than 16. While using ADC and TSC one should take care to set this parameter correctly. Sebastian added the common lock and moved the code, that manipulates the steps, from into the mfd module. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 20 ++++++++++++++-- drivers/input/touchscreen/ti_am335x_tsc.c | 12 ++++++++-- drivers/mfd/ti_am335x_tscadc.c | 29 ++++++++++++++++++++++- include/linux/mfd/ti_am335x_tscadc.h | 8 +++++-- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 9db352e413e4..543b9c42ac5f 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -42,10 +42,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg, writel(val, adc->mfd_tscadc->tscadc_base + reg); } +static u32 get_adc_step_mask(struct tiadc_device *adc_dev) +{ + u32 step_en; + + step_en = ((1 << adc_dev->channels) - 1); + step_en <<= TOTAL_STEPS - adc_dev->channels + 1; + return step_en; +} + static void tiadc_step_config(struct tiadc_device *adc_dev) { unsigned int stepconfig; int i, channels = 0, steps; + u32 step_en; /* * There are 16 configurable steps and 8 analog input @@ -69,7 +79,8 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) STEPCONFIG_OPENDLY); channels++; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); } static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) @@ -127,7 +138,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, if (i == chan->channel) *val = readx1 & 0xfff; } - tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(adc_dev->mfd_tscadc); return IIO_VAL_INT; } @@ -191,10 +202,15 @@ static int tiadc_probe(struct platform_device *pdev) static int tiadc_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct tiadc_device *adc_dev = iio_priv(indio_dev); + u32 step_en; iio_device_unregister(indio_dev); tiadc_channels_remove(indio_dev); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en); + iio_device_free(indio_dev); return 0; diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 16077d3d80ba..23d6a4dacc88 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -57,6 +57,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; + unsigned int stepenable = 0; int i, total_steps; /* Configure the Step registers */ @@ -128,7 +129,9 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + /* The steps1 … end and bit 0 for TS_Charge */ + stepenable = (1 << (total_steps + 2)) - 1; + am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, @@ -250,7 +253,7 @@ static irqreturn_t titsc_irq(int irq, void *dev) titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); - titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + am335x_tsc_se_update(ts_dev->mfd_tscadc); return IRQ_HANDLED; } @@ -334,6 +337,11 @@ static int titsc_remove(struct platform_device *pdev) free_irq(ts_dev->irq, ts_dev); + /* total steps followed by the enable mask */ + steps = 2 * ts_dev->steps_to_configure + 2; + steps = (1 << steps) - 1; + am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); + input_unregister_device(ts_dev->input); platform_set_drvdata(pdev, NULL); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 772ea2adb539..90ccfc07e16b 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -48,6 +48,32 @@ static const struct regmap_config tscadc_regmap_config = { .val_bits = 32, }; +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc) +{ + tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_update); + +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache |= val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_set); + +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) +{ + spin_lock(&tsadc->reg_lock); + tsadc->reg_se_cache &= ~val; + spin_unlock(&tsadc->reg_lock); + + am335x_tsc_se_update(tsadc); +} +EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); + static void tscadc_idle_config(struct ti_tscadc_dev *config) { unsigned int idleconfig; @@ -129,6 +155,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) goto ret; } + spin_lock_init(&tscadc->reg_lock); pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -239,7 +266,7 @@ static int tscadc_resume(struct device *dev) CNTRLREG_STEPID | CNTRLREG_4WIRE; tscadc_writel(tscadc_dev, REG_CTRL, ctrl); tscadc_idle_config(tscadc_dev); - tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB); + am335x_tsc_se_update(tscadc_dev); restore = tscadc_readl(tscadc_dev, REG_CTRL); tscadc_writel(tscadc_dev, REG_CTRL, (restore | CNTRLREG_TSCSSENB)); diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8114e4e8b91b..4258627d076a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -46,8 +46,6 @@ /* Step Enable */ #define STEPENB_MASK (0x1FFFF << 0) #define STEPENB(val) ((val) << 0) -#define STPENB_STEPENB STEPENB(0x1FFFF) -#define STPENB_STEPENB_TC STEPENB(0x1FFF) /* IRQ enable */ #define IRQENB_HW_PEN BIT(0) @@ -141,6 +139,8 @@ struct ti_tscadc_dev { void __iomem *tscadc_base; int irq; struct mfd_cell cells[TSCADC_CELLS]; + u32 reg_se_cache; + spinlock_t reg_lock; /* tsc device */ struct titsc *tsc; @@ -156,4 +156,8 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p) return *tscadc_dev; } +void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc); +void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val); +void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val); + #endif -- GitLab From bb76dc09ddfc135c6c5e8eb7d3c583bfa8bdd439 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:06 +0000 Subject: [PATCH 0911/2900] input: ti_am33x_tsc: Order of TSC wires, made configurable The current driver expected touchscreen input wires(XP,XN,YP,YN) to be connected in a particular order. Making changes to accept this as platform data. Sebastian reworked the original patch and removed a lot of the not required pieces. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 102 ++++++++++++++++++---- include/linux/input/ti_am335x_tsc.h | 12 +++ include/linux/mfd/ti_am335x_tscadc.h | 3 - 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 23d6a4dacc88..2bdd66cd76a7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -33,6 +33,13 @@ #define SEQ_SETTLE 275 #define MAX_12BIT ((1 << 12) - 1) +static const int config_pins[] = { + STEPCONFIG_XPP, + STEPCONFIG_XNN, + STEPCONFIG_YPP, + STEPCONFIG_YNN, +}; + struct titsc { struct input_dev *input; struct ti_tscadc_dev *mfd_tscadc; @@ -41,6 +48,9 @@ struct titsc { unsigned int x_plate_resistance; bool pen_down; int steps_to_configure; + u32 config_inp[4]; + u32 bit_xp, bit_xn, bit_yp, bit_yn; + u32 inp_xp, inp_xn, inp_yp, inp_yn; }; static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) @@ -54,6 +64,58 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg, writel(val, tsc->mfd_tscadc->tscadc_base + reg); } +static int titsc_config_wires(struct titsc *ts_dev) +{ + u32 analog_line[4]; + u32 wire_order[4]; + int i, bit_cfg; + + for (i = 0; i < 4; i++) { + /* + * Get the order in which TSC wires are attached + * w.r.t. each of the analog input lines on the EVM. + */ + analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4; + wire_order[i] = ts_dev->config_inp[i] & 0x0F; + if (WARN_ON(analog_line[i] > 7)) + return -EINVAL; + if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins))) + return -EINVAL; + } + + for (i = 0; i < 4; i++) { + int an_line; + int wi_order; + + an_line = analog_line[i]; + wi_order = wire_order[i]; + bit_cfg = config_pins[wi_order]; + if (bit_cfg == 0) + return -EINVAL; + switch (wi_order) { + case 0: + ts_dev->bit_xp = bit_cfg; + ts_dev->inp_xp = an_line; + break; + + case 1: + ts_dev->bit_xn = bit_cfg; + ts_dev->inp_xn = an_line; + break; + + case 2: + ts_dev->bit_yp = bit_cfg; + ts_dev->inp_yp = an_line; + break; + case 3: + ts_dev->bit_yn = bit_cfg; + ts_dev->inp_yn = an_line; + break; + } + } + return 0; +} + static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; @@ -64,18 +126,18 @@ static void titsc_step_config(struct titsc *ts_dev) total_steps = 2 * ts_dev->steps_to_configure; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_XPP; + STEPCONFIG_AVG_16 | ts_dev->bit_xp; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; case 5: - config |= STEPCONFIG_YNN | - STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | - STEPCONFIG_YPP; + config |= ts_dev->bit_yn | + STEPCONFIG_INP_AN4 | ts_dev->bit_xn | + ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn; break; } @@ -86,18 +148,18 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YNN | + STEPCONFIG_AVG_16 | ts_dev->bit_yn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; switch (ts_dev->wires) { case 4: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; case 5: - config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | - STEPCONFIG_XNP | STEPCONFIG_YPN; + config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | + ts_dev->bit_xn | ts_dev->bit_yp; break; case 8: - config |= STEPCONFIG_YPP; + config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); break; } @@ -108,9 +170,9 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Charge step configuration */ - config = STEPCONFIG_XPP | STEPCONFIG_YNN | + config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | - STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; + STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp); titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); @@ -118,13 +180,14 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; /* Configure to calculate pressure */ config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_AVG_16 | STEPCONFIG_YPP | - STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; + STEPCONFIG_AVG_16 | ts_dev->bit_yp | + ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | + STEPCONFIG_INP(ts_dev->inp_xp); titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; + config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), STEPCONFIG_OPENDLY); @@ -292,6 +355,8 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->wires = pdata->tsc_init->wires; ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; + memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, + sizeof(pdata->tsc_init->wire_config)); err = request_irq(ts_dev->irq, titsc_irq, 0, pdev->dev.driver->name, ts_dev); @@ -301,6 +366,11 @@ static int titsc_probe(struct platform_device *pdev) } titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); + err = titsc_config_wires(ts_dev); + if (err) { + dev_err(&pdev->dev, "wrong i/p wire configuration\n"); + goto err_free_irq; + } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h index 49269a2aa329..6a66b4d1ac2c 100644 --- a/include/linux/input/ti_am335x_tsc.h +++ b/include/linux/input/ti_am335x_tsc.h @@ -12,12 +12,24 @@ * A step configured to read a single * co-ordinate value, can be applied * more number of times for better results. + * @wire_config: Different EVM's could have a different order + * for connecting wires on touchscreen. + * We need to provide an 8 bit number where in + * the 1st four bits represent the analog lines + * and the next 4 bits represent positive/ + * negative terminal on that input line. + * Notations to represent the input lines and + * terminals resoectively is as follows: + * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + * XP = 0, XN = 1, YP = 2, YN = 3. + * */ struct tsc_data { int wires; int x_plate_resistance; int steps_to_configure; + int wire_config[10]; }; #endif diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 4258627d076a..e36ae4184917 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -71,8 +71,6 @@ #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8) #define STEPCONFIG_INP_MASK (0xF << 19) #define STEPCONFIG_INP(val) ((val) << 19) -#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2) -#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3) #define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4) #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8) #define STEPCONFIG_FIFO1 BIT(26) @@ -94,7 +92,6 @@ #define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1) #define STEPCHARGE_INP_MASK (0xF << 19) #define STEPCHARGE_INP(val) ((val) << 19) -#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1) #define STEPCHARGE_RFM_MASK (3 << 23) #define STEPCHARGE_RFM(val) ((val) << 23) #define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1) -- GitLab From af9c2fe3740fe8dac05eede8805d9aaa45972cb6 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:07 +0000 Subject: [PATCH 0912/2900] input: ti_am33x_tsc: remove unwanted fifo flush When touchscreen and ADC are used together, this unwanted fifo flush leads to loss of ADC data. Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 2bdd66cd76a7..7b7de6035af7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -252,8 +252,6 @@ static irqreturn_t titsc_irq(int irq, void *dev) unsigned int x = 0, y = 0; unsigned int z1, z2, z; unsigned int fsm; - unsigned int fifo1count, fifo0count; - int i; status = titsc_readl(ts_dev, REG_IRQSTATUS); if (status & IRQENB_FIFO0THRES) { @@ -262,14 +260,6 @@ static irqreturn_t titsc_irq(int irq, void *dev) z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; - fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); - for (i = 0; i < fifo1count; i++) - titsc_readl(ts_dev, REG_FIFO1); - - fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); - for (i = 0; i < fifo0count; i++) - titsc_readl(ts_dev, REG_FIFO0); - if (ts_dev->pen_down && z1 != 0 && z2 != 0) { /* * Calculate pressure using formula -- GitLab From 0396310b0eba71595c1151ce7c8fde7a9f33f719 Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:10 +0000 Subject: [PATCH 0913/2900] input: ti_am33x_tsc: Add DT support This patch adds DT support to touch driver. It also provides a binding document which is used by the MFD and IIO part of the device. This patch also renames steps_to_configure to coordinate_readouts because the original name misleads the purpose of the variable. Signed-off-by: Pantelis Antoniou Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- .../bindings/input/touchscreen/ti-tsc-adc.txt | 44 ++++++++ drivers/input/touchscreen/ti_am335x_tsc.c | 105 ++++++++++++++---- drivers/mfd/ti_am335x_tscadc.c | 1 + 3 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt new file mode 100644 index 000000000000..491c97b78384 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt @@ -0,0 +1,44 @@ +* TI - TSC ADC (Touschscreen and analog digital converter) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Required properties: +- child "tsc" + ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen + support on the platform. + ti,x-plate-resistance: X plate resistance + ti,coordiante-readouts: The sequencer supports a total of 16 + programmable steps each step is used to + read a single coordinate. A single + readout is enough but multiple reads can + increase the quality. + A value of 5 means, 5 reads for X, 5 for + Y and 2 for Z (always). This utilises 12 + of the 16 software steps available. The + remaining 4 can be used by the ADC. + ti,wire-config: Different boards could have a different order for + connecting wires on touchscreen. We need to provide an + 8 bit number where in the 1st four bits represent the + analog lines and the next 4 bits represent positive/ + negative terminal on that input line. Notations to + represent the input lines and terminals resoectively + is as follows: + AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + XP = 0, XN = 1, YP = 2, YN = 3. +- child "adc" + ti,adc-channels: List of analog inputs available for ADC. + AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. + +Example: + tscadc: tscadc@44e0d000 { + compatible = "ti,am3359-tscadc"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordiante-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; + + adc { + ti,adc-channels = <4 5 6 7>; + }; + } diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 7b7de6035af7..449c0fbbe1d6 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include @@ -47,7 +49,7 @@ struct titsc { unsigned int wires; unsigned int x_plate_resistance; bool pen_down; - int steps_to_configure; + int coordinate_readouts; u32 config_inp[4]; u32 bit_xp, bit_xn, bit_yp, bit_yn; u32 inp_xp, inp_xn, inp_yp, inp_yn; @@ -123,7 +125,7 @@ static void titsc_step_config(struct titsc *ts_dev) int i, total_steps; /* Configure the Step registers */ - total_steps = 2 * ts_dev->steps_to_configure; + total_steps = 2 * ts_dev->coordinate_readouts; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_xp; @@ -141,7 +143,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = 1; i <= ts_dev->steps_to_configure; i++) { + for (i = 1; i <= ts_dev->coordinate_readouts; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -163,7 +165,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { + for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -218,7 +220,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev, read = titsc_readl(ts_dev, REG_FIFO0); channel = read & 0xf0000; channel = channel >> 0x10; - if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { + if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) { read &= 0xfff; diff = abs(read - prev_val_x); if (diff < prev_diff_x) { @@ -231,8 +233,8 @@ static void titsc_read_coordinates(struct titsc *ts_dev, read = titsc_readl(ts_dev, REG_FIFO1); channel = read & 0xf0000; channel = channel >> 0x10; - if ((channel >= ts_dev->steps_to_configure) && - (channel < (2 * ts_dev->steps_to_configure - 1))) { + if ((channel >= ts_dev->coordinate_readouts) && + (channel < (2 * ts_dev->coordinate_readouts - 1))) { read &= 0xfff; diff = abs(read - prev_val_y); if (diff < prev_diff_y) { @@ -310,6 +312,59 @@ static irqreturn_t titsc_irq(int irq, void *dev) return IRQ_HANDLED; } +static int titsc_parse_dt(struct platform_device *pdev, + struct titsc *ts_dev) +{ + struct device_node *node = pdev->dev.of_node; + int err; + + if (!node) + return -EINVAL; + + err = of_property_read_u32(node, "ti,wires", &ts_dev->wires); + if (err < 0) + return err; + switch (ts_dev->wires) { + case 4: + case 5: + case 8: + break; + default: + return -EINVAL; + } + + err = of_property_read_u32(node, "ti,x-plate-resistance", + &ts_dev->x_plate_resistance); + if (err < 0) + return err; + + err = of_property_read_u32(node, "ti,coordiante-readouts", + &ts_dev->coordinate_readouts); + if (err < 0) + return err; + + return of_property_read_u32_array(node, "ti,wire-config", + ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); +} + +static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev, + struct titsc *ts_dev) +{ + struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; + + if (!pdata) + return -EINVAL; + + ts_dev->wires = pdata->tsc_init->wires; + ts_dev->x_plate_resistance = + pdata->tsc_init->x_plate_resistance; + ts_dev->steps_to_configure = + pdata->tsc_init->steps_to_configure; + memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, + sizeof(pdata->tsc_init->wire_config)); + return 0; +} + /* * The functions for inserting/removing driver as a module. */ @@ -319,16 +374,8 @@ static int titsc_probe(struct platform_device *pdev) struct titsc *ts_dev; struct input_dev *input_dev; struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); - struct mfd_tscadc_board *pdata; int err; - pdata = tscadc_dev->dev->platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "Could not find platform data\n"); - return -EINVAL; - } - /* Allocate memory for device */ ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); input_dev = input_allocate_device(); @@ -342,11 +389,16 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->mfd_tscadc = tscadc_dev; ts_dev->input = input_dev; ts_dev->irq = tscadc_dev->irq; - ts_dev->wires = pdata->tsc_init->wires; - ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; - ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; - memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, - sizeof(pdata->tsc_init->wire_config)); + + if (tscadc_dev->dev->platform_data) + err = titsc_parse_pdata(tscadc_dev, ts_dev); + else + err = titsc_parse_dt(pdev, ts_dev); + + if (err) { + dev_err(&pdev->dev, "Could not find valid DT data.\n"); + goto err_free_mem; + } err = request_irq(ts_dev->irq, titsc_irq, 0, pdev->dev.driver->name, ts_dev); @@ -362,7 +414,7 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_irq; } titsc_step_config(ts_dev); - titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); + titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts); input_dev->name = "ti-tsc"; input_dev->dev.parent = &pdev->dev; @@ -398,7 +450,7 @@ static int titsc_remove(struct platform_device *pdev) free_irq(ts_dev->irq, ts_dev); /* total steps followed by the enable mask */ - steps = 2 * ts_dev->steps_to_configure + 2; + steps = 2 * ts_dev->coordinate_readouts + 2; steps = (1 << steps) - 1; am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps); @@ -439,7 +491,7 @@ static int titsc_resume(struct device *dev) } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, - ts_dev->steps_to_configure); + ts_dev->coordinate_readouts); return 0; } @@ -452,6 +504,12 @@ static const struct dev_pm_ops titsc_pm_ops = { #define TITSC_PM_OPS NULL #endif +static const struct of_device_id ti_tsc_dt_ids[] = { + { .compatible = "ti,am3359-tsc", }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); + static struct platform_driver ti_tsc_driver = { .probe = titsc_probe, .remove = titsc_remove, @@ -459,6 +517,7 @@ static struct platform_driver ti_tsc_driver = { .name = "tsc", .owner = THIS_MODULE, .pm = TITSC_PM_OPS, + .of_match_table = of_match_ptr(ti_tsc_dt_ids), }, }; module_platform_driver(ti_tsc_driver); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 90ccfc07e16b..f50976623a01 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -203,6 +203,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* TSC Cell */ cell = &tscadc->cells[TSC_CELL]; cell->name = "tsc"; + cell->of_compatible = "ti,am3359-tsc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- GitLab From b9194fdfa6e729b97ffc59ae00dc9d51c7ae314d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 17:39:13 +0200 Subject: [PATCH 0914/2900] input: ti_am33x_tsc: remove platform_data support This patch removes access to platform data mfd_tscadc_board because the platform is DT only. Acked-by: Dmitry Torokhov Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 25 +---------------------- 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 449c0fbbe1d6..a1db55d1a862 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -347,24 +346,6 @@ static int titsc_parse_dt(struct platform_device *pdev, ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp)); } -static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev, - struct titsc *ts_dev) -{ - struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; - - if (!pdata) - return -EINVAL; - - ts_dev->wires = pdata->tsc_init->wires; - ts_dev->x_plate_resistance = - pdata->tsc_init->x_plate_resistance; - ts_dev->steps_to_configure = - pdata->tsc_init->steps_to_configure; - memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config, - sizeof(pdata->tsc_init->wire_config)); - return 0; -} - /* * The functions for inserting/removing driver as a module. */ @@ -390,11 +371,7 @@ static int titsc_probe(struct platform_device *pdev) ts_dev->input = input_dev; ts_dev->irq = tscadc_dev->irq; - if (tscadc_dev->dev->platform_data) - err = titsc_parse_pdata(tscadc_dev, ts_dev); - else - err = titsc_parse_dt(pdev, ts_dev); - + err = titsc_parse_dt(pdev, ts_dev); if (err) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); goto err_free_mem; -- GitLab From 6f39ac4e20c6211c98e8d9da2d8c51100a77d1df Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:11 +0000 Subject: [PATCH 0915/2900] iio: ti_am335x_adc: Add DT support Add DT support for client ADC driver. Acked-by: Jonathan Cameron Signed-off-by: Patil, Rachna Signed-off-by: Pantelis Antoniou Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 29 ++++++++++++++++++++++++----- drivers/mfd/ti_am335x_tscadc.c | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 543b9c42ac5f..b24402cb5432 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -152,11 +154,12 @@ static int tiadc_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct tiadc_device *adc_dev; struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); - struct mfd_tscadc_board *pdata; + struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; + struct device_node *node = pdev->dev.of_node; int err; + u32 val32; - pdata = tscadc_dev->dev->platform_data; - if (!pdata || !pdata->adc_init) { + if (!pdata && !node) { dev_err(&pdev->dev, "Could not find platform data\n"); return -EINVAL; } @@ -169,8 +172,17 @@ static int tiadc_probe(struct platform_device *pdev) } adc_dev = iio_priv(indio_dev); - adc_dev->mfd_tscadc = tscadc_dev; - adc_dev->channels = pdata->adc_init->adc_channels; + adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); + + if (pdata) + adc_dev->channels = pdata->adc_init->adc_channels; + else { + err = of_property_read_u32(node, + "ti,adc-channels", &val32); + if (err < 0) + goto err_free_device; + adc_dev->channels = val32; + } indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); @@ -260,11 +272,18 @@ static const struct dev_pm_ops tiadc_pm_ops = { #define TIADC_PM_OPS NULL #endif +static const struct of_device_id ti_adc_dt_ids[] = { + { .compatible = "ti,am3359-adc", }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); + static struct platform_driver tiadc_driver = { .driver = { .name = "tiadc", .owner = THIS_MODULE, .pm = TIADC_PM_OPS, + .of_match_table = of_match_ptr(ti_adc_dt_ids), }, .probe = tiadc_probe, .remove = tiadc_remove, diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index f50976623a01..1d6c74049590 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -210,6 +210,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) /* ADC Cell */ cell = &tscadc->cells[ADC_CELL]; cell->name = "tiadc"; + cell->of_compatible = "ti,am3359-adc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- GitLab From 0ead4fb22a5f1b31fee966117604e3be9cdeb2fb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 17:49:22 +0200 Subject: [PATCH 0916/2900] iio: ti_am335x_adc: remove platform_data support This patch removes access to platform data mfd_tscadc_board because the platform is DT only. Acked-by: Jonathan Cameron Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index b24402cb5432..2868c0c1b7e0 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -26,7 +26,6 @@ #include #include -#include struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; @@ -153,14 +152,12 @@ static int tiadc_probe(struct platform_device *pdev) { struct iio_dev *indio_dev; struct tiadc_device *adc_dev; - struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev); - struct mfd_tscadc_board *pdata = tscadc_dev->dev->platform_data; struct device_node *node = pdev->dev.of_node; int err; u32 val32; - if (!pdata && !node) { - dev_err(&pdev->dev, "Could not find platform data\n"); + if (!node) { + dev_err(&pdev->dev, "Could not find valid DT data.\n"); return -EINVAL; } @@ -174,15 +171,11 @@ static int tiadc_probe(struct platform_device *pdev) adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); - if (pdata) - adc_dev->channels = pdata->adc_init->adc_channels; - else { - err = of_property_read_u32(node, - "ti,adc-channels", &val32); - if (err < 0) - goto err_free_device; - adc_dev->channels = val32; - } + err = of_property_read_u32(node, + "ti,adc-channels", &val32); + if (err < 0) + goto err_free_device; + adc_dev->channels = val32; indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); -- GitLab From a6543a1cb56ab1bf4f722226ae36dd51eeaea97e Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:09 +0000 Subject: [PATCH 0917/2900] mfd: ti_am335x_tscadc: Add DT support Add DT support in the MFD core driver. The node name is "am3359" because it was tested on this platform. Signed-off-by: Pantelis Antoniou Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/mfd/ti_am335x_tscadc.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 1d6c74049590..292d34eaed54 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -90,20 +92,31 @@ static int ti_tscadc_probe(struct platform_device *pdev) struct resource *res; struct clk *clk; struct mfd_tscadc_board *pdata = pdev->dev.platform_data; + struct device_node *node = pdev->dev.of_node; struct mfd_cell *cell; int err, ctrl; int clk_value, clock_rate; - int tsc_wires, adc_channels = 0, total_channels; + int tsc_wires = 0, adc_channels = 0, total_channels; - if (!pdata) { + if (!pdata && !pdev->dev.of_node) { dev_err(&pdev->dev, "Could not find platform data\n"); return -EINVAL; } - if (pdata->adc_init) - adc_channels = pdata->adc_init->adc_channels; + if (pdev->dev.platform_data) { + if (pdata->tsc_init) + tsc_wires = pdata->tsc_init->wires; + + if (pdata->adc_init) + adc_channels = pdata->adc_init->adc_channels; + } else { + node = of_get_child_by_name(pdev->dev.of_node, "tsc"); + of_property_read_u32(node, "ti,wires", &tsc_wires); + + node = of_get_child_by_name(pdev->dev.of_node, "adc"); + of_property_read_u32(node, "ti,adc-channels", &adc_channels); + } - tsc_wires = pdata->tsc_init->wires; total_channels = tsc_wires + adc_channels; if (total_channels > 8) { @@ -285,11 +298,18 @@ static const struct dev_pm_ops tscadc_pm_ops = { #define TSCADC_PM_OPS NULL #endif +static const struct of_device_id ti_tscadc_dt_ids[] = { + { .compatible = "ti,am3359-tscadc", }, + { } +}; +MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids); + static struct platform_driver ti_tscadc_driver = { .driver = { - .name = "ti_tscadc", + .name = "ti_am3359-tscadc", .owner = THIS_MODULE, .pm = TSCADC_PM_OPS, + .of_match_table = of_match_ptr(ti_tscadc_dt_ids), }, .probe = ti_tscadc_probe, .remove = ti_tscadc_remove, -- GitLab From 9e5775f31289fc9915e4a2e4077950ea9a5da0b4 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 17:56:49 +0200 Subject: [PATCH 0918/2900] mfd: ti_am335x_tscadc: remove platform_data support This patch removes access to platform data mfd_tscadc_board because the platform is DT only. Signed-off-by: Sebastian Andrzej Siewior --- drivers/mfd/ti_am335x_tscadc.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 292d34eaed54..e78b9df590c0 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -26,8 +26,6 @@ #include #include -#include -#include static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg) { @@ -91,31 +89,22 @@ static int ti_tscadc_probe(struct platform_device *pdev) struct ti_tscadc_dev *tscadc; struct resource *res; struct clk *clk; - struct mfd_tscadc_board *pdata = pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; struct mfd_cell *cell; int err, ctrl; int clk_value, clock_rate; int tsc_wires = 0, adc_channels = 0, total_channels; - if (!pdata && !pdev->dev.of_node) { - dev_err(&pdev->dev, "Could not find platform data\n"); + if (!pdev->dev.of_node) { + dev_err(&pdev->dev, "Could not find valid DT data.\n"); return -EINVAL; } - if (pdev->dev.platform_data) { - if (pdata->tsc_init) - tsc_wires = pdata->tsc_init->wires; + node = of_get_child_by_name(pdev->dev.of_node, "tsc"); + of_property_read_u32(node, "ti,wires", &tsc_wires); - if (pdata->adc_init) - adc_channels = pdata->adc_init->adc_channels; - } else { - node = of_get_child_by_name(pdev->dev.of_node, "tsc"); - of_property_read_u32(node, "ti,wires", &tsc_wires); - - node = of_get_child_by_name(pdev->dev.of_node, "adc"); - of_property_read_u32(node, "ti,adc-channels", &adc_channels); - } + node = of_get_child_by_name(pdev->dev.of_node, "adc"); + of_property_read_u32(node, "ti,adc-channels", &adc_channels); total_channels = tsc_wires + adc_channels; -- GitLab From c80df483f61d0464224dc4386ced470c7275d78f Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sat, 13 Oct 2012 16:37:24 +0300 Subject: [PATCH 0919/2900] iio: ti_tscadc: provide datasheet_name and scan_type This patch provides the members "datasheet_name" and scan_type. This is the remaining part of the earlier patch where I (bigeasy) removed iio_map because it is now supplied by the device tree. It also static names as suggested by Jonathan. Acked-by: Jonathan Cameron Signed-off-by: Pantelis Antoniou Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 2868c0c1b7e0..9939810954f1 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -84,29 +86,46 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); } +static const char * const chan_name_ain[] = { + "AIN0", + "AIN1", + "AIN2", + "AIN3", + "AIN4", + "AIN5", + "AIN6", + "AIN7", +}; + static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) { + struct tiadc_device *adc_dev = iio_priv(indio_dev); struct iio_chan_spec *chan_array; + struct iio_chan_spec *chan; int i; indio_dev->num_channels = channels; - chan_array = kcalloc(indio_dev->num_channels, + chan_array = kcalloc(channels, sizeof(struct iio_chan_spec), GFP_KERNEL); - if (chan_array == NULL) return -ENOMEM; - for (i = 0; i < (indio_dev->num_channels); i++) { - struct iio_chan_spec *chan = chan_array + i; + chan = chan_array; + for (i = 0; i < channels; i++, chan++) { + chan->type = IIO_VOLTAGE; chan->indexed = 1; chan->channel = i; chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + chan->datasheet_name = chan_name_ain[i]; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 12; + chan->scan_type.storagebits = 32; } indio_dev->channels = chan_array; - return indio_dev->num_channels; + return 0; } static void tiadc_channels_remove(struct iio_dev *indio_dev) -- GitLab From 24d5c82f8227d4dedf177df3f062eb35db15aaf6 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sat, 13 Oct 2012 16:37:24 +0300 Subject: [PATCH 0920/2900] mfd: ti_tscadc: deal with partial activation Fix the mfd device in the case where a subdevice might not be activated. Signed-off-by: Pantelis Antoniou Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- drivers/mfd/ti_am335x_tscadc.c | 38 ++++++++++++++++++---------- include/linux/mfd/ti_am335x_tscadc.h | 8 +++--- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index e78b9df590c0..d05fcba6f13a 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -107,11 +107,14 @@ static int ti_tscadc_probe(struct platform_device *pdev) of_property_read_u32(node, "ti,adc-channels", &adc_channels); total_channels = tsc_wires + adc_channels; - if (total_channels > 8) { dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); return -EINVAL; } + if (total_channels == 0) { + dev_err(&pdev->dev, "Need atleast one channel.\n"); + return -EINVAL; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -202,28 +205,37 @@ static int ti_tscadc_probe(struct platform_device *pdev) ctrl |= CNTRLREG_TSCSSENB; tscadc_writel(tscadc, REG_CTRL, ctrl); + tscadc->used_cells = 0; + tscadc->tsc_cell = -1; + tscadc->adc_cell = -1; + /* TSC Cell */ - cell = &tscadc->cells[TSC_CELL]; - cell->name = "tsc"; - cell->of_compatible = "ti,am3359-tsc"; - cell->platform_data = &tscadc; - cell->pdata_size = sizeof(tscadc); + if (tsc_wires > 0) { + tscadc->tsc_cell = tscadc->used_cells; + cell = &tscadc->cells[tscadc->used_cells++]; + cell->name = "tsc"; + cell->of_compatible = "ti,am3359-tsc"; + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); + } /* ADC Cell */ - cell = &tscadc->cells[ADC_CELL]; - cell->name = "tiadc"; - cell->of_compatible = "ti,am3359-adc"; - cell->platform_data = &tscadc; - cell->pdata_size = sizeof(tscadc); + if (adc_channels > 0) { + tscadc->adc_cell = tscadc->used_cells; + cell = &tscadc->cells[tscadc->used_cells++]; + cell->name = "tiadc"; + cell->of_compatible = "ti,am3359-adc"; + cell->platform_data = &tscadc; + cell->pdata_size = sizeof(tscadc); + } err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells, - TSCADC_CELLS, NULL, 0, NULL); + tscadc->used_cells, NULL, 0, NULL); if (err < 0) goto err_disable_clk; device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, tscadc); - return 0; err_disable_clk: diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index e36ae4184917..fe54ba4a3b2f 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -120,11 +120,6 @@ #define TSCADC_CELLS 2 -enum tscadc_cells { - TSC_CELL, - ADC_CELL, -}; - struct mfd_tscadc_board { struct tsc_data *tsc_init; struct adc_data *adc_init; @@ -135,6 +130,9 @@ struct ti_tscadc_dev { struct regmap *regmap_tscadc; void __iomem *tscadc_base; int irq; + int used_cells; /* 1-2 */ + int tsc_cell; /* -1 if not used */ + int adc_cell; /* -1 if not used */ struct mfd_cell cells[TSCADC_CELLS]; u32 reg_se_cache; spinlock_t reg_lock; -- GitLab From a82279dd6d3e500fea457f1cfea46a6b7ecd7e1f Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Thu, 24 Jan 2013 03:45:12 +0000 Subject: [PATCH 0921/2900] arm: am33xx: add TSC/ADC mfd device support Add support for core multifunctional device along with its clients touchscreen and ADC. Signed-off-by: Pantelis Antoniou Signed-off-by: Patil, Rachna Signed-off-by: Felipe Balbi Signed-off-by: Sebastian Andrzej Siewior --- arch/arm/boot/dts/am335x-evm.dts | 14 ++++++++++++++ arch/arm/boot/dts/am33xx.dtsi | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index 0423298a26fe..26fea97dd6e0 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -244,3 +244,17 @@ &cpsw_emac1 { phy_id = <&davinci_mdio>, <1>; }; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordiante-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; + + adc { + ti,adc-channels = <4>; + }; +}; diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index 1460d9b88adf..4ad7797b97b6 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -404,6 +404,24 @@ ti,hwmods = "wkup_m3"; }; + tscadc: tscadc@44e0d000 { + compatible = "ti,am3359-tscadc"; + reg = <0x44e0d000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <16>; + ti,hwmods = "adc_tsc"; + status = "disabled"; + + tsc { + compatible = "ti,am3359-tsc"; + }; + am335x_adc: adc { + #io-channel-cells = <1>; + compatible = "ti,am3359-adc"; + }; + + }; + gpmc: gpmc@50000000 { compatible = "ti,am3352-gpmc"; ti,hwmods = "gpmc"; -- GitLab From a3e509bb328287beba05017037e505bc53b62724 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 21 May 2013 18:49:58 +0200 Subject: [PATCH 0922/2900] input: mfd: ti_am335x_tsc remove remaining platform data pieces The two header files removed here are unused and have no users as this platform was never used with platform devices. Signed-off-by: Sebastian Andrzej Siewior --- include/linux/input/ti_am335x_tsc.h | 35 --------------------- include/linux/mfd/ti_am335x_tscadc.h | 5 --- include/linux/platform_data/ti_am335x_adc.h | 14 --------- 3 files changed, 54 deletions(-) delete mode 100644 include/linux/input/ti_am335x_tsc.h delete mode 100644 include/linux/platform_data/ti_am335x_adc.h diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h deleted file mode 100644 index 6a66b4d1ac2c..000000000000 --- a/include/linux/input/ti_am335x_tsc.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __LINUX_TI_AM335X_TSC_H -#define __LINUX_TI_AM335X_TSC_H - -/** - * struct tsc_data Touchscreen wire configuration - * @wires: Wires refer to application modes - * i.e. 4/5/8 wire touchscreen support - * on the platform. - * @x_plate_resistance: X plate resistance. - * @steps_to_configure: The sequencer supports a total of - * 16 programmable steps. - * A step configured to read a single - * co-ordinate value, can be applied - * more number of times for better results. - * @wire_config: Different EVM's could have a different order - * for connecting wires on touchscreen. - * We need to provide an 8 bit number where in - * the 1st four bits represent the analog lines - * and the next 4 bits represent positive/ - * negative terminal on that input line. - * Notations to represent the input lines and - * terminals resoectively is as follows: - * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7. - * XP = 0, XN = 1, YP = 2, YN = 3. - * - */ - -struct tsc_data { - int wires; - int x_plate_resistance; - int steps_to_configure; - int wire_config[10]; -}; - -#endif diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index fe54ba4a3b2f..533f200e6d0e 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -120,11 +120,6 @@ #define TSCADC_CELLS 2 -struct mfd_tscadc_board { - struct tsc_data *tsc_init; - struct adc_data *adc_init; -}; - struct ti_tscadc_dev { struct device *dev; struct regmap *regmap_tscadc; diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h deleted file mode 100644 index e41d5834cb84..000000000000 --- a/include/linux/platform_data/ti_am335x_adc.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LINUX_TI_AM335X_ADC_H -#define __LINUX_TI_AM335X_ADC_H - -/** - * struct adc_data ADC Input information - * @adc_channels: Number of analog inputs - * available for ADC. - */ - -struct adc_data { - unsigned int adc_channels; -}; - -#endif -- GitLab From 5f184e63c61f92ab499273e682bb8898e88209a8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 27 May 2013 17:08:28 +0200 Subject: [PATCH 0923/2900] mfd: input: ti_am335x_tsc: rename device from tsc to TI-am335x-tsc tsc is a very generic name. This patch adds a TI and HW prefix to it less generic. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 2 +- drivers/mfd/ti_am335x_tscadc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index a1db55d1a862..ff3215ddf9f5 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -491,7 +491,7 @@ static struct platform_driver ti_tsc_driver = { .probe = titsc_probe, .remove = titsc_remove, .driver = { - .name = "tsc", + .name = "TI-am335x-tsc", .owner = THIS_MODULE, .pm = TITSC_PM_OPS, .of_match_table = of_match_ptr(ti_tsc_dt_ids), diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index d05fcba6f13a..5fb8b1dace8e 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -213,7 +213,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (tsc_wires > 0) { tscadc->tsc_cell = tscadc->used_cells; cell = &tscadc->cells[tscadc->used_cells++]; - cell->name = "tsc"; + cell->name = "TI-am335x-tsc"; cell->of_compatible = "ti,am3359-tsc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- GitLab From 9f99928fe0a03dd2ba5894b7bb942cc50b5d7c5e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 27 May 2013 17:12:52 +0200 Subject: [PATCH 0924/2900] mfd: iio: ti_am335x_adc: rename device from tiadc to TI-am335x-adc TI-adc reads a little better compared to tiadc. And if we add am335x to it then we have the same naming scheme as the tsc side. Acked-by: Jonathan Cameron Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 3 +-- drivers/mfd/ti_am335x_tscadc.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 9939810954f1..4bec91e40bf7 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids); static struct platform_driver tiadc_driver = { .driver = { - .name = "tiadc", + .name = "TI-am335x-adc", .owner = THIS_MODULE, .pm = TIADC_PM_OPS, .of_match_table = of_match_ptr(ti_adc_dt_ids), @@ -300,7 +300,6 @@ static struct platform_driver tiadc_driver = { .probe = tiadc_probe, .remove = tiadc_remove, }; - module_platform_driver(tiadc_driver); MODULE_DESCRIPTION("TI ADC controller driver"); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 5fb8b1dace8e..253233915009 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -223,7 +223,7 @@ static int ti_tscadc_probe(struct platform_device *pdev) if (adc_channels > 0) { tscadc->adc_cell = tscadc->used_cells; cell = &tscadc->cells[tscadc->used_cells++]; - cell->name = "tiadc"; + cell->name = "TI-am335x-adc"; cell->of_compatible = "ti,am3359-adc"; cell->platform_data = &tscadc; cell->pdata_size = sizeof(tscadc); -- GitLab From 8c896308feae7fb2e8da4ae4c09fe2d2ca18ad7b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 May 2013 14:46:21 +0200 Subject: [PATCH 0925/2900] input: ti_am335x_adc: use only FIFO0 and clean up a little The driver programs a threshold of "coordinate_readouts" say 5. The REG_FIFO0THR registers says it should it be programmed to "threshold minus one". The driver does not expect just 5 coordinates but 5 * 2 + 2. Multiplied by two because 5 for X and 5 for Y and plus 2 because we have two Z. The whole thing kind of works because It reads the 5 coordinates for X and Y from FIFO0 and FIFO1 and the last element in each FIFO is ignored within the loop and read later. Nothing guaranties that FIFO1 is ready by the time it is read. In fact I could see that that FIFO1 reaturns for Y channels 8,9, 10, 12, 6 and for Y channel 7 for Z. The problem is that channel 7 and channel 12 got somehow mixed up. The other Problem is that FIFO1 is also used by the IIO part leading to wrong results if both (tsc & adc) are used. The patch tries to clean up the whole thing a little: - Remove the +1 and -1 in REG_STEPCONFIG, REG_STEPDELAY and its counter part in the for loop. This is just confusing. - Use only FIFO0 in TSC. The fifo has space for 64 entries so should be fine. - Read the whole FIFO in one function and check the channel. - in case we dawdle around, make sure we only read a multiple of our coordinate set. On the second interrupt we will cleanup the remaining enties. Acked-by: Dmitry Torokhov Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 2 +- drivers/input/touchscreen/ti_am335x_tsc.c | 78 ++++++++++++----------- include/linux/mfd/ti_am335x_tscadc.h | 4 +- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 4bec91e40bf7..307a7c07be47 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -75,7 +75,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; - for (i = (steps + 1); i <= TOTAL_STEPS; i++) { + for (i = steps; i < TOTAL_STEPS; i++) { tiadc_writel(adc_dev, REG_STEPCONFIG(i), stepconfig | STEPCONFIG_INP(channels)); tiadc_writel(adc_dev, REG_STEPDELAY(i), diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index ff3215ddf9f5..1bceb2591fc7 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -120,11 +120,9 @@ static int titsc_config_wires(struct titsc *ts_dev) static void titsc_step_config(struct titsc *ts_dev) { unsigned int config; - unsigned int stepenable = 0; - int i, total_steps; - - /* Configure the Step registers */ - total_steps = 2 * ts_dev->coordinate_readouts; + int i; + int end_step; + u32 stepenable; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_xp; @@ -142,7 +140,9 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = 1; i <= ts_dev->coordinate_readouts; i++) { + /* 1 … coordinate_readouts is for X */ + end_step = ts_dev->coordinate_readouts; + for (i = 0; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } @@ -150,7 +150,7 @@ static void titsc_step_config(struct titsc *ts_dev) config = 0; config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yn | - STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; + STEPCONFIG_INM_ADCREFM; switch (ts_dev->wires) { case 4: config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); @@ -164,12 +164,13 @@ static void titsc_step_config(struct titsc *ts_dev) break; } - for (i = (ts_dev->coordinate_readouts + 1); i <= total_steps; i++) { + /* coordinate_readouts … coordinate_readouts * 2 is for Y */ + end_step = ts_dev->coordinate_readouts * 2; + for (i = ts_dev->coordinate_readouts; i < end_step; i++) { titsc_writel(ts_dev, REG_STEPCONFIG(i), config); titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); } - config = 0; /* Charge step configuration */ config = ts_dev->bit_xp | ts_dev->bit_yn | STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | @@ -178,35 +179,39 @@ static void titsc_step_config(struct titsc *ts_dev) titsc_writel(ts_dev, REG_CHARGECONFIG, config); titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); - config = 0; - /* Configure to calculate pressure */ + /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */ config = STEPCONFIG_MODE_HWSYNC | STEPCONFIG_AVG_16 | ts_dev->bit_yp | ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM | STEPCONFIG_INP(ts_dev->inp_xp); - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); - config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1; - titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); - titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), + end_step++; + config |= STEPCONFIG_INP(ts_dev->inp_yn); + titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config); + titsc_writel(ts_dev, REG_STEPDELAY(end_step), STEPCONFIG_OPENDLY); /* The steps1 … end and bit 0 for TS_Charge */ - stepenable = (1 << (total_steps + 2)) - 1; + stepenable = (1 << (end_step + 2)) - 1; am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable); } static void titsc_read_coordinates(struct titsc *ts_dev, - unsigned int *x, unsigned int *y) + u32 *x, u32 *y, u32 *z1, u32 *z2) { unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); unsigned int prev_val_x = ~0, prev_val_y = ~0; unsigned int prev_diff_x = ~0, prev_diff_y = ~0; unsigned int read, diff; unsigned int i, channel; + unsigned int creads = ts_dev->coordinate_readouts; + *z1 = *z2 = 0; + if (fifocount % (creads * 2 + 2)) + fifocount -= fifocount % (creads * 2 + 2); /* * Delta filter is used to remove large variations in sampled * values from ADC. The filter tries to predict where the next @@ -215,32 +220,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev, * algorithm compares the difference with that of a present value, * if true the value is reported to the sub system. */ - for (i = 0; i < fifocount - 1; i++) { + for (i = 0; i < fifocount; i++) { read = titsc_readl(ts_dev, REG_FIFO0); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= 0) && (channel < ts_dev->coordinate_readouts)) { - read &= 0xfff; + + channel = (read & 0xf0000) >> 16; + read &= 0xfff; + if (channel < creads) { diff = abs(read - prev_val_x); if (diff < prev_diff_x) { prev_diff_x = diff; *x = read; } prev_val_x = read; - } - read = titsc_readl(ts_dev, REG_FIFO1); - channel = read & 0xf0000; - channel = channel >> 0x10; - if ((channel >= ts_dev->coordinate_readouts) && - (channel < (2 * ts_dev->coordinate_readouts - 1))) { - read &= 0xfff; + } else if (channel < creads * 2) { diff = abs(read - prev_val_y); if (diff < prev_diff_y) { prev_diff_y = diff; *y = read; } prev_val_y = read; + + } else if (channel < creads * 2 + 1) { + *z1 = read; + + } else if (channel < creads * 2 + 2) { + *z2 = read; } } } @@ -256,10 +261,8 @@ static irqreturn_t titsc_irq(int irq, void *dev) status = titsc_readl(ts_dev, REG_IRQSTATUS); if (status & IRQENB_FIFO0THRES) { - titsc_read_coordinates(ts_dev, &x, &y); - z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; - z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; + titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2); if (ts_dev->pen_down && z1 != 0 && z2 != 0) { /* @@ -267,10 +270,10 @@ static irqreturn_t titsc_irq(int irq, void *dev) * Resistance(touch) = x plate resistance * * x postion/4096 * ((z2 / z1) - 1) */ - z = z2 - z1; + z = z1 - z2; z *= x; z *= ts_dev->x_plate_resistance; - z /= z1; + z /= z2; z = (z + 2047) >> 12; if (z <= MAX_12BIT) { @@ -391,7 +394,8 @@ static int titsc_probe(struct platform_device *pdev) goto err_free_irq; } titsc_step_config(ts_dev); - titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->coordinate_readouts); + titsc_writel(ts_dev, REG_FIFO0THR, + ts_dev->coordinate_readouts * 2 + 2 - 1); input_dev->name = "ti-tsc"; input_dev->dev.parent = &pdev->dev; @@ -468,7 +472,7 @@ static int titsc_resume(struct device *dev) } titsc_step_config(ts_dev); titsc_writel(ts_dev, REG_FIFO0THR, - ts_dev->coordinate_readouts); + ts_dev->coordinate_readouts * 2 + 2 - 1); return 0; } diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 533f200e6d0e..8d73fe29796a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -30,8 +30,8 @@ #define REG_IDLECONFIG 0x058 #define REG_CHARGECONFIG 0x05C #define REG_CHARGEDELAY 0x060 -#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) -#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) +#define REG_STEPCONFIG(n) (0x64 + ((n) * 8)) +#define REG_STEPDELAY(n) (0x68 + ((n) * 8)) #define REG_FIFO0CNT 0xE4 #define REG_FIFO0THR 0xE8 #define REG_FIFO1CNT 0xF0 -- GitLab From 00789e5deb0af08826bd0c602d21baa9016b54b5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:23:18 +0200 Subject: [PATCH 0926/2900] input: ti_am335x_tsc: ACK the HW_PEN irq in ISR The interrupt source IRQENB_HW_PEN is enabled in suspend and suposed to be used as a wake up source. Once this interrupt source is unmaksed, the devices ends up in ISR and never continues. This change ACKs the interrupt and disables it so the system does not freeze. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 1bceb2591fc7..2ba77039ab91 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -308,6 +308,12 @@ static irqreturn_t titsc_irq(int irq, void *dev) irqclr |= IRQENB_PENUP; } + if (status & IRQENB_HW_PEN) { + + titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00); + titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); + } + titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); am335x_tsc_se_update(ts_dev->mfd_tscadc); -- GitLab From 9a28b8834c55f7315fb1a7c487f836472fd37bf9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 5 Jun 2013 16:30:00 +0200 Subject: [PATCH 0927/2900] input: ti_am335x_tsc: return IRQ_NONE if there was no IRQ for us The previous patch ("input/ti_am335x_tsc: ACK the HW_PEN irq in ISR") acked the interrupt so we don't freeze if we don't handle an enabled interrupt source. The interrupt core has a mechanism for this and to get it work one should only say that it handled an interrupt if it is actually the case. Signed-off-by: Sebastian Andrzej Siewior --- drivers/input/touchscreen/ti_am335x_tsc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 2ba77039ab91..0e9f02aeae6b 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -314,10 +314,12 @@ static irqreturn_t titsc_irq(int irq, void *dev) titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); } - titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); - - am335x_tsc_se_update(ts_dev->mfd_tscadc); - return IRQ_HANDLED; + if (irqclr) { + titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); + am335x_tsc_se_update(ts_dev->mfd_tscadc); + return IRQ_HANDLED; + } + return IRQ_NONE; } static int titsc_parse_dt(struct platform_device *pdev, -- GitLab From 18926edebcb82ca325abf843293801d4ff43436a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 May 2013 17:39:02 +0200 Subject: [PATCH 0928/2900] iio: ti_am335x_adc: Allow to specify input line The TSC part allows to specify the input lines. The IIO part assumes that it usues always the last few, that means if IIO has adc-channels set to 2 it will use channel 6 and 7. However it might make sense to use only 6. This patch changes the device property (which was introduced recently and was never in an official release) in a way that the user can specify which of the AIN lines should be used. In Addition to this, the name is now AINx where x is the channel number i.e. for AIN6 we would have 6. Prior this, it always started counting at 0 which is confusing. In addition to this, it also checks for correct step number during reading and does not rely on proper FIFO depth. Acked-by: Jonathan Cameron Signed-off-by: Sebastian Andrzej Siewior --- arch/arm/boot/dts/am335x-evm.dts | 2 +- drivers/iio/adc/ti_am335x_adc.c | 57 +++++++++++++++++++++----------- drivers/mfd/ti_am335x_tscadc.c | 20 +++++++++-- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts index 26fea97dd6e0..0fa4c7f9539f 100644 --- a/arch/arm/boot/dts/am335x-evm.dts +++ b/arch/arm/boot/dts/am335x-evm.dts @@ -255,6 +255,6 @@ }; adc { - ti,adc-channels = <4>; + ti,adc-channels = <4 5 6 7>; }; }; diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 307a7c07be47..8ffe52d58829 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -32,6 +32,8 @@ struct tiadc_device { struct ti_tscadc_dev *mfd_tscadc; int channels; + u8 channel_line[8]; + u8 channel_step[8]; }; static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) @@ -57,7 +59,7 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev) static void tiadc_step_config(struct tiadc_device *adc_dev) { unsigned int stepconfig; - int i, channels = 0, steps; + int i, steps; u32 step_en; /* @@ -71,16 +73,18 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) */ steps = TOTAL_STEPS - adc_dev->channels; - channels = TOTAL_CHANNELS - adc_dev->channels; - stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; - for (i = steps; i < TOTAL_STEPS; i++) { - tiadc_writel(adc_dev, REG_STEPCONFIG(i), - stepconfig | STEPCONFIG_INP(channels)); - tiadc_writel(adc_dev, REG_STEPDELAY(i), + for (i = 0; i < adc_dev->channels; i++) { + int chan; + + chan = adc_dev->channel_line[i]; + tiadc_writel(adc_dev, REG_STEPCONFIG(steps), + stepconfig | STEPCONFIG_INP(chan)); + tiadc_writel(adc_dev, REG_STEPDELAY(steps), STEPCONFIG_OPENDLY); - channels++; + adc_dev->channel_step[i] = steps; + steps++; } step_en = get_adc_step_mask(adc_dev); am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); @@ -115,9 +119,9 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels) chan->type = IIO_VOLTAGE; chan->indexed = 1; - chan->channel = i; + chan->channel = adc_dev->channel_line[i]; chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - chan->datasheet_name = chan_name_ain[i]; + chan->datasheet_name = chan_name_ain[chan->channel]; chan->scan_type.sign = 'u'; chan->scan_type.realbits = 12; chan->scan_type.storagebits = 32; @@ -139,7 +143,8 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, { struct tiadc_device *adc_dev = iio_priv(indio_dev); int i; - unsigned int fifo1count, readx1; + unsigned int fifo1count, read; + u32 step = UINT_MAX; /* * When the sub-system is first enabled, @@ -152,11 +157,20 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, * Hence we need to flush out this data. */ + for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) { + if (chan->channel == adc_dev->channel_line[i]) { + step = adc_dev->channel_step[i]; + break; + } + } + if (WARN_ON_ONCE(step == UINT_MAX)) + return -EINVAL; + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (i = 0; i < fifo1count; i++) { - readx1 = tiadc_readl(adc_dev, REG_FIFO1); - if (i == chan->channel) - *val = readx1 & 0xfff; + read = tiadc_readl(adc_dev, REG_FIFO1); + if (read >> 16 == step) + *val = read & 0xfff; } am335x_tsc_se_update(adc_dev->mfd_tscadc); @@ -172,8 +186,11 @@ static int tiadc_probe(struct platform_device *pdev) struct iio_dev *indio_dev; struct tiadc_device *adc_dev; struct device_node *node = pdev->dev.of_node; + struct property *prop; + const __be32 *cur; int err; - u32 val32; + u32 val; + int channels = 0; if (!node) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); @@ -190,11 +207,11 @@ static int tiadc_probe(struct platform_device *pdev) adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); - err = of_property_read_u32(node, - "ti,adc-channels", &val32); - if (err < 0) - goto err_free_device; - adc_dev->channels = val32; + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { + adc_dev->channel_line[channels] = val; + channels++; + } + adc_dev->channels = channels; indio_dev->dev.parent = &pdev->dev; indio_dev->name = dev_name(&pdev->dev); diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index 253233915009..b003a16ba227 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -91,9 +91,13 @@ static int ti_tscadc_probe(struct platform_device *pdev) struct clk *clk; struct device_node *node = pdev->dev.of_node; struct mfd_cell *cell; + struct property *prop; + const __be32 *cur; + u32 val; int err, ctrl; int clk_value, clock_rate; int tsc_wires = 0, adc_channels = 0, total_channels; + int readouts = 0; if (!pdev->dev.of_node) { dev_err(&pdev->dev, "Could not find valid DT data.\n"); @@ -102,10 +106,17 @@ static int ti_tscadc_probe(struct platform_device *pdev) node = of_get_child_by_name(pdev->dev.of_node, "tsc"); of_property_read_u32(node, "ti,wires", &tsc_wires); + of_property_read_u32(node, "ti,coordiante-readouts", &readouts); node = of_get_child_by_name(pdev->dev.of_node, "adc"); - of_property_read_u32(node, "ti,adc-channels", &adc_channels); - + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { + adc_channels++; + if (val > 7) { + dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n", + val); + return -EINVAL; + } + } total_channels = tsc_wires + adc_channels; if (total_channels > 8) { dev_err(&pdev->dev, "Number of i/p channels more than 8\n"); @@ -116,6 +127,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) return -EINVAL; } + if (readouts * 2 + 2 + adc_channels > 16) { + dev_err(&pdev->dev, "Too many step configurations requested\n"); + return -EINVAL; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no memory resource defined.\n"); -- GitLab From 1460c152c53335b5403045d056502eda1204c33a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 29 May 2013 18:49:55 +0200 Subject: [PATCH 0929/2900] iio: ti_am335x_adc: check if we found the value Usually we get all the values we wanted but it is possible, that te ADC unit is busy performing the conversation for the HW events. In that case -EBUSY is returned and the user may re-call the function. Acked-by: Jonathan Cameron Signed-off-by: Sebastian Andrzej Siewior --- drivers/iio/adc/ti_am335x_adc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 8ffe52d58829..4427e8e46a7f 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -145,6 +145,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, int i; unsigned int fifo1count, read; u32 step = UINT_MAX; + bool found = false; /* * When the sub-system is first enabled, @@ -169,11 +170,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (i = 0; i < fifo1count; i++) { read = tiadc_readl(adc_dev, REG_FIFO1); - if (read >> 16 == step) + if (read >> 16 == step) { *val = read & 0xfff; + found = true; + } } am335x_tsc_se_update(adc_dev->mfd_tscadc); - + if (found == false) + return -EBUSY; return IIO_VAL_INT; } -- GitLab From 5e3dd157d7e70f0e3cea3f2573ed69fb156a19d5 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 12 Jun 2013 20:52:10 +0300 Subject: [PATCH 0930/2900] ath10k: mac80211 driver for Qualcomm Atheros 802.11ac CQA98xx devices Here's a new mac80211 driver for Qualcomm Atheros 802.11ac QCA98xx devices. A major difference from ath9k is that there's now a firmware and that's why we had to implement a new driver. The wiki page for the driver is: http://wireless.kernel.org/en/users/Drivers/ath10k The driver has had many authors, they are listed here alphabetically: Bartosz Markowski Janusz Dziedzic Kalle Valo Marek Kwaczynski Marek Puzyniak Michal Kazior Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/Kconfig | 1 + drivers/net/wireless/ath/Makefile | 1 + drivers/net/wireless/ath/ath10k/Kconfig | 39 + drivers/net/wireless/ath/ath10k/Makefile | 20 + drivers/net/wireless/ath/ath10k/bmi.c | 295 ++ drivers/net/wireless/ath/ath10k/bmi.h | 224 ++ drivers/net/wireless/ath/ath10k/ce.c | 1189 +++++++ drivers/net/wireless/ath/ath10k/ce.h | 516 ++++ drivers/net/wireless/ath/ath10k/core.c | 665 ++++ drivers/net/wireless/ath/ath10k/core.h | 369 +++ drivers/net/wireless/ath/ath10k/debug.c | 503 +++ drivers/net/wireless/ath/ath10k/debug.h | 90 + drivers/net/wireless/ath/ath10k/hif.h | 137 + drivers/net/wireless/ath/ath10k/htc.c | 1000 ++++++ drivers/net/wireless/ath/ath10k/htc.h | 368 +++ drivers/net/wireless/ath/ath10k/htt.c | 152 + drivers/net/wireless/ath/ath10k/htt.h | 1338 ++++++++ drivers/net/wireless/ath/ath10k/htt_rx.c | 1167 +++++++ drivers/net/wireless/ath/ath10k/htt_tx.c | 510 +++ drivers/net/wireless/ath/ath10k/hw.h | 304 ++ drivers/net/wireless/ath/ath10k/mac.c | 3066 +++++++++++++++++++ drivers/net/wireless/ath/ath10k/mac.h | 61 + drivers/net/wireless/ath/ath10k/pci.c | 2506 +++++++++++++++ drivers/net/wireless/ath/ath10k/pci.h | 355 +++ drivers/net/wireless/ath/ath10k/rx_desc.h | 990 ++++++ drivers/net/wireless/ath/ath10k/targaddrs.h | 449 +++ drivers/net/wireless/ath/ath10k/trace.c | 20 + drivers/net/wireless/ath/ath10k/trace.h | 170 + drivers/net/wireless/ath/ath10k/txrx.c | 417 +++ drivers/net/wireless/ath/ath10k/txrx.h | 39 + drivers/net/wireless/ath/ath10k/wmi.c | 2081 +++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 3052 ++++++++++++++++++ 32 files changed, 22094 insertions(+) create mode 100644 drivers/net/wireless/ath/ath10k/Kconfig create mode 100644 drivers/net/wireless/ath/ath10k/Makefile create mode 100644 drivers/net/wireless/ath/ath10k/bmi.c create mode 100644 drivers/net/wireless/ath/ath10k/bmi.h create mode 100644 drivers/net/wireless/ath/ath10k/ce.c create mode 100644 drivers/net/wireless/ath/ath10k/ce.h create mode 100644 drivers/net/wireless/ath/ath10k/core.c create mode 100644 drivers/net/wireless/ath/ath10k/core.h create mode 100644 drivers/net/wireless/ath/ath10k/debug.c create mode 100644 drivers/net/wireless/ath/ath10k/debug.h create mode 100644 drivers/net/wireless/ath/ath10k/hif.h create mode 100644 drivers/net/wireless/ath/ath10k/htc.c create mode 100644 drivers/net/wireless/ath/ath10k/htc.h create mode 100644 drivers/net/wireless/ath/ath10k/htt.c create mode 100644 drivers/net/wireless/ath/ath10k/htt.h create mode 100644 drivers/net/wireless/ath/ath10k/htt_rx.c create mode 100644 drivers/net/wireless/ath/ath10k/htt_tx.c create mode 100644 drivers/net/wireless/ath/ath10k/hw.h create mode 100644 drivers/net/wireless/ath/ath10k/mac.c create mode 100644 drivers/net/wireless/ath/ath10k/mac.h create mode 100644 drivers/net/wireless/ath/ath10k/pci.c create mode 100644 drivers/net/wireless/ath/ath10k/pci.h create mode 100644 drivers/net/wireless/ath/ath10k/rx_desc.h create mode 100644 drivers/net/wireless/ath/ath10k/targaddrs.h create mode 100644 drivers/net/wireless/ath/ath10k/trace.c create mode 100644 drivers/net/wireless/ath/ath10k/trace.h create mode 100644 drivers/net/wireless/ath/ath10k/txrx.c create mode 100644 drivers/net/wireless/ath/ath10k/txrx.h create mode 100644 drivers/net/wireless/ath/ath10k/wmi.c create mode 100644 drivers/net/wireless/ath/ath10k/wmi.h diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 2c02b4e84094..1abf1d421173 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig @@ -31,5 +31,6 @@ source "drivers/net/wireless/ath/carl9170/Kconfig" source "drivers/net/wireless/ath/ath6kl/Kconfig" source "drivers/net/wireless/ath/ar5523/Kconfig" source "drivers/net/wireless/ath/wil6210/Kconfig" +source "drivers/net/wireless/ath/ath10k/Kconfig" endif diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 97b964ded2be..fb05cfd19361 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_CARL9170) += carl9170/ obj-$(CONFIG_ATH6KL) += ath6kl/ obj-$(CONFIG_AR5523) += ar5523/ obj-$(CONFIG_WIL6210) += wil6210/ +obj-$(CONFIG_ATH10K) += ath10k/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig new file mode 100644 index 000000000000..cde58fe96254 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -0,0 +1,39 @@ +config ATH10K + tristate "Atheros 802.11ac wireless cards support" + depends on MAC80211 + select ATH_COMMON + ---help--- + This module adds support for wireless adapters based on + Atheros IEEE 802.11ac family of chipsets. + + If you choose to build a module, it'll be called ath10k. + +config ATH10K_PCI + tristate "Atheros ath10k PCI support" + depends on ATH10K && PCI + ---help--- + This module adds support for PCIE bus + +config ATH10K_DEBUG + bool "Atheros ath10k debugging" + depends on ATH10K + ---help--- + Enables debug support + + If unsure, say Y to make it easier to debug problems. + +config ATH10K_DEBUGFS + bool "Atheros ath10k debugfs support" + depends on ATH10K + ---help--- + Enabled debugfs support + + If unsure, say Y to make it easier to debug problems. + +config ATH10K_TRACING + bool "Atheros ath10k tracing support" + depends on ATH10K + depends on EVENT_TRACING + ---help--- + Select this to ath10k use tracing infrastructure. + diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile new file mode 100644 index 000000000000..a4179f49ee1f --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -0,0 +1,20 @@ +obj-$(CONFIG_ATH10K) += ath10k_core.o +ath10k_core-y += mac.o \ + debug.o \ + core.o \ + htc.o \ + htt.o \ + htt_rx.o \ + htt_tx.o \ + txrx.o \ + wmi.o \ + bmi.o + +ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o + +obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o +ath10k_pci-y += pci.o \ + ce.o + +# for tracing framework to find trace.h +CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c new file mode 100644 index 000000000000..1a2ef51b69d9 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/bmi.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bmi.h" +#include "hif.h" +#include "debug.h" +#include "htc.h" + +int ath10k_bmi_done(struct ath10k *ar) +{ + struct bmi_cmd cmd; + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done); + int ret; + + if (ar->bmi.done_sent) { + ath10k_dbg(ATH10K_DBG_CORE, "%s skipped\n", __func__); + return 0; + } + + ar->bmi.done_sent = true; + cmd.id = __cpu_to_le32(BMI_DONE); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL); + if (ret) { + ath10k_warn("unable to write to the device: %d\n", ret); + return ret; + } + + ath10k_dbg(ATH10K_DBG_CORE, "BMI done\n"); + return 0; +} + +int ath10k_bmi_get_target_info(struct ath10k *ar, + struct bmi_target_info *target_info) +{ + struct bmi_cmd cmd; + union bmi_resp resp; + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info); + u32 resplen = sizeof(resp.get_target_info); + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("BMI Get Target Info Command disallowed\n"); + return -EBUSY; + } + + cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen); + if (ret) { + ath10k_warn("unable to get target info from device\n"); + return ret; + } + + if (resplen < sizeof(resp.get_target_info)) { + ath10k_warn("invalid get_target_info response length (%d)\n", + resplen); + return -EIO; + } + + target_info->version = __le32_to_cpu(resp.get_target_info.version); + target_info->type = __le32_to_cpu(resp.get_target_info.type); + return 0; +} + +int ath10k_bmi_read_memory(struct ath10k *ar, + u32 address, void *buffer, u32 length) +{ + struct bmi_cmd cmd; + union bmi_resp resp; + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_mem); + u32 rxlen; + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("command disallowed\n"); + return -EBUSY; + } + + ath10k_dbg(ATH10K_DBG_CORE, + "%s: (device: 0x%p, address: 0x%x, length: %d)\n", + __func__, ar, address, length); + + while (length) { + rxlen = min_t(u32, length, BMI_MAX_DATA_SIZE); + + cmd.id = __cpu_to_le32(BMI_READ_MEMORY); + cmd.read_mem.addr = __cpu_to_le32(address); + cmd.read_mem.len = __cpu_to_le32(rxlen); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, + &resp, &rxlen); + if (ret) { + ath10k_warn("unable to read from the device\n"); + return ret; + } + + memcpy(buffer, resp.read_mem.payload, rxlen); + address += rxlen; + buffer += rxlen; + length -= rxlen; + } + + return 0; +} + +int ath10k_bmi_write_memory(struct ath10k *ar, + u32 address, const void *buffer, u32 length) +{ + struct bmi_cmd cmd; + u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.write_mem); + u32 txlen; + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("command disallowed\n"); + return -EBUSY; + } + + ath10k_dbg(ATH10K_DBG_CORE, + "%s: (device: 0x%p, address: 0x%x, length: %d)\n", + __func__, ar, address, length); + + while (length) { + txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen); + + /* copy before roundup to avoid reading beyond buffer*/ + memcpy(cmd.write_mem.payload, buffer, txlen); + txlen = roundup(txlen, 4); + + cmd.id = __cpu_to_le32(BMI_WRITE_MEMORY); + cmd.write_mem.addr = __cpu_to_le32(address); + cmd.write_mem.len = __cpu_to_le32(txlen); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen, + NULL, NULL); + if (ret) { + ath10k_warn("unable to write to the device\n"); + return ret; + } + + /* fixup roundup() so `length` zeroes out for last chunk */ + txlen = min(txlen, length); + + address += txlen; + buffer += txlen; + length -= txlen; + } + + return 0; +} + +int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param) +{ + struct bmi_cmd cmd; + union bmi_resp resp; + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.execute); + u32 resplen = sizeof(resp.execute); + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("command disallowed\n"); + return -EBUSY; + } + + ath10k_dbg(ATH10K_DBG_CORE, + "%s: (device: 0x%p, address: 0x%x, param: %d)\n", + __func__, ar, address, *param); + + cmd.id = __cpu_to_le32(BMI_EXECUTE); + cmd.execute.addr = __cpu_to_le32(address); + cmd.execute.param = __cpu_to_le32(*param); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen); + if (ret) { + ath10k_warn("unable to read from the device\n"); + return ret; + } + + if (resplen < sizeof(resp.execute)) { + ath10k_warn("invalid execute response length (%d)\n", + resplen); + return ret; + } + + *param = __le32_to_cpu(resp.execute.result); + return 0; +} + +int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length) +{ + struct bmi_cmd cmd; + u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.lz_data); + u32 txlen; + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("command disallowed\n"); + return -EBUSY; + } + + while (length) { + txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen); + + WARN_ON_ONCE(txlen & 3); + + cmd.id = __cpu_to_le32(BMI_LZ_DATA); + cmd.lz_data.len = __cpu_to_le32(txlen); + memcpy(cmd.lz_data.payload, buffer, txlen); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen, + NULL, NULL); + if (ret) { + ath10k_warn("unable to write to the device\n"); + return ret; + } + + buffer += txlen; + length -= txlen; + } + + return 0; +} + +int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address) +{ + struct bmi_cmd cmd; + u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start); + int ret; + + if (ar->bmi.done_sent) { + ath10k_warn("command disallowed\n"); + return -EBUSY; + } + + cmd.id = __cpu_to_le32(BMI_LZ_STREAM_START); + cmd.lz_start.addr = __cpu_to_le32(address); + + ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL); + if (ret) { + ath10k_warn("unable to Start LZ Stream to the device\n"); + return ret; + } + + return 0; +} + +int ath10k_bmi_fast_download(struct ath10k *ar, + u32 address, const void *buffer, u32 length) +{ + u8 trailer[4] = {}; + u32 head_len = rounddown(length, 4); + u32 trailer_len = length - head_len; + int ret; + + ret = ath10k_bmi_lz_stream_start(ar, address); + if (ret) + return ret; + + /* copy the last word into a zero padded buffer */ + if (trailer_len > 0) + memcpy(trailer, buffer + head_len, trailer_len); + + ret = ath10k_bmi_lz_data(ar, buffer, head_len); + if (ret) + return ret; + + if (trailer_len > 0) + ret = ath10k_bmi_lz_data(ar, trailer, 4); + + if (ret != 0) + return ret; + + /* + * Close compressed stream and open a new (fake) one. + * This serves mainly to flush Target caches. + */ + ret = ath10k_bmi_lz_stream_start(ar, 0x00); + + return ret; +} diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h new file mode 100644 index 000000000000..32c56aa33a5e --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _BMI_H_ +#define _BMI_H_ + +#include "core.h" + +/* + * Bootloader Messaging Interface (BMI) + * + * BMI is a very simple messaging interface used during initialization + * to read memory, write memory, execute code, and to define an + * application entry PC. + * + * It is used to download an application to QCA988x, to provide + * patches to code that is already resident on QCA988x, and generally + * to examine and modify state. The Host has an opportunity to use + * BMI only once during bootup. Once the Host issues a BMI_DONE + * command, this opportunity ends. + * + * The Host writes BMI requests to mailbox0, and reads BMI responses + * from mailbox0. BMI requests all begin with a command + * (see below for specific commands), and are followed by + * command-specific data. + * + * Flow control: + * The Host can only issue a command once the Target gives it a + * "BMI Command Credit", using AR8K Counter #4. As soon as the + * Target has completed a command, it issues another BMI Command + * Credit (so the Host can issue the next command). + * + * BMI handles all required Target-side cache flushing. + */ + +/* Maximum data size used for BMI transfers */ +#define BMI_MAX_DATA_SIZE 256 + +/* len = cmd + addr + length */ +#define BMI_MAX_CMDBUF_SIZE (BMI_MAX_DATA_SIZE + \ + sizeof(u32) + \ + sizeof(u32) + \ + sizeof(u32)) + +/* BMI Commands */ + +enum bmi_cmd_id { + BMI_NO_COMMAND = 0, + BMI_DONE = 1, + BMI_READ_MEMORY = 2, + BMI_WRITE_MEMORY = 3, + BMI_EXECUTE = 4, + BMI_SET_APP_START = 5, + BMI_READ_SOC_REGISTER = 6, + BMI_READ_SOC_WORD = 6, + BMI_WRITE_SOC_REGISTER = 7, + BMI_WRITE_SOC_WORD = 7, + BMI_GET_TARGET_ID = 8, + BMI_GET_TARGET_INFO = 8, + BMI_ROMPATCH_INSTALL = 9, + BMI_ROMPATCH_UNINSTALL = 10, + BMI_ROMPATCH_ACTIVATE = 11, + BMI_ROMPATCH_DEACTIVATE = 12, + BMI_LZ_STREAM_START = 13, /* should be followed by LZ_DATA */ + BMI_LZ_DATA = 14, + BMI_NVRAM_PROCESS = 15, +}; + +#define BMI_NVRAM_SEG_NAME_SZ 16 + +struct bmi_cmd { + __le32 id; /* enum bmi_cmd_id */ + union { + struct { + } done; + struct { + __le32 addr; + __le32 len; + } read_mem; + struct { + __le32 addr; + __le32 len; + u8 payload[0]; + } write_mem; + struct { + __le32 addr; + __le32 param; + } execute; + struct { + __le32 addr; + } set_app_start; + struct { + __le32 addr; + } read_soc_reg; + struct { + __le32 addr; + __le32 value; + } write_soc_reg; + struct { + } get_target_info; + struct { + __le32 rom_addr; + __le32 ram_addr; /* or value */ + __le32 size; + __le32 activate; /* 0=install, but dont activate */ + } rompatch_install; + struct { + __le32 patch_id; + } rompatch_uninstall; + struct { + __le32 count; + __le32 patch_ids[0]; /* length of @count */ + } rompatch_activate; + struct { + __le32 count; + __le32 patch_ids[0]; /* length of @count */ + } rompatch_deactivate; + struct { + __le32 addr; + } lz_start; + struct { + __le32 len; /* max BMI_MAX_DATA_SIZE */ + u8 payload[0]; /* length of @len */ + } lz_data; + struct { + u8 name[BMI_NVRAM_SEG_NAME_SZ]; + } nvram_process; + u8 payload[BMI_MAX_CMDBUF_SIZE]; + }; +} __packed; + +union bmi_resp { + struct { + u8 payload[0]; + } read_mem; + struct { + __le32 result; + } execute; + struct { + __le32 value; + } read_soc_reg; + struct { + __le32 len; + __le32 version; + __le32 type; + } get_target_info; + struct { + __le32 patch_id; + } rompatch_install; + struct { + __le32 patch_id; + } rompatch_uninstall; + struct { + /* 0 = nothing executed + * otherwise = NVRAM segment return value */ + __le32 result; + } nvram_process; + u8 payload[BMI_MAX_CMDBUF_SIZE]; +} __packed; + +struct bmi_target_info { + u32 version; + u32 type; +}; + + +/* in msec */ +#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ) + +#define BMI_CE_NUM_TO_TARG 0 +#define BMI_CE_NUM_TO_HOST 1 + +int ath10k_bmi_done(struct ath10k *ar); +int ath10k_bmi_get_target_info(struct ath10k *ar, + struct bmi_target_info *target_info); +int ath10k_bmi_read_memory(struct ath10k *ar, u32 address, + void *buffer, u32 length); +int ath10k_bmi_write_memory(struct ath10k *ar, u32 address, + const void *buffer, u32 length); + +#define ath10k_bmi_read32(ar, item, val) \ + ({ \ + int ret; \ + u32 addr; \ + __le32 tmp; \ + \ + addr = host_interest_item_address(HI_ITEM(item)); \ + ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \ + *val = __le32_to_cpu(tmp); \ + ret; \ + }) + +#define ath10k_bmi_write32(ar, item, val) \ + ({ \ + int ret; \ + u32 address; \ + __le32 v = __cpu_to_le32(val); \ + \ + address = host_interest_item_address(HI_ITEM(item)); \ + ret = ath10k_bmi_write_memory(ar, address, \ + (u8 *)&v, sizeof(v)); \ + ret; \ + }) + +int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param); +int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address); +int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length); +int ath10k_bmi_fast_download(struct ath10k *ar, u32 address, + const void *buffer, u32 length); +#endif /* _BMI_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c new file mode 100644 index 000000000000..61a8ac70d3ca --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -0,0 +1,1189 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hif.h" +#include "pci.h" +#include "ce.h" +#include "debug.h" + +/* + * Support for Copy Engine hardware, which is mainly used for + * communication between Host and Target over a PCIe interconnect. + */ + +/* + * A single CopyEngine (CE) comprises two "rings": + * a source ring + * a destination ring + * + * Each ring consists of a number of descriptors which specify + * an address, length, and meta-data. + * + * Typically, one side of the PCIe interconnect (Host or Target) + * controls one ring and the other side controls the other ring. + * The source side chooses when to initiate a transfer and it + * chooses what to send (buffer address, length). The destination + * side keeps a supply of "anonymous receive buffers" available and + * it handles incoming data as it arrives (when the destination + * recieves an interrupt). + * + * The sender may send a simple buffer (address/length) or it may + * send a small list of buffers. When a small list is sent, hardware + * "gathers" these and they end up in a single destination buffer + * with a single interrupt. + * + * There are several "contexts" managed by this layer -- more, it + * may seem -- than should be needed. These are provided mainly for + * maximum flexibility and especially to facilitate a simpler HIF + * implementation. There are per-CopyEngine recv, send, and watermark + * contexts. These are supplied by the caller when a recv, send, + * or watermark handler is established and they are echoed back to + * the caller when the respective callbacks are invoked. There is + * also a per-transfer context supplied by the caller when a buffer + * (or sendlist) is sent and when a buffer is enqueued for recv. + * These per-transfer contexts are echoed back to the caller when + * the buffer is sent/received. + */ + +static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n); +} + +static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + return ath10k_pci_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS); +} + +static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + void __iomem *indicator_addr; + + if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) { + ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); + return; + } + + /* workaround for QCA988x_1.0 HW CE */ + indicator_addr = ar_pci->mem + ce_ctrl_addr + DST_WATERMARK_ADDRESS; + + if (ce_ctrl_addr == ath10k_ce_base_address(CDC_WAR_DATA_CE)) { + iowrite32((CDC_WAR_MAGIC_STR | n), indicator_addr); + } else { + unsigned long irq_flags; + local_irq_save(irq_flags); + iowrite32(1, indicator_addr); + + /* + * PCIE write waits for ACK in IPQ8K, there is no + * need to read back value. + */ + (void)ioread32(indicator_addr); + (void)ioread32(indicator_addr); /* conservative */ + + ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); + + iowrite32(0, indicator_addr); + local_irq_restore(irq_flags); + } +} + +static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + return ath10k_pci_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS); +} + +static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS); +} + +static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int addr) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr); +} + +static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n); +} + +static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 ctrl1_addr = ath10k_pci_read32((ar), + (ce_ctrl_addr) + CE_CTRL1_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) | + CE_CTRL1_DMAX_LENGTH_SET(n)); +} + +static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) | + CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n)); +} + +static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 ctrl1_addr = ath10k_pci_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, + (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) | + CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n)); +} + +static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + return ath10k_pci_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS); +} + +static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, + u32 ce_ctrl_addr, + u32 addr) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr); +} + +static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n); +} + +static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, + (addr & ~SRC_WATERMARK_HIGH_MASK) | + SRC_WATERMARK_HIGH_SET(n)); +} + +static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, + (addr & ~SRC_WATERMARK_LOW_MASK) | + SRC_WATERMARK_LOW_SET(n)); +} + +static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, + (addr & ~DST_WATERMARK_HIGH_MASK) | + DST_WATERMARK_HIGH_SET(n)); +} + +static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + u32 addr = ath10k_pci_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, + (addr & ~DST_WATERMARK_LOW_MASK) | + DST_WATERMARK_LOW_SET(n)); +} + +static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + u32 host_ie_addr = ath10k_pci_read32(ar, + ce_ctrl_addr + HOST_IE_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + host_ie_addr | HOST_IE_COPY_COMPLETE_MASK); +} + +static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + u32 host_ie_addr = ath10k_pci_read32(ar, + ce_ctrl_addr + HOST_IE_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK); +} + +static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + u32 host_ie_addr = ath10k_pci_read32(ar, + ce_ctrl_addr + HOST_IE_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, + host_ie_addr & ~CE_WATERMARK_MASK); +} + +static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, + u32 ce_ctrl_addr) +{ + u32 misc_ie_addr = ath10k_pci_read32(ar, + ce_ctrl_addr + MISC_IE_ADDRESS); + + ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, + misc_ie_addr | CE_ERROR_MASK); +} + +static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int mask) +{ + ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); +} + + +/* + * Guts of ath10k_ce_send, used by both ath10k_ce_send and + * ath10k_ce_sendlist_send. + * The caller takes responsibility for any needed locking. + */ +static int ath10k_ce_send_nolock(struct ce_state *ce_state, + void *per_transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + struct ath10k *ar = ce_state->ar; + struct ce_ring_state *src_ring = ce_state->src_ring; + struct ce_desc *desc, *sdesc; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int write_index = src_ring->write_index; + u32 ctrl_addr = ce_state->ctrl_addr; + u32 desc_flags = 0; + int ret = 0; + + if (nbytes > ce_state->src_sz_max) + ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n", + __func__, nbytes, ce_state->src_sz_max); + + ath10k_pci_wake(ar); + + if (unlikely(CE_RING_DELTA(nentries_mask, + write_index, sw_index - 1) <= 0)) { + ret = -EIO; + goto exit; + } + + desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, + write_index); + sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index); + + desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); + + if (flags & CE_SEND_FLAG_GATHER) + desc_flags |= CE_DESC_FLAGS_GATHER; + if (flags & CE_SEND_FLAG_BYTE_SWAP) + desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; + + sdesc->addr = __cpu_to_le32(buffer); + sdesc->nbytes = __cpu_to_le16(nbytes); + sdesc->flags = __cpu_to_le16(desc_flags); + + *desc = *sdesc; + + src_ring->per_transfer_context[write_index] = per_transfer_context; + + /* Update Source Ring Write Index */ + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + + /* WORKAROUND */ + if (!(flags & CE_SEND_FLAG_GATHER)) + ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); + + src_ring->write_index = write_index; +exit: + ath10k_pci_sleep(ar); + return ret; +} + +int ath10k_ce_send(struct ce_state *ce_state, + void *per_transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + spin_lock_bh(&ar_pci->ce_lock); + ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, + buffer, nbytes, transfer_id, flags); + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist, u32 buffer, + unsigned int nbytes, u32 flags) +{ + unsigned int num_items = sendlist->num_items; + struct ce_sendlist_item *item; + + item = &sendlist->item[num_items]; + item->data = buffer; + item->u.nbytes = nbytes; + item->flags = flags; + sendlist->num_items++; +} + +int ath10k_ce_sendlist_send(struct ce_state *ce_state, + void *per_transfer_context, + struct ce_sendlist *sendlist, + unsigned int transfer_id) +{ + struct ce_ring_state *src_ring = ce_state->src_ring; + struct ce_sendlist_item *item; + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int num_items = sendlist->num_items; + unsigned int sw_index; + unsigned int write_index; + int i, delta, ret = -ENOMEM; + + spin_lock_bh(&ar_pci->ce_lock); + + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + + delta = CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); + + if (delta >= num_items) { + /* + * Handle all but the last item uniformly. + */ + for (i = 0; i < num_items - 1; i++) { + item = &sendlist->item[i]; + ret = ath10k_ce_send_nolock(ce_state, + CE_SENDLIST_ITEM_CTXT, + (u32) item->data, + item->u.nbytes, transfer_id, + item->flags | + CE_SEND_FLAG_GATHER); + if (ret) + ath10k_warn("CE send failed for item: %d\n", i); + } + /* + * Provide valid context pointer for final item. + */ + item = &sendlist->item[i]; + ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, + (u32) item->data, item->u.nbytes, + transfer_id, item->flags); + if (ret) + ath10k_warn("CE send failed for last item: %d\n", i); + } + + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, + void *per_recv_context, + u32 buffer) +{ + struct ce_ring_state *dest_ring = ce_state->dest_ring; + u32 ctrl_addr = ce_state->ctrl_addr; + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int write_index; + unsigned int sw_index; + int ret; + + spin_lock_bh(&ar_pci->ce_lock); + write_index = dest_ring->write_index; + sw_index = dest_ring->sw_index; + + ath10k_pci_wake(ar); + + if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) { + struct ce_desc *base = dest_ring->base_addr_owner_space; + struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index); + + /* Update destination descriptor */ + desc->addr = __cpu_to_le32(buffer); + desc->nbytes = 0; + + dest_ring->per_transfer_context[write_index] = + per_recv_context; + + /* Update Destination Ring Write Index */ + write_index = CE_RING_IDX_INCR(nentries_mask, write_index); + ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index); + dest_ring->write_index = write_index; + ret = 0; + } else { + ret = -EIO; + } + ath10k_pci_sleep(ar); + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +/* + * Guts of ath10k_ce_completed_recv_next. + * The caller takes responsibility for any necessary locking. + */ +static int ath10k_ce_completed_recv_next_nolock(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp) +{ + struct ce_ring_state *dest_ring = ce_state->dest_ring; + unsigned int nentries_mask = dest_ring->nentries_mask; + unsigned int sw_index = dest_ring->sw_index; + + struct ce_desc *base = dest_ring->base_addr_owner_space; + struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, sw_index); + struct ce_desc sdesc; + u16 nbytes; + + /* Copy in one go for performance reasons */ + sdesc = *desc; + + nbytes = __le16_to_cpu(sdesc.nbytes); + if (nbytes == 0) { + /* + * This closes a relatively unusual race where the Host + * sees the updated DRRI before the update to the + * corresponding descriptor has completed. We treat this + * as a descriptor that is not yet done. + */ + return -EIO; + } + + desc->nbytes = 0; + + /* Return data from completed destination descriptor */ + *bufferp = __le32_to_cpu(sdesc.addr); + *nbytesp = nbytes; + *transfer_idp = MS(__le16_to_cpu(sdesc.flags), CE_DESC_FLAGS_META_DATA); + + if (__le16_to_cpu(sdesc.flags) & CE_DESC_FLAGS_BYTE_SWAP) + *flagsp = CE_RECV_FLAG_SWAPPED; + else + *flagsp = 0; + + if (per_transfer_contextp) + *per_transfer_contextp = + dest_ring->per_transfer_context[sw_index]; + + /* sanity */ + dest_ring->per_transfer_context[sw_index] = NULL; + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + dest_ring->sw_index = sw_index; + + return 0; +} + +int ath10k_ce_completed_recv_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + spin_lock_bh(&ar_pci->ce_lock); + ret = ath10k_ce_completed_recv_next_nolock(ce_state, + per_transfer_contextp, + bufferp, nbytesp, + transfer_idp, flagsp); + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp) +{ + struct ce_ring_state *dest_ring; + unsigned int nentries_mask; + unsigned int sw_index; + unsigned int write_index; + int ret; + struct ath10k *ar; + struct ath10k_pci *ar_pci; + + dest_ring = ce_state->dest_ring; + + if (!dest_ring) + return -EIO; + + ar = ce_state->ar; + ar_pci = ath10k_pci_priv(ar); + + spin_lock_bh(&ar_pci->ce_lock); + + nentries_mask = dest_ring->nentries_mask; + sw_index = dest_ring->sw_index; + write_index = dest_ring->write_index; + if (write_index != sw_index) { + struct ce_desc *base = dest_ring->base_addr_owner_space; + struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, sw_index); + + /* Return data from completed destination descriptor */ + *bufferp = __le32_to_cpu(desc->addr); + + if (per_transfer_contextp) + *per_transfer_contextp = + dest_ring->per_transfer_context[sw_index]; + + /* sanity */ + dest_ring->per_transfer_context[sw_index] = NULL; + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + dest_ring->sw_index = sw_index; + ret = 0; + } else { + ret = -EIO; + } + + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +/* + * Guts of ath10k_ce_completed_send_next. + * The caller takes responsibility for any necessary locking. + */ +static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp) +{ + struct ce_ring_state *src_ring = ce_state->src_ring; + u32 ctrl_addr = ce_state->ctrl_addr; + struct ath10k *ar = ce_state->ar; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int read_index; + int ret = -EIO; + + if (src_ring->hw_index == sw_index) { + /* + * The SW completion index has caught up with the cached + * version of the HW completion index. + * Update the cached HW completion index to see whether + * the SW has really caught up to the HW, or if the cached + * value of the HW index has become stale. + */ + ath10k_pci_wake(ar); + src_ring->hw_index = + ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + ath10k_pci_sleep(ar); + } + read_index = src_ring->hw_index; + + if ((read_index != sw_index) && (read_index != 0xffffffff)) { + struct ce_desc *sbase = src_ring->shadow_base; + struct ce_desc *sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); + + /* Return data from completed source descriptor */ + *bufferp = __le32_to_cpu(sdesc->addr); + *nbytesp = __le16_to_cpu(sdesc->nbytes); + *transfer_idp = MS(__le16_to_cpu(sdesc->flags), + CE_DESC_FLAGS_META_DATA); + + if (per_transfer_contextp) + *per_transfer_contextp = + src_ring->per_transfer_context[sw_index]; + + /* sanity */ + src_ring->per_transfer_context[sw_index] = NULL; + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + src_ring->sw_index = sw_index; + ret = 0; + } + + return ret; +} + +/* NB: Modeled after ath10k_ce_completed_send_next */ +int ath10k_ce_cancel_send_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp) +{ + struct ce_ring_state *src_ring; + unsigned int nentries_mask; + unsigned int sw_index; + unsigned int write_index; + int ret; + struct ath10k *ar; + struct ath10k_pci *ar_pci; + + src_ring = ce_state->src_ring; + + if (!src_ring) + return -EIO; + + ar = ce_state->ar; + ar_pci = ath10k_pci_priv(ar); + + spin_lock_bh(&ar_pci->ce_lock); + + nentries_mask = src_ring->nentries_mask; + sw_index = src_ring->sw_index; + write_index = src_ring->write_index; + + if (write_index != sw_index) { + struct ce_desc *base = src_ring->base_addr_owner_space; + struct ce_desc *desc = CE_SRC_RING_TO_DESC(base, sw_index); + + /* Return data from completed source descriptor */ + *bufferp = __le32_to_cpu(desc->addr); + *nbytesp = __le16_to_cpu(desc->nbytes); + *transfer_idp = MS(__le16_to_cpu(desc->flags), + CE_DESC_FLAGS_META_DATA); + + if (per_transfer_contextp) + *per_transfer_contextp = + src_ring->per_transfer_context[sw_index]; + + /* sanity */ + src_ring->per_transfer_context[sw_index] = NULL; + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + src_ring->sw_index = sw_index; + ret = 0; + } else { + ret = -EIO; + } + + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +int ath10k_ce_completed_send_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + spin_lock_bh(&ar_pci->ce_lock); + ret = ath10k_ce_completed_send_next_nolock(ce_state, + per_transfer_contextp, + bufferp, nbytesp, + transfer_idp); + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +} + +/* + * Guts of interrupt handler for per-engine interrupts on a particular CE. + * + * Invokes registered callbacks for recv_complete, + * send_complete, and watermarks. + */ +void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id]; + u32 ctrl_addr = ce_state->ctrl_addr; + void *transfer_context; + u32 buf; + unsigned int nbytes; + unsigned int id; + unsigned int flags; + + ath10k_pci_wake(ar); + spin_lock_bh(&ar_pci->ce_lock); + + /* Clear the copy-complete interrupts that will be handled here. */ + ath10k_ce_engine_int_status_clear(ar, ctrl_addr, + HOST_IS_COPY_COMPLETE_MASK); + + if (ce_state->recv_cb) { + /* + * Pop completed recv buffers and call the registered + * recv callback for each + */ + while (ath10k_ce_completed_recv_next_nolock(ce_state, + &transfer_context, + &buf, &nbytes, + &id, &flags) == 0) { + spin_unlock_bh(&ar_pci->ce_lock); + ce_state->recv_cb(ce_state, transfer_context, buf, + nbytes, id, flags); + spin_lock_bh(&ar_pci->ce_lock); + } + } + + if (ce_state->send_cb) { + /* + * Pop completed send buffers and call the registered + * send callback for each + */ + while (ath10k_ce_completed_send_next_nolock(ce_state, + &transfer_context, + &buf, + &nbytes, + &id) == 0) { + spin_unlock_bh(&ar_pci->ce_lock); + ce_state->send_cb(ce_state, transfer_context, + buf, nbytes, id); + spin_lock_bh(&ar_pci->ce_lock); + } + } + + /* + * Misc CE interrupts are not being handled, but still need + * to be cleared. + */ + ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK); + + spin_unlock_bh(&ar_pci->ce_lock); + ath10k_pci_sleep(ar); +} + +/* + * Handler for per-engine interrupts on ALL active CEs. + * This is used in cases where the system is sharing a + * single interrput for all CEs + */ + +void ath10k_ce_per_engine_service_any(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ce_id; + u32 intr_summary; + + ath10k_pci_wake(ar); + intr_summary = CE_INTERRUPT_SUMMARY(ar); + + for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) { + if (intr_summary & (1 << ce_id)) + intr_summary &= ~(1 << ce_id); + else + /* no intr pending on this CE */ + continue; + + ath10k_ce_per_engine_service(ar, ce_id); + } + + ath10k_pci_sleep(ar); +} + +/* + * Adjust interrupts for the copy complete handler. + * If it's needed for either send or recv, then unmask + * this interrupt; otherwise, mask it. + * + * Called with ce_lock held. + */ +static void ath10k_ce_per_engine_handler_adjust(struct ce_state *ce_state, + int disable_copy_compl_intr) +{ + u32 ctrl_addr = ce_state->ctrl_addr; + struct ath10k *ar = ce_state->ar; + + ath10k_pci_wake(ar); + + if ((!disable_copy_compl_intr) && + (ce_state->send_cb || ce_state->recv_cb)) + ath10k_ce_copy_complete_inter_enable(ar, ctrl_addr); + else + ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); + + ath10k_ce_watermark_intr_disable(ar, ctrl_addr); + + ath10k_pci_sleep(ar); +} + +void ath10k_ce_disable_interrupts(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ce_id; + + ath10k_pci_wake(ar); + for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) { + struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id]; + u32 ctrl_addr = ce_state->ctrl_addr; + + ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); + } + ath10k_pci_sleep(ar); +} + +void ath10k_ce_send_cb_register(struct ce_state *ce_state, + void (*send_cb) (struct ce_state *ce_state, + void *transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id), + int disable_interrupts) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + spin_lock_bh(&ar_pci->ce_lock); + ce_state->send_cb = send_cb; + ath10k_ce_per_engine_handler_adjust(ce_state, disable_interrupts); + spin_unlock_bh(&ar_pci->ce_lock); +} + +void ath10k_ce_recv_cb_register(struct ce_state *ce_state, + void (*recv_cb) (struct ce_state *ce_state, + void *transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags)) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + spin_lock_bh(&ar_pci->ce_lock); + ce_state->recv_cb = recv_cb; + ath10k_ce_per_engine_handler_adjust(ce_state, 0); + spin_unlock_bh(&ar_pci->ce_lock); +} + +static int ath10k_ce_init_src_ring(struct ath10k *ar, + unsigned int ce_id, + struct ce_state *ce_state, + const struct ce_attr *attr) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_ring_state *src_ring; + unsigned int nentries = attr->src_nentries; + unsigned int ce_nbytes; + u32 ctrl_addr = ath10k_ce_base_address(ce_id); + dma_addr_t base_addr; + char *ptr; + + nentries = roundup_pow_of_two(nentries); + + if (ce_state->src_ring) { + WARN_ON(ce_state->src_ring->nentries != nentries); + return 0; + } + + ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *)); + ptr = kzalloc(ce_nbytes, GFP_KERNEL); + if (ptr == NULL) + return -ENOMEM; + + ce_state->src_ring = (struct ce_ring_state *)ptr; + src_ring = ce_state->src_ring; + + ptr += sizeof(struct ce_ring_state); + src_ring->nentries = nentries; + src_ring->nentries_mask = nentries - 1; + + ath10k_pci_wake(ar); + src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + src_ring->hw_index = src_ring->sw_index; + + src_ring->write_index = + ath10k_ce_src_ring_write_index_get(ar, ctrl_addr); + ath10k_pci_sleep(ar); + + src_ring->per_transfer_context = (void **)ptr; + + /* + * Legacy platforms that do not support cache + * coherent DMA are unsupported + */ + src_ring->base_addr_owner_space_unaligned = + pci_alloc_consistent(ar_pci->pdev, + (nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + &base_addr); + src_ring->base_addr_ce_space_unaligned = base_addr; + + src_ring->base_addr_owner_space = PTR_ALIGN( + src_ring->base_addr_owner_space_unaligned, + CE_DESC_RING_ALIGN); + src_ring->base_addr_ce_space = ALIGN( + src_ring->base_addr_ce_space_unaligned, + CE_DESC_RING_ALIGN); + + /* + * Also allocate a shadow src ring in regular + * mem to use for faster access. + */ + src_ring->shadow_base_unaligned = + kmalloc((nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), GFP_KERNEL); + + src_ring->shadow_base = PTR_ALIGN( + src_ring->shadow_base_unaligned, + CE_DESC_RING_ALIGN); + + ath10k_pci_wake(ar); + ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, + src_ring->base_addr_ce_space); + ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries); + ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, attr->src_sz_max); + ath10k_ce_src_ring_byte_swap_set(ar, ctrl_addr, 0); + ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0); + ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries); + ath10k_pci_sleep(ar); + + return 0; +} + +static int ath10k_ce_init_dest_ring(struct ath10k *ar, + unsigned int ce_id, + struct ce_state *ce_state, + const struct ce_attr *attr) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_ring_state *dest_ring; + unsigned int nentries = attr->dest_nentries; + unsigned int ce_nbytes; + u32 ctrl_addr = ath10k_ce_base_address(ce_id); + dma_addr_t base_addr; + char *ptr; + + nentries = roundup_pow_of_two(nentries); + + if (ce_state->dest_ring) { + WARN_ON(ce_state->dest_ring->nentries != nentries); + return 0; + } + + ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *)); + ptr = kzalloc(ce_nbytes, GFP_KERNEL); + if (ptr == NULL) + return -ENOMEM; + + ce_state->dest_ring = (struct ce_ring_state *)ptr; + dest_ring = ce_state->dest_ring; + + ptr += sizeof(struct ce_ring_state); + dest_ring->nentries = nentries; + dest_ring->nentries_mask = nentries - 1; + + ath10k_pci_wake(ar); + dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); + dest_ring->write_index = + ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); + ath10k_pci_sleep(ar); + + dest_ring->per_transfer_context = (void **)ptr; + + /* + * Legacy platforms that do not support cache + * coherent DMA are unsupported + */ + dest_ring->base_addr_owner_space_unaligned = + pci_alloc_consistent(ar_pci->pdev, + (nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + &base_addr); + dest_ring->base_addr_ce_space_unaligned = base_addr; + + /* + * Correctly initialize memory to 0 to prevent garbage + * data crashing system when download firmware + */ + memset(dest_ring->base_addr_owner_space_unaligned, 0, + nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN); + + dest_ring->base_addr_owner_space = PTR_ALIGN( + dest_ring->base_addr_owner_space_unaligned, + CE_DESC_RING_ALIGN); + dest_ring->base_addr_ce_space = ALIGN( + dest_ring->base_addr_ce_space_unaligned, + CE_DESC_RING_ALIGN); + + ath10k_pci_wake(ar); + ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, + dest_ring->base_addr_ce_space); + ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); + ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); + ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); + ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); + ath10k_pci_sleep(ar); + + return 0; +} + +static struct ce_state *ath10k_ce_init_state(struct ath10k *ar, + unsigned int ce_id, + const struct ce_attr *attr) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_state *ce_state = NULL; + u32 ctrl_addr = ath10k_ce_base_address(ce_id); + + spin_lock_bh(&ar_pci->ce_lock); + + if (!ar_pci->ce_id_to_state[ce_id]) { + ce_state = kzalloc(sizeof(*ce_state), GFP_ATOMIC); + if (ce_state == NULL) { + spin_unlock_bh(&ar_pci->ce_lock); + return NULL; + } + + ar_pci->ce_id_to_state[ce_id] = ce_state; + ce_state->ar = ar; + ce_state->id = ce_id; + ce_state->ctrl_addr = ctrl_addr; + ce_state->state = CE_RUNNING; + /* Save attribute flags */ + ce_state->attr_flags = attr->flags; + ce_state->src_sz_max = attr->src_sz_max; + } + + spin_unlock_bh(&ar_pci->ce_lock); + + return ce_state; +} + +/* + * Initialize a Copy Engine based on caller-supplied attributes. + * This may be called once to initialize both source and destination + * rings or it may be called twice for separate source and destination + * initialization. It may be that only one side or the other is + * initialized by software/firmware. + */ +struct ce_state *ath10k_ce_init(struct ath10k *ar, + unsigned int ce_id, + const struct ce_attr *attr) +{ + struct ce_state *ce_state; + u32 ctrl_addr = ath10k_ce_base_address(ce_id); + + ce_state = ath10k_ce_init_state(ar, ce_id, attr); + if (!ce_state) { + ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id); + return NULL; + } + + if (attr->src_nentries) { + if (ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr)) { + ath10k_err("Failed to initialize CE src ring for ID: %d\n", + ce_id); + ath10k_ce_deinit(ce_state); + return NULL; + } + } + + if (attr->dest_nentries) { + if (ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr)) { + ath10k_err("Failed to initialize CE dest ring for ID: %d\n", + ce_id); + ath10k_ce_deinit(ce_state); + return NULL; + } + } + + /* Enable CE error interrupts */ + ath10k_pci_wake(ar); + ath10k_ce_error_intr_enable(ar, ctrl_addr); + ath10k_pci_sleep(ar); + + return ce_state; +} + +void ath10k_ce_deinit(struct ce_state *ce_state) +{ + unsigned int ce_id = ce_state->id; + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + ce_state->state = CE_UNUSED; + ar_pci->ce_id_to_state[ce_id] = NULL; + + if (ce_state->src_ring) { + kfree(ce_state->src_ring->shadow_base_unaligned); + pci_free_consistent(ar_pci->pdev, + (ce_state->src_ring->nentries * + sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + ce_state->src_ring->base_addr_owner_space, + ce_state->src_ring->base_addr_ce_space); + kfree(ce_state->src_ring); + } + + if (ce_state->dest_ring) { + pci_free_consistent(ar_pci->pdev, + (ce_state->dest_ring->nentries * + sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + ce_state->dest_ring->base_addr_owner_space, + ce_state->dest_ring->base_addr_ce_space); + kfree(ce_state->dest_ring); + } + kfree(ce_state); +} diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h new file mode 100644 index 000000000000..c17f07c026f4 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -0,0 +1,516 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _CE_H_ +#define _CE_H_ + +#include "hif.h" + + +/* Maximum number of Copy Engine's supported */ +#define CE_COUNT_MAX 8 +#define CE_HTT_H2T_MSG_SRC_NENTRIES 2048 + +/* Descriptor rings must be aligned to this boundary */ +#define CE_DESC_RING_ALIGN 8 +#define CE_SENDLIST_ITEMS_MAX 12 +#define CE_SEND_FLAG_GATHER 0x00010000 + +/* + * Copy Engine support: low-level Target-side Copy Engine API. + * This is a hardware access layer used by code that understands + * how to use copy engines. + */ + +struct ce_state; + + +/* Copy Engine operational state */ +enum ce_op_state { + CE_UNUSED, + CE_PAUSED, + CE_RUNNING, +}; + +#define CE_DESC_FLAGS_GATHER (1 << 0) +#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1) +#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC +#define CE_DESC_FLAGS_META_DATA_LSB 3 + +struct ce_desc { + __le32 addr; + __le16 nbytes; + __le16 flags; /* %CE_DESC_FLAGS_ */ +}; + +/* Copy Engine Ring internal state */ +struct ce_ring_state { + /* Number of entries in this ring; must be power of 2 */ + unsigned int nentries; + unsigned int nentries_mask; + + /* + * For dest ring, this is the next index to be processed + * by software after it was/is received into. + * + * For src ring, this is the last descriptor that was sent + * and completion processed by software. + * + * Regardless of src or dest ring, this is an invariant + * (modulo ring size): + * write index >= read index >= sw_index + */ + unsigned int sw_index; + /* cached copy */ + unsigned int write_index; + /* + * For src ring, this is the next index not yet processed by HW. + * This is a cached copy of the real HW index (read index), used + * for avoiding reading the HW index register more often than + * necessary. + * This extends the invariant: + * write index >= read index >= hw_index >= sw_index + * + * For dest ring, this is currently unused. + */ + /* cached copy */ + unsigned int hw_index; + + /* Start of DMA-coherent area reserved for descriptors */ + /* Host address space */ + void *base_addr_owner_space_unaligned; + /* CE address space */ + u32 base_addr_ce_space_unaligned; + + /* + * Actual start of descriptors. + * Aligned to descriptor-size boundary. + * Points into reserved DMA-coherent area, above. + */ + /* Host address space */ + void *base_addr_owner_space; + + /* CE address space */ + u32 base_addr_ce_space; + /* + * Start of shadow copy of descriptors, within regular memory. + * Aligned to descriptor-size boundary. + */ + void *shadow_base_unaligned; + struct ce_desc *shadow_base; + + void **per_transfer_context; +}; + +/* Copy Engine internal state */ +struct ce_state { + struct ath10k *ar; + unsigned int id; + + unsigned int attr_flags; + + u32 ctrl_addr; + enum ce_op_state state; + + void (*send_cb) (struct ce_state *ce_state, + void *per_transfer_send_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id); + void (*recv_cb) (struct ce_state *ce_state, + void *per_transfer_recv_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags); + + unsigned int src_sz_max; + struct ce_ring_state *src_ring; + struct ce_ring_state *dest_ring; +}; + +struct ce_sendlist_item { + /* e.g. buffer or desc list */ + dma_addr_t data; + union { + /* simple buffer */ + unsigned int nbytes; + /* Rx descriptor list */ + unsigned int ndesc; + } u; + /* externally-specified flags; OR-ed with internal flags */ + u32 flags; +}; + +struct ce_sendlist { + unsigned int num_items; + struct ce_sendlist_item item[CE_SENDLIST_ITEMS_MAX]; +}; + +/* Copy Engine settable attributes */ +struct ce_attr; + +/*==================Send====================*/ + +/* ath10k_ce_send flags */ +#define CE_SEND_FLAG_BYTE_SWAP 1 + +/* + * Queue a source buffer to be sent to an anonymous destination buffer. + * ce - which copy engine to use + * buffer - address of buffer + * nbytes - number of bytes to send + * transfer_id - arbitrary ID; reflected to destination + * flags - CE_SEND_FLAG_* values + * Returns 0 on success; otherwise an error status. + * + * Note: If no flags are specified, use CE's default data swap mode. + * + * Implementation note: pushes 1 buffer to Source ring + */ +int ath10k_ce_send(struct ce_state *ce_state, + void *per_transfer_send_context, + u32 buffer, + unsigned int nbytes, + /* 14 bits */ + unsigned int transfer_id, + unsigned int flags); + +void ath10k_ce_send_cb_register(struct ce_state *ce_state, + void (*send_cb) (struct ce_state *ce_state, + void *transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id), + int disable_interrupts); + +/* Append a simple buffer (address/length) to a sendlist. */ +void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist, + u32 buffer, + unsigned int nbytes, + /* OR-ed with internal flags */ + u32 flags); + +/* + * Queue a "sendlist" of buffers to be sent using gather to a single + * anonymous destination buffer + * ce - which copy engine to use + * sendlist - list of simple buffers to send using gather + * transfer_id - arbitrary ID; reflected to destination + * Returns 0 on success; otherwise an error status. + * + * Implemenation note: Pushes multiple buffers with Gather to Source ring. + */ +int ath10k_ce_sendlist_send(struct ce_state *ce_state, + void *per_transfer_send_context, + struct ce_sendlist *sendlist, + /* 14 bits */ + unsigned int transfer_id); + +/*==================Recv=======================*/ + +/* + * Make a buffer available to receive. The buffer must be at least of a + * minimal size appropriate for this copy engine (src_sz_max attribute). + * ce - which copy engine to use + * per_transfer_recv_context - context passed back to caller's recv_cb + * buffer - address of buffer in CE space + * Returns 0 on success; otherwise an error status. + * + * Implemenation note: Pushes a buffer to Dest ring. + */ +int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state, + void *per_transfer_recv_context, + u32 buffer); + +void ath10k_ce_recv_cb_register(struct ce_state *ce_state, + void (*recv_cb) (struct ce_state *ce_state, + void *transfer_context, + u32 buffer, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags)); + +/* recv flags */ +/* Data is byte-swapped */ +#define CE_RECV_FLAG_SWAPPED 1 + +/* + * Supply data for the next completed unprocessed receive descriptor. + * Pops buffer from Dest ring. + */ +int ath10k_ce_completed_recv_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp, + unsigned int *flagsp); +/* + * Supply data for the next completed unprocessed send descriptor. + * Pops 1 completed send buffer from Source ring. + */ +int ath10k_ce_completed_send_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp); + +/*==================CE Engine Initialization=======================*/ + +/* Initialize an instance of a CE */ +struct ce_state *ath10k_ce_init(struct ath10k *ar, + unsigned int ce_id, + const struct ce_attr *attr); + +/*==================CE Engine Shutdown=======================*/ +/* + * Support clean shutdown by allowing the caller to revoke + * receive buffers. Target DMA must be stopped before using + * this API. + */ +int ath10k_ce_revoke_recv_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp); + +/* + * Support clean shutdown by allowing the caller to cancel + * pending sends. Target DMA must be stopped before using + * this API. + */ +int ath10k_ce_cancel_send_next(struct ce_state *ce_state, + void **per_transfer_contextp, + u32 *bufferp, + unsigned int *nbytesp, + unsigned int *transfer_idp); + +void ath10k_ce_deinit(struct ce_state *ce_state); + +/*==================CE Interrupt Handlers====================*/ +void ath10k_ce_per_engine_service_any(struct ath10k *ar); +void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); +void ath10k_ce_disable_interrupts(struct ath10k *ar); + +/* ce_attr.flags values */ +/* Use NonSnooping PCIe accesses? */ +#define CE_ATTR_NO_SNOOP 1 + +/* Byte swap data words */ +#define CE_ATTR_BYTE_SWAP_DATA 2 + +/* Swizzle descriptors? */ +#define CE_ATTR_SWIZZLE_DESCRIPTORS 4 + +/* no interrupt on copy completion */ +#define CE_ATTR_DIS_INTR 8 + +/* Attributes of an instance of a Copy Engine */ +struct ce_attr { + /* CE_ATTR_* values */ + unsigned int flags; + + /* currently not in use */ + unsigned int priority; + + /* #entries in source ring - Must be a power of 2 */ + unsigned int src_nentries; + + /* + * Max source send size for this CE. + * This is also the minimum size of a destination buffer. + */ + unsigned int src_sz_max; + + /* #entries in destination ring - Must be a power of 2 */ + unsigned int dest_nentries; + + /* Future use */ + void *reserved; +}; + +/* + * When using sendlist_send to transfer multiple buffer fragments, the + * transfer context of each fragment, except last one, will be filled + * with CE_SENDLIST_ITEM_CTXT. ce_completed_send will return success for + * each fragment done with send and the transfer context would be + * CE_SENDLIST_ITEM_CTXT. Upper layer could use this to identify the + * status of a send completion. + */ +#define CE_SENDLIST_ITEM_CTXT ((void *)0xcecebeef) + +#define SR_BA_ADDRESS 0x0000 +#define SR_SIZE_ADDRESS 0x0004 +#define DR_BA_ADDRESS 0x0008 +#define DR_SIZE_ADDRESS 0x000c +#define CE_CMD_ADDRESS 0x0018 + +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 17 +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 +#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \ + (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \ + CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) + +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16 +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \ + (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \ + CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) +#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \ + (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \ + CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) + +#define CE_CTRL1_DMAX_LENGTH_MSB 15 +#define CE_CTRL1_DMAX_LENGTH_LSB 0 +#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff +#define CE_CTRL1_DMAX_LENGTH_GET(x) \ + (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB) +#define CE_CTRL1_DMAX_LENGTH_SET(x) \ + (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) + +#define CE_CTRL1_ADDRESS 0x0010 +#define CE_CTRL1_HW_MASK 0x0007ffff +#define CE_CTRL1_SW_MASK 0x0007ffff +#define CE_CTRL1_HW_WRITE_MASK 0x00000000 +#define CE_CTRL1_SW_WRITE_MASK 0x0007ffff +#define CE_CTRL1_RSTMASK 0xffffffff +#define CE_CTRL1_RESET 0x00000080 + +#define CE_CMD_HALT_STATUS_MSB 3 +#define CE_CMD_HALT_STATUS_LSB 3 +#define CE_CMD_HALT_STATUS_MASK 0x00000008 +#define CE_CMD_HALT_STATUS_GET(x) \ + (((x) & CE_CMD_HALT_STATUS_MASK) >> CE_CMD_HALT_STATUS_LSB) +#define CE_CMD_HALT_STATUS_SET(x) \ + (((0 | (x)) << CE_CMD_HALT_STATUS_LSB) & CE_CMD_HALT_STATUS_MASK) +#define CE_CMD_HALT_STATUS_RESET 0 +#define CE_CMD_HALT_MSB 0 +#define CE_CMD_HALT_MASK 0x00000001 + +#define HOST_IE_COPY_COMPLETE_MSB 0 +#define HOST_IE_COPY_COMPLETE_LSB 0 +#define HOST_IE_COPY_COMPLETE_MASK 0x00000001 +#define HOST_IE_COPY_COMPLETE_GET(x) \ + (((x) & HOST_IE_COPY_COMPLETE_MASK) >> HOST_IE_COPY_COMPLETE_LSB) +#define HOST_IE_COPY_COMPLETE_SET(x) \ + (((0 | (x)) << HOST_IE_COPY_COMPLETE_LSB) & HOST_IE_COPY_COMPLETE_MASK) +#define HOST_IE_COPY_COMPLETE_RESET 0 +#define HOST_IE_ADDRESS 0x002c + +#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 +#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 +#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 +#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 +#define HOST_IS_COPY_COMPLETE_MASK 0x00000001 +#define HOST_IS_ADDRESS 0x0030 + +#define MISC_IE_ADDRESS 0x0034 + +#define MISC_IS_AXI_ERR_MASK 0x00000400 + +#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200 +#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100 +#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 +#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 +#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 + +#define MISC_IS_ADDRESS 0x0038 + +#define SR_WR_INDEX_ADDRESS 0x003c + +#define DST_WR_INDEX_ADDRESS 0x0040 + +#define CURRENT_SRRI_ADDRESS 0x0044 + +#define CURRENT_DRRI_ADDRESS 0x0048 + +#define SRC_WATERMARK_LOW_MSB 31 +#define SRC_WATERMARK_LOW_LSB 16 +#define SRC_WATERMARK_LOW_MASK 0xffff0000 +#define SRC_WATERMARK_LOW_GET(x) \ + (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB) +#define SRC_WATERMARK_LOW_SET(x) \ + (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) +#define SRC_WATERMARK_LOW_RESET 0 +#define SRC_WATERMARK_HIGH_MSB 15 +#define SRC_WATERMARK_HIGH_LSB 0 +#define SRC_WATERMARK_HIGH_MASK 0x0000ffff +#define SRC_WATERMARK_HIGH_GET(x) \ + (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB) +#define SRC_WATERMARK_HIGH_SET(x) \ + (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) +#define SRC_WATERMARK_HIGH_RESET 0 +#define SRC_WATERMARK_ADDRESS 0x004c + +#define DST_WATERMARK_LOW_LSB 16 +#define DST_WATERMARK_LOW_MASK 0xffff0000 +#define DST_WATERMARK_LOW_SET(x) \ + (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) +#define DST_WATERMARK_LOW_RESET 0 +#define DST_WATERMARK_HIGH_MSB 15 +#define DST_WATERMARK_HIGH_LSB 0 +#define DST_WATERMARK_HIGH_MASK 0x0000ffff +#define DST_WATERMARK_HIGH_GET(x) \ + (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB) +#define DST_WATERMARK_HIGH_SET(x) \ + (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) +#define DST_WATERMARK_HIGH_RESET 0 +#define DST_WATERMARK_ADDRESS 0x0050 + + +static inline u32 ath10k_ce_base_address(unsigned int ce_id) +{ + return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; +} + +#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \ + HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \ + HOST_IS_DST_RING_LOW_WATERMARK_MASK | \ + HOST_IS_DST_RING_HIGH_WATERMARK_MASK) + +#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \ + MISC_IS_DST_ADDR_ERR_MASK | \ + MISC_IS_SRC_LEN_ERR_MASK | \ + MISC_IS_DST_MAX_LEN_VIO_MASK | \ + MISC_IS_DST_RING_OVERFLOW_MASK | \ + MISC_IS_SRC_RING_OVERFLOW_MASK) + +#define CE_SRC_RING_TO_DESC(baddr, idx) \ + (&(((struct ce_desc *)baddr)[idx])) + +#define CE_DEST_RING_TO_DESC(baddr, idx) \ + (&(((struct ce_desc *)baddr)[idx])) + +/* Ring arithmetic (modulus number of entries in ring, which is a pwr of 2). */ +#define CE_RING_DELTA(nentries_mask, fromidx, toidx) \ + (((int)(toidx)-(int)(fromidx)) & (nentries_mask)) + +#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) + +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB 8 +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK 0x0000ff00 +#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) \ + (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \ + CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) +#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 + +#define CE_INTERRUPT_SUMMARY(ar) \ + CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ + ath10k_pci_read32((ar), CE_WRAPPER_BASE_ADDRESS + \ + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) + +#endif /* _CE_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c new file mode 100644 index 000000000000..2b3426b1ff3f --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "core.h" +#include "mac.h" +#include "htc.h" +#include "hif.h" +#include "wmi.h" +#include "bmi.h" +#include "debug.h" +#include "htt.h" + +unsigned int ath10k_debug_mask; +static bool uart_print; +static unsigned int ath10k_p2p; +module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); +module_param(uart_print, bool, 0644); +module_param_named(p2p, ath10k_p2p, uint, 0644); +MODULE_PARM_DESC(debug_mask, "Debugging mask"); +MODULE_PARM_DESC(uart_print, "Uart target debugging"); +MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); + +static const struct ath10k_hw_params ath10k_hw_params_list[] = { + { + .id = QCA988X_HW_1_0_VERSION, + .name = "qca988x hw1.0", + .patch_load_addr = QCA988X_HW_1_0_PATCH_LOAD_ADDR, + .fw = { + .dir = QCA988X_HW_1_0_FW_DIR, + .fw = QCA988X_HW_1_0_FW_FILE, + .otp = QCA988X_HW_1_0_OTP_FILE, + .board = QCA988X_HW_1_0_BOARD_DATA_FILE, + }, + }, + { + .id = QCA988X_HW_2_0_VERSION, + .name = "qca988x hw2.0", + .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, + .fw = { + .dir = QCA988X_HW_2_0_FW_DIR, + .fw = QCA988X_HW_2_0_FW_FILE, + .otp = QCA988X_HW_2_0_OTP_FILE, + .board = QCA988X_HW_2_0_BOARD_DATA_FILE, + }, + }, +}; + +static void ath10k_send_suspend_complete(struct ath10k *ar) +{ + ath10k_dbg(ATH10K_DBG_CORE, "%s\n", __func__); + + ar->is_target_paused = true; + wake_up(&ar->event_queue); +} + +static int ath10k_check_fw_version(struct ath10k *ar) +{ + char version[32]; + + if (ar->fw_version_major >= SUPPORTED_FW_MAJOR && + ar->fw_version_minor >= SUPPORTED_FW_MINOR && + ar->fw_version_release >= SUPPORTED_FW_RELEASE && + ar->fw_version_build >= SUPPORTED_FW_BUILD) + return 0; + + snprintf(version, sizeof(version), "%u.%u.%u.%u", + SUPPORTED_FW_MAJOR, SUPPORTED_FW_MINOR, + SUPPORTED_FW_RELEASE, SUPPORTED_FW_BUILD); + + ath10k_warn("WARNING: Firmware version %s is not officially supported.\n", + ar->hw->wiphy->fw_version); + ath10k_warn("Please upgrade to version %s (or newer)\n", version); + + return 0; +} + +static int ath10k_init_connect_htc(struct ath10k *ar) +{ + int status; + + status = ath10k_wmi_connect_htc_service(ar); + if (status) + goto conn_fail; + + /* Start HTC */ + status = ath10k_htc_start(ar->htc); + if (status) + goto conn_fail; + + /* Wait for WMI event to be ready */ + status = ath10k_wmi_wait_for_service_ready(ar); + if (status <= 0) { + ath10k_warn("wmi service ready event not received"); + status = -ETIMEDOUT; + goto timeout; + } + + ath10k_dbg(ATH10K_DBG_CORE, "core wmi ready\n"); + return 0; + +timeout: + ath10k_htc_stop(ar->htc); +conn_fail: + return status; +} + +static int ath10k_init_configure_target(struct ath10k *ar) +{ + u32 param_host; + int ret; + + /* tell target which HTC version it is used*/ + ret = ath10k_bmi_write32(ar, hi_app_host_interest, + HTC_PROTOCOL_VERSION); + if (ret) { + ath10k_err("settings HTC version failed\n"); + return ret; + } + + /* set the firmware mode to STA/IBSS/AP */ + ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m_host); + if (ret) { + ath10k_err("setting firmware mode (1/2) failed\n"); + return ret; + } + + /* TODO following parameters need to be re-visited. */ + /* num_device */ + param_host |= (1 << HI_OPTION_NUM_DEV_SHIFT); + /* Firmware mode */ + /* FIXME: Why FW_MODE_AP ??.*/ + param_host |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT); + /* mac_addr_method */ + param_host |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); + /* firmware_bridge */ + param_host |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); + /* fwsubmode */ + param_host |= (0 << HI_OPTION_FW_SUBMODE_SHIFT); + + ret = ath10k_bmi_write32(ar, hi_option_flag, param_host); + if (ret) { + ath10k_err("setting firmware mode (2/2) failed\n"); + return ret; + } + + /* We do all byte-swapping on the host */ + ret = ath10k_bmi_write32(ar, hi_be, 0); + if (ret) { + ath10k_err("setting host CPU BE mode failed\n"); + return ret; + } + + /* FW descriptor/Data swap flags */ + ret = ath10k_bmi_write32(ar, hi_fw_swap, 0); + + if (ret) { + ath10k_err("setting FW data/desc swap flags failed\n"); + return ret; + } + + return 0; +} + +static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, + const char *dir, + const char *file) +{ + char filename[100]; + const struct firmware *fw; + int ret; + + if (file == NULL) + return ERR_PTR(-ENOENT); + + if (dir == NULL) + dir = "."; + + snprintf(filename, sizeof(filename), "%s/%s", dir, file); + ret = request_firmware(&fw, filename, ar->dev); + if (ret) + return ERR_PTR(ret); + + return fw; +} + +static int ath10k_push_board_ext_data(struct ath10k *ar, + const struct firmware *fw) +{ + u32 board_data_size = QCA988X_BOARD_DATA_SZ; + u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; + u32 board_ext_data_addr; + int ret; + + ret = ath10k_bmi_read32(ar, hi_board_ext_data, &board_ext_data_addr); + if (ret) { + ath10k_err("could not read board ext data addr (%d)\n", ret); + return ret; + } + + ath10k_dbg(ATH10K_DBG_CORE, + "ath10k: Board extended Data download addr: 0x%x\n", + board_ext_data_addr); + + if (board_ext_data_addr == 0) + return 0; + + if (fw->size != (board_data_size + board_ext_data_size)) { + ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", + fw->size, board_data_size, board_ext_data_size); + return -EINVAL; + } + + ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, + fw->data + board_data_size, + board_ext_data_size); + if (ret) { + ath10k_err("could not write board ext data (%d)\n", ret); + return ret; + } + + ret = ath10k_bmi_write32(ar, hi_board_ext_data_config, + (board_ext_data_size << 16) | 1); + if (ret) { + ath10k_err("could not write board ext data bit (%d)\n", ret); + return ret; + } + + return 0; +} + +static int ath10k_download_board_data(struct ath10k *ar) +{ + u32 board_data_size = QCA988X_BOARD_DATA_SZ; + u32 address; + const struct firmware *fw; + int ret; + + fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, + ar->hw_params.fw.board); + if (IS_ERR(fw)) { + ath10k_err("could not fetch board data fw file (%ld)\n", + PTR_ERR(fw)); + return PTR_ERR(fw); + } + + ret = ath10k_push_board_ext_data(ar, fw); + if (ret) { + ath10k_err("could not push board ext data (%d)\n", ret); + goto exit; + } + + ret = ath10k_bmi_read32(ar, hi_board_data, &address); + if (ret) { + ath10k_err("could not read board data addr (%d)\n", ret); + goto exit; + } + + ret = ath10k_bmi_write_memory(ar, address, fw->data, + min_t(u32, board_data_size, fw->size)); + if (ret) { + ath10k_err("could not write board data (%d)\n", ret); + goto exit; + } + + ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1); + if (ret) { + ath10k_err("could not write board data bit (%d)\n", ret); + goto exit; + } + +exit: + release_firmware(fw); + return ret; +} + +static int ath10k_download_and_run_otp(struct ath10k *ar) +{ + const struct firmware *fw; + u32 address; + u32 exec_param; + int ret; + + /* OTP is optional */ + + if (ar->hw_params.fw.otp == NULL) { + ath10k_info("otp file not defined\n"); + return 0; + } + + address = ar->hw_params.patch_load_addr; + + fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, + ar->hw_params.fw.otp); + if (IS_ERR(fw)) { + ath10k_warn("could not fetch otp (%ld)\n", PTR_ERR(fw)); + return 0; + } + + ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); + if (ret) { + ath10k_err("could not write otp (%d)\n", ret); + goto exit; + } + + exec_param = 0; + ret = ath10k_bmi_execute(ar, address, &exec_param); + if (ret) { + ath10k_err("could not execute otp (%d)\n", ret); + goto exit; + } + +exit: + release_firmware(fw); + return ret; +} + +static int ath10k_download_fw(struct ath10k *ar) +{ + const struct firmware *fw; + u32 address; + int ret; + + if (ar->hw_params.fw.fw == NULL) + return -EINVAL; + + address = ar->hw_params.patch_load_addr; + + fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, + ar->hw_params.fw.fw); + if (IS_ERR(fw)) { + ath10k_err("could not fetch fw (%ld)\n", PTR_ERR(fw)); + return PTR_ERR(fw); + } + + ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); + if (ret) { + ath10k_err("could not write fw (%d)\n", ret); + goto exit; + } + +exit: + release_firmware(fw); + return ret; +} + +static int ath10k_init_download_firmware(struct ath10k *ar) +{ + int ret; + + ret = ath10k_download_board_data(ar); + if (ret) + return ret; + + ret = ath10k_download_and_run_otp(ar); + if (ret) + return ret; + + ret = ath10k_download_fw(ar); + if (ret) + return ret; + + return ret; +} + +static int ath10k_init_uart(struct ath10k *ar) +{ + int ret; + + /* + * Explicitly setting UART prints to zero as target turns it on + * based on scratch registers. + */ + ret = ath10k_bmi_write32(ar, hi_serial_enable, 0); + if (ret) { + ath10k_warn("could not disable UART prints (%d)\n", ret); + return ret; + } + + if (!uart_print) { + ath10k_info("UART prints disabled\n"); + return 0; + } + + ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7); + if (ret) { + ath10k_warn("could not enable UART prints (%d)\n", ret); + return ret; + } + + ret = ath10k_bmi_write32(ar, hi_serial_enable, 1); + if (ret) { + ath10k_warn("could not enable UART prints (%d)\n", ret); + return ret; + } + + ath10k_info("UART prints enabled\n"); + return 0; +} + +static int ath10k_init_hw_params(struct ath10k *ar) +{ + const struct ath10k_hw_params *uninitialized_var(hw_params); + int i; + + for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) { + hw_params = &ath10k_hw_params_list[i]; + + if (hw_params->id == ar->target_version) + break; + } + + if (i == ARRAY_SIZE(ath10k_hw_params_list)) { + ath10k_err("Unsupported hardware version: 0x%x\n", + ar->target_version); + return -EINVAL; + } + + ar->hw_params = *hw_params; + + ath10k_info("Hardware name %s version 0x%x\n", + ar->hw_params.name, ar->target_version); + + return 0; +} + +struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, + enum ath10k_bus bus, + const struct ath10k_hif_ops *hif_ops) +{ + struct ath10k *ar; + + ar = ath10k_mac_create(); + if (!ar) + return NULL; + + ar->ath_common.priv = ar; + ar->ath_common.hw = ar->hw; + + ar->p2p = !!ath10k_p2p; + ar->dev = dev; + + ar->hif.priv = hif_priv; + ar->hif.ops = hif_ops; + ar->hif.bus = bus; + + ar->free_vdev_map = 0xFF; /* 8 vdevs */ + + init_completion(&ar->scan.started); + init_completion(&ar->scan.completed); + init_completion(&ar->scan.on_channel); + + init_completion(&ar->install_key_done); + init_completion(&ar->vdev_setup_done); + + setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar); + + ar->workqueue = create_singlethread_workqueue("ath10k_wq"); + if (!ar->workqueue) + goto err_wq; + + mutex_init(&ar->conf_mutex); + spin_lock_init(&ar->data_lock); + + INIT_LIST_HEAD(&ar->peers); + init_waitqueue_head(&ar->peer_mapping_wq); + + init_completion(&ar->offchan_tx_completed); + INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); + skb_queue_head_init(&ar->offchan_tx_queue); + + init_waitqueue_head(&ar->event_queue); + + return ar; + +err_wq: + ath10k_mac_destroy(ar); + return NULL; +} +EXPORT_SYMBOL(ath10k_core_create); + +void ath10k_core_destroy(struct ath10k *ar) +{ + flush_workqueue(ar->workqueue); + destroy_workqueue(ar->workqueue); + + ath10k_mac_destroy(ar); +} +EXPORT_SYMBOL(ath10k_core_destroy); + + +int ath10k_core_register(struct ath10k *ar) +{ + struct ath10k_htc_ops htc_ops; + struct bmi_target_info target_info; + int status; + + memset(&target_info, 0, sizeof(target_info)); + status = ath10k_bmi_get_target_info(ar, &target_info); + if (status) + goto err; + + ar->target_version = target_info.version; + ar->hw->wiphy->hw_version = target_info.version; + + status = ath10k_init_hw_params(ar); + if (status) + goto err; + + if (ath10k_init_configure_target(ar)) { + status = -EINVAL; + goto err; + } + + status = ath10k_init_download_firmware(ar); + if (status) + goto err; + + status = ath10k_init_uart(ar); + if (status) + goto err; + + htc_ops.target_send_suspend_complete = ath10k_send_suspend_complete; + + ar->htc = ath10k_htc_create(ar, &htc_ops); + if (IS_ERR(ar->htc)) { + status = PTR_ERR(ar->htc); + ath10k_err("could not create HTC (%d)\n", status); + goto err; + } + + status = ath10k_bmi_done(ar); + if (status) + goto err_htc_destroy; + + status = ath10k_wmi_attach(ar); + if (status) { + ath10k_err("WMI attach failed: %d\n", status); + goto err_htc_destroy; + } + + status = ath10k_htc_wait_target(ar->htc); + if (status) + goto err_wmi_detach; + + ar->htt = ath10k_htt_attach(ar); + if (!ar->htt) { + status = -ENOMEM; + goto err_wmi_detach; + } + + status = ath10k_init_connect_htc(ar); + if (status) + goto err_htt_detach; + + ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); + + status = ath10k_check_fw_version(ar); + if (status) + goto err_disconnect_htc; + + status = ath10k_wmi_cmd_init(ar); + if (status) { + ath10k_err("could not send WMI init command (%d)\n", status); + goto err_disconnect_htc; + } + + status = ath10k_wmi_wait_for_unified_ready(ar); + if (status <= 0) { + ath10k_err("wmi unified ready event not received\n"); + status = -ETIMEDOUT; + goto err_disconnect_htc; + } + + status = ath10k_htt_attach_target(ar->htt); + if (status) + goto err_disconnect_htc; + + status = ath10k_mac_register(ar); + if (status) + goto err_disconnect_htc; + + status = ath10k_debug_create(ar); + if (status) { + ath10k_err("unable to initialize debugfs\n"); + goto err_unregister_mac; + } + + return 0; + +err_unregister_mac: + ath10k_mac_unregister(ar); +err_disconnect_htc: + ath10k_htc_stop(ar->htc); +err_htt_detach: + ath10k_htt_detach(ar->htt); +err_wmi_detach: + ath10k_wmi_detach(ar); +err_htc_destroy: + ath10k_htc_destroy(ar->htc); +err: + return status; +} +EXPORT_SYMBOL(ath10k_core_register); + +void ath10k_core_unregister(struct ath10k *ar) +{ + /* We must unregister from mac80211 before we stop HTC and HIF. + * Otherwise we will fail to submit commands to FW and mac80211 will be + * unhappy about callback failures. */ + ath10k_mac_unregister(ar); + ath10k_htc_stop(ar->htc); + ath10k_htt_detach(ar->htt); + ath10k_wmi_detach(ar); + ath10k_htc_destroy(ar->htc); +} +EXPORT_SYMBOL(ath10k_core_unregister); + +int ath10k_core_target_suspend(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__); + + ret = ath10k_wmi_pdev_suspend_target(ar); + if (ret) + ath10k_warn("could not suspend target (%d)\n", ret); + + return ret; +} +EXPORT_SYMBOL(ath10k_core_target_suspend); + +int ath10k_core_target_resume(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__); + + ret = ath10k_wmi_pdev_resume_target(ar); + if (ret) + ath10k_warn("could not resume target (%d)\n", ret); + + return ret; +} +EXPORT_SYMBOL(ath10k_core_target_resume); + +MODULE_AUTHOR("Qualcomm Atheros"); +MODULE_DESCRIPTION("Core module for QCA988X PCIe devices."); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h new file mode 100644 index 000000000000..539336d1be4b --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _CORE_H_ +#define _CORE_H_ + +#include +#include +#include +#include + +#include "htc.h" +#include "hw.h" +#include "targaddrs.h" +#include "wmi.h" +#include "../ath.h" +#include "../regd.h" + +#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) +#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) +#define WO(_f) ((_f##_OFFSET) >> 2) + +#define ATH10K_SCAN_ID 0 +#define WMI_READY_TIMEOUT (5 * HZ) +#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ) + +/* Antenna noise floor */ +#define ATH10K_DEFAULT_NOISE_FLOOR -95 + +struct ath10k; + +enum ath10k_bus { + ATH10K_BUS_PCI, +}; + +struct ath10k_skb_cb { + dma_addr_t paddr; + bool is_mapped; + bool is_aborted; + + struct { + u8 vdev_id; + u16 msdu_id; + u8 tid; + bool is_offchan; + bool is_conf; + bool discard; + bool no_ack; + u8 refcount; + struct sk_buff *txfrag; + struct sk_buff *msdu; + } __packed htt; + + /* 4 bytes left on 64bit arch */ +} __packed; + +static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) > + IEEE80211_TX_INFO_DRIVER_DATA_SIZE); + return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data; +} + +static inline int ath10k_skb_map(struct device *dev, struct sk_buff *skb) +{ + if (ATH10K_SKB_CB(skb)->is_mapped) + return -EINVAL; + + ATH10K_SKB_CB(skb)->paddr = dma_map_single(dev, skb->data, skb->len, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(dev, ATH10K_SKB_CB(skb)->paddr))) + return -EIO; + + ATH10K_SKB_CB(skb)->is_mapped = true; + return 0; +} + +static inline int ath10k_skb_unmap(struct device *dev, struct sk_buff *skb) +{ + if (!ATH10K_SKB_CB(skb)->is_mapped) + return -EINVAL; + + dma_unmap_single(dev, ATH10K_SKB_CB(skb)->paddr, skb->len, + DMA_TO_DEVICE); + ATH10K_SKB_CB(skb)->is_mapped = false; + return 0; +} + +static inline u32 host_interest_item_address(u32 item_offset) +{ + return QCA988X_HOST_INTEREST_ADDRESS + item_offset; +} + +struct ath10k_bmi { + bool done_sent; +}; + +struct ath10k_wmi { + enum ath10k_htc_ep_id eid; + struct completion service_ready; + struct completion unified_ready; + atomic_t pending_tx_count; + wait_queue_head_t wq; + + struct sk_buff_head wmi_event_list; + struct work_struct wmi_event_work; +}; + +struct ath10k_peer_stat { + u8 peer_macaddr[ETH_ALEN]; + u32 peer_rssi; + u32 peer_tx_rate; +}; + +struct ath10k_target_stats { + /* PDEV stats */ + s32 ch_noise_floor; + u32 tx_frame_count; + u32 rx_frame_count; + u32 rx_clear_count; + u32 cycle_count; + u32 phy_err_count; + u32 chan_tx_power; + + /* PDEV TX stats */ + s32 comp_queued; + s32 comp_delivered; + s32 msdu_enqued; + s32 mpdu_enqued; + s32 wmm_drop; + s32 local_enqued; + s32 local_freed; + s32 hw_queued; + s32 hw_reaped; + s32 underrun; + s32 tx_abort; + s32 mpdus_requed; + u32 tx_ko; + u32 data_rc; + u32 self_triggers; + u32 sw_retry_failure; + u32 illgl_rate_phy_err; + u32 pdev_cont_xretry; + u32 pdev_tx_timeout; + u32 pdev_resets; + u32 phy_underrun; + u32 txop_ovf; + + /* PDEV RX stats */ + s32 mid_ppdu_route_change; + s32 status_rcvd; + s32 r0_frags; + s32 r1_frags; + s32 r2_frags; + s32 r3_frags; + s32 htt_msdus; + s32 htt_mpdus; + s32 loc_msdus; + s32 loc_mpdus; + s32 oversize_amsdu; + s32 phy_errs; + s32 phy_err_drop; + s32 mpdu_errs; + + /* VDEV STATS */ + + /* PEER STATS */ + u8 peers; + struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS]; + + /* TODO: Beacon filter stats */ + +}; + +#define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */ + +struct ath10k_peer { + struct list_head list; + int vdev_id; + u8 addr[ETH_ALEN]; + DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; +}; + +#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) + +struct ath10k_vif { + u32 vdev_id; + enum wmi_vdev_type vdev_type; + enum wmi_vdev_subtype vdev_subtype; + u32 beacon_interval; + u32 dtim_period; + + struct ath10k *ar; + struct ieee80211_vif *vif; + + struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; + u8 def_wep_key_index; + + u16 tx_seq_no; + + union { + struct { + u8 bssid[ETH_ALEN]; + u32 uapsd; + } sta; + struct { + /* 127 stations; wmi limit */ + u8 tim_bitmap[16]; + u8 tim_len; + u32 ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + bool hidden_ssid; + /* P2P_IE with NoA attribute for P2P_GO case */ + u32 noa_len; + u8 *noa_data; + } ap; + struct { + u8 bssid[ETH_ALEN]; + } ibss; + } u; +}; + +struct ath10k_vif_iter { + u32 vdev_id; + struct ath10k_vif *arvif; +}; + +struct ath10k_debug { + struct dentry *debugfs_phy; + + struct ath10k_target_stats target_stats; + u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; + + struct completion event_stats_compl; +}; + +struct ath10k { + struct ath_common ath_common; + struct ieee80211_hw *hw; + struct device *dev; + u8 mac_addr[ETH_ALEN]; + + u32 target_version; + u8 fw_version_major; + u32 fw_version_minor; + u16 fw_version_release; + u16 fw_version_build; + u32 phy_capability; + u32 hw_min_tx_power; + u32 hw_max_tx_power; + u32 ht_cap_info; + u32 vht_cap_info; + + struct targetdef *targetdef; + struct hostdef *hostdef; + + bool p2p; + + struct { + void *priv; + enum ath10k_bus bus; + const struct ath10k_hif_ops *ops; + } hif; + + struct ath10k_wmi wmi; + + wait_queue_head_t event_queue; + bool is_target_paused; + + struct ath10k_bmi bmi; + + struct ath10k_htc *htc; + struct ath10k_htt *htt; + + struct ath10k_hw_params { + u32 id; + const char *name; + u32 patch_load_addr; + + struct ath10k_hw_params_fw { + const char *dir; + const char *fw; + const char *otp; + const char *board; + } fw; + } hw_params; + + struct { + struct completion started; + struct completion completed; + struct completion on_channel; + struct timer_list timeout; + bool is_roc; + bool in_progress; + bool aborting; + int vdev_id; + int roc_freq; + } scan; + + struct { + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; + } mac; + + /* should never be NULL; needed for regular htt rx */ + struct ieee80211_channel *rx_channel; + + /* valid during scan; needed for mgmt rx during scan */ + struct ieee80211_channel *scan_channel; + + int free_vdev_map; + int monitor_vdev_id; + bool monitor_enabled; + bool monitor_present; + unsigned int filter_flags; + + struct wmi_pdev_set_wmm_params_arg wmm_params; + struct completion install_key_done; + + struct completion vdev_setup_done; + + struct workqueue_struct *workqueue; + + /* prevents concurrent FW reconfiguration */ + struct mutex conf_mutex; + + /* protects shared structure data */ + spinlock_t data_lock; + + struct list_head peers; + wait_queue_head_t peer_mapping_wq; + + struct work_struct offchan_tx_work; + struct sk_buff_head offchan_tx_queue; + struct completion offchan_tx_completed; + struct sk_buff *offchan_tx_skb; + +#ifdef CONFIG_ATH10K_DEBUGFS + struct ath10k_debug debug; +#endif +}; + +struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, + enum ath10k_bus bus, + const struct ath10k_hif_ops *hif_ops); +void ath10k_core_destroy(struct ath10k *ar); + +int ath10k_core_register(struct ath10k *ar); +void ath10k_core_unregister(struct ath10k *ar); + +int ath10k_core_target_suspend(struct ath10k *ar); +int ath10k_core_target_resume(struct ath10k *ar); + +#endif /* _CORE_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c new file mode 100644 index 000000000000..499034b873d1 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "core.h" +#include "debug.h" + +static int ath10k_printk(const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int rtn; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + rtn = printk("%sath10k: %pV", level, &vaf); + + va_end(args); + + return rtn; +} + +int ath10k_info(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = ath10k_printk(KERN_INFO, "%pV", &vaf); + trace_ath10k_log_info(&vaf); + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath10k_info); + +int ath10k_err(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = ath10k_printk(KERN_ERR, "%pV", &vaf); + trace_ath10k_log_err(&vaf); + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath10k_err); + +int ath10k_warn(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret = 0; + + va_start(args, fmt); + vaf.va = &args; + + if (net_ratelimit()) + ret = ath10k_printk(KERN_WARNING, "%pV", &vaf); + + trace_ath10k_log_warn(&vaf); + + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath10k_warn); + +#ifdef CONFIG_ATH10K_DEBUGFS + +void ath10k_debug_read_service_map(struct ath10k *ar, + void *service_map, + size_t map_size) +{ + memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); +} + +static ssize_t ath10k_read_wmi_services(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + char *buf; + unsigned int len = 0, buf_len = 1500; + const char *status; + ssize_t ret_cnt; + int i; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + mutex_lock(&ar->conf_mutex); + + if (len > buf_len) + len = buf_len; + + for (i = 0; i < WMI_SERVICE_LAST; i++) { + if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i)) + status = "enabled"; + else + status = "disabled"; + + len += scnprintf(buf + len, buf_len - len, + "0x%02x - %20s - %s\n", + i, wmi_service_name(i), status); + } + + ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); + + mutex_unlock(&ar->conf_mutex); + + kfree(buf); + return ret_cnt; +} + +static const struct file_operations fops_wmi_services = { + .read = ath10k_read_wmi_services, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +void ath10k_debug_read_target_stats(struct ath10k *ar, + struct wmi_stats_event *ev) +{ + u8 *tmp = ev->data; + struct ath10k_target_stats *stats; + int num_pdev_stats, num_vdev_stats, num_peer_stats; + struct wmi_pdev_stats *ps; + int i; + + mutex_lock(&ar->conf_mutex); + + stats = &ar->debug.target_stats; + + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */ + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */ + num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */ + + if (num_pdev_stats) { + ps = (struct wmi_pdev_stats *)tmp; + + stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf); + stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count); + stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count); + stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count); + stats->cycle_count = __le32_to_cpu(ps->cycle_count); + stats->phy_err_count = __le32_to_cpu(ps->phy_err_count); + stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr); + + stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued); + stats->comp_delivered = + __le32_to_cpu(ps->wal.tx.comp_delivered); + stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued); + stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued); + stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop); + stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued); + stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed); + stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued); + stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped); + stats->underrun = __le32_to_cpu(ps->wal.tx.underrun); + stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort); + stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed); + stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko); + stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc); + stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers); + stats->sw_retry_failure = + __le32_to_cpu(ps->wal.tx.sw_retry_failure); + stats->illgl_rate_phy_err = + __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err); + stats->pdev_cont_xretry = + __le32_to_cpu(ps->wal.tx.pdev_cont_xretry); + stats->pdev_tx_timeout = + __le32_to_cpu(ps->wal.tx.pdev_tx_timeout); + stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets); + stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun); + stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf); + + stats->mid_ppdu_route_change = + __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change); + stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd); + stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags); + stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags); + stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags); + stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags); + stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus); + stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus); + stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus); + stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus); + stats->oversize_amsdu = + __le32_to_cpu(ps->wal.rx.oversize_amsdu); + stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs); + stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop); + stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs); + + tmp += sizeof(struct wmi_pdev_stats); + } + + /* 0 or max vdevs */ + /* Currently firmware does not support VDEV stats */ + if (num_vdev_stats) { + struct wmi_vdev_stats *vdev_stats; + + for (i = 0; i < num_vdev_stats; i++) { + vdev_stats = (struct wmi_vdev_stats *)tmp; + tmp += sizeof(struct wmi_vdev_stats); + } + } + + if (num_peer_stats) { + struct wmi_peer_stats *peer_stats; + struct ath10k_peer_stat *s; + + stats->peers = num_peer_stats; + + for (i = 0; i < num_peer_stats; i++) { + peer_stats = (struct wmi_peer_stats *)tmp; + s = &stats->peer_stat[i]; + + WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_stats->peer_macaddr, + s->peer_macaddr); + s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi); + s->peer_tx_rate = + __le32_to_cpu(peer_stats->peer_tx_rate); + + tmp += sizeof(struct wmi_peer_stats); + } + } + + mutex_unlock(&ar->conf_mutex); + complete(&ar->debug.event_stats_compl); +} + +static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath10k *ar = file->private_data; + struct ath10k_target_stats *fw_stats; + char *buf; + unsigned int len = 0, buf_len = 2500; + ssize_t ret_cnt; + long left; + int i; + int ret; + + fw_stats = &ar->debug.target_stats; + + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); + if (ret) { + ath10k_warn("could not request stats (%d)\n", ret); + kfree(buf); + return -EIO; + } + + left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ); + + if (left <= 0) { + kfree(buf); + return -ETIMEDOUT; + } + + mutex_lock(&ar->conf_mutex); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PDEV stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Channel noise floor", fw_stats->ch_noise_floor); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Channel TX power", fw_stats->chan_tx_power); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "TX frame count", fw_stats->tx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX frame count", fw_stats->rx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX clear count", fw_stats->rx_clear_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Cycle count", fw_stats->cycle_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "PHY error count", fw_stats->phy_err_count); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PDEV TX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies queued", fw_stats->comp_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies disp.", fw_stats->comp_delivered); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDU queued", fw_stats->msdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU queued", fw_stats->mpdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs dropped", fw_stats->wmm_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local enqued", fw_stats->local_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local freed", fw_stats->local_freed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW queued", fw_stats->hw_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs reaped", fw_stats->hw_reaped); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Num underruns", fw_stats->underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs cleaned", fw_stats->tx_abort); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs requed", fw_stats->mpdus_requed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Excessive retries", fw_stats->tx_ko); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW rate", fw_stats->data_rc); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Sched self tiggers", fw_stats->self_triggers); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Dropped due to SW retries", + fw_stats->sw_retry_failure); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Illegal rate phy errors", + fw_stats->illgl_rate_phy_err); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Pdev continous xretry", fw_stats->pdev_cont_xretry); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "TX timeout", fw_stats->pdev_tx_timeout); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PDEV resets", fw_stats->pdev_resets); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY underrun", fw_stats->phy_underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU is more than txop limit", fw_stats->txop_ovf); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PDEV RX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Mid PPDU route change", + fw_stats->mid_ppdu_route_change); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Tot. number of statuses", fw_stats->status_rcvd); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 0", fw_stats->r0_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 1", fw_stats->r1_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 2", fw_stats->r2_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 3", fw_stats->r3_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to HTT", fw_stats->htt_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to HTT", fw_stats->htt_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to stack", fw_stats->loc_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to stack", fw_stats->loc_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Oversized AMSUs", fw_stats->oversize_amsdu); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors", fw_stats->phy_errs); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors drops", fw_stats->phy_err_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PEER stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + for (i = 0; i < fw_stats->peers; i++) { + len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", + "Peer MAC address", + fw_stats->peer_stat[i].peer_macaddr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RSSI", fw_stats->peer_stat[i].peer_rssi); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer TX rate", + fw_stats->peer_stat[i].peer_tx_rate); + len += scnprintf(buf + len, buf_len - len, "\n"); + } + + if (len > buf_len) + len = buf_len; + + ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); + + mutex_unlock(&ar->conf_mutex); + + kfree(buf); + return ret_cnt; +} + +static const struct file_operations fops_fw_stats = { + .read = ath10k_read_fw_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +int ath10k_debug_create(struct ath10k *ar) +{ + ar->debug.debugfs_phy = debugfs_create_dir("ath10k", + ar->hw->wiphy->debugfsdir); + + if (!ar->debug.debugfs_phy) + return -ENOMEM; + + init_completion(&ar->debug.event_stats_compl); + + debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, + &fops_fw_stats); + + debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, + &fops_wmi_services); + + return 0; +} +#endif /* CONFIG_ATH10K_DEBUGFS */ + +#ifdef CONFIG_ATH10K_DEBUG +void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + if (ath10k_debug_mask & mask) + ath10k_printk(KERN_DEBUG, "%pV", &vaf); + + trace_ath10k_log_dbg(mask, &vaf); + + va_end(args); +} +EXPORT_SYMBOL(ath10k_dbg); + +void ath10k_dbg_dump(enum ath10k_debug_mask mask, + const char *msg, const char *prefix, + const void *buf, size_t len) +{ + if (ath10k_debug_mask & mask) { + if (msg) + ath10k_dbg(mask, "%s\n", msg); + + print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); + } + + /* tracing code doesn't like null strings :/ */ + trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", + buf, len); +} +EXPORT_SYMBOL(ath10k_dbg_dump); + +#endif /* CONFIG_ATH10K_DEBUG */ diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h new file mode 100644 index 000000000000..168140c54028 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include +#include "trace.h" + +enum ath10k_debug_mask { + ATH10K_DBG_PCI = 0x00000001, + ATH10K_DBG_WMI = 0x00000002, + ATH10K_DBG_HTC = 0x00000004, + ATH10K_DBG_HTT = 0x00000008, + ATH10K_DBG_MAC = 0x00000010, + ATH10K_DBG_CORE = 0x00000020, + ATH10K_DBG_PCI_DUMP = 0x00000040, + ATH10K_DBG_HTT_DUMP = 0x00000080, + ATH10K_DBG_MGMT = 0x00000100, + ATH10K_DBG_DATA = 0x00000200, + ATH10K_DBG_ANY = 0xffffffff, +}; + +extern unsigned int ath10k_debug_mask; + +extern __printf(1, 2) int ath10k_info(const char *fmt, ...); +extern __printf(1, 2) int ath10k_err(const char *fmt, ...); +extern __printf(1, 2) int ath10k_warn(const char *fmt, ...); + +#ifdef CONFIG_ATH10K_DEBUGFS +int ath10k_debug_create(struct ath10k *ar); +void ath10k_debug_read_service_map(struct ath10k *ar, + void *service_map, + size_t map_size); +void ath10k_debug_read_target_stats(struct ath10k *ar, + struct wmi_stats_event *ev); + +#else +static inline int ath10k_debug_create(struct ath10k *ar) +{ + return 0; +} + +static inline void ath10k_debug_read_service_map(struct ath10k *ar, + void *service_map, + size_t map_size) +{ +} + +static inline void ath10k_debug_read_target_stats(struct ath10k *ar, + struct wmi_stats_event *ev) +{ +} +#endif /* CONFIG_ATH10K_DEBUGFS */ + +#ifdef CONFIG_ATH10K_DEBUG +extern __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask, + const char *fmt, ...); +void ath10k_dbg_dump(enum ath10k_debug_mask mask, + const char *msg, const char *prefix, + const void *buf, size_t len); +#else /* CONFIG_ATH10K_DEBUG */ + +static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask, + const char *fmt, ...) +{ + return 0; +} + +static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask, + const char *msg, const char *prefix, + const void *buf, size_t len) +{ +} +#endif /* CONFIG_ATH10K_DEBUG */ +#endif /* _DEBUG_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h new file mode 100644 index 000000000000..73a24d44d1b4 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HIF_H_ +#define _HIF_H_ + +#include +#include "core.h" + +struct ath10k_hif_cb { + int (*tx_completion)(struct ath10k *ar, + struct sk_buff *wbuf, + unsigned transfer_id); + int (*rx_completion)(struct ath10k *ar, + struct sk_buff *wbuf, + u8 pipe_id); +}; + +struct ath10k_hif_ops { + /* Send the head of a buffer to HIF for transmission to the target. */ + int (*send_head)(struct ath10k *ar, u8 pipe_id, + unsigned int transfer_id, + unsigned int nbytes, + struct sk_buff *buf); + + /* + * API to handle HIF-specific BMI message exchanges, this API is + * synchronous and only allowed to be called from a context that + * can block (sleep) + */ + int (*exchange_bmi_msg)(struct ath10k *ar, + void *request, u32 request_len, + void *response, u32 *response_len); + + int (*start)(struct ath10k *ar); + + void (*stop)(struct ath10k *ar); + + int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe, + int *ul_is_polled, int *dl_is_polled); + + void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe); + + /* + * Check if prior sends have completed. + * + * Check whether the pipe in question has any completed + * sends that have not yet been processed. + * This function is only relevant for HIF pipes that are configured + * to be polled rather than interrupt-driven. + */ + void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force); + + void (*init)(struct ath10k *ar, + struct ath10k_hif_cb *callbacks); + + u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); +}; + + +static inline int ath10k_hif_send_head(struct ath10k *ar, u8 pipe_id, + unsigned int transfer_id, + unsigned int nbytes, + struct sk_buff *buf) +{ + return ar->hif.ops->send_head(ar, pipe_id, transfer_id, nbytes, buf); +} + +static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, + void *request, u32 request_len, + void *response, u32 *response_len) +{ + return ar->hif.ops->exchange_bmi_msg(ar, request, request_len, + response, response_len); +} + +static inline int ath10k_hif_start(struct ath10k *ar) +{ + return ar->hif.ops->start(ar); +} + +static inline void ath10k_hif_stop(struct ath10k *ar) +{ + return ar->hif.ops->stop(ar); +} + +static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, + u16 service_id, + u8 *ul_pipe, u8 *dl_pipe, + int *ul_is_polled, + int *dl_is_polled) +{ + return ar->hif.ops->map_service_to_pipe(ar, service_id, + ul_pipe, dl_pipe, + ul_is_polled, dl_is_polled); +} + +static inline void ath10k_hif_get_default_pipe(struct ath10k *ar, + u8 *ul_pipe, u8 *dl_pipe) +{ + ar->hif.ops->get_default_pipe(ar, ul_pipe, dl_pipe); +} + +static inline void ath10k_hif_send_complete_check(struct ath10k *ar, + u8 pipe_id, int force) +{ + ar->hif.ops->send_complete_check(ar, pipe_id, force); +} + +static inline void ath10k_hif_init(struct ath10k *ar, + struct ath10k_hif_cb *callbacks) +{ + ar->hif.ops->init(ar, callbacks); +} + +static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar, + u8 pipe_id) +{ + return ar->hif.ops->get_free_queue_number(ar, pipe_id); +} + +#endif /* _HIF_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c new file mode 100644 index 000000000000..74363c949392 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -0,0 +1,1000 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "hif.h" +#include "debug.h" + +/********/ +/* Send */ +/********/ + +static inline void ath10k_htc_send_complete_check(struct ath10k_htc_ep *ep, + int force) +{ + /* + * Check whether HIF has any prior sends that have finished, + * have not had the post-processing done. + */ + ath10k_hif_send_complete_check(ep->htc->ar, ep->ul_pipe_id, force); +} + +static void ath10k_htc_control_tx_complete(struct ath10k *ar, + struct sk_buff *skb) +{ + kfree_skb(skb); +} + +static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) +{ + struct sk_buff *skb; + struct ath10k_skb_cb *skb_cb; + + skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE); + if (!skb) { + ath10k_warn("Unable to allocate ctrl skb\n"); + return NULL; + } + + skb_reserve(skb, 20); /* FIXME: why 20 bytes? */ + WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb"); + + skb_cb = ATH10K_SKB_CB(skb); + memset(skb_cb, 0, sizeof(*skb_cb)); + + ath10k_dbg(ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb); + return skb; +} + +static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, + struct sk_buff *skb) +{ + ath10k_skb_unmap(htc->ar->dev, skb); + skb_pull(skb, sizeof(struct ath10k_htc_hdr)); +} + +static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__, + ep->eid, skb); + + ath10k_htc_restore_tx_skb(ep->htc, skb); + + if (!ep->ep_ops.ep_tx_complete) { + ath10k_warn("no tx handler for eid %d\n", ep->eid); + dev_kfree_skb_any(skb); + return; + } + + ep->ep_ops.ep_tx_complete(ep->htc->ar, skb); +} + +/* assumes tx_lock is held */ +static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep) +{ + if (!ep->tx_credit_flow_enabled) + return false; + if (ep->tx_credits >= ep->tx_credits_per_max_message) + return false; + + ath10k_dbg(ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n", + ep->eid); + return true; +} + +static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, + struct sk_buff *skb) +{ + struct ath10k_htc_hdr *hdr; + + hdr = (struct ath10k_htc_hdr *)skb->data; + memset(hdr, 0, sizeof(*hdr)); + + hdr->eid = ep->eid; + hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); + + spin_lock_bh(&ep->htc->tx_lock); + hdr->seq_no = ep->seq_no++; + + if (ath10k_htc_ep_need_credit_update(ep)) + hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; + + spin_unlock_bh(&ep->htc->tx_lock); +} + +static int ath10k_htc_issue_skb(struct ath10k_htc *htc, + struct ath10k_htc_ep *ep, + struct sk_buff *skb, + u8 credits) +{ + struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); + int ret; + + ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__, + ep->eid, skb); + + ath10k_htc_prepare_tx_skb(ep, skb); + + ret = ath10k_skb_map(htc->ar->dev, skb); + if (ret) + goto err; + + ret = ath10k_hif_send_head(htc->ar, + ep->ul_pipe_id, + ep->eid, + skb->len, + skb); + if (unlikely(ret)) + goto err; + + return 0; +err: + ath10k_warn("HTC issue failed: %d\n", ret); + + spin_lock_bh(&htc->tx_lock); + ep->tx_credits += credits; + spin_unlock_bh(&htc->tx_lock); + + /* this is the simplest way to handle out-of-resources for non-credit + * based endpoints. credit based endpoints can still get -ENOSR, but + * this is highly unlikely as credit reservation should prevent that */ + if (ret == -ENOSR) { + spin_lock_bh(&htc->tx_lock); + __skb_queue_head(&ep->tx_queue, skb); + spin_unlock_bh(&htc->tx_lock); + + return ret; + } + + skb_cb->is_aborted = true; + ath10k_htc_notify_tx_completion(ep, skb); + + return ret; +} + +static struct sk_buff *ath10k_htc_get_skb_credit_based(struct ath10k_htc *htc, + struct ath10k_htc_ep *ep, + u8 *credits) +{ + struct sk_buff *skb; + struct ath10k_skb_cb *skb_cb; + int credits_required; + int remainder; + unsigned int transfer_len; + + lockdep_assert_held(&htc->tx_lock); + + skb = __skb_dequeue(&ep->tx_queue); + if (!skb) + return NULL; + + skb_cb = ATH10K_SKB_CB(skb); + transfer_len = skb->len; + + if (likely(transfer_len <= htc->target_credit_size)) { + credits_required = 1; + } else { + /* figure out how many credits this message requires */ + credits_required = transfer_len / htc->target_credit_size; + remainder = transfer_len % htc->target_credit_size; + + if (remainder) + credits_required++; + } + + ath10k_dbg(ATH10K_DBG_HTC, "Credits required %d got %d\n", + credits_required, ep->tx_credits); + + if (ep->tx_credits < credits_required) { + __skb_queue_head(&ep->tx_queue, skb); + return NULL; + } + + ep->tx_credits -= credits_required; + *credits = credits_required; + return skb; +} + +static void ath10k_htc_send_work(struct work_struct *work) +{ + struct ath10k_htc_ep *ep = container_of(work, + struct ath10k_htc_ep, send_work); + struct ath10k_htc *htc = ep->htc; + struct sk_buff *skb; + u8 credits = 0; + int ret; + + while (true) { + if (ep->ul_is_polled) + ath10k_htc_send_complete_check(ep, 0); + + spin_lock_bh(&htc->tx_lock); + if (ep->tx_credit_flow_enabled) + skb = ath10k_htc_get_skb_credit_based(htc, ep, + &credits); + else + skb = __skb_dequeue(&ep->tx_queue); + spin_unlock_bh(&htc->tx_lock); + + if (!skb) + break; + + ret = ath10k_htc_issue_skb(htc, ep, skb, credits); + if (ret == -ENOSR) + break; + } +} + +int ath10k_htc_send(struct ath10k_htc *htc, + enum ath10k_htc_ep_id eid, + struct sk_buff *skb) +{ + struct ath10k_htc_ep *ep = &htc->endpoint[eid]; + + if (eid >= ATH10K_HTC_EP_COUNT) { + ath10k_warn("Invalid endpoint id: %d\n", eid); + return -ENOENT; + } + + skb_push(skb, sizeof(struct ath10k_htc_hdr)); + + spin_lock_bh(&htc->tx_lock); + __skb_queue_tail(&ep->tx_queue, skb); + spin_unlock_bh(&htc->tx_lock); + + queue_work(htc->ar->workqueue, &ep->send_work); + return 0; +} + +static int ath10k_htc_tx_completion_handler(struct ath10k *ar, + struct sk_buff *skb, + unsigned int eid) +{ + struct ath10k_htc *htc = ar->htc; + struct ath10k_htc_ep *ep = &htc->endpoint[eid]; + bool stopping; + + ath10k_htc_notify_tx_completion(ep, skb); + /* the skb now belongs to the completion handler */ + + spin_lock_bh(&htc->tx_lock); + stopping = htc->stopping; + spin_unlock_bh(&htc->tx_lock); + + if (!ep->tx_credit_flow_enabled && !stopping) + /* + * note: when using TX credit flow, the re-checking of + * queues happens when credits flow back from the target. + * in the non-TX credit case, we recheck after the packet + * completes + */ + queue_work(ar->workqueue, &ep->send_work); + + return 0; +} + +/* flush endpoint TX queue */ +static void ath10k_htc_flush_endpoint_tx(struct ath10k_htc *htc, + struct ath10k_htc_ep *ep) +{ + struct sk_buff *skb; + struct ath10k_skb_cb *skb_cb; + + spin_lock_bh(&htc->tx_lock); + for (;;) { + skb = __skb_dequeue(&ep->tx_queue); + if (!skb) + break; + + skb_cb = ATH10K_SKB_CB(skb); + skb_cb->is_aborted = true; + ath10k_htc_notify_tx_completion(ep, skb); + } + spin_unlock_bh(&htc->tx_lock); + + cancel_work_sync(&ep->send_work); +} + +/***********/ +/* Receive */ +/***********/ + +static void +ath10k_htc_process_credit_report(struct ath10k_htc *htc, + const struct ath10k_htc_credit_report *report, + int len, + enum ath10k_htc_ep_id eid) +{ + struct ath10k_htc_ep *ep; + int i, n_reports; + + if (len % sizeof(*report)) + ath10k_warn("Uneven credit report len %d", len); + + n_reports = len / sizeof(*report); + + spin_lock_bh(&htc->tx_lock); + for (i = 0; i < n_reports; i++, report++) { + if (report->eid >= ATH10K_HTC_EP_COUNT) + break; + + ath10k_dbg(ATH10K_DBG_HTC, "ep %d got %d credits\n", + report->eid, report->credits); + + ep = &htc->endpoint[report->eid]; + ep->tx_credits += report->credits; + + if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue)) + queue_work(htc->ar->workqueue, &ep->send_work); + } + spin_unlock_bh(&htc->tx_lock); +} + +static int ath10k_htc_process_trailer(struct ath10k_htc *htc, + u8 *buffer, + int length, + enum ath10k_htc_ep_id src_eid) +{ + int status = 0; + struct ath10k_htc_record *record; + u8 *orig_buffer; + int orig_length; + size_t len; + + orig_buffer = buffer; + orig_length = length; + + while (length > 0) { + record = (struct ath10k_htc_record *)buffer; + + if (length < sizeof(record->hdr)) { + status = -EINVAL; + break; + } + + if (record->hdr.len > length) { + /* no room left in buffer for record */ + ath10k_warn("Invalid record length: %d\n", + record->hdr.len); + status = -EINVAL; + break; + } + + switch (record->hdr.id) { + case ATH10K_HTC_RECORD_CREDITS: + len = sizeof(struct ath10k_htc_credit_report); + if (record->hdr.len < len) { + ath10k_warn("Credit report too long\n"); + status = -EINVAL; + break; + } + ath10k_htc_process_credit_report(htc, + record->credit_report, + record->hdr.len, + src_eid); + break; + default: + ath10k_warn("Unhandled record: id:%d length:%d\n", + record->hdr.id, record->hdr.len); + break; + } + + if (status) + break; + + /* multiple records may be present in a trailer */ + buffer += sizeof(record->hdr) + record->hdr.len; + length -= sizeof(record->hdr) + record->hdr.len; + } + + if (status) + ath10k_dbg_dump(ATH10K_DBG_HTC, "htc rx bad trailer", "", + orig_buffer, orig_length); + + return status; +} + +static int ath10k_htc_rx_completion_handler(struct ath10k *ar, + struct sk_buff *skb, + u8 pipe_id) +{ + int status = 0; + struct ath10k_htc *htc = ar->htc; + struct ath10k_htc_hdr *hdr; + struct ath10k_htc_ep *ep; + u16 payload_len; + u32 trailer_len = 0; + size_t min_len; + u8 eid; + bool trailer_present; + + hdr = (struct ath10k_htc_hdr *)skb->data; + skb_pull(skb, sizeof(*hdr)); + + eid = hdr->eid; + + if (eid >= ATH10K_HTC_EP_COUNT) { + ath10k_warn("HTC Rx: invalid eid %d\n", eid); + ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad header", "", + hdr, sizeof(*hdr)); + status = -EINVAL; + goto out; + } + + ep = &htc->endpoint[eid]; + + /* + * If this endpoint that received a message from the target has + * a to-target HIF pipe whose send completions are polled rather + * than interrupt-driven, this is a good point to ask HIF to check + * whether it has any completed sends to handle. + */ + if (ep->ul_is_polled) + ath10k_htc_send_complete_check(ep, 1); + + payload_len = __le16_to_cpu(hdr->len); + + if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) { + ath10k_warn("HTC rx frame too long, len: %zu\n", + payload_len + sizeof(*hdr)); + ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", "", + hdr, sizeof(*hdr)); + status = -EINVAL; + goto out; + } + + if (skb->len < payload_len) { + ath10k_dbg(ATH10K_DBG_HTC, + "HTC Rx: insufficient length, got %d, expected %d\n", + skb->len, payload_len); + ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", + "", hdr, sizeof(*hdr)); + status = -EINVAL; + goto out; + } + + /* get flags to check for trailer */ + trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT; + if (trailer_present) { + u8 *trailer; + + trailer_len = hdr->trailer_len; + min_len = sizeof(struct ath10k_ath10k_htc_record_hdr); + + if ((trailer_len < min_len) || + (trailer_len > payload_len)) { + ath10k_warn("Invalid trailer length: %d\n", + trailer_len); + status = -EPROTO; + goto out; + } + + trailer = (u8 *)hdr; + trailer += sizeof(*hdr); + trailer += payload_len; + trailer -= trailer_len; + status = ath10k_htc_process_trailer(htc, trailer, + trailer_len, hdr->eid); + if (status) + goto out; + + skb_trim(skb, skb->len - trailer_len); + } + + if (((int)payload_len - (int)trailer_len) <= 0) + /* zero length packet with trailer data, just drop these */ + goto out; + + if (eid == ATH10K_HTC_EP_0) { + struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data; + + switch (__le16_to_cpu(msg->hdr.message_id)) { + default: + /* handle HTC control message */ + if (completion_done(&htc->ctl_resp)) { + /* + * this is a fatal error, target should not be + * sending unsolicited messages on the ep 0 + */ + ath10k_warn("HTC rx ctrl still processing\n"); + status = -EINVAL; + complete(&htc->ctl_resp); + goto out; + } + + htc->control_resp_len = + min_t(int, skb->len, + ATH10K_HTC_MAX_CTRL_MSG_LEN); + + memcpy(htc->control_resp_buffer, skb->data, + htc->control_resp_len); + + complete(&htc->ctl_resp); + break; + case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE: + htc->htc_ops.target_send_suspend_complete(ar); + } + goto out; + } + + ath10k_dbg(ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n", + eid, skb); + ep->ep_ops.ep_rx_complete(ar, skb); + + /* skb is now owned by the rx completion handler */ + skb = NULL; +out: + kfree_skb(skb); + + return status; +} + +static void ath10k_htc_control_rx_complete(struct ath10k *ar, + struct sk_buff *skb) +{ + /* This is unexpected. FW is not supposed to send regular rx on this + * endpoint. */ + ath10k_warn("unexpected htc rx\n"); + kfree_skb(skb); +} + +/***************/ +/* Init/Deinit */ +/***************/ + +static const char *htc_service_name(enum ath10k_htc_svc_id id) +{ + switch (id) { + case ATH10K_HTC_SVC_ID_RESERVED: + return "Reserved"; + case ATH10K_HTC_SVC_ID_RSVD_CTRL: + return "Control"; + case ATH10K_HTC_SVC_ID_WMI_CONTROL: + return "WMI"; + case ATH10K_HTC_SVC_ID_WMI_DATA_BE: + return "DATA BE"; + case ATH10K_HTC_SVC_ID_WMI_DATA_BK: + return "DATA BK"; + case ATH10K_HTC_SVC_ID_WMI_DATA_VI: + return "DATA VI"; + case ATH10K_HTC_SVC_ID_WMI_DATA_VO: + return "DATA VO"; + case ATH10K_HTC_SVC_ID_NMI_CONTROL: + return "NMI Control"; + case ATH10K_HTC_SVC_ID_NMI_DATA: + return "NMI Data"; + case ATH10K_HTC_SVC_ID_HTT_DATA_MSG: + return "HTT Data"; + case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS: + return "RAW"; + } + + return "Unknown"; +} + +static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc) +{ + struct ath10k_htc_ep *ep; + int i; + + for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) { + ep = &htc->endpoint[i]; + ep->service_id = ATH10K_HTC_SVC_ID_UNUSED; + ep->max_ep_message_len = 0; + ep->max_tx_queue_depth = 0; + ep->eid = i; + skb_queue_head_init(&ep->tx_queue); + ep->htc = htc; + ep->tx_credit_flow_enabled = true; + INIT_WORK(&ep->send_work, ath10k_htc_send_work); + } +} + +static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc) +{ + struct ath10k_htc_svc_tx_credits *entry; + + entry = &htc->service_tx_alloc[0]; + + /* + * for PCIE allocate all credists/HTC buffers to WMI. + * no buffers are used/required for data. data always + * remains on host. + */ + entry++; + entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; + entry->credit_allocation = htc->total_transmit_credits; +} + +static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc, + u16 service_id) +{ + u8 allocation = 0; + int i; + + for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) { + if (htc->service_tx_alloc[i].service_id == service_id) + allocation = + htc->service_tx_alloc[i].credit_allocation; + } + + return allocation; +} + +int ath10k_htc_wait_target(struct ath10k_htc *htc) +{ + int status = 0; + struct ath10k_htc_svc_conn_req conn_req; + struct ath10k_htc_svc_conn_resp conn_resp; + struct ath10k_htc_msg *msg; + u16 message_id; + u16 credit_count; + u16 credit_size; + + INIT_COMPLETION(htc->ctl_resp); + + status = ath10k_hif_start(htc->ar); + if (status) { + ath10k_err("could not start HIF (%d)\n", status); + goto err_start; + } + + status = wait_for_completion_timeout(&htc->ctl_resp, + ATH10K_HTC_WAIT_TIMEOUT_HZ); + if (status <= 0) { + if (status == 0) + status = -ETIMEDOUT; + + ath10k_err("ctl_resp never came in (%d)\n", status); + goto err_target; + } + + if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { + ath10k_err("Invalid HTC ready msg len:%d\n", + htc->control_resp_len); + + status = -ECOMM; + goto err_target; + } + + msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; + message_id = __le16_to_cpu(msg->hdr.message_id); + credit_count = __le16_to_cpu(msg->ready.credit_count); + credit_size = __le16_to_cpu(msg->ready.credit_size); + + if (message_id != ATH10K_HTC_MSG_READY_ID) { + ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id); + status = -ECOMM; + goto err_target; + } + + htc->total_transmit_credits = credit_count; + htc->target_credit_size = credit_size; + + ath10k_dbg(ATH10K_DBG_HTC, + "Target ready! transmit resources: %d size:%d\n", + htc->total_transmit_credits, + htc->target_credit_size); + + if ((htc->total_transmit_credits == 0) || + (htc->target_credit_size == 0)) { + status = -ECOMM; + ath10k_err("Invalid credit size received\n"); + goto err_target; + } + + ath10k_htc_setup_target_buffer_assignments(htc); + + /* setup our pseudo HTC control endpoint connection */ + memset(&conn_req, 0, sizeof(conn_req)); + memset(&conn_resp, 0, sizeof(conn_resp)); + conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete; + conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete; + conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS; + conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL; + + /* connect fake service */ + status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); + if (status) { + ath10k_err("could not connect to htc service (%d)\n", status); + goto err_target; + } + + return 0; +err_target: + ath10k_hif_stop(htc->ar); +err_start: + return status; +} + +int ath10k_htc_connect_service(struct ath10k_htc *htc, + struct ath10k_htc_svc_conn_req *conn_req, + struct ath10k_htc_svc_conn_resp *conn_resp) +{ + struct ath10k_htc_msg *msg; + struct ath10k_htc_conn_svc *req_msg; + struct ath10k_htc_conn_svc_response resp_msg_dummy; + struct ath10k_htc_conn_svc_response *resp_msg = &resp_msg_dummy; + enum ath10k_htc_ep_id assigned_eid = ATH10K_HTC_EP_COUNT; + struct ath10k_htc_ep *ep; + struct sk_buff *skb; + unsigned int max_msg_size = 0; + int length, status; + bool disable_credit_flow_ctrl = false; + u16 message_id, service_id, flags = 0; + u8 tx_alloc = 0; + + /* special case for HTC pseudo control service */ + if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) { + disable_credit_flow_ctrl = true; + assigned_eid = ATH10K_HTC_EP_0; + max_msg_size = ATH10K_HTC_MAX_CTRL_MSG_LEN; + memset(&resp_msg_dummy, 0, sizeof(resp_msg_dummy)); + goto setup; + } + + tx_alloc = ath10k_htc_get_credit_allocation(htc, + conn_req->service_id); + if (!tx_alloc) + ath10k_warn("HTC Service %s does not allocate target credits\n", + htc_service_name(conn_req->service_id)); + + skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); + if (!skb) { + ath10k_err("Failed to allocate HTC packet\n"); + return -ENOMEM; + } + + length = sizeof(msg->hdr) + sizeof(msg->connect_service); + skb_put(skb, length); + memset(skb->data, 0, length); + + msg = (struct ath10k_htc_msg *)skb->data; + msg->hdr.message_id = + __cpu_to_le16(ATH10K_HTC_MSG_CONNECT_SERVICE_ID); + + flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC); + + req_msg = &msg->connect_service; + req_msg->flags = __cpu_to_le16(flags); + req_msg->service_id = __cpu_to_le16(conn_req->service_id); + + /* Only enable credit flow control for WMI ctrl service */ + if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) { + flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; + disable_credit_flow_ctrl = true; + } + + INIT_COMPLETION(htc->ctl_resp); + + status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); + if (status) { + kfree_skb(skb); + return status; + } + + /* wait for response */ + status = wait_for_completion_timeout(&htc->ctl_resp, + ATH10K_HTC_CONN_SVC_TIMEOUT_HZ); + if (status <= 0) { + if (status == 0) + status = -ETIMEDOUT; + ath10k_err("Service connect timeout: %d\n", status); + return status; + } + + /* we controlled the buffer creation, it's aligned */ + msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; + resp_msg = &msg->connect_service_response; + message_id = __le16_to_cpu(msg->hdr.message_id); + service_id = __le16_to_cpu(resp_msg->service_id); + + if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) || + (htc->control_resp_len < sizeof(msg->hdr) + + sizeof(msg->connect_service_response))) { + ath10k_err("Invalid resp message ID 0x%x", message_id); + return -EPROTO; + } + + ath10k_dbg(ATH10K_DBG_HTC, + "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n", + htc_service_name(service_id), + resp_msg->status, resp_msg->eid); + + conn_resp->connect_resp_code = resp_msg->status; + + /* check response status */ + if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) { + ath10k_err("HTC Service %s connect request failed: 0x%x)\n", + htc_service_name(service_id), + resp_msg->status); + return -EPROTO; + } + + assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid; + max_msg_size = __le16_to_cpu(resp_msg->max_msg_size); + +setup: + + if (assigned_eid >= ATH10K_HTC_EP_COUNT) + return -EPROTO; + + if (max_msg_size == 0) + return -EPROTO; + + ep = &htc->endpoint[assigned_eid]; + ep->eid = assigned_eid; + + if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED) + return -EPROTO; + + /* return assigned endpoint to caller */ + conn_resp->eid = assigned_eid; + conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size); + + /* setup the endpoint */ + ep->service_id = conn_req->service_id; + ep->max_tx_queue_depth = conn_req->max_send_queue_depth; + ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size); + ep->tx_credits = tx_alloc; + ep->tx_credit_size = htc->target_credit_size; + ep->tx_credits_per_max_message = ep->max_ep_message_len / + htc->target_credit_size; + + if (ep->max_ep_message_len % htc->target_credit_size) + ep->tx_credits_per_max_message++; + + /* copy all the callbacks */ + ep->ep_ops = conn_req->ep_ops; + + status = ath10k_hif_map_service_to_pipe(htc->ar, + ep->service_id, + &ep->ul_pipe_id, + &ep->dl_pipe_id, + &ep->ul_is_polled, + &ep->dl_is_polled); + if (status) + return status; + + ath10k_dbg(ATH10K_DBG_HTC, + "HTC service: %s UL pipe: %d DL pipe: %d eid: %d ready\n", + htc_service_name(ep->service_id), ep->ul_pipe_id, + ep->dl_pipe_id, ep->eid); + + ath10k_dbg(ATH10K_DBG_HTC, + "EP %d UL polled: %d, DL polled: %d\n", + ep->eid, ep->ul_is_polled, ep->dl_is_polled); + + if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { + ep->tx_credit_flow_enabled = false; + ath10k_dbg(ATH10K_DBG_HTC, + "HTC service: %s eid: %d TX flow control disabled\n", + htc_service_name(ep->service_id), assigned_eid); + } + + return status; +} + +struct sk_buff *ath10k_htc_alloc_skb(int size) +{ + struct sk_buff *skb; + + skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr)); + if (!skb) { + ath10k_warn("could not allocate HTC tx skb\n"); + return NULL; + } + + skb_reserve(skb, sizeof(struct ath10k_htc_hdr)); + + /* FW/HTC requires 4-byte aligned streams */ + if (!IS_ALIGNED((unsigned long)skb->data, 4)) + ath10k_warn("Unaligned HTC tx skb\n"); + + return skb; +} + +int ath10k_htc_start(struct ath10k_htc *htc) +{ + struct sk_buff *skb; + int status = 0; + struct ath10k_htc_msg *msg; + + skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); + if (!skb) + return -ENOMEM; + + skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext)); + memset(skb->data, 0, skb->len); + + msg = (struct ath10k_htc_msg *)skb->data; + msg->hdr.message_id = + __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID); + + ath10k_dbg(ATH10K_DBG_HTC, "HTC is using TX credit flow control\n"); + + status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); + if (status) { + kfree_skb(skb); + return status; + } + + return 0; +} + +/* + * stop HTC communications, i.e. stop interrupt reception, and flush all + * queued buffers + */ +void ath10k_htc_stop(struct ath10k_htc *htc) +{ + int i; + struct ath10k_htc_ep *ep; + + spin_lock_bh(&htc->tx_lock); + htc->stopping = true; + spin_unlock_bh(&htc->tx_lock); + + for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) { + ep = &htc->endpoint[i]; + ath10k_htc_flush_endpoint_tx(htc, ep); + } + + ath10k_hif_stop(htc->ar); + ath10k_htc_reset_endpoint_states(htc); +} + +/* registered target arrival callback from the HIF layer */ +struct ath10k_htc *ath10k_htc_create(struct ath10k *ar, + struct ath10k_htc_ops *htc_ops) +{ + struct ath10k_hif_cb htc_callbacks; + struct ath10k_htc_ep *ep = NULL; + struct ath10k_htc *htc = NULL; + + /* FIXME: use struct ath10k instead */ + htc = kzalloc(sizeof(struct ath10k_htc), GFP_KERNEL); + if (!htc) + return ERR_PTR(-ENOMEM); + + spin_lock_init(&htc->tx_lock); + + memcpy(&htc->htc_ops, htc_ops, sizeof(struct ath10k_htc_ops)); + + ath10k_htc_reset_endpoint_states(htc); + + /* setup HIF layer callbacks */ + htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler; + htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler; + htc->ar = ar; + + /* Get HIF default pipe for HTC message exchange */ + ep = &htc->endpoint[ATH10K_HTC_EP_0]; + + ath10k_hif_init(ar, &htc_callbacks); + ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id); + + init_completion(&htc->ctl_resp); + + return htc; +} + +void ath10k_htc_destroy(struct ath10k_htc *htc) +{ + kfree(htc); +} diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h new file mode 100644 index 000000000000..fa45844b59fb --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HTC_H_ +#define _HTC_H_ + +#include +#include +#include +#include +#include +#include + +struct ath10k; + +/****************/ +/* HTC protocol */ +/****************/ + +/* + * HTC - host-target control protocol + * + * tx packets are generally + * rx packets are more complex: + * + * The payload + trailer length is stored in len. + * To get payload-only length one needs to payload - trailer_len. + * + * Trailer contains (possibly) multiple . + * Each record is a id-len-value. + * + * HTC header flags, control_byte0, control_byte1 + * have different meaning depending whether its tx + * or rx. + * + * Alignment: htc_hdr, payload and trailer are + * 4-byte aligned. + */ + +enum ath10k_htc_tx_flags { + ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01, + ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02 +}; + +enum ath10k_htc_rx_flags { + ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02, + ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0 +}; + +struct ath10k_htc_hdr { + u8 eid; /* @enum ath10k_htc_ep_id */ + u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */ + __le16 len; + union { + u8 trailer_len; /* for rx */ + u8 control_byte0; + } __packed; + union { + u8 seq_no; /* for tx */ + u8 control_byte1; + } __packed; + u8 pad0; + u8 pad1; +} __packed __aligned(4); + +enum ath10k_ath10k_htc_msg_id { + ATH10K_HTC_MSG_READY_ID = 1, + ATH10K_HTC_MSG_CONNECT_SERVICE_ID = 2, + ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3, + ATH10K_HTC_MSG_SETUP_COMPLETE_ID = 4, + ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID = 5, + ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6 +}; + +enum ath10k_htc_version { + ATH10K_HTC_VERSION_2P0 = 0x00, /* 2.0 */ + ATH10K_HTC_VERSION_2P1 = 0x01, /* 2.1 */ +}; + +enum ath10k_htc_conn_flags { + ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH = 0x0, + ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF = 0x1, + ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2, + ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY = 0x3, +#define ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK 0x3 + ATH10K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE = 1 << 2, + ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3 +#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_MASK 0xFF00 +#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB 8 +}; + +enum ath10k_htc_conn_svc_status { + ATH10K_HTC_CONN_SVC_STATUS_SUCCESS = 0, + ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND = 1, + ATH10K_HTC_CONN_SVC_STATUS_FAILED = 2, + ATH10K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3, + ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP = 4 +}; + +struct ath10k_ath10k_htc_msg_hdr { + __le16 message_id; /* @enum htc_message_id */ +} __packed; + +struct ath10k_htc_unknown { + u8 pad0; + u8 pad1; +} __packed; + +struct ath10k_htc_ready { + __le16 credit_count; + __le16 credit_size; + u8 max_endpoints; + u8 pad0; +} __packed; + +struct ath10k_htc_ready_extended { + struct ath10k_htc_ready base; + u8 htc_version; /* @enum ath10k_htc_version */ + u8 max_msgs_per_htc_bundle; + u8 pad0; + u8 pad1; +} __packed; + +struct ath10k_htc_conn_svc { + __le16 service_id; + __le16 flags; /* @enum ath10k_htc_conn_flags */ + u8 pad0; + u8 pad1; +} __packed; + +struct ath10k_htc_conn_svc_response { + __le16 service_id; + u8 status; /* @enum ath10k_htc_conn_svc_status */ + u8 eid; + __le16 max_msg_size; +} __packed; + +struct ath10k_htc_setup_complete_extended { + u8 pad0; + u8 pad1; + __le32 flags; /* @enum htc_setup_complete_flags */ + u8 max_msgs_per_bundled_recv; + u8 pad2; + u8 pad3; + u8 pad4; +} __packed; + +struct ath10k_htc_msg { + struct ath10k_ath10k_htc_msg_hdr hdr; + union { + /* host-to-target */ + struct ath10k_htc_conn_svc connect_service; + struct ath10k_htc_ready ready; + struct ath10k_htc_ready_extended ready_ext; + struct ath10k_htc_unknown unknown; + struct ath10k_htc_setup_complete_extended setup_complete_ext; + + /* target-to-host */ + struct ath10k_htc_conn_svc_response connect_service_response; + }; +} __packed __aligned(4); + +enum ath10k_ath10k_htc_record_id { + ATH10K_HTC_RECORD_NULL = 0, + ATH10K_HTC_RECORD_CREDITS = 1 +}; + +struct ath10k_ath10k_htc_record_hdr { + u8 id; /* @enum ath10k_ath10k_htc_record_id */ + u8 len; + u8 pad0; + u8 pad1; +} __packed; + +struct ath10k_htc_credit_report { + u8 eid; /* @enum ath10k_htc_ep_id */ + u8 credits; + u8 pad0; + u8 pad1; +} __packed; + +struct ath10k_htc_record { + struct ath10k_ath10k_htc_record_hdr hdr; + union { + struct ath10k_htc_credit_report credit_report[0]; + u8 pauload[0]; + }; +} __packed __aligned(4); + +/* + * note: the trailer offset is dynamic depending + * on payload length. this is only a struct layout draft + */ +struct ath10k_htc_frame { + struct ath10k_htc_hdr hdr; + union { + struct ath10k_htc_msg msg; + u8 payload[0]; + }; + struct ath10k_htc_record trailer[0]; +} __packed __aligned(4); + + +/*******************/ +/* Host-side stuff */ +/*******************/ + +enum ath10k_htc_svc_gid { + ATH10K_HTC_SVC_GRP_RSVD = 0, + ATH10K_HTC_SVC_GRP_WMI = 1, + ATH10K_HTC_SVC_GRP_NMI = 2, + ATH10K_HTC_SVC_GRP_HTT = 3, + + ATH10K_HTC_SVC_GRP_TEST = 254, + ATH10K_HTC_SVC_GRP_LAST = 255, +}; + +#define SVC(group, idx) \ + (int)(((int)(group) << 8) | (int)(idx)) + +enum ath10k_htc_svc_id { + /* NOTE: service ID of 0x0000 is reserved and should never be used */ + ATH10K_HTC_SVC_ID_RESERVED = 0x0000, + ATH10K_HTC_SVC_ID_UNUSED = ATH10K_HTC_SVC_ID_RESERVED, + + ATH10K_HTC_SVC_ID_RSVD_CTRL = SVC(ATH10K_HTC_SVC_GRP_RSVD, 1), + ATH10K_HTC_SVC_ID_WMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_WMI, 0), + ATH10K_HTC_SVC_ID_WMI_DATA_BE = SVC(ATH10K_HTC_SVC_GRP_WMI, 1), + ATH10K_HTC_SVC_ID_WMI_DATA_BK = SVC(ATH10K_HTC_SVC_GRP_WMI, 2), + ATH10K_HTC_SVC_ID_WMI_DATA_VI = SVC(ATH10K_HTC_SVC_GRP_WMI, 3), + ATH10K_HTC_SVC_ID_WMI_DATA_VO = SVC(ATH10K_HTC_SVC_GRP_WMI, 4), + + ATH10K_HTC_SVC_ID_NMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_NMI, 0), + ATH10K_HTC_SVC_ID_NMI_DATA = SVC(ATH10K_HTC_SVC_GRP_NMI, 1), + + ATH10K_HTC_SVC_ID_HTT_DATA_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 0), + + /* raw stream service (i.e. flash, tcmd, calibration apps) */ + ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0), +}; + +#undef SVC + +enum ath10k_htc_ep_id { + ATH10K_HTC_EP_UNUSED = -1, + ATH10K_HTC_EP_0 = 0, + ATH10K_HTC_EP_1 = 1, + ATH10K_HTC_EP_2, + ATH10K_HTC_EP_3, + ATH10K_HTC_EP_4, + ATH10K_HTC_EP_5, + ATH10K_HTC_EP_6, + ATH10K_HTC_EP_7, + ATH10K_HTC_EP_8, + ATH10K_HTC_EP_COUNT, +}; + +struct ath10k_htc_ops { + void (*target_send_suspend_complete)(struct ath10k *ar); +}; + +struct ath10k_htc_ep_ops { + void (*ep_tx_complete)(struct ath10k *, struct sk_buff *); + void (*ep_rx_complete)(struct ath10k *, struct sk_buff *); +}; + +/* service connection information */ +struct ath10k_htc_svc_conn_req { + u16 service_id; + struct ath10k_htc_ep_ops ep_ops; + int max_send_queue_depth; +}; + +/* service connection response information */ +struct ath10k_htc_svc_conn_resp { + u8 buffer_len; + u8 actual_len; + enum ath10k_htc_ep_id eid; + unsigned int max_msg_len; + u8 connect_resp_code; +}; + +#define ATH10K_NUM_CONTROL_TX_BUFFERS 2 +#define ATH10K_HTC_MAX_LEN 4096 +#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256 +#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ) +#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \ + sizeof(struct ath10k_htc_hdr)) +#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ) + +struct ath10k_htc_ep { + struct ath10k_htc *htc; + enum ath10k_htc_ep_id eid; + enum ath10k_htc_svc_id service_id; + struct ath10k_htc_ep_ops ep_ops; + + int max_tx_queue_depth; + int max_ep_message_len; + u8 ul_pipe_id; + u8 dl_pipe_id; + int ul_is_polled; /* call HIF to get tx completions */ + int dl_is_polled; /* call HIF to fetch rx (not implemented) */ + + struct sk_buff_head tx_queue; + + u8 seq_no; /* for debugging */ + int tx_credits; + int tx_credit_size; + int tx_credits_per_max_message; + bool tx_credit_flow_enabled; + + struct work_struct send_work; +}; + +struct ath10k_htc_svc_tx_credits { + u16 service_id; + u8 credit_allocation; +}; + +struct ath10k_htc { + struct ath10k *ar; + struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT]; + + /* protects endpoint and stopping fields */ + spinlock_t tx_lock; + + struct ath10k_htc_ops htc_ops; + + u8 control_resp_buffer[ATH10K_HTC_MAX_CTRL_MSG_LEN]; + int control_resp_len; + + struct completion ctl_resp; + + int total_transmit_credits; + struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; + int target_credit_size; + + bool stopping; +}; + +struct ath10k_htc *ath10k_htc_create(struct ath10k *ar, + struct ath10k_htc_ops *htc_ops); +int ath10k_htc_wait_target(struct ath10k_htc *htc); +int ath10k_htc_start(struct ath10k_htc *htc); +int ath10k_htc_connect_service(struct ath10k_htc *htc, + struct ath10k_htc_svc_conn_req *conn_req, + struct ath10k_htc_svc_conn_resp *conn_resp); +int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, + struct sk_buff *packet); +void ath10k_htc_stop(struct ath10k_htc *htc); +void ath10k_htc_destroy(struct ath10k_htc *htc); +struct sk_buff *ath10k_htc_alloc_skb(int size); + +#endif diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c new file mode 100644 index 000000000000..185a5468a2f2 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "htt.h" +#include "core.h" +#include "debug.h" + +static int ath10k_htt_htc_attach(struct ath10k_htt *htt) +{ + struct ath10k_htc_svc_conn_req conn_req; + struct ath10k_htc_svc_conn_resp conn_resp; + int status; + + memset(&conn_req, 0, sizeof(conn_req)); + memset(&conn_resp, 0, sizeof(conn_resp)); + + conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete; + conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler; + + /* connect to control service */ + conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG; + + status = ath10k_htc_connect_service(htt->ar->htc, &conn_req, + &conn_resp); + + if (status) + return status; + + htt->eid = conn_resp.eid; + + return 0; +} + +struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar) +{ + struct ath10k_htt *htt; + int ret; + + htt = kzalloc(sizeof(*htt), GFP_KERNEL); + if (!htt) + return NULL; + + htt->ar = ar; + htt->max_throughput_mbps = 800; + + /* + * Connect to HTC service. + * This has to be done before calling ath10k_htt_rx_attach, + * since ath10k_htt_rx_attach involves sending a rx ring configure + * message to the target. + */ + if (ath10k_htt_htc_attach(htt)) + goto err_htc_attach; + + ret = ath10k_htt_tx_attach(htt); + if (ret) { + ath10k_err("could not attach htt tx (%d)\n", ret); + goto err_htc_attach; + } + + if (ath10k_htt_rx_attach(htt)) + goto err_rx_attach; + + /* + * Prefetch enough data to satisfy target + * classification engine. + * This is for LL chips. HL chips will probably + * transfer all frame in the tx fragment. + */ + htt->prefetch_len = + 36 + /* 802.11 + qos + ht */ + 4 + /* 802.1q */ + 8 + /* llc snap */ + 2; /* ip4 dscp or ip6 priority */ + + return htt; + +err_rx_attach: + ath10k_htt_tx_detach(htt); +err_htc_attach: + kfree(htt); + return NULL; +} + +#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ) + +static int ath10k_htt_verify_version(struct ath10k_htt *htt) +{ + ath10k_dbg(ATH10K_DBG_HTT, + "htt target version %d.%d; host version %d.%d\n", + htt->target_version_major, + htt->target_version_minor, + HTT_CURRENT_VERSION_MAJOR, + HTT_CURRENT_VERSION_MINOR); + + if (htt->target_version_major != HTT_CURRENT_VERSION_MAJOR) { + ath10k_err("htt major versions are incompatible!\n"); + return -ENOTSUPP; + } + + if (htt->target_version_minor != HTT_CURRENT_VERSION_MINOR) + ath10k_warn("htt minor version differ but still compatible\n"); + + return 0; +} + +int ath10k_htt_attach_target(struct ath10k_htt *htt) +{ + int status; + + init_completion(&htt->target_version_received); + + status = ath10k_htt_h2t_ver_req_msg(htt); + if (status) + return status; + + status = wait_for_completion_timeout(&htt->target_version_received, + HTT_TARGET_VERSION_TIMEOUT_HZ); + if (status <= 0) { + ath10k_warn("htt version request timed out\n"); + return -ETIMEDOUT; + } + + status = ath10k_htt_verify_version(htt); + if (status) + return status; + + return ath10k_htt_send_rx_ring_cfg_ll(htt); +} + +void ath10k_htt_detach(struct ath10k_htt *htt) +{ + ath10k_htt_rx_detach(htt); + ath10k_htt_tx_detach(htt); + kfree(htt); +} diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h new file mode 100644 index 000000000000..a7a7aa040536 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -0,0 +1,1338 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HTT_H_ +#define _HTT_H_ + +#include + +#include "core.h" +#include "htc.h" +#include "rx_desc.h" + +#define HTT_CURRENT_VERSION_MAJOR 2 +#define HTT_CURRENT_VERSION_MINOR 1 + +enum htt_dbg_stats_type { + HTT_DBG_STATS_WAL_PDEV_TXRX = 1 << 0, + HTT_DBG_STATS_RX_REORDER = 1 << 1, + HTT_DBG_STATS_RX_RATE_INFO = 1 << 2, + HTT_DBG_STATS_TX_PPDU_LOG = 1 << 3, + HTT_DBG_STATS_TX_RATE_INFO = 1 << 4, + /* bits 5-23 currently reserved */ + + HTT_DBG_NUM_STATS /* keep this last */ +}; + +enum htt_h2t_msg_type { /* host-to-target */ + HTT_H2T_MSG_TYPE_VERSION_REQ = 0, + HTT_H2T_MSG_TYPE_TX_FRM = 1, + HTT_H2T_MSG_TYPE_RX_RING_CFG = 2, + HTT_H2T_MSG_TYPE_STATS_REQ = 3, + HTT_H2T_MSG_TYPE_SYNC = 4, + HTT_H2T_MSG_TYPE_AGGR_CFG = 5, + HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG = 6, + HTT_H2T_MSG_TYPE_MGMT_TX = 7, + + HTT_H2T_NUM_MSGS /* keep this last */ +}; + +struct htt_cmd_hdr { + u8 msg_type; +} __packed; + +struct htt_ver_req { + u8 pad[sizeof(u32) - sizeof(struct htt_cmd_hdr)]; +} __packed; + +/* + * HTT tx MSDU descriptor + * + * The HTT tx MSDU descriptor is created by the host HTT SW for each + * tx MSDU. The HTT tx MSDU descriptor contains the information that + * the target firmware needs for the FW's tx processing, particularly + * for creating the HW msdu descriptor. + * The same HTT tx descriptor is used for HL and LL systems, though + * a few fields within the tx descriptor are used only by LL or + * only by HL. + * The HTT tx descriptor is defined in two manners: by a struct with + * bitfields, and by a series of [dword offset, bit mask, bit shift] + * definitions. + * The target should use the struct def, for simplicitly and clarity, + * but the host shall use the bit-mast + bit-shift defs, to be endian- + * neutral. Specifically, the host shall use the get/set macros built + * around the mask + shift defs. + */ +struct htt_data_tx_desc_frag { + __le32 paddr; + __le32 len; +} __packed; + +enum htt_data_tx_desc_flags0 { + HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT = 1 << 0, + HTT_DATA_TX_DESC_FLAGS0_NO_AGGR = 1 << 1, + HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT = 1 << 2, + HTT_DATA_TX_DESC_FLAGS0_NO_CLASSIFY = 1 << 3, + HTT_DATA_TX_DESC_FLAGS0_RSVD0 = 1 << 4 +#define HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE_MASK 0xE0 +#define HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE_LSB 5 +}; + +enum htt_data_tx_desc_flags1 { +#define HTT_DATA_TX_DESC_FLAGS1_VDEV_ID_BITS 6 +#define HTT_DATA_TX_DESC_FLAGS1_VDEV_ID_MASK 0x003F +#define HTT_DATA_TX_DESC_FLAGS1_VDEV_ID_LSB 0 +#define HTT_DATA_TX_DESC_FLAGS1_EXT_TID_BITS 5 +#define HTT_DATA_TX_DESC_FLAGS1_EXT_TID_MASK 0x07C0 +#define HTT_DATA_TX_DESC_FLAGS1_EXT_TID_LSB 6 + HTT_DATA_TX_DESC_FLAGS1_POSTPONED = 1 << 11, + HTT_DATA_TX_DESC_FLAGS1_MORE_IN_BATCH = 1 << 12, + HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD = 1 << 13, + HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD = 1 << 14, + HTT_DATA_TX_DESC_FLAGS1_RSVD1 = 1 << 15 +}; + +enum htt_data_tx_ext_tid { + HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST = 16, + HTT_DATA_TX_EXT_TID_MGMT = 17, + HTT_DATA_TX_EXT_TID_INVALID = 31 +}; + +#define HTT_INVALID_PEERID 0xFFFF + +/* + * htt_data_tx_desc - used for data tx path + * + * Note: vdev_id irrelevant for pkt_type == raw and no_classify == 1. + * ext_tid: for qos-data frames (0-15), see %HTT_DATA_TX_EXT_TID_ + * for special kinds of tids + * postponed: only for HL hosts. indicates if this is a resend + * (HL hosts manage queues on the host ) + * more_in_batch: only for HL hosts. indicates if more packets are + * pending. this allows target to wait and aggregate + */ +struct htt_data_tx_desc { + u8 flags0; /* %HTT_DATA_TX_DESC_FLAGS0_ */ + __le16 flags1; /* %HTT_DATA_TX_DESC_FLAGS1_ */ + __le16 len; + __le16 id; + __le32 frags_paddr; + __le32 peerid; + u8 prefetch[0]; /* start of frame, for FW classification engine */ +} __packed; + +enum htt_rx_ring_flags { + HTT_RX_RING_FLAGS_MAC80211_HDR = 1 << 0, + HTT_RX_RING_FLAGS_MSDU_PAYLOAD = 1 << 1, + HTT_RX_RING_FLAGS_PPDU_START = 1 << 2, + HTT_RX_RING_FLAGS_PPDU_END = 1 << 3, + HTT_RX_RING_FLAGS_MPDU_START = 1 << 4, + HTT_RX_RING_FLAGS_MPDU_END = 1 << 5, + HTT_RX_RING_FLAGS_MSDU_START = 1 << 6, + HTT_RX_RING_FLAGS_MSDU_END = 1 << 7, + HTT_RX_RING_FLAGS_RX_ATTENTION = 1 << 8, + HTT_RX_RING_FLAGS_FRAG_INFO = 1 << 9, + HTT_RX_RING_FLAGS_UNICAST_RX = 1 << 10, + HTT_RX_RING_FLAGS_MULTICAST_RX = 1 << 11, + HTT_RX_RING_FLAGS_CTRL_RX = 1 << 12, + HTT_RX_RING_FLAGS_MGMT_RX = 1 << 13, + HTT_RX_RING_FLAGS_NULL_RX = 1 << 14, + HTT_RX_RING_FLAGS_PHY_DATA_RX = 1 << 15 +}; + +struct htt_rx_ring_setup_ring { + __le32 fw_idx_shadow_reg_paddr; + __le32 rx_ring_base_paddr; + __le16 rx_ring_len; /* in 4-byte words */ + __le16 rx_ring_bufsize; /* rx skb size - in bytes */ + __le16 flags; /* %HTT_RX_RING_FLAGS_ */ + __le16 fw_idx_init_val; + + /* the following offsets are in 4-byte units */ + __le16 mac80211_hdr_offset; + __le16 msdu_payload_offset; + __le16 ppdu_start_offset; + __le16 ppdu_end_offset; + __le16 mpdu_start_offset; + __le16 mpdu_end_offset; + __le16 msdu_start_offset; + __le16 msdu_end_offset; + __le16 rx_attention_offset; + __le16 frag_info_offset; +} __packed; + +struct htt_rx_ring_setup_hdr { + u8 num_rings; /* supported values: 1, 2 */ + __le16 rsvd0; +} __packed; + +struct htt_rx_ring_setup { + struct htt_rx_ring_setup_hdr hdr; + struct htt_rx_ring_setup_ring rings[0]; +} __packed; + +/* + * htt_stats_req - request target to send specified statistics + * + * @msg_type: hardcoded %HTT_H2T_MSG_TYPE_STATS_REQ + * @upload_types: see %htt_dbg_stats_type. this is 24bit field actually + * so make sure its little-endian. + * @reset_types: see %htt_dbg_stats_type. this is 24bit field actually + * so make sure its little-endian. + * @cfg_val: stat_type specific configuration + * @stat_type: see %htt_dbg_stats_type + * @cookie_lsb: used for confirmation message from target->host + * @cookie_msb: ditto as %cookie + */ +struct htt_stats_req { + u8 upload_types[3]; + u8 rsvd0; + u8 reset_types[3]; + struct { + u8 mpdu_bytes; + u8 mpdu_num_msdus; + u8 msdu_bytes; + } __packed; + u8 stat_type; + __le32 cookie_lsb; + __le32 cookie_msb; +} __packed; + +#define HTT_STATS_REQ_CFG_STAT_TYPE_INVALID 0xff + +/* + * htt_oob_sync_req - request out-of-band sync + * + * The HTT SYNC tells the target to suspend processing of subsequent + * HTT host-to-target messages until some other target agent locally + * informs the target HTT FW that the current sync counter is equal to + * or greater than (in a modulo sense) the sync counter specified in + * the SYNC message. + * + * This allows other host-target components to synchronize their operation + * with HTT, e.g. to ensure that tx frames don't get transmitted until a + * security key has been downloaded to and activated by the target. + * In the absence of any explicit synchronization counter value + * specification, the target HTT FW will use zero as the default current + * sync value. + * + * The HTT target FW will suspend its host->target message processing as long + * as 0 < (in-band sync counter - out-of-band sync counter) & 0xff < 128. + */ +struct htt_oob_sync_req { + u8 sync_count; + __le16 rsvd0; +} __packed; + +#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F +#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0 + +struct htt_aggr_conf { + u8 max_num_ampdu_subframes; + union { + /* dont use bitfields; undefined behaviour */ + u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */ + u8 max_num_amsdu_subframes:5; + } __packed; +} __packed; + +#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 + +struct htt_mgmt_tx_desc { + u8 pad[sizeof(u32) - sizeof(struct htt_cmd_hdr)]; + __le32 msdu_paddr; + __le32 desc_id; + __le32 len; + __le32 vdev_id; + u8 hdr[HTT_MGMT_FRM_HDR_DOWNLOAD_LEN]; +} __packed; + +enum htt_mgmt_tx_status { + HTT_MGMT_TX_STATUS_OK = 0, + HTT_MGMT_TX_STATUS_RETRY = 1, + HTT_MGMT_TX_STATUS_DROP = 2 +}; + +/*=== target -> host messages ===============================================*/ + + +enum htt_t2h_msg_type { + HTT_T2H_MSG_TYPE_VERSION_CONF = 0x0, + HTT_T2H_MSG_TYPE_RX_IND = 0x1, + HTT_T2H_MSG_TYPE_RX_FLUSH = 0x2, + HTT_T2H_MSG_TYPE_PEER_MAP = 0x3, + HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x4, + HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5, + HTT_T2H_MSG_TYPE_RX_DELBA = 0x6, + HTT_T2H_MSG_TYPE_TX_COMPL_IND = 0x7, + HTT_T2H_MSG_TYPE_PKTLOG = 0x8, + HTT_T2H_MSG_TYPE_STATS_CONF = 0x9, + HTT_T2H_MSG_TYPE_RX_FRAG_IND = 0xa, + HTT_T2H_MSG_TYPE_SEC_IND = 0xb, + HTT_T2H_MSG_TYPE_RC_UPDATE_IND = 0xc, + HTT_T2H_MSG_TYPE_TX_INSPECT_IND = 0xd, + HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION = 0xe, + HTT_T2H_MSG_TYPE_TEST, + /* keep this last */ + HTT_T2H_NUM_MSGS +}; + +/* + * htt_resp_hdr - header for target-to-host messages + * + * msg_type: see htt_t2h_msg_type + */ +struct htt_resp_hdr { + u8 msg_type; +} __packed; + +#define HTT_RESP_HDR_MSG_TYPE_OFFSET 0 +#define HTT_RESP_HDR_MSG_TYPE_MASK 0xff +#define HTT_RESP_HDR_MSG_TYPE_LSB 0 + +/* htt_ver_resp - response sent for htt_ver_req */ +struct htt_ver_resp { + u8 minor; + u8 major; + u8 rsvd0; +} __packed; + +struct htt_mgmt_tx_completion { + u8 rsvd0; + u8 rsvd1; + u8 rsvd2; + __le32 desc_id; + __le32 status; +} __packed; + +#define HTT_RX_INDICATION_INFO0_EXT_TID_MASK (0x3F) +#define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0) +#define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 6) +#define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 7) + +#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F +#define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0 +#define HTT_RX_INDICATION_INFO1_FLUSH_END_SEQNO_MASK 0x00000FC0 +#define HTT_RX_INDICATION_INFO1_FLUSH_END_SEQNO_LSB 6 +#define HTT_RX_INDICATION_INFO1_RELEASE_START_SEQNO_MASK 0x0003F000 +#define HTT_RX_INDICATION_INFO1_RELEASE_START_SEQNO_LSB 12 +#define HTT_RX_INDICATION_INFO1_RELEASE_END_SEQNO_MASK 0x00FC0000 +#define HTT_RX_INDICATION_INFO1_RELEASE_END_SEQNO_LSB 18 +#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_MASK 0xFF000000 +#define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_LSB 24 + +struct htt_rx_indication_hdr { + u8 info0; /* %HTT_RX_INDICATION_INFO0_ */ + __le16 peer_id; + __le32 info1; /* %HTT_RX_INDICATION_INFO1_ */ +} __packed; + +#define HTT_RX_INDICATION_INFO0_PHY_ERR_VALID (1 << 0) +#define HTT_RX_INDICATION_INFO0_LEGACY_RATE_MASK (0x1E) +#define HTT_RX_INDICATION_INFO0_LEGACY_RATE_LSB (1) +#define HTT_RX_INDICATION_INFO0_LEGACY_RATE_CCK (1 << 5) +#define HTT_RX_INDICATION_INFO0_END_VALID (1 << 6) +#define HTT_RX_INDICATION_INFO0_START_VALID (1 << 7) + +#define HTT_RX_INDICATION_INFO1_VHT_SIG_A1_MASK 0x00FFFFFF +#define HTT_RX_INDICATION_INFO1_VHT_SIG_A1_LSB 0 +#define HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE_MASK 0xFF000000 +#define HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE_LSB 24 + +#define HTT_RX_INDICATION_INFO2_VHT_SIG_A1_MASK 0x00FFFFFF +#define HTT_RX_INDICATION_INFO2_VHT_SIG_A1_LSB 0 +#define HTT_RX_INDICATION_INFO2_SERVICE_MASK 0xFF000000 +#define HTT_RX_INDICATION_INFO2_SERVICE_LSB 24 + +enum htt_rx_legacy_rate { + HTT_RX_OFDM_48 = 0, + HTT_RX_OFDM_24 = 1, + HTT_RX_OFDM_12, + HTT_RX_OFDM_6, + HTT_RX_OFDM_54, + HTT_RX_OFDM_36, + HTT_RX_OFDM_18, + HTT_RX_OFDM_9, + + /* long preamble */ + HTT_RX_CCK_11_LP = 0, + HTT_RX_CCK_5_5_LP = 1, + HTT_RX_CCK_2_LP, + HTT_RX_CCK_1_LP, + /* short preamble */ + HTT_RX_CCK_11_SP, + HTT_RX_CCK_5_5_SP, + HTT_RX_CCK_2_SP +}; + +enum htt_rx_legacy_rate_type { + HTT_RX_LEGACY_RATE_OFDM = 0, + HTT_RX_LEGACY_RATE_CCK +}; + +enum htt_rx_preamble_type { + HTT_RX_LEGACY = 0x4, + HTT_RX_HT = 0x8, + HTT_RX_HT_WITH_TXBF = 0x9, + HTT_RX_VHT = 0xC, + HTT_RX_VHT_WITH_TXBF = 0xD, +}; + +/* + * Fields: phy_err_valid, phy_err_code, tsf, + * usec_timestamp, sub_usec_timestamp + * ..are valid only if end_valid == 1. + * + * Fields: rssi_chains, legacy_rate_type, + * legacy_rate_cck, preamble_type, service, + * vht_sig_* + * ..are valid only if start_valid == 1; + */ +struct htt_rx_indication_ppdu { + u8 combined_rssi; + u8 sub_usec_timestamp; + u8 phy_err_code; + u8 info0; /* HTT_RX_INDICATION_INFO0_ */ + struct { + u8 pri20_db; + u8 ext20_db; + u8 ext40_db; + u8 ext80_db; + } __packed rssi_chains[4]; + __le32 tsf; + __le32 usec_timestamp; + __le32 info1; /* HTT_RX_INDICATION_INFO1_ */ + __le32 info2; /* HTT_RX_INDICATION_INFO2_ */ +} __packed; + +enum htt_rx_mpdu_status { + HTT_RX_IND_MPDU_STATUS_UNKNOWN = 0x0, + HTT_RX_IND_MPDU_STATUS_OK, + HTT_RX_IND_MPDU_STATUS_ERR_FCS, + HTT_RX_IND_MPDU_STATUS_ERR_DUP, + HTT_RX_IND_MPDU_STATUS_ERR_REPLAY, + HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER, + /* only accept EAPOL frames */ + HTT_RX_IND_MPDU_STATUS_UNAUTH_PEER, + HTT_RX_IND_MPDU_STATUS_OUT_OF_SYNC, + /* Non-data in promiscous mode */ + HTT_RX_IND_MPDU_STATUS_MGMT_CTRL, + HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR, + HTT_RX_IND_MPDU_STATUS_DECRYPT_ERR, + HTT_RX_IND_MPDU_STATUS_MPDU_LENGTH_ERR, + HTT_RX_IND_MPDU_STATUS_ENCRYPT_REQUIRED_ERR, + HTT_RX_IND_MPDU_STATUS_PRIVACY_ERR, + + /* + * MISC: discard for unspecified reasons. + * Leave this enum value last. + */ + HTT_RX_IND_MPDU_STATUS_ERR_MISC = 0xFF +}; + +struct htt_rx_indication_mpdu_range { + u8 mpdu_count; + u8 mpdu_range_status; /* %htt_rx_mpdu_status */ + u8 pad0; + u8 pad1; +} __packed; + +struct htt_rx_indication_prefix { + __le16 fw_rx_desc_bytes; + u8 pad0; + u8 pad1; +}; + +struct htt_rx_indication { + struct htt_rx_indication_hdr hdr; + struct htt_rx_indication_ppdu ppdu; + struct htt_rx_indication_prefix prefix; + + /* + * the following fields are both dynamically sized, so + * take care addressing them + */ + + /* the size of this is %fw_rx_desc_bytes */ + struct fw_rx_desc_base fw_desc; + + /* + * %mpdu_ranges starts after &%prefix + roundup(%fw_rx_desc_bytes, 4) + * and has %num_mpdu_ranges elements. + */ + struct htt_rx_indication_mpdu_range mpdu_ranges[0]; +} __packed; + +static inline struct htt_rx_indication_mpdu_range * + htt_rx_ind_get_mpdu_ranges(struct htt_rx_indication *rx_ind) +{ + void *ptr = rx_ind; + + ptr += sizeof(rx_ind->hdr) + + sizeof(rx_ind->ppdu) + + sizeof(rx_ind->prefix) + + roundup(__le16_to_cpu(rx_ind->prefix.fw_rx_desc_bytes), 4); + return ptr; +} + +enum htt_rx_flush_mpdu_status { + HTT_RX_FLUSH_MPDU_DISCARD = 0, + HTT_RX_FLUSH_MPDU_REORDER = 1, +}; + +/* + * htt_rx_flush - discard or reorder given range of mpdus + * + * Note: host must check if all sequence numbers between + * [seq_num_start, seq_num_end-1] are valid. + */ +struct htt_rx_flush { + __le16 peer_id; + u8 tid; + u8 rsvd0; + u8 mpdu_status; /* %htt_rx_flush_mpdu_status */ + u8 seq_num_start; /* it is 6 LSBs of 802.11 seq no */ + u8 seq_num_end; /* it is 6 LSBs of 802.11 seq no */ +}; + +struct htt_rx_peer_map { + u8 vdev_id; + __le16 peer_id; + u8 addr[6]; + u8 rsvd0; + u8 rsvd1; +} __packed; + +struct htt_rx_peer_unmap { + u8 rsvd0; + __le16 peer_id; +} __packed; + +enum htt_security_types { + HTT_SECURITY_NONE, + HTT_SECURITY_WEP128, + HTT_SECURITY_WEP104, + HTT_SECURITY_WEP40, + HTT_SECURITY_TKIP, + HTT_SECURITY_TKIP_NOMIC, + HTT_SECURITY_AES_CCMP, + HTT_SECURITY_WAPI, + + HTT_NUM_SECURITY_TYPES /* keep this last! */ +}; + +enum htt_security_flags { +#define HTT_SECURITY_TYPE_MASK 0x7F +#define HTT_SECURITY_TYPE_LSB 0 + HTT_SECURITY_IS_UNICAST = 1 << 7 +}; + +struct htt_security_indication { + union { + /* dont use bitfields; undefined behaviour */ + u8 flags; /* %htt_security_flags */ + struct { + u8 security_type:7, /* %htt_security_types */ + is_unicast:1; + } __packed; + } __packed; + __le16 peer_id; + u8 michael_key[8]; + u8 wapi_rsc[16]; +} __packed; + +#define HTT_RX_BA_INFO0_TID_MASK 0x000F +#define HTT_RX_BA_INFO0_TID_LSB 0 +#define HTT_RX_BA_INFO0_PEER_ID_MASK 0xFFF0 +#define HTT_RX_BA_INFO0_PEER_ID_LSB 4 + +struct htt_rx_addba { + u8 window_size; + __le16 info0; /* %HTT_RX_BA_INFO0_ */ +} __packed; + +struct htt_rx_delba { + u8 rsvd0; + __le16 info0; /* %HTT_RX_BA_INFO0_ */ +} __packed; + +enum htt_data_tx_status { + HTT_DATA_TX_STATUS_OK = 0, + HTT_DATA_TX_STATUS_DISCARD = 1, + HTT_DATA_TX_STATUS_NO_ACK = 2, + HTT_DATA_TX_STATUS_POSTPONE = 3, /* HL only */ + HTT_DATA_TX_STATUS_DOWNLOAD_FAIL = 128 +}; + +enum htt_data_tx_flags { +#define HTT_DATA_TX_STATUS_MASK 0x07 +#define HTT_DATA_TX_STATUS_LSB 0 +#define HTT_DATA_TX_TID_MASK 0x78 +#define HTT_DATA_TX_TID_LSB 3 + HTT_DATA_TX_TID_INVALID = 1 << 7 +}; + +#define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF + +struct htt_data_tx_completion { + union { + u8 flags; + struct { + u8 status:3, + tid:4, + tid_invalid:1; + } __packed; + } __packed; + u8 num_msdus; + u8 rsvd0; + __le16 msdus[0]; /* variable length based on %num_msdus */ +} __packed; + +struct htt_tx_compl_ind_base { + u32 hdr; + u16 payload[1/*or more*/]; +} __packed; + +struct htt_rc_tx_done_params { + u32 rate_code; + u32 rate_code_flags; + u32 flags; + u32 num_enqued; /* 1 for non-AMPDU */ + u32 num_retries; + u32 num_failed; /* for AMPDU */ + u32 ack_rssi; + u32 time_stamp; + u32 is_probe; +}; + +struct htt_rc_update { + u8 vdev_id; + __le16 peer_id; + u8 addr[6]; + u8 num_elems; + u8 rsvd0; + struct htt_rc_tx_done_params params[0]; /* variable length %num_elems */ +} __packed; + +/* see htt_rx_indication for similar fields and descriptions */ +struct htt_rx_fragment_indication { + union { + u8 info0; /* %HTT_RX_FRAG_IND_INFO0_ */ + struct { + u8 ext_tid:5, + flush_valid:1; + } __packed; + } __packed; + __le16 peer_id; + __le32 info1; /* %HTT_RX_FRAG_IND_INFO1_ */ + __le16 fw_rx_desc_bytes; + __le16 rsvd0; + + u8 fw_msdu_rx_desc[0]; +} __packed; + +#define HTT_RX_FRAG_IND_INFO0_EXT_TID_MASK 0x1F +#define HTT_RX_FRAG_IND_INFO0_EXT_TID_LSB 0 +#define HTT_RX_FRAG_IND_INFO0_FLUSH_VALID_MASK 0x20 +#define HTT_RX_FRAG_IND_INFO0_FLUSH_VALID_LSB 5 + +#define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_START_MASK 0x0000003F +#define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_START_LSB 0 +#define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_MASK 0x00000FC0 +#define HTT_RX_FRAG_IND_INFO1_FLUSH_SEQ_NUM_END_LSB 6 + +/* + * target -> host test message definition + * + * The following field definitions describe the format of the test + * message sent from the target to the host. + * The message consists of a 4-octet header, followed by a variable + * number of 32-bit integer values, followed by a variable number + * of 8-bit character values. + * + * |31 16|15 8|7 0| + * |-----------------------------------------------------------| + * | num chars | num ints | msg type | + * |-----------------------------------------------------------| + * | int 0 | + * |-----------------------------------------------------------| + * | int 1 | + * |-----------------------------------------------------------| + * | ... | + * |-----------------------------------------------------------| + * | char 3 | char 2 | char 1 | char 0 | + * |-----------------------------------------------------------| + * | | | ... | char 4 | + * |-----------------------------------------------------------| + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a test message + * Value: HTT_MSG_TYPE_TEST + * - NUM_INTS + * Bits 15:8 + * Purpose: indicate how many 32-bit integers follow the message header + * - NUM_CHARS + * Bits 31:16 + * Purpose: indicate how many 8-bit charaters follow the series of integers + */ +struct htt_rx_test { + u8 num_ints; + __le16 num_chars; + + /* payload consists of 2 lists: + * a) num_ints * sizeof(__le32) + * b) num_chars * sizeof(u8) aligned to 4bytes */ + u8 payload[0]; +} __packed; + +static inline __le32 *htt_rx_test_get_ints(struct htt_rx_test *rx_test) +{ + return (__le32 *)rx_test->payload; +} + +static inline u8 *htt_rx_test_get_chars(struct htt_rx_test *rx_test) +{ + return rx_test->payload + (rx_test->num_ints * sizeof(__le32)); +} + +/* + * target -> host packet log message + * + * The following field definitions describe the format of the packet log + * message sent from the target to the host. + * The message consists of a 4-octet header,followed by a variable number + * of 32-bit character values. + * + * |31 24|23 16|15 8|7 0| + * |-----------------------------------------------------------| + * | | | | msg type | + * |-----------------------------------------------------------| + * | payload | + * |-----------------------------------------------------------| + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this as a test message + * Value: HTT_MSG_TYPE_PACKETLOG + */ +struct htt_pktlog_msg { + u8 pad[3]; + __le32 payload[1 /* or more */]; +} __packed; + +struct htt_dbg_stats_rx_reorder_stats { + /* Non QoS MPDUs received */ + __le32 deliver_non_qos; + + /* MPDUs received in-order */ + __le32 deliver_in_order; + + /* Flush due to reorder timer expired */ + __le32 deliver_flush_timeout; + + /* Flush due to move out of window */ + __le32 deliver_flush_oow; + + /* Flush due to DELBA */ + __le32 deliver_flush_delba; + + /* MPDUs dropped due to FCS error */ + __le32 fcs_error; + + /* MPDUs dropped due to monitor mode non-data packet */ + __le32 mgmt_ctrl; + + /* MPDUs dropped due to invalid peer */ + __le32 invalid_peer; + + /* MPDUs dropped due to duplication (non aggregation) */ + __le32 dup_non_aggr; + + /* MPDUs dropped due to processed before */ + __le32 dup_past; + + /* MPDUs dropped due to duplicate in reorder queue */ + __le32 dup_in_reorder; + + /* Reorder timeout happened */ + __le32 reorder_timeout; + + /* invalid bar ssn */ + __le32 invalid_bar_ssn; + + /* reorder reset due to bar ssn */ + __le32 ssn_reset; +}; + +struct htt_dbg_stats_wal_tx_stats { + /* Num HTT cookies queued to dispatch list */ + __le32 comp_queued; + + /* Num HTT cookies dispatched */ + __le32 comp_delivered; + + /* Num MSDU queued to WAL */ + __le32 msdu_enqued; + + /* Num MPDU queue to WAL */ + __le32 mpdu_enqued; + + /* Num MSDUs dropped by WMM limit */ + __le32 wmm_drop; + + /* Num Local frames queued */ + __le32 local_enqued; + + /* Num Local frames done */ + __le32 local_freed; + + /* Num queued to HW */ + __le32 hw_queued; + + /* Num PPDU reaped from HW */ + __le32 hw_reaped; + + /* Num underruns */ + __le32 underrun; + + /* Num PPDUs cleaned up in TX abort */ + __le32 tx_abort; + + /* Num MPDUs requed by SW */ + __le32 mpdus_requed; + + /* excessive retries */ + __le32 tx_ko; + + /* data hw rate code */ + __le32 data_rc; + + /* Scheduler self triggers */ + __le32 self_triggers; + + /* frames dropped due to excessive sw retries */ + __le32 sw_retry_failure; + + /* illegal rate phy errors */ + __le32 illgl_rate_phy_err; + + /* wal pdev continous xretry */ + __le32 pdev_cont_xretry; + + /* wal pdev continous xretry */ + __le32 pdev_tx_timeout; + + /* wal pdev resets */ + __le32 pdev_resets; + + __le32 phy_underrun; + + /* MPDU is more than txop limit */ + __le32 txop_ovf; +} __packed; + +struct htt_dbg_stats_wal_rx_stats { + /* Cnts any change in ring routing mid-ppdu */ + __le32 mid_ppdu_route_change; + + /* Total number of statuses processed */ + __le32 status_rcvd; + + /* Extra frags on rings 0-3 */ + __le32 r0_frags; + __le32 r1_frags; + __le32 r2_frags; + __le32 r3_frags; + + /* MSDUs / MPDUs delivered to HTT */ + __le32 htt_msdus; + __le32 htt_mpdus; + + /* MSDUs / MPDUs delivered to local stack */ + __le32 loc_msdus; + __le32 loc_mpdus; + + /* AMSDUs that have more MSDUs than the status ring size */ + __le32 oversize_amsdu; + + /* Number of PHY errors */ + __le32 phy_errs; + + /* Number of PHY errors drops */ + __le32 phy_err_drop; + + /* Number of mpdu errors - FCS, MIC, ENC etc. */ + __le32 mpdu_errs; +} __packed; + +struct htt_dbg_stats_wal_peer_stats { + __le32 dummy; /* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */ +} __packed; + +struct htt_dbg_stats_wal_pdev_txrx { + struct htt_dbg_stats_wal_tx_stats tx_stats; + struct htt_dbg_stats_wal_rx_stats rx_stats; + struct htt_dbg_stats_wal_peer_stats peer_stats; +} __packed; + +struct htt_dbg_stats_rx_rate_info { + __le32 mcs[10]; + __le32 sgi[10]; + __le32 nss[4]; + __le32 stbc[10]; + __le32 bw[3]; + __le32 pream[6]; + __le32 ldpc; + __le32 txbf; +}; + +/* + * htt_dbg_stats_status - + * present - The requested stats have been delivered in full. + * This indicates that either the stats information was contained + * in its entirety within this message, or else this message + * completes the delivery of the requested stats info that was + * partially delivered through earlier STATS_CONF messages. + * partial - The requested stats have been delivered in part. + * One or more subsequent STATS_CONF messages with the same + * cookie value will be sent to deliver the remainder of the + * information. + * error - The requested stats could not be delivered, for example due + * to a shortage of memory to construct a message holding the + * requested stats. + * invalid - The requested stat type is either not recognized, or the + * target is configured to not gather the stats type in question. + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * series_done - This special value indicates that no further stats info + * elements are present within a series of stats info elems + * (within a stats upload confirmation message). + */ +enum htt_dbg_stats_status { + HTT_DBG_STATS_STATUS_PRESENT = 0, + HTT_DBG_STATS_STATUS_PARTIAL = 1, + HTT_DBG_STATS_STATUS_ERROR = 2, + HTT_DBG_STATS_STATUS_INVALID = 3, + HTT_DBG_STATS_STATUS_SERIES_DONE = 7 +}; + +/* + * target -> host statistics upload + * + * The following field definitions describe the format of the HTT target + * to host stats upload confirmation message. + * The message contains a cookie echoed from the HTT host->target stats + * upload request, which identifies which request the confirmation is + * for, and a series of tag-length-value stats information elements. + * The tag-length header for each stats info element also includes a + * status field, to indicate whether the request for the stat type in + * question was fully met, partially met, unable to be met, or invalid + * (if the stat type in question is disabled in the target). + * A special value of all 1's in this status field is used to indicate + * the end of the series of stats info elements. + * + * + * |31 16|15 8|7 5|4 0| + * |------------------------------------------------------------| + * | reserved | msg type | + * |------------------------------------------------------------| + * | cookie LSBs | + * |------------------------------------------------------------| + * | cookie MSBs | + * |------------------------------------------------------------| + * | stats entry length | reserved | S |stat type| + * |------------------------------------------------------------| + * | | + * | type-specific stats info | + * | | + * |------------------------------------------------------------| + * | stats entry length | reserved | S |stat type| + * |------------------------------------------------------------| + * | | + * | type-specific stats info | + * | | + * |------------------------------------------------------------| + * | n/a | reserved | 111 | n/a | + * |------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Purpose: identifies this is a statistics upload confirmation message + * Value: 0x9 + * - COOKIE_LSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: LSBs of the opaque cookie specified by the host-side requestor + * - COOKIE_MSBS + * Bits 31:0 + * Purpose: Provide a mechanism to match a target->host stats confirmation + * message with its preceding host->target stats request message. + * Value: MSBs of the opaque cookie specified by the host-side requestor + * + * Stats Information Element tag-length header fields: + * - STAT_TYPE + * Bits 4:0 + * Purpose: identifies the type of statistics info held in the + * following information element + * Value: htt_dbg_stats_type + * - STATUS + * Bits 7:5 + * Purpose: indicate whether the requested stats are present + * Value: htt_dbg_stats_status, including a special value (0x7) to mark + * the completion of the stats entry series + * - LENGTH + * Bits 31:16 + * Purpose: indicate the stats information size + * Value: This field specifies the number of bytes of stats information + * that follows the element tag-length header. + * It is expected but not required that this length is a multiple of + * 4 bytes. Even if the length is not an integer multiple of 4, the + * subsequent stats entry header will begin on a 4-byte aligned + * boundary. + */ + +#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_MASK 0x1F +#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_LSB 0 +#define HTT_STATS_CONF_ITEM_INFO_STATUS_MASK 0xE0 +#define HTT_STATS_CONF_ITEM_INFO_STATUS_LSB 5 + +struct htt_stats_conf_item { + union { + u8 info; + struct { + u8 stat_type:5; /* %HTT_DBG_STATS_ */ + u8 status:3; /* %HTT_DBG_STATS_STATUS_ */ + } __packed; + } __packed; + u8 pad; + __le16 length; + u8 payload[0]; /* roundup(length, 4) long */ +} __packed; + +struct htt_stats_conf { + u8 pad[3]; + __le32 cookie_lsb; + __le32 cookie_msb; + + /* each item has variable length! */ + struct htt_stats_conf_item items[0]; +} __packed; + +static inline struct htt_stats_conf_item *htt_stats_conf_next_item( + const struct htt_stats_conf_item *item) +{ + return (void *)item + sizeof(*item) + roundup(item->length, 4); +} +/* + * host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank + * + * The following field definitions describe the format of the HTT host + * to target frag_desc/msdu_ext bank configuration message. + * The message contains the based address and the min and max id of the + * MSDU_EXT/FRAG_DESC that will be used by the HTT to map MSDU DESC and + * MSDU_EXT/FRAG_DESC. + * HTT will use id in HTT descriptor instead sending the frag_desc_ptr. + * For QCA988X HW the firmware will use fragment_desc_ptr but in WIFI2.0 + * the hardware does the mapping/translation. + * + * Total banks that can be configured is configured to 16. + * + * This should be called before any TX has be initiated by the HTT + * + * |31 16|15 8|7 5|4 0| + * |------------------------------------------------------------| + * | DESC_SIZE | NUM_BANKS | RES |SWP|pdev| msg type | + * |------------------------------------------------------------| + * | BANK0_BASE_ADDRESS | + * |------------------------------------------------------------| + * | ... | + * |------------------------------------------------------------| + * | BANK15_BASE_ADDRESS | + * |------------------------------------------------------------| + * | BANK0_MAX_ID | BANK0_MIN_ID | + * |------------------------------------------------------------| + * | ... | + * |------------------------------------------------------------| + * | BANK15_MAX_ID | BANK15_MIN_ID | + * |------------------------------------------------------------| + * Header fields: + * - MSG_TYPE + * Bits 7:0 + * Value: 0x6 + * - BANKx_BASE_ADDRESS + * Bits 31:0 + * Purpose: Provide a mechanism to specify the base address of the MSDU_EXT + * bank physical/bus address. + * - BANKx_MIN_ID + * Bits 15:0 + * Purpose: Provide a mechanism to specify the min index that needs to + * mapped. + * - BANKx_MAX_ID + * Bits 31:16 + * Purpose: Provide a mechanism to specify the max index that needs to + * + */ +struct htt_frag_desc_bank_id { + __le16 bank_min_id; + __le16 bank_max_id; +} __packed; + +/* real is 16 but it wouldn't fit in the max htt message size + * so we use a conservatively safe value for now */ +#define HTT_FRAG_DESC_BANK_MAX 4 + +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 +#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2) + +struct htt_frag_desc_bank_cfg { + u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */ + u8 num_banks; + u8 desc_size; + __le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX]; + struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX]; +} __packed; + +union htt_rx_pn_t { + /* WEP: 24-bit PN */ + u32 pn24; + + /* TKIP or CCMP: 48-bit PN */ + u_int64_t pn48; + + /* WAPI: 128-bit PN */ + u_int64_t pn128[2]; +}; + +struct htt_cmd { + struct htt_cmd_hdr hdr; + union { + struct htt_ver_req ver_req; + struct htt_mgmt_tx_desc mgmt_tx; + struct htt_data_tx_desc data_tx; + struct htt_rx_ring_setup rx_setup; + struct htt_stats_req stats_req; + struct htt_oob_sync_req oob_sync_req; + struct htt_aggr_conf aggr_conf; + struct htt_frag_desc_bank_cfg frag_desc_bank_cfg; + }; +} __packed; + +struct htt_resp { + struct htt_resp_hdr hdr; + union { + struct htt_ver_resp ver_resp; + struct htt_mgmt_tx_completion mgmt_tx_completion; + struct htt_data_tx_completion data_tx_completion; + struct htt_rx_indication rx_ind; + struct htt_rx_fragment_indication rx_frag_ind; + struct htt_rx_peer_map peer_map; + struct htt_rx_peer_unmap peer_unmap; + struct htt_rx_flush rx_flush; + struct htt_rx_addba rx_addba; + struct htt_rx_delba rx_delba; + struct htt_security_indication security_indication; + struct htt_rc_update rc_update; + struct htt_rx_test rx_test; + struct htt_pktlog_msg pktlog_msg; + struct htt_stats_conf stats_conf; + }; +} __packed; + + +/*** host side structures follow ***/ + +struct htt_tx_done { + u32 msdu_id; + bool discard; + bool no_ack; +}; + +struct htt_peer_map_event { + u8 vdev_id; + u16 peer_id; + u8 addr[ETH_ALEN]; +}; + +struct htt_peer_unmap_event { + u16 peer_id; +}; + +struct htt_rx_info { + struct sk_buff *skb; + enum htt_rx_mpdu_status status; + enum htt_rx_mpdu_encrypt_type encrypt_type; + s8 signal; + struct { + u8 info0; + u32 info1; + u32 info2; + } rate; + bool fcs_err; +}; + +struct ath10k_htt { + struct ath10k *ar; + enum ath10k_htc_ep_id eid; + + int max_throughput_mbps; + u8 target_version_major; + u8 target_version_minor; + struct completion target_version_received; + + struct { + /* + * Ring of network buffer objects - This ring is + * used exclusively by the host SW. This ring + * mirrors the dev_addrs_ring that is shared + * between the host SW and the MAC HW. The host SW + * uses this netbufs ring to locate the network + * buffer objects whose data buffers the HW has + * filled. + */ + struct sk_buff **netbufs_ring; + /* + * Ring of buffer addresses - + * This ring holds the "physical" device address of the + * rx buffers the host SW provides for the MAC HW to + * fill. + */ + __le32 *paddrs_ring; + + /* + * Base address of ring, as a "physical" device address + * rather than a CPU address. + */ + dma_addr_t base_paddr; + + /* how many elems in the ring (power of 2) */ + int size; + + /* size - 1 */ + unsigned size_mask; + + /* how many rx buffers to keep in the ring */ + int fill_level; + + /* how many rx buffers (full+empty) are in the ring */ + int fill_cnt; + + /* + * alloc_idx - where HTT SW has deposited empty buffers + * This is allocated in consistent mem, so that the FW can + * read this variable, and program the HW's FW_IDX reg with + * the value of this shadow register. + */ + struct { + __le32 *vaddr; + dma_addr_t paddr; + } alloc_idx; + + /* where HTT SW has processed bufs filled by rx MAC DMA */ + struct { + unsigned msdu_payld; + } sw_rd_idx; + + /* + * refill_retry_timer - timer triggered when the ring is + * not refilled to the level expected + */ + struct timer_list refill_retry_timer; + + /* Protects access to all rx ring buffer state variables */ + spinlock_t lock; + } rx_ring; + + unsigned int prefetch_len; + + /* Protects access to %pending_tx, %used_msdu_ids */ + spinlock_t tx_lock; + int max_num_pending_tx; + int num_pending_tx; + struct sk_buff **pending_tx; + unsigned long *used_msdu_ids; /* bitmap */ + wait_queue_head_t empty_tx_wq; + + /* set if host-fw communication goes haywire + * used to avoid further failures */ + bool rx_confused; +}; + +#define RX_HTT_HDR_STATUS_LEN 64 + +/* This structure layout is programmed via rx ring setup + * so that FW knows how to transfer the rx descriptor to the host. + * Buffers like this are placed on the rx ring. */ +struct htt_rx_desc { + union { + /* This field is filled on the host using the msdu buffer + * from htt_rx_indication */ + struct fw_rx_desc_base fw_desc; + u32 pad; + } __packed; + struct { + struct rx_attention attention; + struct rx_frag_info frag_info; + struct rx_mpdu_start mpdu_start; + struct rx_msdu_start msdu_start; + struct rx_msdu_end msdu_end; + struct rx_mpdu_end mpdu_end; + struct rx_ppdu_start ppdu_start; + struct rx_ppdu_end ppdu_end; + } __packed; + u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; + u8 msdu_payload[0]; +}; + +#define HTT_RX_DESC_ALIGN 8 + +#define HTT_MAC_ADDR_LEN 6 + +/* + * FIX THIS + * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size, + * rounded up to a cache line size. + */ +#define HTT_RX_BUF_SIZE 1920 +#define HTT_RX_MSDU_SIZE (HTT_RX_BUF_SIZE - (int)sizeof(struct htt_rx_desc)) + +/* + * DMA_MAP expects the buffer to be an integral number of cache lines. + * Rather than checking the actual cache line size, this code makes a + * conservative estimate of what the cache line size could be. + */ +#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */ +#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1) + +struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar); +int ath10k_htt_attach_target(struct ath10k_htt *htt); +void ath10k_htt_detach(struct ath10k_htt *htt); + +int ath10k_htt_tx_attach(struct ath10k_htt *htt); +void ath10k_htt_tx_detach(struct ath10k_htt *htt); +int ath10k_htt_rx_attach(struct ath10k_htt *htt); +void ath10k_htt_rx_detach(struct ath10k_htt *htt); +void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); +void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); +int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); +int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); + +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); +int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); +void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); +int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); +int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *); +#endif diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c new file mode 100644 index 000000000000..de058d7adca8 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -0,0 +1,1167 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "htc.h" +#include "htt.h" +#include "txrx.h" +#include "debug.h" + +#include + +/* slightly larger than one large A-MPDU */ +#define HTT_RX_RING_SIZE_MIN 128 + +/* roughly 20 ms @ 1 Gbps of 1500B MSDUs */ +#define HTT_RX_RING_SIZE_MAX 2048 + +#define HTT_RX_AVG_FRM_BYTES 1000 + +/* ms, very conservative */ +#define HTT_RX_HOST_LATENCY_MAX_MS 20 + +/* ms, conservative */ +#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10 + +/* when under memory pressure rx ring refill may fail and needs a retry */ +#define HTT_RX_RING_REFILL_RETRY_MS 50 + +static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt) +{ + int size; + + /* + * It is expected that the host CPU will typically be able to + * service the rx indication from one A-MPDU before the rx + * indication from the subsequent A-MPDU happens, roughly 1-2 ms + * later. However, the rx ring should be sized very conservatively, + * to accomodate the worst reasonable delay before the host CPU + * services a rx indication interrupt. + * + * The rx ring need not be kept full of empty buffers. In theory, + * the htt host SW can dynamically track the low-water mark in the + * rx ring, and dynamically adjust the level to which the rx ring + * is filled with empty buffers, to dynamically meet the desired + * low-water mark. + * + * In contrast, it's difficult to resize the rx ring itself, once + * it's in use. Thus, the ring itself should be sized very + * conservatively, while the degree to which the ring is filled + * with empty buffers should be sized moderately conservatively. + */ + + /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ + size = + htt->max_throughput_mbps + + 1000 / + (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_MAX_MS; + + if (size < HTT_RX_RING_SIZE_MIN) + size = HTT_RX_RING_SIZE_MIN; + + if (size > HTT_RX_RING_SIZE_MAX) + size = HTT_RX_RING_SIZE_MAX; + + size = roundup_pow_of_two(size); + + return size; +} + +static int ath10k_htt_rx_ring_fill_level(struct ath10k_htt *htt) +{ + int size; + + /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ + size = + htt->max_throughput_mbps * + 1000 / + (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS; + + /* + * Make sure the fill level is at least 1 less than the ring size. + * Leaving 1 element empty allows the SW to easily distinguish + * between a full ring vs. an empty ring. + */ + if (size >= htt->rx_ring.size) + size = htt->rx_ring.size - 1; + + return size; +} + +static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt) +{ + struct sk_buff *skb; + struct ath10k_skb_cb *cb; + int i; + + for (i = 0; i < htt->rx_ring.fill_cnt; i++) { + skb = htt->rx_ring.netbufs_ring[i]; + cb = ATH10K_SKB_CB(skb); + dma_unmap_single(htt->ar->dev, cb->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + dev_kfree_skb_any(skb); + } + + htt->rx_ring.fill_cnt = 0; +} + +static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) +{ + struct htt_rx_desc *rx_desc; + struct sk_buff *skb; + dma_addr_t paddr; + int ret = 0, idx; + + idx = __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr)); + while (num > 0) { + skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); + if (!skb) { + ret = -ENOMEM; + goto fail; + } + + if (!IS_ALIGNED((unsigned long)skb->data, HTT_RX_DESC_ALIGN)) + skb_pull(skb, + PTR_ALIGN(skb->data, HTT_RX_DESC_ALIGN) - + skb->data); + + /* Clear rx_desc attention word before posting to Rx ring */ + rx_desc = (struct htt_rx_desc *)skb->data; + rx_desc->attention.flags = __cpu_to_le32(0); + + paddr = dma_map_single(htt->ar->dev, skb->data, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(htt->ar->dev, paddr))) { + dev_kfree_skb_any(skb); + ret = -ENOMEM; + goto fail; + } + + ATH10K_SKB_CB(skb)->paddr = paddr; + htt->rx_ring.netbufs_ring[idx] = skb; + htt->rx_ring.paddrs_ring[idx] = __cpu_to_le32(paddr); + htt->rx_ring.fill_cnt++; + + num--; + idx++; + idx &= htt->rx_ring.size_mask; + } + +fail: + *(htt->rx_ring.alloc_idx.vaddr) = __cpu_to_le32(idx); + return ret; +} + +static int ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) +{ + lockdep_assert_held(&htt->rx_ring.lock); + return __ath10k_htt_rx_ring_fill_n(htt, num); +} + +static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) +{ + int ret, num_to_fill; + + spin_lock_bh(&htt->rx_ring.lock); + num_to_fill = htt->rx_ring.fill_level - htt->rx_ring.fill_cnt; + ret = ath10k_htt_rx_ring_fill_n(htt, num_to_fill); + if (ret == -ENOMEM) { + /* + * Failed to fill it to the desired level - + * we'll start a timer and try again next time. + * As long as enough buffers are left in the ring for + * another A-MPDU rx, no special recovery is needed. + */ + mod_timer(&htt->rx_ring.refill_retry_timer, jiffies + + msecs_to_jiffies(HTT_RX_RING_REFILL_RETRY_MS)); + } + spin_unlock_bh(&htt->rx_ring.lock); +} + +static void ath10k_htt_rx_ring_refill_retry(unsigned long arg) +{ + struct ath10k_htt *htt = (struct ath10k_htt *)arg; + ath10k_htt_rx_msdu_buff_replenish(htt); +} + +static unsigned ath10k_htt_rx_ring_elems(struct ath10k_htt *htt) +{ + return (__le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr) - + htt->rx_ring.sw_rd_idx.msdu_payld) & htt->rx_ring.size_mask; +} + +void ath10k_htt_rx_detach(struct ath10k_htt *htt) +{ + int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld; + + del_timer_sync(&htt->rx_ring.refill_retry_timer); + + while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) { + struct sk_buff *skb = + htt->rx_ring.netbufs_ring[sw_rd_idx]; + struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); + + dma_unmap_single(htt->ar->dev, cb->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + dev_kfree_skb_any(htt->rx_ring.netbufs_ring[sw_rd_idx]); + sw_rd_idx++; + sw_rd_idx &= htt->rx_ring.size_mask; + } + + dma_free_coherent(htt->ar->dev, + (htt->rx_ring.size * + sizeof(htt->rx_ring.paddrs_ring)), + htt->rx_ring.paddrs_ring, + htt->rx_ring.base_paddr); + + dma_free_coherent(htt->ar->dev, + sizeof(*htt->rx_ring.alloc_idx.vaddr), + htt->rx_ring.alloc_idx.vaddr, + htt->rx_ring.alloc_idx.paddr); + + kfree(htt->rx_ring.netbufs_ring); +} + +static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) +{ + int idx; + struct sk_buff *msdu; + + spin_lock_bh(&htt->rx_ring.lock); + + if (ath10k_htt_rx_ring_elems(htt) == 0) + ath10k_warn("htt rx ring is empty!\n"); + + idx = htt->rx_ring.sw_rd_idx.msdu_payld; + msdu = htt->rx_ring.netbufs_ring[idx]; + + idx++; + idx &= htt->rx_ring.size_mask; + htt->rx_ring.sw_rd_idx.msdu_payld = idx; + htt->rx_ring.fill_cnt--; + + spin_unlock_bh(&htt->rx_ring.lock); + return msdu; +} + +static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb) +{ + struct sk_buff *next; + + while (skb) { + next = skb->next; + dev_kfree_skb_any(skb); + skb = next; + } +} + +static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, + u8 **fw_desc, int *fw_desc_len, + struct sk_buff **head_msdu, + struct sk_buff **tail_msdu) +{ + int msdu_len, msdu_chaining = 0; + struct sk_buff *msdu; + struct htt_rx_desc *rx_desc; + + if (ath10k_htt_rx_ring_elems(htt) == 0) + ath10k_warn("htt rx ring is empty!\n"); + + if (htt->rx_confused) { + ath10k_warn("htt is confused. refusing rx\n"); + return 0; + } + + msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt); + while (msdu) { + int last_msdu, msdu_len_invalid, msdu_chained; + + dma_unmap_single(htt->ar->dev, + ATH10K_SKB_CB(msdu)->paddr, + msdu->len + skb_tailroom(msdu), + DMA_FROM_DEVICE); + + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx: ", + msdu->data, msdu->len + skb_tailroom(msdu)); + + rx_desc = (struct htt_rx_desc *)msdu->data; + + /* FIXME: we must report msdu payload since this is what caller + * expects now */ + skb_put(msdu, offsetof(struct htt_rx_desc, msdu_payload)); + skb_pull(msdu, offsetof(struct htt_rx_desc, msdu_payload)); + + /* + * Sanity check - confirm the HW is finished filling in the + * rx data. + * If the HW and SW are working correctly, then it's guaranteed + * that the HW's MAC DMA is done before this point in the SW. + * To prevent the case that we handle a stale Rx descriptor, + * just assert for now until we have a way to recover. + */ + if (!(__le32_to_cpu(rx_desc->attention.flags) + & RX_ATTENTION_FLAGS_MSDU_DONE)) { + ath10k_htt_rx_free_msdu_chain(*head_msdu); + *head_msdu = NULL; + msdu = NULL; + ath10k_err("htt rx stopped. cannot recover\n"); + htt->rx_confused = true; + break; + } + + /* + * Copy the FW rx descriptor for this MSDU from the rx + * indication message into the MSDU's netbuf. HL uses the + * same rx indication message definition as LL, and simply + * appends new info (fields from the HW rx desc, and the + * MSDU payload itself). So, the offset into the rx + * indication message only has to account for the standard + * offset of the per-MSDU FW rx desc info within the + * message, and how many bytes of the per-MSDU FW rx desc + * info have already been consumed. (And the endianness of + * the host, since for a big-endian host, the rx ind + * message contents, including the per-MSDU rx desc bytes, + * were byteswapped during upload.) + */ + if (*fw_desc_len > 0) { + rx_desc->fw_desc.info0 = **fw_desc; + /* + * The target is expected to only provide the basic + * per-MSDU rx descriptors. Just to be sure, verify + * that the target has not attached extension data + * (e.g. LRO flow ID). + */ + + /* or more, if there's extension data */ + (*fw_desc)++; + (*fw_desc_len)--; + } else { + /* + * When an oversized AMSDU happened, FW will lost + * some of MSDU status - in this case, the FW + * descriptors provided will be less than the + * actual MSDUs inside this MPDU. Mark the FW + * descriptors so that it will still deliver to + * upper stack, if no CRC error for this MPDU. + * + * FIX THIS - the FW descriptors are actually for + * MSDUs in the end of this A-MSDU instead of the + * beginning. + */ + rx_desc->fw_desc.info0 = 0; + } + + msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags) + & (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR | + RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR)); + msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0), + RX_MSDU_START_INFO0_MSDU_LENGTH); + msdu_chained = rx_desc->frag_info.ring2_more_count; + + if (msdu_len_invalid) + msdu_len = 0; + + skb_trim(msdu, 0); + skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE)); + msdu_len -= msdu->len; + + /* FIXME: Do chained buffers include htt_rx_desc or not? */ + while (msdu_chained--) { + struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); + + dma_unmap_single(htt->ar->dev, + ATH10K_SKB_CB(next)->paddr, + next->len + skb_tailroom(next), + DMA_FROM_DEVICE); + + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx: ", + next->data, + next->len + skb_tailroom(next)); + + skb_trim(next, 0); + skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); + msdu_len -= next->len; + + msdu->next = next; + msdu = next; + msdu_chaining = 1; + } + + if (msdu_len > 0) { + /* This may suggest FW bug? */ + ath10k_warn("htt rx msdu len not consumed (%d)\n", + msdu_len); + } + + last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & + RX_MSDU_END_INFO0_LAST_MSDU; + + if (last_msdu) { + msdu->next = NULL; + break; + } else { + struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); + msdu->next = next; + msdu = next; + } + } + *tail_msdu = msdu; + + /* + * Don't refill the ring yet. + * + * First, the elements popped here are still in use - it is not + * safe to overwrite them until the matching call to + * mpdu_desc_list_next. Second, for efficiency it is preferable to + * refill the rx ring with 1 PPDU's worth of rx buffers (something + * like 32 x 3 buffers), rather than one MPDU's worth of rx buffers + * (something like 3 buffers). Consequently, we'll rely on the txrx + * SW to tell us when it is done pulling all the PPDU's rx buffers + * out of the rx ring, and then refill it just once. + */ + + return msdu_chaining; +} + +int ath10k_htt_rx_attach(struct ath10k_htt *htt) +{ + dma_addr_t paddr; + void *vaddr; + struct timer_list *timer = &htt->rx_ring.refill_retry_timer; + + htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); + if (!is_power_of_2(htt->rx_ring.size)) { + ath10k_warn("htt rx ring size is not power of 2\n"); + return -EINVAL; + } + + htt->rx_ring.size_mask = htt->rx_ring.size - 1; + + /* + * Set the initial value for the level to which the rx ring + * should be filled, based on the max throughput and the + * worst likely latency for the host to fill the rx ring + * with new buffers. In theory, this fill level can be + * dynamically adjusted from the initial value set here, to + * reflect the actual host latency rather than a + * conservative assumption about the host latency. + */ + htt->rx_ring.fill_level = ath10k_htt_rx_ring_fill_level(htt); + + htt->rx_ring.netbufs_ring = + kmalloc(htt->rx_ring.size * sizeof(struct sk_buff *), + GFP_KERNEL); + if (!htt->rx_ring.netbufs_ring) + goto err_netbuf; + + vaddr = dma_alloc_coherent(htt->ar->dev, + (htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring)), + &paddr, GFP_DMA); + if (!vaddr) + goto err_dma_ring; + + htt->rx_ring.paddrs_ring = vaddr; + htt->rx_ring.base_paddr = paddr; + + vaddr = dma_alloc_coherent(htt->ar->dev, + sizeof(*htt->rx_ring.alloc_idx.vaddr), + &paddr, GFP_DMA); + if (!vaddr) + goto err_dma_idx; + + htt->rx_ring.alloc_idx.vaddr = vaddr; + htt->rx_ring.alloc_idx.paddr = paddr; + htt->rx_ring.sw_rd_idx.msdu_payld = 0; + *htt->rx_ring.alloc_idx.vaddr = 0; + + /* Initialize the Rx refill retry timer */ + setup_timer(timer, ath10k_htt_rx_ring_refill_retry, (unsigned long)htt); + + spin_lock_init(&htt->rx_ring.lock); + + htt->rx_ring.fill_cnt = 0; + if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level)) + goto err_fill_ring; + + ath10k_dbg(ATH10K_DBG_HTT, "HTT RX ring size: %d, fill_level: %d\n", + htt->rx_ring.size, htt->rx_ring.fill_level); + return 0; + +err_fill_ring: + ath10k_htt_rx_ring_free(htt); + dma_free_coherent(htt->ar->dev, + sizeof(*htt->rx_ring.alloc_idx.vaddr), + htt->rx_ring.alloc_idx.vaddr, + htt->rx_ring.alloc_idx.paddr); +err_dma_idx: + dma_free_coherent(htt->ar->dev, + (htt->rx_ring.size * + sizeof(htt->rx_ring.paddrs_ring)), + htt->rx_ring.paddrs_ring, + htt->rx_ring.base_paddr); +err_dma_ring: + kfree(htt->rx_ring.netbufs_ring); +err_netbuf: + return -ENOMEM; +} + +static int ath10k_htt_rx_crypto_param_len(enum htt_rx_mpdu_encrypt_type type) +{ + switch (type) { + case HTT_RX_MPDU_ENCRYPT_WEP40: + case HTT_RX_MPDU_ENCRYPT_WEP104: + return 4; + case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: + case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */ + case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: + case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */ + case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: + return 8; + case HTT_RX_MPDU_ENCRYPT_NONE: + return 0; + } + + ath10k_warn("unknown encryption type %d\n", type); + return 0; +} + +static int ath10k_htt_rx_crypto_tail_len(enum htt_rx_mpdu_encrypt_type type) +{ + switch (type) { + case HTT_RX_MPDU_ENCRYPT_NONE: + case HTT_RX_MPDU_ENCRYPT_WEP40: + case HTT_RX_MPDU_ENCRYPT_WEP104: + case HTT_RX_MPDU_ENCRYPT_WEP128: + case HTT_RX_MPDU_ENCRYPT_WAPI: + return 0; + case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: + case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: + return 4; + case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: + return 8; + } + + ath10k_warn("unknown encryption type %d\n", type); + return 0; +} + +/* Applies for first msdu in chain, before altering it. */ +static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb) +{ + struct htt_rx_desc *rxd; + enum rx_msdu_decap_format fmt; + + rxd = (void *)skb->data - sizeof(*rxd); + fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), + RX_MSDU_START_INFO1_DECAP_FORMAT); + + if (fmt == RX_MSDU_DECAP_RAW) + return (void *)skb->data; + else + return (void *)skb->data - RX_HTT_HDR_STATUS_LEN; +} + +/* This function only applies for first msdu in an msdu chain */ +static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr) +{ + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + if (qc[0] & 0x80) + return true; + } + return false; +} + +static int ath10k_htt_rx_amsdu(struct ath10k_htt *htt, + struct htt_rx_info *info) +{ + struct htt_rx_desc *rxd; + struct sk_buff *amsdu; + struct sk_buff *first; + struct ieee80211_hdr *hdr; + struct sk_buff *skb = info->skb; + enum rx_msdu_decap_format fmt; + enum htt_rx_mpdu_encrypt_type enctype; + unsigned int hdr_len; + int crypto_len; + + rxd = (void *)skb->data - sizeof(*rxd); + fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), + RX_MSDU_START_INFO1_DECAP_FORMAT); + enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), + RX_MPDU_START_INFO0_ENCRYPT_TYPE); + + /* FIXME: No idea what assumptions are safe here. Need logs */ + if ((fmt == RX_MSDU_DECAP_RAW && skb->next) || + (fmt == RX_MSDU_DECAP_8023_SNAP_LLC)) { + ath10k_htt_rx_free_msdu_chain(skb->next); + skb->next = NULL; + return -ENOTSUPP; + } + + /* A-MSDU max is a little less than 8K */ + amsdu = dev_alloc_skb(8*1024); + if (!amsdu) { + ath10k_warn("A-MSDU allocation failed\n"); + ath10k_htt_rx_free_msdu_chain(skb->next); + skb->next = NULL; + return -ENOMEM; + } + + if (fmt >= RX_MSDU_DECAP_NATIVE_WIFI) { + int hdrlen; + + hdr = (void *)rxd->rx_hdr_status; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + memcpy(skb_put(amsdu, hdrlen), hdr, hdrlen); + } + + first = skb; + while (skb) { + void *decap_hdr; + int decap_len = 0; + + rxd = (void *)skb->data - sizeof(*rxd); + fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), + RX_MSDU_START_INFO1_DECAP_FORMAT); + decap_hdr = (void *)rxd->rx_hdr_status; + + if (skb == first) { + /* We receive linked A-MSDU subframe skbuffs. The + * first one contains the original 802.11 header (and + * possible crypto param) in the RX descriptor. The + * A-MSDU subframe header follows that. Each part is + * aligned to 4 byte boundary. */ + + hdr = (void *)amsdu->data; + hdr_len = ieee80211_hdrlen(hdr->frame_control); + crypto_len = ath10k_htt_rx_crypto_param_len(enctype); + + decap_hdr += roundup(hdr_len, 4); + decap_hdr += roundup(crypto_len, 4); + } + + if (fmt == RX_MSDU_DECAP_ETHERNET2_DIX) { + /* Ethernet2 decap inserts ethernet header in place of + * A-MSDU subframe header. */ + skb_pull(skb, 6 + 6 + 2); + + /* A-MSDU subframe header length */ + decap_len += 6 + 6 + 2; + + /* Ethernet2 decap also strips the LLC/SNAP so we need + * to re-insert it. The LLC/SNAP follows A-MSDU + * subframe header. */ + /* FIXME: Not all LLCs are 8 bytes long */ + decap_len += 8; + + memcpy(skb_put(amsdu, decap_len), decap_hdr, decap_len); + } + + if (fmt == RX_MSDU_DECAP_NATIVE_WIFI) { + /* Native Wifi decap inserts regular 802.11 header + * in place of A-MSDU subframe header. */ + hdr = (struct ieee80211_hdr *)skb->data; + skb_pull(skb, ieee80211_hdrlen(hdr->frame_control)); + + /* A-MSDU subframe header length */ + decap_len += 6 + 6 + 2; + + memcpy(skb_put(amsdu, decap_len), decap_hdr, decap_len); + } + + if (fmt == RX_MSDU_DECAP_RAW) + skb_trim(skb, skb->len - 4); /* remove FCS */ + + memcpy(skb_put(amsdu, skb->len), skb->data, skb->len); + + /* A-MSDU subframes are padded to 4bytes + * but relative to first subframe, not the whole MPDU */ + if (skb->next && ((decap_len + skb->len) & 3)) { + int padlen = 4 - ((decap_len + skb->len) & 3); + memset(skb_put(amsdu, padlen), 0, padlen); + } + + skb = skb->next; + } + + info->skb = amsdu; + info->encrypt_type = enctype; + + ath10k_htt_rx_free_msdu_chain(first); + + return 0; +} + +static int ath10k_htt_rx_msdu(struct ath10k_htt *htt, struct htt_rx_info *info) +{ + struct sk_buff *skb = info->skb; + struct htt_rx_desc *rxd; + struct ieee80211_hdr *hdr; + enum rx_msdu_decap_format fmt; + enum htt_rx_mpdu_encrypt_type enctype; + + /* This shouldn't happen. If it does than it may be a FW bug. */ + if (skb->next) { + ath10k_warn("received chained non A-MSDU frame\n"); + ath10k_htt_rx_free_msdu_chain(skb->next); + skb->next = NULL; + } + + rxd = (void *)skb->data - sizeof(*rxd); + fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), + RX_MSDU_START_INFO1_DECAP_FORMAT); + enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), + RX_MPDU_START_INFO0_ENCRYPT_TYPE); + hdr = (void *)skb->data - RX_HTT_HDR_STATUS_LEN; + + switch (fmt) { + case RX_MSDU_DECAP_RAW: + /* remove trailing FCS */ + skb_trim(skb, skb->len - 4); + break; + case RX_MSDU_DECAP_NATIVE_WIFI: + /* nothing to do here */ + break; + case RX_MSDU_DECAP_ETHERNET2_DIX: + /* macaddr[6] + macaddr[6] + ethertype[2] */ + skb_pull(skb, 6 + 6 + 2); + break; + case RX_MSDU_DECAP_8023_SNAP_LLC: + /* macaddr[6] + macaddr[6] + len[2] */ + /* we don't need this for non-A-MSDU */ + skb_pull(skb, 6 + 6 + 2); + break; + } + + if (fmt == RX_MSDU_DECAP_ETHERNET2_DIX) { + void *llc; + int llclen; + + llclen = 8; + llc = hdr; + llc += roundup(ieee80211_hdrlen(hdr->frame_control), 4); + llc += roundup(ath10k_htt_rx_crypto_param_len(enctype), 4); + + skb_push(skb, llclen); + memcpy(skb->data, llc, llclen); + } + + if (fmt >= RX_MSDU_DECAP_ETHERNET2_DIX) { + int len = ieee80211_hdrlen(hdr->frame_control); + skb_push(skb, len); + memcpy(skb->data, hdr, len); + } + + info->skb = skb; + info->encrypt_type = enctype; + return 0; +} + +static bool ath10k_htt_rx_has_decrypt_err(struct sk_buff *skb) +{ + struct htt_rx_desc *rxd; + u32 flags; + + rxd = (void *)skb->data - sizeof(*rxd); + flags = __le32_to_cpu(rxd->attention.flags); + + if (flags & RX_ATTENTION_FLAGS_DECRYPT_ERR) + return true; + + return false; +} + +static bool ath10k_htt_rx_has_fcs_err(struct sk_buff *skb) +{ + struct htt_rx_desc *rxd; + u32 flags; + + rxd = (void *)skb->data - sizeof(*rxd); + flags = __le32_to_cpu(rxd->attention.flags); + + if (flags & RX_ATTENTION_FLAGS_FCS_ERR) + return true; + + return false; +} + +static void ath10k_htt_rx_handler(struct ath10k_htt *htt, + struct htt_rx_indication *rx) +{ + struct htt_rx_info info; + struct htt_rx_indication_mpdu_range *mpdu_ranges; + struct ieee80211_hdr *hdr; + int num_mpdu_ranges; + int fw_desc_len; + u8 *fw_desc; + int i, j; + int ret; + + memset(&info, 0, sizeof(info)); + + fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); + fw_desc = (u8 *)&rx->fw_desc; + + num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1), + HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES); + mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx); + + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", + rx, sizeof(*rx) + + (sizeof(struct htt_rx_indication_mpdu_range) * + num_mpdu_ranges)); + + for (i = 0; i < num_mpdu_ranges; i++) { + info.status = mpdu_ranges[i].mpdu_range_status; + + for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { + struct sk_buff *msdu_head, *msdu_tail; + enum htt_rx_mpdu_status status; + int msdu_chaining; + + msdu_head = NULL; + msdu_tail = NULL; + msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, + &fw_desc, + &fw_desc_len, + &msdu_head, + &msdu_tail); + + if (!msdu_head) { + ath10k_warn("htt rx no data!\n"); + continue; + } + + if (msdu_head->len == 0) { + ath10k_dbg(ATH10K_DBG_HTT, + "htt rx dropping due to zero-len\n"); + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + + if (ath10k_htt_rx_has_decrypt_err(msdu_head)) { + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + + status = info.status; + + /* Skip mgmt frames while we handle this in WMI */ + if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL) { + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + + if (status != HTT_RX_IND_MPDU_STATUS_OK && + status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && + !htt->ar->monitor_enabled) { + ath10k_dbg(ATH10K_DBG_HTT, + "htt rx ignoring frame w/ status %d\n", + status); + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + + /* FIXME: we do not support chaining yet. + * this needs investigation */ + if (msdu_chaining) { + ath10k_warn("msdu_chaining is true\n"); + ath10k_htt_rx_free_msdu_chain(msdu_head); + continue; + } + + info.skb = msdu_head; + info.fcs_err = ath10k_htt_rx_has_fcs_err(msdu_head); + info.signal = ATH10K_DEFAULT_NOISE_FLOOR; + info.signal += rx->ppdu.combined_rssi; + + info.rate.info0 = rx->ppdu.info0; + info.rate.info1 = __le32_to_cpu(rx->ppdu.info1); + info.rate.info2 = __le32_to_cpu(rx->ppdu.info2); + + hdr = ath10k_htt_rx_skb_get_hdr(msdu_head); + + if (ath10k_htt_rx_hdr_is_amsdu(hdr)) + ret = ath10k_htt_rx_amsdu(htt, &info); + else + ret = ath10k_htt_rx_msdu(htt, &info); + + if (ret && !info.fcs_err) { + ath10k_warn("error processing msdus %d\n", ret); + dev_kfree_skb_any(info.skb); + continue; + } + + if (ath10k_htt_rx_hdr_is_amsdu((void *)info.skb->data)) + ath10k_dbg(ATH10K_DBG_HTT, "htt mpdu is amsdu\n"); + + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt mpdu: ", + info.skb->data, info.skb->len); + ath10k_process_rx(htt->ar, &info); + } + } + + ath10k_htt_rx_msdu_buff_replenish(htt); +} + +static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, + struct htt_rx_fragment_indication *frag) +{ + struct sk_buff *msdu_head, *msdu_tail; + struct htt_rx_desc *rxd; + enum rx_msdu_decap_format fmt; + struct htt_rx_info info = {}; + struct ieee80211_hdr *hdr; + int msdu_chaining; + bool tkip_mic_err; + bool decrypt_err; + u8 *fw_desc; + int fw_desc_len, hdrlen, paramlen; + int trim; + + fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes); + fw_desc = (u8 *)frag->fw_msdu_rx_desc; + + msdu_head = NULL; + msdu_tail = NULL; + msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, + &msdu_head, &msdu_tail); + + ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); + + if (!msdu_head) { + ath10k_warn("htt rx frag no data\n"); + return; + } + + if (msdu_chaining || msdu_head != msdu_tail) { + ath10k_warn("aggregation with fragmentation?!\n"); + ath10k_htt_rx_free_msdu_chain(msdu_head); + return; + } + + /* FIXME: implement signal strength */ + + hdr = (struct ieee80211_hdr *)msdu_head->data; + rxd = (void *)msdu_head->data - sizeof(*rxd); + tkip_mic_err = !!(__le32_to_cpu(rxd->attention.flags) & + RX_ATTENTION_FLAGS_TKIP_MIC_ERR); + decrypt_err = !!(__le32_to_cpu(rxd->attention.flags) & + RX_ATTENTION_FLAGS_DECRYPT_ERR); + fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), + RX_MSDU_START_INFO1_DECAP_FORMAT); + + if (fmt != RX_MSDU_DECAP_RAW) { + ath10k_warn("we dont support non-raw fragmented rx yet\n"); + dev_kfree_skb_any(msdu_head); + goto end; + } + + info.skb = msdu_head; + info.status = HTT_RX_IND_MPDU_STATUS_OK; + info.encrypt_type = MS(__le32_to_cpu(rxd->mpdu_start.info0), + RX_MPDU_START_INFO0_ENCRYPT_TYPE); + + if (tkip_mic_err) { + ath10k_warn("tkip mic error\n"); + info.status = HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR; + } + + if (decrypt_err) { + ath10k_warn("decryption err in fragmented rx\n"); + dev_kfree_skb_any(info.skb); + goto end; + } + + if (info.encrypt_type != HTT_RX_MPDU_ENCRYPT_NONE) { + hdrlen = ieee80211_hdrlen(hdr->frame_control); + paramlen = ath10k_htt_rx_crypto_param_len(info.encrypt_type); + + /* It is more efficient to move the header than the payload */ + memmove((void *)info.skb->data + paramlen, + (void *)info.skb->data, + hdrlen); + skb_pull(info.skb, paramlen); + hdr = (struct ieee80211_hdr *)info.skb->data; + } + + /* remove trailing FCS */ + trim = 4; + + /* remove crypto trailer */ + trim += ath10k_htt_rx_crypto_tail_len(info.encrypt_type); + + /* last fragment of TKIP frags has MIC */ + if (!ieee80211_has_morefrags(hdr->frame_control) && + info.encrypt_type == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) + trim += 8; + + if (trim > info.skb->len) { + ath10k_warn("htt rx fragment: trailer longer than the frame itself? drop\n"); + dev_kfree_skb_any(info.skb); + goto end; + } + + skb_trim(info.skb, info.skb->len - trim); + + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt frag mpdu: ", + info.skb->data, info.skb->len); + ath10k_process_rx(htt->ar, &info); + +end: + if (fw_desc_len > 0) { + ath10k_dbg(ATH10K_DBG_HTT, + "expecting more fragmented rx in one indication %d\n", + fw_desc_len); + } +} + +void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) +{ + struct ath10k_htt *htt = ar->htt; + struct htt_resp *resp = (struct htt_resp *)skb->data; + + /* confirm alignment */ + if (!IS_ALIGNED((unsigned long)skb->data, 4)) + ath10k_warn("unaligned htt message, expect trouble\n"); + + ath10k_dbg(ATH10K_DBG_HTT, "HTT RX, msg_type: 0x%0X\n", + resp->hdr.msg_type); + switch (resp->hdr.msg_type) { + case HTT_T2H_MSG_TYPE_VERSION_CONF: { + htt->target_version_major = resp->ver_resp.major; + htt->target_version_minor = resp->ver_resp.minor; + complete(&htt->target_version_received); + break; + } + case HTT_T2H_MSG_TYPE_RX_IND: { + ath10k_htt_rx_handler(htt, &resp->rx_ind); + break; + } + case HTT_T2H_MSG_TYPE_PEER_MAP: { + struct htt_peer_map_event ev = { + .vdev_id = resp->peer_map.vdev_id, + .peer_id = __le16_to_cpu(resp->peer_map.peer_id), + }; + memcpy(ev.addr, resp->peer_map.addr, sizeof(ev.addr)); + ath10k_peer_map_event(htt, &ev); + break; + } + case HTT_T2H_MSG_TYPE_PEER_UNMAP: { + struct htt_peer_unmap_event ev = { + .peer_id = __le16_to_cpu(resp->peer_unmap.peer_id), + }; + ath10k_peer_unmap_event(htt, &ev); + break; + } + case HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION: { + struct htt_tx_done tx_done = {}; + int status = __le32_to_cpu(resp->mgmt_tx_completion.status); + + tx_done.msdu_id = + __le32_to_cpu(resp->mgmt_tx_completion.desc_id); + + switch (status) { + case HTT_MGMT_TX_STATUS_OK: + break; + case HTT_MGMT_TX_STATUS_RETRY: + tx_done.no_ack = true; + break; + case HTT_MGMT_TX_STATUS_DROP: + tx_done.discard = true; + break; + } + + ath10k_txrx_tx_completed(htt, &tx_done); + break; + } + case HTT_T2H_MSG_TYPE_TX_COMPL_IND: { + struct htt_tx_done tx_done = {}; + int status = MS(resp->data_tx_completion.flags, + HTT_DATA_TX_STATUS); + __le16 msdu_id; + int i; + + switch (status) { + case HTT_DATA_TX_STATUS_NO_ACK: + tx_done.no_ack = true; + break; + case HTT_DATA_TX_STATUS_OK: + break; + case HTT_DATA_TX_STATUS_DISCARD: + case HTT_DATA_TX_STATUS_POSTPONE: + case HTT_DATA_TX_STATUS_DOWNLOAD_FAIL: + tx_done.discard = true; + break; + default: + ath10k_warn("unhandled tx completion status %d\n", + status); + tx_done.discard = true; + break; + } + + ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n", + resp->data_tx_completion.num_msdus); + + for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { + msdu_id = resp->data_tx_completion.msdus[i]; + tx_done.msdu_id = __le16_to_cpu(msdu_id); + ath10k_txrx_tx_completed(htt, &tx_done); + } + break; + } + case HTT_T2H_MSG_TYPE_SEC_IND: { + struct ath10k *ar = htt->ar; + struct htt_security_indication *ev = &resp->security_indication; + + ath10k_dbg(ATH10K_DBG_HTT, + "sec ind peer_id %d unicast %d type %d\n", + __le16_to_cpu(ev->peer_id), + !!(ev->flags & HTT_SECURITY_IS_UNICAST), + MS(ev->flags, HTT_SECURITY_TYPE)); + complete(&ar->install_key_done); + break; + } + case HTT_T2H_MSG_TYPE_RX_FRAG_IND: { + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", + skb->data, skb->len); + ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind); + break; + } + case HTT_T2H_MSG_TYPE_TEST: + /* FIX THIS */ + break; + case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: + case HTT_T2H_MSG_TYPE_STATS_CONF: + case HTT_T2H_MSG_TYPE_RX_ADDBA: + case HTT_T2H_MSG_TYPE_RX_DELBA: + case HTT_T2H_MSG_TYPE_RX_FLUSH: + default: + ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n", + resp->hdr.msg_type); + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", + skb->data, skb->len); + break; + }; + + /* Free the indication buffer */ + dev_kfree_skb_any(skb); +} diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c new file mode 100644 index 000000000000..ef79106db247 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include "htt.h" +#include "mac.h" +#include "hif.h" +#include "txrx.h" +#include "debug.h" + +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +{ + htt->num_pending_tx--; + if (htt->num_pending_tx == htt->max_num_pending_tx - 1) + ieee80211_wake_queues(htt->ar->hw); +} + +static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +{ + spin_lock_bh(&htt->tx_lock); + __ath10k_htt_tx_dec_pending(htt); + spin_unlock_bh(&htt->tx_lock); +} + +static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) +{ + int ret = 0; + + spin_lock_bh(&htt->tx_lock); + + if (htt->num_pending_tx >= htt->max_num_pending_tx) { + ret = -EBUSY; + goto exit; + } + + htt->num_pending_tx++; + if (htt->num_pending_tx == htt->max_num_pending_tx) + ieee80211_stop_queues(htt->ar->hw); + +exit: + spin_unlock_bh(&htt->tx_lock); + return ret; +} + +int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt) +{ + int msdu_id; + + lockdep_assert_held(&htt->tx_lock); + + msdu_id = find_first_zero_bit(htt->used_msdu_ids, + htt->max_num_pending_tx); + if (msdu_id == htt->max_num_pending_tx) + return -ENOBUFS; + + ath10k_dbg(ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", msdu_id); + __set_bit(msdu_id, htt->used_msdu_ids); + return msdu_id; +} + +void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) +{ + lockdep_assert_held(&htt->tx_lock); + + if (!test_bit(msdu_id, htt->used_msdu_ids)) + ath10k_warn("trying to free unallocated msdu_id %d\n", msdu_id); + + ath10k_dbg(ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id); + __clear_bit(msdu_id, htt->used_msdu_ids); +} + +int ath10k_htt_tx_attach(struct ath10k_htt *htt) +{ + u8 pipe; + + spin_lock_init(&htt->tx_lock); + init_waitqueue_head(&htt->empty_tx_wq); + + /* At the beginning free queue number should hint us the maximum + * queue length */ + pipe = htt->ar->htc->endpoint[htt->eid].ul_pipe_id; + htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar, + pipe); + + ath10k_dbg(ATH10K_DBG_HTT, "htt tx max num pending tx %d\n", + htt->max_num_pending_tx); + + htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) * + htt->max_num_pending_tx, GFP_KERNEL); + if (!htt->pending_tx) + return -ENOMEM; + + htt->used_msdu_ids = kzalloc(sizeof(unsigned long) * + BITS_TO_LONGS(htt->max_num_pending_tx), + GFP_KERNEL); + if (!htt->used_msdu_ids) { + kfree(htt->pending_tx); + return -ENOMEM; + } + + return 0; +} + +static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) +{ + struct sk_buff *txdesc; + int msdu_id; + + /* No locks needed. Called after communication with the device has + * been stopped. */ + + for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { + if (!test_bit(msdu_id, htt->used_msdu_ids)) + continue; + + txdesc = htt->pending_tx[msdu_id]; + if (!txdesc) + continue; + + ath10k_dbg(ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", + msdu_id); + + if (ATH10K_SKB_CB(txdesc)->htt.refcount > 0) + ATH10K_SKB_CB(txdesc)->htt.refcount = 1; + + ATH10K_SKB_CB(txdesc)->htt.discard = true; + ath10k_txrx_tx_unref(htt, txdesc); + } +} + +void ath10k_htt_tx_detach(struct ath10k_htt *htt) +{ + ath10k_htt_tx_cleanup_pending(htt); + kfree(htt->pending_tx); + kfree(htt->used_msdu_ids); + return; +} + +void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) +{ + struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); + struct ath10k_htt *htt = ar->htt; + + if (skb_cb->htt.is_conf) { + dev_kfree_skb_any(skb); + return; + } + + if (skb_cb->is_aborted) { + skb_cb->htt.discard = true; + + /* if the skbuff is aborted we need to make sure we'll free up + * the tx resources, we can't simply run tx_unref() 2 times + * because if htt tx completion came in earlier we'd access + * unallocated memory */ + if (skb_cb->htt.refcount > 1) + skb_cb->htt.refcount = 1; + } + + ath10k_txrx_tx_unref(htt, skb); +} + +int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) +{ + struct sk_buff *skb; + struct htt_cmd *cmd; + int len = 0; + int ret; + + len += sizeof(cmd->hdr); + len += sizeof(cmd->ver_req); + + skb = ath10k_htc_alloc_skb(len); + if (!skb) + return -ENOMEM; + + skb_put(skb, len); + cmd = (struct htt_cmd *)skb->data; + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_VERSION_REQ; + + ATH10K_SKB_CB(skb)->htt.is_conf = true; + + ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb); + if (ret) { + dev_kfree_skb_any(skb); + return ret; + } + + return 0; +} + +int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) +{ + struct sk_buff *skb; + struct htt_cmd *cmd; + struct htt_rx_ring_setup_ring *ring; + const int num_rx_ring = 1; + u16 flags; + u32 fw_idx; + int len; + int ret; + + /* + * the HW expects the buffer to be an integral number of 4-byte + * "words" + */ + BUILD_BUG_ON(!IS_ALIGNED(HTT_RX_BUF_SIZE, 4)); + BUILD_BUG_ON((HTT_RX_BUF_SIZE & HTT_MAX_CACHE_LINE_SIZE_MASK) != 0); + + len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup.hdr) + + (sizeof(*ring) * num_rx_ring); + skb = ath10k_htc_alloc_skb(len); + if (!skb) + return -ENOMEM; + + skb_put(skb, len); + + cmd = (struct htt_cmd *)skb->data; + ring = &cmd->rx_setup.rings[0]; + + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_RX_RING_CFG; + cmd->rx_setup.hdr.num_rings = 1; + + /* FIXME: do we need all of this? */ + flags = 0; + flags |= HTT_RX_RING_FLAGS_MAC80211_HDR; + flags |= HTT_RX_RING_FLAGS_MSDU_PAYLOAD; + flags |= HTT_RX_RING_FLAGS_PPDU_START; + flags |= HTT_RX_RING_FLAGS_PPDU_END; + flags |= HTT_RX_RING_FLAGS_MPDU_START; + flags |= HTT_RX_RING_FLAGS_MPDU_END; + flags |= HTT_RX_RING_FLAGS_MSDU_START; + flags |= HTT_RX_RING_FLAGS_MSDU_END; + flags |= HTT_RX_RING_FLAGS_RX_ATTENTION; + flags |= HTT_RX_RING_FLAGS_FRAG_INFO; + flags |= HTT_RX_RING_FLAGS_UNICAST_RX; + flags |= HTT_RX_RING_FLAGS_MULTICAST_RX; + flags |= HTT_RX_RING_FLAGS_CTRL_RX; + flags |= HTT_RX_RING_FLAGS_MGMT_RX; + flags |= HTT_RX_RING_FLAGS_NULL_RX; + flags |= HTT_RX_RING_FLAGS_PHY_DATA_RX; + + fw_idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr); + + ring->fw_idx_shadow_reg_paddr = + __cpu_to_le32(htt->rx_ring.alloc_idx.paddr); + ring->rx_ring_base_paddr = __cpu_to_le32(htt->rx_ring.base_paddr); + ring->rx_ring_len = __cpu_to_le16(htt->rx_ring.size); + ring->rx_ring_bufsize = __cpu_to_le16(HTT_RX_BUF_SIZE); + ring->flags = __cpu_to_le16(flags); + ring->fw_idx_init_val = __cpu_to_le16(fw_idx); + +#define desc_offset(x) (offsetof(struct htt_rx_desc, x) / 4) + + ring->mac80211_hdr_offset = __cpu_to_le16(desc_offset(rx_hdr_status)); + ring->msdu_payload_offset = __cpu_to_le16(desc_offset(msdu_payload)); + ring->ppdu_start_offset = __cpu_to_le16(desc_offset(ppdu_start)); + ring->ppdu_end_offset = __cpu_to_le16(desc_offset(ppdu_end)); + ring->mpdu_start_offset = __cpu_to_le16(desc_offset(mpdu_start)); + ring->mpdu_end_offset = __cpu_to_le16(desc_offset(mpdu_end)); + ring->msdu_start_offset = __cpu_to_le16(desc_offset(msdu_start)); + ring->msdu_end_offset = __cpu_to_le16(desc_offset(msdu_end)); + ring->rx_attention_offset = __cpu_to_le16(desc_offset(attention)); + ring->frag_info_offset = __cpu_to_le16(desc_offset(frag_info)); + +#undef desc_offset + + ATH10K_SKB_CB(skb)->htt.is_conf = true; + + ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb); + if (ret) { + dev_kfree_skb_any(skb); + return ret; + } + + return 0; +} + +int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) +{ + struct device *dev = htt->ar->dev; + struct ath10k_skb_cb *skb_cb; + struct sk_buff *txdesc = NULL; + struct htt_cmd *cmd; + u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; + int len = 0; + int msdu_id = -1; + int res; + + + res = ath10k_htt_tx_inc_pending(htt); + if (res) + return res; + + len += sizeof(cmd->hdr); + len += sizeof(cmd->mgmt_tx); + + txdesc = ath10k_htc_alloc_skb(len); + if (!txdesc) { + res = -ENOMEM; + goto err; + } + + spin_lock_bh(&htt->tx_lock); + msdu_id = ath10k_htt_tx_alloc_msdu_id(htt); + if (msdu_id < 0) { + spin_unlock_bh(&htt->tx_lock); + res = msdu_id; + goto err; + } + htt->pending_tx[msdu_id] = txdesc; + spin_unlock_bh(&htt->tx_lock); + + res = ath10k_skb_map(dev, msdu); + if (res) + goto err; + + skb_put(txdesc, len); + cmd = (struct htt_cmd *)txdesc->data; + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_MGMT_TX; + cmd->mgmt_tx.msdu_paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr); + cmd->mgmt_tx.len = __cpu_to_le32(msdu->len); + cmd->mgmt_tx.desc_id = __cpu_to_le32(msdu_id); + cmd->mgmt_tx.vdev_id = __cpu_to_le32(vdev_id); + memcpy(cmd->mgmt_tx.hdr, msdu->data, + min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); + + /* refcount is decremented by HTC and HTT completions until it reaches + * zero and is freed */ + skb_cb = ATH10K_SKB_CB(txdesc); + skb_cb->htt.msdu_id = msdu_id; + skb_cb->htt.refcount = 2; + skb_cb->htt.msdu = msdu; + + res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc); + if (res) + goto err; + + return 0; + +err: + ath10k_skb_unmap(dev, msdu); + + if (txdesc) + dev_kfree_skb_any(txdesc); + if (msdu_id >= 0) { + spin_lock_bh(&htt->tx_lock); + htt->pending_tx[msdu_id] = NULL; + ath10k_htt_tx_free_msdu_id(htt, msdu_id); + spin_unlock_bh(&htt->tx_lock); + } + ath10k_htt_tx_dec_pending(htt); + return res; +} + +int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) +{ + struct device *dev = htt->ar->dev; + struct htt_cmd *cmd; + struct htt_data_tx_desc_frag *tx_frags; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + struct ath10k_skb_cb *skb_cb; + struct sk_buff *txdesc = NULL; + struct sk_buff *txfrag = NULL; + u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; + u8 tid; + int prefetch_len, desc_len, frag_len; + dma_addr_t frags_paddr; + int msdu_id = -1; + int res; + u8 flags0; + u16 flags1; + + res = ath10k_htt_tx_inc_pending(htt); + if (res) + return res; + + prefetch_len = min(htt->prefetch_len, msdu->len); + prefetch_len = roundup(prefetch_len, 4); + + desc_len = sizeof(cmd->hdr) + sizeof(cmd->data_tx) + prefetch_len; + frag_len = sizeof(*tx_frags) * 2; + + txdesc = ath10k_htc_alloc_skb(desc_len); + if (!txdesc) { + res = -ENOMEM; + goto err; + } + + txfrag = dev_alloc_skb(frag_len); + if (!txfrag) { + res = -ENOMEM; + goto err; + } + + if (!IS_ALIGNED((unsigned long)txdesc->data, 4)) { + ath10k_warn("htt alignment check failed. dropping packet.\n"); + res = -EIO; + goto err; + } + + spin_lock_bh(&htt->tx_lock); + msdu_id = ath10k_htt_tx_alloc_msdu_id(htt); + if (msdu_id < 0) { + spin_unlock_bh(&htt->tx_lock); + res = msdu_id; + goto err; + } + htt->pending_tx[msdu_id] = txdesc; + spin_unlock_bh(&htt->tx_lock); + + res = ath10k_skb_map(dev, msdu); + if (res) + goto err; + + /* tx fragment list must be terminated with zero-entry */ + skb_put(txfrag, frag_len); + tx_frags = (struct htt_data_tx_desc_frag *)txfrag->data; + tx_frags[0].paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr); + tx_frags[0].len = __cpu_to_le32(msdu->len); + tx_frags[1].paddr = __cpu_to_le32(0); + tx_frags[1].len = __cpu_to_le32(0); + + res = ath10k_skb_map(dev, txfrag); + if (res) + goto err; + + ath10k_dbg(ATH10K_DBG_HTT, "txfrag 0x%llx msdu 0x%llx\n", + (unsigned long long) ATH10K_SKB_CB(txfrag)->paddr, + (unsigned long long) ATH10K_SKB_CB(msdu)->paddr); + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "txfrag: ", + txfrag->data, frag_len); + ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "msdu: ", + msdu->data, msdu->len); + + skb_put(txdesc, desc_len); + cmd = (struct htt_cmd *)txdesc->data; + memset(cmd, 0, desc_len); + + tid = ATH10K_SKB_CB(msdu)->htt.tid; + + ath10k_dbg(ATH10K_DBG_HTT, "htt data tx using tid %hhu\n", tid); + + flags0 = 0; + if (!ieee80211_has_protected(hdr->frame_control)) + flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; + flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; + flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI, + HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); + + flags1 = 0; + flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); + flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID); + + frags_paddr = ATH10K_SKB_CB(txfrag)->paddr; + + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; + cmd->data_tx.flags0 = flags0; + cmd->data_tx.flags1 = __cpu_to_le16(flags1); + cmd->data_tx.len = __cpu_to_le16(msdu->len); + cmd->data_tx.id = __cpu_to_le16(msdu_id); + cmd->data_tx.frags_paddr = __cpu_to_le32(frags_paddr); + cmd->data_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); + + memcpy(cmd->data_tx.prefetch, msdu->data, prefetch_len); + + /* refcount is decremented by HTC and HTT completions until it reaches + * zero and is freed */ + skb_cb = ATH10K_SKB_CB(txdesc); + skb_cb->htt.msdu_id = msdu_id; + skb_cb->htt.refcount = 2; + skb_cb->htt.txfrag = txfrag; + skb_cb->htt.msdu = msdu; + + res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc); + if (res) + goto err; + + return 0; +err: + if (txfrag) + ath10k_skb_unmap(dev, txfrag); + if (txdesc) + dev_kfree_skb_any(txdesc); + if (txfrag) + dev_kfree_skb_any(txfrag); + if (msdu_id >= 0) { + spin_lock_bh(&htt->tx_lock); + htt->pending_tx[msdu_id] = NULL; + ath10k_htt_tx_free_msdu_id(htt, msdu_id); + spin_unlock_bh(&htt->tx_lock); + } + ath10k_htt_tx_dec_pending(htt); + ath10k_skb_unmap(dev, msdu); + return res; +} diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h new file mode 100644 index 000000000000..44ed5af0a204 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HW_H_ +#define _HW_H_ + +#include "targaddrs.h" + +/* Supported FW version */ +#define SUPPORTED_FW_MAJOR 1 +#define SUPPORTED_FW_MINOR 0 +#define SUPPORTED_FW_RELEASE 0 +#define SUPPORTED_FW_BUILD 629 + +/* QCA988X 1.0 definitions */ +#define QCA988X_HW_1_0_VERSION 0x4000002c +#define QCA988X_HW_1_0_FW_DIR "ath10k/QCA988X/hw1.0" +#define QCA988X_HW_1_0_FW_FILE "firmware.bin" +#define QCA988X_HW_1_0_OTP_FILE "otp.bin" +#define QCA988X_HW_1_0_BOARD_DATA_FILE "board.bin" +#define QCA988X_HW_1_0_PATCH_LOAD_ADDR 0x1234 + +/* QCA988X 2.0 definitions */ +#define QCA988X_HW_2_0_VERSION 0x4100016c +#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" +#define QCA988X_HW_2_0_FW_FILE "firmware.bin" +#define QCA988X_HW_2_0_OTP_FILE "otp.bin" +#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" +#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 + +/* Known pecularities: + * - current FW doesn't support raw rx mode (last tested v599) + * - current FW dumps upon raw tx mode (last tested v599) + * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap + * - raw have FCS, nwifi doesn't + * - ethernet frames have 802.11 header decapped and parts (base hdr, cipher + * param, llc/snap) are aligned to 4byte boundaries each */ +enum ath10k_hw_txrx_mode { + ATH10K_HW_TXRX_RAW = 0, + ATH10K_HW_TXRX_NATIVE_WIFI = 1, + ATH10K_HW_TXRX_ETHERNET = 2, +}; + +enum ath10k_mcast2ucast_mode { + ATH10K_MCAST2UCAST_DISABLED = 0, + ATH10K_MCAST2UCAST_ENABLED = 1, +}; + +#define TARGET_NUM_VDEVS 8 +#define TARGET_NUM_PEER_AST 2 +#define TARGET_NUM_WDS_ENTRIES 32 +#define TARGET_DMA_BURST_SIZE 0 +#define TARGET_MAC_AGGR_DELIM 0 +#define TARGET_AST_SKID_LIMIT 16 +#define TARGET_NUM_PEERS 16 +#define TARGET_NUM_OFFLOAD_PEERS 0 +#define TARGET_NUM_OFFLOAD_REORDER_BUFS 0 +#define TARGET_NUM_PEER_KEYS 2 +#define TARGET_NUM_TIDS (2 * ((TARGET_NUM_PEERS) + (TARGET_NUM_VDEVS))) +#define TARGET_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) +#define TARGET_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2)) +#define TARGET_RX_TIMEOUT_LO_PRI 100 +#define TARGET_RX_TIMEOUT_HI_PRI 40 +#define TARGET_RX_DECAP_MODE ATH10K_HW_TXRX_ETHERNET +#define TARGET_SCAN_MAX_PENDING_REQS 4 +#define TARGET_BMISS_OFFLOAD_MAX_VDEV 3 +#define TARGET_ROAM_OFFLOAD_MAX_VDEV 3 +#define TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES 8 +#define TARGET_GTK_OFFLOAD_MAX_VDEV 3 +#define TARGET_NUM_MCAST_GROUPS 0 +#define TARGET_NUM_MCAST_TABLE_ELEMS 0 +#define TARGET_MCAST2UCAST_MODE ATH10K_MCAST2UCAST_DISABLED +#define TARGET_TX_DBG_LOG_SIZE 1024 +#define TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 0 +#define TARGET_VOW_CONFIG 0 +#define TARGET_NUM_MSDU_DESC (1024 + 400) +#define TARGET_MAX_FRAG_ENTRIES 0 + + +/* Number of Copy Engines supported */ +#define CE_COUNT 8 + +/* + * Total number of PCIe MSI interrupts requested for all interrupt sources. + * PCIe standard forces this to be a power of 2. + * Some Host OS's limit MSI requests that can be granted to 8 + * so for now we abide by this limit and avoid requesting more + * than that. + */ +#define MSI_NUM_REQUEST_LOG2 3 +#define MSI_NUM_REQUEST (1<> RTC_STATE_V_LSB) + +#endif /* _HW_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c new file mode 100644 index 000000000000..1285554a1025 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -0,0 +1,3066 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mac.h" + +#include +#include + +#include "core.h" +#include "debug.h" +#include "wmi.h" +#include "htt.h" +#include "txrx.h" + +/**********/ +/* Crypto */ +/**********/ + +static int ath10k_send_key(struct ath10k_vif *arvif, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd, + const u8 *macaddr) +{ + struct wmi_vdev_install_key_arg arg = { + .vdev_id = arvif->vdev_id, + .key_idx = key->keyidx, + .key_len = key->keylen, + .key_data = key->key, + .macaddr = macaddr, + }; + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) + arg.key_flags = WMI_KEY_PAIRWISE; + else + arg.key_flags = WMI_KEY_GROUP; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + arg.key_cipher = WMI_CIPHER_AES_CCM; + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + arg.key_cipher = WMI_CIPHER_TKIP; + arg.key_txmic_len = 8; + arg.key_rxmic_len = 8; + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + arg.key_cipher = WMI_CIPHER_WEP; + /* AP/IBSS mode requires self-key to be groupwise + * Otherwise pairwise key must be set */ + if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN)) + arg.key_flags = WMI_KEY_PAIRWISE; + break; + default: + ath10k_warn("cipher %d is not supported\n", key->cipher); + return -EOPNOTSUPP; + } + + if (cmd == DISABLE_KEY) { + arg.key_cipher = WMI_CIPHER_NONE; + arg.key_data = NULL; + } + + return ath10k_wmi_vdev_install_key(arvif->ar, &arg); +} + +static int ath10k_install_key(struct ath10k_vif *arvif, + struct ieee80211_key_conf *key, + enum set_key_cmd cmd, + const u8 *macaddr) +{ + struct ath10k *ar = arvif->ar; + int ret; + + INIT_COMPLETION(ar->install_key_done); + + ret = ath10k_send_key(arvif, key, cmd, macaddr); + if (ret) + return ret; + + ret = wait_for_completion_timeout(&ar->install_key_done, 3*HZ); + if (ret == 0) + return -ETIMEDOUT; + + return 0; +} + +static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, + const u8 *addr) +{ + struct ath10k *ar = arvif->ar; + struct ath10k_peer *peer; + int ret; + int i; + + lockdep_assert_held(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, arvif->vdev_id, addr); + spin_unlock_bh(&ar->data_lock); + + if (!peer) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) { + if (arvif->wep_keys[i] == NULL) + continue; + + ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY, + addr); + if (ret) + return ret; + + peer->keys[i] = arvif->wep_keys[i]; + } + + return 0; +} + +static int ath10k_clear_peer_keys(struct ath10k_vif *arvif, + const u8 *addr) +{ + struct ath10k *ar = arvif->ar; + struct ath10k_peer *peer; + int first_errno = 0; + int ret; + int i; + + lockdep_assert_held(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, arvif->vdev_id, addr); + spin_unlock_bh(&ar->data_lock); + + if (!peer) + return -ENOENT; + + for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { + if (peer->keys[i] == NULL) + continue; + + ret = ath10k_install_key(arvif, peer->keys[i], + DISABLE_KEY, addr); + if (ret && first_errno == 0) + first_errno = ret; + + if (ret) + ath10k_warn("could not remove peer wep key %d (%d)\n", + i, ret); + + peer->keys[i] = NULL; + } + + return first_errno; +} + +static int ath10k_clear_vdev_key(struct ath10k_vif *arvif, + struct ieee80211_key_conf *key) +{ + struct ath10k *ar = arvif->ar; + struct ath10k_peer *peer; + u8 addr[ETH_ALEN]; + int first_errno = 0; + int ret; + int i; + + lockdep_assert_held(&ar->conf_mutex); + + for (;;) { + /* since ath10k_install_key we can't hold data_lock all the + * time, so we try to remove the keys incrementally */ + spin_lock_bh(&ar->data_lock); + i = 0; + list_for_each_entry(peer, &ar->peers, list) { + for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { + if (peer->keys[i] == key) { + memcpy(addr, peer->addr, ETH_ALEN); + peer->keys[i] = NULL; + break; + } + } + + if (i < ARRAY_SIZE(peer->keys)) + break; + } + spin_unlock_bh(&ar->data_lock); + + if (i == ARRAY_SIZE(peer->keys)) + break; + + ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr); + if (ret && first_errno == 0) + first_errno = ret; + + if (ret) + ath10k_warn("could not remove key for %pM\n", addr); + } + + return first_errno; +} + + +/*********************/ +/* General utilities */ +/*********************/ + +static inline enum wmi_phy_mode +chan_to_phymode(const struct cfg80211_chan_def *chandef) +{ + enum wmi_phy_mode phymode = MODE_UNKNOWN; + + switch (chandef->chan->band) { + case IEEE80211_BAND_2GHZ: + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + phymode = MODE_11G; + break; + case NL80211_CHAN_WIDTH_20: + phymode = MODE_11NG_HT20; + break; + case NL80211_CHAN_WIDTH_40: + phymode = MODE_11NG_HT40; + break; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + phymode = MODE_UNKNOWN; + break; + } + break; + case IEEE80211_BAND_5GHZ: + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + phymode = MODE_11A; + break; + case NL80211_CHAN_WIDTH_20: + phymode = MODE_11NA_HT20; + break; + case NL80211_CHAN_WIDTH_40: + phymode = MODE_11NA_HT40; + break; + case NL80211_CHAN_WIDTH_80: + phymode = MODE_11AC_VHT80; + break; + case NL80211_CHAN_WIDTH_80P80: + case NL80211_CHAN_WIDTH_160: + phymode = MODE_UNKNOWN; + break; + } + break; + default: + break; + } + + WARN_ON(phymode == MODE_UNKNOWN); + return phymode; +} + +static u8 ath10k_parse_mpdudensity(u8 mpdudensity) +{ +/* + * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": + * 0 for no restriction + * 1 for 1/4 us + * 2 for 1/2 us + * 3 for 1 us + * 4 for 2 us + * 5 for 4 us + * 6 for 8 us + * 7 for 16 us + */ + switch (mpdudensity) { + case 0: + return 0; + case 1: + case 2: + case 3: + /* Our lower layer calculations limit our precision to + 1 microsecond */ + return 1; + case 4: + return 2; + case 5: + return 4; + case 6: + return 8; + case 7: + return 16; + default: + return 0; + } +} + +static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr) +{ + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ret = ath10k_wmi_peer_create(ar, vdev_id, addr); + if (ret) + return ret; + + ret = ath10k_wait_for_peer_created(ar, vdev_id, addr); + if (ret) + return ret; + + return 0; +} + +static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) +{ + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ret = ath10k_wmi_peer_delete(ar, vdev_id, addr); + if (ret) + return ret; + + ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr); + if (ret) + return ret; + + return 0; +} + +static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) +{ + struct ath10k_peer *peer, *tmp; + + lockdep_assert_held(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + list_for_each_entry_safe(peer, tmp, &ar->peers, list) { + if (peer->vdev_id != vdev_id) + continue; + + ath10k_warn("removing stale peer %pM from vdev_id %d\n", + peer->addr, vdev_id); + + list_del(&peer->list); + kfree(peer); + } + spin_unlock_bh(&ar->data_lock); +} + +/************************/ +/* Interface management */ +/************************/ + +static inline int ath10k_vdev_setup_sync(struct ath10k *ar) +{ + int ret; + + ret = wait_for_completion_timeout(&ar->vdev_setup_done, + ATH10K_VDEV_SETUP_TIMEOUT_HZ); + if (ret == 0) + return -ETIMEDOUT; + + return 0; +} + +static int ath10k_vdev_start(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + struct ieee80211_conf *conf = &ar->hw->conf; + struct ieee80211_channel *channel = conf->chandef.chan; + struct wmi_vdev_start_request_arg arg = {}; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + INIT_COMPLETION(ar->vdev_setup_done); + + arg.vdev_id = arvif->vdev_id; + arg.dtim_period = arvif->dtim_period; + arg.bcn_intval = arvif->beacon_interval; + + arg.channel.freq = channel->center_freq; + + arg.channel.band_center_freq1 = conf->chandef.center_freq1; + + arg.channel.mode = chan_to_phymode(&conf->chandef); + + arg.channel.min_power = channel->max_power * 3; + arg.channel.max_power = channel->max_power * 4; + arg.channel.max_reg_power = channel->max_reg_power * 4; + arg.channel.max_antenna_gain = channel->max_antenna_gain; + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + arg.ssid = arvif->u.ap.ssid; + arg.ssid_len = arvif->u.ap.ssid_len; + arg.hidden_ssid = arvif->u.ap.hidden_ssid; + } else if (arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { + arg.ssid = arvif->vif->bss_conf.ssid; + arg.ssid_len = arvif->vif->bss_conf.ssid_len; + } + + ret = ath10k_wmi_vdev_start(ar, &arg); + if (ret) { + ath10k_warn("WMI vdev start failed: ret %d\n", ret); + return ret; + } + + ret = ath10k_vdev_setup_sync(ar); + if (ret) { + ath10k_warn("vdev setup failed %d\n", ret); + return ret; + } + + return ret; +} + +static int ath10k_vdev_stop(struct ath10k_vif *arvif) +{ + struct ath10k *ar = arvif->ar; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + INIT_COMPLETION(ar->vdev_setup_done); + + ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id); + if (ret) { + ath10k_warn("WMI vdev stop failed: ret %d\n", ret); + return ret; + } + + ret = ath10k_vdev_setup_sync(ar); + if (ret) { + ath10k_warn("vdev setup failed %d\n", ret); + return ret; + } + + return ret; +} + +static int ath10k_monitor_start(struct ath10k *ar, int vdev_id) +{ + struct ieee80211_channel *channel = ar->hw->conf.chandef.chan; + struct wmi_vdev_start_request_arg arg = {}; + enum nl80211_channel_type type; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + type = cfg80211_get_chandef_type(&ar->hw->conf.chandef); + + arg.vdev_id = vdev_id; + arg.channel.freq = channel->center_freq; + arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1; + + /* TODO setup this dynamically, what in case we + don't have any vifs? */ + arg.channel.mode = chan_to_phymode(&ar->hw->conf.chandef); + + arg.channel.min_power = channel->max_power * 3; + arg.channel.max_power = channel->max_power * 4; + arg.channel.max_reg_power = channel->max_reg_power * 4; + arg.channel.max_antenna_gain = channel->max_antenna_gain; + + ret = ath10k_wmi_vdev_start(ar, &arg); + if (ret) { + ath10k_warn("Monitor vdev start failed: ret %d\n", ret); + return ret; + } + + ret = ath10k_vdev_setup_sync(ar); + if (ret) { + ath10k_warn("Monitor vdev setup failed %d\n", ret); + return ret; + } + + ret = ath10k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); + if (ret) { + ath10k_warn("Monitor vdev up failed: %d\n", ret); + goto vdev_stop; + } + + ar->monitor_vdev_id = vdev_id; + ar->monitor_enabled = true; + + return 0; + +vdev_stop: + ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); + if (ret) + ath10k_warn("Monitor vdev stop failed: %d\n", ret); + + return ret; +} + +static int ath10k_monitor_stop(struct ath10k *ar) +{ + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + /* For some reasons, ath10k_wmi_vdev_down() here couse + * often ath10k_wmi_vdev_stop() to fail. Next we could + * not run monitor vdev and driver reload + * required. Don't see such problems we skip + * ath10k_wmi_vdev_down() here. + */ + + ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); + if (ret) + ath10k_warn("Monitor vdev stop failed: %d\n", ret); + + ret = ath10k_vdev_setup_sync(ar); + if (ret) + ath10k_warn("Monitor_down sync failed: %d\n", ret); + + ar->monitor_enabled = false; + return ret; +} + +static int ath10k_monitor_create(struct ath10k *ar) +{ + int bit, ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + if (ar->monitor_present) { + ath10k_warn("Monitor mode already enabled\n"); + return 0; + } + + bit = ffs(ar->free_vdev_map); + if (bit == 0) { + ath10k_warn("No free VDEV slots\n"); + return -ENOMEM; + } + + ar->monitor_vdev_id = bit - 1; + ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id); + + ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, + WMI_VDEV_TYPE_MONITOR, + 0, ar->mac_addr); + if (ret) { + ath10k_warn("WMI vdev monitor create failed: ret %d\n", ret); + goto vdev_fail; + } + + ath10k_dbg(ATH10K_DBG_MAC, "Monitor interface created, vdev id: %d\n", + ar->monitor_vdev_id); + + ar->monitor_present = true; + return 0; + +vdev_fail: + /* + * Restore the ID to the global map. + */ + ar->free_vdev_map |= 1 << (ar->monitor_vdev_id); + return ret; +} + +static int ath10k_monitor_destroy(struct ath10k *ar) +{ + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); + + if (!ar->monitor_present) + return 0; + + ret = ath10k_wmi_vdev_delete(ar, ar->monitor_vdev_id); + if (ret) { + ath10k_warn("WMI vdev monitor delete failed: %d\n", ret); + return ret; + } + + ar->free_vdev_map |= 1 << (ar->monitor_vdev_id); + ar->monitor_present = false; + + ath10k_dbg(ATH10K_DBG_MAC, "Monitor interface destroyed, vdev id: %d\n", + ar->monitor_vdev_id); + return ret; +} + +static void ath10k_control_beaconing(struct ath10k_vif *arvif, + struct ieee80211_bss_conf *info) +{ + int ret = 0; + + if (!info->enable_beacon) { + ath10k_vdev_stop(arvif); + return; + } + + arvif->tx_seq_no = 0x1000; + + ret = ath10k_vdev_start(arvif); + if (ret) + return; + + ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, 0, info->bssid); + if (ret) { + ath10k_warn("Failed to bring up VDEV: %d\n", + arvif->vdev_id); + return; + } + ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d up\n", arvif->vdev_id); +} + +static void ath10k_control_ibss(struct ath10k_vif *arvif, + struct ieee80211_bss_conf *info, + const u8 self_peer[ETH_ALEN]) +{ + int ret = 0; + + if (!info->ibss_joined) { + ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, self_peer); + if (ret) + ath10k_warn("Failed to delete IBSS self peer:%pM for VDEV:%d ret:%d\n", + self_peer, arvif->vdev_id, ret); + + if (is_zero_ether_addr(arvif->u.ibss.bssid)) + return; + + ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, + arvif->u.ibss.bssid); + if (ret) { + ath10k_warn("Failed to delete IBSS BSSID peer:%pM for VDEV:%d ret:%d\n", + arvif->u.ibss.bssid, arvif->vdev_id, ret); + return; + } + + memset(arvif->u.ibss.bssid, 0, ETH_ALEN); + + return; + } + + ret = ath10k_peer_create(arvif->ar, arvif->vdev_id, self_peer); + if (ret) { + ath10k_warn("Failed to create IBSS self peer:%pM for VDEV:%d ret:%d\n", + self_peer, arvif->vdev_id, ret); + return; + } + + ret = ath10k_wmi_vdev_set_param(arvif->ar, arvif->vdev_id, + WMI_VDEV_PARAM_ATIM_WINDOW, + ATH10K_DEFAULT_ATIM); + if (ret) + ath10k_warn("Failed to set IBSS ATIM for VDEV:%d ret:%d\n", + arvif->vdev_id, ret); +} + +/* + * Review this when mac80211 gains per-interface powersave support. + */ +static void ath10k_ps_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath10k_generic_iter *ar_iter = data; + struct ieee80211_conf *conf = &ar_iter->ar->hw->conf; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + enum wmi_sta_powersave_param param; + enum wmi_sta_ps_mode psmode; + int ret; + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (conf->flags & IEEE80211_CONF_PS) { + psmode = WMI_STA_PS_MODE_ENABLED; + param = WMI_STA_PS_PARAM_INACTIVITY_TIME; + + ret = ath10k_wmi_set_sta_ps_param(ar_iter->ar, + arvif->vdev_id, + param, + conf->dynamic_ps_timeout); + if (ret) { + ath10k_warn("Failed to set inactivity time for VDEV: %d\n", + arvif->vdev_id); + return; + } + + ar_iter->ret = ret; + } else { + psmode = WMI_STA_PS_MODE_DISABLED; + } + + ar_iter->ret = ath10k_wmi_set_psmode(ar_iter->ar, arvif->vdev_id, + psmode); + if (ar_iter->ret) + ath10k_warn("Failed to set PS Mode: %d for VDEV: %d\n", + psmode, arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, "Set PS Mode: %d for VDEV: %d\n", + psmode, arvif->vdev_id); +} + +/**********************/ +/* Station management */ +/**********************/ + +static void ath10k_peer_assoc_h_basic(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct ieee80211_bss_conf *bss_conf, + struct wmi_peer_assoc_complete_arg *arg) +{ + memcpy(arg->addr, sta->addr, ETH_ALEN); + arg->vdev_id = arvif->vdev_id; + arg->peer_aid = sta->aid; + arg->peer_flags |= WMI_PEER_AUTH; + + if (arvif->vdev_type == WMI_VDEV_TYPE_STA) + /* + * Seems FW have problems with Power Save in STA + * mode when we setup this parameter to high (eg. 5). + * Often we see that FW don't send NULL (with clean P flags) + * frame even there is info about buffered frames in beacons. + * Sometimes we have to wait more than 10 seconds before FW + * will wakeup. Often sending one ping from AP to our device + * just fail (more than 50%). + * + * Seems setting this FW parameter to 1 couse FW + * will check every beacon and will wakup immediately + * after detection buffered data. + */ + arg->peer_listen_intval = 1; + else + arg->peer_listen_intval = ar->hw->conf.listen_interval; + + arg->peer_num_spatial_streams = 1; + + /* + * The assoc capabilities are available only in managed mode. + */ + if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf) + arg->peer_caps = bss_conf->assoc_capability; +} + +static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, + struct ath10k_vif *arvif, + struct wmi_peer_assoc_complete_arg *arg) +{ + struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_bss_conf *info = &vif->bss_conf; + struct cfg80211_bss *bss; + const u8 *rsnie = NULL; + const u8 *wpaie = NULL; + + bss = cfg80211_get_bss(ar->hw->wiphy, ar->hw->conf.chandef.chan, + info->bssid, NULL, 0, 0, 0); + if (bss) { + const struct cfg80211_bss_ies *ies; + + rcu_read_lock(); + rsnie = ieee80211_bss_get_ie(bss, WLAN_EID_RSN); + + ies = rcu_dereference(bss->ies); + + wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies->data, + ies->len); + rcu_read_unlock(); + cfg80211_put_bss(ar->hw->wiphy, bss); + } + + /* FIXME: base on RSN IE/WPA IE is a correct idea? */ + if (rsnie || wpaie) { + ath10k_dbg(ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__); + arg->peer_flags |= WMI_PEER_NEED_PTK_4_WAY; + } + + if (wpaie) { + ath10k_dbg(ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__); + arg->peer_flags |= WMI_PEER_NEED_GTK_2_WAY; + } +} + +static void ath10k_peer_assoc_h_rates(struct ath10k *ar, + struct ieee80211_sta *sta, + struct wmi_peer_assoc_complete_arg *arg) +{ + struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; + const struct ieee80211_supported_band *sband; + const struct ieee80211_rate *rates; + u32 ratemask; + int i; + + sband = ar->hw->wiphy->bands[ar->hw->conf.chandef.chan->band]; + ratemask = sta->supp_rates[ar->hw->conf.chandef.chan->band]; + rates = sband->bitrates; + + rateset->num_rates = 0; + + for (i = 0; i < 32; i++, ratemask >>= 1, rates++) { + if (!(ratemask & 1)) + continue; + + rateset->rates[rateset->num_rates] = rates->hw_value; + rateset->num_rates++; + } +} + +static void ath10k_peer_assoc_h_ht(struct ath10k *ar, + struct ieee80211_sta *sta, + struct wmi_peer_assoc_complete_arg *arg) +{ + const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; + int smps; + int i, n; + + if (!ht_cap->ht_supported) + return; + + arg->peer_flags |= WMI_PEER_HT; + arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + + ht_cap->ampdu_factor)) - 1; + + arg->peer_mpdu_density = + ath10k_parse_mpdudensity(ht_cap->ampdu_density); + + arg->peer_ht_caps = ht_cap->cap; + arg->peer_rate_caps |= WMI_RC_HT_FLAG; + + if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) + arg->peer_flags |= WMI_PEER_LDPC; + + if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) { + arg->peer_flags |= WMI_PEER_40MHZ; + arg->peer_rate_caps |= WMI_RC_CW40_FLAG; + } + + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) + arg->peer_rate_caps |= WMI_RC_SGI_FLAG; + + if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40) + arg->peer_rate_caps |= WMI_RC_SGI_FLAG; + + if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) { + arg->peer_rate_caps |= WMI_RC_TX_STBC_FLAG; + arg->peer_flags |= WMI_PEER_STBC; + } + + if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) { + u32 stbc; + stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC; + stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT; + stbc = stbc << WMI_RC_RX_STBC_FLAG_S; + arg->peer_rate_caps |= stbc; + arg->peer_flags |= WMI_PEER_STBC; + } + + smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS; + smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT; + + if (smps == WLAN_HT_CAP_SM_PS_STATIC) { + arg->peer_flags |= WMI_PEER_SPATIAL_MUX; + arg->peer_flags |= WMI_PEER_STATIC_MIMOPS; + } else if (smps == WLAN_HT_CAP_SM_PS_DYNAMIC) { + arg->peer_flags |= WMI_PEER_SPATIAL_MUX; + arg->peer_flags |= WMI_PEER_DYN_MIMOPS; + } + + if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2]) + arg->peer_rate_caps |= WMI_RC_TS_FLAG; + else if (ht_cap->mcs.rx_mask[1]) + arg->peer_rate_caps |= WMI_RC_DS_FLAG; + + for (i = 0, n = 0; i < IEEE80211_HT_MCS_MASK_LEN*8; i++) + if (ht_cap->mcs.rx_mask[i/8] & (1 << i%8)) + arg->peer_ht_rates.rates[n++] = i; + + arg->peer_ht_rates.num_rates = n; + arg->peer_num_spatial_streams = max((n+7) / 8, 1); + + ath10k_dbg(ATH10K_DBG_MAC, "mcs cnt %d nss %d\n", + arg->peer_ht_rates.num_rates, + arg->peer_num_spatial_streams); +} + +static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct ieee80211_bss_conf *bss_conf, + struct wmi_peer_assoc_complete_arg *arg) +{ + u32 uapsd = 0; + u32 max_sp = 0; + + if (sta->wme) + arg->peer_flags |= WMI_PEER_QOS; + + if (sta->wme && sta->uapsd_queues) { + ath10k_dbg(ATH10K_DBG_MAC, "uapsd_queues: 0x%X, max_sp: %d\n", + sta->uapsd_queues, sta->max_sp); + + arg->peer_flags |= WMI_PEER_APSD; + arg->peer_flags |= WMI_RC_UAPSD_FLAG; + + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC3_TRIGGER_EN; + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) + uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC2_TRIGGER_EN; + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) + uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC1_TRIGGER_EN; + if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) + uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN | + WMI_AP_PS_UAPSD_AC0_TRIGGER_EN; + + + if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP) + max_sp = sta->max_sp; + + ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, + sta->addr, + WMI_AP_PS_PEER_PARAM_UAPSD, + uapsd); + + ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, + sta->addr, + WMI_AP_PS_PEER_PARAM_MAX_SP, + max_sp); + + /* TODO setup this based on STA listen interval and + beacon interval. Currently we don't know + sta->listen_interval - mac80211 patch required. + Currently use 10 seconds */ + ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, + sta->addr, + WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, + 10); + } +} + +static void ath10k_peer_assoc_h_qos_sta(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct ieee80211_bss_conf *bss_conf, + struct wmi_peer_assoc_complete_arg *arg) +{ + if (bss_conf->qos) + arg->peer_flags |= WMI_PEER_QOS; +} + +static void ath10k_peer_assoc_h_vht(struct ath10k *ar, + struct ieee80211_sta *sta, + struct wmi_peer_assoc_complete_arg *arg) +{ + const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; + + if (!vht_cap->vht_supported) + return; + + arg->peer_flags |= WMI_PEER_VHT; + + arg->peer_vht_caps = vht_cap->cap; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + arg->peer_flags |= WMI_PEER_80MHZ; + + arg->peer_vht_rates.rx_max_rate = + __le16_to_cpu(vht_cap->vht_mcs.rx_highest); + arg->peer_vht_rates.rx_mcs_set = + __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map); + arg->peer_vht_rates.tx_max_rate = + __le16_to_cpu(vht_cap->vht_mcs.tx_highest); + arg->peer_vht_rates.tx_mcs_set = + __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map); + + ath10k_dbg(ATH10K_DBG_MAC, "mac vht peer\n"); +} + +static void ath10k_peer_assoc_h_qos(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct ieee80211_bss_conf *bss_conf, + struct wmi_peer_assoc_complete_arg *arg) +{ + switch (arvif->vdev_type) { + case WMI_VDEV_TYPE_AP: + ath10k_peer_assoc_h_qos_ap(ar, arvif, sta, bss_conf, arg); + break; + case WMI_VDEV_TYPE_STA: + ath10k_peer_assoc_h_qos_sta(ar, arvif, sta, bss_conf, arg); + break; + default: + break; + } +} + +static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct wmi_peer_assoc_complete_arg *arg) +{ + enum wmi_phy_mode phymode = MODE_UNKNOWN; + + /* FIXME: add VHT */ + + switch (ar->hw->conf.chandef.chan->band) { + case IEEE80211_BAND_2GHZ: + if (sta->ht_cap.ht_supported) { + if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11NG_HT40; + else + phymode = MODE_11NG_HT20; + } else { + phymode = MODE_11G; + } + + break; + case IEEE80211_BAND_5GHZ: + if (sta->ht_cap.ht_supported) { + if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + phymode = MODE_11NA_HT40; + else + phymode = MODE_11NA_HT20; + } else { + phymode = MODE_11A; + } + + break; + default: + break; + } + + arg->peer_phymode = phymode; + WARN_ON(phymode == MODE_UNKNOWN); +} + +static int ath10k_peer_assoc(struct ath10k *ar, + struct ath10k_vif *arvif, + struct ieee80211_sta *sta, + struct ieee80211_bss_conf *bss_conf) +{ + struct wmi_peer_assoc_complete_arg arg; + + memset(&arg, 0, sizeof(struct wmi_peer_assoc_complete_arg)); + + ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, &arg); + ath10k_peer_assoc_h_crypto(ar, arvif, &arg); + ath10k_peer_assoc_h_rates(ar, sta, &arg); + ath10k_peer_assoc_h_ht(ar, sta, &arg); + ath10k_peer_assoc_h_vht(ar, sta, &arg); + ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, &arg); + ath10k_peer_assoc_h_phymode(ar, arvif, sta, &arg); + + return ath10k_wmi_peer_assoc(ar, &arg); +} + +/* can be called only in mac80211 callbacks due to `key_count` usage */ +static void ath10k_bss_assoc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ieee80211_sta *ap_sta; + int ret; + + rcu_read_lock(); + + ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!ap_sta) { + ath10k_warn("Failed to find station entry for %pM\n", + bss_conf->bssid); + rcu_read_unlock(); + return; + } + + ret = ath10k_peer_assoc(ar, arvif, ap_sta, bss_conf); + if (ret) { + ath10k_warn("Peer assoc failed for %pM\n", bss_conf->bssid); + rcu_read_unlock(); + return; + } + + rcu_read_unlock(); + + ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, bss_conf->aid, + bss_conf->bssid); + if (ret) + ath10k_warn("VDEV: %d up failed: ret %d\n", + arvif->vdev_id, ret); + else + ath10k_dbg(ATH10K_DBG_MAC, + "VDEV: %d associated, BSSID: %pM, AID: %d\n", + arvif->vdev_id, bss_conf->bssid, bss_conf->aid); +} + +/* + * FIXME: flush TIDs + */ +static void ath10k_bss_disassoc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + int ret; + + /* + * For some reason, calling VDEV-DOWN before VDEV-STOP + * makes the FW to send frames via HTT after disassociation. + * No idea why this happens, even though VDEV-DOWN is supposed + * to be analogous to link down, so just stop the VDEV. + */ + ret = ath10k_vdev_stop(arvif); + if (!ret) + ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d stopped\n", + arvif->vdev_id); + + /* + * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and + * report beacons from previously associated network through HTT. + * This in turn would spam mac80211 WARN_ON if we bring down all + * interfaces as it expects there is no rx when no interface is + * running. + */ + ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) + ath10k_dbg(ATH10K_DBG_MAC, "VDEV: %d ath10k_wmi_vdev_down failed (%d)\n", + arvif->vdev_id, ret); + + ath10k_wmi_flush_tx(ar); + + arvif->def_wep_key_index = 0; +} + +static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, + struct ieee80211_sta *sta) +{ + int ret = 0; + + ret = ath10k_peer_assoc(ar, arvif, sta, NULL); + if (ret) { + ath10k_warn("WMI peer assoc failed for %pM\n", sta->addr); + return ret; + } + + ret = ath10k_install_peer_wep_keys(arvif, sta->addr); + if (ret) { + ath10k_warn("could not install peer wep keys (%d)\n", ret); + return ret; + } + + return ret; +} + +static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, + struct ieee80211_sta *sta) +{ + int ret = 0; + + ret = ath10k_clear_peer_keys(arvif, sta->addr); + if (ret) { + ath10k_warn("could not clear all peer wep keys (%d)\n", ret); + return ret; + } + + return ret; +} + +/**************/ +/* Regulatory */ +/**************/ + +static int ath10k_update_channel_list(struct ath10k *ar) +{ + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_supported_band **bands; + enum ieee80211_band band; + struct ieee80211_channel *channel; + struct wmi_scan_chan_list_arg arg = {0}; + struct wmi_channel_arg *ch; + bool passive; + int len; + int ret; + int i; + + bands = hw->wiphy->bands; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!bands[band]) + continue; + + for (i = 0; i < bands[band]->n_channels; i++) { + if (bands[band]->channels[i].flags & + IEEE80211_CHAN_DISABLED) + continue; + + arg.n_channels++; + } + } + + len = sizeof(struct wmi_channel_arg) * arg.n_channels; + arg.channels = kzalloc(len, GFP_KERNEL); + if (!arg.channels) + return -ENOMEM; + + ch = arg.channels; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!bands[band]) + continue; + + for (i = 0; i < bands[band]->n_channels; i++) { + channel = &bands[band]->channels[i]; + + if (channel->flags & IEEE80211_CHAN_DISABLED) + continue; + + ch->allow_ht = true; + + /* FIXME: when should we really allow VHT? */ + ch->allow_vht = true; + + ch->allow_ibss = + !(channel->flags & IEEE80211_CHAN_NO_IBSS); + + ch->ht40plus = + !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS); + + passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN; + ch->passive = passive; + + ch->freq = channel->center_freq; + ch->min_power = channel->max_power * 3; + ch->max_power = channel->max_power * 4; + ch->max_reg_power = channel->max_reg_power * 4; + ch->max_antenna_gain = channel->max_antenna_gain; + ch->reg_class_id = 0; /* FIXME */ + + /* FIXME: why use only legacy modes, why not any + * HT/VHT modes? Would that even make any + * difference? */ + if (channel->band == IEEE80211_BAND_2GHZ) + ch->mode = MODE_11G; + else + ch->mode = MODE_11A; + + if (WARN_ON_ONCE(ch->mode == MODE_UNKNOWN)) + continue; + + ath10k_dbg(ATH10K_DBG_WMI, + "%s: [%zd/%d] freq %d maxpower %d regpower %d antenna %d mode %d\n", + __func__, ch - arg.channels, arg.n_channels, + ch->freq, ch->max_power, ch->max_reg_power, + ch->max_antenna_gain, ch->mode); + + ch++; + } + } + + ret = ath10k_wmi_scan_chan_list(ar, &arg); + kfree(arg.channels); + + return ret; +} + +static void ath10k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct reg_dmn_pair_mapping *regpair; + struct ath10k *ar = hw->priv; + int ret; + + ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory); + + ret = ath10k_update_channel_list(ar); + if (ret) + ath10k_warn("could not update channel list (%d)\n", ret); + + regpair = ar->ath_common.regulatory.regpair; + /* Target allows setting up per-band regdomain but ath_common provides + * a combined one only */ + ret = ath10k_wmi_pdev_set_regdomain(ar, + regpair->regDmnEnum, + regpair->regDmnEnum, /* 2ghz */ + regpair->regDmnEnum, /* 5ghz */ + regpair->reg_2ghz_ctl, + regpair->reg_5ghz_ctl); + if (ret) + ath10k_warn("could not set pdev regdomain (%d)\n", ret); +} + +/***************/ +/* TX handlers */ +/***************/ + +/* + * Frames sent to the FW have to be in "Native Wifi" format. + * Strip the QoS field from the 802.11 header. + */ +static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (void *)skb->data; + u8 *qos_ctl; + + if (!ieee80211_is_data_qos(hdr->frame_control)) + return; + + qos_ctl = ieee80211_get_qos_ctl(hdr); + memmove(qos_ctl, qos_ctl + IEEE80211_QOS_CTL_LEN, + skb->len - ieee80211_hdrlen(hdr->frame_control)); + skb_trim(skb, skb->len - IEEE80211_QOS_CTL_LEN); +} + +static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k *ar = arvif->ar; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_key_conf *key = info->control.hw_key; + int ret; + + /* TODO AP mode should be implemented */ + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (!ieee80211_has_protected(hdr->frame_control)) + return; + + if (!key) + return; + + if (key->cipher != WLAN_CIPHER_SUITE_WEP40 && + key->cipher != WLAN_CIPHER_SUITE_WEP104) + return; + + if (key->keyidx == arvif->def_wep_key_index) + return; + + ath10k_dbg(ATH10K_DBG_MAC, "new wep keyidx will be %d\n", key->keyidx); + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_DEF_KEYID, + key->keyidx); + if (ret) { + ath10k_warn("could not update wep keyidx (%d)\n", ret); + return; + } + + arvif->def_wep_key_index = key->keyidx; +} + +static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + /* This is case only for P2P_GO */ + if (arvif->vdev_type != WMI_VDEV_TYPE_AP || + arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + return; + + if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { + spin_lock_bh(&ar->data_lock); + if (arvif->u.ap.noa_data) + if (!pskb_expand_head(skb, 0, arvif->u.ap.noa_len, + GFP_ATOMIC)) + memcpy(skb_put(skb, arvif->u.ap.noa_len), + arvif->u.ap.noa_data, + arvif->u.ap.noa_len); + spin_unlock_bh(&ar->data_lock); + } +} + +static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int ret; + + if (ieee80211_is_mgmt(hdr->frame_control)) + ret = ath10k_htt_mgmt_tx(ar->htt, skb); + else if (ieee80211_is_nullfunc(hdr->frame_control)) + /* FW does not report tx status properly for NullFunc frames + * unless they are sent through mgmt tx path. mac80211 sends + * those frames when it detects link/beacon loss and depends on + * the tx status to be correct. */ + ret = ath10k_htt_mgmt_tx(ar->htt, skb); + else + ret = ath10k_htt_tx(ar->htt, skb); + + if (ret) { + ath10k_warn("tx failed (%d). dropping packet.\n", ret); + ieee80211_free_txskb(ar->hw, skb); + } +} + +void ath10k_offchan_tx_purge(struct ath10k *ar) +{ + struct sk_buff *skb; + + for (;;) { + skb = skb_dequeue(&ar->offchan_tx_queue); + if (!skb) + break; + + ieee80211_free_txskb(ar->hw, skb); + } +} + +void ath10k_offchan_tx_work(struct work_struct *work) +{ + struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work); + struct ath10k_peer *peer; + struct ieee80211_hdr *hdr; + struct sk_buff *skb; + const u8 *peer_addr; + int vdev_id; + int ret; + + /* FW requirement: We must create a peer before FW will send out + * an offchannel frame. Otherwise the frame will be stuck and + * never transmitted. We delete the peer upon tx completion. + * It is unlikely that a peer for offchannel tx will already be + * present. However it may be in some rare cases so account for that. + * Otherwise we might remove a legitimate peer and break stuff. */ + + for (;;) { + skb = skb_dequeue(&ar->offchan_tx_queue); + if (!skb) + break; + + mutex_lock(&ar->conf_mutex); + + ath10k_dbg(ATH10K_DBG_MAC, "processing offchannel skb %p\n", + skb); + + hdr = (struct ieee80211_hdr *)skb->data; + peer_addr = ieee80211_get_DA(hdr); + vdev_id = ATH10K_SKB_CB(skb)->htt.vdev_id; + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, vdev_id, peer_addr); + spin_unlock_bh(&ar->data_lock); + + if (peer) + ath10k_dbg(ATH10K_DBG_MAC, "peer %pM on vdev %d already present\n", + peer_addr, vdev_id); + + if (!peer) { + ret = ath10k_peer_create(ar, vdev_id, peer_addr); + if (ret) + ath10k_warn("peer %pM on vdev %d not created (%d)\n", + peer_addr, vdev_id, ret); + } + + spin_lock_bh(&ar->data_lock); + INIT_COMPLETION(ar->offchan_tx_completed); + ar->offchan_tx_skb = skb; + spin_unlock_bh(&ar->data_lock); + + ath10k_tx_htt(ar, skb); + + ret = wait_for_completion_timeout(&ar->offchan_tx_completed, + 3 * HZ); + if (ret <= 0) + ath10k_warn("timed out waiting for offchannel skb %p\n", + skb); + + if (!peer) { + ret = ath10k_peer_delete(ar, vdev_id, peer_addr); + if (ret) + ath10k_warn("peer %pM on vdev %d not deleted (%d)\n", + peer_addr, vdev_id, ret); + } + + mutex_unlock(&ar->conf_mutex); + } +} + +/************/ +/* Scanning */ +/************/ + +/* + * This gets called if we dont get a heart-beat during scan. + * This may indicate the FW has hung and we need to abort the + * scan manually to prevent cancel_hw_scan() from deadlocking + */ +void ath10k_reset_scan(unsigned long ptr) +{ + struct ath10k *ar = (struct ath10k *)ptr; + + spin_lock_bh(&ar->data_lock); + if (!ar->scan.in_progress) { + spin_unlock_bh(&ar->data_lock); + return; + } + + ath10k_warn("scan timeout. resetting. fw issue?\n"); + + if (ar->scan.is_roc) + ieee80211_remain_on_channel_expired(ar->hw); + else + ieee80211_scan_completed(ar->hw, 1 /* aborted */); + + ar->scan.in_progress = false; + complete_all(&ar->scan.completed); + spin_unlock_bh(&ar->data_lock); +} + +static int ath10k_abort_scan(struct ath10k *ar) +{ + struct wmi_stop_scan_arg arg = { + .req_id = 1, /* FIXME */ + .req_type = WMI_SCAN_STOP_ONE, + .u.scan_id = ATH10K_SCAN_ID, + }; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + del_timer_sync(&ar->scan.timeout); + + spin_lock_bh(&ar->data_lock); + if (!ar->scan.in_progress) { + spin_unlock_bh(&ar->data_lock); + return 0; + } + + ar->scan.aborting = true; + spin_unlock_bh(&ar->data_lock); + + ret = ath10k_wmi_stop_scan(ar, &arg); + if (ret) { + ath10k_warn("could not submit wmi stop scan (%d)\n", ret); + return -EIO; + } + + ath10k_wmi_flush_tx(ar); + + ret = wait_for_completion_timeout(&ar->scan.completed, 3*HZ); + if (ret == 0) + ath10k_warn("timed out while waiting for scan to stop\n"); + + /* scan completion may be done right after we timeout here, so let's + * check the in_progress and tell mac80211 scan is completed. if we + * don't do that and FW fails to send us scan completion indication + * then userspace won't be able to scan anymore */ + ret = 0; + + spin_lock_bh(&ar->data_lock); + if (ar->scan.in_progress) { + ath10k_warn("could not stop scan. its still in progress\n"); + ar->scan.in_progress = false; + ath10k_offchan_tx_purge(ar); + ret = -ETIMEDOUT; + } + spin_unlock_bh(&ar->data_lock); + + return ret; +} + +static int ath10k_start_scan(struct ath10k *ar, + const struct wmi_start_scan_arg *arg) +{ + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ret = ath10k_wmi_start_scan(ar, arg); + if (ret) + return ret; + + /* make sure we submit the command so the completion + * timeout makes sense */ + ath10k_wmi_flush_tx(ar); + + ret = wait_for_completion_timeout(&ar->scan.started, 1*HZ); + if (ret == 0) { + ath10k_abort_scan(ar); + return ret; + } + + /* the scan can complete earlier, before we even + * start the timer. in that case the timer handler + * checks ar->scan.in_progress and bails out if its + * false. Add a 200ms margin to account event/command + * processing. */ + mod_timer(&ar->scan.timeout, jiffies + + msecs_to_jiffies(arg->max_scan_time+200)); + return 0; +} + +/**********************/ +/* mac80211 callbacks */ +/**********************/ + +static void ath10k_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = NULL; + u32 vdev_id = 0; + u8 tid; + + if (info->control.vif) { + arvif = ath10k_vif_to_arvif(info->control.vif); + vdev_id = arvif->vdev_id; + } else if (ar->monitor_enabled) { + vdev_id = ar->monitor_vdev_id; + } + + /* We should disable CCK RATE due to P2P */ + if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) + ath10k_dbg(ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n"); + + /* we must calculate tid before we apply qos workaround + * as we'd lose the qos control field */ + tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST; + if (ieee80211_is_data_qos(hdr->frame_control) && + is_unicast_ether_addr(ieee80211_get_DA(hdr))) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + } + + ath10k_tx_h_qos_workaround(hw, control, skb); + ath10k_tx_h_update_wep_key(skb); + ath10k_tx_h_add_p2p_noa_ie(ar, skb); + ath10k_tx_h_seq_no(skb); + + memset(ATH10K_SKB_CB(skb), 0, sizeof(*ATH10K_SKB_CB(skb))); + ATH10K_SKB_CB(skb)->htt.vdev_id = vdev_id; + ATH10K_SKB_CB(skb)->htt.tid = tid; + + if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) { + spin_lock_bh(&ar->data_lock); + ATH10K_SKB_CB(skb)->htt.is_offchan = true; + ATH10K_SKB_CB(skb)->htt.vdev_id = ar->scan.vdev_id; + spin_unlock_bh(&ar->data_lock); + + ath10k_dbg(ATH10K_DBG_MAC, "queued offchannel skb %p\n", skb); + + skb_queue_tail(&ar->offchan_tx_queue, skb); + ieee80211_queue_work(hw, &ar->offchan_tx_work); + return; + } + + ath10k_tx_htt(ar, skb); +} + +/* + * Initialize various parameters with default vaules. + */ +static int ath10k_start(struct ieee80211_hw *hw) +{ + struct ath10k *ar = hw->priv; + int ret; + + ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1); + if (ret) + ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n", + ret); + + ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 0); + if (ret) + ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n", + ret); + + return 0; +} + +static void ath10k_stop(struct ieee80211_hw *hw) +{ + struct ath10k *ar = hw->priv; + + /* avoid leaks in case FW never confirms scan for offchannel */ + cancel_work_sync(&ar->offchan_tx_work); + ath10k_offchan_tx_purge(ar); +} + +static int ath10k_config(struct ieee80211_hw *hw, u32 changed) +{ + struct ath10k_generic_iter ar_iter; + struct ath10k *ar = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + int ret = 0; + u32 flags; + + mutex_lock(&ar->conf_mutex); + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + ath10k_dbg(ATH10K_DBG_MAC, "Config channel %d mhz\n", + conf->chandef.chan->center_freq); + spin_lock_bh(&ar->data_lock); + ar->rx_channel = conf->chandef.chan; + spin_unlock_bh(&ar->data_lock); + } + + if (changed & IEEE80211_CONF_CHANGE_PS) { + memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); + ar_iter.ar = ar; + flags = IEEE80211_IFACE_ITER_RESUME_ALL; + + ieee80211_iterate_active_interfaces_atomic(hw, + flags, + ath10k_ps_iter, + &ar_iter); + + ret = ar_iter.ret; + } + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + if (conf->flags & IEEE80211_CONF_MONITOR) + ret = ath10k_monitor_create(ar); + else + ret = ath10k_monitor_destroy(ar); + } + + mutex_unlock(&ar->conf_mutex); + return ret; +} + +/* + * TODO: + * Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE, + * because we will send mgmt frames without CCK. This requirement + * for P2P_FIND/GO_NEG should be handled by checking CCK flag + * in the TX packet. + */ +static int ath10k_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + enum wmi_sta_powersave_param param; + int ret = 0; + u32 value; + int bit; + + mutex_lock(&ar->conf_mutex); + + arvif->ar = ar; + arvif->vif = vif; + + if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { + ath10k_warn("Only one monitor interface allowed\n"); + ret = -EBUSY; + goto exit; + } + + bit = ffs(ar->free_vdev_map); + if (bit == 0) { + ret = -EBUSY; + goto exit; + } + + arvif->vdev_id = bit - 1; + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + ar->free_vdev_map &= ~(1 << arvif->vdev_id); + + if (ar->p2p) + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; + + switch (vif->type) { + case NL80211_IFTYPE_UNSPECIFIED: + case NL80211_IFTYPE_STATION: + arvif->vdev_type = WMI_VDEV_TYPE_STA; + if (vif->p2p) + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; + break; + case NL80211_IFTYPE_ADHOC: + arvif->vdev_type = WMI_VDEV_TYPE_IBSS; + break; + case NL80211_IFTYPE_AP: + arvif->vdev_type = WMI_VDEV_TYPE_AP; + + if (vif->p2p) + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; + break; + case NL80211_IFTYPE_MONITOR: + arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; + break; + default: + WARN_ON(1); + break; + } + + ath10k_dbg(ATH10K_DBG_MAC, "Add interface: id %d type %d subtype %d\n", + arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); + + ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, + arvif->vdev_subtype, vif->addr); + if (ret) { + ath10k_warn("WMI vdev create failed: ret %d\n", ret); + goto exit; + } + + ret = ath10k_wmi_vdev_set_param(ar, 0, WMI_VDEV_PARAM_DEF_KEYID, + arvif->def_wep_key_index); + if (ret) + ath10k_warn("Failed to set default keyid: %d\n", ret); + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_TX_ENCAP_TYPE, + ATH10K_HW_TXRX_NATIVE_WIFI); + if (ret) + ath10k_warn("Failed to set TX encap: %d\n", ret); + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr); + if (ret) { + ath10k_warn("Failed to create peer for AP: %d\n", ret); + goto exit; + } + } + + if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { + param = WMI_STA_PS_PARAM_RX_WAKE_POLICY; + value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; + ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + param, value); + if (ret) + ath10k_warn("Failed to set RX wake policy: %d\n", ret); + + param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD; + value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS; + ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + param, value); + if (ret) + ath10k_warn("Failed to set TX wake thresh: %d\n", ret); + + param = WMI_STA_PS_PARAM_PSPOLL_COUNT; + value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX; + ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + param, value); + if (ret) + ath10k_warn("Failed to set PSPOLL count: %d\n", ret); + } + + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + ar->monitor_present = true; + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static void ath10k_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + int ret; + + mutex_lock(&ar->conf_mutex); + + ath10k_dbg(ATH10K_DBG_MAC, "Remove interface: id %d\n", arvif->vdev_id); + + ar->free_vdev_map |= 1 << (arvif->vdev_id); + + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { + ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, vif->addr); + if (ret) + ath10k_warn("Failed to remove peer for AP: %d\n", ret); + + kfree(arvif->u.ap.noa_data); + } + + ret = ath10k_wmi_vdev_delete(ar, arvif->vdev_id); + if (ret) + ath10k_warn("WMI vdev delete failed: %d\n", ret); + + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) + ar->monitor_present = false; + + ath10k_peer_cleanup(ar, arvif->vdev_id); + + mutex_unlock(&ar->conf_mutex); +} + +/* + * FIXME: Has to be verified. + */ +#define SUPPORTED_FILTERS \ + (FIF_PROMISC_IN_BSS | \ + FIF_ALLMULTI | \ + FIF_CONTROL | \ + FIF_PSPOLL | \ + FIF_OTHER_BSS | \ + FIF_BCN_PRBRESP_PROMISC | \ + FIF_PROBE_REQ | \ + FIF_FCSFAIL) + +static void ath10k_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct ath10k *ar = hw->priv; + int ret; + + mutex_lock(&ar->conf_mutex); + + changed_flags &= SUPPORTED_FILTERS; + *total_flags &= SUPPORTED_FILTERS; + ar->filter_flags = *total_flags; + + if ((ar->filter_flags & FIF_PROMISC_IN_BSS) && + !ar->monitor_enabled) { + ret = ath10k_monitor_start(ar, ar->monitor_vdev_id); + if (ret) + ath10k_warn("Unable to start monitor mode\n"); + else + ath10k_dbg(ATH10K_DBG_MAC, "Monitor mode started\n"); + } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && + ar->monitor_enabled) { + ret = ath10k_monitor_stop(ar); + if (ret) + ath10k_warn("Unable to stop monitor mode\n"); + else + ath10k_dbg(ATH10K_DBG_MAC, "Monitor mode stopped\n"); + } + + mutex_unlock(&ar->conf_mutex); +} + +static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + int ret = 0; + + mutex_lock(&ar->conf_mutex); + + if (changed & BSS_CHANGED_IBSS) + ath10k_control_ibss(arvif, info, vif->addr); + + if (changed & BSS_CHANGED_BEACON_INT) { + arvif->beacon_interval = info->beacon_int; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_BEACON_INTERVAL, + arvif->beacon_interval); + if (ret) + ath10k_warn("Failed to set beacon interval for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Beacon interval: %d set for VDEV: %d\n", + arvif->beacon_interval, arvif->vdev_id); + } + + if (changed & BSS_CHANGED_BEACON) { + ret = ath10k_wmi_pdev_set_param(ar, + WMI_PDEV_PARAM_BEACON_TX_MODE, + WMI_BEACON_STAGGERED_MODE); + if (ret) + ath10k_warn("Failed to set beacon mode for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set staggered beacon mode for VDEV: %d\n", + arvif->vdev_id); + } + + if (changed & BSS_CHANGED_DTIM_PERIOD) { + arvif->dtim_period = info->dtim_period; + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_DTIM_PERIOD, + arvif->dtim_period); + if (ret) + ath10k_warn("Failed to set dtim period for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set dtim period: %d for VDEV: %d\n", + arvif->dtim_period, arvif->vdev_id); + } + + if (changed & BSS_CHANGED_SSID && + vif->type == NL80211_IFTYPE_AP) { + arvif->u.ap.ssid_len = info->ssid_len; + if (info->ssid_len) + memcpy(arvif->u.ap.ssid, info->ssid, info->ssid_len); + arvif->u.ap.hidden_ssid = info->hidden_ssid; + } + + if (changed & BSS_CHANGED_BSSID) { + if (!is_zero_ether_addr(info->bssid)) { + ret = ath10k_peer_create(ar, arvif->vdev_id, + info->bssid); + if (ret) + ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", + info->bssid, arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Added peer: %pM for VDEV: %d\n", + info->bssid, arvif->vdev_id); + + + if (vif->type == NL80211_IFTYPE_STATION) { + /* + * this is never erased as we it for crypto key + * clearing; this is FW requirement + */ + memcpy(arvif->u.sta.bssid, info->bssid, + ETH_ALEN); + + ret = ath10k_vdev_start(arvif); + if (!ret) + ath10k_dbg(ATH10K_DBG_MAC, + "VDEV: %d started with BSSID: %pM\n", + arvif->vdev_id, info->bssid); + } + + /* + * Mac80211 does not keep IBSS bssid when leaving IBSS, + * so driver need to store it. It is needed when leaving + * IBSS in order to remove BSSID peer. + */ + if (vif->type == NL80211_IFTYPE_ADHOC) + memcpy(arvif->u.ibss.bssid, info->bssid, + ETH_ALEN); + } + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + ath10k_control_beaconing(arvif, info); + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + u32 cts_prot; + if (info->use_cts_prot) + cts_prot = 1; + else + cts_prot = 0; + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_ENABLE_RTSCTS, + cts_prot); + if (ret) + ath10k_warn("Failed to set CTS prot for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set CTS prot: %d for VDEV: %d\n", + cts_prot, arvif->vdev_id); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + u32 slottime; + if (info->use_short_slot) + slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */ + + else + slottime = WMI_VDEV_SLOT_TIME_LONG; /* 20us */ + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_SLOT_TIME, + slottime); + if (ret) + ath10k_warn("Failed to set erp slot for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set slottime: %d for VDEV: %d\n", + slottime, arvif->vdev_id); + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + u32 preamble; + if (info->use_short_preamble) + preamble = WMI_VDEV_PREAMBLE_SHORT; + else + preamble = WMI_VDEV_PREAMBLE_LONG; + + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, + WMI_VDEV_PARAM_PREAMBLE, + preamble); + if (ret) + ath10k_warn("Failed to set preamble for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set preamble: %d for VDEV: %d\n", + preamble, arvif->vdev_id); + } + + if (changed & BSS_CHANGED_ASSOC) { + if (info->assoc) + ath10k_bss_assoc(hw, vif, info); + } + + mutex_unlock(&ar->conf_mutex); +} + +static int ath10k_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_scan_request *req) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct wmi_start_scan_arg arg; + int ret = 0; + int i; + + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + if (ar->scan.in_progress) { + spin_unlock_bh(&ar->data_lock); + ret = -EBUSY; + goto exit; + } + + INIT_COMPLETION(ar->scan.started); + INIT_COMPLETION(ar->scan.completed); + ar->scan.in_progress = true; + ar->scan.aborting = false; + ar->scan.is_roc = false; + ar->scan.vdev_id = arvif->vdev_id; + spin_unlock_bh(&ar->data_lock); + + memset(&arg, 0, sizeof(arg)); + ath10k_wmi_start_scan_init(ar, &arg); + arg.vdev_id = arvif->vdev_id; + arg.scan_id = ATH10K_SCAN_ID; + + if (!req->no_cck) + arg.scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES; + + if (req->ie_len) { + arg.ie_len = req->ie_len; + memcpy(arg.ie, req->ie, arg.ie_len); + } + + if (req->n_ssids) { + arg.n_ssids = req->n_ssids; + for (i = 0; i < arg.n_ssids; i++) { + arg.ssids[i].len = req->ssids[i].ssid_len; + arg.ssids[i].ssid = req->ssids[i].ssid; + } + } + + if (req->n_channels) { + arg.n_channels = req->n_channels; + for (i = 0; i < arg.n_channels; i++) + arg.channels[i] = req->channels[i]->center_freq; + } + + ret = ath10k_start_scan(ar, &arg); + if (ret) { + ath10k_warn("could not start hw scan (%d)\n", ret); + spin_lock_bh(&ar->data_lock); + ar->scan.in_progress = false; + spin_unlock_bh(&ar->data_lock); + } + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k *ar = hw->priv; + int ret; + + mutex_lock(&ar->conf_mutex); + ret = ath10k_abort_scan(ar); + if (ret) { + ath10k_warn("couldn't abort scan (%d). forcefully sending scan completion to mac80211\n", + ret); + ieee80211_scan_completed(hw, 1 /* aborted */); + } + mutex_unlock(&ar->conf_mutex); +} + +static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_peer *peer; + const u8 *peer_addr; + bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104; + int ret = 0; + + if (key->keyidx > WMI_MAX_KEY_INDEX) + return -ENOSPC; + + mutex_lock(&ar->conf_mutex); + + if (sta) + peer_addr = sta->addr; + else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) + peer_addr = vif->bss_conf.bssid; + else + peer_addr = vif->addr; + + key->hw_key_idx = key->keyidx; + + /* the peer should not disappear in mid-way (unless FW goes awry) since + * we already hold conf_mutex. we just make sure its there now. */ + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, arvif->vdev_id, peer_addr); + spin_unlock_bh(&ar->data_lock); + + if (!peer) { + if (cmd == SET_KEY) { + ath10k_warn("cannot install key for non-existent peer %pM\n", + peer_addr); + ret = -EOPNOTSUPP; + goto exit; + } else { + /* if the peer doesn't exist there is no key to disable + * anymore */ + goto exit; + } + } + + if (is_wep) { + if (cmd == SET_KEY) + arvif->wep_keys[key->keyidx] = key; + else + arvif->wep_keys[key->keyidx] = NULL; + + if (cmd == DISABLE_KEY) + ath10k_clear_vdev_key(arvif, key); + } + + ret = ath10k_install_key(arvif, key, cmd, peer_addr); + if (ret) { + ath10k_warn("ath10k_install_key failed (%d)\n", ret); + goto exit; + } + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, arvif->vdev_id, peer_addr); + if (peer && cmd == SET_KEY) + peer->keys[key->keyidx] = key; + else if (peer && cmd == DISABLE_KEY) + peer->keys[key->keyidx] = NULL; + else if (peer == NULL) + /* impossible unless FW goes crazy */ + ath10k_warn("peer %pM disappeared!\n", peer_addr); + spin_unlock_bh(&ar->data_lock); + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + enum ieee80211_sta_state old_state, + enum ieee80211_sta_state new_state) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + int ret = 0; + + mutex_lock(&ar->conf_mutex); + + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE && + vif->type != NL80211_IFTYPE_STATION) { + /* + * New station addition. + */ + ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr); + if (ret) + ath10k_warn("Failed to add peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Added peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); + } else if ((old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST)) { + /* + * Existing station deletion. + */ + ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); + if (ret) + ath10k_warn("Failed to delete peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Removed peer: %pM for VDEV: %d\n", + sta->addr, arvif->vdev_id); + + if (vif->type == NL80211_IFTYPE_STATION) + ath10k_bss_disassoc(hw, vif); + } else if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC && + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC)) { + /* + * New association. + */ + ret = ath10k_station_assoc(ar, arvif, sta); + if (ret) + ath10k_warn("Failed to associate station: %pM\n", + sta->addr); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Station %pM moved to assoc state\n", + sta->addr); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTH && + (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC)) { + /* + * Disassociation. + */ + ret = ath10k_station_disassoc(ar, arvif, sta); + if (ret) + ath10k_warn("Failed to disassociate station: %pM\n", + sta->addr); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Station %pM moved to disassociated state\n", + sta->addr); + } + + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, + u16 ac, bool enable) +{ + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + u32 value = 0; + int ret = 0; + + if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + return 0; + + switch (ac) { + case IEEE80211_AC_VO: + value = WMI_STA_PS_UAPSD_AC3_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC3_TRIGGER_EN; + break; + case IEEE80211_AC_VI: + value = WMI_STA_PS_UAPSD_AC2_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC2_TRIGGER_EN; + break; + case IEEE80211_AC_BE: + value = WMI_STA_PS_UAPSD_AC1_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC1_TRIGGER_EN; + break; + case IEEE80211_AC_BK: + value = WMI_STA_PS_UAPSD_AC0_DELIVERY_EN | + WMI_STA_PS_UAPSD_AC0_TRIGGER_EN; + break; + } + + if (enable) + arvif->u.sta.uapsd |= value; + else + arvif->u.sta.uapsd &= ~value; + + ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + WMI_STA_PS_PARAM_UAPSD, + arvif->u.sta.uapsd); + if (ret) { + ath10k_warn("could not set uapsd params %d\n", ret); + goto exit; + } + + if (arvif->u.sta.uapsd) + value = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD; + else + value = WMI_STA_PS_RX_WAKE_POLICY_WAKE; + + ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, + WMI_STA_PS_PARAM_RX_WAKE_POLICY, + value); + if (ret) + ath10k_warn("could not set rx wake param %d\n", ret); + +exit: + return ret; +} + +static int ath10k_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 ac, + const struct ieee80211_tx_queue_params *params) +{ + struct ath10k *ar = hw->priv; + struct wmi_wmm_params_arg *p = NULL; + int ret; + + mutex_lock(&ar->conf_mutex); + + switch (ac) { + case IEEE80211_AC_VO: + p = &ar->wmm_params.ac_vo; + break; + case IEEE80211_AC_VI: + p = &ar->wmm_params.ac_vi; + break; + case IEEE80211_AC_BE: + p = &ar->wmm_params.ac_be; + break; + case IEEE80211_AC_BK: + p = &ar->wmm_params.ac_bk; + break; + } + + if (WARN_ON(!p)) { + ret = -EINVAL; + goto exit; + } + + p->cwmin = params->cw_min; + p->cwmax = params->cw_max; + p->aifs = params->aifs; + + /* + * The channel time duration programmed in the HW is in absolute + * microseconds, while mac80211 gives the txop in units of + * 32 microseconds. + */ + p->txop = params->txop * 32; + + /* FIXME: FW accepts wmm params per hw, not per vif */ + ret = ath10k_wmi_pdev_set_wmm_params(ar, &ar->wmm_params); + if (ret) { + ath10k_warn("could not set wmm params %d\n", ret); + goto exit; + } + + ret = ath10k_conf_tx_uapsd(ar, vif, ac, params->uapsd); + if (ret) + ath10k_warn("could not set sta uapsd %d\n", ret); + +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +#define ATH10K_ROC_TIMEOUT_HZ (2*HZ) + +static int ath10k_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum ieee80211_roc_type type) +{ + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct wmi_start_scan_arg arg; + int ret; + + mutex_lock(&ar->conf_mutex); + + spin_lock_bh(&ar->data_lock); + if (ar->scan.in_progress) { + spin_unlock_bh(&ar->data_lock); + ret = -EBUSY; + goto exit; + } + + INIT_COMPLETION(ar->scan.started); + INIT_COMPLETION(ar->scan.completed); + INIT_COMPLETION(ar->scan.on_channel); + ar->scan.in_progress = true; + ar->scan.aborting = false; + ar->scan.is_roc = true; + ar->scan.vdev_id = arvif->vdev_id; + ar->scan.roc_freq = chan->center_freq; + spin_unlock_bh(&ar->data_lock); + + memset(&arg, 0, sizeof(arg)); + ath10k_wmi_start_scan_init(ar, &arg); + arg.vdev_id = arvif->vdev_id; + arg.scan_id = ATH10K_SCAN_ID; + arg.n_channels = 1; + arg.channels[0] = chan->center_freq; + arg.dwell_time_active = duration; + arg.dwell_time_passive = duration; + arg.max_scan_time = 2 * duration; + arg.scan_ctrl_flags |= WMI_SCAN_FLAG_PASSIVE; + arg.scan_ctrl_flags |= WMI_SCAN_FILTER_PROBE_REQ; + + ret = ath10k_start_scan(ar, &arg); + if (ret) { + ath10k_warn("could not start roc scan (%d)\n", ret); + spin_lock_bh(&ar->data_lock); + ar->scan.in_progress = false; + spin_unlock_bh(&ar->data_lock); + goto exit; + } + + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ); + if (ret == 0) { + ath10k_warn("could not switch to channel for roc scan\n"); + ath10k_abort_scan(ar); + ret = -ETIMEDOUT; + goto exit; + } + + ret = 0; +exit: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) +{ + struct ath10k *ar = hw->priv; + + mutex_lock(&ar->conf_mutex); + ath10k_abort_scan(ar); + mutex_unlock(&ar->conf_mutex); + + return 0; +} + +/* + * Both RTS and Fragmentation threshold are interface-specific + * in ath10k, but device-specific in mac80211. + */ +static void ath10k_set_rts_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath10k_generic_iter *ar_iter = data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + u32 rts = ar_iter->ar->hw->wiphy->rts_threshold; + + rts = min_t(u32, rts, ATH10K_RTS_MAX); + + ar_iter->ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id, + WMI_VDEV_PARAM_RTS_THRESHOLD, + rts); + if (ar_iter->ret) + ath10k_warn("Failed to set RTS threshold for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set RTS threshold: %d for VDEV: %d\n", + rts, arvif->vdev_id); +} + +static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct ath10k_generic_iter ar_iter; + struct ath10k *ar = hw->priv; + + memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); + ar_iter.ar = ar; + + mutex_lock(&ar->conf_mutex); + ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, + ath10k_set_rts_iter, &ar_iter); + mutex_unlock(&ar->conf_mutex); + + return ar_iter.ret; +} + +static void ath10k_set_frag_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +{ + struct ath10k_generic_iter *ar_iter = data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + u32 frag = ar_iter->ar->hw->wiphy->frag_threshold; + int ret; + + frag = clamp_t(u32, frag, + ATH10K_FRAGMT_THRESHOLD_MIN, + ATH10K_FRAGMT_THRESHOLD_MAX); + + ret = ath10k_wmi_vdev_set_param(ar_iter->ar, arvif->vdev_id, + WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, + frag); + + ar_iter->ret = ret; + if (ar_iter->ret) + ath10k_warn("Failed to set frag threshold for VDEV: %d\n", + arvif->vdev_id); + else + ath10k_dbg(ATH10K_DBG_MAC, + "Set frag threshold: %d for VDEV: %d\n", + frag, arvif->vdev_id); +} + +static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct ath10k_generic_iter ar_iter; + struct ath10k *ar = hw->priv; + + memset(&ar_iter, 0, sizeof(struct ath10k_generic_iter)); + ar_iter.ar = ar; + + mutex_lock(&ar->conf_mutex); + ieee80211_iterate_active_interfaces(hw, IEEE80211_IFACE_ITER_RESUME_ALL, + ath10k_set_frag_iter, &ar_iter); + mutex_unlock(&ar->conf_mutex); + + return ar_iter.ret; +} + +static void ath10k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) +{ + struct ath10k *ar = hw->priv; + int ret; + + /* mac80211 doesn't care if we really xmit queued frames or not + * we'll collect those frames either way if we stop/delete vdevs */ + if (drop) + return; + + ret = wait_event_timeout(ar->htt->empty_tx_wq, ({ + bool empty; + spin_lock_bh(&ar->htt->tx_lock); + empty = bitmap_empty(ar->htt->used_msdu_ids, + ar->htt->max_num_pending_tx); + spin_unlock_bh(&ar->htt->tx_lock); + (empty); + }), ATH10K_FLUSH_TIMEOUT_HZ); + if (ret <= 0) + ath10k_warn("tx not flushed\n"); +} + +/* TODO: Implement this function properly + * For now it is needed to reply to Probe Requests in IBSS mode. + * Propably we need this information from FW. + */ +static int ath10k_tx_last_beacon(struct ieee80211_hw *hw) +{ + return 1; +} + +static const struct ieee80211_ops ath10k_ops = { + .tx = ath10k_tx, + .start = ath10k_start, + .stop = ath10k_stop, + .config = ath10k_config, + .add_interface = ath10k_add_interface, + .remove_interface = ath10k_remove_interface, + .configure_filter = ath10k_configure_filter, + .bss_info_changed = ath10k_bss_info_changed, + .hw_scan = ath10k_hw_scan, + .cancel_hw_scan = ath10k_cancel_hw_scan, + .set_key = ath10k_set_key, + .sta_state = ath10k_sta_state, + .conf_tx = ath10k_conf_tx, + .remain_on_channel = ath10k_remain_on_channel, + .cancel_remain_on_channel = ath10k_cancel_remain_on_channel, + .set_rts_threshold = ath10k_set_rts_threshold, + .set_frag_threshold = ath10k_set_frag_threshold, + .flush = ath10k_flush, + .tx_last_beacon = ath10k_tx_last_beacon, +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .flags = (_flags), \ + .hw_value = (_rateid), \ +} + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static const struct ieee80211_channel ath10k_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +static const struct ieee80211_channel ath10k_5ghz_channels[] = { + CHAN5G(36, 5180, 14), + CHAN5G(40, 5200, 15), + CHAN5G(44, 5220, 16), + CHAN5G(48, 5240, 17), + CHAN5G(52, 5260, 18), + CHAN5G(56, 5280, 19), + CHAN5G(60, 5300, 20), + CHAN5G(64, 5320, 21), + CHAN5G(100, 5500, 22), + CHAN5G(104, 5520, 23), + CHAN5G(108, 5540, 24), + CHAN5G(112, 5560, 25), + CHAN5G(116, 5580, 26), + CHAN5G(120, 5600, 27), + CHAN5G(124, 5620, 28), + CHAN5G(128, 5640, 29), + CHAN5G(132, 5660, 30), + CHAN5G(136, 5680, 31), + CHAN5G(140, 5700, 32), + CHAN5G(149, 5745, 33), + CHAN5G(153, 5765, 34), + CHAN5G(157, 5785, 35), + CHAN5G(161, 5805, 36), + CHAN5G(165, 5825, 37), +}; + +static struct ieee80211_rate ath10k_rates[] = { + /* CCK */ + RATETAB_ENT(10, 0x82, 0), + RATETAB_ENT(20, 0x84, 0), + RATETAB_ENT(55, 0x8b, 0), + RATETAB_ENT(110, 0x96, 0), + /* OFDM */ + RATETAB_ENT(60, 0x0c, 0), + RATETAB_ENT(90, 0x12, 0), + RATETAB_ENT(120, 0x18, 0), + RATETAB_ENT(180, 0x24, 0), + RATETAB_ENT(240, 0x30, 0), + RATETAB_ENT(360, 0x48, 0), + RATETAB_ENT(480, 0x60, 0), + RATETAB_ENT(540, 0x6c, 0), +}; + +#define ath10k_a_rates (ath10k_rates + 4) +#define ath10k_a_rates_size (ARRAY_SIZE(ath10k_rates) - 4) +#define ath10k_g_rates (ath10k_rates + 0) +#define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates)) + +struct ath10k *ath10k_mac_create(void) +{ + struct ieee80211_hw *hw; + struct ath10k *ar; + + hw = ieee80211_alloc_hw(sizeof(struct ath10k), &ath10k_ops); + if (!hw) + return NULL; + + ar = hw->priv; + ar->hw = hw; + + return ar; +} + +void ath10k_mac_destroy(struct ath10k *ar) +{ + ieee80211_free_hw(ar->hw); +} + +static const struct ieee80211_iface_limit ath10k_if_limits[] = { + { + .max = 8, + .types = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_AP) + } +}; + +static const struct ieee80211_iface_combination ath10k_if_comb = { + .limits = ath10k_if_limits, + .n_limits = ARRAY_SIZE(ath10k_if_limits), + .max_interfaces = 8, + .num_different_channels = 1, + .beacon_int_infra_match = true, +}; + +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) +{ + struct ieee80211_sta_vht_cap vht_cap = {0}; + u16 mcs_map; + + vht_cap.vht_supported = 1; + vht_cap.cap = ar->vht_cap_info; + + /* FIXME: check dynamically how many streams board supports */ + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | + IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + + vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + + return vht_cap; +} + +static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) +{ + int i; + struct ieee80211_sta_ht_cap ht_cap = {0}; + + if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) + return ht_cap; + + ht_cap.ht_supported = 1; + ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; + ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; + + if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + + if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + + if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { + u32 smps; + + smps = WLAN_HT_CAP_SM_PS_DYNAMIC; + smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; + + ht_cap.cap |= smps; + } + + if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) + ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; + + if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { + u32 stbc; + + stbc = ar->ht_cap_info; + stbc &= WMI_HT_CAP_RX_STBC; + stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; + stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; + stbc &= IEEE80211_HT_CAP_RX_STBC; + + ht_cap.cap |= stbc; + } + + if (ar->ht_cap_info & WMI_HT_CAP_LDPC) + ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + + if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) + ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; + + /* max AMSDU is implicitly taken from vht_cap_info */ + if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) + ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + + for (i = 0; i < WMI_MAX_SPATIAL_STREAM; i++) + ht_cap.mcs.rx_mask[i] = 0xFF; + + ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; + + return ht_cap; +} + + +static void ath10k_get_arvif_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_vif_iter *arvif_iter = data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + if (arvif->vdev_id == arvif_iter->vdev_id) + arvif_iter->arvif = arvif; +} + +struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id) +{ + struct ath10k_vif_iter arvif_iter; + u32 flags; + + memset(&arvif_iter, 0, sizeof(struct ath10k_vif_iter)); + arvif_iter.vdev_id = vdev_id; + + flags = IEEE80211_IFACE_ITER_RESUME_ALL; + ieee80211_iterate_active_interfaces_atomic(ar->hw, + flags, + ath10k_get_arvif_iter, + &arvif_iter); + if (!arvif_iter.arvif) { + ath10k_warn("No VIF found for VDEV: %d\n", vdev_id); + return NULL; + } + + return arvif_iter.arvif; +} + +int ath10k_mac_register(struct ath10k *ar) +{ + struct ieee80211_supported_band *band; + struct ieee80211_sta_vht_cap vht_cap; + struct ieee80211_sta_ht_cap ht_cap; + void *channels; + int ret; + + SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr); + + SET_IEEE80211_DEV(ar->hw, ar->dev); + + ht_cap = ath10k_get_ht_cap(ar); + vht_cap = ath10k_create_vht_cap(ar); + + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + channels = kmemdup(ath10k_2ghz_channels, + sizeof(ath10k_2ghz_channels), + GFP_KERNEL); + if (!channels) + return -ENOMEM; + + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels); + band->channels = channels; + band->n_bitrates = ath10k_g_rates_size; + band->bitrates = ath10k_g_rates; + band->ht_cap = ht_cap; + + /* vht is not supported in 2.4 GHz */ + + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; + } + + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + channels = kmemdup(ath10k_5ghz_channels, + sizeof(ath10k_5ghz_channels), + GFP_KERNEL); + if (!channels) { + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + kfree(band->channels); + } + return -ENOMEM; + } + + band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; + band->n_channels = ARRAY_SIZE(ath10k_5ghz_channels); + band->channels = channels; + band->n_bitrates = ath10k_a_rates_size; + band->bitrates = ath10k_a_rates; + band->ht_cap = ht_cap; + band->vht_cap = vht_cap; + ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; + } + + ar->hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); + + ar->hw->flags = IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS | + IEEE80211_HW_SUPPORTS_UAPSD | + IEEE80211_HW_MFP_CAPABLE | + IEEE80211_HW_REPORTS_TX_ACK_STATUS | + IEEE80211_HW_HAS_RATE_CONTROL | + IEEE80211_HW_SUPPORTS_STATIC_SMPS | + IEEE80211_HW_WANT_MONITOR_VIF | + IEEE80211_HW_AP_LINK_PS; + + if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) + ar->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; + + if (ar->ht_cap_info & WMI_HT_CAP_ENABLED) { + ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + ar->hw->flags |= IEEE80211_HW_TX_AMPDU_SETUP_IN_HW; + } + + ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID; + ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN; + + ar->hw->vif_data_size = sizeof(struct ath10k_vif); + + ar->hw->channel_change_time = 5000; + ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL; + + ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + ar->hw->wiphy->max_remain_on_channel_duration = 5000; + + ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; + /* + * on LL hardware queues are managed entirely by the FW + * so we only advertise to mac we can do the queues thing + */ + ar->hw->queues = 4; + + ar->hw->wiphy->iface_combinations = &ath10k_if_comb; + ar->hw->wiphy->n_iface_combinations = 1; + + ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, + ath10k_reg_notifier); + if (ret) { + ath10k_err("Regulatory initialization failed\n"); + return ret; + } + + ret = ieee80211_register_hw(ar->hw); + if (ret) { + ath10k_err("ieee80211 registration failed: %d\n", ret); + return ret; + } + + if (!ath_is_world_regd(&ar->ath_common.regulatory)) { + ret = regulatory_hint(ar->hw->wiphy, + ar->ath_common.regulatory.alpha2); + if (ret) + goto exit; + } + + return 0; +exit: + ieee80211_unregister_hw(ar->hw); + return ret; +} + +void ath10k_mac_unregister(struct ath10k *ar) +{ + ieee80211_unregister_hw(ar->hw); + + kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); + kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + + SET_IEEE80211_DEV(ar->hw, NULL); +} diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h new file mode 100644 index 000000000000..27fc92e58829 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MAC_H_ +#define _MAC_H_ + +#include +#include "core.h" + +struct ath10k_generic_iter { + struct ath10k *ar; + int ret; +}; + +struct ath10k *ath10k_mac_create(void); +void ath10k_mac_destroy(struct ath10k *ar); +int ath10k_mac_register(struct ath10k *ar); +void ath10k_mac_unregister(struct ath10k *ar); +struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id); +void ath10k_reset_scan(unsigned long ptr); +void ath10k_offchan_tx_purge(struct ath10k *ar); +void ath10k_offchan_tx_work(struct work_struct *work); + +static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) +{ + return (struct ath10k_vif *)vif->drv_priv; +} + +static inline void ath10k_tx_h_seq_no(struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_vif *vif = info->control.vif; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (arvif->tx_seq_no == 0) + arvif->tx_seq_no = 0x1000; + + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + arvif->tx_seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(arvif->tx_seq_no); + } +} + +#endif /* _MAC_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c new file mode 100644 index 000000000000..8e4e8327d33e --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -0,0 +1,2506 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "core.h" +#include "debug.h" + +#include "targaddrs.h" +#include "bmi.h" + +#include "hif.h" +#include "htc.h" + +#include "ce.h" +#include "pci.h" + +unsigned int ath10k_target_ps; +module_param(ath10k_target_ps, uint, 0644); +MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option"); + +#define QCA988X_1_0_DEVICE_ID (0xabcd) +#define QCA988X_2_0_DEVICE_ID (0x003c) + +static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = { + { PCI_VDEVICE(ATHEROS, QCA988X_1_0_DEVICE_ID) }, /* PCI-E QCA988X V1 */ + { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ + {0} +}; + +static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address, + u32 *data); + +static void ath10k_pci_process_ce(struct ath10k *ar); +static int ath10k_pci_post_rx(struct ath10k *ar); +static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info, + int num); +static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info); +static void ath10k_pci_stop_ce(struct ath10k *ar); + +static const struct ce_attr host_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,}, + /* could be moved to share CE3 */ + /* target->host HTT + HTC control */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL,}, + /* target->host WMI */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,}, + /* host->target WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,}, + /* host->target HTT */ + { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,}, + /* unused */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* Target autonomous hif_memcpy */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,}, + /* ce_diag, the Diagnostic Window */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,}, +}; + +/* Target firmware's Copy Engine configuration. */ +static const struct ce_pipe_config target_ce_config_wlan[] = { + /* host->target HTC control and raw streams */ + { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0,}, + /* target->host HTT + HTC control */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0,}, + /* target->host WMI */ + { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* host->target HTT */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0,}, + /* NB: 50% of src nentries, since tx has 2 frags */ + /* unused */ + { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,}, + /* Reserved for target autonomous hif_memcpy */ + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0,}, + /* CE7 used only by Host */ +}; + +/* + * Diagnostic read/write access is provided for startup/config/debug usage. + * Caller must guarantee proper alignment, when applicable, and single user + * at any moment. + */ +static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, + int nbytes) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret = 0; + u32 buf; + unsigned int completed_nbytes, orig_nbytes, remaining_bytes; + unsigned int id; + unsigned int flags; + struct ce_state *ce_diag; + /* Host buffer address in CE space */ + u32 ce_data; + dma_addr_t ce_data_base = 0; + void *data_buf = NULL; + int i; + + /* + * This code cannot handle reads to non-memory space. Redirect to the + * register read fn but preserve the multi word read capability of + * this fn + */ + if (address < DRAM_BASE_ADDRESS) { + if (!IS_ALIGNED(address, 4) || + !IS_ALIGNED((unsigned long)data, 4)) + return -EIO; + + while ((nbytes >= 4) && ((ret = ath10k_pci_diag_read_access( + ar, address, (u32 *)data)) == 0)) { + nbytes -= sizeof(u32); + address += sizeof(u32); + data += sizeof(u32); + } + return ret; + } + + ce_diag = ar_pci->ce_diag; + + /* + * Allocate a temporary bounce buffer to hold caller's data + * to be DMA'ed from Target. This guarantees + * 1) 4-byte alignment + * 2) Buffer in DMA-able space + */ + orig_nbytes = nbytes; + data_buf = (unsigned char *)pci_alloc_consistent(ar_pci->pdev, + orig_nbytes, + &ce_data_base); + + if (!data_buf) { + ret = -ENOMEM; + goto done; + } + memset(data_buf, 0, orig_nbytes); + + remaining_bytes = orig_nbytes; + ce_data = ce_data_base; + while (remaining_bytes) { + nbytes = min_t(unsigned int, remaining_bytes, + DIAG_TRANSFER_LIMIT); + + ret = ath10k_ce_recv_buf_enqueue(ce_diag, NULL, ce_data); + if (ret != 0) + goto done; + + /* Request CE to send from Target(!) address to Host buffer */ + /* + * The address supplied by the caller is in the + * Target CPU virtual address space. + * + * In order to use this address with the diagnostic CE, + * convert it from Target CPU virtual address space + * to CE address space + */ + ath10k_pci_wake(ar); + address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, + address); + ath10k_pci_sleep(ar); + + ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, + 0); + if (ret) + goto done; + + i = 0; + while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { + mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + ret = -EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + ret = -EIO; + goto done; + } + + if (buf != (u32) address) { + ret = -EIO; + goto done; + } + + i = 0; + while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { + mdelay(1); + + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + ret = -EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + ret = -EIO; + goto done; + } + + if (buf != ce_data) { + ret = -EIO; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + ce_data += nbytes; + } + +done: + if (ret == 0) { + /* Copy data from allocated DMA buf to caller's buf */ + WARN_ON_ONCE(orig_nbytes & 3); + for (i = 0; i < orig_nbytes / sizeof(__le32); i++) { + ((u32 *)data)[i] = + __le32_to_cpu(((__le32 *)data_buf)[i]); + } + } else + ath10k_dbg(ATH10K_DBG_PCI, "%s failure (0x%x)\n", + __func__, address); + + if (data_buf) + pci_free_consistent(ar_pci->pdev, orig_nbytes, + data_buf, ce_data_base); + + return ret; +} + +/* Read 4-byte aligned data from Target memory or register */ +static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address, + u32 *data) +{ + /* Assume range doesn't cross this boundary */ + if (address >= DRAM_BASE_ADDRESS) + return ath10k_pci_diag_read_mem(ar, address, data, sizeof(u32)); + + ath10k_pci_wake(ar); + *data = ath10k_pci_read32(ar, address); + ath10k_pci_sleep(ar); + return 0; +} + +static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, + const void *data, int nbytes) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret = 0; + u32 buf; + unsigned int completed_nbytes, orig_nbytes, remaining_bytes; + unsigned int id; + unsigned int flags; + struct ce_state *ce_diag; + void *data_buf = NULL; + u32 ce_data; /* Host buffer address in CE space */ + dma_addr_t ce_data_base = 0; + int i; + + ce_diag = ar_pci->ce_diag; + + /* + * Allocate a temporary bounce buffer to hold caller's data + * to be DMA'ed to Target. This guarantees + * 1) 4-byte alignment + * 2) Buffer in DMA-able space + */ + orig_nbytes = nbytes; + data_buf = (unsigned char *)pci_alloc_consistent(ar_pci->pdev, + orig_nbytes, + &ce_data_base); + if (!data_buf) { + ret = -ENOMEM; + goto done; + } + + /* Copy caller's data to allocated DMA buf */ + WARN_ON_ONCE(orig_nbytes & 3); + for (i = 0; i < orig_nbytes / sizeof(__le32); i++) + ((__le32 *)data_buf)[i] = __cpu_to_le32(((u32 *)data)[i]); + + /* + * The address supplied by the caller is in the + * Target CPU virtual address space. + * + * In order to use this address with the diagnostic CE, + * convert it from + * Target CPU virtual address space + * to + * CE address space + */ + ath10k_pci_wake(ar); + address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, address); + ath10k_pci_sleep(ar); + + remaining_bytes = orig_nbytes; + ce_data = ce_data_base; + while (remaining_bytes) { + /* FIXME: check cast */ + nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); + + /* Set up to receive directly into Target(!) address */ + ret = ath10k_ce_recv_buf_enqueue(ce_diag, NULL, address); + if (ret != 0) + goto done; + + /* + * Request CE to send caller-supplied data that + * was copied to bounce buffer to Target(!) address. + */ + ret = ath10k_ce_send(ce_diag, NULL, (u32) ce_data, + nbytes, 0, 0); + if (ret != 0) + goto done; + + i = 0; + while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, + &completed_nbytes, + &id) != 0) { + mdelay(1); + + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + ret = -EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + ret = -EIO; + goto done; + } + + if (buf != ce_data) { + ret = -EIO; + goto done; + } + + i = 0; + while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, + &completed_nbytes, + &id, &flags) != 0) { + mdelay(1); + + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + ret = -EBUSY; + goto done; + } + } + + if (nbytes != completed_nbytes) { + ret = -EIO; + goto done; + } + + if (buf != address) { + ret = -EIO; + goto done; + } + + remaining_bytes -= nbytes; + address += nbytes; + ce_data += nbytes; + } + +done: + if (data_buf) { + pci_free_consistent(ar_pci->pdev, orig_nbytes, data_buf, + ce_data_base); + } + + if (ret != 0) + ath10k_dbg(ATH10K_DBG_PCI, "%s failure (0x%x)\n", __func__, + address); + + return ret; +} + +/* Write 4B data to Target memory or register */ +static int ath10k_pci_diag_write_access(struct ath10k *ar, u32 address, + u32 data) +{ + /* Assume range doesn't cross this boundary */ + if (address >= DRAM_BASE_ADDRESS) + return ath10k_pci_diag_write_mem(ar, address, &data, + sizeof(u32)); + + ath10k_pci_wake(ar); + ath10k_pci_write32(ar, address, data); + ath10k_pci_sleep(ar); + return 0; +} + +static bool ath10k_pci_target_is_awake(struct ath10k *ar) +{ + void __iomem *mem = ath10k_pci_priv(ar)->mem; + u32 val; + val = ioread32(mem + PCIE_LOCAL_BASE_ADDRESS + + RTC_STATE_ADDRESS); + return (RTC_STATE_V_GET(val) == RTC_STATE_V_ON); +} + +static void ath10k_pci_wait(struct ath10k *ar) +{ + int n = 100; + + while (n-- && !ath10k_pci_target_is_awake(ar)) + msleep(10); + + if (n < 0) + ath10k_warn("Unable to wakeup target\n"); +} + +void ath10k_do_pci_wake(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + void __iomem *pci_addr = ar_pci->mem; + int tot_delay = 0; + int curr_delay = 5; + + if (atomic_read(&ar_pci->keep_awake_count) == 0) { + /* Force AWAKE */ + iowrite32(PCIE_SOC_WAKE_V_MASK, + pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + } + atomic_inc(&ar_pci->keep_awake_count); + + if (ar_pci->verified_awake) + return; + + for (;;) { + if (ath10k_pci_target_is_awake(ar)) { + ar_pci->verified_awake = true; + break; + } + + if (tot_delay > PCIE_WAKE_TIMEOUT) { + ath10k_warn("target takes too long to wake up (awake count %d)\n", + atomic_read(&ar_pci->keep_awake_count)); + break; + } + + udelay(curr_delay); + tot_delay += curr_delay; + + if (curr_delay < 50) + curr_delay += 5; + } +} + +void ath10k_do_pci_sleep(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + void __iomem *pci_addr = ar_pci->mem; + + if (atomic_dec_and_test(&ar_pci->keep_awake_count)) { + /* Allow sleep */ + ar_pci->verified_awake = false; + iowrite32(PCIE_SOC_WAKE_RESET, + pci_addr + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + } +} + +/* + * FIXME: Handle OOM properly. + */ +static inline +struct ath10k_pci_compl *get_free_compl(struct hif_ce_pipe_info *pipe_info) +{ + struct ath10k_pci_compl *compl = NULL; + + spin_lock_bh(&pipe_info->pipe_lock); + if (list_empty(&pipe_info->compl_free)) { + ath10k_warn("Completion buffers are full\n"); + goto exit; + } + compl = list_first_entry(&pipe_info->compl_free, + struct ath10k_pci_compl, list); + list_del(&compl->list); +exit: + spin_unlock_bh(&pipe_info->pipe_lock); + return compl; +} + +/* Called by lower (CE) layer when a send to Target completes. */ +static void ath10k_pci_ce_send_done(struct ce_state *ce_state, + void *transfer_context, + u32 ce_data, + unsigned int nbytes, + unsigned int transfer_id) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id]; + struct ath10k_pci_compl *compl; + bool process = false; + + do { + /* + * For the send completion of an item in sendlist, just + * increment num_sends_allowed. The upper layer callback will + * be triggered when last fragment is done with send. + */ + if (transfer_context == CE_SENDLIST_ITEM_CTXT) { + spin_lock_bh(&pipe_info->pipe_lock); + pipe_info->num_sends_allowed++; + spin_unlock_bh(&pipe_info->pipe_lock); + continue; + } + + compl = get_free_compl(pipe_info); + if (!compl) + break; + + compl->send_or_recv = HIF_CE_COMPLETE_SEND; + compl->ce_state = ce_state; + compl->pipe_info = pipe_info; + compl->transfer_context = transfer_context; + compl->nbytes = nbytes; + compl->transfer_id = transfer_id; + compl->flags = 0; + + /* + * Add the completion to the processing queue. + */ + spin_lock_bh(&ar_pci->compl_lock); + list_add_tail(&compl->list, &ar_pci->compl_process); + spin_unlock_bh(&ar_pci->compl_lock); + + process = true; + } while (ath10k_ce_completed_send_next(ce_state, + &transfer_context, + &ce_data, &nbytes, + &transfer_id) == 0); + + /* + * If only some of the items within a sendlist have completed, + * don't invoke completion processing until the entire sendlist + * has been sent. + */ + if (!process) + return; + + ath10k_pci_process_ce(ar); +} + +/* Called by lower (CE) layer when data is received from the Target. */ +static void ath10k_pci_ce_recv_data(struct ce_state *ce_state, + void *transfer_context, u32 ce_data, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id]; + struct ath10k_pci_compl *compl; + struct sk_buff *skb; + + do { + compl = get_free_compl(pipe_info); + if (!compl) + break; + + compl->send_or_recv = HIF_CE_COMPLETE_RECV; + compl->ce_state = ce_state; + compl->pipe_info = pipe_info; + compl->transfer_context = transfer_context; + compl->nbytes = nbytes; + compl->transfer_id = transfer_id; + compl->flags = flags; + + skb = transfer_context; + dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + /* + * Add the completion to the processing queue. + */ + spin_lock_bh(&ar_pci->compl_lock); + list_add_tail(&compl->list, &ar_pci->compl_process); + spin_unlock_bh(&ar_pci->compl_lock); + + } while (ath10k_ce_completed_recv_next(ce_state, + &transfer_context, + &ce_data, &nbytes, + &transfer_id, + &flags) == 0); + + ath10k_pci_process_ce(ar); +} + +/* Send the first nbytes bytes of the buffer */ +static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, + unsigned int transfer_id, + unsigned int bytes, struct sk_buff *nbuf) +{ + struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(nbuf); + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe_id]); + struct ce_state *ce_hdl = pipe_info->ce_hdl; + struct ce_sendlist sendlist; + unsigned int len; + u32 flags = 0; + int ret; + + memset(&sendlist, 0, sizeof(struct ce_sendlist)); + + len = min(bytes, nbuf->len); + bytes -= len; + + if (len & 3) + ath10k_warn("skb not aligned to 4-byte boundary (%d)\n", len); + + ath10k_dbg(ATH10K_DBG_PCI, + "pci send data vaddr %p paddr 0x%llx len %d as %d bytes\n", + nbuf->data, (unsigned long long) skb_cb->paddr, + nbuf->len, len); + ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, + "ath10k tx: data: ", + nbuf->data, nbuf->len); + + ath10k_ce_sendlist_buf_add(&sendlist, skb_cb->paddr, len, flags); + + /* Make sure we have resources to handle this request */ + spin_lock_bh(&pipe_info->pipe_lock); + if (!pipe_info->num_sends_allowed) { + ath10k_warn("Pipe: %d is full\n", pipe_id); + spin_unlock_bh(&pipe_info->pipe_lock); + return -ENOSR; + } + pipe_info->num_sends_allowed--; + spin_unlock_bh(&pipe_info->pipe_lock); + + ret = ath10k_ce_sendlist_send(ce_hdl, nbuf, &sendlist, transfer_id); + if (ret) + ath10k_warn("CE send failed: %p\n", nbuf); + + return ret; +} + +static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe]); + int ret; + + spin_lock_bh(&pipe_info->pipe_lock); + ret = pipe_info->num_sends_allowed; + spin_unlock_bh(&pipe_info->pipe_lock); + + return ret; +} + +static void ath10k_pci_hif_dump_area(struct ath10k *ar) +{ + u32 reg_dump_area = 0; + u32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {}; + u32 host_addr; + int ret; + u32 i; + + ath10k_err("firmware crashed!\n"); + ath10k_err("hardware name %s version 0x%x\n", + ar->hw_params.name, ar->target_version); + ath10k_err("firmware version: %u.%u.%u.%u\n", ar->fw_version_major, + ar->fw_version_minor, ar->fw_version_release, + ar->fw_version_build); + + host_addr = host_interest_item_address(HI_ITEM(hi_failure_state)); + if (ath10k_pci_diag_read_mem(ar, host_addr, + ®_dump_area, sizeof(u32)) != 0) { + ath10k_warn("could not read hi_failure_state\n"); + return; + } + + ath10k_err("target register Dump Location: 0x%08X\n", reg_dump_area); + + ret = ath10k_pci_diag_read_mem(ar, reg_dump_area, + ®_dump_values[0], + REG_DUMP_COUNT_QCA988X * sizeof(u32)); + if (ret != 0) { + ath10k_err("could not dump FW Dump Area\n"); + return; + } + + BUILD_BUG_ON(REG_DUMP_COUNT_QCA988X % 4); + + ath10k_err("target Register Dump\n"); + for (i = 0; i < REG_DUMP_COUNT_QCA988X; i += 4) + ath10k_err("[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X\n", + i, + reg_dump_values[i], + reg_dump_values[i + 1], + reg_dump_values[i + 2], + reg_dump_values[i + 3]); +} + +static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, + int force) +{ + if (!force) { + int resources; + /* + * Decide whether to actually poll for completions, or just + * wait for a later chance. + * If there seem to be plenty of resources left, then just wait + * since checking involves reading a CE register, which is a + * relatively expensive operation. + */ + resources = ath10k_pci_hif_get_free_queue_number(ar, pipe); + + /* + * If at least 50% of the total resources are still available, + * don't bother checking again yet. + */ + if (resources > (host_ce_config_wlan[pipe].src_nentries >> 1)) + return; + } + ath10k_ce_per_engine_service(ar, pipe); +} + +static void ath10k_pci_hif_post_init(struct ath10k *ar, + struct ath10k_hif_cb *callbacks) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + memcpy(&ar_pci->msg_callbacks_current, callbacks, + sizeof(ar_pci->msg_callbacks_current)); +} + +static int ath10k_pci_start_ce(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_state *ce_diag = ar_pci->ce_diag; + const struct ce_attr *attr; + struct hif_ce_pipe_info *pipe_info; + struct ath10k_pci_compl *compl; + int i, pipe_num, completions, disable_interrupts; + + spin_lock_init(&ar_pci->compl_lock); + INIT_LIST_HEAD(&ar_pci->compl_process); + + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + + spin_lock_init(&pipe_info->pipe_lock); + INIT_LIST_HEAD(&pipe_info->compl_free); + + /* Handle Diagnostic CE specially */ + if (pipe_info->ce_hdl == ce_diag) + continue; + + attr = &host_ce_config_wlan[pipe_num]; + completions = 0; + + if (attr->src_nentries) { + disable_interrupts = attr->flags & CE_ATTR_DIS_INTR; + ath10k_ce_send_cb_register(pipe_info->ce_hdl, + ath10k_pci_ce_send_done, + disable_interrupts); + completions += attr->src_nentries; + pipe_info->num_sends_allowed = attr->src_nentries - 1; + } + + if (attr->dest_nentries) { + ath10k_ce_recv_cb_register(pipe_info->ce_hdl, + ath10k_pci_ce_recv_data); + completions += attr->dest_nentries; + } + + if (completions == 0) + continue; + + for (i = 0; i < completions; i++) { + compl = kmalloc(sizeof(struct ath10k_pci_compl), + GFP_KERNEL); + if (!compl) { + ath10k_warn("No memory for completion state\n"); + ath10k_pci_stop_ce(ar); + return -ENOMEM; + } + + compl->send_or_recv = HIF_CE_COMPLETE_FREE; + list_add_tail(&compl->list, &pipe_info->compl_free); + } + } + + return 0; +} + +static void ath10k_pci_stop_ce(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_compl *compl; + struct sk_buff *skb; + int i; + + ath10k_ce_disable_interrupts(ar); + + /* Cancel the pending tasklet */ + tasklet_kill(&ar_pci->intr_tq); + + for (i = 0; i < CE_COUNT; i++) + tasklet_kill(&ar_pci->pipe_info[i].intr); + + /* Mark pending completions as aborted, so that upper layers free up + * their associated resources */ + spin_lock_bh(&ar_pci->compl_lock); + list_for_each_entry(compl, &ar_pci->compl_process, list) { + skb = (struct sk_buff *)compl->transfer_context; + ATH10K_SKB_CB(skb)->is_aborted = true; + } + spin_unlock_bh(&ar_pci->compl_lock); +} + +static void ath10k_pci_cleanup_ce(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci_compl *compl, *tmp; + struct hif_ce_pipe_info *pipe_info; + struct sk_buff *netbuf; + int pipe_num; + + /* Free pending completions. */ + spin_lock_bh(&ar_pci->compl_lock); + if (!list_empty(&ar_pci->compl_process)) + ath10k_warn("pending completions still present! possible memory leaks.\n"); + + list_for_each_entry_safe(compl, tmp, &ar_pci->compl_process, list) { + list_del(&compl->list); + netbuf = (struct sk_buff *)compl->transfer_context; + dev_kfree_skb_any(netbuf); + kfree(compl); + } + spin_unlock_bh(&ar_pci->compl_lock); + + /* Free unused completions for each pipe. */ + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + + spin_lock_bh(&pipe_info->pipe_lock); + list_for_each_entry_safe(compl, tmp, + &pipe_info->compl_free, list) { + list_del(&compl->list); + kfree(compl); + } + spin_unlock_bh(&pipe_info->pipe_lock); + } +} + +static void ath10k_pci_process_ce(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ar->hif.priv; + struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; + struct ath10k_pci_compl *compl; + struct sk_buff *skb; + unsigned int nbytes; + int ret, send_done = 0; + + /* Upper layers aren't ready to handle tx/rx completions in parallel so + * we must serialize all completion processing. */ + + spin_lock_bh(&ar_pci->compl_lock); + if (ar_pci->compl_processing) { + spin_unlock_bh(&ar_pci->compl_lock); + return; + } + ar_pci->compl_processing = true; + spin_unlock_bh(&ar_pci->compl_lock); + + for (;;) { + spin_lock_bh(&ar_pci->compl_lock); + if (list_empty(&ar_pci->compl_process)) { + spin_unlock_bh(&ar_pci->compl_lock); + break; + } + compl = list_first_entry(&ar_pci->compl_process, + struct ath10k_pci_compl, list); + list_del(&compl->list); + spin_unlock_bh(&ar_pci->compl_lock); + + if (compl->send_or_recv == HIF_CE_COMPLETE_SEND) { + cb->tx_completion(ar, + compl->transfer_context, + compl->transfer_id); + send_done = 1; + } else { + ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1); + if (ret) { + ath10k_warn("Unable to post recv buffer for pipe: %d\n", + compl->pipe_info->pipe_num); + break; + } + + skb = (struct sk_buff *)compl->transfer_context; + nbytes = compl->nbytes; + + ath10k_dbg(ATH10K_DBG_PCI, + "ath10k_pci_ce_recv_data netbuf=%p nbytes=%d\n", + skb, nbytes); + ath10k_dbg_dump(ATH10K_DBG_PCI_DUMP, NULL, + "ath10k rx: ", skb->data, nbytes); + + if (skb->len + skb_tailroom(skb) >= nbytes) { + skb_trim(skb, 0); + skb_put(skb, nbytes); + cb->rx_completion(ar, skb, + compl->pipe_info->pipe_num); + } else { + ath10k_warn("rxed more than expected (nbytes %d, max %d)", + nbytes, + skb->len + skb_tailroom(skb)); + } + } + + compl->send_or_recv = HIF_CE_COMPLETE_FREE; + + /* + * Add completion back to the pipe's free list. + */ + spin_lock_bh(&compl->pipe_info->pipe_lock); + list_add_tail(&compl->list, &compl->pipe_info->compl_free); + compl->pipe_info->num_sends_allowed += send_done; + spin_unlock_bh(&compl->pipe_info->pipe_lock); + } + + spin_lock_bh(&ar_pci->compl_lock); + ar_pci->compl_processing = false; + spin_unlock_bh(&ar_pci->compl_lock); +} + +/* TODO - temporary mapping while we have too few CE's */ +static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, + u16 service_id, u8 *ul_pipe, + u8 *dl_pipe, int *ul_is_polled, + int *dl_is_polled) +{ + int ret = 0; + + /* polling for received messages not supported */ + *dl_is_polled = 0; + + switch (service_id) { + case ATH10K_HTC_SVC_ID_HTT_DATA_MSG: + /* + * Host->target HTT gets its own pipe, so it can be polled + * while other pipes are interrupt driven. + */ + *ul_pipe = 4; + /* + * Use the same target->host pipe for HTC ctrl, HTC raw + * streams, and HTT. + */ + *dl_pipe = 1; + break; + + case ATH10K_HTC_SVC_ID_RSVD_CTRL: + case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS: + /* + * Note: HTC_RAW_STREAMS_SVC is currently unused, and + * HTC_CTRL_RSVD_SVC could share the same pipe as the + * WMI services. So, if another CE is needed, change + * this to *ul_pipe = 3, which frees up CE 0. + */ + /* *ul_pipe = 3; */ + *ul_pipe = 0; + *dl_pipe = 1; + break; + + case ATH10K_HTC_SVC_ID_WMI_DATA_BK: + case ATH10K_HTC_SVC_ID_WMI_DATA_BE: + case ATH10K_HTC_SVC_ID_WMI_DATA_VI: + case ATH10K_HTC_SVC_ID_WMI_DATA_VO: + + case ATH10K_HTC_SVC_ID_WMI_CONTROL: + *ul_pipe = 3; + *dl_pipe = 2; + break; + + /* pipe 5 unused */ + /* pipe 6 reserved */ + /* pipe 7 reserved */ + + default: + ret = -1; + break; + } + *ul_is_polled = + (host_ce_config_wlan[*ul_pipe].flags & CE_ATTR_DIS_INTR) != 0; + + return ret; +} + +static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, + u8 *ul_pipe, u8 *dl_pipe) +{ + int ul_is_polled, dl_is_polled; + + (void)ath10k_pci_hif_map_service_to_pipe(ar, + ATH10K_HTC_SVC_ID_RSVD_CTRL, + ul_pipe, + dl_pipe, + &ul_is_polled, + &dl_is_polled); +} + +static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info, + int num) +{ + struct ath10k *ar = pipe_info->hif_ce_state; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_state *ce_state = pipe_info->ce_hdl; + struct sk_buff *skb; + dma_addr_t ce_data; + int i, ret = 0; + + if (pipe_info->buf_sz == 0) + return 0; + + for (i = 0; i < num; i++) { + skb = dev_alloc_skb(pipe_info->buf_sz); + if (!skb) { + ath10k_warn("could not allocate skbuff for pipe %d\n", + num); + ret = -ENOMEM; + goto err; + } + + WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb"); + + ce_data = dma_map_single(ar->dev, skb->data, + skb->len + skb_tailroom(skb), + DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(ar->dev, ce_data))) { + ath10k_warn("could not dma map skbuff\n"); + dev_kfree_skb_any(skb); + ret = -EIO; + goto err; + } + + ATH10K_SKB_CB(skb)->paddr = ce_data; + + pci_dma_sync_single_for_device(ar_pci->pdev, ce_data, + pipe_info->buf_sz, + PCI_DMA_FROMDEVICE); + + ret = ath10k_ce_recv_buf_enqueue(ce_state, (void *)skb, + ce_data); + if (ret) { + ath10k_warn("could not enqueue to pipe %d (%d)\n", + num, ret); + goto err; + } + } + + return ret; + +err: + ath10k_pci_rx_pipe_cleanup(pipe_info); + return ret; +} + +static int ath10k_pci_post_rx(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info; + const struct ce_attr *attr; + int pipe_num, ret = 0; + + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + attr = &host_ce_config_wlan[pipe_num]; + + if (attr->dest_nentries == 0) + continue; + + ret = ath10k_pci_post_rx_pipe(pipe_info, + attr->dest_nentries - 1); + if (ret) { + ath10k_warn("Unable to replenish recv buffers for pipe: %d\n", + pipe_num); + + for (; pipe_num >= 0; pipe_num--) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + ath10k_pci_rx_pipe_cleanup(pipe_info); + } + return ret; + } + } + + return 0; +} + +static int ath10k_pci_hif_start(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + ret = ath10k_pci_start_ce(ar); + if (ret) { + ath10k_warn("could not start CE (%d)\n", ret); + return ret; + } + + /* Post buffers once to start things off. */ + ret = ath10k_pci_post_rx(ar); + if (ret) { + ath10k_warn("could not post rx pipes (%d)\n", ret); + return ret; + } + + ar_pci->started = 1; + return 0; +} + +static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) +{ + struct ath10k *ar; + struct ath10k_pci *ar_pci; + struct ce_state *ce_hdl; + u32 buf_sz; + struct sk_buff *netbuf; + u32 ce_data; + + buf_sz = pipe_info->buf_sz; + + /* Unused Copy Engine */ + if (buf_sz == 0) + return; + + ar = pipe_info->hif_ce_state; + ar_pci = ath10k_pci_priv(ar); + + if (!ar_pci->started) + return; + + ce_hdl = pipe_info->ce_hdl; + + while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf, + &ce_data) == 0) { + dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr, + netbuf->len + skb_tailroom(netbuf), + DMA_FROM_DEVICE); + dev_kfree_skb_any(netbuf); + } +} + +static void ath10k_pci_tx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info) +{ + struct ath10k *ar; + struct ath10k_pci *ar_pci; + struct ce_state *ce_hdl; + struct sk_buff *netbuf; + u32 ce_data; + unsigned int nbytes; + unsigned int id; + u32 buf_sz; + + buf_sz = pipe_info->buf_sz; + + /* Unused Copy Engine */ + if (buf_sz == 0) + return; + + ar = pipe_info->hif_ce_state; + ar_pci = ath10k_pci_priv(ar); + + if (!ar_pci->started) + return; + + ce_hdl = pipe_info->ce_hdl; + + while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, + &ce_data, &nbytes, &id) == 0) { + if (netbuf != CE_SENDLIST_ITEM_CTXT) + /* + * Indicate the completion to higer layer to free + * the buffer + */ + ATH10K_SKB_CB(netbuf)->is_aborted = true; + ar_pci->msg_callbacks_current.tx_completion(ar, + netbuf, + id); + } +} + +/* + * Cleanup residual buffers for device shutdown: + * buffers that were enqueued for receive + * buffers that were to be sent + * Note: Buffers that had completed but which were + * not yet processed are on a completion queue. They + * are handled when the completion thread shuts down. + */ +static void ath10k_pci_buffer_cleanup(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int pipe_num; + + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + struct hif_ce_pipe_info *pipe_info; + + pipe_info = &ar_pci->pipe_info[pipe_num]; + ath10k_pci_rx_pipe_cleanup(pipe_info); + ath10k_pci_tx_pipe_cleanup(pipe_info); + } +} + +static void ath10k_pci_ce_deinit(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info; + int pipe_num; + + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + if (pipe_info->ce_hdl) { + ath10k_ce_deinit(pipe_info->ce_hdl); + pipe_info->ce_hdl = NULL; + pipe_info->buf_sz = 0; + } + } +} + +static void ath10k_pci_hif_stop(struct ath10k *ar) +{ + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + ath10k_pci_stop_ce(ar); + + /* At this point, asynchronous threads are stopped, the target should + * not DMA nor interrupt. We process the leftovers and then free + * everything else up. */ + + ath10k_pci_process_ce(ar); + ath10k_pci_cleanup_ce(ar); + ath10k_pci_buffer_cleanup(ar); + ath10k_pci_ce_deinit(ar); +} + +static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, + void *req, u32 req_len, + void *resp, u32 *resp_len) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ce_state *ce_tx = ar_pci->pipe_info[BMI_CE_NUM_TO_TARG].ce_hdl; + struct ce_state *ce_rx = ar_pci->pipe_info[BMI_CE_NUM_TO_HOST].ce_hdl; + dma_addr_t req_paddr = 0; + dma_addr_t resp_paddr = 0; + struct bmi_xfer xfer = {}; + void *treq, *tresp = NULL; + int ret = 0; + + if (resp && !resp_len) + return -EINVAL; + + if (resp && resp_len && *resp_len == 0) + return -EINVAL; + + treq = kmemdup(req, req_len, GFP_KERNEL); + if (!treq) + return -ENOMEM; + + req_paddr = dma_map_single(ar->dev, treq, req_len, DMA_TO_DEVICE); + ret = dma_mapping_error(ar->dev, req_paddr); + if (ret) + goto err_dma; + + if (resp && resp_len) { + tresp = kzalloc(*resp_len, GFP_KERNEL); + if (!tresp) { + ret = -ENOMEM; + goto err_req; + } + + resp_paddr = dma_map_single(ar->dev, tresp, *resp_len, + DMA_FROM_DEVICE); + ret = dma_mapping_error(ar->dev, resp_paddr); + if (ret) + goto err_req; + + xfer.wait_for_resp = true; + xfer.resp_len = 0; + + ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); + } + + init_completion(&xfer.done); + + ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); + if (ret) + goto err_resp; + + ret = wait_for_completion_timeout(&xfer.done, + BMI_COMMUNICATION_TIMEOUT_HZ); + if (ret <= 0) { + u32 unused_buffer; + unsigned int unused_nbytes; + unsigned int unused_id; + + ret = -ETIMEDOUT; + ath10k_ce_cancel_send_next(ce_tx, NULL, &unused_buffer, + &unused_nbytes, &unused_id); + } else { + /* non-zero means we did not time out */ + ret = 0; + } + +err_resp: + if (resp) { + u32 unused_buffer; + + ath10k_ce_revoke_recv_next(ce_rx, NULL, &unused_buffer); + dma_unmap_single(ar->dev, resp_paddr, + *resp_len, DMA_FROM_DEVICE); + } +err_req: + dma_unmap_single(ar->dev, req_paddr, req_len, DMA_TO_DEVICE); + + if (ret == 0 && resp_len) { + *resp_len = min(*resp_len, xfer.resp_len); + memcpy(resp, tresp, xfer.resp_len); + } +err_dma: + kfree(treq); + kfree(tresp); + + return ret; +} + +static void ath10k_pci_bmi_send_done(struct ce_state *ce_state, + void *transfer_context, + u32 data, + unsigned int nbytes, + unsigned int transfer_id) +{ + struct bmi_xfer *xfer = transfer_context; + + if (xfer->wait_for_resp) + return; + + complete(&xfer->done); +} + +static void ath10k_pci_bmi_recv_data(struct ce_state *ce_state, + void *transfer_context, + u32 data, + unsigned int nbytes, + unsigned int transfer_id, + unsigned int flags) +{ + struct bmi_xfer *xfer = transfer_context; + + if (!xfer->wait_for_resp) { + ath10k_warn("unexpected: BMI data received; ignoring\n"); + return; + } + + xfer->resp_len = nbytes; + complete(&xfer->done); +} + +/* + * Map from service/endpoint to Copy Engine. + * This table is derived from the CE_PCI TABLE, above. + * It is passed to the Target at startup for use by firmware. + */ +static const struct service_to_pipe target_service_to_ce_map_wlan[] = { + { + ATH10K_HTC_SVC_ID_WMI_DATA_VO, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_VO, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_BK, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_BK, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_BE, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_BE, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_VI, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + ATH10K_HTC_SVC_ID_WMI_DATA_VI, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + ATH10K_HTC_SVC_ID_WMI_CONTROL, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + ATH10K_HTC_SVC_ID_WMI_CONTROL, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + ATH10K_HTC_SVC_ID_RSVD_CTRL, + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, /* could be moved to 3 (share with WMI) */ + }, + { + ATH10K_HTC_SVC_ID_RSVD_CTRL, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS, /* not currently used */ + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, + }, + { + ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS, /* not currently used */ + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + ATH10K_HTC_SVC_ID_HTT_DATA_MSG, + PIPEDIR_OUT, /* out = UL = host -> target */ + 4, + }, + { + ATH10K_HTC_SVC_ID_HTT_DATA_MSG, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + + /* (Additions here) */ + + { /* Must be last */ + 0, + 0, + 0, + }, +}; + +/* + * Send an interrupt to the device to wake up the Target CPU + * so it has an opportunity to notice any changed state. + */ +static int ath10k_pci_wake_target_cpu(struct ath10k *ar) +{ + int ret; + u32 core_ctrl; + + ret = ath10k_pci_diag_read_access(ar, SOC_CORE_BASE_ADDRESS | + CORE_CTRL_ADDRESS, + &core_ctrl); + if (ret) { + ath10k_warn("Unable to read core ctrl\n"); + return ret; + } + + /* A_INUM_FIRMWARE interrupt to Target CPU */ + core_ctrl |= CORE_CTRL_CPU_INTR_MASK; + + ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS | + CORE_CTRL_ADDRESS, + core_ctrl); + if (ret) + ath10k_warn("Unable to set interrupt mask\n"); + + return ret; +} + +static int ath10k_pci_init_config(struct ath10k *ar) +{ + u32 interconnect_targ_addr; + u32 pcie_state_targ_addr = 0; + u32 pipe_cfg_targ_addr = 0; + u32 svc_to_pipe_map = 0; + u32 pcie_config_flags = 0; + u32 ealloc_value; + u32 ealloc_targ_addr; + u32 flag2_value; + u32 flag2_targ_addr; + int ret = 0; + + /* Download to Target the CE Config and the service-to-CE map */ + interconnect_targ_addr = + host_interest_item_address(HI_ITEM(hi_interconnect_state)); + + /* Supply Target-side CE configuration */ + ret = ath10k_pci_diag_read_access(ar, interconnect_targ_addr, + &pcie_state_targ_addr); + if (ret != 0) { + ath10k_err("Failed to get pcie state addr: %d\n", ret); + return ret; + } + + if (pcie_state_targ_addr == 0) { + ret = -EIO; + ath10k_err("Invalid pcie state addr\n"); + return ret; + } + + ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + + offsetof(struct pcie_state, + pipe_cfg_addr), + &pipe_cfg_targ_addr); + if (ret != 0) { + ath10k_err("Failed to get pipe cfg addr: %d\n", ret); + return ret; + } + + if (pipe_cfg_targ_addr == 0) { + ret = -EIO; + ath10k_err("Invalid pipe cfg addr\n"); + return ret; + } + + ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr, + target_ce_config_wlan, + sizeof(target_ce_config_wlan)); + + if (ret != 0) { + ath10k_err("Failed to write pipe cfg: %d\n", ret); + return ret; + } + + ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + + offsetof(struct pcie_state, + svc_to_pipe_map), + &svc_to_pipe_map); + if (ret != 0) { + ath10k_err("Failed to get svc/pipe map: %d\n", ret); + return ret; + } + + if (svc_to_pipe_map == 0) { + ret = -EIO; + ath10k_err("Invalid svc_to_pipe map\n"); + return ret; + } + + ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map, + target_service_to_ce_map_wlan, + sizeof(target_service_to_ce_map_wlan)); + if (ret != 0) { + ath10k_err("Failed to write svc/pipe map: %d\n", ret); + return ret; + } + + ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + + offsetof(struct pcie_state, + config_flags), + &pcie_config_flags); + if (ret != 0) { + ath10k_err("Failed to get pcie config_flags: %d\n", ret); + return ret; + } + + pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1; + + ret = ath10k_pci_diag_write_mem(ar, pcie_state_targ_addr + + offsetof(struct pcie_state, config_flags), + &pcie_config_flags, + sizeof(pcie_config_flags)); + if (ret != 0) { + ath10k_err("Failed to write pcie config_flags: %d\n", ret); + return ret; + } + + /* configure early allocation */ + ealloc_targ_addr = host_interest_item_address(HI_ITEM(hi_early_alloc)); + + ret = ath10k_pci_diag_read_access(ar, ealloc_targ_addr, &ealloc_value); + if (ret != 0) { + ath10k_err("Faile to get early alloc val: %d\n", ret); + return ret; + } + + /* first bank is switched to IRAM */ + ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & + HI_EARLY_ALLOC_MAGIC_MASK); + ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & + HI_EARLY_ALLOC_IRAM_BANKS_MASK); + + ret = ath10k_pci_diag_write_access(ar, ealloc_targ_addr, ealloc_value); + if (ret != 0) { + ath10k_err("Failed to set early alloc val: %d\n", ret); + return ret; + } + + /* Tell Target to proceed with initialization */ + flag2_targ_addr = host_interest_item_address(HI_ITEM(hi_option_flag2)); + + ret = ath10k_pci_diag_read_access(ar, flag2_targ_addr, &flag2_value); + if (ret != 0) { + ath10k_err("Failed to get option val: %d\n", ret); + return ret; + } + + flag2_value |= HI_OPTION_EARLY_CFG_DONE; + + ret = ath10k_pci_diag_write_access(ar, flag2_targ_addr, flag2_value); + if (ret != 0) { + ath10k_err("Failed to set option val: %d\n", ret); + return ret; + } + + return 0; +} + + + +static int ath10k_pci_ce_init(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct hif_ce_pipe_info *pipe_info; + const struct ce_attr *attr; + int pipe_num; + + for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) { + pipe_info = &ar_pci->pipe_info[pipe_num]; + pipe_info->pipe_num = pipe_num; + pipe_info->hif_ce_state = ar; + attr = &host_ce_config_wlan[pipe_num]; + + pipe_info->ce_hdl = ath10k_ce_init(ar, pipe_num, attr); + if (pipe_info->ce_hdl == NULL) { + ath10k_err("Unable to initialize CE for pipe: %d\n", + pipe_num); + + /* It is safe to call it here. It checks if ce_hdl is + * valid for each pipe */ + ath10k_pci_ce_deinit(ar); + return -1; + } + + if (pipe_num == ar_pci->ce_count - 1) { + /* + * Reserve the ultimate CE for + * diagnostic Window support + */ + ar_pci->ce_diag = + ar_pci->pipe_info[ar_pci->ce_count - 1].ce_hdl; + continue; + } + + pipe_info->buf_sz = (size_t) (attr->src_sz_max); + } + + /* + * Initially, establish CE completion handlers for use with BMI. + * These are overwritten with generic handlers after we exit BMI phase. + */ + pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; + ath10k_ce_send_cb_register(pipe_info->ce_hdl, + ath10k_pci_bmi_send_done, 0); + + pipe_info = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST]; + ath10k_ce_recv_cb_register(pipe_info->ce_hdl, + ath10k_pci_bmi_recv_data); + + return 0; +} + +static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + u32 fw_indicator_address, fw_indicator; + + ath10k_pci_wake(ar); + + fw_indicator_address = ar_pci->fw_indicator_address; + fw_indicator = ath10k_pci_read32(ar, fw_indicator_address); + + if (fw_indicator & FW_IND_EVENT_PENDING) { + /* ACK: clear Target-side pending event */ + ath10k_pci_write32(ar, fw_indicator_address, + fw_indicator & ~FW_IND_EVENT_PENDING); + + if (ar_pci->started) { + ath10k_pci_hif_dump_area(ar); + } else { + /* + * Probable Target failure before we're prepared + * to handle it. Generally unexpected. + */ + ath10k_warn("early firmware event indicated\n"); + } + } + + ath10k_pci_sleep(ar); +} + +static const struct ath10k_hif_ops ath10k_pci_hif_ops = { + .send_head = ath10k_pci_hif_send_head, + .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, + .start = ath10k_pci_hif_start, + .stop = ath10k_pci_hif_stop, + .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, + .get_default_pipe = ath10k_pci_hif_get_default_pipe, + .send_complete_check = ath10k_pci_hif_send_complete_check, + .init = ath10k_pci_hif_post_init, + .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, +}; + +static void ath10k_pci_ce_tasklet(unsigned long ptr) +{ + struct hif_ce_pipe_info *pipe = (struct hif_ce_pipe_info *)ptr; + struct ath10k_pci *ar_pci = pipe->ar_pci; + + ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num); +} + +static void ath10k_msi_err_tasklet(unsigned long data) +{ + struct ath10k *ar = (struct ath10k *)data; + + ath10k_pci_fw_interrupt_handler(ar); +} + +/* + * Handler for a per-engine interrupt on a PARTICULAR CE. + * This is used in cases where each CE has a private MSI interrupt. + */ +static irqreturn_t ath10k_pci_per_engine_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL; + + if (ce_id < 0 || ce_id > ARRAY_SIZE(ar_pci->pipe_info)) { + ath10k_warn("unexpected/invalid irq %d ce_id %d\n", irq, ce_id); + return IRQ_HANDLED; + } + + /* + * NOTE: We are able to derive ce_id from irq because we + * use a one-to-one mapping for CE's 0..5. + * CE's 6 & 7 do not use interrupts at all. + * + * This mapping must be kept in sync with the mapping + * used by firmware. + */ + tasklet_schedule(&ar_pci->pipe_info[ce_id].intr); + return IRQ_HANDLED; +} + +static irqreturn_t ath10k_pci_msi_fw_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + tasklet_schedule(&ar_pci->msi_fw_err); + return IRQ_HANDLED; +} + +/* + * Top-level interrupt handler for all PCI interrupts from a Target. + * When a block of MSI interrupts is allocated, this top-level handler + * is not used; instead, we directly call the correct sub-handler. + */ +static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (ar_pci->num_msi_intrs == 0) { + /* + * IMPORTANT: INTR_CLR regiser has to be set after + * INTR_ENABLE is set to 0, otherwise interrupt can not be + * really cleared. + */ + iowrite32(0, ar_pci->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + iowrite32(PCIE_INTR_FIRMWARE_MASK | + PCIE_INTR_CE_MASK_ALL, + ar_pci->mem + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_CLR_ADDRESS)); + /* + * IMPORTANT: this extra read transaction is required to + * flush the posted write buffer. + */ + (void) ioread32(ar_pci->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + } + + tasklet_schedule(&ar_pci->intr_tq); + + return IRQ_HANDLED; +} + +static void ath10k_pci_tasklet(unsigned long data) +{ + struct ath10k *ar = (struct ath10k *)data; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + ath10k_pci_fw_interrupt_handler(ar); /* FIXME: Handle FW error */ + ath10k_ce_per_engine_service_any(ar); + + if (ar_pci->num_msi_intrs == 0) { + /* Enable Legacy PCI line interrupts */ + iowrite32(PCIE_INTR_FIRMWARE_MASK | + PCIE_INTR_CE_MASK_ALL, + ar_pci->mem + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + /* + * IMPORTANT: this extra read transaction is required to + * flush the posted write buffer + */ + (void) ioread32(ar_pci->mem + + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + } +} + +static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + int i; + + ret = pci_enable_msi_block(ar_pci->pdev, num); + if (ret) + return ret; + + ret = request_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, + ath10k_pci_msi_fw_handler, + IRQF_SHARED, "ath10k_pci", ar); + if (ret) + return ret; + + for (i = MSI_ASSIGN_CE_INITIAL; i <= MSI_ASSIGN_CE_MAX; i++) { + ret = request_irq(ar_pci->pdev->irq + i, + ath10k_pci_per_engine_handler, + IRQF_SHARED, "ath10k_pci", ar); + if (ret) { + ath10k_warn("request_irq(%d) failed %d\n", + ar_pci->pdev->irq + i, ret); + + for (; i >= MSI_ASSIGN_CE_INITIAL; i--) + free_irq(ar_pci->pdev->irq, ar); + + pci_disable_msi(ar_pci->pdev); + return ret; + } + } + + ath10k_info("MSI-X interrupt handling (%d intrs)\n", num); + return 0; +} + +static int ath10k_pci_start_intr_msi(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + ret = pci_enable_msi(ar_pci->pdev); + if (ret < 0) + return ret; + + ret = request_irq(ar_pci->pdev->irq, + ath10k_pci_interrupt_handler, + IRQF_SHARED, "ath10k_pci", ar); + if (ret < 0) { + pci_disable_msi(ar_pci->pdev); + return ret; + } + + ath10k_info("MSI interrupt handling\n"); + return 0; +} + +static int ath10k_pci_start_intr_legacy(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + ret = request_irq(ar_pci->pdev->irq, + ath10k_pci_interrupt_handler, + IRQF_SHARED, "ath10k_pci", ar); + if (ret < 0) + return ret; + + /* + * Make sure to wake the Target before enabling Legacy + * Interrupt. + */ + iowrite32(PCIE_SOC_WAKE_V_MASK, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + ath10k_pci_wait(ar); + + /* + * A potential race occurs here: The CORE_BASE write + * depends on target correctly decoding AXI address but + * host won't know when target writes BAR to CORE_CTRL. + * This write might get lost if target has NOT written BAR. + * For now, fix the race by repeating the write in below + * synchronization checking. + */ + iowrite32(PCIE_INTR_FIRMWARE_MASK | + PCIE_INTR_CE_MASK_ALL, + ar_pci->mem + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + iowrite32(PCIE_SOC_WAKE_RESET, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + ath10k_info("legacy interrupt handling\n"); + return 0; +} + +static int ath10k_pci_start_intr(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int num = MSI_NUM_REQUEST; + int ret; + int i; + + tasklet_init(&ar_pci->intr_tq, ath10k_pci_tasklet, (unsigned long) ar); + tasklet_init(&ar_pci->msi_fw_err, ath10k_msi_err_tasklet, + (unsigned long) ar); + + for (i = 0; i < CE_COUNT; i++) { + ar_pci->pipe_info[i].ar_pci = ar_pci; + tasklet_init(&ar_pci->pipe_info[i].intr, + ath10k_pci_ce_tasklet, + (unsigned long)&ar_pci->pipe_info[i]); + } + + if (!test_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features)) + num = 1; + + if (num > 1) { + ret = ath10k_pci_start_intr_msix(ar, num); + if (ret == 0) + goto exit; + + ath10k_warn("MSI-X didn't succeed (%d), trying MSI\n", ret); + num = 1; + } + + if (num == 1) { + ret = ath10k_pci_start_intr_msi(ar); + if (ret == 0) + goto exit; + + ath10k_warn("MSI didn't succeed (%d), trying legacy INTR\n", + ret); + num = 0; + } + + ret = ath10k_pci_start_intr_legacy(ar); + +exit: + ar_pci->num_msi_intrs = num; + ar_pci->ce_count = CE_COUNT; + return ret; +} + +static void ath10k_pci_stop_intr(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int i; + + /* There's at least one interrupt irregardless whether its legacy INTR + * or MSI or MSI-X */ + for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) + free_irq(ar_pci->pdev->irq + i, ar); + + if (ar_pci->num_msi_intrs > 0) + pci_disable_msi(ar_pci->pdev); +} + +static int ath10k_pci_reset_target(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int wait_limit = 300; /* 3 sec */ + + /* Wait for Target to finish initialization before we proceed. */ + iowrite32(PCIE_SOC_WAKE_V_MASK, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + ath10k_pci_wait(ar); + + while (wait_limit-- && + !(ioread32(ar_pci->mem + FW_INDICATOR_ADDRESS) & + FW_IND_INITIALIZED)) { + if (ar_pci->num_msi_intrs == 0) + /* Fix potential race by repeating CORE_BASE writes */ + iowrite32(PCIE_INTR_FIRMWARE_MASK | + PCIE_INTR_CE_MASK_ALL, + ar_pci->mem + (SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); + mdelay(10); + } + + if (wait_limit < 0) { + ath10k_err("Target stalled\n"); + iowrite32(PCIE_SOC_WAKE_RESET, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + return -EIO; + } + + iowrite32(PCIE_SOC_WAKE_RESET, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + return 0; +} + +static void ath10k_pci_device_reset(struct ath10k_pci *ar_pci) +{ + struct ath10k *ar = ar_pci->ar; + void __iomem *mem = ar_pci->mem; + int i; + u32 val; + + if (!SOC_GLOBAL_RESET_ADDRESS) + return; + + if (!mem) + return; + + ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS, + PCIE_SOC_WAKE_V_MASK); + for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (ath10k_pci_target_is_awake(ar)) + break; + msleep(1); + } + + /* Put Target, including PCIe, into RESET. */ + val = ath10k_pci_reg_read32(mem, SOC_GLOBAL_RESET_ADDRESS); + val |= 1; + ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val); + + for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) & + RTC_STATE_COLD_RESET_MASK) + break; + msleep(1); + } + + /* Pull Target, including PCIe, out of RESET. */ + val &= ~1; + ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val); + + for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { + if (!(ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) & + RTC_STATE_COLD_RESET_MASK)) + break; + msleep(1); + } + + ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); +} + +static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci) +{ + int i; + + for (i = 0; i < ATH10K_PCI_FEATURE_COUNT; i++) { + if (!test_bit(i, ar_pci->features)) + continue; + + switch (i) { + case ATH10K_PCI_FEATURE_MSI_X: + ath10k_dbg(ATH10K_DBG_PCI, "device supports MSI-X\n"); + break; + case ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND: + ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n"); + break; + } + } +} + +static int ath10k_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_dev) +{ + void __iomem *mem; + int ret = 0; + struct ath10k *ar; + struct ath10k_pci *ar_pci; + u32 lcr_val; + + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + ar_pci = kzalloc(sizeof(*ar_pci), GFP_KERNEL); + if (ar_pci == NULL) + return -ENOMEM; + + ar_pci->pdev = pdev; + ar_pci->dev = &pdev->dev; + + switch (pci_dev->device) { + case QCA988X_1_0_DEVICE_ID: + set_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features); + break; + case QCA988X_2_0_DEVICE_ID: + set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features); + break; + default: + ret = -ENODEV; + ath10k_err("Unkown device ID: %d\n", pci_dev->device); + goto err_ar_pci; + } + + ath10k_pci_dump_features(ar_pci); + + ar = ath10k_core_create(ar_pci, ar_pci->dev, ATH10K_BUS_PCI, + &ath10k_pci_hif_ops); + if (!ar) { + ath10k_err("ath10k_core_create failed!\n"); + ret = -EINVAL; + goto err_ar_pci; + } + + /* Enable QCA988X_1.0 HW workarounds */ + if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) + spin_lock_init(&ar_pci->hw_v1_workaround_lock); + + ar_pci->ar = ar; + ar_pci->fw_indicator_address = FW_INDICATOR_ADDRESS; + atomic_set(&ar_pci->keep_awake_count, 0); + + pci_set_drvdata(pdev, ar); + + /* + * Without any knowledge of the Host, the Target may have been reset or + * power cycled and its Config Space may no longer reflect the PCI + * address space that was assigned earlier by the PCI infrastructure. + * Refresh it now. + */ + ret = pci_assign_resource(pdev, BAR_NUM); + if (ret) { + ath10k_err("cannot assign PCI space: %d\n", ret); + goto err_ar; + } + + ret = pci_enable_device(pdev); + if (ret) { + ath10k_err("cannot enable PCI device: %d\n", ret); + goto err_ar; + } + + /* Request MMIO resources */ + ret = pci_request_region(pdev, BAR_NUM, "ath"); + if (ret) { + ath10k_err("PCI MMIO reservation error: %d\n", ret); + goto err_device; + } + + /* + * Target structures have a limit of 32 bit DMA pointers. + * DMA pointers can be wider than 32 bits by default on some systems. + */ + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err("32-bit DMA not available: %d\n", ret); + goto err_region; + } + + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err("cannot enable 32-bit consistent DMA\n"); + goto err_region; + } + + /* Set bus master bit in PCI_COMMAND to enable DMA */ + pci_set_master(pdev); + + /* + * Temporary FIX: disable ASPM + * Will be removed after the OTP is programmed + */ + pci_read_config_dword(pdev, 0x80, &lcr_val); + pci_write_config_dword(pdev, 0x80, (lcr_val & 0xffffff00)); + + /* Arrange for access to Target SoC registers. */ + mem = pci_iomap(pdev, BAR_NUM, 0); + if (!mem) { + ath10k_err("PCI iomap error\n"); + ret = -EIO; + goto err_master; + } + + ar_pci->mem = mem; + + spin_lock_init(&ar_pci->ce_lock); + + ar_pci->cacheline_sz = dma_get_cache_alignment(); + + ret = ath10k_pci_start_intr(ar); + if (ret) { + ath10k_err("could not start interrupt handling (%d)\n", ret); + goto err_iomap; + } + + /* + * Bring the target up cleanly. + * + * The target may be in an undefined state with an AUX-powered Target + * and a Host in WoW mode. If the Host crashes, loses power, or is + * restarted (without unloading the driver) then the Target is left + * (aux) powered and running. On a subsequent driver load, the Target + * is in an unexpected state. We try to catch that here in order to + * reset the Target and retry the probe. + */ + ath10k_pci_device_reset(ar_pci); + + ret = ath10k_pci_reset_target(ar); + if (ret) + goto err_intr; + + if (ath10k_target_ps) { + ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save enabled\n"); + } else { + /* Force AWAKE forever */ + ath10k_dbg(ATH10K_DBG_PCI, "on-chip power save disabled\n"); + ath10k_do_pci_wake(ar); + } + + ret = ath10k_pci_ce_init(ar); + if (ret) + goto err_intr; + + ret = ath10k_pci_init_config(ar); + if (ret) + goto err_ce; + + ret = ath10k_pci_wake_target_cpu(ar); + if (ret) { + ath10k_err("could not wake up target CPU (%d)\n", ret); + goto err_ce; + } + + ret = ath10k_core_register(ar); + if (ret) { + ath10k_err("could not register driver core (%d)\n", ret); + goto err_ce; + } + + return 0; + +err_ce: + ath10k_pci_ce_deinit(ar); +err_intr: + ath10k_pci_stop_intr(ar); +err_iomap: + pci_iounmap(pdev, mem); +err_master: + pci_clear_master(pdev); +err_region: + pci_release_region(pdev, BAR_NUM); +err_device: + pci_disable_device(pdev); +err_ar: + pci_set_drvdata(pdev, NULL); + ath10k_core_destroy(ar); +err_ar_pci: + /* call HIF PCI free here */ + kfree(ar_pci); + + return ret; +} + +static void ath10k_pci_remove(struct pci_dev *pdev) +{ + struct ath10k *ar = pci_get_drvdata(pdev); + struct ath10k_pci *ar_pci; + + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + if (!ar) + return; + + ar_pci = ath10k_pci_priv(ar); + + if (!ar_pci) + return; + + tasklet_kill(&ar_pci->msi_fw_err); + + ath10k_core_unregister(ar); + ath10k_pci_stop_intr(ar); + + pci_set_drvdata(pdev, NULL); + pci_iounmap(pdev, ar_pci->mem); + pci_release_region(pdev, BAR_NUM); + pci_clear_master(pdev); + pci_disable_device(pdev); + + ath10k_core_destroy(ar); + kfree(ar_pci); +} + +#if defined(CONFIG_PM_SLEEP) + +#define ATH10K_PCI_PM_CONTROL 0x44 + +static int ath10k_pci_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct ath10k *ar = pci_get_drvdata(pdev); + struct ath10k_pci *ar_pci; + u32 val; + int ret, retval; + + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + if (!ar) + return -ENODEV; + + ar_pci = ath10k_pci_priv(ar); + if (!ar_pci) + return -ENODEV; + + if (ath10k_core_target_suspend(ar)) + return -EBUSY; + + ret = wait_event_interruptible_timeout(ar->event_queue, + ar->is_target_paused == true, + 1 * HZ); + if (ret < 0) { + ath10k_warn("suspend interrupted (%d)\n", ret); + retval = ret; + goto resume; + } else if (ret == 0) { + ath10k_warn("suspend timed out - target pause event never came\n"); + retval = EIO; + goto resume; + } + + /* + * reset is_target_paused and host can check that in next time, + * or it will always be TRUE and host just skip the waiting + * condition, it causes target assert due to host already + * suspend + */ + ar->is_target_paused = false; + + pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val); + + if ((val & 0x000000ff) != 0x3) { + pci_save_state(pdev); + pci_disable_device(pdev); + pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL, + (val & 0xffffff00) | 0x03); + } + + return 0; +resume: + ret = ath10k_core_target_resume(ar); + if (ret) + ath10k_warn("could not resume (%d)\n", ret); + + return retval; +} + +static int ath10k_pci_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct ath10k *ar = pci_get_drvdata(pdev); + struct ath10k_pci *ar_pci; + int ret; + u32 val; + + ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__); + + if (!ar) + return -ENODEV; + ar_pci = ath10k_pci_priv(ar); + + if (!ar_pci) + return -ENODEV; + + ret = pci_enable_device(pdev); + if (ret) { + ath10k_warn("cannot enable PCI device: %d\n", ret); + return ret; + } + + pci_read_config_dword(pdev, ATH10K_PCI_PM_CONTROL, &val); + + if ((val & 0x000000ff) != 0) { + pci_restore_state(pdev); + pci_write_config_dword(pdev, ATH10K_PCI_PM_CONTROL, + val & 0xffffff00); + /* + * Suspend/Resume resets the PCI configuration space, + * so we have to re-disable the RETRY_TIMEOUT register (0x41) + * to keep PCI Tx retries from interfering with C3 CPU state + */ + pci_read_config_dword(pdev, 0x40, &val); + + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + } + + ret = ath10k_core_target_resume(ar); + if (ret) + ath10k_warn("target resume failed: %d\n", ret); + + return ret; +} + +static SIMPLE_DEV_PM_OPS(ath10k_dev_pm_ops, + ath10k_pci_suspend, + ath10k_pci_resume); + +#define ATH10K_PCI_PM_OPS (&ath10k_dev_pm_ops) + +#else + +#define ATH10K_PCI_PM_OPS NULL + +#endif /* CONFIG_PM_SLEEP */ + +MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table); + +static struct pci_driver ath10k_pci_driver = { + .name = "ath10k_pci", + .id_table = ath10k_pci_id_table, + .probe = ath10k_pci_probe, + .remove = ath10k_pci_remove, + .driver.pm = ATH10K_PCI_PM_OPS, +}; + +static int __init ath10k_pci_init(void) +{ + int ret; + + ret = pci_register_driver(&ath10k_pci_driver); + if (ret) + ath10k_err("pci_register_driver failed [%d]\n", ret); + + return ret; +} +module_init(ath10k_pci_init); + +static void __exit ath10k_pci_exit(void) +{ + pci_unregister_driver(&ath10k_pci_driver); +} + +module_exit(ath10k_pci_exit); + +MODULE_AUTHOR("Qualcomm Atheros"); +MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_FW_FILE); +MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_OTP_FILE); +MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_OTP_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h new file mode 100644 index 000000000000..d2a055a07dc6 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _PCI_H_ +#define _PCI_H_ + +#include + +#include "hw.h" +#include "ce.h" + +/* FW dump area */ +#define REG_DUMP_COUNT_QCA988X 60 + +/* + * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite + */ +#define DIAG_TRANSFER_LIMIT 2048 + +/* + * maximum number of bytes that can be + * handled atomically by DiagRead/DiagWrite + */ +#define DIAG_TRANSFER_LIMIT 2048 + +struct bmi_xfer { + struct completion done; + bool wait_for_resp; + u32 resp_len; +}; + +struct ath10k_pci_compl { + struct list_head list; + int send_or_recv; + struct ce_state *ce_state; + struct hif_ce_pipe_info *pipe_info; + void *transfer_context; + unsigned int nbytes; + unsigned int transfer_id; + unsigned int flags; +}; + +/* compl_state.send_or_recv */ +#define HIF_CE_COMPLETE_FREE 0 +#define HIF_CE_COMPLETE_SEND 1 +#define HIF_CE_COMPLETE_RECV 2 + +/* + * PCI-specific Target state + * + * NOTE: Structure is shared between Host software and Target firmware! + * + * Much of this may be of interest to the Host so + * HOST_INTEREST->hi_interconnect_state points here + * (and all members are 32-bit quantities in order to + * facilitate Host access). In particular, Host software is + * required to initialize pipe_cfg_addr and svc_to_pipe_map. + */ +struct pcie_state { + /* Pipe configuration Target address */ + /* NB: ce_pipe_config[CE_COUNT] */ + u32 pipe_cfg_addr; + + /* Service to pipe map Target address */ + /* NB: service_to_pipe[PIPE_TO_CE_MAP_CN] */ + u32 svc_to_pipe_map; + + /* number of MSI interrupts requested */ + u32 msi_requested; + + /* number of MSI interrupts granted */ + u32 msi_granted; + + /* Message Signalled Interrupt address */ + u32 msi_addr; + + /* Base data */ + u32 msi_data; + + /* + * Data for firmware interrupt; + * MSI data for other interrupts are + * in various SoC registers + */ + u32 msi_fw_intr_data; + + /* PCIE_PWR_METHOD_* */ + u32 power_mgmt_method; + + /* PCIE_CONFIG_FLAG_* */ + u32 config_flags; +}; + +/* PCIE_CONFIG_FLAG definitions */ +#define PCIE_CONFIG_FLAG_ENABLE_L1 0x0000001 + +/* Host software's Copy Engine configuration. */ +#define CE_ATTR_FLAGS 0 + +/* + * Configuration information for a Copy Engine pipe. + * Passed from Host to Target during startup (one per CE). + * + * NOTE: Structure is shared between Host software and Target firmware! + */ +struct ce_pipe_config { + u32 pipenum; + u32 pipedir; + u32 nentries; + u32 nbytes_max; + u32 flags; + u32 reserved; +}; + +/* + * Directions for interconnect pipe configuration. + * These definitions may be used during configuration and are shared + * between Host and Target. + * + * Pipe Directions are relative to the Host, so PIPEDIR_IN means + * "coming IN over air through Target to Host" as with a WiFi Rx operation. + * Conversely, PIPEDIR_OUT means "going OUT from Host through Target over air" + * as with a WiFi Tx operation. This is somewhat awkward for the "middle-man" + * Target since things that are "PIPEDIR_OUT" are coming IN to the Target + * over the interconnect. + */ +#define PIPEDIR_NONE 0 +#define PIPEDIR_IN 1 /* Target-->Host, WiFi Rx direction */ +#define PIPEDIR_OUT 2 /* Host->Target, WiFi Tx direction */ +#define PIPEDIR_INOUT 3 /* bidirectional */ + +/* Establish a mapping between a service/direction and a pipe. */ +struct service_to_pipe { + u32 service_id; + u32 pipedir; + u32 pipenum; +}; + +enum ath10k_pci_features { + ATH10K_PCI_FEATURE_MSI_X = 0, + ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND = 1, + + /* keep last */ + ATH10K_PCI_FEATURE_COUNT +}; + +/* Per-pipe state. */ +struct hif_ce_pipe_info { + /* Handle of underlying Copy Engine */ + struct ce_state *ce_hdl; + + /* Our pipe number; facilitiates use of pipe_info ptrs. */ + u8 pipe_num; + + /* Convenience back pointer to hif_ce_state. */ + struct ath10k *hif_ce_state; + + size_t buf_sz; + + /* protects compl_free and num_send_allowed */ + spinlock_t pipe_lock; + + /* List of free CE completion slots */ + struct list_head compl_free; + + /* Limit the number of outstanding send requests. */ + int num_sends_allowed; + + struct ath10k_pci *ar_pci; + struct tasklet_struct intr; +}; + +struct ath10k_pci { + struct pci_dev *pdev; + struct device *dev; + struct ath10k *ar; + void __iomem *mem; + int cacheline_sz; + + DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT); + + /* + * Number of MSI interrupts granted, 0 --> using legacy PCI line + * interrupts. + */ + int num_msi_intrs; + + struct tasklet_struct intr_tq; + struct tasklet_struct msi_fw_err; + + /* Number of Copy Engines supported */ + unsigned int ce_count; + + int started; + + atomic_t keep_awake_count; + bool verified_awake; + + /* List of CE completions to be processed */ + struct list_head compl_process; + + /* protects compl_processing and compl_process */ + spinlock_t compl_lock; + + bool compl_processing; + + struct hif_ce_pipe_info pipe_info[CE_COUNT_MAX]; + + struct ath10k_hif_cb msg_callbacks_current; + + /* Target address used to signal a pending firmware event */ + u32 fw_indicator_address; + + /* Copy Engine used for Diagnostic Accesses */ + struct ce_state *ce_diag; + + /* FIXME: document what this really protects */ + spinlock_t ce_lock; + + /* Map CE id to ce_state */ + struct ce_state *ce_id_to_state[CE_COUNT_MAX]; + + /* makes sure that dummy reads are atomic */ + spinlock_t hw_v1_workaround_lock; +}; + +static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) +{ + return ar->hif.priv; +} + +static inline u32 ath10k_pci_reg_read32(void __iomem *mem, u32 addr) +{ + return ioread32(mem + PCIE_LOCAL_BASE_ADDRESS + addr); +} + +static inline void ath10k_pci_reg_write32(void __iomem *mem, u32 addr, u32 val) +{ + iowrite32(val, mem + PCIE_LOCAL_BASE_ADDRESS + addr); +} + +#define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ +#define PCIE_WAKE_TIMEOUT 5000 /* 5ms */ + +#define BAR_NUM 0 + +#define CDC_WAR_MAGIC_STR 0xceef0000 +#define CDC_WAR_DATA_CE 4 + +/* + * TODO: Should be a function call specific to each Target-type. + * This convoluted macro converts from Target CPU Virtual Address Space to CE + * Address Space. As part of this process, we conservatively fetch the current + * PCIE_BAR. MOST of the time, this should match the upper bits of PCI space + * for this device; but that's not guaranteed. + */ +#define TARG_CPU_SPACE_TO_CE_SPACE(ar, pci_addr, addr) \ + (((ioread32((pci_addr)+(SOC_CORE_BASE_ADDRESS| \ + CORE_CTRL_ADDRESS)) & 0x7ff) << 21) | \ + 0x100000 | ((addr) & 0xfffff)) + +/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ +#define DIAG_ACCESS_CE_TIMEOUT_MS 10 + +/* + * This API allows the Host to access Target registers directly + * and relatively efficiently over PCIe. + * This allows the Host to avoid extra overhead associated with + * sending a message to firmware and waiting for a response message + * from firmware, as is done on other interconnects. + * + * Yet there is some complexity with direct accesses because the + * Target's power state is not known a priori. The Host must issue + * special PCIe reads/writes in order to explicitly wake the Target + * and to verify that it is awake and will remain awake. + * + * Usage: + * + * Use ath10k_pci_read32 and ath10k_pci_write32 to access Target space. + * These calls must be bracketed by ath10k_pci_wake and + * ath10k_pci_sleep. A single BEGIN/END pair is adequate for + * multiple READ/WRITE operations. + * + * Use ath10k_pci_wake to put the Target in a state in + * which it is legal for the Host to directly access it. This + * may involve waking the Target from a low power state, which + * may take up to 2Ms! + * + * Use ath10k_pci_sleep to tell the Target that as far as + * this code path is concerned, it no longer needs to remain + * directly accessible. BEGIN/END is under a reference counter; + * multiple code paths may issue BEGIN/END on a single targid. + */ +static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, + u32 value) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + void __iomem *addr = ar_pci->mem; + + if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) { + unsigned long irq_flags; + + spin_lock_irqsave(&ar_pci->hw_v1_workaround_lock, irq_flags); + + ioread32(addr+offset+4); /* 3rd read prior to write */ + ioread32(addr+offset+4); /* 2nd read prior to write */ + ioread32(addr+offset+4); /* 1st read prior to write */ + iowrite32(value, addr+offset); + + spin_unlock_irqrestore(&ar_pci->hw_v1_workaround_lock, + irq_flags); + } else { + iowrite32(value, addr+offset); + } +} + +static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + return ioread32(ar_pci->mem + offset); +} + +extern unsigned int ath10k_target_ps; + +void ath10k_do_pci_wake(struct ath10k *ar); +void ath10k_do_pci_sleep(struct ath10k *ar); + +static inline void ath10k_pci_wake(struct ath10k *ar) +{ + if (ath10k_target_ps) + ath10k_do_pci_wake(ar); +} + +static inline void ath10k_pci_sleep(struct ath10k *ar) +{ + if (ath10k_target_ps) + ath10k_do_pci_sleep(ar); +} + +#endif /* _PCI_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h new file mode 100644 index 000000000000..bfec6c8f2ecb --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -0,0 +1,990 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _RX_DESC_H_ +#define _RX_DESC_H_ + +enum rx_attention_flags { + RX_ATTENTION_FLAGS_FIRST_MPDU = 1 << 0, + RX_ATTENTION_FLAGS_LAST_MPDU = 1 << 1, + RX_ATTENTION_FLAGS_MCAST_BCAST = 1 << 2, + RX_ATTENTION_FLAGS_PEER_IDX_INVALID = 1 << 3, + RX_ATTENTION_FLAGS_PEER_IDX_TIMEOUT = 1 << 4, + RX_ATTENTION_FLAGS_POWER_MGMT = 1 << 5, + RX_ATTENTION_FLAGS_NON_QOS = 1 << 6, + RX_ATTENTION_FLAGS_NULL_DATA = 1 << 7, + RX_ATTENTION_FLAGS_MGMT_TYPE = 1 << 8, + RX_ATTENTION_FLAGS_CTRL_TYPE = 1 << 9, + RX_ATTENTION_FLAGS_MORE_DATA = 1 << 10, + RX_ATTENTION_FLAGS_EOSP = 1 << 11, + RX_ATTENTION_FLAGS_U_APSD_TRIGGER = 1 << 12, + RX_ATTENTION_FLAGS_FRAGMENT = 1 << 13, + RX_ATTENTION_FLAGS_ORDER = 1 << 14, + RX_ATTENTION_FLAGS_CLASSIFICATION = 1 << 15, + RX_ATTENTION_FLAGS_OVERFLOW_ERR = 1 << 16, + RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR = 1 << 17, + RX_ATTENTION_FLAGS_TCP_UDP_CHKSUM_FAIL = 1 << 18, + RX_ATTENTION_FLAGS_IP_CHKSUM_FAIL = 1 << 19, + RX_ATTENTION_FLAGS_SA_IDX_INVALID = 1 << 20, + RX_ATTENTION_FLAGS_DA_IDX_INVALID = 1 << 21, + RX_ATTENTION_FLAGS_SA_IDX_TIMEOUT = 1 << 22, + RX_ATTENTION_FLAGS_DA_IDX_TIMEOUT = 1 << 23, + RX_ATTENTION_FLAGS_ENCRYPT_REQUIRED = 1 << 24, + RX_ATTENTION_FLAGS_DIRECTED = 1 << 25, + RX_ATTENTION_FLAGS_BUFFER_FRAGMENT = 1 << 26, + RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR = 1 << 27, + RX_ATTENTION_FLAGS_TKIP_MIC_ERR = 1 << 28, + RX_ATTENTION_FLAGS_DECRYPT_ERR = 1 << 29, + RX_ATTENTION_FLAGS_FCS_ERR = 1 << 30, + RX_ATTENTION_FLAGS_MSDU_DONE = 1 << 31, +}; + +struct rx_attention { + __le32 flags; /* %RX_ATTENTION_FLAGS_ */ +} __packed; + +/* + * first_mpdu + * Indicates the first MSDU of the PPDU. If both first_mpdu + * and last_mpdu are set in the MSDU then this is a not an + * A-MPDU frame but a stand alone MPDU. Interior MPDU in an + * A-MPDU shall have both first_mpdu and last_mpdu bits set to + * 0. The PPDU start status will only be valid when this bit + * is set. + * + * last_mpdu + * Indicates the last MSDU of the last MPDU of the PPDU. The + * PPDU end status will only be valid when this bit is set. + * + * mcast_bcast + * Multicast / broadcast indicator. Only set when the MAC + * address 1 bit 0 is set indicating mcast/bcast and the BSSID + * matches one of the 4 BSSID registers. Only set when + * first_msdu is set. + * + * peer_idx_invalid + * Indicates no matching entries within the the max search + * count. Only set when first_msdu is set. + * + * peer_idx_timeout + * Indicates an unsuccessful search for the peer index due to + * timeout. Only set when first_msdu is set. + * + * power_mgmt + * Power management bit set in the 802.11 header. Only set + * when first_msdu is set. + * + * non_qos + * Set if packet is not a non-QoS data frame. Only set when + * first_msdu is set. + * + * null_data + * Set if frame type indicates either null data or QoS null + * data format. Only set when first_msdu is set. + * + * mgmt_type + * Set if packet is a management packet. Only set when + * first_msdu is set. + * + * ctrl_type + * Set if packet is a control packet. Only set when first_msdu + * is set. + * + * more_data + * Set if more bit in frame control is set. Only set when + * first_msdu is set. + * + * eosp + * Set if the EOSP (end of service period) bit in the QoS + * control field is set. Only set when first_msdu is set. + * + * u_apsd_trigger + * Set if packet is U-APSD trigger. Key table will have bits + * per TID to indicate U-APSD trigger. + * + * fragment + * Indicates that this is an 802.11 fragment frame. This is + * set when either the more_frag bit is set in the frame + * control or the fragment number is not zero. Only set when + * first_msdu is set. + * + * order + * Set if the order bit in the frame control is set. Only set + * when first_msdu is set. + * + * classification + * Indicates that this status has a corresponding MSDU that + * requires FW processing. The OLE will have classification + * ring mask registers which will indicate the ring(s) for + * packets and descriptors which need FW attention. + * + * overflow_err + * PCU Receive FIFO does not have enough space to store the + * full receive packet. Enough space is reserved in the + * receive FIFO for the status is written. This MPDU remaining + * packets in the PPDU will be filtered and no Ack response + * will be transmitted. + * + * msdu_length_err + * Indicates that the MSDU length from the 802.3 encapsulated + * length field extends beyond the MPDU boundary. + * + * tcp_udp_chksum_fail + * Indicates that the computed checksum (tcp_udp_chksum) did + * not match the checksum in the TCP/UDP header. + * + * ip_chksum_fail + * Indicates that the computed checksum did not match the + * checksum in the IP header. + * + * sa_idx_invalid + * Indicates no matching entry was found in the address search + * table for the source MAC address. + * + * da_idx_invalid + * Indicates no matching entry was found in the address search + * table for the destination MAC address. + * + * sa_idx_timeout + * Indicates an unsuccessful search for the source MAC address + * due to the expiring of the search timer. + * + * da_idx_timeout + * Indicates an unsuccessful search for the destination MAC + * address due to the expiring of the search timer. + * + * encrypt_required + * Indicates that this data type frame is not encrypted even if + * the policy for this MPDU requires encryption as indicated in + * the peer table key type. + * + * directed + * MPDU is a directed packet which means that the RA matched + * our STA addresses. In proxySTA it means that the TA matched + * an entry in our address search table with the corresponding + * 'no_ack' bit is the address search entry cleared. + * + * buffer_fragment + * Indicates that at least one of the rx buffers has been + * fragmented. If set the FW should look at the rx_frag_info + * descriptor described below. + * + * mpdu_length_err + * Indicates that the MPDU was pre-maturely terminated + * resulting in a truncated MPDU. Don't trust the MPDU length + * field. + * + * tkip_mic_err + * Indicates that the MPDU Michael integrity check failed + * + * decrypt_err + * Indicates that the MPDU decrypt integrity check failed + * + * fcs_err + * Indicates that the MPDU FCS check failed + * + * msdu_done + * If set indicates that the RX packet data, RX header data, RX + * PPDU start descriptor, RX MPDU start/end descriptor, RX MSDU + * start/end descriptors and RX Attention descriptor are all + * valid. This bit must be in the last octet of the + * descriptor. + */ + +struct rx_frag_info { + u8 ring0_more_count; + u8 ring1_more_count; + u8 ring2_more_count; + u8 ring3_more_count; +} __packed; + +/* + * ring0_more_count + * Indicates the number of more buffers associated with RX DMA + * ring 0. Field is filled in by the RX_DMA. + * + * ring1_more_count + * Indicates the number of more buffers associated with RX DMA + * ring 1. Field is filled in by the RX_DMA. + * + * ring2_more_count + * Indicates the number of more buffers associated with RX DMA + * ring 2. Field is filled in by the RX_DMA. + * + * ring3_more_count + * Indicates the number of more buffers associated with RX DMA + * ring 3. Field is filled in by the RX_DMA. + */ + +enum htt_rx_mpdu_encrypt_type { + HTT_RX_MPDU_ENCRYPT_WEP40 = 0, + HTT_RX_MPDU_ENCRYPT_WEP104 = 1, + HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC = 2, + HTT_RX_MPDU_ENCRYPT_WEP128 = 3, + HTT_RX_MPDU_ENCRYPT_TKIP_WPA = 4, + HTT_RX_MPDU_ENCRYPT_WAPI = 5, + HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2 = 6, + HTT_RX_MPDU_ENCRYPT_NONE = 7, +}; + +#define RX_MPDU_START_INFO0_PEER_IDX_MASK 0x000007ff +#define RX_MPDU_START_INFO0_PEER_IDX_LSB 0 +#define RX_MPDU_START_INFO0_SEQ_NUM_MASK 0x0fff0000 +#define RX_MPDU_START_INFO0_SEQ_NUM_LSB 16 +#define RX_MPDU_START_INFO0_ENCRYPT_TYPE_MASK 0xf0000000 +#define RX_MPDU_START_INFO0_ENCRYPT_TYPE_LSB 28 +#define RX_MPDU_START_INFO0_FROM_DS (1 << 11) +#define RX_MPDU_START_INFO0_TO_DS (1 << 12) +#define RX_MPDU_START_INFO0_ENCRYPTED (1 << 13) +#define RX_MPDU_START_INFO0_RETRY (1 << 14) +#define RX_MPDU_START_INFO0_TXBF_H_INFO (1 << 15) + +#define RX_MPDU_START_INFO1_TID_MASK 0xf0000000 +#define RX_MPDU_START_INFO1_TID_LSB 28 +#define RX_MPDU_START_INFO1_DIRECTED (1 << 16) + +struct rx_mpdu_start { + __le32 info0; + union { + struct { + __le32 pn31_0; + __le32 info1; /* %RX_MPDU_START_INFO1_ */ + } __packed; + struct { + u8 pn[6]; + } __packed; + } __packed; +} __packed; + +/* + * peer_idx + * The index of the address search table which associated with + * the peer table entry corresponding to this MPDU. Only valid + * when first_msdu is set. + * + * fr_ds + * Set if the from DS bit is set in the frame control. Only + * valid when first_msdu is set. + * + * to_ds + * Set if the to DS bit is set in the frame control. Only + * valid when first_msdu is set. + * + * encrypted + * Protected bit from the frame control. Only valid when + * first_msdu is set. + * + * retry + * Retry bit from the frame control. Only valid when + * first_msdu is set. + * + * txbf_h_info + * The MPDU data will contain H information. Primarily used + * for debug. + * + * seq_num + * The sequence number from the 802.11 header. Only valid when + * first_msdu is set. + * + * encrypt_type + * Indicates type of decrypt cipher used (as defined in the + * peer table) + * 0: WEP40 + * 1: WEP104 + * 2: TKIP without MIC + * 3: WEP128 + * 4: TKIP (WPA) + * 5: WAPI + * 6: AES-CCM (WPA2) + * 7: No cipher + * Only valid when first_msdu_is set + * + * pn_31_0 + * Bits [31:0] of the PN number extracted from the IV field + * WEP: IV = {key_id_octet, pn2, pn1, pn0}. Only pn[23:0] is + * valid. + * TKIP: IV = {pn5, pn4, pn3, pn2, key_id_octet, pn0, + * WEPSeed[1], pn1}. Only pn[47:0] is valid. + * AES-CCM: IV = {pn5, pn4, pn3, pn2, key_id_octet, 0x0, pn1, + * pn0}. Only pn[47:0] is valid. + * WAPI: IV = {key_id_octet, 0x0, pn15, pn14, pn13, pn12, pn11, + * pn10, pn9, pn8, pn7, pn6, pn5, pn4, pn3, pn2, pn1, pn0}. + * The ext_wapi_pn[127:48] in the rx_msdu_misc descriptor and + * pn[47:0] are valid. + * Only valid when first_msdu is set. + * + * pn_47_32 + * Bits [47:32] of the PN number. See description for + * pn_31_0. The remaining PN fields are in the rx_msdu_end + * descriptor + * + * pn + * Use this field to access the pn without worrying about + * byte-order and bitmasking/bitshifting. + * + * directed + * See definition in RX attention descriptor + * + * reserved_2 + * Reserved: HW should fill with zero. FW should ignore. + * + * tid + * The TID field in the QoS control field + */ + +#define RX_MPDU_END_INFO0_RESERVED_0_MASK 0x00001fff +#define RX_MPDU_END_INFO0_RESERVED_0_LSB 0 +#define RX_MPDU_END_INFO0_POST_DELIM_CNT_MASK 0x0fff0000 +#define RX_MPDU_END_INFO0_POST_DELIM_CNT_LSB 16 +#define RX_MPDU_END_INFO0_OVERFLOW_ERR (1 << 13) +#define RX_MPDU_END_INFO0_LAST_MPDU (1 << 14) +#define RX_MPDU_END_INFO0_POST_DELIM_ERR (1 << 15) +#define RX_MPDU_END_INFO0_MPDU_LENGTH_ERR (1 << 28) +#define RX_MPDU_END_INFO0_TKIP_MIC_ERR (1 << 29) +#define RX_MPDU_END_INFO0_DECRYPT_ERR (1 << 30) +#define RX_MPDU_END_INFO0_FCS_ERR (1 << 31) + +struct rx_mpdu_end { + __le32 info0; +} __packed; + +/* + * reserved_0 + * Reserved + * + * overflow_err + * PCU Receive FIFO does not have enough space to store the + * full receive packet. Enough space is reserved in the + * receive FIFO for the status is written. This MPDU remaining + * packets in the PPDU will be filtered and no Ack response + * will be transmitted. + * + * last_mpdu + * Indicates that this is the last MPDU of a PPDU. + * + * post_delim_err + * Indicates that a delimiter FCS error occurred after this + * MPDU before the next MPDU. Only valid when last_msdu is + * set. + * + * post_delim_cnt + * Count of the delimiters after this MPDU. This requires the + * last MPDU to be held until all the EOF descriptors have been + * received. This may be inefficient in the future when + * ML-MIMO is used. Only valid when last_mpdu is set. + * + * mpdu_length_err + * See definition in RX attention descriptor + * + * tkip_mic_err + * See definition in RX attention descriptor + * + * decrypt_err + * See definition in RX attention descriptor + * + * fcs_err + * See definition in RX attention descriptor + */ + +#define RX_MSDU_START_INFO0_MSDU_LENGTH_MASK 0x00003fff +#define RX_MSDU_START_INFO0_MSDU_LENGTH_LSB 0 +#define RX_MSDU_START_INFO0_IP_OFFSET_MASK 0x000fc000 +#define RX_MSDU_START_INFO0_IP_OFFSET_LSB 14 +#define RX_MSDU_START_INFO0_RING_MASK_MASK 0x00f00000 +#define RX_MSDU_START_INFO0_RING_MASK_LSB 20 +#define RX_MSDU_START_INFO0_TCP_UDP_OFFSET_MASK 0x7f000000 +#define RX_MSDU_START_INFO0_TCP_UDP_OFFSET_LSB 24 + +#define RX_MSDU_START_INFO1_MSDU_NUMBER_MASK 0x000000ff +#define RX_MSDU_START_INFO1_MSDU_NUMBER_LSB 0 +#define RX_MSDU_START_INFO1_DECAP_FORMAT_MASK 0x00000300 +#define RX_MSDU_START_INFO1_DECAP_FORMAT_LSB 8 +#define RX_MSDU_START_INFO1_SA_IDX_MASK 0x07ff0000 +#define RX_MSDU_START_INFO1_SA_IDX_LSB 16 +#define RX_MSDU_START_INFO1_IPV4_PROTO (1 << 10) +#define RX_MSDU_START_INFO1_IPV6_PROTO (1 << 11) +#define RX_MSDU_START_INFO1_TCP_PROTO (1 << 12) +#define RX_MSDU_START_INFO1_UDP_PROTO (1 << 13) +#define RX_MSDU_START_INFO1_IP_FRAG (1 << 14) +#define RX_MSDU_START_INFO1_TCP_ONLY_ACK (1 << 15) + +enum rx_msdu_decap_format { + RX_MSDU_DECAP_RAW = 0, + RX_MSDU_DECAP_NATIVE_WIFI = 1, + RX_MSDU_DECAP_ETHERNET2_DIX = 2, + RX_MSDU_DECAP_8023_SNAP_LLC = 3 +}; + +struct rx_msdu_start { + __le32 info0; /* %RX_MSDU_START_INFO0_ */ + __le32 flow_id_crc; + __le32 info1; /* %RX_MSDU_START_INFO1_ */ +} __packed; + +/* + * msdu_length + * MSDU length in bytes after decapsulation. This field is + * still valid for MPDU frames without A-MSDU. It still + * represents MSDU length after decapsulation + * + * ip_offset + * Indicates the IP offset in bytes from the start of the + * packet after decapsulation. Only valid if ipv4_proto or + * ipv6_proto is set. + * + * ring_mask + * Indicates the destination RX rings for this MSDU. + * + * tcp_udp_offset + * Indicates the offset in bytes to the start of TCP or UDP + * header from the start of the IP header after decapsulation. + * Only valid if tcp_prot or udp_prot is set. The value 0 + * indicates that the offset is longer than 127 bytes. + * + * reserved_0c + * Reserved: HW should fill with zero. FW should ignore. + * + * flow_id_crc + * The flow_id_crc runs CRC32 on the following information: + * IPv4 option: dest_addr[31:0], src_addr [31:0], {24'b0, + * protocol[7:0]}. + * IPv6 option: dest_addr[127:0], src_addr [127:0], {24'b0, + * next_header[7:0]} + * UDP case: sort_port[15:0], dest_port[15:0] + * TCP case: sort_port[15:0], dest_port[15:0], + * {header_length[3:0], 6'b0, flags[5:0], window_size[15:0]}, + * {16'b0, urgent_ptr[15:0]}, all options except 32-bit + * timestamp. + * + * msdu_number + * Indicates the MSDU number within a MPDU. This value is + * reset to zero at the start of each MPDU. If the number of + * MSDU exceeds 255 this number will wrap using modulo 256. + * + * decap_format + * Indicates the format after decapsulation: + * 0: RAW: No decapsulation + * 1: Native WiFi + * 2: Ethernet 2 (DIX) + * 3: 802.3 (SNAP/LLC) + * + * ipv4_proto + * Set if L2 layer indicates IPv4 protocol. + * + * ipv6_proto + * Set if L2 layer indicates IPv6 protocol. + * + * tcp_proto + * Set if the ipv4_proto or ipv6_proto are set and the IP + * protocol indicates TCP. + * + * udp_proto + * Set if the ipv4_proto or ipv6_proto are set and the IP + * protocol indicates UDP. + * + * ip_frag + * Indicates that either the IP More frag bit is set or IP frag + * number is non-zero. If set indicates that this is a + * fragmented IP packet. + * + * tcp_only_ack + * Set if only the TCP Ack bit is set in the TCP flags and if + * the TCP payload is 0. + * + * sa_idx + * The offset in the address table which matches the MAC source + * address. + * + * reserved_2b + * Reserved: HW should fill with zero. FW should ignore. + */ + +#define RX_MSDU_END_INFO0_REPORTED_MPDU_LENGTH_MASK 0x00003fff +#define RX_MSDU_END_INFO0_REPORTED_MPDU_LENGTH_LSB 0 +#define RX_MSDU_END_INFO0_FIRST_MSDU (1 << 14) +#define RX_MSDU_END_INFO0_LAST_MSDU (1 << 15) +#define RX_MSDU_END_INFO0_PRE_DELIM_ERR (1 << 30) +#define RX_MSDU_END_INFO0_RESERVED_3B (1 << 31) + +struct rx_msdu_end { + __le16 ip_hdr_cksum; + __le16 tcp_hdr_cksum; + u8 key_id_octet; + u8 classification_filter; + u8 wapi_pn[10]; + __le32 info0; +} __packed; + +/* + *ip_hdr_chksum + * This can include the IP header checksum or the pseudo header + * checksum used by TCP/UDP checksum. + * + *tcp_udp_chksum + * The value of the computed TCP/UDP checksum. A mode bit + * selects whether this checksum is the full checksum or the + * partial checksum which does not include the pseudo header. + * + *key_id_octet + * The key ID octet from the IV. Only valid when first_msdu is + * set. + * + *classification_filter + * Indicates the number classification filter rule + * + *ext_wapi_pn_63_48 + * Extension PN (packet number) which is only used by WAPI. + * This corresponds to WAPI PN bits [63:48] (pn6 and pn7). The + * WAPI PN bits [63:0] are in the pn field of the rx_mpdu_start + * descriptor. + * + *ext_wapi_pn_95_64 + * Extension PN (packet number) which is only used by WAPI. + * This corresponds to WAPI PN bits [95:64] (pn8, pn9, pn10 and + * pn11). + * + *ext_wapi_pn_127_96 + * Extension PN (packet number) which is only used by WAPI. + * This corresponds to WAPI PN bits [127:96] (pn12, pn13, pn14, + * pn15). + * + *reported_mpdu_length + * MPDU length before decapsulation. Only valid when + * first_msdu is set. This field is taken directly from the + * length field of the A-MPDU delimiter or the preamble length + * field for non-A-MPDU frames. + * + *first_msdu + * Indicates the first MSDU of A-MSDU. If both first_msdu and + * last_msdu are set in the MSDU then this is a non-aggregated + * MSDU frame: normal MPDU. Interior MSDU in an A-MSDU shall + * have both first_mpdu and last_mpdu bits set to 0. + * + *last_msdu + * Indicates the last MSDU of the A-MSDU. MPDU end status is + * only valid when last_msdu is set. + * + *reserved_3a + * Reserved: HW should fill with zero. FW should ignore. + * + *pre_delim_err + * Indicates that the first delimiter had a FCS failure. Only + * valid when first_mpdu and first_msdu are set. + * + *reserved_3b + * Reserved: HW should fill with zero. FW should ignore. + */ + +#define RX_PPDU_START_SIG_RATE_SELECT_OFDM 0 +#define RX_PPDU_START_SIG_RATE_SELECT_CCK 1 + +#define RX_PPDU_START_SIG_RATE_OFDM_48 0 +#define RX_PPDU_START_SIG_RATE_OFDM_24 1 +#define RX_PPDU_START_SIG_RATE_OFDM_12 2 +#define RX_PPDU_START_SIG_RATE_OFDM_6 3 +#define RX_PPDU_START_SIG_RATE_OFDM_54 4 +#define RX_PPDU_START_SIG_RATE_OFDM_36 5 +#define RX_PPDU_START_SIG_RATE_OFDM_18 6 +#define RX_PPDU_START_SIG_RATE_OFDM_9 7 + +#define RX_PPDU_START_SIG_RATE_CCK_LP_11 0 +#define RX_PPDU_START_SIG_RATE_CCK_LP_5_5 1 +#define RX_PPDU_START_SIG_RATE_CCK_LP_2 2 +#define RX_PPDU_START_SIG_RATE_CCK_LP_1 3 +#define RX_PPDU_START_SIG_RATE_CCK_SP_11 4 +#define RX_PPDU_START_SIG_RATE_CCK_SP_5_5 5 +#define RX_PPDU_START_SIG_RATE_CCK_SP_2 6 + +#define HTT_RX_PPDU_START_PREAMBLE_LEGACY 0x04 +#define HTT_RX_PPDU_START_PREAMBLE_HT 0x08 +#define HTT_RX_PPDU_START_PREAMBLE_HT_WITH_TXBF 0x09 +#define HTT_RX_PPDU_START_PREAMBLE_VHT 0x0C +#define HTT_RX_PPDU_START_PREAMBLE_VHT_WITH_TXBF 0x0D + +#define RX_PPDU_START_INFO0_IS_GREENFIELD (1 << 0) + +#define RX_PPDU_START_INFO1_L_SIG_RATE_MASK 0x0000000f +#define RX_PPDU_START_INFO1_L_SIG_RATE_LSB 0 +#define RX_PPDU_START_INFO1_L_SIG_LENGTH_MASK 0x0001ffe0 +#define RX_PPDU_START_INFO1_L_SIG_LENGTH_LSB 5 +#define RX_PPDU_START_INFO1_L_SIG_TAIL_MASK 0x00fc0000 +#define RX_PPDU_START_INFO1_L_SIG_TAIL_LSB 18 +#define RX_PPDU_START_INFO1_PREAMBLE_TYPE_MASK 0xff000000 +#define RX_PPDU_START_INFO1_PREAMBLE_TYPE_LSB 24 +#define RX_PPDU_START_INFO1_L_SIG_RATE_SELECT (1 << 4) +#define RX_PPDU_START_INFO1_L_SIG_PARITY (1 << 17) + +#define RX_PPDU_START_INFO2_HT_SIG_VHT_SIG_A_1_MASK 0x00ffffff +#define RX_PPDU_START_INFO2_HT_SIG_VHT_SIG_A_1_LSB 0 + +#define RX_PPDU_START_INFO3_HT_SIG_VHT_SIG_A_2_MASK 0x00ffffff +#define RX_PPDU_START_INFO3_HT_SIG_VHT_SIG_A_2_LSB 0 +#define RX_PPDU_START_INFO3_TXBF_H_INFO (1 << 24) + +#define RX_PPDU_START_INFO4_VHT_SIG_B_MASK 0x1fffffff +#define RX_PPDU_START_INFO4_VHT_SIG_B_LSB 0 + +#define RX_PPDU_START_INFO5_SERVICE_MASK 0x0000ffff +#define RX_PPDU_START_INFO5_SERVICE_LSB 0 + +struct rx_ppdu_start { + struct { + u8 pri20_mhz; + u8 ext20_mhz; + u8 ext40_mhz; + u8 ext80_mhz; + } rssi_chains[4]; + u8 rssi_comb; + __le16 rsvd0; + u8 info0; /* %RX_PPDU_START_INFO0_ */ + __le32 info1; /* %RX_PPDU_START_INFO1_ */ + __le32 info2; /* %RX_PPDU_START_INFO2_ */ + __le32 info3; /* %RX_PPDU_START_INFO3_ */ + __le32 info4; /* %RX_PPDU_START_INFO4_ */ + __le32 info5; /* %RX_PPDU_START_INFO5_ */ +} __packed; + +/* + * rssi_chain0_pri20 + * RSSI of RX PPDU on chain 0 of primary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain0_sec20 + * RSSI of RX PPDU on chain 0 of secondary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain0_sec40 + * RSSI of RX PPDU on chain 0 of secondary 40 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain0_sec80 + * RSSI of RX PPDU on chain 0 of secondary 80 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain1_pri20 + * RSSI of RX PPDU on chain 1 of primary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain1_sec20 + * RSSI of RX PPDU on chain 1 of secondary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain1_sec40 + * RSSI of RX PPDU on chain 1 of secondary 40 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain1_sec80 + * RSSI of RX PPDU on chain 1 of secondary 80 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain2_pri20 + * RSSI of RX PPDU on chain 2 of primary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain2_sec20 + * RSSI of RX PPDU on chain 2 of secondary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain2_sec40 + * RSSI of RX PPDU on chain 2 of secondary 40 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain2_sec80 + * RSSI of RX PPDU on chain 2 of secondary 80 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain3_pri20 + * RSSI of RX PPDU on chain 3 of primary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain3_sec20 + * RSSI of RX PPDU on chain 3 of secondary 20 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain3_sec40 + * RSSI of RX PPDU on chain 3 of secondary 40 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_chain3_sec80 + * RSSI of RX PPDU on chain 3 of secondary 80 MHz bandwidth. + * Value of 0x80 indicates invalid. + * + * rssi_comb + * The combined RSSI of RX PPDU of all active chains and + * bandwidths. Value of 0x80 indicates invalid. + * + * reserved_4a + * Reserved: HW should fill with 0, FW should ignore. + * + * is_greenfield + * Do we really support this? + * + * reserved_4b + * Reserved: HW should fill with 0, FW should ignore. + * + * l_sig_rate + * If l_sig_rate_select is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If l_sig_rate_select is 1: + * 0x8: CCK 11 Mbps long preamble + * 0x9: CCK 5.5 Mbps long preamble + * 0xA: CCK 2 Mbps long preamble + * 0xB: CCK 1 Mbps long preamble + * 0xC: CCK 11 Mbps short preamble + * 0xD: CCK 5.5 Mbps short preamble + * 0xE: CCK 2 Mbps short preamble + * + * l_sig_rate_select + * Legacy signal rate select. If set then l_sig_rate indicates + * CCK rates. If clear then l_sig_rate indicates OFDM rates. + * + * l_sig_length + * Length of legacy frame in octets. + * + * l_sig_parity + * Odd parity over l_sig_rate and l_sig_length + * + * l_sig_tail + * Tail bits for Viterbi decoder + * + * preamble_type + * Indicates the type of preamble ahead: + * 0x4: Legacy (OFDM/CCK) + * 0x8: HT + * 0x9: HT with TxBF + * 0xC: VHT + * 0xD: VHT with TxBF + * 0x80 - 0xFF: Reserved for special baseband data types such + * as radar and spectral scan. + * + * ht_sig_vht_sig_a_1 + * If preamble_type == 0x8 or 0x9 + * HT-SIG (first 24 bits) + * If preamble_type == 0xC or 0xD + * VHT-SIG A (first 24 bits) + * Else + * Reserved + * + * reserved_6 + * Reserved: HW should fill with 0, FW should ignore. + * + * ht_sig_vht_sig_a_2 + * If preamble_type == 0x8 or 0x9 + * HT-SIG (last 24 bits) + * If preamble_type == 0xC or 0xD + * VHT-SIG A (last 24 bits) + * Else + * Reserved + * + * txbf_h_info + * Indicates that the packet data carries H information which + * is used for TxBF debug. + * + * reserved_7 + * Reserved: HW should fill with 0, FW should ignore. + * + * vht_sig_b + * WiFi 1.0 and WiFi 2.0 will likely have this field to be all + * 0s since the BB does not plan on decoding VHT SIG-B. + * + * reserved_8 + * Reserved: HW should fill with 0, FW should ignore. + * + * service + * Service field from BB for OFDM, HT and VHT packets. CCK + * packets will have service field of 0. + * + * reserved_9 + * Reserved: HW should fill with 0, FW should ignore. +*/ + + +#define RX_PPDU_END_FLAGS_PHY_ERR (1 << 0) +#define RX_PPDU_END_FLAGS_RX_LOCATION (1 << 1) +#define RX_PPDU_END_FLAGS_TXBF_H_INFO (1 << 2) + +#define RX_PPDU_END_INFO0_RX_ANTENNA_MASK 0x00ffffff +#define RX_PPDU_END_INFO0_RX_ANTENNA_LSB 0 +#define RX_PPDU_END_INFO0_FLAGS_TX_HT_VHT_ACK (1 << 24) +#define RX_PPDU_END_INFO0_BB_CAPTURED_CHANNEL (1 << 25) + +#define RX_PPDU_END_INFO1_PPDU_DONE (1 << 15) + +struct rx_ppdu_end { + __le32 evm_p0; + __le32 evm_p1; + __le32 evm_p2; + __le32 evm_p3; + __le32 evm_p4; + __le32 evm_p5; + __le32 evm_p6; + __le32 evm_p7; + __le32 evm_p8; + __le32 evm_p9; + __le32 evm_p10; + __le32 evm_p11; + __le32 evm_p12; + __le32 evm_p13; + __le32 evm_p14; + __le32 evm_p15; + __le32 tsf_timestamp; + __le32 wb_timestamp; + u8 locationing_timestamp; + u8 phy_err_code; + __le16 flags; /* %RX_PPDU_END_FLAGS_ */ + __le32 info0; /* %RX_PPDU_END_INFO0_ */ + __le16 bb_length; + __le16 info1; /* %RX_PPDU_END_INFO1_ */ +} __packed; + +/* + * evm_p0 + * EVM for pilot 0. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p1 + * EVM for pilot 1. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p2 + * EVM for pilot 2. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p3 + * EVM for pilot 3. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p4 + * EVM for pilot 4. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p5 + * EVM for pilot 5. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p6 + * EVM for pilot 6. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p7 + * EVM for pilot 7. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p8 + * EVM for pilot 8. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p9 + * EVM for pilot 9. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p10 + * EVM for pilot 10. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p11 + * EVM for pilot 11. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p12 + * EVM for pilot 12. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p13 + * EVM for pilot 13. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p14 + * EVM for pilot 14. Contain EVM for streams: 0, 1, 2 and 3. + * + * evm_p15 + * EVM for pilot 15. Contain EVM for streams: 0, 1, 2 and 3. + * + * tsf_timestamp + * Receive TSF timestamp sampled on the rising edge of + * rx_clear. For PHY errors this may be the current TSF when + * phy_error is asserted if the rx_clear does not assert before + * the end of the PHY error. + * + * wb_timestamp + * WLAN/BT timestamp is a 1 usec resolution timestamp which + * does not get updated based on receive beacon like TSF. The + * same rules for capturing tsf_timestamp are used to capture + * the wb_timestamp. + * + * locationing_timestamp + * Timestamp used for locationing. This timestamp is used to + * indicate fractions of usec. For example if the MAC clock is + * running at 80 MHz, the timestamp will increment every 12.5 + * nsec. The value starts at 0 and increments to 79 and + * returns to 0 and repeats. This information is valid for + * every PPDU. This information can be used in conjunction + * with wb_timestamp to capture large delta times. + * + * phy_err_code + * See the 1.10.8.1.2 for the list of the PHY error codes. + * + * phy_err + * Indicates a PHY error was detected for this PPDU. + * + * rx_location + * Indicates that location information was requested. + * + * txbf_h_info + * Indicates that the packet data carries H information which + * is used for TxBF debug. + * + * reserved_18 + * Reserved: HW should fill with 0, FW should ignore. + * + * rx_antenna + * Receive antenna value + * + * tx_ht_vht_ack + * Indicates that a HT or VHT Ack/BA frame was transmitted in + * response to this receive packet. + * + * bb_captured_channel + * Indicates that the BB has captured a channel dump. FW can + * then read the channel dump memory. This may indicate that + * the channel was captured either based on PCU setting the + * capture_channel bit BB descriptor or FW setting the + * capture_channel mode bit. + * + * reserved_19 + * Reserved: HW should fill with 0, FW should ignore. + * + * bb_length + * Indicates the number of bytes of baseband information for + * PPDUs where the BB descriptor preamble type is 0x80 to 0xFF + * which indicates that this is not a normal PPDU but rather + * contains baseband debug information. + * + * reserved_20 + * Reserved: HW should fill with 0, FW should ignore. + * + * ppdu_done + * PPDU end status is only valid when ppdu_done bit is set. + * Every time HW sets this bit in memory FW/SW must clear this + * bit in memory. FW will initialize all the ppdu_done dword + * to 0. +*/ + +#define FW_RX_DESC_INFO0_DISCARD (1 << 0) +#define FW_RX_DESC_INFO0_FORWARD (1 << 1) +#define FW_RX_DESC_INFO0_INSPECT (1 << 5) +#define FW_RX_DESC_INFO0_EXT_MASK 0xC0 +#define FW_RX_DESC_INFO0_EXT_LSB 6 + +struct fw_rx_desc_base { + u8 info0; +} __packed; + +#endif /* _RX_DESC_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h new file mode 100644 index 000000000000..be7ba1e78afe --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __TARGADDRS_H__ +#define __TARGADDRS_H__ + +/* + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the + * host_interest structure. It must match the address of the _host_interest + * symbol (see linker script). + * + * Host Interest is shared between Host and Target in order to coordinate + * between the two, and is intended to remain constant (with additions only + * at the end) across software releases. + * + * All addresses are available here so that it's possible to + * write a single binary that works with all Target Types. + * May be used in assembler code as well as C. + */ +#define QCA988X_HOST_INTEREST_ADDRESS 0x00400800 +#define HOST_INTEREST_MAX_SIZE 0x200 + +/* + * These are items that the Host may need to access via BMI or via the + * Diagnostic Window. The position of items in this structure must remain + * constant across firmware revisions! Types for each item must be fixed + * size across target and host platforms. More items may be added at the end. + */ +struct host_interest { + /* + * Pointer to application-defined area, if any. + * Set by Target application during startup. + */ + u32 hi_app_host_interest; /* 0x00 */ + + /* Pointer to register dump area, valid after Target crash. */ + u32 hi_failure_state; /* 0x04 */ + + /* Pointer to debug logging header */ + u32 hi_dbglog_hdr; /* 0x08 */ + + u32 hi_unused0c; /* 0x0c */ + + /* + * General-purpose flag bits, similar to SOC_OPTION_* flags. + * Can be used by application rather than by OS. + */ + u32 hi_option_flag; /* 0x10 */ + + /* + * Boolean that determines whether or not to + * display messages on the serial port. + */ + u32 hi_serial_enable; /* 0x14 */ + + /* Start address of DataSet index, if any */ + u32 hi_dset_list_head; /* 0x18 */ + + /* Override Target application start address */ + u32 hi_app_start; /* 0x1c */ + + /* Clock and voltage tuning */ + u32 hi_skip_clock_init; /* 0x20 */ + u32 hi_core_clock_setting; /* 0x24 */ + u32 hi_cpu_clock_setting; /* 0x28 */ + u32 hi_system_sleep_setting; /* 0x2c */ + u32 hi_xtal_control_setting; /* 0x30 */ + u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ + u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ + u32 hi_ref_voltage_trim_setting; /* 0x3c */ + u32 hi_clock_info; /* 0x40 */ + + /* Host uses BE CPU or not */ + u32 hi_be; /* 0x44 */ + + u32 hi_stack; /* normal stack */ /* 0x48 */ + u32 hi_err_stack; /* error stack */ /* 0x4c */ + u32 hi_desired_cpu_speed_hz; /* 0x50 */ + + /* Pointer to Board Data */ + u32 hi_board_data; /* 0x54 */ + + /* + * Indication of Board Data state: + * 0: board data is not yet initialized. + * 1: board data is initialized; unknown size + * >1: number of bytes of initialized board data + */ + u32 hi_board_data_initialized; /* 0x58 */ + + u32 hi_dset_ram_index_table; /* 0x5c */ + + u32 hi_desired_baud_rate; /* 0x60 */ + u32 hi_dbglog_config; /* 0x64 */ + u32 hi_end_ram_reserve_sz; /* 0x68 */ + u32 hi_mbox_io_block_sz; /* 0x6c */ + + u32 hi_num_bpatch_streams; /* 0x70 -- unused */ + u32 hi_mbox_isr_yield_limit; /* 0x74 */ + + u32 hi_refclk_hz; /* 0x78 */ + u32 hi_ext_clk_detected; /* 0x7c */ + u32 hi_dbg_uart_txpin; /* 0x80 */ + u32 hi_dbg_uart_rxpin; /* 0x84 */ + u32 hi_hci_uart_baud; /* 0x88 */ + u32 hi_hci_uart_pin_assignments; /* 0x8C */ + + u32 hi_hci_uart_baud_scale_val; /* 0x90 */ + u32 hi_hci_uart_baud_step_val; /* 0x94 */ + + u32 hi_allocram_start; /* 0x98 */ + u32 hi_allocram_sz; /* 0x9c */ + u32 hi_hci_bridge_flags; /* 0xa0 */ + u32 hi_hci_uart_support_pins; /* 0xa4 */ + + u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */ + + /* + * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high + * [31:16]: wakeup timeout in ms + */ + /* Pointer to extended board Data */ + u32 hi_board_ext_data; /* 0xac */ + u32 hi_board_ext_data_config; /* 0xb0 */ + /* + * Bit [0] : valid + * Bit[31:16: size + */ + /* + * hi_reset_flag is used to do some stuff when target reset. + * such as restore app_start after warm reset or + * preserve host Interest area, or preserve ROM data, literals etc. + */ + u32 hi_reset_flag; /* 0xb4 */ + /* indicate hi_reset_flag is valid */ + u32 hi_reset_flag_valid; /* 0xb8 */ + u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */ + /* 0xbc - [31:0]: idle timeout in ms */ + /* ACS flags */ + u32 hi_acs_flags; /* 0xc0 */ + u32 hi_console_flags; /* 0xc4 */ + u32 hi_nvram_state; /* 0xc8 */ + u32 hi_option_flag2; /* 0xcc */ + + /* If non-zero, override values sent to Host in WMI_READY event. */ + u32 hi_sw_version_override; /* 0xd0 */ + u32 hi_abi_version_override; /* 0xd4 */ + + /* + * Percentage of high priority RX traffic to total expected RX traffic + * applicable only to ar6004 + */ + u32 hi_hp_rx_traffic_ratio; /* 0xd8 */ + + /* test applications flags */ + u32 hi_test_apps_related; /* 0xdc */ + /* location of test script */ + u32 hi_ota_testscript; /* 0xe0 */ + /* location of CAL data */ + u32 hi_cal_data; /* 0xe4 */ + + /* Number of packet log buffers */ + u32 hi_pktlog_num_buffers; /* 0xe8 */ + + /* wow extension configuration */ + u32 hi_wow_ext_config; /* 0xec */ + u32 hi_pwr_save_flags; /* 0xf0 */ + + /* Spatial Multiplexing Power Save (SMPS) options */ + u32 hi_smps_options; /* 0xf4 */ + + /* Interconnect-specific state */ + u32 hi_interconnect_state; /* 0xf8 */ + + /* Coex configuration flags */ + u32 hi_coex_config; /* 0xfc */ + + /* Early allocation support */ + u32 hi_early_alloc; /* 0x100 */ + /* FW swap field */ + /* + * Bits of this 32bit word will be used to pass specific swap + * instruction to FW + */ + /* + * Bit 0 -- AP Nart descriptor no swap. When this bit is set + * FW will not swap TX descriptor. Meaning packets are formed + * on the target processor. + */ + /* Bit 1 - unused */ + u32 hi_fw_swap; /* 0x104 */ +} __packed; + +#define HI_ITEM(item) offsetof(struct host_interest, item) + +/* Bits defined in hi_option_flag */ + +/* Enable timer workaround */ +#define HI_OPTION_TIMER_WAR 0x01 +/* Limit BMI command credits */ +#define HI_OPTION_BMI_CRED_LIMIT 0x02 +/* Relay Dot11 hdr to/from host */ +#define HI_OPTION_RELAY_DOT11_HDR 0x04 +/* MAC addr method 0-locally administred 1-globally unique addrs */ +#define HI_OPTION_MAC_ADDR_METHOD 0x08 +/* Firmware Bridging */ +#define HI_OPTION_FW_BRIDGE 0x10 +/* Enable CPU profiling */ +#define HI_OPTION_ENABLE_PROFILE 0x20 +/* Disable debug logging */ +#define HI_OPTION_DISABLE_DBGLOG 0x40 +/* Skip Era Tracking */ +#define HI_OPTION_SKIP_ERA_TRACKING 0x80 +/* Disable PAPRD (debug) */ +#define HI_OPTION_PAPRD_DISABLE 0x100 +#define HI_OPTION_NUM_DEV_LSB 0x200 +#define HI_OPTION_NUM_DEV_MSB 0x800 +#define HI_OPTION_DEV_MODE_LSB 0x1000 +#define HI_OPTION_DEV_MODE_MSB 0x8000000 +/* Disable LowFreq Timer Stabilization */ +#define HI_OPTION_NO_LFT_STBL 0x10000000 +/* Skip regulatory scan */ +#define HI_OPTION_SKIP_REG_SCAN 0x20000000 +/* + * Do regulatory scan during init before + * sending WMI ready event to host + */ +#define HI_OPTION_INIT_REG_SCAN 0x40000000 + +/* REV6: Do not adjust memory map */ +#define HI_OPTION_SKIP_MEMMAP 0x80000000 + +#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3 + +/* 2 bits of hi_option_flag are used to represent 3 modes */ +#define HI_OPTION_FW_MODE_IBSS 0x0 /* IBSS Mode */ +#define HI_OPTION_FW_MODE_BSS_STA 0x1 /* STA Mode */ +#define HI_OPTION_FW_MODE_AP 0x2 /* AP Mode */ +#define HI_OPTION_FW_MODE_BT30AMP 0x3 /* BT30 AMP Mode */ + +/* 2 bits of hi_option flag are usedto represent 4 submodes */ +#define HI_OPTION_FW_SUBMODE_NONE 0x0 /* Normal mode */ +#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1 /* p2p device mode */ +#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2 /* p2p client mode */ +#define HI_OPTION_FW_SUBMODE_P2PGO 0x3 /* p2p go mode */ + +/* Num dev Mask */ +#define HI_OPTION_NUM_DEV_MASK 0x7 +#define HI_OPTION_NUM_DEV_SHIFT 0x9 + +/* firmware bridging */ +#define HI_OPTION_FW_BRIDGE_SHIFT 0x04 + +/* +Fw Mode/SubMode Mask +|-----------------------------------------------------------------------------| +| SUB | SUB | SUB | SUB | | | | | +|MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0]| +| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | +|-----------------------------------------------------------------------------| +*/ +#define HI_OPTION_FW_MODE_BITS 0x2 +#define HI_OPTION_FW_MODE_MASK 0x3 +#define HI_OPTION_FW_MODE_SHIFT 0xC +#define HI_OPTION_ALL_FW_MODE_MASK 0xFF + +#define HI_OPTION_FW_SUBMODE_BITS 0x2 +#define HI_OPTION_FW_SUBMODE_MASK 0x3 +#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 +#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 +#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 + + +/* hi_option_flag2 options */ +#define HI_OPTION_OFFLOAD_AMSDU 0x01 +#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */ +#define HI_OPTION_ENABLE_RFKILL 0x04 /* RFKill Enable Feature*/ +#define HI_OPTION_RADIO_RETENTION_DISABLE 0x08 /* Disable radio retention */ +#define HI_OPTION_EARLY_CFG_DONE 0x10 /* Early configuration is complete */ + +#define HI_OPTION_RF_KILL_SHIFT 0x2 +#define HI_OPTION_RF_KILL_MASK 0x1 + +/* hi_reset_flag */ +/* preserve App Start address */ +#define HI_RESET_FLAG_PRESERVE_APP_START 0x01 +/* preserve host interest */ +#define HI_RESET_FLAG_PRESERVE_HOST_INTEREST 0x02 +/* preserve ROM data */ +#define HI_RESET_FLAG_PRESERVE_ROMDATA 0x04 +#define HI_RESET_FLAG_PRESERVE_NVRAM_STATE 0x08 +#define HI_RESET_FLAG_PRESERVE_BOOT_INFO 0x10 +#define HI_RESET_FLAG_WARM_RESET 0x20 + +/* define hi_fw_swap bits */ +#define HI_DESC_IN_FW_BIT 0x01 + +/* indicate the reset flag is valid */ +#define HI_RESET_FLAG_IS_VALID 0x12345678 + +/* ACS is enabled */ +#define HI_ACS_FLAGS_ENABLED (1 << 0) +/* Use physical WWAN device */ +#define HI_ACS_FLAGS_USE_WWAN (1 << 1) +/* Use test VAP */ +#define HI_ACS_FLAGS_TEST_VAP (1 << 2) + +/* + * CONSOLE FLAGS + * + * Bit Range Meaning + * --------- -------------------------------- + * 2..0 UART ID (0 = Default) + * 3 Baud Select (0 = 9600, 1 = 115200) + * 30..4 Reserved + * 31 Enable Console + * + */ + +#define HI_CONSOLE_FLAGS_ENABLE (1 << 31) +#define HI_CONSOLE_FLAGS_UART_MASK (0x7) +#define HI_CONSOLE_FLAGS_UART_SHIFT 0 +#define HI_CONSOLE_FLAGS_BAUD_SELECT (1 << 3) + +/* SM power save options */ +#define HI_SMPS_ALLOW_MASK (0x00000001) +#define HI_SMPS_MODE_MASK (0x00000002) +#define HI_SMPS_MODE_STATIC (0x00000000) +#define HI_SMPS_MODE_DYNAMIC (0x00000002) +#define HI_SMPS_DISABLE_AUTO_MODE (0x00000004) +#define HI_SMPS_DATA_THRESH_MASK (0x000007f8) +#define HI_SMPS_DATA_THRESH_SHIFT (3) +#define HI_SMPS_RSSI_THRESH_MASK (0x0007f800) +#define HI_SMPS_RSSI_THRESH_SHIFT (11) +#define HI_SMPS_LOWPWR_CM_MASK (0x00380000) +#define HI_SMPS_LOWPWR_CM_SHIFT (15) +#define HI_SMPS_HIPWR_CM_MASK (0x03c00000) +#define HI_SMPS_HIPWR_CM_SHIFT (19) + +/* + * WOW Extension configuration + * + * Bit Range Meaning + * --------- -------------------------------- + * 8..0 Size of each WOW pattern (max 511) + * 15..9 Number of patterns per list (max 127) + * 17..16 Number of lists (max 4) + * 30..18 Reserved + * 31 Enabled + * + * set values (except enable) to zeros for default settings + */ + +#define HI_WOW_EXT_ENABLED_MASK (1 << 31) +#define HI_WOW_EXT_NUM_LIST_SHIFT 16 +#define HI_WOW_EXT_NUM_LIST_MASK (0x3 << HI_WOW_EXT_NUM_LIST_SHIFT) +#define HI_WOW_EXT_NUM_PATTERNS_SHIFT 9 +#define HI_WOW_EXT_NUM_PATTERNS_MASK (0x7F << HI_WOW_EXT_NUM_PATTERNS_SHIFT) +#define HI_WOW_EXT_PATTERN_SIZE_SHIFT 0 +#define HI_WOW_EXT_PATTERN_SIZE_MASK (0x1FF << HI_WOW_EXT_PATTERN_SIZE_SHIFT) + +#define HI_WOW_EXT_MAKE_CONFIG(num_lists, count, size) \ + ((((num_lists) << HI_WOW_EXT_NUM_LIST_SHIFT) & \ + HI_WOW_EXT_NUM_LIST_MASK) | \ + (((count) << HI_WOW_EXT_NUM_PATTERNS_SHIFT) & \ + HI_WOW_EXT_NUM_PATTERNS_MASK) | \ + (((size) << HI_WOW_EXT_PATTERN_SIZE_SHIFT) & \ + HI_WOW_EXT_PATTERN_SIZE_MASK)) + +#define HI_WOW_EXT_GET_NUM_LISTS(config) \ + (((config) & HI_WOW_EXT_NUM_LIST_MASK) >> HI_WOW_EXT_NUM_LIST_SHIFT) +#define HI_WOW_EXT_GET_NUM_PATTERNS(config) \ + (((config) & HI_WOW_EXT_NUM_PATTERNS_MASK) >> \ + HI_WOW_EXT_NUM_PATTERNS_SHIFT) +#define HI_WOW_EXT_GET_PATTERN_SIZE(config) \ + (((config) & HI_WOW_EXT_PATTERN_SIZE_MASK) >> \ + HI_WOW_EXT_PATTERN_SIZE_SHIFT) + +/* + * Early allocation configuration + * Support RAM bank configuration before BMI done and this eases the memory + * allocation at very early stage + * Bit Range Meaning + * --------- ---------------------------------- + * [0:3] number of bank assigned to be IRAM + * [4:15] reserved + * [16:31] magic number + * + * Note: + * 1. target firmware would check magic number and if it's a match, firmware + * would consider the bits[0:15] are valid and base on that to calculate + * the end of DRAM. Early allocation would be located at that area and + * may be reclaimed when necesary + * 2. if no magic number is found, early allocation would happen at "_end" + * symbol of ROM which is located before the app-data and might NOT be + * re-claimable. If this is adopted, link script should keep this in + * mind to avoid data corruption. + */ +#define HI_EARLY_ALLOC_MAGIC 0x6d8a +#define HI_EARLY_ALLOC_MAGIC_MASK 0xffff0000 +#define HI_EARLY_ALLOC_MAGIC_SHIFT 16 +#define HI_EARLY_ALLOC_IRAM_BANKS_MASK 0x0000000f +#define HI_EARLY_ALLOC_IRAM_BANKS_SHIFT 0 + +#define HI_EARLY_ALLOC_VALID() \ + ((((HOST_INTEREST->hi_early_alloc) & HI_EARLY_ALLOC_MAGIC_MASK) >> \ + HI_EARLY_ALLOC_MAGIC_SHIFT) == (HI_EARLY_ALLOC_MAGIC)) +#define HI_EARLY_ALLOC_GET_IRAM_BANKS() \ + (((HOST_INTEREST->hi_early_alloc) & HI_EARLY_ALLOC_IRAM_BANKS_MASK) \ + >> HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) + +/*power save flag bit definitions*/ +#define HI_PWR_SAVE_LPL_ENABLED 0x1 +/*b1-b3 reserved*/ +/*b4-b5 : dev0 LPL type : 0 - none + 1- Reduce Pwr Search + 2- Reduce Pwr Listen*/ +/*b6-b7 : dev1 LPL type and so on for Max 8 devices*/ +#define HI_PWR_SAVE_LPL_DEV0_LSB 4 +#define HI_PWR_SAVE_LPL_DEV_MASK 0x3 +/*power save related utility macros*/ +#define HI_LPL_ENABLED() \ + ((HOST_INTEREST->hi_pwr_save_flags & HI_PWR_SAVE_LPL_ENABLED)) +#define HI_DEV_LPL_TYPE_GET(_devix) \ + (HOST_INTEREST->hi_pwr_save_flags & ((HI_PWR_SAVE_LPL_DEV_MASK) << \ + (HI_PWR_SAVE_LPL_DEV0_LSB + (_devix)*2))) + +#define HOST_INTEREST_SMPS_IS_ALLOWED() \ + ((HOST_INTEREST->hi_smps_options & HI_SMPS_ALLOW_MASK)) + +/* Reserve 1024 bytes for extended board data */ +#define QCA988X_BOARD_DATA_SZ 7168 +#define QCA988X_BOARD_EXT_DATA_SZ 0 + +#endif /* __TARGADDRS_H__ */ diff --git a/drivers/net/wireless/ath/ath10k/trace.c b/drivers/net/wireless/ath/ath10k/trace.c new file mode 100644 index 000000000000..4a31e2c6fbd4 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/trace.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h new file mode 100644 index 000000000000..85e806bf7257 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/trace.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) + +#include + +#define _TRACE_H_ + +/* create empty functions when tracing is disabled */ +#if !defined(CONFIG_ATH10K_TRACING) +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#undef DECLARE_EVENT_CLASS +#define DECLARE_EVENT_CLASS(...) +#undef DEFINE_EVENT +#define DEFINE_EVENT(evt_class, name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif /* !CONFIG_ATH10K_TRACING || __CHECKER__ */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ath10k + +#define ATH10K_MSG_MAX 200 + +DECLARE_EVENT_CLASS(ath10k_log_event, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf), + TP_STRUCT__entry( + __dynamic_array(char, msg, ATH10K_MSG_MAX) + ), + TP_fast_assign( + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + ATH10K_MSG_MAX, + vaf->fmt, + *vaf->va) >= ATH10K_MSG_MAX); + ), + TP_printk("%s", __get_str(msg)) +); + +DEFINE_EVENT(ath10k_log_event, ath10k_log_err, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(ath10k_log_event, ath10k_log_warn, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(ath10k_log_event, ath10k_log_info, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +TRACE_EVENT(ath10k_log_dbg, + TP_PROTO(unsigned int level, struct va_format *vaf), + TP_ARGS(level, vaf), + TP_STRUCT__entry( + __field(unsigned int, level) + __dynamic_array(char, msg, ATH10K_MSG_MAX) + ), + TP_fast_assign( + __entry->level = level; + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + ATH10K_MSG_MAX, + vaf->fmt, + *vaf->va) >= ATH10K_MSG_MAX); + ), + TP_printk("%s", __get_str(msg)) +); + +TRACE_EVENT(ath10k_log_dbg_dump, + TP_PROTO(const char *msg, const char *prefix, + const void *buf, size_t buf_len), + + TP_ARGS(msg, prefix, buf, buf_len), + + TP_STRUCT__entry( + __string(msg, msg) + __string(prefix, prefix) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __assign_str(msg, msg); + __assign_str(prefix, prefix); + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "%s/%s\n", __get_str(prefix), __get_str(msg) + ) +); + +TRACE_EVENT(ath10k_wmi_cmd, + TP_PROTO(int id, void *buf, size_t buf_len), + + TP_ARGS(id, buf, buf_len), + + TP_STRUCT__entry( + __field(unsigned int, id) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "id %d len %zu", + __entry->id, + __entry->buf_len + ) +); + +TRACE_EVENT(ath10k_wmi_event, + TP_PROTO(int id, void *buf, size_t buf_len), + + TP_ARGS(id, buf, buf_len), + + TP_STRUCT__entry( + __field(unsigned int, id) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->id = id; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "id %d len %zu", + __entry->id, + __entry->buf_len + ) +); + +#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ + +/* we don't want to use include/trace/events */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +/* This part must be outside protection */ +#include diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c new file mode 100644 index 000000000000..68b6faefd1d8 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" +#include "txrx.h" +#include "htt.h" +#include "mac.h" +#include "debug.h" + +static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) +{ + if (!ATH10K_SKB_CB(skb)->htt.is_offchan) + return; + + /* If the original wait_for_completion() timed out before + * {data,mgmt}_tx_completed() was called then we could complete + * offchan_tx_completed for a different skb. Prevent this by using + * offchan_tx_skb. */ + spin_lock_bh(&ar->data_lock); + if (ar->offchan_tx_skb != skb) { + ath10k_warn("completed old offchannel frame\n"); + goto out; + } + + complete(&ar->offchan_tx_completed); + ar->offchan_tx_skb = NULL; /* just for sanity */ + + ath10k_dbg(ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb); +out: + spin_unlock_bh(&ar->data_lock); +} + +void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) +{ + struct device *dev = htt->ar->dev; + struct ieee80211_tx_info *info; + struct sk_buff *txfrag = ATH10K_SKB_CB(txdesc)->htt.txfrag; + struct sk_buff *msdu = ATH10K_SKB_CB(txdesc)->htt.msdu; + int ret; + + if (ATH10K_SKB_CB(txdesc)->htt.refcount == 0) + return; + + ATH10K_SKB_CB(txdesc)->htt.refcount--; + + if (ATH10K_SKB_CB(txdesc)->htt.refcount > 0) + return; + + if (txfrag) { + ret = ath10k_skb_unmap(dev, txfrag); + if (ret) + ath10k_warn("txfrag unmap failed (%d)\n", ret); + + dev_kfree_skb_any(txfrag); + } + + ret = ath10k_skb_unmap(dev, msdu); + if (ret) + ath10k_warn("data skb unmap failed (%d)\n", ret); + + ath10k_report_offchan_tx(htt->ar, msdu); + + info = IEEE80211_SKB_CB(msdu); + memset(&info->status, 0, sizeof(info->status)); + + if (ATH10K_SKB_CB(txdesc)->htt.discard) { + ieee80211_free_txskb(htt->ar->hw, msdu); + goto exit; + } + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + if (ATH10K_SKB_CB(txdesc)->htt.no_ack) + info->flags &= ~IEEE80211_TX_STAT_ACK; + + ieee80211_tx_status(htt->ar->hw, msdu); + /* we do not own the msdu anymore */ + +exit: + spin_lock_bh(&htt->tx_lock); + htt->pending_tx[ATH10K_SKB_CB(txdesc)->htt.msdu_id] = NULL; + ath10k_htt_tx_free_msdu_id(htt, ATH10K_SKB_CB(txdesc)->htt.msdu_id); + __ath10k_htt_tx_dec_pending(htt); + if (bitmap_empty(htt->used_msdu_ids, htt->max_num_pending_tx)) + wake_up(&htt->empty_tx_wq); + spin_unlock_bh(&htt->tx_lock); + + dev_kfree_skb_any(txdesc); +} + +void ath10k_txrx_tx_completed(struct ath10k_htt *htt, + const struct htt_tx_done *tx_done) +{ + struct sk_buff *txdesc; + + ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", + tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); + + if (tx_done->msdu_id >= htt->max_num_pending_tx) { + ath10k_warn("warning: msdu_id %d too big, ignoring\n", + tx_done->msdu_id); + return; + } + + txdesc = htt->pending_tx[tx_done->msdu_id]; + + ATH10K_SKB_CB(txdesc)->htt.discard = tx_done->discard; + ATH10K_SKB_CB(txdesc)->htt.no_ack = tx_done->no_ack; + + ath10k_txrx_tx_unref(htt, txdesc); +} + +static const u8 rx_legacy_rate_idx[] = { + 3, /* 0x00 - 11Mbps */ + 2, /* 0x01 - 5.5Mbps */ + 1, /* 0x02 - 2Mbps */ + 0, /* 0x03 - 1Mbps */ + 3, /* 0x04 - 11Mbps */ + 2, /* 0x05 - 5.5Mbps */ + 1, /* 0x06 - 2Mbps */ + 0, /* 0x07 - 1Mbps */ + 10, /* 0x08 - 48Mbps */ + 8, /* 0x09 - 24Mbps */ + 6, /* 0x0A - 12Mbps */ + 4, /* 0x0B - 6Mbps */ + 11, /* 0x0C - 54Mbps */ + 9, /* 0x0D - 36Mbps */ + 7, /* 0x0E - 18Mbps */ + 5, /* 0x0F - 9Mbps */ +}; + +static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info, + enum ieee80211_band band, + struct ieee80211_rx_status *status) +{ + u8 cck, rate, rate_idx, bw, sgi, mcs, nss; + u8 info0 = info->rate.info0; + u32 info1 = info->rate.info1; + u32 info2 = info->rate.info2; + u8 preamble = 0; + + /* Check if valid fields */ + if (!(info0 & HTT_RX_INDICATION_INFO0_START_VALID)) + return; + + preamble = MS(info1, HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE); + + switch (preamble) { + case HTT_RX_LEGACY: + cck = info0 & HTT_RX_INDICATION_INFO0_LEGACY_RATE_CCK; + rate = MS(info0, HTT_RX_INDICATION_INFO0_LEGACY_RATE); + rate_idx = 0; + + if (rate < 0x08 || rate > 0x0F) + break; + + switch (band) { + case IEEE80211_BAND_2GHZ: + if (cck) + rate &= ~BIT(3); + rate_idx = rx_legacy_rate_idx[rate]; + break; + case IEEE80211_BAND_5GHZ: + rate_idx = rx_legacy_rate_idx[rate]; + /* We are using same rate table registering + HW - ath10k_rates[]. In case of 5GHz skip + CCK rates, so -4 here */ + rate_idx -= 4; + break; + default: + break; + } + + status->rate_idx = rate_idx; + break; + case HTT_RX_HT: + case HTT_RX_HT_WITH_TXBF: + /* HT-SIG - Table 20-11 in info1 and info2 */ + mcs = info1 & 0x1F; + nss = mcs >> 3; + bw = (info1 >> 7) & 1; + sgi = (info2 >> 7) & 1; + + status->rate_idx = mcs; + status->flag |= RX_FLAG_HT; + if (sgi) + status->flag |= RX_FLAG_SHORT_GI; + if (bw) + status->flag |= RX_FLAG_40MHZ; + break; + case HTT_RX_VHT: + case HTT_RX_VHT_WITH_TXBF: + /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2 + TODO check this */ + mcs = (info2 >> 4) & 0x0F; + nss = (info1 >> 10) & 0x07; + bw = info1 & 3; + sgi = info2 & 1; + + status->rate_idx = mcs; + status->vht_nss = nss; + + if (sgi) + status->flag |= RX_FLAG_SHORT_GI; + + switch (bw) { + /* 20MHZ */ + case 0: + break; + /* 40MHZ */ + case 1: + status->flag |= RX_FLAG_40MHZ; + break; + /* 80MHZ */ + case 2: + status->flag |= RX_FLAG_80MHZ; + } + + status->flag |= RX_FLAG_VHT; + break; + default: + break; + } +} + +void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) +{ + struct ieee80211_rx_status *status; + struct ieee80211_channel *ch; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)info->skb->data; + + status = IEEE80211_SKB_RXCB(info->skb); + memset(status, 0, sizeof(*status)); + + if (info->encrypt_type != HTT_RX_MPDU_ENCRYPT_NONE) { + status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | + RX_FLAG_MMIC_STRIPPED; + hdr->frame_control = __cpu_to_le16( + __le16_to_cpu(hdr->frame_control) & + ~IEEE80211_FCTL_PROTECTED); + } + + if (info->status == HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + + if (info->fcs_err) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + status->signal = info->signal; + + spin_lock_bh(&ar->data_lock); + ch = ar->scan_channel; + if (!ch) + ch = ar->rx_channel; + spin_unlock_bh(&ar->data_lock); + + if (!ch) { + ath10k_warn("no channel configured; ignoring frame!\n"); + dev_kfree_skb_any(info->skb); + return; + } + + process_rx_rates(ar, info, ch->band, status); + status->band = ch->band; + status->freq = ch->center_freq; + + ath10k_dbg(ATH10K_DBG_DATA, + "rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u\n", + info->skb, + info->skb->len, + status->flag == 0 ? "legacy" : "", + status->flag & RX_FLAG_HT ? "ht" : "", + status->flag & RX_FLAG_VHT ? "vht" : "", + status->flag & RX_FLAG_40MHZ ? "40" : "", + status->flag & RX_FLAG_80MHZ ? "80" : "", + status->flag & RX_FLAG_SHORT_GI ? "sgi " : "", + status->rate_idx, + status->vht_nss, + status->freq, + status->band); + + ieee80211_rx(ar->hw, info->skb); +} + +struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, + const u8 *addr) +{ + struct ath10k_peer *peer; + + lockdep_assert_held(&ar->data_lock); + + list_for_each_entry(peer, &ar->peers, list) { + if (peer->vdev_id != vdev_id) + continue; + if (memcmp(peer->addr, addr, ETH_ALEN)) + continue; + + return peer; + } + + return NULL; +} + +static struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, + int peer_id) +{ + struct ath10k_peer *peer; + + lockdep_assert_held(&ar->data_lock); + + list_for_each_entry(peer, &ar->peers, list) + if (test_bit(peer_id, peer->peer_ids)) + return peer; + + return NULL; +} + +static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, + const u8 *addr, bool expect_mapped) +{ + int ret; + + ret = wait_event_timeout(ar->peer_mapping_wq, ({ + bool mapped; + + spin_lock_bh(&ar->data_lock); + mapped = !!ath10k_peer_find(ar, vdev_id, addr); + spin_unlock_bh(&ar->data_lock); + + mapped == expect_mapped; + }), 3*HZ); + + if (ret <= 0) + return -ETIMEDOUT; + + return 0; +} + +int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, const u8 *addr) +{ + return ath10k_wait_for_peer_common(ar, vdev_id, addr, true); +} + +int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, const u8 *addr) +{ + return ath10k_wait_for_peer_common(ar, vdev_id, addr, false); +} + +void ath10k_peer_map_event(struct ath10k_htt *htt, + struct htt_peer_map_event *ev) +{ + struct ath10k *ar = htt->ar; + struct ath10k_peer *peer; + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr); + if (!peer) { + peer = kzalloc(sizeof(*peer), GFP_ATOMIC); + if (!peer) + goto exit; + + peer->vdev_id = ev->vdev_id; + memcpy(peer->addr, ev->addr, ETH_ALEN); + list_add(&peer->list, &ar->peers); + wake_up(&ar->peer_mapping_wq); + } + + ath10k_dbg(ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n", + ev->vdev_id, ev->addr, ev->peer_id); + + set_bit(ev->peer_id, peer->peer_ids); +exit: + spin_unlock_bh(&ar->data_lock); +} + +void ath10k_peer_unmap_event(struct ath10k_htt *htt, + struct htt_peer_unmap_event *ev) +{ + struct ath10k *ar = htt->ar; + struct ath10k_peer *peer; + + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find_by_id(ar, ev->peer_id); + if (!peer) { + ath10k_warn("unknown peer id %d\n", ev->peer_id); + goto exit; + } + + ath10k_dbg(ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n", + peer->vdev_id, peer->addr, ev->peer_id); + + clear_bit(ev->peer_id, peer->peer_ids); + + if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) { + list_del(&peer->list); + kfree(peer); + wake_up(&ar->peer_mapping_wq); + } + +exit: + spin_unlock_bh(&ar->data_lock); +} diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h new file mode 100644 index 000000000000..e78632a76df7 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/txrx.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef _TXRX_H_ +#define _TXRX_H_ + +#include "htt.h" + +void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc); +void ath10k_txrx_tx_completed(struct ath10k_htt *htt, + const struct htt_tx_done *tx_done); +void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info); + +struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, + const u8 *addr); +int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, + const u8 *addr); +int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, + const u8 *addr); + +void ath10k_peer_map_event(struct ath10k_htt *htt, + struct htt_peer_map_event *ev); +void ath10k_peer_unmap_event(struct ath10k_htt *htt, + struct htt_peer_unmap_event *ev); + +#endif diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c new file mode 100644 index 000000000000..7d4b7987422d --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -0,0 +1,2081 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "core.h" +#include "htc.h" +#include "debug.h" +#include "wmi.h" +#include "mac.h" + +void ath10k_wmi_flush_tx(struct ath10k *ar) +{ + int ret; + + ret = wait_event_timeout(ar->wmi.wq, + atomic_read(&ar->wmi.pending_tx_count) == 0, + 5*HZ); + if (atomic_read(&ar->wmi.pending_tx_count) == 0) + return; + + if (ret == 0) + ret = -ETIMEDOUT; + + if (ret < 0) + ath10k_warn("wmi flush failed (%d)\n", ret); +} + +int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) +{ + int ret; + ret = wait_for_completion_timeout(&ar->wmi.service_ready, + WMI_SERVICE_READY_TIMEOUT_HZ); + return ret; +} + +int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) +{ + int ret; + ret = wait_for_completion_timeout(&ar->wmi.unified_ready, + WMI_UNIFIED_READY_TIMEOUT_HZ); + return ret; +} + +static struct sk_buff *ath10k_wmi_alloc_skb(u32 len) +{ + struct sk_buff *skb; + u32 round_len = roundup(len, 4); + + skb = ath10k_htc_alloc_skb(WMI_SKB_HEADROOM + round_len); + if (!skb) + return NULL; + + skb_reserve(skb, WMI_SKB_HEADROOM); + if (!IS_ALIGNED((unsigned long)skb->data, 4)) + ath10k_warn("Unaligned WMI skb\n"); + + skb_put(skb, round_len); + memset(skb->data, 0, round_len); + + return skb; +} + +static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) +{ + dev_kfree_skb(skb); + + if (atomic_sub_return(1, &ar->wmi.pending_tx_count) == 0) + wake_up(&ar->wmi.wq); +} + +/* WMI command API */ +static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, + enum wmi_cmd_id cmd_id) +{ + struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); + struct wmi_cmd_hdr *cmd_hdr; + int status; + u32 cmd = 0; + + if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL) + return -ENOMEM; + + cmd |= SM(cmd_id, WMI_CMD_HDR_CMD_ID); + + cmd_hdr = (struct wmi_cmd_hdr *)skb->data; + cmd_hdr->cmd_id = __cpu_to_le32(cmd); + + if (atomic_add_return(1, &ar->wmi.pending_tx_count) > + WMI_MAX_PENDING_TX_COUNT) { + /* avoid using up memory when FW hangs */ + atomic_dec(&ar->wmi.pending_tx_count); + return -EBUSY; + } + + memset(skb_cb, 0, sizeof(*skb_cb)); + + trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len); + + status = ath10k_htc_send(ar->htc, ar->wmi.eid, skb); + if (status) { + dev_kfree_skb_any(skb); + atomic_dec(&ar->wmi.pending_tx_count); + return status; + } + + return 0; +} + +static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; + enum wmi_scan_event_type event_type; + enum wmi_scan_completion_reason reason; + u32 freq; + u32 req_id; + u32 scan_id; + u32 vdev_id; + + event_type = __le32_to_cpu(event->event_type); + reason = __le32_to_cpu(event->reason); + freq = __le32_to_cpu(event->channel_freq); + req_id = __le32_to_cpu(event->scan_req_id); + scan_id = __le32_to_cpu(event->scan_id); + vdev_id = __le32_to_cpu(event->vdev_id); + + ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENTID\n"); + ath10k_dbg(ATH10K_DBG_WMI, + "scan event type %d reason %d freq %d req_id %d " + "scan_id %d vdev_id %d\n", + event_type, reason, freq, req_id, scan_id, vdev_id); + + spin_lock_bh(&ar->data_lock); + + switch (event_type) { + case WMI_SCAN_EVENT_STARTED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_STARTED\n"); + if (ar->scan.in_progress && ar->scan.is_roc) + ieee80211_ready_on_channel(ar->hw); + + complete(&ar->scan.started); + break; + case WMI_SCAN_EVENT_COMPLETED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_COMPLETED\n"); + switch (reason) { + case WMI_SCAN_REASON_COMPLETED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_COMPLETED\n"); + break; + case WMI_SCAN_REASON_CANCELLED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_CANCELED\n"); + break; + case WMI_SCAN_REASON_PREEMPTED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_PREEMPTED\n"); + break; + case WMI_SCAN_REASON_TIMEDOUT: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_REASON_TIMEDOUT\n"); + break; + default: + break; + } + + ar->scan_channel = NULL; + if (!ar->scan.in_progress) { + ath10k_warn("no scan requested, ignoring\n"); + break; + } + + if (ar->scan.is_roc) { + ath10k_offchan_tx_purge(ar); + + if (!ar->scan.aborting) + ieee80211_remain_on_channel_expired(ar->hw); + } else { + ieee80211_scan_completed(ar->hw, ar->scan.aborting); + } + + del_timer(&ar->scan.timeout); + complete_all(&ar->scan.completed); + ar->scan.in_progress = false; + break; + case WMI_SCAN_EVENT_BSS_CHANNEL: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_BSS_CHANNEL\n"); + ar->scan_channel = NULL; + break; + case WMI_SCAN_EVENT_FOREIGN_CHANNEL: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n"); + ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); + if (ar->scan.in_progress && ar->scan.is_roc && + ar->scan.roc_freq == freq) { + complete(&ar->scan.on_channel); + } + break; + case WMI_SCAN_EVENT_DEQUEUED: + ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n"); + break; + case WMI_SCAN_EVENT_PREEMPTED: + ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_PREEMPTED\n"); + break; + case WMI_SCAN_EVENT_START_FAILED: + ath10k_dbg(ATH10K_DBG_WMI, "WMI_SCAN_EVENT_START_FAILED\n"); + break; + default: + break; + } + + spin_unlock_bh(&ar->data_lock); + return 0; +} + +static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode) +{ + enum ieee80211_band band; + + switch (phy_mode) { + case MODE_11A: + case MODE_11NA_HT20: + case MODE_11NA_HT40: + case MODE_11AC_VHT20: + case MODE_11AC_VHT40: + case MODE_11AC_VHT80: + band = IEEE80211_BAND_5GHZ; + break; + case MODE_11G: + case MODE_11B: + case MODE_11GONLY: + case MODE_11NG_HT20: + case MODE_11NG_HT40: + case MODE_11AC_VHT20_2G: + case MODE_11AC_VHT40_2G: + case MODE_11AC_VHT80_2G: + default: + band = IEEE80211_BAND_2GHZ; + } + + return band; +} + +static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band) +{ + u8 rate_idx = 0; + + /* rate in Kbps */ + switch (rate) { + case 1000: + rate_idx = 0; + break; + case 2000: + rate_idx = 1; + break; + case 5500: + rate_idx = 2; + break; + case 11000: + rate_idx = 3; + break; + case 6000: + rate_idx = 4; + break; + case 9000: + rate_idx = 5; + break; + case 12000: + rate_idx = 6; + break; + case 18000: + rate_idx = 7; + break; + case 24000: + rate_idx = 8; + break; + case 36000: + rate_idx = 9; + break; + case 48000: + rate_idx = 10; + break; + case 54000: + rate_idx = 11; + break; + default: + break; + } + + if (band == IEEE80211_BAND_5GHZ) { + if (rate_idx > 3) + /* Omit CCK rates */ + rate_idx -= 4; + else + rate_idx = 0; + } + + return rate_idx; +} + +static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_mgmt_rx_event *event = (struct wmi_mgmt_rx_event *)skb->data; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_hdr *hdr; + u32 rx_status; + u32 channel; + u32 phy_mode; + u32 snr; + u32 rate; + u32 buf_len; + u16 fc; + + channel = __le32_to_cpu(event->hdr.channel); + buf_len = __le32_to_cpu(event->hdr.buf_len); + rx_status = __le32_to_cpu(event->hdr.status); + snr = __le32_to_cpu(event->hdr.snr); + phy_mode = __le32_to_cpu(event->hdr.phy_mode); + rate = __le32_to_cpu(event->hdr.rate); + + memset(status, 0, sizeof(*status)); + + ath10k_dbg(ATH10K_DBG_MGMT, + "event mgmt rx status %08x\n", rx_status); + + if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) { + dev_kfree_skb(skb); + return 0; + } + + if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) { + dev_kfree_skb(skb); + return 0; + } + + if (rx_status & WMI_RX_STATUS_ERR_CRC) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_status & WMI_RX_STATUS_ERR_MIC) + status->flag |= RX_FLAG_MMIC_ERROR; + + status->band = phy_mode_to_band(phy_mode); + status->freq = ieee80211_channel_to_frequency(channel, status->band); + status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; + status->rate_idx = get_rate_idx(rate, status->band); + + skb_pull(skb, sizeof(event->hdr)); + + hdr = (struct ieee80211_hdr *)skb->data; + fc = le16_to_cpu(hdr->frame_control); + + if (fc & IEEE80211_FCTL_PROTECTED) { + status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED | + RX_FLAG_MMIC_STRIPPED; + hdr->frame_control = __cpu_to_le16(fc & + ~IEEE80211_FCTL_PROTECTED); + } + + ath10k_dbg(ATH10K_DBG_MGMT, + "event mgmt rx skb %p len %d ftype %02x stype %02x\n", + skb, skb->len, + fc & IEEE80211_FCTL_FTYPE, fc & IEEE80211_FCTL_STYPE); + + ath10k_dbg(ATH10K_DBG_MGMT, + "event mgmt rx freq %d band %d snr %d, rate_idx %d\n", + status->freq, status->band, status->signal, + status->rate_idx); + + /* + * packets from HTC come aligned to 4byte boundaries + * because they can originally come in along with a trailer + */ + skb_trim(skb, buf_len); + + ieee80211_rx(ar->hw, skb); + return 0; +} + +static void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_CHAN_INFO_EVENTID\n"); +} + +static void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_ECHO_EVENTID\n"); +} + +static void ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_MESG_EVENTID\n"); +} + +static void ath10k_wmi_event_update_stats(struct ath10k *ar, + struct sk_buff *skb) +{ + struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data; + + ath10k_dbg(ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); + + ath10k_debug_read_target_stats(ar, ev); +} + +static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, + struct sk_buff *skb) +{ + struct wmi_vdev_start_response_event *ev; + + ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_START_RESP_EVENTID\n"); + + ev = (struct wmi_vdev_start_response_event *)skb->data; + + if (WARN_ON(__le32_to_cpu(ev->status))) + return; + + complete(&ar->vdev_setup_done); +} + +static void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_STOPPED_EVENTID\n"); + complete(&ar->vdev_setup_done); +} + +static void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PEER_STA_KICKOUT_EVENTID\n"); +} + +/* + * FIXME + * + * We don't report to mac80211 sleep state of connected + * stations. Due to this mac80211 can't fill in TIM IE + * correctly. + * + * I know of no way of getting nullfunc frames that contain + * sleep transition from connected stations - these do not + * seem to be sent from the target to the host. There also + * doesn't seem to be a dedicated event for that. So the + * only way left to do this would be to read tim_bitmap + * during SWBA. + * + * We could probably try using tim_bitmap from SWBA to tell + * mac80211 which stations are asleep and which are not. The + * problem here is calling mac80211 functions so many times + * could take too long and make us miss the time to submit + * the beacon to the target. + * + * So as a workaround we try to extend the TIM IE if there + * is unicast buffered for stations with aid > 7 and fill it + * in ourselves. + */ +static void ath10k_wmi_update_tim(struct ath10k *ar, + struct ath10k_vif *arvif, + struct sk_buff *bcn, + struct wmi_bcn_info *bcn_info) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data; + struct ieee80211_tim_ie *tim; + u8 *ies, *ie; + u8 ie_len, pvm_len; + + /* if next SWBA has no tim_changed the tim_bitmap is garbage. + * we must copy the bitmap upon change and reuse it later */ + if (__le32_to_cpu(bcn_info->tim_info.tim_changed)) { + int i; + + BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) != + sizeof(bcn_info->tim_info.tim_bitmap)); + + for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) { + __le32 t = bcn_info->tim_info.tim_bitmap[i / 4]; + u32 v = __le32_to_cpu(t); + arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF; + } + + /* FW reports either length 0 or 16 + * so we calculate this on our own */ + arvif->u.ap.tim_len = 0; + for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) + if (arvif->u.ap.tim_bitmap[i]) + arvif->u.ap.tim_len = i; + + arvif->u.ap.tim_len++; + } + + ies = bcn->data; + ies += ieee80211_hdrlen(hdr->frame_control); + ies += 12; /* fixed parameters */ + + ie = (u8 *)cfg80211_find_ie(WLAN_EID_TIM, ies, + (u8 *)skb_tail_pointer(bcn) - ies); + if (!ie) { + /* highly unlikely for mac80211 */ + ath10k_warn("no tim ie found;\n"); + return; + } + + tim = (void *)ie + 2; + ie_len = ie[1]; + pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */ + + if (pvm_len < arvif->u.ap.tim_len) { + int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len; + int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len); + void *next_ie = ie + 2 + ie_len; + + if (skb_put(bcn, expand_size)) { + memmove(next_ie + expand_size, next_ie, move_size); + + ie[1] += expand_size; + ie_len += expand_size; + pvm_len += expand_size; + } else { + ath10k_warn("tim expansion failed\n"); + } + } + + if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) { + ath10k_warn("tim pvm length is too great (%d)\n", pvm_len); + return; + } + + tim->bitmap_ctrl = !!__le32_to_cpu(bcn_info->tim_info.tim_mcast); + memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len); + + ath10k_dbg(ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n", + tim->dtim_count, tim->dtim_period, + tim->bitmap_ctrl, pvm_len); +} + +static void ath10k_p2p_fill_noa_ie(u8 *data, u32 len, + struct wmi_p2p_noa_info *noa) +{ + struct ieee80211_p2p_noa_attr *noa_attr; + u8 ctwindow_oppps = noa->ctwindow_oppps; + u8 ctwindow = ctwindow_oppps >> WMI_P2P_OPPPS_CTWINDOW_OFFSET; + bool oppps = !!(ctwindow_oppps & WMI_P2P_OPPPS_ENABLE_BIT); + __le16 *noa_attr_len; + u16 attr_len; + u8 noa_descriptors = noa->num_descriptors; + int i; + + /* P2P IE */ + data[0] = WLAN_EID_VENDOR_SPECIFIC; + data[1] = len - 2; + data[2] = (WLAN_OUI_WFA >> 16) & 0xff; + data[3] = (WLAN_OUI_WFA >> 8) & 0xff; + data[4] = (WLAN_OUI_WFA >> 0) & 0xff; + data[5] = WLAN_OUI_TYPE_WFA_P2P; + + /* NOA ATTR */ + data[6] = IEEE80211_P2P_ATTR_ABSENCE_NOTICE; + noa_attr_len = (__le16 *)&data[7]; /* 2 bytes */ + noa_attr = (struct ieee80211_p2p_noa_attr *)&data[9]; + + noa_attr->index = noa->index; + noa_attr->oppps_ctwindow = ctwindow; + if (oppps) + noa_attr->oppps_ctwindow |= IEEE80211_P2P_OPPPS_ENABLE_BIT; + + for (i = 0; i < noa_descriptors; i++) { + noa_attr->desc[i].count = + __le32_to_cpu(noa->descriptors[i].type_count); + noa_attr->desc[i].duration = noa->descriptors[i].duration; + noa_attr->desc[i].interval = noa->descriptors[i].interval; + noa_attr->desc[i].start_time = noa->descriptors[i].start_time; + } + + attr_len = 2; /* index + oppps_ctwindow */ + attr_len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); + *noa_attr_len = __cpu_to_le16(attr_len); +} + +static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa) +{ + u32 len = 0; + u8 noa_descriptors = noa->num_descriptors; + u8 opp_ps_info = noa->ctwindow_oppps; + bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT); + + + if (!noa_descriptors && !opps_enabled) + return len; + + len += 1 + 1 + 4; /* EID + len + OUI */ + len += 1 + 2; /* noa attr + attr len */ + len += 1 + 1; /* index + oppps_ctwindow */ + len += noa_descriptors * sizeof(struct ieee80211_p2p_noa_desc); + + return len; +} + +static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, + struct sk_buff *bcn, + struct wmi_bcn_info *bcn_info) +{ + struct wmi_p2p_noa_info *noa = &bcn_info->p2p_noa_info; + u8 *new_data, *old_data = arvif->u.ap.noa_data; + u32 new_len; + + if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + return; + + ath10k_dbg(ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); + if (noa->changed & WMI_P2P_NOA_CHANGED_BIT) { + new_len = ath10k_p2p_calc_noa_ie_len(noa); + if (!new_len) + goto cleanup; + + new_data = kmalloc(new_len, GFP_ATOMIC); + if (!new_data) + goto cleanup; + + ath10k_p2p_fill_noa_ie(new_data, new_len, noa); + + spin_lock_bh(&ar->data_lock); + arvif->u.ap.noa_data = new_data; + arvif->u.ap.noa_len = new_len; + spin_unlock_bh(&ar->data_lock); + kfree(old_data); + } + + if (arvif->u.ap.noa_data) + if (!pskb_expand_head(bcn, 0, arvif->u.ap.noa_len, GFP_ATOMIC)) + memcpy(skb_put(bcn, arvif->u.ap.noa_len), + arvif->u.ap.noa_data, + arvif->u.ap.noa_len); + return; + +cleanup: + spin_lock_bh(&ar->data_lock); + arvif->u.ap.noa_data = NULL; + arvif->u.ap.noa_len = 0; + spin_unlock_bh(&ar->data_lock); + kfree(old_data); +} + + +static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_host_swba_event *ev; + u32 map; + int i = -1; + struct wmi_bcn_info *bcn_info; + struct ath10k_vif *arvif; + struct wmi_bcn_tx_arg arg; + struct sk_buff *bcn; + int vdev_id = 0; + int ret; + + ath10k_dbg(ATH10K_DBG_MGMT, "WMI_HOST_SWBA_EVENTID\n"); + + ev = (struct wmi_host_swba_event *)skb->data; + map = __le32_to_cpu(ev->vdev_map); + + ath10k_dbg(ATH10K_DBG_MGMT, "host swba:\n" + "-vdev map 0x%x\n", + ev->vdev_map); + + for (; map; map >>= 1, vdev_id++) { + if (!(map & 0x1)) + continue; + + i++; + + if (i >= WMI_MAX_AP_VDEV) { + ath10k_warn("swba has corrupted vdev map\n"); + break; + } + + bcn_info = &ev->bcn_info[i]; + + ath10k_dbg(ATH10K_DBG_MGMT, + "-bcn_info[%d]:\n" + "--tim_len %d\n" + "--tim_mcast %d\n" + "--tim_changed %d\n" + "--tim_num_ps_pending %d\n" + "--tim_bitmap 0x%08x%08x%08x%08x\n", + i, + __le32_to_cpu(bcn_info->tim_info.tim_len), + __le32_to_cpu(bcn_info->tim_info.tim_mcast), + __le32_to_cpu(bcn_info->tim_info.tim_changed), + __le32_to_cpu(bcn_info->tim_info.tim_num_ps_pending), + __le32_to_cpu(bcn_info->tim_info.tim_bitmap[3]), + __le32_to_cpu(bcn_info->tim_info.tim_bitmap[2]), + __le32_to_cpu(bcn_info->tim_info.tim_bitmap[1]), + __le32_to_cpu(bcn_info->tim_info.tim_bitmap[0])); + + arvif = ath10k_get_arvif(ar, vdev_id); + if (arvif == NULL) { + ath10k_warn("no vif for vdev_id %d found\n", vdev_id); + continue; + } + + bcn = ieee80211_beacon_get(ar->hw, arvif->vif); + if (!bcn) { + ath10k_warn("could not get mac80211 beacon\n"); + continue; + } + + ath10k_tx_h_seq_no(bcn); + ath10k_wmi_update_tim(ar, arvif, bcn, bcn_info); + ath10k_wmi_update_noa(ar, arvif, bcn, bcn_info); + + arg.vdev_id = arvif->vdev_id; + arg.tx_rate = 0; + arg.tx_power = 0; + arg.bcn = bcn->data; + arg.bcn_len = bcn->len; + + ret = ath10k_wmi_beacon_send(ar, &arg); + if (ret) + ath10k_warn("could not send beacon (%d)\n", ret); + + dev_kfree_skb_any(bcn); + } +} + +static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n"); +} + +static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PHYERR_EVENTID\n"); +} + +static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_ROAM_EVENTID\n"); +} + +static void ath10k_wmi_event_profile_match(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n"); +} + +static void ath10k_wmi_event_debug_print(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_DEBUG_PRINT_EVENTID\n"); +} + +static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_QVIT_EVENTID\n"); +} + +static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_WLAN_PROFILE_DATA_EVENTID\n"); +} + +static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n"); +} + +static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n"); +} + +static void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_RTT_ERROR_REPORT_EVENTID\n"); +} + +static void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_WOW_WAKEUP_HOST_EVENTID\n"); +} + +static void ath10k_wmi_event_dcs_interference(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n"); +} + +static void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n"); +} + +static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n"); +} + +static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n"); +} + +static void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_GTK_REKEY_FAIL_EVENTID\n"); +} + +static void ath10k_wmi_event_delba_complete(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_DELBA_COMPLETE_EVENTID\n"); +} + +static void ath10k_wmi_event_addba_complete(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_TX_ADDBA_COMPLETE_EVENTID\n"); +} + +static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, + struct sk_buff *skb) +{ + ath10k_dbg(ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); +} + +static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, + struct sk_buff *skb) +{ + struct wmi_service_ready_event *ev = (void *)skb->data; + + if (skb->len < sizeof(*ev)) { + ath10k_warn("Service ready event was %d B but expected %zu B. Wrong firmware version?\n", + skb->len, sizeof(*ev)); + return; + } + + ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); + ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); + ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); + ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); + ar->fw_version_major = + (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; + ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); + ar->fw_version_release = + (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; + ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); + ar->phy_capability = __le32_to_cpu(ev->phy_capability); + + ar->ath_common.regulatory.current_rd = + __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); + + ath10k_debug_read_service_map(ar, ev->wmi_service_bitmap, + sizeof(ev->wmi_service_bitmap)); + + if (strlen(ar->hw->wiphy->fw_version) == 0) { + snprintf(ar->hw->wiphy->fw_version, + sizeof(ar->hw->wiphy->fw_version), + "%u.%u.%u.%u", + ar->fw_version_major, + ar->fw_version_minor, + ar->fw_version_release, + ar->fw_version_build); + } + + /* FIXME: it probably should be better to support this */ + if (__le32_to_cpu(ev->num_mem_reqs) > 0) { + ath10k_warn("target requested %d memory chunks; ignoring\n", + __le32_to_cpu(ev->num_mem_reqs)); + } + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u\n", + __le32_to_cpu(ev->sw_version), + __le32_to_cpu(ev->sw_version_1), + __le32_to_cpu(ev->abi_version), + __le32_to_cpu(ev->phy_capability), + __le32_to_cpu(ev->ht_cap_info), + __le32_to_cpu(ev->vht_cap_info), + __le32_to_cpu(ev->vht_supp_mcs), + __le32_to_cpu(ev->sys_cap_info), + __le32_to_cpu(ev->num_mem_reqs)); + + complete(&ar->wmi.service_ready); +} + +static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; + + if (WARN_ON(skb->len < sizeof(*ev))) + return -EINVAL; + + memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n", + __le32_to_cpu(ev->sw_version), + __le32_to_cpu(ev->abi_version), + ev->mac_addr.addr, + __le32_to_cpu(ev->status)); + + complete(&ar->wmi.unified_ready); + return 0; +} + +static void ath10k_wmi_event_process(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_cmd_hdr *cmd_hdr; + enum wmi_event_id id; + u16 len; + + cmd_hdr = (struct wmi_cmd_hdr *)skb->data; + id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); + + if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) + return; + + len = skb->len; + + trace_ath10k_wmi_event(id, skb->data, skb->len); + + switch (id) { + case WMI_MGMT_RX_EVENTID: + ath10k_wmi_event_mgmt_rx(ar, skb); + /* mgmt_rx() owns the skb now! */ + return; + case WMI_SCAN_EVENTID: + ath10k_wmi_event_scan(ar, skb); + break; + case WMI_CHAN_INFO_EVENTID: + ath10k_wmi_event_chan_info(ar, skb); + break; + case WMI_ECHO_EVENTID: + ath10k_wmi_event_echo(ar, skb); + break; + case WMI_DEBUG_MESG_EVENTID: + ath10k_wmi_event_debug_mesg(ar, skb); + break; + case WMI_UPDATE_STATS_EVENTID: + ath10k_wmi_event_update_stats(ar, skb); + break; + case WMI_VDEV_START_RESP_EVENTID: + ath10k_wmi_event_vdev_start_resp(ar, skb); + break; + case WMI_VDEV_STOPPED_EVENTID: + ath10k_wmi_event_vdev_stopped(ar, skb); + break; + case WMI_PEER_STA_KICKOUT_EVENTID: + ath10k_wmi_event_peer_sta_kickout(ar, skb); + break; + case WMI_HOST_SWBA_EVENTID: + ath10k_wmi_event_host_swba(ar, skb); + break; + case WMI_TBTTOFFSET_UPDATE_EVENTID: + ath10k_wmi_event_tbttoffset_update(ar, skb); + break; + case WMI_PHYERR_EVENTID: + ath10k_wmi_event_phyerr(ar, skb); + break; + case WMI_ROAM_EVENTID: + ath10k_wmi_event_roam(ar, skb); + break; + case WMI_PROFILE_MATCH: + ath10k_wmi_event_profile_match(ar, skb); + break; + case WMI_DEBUG_PRINT_EVENTID: + ath10k_wmi_event_debug_print(ar, skb); + break; + case WMI_PDEV_QVIT_EVENTID: + ath10k_wmi_event_pdev_qvit(ar, skb); + break; + case WMI_WLAN_PROFILE_DATA_EVENTID: + ath10k_wmi_event_wlan_profile_data(ar, skb); + break; + case WMI_RTT_MEASUREMENT_REPORT_EVENTID: + ath10k_wmi_event_rtt_measurement_report(ar, skb); + break; + case WMI_TSF_MEASUREMENT_REPORT_EVENTID: + ath10k_wmi_event_tsf_measurement_report(ar, skb); + break; + case WMI_RTT_ERROR_REPORT_EVENTID: + ath10k_wmi_event_rtt_error_report(ar, skb); + break; + case WMI_WOW_WAKEUP_HOST_EVENTID: + ath10k_wmi_event_wow_wakeup_host(ar, skb); + break; + case WMI_DCS_INTERFERENCE_EVENTID: + ath10k_wmi_event_dcs_interference(ar, skb); + break; + case WMI_PDEV_TPC_CONFIG_EVENTID: + ath10k_wmi_event_pdev_tpc_config(ar, skb); + break; + case WMI_PDEV_FTM_INTG_EVENTID: + ath10k_wmi_event_pdev_ftm_intg(ar, skb); + break; + case WMI_GTK_OFFLOAD_STATUS_EVENTID: + ath10k_wmi_event_gtk_offload_status(ar, skb); + break; + case WMI_GTK_REKEY_FAIL_EVENTID: + ath10k_wmi_event_gtk_rekey_fail(ar, skb); + break; + case WMI_TX_DELBA_COMPLETE_EVENTID: + ath10k_wmi_event_delba_complete(ar, skb); + break; + case WMI_TX_ADDBA_COMPLETE_EVENTID: + ath10k_wmi_event_addba_complete(ar, skb); + break; + case WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID: + ath10k_wmi_event_vdev_install_key_complete(ar, skb); + break; + case WMI_SERVICE_READY_EVENTID: + ath10k_wmi_service_ready_event_rx(ar, skb); + break; + case WMI_READY_EVENTID: + ath10k_wmi_ready_event_rx(ar, skb); + break; + default: + ath10k_warn("Unknown eventid: %d\n", id); + break; + } + + dev_kfree_skb(skb); +} + +static void ath10k_wmi_event_work(struct work_struct *work) +{ + struct ath10k *ar = container_of(work, struct ath10k, + wmi.wmi_event_work); + struct sk_buff *skb; + + for (;;) { + skb = skb_dequeue(&ar->wmi.wmi_event_list); + if (!skb) + break; + + ath10k_wmi_event_process(ar, skb); + } +} + +static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_cmd_hdr *cmd_hdr = (struct wmi_cmd_hdr *)skb->data; + enum wmi_event_id event_id; + + event_id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); + + /* some events require to be handled ASAP + * thus can't be defered to a worker thread */ + switch (event_id) { + case WMI_HOST_SWBA_EVENTID: + case WMI_MGMT_RX_EVENTID: + ath10k_wmi_event_process(ar, skb); + return; + default: + break; + } + + skb_queue_tail(&ar->wmi.wmi_event_list, skb); + queue_work(ar->workqueue, &ar->wmi.wmi_event_work); +} + +/* WMI Initialization functions */ +int ath10k_wmi_attach(struct ath10k *ar) +{ + init_completion(&ar->wmi.service_ready); + init_completion(&ar->wmi.unified_ready); + init_waitqueue_head(&ar->wmi.wq); + + skb_queue_head_init(&ar->wmi.wmi_event_list); + INIT_WORK(&ar->wmi.wmi_event_work, ath10k_wmi_event_work); + + return 0; +} + +void ath10k_wmi_detach(struct ath10k *ar) +{ + /* HTC should've drained the packets already */ + if (WARN_ON(atomic_read(&ar->wmi.pending_tx_count) > 0)) + ath10k_warn("there are still pending packets\n"); + + cancel_work_sync(&ar->wmi.wmi_event_work); + skb_queue_purge(&ar->wmi.wmi_event_list); +} + +int ath10k_wmi_connect_htc_service(struct ath10k *ar) +{ + int status; + struct ath10k_htc_svc_conn_req conn_req; + struct ath10k_htc_svc_conn_resp conn_resp; + + memset(&conn_req, 0, sizeof(conn_req)); + memset(&conn_resp, 0, sizeof(conn_resp)); + + /* these fields are the same for all service endpoints */ + conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete; + conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx; + + /* connect to control service */ + conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; + + status = ath10k_htc_connect_service(ar->htc, &conn_req, &conn_resp); + if (status) { + ath10k_warn("failed to connect to WMI CONTROL service status: %d\n", + status); + return status; + } + + ar->wmi.eid = conn_resp.eid; + return 0; +} + +int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, + u16 rd5g, u16 ctl2g, u16 ctl5g) +{ + struct wmi_pdev_set_regdomain_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_set_regdomain_cmd *)skb->data; + cmd->reg_domain = __cpu_to_le32(rd); + cmd->reg_domain_2G = __cpu_to_le32(rd2g); + cmd->reg_domain_5G = __cpu_to_le32(rd5g); + cmd->conformance_test_limit_2G = __cpu_to_le32(ctl2g); + cmd->conformance_test_limit_5G = __cpu_to_le32(ctl5g); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi pdev regdomain rd %x rd2g %x rd5g %x ctl2g %x ctl5g %x\n", + rd, rd2g, rd5g, ctl2g, ctl5g); + + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_REGDOMAIN_CMDID); +} + +int ath10k_wmi_pdev_set_channel(struct ath10k *ar, + const struct wmi_channel_arg *arg) +{ + struct wmi_set_channel_cmd *cmd; + struct sk_buff *skb; + + if (arg->passive) + return -EINVAL; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_channel_cmd *)skb->data; + cmd->chan.mhz = __cpu_to_le32(arg->freq); + cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); + cmd->chan.mode = arg->mode; + cmd->chan.min_power = arg->min_power; + cmd->chan.max_power = arg->max_power; + cmd->chan.reg_power = arg->max_reg_power; + cmd->chan.reg_classid = arg->reg_class_id; + cmd->chan.antenna_max = arg->max_antenna_gain; + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi set channel mode %d freq %d\n", + arg->mode, arg->freq); + + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_CHANNEL_CMDID); +} + +int ath10k_wmi_pdev_suspend_target(struct ath10k *ar) +{ + struct wmi_pdev_suspend_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_suspend_cmd *)skb->data; + cmd->suspend_opt = WMI_PDEV_SUSPEND; + + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SUSPEND_CMDID); +} + +int ath10k_wmi_pdev_resume_target(struct ath10k *ar) +{ + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(0); + if (skb == NULL) + return -ENOMEM; + + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_RESUME_CMDID); +} + +int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, + u32 value) +{ + struct wmi_pdev_set_param_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_set_param_cmd *)skb->data; + cmd->param_id = __cpu_to_le32(id); + cmd->param_value = __cpu_to_le32(value); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set param %d value %d\n", + id, value); + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_PARAM_CMDID); +} + +int ath10k_wmi_cmd_init(struct ath10k *ar) +{ + struct wmi_init_cmd *cmd; + struct sk_buff *buf; + struct wmi_resource_config config = {}; + u32 val; + + config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); + config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); + config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS); + + config.num_offload_reorder_bufs = + __cpu_to_le32(TARGET_NUM_OFFLOAD_REORDER_BUFS); + + config.num_peer_keys = __cpu_to_le32(TARGET_NUM_PEER_KEYS); + config.num_tids = __cpu_to_le32(TARGET_NUM_TIDS); + config.ast_skid_limit = __cpu_to_le32(TARGET_AST_SKID_LIMIT); + config.tx_chain_mask = __cpu_to_le32(TARGET_TX_CHAIN_MASK); + config.rx_chain_mask = __cpu_to_le32(TARGET_RX_CHAIN_MASK); + config.rx_timeout_pri_vo = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); + config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); + config.rx_timeout_pri_be = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI); + config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_RX_TIMEOUT_HI_PRI); + config.rx_decap_mode = __cpu_to_le32(TARGET_RX_DECAP_MODE); + + config.scan_max_pending_reqs = + __cpu_to_le32(TARGET_SCAN_MAX_PENDING_REQS); + + config.bmiss_offload_max_vdev = + __cpu_to_le32(TARGET_BMISS_OFFLOAD_MAX_VDEV); + + config.roam_offload_max_vdev = + __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_VDEV); + + config.roam_offload_max_ap_profiles = + __cpu_to_le32(TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES); + + config.num_mcast_groups = __cpu_to_le32(TARGET_NUM_MCAST_GROUPS); + config.num_mcast_table_elems = + __cpu_to_le32(TARGET_NUM_MCAST_TABLE_ELEMS); + + config.mcast2ucast_mode = __cpu_to_le32(TARGET_MCAST2UCAST_MODE); + config.tx_dbg_log_size = __cpu_to_le32(TARGET_TX_DBG_LOG_SIZE); + config.num_wds_entries = __cpu_to_le32(TARGET_NUM_WDS_ENTRIES); + config.dma_burst_size = __cpu_to_le32(TARGET_DMA_BURST_SIZE); + config.mac_aggr_delim = __cpu_to_le32(TARGET_MAC_AGGR_DELIM); + + val = TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK; + config.rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(val); + + config.vow_config = __cpu_to_le32(TARGET_VOW_CONFIG); + + config.gtk_offload_max_vdev = + __cpu_to_le32(TARGET_GTK_OFFLOAD_MAX_VDEV); + + config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC); + config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES); + + buf = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!buf) + return -ENOMEM; + + cmd = (struct wmi_init_cmd *)buf->data; + cmd->num_host_mem_chunks = 0; + memcpy(&cmd->resource_config, &config, sizeof(config)); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi init\n"); + return ath10k_wmi_cmd_send(ar, buf, WMI_INIT_CMDID); +} + +static int ath10k_wmi_start_scan_calc_len(const struct wmi_start_scan_arg *arg) +{ + int len; + + len = sizeof(struct wmi_start_scan_cmd); + + if (arg->ie_len) { + if (!arg->ie) + return -EINVAL; + if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) + return -EINVAL; + + len += sizeof(struct wmi_ie_data); + len += roundup(arg->ie_len, 4); + } + + if (arg->n_channels) { + if (!arg->channels) + return -EINVAL; + if (arg->n_channels > ARRAY_SIZE(arg->channels)) + return -EINVAL; + + len += sizeof(struct wmi_chan_list); + len += sizeof(__le32) * arg->n_channels; + } + + if (arg->n_ssids) { + if (!arg->ssids) + return -EINVAL; + if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) + return -EINVAL; + + len += sizeof(struct wmi_ssid_list); + len += sizeof(struct wmi_ssid) * arg->n_ssids; + } + + if (arg->n_bssids) { + if (!arg->bssids) + return -EINVAL; + if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) + return -EINVAL; + + len += sizeof(struct wmi_bssid_list); + len += sizeof(struct wmi_mac_addr) * arg->n_bssids; + } + + return len; +} + +int ath10k_wmi_start_scan(struct ath10k *ar, + const struct wmi_start_scan_arg *arg) +{ + struct wmi_start_scan_cmd *cmd; + struct sk_buff *skb; + struct wmi_ie_data *ie; + struct wmi_chan_list *channels; + struct wmi_ssid_list *ssids; + struct wmi_bssid_list *bssids; + u32 scan_id; + u32 scan_req_id; + int off; + int len = 0; + int i; + + len = ath10k_wmi_start_scan_calc_len(arg); + if (len < 0) + return len; /* len contains error code here */ + + skb = ath10k_wmi_alloc_skb(len); + if (!skb) + return -ENOMEM; + + scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; + scan_id |= arg->scan_id; + + scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; + scan_req_id |= arg->scan_req_id; + + cmd = (struct wmi_start_scan_cmd *)skb->data; + cmd->scan_id = __cpu_to_le32(scan_id); + cmd->scan_req_id = __cpu_to_le32(scan_req_id); + cmd->vdev_id = __cpu_to_le32(arg->vdev_id); + cmd->scan_priority = __cpu_to_le32(arg->scan_priority); + cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); + cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); + cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); + cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); + cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); + cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); + cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); + cmd->idle_time = __cpu_to_le32(arg->idle_time); + cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); + cmd->probe_delay = __cpu_to_le32(arg->probe_delay); + cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); + + /* TLV list starts after fields included in the struct */ + off = sizeof(*cmd); + + if (arg->n_channels) { + channels = (void *)skb->data + off; + channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); + channels->num_chan = __cpu_to_le32(arg->n_channels); + + for (i = 0; i < arg->n_channels; i++) + channels->channel_list[i] = + __cpu_to_le32(arg->channels[i]); + + off += sizeof(*channels); + off += sizeof(__le32) * arg->n_channels; + } + + if (arg->n_ssids) { + ssids = (void *)skb->data + off; + ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); + ssids->num_ssids = __cpu_to_le32(arg->n_ssids); + + for (i = 0; i < arg->n_ssids; i++) { + ssids->ssids[i].ssid_len = + __cpu_to_le32(arg->ssids[i].len); + memcpy(&ssids->ssids[i].ssid, + arg->ssids[i].ssid, + arg->ssids[i].len); + } + + off += sizeof(*ssids); + off += sizeof(struct wmi_ssid) * arg->n_ssids; + } + + if (arg->n_bssids) { + bssids = (void *)skb->data + off; + bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); + bssids->num_bssid = __cpu_to_le32(arg->n_bssids); + + for (i = 0; i < arg->n_bssids; i++) + memcpy(&bssids->bssid_list[i], + arg->bssids[i].bssid, + ETH_ALEN); + + off += sizeof(*bssids); + off += sizeof(struct wmi_mac_addr) * arg->n_bssids; + } + + if (arg->ie_len) { + ie = (void *)skb->data + off; + ie->tag = __cpu_to_le32(WMI_IE_TAG); + ie->ie_len = __cpu_to_le32(arg->ie_len); + memcpy(ie->ie_data, arg->ie, arg->ie_len); + + off += sizeof(*ie); + off += roundup(arg->ie_len, 4); + } + + if (off != skb->len) { + dev_kfree_skb(skb); + return -EINVAL; + } + + ath10k_dbg(ATH10K_DBG_WMI, "wmi start scan\n"); + return ath10k_wmi_cmd_send(ar, skb, WMI_START_SCAN_CMDID); +} + +void ath10k_wmi_start_scan_init(struct ath10k *ar, + struct wmi_start_scan_arg *arg) +{ + /* setup commonly used values */ + arg->scan_req_id = 1; + arg->scan_priority = WMI_SCAN_PRIORITY_LOW; + arg->dwell_time_active = 50; + arg->dwell_time_passive = 150; + arg->min_rest_time = 50; + arg->max_rest_time = 500; + arg->repeat_probe_time = 0; + arg->probe_spacing_time = 0; + arg->idle_time = 0; + arg->max_scan_time = 5000; + arg->probe_delay = 5; + arg->notify_scan_events = WMI_SCAN_EVENT_STARTED + | WMI_SCAN_EVENT_COMPLETED + | WMI_SCAN_EVENT_BSS_CHANNEL + | WMI_SCAN_EVENT_FOREIGN_CHANNEL + | WMI_SCAN_EVENT_DEQUEUED; + arg->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES; + arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT; + arg->n_bssids = 1; + arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF"; +} + +int ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg) +{ + struct wmi_stop_scan_cmd *cmd; + struct sk_buff *skb; + u32 scan_id; + u32 req_id; + + if (arg->req_id > 0xFFF) + return -EINVAL; + if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF) + return -EINVAL; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + scan_id = arg->u.scan_id; + scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX; + + req_id = arg->req_id; + req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; + + cmd = (struct wmi_stop_scan_cmd *)skb->data; + cmd->req_type = __cpu_to_le32(arg->req_type); + cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id); + cmd->scan_id = __cpu_to_le32(scan_id); + cmd->scan_req_id = __cpu_to_le32(req_id); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi stop scan reqid %d req_type %d vdev/scan_id %d\n", + arg->req_id, arg->req_type, arg->u.scan_id); + return ath10k_wmi_cmd_send(ar, skb, WMI_STOP_SCAN_CMDID); +} + +int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, + enum wmi_vdev_type type, + enum wmi_vdev_subtype subtype, + const u8 macaddr[ETH_ALEN]) +{ + struct wmi_vdev_create_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_create_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->vdev_type = __cpu_to_le32(type); + cmd->vdev_subtype = __cpu_to_le32(subtype); + memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "WMI vdev create: id %d type %d subtype %d macaddr %pM\n", + vdev_id, type, subtype, macaddr); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_CREATE_CMDID); +} + +int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) +{ + struct wmi_vdev_delete_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_delete_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + + ath10k_dbg(ATH10K_DBG_WMI, + "WMI vdev delete id %d\n", vdev_id); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DELETE_CMDID); +} + +static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, + const struct wmi_vdev_start_request_arg *arg, + enum wmi_cmd_id cmd_id) +{ + struct wmi_vdev_start_request_cmd *cmd; + struct sk_buff *skb; + const char *cmdname; + u32 flags = 0; + + if (cmd_id != WMI_VDEV_START_REQUEST_CMDID && + cmd_id != WMI_VDEV_RESTART_REQUEST_CMDID) + return -EINVAL; + if (WARN_ON(arg->ssid && arg->ssid_len == 0)) + return -EINVAL; + if (WARN_ON(arg->hidden_ssid && !arg->ssid)) + return -EINVAL; + if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) + return -EINVAL; + + if (cmd_id == WMI_VDEV_START_REQUEST_CMDID) + cmdname = "start"; + else if (cmd_id == WMI_VDEV_RESTART_REQUEST_CMDID) + cmdname = "restart"; + else + return -EINVAL; /* should not happen, we already check cmd_id */ + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + if (arg->hidden_ssid) + flags |= WMI_VDEV_START_HIDDEN_SSID; + if (arg->pmf_enabled) + flags |= WMI_VDEV_START_PMF_ENABLED; + + cmd = (struct wmi_vdev_start_request_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(arg->vdev_id); + cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack); + cmd->beacon_interval = __cpu_to_le32(arg->bcn_intval); + cmd->dtim_period = __cpu_to_le32(arg->dtim_period); + cmd->flags = __cpu_to_le32(flags); + cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate); + cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power); + + if (arg->ssid) { + cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len); + memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); + } + + cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); + + cmd->chan.band_center_freq1 = + __cpu_to_le32(arg->channel.band_center_freq1); + + cmd->chan.mode = arg->channel.mode; + cmd->chan.min_power = arg->channel.min_power; + cmd->chan.max_power = arg->channel.max_power; + cmd->chan.reg_power = arg->channel.max_reg_power; + cmd->chan.reg_classid = arg->channel.reg_class_id; + cmd->chan.antenna_max = arg->channel.max_antenna_gain; + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi vdev %s id 0x%x freq %d, mode %d, ch_flags: 0x%0X," + "max_power: %d\n", cmdname, arg->vdev_id, arg->channel.freq, + arg->channel.mode, flags, arg->channel.max_power); + + return ath10k_wmi_cmd_send(ar, skb, cmd_id); +} + +int ath10k_wmi_vdev_start(struct ath10k *ar, + const struct wmi_vdev_start_request_arg *arg) +{ + return ath10k_wmi_vdev_start_restart(ar, arg, + WMI_VDEV_START_REQUEST_CMDID); +} + +int ath10k_wmi_vdev_restart(struct ath10k *ar, + const struct wmi_vdev_start_request_arg *arg) +{ + return ath10k_wmi_vdev_start_restart(ar, arg, + WMI_VDEV_RESTART_REQUEST_CMDID); +} + +int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id) +{ + struct wmi_vdev_stop_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_stop_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi vdev stop id 0x%x\n", vdev_id); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_STOP_CMDID); +} + +int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) +{ + struct wmi_vdev_up_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_up_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->vdev_assoc_id = __cpu_to_le32(aid); + memcpy(&cmd->vdev_bssid.addr, bssid, 6); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", + vdev_id, aid, bssid); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_UP_CMDID); +} + +int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id) +{ + struct wmi_vdev_down_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_down_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi mgmt vdev down id 0x%x\n", vdev_id); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_DOWN_CMDID); +} + +int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, + enum wmi_vdev_param param_id, u32 param_value) +{ + struct wmi_vdev_set_param_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_set_param_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->param_id = __cpu_to_le32(param_id); + cmd->param_value = __cpu_to_le32(param_value); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi vdev id 0x%x set param %d value %d\n", + vdev_id, param_id, param_value); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_SET_PARAM_CMDID); +} + +int ath10k_wmi_vdev_install_key(struct ath10k *ar, + const struct wmi_vdev_install_key_arg *arg) +{ + struct wmi_vdev_install_key_cmd *cmd; + struct sk_buff *skb; + + if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) + return -EINVAL; + if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) + return -EINVAL; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->key_len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_vdev_install_key_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(arg->vdev_id); + cmd->key_idx = __cpu_to_le32(arg->key_idx); + cmd->key_flags = __cpu_to_le32(arg->key_flags); + cmd->key_cipher = __cpu_to_le32(arg->key_cipher); + cmd->key_len = __cpu_to_le32(arg->key_len); + cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len); + cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len); + + if (arg->macaddr) + memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN); + if (arg->key_data) + memcpy(cmd->key_data, arg->key_data, arg->key_len); + + return ath10k_wmi_cmd_send(ar, skb, WMI_VDEV_INSTALL_KEY_CMDID); +} + +int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN]) +{ + struct wmi_peer_create_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_peer_create_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi peer create vdev_id %d peer_addr %pM\n", + vdev_id, peer_addr); + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_CREATE_CMDID); +} + +int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN]) +{ + struct wmi_peer_delete_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_peer_delete_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi peer delete vdev_id %d peer_addr %pM\n", + vdev_id, peer_addr); + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_DELETE_CMDID); +} + +int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN], u32 tid_bitmap) +{ + struct wmi_peer_flush_tids_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_peer_flush_tids_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap); + memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", + vdev_id, peer_addr, tid_bitmap); + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_FLUSH_TIDS_CMDID); +} + +int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, + const u8 *peer_addr, enum wmi_peer_param param_id, + u32 param_value) +{ + struct wmi_peer_set_param_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_peer_set_param_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->param_id = __cpu_to_le32(param_id); + cmd->param_value = __cpu_to_le32(param_value); + memcpy(&cmd->peer_macaddr.addr, peer_addr, 6); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi vdev %d peer 0x%pM set param %d value %d\n", + vdev_id, peer_addr, param_id, param_value); + + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_SET_PARAM_CMDID); +} + +int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_ps_mode psmode) +{ + struct wmi_sta_powersave_mode_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_sta_powersave_mode_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->sta_ps_mode = __cpu_to_le32(psmode); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi set powersave id 0x%x mode %d\n", + vdev_id, psmode); + + return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_MODE_CMDID); +} + +int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_powersave_param param_id, + u32 value) +{ + struct wmi_sta_powersave_param_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_sta_powersave_param_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->param_id = __cpu_to_le32(param_id); + cmd->param_value = __cpu_to_le32(value); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi sta ps param vdev_id 0x%x param %d value %d\n", + vdev_id, param_id, value); + return ath10k_wmi_cmd_send(ar, skb, WMI_STA_POWERSAVE_PARAM_CMDID); +} + +int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, + enum wmi_ap_ps_peer_param param_id, u32 value) +{ + struct wmi_ap_ps_peer_cmd *cmd; + struct sk_buff *skb; + + if (!mac) + return -EINVAL; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_ps_peer_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(vdev_id); + cmd->param_id = __cpu_to_le32(param_id); + cmd->param_value = __cpu_to_le32(value); + memcpy(&cmd->peer_macaddr, mac, ETH_ALEN); + + ath10k_dbg(ATH10K_DBG_WMI, + "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", + vdev_id, param_id, value, mac); + + return ath10k_wmi_cmd_send(ar, skb, WMI_AP_PS_PEER_PARAM_CMDID); +} + +int ath10k_wmi_scan_chan_list(struct ath10k *ar, + const struct wmi_scan_chan_list_arg *arg) +{ + struct wmi_scan_chan_list_cmd *cmd; + struct sk_buff *skb; + struct wmi_channel_arg *ch; + struct wmi_channel *ci; + int len; + int i; + + len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel); + + skb = ath10k_wmi_alloc_skb(len); + if (!skb) + return -EINVAL; + + cmd = (struct wmi_scan_chan_list_cmd *)skb->data; + cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); + + for (i = 0; i < arg->n_channels; i++) { + u32 flags = 0; + + ch = &arg->channels[i]; + ci = &cmd->chan_info[i]; + + if (ch->passive) + flags |= WMI_CHAN_FLAG_PASSIVE; + if (ch->allow_ibss) + flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; + if (ch->allow_ht) + flags |= WMI_CHAN_FLAG_ALLOW_HT; + if (ch->allow_vht) + flags |= WMI_CHAN_FLAG_ALLOW_VHT; + if (ch->ht40plus) + flags |= WMI_CHAN_FLAG_HT40_PLUS; + + ci->mhz = __cpu_to_le32(ch->freq); + ci->band_center_freq1 = __cpu_to_le32(ch->freq); + ci->band_center_freq2 = 0; + ci->min_power = ch->min_power; + ci->max_power = ch->max_power; + ci->reg_power = ch->max_reg_power; + ci->antenna_max = ch->max_antenna_gain; + ci->antenna_max = 0; + + /* mode & flags share storage */ + ci->mode = ch->mode; + ci->flags |= __cpu_to_le32(flags); + } + + return ath10k_wmi_cmd_send(ar, skb, WMI_SCAN_CHAN_LIST_CMDID); +} + +int ath10k_wmi_peer_assoc(struct ath10k *ar, + const struct wmi_peer_assoc_complete_arg *arg) +{ + struct wmi_peer_assoc_complete_cmd *cmd; + struct sk_buff *skb; + + if (arg->peer_mpdu_density > 16) + return -EINVAL; + if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES) + return -EINVAL; + if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES) + return -EINVAL; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_peer_assoc_complete_cmd *)skb->data; + cmd->vdev_id = __cpu_to_le32(arg->vdev_id); + cmd->peer_new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1); + cmd->peer_associd = __cpu_to_le32(arg->peer_aid); + cmd->peer_flags = __cpu_to_le32(arg->peer_flags); + cmd->peer_caps = __cpu_to_le32(arg->peer_caps); + cmd->peer_listen_intval = __cpu_to_le32(arg->peer_listen_intval); + cmd->peer_ht_caps = __cpu_to_le32(arg->peer_ht_caps); + cmd->peer_max_mpdu = __cpu_to_le32(arg->peer_max_mpdu); + cmd->peer_mpdu_density = __cpu_to_le32(arg->peer_mpdu_density); + cmd->peer_rate_caps = __cpu_to_le32(arg->peer_rate_caps); + cmd->peer_nss = __cpu_to_le32(arg->peer_num_spatial_streams); + cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps); + cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode); + + memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN); + + cmd->peer_legacy_rates.num_rates = + __cpu_to_le32(arg->peer_legacy_rates.num_rates); + memcpy(cmd->peer_legacy_rates.rates, arg->peer_legacy_rates.rates, + arg->peer_legacy_rates.num_rates); + + cmd->peer_ht_rates.num_rates = + __cpu_to_le32(arg->peer_ht_rates.num_rates); + memcpy(cmd->peer_ht_rates.rates, arg->peer_ht_rates.rates, + arg->peer_ht_rates.num_rates); + + cmd->peer_vht_rates.rx_max_rate = + __cpu_to_le32(arg->peer_vht_rates.rx_max_rate); + cmd->peer_vht_rates.rx_mcs_set = + __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set); + cmd->peer_vht_rates.tx_max_rate = + __cpu_to_le32(arg->peer_vht_rates.tx_max_rate); + cmd->peer_vht_rates.tx_mcs_set = + __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set); + + return ath10k_wmi_cmd_send(ar, skb, WMI_PEER_ASSOC_CMDID); +} + +int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg) +{ + struct wmi_bcn_tx_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd) + arg->bcn_len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_bcn_tx_cmd *)skb->data; + cmd->hdr.vdev_id = __cpu_to_le32(arg->vdev_id); + cmd->hdr.tx_rate = __cpu_to_le32(arg->tx_rate); + cmd->hdr.tx_power = __cpu_to_le32(arg->tx_power); + cmd->hdr.bcn_len = __cpu_to_le32(arg->bcn_len); + memcpy(cmd->bcn, arg->bcn, arg->bcn_len); + + return ath10k_wmi_cmd_send(ar, skb, WMI_BCN_TX_CMDID); +} + +static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, + const struct wmi_wmm_params_arg *arg) +{ + params->cwmin = __cpu_to_le32(arg->cwmin); + params->cwmax = __cpu_to_le32(arg->cwmax); + params->aifs = __cpu_to_le32(arg->aifs); + params->txop = __cpu_to_le32(arg->txop); + params->acm = __cpu_to_le32(arg->acm); + params->no_ack = __cpu_to_le32(arg->no_ack); +} + +int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, + const struct wmi_pdev_set_wmm_params_arg *arg) +{ + struct wmi_pdev_set_wmm_params *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_set_wmm_params *)skb->data; + ath10k_wmi_pdev_set_wmm_param(&cmd->ac_be, &arg->ac_be); + ath10k_wmi_pdev_set_wmm_param(&cmd->ac_bk, &arg->ac_bk); + ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vi, &arg->ac_vi); + ath10k_wmi_pdev_set_wmm_param(&cmd->ac_vo, &arg->ac_vo); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi pdev set wmm params\n"); + return ath10k_wmi_cmd_send(ar, skb, WMI_PDEV_SET_WMM_PARAMS_CMDID); +} + +int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id) +{ + struct wmi_request_stats_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_request_stats_cmd *)skb->data; + cmd->stats_id = __cpu_to_le32(stats_id); + + ath10k_dbg(ATH10K_DBG_WMI, "wmi request stats %d\n", (int)stats_id); + return ath10k_wmi_cmd_send(ar, skb, WMI_REQUEST_STATS_CMDID); +} diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h new file mode 100644 index 000000000000..9555f5a0e041 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -0,0 +1,3052 @@ +/* + * Copyright (c) 2005-2011 Atheros Communications Inc. + * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _WMI_H_ +#define _WMI_H_ + +#include +#include + +/* + * This file specifies the WMI interface for the Unified Software + * Architecture. + * + * It includes definitions of all the commands and events. Commands are + * messages from the host to the target. Events and Replies are messages + * from the target to the host. + * + * Ownership of correctness in regards to WMI commands belongs to the host + * driver and the target is not required to validate parameters for value, + * proper range, or any other checking. + * + * Guidelines for extending this interface are below. + * + * 1. Add new WMI commands ONLY within the specified range - 0x9000 - 0x9fff + * + * 2. Use ONLY u32 type for defining member variables within WMI + * command/event structures. Do not use u8, u16, bool or + * enum types within these structures. + * + * 3. DO NOT define bit fields within structures. Implement bit fields + * using masks if necessary. Do not use the programming language's bit + * field definition. + * + * 4. Define macros for encode/decode of u8, u16 fields within + * the u32 variables. Use these macros for set/get of these fields. + * Try to use this to optimize the structure without bloating it with + * u32 variables for every lower sized field. + * + * 5. Do not use PACK/UNPACK attributes for the structures as each member + * variable is already 4-byte aligned by virtue of being a u32 + * type. + * + * 6. Comment each parameter part of the WMI command/event structure by + * using the 2 stars at the begining of C comment instead of one star to + * enable HTML document generation using Doxygen. + * + */ + +/* Control Path */ +struct wmi_cmd_hdr { + __le32 cmd_id; +} __packed; + +#define WMI_CMD_HDR_CMD_ID_MASK 0x00FFFFFF +#define WMI_CMD_HDR_CMD_ID_LSB 0 +#define WMI_CMD_HDR_PLT_PRIV_MASK 0xFF000000 +#define WMI_CMD_HDR_PLT_PRIV_LSB 24 + +#define HTC_PROTOCOL_VERSION 0x0002 +#define WMI_PROTOCOL_VERSION 0x0002 + +enum wmi_service_id { + WMI_SERVICE_BEACON_OFFLOAD = 0, /* beacon offload */ + WMI_SERVICE_SCAN_OFFLOAD, /* scan offload */ + WMI_SERVICE_ROAM_OFFLOAD, /* roam offload */ + WMI_SERVICE_BCN_MISS_OFFLOAD, /* beacon miss offload */ + WMI_SERVICE_STA_PWRSAVE, /* fake sleep + basic power save */ + WMI_SERVICE_STA_ADVANCED_PWRSAVE, /* uapsd, pspoll, force sleep */ + WMI_SERVICE_AP_UAPSD, /* uapsd on AP */ + WMI_SERVICE_AP_DFS, /* DFS on AP */ + WMI_SERVICE_11AC, /* supports 11ac */ + WMI_SERVICE_BLOCKACK, /* Supports triggering ADDBA/DELBA from host*/ + WMI_SERVICE_PHYERR, /* PHY error */ + WMI_SERVICE_BCN_FILTER, /* Beacon filter support */ + WMI_SERVICE_RTT, /* RTT (round trip time) support */ + WMI_SERVICE_RATECTRL, /* Rate-control */ + WMI_SERVICE_WOW, /* WOW Support */ + WMI_SERVICE_RATECTRL_CACHE, /* Rate-control caching */ + WMI_SERVICE_IRAM_TIDS, /* TIDs in IRAM */ + WMI_SERVICE_ARPNS_OFFLOAD, /* ARP NS Offload support */ + WMI_SERVICE_NLO, /* Network list offload service */ + WMI_SERVICE_GTK_OFFLOAD, /* GTK offload */ + WMI_SERVICE_SCAN_SCH, /* Scan Scheduler Service */ + WMI_SERVICE_CSA_OFFLOAD, /* CSA offload service */ + WMI_SERVICE_CHATTER, /* Chatter service */ + WMI_SERVICE_COEX_FREQAVOID, /* FW report freq range to avoid */ + WMI_SERVICE_PACKET_POWER_SAVE, /* packet power save service */ + WMI_SERVICE_FORCE_FW_HANG, /* To test fw recovery mechanism */ + WMI_SERVICE_GPIO, /* GPIO service */ + WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, /* Modulated DTIM support */ + WMI_STA_UAPSD_BASIC_AUTO_TRIG, /* UAPSD AC Trigger Generation */ + WMI_STA_UAPSD_VAR_AUTO_TRIG, /* -do- */ + WMI_SERVICE_STA_KEEP_ALIVE, /* STA keep alive mechanism support */ + WMI_SERVICE_TX_ENCAP, /* Packet type for TX encapsulation */ + + WMI_SERVICE_LAST, + WMI_MAX_SERVICE = 64 /* max service */ +}; + +static inline char *wmi_service_name(int service_id) +{ + switch (service_id) { + case WMI_SERVICE_BEACON_OFFLOAD: + return "BEACON_OFFLOAD"; + case WMI_SERVICE_SCAN_OFFLOAD: + return "SCAN_OFFLOAD"; + case WMI_SERVICE_ROAM_OFFLOAD: + return "ROAM_OFFLOAD"; + case WMI_SERVICE_BCN_MISS_OFFLOAD: + return "BCN_MISS_OFFLOAD"; + case WMI_SERVICE_STA_PWRSAVE: + return "STA_PWRSAVE"; + case WMI_SERVICE_STA_ADVANCED_PWRSAVE: + return "STA_ADVANCED_PWRSAVE"; + case WMI_SERVICE_AP_UAPSD: + return "AP_UAPSD"; + case WMI_SERVICE_AP_DFS: + return "AP_DFS"; + case WMI_SERVICE_11AC: + return "11AC"; + case WMI_SERVICE_BLOCKACK: + return "BLOCKACK"; + case WMI_SERVICE_PHYERR: + return "PHYERR"; + case WMI_SERVICE_BCN_FILTER: + return "BCN_FILTER"; + case WMI_SERVICE_RTT: + return "RTT"; + case WMI_SERVICE_RATECTRL: + return "RATECTRL"; + case WMI_SERVICE_WOW: + return "WOW"; + case WMI_SERVICE_RATECTRL_CACHE: + return "RATECTRL CACHE"; + case WMI_SERVICE_IRAM_TIDS: + return "IRAM TIDS"; + case WMI_SERVICE_ARPNS_OFFLOAD: + return "ARPNS_OFFLOAD"; + case WMI_SERVICE_NLO: + return "NLO"; + case WMI_SERVICE_GTK_OFFLOAD: + return "GTK_OFFLOAD"; + case WMI_SERVICE_SCAN_SCH: + return "SCAN_SCH"; + case WMI_SERVICE_CSA_OFFLOAD: + return "CSA_OFFLOAD"; + case WMI_SERVICE_CHATTER: + return "CHATTER"; + case WMI_SERVICE_COEX_FREQAVOID: + return "COEX_FREQAVOID"; + case WMI_SERVICE_PACKET_POWER_SAVE: + return "PACKET_POWER_SAVE"; + case WMI_SERVICE_FORCE_FW_HANG: + return "FORCE FW HANG"; + case WMI_SERVICE_GPIO: + return "GPIO"; + case WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM: + return "MODULATED DTIM"; + case WMI_STA_UAPSD_BASIC_AUTO_TRIG: + return "BASIC UAPSD"; + case WMI_STA_UAPSD_VAR_AUTO_TRIG: + return "VAR UAPSD"; + case WMI_SERVICE_STA_KEEP_ALIVE: + return "STA KEEP ALIVE"; + case WMI_SERVICE_TX_ENCAP: + return "TX ENCAP"; + default: + return "UNKNOWN SERVICE\n"; + } +} + + +#define WMI_SERVICE_BM_SIZE \ + ((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32)) + +/* 2 word representation of MAC addr */ +struct wmi_mac_addr { + union { + u8 addr[6]; + struct { + u32 word0; + u32 word1; + } __packed; + } __packed; +} __packed; + +/* macro to convert MAC address from WMI word format to char array */ +#define WMI_MAC_ADDR_TO_CHAR_ARRAY(pwmi_mac_addr, c_macaddr) do { \ + (c_macaddr)[0] = ((pwmi_mac_addr)->word0) & 0xff; \ + (c_macaddr)[1] = (((pwmi_mac_addr)->word0) >> 8) & 0xff; \ + (c_macaddr)[2] = (((pwmi_mac_addr)->word0) >> 16) & 0xff; \ + (c_macaddr)[3] = (((pwmi_mac_addr)->word0) >> 24) & 0xff; \ + (c_macaddr)[4] = ((pwmi_mac_addr)->word1) & 0xff; \ + (c_macaddr)[5] = (((pwmi_mac_addr)->word1) >> 8) & 0xff; \ + } while (0) + +/* + * wmi command groups. + */ +enum wmi_cmd_group { + /* 0 to 2 are reserved */ + WMI_GRP_START = 0x3, + WMI_GRP_SCAN = WMI_GRP_START, + WMI_GRP_PDEV, + WMI_GRP_VDEV, + WMI_GRP_PEER, + WMI_GRP_MGMT, + WMI_GRP_BA_NEG, + WMI_GRP_STA_PS, + WMI_GRP_DFS, + WMI_GRP_ROAM, + WMI_GRP_OFL_SCAN, + WMI_GRP_P2P, + WMI_GRP_AP_PS, + WMI_GRP_RATE_CTRL, + WMI_GRP_PROFILE, + WMI_GRP_SUSPEND, + WMI_GRP_BCN_FILTER, + WMI_GRP_WOW, + WMI_GRP_RTT, + WMI_GRP_SPECTRAL, + WMI_GRP_STATS, + WMI_GRP_ARP_NS_OFL, + WMI_GRP_NLO_OFL, + WMI_GRP_GTK_OFL, + WMI_GRP_CSA_OFL, + WMI_GRP_CHATTER, + WMI_GRP_TID_ADDBA, + WMI_GRP_MISC, + WMI_GRP_GPIO, +}; + +#define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1) +#define WMI_EVT_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) + +/* Command IDs and commande events. */ +enum wmi_cmd_id { + WMI_INIT_CMDID = 0x1, + + /* Scan specific commands */ + WMI_START_SCAN_CMDID = WMI_CMD_GRP(WMI_GRP_SCAN), + WMI_STOP_SCAN_CMDID, + WMI_SCAN_CHAN_LIST_CMDID, + WMI_SCAN_SCH_PRIO_TBL_CMDID, + + /* PDEV (physical device) specific commands */ + WMI_PDEV_SET_REGDOMAIN_CMDID = WMI_CMD_GRP(WMI_GRP_PDEV), + WMI_PDEV_SET_CHANNEL_CMDID, + WMI_PDEV_SET_PARAM_CMDID, + WMI_PDEV_PKTLOG_ENABLE_CMDID, + WMI_PDEV_PKTLOG_DISABLE_CMDID, + WMI_PDEV_SET_WMM_PARAMS_CMDID, + WMI_PDEV_SET_HT_CAP_IE_CMDID, + WMI_PDEV_SET_VHT_CAP_IE_CMDID, + WMI_PDEV_SET_DSCP_TID_MAP_CMDID, + WMI_PDEV_SET_QUIET_MODE_CMDID, + WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID, + WMI_PDEV_GET_TPC_CONFIG_CMDID, + WMI_PDEV_SET_BASE_MACADDR_CMDID, + + /* VDEV (virtual device) specific commands */ + WMI_VDEV_CREATE_CMDID = WMI_CMD_GRP(WMI_GRP_VDEV), + WMI_VDEV_DELETE_CMDID, + WMI_VDEV_START_REQUEST_CMDID, + WMI_VDEV_RESTART_REQUEST_CMDID, + WMI_VDEV_UP_CMDID, + WMI_VDEV_STOP_CMDID, + WMI_VDEV_DOWN_CMDID, + WMI_VDEV_SET_PARAM_CMDID, + WMI_VDEV_INSTALL_KEY_CMDID, + + /* peer specific commands */ + WMI_PEER_CREATE_CMDID = WMI_CMD_GRP(WMI_GRP_PEER), + WMI_PEER_DELETE_CMDID, + WMI_PEER_FLUSH_TIDS_CMDID, + WMI_PEER_SET_PARAM_CMDID, + WMI_PEER_ASSOC_CMDID, + WMI_PEER_ADD_WDS_ENTRY_CMDID, + WMI_PEER_REMOVE_WDS_ENTRY_CMDID, + WMI_PEER_MCAST_GROUP_CMDID, + + /* beacon/management specific commands */ + WMI_BCN_TX_CMDID = WMI_CMD_GRP(WMI_GRP_MGMT), + WMI_PDEV_SEND_BCN_CMDID, + WMI_BCN_TMPL_CMDID, + WMI_BCN_FILTER_RX_CMDID, + WMI_PRB_REQ_FILTER_RX_CMDID, + WMI_MGMT_TX_CMDID, + WMI_PRB_TMPL_CMDID, + + /* commands to directly control BA negotiation directly from host. */ + WMI_ADDBA_CLEAR_RESP_CMDID = WMI_CMD_GRP(WMI_GRP_BA_NEG), + WMI_ADDBA_SEND_CMDID, + WMI_ADDBA_STATUS_CMDID, + WMI_DELBA_SEND_CMDID, + WMI_ADDBA_SET_RESP_CMDID, + WMI_SEND_SINGLEAMSDU_CMDID, + + /* Station power save specific config */ + WMI_STA_POWERSAVE_MODE_CMDID = WMI_CMD_GRP(WMI_GRP_STA_PS), + WMI_STA_POWERSAVE_PARAM_CMDID, + WMI_STA_MIMO_PS_MODE_CMDID, + + /** DFS-specific commands */ + WMI_PDEV_DFS_ENABLE_CMDID = WMI_CMD_GRP(WMI_GRP_DFS), + WMI_PDEV_DFS_DISABLE_CMDID, + + /* Roaming specific commands */ + WMI_ROAM_SCAN_MODE = WMI_CMD_GRP(WMI_GRP_ROAM), + WMI_ROAM_SCAN_RSSI_THRESHOLD, + WMI_ROAM_SCAN_PERIOD, + WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, + WMI_ROAM_AP_PROFILE, + + /* offload scan specific commands */ + WMI_OFL_SCAN_ADD_AP_PROFILE = WMI_CMD_GRP(WMI_GRP_OFL_SCAN), + WMI_OFL_SCAN_REMOVE_AP_PROFILE, + WMI_OFL_SCAN_PERIOD, + + /* P2P specific commands */ + WMI_P2P_DEV_SET_DEVICE_INFO = WMI_CMD_GRP(WMI_GRP_P2P), + WMI_P2P_DEV_SET_DISCOVERABILITY, + WMI_P2P_GO_SET_BEACON_IE, + WMI_P2P_GO_SET_PROBE_RESP_IE, + WMI_P2P_SET_VENDOR_IE_DATA_CMDID, + + /* AP power save specific config */ + WMI_AP_PS_PEER_PARAM_CMDID = WMI_CMD_GRP(WMI_GRP_AP_PS), + WMI_AP_PS_PEER_UAPSD_COEX_CMDID, + + /* Rate-control specific commands */ + WMI_PEER_RATE_RETRY_SCHED_CMDID = + WMI_CMD_GRP(WMI_GRP_RATE_CTRL), + + /* WLAN Profiling commands. */ + WMI_WLAN_PROFILE_TRIGGER_CMDID = WMI_CMD_GRP(WMI_GRP_PROFILE), + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + + /* Suspend resume command Ids */ + WMI_PDEV_SUSPEND_CMDID = WMI_CMD_GRP(WMI_GRP_SUSPEND), + WMI_PDEV_RESUME_CMDID, + + /* Beacon filter commands */ + WMI_ADD_BCN_FILTER_CMDID = WMI_CMD_GRP(WMI_GRP_BCN_FILTER), + WMI_RMV_BCN_FILTER_CMDID, + + /* WOW Specific WMI commands*/ + WMI_WOW_ADD_WAKE_PATTERN_CMDID = WMI_CMD_GRP(WMI_GRP_WOW), + WMI_WOW_DEL_WAKE_PATTERN_CMDID, + WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, + WMI_WOW_ENABLE_CMDID, + WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, + + /* RTT measurement related cmd */ + WMI_RTT_MEASREQ_CMDID = WMI_CMD_GRP(WMI_GRP_RTT), + WMI_RTT_TSF_CMDID, + + /* spectral scan commands */ + WMI_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID = WMI_CMD_GRP(WMI_GRP_SPECTRAL), + WMI_VDEV_SPECTRAL_SCAN_ENABLE_CMDID, + + /* F/W stats */ + WMI_REQUEST_STATS_CMDID = WMI_CMD_GRP(WMI_GRP_STATS), + + /* ARP OFFLOAD REQUEST*/ + WMI_SET_ARP_NS_OFFLOAD_CMDID = WMI_CMD_GRP(WMI_GRP_ARP_NS_OFL), + + /* NS offload confid*/ + WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID = WMI_CMD_GRP(WMI_GRP_NLO_OFL), + + /* GTK offload Specific WMI commands*/ + WMI_GTK_OFFLOAD_CMDID = WMI_CMD_GRP(WMI_GRP_GTK_OFL), + + /* CSA offload Specific WMI commands*/ + WMI_CSA_OFFLOAD_ENABLE_CMDID = WMI_CMD_GRP(WMI_GRP_CSA_OFL), + WMI_CSA_OFFLOAD_CHANSWITCH_CMDID, + + /* Chatter commands*/ + WMI_CHATTER_SET_MODE_CMDID = WMI_CMD_GRP(WMI_GRP_CHATTER), + + /* addba specific commands */ + WMI_PEER_TID_ADDBA_CMDID = WMI_CMD_GRP(WMI_GRP_TID_ADDBA), + WMI_PEER_TID_DELBA_CMDID, + + /* set station mimo powersave method */ + WMI_STA_DTIM_PS_METHOD_CMDID, + /* Configure the Station UAPSD AC Auto Trigger Parameters */ + WMI_STA_UAPSD_AUTO_TRIG_CMDID, + + /* STA Keep alive parameter configuration, + Requires WMI_SERVICE_STA_KEEP_ALIVE */ + WMI_STA_KEEPALIVE_CMD, + + /* misc command group */ + WMI_ECHO_CMDID = WMI_CMD_GRP(WMI_GRP_MISC), + WMI_PDEV_UTF_CMDID, + WMI_DBGLOG_CFG_CMDID, + WMI_PDEV_QVIT_CMDID, + WMI_PDEV_FTM_INTG_CMDID, + WMI_VDEV_SET_KEEPALIVE_CMDID, + WMI_VDEV_GET_KEEPALIVE_CMDID, + + /* GPIO Configuration */ + WMI_GPIO_CONFIG_CMDID = WMI_CMD_GRP(WMI_GRP_GPIO), + WMI_GPIO_OUTPUT_CMDID, +}; + +enum wmi_event_id { + WMI_SERVICE_READY_EVENTID = 0x1, + WMI_READY_EVENTID, + + /* Scan specific events */ + WMI_SCAN_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_SCAN), + + /* PDEV specific events */ + WMI_PDEV_TPC_CONFIG_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_PDEV), + WMI_CHAN_INFO_EVENTID, + WMI_PHYERR_EVENTID, + + /* VDEV specific events */ + WMI_VDEV_START_RESP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_VDEV), + WMI_VDEV_STOPPED_EVENTID, + WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID, + + /* peer specific events */ + WMI_PEER_STA_KICKOUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_PEER), + + /* beacon/mgmt specific events */ + WMI_MGMT_RX_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MGMT), + WMI_HOST_SWBA_EVENTID, + WMI_TBTTOFFSET_UPDATE_EVENTID, + + /* ADDBA Related WMI Events*/ + WMI_TX_DELBA_COMPLETE_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_BA_NEG), + WMI_TX_ADDBA_COMPLETE_EVENTID, + + /* Roam event to trigger roaming on host */ + WMI_ROAM_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_ROAM), + WMI_PROFILE_MATCH, + + /* WoW */ + WMI_WOW_WAKEUP_HOST_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_WOW), + + /* RTT */ + WMI_RTT_MEASUREMENT_REPORT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_RTT), + WMI_TSF_MEASUREMENT_REPORT_EVENTID, + WMI_RTT_ERROR_REPORT_EVENTID, + + /* GTK offload */ + WMI_GTK_OFFLOAD_STATUS_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GTK_OFL), + WMI_GTK_REKEY_FAIL_EVENTID, + + /* CSA IE received event */ + WMI_CSA_HANDLING_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_CSA_OFL), + + /* Misc events */ + WMI_ECHO_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_MISC), + WMI_PDEV_UTF_EVENTID, + WMI_DEBUG_MESG_EVENTID, + WMI_UPDATE_STATS_EVENTID, + WMI_DEBUG_PRINT_EVENTID, + WMI_DCS_INTERFERENCE_EVENTID, + WMI_PDEV_QVIT_EVENTID, + WMI_WLAN_PROFILE_DATA_EVENTID, + WMI_PDEV_FTM_INTG_EVENTID, + WMI_WLAN_FREQ_AVOID_EVENTID, + WMI_VDEV_GET_KEEPALIVE_EVENTID, + + /* GPIO Event */ + WMI_GPIO_INPUT_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_GPIO), +}; + +enum wmi_phy_mode { + MODE_11A = 0, /* 11a Mode */ + MODE_11G = 1, /* 11b/g Mode */ + MODE_11B = 2, /* 11b Mode */ + MODE_11GONLY = 3, /* 11g only Mode */ + MODE_11NA_HT20 = 4, /* 11a HT20 mode */ + MODE_11NG_HT20 = 5, /* 11g HT20 mode */ + MODE_11NA_HT40 = 6, /* 11a HT40 mode */ + MODE_11NG_HT40 = 7, /* 11g HT40 mode */ + MODE_11AC_VHT20 = 8, + MODE_11AC_VHT40 = 9, + MODE_11AC_VHT80 = 10, + /* MODE_11AC_VHT160 = 11, */ + MODE_11AC_VHT20_2G = 11, + MODE_11AC_VHT40_2G = 12, + MODE_11AC_VHT80_2G = 13, + MODE_UNKNOWN = 14, + MODE_MAX = 14 +}; + +#define WMI_CHAN_LIST_TAG 0x1 +#define WMI_SSID_LIST_TAG 0x2 +#define WMI_BSSID_LIST_TAG 0x3 +#define WMI_IE_TAG 0x4 + +struct wmi_channel { + __le32 mhz; + __le32 band_center_freq1; + __le32 band_center_freq2; /* valid for 11ac, 80plus80 */ + union { + __le32 flags; /* WMI_CHAN_FLAG_ */ + struct { + u8 mode; /* only 6 LSBs */ + } __packed; + } __packed; + union { + __le32 reginfo0; + struct { + u8 min_power; + u8 max_power; + u8 reg_power; + u8 reg_classid; + } __packed; + } __packed; + union { + __le32 reginfo1; + struct { + u8 antenna_max; + } __packed; + } __packed; +} __packed; + +struct wmi_channel_arg { + u32 freq; + u32 band_center_freq1; + bool passive; + bool allow_ibss; + bool allow_ht; + bool allow_vht; + bool ht40plus; + /* note: power unit is 1/4th of dBm */ + u32 min_power; + u32 max_power; + u32 max_reg_power; + u32 max_antenna_gain; + u32 reg_class_id; + enum wmi_phy_mode mode; +}; + +enum wmi_channel_change_cause { + WMI_CHANNEL_CHANGE_CAUSE_NONE = 0, + WMI_CHANNEL_CHANGE_CAUSE_CSA, +}; + +#define WMI_CHAN_FLAG_HT40_PLUS (1 << 6) +#define WMI_CHAN_FLAG_PASSIVE (1 << 7) +#define WMI_CHAN_FLAG_ADHOC_ALLOWED (1 << 8) +#define WMI_CHAN_FLAG_AP_DISABLED (1 << 9) +#define WMI_CHAN_FLAG_DFS (1 << 10) +#define WMI_CHAN_FLAG_ALLOW_HT (1 << 11) +#define WMI_CHAN_FLAG_ALLOW_VHT (1 << 12) + +/* Indicate reason for channel switch */ +#define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13) + +#define WMI_MAX_SPATIAL_STREAM 3 + +/* HT Capabilities*/ +#define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ +#define WMI_HT_CAP_HT20_SGI 0x0002 /* Short Guard Interval with HT20 */ +#define WMI_HT_CAP_DYNAMIC_SMPS 0x0004 /* Dynamic MIMO powersave */ +#define WMI_HT_CAP_TX_STBC 0x0008 /* B3 TX STBC */ +#define WMI_HT_CAP_TX_STBC_MASK_SHIFT 3 +#define WMI_HT_CAP_RX_STBC 0x0030 /* B4-B5 RX STBC */ +#define WMI_HT_CAP_RX_STBC_MASK_SHIFT 4 +#define WMI_HT_CAP_LDPC 0x0040 /* LDPC supported */ +#define WMI_HT_CAP_L_SIG_TXOP_PROT 0x0080 /* L-SIG TXOP Protection */ +#define WMI_HT_CAP_MPDU_DENSITY 0x0700 /* MPDU Density */ +#define WMI_HT_CAP_MPDU_DENSITY_MASK_SHIFT 8 +#define WMI_HT_CAP_HT40_SGI 0x0800 + +#define WMI_HT_CAP_DEFAULT_ALL (WMI_HT_CAP_ENABLED | \ + WMI_HT_CAP_HT20_SGI | \ + WMI_HT_CAP_HT40_SGI | \ + WMI_HT_CAP_TX_STBC | \ + WMI_HT_CAP_RX_STBC | \ + WMI_HT_CAP_LDPC) + + +/* + * WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information + * field. The fields not defined here are not supported, or reserved. + * Do not change these masks and if you have to add new one follow the + * bitmask as specified by 802.11ac draft. + */ + +#define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003 +#define WMI_VHT_CAP_RX_LDPC 0x00000010 +#define WMI_VHT_CAP_SGI_80MHZ 0x00000020 +#define WMI_VHT_CAP_TX_STBC 0x00000080 +#define WMI_VHT_CAP_RX_STBC_MASK 0x00000300 +#define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8 +#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000 +#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23 +#define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000 +#define WMI_VHT_CAP_TX_FIXED_ANT 0x20000000 + +/* The following also refer for max HT AMSDU */ +#define WMI_VHT_CAP_MAX_MPDU_LEN_3839 0x00000000 +#define WMI_VHT_CAP_MAX_MPDU_LEN_7935 0x00000001 +#define WMI_VHT_CAP_MAX_MPDU_LEN_11454 0x00000002 + +#define WMI_VHT_CAP_DEFAULT_ALL (WMI_VHT_CAP_MAX_MPDU_LEN_11454 | \ + WMI_VHT_CAP_RX_LDPC | \ + WMI_VHT_CAP_SGI_80MHZ | \ + WMI_VHT_CAP_TX_STBC | \ + WMI_VHT_CAP_RX_STBC_MASK | \ + WMI_VHT_CAP_MAX_AMPDU_LEN_EXP | \ + WMI_VHT_CAP_RX_FIXED_ANT | \ + WMI_VHT_CAP_TX_FIXED_ANT) + +/* + * Interested readers refer to Rx/Tx MCS Map definition as defined in + * 802.11ac + */ +#define WMI_VHT_MAX_MCS_4_SS_MASK(r, ss) ((3 & (r)) << (((ss) - 1) << 1)) +#define WMI_VHT_MAX_SUPP_RATE_MASK 0x1fff0000 +#define WMI_VHT_MAX_SUPP_RATE_MASK_SHIFT 16 + +enum { + REGDMN_MODE_11A = 0x00001, /* 11a channels */ + REGDMN_MODE_TURBO = 0x00002, /* 11a turbo-only channels */ + REGDMN_MODE_11B = 0x00004, /* 11b channels */ + REGDMN_MODE_PUREG = 0x00008, /* 11g channels (OFDM only) */ + REGDMN_MODE_11G = 0x00008, /* XXX historical */ + REGDMN_MODE_108G = 0x00020, /* 11a+Turbo channels */ + REGDMN_MODE_108A = 0x00040, /* 11g+Turbo channels */ + REGDMN_MODE_XR = 0x00100, /* XR channels */ + REGDMN_MODE_11A_HALF_RATE = 0x00200, /* 11A half rate channels */ + REGDMN_MODE_11A_QUARTER_RATE = 0x00400, /* 11A quarter rate channels */ + REGDMN_MODE_11NG_HT20 = 0x00800, /* 11N-G HT20 channels */ + REGDMN_MODE_11NA_HT20 = 0x01000, /* 11N-A HT20 channels */ + REGDMN_MODE_11NG_HT40PLUS = 0x02000, /* 11N-G HT40 + channels */ + REGDMN_MODE_11NG_HT40MINUS = 0x04000, /* 11N-G HT40 - channels */ + REGDMN_MODE_11NA_HT40PLUS = 0x08000, /* 11N-A HT40 + channels */ + REGDMN_MODE_11NA_HT40MINUS = 0x10000, /* 11N-A HT40 - channels */ + REGDMN_MODE_11AC_VHT20 = 0x20000, /* 5Ghz, VHT20 */ + REGDMN_MODE_11AC_VHT40PLUS = 0x40000, /* 5Ghz, VHT40 + channels */ + REGDMN_MODE_11AC_VHT40MINUS = 0x80000, /* 5Ghz VHT40 - channels */ + REGDMN_MODE_11AC_VHT80 = 0x100000, /* 5Ghz, VHT80 channels */ + REGDMN_MODE_ALL = 0xffffffff +}; + +#define REGDMN_CAP1_CHAN_HALF_RATE 0x00000001 +#define REGDMN_CAP1_CHAN_QUARTER_RATE 0x00000002 +#define REGDMN_CAP1_CHAN_HAL49GHZ 0x00000004 + +/* regulatory capabilities */ +#define REGDMN_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U2 0x0100 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 +#define REGDMN_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 + +struct hal_reg_capabilities { + /* regdomain value specified in EEPROM */ + __le32 eeprom_rd; + /*regdomain */ + __le32 eeprom_rd_ext; + /* CAP1 capabilities bit map. */ + __le32 regcap1; + /* REGDMN EEPROM CAP. */ + __le32 regcap2; + /* REGDMN MODE */ + __le32 wireless_modes; + __le32 low_2ghz_chan; + __le32 high_2ghz_chan; + __le32 low_5ghz_chan; + __le32 high_5ghz_chan; +} __packed; + +enum wlan_mode_capability { + WHAL_WLAN_11A_CAPABILITY = 0x1, + WHAL_WLAN_11G_CAPABILITY = 0x2, + WHAL_WLAN_11AG_CAPABILITY = 0x3, +}; + +/* structure used by FW for requesting host memory */ +struct wlan_host_mem_req { + /* ID of the request */ + __le32 req_id; + /* size of the of each unit */ + __le32 unit_size; + /* flags to indicate that + * the number units is dependent + * on number of resources(num vdevs num peers .. etc) + */ + __le32 num_unit_info; + /* + * actual number of units to allocate . if flags in the num_unit_info + * indicate that number of units is tied to number of a particular + * resource to allocate then num_units filed is set to 0 and host + * will derive the number units from number of the resources it is + * requesting. + */ + __le32 num_units; +} __packed; + +#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \ + ((((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ + (1 << ((svc_id)%(sizeof(u32))))) != 0) + +/* + * The following struct holds optional payload for + * wmi_service_ready_event,e.g., 11ac pass some of the + * device capability to the host. + */ +struct wmi_service_ready_event { + __le32 sw_version; + __le32 sw_version_1; + __le32 abi_version; + /* WMI_PHY_CAPABILITY */ + __le32 phy_capability; + /* Maximum number of frag table entries that SW will populate less 1 */ + __le32 max_frag_entry; + __le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; + __le32 num_rf_chains; + /* + * The following field is only valid for service type + * WMI_SERVICE_11AC + */ + __le32 ht_cap_info; /* WMI HT Capability */ + __le32 vht_cap_info; /* VHT capability info field of 802.11ac */ + __le32 vht_supp_mcs; /* VHT Supported MCS Set field Rx/Tx same */ + __le32 hw_min_tx_power; + __le32 hw_max_tx_power; + struct hal_reg_capabilities hal_reg_capabilities; + __le32 sys_cap_info; + __le32 min_pkt_size_enable; /* Enterprise mode short pkt enable */ + /* + * Max beacon and Probe Response IE offload size + * (includes optional P2P IEs) + */ + __le32 max_bcn_ie_size; + /* + * request to host to allocate a chuck of memory and pss it down to FW + * via WM_INIT. FW uses this as FW extesnsion memory for saving its + * data structures. Only valid for low latency interfaces like PCIE + * where FW can access this memory directly (or) by DMA. + */ + __le32 num_mem_reqs; + struct wlan_host_mem_req mem_reqs[1]; +} __packed; + +/* + * status consists of upper 16 bits fo int status and lower 16 bits of + * module ID that retuned status + */ +#define WLAN_INIT_STATUS_SUCCESS 0x0 +#define WLAN_GET_INIT_STATUS_REASON(status) ((status) & 0xffff) +#define WLAN_GET_INIT_STATUS_MODULE_ID(status) (((status) >> 16) & 0xffff) + +#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) +#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) + +struct wmi_ready_event { + __le32 sw_version; + __le32 abi_version; + struct wmi_mac_addr mac_addr; + __le32 status; +} __packed; + +struct wmi_resource_config { + /* number of virtual devices (VAPs) to support */ + __le32 num_vdevs; + + /* number of peer nodes to support */ + __le32 num_peers; + + /* + * In offload mode target supports features like WOW, chatter and + * other protocol offloads. In order to support them some + * functionalities like reorder buffering, PN checking need to be + * done in target. This determines maximum number of peers suported + * by target in offload mode + */ + __le32 num_offload_peers; + + /* For target-based RX reordering */ + __le32 num_offload_reorder_bufs; + + /* number of keys per peer */ + __le32 num_peer_keys; + + /* total number of TX/RX data TIDs */ + __le32 num_tids; + + /* + * max skid for resolving hash collisions + * + * The address search table is sparse, so that if two MAC addresses + * result in the same hash value, the second of these conflicting + * entries can slide to the next index in the address search table, + * and use it, if it is unoccupied. This ast_skid_limit parameter + * specifies the upper bound on how many subsequent indices to search + * over to find an unoccupied space. + */ + __le32 ast_skid_limit; + + /* + * the nominal chain mask for transmit + * + * The chain mask may be modified dynamically, e.g. to operate AP + * tx with a reduced number of chains if no clients are associated. + * This configuration parameter specifies the nominal chain-mask that + * should be used when not operating with a reduced set of tx chains. + */ + __le32 tx_chain_mask; + + /* + * the nominal chain mask for receive + * + * The chain mask may be modified dynamically, e.g. for a client + * to use a reduced number of chains for receive if the traffic to + * the client is low enough that it doesn't require downlink MIMO + * or antenna diversity. + * This configuration parameter specifies the nominal chain-mask that + * should be used when not operating with a reduced set of rx chains. + */ + __le32 rx_chain_mask; + + /* + * what rx reorder timeout (ms) to use for the AC + * + * Each WMM access class (voice, video, best-effort, background) will + * have its own timeout value to dictate how long to wait for missing + * rx MPDUs to arrive before flushing subsequent MPDUs that have + * already been received. + * This parameter specifies the timeout in milliseconds for each + * class. + */ + __le32 rx_timeout_pri_vi; + __le32 rx_timeout_pri_vo; + __le32 rx_timeout_pri_be; + __le32 rx_timeout_pri_bk; + + /* + * what mode the rx should decap packets to + * + * MAC can decap to RAW (no decap), native wifi or Ethernet types + * THis setting also determines the default TX behavior, however TX + * behavior can be modified on a per VAP basis during VAP init + */ + __le32 rx_decap_mode; + + /* what is the maximum scan requests than can be queued */ + __le32 scan_max_pending_reqs; + + /* maximum VDEV that could use BMISS offload */ + __le32 bmiss_offload_max_vdev; + + /* maximum VDEV that could use offload roaming */ + __le32 roam_offload_max_vdev; + + /* maximum AP profiles that would push to offload roaming */ + __le32 roam_offload_max_ap_profiles; + + /* + * how many groups to use for mcast->ucast conversion + * + * The target's WAL maintains a table to hold information regarding + * which peers belong to a given multicast group, so that if + * multicast->unicast conversion is enabled, the target can convert + * multicast tx frames to a series of unicast tx frames, to each + * peer within the multicast group. + This num_mcast_groups configuration parameter tells the target how + * many multicast groups to provide storage for within its multicast + * group membership table. + */ + __le32 num_mcast_groups; + + /* + * size to alloc for the mcast membership table + * + * This num_mcast_table_elems configuration parameter tells the + * target how many peer elements it needs to provide storage for in + * its multicast group membership table. + * These multicast group membership table elements are shared by the + * multicast groups stored within the table. + */ + __le32 num_mcast_table_elems; + + /* + * whether/how to do multicast->unicast conversion + * + * This configuration parameter specifies whether the target should + * perform multicast --> unicast conversion on transmit, and if so, + * what to do if it finds no entries in its multicast group + * membership table for the multicast IP address in the tx frame. + * Configuration value: + * 0 -> Do not perform multicast to unicast conversion. + * 1 -> Convert multicast frames to unicast, if the IP multicast + * address from the tx frame is found in the multicast group + * membership table. If the IP multicast address is not found, + * drop the frame. + * 2 -> Convert multicast frames to unicast, if the IP multicast + * address from the tx frame is found in the multicast group + * membership table. If the IP multicast address is not found, + * transmit the frame as multicast. + */ + __le32 mcast2ucast_mode; + + /* + * how much memory to allocate for a tx PPDU dbg log + * + * This parameter controls how much memory the target will allocate + * to store a log of tx PPDU meta-information (how large the PPDU + * was, when it was sent, whether it was successful, etc.) + */ + __le32 tx_dbg_log_size; + + /* how many AST entries to be allocated for WDS */ + __le32 num_wds_entries; + + /* + * MAC DMA burst size, e.g., For target PCI limit can be + * 0 -default, 1 256B + */ + __le32 dma_burst_size; + + /* + * Fixed delimiters to be inserted after every MPDU to + * account for interface latency to avoid underrun. + */ + __le32 mac_aggr_delim; + + /* + * determine whether target is responsible for detecting duplicate + * non-aggregate MPDU and timing out stale fragments. + * + * A-MPDU reordering is always performed on the target. + * + * 0: target responsible for frag timeout and dup checking + * 1: host responsible for frag timeout and dup checking + */ + __le32 rx_skip_defrag_timeout_dup_detection_check; + + /* + * Configuration for VoW : + * No of Video Nodes to be supported + * and Max no of descriptors for each Video link (node). + */ + __le32 vow_config; + + /* maximum VDEV that could use GTK offload */ + __le32 gtk_offload_max_vdev; + + /* Number of msdu descriptors target should use */ + __le32 num_msdu_desc; + + /* + * Max. number of Tx fragments per MSDU + * This parameter controls the max number of Tx fragments per MSDU. + * This is sent by the target as part of the WMI_SERVICE_READY event + * and is overriden by the OS shim as required. + */ + __le32 max_frag_entries; +} __packed; + +/* strucutre describing host memory chunk. */ +struct host_memory_chunk { + /* id of the request that is passed up in service ready */ + __le32 req_id; + /* the physical address the memory chunk */ + __le32 ptr; + /* size of the chunk */ + __le32 size; +} __packed; + +struct wmi_init_cmd { + struct wmi_resource_config resource_config; + __le32 num_host_mem_chunks; + + /* + * variable number of host memory chunks. + * This should be the last element in the structure + */ + struct host_memory_chunk host_mem_chunks[1]; +} __packed; + +/* TLV for channel list */ +struct wmi_chan_list { + __le32 tag; /* WMI_CHAN_LIST_TAG */ + __le32 num_chan; + __le32 channel_list[0]; +} __packed; + +struct wmi_bssid_list { + __le32 tag; /* WMI_BSSID_LIST_TAG */ + __le32 num_bssid; + struct wmi_mac_addr bssid_list[0]; +} __packed; + +struct wmi_ie_data { + __le32 tag; /* WMI_IE_TAG */ + __le32 ie_len; + u8 ie_data[0]; +} __packed; + +struct wmi_ssid { + __le32 ssid_len; + u8 ssid[32]; +} __packed; + +struct wmi_ssid_list { + __le32 tag; /* WMI_SSID_LIST_TAG */ + __le32 num_ssids; + struct wmi_ssid ssids[0]; +} __packed; + +/* prefix used by scan requestor ids on the host */ +#define WMI_HOST_SCAN_REQUESTOR_ID_PREFIX 0xA000 + +/* prefix used by scan request ids generated on the host */ +/* host cycles through the lower 12 bits to generate ids */ +#define WMI_HOST_SCAN_REQ_ID_PREFIX 0xA000 + +#define WLAN_SCAN_PARAMS_MAX_SSID 16 +#define WLAN_SCAN_PARAMS_MAX_BSSID 4 +#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256 + +/* Scan priority numbers must be sequential, starting with 0 */ +enum wmi_scan_priority { + WMI_SCAN_PRIORITY_VERY_LOW = 0, + WMI_SCAN_PRIORITY_LOW, + WMI_SCAN_PRIORITY_MEDIUM, + WMI_SCAN_PRIORITY_HIGH, + WMI_SCAN_PRIORITY_VERY_HIGH, + WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ +}; + +struct wmi_start_scan_cmd { + /* Scan ID */ + __le32 scan_id; + /* Scan requestor ID */ + __le32 scan_req_id; + /* VDEV id(interface) that is requesting scan */ + __le32 vdev_id; + /* Scan Priority, input to scan scheduler */ + __le32 scan_priority; + /* Scan events subscription */ + __le32 notify_scan_events; + /* dwell time in msec on active channels */ + __le32 dwell_time_active; + /* dwell time in msec on passive channels */ + __le32 dwell_time_passive; + /* + * min time in msec on the BSS channel,only valid if atleast one + * VDEV is active + */ + __le32 min_rest_time; + /* + * max rest time in msec on the BSS channel,only valid if at least + * one VDEV is active + */ + /* + * the scanner will rest on the bss channel at least min_rest_time + * after min_rest_time the scanner will start checking for tx/rx + * activity on all VDEVs. if there is no activity the scanner will + * switch to off channel. if there is activity the scanner will let + * the radio on the bss channel until max_rest_time expires.at + * max_rest_time scanner will switch to off channel irrespective of + * activity. activity is determined by the idle_time parameter. + */ + __le32 max_rest_time; + /* + * time before sending next set of probe requests. + * The scanner keeps repeating probe requests transmission with + * period specified by repeat_probe_time. + * The number of probe requests specified depends on the ssid_list + * and bssid_list + */ + __le32 repeat_probe_time; + /* time in msec between 2 consequetive probe requests with in a set. */ + __le32 probe_spacing_time; + /* + * data inactivity time in msec on bss channel that will be used by + * scanner for measuring the inactivity. + */ + __le32 idle_time; + /* maximum time in msec allowed for scan */ + __le32 max_scan_time; + /* + * delay in msec before sending first probe request after switching + * to a channel + */ + __le32 probe_delay; + /* Scan control flags */ + __le32 scan_ctrl_flags; + + /* Burst duration time in msecs */ + __le32 burst_duration; + /* + * TLV (tag length value ) paramerters follow the scan_cmd structure. + * TLV can contain channel list, bssid list, ssid list and + * ie. the TLV tags are defined above; + */ +} __packed; + +struct wmi_ssid_arg { + int len; + const u8 *ssid; +}; + +struct wmi_bssid_arg { + const u8 *bssid; +}; + +struct wmi_start_scan_arg { + u32 scan_id; + u32 scan_req_id; + u32 vdev_id; + u32 scan_priority; + u32 notify_scan_events; + u32 dwell_time_active; + u32 dwell_time_passive; + u32 min_rest_time; + u32 max_rest_time; + u32 repeat_probe_time; + u32 probe_spacing_time; + u32 idle_time; + u32 max_scan_time; + u32 probe_delay; + u32 scan_ctrl_flags; + + u32 ie_len; + u32 n_channels; + u32 n_ssids; + u32 n_bssids; + + u8 ie[WLAN_SCAN_PARAMS_MAX_IE_LEN]; + u32 channels[64]; + struct wmi_ssid_arg ssids[WLAN_SCAN_PARAMS_MAX_SSID]; + struct wmi_bssid_arg bssids[WLAN_SCAN_PARAMS_MAX_BSSID]; +}; + +/* scan control flags */ + +/* passively scan all channels including active channels */ +#define WMI_SCAN_FLAG_PASSIVE 0x1 +/* add wild card ssid probe request even though ssid_list is specified. */ +#define WMI_SCAN_ADD_BCAST_PROBE_REQ 0x2 +/* add cck rates to rates/xrate ie for the generated probe request */ +#define WMI_SCAN_ADD_CCK_RATES 0x4 +/* add ofdm rates to rates/xrate ie for the generated probe request */ +#define WMI_SCAN_ADD_OFDM_RATES 0x8 +/* To enable indication of Chan load and Noise floor to host */ +#define WMI_SCAN_CHAN_STAT_EVENT 0x10 +/* Filter Probe request frames */ +#define WMI_SCAN_FILTER_PROBE_REQ 0x20 +/* When set, DFS channels will not be scanned */ +#define WMI_SCAN_BYPASS_DFS_CHN 0x40 +/* Different FW scan engine may choose to bail out on errors. + * Allow the driver to have influence over that. */ +#define WMI_SCAN_CONTINUE_ON_ERROR 0x80 + +/* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */ +#define WMI_SCAN_CLASS_MASK 0xFF000000 + + +enum wmi_stop_scan_type { + WMI_SCAN_STOP_ONE = 0x00000000, /* stop by scan_id */ + WMI_SCAN_STOP_VDEV_ALL = 0x01000000, /* stop by vdev_id */ + WMI_SCAN_STOP_ALL = 0x04000000, /* stop all scans */ +}; + +struct wmi_stop_scan_cmd { + __le32 scan_req_id; + __le32 scan_id; + __le32 req_type; + __le32 vdev_id; +} __packed; + +struct wmi_stop_scan_arg { + u32 req_id; + enum wmi_stop_scan_type req_type; + union { + u32 scan_id; + u32 vdev_id; + } u; +}; + +struct wmi_scan_chan_list_cmd { + __le32 num_scan_chans; + struct wmi_channel chan_info[0]; +} __packed; + +struct wmi_scan_chan_list_arg { + u32 n_channels; + struct wmi_channel_arg *channels; +}; + +enum wmi_bss_filter { + WMI_BSS_FILTER_NONE = 0, /* no beacons forwarded */ + WMI_BSS_FILTER_ALL, /* all beacons forwarded */ + WMI_BSS_FILTER_PROFILE, /* only beacons matching profile */ + WMI_BSS_FILTER_ALL_BUT_PROFILE, /* all but beacons matching profile */ + WMI_BSS_FILTER_CURRENT_BSS, /* only beacons matching current BSS */ + WMI_BSS_FILTER_ALL_BUT_BSS, /* all but beacons matching BSS */ + WMI_BSS_FILTER_PROBED_SSID, /* beacons matching probed ssid */ + WMI_BSS_FILTER_LAST_BSS, /* marker only */ +}; + +enum wmi_scan_event_type { + WMI_SCAN_EVENT_STARTED = 0x1, + WMI_SCAN_EVENT_COMPLETED = 0x2, + WMI_SCAN_EVENT_BSS_CHANNEL = 0x4, + WMI_SCAN_EVENT_FOREIGN_CHANNEL = 0x8, + WMI_SCAN_EVENT_DEQUEUED = 0x10, + WMI_SCAN_EVENT_PREEMPTED = 0x20, /* possibly by high-prio scan */ + WMI_SCAN_EVENT_START_FAILED = 0x40, + WMI_SCAN_EVENT_RESTARTED = 0x80, + WMI_SCAN_EVENT_MAX = 0x8000 +}; + +enum wmi_scan_completion_reason { + WMI_SCAN_REASON_COMPLETED, + WMI_SCAN_REASON_CANCELLED, + WMI_SCAN_REASON_PREEMPTED, + WMI_SCAN_REASON_TIMEDOUT, + WMI_SCAN_REASON_MAX, +}; + +struct wmi_scan_event { + __le32 event_type; /* %WMI_SCAN_EVENT_ */ + __le32 reason; /* %WMI_SCAN_REASON_ */ + __le32 channel_freq; /* only valid for WMI_SCAN_EVENT_FOREIGN_CHANNEL */ + __le32 scan_req_id; + __le32 scan_id; + __le32 vdev_id; +} __packed; + +/* + * This defines how much headroom is kept in the + * receive frame between the descriptor and the + * payload, in order for the WMI PHY error and + * management handler to insert header contents. + * + * This is in bytes. + */ +#define WMI_MGMT_RX_HDR_HEADROOM 52 + +/* + * This event will be used for sending scan results + * as well as rx mgmt frames to the host. The rx buffer + * will be sent as part of this WMI event. It would be a + * good idea to pass all the fields in the RX status + * descriptor up to the host. + */ +struct wmi_mgmt_rx_hdr { + __le32 channel; + __le32 snr; + __le32 rate; + __le32 phy_mode; + __le32 buf_len; + __le32 status; /* %WMI_RX_STATUS_ */ +} __packed; + +struct wmi_mgmt_rx_event { + struct wmi_mgmt_rx_hdr hdr; + u8 buf[0]; +} __packed; + +#define WMI_RX_STATUS_OK 0x00 +#define WMI_RX_STATUS_ERR_CRC 0x01 +#define WMI_RX_STATUS_ERR_DECRYPT 0x08 +#define WMI_RX_STATUS_ERR_MIC 0x10 +#define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20 + +struct wmi_single_phyerr_rx_hdr { + /* TSF timestamp */ + __le32 tsf_timestamp; + + /* + * Current freq1, freq2 + * + * [7:0]: freq1[lo] + * [15:8] : freq1[hi] + * [23:16]: freq2[lo] + * [31:24]: freq2[hi] + */ + __le16 freq1; + __le16 freq2; + + /* + * Combined RSSI over all chains and channel width for this PHY error + * + * [7:0]: RSSI combined + * [15:8]: Channel width (MHz) + * [23:16]: PHY error code + * [24:16]: reserved (future use) + */ + u8 rssi_combined; + u8 chan_width_mhz; + u8 phy_err_code; + u8 rsvd0; + + /* + * RSSI on chain 0 through 3 + * + * This is formatted the same as the PPDU_START RX descriptor + * field: + * + * [7:0]: pri20 + * [15:8]: sec20 + * [23:16]: sec40 + * [31:24]: sec80 + */ + + __le32 rssi_chain0; + __le32 rssi_chain1; + __le32 rssi_chain2; + __le32 rssi_chain3; + + /* + * Last calibrated NF value for chain 0 through 3 + * + * nf_list_1: + * + * + [15:0] - chain 0 + * + [31:16] - chain 1 + * + * nf_list_2: + * + * + [15:0] - chain 2 + * + [31:16] - chain 3 + */ + __le32 nf_list_1; + __le32 nf_list_2; + + + /* Length of the frame */ + __le32 buf_len; +} __packed; + +struct wmi_single_phyerr_rx_event { + /* Phy error event header */ + struct wmi_single_phyerr_rx_hdr hdr; + /* frame buffer */ + u8 bufp[0]; +} __packed; + +struct wmi_comb_phyerr_rx_hdr { + /* Phy error phy error count */ + __le32 num_phyerr_events; + __le32 tsf_l32; + __le32 tsf_u32; +} __packed; + +struct wmi_comb_phyerr_rx_event { + /* Phy error phy error count */ + struct wmi_comb_phyerr_rx_hdr hdr; + /* + * frame buffer - contains multiple payloads in the order: + * header - payload, header - payload... + * (The header is of type: wmi_single_phyerr_rx_hdr) + */ + u8 bufp[0]; +} __packed; + +struct wmi_mgmt_tx_hdr { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; + __le32 tx_rate; + __le32 tx_power; + __le32 buf_len; +} __packed; + +struct wmi_mgmt_tx_cmd { + struct wmi_mgmt_tx_hdr hdr; + u8 buf[0]; +} __packed; + +struct wmi_echo_event { + __le32 value; +} __packed; + +struct wmi_echo_cmd { + __le32 value; +} __packed; + + +struct wmi_pdev_set_regdomain_cmd { + __le32 reg_domain; + __le32 reg_domain_2G; + __le32 reg_domain_5G; + __le32 conformance_test_limit_2G; + __le32 conformance_test_limit_5G; +} __packed; + +/* Command to set/unset chip in quiet mode */ +struct wmi_pdev_set_quiet_cmd { + /* period in TUs */ + __le32 period; + + /* duration in TUs */ + __le32 duration; + + /* offset in TUs */ + __le32 next_start; + + /* enable/disable */ + __le32 enabled; +} __packed; + + +/* + * 802.11g protection mode. + */ +enum ath10k_protmode { + ATH10K_PROT_NONE = 0, /* no protection */ + ATH10K_PROT_CTSONLY = 1, /* CTS to self */ + ATH10K_PROT_RTSCTS = 2, /* RTS-CTS */ +}; + +enum wmi_beacon_gen_mode { + WMI_BEACON_STAGGERED_MODE = 0, + WMI_BEACON_BURST_MODE = 1 +}; + +enum wmi_csa_event_ies_present_flag { + WMI_CSA_IE_PRESENT = 0x00000001, + WMI_XCSA_IE_PRESENT = 0x00000002, + WMI_WBW_IE_PRESENT = 0x00000004, + WMI_CSWARP_IE_PRESENT = 0x00000008, +}; + +/* wmi CSA receive event from beacon frame */ +struct wmi_csa_event { + __le32 i_fc_dur; + /* Bit 0-15: FC */ + /* Bit 16-31: DUR */ + struct wmi_mac_addr i_addr1; + struct wmi_mac_addr i_addr2; + __le32 csa_ie[2]; + __le32 xcsa_ie[2]; + __le32 wb_ie[2]; + __le32 cswarp_ie; + __le32 ies_present_flag; /* wmi_csa_event_ies_present_flag */ +} __packed; + +/* the definition of different PDEV parameters */ +#define PDEV_DEFAULT_STATS_UPDATE_PERIOD 500 +#define VDEV_DEFAULT_STATS_UPDATE_PERIOD 500 +#define PEER_DEFAULT_STATS_UPDATE_PERIOD 500 + +enum wmi_pdev_param { + /* TX chian mask */ + WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1, + /* RX chian mask */ + WMI_PDEV_PARAM_RX_CHAIN_MASK, + /* TX power limit for 2G Radio */ + WMI_PDEV_PARAM_TXPOWER_LIMIT2G, + /* TX power limit for 5G Radio */ + WMI_PDEV_PARAM_TXPOWER_LIMIT5G, + /* TX power scale */ + WMI_PDEV_PARAM_TXPOWER_SCALE, + /* Beacon generation mode . 0: host, 1: target */ + WMI_PDEV_PARAM_BEACON_GEN_MODE, + /* Beacon generation mode . 0: staggered 1: bursted */ + WMI_PDEV_PARAM_BEACON_TX_MODE, + /* + * Resource manager off chan mode . + * 0: turn off off chan mode. 1: turn on offchan mode + */ + WMI_PDEV_PARAM_RESMGR_OFFCHAN_MODE, + /* + * Protection mode: + * 0: no protection 1:use CTS-to-self 2: use RTS/CTS + */ + WMI_PDEV_PARAM_PROTECTION_MODE, + /* Dynamic bandwidth 0: disable 1: enable */ + WMI_PDEV_PARAM_DYNAMIC_BW, + /* Non aggregrate/ 11g sw retry threshold.0-disable */ + WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, + /* aggregrate sw retry threshold. 0-disable*/ + WMI_PDEV_PARAM_AGG_SW_RETRY_TH, + /* Station kickout threshold (non of consecutive failures).0-disable */ + WMI_PDEV_PARAM_STA_KICKOUT_TH, + /* Aggerate size scaling configuration per AC */ + WMI_PDEV_PARAM_AC_AGGRSIZE_SCALING, + /* LTR enable */ + WMI_PDEV_PARAM_LTR_ENABLE, + /* LTR latency for BE, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_BE, + /* LTR latency for BK, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_BK, + /* LTR latency for VI, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_VI, + /* LTR latency for VO, in us */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_VO, + /* LTR AC latency timeout, in ms */ + WMI_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, + /* LTR platform latency override, in us */ + WMI_PDEV_PARAM_LTR_SLEEP_OVERRIDE, + /* LTR-RX override, in us */ + WMI_PDEV_PARAM_LTR_RX_OVERRIDE, + /* Tx activity timeout for LTR, in us */ + WMI_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, + /* L1SS state machine enable */ + WMI_PDEV_PARAM_L1SS_ENABLE, + /* Deep sleep state machine enable */ + WMI_PDEV_PARAM_DSLEEP_ENABLE, + /* RX buffering flush enable */ + WMI_PDEV_PARAM_PCIELP_TXBUF_FLUSH, + /* RX buffering matermark */ + WMI_PDEV_PARAM_PCIELP_TXBUF_WATERMARK, + /* RX buffering timeout enable */ + WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, + /* RX buffering timeout value */ + WMI_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, + /* pdev level stats update period in ms */ + WMI_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, + /* vdev level stats update period in ms */ + WMI_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, + /* peer level stats update period in ms */ + WMI_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, + /* beacon filter status update period */ + WMI_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, + /* QOS Mgmt frame protection MFP/PMF 0: disable, 1: enable */ + WMI_PDEV_PARAM_PMF_QOS, + /* Access category on which ARP frames are sent */ + WMI_PDEV_PARAM_ARP_AC_OVERRIDE, + /* DCS configuration */ + WMI_PDEV_PARAM_DCS, + /* Enable/Disable ANI on target */ + WMI_PDEV_PARAM_ANI_ENABLE, + /* configure the ANI polling period */ + WMI_PDEV_PARAM_ANI_POLL_PERIOD, + /* configure the ANI listening period */ + WMI_PDEV_PARAM_ANI_LISTEN_PERIOD, + /* configure OFDM immunity level */ + WMI_PDEV_PARAM_ANI_OFDM_LEVEL, + /* configure CCK immunity level */ + WMI_PDEV_PARAM_ANI_CCK_LEVEL, + /* Enable/Disable CDD for 1x1 STAs in rate control module */ + WMI_PDEV_PARAM_DYNTXCHAIN, + /* Enable/Disable proxy STA */ + WMI_PDEV_PARAM_PROXY_STA, + /* Enable/Disable low power state when all VDEVs are inactive/idle. */ + WMI_PDEV_PARAM_IDLE_PS_CONFIG, + /* Enable/Disable power gating sleep */ + WMI_PDEV_PARAM_POWER_GATING_SLEEP, +}; + +struct wmi_pdev_set_param_cmd { + __le32 param_id; + __le32 param_value; +} __packed; + +struct wmi_pdev_get_tpc_config_cmd { + /* parameter */ + __le32 param; +} __packed; + +#define WMI_TPC_RATE_MAX 160 +#define WMI_TPC_TX_N_CHAIN 4 + +enum wmi_tpc_config_event_flag { + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD = 0x1, + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC = 0x2, + WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF = 0x4, +}; + +struct wmi_pdev_tpc_config_event { + __le32 reg_domain; + __le32 chan_freq; + __le32 phy_mode; + __le32 twice_antenna_reduction; + __le32 twice_max_rd_power; + s32 twice_antenna_gain; + __le32 power_limit; + __le32 rate_max; + __le32 num_tx_chain; + __le32 ctl; + __le32 flags; + s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN]; + s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; + s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; + s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN]; + u8 rates_array[WMI_TPC_RATE_MAX]; +} __packed; + +/* Transmit power scale factor. */ +enum wmi_tp_scale { + WMI_TP_SCALE_MAX = 0, /* no scaling (default) */ + WMI_TP_SCALE_50 = 1, /* 50% of max (-3 dBm) */ + WMI_TP_SCALE_25 = 2, /* 25% of max (-6 dBm) */ + WMI_TP_SCALE_12 = 3, /* 12% of max (-9 dBm) */ + WMI_TP_SCALE_MIN = 4, /* min, but still on */ + WMI_TP_SCALE_SIZE = 5, /* max num of enum */ +}; + +struct wmi_set_channel_cmd { + /* channel (only frequency and mode info are used) */ + struct wmi_channel chan; +} __packed; + +struct wmi_pdev_chanlist_update_event { + /* number of channels */ + __le32 num_chan; + /* array of channels */ + struct wmi_channel channel_list[1]; +} __packed; + +#define WMI_MAX_DEBUG_MESG (sizeof(u32) * 32) + +struct wmi_debug_mesg_event { + /* message buffer, NULL terminated */ + char bufp[WMI_MAX_DEBUG_MESG]; +} __packed; + +enum { + /* P2P device */ + VDEV_SUBTYPE_P2PDEV = 0, + /* P2P client */ + VDEV_SUBTYPE_P2PCLI, + /* P2P GO */ + VDEV_SUBTYPE_P2PGO, + /* BT3.0 HS */ + VDEV_SUBTYPE_BT, +}; + +struct wmi_pdev_set_channel_cmd { + /* idnore power , only use flags , mode and freq */ + struct wmi_channel chan; +} __packed; + +/* Customize the DSCP (bit) to TID (0-7) mapping for QOS */ +#define WMI_DSCP_MAP_MAX (64) +struct wmi_pdev_set_dscp_tid_map_cmd { + /* map indicating DSCP to TID conversion */ + __le32 dscp_to_tid_map[WMI_DSCP_MAP_MAX]; +} __packed; + +enum mcast_bcast_rate_id { + WMI_SET_MCAST_RATE, + WMI_SET_BCAST_RATE +}; + +struct mcast_bcast_rate { + enum mcast_bcast_rate_id rate_id; + __le32 rate; +} __packed; + +struct wmi_wmm_params { + __le32 cwmin; + __le32 cwmax; + __le32 aifs; + __le32 txop; + __le32 acm; + __le32 no_ack; +} __packed; + +struct wmi_pdev_set_wmm_params { + struct wmi_wmm_params ac_be; + struct wmi_wmm_params ac_bk; + struct wmi_wmm_params ac_vi; + struct wmi_wmm_params ac_vo; +} __packed; + +struct wmi_wmm_params_arg { + u32 cwmin; + u32 cwmax; + u32 aifs; + u32 txop; + u32 acm; + u32 no_ack; +}; + +struct wmi_pdev_set_wmm_params_arg { + struct wmi_wmm_params_arg ac_be; + struct wmi_wmm_params_arg ac_bk; + struct wmi_wmm_params_arg ac_vi; + struct wmi_wmm_params_arg ac_vo; +}; + +struct wal_dbg_tx_stats { + /* Num HTT cookies queued to dispatch list */ + __le32 comp_queued; + + /* Num HTT cookies dispatched */ + __le32 comp_delivered; + + /* Num MSDU queued to WAL */ + __le32 msdu_enqued; + + /* Num MPDU queue to WAL */ + __le32 mpdu_enqued; + + /* Num MSDUs dropped by WMM limit */ + __le32 wmm_drop; + + /* Num Local frames queued */ + __le32 local_enqued; + + /* Num Local frames done */ + __le32 local_freed; + + /* Num queued to HW */ + __le32 hw_queued; + + /* Num PPDU reaped from HW */ + __le32 hw_reaped; + + /* Num underruns */ + __le32 underrun; + + /* Num PPDUs cleaned up in TX abort */ + __le32 tx_abort; + + /* Num MPDUs requed by SW */ + __le32 mpdus_requed; + + /* excessive retries */ + __le32 tx_ko; + + /* data hw rate code */ + __le32 data_rc; + + /* Scheduler self triggers */ + __le32 self_triggers; + + /* frames dropped due to excessive sw retries */ + __le32 sw_retry_failure; + + /* illegal rate phy errors */ + __le32 illgl_rate_phy_err; + + /* wal pdev continous xretry */ + __le32 pdev_cont_xretry; + + /* wal pdev continous xretry */ + __le32 pdev_tx_timeout; + + /* wal pdev resets */ + __le32 pdev_resets; + + __le32 phy_underrun; + + /* MPDU is more than txop limit */ + __le32 txop_ovf; +} __packed; + +struct wal_dbg_rx_stats { + /* Cnts any change in ring routing mid-ppdu */ + __le32 mid_ppdu_route_change; + + /* Total number of statuses processed */ + __le32 status_rcvd; + + /* Extra frags on rings 0-3 */ + __le32 r0_frags; + __le32 r1_frags; + __le32 r2_frags; + __le32 r3_frags; + + /* MSDUs / MPDUs delivered to HTT */ + __le32 htt_msdus; + __le32 htt_mpdus; + + /* MSDUs / MPDUs delivered to local stack */ + __le32 loc_msdus; + __le32 loc_mpdus; + + /* AMSDUs that have more MSDUs than the status ring size */ + __le32 oversize_amsdu; + + /* Number of PHY errors */ + __le32 phy_errs; + + /* Number of PHY errors drops */ + __le32 phy_err_drop; + + /* Number of mpdu errors - FCS, MIC, ENC etc. */ + __le32 mpdu_errs; +} __packed; + +struct wal_dbg_peer_stats { + /* REMOVE THIS ONCE REAL PEER STAT COUNTERS ARE ADDED */ + __le32 dummy; +} __packed; + +struct wal_dbg_stats { + struct wal_dbg_tx_stats tx; + struct wal_dbg_rx_stats rx; + struct wal_dbg_peer_stats peer; +} __packed; + +enum wmi_stats_id { + WMI_REQUEST_PEER_STAT = 0x01, + WMI_REQUEST_AP_STAT = 0x02 +}; + +struct wmi_request_stats_cmd { + __le32 stats_id; + + /* + * Space to add parameters like + * peer mac addr + */ +} __packed; + +/* Suspend option */ +enum { + /* suspend */ + WMI_PDEV_SUSPEND, + + /* suspend and disable all interrupts */ + WMI_PDEV_SUSPEND_AND_DISABLE_INTR, +}; + +struct wmi_pdev_suspend_cmd { + /* suspend option sent to target */ + __le32 suspend_opt; +} __packed; + +struct wmi_stats_event { + __le32 stats_id; /* %WMI_REQUEST_ */ + /* + * number of pdev stats event structures + * (wmi_pdev_stats) 0 or 1 + */ + __le32 num_pdev_stats; + /* + * number of vdev stats event structures + * (wmi_vdev_stats) 0 or max vdevs + */ + __le32 num_vdev_stats; + /* + * number of peer stats event structures + * (wmi_peer_stats) 0 or max peers + */ + __le32 num_peer_stats; + __le32 num_bcnflt_stats; + /* + * followed by + * num_pdev_stats * size of(struct wmi_pdev_stats) + * num_vdev_stats * size of(struct wmi_vdev_stats) + * num_peer_stats * size of(struct wmi_peer_stats) + * + * By having a zero sized array, the pointer to data area + * becomes available without increasing the struct size + */ + u8 data[0]; +} __packed; + +/* + * PDEV statistics + * TODO: add all PDEV stats here + */ +struct wmi_pdev_stats { + __le32 chan_nf; /* Channel noise floor */ + __le32 tx_frame_count; /* TX frame count */ + __le32 rx_frame_count; /* RX frame count */ + __le32 rx_clear_count; /* rx clear count */ + __le32 cycle_count; /* cycle count */ + __le32 phy_err_count; /* Phy error count */ + __le32 chan_tx_pwr; /* channel tx power */ + struct wal_dbg_stats wal; /* WAL dbg stats */ +} __packed; + +/* + * VDEV statistics + * TODO: add all VDEV stats here + */ +struct wmi_vdev_stats { + __le32 vdev_id; +} __packed; + +/* + * peer statistics. + * TODO: add more stats + */ +struct wmi_peer_stats { + struct wmi_mac_addr peer_macaddr; + __le32 peer_rssi; + __le32 peer_tx_rate; +} __packed; + +struct wmi_vdev_create_cmd { + __le32 vdev_id; + __le32 vdev_type; + __le32 vdev_subtype; + struct wmi_mac_addr vdev_macaddr; +} __packed; + +enum wmi_vdev_type { + WMI_VDEV_TYPE_AP = 1, + WMI_VDEV_TYPE_STA = 2, + WMI_VDEV_TYPE_IBSS = 3, + WMI_VDEV_TYPE_MONITOR = 4, +}; + +enum wmi_vdev_subtype { + WMI_VDEV_SUBTYPE_NONE = 0, + WMI_VDEV_SUBTYPE_P2P_DEVICE = 1, + WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, + WMI_VDEV_SUBTYPE_P2P_GO = 3, +}; + +/* values for vdev_subtype */ + +/* values for vdev_start_request flags */ +/* + * Indicates that AP VDEV uses hidden ssid. only valid for + * AP/GO */ +#define WMI_VDEV_START_HIDDEN_SSID (1<<0) +/* + * Indicates if robust management frame/management frame + * protection is enabled. For GO/AP vdevs, it indicates that + * it may support station/client associations with RMF enabled. + * For STA/client vdevs, it indicates that sta will + * associate with AP with RMF enabled. */ +#define WMI_VDEV_START_PMF_ENABLED (1<<1) + +struct wmi_p2p_noa_descriptor { + __le32 type_count; /* 255: continuous schedule, 0: reserved */ + __le32 duration; /* Absent period duration in micro seconds */ + __le32 interval; /* Absent period interval in micro seconds */ + __le32 start_time; /* 32 bit tsf time when in starts */ +} __packed; + +struct wmi_vdev_start_request_cmd { + /* WMI channel */ + struct wmi_channel chan; + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* requestor id identifying the caller module */ + __le32 requestor_id; + /* beacon interval from received beacon */ + __le32 beacon_interval; + /* DTIM Period from the received beacon */ + __le32 dtim_period; + /* Flags */ + __le32 flags; + /* ssid field. Only valid for AP/GO/IBSS/BTAmp VDEV type. */ + struct wmi_ssid ssid; + /* beacon/probe reponse xmit rate. Applicable for SoftAP. */ + __le32 bcn_tx_rate; + /* beacon/probe reponse xmit power. Applicable for SoftAP. */ + __le32 bcn_tx_power; + /* number of p2p NOA descriptor(s) from scan entry */ + __le32 num_noa_descriptors; + /* + * Disable H/W ack. This used by WMI_VDEV_RESTART_REQUEST_CMDID. + * During CAC, Our HW shouldn't ack ditected frames + */ + __le32 disable_hw_ack; + /* actual p2p NOA descriptor from scan entry */ + struct wmi_p2p_noa_descriptor noa_descriptors[2]; +} __packed; + +struct wmi_vdev_restart_request_cmd { + struct wmi_vdev_start_request_cmd vdev_start_request_cmd; +} __packed; + +struct wmi_vdev_start_request_arg { + u32 vdev_id; + struct wmi_channel_arg channel; + u32 bcn_intval; + u32 dtim_period; + u8 *ssid; + u32 ssid_len; + u32 bcn_tx_rate; + u32 bcn_tx_power; + bool disable_hw_ack; + bool hidden_ssid; + bool pmf_enabled; +}; + +struct wmi_vdev_delete_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +struct wmi_vdev_up_cmd { + __le32 vdev_id; + __le32 vdev_assoc_id; + struct wmi_mac_addr vdev_bssid; +} __packed; + +struct wmi_vdev_stop_cmd { + __le32 vdev_id; +} __packed; + +struct wmi_vdev_down_cmd { + __le32 vdev_id; +} __packed; + +struct wmi_vdev_standby_response_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +struct wmi_vdev_resume_response_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +struct wmi_vdev_set_param_cmd { + __le32 vdev_id; + __le32 param_id; + __le32 param_value; +} __packed; + +#define WMI_MAX_KEY_INDEX 3 +#define WMI_MAX_KEY_LEN 32 + +#define WMI_KEY_PAIRWISE 0x00 +#define WMI_KEY_GROUP 0x01 +#define WMI_KEY_TX_USAGE 0x02 /* default tx key - static wep */ + +struct wmi_key_seq_counter { + __le32 key_seq_counter_l; + __le32 key_seq_counter_h; +} __packed; + +#define WMI_CIPHER_NONE 0x0 /* clear key */ +#define WMI_CIPHER_WEP 0x1 +#define WMI_CIPHER_TKIP 0x2 +#define WMI_CIPHER_AES_OCB 0x3 +#define WMI_CIPHER_AES_CCM 0x4 +#define WMI_CIPHER_WAPI 0x5 +#define WMI_CIPHER_CKIP 0x6 +#define WMI_CIPHER_AES_CMAC 0x7 + +struct wmi_vdev_install_key_cmd { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; + __le32 key_idx; + __le32 key_flags; + __le32 key_cipher; /* %WMI_CIPHER_ */ + struct wmi_key_seq_counter key_rsc_counter; + struct wmi_key_seq_counter key_global_rsc_counter; + struct wmi_key_seq_counter key_tsc_counter; + u8 wpi_key_rsc_counter[16]; + u8 wpi_key_tsc_counter[16]; + __le32 key_len; + __le32 key_txmic_len; + __le32 key_rxmic_len; + + /* contains key followed by tx mic followed by rx mic */ + u8 key_data[0]; +} __packed; + +struct wmi_vdev_install_key_arg { + u32 vdev_id; + const u8 *macaddr; + u32 key_idx; + u32 key_flags; + u32 key_cipher; + u32 key_len; + u32 key_txmic_len; + u32 key_rxmic_len; + const void *key_data; +}; + +/* Preamble types to be used with VDEV fixed rate configuration */ +enum wmi_rate_preamble { + WMI_RATE_PREAMBLE_OFDM, + WMI_RATE_PREAMBLE_CCK, + WMI_RATE_PREAMBLE_HT, + WMI_RATE_PREAMBLE_VHT, +}; + +/* Value to disable fixed rate setting */ +#define WMI_FIXED_RATE_NONE (0xff) + +/* the definition of different VDEV parameters */ +enum wmi_vdev_param { + /* RTS Threshold */ + WMI_VDEV_PARAM_RTS_THRESHOLD = 0x1, + /* Fragmentation threshold */ + WMI_VDEV_PARAM_FRAGMENTATION_THRESHOLD, + /* beacon interval in TUs */ + WMI_VDEV_PARAM_BEACON_INTERVAL, + /* Listen interval in TUs */ + WMI_VDEV_PARAM_LISTEN_INTERVAL, + /* muticast rate in Mbps */ + WMI_VDEV_PARAM_MULTICAST_RATE, + /* management frame rate in Mbps */ + WMI_VDEV_PARAM_MGMT_TX_RATE, + /* slot time (long vs short) */ + WMI_VDEV_PARAM_SLOT_TIME, + /* preamble (long vs short) */ + WMI_VDEV_PARAM_PREAMBLE, + /* SWBA time (time before tbtt in msec) */ + WMI_VDEV_PARAM_SWBA_TIME, + /* time period for updating VDEV stats */ + WMI_VDEV_STATS_UPDATE_PERIOD, + /* age out time in msec for frames queued for station in power save */ + WMI_VDEV_PWRSAVE_AGEOUT_TIME, + /* + * Host SWBA interval (time in msec before tbtt for SWBA event + * generation). + */ + WMI_VDEV_HOST_SWBA_INTERVAL, + /* DTIM period (specified in units of num beacon intervals) */ + WMI_VDEV_PARAM_DTIM_PERIOD, + /* + * scheduler air time limit for this VDEV. used by off chan + * scheduler. + */ + WMI_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, + /* enable/dsiable WDS for this VDEV */ + WMI_VDEV_PARAM_WDS, + /* ATIM Window */ + WMI_VDEV_PARAM_ATIM_WINDOW, + /* BMISS max */ + WMI_VDEV_PARAM_BMISS_COUNT_MAX, + /* BMISS first time */ + WMI_VDEV_PARAM_BMISS_FIRST_BCNT, + /* BMISS final time */ + WMI_VDEV_PARAM_BMISS_FINAL_BCNT, + /* WMM enables/disabled */ + WMI_VDEV_PARAM_FEATURE_WMM, + /* Channel width */ + WMI_VDEV_PARAM_CHWIDTH, + /* Channel Offset */ + WMI_VDEV_PARAM_CHEXTOFFSET, + /* Disable HT Protection */ + WMI_VDEV_PARAM_DISABLE_HTPROTECTION, + /* Quick STA Kickout */ + WMI_VDEV_PARAM_STA_QUICKKICKOUT, + /* Rate to be used with Management frames */ + WMI_VDEV_PARAM_MGMT_RATE, + /* Protection Mode */ + WMI_VDEV_PARAM_PROTECTION_MODE, + /* Fixed rate setting */ + WMI_VDEV_PARAM_FIXED_RATE, + /* Short GI Enable/Disable */ + WMI_VDEV_PARAM_SGI, + /* Enable LDPC */ + WMI_VDEV_PARAM_LDPC, + /* Enable Tx STBC */ + WMI_VDEV_PARAM_TX_STBC, + /* Enable Rx STBC */ + WMI_VDEV_PARAM_RX_STBC, + /* Intra BSS forwarding */ + WMI_VDEV_PARAM_INTRA_BSS_FWD, + /* Setting Default xmit key for Vdev */ + WMI_VDEV_PARAM_DEF_KEYID, + /* NSS width */ + WMI_VDEV_PARAM_NSS, + /* Set the custom rate for the broadcast data frames */ + WMI_VDEV_PARAM_BCAST_DATA_RATE, + /* Set the custom rate (rate-code) for multicast data frames */ + WMI_VDEV_PARAM_MCAST_DATA_RATE, + /* Tx multicast packet indicate Enable/Disable */ + WMI_VDEV_PARAM_MCAST_INDICATE, + /* Tx DHCP packet indicate Enable/Disable */ + WMI_VDEV_PARAM_DHCP_INDICATE, + /* Enable host inspection of Tx unicast packet to unknown destination */ + WMI_VDEV_PARAM_UNKNOWN_DEST_INDICATE, + + /* The minimum amount of time AP begins to consider STA inactive */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, + + /* + * An associated STA is considered inactive when there is no recent + * TX/RX activity and no downlink frames are buffered for it. Once a + * STA exceeds the maximum idle inactive time, the AP will send an + * 802.11 data-null as a keep alive to verify the STA is still + * associated. If the STA does ACK the data-null, or if the data-null + * is buffered and the STA does not retrieve it, the STA will be + * considered unresponsive + * (see WMI_VDEV_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS). + */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, + + /* + * An associated STA is considered unresponsive if there is no recent + * TX/RX activity and downlink frames are buffered for it. Once a STA + * exceeds the maximum unresponsive time, the AP will send a + * WMI_STA_KICKOUT event to the host so the STA can be deleted. */ + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, + + /* Enable NAWDS : MCAST INSPECT Enable, NAWDS Flag set */ + WMI_VDEV_PARAM_AP_ENABLE_NAWDS, + /* Enable/Disable RTS-CTS */ + WMI_VDEV_PARAM_ENABLE_RTSCTS, + /* Enable TXBFee/er */ + WMI_VDEV_PARAM_TXBF, + + /* Set packet power save */ + WMI_VDEV_PARAM_PACKET_POWERSAVE, + + /* + * Drops un-encrypted packets if eceived in an encrypted connection + * otherwise forwards to host. + */ + WMI_VDEV_PARAM_DROP_UNENCRY, + + /* + * Set the encapsulation type for frames. + */ + WMI_VDEV_PARAM_TX_ENCAP_TYPE, +}; + +/* slot time long */ +#define WMI_VDEV_SLOT_TIME_LONG 0x1 +/* slot time short */ +#define WMI_VDEV_SLOT_TIME_SHORT 0x2 +/* preablbe long */ +#define WMI_VDEV_PREAMBLE_LONG 0x1 +/* preablbe short */ +#define WMI_VDEV_PREAMBLE_SHORT 0x2 + +enum wmi_start_event_param { + WMI_VDEV_RESP_START_EVENT = 0, + WMI_VDEV_RESP_RESTART_EVENT, +}; + +struct wmi_vdev_start_response_event { + __le32 vdev_id; + __le32 req_id; + __le32 resp_type; /* %WMI_VDEV_RESP_ */ + __le32 status; +} __packed; + +struct wmi_vdev_standby_req_event { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +struct wmi_vdev_resume_req_event { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +struct wmi_vdev_stopped_event { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +/* + * common structure used for simple events + * (stopped, resume_req, standby response) + */ +struct wmi_vdev_simple_event { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; +} __packed; + +/* VDEV start response status codes */ +/* VDEV succesfully started */ +#define WMI_INIFIED_VDEV_START_RESPONSE_STATUS_SUCCESS 0x0 + +/* requested VDEV not found */ +#define WMI_INIFIED_VDEV_START_RESPONSE_INVALID_VDEVID 0x1 + +/* unsupported VDEV combination */ +#define WMI_INIFIED_VDEV_START_RESPONSE_NOT_SUPPORTED 0x2 + +/* Beacon processing related command and event structures */ +struct wmi_bcn_tx_hdr { + __le32 vdev_id; + __le32 tx_rate; + __le32 tx_power; + __le32 bcn_len; +} __packed; + +struct wmi_bcn_tx_cmd { + struct wmi_bcn_tx_hdr hdr; + u8 *bcn[0]; +} __packed; + +struct wmi_bcn_tx_arg { + u32 vdev_id; + u32 tx_rate; + u32 tx_power; + u32 bcn_len; + const void *bcn; +}; + +/* Beacon filter */ +#define WMI_BCN_FILTER_ALL 0 /* Filter all beacons */ +#define WMI_BCN_FILTER_NONE 1 /* Pass all beacons */ +#define WMI_BCN_FILTER_RSSI 2 /* Pass Beacons RSSI >= RSSI threshold */ +#define WMI_BCN_FILTER_BSSID 3 /* Pass Beacons with matching BSSID */ +#define WMI_BCN_FILTER_SSID 4 /* Pass Beacons with matching SSID */ + +struct wmi_bcn_filter_rx_cmd { + /* Filter ID */ + __le32 bcn_filter_id; + /* Filter type - wmi_bcn_filter */ + __le32 bcn_filter; + /* Buffer len */ + __le32 bcn_filter_len; + /* Filter info (threshold, BSSID, RSSI) */ + u8 *bcn_filter_buf; +} __packed; + +/* Capabilities and IEs to be passed to firmware */ +struct wmi_bcn_prb_info { + /* Capabilities */ + __le32 caps; + /* ERP info */ + __le32 erp; + /* Advanced capabilities */ + /* HT capabilities */ + /* HT Info */ + /* ibss_dfs */ + /* wpa Info */ + /* rsn Info */ + /* rrm info */ + /* ath_ext */ + /* app IE */ +} __packed; + +struct wmi_bcn_tmpl_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* TIM IE offset from the beginning of the template. */ + __le32 tim_ie_offset; + /* beacon probe capabilities and IEs */ + struct wmi_bcn_prb_info bcn_prb_info; + /* beacon buffer length */ + __le32 buf_len; + /* variable length data */ + u8 data[1]; +} __packed; + +struct wmi_prb_tmpl_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* beacon probe capabilities and IEs */ + struct wmi_bcn_prb_info bcn_prb_info; + /* beacon buffer length */ + __le32 buf_len; + /* Variable length data */ + u8 data[1]; +} __packed; + +enum wmi_sta_ps_mode { + /* enable power save for the given STA VDEV */ + WMI_STA_PS_MODE_DISABLED = 0, + /* disable power save for a given STA VDEV */ + WMI_STA_PS_MODE_ENABLED = 1, +}; + +struct wmi_sta_powersave_mode_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + + /* + * Power save mode + * (see enum wmi_sta_ps_mode) + */ + __le32 sta_ps_mode; +} __packed; + +enum wmi_csa_offload_en { + WMI_CSA_OFFLOAD_DISABLE = 0, + WMI_CSA_OFFLOAD_ENABLE = 1, +}; + +struct wmi_csa_offload_enable_cmd { + __le32 vdev_id; + __le32 csa_offload_enable; +} __packed; + +struct wmi_csa_offload_chanswitch_cmd { + __le32 vdev_id; + struct wmi_channel chan; +} __packed; + +/* + * This parameter controls the policy for retrieving frames from AP while the + * STA is in sleep state. + * + * Only takes affect if the sta_ps_mode is enabled + */ +enum wmi_sta_ps_param_rx_wake_policy { + /* + * Wake up when ever there is an RX activity on the VDEV. In this mode + * the Power save SM(state machine) will come out of sleep by either + * sending null frame (or) a data frame (with PS==0) in response to TIM + * bit set in the received beacon frame from AP. + */ + WMI_STA_PS_RX_WAKE_POLICY_WAKE = 0, + + /* + * Here the power save state machine will not wakeup in response to TIM + * bit, instead it will send a PSPOLL (or) UASPD trigger based on UAPSD + * configuration setup by WMISET_PS_SET_UAPSD WMI command. When all + * access categories are delivery-enabled, the station will send a + * UAPSD trigger frame, otherwise it will send a PS-Poll. + */ + WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD = 1, +}; + +/* + * Number of tx frames/beacon that cause the power save SM to wake up. + * + * Value 1 causes the SM to wake up for every TX. Value 0 has a special + * meaning, It will cause the SM to never wake up. This is useful if you want + * to keep the system to sleep all the time for some kind of test mode . host + * can change this parameter any time. It will affect at the next tx frame. + */ +enum wmi_sta_ps_param_tx_wake_threshold { + WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER = 0, + WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS = 1, + + /* + * Values greater than one indicate that many TX attempts per beacon + * interval before the STA will wake up + */ +}; + +/* + * The maximum number of PS-Poll frames the FW will send in response to + * traffic advertised in TIM before waking up (by sending a null frame with PS + * = 0). Value 0 has a special meaning: there is no maximum count and the FW + * will send as many PS-Poll as are necessary to retrieve buffered BU. This + * parameter is used when the RX wake policy is + * WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD and ignored when the RX wake + * policy is WMI_STA_PS_RX_WAKE_POLICY_WAKE. + */ +enum wmi_sta_ps_param_pspoll_count { + WMI_STA_PS_PSPOLL_COUNT_NO_MAX = 0, + /* + * Values greater than 0 indicate the maximum numer of PS-Poll frames + * FW will send before waking up. + */ +}; + +/* + * This will include the delivery and trigger enabled state for every AC. + * This is the negotiated state with AP. The host MLME needs to set this based + * on AP capability and the state Set in the association request by the + * station MLME.Lower 8 bits of the value specify the UAPSD configuration. + */ +#define WMI_UAPSD_AC_TYPE_DELI 0 +#define WMI_UAPSD_AC_TYPE_TRIG 1 + +#define WMI_UAPSD_AC_BIT_MASK(ac, type) \ + ((type == WMI_UAPSD_AC_TYPE_DELI) ? (1<<(ac<<1)) : (1<<((ac<<1)+1))) + +enum wmi_sta_ps_param_uapsd { + WMI_STA_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), + WMI_STA_PS_UAPSD_AC0_TRIGGER_EN = (1 << 1), + WMI_STA_PS_UAPSD_AC1_DELIVERY_EN = (1 << 2), + WMI_STA_PS_UAPSD_AC1_TRIGGER_EN = (1 << 3), + WMI_STA_PS_UAPSD_AC2_DELIVERY_EN = (1 << 4), + WMI_STA_PS_UAPSD_AC2_TRIGGER_EN = (1 << 5), + WMI_STA_PS_UAPSD_AC3_DELIVERY_EN = (1 << 6), + WMI_STA_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), +}; + +enum wmi_sta_powersave_param { + /* + * Controls how frames are retrievd from AP while STA is sleeping + * + * (see enum wmi_sta_ps_param_rx_wake_policy) + */ + WMI_STA_PS_PARAM_RX_WAKE_POLICY = 0, + + /* + * The STA will go active after this many TX + * + * (see enum wmi_sta_ps_param_tx_wake_threshold) + */ + WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD = 1, + + /* + * Number of PS-Poll to send before STA wakes up + * + * (see enum wmi_sta_ps_param_pspoll_count) + * + */ + WMI_STA_PS_PARAM_PSPOLL_COUNT = 2, + + /* + * TX/RX inactivity time in msec before going to sleep. + * + * The power save SM will monitor tx/rx activity on the VDEV, if no + * activity for the specified msec of the parameter the Power save + * SM will go to sleep. + */ + WMI_STA_PS_PARAM_INACTIVITY_TIME = 3, + + /* + * Set uapsd configuration. + * + * (see enum wmi_sta_ps_param_uapsd) + */ + WMI_STA_PS_PARAM_UAPSD = 4, +}; + +struct wmi_sta_powersave_param_cmd { + __le32 vdev_id; + __le32 param_id; /* %WMI_STA_PS_PARAM_ */ + __le32 param_value; +} __packed; + +/* No MIMO power save */ +#define WMI_STA_MIMO_PS_MODE_DISABLE +/* mimo powersave mode static*/ +#define WMI_STA_MIMO_PS_MODE_STATIC +/* mimo powersave mode dynamic */ +#define WMI_STA_MIMO_PS_MODE_DYNAMIC + +struct wmi_sta_mimo_ps_mode_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* mimo powersave mode as defined above */ + __le32 mimo_pwrsave_mode; +} __packed; + +/* U-APSD configuration of peer station from (re)assoc request and TSPECs */ +enum wmi_ap_ps_param_uapsd { + WMI_AP_PS_UAPSD_AC0_DELIVERY_EN = (1 << 0), + WMI_AP_PS_UAPSD_AC0_TRIGGER_EN = (1 << 1), + WMI_AP_PS_UAPSD_AC1_DELIVERY_EN = (1 << 2), + WMI_AP_PS_UAPSD_AC1_TRIGGER_EN = (1 << 3), + WMI_AP_PS_UAPSD_AC2_DELIVERY_EN = (1 << 4), + WMI_AP_PS_UAPSD_AC2_TRIGGER_EN = (1 << 5), + WMI_AP_PS_UAPSD_AC3_DELIVERY_EN = (1 << 6), + WMI_AP_PS_UAPSD_AC3_TRIGGER_EN = (1 << 7), +}; + +/* U-APSD maximum service period of peer station */ +enum wmi_ap_ps_peer_param_max_sp { + WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED = 0, + WMI_AP_PS_PEER_PARAM_MAX_SP_2 = 1, + WMI_AP_PS_PEER_PARAM_MAX_SP_4 = 2, + WMI_AP_PS_PEER_PARAM_MAX_SP_6 = 3, + MAX_WMI_AP_PS_PEER_PARAM_MAX_SP, +}; + +/* + * AP power save parameter + * Set a power save specific parameter for a peer station + */ +enum wmi_ap_ps_peer_param { + /* Set uapsd configuration for a given peer. + * + * Include the delivery and trigger enabled state for every AC. + * The host MLME needs to set this based on AP capability and stations + * request Set in the association request received from the station. + * + * Lower 8 bits of the value specify the UAPSD configuration. + * + * (see enum wmi_ap_ps_param_uapsd) + * The default value is 0. + */ + WMI_AP_PS_PEER_PARAM_UAPSD = 0, + + /* + * Set the service period for a UAPSD capable station + * + * The service period from wme ie in the (re)assoc request frame. + * + * (see enum wmi_ap_ps_peer_param_max_sp) + */ + WMI_AP_PS_PEER_PARAM_MAX_SP = 1, + + /* Time in seconds for aging out buffered frames for STA in PS */ + WMI_AP_PS_PEER_PARAM_AGEOUT_TIME = 2, +}; + +struct wmi_ap_ps_peer_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + + /* AP powersave param (see enum wmi_ap_ps_peer_param) */ + __le32 param_id; + + /* AP powersave param value */ + __le32 param_value; +} __packed; + +/* 128 clients = 4 words */ +#define WMI_TIM_BITMAP_ARRAY_SIZE 4 + +struct wmi_tim_info { + __le32 tim_len; + __le32 tim_mcast; + __le32 tim_bitmap[WMI_TIM_BITMAP_ARRAY_SIZE]; + __le32 tim_changed; + __le32 tim_num_ps_pending; +} __packed; + +/* Maximum number of NOA Descriptors supported */ +#define WMI_P2P_MAX_NOA_DESCRIPTORS 4 +#define WMI_P2P_OPPPS_ENABLE_BIT BIT(0) +#define WMI_P2P_OPPPS_CTWINDOW_OFFSET 1 +#define WMI_P2P_NOA_CHANGED_BIT BIT(0) + +struct wmi_p2p_noa_info { + /* Bit 0 - Flag to indicate an update in NOA schedule + Bits 7-1 - Reserved */ + u8 changed; + /* NOA index */ + u8 index; + /* Bit 0 - Opp PS state of the AP + Bits 1-7 - Ctwindow in TUs */ + u8 ctwindow_oppps; + /* Number of NOA descriptors */ + u8 num_descriptors; + + struct wmi_p2p_noa_descriptor descriptors[WMI_P2P_MAX_NOA_DESCRIPTORS]; +} __packed; + +struct wmi_bcn_info { + struct wmi_tim_info tim_info; + struct wmi_p2p_noa_info p2p_noa_info; +} __packed; + +struct wmi_host_swba_event { + __le32 vdev_map; + struct wmi_bcn_info bcn_info[1]; +} __packed; + +#define WMI_MAX_AP_VDEV 16 + +struct wmi_tbtt_offset_event { + __le32 vdev_map; + __le32 tbttoffset_list[WMI_MAX_AP_VDEV]; +} __packed; + + +struct wmi_peer_create_cmd { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; +} __packed; + +struct wmi_peer_delete_cmd { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; +} __packed; + +struct wmi_peer_flush_tids_cmd { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; + __le32 peer_tid_bitmap; +} __packed; + +struct wmi_fixed_rate { + /* + * rate mode . 0: disable fixed rate (auto rate) + * 1: legacy (non 11n) rate specified as ieee rate 2*Mbps + * 2: ht20 11n rate specified as mcs index + * 3: ht40 11n rate specified as mcs index + */ + __le32 rate_mode; + /* + * 4 rate values for 4 rate series. series 0 is stored in byte 0 (LSB) + * and series 3 is stored at byte 3 (MSB) + */ + __le32 rate_series; + /* + * 4 retry counts for 4 rate series. retry count for rate 0 is stored + * in byte 0 (LSB) and retry count for rate 3 is stored at byte 3 + * (MSB) + */ + __le32 rate_retries; +} __packed; + +struct wmi_peer_fixed_rate_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + /* fixed rate */ + struct wmi_fixed_rate peer_fixed_rate; +} __packed; + +#define WMI_MGMT_TID 17 + +struct wmi_addba_clear_resp_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; +} __packed; + +struct wmi_addba_send_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + /* Tid number */ + __le32 tid; + /* Buffer/Window size*/ + __le32 buffersize; +} __packed; + +struct wmi_delba_send_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + /* Tid number */ + __le32 tid; + /* Is Initiator */ + __le32 initiator; + /* Reason code */ + __le32 reasoncode; +} __packed; + +struct wmi_addba_setresponse_cmd { + /* unique id identifying the vdev, generated by the caller */ + __le32 vdev_id; + /* peer mac address */ + struct wmi_mac_addr peer_macaddr; + /* Tid number */ + __le32 tid; + /* status code */ + __le32 statuscode; +} __packed; + +struct wmi_send_singleamsdu_cmd { + /* unique id identifying the vdev, generated by the caller */ + __le32 vdev_id; + /* peer mac address */ + struct wmi_mac_addr peer_macaddr; + /* Tid number */ + __le32 tid; +} __packed; + +enum wmi_peer_smps_state { + WMI_PEER_SMPS_PS_NONE = 0x0, + WMI_PEER_SMPS_STATIC = 0x1, + WMI_PEER_SMPS_DYNAMIC = 0x2 +}; + +enum wmi_peer_param { + WMI_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */ + WMI_PEER_AMPDU = 0x2, + WMI_PEER_AUTHORIZE = 0x3, + WMI_PEER_CHAN_WIDTH = 0x4, + WMI_PEER_NSS = 0x5, + WMI_PEER_USE_4ADDR = 0x6 +}; + +struct wmi_peer_set_param_cmd { + __le32 vdev_id; + struct wmi_mac_addr peer_macaddr; + __le32 param_id; + __le32 param_value; +} __packed; + +#define MAX_SUPPORTED_RATES 128 + +struct wmi_rate_set { + /* total number of rates */ + __le32 num_rates; + /* + * rates (each 8bit value) packed into a 32 bit word. + * the rates are filled from least significant byte to most + * significant byte. + */ + __le32 rates[(MAX_SUPPORTED_RATES/4)+1]; +} __packed; + +struct wmi_rate_set_arg { + unsigned int num_rates; + u8 rates[MAX_SUPPORTED_RATES]; +}; + +/* + * NOTE: It would bea good idea to represent the Tx MCS + * info in one word and Rx in another word. This is split + * into multiple words for convenience + */ +struct wmi_vht_rate_set { + __le32 rx_max_rate; /* Max Rx data rate */ + __le32 rx_mcs_set; /* Negotiated RX VHT rates */ + __le32 tx_max_rate; /* Max Tx data rate */ + __le32 tx_mcs_set; /* Negotiated TX VHT rates */ +} __packed; + +struct wmi_vht_rate_set_arg { + u32 rx_max_rate; + u32 rx_mcs_set; + u32 tx_max_rate; + u32 tx_mcs_set; +}; + +struct wmi_peer_set_rates_cmd { + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + /* legacy rate set */ + struct wmi_rate_set peer_legacy_rates; + /* ht rate set */ + struct wmi_rate_set peer_ht_rates; +} __packed; + +struct wmi_peer_set_q_empty_callback_cmd { + /* unique id identifying the VDEV, generated by the caller */ + __le32 vdev_id; + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + __le32 callback_enable; +} __packed; + +#define WMI_PEER_AUTH 0x00000001 +#define WMI_PEER_QOS 0x00000002 +#define WMI_PEER_NEED_PTK_4_WAY 0x00000004 +#define WMI_PEER_NEED_GTK_2_WAY 0x00000010 +#define WMI_PEER_APSD 0x00000800 +#define WMI_PEER_HT 0x00001000 +#define WMI_PEER_40MHZ 0x00002000 +#define WMI_PEER_STBC 0x00008000 +#define WMI_PEER_LDPC 0x00010000 +#define WMI_PEER_DYN_MIMOPS 0x00020000 +#define WMI_PEER_STATIC_MIMOPS 0x00040000 +#define WMI_PEER_SPATIAL_MUX 0x00200000 +#define WMI_PEER_VHT 0x02000000 +#define WMI_PEER_80MHZ 0x04000000 +#define WMI_PEER_PMF 0x08000000 + +/* + * Peer rate capabilities. + * + * This is of interest to the ratecontrol + * module which resides in the firmware. The bit definitions are + * consistent with that defined in if_athrate.c. + */ +#define WMI_RC_DS_FLAG 0x01 +#define WMI_RC_CW40_FLAG 0x02 +#define WMI_RC_SGI_FLAG 0x04 +#define WMI_RC_HT_FLAG 0x08 +#define WMI_RC_RTSCTS_FLAG 0x10 +#define WMI_RC_TX_STBC_FLAG 0x20 +#define WMI_RC_RX_STBC_FLAG 0xC0 +#define WMI_RC_RX_STBC_FLAG_S 6 +#define WMI_RC_WEP_TKIP_FLAG 0x100 +#define WMI_RC_TS_FLAG 0x200 +#define WMI_RC_UAPSD_FLAG 0x400 + +/* Maximum listen interval supported by hw in units of beacon interval */ +#define ATH10K_MAX_HW_LISTEN_INTERVAL 5 + +struct wmi_peer_assoc_complete_cmd { + struct wmi_mac_addr peer_macaddr; + __le32 vdev_id; + __le32 peer_new_assoc; /* 1=assoc, 0=reassoc */ + __le32 peer_associd; /* 16 LSBs */ + __le32 peer_flags; + __le32 peer_caps; /* 16 LSBs */ + __le32 peer_listen_intval; + __le32 peer_ht_caps; + __le32 peer_max_mpdu; + __le32 peer_mpdu_density; /* 0..16 */ + __le32 peer_rate_caps; + struct wmi_rate_set peer_legacy_rates; + struct wmi_rate_set peer_ht_rates; + __le32 peer_nss; /* num of spatial streams */ + __le32 peer_vht_caps; + __le32 peer_phymode; + struct wmi_vht_rate_set peer_vht_rates; + /* HT Operation Element of the peer. Five bytes packed in 2 + * INT32 array and filled from lsb to msb. */ + __le32 peer_ht_info[2]; +} __packed; + +struct wmi_peer_assoc_complete_arg { + u8 addr[ETH_ALEN]; + u32 vdev_id; + bool peer_reassoc; + u16 peer_aid; + u32 peer_flags; /* see %WMI_PEER_ */ + u16 peer_caps; + u32 peer_listen_intval; + u32 peer_ht_caps; + u32 peer_max_mpdu; + u32 peer_mpdu_density; /* 0..16 */ + u32 peer_rate_caps; /* see %WMI_RC_ */ + struct wmi_rate_set_arg peer_legacy_rates; + struct wmi_rate_set_arg peer_ht_rates; + u32 peer_num_spatial_streams; + u32 peer_vht_caps; + enum wmi_phy_mode peer_phymode; + struct wmi_vht_rate_set_arg peer_vht_rates; +}; + +struct wmi_peer_add_wds_entry_cmd { + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; + /* wds MAC addr */ + struct wmi_mac_addr wds_macaddr; +} __packed; + +struct wmi_peer_remove_wds_entry_cmd { + /* wds MAC addr */ + struct wmi_mac_addr wds_macaddr; +} __packed; + +struct wmi_peer_q_empty_callback_event { + /* peer MAC address */ + struct wmi_mac_addr peer_macaddr; +} __packed; + +/* + * Channel info WMI event + */ +struct wmi_chan_info_event { + __le32 err_code; + __le32 freq; + __le32 cmd_flags; + __le32 noise_floor; + __le32 rx_clear_count; + __le32 cycle_count; +} __packed; + +/* Beacon filter wmi command info */ +#define BCN_FLT_MAX_SUPPORTED_IES 256 +#define BCN_FLT_MAX_ELEMS_IE_LIST (BCN_FLT_MAX_SUPPORTED_IES / 32) + +struct bss_bcn_stats { + __le32 vdev_id; + __le32 bss_bcnsdropped; + __le32 bss_bcnsdelivered; +} __packed; + +struct bcn_filter_stats { + __le32 bcns_dropped; + __le32 bcns_delivered; + __le32 activefilters; + struct bss_bcn_stats bss_stats; +} __packed; + +struct wmi_add_bcn_filter_cmd { + u32 vdev_id; + u32 ie_map[BCN_FLT_MAX_ELEMS_IE_LIST]; +} __packed; + +enum wmi_sta_keepalive_method { + WMI_STA_KEEPALIVE_METHOD_NULL_FRAME = 1, + WMI_STA_KEEPALIVE_METHOD_UNSOLICITATED_ARP_RESPONSE = 2, +}; + +/* note: ip4 addresses are in network byte order, i.e. big endian */ +struct wmi_sta_keepalive_arp_resp { + __be32 src_ip4_addr; + __be32 dest_ip4_addr; + struct wmi_mac_addr dest_mac_addr; +} __packed; + +struct wmi_sta_keepalive_cmd { + __le32 vdev_id; + __le32 enabled; + __le32 method; /* WMI_STA_KEEPALIVE_METHOD_ */ + __le32 interval; /* in seconds */ + struct wmi_sta_keepalive_arp_resp arp_resp; +} __packed; + +#define ATH10K_RTS_MAX 2347 +#define ATH10K_FRAGMT_THRESHOLD_MIN 540 +#define ATH10K_FRAGMT_THRESHOLD_MAX 2346 + +#define WMI_MAX_EVENT 0x1000 +/* Maximum number of pending TXed WMI packets */ +#define WMI_MAX_PENDING_TX_COUNT 128 +#define WMI_SKB_HEADROOM sizeof(struct wmi_cmd_hdr) + +/* By default disable power save for IBSS */ +#define ATH10K_DEFAULT_ATIM 0 + +struct ath10k; +struct ath10k_vif; + +int ath10k_wmi_attach(struct ath10k *ar); +void ath10k_wmi_detach(struct ath10k *ar); +int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); +int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); +void ath10k_wmi_flush_tx(struct ath10k *ar); + +int ath10k_wmi_connect_htc_service(struct ath10k *ar); +int ath10k_wmi_pdev_set_channel(struct ath10k *ar, + const struct wmi_channel_arg *); +int ath10k_wmi_pdev_suspend_target(struct ath10k *ar); +int ath10k_wmi_pdev_resume_target(struct ath10k *ar); +int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, + u16 rd5g, u16 ctl2g, u16 ctl5g); +int ath10k_wmi_pdev_set_param(struct ath10k *ar, enum wmi_pdev_param id, + u32 value); +int ath10k_wmi_cmd_init(struct ath10k *ar); +int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *); +void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); +int ath10k_wmi_stop_scan(struct ath10k *ar, + const struct wmi_stop_scan_arg *arg); +int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, + enum wmi_vdev_type type, + enum wmi_vdev_subtype subtype, + const u8 macaddr[ETH_ALEN]); +int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id); +int ath10k_wmi_vdev_start(struct ath10k *ar, + const struct wmi_vdev_start_request_arg *); +int ath10k_wmi_vdev_restart(struct ath10k *ar, + const struct wmi_vdev_start_request_arg *); +int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id); +int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, + const u8 *bssid); +int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id); +int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, + enum wmi_vdev_param param_id, u32 param_value); +int ath10k_wmi_vdev_install_key(struct ath10k *ar, + const struct wmi_vdev_install_key_arg *arg); +int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN]); +int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN]); +int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, + const u8 peer_addr[ETH_ALEN], u32 tid_bitmap); +int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, + const u8 *peer_addr, + enum wmi_peer_param param_id, u32 param_value); +int ath10k_wmi_peer_assoc(struct ath10k *ar, + const struct wmi_peer_assoc_complete_arg *arg); +int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_ps_mode psmode); +int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id, + enum wmi_sta_powersave_param param_id, + u32 value); +int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, + enum wmi_ap_ps_peer_param param_id, u32 value); +int ath10k_wmi_scan_chan_list(struct ath10k *ar, + const struct wmi_scan_chan_list_arg *arg); +int ath10k_wmi_beacon_send(struct ath10k *ar, const struct wmi_bcn_tx_arg *arg); +int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, + const struct wmi_pdev_set_wmm_params_arg *arg); +int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); + +#endif /* _WMI_H_ */ -- GitLab From 80b4205bc1da3fdcb665f43d1a7fbbb202e9cd41 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:30 +0530 Subject: [PATCH 0931/2900] ath9k: Fix OFDM weak signal detection for AP mode The commit "ath9k_hw: improve ANI processing and rx desensitizing parameters" changed the OFDM weak signal detection logic to disable it for AP mode, which is not allowed. Fix this and enable it always for AP mode. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index e91725bf401c..3ec4c5388c28 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -177,10 +177,15 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH) weak_sig = true; - if (aniState->ofdmWeakSigDetect != weak_sig) - ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - entry_ofdm->ofdm_weak_signal_on); + /* + * OFDM Weak signal detection is always enabled for AP mode. + */ + if (ah->opmode != NL80211_IFTYPE_AP && + aniState->ofdmWeakSigDetect != weak_sig) { + ath9k_hw_ani_control(ah, + ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, + entry_ofdm->ofdm_weak_signal_on); + } if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; -- GitLab From a04eb985f18b7e0f3b071a29600ebc4741475ce9 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:31 +0530 Subject: [PATCH 0932/2900] ath9k: Fix ANI monitoring The commit "ath9k_hw: improve ANI processing and rx desensitizing parameters" changed various ANI operational parameters to address a specific card/environment. This is not really applicable for other cards in general usage. As per internal documentation, lowering the immunity level can be done only after 5 periods have passed and the CCK/OFDM errors are below the low watermak threshold - which have been fixed at 300 and 400 respectively by the sytems team. Raising the immunity level can be done when CCK/OFDM errors exceed 600 and 1000 (per second). Set these values once during attach. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 29 ++++++++++++++++------------ drivers/net/wireless/ath/ath9k/ani.h | 2 -- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 3ec4c5388c28..1520e5508210 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -186,14 +186,6 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, entry_ofdm->ofdm_weak_signal_on); } - - if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { - ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; - ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI; - } else { - ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI; - ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; - } } static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) @@ -439,12 +431,25 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, cckPhyErrRate, aniState->ofdmsTurn); - if (aniState->listenTime > ah->aniperiod) { - if (cckPhyErrRate < ah->config.cck_trig_low && - ofdmPhyErrRate < ah->config.ofdm_trig_low) { + if (aniState->listenTime > 5 * ah->aniperiod) { + /* + * Check if we need to lower immunity if + * 5 ani_periods have passed. + */ + if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && + cckPhyErrRate <= ah->config.cck_trig_low) { ath9k_hw_ani_lower_immunity(ah); aniState->ofdmsTurn = !aniState->ofdmsTurn; - } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) { + } + ath9k_ani_restart(ah); + } else if (aniState->listenTime > ah->aniperiod) { + /* + * Check if immunity has to be raised, + * (either OFDM or CCK). + */ + if (ofdmPhyErrRate > ah->config.ofdm_trig_high && + (cckPhyErrRate <= ah->config.cck_trig_high || + aniState->ofdmsTurn)) { ath9k_hw_ani_ofdm_err_trigger(ah); aniState->ofdmsTurn = false; } else if (cckPhyErrRate > ah->config.cck_trig_high) { diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 78b9fa9f6455..10884728d30e 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -21,11 +21,9 @@ /* units are errors per second */ #define ATH9K_ANI_OFDM_TRIG_HIGH 3500 -#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 /* units are errors per second */ #define ATH9K_ANI_OFDM_TRIG_LOW 400 -#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 /* units are errors per second */ #define ATH9K_ANI_CCK_TRIG_HIGH 600 -- GitLab From b99553fb60c1a1d3569993fdb5e21fb7214dbbf0 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:32 +0530 Subject: [PATCH 0933/2900] ath9k: Fix ANI levels The commit, "ath9k_hw: improve ANI processing and rx desensitizing parameters" modified the immunity level tables for both CCK and OFDM. Fix them so that the tables are in sync with the internal driver/codebase. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 1520e5508210..c8595f41b298 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -46,8 +46,8 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = { { 5, 4, 1 }, /* lvl 5 */ { 6, 5, 1 }, /* lvl 6 */ { 7, 6, 1 }, /* lvl 7 */ - { 7, 6, 0 }, /* lvl 8 */ - { 7, 7, 0 } /* lvl 9 */ + { 7, 7, 1 }, /* lvl 8 */ + { 7, 8, 0 } /* lvl 9 */ }; #define ATH9K_ANI_OFDM_NUM_LEVEL \ ARRAY_SIZE(ofdm_level_table) @@ -91,8 +91,8 @@ static const struct ani_cck_level_entry cck_level_table[] = { { 4, 0 }, /* lvl 4 */ { 5, 0 }, /* lvl 5 */ { 6, 0 }, /* lvl 6 */ - { 6, 0 }, /* lvl 7 (only for high rssi) */ - { 7, 0 } /* lvl 8 (only for high rssi) */ + { 7, 0 }, /* lvl 7 (only for high rssi) */ + { 8, 0 } /* lvl 8 (only for high rssi) */ }; #define ATH9K_ANI_CCK_NUM_LEVEL \ -- GitLab From ff23e0845b1ba33ec2ee25989758e2cf3df6d4c5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:33 +0530 Subject: [PATCH 0934/2900] ath9k: Fix ofdm weak signal configuration The commit, "ath9k_hw: improve ANI processing and rx desensitizing parameters" removed code setting various phy registers holding threshold values. This is likely required for OFDM weak signal detection to function correctly, so add them, but skip AR9462 and AR9565. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 83e03857c014..bc483128efcd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -906,6 +906,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, struct ath_common *common = ath9k_hw_common(ah); struct ath9k_channel *chan = ah->curchan; struct ar5416AniState *aniState = &ah->ani; + int m1ThreshLow, m2ThreshLow; + int m1Thresh, m2Thresh; + int m2CountThr, m2CountThrLow; + int m1ThreshLowExt, m2ThreshLowExt; + int m1ThreshExt, m2ThreshExt; s32 value, value2; switch (cmd & ah->ani_function) { @@ -919,6 +924,61 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, */ u32 on = param ? 1 : 0; + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + goto skip_ws_det; + + m1ThreshLow = on ? + aniState->iniDef.m1ThreshLow : m1ThreshLow_off; + m2ThreshLow = on ? + aniState->iniDef.m2ThreshLow : m2ThreshLow_off; + m1Thresh = on ? + aniState->iniDef.m1Thresh : m1Thresh_off; + m2Thresh = on ? + aniState->iniDef.m2Thresh : m2Thresh_off; + m2CountThr = on ? + aniState->iniDef.m2CountThr : m2CountThr_off; + m2CountThrLow = on ? + aniState->iniDef.m2CountThrLow : m2CountThrLow_off; + m1ThreshLowExt = on ? + aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; + m2ThreshLowExt = on ? + aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; + m1ThreshExt = on ? + aniState->iniDef.m1ThreshExt : m1ThreshExt_off; + m2ThreshExt = on ? + aniState->iniDef.m2ThreshExt : m2ThreshExt_off; + + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M1_THRESH_LOW, + m1ThreshLow); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2_THRESH_LOW, + m2ThreshLow); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M1_THRESH, + m1Thresh); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2_THRESH, + m2Thresh); + REG_RMW_FIELD(ah, AR_PHY_SFCORR, + AR_PHY_SFCORR_M2COUNT_THR, + m2CountThr); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, + m2CountThrLow); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH_LOW, + m1ThreshLowExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH_LOW, + m2ThreshLowExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M1_THRESH, + m1ThreshExt); + REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, + AR_PHY_SFCORR_EXT_M2_THRESH, + m2ThreshExt); +skip_ws_det: if (on) REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); -- GitLab From 50a0f5bc3075b37ccaad97780d4b9238309fdf15 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:34 +0530 Subject: [PATCH 0935/2900] ath9k: Remove redundant code The phy error mask registers are programmed already in ath9k_ani_restart(), so there is no need to set them in ath9k_ani_reset(). Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index c8595f41b298..a68beb19ce4d 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -360,18 +360,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning); ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning); - /* - * enable phy counters if hw supports or if not, enable phy - * interrupts (so we can count each one) - */ ath9k_ani_restart(ah); - - ENABLE_REGWRITE_BUFFER(ah); - - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); - - REGWRITE_BUFFER_FLUSH(ah); } static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) -- GitLab From 057c1dd6cd5041e3b6a6fb65708ac5a4d9c12b36 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 4 Jun 2013 15:41:35 +0530 Subject: [PATCH 0936/2900] ath9k: Remove unused ANI macros Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 10884728d30e..b75aea23b313 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -21,17 +21,10 @@ /* units are errors per second */ #define ATH9K_ANI_OFDM_TRIG_HIGH 3500 - -/* units are errors per second */ #define ATH9K_ANI_OFDM_TRIG_LOW 400 - -/* units are errors per second */ #define ATH9K_ANI_CCK_TRIG_HIGH 600 - -/* units are errors per second */ #define ATH9K_ANI_CCK_TRIG_LOW 300 -#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 #define ATH9K_ANI_SPUR_IMMUNE_LVL 3 #define ATH9K_ANI_FIRSTEP_LVL 2 @@ -43,10 +36,6 @@ /* in ms */ #define ATH9K_ANI_POLLINTERVAL 1000 -#define HAL_NOISE_IMMUNE_MAX 4 -#define HAL_SPUR_IMMUNE_MAX 7 -#define HAL_FIRST_STEP_MAX 2 - #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 -- GitLab From 568f7a438f6d5f0f0909c94e66b7c5c8b96ebf7a Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:38 +0200 Subject: [PATCH 0937/2900] rt2x00: rt2x00queue: add priv_size field to struct data_queue Add a new field into struct data_queue and store the size of the per-queue_entry private data in that. Additionally, use the new field in the rt2x00queue_alloc_entries function to compute the size of the queue entries for a given queue. The patch does not change the current behaviour but makes it possible to remove the queue_desc parameter of the rt2x00queue_alloc_entries function. That will be done by a subsequent patch. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 5 +++-- drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 5efbbbdca701..7f938a513f3a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1173,7 +1173,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, /* * Allocate all queue entries. */ - entry_size = sizeof(*entries) + qdesc->priv_size; + entry_size = sizeof(*entries) + queue->priv_size; entries = kcalloc(queue->limit, entry_size, GFP_KERNEL); if (!entries) return -ENOMEM; @@ -1189,7 +1189,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, entries[i].entry_idx = i; entries[i].priv_data = QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit, - sizeof(*entries), qdesc->priv_size); + sizeof(*entries), queue->priv_size); } #undef QUEUE_ENTRY_PRIV_OFFSET @@ -1329,6 +1329,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, queue->data_size = qdesc->data_size; queue->desc_size = qdesc->desc_size; queue->winfo_size = qdesc->winfo_size; + queue->priv_size = qdesc->priv_size; } int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4a7b34e9261b..2cf4903ce112 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -453,6 +453,7 @@ enum data_queue_flags { * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). * @data_size: Maximum data size for the frames in this queue. * @desc_size: Hardware descriptor size for the data in this queue. + * @priv_size: Size of per-queue_entry private data. * @usb_endpoint: Device endpoint used for communication (USB only) * @usb_maxpacket: Max packet size for given endpoint (USB only) */ @@ -481,6 +482,7 @@ struct data_queue { unsigned short data_size; unsigned char desc_size; unsigned char winfo_size; + unsigned short priv_size; unsigned short usb_endpoint; unsigned short usb_maxpacket; -- GitLab From 15d6c07929a2efa8802b5cc9bb8c91bdf5ba219b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:39 +0200 Subject: [PATCH 0938/2900] rt2x00: rt2x00queue: remove qdesc parameter of rt2x00queue_alloc_entries The qdesc parameter is not used anymore, so remove that. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 7f938a513f3a..c12d1c8ae618 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1161,8 +1161,7 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) } } -static int rt2x00queue_alloc_entries(struct data_queue *queue, - const struct data_queue_desc *qdesc) +static int rt2x00queue_alloc_entries(struct data_queue *queue) { struct queue_entry *entries; unsigned int entry_size; @@ -1231,23 +1230,22 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; int status; - status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); + status = rt2x00queue_alloc_entries(rt2x00dev->rx); if (status) goto exit; tx_queue_for_each(rt2x00dev, queue) { - status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx); + status = rt2x00queue_alloc_entries(queue); if (status) goto exit; } - status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn); + status = rt2x00queue_alloc_entries(rt2x00dev->bcn); if (status) goto exit; if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) { - status = rt2x00queue_alloc_entries(rt2x00dev->atim, - rt2x00dev->ops->atim); + status = rt2x00queue_alloc_entries(rt2x00dev->atim); if (status) goto exit; } -- GitLab From 56e8256351c358d7a2003f6fe10dcb5e2bc394f7 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:40 +0200 Subject: [PATCH 0939/2900] rt2x00: rt2x00dev: use rt2x00dev->bcn->limit The beacon data queue is initialized already, so fetch the number of the queue entries from that instead of using the entry_num field of the data queue descriptor. The two values are the same, and the use of the rt2x00dev->bcn->limit value allows us to get rid of a superfluous pointer dereference. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6a201725bc50..dff5012f0548 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1336,7 +1336,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) * beacon entries. */ rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - if (rt2x00dev->ops->bcn->entry_num > 0) + if (rt2x00dev->bcn->limit > 0) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | -- GitLab From 04453e9bda9da510e79c66f56ab463215d042aa8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:41 +0200 Subject: [PATCH 0940/2900] rt2x00: rt2x00queue: setup queue->threshold from queue->limit Use the queue->limit value instead of the qdesc->entry_num to compute the threshold. The two source values are the same and the data queue descriptor structure will be removed by a later patch. Also separate the computation from the rest of the init code to make further changes easier. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index c12d1c8ae618..3ae2264fdabc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1323,11 +1323,12 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, BUG_ON(!qdesc); queue->limit = qdesc->entry_num; - queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); queue->data_size = qdesc->data_size; queue->desc_size = qdesc->desc_size; queue->winfo_size = qdesc->winfo_size; queue->priv_size = qdesc->priv_size; + + queue->threshold = DIV_ROUND_UP(queue->limit, 10); } int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) -- GitLab From 25bf6ce41d2692db2e991447015fb4bfbf3c3982 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:42 +0200 Subject: [PATCH 0941/2900] rt2x00: add queue_init callback to rt2x00_ops The driver uses static data structures for initializing specific fields of a given data queue. These static queue data descriptor structures are containing values which related to a given chipset. Even though the values are chip specific, the actual selection of the used structure is based on device specific vendor/product identifiers. This approach works, but it is not always reliable. Sometimes the vendor and/or device IDs of the PCI and USB devices contains improper values which makes it impossible to select the correct structure for such devices. The patch adds a new callback to tr2x00_ops which is called after the chipset detection is finished. This allows the drivers to do dynamic initialization of the data_queue structure for a given queue based on the actual chipset. After each driver implements the queue_init callback, the data_queue_desc structure will be removed. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 1 + drivers/net/wireless/rt2x00/rt2x00queue.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7510723a8c37..2d2db6472c04 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -653,6 +653,7 @@ struct rt2x00_ops { const struct data_queue_desc *tx; const struct data_queue_desc *bcn; const struct data_queue_desc *atim; + void (*queue_init)(struct data_queue *queue); const struct rt2x00lib_ops *lib; const void *drv; const struct ieee80211_ops *hw; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 3ae2264fdabc..2a99ff1714ac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1306,8 +1306,6 @@ rt2x00queue_get_qdesc_by_qid(struct rt2x00_dev *rt2x00dev, static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { - const struct data_queue_desc *qdesc; - mutex_init(&queue->status_lock); spin_lock_init(&queue->tx_lock); spin_lock_init(&queue->index_lock); @@ -1319,14 +1317,20 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, queue->cw_min = 5; queue->cw_max = 10; - qdesc = rt2x00queue_get_qdesc_by_qid(rt2x00dev, qid); - BUG_ON(!qdesc); + if (rt2x00dev->ops->queue_init) { + rt2x00dev->ops->queue_init(queue); + } else { + const struct data_queue_desc *qdesc; + + qdesc = rt2x00queue_get_qdesc_by_qid(rt2x00dev, qid); + BUG_ON(!qdesc); - queue->limit = qdesc->entry_num; - queue->data_size = qdesc->data_size; - queue->desc_size = qdesc->desc_size; - queue->winfo_size = qdesc->winfo_size; - queue->priv_size = qdesc->priv_size; + queue->limit = qdesc->entry_num; + queue->data_size = qdesc->data_size; + queue->desc_size = qdesc->desc_size; + queue->winfo_size = qdesc->winfo_size; + queue->priv_size = qdesc->priv_size; + } queue->threshold = DIV_ROUND_UP(queue->limit, 10); } -- GitLab From d36d13a3ec1ef25c411d39c1e14dd2cdff98edbb Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:43 +0200 Subject: [PATCH 0942/2900] rt2x00: rt2800usb: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. The actual chipset is already known when the callback is used. This allows us to use a single callback for all supported devices. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 100 ++++++++++++------------ 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c71a48da9a31..b81d5098816a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -849,29 +849,54 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { .sta_remove = rt2800_sta_remove, }; -static const struct data_queue_desc rt2800usb_queue_rx = { - .entry_num = 128, - .data_size = AGGREGATION_SIZE, - .desc_size = RXINFO_DESC_SIZE, - .winfo_size = RXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; +static void rt2800usb_queue_init(struct data_queue *queue) +{ + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + unsigned short txwi_size, rxwi_size; -static const struct data_queue_desc rt2800usb_queue_tx = { - .entry_num = 16, - .data_size = AGGREGATION_SIZE, - .desc_size = TXINFO_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + if (rt2x00_rt(rt2x00dev, RT5592)) { + txwi_size = TXWI_DESC_SIZE_5592; + rxwi_size = RXWI_DESC_SIZE_5592; + } else { + txwi_size = TXWI_DESC_SIZE; + rxwi_size = RXWI_DESC_SIZE; + } -static const struct data_queue_desc rt2800usb_queue_bcn = { - .entry_num = 8, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXINFO_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + switch (queue->qid) { + case QID_RX: + queue->limit = 128; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = RXINFO_DESC_SIZE; + queue->winfo_size = rxwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; + + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 16; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = TXINFO_DESC_SIZE; + queue->winfo_size = txwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; + + case QID_BEACON: + queue->limit = 8; + queue->data_size = MGMT_FRAME_SIZE; + queue->desc_size = TXINFO_DESC_SIZE; + queue->winfo_size = txwi_size; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; + + case QID_ATIM: + /* fallthrough */ + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt2800usb_ops = { .name = KBUILD_MODNAME, @@ -881,9 +906,7 @@ static const struct rt2x00_ops rt2800usb_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, - .rx = &rt2800usb_queue_rx, - .tx = &rt2800usb_queue_tx, - .bcn = &rt2800usb_queue_bcn, + .queue_init = rt2800usb_queue_init, .lib = &rt2800usb_rt2x00_ops, .drv = &rt2800usb_rt2800_ops, .hw = &rt2800usb_mac80211_ops, @@ -892,31 +915,6 @@ static const struct rt2x00_ops rt2800usb_ops = { #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; -static const struct data_queue_desc rt2800usb_queue_rx_5592 = { - .entry_num = 128, - .data_size = AGGREGATION_SIZE, - .desc_size = RXINFO_DESC_SIZE, - .winfo_size = RXWI_DESC_SIZE_5592, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2800usb_queue_tx_5592 = { - .entry_num = 16, - .data_size = AGGREGATION_SIZE, - .desc_size = TXINFO_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE_5592, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2800usb_queue_bcn_5592 = { - .entry_num = 8, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXINFO_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE_5592, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - - static const struct rt2x00_ops rt2800usb_ops_5592 = { .name = KBUILD_MODNAME, .drv_data_size = sizeof(struct rt2800_drv_data), @@ -925,9 +923,7 @@ static const struct rt2x00_ops rt2800usb_ops_5592 = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, - .rx = &rt2800usb_queue_rx_5592, - .tx = &rt2800usb_queue_tx_5592, - .bcn = &rt2800usb_queue_bcn_5592, + .queue_init = rt2800usb_queue_init, .lib = &rt2800usb_rt2x00_ops, .drv = &rt2800usb_rt2800_ops, .hw = &rt2800usb_mac80211_ops, -- GitLab From 1896b760c3024e90db3b3577bf0ed31c008a3543 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:44 +0200 Subject: [PATCH 0943/2900] rt2x00: rt2800pci: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 60 +++++++++++++++---------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 330f1d25726d..260c8b4d7399 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1186,29 +1186,43 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { .sta_remove = rt2800_sta_remove, }; -static const struct data_queue_desc rt2800pci_queue_rx = { - .entry_num = 128, - .data_size = AGGREGATION_SIZE, - .desc_size = RXD_DESC_SIZE, - .winfo_size = RXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; +static void rt2800pci_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 128; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->winfo_size = RXWI_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2800pci_queue_tx = { - .entry_num = 64, - .data_size = AGGREGATION_SIZE, - .desc_size = TXD_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 64; + queue->data_size = AGGREGATION_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->winfo_size = TXWI_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2800pci_queue_bcn = { - .entry_num = 8, - .data_size = 0, /* No DMA required for beacons */ - .desc_size = TXD_DESC_SIZE, - .winfo_size = TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_BEACON: + queue->limit = 8; + queue->data_size = 0; /* No DMA required for beacons */ + queue->desc_size = TXD_DESC_SIZE; + queue->winfo_size = TXWI_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + + case QID_ATIM: + /* fallthrough */ + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt2800pci_ops = { .name = KBUILD_MODNAME, @@ -1218,9 +1232,7 @@ static const struct rt2x00_ops rt2800pci_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = TXWI_DESC_SIZE, - .rx = &rt2800pci_queue_rx, - .tx = &rt2800pci_queue_tx, - .bcn = &rt2800pci_queue_bcn, + .queue_init = rt2800pci_queue_init, .lib = &rt2800pci_rt2x00_ops, .drv = &rt2800pci_rt2800_ops, .hw = &rt2800pci_mac80211_ops, -- GitLab From 0d7aada3bcbc0bde68379831d29c1a015f2fd613 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:45 +0200 Subject: [PATCH 0944/2900] rt2x00: rt73usb: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 54 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 377e09bb0b81..b2e346a482cc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2359,26 +2359,40 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .config = rt73usb_config, }; -static const struct data_queue_desc rt73usb_queue_rx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; +static void rt73usb_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; -static const struct data_queue_desc rt73usb_queue_tx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; -static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = 4, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXINFO_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + case QID_BEACON: + queue->limit = 4; + queue->data_size = MGMT_FRAME_SIZE; + queue->desc_size = TXINFO_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; + + case QID_ATIM: + /* fallthrough */ + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, @@ -2387,9 +2401,7 @@ static const struct rt2x00_ops rt73usb_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = TXD_DESC_SIZE, - .rx = &rt73usb_queue_rx, - .tx = &rt73usb_queue_tx, - .bcn = &rt73usb_queue_bcn, + .queue_init = rt73usb_queue_init, .lib = &rt73usb_rt2x00_ops, .hw = &rt73usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS -- GitLab From 3d8979ba7d873cd203bf98a17a2143a20eef488c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:46 +0200 Subject: [PATCH 0945/2900] rt2x00: rt2400pci: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Compile tested only. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 65 ++++++++++++++----------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index f7143733d7e9..e1ec9a4517d1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1767,33 +1767,45 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .config = rt2400pci_config, }; -static const struct data_queue_desc rt2400pci_queue_rx = { - .entry_num = 24, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; +static void rt2400pci_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 24; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2400pci_queue_tx = { - .entry_num = 24, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 24; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2400pci_queue_bcn = { - .entry_num = 1, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_BEACON: + queue->limit = 1; + queue->data_size = MGMT_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2400pci_queue_atim = { - .entry_num = 8, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_ATIM: + queue->limit = 8; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, @@ -1802,10 +1814,7 @@ static const struct rt2x00_ops rt2400pci_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = 0, - .rx = &rt2400pci_queue_rx, - .tx = &rt2400pci_queue_tx, - .bcn = &rt2400pci_queue_bcn, - .atim = &rt2400pci_queue_atim, + .queue_init = rt2400pci_queue_init, .lib = &rt2400pci_rt2x00_ops, .hw = &rt2400pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS -- GitLab From 7c030821ede91bca94b425d27afd504842bb1865 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:47 +0200 Subject: [PATCH 0946/2900] rt2x00: rt2500pci: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Compile tested only. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500pci.c | 65 ++++++++++++++----------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 77e45b223d15..a1670e8967ed 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2056,33 +2056,45 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .config = rt2500pci_config, }; -static const struct data_queue_desc rt2500pci_queue_rx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; +static void rt2500pci_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2500pci_queue_tx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2500pci_queue_bcn = { - .entry_num = 1, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_BEACON: + queue->limit = 1; + queue->data_size = MGMT_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt2500pci_queue_atim = { - .entry_num = 8, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_ATIM: + queue->limit = 8; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, @@ -2091,10 +2103,7 @@ static const struct rt2x00_ops rt2500pci_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = 0, - .rx = &rt2500pci_queue_rx, - .tx = &rt2500pci_queue_tx, - .bcn = &rt2500pci_queue_bcn, - .atim = &rt2500pci_queue_atim, + .queue_init = rt2500pci_queue_init, .lib = &rt2500pci_rt2x00_ops, .hw = &rt2500pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS -- GitLab From 7106d97bc475b2c0f2a134f804b245bf5eaebffc Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:48 +0200 Subject: [PATCH 0947/2900] rt2x00: rt61pci: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Signed-off-by: Gabor Juhos Tested-by: Jakub Kicinski Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 54 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 7e1759b3e49a..17507d12d5ee 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -3025,26 +3025,40 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .config = rt61pci_config, }; -static const struct data_queue_desc rt61pci_queue_rx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; +static void rt61pci_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt61pci_queue_tx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; -static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = 4, - .data_size = 0, /* No DMA required for beacons */ - .desc_size = TXINFO_SIZE, - .priv_size = sizeof(struct queue_entry_priv_mmio), -}; + case QID_BEACON: + queue->limit = 4; + queue->data_size = 0; /* No DMA required for beacons */ + queue->desc_size = TXINFO_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_mmio); + break; + + case QID_ATIM: + /* fallthrough */ + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, @@ -3053,9 +3067,7 @@ static const struct rt2x00_ops rt61pci_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = 0, - .rx = &rt61pci_queue_rx, - .tx = &rt61pci_queue_tx, - .bcn = &rt61pci_queue_bcn, + .queue_init = rt61pci_queue_init, .lib = &rt61pci_rt2x00_ops, .hw = &rt61pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS -- GitLab From c29a32c8f15c81470d16aee82f52432eb477aa9b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:49 +0200 Subject: [PATCH 0948/2900] rt2x00: rt2500usb: implement queue_init callback The generic rt2x00 code has been changed to allow the drivers toimplement dynamic data_queue initialization. Remove the static data queue descriptor structures and implement the queue_init callback instead. Compile tested only. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 65 ++++++++++++++----------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a7f7b365eff4..e5e5479bcf93 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1867,33 +1867,45 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .config = rt2500usb_config, }; -static const struct data_queue_desc rt2500usb_queue_rx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; +static void rt2500usb_queue_init(struct data_queue *queue) +{ + switch (queue->qid) { + case QID_RX: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = RXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; -static const struct data_queue_desc rt2500usb_queue_tx = { - .entry_num = 32, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + case QID_AC_VO: + case QID_AC_VI: + case QID_AC_BE: + case QID_AC_BK: + queue->limit = 32; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; -static const struct data_queue_desc rt2500usb_queue_bcn = { - .entry_num = 1, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb_bcn), -}; + case QID_BEACON: + queue->limit = 1; + queue->data_size = MGMT_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn); + break; -static const struct data_queue_desc rt2500usb_queue_atim = { - .entry_num = 8, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; + case QID_ATIM: + queue->limit = 8; + queue->data_size = DATA_FRAME_SIZE; + queue->desc_size = TXD_DESC_SIZE; + queue->priv_size = sizeof(struct queue_entry_priv_usb); + break; + + default: + BUG(); + break; + } +} static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, @@ -1902,10 +1914,7 @@ static const struct rt2x00_ops rt2500usb_ops = { .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, .extra_tx_headroom = TXD_DESC_SIZE, - .rx = &rt2500usb_queue_rx, - .tx = &rt2500usb_queue_tx, - .bcn = &rt2500usb_queue_bcn, - .atim = &rt2500usb_queue_atim, + .queue_init = rt2500usb_queue_init, .lib = &rt2500usb_rt2x00_ops, .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS -- GitLab From 705802bf56b1b7a64e543805ba196a6e1fb80ec6 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 4 Jun 2013 13:40:50 +0200 Subject: [PATCH 0949/2900] rt2x00: remove data_queue_desc struct If the queue_init callback is implemented by a driver it gets used instead of the data_queue_desc based initialization. The queue_init callback is implemented for each drivers now, so the old initialization method is not used anymore. Remove the unused data_queue_desc structure and all of the related code. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 4 --- drivers/net/wireless/rt2x00/rt2x00queue.c | 42 +---------------------- drivers/net/wireless/rt2x00/rt2x00queue.h | 19 ---------- 3 files changed, 1 insertion(+), 64 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2d2db6472c04..2a17f7e4ed5e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -649,10 +649,6 @@ struct rt2x00_ops { const unsigned int rf_size; const unsigned int tx_queues; const unsigned int extra_tx_headroom; - const struct data_queue_desc *rx; - const struct data_queue_desc *tx; - const struct data_queue_desc *bcn; - const struct data_queue_desc *atim; void (*queue_init)(struct data_queue *queue); const struct rt2x00lib_ops *lib; const void *drv; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 2a99ff1714ac..c4f1e2b8dc8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -1276,33 +1276,6 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) } } -static const struct data_queue_desc * -rt2x00queue_get_qdesc_by_qid(struct rt2x00_dev *rt2x00dev, - enum data_queue_qid qid) -{ - switch (qid) { - case QID_RX: - return rt2x00dev->ops->rx; - - case QID_AC_BE: - case QID_AC_BK: - case QID_AC_VO: - case QID_AC_VI: - return rt2x00dev->ops->tx; - - case QID_BEACON: - return rt2x00dev->ops->bcn; - - case QID_ATIM: - return rt2x00dev->ops->atim; - - default: - break; - } - - return NULL; -} - static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, enum data_queue_qid qid) { @@ -1317,20 +1290,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, queue->cw_min = 5; queue->cw_max = 10; - if (rt2x00dev->ops->queue_init) { - rt2x00dev->ops->queue_init(queue); - } else { - const struct data_queue_desc *qdesc; - - qdesc = rt2x00queue_get_qdesc_by_qid(rt2x00dev, qid); - BUG_ON(!qdesc); - - queue->limit = qdesc->entry_num; - queue->data_size = qdesc->data_size; - queue->desc_size = qdesc->desc_size; - queue->winfo_size = qdesc->winfo_size; - queue->priv_size = qdesc->priv_size; - } + rt2x00dev->ops->queue_init(queue); queue->threshold = DIV_ROUND_UP(queue->limit, 10); } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 2cf4903ce112..ebe117224979 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -488,25 +488,6 @@ struct data_queue { unsigned short usb_maxpacket; }; -/** - * struct data_queue_desc: Data queue description - * - * The information in this structure is used by drivers - * to inform rt2x00lib about the creation of the data queue. - * - * @entry_num: Maximum number of entries for a queue. - * @data_size: Maximum data size for the frames in this queue. - * @desc_size: Hardware descriptor size for the data in this queue. - * @priv_size: Size of per-queue_entry private data. - */ -struct data_queue_desc { - unsigned short entry_num; - unsigned short data_size; - unsigned char desc_size; - unsigned char winfo_size; - unsigned short priv_size; -}; - /** * queue_end - Return pointer to the last queue (HELPER MACRO). * @__dev: Pointer to &struct rt2x00_dev -- GitLab From df8100836e05b457af7b1627c601afe82e1d3ebe Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 4 Jun 2013 16:19:56 -0700 Subject: [PATCH 0950/2900] mwifiex: fix regression issue for usb interface PATCH "mwifiex: scan delay timer cleanup in unload path" adds code to cancel scan delay timer in unload path. It causes a regression for USB interface. USB8797 card gets enumerated twice. First enumeration is for firmware download and second enumeration expects firmware initialization. It was observed that we are trying del_timer_sync() without setting up the timer when remove handler is called after first enumeration. This patch moves setup_timer() call to appropriate place so that timer is setup for both the enumerations. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/init.c | 81 ---------------------------- drivers/net/wireless/mwifiex/main.c | 82 +++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index c7f11c0c3bb7..2fe31dcaa6ef 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -52,84 +52,6 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) return 0; } -static void scan_delay_timer_fn(unsigned long data) -{ - struct mwifiex_private *priv = (struct mwifiex_private *)data; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node, *tmp_node; - unsigned long flags; - - if (adapter->surprise_removed) - return; - - if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { - /* - * Abort scan operation by cancelling all pending scan - * commands - */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - adapter->scan_delay_cnt = 0; - adapter->empty_tx_q_cnt = 0; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - if (priv->scan_request) { - dev_dbg(adapter->dev, "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } else { - priv->scan_aborting = false; - dev_dbg(adapter->dev, "info: scan already aborted\n"); - } - goto done; - } - - if (!atomic_read(&priv->adapter->is_tx_received)) { - adapter->empty_tx_q_cnt++; - if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { - /* - * No Tx traffic for 200msec. Get scan command from - * scan pending queue and put to cmd pending queue to - * resume scan operation - */ - adapter->scan_delay_cnt = 0; - adapter->empty_tx_q_cnt = 0; - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, - true); - queue_work(adapter->workqueue, &adapter->main_work); - goto done; - } - } else { - adapter->empty_tx_q_cnt = 0; - } - - /* Delay scan operation further by 20msec */ - mod_timer(&priv->scan_delay_timer, jiffies + - msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); - adapter->scan_delay_cnt++; - -done: - if (atomic_read(&priv->adapter->is_tx_received)) - atomic_set(&priv->adapter->is_tx_received, false); - - return; -} - /* * This function initializes the private structure and sets default * values to the members. @@ -211,9 +133,6 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->scan_block = false; - setup_timer(&priv->scan_delay_timer, scan_delay_timer_fn, - (unsigned long)priv); - return mwifiex_add_bss_prio_tbl(priv); } diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 5bc7ef8d04d6..485871940d3c 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -28,6 +28,84 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; static char *cal_data_cfg; module_param(cal_data_cfg, charp, 0); +static void scan_delay_timer_fn(unsigned long data) +{ + struct mwifiex_private *priv = (struct mwifiex_private *)data; + struct mwifiex_adapter *adapter = priv->adapter; + struct cmd_ctrl_node *cmd_node, *tmp_node; + unsigned long flags; + + if (adapter->surprise_removed) + return; + + if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { + /* + * Abort scan operation by cancelling all pending scan + * commands + */ + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + list_for_each_entry_safe(cmd_node, tmp_node, + &adapter->scan_pending_q, list) { + list_del(&cmd_node->list); + mwifiex_insert_cmd_to_free_q(adapter, cmd_node); + } + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); + + spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); + adapter->scan_processing = false; + adapter->scan_delay_cnt = 0; + adapter->empty_tx_q_cnt = 0; + spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); + + if (priv->scan_request) { + dev_dbg(adapter->dev, "info: aborting scan\n"); + cfg80211_scan_done(priv->scan_request, 1); + priv->scan_request = NULL; + } else { + priv->scan_aborting = false; + dev_dbg(adapter->dev, "info: scan already aborted\n"); + } + goto done; + } + + if (!atomic_read(&priv->adapter->is_tx_received)) { + adapter->empty_tx_q_cnt++; + if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) { + /* + * No Tx traffic for 200msec. Get scan command from + * scan pending queue and put to cmd pending queue to + * resume scan operation + */ + adapter->scan_delay_cnt = 0; + adapter->empty_tx_q_cnt = 0; + spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); + cmd_node = list_first_entry(&adapter->scan_pending_q, + struct cmd_ctrl_node, list); + list_del(&cmd_node->list); + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, + flags); + + mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, + true); + queue_work(adapter->workqueue, &adapter->main_work); + goto done; + } + } else { + adapter->empty_tx_q_cnt = 0; + } + + /* Delay scan operation further by 20msec */ + mod_timer(&priv->scan_delay_timer, jiffies + + msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); + adapter->scan_delay_cnt++; + +done: + if (atomic_read(&priv->adapter->is_tx_received)) + atomic_set(&priv->adapter->is_tx_received, false); + + return; +} + /* * This function registers the device and performs all the necessary * initializations. @@ -75,6 +153,10 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, adapter->priv[i]->adapter = adapter; adapter->priv_num++; + + setup_timer(&adapter->priv[i]->scan_delay_timer, + scan_delay_timer_fn, + (unsigned long)adapter->priv[i]); } mwifiex_init_lock_list(adapter); -- GitLab From c9e2404c9ffcbb31b0bd1348be5fc7a4de6f90d6 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Tue, 4 Jun 2013 16:20:38 -0700 Subject: [PATCH 0951/2900] mwifiex: enable/disable tx_amsdu support via module parameter This patch disables tx_amsdu support in mwifiex by default. tx_amdsu support can be enabled via module parameter at load time. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/wmm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 4be3d33ceae8..944e8846f6fc 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -37,6 +37,9 @@ /* Offset for TOS field in the IP header */ #define IPTOS_OFFSET 5 +static bool enable_tx_amsdu; +module_param(enable_tx_amsdu, bool, 0644); + /* WMM information IE */ static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, @@ -1233,7 +1236,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) mwifiex_send_delba(priv, tid_del, ra, 1); } } - if (mwifiex_is_amsdu_allowed(priv, tid) && + if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) && mwifiex_is_11n_aggragation_possible(priv, ptr, adapter->tx_buf_size)) mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN, -- GitLab From ca3ae51396c049fcb9a93ded6f90ec81f7360ffa Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 5 Jun 2013 10:16:33 +0800 Subject: [PATCH 0952/2900] iwlegacy: fix error return code in il3945_pci_probe() Fix to return a negative error code in the il3945_hw_set_hw_params() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945-mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b37a582ccbe7..866ce6c68405 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3727,7 +3727,8 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * 5. Setup HW Constants * ********************/ /* Device-specific setup */ - if (il3945_hw_set_hw_params(il)) { + err = il3945_hw_set_hw_params(il); + if (err) { IL_ERR("failed to set hw settings\n"); goto out_eeprom_free; } -- GitLab From d619c62f161a43db1f40e5039ff1285dd29b8658 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 5 Jun 2013 20:45:36 -0700 Subject: [PATCH 0953/2900] ath: add VHT80 support for regulatory domains This adds VHT80 support for the QCA world regulatory domains. Cc: kvalo@qca.qualcomm.com Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index ccc4c718f124..7d077c752dd5 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -42,11 +42,11 @@ static int __ath_regd_init(struct ath_regulatory *reg); NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) /* We allow IBSS on these on a case by case basis by regulatory domain */ -#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\ +#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\ +#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\ +#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) #define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ -- GitLab From 5616a6efb2a255330319f9f09f3bcf0fc4680b5f Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 6 Jun 2013 09:36:19 +0200 Subject: [PATCH 0954/2900] rt2x00: move extra_tx_headroom field from rt2x00_ops to rt2x00_dev The extra_tx_headroom field of struct rt2x00_ops indicates the extra TX headroom size required for a given device. This data is redundant, the value can be computed from the desc_size and winfo_size fields of the TX queues. Move the extra_tx_headroom field to struct rt2x00_dev, compute its value in the probe routine and use the cached value in the rest of the code. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 - drivers/net/wireless/rt2x00/rt2500pci.c | 1 - drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2800pci.c | 1 - drivers/net/wireless/rt2x00/rt2800usb.c | 2 -- drivers/net/wireless/rt2x00/rt2x00.h | 4 +++- drivers/net/wireless/rt2x00/rt2x00dev.c | 18 ++++++++++++++++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +++--- drivers/net/wireless/rt2x00/rt61pci.c | 1 - drivers/net/wireless/rt2x00/rt73usb.c | 1 - 10 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e1ec9a4517d1..3d53a09da5a1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1813,7 +1813,6 @@ static const struct rt2x00_ops rt2400pci_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = 0, .queue_init = rt2400pci_queue_init, .lib = &rt2400pci_rt2x00_ops, .hw = &rt2400pci_mac80211_ops, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a1670e8967ed..0ac5c589ddce 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2102,7 +2102,6 @@ static const struct rt2x00_ops rt2500pci_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = 0, .queue_init = rt2500pci_queue_init, .lib = &rt2500pci_rt2x00_ops, .hw = &rt2500pci_mac80211_ops, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index e5e5479bcf93..85acc79f68b8 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1913,7 +1913,6 @@ static const struct rt2x00_ops rt2500usb_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = TXD_DESC_SIZE, .queue_init = rt2500usb_queue_init, .lib = &rt2500usb_rt2x00_ops, .hw = &rt2500usb_mac80211_ops, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 260c8b4d7399..7c7478219bbc 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1231,7 +1231,6 @@ static const struct rt2x00_ops rt2800pci_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = TXWI_DESC_SIZE, .queue_init = rt2800pci_queue_init, .lib = &rt2800pci_rt2x00_ops, .drv = &rt2800pci_rt2800_ops, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b81d5098816a..68ea00e169d2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -905,7 +905,6 @@ static const struct rt2x00_ops rt2800usb_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, .queue_init = rt2800usb_queue_init, .lib = &rt2800usb_rt2x00_ops, .drv = &rt2800usb_rt2800_ops, @@ -922,7 +921,6 @@ static const struct rt2x00_ops rt2800usb_ops_5592 = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE_5592, .queue_init = rt2800usb_queue_init, .lib = &rt2800usb_rt2x00_ops, .drv = &rt2800usb_rt2800_ops, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2a17f7e4ed5e..ee3fc570b11d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -648,7 +648,6 @@ struct rt2x00_ops { const unsigned int eeprom_size; const unsigned int rf_size; const unsigned int tx_queues; - const unsigned int extra_tx_headroom; void (*queue_init)(struct data_queue *queue); const struct rt2x00lib_ops *lib; const void *drv; @@ -1007,6 +1006,9 @@ struct rt2x00_dev { */ struct list_head bar_list; spinlock_t bar_list_lock; + + /* Extra TX headroom required for alignment purposes. */ + unsigned int extra_tx_headroom; }; struct rt2x00_bar_list_entry { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index dff5012f0548..f03e3bba51c3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -334,7 +334,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * Remove the extra tx headroom from the skb. */ - skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom); + skb_pull(entry->skb, rt2x00dev->extra_tx_headroom); /* * Signal that the TX descriptor is no longer in the skb. @@ -1049,7 +1049,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) */ rt2x00dev->hw->extra_tx_headroom = max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM, - rt2x00dev->ops->extra_tx_headroom); + rt2x00dev->extra_tx_headroom); /* * Take TX headroom required for alignment into account. @@ -1256,6 +1256,17 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->n_iface_combinations = 1; } +static unsigned int rt2x00dev_extra_tx_headroom(struct rt2x00_dev *rt2x00dev) +{ + if (WARN_ON(!rt2x00dev->tx)) + return 0; + + if (rt2x00_is_usb(rt2x00dev)) + return rt2x00dev->tx[0].winfo_size + rt2x00dev->tx[0].desc_size; + + return rt2x00dev->tx[0].winfo_size; +} + /* * driver allocation handlers. */ @@ -1330,6 +1341,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) if (retval) goto exit; + /* Cache TX headroom value */ + rt2x00dev->extra_tx_headroom = rt2x00dev_extra_tx_headroom(rt2x00dev); + /* * Determine which operating modes are supported, all modes * which require beaconing, depend on the availability of diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index c4f1e2b8dc8e..6c0a91ff963c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -542,8 +542,8 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry, /* * Add the requested extra tx headroom in front of the skb. */ - skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom); - memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom); + skb_push(entry->skb, rt2x00dev->extra_tx_headroom); + memset(entry->skb->data, 0, rt2x00dev->extra_tx_headroom); /* * Call the driver's write_tx_data function, if it exists. @@ -596,7 +596,7 @@ static void rt2x00queue_bar_check(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_bar *bar = (void *) (entry->skb->data + - rt2x00dev->ops->extra_tx_headroom); + rt2x00dev->extra_tx_headroom); struct rt2x00_bar_list_entry *bar_entry; if (likely(!ieee80211_is_back_req(bar->frame_control))) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 17507d12d5ee..53754bc66d05 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -3066,7 +3066,6 @@ static const struct rt2x00_ops rt61pci_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = 0, .queue_init = rt61pci_queue_init, .lib = &rt61pci_rt2x00_ops, .hw = &rt61pci_mac80211_ops, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b2e346a482cc..1616ed484ceb 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2400,7 +2400,6 @@ static const struct rt2x00_ops rt73usb_ops = { .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .tx_queues = NUM_TX_QUEUES, - .extra_tx_headroom = TXD_DESC_SIZE, .queue_init = rt73usb_queue_init, .lib = &rt73usb_rt2x00_ops, .hw = &rt73usb_mac80211_ops, -- GitLab From 7ce0bad5c4586e4e9fb9d3e90d89101cd06fb999 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 6 Jun 2013 09:36:20 +0200 Subject: [PATCH 0955/2900] rt2x00: rt2800usb: nuke rt2800usb_ops_5592 It is exactly the same like the generic rt2800usb_ops. Remove the duplicate and use the generic ops for all devices. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 29 +++++-------------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 68ea00e169d2..7edd903dd749 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -914,22 +914,6 @@ static const struct rt2x00_ops rt2800usb_ops = { #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; -static const struct rt2x00_ops rt2800usb_ops_5592 = { - .name = KBUILD_MODNAME, - .drv_data_size = sizeof(struct rt2800_drv_data), - .max_ap_intf = 8, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .queue_init = rt2800usb_queue_init, - .lib = &rt2800usb_rt2x00_ops, - .drv = &rt2800usb_rt2800_ops, - .hw = &rt2800usb_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2800_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - /* * rt2800usb module information. */ @@ -1242,15 +1226,15 @@ static struct usb_device_id rt2800usb_device_table[] = { #endif #ifdef CONFIG_RT2800USB_RT55XX /* Arcadyan */ - { USB_DEVICE(0x043e, 0x7a32), .driver_info = 5592 }, + { USB_DEVICE(0x043e, 0x7a32) }, /* AVM GmbH */ - { USB_DEVICE(0x057c, 0x8501), .driver_info = 5592 }, + { USB_DEVICE(0x057c, 0x8501) }, /* D-Link DWA-160-B2 */ - { USB_DEVICE(0x2001, 0x3c1a), .driver_info = 5592 }, + { USB_DEVICE(0x2001, 0x3c1a) }, /* Proware */ - { USB_DEVICE(0x043e, 0x7a13), .driver_info = 5592 }, + { USB_DEVICE(0x043e, 0x7a13) }, /* Ralink */ - { USB_DEVICE(0x148f, 0x5572), .driver_info = 5592 }, + { USB_DEVICE(0x148f, 0x5572) }, #endif #ifdef CONFIG_RT2800USB_UNKNOWN /* @@ -1355,9 +1339,6 @@ MODULE_LICENSE("GPL"); static int rt2800usb_probe(struct usb_interface *usb_intf, const struct usb_device_id *id) { - if (id->driver_info == 5592) - return rt2x00usb_probe(usb_intf, &rt2800usb_ops_5592); - return rt2x00usb_probe(usb_intf, &rt2800usb_ops); } -- GitLab From f55d94a600ab5db0df4eccbc15d889ae104d058e Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:17:46 +0200 Subject: [PATCH 0956/2900] brcmfmac: allow firmware-signal tlv to be longer than specified The firmware-signal API specification defines length for the different tlv. During testing on different devices it turned out not all firmware used the tlv length according specification. Therefore the length check is made less strict with this patch. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 5352dc1fdf3c..d6f05ae85de3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1433,7 +1433,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, if (data_len < len + 2) break; - if (len != brcmf_fws_get_tlv_len(fws, type)) + if (len < brcmf_fws_get_tlv_len(fws, type)) break; err = BRCMF_FWS_RET_OK_NOSCHEDULE; -- GitLab From 51f6dd9da27359d9218046ed0003f71e05a673c1 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:17:47 +0200 Subject: [PATCH 0957/2900] brcmfmac: remove fifo bitfield from brcmf_skbuff_cb::if_flags The brcmf_skbuff_cb structure contain if_flags and htod fields. Both have a bitfield defined to hold the fifo number. With a small code change we get rid of the fifo bitfield in if_flags. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index d6f05ae85de3..bc2edc04e525 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -195,7 +195,6 @@ struct brcmf_skbuff_cb { * b[9] - packet is a tx packet. * b[8] - packet uses FIFO credit (non-pspoll). * b[7] - interface in AP mode. - * b[6:4] - AC FIFO number. * b[3:0] - interface index. */ #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800 @@ -208,8 +207,6 @@ struct brcmf_skbuff_cb { #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT 8 #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK 0x0080 #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT 7 -#define BRCMF_SKB_IF_FLAGS_FIFO_MASK 0x0070 -#define BRCMF_SKB_IF_FLAGS_FIFO_SHIFT 4 #define BRCMF_SKB_IF_FLAGS_INDEX_MASK 0x000f #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT 0 @@ -1608,7 +1605,8 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, } static void -brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb) +brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, + struct sk_buff *skb, int fifo) { /* put the packet back to the head of queue @@ -1622,11 +1620,9 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb) enum brcmf_fws_skb_state state; struct sk_buff *pktout; int rc = 0; - int fifo; int hslot; u8 ifidx; - fifo = brcmf_skb_if_flags_get_field(skb, FIFO); state = brcmf_skbcb(skb)->state; entry = brcmf_skbcb(skb)->mac; @@ -1794,7 +1790,7 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, return rc; rollback: - brcmf_fws_rollback_toq(fws, skb); + brcmf_fws_rollback_toq(fws, skb, fifo); return rc; } @@ -1831,7 +1827,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); if (!multicast) fifo = brcmf_fws_prio2fifo[skb->priority]; - brcmf_skb_if_flags_set_field(skb, FIFO, fifo); brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest, multicast, fifo); -- GitLab From df50f756966cc07addaae5449a6fd45a17bdb06c Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:48 +0200 Subject: [PATCH 0958/2900] brcmfmac: Take bus flowcontrol at credit mgmt into account. On bus flow control (no more host bus resources to send packets to device) the netif flow control was toggled, however credit management should also take this status into account. Since there are multiple sources handling this flow control necessary spinlocks were added to protect flow control related data/states. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 ++ .../wireless/brcm80211/brcmfmac/dhd_linux.c | 8 +++++++ .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 2 +- .../wireless/brcm80211/brcmfmac/fwsignal.c | 21 +++++++++++++++++-- .../wireless/brcm80211/brcmfmac/fwsignal.h | 1 + drivers/net/wireless/brcm80211/brcmfmac/usb.c | 8 +++++++ 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 28db9cf39672..86cbfe2c7c6c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -583,6 +583,7 @@ enum brcmf_netif_stop_reason { * @bssidx: index of bss associated with this interface. * @mac_addr: assigned mac address. * @netif_stop: bitmap indicates reason why netif queues are stopped. + * @netif_stop_lock: spinlock for update netif_stop from multiple sources. * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. * @pend_8021x_wait: used for signalling change in count. */ @@ -598,6 +599,7 @@ struct brcmf_if { s32 bssidx; u8 mac_addr[ETH_ALEN]; u8 netif_stop; + spinlock_t netif_stop_lock; atomic_t pend_8021x_cnt; wait_queue_head_t pend_8021x_wait; }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index b98f2235978e..df37645f493e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -240,11 +240,15 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state) { + unsigned long flags; + if (!ifp) return; brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", ifp->bssidx, ifp->netif_stop, reason, state); + + spin_lock_irqsave(&ifp->netif_stop_lock, flags); if (state) { if (!ifp->netif_stop) netif_stop_queue(ifp->ndev); @@ -254,6 +258,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, if (!ifp->netif_stop) netif_wake_queue(ifp->ndev); } + spin_unlock_irqrestore(&ifp->netif_stop_lock, flags); } void brcmf_txflowblock(struct device *dev, bool state) @@ -264,6 +269,8 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_dbg(TRACE, "Enter\n"); + brcmf_fws_bus_blocked(drvr, state); + for (i = 0; i < BRCMF_MAX_IFS; i++) brcmf_txflowblock_if(drvr->iflist[i], BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state); @@ -779,6 +786,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp->bssidx = bssidx; init_waitqueue_head(&ifp->pend_8021x_wait); + spin_lock_init(&ifp->netif_stop_lock); if (mac_addr != NULL) memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index d2487518bd2a..6f3d181659ef 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -2369,12 +2369,12 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) } else { ret = 0; } - spin_unlock_bh(&bus->txqlock); if (pktq_len(&bus->txq) >= TXHI) { bus->txoff = true; brcmf_txflowblock(bus->sdiodev->dev, true); } + spin_unlock_bh(&bus->txqlock); #ifdef DEBUG if (pktq_plen(&bus->txq, prec) > qcount[prec]) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index bc2edc04e525..c1930ef5c55f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -431,6 +431,7 @@ struct brcmf_fws_info { u32 fifo_credit_map; u32 fifo_delay_map; unsigned long borrow_defer_timestamp; + bool bus_flow_blocked; }; /* @@ -1833,6 +1834,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_lock(drvr, flags); if (skcb->mac->suppressed || + fws->bus_flow_blocked || brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) || brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) || (!multicast && @@ -1905,7 +1907,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) brcmf_dbg(TRACE, "enter: fws=%p\n", fws); brcmf_fws_lock(fws->drvr, flags); - for (fifo = NL80211_NUM_ACS; fifo >= 0; fifo--) { + for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked; + fifo--) { brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, fws->fifo_credit[fifo]); for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) { @@ -1915,9 +1918,12 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) credit++; + if (fws->bus_flow_blocked) + break; } if ((fifo == BRCMF_FWS_FIFO_AC_BE) && - (credit == fws->fifo_credit[fifo])) { + (credit == fws->fifo_credit[fifo]) && + (!fws->bus_flow_blocked)) { fws->fifo_credit[fifo] -= credit; while (brcmf_fws_borrow_credit(fws) == 0) { skb = brcmf_fws_deq(fws, fifo); @@ -1929,6 +1935,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) brcmf_fws_return_credits(fws, fifo, 1); break; } + if (fws->bus_flow_blocked) + break; } } else { fws->fifo_credit[fifo] -= credit; @@ -2060,3 +2068,12 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) } brcmf_fws_unlock(fws->drvr, flags); } + +void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked) +{ + struct brcmf_fws_info *fws = drvr->fws; + + fws->bus_flow_blocked = flow_blocked; + if (!flow_blocked) + brcmf_fws_schedule_deq(fws); +} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h index fbe483d23752..9fc860910bd8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h @@ -29,5 +29,6 @@ void brcmf_fws_reset_interface(struct brcmf_if *ifp); void brcmf_fws_add_interface(struct brcmf_if *ifp); void brcmf_fws_del_interface(struct brcmf_if *ifp); void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb); +void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked); #endif /* FWSIGNAL_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 01aed7ad6bec..322cadc51ded 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -82,6 +82,7 @@ struct brcmf_usbdev_info { int tx_high_watermark; int tx_freecount; bool tx_flowblock; + spinlock_t tx_flowblock_lock; struct brcmf_usbreq *tx_reqs; struct brcmf_usbreq *rx_reqs; @@ -411,6 +412,7 @@ static void brcmf_usb_tx_complete(struct urb *urb) { struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; struct brcmf_usbdev_info *devinfo = req->devinfo; + unsigned long flags; brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status, req->skb); @@ -419,11 +421,13 @@ static void brcmf_usb_tx_complete(struct urb *urb) brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); + spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags); if (devinfo->tx_freecount > devinfo->tx_high_watermark && devinfo->tx_flowblock) { brcmf_txflowblock(devinfo->dev, false); devinfo->tx_flowblock = false; } + spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags); } static void brcmf_usb_rx_complete(struct urb *urb) @@ -568,6 +572,7 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); struct brcmf_usbreq *req; int ret; + unsigned long flags; brcmf_dbg(USB, "Enter, skb=%p\n", skb); if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) { @@ -599,11 +604,13 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) goto fail; } + spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags); if (devinfo->tx_freecount < devinfo->tx_low_watermark && !devinfo->tx_flowblock) { brcmf_txflowblock(dev, true); devinfo->tx_flowblock = true; } + spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags); return 0; fail: @@ -1164,6 +1171,7 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, /* Initialize the spinlocks */ spin_lock_init(&devinfo->qlock); + spin_lock_init(&devinfo->tx_flowblock_lock); INIT_LIST_HEAD(&devinfo->rx_freeq); INIT_LIST_HEAD(&devinfo->rx_postq); -- GitLab From fe353b24c385f219aca1e19767119017618deca7 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:17:49 +0200 Subject: [PATCH 0959/2900] brcmfmac: rework credit pickup to assure consistent handling Reworked brcmf_skb_pick_up_credit() so it can be used for both fcmode flavours in the same way. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index c1930ef5c55f..a7a02473e7e9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1040,24 +1040,21 @@ static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) queue_work(fws->fws_wq, &fws->fws_dequeue_work); } -static void brcmf_skb_pick_up_credit(struct brcmf_fws_info *fws, int fifo, +static void brcmf_fws_skb_pickup_credit(struct brcmf_fws_info *fws, int fifo, struct sk_buff *p) { struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(p)->mac; - if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { - if (fws->fcmode != BRCMF_FWS_FCMODE_IMPLIED_CREDIT) - return; + if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) brcmf_fws_return_credits(fws, fifo, 1); - } else { + else if (!brcmf_skb_if_flags_get_field(p, REQUESTED)) /* * if this packet did not count against FIFO credit, it * must have taken a requested_credit from the destination * entry (for pspoll etc.) */ - if (!brcmf_skb_if_flags_get_field(p, REQUESTED)) - entry->requested_credit++; - } + entry->requested_credit++; + brcmf_fws_schedule_deq(fws); } @@ -1272,7 +1269,9 @@ brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, /* pick up the implicit credit from this packet */ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); - brcmf_skb_pick_up_credit(fws, fifo, skb); + if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT || + !(brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) + brcmf_fws_skb_pickup_credit(fws, fifo, skb); if (!remove_from_hanger) ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); @@ -1845,7 +1844,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) } else { if (brcmf_fws_commit_skb(fws, fifo, skb)) if (!multicast) - brcmf_skb_pick_up_credit(fws, fifo, skb); + brcmf_fws_skb_pickup_credit(fws, fifo, skb); } brcmf_fws_unlock(drvr, flags); return 0; @@ -2053,18 +2052,15 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) { ulong flags; + int fifo; brcmf_fws_lock(fws->drvr, flags); brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); /* the packet never reached firmware so reclaim credit */ - if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT && - brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { - brcmf_fws_return_credits(fws, - brcmf_skb_htod_tag_get_field(skb, - FIFO), - 1); - brcmf_fws_schedule_deq(fws); + if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { + fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); + brcmf_fws_skb_pickup_credit(fws, fifo, skb); } brcmf_fws_unlock(fws->drvr, flags); } -- GitLab From 289ec1c71911fe4b1b9bab25ae4a2ab75036b72d Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:17:50 +0200 Subject: [PATCH 0960/2900] brcmfmac: explicitly indicate sk_buff is sent upon request credit Firmware can request the driver for transmit packets using two different signals. Only for one signal a flag was set in the sk_buff control buffer. This patch adds explicit flag for the other signal as well. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 122 ++++++++---------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index a7a02473e7e9..d080874a14ab 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -190,13 +190,16 @@ struct brcmf_skbuff_cb { /* * sk_buff control if flags * - * b[11] - packet sent upon firmware request. + * b[12] - packet sent upon credit request. + * b[11] - packet sent upon packet request. * b[10] - packet only contains signalling data. * b[9] - packet is a tx packet. * b[8] - packet uses FIFO credit (non-pspoll). * b[7] - interface in AP mode. * b[3:0] - interface index. */ +#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK 0x1000 +#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT 12 #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400 @@ -998,6 +1001,37 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, return BRCMF_FWS_RET_OK_SCHEDULE; } +static int brcmf_fws_macdesc_use_credit(struct brcmf_fws_mac_descriptor *entry, + struct sk_buff *skb) +{ + int use_credit = 1; + + if (entry->state == BRCMF_FWS_STATE_CLOSE) { + if (entry->requested_credit > 0) { + /* + * if the packet was pulled out while destination is in + * closed state but had a non-zero packets requested, + * then this should not count against the FIFO credit. + * That is due to the fact that the firmware will + * most likely hold onto this packet until a suitable + * time later to push it to the appropriate AC FIFO. + */ + entry->requested_credit--; + brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1); + use_credit = 0; + } else if (entry->requested_packet > 0) { + entry->requested_packet--; + brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); + use_credit = 0; + } + } else { + WARN_ON(entry->requested_credit); + WARN_ON(entry->requested_packet); + } + brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit); + return use_credit; +} + static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, u8 fifo, u8 credits) { @@ -1047,10 +1081,11 @@ static void brcmf_fws_skb_pickup_credit(struct brcmf_fws_info *fws, int fifo, if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) brcmf_fws_return_credits(fws, fifo, 1); - else if (!brcmf_skb_if_flags_get_field(p, REQUESTED)) + else if (brcmf_skb_if_flags_get_field(p, REQ_CREDIT) && + entry->state == BRCMF_FWS_STATE_CLOSE) /* * if this packet did not count against FIFO credit, it - * must have taken a requested_credit from the destination + * could have taken a requested_credit from the destination * entry (for pspoll etc.) */ entry->requested_credit++; @@ -1108,7 +1143,6 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) struct brcmf_fws_mac_descriptor *table; struct brcmf_fws_mac_descriptor *entry; struct sk_buff *p; - int use_credit = 1; int num_nodes; int node_pos; int prec_out; @@ -1143,26 +1177,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) if (p == NULL) continue; - /* did the packet come from suppress sub-queue? */ - if (entry->requested_credit > 0) { - entry->requested_credit--; - /* - * if the packet was pulled out while destination is in - * closed state but had a non-zero packets requested, - * then this should not count against the FIFO credit. - * That is due to the fact that the firmware will - * most likely hold onto this packet until a suitable - * time later to push it to the appropriate AC FIFO. - */ - if (entry->state == BRCMF_FWS_STATE_CLOSE) - use_credit = 0; - } else if (entry->requested_packet > 0) { - entry->requested_packet--; - brcmf_skb_if_flags_set_field(p, REQUESTED, 1); - if (entry->state == BRCMF_FWS_STATE_CLOSE) - use_credit = 0; - } - brcmf_skb_if_flags_set_field(p, CREDITCHECK, use_credit); + brcmf_fws_macdesc_use_credit(entry, p); /* move dequeue position to ensure fair round-robin */ fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes; @@ -1664,13 +1679,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, /* decrement sequence count */ entry->seq[fifo]--; } - /* - if this packet did not count against FIFO credit, it must have - taken a requested_credit from the firmware (for pspoll etc.) - */ - if (!(brcmf_skbcb(skb)->if_flags & - BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) - entry->requested_credit++; } else { brcmf_err("no mac entry linked\n"); rc = -ENOENT; @@ -1679,10 +1687,12 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, fail: if (rc) { - brcmf_txfinalize(fws->drvr, skb, false); + brcmf_fws_bustxfail(fws, skb); fws->stats.rollback_failed++; - } else + } else { fws->stats.rollback_success++; + brcmf_fws_skb_pickup_credit(fws, fifo, skb); + } } static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) @@ -1710,30 +1720,10 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, { struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; int *credit = &fws->fifo_credit[fifo]; - int use_credit = 1; brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit); - if (entry->requested_credit > 0) { - /* - * if the packet was pulled out while destination is in - * closed state but had a non-zero packets requested, - * then this should not count against the FIFO credit. - * That is due to the fact that the firmware will - * most likely hold onto this packet until a suitable - * time later to push it to the appropriate AC FIFO. - */ - entry->requested_credit--; - if (entry->state == BRCMF_FWS_STATE_CLOSE) - use_credit = 0; - } else if (entry->requested_packet > 0) { - entry->requested_packet--; - brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); - if (entry->state == BRCMF_FWS_STATE_CLOSE) - use_credit = 0; - } - brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit); - if (!use_credit) { + if (!brcmf_fws_macdesc_use_credit(entry, skb)) { brcmf_dbg(TRACE, "exit: no creditcheck set\n"); return 0; } @@ -1842,9 +1832,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) drvr->fws->fifo_delay_map |= 1 << fifo; brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); } else { - if (brcmf_fws_commit_skb(fws, fifo, skb)) - if (!multicast) - brcmf_fws_skb_pickup_credit(fws, fifo, skb); + brcmf_fws_commit_skb(fws, fifo, skb); } brcmf_fws_unlock(drvr, flags); return 0; @@ -1900,7 +1888,6 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) struct sk_buff *skb; ulong flags; int fifo; - int credit; fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); @@ -1910,35 +1897,32 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) fifo--) { brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, fws->fifo_credit[fifo]); - for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) { + while (fws->fifo_credit[fifo]) { skb = brcmf_fws_deq(fws, fifo); - if (!skb || brcmf_fws_commit_skb(fws, fifo, skb)) + if (!skb) break; if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) - credit++; + fws->fifo_credit[fifo]--; + + if (brcmf_fws_commit_skb(fws, fifo, skb)) + break; if (fws->bus_flow_blocked) break; } if ((fifo == BRCMF_FWS_FIFO_AC_BE) && - (credit == fws->fifo_credit[fifo]) && + (fws->fifo_credit[fifo] == 0) && (!fws->bus_flow_blocked)) { - fws->fifo_credit[fifo] -= credit; while (brcmf_fws_borrow_credit(fws) == 0) { skb = brcmf_fws_deq(fws, fifo); if (!skb) { brcmf_fws_return_credits(fws, fifo, 1); break; } - if (brcmf_fws_commit_skb(fws, fifo, skb)) { - brcmf_fws_return_credits(fws, fifo, 1); - break; - } + brcmf_fws_commit_skb(fws, fifo, skb); if (fws->bus_flow_blocked) break; } - } else { - fws->fifo_credit[fifo] -= credit; } } brcmf_fws_unlock(fws->drvr, flags); -- GitLab From 8071fd61b421f5c9b9a67a7c222c1f5581bcf0f3 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:17:51 +0200 Subject: [PATCH 0961/2900] brcmfmac: reducing debug logging in firmware-signalling code The debug logging in firmware-signalling code was rather extensive and for a large part in the data path. This patch removes large part or the level is changed to DATA level. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/dhd_linux.c | 4 +- .../wireless/brcm80211/brcmfmac/fwsignal.c | 124 +++++++++--------- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index df37645f493e..9450d10b0fb9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -179,7 +179,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, struct brcmf_pub *drvr = ifp->drvr; struct ethhdr *eh; - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); /* Can the device send data? */ if (drvr->bus_if->state != BRCMF_BUS_DATA) { @@ -287,7 +287,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) u8 ifidx; int ret; - brcmf_dbg(TRACE, "Enter\n"); + brcmf_dbg(DATA, "Enter\n"); skb_queue_walk_safe(skb_list, skb, pnext) { skb_unlink(skb, skb_list); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index d080874a14ab..73e3e1dc073a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -343,6 +343,7 @@ enum brcmf_fws_mac_desc_state { * @transit_count: packet in transit to firmware. */ struct brcmf_fws_mac_descriptor { + char name[16]; u8 occupied; u8 mac_handle; u8 interface_id; @@ -508,7 +509,6 @@ static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger) { int i; - brcmf_dbg(TRACE, "enter\n"); memset(hanger, 0, sizeof(*hanger)); for (i = 0; i < ARRAY_SIZE(hanger->items); i++) hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; @@ -518,7 +518,6 @@ static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h) { u32 i; - brcmf_dbg(TRACE, "enter\n"); i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS; while (i != h->slot_pos) { @@ -534,14 +533,12 @@ static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h) h->failed_slotfind++; i = BRCMF_FWS_HANGER_MAXITEMS; done: - brcmf_dbg(TRACE, "exit: %d\n", i); return i; } static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h, struct sk_buff *pkt, u32 slot_id) { - brcmf_dbg(TRACE, "enter\n"); if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; @@ -561,7 +558,6 @@ static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, u32 slot_id, struct sk_buff **pktout, bool remove_item) { - brcmf_dbg(TRACE, "enter\n"); if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; @@ -584,8 +580,6 @@ static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, u32 slot_id, u8 gen) { - brcmf_dbg(TRACE, "enter\n"); - if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; @@ -604,7 +598,6 @@ static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger, struct sk_buff *pkt, u32 slot_id, int *gen) { - brcmf_dbg(TRACE, "enter\n"); *gen = 0xff; if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) @@ -628,7 +621,6 @@ static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws, int i; enum brcmf_fws_hanger_item_state s; - brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); for (i = 0; i < ARRAY_SIZE(h->items); i++) { s = h->items[i].state; if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE || @@ -645,6 +637,19 @@ static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws, } } +static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws, + struct brcmf_fws_mac_descriptor *desc) +{ + if (desc == &fws->desc.other) + strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name)); + else if (desc->mac_handle) + scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d", + desc->mac_handle, desc->interface_id); + else + scnprintf(desc->name, sizeof(desc->name), "MACIF:%d", + desc->interface_id); +} + static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, u8 *addr, u8 ifidx) { @@ -676,7 +681,6 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) struct brcmf_fws_mac_descriptor *entry; int i; - brcmf_dbg(TRACE, "enter: ea=%pM\n", ea); if (ea == NULL) return ERR_PTR(-EINVAL); @@ -698,8 +702,6 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, bool multicast; enum nl80211_iftype iftype; - brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); - multicast = is_multicast_ether_addr(da); iftype = brcmf_cfg80211_get_iftype(ifp); @@ -720,7 +722,6 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, entry = &fws->desc.other; done: - brcmf_dbg(TRACE, "exit: entry=%p\n", entry); return entry; } @@ -753,11 +754,7 @@ static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws, struct brcmf_fws_mac_descriptor *entry, int ifidx) { - brcmf_dbg(TRACE, "enter: entry=(ea=%pM, ifid=%d), ifidx=%d\n", - entry->ea, entry->interface_id, ifidx); if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) { - brcmf_dbg(TRACE, "flush psq: ifidx=%d, qlen=%d\n", - ifidx, entry->psq.len); brcmf_fws_psq_flush(fws, &entry->psq, ifidx); entry->occupied = !!(entry->psq.len); } @@ -773,7 +770,6 @@ static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws, int prec; u32 hslot; - brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); txq = brcmf_bus_gettxq(fws->drvr->bus_if); if (IS_ERR(txq)) { brcmf_dbg(TRACE, "no txq to clean up\n"); @@ -799,7 +795,6 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) struct brcmf_fws_mac_descriptor *table; bool (*matchfn)(struct sk_buff *, void *) = NULL; - brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); if (fws == NULL) return; @@ -820,7 +815,6 @@ static void brcmf_fws_tim_update(struct brcmf_fws_info *ctx, struct brcmf_fws_mac_descriptor *entry, int prec) { - brcmf_dbg(TRACE, "enter: ea=%pM\n", entry->ea); if (entry->state == BRCMF_FWS_STATE_CLOSE) { /* check delayedQ and suppressQ in one call using bitmap */ if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) @@ -877,8 +871,9 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) entry = &fws->desc.nodes[mac_handle & 0x1F]; if (type == BRCMF_FWS_TYPE_MACDESC_DEL) { - brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx); if (entry->occupied) { + brcmf_dbg(TRACE, "deleting %s mac %pM\n", + entry->name, addr); brcmf_fws_mac_desc_cleanup(fws, entry, -1); brcmf_fws_clear_mac_descriptor(entry); } else @@ -886,25 +881,28 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) return 0; } - brcmf_dbg(TRACE, - "add mac %pM handle %u idx %d\n", addr, mac_handle, ifidx); existing = brcmf_fws_mac_descriptor_lookup(fws, addr); if (IS_ERR(existing)) { if (!entry->occupied) { entry->mac_handle = mac_handle; brcmf_fws_init_mac_descriptor(entry, addr, ifidx); + brcmf_fws_macdesc_set_name(fws, entry); brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); + brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr); } else { fws->stats.mac_update_failed++; } } else { if (entry != existing) { - brcmf_dbg(TRACE, "relocate mac\n"); + brcmf_dbg(TRACE, "copy mac %s\n", existing->name); memcpy(entry, existing, offsetof(struct brcmf_fws_mac_descriptor, psq)); entry->mac_handle = mac_handle; brcmf_fws_clear_mac_descriptor(existing); + brcmf_fws_macdesc_set_name(fws, entry); + brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, + addr); } else { brcmf_dbg(TRACE, "use existing\n"); WARN_ON(entry->mac_handle != mac_handle); @@ -928,6 +926,8 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, return -ESRCH; } + brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, + entry->name); /* a state update should wipe old credits? */ entry->requested_credit = 0; if (type == BRCMF_FWS_TYPE_MAC_OPEN) { @@ -950,7 +950,6 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, ifidx = data[0]; - brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); if (ifidx >= BRCMF_MAX_IFS) { ret = -ERANGE; goto fail; @@ -962,6 +961,8 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, goto fail; } + brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, + entry->name); switch (type) { case BRCMF_FWS_TYPE_INTERFACE_OPEN: entry->state = BRCMF_FWS_STATE_OPEN; @@ -992,6 +993,9 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, return -ESRCH; } + brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n", + brcmf_fws_get_tlv_name(type), type, entry->name, + data[0], data[2]); if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) entry->requested_credit = data[0]; else @@ -1108,7 +1112,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, return -ENOENT; } - brcmf_dbg(TRACE, "enter: ea=%pM, qlen=%d\n", entry->ea, entry->psq.len); + brcmf_dbg(DATA, "enter: fifo %d skb %p\n", fifo, p); if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { prec += 1; qfull_stat = &fws->stats.supprq_full_error; @@ -1202,7 +1206,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) } p = NULL; done: - brcmf_dbg(TRACE, "exit: fifo %d skb %p\n", fifo, p); + brcmf_dbg(DATA, "exit: fifo %d skb %p\n", fifo, p); return p; } @@ -1221,6 +1225,9 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, entry->suppress_count = brcmu_pktq_mlen(&entry->psq, 1 << (fifo * 2 + 1)); entry->suppr_transit_count = entry->transit_count; + brcmf_dbg(DATA, "suppress %s: supp_cnt %d transit %d\n", + entry->name, entry->suppress_count, + entry->transit_count); } entry->generation = genbit; @@ -1244,17 +1251,17 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, } static int -brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, +brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, u32 genbit) { u32 fifo; int ret; bool remove_from_hanger = true; struct sk_buff *skb; + struct brcmf_skbuff_cb *skcb; struct brcmf_fws_mac_descriptor *entry = NULL; - brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n", - flags, hslot); + brcmf_dbg(DATA, "flags %d\n", flags); if (flags == BRCMF_FWS_TXSTATUS_DISCARD) fws->stats.txs_discard++; @@ -1276,12 +1283,16 @@ brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, return ret; } - entry = brcmf_skbcb(skb)->mac; + skcb = brcmf_skbcb(skb); + entry = skcb->mac; if (WARN_ON(!entry)) { brcmu_pkt_buf_free_skb(skb); return -EINVAL; } + brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, + skcb->htod); + /* pick up the implicit credit from this packet */ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT || @@ -1311,11 +1322,11 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, return BRCMF_FWS_RET_OK_NOSCHEDULE; } - brcmf_dbg(TRACE, "enter: data %pM\n", data); + brcmf_dbg(DATA, "enter: data %pM\n", data); for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) brcmf_fws_return_credits(fws, i, data[i]); - brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map, + brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map, fws->fifo_delay_map); return BRCMF_FWS_RET_OK_SCHEDULE; } @@ -1335,7 +1346,7 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) hslot = brcmf_txstatus_get_field(status, HSLOT); genbit = brcmf_txstatus_get_field(status, GENERATION); - return brcmf_fws_txstatus_process(fws, flags, hslot, genbit); + return brcmf_fws_txs_process(fws, flags, hslot, genbit); } static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) @@ -1343,7 +1354,7 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) __le32 timestamp; memcpy(×tamp, &data[2], sizeof(timestamp)); - brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1], + brcmf_dbg(CTL, "received: seq %d, timestamp %d\n", data[1], le32_to_cpu(timestamp)); return 0; } @@ -1404,7 +1415,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, s32 status; s32 err; - brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n", + brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n", ifidx, skb->len, signal_len); WARN_ON(signal_len > skb->len); @@ -1438,8 +1449,9 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, len = signal_data[1]; data = signal_data + 2; - brcmf_dbg(INFO, "tlv type=%d (%s), len=%d, data[0]=%d\n", type, - brcmf_fws_get_tlv_name(type), len, *data); + brcmf_dbg(HDRS, "tlv type=%s (%d), len=%d (%d)\n", + brcmf_fws_get_tlv_name(type), type, len, + brcmf_fws_get_tlv_len(fws, type)); /* abort parsing when length invalid */ if (data_len < len + 2) @@ -1522,8 +1534,6 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) u8 fillers; __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); - brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u, pkttag=0x%08X\n", - entry->ea, entry->interface_id, le32_to_cpu(pkttag)); if (entry->send_tim_signal) data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; @@ -1708,7 +1718,7 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) fws->fifo_credit[lender_ac]--; if (fws->fifo_credit[lender_ac] == 0) fws->fifo_credit_map &= ~(1 << lender_ac); - brcmf_dbg(TRACE, "borrow credit from: %d\n", lender_ac); + brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac); return 0; } } @@ -1721,12 +1731,8 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; int *credit = &fws->fifo_credit[fifo]; - brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit); - - if (!brcmf_fws_macdesc_use_credit(entry, skb)) { - brcmf_dbg(TRACE, "exit: no creditcheck set\n"); + if (!brcmf_fws_macdesc_use_credit(entry, skb)) return 0; - } if (fifo != BRCMF_FWS_FIFO_AC_BE) fws->borrow_defer_timestamp = jiffies + @@ -1738,13 +1744,13 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, brcmf_fws_borrow_credit(fws) == 0) return 0; - brcmf_dbg(TRACE, "exit: ac=%d, credits depleted\n", fifo); + brcmf_dbg(DATA, "exit: ac=%d, credits depleted\n", fifo); return -ENAVAIL; } (*credit)--; if (!(*credit)) fws->fifo_credit_map &= ~(1 << fifo); - brcmf_dbg(TRACE, "exit: ac=%d, credits=%d\n", fifo, *credit); + brcmf_dbg(DATA, "exit: ac=%d, credits=%d\n", fifo, *credit); return 0; } @@ -1766,6 +1772,8 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, goto rollback; } + brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, + skcb->htod); rc = brcmf_bus_txdata(bus, skb); if (rc < 0) goto rollback; @@ -1818,8 +1826,8 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) if (!multicast) fifo = brcmf_fws_prio2fifo[skb->priority]; - brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest, - multicast, fifo); + brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name, + eh->h_dest, multicast, fifo); brcmf_fws_lock(drvr, flags); if (skcb->mac->suppressed || @@ -1854,16 +1862,16 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp) struct brcmf_fws_info *fws = ifp->drvr->fws; struct brcmf_fws_mac_descriptor *entry; - brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n", - ifp->bssidx, ifp->mac_addr); if (!ifp->ndev || !ifp->drvr->fw_signals) return; entry = &fws->desc.iface[ifp->ifidx]; ifp->fws_desc = entry; brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); + brcmf_fws_macdesc_set_name(fws, entry); brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); + brcmf_dbg(TRACE, "added %s\n", entry->name); } void brcmf_fws_del_interface(struct brcmf_if *ifp) @@ -1871,12 +1879,12 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp) struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; ulong flags; - brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); if (!entry) return; brcmf_fws_lock(ifp->drvr, flags); ifp->fws_desc = NULL; + brcmf_dbg(TRACE, "deleting %s\n", entry->name); brcmf_fws_clear_mac_descriptor(entry); brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx); brcmf_fws_unlock(ifp->drvr, flags); @@ -1891,12 +1899,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); - brcmf_dbg(TRACE, "enter: fws=%p\n", fws); brcmf_fws_lock(fws->drvr, flags); for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked; fifo--) { - brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, - fws->fifo_credit[fifo]); while (fws->fifo_credit[fifo]) { skb = brcmf_fws_deq(fws, fifo); if (!skb) @@ -1980,14 +1985,14 @@ int brcmf_fws_init(struct brcmf_pub *drvr) brcmf_fws_hanger_init(&drvr->fws->hanger); brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0); + brcmf_fws_macdesc_set_name(drvr->fws, &drvr->fws->desc.other); brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); /* create debugfs file for statistics */ brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); - /* TODO: remove upon feature delivery */ - brcmf_err("%s bdcv2 tlv signaling [%x]\n", + brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", drvr->fw_signals ? "enabled" : "disabled", tlv); return 0; @@ -2029,7 +2034,6 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) if (!fws) return false; - brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode); return fws->fcmode != BRCMF_FWS_FCMODE_NONE; } @@ -2039,7 +2043,7 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) int fifo; brcmf_fws_lock(fws->drvr, flags); - brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, + brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); /* the packet never reached firmware so reclaim credit */ if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { -- GitLab From ce17194ead199bec9f4721bdcffa624d7564845d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:52 +0200 Subject: [PATCH 0962/2900] brcmfmac: On bus flow control use fw signalling or netif. Currently on a bus flow control both fws is informed and netif queue gets closed. In case of fw signalling enabled, let the flow control be handled by fw signalling only. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 9450d10b0fb9..63cadf63ccfe 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -269,11 +269,14 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_dbg(TRACE, "Enter\n"); - brcmf_fws_bus_blocked(drvr, state); - - for (i = 0; i < BRCMF_MAX_IFS; i++) - brcmf_txflowblock_if(drvr->iflist[i], - BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state); + if (brcmf_fws_fc_active(drvr->fws)) { + brcmf_fws_bus_blocked(drvr, state); + } else { + for (i = 0; i < BRCMF_MAX_IFS; i++) + brcmf_txflowblock_if(drvr->iflist[i], + BRCMF_NETIF_STOP_REASON_BLOCK_BUS, + state); + } } void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) -- GitLab From be4910adf1817d357bfb20d28e0f8b6b0fecd945 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:53 +0200 Subject: [PATCH 0963/2900] brcmfmac: For FW signalling it is necessary to track gen bit. Store gen bit on suppressed packet per entry and use latest stored version for each packet which gets transmitted to fw. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 92 ++++++------------- 1 file changed, 29 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 73e3e1dc073a..682ac62459ea 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -246,7 +246,7 @@ struct brcmf_skbuff_cb { #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK 0x00ffff00 #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT 8 #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK 0x000000ff -#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 +#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 #define brcmf_skb_htod_tag_set_field(skb, field, value) \ brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \ @@ -384,12 +384,10 @@ enum brcmf_fws_hanger_item_state { * struct brcmf_fws_hanger_item - single entry for tx pending packet. * * @state: entry is either free or occupied. - * @gen: generation. * @pkt: packet itself. */ struct brcmf_fws_hanger_item { enum brcmf_fws_hanger_item_state state; - u8 gen; struct sk_buff *pkt; }; @@ -537,7 +535,7 @@ static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h) } static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h, - struct sk_buff *pkt, u32 slot_id) + struct sk_buff *pkt, u32 slot_id) { if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; @@ -571,20 +569,17 @@ static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, if (remove_item) { h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; h->items[slot_id].pkt = NULL; - h->items[slot_id].gen = 0xff; h->popped++; } return 0; } static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, - u32 slot_id, u8 gen) + u32 slot_id) { if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; - h->items[slot_id].gen = gen; - if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) { brcmf_err("entry not in use\n"); return -EINVAL; @@ -594,24 +589,6 @@ static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, return 0; } -static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger, - struct sk_buff *pkt, u32 slot_id, - int *gen) -{ - *gen = 0xff; - - if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) - return -ENOENT; - - if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { - brcmf_err("slot not in use\n"); - return -EINVAL; - } - - *gen = hanger->items[slot_id].gen; - return 0; -} - static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws, bool (*fn)(struct sk_buff *, void *), int ifidx) @@ -838,9 +815,6 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, if (WARN_ON(!ifp)) return; - brcmf_dbg(TRACE, - "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx); - if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER) brcmf_txflowblock_if(ifp, @@ -1220,7 +1194,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); /* this packet was suppressed */ - if (!entry->suppressed || entry->generation != genbit) { + if (!entry->suppressed) { entry->suppressed = true; entry->suppress_count = brcmu_pktq_mlen(&entry->psq, 1 << (fifo * 2 + 1)); @@ -1242,8 +1216,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, * Mark suppressed to avoid a double free during * wlfc cleanup */ - brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot, - genbit); + brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); entry->suppress_count++; } @@ -1573,15 +1546,34 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); struct brcmf_fws_mac_descriptor *entry = skcb->mac; int rc = 0; - bool header_needed; + bool first_time; int hslot = BRCMF_FWS_HANGER_MAXITEMS; u8 free_ctr; u8 ifidx; u8 flags; - header_needed = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; + first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; - if (header_needed) { + if (!first_time) { + rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p); + if (rc) { + brcmf_err("hdrpull failed\n"); + return rc; + } + } + brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); + brcmf_skb_htod_tag_set_field(p, FIFO, fifo); + brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); + flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; + if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) { + /* + * Indicate that this packet is being sent in response to an + * explicit request from the firmware side. + */ + flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; + } + brcmf_skb_htod_tag_set_field(p, FLAGS, flags); + if (first_time) { /* obtaining free slot may fail, but that will be caught * by the hanger push. This assures the packet has a BDC * header upon return. @@ -1590,40 +1582,14 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, free_ctr = entry->seq[fifo]; brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); - brcmf_skb_htod_tag_set_field(p, GENERATION, 1); entry->transit_count++; } - brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); - brcmf_skb_htod_tag_set_field(p, FIFO, fifo); - flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; - if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) { - /* - Indicate that this packet is being sent in response to an - explicit request from the firmware side. - */ - flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; - } - brcmf_skb_htod_tag_set_field(p, FLAGS, flags); - if (header_needed) { - brcmf_fws_hdrpush(fws, p); + brcmf_fws_hdrpush(fws, p); + if (first_time) { rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); if (rc) brcmf_err("hanger push failed: rc=%d\n", rc); - } else { - int gen; - - /* remove old header */ - rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p); - if (rc == 0) { - hslot = brcmf_skb_htod_tag_get_field(p, HSLOT); - brcmf_fws_hanger_get_genbit(&fws->hanger, p, - hslot, &gen); - brcmf_skb_htod_tag_set_field(p, GENERATION, gen); - - /* push new header */ - brcmf_fws_hdrpush(fws, p); - } } return rc; -- GitLab From afc3bbfcd62efe87041571369b2d12beb00f4bc3 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:54 +0200 Subject: [PATCH 0964/2900] brcmfmac: Correct creditmap when credit borrowing is active. When credit borrowing is active the BE credits have been depleted, however the worker should still be scheduled. In case of credit borrowing correct credit map to make sure worker remains active. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 682ac62459ea..abba7f78a6fe 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1020,6 +1020,8 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, if (!credits) return; + fws->fifo_credit_map |= 1 << fifo; + if ((fifo == BRCMF_FWS_FIFO_AC_BE) && (fws->credits_borrowed[0])) { for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0; @@ -1041,7 +1043,6 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, } } - fws->fifo_credit_map |= 1 << fifo; fws->fifo_credit[fifo] += credits; } @@ -1675,8 +1676,10 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) { int lender_ac; - if (time_after(fws->borrow_defer_timestamp, jiffies)) + if (time_after(fws->borrow_defer_timestamp, jiffies)) { + fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE); return -ENAVAIL; + } for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) { if (fws->fifo_credit[lender_ac]) { @@ -1684,10 +1687,12 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) fws->fifo_credit[lender_ac]--; if (fws->fifo_credit[lender_ac] == 0) fws->fifo_credit_map &= ~(1 << lender_ac); + fws->fifo_credit_map |= (1 << BRCMF_FWS_FIFO_AC_BE); brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac); return 0; } } + fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE); return -ENAVAIL; } -- GitLab From 5cd51c2bad56625e4447739426845cfa37fc11a5 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:56 +0200 Subject: [PATCH 0965/2900] brcmfmac: Find correct MAC descriptor in case of TDLS. In case of TDLS find the correct MAC descriptor for fw signalling data. In case of TDLS each destination gets its own entry. This was not handled correctly for P2P client. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/fwsignal.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index abba7f78a6fe..876ea423048d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -677,26 +677,21 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, { struct brcmf_fws_mac_descriptor *entry = &fws->desc.other; bool multicast; - enum nl80211_iftype iftype; multicast = is_multicast_ether_addr(da); - iftype = brcmf_cfg80211_get_iftype(ifp); - /* Multicast destination and P2P clients get the interface entry. - * STA gets the interface entry if there is no exact match. For - * example, TDLS destinations have their own entry. + /* Multicast destination, STA and P2P clients get the interface entry. + * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations + * have their own entry. */ - entry = NULL; - if ((multicast || iftype == NL80211_IFTYPE_STATION || - iftype == NL80211_IFTYPE_P2P_CLIENT) && ifp->fws_desc) + if (multicast && ifp->fws_desc) { entry = ifp->fws_desc; - - if (entry != NULL && iftype != NL80211_IFTYPE_STATION) goto done; + } entry = brcmf_fws_mac_descriptor_lookup(fws, da); if (IS_ERR(entry)) - entry = &fws->desc.other; + entry = ifp->fws_desc; done: return entry; -- GitLab From 402e3ba20285f0ebe4f4bebdecb7ab24999f3626 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:57 +0200 Subject: [PATCH 0966/2900] brcmfmac: fix invalid ifp lookup in firmware-signalling The destination entries for firmware-signalled flow control have the interface id stored. This needs to be translated to bsscfg index when looking up the ifp object for the interface. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 876ea423048d..5f3874288d6b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -805,7 +805,7 @@ static void brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, u8 if_id) { - struct brcmf_if *ifp = fws->drvr->iflist[if_id]; + struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1]; if (WARN_ON(!ifp)) return; -- GitLab From 0d24b0eade7d4b6a5d06fe02645449b1fd0f8e17 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:58 +0200 Subject: [PATCH 0967/2900] brcmfmac: Accept only first creditmap event. During P2P testing it turned out that the firmware sents multiple multiple creditmap event messages. Only the first message from the firmware should be processed. Otherwise the firmware-signalled flow control can run haywire when it has packets outstanding in firmware. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 5f3874288d6b..bba4ff04ee19 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -434,6 +434,7 @@ struct brcmf_fws_info { u32 fifo_delay_map; unsigned long borrow_defer_timestamp; bool bus_flow_blocked; + bool creditmap_received; }; /* @@ -1356,6 +1357,10 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, brcmf_err("event payload too small (%d)\n", e->datalen); return -EINVAL; } + if (fws->creditmap_received) + return 0; + + fws->creditmap_received = true; brcmf_dbg(TRACE, "enter: credits %pM\n", credits); brcmf_fws_lock(ifp->drvr, flags); -- GitLab From 2747e5f7f83d215cbc9bdb66f69411ff3dedeeee Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:17:59 +0200 Subject: [PATCH 0968/2900] brcmfmac: Signalling header push and pull on logic places. Currently suppressed packets get enque-ed with header which then gets pulled before transmit. It is more logical and clean to pull the header on return and push it unconditionally on xmit. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index bba4ff04ee19..6255312d5986 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1187,6 +1187,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; u32 hslot; int ret; + u8 ifidx; hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); @@ -1203,9 +1204,12 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, entry->generation = genbit; - ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); + ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); + if (ret == 0) + ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, + skb); if (ret != 0) { - /* suppress q is full, drop this packet */ + /* suppress q is full or hdrpull failed, drop this packet */ brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true); } else { @@ -1550,18 +1554,10 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, bool first_time; int hslot = BRCMF_FWS_HANGER_MAXITEMS; u8 free_ctr; - u8 ifidx; u8 flags; first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; - if (!first_time) { - rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p); - if (rc) { - brcmf_err("hdrpull failed\n"); - return rc; - } - } brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); brcmf_skb_htod_tag_set_field(p, FIFO, fifo); brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); @@ -1584,15 +1580,14 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); entry->transit_count++; - } - - brcmf_fws_hdrpush(fws, p); - if (first_time) { rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); if (rc) brcmf_err("hanger push failed: rc=%d\n", rc); } + if (rc == 0) + brcmf_fws_hdrpush(fws, p); + return rc; } @@ -1613,7 +1608,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *pktout; int rc = 0; int hslot; - u8 ifidx; state = brcmf_skbcb(skb)->state; entry = brcmf_skbcb(skb)->mac; @@ -1630,17 +1624,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, } else { hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); - /* remove header first */ - rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); - if (rc) { - brcmf_err("header removal failed\n"); - /* free the hanger slot */ - brcmf_fws_hanger_poppkt(&fws->hanger, hslot, - &pktout, true); - rc = -EINVAL; - goto fail; - } - /* delay-q packets are going to delay-q */ pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo, skb); @@ -1661,8 +1644,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, rc = -ENOENT; } - -fail: if (rc) { brcmf_fws_bustxfail(fws, skb); fws->stats.rollback_failed++; @@ -1732,6 +1713,7 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, struct brcmf_fws_mac_descriptor *entry; struct brcmf_bus *bus = fws->drvr->bus_if; int rc; + u8 ifidx; entry = skcb->mac; if (IS_ERR(entry)) @@ -1746,8 +1728,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, skcb->htod); rc = brcmf_bus_txdata(bus, skb); - if (rc < 0) + if (rc < 0) { + brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); goto rollback; + } entry->seq[fifo]++; fws->stats.pkt2bus++; -- GitLab From eb2410cdd92e5232e6b7e8d95cb60b9e0cea434d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:18:00 +0200 Subject: [PATCH 0969/2900] brcmfmac: Fix endless loop when brcmf_fws_commit_skb fails. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 6255312d5986..881c0b2f7412 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1879,7 +1879,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) brcmf_fws_return_credits(fws, fifo, 1); break; } - brcmf_fws_commit_skb(fws, fifo, skb); + if (brcmf_fws_commit_skb(fws, fifo, skb)) + break; if (fws->bus_flow_blocked) break; } -- GitLab From 8c5140f63a7aa01e6836fc9eace201b0a3f1475f Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:18:01 +0200 Subject: [PATCH 0970/2900] brcmfmac: Simplify counting transit count. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 881c0b2f7412..dc40eec8a5cc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -357,7 +357,6 @@ struct brcmf_fws_mac_descriptor { u8 seq[BRCMF_FWS_FIFO_COUNT]; struct pktq psq; int transit_count; - int suppress_count; int suppr_transit_count; bool send_tim_signal; u8 traffic_pending_bmp; @@ -1100,8 +1099,6 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, /* update the sk_buff state */ brcmf_skbcb(p)->state = state; - if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) - entry->suppress_count++; /* * A packet has been pushed so update traffic @@ -1141,9 +1138,8 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out); if (p == NULL) { if (entry->suppressed) { - if (entry->suppr_transit_count > - entry->suppress_count) - return NULL; + if (entry->suppr_transit_count) + continue; entry->suppressed = false; p = brcmu_pktq_mdeq(&entry->psq, 1 << (fifo * 2), &prec_out); @@ -1194,12 +1190,9 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, /* this packet was suppressed */ if (!entry->suppressed) { entry->suppressed = true; - entry->suppress_count = brcmu_pktq_mlen(&entry->psq, - 1 << (fifo * 2 + 1)); entry->suppr_transit_count = entry->transit_count; - brcmf_dbg(DATA, "suppress %s: supp_cnt %d transit %d\n", - entry->name, entry->suppress_count, - entry->transit_count); + brcmf_dbg(DATA, "suppress %s: transit %d\n", + entry->name, entry->transit_count); } entry->generation = genbit; @@ -1218,7 +1211,6 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, * wlfc cleanup */ brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); - entry->suppress_count++; } return ret; @@ -1263,6 +1255,9 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, brcmu_pkt_buf_free_skb(skb); return -EINVAL; } + entry->transit_count--; + if (entry->suppressed && entry->suppr_transit_count) + entry->suppr_transit_count--; brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, skcb->htod); @@ -1276,13 +1271,9 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, if (!remove_from_hanger) ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); - if (remove_from_hanger || ret) { - entry->transit_count--; - if (entry->suppressed) - entry->suppr_transit_count--; - + if (remove_from_hanger || ret) brcmf_txfinalize(fws->drvr, skb, true); - } + return 0; } @@ -1579,7 +1570,6 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, free_ctr = entry->seq[fifo]; brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); - entry->transit_count++; rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); if (rc) brcmf_err("hanger push failed: rc=%d\n", rc); @@ -1733,6 +1723,9 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, goto rollback; } + entry->transit_count++; + if (entry->suppressed) + entry->suppr_transit_count++; entry->seq[fifo]++; fws->stats.pkt2bus++; if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { -- GitLab From cf3a6872b981037e29517b3e61e199bde14abc65 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:18:02 +0200 Subject: [PATCH 0971/2900] brcmfmac: fix send_pkts statistic counter in firmware-signalling The statistic counter send_pkts was wrongly counted conditionally. Correcting the mistake. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index dc40eec8a5cc..04aa4b286611 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1728,10 +1728,9 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, entry->suppr_transit_count++; entry->seq[fifo]++; fws->stats.pkt2bus++; - if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) { - fws->stats.send_pkts[fifo]++; + fws->stats.send_pkts[fifo]++; + if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) fws->stats.fifo_credits_sent[fifo]++; - } return rc; -- GitLab From ea0737d6e24b44b632e9094108bb987b0338ea74 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:18:05 +0200 Subject: [PATCH 0972/2900] brcmfmac: add trace event for capturing BDC header The BDC header contains PropTx TLV signals that are useful to capture for debugging. This event captures the header and tlv's in binary form. This can be post-processed using trace-cmd plugin. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 3 +++ .../wireless/brcm80211/brcmfmac/tracepoint.h | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index 59c77aa3b959..dd85401063cb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -30,6 +30,7 @@ #include "dhd_bus.h" #include "fwsignal.h" #include "dhd_dbg.h" +#include "tracepoint.h" struct brcmf_proto_cdc_dcmd { __le32 cmd; /* dongle command value */ @@ -292,6 +293,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, h->flags2 = 0; h->data_offset = offset; BDC_SET_IF_IDX(h, ifidx); + trace_brcmf_bdchdr(pktbuf->data); } int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, @@ -309,6 +311,7 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, return -EBADE; } + trace_brcmf_bdchdr(pktbuf->data); h = (struct brcmf_proto_bdc_header *)(pktbuf->data); *ifidx = BDC_GET_IF_IDX(h); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h index 9df1f7a681e0..bc2917112899 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h @@ -87,6 +87,27 @@ TRACE_EVENT(brcmf_hexdump, TP_printk("hexdump [length=%lu]", __entry->len) ); +TRACE_EVENT(brcmf_bdchdr, + TP_PROTO(void *data), + TP_ARGS(data), + TP_STRUCT__entry( + __field(u8, flags) + __field(u8, prio) + __field(u8, flags2) + __field(u32, siglen) + __dynamic_array(u8, signal, *((u8 *)data + 3) * 4) + ), + TP_fast_assign( + __entry->flags = *(u8 *)data; + __entry->prio = *((u8 *)data + 1); + __entry->flags2 = *((u8 *)data + 2); + __entry->siglen = *((u8 *)data + 3) * 4; + memcpy(__get_dynamic_array(signal), + (u8 *)data + 4, __entry->siglen); + ), + TP_printk("bdc: prio=%d siglen=%d", __entry->prio, __entry->siglen) +); + #ifdef CONFIG_BRCM_TRACING #undef TRACE_INCLUDE_PATH -- GitLab From 672774f124dd07b2aaa1c8fdd56d98d786434fbb Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:18:06 +0200 Subject: [PATCH 0973/2900] brcmfmac: increment hard_header_len instead of overriding In brcmf_net_attach() the hard_header_len is set to sum of ETH_HLEN and the headroom needed by the bus interface. Better use increment instead as hard_header_len is already initialized upon alloc_netdev(). Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 63cadf63ccfe..29828865ed69 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -640,7 +640,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) /* set appropriate operations */ ndev->netdev_ops = &brcmf_netdev_ops_pri; - ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; + ndev->hard_header_len += drvr->hdrlen; ndev->ethtool_ops = &brcmf_ethtool_ops; drvr->rxsz = ndev->mtu + ndev->hard_header_len + -- GitLab From c7773fc1ef55b7d1ed44a27900b86dc28351dec4 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:49:32 +0200 Subject: [PATCH 0974/2900] brcmfmac: Sent TIM information in case of data available. When data is available and fw signalling is enabled then TIM information should be sent to firmware. If it can piggy back on existing packet then do that otherwise create dummy packet to get information out. Cc: Dan Carpenter Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 167 +++++++++++------- 1 file changed, 103 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 04aa4b286611..ff920601898c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -157,11 +157,13 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver. * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue. * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware. + * @BRCMF_FWS_SKBSTATE_TIM: allocated for TIM update info. */ enum brcmf_fws_skb_state { BRCMF_FWS_SKBSTATE_NEW, BRCMF_FWS_SKBSTATE_DELAYED, - BRCMF_FWS_SKBSTATE_SUPPRESSED + BRCMF_FWS_SKBSTATE_SUPPRESSED, + BRCMF_FWS_SKBSTATE_TIM }; /** @@ -278,6 +280,7 @@ struct brcmf_skbuff_cb { /** * enum brcmf_fws_fifo - fifo indices used by dongle firmware. * + * @BRCMF_FWS_FIFO_FIRST: first fifo, ie. background. * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic. * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic. * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic. @@ -287,7 +290,8 @@ struct brcmf_skbuff_cb { * @BRCMF_FWS_FIFO_COUNT: number of fifos. */ enum brcmf_fws_fifo { - BRCMF_FWS_FIFO_AC_BK, + BRCMF_FWS_FIFO_FIRST, + BRCMF_FWS_FIFO_AC_BK = BRCMF_FWS_FIFO_FIRST, BRCMF_FWS_FIFO_AC_BE, BRCMF_FWS_FIFO_AC_VI, BRCMF_FWS_FIFO_AC_VO, @@ -783,22 +787,95 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); } -static void brcmf_fws_tim_update(struct brcmf_fws_info *ctx, - struct brcmf_fws_mac_descriptor *entry, - int prec) +static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) { - if (entry->state == BRCMF_FWS_STATE_CLOSE) { - /* check delayedQ and suppressQ in one call using bitmap */ - if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) - entry->traffic_pending_bmp = - entry->traffic_pending_bmp & ~NBITVAL(prec); - else - entry->traffic_pending_bmp = - entry->traffic_pending_bmp | NBITVAL(prec); + struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; + u8 *wlh; + u16 data_offset = 0; + u8 fillers; + __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); + + brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u (%u), pkttag=0x%08X, hslot=%d\n", + entry->ea, entry->interface_id, + brcmf_skb_if_flags_get_field(skb, INDEX), + le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff); + if (entry->send_tim_signal) + data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; + + /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ + data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; + fillers = round_up(data_offset, 4) - data_offset; + data_offset += fillers; + + skb_push(skb, data_offset); + wlh = skb->data; + + wlh[0] = BRCMF_FWS_TYPE_PKTTAG; + wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; + memcpy(&wlh[2], &pkttag, sizeof(pkttag)); + wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; + + if (entry->send_tim_signal) { + entry->send_tim_signal = 0; + wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; + wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; + wlh[2] = entry->mac_handle; + wlh[3] = entry->traffic_pending_bmp; + brcmf_dbg(TRACE, "adding TIM info: %02X:%02X:%02X:%02X\n", + wlh[0], wlh[1], wlh[2], wlh[3]); + wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; + entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; } - /* request a TIM update to firmware at the next piggyback opportunity */ + if (fillers) + memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); + + brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX), + data_offset >> 2, skb); + return 0; +} + +static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, + struct brcmf_fws_mac_descriptor *entry, + int prec, bool send_immediately) +{ + struct sk_buff *skb; + struct brcmf_bus *bus; + struct brcmf_skbuff_cb *skcb; + s32 err; + u32 len; + + /* check delayedQ and suppressQ in one call using bitmap */ + if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) + entry->traffic_pending_bmp &= ~NBITVAL(prec); + else + entry->traffic_pending_bmp |= NBITVAL(prec); + + entry->send_tim_signal = false; if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) entry->send_tim_signal = true; + if (send_immediately && entry->send_tim_signal && + entry->state == BRCMF_FWS_STATE_CLOSE) { + /* create a dummy packet and sent that. The traffic */ + /* bitmap info will automatically be attached to that packet */ + len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 + + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 + + 4 + fws->drvr->hdrlen; + skb = brcmu_pkt_buf_get_skb(len); + if (skb == NULL) + return false; + skb_pull(skb, len); + skcb = brcmf_skbcb(skb); + skcb->mac = entry; + skcb->state = BRCMF_FWS_SKBSTATE_TIM; + bus = fws->drvr->bus_if; + err = brcmf_fws_hdrpush(fws, skb); + if (err == 0) + err = brcmf_bus_txdata(bus, skb); + if (err) + brcmu_pkt_buf_free_skb(skb); + return true; + } + return false; } static void @@ -886,7 +963,6 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, { struct brcmf_fws_mac_descriptor *entry; u8 mac_handle; - int i; mac_handle = data[0]; entry = &fws->desc.nodes[mac_handle & 0x1F]; @@ -894,18 +970,18 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, fws->stats.mac_ps_update_failed++; return -ESRCH; } - - brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, - entry->name); - /* a state update should wipe old credits? */ + /* a state update should wipe old credits */ entry->requested_credit = 0; + entry->requested_packet = 0; if (type == BRCMF_FWS_TYPE_MAC_OPEN) { entry->state = BRCMF_FWS_STATE_OPEN; return BRCMF_FWS_RET_OK_SCHEDULE; } else { entry->state = BRCMF_FWS_STATE_CLOSE; - for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++) - brcmf_fws_tim_update(fws, entry, i); + brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false); + brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false); + brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false); + brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true); } return BRCMF_FWS_RET_OK_NOSCHEDULE; } @@ -1104,7 +1180,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, * A packet has been pushed so update traffic * availability bitmap, if applicable */ - brcmf_fws_tim_update(fws, entry, fifo); + brcmf_fws_tim_update(fws, entry, fifo, true); brcmf_fws_flow_control_check(fws, &entry->psq, brcmf_skb_if_flags_get_field(p, INDEX)); return 0; @@ -1160,7 +1236,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) * A packet has been picked up, update traffic * availability bitmap, if applicable */ - brcmf_fws_tim_update(fws, entry, fifo); + brcmf_fws_tim_update(fws, entry, fifo, false); /* * decrement total enqueued fifo packets and @@ -1495,47 +1571,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, return 0; } -static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) -{ - struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; - u8 *wlh; - u16 data_offset = 0; - u8 fillers; - __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); - - if (entry->send_tim_signal) - data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; - - /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ - data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN; - fillers = round_up(data_offset, 4) - data_offset; - data_offset += fillers; - - skb_push(skb, data_offset); - wlh = skb->data; - - wlh[0] = BRCMF_FWS_TYPE_PKTTAG; - wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN; - memcpy(&wlh[2], &pkttag, sizeof(pkttag)); - wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2; - - if (entry->send_tim_signal) { - entry->send_tim_signal = 0; - wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; - wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; - wlh[2] = entry->mac_handle; - wlh[3] = entry->traffic_pending_bmp; - wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; - entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; - } - if (fillers) - memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers); - - brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX), - data_offset >> 2, skb); - return 0; -} - static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, struct sk_buff *p) { @@ -1990,6 +2025,10 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) ulong flags; int fifo; + if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) { + brcmu_pkt_buf_free_skb(skb); + return; + } brcmf_fws_lock(fws->drvr, flags); brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); -- GitLab From ee06fcad742ab52a1ba67ba734fee6a98af51621 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Fri, 7 Jun 2013 11:03:00 +0200 Subject: [PATCH 0975/2900] brcmfmac: free primary net_device when brcmf_bus_start() fails When initialization within brcmf_bus_start() fails on steps before the brcmf_net_attach() the net_device for the primary interface needs to be freed. This patch resolves a panic during kernel boot as reported by Stephen Warren. ref.: http://mid.gmane.org/51AD1F22.2080004@wwwdotorg.org Tested-by: Stephen Warren Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 29828865ed69..8c402e7b97eb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -941,6 +941,10 @@ int brcmf_bus_start(struct device *dev) brcmf_fws_del_interface(ifp); brcmf_fws_deinit(drvr); } + if (drvr->iflist[0]) { + free_netdev(ifp->ndev); + drvr->iflist[0] = NULL; + } if (p2p_ifp) { free_netdev(p2p_ifp->ndev); drvr->iflist[1] = NULL; -- GitLab From f2c7a793374be88eb680a5dfcf400b4cd97f29d4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 7 Jun 2013 18:12:00 +0200 Subject: [PATCH 0976/2900] ath9k: add support for IEEE80211_TX_CTL_PS_RESPONSE Use the UAPSD hardware queue to get PS-Poll responses out as fast as possible and without backoff. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 2 ++ drivers/net/wireless/ath/ath9k/xmit.c | 43 ++++++++++++++++---------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 18fcee4e9d68..4f798276802c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -296,6 +296,7 @@ struct ath_tx { struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; struct ath_descdma txdma; struct ath_txq *txq_map[IEEE80211_NUM_ACS]; + struct ath_txq *uapsdq; u32 txq_max_pending[IEEE80211_NUM_ACS]; u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32]; }; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 389ee1b59976..d65ee6e6437b 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -432,6 +432,8 @@ static int ath9k_init_queues(struct ath_softc *sc) sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); + sc->tx.uapsdq = ath_txq_setup(sc, ATH9K_TX_QUEUE_UAPSD, 0); + for (i = 0; i < IEEE80211_NUM_ACS; i++) { sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); sc->tx.txq_map[i]->mac80211_qnum = i; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1c9b1bac8b0d..3931bd82629d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1681,8 +1681,9 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } } -static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct sk_buff *skb, struct ath_tx_control *txctl) +static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, struct sk_buff *skb, + struct ath_tx_control *txctl) { struct ath_frame_info *fi = get_frame_info(skb); struct list_head bf_head; @@ -1695,21 +1696,22 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, * - seqno is not within block-ack window * - h/w queue depth exceeds low water mark */ - if (!skb_queue_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || - txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { + if ((!skb_queue_empty(&tid->buf_q) || tid->paused || + !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) || + txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) && + txq != sc->tx.uapsdq) { /* * Add this frame to software queue for scheduling later * for aggregation. */ - TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); + TX_STAT_INC(txq->axq_qnum, a_queued_sw); __skb_queue_tail(&tid->buf_q, skb); if (!txctl->an || !txctl->an->sleeping) - ath_tx_queue_tid(txctl->txq, tid); + ath_tx_queue_tid(txq, tid); return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txq, tid, skb); if (!bf) { ieee80211_free_txskb(sc->hw, skb); return; @@ -1724,10 +1726,10 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); /* Queue to h/w without aggregation */ - TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); + TX_STAT_INC(txq->axq_qnum, a_queued_hw); bf->bf_lastbf = bf; - ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen); - ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false); + ath_tx_fill_desc(sc, bf, txq, fi->framelen); + ath_tx_txqaddbuf(sc, txq, &bf_head, false); } static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, @@ -1935,6 +1937,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, txq->stopped = true; } + if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) { + ath_txq_unlock(sc, txq); + txq = sc->tx.uapsdq; + ath_txq_lock(sc, txq); + } + if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; @@ -1948,11 +1956,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, * Try aggregation if it's a unicast data frame * and the destination is HT capable. */ - ath_tx_send_ampdu(sc, tid, skb, txctl); + ath_tx_send_ampdu(sc, txq, tid, skb, txctl); goto out; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txq, tid, skb); if (!bf) { if (txctl->paprd) dev_kfree_skb_any(skb); @@ -1967,7 +1975,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, bf->bf_state.bfs_paprd_timestamp = jiffies; ath_set_rates(vif, sta, bf); - ath_tx_send_normal(sc, txctl->txq, tid, skb); + ath_tx_send_normal(sc, txq, tid, skb); out: ath_txq_unlock(sc, txq); @@ -2020,7 +2028,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, } spin_unlock_irqrestore(&sc->sc_pm_lock, flags); + __skb_queue_tail(&txq->complete_q, skb); + q = skb_get_queue_mapping(skb); + if (txq == sc->tx.uapsdq) + txq = sc->tx.txq_map[q]; + if (txq == sc->tx.txq_map[q]) { if (WARN_ON(--txq->pending_frames < 0)) txq->pending_frames = 0; @@ -2031,8 +2044,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, txq->stopped = false; } } - - __skb_queue_tail(&txq->complete_q, skb); } static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, -- GitLab From 86a22acfcb40ed9cf4ceee789b45da6a3314ed77 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 7 Jun 2013 18:12:01 +0200 Subject: [PATCH 0977/2900] ath9k: implement support for .release_buffered_frames() This adds support for PS-Poll and U-APSD driver-buffered frames (part of an aggregation session). Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 5 + drivers/net/wireless/ath/ath9k/main.c | 1 + drivers/net/wireless/ath/ath9k/xmit.c | 175 ++++++++++++++++++++----- 3 files changed, 145 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 4f798276802c..bd35a54a3f04 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -354,6 +354,11 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, struct ath_node *an); +void ath9k_release_buffered_frames(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u16 tids, int nframes, + enum ieee80211_frame_release_type reason, + bool more_data); /********/ /* VIFs */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e5b186b04b29..bf61a1c3f14c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2347,6 +2347,7 @@ struct ieee80211_ops ath9k_ops = { .flush = ath9k_flush, .tx_frames_pending = ath9k_tx_frames_pending, .tx_last_beacon = ath9k_tx_last_beacon, + .release_buffered_frames = ath9k_release_buffered_frames, .get_stats = ath9k_get_stats, .set_antenna = ath9k_set_antenna, .get_antenna = ath9k_get_antenna, diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3931bd82629d..6c9ff9c9730f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -518,6 +518,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, !txfail); } else { + if (tx_info->flags & IEEE80211_TX_STATUS_EOSP) { + tx_info->flags &= ~IEEE80211_TX_STATUS_EOSP; + ieee80211_sta_eosp(sta); + } /* retry the un-acked ones */ if (bf->bf_next == NULL && bf_last->bf_stale) { struct ath_buf *tbf; @@ -786,25 +790,20 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, return ndelim; } -static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_q, - int *aggr_len) +static struct ath_buf * +ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) { -#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; - int rl = 0, nframes = 0, ndelim, prev_al = 0; - u16 aggr_limit = 0, al = 0, bpad = 0, - al_delta, h_baw = tid->baw_size / 2; - enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; - struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; struct sk_buff *skb; + struct ath_buf *bf; u16 seqno; - do { + while (1) { skb = skb_peek(&tid->buf_q); + if (!skb) + break; + fi = get_frame_info(skb); bf = fi->bf; if (!fi->bf) @@ -820,10 +819,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, seqno = bf->bf_state.seqno; /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { - status = ATH_AGGR_BAW_CLOSED; + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) break; - } if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { struct ath_tx_status ts = {}; @@ -837,6 +834,40 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, continue; } + bf->bf_next = NULL; + bf->bf_lastbf = bf; + return bf; + } + + return NULL; +} + +static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_q, + int *aggr_len) +{ +#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) + struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; + int rl = 0, nframes = 0, ndelim, prev_al = 0; + u16 aggr_limit = 0, al = 0, bpad = 0, + al_delta, h_baw = tid->baw_size / 2; + enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; + struct ieee80211_tx_info *tx_info; + struct ath_frame_info *fi; + struct sk_buff *skb; + + do { + bf = ath_tx_get_tid_subframe(sc, txq, tid); + if (!bf) { + status = ATH_AGGR_BAW_CLOSED; + break; + } + + skb = bf->bf_mpdu; + fi = get_frame_info(skb); + if (!bf_first) bf_first = bf; @@ -882,7 +913,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, /* link buffers of this frame to the aggregate */ if (!fi->retries) - ath_tx_addto_baw(sc, tid, seqno); + ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); bf->bf_state.ndelim = ndelim; __skb_unlink(skb, &tid->buf_q); @@ -1090,10 +1121,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, int len) { struct ath_hw *ah = sc->sc_ah; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); - struct ath_buf *bf_first = bf; + struct ath_buf *bf_first = NULL; struct ath_tx_info info; - bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR); memset(&info, 0, sizeof(info)); info.is_first = true; @@ -1101,24 +1130,11 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, info.txpower = MAX_RATE_POWER; info.qcu = txq->axq_qnum; - info.flags = ATH9K_TXDESC_INTREQ; - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - info.flags |= ATH9K_TXDESC_NOACK; - if (tx_info->flags & IEEE80211_TX_CTL_LDPC) - info.flags |= ATH9K_TXDESC_LDPC; - - ath_buf_set_rate(sc, bf, &info, len); - - if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) - info.flags |= ATH9K_TXDESC_CLRDMASK; - - if (bf->bf_state.bfs_paprd) - info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S; - - while (bf) { struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ath_frame_info *fi = get_frame_info(skb); + bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR); info.type = get_hw_packet_type(skb); if (bf->bf_next) @@ -1126,6 +1142,26 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, else info.link = 0; + if (!bf_first) { + bf_first = bf; + + info.flags = ATH9K_TXDESC_INTREQ; + if ((tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) || + txq == sc->tx.uapsdq) + info.flags |= ATH9K_TXDESC_CLRDMASK; + + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) + info.flags |= ATH9K_TXDESC_NOACK; + if (tx_info->flags & IEEE80211_TX_CTL_LDPC) + info.flags |= ATH9K_TXDESC_LDPC; + + if (bf->bf_state.bfs_paprd) + info.flags |= (u32) bf->bf_state.bfs_paprd << + ATH9K_TXDESC_PAPRD_S; + + ath_buf_set_rate(sc, bf, &info, len); + } + info.buf_addr[0] = bf->bf_buf_addr; info.buf_len[0] = skb->len; info.pkt_len = fi->framelen; @@ -1135,7 +1171,7 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, if (aggr) { if (bf == bf_first) info.aggr = AGGR_BUF_FIRST; - else if (!bf->bf_next) + else if (bf == bf_first->bf_lastbf) info.aggr = AGGR_BUF_LAST; else info.aggr = AGGR_BUF_MIDDLE; @@ -1144,6 +1180,9 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf, info.aggr_len = len; } + if (bf == bf_first->bf_lastbf) + bf_first = NULL; + ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); bf = bf->bf_next; } @@ -1328,6 +1367,70 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, ath_txq_unlock_complete(sc, txq); } +void ath9k_release_buffered_frames(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u16 tids, int nframes, + enum ieee80211_frame_release_type reason, + bool more_data) +{ + struct ath_softc *sc = hw->priv; + struct ath_node *an = (struct ath_node *)sta->drv_priv; + struct ath_txq *txq = sc->tx.uapsdq; + struct ieee80211_tx_info *info; + struct list_head bf_q; + struct ath_buf *bf_tail = NULL, *bf; + int sent = 0; + int i; + + INIT_LIST_HEAD(&bf_q); + for (i = 0; tids && nframes; i++, tids >>= 1) { + struct ath_atx_tid *tid; + + if (!(tids & 1)) + continue; + + tid = ATH_AN_2_TID(an, i); + if (tid->paused) + continue; + + ath_txq_lock(sc, tid->ac->txq); + while (!skb_queue_empty(&tid->buf_q) && nframes > 0) { + bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); + if (!bf) + break; + + __skb_unlink(bf->bf_mpdu, &tid->buf_q); + list_add_tail(&bf->list, &bf_q); + ath_set_rates(tid->an->vif, tid->an->sta, bf); + ath_tx_addto_baw(sc, tid, bf->bf_state.seqno); + bf->bf_state.bf_type &= ~BUF_AGGR; + if (bf_tail) + bf_tail->bf_next = bf; + + bf_tail = bf; + nframes--; + sent++; + TX_STAT_INC(txq->axq_qnum, a_queued_hw); + + if (skb_queue_empty(&tid->buf_q)) + ieee80211_sta_set_buffered(an->sta, i, false); + } + ath_txq_unlock_complete(sc, tid->ac->txq); + } + + if (list_empty(&bf_q)) + return; + + info = IEEE80211_SKB_CB(bf_tail->bf_mpdu); + info->flags |= IEEE80211_TX_STATUS_EOSP; + + bf = list_first_entry(&bf_q, struct ath_buf, list); + ath_txq_lock(sc, txq); + ath_tx_fill_desc(sc, bf, txq, 0); + ath_tx_txqaddbuf(sc, txq, &bf_q, false); + ath_txq_unlock(sc, txq); +} + /********************/ /* Queue Management */ /********************/ -- GitLab From 59505c02e106ce9388d816799cd64b0405f98f2f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 7 Jun 2013 18:12:02 +0200 Subject: [PATCH 0978/2900] ath9k: limit multicast buffer hardware queue depth The CAB (Content after Beacon) queue is used for beacon-triggered transmission of buffered multicast frames. If lots of multicast frames were buffered and this queue fills up, it drowns out all regular traffic. To limit the damage that buffered traffic can do, try to limit the queued data to becaon_interval / 8. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 + drivers/net/wireless/ath/ath9k/beacon.c | 23 +---- drivers/net/wireless/ath/ath9k/xmit.c | 115 ++++++++++++++++++++---- 3 files changed, 104 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bd35a54a3f04..a6e666bcc0a7 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -344,6 +344,8 @@ int ath_txq_update(struct ath_softc *sc, int qnum, void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl); +void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct sk_buff *skb); void ath_tx_tasklet(struct ath_softc *sc); void ath_tx_edma_tasklet(struct ath_softc *sc); int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index fd1eebab8647..1a17732bb089 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -108,23 +108,6 @@ static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif, ath9k_hw_set_txdesc(ah, bf->bf_desc, &info); } -static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_softc *sc = hw->priv; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_tx_control txctl; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - txctl.txq = sc->beacon.cabq; - - ath_dbg(common, XMIT, "transmitting CABQ packet, skb: %p\n", skb); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_dbg(common, XMIT, "CABQ TX failed\n"); - ieee80211_free_txskb(hw, skb); - } -} - static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -206,10 +189,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx); - while (skb) { - ath9k_tx_cabq(hw, skb); - skb = ieee80211_get_buffered_bc(hw, vif); - } + if (skb) + ath_tx_cabq(hw, vif, skb); return bf; } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 6c9ff9c9730f..7e19d9b5214e 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1970,22 +1970,16 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, return bf; } -/* Upon failure caller should free skb */ -int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath_tx_control *txctl) +static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath_tx_control *txctl) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_sta *sta = txctl->sta; struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; - struct ath_txq *txq = txctl->txq; - struct ath_atx_tid *tid = NULL; - struct ath_buf *bf; - int padpos, padsize; int frmlen = skb->len + FCS_LEN; - u8 tidno; - int q; + int padpos, padsize; /* NOTE: sta can be NULL according to net/mac80211.h */ if (sta) @@ -2006,6 +2000,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); } + if ((vif && vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_AP_VLAN) || + !ieee80211_is_data(hdr->frame_control)) + info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; + /* Add the padding after the header if this is not already done */ padpos = ieee80211_hdrlen(hdr->frame_control); padsize = padpos & 3; @@ -2015,16 +2014,34 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); - hdr = (struct ieee80211_hdr *) skb->data; } - if ((vif && vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_AP_VLAN) || - !ieee80211_is_data(hdr->frame_control)) - info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - setup_frame_info(hw, sta, skb, frmlen); + return 0; +} + +/* Upon failure caller should free skb */ +int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath_tx_control *txctl) +{ + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = txctl->sta; + struct ieee80211_vif *vif = info->control.vif; + struct ath_softc *sc = hw->priv; + struct ath_txq *txq = txctl->txq; + struct ath_atx_tid *tid = NULL; + struct ath_buf *bf; + u8 tidno; + int q; + int ret; + + ret = ath_tx_prepare(hw, skb, txctl); + if (ret) + return ret; + + hdr = (struct ieee80211_hdr *) skb->data; /* * At this point, the vif, hw_key and sta pointers in the tx control * info are no longer valid (overwritten by the ath_frame_info data. @@ -2086,6 +2103,74 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, return 0; } +void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ath_softc *sc = hw->priv; + struct ath_tx_control txctl = { + .txq = sc->beacon.cabq + }; + struct ath_tx_info info = {}; + struct ieee80211_hdr *hdr; + struct ath_buf *bf_tail = NULL; + struct ath_buf *bf; + LIST_HEAD(bf_q); + int duration = 0; + int max_duration; + + max_duration = + sc->cur_beacon_conf.beacon_interval * 1000 * + sc->cur_beacon_conf.dtim_period / ATH_BCBUF; + + do { + struct ath_frame_info *fi = get_frame_info(skb); + + if (ath_tx_prepare(hw, skb, &txctl)) + break; + + bf = ath_tx_setup_buffer(sc, txctl.txq, NULL, skb); + if (!bf) + break; + + bf->bf_lastbf = bf; + ath_set_rates(vif, NULL, bf); + ath_buf_set_rate(sc, bf, &info, fi->framelen); + duration += info.rates[0].PktDuration; + if (bf_tail) + bf_tail->bf_next = bf; + + list_add_tail(&bf->list, &bf_q); + bf_tail = bf; + skb = NULL; + + if (duration > max_duration) + break; + + skb = ieee80211_get_buffered_bc(hw, vif); + } while(skb); + + if (skb) + ieee80211_free_txskb(hw, skb); + + if (list_empty(&bf_q)) + return; + + bf = list_first_entry(&bf_q, struct ath_buf, list); + hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data; + + if (hdr->frame_control & IEEE80211_FCTL_MOREDATA) { + hdr->frame_control &= ~IEEE80211_FCTL_MOREDATA; + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, + sizeof(*hdr), DMA_TO_DEVICE); + } + + ath_txq_lock(sc, txctl.txq); + ath_tx_fill_desc(sc, bf, txctl.txq, 0); + ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false); + TX_STAT_INC(txctl.txq->axq_qnum, queued); + ath_txq_unlock(sc, txctl.txq); +} + /*****************/ /* TX Completion */ /*****************/ -- GitLab From 8b5c7f6c2b16a31b9f0fc4dba72524a7028e5e43 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:50 +0300 Subject: [PATCH 0979/2900] wil6210: fix timeout for start_pcp It may take up to 3500ms for the FW to start AP/PCP. Increase accordingly, adding some safety margin. Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/wmi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 527ffb543821..aeb64f21273a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -739,8 +739,12 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan) if (!wil->secure_pcp) cmd.disable_sec = 1; + /* + * Processing time may be huge, in case of secure AP it takes about + * 3500ms for FW to start AP + */ rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd), - WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 100); + WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000); if (rc) return rc; -- GitLab From af6b48db9239922391952c09a973c00fde235e92 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:51 +0300 Subject: [PATCH 0980/2900] wil6210: map more FW memory map card's back-door debug data Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/wmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index aeb64f21273a..cfcaf7bf4da6 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -75,10 +75,11 @@ static const struct { {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ {0x880000, 0x88a000, 0x880000}, /* various RGF */ - {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ + {0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */ /* * 920000..930000 ucode code RAM * 930000..932000 ucode data RAM + * 932000..949000 back-door debug data */ }; -- GitLab From f27dbf78c669902adcf45a9561d22f15362a6907 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:52 +0300 Subject: [PATCH 0981/2900] wil6210: improve frame type reporting Report FC from the frame itself, as auxiliary information includes only frame subtype. This is preparation for future changes, when DMG beacon (extension frame) may be reported through wmi_evt_rx_mgmt() Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/wmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index cfcaf7bf4da6..ac4d26b34097 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -315,8 +315,8 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) wil_dbg_wmi(wil, "MGMT: channel %d MCS %d SNR %d\n", data->info.channel, data->info.mcs, data->info.snr); - wil_dbg_wmi(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, - le16_to_cpu(data->info.stype)); + wil_dbg_wmi(wil, "status 0x%04x len %d fc 0x%04x\n", d_status, d_len, + le16_to_cpu(fc)); wil_dbg_wmi(wil, "qid %d mid %d cid %d\n", data->info.qid, data->info.mid, data->info.cid); -- GitLab From 92646c9f1f8fa2a31a3c12b026c2a8cd0e168341 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:53 +0300 Subject: [PATCH 0982/2900] wil6210: Derive IE's for AP When starting secure AP, in some cases wpa_s provides probe template but not probe/assoc IE's. In this case, derive missing IE's from probe. Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/cfg80211.c | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 4eb05d0818c3..189c3078ef7d 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -402,6 +402,30 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy, return 0; } +static int wil_fix_bcon(struct wil6210_priv *wil, + struct cfg80211_beacon_data *bcon) +{ + struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp; + size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + int rc = 0; + + if (bcon->probe_resp_len <= hlen) + return 0; + + if (!bcon->proberesp_ies) { + bcon->proberesp_ies = f->u.probe_resp.variable; + bcon->proberesp_ies_len = bcon->probe_resp_len - hlen; + rc = 1; + } + if (!bcon->assocresp_ies) { + bcon->assocresp_ies = f->u.probe_resp.variable; + bcon->assocresp_ies_len = bcon->probe_resp_len - hlen; + rc = 1; + } + + return rc; +} + static int wil_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ap_settings *info) @@ -423,6 +447,9 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, info->ssid, info->ssid_len); + if (wil_fix_bcon(wil, bcon)) + wil_dbg_misc(wil, "Fixed bcon\n"); + rc = wil_reset(wil); if (rc) return rc; -- GitLab From d58db4e49f58152a28dd598ebbec56f1fe92aa80 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:54 +0300 Subject: [PATCH 0983/2900] wil6210: Send EAPOL frames using normal Tx queue No more need for special processing of EAPOL, FW can now send EAPOL frames using normal Tx queue for TID 0 This fixes "schedule while atomic" bug - start_xmit called in softirq context; while WMI mechanism that was used may sleep. Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 20 ++++++------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 - drivers/net/wireless/ath/wil6210/wmi.c | 34 ---------------------- 3 files changed, 9 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 00dffeda983e..e1c492b9dfef 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -768,18 +768,16 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) wil_err(wil, "Xmit in monitor mode not supported\n"); goto drop; } - if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { - rc = wmi_tx_eapol(wil, skb); - } else { - /* find vring */ - vring = wil_find_tx_vring(wil, skb); - if (!vring) { - wil_err(wil, "No Tx VRING available\n"); - goto drop; - } - /* set up vring entry */ - rc = wil_tx_vring(wil, vring, skb); + + /* find vring */ + vring = wil_find_tx_vring(wil, skb); + if (!vring) { + wil_err(wil, "No Tx VRING available\n"); + goto drop; } + /* set up vring entry */ + rc = wil_tx_vring(wil, vring, skb); + switch (rc) { case 0: /* statistics will be updated on the tx_complete */ diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 373cf656f5b0..44fdab51de7e 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -329,7 +329,6 @@ int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); int wmi_set_channel(struct wil6210_priv *wil, int channel); int wmi_get_channel(struct wil6210_priv *wil, int *channel); -int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, const void *mac_addr); int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index ac4d26b34097..dc8059ad4bab 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -839,40 +839,6 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel) return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd)); } -int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) -{ - struct wmi_eapol_tx_cmd *cmd; - struct ethhdr *eth; - u16 eapol_len = skb->len - ETH_HLEN; - void *eapol = skb->data + ETH_HLEN; - uint i; - int rc; - - skb_set_mac_header(skb, 0); - eth = eth_hdr(skb); - wil_dbg_wmi(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { - if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) - goto found_dest; - } - - return -EINVAL; - - found_dest: - /* find out eapol data & len */ - cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); - if (!cmd) - return -EINVAL; - - memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); - cmd->eapol_len = cpu_to_le16(eapol_len); - memcpy(cmd->eapol, eapol, eapol_len); - rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); - kfree(cmd); - - return rc; -} - int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, const void *mac_addr) { -- GitLab From e31b25627f6ddcc0905d552c3a9642b1060657bb Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 9 Jun 2013 09:12:55 +0300 Subject: [PATCH 0984/2900] wil6210: Init Rx vring right after reset at the vring initialisation, memory pool get allocated in the FW. Make it 1-st because FW need this memory pool to precess next commands Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/cfg80211.c | 7 +++++-- drivers/net/wireless/ath/wil6210/main.c | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 189c3078ef7d..61c302a6bdea 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -454,6 +454,11 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) return rc; + /* Rx VRING. */ + rc = wil_rx_init(wil); + if (rc) + return rc; + rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); if (rc) return rc; @@ -482,8 +487,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) return rc; - /* Rx VRING. After MAC and beacon */ - rc = wil_rx_init(wil); netif_carrier_on(ndev); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index c97b864667c5..8cafa456398a 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -295,6 +295,11 @@ static int __wil_up(struct wil6210_priv *wil) if (rc) return rc; + /* Rx VRING. After MAC and beacon */ + rc = wil_rx_init(wil); + if (rc) + return rc; + /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); switch (wdev->iftype) { @@ -356,9 +361,6 @@ static int __wil_up(struct wil6210_priv *wil) return rc; } - /* Rx VRING. After MAC and beacon */ - wil_rx_init(wil); - napi_enable(&wil->napi_rx); napi_enable(&wil->napi_tx); -- GitLab From eb4928cfc6263c3377d049a41830e36d1af15b31 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 9 Jun 2013 13:10:05 +0200 Subject: [PATCH 0985/2900] wil6210: fix name of tracing config option Tracing in wil6210 is activated with WIL6210_TRACING and not with ATH6KL_TRACING, this is used for the ath6kl driver. Rename the config option. Signed-off-by: Hauke Mehrtens Acked-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index 5644ac54facc..ce8c0381825e 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -28,7 +28,7 @@ config WIL6210_ISR_COR such monitoring impossible. Say y unless you debug interrupts -config ATH6KL_TRACING +config WIL6210_TRACING bool "wil6210 tracing support" depends on WIL6210 depends on EVENT_TRACING -- GitLab From 4c895f41a750b3f81bf0890d2730ac6b867357f8 Mon Sep 17 00:00:00 2001 From: Kirshenbaum Erez Date: Sun, 9 Jun 2013 17:35:28 +0300 Subject: [PATCH 0986/2900] wil6210: Fix AP/PCP start flow WMI PCP Start flow should not be handled through: net_device_ops->ndo_open()->wil_up()->__wil_up() because it missing mandatory FW parameters (SSID,Channel,IEs, Security...). Prior to AP starting __wil_up() may be called with iftype set cfg80211_ops->change_virtual_intf(NL80211_IFTYPE_AP or STATION) depend on the application hostapd/wpa_supplicant/iw. there should not be an attempt to start an AP flow, AP/PCP start flow will be started latter by cfg80211_ops->start_ap(). Signed-off-by: Kirshenbaum Erez Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/main.c | 34 ------------------------- 1 file changed, 34 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 8cafa456398a..0a2844c48a60 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -286,10 +286,7 @@ static int __wil_up(struct wil6210_priv *wil) { struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *wdev = wil->wdev; - struct ieee80211_channel *channel = wdev->preset_chandef.chan; int rc; - int bi; - u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); rc = wil_reset(wil); if (rc) @@ -300,32 +297,25 @@ static int __wil_up(struct wil6210_priv *wil) if (rc) return rc; - /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ - wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); switch (wdev->iftype) { case NL80211_IFTYPE_STATION: wil_dbg_misc(wil, "type: STATION\n"); - bi = 0; ndev->type = ARPHRD_ETHER; break; case NL80211_IFTYPE_AP: wil_dbg_misc(wil, "type: AP\n"); - bi = 100; ndev->type = ARPHRD_ETHER; break; case NL80211_IFTYPE_P2P_CLIENT: wil_dbg_misc(wil, "type: P2P_CLIENT\n"); - bi = 0; ndev->type = ARPHRD_ETHER; break; case NL80211_IFTYPE_P2P_GO: wil_dbg_misc(wil, "type: P2P_GO\n"); - bi = 100; ndev->type = ARPHRD_ETHER; break; case NL80211_IFTYPE_MONITOR: wil_dbg_misc(wil, "type: Monitor\n"); - bi = 0; ndev->type = ARPHRD_IEEE80211_RADIOTAP; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ break; @@ -333,33 +323,9 @@ static int __wil_up(struct wil6210_priv *wil) return -EOPNOTSUPP; } - /* Apply profile in the following order: */ - /* SSID and channel for the AP */ - switch (wdev->iftype) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - if (wdev->ssid_len == 0) { - wil_err(wil, "SSID not set\n"); - return -EINVAL; - } - rc = wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); - if (rc) - return rc; - break; - default: - break; - } - /* MAC address - pre-requisite for other commands */ wmi_set_mac_address(wil, ndev->dev_addr); - /* Set up beaconing if required. */ - if (bi > 0) { - rc = wmi_pcp_start(wil, bi, wmi_nettype, - (channel ? channel->hw_value : 0)); - if (rc) - return rc; - } napi_enable(&wil->napi_rx); napi_enable(&wil->napi_tx); -- GitLab From a226c3d96d920ba88a28f463ba77c9693988ff1e Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Sun, 9 Jun 2013 18:51:24 +0200 Subject: [PATCH 0987/2900] ath9k_htc: add STBC TX support All known ar7010+ar* device and current FW support STBC TX. This patch make use of it and suggest to send STBC if peer support it. I use wort "suggest" since currenly we have separate rate controller in FW which will make decision based on rate and hardware. Signed-off-by: Oleksij Rempel Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 +++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0085e643132f..69581031f2cd 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -142,6 +142,7 @@ struct ath9k_htc_target_aggr { #define WLAN_RC_40_FLAG 0x02 #define WLAN_RC_SGI_FLAG 0x04 #define WLAN_RC_HT_FLAG 0x08 +#define ATH_RC_TX_STBC_FLAG 0x20 struct ath9k_htc_rateset { u8 rs_nrates; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 59f64367e8ca..bb0ba9e3e083 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -517,6 +517,9 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv, ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n", tx_streams, rx_streams); + if (tx_streams >= 2) + ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; + if (tx_streams != rx_streams) { ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; ht_info->mcs.tx_params |= ((tx_streams - 1) << diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 34869c2405aa..eaa94feb4333 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -627,6 +627,8 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, trate->rates.ht_rates.rs_nrates = j; caps = WLAN_RC_HT_FLAG; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) + caps |= ATH_RC_TX_STBC_FLAG; if (sta->ht_cap.mcs.rx_mask[1]) caps |= WLAN_RC_DS_FLAG; if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && -- GitLab From 693026ef2e751fd94d2e6c71028e68343cc875d5 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 9 Jun 2013 18:53:58 +0200 Subject: [PATCH 0988/2900] b43: ensue that BCMA is "y" when B43 is "y" When b43 gets build into the kernel and it should use bcma we have to ensure that bcma was also build into the kernel and not as a module. In this patch this is also done for SSB, although you can not build b43 without ssb support for now. This fixes a build problem reported by Randy Dunlap in 5187EB95.2060605@infradead.org Reported-By: Randy Dunlap Cc: Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 078e6f3477a9..13f91ac9499e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -28,7 +28,7 @@ config B43 config B43_BCMA bool "Support for BCMA bus" - depends on B43 && BCMA + depends on B43 && (BCMA = y || BCMA = B43) default y config B43_BCMA_EXTRA @@ -39,7 +39,7 @@ config B43_BCMA_EXTRA config B43_SSB bool - depends on B43 && SSB + depends on B43 && (SSB = y || SSB = B43) default y # Auto-select SSB PCI-HOST support, if possible -- GitLab From d186899fa55ae773ae26cf57aa274c50de4c508c Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 9 Jun 2013 18:59:42 +0200 Subject: [PATCH 0989/2900] bcma: activate PCI host option by default Most users are using bcma with a PCIe card, activate support for this by default. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 8b4221cfd118..380a2003231e 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig @@ -26,6 +26,7 @@ config BCMA_HOST_PCI_POSSIBLE config BCMA_HOST_PCI bool "Support for BCMA on PCI-host bus" depends on BCMA_HOST_PCI_POSSIBLE + default y config BCMA_DRIVER_PCI_HOSTMODE bool "Driver for PCI core working in hostmode" -- GitLab From 6b692f3b66e4a70dff73b3cdc60f7e6d6823300a Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 9 Jun 2013 18:59:43 +0200 Subject: [PATCH 0990/2900] b43: activate N-PHY and HT-PHY support by default N-PHY and HT-PHY support is more or less stable and should be activated by default. Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 13f91ac9499e..3f21e0ba39ba 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -111,6 +111,7 @@ config B43_PIO config B43_PHY_N bool "Support for 802.11n (N-PHY) devices" depends on B43 + default y ---help--- Support for the N-PHY. @@ -132,6 +133,7 @@ config B43_PHY_LP config B43_PHY_HT bool "Support for HT-PHY (high throughput) devices" depends on B43 && B43_BCMA + default y ---help--- Support for the HT-PHY. -- GitLab From 30d5b709da23f4ab9836c7f66d2d2e780a69cf12 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 10 Jun 2013 13:49:38 +0530 Subject: [PATCH 0991/2900] ath9k_hw: Assign default xlna config for AR9485 For AR9485 boards with XLNA, the default gpio config is not set correctly, fix this. Cc: stable@vger.kernel.org Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 8 ++++++-- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index e6b92ff265fd..25b8bbbe74fe 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3563,14 +3563,18 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { struct ath9k_hw_capabilities *pCap = &ah->caps; int chain; - u32 regval; + u32 regval, value; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, AR_PHY_SWITCH_CHAIN_2, }; - u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); + if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) + ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485, + AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); + + value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index e71774196c01..5013c731f9f6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -351,6 +351,8 @@ #define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118 +#define AR9300_EXT_LNA_CTL_GPIO_AR9485 9 + /* * AGC Field Definitions */ -- GitLab From 696df78509d1f81b651dd98ecdc1aecab616db6b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 10 Jun 2013 13:49:39 +0530 Subject: [PATCH 0992/2900] ath9k: Fix noisefloor calibration The commits, "ath9k: Fix regression in channelwidth switch at the same channel" "ath9k: Fix invalid noisefloor reading due to channel update" attempted to fix noisefloor calibration when a channel switch happens due to HT20/HT40 bandwidth change. This is causing invalid readings resulting in messages like: "ath: phy16: NF[0] (-45) > MAX (-95), correcting to MAX". This results in an incorrect noise being used initially for reporting the signal level of received packets, until NF calibration is done and the history buffer is updated via the ANI timer, which happens much later. When a bandwidth change happens, it is appropriate to reset the internal history data for the channel. Do this correctly in the reset() routine by checking the "chanmode" variable. Cc: stable@vger.kernel.org Cc: Rajkumar Manoharan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 3 ++- drivers/net/wireless/ath/ath9k/main.c | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index d813ab8104d6..ca9d9cd14ddb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1870,7 +1870,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ah->caldata = caldata; if (caldata && (chan->channel != caldata->channel || - chan->channelFlags != caldata->channelFlags)) { + chan->channelFlags != caldata->channelFlags || + chan->chanmode != caldata->chanmode)) { /* Operating channel changed, reset channel calibration data */ memset(caldata, 0, sizeof(*caldata)); ath9k_init_nfcal_hist_buffer(ah, chan); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index bf61a1c3f14c..1737a3e33685 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1210,13 +1210,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath_update_survey_stats(sc); spin_unlock_irqrestore(&common->cc_lock, flags); - /* - * Preserve the current channel values, before updating - * the same channel - */ - if (ah->curchan && (old_pos == pos)) - ath9k_hw_getnf(ah, ah->curchan); - ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], curchan, channel_type); -- GitLab From d3bcb7b24bbf09fde8405770e676fe0c11c79662 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 10 Jun 2013 13:49:40 +0530 Subject: [PATCH 0993/2900] ath9k: Do not assign noise for NULL caldata ah->noise is maintained globally and not per-channel. This is updated in the reset() routine after the NF history has been filled for the *current channel*, just before switching to the new channel. There is no need to do it inside getnf(), since ah->noise must contain a value for the new channel. Cc: stable@vger.kernel.org Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/calib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 7304e7585009..5e8219a91e25 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -387,7 +387,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) if (!caldata) { chan->noisefloor = nf; - ah->noise = ath9k_hw_getchan_noise(ah, chan); return false; } -- GitLab From 0967e01e8e713ed2982fb4eba8ba13794e9a6e89 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Tue, 11 Jun 2013 15:10:31 +0200 Subject: [PATCH 0994/2900] ath5k: make use of the new rate control API This patch enabels ath5k to use the new rate table to lookup each mrr rate and retry information per packet. Signed-off-by: Benjamin Vahl Signed-off-by: Thomas Huehn Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 79 +++++++++++++++---- drivers/net/wireless/ath/ath5k/base.h | 14 ++-- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7f702fe3ecc2..ce67ab791eae 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -60,6 +60,7 @@ #include +#include #include "base.h" #include "reg.h" #include "debug.h" @@ -666,9 +667,46 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) return htype; } +static struct ieee80211_rate * +ath5k_get_rate(const struct ieee80211_hw *hw, + const struct ieee80211_tx_info *info, + struct ath5k_buf *bf, int idx) +{ + /* + * convert a ieee80211_tx_rate RC-table entry to + * the respective ieee80211_rate struct + */ + if (bf->rates[idx].idx < 0) { + return NULL; + } + + return &hw->wiphy->bands[info->band]->bitrates[ bf->rates[idx].idx ]; +} + +static u16 +ath5k_get_rate_hw_value(const struct ieee80211_hw *hw, + const struct ieee80211_tx_info *info, + struct ath5k_buf *bf, int idx) +{ + struct ieee80211_rate *rate; + u16 hw_rate; + u8 rc_flags; + + rate = ath5k_get_rate(hw, info, bf, idx); + if (!rate) + return 0; + + rc_flags = bf->rates[idx].flags; + hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? + rate->hw_value_short : rate->hw_value; + + return hw_rate; +} + static int ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, - struct ath5k_txq *txq, int padsize) + struct ath5k_txq *txq, int padsize, + struct ieee80211_tx_control *control) { struct ath5k_desc *ds = bf->desc; struct sk_buff *skb = bf->skb; @@ -688,7 +726,11 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, bf->skbaddr = dma_map_single(ah->dev, skb->data, skb->len, DMA_TO_DEVICE); - rate = ieee80211_get_tx_rate(ah->hw, info); + ieee80211_get_tx_rates(info->control.vif, (control) ? control->sta : NULL, skb, bf->rates, + ARRAY_SIZE(bf->rates)); + + rate = ath5k_get_rate(ah->hw, info, bf, 0); + if (!rate) { ret = -EINVAL; goto err_unmap; @@ -698,8 +740,8 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, flags |= AR5K_TXDESC_NOACK; rc_flags = info->control.rates[0].flags; - hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? - rate->hw_value_short : rate->hw_value; + + hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0); pktlen = skb->len; @@ -722,12 +764,13 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, duration = le16_to_cpu(ieee80211_ctstoself_duration(ah->hw, info->control.vif, pktlen, info)); } + ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), padsize, get_hw_packet_type(skb), (ah->ah_txpower.txp_requested * 2), hw_rate, - info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, + bf->rates[0].count, keyidx, ah->ah_tx_ant, flags, cts_rate, duration); if (ret) goto err_unmap; @@ -736,13 +779,15 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, if (ah->ah_capabilities.cap_has_mrr_support) { memset(mrr_rate, 0, sizeof(mrr_rate)); memset(mrr_tries, 0, sizeof(mrr_tries)); + for (i = 0; i < 3; i++) { - rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); + + rate = ath5k_get_rate(ah->hw, info, bf, i); if (!rate) break; - mrr_rate[i] = rate->hw_value; - mrr_tries[i] = info->control.rates[i + 1].count; + mrr_rate[i] = ath5k_get_rate_hw_value(ah->hw, info, bf, i); + mrr_tries[i] = bf->rates[i].count; } ath5k_hw_setup_mrr_tx_desc(ah, ds, @@ -1515,7 +1560,7 @@ ath5k_tasklet_rx(unsigned long data) void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath5k_txq *txq) + struct ath5k_txq *txq, struct ieee80211_tx_control *control) { struct ath5k_hw *ah = hw->priv; struct ath5k_buf *bf; @@ -1555,7 +1600,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, bf->skb = skb; - if (ath5k_txbuf_setup(ah, bf, txq, padsize)) { + if (ath5k_txbuf_setup(ah, bf, txq, padsize, control)) { bf->skb = NULL; spin_lock_irqsave(&ah->txbuflock, flags); list_add_tail(&bf->list, &ah->txbuf); @@ -1571,11 +1616,13 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, static void ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, - struct ath5k_txq *txq, struct ath5k_tx_status *ts) + struct ath5k_txq *txq, struct ath5k_tx_status *ts, + struct ath5k_buf *bf) { struct ieee80211_tx_info *info; u8 tries[3]; int i; + int size = 0; ah->stats.tx_all_count++; ah->stats.tx_bytes_count += skb->len; @@ -1587,6 +1634,9 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb, ieee80211_tx_info_clear_status(info); + size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); + memcpy(info->status.rates, bf->rates, size); + for (i = 0; i < ts->ts_final_idx; i++) { struct ieee80211_tx_rate *r = &info->status.rates[i]; @@ -1663,7 +1713,7 @@ ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq) dma_unmap_single(ah->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); - ath5k_tx_frame_completed(ah, skb, txq, &ts); + ath5k_tx_frame_completed(ah, skb, txq, &ts, bf); } /* @@ -1917,7 +1967,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) skb = ieee80211_get_buffered_bc(ah->hw, vif); while (skb) { - ath5k_tx_queue(ah->hw, skb, ah->cabq); + ath5k_tx_queue(ah->hw, skb, ah->cabq, NULL); if (ah->cabq->txq_len >= ah->cabq->txq_max) break; @@ -2442,7 +2492,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_MFP_CAPABLE | - IEEE80211_HW_REPORTS_TX_ACK_STATUS; + IEEE80211_HW_REPORTS_TX_ACK_STATUS | + IEEE80211_HW_SUPPORTS_RC_TABLE; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 6c94c7ff2350..ca9a83ceeee1 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -47,6 +47,7 @@ struct ath5k_hw; struct ath5k_txq; struct ieee80211_channel; struct ath_bus_ops; +struct ieee80211_tx_control; enum nl80211_iftype; enum ath5k_srev_type { @@ -61,11 +62,12 @@ struct ath5k_srev_name { }; struct ath5k_buf { - struct list_head list; - struct ath5k_desc *desc; /* virtual addr of desc */ - dma_addr_t daddr; /* physical addr of desc */ - struct sk_buff *skb; /* skbuff for buf */ - dma_addr_t skbaddr;/* physical addr of skb data */ + struct list_head list; + struct ath5k_desc *desc; /* virtual addr of desc */ + dma_addr_t daddr; /* physical addr of desc */ + struct sk_buff *skb; /* skbuff for buf */ + dma_addr_t skbaddr; /* physical addr of skb data */ + struct ieee80211_tx_rate rates[4]; /* number of multi-rate stages */ }; struct ath5k_vif { @@ -103,7 +105,7 @@ int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan); void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath5k_txq *txq); + struct ath5k_txq *txq, struct ieee80211_tx_control *control); const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 06f86f435711..81b686c6a376 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -66,7 +66,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, return; } - ath5k_tx_queue(hw, skb, &ah->txqs[qnum]); + ath5k_tx_queue(hw, skb, &ah->txqs[qnum], control); } -- GitLab From 42ce8943e14734dd388e6934fff31a11c1adad8f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 12 Jun 2013 16:44:47 +0200 Subject: [PATCH 0995/2900] iwlegacy: small refactoring of il_{stop,wake}_queue Tested-by: Jake Edge Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 4caaf52986a4..67da89b39e11 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -2256,6 +2256,19 @@ il_set_swq_id(struct il_tx_queue *txq, u8 ac, u8 hwq) txq->swq_id = (hwq << 2) | ac; } +static inline void +_il_wake_queue(struct il_priv *il, u8 ac) +{ + if (atomic_dec_return(&il->queue_stop_count[ac]) <= 0) + ieee80211_wake_queue(il->hw, ac); +} + +static inline void +_il_stop_queue(struct il_priv *il, u8 ac) +{ + if (atomic_inc_return(&il->queue_stop_count[ac]) > 0) + ieee80211_stop_queue(il->hw, ac); +} static inline void il_wake_queue(struct il_priv *il, struct il_tx_queue *txq) { @@ -2264,8 +2277,7 @@ il_wake_queue(struct il_priv *il, struct il_tx_queue *txq) u8 hwq = (queue >> 2) & 0x1f; if (test_and_clear_bit(hwq, il->queue_stopped)) - if (atomic_dec_return(&il->queue_stop_count[ac]) <= 0) - ieee80211_wake_queue(il->hw, ac); + _il_wake_queue(il, ac); } static inline void @@ -2276,8 +2288,7 @@ il_stop_queue(struct il_priv *il, struct il_tx_queue *txq) u8 hwq = (queue >> 2) & 0x1f; if (!test_and_set_bit(hwq, il->queue_stopped)) - if (atomic_inc_return(&il->queue_stop_count[ac]) > 0) - ieee80211_stop_queue(il->hw, ac); + _il_stop_queue(il, ac); } #ifdef ieee80211_stop_queue -- GitLab From c6af8074fd3654b2a8d7b31304d686519b062e14 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 12 Jun 2013 16:44:48 +0200 Subject: [PATCH 0996/2900] iwlegacy: add il_{stop,wake}_queues_by_reason functions Add functions that will stop/wake all queues. Make them safe regarding multiple calls and when some ac are stopped/woke independently. Tested-by: Jake Edge Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/common.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 67da89b39e11..83f8ed8a5528 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1299,6 +1299,8 @@ struct il_priv { /* queue refcounts */ #define IL_MAX_HW_QUEUES 32 unsigned long queue_stopped[BITS_TO_LONGS(IL_MAX_HW_QUEUES)]; +#define IL_STOP_REASON_PASSIVE 0 + unsigned long stop_reason; /* for each AC */ atomic_t queue_stop_count[4]; @@ -2291,6 +2293,26 @@ il_stop_queue(struct il_priv *il, struct il_tx_queue *txq) _il_stop_queue(il, ac); } +static inline void +il_wake_queues_by_reason(struct il_priv *il, int reason) +{ + u8 ac; + + if (test_and_clear_bit(reason, &il->stop_reason)) + for (ac = 0; ac < 4; ac++) + _il_wake_queue(il, ac); +} + +static inline void +il_stop_queues_by_reason(struct il_priv *il, int reason) +{ + u8 ac; + + if (!test_and_set_bit(reason, &il->stop_reason)) + for (ac = 0; ac < 4; ac++) + _il_stop_queue(il, ac); +} + #ifdef ieee80211_stop_queue #undef ieee80211_stop_queue #endif -- GitLab From 8cdbab7f07e82f26c48adcc761391c1c7ff339ff Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 12 Jun 2013 16:44:49 +0200 Subject: [PATCH 0997/2900] iwl4965: workaround for firmware frame tx rejection Firmware can reject to transmit frame on passive channel, when it did not yet received any frame with valid CRC on that channel. Workaround this problem in the driver. Tested-by: Jake Edge Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 18 ++++++++++++++++++ drivers/net/wireless/iwlegacy/common.c | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 9a95045c97b6..1c44bb59f6c8 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -588,6 +588,11 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr, return; } + if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) { + il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + D_INFO("Woke queues - frame received on passive channel\n"); + } + /* In case of HW accelerated crypto and bad decryption, drop */ if (!il->cfg->mod_params->sw_crypto && il_set_decrypted_flag(il, hdr, ampdu_status, stats)) @@ -2806,6 +2811,19 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) return; } + /* + * Firmware will not transmit frame on passive channel, if it not yet + * received some valid frame on that channel. When this error happen + * we have to wait until firmware will unblock itself i.e. when we + * note received beacon or other frame. We unblock queues in + * il4965_pass_packet_to_mac80211 or in il_mac_bss_info_changed. + */ + if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) && + il->iw_mode == NL80211_IFTYPE_STATION) { + il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + D_INFO("Stopped queues - RX waiting on passive channel\n"); + } + spin_lock_irqsave(&il->sta_lock, flags); if (txq->sched_retry) { const u32 scd_ssn = il4965_get_scd_ssn(tx_resp); diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index e9a3cbc409ae..3195aad440dd 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -5306,6 +5306,17 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_BSSID) { D_MAC80211("BSSID %pM\n", bss_conf->bssid); + /* + * On passive channel we wait with blocked queues to see if + * there is traffic on that channel. If no frame will be + * received (what is very unlikely since scan detects AP on + * that channel, but theoretically possible), mac80211 associate + * procedure will time out and mac80211 will call us with NULL + * bssid. We have to unblock queues on such condition. + */ + if (is_zero_ether_addr(bss_conf->bssid)) + il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + /* * If there is currently a HW scan going on in the background, * then we need to cancel it, otherwise sometimes we are not -- GitLab From c72456c75ae48d4d747c2ad4f7fe82601484a949 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 12 Jun 2013 16:44:50 +0200 Subject: [PATCH 0998/2900] iwl3945: workaround for firmware frame tx rejection Firmware can reject to transmit frame on passive channel, when it did not yet received any frame with valid CRC on that channel. Workaround this problem in the driver. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/3945.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index dc1e6da9976a..c092033945cc 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -331,6 +331,19 @@ il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) return; } + /* + * Firmware will not transmit frame on passive channel, if it not yet + * received some valid frame on that channel. When this error happen + * we have to wait until firmware will unblock itself i.e. when we + * note received beacon or other frame. We unblock queues in + * il3945_pass_packet_to_mac80211 or in il_mac_bss_info_changed. + */ + if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) && + il->iw_mode == NL80211_IFTYPE_STATION) { + il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + D_INFO("Stopped queues - RX waiting on passive channel\n"); + } + txq->time_stamp = jiffies; info = IEEE80211_SKB_CB(txq->skbs[txq->q.read_ptr]); ieee80211_tx_info_clear_status(info); @@ -488,6 +501,11 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb, return; } + if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) { + il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + D_INFO("Woke queues - frame received on passive channel\n"); + } + skb = dev_alloc_skb(128); if (!skb) { IL_ERR("dev_alloc_skb failed\n"); -- GitLab From d5346171d721bcfaab5843bf996ac6a379f7bd93 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 12 Jun 2013 16:48:25 +0200 Subject: [PATCH 0999/2900] Revert "iwl4965: workaround connection regression on passive channel" This reverts commit dd9c46408fdc07098333655ff27edf8cac8d9fcf. With "iwl{4965,3495): workaround for firmware frame tx rejection" patches we can enable IEEE80211_HW_REPORTS_TX_ACK_STATUS again. Tested-by: Jake Edge Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 1c44bb59f6c8..d287fd2dce42 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5759,7 +5759,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | - IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_SUPPORTS_DYNAMIC_PS; if (il->cfg->sku & IL_SKU_N) hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | -- GitLab From fa587d4b2f968b3719190a668a8707989855228d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 6 Jun 2013 13:18:03 +0200 Subject: [PATCH 1000/2900] brcmfmac: Always use fifo_credits, also for requested credits. Currently firmware requested credits do not require fifo credits. From a buffer management point of view this is incorrect. So firwmware requested credits require also fifo credits before the packet can be transferred to the host. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/dhd_dbg.c | 10 +- .../net/wireless/brcm80211/brcmfmac/dhd_dbg.h | 3 +- .../wireless/brcm80211/brcmfmac/fwsignal.c | 163 ++++++++---------- 3 files changed, 79 insertions(+), 97 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 202869cd0932..ce50686a86c8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c @@ -179,11 +179,11 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, fwstats->send_pkts[0], fwstats->send_pkts[1], fwstats->send_pkts[2], fwstats->send_pkts[3], fwstats->send_pkts[4], - fwstats->fifo_credits_sent[0], - fwstats->fifo_credits_sent[1], - fwstats->fifo_credits_sent[2], - fwstats->fifo_credits_sent[3], - fwstats->fifo_credits_sent[4]); + fwstats->requested_sent[0], + fwstats->requested_sent[1], + fwstats->requested_sent[2], + fwstats->requested_sent[3], + fwstats->requested_sent[4]); return simple_read_from_buffer(data, count, ppos, buf, res); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 009c87bfd9ae..451ebac09520 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -141,8 +141,7 @@ struct brcmf_fws_stats { u32 header_pulls; u32 pkt2bus; u32 send_pkts[5]; - u32 fifo_credits_sent[5]; - u32 fifo_credits_back[6]; + u32 requested_sent[5]; u32 generic_error; u32 mac_update_failed; u32 mac_ps_update_failed; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index ff920601898c..79d60a658a67 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -192,24 +192,21 @@ struct brcmf_skbuff_cb { /* * sk_buff control if flags * - * b[12] - packet sent upon credit request. - * b[11] - packet sent upon packet request. + * b[11] - packet sent upon firmware request. * b[10] - packet only contains signalling data. * b[9] - packet is a tx packet. - * b[8] - packet uses FIFO credit (non-pspoll). + * b[8] - packet used requested credit * b[7] - interface in AP mode. * b[3:0] - interface index. */ -#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK 0x1000 -#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT 12 #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT 10 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK 0x0200 #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT 9 -#define BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK 0x0100 -#define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT 8 +#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK 0x0100 +#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT 8 #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK 0x0080 #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT 7 #define BRCMF_SKB_IF_FLAGS_INDEX_MASK 0x000f @@ -311,12 +308,15 @@ enum brcmf_fws_fifo { * firmware suppress the packet as device is already in PS mode. * @BRCMF_FWS_TXSTATUS_FW_TOSSED: * firmware tossed the packet. + * @BRCMF_FWS_TXSTATUS_HOST_TOSSED: + * host tossed the packet. */ enum brcmf_fws_txstatus { BRCMF_FWS_TXSTATUS_DISCARD, BRCMF_FWS_TXSTATUS_CORE_SUPPRESS, BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS, - BRCMF_FWS_TXSTATUS_FW_TOSSED + BRCMF_FWS_TXSTATUS_FW_TOSSED, + BRCMF_FWS_TXSTATUS_HOST_TOSSED }; enum brcmf_fws_fcmode { @@ -639,6 +639,7 @@ static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, desc->occupied = 1; desc->state = BRCMF_FWS_STATE_OPEN; desc->requested_credit = 0; + desc->requested_packet = 0; /* depending on use may need ifp->bssidx instead */ desc->interface_id = ifidx; desc->ac_bitmap = 0xff; /* update this when handling APSD */ @@ -654,6 +655,7 @@ void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc) desc->occupied = 0; desc->state = BRCMF_FWS_STATE_CLOSE; desc->requested_credit = 0; + desc->requested_packet = 0; } static struct brcmf_fws_mac_descriptor * @@ -1050,35 +1052,35 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, return BRCMF_FWS_RET_OK_SCHEDULE; } -static int brcmf_fws_macdesc_use_credit(struct brcmf_fws_mac_descriptor *entry, - struct sk_buff *skb) +static void +brcmf_fws_macdesc_use_req_credit(struct brcmf_fws_mac_descriptor *entry, + struct sk_buff *skb) { - int use_credit = 1; - - if (entry->state == BRCMF_FWS_STATE_CLOSE) { - if (entry->requested_credit > 0) { - /* - * if the packet was pulled out while destination is in - * closed state but had a non-zero packets requested, - * then this should not count against the FIFO credit. - * That is due to the fact that the firmware will - * most likely hold onto this packet until a suitable - * time later to push it to the appropriate AC FIFO. - */ - entry->requested_credit--; - brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1); - use_credit = 0; - } else if (entry->requested_packet > 0) { - entry->requested_packet--; - brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); - use_credit = 0; - } + if (entry->requested_credit > 0) { + entry->requested_credit--; + brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); + brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1); + if (entry->state != BRCMF_FWS_STATE_CLOSE) + brcmf_err("requested credit set while mac not closed!\n"); + } else if (entry->requested_packet > 0) { + entry->requested_packet--; + brcmf_skb_if_flags_set_field(skb, REQUESTED, 1); + brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0); + if (entry->state != BRCMF_FWS_STATE_CLOSE) + brcmf_err("requested packet set while mac not closed!\n"); } else { - WARN_ON(entry->requested_credit); - WARN_ON(entry->requested_packet); + brcmf_skb_if_flags_set_field(skb, REQUESTED, 0); + brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0); } - brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit); - return use_credit; +} + +static void brcmf_fws_macdesc_return_req_credit(struct sk_buff *skb) +{ + struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; + + if ((brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) && + (entry->state == BRCMF_FWS_STATE_CLOSE)) + entry->requested_credit++; } static void brcmf_fws_return_credits(struct brcmf_fws_info *fws, @@ -1124,25 +1126,6 @@ static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) queue_work(fws->fws_wq, &fws->fws_dequeue_work); } -static void brcmf_fws_skb_pickup_credit(struct brcmf_fws_info *fws, int fifo, - struct sk_buff *p) -{ - struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(p)->mac; - - if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) - brcmf_fws_return_credits(fws, fifo, 1); - else if (brcmf_skb_if_flags_get_field(p, REQ_CREDIT) && - entry->state == BRCMF_FWS_STATE_CLOSE) - /* - * if this packet did not count against FIFO credit, it - * could have taken a requested_credit from the destination - * entry (for pspoll etc.) - */ - entry->requested_credit++; - - brcmf_fws_schedule_deq(fws); -} - static int brcmf_fws_enq(struct brcmf_fws_info *fws, enum brcmf_fws_skb_state state, int fifo, struct sk_buff *p) @@ -1224,7 +1207,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) if (p == NULL) continue; - brcmf_fws_macdesc_use_credit(entry, p); + brcmf_fws_macdesc_use_req_credit(entry, p); /* move dequeue position to ensure fair round-robin */ fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes; @@ -1313,7 +1296,8 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { fws->stats.txs_supp_ps++; remove_from_hanger = false; - } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) + } else if ((flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) || + (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) fws->stats.txs_tossed++; else brcmf_err("unexpected txstatus\n"); @@ -1340,9 +1324,13 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, /* pick up the implicit credit from this packet */ fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); - if (fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT || - !(brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) - brcmf_fws_skb_pickup_credit(fws, fifo, skb); + if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) || + (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) || + (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) { + brcmf_fws_return_credits(fws, fifo, 1); + brcmf_fws_schedule_deq(fws); + } + brcmf_fws_macdesc_return_req_credit(skb); if (!remove_from_hanger) ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit); @@ -1588,7 +1576,7 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, brcmf_skb_htod_tag_set_field(p, FIFO, fifo); brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; - if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) { + if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { /* * Indicate that this packet is being sent in response to an * explicit request from the firmware side. @@ -1636,6 +1624,7 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, state = brcmf_skbcb(skb)->state; entry = brcmf_skbcb(skb)->mac; + hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); if (entry != NULL) { if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { @@ -1647,8 +1636,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, rc = -ENOSPC; } } else { - hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); - /* delay-q packets are going to delay-q */ pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo, skb); @@ -1670,11 +1657,13 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, } if (rc) { - brcmf_fws_bustxfail(fws, skb); fws->stats.rollback_failed++; + brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, + hslot, 0); } else { fws->stats.rollback_success++; - brcmf_fws_skb_pickup_credit(fws, fifo, skb); + brcmf_fws_return_credits(fws, fifo, 1); + brcmf_fws_macdesc_return_req_credit(skb); } } @@ -1708,26 +1697,28 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; int *credit = &fws->fifo_credit[fifo]; - if (!brcmf_fws_macdesc_use_credit(entry, skb)) - return 0; - if (fifo != BRCMF_FWS_FIFO_AC_BE) fws->borrow_defer_timestamp = jiffies + BRCMF_FWS_BORROW_DEFER_PERIOD; if (!(*credit)) { /* Try to borrow a credit from other queue */ - if (fifo == BRCMF_FWS_FIFO_AC_BE && - brcmf_fws_borrow_credit(fws) == 0) - return 0; - - brcmf_dbg(DATA, "exit: ac=%d, credits depleted\n", fifo); - return -ENAVAIL; + if (fifo != BRCMF_FWS_FIFO_AC_BE || + (brcmf_fws_borrow_credit(fws) != 0)) { + brcmf_dbg(DATA, "ac=%d, credits depleted\n", fifo); + return -ENAVAIL; + } + } else { + (*credit)--; + if (!(*credit)) + fws->fifo_credit_map &= ~(1 << fifo); } - (*credit)--; - if (!(*credit)) - fws->fifo_credit_map &= ~(1 << fifo); - brcmf_dbg(DATA, "exit: ac=%d, credits=%d\n", fifo, *credit); + + brcmf_fws_macdesc_use_req_credit(entry, skb); + + brcmf_dbg(DATA, "ac=%d, credits=%02d:%02d:%02d:%02d\n", fifo, + fws->fifo_credit[0], fws->fifo_credit[1], + fws->fifo_credit[2], fws->fifo_credit[3]); return 0; } @@ -1764,8 +1755,8 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, entry->seq[fifo]++; fws->stats.pkt2bus++; fws->stats.send_pkts[fifo]++; - if (brcmf_skbcb(skb)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) - fws->stats.fifo_credits_sent[fifo]++; + if (brcmf_skb_if_flags_get_field(skb, REQUESTED)) + fws->stats.requested_sent[fifo]++; return rc; @@ -1888,10 +1879,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) skb = brcmf_fws_deq(fws, fifo); if (!skb) break; - if (brcmf_skbcb(skb)->if_flags & - BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) - fws->fifo_credit[fifo]--; - + fws->fifo_credit[fifo]--; if (brcmf_fws_commit_skb(fws, fifo, skb)) break; if (fws->bus_flow_blocked) @@ -2023,20 +2011,15 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) { ulong flags; - int fifo; + u32 hslot; if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) { brcmu_pkt_buf_free_skb(skb); return; } brcmf_fws_lock(fws->drvr, flags); - brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED, - brcmf_skb_htod_tag_get_field(skb, HSLOT), 0); - /* the packet never reached firmware so reclaim credit */ - if (fws->fcmode == BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { - fifo = brcmf_skb_htod_tag_get_field(skb, FIFO); - brcmf_fws_skb_pickup_credit(fws, fifo, skb); - } + hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); + brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0); brcmf_fws_unlock(fws->drvr, flags); } -- GitLab From 5631becbb8703d73239e097d222b183aa4f24e40 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 6 Jun 2013 13:18:07 +0200 Subject: [PATCH 1001/2900] brcmfmac: add debugfs statistics for firmware-signalling Added statistics for flow-control and packets dropped by the driver. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | 8 +++++++- drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | 3 +++ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 13 +++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index ce50686a86c8..c37b9d68e458 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c @@ -156,8 +156,11 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, "txs_suppr_core: %u\n" "txs_suppr_ps: %u\n" "txs_tossed: %u\n" + "txs_host_tossed: %u\n" + "bus_flow_block: %u\n" + "fws_flow_block: %u\n" "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" - "fifo_credits_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", + "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", fwstats->header_pulls, fwstats->header_only_pkt, fwstats->tlv_parse_failed, @@ -176,6 +179,9 @@ ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, fwstats->txs_supp_core, fwstats->txs_supp_ps, fwstats->txs_tossed, + fwstats->txs_host_tossed, + fwstats->bus_flow_block, + fwstats->fws_flow_block, fwstats->send_pkts[0], fwstats->send_pkts[1], fwstats->send_pkts[2], fwstats->send_pkts[3], fwstats->send_pkts[4], diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index 451ebac09520..0af1f5dc583a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -157,6 +157,9 @@ struct brcmf_fws_stats { u32 txs_supp_core; u32 txs_supp_ps; u32 txs_tossed; + u32 txs_host_tossed; + u32 bus_flow_block; + u32 fws_flow_block; }; struct brcmf_pub; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 79d60a658a67..70f70cea7f7d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -584,7 +584,7 @@ static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h, if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS) return -ENOENT; - if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) { + if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) { brcmf_err("entry not in use\n"); return -EINVAL; } @@ -894,8 +894,10 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, false); if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) && - pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) + pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) { + fws->stats.fws_flow_block++; brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true); + } return; } @@ -1296,9 +1298,10 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, } else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) { fws->stats.txs_supp_ps++; remove_from_hanger = false; - } else if ((flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) || - (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) + } else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED) fws->stats.txs_tossed++; + else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) + fws->stats.txs_host_tossed++; else brcmf_err("unexpected txstatus\n"); @@ -2030,4 +2033,6 @@ void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked) fws->bus_flow_blocked = flow_blocked; if (!flow_blocked) brcmf_fws_schedule_deq(fws); + else + fws->stats.bus_flow_block++; } -- GitLab From c70eba74532a9b54583689fead6e2e8f3a86e1c5 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 12 Jun 2013 14:11:16 -0700 Subject: [PATCH 1002/2900] igmp: fix new sparse errors Fix following sparse errors : net/ipv4/igmp.c:1222:25: warning: cast from restricted __be32 net/ipv4/igmp.c:1234:31: warning: incorrect type in assignment (different address spaces) net/ipv4/igmp.c:1234:31: expected struct ip_mc_list [noderef] *next_hash net/ipv4/igmp.c:1234:31: got struct ip_mc_list * net/ipv4/igmp.c:1250:31: warning: incorrect type in assignment (different address spaces) net/ipv4/igmp.c:1250:31: expected struct ip_mc_list [noderef] *next_hash net/ipv4/igmp.c:1250:31: got struct ip_mc_list * net/ipv4/igmp.c:2380:37: warning: cast from restricted __be32 These were added by commit e9897071350bd9 ("igmp: hash a hash table to speedup ip_check_mc_rcu()") Reported-by: kbuild test robot Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/igmp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index a09190ddffba..cd71190d2962 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1219,7 +1219,7 @@ static void igmp_group_added(struct ip_mc_list *im) static u32 ip_mc_hash(const struct ip_mc_list *im) { - return hash_32((u32)im->multiaddr, MC_HASH_SZ_LOG); + return hash_32((__force u32)im->multiaddr, MC_HASH_SZ_LOG); } static void ip_mc_hash_add(struct in_device *in_dev, @@ -1231,7 +1231,7 @@ static void ip_mc_hash_add(struct in_device *in_dev, mc_hash = rtnl_dereference(in_dev->mc_hash); if (mc_hash) { hash = ip_mc_hash(im); - im->next_hash = rtnl_dereference(mc_hash[hash]); + im->next_hash = mc_hash[hash]; rcu_assign_pointer(mc_hash[hash], im); return; } @@ -1247,7 +1247,7 @@ static void ip_mc_hash_add(struct in_device *in_dev, for_each_pmc_rtnl(in_dev, im) { hash = ip_mc_hash(im); - im->next_hash = rtnl_dereference(mc_hash[hash]); + im->next_hash = mc_hash[hash]; RCU_INIT_POINTER(mc_hash[hash], im); } @@ -2377,7 +2377,7 @@ int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u mc_hash = rcu_dereference(in_dev->mc_hash); if (mc_hash) { - u32 hash = hash_32((u32)mc_addr, MC_HASH_SZ_LOG); + u32 hash = hash_32((__force u32)mc_addr, MC_HASH_SZ_LOG); for (im = rcu_dereference(mc_hash[hash]); im != NULL; -- GitLab From 8f728d7934c77f63e89abcc96b46a7a98416d5c1 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 13 Jun 2013 00:55:34 +0400 Subject: [PATCH 1003/2900] sh_eth: split 'sh_eth_netdev_ops' Commit 9f86134155047720a3685cda21467f68695152d2 (sh_eth: remove SH_ETH_HAS_TSU) removes 'const' from 'sh_eth_netdev_ops' and modifies it in case TSU registers are present. I've originally suggested to Iwamatsu-san to split this structure in two instead and afterwards Dave M. suggested doing the same. Split 'sh_eth_netdev_ops_tsu' from 'sh_eth_netdev_ops', making both 'const', and assigning 'ndev->detdev_ops' depending on the presence of TSU registers. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 29 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 43d8490cfe0d..67a9e962f142 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2486,7 +2486,7 @@ static const u16 *sh_eth_get_register_offset(int register_type) return reg_offset; } -static struct net_device_ops sh_eth_netdev_ops = { +static const struct net_device_ops sh_eth_netdev_ops = { .ndo_open = sh_eth_open, .ndo_stop = sh_eth_close, .ndo_start_xmit = sh_eth_start_xmit, @@ -2498,6 +2498,21 @@ static struct net_device_ops sh_eth_netdev_ops = { .ndo_change_mtu = eth_change_mtu, }; +static const struct net_device_ops sh_eth_netdev_ops_tsu = { + .ndo_open = sh_eth_open, + .ndo_stop = sh_eth_close, + .ndo_start_xmit = sh_eth_start_xmit, + .ndo_get_stats = sh_eth_get_stats, + .ndo_set_rx_mode = sh_eth_set_multicast_list, + .ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = sh_eth_vlan_rx_kill_vid, + .ndo_tx_timeout = sh_eth_tx_timeout, + .ndo_do_ioctl = sh_eth_do_ioctl, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, +}; + static int sh_eth_drv_probe(struct platform_device *pdev) { int ret, devno = 0; @@ -2568,14 +2583,10 @@ static int sh_eth_drv_probe(struct platform_device *pdev) sh_eth_set_default_cpu_data(mdp->cd); /* set function */ - if (mdp->cd->tsu) { - sh_eth_netdev_ops.ndo_set_rx_mode = sh_eth_set_multicast_list; - sh_eth_netdev_ops.ndo_vlan_rx_add_vid = sh_eth_vlan_rx_add_vid; - sh_eth_netdev_ops.ndo_vlan_rx_kill_vid = - sh_eth_vlan_rx_kill_vid; - } - - ndev->netdev_ops = &sh_eth_netdev_ops; + if (mdp->cd->tsu) + ndev->netdev_ops = &sh_eth_netdev_ops_tsu; + else + ndev->netdev_ops = &sh_eth_netdev_ops; SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops); ndev->watchdog_timeo = TX_TIMEOUT; -- GitLab From 5e5726789a2c55db2e41ea8e7171ce4ee4066d01 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 13 May 2013 06:17:54 -0300 Subject: [PATCH 1004/2900] [media] omap3isp: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Acked-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 4c4bd3d1a2bc..5a04077b362b 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2291,8 +2291,6 @@ static int isp_probe(struct platform_device *pdev) isp_xclk_cleanup(isp); omap3isp_put(isp); error: - platform_set_drvdata(pdev, NULL); - mutex_destroy(&isp->isp_mutex); return ret; -- GitLab From 31036441d785359999e45bf410c778f64ffcab64 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 31 May 2013 19:22:50 -0300 Subject: [PATCH 1005/2900] [media] omap3isp: include linux/mm_types.h The ispqueue.h file uses vm_flags_t, which is defined in linux/mm_types.h, so we must include that header in order to build in all configurations. Signed-off-by: Arnd Bergmann Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispqueue.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h index 908dfd712e8e..3e048ad65647 100644 --- a/drivers/media/platform/omap3isp/ispqueue.h +++ b/drivers/media/platform/omap3isp/ispqueue.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include -- GitLab From 7c0f812a5d65e712618af880dda4a5cc7ed79463 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Mar 2013 12:02:13 -0300 Subject: [PATCH 1006/2900] [media] omap3isp: Defer probe when the IOMMU is not available When the OMAP3 ISP driver is compiled in the kernel the device can be probed before the corresponding IOMMU is available. Defer the probe in that case, and fix a crash in the error path. Reported-by: Javier Martin Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 5a04077b362b..ff5a20afa691 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2249,6 +2249,7 @@ static int isp_probe(struct platform_device *pdev) ret = iommu_attach_device(isp->domain, &pdev->dev); if (ret) { dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret); + ret = -EPROBE_DEFER; goto free_domain; } @@ -2287,6 +2288,7 @@ static int isp_probe(struct platform_device *pdev) iommu_detach_device(isp->domain, &pdev->dev); free_domain: iommu_domain_free(isp->domain); + isp->domain = NULL; error_isp: isp_xclk_cleanup(isp); omap3isp_put(isp); -- GitLab From fe905b8cc992edd3d1f729f4a88c4701e7c3b774 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 May 2013 00:47:41 -0300 Subject: [PATCH 1007/2900] [media] omap3isp: ccp2: Don't ignore the regulator_enable() return value Check the return value and catch errors correctly. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispccp2.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index 13982b0ab560..e71651429dda 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -158,13 +158,17 @@ static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2) * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ -static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) +static int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); + int ret; int i; - if (enable && ccp2->vdds_csib) - regulator_enable(ccp2->vdds_csib); + if (enable && ccp2->vdds_csib) { + ret = regulator_enable(ccp2->vdds_csib); + if (ret < 0) + return ret; + } /* Enable/Disable all the LCx channels */ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) @@ -179,6 +183,8 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); + + return 0; } /* @@ -851,7 +857,12 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable) ccp2_print_status(ccp2); /* Enable CSI1/CCP2 interface */ - ccp2_if_enable(ccp2, 1); + ret = ccp2_if_enable(ccp2, 1); + if (ret < 0) { + if (ccp2->phy) + omap3isp_csiphy_release(ccp2->phy); + return ret; + } break; case ISP_PIPELINE_STREAM_SINGLESHOT: -- GitLab From c88e739b1fad662240e99ecbd0bdaac871717987 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 13 Apr 2013 06:32:15 -0300 Subject: [PATCH 1008/2900] [media] media: info leak in __media_device_enum_links() These structs have holes and reserved struct members which aren't cleared. I've added a memset() so we don't leak stack information. Signed-off-by: Dan Carpenter Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 1957c0df08fd..d5a7a135f75d 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -142,6 +142,8 @@ static long __media_device_enum_links(struct media_device *mdev, for (p = 0; p < entity->num_pads; p++) { struct media_pad_desc pad; + + memset(&pad, 0, sizeof(pad)); media_device_kpad_to_upad(&entity->pads[p], &pad); if (copy_to_user(&links->pads[p], &pad, sizeof(pad))) return -EFAULT; @@ -159,6 +161,7 @@ static long __media_device_enum_links(struct media_device *mdev, if (entity->links[l].source->entity != entity) continue; + memset(&link, 0, sizeof(link)); media_device_kpad_to_upad(entity->links[l].source, &link.source); media_device_kpad_to_upad(entity->links[l].sink, -- GitLab From 5b9b6263775d45ccc0c8b27344bfb1a97cf6f725 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 12 Jun 2013 14:23:15 -0700 Subject: [PATCH 1009/2900] gro: remove a sparse error Fix following sparse error : net/ipv4/af_inet.c:1410:59: warning: restricted __be16 degrades to integer added in commit db8caf3dbc77599 ("gro: should aggregate frames without DF") Reported-by: kbuild test robot From: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 5598b06d62db..b4d0be2b7ce9 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1407,7 +1407,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, NAPI_GRO_CB(p)->flush |= (iph->ttl ^ iph2->ttl) | (iph->tos ^ iph2->tos) | - ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) | + (__force int)((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) | ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); NAPI_GRO_CB(p)->flush |= flush; -- GitLab From 7c0cadc69ca2ac8893aa162ee80d92a805840909 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 12 Jun 2013 14:31:39 -0700 Subject: [PATCH 1010/2900] udp: fix two sparse errors commit ba418fa357a7b3c ("soreuseport: UDP/IPv4 implementation") added following sparse errors : net/ipv4/udp.c:433:60: warning: cast from restricted __be16 net/ipv4/udp.c:433:60: warning: incorrect type in argument 1 (different base types) net/ipv4/udp.c:433:60: expected unsigned short [unsigned] [usertype] val net/ipv4/udp.c:433:60: got restricted __be16 [usertype] sport net/ipv4/udp.c:433:60: warning: cast from restricted __be16 net/ipv4/udp.c:433:60: warning: cast from restricted __be16 net/ipv4/udp.c:514:60: warning: cast from restricted __be16 net/ipv4/udp.c:514:60: warning: incorrect type in argument 1 (different base types) net/ipv4/udp.c:514:60: expected unsigned short [unsigned] [usertype] val net/ipv4/udp.c:514:60: got restricted __be16 [usertype] sport net/ipv4/udp.c:514:60: warning: cast from restricted __be16 net/ipv4/udp.c:514:60: warning: cast from restricted __be16 Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/udp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f65bc32c0266..959502afd8d9 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -430,7 +430,7 @@ static struct sock *udp4_lib_lookup2(struct net *net, reuseport = sk->sk_reuseport; if (reuseport) { hash = inet_ehashfn(net, daddr, hnum, - saddr, htons(sport)); + saddr, sport); matches = 1; } } else if (score == badness && reuseport) { @@ -511,7 +511,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, reuseport = sk->sk_reuseport; if (reuseport) { hash = inet_ehashfn(net, daddr, hnum, - saddr, htons(sport)); + saddr, sport); matches = 1; } } else if (score == badness && reuseport) { -- GitLab From 274038f8c94c493e2977983e2aecb5f5f0778479 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 11 Jun 2013 14:41:24 +0400 Subject: [PATCH 1011/2900] tun: Report "persist" flag to userspace The TUN_PERSIST flag is not reported at all -- both TUNGETIFF, and sysfs "flags" attribute skip one. Knowing whether a device is persistent or not is critical for checkpoint-restore, thus I propose to add the read-only IFF_PERSIST one for this. Setting this new IFF_PERSIST is hardly possible, as TUNSETIFF doesn't check for unknown flags being zero and thus there can be trash. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- drivers/net/tun.c | 3 +++ include/uapi/linux/if_tun.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 89776c592151..b90a73165d30 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1530,6 +1530,9 @@ static int tun_flags(struct tun_struct *tun) if (tun->flags & TUN_TAP_MQ) flags |= IFF_MULTI_QUEUE; + if (tun->flags & TUN_PERSIST) + flags |= IFF_PERSIST; + return flags; } diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h index 2835b85fd46d..82334f88967e 100644 --- a/include/uapi/linux/if_tun.h +++ b/include/uapi/linux/if_tun.h @@ -68,6 +68,8 @@ #define IFF_MULTI_QUEUE 0x0100 #define IFF_ATTACH_QUEUE 0x0200 #define IFF_DETACH_QUEUE 0x0400 +/* read-only flag */ +#define IFF_PERSIST 0x0800 /* Features for GSO (TUNSETOFFLOAD). */ #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ -- GitLab From 944a1376b6ca1f00cc67f7d319afd55d5d9afba5 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 11 Jun 2013 17:01:08 +0400 Subject: [PATCH 1012/2900] tun: Turn tun_flow_init() into void fn This routine doesn't fail since 9fdc6bef (tuntap: dont use a private kmem_cache) so it makes sense to compact the code a little bit. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- drivers/net/tun.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b90a73165d30..a34427065460 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -841,7 +841,7 @@ static const struct net_device_ops tap_netdev_ops = { #endif }; -static int tun_flow_init(struct tun_struct *tun) +static void tun_flow_init(struct tun_struct *tun) { int i; @@ -852,8 +852,6 @@ static int tun_flow_init(struct tun_struct *tun) setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun); mod_timer(&tun->flow_gc_timer, round_jiffies_up(jiffies + tun->ageing_time)); - - return 0; } static void tun_flow_uninit(struct tun_struct *tun) @@ -1662,10 +1660,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) goto err_free_dev; tun_net_init(dev); - - err = tun_flow_init(tun); - if (err < 0) - goto err_free_dev; + tun_flow_init(tun); dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | TUN_USER_FEATURES; -- GitLab From e3d73bcedfdf66d21349fee00241b0931d28a943 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Jun 2013 18:54:39 +0800 Subject: [PATCH 1013/2900] net: add doc for ip_early_demux sysctl commit 6648bd7e0e62c0c8c03b (ipv4: Add sysctl knob to control early socket demux) introduced such sysctl, but forgot to add doc into Documentation/networking/ip-sysctl.txt. This patch adds it. Basically I grab the doc from the description of commit 41063e9dd11956f2d285 (ipv4: Early TCP socket demux.) and the above commit. Cc: Eric Dumazet Cc: Alexander Duyck Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 9cea5d3b3c50..36e5a402ed0e 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -685,6 +685,15 @@ ip_dynaddr - BOOLEAN occurs. Default: 0 +ip_early_demux - BOOLEAN + Optimize input packet processing down to one demux for + certain kinds of local sockets. Currently we only do this + for established TCP sockets. + + It may add an additional cost for pure routing workloads that + reduces overall throughput, in such case you should disable it. + Default: 1 + icmp_echo_ignore_all - BOOLEAN If set non-zero, then the kernel will ignore all ICMP ECHO requests sent to it. -- GitLab From 4eb1d01d3f5c0bf7e4f02cb1b73b2d85d64cc762 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 02:16:20 -0300 Subject: [PATCH 1014/2900] [media] s3c-camif: Staticize local symbols These symbols are local to the file and should be static. Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-regs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c index 1a3b4fc05ec6..7b22d6c4613b 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.c +++ b/drivers/media/platform/s3c-camif/camif-regs.c @@ -379,7 +379,7 @@ static void camif_hw_set_prescaler(struct camif_vp *vp) camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg); } -void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) +static void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) { struct camif_dev *camif = vp->camif; struct camif_scaler *scaler = &vp->scaler; @@ -426,7 +426,7 @@ void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) scaler->main_h_ratio, scaler->main_v_ratio); } -void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp) +static void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp) { struct camif_dev *camif = vp->camif; struct camif_scaler *scaler = &vp->scaler; -- GitLab From 661eb3811df568161399af0048f1ecb4ac073687 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 12 Jun 2013 22:47:56 +0200 Subject: [PATCH 1015/2900] mac80211: fix TX aggregation TID struct leak Ben reports that kmemleak is saying TX aggregation TID structs are leaked. Given his workload, I suspect that they're leaked because stations are destroyed before their aggregation sessions get a chance to start. Fix this by simply freeing structs that are not used yet. Reported-by: Ben Greear Tested-by: Ben Greear Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b4297982d34a..aaf68d297221 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -149,6 +149,7 @@ static void cleanup_single_sta(struct sta_info *sta) * directly by station destruction. */ for (i = 0; i < IEEE80211_NUM_TIDS; i++) { + kfree(sta->ampdu_mlme.tid_start_tx[i]); tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; -- GitLab From 99b63ac8b12dd08ce403b0d4cf498615c1ec311f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 02:16:21 -0300 Subject: [PATCH 1016/2900] [media] s3c-camif: Use dev_info instead of printk dev_info is preferred to printk. Silences the related checkpatch warning. WARNING: Prefer netdev_info(netdev, ... then dev_info(dev, ... then pr_info(... to printk(KERN_INFO ... Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c index 7b22d6c4613b..a9e3b16460b8 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.c +++ b/drivers/media/platform/s3c-camif/camif-regs.c @@ -601,6 +601,6 @@ void camif_hw_dump_regs(struct camif_dev *camif, const char *label) pr_info("--- %s ---\n", label); for (i = 0; i < ARRAY_SIZE(registers); i++) { u32 cfg = readl(camif->io_base + registers[i].offset); - printk(KERN_INFO "%s:\t0x%08x\n", registers[i].name, cfg); + dev_info(camif->dev, "%s:\t0x%08x\n", registers[i].name, cfg); } } -- GitLab From 8638a467cc3357c00dadbf3280497f089802bb96 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 05:04:09 -0300 Subject: [PATCH 1017/2900] [media] s5c73m3: Fix whitespace related warnings Silences the following type of warning: WARNING: space prohibited before semicolon Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 6f3a9c00fe65..8079e26eb5e2 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -73,7 +73,7 @@ int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr, memset(padding, 0, sizeof(padding)); - for (i = 0; i < count ; i++) { + for (i = 0; i < count; i++) { r = spi_xmit(spi_dev, (void *)addr + j, tx_size, SPI_DIR_TX); if (r < 0) return r; @@ -98,7 +98,7 @@ int s5c73m3_spi_read(struct s5c73m3 *state, void *addr, unsigned int i, j = 0; int r = 0; - for (i = 0; i < count ; i++) { + for (i = 0; i < count; i++) { r = spi_xmit(spi_dev, addr + j, tx_size, SPI_DIR_RX); if (r < 0) return r; -- GitLab From 24f99dd0fb546b0933564f9697aa5fa5fe9b41da Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 00:51:33 -0300 Subject: [PATCH 1018/2900] [media] exynos4-is: Remove redundant NULL check in fimc-lite.c clk_unprepare checks for NULL pointer. Hence convert IS_ERR_OR_NULL to IS_ERR only. [s.nawrocki: replaced initialisations to NULL with ERR_PTR() value] Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 2f11ae4fd4a4..80ebf439e352 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1417,12 +1417,12 @@ static void fimc_lite_unregister_capture_subdev(struct fimc_lite *fimc) static void fimc_lite_clk_put(struct fimc_lite *fimc) { - if (IS_ERR_OR_NULL(fimc->clock)) + if (IS_ERR(fimc->clock)) return; clk_unprepare(fimc->clock); clk_put(fimc->clock); - fimc->clock = NULL; + fimc->clock = ERR_PTR(-EINVAL); } static int fimc_lite_clk_get(struct fimc_lite *fimc) @@ -1436,7 +1436,7 @@ static int fimc_lite_clk_get(struct fimc_lite *fimc) ret = clk_prepare(fimc->clock); if (ret < 0) { clk_put(fimc->clock); - fimc->clock = NULL; + fimc->clock = ERR_PTR(-EINVAL); } return ret; } -- GitLab From d46a5a68b1690fc9f47d6b3e13ccef4e79a87e84 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 02:16:18 -0300 Subject: [PATCH 1019/2900] [media] s3c-camif: Remove redundant NULL check clk_unprepare checks for NULL pointer. Hence convert IS_ERR_OR_NULL to IS_ERR only. [s.nawrocki: added initialisation of the clock array to ERR_PTR() value] Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s3c-camif/camif-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 0d0fab1a7b5e..b38574702fe9 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -341,10 +341,11 @@ static void camif_clk_put(struct camif_dev *camif) int i; for (i = 0; i < CLK_MAX_NUM; i++) { - if (IS_ERR_OR_NULL(camif->clock[i])) + if (IS_ERR(camif->clock[i])) continue; clk_unprepare(camif->clock[i]); clk_put(camif->clock[i]); + camif->clock[i] = ERR_PTR(-EINVAL); } } @@ -352,6 +353,9 @@ static int camif_clk_get(struct camif_dev *camif) { int ret, i; + for (i = 1; i < CLK_MAX_NUM; i++) + camif->clock[i] = ERR_PTR(-EINVAL); + for (i = 0; i < CLK_MAX_NUM; i++) { camif->clock[i] = clk_get(camif->dev, camif_clocks[i]); if (IS_ERR(camif->clock[i])) { -- GitLab From 6a2f18cf58a59ba7de2a5f912b12d9732702969c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 13 May 2013 01:49:13 -0300 Subject: [PATCH 1020/2900] [media] s5p-tv: fix error return code in mxr_acquire_video() Fix to return a negative error code in the vb2_dma_contig_init_ctx() error handling case instead of 0, as done elsewhere in this function. Also vb2_dma_contig_init_ctx() return ERR_PTR() in case of error and never return NULL, so use IS_ERR() replace IS_ERR_OR_NULL(). Signed-off-by: Wei Yongjun Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index ef0efdf422fe..641b1f071e06 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -81,8 +81,9 @@ int mxr_acquire_video(struct mxr_device *mdev, } mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev); - if (IS_ERR_OR_NULL(mdev->alloc_ctx)) { + if (IS_ERR(mdev->alloc_ctx)) { mxr_err(mdev, "could not acquire vb2 allocator\n"); + ret = PTR_ERR(mdev->alloc_ctx); goto fail_v4l2_dev; } -- GitLab From c28c99e7741f848ffe808a578b265dd2bb23a52f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 8 May 2013 14:24:14 -0300 Subject: [PATCH 1021/2900] [media] exynos4-is: Fix example dts in .../bindings/samsung-fimc.txt The s5c73m3 sensor node should be off an I2C bus controller node. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/samsung-fimc.txt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt index 51c776b7f7a3..96312f6c4c26 100644 --- a/Documentation/devicetree/bindings/media/samsung-fimc.txt +++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt @@ -127,22 +127,22 @@ Example: }; }; }; - }; - /* MIPI CSI-2 bus IF sensor */ - s5c73m3: sensor@0x1a { - compatible = "samsung,s5c73m3"; - reg = <0x1a>; - vddio-supply = <...>; + /* MIPI CSI-2 bus IF sensor */ + s5c73m3: sensor@0x1a { + compatible = "samsung,s5c73m3"; + reg = <0x1a>; + vddio-supply = <...>; - clock-frequency = <24000000>; - clocks = <...>; - clock-names = "mclk"; + clock-frequency = <24000000>; + clocks = <...>; + clock-names = "mclk"; - port { - s5c73m3_1: endpoint { - data-lanes = <1 2 3 4>; - remote-endpoint = <&csis0_ep>; + port { + s5c73m3_1: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&csis0_ep>; + }; }; }; }; -- GitLab From 8a0c28f5ba8965790b20a82208226567dad69a2a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 30 Apr 2013 09:27:08 -0300 Subject: [PATCH 1022/2900] [media] exynos4-is: Remove platform_device_id table at fimc-lite driver The driver id_table is unused since all SoCs containing the FIMC-LITE IP block have been dt-only. Just remove it. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 80ebf439e352..d770f33150f5 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1,8 +1,8 @@ /* * Samsung EXYNOS FIMC-LITE (camera host interface) driver * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1626,15 +1626,6 @@ static struct flite_drvdata fimc_lite_drvdata_exynos4 = { .out_hor_offs_align = 8, }; -static struct platform_device_id fimc_lite_driver_ids[] = { - { - .name = "exynos-fimc-lite", - .driver_data = (unsigned long)&fimc_lite_drvdata_exynos4, - }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids); - static const struct of_device_id flite_of_match[] = { { .compatible = "samsung,exynos4212-fimc-lite", @@ -1647,7 +1638,6 @@ MODULE_DEVICE_TABLE(of, flite_of_match); static struct platform_driver fimc_lite_driver = { .probe = fimc_lite_probe, .remove = fimc_lite_remove, - .id_table = fimc_lite_driver_ids, .driver = { .of_match_table = flite_of_match, .name = FIMC_LITE_DRV_NAME, -- GitLab From 793ad32d1b7159772feb36ac41e265786729e78c Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 30 Apr 2013 09:27:53 -0300 Subject: [PATCH 1023/2900] [media] exynos4-is: Correct querycap ioctl handling at fimc-lite driver Fill in properly bus_info and card fields and set device_caps. The querycap ioctl handler is renamed for consistency with the other ioctls. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index d770f33150f5..5634799ab944 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -637,13 +637,18 @@ static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r) /* * Video node ioctl operations */ -static int fimc_vidioc_querycap_capture(struct file *file, void *priv, +static int fimc_lite_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { + struct fimc_lite *fimc = video_drvdata(file); + strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver)); - cap->bus_info[0] = 0; - cap->card[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING; + strlcpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + dev_name(&fimc->pdev->dev)); + + cap->device_caps = V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -938,7 +943,7 @@ static int fimc_lite_s_selection(struct file *file, void *fh, } static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = { - .vidioc_querycap = fimc_vidioc_querycap_capture, + .vidioc_querycap = fimc_lite_querycap, .vidioc_enum_fmt_vid_cap_mplane = fimc_lite_enum_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane, -- GitLab From 44048752345460df738b87ebec82c9bfc8257943 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 17 May 2013 00:31:01 -0300 Subject: [PATCH 1024/2900] [media] s5p-tv: Fix incorrect usage of IS_ERR_OR_NULL in hdmi_drv.c NULL check on clocks obtained using common clock APIs should not be done. Use IS_ERR only. Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/hdmi_drv.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 4e86626dad4b..cd525f193240 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -755,6 +755,15 @@ static const struct dev_pm_ops hdmi_pm_ops = { .runtime_resume = hdmi_runtime_resume, }; +static void hdmi_resource_clear_clocks(struct hdmi_resources *res) +{ + res->hdmi = ERR_PTR(-EINVAL); + res->sclk_hdmi = ERR_PTR(-EINVAL); + res->sclk_pixel = ERR_PTR(-EINVAL); + res->sclk_hdmiphy = ERR_PTR(-EINVAL); + res->hdmiphy = ERR_PTR(-EINVAL); +} + static void hdmi_resources_cleanup(struct hdmi_device *hdev) { struct hdmi_resources *res = &hdev->res; @@ -765,17 +774,18 @@ static void hdmi_resources_cleanup(struct hdmi_device *hdev) regulator_bulk_free(res->regul_count, res->regul_bulk); /* kfree is NULL-safe */ kfree(res->regul_bulk); - if (!IS_ERR_OR_NULL(res->hdmiphy)) + if (!IS_ERR(res->hdmiphy)) clk_put(res->hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_hdmiphy)) + if (!IS_ERR(res->sclk_hdmiphy)) clk_put(res->sclk_hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_pixel)) + if (!IS_ERR(res->sclk_pixel)) clk_put(res->sclk_pixel); - if (!IS_ERR_OR_NULL(res->sclk_hdmi)) + if (!IS_ERR(res->sclk_hdmi)) clk_put(res->sclk_hdmi); - if (!IS_ERR_OR_NULL(res->hdmi)) + if (!IS_ERR(res->hdmi)) clk_put(res->hdmi); memset(res, 0, sizeof(*res)); + hdmi_resource_clear_clocks(res); } static int hdmi_resources_init(struct hdmi_device *hdev) @@ -793,8 +803,9 @@ static int hdmi_resources_init(struct hdmi_device *hdev) dev_dbg(dev, "HDMI resource init\n"); memset(res, 0, sizeof(*res)); - /* get clocks, power */ + hdmi_resource_clear_clocks(res); + /* get clocks, power */ res->hdmi = clk_get(dev, "hdmi"); if (IS_ERR(res->hdmi)) { dev_err(dev, "failed to get clock 'hdmi'\n"); -- GitLab From 0781c057e3fd49e096ec2ea7fa5d6ad18a2f42bb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 17 May 2013 00:31:02 -0300 Subject: [PATCH 1025/2900] [media] s5p-tv: Fix incorrect usage of IS_ERR_OR_NULL in mixer_drv.c NULL check on clocks obtained using common clock APIs should not be done. Use IS_ERR only. [s.nawrocki: removed unrelated whitespace change] Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/mixer_drv.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index 5733033a6ead..51805a5e2beb 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -211,6 +211,15 @@ static int mxr_acquire_plat_resources(struct mxr_device *mdev, return ret; } +static void mxr_resource_clear_clocks(struct mxr_resources *res) +{ + res->mixer = ERR_PTR(-EINVAL); + res->vp = ERR_PTR(-EINVAL); + res->sclk_mixer = ERR_PTR(-EINVAL); + res->sclk_hdmi = ERR_PTR(-EINVAL); + res->sclk_dac = ERR_PTR(-EINVAL); +} + static void mxr_release_plat_resources(struct mxr_device *mdev) { free_irq(mdev->res.irq, mdev); @@ -222,15 +231,15 @@ static void mxr_release_clocks(struct mxr_device *mdev) { struct mxr_resources *res = &mdev->res; - if (!IS_ERR_OR_NULL(res->sclk_dac)) + if (!IS_ERR(res->sclk_dac)) clk_put(res->sclk_dac); - if (!IS_ERR_OR_NULL(res->sclk_hdmi)) + if (!IS_ERR(res->sclk_hdmi)) clk_put(res->sclk_hdmi); - if (!IS_ERR_OR_NULL(res->sclk_mixer)) + if (!IS_ERR(res->sclk_mixer)) clk_put(res->sclk_mixer); - if (!IS_ERR_OR_NULL(res->vp)) + if (!IS_ERR(res->vp)) clk_put(res->vp); - if (!IS_ERR_OR_NULL(res->mixer)) + if (!IS_ERR(res->mixer)) clk_put(res->mixer); } @@ -239,6 +248,8 @@ static int mxr_acquire_clocks(struct mxr_device *mdev) struct mxr_resources *res = &mdev->res; struct device *dev = mdev->dev; + mxr_resource_clear_clocks(res); + res->mixer = clk_get(dev, "mixer"); if (IS_ERR(res->mixer)) { mxr_err(mdev, "failed to get clock 'mixer'\n"); @@ -299,6 +310,7 @@ static void mxr_release_resources(struct mxr_device *mdev) mxr_release_clocks(mdev); mxr_release_plat_resources(mdev); memset(&mdev->res, 0, sizeof(mdev->res)); + mxr_resource_clear_clocks(&mdev->res); } static void mxr_release_layers(struct mxr_device *mdev) -- GitLab From 0425d7963af85a01b3d96b42977cafe41f94e50e Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 23 May 2013 00:51:18 -0300 Subject: [PATCH 1026/2900] [media] exynos-gsc: Remove redundant use of of_match_ptr macro This is a DT only driver and exynos_gsc_match is always compiled in. Hence of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 33b5ffc8d66d..559fab2a2d67 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -988,7 +988,7 @@ static void *gsc_get_drv_data(struct platform_device *pdev) if (pdev->dev.of_node) { const struct of_device_id *match; - match = of_match_node(of_match_ptr(exynos_gsc_match), + match = of_match_node(exynos_gsc_match, pdev->dev.of_node); if (match) driver_data = (struct gsc_driverdata *)match->data; -- GitLab From a40a138291a3cc9110b300f35977479914a1613b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 23 May 2013 00:51:19 -0300 Subject: [PATCH 1027/2900] [media] s5p-mfc: Remove redundant use of of_match_ptr macro 'exynos_mfc_match' is always compiled in. Hence of_match_ptr is unnecessary. Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 01f9ae0dadb0..5d0419bd6aff 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1426,7 +1426,7 @@ static void *mfc_get_drv_data(struct platform_device *pdev) if (pdev->dev.of_node) { const struct of_device_id *match; - match = of_match_node(of_match_ptr(exynos_mfc_match), + match = of_match_node(exynos_mfc_match, pdev->dev.of_node); if (match) driver_data = (struct s5p_mfc_variant *)match->data; -- GitLab From e0e9f67afcd5e06bc1ff6ecbf130635673a41d48 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 16 Apr 2013 02:02:21 -0300 Subject: [PATCH 1028/2900] [media] exynos4-is: Staticize local symbols These symbols are used only in their respective files and hence should be made static. [s.nawrocki@samsung.com: dropped the __fimc_is_hw_update_param() function change] Signed-off-by: Sachin Kamat Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-is-i2c.c | 2 +- drivers/media/platform/exynos4-is/fimc-is-param.c | 4 ++-- drivers/media/platform/exynos4-is/fimc-is.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index c397777d7cbb..617a798d9235 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c @@ -96,7 +96,7 @@ static int fimc_is_i2c_resume(struct device *dev) return clk_prepare_enable(isp_i2c->clock); } -UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, +static UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, fimc_is_i2c_resume, NULL); static const struct of_device_id fimc_is_i2c_of_match[] = { diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c index 53fe2a2b4db3..c435db0da673 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ b/drivers/media/platform/exynos4-is/fimc-is-param.c @@ -38,7 +38,7 @@ static void __hw_param_copy(void *dst, void *src) memcpy(dst, src, FIMC_IS_PARAM_MAX_SIZE); } -void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) +static void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) { struct param_global_shotmode *dst, *src; @@ -47,7 +47,7 @@ void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) __hw_param_copy(dst, src); } -void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) +static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) { struct param_sensor_framerate *dst, *src; diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 47c6363d04e2..cdb6b5e27336 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -137,7 +137,7 @@ static int fimc_is_setup_clocks(struct fimc_is *is) ATCLK_MCUISP_FREQUENCY); } -int fimc_is_enable_clocks(struct fimc_is *is) +static int fimc_is_enable_clocks(struct fimc_is *is) { int i, ret; @@ -157,7 +157,7 @@ int fimc_is_enable_clocks(struct fimc_is *is) return 0; } -void fimc_is_disable_clocks(struct fimc_is *is) +static void fimc_is_disable_clocks(struct fimc_is *is) { int i; -- GitLab From a44e3b206a26e3978d1041b4145e5afc4ed52e86 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 19:43:35 -0300 Subject: [PATCH 1029/2900] [media] s5c73m3: Do not ignore errors from regulator_enable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes following compilation warning: drivers/media/i2c/s5c73m3/s5c73m3-core.c: In function ‘__s5c73m3_power_off’: drivers/media/i2c/s5c73m3/s5c73m3-core.c:1389:19: warning: ignoring return value of ‘regulator_enable’, declared with attribute warn_unused_result Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index d3e867a7a565..402da96f5a71 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1385,9 +1385,12 @@ static int __s5c73m3_power_off(struct s5c73m3 *state) } return 0; err: - for (++i; i < S5C73M3_MAX_SUPPLIES; i++) - regulator_enable(state->supplies[i].consumer); - + for (++i; i < S5C73M3_MAX_SUPPLIES; i++) { + int r = regulator_enable(state->supplies[i].consumer); + if (r < 0) + v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n", + state->supplies[i].supply, r); + } return ret; } -- GitLab From 045a1faca83cdaa54dd88f9a2875debdea5d79fa Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 10 Jun 2013 08:51:44 -0300 Subject: [PATCH 1030/2900] [media] exynos4-is: Move common functions to a separate module Create a common module (exynos4-is-common.ko) for common functions used across the exynos4-is video device and subdev drivers. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/Kconfig | 7 +++- drivers/media/platform/exynos4-is/Makefile | 5 ++- drivers/media/platform/exynos4-is/common.c | 41 +++++++++++++++++++ drivers/media/platform/exynos4-is/common.h | 12 ++++++ drivers/media/platform/exynos4-is/fimc-lite.c | 29 ++----------- 5 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 drivers/media/platform/exynos4-is/common.c create mode 100644 drivers/media/platform/exynos4-is/common.h diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig index 6ff99b5849f9..c622532174e3 100644 --- a/drivers/media/platform/exynos4-is/Kconfig +++ b/drivers/media/platform/exynos4-is/Kconfig @@ -8,12 +8,16 @@ config VIDEO_SAMSUNG_EXYNOS4_IS if VIDEO_SAMSUNG_EXYNOS4_IS +config VIDEO_EXYNOS4_IS_COMMON + tristate + config VIDEO_S5P_FIMC tristate "S5P/EXYNOS4 FIMC/CAMIF camera interface driver" depends on I2C select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV select MFD_SYSCON if OF + select VIDEO_EXYNOS4_IS_COMMON help This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host interface and video postprocessor (FIMC) devices. @@ -38,6 +42,7 @@ config VIDEO_EXYNOS_FIMC_LITE tristate "EXYNOS FIMC-LITE camera interface driver" depends on I2C select VIDEOBUF2_DMA_CONTIG + select VIDEO_EXYNOS4_IS_COMMON help This is a V4L2 driver for Samsung EXYNOS4/5 SoC FIMC-LITE camera host interface. @@ -58,4 +63,4 @@ config VIDEO_EXYNOS4_FIMC_IS To compile this driver as a module, choose M here: the module will be called exynos4-fimc-is. -endif # VIDEO_SAMSUNG_S5P_FIMC +endif # VIDEO_SAMSUNG_EXYNOS4_IS diff --git a/drivers/media/platform/exynos4-is/Makefile b/drivers/media/platform/exynos4-is/Makefile index f25f46377399..c2ff29ba6856 100644 --- a/drivers/media/platform/exynos4-is/Makefile +++ b/drivers/media/platform/exynos4-is/Makefile @@ -1,10 +1,13 @@ s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o media-dev.o exynos-fimc-lite-objs += fimc-lite-reg.o fimc-lite.o +s5p-csis-objs := mipi-csis.o +exynos4-is-common-objs := common.o + exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o -s5p-csis-objs := mipi-csis.o obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o obj-$(CONFIG_VIDEO_S5P_FIMC) += s5p-fimc.o +obj-$(CONFIG_VIDEO_EXYNOS4_IS_COMMON) += exynos4-is-common.o diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c new file mode 100644 index 000000000000..57f9010cee50 --- /dev/null +++ b/drivers/media/platform/exynos4-is/common.c @@ -0,0 +1,41 @@ +/* + * Samsung S5P/EXYNOS4 SoC Camera Subsystem driver + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include "common.h" + +/* Called with the media graph mutex held or entity->stream_count > 0. */ +struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity) +{ + struct media_pad *pad = &entity->pads[0]; + struct v4l2_subdev *sd; + + while (pad->flags & MEDIA_PAD_FL_SINK) { + /* source pad */ + pad = media_entity_remote_pad(pad); + if (pad == NULL || + media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + break; + + sd = media_entity_to_v4l2_subdev(pad->entity); + + if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR || + sd->grp_id == GRP_ID_SENSOR) + return sd; + /* sink pad */ + pad = &sd->entity.pads[0]; + } + return NULL; +} +EXPORT_SYMBOL(fimc_find_remote_sensor); + +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos4-is/common.h b/drivers/media/platform/exynos4-is/common.h new file mode 100644 index 000000000000..3c398039ba28 --- /dev/null +++ b/drivers/media/platform/exynos4-is/common.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 5634799ab944..6daa88531e6e 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -32,6 +32,7 @@ #include #include +#include "common.h" #include "fimc-core.h" #include "fimc-lite.h" #include "fimc-lite-reg.h" @@ -131,30 +132,6 @@ static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat, return def_fmt; } -/* Called with the media graph mutex held or @me stream_count > 0. */ -static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me) -{ - struct media_pad *pad = &me->pads[0]; - struct v4l2_subdev *sd; - - while (pad->flags & MEDIA_PAD_FL_SINK) { - /* source pad */ - pad = media_entity_remote_pad(pad); - if (pad == NULL || - media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - break; - - sd = media_entity_to_v4l2_subdev(pad->entity); - - if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR || - sd->grp_id == GRP_ID_SENSOR) - return sd; - /* sink pad */ - pad = &sd->entity.pads[0]; - } - return NULL; -} - static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output) { struct fimc_source_info *si; @@ -830,7 +807,7 @@ static int fimc_lite_streamon(struct file *file, void *priv, if (ret < 0) goto err_p_stop; - fimc->sensor = __find_remote_sensor(&fimc->subdev.entity); + fimc->sensor = fimc_find_remote_sensor(&fimc->subdev.entity); ret = vb2_ioctl_streamon(file, priv, type); if (!ret) { @@ -1212,7 +1189,7 @@ static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on) * The pipeline links are protected through entity.stream_count * so there is no need to take the media graph mutex here. */ - fimc->sensor = __find_remote_sensor(&sd->entity); + fimc->sensor = fimc_find_remote_sensor(&sd->entity); if (atomic_read(&fimc->out_path) != FIMC_IO_ISP) return -ENOIOCTLCMD; -- GitLab From bc7584b0b7a99326d31195f81f7494efe9fe0c0f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:18 -0300 Subject: [PATCH 1031/2900] [media] exynos4-is: Add struct exynos_video_entity This patch introduces common structure for the video entities to handle all video nodes and media pipelines associated with them in more generic way. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 43 +++++++++++-------- drivers/media/platform/exynos4-is/fimc-core.h | 4 +- .../media/platform/exynos4-is/fimc-lite-reg.c | 2 +- drivers/media/platform/exynos4-is/fimc-lite.c | 20 ++++----- drivers/media/platform/exynos4-is/fimc-lite.h | 4 +- drivers/media/platform/exynos4-is/fimc-reg.c | 7 +-- drivers/media/platform/exynos4-is/media-dev.c | 4 +- drivers/media/platform/exynos4-is/media-dev.h | 8 ++-- include/media/s5p_fimc.h | 5 +++ 9 files changed, 55 insertions(+), 42 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index a8b9b06d96aa..b80ca59a099d 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -320,6 +320,7 @@ static void buffer_queue(struct vb2_buffer *vb); int fimc_capture_resume(struct fimc_dev *fimc) { struct fimc_vid_cap *vid_cap = &fimc->vid_cap; + struct exynos_video_entity *ve = &vid_cap->ve; struct fimc_vid_buffer *buf; int i; @@ -329,7 +330,7 @@ int fimc_capture_resume(struct fimc_dev *fimc) INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); vid_cap->buf_index = 0; fimc_pipeline_call(fimc, open, &fimc->pipeline, - &vid_cap->vfd.entity, false); + &ve->vdev.entity, false); fimc_capture_hw_init(fimc); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); @@ -397,7 +398,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = ctx->d_frame.payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(&ctx->fimc_dev->vid_cap.vfd, + v4l2_err(&ctx->fimc_dev->vid_cap.ve.vdev, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -415,6 +416,7 @@ static void buffer_queue(struct vb2_buffer *vb) struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_vid_cap *vid_cap = &fimc->vid_cap; + struct exynos_video_entity *ve = &vid_cap->ve; unsigned long flags; int min_bufs; @@ -454,7 +456,7 @@ static void buffer_queue(struct vb2_buffer *vb) ret = fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 1); if (ret < 0) - v4l2_err(&vid_cap->vfd, "stream on failed: %d\n", ret); + v4l2_err(&ve->vdev, "stream on failed: %d\n", ret); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -503,11 +505,12 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc); static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); + struct exynos_video_entity *ve = &fimc->vid_cap.ve; int ret = -EBUSY; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - fimc_md_graph_lock(fimc); + fimc_md_graph_lock(ve); mutex_lock(&fimc->lock); if (fimc_m2m_active(fimc)) @@ -526,7 +529,7 @@ static int fimc_capture_open(struct file *file) if (v4l2_fh_is_singular_file(file)) { ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, - &fimc->vid_cap.vfd.entity, true); + &fimc->vid_cap.ve.vdev.entity, true); if (!ret && !fimc->vid_cap.user_subdev_api) ret = fimc_capture_set_default_format(fimc); @@ -544,7 +547,7 @@ static int fimc_capture_open(struct file *file) } unlock: mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); + fimc_md_graph_unlock(ve); return ret; } @@ -560,7 +563,7 @@ static int fimc_capture_release(struct file *file) if (v4l2_fh_is_singular_file(file)) { if (vc->streaming) { - media_entity_pipeline_stop(&vc->vfd.entity); + media_entity_pipeline_stop(&vc->ve.vdev.entity); vc->streaming = false; } clear_bit(ST_CAPT_BUSY, &fimc->state); @@ -935,11 +938,12 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx = fimc->vid_cap.ctx; + struct exynos_video_entity *ve = &fimc->vid_cap.ve; struct v4l2_mbus_framefmt mf; struct fimc_fmt *ffmt = NULL; int ret = 0; - fimc_md_graph_lock(fimc); + fimc_md_graph_lock(ve); mutex_lock(&fimc->lock); if (fimc_jpeg_fourcc(pix->pixelformat)) { @@ -975,7 +979,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, pix->plane_fmt, ffmt->memplanes, true); unlock: mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); + fimc_md_graph_unlock(ve); return ret; } @@ -1076,7 +1080,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, struct fimc_dev *fimc = video_drvdata(file); int ret; - fimc_md_graph_lock(fimc); + fimc_md_graph_lock(&fimc->vid_cap.ve); mutex_lock(&fimc->lock); /* * The graph is walked within __fimc_capture_set_format() to set @@ -1088,8 +1092,8 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, */ ret = __fimc_capture_set_format(fimc, f); + fimc_md_graph_unlock(&fimc->vid_cap.ve); mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); return ret; } @@ -1209,7 +1213,7 @@ static int fimc_cap_streamon(struct file *file, void *priv, struct fimc_dev *fimc = video_drvdata(file); struct fimc_pipeline *p = &fimc->pipeline; struct fimc_vid_cap *vc = &fimc->vid_cap; - struct media_entity *entity = &vc->vfd.entity; + struct media_entity *entity = &vc->ve.vdev.entity; struct fimc_source_info *si = NULL; struct v4l2_subdev *sd; int ret; @@ -1259,14 +1263,15 @@ static int fimc_cap_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); + struct fimc_vid_cap *vc = &fimc->vid_cap; int ret; ret = vb2_ioctl_streamoff(file, priv, type); if (ret < 0) return ret; - media_entity_pipeline_stop(&fimc->vid_cap.vfd.entity); - fimc->vid_cap.streaming = false; + media_entity_pipeline_stop(&vc->ve.vdev.entity); + vc->streaming = false; return 0; } @@ -1735,7 +1740,7 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) static int fimc_register_capture_device(struct fimc_dev *fimc, struct v4l2_device *v4l2_dev) { - struct video_device *vfd = &fimc->vid_cap.vfd; + struct video_device *vfd = &fimc->vid_cap.ve.vdev; struct vb2_queue *q = &fimc->vid_cap.vbq; struct fimc_ctx *ctx; struct fimc_vid_cap *vid_cap; @@ -1840,15 +1845,17 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) { struct fimc_dev *fimc = v4l2_get_subdevdata(sd); + struct video_device *vdev; if (fimc == NULL) return; fimc_unregister_m2m_device(fimc); + vdev = &fimc->vid_cap.ve.vdev; - if (video_is_registered(&fimc->vid_cap.vfd)) { - video_unregister_device(&fimc->vid_cap.vfd); - media_entity_cleanup(&fimc->vid_cap.vfd.entity); + if (video_is_registered(vdev)) { + video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); fimc->pipeline_ops = NULL; } kfree(fimc->vid_cap.ctx); diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 539a3f71c16a..dfecef6bfefe 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -283,8 +283,8 @@ struct fimc_m2m_device { /** * struct fimc_vid_cap - camera capture device information * @ctx: hardware context data - * @vfd: video device node for camera capture mode * @subdev: subdev exposing the FIMC processing block + * @ve: exynos video device entity structure * @vd_pad: fimc video capture node pad * @sd_pads: fimc video processing block pads * @ci_fmt: image format at the FIMC camera input (and the scaler output) @@ -305,8 +305,8 @@ struct fimc_m2m_device { struct fimc_vid_cap { struct fimc_ctx *ctx; struct vb2_alloc_ctx *alloc_ctx; - struct video_device vfd; struct v4l2_subdev subdev; + struct exynos_video_entity ve; struct media_pad vd_pad; struct media_pad sd_pads[FIMC_SD_PADS_NUM]; struct v4l2_mbus_framefmt ci_fmt; diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c index 8cc0d39a2fea..eb4f7635f5e0 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c @@ -137,7 +137,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) } if (i == 0 && src_pixfmt_map[i][0] != pixelcode) { - v4l2_err(&dev->vfd, + v4l2_err(&dev->ve.vdev, "Unsupported pixel code, falling back to %#08x\n", src_pixfmt_map[i][0]); } diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 6daa88531e6e..64198b84f673 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -392,7 +392,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = fimc->payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(&fimc->vfd, + v4l2_err(&fimc->ve.vdev, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -458,7 +458,7 @@ static void fimc_lite_clear_event_counters(struct fimc_lite *fimc) static int fimc_lite_open(struct file *file) { struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *me = &fimc->vfd.entity; + struct media_entity *me = &fimc->ve.vdev.entity; int ret; mutex_lock(&me->parent->graph_mutex); @@ -509,7 +509,7 @@ static int fimc_lite_release(struct file *file) if (v4l2_fh_is_singular_file(file) && atomic_read(&fimc->out_path) == FIMC_IO_DMA) { if (fimc->streaming) { - media_entity_pipeline_stop(&fimc->vfd.entity); + media_entity_pipeline_stop(&fimc->ve.vdev.entity); fimc->streaming = false; } clear_bit(ST_FLITE_IN_USE, &fimc->state); @@ -792,7 +792,7 @@ static int fimc_lite_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *entity = &fimc->vfd.entity; + struct media_entity *entity = &fimc->ve.vdev.entity; struct fimc_pipeline *p = &fimc->pipeline; int ret; @@ -830,7 +830,7 @@ static int fimc_lite_streamoff(struct file *file, void *priv, if (ret < 0) return ret; - media_entity_pipeline_stop(&fimc->vfd.entity); + media_entity_pipeline_stop(&fimc->ve.vdev.entity); fimc->streaming = false; return 0; } @@ -1234,7 +1234,7 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) { struct fimc_lite *fimc = v4l2_get_subdevdata(sd); struct vb2_queue *q = &fimc->vb_queue; - struct video_device *vfd = &fimc->vfd; + struct video_device *vfd = &fimc->ve.vdev; int ret; memset(vfd, 0, sizeof(*vfd)); @@ -1298,9 +1298,9 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (fimc == NULL) return; - if (video_is_registered(&fimc->vfd)) { - video_unregister_device(&fimc->vfd); - media_entity_cleanup(&fimc->vfd.entity); + if (video_is_registered(&fimc->ve.vdev)) { + video_unregister_device(&fimc->ve.vdev); + media_entity_cleanup(&fimc->ve.vdev.entity); fimc->pipeline_ops = NULL; } } @@ -1548,7 +1548,7 @@ static int fimc_lite_resume(struct device *dev) INIT_LIST_HEAD(&fimc->active_buf_q); fimc_pipeline_call(fimc, open, &fimc->pipeline, - &fimc->vfd.entity, false); + &fimc->ve.vdev.entity, false); fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index 47da5e049247..fa3886a297ba 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -95,8 +95,8 @@ struct flite_buffer { * struct fimc_lite - fimc lite structure * @pdev: pointer to FIMC-LITE platform device * @dd: SoC specific driver data structure + * @ve: exynos video device entity structure * @v4l2_dev: pointer to top the level v4l2_device - * @vfd: video device node * @fh: v4l2 file handle * @alloc_ctx: videobuf2 memory allocator context * @subdev: FIMC-LITE subdev @@ -130,8 +130,8 @@ struct flite_buffer { struct fimc_lite { struct platform_device *pdev; struct flite_drvdata *dd; + struct exynos_video_entity ve; struct v4l2_device *v4l2_dev; - struct video_device vfd; struct v4l2_fh fh; struct vb2_alloc_ctx *alloc_ctx; struct v4l2_subdev subdev; diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c index f079f36099de..1db8cb4c46ef 100644 --- a/drivers/media/platform/exynos4-is/fimc-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-reg.c @@ -618,7 +618,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc, } if (i == ARRAY_SIZE(pix_desc)) { - v4l2_err(&vc->vfd, + v4l2_err(&vc->ve.vdev, "Camera color format not supported: %d\n", vc->ci_fmt.code); return -EINVAL; @@ -698,7 +698,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; break; default: - v4l2_err(&vid_cap->vfd, + v4l2_err(&vid_cap->ve.vdev, "Not supported camera pixel format: %#x\n", vid_cap->ci_fmt.code); return -EINVAL; @@ -721,7 +721,8 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, WARN_ONCE(1, "ISP Writeback input is not supported\n"); break; default: - v4l2_err(&vid_cap->vfd, "Invalid FIMC bus type selected: %d\n", + v4l2_err(&vid_cap->ve.vdev, + "Invalid FIMC bus type selected: %d\n", source->fimc_bus_type); return -EINVAL; } diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 396e06e14a17..c20b2728d55b 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -929,7 +929,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) continue; source = &fimc->subdev.entity; - sink = &fimc->vfd.entity; + sink = &fimc->ve.vdev.entity; /* FIMC-LITE's subdev and video node */ ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA, sink, 0, 0); @@ -1066,7 +1066,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) continue; source = &fmd->fimc[i]->vid_cap.subdev.entity; - sink = &fmd->fimc[i]->vid_cap.vfd.entity; + sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 44d86b61d660..3e9680c9de8b 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -127,14 +127,14 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) container_of(me->parent, struct fimc_md, media_dev); } -static inline void fimc_md_graph_lock(struct fimc_dev *fimc) +static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) { - mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); + mutex_lock(&ve->vdev.entity.parent->graph_mutex); } -static inline void fimc_md_graph_unlock(struct fimc_dev *fimc) +static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve) { - mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); + mutex_unlock(&ve->vdev.entity.parent->graph_mutex); } int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h index f50969025ef3..f5313b402eb7 100644 --- a/include/media/s5p_fimc.h +++ b/include/media/s5p_fimc.h @@ -13,6 +13,7 @@ #define S5P_FIMC_H_ #include +#include #include /* @@ -157,6 +158,10 @@ struct fimc_pipeline { struct media_pipeline *m_pipeline; }; +struct exynos_video_entity { + struct video_device vdev; +}; + /* * Media pipeline operations to be called from within the fimc(-lite) * video node when it is the last entity of the pipeline. Implemented -- GitLab From 4403106d5cfeb438b19e492e29537a00f9b5495a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:19 -0300 Subject: [PATCH 1032/2900] [media] exynos4-is: Preserve state of controls between /dev/video open/close This patch moves the code for inheriting subdev v4l2 controls on the FIMC video capture nodes from open()/close() fops to the link setup notification callback. This allows for the state of the FIMC controls to be always kept, in opposite to the current situation when it is lost when last process closes video device. There is no visible change for the original V4L2 compliant interface. For the MC aware applications (user_subdev_api == true) inheriting of the controls is dropped, since there can be same controls on the subdevs withing single pipeline, now when the ISP (FIMC-IS) is also used. This patch is a prerequisite to allow /dev/video device to be opened without errors even if there is no media links connecting it to an image source (sensor) subdev. This is required for a libv4l2 plugin to be initialized while a video node is opened and it also should be possible to always open the device to query the capabilities. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 96 +++++++++---------- drivers/media/platform/exynos4-is/fimc-core.h | 3 + drivers/media/platform/exynos4-is/media-dev.c | 4 - 3 files changed, 50 insertions(+), 53 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index b80ca59a099d..07089de6c669 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -27,9 +27,10 @@ #include #include -#include "media-dev.h" +#include "common.h" #include "fimc-core.h" #include "fimc-reg.h" +#include "media-dev.h" static int fimc_capture_hw_init(struct fimc_dev *fimc) { @@ -472,40 +473,13 @@ static struct vb2_ops fimc_capture_qops = { .stop_streaming = stop_streaming, }; -/** - * fimc_capture_ctrls_create - initialize the control handler - * Initialize the capture video node control handler and fill it - * with the FIMC controls. Inherit any sensor's controls if the - * 'user_subdev_api' flag is false (default behaviour). - * This function need to be called with the graph mutex held. - */ -int fimc_capture_ctrls_create(struct fimc_dev *fimc) -{ - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR]; - int ret; - - if (WARN_ON(vid_cap->ctx == NULL)) - return -ENXIO; - if (vid_cap->ctx->ctrls.ready) - return 0; - - ret = fimc_ctrls_create(vid_cap->ctx); - - if (ret || vid_cap->user_subdev_api || !sensor || - !vid_cap->ctx->ctrls.ready) - return ret; - - return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler, - sensor->ctrl_handler, NULL); -} - static int fimc_capture_set_default_format(struct fimc_dev *fimc); static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); - struct exynos_video_entity *ve = &fimc->vid_cap.ve; + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct exynos_video_entity *ve = &vc->ve; int ret = -EBUSY; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); @@ -530,12 +504,20 @@ static int fimc_capture_open(struct file *file) if (v4l2_fh_is_singular_file(file)) { ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, &fimc->vid_cap.ve.vdev.entity, true); - - if (!ret && !fimc->vid_cap.user_subdev_api) + if (ret == 0) ret = fimc_capture_set_default_format(fimc); - if (!ret) - ret = fimc_capture_ctrls_create(fimc); + if (ret == 0 && vc->user_subdev_api && vc->inh_sensor_ctrls) { + /* + * Recreate controls of the the video node to drop + * any controls inherited from the sensor subdev. + */ + fimc_ctrls_delete(vc->ctx); + + ret = fimc_ctrls_create(vc->ctx); + if (ret == 0) + vc->inh_sensor_ctrls = false; + } if (ret < 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); @@ -574,10 +556,6 @@ static int fimc_capture_release(struct file *file) } pm_runtime_put(&fimc->pdev->dev); - - if (v4l2_fh_is_singular_file(file)) - fimc_ctrls_delete(fimc->vid_cap.ctx); - ret = vb2_fop_release(file); mutex_unlock(&fimc->lock); @@ -1410,6 +1388,8 @@ static int fimc_link_setup(struct media_entity *entity, { struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); struct fimc_dev *fimc = v4l2_get_subdevdata(sd); + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct v4l2_subdev *sensor; if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) return -EINVAL; @@ -1421,15 +1401,26 @@ static int fimc_link_setup(struct media_entity *entity, local->entity->name, remote->entity->name, flags, fimc->vid_cap.input); - if (flags & MEDIA_LNK_FL_ENABLED) { - if (fimc->vid_cap.input != 0) - return -EBUSY; - fimc->vid_cap.input = sd->grp_id; + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + fimc->vid_cap.input = 0; return 0; } - fimc->vid_cap.input = 0; - return 0; + if (vc->input != 0) + return -EBUSY; + + vc->input = sd->grp_id; + + if (vc->user_subdev_api || vc->inh_sensor_ctrls) + return 0; + + /* Inherit V4L2 controls from the image sensor subdev. */ + sensor = fimc_find_remote_sensor(&vc->subdev.entity); + if (sensor == NULL) + return 0; + + return v4l2_ctrl_add_handler(&vc->ctx->ctrls.handler, + sensor->ctrl_handler, NULL); } static const struct media_entity_operations fimc_sd_media_ops = { @@ -1789,12 +1780,16 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ret = vb2_queue_init(q); if (ret) - goto err_ent; + goto err_free_ctx; vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); if (ret) - goto err_ent; + goto err_free_ctx; + + ret = fimc_ctrls_create(ctx); + if (ret) + goto err_me_cleanup; /* * For proper order of acquiring/releasing the video * and the graph mutex. @@ -1804,7 +1799,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) - goto err_vd; + goto err_ctrl_free; v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", vfd->name, video_device_node_name(vfd)); @@ -1812,9 +1807,11 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, vfd->ctrl_handler = &ctx->ctrls.handler; return 0; -err_vd: +err_ctrl_free: + fimc_ctrls_delete(ctx); +err_me_cleanup: media_entity_cleanup(&vfd->entity); -err_ent: +err_free_ctx: kfree(ctx); return ret; } @@ -1856,6 +1853,7 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) if (video_is_registered(vdev)) { video_unregister_device(vdev); media_entity_cleanup(&vdev->entity); + fimc_ctrls_delete(fimc->vid_cap.ctx); fimc->pipeline_ops = NULL; } kfree(fimc->vid_cap.ctx); diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index dfecef6bfefe..61c0c83cc5b7 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -301,6 +301,8 @@ struct fimc_m2m_device { * @refcnt: driver's private reference counter * @input: capture input type, grp_id of the attached subdev * @user_subdev_api: true if subdevs are not configured by the host driver + * @inh_sensor_ctrls: a flag indicating v4l2 controls are inherited from + * an image sensor subdev */ struct fimc_vid_cap { struct fimc_ctx *ctx; @@ -324,6 +326,7 @@ struct fimc_vid_cap { int refcnt; u32 input; bool user_subdev_api; + bool inh_sensor_ctrls; }; /** diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index c20b2728d55b..7a562d289977 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1272,8 +1272,6 @@ static int fimc_md_link_notify(struct media_pad *source, if (!(flags & MEDIA_LNK_FL_ENABLED)) { if (ref_count > 0) { ret = __fimc_pipeline_close(pipeline); - if (!ret && fimc) - fimc_ctrls_delete(fimc->vid_cap.ctx); } for (i = 0; i < IDX_MAX; i++) pipeline->subdevs[i] = NULL; @@ -1285,8 +1283,6 @@ static int fimc_md_link_notify(struct media_pad *source, */ ret = __fimc_pipeline_open(pipeline, source->entity, true); - if (!ret && fimc) - ret = fimc_capture_ctrls_create(fimc); } mutex_unlock(lock); -- GitLab From 42625fdfbd608f0bdaffaf25e8eb32ef55cddf96 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:20 -0300 Subject: [PATCH 1033/2900] [media] exynos4-is: Media graph/video device locking rework Remove driver private video node reference counters and use entity->use_count instead. This makes the video pipelines power handling more similar to the method used in omap3isp driver. Now the graph mutex is taken always after the video mutex, as it is not possible to ensure apposite order at the all modules. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 59 ++++++++----------- drivers/media/platform/exynos4-is/fimc-core.h | 2 - drivers/media/platform/exynos4-is/fimc-lite.c | 23 +++++--- drivers/media/platform/exynos4-is/fimc-lite.h | 2 - drivers/media/platform/exynos4-is/media-dev.c | 12 +--- 5 files changed, 42 insertions(+), 56 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 07089de6c669..b6055d2b09d6 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -484,7 +484,6 @@ static int fimc_capture_open(struct file *file) dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - fimc_md_graph_lock(ve); mutex_lock(&fimc->lock); if (fimc_m2m_active(fimc)) @@ -502,6 +501,8 @@ static int fimc_capture_open(struct file *file) } if (v4l2_fh_is_singular_file(file)) { + fimc_md_graph_lock(ve); + ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, &fimc->vid_cap.ve.vdev.entity, true); if (ret == 0) @@ -518,18 +519,19 @@ static int fimc_capture_open(struct file *file) if (ret == 0) vc->inh_sensor_ctrls = false; } + if (ret == 0) + ve->vdev.entity.use_count++; + + fimc_md_graph_unlock(ve); if (ret < 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_put_sync(&fimc->pdev->dev); v4l2_fh_release(file); - } else { - fimc->vid_cap.refcnt++; } } unlock: mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(ve); return ret; } @@ -537,26 +539,32 @@ static int fimc_capture_release(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_vid_cap *vc = &fimc->vid_cap; + bool close = v4l2_fh_is_singular_file(file); int ret; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); mutex_lock(&fimc->lock); - if (v4l2_fh_is_singular_file(file)) { - if (vc->streaming) { - media_entity_pipeline_stop(&vc->ve.vdev.entity); - vc->streaming = false; - } + if (close && vc->streaming) { + media_entity_pipeline_stop(&vc->ve.vdev.entity); + vc->streaming = false; + } + + ret = vb2_fop_release(file); + + if (close) { clear_bit(ST_CAPT_BUSY, &fimc->state); fimc_stop_capture(fimc, false); fimc_pipeline_call(fimc, close, &fimc->pipeline); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - fimc->vid_cap.refcnt--; + + fimc_md_graph_lock(&vc->ve); + vc->ve.vdev.entity.use_count--; + fimc_md_graph_unlock(&vc->ve); } pm_runtime_put(&fimc->pdev->dev); - ret = vb2_fop_release(file); mutex_unlock(&fimc->lock); return ret; @@ -921,9 +929,6 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, struct fimc_fmt *ffmt = NULL; int ret = 0; - fimc_md_graph_lock(ve); - mutex_lock(&fimc->lock); - if (fimc_jpeg_fourcc(pix->pixelformat)) { fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, @@ -934,16 +939,18 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SOURCE); - if (!ffmt) { - ret = -EINVAL; - goto unlock; - } + if (!ffmt) + return -EINVAL; if (!fimc->vid_cap.user_subdev_api) { mf.width = pix->width; mf.height = pix->height; mf.code = ffmt->mbus_code; + + fimc_md_graph_lock(ve); fimc_pipeline_try_format(ctx, &mf, &ffmt, false); + fimc_md_graph_unlock(ve); + pix->width = mf.width; pix->height = mf.height; if (ffmt) @@ -955,9 +962,6 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, if (ffmt->flags & FMT_FLAGS_COMPRESSED) fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], pix->plane_fmt, ffmt->memplanes, true); -unlock: - mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(ve); return ret; } @@ -1059,19 +1063,14 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, int ret; fimc_md_graph_lock(&fimc->vid_cap.ve); - mutex_lock(&fimc->lock); /* * The graph is walked within __fimc_capture_set_format() to set * the format at subdevs thus the graph mutex needs to be held at - * this point and acquired before the video mutex, to avoid AB-BA - * deadlock when fimc_md_link_notify() is called by other thread. - * Ideally the graph walking and setting format at the whole pipeline - * should be removed from this driver and handled in userspace only. + * this point. */ ret = __fimc_capture_set_format(fimc, f); fimc_md_graph_unlock(&fimc->vid_cap.ve); - mutex_unlock(&fimc->lock); return ret; } @@ -1790,12 +1789,6 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ret = fimc_ctrls_create(ctx); if (ret) goto err_me_cleanup; - /* - * For proper order of acquiring/releasing the video - * and the graph mutex. - */ - v4l2_disable_ioctl_locking(vfd, VIDIOC_TRY_FMT); - v4l2_disable_ioctl_locking(vfd, VIDIOC_S_FMT); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 61c0c83cc5b7..e3da4ffd7a5e 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -298,7 +298,6 @@ struct fimc_m2m_device { * @frame_count: the frame counter for statistics * @reqbufs_count: the number of buffers requested in REQBUFS ioctl * @input_index: input (camera sensor) index - * @refcnt: driver's private reference counter * @input: capture input type, grp_id of the attached subdev * @user_subdev_api: true if subdevs are not configured by the host driver * @inh_sensor_ctrls: a flag indicating v4l2 controls are inherited from @@ -323,7 +322,6 @@ struct fimc_vid_cap { unsigned int reqbufs_count; bool streaming; int input_index; - int refcnt; u32 input; bool user_subdev_api; bool inh_sensor_ctrls; diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 64198b84f673..0f372bfffaf0 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -461,8 +461,6 @@ static int fimc_lite_open(struct file *file) struct media_entity *me = &fimc->ve.vdev.entity; int ret; - mutex_lock(&me->parent->graph_mutex); - mutex_lock(&fimc->lock); if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) { ret = -EBUSY; @@ -482,11 +480,19 @@ static int fimc_lite_open(struct file *file) atomic_read(&fimc->out_path) != FIMC_IO_DMA) goto unlock; + mutex_lock(&me->parent->graph_mutex); + ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, me, true); + + /* Mark video pipeline ending at this video node as in use. */ + if (ret == 0) + me->use_count++; + + mutex_unlock(&me->parent->graph_mutex); + if (!ret) { fimc_lite_clear_event_counters(fimc); - fimc->ref_count++; goto unlock; } @@ -496,26 +502,28 @@ static int fimc_lite_open(struct file *file) clear_bit(ST_FLITE_IN_USE, &fimc->state); unlock: mutex_unlock(&fimc->lock); - mutex_unlock(&me->parent->graph_mutex); return ret; } static int fimc_lite_release(struct file *file) { struct fimc_lite *fimc = video_drvdata(file); + struct media_entity *entity = &fimc->ve.vdev.entity; mutex_lock(&fimc->lock); if (v4l2_fh_is_singular_file(file) && atomic_read(&fimc->out_path) == FIMC_IO_DMA) { if (fimc->streaming) { - media_entity_pipeline_stop(&fimc->ve.vdev.entity); + media_entity_pipeline_stop(entity); fimc->streaming = false; } clear_bit(ST_FLITE_IN_USE, &fimc->state); fimc_lite_stop_capture(fimc, false); fimc_pipeline_call(fimc, close, &fimc->pipeline); - fimc->ref_count--; + mutex_lock(&entity->parent->graph_mutex); + entity->use_count--; + mutex_unlock(&entity->parent->graph_mutex); } vb2_fop_release(file); @@ -954,8 +962,6 @@ static int fimc_lite_link_setup(struct media_entity *entity, __func__, remote->entity->name, local->entity->name, flags, fimc->source_subdev_grp_id); - mutex_lock(&fimc->lock); - switch (local->index) { case FLITE_SD_PAD_SINK: if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) { @@ -997,7 +1003,6 @@ static int fimc_lite_link_setup(struct media_entity *entity, } mb(); - mutex_unlock(&fimc->lock); return ret; } diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index fa3886a297ba..25abba98d7e9 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -125,7 +125,6 @@ struct flite_buffer { * @active_buf_count: number of video buffers scheduled in hardware * @frame_count: the captured frames counter * @reqbufs_count: the number of buffers requested with REQBUFS ioctl - * @ref_count: driver's private reference counter */ struct fimc_lite { struct platform_device *pdev; @@ -163,7 +162,6 @@ struct fimc_lite { struct vb2_queue vb_queue; unsigned int frame_count; unsigned int reqbufs_count; - int ref_count; struct fimc_lite_events events; bool streaming; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 7a562d289977..1b4bb25d0a55 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1238,9 +1238,7 @@ static int fimc_md_link_notify(struct media_pad *source, struct fimc_dev *fimc = NULL; struct fimc_pipeline *pipeline; struct v4l2_subdev *sd; - struct mutex *lock; int i, ret = 0; - int ref_count; if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) return 0; @@ -1253,29 +1251,24 @@ static int fimc_md_link_notify(struct media_pad *source, if (WARN_ON(fimc_lite == NULL)) return 0; pipeline = &fimc_lite->pipeline; - lock = &fimc_lite->lock; break; case GRP_ID_FIMC: fimc = v4l2_get_subdevdata(sd); if (WARN_ON(fimc == NULL)) return 0; pipeline = &fimc->pipeline; - lock = &fimc->lock; break; default: return 0; } - mutex_lock(lock); - ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count; - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - if (ref_count > 0) { + if (sink->entity->use_count > 0) { ret = __fimc_pipeline_close(pipeline); } for (i = 0; i < IDX_MAX; i++) pipeline->subdevs[i] = NULL; - } else if (ref_count > 0) { + } else if (sink->entity->use_count > 0) { /* * Link activation. Enable power of pipeline elements only if * the pipeline is already in use, i.e. its video node is open. @@ -1285,7 +1278,6 @@ static int fimc_md_link_notify(struct media_pad *source, source->entity, true); } - mutex_unlock(lock); return ret ? -EPIPE : ret; } -- GitLab From 4bd728a16ee8212e3e468dabb737fe9ef5cea83d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:21 -0300 Subject: [PATCH 1034/2900] [media] exynos4-is: Do not use asynchronous runtime PM in release fop Use pm_runtime_put_sync() instead of pm_runtime_put() to avoid races in handling the 'state' bit flags when the fimc-capture drivers' runtime_resume callback is called from the PM workqueue. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-capture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index b6055d2b09d6..b2f9581f1a8a 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -496,7 +496,7 @@ static int fimc_capture_open(struct file *file) ret = v4l2_fh_open(file); if (ret) { - pm_runtime_put(&fimc->pdev->dev); + pm_runtime_put_sync(&fimc->pdev->dev); goto unlock; } @@ -564,7 +564,7 @@ static int fimc_capture_release(struct file *file) fimc_md_graph_unlock(&vc->ve); } - pm_runtime_put(&fimc->pdev->dev); + pm_runtime_put_sync(&fimc->pdev->dev); mutex_unlock(&fimc->lock); return ret; -- GitLab From 403dfbec45419c1838e0ea3be16625986ec17cfd Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:22 -0300 Subject: [PATCH 1035/2900] [media] exynos4-is: Use common exynos_media_pipeline data structure This enumeration is now private to exynos4-is and the exynos5 camera subsystem driver may have the subdevs handling designed differently. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 67 ++++++----- drivers/media/platform/exynos4-is/fimc-core.h | 2 - drivers/media/platform/exynos4-is/fimc-lite.c | 29 +++-- drivers/media/platform/exynos4-is/fimc-lite.h | 2 - drivers/media/platform/exynos4-is/media-dev.c | 110 +++++++++++------- drivers/media/platform/exynos4-is/media-dev.h | 38 ++++++ include/media/s5p_fimc.h | 53 +++++---- 7 files changed, 187 insertions(+), 114 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index b2f9581f1a8a..33c6a2f0ad74 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -120,8 +120,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) spin_unlock_irqrestore(&fimc->slock, flags); if (streaming) - return fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 0); + return fimc_pipeline_call(&cap->ve, set_stream, 0); else return 0; } @@ -179,8 +178,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx) void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) { - struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS]; struct fimc_vid_cap *cap = &fimc->vid_cap; + struct fimc_pipeline *p = to_fimc_pipeline(cap->ve.pipe); + struct v4l2_subdev *csis = p->subdevs[IDX_CSIS]; struct fimc_frame *f = &cap->ctx->d_frame; struct fimc_vid_buffer *v_buf; struct timeval *tv; @@ -288,8 +288,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) fimc_activate_capture(ctx); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - return fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + return fimc_pipeline_call(&vid_cap->ve, set_stream, 1); } return 0; @@ -313,7 +312,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc) int ret = fimc_stop_capture(fimc, suspend); if (ret) return ret; - return fimc_pipeline_call(fimc, close, &fimc->pipeline); + return fimc_pipeline_call(&fimc->vid_cap.ve, close); } static void buffer_queue(struct vb2_buffer *vb); @@ -330,8 +329,7 @@ int fimc_capture_resume(struct fimc_dev *fimc) INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); vid_cap->buf_index = 0; - fimc_pipeline_call(fimc, open, &fimc->pipeline, - &ve->vdev.entity, false); + fimc_pipeline_call(ve, open, &ve->vdev.entity, false); fimc_capture_hw_init(fimc); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); @@ -455,7 +453,7 @@ static void buffer_queue(struct vb2_buffer *vb) if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) return; - ret = fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 1); + ret = fimc_pipeline_call(ve, set_stream, 1); if (ret < 0) v4l2_err(&ve->vdev, "stream on failed: %d\n", ret); return; @@ -503,8 +501,8 @@ static int fimc_capture_open(struct file *file) if (v4l2_fh_is_singular_file(file)) { fimc_md_graph_lock(ve); - ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, - &fimc->vid_cap.ve.vdev.entity, true); + ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true); + if (ret == 0) ret = fimc_capture_set_default_format(fimc); @@ -555,8 +553,7 @@ static int fimc_capture_release(struct file *file) if (close) { clear_bit(ST_CAPT_BUSY, &fimc->state); - fimc_stop_capture(fimc, false); - fimc_pipeline_call(fimc, close, &fimc->pipeline); + fimc_pipeline_call(&vc->ve, close); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); fimc_md_graph_lock(&vc->ve); @@ -786,7 +783,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, bool set) { struct fimc_dev *fimc = ctx->fimc_dev; - struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; + struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe); + struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR]; struct v4l2_subdev_format sfmt; struct v4l2_mbus_framefmt *mf = &sfmt.format; struct media_entity *me; @@ -926,6 +924,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct exynos_video_entity *ve = &fimc->vid_cap.ve; struct v4l2_mbus_framefmt mf; + struct v4l2_subdev *sensor; struct fimc_fmt *ffmt = NULL; int ret = 0; @@ -959,9 +958,18 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); - if (ffmt->flags & FMT_FLAGS_COMPRESSED) - fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], - pix->plane_fmt, ffmt->memplanes, true); + if (ffmt->flags & FMT_FLAGS_COMPRESSED) { + fimc_md_graph_lock(ve); + + sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); + if (sensor) + fimc_get_sensor_frame_desc(sensor, pix->plane_fmt, + ffmt->memplanes, true); + else + ret = -EPIPE; + + fimc_md_graph_unlock(ve); + } return ret; } @@ -986,6 +994,7 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc, struct fimc_ctx *ctx = fimc->vid_cap.ctx; struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt; + struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe); struct fimc_frame *ff = &ctx->d_frame; struct fimc_fmt *s_fmt = NULL; int ret, i; @@ -1027,7 +1036,7 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc, fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) { - ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], + ret = fimc_get_sensor_frame_desc(p->subdevs[IDX_SENSOR], pix->plane_fmt, ff->fmt->memplanes, true); if (ret < 0) @@ -1078,14 +1087,20 @@ static int fimc_cap_enum_input(struct file *file, void *priv, struct v4l2_input *i) { struct fimc_dev *fimc = video_drvdata(file); - struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; + struct exynos_video_entity *ve = &fimc->vid_cap.ve; + struct v4l2_subdev *sd; if (i->index != 0) return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; + fimc_md_graph_lock(ve); + sd = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); + fimc_md_graph_unlock(ve); + if (sd) strlcpy(i->name, sd->name, sizeof(i->name)); + return 0; } @@ -1111,6 +1126,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) struct v4l2_subdev_format sink_fmt, src_fmt; struct fimc_vid_cap *vc = &fimc->vid_cap; struct v4l2_subdev *sd = &vc->subdev; + struct fimc_pipeline *p = to_fimc_pipeline(vc->ve.pipe); struct media_pad *sink_pad, *src_pad; int i, ret; @@ -1164,7 +1180,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) src_fmt.format.code != sink_fmt.format.code) return -EPIPE; - if (sd == fimc->pipeline.subdevs[IDX_SENSOR] && + if (sd == p->subdevs[IDX_SENSOR] && fimc_user_defined_mbus_fmt(src_fmt.format.code)) { struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES]; struct fimc_frame *frame = &vc->ctx->d_frame; @@ -1188,7 +1204,6 @@ static int fimc_cap_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); - struct fimc_pipeline *p = &fimc->pipeline; struct fimc_vid_cap *vc = &fimc->vid_cap; struct media_entity *entity = &vc->ve.vdev.entity; struct fimc_source_info *si = NULL; @@ -1198,11 +1213,11 @@ static int fimc_cap_streamon(struct file *file, void *priv, if (fimc_capture_active(fimc)) return -EBUSY; - ret = media_entity_pipeline_start(entity, p->m_pipeline); + ret = media_entity_pipeline_start(entity, &vc->ve.pipe->mp); if (ret < 0) return ret; - sd = p->subdevs[IDX_SENSOR]; + sd = __fimc_md_get_subdev(vc->ve.pipe, IDX_SENSOR); if (sd) si = v4l2_get_subdev_hostdata(sd); @@ -1821,12 +1836,12 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) if (ret) return ret; - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); + fimc->vid_cap.ve.pipe = v4l2_get_subdev_hostdata(sd); ret = fimc_register_capture_device(fimc, sd->v4l2_dev); if (ret) { fimc_unregister_m2m_device(fimc); - fimc->pipeline_ops = NULL; + fimc->vid_cap.ve.pipe = NULL; } return ret; @@ -1847,7 +1862,7 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) video_unregister_device(vdev); media_entity_cleanup(&vdev->entity); fimc_ctrls_delete(fimc->vid_cap.ctx); - fimc->pipeline_ops = NULL; + fimc->vid_cap.ve.pipe = NULL; } kfree(fimc->vid_cap.ctx); fimc->vid_cap.ctx = NULL; diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index e3da4ffd7a5e..c48a79254d83 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -435,8 +435,6 @@ struct fimc_dev { struct fimc_vid_cap vid_cap; unsigned long state; struct vb2_alloc_ctx *alloc_ctx; - struct fimc_pipeline pipeline; - const struct fimc_pipeline_ops *pipeline_ops; }; /** diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 0f372bfffaf0..24e2a0f8797a 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -210,7 +210,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) if (!streaming) return 0; - return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0); + return fimc_pipeline_call(&fimc->ve, set_stream, 0); } static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend) @@ -324,8 +324,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) flite_hw_capture_start(fimc); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + fimc_pipeline_call(&fimc->ve, set_stream, 1); } if (debug > 0) flite_hw_dump_regs(fimc, __func__); @@ -429,8 +428,7 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + fimc_pipeline_call(&fimc->ve, set_stream, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -482,8 +480,7 @@ static int fimc_lite_open(struct file *file) mutex_lock(&me->parent->graph_mutex); - ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, - me, true); + ret = fimc_pipeline_call(&fimc->ve, open, me, true); /* Mark video pipeline ending at this video node as in use. */ if (ret == 0) @@ -518,9 +515,10 @@ static int fimc_lite_release(struct file *file) media_entity_pipeline_stop(entity); fimc->streaming = false; } - clear_bit(ST_FLITE_IN_USE, &fimc->state); fimc_lite_stop_capture(fimc, false); - fimc_pipeline_call(fimc, close, &fimc->pipeline); + fimc_pipeline_call(&fimc->ve, close); + clear_bit(ST_FLITE_IN_USE, &fimc->state); + mutex_lock(&entity->parent->graph_mutex); entity->use_count--; mutex_unlock(&entity->parent->graph_mutex); @@ -801,13 +799,12 @@ static int fimc_lite_streamon(struct file *file, void *priv, { struct fimc_lite *fimc = video_drvdata(file); struct media_entity *entity = &fimc->ve.vdev.entity; - struct fimc_pipeline *p = &fimc->pipeline; int ret; if (fimc_lite_active(fimc)) return -EBUSY; - ret = media_entity_pipeline_start(entity, p->m_pipeline); + ret = media_entity_pipeline_start(entity, &fimc->ve.pipe->mp); if (ret < 0) return ret; @@ -1282,12 +1279,12 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) return ret; video_set_drvdata(vfd, fimc); - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); + fimc->ve.pipe = v4l2_get_subdev_hostdata(sd); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret < 0) { media_entity_cleanup(&vfd->entity); - fimc->pipeline_ops = NULL; + fimc->ve.pipe = NULL; return ret; } @@ -1306,7 +1303,7 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (video_is_registered(&fimc->ve.vdev)) { video_unregister_device(&fimc->ve.vdev); media_entity_cleanup(&fimc->ve.vdev.entity); - fimc->pipeline_ops = NULL; + fimc->ve.pipe = NULL; } } @@ -1552,7 +1549,7 @@ static int fimc_lite_resume(struct device *dev) return 0; INIT_LIST_HEAD(&fimc->active_buf_q); - fimc_pipeline_call(fimc, open, &fimc->pipeline, + fimc_pipeline_call(&fimc->ve, open, &fimc->ve.vdev.entity, false); fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); @@ -1579,7 +1576,7 @@ static int fimc_lite_suspend(struct device *dev) if (ret < 0 || !fimc_lite_active(fimc)) return ret; - return fimc_pipeline_call(fimc, close, &fimc->pipeline); + return fimc_pipeline_call(&fimc->ve, close); } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index 25abba98d7e9..c7aa08477830 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -140,8 +140,6 @@ struct fimc_lite { struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *test_pattern; int index; - struct fimc_pipeline pipeline; - const struct fimc_pipeline_ops *pipeline_ops; struct mutex lock; spinlock_t slock; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 1b4bb25d0a55..2020e44f63b1 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -46,7 +46,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, * Caller holds the graph mutex. */ static void fimc_pipeline_prepare(struct fimc_pipeline *p, - struct media_entity *me) + struct media_entity *me) { struct v4l2_subdev *sd; int i; @@ -168,10 +168,11 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on) * * Called with the graph mutex held. */ -static int __fimc_pipeline_open(struct fimc_pipeline *p, +static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, struct media_entity *me, bool prepare) { struct fimc_md *fmd = entity_to_fimc_mdev(me); + struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd; int ret; @@ -214,8 +215,9 @@ static int __fimc_pipeline_open(struct fimc_pipeline *p, * * Disable power of all subdevs and turn the external sensor clock off. */ -static int __fimc_pipeline_close(struct fimc_pipeline *p) +static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) { + struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL; struct fimc_md *fmd; int ret = 0; @@ -242,12 +244,13 @@ static int __fimc_pipeline_close(struct fimc_pipeline *p) * @pipeline: video pipeline structure * @on: passed as the s_stream() callback argument */ -static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) +static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) { static const u8 seq[2][IDX_MAX] = { { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE }, { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, }; + struct fimc_pipeline *p = to_fimc_pipeline(ep); int i, ret = 0; if (p->subdevs[IDX_SENSOR] == NULL) @@ -271,12 +274,38 @@ static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) } /* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ -static const struct fimc_pipeline_ops fimc_pipeline_ops = { +static const struct exynos_media_pipeline_ops fimc_pipeline_ops = { .open = __fimc_pipeline_open, .close = __fimc_pipeline_close, .set_stream = __fimc_pipeline_s_stream, }; +static struct exynos_media_pipeline *fimc_md_pipeline_create( + struct fimc_md *fmd) +{ + struct fimc_pipeline *p; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + + list_add_tail(&p->list, &fmd->pipelines); + + p->ep.ops = &fimc_pipeline_ops; + return &p->ep; +} + +static void fimc_md_pipelines_free(struct fimc_md *fmd) +{ + while (!list_empty(&fmd->pipelines)) { + struct fimc_pipeline *p; + + p = list_entry(fmd->pipelines.next, typeof(*p), list); + list_del(&p->list); + kfree(p); + } +} + /* * Sensor subdevice helper functions */ @@ -592,6 +621,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, struct fimc_lite *fimc_lite) { struct v4l2_subdev *sd; + struct exynos_media_pipeline *ep; int ret; if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS || @@ -600,7 +630,12 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, sd = &fimc_lite->subdev; sd->grp_id = GRP_ID_FLITE; - v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); + + ep = fimc_md_pipeline_create(fmd); + if (!ep) + return -ENOMEM; + + v4l2_set_subdev_hostdata(sd, ep); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (!ret) @@ -614,6 +649,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) { struct v4l2_subdev *sd; + struct exynos_media_pipeline *ep; int ret; if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id])) @@ -621,7 +657,12 @@ static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) sd = &fimc->vid_cap.subdev; sd->grp_id = GRP_ID_FIMC; - v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); + + ep = fimc_md_pipeline_create(fmd); + if (!ep) + return -ENOMEM; + + v4l2_set_subdev_hostdata(sd, ep); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (!ret) { @@ -797,17 +838,19 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) int i; for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (fmd->fimc[i] == NULL) + struct fimc_dev *dev = fmd->fimc[i]; + if (dev == NULL) continue; - v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); - fmd->fimc[i]->pipeline_ops = NULL; + v4l2_device_unregister_subdev(&dev->vid_cap.subdev); + dev->vid_cap.ve.pipe = NULL; fmd->fimc[i] = NULL; } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { - if (fmd->fimc_lite[i] == NULL) + struct fimc_lite *dev = fmd->fimc_lite[i]; + if (dev == NULL) continue; - v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); - fmd->fimc_lite[i]->pipeline_ops = NULL; + v4l2_device_unregister_subdev(&dev->subdev); + dev->ve.pipe = NULL; fmd->fimc_lite[i] = NULL; } for (i = 0; i < CSIS_MAX_ENTITIES; i++) { @@ -1234,38 +1277,22 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) static int fimc_md_link_notify(struct media_pad *source, struct media_pad *sink, u32 flags) { - struct fimc_lite *fimc_lite = NULL; - struct fimc_dev *fimc = NULL; + struct exynos_video_entity *ve; + struct video_device *vdev; struct fimc_pipeline *pipeline; - struct v4l2_subdev *sd; int i, ret = 0; - if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + if (media_entity_type(sink->entity) != MEDIA_ENT_T_DEVNODE_V4L) return 0; - sd = media_entity_to_v4l2_subdev(sink->entity); - - switch (sd->grp_id) { - case GRP_ID_FLITE: - fimc_lite = v4l2_get_subdevdata(sd); - if (WARN_ON(fimc_lite == NULL)) - return 0; - pipeline = &fimc_lite->pipeline; - break; - case GRP_ID_FIMC: - fimc = v4l2_get_subdevdata(sd); - if (WARN_ON(fimc == NULL)) - return 0; - pipeline = &fimc->pipeline; - break; - default: - return 0; - } + vdev = media_entity_to_video_device(sink->entity); + ve = vdev_to_exynos_video_entity(vdev); + pipeline = to_fimc_pipeline(ve->pipe); + + if (!(flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) { + if (sink->entity->use_count > 0) + ret = __fimc_pipeline_close(ve->pipe); - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - if (sink->entity->use_count > 0) { - ret = __fimc_pipeline_close(pipeline); - } for (i = 0; i < IDX_MAX; i++) pipeline->subdevs[i] = NULL; } else if (sink->entity->use_count > 0) { @@ -1274,8 +1301,7 @@ static int fimc_md_link_notify(struct media_pad *source, * the pipeline is already in use, i.e. its video node is open. * Recreate the controls destroyed during the link deactivation. */ - ret = __fimc_pipeline_open(pipeline, - source->entity, true); + ret = __fimc_pipeline_open(ve->pipe, sink->entity, true); } return ret ? -EPIPE : ret; @@ -1358,6 +1384,7 @@ static int fimc_md_probe(struct platform_device *pdev) spin_lock_init(&fmd->slock); fmd->pdev = pdev; + INIT_LIST_HEAD(&fmd->pipelines); strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", sizeof(fmd->media_dev.model)); @@ -1445,6 +1472,7 @@ static int fimc_md_remove(struct platform_device *pdev) return 0; device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); fimc_md_unregister_entities(fmd); + fimc_md_pipelines_free(fmd); media_device_unregister(&fmd->media_dev); fimc_md_put_clocks(fmd); return 0; diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 3e9680c9de8b..a704eea2cfbd 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "fimc-core.h" #include "fimc-lite.h" @@ -40,6 +41,29 @@ enum { FIMC_MAX_WBCLKS }; +enum fimc_subdev_index { + IDX_SENSOR, + IDX_CSIS, + IDX_FLITE, + IDX_IS_ISP, + IDX_FIMC, + IDX_MAX, +}; + +/* + * This structure represents a chain of media entities, including a data + * source entity (e.g. an image sensor subdevice), a data capture entity + * - a video capture device node and any remaining entities. + */ +struct fimc_pipeline { + struct exynos_media_pipeline ep; + struct list_head list; + struct media_entity *vdev_entity; + struct v4l2_subdev *subdevs[IDX_MAX]; +}; + +#define to_fimc_pipeline(_ep) container_of(_ep, struct fimc_pipeline, ep) + struct fimc_csis_info { struct v4l2_subdev *sd; int id; @@ -104,7 +128,9 @@ struct fimc_md { struct pinctrl_state *state_idle; } pinctl; bool user_subdev_api; + spinlock_t slock; + struct list_head pipelines; }; #define is_subdev_pad(pad) (pad == NULL || \ @@ -149,4 +175,16 @@ static inline bool fimc_md_is_isp_available(struct device_node *node) #define fimc_md_is_isp_available(node) (false) #endif /* CONFIG_OF */ +static inline struct v4l2_subdev *__fimc_md_get_subdev( + struct exynos_media_pipeline *ep, + unsigned int index) +{ + struct fimc_pipeline *p = to_fimc_pipeline(ep); + + if (!p || index >= IDX_MAX) + return NULL; + else + return p->subdevs[index]; +} + #endif diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h index f5313b402eb7..0afadb663bbd 100644 --- a/include/media/s5p_fimc.h +++ b/include/media/s5p_fimc.h @@ -141,41 +141,40 @@ struct fimc_fmt { #define FMT_FLAGS_YUV (1 << 7) }; -enum fimc_subdev_index { - IDX_SENSOR, - IDX_CSIS, - IDX_FLITE, - IDX_IS_ISP, - IDX_FIMC, - IDX_MAX, -}; - -struct media_pipeline; -struct v4l2_subdev; +struct exynos_media_pipeline; -struct fimc_pipeline { - struct v4l2_subdev *subdevs[IDX_MAX]; - struct media_pipeline *m_pipeline; +/* + * Media pipeline operations to be called from within a video node, i.e. the + * last entity within the pipeline. Implemented by related media device driver. + */ +struct exynos_media_pipeline_ops { + int (*prepare)(struct exynos_media_pipeline *p, + struct media_entity *me); + int (*unprepare)(struct exynos_media_pipeline *p); + int (*open)(struct exynos_media_pipeline *p, struct media_entity *me, + bool resume); + int (*close)(struct exynos_media_pipeline *p); + int (*set_stream)(struct exynos_media_pipeline *p, bool state); }; struct exynos_video_entity { struct video_device vdev; + struct exynos_media_pipeline *pipe; }; -/* - * Media pipeline operations to be called from within the fimc(-lite) - * video node when it is the last entity of the pipeline. Implemented - * by corresponding media device driver. - */ -struct fimc_pipeline_ops { - int (*open)(struct fimc_pipeline *p, struct media_entity *me, - bool resume); - int (*close)(struct fimc_pipeline *p); - int (*set_stream)(struct fimc_pipeline *p, bool state); +struct exynos_media_pipeline { + struct media_pipeline mp; + const struct exynos_media_pipeline_ops *ops; }; -#define fimc_pipeline_call(f, op, p, args...) \ - (!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \ - (f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD)) +static inline struct exynos_video_entity *vdev_to_exynos_video_entity( + struct video_device *vdev) +{ + return container_of(vdev, struct exynos_video_entity, vdev); +} + +#define fimc_pipeline_call(ent, op, args...) \ + (!(ent) ? -ENOENT : (((ent)->pipe->ops && (ent)->pipe->ops->op) ? \ + (ent)->pipe->ops->op(((ent)->pipe), ##args) : -ENOIOCTLCMD)) \ #endif /* S5P_FIMC_H_ */ -- GitLab From 36da6fcdc52eae6f06f6a3fde9f8395187222162 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:23 -0300 Subject: [PATCH 1036/2900] [media] exynos4-is: Remove WARN_ON() from __fimc_pipeline_close() It's not a critical error to call __fimc_pipeline_close() with missing sensor subdev entity. Replace WARN_ON() with pr_warn() and return 0 instead of -EINVAL to fix control flow in some conditions. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 2020e44f63b1..5b307f26f995 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -220,16 +220,16 @@ static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL; struct fimc_md *fmd; - int ret = 0; - - if (WARN_ON(sd == NULL)) - return -EINVAL; + int ret; - if (p->subdevs[IDX_SENSOR]) { - ret = fimc_pipeline_s_power(p, 0); - fimc_md_set_camclk(sd, false); + if (sd == NULL) { + pr_warn("%s(): No sensor subdev\n", __func__); + return 0; } + ret = fimc_pipeline_s_power(p, 0); + fimc_md_set_camclk(sd, false); + fmd = entity_to_fimc_mdev(&sd->entity); /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */ -- GitLab From 52917bcbe06c937e97d941ef21211f981f192f99 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:24 -0300 Subject: [PATCH 1037/2900] [media] exynos4-is: Fix sensor subdev -> FIMC notification setup Ensure the v4l2_device notifications from sensor subdev works also after the media links reconfiguration. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 5b307f26f995..784c9e9daed8 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1,8 +1,8 @@ /* * S5P/EXYNOS4 SoC series camera host interface media device driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -39,6 +39,26 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, struct fimc_source_info *si, bool on); + +/* Set up image sensor subdev -> FIMC capture node notifications. */ +static void __setup_sensor_notification(struct fimc_md *fmd, + struct v4l2_subdev *sensor, + struct v4l2_subdev *fimc_sd) +{ + struct fimc_source_info *src_inf; + struct fimc_sensor_info *md_si; + unsigned long flags; + + src_inf = v4l2_get_subdev_hostdata(sensor); + if (!src_inf || WARN_ON(fmd == NULL)) + return; + + md_si = source_to_sensor_info(src_inf); + spin_lock_irqsave(&fmd->slock, flags); + md_si->host = v4l2_get_subdevdata(fimc_sd); + spin_unlock_irqrestore(&fmd->slock, flags); +} + /** * fimc_pipeline_prepare - update pipeline information with subdevice pointers * @me: media entity terminating the pipeline @@ -48,7 +68,9 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, static void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me) { + struct fimc_md *fmd = entity_to_fimc_mdev(me); struct v4l2_subdev *sd; + struct v4l2_subdev *sensor = NULL; int i; for (i = 0; i < IDX_MAX; i++) @@ -73,8 +95,10 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, sd = media_entity_to_v4l2_subdev(pad->entity); switch (sd->grp_id) { - case GRP_ID_FIMC_IS_SENSOR: case GRP_ID_SENSOR: + sensor = sd; + /* fall through */ + case GRP_ID_FIMC_IS_SENSOR: p->subdevs[IDX_SENSOR] = sd; break; case GRP_ID_CSIS: @@ -84,7 +108,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, p->subdevs[IDX_FLITE] = sd; break; case GRP_ID_FIMC: - /* No need to control FIMC subdev through subdev ops */ + p->subdevs[IDX_FIMC] = sd; break; case GRP_ID_FIMC_IS: p->subdevs[IDX_IS_ISP] = sd; @@ -96,6 +120,9 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, if (me->num_pads == 1) break; } + + if (sensor && p->subdevs[IDX_FIMC]) + __setup_sensor_notification(fmd, sensor, p->subdevs[IDX_FIMC]); } /** @@ -923,18 +950,6 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n", source->name, flags ? '=' : '-', sink->name); - - if (flags == 0 || sensor == NULL) - continue; - - if (!WARN_ON(si == NULL)) { - unsigned long irq_flags; - struct fimc_sensor_info *inf = source_to_sensor_info(si); - - spin_lock_irqsave(&fmd->slock, irq_flags); - inf->host = fmd->fimc[i]; - spin_unlock_irqrestore(&fmd->slock, irq_flags); - } } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { -- GitLab From 26d63d13da2c7de2547f6f455ae20045285dfeb8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 11:37:25 -0300 Subject: [PATCH 1038/2900] [media] exynos4-is: Add locking at fimc(-lite) subdev unregistered handler Protect the fimc/fimc-lite video nodes unregistration with their video lock. This prevents a kernel crash when e.g. udev opens a video node right after the driver registers it and then the driver tries to unregister it and defers its probing. Using video_is_unregistered() together with the video mutex allows safe unregistration of the video nodes at any time. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-capture.c | 4 ++++ drivers/media/platform/exynos4-is/fimc-lite.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 33c6a2f0ad74..1578aa4e4bb5 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -1855,6 +1855,8 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) if (fimc == NULL) return; + mutex_lock(&fimc->lock); + fimc_unregister_m2m_device(fimc); vdev = &fimc->vid_cap.ve.vdev; @@ -1866,6 +1868,8 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) } kfree(fimc->vid_cap.ctx); fimc->vid_cap.ctx = NULL; + + mutex_unlock(&fimc->lock); } static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = { diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 24e2a0f8797a..3f76f8abc4b3 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1300,11 +1300,15 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (fimc == NULL) return; + mutex_lock(&fimc->lock); + if (video_is_registered(&fimc->ve.vdev)) { video_unregister_device(&fimc->ve.vdev); media_entity_cleanup(&fimc->ve.vdev.entity); fimc->ve.pipe = NULL; } + + mutex_unlock(&fimc->lock); } static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = { -- GitLab From 5c327e73991485008c941436fb96413d9b010254 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 13:46:59 -0300 Subject: [PATCH 1039/2900] [media] exynos4-is: Remove leftovers of non-dt FIMC-LITE support FIMC-LITE devices are never looked up by iterating over all platform devices with bus_for_each_device() as these IP blocks are available only on dt-only Exynos SoC platforms. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 784c9e9daed8..b5624931d16d 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -804,8 +804,6 @@ static int fimc_md_pdev_match(struct device *dev, void *data) if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) { plat_entity = IDX_CSIS; - } else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME)) { - plat_entity = IDX_FLITE; } else { p = strstr(pdev->name, "fimc"); if (p && *(p + 4) == 0) -- GitLab From 0e761b21b9d6c7a95a8e2b858af85d07f6c62d99 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Fri, 31 May 2013 13:47:00 -0300 Subject: [PATCH 1040/2900] [media] exynos4-is: Simplify bitmask usage Merge the two sets of flags into one array to simplify accessing arbitrary bits from them. Signed-off-by: Phil Carmody Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-is-param.c | 80 +++++++++---------- .../media/platform/exynos4-is/fimc-is-regs.c | 4 +- drivers/media/platform/exynos4-is/fimc-is.c | 8 +- drivers/media/platform/exynos4-is/fimc-is.h | 8 +- drivers/media/platform/exynos4-is/fimc-isp.c | 4 +- 5 files changed, 49 insertions(+), 55 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c index c435db0da673..c7e7f694c6ed 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ b/drivers/media/platform/exynos4-is/fimc-is-param.c @@ -168,8 +168,8 @@ unsigned int __get_pending_param_count(struct fimc_is *is) unsigned int count; spin_lock_irqsave(&is->slock, flags); - count = hweight32(config->p_region_index1); - count += hweight32(config->p_region_index2); + count = hweight32(config->p_region_index[0]); + count += hweight32(config->p_region_index[1]); spin_unlock_irqrestore(&is->slock, flags); return count; @@ -177,31 +177,30 @@ unsigned int __get_pending_param_count(struct fimc_is *is) int __is_hw_update_params(struct fimc_is *is) { - unsigned long *p_index1, *p_index2; + unsigned long *p_index; int i, id, ret = 0; id = is->config_index; - p_index1 = &is->config[id].p_region_index1; - p_index2 = &is->config[id].p_region_index2; + p_index = &is->config[id].p_region_index[0]; - if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index1)) + if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index)) __fimc_is_hw_update_param_global_shotmode(is); - if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index1)) + if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) __fimc_is_hw_update_param_sensor_framerate(is); for (i = PARAM_ISP_CONTROL; i < PARAM_DRC_CONTROL; i++) { - if (test_bit(i, p_index1)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } for (i = PARAM_DRC_CONTROL; i < PARAM_SCALERC_CONTROL; i++) { - if (test_bit(i, p_index1)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } for (i = PARAM_FD_CONTROL; i <= PARAM_FD_CONFIG; i++) { - if (test_bit((i - 32), p_index2)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } @@ -243,7 +242,7 @@ void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf) fd->otf_input.height = mf->height; if (test_bit(PARAM_ISP_OTF_INPUT, - &is->config[index].p_region_index1)) + &is->config[index].p_region_index[0])) return; /* Update field */ @@ -368,7 +367,7 @@ void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val) unsigned long *p_index; struct isp_param *isp; - p_index = &is->config[index].p_region_index1; + p_index = &is->config[index].p_region_index[0]; isp = &is->config[index].isp; switch (cmd) { @@ -415,7 +414,7 @@ void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val) struct isp_param *isp; unsigned long *p_index; - p_index = &is->config[index].p_region_index1; + p_index = &is->config[index].p_region_index[0]; isp = &is->config[index].isp; switch (id) { @@ -476,7 +475,7 @@ void __is_set_fd_control(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->control.cmd = val; @@ -491,7 +490,7 @@ void __is_set_fd_config_maxface(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.max_number = val; @@ -511,7 +510,7 @@ void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.roll_angle = val; @@ -531,7 +530,7 @@ void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.yaw_angle = val; @@ -551,7 +550,7 @@ void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.smile_mode = val; @@ -571,7 +570,7 @@ void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.blink_mode = val; @@ -591,7 +590,7 @@ void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.eye_detect = val; @@ -611,7 +610,7 @@ void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.mouth_detect = val; @@ -631,7 +630,7 @@ void __is_set_fd_config_orientation(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.orientation = val; @@ -651,7 +650,7 @@ void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.orientation_value = val; @@ -672,7 +671,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) struct isp_param *isp; struct drc_param *drc; struct fd_param *fd; - unsigned long *p_index1, *p_index2; + unsigned long *p_index; unsigned int index; index = is->config_index; @@ -681,8 +680,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp = &is->config[index].isp; drc = &is->config[index].drc; fd = &is->config[index].fd; - p_index1 = &is->config[index].p_region_index1; - p_index2 = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[0]; /* Global */ global->shotmode.cmd = 1; @@ -695,7 +693,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_ISP_CONTROL); isp->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_INPUT, p_index1)) { + if (!test_bit(PARAM_ISP_OTF_INPUT, p_index)) { isp->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; isp->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); @@ -738,20 +736,20 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp->aa.target = ISP_AA_TARGET_AE | ISP_AA_TARGET_AWB; fimc_is_set_param_bit(is, PARAM_ISP_AA); - if (!test_bit(PARAM_ISP_FLASH, p_index1)) + if (!test_bit(PARAM_ISP_FLASH, p_index)) __is_set_isp_flash(is, ISP_FLASH_COMMAND_DISABLE, ISP_FLASH_REDEYE_DISABLE); - if (!test_bit(PARAM_ISP_AWB, p_index1)) + if (!test_bit(PARAM_ISP_AWB, p_index)) __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0); - if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index1)) + if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index)) __is_set_isp_effect(is, ISP_IMAGE_EFFECT_DISABLE); - if (!test_bit(PARAM_ISP_ISO, p_index1)) + if (!test_bit(PARAM_ISP_ISO, p_index)) __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0); - if (!test_bit(PARAM_ISP_ADJUST, p_index1)) { + if (!test_bit(PARAM_ISP_ADJUST, p_index)) { __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, 0); __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SATURATION, 0); @@ -762,7 +760,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, 0); } - if (!test_bit(PARAM_ISP_METERING, p_index1)) { + if (!test_bit(PARAM_ISP_METERING, p_index)) { __is_set_isp_metering(is, 0, ISP_METERING_COMMAND_CENTER); __is_set_isp_metering(is, 1, 0); __is_set_isp_metering(is, 2, 0); @@ -770,11 +768,11 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_isp_metering(is, 4, 0); } - if (!test_bit(PARAM_ISP_AFC, p_index1)) + if (!test_bit(PARAM_ISP_AFC, p_index)) __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0); isp->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index)) { isp->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; isp->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT); @@ -784,7 +782,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp->otf_output.order = 0; isp->otf_output.err = OTF_OUTPUT_ERROR_NONE; - if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index)) { isp->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; isp->dma1_output.width = 0; isp->dma1_output.height = 0; @@ -800,7 +798,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_ISP_DMA1_OUTPUT); } - if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index)) { isp->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; isp->dma2_output.width = 0; isp->dma2_output.height = 0; @@ -817,7 +815,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) } /* Sensor */ - if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index1)) { + if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) { if (is->config_index == 0) __is_set_sensor(is, 0); } @@ -827,7 +825,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_drc_control(is, CONTROL_BYPASS_ENABLE); drc->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_INPUT, p_index1)) { + if (!test_bit(PARAM_DRC_OTF_INPUT, p_index)) { drc->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; drc->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT); @@ -850,7 +848,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_DRC_DMA_INPUT); drc->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index1)) { + if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index)) { drc->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; drc->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT); @@ -865,7 +863,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fd->control.bypass = CONTROL_BYPASS_DISABLE; fd->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit((PARAM_FD_OTF_INPUT - 32), p_index2)) { + if (!test_bit(PARAM_FD_OTF_INPUT, p_index)) { fd->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; fd->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT); diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index b0ff67bc1b05..11b7b0acb56d 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c @@ -89,8 +89,8 @@ int fimc_is_hw_set_param(struct fimc_is *is) mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2)); mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3)); - mcuctl_write(config->p_region_index1, is, MCUCTL_REG_ISSR(4)); - mcuctl_write(config->p_region_index2, is, MCUCTL_REG_ISSR(5)); + mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4)); + mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5)); fimc_is_hw_set_intgr0_gd0(is); return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index cdb6b5e27336..ddb32e4ae0e9 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -530,8 +530,8 @@ static void fimc_is_general_irq_handler(struct fimc_is *is) break; case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); pr_debug("HIC_SET_PARAMETER\n"); break; @@ -590,8 +590,8 @@ static void fimc_is_general_irq_handler(struct fimc_is *is) switch (is->i2h_cmd.args[0]) { case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); break; } diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h index f5275a5b0156..04b456499d49 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ b/drivers/media/platform/exynos4-is/fimc-is.h @@ -226,8 +226,7 @@ struct chain_config { struct drc_param drc; struct fd_param fd; - unsigned long p_region_index1; - unsigned long p_region_index2; + unsigned long p_region_index[2]; }; /** @@ -304,10 +303,7 @@ static inline void fimc_is_set_param_bit(struct fimc_is *is, int num) { struct chain_config *cfg = &is->config[is->config_index]; - if (num >= 32) - set_bit(num - 32, &cfg->p_region_index2); - else - set_bit(num, &cfg->p_region_index1); + set_bit(num, &cfg->p_region_index[0]); } static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index d63947f7b302..0fefb53a5b56 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -317,8 +317,8 @@ static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on) clear_bit(IS_ST_PWR_ON, &is->state); clear_bit(IS_ST_INIT_DONE, &is->state); is->state = 0; - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_IDLE, &is->state); wmb(); } -- GitLab From f525e176f938f31a7335ce2bfec433236e0d8d6a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 13:47:01 -0300 Subject: [PATCH 1041/2900] [media] exynos4-is: Remove unused code Remove unused macros and fields of struct fimc_is_video. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-isp.h | 13 +------------ drivers/media/platform/exynos4-is/media-dev.h | 8 -------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index 800aba7ab4a7..f5c802cf40f9 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -118,7 +118,6 @@ struct fimc_is_video { unsigned int frame_count; unsigned int reqbufs_count; int streaming; - unsigned long payload[FIMC_ISP_MAX_PLANES]; const struct fimc_fmt *format; }; @@ -128,15 +127,9 @@ struct fimc_is_video { * @alloc_ctx: videobuf2 memory allocator context * @subdev: ISP v4l2_subdev * @subdev_pads: the ISP subdev media pads - * @ctrl_handler: v4l2 controls handler * @test_pattern: test pattern controls - * @pipeline: video capture pipeline data structure + * @ctrls: v4l2 controls structure * @video_lock: mutex serializing video device and the subdev operations - * @fmt: pointer to color format description structure - * @payload: image size in bytes (w x h x bpp) - * @inp_frame: camera input frame structure - * @out_frame: DMA output frame structure - * @source_subdev_grp_id: group id of remote source subdev * @cac_margin_x: horizontal CAC margin in pixels * @cac_margin_y: vertical CAC margin in pixels * @state: driver state flags @@ -154,10 +147,6 @@ struct fimc_isp { struct mutex video_lock; struct mutex subdev_lock; - struct fimc_isp_frame inp_frame; - struct fimc_isp_frame out_frame; - unsigned int source_subdev_grp_id; - unsigned int cac_margin_x; unsigned int cac_margin_y; diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index a704eea2cfbd..62599fd7756f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -133,14 +133,6 @@ struct fimc_md { struct list_head pipelines; }; -#define is_subdev_pad(pad) (pad == NULL || \ - media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) - -#define me_subtype(me) \ - ((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK)) - -#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) - static inline struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si) { -- GitLab From 7536b4240f1bdc71f83cf008160e71c38f7ac9ff Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 13:47:02 -0300 Subject: [PATCH 1042/2900] [media] exynos4-is: Refactor vidioc_s_fmt, vidioc_try_fmt handlers Remove duplicated code in the vidioc_try_fmt and vidioc_s_fmt handlers. This is a pre-requsite to allow successful fimc.capture video open even if its corresponding media entities are not linked into a complete pipeline. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 158 +++++++++--------- 1 file changed, 75 insertions(+), 83 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 1578aa4e4bb5..2b045b6db569 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -503,9 +503,6 @@ static int fimc_capture_open(struct file *file) ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true); - if (ret == 0) - ret = fimc_capture_set_default_format(fimc); - if (ret == 0 && vc->user_subdev_api && vc->inh_sensor_ctrls) { /* * Recreate controls of the the video node to drop @@ -522,6 +519,9 @@ static int fimc_capture_open(struct file *file) fimc_md_graph_unlock(ve); + if (ret == 0) + ret = fimc_capture_set_default_format(fimc); + if (ret < 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_put_sync(&fimc->pdev->dev); @@ -916,55 +916,83 @@ static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, return 0; } -static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) +/* + * Try or set format on the fimc.X.capture video node and additionally + * on the whole pipeline if @try is false. + * Locking: the caller must _not_ hold the graph mutex. + */ +static int __video_try_or_set_format(struct fimc_dev *fimc, + struct v4l2_format *f, bool try, + struct fimc_fmt **inp_fmt, + struct fimc_fmt **out_fmt) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct exynos_video_entity *ve = &fimc->vid_cap.ve; - struct v4l2_mbus_framefmt mf; - struct v4l2_subdev *sensor; - struct fimc_fmt *ffmt = NULL; + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct exynos_video_entity *ve = &vc->ve; + struct fimc_ctx *ctx = vc->ctx; + unsigned int width = 0, height = 0; int ret = 0; + /* Pre-configure format at the camera input interface, for JPEG only */ if (fimc_jpeg_fourcc(pix->pixelformat)) { fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SINK_CAM); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; + if (try) { + width = pix->width; + height = pix->height; + } else { + ctx->s_frame.f_width = pix->width; + ctx->s_frame.f_height = pix->height; + } } - ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ffmt) + + /* Try the format at the scaler and the DMA output */ + *out_fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, + NULL, &pix->pixelformat, + FIMC_SD_PAD_SOURCE); + if (*out_fmt == NULL) return -EINVAL; - if (!fimc->vid_cap.user_subdev_api) { - mf.width = pix->width; - mf.height = pix->height; - mf.code = ffmt->mbus_code; + /* Restore image width/height for JPEG (no resizing supported). */ + if (try && fimc_jpeg_fourcc(pix->pixelformat)) { + pix->width = width; + pix->height = height; + } + + /* Try to match format at the host and the sensor */ + if (!vc->user_subdev_api) { + struct v4l2_mbus_framefmt mbus_fmt; + struct v4l2_mbus_framefmt *mf; + + mf = try ? &mbus_fmt : &fimc->vid_cap.ci_fmt; + + mf->code = (*out_fmt)->mbus_code; + mf->width = pix->width; + mf->height = pix->height; fimc_md_graph_lock(ve); - fimc_pipeline_try_format(ctx, &mf, &ffmt, false); + ret = fimc_pipeline_try_format(ctx, mf, inp_fmt, try); fimc_md_graph_unlock(ve); - pix->width = mf.width; - pix->height = mf.height; - if (ffmt) - pix->pixelformat = ffmt->fourcc; + if (ret < 0) + return ret; + + pix->width = mf->width; + pix->height = mf->height; } - fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); + fimc_adjust_mplane_format(*out_fmt, pix->width, pix->height, pix); + + if ((*out_fmt)->flags & FMT_FLAGS_COMPRESSED) { + struct v4l2_subdev *sensor; - if (ffmt->flags & FMT_FLAGS_COMPRESSED) { fimc_md_graph_lock(ve); sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); if (sensor) fimc_get_sensor_frame_desc(sensor, pix->plane_fmt, - ffmt->memplanes, true); + (*out_fmt)->memplanes, try); else ret = -EPIPE; @@ -974,6 +1002,15 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, return ret; } +static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct fimc_dev *fimc = video_drvdata(file); + struct fimc_fmt *out_fmt = NULL, *inp_fmt = NULL; + + return __video_try_or_set_format(fimc, f, true, &inp_fmt, &out_fmt); +} + static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, enum fimc_color_fmt color) { @@ -991,58 +1028,23 @@ static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, static int __fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) { - struct fimc_ctx *ctx = fimc->vid_cap.ctx; + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct fimc_ctx *ctx = vc->ctx; struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt; - struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe); struct fimc_frame *ff = &ctx->d_frame; - struct fimc_fmt *s_fmt = NULL; + struct fimc_fmt *inp_fmt = NULL; int ret, i; if (vb2_is_busy(&fimc->vid_cap.vbq)) return -EBUSY; - /* Pre-configure format at camera interface input, for JPEG only */ - if (fimc_jpeg_fourcc(pix->pixelformat)) { - fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SINK_CAM); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; - } - /* Try the format at the scaler and the DMA output */ - ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ff->fmt) - return -EINVAL; + ret = __video_try_or_set_format(fimc, f, false, &inp_fmt, &ff->fmt); + if (ret < 0) + return ret; /* Update RGB Alpha control state and value range */ fimc_alpha_ctrl_update(ctx); - /* Try to match format at the host and the sensor */ - if (!fimc->vid_cap.user_subdev_api) { - mf->code = ff->fmt->mbus_code; - mf->width = pix->width; - mf->height = pix->height; - ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); - if (ret) - return ret; - - pix->width = mf->width; - pix->height = mf->height; - } - - fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); - - if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) { - ret = fimc_get_sensor_frame_desc(p->subdevs[IDX_SENSOR], - pix->plane_fmt, ff->fmt->memplanes, - true); - if (ret < 0) - return ret; - } - for (i = 0; i < ff->fmt->memplanes; i++) { ff->bytesperline[i] = pix->plane_fmt[i].bytesperline; ff->payload[i] = pix->plane_fmt[i].sizeimage; @@ -1056,8 +1058,8 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc, fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color); /* Reset cropping and set format at the camera interface input */ - if (!fimc->vid_cap.user_subdev_api) { - ctx->s_frame.fmt = s_fmt; + if (!vc->user_subdev_api) { + ctx->s_frame.fmt = inp_fmt; set_frame_bounds(&ctx->s_frame, pix->width, pix->height); set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height); } @@ -1069,18 +1071,8 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct fimc_dev *fimc = video_drvdata(file); - int ret; - fimc_md_graph_lock(&fimc->vid_cap.ve); - /* - * The graph is walked within __fimc_capture_set_format() to set - * the format at subdevs thus the graph mutex needs to be held at - * this point. - */ - ret = __fimc_capture_set_format(fimc, f); - - fimc_md_graph_unlock(&fimc->vid_cap.ve); - return ret; + return __fimc_capture_set_format(fimc, f); } static int fimc_cap_enum_input(struct file *file, void *priv, -- GitLab From 0f20956be654cf52a69b9071590faa9c6657b77f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 13:47:03 -0300 Subject: [PATCH 1043/2900] [media] exynos4-is: Move __fimc_videoc_querycap() function to the common module Move __fimc_videoc_querycap() function to the common exynos4-is-common.ko module so it don't need to be reimplemented in multiple video node drivers of the exynos4-is. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/common.c | 12 ++++++++++++ drivers/media/platform/exynos4-is/common.h | 4 ++++ drivers/media/platform/exynos4-is/fimc-core.c | 11 ----------- drivers/media/platform/exynos4-is/fimc-core.h | 2 -- drivers/media/platform/exynos4-is/fimc-m2m.c | 1 + 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c index 57f9010cee50..0ec210b4da1d 100644 --- a/drivers/media/platform/exynos4-is/common.c +++ b/drivers/media/platform/exynos4-is/common.c @@ -38,4 +38,16 @@ struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity) } EXPORT_SYMBOL(fimc_find_remote_sensor); +void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, + unsigned int caps) +{ + strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver)); + strlcpy(cap->card, dev->driver->name, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev_name(dev)); + cap->device_caps = caps; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; +} +EXPORT_SYMBOL(__fimc_vidioc_querycap); + MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos4-is/common.h b/drivers/media/platform/exynos4-is/common.h index 3c398039ba28..75b9c71d9419 100644 --- a/drivers/media/platform/exynos4-is/common.h +++ b/drivers/media/platform/exynos4-is/common.h @@ -6,7 +6,11 @@ * published by the Free Software Foundation. */ +#include +#include #include #include struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity); +void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, + unsigned int caps); diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 379a5e9d52a7..6489c5160ee8 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -213,17 +213,6 @@ struct fimc_fmt *fimc_get_format(unsigned int index) return &fimc_formats[index]; } -void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, - unsigned int caps) -{ - strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver)); - strlcpy(cap->card, dev->driver->name, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), - "platform:%s", dev_name(dev)); - cap->device_caps = caps; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; -} - int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, int dw, int dh, int rotation) { diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index c48a79254d83..349c7c01e49a 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -619,8 +619,6 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, /* fimc-core.c */ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, struct v4l2_fmtdesc *f); -void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, - unsigned int caps); int fimc_ctrls_create(struct fimc_ctx *ctx); void fimc_ctrls_delete(struct fimc_ctx *ctx); void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index bde1f47f7ed3..8d33b68c76ba 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -27,6 +27,7 @@ #include #include +#include "common.h" #include "fimc-core.h" #include "fimc-reg.h" #include "media-dev.h" -- GitLab From 4434adff80bf24c1c558a1605599665301185bdb Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 13:47:04 -0300 Subject: [PATCH 1044/2900] [media] exynos4-is: Add isp_dbg() macro Add a debug trace macro for the FIMC-IS ISP subdev and the ISP video node drivers which are going to be added in subsequent patches. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-isp.c | 16 ++++++++-------- drivers/media/platform/exynos4-is/fimc-isp.h | 5 +++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index 0fefb53a5b56..e6b0a4b027a9 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -30,8 +30,8 @@ #include "fimc-is-regs.h" #include "fimc-is.h" -static int debug; -module_param_named(debug_isp, debug, int, S_IRUGO | S_IWUSR); +int fimc_isp_debug; +module_param_named(debug_isp, fimc_isp_debug, int, S_IRUGO | S_IWUSR); static const struct fimc_fmt fimc_isp_formats[FIMC_ISP_NUM_FORMATS] = { { @@ -157,8 +157,8 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, mutex_unlock(&isp->subdev_lock); - v4l2_dbg(1, debug, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n", - __func__, fmt->pad, mf->code, mf->width, mf->height); + isp_dbg(1, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n", __func__, + fmt->pad, mf->code, mf->width, mf->height); return 0; } @@ -191,7 +191,7 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf = &fmt->format; int ret = 0; - v4l2_dbg(1, debug, sd, "%s: pad%d: code: 0x%x, %dx%d\n", + isp_dbg(1, sd, "%s: pad%d: code: 0x%x, %dx%d\n", __func__, fmt->pad, mf->code, mf->width, mf->height); mf->colorspace = V4L2_COLORSPACE_JPEG; @@ -221,7 +221,7 @@ static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) struct fimc_is *is = fimc_isp_to_is(isp); int ret; - v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on); + isp_dbg(1, sd, "%s: on: %d\n", __func__, on); if (!test_bit(IS_ST_INIT_DONE, &is->state)) return -EBUSY; @@ -235,8 +235,8 @@ static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) return ret; } - v4l2_dbg(1, debug, sd, "changing mode to %d\n", - is->config_index); + isp_dbg(1, sd, "changing mode to %d\n", is->config_index); + ret = fimc_is_itf_mode_change(is); if (ret) return -EINVAL; diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index f5c802cf40f9..756063e77fb8 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -26,6 +26,11 @@ #include #include +extern int fimc_isp_debug; + +#define isp_dbg(level, dev, fmt, arg...) \ + v4l2_dbg(level, fimc_isp_debug, dev, fmt, ## arg) + /* FIXME: revisit these constraints */ #define FIMC_ISP_SINK_WIDTH_MIN (16 + 8) #define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8) -- GitLab From 813f5c0ac5ccf7dd9c216a8f7fbe827ca36cb83f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 10:37:26 -0300 Subject: [PATCH 1045/2900] [media] media: Change media device link_notify behaviour Currently the media device link_notify callback is invoked before the actual change of state of a link when the link is being enabled, and after the actual change of state when the link is being disabled. This doesn't allow a media device driver to perform any operations on a full graph before a link is disabled, as well as performing any tasks on a modified graph right after a link's state is changed. This patch modifies signature of the link_notify callback. This callback is now called always before and after a link's state change. To distinguish the notifications a 'notification' argument is added to the link_notify callback: MEDIA_DEV_NOTIFY_PRE_LINK_CH indicates notification before link's state change and MEDIA_DEV_NOTIFY_POST_LINK_CH corresponds to a notification after link flags change. [mchehab@redhat.com: whitespace cleanups] Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 18 +++----- drivers/media/platform/exynos4-is/media-dev.c | 18 ++++---- drivers/media/platform/omap3isp/isp.c | 41 +++++++++++-------- include/media/media-device.h | 9 +++- 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 0438209d020a..df72f7d99d80 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -496,25 +496,17 @@ int __media_entity_setup_link(struct media_link *link, u32 flags) mdev = source->parent; - if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) { - ret = mdev->link_notify(link->source, link->sink, - MEDIA_LNK_FL_ENABLED); + if (mdev->link_notify) { + ret = mdev->link_notify(link, flags, + MEDIA_DEV_NOTIFY_PRE_LINK_CH); if (ret < 0) return ret; } ret = __media_entity_setup_link_notify(link, flags); - if (ret < 0) - goto err; - if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) - mdev->link_notify(link->source, link->sink, 0); - - return 0; - -err: - if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) - mdev->link_notify(link->source, link->sink, 0); + if (mdev->link_notify) + mdev->link_notify(link, flags, MEDIA_DEV_NOTIFY_POST_LINK_CH); return ret; } diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index b5624931d16d..5298dd6680ae 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1287,34 +1287,36 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) return __fimc_md_set_camclk(fmd, si, on); } -static int fimc_md_link_notify(struct media_pad *source, - struct media_pad *sink, u32 flags) +static int fimc_md_link_notify(struct media_link *link, u32 flags, + unsigned int notification) { + struct media_entity *sink = link->sink->entity; struct exynos_video_entity *ve; struct video_device *vdev; struct fimc_pipeline *pipeline; int i, ret = 0; - if (media_entity_type(sink->entity) != MEDIA_ENT_T_DEVNODE_V4L) + if (media_entity_type(sink) != MEDIA_ENT_T_DEVNODE_V4L || + notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) return 0; - vdev = media_entity_to_video_device(sink->entity); + vdev = media_entity_to_video_device(sink); ve = vdev_to_exynos_video_entity(vdev); pipeline = to_fimc_pipeline(ve->pipe); - if (!(flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) { - if (sink->entity->use_count > 0) + if (!(link->flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) { + if (sink->use_count > 0) ret = __fimc_pipeline_close(ve->pipe); for (i = 0; i < IDX_MAX; i++) pipeline->subdevs[i] = NULL; - } else if (sink->entity->use_count > 0) { + } else if (sink->use_count > 0) { /* * Link activation. Enable power of pipeline elements only if * the pipeline is already in use, i.e. its video node is open. * Recreate the controls destroyed during the link deactivation. */ - ret = __fimc_pipeline_open(ve->pipe, sink->entity, true); + ret = __fimc_pipeline_open(ve->pipe, sink, true); } return ret ? -EPIPE : ret; diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index ff5a20afa691..df3a0ec7fd2c 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -792,9 +792,9 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) /* * isp_pipeline_link_notify - Link management notification callback - * @source: Pad at the start of the link - * @sink: Pad at the end of the link + * @link: The link * @flags: New link flags that will be applied + * @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*) * * React to link management on powered pipelines by updating the use count of * all entities in the source and sink sides of the link. Entities are powered @@ -804,29 +804,38 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) * off is assumed to never fail. This function will not fail for disconnection * events. */ -static int isp_pipeline_link_notify(struct media_pad *source, - struct media_pad *sink, u32 flags) +static int isp_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification) { - int source_use = isp_pipeline_pm_use_count(source->entity); - int sink_use = isp_pipeline_pm_use_count(sink->entity); + struct media_entity *source = link->source->entity; + struct media_entity *sink = link->sink->entity; + int source_use = isp_pipeline_pm_use_count(source); + int sink_use = isp_pipeline_pm_use_count(sink); int ret; - if (!(flags & MEDIA_LNK_FL_ENABLED)) { + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + !(link->flags & MEDIA_LNK_FL_ENABLED)) { /* Powering off entities is assumed to never fail. */ - isp_pipeline_pm_power(source->entity, -sink_use); - isp_pipeline_pm_power(sink->entity, -source_use); + isp_pipeline_pm_power(source, -sink_use); + isp_pipeline_pm_power(sink, -source_use); return 0; } - ret = isp_pipeline_pm_power(source->entity, sink_use); - if (ret < 0) - return ret; + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + (flags & MEDIA_LNK_FL_ENABLED)) { - ret = isp_pipeline_pm_power(sink->entity, source_use); - if (ret < 0) - isp_pipeline_pm_power(source->entity, -sink_use); + ret = isp_pipeline_pm_power(source, sink_use); + if (ret < 0) + return ret; - return ret; + ret = isp_pipeline_pm_power(sink, source_use); + if (ret < 0) + isp_pipeline_pm_power(source, -sink_use); + + return ret; + } + + return 0; } /* ----------------------------------------------------------------------------- diff --git a/include/media/media-device.h b/include/media/media-device.h index eaade9815bb6..12155a9596c4 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -45,6 +45,7 @@ struct device; * @entities: List of registered entities * @lock: Entities list lock * @graph_mutex: Entities graph operation lock + * @link_notify: Link state change notification callback * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -75,10 +76,14 @@ struct media_device { /* Serializes graph operations. */ struct mutex graph_mutex; - int (*link_notify)(struct media_pad *source, - struct media_pad *sink, u32 flags); + int (*link_notify)(struct media_link *link, u32 flags, + unsigned int notification); }; +/* Supported link_notify @notification values. */ +#define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0 +#define MEDIA_DEV_NOTIFY_POST_LINK_CH 1 + /* media_devnode to media_device */ #define to_media_device(node) container_of(node, struct media_device, devnode) -- GitLab From d3775fa76bed74a46e179c08895fafc968f7292a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 10:37:27 -0300 Subject: [PATCH 1046/2900] [media] exynos4-is: Extend link_notify handler to support fimc-is/lite pipelines This patch corrects the link_notify handler to support more complex pipelines, including fimc-lite and fimc-is entities. After the FIMC-IS driver addition the assumptions made in the link_notify callback are no longer valid, e.g. the link between fimc-lite subdev and its video node is not immutable any more and there is more subdevs than just sensor, MIPI-CSIS and FIMC(-LITE). The graph is now walked and for each video node found a media pipeline which ends at this node is disabled/enabled (the subdevs are powered on/off). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 103 ++++++++++++++---- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 5298dd6680ae..19f556c5957f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1287,39 +1287,98 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) return __fimc_md_set_camclk(fmd, si, on); } -static int fimc_md_link_notify(struct media_link *link, u32 flags, - unsigned int notification) +static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) { - struct media_entity *sink = link->sink->entity; struct exynos_video_entity *ve; + struct fimc_pipeline *p; struct video_device *vdev; - struct fimc_pipeline *pipeline; - int i, ret = 0; + int ret; - if (media_entity_type(sink) != MEDIA_ENT_T_DEVNODE_V4L || - notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) + vdev = media_entity_to_video_device(entity); + if (vdev->entity.use_count == 0) return 0; - vdev = media_entity_to_video_device(sink); ve = vdev_to_exynos_video_entity(vdev); - pipeline = to_fimc_pipeline(ve->pipe); + p = to_fimc_pipeline(ve->pipe); + /* + * Nothing to do if we are disabling the pipeline, some link + * has been disconnected and p->subdevs array is cleared now. + */ + if (!enable && p->subdevs[IDX_SENSOR] == NULL) + return 0; - if (!(link->flags & MEDIA_LNK_FL_ENABLED) && pipeline->subdevs[IDX_SENSOR]) { - if (sink->use_count > 0) - ret = __fimc_pipeline_close(ve->pipe); + if (enable) + ret = __fimc_pipeline_open(ve->pipe, entity, true); + else + ret = __fimc_pipeline_close(ve->pipe); - for (i = 0; i < IDX_MAX; i++) - pipeline->subdevs[i] = NULL; - } else if (sink->use_count > 0) { - /* - * Link activation. Enable power of pipeline elements only if - * the pipeline is already in use, i.e. its video node is open. - * Recreate the controls destroyed during the link deactivation. - */ - ret = __fimc_pipeline_open(ve->pipe, sink, true); + if (ret == 0 && !enable) + memset(p->subdevs, 0, sizeof(p->subdevs)); + + return ret; +} + +/* Locking: called with entity->parent->graph_mutex mutex held. */ +static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) +{ + struct media_entity *entity_err = entity; + struct media_entity_graph graph; + int ret; + + /* + * Walk current graph and call the pipeline open/close routine for each + * opened video node that belongs to the graph of entities connected + * through active links. This is needed as we cannot power on/off the + * subdevs in random order. + */ + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) + continue; + + ret = __fimc_md_modify_pipeline(entity, enable); + + if (ret < 0) + goto err; + } + + return 0; + err: + media_entity_graph_walk_start(&graph, entity_err); + + while ((entity_err = media_entity_graph_walk_next(&graph))) { + if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE) + continue; + + __fimc_md_modify_pipeline(entity_err, !enable); + + if (entity_err == entity) + break; + } + + return ret; +} + +static int fimc_md_link_notify(struct media_link *link, unsigned int flags, + unsigned int notification) +{ + struct media_entity *sink = link->sink->entity; + int ret = 0; + + /* Before link disconnection */ + if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { + if (!(flags & MEDIA_LNK_FL_ENABLED)) + ret = __fimc_md_modify_pipelines(sink, false); + else + ; /* TODO: Link state change validation */ + /* After link activation */ + } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + (link->flags & MEDIA_LNK_FL_ENABLED)) { + ret = __fimc_md_modify_pipelines(sink, true); } - return ret ? -EPIPE : ret; + return ret ? -EPIPE : 0; } static ssize_t fimc_md_sysfs_show(struct device *dev, -- GitLab From 984b248f6bdcd0b319e84e43f0be532f989c709a Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 10 Jun 2013 08:54:15 -0300 Subject: [PATCH 1047/2900] [media] s5p-tv: Don't ignore return value of regulator_enable() in sii9234_drv.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes following compilation warning: CC [M] drivers/media/platform/s5p-tv/sii9234_drv.o drivers/media/platform/s5p-tv/sii9234_drv.c: In function ‘sii9234_runtime_resume’: drivers/media/platform/s5p-tv/sii9234_drv.c:252:18: warning: ignoring return value of ‘regulator_enable’, declared with attribute warn_unused_result Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/sii9234_drv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/s5p-tv/sii9234_drv.c b/drivers/media/platform/s5p-tv/sii9234_drv.c index 39b77d24b9c2..3dd762e5b67e 100644 --- a/drivers/media/platform/s5p-tv/sii9234_drv.c +++ b/drivers/media/platform/s5p-tv/sii9234_drv.c @@ -249,7 +249,9 @@ static int sii9234_runtime_resume(struct device *dev) int ret; dev_info(dev, "resume start\n"); - regulator_enable(ctx->power); + ret = regulator_enable(ctx->power); + if (ret < 0) + return ret; ret = sii9234_reset(ctx); if (ret) -- GitLab From d285837eaf5e363ac0ab1bf6deb110e007325949 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 10 Jun 2013 08:54:30 -0300 Subject: [PATCH 1048/2900] [media] s5p-tv: Do not ignore regulator/clk API return values in sdo_drv.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes following compilation warning: drivers/media/platform/s5p-tv/sdo_drv.c: In function ‘sdo_runtime_resume’: drivers/media/platform/s5p-tv/sdo_drv.c:268:18: warning: ignoring return value of ‘regulator_enable’, declared with attribute warn_unused_result drivers/media/platform/s5p-tv/sdo_drv.c:269:18: warning: ignoring return value of ‘regulator_enable’, declared with attribute warn_unused_result Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/sdo_drv.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index ab6f9ef89423..0afa90f0f6ab 100644 --- a/drivers/media/platform/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c @@ -262,11 +262,21 @@ static int sdo_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct sdo_device *sdev = sd_to_sdev(sd); + int ret; dev_info(dev, "resume\n"); - clk_enable(sdev->sclk_dac); - regulator_enable(sdev->vdac); - regulator_enable(sdev->vdet); + + ret = clk_enable(sdev->sclk_dac); + if (ret < 0) + return ret; + + ret = regulator_enable(sdev->vdac); + if (ret < 0) + goto dac_clk_dis; + + ret = regulator_enable(sdev->vdet); + if (ret < 0) + goto vdac_r_dis; /* software reset */ sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET); @@ -285,6 +295,12 @@ static int sdo_runtime_resume(struct device *dev) SDO_COMPENSATION_CVBS_COMP_OFF); sdo_reg_debug(sdev); return 0; + +vdac_r_dis: + regulator_disable(sdev->vdac); +dac_clk_dis: + clk_disable(sdev->sclk_dac); + return ret; } static const struct dev_pm_ops sdo_pm_ops = { -- GitLab From 62d54876c511628daed2246753e2fe348da022f1 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 10 Jun 2013 08:54:48 -0300 Subject: [PATCH 1049/2900] [media] s5p-tv: Don't ignore return value of regulator_bulk_enable() in hdmi_drv.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes following compilation warning: CC [M] drivers/media/platform/s5p-tv/hdmi_drv.o drivers/media/platform/s5p-tv/hdmi_drv.c: In function ‘hdmi_resource_poweron’: drivers/media/platform/s5p-tv/hdmi_drv.c:583:23: warning: ignoring return value of ‘regulator_bulk_enable’, declared with attribute warn_unused_result Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-tv/hdmi_drv.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index cd525f193240..1b34c3629858 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -576,16 +576,22 @@ static int hdmi_s_stream(struct v4l2_subdev *sd, int enable) return hdmi_streamoff(hdev); } -static void hdmi_resource_poweron(struct hdmi_resources *res) +static int hdmi_resource_poweron(struct hdmi_resources *res) { + int ret; + /* turn HDMI power on */ - regulator_bulk_enable(res->regul_count, res->regul_bulk); + ret = regulator_bulk_enable(res->regul_count, res->regul_bulk); + if (ret < 0) + return ret; /* power-on hdmi physical interface */ clk_enable(res->hdmiphy); /* use VPP as parent clock; HDMIPHY is not working yet */ clk_set_parent(res->sclk_hdmi, res->sclk_pixel); /* turn clocks on */ clk_enable(res->sclk_hdmi); + + return 0; } static void hdmi_resource_poweroff(struct hdmi_resources *res) @@ -728,11 +734,13 @@ static int hdmi_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - int ret = 0; + int ret; dev_dbg(dev, "%s\n", __func__); - hdmi_resource_poweron(&hdev->res); + ret = hdmi_resource_poweron(&hdev->res); + if (ret < 0) + return ret; /* starting MHL */ ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); -- GitLab From 25cdce170d28092e8e162f36702be3308973b19d Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 17 May 2013 23:42:01 +0000 Subject: [PATCH 1050/2900] x86, mcheck, therm_throt: Process package thresholds Added callback registration for package threshold reports. Also added a callback to check the rate control implemented in callback or not. If there is no rate control implemented, then there is a default rate control similar to core threshold notification by delaying for CHECK_INTERVAL (5 minutes) between reports. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- arch/x86/include/asm/mce.h | 7 +++ arch/x86/kernel/cpu/mcheck/therm_throt.c | 63 ++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index fa5f71e021d5..16a214557a58 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -214,6 +214,13 @@ void mce_log_therm_throt_event(__u64 status); /* Interrupt Handler for core thermal thresholds */ extern int (*platform_thermal_notify)(__u64 msr_val); +/* Interrupt Handler for package thermal thresholds */ +extern int (*platform_thermal_package_notify)(__u64 msr_val); + +/* Callback support of rate control, return true, if + * callback has rate control */ +extern bool (*platform_thermal_package_rate_control)(void); + #ifdef CONFIG_X86_THERMAL_VECTOR extern void mcheck_intel_therm_init(void); #else diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 47a1870279aa..4131c0393594 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -54,12 +54,24 @@ struct thermal_state { struct _thermal_state package_power_limit; struct _thermal_state core_thresh0; struct _thermal_state core_thresh1; + struct _thermal_state pkg_thresh0; + struct _thermal_state pkg_thresh1; }; /* Callback to handle core threshold interrupts */ int (*platform_thermal_notify)(__u64 msr_val); EXPORT_SYMBOL(platform_thermal_notify); +/* Callback to handle core package threshold_interrupts */ +int (*platform_thermal_package_notify)(__u64 msr_val); +EXPORT_SYMBOL_GPL(platform_thermal_package_notify); + +/* Callback support of rate control, return true, if + * callback has rate control */ +bool (*platform_thermal_package_rate_control)(void); +EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control); + + static DEFINE_PER_CPU(struct thermal_state, thermal_state); static atomic_t therm_throt_en = ATOMIC_INIT(0); @@ -203,19 +215,25 @@ static int therm_throt_process(bool new_event, int event, int level) return 0; } -static int thresh_event_valid(int event) +static int thresh_event_valid(int level, int event) { struct _thermal_state *state; unsigned int this_cpu = smp_processor_id(); struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); u64 now = get_jiffies_64(); - state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1; + if (level == PACKAGE_LEVEL) + state = (event == 0) ? &pstate->pkg_thresh0 : + &pstate->pkg_thresh1; + else + state = (event == 0) ? &pstate->core_thresh0 : + &pstate->core_thresh1; if (time_before64(now, state->next_check)) return 0; state->next_check = now + CHECK_INTERVAL; + return 1; } @@ -321,6 +339,39 @@ device_initcall(thermal_throttle_init_device); #endif /* CONFIG_SYSFS */ +static void notify_package_thresholds(__u64 msr_val) +{ + bool notify_thres_0 = false; + bool notify_thres_1 = false; + + if (!platform_thermal_package_notify) + return; + + /* lower threshold check */ + if (msr_val & THERM_LOG_THRESHOLD0) + notify_thres_0 = true; + /* higher threshold check */ + if (msr_val & THERM_LOG_THRESHOLD1) + notify_thres_1 = true; + + if (!notify_thres_0 && !notify_thres_1) + return; + + if (platform_thermal_package_rate_control && + platform_thermal_package_rate_control()) { + /* Rate control is implemented in callback */ + platform_thermal_package_notify(msr_val); + return; + } + + /* lower threshold reached */ + if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0)) + platform_thermal_package_notify(msr_val); + /* higher threshold reached */ + if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1)) + platform_thermal_package_notify(msr_val); +} + static void notify_thresholds(__u64 msr_val) { /* check whether the interrupt handler is defined; @@ -330,10 +381,12 @@ static void notify_thresholds(__u64 msr_val) return; /* lower threshold reached */ - if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0)) + if ((msr_val & THERM_LOG_THRESHOLD0) && + thresh_event_valid(CORE_LEVEL, 0)) platform_thermal_notify(msr_val); /* higher threshold reached */ - if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1)) + if ((msr_val & THERM_LOG_THRESHOLD1) && + thresh_event_valid(CORE_LEVEL, 1)) platform_thermal_notify(msr_val); } @@ -359,6 +412,8 @@ static void intel_thermal_interrupt(void) if (this_cpu_has(X86_FEATURE_PTS)) { rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); + /* check violations of package thermal thresholds */ + notify_package_thresholds(msr_val); therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT, THERMAL_THROTTLING_EVENT, PACKAGE_LEVEL); -- GitLab From 0c1569590a6f14130b3660241580036176dba718 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 15:07:40 +0000 Subject: [PATCH 1051/2900] thermal: ti-soc-thermal: update DT reference for OMAP5430 Add missing irq line for TALERT on DT entry for OMAP5430. Cc: linux-pm@vger.kernel.org Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: Greg Kroah-Hartman Cc: Zhang Rui Cc: J Keerthy Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt index a4a33d1a0746..1629652372b6 100644 --- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt @@ -57,4 +57,5 @@ bandgap { 0x4a002380 0x2c 0x4a0023C0 0x3c>; compatible = "ti,omap5430-bandgap"; + interrupts = <0 126 4>; /* talert */ }; -- GitLab From 359836e1de4d32a647bf2c1f99d84d2ff0a098bd Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 15:07:41 +0000 Subject: [PATCH 1052/2900] thermal: ti-soc-thermal: remove external heat while extrapolating hotspot For boards that provide a PCB sensor close to SoC junction temperature, it is possible to remove the cumulative heat reported by the SoC temperature sensor. This patch changes the extrapolation computation to consider an external sensor in the extrapolation equations. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- .../ti-soc-thermal/ti-thermal-common.c | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index e3c5e677eaa5..8e67ebf98404 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -38,6 +38,7 @@ /* common data structures */ struct ti_thermal_data { struct thermal_zone_device *ti_thermal; + struct thermal_zone_device *pcb_tz; struct thermal_cooling_device *cool_dev; struct ti_bandgap *bgp; enum thermal_device_mode mode; @@ -77,10 +78,12 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, unsigned long *temp) { + struct thermal_zone_device *pcb_tz = NULL; struct ti_thermal_data *data = thermal->devdata; struct ti_bandgap *bgp; const struct ti_temp_sensor *s; - int ret, tmp, pcb_temp, slope, constant; + int ret, tmp, slope, constant; + unsigned long pcb_temp; if (!data) return 0; @@ -92,16 +95,22 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, if (ret) return ret; - pcb_temp = 0; - /* TODO: Introduce pcb temperature lookup */ + /* Default constants */ + slope = s->slope; + constant = s->constant; + + pcb_tz = data->pcb_tz; /* In case pcb zone is available, use the extrapolation rule with it */ - if (pcb_temp) { - tmp -= pcb_temp; - slope = s->slope_pcb; - constant = s->constant_pcb; - } else { - slope = s->slope; - constant = s->constant; + if (!IS_ERR_OR_NULL(pcb_tz)) { + ret = thermal_zone_get_temp(pcb_tz, &pcb_temp); + if (!ret) { + tmp -= pcb_temp; /* got a valid PCB temp */ + slope = s->slope_pcb; + constant = s->constant_pcb; + } else { + dev_err(bgp->dev, + "Failed to read PCB state. Using defaults\n"); + } } *temp = ti_thermal_hotspot_temperature(tmp, slope, constant); @@ -273,6 +282,7 @@ static struct ti_thermal_data data->sensor_id = id; data->bgp = bgp; data->mode = THERMAL_DEVICE_ENABLED; + data->pcb_tz = thermal_zone_get_zone_by_name("pcb"); INIT_WORK(&data->thermal_wq, ti_thermal_work); return data; -- GitLab From ba0049eacc59831f4018060dc30fb7c818421a75 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Fri, 7 Jun 2013 19:13:13 +0000 Subject: [PATCH 1053/2900] thermal: ti-soc-thermal: freeze FSM while computing trend In order to read the history buffer, it is required to freeze BG FSM. This patch adds the missing piece of code to freeze the FSM and also a contention area to avoid other parts of the code to access the DTEMPs. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index f20c1cfe9800..219c051d2e68 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -992,9 +992,12 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) goto exit; } + spin_lock(&bgp->lock); + tsr = bgp->conf->sensors[id].registers; /* Freeze and read the last 2 valid readings */ + RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 1); reg1 = tsr->ctrl_dtemp_1; reg2 = tsr->ctrl_dtemp_2; @@ -1008,22 +1011,25 @@ int ti_bandgap_get_trend(struct ti_bandgap *bgp, int id, int *trend) /* Convert from adc values to mCelsius temperature */ ret = ti_bandgap_adc_to_mcelsius(bgp, temp1, &t1); if (ret) - goto exit; + goto unfreeze; ret = ti_bandgap_adc_to_mcelsius(bgp, temp2, &t2); if (ret) - goto exit; + goto unfreeze; /* Fetch the update interval */ ret = ti_bandgap_read_update_interval(bgp, id, &interval); if (ret || !interval) - goto exit; + goto unfreeze; *trend = (t1 - t2) / interval; dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n", t1, t2, *trend); +unfreeze: + RMW_BITS(bgp, id, bgap_mask_ctrl, mask_freeze_mask, 0); + spin_unlock(&bgp->lock); exit: return ret; } -- GitLab From 0c12b5ac82fbae6903237997677c228089569ace Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 15:07:43 +0000 Subject: [PATCH 1054/2900] thermal: ti-soc-thermal: remove usage of IS_ERR_OR_NULL This patch changes the driver to avoid the usage of IS_ERR_OR_NULL() macro. This macro can lead to dangerous results, like returning success (0) during a failure scenario (NULL pointer handling). For this reason this patch is changing the driver after revisiting the code. These are the cases: i. For cases in which IS_ERR_OR_NULL() is used for checking return values of functions that returns either PTR_ERR() or a valid pointer, it has been translated to IS_ERR() check only. ii. For cases that a NULL check is still needed, it has been translated to if (!ptr || IS_ERR(ptr)). Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 10 ++++++---- .../thermal/ti-soc-thermal/ti-thermal-common.c | 15 ++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 219c051d2e68..3f3c512445bb 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -469,7 +469,7 @@ static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id) { int ret = 0; - if (IS_ERR_OR_NULL(bgp)) { + if (!bgp || IS_ERR(bgp)) { pr_err("%s: invalid bandgap pointer\n", __func__); ret = -EINVAL; goto exit; @@ -1197,7 +1197,7 @@ int ti_bandgap_probe(struct platform_device *pdev) int clk_rate, ret = 0, i; bgp = ti_bandgap_build(pdev); - if (IS_ERR_OR_NULL(bgp)) { + if (IS_ERR(bgp)) { dev_err(&pdev->dev, "failed to fetch platform data\n"); return PTR_ERR(bgp); } @@ -1213,17 +1213,19 @@ int ti_bandgap_probe(struct platform_device *pdev) } bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); - ret = IS_ERR_OR_NULL(bgp->fclock); + ret = IS_ERR(bgp->fclock); if (ret) { dev_err(&pdev->dev, "failed to request fclock reference\n"); + ret = PTR_ERR(bgp->fclock); goto free_irqs; } bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); - ret = IS_ERR_OR_NULL(bgp->div_clk); + ret = IS_ERR(bgp->div_clk); if (ret) { dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n"); + ret = PTR_ERR(bgp->div_clk); goto free_irqs; } diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 8e67ebf98404..4c5f55c37349 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -101,7 +101,7 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal, pcb_tz = data->pcb_tz; /* In case pcb zone is available, use the extrapolation rule with it */ - if (!IS_ERR_OR_NULL(pcb_tz)) { + if (!IS_ERR(pcb_tz)) { ret = thermal_zone_get_temp(pcb_tz, &pcb_temp); if (!ret) { tmp -= pcb_temp; /* got a valid PCB temp */ @@ -124,7 +124,7 @@ static int ti_thermal_bind(struct thermal_zone_device *thermal, struct ti_thermal_data *data = thermal->devdata; int id; - if (IS_ERR_OR_NULL(data)) + if (!data || IS_ERR(data)) return -ENODEV; /* check if this is the cooling device we registered */ @@ -146,7 +146,7 @@ static int ti_thermal_unbind(struct thermal_zone_device *thermal, { struct ti_thermal_data *data = thermal->devdata; - if (IS_ERR_OR_NULL(data)) + if (!data || IS_ERR(data)) return -ENODEV; /* check if this is the cooling device we registered */ @@ -282,6 +282,7 @@ static struct ti_thermal_data data->sensor_id = id; data->bgp = bgp; data->mode = THERMAL_DEVICE_ENABLED; + /* pcb_tz will be either valid or PTR_ERR() */ data->pcb_tz = thermal_zone_get_zone_by_name("pcb"); INIT_WORK(&data->thermal_wq, ti_thermal_work); @@ -295,7 +296,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, data = ti_bandgap_get_sensor_data(bgp, id); - if (IS_ERR_OR_NULL(data)) + if (!data || IS_ERR(data)) data = ti_thermal_build_data(bgp, id); if (!data) @@ -306,7 +307,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops, NULL, FAST_TEMP_MONITORING_RATE, FAST_TEMP_MONITORING_RATE); - if (IS_ERR_OR_NULL(data->ti_thermal)) { + if (IS_ERR(data->ti_thermal)) { dev_err(bgp->dev, "thermal zone device is NULL\n"); return PTR_ERR(data->ti_thermal); } @@ -343,7 +344,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) struct ti_thermal_data *data; data = ti_bandgap_get_sensor_data(bgp, id); - if (IS_ERR_OR_NULL(data)) + if (!data || IS_ERR(data)) data = ti_thermal_build_data(bgp, id); if (!data) @@ -356,7 +357,7 @@ int ti_thermal_register_cpu_cooling(struct ti_bandgap *bgp, int id) /* Register cooling device */ data->cool_dev = cpufreq_cooling_register(cpu_present_mask); - if (IS_ERR_OR_NULL(data->cool_dev)) { + if (IS_ERR(data->cool_dev)) { dev_err(bgp->dev, "Failed to register cpufreq cooling device\n"); return PTR_ERR(data->cool_dev); -- GitLab From 8926fa4f9b6160b1953ca44852d6044b58a829e1 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Mon, 3 Jun 2013 20:31:55 +0000 Subject: [PATCH 1055/2900] thermal: ti-soc-thermal: add thermal data for DRA752 chips This patch adds the thermal data for TI DRA752 chips. In this change it includes (autogen): . Register offset definitions . Bitfields and masks for all registers . Conversion table Also, the thermal limits, thresholds and extrapolation rules are included. The extrapolation rule is simply add +2C as margin. All 5 sensors, MPU, GPU, CORE, DSPEVE and IVA, are defined and exposed. Only MPU has cooling device. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/ti-soc-thermal/Kconfig | 12 + drivers/thermal/ti-soc-thermal/Makefile | 1 + .../thermal/ti-soc-thermal/dra752-bandgap.h | 280 +++++++++++ .../ti-soc-thermal/dra752-thermal-data.c | 476 ++++++++++++++++++ drivers/thermal/ti-soc-thermal/ti-thermal.h | 6 + 5 files changed, 775 insertions(+) create mode 100644 drivers/thermal/ti-soc-thermal/dra752-bandgap.h create mode 100644 drivers/thermal/ti-soc-thermal/dra752-thermal-data.c diff --git a/drivers/thermal/ti-soc-thermal/Kconfig b/drivers/thermal/ti-soc-thermal/Kconfig index e81375fb2155..bd4c7beba679 100644 --- a/drivers/thermal/ti-soc-thermal/Kconfig +++ b/drivers/thermal/ti-soc-thermal/Kconfig @@ -46,3 +46,15 @@ config OMAP5_THERMAL This includes alert interrupts generation and also the TSHUT support. + +config DRA752_THERMAL + bool "Texas Instruments DRA752 thermal support" + depends on TI_SOC_THERMAL + depends on SOC_DRA7XX + help + If you say yes here you get thermal support for the Texas Instruments + DRA752 SoC family. The current chip supported are: + - DRA752 + + This includes alert interrupts generation and also the TSHUT + support. diff --git a/drivers/thermal/ti-soc-thermal/Makefile b/drivers/thermal/ti-soc-thermal/Makefile index 0ca034fb419d..1226b2484e55 100644 --- a/drivers/thermal/ti-soc-thermal/Makefile +++ b/drivers/thermal/ti-soc-thermal/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal.o ti-soc-thermal-y := ti-bandgap.o ti-soc-thermal-$(CONFIG_TI_THERMAL) += ti-thermal-common.o +ti-soc-thermal-$(CONFIG_DRA752_THERMAL) += dra752-thermal-data.o ti-soc-thermal-$(CONFIG_OMAP4_THERMAL) += omap4-thermal-data.o ti-soc-thermal-$(CONFIG_OMAP5_THERMAL) += omap5-thermal-data.o diff --git a/drivers/thermal/ti-soc-thermal/dra752-bandgap.h b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h new file mode 100644 index 000000000000..6b0f2b1160f7 --- /dev/null +++ b/drivers/thermal/ti-soc-thermal/dra752-bandgap.h @@ -0,0 +1,280 @@ +/* + * DRA752 bandgap registers, bitfields and temperature definitions + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * Contact: + * Eduardo Valentin + * Tero Kristo + * + * This is an auto generated file. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __DRA752_BANDGAP_H +#define __DRA752_BANDGAP_H + +/** + * *** DRA752 *** + * + * Below, in sequence, are the Register definitions, + * the bitfields and the temperature definitions for DRA752. + */ + +/** + * DRA752 register definitions + * + * Registers are defined as offsets. The offsets are + * relative to FUSE_OPP_BGAP_GPU on DRA752. + * DRA752_BANDGAP_BASE 0x4a0021e0 + * + * Register below are grouped by domain (not necessarily in offset order) + */ + + +/* DRA752.common register offsets */ +#define DRA752_BANDGAP_CTRL_1_OFFSET 0x1a0 +#define DRA752_BANDGAP_STATUS_1_OFFSET 0x1c8 +#define DRA752_BANDGAP_CTRL_2_OFFSET 0x39c +#define DRA752_BANDGAP_STATUS_2_OFFSET 0x3b8 + +/* DRA752.core register offsets */ +#define DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET 0x8 +#define DRA752_TEMP_SENSOR_CORE_OFFSET 0x154 +#define DRA752_BANDGAP_THRESHOLD_CORE_OFFSET 0x1ac +#define DRA752_BANDGAP_TSHUT_CORE_OFFSET 0x1b8 +#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET 0x1c4 +#define DRA752_DTEMP_CORE_0_OFFSET 0x208 +#define DRA752_DTEMP_CORE_1_OFFSET 0x20c +#define DRA752_DTEMP_CORE_2_OFFSET 0x210 +#define DRA752_DTEMP_CORE_3_OFFSET 0x214 +#define DRA752_DTEMP_CORE_4_OFFSET 0x218 + +/* DRA752.iva register offsets */ +#define DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET 0x388 +#define DRA752_TEMP_SENSOR_IVA_OFFSET 0x398 +#define DRA752_BANDGAP_THRESHOLD_IVA_OFFSET 0x3a4 +#define DRA752_BANDGAP_TSHUT_IVA_OFFSET 0x3ac +#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET 0x3b4 +#define DRA752_DTEMP_IVA_0_OFFSET 0x3d0 +#define DRA752_DTEMP_IVA_1_OFFSET 0x3d4 +#define DRA752_DTEMP_IVA_2_OFFSET 0x3d8 +#define DRA752_DTEMP_IVA_3_OFFSET 0x3dc +#define DRA752_DTEMP_IVA_4_OFFSET 0x3e0 + +/* DRA752.mpu register offsets */ +#define DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET 0x4 +#define DRA752_TEMP_SENSOR_MPU_OFFSET 0x14c +#define DRA752_BANDGAP_THRESHOLD_MPU_OFFSET 0x1a4 +#define DRA752_BANDGAP_TSHUT_MPU_OFFSET 0x1b0 +#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET 0x1bc +#define DRA752_DTEMP_MPU_0_OFFSET 0x1e0 +#define DRA752_DTEMP_MPU_1_OFFSET 0x1e4 +#define DRA752_DTEMP_MPU_2_OFFSET 0x1e8 +#define DRA752_DTEMP_MPU_3_OFFSET 0x1ec +#define DRA752_DTEMP_MPU_4_OFFSET 0x1f0 + +/* DRA752.dspeve register offsets */ +#define DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET 0x384 +#define DRA752_TEMP_SENSOR_DSPEVE_OFFSET 0x394 +#define DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET 0x3a0 +#define DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET 0x3a8 +#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET 0x3b0 +#define DRA752_DTEMP_DSPEVE_0_OFFSET 0x3bc +#define DRA752_DTEMP_DSPEVE_1_OFFSET 0x3c0 +#define DRA752_DTEMP_DSPEVE_2_OFFSET 0x3c4 +#define DRA752_DTEMP_DSPEVE_3_OFFSET 0x3c8 +#define DRA752_DTEMP_DSPEVE_4_OFFSET 0x3cc + +/* DRA752.gpu register offsets */ +#define DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET 0x0 +#define DRA752_TEMP_SENSOR_GPU_OFFSET 0x150 +#define DRA752_BANDGAP_THRESHOLD_GPU_OFFSET 0x1a8 +#define DRA752_BANDGAP_TSHUT_GPU_OFFSET 0x1b4 +#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET 0x1c0 +#define DRA752_DTEMP_GPU_0_OFFSET 0x1f4 +#define DRA752_DTEMP_GPU_1_OFFSET 0x1f8 +#define DRA752_DTEMP_GPU_2_OFFSET 0x1fc +#define DRA752_DTEMP_GPU_3_OFFSET 0x200 +#define DRA752_DTEMP_GPU_4_OFFSET 0x204 + +/** + * Register bitfields for DRA752 + * + * All the macros bellow define the required bits for + * controlling temperature on DRA752. Bit defines are + * grouped by register. + */ + +/* DRA752.BANDGAP_STATUS_1 */ +#define DRA752_BANDGAP_STATUS_1_ALERT_MASK BIT(31) +#define DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK BIT(5) +#define DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK BIT(4) +#define DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK BIT(3) +#define DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK BIT(2) +#define DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK BIT(1) +#define DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK BIT(0) + +/* DRA752.BANDGAP_CTRL_2 */ +#define DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK BIT(22) +#define DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK BIT(21) +#define DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK BIT(19) +#define DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK BIT(18) +#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK BIT(16) +#define DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK BIT(15) +#define DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK BIT(3) +#define DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK BIT(2) +#define DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK BIT(1) +#define DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK BIT(0) + +/* DRA752.BANDGAP_STATUS_2 */ +#define DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK BIT(3) +#define DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK BIT(2) +#define DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK BIT(1) +#define DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK BIT(0) + +/* DRA752.BANDGAP_CTRL_1 */ +#define DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK (0x3 << 30) +#define DRA752_BANDGAP_CTRL_1_COUNTER_DELAY_MASK (0x7 << 27) +#define DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK BIT(23) +#define DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK BIT(22) +#define DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK BIT(21) +#define DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK BIT(20) +#define DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK BIT(19) +#define DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK BIT(18) +#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK BIT(17) +#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK BIT(16) +#define DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK BIT(15) +#define DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK BIT(5) +#define DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK BIT(4) +#define DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK BIT(3) +#define DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK BIT(2) +#define DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK BIT(1) +#define DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK BIT(0) + +/* DRA752.TEMP_SENSOR */ +#define DRA752_TEMP_SENSOR_TMPSOFF_MASK BIT(11) +#define DRA752_TEMP_SENSOR_EOCZ_MASK BIT(10) +#define DRA752_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) + +/* DRA752.BANDGAP_THRESHOLD */ +#define DRA752_BANDGAP_THRESHOLD_HOT_MASK (0x3ff << 16) +#define DRA752_BANDGAP_THRESHOLD_COLD_MASK (0x3ff << 0) + +/* DRA752.TSHUT_THRESHOLD */ +#define DRA752_TSHUT_THRESHOLD_MUXCTRL_MASK BIT(31) +#define DRA752_TSHUT_THRESHOLD_HOT_MASK (0x3ff << 16) +#define DRA752_TSHUT_THRESHOLD_COLD_MASK (0x3ff << 0) + +/* DRA752.BANDGAP_CUMUL_DTEMP_CORE */ +#define DRA752_BANDGAP_CUMUL_DTEMP_CORE_MASK (0xffffffff << 0) + +/* DRA752.BANDGAP_CUMUL_DTEMP_IVA */ +#define DRA752_BANDGAP_CUMUL_DTEMP_IVA_MASK (0xffffffff << 0) + +/* DRA752.BANDGAP_CUMUL_DTEMP_MPU */ +#define DRA752_BANDGAP_CUMUL_DTEMP_MPU_MASK (0xffffffff << 0) + +/* DRA752.BANDGAP_CUMUL_DTEMP_DSPEVE */ +#define DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_MASK (0xffffffff << 0) + +/* DRA752.BANDGAP_CUMUL_DTEMP_GPU */ +#define DRA752_BANDGAP_CUMUL_DTEMP_GPU_MASK (0xffffffff << 0) + +/** + * Temperature limits and thresholds for DRA752 + * + * All the macros bellow are definitions for handling the + * ADC conversions and representation of temperature limits + * and thresholds for DRA752. Definitions are grouped + * by temperature domain. + */ + +/* DRA752.common temperature definitions */ +/* ADC conversion table limits */ +#define DRA752_ADC_START_VALUE 540 +#define DRA752_ADC_END_VALUE 945 + +/* DRA752.GPU temperature definitions */ +/* bandgap clock limits */ +#define DRA752_GPU_MAX_FREQ 1500000 +#define DRA752_GPU_MIN_FREQ 1000000 +/* sensor limits */ +#define DRA752_GPU_MIN_TEMP -40000 +#define DRA752_GPU_MAX_TEMP 125000 +#define DRA752_GPU_HYST_VAL 5000 +/* interrupts thresholds */ +#define DRA752_GPU_TSHUT_HOT 915 +#define DRA752_GPU_TSHUT_COLD 900 +#define DRA752_GPU_T_HOT 800 +#define DRA752_GPU_T_COLD 795 + +/* DRA752.MPU temperature definitions */ +/* bandgap clock limits */ +#define DRA752_MPU_MAX_FREQ 1500000 +#define DRA752_MPU_MIN_FREQ 1000000 +/* sensor limits */ +#define DRA752_MPU_MIN_TEMP -40000 +#define DRA752_MPU_MAX_TEMP 125000 +#define DRA752_MPU_HYST_VAL 5000 +/* interrupts thresholds */ +#define DRA752_MPU_TSHUT_HOT 915 +#define DRA752_MPU_TSHUT_COLD 900 +#define DRA752_MPU_T_HOT 800 +#define DRA752_MPU_T_COLD 795 + +/* DRA752.CORE temperature definitions */ +/* bandgap clock limits */ +#define DRA752_CORE_MAX_FREQ 1500000 +#define DRA752_CORE_MIN_FREQ 1000000 +/* sensor limits */ +#define DRA752_CORE_MIN_TEMP -40000 +#define DRA752_CORE_MAX_TEMP 125000 +#define DRA752_CORE_HYST_VAL 5000 +/* interrupts thresholds */ +#define DRA752_CORE_TSHUT_HOT 915 +#define DRA752_CORE_TSHUT_COLD 900 +#define DRA752_CORE_T_HOT 800 +#define DRA752_CORE_T_COLD 795 + +/* DRA752.DSPEVE temperature definitions */ +/* bandgap clock limits */ +#define DRA752_DSPEVE_MAX_FREQ 1500000 +#define DRA752_DSPEVE_MIN_FREQ 1000000 +/* sensor limits */ +#define DRA752_DSPEVE_MIN_TEMP -40000 +#define DRA752_DSPEVE_MAX_TEMP 125000 +#define DRA752_DSPEVE_HYST_VAL 5000 +/* interrupts thresholds */ +#define DRA752_DSPEVE_TSHUT_HOT 915 +#define DRA752_DSPEVE_TSHUT_COLD 900 +#define DRA752_DSPEVE_T_HOT 800 +#define DRA752_DSPEVE_T_COLD 795 + +/* DRA752.IVA temperature definitions */ +/* bandgap clock limits */ +#define DRA752_IVA_MAX_FREQ 1500000 +#define DRA752_IVA_MIN_FREQ 1000000 +/* sensor limits */ +#define DRA752_IVA_MIN_TEMP -40000 +#define DRA752_IVA_MAX_TEMP 125000 +#define DRA752_IVA_HYST_VAL 5000 +/* interrupts thresholds */ +#define DRA752_IVA_TSHUT_HOT 915 +#define DRA752_IVA_TSHUT_COLD 900 +#define DRA752_IVA_T_HOT 800 +#define DRA752_IVA_T_COLD 795 + +#endif /* __DRA752_BANDGAP_H */ diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c new file mode 100644 index 000000000000..e5d8326a54d6 --- /dev/null +++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c @@ -0,0 +1,476 @@ +/* + * DRA752 thermal data. + * + * Copyright (C) 2013 Texas Instruments Inc. + * Contact: + * Eduardo Valentin + * Tero Kristo + * + * This file is partially autogenerated. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ti-thermal.h" +#include "ti-bandgap.h" +#include "dra752-bandgap.h" + +/* + * DRA752 has five instances of thermal sensor: MPU, GPU, CORE, + * IVA and DSPEVE need to describe the individual registers and + * bit fields. + */ + +/* + * DRA752 CORE thermal sensor register offsets and bit-fields + */ +static struct temp_sensor_registers +dra752_core_temp_sensor_registers = { + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_CORE_OFFSET, + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_CORE_MASK, + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_CORE_MASK, + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_CORE_MASK, + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_CORE_MASK, + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_CORE_MASK, + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_CORE_OFFSET, + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, + .tshut_threshold = DRA752_BANDGAP_TSHUT_CORE_OFFSET, + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_CORE_MASK, + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_CORE_MASK, + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_CORE_OFFSET, + .ctrl_dtemp_0 = DRA752_DTEMP_CORE_0_OFFSET, + .ctrl_dtemp_1 = DRA752_DTEMP_CORE_1_OFFSET, + .ctrl_dtemp_2 = DRA752_DTEMP_CORE_2_OFFSET, + .ctrl_dtemp_3 = DRA752_DTEMP_CORE_3_OFFSET, + .ctrl_dtemp_4 = DRA752_DTEMP_CORE_4_OFFSET, + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_CORE_OFFSET, +}; + +/* + * DRA752 IVA thermal sensor register offsets and bit-fields + */ +static struct temp_sensor_registers +dra752_iva_temp_sensor_registers = { + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_IVA_OFFSET, + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, + .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_IVA_MASK, + .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_IVA_MASK, + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, + .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_IVA_MASK, + .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_IVA_MASK, + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_IVA_MASK, + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_IVA_OFFSET, + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, + .tshut_threshold = DRA752_BANDGAP_TSHUT_IVA_OFFSET, + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, + .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, + .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_IVA_MASK, + .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_IVA_MASK, + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_IVA_OFFSET, + .ctrl_dtemp_0 = DRA752_DTEMP_IVA_0_OFFSET, + .ctrl_dtemp_1 = DRA752_DTEMP_IVA_1_OFFSET, + .ctrl_dtemp_2 = DRA752_DTEMP_IVA_2_OFFSET, + .ctrl_dtemp_3 = DRA752_DTEMP_IVA_3_OFFSET, + .ctrl_dtemp_4 = DRA752_DTEMP_IVA_4_OFFSET, + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_IVA_OFFSET, +}; + +/* + * DRA752 MPU thermal sensor register offsets and bit-fields + */ +static struct temp_sensor_registers +dra752_mpu_temp_sensor_registers = { + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_MPU_OFFSET, + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_MPU_MASK, + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_MPU_MASK, + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_MPU_MASK, + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_MPU_MASK, + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_MPU_MASK, + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_MPU_OFFSET, + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, + .tshut_threshold = DRA752_BANDGAP_TSHUT_MPU_OFFSET, + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_MPU_MASK, + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_MPU_MASK, + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_MPU_OFFSET, + .ctrl_dtemp_0 = DRA752_DTEMP_MPU_0_OFFSET, + .ctrl_dtemp_1 = DRA752_DTEMP_MPU_1_OFFSET, + .ctrl_dtemp_2 = DRA752_DTEMP_MPU_2_OFFSET, + .ctrl_dtemp_3 = DRA752_DTEMP_MPU_3_OFFSET, + .ctrl_dtemp_4 = DRA752_DTEMP_MPU_4_OFFSET, + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_MPU_OFFSET, +}; + +/* + * DRA752 DSPEVE thermal sensor register offsets and bit-fields + */ +static struct temp_sensor_registers +dra752_dspeve_temp_sensor_registers = { + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_DSPEVE_OFFSET, + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_2_OFFSET, + .mask_hot_mask = DRA752_BANDGAP_CTRL_2_MASK_HOT_DSPEVE_MASK, + .mask_cold_mask = DRA752_BANDGAP_CTRL_2_MASK_COLD_DSPEVE_MASK, + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, + .mask_freeze_mask = DRA752_BANDGAP_CTRL_2_FREEZE_DSPEVE_MASK, + .mask_clear_mask = DRA752_BANDGAP_CTRL_2_CLEAR_DSPEVE_MASK, + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_2_CLEAR_ACCUM_DSPEVE_MASK, + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_DSPEVE_OFFSET, + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, + .tshut_threshold = DRA752_BANDGAP_TSHUT_DSPEVE_OFFSET, + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, + .bgap_status = DRA752_BANDGAP_STATUS_2_OFFSET, + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, + .status_hot_mask = DRA752_BANDGAP_STATUS_2_HOT_DSPEVE_MASK, + .status_cold_mask = DRA752_BANDGAP_STATUS_2_COLD_DSPEVE_MASK, + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_DSPEVE_OFFSET, + .ctrl_dtemp_0 = DRA752_DTEMP_DSPEVE_0_OFFSET, + .ctrl_dtemp_1 = DRA752_DTEMP_DSPEVE_1_OFFSET, + .ctrl_dtemp_2 = DRA752_DTEMP_DSPEVE_2_OFFSET, + .ctrl_dtemp_3 = DRA752_DTEMP_DSPEVE_3_OFFSET, + .ctrl_dtemp_4 = DRA752_DTEMP_DSPEVE_4_OFFSET, + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_DSPEVE_OFFSET, +}; + +/* + * DRA752 GPU thermal sensor register offsets and bit-fields + */ +static struct temp_sensor_registers +dra752_gpu_temp_sensor_registers = { + .temp_sensor_ctrl = DRA752_TEMP_SENSOR_GPU_OFFSET, + .bgap_tempsoff_mask = DRA752_TEMP_SENSOR_TMPSOFF_MASK, + .bgap_eocz_mask = DRA752_TEMP_SENSOR_EOCZ_MASK, + .bgap_dtemp_mask = DRA752_TEMP_SENSOR_DTEMP_MASK, + .bgap_mask_ctrl = DRA752_BANDGAP_CTRL_1_OFFSET, + .mask_hot_mask = DRA752_BANDGAP_CTRL_1_MASK_HOT_GPU_MASK, + .mask_cold_mask = DRA752_BANDGAP_CTRL_1_MASK_COLD_GPU_MASK, + .mask_sidlemode_mask = DRA752_BANDGAP_CTRL_1_SIDLEMODE_MASK, + .mask_freeze_mask = DRA752_BANDGAP_CTRL_1_FREEZE_GPU_MASK, + .mask_clear_mask = DRA752_BANDGAP_CTRL_1_CLEAR_GPU_MASK, + .mask_clear_accum_mask = DRA752_BANDGAP_CTRL_1_CLEAR_ACCUM_GPU_MASK, + .bgap_threshold = DRA752_BANDGAP_THRESHOLD_GPU_OFFSET, + .threshold_thot_mask = DRA752_BANDGAP_THRESHOLD_HOT_MASK, + .threshold_tcold_mask = DRA752_BANDGAP_THRESHOLD_COLD_MASK, + .tshut_threshold = DRA752_BANDGAP_TSHUT_GPU_OFFSET, + .tshut_hot_mask = DRA752_TSHUT_THRESHOLD_HOT_MASK, + .tshut_cold_mask = DRA752_TSHUT_THRESHOLD_COLD_MASK, + .bgap_status = DRA752_BANDGAP_STATUS_1_OFFSET, + .status_bgap_alert_mask = DRA752_BANDGAP_STATUS_1_ALERT_MASK, + .status_hot_mask = DRA752_BANDGAP_STATUS_1_HOT_GPU_MASK, + .status_cold_mask = DRA752_BANDGAP_STATUS_1_COLD_GPU_MASK, + .bgap_cumul_dtemp = DRA752_BANDGAP_CUMUL_DTEMP_GPU_OFFSET, + .ctrl_dtemp_0 = DRA752_DTEMP_GPU_0_OFFSET, + .ctrl_dtemp_1 = DRA752_DTEMP_GPU_1_OFFSET, + .ctrl_dtemp_2 = DRA752_DTEMP_GPU_2_OFFSET, + .ctrl_dtemp_3 = DRA752_DTEMP_GPU_3_OFFSET, + .ctrl_dtemp_4 = DRA752_DTEMP_GPU_4_OFFSET, + .bgap_efuse = DRA752_STD_FUSE_OPP_BGAP_GPU_OFFSET, +}; + +/* Thresholds and limits for DRA752 MPU temperature sensor */ +static struct temp_sensor_data dra752_mpu_temp_sensor_data = { + .tshut_hot = DRA752_MPU_TSHUT_HOT, + .tshut_cold = DRA752_MPU_TSHUT_COLD, + .t_hot = DRA752_MPU_T_HOT, + .t_cold = DRA752_MPU_T_COLD, + .min_freq = DRA752_MPU_MIN_FREQ, + .max_freq = DRA752_MPU_MAX_FREQ, + .max_temp = DRA752_MPU_MAX_TEMP, + .min_temp = DRA752_MPU_MIN_TEMP, + .hyst_val = DRA752_MPU_HYST_VAL, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for DRA752 GPU temperature sensor */ +static struct temp_sensor_data dra752_gpu_temp_sensor_data = { + .tshut_hot = DRA752_GPU_TSHUT_HOT, + .tshut_cold = DRA752_GPU_TSHUT_COLD, + .t_hot = DRA752_GPU_T_HOT, + .t_cold = DRA752_GPU_T_COLD, + .min_freq = DRA752_GPU_MIN_FREQ, + .max_freq = DRA752_GPU_MAX_FREQ, + .max_temp = DRA752_GPU_MAX_TEMP, + .min_temp = DRA752_GPU_MIN_TEMP, + .hyst_val = DRA752_GPU_HYST_VAL, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for DRA752 CORE temperature sensor */ +static struct temp_sensor_data dra752_core_temp_sensor_data = { + .tshut_hot = DRA752_CORE_TSHUT_HOT, + .tshut_cold = DRA752_CORE_TSHUT_COLD, + .t_hot = DRA752_CORE_T_HOT, + .t_cold = DRA752_CORE_T_COLD, + .min_freq = DRA752_CORE_MIN_FREQ, + .max_freq = DRA752_CORE_MAX_FREQ, + .max_temp = DRA752_CORE_MAX_TEMP, + .min_temp = DRA752_CORE_MIN_TEMP, + .hyst_val = DRA752_CORE_HYST_VAL, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for DRA752 DSPEVE temperature sensor */ +static struct temp_sensor_data dra752_dspeve_temp_sensor_data = { + .tshut_hot = DRA752_DSPEVE_TSHUT_HOT, + .tshut_cold = DRA752_DSPEVE_TSHUT_COLD, + .t_hot = DRA752_DSPEVE_T_HOT, + .t_cold = DRA752_DSPEVE_T_COLD, + .min_freq = DRA752_DSPEVE_MIN_FREQ, + .max_freq = DRA752_DSPEVE_MAX_FREQ, + .max_temp = DRA752_DSPEVE_MAX_TEMP, + .min_temp = DRA752_DSPEVE_MIN_TEMP, + .hyst_val = DRA752_DSPEVE_HYST_VAL, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* Thresholds and limits for DRA752 IVA temperature sensor */ +static struct temp_sensor_data dra752_iva_temp_sensor_data = { + .tshut_hot = DRA752_IVA_TSHUT_HOT, + .tshut_cold = DRA752_IVA_TSHUT_COLD, + .t_hot = DRA752_IVA_T_HOT, + .t_cold = DRA752_IVA_T_COLD, + .min_freq = DRA752_IVA_MIN_FREQ, + .max_freq = DRA752_IVA_MAX_FREQ, + .max_temp = DRA752_IVA_MAX_TEMP, + .min_temp = DRA752_IVA_MIN_TEMP, + .hyst_val = DRA752_IVA_HYST_VAL, + .update_int1 = 1000, + .update_int2 = 2000, +}; + +/* + * DRA752 : Temperature values in milli degree celsius + * ADC code values from 540 to 945 + */ +static +int dra752_adc_to_temp[DRA752_ADC_END_VALUE - DRA752_ADC_START_VALUE + 1] = { + /* Index 540 - 549 */ + -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200, + -37800, + /* Index 550 - 559 */ + -37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200, -33800, + -33400, + /* Index 560 - 569 */ + -33000, -32600, -32200, -31800, -31400, -31000, -30600, -30200, -29800, + -29400, + /* Index 570 - 579 */ + -29000, -28600, -28200, -27700, -27100, -26600, -26200, -25800, -25400, + -25000, + /* Index 580 - 589 */ + -24600, -24200, -23800, -23400, -23000, -22600, -22200, -21800, -21400, + -21000, + /* Index 590 - 599 */ + -20500, -19900, -19400, -19000, -18600, -18200, -17800, -17400, -17000, + -16600, + /* Index 600 - 609 */ + -16200, -15800, -15400, -15000, -14600, -14200, -13800, -13400, -13000, + -12500, + /* Index 610 - 619 */ + -11900, -11400, -11000, -10600, -10200, -9800, -9400, -9000, -8600, + -8200, + /* Index 620 - 629 */ + -7800, -7400, -7000, -6600, -6200, -5800, -5400, -5000, -4500, + -3900, + /* Index 630 - 639 */ + -3400, -3000, -2600, -2200, -1800, -1400, -1000, -600, -200, + 200, + /* Index 640 - 649 */ + 600, 1000, 1400, 1800, 2200, 2600, 3000, 3400, 3900, + 4500, + /* Index 650 - 659 */ + 5000, 5400, 5800, 6200, 6600, 7000, 7400, 7800, 8200, + 8600, + /* Index 660 - 669 */ + 9000, 9400, 9800, 10200, 10600, 11000, 11400, 11800, 12200, + 12700, + /* Index 670 - 679 */ + 13300, 13800, 14200, 14600, 15000, 15400, 15800, 16200, 16600, + 17000, + /* Index 680 - 689 */ + 17400, 17800, 18200, 18600, 19000, 19400, 19800, 20200, 20600, + 21000, + /* Index 690 - 699 */ + 21400, 21900, 22500, 23000, 23400, 23800, 24200, 24600, 25000, + 25400, + /* Index 700 - 709 */ + 25800, 26200, 26600, 27000, 27400, 27800, 28200, 28600, 29000, + 29400, + /* Index 710 - 719 */ + 29800, 30200, 30600, 31000, 31400, 31900, 32500, 33000, 33400, + 33800, + /* Index 720 - 729 */ + 34200, 34600, 35000, 35400, 35800, 36200, 36600, 37000, 37400, + 37800, + /* Index 730 - 739 */ + 38200, 38600, 39000, 39400, 39800, 40200, 40600, 41000, 41400, + 41800, + /* Index 740 - 749 */ + 42200, 42600, 43100, 43700, 44200, 44600, 45000, 45400, 45800, + 46200, + /* Index 750 - 759 */ + 46600, 47000, 47400, 47800, 48200, 48600, 49000, 49400, 49800, + 50200, + /* Index 760 - 769 */ + 50600, 51000, 51400, 51800, 52200, 52600, 53000, 53400, 53800, + 54200, + /* Index 770 - 779 */ + 54600, 55000, 55400, 55900, 56500, 57000, 57400, 57800, 58200, + 58600, + /* Index 780 - 789 */ + 59000, 59400, 59800, 60200, 60600, 61000, 61400, 61800, 62200, + 62600, + /* Index 790 - 799 */ + 63000, 63400, 63800, 64200, 64600, 65000, 65400, 65800, 66200, + 66600, + /* Index 800 - 809 */ + 67000, 67400, 67800, 68200, 68600, 69000, 69400, 69800, 70200, + 70600, + /* Index 810 - 819 */ + 71000, 71500, 72100, 72600, 73000, 73400, 73800, 74200, 74600, + 75000, + /* Index 820 - 829 */ + 75400, 75800, 76200, 76600, 77000, 77400, 77800, 78200, 78600, + 79000, + /* Index 830 - 839 */ + 79400, 79800, 80200, 80600, 81000, 81400, 81800, 82200, 82600, + 83000, + /* Index 840 - 849 */ + 83400, 83800, 84200, 84600, 85000, 85400, 85800, 86200, 86600, + 87000, + /* Index 850 - 859 */ + 87400, 87800, 88200, 88600, 89000, 89400, 89800, 90200, 90600, + 91000, + /* Index 860 - 869 */ + 91400, 91800, 92200, 92600, 93000, 93400, 93800, 94200, 94600, + 95000, + /* Index 870 - 879 */ + 95400, 95800, 96200, 96600, 97000, 97500, 98100, 98600, 99000, + 99400, + /* Index 880 - 889 */ + 99800, 100200, 100600, 101000, 101400, 101800, 102200, 102600, 103000, + 103400, + /* Index 890 - 899 */ + 103800, 104200, 104600, 105000, 105400, 105800, 106200, 106600, 107000, + 107400, + /* Index 900 - 909 */ + 107800, 108200, 108600, 109000, 109400, 109800, 110200, 110600, 111000, + 111400, + /* Index 910 - 919 */ + 111800, 112200, 112600, 113000, 113400, 113800, 114200, 114600, 115000, + 115400, + /* Index 920 - 929 */ + 115800, 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000, + 119400, + /* Index 930 - 939 */ + 119800, 120200, 120600, 121000, 121400, 121800, 122200, 122600, 123000, + 123400, + /* Index 940 - 945 */ + 123800, 124200, 124600, 124900, 125000, 125000, +}; + +/* DRA752 data */ +const struct ti_bandgap_data dra752_data = { + .features = TI_BANDGAP_FEATURE_TSHUT_CONFIG | + TI_BANDGAP_FEATURE_FREEZE_BIT | + TI_BANDGAP_FEATURE_TALERT | + TI_BANDGAP_FEATURE_COUNTER_DELAY | + TI_BANDGAP_FEATURE_HISTORY_BUFFER, + .fclock_name = "l3instr_ts_gclk_div", + .div_ck_name = "l3instr_ts_gclk_div", + .conv_table = dra752_adc_to_temp, + .adc_start_val = DRA752_ADC_START_VALUE, + .adc_end_val = DRA752_ADC_END_VALUE, + .expose_sensor = ti_thermal_expose_sensor, + .remove_sensor = ti_thermal_remove_sensor, + .sensors = { + { + .registers = &dra752_mpu_temp_sensor_registers, + .ts_data = &dra752_mpu_temp_sensor_data, + .domain = "cpu", + .register_cooling = ti_thermal_register_cpu_cooling, + .unregister_cooling = ti_thermal_unregister_cpu_cooling, + .slope = DRA752_GRADIENT_SLOPE, + .constant = DRA752_GRADIENT_CONST, + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, + }, + { + .registers = &dra752_gpu_temp_sensor_registers, + .ts_data = &dra752_gpu_temp_sensor_data, + .domain = "gpu", + .slope = DRA752_GRADIENT_SLOPE, + .constant = DRA752_GRADIENT_CONST, + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, + }, + { + .registers = &dra752_core_temp_sensor_registers, + .ts_data = &dra752_core_temp_sensor_data, + .domain = "core", + .slope = DRA752_GRADIENT_SLOPE, + .constant = DRA752_GRADIENT_CONST, + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, + }, + { + .registers = &dra752_dspeve_temp_sensor_registers, + .ts_data = &dra752_dspeve_temp_sensor_data, + .domain = "dspeve", + .slope = DRA752_GRADIENT_SLOPE, + .constant = DRA752_GRADIENT_CONST, + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, + }, + { + .registers = &dra752_iva_temp_sensor_registers, + .ts_data = &dra752_iva_temp_sensor_data, + .domain = "iva", + .slope = DRA752_GRADIENT_SLOPE, + .constant = DRA752_GRADIENT_CONST, + .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB, + .constant_pcb = DRA752_GRADIENT_CONST_W_PCB, + }, + }, + .sensor_count = 5, +}; diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal.h b/drivers/thermal/ti-soc-thermal/ti-thermal.h index 5055777727cc..f8b7ffea6194 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal.h +++ b/drivers/thermal/ti-soc-thermal/ti-thermal.h @@ -38,6 +38,9 @@ #define OMAP_GRADIENT_SLOPE_5430_GPU 117 #define OMAP_GRADIENT_CONST_5430_GPU -2992 +#define DRA752_GRADIENT_SLOPE 0 +#define DRA752_GRADIENT_CONST 2000 + /* PCB sensor calculation constants */ #define OMAP_GRADIENT_SLOPE_W_PCB_4430 0 #define OMAP_GRADIENT_CONST_W_PCB_4430 20000 @@ -51,6 +54,9 @@ #define OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU 464 #define OMAP_GRADIENT_CONST_W_PCB_5430_GPU -5102 +#define DRA752_GRADIENT_SLOPE_W_PCB 0 +#define DRA752_GRADIENT_CONST_W_PCB 2000 + /* trip points of interest in milicelsius (at hotspot level) */ #define OMAP_TRIP_COLD 100000 #define OMAP_TRIP_HOT 110000 -- GitLab From 25870e623476ac210f914d6a0a33bea8baa9eadb Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 15:07:45 +0000 Subject: [PATCH 1056/2900] thermal: ti-soc-thermal: add dra752 chip to device table Add support to TI dra752 chips by adapting the driver device table. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 6 ++++++ drivers/thermal/ti-soc-thermal/ti-bandgap.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 3f3c512445bb..7c0b3ebcf83a 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1530,6 +1530,12 @@ static const struct of_device_id of_ti_bandgap_match[] = { .compatible = "ti,omap5430-bandgap", .data = (void *)&omap5430_data, }, +#endif +#ifdef CONFIG_DRA752_THERMAL + { + .compatible = "ti,dra752-bandgap", + .data = (void *)&dra752_data, + }, #endif /* Sentinel */ { }, diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index 5f4794abf583..b3adf72f252d 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -400,4 +400,9 @@ extern const struct ti_bandgap_data omap5430_data; #define omap5430_data NULL #endif +#ifdef CONFIG_DRA752_THERMAL +extern const struct ti_bandgap_data dra752_data; +#else +#define dra752_data NULL +#endif #endif -- GitLab From ca0c711463565a8735b24f3b08310287adb6b4c9 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 15:07:46 +0000 Subject: [PATCH 1057/2900] thermal: ti-soc-thermal: add DT example for DRA752 chip Update documentation by adding an example for DRA752 on DT description. Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: Greg Kroah-Hartman Cc: Zhang Rui Cc: J Keerthy Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- .../devicetree/bindings/thermal/ti_soc_thermal.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt index 1629652372b6..1953b33cad51 100644 --- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt @@ -59,3 +59,15 @@ bandgap { compatible = "ti,omap5430-bandgap"; interrupts = <0 126 4>; /* talert */ }; + +DRA752: +bandgap { + reg = <0x4a0021e0 0xc + 0x4a00232c 0xc + 0x4a002380 0x2c + 0x4a0023C0 0x3c + 0x4a002564 0x8 + 0x4a002574 0x50>; + compatible = "ti,dra752-bandgap"; + interrupts = <0 126 4>; /* talert */ +}; -- GitLab From 0c872507d84a6193cd769a808e65d34e1514b083 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Wed, 29 May 2013 21:37:00 +0000 Subject: [PATCH 1058/2900] thermal: consider emul_temperature while computing trend In case emulated temperature is in use, using the trend provided by driver layer can lead to bogus situation. In this case, debugger user would set a temperature value, but the trend would be from driver computation. To avoid this situation, this patch changes the get_tz_trend() to consider the emulated temperature whenever that is in use. Cc: Zhang Rui Cc: Amit Daniel Kachhap Cc: Durgadoss R Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Zhang Rui --- drivers/thermal/thermal_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d755440791b7..c00dc9275fc0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -155,7 +155,8 @@ int get_tz_trend(struct thermal_zone_device *tz, int trip) { enum thermal_trend trend; - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { + if (tz->emul_temperature || !tz->ops->get_trend || + tz->ops->get_trend(tz, trip, &trend)) { if (tz->temperature > tz->last_temperature) trend = THERMAL_TREND_RAISING; else if (tz->temperature < tz->last_temperature) -- GitLab From ca15febfe98f7c681ac345fc1d2ee1b8decaa493 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 13 Jun 2013 10:05:38 +0800 Subject: [PATCH 1059/2900] netlink: make compare exist all the time Commit da12c90e099789a63073fc82a19542ce54d4efb9 "netlink: Add compare function for netlink_table" only set compare at the time we create kernel netlink, and reset compare to NULL at the time we finially release netlink socket, but netlink_lookup wants the compare exist always. So we should set compare after we allocate nl_table, and never reset it. make comapre exist all the time. Reported-by: Fengguang Wu Signed-off-by: Gao feng Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9b6b115e008f..8978755251f7 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1174,7 +1174,6 @@ static int netlink_release(struct socket *sock) kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].bind = NULL; - nl_table[sk->sk_protocol].compare = NULL; nl_table[sk->sk_protocol].flags = 0; nl_table[sk->sk_protocol].registered = 0; } @@ -2326,7 +2325,6 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, rcu_assign_pointer(nl_table[unit].listeners, listeners); nl_table[unit].cb_mutex = cb_mutex; nl_table[unit].module = module; - nl_table[unit].compare = netlink_compare; if (cfg) { nl_table[unit].bind = cfg->bind; nl_table[unit].flags = cfg->flags; @@ -2973,6 +2971,8 @@ static int __init netlink_proto_init(void) hash->shift = 0; hash->mask = 0; hash->rehash_time = jiffies; + + nl_table[i].compare = netlink_compare; } netlink_add_usersock_entry(); -- GitLab From 2c928e0e8dd6b3661870bfacb53d1c330a1a7411 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 13 Jun 2013 16:04:33 +0900 Subject: [PATCH 1060/2900] sctp: Correct byte order of access to skb->{network, transport}_header Corrects an byte order conflict introduced by 158874cac61245b84e939c92c53db7000122b7b0 ("sctp: Correct access to skb->{network, transport}_header"). The values in question are host byte order. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/sctp/ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 8ee553b499ce..fffc7b62a9a8 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -153,7 +153,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct sctp_association *asoc; struct sctp_transport *transport; struct ipv6_pinfo *np; - __be16 saveip, savesctp; + __u16 saveip, savesctp; int err; struct net *net = dev_net(skb->dev); -- GitLab From d9a90a3105eb6ca89aab74223e6526ab4a5e44b5 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 13 Jun 2013 14:23:35 +0800 Subject: [PATCH 1061/2900] macvtap: slient sparse warnings This patch silents the following sparse warnings: drivers/net/macvtap.c:98:9: warning: incorrect type in assignment (different address spaces) drivers/net/macvtap.c:98:9: expected struct macvtap_queue * drivers/net/macvtap.c:98:9: got struct macvtap_queue [noderef] * drivers/net/macvtap.c:120:9: warning: incorrect type in assignment (different address spaces) drivers/net/macvtap.c:120:9: expected struct macvtap_queue * drivers/net/macvtap.c:120:9: got struct macvtap_queue [noderef] * drivers/net/macvtap.c:151:22: error: incompatible types in comparison expression (different address spaces) drivers/net/macvtap.c:233:23: error: incompatible types in comparison expression (different address spaces) drivers/net/macvtap.c:243:23: error: incompatible types in comparison expression (different address spaces) drivers/net/macvtap.c:247:15: error: incompatible types in comparison expression (different address spaces) CC [M] drivers/net/macvtap.o drivers/net/macvlan.c:232:24: error: incompatible types in comparison expression (different address spaces) Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 +- include/linux/if_macvlan.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 992151ce08a4..edcbf1c0d6ed 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -429,7 +429,7 @@ static int macvtap_open(struct inode *inode, struct file *file) if (!q) goto out; - q->sock.wq = &q->wq; + RCU_INIT_POINTER(q->sock.wq, &q->wq); init_waitqueue_head(&q->wq.wait); q->sock.type = SOCK_RAW; q->sock.state = SS_CONNECTED; diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 19121331a5ed..f49a9f66c3d9 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -70,7 +70,7 @@ struct macvlan_dev { int (*receive)(struct sk_buff *skb); int (*forward)(struct net_device *dev, struct sk_buff *skb); /* This array tracks active taps. */ - struct macvtap_queue *taps[MAX_MACVTAP_QUEUES]; + struct macvtap_queue __rcu *taps[MAX_MACVTAP_QUEUES]; /* This list tracks all taps (both enabled and disabled) */ struct list_head queue_list; int numvtaps; -- GitLab From f57855a54fb1e7529b32821f021d351e01dcfe39 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 13 Jun 2013 14:23:36 +0800 Subject: [PATCH 1062/2900] macvtap: fix uninitialized return value macvtap_ioctl_set_queue() Return -EINVAL on illegal flag instead of uninitialized value. This fixes the kbuild test warning. Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index edcbf1c0d6ed..5a76f20776af 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -969,6 +969,8 @@ static int macvtap_ioctl_set_queue(struct file *file, unsigned int flags) ret = macvtap_enable_queue(vlan->dev, file, q); else if (flags & IFF_DETACH_QUEUE) ret = macvtap_disable_queue(q); + else + ret = -EINVAL; macvtap_put_vlan(vlan); return ret; -- GitLab From 8c367fcbe6549195d2eb11e62bea233f811aad41 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 10 Jun 2013 17:34:13 +0100 Subject: [PATCH 1063/2900] cxgb4: Do not set net_device::dev_id to VI index net_device::dev_id should not be used merely to indicate a VI index, as it affects the way the local part of IPv6 addresses is normally generated. This field was intended for use where multiple devices may share a single assigned MAC address and need to have different IPv6 addresses. T4 VIs each have their own MAC address. Signed-off-by: Ben Hutchings Acked-by: Dimitris Michailidis Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index bff89a437b76..4cbb2f9850be 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -3782,7 +3782,6 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf) p->lport = j; p->rss_size = rss_size; memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN); - adap->port[i]->dev_id = j; ret = ntohl(c.u.info.lstatus_to_modtype); p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP) ? -- GitLab From e562078a19226660299eeaf40a50752672214f11 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 12 Jun 2013 14:08:44 -0700 Subject: [PATCH 1064/2900] mac80211: Ensure tid_start_tx is protected by sta->lock All accesses of the tid_start_tx lock should be protected by sta->lock if there is any chance that another thread could still be accessing the sta object. Signed-off-by: Ben Greear Signed-off-by: Johannes Berg --- net/mac80211/ht.c | 4 +++- net/mac80211/sta_info.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 75dff338f581..f83534f6a2ee 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -281,13 +281,14 @@ void ieee80211_ba_session_work(struct work_struct *work) sta, tid, WLAN_BACK_RECIPIENT, WLAN_REASON_UNSPECIFIED, true); + spin_lock_bh(&sta->lock); + tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; if (tid_tx) { /* * Assign it over to the normal tid_tx array * where it "goes live". */ - spin_lock_bh(&sta->lock); sta->ampdu_mlme.tid_start_tx[tid] = NULL; /* could there be a race? */ @@ -300,6 +301,7 @@ void ieee80211_ba_session_work(struct work_struct *work) ieee80211_tx_ba_session_handle_start(sta, tid); continue; } + spin_unlock_bh(&sta->lock); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index bd12fc54266c..4208dbd5861f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -203,6 +203,7 @@ struct tid_ampdu_rx { * driver requested to close until the work for it runs * @mtx: mutex to protect all TX data (except non-NULL assignments * to tid_tx[idx], which are protected by the sta spinlock) + * tid_start_tx is also protected by sta->lock. */ struct sta_ampdu_mlme { struct mutex mtx; -- GitLab From a06a2d378dbf099c874ad58de07a8e54ffdc94d3 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Wed, 12 Jun 2013 21:04:16 +0800 Subject: [PATCH 1065/2900] net: ping_check_bind_addr() etc. can be static net/ipv4/ping.c:286:5: sparse: symbol 'ping_check_bind_addr' was not declared. Should it be static? net/ipv4/ping.c:355:6: sparse: symbol 'ping_set_saddr' was not declared. Should it be static? net/ipv4/ping.c:370:6: sparse: symbol 'ping_clear_saddr' was not declared. Should it be static? net/ipv6/ping.c:60:5: sparse: symbol 'dummy_ipv6_recv_error' was not declared. Should it be static? net/ipv6/ping.c:64:5: sparse: symbol 'dummy_ip6_datagram_recv_ctl' was not declared. Should it be static? net/ipv6/ping.c:69:5: sparse: symbol 'dummy_icmpv6_err_convert' was not declared. Should it be static? net/ipv6/ping.c:73:6: sparse: symbol 'dummy_ipv6_icmp_error' was not declared. Should it be static? net/ipv6/ping.c:75:5: sparse: symbol 'dummy_ipv6_chk_addr' was not declared. Should it be static? net/ipv6/ping.c:201:5: sparse: symbol 'ping_v6_seq_show' was not declared. Should it be static? Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- net/ipv4/ping.c | 8 ++++---- net/ipv6/ping.c | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 1f1b2dd90277..746427c9e719 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -283,8 +283,8 @@ void ping_close(struct sock *sk, long timeout) EXPORT_SYMBOL_GPL(ping_close); /* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */ -int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, - struct sockaddr *uaddr, int addr_len) { +static int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + struct sockaddr *uaddr, int addr_len) { struct net *net = sock_net(sk); if (sk->sk_family == AF_INET) { struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; @@ -352,7 +352,7 @@ int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, return 0; } -void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) +static void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) { if (saddr->sa_family == AF_INET) { struct inet_sock *isk = inet_sk(sk); @@ -367,7 +367,7 @@ void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) } } -void ping_clear_saddr(struct sock *sk, int dif) +static void ping_clear_saddr(struct sock *sk, int dif) { sk->sk_bound_dev_if = dif; if (sk->sk_family == AF_INET) { diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index a43110385918..2b52046e1263 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -57,23 +57,23 @@ static struct inet_protosw pingv6_protosw = { /* Compatibility glue so we can support IPv6 when it's compiled as a module */ -int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +static int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) { return -EAFNOSUPPORT; } -int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, - struct sk_buff *skb) +static int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb) { return -EAFNOSUPPORT; } -int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) +static int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) { return -EAFNOSUPPORT; } -void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, - __be16 port, u32 info, u8 *payload) {} -int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, - const struct net_device *dev, int strict) +static void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload) {} +static int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, + const struct net_device *dev, int strict) { return 0; } @@ -198,7 +198,7 @@ static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos) return ping_seq_start(seq, pos, AF_INET6); } -int ping_v6_seq_show(struct seq_file *seq, void *v) +static int ping_v6_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) { seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); -- GitLab From 194f4a6df2a92c3d0bc65a85facfbc2433b25d06 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Tue, 11 Jun 2013 23:09:29 +0200 Subject: [PATCH 1066/2900] net: make all team port device link events urgent Since team functionality relies heavily on userspace daemon, we need to deliver event to userspace via Netlink as quick as possible. So make all team port device link events urgent. Signed-off-by: Flavio Leitner Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/link_watch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 8f82a5cc3851..9c3a839322ba 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -92,6 +92,9 @@ static bool linkwatch_urgent_event(struct net_device *dev) if (dev->ifindex != dev->iflink) return true; + if (dev->priv_flags & IFF_TEAM_PORT) + return true; + return netif_carrier_ok(dev) && qdisc_tx_changing(dev); } -- GitLab From fe2c6338fd2c6f383c4d4164262f35c8f3708e1f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Jun 2013 23:04:25 -0700 Subject: [PATCH 1067/2900] net: Convert uses of typedef ctl_table to struct ctl_table Reduce the uses of this unnecessary typedef. Done via perl script: $ git grep --name-only -w ctl_table net | \ xargs perl -p -i -e '\ sub trim { my ($local) = @_; $local =~ s/(^\s+|\s+$)//g; return $local; } \ s/\b(? Signed-off-by: David S. Miller --- net/ax25/sysctl_net_ax25.c | 2 +- net/bridge/br_netfilter.c | 4 +-- net/core/neighbour.c | 6 ++-- net/core/sysctl_net_core.c | 8 ++--- net/decnet/dn_dev.c | 6 ++-- net/decnet/sysctl_net_decnet.c | 6 ++-- net/ipv4/devinet.c | 6 ++-- .../netfilter/nf_conntrack_l3proto_ipv4.c | 2 +- net/ipv4/route.c | 4 +-- net/ipv4/sysctl_net_ipv4.c | 31 ++++++++++--------- net/ipv6/addrconf.c | 10 +++--- net/ipv6/icmp.c | 2 +- net/ipv6/route.c | 4 +-- net/ipv6/sysctl_net_ipv6.c | 4 +-- net/irda/irsysctl.c | 6 ++-- net/netfilter/ipvs/ip_vs_ctl.c | 8 ++--- net/netfilter/ipvs/ip_vs_lblc.c | 2 +- net/netfilter/ipvs/ip_vs_lblcr.c | 2 +- net/netfilter/nf_conntrack_standalone.c | 4 +-- net/netfilter/nf_log.c | 2 +- net/netrom/sysctl_net_netrom.c | 2 +- net/phonet/sysctl.c | 4 +-- net/rds/ib_sysctl.c | 2 +- net/rds/iw_sysctl.c | 2 +- net/rds/sysctl.c | 2 +- net/rose/sysctl_net_rose.c | 2 +- net/sctp/sysctl.c | 10 +++--- net/sunrpc/sysctl.c | 10 +++--- net/sunrpc/xprtrdma/svc_rdma.c | 8 ++--- net/sunrpc/xprtrdma/transport.c | 4 +-- net/sunrpc/xprtsock.c | 4 +-- net/unix/sysctl_net_unix.c | 2 +- 32 files changed, 86 insertions(+), 85 deletions(-) diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index d5744b752511..919a5ce47515 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -29,7 +29,7 @@ static int min_proto[1], max_proto[] = { AX25_PROTO_MAX }; static int min_ds_timeout[1], max_ds_timeout[] = {65535000}; #endif -static const ctl_table ax25_param_table[] = { +static const struct ctl_table ax25_param_table[] = { { .procname = "ip_default_mode", .maxlen = sizeof(int), diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1ed75bfd8d1d..f87736270eaa 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -992,7 +992,7 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { #ifdef CONFIG_SYSCTL static -int brnf_sysctl_call_tables(ctl_table * ctl, int write, +int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, void __user * buffer, size_t * lenp, loff_t * ppos) { int ret; @@ -1004,7 +1004,7 @@ int brnf_sysctl_call_tables(ctl_table * ctl, int write, return ret; } -static ctl_table brnf_table[] = { +static struct ctl_table brnf_table[] = { { .procname = "bridge-nf-call-arptables", .data = &brnf_call_arptables, diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 5c56b217b999..decaa4b9db2f 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2765,11 +2765,11 @@ EXPORT_SYMBOL(neigh_app_ns); static int zero; static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN); -static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_unres_qlen(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { int size, ret; - ctl_table tmp = *ctl; + struct ctl_table tmp = *ctl; tmp.extra1 = &zero; tmp.extra2 = &unres_qlen_max; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 4b48f39582b0..637a42e5d589 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -24,12 +24,12 @@ static int one = 1; #ifdef CONFIG_RPS -static int rps_sock_flow_sysctl(ctl_table *table, int write, +static int rps_sock_flow_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { unsigned int orig_size, size; int ret, i; - ctl_table tmp = { + struct ctl_table tmp = { .data = &size, .maxlen = sizeof(size), .mode = table->mode @@ -91,7 +91,7 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write, #ifdef CONFIG_NET_FLOW_LIMIT static DEFINE_MUTEX(flow_limit_update_mutex); -static int flow_limit_cpu_sysctl(ctl_table *table, int write, +static int flow_limit_cpu_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -156,7 +156,7 @@ static int flow_limit_cpu_sysctl(ctl_table *table, int write, return ret; } -static int flow_limit_table_len_sysctl(ctl_table *table, int write, +static int flow_limit_table_len_sysctl(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 7d9197063ebb..dd0dfb25f4b1 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -158,11 +158,11 @@ static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MU static int min_priority[1]; static int max_priority[] = { 127 }; /* From DECnet spec */ -static int dn_forwarding_proc(ctl_table *, int, +static int dn_forwarding_proc(struct ctl_table *, int, void __user *, size_t *, loff_t *); static struct dn_dev_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table dn_dev_vars[5]; + struct ctl_table dn_dev_vars[5]; } dn_dev_sysctl = { NULL, { @@ -242,7 +242,7 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) } } -static int dn_forwarding_proc(ctl_table *table, int write, +static int dn_forwarding_proc(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index a55eeccaa72f..5325b541c526 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c @@ -132,7 +132,7 @@ static int parse_addr(__le16 *addr, char *str) return 0; } -static int dn_node_address_handler(ctl_table *table, int write, +static int dn_node_address_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -183,7 +183,7 @@ static int dn_node_address_handler(ctl_table *table, int write, return 0; } -static int dn_def_dev_handler(ctl_table *table, int write, +static int dn_def_dev_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -246,7 +246,7 @@ static int dn_def_dev_handler(ctl_table *table, int write, return 0; } -static ctl_table dn_table[] = { +static struct ctl_table dn_table[] = { { .procname = "node_address", .maxlen = 7, diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 3469506c106d..8d48c392adcc 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1942,7 +1942,7 @@ static void inet_forward_change(struct net *net) } } -static int devinet_conf_proc(ctl_table *ctl, int write, +static int devinet_conf_proc(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -1985,7 +1985,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write, return ret; } -static int devinet_sysctl_forward(ctl_table *ctl, int write, +static int devinet_sysctl_forward(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -2028,7 +2028,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, return ret; } -static int ipv4_doint_and_flush(ctl_table *ctl, int write, +static int ipv4_doint_and_flush(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 567d84168bd2..0a2e0e3e95ba 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -223,7 +223,7 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = { static int log_invalid_proto_min = 0; static int log_invalid_proto_max = 255; -static ctl_table ip_ct_sysctl_table[] = { +static struct ctl_table ip_ct_sysctl_table[] = { { .procname = "ip_conntrack_max", .maxlen = sizeof(int), diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 198ea596f2d9..f3fa42eac461 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2448,7 +2448,7 @@ static int ip_rt_gc_interval __read_mostly = 60 * HZ; static int ip_rt_gc_min_interval __read_mostly = HZ / 2; static int ip_rt_gc_elasticity __read_mostly = 8; -static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, +static int ipv4_sysctl_rtcache_flush(struct ctl_table *__ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -2463,7 +2463,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write, return -EINVAL; } -static ctl_table ipv4_route_table[] = { +static struct ctl_table ipv4_route_table[] = { { .procname = "gc_thresh", .data = &ipv4_dst_ops.gc_thresh, diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fa2f63fc453b..b2c123c44d69 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -49,13 +49,13 @@ static void set_local_port_range(int range[2]) } /* Validate changes from /proc interface. */ -static int ipv4_local_port_range(ctl_table *table, int write, +static int ipv4_local_port_range(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; int range[2]; - ctl_table tmp = { + struct ctl_table tmp = { .data = &range, .maxlen = sizeof(range), .mode = table->mode, @@ -100,7 +100,7 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig } /* Validate changes from /proc interface. */ -static int ipv4_ping_group_range(ctl_table *table, int write, +static int ipv4_ping_group_range(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -108,7 +108,7 @@ static int ipv4_ping_group_range(ctl_table *table, int write, int ret; gid_t urange[2]; kgid_t low, high; - ctl_table tmp = { + struct ctl_table tmp = { .data = &urange, .maxlen = sizeof(urange), .mode = table->mode, @@ -135,11 +135,11 @@ static int ipv4_ping_group_range(ctl_table *table, int write, return ret; } -static int proc_tcp_congestion_control(ctl_table *ctl, int write, +static int proc_tcp_congestion_control(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { char val[TCP_CA_NAME_MAX]; - ctl_table tbl = { + struct ctl_table tbl = { .data = val, .maxlen = TCP_CA_NAME_MAX, }; @@ -153,12 +153,12 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write, return ret; } -static int proc_tcp_available_congestion_control(ctl_table *ctl, +static int proc_tcp_available_congestion_control(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, }; + struct ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, }; int ret; tbl.data = kmalloc(tbl.maxlen, GFP_USER); @@ -170,12 +170,12 @@ static int proc_tcp_available_congestion_control(ctl_table *ctl, return ret; } -static int proc_allowed_congestion_control(ctl_table *ctl, +static int proc_allowed_congestion_control(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX }; + struct ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX }; int ret; tbl.data = kmalloc(tbl.maxlen, GFP_USER); @@ -190,7 +190,7 @@ static int proc_allowed_congestion_control(ctl_table *ctl, return ret; } -static int ipv4_tcp_mem(ctl_table *ctl, int write, +static int ipv4_tcp_mem(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -201,7 +201,7 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, struct mem_cgroup *memcg; #endif - ctl_table tmp = { + struct ctl_table tmp = { .data = &vec, .maxlen = sizeof(vec), .mode = ctl->mode, @@ -233,10 +233,11 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, return 0; } -static int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { - ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; + struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; struct tcp_fastopen_context *ctxt; int ret; u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 21010fddb203..80449121afa2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4620,13 +4620,13 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) #ifdef CONFIG_SYSCTL static -int addrconf_sysctl_forward(ctl_table *ctl, int write, +int addrconf_sysctl_forward(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; - ctl_table lctl; + struct ctl_table lctl; int ret; /* @@ -4705,13 +4705,13 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf) } static -int addrconf_sysctl_disable(ctl_table *ctl, int write, +int addrconf_sysctl_disable(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; - ctl_table lctl; + struct ctl_table lctl; int ret; /* @@ -4733,7 +4733,7 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, static struct addrconf_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table addrconf_vars[DEVCONF_MAX+1]; + struct ctl_table addrconf_vars[DEVCONF_MAX+1]; } addrconf_sysctl __read_mostly = { .sysctl_header = NULL, .addrconf_vars = { diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4b4890bbe16d..7cfc8d284870 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -976,7 +976,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err) EXPORT_SYMBOL(icmpv6_err_convert); #ifdef CONFIG_SYSCTL -ctl_table ipv6_icmp_table_template[] = { +struct ctl_table ipv6_icmp_table_template[] = { { .procname = "ratelimit", .data = &init_net.ipv6.sysctl.icmpv6_time, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 2b874185ebb2..7ca87b37c0ef 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2790,7 +2790,7 @@ static const struct file_operations rt6_stats_seq_fops = { #ifdef CONFIG_SYSCTL static -int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, +int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { struct net *net; @@ -2805,7 +2805,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, return 0; } -ctl_table ipv6_route_table_template[] = { +struct ctl_table ipv6_route_table_template[] = { { .procname = "flush", .data = &init_net.ipv6.sysctl.flush_delay, diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index e85c48bd404f..107b2f1d90ae 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -16,7 +16,7 @@ #include #include -static ctl_table ipv6_table_template[] = { +static struct ctl_table ipv6_table_template[] = { { .procname = "bindv6only", .data = &init_net.ipv6.sysctl.bindv6only, @@ -27,7 +27,7 @@ static ctl_table ipv6_table_template[] = { { } }; -static ctl_table ipv6_rotable[] = { +static struct ctl_table ipv6_rotable[] = { { .procname = "mld_max_msf", .data = &sysctl_mld_max_msf, diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c index de73f6496db5..d6a59651767a 100644 --- a/net/irda/irsysctl.c +++ b/net/irda/irsysctl.c @@ -73,7 +73,7 @@ static int min_lap_keepalive_time = 100; /* 100us */ /* For other sysctl, I've no idea of the range. Maybe Dag could help * us on that - Jean II */ -static int do_devname(ctl_table *table, int write, +static int do_devname(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; @@ -90,7 +90,7 @@ static int do_devname(ctl_table *table, int write, } -static int do_discovery(ctl_table *table, int write, +static int do_discovery(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; @@ -111,7 +111,7 @@ static int do_discovery(ctl_table *table, int write, } /* One file */ -static ctl_table irda_table[] = { +static struct ctl_table irda_table[] = { { .procname = "discovery", .data = &sysctl_discovery, diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index df05c1c276f0..edb88fbcb1bd 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1575,7 +1575,7 @@ static int zero; static int three = 3; static int -proc_do_defense_mode(ctl_table *table, int write, +proc_do_defense_mode(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { struct net *net = current->nsproxy->net_ns; @@ -1596,7 +1596,7 @@ proc_do_defense_mode(ctl_table *table, int write, } static int -proc_do_sync_threshold(ctl_table *table, int write, +proc_do_sync_threshold(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = table->data; @@ -1616,7 +1616,7 @@ proc_do_sync_threshold(ctl_table *table, int write, } static int -proc_do_sync_mode(ctl_table *table, int write, +proc_do_sync_mode(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = table->data; @@ -1634,7 +1634,7 @@ proc_do_sync_mode(ctl_table *table, int write, } static int -proc_do_sync_ports(ctl_table *table, int write, +proc_do_sync_ports(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int *valp = table->data; diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 5ea26bd87743..44595b8ae37f 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -118,7 +118,7 @@ struct ip_vs_lblc_table { * IPVS LBLC sysctl table */ #ifdef CONFIG_SYSCTL -static ctl_table vs_vars_table[] = { +static struct ctl_table vs_vars_table[] = { { .procname = "lblc_expiration", .data = NULL, diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 50123c2ab484..876937db0bf4 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -299,7 +299,7 @@ struct ip_vs_lblcr_table { * IPVS LBLCR sysctl table */ -static ctl_table vs_vars_table[] = { +static struct ctl_table vs_vars_table[] = { { .procname = "lblcr_expiration", .data = NULL, diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index bd700b4013c1..f641751dba9d 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -408,7 +408,7 @@ static int log_invalid_proto_max = 255; static struct ctl_table_header *nf_ct_netfilter_header; -static ctl_table nf_ct_sysctl_table[] = { +static struct ctl_table nf_ct_sysctl_table[] = { { .procname = "nf_conntrack_max", .data = &nf_conntrack_max, @@ -458,7 +458,7 @@ static ctl_table nf_ct_sysctl_table[] = { #define NET_NF_CONNTRACK_MAX 2089 -static ctl_table nf_ct_netfilter_table[] = { +static struct ctl_table nf_ct_netfilter_table[] = { { .procname = "nf_conntrack_max", .data = &nf_conntrack_max, diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 4b60a87b7596..85296d4eac0e 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -245,7 +245,7 @@ static const struct file_operations nflog_file_ops = { static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; -static int nf_log_proc_dostring(ctl_table *table, int write, +static int nf_log_proc_dostring(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { const struct nf_logger *logger; diff --git a/net/netrom/sysctl_net_netrom.c b/net/netrom/sysctl_net_netrom.c index 42f630b9a698..ba1c368b3f18 100644 --- a/net/netrom/sysctl_net_netrom.c +++ b/net/netrom/sysctl_net_netrom.c @@ -34,7 +34,7 @@ static int min_reset[] = {0}, max_reset[] = {1}; static struct ctl_table_header *nr_table_header; -static ctl_table nr_table[] = { +static struct ctl_table nr_table[] = { { .procname = "default_path_quality", .data = &sysctl_netrom_default_path_quality, diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c index d6bbbbd0af18..c02a8c4bc11f 100644 --- a/net/phonet/sysctl.c +++ b/net/phonet/sysctl.c @@ -61,13 +61,13 @@ void phonet_get_local_port_range(int *min, int *max) } while (read_seqretry(&local_port_range_lock, seq)); } -static int proc_local_port_range(ctl_table *table, int write, +static int proc_local_port_range(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int ret; int range[2] = {local_port_range[0], local_port_range[1]}; - ctl_table tmp = { + struct ctl_table tmp = { .data = &range, .maxlen = sizeof(range), .mode = table->mode, diff --git a/net/rds/ib_sysctl.c b/net/rds/ib_sysctl.c index 7e643bafb4af..e4e41b3afce7 100644 --- a/net/rds/ib_sysctl.c +++ b/net/rds/ib_sysctl.c @@ -61,7 +61,7 @@ static unsigned long rds_ib_sysctl_max_unsig_wr_max = 64; */ unsigned int rds_ib_sysctl_flow_control = 0; -static ctl_table rds_ib_sysctl_table[] = { +static struct ctl_table rds_ib_sysctl_table[] = { { .procname = "max_send_wr", .data = &rds_ib_sysctl_max_send_wr, diff --git a/net/rds/iw_sysctl.c b/net/rds/iw_sysctl.c index 5d5ebd576f3f..89c91515ed0c 100644 --- a/net/rds/iw_sysctl.c +++ b/net/rds/iw_sysctl.c @@ -55,7 +55,7 @@ static unsigned long rds_iw_sysctl_max_unsig_bytes_max = ~0UL; unsigned int rds_iw_sysctl_flow_control = 1; -static ctl_table rds_iw_sysctl_table[] = { +static struct ctl_table rds_iw_sysctl_table[] = { { .procname = "max_send_wr", .data = &rds_iw_sysctl_max_send_wr, diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c index 907214b4c4d0..b5cb2aa08f33 100644 --- a/net/rds/sysctl.c +++ b/net/rds/sysctl.c @@ -49,7 +49,7 @@ unsigned int rds_sysctl_max_unacked_bytes = (16 << 20); unsigned int rds_sysctl_ping_enable = 1; -static ctl_table rds_sysctl_rds_table[] = { +static struct ctl_table rds_sysctl_rds_table[] = { { .procname = "reconnect_min_delay_ms", .data = &rds_sysctl_reconnect_min_jiffies, diff --git a/net/rose/sysctl_net_rose.c b/net/rose/sysctl_net_rose.c index 94ca9c2ccd69..89a9278795a9 100644 --- a/net/rose/sysctl_net_rose.c +++ b/net/rose/sysctl_net_rose.c @@ -24,7 +24,7 @@ static int min_window[] = {1}, max_window[] = {7}; static struct ctl_table_header *rose_table_header; -static ctl_table rose_table[] = { +static struct ctl_table rose_table[] = { { .procname = "restart_request_timeout", .data = &sysctl_rose_restart_request_timeout, diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index bf3c6e8fc401..9a5c4c9eddaf 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -62,12 +62,12 @@ extern long sysctl_sctp_mem[3]; extern int sysctl_sctp_rmem[3]; extern int sysctl_sctp_wmem[3]; -static int proc_sctp_do_hmac_alg(ctl_table *ctl, +static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos); -static ctl_table sctp_table[] = { +static struct ctl_table sctp_table[] = { { .procname = "sctp_mem", .data = &sysctl_sctp_mem, @@ -93,7 +93,7 @@ static ctl_table sctp_table[] = { { /* sentinel */ } }; -static ctl_table sctp_net_table[] = { +static struct ctl_table sctp_net_table[] = { { .procname = "rto_initial", .data = &init_net.sctp.rto_initial, @@ -300,14 +300,14 @@ static ctl_table sctp_net_table[] = { { /* sentinel */ } }; -static int proc_sctp_do_hmac_alg(ctl_table *ctl, +static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { struct net *net = current->nsproxy->net_ns; char tmp[8]; - ctl_table tbl; + struct ctl_table tbl; int ret; int changed = 0; char *none = "none"; diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index af7d339add9d..c99c58e2ee66 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -40,7 +40,7 @@ EXPORT_SYMBOL_GPL(nlm_debug); #ifdef RPC_DEBUG static struct ctl_table_header *sunrpc_table_header; -static ctl_table sunrpc_table[]; +static struct ctl_table sunrpc_table[]; void rpc_register_sysctl(void) @@ -58,7 +58,7 @@ rpc_unregister_sysctl(void) } } -static int proc_do_xprt(ctl_table *table, int write, +static int proc_do_xprt(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { char tmpbuf[256]; @@ -73,7 +73,7 @@ static int proc_do_xprt(ctl_table *table, int write, } static int -proc_dodebug(ctl_table *table, int write, +proc_dodebug(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { char tmpbuf[20], c, *s; @@ -135,7 +135,7 @@ proc_dodebug(ctl_table *table, int write, } -static ctl_table debug_table[] = { +static struct ctl_table debug_table[] = { { .procname = "rpc_debug", .data = &rpc_debug, @@ -173,7 +173,7 @@ static ctl_table debug_table[] = { { } }; -static ctl_table sunrpc_table[] = { +static struct ctl_table sunrpc_table[] = { { .procname = "sunrpc", .mode = 0555, diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c index 8343737e85f4..c1b6270262c2 100644 --- a/net/sunrpc/xprtrdma/svc_rdma.c +++ b/net/sunrpc/xprtrdma/svc_rdma.c @@ -84,7 +84,7 @@ struct workqueue_struct *svc_rdma_wq; * resets the associated statistic to zero. Any read returns it's * current value. */ -static int read_reset_stat(ctl_table *table, int write, +static int read_reset_stat(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -119,7 +119,7 @@ static int read_reset_stat(ctl_table *table, int write, } static struct ctl_table_header *svcrdma_table_header; -static ctl_table svcrdma_parm_table[] = { +static struct ctl_table svcrdma_parm_table[] = { { .procname = "max_requests", .data = &svcrdma_max_requests, @@ -214,7 +214,7 @@ static ctl_table svcrdma_parm_table[] = { { }, }; -static ctl_table svcrdma_table[] = { +static struct ctl_table svcrdma_table[] = { { .procname = "svc_rdma", .mode = 0555, @@ -223,7 +223,7 @@ static ctl_table svcrdma_table[] = { { }, }; -static ctl_table svcrdma_root_table[] = { +static struct ctl_table svcrdma_root_table[] = { { .procname = "sunrpc", .mode = 0555, diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 794312f22b9b..285dc0884115 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -86,7 +86,7 @@ static unsigned int max_memreg = RPCRDMA_LAST - 1; static struct ctl_table_header *sunrpc_table_header; -static ctl_table xr_tunables_table[] = { +static struct ctl_table xr_tunables_table[] = { { .procname = "rdma_slot_table_entries", .data = &xprt_rdma_slot_table_entries, @@ -138,7 +138,7 @@ static ctl_table xr_tunables_table[] = { { }, }; -static ctl_table sunrpc_table[] = { +static struct ctl_table sunrpc_table[] = { { .procname = "sunrpc", .mode = 0555, diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ffd50348a509..412de7cfcc80 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -87,7 +87,7 @@ static struct ctl_table_header *sunrpc_table_header; * FIXME: changing the UDP slot table size should also resize the UDP * socket buffers for existing UDP transports */ -static ctl_table xs_tunables_table[] = { +static struct ctl_table xs_tunables_table[] = { { .procname = "udp_slot_table_entries", .data = &xprt_udp_slot_table_entries, @@ -143,7 +143,7 @@ static ctl_table xs_tunables_table[] = { { }, }; -static ctl_table sunrpc_table[] = { +static struct ctl_table sunrpc_table[] = { { .procname = "sunrpc", .mode = 0555, diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 8800604c93f4..b3d515021b74 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -15,7 +15,7 @@ #include -static ctl_table unix_table[] = { +static struct ctl_table unix_table[] = { { .procname = "max_dgram_qlen", .data = &init_net.unx.sysctl_max_dgram_qlen, -- GitLab From 8e994402ad5e6ae3d391c0935f9f1dc2eeb92a5e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 12 Jun 2013 03:07:29 +0400 Subject: [PATCH 1068/2900] sh_eth: remove '__maybe_unused' annotations Now that the SoC specific support is no longer done with help of #ifdef'fery, we no longer need '__maybe_unused' annotations to sh_eth_select_mii() and sh_eth_set_duplex()... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 67a9e962f142..a2eadc070328 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -321,7 +321,7 @@ static int sh_eth_is_gether(struct sh_eth_private *mdp) return 0; } -static void __maybe_unused sh_eth_select_mii(struct net_device *ndev) +static void sh_eth_select_mii(struct net_device *ndev) { u32 value = 0x0; struct sh_eth_private *mdp = netdev_priv(ndev); @@ -345,7 +345,7 @@ static void __maybe_unused sh_eth_select_mii(struct net_device *ndev) sh_eth_write(ndev, value, RMII_MII); } -static void __maybe_unused sh_eth_set_duplex(struct net_device *ndev) +static void sh_eth_set_duplex(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); -- GitLab From 85f16525a2eb66e6092cbd8dcf42371df8334ed0 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 11 Jun 2013 15:35:32 -0700 Subject: [PATCH 1069/2900] tcp: properly send new data in fast recovery in first RTT Linux sends new unset data during disorder and recovery state if all (suspected) lost packets have been retransmitted ( RFC5681, section 3.2 step 1 & 2, RFC3517 section 4, NexSeg() Rule 2). One requirement is to keep the receive window about twice the estimated sender's congestion window (tcp_rcv_space_adjust()), assuming the fast retransmits repair the losses in the next round trip. But currently it's not the case on the first round trip in either normal or Fast Open connection, beucase the initial receive window is identical to (expected) sender's initial congestion window. The fix is to double it. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/tcp.h | 5 ++--- net/ipv4/tcp_input.c | 13 ++----------- net/ipv4/tcp_output.c | 33 ++++++++++++++++++--------------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 0d637e9403a5..6fa80831dc40 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -61,9 +61,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); */ #define MAX_TCP_WINDOW 32767U -/* Offer an initial receive window of 10 mss. */ -#define TCP_DEFAULT_INIT_RCVWND 10 - /* Minimal accepted MSS. It is (60+60+8) - (20+20). */ #define TCP_MIN_MSS 88U @@ -1047,6 +1044,8 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) rx_opt->num_sacks = 0; } +extern u32 tcp_default_init_rwnd(u32 mss); + /* Determine a window scaling and initial window to offer. */ extern void tcp_select_initial_window(int __space, __u32 mss, __u32 *rcv_wnd, __u32 *window_clamp, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 907311c9a012..46271cdcf088 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -347,22 +347,13 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb) } /* 3. Tuning rcvbuf, when connection enters established state. */ - static void tcp_fixup_rcvbuf(struct sock *sk) { u32 mss = tcp_sk(sk)->advmss; - u32 icwnd = TCP_DEFAULT_INIT_RCVWND; int rcvmem; - /* Limit to 10 segments if mss <= 1460, - * or 14600/mss segments, with a minimum of two segments. - */ - if (mss > 1460) - icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); - - rcvmem = 2 * SKB_TRUESIZE(mss + MAX_TCP_HEADER); - - rcvmem *= icwnd; + rcvmem = 2 * SKB_TRUESIZE(mss + MAX_TCP_HEADER) * + tcp_default_init_rwnd(mss); if (sk->sk_rcvbuf < rcvmem) sk->sk_rcvbuf = min(rcvmem, sysctl_tcp_rmem[2]); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ec335fabd5cc..3dd46eab3b05 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -181,6 +181,21 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); } + +u32 tcp_default_init_rwnd(u32 mss) +{ + /* Initial receive window should be twice of TCP_INIT_CWND to + * enable proper sending of new unset data during fast recovery + * (RFC 3517, Section 4, NextSeg() rule (2)). Further place a + * limit when mss is larger than 1460. + */ + u32 init_rwnd = TCP_INIT_CWND * 2; + + if (mss > 1460) + init_rwnd = max((1460 * init_rwnd) / mss, 2U); + return init_rwnd; +} + /* Determine a window scaling and initial window to offer. * Based on the assumption that the given amount of space * will be offered. Store the results in the tp structure. @@ -230,22 +245,10 @@ void tcp_select_initial_window(int __space, __u32 mss, } } - /* Set initial window to a value enough for senders starting with - * initial congestion window of TCP_DEFAULT_INIT_RCVWND. Place - * a limit on the initial window when mss is larger than 1460. - */ if (mss > (1 << *rcv_wscale)) { - int init_cwnd = TCP_DEFAULT_INIT_RCVWND; - if (mss > 1460) - init_cwnd = - max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); - /* when initializing use the value from init_rcv_wnd - * rather than the default from above - */ - if (init_rcv_wnd) - *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss); - else - *rcv_wnd = min(*rcv_wnd, init_cwnd * mss); + if (!init_rcv_wnd) /* Use default unless specified otherwise */ + init_rcv_wnd = tcp_default_init_rwnd(mss); + *rcv_wnd = min(*rcv_wnd, init_rcv_wnd * mss); } /* Set the clamp no higher than max representable value */ -- GitLab From 2809126512fcbd61ce3140af0bc255b441fcdaf9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 13 Jun 2013 10:48:11 +0100 Subject: [PATCH 1070/2900] mfd: ab8500-core: Drop references to ab8500-leds The ab8500-leds driver has never been upstreamed and was replaced by a PWM framework based driver, so these references are not needed anymore. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Lee Jones --- drivers/mfd/ab8500-core.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 258b367e3989..1863985df615 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1098,10 +1098,6 @@ static struct mfd_cell ab8500_devs[] = { .of_compatible = "stericsson,ab8500-pwm", .id = 3, }, - { - .name = "ab8500-leds", - .of_compatible = "stericsson,ab8500-leds", - }, { .name = "ab8500-denc", .of_compatible = "stericsson,ab8500-denc", @@ -1170,9 +1166,6 @@ static struct mfd_cell ab9540_devs[] = { .name = "ab8500-pwm", .id = 1, }, - { - .name = "ab8500-leds", - }, { .name = "abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), @@ -1241,9 +1234,6 @@ static struct mfd_cell ab8505_devs[] = { .name = "ab8500-pwm", .id = 1, }, - { - .name = "ab8500-leds", - }, { .name = "pinctrl-ab8505", }, @@ -1305,9 +1295,6 @@ static struct mfd_cell ab8540_devs[] = { .name = "ab8500-pwm", .id = 1, }, - { - .name = "ab8500-leds", - }, { .name = "abx500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), -- GitLab From 9c717cf3fa16f8ae8c6ccb8f4f8e784404ac9689 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Fri, 24 May 2013 11:59:47 +0200 Subject: [PATCH 1071/2900] mfd: ab8500-core: Add device for new RTC version for AB8540 cut2 AB8540 RTC have changed between AB8540_cut1 and AB8540_cut2.Different ressources to define for those two version. Acked-by: Linus Walleij Signed-off-by: Julien Delacou Signed-off-by: Alexandre Torgue Signed-off-by: Lee Jones --- drivers/mfd/ab8500-core.c | 55 ++++++++++++++++++++++++++----- include/linux/mfd/abx500/ab8500.h | 2 ++ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 1863985df615..02698da00b78 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -650,6 +650,21 @@ static struct resource ab8500_rtc_resources[] = { }, }; +static struct resource ab8540_rtc_resources[] = { + { + .name = "1S", + .start = AB8540_INT_RTC_1S, + .end = AB8540_INT_RTC_1S, + .flags = IORESOURCE_IRQ, + }, + { + .name = "ALARM", + .start = AB8500_INT_RTC_ALARM, + .end = AB8500_INT_RTC_ALARM, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource ab8500_poweronkey_db_resources[] = { { .name = "ONKEY_DBF", @@ -1276,11 +1291,6 @@ static struct mfd_cell ab8540_devs[] = { .num_resources = ARRAY_SIZE(ab8505_gpadc_resources), .resources = ab8505_gpadc_resources, }, - { - .name = "ab8500-rtc", - .num_resources = ARRAY_SIZE(ab8500_rtc_resources), - .resources = ab8500_rtc_resources, - }, { .name = "ab8500-acc-det", .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), @@ -1318,6 +1328,24 @@ static struct mfd_cell ab8540_devs[] = { }, }; +static struct mfd_cell ab8540_cut1_devs[] = { + { + .name = "ab8500-rtc", + .of_compatible = "stericsson,ab8500-rtc", + .num_resources = ARRAY_SIZE(ab8500_rtc_resources), + .resources = ab8500_rtc_resources, + }, +}; + +static struct mfd_cell ab8540_cut2_devs[] = { + { + .name = "ab8540-rtc", + .of_compatible = "stericsson,ab8540-rtc", + .num_resources = ARRAY_SIZE(ab8540_rtc_resources), + .resources = ab8540_rtc_resources, + }, +}; + static ssize_t show_chip_id(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1721,11 +1749,22 @@ static int ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, ab8500->irq_base, ab8500->domain); - else if (is_ab8540(ab8500)) + else if (is_ab8540(ab8500)) { ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, ARRAY_SIZE(ab8540_devs), NULL, - ab8500->irq_base, ab8500->domain); - else if (is_ab8505(ab8500)) + ab8500->irq_base, NULL); + if (ret) + return ret; + + if (is_ab8540_1p2_or_earlier(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs, + ARRAY_SIZE(ab8540_cut1_devs), NULL, + ab8500->irq_base, NULL); + else /* ab8540 >= cut2 */ + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs, + ARRAY_SIZE(ab8540_cut2_devs), NULL, + ab8500->irq_base, NULL); + } else if (is_ab8505(ab8500)) ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, ARRAY_SIZE(ab8505_devs), NULL, ab8500->irq_base, ab8500->domain); diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index 0390d5943ed6..f4acd898dac9 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -291,6 +291,8 @@ enum ab8500_version { #define AB8540_INT_FSYNC2R 213 #define AB8540_INT_BITCLK2F 214 #define AB8540_INT_BITCLK2R 215 +/* ab8540_irq_regoffset[27] -> IT[Source|Latch|Mask]33 */ +#define AB8540_INT_RTC_1S 216 /* * AB8500_AB9540_NR_IRQS is used when configuring the IRQ numbers for the -- GitLab From fccf14ad1e4f09a4033908ead9bf3f393979d54b Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 30 May 2013 15:27:45 +0200 Subject: [PATCH 1072/2900] mfd: ab8500-core: Add of_compatible property for ab8500-codec Add of_compatible string to the ab8500-codec cell to allow the driver to grab handlers such as regulators from device-tree when available. Signed-off-by: Fabio Baltieri Signed-off-by: Lee Jones --- drivers/mfd/ab8500-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 02698da00b78..ca6bd1c8bd3f 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1135,6 +1135,7 @@ static struct mfd_cell ab8500_devs[] = { }, { .name = "ab8500-codec", + .of_compatible = "stericsson,ab8500-codec", }, }; -- GitLab From 8420a24138e4ad7a8351bef136139ecb27cb15c5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 4 Jun 2013 13:11:50 +0900 Subject: [PATCH 1073/2900] mfd: Replace strict_strtoul() with kstrtoul() in ab* and att* The usage of strict_strtoul() is not preferred, because strict_strtoul() is obsolete. Thus, kstrtoul() should be used. Signed-off-by: Jingoo Han Reviewed-by: Andy Shevchenko Signed-off-by: Lee Jones --- drivers/mfd/aat2870-core.c | 5 +++-- drivers/mfd/ab3100-core.c | 28 ++++++++++------------------ drivers/mfd/ab8500-debugfs.c | 2 +- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index dfdb0a2b6835..d4f594517521 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c @@ -312,8 +312,9 @@ static ssize_t aat2870_reg_write_file(struct file *file, while (*start == ' ') start++; - if (strict_strtoul(start, 16, &val)) - return -EINVAL; + ret = kstrtoul(start, 16, &val); + if (ret) + return ret; ret = aat2870->write(aat2870, (u8)addr, (u8)val); if (ret) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index a9bb140bc86b..ddc669d19530 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -491,7 +491,7 @@ static ssize_t ab3100_get_set_reg(struct file *file, char buf[32]; ssize_t buf_size; int regp; - unsigned long user_reg; + u8 user_reg; int err; int i = 0; @@ -514,34 +514,29 @@ static ssize_t ab3100_get_set_reg(struct file *file, /* * Advance pointer to end of string then terminate * the register string. This is needed to satisfy - * the strict_strtoul() function. + * the kstrtou8() function. */ while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; - err = strict_strtoul(&buf[regp], 16, &user_reg); + err = kstrtou8(&buf[regp], 16, &user_reg); if (err) return err; - if (user_reg > 0xff) - return -EINVAL; /* Either we read or we write a register here */ if (!priv->mode) { /* Reading */ - u8 reg = (u8) user_reg; u8 regvalue; - ab3100_get_register_interruptible(ab3100, reg, ®value); + ab3100_get_register_interruptible(ab3100, user_reg, ®value); dev_info(ab3100->dev, "debug read AB3100 reg[0x%02x]: 0x%02x\n", - reg, regvalue); + user_reg, regvalue); } else { int valp; - unsigned long user_value; - u8 reg = (u8) user_reg; - u8 value; + u8 user_value; u8 regvalue; /* @@ -557,20 +552,17 @@ static ssize_t ab3100_get_set_reg(struct file *file, i++; buf[i] = '\0'; - err = strict_strtoul(&buf[valp], 16, &user_value); + err = kstrtou8(&buf[valp], 16, &user_value); if (err) return err; - if (user_reg > 0xff) - return -EINVAL; - value = (u8) user_value; - ab3100_set_register_interruptible(ab3100, reg, value); - ab3100_get_register_interruptible(ab3100, reg, ®value); + ab3100_set_register_interruptible(ab3100, user_reg, user_value); + ab3100_get_register_interruptible(ab3100, user_reg, ®value); dev_info(ab3100->dev, "debug write reg[0x%02x] with 0x%02x, " "after readback: 0x%02x\n", - reg, value, regvalue); + user_reg, user_value, regvalue); } return buf_size; } diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 37b7ce4c7c3b..11656c2c63cb 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2757,7 +2757,7 @@ static ssize_t show_irq(struct device *dev, unsigned int irq_index; int err; - err = strict_strtoul(attr->attr.name, 0, &name); + err = kstrtoul(attr->attr.name, 0, &name); if (err) return err; -- GitLab From 7f8c5e1494544ce86d358fa9dc553db3e20cb4d0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 6 Jun 2013 12:21:13 +0100 Subject: [PATCH 1074/2900] mfd: dbx500-prcmu: Use correct names for clock management registers ... as stipulated by the Hardware Specification document. Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/dbx500-prcmu-regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index d14836ed2114..7cc32a8ff01c 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -16,8 +16,8 @@ #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) #define PRCM_ACLK_MGT (0x004) -#define PRCM_SVACLK_MGT (0x008) -#define PRCM_SIACLK_MGT (0x00C) +#define PRCM_SVAMMCSPCLK_MGT (0x008) +#define PRCM_SIAMMDSPCLK_MGT (0x00C) #define PRCM_SGACLK_MGT (0x014) #define PRCM_UARTCLK_MGT (0x018) #define PRCM_MSP02CLK_MGT (0x01C) -- GitLab From 53f325be2f99fb1e5dbbfc1f7707a9a6c97c83c2 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 7 Jun 2013 16:07:47 +0100 Subject: [PATCH 1075/2900] mfd: ab8500-core: Add AB8500 external regulators as MFD devices The AB8500 external regulator driver is now a device in its own right, so it requires registering and probing in the normal way. This patch will ensure the driver is probed once registered for all devices which support them. Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/mfd/ab8500-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index ca6bd1c8bd3f..b6c2cdc76091 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -1065,6 +1065,10 @@ static struct mfd_cell ab8500_devs[] = { .name = "ab8500-sysctrl", .of_compatible = "stericsson,ab8500-sysctrl", }, + { + .name = "ab8500-ext-regulator", + .of_compatible = "stericsson,ab8500-ext-regulator", + }, { .name = "ab8500-regulator", .of_compatible = "stericsson,ab8500-regulator", @@ -1150,6 +1154,9 @@ static struct mfd_cell ab9540_devs[] = { { .name = "ab8500-sysctrl", }, + { + .name = "ab8500-ext-regulator", + }, { .name = "ab8500-regulator", }, @@ -1279,6 +1286,9 @@ static struct mfd_cell ab8540_devs[] = { { .name = "ab8500-sysctrl", }, + { + .name = "ab8500-ext-regulator", + }, { .name = "ab8500-regulator", }, -- GitLab From 817cee767523769cbc5ac94e439cde0c21752cbc Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Sun, 19 May 2013 14:23:57 +0300 Subject: [PATCH 1076/2900] mac80211: track AP's beacon rate and give it to the driver Track the AP's beacon rate in the scan BSS data and in the interface configuration to let the drivers know which rate the AP is using. This information may be used by drivers, in our case to let the firmware optimise beacon RX. Signed-off-by: Alexander Bondar Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 ++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 8 +++++++- net/mac80211/scan.c | 9 +++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a405a7a9775c..5b7a3dadadde 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -305,6 +305,7 @@ enum ieee80211_rssi_event { * @basic_rates: bitmap of basic rates, each bit stands for an * index into the rate table configured by the driver in * the current band. + * @beacon_rate: associated AP's beacon TX rate * @mcast_rate: per-band multicast rate index + 1 (0: disabled) * @bssid: The BSSID for this BSS * @enable_beacon: whether beaconing should be enabled or not @@ -352,6 +353,7 @@ struct ieee80211_bss_conf { u32 sync_device_ts; u8 sync_dtim_count; u32 basic_rates; + struct ieee80211_rate *beacon_rate; int mcast_rate[IEEE80211_NUM_BANDS]; u16 ht_operation_mode; s32 cqm_rssi_thold; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7a6f1a0207ec..a4dfb0be53d7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -94,6 +94,7 @@ struct ieee80211_bss { #define IEEE80211_MAX_SUPP_RATES 32 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; size_t supp_rates_len; + struct ieee80211_rate *beacon_rate; /* * During association, we save an ERP value from a probe response so diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ad9bb9e10cbb..87f2d4df31f8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1779,8 +1779,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, * probably just won't work at all. */ bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; + bss_conf->beacon_rate = bss->beacon_rate; bss_info_changed |= BSS_CHANGED_BEACON_INFO; } else { + bss_conf->beacon_rate = NULL; bss_conf->dtim_period = 0; } @@ -1903,6 +1905,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, del_timer_sync(&sdata->u.mgd.chswitch_timer); sdata->vif.bss_conf.dtim_period = 0; + sdata->vif.bss_conf.beacon_rate = NULL; + ifmgd->have_beacon = false; ifmgd->flags = 0; @@ -2754,8 +2758,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, channel); - if (bss) + if (bss) { ieee80211_rx_bss_put(local, bss); + sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; + } if (!sdata->u.mgd.associated || !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 99b103921a4b..1b122a79b0d8 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -140,6 +140,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->valid_data |= IEEE80211_BSS_VALID_WMM; } + if (beacon) { + struct ieee80211_supported_band *sband = + local->hw.wiphy->bands[rx_status->band]; + if (!(rx_status->flag & RX_FLAG_HT) && + !(rx_status->flag & RX_FLAG_VHT)) + bss->beacon_rate = + &sband->bitrates[rx_status->rate_idx]; + } + return bss; } -- GitLab From 38745c7414c0d9a0567c5b4a4e056c6b7f807179 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 10 Jun 2013 10:34:14 +0300 Subject: [PATCH 1077/2900] mac80211: Fix VHT bandwidth change event Signed-off-by: Ilan Peer Signed-off-by: Johannes Berg --- net/mac80211/vht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 171344d4eb7c..97c289414e32 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -396,7 +396,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, new_bw = ieee80211_sta_cur_vht_bw(sta); if (new_bw != sta->sta.bandwidth) { sta->sta.bandwidth = new_bw; - changed |= IEEE80211_RC_NSS_CHANGED; + changed |= IEEE80211_RC_BW_CHANGED; } change: -- GitLab From 68972c46f2975d3d61f9dc9f311f77bfc8a8b12b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 11 Jun 2013 19:05:27 +0200 Subject: [PATCH 1078/2900] iwlwifi: make TX seqno validation more efficient Accessing the device in Tx path is not a good idea. Mirror the data in DRAM. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/internal.h | 2 ++ drivers/net/wireless/iwlwifi/pcie/tx.c | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 148843e7f34f..b654dcdd048a 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h @@ -217,6 +217,7 @@ struct iwl_pcie_txq_scratch_buf { * @trans_pcie: pointer back to transport (for timer) * @need_update: indicates need to update read/write index * @active: stores if queue is active + * @ampdu: true if this queue is an ampdu queue for an specific RA/TID * * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame * descriptors) and required locking structures. @@ -232,6 +233,7 @@ struct iwl_txq { struct iwl_trans_pcie *trans_pcie; u8 need_update; u8 active; + bool ampdu; }; static inline dma_addr_t diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index f65da1984d91..b8f3cb78382b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1073,6 +1073,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, /* enable aggregations for the queue */ iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); + trans_pcie->txq[txq_id].ampdu = true; } else { /* * disable aggregations for the queue, this will also make the @@ -1129,6 +1130,7 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) ARRAY_SIZE(zero_val)); iwl_pcie_txq_unmap(trans, txq_id); + trans_pcie->txq[txq_id].ampdu = false; IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } @@ -1599,7 +1601,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, u8 wait_write_ptr = 0; __le16 fc = hdr->frame_control; u8 hdr_len = ieee80211_hdrlen(fc); - u16 __maybe_unused wifi_seq; + u16 wifi_seq; txq = &trans_pcie->txq[txq_id]; q = &txq->q; @@ -1616,13 +1618,11 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * the BA. * Check here that the packets are in the right place on the ring. */ -#ifdef CONFIG_IWLWIFI_DEBUG wifi_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); - WARN_ONCE((iwl_read_prph(trans, SCD_AGGR_SEL) & BIT(txq_id)) && - ((wifi_seq & 0xff) != q->write_ptr), + WARN_ONCE(trans_pcie->txq[txq_id].ampdu && + (wifi_seq & 0xff) != q->write_ptr, "Q: %d WiFi Seq %d tfdNum %d", txq_id, wifi_seq, q->write_ptr); -#endif /* Set up driver data for this TFD */ txq->entries[q->write_ptr].skb = skb; -- GitLab From aaaab4223ebad2470d56d5db2e71c5395d9609b3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 12 Jun 2013 13:55:43 +0530 Subject: [PATCH 1079/2900] mfd: 88pm860x: Use devm_regmap_init_i2c() devm_regmap_init_i2c() is device managed and makes cleanup simpler. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/88pm860x-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 31ca55548ef9..629d6404cab4 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1155,7 +1155,7 @@ static int pm860x_probe(struct i2c_client *client, return -ENOMEM; chip->id = verify_addr(client); - chip->regmap = regmap_init_i2c(client, &pm860x_regmap_config); + chip->regmap = devm_regmap_init_i2c(client, &pm860x_regmap_config); if (IS_ERR(chip->regmap)) { ret = PTR_ERR(chip->regmap); dev_err(&client->dev, "Failed to allocate register map: %d\n", @@ -1203,7 +1203,6 @@ static int pm860x_remove(struct i2c_client *client) regmap_exit(chip->regmap_companion); i2c_unregister_device(chip->companion); } - regmap_exit(chip->regmap); kfree(chip); return 0; } -- GitLab From 01911dab97cb3e21e640aaca82689acec00ed848 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 11 Jun 2013 21:12:29 +0200 Subject: [PATCH 1080/2900] iwlwifi: pcie: don't read INTA register in ICT IRQ handler There's no reason to read the INTA register in the ICT IRQ handler, this interrupt mechanism is designed to not have to read as many registers as the regular one. Not reading the INTA register gives a significant performance/CPU use improvement. Since we still want to get this info, fetch it only if the ISR debug level is enabled. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/rx.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 567e67ad1f61..63ba21e51f8d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -1198,7 +1198,7 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) { struct iwl_trans *trans = data; struct iwl_trans_pcie *trans_pcie; - u32 inta, inta_mask; + u32 inta; u32 val = 0; u32 read; unsigned long flags; @@ -1226,7 +1226,6 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(trans, CSR_INT_MASK); iwl_write32(trans, CSR_INT_MASK, 0x00000000); /* Ignore interrupt if there's nothing in NIC to service. @@ -1271,8 +1270,13 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) val |= 0x8000; inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", - inta, inta_mask, val); + IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n", + inta, trans_pcie->inta_mask, val); +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_have_debug_level(IWL_DL_ISR)) + IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n", + iwl_read32(trans, CSR_INT_MASK)); +#endif inta &= trans_pcie->inta_mask; trans_pcie->inta |= inta; -- GitLab From b002c7e1f327bb56fe068bf76fd7179b1b490e02 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Wed, 12 Jun 2013 20:37:03 +0300 Subject: [PATCH 1081/2900] iwlwifi: mvm: removed an unused parameter from a function Remove the unused iwl_mvm *mvm parameter from the iwl_mvm_send_remote_wake_cfg function in D3.c. Signed-off-by: Oren Givon Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/d3.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 7a2ef3f013fd..8c49db02c9c1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -420,8 +420,7 @@ static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr) return cpu_to_le16(be16_to_cpu((__force __be16)check)); } -static void iwl_mvm_build_tcp_packet(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, +static void iwl_mvm_build_tcp_packet(struct ieee80211_vif *vif, struct cfg80211_wowlan_tcp *tcp, void *_pkt, u8 *mask, __le16 *pseudo_hdr_csum, @@ -567,21 +566,21 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, /* SYN (TX) */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->syn_tx.data, NULL, + vif, tcp, cfg->syn_tx.data, NULL, &cfg->syn_tx.info.tcp_pseudo_header_checksum, MVM_TCP_TX_SYN); cfg->syn_tx.info.tcp_payload_length = 0; /* SYN/ACK (RX) */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask, + vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask, &cfg->synack_rx.info.tcp_pseudo_header_checksum, MVM_TCP_RX_SYNACK); cfg->synack_rx.info.tcp_payload_length = 0; /* KEEPALIVE/ACK (TX) */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->keepalive_tx.data, NULL, + vif, tcp, cfg->keepalive_tx.data, NULL, &cfg->keepalive_tx.info.tcp_pseudo_header_checksum, MVM_TCP_TX_DATA); cfg->keepalive_tx.info.tcp_payload_length = @@ -605,7 +604,7 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, /* ACK (RX) */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->keepalive_ack_rx.data, + vif, tcp, cfg->keepalive_ack_rx.data, cfg->keepalive_ack_rx.rx_mask, &cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum, MVM_TCP_RX_ACK); @@ -613,7 +612,7 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, /* WAKEUP (RX) */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask, + vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask, &cfg->wake_rx.info.tcp_pseudo_header_checksum, MVM_TCP_RX_WAKE); cfg->wake_rx.info.tcp_payload_length = @@ -621,7 +620,7 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, /* FIN */ iwl_mvm_build_tcp_packet( - mvm, vif, tcp, cfg->fin_tx.data, NULL, + vif, tcp, cfg->fin_tx.data, NULL, &cfg->fin_tx.info.tcp_pseudo_header_checksum, MVM_TCP_TX_FIN); cfg->fin_tx.info.tcp_payload_length = 0; -- GitLab From 12dcf2c3325a8aa25e8634b7e8337aad6f9be9b7 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Wed, 12 Jun 2013 16:58:04 +0300 Subject: [PATCH 1082/2900] iwlwifi: remove calib channel section from PHY DB Remove calibration per-channel data as it's no longer used. Signed-off-by: David Spinadel Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-phy-db.c | 36 ++--------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 84acb4deca8a..1a405ae6a9c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c @@ -92,20 +92,16 @@ struct iwl_phy_db_entry { struct iwl_phy_db { struct iwl_phy_db_entry cfg; struct iwl_phy_db_entry calib_nch; - struct iwl_phy_db_entry calib_ch; struct iwl_phy_db_entry calib_ch_group_papd[IWL_NUM_PAPD_CH_GROUPS]; struct iwl_phy_db_entry calib_ch_group_txp[IWL_NUM_TXP_CH_GROUPS]; - u32 channel_num; - u32 channel_size; - struct iwl_trans *trans; }; enum iwl_phy_db_section_type { IWL_PHY_DB_CFG = 1, IWL_PHY_DB_CALIB_NCH, - IWL_PHY_DB_CALIB_CH, + IWL_PHY_DB_UNUSED, IWL_PHY_DB_CALIB_CHG_PAPD, IWL_PHY_DB_CALIB_CHG_TXP, IWL_PHY_DB_MAX @@ -169,8 +165,6 @@ iwl_phy_db_get_section(struct iwl_phy_db *phy_db, return &phy_db->cfg; case IWL_PHY_DB_CALIB_NCH: return &phy_db->calib_nch; - case IWL_PHY_DB_CALIB_CH: - return &phy_db->calib_ch; case IWL_PHY_DB_CALIB_CHG_PAPD: if (chg_id >= IWL_NUM_PAPD_CH_GROUPS) return NULL; @@ -208,7 +202,6 @@ void iwl_phy_db_free(struct iwl_phy_db *phy_db) iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0); iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0); - iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CH, 0); for (i = 0; i < IWL_NUM_PAPD_CH_GROUPS; i++) iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i); for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++) @@ -248,13 +241,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, entry->size = size; - if (type == IWL_PHY_DB_CALIB_CH) { - phy_db->channel_num = - le32_to_cpup((__le32 *)phy_db_notif->data); - phy_db->channel_size = - (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; - } - IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", __func__, __LINE__, type, size); @@ -328,10 +314,7 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, u32 type, u8 **data, u16 *size, u16 ch_id) { struct iwl_phy_db_entry *entry; - u32 channel_num; - u32 channel_size; u16 ch_group_id = 0; - u16 index; if (!phy_db) return -EINVAL; @@ -346,21 +329,8 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, if (!entry) return -EINVAL; - if (type == IWL_PHY_DB_CALIB_CH) { - index = ch_id_to_ch_index(ch_id); - channel_num = phy_db->channel_num; - channel_size = phy_db->channel_size; - if (index >= channel_num) { - IWL_ERR(phy_db->trans, "Wrong channel number %d\n", - ch_id); - return -EINVAL; - } - *data = entry->data + CHANNEL_NUM_SIZE + index * channel_size; - *size = channel_size; - } else { - *data = entry->data; - *size = entry->size; - } + *data = entry->data; + *size = entry->size; IWL_DEBUG_INFO(phy_db->trans, "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", -- GitLab From 51cd53ad120f33410c48fd0d696e6f6255c8e780 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 12 Jun 2013 09:56:51 +0200 Subject: [PATCH 1083/2900] iwlwifi: reduce debug ifdefs using the optimiser Instead of using #ifdef CONFIG_IWLWIFI_DEBUG, remove the iwlwifi_mod_params.debug_level variable completely and make iwl_have_debug_level() always return false in the non-debug case. This way, the optimiser will elide all code for it automatically without having to add #ifdefs. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/main.c | 7 ---- drivers/net/wireless/iwlwifi/iwl-debug.h | 4 +++ drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 ++ drivers/net/wireless/iwlwifi/pcie/rx.c | 36 ++++++-------------- 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 68f754659570..7aa9c8dc33ef 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1859,14 +1859,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, return pos; } -#ifdef CONFIG_IWLWIFI_DEBUG if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#else - size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) - ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#endif IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", size); @@ -1910,10 +1905,8 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned int reload_msec; unsigned long reload_jiffies; -#ifdef CONFIG_IWLWIFI_DEBUG if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); -#endif /* uCode is no longer loaded. */ priv->ucode_loaded = false; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 8cf5db7fb5c9..7edb8519c8a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -34,7 +34,11 @@ static inline bool iwl_have_debug_level(u32 level) { +#ifdef CONFIG_IWLWIFI_DEBUG return iwlwifi_mod_params.debug_level & level; +#else + return false; +#endif } void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace, diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 36dfe0919f6b..d4ad505b0a4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -115,7 +115,9 @@ struct iwl_mod_params { int led_mode; bool power_save; int power_level; +#ifdef CONFIG_IWLWIFI_DEBUG u32 debug_level; +#endif int ant_coupling; bool bt_ch_announce; bool auto_agg; diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 63ba21e51f8d..3688dc5ba1ac 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -802,9 +802,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) u32 handled = 0; unsigned long flags; u32 i; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif lock_map_acquire(&trans->sync_cmd_lockdep_map); @@ -826,14 +823,9 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) inta = trans_pcie->inta; -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_have_debug_level(IWL_DL_ISR)) { - /* just for debug */ - inta_mask = iwl_read32(trans, CSR_INT_MASK); + if (iwl_have_debug_level(IWL_DL_ISR)) IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", - inta, inta_mask); - } -#endif + inta, iwl_read32(trans, CSR_INT_MASK)); /* saved interrupt in inta variable now we can reset trans_pcie->inta */ trans_pcie->inta = 0; @@ -855,12 +847,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) goto out; } -#ifdef CONFIG_IWLWIFI_DEBUG if (iwl_have_debug_level(IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(trans, "Scheduler finished to transmit " - "the frame/frames.\n"); + IWL_DEBUG_ISR(trans, + "Scheduler finished to transmit the frame/frames.\n"); isr_stats->sch++; } @@ -870,7 +861,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) isr_stats->alive++; } } -#endif + /* Safely ignore these bits for debug checks below */ inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); @@ -1118,9 +1109,6 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) struct iwl_trans *trans = data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 inta, inta_mask; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_fh; -#endif lockdep_assert_held(&trans_pcie->irq_lock); @@ -1159,13 +1147,11 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) return IRQ_HANDLED; } -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_have_debug_level(IWL_DL_ISR)) { - inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, " - "fh 0x%08x\n", inta, inta_mask, inta_fh); - } -#endif + if (iwl_have_debug_level(IWL_DL_ISR)) + IWL_DEBUG_ISR(trans, + "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", + inta, inta_mask, + iwl_read32(trans, CSR_FH_INT_STATUS)); trans_pcie->inta |= inta; /* the thread will service interrupts and re-enable them */ @@ -1272,11 +1258,9 @@ irqreturn_t iwl_pcie_isr_ict(int irq, void *data) inta = (0xff & val) | ((0xff00 & val) << 16); IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled(sw) 0x%08x ict 0x%08x\n", inta, trans_pcie->inta_mask, val); -#ifdef CONFIG_IWLWIFI_DEBUG if (iwl_have_debug_level(IWL_DL_ISR)) IWL_DEBUG_ISR(trans, "enabled(hw) 0x%08x\n", iwl_read32(trans, CSR_INT_MASK)); -#endif inta &= trans_pcie->inta_mask; trans_pcie->inta |= inta; -- GitLab From bc888f4078d549792e7b10a886f98271d5ad432b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Jun 2013 15:58:13 +0200 Subject: [PATCH 1084/2900] iwlwifi: mvm: mark scratch area in TX command Give the scratch area a sub structure so it's marked explicitly and it is obvious which part it is. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h index 6994232f5726..700cce731770 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h @@ -228,10 +228,11 @@ struct iwl_tx_cmd { __le16 len; __le16 next_frame_len; __le32 tx_flags; - /* DRAM_SCRATCH_API_U_VER_1 */ - u8 try_cnt; - u8 btkill_cnt; - __le16 reserved; + struct { + u8 try_cnt; + u8 btkill_cnt; + __le16 reserved; + } scratch; /* DRAM_SCRATCH_API_U_VER_1 */ __le32 rate_n_flags; u8 sta_id; u8 sec_ctl; -- GitLab From b3fff1770a33abb1905eae2baa8dffd48e5913ae Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:02 +0100 Subject: [PATCH 1085/2900] mfd: tps65912: Convert to managed resources for allocating memory Saves on code and simplifies the driver, as these resources are now tracked and freed automatically when the driver is realised. Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/tps65912-core.c | 2 -- drivers/mfd/tps65912-i2c.c | 3 ++- drivers/mfd/tps65912-spi.c | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index aeb8e40ab424..479886a4cf80 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c @@ -162,7 +162,6 @@ int tps65912_device_init(struct tps65912 *tps65912) err: kfree(init_data); mfd_remove_devices(tps65912->dev); - kfree(tps65912); return ret; } @@ -170,7 +169,6 @@ void tps65912_device_exit(struct tps65912 *tps65912) { mfd_remove_devices(tps65912->dev); tps65912_irq_exit(tps65912); - kfree(tps65912); } MODULE_AUTHOR("Margarita Olaya "); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c index c041f2c3d2bd..6a6343ee95fe 100644 --- a/drivers/mfd/tps65912-i2c.c +++ b/drivers/mfd/tps65912-i2c.c @@ -77,7 +77,8 @@ static int tps65912_i2c_probe(struct i2c_client *i2c, { struct tps65912 *tps65912; - tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); + tps65912 = devm_kzalloc(&i2c->dev, + sizeof(struct tps65912), GFP_KERNEL); if (tps65912 == NULL) return -ENOMEM; diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index b45f460d299f..69a5178bf152 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -85,7 +85,8 @@ static int tps65912_spi_probe(struct spi_device *spi) { struct tps65912 *tps65912; - tps65912 = kzalloc(sizeof(struct tps65912), GFP_KERNEL); + tps65912 = devm_kzalloc(&spi->dev, + sizeof(struct tps65912), GFP_KERNEL); if (tps65912 == NULL) return -ENOMEM; -- GitLab From 5feac05dd4a403b12e8e0212006bad5c52e36fba Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:04 +0100 Subject: [PATCH 1086/2900] mfd: ab3100-otp: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab3100-otp.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index d7ce016029fa..c9af16cc7310 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c @@ -187,7 +187,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) int err = 0; int i; - otp = kzalloc(sizeof(struct ab3100_otp), GFP_KERNEL); + otp = devm_kzalloc(&pdev->dev, sizeof(struct ab3100_otp), GFP_KERNEL); if (!otp) { dev_err(&pdev->dev, "could not allocate AB3100 OTP device\n"); return -ENOMEM; @@ -199,7 +199,7 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) err = ab3100_otp_read(otp); if (err) - goto err_otp_read; + return err; dev_info(&pdev->dev, "AB3100 OTP readout registered\n"); @@ -208,22 +208,19 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) err = device_create_file(&pdev->dev, &ab3100_otp_attrs[i]); if (err) - goto err_create_file; + goto err; } /* debugfs entries */ err = ab3100_otp_init_debugfs(&pdev->dev, otp); if (err) - goto err_init_debugfs; + goto err; return 0; -err_init_debugfs: -err_create_file: +err: while (--i >= 0) device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); -err_otp_read: - kfree(otp); return err; } @@ -236,7 +233,6 @@ static int __exit ab3100_otp_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &ab3100_otp_attrs[i]); ab3100_otp_exit_debugfs(otp); - kfree(otp); return 0; } -- GitLab From c18cf6d1b0d871745709e4273dc2dfa05376d13b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:05 +0100 Subject: [PATCH 1087/2900] mfd: ab8500-debug: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-debugfs.c | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 11656c2c63cb..7d1f1b08fc4b 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -2937,7 +2937,6 @@ static struct dentry *ab8500_gpadc_dir; static int ab8500_debug_probe(struct platform_device *plf) { struct dentry *file; - int ret = -ENOMEM; struct ab8500 *ab8500; struct resource *res; debug_bank = AB8500_MISC; @@ -2946,24 +2945,26 @@ static int ab8500_debug_probe(struct platform_device *plf) ab8500 = dev_get_drvdata(plf->dev.parent); num_irqs = ab8500->mask_size; - irq_count = kzalloc(sizeof(*irq_count)*num_irqs, GFP_KERNEL); + irq_count = devm_kzalloc(&plf->dev, + sizeof(*irq_count)*num_irqs, GFP_KERNEL); if (!irq_count) return -ENOMEM; - dev_attr = kzalloc(sizeof(*dev_attr)*num_irqs,GFP_KERNEL); + dev_attr = devm_kzalloc(&plf->dev, + sizeof(*dev_attr)*num_irqs,GFP_KERNEL); if (!dev_attr) - goto out_freeirq_count; + return -ENOMEM; - event_name = kzalloc(sizeof(*event_name)*num_irqs, GFP_KERNEL); + event_name = devm_kzalloc(&plf->dev, + sizeof(*event_name)*num_irqs, GFP_KERNEL); if (!event_name) - goto out_freedev_attr; + return -ENOMEM; res = platform_get_resource_byname(plf, 0, "IRQ_AB8500"); if (!res) { dev_err(&plf->dev, "AB8500 irq not found, err %d\n", irq_first); - ret = -ENXIO; - goto out_freeevent_name; + return ENXIO; } irq_ab8500 = res->start; @@ -2971,16 +2972,14 @@ static int ab8500_debug_probe(struct platform_device *plf) if (irq_first < 0) { dev_err(&plf->dev, "First irq not found, err %d\n", irq_first); - ret = irq_first; - goto out_freeevent_name; + return irq_first; } irq_last = platform_get_irq_byname(plf, "IRQ_LAST"); if (irq_last < 0) { dev_err(&plf->dev, "Last irq not found, err %d\n", irq_last); - ret = irq_last; - goto out_freeevent_name; + return irq_last; } ab8500_dir = debugfs_create_dir(AB8500_NAME_STRING, NULL); @@ -3189,22 +3188,13 @@ static int ab8500_debug_probe(struct platform_device *plf) if (ab8500_dir) debugfs_remove_recursive(ab8500_dir); dev_err(&plf->dev, "failed to create debugfs entries.\n"); -out_freeevent_name: - kfree(event_name); -out_freedev_attr: - kfree(dev_attr); -out_freeirq_count: - kfree(irq_count); - return ret; + return -ENOMEM; } static int ab8500_debug_remove(struct platform_device *plf) { debugfs_remove_recursive(ab8500_dir); - kfree(event_name); - kfree(dev_attr); - kfree(irq_count); return 0; } -- GitLab From 99cd4b4d5f4f0fa3678b2a4a89b345f2ec1de305 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:06 +0100 Subject: [PATCH 1088/2900] mfd: ab8500-gpadc: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ab8500-gpadc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 13f7866de46e..f1d4565e6fb4 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -925,7 +925,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) int ret = 0; struct ab8500_gpadc *gpadc; - gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL); + gpadc = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_gpadc), GFP_KERNEL); if (!gpadc) { dev_err(&pdev->dev, "Error: No memory\n"); return -ENOMEM; @@ -1005,8 +1005,6 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) free_irq(gpadc->irq_sw, gpadc); free_irq(gpadc->irq_hw, gpadc); fail: - kfree(gpadc); - gpadc = NULL; return ret; } @@ -1031,8 +1029,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) pm_runtime_put_noidle(gpadc->dev); - kfree(gpadc); - gpadc = NULL; return 0; } -- GitLab From c211b6b9c0144a531f08f0f975b45ecee895ae50 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:07 +0100 Subject: [PATCH 1089/2900] mfd: abx500-core: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/abx500-core.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c index 3714acb61458..f3a15aa54d7b 100644 --- a/drivers/mfd/abx500-core.c +++ b/drivers/mfd/abx500-core.c @@ -36,7 +36,9 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops) { struct abx500_device_entry *dev_entry; - dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); + dev_entry = devm_kzalloc(dev, + sizeof(struct abx500_device_entry), + GFP_KERNEL); if (!dev_entry) { dev_err(dev, "register_ops kzalloc failed"); return -ENOMEM; @@ -54,12 +56,8 @@ void abx500_remove_ops(struct device *dev) struct abx500_device_entry *dev_entry, *tmp; list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list) - { - if (dev_entry->dev == dev) { + if (dev_entry->dev == dev) list_del(&dev_entry->list); - kfree(dev_entry); - } - } } EXPORT_SYMBOL(abx500_remove_ops); -- GitLab From 76ba0b896bed38f7be13682a0170074a5235f1be Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:08 +0100 Subject: [PATCH 1090/2900] mfd: adp5520: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/adp5520.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 0d2eba023439..28346ad0b4a6 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -223,7 +223,7 @@ static int adp5520_probe(struct i2c_client *client, return -ENODEV; } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -244,7 +244,7 @@ static int adp5520_probe(struct i2c_client *client, if (ret) { dev_err(&client->dev, "failed to request irq %d\n", chip->irq); - goto out_free_chip; + return ret; } } @@ -302,9 +302,6 @@ static int adp5520_probe(struct i2c_client *client, if (chip->irq) free_irq(chip->irq, chip); -out_free_chip: - kfree(chip); - return ret; } @@ -317,7 +314,6 @@ static int adp5520_remove(struct i2c_client *client) adp5520_remove_subdevs(chip); adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); - kfree(chip); return 0; } -- GitLab From 1cee87fdf1f8b99585891e7defa1d08fef3c1451 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:09 +0100 Subject: [PATCH 1091/2900] mfd: asic3: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/asic3.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 1b15986c01e1..9532f749412f 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -958,7 +958,8 @@ static int __init asic3_probe(struct platform_device *pdev) unsigned long clksel; int ret = 0; - asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); + asic = devm_kzalloc(&pdev->dev, + sizeof(struct asic3), GFP_KERNEL); if (asic == NULL) { printk(KERN_ERR "kzalloc failed\n"); return -ENOMEM; @@ -970,16 +971,14 @@ static int __init asic3_probe(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { - ret = -ENOMEM; dev_err(asic->dev, "no MEM resource\n"); - goto out_free; + return -ENOMEM; } asic->mapping = ioremap(mem->start, resource_size(mem)); if (!asic->mapping) { - ret = -ENOMEM; dev_err(asic->dev, "Couldn't ioremap\n"); - goto out_free; + return -ENOMEM; } asic->irq_base = pdata->irq_base; @@ -1033,9 +1032,6 @@ static int __init asic3_probe(struct platform_device *pdev) out_unmap: iounmap(asic->mapping); - out_free: - kfree(asic); - return ret; } @@ -1058,8 +1054,6 @@ static int asic3_remove(struct platform_device *pdev) iounmap(asic->mapping); - kfree(asic); - return 0; } -- GitLab From 22f9ee756bfd9ce9b066e2f90cf9f002aa7d1d44 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:10 +0100 Subject: [PATCH 1092/2900] mfd: cros_ec: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/cros_ec.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c index 10cd14e35eb0..1f36885d674b 100644 --- a/drivers/mfd/cros_ec.c +++ b/drivers/mfd/cros_ec.c @@ -104,23 +104,19 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ec_dev->command_sendrecv = cros_ec_command_sendrecv; if (ec_dev->din_size) { - ec_dev->din = kmalloc(ec_dev->din_size, GFP_KERNEL); - if (!ec_dev->din) { - err = -ENOMEM; - goto fail_din; - } + ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); + if (!ec_dev->din) + return -ENOMEM; } if (ec_dev->dout_size) { - ec_dev->dout = kmalloc(ec_dev->dout_size, GFP_KERNEL); - if (!ec_dev->dout) { - err = -ENOMEM; - goto fail_dout; - } + ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); + if (!ec_dev->dout) + return -ENOMEM; } if (!ec_dev->irq) { dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq); - goto fail_irq; + return err; } err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread, @@ -128,7 +124,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) "chromeos-ec", ec_dev); if (err) { dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err); - goto fail_irq; + return err; } err = mfd_add_devices(dev, 0, cros_devs, @@ -145,11 +141,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) fail_mfd: free_irq(ec_dev->irq, ec_dev); -fail_irq: - kfree(ec_dev->dout); -fail_dout: - kfree(ec_dev->din); -fail_din: + return err; } EXPORT_SYMBOL(cros_ec_register); @@ -158,8 +150,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev) { mfd_remove_devices(ec_dev->dev); free_irq(ec_dev->irq, ec_dev); - kfree(ec_dev->dout); - kfree(ec_dev->din); return 0; } -- GitLab From 099053a497638a928dac278bd95f192220c3cde1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:11 +0100 Subject: [PATCH 1093/2900] mfd: davinci_voicecodec: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/davinci_voicecodec.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index c60ab0c3c4db..b6e297363946 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -50,7 +50,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev) struct mfd_cell *cell = NULL; int ret; - davinci_vc = kzalloc(sizeof(struct davinci_vc), GFP_KERNEL); + davinci_vc = devm_kzalloc(&pdev->dev, + sizeof(struct davinci_vc), GFP_KERNEL); if (!davinci_vc) { dev_dbg(&pdev->dev, "could not allocate memory for private data\n"); @@ -61,8 +62,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) if (IS_ERR(davinci_vc->clk)) { dev_dbg(&pdev->dev, "could not get the clock for voice codec\n"); - ret = -ENODEV; - goto fail1; + return -ENODEV; } clk_enable(davinci_vc->clk); @@ -145,8 +145,6 @@ static int __init davinci_vc_probe(struct platform_device *pdev) clk_disable(davinci_vc->clk); clk_put(davinci_vc->clk); davinci_vc->clk = NULL; -fail1: - kfree(davinci_vc); return ret; } @@ -164,8 +162,6 @@ static int davinci_vc_remove(struct platform_device *pdev) clk_put(davinci_vc->clk); davinci_vc->clk = NULL; - kfree(davinci_vc); - return 0; } -- GitLab From 58645b36b2ce0a3468e4fd445578227797c56d81 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:12 +0100 Subject: [PATCH 1094/2900] mfd: htc-egpio: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/htc-egpio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index bbaec0ccba8f..f2e0ad4b332e 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -270,7 +270,7 @@ static int __init egpio_probe(struct platform_device *pdev) int ret; /* Initialize ei data structure. */ - ei = kzalloc(sizeof(*ei), GFP_KERNEL); + ei = devm_kzalloc(&pdev->dev, sizeof(*ei), GFP_KERNEL); if (!ei) return -ENOMEM; @@ -306,7 +306,9 @@ static int __init egpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ei); ei->nchips = pdata->num_chips; - ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL); + ei->chip = devm_kzalloc(&pdev->dev, + sizeof(struct egpio_chip) * ei->nchips, + GFP_KERNEL); if (!ei->chip) { ret = -ENOMEM; goto fail; @@ -361,7 +363,6 @@ static int __init egpio_probe(struct platform_device *pdev) fail: printk(KERN_ERR "EGPIO failed to setup\n"); - kfree(ei); return ret; } @@ -380,8 +381,6 @@ static int __exit egpio_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); } iounmap(ei->base_addr); - kfree(ei->chip); - kfree(ei); return 0; } -- GitLab From 2b0b5e2dfe663f53bd07eafa01df9809edf6327e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:13 +0100 Subject: [PATCH 1095/2900] mfd: htc-i2cpld: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/htc-i2cpld.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c index 324187c0c124..c9dfce6ae0c2 100644 --- a/drivers/mfd/htc-i2cpld.c +++ b/drivers/mfd/htc-i2cpld.c @@ -514,8 +514,8 @@ static int htcpld_setup_chips(struct platform_device *pdev) /* Setup each chip's output GPIOs */ htcpld->nchips = pdata->num_chip; - htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips, - GFP_KERNEL); + htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips, + GFP_KERNEL); if (!htcpld->chip) { dev_warn(dev, "Unable to allocate memory for chips\n"); return -ENOMEM; @@ -580,12 +580,11 @@ static int htcpld_core_probe(struct platform_device *pdev) return -ENXIO; } - htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL); + htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL); if (!htcpld) return -ENOMEM; /* Find chained irq */ - ret = -EINVAL; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res) { int flags; @@ -598,7 +597,7 @@ static int htcpld_core_probe(struct platform_device *pdev) flags, pdev->name, htcpld); if (ret) { dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret); - goto fail; + return ret; } else device_init_wakeup(dev, 0); } @@ -609,7 +608,7 @@ static int htcpld_core_probe(struct platform_device *pdev) /* Setup the htcpld chips */ ret = htcpld_setup_chips(pdev); if (ret) - goto fail; + return ret; /* Request the GPIO(s) for the int reset and set them up */ if (pdata->int_reset_gpio_hi) { @@ -644,10 +643,6 @@ static int htcpld_core_probe(struct platform_device *pdev) dev_info(dev, "Initialized successfully\n"); return 0; - -fail: - kfree(htcpld); - return ret; } /* The I2C Driver -- used internally */ -- GitLab From 8692881e38644383398affaa68fcabc0299a4d7f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:14 +0100 Subject: [PATCH 1096/2900] mfd: htc-pasic3: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/htc-pasic3.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 0285fceb99a6..0a5e85fd8517 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -147,7 +147,7 @@ static int __init pasic3_probe(struct platform_device *pdev) if (!request_mem_region(r->start, resource_size(r), "pasic3")) return -EBUSY; - asic = kzalloc(sizeof(struct pasic3_data), GFP_KERNEL); + asic = devm_kzalloc(dev, sizeof(struct pasic3_data), GFP_KERNEL); if (!asic) return -ENOMEM; @@ -156,7 +156,6 @@ static int __init pasic3_probe(struct platform_device *pdev) asic->mapping = ioremap(r->start, resource_size(r)); if (!asic->mapping) { dev_err(dev, "couldn't ioremap PASIC3\n"); - kfree(asic); return -ENOMEM; } @@ -195,7 +194,6 @@ static int pasic3_remove(struct platform_device *pdev) iounmap(asic->mapping); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, resource_size(r)); - kfree(asic); return 0; } -- GitLab From fa75d4a6799ff73be55ae44ca7bc5470239a13db Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:15 +0100 Subject: [PATCH 1097/2900] mfd: janz-cmodio: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/janz-cmodio.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c index 45ece11cc27c..fcbb2e9dfd37 100644 --- a/drivers/mfd/janz-cmodio.c +++ b/drivers/mfd/janz-cmodio.c @@ -183,11 +183,10 @@ static int cmodio_pci_probe(struct pci_dev *dev, struct cmodio_device *priv; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&dev->dev, "unable to allocate private data\n"); - ret = -ENOMEM; - goto out_return; + return -ENOMEM; } pci_set_drvdata(dev, priv); @@ -197,7 +196,7 @@ static int cmodio_pci_probe(struct pci_dev *dev, ret = pci_enable_device(dev); if (ret) { dev_err(&dev->dev, "unable to enable device\n"); - goto out_free_priv; + return ret; } pci_set_master(dev); @@ -248,9 +247,7 @@ static int cmodio_pci_probe(struct pci_dev *dev, pci_release_regions(dev); out_pci_disable_device: pci_disable_device(dev); -out_free_priv: - kfree(priv); -out_return: + return ret; } @@ -263,7 +260,6 @@ static void cmodio_pci_remove(struct pci_dev *dev) iounmap(priv->ctrl); pci_release_regions(dev); pci_disable_device(dev); - kfree(priv); } #define PCI_VENDOR_ID_JANZ 0x13c3 -- GitLab From 742413a48fafad813393e8f5dcb26b8ac2944140 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:16 +0100 Subject: [PATCH 1098/2900] mfd: max77686: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/max77686.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index 5bd24670e1b6..f27a21831583 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c @@ -85,12 +85,12 @@ static int max77686_i2c_probe(struct i2c_client *i2c, pdata = max77686_i2c_parse_dt_pdata(&i2c->dev); if (!pdata) { - ret = -EIO; dev_err(&i2c->dev, "No platform data found.\n"); - goto err; + return -EIO; } - max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL); + max77686 = devm_kzalloc(&i2c->dev, + sizeof(struct max77686_dev), GFP_KERNEL); if (max77686 == NULL) return -ENOMEM; @@ -108,7 +108,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ret = PTR_ERR(max77686->regmap); dev_err(max77686->dev, "Failed to allocate register map: %d\n", ret); - kfree(max77686); return ret; } @@ -116,8 +115,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c, MAX77686_REG_DEVICE_ID, &data) < 0) { dev_err(max77686->dev, "device not found on this channel (this is not an error)\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } else dev_info(max77686->dev, "device found\n"); @@ -128,17 +126,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ret = mfd_add_devices(max77686->dev, -1, max77686_devs, ARRAY_SIZE(max77686_devs), NULL, 0, NULL); + if (ret < 0) { + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); + } - if (ret < 0) - goto err_mfd; - - return ret; - -err_mfd: - mfd_remove_devices(max77686->dev); - i2c_unregister_device(max77686->rtc); -err: - kfree(max77686); return ret; } @@ -148,7 +140,6 @@ static int max77686_i2c_remove(struct i2c_client *i2c) mfd_remove_devices(max77686->dev); i2c_unregister_device(max77686->rtc); - kfree(max77686); return 0; } -- GitLab From 02c7d848946d4f62ef9a2bee9de00b37e5941dc1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:17 +0100 Subject: [PATCH 1099/2900] mfd: max8925: Convert to managed resources for allocating memory Signed-off-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/max8925-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index 92bbebd31598..8042b3205eaa 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -170,7 +170,8 @@ static int max8925_probe(struct i2c_client *client, return -EINVAL; } - chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, + sizeof(struct max8925_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->i2c = client; @@ -199,7 +200,6 @@ static int max8925_remove(struct i2c_client *client) max8925_device_exit(chip); i2c_unregister_device(chip->adc); i2c_unregister_device(chip->rtc); - kfree(chip); return 0; } -- GitLab From 4f25bbdb160e4317f5d0efac90357d0a899a4be1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Jun 2013 16:12:52 +0200 Subject: [PATCH 1100/2900] iwlwifi: create opmode/device dependencies The older devices (pre-7000/3000 series) all only work with the DVM opmode due to firmware availability, while newer ones will only work with the MVM opmode for the same reason. When building a driver that only has one of MVM or DVM, there's no reason to build the device support and have the PCIe IDs for all devices since they can't be used anyway, so avoid that. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/Makefile | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-config.h | 4 ++++ drivers/net/wireless/iwlwifi/pcie/drv.c | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 3b5613ea458b..f55a758b87f6 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -7,14 +7,16 @@ iwlwifi-objs += iwl-notif-wait.o iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o -iwlwifi-objs += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwl-7000.o +iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o +iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o + +iwlwifi-objs += $(iwlwifi-m) iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o ccflags-y += -D__CHECK_ENDIAN__ -I$(src) - obj-$(CONFIG_IWLDVM) += dvm/ obj-$(CONFIG_IWLMVM) += mvm/ diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index a193832fc790..0189b9050f22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -237,6 +237,7 @@ struct iwl_cfg { /* * This list declares the config structures for all devices. */ +#if IS_ENABLED(CONFIG_IWLDVM) extern const struct iwl_cfg iwl5300_agn_cfg; extern const struct iwl_cfg iwl5100_agn_cfg; extern const struct iwl_cfg iwl5350_agn_cfg; @@ -278,11 +279,14 @@ extern const struct iwl_cfg iwl6035_2agn_cfg; extern const struct iwl_cfg iwl105_bgn_cfg; extern const struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl135_bgn_cfg; +#endif /* CONFIG_IWLDVM */ +#if IS_ENABLED(CONFIG_IWLMVM) extern const struct iwl_cfg iwl7260_2ac_cfg; extern const struct iwl_cfg iwl7260_2n_cfg; extern const struct iwl_cfg iwl7260_n_cfg; extern const struct iwl_cfg iwl3160_2ac_cfg; extern const struct iwl_cfg iwl3160_2n_cfg; extern const struct iwl_cfg iwl3160_n_cfg; +#endif /* CONFIG_IWLMVM */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index db7bdd35a9c5..81f3ea5b09a4 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -78,6 +78,7 @@ /* Hardware specific file defines the PCI IDs table for that hardware module */ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { +#if IS_ENABLED(CONFIG_IWLDVM) {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ @@ -253,7 +254,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)}, {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)}, {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)}, +#endif /* CONFIG_IWLDVM */ +#if IS_ENABLED(CONFIG_IWLMVM) /* 7000 Series */ {IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)}, @@ -304,6 +307,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, +#endif /* CONFIG_IWLMVM */ {0} }; -- GitLab From a1ace0aac5a83b859c2ddeb5dfb032b9b6dcd9cf Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 23 May 2013 16:25:03 +0100 Subject: [PATCH 1101/2900] mfd: 88pm860x: Convert to managed resources for allocating memory Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm860x-core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 629d6404cab4..eeb481d426b5 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -1150,7 +1150,8 @@ static int pm860x_probe(struct i2c_client *client, return -EINVAL; } - chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, + sizeof(struct pm860x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; @@ -1160,7 +1161,6 @@ static int pm860x_probe(struct i2c_client *client, ret = PTR_ERR(chip->regmap); dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); - kfree(chip); return ret; } chip->client = client; @@ -1203,7 +1203,6 @@ static int pm860x_remove(struct i2c_client *client) regmap_exit(chip->regmap_companion); i2c_unregister_device(chip->companion); } - kfree(chip); return 0; } -- GitLab From 36b51146539c42306fd6ab1ff30cfc5a2d13c706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Alc=C3=A2ntara?= Date: Tue, 21 May 2013 16:32:30 -0300 Subject: [PATCH 1102/2900] [media] smscoreapi: memory leak fix Ensure release_firmware is called if kmalloc fails. [mchehab@redhat.com: patch unmangled and converted from -p2 to -p1] Signed-off-by: Roberto Alcantara Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smscoreapi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index dbe9b4d9b799..a142f7942a01 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -1173,15 +1173,16 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, GFP_KERNEL | GFP_DMA); if (!fw_buf) { sms_err("failed to allocate firmware buffer"); - return -ENOMEM; - } - memcpy(fw_buf, fw->data, fw->size); - fw_buf_size = fw->size; + rc = -ENOMEM; + } else { + memcpy(fw_buf, fw->data, fw->size); + fw_buf_size = fw->size; - rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? - smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) - : loadfirmware_handler(coredev->context, fw_buf, - fw_buf_size); + rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? + smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) + : loadfirmware_handler(coredev->context, fw_buf, + fw_buf_size); + } kfree(fw_buf); release_firmware(fw); -- GitLab From 1c00a47e48d1bad3ca60c4e923d51c4ac6add5b5 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 13 Jun 2013 11:53:09 +0100 Subject: [PATCH 1103/2900] Makefile.lib: align DTB quiet_cmd The unaligned dtb.S filename in make output started to irritate me: DTC arch/metag/boot/dts/skeleton.dtb DTB arch/metag/boot/dts/skeleton.dtb.S AS arch/metag/boot/dts/skeleton.dtb.o LD arch/metag/boot/dts/built-in.o Add an extra space to quiet_cmd_dt_S_dtb so the dtb.S filename aligns with all the others. Signed-off-by: James Hogan Cc: Dirk Brandewie Cc: Grant Likely Cc: trivial@kernel.org Signed-off-by: Michal Marek --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 51bb3de680b6..e5c81aa60778 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -244,7 +244,7 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ # --------------------------------------------------------------------------- # Generate an assembly file to wrap the output of the device tree compiler -quiet_cmd_dt_S_dtb= DTB $@ +quiet_cmd_dt_S_dtb= DTB $@ cmd_dt_S_dtb= \ ( \ echo '\#include '; \ -- GitLab From ab6e134a48a58b111f28dfb5c8440a56d6be10c5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 03:55:13 -0300 Subject: [PATCH 1104/2900] [media] hdpvr: fix querystd 'unknown format' return If no format has been detected, then querystd should return V4L2_STD_UNKNOWN, not V4L2_STD_ALL. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 2d02b490756b..81018c478f44 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -613,7 +613,7 @@ static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) struct hdpvr_fh *fh = _fh; int ret; - *a = V4L2_STD_ALL; + *a = V4L2_STD_UNKNOWN; if (dev->options.video_input == HDPVR_COMPONENT) return fh->legacy_mode ? 0 : -ENODATA; ret = get_video_info(dev, &vid_info); -- GitLab From 79f10b625e5eff93c8fad54ba345e5f35feb8461 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 03:55:14 -0300 Subject: [PATCH 1105/2900] [media] hdpvr: code cleanup Remove an unnecessary 'else' and invert a condition which makes the code more readable. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 54 +++++++++++++-------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 81018c478f44..e9471059056e 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -281,43 +281,43 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) if (dev->status == STATUS_STREAMING) return 0; - else if (dev->status != STATUS_IDLE) + if (dev->status != STATUS_IDLE) return -EAGAIN; ret = get_video_info(dev, &vidinf); + if (ret) { + msleep(250); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "no video signal at input %d\n", dev->options.video_input); + return -EAGAIN; + } - if (!ret) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "video signal: %dx%d@%dhz\n", vidinf.width, - vidinf.height, vidinf.fps); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "video signal: %dx%d@%dhz\n", vidinf.width, + vidinf.height, vidinf.fps); - /* start streaming 2 request */ - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "encoder start control request returned %d\n", ret); - if (ret < 0) - return ret; + /* start streaming 2 request */ + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "encoder start control request returned %d\n", ret); + if (ret < 0) + return ret; - ret = hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); - if (ret) - return ret; + ret = hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + if (ret) + return ret; - dev->status = STATUS_STREAMING; + dev->status = STATUS_STREAMING; - INIT_WORK(&dev->worker, hdpvr_transmit_buffers); - queue_work(dev->workqueue, &dev->worker); + INIT_WORK(&dev->worker, hdpvr_transmit_buffers); + queue_work(dev->workqueue, &dev->worker); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "streaming started\n"); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "streaming started\n"); - return 0; - } - msleep(250); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no video signal at input %d\n", dev->options.video_input); - return -EAGAIN; + return 0; } -- GitLab From 5f454d82e5958e59c16580b9b4531f4bbc7231f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 03:55:15 -0300 Subject: [PATCH 1106/2900] [media] hdpvr: improve error handling get_video_info() should never return EFAULT, instead it should return the low-level usb_control_msg() error. Add a valid field to the hdpvr_video_info struct so the driver can easily check if a valid format was detected. Whenever get_video_info is called and it returns an error (e.g. usb_control_msg failed), then return that error to userspace as well. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-control.c | 21 +++++++++------------ drivers/media/usb/hdpvr/hdpvr-video.c | 18 +++++++++++------- drivers/media/usb/hdpvr/hdpvr.h | 1 + 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c index df6bcb524d80..6053661dc04b 100644 --- a/drivers/media/usb/hdpvr/hdpvr-control.c +++ b/drivers/media/usb/hdpvr/hdpvr-control.c @@ -49,6 +49,7 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) { int ret; + vidinf->valid = false; mutex_lock(&dev->usbc_mutex); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), @@ -56,11 +57,6 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) 0x1400, 0x0003, dev->usbc_buf, 5, 1000); - if (ret == 5) { - vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; - vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; - vidinf->fps = dev->usbc_buf[4]; - } #ifdef HDPVR_DEBUG if (hdpvr_debug & MSG_INFO) { @@ -73,14 +69,15 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) #endif mutex_unlock(&dev->usbc_mutex); - if ((ret > 0 && ret != 5) ||/* fail if unexpected byte count returned */ - !vidinf->width || /* preserve original behavior - */ - !vidinf->height || /* fail if no signal is detected */ - !vidinf->fps) { - ret = -EFAULT; - } + if (ret < 0) + return ret; - return ret < 0 ? ret : 0; + vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; + vidinf->fps = dev->usbc_buf[4]; + vidinf->valid = vidinf->width && vidinf->height && vidinf->fps; + + return 0; } int get_input_lines_info(struct hdpvr_device *dev) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index e9471059056e..4f8567aa99d8 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -285,7 +285,10 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) return -EAGAIN; ret = get_video_info(dev, &vidinf); - if (ret) { + if (ret < 0) + return ret; + + if (!vidinf.valid) { msleep(250); v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "no video signal at input %d\n", dev->options.video_input); @@ -617,15 +620,12 @@ static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) if (dev->options.video_input == HDPVR_COMPONENT) return fh->legacy_mode ? 0 : -ENODATA; ret = get_video_info(dev, &vid_info); - if (ret) - return 0; - if (vid_info.width == 720 && + if (vid_info.valid && vid_info.width == 720 && (vid_info.height == 480 || vid_info.height == 576)) { *a = (vid_info.height == 480) ? V4L2_STD_525_60 : V4L2_STD_625_50; } - - return 0; + return ret; } static int vidioc_s_dv_timings(struct file *file, void *_fh, @@ -679,6 +679,8 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, return -ENODATA; ret = get_video_info(dev, &vid_info); if (ret) + return ret; + if (!vid_info.valid) return -ENOLCK; interlaced = vid_info.fps <= 30; for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) { @@ -1008,7 +1010,9 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, struct hdpvr_video_info vid_info; ret = get_video_info(dev, &vid_info); - if (ret) + if (ret < 0) + return ret; + if (!vid_info.valid) return -EFAULT; f->fmt.pix.width = vid_info.width; f->fmt.pix.height = vid_info.height; diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index 808ea7a0efe5..dc685d44cb3e 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h @@ -154,6 +154,7 @@ struct hdpvr_video_info { u16 width; u16 height; u8 fps; + bool valid; }; enum { -- GitLab From cccb83f7a1848a8b2dda6480c2dc26e80710e50b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 29 May 2013 14:50:57 -0300 Subject: [PATCH 1107/2900] [media] adv7180: add more subdev video ops Add subdev video ops for ADV7180 video decoder. This makes decoder usable on the soc-camera drivers. [Sergei: renamed adv7180_try_mbus_fmt() to adv7180_mbus_fmt().] Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7180.c | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 04ee1d4a4b93..11f13a83a64b 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1,6 +1,8 @@ /* * adv7180.c Analog Devices ADV7180 video decoder driver * Copyright (c) 2009 Intel Corporation + * Copyright (C) 2013 Cogent Embedded, Inc. + * Copyright (C) 2013 Renesas Solutions Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -397,10 +399,54 @@ static void adv7180_exit_controls(struct adv7180_state *state) v4l2_ctrl_handler_free(&state->ctrl_hdl); } +static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index > 0) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YUYV8_2X8; + + return 0; +} + +static int adv7180_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct adv7180_state *state = to_state(sd); + + fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->width = 720; + fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576; + + return 0; +} + +static int adv7180_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + /* + * The ADV7180 sensor supports BT.601/656 output modes. + * The BT.656 is default and not yet configurable by s/w. + */ + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_BT656; + + return 0; +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, + .enum_mbus_fmt = adv7180_enum_mbus_fmt, + .try_mbus_fmt = adv7180_mbus_fmt, + .g_mbus_fmt = adv7180_mbus_fmt, + .s_mbus_fmt = adv7180_mbus_fmt, + .g_mbus_config = adv7180_g_mbus_config, }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { -- GitLab From ed3e12d2b03f756f09433f08c4606cdc61ffbc7c Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 29 May 2013 14:52:28 -0300 Subject: [PATCH 1108/2900] [media] ML86V7667: new video decoder driver Add OKI Semiconductor ML86V7667 video decoder driver. [Sergei: added v4l2_device_unregister_subdev() call to the error cleanup path of ml86v7667_probe(), renamed ml86v7667_try_mbus_fmt() to ml86v7667_mbus_fmt(), killed v4l2_chip_match_i2c_client() checks in the [gs]_register() methods, fixed the prototype of the s_register() method, did some cleanup.] Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 9 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ml86v7667.c | 431 ++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 drivers/media/i2c/ml86v7667.c diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index f981d50a2a8c..9c04ddb2101e 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -245,6 +245,15 @@ config VIDEO_KS0127 To compile this driver as a module, choose M here: the module will be called ks0127. +config VIDEO_ML86V7667 + tristate "OKI ML86V7667 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the OKI Semiconductor ML86V7667 video decoder. + + To compile this driver as a module, choose M here: the + module will be called ml86v7667. + config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" depends on VIDEO_V4L2 && I2C diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 720f42d9d9f4..b40ea089861a 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -70,3 +70,4 @@ obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o obj-$(CONFIG_VIDEO_AK881X) += ak881x.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c new file mode 100644 index 000000000000..0f256d3cc62b --- /dev/null +++ b/drivers/media/i2c/ml86v7667.c @@ -0,0 +1,431 @@ +/* + * OKI Semiconductor ML86V7667 video decoder driver + * + * Author: Vladimir Barinov + * Copyright (C) 2013 Cogent Embedded, Inc. + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "ml86v7667" + +/* Subaddresses */ +#define MRA_REG 0x00 /* Mode Register A */ +#define MRC_REG 0x02 /* Mode Register C */ +#define LUMC_REG 0x0C /* Luminance Control */ +#define CLC_REG 0x10 /* Contrast level control */ +#define SSEPL_REG 0x11 /* Sync separation level */ +#define CHRCA_REG 0x12 /* Chrominance Control A */ +#define ACCC_REG 0x14 /* ACC Loop filter & Chrominance control */ +#define ACCRC_REG 0x15 /* ACC Reference level control */ +#define HUE_REG 0x16 /* Hue control */ +#define ADC2_REG 0x1F /* ADC Register 2 */ +#define PLLR1_REG 0x20 /* PLL Register 1 */ +#define STATUS_REG 0x2C /* STATUS Register */ + +/* Mode Register A register bits */ +#define MRA_OUTPUT_MODE_MASK (3 << 6) +#define MRA_ITUR_BT601 (1 << 6) +#define MRA_ITUR_BT656 (0 << 6) +#define MRA_INPUT_MODE_MASK (7 << 3) +#define MRA_PAL_BT601 (4 << 3) +#define MRA_NTSC_BT601 (0 << 3) +#define MRA_REGISTER_MODE (1 << 0) + +/* Mode Register C register bits */ +#define MRC_AUTOSELECT (1 << 7) + +/* Luminance Control register bits */ +#define LUMC_ONOFF_SHIFT 7 +#define LUMC_ONOFF_MASK (1 << 7) + +/* Contrast level control register bits */ +#define CLC_CONTRAST_ONOFF (1 << 7) +#define CLC_CONTRAST_MASK 0x0F + +/* Sync separation level register bits */ +#define SSEPL_LUMINANCE_ONOFF (1 << 7) +#define SSEPL_LUMINANCE_MASK 0x7F + +/* Chrominance Control A register bits */ +#define CHRCA_MODE_SHIFT 6 +#define CHRCA_MODE_MASK (1 << 6) + +/* ACC Loop filter & Chrominance control register bits */ +#define ACCC_CHROMA_CR_SHIFT 3 +#define ACCC_CHROMA_CR_MASK (7 << 3) +#define ACCC_CHROMA_CB_SHIFT 0 +#define ACCC_CHROMA_CB_MASK (7 << 0) + +/* ACC Reference level control register bits */ +#define ACCRC_CHROMA_MASK 0xfc +#define ACCRC_CHROMA_SHIFT 2 + +/* ADC Register 2 register bits */ +#define ADC2_CLAMP_VOLTAGE_MASK (7 << 1) +#define ADC2_CLAMP_VOLTAGE(n) ((n & 7) << 1) + +/* PLL Register 1 register bits */ +#define PLLR1_FIXED_CLOCK (1 << 7) + +/* STATUS Register register bits */ +#define STATUS_HLOCK_DETECT (1 << 3) +#define STATUS_NTSCPAL (1 << 2) + +struct ml86v7667_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + v4l2_std_id std; +}; + +static inline struct ml86v7667_priv *to_ml86v7667(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct ml86v7667_priv, sd); +} + +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, struct ml86v7667_priv, hdl)->sd; +} + +static int ml86v7667_mask_set(struct i2c_client *client, const u8 reg, + const u8 mask, const u8 data) +{ + int val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) + return val; + + val = (val & ~mask) | (data & mask); + return i2c_smbus_write_byte_data(client, reg, val); +} + +static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = 0; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ret = ml86v7667_mask_set(client, SSEPL_REG, + SSEPL_LUMINANCE_MASK, ctrl->val); + break; + case V4L2_CID_CONTRAST: + ret = ml86v7667_mask_set(client, CLC_REG, + CLC_CONTRAST_MASK, ctrl->val); + break; + case V4L2_CID_CHROMA_GAIN: + ret = ml86v7667_mask_set(client, ACCRC_REG, ACCRC_CHROMA_MASK, + ctrl->val << ACCRC_CHROMA_SHIFT); + break; + case V4L2_CID_HUE: + ret = ml86v7667_mask_set(client, HUE_REG, ~0, ctrl->val); + break; + case V4L2_CID_RED_BALANCE: + ret = ml86v7667_mask_set(client, ACCC_REG, + ACCC_CHROMA_CR_MASK, + ctrl->val << ACCC_CHROMA_CR_SHIFT); + break; + case V4L2_CID_BLUE_BALANCE: + ret = ml86v7667_mask_set(client, ACCC_REG, + ACCC_CHROMA_CB_MASK, + ctrl->val << ACCC_CHROMA_CB_SHIFT); + break; + case V4L2_CID_SHARPNESS: + ret = ml86v7667_mask_set(client, LUMC_REG, + LUMC_ONOFF_MASK, + ctrl->val << LUMC_ONOFF_SHIFT); + break; + case V4L2_CID_COLOR_KILLER: + ret = ml86v7667_mask_set(client, CHRCA_REG, + CHRCA_MODE_MASK, + ctrl->val << CHRCA_MODE_SHIFT); + break; + } + + return 0; +} + +static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int status; + + status = i2c_smbus_read_byte_data(client, STATUS_REG); + if (status < 0) + return status; + + if (!(status & STATUS_HLOCK_DETECT)) + return V4L2_STD_UNKNOWN; + + *std = status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + + return 0; +} + +static int ml86v7667_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int status_reg; + + status_reg = i2c_smbus_read_byte_data(client, STATUS_REG); + if (status_reg < 0) + return status_reg; + + *status = status_reg & STATUS_HLOCK_DETECT ? 0 : V4L2_IN_ST_NO_SIGNAL; + + return 0; +} + +static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index > 0) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YUYV8_2X8; + + return 0; +} + +static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct ml86v7667_priv *priv = to_ml86v7667(sd); + + fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->width = 720; + fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; + + return 0; +} + +static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_BT656; + + return 0; +} + +static int ml86v7667_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct ml86v7667_priv *priv = to_ml86v7667(sd); + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int ret; + u8 mode; + + /* PAL/NTSC ITU-R BT.601 input mode */ + mode = std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601; + ret = ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, mode); + if (ret < 0) + return ret; + + priv->std = std; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ml86v7667_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + ret = i2c_smbus_read_byte_data(client, (u8)reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + reg->size = sizeof(u8); + + return 0; +} + +static int ml86v7667_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, (u8)reg->reg, (u8)reg->val); +} +#endif + +static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = { + .s_ctrl = ml86v7667_s_ctrl, +}; + +static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { + .querystd = ml86v7667_querystd, + .g_input_status = ml86v7667_g_input_status, + .enum_mbus_fmt = ml86v7667_enum_mbus_fmt, + .try_mbus_fmt = ml86v7667_mbus_fmt, + .g_mbus_fmt = ml86v7667_mbus_fmt, + .s_mbus_fmt = ml86v7667_mbus_fmt, + .g_mbus_config = ml86v7667_g_mbus_config, +}; + +static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = { + .s_std = ml86v7667_s_std, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ml86v7667_g_register, + .s_register = ml86v7667_s_register, +#endif +}; + +static struct v4l2_subdev_ops ml86v7667_subdev_ops = { + .core = &ml86v7667_subdev_core_ops, + .video = &ml86v7667_subdev_video_ops, +}; + +static int ml86v7667_init(struct ml86v7667_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int val; + int ret; + + /* BT.656-4 output mode, register mode */ + ret = ml86v7667_mask_set(client, MRA_REG, + MRA_OUTPUT_MODE_MASK | MRA_REGISTER_MODE, + MRA_ITUR_BT656 | MRA_REGISTER_MODE); + + /* PLL circuit fixed clock, 32MHz */ + ret |= ml86v7667_mask_set(client, PLLR1_REG, PLLR1_FIXED_CLOCK, + PLLR1_FIXED_CLOCK); + + /* ADC2 clamping voltage maximum */ + ret |= ml86v7667_mask_set(client, ADC2_REG, ADC2_CLAMP_VOLTAGE_MASK, + ADC2_CLAMP_VOLTAGE(7)); + + /* enable luminance function */ + ret |= ml86v7667_mask_set(client, SSEPL_REG, SSEPL_LUMINANCE_ONOFF, + SSEPL_LUMINANCE_ONOFF); + + /* enable contrast function */ + ret |= ml86v7667_mask_set(client, CLC_REG, CLC_CONTRAST_ONOFF, 0); + + /* + * PAL/NTSC autodetection is enabled after reset, + * set the autodetected std in manual std mode and + * disable autodetection + */ + val = i2c_smbus_read_byte_data(client, STATUS_REG); + if (val < 0) + return val; + + priv->std = val & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + ret |= ml86v7667_mask_set(client, MRC_REG, MRC_AUTOSELECT, 0); + + val = priv->std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601; + ret |= ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, val); + + return ret; +} + +static int ml86v7667_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ml86v7667_priv *priv; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + v4l2_i2c_subdev_init(&priv->sd, client, &ml86v7667_subdev_ops); + + v4l2_ctrl_handler_init(&priv->hdl, 8); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_BRIGHTNESS, -64, 63, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_CONTRAST, -8, 7, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_CHROMA_GAIN, -32, 31, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_RED_BALANCE, -4, 3, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_BLUE_BALANCE, -4, 3, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 1, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_COLOR_KILLER, 0, 1, 1, 0); + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; + if (ret) + goto cleanup; + + v4l2_ctrl_handler_setup(&priv->hdl); + + ret = ml86v7667_init(priv); + if (ret) + goto cleanup; + + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + return 0; + +cleanup: + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + return ret; +} + +static int ml86v7667_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ml86v7667_priv *priv = to_ml86v7667(sd); + + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); + + return 0; +} + +static const struct i2c_device_id ml86v7667_id[] = { + {DRV_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ml86v7667_id); + +static struct i2c_driver ml86v7667_i2c_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ml86v7667_probe, + .remove = ml86v7667_remove, + .id_table = ml86v7667_id, +}; + +module_i2c_driver(ml86v7667_i2c_driver); + +MODULE_DESCRIPTION("OKI Semiconductor ML86V7667 video decoder driver"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); -- GitLab From d13ac96f576ef23670d9e65f8f3771b17fd6dce1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 05:15:17 -0300 Subject: [PATCH 1109/2900] [media] ml86v7667: fix the querystd implementation The *std should be set to V4L2_STD_UNKNOWN, not the function's return code. Also, *std should be ANDed with 525_60 or 625_50. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ml86v7667.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index 0f256d3cc62b..cd9f86e743b2 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -169,10 +169,10 @@ static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) if (status < 0) return status; - if (!(status & STATUS_HLOCK_DETECT)) - return V4L2_STD_UNKNOWN; - - *std = status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + if (status & STATUS_HLOCK_DETECT) + *std &= status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + else + *std = V4L2_STD_UNKNOWN; return 0; } -- GitLab From 542d30f2e00eb10a3e548fb0d0f47646e51c3736 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 2 Jun 2013 19:41:45 -0300 Subject: [PATCH 1110/2900] [media] radio-keene: set initial frequency The device was never set to the initial frequency. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-keene.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index 4c9ae767fb31..99da3d4f8d95 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -93,7 +93,7 @@ static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) /* If bit 4 is set, then tune to the frequency. If bit 3 is set, then unmute; if bit 2 is set, then mute. If bit 1 is set, then enter idle mode; if bit 0 is set, - then enter transit mode. + then enter transmit mode. */ radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | (freq ? 0x10 : 0); @@ -350,7 +350,6 @@ static int usb_keene_probe(struct usb_interface *intf, radio->pa = 118; radio->tx = 0x32; radio->stereo = true; - radio->curfreq = 95.16 * FREQ_MUL; if (hdl->error) { retval = hdl->error; @@ -383,6 +382,8 @@ static int usb_keene_probe(struct usb_interface *intf, video_set_drvdata(&radio->vdev, radio); set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); + keene_cmd_main(radio, 95.16 * FREQ_MUL, false); + retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); -- GitLab From 4b9a4a666c271bcb10469f61515b3c518ccc668f Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Sun, 2 Jun 2013 19:41:46 -0300 Subject: [PATCH 1111/2900] [media] radio-keene: add delay in order to settle hardware It was found by trial and error testing that at least 11 ms delay is needed before first I/O, otherwise device will skip given command. Signed-off-by: Antti Palosaari Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-keene.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index 99da3d4f8d95..21db23b196be 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -382,6 +382,8 @@ static int usb_keene_probe(struct usb_interface *intf, video_set_drvdata(&radio->vdev, radio); set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); + /* at least 11ms is needed in order to settle hardware */ + msleep(20); keene_cmd_main(radio, 95.16 * FREQ_MUL, false); retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); -- GitLab From 68f9f8ae98a580fa710f9652b01b9690e224fb1f Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 25 May 2013 13:39:33 -0300 Subject: [PATCH 1112/2900] [media] ARM: davinci: dm365 evm: remove init_enable from ths7303 pdata Remove init_enable from ths7303 pdata as it is being dropped from ths7303_platform_data. The purpose of init_enable was that the device should start streaming video immediately but instead the bridge drivers should call s_stream explicitly for such devices. This is in fact what happens for the dm365, so setting init_enable here never made sense in the first place. Signed-off-by: Lad, Prabhakar [hans.verkuil@cisco.com: improve the commit comment] Acked-by: Sekhar Nori Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-davinci/board-dm365-evm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index fd38c8d22e3c..afbc439f11d4 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -509,7 +509,6 @@ struct ths7303_platform_data ths7303_pdata = { .ch_1 = 3, .ch_2 = 3, .ch_3 = 3, - .init_enable = 1, }; static struct amp_config_info vpbe_amp = { -- GitLab From d97ada97ae7b29a83bc04fc3a05ef7b75c88e335 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 25 May 2013 13:39:34 -0300 Subject: [PATCH 1113/2900] [media] media: i2c: ths7303: remove init_enable option from pdata This patch removes init_enable option from pdata, the init_enable was intended that the device should start streaming video immediately but ideally the bridge drivers should call s_stream explicitly for such devices to start video. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths7303.c | 4 +--- include/media/ths7303.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 65853eea09a1..8cddcd0cfa09 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -356,9 +356,7 @@ static int ths7303_setup(struct v4l2_subdev *sd) int ret; u8 mask; - state->stream_on = pdata->init_enable; - - mask = state->stream_on ? 0xff : 0xf8; + mask = 0xf8; ret = ths7303_write(sd, THS7303_CHANNEL_1, pdata->ch_1 & mask); if (ret) diff --git a/include/media/ths7303.h b/include/media/ths7303.h index 980ec51d574d..a7b49297da82 100644 --- a/include/media/ths7303.h +++ b/include/media/ths7303.h @@ -30,13 +30,11 @@ * @ch_1: Bias value for channel one. * @ch_2: Bias value for channel two. * @ch_3: Bias value for channel three. - * @init_enable: initalize on init. */ struct ths7303_platform_data { u8 ch_1; u8 ch_2; u8 ch_3; - u8 init_enable; }; #endif -- GitLab From 8524ce558a0111762efa1a6b5ba9ce5e092b4707 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 25 May 2013 13:39:35 -0300 Subject: [PATCH 1114/2900] [media] media: i2c: ths7303: remove unnecessary function ths7303_setup() the ths7303_setup() was doing the same thing as ths7303_setval() except that ths7303_setval() sets it to some particular mode. This patch removes ths7303_setup() function and calls ths7303_setval() in the probe setting the device to 480I_576I filter mode in the probe. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths7303.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 8cddcd0cfa09..af06187c74f8 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -349,30 +349,6 @@ static const struct v4l2_subdev_ops ths7303_ops = { .video = &ths7303_video_ops, }; -static int ths7303_setup(struct v4l2_subdev *sd) -{ - struct ths7303_state *state = to_state(sd); - struct ths7303_platform_data *pdata = &state->pdata; - int ret; - u8 mask; - - mask = 0xf8; - - ret = ths7303_write(sd, THS7303_CHANNEL_1, pdata->ch_1 & mask); - if (ret) - return ret; - - ret = ths7303_write(sd, THS7303_CHANNEL_2, pdata->ch_2 & mask); - if (ret) - return ret; - - ret = ths7303_write(sd, THS7303_CHANNEL_3, pdata->ch_3 & mask); - if (ret) - return ret; - - return 0; -} - static int ths7303_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -402,9 +378,10 @@ static int ths7303_probe(struct i2c_client *client, /* store the driver data to differntiate the chip */ state->driver_data = (int)id->driver_data; - if (ths7303_setup(sd) < 0) { - v4l_err(client, "init failed\n"); - return -EIO; + /* set to default 480I_576I filter mode */ + if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) { + v4l_err(client, "Setting to 480I_576I filter mode failed!\n"); + return -EINVAL; } return 0; -- GitLab From dd8c393b3c39f7ebd9ad69ce50cc836773d512b6 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 25 May 2013 13:39:36 -0300 Subject: [PATCH 1115/2900] [media] media: i2c: ths7303: make the pdata as a constant pointer generally the pdata needs to be a constant pointer in the device state structure. This patch makes the pdata as a constant pointer and alongside returns -EINVAL when pdata is NULL. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths7303.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index af06187c74f8..b954195cfbe7 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -35,7 +35,7 @@ struct ths7303_state { struct v4l2_subdev sd; - struct ths7303_platform_data pdata; + const struct ths7303_platform_data *pdata; struct v4l2_bt_timings bt; int std_id; int stream_on; @@ -89,7 +89,7 @@ int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ths7303_state *state = to_state(sd); - struct ths7303_platform_data *pdata = &state->pdata; + const struct ths7303_platform_data *pdata = state->pdata; u8 val, sel = 0; int err, disable = 0; @@ -356,6 +356,11 @@ static int ths7303_probe(struct i2c_client *client, struct ths7303_state *state; struct v4l2_subdev *sd; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; @@ -367,11 +372,7 @@ static int ths7303_probe(struct i2c_client *client, if (!state) return -ENOMEM; - if (!pdata) - v4l_warn(client, "No platform data, using default data!\n"); - else - state->pdata = *pdata; - + state->pdata = pdata; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &ths7303_ops); -- GitLab From ebea2f32e814445f94f9e087b646f1cf4d55fa5a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 13 Jun 2013 10:07:47 +0300 Subject: [PATCH 1116/2900] iwlwifi: mvm: take the seqno from packet if transmit failed The fw is unreliable in all the cases in which the packet wasn't sent. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index a830eb6cc411..72fc580f8d71 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -609,8 +609,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, !(info->flags & IEEE80211_TX_STAT_ACK)) info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ - if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { + /* W/A FW bug: seq_ctl is wrong when the status isn't success */ + if (status != TX_STATUS_SUCCESS) { struct ieee80211_hdr *hdr = (void *)skb->data; seq_ctl = le16_to_cpu(hdr->seq_ctrl); } -- GitLab From b378758658d91656b864170ad896f45269c22e2f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 11 Jun 2013 23:10:49 +0200 Subject: [PATCH 1117/2900] MIPS: Kconfig: Remove extranous help keyword. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 7a58ab933b20..49f98bf9e89d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1030,7 +1030,6 @@ config CPU_BIG_ENDIAN config CPU_LITTLE_ENDIAN bool "Little endian" depends on SYS_SUPPORTS_LITTLE_ENDIAN - help endchoice -- GitLab From adaf69186c24100d34c2fb107dacd33546cad3c5 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 13 Jun 2013 10:25:43 +0300 Subject: [PATCH 1118/2900] iwlwifi: mvm: remove obsolete comment Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/tx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 72fc580f8d71..42df1fdc5cbd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -407,7 +407,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, tid, txq_id, seq_number); - /* NOTE: aggregation will need changes here (for txq id) */ if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) goto drop_unlock_sta; -- GitLab From b8121f0f2fd9668ac4290bd969b664a4c1ca9ad5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 19:05:05 +0200 Subject: [PATCH 1119/2900] MIPS: : Don't reference CONFIG_* symbols. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/fcntl.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h index 0bda78f70e1e..6e9e74648f98 100644 --- a/arch/mips/include/uapi/asm/fcntl.h +++ b/arch/mips/include/uapi/asm/fcntl.h @@ -8,6 +8,7 @@ #ifndef _ASM_FCNTL_H #define _ASM_FCNTL_H +#include #define O_APPEND 0x0008 #define O_DSYNC 0x0010 /* used to be O_SYNC, see below */ @@ -55,7 +56,8 @@ * contain all the same fields as struct flock. */ -#ifdef CONFIG_32BIT +#if _MIPS_SIM != _MIPS_SIM_ABI64 + #include struct flock { @@ -70,7 +72,7 @@ struct flock { #define HAVE_ARCH_STRUCT_FLOCK -#endif /* CONFIG_32BIT */ +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #include -- GitLab From b967613d7e7c7bad176f5627c55e2d8c5aa2480e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 13 Jun 2013 11:45:59 +0300 Subject: [PATCH 1120/2900] iwlwifi: pcie: fix race in queue unmapping When a queue is disabled, it frees all its entries. Later, the op_mode might still get notifications from the firmware that triggers to free entries in the tx queue. The transport should be prepared for these races and know to ignore reclaim calls on queues that have been disabled and whose entries have been freed. Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/tx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index c5e30294c5ac..51fca425def7 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -576,9 +576,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) spin_lock_bh(&txq->lock); while (q->write_ptr != q->read_ptr) { + IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", + txq_id, q->read_ptr); iwl_pcie_txq_free_tfd(trans, txq); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } + txq->active = false; spin_unlock_bh(&txq->lock); } @@ -927,6 +930,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, spin_lock_bh(&txq->lock); + if (!txq->active) { + IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n", + txq_id, ssn); + goto out; + } + if (txq->q.read_ptr == tfd_num) goto out; @@ -1103,6 +1112,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, (fifo << SCD_QUEUE_STTS_REG_POS_TXF) | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | SCD_QUEUE_STTS_REG_MSK); + trans_pcie->txq[txq_id].active = true; IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d WrPtr: %d\n", txq_id, fifo, ssn & 0xff); } -- GitLab From 8a487b1a7432b20ff3f82387a8ce7555a964b44e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 13 Jun 2013 13:10:00 +0300 Subject: [PATCH 1121/2900] iwlwifi: pcie: wake the queue if stopped when being unmapped When the queue is unmapped while it was so loaded that mac80211's was stopped, we need to wake the queue after having freed all the packets in the queue. Not doing so can result in weird stuff like: * run lots of traffic (mac80211's queue gets stopped) * RFKILL * de-assert RFKILL * no traffic Cc: stable@vger.kernel.org Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 51fca425def7..48acfc620191 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -583,6 +583,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) } txq->active = false; spin_unlock_bh(&txq->lock); + + /* just in case - this queue may have been stopped */ + iwl_wake_queue(trans, txq); } /* -- GitLab From 191b79b0883cb0e604ba63fb3f85cf50ecfc9dc3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:34 -0300 Subject: [PATCH 1122/2900] [media] v4l2-ioctl: dbg_g/s_register: only match BRIDGE and SUBDEV types Drop support for V4L2_CHIP_MATCH_I2C_DRIVER/ADDR and V4L2_CHIP_MATCH_AC97 types. The following patches will remove support for those in the drivers as well. This means that bridge drivers no longer have to check for the match.type field in their g/s_register implementations. Only if they also implement g_chip_info do they still have to check the match.addr field, otherwise the core will check for that as well. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index f81bda1a48ec..60b8c259da96 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1807,7 +1807,8 @@ static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, return v4l2_subdev_call(sd, core, g_register, p); return -EINVAL; } - if (ops->vidioc_g_register) + if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && + (ops->vidioc_g_chip_info || p->match.addr == 0)) return ops->vidioc_g_register(file, fh, p); return -EINVAL; #else @@ -1834,7 +1835,8 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, return v4l2_subdev_call(sd, core, s_register, p); return -EINVAL; } - if (ops->vidioc_s_register) + if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && + (ops->vidioc_g_chip_info || p->match.addr == 0)) return ops->vidioc_s_register(file, fh, p); return -EINVAL; #else -- GitLab From e05eb3f8c1125405692bb0c41a13b560bc7f464d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 10:54:11 +0200 Subject: [PATCH 1123/2900] MIPS: Kconfig: Move ZONE_DMA to a more appropriate place. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 87ddac9477fa..f17ba1ea7a47 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -46,9 +46,6 @@ config MIPS menu "Machine selection" -config ZONE_DMA - bool - choice prompt "System type" default SGI_IP22 @@ -2464,6 +2461,9 @@ config I8253 select CLKEVT_I8253 select MIPS_EXTERNAL_TIMER +config ZONE_DMA + bool + config ZONE_DMA32 bool -- GitLab From 0cecddecd3d0f4e2d9499ad2f226969e82910e79 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 11 Jun 2013 23:10:49 +0200 Subject: [PATCH 1124/2900] MIPS: Kconfig: Remove extranous help keyword. Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f17ba1ea7a47..a46b0a2f8f0f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1013,7 +1013,6 @@ config CPU_BIG_ENDIAN config CPU_LITTLE_ENDIAN bool "Little endian" depends on SYS_SUPPORTS_LITTLE_ENDIAN - help endchoice -- GitLab From 4954a9a211f1863e3ca3958fd56ad06e1bddc22d Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:28:08 +0000 Subject: [PATCH 1125/2900] MIPS: Support SWIOTLB in default dma operations Provide a default implementation of phys_to_dma and dma_to_phys in mach-generic/dma_coherence.h. If CONFIG_NEED_SG_DMA_LENGTH is defined, the dma_length field in struct scatterlist is used. Set this up in mips_dma_map_sg so that the default mips DMA ops can be used when SWIOTLB is enabled. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5409/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-generic/dma-coherence.h | 12 ++++++++++++ arch/mips/mm/dma-default.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h index fe23034aaf72..74cb99257d5b 100644 --- a/arch/mips/include/asm/mach-generic/dma-coherence.h +++ b/arch/mips/include/asm/mach-generic/dma-coherence.h @@ -66,4 +66,16 @@ static inline int plat_device_is_coherent(struct device *dev) #endif } +#ifdef CONFIG_SWIOTLB +static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) +{ + return paddr; +} + +static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) +{ + return daddr; +} +#endif + #endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */ diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index caf92ecb37d6..aaccf1c10699 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -246,6 +246,9 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg, if (!plat_device_is_coherent(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); +#ifdef CONFIG_NEED_SG_DMA_LENGTH + sg->dma_length = sg->length; +#endif sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) + sg->offset; } -- GitLab From 79f8511c83f13689913f54d2f189297c226ec064 Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Mon, 10 Jun 2013 06:28:09 +0000 Subject: [PATCH 1126/2900] MIPS: Netlogic: SWIOTLB dma ops for 32-bit DMA Add SWIOTLB config option and related files to Netlogic platform. Some XLP SoC components like the SD/MMC interface cannot do DMA beyond 32-bit physical address. The SD/MMC driver can use memory outside this range for IO, to support this we have to add bounce buffers implemented by SWIOTLB. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: Ganesan Ramalingam Patchwork: https://patchwork.linux-mips.org/patch/5410/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/common.h | 3 + arch/mips/netlogic/Kconfig | 11 +++ arch/mips/netlogic/common/Makefile | 1 + arch/mips/netlogic/common/nlm-dma.c | 107 ++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 arch/mips/netlogic/common/nlm-dma.c diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index aef560a51a7e..70351b95ef88 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -76,6 +76,9 @@ void nlm_node_init(int node); extern struct plat_smp_ops nlm_smp_ops; extern char nlm_reset_entry[], nlm_reset_entry_end[]; +/* SWIOTLB */ +extern struct dma_map_ops nlm_swiotlb_dma_ops; + extern unsigned int nlm_threads_per_core; extern cpumask_t nlm_cpumask; diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index e0873a31ebaa..2447bf97d35a 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -51,4 +51,15 @@ endif config NLM_COMMON bool +config IOMMU_HELPER + bool + +config NEED_SG_DMA_LENGTH + bool + +config SWIOTLB + def_bool y + select NEED_SG_DMA_LENGTH + select IOMMU_HELPER + endif diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile index 291372a086f5..b29549741e05 100644 --- a/arch/mips/netlogic/common/Makefile +++ b/arch/mips/netlogic/common/Makefile @@ -1,3 +1,4 @@ obj-y += irq.o time.o +obj-y += nlm-dma.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o diff --git a/arch/mips/netlogic/common/nlm-dma.c b/arch/mips/netlogic/common/nlm-dma.c new file mode 100644 index 000000000000..f3d4ae87abc7 --- /dev/null +++ b/arch/mips/netlogic/common/nlm-dma.c @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2003-2013 Broadcom Corporation +* All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static char *nlm_swiotlb; + +static void *nlm_dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs) +{ + void *ret; + + if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) + return ret; + + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); + +#ifdef CONFIG_ZONE_DMA32 + if (dev->coherent_dma_mask <= DMA_BIT_MASK(32)) + gfp |= __GFP_DMA32; +#endif + + /* Don't invoke OOM killer */ + gfp |= __GFP_NORETRY; + + return swiotlb_alloc_coherent(dev, size, dma_handle, gfp); +} + +static void nlm_dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs) +{ + int order = get_order(size); + + if (dma_release_from_coherent(dev, order, vaddr)) + return; + + swiotlb_free_coherent(dev, size, vaddr, dma_handle); +} + +struct dma_map_ops nlm_swiotlb_dma_ops = { + .alloc = nlm_dma_alloc_coherent, + .free = nlm_dma_free_coherent, + .map_page = swiotlb_map_page, + .unmap_page = swiotlb_unmap_page, + .map_sg = swiotlb_map_sg_attrs, + .unmap_sg = swiotlb_unmap_sg_attrs, + .sync_single_for_cpu = swiotlb_sync_single_for_cpu, + .sync_single_for_device = swiotlb_sync_single_for_device, + .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, + .sync_sg_for_device = swiotlb_sync_sg_for_device, + .mapping_error = swiotlb_dma_mapping_error, + .dma_supported = swiotlb_dma_supported +}; + +void __init plat_swiotlb_setup(void) +{ + size_t swiotlbsize; + unsigned long swiotlb_nslabs; + + swiotlbsize = 1 << 20; /* 1 MB for now */ + swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT; + swiotlb_nslabs = ALIGN(swiotlb_nslabs, IO_TLB_SEGSIZE); + swiotlbsize = swiotlb_nslabs << IO_TLB_SHIFT; + + nlm_swiotlb = alloc_bootmem_low_pages(swiotlbsize); + swiotlb_init_with_tbl(nlm_swiotlb, swiotlb_nslabs, 1); +} -- GitLab From 2c952e06e4f57716109b609956eda28c900faac0 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:30:00 +0000 Subject: [PATCH 1127/2900] MIPS: Move cop2 save/restore to switch_to() Move the common code for saving and restoring platform specific COP2 registers to switch_to(). This will make supporting new platforms (like Netlogic XLP) easier. The platform specific COP2 definitions are to be specified in asm/processor.h and in asm/cop2.h. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5411/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cop2.h | 19 +++++++++++++++++++ arch/mips/include/asm/processor.h | 18 +++++++----------- arch/mips/include/asm/switch_to.h | 19 ++++++++++++++++++- arch/mips/kernel/octeon_switch.S | 27 --------------------------- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index 3532e2c5f098..b17f38ee1ed4 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h @@ -11,6 +11,25 @@ #include +#if defined(CONFIG_CPU_CAVIUM_OCTEON) + +extern void octeon_cop2_save(struct octeon_cop2_state *); +extern void octeon_cop2_restore(struct octeon_cop2_state *); + +#define cop2_save(r) octeon_cop2_save(r) +#define cop2_restore(r) octeon_cop2_restore(r) + +#define cop2_present 1 +#define cop2_lazy_restore 1 + +#else + +#define cop2_present 0 +#define cop2_lazy_restore 0 +#define cop2_save(r) +#define cop2_restore(r) +#endif + enum cu2_ops { CU2_EXCEPTION, CU2_LWC2_OP, diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 1470b7b68b0e..7c637a461ced 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -137,7 +137,7 @@ union mips_watch_reg_state { struct mips3264_watch_reg_state mips3264; }; -#ifdef CONFIG_CPU_CAVIUM_OCTEON +#if defined(CONFIG_CPU_CAVIUM_OCTEON) struct octeon_cop2_state { /* DMFC2 rt, 0x0201 */ @@ -182,13 +182,16 @@ struct octeon_cop2_state { /* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */ unsigned long cop2_gfm_result[2]; }; -#define INIT_OCTEON_COP2 {0,} +#define COP2_INIT \ + .cp2 = {0,}, struct octeon_cvmseg_state { unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE] [cpu_dcache_line_size() / sizeof(unsigned long)]; }; +#else +#define COP2_INIT #endif typedef struct { @@ -245,13 +248,6 @@ struct thread_struct { #define FPAFF_INIT #endif /* CONFIG_MIPS_MT_FPAFF */ -#ifdef CONFIG_CPU_CAVIUM_OCTEON -#define OCTEON_INIT \ - .cp2 = INIT_OCTEON_COP2, -#else -#define OCTEON_INIT -#endif /* CONFIG_CPU_CAVIUM_OCTEON */ - #define INIT_THREAD { \ /* \ * Saved main processor registers \ @@ -300,9 +296,9 @@ struct thread_struct { .cp0_baduaddr = 0, \ .error_code = 0, \ /* \ - * Cavium Octeon specifics (null if not Octeon) \ + * Platform specific cop2 registers(null if no COP2) \ */ \ - OCTEON_INIT \ + COP2_INIT \ } struct task_struct; diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index fd16bcb6c311..eb0af15ac656 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -15,6 +15,7 @@ #include #include #include +#include struct task_struct; @@ -66,10 +67,18 @@ do { \ #define switch_to(prev, next, last) \ do { \ - u32 __usedfpu; \ + u32 __usedfpu, __c0_stat; \ __mips_mt_fpaff_switch_to(prev); \ if (cpu_has_dsp) \ __save_dsp(prev); \ + if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) { \ + if (cop2_lazy_restore) \ + KSTK_STATUS(prev) &= ~ST0_CU2; \ + __c0_stat = read_c0_status(); \ + write_c0_status(__c0_stat | ST0_CU2); \ + cop2_save(&prev->thread.cp2); \ + write_c0_status(__c0_stat & ~ST0_CU2); \ + } \ __clear_software_ll_bit(); \ __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU); \ (last) = resume(prev, next, task_thread_info(next), __usedfpu); \ @@ -77,6 +86,14 @@ do { \ #define finish_arch_switch(prev) \ do { \ + u32 __c0_stat; \ + if (cop2_present && !cop2_lazy_restore && \ + (KSTK_STATUS(current) & ST0_CU2)) { \ + __c0_stat = read_c0_status(); \ + write_c0_status(__c0_stat | ST0_CU2); \ + cop2_restore(¤t->thread.cp2); \ + write_c0_status(__c0_stat & ~ST0_CU2); \ + } \ if (cpu_has_dsp) \ __restore_dsp(current); \ if (cpu_has_userlocal) \ diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 0e23343eb0a9..22e2aa1e8d37 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S @@ -40,33 +40,6 @@ cpu_save_nonscratch a0 LONG_S ra, THREAD_REG31(a0) - /* check if we need to save COP2 registers */ - PTR_L t2, TASK_THREAD_INFO(a0) - LONG_L t0, ST_OFF(t2) - bbit0 t0, 30, 1f - - /* Disable COP2 in the stored process state */ - li t1, ST0_CU2 - xor t0, t1 - LONG_S t0, ST_OFF(t2) - - /* Enable COP2 so we can save it */ - mfc0 t0, CP0_STATUS - or t0, t1 - mtc0 t0, CP0_STATUS - - /* Save COP2 */ - daddu a0, THREAD_CP2 - jal octeon_cop2_save - dsubu a0, THREAD_CP2 - - /* Disable COP2 now that we are done */ - mfc0 t0, CP0_STATUS - li t1, ST0_CU2 - xor t0, t1 - mtc0 t0, CP0_STATUS - -1: #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 /* Check if we need to store CVMSEG state */ mfc0 t0, $11,7 /* CvmMemCtl */ -- GitLab From 83bee792d7cb20d250be57e99d97f8cc83d9b4d5 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:30:01 +0000 Subject: [PATCH 1128/2900] MIPS: Allow kernel to use coprocessor 2 Kernel threads should be able to use COP2 if the platform needs it. Do not call die_if_kernel() for a coprocessor unusable exception if the exception due to COP2 usage. Instead, the default notifier for COP2 exceptions is updated to call die_if_kernel. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5415/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index beba1e616b6e..142d2bede024 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1056,15 +1056,9 @@ static int default_cu2_call(struct notifier_block *nfb, unsigned long action, { struct pt_regs *regs = data; - switch (action) { - default: - die_if_kernel("Unhandled kernel unaligned access or invalid " + die_if_kernel("COP2: Unhandled kernel unaligned access or invalid " "instruction", regs); - /* Fall through */ - - case CU2_EXCEPTION: - force_sig(SIGILL, current); - } + force_sig(SIGILL, current); return NOTIFY_OK; } @@ -1080,10 +1074,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) unsigned long __maybe_unused flags; prev_state = exception_enter(); - die_if_kernel("do_cpu invoked from kernel context!", regs); - cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; + if (cpid != 2) + die_if_kernel("do_cpu invoked from kernel context!", regs); + switch (cpid) { case 0: epc = (unsigned int __user *)exception_epc(regs); -- GitLab From 1c146cd46fccfaa5525152f086da2752fe0ed4dd Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:30:02 +0000 Subject: [PATCH 1129/2900] MIPS: Netlogic: Fix nlm_read_c2_status() definition The sel argument os nlm_read_c2_status() was not used and the macro returned the sel 0 in all cases. Fix this by defining two macros: nlm_read_c2_status0() and nlm_read_c2_status1() to return the two status registers. Add functions to write to the status registers as well. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5414/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/xlr/fmn.h | 8 ++++++-- arch/mips/netlogic/xlr/fmn.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h index 2a78929cef73..56c7b85ea7dd 100644 --- a/arch/mips/include/asm/netlogic/xlr/fmn.h +++ b/arch/mips/include/asm/netlogic/xlr/fmn.h @@ -175,6 +175,10 @@ #define nlm_write_c2_cc14(s, v) __write_32bit_c2_register($30, s, v) #define nlm_write_c2_cc15(s, v) __write_32bit_c2_register($31, s, v) +#define nlm_read_c2_status0() __read_32bit_c2_register($2, 0) +#define nlm_write_c2_status0(v) __write_32bit_c2_register($2, 0, v) +#define nlm_read_c2_status1() __read_32bit_c2_register($2, 1) +#define nlm_write_c2_status1(v) __write_32bit_c2_register($2, 1, v) #define nlm_read_c2_status(sel) __read_32bit_c2_register($2, 0) #define nlm_read_c2_config() __read_32bit_c2_register($3, 0) #define nlm_write_c2_config(v) __write_32bit_c2_register($3, 0, v) @@ -296,7 +300,7 @@ static inline int nlm_fmn_send(unsigned int size, unsigned int code, */ for (i = 0; i < 8; i++) { nlm_msgsnd(dest); - status = nlm_read_c2_status(0); + status = nlm_read_c2_status0(); if ((status & 0x2) == 1) pr_info("Send pending fail!\n"); if ((status & 0x4) == 0) @@ -316,7 +320,7 @@ static inline int nlm_fmn_receive(int bucket, int *size, int *code, int *stid, /* wait for load pending to clear */ do { - status = nlm_read_c2_status(1); + status = nlm_read_c2_status0(); } while ((status & 0x08) != 0); /* receive error bits */ diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c index 4d74f03de506..0fdce61857cd 100644 --- a/arch/mips/netlogic/xlr/fmn.c +++ b/arch/mips/netlogic/xlr/fmn.c @@ -80,7 +80,7 @@ static irqreturn_t fmn_message_handler(int irq, void *data) while (1) { /* 8 bkts per core, [24:31] each bit represents one bucket * Bit is Zero if bucket is not empty */ - bkt_status = (nlm_read_c2_status() >> 24) & 0xff; + bkt_status = (nlm_read_c2_status0() >> 24) & 0xff; if (bkt_status == 0xff) break; for (bucket = 0; bucket < 8; bucket++) { -- GitLab From 64f6ebe63914835ad5cd5bc4c490f3deaeac2511 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:30:03 +0000 Subject: [PATCH 1130/2900] MIPS: Netlogic: rename nlm_cop2_save/restore Rename macro nlm_cop2_enable() to nlm_cop2_enable_irqsave() and the macro nlm_cop2_restore to nlm_cop2_disable_irqrestore(). The new names will reflect the functionality better, and will make nlm_cop2_restore() available to be used later in COP2 save/restore patch. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5412/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/xlr/fmn.h | 4 ++-- arch/mips/netlogic/xlr/fmn.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h index 56c7b85ea7dd..5604db3d1836 100644 --- a/arch/mips/include/asm/netlogic/xlr/fmn.h +++ b/arch/mips/include/asm/netlogic/xlr/fmn.h @@ -241,7 +241,7 @@ static inline void nlm_msgwait(unsigned int mask) /* * Disable interrupts and enable COP2 access */ -static inline uint32_t nlm_cop2_enable(void) +static inline uint32_t nlm_cop2_enable_irqsave(void) { uint32_t sr = read_c0_status(); @@ -249,7 +249,7 @@ static inline uint32_t nlm_cop2_enable(void) return sr; } -static inline void nlm_cop2_restore(uint32_t sr) +static inline void nlm_cop2_disable_irqrestore(uint32_t sr) { write_c0_status(sr); } diff --git a/arch/mips/netlogic/xlr/fmn.c b/arch/mips/netlogic/xlr/fmn.c index 0fdce61857cd..d428e8471eec 100644 --- a/arch/mips/netlogic/xlr/fmn.c +++ b/arch/mips/netlogic/xlr/fmn.c @@ -74,7 +74,7 @@ static irqreturn_t fmn_message_handler(int irq, void *data) struct nlm_fmn_msg msg; uint32_t mflags, bkt_status; - mflags = nlm_cop2_enable(); + mflags = nlm_cop2_enable_irqsave(); /* Disable message ring interrupt */ nlm_fmn_setup_intr(irq, 0); while (1) { @@ -97,16 +97,16 @@ static irqreturn_t fmn_message_handler(int irq, void *data) pr_warn("No msgring handler for stnid %d\n", src_stnid); else { - nlm_cop2_restore(mflags); + nlm_cop2_disable_irqrestore(mflags); hndlr->action(bucket, src_stnid, size, code, &msg, hndlr->arg); - mflags = nlm_cop2_enable(); + mflags = nlm_cop2_enable_irqsave(); } } }; /* Enable message ring intr, to any thread in core */ nlm_fmn_setup_intr(irq, (1 << nlm_threads_per_core) - 1); - nlm_cop2_restore(mflags); + nlm_cop2_disable_irqrestore(mflags); return IRQ_HANDLED; } @@ -128,7 +128,7 @@ void xlr_percpu_fmn_init(void) bucket_sizes = xlr_board_fmn_config.bucket_size; cpu_fmn_info = &xlr_board_fmn_config.cpu[id]; - flags = nlm_cop2_enable(); + flags = nlm_cop2_enable_irqsave(); /* Setup bucket sizes for the core. */ nlm_write_c2_bucksize(0, bucket_sizes[id * 8 + 0]); @@ -166,7 +166,7 @@ void xlr_percpu_fmn_init(void) /* enable FMN interrupts on this CPU */ nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1); - nlm_cop2_restore(flags); + nlm_cop2_disable_irqrestore(flags); } @@ -198,7 +198,7 @@ void nlm_setup_fmn_irq(void) /* setup irq only once */ setup_irq(IRQ_FMN, &fmn_irqaction); - flags = nlm_cop2_enable(); + flags = nlm_cop2_enable_irqsave(); nlm_fmn_setup_intr(IRQ_FMN, (1 << nlm_threads_per_core) - 1); - nlm_cop2_restore(flags); + nlm_cop2_disable_irqrestore(flags); } -- GitLab From 5649d37c2b23ad6545709c976b9abbfa8d5f4e11 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:30:04 +0000 Subject: [PATCH 1131/2900] MIPS: Netlogic: COP2 save/restore code Add COP2 register state structure and functions for Netlogic XLP. The RX and TX buffers and status registers are to be saved. Since the registers are 64-bit, do the implementation in inline assembly which works on both 32-bit and 64-bit kernels. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: ddaney.cavm@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5413/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cop2.h | 10 +++ arch/mips/include/asm/processor.h | 13 ++++ arch/mips/netlogic/xlp/Makefile | 2 +- arch/mips/netlogic/xlp/cop2-ex.c | 118 ++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 arch/mips/netlogic/xlp/cop2-ex.c diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h index b17f38ee1ed4..c1516cc0285f 100644 --- a/arch/mips/include/asm/cop2.h +++ b/arch/mips/include/asm/cop2.h @@ -22,6 +22,16 @@ extern void octeon_cop2_restore(struct octeon_cop2_state *); #define cop2_present 1 #define cop2_lazy_restore 1 +#elif defined(CONFIG_CPU_XLP) + +extern void nlm_cop2_save(struct nlm_cop2_state *); +extern void nlm_cop2_restore(struct nlm_cop2_state *); +#define cop2_save(r) nlm_cop2_save(r) +#define cop2_restore(r) nlm_cop2_restore(r) + +#define cop2_present 1 +#define cop2_lazy_restore 0 + #else #define cop2_present 0 diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 7c637a461ced..016dc4bffc80 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -190,6 +190,16 @@ struct octeon_cvmseg_state { [cpu_dcache_line_size() / sizeof(unsigned long)]; }; +#elif defined(CONFIG_CPU_XLP) +struct nlm_cop2_state { + u64 rx[4]; + u64 tx[4]; + u32 tx_msg_status; + u32 rx_msg_status; +}; + +#define COP2_INIT \ + .cp2 = {{0}, {0}, 0, 0}, #else #define COP2_INIT #endif @@ -236,6 +246,9 @@ struct thread_struct { #ifdef CONFIG_CPU_CAVIUM_OCTEON struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128))); struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128))); +#endif +#ifdef CONFIG_CPU_XLP + struct nlm_cop2_state cp2; #endif struct mips_abi *abi; }; diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index a84d6ed3746c..e8dd14c38cb6 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -1,3 +1,3 @@ -obj-y += setup.o nlm_hal.o +obj-y += setup.o nlm_hal.o cop2-ex.o obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_USB) += usb-init.o diff --git a/arch/mips/netlogic/xlp/cop2-ex.c b/arch/mips/netlogic/xlp/cop2-ex.c new file mode 100644 index 000000000000..52bc5de42005 --- /dev/null +++ b/arch/mips/netlogic/xlp/cop2-ex.c @@ -0,0 +1,118 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Broadcom Corporation. + * + * based on arch/mips/cavium-octeon/cpu.c + * Copyright (C) 2009 Wind River Systems, + * written by Ralf Baechle + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/* + * 64 bit ops are done in inline assembly to support 32 bit + * compilation + */ +void nlm_cop2_save(struct nlm_cop2_state *r) +{ + asm volatile( + ".set push\n" + ".set noat\n" + "dmfc2 $1, $0, 0\n" + "sd $1, 0(%1)\n" + "dmfc2 $1, $0, 1\n" + "sd $1, 8(%1)\n" + "dmfc2 $1, $0, 2\n" + "sd $1, 16(%1)\n" + "dmfc2 $1, $0, 3\n" + "sd $1, 24(%1)\n" + "dmfc2 $1, $1, 0\n" + "sd $1, 0(%2)\n" + "dmfc2 $1, $1, 1\n" + "sd $1, 8(%2)\n" + "dmfc2 $1, $1, 2\n" + "sd $1, 16(%2)\n" + "dmfc2 $1, $1, 3\n" + "sd $1, 24(%2)\n" + ".set pop\n" + : "=m"(*r) + : "r"(r->tx), "r"(r->rx)); + + r->tx_msg_status = __read_32bit_c2_register($2, 0); + r->rx_msg_status = __read_32bit_c2_register($3, 0) & 0x0fffffff; +} + +void nlm_cop2_restore(struct nlm_cop2_state *r) +{ + u32 rstat; + + asm volatile( + ".set push\n" + ".set noat\n" + "ld $1, 0(%1)\n" + "dmtc2 $1, $0, 0\n" + "ld $1, 8(%1)\n" + "dmtc2 $1, $0, 1\n" + "ld $1, 16(%1)\n" + "dmtc2 $1, $0, 2\n" + "ld $1, 24(%1)\n" + "dmtc2 $1, $0, 3\n" + "ld $1, 0(%2)\n" + "dmtc2 $1, $1, 0\n" + "ld $1, 8(%2)\n" + "dmtc2 $1, $1, 1\n" + "ld $1, 16(%2)\n" + "dmtc2 $1, $1, 2\n" + "ld $1, 24(%2)\n" + "dmtc2 $1, $1, 3\n" + ".set pop\n" + : : "m"(*r), "r"(r->tx), "r"(r->rx)); + + __write_32bit_c2_register($2, 0, r->tx_msg_status); + rstat = __read_32bit_c2_register($3, 0) & 0xf0000000u; + __write_32bit_c2_register($3, 0, r->rx_msg_status | rstat); +} + +static int nlm_cu2_call(struct notifier_block *nfb, unsigned long action, + void *data) +{ + unsigned long flags; + unsigned int status; + + switch (action) { + case CU2_EXCEPTION: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + break; + local_irq_save(flags); + KSTK_STATUS(current) |= ST0_CU2; + status = read_c0_status(); + write_c0_status(status | ST0_CU2); + nlm_cop2_restore(&(current->thread.cp2)); + write_c0_status(status & ~ST0_CU2); + local_irq_restore(flags); + pr_info("COP2 access enabled for pid %d (%s)\n", + current->pid, current->comm); + return NOTIFY_BAD; /* Don't call default notifier */ + } + + return NOTIFY_OK; /* Let default notifier send signals */ +} + +static int __init nlm_cu2_setup(void) +{ + return cu2_notifier(nlm_cu2_call, 0); +} +early_initcall(nlm_cu2_setup); -- GitLab From d6a5078459d95137d8d620787d1099a3016932a9 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:33:25 +0000 Subject: [PATCH 1132/2900] MIPS: boot: Fixes for compressed/uart-16550.c Fix uart-16550.c for adding XLR/XLP support, changes are: * Make register read/write use volatile pointers * Support 32 bit IO read/write * Increase timeout in waiting for UART LSR Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5416/ Signed-off-by: Ralf Baechle --- arch/mips/boot/compressed/uart-16550.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c index 1c7b739b6a1d..90ae4400c40c 100644 --- a/arch/mips/boot/compressed/uart-16550.c +++ b/arch/mips/boot/compressed/uart-16550.c @@ -23,23 +23,27 @@ #define PORT(offset) (UART0_BASE + (4 * offset)) #endif +#ifndef IOTYPE +#define IOTYPE char +#endif + #ifndef PORT #error please define the serial port address for your own machine #endif static inline unsigned int serial_in(int offset) { - return *((char *)PORT(offset)); + return *((volatile IOTYPE *)PORT(offset)) & 0xFF; } static inline void serial_out(int offset, int value) { - *((char *)PORT(offset)) = value; + *((volatile IOTYPE *)PORT(offset)) = value & 0xFF; } void putc(char c) { - int timeout = 1024; + int timeout = 1000000; while (((serial_in(UART_LSR) & UART_LSR_THRE) == 0) && (timeout-- > 0)) ; -- GitLab From 8f0b043045d0b19d7eb8b510bfe279c9bb05d952 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:33:26 +0000 Subject: [PATCH 1133/2900] MIPS: Netlogic: Support compressed kernel Add SYS_SUPPORTS_ZBOOT and SYS_SUPPORTS_ZBOOT_UART16550 config options for XLR and XLP. Update boot/compressed/uart-16550.c to add UART port for XLR and XLP. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5417/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 4 ++++ arch/mips/boot/compressed/uart-16550.c | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index a46b0a2f8f0f..69bf31062ca4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -788,6 +788,8 @@ config NLM_XLR_BOARD select SYS_HAS_EARLY_PRINTK select USB_ARCH_HAS_OHCI if USB_SUPPORT select USB_ARCH_HAS_EHCI if USB_SUPPORT + select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_ZBOOT_UART16550 help Support for systems based on Netlogic XLR and XLS processors. Say Y here if you have a XLR or XLS based board. @@ -814,6 +816,8 @@ config NLM_XLP_BOARD select SYNC_R4K select SYS_HAS_EARLY_PRINTK select USE_OF + select SYS_SUPPORTS_ZBOOT + select SYS_SUPPORTS_ZBOOT_UART16550 help This board is based on Netlogic XLP Processor. Say Y here if you have a XLP based board. diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c index 90ae4400c40c..c01d343ce6ad 100644 --- a/arch/mips/boot/compressed/uart-16550.c +++ b/arch/mips/boot/compressed/uart-16550.c @@ -23,6 +23,18 @@ #define PORT(offset) (UART0_BASE + (4 * offset)) #endif +#ifdef CONFIG_CPU_XLR +#define UART0_BASE 0x1EF14000 +#define PORT(offset) (CKSEG1ADDR(UART0_BASE) + (4 * offset)) +#define IOTYPE unsigned int +#endif + +#ifdef CONFIG_CPU_XLP +#define UART0_BASE 0x18030100 +#define PORT(offset) (CKSEG1ADDR(UART0_BASE) + (4 * offset)) +#define IOTYPE unsigned int +#endif + #ifndef IOTYPE #define IOTYPE char #endif -- GitLab From aceee09d4f09dd7a6be48d04d329c140a5caaaf7 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:00 +0000 Subject: [PATCH 1134/2900] MIPS: Netlogic: Split XLP device tree code to dt.c Create new flle arch/mips/netlogic/xlp/dt.c and move the device tree related code there. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5422/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/xlp-hal/xlp.h | 1 + arch/mips/netlogic/xlp/Makefile | 2 +- arch/mips/netlogic/xlp/dt.c | 99 ++++++++++++++++++++ arch/mips/netlogic/xlp/setup.c | 73 +-------------- 4 files changed, 105 insertions(+), 70 deletions(-) create mode 100644 arch/mips/netlogic/xlp/dt.c diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 7e47209327a5..f4ea0f7f3965 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -59,6 +59,7 @@ void xlp_wakeup_secondary_cpus(void); void xlp_mmu_init(void); void nlm_hal_init(void); +void *xlp_dt_init(void *fdtp); #endif /* !__ASSEMBLY__ */ #endif /* _ASM_NLM_XLP_H */ diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index e8dd14c38cb6..85ac4a892ced 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -1,3 +1,3 @@ -obj-y += setup.o nlm_hal.o cop2-ex.o +obj-y += setup.o nlm_hal.o cop2-ex.o dt.o obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_USB) += usb-init.o diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c new file mode 100644 index 000000000000..a15cdbb8d0bd --- /dev/null +++ b/arch/mips/netlogic/xlp/dt.c @@ -0,0 +1,99 @@ +/* + * Copyright 2003-2013 Broadcom Corporation. + * All Rights Reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[]; + +void __init *xlp_dt_init(void *fdtp) +{ + if (!fdtp) { + switch (current_cpu_data.processor_id & 0xff00) { +#ifdef CONFIG_DT_XLP_SVP + case PRID_IMP_NETLOGIC_XLP3XX: + fdtp = __dtb_xlp_svp_begin; + break; +#endif +#ifdef CONFIG_DT_XLP_EVP + case PRID_IMP_NETLOGIC_XLP8XX: + fdtp = __dtb_xlp_evp_begin; + break; +#endif + default: + /* Pick a built-in if any, and hope for the best */ + fdtp = __dtb_start; + break; + } + } + initial_boot_params = fdtp; + return fdtp; +} + +void __init device_tree_init(void) +{ + unsigned long base, size; + + if (!initial_boot_params) + return; + + base = virt_to_phys((void *)initial_boot_params); + size = be32_to_cpu(initial_boot_params->totalsize); + + /* Before we do anything, lets reserve the dt blob */ + reserve_bootmem(base, size, BOOTMEM_DEFAULT); + + unflatten_device_tree(); + + /* free the space reserved for the dt blob */ + free_bootmem(base, size); +} + +static struct of_device_id __initdata xlp_ids[] = { + { .compatible = "simple-bus", }, + {}, +}; + +int __init xlp8xx_ds_publish_devices(void) +{ + if (!of_have_populated_dt()) + return 0; + return of_platform_bus_probe(NULL, xlp_ids, NULL); +} + +device_initcall(xlp8xx_ds_publish_devices); diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index eaa99d28cb8e..7b6694998cdc 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -33,19 +33,13 @@ */ #include -#include -#include -#include +#include #include #include #include #include -#include -#include -#include - #include #include @@ -57,7 +51,6 @@ uint64_t nlm_io_base; struct nlm_soc_info nlm_nodes[NLM_NR_NODES]; cpumask_t nlm_cpumask = CPU_MASK_CPU0; unsigned int nlm_threads_per_core; -extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], __dtb_start[]; static void nlm_linux_exit(void) { @@ -70,39 +63,13 @@ static void nlm_linux_exit(void) void __init plat_mem_setup(void) { - void *fdtp; - panic_timeout = 5; _machine_restart = (void (*)(char *))nlm_linux_exit; _machine_halt = nlm_linux_exit; pm_power_off = nlm_linux_exit; - /* - * If no FDT pointer is passed in, use the built-in FDT. - * device_tree_init() does not handle CKSEG0 pointers in - * 64-bit, so convert pointer. - */ - fdtp = (void *)(long)fw_arg0; - if (!fdtp) { - switch (current_cpu_data.processor_id & 0xff00) { -#ifdef CONFIG_DT_XLP_SVP - case PRID_IMP_NETLOGIC_XLP3XX: - fdtp = __dtb_xlp_svp_begin; - break; -#endif -#ifdef CONFIG_DT_XLP_EVP - case PRID_IMP_NETLOGIC_XLP8XX: - fdtp = __dtb_xlp_evp_begin; - break; -#endif - default: - /* Pick a built-in if any, and hope for the best */ - fdtp = __dtb_start; - break; - } - } - fdtp = phys_to_virt(__pa(fdtp)); - early_init_devtree(fdtp); + /* memory and bootargs from DT */ + early_init_devtree(initial_boot_params); } const char *get_system_type(void) @@ -134,6 +101,7 @@ void __init prom_init(void) nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); xlp_mmu_init(); nlm_node_init(0); + xlp_dt_init((void *)(long)fw_arg0); #ifdef CONFIG_SMP cpumask_setall(&nlm_cpumask); @@ -145,36 +113,3 @@ void __init prom_init(void) register_smp_ops(&nlm_smp_ops); #endif } - -void __init device_tree_init(void) -{ - unsigned long base, size; - - if (!initial_boot_params) - return; - - base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); - - /* Before we do anything, lets reserve the dt blob */ - reserve_bootmem(base, size, BOOTMEM_DEFAULT); - - unflatten_device_tree(); - - /* free the space reserved for the dt blob */ - free_bootmem(base, size); -} - -static struct of_device_id __initdata xlp_ids[] = { - { .compatible = "simple-bus", }, - {}, -}; - -int __init xlp8xx_ds_publish_devices(void) -{ - if (!of_have_populated_dt()) - return 0; - return of_platform_bus_probe(NULL, xlp_ids, NULL); -} - -device_initcall(xlp8xx_ds_publish_devices); -- GitLab From 9584c55a5cc0db82329dd1142ca570e2d64ea491 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:01 +0000 Subject: [PATCH 1135/2900] MIPS: Netlogic: Split reset code out of smpboot.S The reset and core initialization code should be available for uniprocessor as well. This changes is just to take out the code into a different file, without any change to the logic. The change for uniprocessor initialization code is in a later patch. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5423/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/common.h | 1 + arch/mips/netlogic/common/Makefile | 2 +- arch/mips/netlogic/common/reset.S | 249 ++++++++++++++++++++++++ arch/mips/netlogic/common/smpboot.S | 187 +----------------- arch/mips/netlogic/xlp/wakeup.c | 1 + 5 files changed, 253 insertions(+), 187 deletions(-) create mode 100644 arch/mips/netlogic/common/reset.S diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index 70351b95ef88..d4ede12b84c6 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -71,6 +71,7 @@ nlm_set_nmi_handler(void *handler) /* * Misc. */ +void nlm_init_boot_cpu(void); unsigned int nlm_get_cpu_frequency(void); void nlm_node_init(int node); extern struct plat_smp_ops nlm_smp_ops; diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile index b29549741e05..a396a39ec491 100644 --- a/arch/mips/netlogic/common/Makefile +++ b/arch/mips/netlogic/common/Makefile @@ -1,4 +1,4 @@ obj-y += irq.o time.o obj-y += nlm-dma.o -obj-$(CONFIG_SMP) += smp.o smpboot.o +obj-$(CONFIG_SMP) += smp.o smpboot.o reset.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S new file mode 100644 index 000000000000..98691d6b3bbe --- /dev/null +++ b/arch/mips/netlogic/common/reset.S @@ -0,0 +1,249 @@ +/* + * Copyright 2003-2013 Broadcom Corporation. + * All Rights Reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define CP0_EBASE $15 +#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ + XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ + SYS_CPU_NONCOHERENT_MODE * 4 + +#define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */ + +/* Enable XLP features and workarounds in the LSU */ +.macro xlp_config_lsu + li t0, LSU_DEFEATURE + mfcr t1, t0 + + lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */ + or t1, t1, t2 +#ifdef XLP_AX_WORKAROUND + li t2, ~0xe /* S1RCM */ + and t1, t1, t2 +#endif + mtcr t1, t0 + + li t0, ICU_DEFEATURE + mfcr t1, t0 + ori t1, 0x1000 /* Enable Icache partitioning */ + mtcr t1, t0 + + +#ifdef XLP_AX_WORKAROUND + li t0, SCHED_DEFEATURE + lui t1, 0x0100 /* Disable BRU accepting ALU ops */ + mtcr t1, t0 +#endif +.endm + +/* + * Low level flush for L1D cache on XLP, the normal cache ops does + * not do the complete and correct cache flush. + */ +.macro xlp_flush_l1_dcache + li t0, LSU_DEBUG_DATA0 + li t1, LSU_DEBUG_ADDR + li t2, 0 /* index */ + li t3, 0x1000 /* loop count */ +1: + sll v0, t2, 5 + mtcr zero, t0 + ori v1, v0, 0x3 /* way0 | write_enable | write_active */ + mtcr v1, t1 +2: + mfcr v1, t1 + andi v1, 0x1 /* wait for write_active == 0 */ + bnez v1, 2b + nop + mtcr zero, t0 + ori v1, v0, 0x7 /* way1 | write_enable | write_active */ + mtcr v1, t1 +3: + mfcr v1, t1 + andi v1, 0x1 /* wait for write_active == 0 */ + bnez v1, 3b + nop + addi t2, 1 + bne t3, t2, 1b + nop +.endm + +/* + * nlm_reset_entry will be copied to the reset entry point for + * XLR and XLP. The XLP cores start here when they are woken up. This + * is also the NMI entry point. + * + * We use scratch reg 6/7 to save k0/k1 and check for NMI first. + * + * The data corresponding to reset/NMI is stored at RESET_DATA_PHYS + * location, this will have the thread mask (used when core is woken up) + * and the current NMI handler in case we reached here for an NMI. + * + * When a core or thread is newly woken up, it marks itself ready and + * loops in a 'wait'. When the CPU really needs waking up, we send an NMI + * IPI to it, with the NMI handler set to prom_boot_secondary_cpus + */ + .set noreorder + .set noat + .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ + +FEXPORT(nlm_reset_entry) + dmtc0 k0, $22, 6 + dmtc0 k1, $22, 7 + mfc0 k0, CP0_STATUS + li k1, 0x80000 + and k1, k0, k1 + beqz k1, 1f /* go to real reset entry */ + nop + li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ + ld k0, BOOT_NMI_HANDLER(k1) + jr k0 + nop + +1: /* Entry point on core wakeup */ + mfc0 t0, CP0_EBASE, 1 + mfc0 t1, CP0_EBASE, 1 + srl t1, 5 + andi t1, 0x3 /* t1 <- node */ + li t2, 0x40000 + mul t3, t2, t1 /* t3 = node * 0x40000 */ + srl t0, t0, 2 + and t0, t0, 0x7 /* t0 <- core */ + li t1, 0x1 + sll t0, t1, t0 + nor t0, t0, zero /* t0 <- ~(1 << core) */ + li t2, SYS_CPU_COHERENT_BASE(0) + add t2, t2, t3 /* t2 <- SYS offset for node */ + lw t1, 0(t2) + and t1, t1, t0 + sw t1, 0(t2) + + /* read back to ensure complete */ + lw t1, 0(t2) + sync + + /* Configure LSU on Non-0 Cores. */ + xlp_config_lsu + /* FALL THROUGH */ + +/* + * Wake up sibling threads from the initial thread in + * a core. + */ +EXPORT(nlm_boot_siblings) + /* core L1D flush before enable threads */ + xlp_flush_l1_dcache + /* Enable hw threads by writing to MAP_THREADMODE of the core */ + li t0, CKSEG1ADDR(RESET_DATA_PHYS) + lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ + li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) + mfcr t2, t0 + or t2, t2, t1 + mtcr t2, t0 + + /* + * The new hardware thread starts at the next instruction + * For all the cases other than core 0 thread 0, we will + * jump to the secondary wait function. + */ + mfc0 v0, CP0_EBASE, 1 + andi v0, 0x3ff /* v0 <- node/core */ + + /* Init MMU in the first thread after changing THREAD_MODE + * register (Ax Errata?) + */ + andi v1, v0, 0x3 /* v1 <- thread id */ + bnez v1, 2f + nop + + li t0, MMU_SETUP + li t1, 0 + mtcr t1, t0 + _ehb + +2: beqz v0, 4f /* boot cpu (cpuid == 0)? */ + nop + + /* setup status reg */ + move t1, zero +#ifdef CONFIG_64BIT + ori t1, ST0_KX +#endif + mtc0 t1, CP0_STATUS + /* mark CPU ready */ + PTR_LA t1, nlm_cpu_ready + sll v1, v0, 2 + PTR_ADDU t1, v1 + li t2, 1 + sw t2, 0(t1) + /* Wait until NMI hits */ +3: wait + j 3b + nop + + /* + * For the boot CPU, we have to restore registers and + * return + */ +4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ + li t1, 0xfadebeef + dmtc0 t1, $4, 2 /* restore SP from UserLocal */ + PTR_SUBU sp, t0, PT_SIZE + RESTORE_ALL + jr ra + nop +EXPORT(nlm_reset_entry_end) + +LEAF(nlm_init_boot_cpu) +#ifdef CONFIG_CPU_XLP + xlp_config_lsu +#endif + jr ra + nop +END(nlm_init_boot_cpu) diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 026517488584..7c7e884f8912 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -50,197 +50,12 @@ #include #define CP0_EBASE $15 -#define SYS_CPU_COHERENT_BASE(node) CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \ - XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ - SYS_CPU_NONCOHERENT_MODE * 4 - -#define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */ - -/* Enable XLP features and workarounds in the LSU */ -.macro xlp_config_lsu - li t0, LSU_DEFEATURE - mfcr t1, t0 - - lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */ - or t1, t1, t2 -#ifdef XLP_AX_WORKAROUND - li t2, ~0xe /* S1RCM */ - and t1, t1, t2 -#endif - mtcr t1, t0 - - li t0, ICU_DEFEATURE - mfcr t1, t0 - ori t1, 0x1000 /* Enable Icache partitioning */ - mtcr t1, t0 - - -#ifdef XLP_AX_WORKAROUND - li t0, SCHED_DEFEATURE - lui t1, 0x0100 /* Disable BRU accepting ALU ops */ - mtcr t1, t0 -#endif -.endm - -/* - * This is the code that will be copied to the reset entry point for - * XLR and XLP. The XLP cores start here when they are woken up. This - * is also the NMI entry point. - */ -.macro xlp_flush_l1_dcache - li t0, LSU_DEBUG_DATA0 - li t1, LSU_DEBUG_ADDR - li t2, 0 /* index */ - li t3, 0x1000 /* loop count */ -1: - sll v0, t2, 5 - mtcr zero, t0 - ori v1, v0, 0x3 /* way0 | write_enable | write_active */ - mtcr v1, t1 -2: - mfcr v1, t1 - andi v1, 0x1 /* wait for write_active == 0 */ - bnez v1, 2b - nop - mtcr zero, t0 - ori v1, v0, 0x7 /* way1 | write_enable | write_active */ - mtcr v1, t1 -3: - mfcr v1, t1 - andi v1, 0x1 /* wait for write_active == 0 */ - bnez v1, 3b - nop - addi t2, 1 - bne t3, t2, 1b - nop -.endm - -/* - * The cores can come start when they are woken up. This is also the NMI - * entry, so check that first. - * - * The data corresponding to reset/NMI is stored at RESET_DATA_PHYS - * location, this will have the thread mask (used when core is woken up) - * and the current NMI handler in case we reached here for an NMI. - * - * When a core or thread is newly woken up, it loops in a 'wait'. When - * the CPU really needs waking up, we send an NMI to it, with the NMI - * handler set to prom_boot_secondary_cpus - */ .set noreorder .set noat - .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ - -FEXPORT(nlm_reset_entry) - dmtc0 k0, $22, 6 - dmtc0 k1, $22, 7 - mfc0 k0, CP0_STATUS - li k1, 0x80000 - and k1, k0, k1 - beqz k1, 1f /* go to real reset entry */ - nop - li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ - ld k0, BOOT_NMI_HANDLER(k1) - jr k0 - nop - -1: /* Entry point on core wakeup */ - mfc0 t0, CP0_EBASE, 1 - mfc0 t1, CP0_EBASE, 1 - srl t1, 5 - andi t1, 0x3 /* t1 <- node */ - li t2, 0x40000 - mul t3, t2, t1 /* t3 = node * 0x40000 */ - srl t0, t0, 2 - and t0, t0, 0x7 /* t0 <- core */ - li t1, 0x1 - sll t0, t1, t0 - nor t0, t0, zero /* t0 <- ~(1 << core) */ - li t2, SYS_CPU_COHERENT_BASE(0) - add t2, t2, t3 /* t2 <- SYS offset for node */ - lw t1, 0(t2) - and t1, t1, t0 - sw t1, 0(t2) - - /* read back to ensure complete */ - lw t1, 0(t2) - sync - - /* Configure LSU on Non-0 Cores. */ - xlp_config_lsu - /* FALL THROUGH */ - -/* - * Wake up sibling threads from the initial thread in - * a core. - */ -EXPORT(nlm_boot_siblings) - /* core L1D flush before enable threads */ - xlp_flush_l1_dcache - /* Enable hw threads by writing to MAP_THREADMODE of the core */ - li t0, CKSEG1ADDR(RESET_DATA_PHYS) - lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ - li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) - mfcr t2, t0 - or t2, t2, t1 - mtcr t2, t0 - - /* - * The new hardware thread starts at the next instruction - * For all the cases other than core 0 thread 0, we will - * jump to the secondary wait function. - */ - mfc0 v0, CP0_EBASE, 1 - andi v0, 0x3ff /* v0 <- node/core */ - - /* Init MMU in the first thread after changing THREAD_MODE - * register (Ax Errata?) - */ - andi v1, v0, 0x3 /* v1 <- thread id */ - bnez v1, 2f - nop - - li t0, MMU_SETUP - li t1, 0 - mtcr t1, t0 - _ehb - -2: beqz v0, 4f /* boot cpu (cpuid == 0)? */ - nop - - /* setup status reg */ - move t1, zero -#ifdef CONFIG_64BIT - ori t1, ST0_KX -#endif - mtc0 t1, CP0_STATUS - /* mark CPU ready */ - PTR_LA t1, nlm_cpu_ready - sll v1, v0, 2 - PTR_ADDU t1, v1 - li t2, 1 - sw t2, 0(t1) - /* Wait until NMI hits */ -3: wait - j 3b - nop - - /* - * For the boot CPU, we have to restore registers and - * return - */ -4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ - li t1, 0xfadebeef - dmtc0 t1, $4, 2 /* restore SP from UserLocal */ - PTR_SUBU sp, t0, PT_SIZE - RESTORE_ALL - jr ra - nop -EXPORT(nlm_reset_entry_end) + .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ - xlp_config_lsu dmtc0 sp, $4, 2 /* SP saved in UserLocal */ SAVE_ALL sync diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index abb3e08cc052..1a7d529fcec0 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -137,6 +137,7 @@ void xlp_wakeup_secondary_cpus() * In case of u-boot, the secondaries are in reset * first wakeup core 0 threads */ + nlm_init_boot_cpu(); xlp_boot_core0_siblings(); /* now get other cores out of reset */ -- GitLab From 571886b2a52395f030d439c6259663a033e11e6a Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:02 +0000 Subject: [PATCH 1136/2900] MIPS: Netlogic: Initialization when !CONFIG_SMP The core initialization and reset vector setup needs to be done even when booting uniprocessor. Move this code from smp.c to setup.c Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5428/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/Makefile | 3 ++- arch/mips/netlogic/common/smp.c | 6 ------ arch/mips/netlogic/xlp/setup.c | 8 ++++++++ arch/mips/netlogic/xlp/wakeup.c | 1 - arch/mips/netlogic/xlr/setup.c | 6 ++++++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile index a396a39ec491..362739d62b1d 100644 --- a/arch/mips/netlogic/common/Makefile +++ b/arch/mips/netlogic/common/Makefile @@ -1,4 +1,5 @@ obj-y += irq.o time.o obj-y += nlm-dma.o -obj-$(CONFIG_SMP) += smp.o smpboot.o reset.o +obj-y += reset.o +obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index ffba52489bef..da3d3bc02c20 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -254,15 +254,9 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask) int __cpuinit nlm_wakeup_secondary_cpus(void) { - unsigned long reset_vec; char *reset_data; int threadmode; - /* Update reset entry point with CPU init code */ - reset_vec = CKSEG1ADDR(RESET_VEC_PHYS); - memcpy((void *)reset_vec, (void *)nlm_reset_entry, - (nlm_reset_entry_end - nlm_reset_entry)); - /* verify the mask and setup core config variables */ threadmode = nlm_parse_cpumask(&nlm_cpumask); diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 7b6694998cdc..5bdd354fef48 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -98,11 +98,19 @@ void nlm_percpu_init(int hwcpuid) void __init prom_init(void) { + void *reset_vec; + nlm_io_base = CKSEG1ADDR(XLP_DEFAULT_IO_BASE); + nlm_init_boot_cpu(); xlp_mmu_init(); nlm_node_init(0); xlp_dt_init((void *)(long)fw_arg0); + /* Update reset entry point with CPU init code */ + reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS); + memcpy(reset_vec, (void *)nlm_reset_entry, + (nlm_reset_entry_end - nlm_reset_entry)); + #ifdef CONFIG_SMP cpumask_setall(&nlm_cpumask); nlm_wakeup_secondary_cpus(); diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 1a7d529fcec0..abb3e08cc052 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -137,7 +137,6 @@ void xlp_wakeup_secondary_cpus() * In case of u-boot, the secondaries are in reset * first wakeup core 0 threads */ - nlm_init_boot_cpu(); xlp_boot_core0_siblings(); /* now get other cores out of reset */ diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index 89c8c1066632..7e27f8591867 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -196,6 +196,7 @@ void __init prom_init(void) { int *argv, *envp; /* passed as 32 bit ptrs */ struct psb_info *prom_infop; + void *reset_vec; #ifdef CONFIG_SMP int i; #endif @@ -208,6 +209,11 @@ void __init prom_init(void) nlm_prom_info = *prom_infop; nlm_init_node(); + /* Update reset entry point with CPU init code */ + reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS); + memcpy(reset_vec, (void *)nlm_reset_entry, + (nlm_reset_entry_end - nlm_reset_entry)); + nlm_early_serial_setup(); build_arcs_cmdline(argv); prom_add_memory(); -- GitLab From 53c832197f3adc5a360336f75fe34a95fe2d796b Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:03 +0000 Subject: [PATCH 1137/2900] MIPS: Netlogic: Add nlm_get_boot_data() helper This moves the calculation and casting needed to access the CPU initialization data to a function nlm_get_boot_data() Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5426/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/common.h | 11 ++++++++--- arch/mips/netlogic/common/smp.c | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index d4ede12b84c6..1b54adbd1583 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -59,13 +59,18 @@ int nlm_wakeup_secondary_cpus(void); void nlm_rmiboot_preboot(void); void nlm_percpu_init(int hwcpuid); +static inline void * +nlm_get_boot_data(int offset) +{ + return (void *)(CKSEG1ADDR(RESET_DATA_PHYS) + offset); +} + static inline void nlm_set_nmi_handler(void *handler) { - char *reset_data; + void *nmih = nlm_get_boot_data(BOOT_NMI_HANDLER); - reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS); - *(int64_t *)(reset_data + BOOT_NMI_HANDLER) = (long)handler; + *(int64_t *)nmih = (long)handler; } /* diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index da3d3bc02c20..1f66eef3aea7 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -254,15 +254,15 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask) int __cpuinit nlm_wakeup_secondary_cpus(void) { - char *reset_data; + u32 *reset_data; int threadmode; /* verify the mask and setup core config variables */ threadmode = nlm_parse_cpumask(&nlm_cpumask); /* Setup CPU init parameters */ - reset_data = (char *)CKSEG1ADDR(RESET_DATA_PHYS); - *(int *)(reset_data + BOOT_THREAD_MODE) = threadmode; + reset_data = nlm_get_boot_data(BOOT_THREAD_MODE); + *reset_data = threadmode; #ifdef CONFIG_CPU_XLP xlp_wakeup_secondary_cpus(); -- GitLab From 919f9abb3723f088290c62648b12fbfc7600d923 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:04 +0000 Subject: [PATCH 1138/2900] MIPS: Netlogic: move cpu_ready array to boot area Move the nlm_cpu_ready[] array used by the cpu wakeup code to the boot area, along with rest of the boot parameter code. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5425/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/common.h | 6 ++++++ arch/mips/netlogic/common/reset.S | 6 ++++-- arch/mips/netlogic/common/smp.c | 6 +++--- arch/mips/netlogic/common/smpboot.S | 5 +++-- arch/mips/netlogic/xlp/setup.c | 1 + arch/mips/netlogic/xlp/wakeup.c | 3 ++- arch/mips/netlogic/xlr/setup.c | 1 + arch/mips/netlogic/xlr/wakeup.c | 3 ++- 8 files changed, 22 insertions(+), 9 deletions(-) diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index 1b54adbd1583..bb68c3398c80 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -39,11 +39,17 @@ * Common SMP definitions */ #define RESET_VEC_PHYS 0x1fc00000 +#define RESET_VEC_SIZE 8192 /* 8KB reset code and data */ #define RESET_DATA_PHYS (RESET_VEC_PHYS + (1<<10)) + +/* Offsets of parameters in the RESET_DATA_PHYS area */ #define BOOT_THREAD_MODE 0 #define BOOT_NMI_LOCK 4 #define BOOT_NMI_HANDLER 8 +/* CPU ready flags for each CPU */ +#define BOOT_CPU_READY 2048 + #ifndef __ASSEMBLY__ #include #include diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index 98691d6b3bbe..b11691c629d0 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -216,8 +216,10 @@ EXPORT(nlm_boot_siblings) ori t1, ST0_KX #endif mtc0 t1, CP0_STATUS - /* mark CPU ready */ - PTR_LA t1, nlm_cpu_ready + + /* mark CPU ready, careful here, previous mtcr trashed registers */ + li t3, CKSEG1ADDR(RESET_DATA_PHYS) + ADDIU t1, t3, BOOT_CPU_READY sll v1, v0, 2 PTR_ADDU t1, v1 li t2, 1 diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 1f66eef3aea7..885d293b61da 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -145,7 +145,6 @@ void nlm_cpus_done(void) * Boot all other cpus in the system, initialize them, and bring them into * the boot function */ -int nlm_cpu_ready[NR_CPUS]; unsigned long nlm_next_gp; unsigned long nlm_next_sp; static cpumask_t phys_cpu_present_mask; @@ -168,6 +167,7 @@ void __init nlm_smp_setup(void) { unsigned int boot_cpu; int num_cpus, i, ncore; + volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); char buf[64]; boot_cpu = hard_smp_processor_id(); @@ -181,10 +181,10 @@ void __init nlm_smp_setup(void) num_cpus = 1; for (i = 0; i < NR_CPUS; i++) { /* - * nlm_cpu_ready array is not set for the boot_cpu, + * cpu_ready array is not set for the boot_cpu, * it is only set for ASPs (see smpboot.S) */ - if (nlm_cpu_ready[i]) { + if (cpu_ready[i]) { cpumask_set_cpu(i, &phys_cpu_present_mask); __cpu_number_map[i] = num_cpus; __cpu_logical_map[num_cpus] = i; diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 7c7e884f8912..6029d1b37f88 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -109,8 +109,9 @@ NESTED(nlm_rmiboot_preboot, 16, sp) andi t2, t0, 0x3 /* thread num */ sll t0, 2 /* offset in cpu array */ - PTR_LA t1, nlm_cpu_ready /* mark CPU ready */ - PTR_ADDU t1, t0 + li t3, CKSEG1ADDR(RESET_DATA_PHYS) + ADDIU t1, t3, BOOT_CPU_READY + ADDU t1, t0 li t3, 1 sw t3, 0(t1) diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 5bdd354fef48..8f6992432f34 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -108,6 +108,7 @@ void __init prom_init(void) /* Update reset entry point with CPU init code */ reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS); + memset(reset_vec, 0, RESET_VEC_SIZE); memcpy(reset_vec, (void *)nlm_reset_entry, (nlm_reset_entry_end - nlm_reset_entry)); diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index abb3e08cc052..feb573670f90 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -82,6 +82,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) struct nlm_soc_info *nodep; uint64_t syspcibase; uint32_t syscoremask; + volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); int core, n, cpu, count, val; for (n = 0; n < NLM_NR_NODES; n++) { @@ -125,7 +126,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) /* spin until the first hw thread sets its ready */ count = 0x20000000; do { - val = *(volatile int *)&nlm_cpu_ready[cpu]; + val = cpu_ready[cpu]; } while (val == 0 && --count > 0); } } diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index 7e27f8591867..214d123b79fa 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -211,6 +211,7 @@ void __init prom_init(void) /* Update reset entry point with CPU init code */ reset_vec = (void *)CKSEG1ADDR(RESET_VEC_PHYS); + memset(reset_vec, 0, RESET_VEC_SIZE); memcpy(reset_vec, (void *)nlm_reset_entry, (nlm_reset_entry_end - nlm_reset_entry)); diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c index 3ebf7411d67b..c06e4c9f0478 100644 --- a/arch/mips/netlogic/xlr/wakeup.c +++ b/arch/mips/netlogic/xlr/wakeup.c @@ -53,6 +53,7 @@ int __cpuinit xlr_wakeup_secondary_cpus(void) { struct nlm_soc_info *nodep; unsigned int i, j, boot_cpu; + volatile u32 *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); /* * In case of RMI boot, hit with NMI to get the cores @@ -71,7 +72,7 @@ int __cpuinit xlr_wakeup_secondary_cpus(void) nodep->coremask = 1; for (i = 1; i < NLM_CORES_PER_NODE; i++) { for (j = 1000000; j > 0; j--) { - if (nlm_cpu_ready[i * NLM_THREADS_PER_CORE]) + if (cpu_ready[i * NLM_THREADS_PER_CORE]) break; udelay(10); } -- GitLab From fd5f527cc58f7112f0d2c3cf2c29ae3ea5417de5 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:05 +0000 Subject: [PATCH 1139/2900] MIPS: Netlogic: use branch instead of jump Fix an issue in the reset code. Since this code is copied to the reset vector, using 'j' for looping is not correct. Use relative branch 'b'. Update the usage of 'j' in smpboot.S to be consistent although it is not a bug there. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5427/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/reset.S | 2 +- arch/mips/netlogic/common/smpboot.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index b11691c629d0..0ebd50a1d618 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -226,7 +226,7 @@ EXPORT(nlm_boot_siblings) sw t2, 0(t1) /* Wait until NMI hits */ 3: wait - j 3b + b 3b nop /* diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 6029d1b37f88..528c46c5a170 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -137,7 +137,7 @@ NESTED(nlm_rmiboot_preboot, 16, sp) mtcr t1, t0 /* update core control */ 1: wait - j 1b + b 1b nop END(nlm_rmiboot_preboot) __FINIT -- GitLab From 9f1f1e7b8b76d8503673a3777b3ee743d8c50e13 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:06 +0000 Subject: [PATCH 1140/2900] MIPS: Netlogic: Fix sign extension in PIC write This does not cause a problem yet, but we do not want to write 1 to reserved bits. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5424/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/netlogic/xlp-hal/pic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index a981f4681a15..4b5108dfaa16 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -315,7 +315,7 @@ nlm_pic_send_ipi(uint64_t base, int hwt, int irq, int nmi) { uint64_t ipi; - ipi = (nmi << 31) | (irq << 20); + ipi = ((uint64_t)nmi << 31) | (irq << 20); ipi |= ((hwt >> 4) << 16) | (1 << (hwt & 0xf)); /* cpuset and mask */ nlm_write_pic_reg(base, PIC_IPI_CTL, ipi); } -- GitLab From 4033d38ceb9d84ed66b925c1740c1a88f8a4a8f9 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:07 +0000 Subject: [PATCH 1141/2900] MIPS: Netlogic: wait for all hardware threads Earlier we just waited for the first thread of the CPU to come online before proceeding to wake up others. Update it to wait for all the CPUs in the core. This will be useful when the boot-up is slow, like while debugging or when running in a simulator. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5429/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/wakeup.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index feb573670f90..0cce37cbffef 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -77,13 +77,28 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core) return count != 0; } +static int wait_for_cpus(int cpu, int bootcpu) +{ + volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); + int i, count, notready; + + count = 0x20000000; + do { + notready = nlm_threads_per_core; + for (i = 0; i < nlm_threads_per_core; i++) + if (cpu_ready[cpu + i] || cpu == bootcpu) + --notready; + } while (notready != 0 && --count > 0); + + return count != 0; +} + static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) { struct nlm_soc_info *nodep; uint64_t syspcibase; uint32_t syscoremask; - volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); - int core, n, cpu, count, val; + int core, n, cpu; for (n = 0; n < NLM_NR_NODES; n++) { syspcibase = nlm_get_sys_pcibase(n); @@ -123,11 +138,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) /* core is up */ nodep->coremask |= 1u << core; - /* spin until the first hw thread sets its ready */ - count = 0x20000000; - do { - val = cpu_ready[cpu]; - } while (val == 0 && --count > 0); + /* spin until the hw threads sets their ready */ + wait_for_cpus(cpu, 0); } } } @@ -139,6 +151,7 @@ void xlp_wakeup_secondary_cpus() * first wakeup core 0 threads */ xlp_boot_core0_siblings(); + wait_for_cpus(0, 0); /* now get other cores out of reset */ xlp_enable_secondary_cores(&nlm_cpumask); -- GitLab From 722138340b9f08d081255ba50928831a972c2e6f Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:08 +0000 Subject: [PATCH 1142/2900] MIPS: Netlogic: Fixup memory regions for prefetch Fix a cache error found in stress test, caused by the prefetch instruction going beyond valid memory when acessing the last page of a region. Add the pref_backup logic similar to XLR in XLP too. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5431/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/setup.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 8f6992432f34..7b638f7be491 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -61,6 +61,18 @@ static void nlm_linux_exit(void) cpu_wait(); } +static void nlm_fixup_mem(void) +{ + const int pref_backup = 512; + int i; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + continue; + boot_mem_map.map[i].size -= pref_backup; + } +} + void __init plat_mem_setup(void) { panic_timeout = 5; @@ -70,6 +82,7 @@ void __init plat_mem_setup(void) /* memory and bootargs from DT */ early_init_devtree(initial_boot_params); + nlm_fixup_mem(); } const char *get_system_type(void) -- GitLab From 6099115e7e5e2c49d3822e093ca7df7015ca57a9 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:09 +0000 Subject: [PATCH 1143/2900] MIPS: Netlogic: Remove workarounds for early SoCs The XLPs in production do not need these workarounds. Remove the code and the associated ifdef. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5430/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/reset.S | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index 0ebd50a1d618..adb18288a6c0 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -54,8 +54,6 @@ XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ SYS_CPU_NONCOHERENT_MODE * 4 -#define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */ - /* Enable XLP features and workarounds in the LSU */ .macro xlp_config_lsu li t0, LSU_DEFEATURE @@ -63,10 +61,6 @@ lui t2, 0xc080 /* SUE, Enable Unaligned Access, L2HPE */ or t1, t1, t2 -#ifdef XLP_AX_WORKAROUND - li t2, ~0xe /* S1RCM */ - and t1, t1, t2 -#endif mtcr t1, t0 li t0, ICU_DEFEATURE @@ -74,12 +68,9 @@ ori t1, 0x1000 /* Enable Icache partitioning */ mtcr t1, t0 - -#ifdef XLP_AX_WORKAROUND li t0, SCHED_DEFEATURE lui t1, 0x0100 /* Disable BRU accepting ALU ops */ mtcr t1, t0 -#endif .endm /* @@ -195,19 +186,7 @@ EXPORT(nlm_boot_siblings) mfc0 v0, CP0_EBASE, 1 andi v0, 0x3ff /* v0 <- node/core */ - /* Init MMU in the first thread after changing THREAD_MODE - * register (Ax Errata?) - */ - andi v1, v0, 0x3 /* v1 <- thread id */ - bnez v1, 2f - nop - - li t0, MMU_SETUP - li t1, 0 - mtcr t1, t0 - _ehb - -2: beqz v0, 4f /* boot cpu (cpuid == 0)? */ + beqz v0, 4f /* boot cpu (cpuid == 0)? */ nop /* setup status reg */ -- GitLab From 8ecd08378c132536c7d47af225e09bd6f3a16779 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Mon, 10 Jun 2013 06:41:10 +0000 Subject: [PATCH 1144/2900] MIPS: Netlogic: Fix plat_irq_dispatch Fix an issue in plat_irq_dispatch due to which it can call do_IRQ with a PIC irq that is not mapped. When a per-cpu interrupt and a PIC interrupt are both active, the check 'eirr & PERCPU_IRQ_MASK' will be true, but the interrupt in 'i' will be the number of the PIC interrupt. In this case, we will call do_IRQ on the PIC interrupt without mapping it with nlm_irq_to_xirq(). Fix this by using __ffs64 instead of __ilog2_u64 and using the interrupt number instead of mask to identify per-cpu interrupts. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5432/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/irq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 9f84c60bf535..73facb2b33bb 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -253,13 +253,12 @@ asmlinkage void plat_irq_dispatch(void) node = nlm_nodeid(); eirr = read_c0_eirr_and_eimr(); - - i = __ilog2_u64(eirr); - if (i == -1) + if (eirr == 0) return; + i = __ffs64(eirr); /* per-CPU IRQs don't need translation */ - if (eirr & PERCPU_IRQ_MASK) { + if (i < PIC_IRQ_BASE) { do_IRQ(i); return; } -- GitLab From 7777b9395b77664cb736b941f95fb8f656edd111 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 11 Jun 2013 14:41:35 +0000 Subject: [PATCH 1145/2900] MIPS: Allow platform specific scratch registers XLR/XLP COP0 scratch is register 22, sel 0-7. Add a function c0_kscratch() which returns the scratch register for the platform, and use the return value while generating TLB handlers. Setup kscratch_mask to 0xf for XLR/XLP since the config4 register does not exist. This allows the kernel to allocate scratch registers 0-3 if needed. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5445/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/cpu-probe.c | 1 + arch/mips/mm/tlbex.c | 41 +++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c6568bf4b1b0..265c97da6619 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -959,6 +959,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) set_isa(c, MIPS_CPU_ISA_M64R1); c->tlbsize = ((read_c0_config1() >> 25) & 0x3f) + 1; } + c->kscratch_mask = 0xf; } #ifdef CONFIG_64BIT diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index afeef93f81a7..c052df8ae7d7 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -305,6 +305,17 @@ static int check_for_high_segbits __cpuinitdata; static unsigned int kscratch_used_mask __cpuinitdata; +static inline int __maybe_unused c0_kscratch(void) +{ + switch (current_cpu_type()) { + case CPU_XLP: + case CPU_XLR: + return 22; + default: + return 31; + } +} + static int __cpuinit allocate_kscratch(void) { int r; @@ -336,7 +347,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) if (scratch_reg > 0) { /* Save in CPU local C0_KScratch? */ - UASM_i_MTC0(p, 1, 31, scratch_reg); + UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg); r.r1 = K0; r.r2 = K1; r.r3 = 1; @@ -385,7 +396,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) static void __cpuinit build_restore_work_registers(u32 **p) { if (scratch_reg > 0) { - UASM_i_MFC0(p, 1, 31, scratch_reg); + UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); return; } /* K0 already points to save area, restore $1 and $2 */ @@ -674,7 +685,7 @@ static __cpuinit void build_restore_pagemask(u32 **p, uasm_il_b(p, r, lid); } if (scratch_reg > 0) - UASM_i_MFC0(p, 1, 31, scratch_reg); + UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); else UASM_i_LW(p, 1, scratchpad_offset(0), 0); } else { @@ -817,7 +828,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, #ifdef CONFIG_MIPS_PGD_C0_CONTEXT if (pgd_reg != -1) { /* pgd is in pgd_reg */ - UASM_i_MFC0(p, ptr, 31, pgd_reg); + UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); } else { /* * &pgd << 11 stored in CONTEXT [23..63]. @@ -930,7 +941,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, if (mode == refill_scratch) { if (scratch_reg > 0) - UASM_i_MFC0(p, 1, 31, scratch_reg); + UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); else UASM_i_LW(p, 1, scratchpad_offset(0), 0); } else { @@ -1096,7 +1107,7 @@ struct mips_huge_tlb_info { static struct mips_huge_tlb_info __cpuinit build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, - unsigned int ptr, int c0_scratch) + unsigned int ptr, int c0_scratch_reg) { struct mips_huge_tlb_info rv; unsigned int even, odd; @@ -1110,12 +1121,12 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, UASM_i_MFC0(p, tmp, C0_BADVADDR); if (pgd_reg != -1) - UASM_i_MFC0(p, ptr, 31, pgd_reg); + UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); else UASM_i_MFC0(p, ptr, C0_CONTEXT); - if (c0_scratch >= 0) - UASM_i_MTC0(p, scratch, 31, c0_scratch); + if (c0_scratch_reg >= 0) + UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); else UASM_i_SW(p, scratch, scratchpad_offset(0), 0); @@ -1130,14 +1141,14 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, } } else { if (pgd_reg != -1) - UASM_i_MFC0(p, ptr, 31, pgd_reg); + UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg); else UASM_i_MFC0(p, ptr, C0_CONTEXT); UASM_i_MFC0(p, tmp, C0_BADVADDR); - if (c0_scratch >= 0) - UASM_i_MTC0(p, scratch, 31, c0_scratch); + if (c0_scratch_reg >= 0) + UASM_i_MTC0(p, scratch, c0_kscratch(), c0_scratch_reg); else UASM_i_SW(p, scratch, scratchpad_offset(0), 0); @@ -1242,8 +1253,8 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, } UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ - if (c0_scratch >= 0) { - UASM_i_MFC0(p, scratch, 31, c0_scratch); + if (c0_scratch_reg >= 0) { + UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg); build_tlb_write_entry(p, l, r, tlb_random); uasm_l_leave(l, *p); rv.restore_scratch = 1; @@ -1490,7 +1501,7 @@ static void __cpuinit build_r4000_setup_pgd(void) } else { /* PGD in c0_KScratch */ uasm_i_jr(&p, 31); - UASM_i_MTC0(&p, a0, 31, pgd_reg); + UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); } if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) panic("tlbmiss_handler_setup_pgd_array space exceeded"); -- GitLab From 0e6ecc1a9aa7cbf991d9711a12cae2b4853ef718 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 11 Jun 2013 14:41:36 +0000 Subject: [PATCH 1146/2900] MIPS: Fixup check for invalid scratch register The invalid value for scratch register is -1, so update the checks of the form (scratch_reg > 0) to be (scratch_reg >= 0). This will fix the case in Netlogic XLP where the scratch_reg can be 0. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5444/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index c052df8ae7d7..9b988c050fdd 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -345,7 +345,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) int smp_processor_id_sel; int smp_processor_id_shift; - if (scratch_reg > 0) { + if (scratch_reg >= 0) { /* Save in CPU local C0_KScratch? */ UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg); r.r1 = K0; @@ -395,7 +395,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) static void __cpuinit build_restore_work_registers(u32 **p) { - if (scratch_reg > 0) { + if (scratch_reg >= 0) { UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); return; } @@ -684,7 +684,7 @@ static __cpuinit void build_restore_pagemask(u32 **p, uasm_i_mtc0(p, 0, C0_PAGEMASK); uasm_il_b(p, r, lid); } - if (scratch_reg > 0) + if (scratch_reg >= 0) UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); else UASM_i_LW(p, 1, scratchpad_offset(0), 0); @@ -940,7 +940,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, uasm_i_jr(p, ptr); if (mode == refill_scratch) { - if (scratch_reg > 0) + if (scratch_reg >= 0) UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); else UASM_i_LW(p, 1, scratchpad_offset(0), 0); @@ -1297,7 +1297,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) memset(relocs, 0, sizeof(relocs)); memset(final_handler, 0, sizeof(final_handler)); - if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) { + if ((scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, scratch_reg); vmalloc_mode = refill_scratch; -- GitLab From 178c059e7640aa8e50213400c6f3dde00189d979 Mon Sep 17 00:00:00 2001 From: "Cho, Yu-Chen" Date: Tue, 4 Jun 2013 21:40:26 +0800 Subject: [PATCH 1147/2900] Bluetooth: Add support for Mediatek Bluetooth device [0e8d:763f] This patch adds support for Mediatek Bluetooth device T: Bus=02 Lev=01 Prnt=01 Port=03 Cnt=01 Dev#= 2 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0e8d ProdID=763f Rev= 1.00 S: Manufacturer=MediaTek S: Product=BT S: SerialNumber=1.0 C:* #Ifs= 2 Cfg#= 1 Atr=a0 MxPwr=450mA A: FirstIf#= 0 IfCount= 2 Cls=ff(vend.) Sub=ff Prot=ff I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=125us E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=125us E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms I: If#= 1 Alt= 6 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms Signed-off-by: Cho, Yu-Chen Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7a7e5f8ecadc..81f12757a842 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -57,6 +57,9 @@ static struct usb_device_id btusb_table[] = { /* Apple-specific (Broadcom) devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* MediaTek MT76x0E */ + { USB_DEVICE(0x0e8d, 0x763f) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, -- GitLab From 6ea81c415574acb88faca905e1d7316057e90a5b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 5 Jun 2013 10:16:55 +0800 Subject: [PATCH 1148/2900] Bluetooth: btmrvl: fix error return code in btmrvl_sdio_card_to_host() Fix to return -ENOMEM in the skb alloc error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Gustavo Padovan Signed-off-by: John W. Linville --- drivers/bluetooth/btmrvl_sdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 13693b7a0d5c..75c262694632 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -554,6 +554,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); if (skb == NULL) { BT_ERR("No free skb"); + ret = -ENOMEM; goto exit; } -- GitLab From 9ad86ed39db83d0c3111c10850e58691ef57e81e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 12 Jun 2013 21:35:39 +0200 Subject: [PATCH 1149/2900] carl9170: add support for the new rate control API With the new rate control API, the driver can now apply the tx rate to outgoing frames just before they are uploaded to the device. This is important because the rate control can now react to fading or improving links a bit sooner. Also, the driver no longer needs to sort the outgoing frames for sample attempts (which affected the size of A-MPDUs and the throughput of the link). For aggregated data frames, the driver (and rate control) needs only to calculate and apply a single set of tx rates to every subframe of the whole aggregate. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/carl9170.h | 3 + drivers/net/wireless/ath/carl9170/main.c | 3 + drivers/net/wireless/ath/carl9170/tx.c | 182 +++++++++++-------- 3 files changed, 110 insertions(+), 78 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 9dce106cd6d4..8596aba34f96 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -133,6 +133,9 @@ struct carl9170_sta_tid { /* Preaggregation reorder queue */ struct sk_buff_head queue; + + struct ieee80211_sta *sta; + struct ieee80211_vif *vif; }; #define CARL9170_QUEUE_TIMEOUT 256 diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index e9010a481dfd..4a33c6e39ca2 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1448,6 +1448,8 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, tid_info->state = CARL9170_TID_STATE_PROGRESS; tid_info->tid = tid; tid_info->max = sta_info->ampdu_max_len; + tid_info->sta = sta; + tid_info->vif = vif; INIT_LIST_HEAD(&tid_info->list); INIT_LIST_HEAD(&tid_info->tmp_list); @@ -1857,6 +1859,7 @@ void *carl9170_alloc(size_t priv_size) IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_SUPPORTS_RC_TABLE | IEEE80211_HW_SIGNAL_DBM; if (!modparam_noht) { diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index c61cafa2665b..e3f696ee4d23 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -625,7 +625,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar) msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT))) goto unlock; - sta = __carl9170_get_tx_sta(ar, skb); + sta = iter->sta; if (WARN_ON(!sta)) goto unlock; @@ -866,6 +866,93 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar, return false; } +static void carl9170_tx_get_rates(struct ar9170 *ar, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info; + + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES > IEEE80211_TX_RATE_TABLE_SIZE); + + info = IEEE80211_SKB_CB(skb); + + ieee80211_get_tx_rates(vif, sta, skb, + info->control.rates, + IEEE80211_TX_MAX_RATES); +} + +static void carl9170_tx_apply_rateset(struct ar9170 *ar, + struct ieee80211_tx_info *sinfo, + struct sk_buff *skb) +{ + struct ieee80211_tx_rate *txrate; + struct ieee80211_tx_info *info; + struct _carl9170_tx_superframe *txc = (void *) skb->data; + int i; + bool ampdu; + bool no_ack; + + info = IEEE80211_SKB_CB(skb); + ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); + no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); + + /* Set the rate control probe flag for all (sub-) frames. + * This is because the TX_STATS_AMPDU flag is only set on + * the last frame, so it has to be inherited. + */ + info->flags |= (sinfo->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); + + /* NOTE: For the first rate, the ERP & AMPDU flags are directly + * taken from mac_control. For all fallback rate, the firmware + * updates the mac_control flags from the rate info field. + */ + for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { + __le32 phy_set; + + txrate = &sinfo->control.rates[i]; + if (txrate->idx < 0) + break; + + phy_set = carl9170_tx_physet(ar, info, txrate); + if (i == 0) { + __le16 mac_tmp = cpu_to_le16(0); + + /* first rate - part of the hw's frame header */ + txc->f.phy_control = phy_set; + + if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); + + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + else if (carl9170_tx_cts_check(ar, txrate)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + + txc->f.mac_control |= mac_tmp; + } else { + /* fallback rates are stored in the firmware's + * retry rate set array. + */ + txc->s.rr[i - 1] = phy_set; + } + + SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], + txrate->count); + + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << + CARL9170_TX_SUPER_RI_ERP_PROT_S); + else if (carl9170_tx_cts_check(ar, txrate)) + txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << + CARL9170_TX_SUPER_RI_ERP_PROT_S); + + if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) + txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; + } +} + static int carl9170_tx_prepare(struct ar9170 *ar, struct ieee80211_sta *sta, struct sk_buff *skb) @@ -874,13 +961,10 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct _carl9170_tx_superframe *txc; struct carl9170_vif_info *cvif; struct ieee80211_tx_info *info; - struct ieee80211_tx_rate *txrate; struct carl9170_tx_info *arinfo; unsigned int hw_queue; - int i; __le16 mac_tmp; u16 len; - bool ampdu, no_ack; BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) != @@ -889,8 +973,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) != AR9170_TX_HWDESC_LEN); - BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); - BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > ((CARL9170_TX_SUPER_MISC_VIF_ID >> CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); @@ -932,8 +1014,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) & AR9170_TX_MAC_QOS); - no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); - if (unlikely(no_ack)) + if (unlikely(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); if (info->control.hw_key) { @@ -954,8 +1035,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, } } - ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); - if (ampdu) { + if (info->flags & IEEE80211_TX_CTL_AMPDU) { unsigned int density, factor; if (unlikely(!sta || !cvif)) @@ -982,50 +1062,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, txc->s.ampdu_settings, factor); } - /* - * NOTE: For the first rate, the ERP & AMPDU flags are directly - * taken from mac_control. For all fallback rate, the firmware - * updates the mac_control flags from the rate info field. - */ - for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { - __le32 phy_set; - txrate = &info->control.rates[i]; - if (txrate->idx < 0) - break; - - phy_set = carl9170_tx_physet(ar, info, txrate); - if (i == 0) { - /* first rate - part of the hw's frame header */ - txc->f.phy_control = phy_set; - - if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - else if (carl9170_tx_cts_check(ar, txrate)) - mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - - } else { - /* fallback rates are stored in the firmware's - * retry rate set array. - */ - txc->s.rr[i - 1] = phy_set; - } - - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i], - txrate->count); - - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS << - CARL9170_TX_SUPER_RI_ERP_PROT_S); - else if (carl9170_tx_cts_check(ar, txrate)) - txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << - CARL9170_TX_SUPER_RI_ERP_PROT_S); - - if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS)) - txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; - } - txc->s.len = cpu_to_le16(skb->len); txc->f.length = cpu_to_le16(len + FCS_LEN); txc->f.mac_control = mac_tmp; @@ -1086,31 +1122,12 @@ static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb) } } -static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest, - struct sk_buff *_src) -{ - struct _carl9170_tx_superframe *dest, *src; - - dest = (void *) _dest->data; - src = (void *) _src->data; - - /* - * The mac80211 rate control algorithm expects that all MPDUs in - * an AMPDU share the same tx vectors. - * This is not really obvious right now, because the hardware - * does the AMPDU setup according to its own rulebook. - * Our nicely assembled, strictly monotonic increasing mpdu - * chains will be broken up, mashed back together... - */ - - return (dest->f.phy_control == src->f.phy_control); -} - static void carl9170_tx_ampdu(struct ar9170 *ar) { struct sk_buff_head agg; struct carl9170_sta_tid *tid_info; struct sk_buff *skb, *first; + struct ieee80211_tx_info *tx_info_first; unsigned int i = 0, done_ampdus = 0; u16 seq, queue, tmpssn; @@ -1156,6 +1173,7 @@ static void carl9170_tx_ampdu(struct ar9170 *ar) goto processed; } + tx_info_first = NULL; while ((skb = skb_peek(&tid_info->queue))) { /* strict 0, 1, ..., n - 1, n frame sequence order */ if (unlikely(carl9170_get_seq(skb) != seq)) @@ -1166,8 +1184,13 @@ static void carl9170_tx_ampdu(struct ar9170 *ar) (tid_info->max - 1))) break; - if (!carl9170_tx_rate_check(ar, skb, first)) - break; + if (!tx_info_first) { + carl9170_tx_get_rates(ar, tid_info->vif, + tid_info->sta, first); + tx_info_first = IEEE80211_SKB_CB(first); + } + + carl9170_tx_apply_rateset(ar, tx_info_first, skb); atomic_inc(&ar->tx_ampdu_upload); tid_info->snx = seq = SEQ_NEXT(seq); @@ -1182,8 +1205,7 @@ static void carl9170_tx_ampdu(struct ar9170 *ar) if (skb_queue_empty(&tid_info->queue) || carl9170_get_seq(skb_peek(&tid_info->queue)) != tid_info->snx) { - /* - * stop TID, if A-MPDU frames are still missing, + /* stop TID, if A-MPDU frames are still missing, * or whenever the queue is empty. */ @@ -1450,12 +1472,14 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct ar9170 *ar = hw->priv; struct ieee80211_tx_info *info; struct ieee80211_sta *sta = control->sta; + struct ieee80211_vif *vif; bool run; if (unlikely(!IS_STARTED(ar))) goto err_free; info = IEEE80211_SKB_CB(skb); + vif = info->control.vif; if (unlikely(carl9170_tx_prepare(ar, sta, skb))) goto err_free; @@ -1486,6 +1510,8 @@ void carl9170_op_tx(struct ieee80211_hw *hw, } else { unsigned int queue = skb_get_queue_mapping(skb); + carl9170_tx_get_rates(ar, vif, sta, skb); + carl9170_tx_apply_rateset(ar, info, skb); skb_queue_tail(&ar->tx_pending[queue], skb); } -- GitLab From fca97d763dc662db446c9a6e5486ef0c77d8ad5b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 13 Jun 2013 08:52:09 +0530 Subject: [PATCH 1150/2900] ath9k: Fix ANI trigger threshold Since raising/lowering the limits based on INI has been changed, the error limit for OFDM has to be 1000, not 3500. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index b75aea23b313..77a06fd40287 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -20,7 +20,7 @@ #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) /* units are errors per second */ -#define ATH9K_ANI_OFDM_TRIG_HIGH 3500 +#define ATH9K_ANI_OFDM_TRIG_HIGH 1000 #define ATH9K_ANI_OFDM_TRIG_LOW 400 #define ATH9K_ANI_CCK_TRIG_HIGH 600 #define ATH9K_ANI_CCK_TRIG_LOW 300 -- GitLab From 9c59844005c22700b36dcdbafeea7956b7f4b174 Mon Sep 17 00:00:00 2001 From: Arron Wang Date: Mon, 22 Apr 2013 17:21:04 +0800 Subject: [PATCH 1151/2900] NFC: pn544: Identify Type F NFC-DEP through NFCID2 NFCID2 is defined as the first 2 manufacturer ID (IDm) bytes. NFC DEP (NFC peer to peer) devices Type-F NFCID2 must start with 0x01fe according to the NFC Digital Specification. By checking those first 2 bytes we send the right command either to the reader gate when NFCID2 != 0x1fe (The NFC tag case) or to the NFCIP1 gate when seeing an NFC DEP device (The NFC peer to peer case). Without this fix, Felica (Type F) tags are not properly detected with this driver. Signed-off-by: Arron Wang Signed-off-by: Samuel Ortiz --- drivers/nfc/pn544/pn544.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 9c5f16e7baef..0963de2f6ab0 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -551,20 +551,25 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, return -EPROTO; } - r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, - PN544_RF_READER_CMD_ACTIVATE_NEXT, - uid_skb->data, uid_skb->len, NULL); - kfree_skb(uid_skb); - - r = nfc_hci_send_cmd(hdev, + /* Type F NFC-DEP IDm has prefix 0x01FE */ + if ((uid_skb->data[0] == 0x01) && (uid_skb->data[1] == 0xfe)) { + kfree_skb(uid_skb); + r = nfc_hci_send_cmd(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); - if (r < 0) - return r; + if (r < 0) + return r; - target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; - target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; + target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; + target->hci_reader_gate = + PN544_RF_READER_NFCIP1_INITIATOR_GATE; + } else { + r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, + PN544_RF_READER_CMD_ACTIVATE_NEXT, + uid_skb->data, uid_skb->len, NULL); + kfree_skb(uid_skb); + } } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { /* * TODO: maybe other ISO 14443 require some kind of continue -- GitLab From a69bdc1ecd032fda1bc808fa0e1634bbc9417ad5 Mon Sep 17 00:00:00 2001 From: Arron Wang Date: Mon, 22 Apr 2013 17:21:27 +0800 Subject: [PATCH 1152/2900] NFC: pn544: Remove Felica and Jewel device presence check There is no builtin command for driver to check the presence of Felica and Jewel device, it is more reasonable for the userspace daemon neard to build seperate commands to check the presence of the card. Signed-off-by: Arron Wang Signed-off-by: Samuel Ortiz --- drivers/nfc/pn544/pn544.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 0963de2f6ab0..84b5168b603c 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -711,12 +711,9 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, PN544_RF_READER_CMD_ACTIVATE_NEXT, target->nfcid1, target->nfcid1_len, NULL); - } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) { - return nfc_hci_send_cmd(hdev, target->hci_reader_gate, - PN544_JEWEL_RAW_CMD, NULL, 0, NULL); - } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { - return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, - PN544_FELICA_RAW, NULL, 0, NULL); + } else if (target->supported_protocols & (NFC_PROTO_JEWEL_MASK | + NFC_PROTO_FELICA_MASK)) { + return -EOPNOTSUPP; } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { return nfc_hci_send_cmd(hdev, target->hci_reader_gate, PN544_HCI_CMD_ATTREQUEST, -- GitLab From 4674d0fecbeeb9731274f03ff35a108630be4585 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 7 May 2013 20:07:52 +0800 Subject: [PATCH 1153/2900] NFC: pn533: Fix error return code in pn533_probe() Fix to return -ENOMEM in the nfc device alloc error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 8f6f2baa930d..0bdfa8852e78 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2783,8 +2783,10 @@ static int pn533_probe(struct usb_interface *interface, dev->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, dev->ops->tx_tail_len); - if (!dev->nfc_dev) + if (!dev->nfc_dev) { + rc = -ENOMEM; goto destroy_wq; + } nfc_set_parent_dev(dev->nfc_dev, &interface->dev); nfc_set_drvdata(dev->nfc_dev, dev); -- GitLab From 1095e69f47926db6f1350a9d6a38626521580e87 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Wed, 22 May 2013 11:36:17 +0200 Subject: [PATCH 1154/2900] NFC: NCI: Fix skb->dev usage skb->dev is used for carrying a net_device pointer and not an nci_dev pointer. Remove usage of skb-dev to carry nci_dev and replace it by parameter in nci_recv_frame(), nci_send_frame() and driver send() functions. NfcWilink driver is also updated to use those functions. Signed-off-by: Frederic Danis Signed-off-by: Samuel Ortiz --- drivers/nfc/nfcwilink.c | 17 +++++------------ include/net/nfc/nci_core.h | 4 ++-- net/nfc/nci/core.c | 17 ++++++----------- net/nfc/nci/data.c | 2 -- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 3b731acbc408..41cf8f70a6ad 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -109,7 +109,7 @@ enum { NFCWILINK_FW_DOWNLOAD, }; -static int nfcwilink_send(struct sk_buff *skb); +static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb); static inline struct sk_buff *nfcwilink_skb_alloc(unsigned int len, gfp_t how) { @@ -156,8 +156,6 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) return -ENOMEM; } - skb->dev = (void *)drv->ndev; - cmd = (struct nci_vs_nfcc_info_cmd *) skb_put(skb, sizeof(struct nci_vs_nfcc_info_cmd)); cmd->gid = NCI_VS_NFCC_INFO_CMD_GID; @@ -166,7 +164,7 @@ static int nfcwilink_get_bts_file_name(struct nfcwilink *drv, char *file_name) drv->nfcc_info.plen = 0; - rc = nfcwilink_send(skb); + rc = nfcwilink_send(drv->ndev, skb); if (rc) return rc; @@ -232,11 +230,9 @@ static int nfcwilink_send_bts_cmd(struct nfcwilink *drv, __u8 *data, int len) return -ENOMEM; } - skb->dev = (void *)drv->ndev; - memcpy(skb_put(skb, len), data, len); - rc = nfcwilink_send(skb); + rc = nfcwilink_send(drv->ndev, skb); if (rc) return rc; @@ -371,10 +367,8 @@ static long nfcwilink_receive(void *priv_data, struct sk_buff *skb) return 0; } - skb->dev = (void *) drv->ndev; - /* Forward skb to NCI core layer */ - rc = nci_recv_frame(skb); + rc = nci_recv_frame(drv->ndev, skb); if (rc < 0) { nfc_dev_err(&drv->pdev->dev, "nci_recv_frame failed %d", rc); return rc; @@ -480,9 +474,8 @@ static int nfcwilink_close(struct nci_dev *ndev) return rc; } -static int nfcwilink_send(struct sk_buff *skb) +static int nfcwilink_send(struct nci_dev *ndev, struct sk_buff *skb) { - struct nci_dev *ndev = (struct nci_dev *)skb->dev; struct nfcwilink *drv = nci_get_drvdata(ndev); struct nfcwilink_hdr hdr = {NFCWILINK_CHNL, NFCWILINK_OPCODE, 0x0000}; long len; diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 5bc0c460edc0..1009d3dcb316 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -66,7 +66,7 @@ struct nci_dev; struct nci_ops { int (*open)(struct nci_dev *ndev); int (*close)(struct nci_dev *ndev); - int (*send)(struct sk_buff *skb); + int (*send)(struct nci_dev *ndev, struct sk_buff *skb); }; #define NCI_MAX_SUPPORTED_RF_INTERFACES 4 @@ -153,7 +153,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, void nci_free_device(struct nci_dev *ndev); int nci_register_device(struct nci_dev *ndev); void nci_unregister_device(struct nci_dev *ndev); -int nci_recv_frame(struct sk_buff *skb); +int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, unsigned int len, diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 48ada0ec749e..8e0dbbeee9e3 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -797,12 +797,11 @@ EXPORT_SYMBOL(nci_unregister_device); /** * nci_recv_frame - receive frame from NCI drivers * + * @ndev: The nci device * @skb: The sk_buff to receive */ -int nci_recv_frame(struct sk_buff *skb) +int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb) { - struct nci_dev *ndev = (struct nci_dev *) skb->dev; - pr_debug("len %d\n", skb->len); if (!ndev || (!test_bit(NCI_UP, &ndev->flags) && @@ -819,10 +818,8 @@ int nci_recv_frame(struct sk_buff *skb) } EXPORT_SYMBOL(nci_recv_frame); -static int nci_send_frame(struct sk_buff *skb) +static int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb) { - struct nci_dev *ndev = (struct nci_dev *) skb->dev; - pr_debug("len %d\n", skb->len); if (!ndev) { @@ -833,7 +830,7 @@ static int nci_send_frame(struct sk_buff *skb) /* Get rid of skb owner, prior to sending to the driver. */ skb_orphan(skb); - return ndev->ops->send(skb); + return ndev->ops->send(ndev, skb); } /* Send NCI command */ @@ -861,8 +858,6 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload) if (plen) memcpy(skb_put(skb, plen), payload, plen); - skb->dev = (void *) ndev; - skb_queue_tail(&ndev->cmd_q, skb); queue_work(ndev->cmd_wq, &ndev->cmd_work); @@ -894,7 +889,7 @@ static void nci_tx_work(struct work_struct *work) nci_conn_id(skb->data), nci_plen(skb->data)); - nci_send_frame(skb); + nci_send_frame(ndev, skb); mod_timer(&ndev->data_timer, jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT)); @@ -963,7 +958,7 @@ static void nci_cmd_work(struct work_struct *work) nci_opcode_oid(nci_opcode(skb->data)), nci_plen(skb->data)); - nci_send_frame(skb); + nci_send_frame(ndev, skb); mod_timer(&ndev->cmd_timer, jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c index 76c48c5324f8..2a9399dd6c68 100644 --- a/net/nfc/nci/data.c +++ b/net/nfc/nci/data.c @@ -80,8 +80,6 @@ static inline void nci_push_data_hdr(struct nci_dev *ndev, nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT); nci_pbf_set((__u8 *)hdr, pbf); - - skb->dev = (void *) ndev; } static int nci_queue_tx_data_frags(struct nci_dev *ndev, -- GitLab From 9674da8759df0d6c0d24e1ede6e2a1acdef91e3c Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 29 Apr 2013 17:13:27 +0200 Subject: [PATCH 1155/2900] NFC: Add firmware upload netlink command As several NFC chipsets can have their firmwares upgraded and reflashed, this patchset adds a new netlink command to trigger that the driver loads or flashes a new firmware. This will allows userspace triggered firmware upgrade through netlink. The firmware name or hint is passed as a parameter, and the driver will eventually fetch the firmware binary through the request_firmware API. The cmd can only be executed when the nfc dev is not in use. Actual firmware loading/flashing is an asynchronous operation. Result of the operation shall send a new event up to user space through the nfc dev multicast socket. During operation, the nfc dev is not openable and thus not usable. Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/nfc.h | 2 ++ include/uapi/linux/nfc.h | 6 ++++ net/nfc/core.c | 46 +++++++++++++++++++++++++++++ net/nfc/netlink.c | 63 ++++++++++++++++++++++++++++++++++++++++ net/nfc/nfc.h | 5 ++++ 5 files changed, 122 insertions(+) diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 5eb80bb3cbb2..3563dbdcaaf2 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -70,6 +70,7 @@ struct nfc_ops { int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); int (*enable_se)(struct nfc_dev *dev, u32 secure_element); int (*disable_se)(struct nfc_dev *dev, u32 secure_element); + int (*fw_upload)(struct nfc_dev *dev, const char *firmware_name); }; #define NFC_TARGET_IDX_ANY -1 @@ -104,6 +105,7 @@ struct nfc_dev { int targets_generation; struct device dev; bool dev_up; + bool fw_upload_in_progress; u8 rf_mode; bool polling; struct nfc_target *active_target; diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 7c6f627a717d..b6cbd164f146 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -69,6 +69,8 @@ * starting a poll from a device which has a secure element enabled means * we want to do SE based card emulation. * @NFC_CMD_DISABLE_SE: Disable the physical link to a specific secure element. + * @NFC_CMD_FW_UPLOAD: Request to Load/flash firmware, or event to inform that + * some firmware was loaded */ enum nfc_commands { NFC_CMD_UNSPEC, @@ -92,6 +94,7 @@ enum nfc_commands { NFC_CMD_DISABLE_SE, NFC_CMD_LLC_SDREQ, NFC_EVENT_LLC_SDRES, + NFC_CMD_FW_UPLOAD, /* private: internal use only */ __NFC_CMD_AFTER_LAST }; @@ -121,6 +124,7 @@ enum nfc_commands { * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter * @NFC_ATTR_SE: Available Secure Elements + * @NFC_ATTR_FIRMWARE_NAME: Free format firmware version */ enum nfc_attrs { NFC_ATTR_UNSPEC, @@ -143,6 +147,7 @@ enum nfc_attrs { NFC_ATTR_LLC_PARAM_MIUX, NFC_ATTR_SE, NFC_ATTR_LLC_SDP, + NFC_ATTR_FIRMWARE_NAME, /* private: internal use only */ __NFC_ATTR_AFTER_LAST }; @@ -162,6 +167,7 @@ enum nfc_sdp_attr { #define NFC_SENSB_RES_MAXSIZE 12 #define NFC_SENSF_RES_MAXSIZE 18 #define NFC_GB_MAXSIZE 48 +#define NFC_FIRMWARE_NAME_MAXSIZE 32 /* NFC protocols */ #define NFC_PROTO_JEWEL 1 diff --git a/net/nfc/core.c b/net/nfc/core.c index 40d2527693da..eb3cecf1764e 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -44,6 +44,47 @@ DEFINE_MUTEX(nfc_devlist_mutex); /* NFC device ID bitmap */ static DEFINE_IDA(nfc_index_ida); +int nfc_fw_upload(struct nfc_dev *dev, const char *firmware_name) +{ + int rc = 0; + + pr_debug("%s do firmware %s\n", dev_name(&dev->dev), firmware_name); + + device_lock(&dev->dev); + + if (!device_is_registered(&dev->dev)) { + rc = -ENODEV; + goto error; + } + + if (dev->dev_up) { + rc = -EBUSY; + goto error; + } + + if (!dev->ops->fw_upload) { + rc = -EOPNOTSUPP; + goto error; + } + + dev->fw_upload_in_progress = true; + rc = dev->ops->fw_upload(dev, firmware_name); + if (rc) + dev->fw_upload_in_progress = false; + +error: + device_unlock(&dev->dev); + return rc; +} + +int nfc_fw_upload_done(struct nfc_dev *dev, const char *firmware_name) +{ + dev->fw_upload_in_progress = false; + + return nfc_genl_fw_upload_done(dev, firmware_name); +} +EXPORT_SYMBOL(nfc_fw_upload_done); + /** * nfc_dev_up - turn on the NFC device * @@ -69,6 +110,11 @@ int nfc_dev_up(struct nfc_dev *dev) goto error; } + if (dev->fw_upload_in_progress) { + rc = -EBUSY; + goto error; + } + if (dev->dev_up) { rc = -EALREADY; goto error; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index f0c4d61f37c0..1deadad9a285 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -56,6 +56,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 }, [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 }, [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, + [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, + .len = NFC_FIRMWARE_NAME_MAXSIZE }, }; static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { @@ -1025,6 +1027,62 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) return rc; } +static int nfc_genl_fw_upload(struct sk_buff *skb, struct genl_info *info) +{ + struct nfc_dev *dev; + int rc; + u32 idx; + char firmware_name[NFC_FIRMWARE_NAME_MAXSIZE + 1]; + + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) + return -EINVAL; + + idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); + + dev = nfc_get_device(idx); + if (!dev) + return -ENODEV; + + nla_strlcpy(firmware_name, info->attrs[NFC_ATTR_FIRMWARE_NAME], + sizeof(firmware_name)); + + rc = nfc_fw_upload(dev, firmware_name); + + nfc_put_device(dev); + return rc; +} + +int nfc_genl_fw_upload_done(struct nfc_dev *dev, const char *firmware_name) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, + NFC_CMD_FW_UPLOAD); + if (!hdr) + goto free_msg; + + if (nla_put_string(msg, NFC_ATTR_FIRMWARE_NAME, firmware_name) || + nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); +free_msg: + nlmsg_free(msg); + return -EMSGSIZE; +} + static struct genl_ops nfc_genl_ops[] = { { .cmd = NFC_CMD_GET_DEVICE, @@ -1084,6 +1142,11 @@ static struct genl_ops nfc_genl_ops[] = { .doit = nfc_genl_llc_sdreq, .policy = nfc_genl_policy, }, + { + .cmd = NFC_CMD_FW_UPLOAD, + .doit = nfc_genl_fw_upload, + .policy = nfc_genl_policy, + }, }; diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index afa1f84ba040..cf0c48165996 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -120,6 +120,11 @@ static inline void nfc_device_iter_exit(struct class_dev_iter *iter) class_dev_iter_exit(iter); } +int nfc_fw_upload(struct nfc_dev *dev, const char *firmware_name); +int nfc_genl_fw_upload_done(struct nfc_dev *dev, const char *firmware_name); + +int nfc_fw_upload_done(struct nfc_dev *dev, const char *firmware_name); + int nfc_dev_up(struct nfc_dev *dev); int nfc_dev_down(struct nfc_dev *dev); -- GitLab From 9a695d23aab889273821c91b4132f1ed315b251b Mon Sep 17 00:00:00 2001 From: Eric Lapuyade Date: Mon, 29 Apr 2013 17:47:42 +0200 Subject: [PATCH 1156/2900] NFC: HCI: Implement fw_upload ops This is a simple forward to the HCI driver. When driver is done with the operation, it shall directly notify NFC Core by calling nfc_fw_upload_done(). Signed-off-by: Eric Lapuyade Signed-off-by: Samuel Ortiz --- include/net/nfc/hci.h | 1 + net/nfc/hci/core.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index b87a1692b086..14faf2dc7a48 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -61,6 +61,7 @@ struct nfc_hci_ops { struct sk_buff *skb); int (*enable_se)(struct nfc_dev *dev, u32 secure_element); int (*disable_se)(struct nfc_dev *dev, u32 secure_element); + int (*fw_upload)(struct nfc_hci_dev *hdev, const char *firmware_name); }; /* Pipes */ diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 91020b210d87..b7e4dac5654e 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -779,6 +779,16 @@ static void nfc_hci_recv_from_llc(struct nfc_hci_dev *hdev, struct sk_buff *skb) } } +static int hci_fw_upload(struct nfc_dev *nfc_dev, const char *firmware_name) +{ + struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); + + if (hdev->ops->fw_upload) + return hdev->ops->fw_upload(hdev, firmware_name); + + return -ENOTSUPP; +} + static struct nfc_ops hci_nfc_ops = { .dev_up = hci_dev_up, .dev_down = hci_dev_down, @@ -791,6 +801,7 @@ static struct nfc_ops hci_nfc_ops = { .im_transceive = hci_transceive, .tm_send = hci_tm_send, .check_presence = hci_check_presence, + .fw_upload = hci_fw_upload, }; struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, -- GitLab From a395298c9c96748cbd6acee4cb9a5ba13fbb3ab8 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Sat, 25 May 2013 01:21:21 +0200 Subject: [PATCH 1157/2900] NFC: HCI: Follow a positive code path in the HCI ops implementations Exiting on the error case is more typical to the kernel coding style. Signed-off-by: Samuel Ortiz --- net/nfc/hci/core.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index b7e4dac5654e..d2ef1e2ee0c6 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -570,21 +570,21 @@ static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - if (hdev->ops->dep_link_up) - return hdev->ops->dep_link_up(hdev, target, comm_mode, - gb, gb_len); + if (!hdev->ops->dep_link_up) + return 0; - return 0; + return hdev->ops->dep_link_up(hdev, target, comm_mode, + gb, gb_len); } static int hci_dep_link_down(struct nfc_dev *nfc_dev) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - if (hdev->ops->dep_link_down) - return hdev->ops->dep_link_down(hdev); + if (!hdev->ops->dep_link_down) + return 0; - return 0; + return hdev->ops->dep_link_down(hdev); } static int hci_activate_target(struct nfc_dev *nfc_dev, @@ -673,12 +673,12 @@ static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - if (hdev->ops->tm_send) - return hdev->ops->tm_send(hdev, skb); - - kfree_skb(skb); + if (!hdev->ops->tm_send) { + kfree_skb(skb); + return -ENOTSUPP; + } - return -ENOTSUPP; + return hdev->ops->tm_send(hdev, skb); } static int hci_check_presence(struct nfc_dev *nfc_dev, @@ -686,10 +686,10 @@ static int hci_check_presence(struct nfc_dev *nfc_dev, { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - if (hdev->ops->check_presence) - return hdev->ops->check_presence(hdev, target); + if (!hdev->ops->check_presence) + return 0; - return 0; + return hdev->ops->check_presence(hdev, target); } static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) @@ -783,10 +783,10 @@ static int hci_fw_upload(struct nfc_dev *nfc_dev, const char *firmware_name) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); - if (hdev->ops->fw_upload) - return hdev->ops->fw_upload(hdev, firmware_name); + if (!hdev->ops->fw_upload) + return -ENOTSUPP; - return -ENOTSUPP; + return hdev->ops->fw_upload(hdev, firmware_name); } static struct nfc_ops hci_nfc_ops = { -- GitLab From 5f121b9a83b499a61ed44e5ba619c7de8f7271ad Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 13 Jun 2013 15:29:38 -0400 Subject: [PATCH 1158/2900] net-rps: fixes for rps flow limit Caught by sparse: - __rcu: missing annotation to sd->flow_limit - __user: direct access in cpumask_scnprintf Also - add endline character when printing bitmap if room in buffer - avoid bucket overflow by reducing FLOW_LIMIT_HISTORY The last item warrants some explanation. The hashtable buckets are subject to overflow if FLOW_LIMIT_HISTORY is larger than or equal to bucket size, since all packets may end up in a single bucket. The current (rather arbitrary) history value of 256 happens to match the buffer size (u8). As a result, with a single flow, the first 128 packets are accepted (correct), the second 128 packets dropped (correct) and then the history[] array has filled, so that each subsequent new packet causes an increment in the bucket for new_flow plus a decrement for old_flow: a steady state. This is fine if packets are dropped, as the steady state goes away as soon as a mix of traffic reappears. But, because the 256th packet overflowed the bucket to 0: no packets are dropped. Instead of explicitly adding an overflow check, this patch changes FLOW_LIMIT_HISTORY to never be able to overflow a single bucket. Reported-by: Fengguang Wu (first item) Signed-off-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/linux/netdevice.h | 4 ++-- net/core/sysctl_net_core.c | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e5d65573b4d6..8c9fcc42502a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1840,7 +1840,7 @@ static inline int unregister_gifconf(unsigned int family) } #ifdef CONFIG_NET_FLOW_LIMIT -#define FLOW_LIMIT_HISTORY (1 << 8) /* must be ^2 */ +#define FLOW_LIMIT_HISTORY (1 << 7) /* must be ^2 and !overflow buckets */ struct sd_flow_limit { u64 count; unsigned int num_buckets; @@ -1883,7 +1883,7 @@ struct softnet_data { struct napi_struct backlog; #ifdef CONFIG_NET_FLOW_LIMIT - struct sd_flow_limit *flow_limit; + struct sd_flow_limit __rcu *flow_limit; #endif }; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 637a42e5d589..78c746e016ae 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -132,6 +132,8 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write, write_unlock: mutex_unlock(&flow_limit_update_mutex); } else { + char kbuf[128]; + if (*ppos || !*lenp) { *lenp = 0; goto done; @@ -146,9 +148,20 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write, } rcu_read_unlock(); - len = cpumask_scnprintf(buffer, *lenp, mask); - *lenp = len + 1; - *ppos += len + 1; + len = min(sizeof(kbuf) - 1, *lenp); + len = cpumask_scnprintf(kbuf, len, mask); + if (!len) { + *lenp = 0; + goto done; + } + if (len < *lenp) + kbuf[len++] = '\n'; + if (copy_to_user(buffer, kbuf, len)) { + ret = -EFAULT; + goto done; + } + *lenp = len; + *ppos += len; } done: -- GitLab From ca4ec90b31d1ecf01087c607933cf792057bc8bf Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 13 Jun 2013 07:58:30 -0700 Subject: [PATCH 1159/2900] htb: reorder struct htb_class fields for performance htb_class structures are big, and source of false sharing on SMP. By carefully splitting them in two parts, we can improve performance. I got 9 % performance increase on a 24 threads machine, with 200 concurrent netperf in TCP_RR mode, using a HTB hierarchy of 4 classes. Signed-off-by: Eric Dumazet Cc: Tom Herbert Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 62 ++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 1a3655a606c1..7954e73d118a 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -76,23 +76,39 @@ enum htb_cmode { HTB_CAN_SEND /* class can send */ }; -/* interior & leaf nodes; props specific to leaves are marked L: */ +/* interior & leaf nodes; props specific to leaves are marked L: + * To reduce false sharing, place mostly read fields at beginning, + * and mostly written ones at the end. + */ struct htb_class { struct Qdisc_class_common common; - /* general class parameters */ - struct gnet_stats_basic_packed bstats; - struct gnet_stats_queue qstats; + struct psched_ratecfg rate; + struct psched_ratecfg ceil; + s64 buffer, cbuffer;/* token bucket depth/rate */ + s64 mbuffer; /* max wait time */ + int prio; /* these two are used only by leaves... */ + int quantum; /* but stored for parent-to-leaf return */ + + struct tcf_proto *filter_list; /* class attached filters */ + int filter_cnt; + int refcnt; /* usage count of this class */ + + int level; /* our level (see above) */ + unsigned int children; + struct htb_class *parent; /* parent class */ + struct gnet_stats_rate_est64 rate_est; - struct tc_htb_xstats xstats; /* our special stats */ - int refcnt; /* usage count of this class */ - /* topology */ - int level; /* our level (see above) */ - unsigned int children; - struct htb_class *parent; /* parent class */ + /* + * Written often fields + */ + struct gnet_stats_basic_packed bstats; + struct gnet_stats_queue qstats; + struct tc_htb_xstats xstats; /* our special stats */ - int prio; /* these two are used only by leaves... */ - int quantum; /* but stored for parent-to-leaf return */ + /* token bucket parameters */ + s64 tokens, ctokens;/* current number of tokens */ + s64 t_c; /* checkpoint time */ union { struct htb_class_leaf { @@ -111,24 +127,12 @@ struct htb_class { u32 last_ptr_id[TC_HTB_NUMPRIO]; } inner; } un; - struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ - struct rb_node pq_node; /* node for event queue */ - s64 pq_key; - - int prio_activity; /* for which prios are we active */ - enum htb_cmode cmode; /* current mode of the class */ + s64 pq_key; - /* class attached filters */ - struct tcf_proto *filter_list; - int filter_cnt; - - /* token bucket parameters */ - struct psched_ratecfg rate; - struct psched_ratecfg ceil; - s64 buffer, cbuffer; /* token bucket depth/rate */ - s64 mbuffer; /* max wait time */ - s64 tokens, ctokens; /* current number of tokens */ - s64 t_c; /* checkpoint time */ + int prio_activity; /* for which prios are we active */ + enum htb_cmode cmode; /* current mode of the class */ + struct rb_node pq_node; /* node for event queue */ + struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ }; struct htb_sched { -- GitLab From 3dc6475c0c9e55ac7f053ad6b8b398e779954545 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 12 Jun 2013 20:53:05 +0100 Subject: [PATCH 1160/2900] bcm63xx_enet: add support Broadcom BCM6345 Ethernet This patch adds support for the Broadcom BCM6345 SoC Ethernet. BCM6345 has a slightly different and older DMA engine which requires the following modifications: - the width of the DMA channels on BCM6345 is 64 bytes vs 16 bytes, which means that the helpers enet_dma{c,s} need to account for this channel width and we can no longer use macros - BCM6345 DMA engine does not have any internal SRAM for transfering buffers - BCM6345 buffer allocation and flow control is not per-channel but global (done in RSET_ENETDMA) - the DMA engine bits are right-shifted by 3 compared to other DMA generations - the DMA enable/interrupt masks are a little different (we need to enabled more bits for 6345) - some register have the same meaning but are offsetted in the ENET_DMAC space so a lookup table is required to return the proper offset The MAC itself is identical and requires no modifications to work. Signed-off-by: Florian Fainelli Acked-by: Ralf Baechle Signed-off-by: David S. Miller --- arch/mips/bcm63xx/dev-enet.c | 65 +++++- .../include/asm/mach-bcm63xx/bcm63xx_cpu.h | 3 +- .../asm/mach-bcm63xx/bcm63xx_dev_enet.h | 94 ++++++++ .../include/asm/mach-bcm63xx/bcm63xx_regs.h | 43 +++- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 200 +++++++++++------- drivers/net/ethernet/broadcom/bcm63xx_enet.h | 15 ++ 6 files changed, 329 insertions(+), 91 deletions(-) diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c index 6cbaee0f6d70..52bc01df9bfe 100644 --- a/arch/mips/bcm63xx/dev-enet.c +++ b/arch/mips/bcm63xx/dev-enet.c @@ -9,10 +9,44 @@ #include #include #include +#include #include #include #include +#ifdef BCMCPU_RUNTIME_DETECT +static const unsigned long bcm6348_regs_enetdmac[] = { + [ENETDMAC_CHANCFG] = ENETDMAC_CHANCFG_REG, + [ENETDMAC_IR] = ENETDMAC_IR_REG, + [ENETDMAC_IRMASK] = ENETDMAC_IRMASK_REG, + [ENETDMAC_MAXBURST] = ENETDMAC_MAXBURST_REG, +}; + +static const unsigned long bcm6345_regs_enetdmac[] = { + [ENETDMAC_CHANCFG] = ENETDMA_6345_CHANCFG_REG, + [ENETDMAC_IR] = ENETDMA_6345_IR_REG, + [ENETDMAC_IRMASK] = ENETDMA_6345_IRMASK_REG, + [ENETDMAC_MAXBURST] = ENETDMA_6345_MAXBURST_REG, + [ENETDMAC_BUFALLOC] = ENETDMA_6345_BUFALLOC_REG, + [ENETDMAC_RSTART] = ENETDMA_6345_RSTART_REG, + [ENETDMAC_FC] = ENETDMA_6345_FC_REG, + [ENETDMAC_LEN] = ENETDMA_6345_LEN_REG, +}; + +const unsigned long *bcm63xx_regs_enetdmac; +EXPORT_SYMBOL(bcm63xx_regs_enetdmac); + +static __init void bcm63xx_enetdmac_regs_init(void) +{ + if (BCMCPU_IS_6345()) + bcm63xx_regs_enetdmac = bcm6345_regs_enetdmac; + else + bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac; +} +#else +static __init void bcm63xx_enetdmac_regs_init(void) { } +#endif + static struct resource shared_res[] = { { .start = -1, /* filled at runtime */ @@ -137,12 +171,19 @@ static int __init register_shared(void) if (shared_device_registered) return 0; + bcm63xx_enetdmac_regs_init(); + shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA); shared_res[0].end = shared_res[0].start; - shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; + if (BCMCPU_IS_6345()) + shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1; + else + shared_res[0].end += (RSET_ENETDMA_SIZE) - 1; if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) chan_count = 32; + else if (BCMCPU_IS_6345()) + chan_count = 8; else chan_count = 16; @@ -172,7 +213,7 @@ int __init bcm63xx_enet_register(int unit, if (unit > 1) return -ENODEV; - if (unit == 1 && BCMCPU_IS_6338()) + if (unit == 1 && (BCMCPU_IS_6338() || BCMCPU_IS_6345())) return -ENODEV; ret = register_shared(); @@ -213,6 +254,21 @@ int __init bcm63xx_enet_register(int unit, dpd->phy_interrupt = bcm63xx_get_irq_number(IRQ_ENET_PHY); } + dpd->dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK; + dpd->dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK; + if (BCMCPU_IS_6345()) { + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_CHAINING_MASK; + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_WRAP_EN_MASK; + dpd->dma_chan_en_mask |= ENETDMAC_CHANCFG_FLOWC_EN_MASK; + dpd->dma_chan_int_mask |= ENETDMA_IR_BUFDONE_MASK; + dpd->dma_chan_int_mask |= ENETDMA_IR_NOTOWNER_MASK; + dpd->dma_chan_width = ENETDMA_6345_CHAN_WIDTH; + dpd->dma_desc_shift = ENETDMA_6345_DESC_SHIFT; + } else { + dpd->dma_has_sram = true; + dpd->dma_chan_width = ENETDMA_CHAN_WIDTH; + } + ret = platform_device_register(pdev); if (ret) return ret; @@ -246,6 +302,11 @@ bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd) else if (BCMCPU_IS_6362() || BCMCPU_IS_6368()) enetsw_pd.num_ports = ENETSW_PORTS_6368; + enetsw_pd.dma_has_sram = true; + enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH; + enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK; + enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK; + ret = platform_device_register(&bcm63xx_enetsw_device); if (ret) return ret; diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 9981f4f0e42f..e6e65dc7d502 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -174,6 +174,7 @@ enum bcm63xx_regs_set { #define BCM_6368_RSET_SPI_SIZE 1804 #define RSET_ENET_SIZE 2048 #define RSET_ENETDMA_SIZE 256 +#define RSET_6345_ENETDMA_SIZE 64 #define RSET_ENETDMAC_SIZE(chans) (16 * (chans)) #define RSET_ENETDMAS_SIZE(chans) (16 * (chans)) #define RSET_ENETSW_SIZE 65536 @@ -300,7 +301,7 @@ enum bcm63xx_regs_set { #define BCM_6345_USBDMA_BASE (0xfffe2800) #define BCM_6345_ENET0_BASE (0xfffe1800) #define BCM_6345_ENETDMA_BASE (0xfffe2800) -#define BCM_6345_ENETDMAC_BASE (0xfffe2900) +#define BCM_6345_ENETDMAC_BASE (0xfffe2840) #define BCM_6345_ENETDMAS_BASE (0xfffe2a00) #define BCM_6345_ENETSW_BASE (0xdeadbeef) #define BCM_6345_PCMCIA_BASE (0xfffe2028) diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h index 118e3c938841..753953e86242 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h @@ -4,6 +4,8 @@ #include #include +#include + /* * on board ethernet platform data */ @@ -37,6 +39,21 @@ struct bcm63xx_enet_platform_data { int phy_id, int reg), void (*mii_write)(struct net_device *dev, int phy_id, int reg, int val)); + + /* DMA channel enable mask */ + u32 dma_chan_en_mask; + + /* DMA channel interrupt mask */ + u32 dma_chan_int_mask; + + /* DMA engine has internal SRAM */ + bool dma_has_sram; + + /* DMA channel register width */ + unsigned int dma_chan_width; + + /* DMA descriptor shift */ + unsigned int dma_desc_shift; }; /* @@ -63,6 +80,18 @@ struct bcm63xx_enetsw_platform_data { char mac_addr[ETH_ALEN]; int num_ports; struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT]; + + /* DMA channel enable mask */ + u32 dma_chan_en_mask; + + /* DMA channel interrupt mask */ + u32 dma_chan_int_mask; + + /* DMA channel register width */ + unsigned int dma_chan_width; + + /* DMA engine has internal SRAM */ + bool dma_has_sram; }; int __init bcm63xx_enet_register(int unit, @@ -70,4 +99,69 @@ int __init bcm63xx_enet_register(int unit, int bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd); +enum bcm63xx_regs_enetdmac { + ENETDMAC_CHANCFG, + ENETDMAC_IR, + ENETDMAC_IRMASK, + ENETDMAC_MAXBURST, + ENETDMAC_BUFALLOC, + ENETDMAC_RSTART, + ENETDMAC_FC, + ENETDMAC_LEN, +}; + +static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg) +{ +#ifdef BCMCPU_RUNTIME_DETECT + extern const unsigned long *bcm63xx_regs_enetdmac; + + return bcm63xx_regs_enetdmac[reg]; +#else +#ifdef CONFIG_BCM63XX_CPU_6345 + switch (reg) { + case ENETDMAC_CHANCFG: + return ENETDMA_6345_CHANCFG_REG; + case ENETDMAC_IR: + return ENETDMA_6345_IR_REG; + case ENETDMAC_IRMASK: + return ENETDMA_6345_IRMASK_REG; + case ENETDMAC_MAXBURST: + return ENETDMA_6345_MAXBURST_REG; + case ENETDMAC_BUFALLOC: + return ENETDMA_6345_BUFALLOC_REG; + case ENETDMAC_RSTART: + return ENETDMA_6345_RSTART_REG; + case ENETDMAC_FC: + return ENETDMA_6345_FC_REG; + case ENETDMAC_LEN: + return ENETDMA_6345_LEN_REG; + } +#endif +#if defined(CONFIG_BCM63XX_CPU_6328) || \ + defined(CONFIG_BCM63XX_CPU_6338) || \ + defined(CONFIG_BCM63XX_CPU_6348) || \ + defined(CONFIG_BCM63XX_CPU_6358) || \ + defined(CONFIG_BCM63XX_CPU_6362) || \ + defined(CONFIG_BCM63XX_CPU_6368) + switch (reg) { + case ENETDMAC_CHANCFG: + return ENETDMAC_CHANCFG_REG; + case ENETDMAC_IR: + return ENETDMAC_IR_REG; + case ENETDMAC_IRMASK: + return ENETDMAC_IRMASK_REG; + case ENETDMAC_MAXBURST: + return ENETDMAC_MAXBURST_REG; + case ENETDMAC_BUFALLOC: + case ENETDMAC_RSTART: + case ENETDMAC_FC: + case ENETDMAC_LEN: + return 0; + } +#endif +#endif + return 0; +} + + #endif /* ! BCM63XX_DEV_ENET_H_ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 0a2121abb1a6..eff7ca7d12b0 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -727,6 +727,8 @@ /************************************************************************* * _REG relative to RSET_ENETDMA *************************************************************************/ +#define ENETDMA_CHAN_WIDTH 0x10 +#define ENETDMA_6345_CHAN_WIDTH 0x40 /* Controller Configuration Register */ #define ENETDMA_CFG_REG (0x0) @@ -782,31 +784,56 @@ /* State Ram Word 4 */ #define ENETDMA_SRAM4_REG(x) (0x20c + (x) * 0x10) +/* Broadcom 6345 ENET DMA definitions */ +#define ENETDMA_6345_CHANCFG_REG (0x00) + +#define ENETDMA_6345_MAXBURST_REG (0x40) + +#define ENETDMA_6345_RSTART_REG (0x08) + +#define ENETDMA_6345_LEN_REG (0x0C) + +#define ENETDMA_6345_IR_REG (0x14) + +#define ENETDMA_6345_IRMASK_REG (0x18) + +#define ENETDMA_6345_FC_REG (0x1C) + +#define ENETDMA_6345_BUFALLOC_REG (0x20) + +/* Shift down for EOP, SOP and WRAP bits */ +#define ENETDMA_6345_DESC_SHIFT (3) /************************************************************************* * _REG relative to RSET_ENETDMAC *************************************************************************/ /* Channel Configuration register */ -#define ENETDMAC_CHANCFG_REG(x) ((x) * 0x10) +#define ENETDMAC_CHANCFG_REG (0x0) #define ENETDMAC_CHANCFG_EN_SHIFT 0 #define ENETDMAC_CHANCFG_EN_MASK (1 << ENETDMAC_CHANCFG_EN_SHIFT) #define ENETDMAC_CHANCFG_PKTHALT_SHIFT 1 #define ENETDMAC_CHANCFG_PKTHALT_MASK (1 << ENETDMAC_CHANCFG_PKTHALT_SHIFT) #define ENETDMAC_CHANCFG_BUFHALT_SHIFT 2 #define ENETDMAC_CHANCFG_BUFHALT_MASK (1 << ENETDMAC_CHANCFG_BUFHALT_SHIFT) +#define ENETDMAC_CHANCFG_CHAINING_SHIFT 2 +#define ENETDMAC_CHANCFG_CHAINING_MASK (1 << ENETDMAC_CHANCFG_CHAINING_SHIFT) +#define ENETDMAC_CHANCFG_WRAP_EN_SHIFT 3 +#define ENETDMAC_CHANCFG_WRAP_EN_MASK (1 << ENETDMAC_CHANCFG_WRAP_EN_SHIFT) +#define ENETDMAC_CHANCFG_FLOWC_EN_SHIFT 4 +#define ENETDMAC_CHANCFG_FLOWC_EN_MASK (1 << ENETDMAC_CHANCFG_FLOWC_EN_SHIFT) /* Interrupt Control/Status register */ -#define ENETDMAC_IR_REG(x) (0x4 + (x) * 0x10) +#define ENETDMAC_IR_REG (0x4) #define ENETDMAC_IR_BUFDONE_MASK (1 << 0) #define ENETDMAC_IR_PKTDONE_MASK (1 << 1) #define ENETDMAC_IR_NOTOWNER_MASK (1 << 2) /* Interrupt Mask register */ -#define ENETDMAC_IRMASK_REG(x) (0x8 + (x) * 0x10) +#define ENETDMAC_IRMASK_REG (0x8) /* Maximum Burst Length */ -#define ENETDMAC_MAXBURST_REG(x) (0xc + (x) * 0x10) +#define ENETDMAC_MAXBURST_REG (0xc) /************************************************************************* @@ -814,16 +841,16 @@ *************************************************************************/ /* Ring Start Address register */ -#define ENETDMAS_RSTART_REG(x) ((x) * 0x10) +#define ENETDMAS_RSTART_REG (0x0) /* State Ram Word 2 */ -#define ENETDMAS_SRAM2_REG(x) (0x4 + (x) * 0x10) +#define ENETDMAS_SRAM2_REG (0x4) /* State Ram Word 3 */ -#define ENETDMAS_SRAM3_REG(x) (0x8 + (x) * 0x10) +#define ENETDMAS_SRAM3_REG (0x8) /* State Ram Word 4 */ -#define ENETDMAS_SRAM4_REG(x) (0xc + (x) * 0x10) +#define ENETDMAS_SRAM4_REG (0xc) /************************************************************************* diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index fbbfc4acd53f..8f1ac023bb03 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -107,26 +107,28 @@ static inline void enet_dma_writel(struct bcm_enet_priv *priv, bcm_writel(val, bcm_enet_shared_base[0] + off); } -static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off) +static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off, int chan) { - return bcm_readl(bcm_enet_shared_base[1] + off); + return bcm_readl(bcm_enet_shared_base[1] + + bcm63xx_enetdmacreg(off) + chan * priv->dma_chan_width); } static inline void enet_dmac_writel(struct bcm_enet_priv *priv, - u32 val, u32 off) + u32 val, u32 off, int chan) { - bcm_writel(val, bcm_enet_shared_base[1] + off); + bcm_writel(val, bcm_enet_shared_base[1] + + bcm63xx_enetdmacreg(off) + chan * priv->dma_chan_width); } -static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off) +static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off, int chan) { - return bcm_readl(bcm_enet_shared_base[2] + off); + return bcm_readl(bcm_enet_shared_base[2] + off + chan * priv->dma_chan_width); } static inline void enet_dmas_writel(struct bcm_enet_priv *priv, - u32 val, u32 off) + u32 val, u32 off, int chan) { - bcm_writel(val, bcm_enet_shared_base[2] + off); + bcm_writel(val, bcm_enet_shared_base[2] + off + chan * priv->dma_chan_width); } /* @@ -262,7 +264,7 @@ static int bcm_enet_refill_rx(struct net_device *dev) len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT; len_stat |= DMADESC_OWNER_MASK; if (priv->rx_dirty_desc == priv->rx_ring_size - 1) { - len_stat |= DMADESC_WRAP_MASK; + len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift); priv->rx_dirty_desc = 0; } else { priv->rx_dirty_desc++; @@ -273,7 +275,10 @@ static int bcm_enet_refill_rx(struct net_device *dev) priv->rx_desc_count++; /* tell dma engine we allocated one buffer */ - enet_dma_writel(priv, 1, ENETDMA_BUFALLOC_REG(priv->rx_chan)); + if (priv->dma_has_sram) + enet_dma_writel(priv, 1, ENETDMA_BUFALLOC_REG(priv->rx_chan)); + else + enet_dmac_writel(priv, 1, ENETDMAC_BUFALLOC, priv->rx_chan); } /* If rx ring is still empty, set a timer to try allocating @@ -349,7 +354,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) /* if the packet does not have start of packet _and_ * end of packet flag set, then just recycle it */ - if ((len_stat & DMADESC_ESOP_MASK) != DMADESC_ESOP_MASK) { + if ((len_stat & (DMADESC_ESOP_MASK >> priv->dma_desc_shift)) != + (DMADESC_ESOP_MASK >> priv->dma_desc_shift)) { dev->stats.rx_dropped++; continue; } @@ -410,8 +416,8 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget) bcm_enet_refill_rx(dev); /* kick rx dma */ - enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(priv->rx_chan)); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->rx_chan); } return processed; @@ -486,10 +492,10 @@ static int bcm_enet_poll(struct napi_struct *napi, int budget) dev = priv->net_dev; /* ack interrupts */ - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->rx_chan)); - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->tx_chan)); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IR, priv->rx_chan); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IR, priv->tx_chan); /* reclaim sent skb */ tx_work_done = bcm_enet_tx_reclaim(dev, 0); @@ -508,10 +514,10 @@ static int bcm_enet_poll(struct napi_struct *napi, int budget) napi_complete(napi); /* restore rx/tx interrupt */ - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IRMASK, priv->tx_chan); return rx_work_done; } @@ -554,8 +560,8 @@ static irqreturn_t bcm_enet_isr_dma(int irq, void *dev_id) priv = netdev_priv(dev); /* mask rx/tx interrupts */ - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan); napi_schedule(&priv->napi); @@ -616,14 +622,14 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) DMA_TO_DEVICE); len_stat = (skb->len << DMADESC_LENGTH_SHIFT) & DMADESC_LENGTH_MASK; - len_stat |= DMADESC_ESOP_MASK | + len_stat |= (DMADESC_ESOP_MASK >> priv->dma_desc_shift) | DMADESC_APPEND_CRC | DMADESC_OWNER_MASK; priv->tx_curr_desc++; if (priv->tx_curr_desc == priv->tx_ring_size) { priv->tx_curr_desc = 0; - len_stat |= DMADESC_WRAP_MASK; + len_stat |= (DMADESC_WRAP_MASK >> priv->dma_desc_shift); } priv->tx_desc_count--; @@ -634,8 +640,8 @@ static int bcm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) wmb(); /* kick tx dma */ - enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(priv->tx_chan)); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->tx_chan); /* stop queue if no more desc available */ if (!priv->tx_desc_count) @@ -763,6 +769,9 @@ static void bcm_enet_set_flow(struct bcm_enet_priv *priv, int rx_en, int tx_en) val &= ~ENET_RXCFG_ENFLOW_MASK; enet_writel(priv, val, ENET_RXCFG_REG); + if (!priv->dma_has_sram) + return; + /* tx flow control (pause frame generation) */ val = enet_dma_readl(priv, ENETDMA_CFG_REG); if (tx_en) @@ -910,8 +919,8 @@ static int bcm_enet_open(struct net_device *dev) /* mask all interrupts and request them */ enet_writel(priv, 0, ENET_IRMASK_REG); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan); ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev); if (ret) @@ -986,8 +995,12 @@ static int bcm_enet_open(struct net_device *dev) priv->rx_curr_desc = 0; /* initialize flow control buffer allocation */ - enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, - ENETDMA_BUFALLOC_REG(priv->rx_chan)); + if (priv->dma_has_sram) + enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, + ENETDMA_BUFALLOC_REG(priv->rx_chan)); + else + enet_dmac_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0, + ENETDMAC_BUFALLOC, priv->rx_chan); if (bcm_enet_refill_rx(dev)) { dev_err(kdev, "cannot allocate rx skb queue\n"); @@ -996,18 +1009,30 @@ static int bcm_enet_open(struct net_device *dev) } /* write rx & tx ring addresses */ - enet_dmas_writel(priv, priv->rx_desc_dma, - ENETDMAS_RSTART_REG(priv->rx_chan)); - enet_dmas_writel(priv, priv->tx_desc_dma, - ENETDMAS_RSTART_REG(priv->tx_chan)); + if (priv->dma_has_sram) { + enet_dmas_writel(priv, priv->rx_desc_dma, + ENETDMAS_RSTART_REG, priv->rx_chan); + enet_dmas_writel(priv, priv->tx_desc_dma, + ENETDMAS_RSTART_REG, priv->tx_chan); + } else { + enet_dmac_writel(priv, priv->rx_desc_dma, + ENETDMAC_RSTART, priv->rx_chan); + enet_dmac_writel(priv, priv->tx_desc_dma, + ENETDMAC_RSTART, priv->tx_chan); + } /* clear remaining state ram for rx & tx channel */ - enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan)); + if (priv->dma_has_sram) { + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->tx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->tx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->tx_chan); + } else { + enet_dmac_writel(priv, 0, ENETDMAC_FC, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_FC, priv->tx_chan); + } /* set max rx/tx length */ enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG); @@ -1015,18 +1040,24 @@ static int bcm_enet_open(struct net_device *dev) /* set dma maximum burst len */ enet_dmac_writel(priv, priv->dma_maxburst, - ENETDMAC_MAXBURST_REG(priv->rx_chan)); + ENETDMAC_MAXBURST, priv->rx_chan); enet_dmac_writel(priv, priv->dma_maxburst, - ENETDMAC_MAXBURST_REG(priv->tx_chan)); + ENETDMAC_MAXBURST, priv->tx_chan); /* set correct transmit fifo watermark */ enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG); /* set flow control low/high threshold to 1/3 / 2/3 */ - val = priv->rx_ring_size / 3; - enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan)); - val = (priv->rx_ring_size * 2) / 3; - enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan)); + if (priv->dma_has_sram) { + val = priv->rx_ring_size / 3; + enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan)); + val = (priv->rx_ring_size * 2) / 3; + enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan)); + } else { + enet_dmac_writel(priv, 5, ENETDMAC_FC, priv->rx_chan); + enet_dmac_writel(priv, priv->rx_ring_size, ENETDMAC_LEN, priv->rx_chan); + enet_dmac_writel(priv, priv->tx_ring_size, ENETDMAC_LEN, priv->tx_chan); + } /* all set, enable mac and interrupts, start dma engine and * kick rx dma channel */ @@ -1035,26 +1066,26 @@ static int bcm_enet_open(struct net_device *dev) val |= ENET_CTL_ENABLE_MASK; enet_writel(priv, val, ENET_CTL_REG); enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); - enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(priv->rx_chan)); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->rx_chan); /* watch "mib counters about to overflow" interrupt */ enet_writel(priv, ENET_IR_MIB, ENET_IR_REG); enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG); /* watch "packet transferred" interrupt in rx and tx */ - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->rx_chan)); - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->tx_chan)); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IR, priv->rx_chan); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IR, priv->tx_chan); /* make sure we enable napi before rx interrupt */ napi_enable(&priv->napi); - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, priv->dma_chan_int_mask, + ENETDMAC_IRMASK, priv->tx_chan); if (priv->has_phy) phy_start(priv->phydev); @@ -1134,13 +1165,13 @@ static void bcm_enet_disable_dma(struct bcm_enet_priv *priv, int chan) { int limit; - enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan)); + enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG, chan); limit = 1000; do { u32 val; - val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan)); + val = enet_dmac_readl(priv, ENETDMAC_CHANCFG, chan); if (!(val & ENETDMAC_CHANCFG_EN_MASK)) break; udelay(1); @@ -1167,8 +1198,8 @@ static int bcm_enet_stop(struct net_device *dev) /* mask all interrupts */ enet_writel(priv, 0, ENET_IRMASK_REG); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan); /* make sure no mib update is scheduled */ cancel_work_sync(&priv->mib_update_task); @@ -1782,6 +1813,11 @@ static int bcm_enet_probe(struct platform_device *pdev) priv->pause_tx = pd->pause_tx; priv->force_duplex_full = pd->force_duplex_full; priv->force_speed_100 = pd->force_speed_100; + priv->dma_chan_en_mask = pd->dma_chan_en_mask; + priv->dma_chan_int_mask = pd->dma_chan_int_mask; + priv->dma_chan_width = pd->dma_chan_width; + priv->dma_has_sram = pd->dma_has_sram; + priv->dma_desc_shift = pd->dma_desc_shift; } if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) { @@ -2118,8 +2154,8 @@ static int bcm_enetsw_open(struct net_device *dev) kdev = &priv->pdev->dev; /* mask all interrupts and request them */ - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan); ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED, dev->name, dev); @@ -2231,23 +2267,23 @@ static int bcm_enetsw_open(struct net_device *dev) /* write rx & tx ring addresses */ enet_dmas_writel(priv, priv->rx_desc_dma, - ENETDMAS_RSTART_REG(priv->rx_chan)); + ENETDMAS_RSTART_REG, priv->rx_chan); enet_dmas_writel(priv, priv->tx_desc_dma, - ENETDMAS_RSTART_REG(priv->tx_chan)); + ENETDMAS_RSTART_REG, priv->tx_chan); /* clear remaining state ram for rx & tx channel */ - enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan)); - enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan)); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG, priv->tx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG, priv->tx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->rx_chan); + enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG, priv->tx_chan); /* set dma maximum burst len */ enet_dmac_writel(priv, priv->dma_maxburst, - ENETDMAC_MAXBURST_REG(priv->rx_chan)); + ENETDMAC_MAXBURST, priv->rx_chan); enet_dmac_writel(priv, priv->dma_maxburst, - ENETDMAC_MAXBURST_REG(priv->tx_chan)); + ENETDMAC_MAXBURST, priv->tx_chan); /* set flow control low/high threshold to 1/3 / 2/3 */ val = priv->rx_ring_size / 3; @@ -2261,21 +2297,21 @@ static int bcm_enetsw_open(struct net_device *dev) wmb(); enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK, - ENETDMAC_CHANCFG_REG(priv->rx_chan)); + ENETDMAC_CHANCFG, priv->rx_chan); /* watch "packet transferred" interrupt in rx and tx */ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->rx_chan)); + ENETDMAC_IR, priv->rx_chan); enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IR_REG(priv->tx_chan)); + ENETDMAC_IR, priv->tx_chan); /* make sure we enable napi before rx interrupt */ napi_enable(&priv->napi); enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->rx_chan)); + ENETDMAC_IRMASK, priv->rx_chan); enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK, - ENETDMAC_IRMASK_REG(priv->tx_chan)); + ENETDMAC_IRMASK, priv->tx_chan); netif_carrier_on(dev); netif_start_queue(dev); @@ -2377,8 +2413,8 @@ static int bcm_enetsw_stop(struct net_device *dev) del_timer_sync(&priv->rx_timeout); /* mask all interrupts */ - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan)); - enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan)); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->rx_chan); + enet_dmac_writel(priv, 0, ENETDMAC_IRMASK, priv->tx_chan); /* disable dma & mac */ bcm_enet_disable_dma(priv, priv->tx_chan); @@ -2712,6 +2748,10 @@ static int bcm_enetsw_probe(struct platform_device *pdev) memcpy(priv->used_ports, pd->used_ports, sizeof(pd->used_ports)); priv->num_ports = pd->num_ports; + priv->dma_has_sram = pd->dma_has_sram; + priv->dma_chan_en_mask = pd->dma_chan_en_mask; + priv->dma_chan_int_mask = pd->dma_chan_int_mask; + priv->dma_chan_width = pd->dma_chan_width; } ret = compute_hw_mtu(priv, dev->mtu); diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.h b/drivers/net/ethernet/broadcom/bcm63xx_enet.h index 721ffbaef8d2..f55af4310085 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h @@ -339,6 +339,21 @@ struct bcm_enet_priv { /* used to poll switch port state */ struct timer_list swphy_poll; spinlock_t enetsw_mdio_lock; + + /* dma channel enable mask */ + u32 dma_chan_en_mask; + + /* dma channel interrupt mask */ + u32 dma_chan_int_mask; + + /* DMA engine has internal SRAM */ + bool dma_has_sram; + + /* dma channel width */ + unsigned int dma_chan_width; + + /* dma descriptor shift value */ + unsigned int dma_desc_shift; }; -- GitLab From 1d8faf48c74b8329a0322dc4b2a2030ae5003c86 Mon Sep 17 00:00:00 2001 From: Rony Efraim Date: Thu, 13 Jun 2013 13:19:10 +0300 Subject: [PATCH 1161/2900] net/core: Add VF link state control Add netlink directives and ndo entry to allow for controling VF link, which can be in one of three states: Auto - VF link state reflects the PF link state (default) Up - VF link state is up, traffic from VF to VF works even if the actual PF link is down Down - VF link state is down, no traffic from/to this VF, can be of use while configuring the VF Signed-off-by: Rony Efraim Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- include/linux/if_link.h | 1 + include/linux/netdevice.h | 3 +++ include/uapi/linux/if_link.h | 13 +++++++++++++ net/core/rtnetlink.c | 22 ++++++++++++++++++++-- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c3f817c3eb45..a86784dec3d3 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -12,5 +12,6 @@ struct ifla_vf_info { __u32 qos; __u32 tx_rate; __u32 spoofchk; + __u32 linkstate; }; #endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 8c9fcc42502a..09b4188c1ea7 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -829,6 +829,7 @@ struct netdev_fcoe_hbainfo { * int (*ndo_set_vf_spoofchk)(struct net_device *dev, int vf, bool setting); * int (*ndo_get_vf_config)(struct net_device *dev, * int vf, struct ifla_vf_info *ivf); + * int (*ndo_set_vf_link_state)(struct net_device *dev, int vf, int link_state); * int (*ndo_set_vf_port)(struct net_device *dev, int vf, * struct nlattr *port[]); * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb); @@ -986,6 +987,8 @@ struct net_device_ops { int (*ndo_get_vf_config)(struct net_device *dev, int vf, struct ifla_vf_info *ivf); + int (*ndo_set_vf_link_state)(struct net_device *dev, + int vf, int link_state); int (*ndo_set_vf_port)(struct net_device *dev, int vf, struct nlattr *port[]); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index da05a2698cb5..03f6170ab337 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -338,6 +338,7 @@ enum { IFLA_VF_VLAN, IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ + IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ __IFLA_VF_MAX, }; @@ -364,6 +365,18 @@ struct ifla_vf_spoofchk { __u32 setting; }; +enum { + IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE, /* link always up */ + IFLA_VF_LINK_STATE_DISABLE, /* link always down */ + __IFLA_VF_LINK_STATE_MAX, +}; + +struct ifla_vf_link_state { + __u32 vf; + __u32 link_state; +}; + /* VF ports management section * * Nested layout of set/get msg is: diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49c14451d8ab..9007533867f0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -947,6 +947,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, struct ifla_vf_vlan vf_vlan; struct ifla_vf_tx_rate vf_tx_rate; struct ifla_vf_spoofchk vf_spoofchk; + struct ifla_vf_link_state vf_linkstate; /* * Not all SR-IOV capable drivers support the @@ -956,18 +957,24 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, */ ivi.spoofchk = -1; memset(ivi.mac, 0, sizeof(ivi.mac)); + /* The default value for VF link state is "auto" + * IFLA_VF_LINK_STATE_AUTO which equals zero + */ + ivi.linkstate = 0; if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) break; vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = - vf_spoofchk.vf = ivi.vf; + vf_spoofchk.vf = + vf_linkstate.vf = ivi.vf; memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); vf_vlan.vlan = ivi.vlan; vf_vlan.qos = ivi.qos; vf_tx_rate.rate = ivi.tx_rate; vf_spoofchk.setting = ivi.spoofchk; + vf_linkstate.link_state = ivi.linkstate; vf = nla_nest_start(skb, IFLA_VF_INFO); if (!vf) { nla_nest_cancel(skb, vfinfo); @@ -978,7 +985,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, nla_put(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate) || nla_put(skb, IFLA_VF_SPOOFCHK, sizeof(vf_spoofchk), - &vf_spoofchk)) + &vf_spoofchk) || + nla_put(skb, IFLA_VF_LINK_STATE, sizeof(vf_linkstate), + &vf_linkstate)) goto nla_put_failure; nla_nest_end(skb, vf); } @@ -1238,6 +1247,15 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) ivs->setting); break; } + case IFLA_VF_LINK_STATE: { + struct ifla_vf_link_state *ivl; + ivl = nla_data(vf); + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_link_state) + err = ops->ndo_set_vf_link_state(dev, ivl->vf, + ivl->link_state); + break; + } default: err = -EINVAL; break; -- GitLab From 948e306d7d645af80ea331b60495710fe4fe12bb Mon Sep 17 00:00:00 2001 From: Rony Efraim Date: Thu, 13 Jun 2013 13:19:11 +0300 Subject: [PATCH 1162/2900] net/mlx4: Add VF link state support Add support to change the link state of VF (vPort) Signed-off-by: Rony Efraim Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 48 +++++++++++++++++++ .../net/ethernet/mellanox/mlx4/en_netdev.c | 8 ++++ drivers/net/ethernet/mellanox/mlx4/eq.c | 9 +++- drivers/net/ethernet/mellanox/mlx4/fw.c | 8 ++++ drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 + include/linux/mlx4/cmd.h | 2 +- 6 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 0e572a527154..ea1e03896353 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -2178,7 +2179,54 @@ int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_in ivf->qos = s_info->default_qos; ivf->tx_rate = s_info->tx_rate; ivf->spoofchk = s_info->spoofchk; + ivf->linkstate = s_info->link_state; return 0; } EXPORT_SYMBOL_GPL(mlx4_get_vf_config); + +int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + struct mlx4_vport_state *s_info; + struct mlx4_vport_oper_state *vp_oper; + int slave; + u8 link_stat_event; + + slave = mlx4_get_slave_indx(dev, vf); + if (slave < 0) + return -EINVAL; + + switch (link_state) { + case IFLA_VF_LINK_STATE_AUTO: + /* get current link state */ + if (!priv->sense.do_sense_port[port]) + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; + else + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; + break; + + case IFLA_VF_LINK_STATE_ENABLE: + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE; + break; + + case IFLA_VF_LINK_STATE_DISABLE: + link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN; + break; + + default: + mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n", + link_state, slave, port); + return -EINVAL; + }; + /* update the admin & oper state on the link state */ + s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; + vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; + s_info->link_state = link_state; + vp_oper->state.link_state = link_state; + + /* send event */ + mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event); + return 0; +} +EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 89c47ea84b50..ade276cca0e6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2061,6 +2061,13 @@ static int mlx4_en_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_ return mlx4_get_vf_config(mdev->dev, en_priv->port, vf, ivf); } +static int mlx4_en_set_vf_link_state(struct net_device *dev, int vf, int link_state) +{ + struct mlx4_en_priv *en_priv = netdev_priv(dev); + struct mlx4_en_dev *mdev = en_priv->mdev; + + return mlx4_set_vf_link_state(mdev->dev, en_priv->port, vf, link_state); +} static const struct net_device_ops mlx4_netdev_ops = { .ndo_open = mlx4_en_open, .ndo_stop = mlx4_en_close, @@ -2101,6 +2108,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = { .ndo_set_vf_mac = mlx4_en_set_vf_mac, .ndo_set_vf_vlan = mlx4_en_set_vf_vlan, .ndo_set_vf_spoofchk = mlx4_en_set_vf_spoofchk, + .ndo_set_vf_link_state = mlx4_en_set_vf_link_state, .ndo_get_vf_config = mlx4_en_get_vf_config, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = mlx4_en_netpoll, diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 6000342f9725..7e042869ef0c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -448,6 +448,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) int i; enum slave_port_gen_event gen_event; unsigned long flags; + struct mlx4_vport_state *s_info; while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) { /* @@ -556,7 +557,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN" " to slave: %d, port:%d\n", __func__, i, port); - mlx4_slave_event(dev, i, eqe); + s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) + mlx4_slave_event(dev, i, eqe); } else { /* IB port */ set_and_calc_slave_port_state(dev, i, port, MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN, @@ -580,7 +583,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) for (i = 0; i < dev->num_slaves; i++) { if (i == mlx4_master_func_num(dev)) continue; - mlx4_slave_event(dev, i, eqe); + s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state; + if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) + mlx4_slave_event(dev, i, eqe); } else /* IB port */ /* port-up event will be sent to a slave when the diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 2c97901c6a6d..569bbe3e7403 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -830,8 +830,10 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, u8 port_type; u16 short_field; int err; + int admin_link_state; #define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0 +#define MLX4_PORT_LINK_UP_MASK 0x80 #define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c #define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e @@ -861,6 +863,12 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, /* set port type to currently operating port type */ port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3); + admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state; + if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state) + port_type |= MLX4_PORT_LINK_UP_MASK; + else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state) + port_type &= ~MLX4_PORT_LINK_UP_MASK; + MLX4_PUT(outbox->buf, port_type, QUERY_PORT_SUPPORTED_TYPE_OFFSET); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index df15bb6631cc..75272935a3f7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -482,6 +482,7 @@ struct mlx4_vport_state { u8 default_qos; u32 tx_rate; bool spoofchk; + u32 link_state; }; struct mlx4_vf_admin_state { diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index adf6e0648f20..8074a9711cf1 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -237,7 +237,7 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac); int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos); int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting); int mlx4_get_vf_config(struct mlx4_dev *dev, int port, int vf, struct ifla_vf_info *ivf); - +int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state); #define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8) -- GitLab From 33ce6a87f2aba790429ac228288edc0e410143a2 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:54 -0700 Subject: [PATCH 1163/2900] target: Add register_type and preempt_type enums to clarify code core_scsi3_enulate_pro_register took an 'ignore_key' parameter that really distinguished between REGISTER and REGISTER_AND_IGNORE_EXISTING_KEY registration types, which was a little confusing. Same situation for PREEMPT and PREEMPT_AND_ABORT. Use enums to add a little more descriptiveness to the code. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 77 +++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 3240f2cc81ef..a081145cd1c7 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -65,6 +65,17 @@ int core_pr_dump_initiator_port( return 1; } +enum register_type { + REGISTER, + REGISTER_AND_IGNORE_EXISTING_KEY, + REGISTER_AND_MOVE, +}; + +enum preempt_type { + PREEMPT, + PREEMPT_AND_ABORT, +}; + static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, struct t10_pr_registration *, int); @@ -869,7 +880,7 @@ static void core_scsi3_aptpl_reserve( } static void __core_scsi3_add_registration(struct se_device *, struct se_node_acl *, - struct t10_pr_registration *, int, int); + struct t10_pr_registration *, enum register_type, int); static int __core_scsi3_check_aptpl_registration( struct se_device *dev, @@ -962,7 +973,7 @@ static void __core_scsi3_dump_registration( struct se_device *dev, struct se_node_acl *nacl, struct t10_pr_registration *pr_reg, - int register_type) + enum register_type register_type) { struct se_portal_group *se_tpg = nacl->se_tpg; char i_buf[PR_REG_ISID_ID_LEN]; @@ -973,8 +984,8 @@ static void __core_scsi3_dump_registration( PR_REG_ISID_ID_LEN); pr_debug("SPC-3 PR [%s] Service Action: REGISTER%s Initiator" - " Node: %s%s\n", tfo->get_fabric_name(), (register_type == 2) ? - "_AND_MOVE" : (register_type == 1) ? + " Node: %s%s\n", tfo->get_fabric_name(), (register_type == REGISTER_AND_MOVE) ? + "_AND_MOVE" : (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "", nacl->initiatorname, (prf_isid) ? i_buf : ""); pr_debug("SPC-3 PR [%s] registration on Target Port: %s,0x%04x\n", @@ -998,7 +1009,7 @@ static void __core_scsi3_add_registration( struct se_device *dev, struct se_node_acl *nacl, struct t10_pr_registration *pr_reg, - int register_type, + enum register_type register_type, int register_move) { struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; @@ -1064,7 +1075,7 @@ static int core_scsi3_alloc_registration( u64 sa_res_key, int all_tg_pt, int aptpl, - int register_type, + enum register_type register_type, int register_move) { struct t10_pr_registration *pr_reg; @@ -2030,7 +2041,7 @@ core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, static sense_reason_t core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, - int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key) + int aptpl, int all_tg_pt, int spec_i_pt, enum register_type register_type) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; @@ -2083,7 +2094,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, if (core_scsi3_alloc_registration(cmd->se_dev, se_sess->se_node_acl, se_deve, isid_ptr, sa_res_key, all_tg_pt, aptpl, - ignore_key, 0)) { + register_type, 0)) { pr_err("Unable to allocate" " struct t10_pr_registration\n"); return TCM_INVALID_PARAMETER_LIST; @@ -2136,7 +2147,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, pr_reg = pr_reg_e; type = pr_reg->pr_res_type; - if (!ignore_key) { + if (register_type == REGISTER) { if (res_key != pr_reg->pr_res_key) { pr_err("SPC-3 PR REGISTER: Received" " res_key: 0x%016Lx does not match" @@ -2280,7 +2291,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" " Key for %s to: 0x%016Lx PRgeneration:" " 0x%08x\n", cmd->se_tfo->get_fabric_name(), - (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "", + (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "", pr_reg->pr_reg_nacl->initiatorname, pr_reg->pr_res_key, pr_reg->pr_res_generation); @@ -2810,7 +2821,7 @@ static void __core_scsi3_complete_pro_preempt( struct list_head *preempt_and_abort_list, int type, int scope, - int abort) + enum preempt_type preempt_type) { struct se_node_acl *nacl = pr_reg->pr_reg_nacl; struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; @@ -2834,11 +2845,11 @@ static void __core_scsi3_complete_pro_preempt( pr_debug("SPC-3 PR [%s] Service Action: PREEMPT%s created new" " reservation holder TYPE: %s ALL_TG_PT: %d\n", - tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "", + tfo->get_fabric_name(), (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "", core_scsi3_pr_dump_type(type), (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); pr_debug("SPC-3 PR [%s] PREEMPT%s from Node: %s%s\n", - tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "", + tfo->get_fabric_name(), (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "", nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); /* * For PREEMPT_AND_ABORT, add the preempting reservation's @@ -2876,7 +2887,7 @@ static void core_scsi3_release_preempt_and_abort( static sense_reason_t core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, - u64 sa_res_key, int abort) + u64 sa_res_key, enum preempt_type preempt_type) { struct se_device *dev = cmd->se_dev; struct se_node_acl *pr_reg_nacl; @@ -2896,7 +2907,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, if (!pr_reg_n) { pr_err("SPC-3 PR: Unable to locate" " PR_REGISTERED *pr_reg for PREEMPT%s\n", - (abort) ? "_AND_ABORT" : ""); + (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); return TCM_RESERVATION_CONFLICT; } if (pr_reg_n->pr_res_key != res_key) { @@ -2965,7 +2976,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, pr_reg_nacl = pr_reg->pr_reg_nacl; pr_res_mapped_lun = pr_reg->pr_res_mapped_lun; __core_scsi3_free_registration(dev, pr_reg, - (abort) ? &preempt_and_abort_list : + (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, calling_it_nexus); released_regs++; } else { @@ -2993,7 +3004,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, pr_reg_nacl = pr_reg->pr_reg_nacl; pr_res_mapped_lun = pr_reg->pr_res_mapped_lun; __core_scsi3_free_registration(dev, pr_reg, - (abort) ? &preempt_and_abort_list : + (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, 0); released_regs++; } @@ -3022,10 +3033,10 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, */ if (pr_res_holder && all_reg && !(sa_res_key)) { __core_scsi3_complete_pro_preempt(dev, pr_reg_n, - (abort) ? &preempt_and_abort_list : NULL, - type, scope, abort); + (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, + type, scope, preempt_type); - if (abort) + if (preempt_type == PREEMPT_AND_ABORT) core_scsi3_release_preempt_and_abort( &preempt_and_abort_list, pr_reg_n); } @@ -3036,7 +3047,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, &pr_reg_n->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL" - " metadata for PREEMPT%s\n", (abort) ? + " metadata for PREEMPT%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); } } @@ -3103,7 +3114,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, pr_reg_nacl = pr_reg->pr_reg_nacl; pr_res_mapped_lun = pr_reg->pr_res_mapped_lun; __core_scsi3_free_registration(dev, pr_reg, - (abort) ? &preempt_and_abort_list : NULL, + (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, calling_it_nexus); /* * e) Establish a unit attention condition for the initiator @@ -3120,8 +3131,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, * I_T nexus using the contents of the SCOPE and TYPE fields; */ __core_scsi3_complete_pro_preempt(dev, pr_reg_n, - (abort) ? &preempt_and_abort_list : NULL, - type, scope, abort); + (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL, + type, scope, preempt_type); /* * d) Process tasks as defined in 5.7.1; * e) See above.. @@ -3161,7 +3172,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, * been removed from the primary pr_reg list), except the * new persistent reservation holder, the calling Initiator Port. */ - if (abort) { + if (preempt_type == PREEMPT_AND_ABORT) { core_tmr_lun_reset(dev, NULL, &preempt_and_abort_list, cmd); core_scsi3_release_preempt_and_abort(&preempt_and_abort_list, pr_reg_n); @@ -3172,7 +3183,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, &pr_reg_n->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" - "%s\n", abort ? "_AND_ABORT" : ""); + "%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); } } @@ -3183,7 +3194,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, static sense_reason_t core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, - u64 res_key, u64 sa_res_key, int abort) + u64 res_key, u64 sa_res_key, enum preempt_type preempt_type) { switch (type) { case PR_TYPE_WRITE_EXCLUSIVE: @@ -3193,10 +3204,10 @@ core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope, case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: return core_scsi3_pro_preempt(cmd, type, scope, res_key, - sa_res_key, abort); + sa_res_key, preempt_type); default: pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s" - " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type); + " Type: 0x%02x\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "", type); return TCM_INVALID_CDB_FIELD; } } @@ -3752,7 +3763,7 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) switch (sa) { case PRO_REGISTER: ret = core_scsi3_emulate_pro_register(cmd, - res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 0); + res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt, REGISTER); break; case PRO_RESERVE: ret = core_scsi3_emulate_pro_reserve(cmd, type, scope, res_key); @@ -3765,15 +3776,15 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd) break; case PRO_PREEMPT: ret = core_scsi3_emulate_pro_preempt(cmd, type, scope, - res_key, sa_res_key, 0); + res_key, sa_res_key, PREEMPT); break; case PRO_PREEMPT_AND_ABORT: ret = core_scsi3_emulate_pro_preempt(cmd, type, scope, - res_key, sa_res_key, 1); + res_key, sa_res_key, PREEMPT_AND_ABORT); break; case PRO_REGISTER_AND_IGNORE_EXISTING_KEY: ret = core_scsi3_emulate_pro_register(cmd, - 0, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 1); + 0, sa_res_key, aptpl, all_tg_pt, spec_i_pt, REGISTER_AND_IGNORE_EXISTING_KEY); break; case PRO_REGISTER_AND_MOVE: ret = core_scsi3_emulate_pro_register_and_move(cmd, res_key, -- GitLab From d2843c173ee53cf4c12e7dfedc069a5bc76f0ac5 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:55 -0700 Subject: [PATCH 1164/2900] target: Alter core_pr_dump_initiator_port for ease of use We use this function exclusively in debug prints. Instead of returning 0 or 1 if isid is present, just set buf to "" if it isn't there. This saves callers from having to check the return value. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_configfs.c | 13 +++--- drivers/target/target_core_pr.c | 58 ++++++++++----------------- drivers/target/target_core_pr.h | 2 +- 3 files changed, 27 insertions(+), 46 deletions(-) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 4a8bd36d3958..e4d22933efaf 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -983,7 +983,6 @@ static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, struct se_node_acl *se_nacl; struct t10_pr_registration *pr_reg; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); @@ -992,12 +991,11 @@ static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev, return sprintf(page, "No SPC-3 Reservation holder\n"); se_nacl = pr_reg->pr_reg_nacl; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n", se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(), - se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); + se_nacl->initiatorname, i_buf); } static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev, @@ -1116,7 +1114,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( unsigned char buf[384]; char i_buf[PR_REG_ISID_ID_LEN]; ssize_t len = 0; - int reg_count = 0, prf_isid; + int reg_count = 0; len += sprintf(page+len, "SPC-3 PR Registrations:\n"); @@ -1127,12 +1125,11 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts( memset(buf, 0, 384); memset(i_buf, 0, PR_REG_ISID_ID_LEN); tfo = pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); sprintf(buf, "%s Node: %s%s Key: 0x%016Lx PRgen: 0x%08x\n", tfo->get_fabric_name(), - pr_reg->pr_reg_nacl->initiatorname, (prf_isid) ? - &i_buf[0] : "", pr_reg->pr_res_key, + pr_reg->pr_reg_nacl->initiatorname, i_buf, pr_reg->pr_res_key, pr_reg->pr_res_generation); if (len + strlen(buf) >= PAGE_SIZE) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index a081145cd1c7..f776368d727a 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -53,16 +53,15 @@ struct pr_transport_id_holder { struct list_head dest_list; }; -int core_pr_dump_initiator_port( +void core_pr_dump_initiator_port( struct t10_pr_registration *pr_reg, char *buf, u32 size) { if (!pr_reg->isid_present_at_reg) - return 0; + buf[0] = '\0'; - snprintf(buf, size, ",i,0x%s", &pr_reg->pr_reg_isid[0]); - return 1; + snprintf(buf, size, ",i,0x%s", pr_reg->pr_reg_isid); } enum register_type { @@ -859,11 +858,9 @@ static void core_scsi3_aptpl_reserve( struct t10_pr_registration *pr_reg) { char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); spin_lock(&dev->dev_reservation_lock); dev->dev_pr_res_holder = pr_reg; @@ -876,7 +873,7 @@ static void core_scsi3_aptpl_reserve( (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n", tpg->se_tpg_tfo->get_fabric_name(), node_acl->initiatorname, - (prf_isid) ? &i_buf[0] : ""); + i_buf); } static void __core_scsi3_add_registration(struct se_device *, struct se_node_acl *, @@ -977,17 +974,15 @@ static void __core_scsi3_dump_registration( { struct se_portal_group *se_tpg = nacl->se_tpg; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(&i_buf[0], 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); pr_debug("SPC-3 PR [%s] Service Action: REGISTER%s Initiator" " Node: %s%s\n", tfo->get_fabric_name(), (register_type == REGISTER_AND_MOVE) ? "_AND_MOVE" : (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "", nacl->initiatorname, - (prf_isid) ? i_buf : ""); + i_buf); pr_debug("SPC-3 PR [%s] registration on Target Port: %s,0x%04x\n", tfo->get_fabric_name(), tfo->tpg_get_wwn(se_tpg), tfo->tpg_get_tag(se_tpg)); @@ -1236,11 +1231,9 @@ static void __core_scsi3_free_registration( pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo; struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); pr_reg->pr_reg_deve->def_pr_registered = 0; pr_reg->pr_reg_deve->pr_res_key = 0; @@ -1268,7 +1261,7 @@ static void __core_scsi3_free_registration( pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator" " Node: %s%s\n", tfo->get_fabric_name(), pr_reg->pr_reg_nacl->initiatorname, - (prf_isid) ? &i_buf[0] : ""); + i_buf); pr_debug("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target" " Port(s)\n", tfo->get_fabric_name(), (pr_reg->pr_reg_all_tg_pt) ? "ALL" : "SINGLE", @@ -1464,7 +1457,7 @@ core_scsi3_decode_spec_i_port( char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; sense_reason_t ret; u32 tpdl, tid_len = 0; - int dest_local_nexus, prf_isid; + int dest_local_nexus; u32 dest_rtpi = 0; memset(dest_iport, 0, 64); @@ -1775,8 +1768,7 @@ core_scsi3_decode_spec_i_port( kfree(tidh); memset(i_buf, 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(dest_pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(dest_pr_reg, i_buf, PR_REG_ISID_ID_LEN); __core_scsi3_add_registration(cmd->se_dev, dest_node_acl, dest_pr_reg, 0, 0); @@ -1784,8 +1776,7 @@ core_scsi3_decode_spec_i_port( pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully" " registered Transport ID for Node: %s%s Mapped LUN:" " %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(), - dest_node_acl->initiatorname, (prf_isid) ? - &i_buf[0] : "", dest_se_deve->mapped_lun); + dest_node_acl->initiatorname, i_buf, dest_se_deve->mapped_lun); if (dest_local_nexus) continue; @@ -2351,7 +2342,6 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) struct t10_reservation *pr_tmpl = &dev->t10_pr; char i_buf[PR_REG_ISID_ID_LEN]; sense_reason_t ret; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); @@ -2477,8 +2467,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) pr_reg->pr_res_type = type; pr_reg->pr_res_holder = 1; dev->dev_pr_res_holder = pr_reg; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); pr_debug("SPC-3 PR [%s] Service Action: RESERVE created new" " reservation holder TYPE: %s ALL_TG_PT: %d\n", @@ -2487,7 +2476,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n", cmd->se_tfo->get_fabric_name(), se_sess->se_node_acl->initiatorname, - (prf_isid) ? &i_buf[0] : ""); + i_buf); spin_unlock(&dev->dev_reservation_lock); if (pr_tmpl->pr_aptpl_active) { @@ -2535,11 +2524,9 @@ static void __core_scsi3_complete_pro_release( { struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); /* * Go ahead and release the current PR reservation holder. */ @@ -2552,7 +2539,7 @@ static void __core_scsi3_complete_pro_release( (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", tfo->get_fabric_name(), se_nacl->initiatorname, - (prf_isid) ? &i_buf[0] : ""); + i_buf); /* * Clear TYPE and SCOPE for the next PROUT Service Action: RESERVE */ @@ -2826,11 +2813,9 @@ static void __core_scsi3_complete_pro_preempt( struct se_node_acl *nacl = pr_reg->pr_reg_nacl; struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; char i_buf[PR_REG_ISID_ID_LEN]; - int prf_isid; memset(i_buf, 0, PR_REG_ISID_ID_LEN); - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); /* * Do an implict RELEASE of the existing reservation. */ @@ -2850,7 +2835,7 @@ static void __core_scsi3_complete_pro_preempt( (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); pr_debug("SPC-3 PR [%s] PREEMPT%s from Node: %s%s\n", tfo->get_fabric_name(), (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "", - nacl->initiatorname, (prf_isid) ? &i_buf[0] : ""); + nacl->initiatorname, i_buf); /* * For PREEMPT_AND_ABORT, add the preempting reservation's * struct t10_pr_registration to the list that will be compared @@ -3231,7 +3216,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, unsigned char *initiator_str; char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN]; u32 tid_len, tmp_tid_len; - int new_reg = 0, type, scope, matching_iname, prf_isid; + int new_reg = 0, type, scope, matching_iname; sense_reason_t ret; unsigned short rtpi; unsigned char proto_ident; @@ -3575,8 +3560,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, dest_pr_reg->pr_res_holder = 1; dest_pr_reg->pr_res_type = type; pr_reg->pr_res_scope = scope; - prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0], - PR_REG_ISID_ID_LEN); + core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); /* * Increment PRGeneration for existing registrations.. */ @@ -3592,7 +3576,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, pr_debug("SPC-3 PR Successfully moved reservation from" " %s Fabric Node: %s%s -> %s Fabric Node: %s %s\n", tf_ops->get_fabric_name(), pr_reg_nacl->initiatorname, - (prf_isid) ? &i_buf[0] : "", dest_tf_ops->get_fabric_name(), + i_buf, dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname, (iport_ptr != NULL) ? iport_ptr : ""); /* diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h index b4a004247ab2..ed75cdd32cb0 100644 --- a/drivers/target/target_core_pr.h +++ b/drivers/target/target_core_pr.h @@ -45,7 +45,7 @@ extern struct kmem_cache *t10_pr_reg_cache; -extern int core_pr_dump_initiator_port(struct t10_pr_registration *, +extern void core_pr_dump_initiator_port(struct t10_pr_registration *, char *, u32); extern sense_reason_t target_scsi2_reservation_release(struct se_cmd *); extern sense_reason_t target_scsi2_reservation_reserve(struct se_cmd *); -- GitLab From 1f070cc2ac7783afd0174c29dc59d2b4fac72646 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:56 -0700 Subject: [PATCH 1165/2900] target: Fix two debugprints that appear to be wrong They're in emulate_pro_register, so change UNREGISTER to REGISTER. The first one seems wrong -- sa_res_key could be 0 there, but it's testing spec_i_pt. Remove unneeded parens in 2nd conditional. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index f776368d727a..c797e79dc5c1 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2151,8 +2151,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, } if (spec_i_pt) { - pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT" - " set while sa_res_key=0\n"); + pr_err("SPC-3 PR REGISTER: SPEC_I_PT" + " set on a registered nexus\n"); ret = TCM_INVALID_PARAMETER_LIST; goto out_put_pr_reg; } @@ -2161,8 +2161,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, * An existing ALL_TG_PT=1 registration being released * must also set ALL_TG_PT=1 in the incoming PROUT. */ - if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) { - pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1" + if (pr_reg->pr_reg_all_tg_pt && !all_tg_pt) { + pr_err("SPC-3 PR REGISTER: ALL_TG_PT=1" " registration exists, but ALL_TG_PT=1 bit not" " present in received PROUT\n"); ret = TCM_INVALID_CDB_FIELD; -- GitLab From 0607decdca51ee33c2caae288a44a82455149b51 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:57 -0700 Subject: [PATCH 1166/2900] target: Simplify metadata handling when clearing aptpl metadata Simpler to just set buf in update_and_write_aptpl(), rather than passing down to ____core_scsi3_update_aptpl_buf(). Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 39 ++++++++------------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index c797e79dc5c1..2e10014c8c33 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1834,8 +1834,7 @@ core_scsi3_decode_spec_i_port( static int __core_scsi3_update_aptpl_buf( struct se_device *dev, unsigned char *buf, - u32 pr_aptpl_buf_len, - int clear_aptpl_metadata) + u32 pr_aptpl_buf_len) { struct se_lun *lun; struct se_portal_group *tpg; @@ -1845,14 +1844,7 @@ static int __core_scsi3_update_aptpl_buf( int reg_count = 0; memset(buf, 0, pr_aptpl_buf_len); - /* - * Called to clear metadata once APTPL has been deactivated. - */ - if (clear_aptpl_metadata) { - snprintf(buf, pr_aptpl_buf_len, - "No Registrations or Reservations\n"); - return 0; - } + /* * Walk the registration list.. */ @@ -1937,14 +1929,12 @@ static int __core_scsi3_update_aptpl_buf( static int core_scsi3_update_aptpl_buf( struct se_device *dev, unsigned char *buf, - u32 pr_aptpl_buf_len, - int clear_aptpl_metadata) + u32 pr_aptpl_buf_len) { int ret; spin_lock(&dev->dev_reservation_lock); - ret = __core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len, - clear_aptpl_metadata); + ret = __core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len); spin_unlock(&dev->dev_reservation_lock); return ret; @@ -1997,32 +1987,21 @@ core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, u32 in_pr_aptpl_buf_len) { unsigned char null_buf[64], *buf; - u32 pr_aptpl_buf_len; - int clear_aptpl_metadata = 0; int ret; /* * Can be called with a NULL pointer from PROUT service action CLEAR */ if (!in_buf) { - memset(null_buf, 0, 64); - buf = &null_buf[0]; - /* - * This will clear the APTPL metadata to: - * "No Registrations or Reservations" status - */ - pr_aptpl_buf_len = 64; - clear_aptpl_metadata = 1; + snprintf(null_buf, 64, "No Registrations or Reservations\n"); + buf = null_buf; } else { + ret = core_scsi3_update_aptpl_buf(dev, in_buf, in_pr_aptpl_buf_len); + if (ret != 0) + return ret; buf = in_buf; - pr_aptpl_buf_len = in_pr_aptpl_buf_len; } - ret = core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len, - clear_aptpl_metadata); - if (ret != 0) - return ret; - /* * __core_scsi3_write_aptpl_to_file() will call strlen() * on the passed buf to determine pr_aptpl_buf_len. -- GitLab From 3c8a6228d078553e32bffc59ed180d01ab1d998a Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:58 -0700 Subject: [PATCH 1167/2900] target: Unify __core_scsi3_update_aptpl_buf and core_scsi3_update_aptpl_buf The __ version is only ever called from the regular version, so just inline it. It's not too much more complex to handle both spinlocks in the same function. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 2e10014c8c33..548fc2a4a7bf 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1828,10 +1828,7 @@ core_scsi3_decode_spec_i_port( return ret; } -/* - * Called with struct se_device->dev_reservation_lock held - */ -static int __core_scsi3_update_aptpl_buf( +static int core_scsi3_update_aptpl_buf( struct se_device *dev, unsigned char *buf, u32 pr_aptpl_buf_len) @@ -1842,13 +1839,15 @@ static int __core_scsi3_update_aptpl_buf( unsigned char tmp[512], isid_buf[32]; ssize_t len = 0; int reg_count = 0; + int ret = 0; memset(buf, 0, pr_aptpl_buf_len); + spin_lock(&dev->dev_reservation_lock); + spin_lock(&dev->t10_pr.registration_lock); /* * Walk the registration list.. */ - spin_lock(&dev->t10_pr.registration_lock); list_for_each_entry(pr_reg, &dev->t10_pr.registration_list, pr_reg_list) { @@ -1894,8 +1893,8 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&dev->t10_pr.registration_lock); - return -EMSGSIZE; + ret = -EMSGSIZE; + goto out; } len += sprintf(buf+len, "%s", tmp); @@ -1912,29 +1911,18 @@ static int __core_scsi3_update_aptpl_buf( if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { pr_err("Unable to update renaming" " APTPL metadata\n"); - spin_unlock(&dev->t10_pr.registration_lock); - return -EMSGSIZE; + ret = -EMSGSIZE; + goto out; } len += sprintf(buf+len, "%s", tmp); reg_count++; } - spin_unlock(&dev->t10_pr.registration_lock); if (!reg_count) len += sprintf(buf+len, "No Registrations or Reservations"); - return 0; -} - -static int core_scsi3_update_aptpl_buf( - struct se_device *dev, - unsigned char *buf, - u32 pr_aptpl_buf_len) -{ - int ret; - - spin_lock(&dev->dev_reservation_lock); - ret = __core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len); +out: + spin_unlock(&dev->t10_pr.registration_lock); spin_unlock(&dev->dev_reservation_lock); return ret; -- GitLab From 4e529be27d0ec4b9c6e4fd1b2908fa21b28539b1 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:40:59 -0700 Subject: [PATCH 1168/2900] target: Remove t10_reservation.pr_aptpl_buf_len It's only ever set to PR_APTPL_BUF_LEN, so we don't need a variable. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 1 - drivers/target/target_core_pr.c | 31 ++++++++++------------------- include/target/target_core_base.h | 2 -- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 4630481b6043..ed679c9420c5 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1410,7 +1410,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) INIT_LIST_HEAD(&dev->t10_alua.tg_pt_gps_list); spin_lock_init(&dev->t10_alua.tg_pt_gps_lock); - dev->t10_pr.pr_aptpl_buf_len = PR_APTPL_BUF_LEN; dev->t10_wwn.t10_dev = dev; dev->t10_alua.t10_dev = dev; diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 548fc2a4a7bf..157368429a51 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -606,8 +606,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( return NULL; } - pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len, - GFP_ATOMIC); + pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_ATOMIC); if (!pr_reg->pr_aptpl_buf) { pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); kmem_cache_free(t10_pr_reg_cache, pr_reg); @@ -804,7 +803,7 @@ int core_scsi3_alloc_aptpl_registration( pr_err("Unable to allocate struct t10_pr_registration\n"); return -ENOMEM; } - pr_reg->pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, GFP_KERNEL); + pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); INIT_LIST_HEAD(&pr_reg->pr_reg_list); INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list); @@ -2090,8 +2089,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, se_sess->se_node_acl, se_sess); if (core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); } @@ -2140,8 +2138,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, * Allocate APTPL metadata buffer used for UNREGISTER ops */ if (aptpl) { - pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, - GFP_KERNEL); + pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); if (!pr_aptpl_buf) { pr_err("Unable to allocate" " pr_aptpl_buf\n"); @@ -2229,8 +2226,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, return 0; } - if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated" " for UNREGISTER\n"); @@ -2262,8 +2258,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, goto out_put_pr_reg; } - if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_tmpl->pr_aptpl_active = 1; pr_debug("SPC-3 PR: Set APTPL Bit Activated" " for REGISTER\n"); @@ -2448,8 +2443,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) if (pr_tmpl->pr_aptpl_active) { if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_debug("SPC-3 PR: Updated APTPL metadata" " for RESERVE\n"); } @@ -2669,7 +2663,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, write_aptpl: if (pr_tmpl->pr_aptpl_active) { if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) { + pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); } } @@ -2996,8 +2990,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, if (pr_tmpl->pr_aptpl_active) { if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_debug("SPC-3 PR: Updated APTPL" " metadata for PREEMPT%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); @@ -3132,8 +3125,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, if (pr_tmpl->pr_aptpl_active) { if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - &pr_reg_n->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" "%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); } @@ -3576,8 +3568,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, } else { pr_tmpl->pr_aptpl_active = 1; if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - &dest_pr_reg->pr_aptpl_buf[0], - pr_tmpl->pr_aptpl_buf_len)) { + dest_pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { pr_debug("SPC-3 PR: Set APTPL Bit Activated for" " REGISTER_AND_MOVE\n"); } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 4ea4f985f394..5976dc3e4066 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -374,9 +374,7 @@ struct t10_reservation { /* Activate Persistence across Target Power Loss enabled * for SCSI device */ int pr_aptpl_active; - /* Used by struct t10_reservation->pr_aptpl_buf_len */ #define PR_APTPL_BUF_LEN 8192 - u32 pr_aptpl_buf_len; u32 pr_generation; spinlock_t registration_lock; spinlock_t aptpl_reg_lock; -- GitLab From 4dee96fb366ec6b5b324c8d4fe9e04244cb32f5d Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:41:00 -0700 Subject: [PATCH 1169/2900] target: Remove unneeded param pr_aptpl_buf_len to write_aptpl_to_file() As mentioned in the comments in update_and_write_aptpl, write_aptpl_to_file() calls strlen() on the buffer, and the length was always being passed as zero. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 157368429a51..26c1f2d8920f 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1932,13 +1932,13 @@ static int core_scsi3_update_aptpl_buf( */ static int __core_scsi3_write_aptpl_to_file( struct se_device *dev, - unsigned char *buf, - u32 pr_aptpl_buf_len) + unsigned char *buf) { struct t10_wwn *wwn = &dev->t10_wwn; struct file *file; int flags = O_RDWR | O_CREAT | O_TRUNC; char path[512]; + u32 pr_aptpl_buf_len; int ret; memset(path, 0, 512); @@ -1957,8 +1957,7 @@ static int __core_scsi3_write_aptpl_to_file( return PTR_ERR(file); } - if (!pr_aptpl_buf_len) - pr_aptpl_buf_len = (strlen(&buf[0]) + 1); /* Add extra for NULL */ + pr_aptpl_buf_len = (strlen(buf) + 1); /* Add extra for NULL */ ret = kernel_write(file, buf, pr_aptpl_buf_len, 0); @@ -1993,7 +1992,7 @@ core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, * __core_scsi3_write_aptpl_to_file() will call strlen() * on the passed buf to determine pr_aptpl_buf_len. */ - return __core_scsi3_write_aptpl_to_file(dev, buf, 0); + return __core_scsi3_write_aptpl_to_file(dev, buf); } static sense_reason_t -- GitLab From 63e03349f5fb32e4e8494cb184c37d2db0bdd223 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:41:01 -0700 Subject: [PATCH 1170/2900] target: Delete incorrect comment aptpl_file_mutex seems to no longer exist. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 26c1f2d8920f..c157b3f7b0e1 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1927,9 +1927,6 @@ static int core_scsi3_update_aptpl_buf( return ret; } -/* - * Called with struct se_device->aptpl_file_mutex held - */ static int __core_scsi3_write_aptpl_to_file( struct se_device *dev, unsigned char *buf) -- GitLab From 459f213ba162bd13e113d6f92a8fa6c780fd67ed Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:41:02 -0700 Subject: [PATCH 1171/2900] target: Allocate aptpl_buf inside update_and_write_aptpl() Instead of taking the buffer and length, update_and_write_aptpl() will allocate the buffer as needed, and then free it. Instead, the function takes an 'aptpl' boolean parameter. This enables us to remove memory alloc/frees from struct t10_pr_registration and other spots. There is a slight loss of functionality because each callsite doesn't get its own pr_debug any more, but this info can be cleaned via ftrace if necessary and I think the shorter code is worth it. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 203 +++++++----------------------- include/target/target_core_base.h | 2 - 2 files changed, 48 insertions(+), 157 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index c157b3f7b0e1..915edaab1919 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -606,13 +606,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration( return NULL; } - pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_ATOMIC); - if (!pr_reg->pr_aptpl_buf) { - pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n"); - kmem_cache_free(t10_pr_reg_cache, pr_reg); - return NULL; - } - INIT_LIST_HEAD(&pr_reg->pr_reg_list); INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list); INIT_LIST_HEAD(&pr_reg->pr_reg_aptpl_list); @@ -803,7 +796,6 @@ int core_scsi3_alloc_aptpl_registration( pr_err("Unable to allocate struct t10_pr_registration\n"); return -ENOMEM; } - pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); INIT_LIST_HEAD(&pr_reg->pr_reg_list); INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list); @@ -1272,7 +1264,6 @@ static void __core_scsi3_free_registration( if (!preempt_and_abort_list) { pr_reg->pr_reg_deve = NULL; pr_reg->pr_reg_nacl = NULL; - kfree(pr_reg->pr_aptpl_buf); kmem_cache_free(t10_pr_reg_cache, pr_reg); return; } @@ -1341,7 +1332,6 @@ void core_scsi3_free_all_registrations( list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->aptpl_reg_list, pr_reg_aptpl_list) { list_del(&pr_reg->pr_reg_aptpl_list); - kfree(pr_reg->pr_aptpl_buf); kmem_cache_free(t10_pr_reg_cache, pr_reg); } spin_unlock(&pr_tmpl->aptpl_reg_lock); @@ -1814,7 +1804,6 @@ core_scsi3_decode_spec_i_port( kmem_cache_free(t10_pr_reg_cache, pr_reg_tmp); } - kfree(dest_pr_reg->pr_aptpl_buf); kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); if (dest_local_nexus) @@ -1840,8 +1829,6 @@ static int core_scsi3_update_aptpl_buf( int reg_count = 0; int ret = 0; - memset(buf, 0, pr_aptpl_buf_len); - spin_lock(&dev->dev_reservation_lock); spin_lock(&dev->t10_pr.registration_lock); /* @@ -1965,31 +1952,45 @@ static int __core_scsi3_write_aptpl_to_file( return ret ? -EIO : 0; } -static int -core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf, - u32 in_pr_aptpl_buf_len) +/* + * Clear the APTPL metadata if APTPL has been disabled, otherwise + * write out the updated metadata to struct file for this SCSI device. + */ +static int core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) { - unsigned char null_buf[64], *buf; - int ret; + int ret = 0; - /* - * Can be called with a NULL pointer from PROUT service action CLEAR - */ - if (!in_buf) { - snprintf(null_buf, 64, "No Registrations or Reservations\n"); - buf = null_buf; + if (!aptpl) { + char *null_buf = "No Registrations or Reservations\n"; + + ret = __core_scsi3_write_aptpl_to_file(dev, null_buf); + dev->t10_pr.pr_aptpl_active = 0; + pr_debug("SPC-3 PR: Set APTPL Bit Deactivated\n"); } else { - ret = core_scsi3_update_aptpl_buf(dev, in_buf, in_pr_aptpl_buf_len); - if (ret != 0) + int ret; + unsigned char *buf; + + buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); + if (ret < 0) { + kfree(buf); return ret; - buf = in_buf; + } + + ret = __core_scsi3_write_aptpl_to_file(dev, buf); + if (ret != 0) { + pr_err("SPC-3 PR: Could not update APTPL\n"); + } else { + dev->t10_pr.pr_aptpl_active = 1; + pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); + } + kfree(buf); } - /* - * __core_scsi3_write_aptpl_to_file() will call strlen() - * on the passed buf to determine pr_aptpl_buf_len. - */ - return __core_scsi3_write_aptpl_to_file(dev, buf); + return ret; } static sense_reason_t @@ -2003,8 +2004,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, struct se_portal_group *se_tpg; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; struct t10_reservation *pr_tmpl = &dev->t10_pr; - /* Used for APTPL metadata w/ UNREGISTER */ - unsigned char *pr_aptpl_buf = NULL; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; sense_reason_t ret = TCM_NO_SENSE; int pr_holder = 0, type; @@ -2066,31 +2065,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, if (ret != 0) return ret; } - /* - * Nothing left to do for the APTPL=0 case. - */ - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for" - " REGISTER\n"); - return 0; - } - /* - * Locate the newly allocated local I_T Nexus *pr_reg, and - * update the APTPL metadata information using its - * preallocated *pr_reg->pr_aptpl_buf. - */ - pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, - se_sess->se_node_acl, se_sess); - - if (core_scsi3_update_and_write_aptpl(cmd->se_dev, - pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n"); - } - goto out_put_pr_reg; + return core_scsi3_update_and_write_aptpl(dev, aptpl); } /* @@ -2130,19 +2106,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, goto out_put_pr_reg; } - /* - * Allocate APTPL metadata buffer used for UNREGISTER ops - */ - if (aptpl) { - pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); - if (!pr_aptpl_buf) { - pr_err("Unable to allocate" - " pr_aptpl_buf\n"); - ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - goto out_put_pr_reg; - } - } - /* * sa_res_key=0 Unregister Reservation Key for registered I_T * Nexus sa_res_key=1 Change Reservation Key for registered I_T @@ -2152,7 +2115,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, pr_holder = core_scsi3_check_implict_release( cmd->se_dev, pr_reg); if (pr_holder < 0) { - kfree(pr_aptpl_buf); ret = TCM_RESERVATION_CONFLICT; goto out_put_pr_reg; } @@ -2214,21 +2176,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, } spin_unlock(&pr_tmpl->registration_lock); - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for UNREGISTER\n"); - return 0; - } - - if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for UNREGISTER\n"); - } - - goto out_free_aptpl_buf; + ret = core_scsi3_update_and_write_aptpl(dev, aptpl); + goto out_put_pr_reg; } /* @@ -2245,24 +2194,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, pr_reg->pr_reg_nacl->initiatorname, pr_reg->pr_res_key, pr_reg->pr_res_generation); - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated" - " for REGISTER\n"); - ret = 0; - goto out_put_pr_reg; - } + ret = core_scsi3_update_and_write_aptpl(dev, aptpl); - if (!core_scsi3_update_and_write_aptpl(dev, pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_tmpl->pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated" - " for REGISTER\n"); - } - -out_free_aptpl_buf: - kfree(pr_aptpl_buf); - ret = 0; out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); return ret; @@ -2437,13 +2370,8 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key) i_buf); spin_unlock(&dev->dev_reservation_lock); - if (pr_tmpl->pr_aptpl_active) { - if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_debug("SPC-3 PR: Updated APTPL metadata" - " for RESERVE\n"); - } - } + if (pr_tmpl->pr_aptpl_active) + core_scsi3_update_and_write_aptpl(cmd->se_dev, true); ret = 0; out_put_pr_reg: @@ -2657,12 +2585,9 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope, spin_unlock(&pr_tmpl->registration_lock); write_aptpl: - if (pr_tmpl->pr_aptpl_active) { - if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n"); - } - } + if (pr_tmpl->pr_aptpl_active) + core_scsi3_update_and_write_aptpl(cmd->se_dev, true); + out_put_pr_reg: core_scsi3_put_pr_reg(pr_reg); return ret; @@ -2746,11 +2671,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key) pr_debug("SPC-3 PR [%s] Service Action: CLEAR complete\n", cmd->se_tfo->get_fabric_name()); - if (pr_tmpl->pr_aptpl_active) { - core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0); - pr_debug("SPC-3 PR: Updated APTPL metadata" - " for CLEAR\n"); - } + core_scsi3_update_and_write_aptpl(cmd->se_dev, false); core_scsi3_pr_generation(dev); return 0; @@ -2822,7 +2743,6 @@ static void core_scsi3_release_preempt_and_abort( pr_reg->pr_reg_deve = NULL; pr_reg->pr_reg_nacl = NULL; - kfree(pr_reg->pr_aptpl_buf); kmem_cache_free(t10_pr_reg_cache, pr_reg); } } @@ -2984,14 +2904,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, } spin_unlock(&dev->dev_reservation_lock); - if (pr_tmpl->pr_aptpl_active) { - if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_debug("SPC-3 PR: Updated APTPL" - " metadata for PREEMPT%s\n", (preempt_type == PREEMPT_AND_ABORT) ? - "_AND_ABORT" : ""); - } - } + if (pr_tmpl->pr_aptpl_active) + core_scsi3_update_and_write_aptpl(cmd->se_dev, true); core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_pr_generation(cmd->se_dev); @@ -3119,13 +3033,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, pr_reg_n); } - if (pr_tmpl->pr_aptpl_active) { - if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - pr_reg_n->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT" - "%s\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : ""); - } - } + if (pr_tmpl->pr_aptpl_active) + core_scsi3_update_and_write_aptpl(cmd->se_dev, true); core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_pr_generation(cmd->se_dev); @@ -3552,23 +3461,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key, } else core_scsi3_put_pr_reg(pr_reg); - /* - * Clear the APTPL metadata if APTPL has been disabled, otherwise - * write out the updated metadata to struct file for this SCSI device. - */ - if (!aptpl) { - pr_tmpl->pr_aptpl_active = 0; - core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0); - pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for" - " REGISTER_AND_MOVE\n"); - } else { - pr_tmpl->pr_aptpl_active = 1; - if (!core_scsi3_update_and_write_aptpl(cmd->se_dev, - dest_pr_reg->pr_aptpl_buf, PR_APTPL_BUF_LEN)) { - pr_debug("SPC-3 PR: Set APTPL Bit Activated for" - " REGISTER_AND_MOVE\n"); - } - } + core_scsi3_update_and_write_aptpl(cmd->se_dev, aptpl); transport_kunmap_data_sg(cmd); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 5976dc3e4066..8952ee9f7cef 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -339,8 +339,6 @@ struct t10_pr_registration { /* Used during APTPL metadata reading */ #define PR_APTPL_MAX_TPORT_LEN 256 unsigned char pr_tport[PR_APTPL_MAX_TPORT_LEN]; - /* For writing out live meta data */ - unsigned char *pr_aptpl_buf; u16 pr_aptpl_rpti; u16 pr_reg_tpgt; /* Reservation effects all target ports */ -- GitLab From 51d9c41d190b6645c69a279b0610aad8e4ed9d72 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:41:03 -0700 Subject: [PATCH 1172/2900] target: Use if/else for sa_res_key conditional in emulate_pro_register() Don't need goto, we can just do an if/else for sa_res_key behavior. Move shorter case first. Slightly shorter b/c both cases can share a call to update_and_write_aptpl() now. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 915edaab1919..6eb0dabb4ac9 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2107,11 +2107,27 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, } /* - * sa_res_key=0 Unregister Reservation Key for registered I_T - * Nexus sa_res_key=1 Change Reservation Key for registered I_T - * Nexus. + * sa_res_key=1 Change Reservation Key for registered I_T Nexus. */ - if (!sa_res_key) { + if (sa_res_key) { + /* + * Increment PRgeneration counter for struct se_device" + * upon a successful REGISTER, see spc4r17 section 6.3.2 + * READ_KEYS service action. + */ + pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); + pr_reg->pr_res_key = sa_res_key; + pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" + " Key for %s to: 0x%016Lx PRgeneration:" + " 0x%08x\n", cmd->se_tfo->get_fabric_name(), + (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "", + pr_reg->pr_reg_nacl->initiatorname, + pr_reg->pr_res_key, pr_reg->pr_res_generation); + + } else { + /* + * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. + */ pr_holder = core_scsi3_check_implict_release( cmd->se_dev, pr_reg); if (pr_holder < 0) { @@ -2174,26 +2190,10 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, ASCQ_2AH_RESERVATIONS_RELEASED); } } - spin_unlock(&pr_tmpl->registration_lock); - ret = core_scsi3_update_and_write_aptpl(dev, aptpl); - goto out_put_pr_reg; + spin_unlock(&pr_tmpl->registration_lock); } - /* - * Increment PRgeneration counter for struct se_device" - * upon a successful REGISTER, see spc4r17 section 6.3.2 - * READ_KEYS service action. - */ - pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev); - pr_reg->pr_res_key = sa_res_key; - pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation" - " Key for %s to: 0x%016Lx PRgeneration:" - " 0x%08x\n", cmd->se_tfo->get_fabric_name(), - (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "", - pr_reg->pr_reg_nacl->initiatorname, - pr_reg->pr_res_key, pr_reg->pr_res_generation); - ret = core_scsi3_update_and_write_aptpl(dev, aptpl); out_put_pr_reg: -- GitLab From bc118fe4c4a8cfa453491ba77c0a146a6d0e73e0 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Thu, 16 May 2013 10:41:04 -0700 Subject: [PATCH 1173/2900] target: Further refactoring of core_scsi3_emulate_pro_register() Use bool params when appropriate. Eliminate unneeded pr_reg_e and type variables. Just one goto label, so rename to 'out' from 'out_put_pr_reg'. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 46 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 6eb0dabb4ac9..05c3f426728a 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1995,18 +1995,18 @@ static int core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) static sense_reason_t core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, - int aptpl, int all_tg_pt, int spec_i_pt, enum register_type register_type) + bool aptpl, bool all_tg_pt, bool spec_i_pt, enum register_type register_type) { struct se_session *se_sess = cmd->se_sess; struct se_device *dev = cmd->se_dev; struct se_dev_entry *se_deve; struct se_lun *se_lun = cmd->se_lun; struct se_portal_group *se_tpg; - struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e; + struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; sense_reason_t ret = TCM_NO_SENSE; - int pr_holder = 0, type; + int pr_holder = 0; if (!se_sess || !se_lun) { pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); @@ -2024,8 +2024,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, /* * Follow logic from spc4r17 Section 5.7.7, Register Behaviors Table 47 */ - pr_reg_e = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess); - if (!pr_reg_e) { + pr_reg = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess); + if (!pr_reg) { if (res_key) { pr_warn("SPC-3 PR: Reservation Key non-zero" " for SA REGISTER, returning CONFLICT\n"); @@ -2069,29 +2069,23 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, return core_scsi3_update_and_write_aptpl(dev, aptpl); } - /* - * Locate the existing *pr_reg via struct se_node_acl pointers - */ - pr_reg = pr_reg_e; - type = pr_reg->pr_res_type; + /* ok, existing registration */ - if (register_type == REGISTER) { - if (res_key != pr_reg->pr_res_key) { - pr_err("SPC-3 PR REGISTER: Received" - " res_key: 0x%016Lx does not match" - " existing SA REGISTER res_key:" - " 0x%016Lx\n", res_key, - pr_reg->pr_res_key); - ret = TCM_RESERVATION_CONFLICT; - goto out_put_pr_reg; - } + if ((register_type == REGISTER) && (res_key != pr_reg->pr_res_key)) { + pr_err("SPC-3 PR REGISTER: Received" + " res_key: 0x%016Lx does not match" + " existing SA REGISTER res_key:" + " 0x%016Lx\n", res_key, + pr_reg->pr_res_key); + ret = TCM_RESERVATION_CONFLICT; + goto out; } if (spec_i_pt) { pr_err("SPC-3 PR REGISTER: SPEC_I_PT" " set on a registered nexus\n"); ret = TCM_INVALID_PARAMETER_LIST; - goto out_put_pr_reg; + goto out; } /* @@ -2103,7 +2097,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, " registration exists, but ALL_TG_PT=1 bit not" " present in received PROUT\n"); ret = TCM_INVALID_CDB_FIELD; - goto out_put_pr_reg; + goto out; } /* @@ -2132,7 +2126,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, cmd->se_dev, pr_reg); if (pr_holder < 0) { ret = TCM_RESERVATION_CONFLICT; - goto out_put_pr_reg; + goto out; } spin_lock(&pr_tmpl->registration_lock); @@ -2177,8 +2171,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, * RESERVATIONS RELEASED. */ if (pr_holder && - (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || - type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { + (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY || + pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) { list_for_each_entry(pr_reg_p, &pr_tmpl->registration_list, pr_reg_list) { @@ -2196,7 +2190,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, ret = core_scsi3_update_and_write_aptpl(dev, aptpl); -out_put_pr_reg: +out: core_scsi3_put_pr_reg(pr_reg); return ret; } -- GitLab From db5d1c3ccc37d1f2066f5dc1f1c9c91a2f1f2956 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 28 May 2013 16:55:20 -0700 Subject: [PATCH 1174/2900] target: Make virtual_lun0 a nullio device Nobody should be expecting to read or write virtual_lun0. Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index ed679c9420c5..8f4142fe5f19 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1544,7 +1544,7 @@ int core_dev_setup_virtual_lun0(void) { struct se_hba *hba; struct se_device *dev; - char buf[16]; + char buf[] = "rd_pages=8,rd_nullio=1"; int ret; hba = core_alloc_hba("rd_mcp", 0, HBA_FLAGS_INTERNAL_USE); @@ -1557,8 +1557,6 @@ int core_dev_setup_virtual_lun0(void) goto out_free_hba; } - memset(buf, 0, 16); - sprintf(buf, "rd_pages=8"); hba->transport->set_configfs_dev_params(dev, buf, sizeof(buf)); ret = target_configure_device(dev); -- GitLab From 670caa9f762647802a1b19749f127ac28949ca5a Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Tue, 28 May 2013 16:55:21 -0700 Subject: [PATCH 1175/2900] target: Don't allocate pages for NULLIO devices Signed-off-by: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_rd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c index 0921a64b5550..51127d15d5c5 100644 --- a/drivers/target/target_core_rd.c +++ b/drivers/target/target_core_rd.c @@ -139,6 +139,11 @@ static int rd_build_device_space(struct rd_dev *rd_dev) rd_dev->rd_page_count); return -EINVAL; } + + /* Don't need backing pages for NULLIO */ + if (rd_dev->rd_flags & RDF_NULLIO) + return 0; + total_sg_needed = rd_dev->rd_page_count; sg_tables = (total_sg_needed / max_sg_per_table) + 1; -- GitLab From 8a00a61b0ef2bfd1b468dd20c0d0b1a94a8f7475 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Wed, 29 May 2013 15:35:02 +0200 Subject: [PATCH 1176/2900] NFC: Add basic NCI over SPI The NFC Forum defines a transport interface based on Serial Peripheral Interface (SPI) for the NFC Controller Interface (NCI). This module implements the SPI transport of NCI, calling SPI module directly to read/write data to NFC controller (NFCC). NFCC driver should provide functions performing device open and close. It should also provide functions asserting/de-asserting interruption to prevent TX/RX race conditions. NFCC driver can also fix a delay between transactions if needed by the hardware. Signed-off-by: Frederic Danis Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 49 +++++++++++++ net/nfc/nci/Kconfig | 10 +++ net/nfc/nci/Makefile | 4 +- net/nfc/nci/spi.c | 136 +++++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 net/nfc/nci/spi.c diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 1009d3dcb316..3b05bebd8235 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -3,6 +3,7 @@ * NFC Controller (NFCC) and a Device Host (DH). * * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2013 Intel Corporation. All rights reserved. * * Written by Ilan Elias * @@ -202,4 +203,52 @@ void nci_req_complete(struct nci_dev *ndev, int result); /* ----- NCI status code ----- */ int nci_to_errno(__u8 code); +/* ----- NCI over SPI acknowledge modes ----- */ +#define NCI_SPI_CRC_DISABLED 0x00 +#define NCI_SPI_CRC_ENABLED 0x01 + +/* ----- NCI SPI structures ----- */ +struct nci_spi_dev; + +struct nci_spi_ops { + int (*open)(struct nci_spi_dev *ndev); + int (*close)(struct nci_spi_dev *ndev); + void (*assert_int)(struct nci_spi_dev *ndev); + void (*deassert_int)(struct nci_spi_dev *ndev); +}; + +struct nci_spi_dev { + struct nci_dev *nci_dev; + struct spi_device *spi; + struct nci_spi_ops *ops; + + unsigned int xfer_udelay; /* microseconds delay between + transactions */ + u8 acknowledge_mode; + + void *driver_data; +}; + +/* ----- NCI SPI Devices ----- */ +struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, + struct nci_spi_ops *ops, + u32 supported_protocols, + u32 supported_se, + u8 acknowledge_mode, + unsigned int delay); +void nci_spi_free_device(struct nci_spi_dev *ndev); +int nci_spi_register_device(struct nci_spi_dev *ndev); +void nci_spi_unregister_device(struct nci_spi_dev *ndev); + +static inline void nci_spi_set_drvdata(struct nci_spi_dev *ndev, + void *data) +{ + ndev->driver_data = data; +} + +static inline void *nci_spi_get_drvdata(struct nci_spi_dev *ndev) +{ + return ndev->driver_data; +} + #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig index 6d69b5f0f19b..2a2416080b4f 100644 --- a/net/nfc/nci/Kconfig +++ b/net/nfc/nci/Kconfig @@ -8,3 +8,13 @@ config NFC_NCI Say Y here to compile NCI support into the kernel or say M to compile it as module (nci). + +config NFC_NCI_SPI + depends on NFC_NCI && SPI + bool "NCI over SPI protocol support" + default n + help + NCI (NFC Controller Interface) is a communication protocol between + an NFC Controller (NFCC) and a Device Host (DH). + + Say yes if you use an NCI driver that requires SPI link layer. diff --git a/net/nfc/nci/Makefile b/net/nfc/nci/Makefile index cdb3a2e44471..7aeedc43187d 100644 --- a/net/nfc/nci/Makefile +++ b/net/nfc/nci/Makefile @@ -4,4 +4,6 @@ obj-$(CONFIG_NFC_NCI) += nci.o -nci-objs := core.o data.o lib.o ntf.o rsp.o \ No newline at end of file +nci-objs := core.o data.o lib.o ntf.o rsp.o + +nci-$(CONFIG_NFC_NCI_SPI) += spi.o diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c new file mode 100644 index 000000000000..ebcdba51418c --- /dev/null +++ b/net/nfc/nci/spi.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#define pr_fmt(fmt) "nci_spi: %s: " fmt, __func__ + +#include +#include +#include +#include + +#define NCI_SPI_HDR_LEN 4 +#define NCI_SPI_CRC_LEN 2 + +static int nci_spi_open(struct nci_dev *nci_dev) +{ + struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + + return ndev->ops->open(ndev); +} + +static int nci_spi_close(struct nci_dev *nci_dev) +{ + struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + + return ndev->ops->close(ndev); +} + +static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) +{ + return 0; +} + +static struct nci_ops nci_spi_ops = { + .open = nci_spi_open, + .close = nci_spi_close, + .send = nci_spi_send, +}; + +/* ---- Interface to NCI SPI drivers ---- */ + +/** + * nci_spi_allocate_device - allocate a new nci spi device + * + * @spi: SPI device + * @ops: device operations + * @supported_protocols: NFC protocols supported by the device + * @supported_se: NFC Secure Elements supported by the device + * @acknowledge_mode: Acknowledge mode used by the device + * @delay: delay between transactions in us + */ +struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, + struct nci_spi_ops *ops, + u32 supported_protocols, + u32 supported_se, + u8 acknowledge_mode, + unsigned int delay) +{ + struct nci_spi_dev *ndev; + int tailroom = 0; + + if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) + return NULL; + + if (!supported_protocols) + return NULL; + + ndev = devm_kzalloc(&spi->dev, sizeof(struct nci_dev), GFP_KERNEL); + if (!ndev) + return NULL; + + ndev->ops = ops; + ndev->acknowledge_mode = acknowledge_mode; + ndev->xfer_udelay = delay; + + if (acknowledge_mode == NCI_SPI_CRC_ENABLED) + tailroom += NCI_SPI_CRC_LEN; + + ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, + supported_se, NCI_SPI_HDR_LEN, + tailroom); + if (!ndev->nci_dev) + return NULL; + + nci_set_drvdata(ndev->nci_dev, ndev); + + return ndev; +} +EXPORT_SYMBOL_GPL(nci_spi_allocate_device); + +/** + * nci_spi_free_device - deallocate nci spi device + * + * @ndev: The nci spi device to deallocate + */ +void nci_spi_free_device(struct nci_spi_dev *ndev) +{ + nci_free_device(ndev->nci_dev); +} +EXPORT_SYMBOL_GPL(nci_spi_free_device); + +/** + * nci_spi_register_device - register a nci spi device in the nfc subsystem + * + * @pdev: The nci spi device to register + */ +int nci_spi_register_device(struct nci_spi_dev *ndev) +{ + return nci_register_device(ndev->nci_dev); +} +EXPORT_SYMBOL_GPL(nci_spi_register_device); + +/** + * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem + * + * @dev: The nci spi device to unregister + */ +void nci_spi_unregister_device(struct nci_spi_dev *ndev) +{ + nci_unregister_device(ndev->nci_dev); +} +EXPORT_SYMBOL_GPL(nci_spi_unregister_device); -- GitLab From ee9596d467e4d05c77a8c883aeeb5b74d1a3cd31 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Wed, 29 May 2013 15:35:03 +0200 Subject: [PATCH 1177/2900] NFC: Add NCI over SPI send Before any operation, driver interruption is de-asserted to prevent race condition between TX and RX. The NCI over SPI header is added in front of NCI packet. If acknowledged mode is set, CRC-16-CCITT is added to the packet. Then the packet is forwarded to SPI module to be sent. A delay after the transaction is added. This delay is determined by the driver during nci_spi_allocate_device() call and can be 0. After data has been sent, driver interruption is re-asserted. If acknowledged mode is set, nci_spi_send will block until acknowledgment is received. Signed-off-by: Frederic Danis Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 3 ++ net/nfc/nci/spi.c | 71 +++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 3b05bebd8235..36df525d2ab3 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -226,6 +226,9 @@ struct nci_spi_dev { transactions */ u8 acknowledge_mode; + struct completion req_completion; + u8 req_result; + void *driver_data; }; diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index ebcdba51418c..6258461e6998 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -20,12 +20,25 @@ #include #include +#include #include #include #define NCI_SPI_HDR_LEN 4 #define NCI_SPI_CRC_LEN 2 +#define NCI_SPI_SEND_TIMEOUT (NCI_CMD_TIMEOUT > NCI_DATA_TIMEOUT ? \ + NCI_CMD_TIMEOUT : NCI_DATA_TIMEOUT) + +#define NCI_SPI_DIRECT_WRITE 0x01 +#define NCI_SPI_DIRECT_READ 0x02 + +#define ACKNOWLEDGE_NONE 0 +#define ACKNOWLEDGE_ACK 1 +#define ACKNOWLEDGE_NACK 2 + +#define CRC_INIT 0xFFFF + static int nci_spi_open(struct nci_dev *nci_dev) { struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); @@ -40,9 +53,65 @@ static int nci_spi_close(struct nci_dev *nci_dev) return ndev->ops->close(ndev); } +static int __nci_spi_send(struct nci_spi_dev *ndev, struct sk_buff *skb) +{ + struct spi_message m; + struct spi_transfer t; + + t.tx_buf = skb->data; + t.len = skb->len; + t.cs_change = 0; + t.delay_usecs = ndev->xfer_udelay; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + return spi_sync(ndev->spi, &m); +} + static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) { - return 0; + struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); + unsigned int payload_len = skb->len; + unsigned char *hdr; + int ret; + long completion_rc; + + ndev->ops->deassert_int(ndev); + + /* add the NCI SPI header to the start of the buffer */ + hdr = skb_push(skb, NCI_SPI_HDR_LEN); + hdr[0] = NCI_SPI_DIRECT_WRITE; + hdr[1] = ndev->acknowledge_mode; + hdr[2] = payload_len >> 8; + hdr[3] = payload_len & 0xFF; + + if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + u16 crc; + + crc = crc_ccitt(CRC_INIT, skb->data, skb->len); + *skb_put(skb, 1) = crc >> 8; + *skb_put(skb, 1) = crc & 0xFF; + } + + ret = __nci_spi_send(ndev, skb); + + kfree_skb(skb); + ndev->ops->assert_int(ndev); + + if (ret != 0 || ndev->acknowledge_mode == NCI_SPI_CRC_DISABLED) + goto done; + + init_completion(&ndev->req_completion); + completion_rc = + wait_for_completion_interruptible_timeout(&ndev->req_completion, + NCI_SPI_SEND_TIMEOUT); + + if (completion_rc <= 0 || ndev->req_result == ACKNOWLEDGE_NACK) + ret = -EIO; + +done: + return ret; } static struct nci_ops nci_spi_ops = { -- GitLab From 391d8a2da787257aeaf952c974405b53926e3fb3 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Wed, 29 May 2013 15:35:04 +0200 Subject: [PATCH 1178/2900] NFC: Add NCI over SPI receive Before any operation, driver interruption is de-asserted to prevent race condition between TX and RX. Transaction starts by emitting "Direct read" and acknowledged mode bytes. Then packet length is read allowing to allocate correct NCI socket buffer. After that payload is retrieved. A delay after the transaction can be added. This delay is determined by the driver during nci_spi_allocate_device() call and can be 0. If acknowledged mode is set: - CRC of header and payload is checked - if frame reception fails (CRC error): NACK is sent - if received frame has ACK or NACK flag: unblock nci_spi_send() Payload is passed to NCI module. At the end, driver interruption is re asserted. Signed-off-by: Frederic Danis Signed-off-by: Samuel Ortiz --- include/net/nfc/nci_core.h | 1 + net/nfc/nci/spi.c | 174 +++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 36df525d2ab3..fc1296db237b 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -242,6 +242,7 @@ struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, void nci_spi_free_device(struct nci_spi_dev *ndev); int nci_spi_register_device(struct nci_spi_dev *ndev); void nci_spi_unregister_device(struct nci_spi_dev *ndev); +int nci_spi_recv_frame(struct nci_spi_dev *ndev); static inline void nci_spi_set_drvdata(struct nci_spi_dev *ndev, void *data) diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index 6258461e6998..70afc387a965 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -26,6 +26,8 @@ #define NCI_SPI_HDR_LEN 4 #define NCI_SPI_CRC_LEN 2 +#define NCI_SPI_ACK_SHIFT 6 +#define NCI_SPI_MSB_PAYLOAD_MASK 0x3F #define NCI_SPI_SEND_TIMEOUT (NCI_CMD_TIMEOUT > NCI_DATA_TIMEOUT ? \ NCI_CMD_TIMEOUT : NCI_DATA_TIMEOUT) @@ -203,3 +205,175 @@ void nci_spi_unregister_device(struct nci_spi_dev *ndev) nci_unregister_device(ndev->nci_dev); } EXPORT_SYMBOL_GPL(nci_spi_unregister_device); + +static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) +{ + struct sk_buff *skb; + unsigned char *hdr; + u16 crc; + int ret; + + skb = nci_skb_alloc(ndev->nci_dev, 0, GFP_KERNEL); + + /* add the NCI SPI header to the start of the buffer */ + hdr = skb_push(skb, NCI_SPI_HDR_LEN); + hdr[0] = NCI_SPI_DIRECT_WRITE; + hdr[1] = NCI_SPI_CRC_ENABLED; + hdr[2] = acknowledge << NCI_SPI_ACK_SHIFT; + hdr[3] = 0; + + crc = crc_ccitt(CRC_INIT, skb->data, skb->len); + *skb_put(skb, 1) = crc >> 8; + *skb_put(skb, 1) = crc & 0xFF; + + ret = __nci_spi_send(ndev, skb); + + kfree_skb(skb); + + return ret; +} + +static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) +{ + struct sk_buff *skb; + struct spi_message m; + unsigned char req[2], resp_hdr[2]; + struct spi_transfer tx, rx; + unsigned short rx_len = 0; + int ret; + + spi_message_init(&m); + req[0] = NCI_SPI_DIRECT_READ; + req[1] = ndev->acknowledge_mode; + tx.tx_buf = req; + tx.len = 2; + tx.cs_change = 0; + spi_message_add_tail(&tx, &m); + rx.rx_buf = resp_hdr; + rx.len = 2; + rx.cs_change = 1; + spi_message_add_tail(&rx, &m); + ret = spi_sync(ndev->spi, &m); + + if (ret) + return NULL; + + if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + + resp_hdr[1] + NCI_SPI_CRC_LEN; + else + rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; + + skb = nci_skb_alloc(ndev->nci_dev, rx_len, GFP_KERNEL); + if (!skb) + return NULL; + + spi_message_init(&m); + rx.rx_buf = skb_put(skb, rx_len); + rx.len = rx_len; + rx.cs_change = 0; + rx.delay_usecs = ndev->xfer_udelay; + spi_message_add_tail(&rx, &m); + ret = spi_sync(ndev->spi, &m); + + if (ret) + goto receive_error; + + if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + *skb_push(skb, 1) = resp_hdr[1]; + *skb_push(skb, 1) = resp_hdr[0]; + } + + return skb; + +receive_error: + kfree_skb(skb); + + return NULL; +} + +static int nci_spi_check_crc(struct sk_buff *skb) +{ + u16 crc_data = (skb->data[skb->len - 2] << 8) | + skb->data[skb->len - 1]; + int ret; + + ret = (crc_ccitt(CRC_INIT, skb->data, skb->len - NCI_SPI_CRC_LEN) + == crc_data); + + skb_trim(skb, skb->len - NCI_SPI_CRC_LEN); + + return ret; +} + +static u8 nci_spi_get_ack(struct sk_buff *skb) +{ + u8 ret; + + ret = skb->data[0] >> NCI_SPI_ACK_SHIFT; + + /* Remove NFCC part of the header: ACK, NACK and MSB payload len */ + skb_pull(skb, 2); + + return ret; +} + +/** + * nci_spi_recv_frame - receive frame from NCI SPI drivers + * + * @ndev: The nci spi device + * Context: can sleep + * + * This call may only be used from a context that may sleep. The sleep + * is non-interruptible, and has no timeout. + * + * It returns zero on success, else a negative error code. + */ +int nci_spi_recv_frame(struct nci_spi_dev *ndev) +{ + struct sk_buff *skb; + int ret = 0; + + ndev->ops->deassert_int(ndev); + + /* Retrieve frame from SPI */ + skb = __nci_spi_recv_frame(ndev); + if (!skb) { + ret = -EIO; + goto done; + } + + if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (!nci_spi_check_crc(skb)) { + send_acknowledge(ndev, ACKNOWLEDGE_NACK); + goto done; + } + + /* In case of acknowledged mode: if ACK or NACK received, + * unblock completion of latest frame sent. + */ + ndev->req_result = nci_spi_get_ack(skb); + if (ndev->req_result) + complete(&ndev->req_completion); + } + + /* If there is no payload (ACK/NACK only frame), + * free the socket buffer + */ + if (skb->len == 0) { + kfree_skb(skb); + goto done; + } + + if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + send_acknowledge(ndev, ACKNOWLEDGE_ACK); + + /* Forward skb to NCI core layer */ + ret = nci_recv_frame(ndev->nci_dev, skb); + +done: + ndev->ops->assert_int(ndev); + + return ret; +} +EXPORT_SYMBOL_GPL(nci_spi_recv_frame); -- GitLab From 31c44464acb8152db5745da700be58ac95ba0a83 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 27 May 2013 14:59:40 +0200 Subject: [PATCH 1179/2900] NFC: pn533: Use 0x3 for SENSF_REQ Time Slot Number (TSN) LLCP validation requires TSN to be 0x03 for type F. Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 0bdfa8852e78..6bd4f598b3e1 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -258,7 +258,7 @@ static const struct pn533_poll_modulations poll_mod[] = { .opcode = PN533_FELICA_OPC_SENSF_REQ, .sc = PN533_FELICA_SENSF_SC_ALL, .rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE, - .tsn = 0, + .tsn = 0x03, }, }, .len = 7, @@ -271,7 +271,7 @@ static const struct pn533_poll_modulations poll_mod[] = { .opcode = PN533_FELICA_OPC_SENSF_REQ, .sc = PN533_FELICA_SENSF_SC_ALL, .rc = PN533_FELICA_SENSF_RC_NO_SYSTEM_CODE, - .tsn = 0, + .tsn = 0x03, }, }, .len = 7, -- GitLab From 322bce957e9b0e30ef7147dae0414ad8f3f558c8 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 27 May 2013 15:29:11 +0200 Subject: [PATCH 1180/2900] NFC: pn533: Copy NFCID2 through ATR_REQ When using NFC-F we should copy the NFCID2 buffer that we got from SENSF_RES through the ATR_REQ NFCID3 buffer. Not doing so violates NFC Forum digital requirement #189. Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 14 +++++++++++++- include/net/nfc/nfc.h | 2 ++ include/uapi/linux/nfc.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 6bd4f598b3e1..e196bdfcfc30 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1235,7 +1235,7 @@ static int pn533_target_found_type_a(struct nfc_target *nfc_tgt, u8 *tgt_data, struct pn533_target_felica { u8 pol_res; u8 opcode; - u8 nfcid2[8]; + u8 nfcid2[NFC_NFCID2_MAXSIZE]; u8 pad[8]; /* optional */ u8 syst_code[]; @@ -1275,6 +1275,9 @@ static int pn533_target_found_felica(struct nfc_target *nfc_tgt, u8 *tgt_data, memcpy(nfc_tgt->sensf_res, &tgt_felica->opcode, 9); nfc_tgt->sensf_res_len = 9; + memcpy(nfc_tgt->nfcid2, tgt_felica->nfcid2, NFC_NFCID2_MAXSIZE); + nfc_tgt->nfcid2_len = NFC_NFCID2_MAXSIZE; + return 0; } @@ -2084,6 +2087,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, if (comm_mode == NFC_COMM_PASSIVE) skb_len += PASSIVE_DATA_LEN; + if (target && target->nfcid2_len) + skb_len += NFC_NFCID3_MAXSIZE; + skb = pn533_alloc_skb(dev, skb_len); if (!skb) return -ENOMEM; @@ -2100,6 +2106,12 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, *next |= 1; } + if (target && target->nfcid2_len) { + memcpy(skb_put(skb, NFC_NFCID3_MAXSIZE), target->nfcid2, + target->nfcid2_len); + *next |= 2; + } + if (gb != NULL && gb_len > 0) { memcpy(skb_put(skb, gb_len), gb, gb_len); *next |= 4; /* We have some Gi */ diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 3563dbdcaaf2..8fc1784a264d 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -84,6 +84,8 @@ struct nfc_target { u8 sel_res; u8 nfcid1_len; u8 nfcid1[NFC_NFCID1_MAXSIZE]; + u8 nfcid2_len; + u8 nfcid2[NFC_NFCID2_MAXSIZE]; u8 sensb_res_len; u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; u8 sensf_res_len; diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index b6cbd164f146..fb304fb774cc 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -164,6 +164,8 @@ enum nfc_sdp_attr { #define NFC_DEVICE_NAME_MAXSIZE 8 #define NFC_NFCID1_MAXSIZE 10 +#define NFC_NFCID2_MAXSIZE 8 +#define NFC_NFCID3_MAXSIZE 10 #define NFC_SENSB_RES_MAXSIZE 12 #define NFC_SENSF_RES_MAXSIZE 18 #define NFC_GB_MAXSIZE 48 -- GitLab From 0b456c418a5595b9d67f300c9ac6a2441e774603 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 7 May 2013 19:22:11 +0200 Subject: [PATCH 1181/2900] NFC: Remove the static supported_se field Supported secure elements are typically found during a discovery process initiated when the NFC controller is up and running. For a given NFC chipset there can be many configurations (embedded SE or not, with or without a SIM card wired to the NFC controller SWP interface, etc...) and thus driver code will never know before hand which SEs are available. So we remove this field, it will be replaced by a real SE discovery mechanism. Signed-off-by: Samuel Ortiz --- drivers/nfc/microread/microread.c | 6 ++---- drivers/nfc/nfcwilink.c | 1 - drivers/nfc/pn533.c | 1 - drivers/nfc/pn544/pn544.c | 6 ++---- include/net/nfc/hci.h | 1 - include/net/nfc/nci_core.h | 1 - include/net/nfc/nfc.h | 2 -- net/nfc/core.c | 2 -- net/nfc/hci/core.c | 3 +-- net/nfc/nci/core.c | 2 -- net/nfc/nci/spi.c | 3 +-- net/nfc/netlink.c | 1 - 12 files changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c index 3420d833db17..cdb9f6de132a 100644 --- a/drivers/nfc/microread/microread.c +++ b/drivers/nfc/microread/microread.c @@ -650,7 +650,7 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, { struct microread_info *info; unsigned long quirks = 0; - u32 protocols, se; + u32 protocols; struct nfc_hci_init_data init_data; int r; @@ -678,10 +678,8 @@ int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; - se = NFC_SE_UICC | NFC_SE_EMBEDDED; - info->hdev = nfc_hci_allocate_device(µread_hci_ops, &init_data, - quirks, protocols, se, llc_name, + quirks, protocols, llc_name, phy_headroom + MICROREAD_CMDS_HEADROOM, phy_tailroom + diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c index 41cf8f70a6ad..59f95d8fc98c 100644 --- a/drivers/nfc/nfcwilink.c +++ b/drivers/nfc/nfcwilink.c @@ -535,7 +535,6 @@ static int nfcwilink_probe(struct platform_device *pdev) drv->ndev = nci_allocate_device(&nfcwilink_ops, protocols, - NFC_SE_NONE, NFCWILINK_HDR_LEN, 0); if (!drv->ndev) { diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index e196bdfcfc30..a1b46aa7b4d5 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2791,7 +2791,6 @@ static int pn533_probe(struct usb_interface *interface, dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - NFC_SE_NONE, dev->ops->tx_header_len + PN533_CMD_DATAEXCH_HEAD_LEN, dev->ops->tx_tail_len); diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 84b5168b603c..0d17da7675b7 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c @@ -803,7 +803,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, struct nfc_hci_dev **hdev) { struct pn544_hci_info *info; - u32 protocols, se; + u32 protocols; struct nfc_hci_init_data init_data; int r; @@ -836,10 +836,8 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK; - se = NFC_SE_UICC | NFC_SE_EMBEDDED; - info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, - protocols, se, llc_name, + protocols, llc_name, phy_headroom + PN544_CMDS_HEADROOM, phy_tailroom, phy_payload); if (!info->hdev) { diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 14faf2dc7a48..eca8846a63d6 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -153,7 +153,6 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, unsigned long quirks, u32 protocols, - u32 supported_se, const char *llc_name, int tx_headroom, int tx_tailroom, diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index fc1296db237b..99fc1f3a392a 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -148,7 +148,6 @@ struct nci_dev { /* ----- NCI Devices ----- */ struct nci_dev *nci_allocate_device(struct nci_ops *ops, __u32 supported_protocols, - __u32 supported_se, int tx_headroom, int tx_tailroom); void nci_free_device(struct nci_dev *ndev); diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 8fc1784a264d..9900c0f5d6bd 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -115,7 +115,6 @@ struct nfc_dev { struct nfc_genl_data genl_data; u32 supported_protocols; - u32 supported_se; u32 active_se; int tx_headroom; @@ -136,7 +135,6 @@ extern struct class nfc_class; struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, u32 supported_protocols, - u32 supported_se, int tx_headroom, int tx_tailroom); diff --git a/net/nfc/core.c b/net/nfc/core.c index eb3cecf1764e..334954a1d6e8 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -832,7 +832,6 @@ struct nfc_dev *nfc_get_device(unsigned int idx) */ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, u32 supported_protocols, - u32 supported_se, int tx_headroom, int tx_tailroom) { struct nfc_dev *dev; @@ -850,7 +849,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->ops = ops; dev->supported_protocols = supported_protocols; - dev->supported_se = supported_se; dev->active_se = NFC_SE_NONE; dev->tx_headroom = tx_headroom; dev->tx_tailroom = tx_tailroom; diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index d2ef1e2ee0c6..9c8a63d341d3 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -808,7 +808,6 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_init_data *init_data, unsigned long quirks, u32 protocols, - u32 supported_se, const char *llc_name, int tx_headroom, int tx_tailroom, @@ -834,7 +833,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, return NULL; } - hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, supported_se, + hdev->ndev = nfc_allocate_device(&hci_nfc_ops, protocols, tx_headroom + HCI_CMDS_HEADROOM, tx_tailroom); if (!hdev->ndev) { diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 8e0dbbeee9e3..145bad15e113 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -658,7 +658,6 @@ static struct nfc_ops nci_nfc_ops = { */ struct nci_dev *nci_allocate_device(struct nci_ops *ops, __u32 supported_protocols, - __u32 supported_se, int tx_headroom, int tx_tailroom) { struct nci_dev *ndev; @@ -681,7 +680,6 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, supported_protocols, - supported_se, tx_headroom + NCI_DATA_HDR_SIZE, tx_tailroom); if (!ndev->nfc_dev) diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index 70afc387a965..c7cf37ba7298 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -162,8 +162,7 @@ struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, tailroom += NCI_SPI_CRC_LEN; ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, - supported_se, NCI_SPI_HDR_LEN, - tailroom); + NCI_SPI_HDR_LEN, tailroom); if (!ndev->nci_dev) return NULL; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 1deadad9a285..fdbc662c564a 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -444,7 +444,6 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || - nla_put_u32(msg, NFC_ATTR_SE, dev->supported_se) || nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) goto nla_put_failure; -- GitLab From 0a946301c2d3eac8673e556df820c0b6023ac6c3 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 11:57:06 +0200 Subject: [PATCH 1182/2900] NFC: Extend and fix the internal secure element API Secure elements need to be discovered after enabling the NFC controller. This is typically done by the NCI core and the HCI drivers (HCI does not specify how to discover SEs, it is left to the specific drivers). Also, the SE enable/disable API explicitely takes a SE index as its argument. Signed-off-by: Samuel Ortiz --- include/net/nfc/hci.h | 5 +++-- include/net/nfc/nfc.h | 7 +++++-- net/nfc/core.c | 7 +++++++ net/nfc/hci/core.c | 33 +++++++++++++++++++++++++++++++++ net/nfc/nci/core.c | 18 ++++++++++++++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index eca8846a63d6..0af851c3b038 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h @@ -59,9 +59,10 @@ struct nfc_hci_ops { struct nfc_target *target); int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *skb); - int (*enable_se)(struct nfc_dev *dev, u32 secure_element); - int (*disable_se)(struct nfc_dev *dev, u32 secure_element); int (*fw_upload)(struct nfc_hci_dev *hdev, const char *firmware_name); + int (*discover_se)(struct nfc_hci_dev *dev); + int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx); + int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx); }; /* Pipes */ diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 9900c0f5d6bd..5187ec70b66a 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -68,9 +68,12 @@ struct nfc_ops { void *cb_context); int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); - int (*enable_se)(struct nfc_dev *dev, u32 secure_element); - int (*disable_se)(struct nfc_dev *dev, u32 secure_element); int (*fw_upload)(struct nfc_dev *dev, const char *firmware_name); + + /* Secure Element API */ + int (*discover_se)(struct nfc_dev *dev); + int (*enable_se)(struct nfc_dev *dev, u32 se_idx); + int (*disable_se)(struct nfc_dev *dev, u32 se_idx); }; #define NFC_TARGET_IDX_ANY -1 diff --git a/net/nfc/core.c b/net/nfc/core.c index 334954a1d6e8..a43a56d7f4be 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -126,6 +126,13 @@ int nfc_dev_up(struct nfc_dev *dev) if (!rc) dev->dev_up = true; + /* We have to enable the device before discovering SEs */ + if (dev->ops->discover_se) { + rc = dev->ops->discover_se(dev); + if (!rc) + pr_warn("SE discovery failed\n"); + } + error: device_unlock(&dev->dev); return rc; diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 9c8a63d341d3..7b1c186736eb 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -692,6 +692,36 @@ static int hci_check_presence(struct nfc_dev *nfc_dev, return hdev->ops->check_presence(hdev, target); } +static int hci_discover_se(struct nfc_dev *nfc_dev) +{ + struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); + + if (hdev->ops->discover_se) + return hdev->ops->discover_se(hdev); + + return 0; +} + +static int hci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx) +{ + struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); + + if (hdev->ops->enable_se) + return hdev->ops->enable_se(hdev, se_idx); + + return 0; +} + +static int hci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) +{ + struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); + + if (hdev->ops->disable_se) + return hdev->ops->enable_se(hdev, se_idx); + + return 0; +} + static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) { mutex_lock(&hdev->msg_tx_mutex); @@ -802,6 +832,9 @@ static struct nfc_ops hci_nfc_ops = { .tm_send = hci_tm_send, .check_presence = hci_check_presence, .fw_upload = hci_fw_upload, + .discover_se = hci_discover_se, + .enable_se = hci_enable_se, + .disable_se = hci_disable_se, }; struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 145bad15e113..b943d46a1644 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -636,6 +636,21 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, return rc; } +static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx) +{ + return 0; +} + +static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) +{ + return 0; +} + +static int nci_discover_se(struct nfc_dev *nfc_dev) +{ + return 0; +} + static struct nfc_ops nci_nfc_ops = { .dev_up = nci_dev_up, .dev_down = nci_dev_down, @@ -646,6 +661,9 @@ static struct nfc_ops nci_nfc_ops = { .activate_target = nci_activate_target, .deactivate_target = nci_deactivate_target, .im_transceive = nci_transceive, + .enable_se = nci_enable_se, + .disable_se = nci_disable_se, + .discover_se = nci_discover_se, }; /* ---- Interface to NCI drivers ---- */ -- GitLab From fed7c25ec0d4894edfc36bbe5c5231e52f45483a Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 15:28:38 +0200 Subject: [PATCH 1183/2900] NFC: Add secure elements addition and removal API This API will allow NFC drivers to add and remove the secure elements they know about or detect. Typically this should be called (asynchronously or not) from the driver or the host interface stack detect_se hook. Signed-off-by: Samuel Ortiz --- include/net/nfc/nfc.h | 22 +++++++++++++++++++- include/uapi/linux/nfc.h | 4 +++- net/nfc/core.c | 45 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 5187ec70b66a..0e353f1658bb 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -97,6 +97,23 @@ struct nfc_target { u8 logical_idx; }; +/** + * nfc_se - A structure for NFC accessible secure elements. + * + * @idx: The secure element index. User space will enable or + * disable a secure element by its index. + * @type: The secure element type. It can be SE_UICC or + * SE_EMBEDDED. + * @state: The secure element state, either enabled or disabled. + * + */ +struct nfc_se { + struct list_head list; + u32 idx; + u16 type; + u16 state; +}; + struct nfc_genl_data { u32 poll_req_portid; struct mutex genl_data_mutex; @@ -118,7 +135,7 @@ struct nfc_dev { struct nfc_genl_data genl_data; u32 supported_protocols; - u32 active_se; + struct list_head secure_elements; int tx_headroom; int tx_tailroom; @@ -221,4 +238,7 @@ int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); void nfc_driver_failure(struct nfc_dev *dev, int err); +int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type); +int nfc_remove_se(struct nfc_dev *dev, u32 se_idx); + #endif /* __NET_NFC_H */ diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index fb304fb774cc..3a57cef0b986 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -199,10 +199,12 @@ enum nfc_sdp_attr { #define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B) /* NFC Secure Elements */ -#define NFC_SE_NONE 0x0 #define NFC_SE_UICC 0x1 #define NFC_SE_EMBEDDED 0x2 +#define NFC_SE_DISABLED 0x0 +#define NFC_SE_ENABLED 0x1 + struct sockaddr_nfc { sa_family_t sa_family; __u32 dev_idx; diff --git a/net/nfc/core.c b/net/nfc/core.c index a43a56d7f4be..dacadfbcacea 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -760,6 +760,49 @@ inline void nfc_driver_failure(struct nfc_dev *dev, int err) } EXPORT_SYMBOL(nfc_driver_failure); +int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) +{ + struct nfc_se *se, *n; + + pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); + + list_for_each_entry_safe(se, n, &dev->secure_elements, list) + if (se->idx == se_idx) + return -EALREADY; + + se = kzalloc(sizeof(struct nfc_se), GFP_KERNEL); + if (!se) + return -ENOMEM; + + se->idx = se_idx; + se->type = type; + se->state = NFC_SE_DISABLED; + INIT_LIST_HEAD(&se->list); + + list_add(&se->list, &dev->secure_elements); + + return 0; +} +EXPORT_SYMBOL(nfc_add_se); + +int nfc_remove_se(struct nfc_dev *dev, u32 se_idx) +{ + struct nfc_se *se, *n; + + pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); + + list_for_each_entry_safe(se, n, &dev->secure_elements, list) + if (se->idx == se_idx) { + list_del(&se->list); + kfree(se); + + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL(nfc_remove_se); + static void nfc_release(struct device *d) { struct nfc_dev *dev = to_nfc_dev(d); @@ -856,9 +899,9 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, dev->ops = ops; dev->supported_protocols = supported_protocols; - dev->active_se = NFC_SE_NONE; dev->tx_headroom = tx_headroom; dev->tx_tailroom = tx_tailroom; + INIT_LIST_HEAD(&dev->secure_elements); nfc_genl_data_init(&dev->genl_data); -- GitLab From 2757c3723c3d2b13e3a8bfaa034826f64e9cca43 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 15:47:37 +0200 Subject: [PATCH 1184/2900] NFC: Send netlink events for secure elements additions and removals When an NFC driver or host controller stack discovers a secure element, it will call nfc_add_se(). In order for userspace applications to use these secure elements, a netlink event will then be sent with the SE index and its type. With that information userspace applications can decide wether or not to enable SEs, through their indexes. Signed-off-by: Samuel Ortiz --- include/uapi/linux/nfc.h | 6 ++++ net/nfc/core.c | 14 +++++++++ net/nfc/netlink.c | 63 ++++++++++++++++++++++++++++++++++++++++ net/nfc/nfc.h | 3 ++ 4 files changed, 86 insertions(+) diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index 3a57cef0b986..caed0f324d5f 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h @@ -95,6 +95,8 @@ enum nfc_commands { NFC_CMD_LLC_SDREQ, NFC_EVENT_LLC_SDRES, NFC_CMD_FW_UPLOAD, + NFC_EVENT_SE_ADDED, + NFC_EVENT_SE_REMOVED, /* private: internal use only */ __NFC_CMD_AFTER_LAST }; @@ -125,6 +127,8 @@ enum nfc_commands { * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter * @NFC_ATTR_SE: Available Secure Elements * @NFC_ATTR_FIRMWARE_NAME: Free format firmware version + * @NFC_ATTR_SE_INDEX: Secure element index + * @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED) */ enum nfc_attrs { NFC_ATTR_UNSPEC, @@ -148,6 +152,8 @@ enum nfc_attrs { NFC_ATTR_SE, NFC_ATTR_LLC_SDP, NFC_ATTR_FIRMWARE_NAME, + NFC_ATTR_SE_INDEX, + NFC_ATTR_SE_TYPE, /* private: internal use only */ __NFC_ATTR_AFTER_LAST }; diff --git a/net/nfc/core.c b/net/nfc/core.c index dacadfbcacea..bb5f16cfc201 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -763,6 +763,7 @@ EXPORT_SYMBOL(nfc_driver_failure); int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) { struct nfc_se *se, *n; + int rc; pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); @@ -781,6 +782,14 @@ int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) list_add(&se->list, &dev->secure_elements); + rc = nfc_genl_se_added(dev, se_idx, type); + if (rc < 0) { + list_del(&se->list); + kfree(se); + + return rc; + } + return 0; } EXPORT_SYMBOL(nfc_add_se); @@ -788,11 +797,16 @@ EXPORT_SYMBOL(nfc_add_se); int nfc_remove_se(struct nfc_dev *dev, u32 se_idx) { struct nfc_se *se, *n; + int rc; pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); list_for_each_entry_safe(se, n, &dev->secure_elements, list) if (se->idx == se_idx) { + rc = nfc_genl_se_removed(dev, se_idx); + if (rc < 0) + return rc; + list_del(&se->list); kfree(se); diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index fdbc662c564a..8a11a3a27e69 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -426,6 +426,69 @@ int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list) return rc; } +int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, + NFC_EVENT_SE_ADDED); + if (!hdr) + goto free_msg; + + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || + nla_put_u32(msg, NFC_ATTR_SE_INDEX, se_idx) || + nla_put_u8(msg, NFC_ATTR_SE_TYPE, type)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); +free_msg: + nlmsg_free(msg); + return -EMSGSIZE; +} + +int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, + NFC_EVENT_SE_REMOVED); + if (!hdr) + goto free_msg; + + if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || + nla_put_u32(msg, NFC_ATTR_SE_INDEX, se_idx)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); + + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); +free_msg: + nlmsg_free(msg); + return -EMSGSIZE; +} + static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, u32 portid, u32 seq, struct netlink_callback *cb, diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index cf0c48165996..a6aeee094aa4 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -94,6 +94,9 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev); int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list); +int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type); +int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx); + struct nfc_dev *nfc_get_device(unsigned int idx); static inline void nfc_put_device(struct nfc_dev *dev) -- GitLab From ee656e9d0993144f4e4ad261aefeeaab9554cd3f Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 15:53:29 +0200 Subject: [PATCH 1185/2900] NFC: Remove and free all SEs when releasing an NFC device Signed-off-by: Samuel Ortiz --- net/nfc/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/nfc/core.c b/net/nfc/core.c index bb5f16cfc201..5b60b9ddfc8f 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -820,11 +820,19 @@ EXPORT_SYMBOL(nfc_remove_se); static void nfc_release(struct device *d) { struct nfc_dev *dev = to_nfc_dev(d); + struct nfc_se *se, *n; pr_debug("dev_name=%s\n", dev_name(&dev->dev)); nfc_genl_data_exit(&dev->genl_data); kfree(dev->targets); + + list_for_each_entry_safe(se, n, &dev->secure_elements, list) { + nfc_genl_se_removed(dev, se->idx); + list_del(&se->list); + kfree(se); + } + kfree(dev); } -- GitLab From c531c9ec2969860c98a8a47f501c4874278388d3 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 16:15:32 +0200 Subject: [PATCH 1186/2900] NFC: Add secure element enablement internal API Called via netlink, this API will enable or disable a specific secure element. When a secure element is enabled, it will handle card emulation and more generically ISO-DEP target mode, i.e. all target mode cases except for p2p target mode. Signed-off-by: Samuel Ortiz --- net/nfc/core.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-- net/nfc/nfc.h | 3 ++ 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/net/nfc/core.c b/net/nfc/core.c index 5b60b9ddfc8f..dc96a83aa6ab 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -528,6 +528,108 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, return rc; } +static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) +{ + struct nfc_se *se, *n; + + list_for_each_entry_safe(se, n, &dev->secure_elements, list) + if (se->idx == se_idx) + return se; + + return NULL; +} + +int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) +{ + + struct nfc_se *se; + int rc; + + pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); + + device_lock(&dev->dev); + + if (!device_is_registered(&dev->dev)) { + rc = -ENODEV; + goto error; + } + + if (!dev->dev_up) { + rc = -ENODEV; + goto error; + } + + if (dev->polling) { + rc = -EBUSY; + goto error; + } + + if (!dev->ops->enable_se || !dev->ops->disable_se) { + rc = -EOPNOTSUPP; + goto error; + } + + se = find_se(dev, se_idx); + if (!se) { + rc = -EINVAL; + goto error; + } + + if (se->type == NFC_SE_ENABLED) { + rc = -EALREADY; + goto error; + } + + rc = dev->ops->enable_se(dev, se_idx); + +error: + device_unlock(&dev->dev); + return rc; +} + +int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) +{ + + struct nfc_se *se; + int rc; + + pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); + + device_lock(&dev->dev); + + if (!device_is_registered(&dev->dev)) { + rc = -ENODEV; + goto error; + } + + if (!dev->dev_up) { + rc = -ENODEV; + goto error; + } + + if (!dev->ops->enable_se || !dev->ops->disable_se) { + rc = -EOPNOTSUPP; + goto error; + } + + se = find_se(dev, se_idx); + if (!se) { + rc = -EINVAL; + goto error; + } + + if (se->type == NFC_SE_DISABLED) { + rc = -EALREADY; + goto error; + } + + rc = dev->ops->disable_se(dev, se_idx); + +error: + device_unlock(&dev->dev); + return rc; +} + int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) { pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); @@ -762,14 +864,14 @@ EXPORT_SYMBOL(nfc_driver_failure); int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) { - struct nfc_se *se, *n; + struct nfc_se *se; int rc; pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); - list_for_each_entry_safe(se, n, &dev->secure_elements, list) - if (se->idx == se_idx) - return -EALREADY; + se = find_se(dev, se_idx); + if (se) + return -EALREADY; se = kzalloc(sizeof(struct nfc_se), GFP_KERNEL); if (!se) diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index a6aeee094aa4..ee85a1fc1b24 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h @@ -147,4 +147,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx); int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context); +int nfc_enable_se(struct nfc_dev *dev, u32 se_idx); +int nfc_disable_se(struct nfc_dev *dev, u32 se_idx); + #endif /* __LOCAL_NFC_H */ -- GitLab From be0856535c64697685af47c5bf2be9f36ab5ca08 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 10 May 2013 17:07:32 +0200 Subject: [PATCH 1187/2900] NFC: Add secure element enablement netlink API Enabling or disabling an NFC accessible secure element through netlink requires giving both an NFC controller and a secure element indexes. Once enabled the secure element will handle card emulation once polling starts. Signed-off-by: Samuel Ortiz --- net/nfc/netlink.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 8a11a3a27e69..b05ad909778f 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -1145,6 +1145,52 @@ int nfc_genl_fw_upload_done(struct nfc_dev *dev, const char *firmware_name) return -EMSGSIZE; } +static int nfc_genl_enable_se(struct sk_buff *skb, struct genl_info *info) +{ + struct nfc_dev *dev; + int rc; + u32 idx, se_idx; + + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || + !info->attrs[NFC_ATTR_SE_INDEX]) + return -EINVAL; + + idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); + se_idx = nla_get_u32(info->attrs[NFC_ATTR_SE_INDEX]); + + dev = nfc_get_device(idx); + if (!dev) + return -ENODEV; + + rc = nfc_enable_se(dev, se_idx); + + nfc_put_device(dev); + return rc; +} + +static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info) +{ + struct nfc_dev *dev; + int rc; + u32 idx, se_idx; + + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || + !info->attrs[NFC_ATTR_SE_INDEX]) + return -EINVAL; + + idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); + se_idx = nla_get_u32(info->attrs[NFC_ATTR_SE_INDEX]); + + dev = nfc_get_device(idx); + if (!dev) + return -ENODEV; + + rc = nfc_disable_se(dev, se_idx); + + nfc_put_device(dev); + return rc; +} + static struct genl_ops nfc_genl_ops[] = { { .cmd = NFC_CMD_GET_DEVICE, @@ -1209,6 +1255,16 @@ static struct genl_ops nfc_genl_ops[] = { .doit = nfc_genl_fw_upload, .policy = nfc_genl_policy, }, + { + .cmd = NFC_CMD_ENABLE_SE, + .doit = nfc_genl_enable_se, + .policy = nfc_genl_policy, + }, + { + .cmd = NFC_CMD_DISABLE_SE, + .doit = nfc_genl_disable_se, + .policy = nfc_genl_policy, + }, }; -- GitLab From 86eca4e71f41fb90800707cd05f580cd3e0cb836 Mon Sep 17 00:00:00 2001 From: Olivier Guiter Date: Mon, 3 Jun 2013 12:02:29 +0200 Subject: [PATCH 1188/2900] NFC: pn533: Fix ACR122 related debug output Instead of dumping ACR122 frames as errors, we use the print_hex_dump() dynamic debug APIs. We also print an accurate IC version, as the ACR122 is pn532 based. Signed-off-by: Olivier Guiter Signed-off-by: Samuel Ortiz --- drivers/nfc/pn533.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index a1b46aa7b4d5..bfb4a4e7c604 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -2501,7 +2501,7 @@ static void pn533_acr122_poweron_rdr_resp(struct urb *urb) nfc_dev_dbg(&urb->dev->dev, "%s", __func__); - print_hex_dump(KERN_ERR, "ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, + print_hex_dump_debug("ACR122 RX: ", DUMP_PREFIX_NONE, 16, 1, urb->transfer_buffer, urb->transfer_buffer_length, false); @@ -2532,7 +2532,7 @@ static int pn533_acr122_poweron_rdr(struct pn533 *dev) dev->out_urb->transfer_buffer = cmd; dev->out_urb->transfer_buffer_length = sizeof(cmd); - print_hex_dump(KERN_ERR, "ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, + print_hex_dump_debug("ACR122 TX: ", DUMP_PREFIX_NONE, 16, 1, cmd, sizeof(cmd), false); rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); @@ -2786,8 +2786,8 @@ static int pn533_probe(struct usb_interface *interface, goto destroy_wq; nfc_dev_info(&dev->interface->dev, - "NXP PN533 firmware ver %d.%d now attached", - fw_ver.ver, fw_ver.rev); + "NXP PN5%02X firmware ver %d.%d now attached", + fw_ver.ic, fw_ver.ver, fw_ver.rev); dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, -- GitLab From 58e3dd1558f56e95e7077a63340bb33e7aa42946 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Tue, 4 Jun 2013 11:34:50 +0200 Subject: [PATCH 1189/2900] NFC: Rename nfc_llcp_disconnect() to nfc_llcp_send_disconnect() nfc_llcp_send_disconnect() already exists but is not used. nfc_llcp_disconnect() naming is not consistent with other PDU sending functions. This patch removes nfc_llcp_send_disconnect() and renames nfc_llcp_disconnect() Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/llcp.h | 1 - net/nfc/llcp_commands.c | 22 +--------------------- net/nfc/llcp_sock.c | 4 ++-- 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index ff8c434f7df8..ac16ebe3069d 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -246,7 +246,6 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); -int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); int nfc_llcp_send_symm(struct nfc_dev *dev); int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c index c1b23eef83ca..1017894807c0 100644 --- a/net/nfc/llcp_commands.c +++ b/net/nfc/llcp_commands.c @@ -339,7 +339,7 @@ static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock, return skb; } -int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) +int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock) { struct sk_buff *skb; struct nfc_dev *dev; @@ -630,26 +630,6 @@ int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) return 0; } -int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock) -{ - struct sk_buff *skb; - struct nfc_llcp_local *local; - - pr_debug("Send DISC\n"); - - local = sock->local; - if (local == NULL) - return -ENODEV; - - skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0); - if (skb == NULL) - return -ENOMEM; - - skb_queue_head(&local->tx_queue, skb); - - return 0; -} - int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, struct msghdr *msg, size_t len) { diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 380253eccb74..03fd3162cee5 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -603,7 +603,7 @@ static int llcp_sock_release(struct socket *sock) /* Send a DISC */ if (sk->sk_state == LLCP_CONNECTED) - nfc_llcp_disconnect(llcp_sock); + nfc_llcp_send_disconnect(llcp_sock); if (sk->sk_state == LLCP_LISTEN) { struct nfc_llcp_sock *lsk, *n; @@ -614,7 +614,7 @@ static int llcp_sock_release(struct socket *sock) accept_sk = &lsk->sk; lock_sock(accept_sk); - nfc_llcp_disconnect(lsk); + nfc_llcp_send_disconnect(lsk); nfc_llcp_accept_unlink(accept_sk); release_sock(accept_sk); -- GitLab From 17f7ae16aef1f58bc4af4c7a16b8778a91a30255 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Tue, 4 Jun 2013 11:34:51 +0200 Subject: [PATCH 1190/2900] NFC: Keep socket alive until the DISC PDU is actually sent This patch keeps the socket alive and therefore does not remove it from the sockets list in the local until the DISC PDU has been actually sent. Otherwise we would reply with DM PDUs before sending the DISC one. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/llcp.h | 1 + net/nfc/llcp_core.c | 7 +++++++ net/nfc/llcp_sock.c | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index ac16ebe3069d..71f649e5ef49 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -19,6 +19,7 @@ enum llcp_state { LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ + LLCP_DISCONNECTING, LLCP_CLOSED, LLCP_BOUND, LLCP_LISTEN, diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 158bdbf668cc..1c4c048e0a1b 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -730,6 +730,13 @@ static void nfc_llcp_tx_work(struct work_struct *work) DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); + if (ptype == LLCP_PDU_DISC && sk != NULL && + sk->sk_state == LLCP_DISCONNECTING) { + nfc_llcp_sock_unlink(&local->sockets, sk); + sock_orphan(sk); + sock_put(sk); + } + if (ptype == LLCP_PDU_I) copy_skb = skb_copy(skb, GFP_ATOMIC); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 03fd3162cee5..47e7acfc0236 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -626,6 +626,13 @@ static int llcp_sock_release(struct socket *sock) release_sock(sk); + /* Keep this sock alive and therefore do not remove it from the sockets + * list until the DISC PDU has been actually sent. Otherwise we would + * reply with DM PDUs before sending the DISC one. + */ + if (sk->sk_state == LLCP_DISCONNECTING) + return err; + if (sock->type == SOCK_RAW) nfc_llcp_sock_unlink(&local->raw_sockets, sk); else -- GitLab From f1b79dc8915ebf176d6f1fcfc4fee001b6d5ca46 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Wed, 5 Jun 2013 17:15:59 +0200 Subject: [PATCH 1191/2900] NFC: Fix a potential memory leak In nfc_llcp_tx_work() the sk_buff is not freed when the llcp_sock is null and the PDU is an I one. Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- net/nfc/llcp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 1c4c048e0a1b..44730f0edfd8 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -719,6 +719,7 @@ static void nfc_llcp_tx_work(struct work_struct *work) llcp_sock = nfc_llcp_sock(sk); if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { + kfree_skb(skb); nfc_llcp_send_symm(local->dev); } else { struct sk_buff *copy_skb = NULL; -- GitLab From 7cbe0ff3e475b7268ad9b55057048b2299fd60e0 Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Thu, 6 Jun 2013 16:23:23 +0200 Subject: [PATCH 1192/2900] NFC: Add a nfc hardware simulation driver This driver declares two virtual NFC devices supporting NFC-DEP protocol. An LLCP connection can be established between them and all packets sent from one device is sent back to the other, acting as loopback devices. Once established, the LLCP link can be disconnected by disabling the target device (with rfkill, nfctool, or neard disable-adapter test script). Signed-off-by: Thierry Escande Signed-off-by: Samuel Ortiz --- drivers/nfc/Kconfig | 10 + drivers/nfc/Makefile | 1 + drivers/nfc/nfcsim.c | 541 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 552 insertions(+) create mode 100644 drivers/nfc/nfcsim.c diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 74a852e4e41f..b0b64ccb7d7d 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -36,6 +36,16 @@ config NFC_MEI_PHY If unsure, say N. +config NFC_SIM + tristate "NFC hardware simulator driver" + help + This driver declares two virtual NFC devices supporting NFC-DEP + protocol. An LLCP connection can be established between them and + all packets sent from one device is sent back to the other, acting as + loopback devices. + + If unsure, say N. + source "drivers/nfc/pn544/Kconfig" source "drivers/nfc/microread/Kconfig" diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index aa6bd657ef40..be7636abcb3f 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_NFC_MICROREAD) += microread/ obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_WILINK) += nfcwilink.o obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o +obj-$(CONFIG_NFC_SIM) += nfcsim.o ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c new file mode 100644 index 000000000000..c5c30fb1d7bf --- /dev/null +++ b/drivers/nfc/nfcsim.c @@ -0,0 +1,541 @@ +/* + * NFC hardware simulation driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include + +#define DEV_ERR(_dev, fmt, args...) nfc_dev_err(&_dev->nfc_dev->dev, \ + "%s: " fmt, __func__, ## args) + +#define DEV_DBG(_dev, fmt, args...) nfc_dev_dbg(&_dev->nfc_dev->dev, \ + "%s: " fmt, __func__, ## args) + +#define NFCSIM_VERSION "0.1" + +#define NFCSIM_POLL_NONE 0 +#define NFCSIM_POLL_INITIATOR 1 +#define NFCSIM_POLL_TARGET 2 +#define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET) + +struct nfcsim { + struct nfc_dev *nfc_dev; + + struct mutex lock; + + struct delayed_work recv_work; + + struct sk_buff *clone_skb; + + struct delayed_work poll_work; + u8 polling_mode; + u8 curr_polling_mode; + + u8 shutting_down; + + u8 up; + + u8 initiator; + + data_exchange_cb_t cb; + void *cb_context; + + struct nfcsim *peer_dev; +}; + +static struct nfcsim *dev0; +static struct nfcsim *dev1; + +struct workqueue_struct *wq; + +static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) +{ + DEV_DBG(dev, "shutdown=%d", shutdown); + + mutex_lock(&dev->lock); + + dev->polling_mode = NFCSIM_POLL_NONE; + dev->shutting_down = shutdown; + dev->cb = NULL; + dev_kfree_skb(dev->clone_skb); + dev->clone_skb = NULL; + + mutex_unlock(&dev->lock); + + cancel_delayed_work_sync(&dev->poll_work); + cancel_delayed_work_sync(&dev->recv_work); +} + +static int nfcsim_target_found(struct nfcsim *dev) +{ + struct nfc_target nfc_tgt; + + DEV_DBG(dev, ""); + + memset(&nfc_tgt, 0, sizeof(struct nfc_target)); + + nfc_tgt.supported_protocols = NFC_PROTO_NFC_DEP_MASK; + nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); + + return 0; +} + +static int nfcsim_dev_up(struct nfc_dev *nfc_dev) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, ""); + + mutex_lock(&dev->lock); + + dev->up = 1; + + mutex_unlock(&dev->lock); + + return 0; +} + +static int nfcsim_dev_down(struct nfc_dev *nfc_dev) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, ""); + + mutex_lock(&dev->lock); + + dev->up = 0; + + mutex_unlock(&dev->lock); + + return 0; +} + +static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, + struct nfc_target *target, + u8 comm_mode, u8 *gb, size_t gb_len) +{ + int rc; + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + struct nfcsim *peer = dev->peer_dev; + u8 *remote_gb; + size_t remote_gb_len; + + DEV_DBG(dev, "target_idx: %d, comm_mode: %d\n", target->idx, comm_mode); + + mutex_lock(&peer->lock); + + nfc_tm_activated(peer->nfc_dev, NFC_PROTO_NFC_DEP_MASK, + NFC_COMM_ACTIVE, gb, gb_len); + + remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); + if (!remote_gb) { + DEV_ERR(peer, "Can't get remote general bytes"); + + mutex_unlock(&peer->lock); + return -EINVAL; + } + + mutex_unlock(&peer->lock); + + mutex_lock(&dev->lock); + + rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); + if (rc) { + DEV_ERR(dev, "Can't set remote general bytes"); + mutex_unlock(&dev->lock); + return rc; + } + + rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_ACTIVE, + NFC_RF_INITIATOR); + + mutex_unlock(&dev->lock); + + return rc; +} + +static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, ""); + + nfcsim_cleanup_dev(dev, 0); + + return 0; +} + +static int nfcsim_start_poll(struct nfc_dev *nfc_dev, + u32 im_protocols, u32 tm_protocols) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + int rc; + + mutex_lock(&dev->lock); + + if (dev->polling_mode != NFCSIM_POLL_NONE) { + DEV_ERR(dev, "Already in polling mode"); + rc = -EBUSY; + goto exit; + } + + if (im_protocols & NFC_PROTO_NFC_DEP_MASK) + dev->polling_mode |= NFCSIM_POLL_INITIATOR; + + if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) + dev->polling_mode |= NFCSIM_POLL_TARGET; + + if (dev->polling_mode == NFCSIM_POLL_NONE) { + DEV_ERR(dev, "Unsupported polling mode"); + rc = -EINVAL; + goto exit; + } + + dev->initiator = 0; + dev->curr_polling_mode = NFCSIM_POLL_NONE; + + queue_delayed_work(wq, &dev->poll_work, 0); + + DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X", im_protocols, + tm_protocols); + + rc = 0; +exit: + mutex_unlock(&dev->lock); + + return rc; +} + +static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, "Stop poll"); + + mutex_lock(&dev->lock); + + dev->polling_mode = NFCSIM_POLL_NONE; + + mutex_unlock(&dev->lock); + + cancel_delayed_work_sync(&dev->poll_work); +} + +static int nfcsim_activate_target(struct nfc_dev *nfc_dev, + struct nfc_target *target, u32 protocol) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, ""); + + return -ENOTSUPP; +} + +static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, + struct nfc_target *target) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + + DEV_DBG(dev, ""); +} + +static void nfcsim_wq_recv(struct work_struct *work) +{ + struct nfcsim *dev = container_of(work, struct nfcsim, + recv_work.work); + + mutex_lock(&dev->lock); + + if (dev->shutting_down || !dev->up || !dev->clone_skb) { + dev_kfree_skb(dev->clone_skb); + goto exit; + } + + if (dev->initiator) { + if (!dev->cb) { + DEV_ERR(dev, "Null recv callback"); + dev_kfree_skb(dev->clone_skb); + goto exit; + } + + dev->cb(dev->cb_context, dev->clone_skb, 0); + dev->cb = NULL; + } else { + nfc_tm_data_received(dev->nfc_dev, dev->clone_skb); + } + +exit: + dev->clone_skb = NULL; + + mutex_unlock(&dev->lock); +} + +static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, + struct sk_buff *skb, data_exchange_cb_t cb, + void *cb_context) +{ + struct nfcsim *dev = nfc_get_drvdata(nfc_dev); + struct nfcsim *peer = dev->peer_dev; + int err; + + mutex_lock(&dev->lock); + + if (dev->shutting_down || !dev->up) { + mutex_unlock(&dev->lock); + err = -ENODEV; + goto exit; + } + + dev->cb = cb; + dev->cb_context = cb_context; + + mutex_unlock(&dev->lock); + + mutex_lock(&peer->lock); + + peer->clone_skb = skb_clone(skb, GFP_KERNEL); + + if (!peer->clone_skb) { + DEV_ERR(dev, "skb_clone failed"); + mutex_unlock(&peer->lock); + err = -ENOMEM; + goto exit; + } + + /* This simulates an arbitrary transmission delay between the 2 devices. + * If packet transmission occurs immediately between them, we have a + * non-stop flow of several tens of thousands SYMM packets per second + * and a burning cpu. + * + * TODO: Add support for a sysfs entry to control this delay. + */ + queue_delayed_work(wq, &peer->recv_work, msecs_to_jiffies(5)); + + mutex_unlock(&peer->lock); + + err = 0; +exit: + dev_kfree_skb(skb); + + return err; +} + +static int nfcsim_im_transceive(struct nfc_dev *nfc_dev, + struct nfc_target *target, struct sk_buff *skb, + data_exchange_cb_t cb, void *cb_context) +{ + return nfcsim_tx(nfc_dev, target, skb, cb, cb_context); +} + +static int nfcsim_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) +{ + return nfcsim_tx(nfc_dev, NULL, skb, NULL, NULL); +} + +static struct nfc_ops nfcsim_nfc_ops = { + .dev_up = nfcsim_dev_up, + .dev_down = nfcsim_dev_down, + .dep_link_up = nfcsim_dep_link_up, + .dep_link_down = nfcsim_dep_link_down, + .start_poll = nfcsim_start_poll, + .stop_poll = nfcsim_stop_poll, + .activate_target = nfcsim_activate_target, + .deactivate_target = nfcsim_deactivate_target, + .im_transceive = nfcsim_im_transceive, + .tm_send = nfcsim_tm_send, +}; + +static void nfcsim_set_polling_mode(struct nfcsim *dev) +{ + if (dev->polling_mode == NFCSIM_POLL_NONE) { + dev->curr_polling_mode = NFCSIM_POLL_NONE; + return; + } + + if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { + if (dev->polling_mode & NFCSIM_POLL_INITIATOR) + dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; + else + dev->curr_polling_mode = NFCSIM_POLL_TARGET; + + return; + } + + if (dev->polling_mode == NFCSIM_POLL_DUAL) { + if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) + dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; + else + dev->curr_polling_mode = NFCSIM_POLL_TARGET; + } +} + +static void nfcsim_wq_poll(struct work_struct *work) +{ + struct nfcsim *dev = container_of(work, struct nfcsim, poll_work.work); + struct nfcsim *peer = dev->peer_dev; + + /* These work items run on an ordered workqueue and are therefore + * serialized. So we can take both mutexes without being dead locked. + */ + mutex_lock(&dev->lock); + mutex_lock(&peer->lock); + + nfcsim_set_polling_mode(dev); + + if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { + DEV_DBG(dev, "Not polling"); + goto unlock; + } + + DEV_DBG(dev, "Polling as %s", + dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? + "initiator" : "target"); + + if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) + goto sched_work; + + if (peer->curr_polling_mode == NFCSIM_POLL_TARGET) { + peer->polling_mode = NFCSIM_POLL_NONE; + dev->polling_mode = NFCSIM_POLL_NONE; + + dev->initiator = 1; + + nfcsim_target_found(dev); + + goto unlock; + } + +sched_work: + /* This defines the delay for an initiator to check if the other device + * is polling in target mode. + * If the device starts in dual mode polling, it switches between + * initiator and target at every round. + * Because the wq is ordered and only 1 work item is executed at a time, + * we'll always have one device polling as initiator and the other as + * target at some point, even if both are started in dual mode. + */ + queue_delayed_work(wq, &dev->poll_work, msecs_to_jiffies(200)); + +unlock: + mutex_unlock(&peer->lock); + mutex_unlock(&dev->lock); +} + +static struct nfcsim *nfcsim_init_dev(void) +{ + struct nfcsim *dev; + int rc = -ENOMEM; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) + return ERR_PTR(-ENOMEM); + + mutex_init(&dev->lock); + + INIT_DELAYED_WORK(&dev->recv_work, nfcsim_wq_recv); + INIT_DELAYED_WORK(&dev->poll_work, nfcsim_wq_poll); + + dev->nfc_dev = nfc_allocate_device(&nfcsim_nfc_ops, + NFC_PROTO_NFC_DEP_MASK, + 0, 0); + if (!dev->nfc_dev) + goto error; + + nfc_set_drvdata(dev->nfc_dev, dev); + + rc = nfc_register_device(dev->nfc_dev); + if (rc) + goto free_nfc_dev; + + return dev; + +free_nfc_dev: + nfc_free_device(dev->nfc_dev); + +error: + kfree(dev); + + return ERR_PTR(rc); +} + +static void nfcsim_free_device(struct nfcsim *dev) +{ + nfc_unregister_device(dev->nfc_dev); + + nfc_free_device(dev->nfc_dev); + + kfree(dev); +} + +int __init nfcsim_init(void) +{ + int rc; + + /* We need an ordered wq to ensure that poll_work items are executed + * one at a time. + */ + wq = alloc_ordered_workqueue("nfcsim", 0); + if (!wq) { + rc = -ENOMEM; + goto exit; + } + + dev0 = nfcsim_init_dev(); + if (IS_ERR(dev0)) { + rc = PTR_ERR(dev0); + goto exit; + } + + dev1 = nfcsim_init_dev(); + if (IS_ERR(dev1)) { + kfree(dev0); + + rc = PTR_ERR(dev1); + goto exit; + } + + dev0->peer_dev = dev1; + dev1->peer_dev = dev0; + + pr_debug("NFCsim " NFCSIM_VERSION " initialized\n"); + + rc = 0; +exit: + if (rc) + pr_err("Failed to initialize nfcsim driver (%d)\n", + rc); + + return rc; +} + +void __exit nfcsim_exit(void) +{ + nfcsim_cleanup_dev(dev0, 1); + nfcsim_cleanup_dev(dev1, 1); + + nfcsim_free_device(dev0); + nfcsim_free_device(dev1); + + destroy_workqueue(wq); +} + +module_init(nfcsim_init); +module_exit(nfcsim_exit); + +MODULE_DESCRIPTION("NFCSim driver ver " NFCSIM_VERSION); +MODULE_VERSION(NFCSIM_VERSION); +MODULE_LICENSE("GPL"); -- GitLab From b4011239a08e7e6c2c6e970dfa9e8ecb73139261 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 3 May 2013 18:29:30 +0200 Subject: [PATCH 1193/2900] NFC: llcp: Fix non blocking sockets connections Without the new LLCP_CONNECTING state, non blocking sockets will be woken up with a POLLHUP right after calling connect() because their state is stuck at LLCP_CLOSED. That prevents userspace from implementing any proper non blocking socket based NFC p2p client. Cc: stable@vger.kernel.org Signed-off-by: Samuel Ortiz --- net/nfc/llcp.h | 1 + net/nfc/llcp_sock.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index 71f649e5ef49..f4d48b57ea11 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -19,6 +19,7 @@ enum llcp_state { LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ + LLCP_CONNECTING, LLCP_DISCONNECTING, LLCP_CLOSED, LLCP_BOUND, diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 47e7acfc0236..d308402b67d8 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -571,7 +571,7 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock, if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; - if (sock_writeable(sk)) + if (sock_writeable(sk) && sk->sk_state == LLCP_CONNECTED) mask |= POLLOUT | POLLWRNORM | POLLWRBAND; else set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); @@ -729,14 +729,16 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, if (ret) goto sock_unlink; + sk->sk_state = LLCP_CONNECTING; + ret = sock_wait_state(sk, LLCP_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); - if (ret) + if (ret && ret != -EINPROGRESS) goto sock_unlink; release_sock(sk); - return 0; + return ret; sock_unlink: nfc_llcp_put_ssap(local, llcp_sock->ssap); -- GitLab From 2635a4bdfa8d513c531fa7d7a0ccafc1d6a9ff85 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 28 May 2013 15:03:17 +0200 Subject: [PATCH 1194/2900] NFC: llcp: Do not send pending Tx frames when the remote is not ready When we receive a RNR, the remote is busy processing the last received frame. We set a local flag for that, and we should send a SYMM when it is set instead of sending any pending frame. Signed-off-by: Samuel Ortiz --- net/nfc/llcp_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 44730f0edfd8..47746a088f8f 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -721,6 +721,9 @@ static void nfc_llcp_tx_work(struct work_struct *work) if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { kfree_skb(skb); nfc_llcp_send_symm(local->dev); + } else if (llcp_sock && !llcp_sock->remote_ready) { + skb_queue_head(&local->tx_queue, skb); + nfc_llcp_send_symm(local->dev); } else { struct sk_buff *copy_skb = NULL; u8 ptype = nfc_llcp_ptype(skb); -- GitLab From f768b34017cbe6e7690686514f682f076bb1f477 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 28 May 2013 15:41:32 +0200 Subject: [PATCH 1195/2900] NFC: llcp: Set the LLC Link Management well known service bit In order to advertise our LLCP support properly and to follow the LLCP specs requirements, we need to initialize the WKS (Well-Known Services) bitfield to 1 as SAP 0 is the only mandatory supported service. Signed-off-by: Samuel Ortiz --- net/nfc/llcp_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 47746a088f8f..d45bcbbc9f78 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -1590,6 +1590,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->lto = 150; /* 1500 ms */ local->rw = LLCP_MAX_RW; local->miux = cpu_to_be16(LLCP_MAX_MIUX); + local->local_wks = 0x1; /* LLC Link Management */ nfc_llcp_build_gb(local); -- GitLab From 4ca546e5545b7345b69e9331ecd53a1e4c6f7fe1 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 3 Jun 2013 12:10:04 +0200 Subject: [PATCH 1196/2900] NFC: llcp: Fix the well known services endianness The WKS (Well Known Services) bitmask should be transmitted in big endian order. Picky implementations will refuse to establish an LLCP link when the WKS bit 0 is not set to 1. The vast majority of implementations out there are not that picky though... Signed-off-by: Samuel Ortiz --- net/nfc/llcp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index d45bcbbc9f78..81cd3416c7d4 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -537,6 +537,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) u8 *lto_tlv, lto_length; u8 *wks_tlv, wks_length; u8 *miux_tlv, miux_length; + __be16 wks = cpu_to_be16(local->local_wks); u8 gb_len = 0; int ret = 0; @@ -549,8 +550,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) gb_len += lto_length; pr_debug("Local wks 0x%lx\n", local->local_wks); - wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2, - &wks_length); + wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&wks, 2, &wks_length); gb_len += wks_length; miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, -- GitLab From bda7eb27635c4d7414fb05a5f55501b71f436cc0 Mon Sep 17 00:00:00 2001 From: Valentin Ilie Date: Fri, 7 Jun 2013 22:01:55 +0300 Subject: [PATCH 1197/2900] NFC: mei_phy: Clean up file Fix checkpatch warnings. Replace __attribute__((__packed__)) with __packed. Replace spaces with tabs. Signed-off-by: Valentin Ilie Signed-off-by: Samuel Ortiz --- drivers/nfc/mei_phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index 1201bdbfb791..606bf55e76ec 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -30,7 +30,7 @@ struct mei_nfc_hdr { u16 req_id; u32 reserved; u16 data_size; -} __attribute__((packed)); +} __packed; #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) @@ -60,8 +60,8 @@ int nfc_mei_phy_enable(void *phy_id) r = mei_cl_enable_device(phy->device); if (r < 0) { - pr_err("MEI_PHY: Could not enable device\n"); - return r; + pr_err("MEI_PHY: Could not enable device\n"); + return r; } r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy); -- GitLab From 1f0a6742dd900b866c046e29d287c28f0df9bd51 Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Thu, 6 Jun 2013 23:39:52 +0200 Subject: [PATCH 1198/2900] Coccinelle: Make 'report' the default mode It appears that the 'report' mode is the one always provided by the semantic patches included in the kernel. It is thus more natural to select it by default. The 'chain' mode is however kept and the 'patch' mode is still the first tried in that case. Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- scripts/coccicheck | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/coccicheck b/scripts/coccicheck index 06fcb3333247..9d8780cdbcd4 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -44,11 +44,19 @@ fi if [ "$MODE" = "" ] ; then if [ "$ONLINE" = "0" ] ; then - echo 'You have not explicitly specified the mode to use. Using default "chain" mode.' - echo 'All available modes will be tried (in that order): patch, report, context, org' + echo 'You have not explicitly specified the mode to use. Using default "report" mode.' + echo 'Available modes are the following: patch, report, context, org' echo 'You can specify the mode with "make coccicheck MODE="' + echo 'Note however that some modes are not implemented by some semantic patches.' + fi + MODE="report" +fi + +if [ "$MODE" = "chain" ] ; then + if [ "$ONLINE" = "0" ] ; then + echo 'You have selected the "chain" mode.' + echo 'All available modes will be tried (in that order): patch, report, context, org' fi - MODE="chain" elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then FLAGS="$FLAGS -no_show_diff" fi -- GitLab From c00b511026eba6a8c58588043d59fec25c06c098 Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Thu, 6 Jun 2013 23:39:53 +0200 Subject: [PATCH 1199/2900] Coccinelle: Update the Coccinelle section of MAINTAINERS Add Michal Marek and the misc branch of the kbuild tree in the Coccinelle section of MAINTAINERS. Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3d7782b9f90d..73b1b3a38ff0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2098,7 +2098,9 @@ COCCINELLE/Semantic Patches (SmPL) M: Julia Lawall M: Gilles Muller M: Nicolas Palix +M: Michal Marek L: cocci@systeme.lip6.fr (moderated for non-subscribers) +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git misc W: http://coccinelle.lip6.fr/ S: Supported F: scripts/coccinelle/ -- GitLab From 61cb48c3f93adee633f996dd40ff5267fae55b3a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 8 Jun 2013 18:21:42 +0200 Subject: [PATCH 1200/2900] scripts/coccinelle: check for field address argument to kfree The argument to kfree should not be the address of a structure field. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/free/kfreeaddr.cocci | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 scripts/coccinelle/free/kfreeaddr.cocci diff --git a/scripts/coccinelle/free/kfreeaddr.cocci b/scripts/coccinelle/free/kfreeaddr.cocci new file mode 100644 index 000000000000..662e997da834 --- /dev/null +++ b/scripts/coccinelle/free/kfreeaddr.cocci @@ -0,0 +1,32 @@ +/// Free of a structure field +/// +// Confidence: High +// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: -no_includes -include_headers + +virtual org +virtual report +virtual context + +@r depends on context || report || org @ +expression e; +identifier f; +position p; +@@ + +* kfree@p(&e->f) + +@script:python depends on org@ +p << r.p; +@@ + +cocci.print_main("kfree",p) + +@script:python depends on report@ +p << r.p; +@@ + +msg = "ERROR: kfree of structure field" +coccilib.report.print_report(p[0],msg) -- GitLab From 9b60b64bfe98b9cc01b21e6126819b11a0f0a971 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 13 Jun 2013 22:51:26 +0530 Subject: [PATCH 1201/2900] ath9k: Add custom parameters for CUS198 CUS198 is a card based on AR9485. There are differences between the base reference design HB125 and CUS198. Identify such cards based on the PCI subsystem IDs and set HW parameters appropriately. Addresses this bug - https://bugzilla.kernel.org/show_bug.cgi?id=49201 Cc: jkp@iki.fi Cc: gfmichaud@gmail.com Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 18 ++++++++++-- drivers/net/wireless/ath/ath9k/ath9k.h | 3 ++ drivers/net/wireless/ath/ath9k/hw.h | 4 +++ drivers/net/wireless/ath/ath9k/init.c | 21 ++++++++++++++ drivers/net/wireless/ath/ath9k/pci.c | 29 +++++++++++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 25b8bbbe74fe..9a00bc0a9304 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3563,16 +3563,22 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { struct ath9k_hw_capabilities *pCap = &ah->caps; int chain; - u32 regval, value; + u32 regval, value, gpio; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, AR_PHY_SWITCH_CHAIN_2, }; - if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) + if (AR_SREV_9485(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) { + if (ah->config.xlna_gpio) + gpio = ah->config.xlna_gpio; + else + gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485; + ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485, AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); + } value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); @@ -3800,7 +3806,13 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); - value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + if (AR_SREV_9485(ah) && + (ar9003_hw_get_rx_gain_idx(ah) == 0) && + ah->config.xatten_margin_cfg) + value = 5; + else + value = ar9003_hw_atten_chain_get_margin(ah, i, chan); + REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index a6e666bcc0a7..74965eefbd1c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -631,6 +631,8 @@ void ath_ant_comb_update(struct ath_softc *sc); /* Main driver core */ /********************/ +#define ATH9K_PCI_CUS198 0x0001 + /* * Default cache line size, in bytes. * Used when PCI device not fully initialized by bootrom/BIOS @@ -715,6 +717,7 @@ struct ath_softc { unsigned int hw_busy_count; unsigned long sc_flags; + unsigned long driver_data; u32 intrstatus; u16 ps_flags; /* PS_* */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7d259b7dc254..ed7d4fcbdcab 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -307,6 +307,10 @@ struct ath9k_ops_config { u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; u8 max_txtrig_level; u16 ani_poll_interval; /* ANI poll interval in ms */ + + /* Platform specific config */ + u32 xlna_gpio; + bool xatten_margin_cfg; }; enum ath9k_int { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 818f22daa8ba..7c2ed1cef9b7 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -513,6 +513,22 @@ static void ath9k_init_misc(struct ath_softc *sc) sc->spec_config.fft_period = 0xF; } +static void ath9k_init_platform(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + + if (common->bus_ops->ath_bus_type != ATH_PCI) + return; + + if (sc->driver_data & ATH9K_PCI_CUS198) { + ah->config.xlna_gpio = 9; + ah->config.xatten_margin_cfg = true; + + ath_info(common, "Set parameters for CUS198\n"); + } +} + static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, void *ctx) { @@ -604,6 +620,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->btcoex_enabled = ath9k_btcoex_enable == 1; common->disable_ani = false; + /* + * Platform quirks. + */ + ath9k_init_platform(sc); + /* * Enable Antenna diversity only when BTCOEX is disabled * and the user manually requests the feature. diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 0e0d39583837..4ac00b4b0d25 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -34,6 +34,34 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ + + /* PCI-E CUS198 */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0032, + PCI_VENDOR_ID_AZWAVE, + 0x2086), + .driver_data = ATH9K_PCI_CUS198 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0032, + PCI_VENDOR_ID_AZWAVE, + 0x1237), + .driver_data = ATH9K_PCI_CUS198 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0032, + PCI_VENDOR_ID_AZWAVE, + 0x2126), + .driver_data = ATH9K_PCI_CUS198 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0032, + PCI_VENDOR_ID_AZWAVE, + 0x2152), + .driver_data = ATH9K_PCI_CUS198 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0032, + PCI_VENDOR_ID_FOXCONN, + 0xE075), + .driver_data = ATH9K_PCI_CUS198 }, + { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ @@ -221,6 +249,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->hw = hw; sc->dev = &pdev->dev; sc->mem = pcim_iomap_table(pdev)[0]; + sc->driver_data = id->driver_data; /* Will be cleared in ath9k_start() */ set_bit(SC_OP_INVALID, &sc->sc_flags); -- GitLab From 1105a13bb8ad29cf83d46989ee462d196038be87 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 14 Jun 2013 00:26:11 +0400 Subject: [PATCH 1202/2900] orinoco_usb: fix memory leak in ezusb_access_ltv() when device disconnected If "device is disconnected" check occurs to be true in ezusb_access_ltv(), it just return -ENODEV. But that means request_context is leaked since there are no any references to it anymore. The patch adds a call to ezusb_request_context_put() before return. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco/orinoco_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 1f9cb55c3360..bdfe637953f4 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -881,7 +881,8 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, if (!upriv->udev) { dbg("Device disconnected"); - return -ENODEV; + retval = -ENODEV; + goto exit; } if (upriv->read_urb->status != -EINPROGRESS) -- GitLab From f44f340883388b57fe03edfb0982e038e57a992c Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 13 May 2013 08:15:26 -0700 Subject: [PATCH 1203/2900] openvswitch: Immediately exit on error in ovs_vport_cmd_set(). It is an error to try to change the type of a vport using the set command. However, while we check that this is an error, we still proceed to allocate memory which then gets freed immediately. This stops processing after noticing the error, which does not actually fix a bug but is more correct. Signed-off-by: Jesse Gross --- net/openvswitch/datapath.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d12d6b8b5e8b..748aa97cbfb2 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1812,10 +1812,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(vport)) goto exit_unlock; - err = 0; if (a[OVS_VPORT_ATTR_TYPE] && - nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) + nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) { err = -EINVAL; + goto exit_unlock; + } reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!reply) { @@ -1823,10 +1824,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) goto exit_unlock; } - if (!err && a[OVS_VPORT_ATTR_OPTIONS]) + if (a[OVS_VPORT_ATTR_OPTIONS]) { err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); - if (err) - goto exit_free; + if (err) + goto exit_free; + } if (a[OVS_VPORT_ATTR_UPCALL_PID]) vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); -- GitLab From cbd531bebb02bc6c0fc3619a2cfc32f7d8843b18 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 13 May 2013 08:16:29 -0700 Subject: [PATCH 1204/2900] openvswitch: Remove unused get_config vport op. The get_config vport op is left over from old compatibility code, it is neither used nor implemented any more. Signed-off-by: Jesse Gross --- net/openvswitch/vport-netdev.h | 1 - net/openvswitch/vport.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h index a3cb3a32cd77..dd298b5c5cdb 100644 --- a/net/openvswitch/vport-netdev.h +++ b/net/openvswitch/vport-netdev.h @@ -39,6 +39,5 @@ netdev_vport_priv(const struct vport *vport) } const char *ovs_netdev_get_name(const struct vport *); -const char *ovs_netdev_get_config(const struct vport *); #endif /* vport_netdev.h */ diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 68a377bc0841..26c594b1a470 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -123,8 +123,6 @@ struct vport_parms { * existing vport to a &struct sk_buff. May be %NULL for a vport that does not * have any configuration. * @get_name: Get the device's name. - * @get_config: Get the device's configuration. - * May be null if the device does not have an ifindex. * @send: Send a packet on the device. Returns the length of the packet sent. */ struct vport_ops { @@ -139,7 +137,6 @@ struct vport_ops { /* Called with rcu_read_lock or ovs_mutex. */ const char *(*get_name)(const struct vport *); - void (*get_config)(const struct vport *, void *); int (*send)(struct vport *, struct sk_buff *); }; -- GitLab From 91b7514cdff406ad8f63d09b74f664c37bed2e01 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 13 May 2013 08:22:34 -0700 Subject: [PATCH 1205/2900] openvswitch: Unify vport error stats handling. Following patch changes vport->send return type so that vport layer can do error accounting. Signed-off-by: Pravin B Shelar Signed-off-by: Jesse Gross --- net/openvswitch/vport-netdev.c | 5 ++--- net/openvswitch/vport.c | 9 +++++++-- net/openvswitch/vport.h | 3 ++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 4f01c6d2ffa4..43712217a372 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -170,7 +170,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb) net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n", netdev_vport->dev->name, packet_length(skb), mtu); - goto error; + goto drop; } skb->dev = netdev_vport->dev; @@ -179,9 +179,8 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb) return len; -error: +drop: kfree_skb(skb); - ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); return 0; } diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 720623190eaa..7f20f6d1be94 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -351,7 +351,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) { int sent = vport->ops->send(vport, skb); - if (likely(sent)) { + if (likely(sent > 0)) { struct pcpu_tstats *stats; stats = this_cpu_ptr(vport->percpu_stats); @@ -360,7 +360,12 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) stats->tx_packets++; stats->tx_bytes += sent; u64_stats_update_end(&stats->syncp); - } + } else if (sent < 0) { + ovs_vport_record_error(vport, VPORT_E_TX_ERROR); + kfree_skb(skb); + } else + ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); + return sent; } diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 26c594b1a470..1cef5cd3be47 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -123,7 +123,8 @@ struct vport_parms { * existing vport to a &struct sk_buff. May be %NULL for a vport that does not * have any configuration. * @get_name: Get the device's name. - * @send: Send a packet on the device. Returns the length of the packet sent. + * @send: Send a packet on the device. Returns the length of the packet sent, + * zero for dropped packets or negative for error. */ struct vport_ops { enum ovs_vport_type type; -- GitLab From 34d94f2102fb361030569eb983751ed80742f6e9 Mon Sep 17 00:00:00 2001 From: Lorand Jakab Date: Mon, 3 Jun 2013 10:01:14 -0700 Subject: [PATCH 1206/2900] openvswitch: fix variable names in comment Signed-off-by: Lorand Jakab Signed-off-by: Jesse Gross --- net/openvswitch/flow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index b15321a2228c..33df0913358d 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -590,10 +590,10 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, * - skb->network_header: just past the Ethernet header, or just past the * VLAN header, to the first byte of the Ethernet payload. * - * - skb->transport_header: If key->dl_type is ETH_P_IP or ETH_P_IPV6 + * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 * on output, then just past the IP header, if one is present and * of a correct length, otherwise the same as skb->network_header. - * For other key->dl_type values it is left untouched. + * For other key->eth.type values it is left untouched. */ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, int *key_lenp) -- GitLab From af7841636bb29575fe27faaeb351146e87217717 Mon Sep 17 00:00:00 2001 From: Andy Hill Date: Fri, 7 Jun 2013 16:53:50 -0700 Subject: [PATCH 1207/2900] openvswitch: Fix misspellings in comments and docs. Flagged with: https://github.com/lyda/misspell-check Run with: git ls-files | misspellings -f - Signed-off-by: Andy Hill Signed-off-by: Jesse Gross --- net/openvswitch/vport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 7f20f6d1be94..176d449351eb 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -376,7 +376,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) * @err_type: one of enum vport_err_type types to indicate the error type * * If using the vport generic stats layer indicate that an error of the given - * type has occured. + * type has occurred. */ void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type) { -- GitLab From 45bfa52e36ef016b789eca73c7847db3f7b4742d Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Wed, 12 Jun 2013 15:57:10 -0700 Subject: [PATCH 1208/2900] openvswitch: Fix struct comment. Signed-off-by: Pravin B Shelar Signed-off-by: Jesse Gross --- include/uapi/linux/openvswitch.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 405918dd7b3f..424672db7f12 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -192,7 +192,6 @@ enum ovs_vport_type { * optional; if not specified a free port number is automatically selected. * Whether %OVS_VPORT_ATTR_OPTIONS is required or optional depends on the type * of vport. - * and other attributes are ignored. * * For other requests, if %OVS_VPORT_ATTR_NAME is specified then it is used to * look up the vport to operate on; otherwise dp_idx from the &struct -- GitLab From b34df5e805a6e98cae0bc5bc80c1b52d9ff811de Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 13 Jun 2013 11:11:44 -0700 Subject: [PATCH 1209/2900] openvswitch: make skb->csum consistent with rest of networking stack. Following patch keeps skb->csum correct across ovs. Signed-off-by: Pravin B Shelar Signed-off-by: Jesse Gross --- net/openvswitch/actions.c | 4 ++++ net/openvswitch/flow.c | 3 +++ net/openvswitch/vport-internal_dev.c | 1 + net/openvswitch/vport-netdev.c | 2 ++ net/openvswitch/vport.h | 7 +++++++ 5 files changed, 17 insertions(+) diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 894b6cbdd929..596d6373399d 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -130,9 +130,13 @@ static int set_eth_addr(struct sk_buff *skb, if (unlikely(err)) return err; + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); + memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN); memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN); + ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); + return 0; } diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 33df0913358d..fca483360ce2 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -618,6 +618,9 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, memcpy(key->eth.dst, eth->h_dest, ETH_ALEN); __skb_pull(skb, 2 * ETH_ALEN); + /* We are going to push all headers that we pull, so no need to + * update skb->csum here. + */ if (vlan_tx_tag_present(skb)) key->eth.tci = htons(skb->vlan_tci); diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 84e0a0379186..e284c7e1fec4 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -221,6 +221,7 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb) skb->dev = netdev; skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, netdev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); netif_rx(skb); diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 43712217a372..40de815b4213 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -49,6 +49,8 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb) return; skb_push(skb, ETH_HLEN); + ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN); + ovs_vport_receive(vport, skb); return; diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 1cef5cd3be47..293278c4c2df 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -192,4 +192,11 @@ void ovs_vport_record_error(struct vport *, enum vport_err_type err_type); extern const struct vport_ops ovs_netdev_vport_ops; extern const struct vport_ops ovs_internal_vport_ops; +static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb, + const void *start, unsigned int len) +{ + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_add(skb->csum, csum_partial(start, len, 0)); +} + #endif /* vport.h */ -- GitLab From 93d8fd1514b6862c3370ea92be3f3b4216e0bf8f Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 13 Jun 2013 11:11:32 -0700 Subject: [PATCH 1210/2900] openvswitch: Simplify interface ovs_flow_metadata_from_nlattrs() This is not functional change, this is just code cleanup. Signed-off-by: Pravin B Shelar Signed-off-by: Jesse Gross --- net/openvswitch/datapath.c | 5 +---- net/openvswitch/flow.c | 22 ++++++++++------------ net/openvswitch/flow.h | 4 ++-- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 748aa97cbfb2..0f783d9fa00d 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -739,10 +739,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) if (err) goto err_flow_free; - err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority, - &flow->key.phy.skb_mark, - &flow->key.phy.in_port, - a[OVS_PACKET_ATTR_KEY]); + err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]); if (err) goto err_flow_free; diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index fca483360ce2..093c191d4fc2 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -1125,10 +1125,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, /** * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. - * @priority: receives the skb priority - * @mark: receives the skb mark - * @in_port: receives the extracted input port. - * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute + * @flow: Receives extracted in_port, priority, tun_key and skb_mark. + * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute * sequence. * * This parses a series of Netlink attributes that form a flow key, which must @@ -1136,15 +1134,15 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, * get the metadata, that is, the parts of the flow key that cannot be * extracted from the packet itself. */ -int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, - const struct nlattr *attr) +int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, + const struct nlattr *attr) { const struct nlattr *nla; int rem; - *in_port = DP_MAX_PORTS; - *priority = 0; - *mark = 0; + flow->key.phy.in_port = DP_MAX_PORTS; + flow->key.phy.priority = 0; + flow->key.phy.skb_mark = 0; nla_for_each_nested(nla, attr, rem) { int type = nla_type(nla); @@ -1155,17 +1153,17 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, switch (type) { case OVS_KEY_ATTR_PRIORITY: - *priority = nla_get_u32(nla); + flow->key.phy.priority = nla_get_u32(nla); break; case OVS_KEY_ATTR_IN_PORT: if (nla_get_u32(nla) >= DP_MAX_PORTS) return -EINVAL; - *in_port = nla_get_u32(nla); + flow->key.phy.in_port = nla_get_u32(nla); break; case OVS_KEY_ATTR_SKB_MARK: - *mark = nla_get_u32(nla); + flow->key.phy.skb_mark = nla_get_u32(nla); break; } } diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 0875fde65b9c..2a83e2141f08 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -141,8 +141,8 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, const struct nlattr *); -int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, - const struct nlattr *); +int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, + const struct nlattr *attr); #define MAX_ACTIONS_BUFSIZE (16 * 1024) #define TBL_MIN_BUCKETS 1024 -- GitLab From f9e42b853523cda0732022c2e0473c183f7aec65 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 14 Jun 2013 18:24:04 +0200 Subject: [PATCH 1211/2900] net: sctp: sideeffect: throw BUG if primary_path is NULL This clearly states a BUG somewhere in the SCTP code as e.g. fixed once in f28156335 ("sctp: Use correct sideffect command in duplicate cookie handling"). If this ever happens, throw a trace in the sideeffect engine where assocs clearly must have a primary_path assigned. When in sctp_seq_dump_local_addrs() also throw a WARN and bail out since we do not need to panic for printing this one asterisk. Also, it will avoid the not so obvious case when primary != NULL test passes and at a later point in time triggering a NULL ptr dereference caused by primary. While at it, also fix up the white space. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/proc.c | 12 +++++++++--- net/sctp/sm_sideeffect.c | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 4e45ee35d0db..0c83162a6bf8 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -134,9 +134,15 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo struct sctp_af *af; if (epb->type == SCTP_EP_TYPE_ASSOCIATION) { - asoc = sctp_assoc(epb); - peer = asoc->peer.primary_path; - primary = &peer->saddr; + asoc = sctp_assoc(epb); + + peer = asoc->peer.primary_path; + if (unlikely(peer == NULL)) { + WARN(1, "Association %p with NULL primary path!", asoc); + return; + } + + primary = &peer->saddr; } rcu_read_lock(); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8aab894aeabe..ff91f47b0239 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -864,6 +864,7 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK)) return; + BUG_ON(asoc->peer.primary_path == NULL); sctp_unhash_established(asoc); sctp_association_free(asoc); } @@ -1274,8 +1275,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, sctp_outq_uncork(&asoc->outqueue); local_cork = 0; } - asoc = cmd->obj.asoc; + /* Register with the endpoint. */ + asoc = cmd->obj.asoc; + BUG_ON(asoc->peer.primary_path == NULL); sctp_endpoint_add_asoc(ep, asoc); sctp_hash_established(asoc); break; -- GitLab From 405426f6ca8ac2d8d5b1f8eb9285452d44222781 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 14 Jun 2013 18:24:05 +0200 Subject: [PATCH 1212/2900] net: sctp: sctp_sf_do_prm_asoc: do SCTP_CMD_INIT_CHOOSE_TRANSPORT first While this currently cannot trigger any NULL pointer dereference in sctp_seq_dump_local_addrs(), better change the order of commands to prevent a future bug to happen. Although we first add SCTP_CMD_NEW_ASOC and then set the SCTP_CMD_INIT_CHOOSE_TRANSPORT, it is okay for now, since this primitive is only called by sctp_connect() or sctp_sendmsg() with sctp_assoc_add_peer() set first. However, lets do this precaution and first set the transport and then add it to the association hashlist to prevent in future something to possibly triggering this. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_statefuns.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index de1a0138317f..b3d186856513 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4632,16 +4632,16 @@ sctp_disposition_t sctp_sf_do_prm_asoc(struct net *net, if (!repl) goto nomem; + /* Choose transport for INIT. */ + sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, + SCTP_CHUNK(repl)); + /* Cast away the const modifier, as we want to just * rerun it through as a sideffect. */ my_asoc = (struct sctp_association *)asoc; sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc)); - /* Choose transport for INIT. */ - sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, - SCTP_CHUNK(repl)); - /* After sending the INIT, "A" starts the T1-init timer and * enters the COOKIE-WAIT state. */ -- GitLab From c164b8381496ca797c37671fe510a264412ccae5 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 14 Jun 2013 18:24:06 +0200 Subject: [PATCH 1213/2900] net: sctp: minor: remove variable in sctp_init_sock It's only used at this one time, so we could remove it as well. This is valid and also makes it more explicit/obvious that in case of error the sp->ep is NULL here, i.e. for the sctp_destroy_sock() check that was recently added. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f631c5ff4dbf..510dc79a32a1 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3862,7 +3862,6 @@ SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) SCTP_STATIC int sctp_init_sock(struct sock *sk) { struct net *net = sock_net(sk); - struct sctp_endpoint *ep; struct sctp_sock *sp; SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk); @@ -3971,11 +3970,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) * change the data structure relationships, this may still * be useful for storing pre-connect address information. */ - ep = sctp_endpoint_new(sk, GFP_KERNEL); - if (!ep) + sp->ep = sctp_endpoint_new(sk, GFP_KERNEL); + if (!sp->ep) return -ENOMEM; - sp->ep = ep; sp->hmac = NULL; SCTP_DBG_OBJCNT_INC(sock); -- GitLab From 2e0c9e7911465b29daf85f7de97949004bf7b31c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 14 Jun 2013 18:24:07 +0200 Subject: [PATCH 1214/2900] net: sctp: sctp_association_init: put refs in reverse order In case we need to bail out for whatever reason during assoc init, we call sctp_endpoint_put() and then sock_put(), however, we've hold both refs in reverse, non-symmetric order, so first sctp_endpoint_hold() and then sock_hold(). Reverse this, so that in an error case we have sock_put() and then sctp_endpoint_put(). Actually shouldn't matter too much, since both cleanup paths do the right thing, but that way, it is more consistent with the rest of the code. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/associola.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 91cfd8f94a19..756025c98e85 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -86,10 +86,9 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a /* Discarding const is appropriate here. */ asoc->ep = (struct sctp_endpoint *)ep; - sctp_endpoint_hold(asoc->ep); - - /* Hold the sock. */ asoc->base.sk = (struct sock *)sk; + + sctp_endpoint_hold(asoc->ep); sock_hold(asoc->base.sk); /* Initialize the common base substructure. */ @@ -343,8 +342,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a return asoc; fail_init: - sctp_endpoint_put(asoc->ep); sock_put(asoc->base.sk); + sctp_endpoint_put(asoc->ep); return NULL; } -- GitLab From fbe98bb9ed3dae23e320c6b113e35f129538d14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Thu, 6 Jun 2013 20:37:00 -0700 Subject: [PATCH 1215/2900] kconfig: Fix defconfig when one choice menu selects options that another choice menu depends on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The defconfig and Kconfig combination below, which is based on 3.10-rc4 Kconfigs, resulted in several options getting set to "m" instead of "y". defconfig.choice: ---8<--- CONFIG_MODULES=y CONFIG_USB_ZERO=y ---8<--- Kconfig.choice: ---8<--- menuconfig MODULES bool "Enable loadable module support" config CONFIGFS_FS tristate "Userspace-driven configuration filesystem" config OCFS2_FS tristate "OCFS2 file system support" depends on CONFIGFS_FS select CRC32 config USB_LIBCOMPOSITE tristate select CONFIGFS_FS choice tristate "USB Gadget Drivers" default USB_ETH config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" select USB_LIBCOMPOSITE config USB_ETH tristate "Ethernet Gadget (with CDC Ethernet support)" select USB_LIBCOMPOSITE endchoice config CRC32 tristate "CRC32/CRC32c functions" default y choice prompt "CRC32 implementation" depends on CRC32 default CRC32_SLICEBY8 config CRC32_SLICEBY8 bool "Slice by 8 bytes" endchoice ---8<--- $ scripts/kconfig/conf --defconfig=defconfig.choice Kconfig.choice would result in: .config: ---8<--- CONFIG_MODULES=y CONFIG_CONFIGFS_FS=m CONFIG_USB_LIBCOMPOSITE=m CONFIG_USB_ZERO=m CONFIG_CRC32=y CONFIG_CRC32_SLICEBY8=y ---8<--- when the expected result would be: .config: ---8<--- CONFIG_MODULES=y CONFIG_CONFIGFS_FS=y CONFIG_USB_LIBCOMPOSITE=y CONFIG_USB_ZERO=y CONFIG_CRC32=y CONFIG_CRC32_SLICEBY8=y ---8<--- Signed-off-by: Arve Hjønnevåg [yann.morin.1998@free.fr: add the resulting .config to commit log, remove unneeded USB_GADGET from the defconfig] Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" Signed-off-by: Yann E. MORIN --- scripts/kconfig/confdata.c | 14 ++++++++++---- scripts/kconfig/expr.h | 3 +++ scripts/kconfig/lkc.h | 1 + scripts/kconfig/symbol.c | 11 +++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 43eda40c3838..35e0f164ef81 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -1083,7 +1083,7 @@ static void randomize_choice_values(struct symbol *csym) csym->flags &= ~(SYMBOL_VALID); } -static void set_all_choice_values(struct symbol *csym) +void set_all_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -1100,7 +1100,7 @@ static void set_all_choice_values(struct symbol *csym) } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ - csym->flags &= ~(SYMBOL_VALID); + csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); } void conf_set_all_new_symbols(enum conf_def_mode mode) @@ -1202,6 +1202,14 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) * selected in a choice block and we set it to yes, * and the rest to no. */ + if (mode != def_random) { + for_all_symbols(i, csym) { + if ((sym_is_choice(csym) && !sym_has_value(csym)) || + sym_is_choice_value(csym)) + csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; + } + } + for_all_symbols(i, csym) { if (sym_has_value(csym) || !sym_is_choice(csym)) continue; @@ -1209,7 +1217,5 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) sym_calc_value(csym); if (mode == def_random) randomize_choice_values(csym); - else - set_all_choice_values(csym); } } diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index cdd48600e02a..df198a5f4822 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -106,6 +106,9 @@ struct symbol { #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ +/* choice values need to be set before calculating this symbol value */ +#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000 + #define SYMBOL_MAXLENGTH 256 #define SYMBOL_HASHSIZE 9973 diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index f8aee5fc6d5e..0c8d4191ca87 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -87,6 +87,7 @@ char *conf_get_default_confname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); void conf_set_all_new_symbols(enum conf_def_mode mode); +void set_all_choice_values(struct symbol *csym); struct conf_printer { void (*print_symbol)(FILE *, struct symbol *, const char *, void *); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index ecc5aa5f865d..ab8f4c835933 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -300,6 +300,14 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_VALID) return; + + if (sym_is_choice_value(sym) && + sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) { + sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES; + prop = sym_get_choice_prop(sym); + sym_calc_value(prop_get_symbol(prop)); + } + sym->flags |= SYMBOL_VALID; oldval = sym->curr; @@ -425,6 +433,9 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_AUTO) sym->flags &= ~SYMBOL_WRITE; + + if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) + set_all_choice_values(sym); } void sym_clear_all_valid(void) -- GitLab From 851f665725581d02d48ffbca50240cda44d698d4 Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Sat, 15 Jun 2013 11:07:35 +0200 Subject: [PATCH 1216/2900] kconfig/lxdialog: Add definitions for mininimum (re)size values Commit c8dc68ad0fbd ("kconfig/lxdialog: support resize") added support for resizing, but forgot to collect all hardcoded values at one single place. Also add a definition for the check for a minimum screen/window size of 80x19. [ ChangeLog v3: * Rename MENU_{HEIGTH,WIDTH}_MIN -> MENUBOX_{HEIGTH,WIDTH}_MIN ChangeLog v2: * Rename WIN_{HEIGTH,WIDTH}_MIN -> WINDOW_{HEIGTH,WIDTH}_MIN * Mention the check for a minimum screen/window size in the changelog * Add a comment above the block of new definitions ] Signed-off-by: Sedat Dilek Acked-by: Wang YanQing Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/lxdialog/checklist.c | 4 ++-- scripts/kconfig/lxdialog/dialog.h | 14 ++++++++++++++ scripts/kconfig/lxdialog/inputbox.c | 4 ++-- scripts/kconfig/lxdialog/menubox.c | 2 +- scripts/kconfig/lxdialog/textbox.c | 2 +- scripts/kconfig/lxdialog/util.c | 2 +- scripts/kconfig/lxdialog/yesno.c | 4 ++-- 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c index a2eb80fbc896..30340571190e 100644 --- a/scripts/kconfig/lxdialog/checklist.c +++ b/scripts/kconfig/lxdialog/checklist.c @@ -132,9 +132,9 @@ int dialog_checklist(const char *title, const char *prompt, int height, } do_resize: - if (getmaxy(stdscr) < (height + 6)) + if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 6)) + if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; max_choice = MIN(list_height, item_count()); diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h index 1099337079b6..b4343d384926 100644 --- a/scripts/kconfig/lxdialog/dialog.h +++ b/scripts/kconfig/lxdialog/dialog.h @@ -200,6 +200,20 @@ int item_is_tag(char tag); int on_key_esc(WINDOW *win); int on_key_resize(void); +/* minimum (re)size values */ +#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */ +#define CHECKLIST_WIDTH_MIN 6 +#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */ +#define INPUTBOX_WIDTH_MIN 2 +#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */ +#define MENUBOX_WIDTH_MIN 65 +#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */ +#define TEXTBOX_WIDTH_MIN 8 +#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */ +#define YESNO_WIDTH_MIN 4 +#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */ +#define WINDOW_WIDTH_MIN 80 + int init_dialog(const char *backtitle); void set_dialog_backtitle(const char *backtitle); void set_dialog_subtitles(struct subtitle_list *subtitles); diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index 21404a04d7c3..7b01add415a8 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c @@ -56,9 +56,9 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width strcpy(instr, init); do_resize: - if (getmaxy(stdscr) <= (height - 2)) + if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) <= (width - 2)) + if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c index 48d382e7e374..00d28410adc9 100644 --- a/scripts/kconfig/lxdialog/menubox.c +++ b/scripts/kconfig/lxdialog/menubox.c @@ -193,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt, do_resize: height = getmaxy(stdscr); width = getmaxx(stdscr); - if (height < 15 || width < 65) + if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN) return -ERRDISPLAYTOOSMALL; height -= 4; diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index a48bb93e0907..907cdcb397c1 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c @@ -80,7 +80,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, do_resize: getmaxyx(stdscr, height, width); - if (height < 8 || width < 8) + if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN) return -ERRDISPLAYTOOSMALL; if (initial_height != 0) height = initial_height; diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index a0e97c299410..78fe4e9d8778 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c @@ -317,7 +317,7 @@ int init_dialog(const char *backtitle) getyx(stdscr, saved_y, saved_x); getmaxyx(stdscr, height, width); - if (height < 19 || width < 80) { + if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { endwin(); return -ERRDISPLAYTOOSMALL; } diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c index 4e6e8090c20b..abb0c392e01b 100644 --- a/scripts/kconfig/lxdialog/yesno.c +++ b/scripts/kconfig/lxdialog/yesno.c @@ -45,9 +45,9 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) WINDOW *dialog; do_resize: - if (getmaxy(stdscr) < (height + 4)) + if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 4)) + if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ -- GitLab From e3b8bbb9e81536f19d6e0b2c6e8186db47dfd426 Mon Sep 17 00:00:00 2001 From: Ido Reis Date: Tue, 27 Nov 2012 08:44:51 +0200 Subject: [PATCH 1217/2900] wl18xx: FDSP Code RAM Corruption fix In PG2.0 there is an issue where PHY's FDSP Code RAM sometimes gets corrupted when exiting from ELP mode. This issue is related to FDSP Code RAM clock implementation. PG2.1 introduces a HW fix for this issue that requires the driver to change the FDSP Code Ram clock settings (mux it to ATGP clock instead of its own clock). This workaround uses PHY_FPGA_SPARE_1 register and is relevant to WL8 PG2.1 devices. The fix is also backward compatible with older PG2.0 devices where the register PHY_FPGA_SPARE_1 is not used and not connected. The fix is done in the wl18xx_pre_upload function (must be performed before uploading the FW code) and includes the following steps: 1. Disable FDSP clock 2. Set ATPG clock toward FDSP Code RAM rather than its own clock. 3. Re-enable FDSP clock Signed-off-by: Yair Shapira Signed-off-by: Ido Reis Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 36 +++++++++++++++++++++++++-- drivers/net/wireless/ti/wl18xx/reg.h | 15 +++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 9fa692d11025..ae85ae46c61b 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -594,8 +594,8 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = { .mem3 = { .start = 0x00000000, .size = 0x00000000 }, }, [PART_PHY_INIT] = { - .mem = { .start = 0x80926000, - .size = sizeof(struct wl18xx_mac_and_phy_params) }, + .mem = { .start = WL18XX_PHY_INIT_MEM_ADDR, + .size = WL18XX_PHY_INIT_MEM_SIZE }, .reg = { .start = 0x00000000, .size = 0x00000000 }, .mem2 = { .start = 0x00000000, .size = 0x00000000 }, .mem3 = { .start = 0x00000000, .size = 0x00000000 }, @@ -799,6 +799,9 @@ static int wl18xx_pre_upload(struct wl1271 *wl) u32 tmp; int ret; + BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) > + WL18XX_PHY_INIT_MEM_SIZE); + ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); if (ret < 0) goto out; @@ -815,6 +818,35 @@ static int wl18xx_pre_upload(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp); + if (ret < 0) + goto out; + + /* + * Workaround for FDSP code RAM corruption (needed for PG2.1 + * and newer; for older chips it's a NOP). Change FDSP clock + * settings so that it's muxed to the ATGP clock instead of + * its own clock. + */ + + ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); + if (ret < 0) + goto out; + + /* disable FDSP clock */ + ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1, + MEM_FDSP_CLK_120_DISABLE); + if (ret < 0) + goto out; + + /* set ATPG clock toward FDSP Code RAM rather than its own clock */ + ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1, + MEM_FDSP_CODERAM_FUNC_CLK_SEL); + if (ret < 0) + goto out; + + /* re-enable FDSP clock */ + ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1, + MEM_FDSP_CLK_120_ENABLE); out: return ret; diff --git a/drivers/net/wireless/ti/wl18xx/reg.h b/drivers/net/wireless/ti/wl18xx/reg.h index 6306e04cd258..05dd8bad2746 100644 --- a/drivers/net/wireless/ti/wl18xx/reg.h +++ b/drivers/net/wireless/ti/wl18xx/reg.h @@ -38,6 +38,9 @@ #define WL18XX_REG_BOOT_PART_SIZE 0x00014578 #define WL18XX_PHY_INIT_MEM_ADDR 0x80926000 +#define WL18XX_PHY_END_MEM_ADDR 0x8093CA44 +#define WL18XX_PHY_INIT_MEM_SIZE \ + (WL18XX_PHY_END_MEM_ADDR - WL18XX_PHY_INIT_MEM_ADDR) #define WL18XX_SDIO_WSPI_BASE (WL18XX_REGISTERS_BASE) #define WL18XX_REG_CONFIG_BASE (WL18XX_REGISTERS_BASE + 0x02000) @@ -217,4 +220,16 @@ static const char * const rdl_names[] = { [RDL_4_SP] = "1897 MIMO", }; +/* FPGA_SPARE_1 register - used to change the PHY ATPG clock at boot time */ +#define WL18XX_PHY_FPGA_SPARE_1 0x8093CA40 + +/* command to disable FDSP clock */ +#define MEM_FDSP_CLK_120_DISABLE 0x80000000 + +/* command to set ATPG clock toward FDSP Code RAM rather than its own clock */ +#define MEM_FDSP_CODERAM_FUNC_CLK_SEL 0xC0000000 + +/* command to re-enable FDSP clock */ +#define MEM_FDSP_CLK_120_ENABLE 0x40000000 + #endif /* __REG_H__ */ -- GitLab From 8f6ac537b50077b3f2b0e926b661a064dc136a2a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Sat, 4 May 2013 01:06:11 +0300 Subject: [PATCH 1218/2900] wlcore: some non-functional clean-ups in main.c Remove unnecessary includes; remove duplicate and useless defines; fix copyright notice and remove some unnecessary line breaks. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 30 ++++++--------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 796928ba875f..32d877f1c684 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1,10 +1,9 @@ /* - * This file is part of wl1271 + * This file is part of wlcore * * Copyright (C) 2008-2010 Nokia Corporation - * - * Contact: Luciano Coelho + * Copyright (C) 2011-2013 Texas Instruments Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,37 +23,25 @@ #include #include -#include -#include -#include #include #include -#include -#include #include -#include #include #include "wlcore.h" #include "debug.h" #include "wl12xx_80211.h" #include "io.h" -#include "event.h" #include "tx.h" -#include "rx.h" #include "ps.h" #include "init.h" #include "debugfs.h" -#include "cmd.h" -#include "boot.h" #include "testmode.h" #include "scan.h" #include "hw_ops.h" #define WL1271_BOOT_RETRIES 3 -#define WL1271_BOOT_RETRIES 3 - static char *fwlog_param; static int bug_on_recovery = -1; static int no_recovery = -1; @@ -65,8 +52,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, static void wlcore_op_stop_locked(struct wl1271 *wl); static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); -static int wl12xx_set_authorized(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl12xx_set_authorized(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret; @@ -1668,8 +1654,7 @@ static int wl1271_configure_suspend(struct wl1271 *wl, return 0; } -static void wl1271_configure_resume(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif) { int ret = 0; bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; @@ -3782,8 +3767,7 @@ static int wlcore_set_beacon_template(struct wl1271 *wl, struct ieee80211_hdr *hdr; u32 min_rate; int ret; - int ieoffset = offsetof(struct ieee80211_mgmt, - u.beacon.variable); + int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable); struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); u16 tmpl_id; @@ -5827,8 +5811,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) return 0; } -#define WL1271_DEFAULT_CHANNEL 0 - struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size, u32 mbox_size) { @@ -5881,7 +5863,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size, goto err_hw; } - wl->channel = WL1271_DEFAULT_CHANNEL; + wl->channel = 0; wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->band = IEEE80211_BAND_2GHZ; -- GitLab From 33cab57a50531756f28199d63b1a529bc9e01605 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Sat, 4 May 2013 02:46:38 +0300 Subject: [PATCH 1219/2900] wlcore: move sysfs handling to a separate file Instead of doing all the sysfs file handling in the main file, move it to a new sysfs source file to reduce the amount of code in a single file. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/Makefile | 2 +- drivers/net/wireless/ti/wlcore/main.c | 178 +------------------ drivers/net/wireless/ti/wlcore/sysfs.c | 216 ++++++++++++++++++++++++ drivers/net/wireless/ti/wlcore/sysfs.h | 28 +++ 4 files changed, 249 insertions(+), 175 deletions(-) create mode 100644 drivers/net/wireless/ti/wlcore/sysfs.c create mode 100644 drivers/net/wireless/ti/wlcore/sysfs.h diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile index b21398f6c3ec..4f23931d7bd5 100644 --- a/drivers/net/wireless/ti/wlcore/Makefile +++ b/drivers/net/wireless/ti/wlcore/Makefile @@ -1,5 +1,5 @@ wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ - boot.o init.o debugfs.o scan.o + boot.o init.o debugfs.o scan.o sysfs.o wlcore_spi-objs = spi.o wlcore_sdio-objs = sdio.o diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 32d877f1c684..600ed7bc38db 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -39,6 +39,7 @@ #include "testmode.h" #include "scan.h" #include "hw_ops.h" +#include "sysfs.h" #define WL1271_BOOT_RETRIES 3 @@ -5387,151 +5388,6 @@ u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band) return idx; } -static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct wl1271 *wl = dev_get_drvdata(dev); - ssize_t len; - - len = PAGE_SIZE; - - mutex_lock(&wl->mutex); - len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", - wl->sg_enabled); - mutex_unlock(&wl->mutex); - - return len; - -} - -static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct wl1271 *wl = dev_get_drvdata(dev); - unsigned long res; - int ret; - - ret = kstrtoul(buf, 10, &res); - if (ret < 0) { - wl1271_warning("incorrect value written to bt_coex_mode"); - return count; - } - - mutex_lock(&wl->mutex); - - res = !!res; - - if (res == wl->sg_enabled) - goto out; - - wl->sg_enabled = res; - - if (unlikely(wl->state != WLCORE_STATE_ON)) - goto out; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - wl1271_acx_sg_enable(wl, wl->sg_enabled); - wl1271_ps_elp_sleep(wl); - - out: - mutex_unlock(&wl->mutex); - return count; -} - -static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, - wl1271_sysfs_show_bt_coex_state, - wl1271_sysfs_store_bt_coex_state); - -static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct wl1271 *wl = dev_get_drvdata(dev); - ssize_t len; - - len = PAGE_SIZE; - - mutex_lock(&wl->mutex); - if (wl->hw_pg_ver >= 0) - len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); - else - len = snprintf(buf, len, "n/a\n"); - mutex_unlock(&wl->mutex); - - return len; -} - -static DEVICE_ATTR(hw_pg_ver, S_IRUGO, - wl1271_sysfs_show_hw_pg_ver, NULL); - -static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t pos, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct wl1271 *wl = dev_get_drvdata(dev); - ssize_t len; - int ret; - - ret = mutex_lock_interruptible(&wl->mutex); - if (ret < 0) - return -ERESTARTSYS; - - /* Let only one thread read the log at a time, blocking others */ - while (wl->fwlog_size == 0) { - DEFINE_WAIT(wait); - - prepare_to_wait_exclusive(&wl->fwlog_waitq, - &wait, - TASK_INTERRUPTIBLE); - - if (wl->fwlog_size != 0) { - finish_wait(&wl->fwlog_waitq, &wait); - break; - } - - mutex_unlock(&wl->mutex); - - schedule(); - finish_wait(&wl->fwlog_waitq, &wait); - - if (signal_pending(current)) - return -ERESTARTSYS; - - ret = mutex_lock_interruptible(&wl->mutex); - if (ret < 0) - return -ERESTARTSYS; - } - - /* Check if the fwlog is still valid */ - if (wl->fwlog_size < 0) { - mutex_unlock(&wl->mutex); - return 0; - } - - /* Seeking is not supported - old logs are not kept. Disregard pos. */ - len = min(count, (size_t)wl->fwlog_size); - wl->fwlog_size -= len; - memcpy(buffer, wl->fwlog, len); - - /* Make room for new messages */ - memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size); - - mutex_unlock(&wl->mutex); - - return len; -} - -static struct bin_attribute fwlog_attr = { - .attr = {.name = "fwlog", .mode = S_IRUSR}, - .read = wl1271_sysfs_read_fwlog, -}; - static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) { int i; @@ -5970,11 +5826,8 @@ int wlcore_free_hw(struct wl1271 *wl) wake_up_interruptible_all(&wl->fwlog_waitq); mutex_unlock(&wl->mutex); - device_remove_bin_file(wl->dev, &fwlog_attr); - - device_remove_file(wl->dev, &dev_attr_hw_pg_ver); + wlcore_sysfs_free(wl); - device_remove_file(wl->dev, &dev_attr_bt_coex_state); kfree(wl->buffer_32); kfree(wl->mbox); free_page((unsigned long)wl->fwlog); @@ -6086,36 +5939,13 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) if (ret) goto out_irq; - /* Create sysfs file to control bt coex state */ - ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); - if (ret < 0) { - wl1271_error("failed to create sysfs file bt_coex_state"); + ret = wlcore_sysfs_init(wl); + if (ret) goto out_unreg; - } - - /* Create sysfs file to get HW PG version */ - ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver); - if (ret < 0) { - wl1271_error("failed to create sysfs file hw_pg_ver"); - goto out_bt_coex_state; - } - - /* Create sysfs file for the FW log */ - ret = device_create_bin_file(wl->dev, &fwlog_attr); - if (ret < 0) { - wl1271_error("failed to create sysfs file fwlog"); - goto out_hw_pg_ver; - } wl->initialized = true; goto out; -out_hw_pg_ver: - device_remove_file(wl->dev, &dev_attr_hw_pg_ver); - -out_bt_coex_state: - device_remove_file(wl->dev, &dev_attr_bt_coex_state); - out_unreg: wl1271_unregister_hw(wl); diff --git a/drivers/net/wireless/ti/wlcore/sysfs.c b/drivers/net/wireless/ti/wlcore/sysfs.c new file mode 100644 index 000000000000..8e583497940d --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/sysfs.c @@ -0,0 +1,216 @@ +/* + * This file is part of wlcore + * + * Copyright (C) 2013 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "wlcore.h" +#include "debug.h" +#include "ps.h" +#include "sysfs.h" + +static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + + len = PAGE_SIZE; + + mutex_lock(&wl->mutex); + len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n", + wl->sg_enabled); + mutex_unlock(&wl->mutex); + + return len; + +} + +static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + unsigned long res; + int ret; + + ret = kstrtoul(buf, 10, &res); + if (ret < 0) { + wl1271_warning("incorrect value written to bt_coex_mode"); + return count; + } + + mutex_lock(&wl->mutex); + + res = !!res; + + if (res == wl->sg_enabled) + goto out; + + wl->sg_enabled = res; + + if (unlikely(wl->state != WLCORE_STATE_ON)) + goto out; + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + wl1271_acx_sg_enable(wl, wl->sg_enabled); + wl1271_ps_elp_sleep(wl); + + out: + mutex_unlock(&wl->mutex); + return count; +} + +static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR, + wl1271_sysfs_show_bt_coex_state, + wl1271_sysfs_store_bt_coex_state); + +static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + + len = PAGE_SIZE; + + mutex_lock(&wl->mutex); + if (wl->hw_pg_ver >= 0) + len = snprintf(buf, len, "%d\n", wl->hw_pg_ver); + else + len = snprintf(buf, len, "n/a\n"); + mutex_unlock(&wl->mutex); + + return len; +} + +static DEVICE_ATTR(hw_pg_ver, S_IRUGO, + wl1271_sysfs_show_hw_pg_ver, NULL); + +static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t pos, size_t count) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct wl1271 *wl = dev_get_drvdata(dev); + ssize_t len; + int ret; + + ret = mutex_lock_interruptible(&wl->mutex); + if (ret < 0) + return -ERESTARTSYS; + + /* Let only one thread read the log at a time, blocking others */ + while (wl->fwlog_size == 0) { + DEFINE_WAIT(wait); + + prepare_to_wait_exclusive(&wl->fwlog_waitq, + &wait, + TASK_INTERRUPTIBLE); + + if (wl->fwlog_size != 0) { + finish_wait(&wl->fwlog_waitq, &wait); + break; + } + + mutex_unlock(&wl->mutex); + + schedule(); + finish_wait(&wl->fwlog_waitq, &wait); + + if (signal_pending(current)) + return -ERESTARTSYS; + + ret = mutex_lock_interruptible(&wl->mutex); + if (ret < 0) + return -ERESTARTSYS; + } + + /* Check if the fwlog is still valid */ + if (wl->fwlog_size < 0) { + mutex_unlock(&wl->mutex); + return 0; + } + + /* Seeking is not supported - old logs are not kept. Disregard pos. */ + len = min(count, (size_t)wl->fwlog_size); + wl->fwlog_size -= len; + memcpy(buffer, wl->fwlog, len); + + /* Make room for new messages */ + memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size); + + mutex_unlock(&wl->mutex); + + return len; +} + +static struct bin_attribute fwlog_attr = { + .attr = {.name = "fwlog", .mode = S_IRUSR}, + .read = wl1271_sysfs_read_fwlog, +}; + +int wlcore_sysfs_init(struct wl1271 *wl) +{ + int ret; + + /* Create sysfs file to control bt coex state */ + ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); + if (ret < 0) { + wl1271_error("failed to create sysfs file bt_coex_state"); + goto out; + } + + /* Create sysfs file to get HW PG version */ + ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver); + if (ret < 0) { + wl1271_error("failed to create sysfs file hw_pg_ver"); + goto out_bt_coex_state; + } + + /* Create sysfs file for the FW log */ + ret = device_create_bin_file(wl->dev, &fwlog_attr); + if (ret < 0) { + wl1271_error("failed to create sysfs file fwlog"); + goto out_hw_pg_ver; + } + + goto out; + +out_hw_pg_ver: + device_remove_file(wl->dev, &dev_attr_hw_pg_ver); + +out_bt_coex_state: + device_remove_file(wl->dev, &dev_attr_bt_coex_state); + +out: + return ret; +} + +void wlcore_sysfs_free(struct wl1271 *wl) +{ + device_remove_bin_file(wl->dev, &fwlog_attr); + + device_remove_file(wl->dev, &dev_attr_hw_pg_ver); + + device_remove_file(wl->dev, &dev_attr_bt_coex_state); +} diff --git a/drivers/net/wireless/ti/wlcore/sysfs.h b/drivers/net/wireless/ti/wlcore/sysfs.h new file mode 100644 index 000000000000..c1488921839d --- /dev/null +++ b/drivers/net/wireless/ti/wlcore/sysfs.h @@ -0,0 +1,28 @@ +/* + * This file is part of wlcore + * + * Copyright (C) 2013 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __SYSFS_H__ +#define __SYSFS_H__ + +int wlcore_sysfs_init(struct wl1271 *wl); +void wlcore_sysfs_free(struct wl1271 *wl); + +#endif -- GitLab From 6f0b1bb2ba2b1df781c64fff645c3fe0495b8161 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 7 May 2013 15:41:08 +0300 Subject: [PATCH 1220/2900] wlcore: configure rates in multiple cases The current code configures the peer caps only on BSS_CHANGED_HT notification. However, we have to configure the peer caps (and rates) even when HT is not enabled. Otherwise, the fw continues working with low rates. Configure the peer caps when sta_exists is true (i.e. when we extracted the sta rates, e.g. on association). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 600ed7bc38db..04dc1b6ae35b 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -4215,8 +4215,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } /* Handle new association with HT. Do this after join. */ - if (sta_exists && - (changed & BSS_CHANGED_HT)) { + if (sta_exists) { bool enabled = bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT; -- GitLab From bc2ab3b850a8c563b3910f396e5f0753ce855134 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Wed, 8 May 2013 12:54:56 +0300 Subject: [PATCH 1221/2900] wl18xx: use locally administered MAC address if not available from fuse In some R&D chips, the device may be left untrimmed and with the MAC address missing from fuse ROM. In order to support those devices, apply a random locally administered MAC address instead. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index ae85ae46c61b..7aa0eb848c5a 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "../wlcore/wlcore.h" #include "../wlcore/debug.h" @@ -1318,6 +1319,16 @@ static int wl18xx_get_mac(struct wl1271 *wl) ((mac1 & 0xff000000) >> 24); wl->fuse_nic_addr = (mac1 & 0xffffff); + if (!wl->fuse_oui_addr && !wl->fuse_nic_addr) { + u8 mac[ETH_ALEN]; + + eth_random_addr(mac); + + wl->fuse_oui_addr = (mac[0] << 16) + (mac[1] << 8) + mac[2]; + wl->fuse_nic_addr = (mac[3] << 16) + (mac[4] << 8) + mac[5]; + wl1271_warning("MAC address from fuse not available, using random locally administered addresses."); + } + ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); out: -- GitLab From ba1e6eb96d73eb1b2be6d67a55a799477b14a353 Mon Sep 17 00:00:00 2001 From: Yoni Divinsky Date: Sun, 12 May 2013 12:35:28 +0300 Subject: [PATCH 1222/2900] wlcore: set default_wep_key when configured When associating to an AP with WEP set the default key upon association by implementing the set_deafult_key_idx op. Fixes auto-arp sent with wrong key_idx bug. Signed-off-by: Yoni Divinsky Signed-off-by: Eyal Shapira Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 49 ++++++++++++++++++++++----- drivers/net/wireless/ti/wlcore/tx.c | 2 +- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 04dc1b6ae35b..7ee422f97c10 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -3196,14 +3196,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (ret < 0) return ret; - /* the default WEP key needs to be configured at least once */ - if (key_type == KEY_WEP) { - ret = wl12xx_cmd_set_default_wep_key(wl, - wlvif->default_key, - wlvif->sta.hlid); - if (ret < 0) - return ret; - } } return 0; @@ -3360,6 +3352,46 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, } EXPORT_SYMBOL_GPL(wlcore_set_key); +static void wl1271_op_set_default_key_idx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + int key_idx) +{ + struct wl1271 *wl = hw->priv; + struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); + int ret; + + wl1271_debug(DEBUG_MAC80211, "mac80211 set default key idx %d", + key_idx); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state != WLCORE_STATE_ON)) { + ret = -EAGAIN; + goto out_unlock; + } + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_unlock; + + wlvif->default_key = key_idx; + + /* the default WEP key needs to be configured at least once */ + if (wlvif->encryption_type == KEY_WEP) { + ret = wl12xx_cmd_set_default_wep_key(wl, + key_idx, + wlvif->sta.hlid); + if (ret < 0) + goto out_sleep; + } + +out_sleep: + wl1271_ps_elp_sleep(wl); + +out_unlock: + mutex_unlock(&wl->mutex); +} + void wlcore_regdomain_config(struct wl1271 *wl) { int ret; @@ -5352,6 +5384,7 @@ static const struct ieee80211_ops wl1271_ops = { .ampdu_action = wl1271_op_ampdu_action, .tx_frames_pending = wl1271_tx_frames_pending, .set_bitrate_mask = wl12xx_set_bitrate_mask, + .set_default_unicast_key = wl1271_op_set_default_key_idx, .channel_switch = wl12xx_op_channel_switch, .flush = wlcore_op_flush, .remain_on_channel = wlcore_op_remain_on_channel, diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 004d02e71f01..7e93fe63a2c7 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -386,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || (cipher == WLAN_CIPHER_SUITE_WEP104); - if (unlikely(is_wep && wlvif->default_key != idx)) { + if (WARN_ON(is_wep && wlvif->default_key != idx)) { ret = wl1271_set_default_wep_key(wl, wlvif, idx); if (ret < 0) return ret; -- GitLab From c838478b7b78d6e212547cd2243031080f2cee45 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 12 May 2013 12:35:29 +0300 Subject: [PATCH 1223/2900] wlcore: cancel channel switch work on interface removal Otherwise, if the work is pending, we might get a bad dereference after the interface is removed. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7ee422f97c10..ed200c61b231 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -2589,6 +2589,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, cancel_work_sync(&wlvif->rx_streaming_enable_work); cancel_work_sync(&wlvif->rx_streaming_disable_work); cancel_delayed_work_sync(&wlvif->connection_loss_work); + cancel_delayed_work_sync(&wlvif->channel_switch_work); mutex_lock(&wl->mutex); } -- GitLab From 2baf53c6e35ea25aaa21486dab023eb3d901611e Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 12 May 2013 12:35:30 +0300 Subject: [PATCH 1224/2900] wlcore: hold jiffies in unsigned long u32 can be incorrect (too small) for some architectures. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 9654577efd01..98066d40c2ad 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -110,7 +110,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) DECLARE_COMPLETION_ONSTACK(compl); unsigned long flags; int ret; - u32 start_time = jiffies; + unsigned long start_time = jiffies; bool pending = false; /* -- GitLab From 5cbba2d48ac3d493d2337414806c718370edcf8a Mon Sep 17 00:00:00 2001 From: Victor Goldenshtein Date: Sun, 12 May 2013 12:35:31 +0300 Subject: [PATCH 1225/2900] wlcore: fix occasional AP TX stop after recovery The fw_status wasn't zeroed during allocation, resulting in uninitialized var usage, and finally causing AP traffic stop after recovery. The wrong value in fw_status_2->counters.tx_lnk_free_pkts led to a bad lnk->allocated_pkts calculation in wlcore_fw_status(), causing wl18xx_lnk_low_prio() to return FALSE (lnk->allocated_pkts > thold). This eventually blocked the link in wlcore_tx_work_locked(), as wl1271_skb_dequeue() continuously returned NULL. Fix it by zeroing wl->fw_status_1/2 during allocation. Signed-off-by: Victor Goldenshtein Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ed200c61b231..b8db55c868c7 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -970,7 +970,7 @@ static int wlcore_fw_wakeup(struct wl1271 *wl) static int wl1271_setup(struct wl1271 *wl) { - wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + + wl->fw_status_1 = kzalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + sizeof(*wl->fw_status_2) + wl->fw_status_priv_len, GFP_KERNEL); if (!wl->fw_status_1) @@ -980,7 +980,7 @@ static int wl1271_setup(struct wl1271 *wl) (((u8 *) wl->fw_status_1) + WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); - wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); + wl->tx_res_if = kzalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); if (!wl->tx_res_if) { kfree(wl->fw_status_1); return -ENOMEM; -- GitLab From d5a49178fa842a83d7161b373117004e0483385a Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 20 May 2013 21:52:40 +0200 Subject: [PATCH 1226/2900] net/wireless/ti/wlcore/spi: Use module_spi_driver to register driver Removing some boilerplate by using module_spi_driver instead of calling register and unregister in the otherwise empty init/exit functions Signed-off-by: Peter Huewe Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/spi.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index e26447832683..1b0cd98e35f1 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -434,19 +434,7 @@ static struct spi_driver wl1271_spi_driver = { .remove = wl1271_remove, }; -static int __init wl1271_init(void) -{ - return spi_register_driver(&wl1271_spi_driver); -} - -static void __exit wl1271_exit(void) -{ - spi_unregister_driver(&wl1271_spi_driver); -} - -module_init(wl1271_init); -module_exit(wl1271_exit); - +module_spi_driver(wl1271_spi_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -- GitLab From 19a4e68a8a192957f7556a0aae9c37a6bc73cde6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 29 May 2013 15:48:22 +0530 Subject: [PATCH 1227/2900] net: wireless: wl1251: Use module_spi_driver macro module_spi_driver() eliminates some boiler plate and makes code simpler. Signed-off-by: Sachin Kamat Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl1251/spi.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 4c67c2f9ea71..dfd087742d1a 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -329,29 +329,7 @@ static struct spi_driver wl1251_spi_driver = { .remove = wl1251_spi_remove, }; -static int __init wl1251_spi_init(void) -{ - int ret; - - ret = spi_register_driver(&wl1251_spi_driver); - if (ret < 0) { - wl1251_error("failed to register spi driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit wl1251_spi_exit(void) -{ - spi_unregister_driver(&wl1251_spi_driver); - - wl1251_notice("unloaded"); -} - -module_init(wl1251_spi_init); -module_exit(wl1251_spi_exit); +module_spi_driver(wl1251_spi_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kalle Valo "); -- GitLab From 789e90e567d7d93edc1b2001d17209c21cc37850 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 29 May 2013 15:48:23 +0530 Subject: [PATCH 1228/2900] net: wireless: wl1251: Fix commenting style Make the commenting style consistent with networking block comment style as suggested by checkpatch. Signed-off-by: Sachin Kamat Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl1251/spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index dfd087742d1a..c7dc6feab2ff 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -93,8 +93,7 @@ static void wl1251_spi_wake(struct wl1251 *wl) memset(&t, 0, sizeof(t)); spi_message_init(&m); - /* - * Set WSPI_INIT_COMMAND + /* Set WSPI_INIT_COMMAND * the data is being send from the MSB to LSB */ cmd[2] = 0xff; @@ -262,7 +261,8 @@ static int wl1251_spi_probe(struct spi_device *spi) wl->if_ops = &wl1251_spi_ops; /* This is the only SPI value that we need to set here, the rest - * comes from the board-peripherals file */ + * comes from the board-peripherals file + */ spi->bits_per_word = 32; ret = spi_setup(spi); -- GitLab From abca2056dc3dd0d813ba2f8b013e98cf009ba168 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:35 -0300 Subject: [PATCH 1229/2900] [media] v4l2: remove g_chip_ident from bridge drivers where it is easy to do so VIDIOC_DBG_G_CHIP_IDENT has been replaced by VIDIOC_DBG_G_CHIP_INFO. Remove g_chip_ident support from bridge drivers since it is no longer needed. This patch takes care of all the trivial cases. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Acked-by: Scott Jiang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146/saa7146_video.c | 23 ------- drivers/media/pci/bt8xx/bttv-driver.c | 38 ----------- drivers/media/pci/saa7134/saa7134-empress.c | 17 ----- drivers/media/pci/saa7134/saa7134-video.c | 4 -- drivers/media/pci/saa7146/mxb.c | 15 ++--- drivers/media/pci/saa7164/saa7164-encoder.c | 37 ----------- drivers/media/pci/saa7164/saa7164-vbi.c | 9 --- drivers/media/pci/saa7164/saa7164.h | 1 - .../media/platform/blackfin/bfin_capture.c | 41 ------------ drivers/media/platform/davinci/vpif_capture.c | 66 ------------------- drivers/media/platform/davinci/vpif_display.c | 66 ------------------- drivers/media/platform/sh_vou.c | 31 --------- .../media/platform/soc_camera/soc_camera.c | 34 ---------- drivers/media/platform/via-camera.c | 16 ----- drivers/media/radio/radio-si476x.c | 11 ---- drivers/media/usb/au0828/au0828-video.c | 39 ----------- drivers/media/usb/em28xx/em28xx-video.c | 66 ++----------------- drivers/media/usb/stk1160/stk1160-v4l.c | 41 ------------ 18 files changed, 10 insertions(+), 545 deletions(-) diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index fe907f2e8f59..30779498c173 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -1,7 +1,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include @@ -988,26 +987,6 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty return err; } -static int vidioc_g_chip_ident(struct file *file, void *__fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7146_fh *fh = __fh; - struct saa7146_dev *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = V4L2_IDENT_SAA7146; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - return v4l2_device_call_until_err(&dev->v4l2_dev, 0, - core, g_chip_ident, chip); -} - const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, @@ -1018,7 +997,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_overlay = vidioc_overlay, .vidioc_g_fbuf = vidioc_g_fbuf, @@ -1039,7 +1017,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_reqbufs = vidioc_reqbufs, .vidioc_querybuf = vidioc_querybuf, diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index a334c94a303d..bfcfa3e8543e 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -1907,28 +1906,6 @@ static int bttv_log_status(struct file *file, void *f) return 0; } -static int bttv_g_chip_ident(struct file *file, void *f, struct v4l2_dbg_chip_ident *chip) -{ - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = btv->id; - if (chip->ident == PCI_DEVICE_ID_FUSION879) - chip->ident = V4L2_IDENT_BT879; - } - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - /* TODO: is this correct? */ - return bttv_call_all_err(btv, core, g_chip_ident, chip); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int bttv_g_register(struct file *file, void *f, struct v4l2_dbg_register *reg) @@ -1936,13 +1913,6 @@ static int bttv_g_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!v4l2_chip_match_host(®->match)) { - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - bttv_call_all(btv, core, g_register, reg); - return 0; - } - /* bt848 has a 12-bit register space */ reg->reg &= 0xfff; reg->val = btread(reg->reg); @@ -1957,13 +1927,6 @@ static int bttv_s_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!v4l2_chip_match_host(®->match)) { - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - bttv_call_all(btv, core, s_register, reg); - return 0; - } - /* bt848 has a 12-bit register space */ btwrite(reg->val, reg->reg & 0xfff); @@ -3203,7 +3166,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { .vidioc_querystd = bttv_querystd, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = bttv_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = bttv_g_register, .vidioc_s_register = bttv_s_register, diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 66a70814004c..05ab2cb7ef3c 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -28,7 +28,6 @@ #include #include -#include /* ------------------------------------------------------------------ */ @@ -413,21 +412,6 @@ static int empress_querymenu(struct file *file, void *priv, return saa_call_empress(dev, core, querymenu, c); } -static int empress_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7134_dev *dev = file->private_data; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && - !strcmp(chip->match.name, "saa6752hs")) - return saa_call_empress(dev, core, g_chip_ident, chip); - if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR) - return saa_call_empress(dev, core, g_chip_ident, chip); - return -EINVAL; -} - static int empress_s_std(struct file *file, void *priv, v4l2_std_id id) { struct saa7134_dev *dev = file->private_data; @@ -475,7 +459,6 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_querymenu = empress_querymenu, .vidioc_g_ctrl = empress_g_ctrl, .vidioc_s_ctrl = empress_s_ctrl, - .vidioc_g_chip_ident = empress_g_chip_ident, .vidioc_s_std = empress_s_std, .vidioc_g_std = empress_g_std, }; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index cc409380ee16..737e643be27a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2258,8 +2258,6 @@ static int vidioc_g_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; reg->val = saa_readb(reg->reg); reg->size = 1; return 0; @@ -2271,8 +2269,6 @@ static int vidioc_s_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; saa_writeb(reg->reg&0xffffff, reg->val); return 0; } diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 52cbe7a027cc..8d177691cd7c 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -669,12 +669,8 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (v4l2_chip_match_host(®->match)) { - reg->val = saa7146_read(dev, reg->reg); - reg->size = 4; - return 0; - } - call_all(dev, core, g_register, reg); + reg->val = saa7146_read(dev, reg->reg); + reg->size = 4; return 0; } @@ -682,11 +678,8 @@ static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_ { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (v4l2_chip_match_host(®->match)) { - saa7146_write(dev, reg->reg, reg->val); - return 0; - } - return call_all(dev, core, s_register, reg); + saa7146_write(dev, reg->reg, reg->val); + return 0; } #endif diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 63a72fb71f30..e4f53a55eab1 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -1288,38 +1288,6 @@ static const struct v4l2_file_operations mpeg_fops = { .unlocked_ioctl = video_ioctl2, }; -static int saa7164_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int saa7164_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - return 0; -} - -static int saa7164_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - return 0; -} -#endif - static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, @@ -1340,11 +1308,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_chip_ident = saa7164_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = saa7164_g_register, - .vidioc_s_register = saa7164_s_register, -#endif }; static struct video_device saa7164_mpeg_template = { diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index da224eb39b95..5a1a69b3dd15 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -1254,15 +1254,6 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_queryctrl = vidioc_queryctrl, -#if 0 - .vidioc_g_chip_ident = saa7164_g_chip_ident, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG -#if 0 - .vidioc_g_register = saa7164_g_register, - .vidioc_s_register = saa7164_s_register, -#endif -#endif .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt, diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 437284e747c9..8d9c7e692242 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -63,7 +63,6 @@ #include #include #include -#include #include "saa7164-reg.h" #include "saa7164-types.h" diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index ca8d56aecfb0..6652e71ea794 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -876,41 +875,6 @@ static int bcap_s_parm(struct file *file, void *fh, return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); } -static int bcap_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - return v4l2_subdev_call(bcap_dev->sd, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int bcap_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - return v4l2_subdev_call(bcap_dev->sd, core, - g_register, reg); -} - -static int bcap_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - return v4l2_subdev_call(bcap_dev->sd, core, - s_register, reg); -} -#endif - static int bcap_log_status(struct file *file, void *priv) { struct bcap_device *bcap_dev = video_drvdata(file); @@ -943,11 +907,6 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { .vidioc_streamoff = bcap_streamoff, .vidioc_g_parm = bcap_g_parm, .vidioc_s_parm = bcap_s_parm, - .vidioc_g_chip_ident = bcap_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = bcap_dbg_g_register, - .vidioc_s_register = bcap_dbg_s_register, -#endif .vidioc_log_status = bcap_log_status, }; diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index caaf4fedadec..d004531e740d 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -24,7 +24,6 @@ #include #include -#include #include #include "vpif.h" @@ -1862,66 +1861,6 @@ static int vpif_g_dv_timings(struct file *file, void *priv, return 0; } -/* - * vpif_g_chip_ident() - Identify the chip - * @file: file ptr - * @priv: file handle - * @chip: chip identity - * - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { - vpif_dbg(2, debug, "match_type is invalid.\n"); - return -EINVAL; - } - - return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * vpif_dbg_g_register() - Read register - * @file: file ptr - * @priv: file handle - * @reg: register to be read - * - * Debugging only - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg){ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, g_register, reg); -} - -/* - * vpif_dbg_s_register() - Write to register - * @file: file ptr - * @priv: file handle - * @reg: register to be modified - * - * Debugging only - * Returns zero or -EINVAL if write operations fails. - */ -static int vpif_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, s_register, reg); -} -#endif - /* * vpif_log_status() - Status information * @file: file ptr @@ -1963,11 +1902,6 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_query_dv_timings = vpif_query_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, - .vidioc_g_chip_ident = vpif_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpif_dbg_g_register, - .vidioc_s_register = vpif_dbg_s_register, -#endif .vidioc_log_status = vpif_log_status, }; diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 5b6f9065b881..6c521f23e40e 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -19,7 +19,6 @@ #include #include -#include #include #include "vpif.h" @@ -1500,66 +1499,6 @@ static int vpif_g_dv_timings(struct file *file, void *priv, return 0; } -/* - * vpif_g_chip_ident() - Identify the chip - * @file: file ptr - * @priv: file handle - * @chip: chip identity - * - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { - vpif_dbg(2, debug, "match_type is invalid.\n"); - return -EINVAL; - } - - return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * vpif_dbg_g_register() - Read register - * @file: file ptr - * @priv: file handle - * @reg: register to be read - * - * Debugging only - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg){ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, g_register, reg); -} - -/* - * vpif_dbg_s_register() - Write to register - * @file: file ptr - * @priv: file handle - * @reg: register to be modified - * - * Debugging only - * Returns zero or -EINVAL if write operations fails. - */ -static int vpif_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, s_register, reg); -} -#endif - /* * vpif_log_status() - Status information * @file: file ptr @@ -1599,11 +1538,6 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_enum_dv_timings = vpif_enum_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, - .vidioc_g_chip_ident = vpif_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpif_dbg_g_register, - .vidioc_s_register = vpif_dbg_s_register, -#endif .vidioc_log_status = vpif_log_status, }; diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 7d0235069c87..fa8ae7241521 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -1248,32 +1248,6 @@ static unsigned int sh_vou_poll(struct file *file, poll_table *wait) return res; } -static int sh_vou_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *id) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int sh_vou_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); -} - -static int sh_vou_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); -} -#endif - /* sh_vou display ioctl operations */ static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { .vidioc_querycap = sh_vou_querycap, @@ -1292,11 +1266,6 @@ static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { .vidioc_cropcap = sh_vou_cropcap, .vidioc_g_crop = sh_vou_g_crop, .vidioc_s_crop = sh_vou_s_crop, - .vidioc_g_chip_ident = sh_vou_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = sh_vou_g_register, - .vidioc_s_register = sh_vou_s_register, -#endif }; static const struct v4l2_file_operations sh_vou_fops = { diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index eea832c5fd01..68efade15a7c 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1036,35 +1036,6 @@ static int soc_camera_s_parm(struct file *file, void *fh, return -ENOIOCTLCMD; } -static int soc_camera_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *id) -{ - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - - return v4l2_subdev_call(sd, core, g_chip_ident, id); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int soc_camera_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - - return v4l2_subdev_call(sd, core, g_register, reg); -} - -static int soc_camera_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) -{ - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - - return v4l2_subdev_call(sd, core, s_register, reg); -} -#endif - static int soc_camera_probe(struct soc_camera_device *icd); /* So far this function cannot fail */ @@ -1495,11 +1466,6 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { .vidioc_s_selection = soc_camera_s_selection, .vidioc_g_parm = soc_camera_g_parm, .vidioc_s_parm = soc_camera_s_parm, - .vidioc_g_chip_ident = soc_camera_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = soc_camera_g_register, - .vidioc_s_register = soc_camera_s_register, -#endif }; static int video_dev_create(struct soc_camera_device *icd) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index a794cd6c4441..e3438277b80b 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -805,20 +804,6 @@ static const struct v4l2_file_operations viacam_fops = { * The long list of v4l2 ioctl ops */ -static int viacam_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *ident) -{ - struct via_camera *cam = priv; - - ident->ident = V4L2_IDENT_NONE; - ident->revision = 0; - if (v4l2_chip_match_host(&ident->match)) { - ident->ident = V4L2_IDENT_VIA_VX855; - return 0; - } - return sensor_call(cam, core, g_chip_ident, ident); -} - /* * Only one input. */ @@ -1174,7 +1159,6 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, static const struct v4l2_ioctl_ops viacam_ioctl_ops = { - .vidioc_g_chip_ident = viacam_g_chip_ident, .vidioc_enum_input = viacam_enum_input, .vidioc_g_input = viacam_g_input, .vidioc_s_input = viacam_s_input, diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9430c6a29937..e039d0332831 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1018,16 +1018,6 @@ static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl) return retval; } -static int si476x_radio_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - if (chip->match.type == V4L2_CHIP_MATCH_HOST && - v4l2_chip_match_host(&chip->match)) - return 0; - return -EINVAL; -} - - #ifdef CONFIG_VIDEO_ADV_DEBUG static int si476x_radio_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) @@ -1203,7 +1193,6 @@ static const struct v4l2_ioctl_ops si4761_ioctl_ops = { .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = si476x_radio_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = si476x_radio_g_register, .vidioc_s_register = si476x_radio_s_register, diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 75ac9947cdac..4944a365570a 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include "au0828.h" #include "au0828-reg.h" @@ -1638,26 +1637,6 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_AU0828; - return 0; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - if (chip->ident == V4L2_IDENT_NONE) - return -EINVAL; - - return 0; -} - static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cc) { @@ -1779,15 +1758,6 @@ static int vidioc_g_register(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - reg->val = au0828_read(dev, reg->reg); return 0; } @@ -1798,14 +1768,6 @@ static int vidioc_s_register(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } return au0828_writereg(dev, reg->reg, reg->val); } #endif @@ -1943,7 +1905,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_log_status = vidioc_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 32d60e5546bc..1a577ed8ea0c 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -1309,28 +1308,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_BRIDGE) { - if (chip->match.addr > 1) - return -EINVAL; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_chip_info(struct file *file, void *priv, struct v4l2_dbg_chip_info *chip) @@ -1366,14 +1343,9 @@ static int vidioc_g_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; int ret; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - if (reg->match.addr > 1) - return -EINVAL; - if (!reg->match.addr) - break; - /* fall-through */ - case V4L2_CHIP_MATCH_AC97: + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) { ret = em28xx_read_ac97(dev, reg->reg); if (ret < 0) return ret; @@ -1381,15 +1353,6 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; reg->size = 1; return 0; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - return -EINVAL; } /* Match host */ @@ -1421,25 +1384,10 @@ static int vidioc_s_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; __le16 buf; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - if (reg->match.addr > 1) - return -EINVAL; - if (!reg->match.addr) - break; - /* fall-through */ - case V4L2_CHIP_MATCH_AC97: - return em28xx_write_ac97(dev, reg->reg, reg->val); - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: + if (reg->match.addr > 1) return -EINVAL; - } + if (reg->match.addr) + return em28xx_write_ac97(dev, reg->reg, reg->val); /* Match host */ buf = cpu_to_le16(reg->val); @@ -1795,7 +1743,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, @@ -1826,7 +1773,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index a59153d2f8bf..876fc26565e3 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -454,19 +453,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - switch (chip->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - return 0; - default: - return -EINVAL; - } -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) @@ -475,19 +461,6 @@ static int vidioc_g_register(struct file *file, void *priv, int rc; u8 val; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - /* Match host */ rc = stk1160_read_reg(dev, reg->reg, &val); reg->val = val; @@ -501,19 +474,6 @@ static int vidioc_s_register(struct file *file, void *priv, { struct stk1160 *dev = video_drvdata(file); - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - /* Match host */ return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val)); } @@ -543,7 +503,6 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, -- GitLab From 076c3454d645ac937bfc293235e3a31e31794114 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:36 -0300 Subject: [PATCH 1230/2900] [media] cx18: remove g_chip_ident support The av-core is really a subdev, so there is no need anymore to act as if it is a 'second' bridge chip. As a result of this the g_chip_ident implementation can be completely dropped. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-av-core.c | 32 ----------- drivers/media/pci/cx18/cx18-av-core.h | 1 - drivers/media/pci/cx18/cx18-ioctl.c | 78 +++------------------------ 3 files changed, 7 insertions(+), 104 deletions(-) diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c index ba8caf0fbb85..c4890a430dc6 100644 --- a/drivers/media/pci/cx18/cx18-av-core.c +++ b/drivers/media/pci/cx18/cx18-av-core.c @@ -22,7 +22,6 @@ * 02110-1301, USA. */ -#include #include "cx18-driver.h" #include "cx18-io.h" #include "cx18-cards.h" @@ -1231,31 +1230,12 @@ static int cx18_av_log_status(struct v4l2_subdev *sd) return 0; } -static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match) -{ - return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1; -} - -static int cx18_av_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx18_av_state *state = to_cx18_av_state(sd); - - if (cx18_av_dbg_match(&chip->match)) { - chip->ident = state->id; - chip->revision = state->rev; - } - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_av_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!cx18_av_dbg_match(®->match)) - return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; reg->size = 4; @@ -1268,8 +1248,6 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, { struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!cx18_av_dbg_match(®->match)) - return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val); @@ -1282,17 +1260,9 @@ static const struct v4l2_ctrl_ops cx18_av_ctrl_ops = { }; static const struct v4l2_subdev_core_ops cx18_av_general_ops = { - .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, .load_fw = cx18_av_load_fw, .reset = cx18_av_reset, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, .s_std = cx18_av_s_std, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx18_av_g_register, @@ -1340,8 +1310,6 @@ int cx18_av_probe(struct cx18 *cx) int err; state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; - state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) - ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN; state->vid_input = CX18_AV_COMPOSITE7; state->aud_input = CX18_AV_AUDIO8; diff --git a/drivers/media/pci/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h index e9c69d9c9e4a..4c559e86e340 100644 --- a/drivers/media/pci/cx18/cx18-av-core.h +++ b/drivers/media/pci/cx18/cx18-av-core.h @@ -104,7 +104,6 @@ struct cx18_av_state { enum cx18_av_audio_input aud_input; u32 audclk_freq; int audmode; - u32 id; u32 rev; int is_initialized; diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index aee7b6dacbfe..414b0ecccc91 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -39,7 +39,6 @@ #include "cx18-cards.h" #include "cx18-av-core.h" #include -#include u16 cx18_service2vbi(int type) { @@ -362,73 +361,16 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, return 0; } -static int cx18_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx18 *cx = fh2id(fh)->cx; - int err = 0; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (chip->match.addr) { - case 0: - chip->ident = V4L2_IDENT_CX23418; - chip->revision = cx18_read_reg(cx, 0xC72028); - break; - case 1: - /* - * The A/V decoder is always present, but in the rare - * case that the card doesn't have analog, we don't - * use it. We find it w/o using the cx->sd_av pointer - */ - cx18_call_hw(cx, CX18_HW_418_AV, - core, g_chip_ident, chip); - break; - default: - /* - * Could return ident = V4L2_IDENT_UNKNOWN if we had - * other host chips at higher addresses, but we don't - */ - err = -EINVAL; /* per V4L2 spec */ - break; - } - break; - case V4L2_CHIP_MATCH_I2C_DRIVER: - /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ - cx18_call_all(cx, core, g_chip_ident, chip); - break; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* - * We could return V4L2_IDENT_UNKNOWN, but we don't do the work - * to look if a chip is at the address with no driver. That's a - * dangerous thing to do with EEPROMs anyway. - */ - cx18_call_all(cx, core, g_chip_ident, chip); - break; - default: - err = -EINVAL; - break; - } - return err; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct cx18 *cx = fh2id(fh)->cx; - if (v4l2_chip_match_host(®->match)) { - if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) - return -EINVAL; - reg->size = 4; - reg->val = cx18_read_enc(cx, reg->reg); - return 0; - } - /* FIXME - errors shouldn't be ignored */ - cx18_call_all(cx, core, g_register, reg); + if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) + return -EINVAL; + reg->size = 4; + reg->val = cx18_read_enc(cx, reg->reg); return 0; } @@ -437,14 +379,9 @@ static int cx18_s_register(struct file *file, void *fh, { struct cx18 *cx = fh2id(fh)->cx; - if (v4l2_chip_match_host(®->match)) { - if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) - return -EINVAL; - cx18_write_enc(cx, reg->val, reg->reg); - return 0; - } - /* FIXME - errors shouldn't be ignored */ - cx18_call_all(cx, core, s_register, reg); + if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) + return -EINVAL; + cx18_write_enc(cx, reg->val, reg->reg); return 0; } #endif @@ -1162,7 +1099,6 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = { .vidioc_try_fmt_vbi_cap = cx18_try_fmt_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap, .vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap, - .vidioc_g_chip_ident = cx18_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cx18_g_register, .vidioc_s_register = cx18_s_register, -- GitLab From e84e91ea486cc153713f48a7c867828b150438d1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:37 -0300 Subject: [PATCH 1231/2900] [media] saa7115: add back the dropped 'found' message The saa7115 driver used to show a 'chip found' message during probe. This was accidentally dropped during recent commits. Add it back as it is quite useful. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 18cf0bfaf743..4daa81c55a82 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1735,6 +1735,8 @@ static int saa711x_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa711x_ops); + v4l_info(client, "%s found @ 0x%x (%s)\n", name, + client->addr << 1, client->adapter->name); hdl = &state->hdl; v4l2_ctrl_handler_init(hdl, 6); /* add in ascending ID order */ -- GitLab From 4bd8193674b7d3158e76eb48bdf3a787b71b8572 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:38 -0300 Subject: [PATCH 1232/2900] [media] ivtv: remove g_chip_ident g_chip_ident was used to determine if a saa7114 or saa7115 was used. Instead just check the subdev name. After that the g_chip_ident function can be removed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtv-driver.c | 8 +----- drivers/media/pci/ivtv/ivtv-ioctl.c | 41 +++------------------------- 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 07b8460953b6..db614528376c 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -58,7 +58,6 @@ #include #include #include -#include #include "tuner-xc2028.h" /* If you have already X v4l cards, then set this to X. This way @@ -968,15 +967,10 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } if (hw & IVTV_HW_SAA711X) { - struct v4l2_dbg_chip_ident v; - /* determine the exact saa711x model */ itv->hw_flags &= ~IVTV_HW_SAA711X; - v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER; - strlcpy(v.match.name, "saa7115", sizeof(v.match.name)); - ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v); - if (v.ident == V4L2_IDENT_SAA7114) { + if (strstr(itv->sd_video->name, "saa7114")) { itv->hw_flags |= IVTV_HW_SAA7114; /* VBI is not yet supported by the saa7114 driver. */ itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 3e281eccdd88..944300f7c60b 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -34,7 +34,6 @@ #include "ivtv-cards.h" #include #include -#include #include #include @@ -692,24 +691,6 @@ static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f return ret; } -static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) -{ - struct ivtv *itv = fh2id(fh)->itv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - /* TODO: is this correct? */ - return ivtv_call_all_err(itv, core, g_chip_ident, chip); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) { @@ -736,29 +717,16 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register { struct ivtv *itv = fh2id(fh)->itv; - if (v4l2_chip_match_host(®->match)) { - reg->size = 4; - return ivtv_itvc(itv, true, reg->reg, ®->val); - } - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, g_register, reg); - return 0; + reg->size = 4; + return ivtv_itvc(itv, true, reg->reg, ®->val); } static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg) { struct ivtv *itv = fh2id(fh)->itv; + u64 val = reg->val; - if (v4l2_chip_match_host(®->match)) { - u64 val = reg->val; - - return ivtv_itvc(itv, false, reg->reg, &val); - } - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, s_register, reg); - return 0; + return ivtv_itvc(itv, false, reg->reg, &val); } #endif @@ -1912,7 +1880,6 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay, .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out, .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap, - .vidioc_g_chip_ident = ivtv_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = ivtv_g_register, .vidioc_s_register = ivtv_s_register, -- GitLab From 80f8568f47306dc4453bb6630ac607f22ca4c7b4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:39 -0300 Subject: [PATCH 1233/2900] [media] cx23885: remove g_chip_ident Replace g_chip_ident by g_chip_info. Note that the IR support is implemented as a subdev, so this part no longer needs to be handled as a 'bridge' chip. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-417.c | 2 +- drivers/media/pci/cx23885/cx23885-ioctl.c | 139 ++++------------------ drivers/media/pci/cx23885/cx23885-ioctl.h | 4 +- drivers/media/pci/cx23885/cx23885-video.c | 2 +- drivers/media/pci/cx23885/cx23888-ir.c | 27 ----- 5 files changed, 29 insertions(+), 145 deletions(-) diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 6dea11a7a858..68568d35a692 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1690,8 +1690,8 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_log_status = vidioc_log_status, .vidioc_querymenu = vidioc_querymenu, .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_chip_ident = cx23885_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx23885_g_chip_info, .vidioc_g_register = cx23885_g_register, .vidioc_s_register = cx23885_s_register, #endif diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c index 00f51251728b..271d69d1ca8c 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.c +++ b/drivers/media/pci/cx23885/cx23885-ioctl.c @@ -24,93 +24,21 @@ #include "cx23885.h" #include "cx23885-ioctl.h" -#include - -int cx23885_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) +#ifdef CONFIG_VIDEO_ADV_DEBUG +int cx23885_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip) { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - int err = 0; - u8 rev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (chip->match.addr) { - case 0: - rev = cx_read(RDR_CFG2) & 0xff; - switch (dev->pci->device) { - case 0x8852: - /* rev 0x04 could be '885 or '888. Pick '888. */ - if (rev == 0x04) - chip->ident = V4L2_IDENT_CX23888; - else - chip->ident = V4L2_IDENT_CX23885; - break; - case 0x8880: - if (rev == 0x0e || rev == 0x0f) - chip->ident = V4L2_IDENT_CX23887; - else - chip->ident = V4L2_IDENT_CX23888; - break; - default: - chip->ident = V4L2_IDENT_UNKNOWN; - break; - } - chip->revision = (dev->pci->device << 16) | (rev << 8) | - (dev->hwrevision & 0xff); - break; - case 1: - if (dev->v4l_device != NULL) { - chip->ident = V4L2_IDENT_CX23417; - chip->revision = 0; - } - break; - case 2: - /* - * The integrated IR controller on the CX23888 is - * host chip 2. It may not be used/initialized or sd_ir - * may be pointing at the cx25840 subdevice for the - * IR controller on the CX23885. Thus we find it - * without using the dev->sd_ir pointer. - */ - call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident, - chip); - break; - default: - err = -EINVAL; /* per V4L2 spec */ - break; - } - break; - case V4L2_CHIP_MATCH_I2C_DRIVER: - /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ - call_all(dev, core, g_chip_ident, chip); - break; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* - * We could return V4L2_IDENT_UNKNOWN, but we don't do the work - * to look if a chip is at the address with no driver. That's a - * dangerous thing to do with EEPROMs anyway. - */ - call_all(dev, core, g_chip_ident, chip); - break; - default: - err = -EINVAL; - break; - } - return err; -} -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int cx23885_g_host_register(struct cx23885_dev *dev, - struct v4l2_dbg_register *reg) -{ - if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + if (chip->match.addr > 1) return -EINVAL; - - reg->size = 4; - reg->val = cx_read(reg->reg); + if (chip->match.addr == 1) { + if (dev->v4l_device == NULL) + return -EINVAL; + strlcpy(chip->name, "cx23417", sizeof(chip->name)); + } else { + strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name)); + } return 0; } @@ -138,29 +66,16 @@ int cx23885_g_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { - switch (reg->match.addr) { - case 0: - return cx23885_g_host_register(dev, reg); - case 1: - return cx23417_g_register(dev, reg); - default: - break; - } - } - - /* FIXME - any error returns should not be ignored */ - call_all(dev, core, g_register, reg); - return 0; -} + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) + return cx23417_g_register(dev, reg); -static int cx23885_s_host_register(struct cx23885_dev *dev, - const struct v4l2_dbg_register *reg) -{ if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) return -EINVAL; - cx_write(reg->reg, reg->val); + reg->size = 4; + reg->val = cx_read(reg->reg); return 0; } @@ -183,19 +98,15 @@ int cx23885_s_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { - switch (reg->match.addr) { - case 0: - return cx23885_s_host_register(dev, reg); - case 1: - return cx23417_s_register(dev, reg); - default: - break; - } - } + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) + return cx23417_s_register(dev, reg); + + if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + return -EINVAL; - /* FIXME - any error returns should not be ignored */ - call_all(dev, core, s_register, reg); + cx_write(reg->reg, reg->val); return 0; } #endif diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h index a6080964a9ee..92d9f0774366 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.h +++ b/drivers/media/pci/cx23885/cx23885-ioctl.h @@ -24,8 +24,8 @@ #ifndef _CX23885_IOCTL_H_ #define _CX23885_IOCTL_H_ -int cx23885_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip); +int cx23885_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip); #ifdef CONFIG_VIDEO_ADV_DEBUG int cx23885_g_register(struct file *file, void *fh, diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index ed08c89adde0..ce057398c632 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -1757,8 +1757,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_chip_ident = cx23885_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx23885_g_chip_info, .vidioc_g_register = cx23885_g_register, .vidioc_s_register = cx23885_s_register, #endif diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index cd98651f3ae6..2c951dec2d33 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -25,7 +25,6 @@ #include #include -#include #include #include "cx23885.h" @@ -131,8 +130,6 @@ union cx23888_ir_fifo_rec { struct cx23888_ir_state { struct v4l2_subdev sd; struct cx23885_dev *dev; - u32 id; - u32 rev; struct v4l2_subdev_ir_parameters rx_params; struct mutex rx_params_lock; @@ -1086,23 +1083,6 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd) return 0; } -static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match) -{ - return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2; -} - -static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx23888_ir_state *state = to_state(sd); - - if (cx23888_ir_dbg_match(&chip->match)) { - chip->ident = state->id; - chip->revision = state->rev; - } - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx23888_ir_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -1110,8 +1090,6 @@ static int cx23888_ir_g_register(struct v4l2_subdev *sd, struct cx23888_ir_state *state = to_state(sd); u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; - if (!cx23888_ir_dbg_match(®->match)) - return -EINVAL; if ((addr & 0x3) != 0) return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) @@ -1127,8 +1105,6 @@ static int cx23888_ir_s_register(struct v4l2_subdev *sd, struct cx23888_ir_state *state = to_state(sd); u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; - if (!cx23888_ir_dbg_match(®->match)) - return -EINVAL; if ((addr & 0x3) != 0) return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) @@ -1139,7 +1115,6 @@ static int cx23888_ir_s_register(struct v4l2_subdev *sd, #endif static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { - .g_chip_ident = cx23888_ir_g_chip_ident, .log_status = cx23888_ir_log_status, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx23888_ir_g_register, @@ -1213,8 +1188,6 @@ int cx23888_ir_probe(struct cx23885_dev *dev) return -ENOMEM; state->dev = dev; - state->id = V4L2_IDENT_CX23888_IR; - state->rev = 0; sd = &state->sd; v4l2_subdev_init(sd, &cx23888_ir_controller_ops); -- GitLab From 23898919c45ff5fc5d882ec6206b38a5fb6ecd88 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:41 -0300 Subject: [PATCH 1234/2900] [media] saa6752hs: drop obsolete g_chip_ident This op and the v4l2-chip-ident.h header are no longer needed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa6752hs.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index f147b05bd860..244b2868dfc8 100644 --- a/drivers/media/pci/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -92,7 +91,6 @@ static const struct v4l2_format v4l2_format_table[] = struct saa6752hs_state { struct v4l2_subdev sd; - int chip; u32 revision; int has_ac3; struct saa6752hs_mpeg_params params; @@ -914,19 +912,9 @@ static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) return 0; } -static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct saa6752hs_state *h = to_state(sd); - - return v4l2_chip_ident_i2c_client(client, - chip, h->chip, h->revision); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { - .g_chip_ident = saa6752hs_g_chip_ident, .init = saa6752hs_init, .queryctrl = saa6752hs_queryctrl, .querymenu = saa6752hs_querymenu, @@ -963,11 +951,9 @@ static int saa6752hs_probe(struct i2c_client *client, i2c_master_send(client, &addr, 1); i2c_master_recv(client, data, sizeof(data)); - h->chip = V4L2_IDENT_SAA6752HS; h->revision = (data[8] << 8) | data[9]; h->has_ac3 = 0; if (h->revision == 0x0206) { - h->chip = V4L2_IDENT_SAA6752HS_AC3; h->has_ac3 = 1; v4l_info(client, "support AC-3\n"); } -- GitLab From b1c85cc049a681aee805311faa56fd21b44fb904 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:42 -0300 Subject: [PATCH 1235/2900] [media] gspca: remove g_chip_ident Remove g_chip_ident and replace it with g_chip_info. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/gspca.c | 32 +++++++-------- drivers/media/usb/gspca/gspca.h | 6 +-- drivers/media/usb/gspca/pac7302.c | 19 +-------- drivers/media/usb/gspca/sn9c20x.c | 67 +++++++------------------------ 4 files changed, 34 insertions(+), 90 deletions(-) diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 5995ec4de6bc..b7ae8721b847 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1029,33 +1029,35 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) +static int vidioc_g_chip_info(struct file *file, void *priv, + struct v4l2_dbg_chip_info *chip) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_register(gspca_dev, reg); + if (gspca_dev->sd_desc->get_chip_info) + return gspca_dev->sd_desc->get_chip_info(gspca_dev, chip); + return chip->match.addr ? -EINVAL : 0; } -static int vidioc_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->set_register(gspca_dev, reg); + return gspca_dev->sd_desc->get_register(gspca_dev, reg); } -#endif -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) +static int vidioc_s_register(struct file *file, void *priv, + const struct v4l2_dbg_register *reg) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); + return gspca_dev->sd_desc->set_register(gspca_dev, reg); } +#endif static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) @@ -1974,10 +1976,10 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_enum_frameintervals = vidioc_enum_frameintervals, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; @@ -2086,14 +2088,10 @@ int gspca_dev_probe2(struct usb_interface *intf, v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF); v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF); v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF); - if (!gspca_dev->sd_desc->get_chip_ident) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT); #ifdef CONFIG_VIDEO_ADV_DEBUG - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->get_register) + if (!gspca_dev->sd_desc->get_register) v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER); - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->set_register) + if (!gspca_dev->sd_desc->set_register) v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER); #endif if (!gspca_dev->sd_desc->get_jcomp) diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h index ef8efeb80070..ac0b11f46f50 100644 --- a/drivers/media/usb/gspca/gspca.h +++ b/drivers/media/usb/gspca/gspca.h @@ -78,8 +78,8 @@ typedef int (*cam_get_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_set_reg_op) (struct gspca_dev *, const struct v4l2_dbg_register *); -typedef int (*cam_ident_op) (struct gspca_dev *, - struct v4l2_dbg_chip_ident *); +typedef int (*cam_chip_info_op) (struct gspca_dev *, + struct v4l2_dbg_chip_info *); typedef void (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, @@ -112,8 +112,8 @@ struct sd_desc { #ifdef CONFIG_VIDEO_ADV_DEBUG cam_set_reg_op set_register; cam_get_reg_op get_register; + cam_chip_info_op get_chip_info; #endif - cam_ident_op get_chip_ident; #if IS_ENABLED(CONFIG_INPUT) cam_int_pkt_op int_pkt_scan; /* other_input makes the gspca core create gspca_dev->input even when diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 6008c8d546a3..a91509643563 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -93,7 +93,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include "gspca.h" /* Include pac common sof detection functions */ #include "pac_common.h" @@ -849,8 +848,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, * reg->reg: bit0..15: reserved for register index (wIndex is 16bit * long on the USB bus) */ - if (reg->match.type == V4L2_CHIP_MATCH_HOST && - reg->match.addr == 0 && + if (reg->match.addr == 0 && (reg->reg < 0x000000ff) && (reg->val <= 0x000000ff) ) { @@ -871,20 +869,6 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, } return gspca_dev->usb_err; } - -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) -{ - int ret = -EINVAL; - - if (chip->match.type == V4L2_CHIP_MATCH_HOST && - chip->match.addr == 0) { - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - ret = 0; - } - return ret; -} #endif #if IS_ENABLED(CONFIG_INPUT) @@ -931,7 +915,6 @@ static const struct sd_desc sd_desc = { .dq_callback = do_autogain, #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, - .get_chip_ident = sd_chip_ident, #endif #if IS_ENABLED(CONFIG_INPUT) .int_pkt_scan = sd_int_pkt_scan, diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index ead9a1f58513..23b71f9f5942 100644 --- a/drivers/media/usb/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -27,7 +27,6 @@ #include "gspca.h" #include "jpeg.h" -#include #include MODULE_AUTHOR("Brian Johnson , " @@ -582,22 +581,6 @@ static const s16 hsv_blue_y[] = { 4, 2, 0, -1, -3, -5, -7, -9, -11 }; -static const u16 i2c_ident[] = { - V4L2_IDENT_OV9650, - V4L2_IDENT_OV9655, - V4L2_IDENT_SOI968, - V4L2_IDENT_OV7660, - V4L2_IDENT_OV7670, - V4L2_IDENT_MT9V011, - V4L2_IDENT_MT9V111, - V4L2_IDENT_MT9V112, - V4L2_IDENT_MT9M001C12ST, - V4L2_IDENT_MT9M111, - V4L2_IDENT_MT9M112, - V4L2_IDENT_HV7131R, -[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN, -}; - static const u16 bridge_init[][2] = { {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, @@ -1574,18 +1557,14 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; + switch (reg->match.addr) { + case 0: if (reg->reg < 0x1000 || reg->reg > 0x11ff) return -EINVAL; reg_r(gspca_dev, reg->reg, 1); reg->val = gspca_dev->usb_buf[0]; return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; + case 1: if (sd->sensor >= SENSOR_MT9V011 && sd->sensor <= SENSOR_MT9M112) { i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); @@ -1602,17 +1581,13 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; + switch (reg->match.addr) { + case 0: if (reg->reg < 0x1000 || reg->reg > 0x11ff) return -EINVAL; reg_w1(gspca_dev, reg->reg, reg->val); return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; + case 1: if (sd->sensor >= SENSOR_MT9V011 && sd->sensor <= SENSOR_MT9M112) { i2c_w2(gspca_dev, reg->reg, reg->val); @@ -1623,29 +1598,17 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, } return -EINVAL; } -#endif -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) +static int sd_chip_info(struct gspca_dev *gspca_dev, + struct v4l2_dbg_chip_info *chip) { - struct sd *sd = (struct sd *) gspca_dev; - - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (chip->match.addr != 0) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_SN9C20X; - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (chip->match.addr != sd->i2c_addr) - return -EINVAL; - chip->revision = 0; - chip->ident = i2c_ident[sd->sensor]; - return 0; - } - return -EINVAL; + if (chip->match.addr > 1) + return -EINVAL; + if (chip->match.addr == 1) + strlcpy(chip->name, "sensor", sizeof(chip->name)); + return 0; } +#endif static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -2356,8 +2319,8 @@ static const struct sd_desc sd_desc = { #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, .get_register = sd_dbg_g_register, + .get_chip_info = sd_chip_info, #endif - .get_chip_ident = sd_chip_ident, }; #define SN9C20X(sensor, i2c_addr, flags) \ -- GitLab From 08fe9f7ddf31b8c42dd1a689b0a2c1501f10b58c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:43 -0300 Subject: [PATCH 1236/2900] [media] cx231xx: remove g_chip_ident Remove g_chip_ident and replace it with g_chip_info. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 1 - drivers/media/usb/cx231xx/cx231xx-avcore.c | 1 - drivers/media/usb/cx231xx/cx231xx-cards.c | 1 - drivers/media/usb/cx231xx/cx231xx-vbi.c | 1 - drivers/media/usb/cx231xx/cx231xx-video.c | 417 +++++---------------- drivers/media/usb/cx231xx/cx231xx.h | 2 +- 6 files changed, 103 insertions(+), 320 deletions(-) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index f548db8043d4..2f63029e7a36 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1840,7 +1840,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_log_status = vidioc_log_status, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 235ba657d52e..89de00bf4f82 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -35,7 +35,6 @@ #include #include -#include #include "cx231xx.h" #include "cx231xx-dif.h" diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 13249e5a7891..27948e1798eb 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "dvb-usb-ids.h" diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 1340ff268817..c02794274f51 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -32,7 +32,6 @@ #include #include -#include #include #include diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index cd221474e1b9..54cdd4dc455e 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -1228,179 +1227,86 @@ int cx231xx_s_frequency(struct file *file, void *priv, return rc; } -int cx231xx_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) +#ifdef CONFIG_VIDEO_ADV_DEBUG + +int cx231xx_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip) { - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = V4L2_IDENT_CX23100; + switch (chip->match.addr) { + case 0: /* Cx231xx - internal registers */ + return 0; + case 1: /* AFE - read byte */ + strlcpy(chip->name, "AFE (byte)", sizeof(chip->name)); + return 0; + case 2: /* Video Block - read byte */ + strlcpy(chip->name, "Video (byte)", sizeof(chip->name)); + return 0; + case 3: /* I2S block - read byte */ + strlcpy(chip->name, "I2S (byte)", sizeof(chip->name)); + return 0; + case 4: /* AFE - read dword */ + strlcpy(chip->name, "AFE (dword)", sizeof(chip->name)); + return 0; + case 5: /* Video Block - read dword */ + strlcpy(chip->name, "Video (dword)", sizeof(chip->name)); + return 0; + case 6: /* I2S Block - read dword */ + strlcpy(chip->name, "I2S (dword)", sizeof(chip->name)); return 0; } return -EINVAL; } -#ifdef CONFIG_VIDEO_ADV_DEBUG - -/* - -R, --list-registers=type=, - chip=[,min=,max=] - dump registers from to [VIDIOC_DBG_G_REGISTER] - -r, --set-register=type=, - chip=,reg=,val= - set the register [VIDIOC_DBG_S_REGISTER] - - if type == host, then is the hosts chip ID (default 0) - if type == i2cdrv (default), then is the I2C driver name or ID - if type == i2caddr, then is the 7-bit I2C address -*/ - int cx231xx_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - int ret = 0; + int ret; u8 value[4] = { 0, 0, 0, 0 }; u32 data = 0; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - (u16)reg->reg, value, 4); - reg->val = value[0] | value[1] << 8 | - value[2] << 16 | value[3] << 24; - break; - case 1: /* AFE - read byte */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 2: /* Video Block - read byte */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 24: /* Video Block - read dword */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 3: /* I2S block - read byte */ - ret = cx231xx_read_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 34: /* I2S Block - read dword */ - ret = - cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, &data, 4); - reg->val = le32_to_cpu(data); - break; - } - return ret < 0 ? ret : 0; - - case V4L2_CHIP_MATCH_I2C_DRIVER: - call_all(dev, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/ - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, - (u16)reg->reg, value, 4); - reg->val = value[0] | value[1] << 8 | - value[2] << 16 | value[3] << 24; - - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - } else { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 4 , 0); - reg->val = le32_to_cpu(data); - } - break; - case 0x980: - ret = cx231xx_read_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x400: - ret = - cx231xx_read_i2c_master(dev, 0x40, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0xc01: - ret = - cx231xx_read_i2c_master(dev, 0xc0, - (u16)reg->reg, 2, - &data, 38, 1); - reg->val = le32_to_cpu(data); - break; - case 0x022: - ret = - cx231xx_read_i2c_master(dev, 0x02, - (u16)reg->reg, 1, - &data, 1, 2); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x322: - ret = cx231xx_read_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - case 0x342: - ret = cx231xx_read_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - - default: - cx231xx_info("no match device address!!\n"); - break; - } - return ret < 0 ? ret : 0; - /*return -EINVAL;*/ + switch (reg->match.addr) { + case 0: /* Cx231xx - internal registers */ + ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, + (u16)reg->reg, value, 4); + reg->val = value[0] | value[1] << 8 | + value[2] << 16 | value[3] << 24; + break; + case 1: /* AFE - read byte */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 1); + reg->val = data; + break; + case 2: /* Video Block - read byte */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 1); + reg->val = data; + break; + case 3: /* I2S block - read byte */ + ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, &data, 1); + reg->val = data; + break; + case 4: /* AFE - read dword */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 4); + reg->val = data; + break; + case 5: /* Video Block - read dword */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 4); + reg->val = data; + break; + case 6: /* I2S Block - read dword */ + ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, &data, 4); + reg->val = data; + break; default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + return -EINVAL; } - - call_all(dev, core, g_register, reg); - - return ret; + return ret < 0 ? ret : 0; } int cx231xx_s_register(struct file *file, void *priv, @@ -1408,165 +1314,46 @@ int cx231xx_s_register(struct file *file, void *priv, { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - int ret = 0; - __le64 buf; - u32 value; + int ret; u8 data[4] = { 0, 0, 0, 0 }; - buf = cpu_to_le64(reg->val); - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0: /* cx231xx internal registers */ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 1: /* AFE - read byte */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 2: /* Video Block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 24: /* Video Block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 3: /* I2S block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1); - break; - case 34: /* I2S block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 4); - break; - } - } - return ret < 0 ? ret : 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0:/*cx231xx internal registers*/ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_write_i2c_master(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1 , 0); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1, 0); - else - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4, 0); - break; - case 0x980: - ret = - cx231xx_write_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0x400: - ret = - cx231xx_write_i2c_master(dev, - 0x40, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0xc01: - ret = - cx231xx_write_i2c_master(dev, - 0xc0, - (u16)reg->reg, 1, - value, 1, 1); - break; - - case 0x022: - ret = - cx231xx_write_i2c_master(dev, - 0x02, - (u16)reg->reg, 1, - value, 1, 2); - break; - case 0x322: - ret = - cx231xx_write_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - value, 4, 2); - break; - - case 0x342: - ret = - cx231xx_write_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - value, 4, 2); - break; - default: - cx231xx_info("no match device address, " - "the value is %x\n", reg->match.addr); - break; - - } - - } - default: + switch (reg->match.addr) { + case 0: /* cx231xx internal registers */ + data[0] = (u8) reg->val; + data[1] = (u8) (reg->val >> 8); + data[2] = (u8) (reg->val >> 16); + data[3] = (u8) (reg->val >> 24); + ret = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + (u16)reg->reg, data, 4); + break; + case 1: /* AFE - write byte */ + ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, reg->val, 1); + break; + case 2: /* Video Block - write byte */ + ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, reg->val, 1); + break; + case 3: /* I2S block - write byte */ + ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, reg->val, 1); + break; + case 4: /* AFE - write dword */ + ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, reg->val, 4); + break; + case 5: /* Video Block - write dword */ + ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, reg->val, 4); break; + case 6: /* I2S block - write dword */ + ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, reg->val, 4); + break; + default: + return -EINVAL; } - - call_all(dev, core, s_register, reg); - - return ret; + return ret < 0 ? ret : 0; } #endif @@ -2208,8 +1995,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = cx231xx_s_tuner, .vidioc_g_frequency = cx231xx_g_frequency, .vidioc_s_frequency = cx231xx_s_frequency, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx231xx_g_chip_info, .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, #endif @@ -2240,8 +2027,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_tuner = radio_s_tuner, .vidioc_g_frequency = cx231xx_g_frequency, .vidioc_s_frequency = cx231xx_s_frequency, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx231xx_g_chip_info, .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, #endif diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 5ad9fd61d3c8..e812119ea7a8 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -945,7 +945,7 @@ int cx231xx_enum_input(struct file *file, void *priv, struct v4l2_input *i); int cx231xx_g_input(struct file *file, void *priv, unsigned int *i); int cx231xx_s_input(struct file *file, void *priv, unsigned int i); -int cx231xx_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip); +int cx231xx_g_chip_info(struct file *file, void *fh, struct v4l2_dbg_chip_info *chip); int cx231xx_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg); int cx231xx_s_register(struct file *file, void *priv, -- GitLab From 7486af1ae3ee34b12fcff1b1ce3a9cc6a2eca03a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:44 -0300 Subject: [PATCH 1237/2900] [media] marvell-ccic: remove g_chip_ident Remove g_chip_ident. This driver used some of the V4L2_IDENT defines, replace those with a driver-specific enum. This makes it possible to drop the v4l2-chip-ident.h define as well. Signed-off-by: Hans Verkuil Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/marvell-ccic/cafe-driver.c | 3 +- .../media/platform/marvell-ccic/mcam-core.c | 55 +++---------------- .../media/platform/marvell-ccic/mcam-core.h | 8 ++- .../media/platform/marvell-ccic/mmp-driver.c | 3 +- 4 files changed, 16 insertions(+), 53 deletions(-) diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index d030f9beae88..7b07fc55cd3c 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -469,7 +468,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, goto out; cam->pdev = pdev; mcam = &cam->mcam; - mcam->chip_id = V4L2_IDENT_CAFE; + mcam->chip_id = MCAM_CAFE; spin_lock_init(&mcam->dev_lock); init_waitqueue_head(&cam->smbus_wait); mcam->plat_power_up = cafe_ctlr_power_up; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 64ab91edfb81..a187161e980e 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -336,7 +335,7 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) mcam_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); } else mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); - if (cam->chip_id == V4L2_IDENT_CAFE) + if (cam->chip_id == MCAM_CAFE) mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ } @@ -796,7 +795,6 @@ static int __mcam_cam_reset(struct mcam_camera *cam) */ static int mcam_cam_init(struct mcam_camera *cam) { - struct v4l2_dbg_chip_ident chip; int ret; mutex_lock(&cam->s_mutex); @@ -804,24 +802,8 @@ static int mcam_cam_init(struct mcam_camera *cam) cam_warn(cam, "Cam init with device in funky state %d", cam->state); ret = __mcam_cam_reset(cam); - if (ret) - goto out; - chip.ident = V4L2_IDENT_NONE; - chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; - chip.match.addr = cam->sensor_addr; - ret = sensor_call(cam, core, g_chip_ident, &chip); - if (ret) - goto out; - cam->sensor_type = chip.ident; - if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); - ret = -EINVAL; - goto out; - } -/* Get/set parameters? */ - ret = 0; + /* Get/set parameters? */ cam->state = S_IDLE; -out: mcam_ctlr_power_down(cam); mutex_unlock(&cam->s_mutex); return ret; @@ -1392,20 +1374,6 @@ static int mcam_vidioc_s_parm(struct file *filp, void *priv, return ret; } -static int mcam_vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct mcam_camera *cam = priv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = cam->chip_id; - return 0; - } - return sensor_call(cam, core, g_chip_ident, chip); -} - static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv, struct v4l2_frmsizeenum *sizes) { @@ -1436,12 +1404,9 @@ static int mcam_vidioc_g_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; - if (v4l2_chip_match_host(®->match)) { - reg->val = mcam_reg_read(cam, reg->reg); - reg->size = 4; - return 0; - } - return sensor_call(cam, core, g_register, reg); + reg->val = mcam_reg_read(cam, reg->reg); + reg->size = 4; + return 0; } static int mcam_vidioc_s_register(struct file *file, void *priv, @@ -1449,11 +1414,8 @@ static int mcam_vidioc_s_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; - if (v4l2_chip_match_host(®->match)) { - mcam_reg_write(cam, reg->reg, reg->val); - return 0; - } - return sensor_call(cam, core, s_register, reg); + mcam_reg_write(cam, reg->reg, reg->val); + return 0; } #endif @@ -1477,7 +1439,6 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = { .vidioc_s_parm = mcam_vidioc_s_parm, .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes, .vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals, - .vidioc_g_chip_ident = mcam_vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = mcam_vidioc_g_register, .vidioc_s_register = mcam_vidioc_s_register, @@ -1695,7 +1656,7 @@ int mccic_register(struct mcam_camera *cam) if (buffer_mode >= 0) cam->buffer_mode = buffer_mode; if (cam->buffer_mode == B_DMA_sg && - cam->chip_id == V4L2_IDENT_CAFE) { + cam->chip_id == MCAM_CAFE) { printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, " "attempting vmalloc mode instead\n"); cam->buffer_mode = B_vmalloc; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 01dec9e5fc2b..46b6ea31e66b 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h @@ -53,6 +53,11 @@ enum mcam_buffer_mode { B_DMA_sg = 2 }; +enum mcam_chip_id { + MCAM_CAFE, + MCAM_ARMADA610, +}; + /* * Is a given buffer mode supported by the current kernel configuration? */ @@ -98,7 +103,7 @@ struct mcam_camera { unsigned char __iomem *regs; spinlock_t dev_lock; struct device *dev; /* For messages, dma alloc */ - unsigned int chip_id; + enum mcam_chip_id chip_id; short int clock_speed; /* Sensor clock speed, default 30 */ short int use_smbus; /* SMBUS or straight I2c? */ enum mcam_buffer_mode buffer_mode; @@ -152,7 +157,6 @@ struct mcam_camera { void (*frame_complete)(struct mcam_camera *cam, int frame); /* Current operating parameters */ - u32 sensor_type; /* Currently ov7670 only */ struct v4l2_pix_format pix_format; enum v4l2_mbus_pixelcode mbus_code; diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index c4c17fe76c0d..cadad647ce0e 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -185,7 +184,7 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->plat_power_down = mmpcam_power_down; mcam->dev = &pdev->dev; mcam->use_smbus = 0; - mcam->chip_id = V4L2_IDENT_ARMADA610; + mcam->chip_id = MCAM_ARMADA610; mcam->buffer_mode = B_DMA_sg; spin_lock_init(&mcam->dev_lock); /* -- GitLab From 33001010013749886eca5b5645efd80006dd2e51 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:45 -0300 Subject: [PATCH 1238/2900] [media] tveeprom: remove v4l2-chip-ident.h include Replace the V4L2_IDENT_* usage with tveeprom-specific defines. This header is deprecated, so those defines shouldn't be used anymore. The em28xx driver is the only one that uses the tveeprom audio_processor field, so that has been updated to use the new tveeprom AUDPROC define. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tveeprom.c | 142 +++++++++++------------- drivers/media/usb/em28xx/em28xx-cards.c | 3 +- include/media/tveeprom.h | 11 ++ 3 files changed, 78 insertions(+), 78 deletions(-) diff --git a/drivers/media/common/tveeprom.c b/drivers/media/common/tveeprom.c index cc1e172dfece..c7dace671a9d 100644 --- a/drivers/media/common/tveeprom.c +++ b/drivers/media/common/tveeprom.c @@ -40,7 +40,6 @@ #include #include #include -#include MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_AUTHOR("John Klar"); @@ -67,13 +66,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); * The Hauppauge eeprom uses an 8bit field to determine which * tuner formats the tuner supports. */ -static struct HAUPPAUGE_TUNER_FMT -{ +static const struct { int id; - char *name; -} -hauppauge_tuner_fmt[] = -{ + const char * const name; +} hauppauge_tuner_fmt[] = { { V4L2_STD_UNKNOWN, " UNKNOWN" }, { V4L2_STD_UNKNOWN, " FM" }, { V4L2_STD_B|V4L2_STD_GH, " PAL(B/G)" }, @@ -88,13 +84,10 @@ hauppauge_tuner_fmt[] = supplying this information. Note that many tuners where only used for testing and never made it to the outside world. So you will only see a subset in actual produced cards. */ -static struct HAUPPAUGE_TUNER -{ +static const struct { int id; - char *name; -} -hauppauge_tuner[] = -{ + const char * const name; +} hauppauge_tuner[] = { /* 0-9 */ { TUNER_ABSENT, "None" }, { TUNER_ABSENT, "External" }, @@ -298,69 +291,66 @@ hauppauge_tuner[] = { TUNER_ABSENT, "NXP 18272S"}, }; -/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are +/* Use TVEEPROM_AUDPROC_INTERNAL for those audio 'chips' that are * internal to a video chip, i.e. not a separate audio chip. */ -static struct HAUPPAUGE_AUDIOIC -{ +static const struct { u32 id; - char *name; -} -audioIC[] = -{ + const char * const name; +} audio_ic[] = { /* 0-4 */ - { V4L2_IDENT_NONE, "None" }, - { V4L2_IDENT_UNKNOWN, "TEA6300" }, - { V4L2_IDENT_UNKNOWN, "TEA6320" }, - { V4L2_IDENT_UNKNOWN, "TDA9850" }, - { V4L2_IDENT_MSPX4XX, "MSP3400C" }, + { TVEEPROM_AUDPROC_NONE, "None" }, + { TVEEPROM_AUDPROC_OTHER, "TEA6300" }, + { TVEEPROM_AUDPROC_OTHER, "TEA6320" }, + { TVEEPROM_AUDPROC_OTHER, "TDA9850" }, + { TVEEPROM_AUDPROC_MSP, "MSP3400C" }, /* 5-9 */ - { V4L2_IDENT_MSPX4XX, "MSP3410D" }, - { V4L2_IDENT_MSPX4XX, "MSP3415" }, - { V4L2_IDENT_MSPX4XX, "MSP3430" }, - { V4L2_IDENT_MSPX4XX, "MSP3438" }, - { V4L2_IDENT_UNKNOWN, "CS5331" }, + { TVEEPROM_AUDPROC_MSP, "MSP3410D" }, + { TVEEPROM_AUDPROC_MSP, "MSP3415" }, + { TVEEPROM_AUDPROC_MSP, "MSP3430" }, + { TVEEPROM_AUDPROC_MSP, "MSP3438" }, + { TVEEPROM_AUDPROC_OTHER, "CS5331" }, /* 10-14 */ - { V4L2_IDENT_MSPX4XX, "MSP3435" }, - { V4L2_IDENT_MSPX4XX, "MSP3440" }, - { V4L2_IDENT_MSPX4XX, "MSP3445" }, - { V4L2_IDENT_MSPX4XX, "MSP3411" }, - { V4L2_IDENT_MSPX4XX, "MSP3416" }, + { TVEEPROM_AUDPROC_MSP, "MSP3435" }, + { TVEEPROM_AUDPROC_MSP, "MSP3440" }, + { TVEEPROM_AUDPROC_MSP, "MSP3445" }, + { TVEEPROM_AUDPROC_MSP, "MSP3411" }, + { TVEEPROM_AUDPROC_MSP, "MSP3416" }, /* 15-19 */ - { V4L2_IDENT_MSPX4XX, "MSP3425" }, - { V4L2_IDENT_MSPX4XX, "MSP3451" }, - { V4L2_IDENT_MSPX4XX, "MSP3418" }, - { V4L2_IDENT_UNKNOWN, "Type 0x12" }, - { V4L2_IDENT_UNKNOWN, "OKI7716" }, + { TVEEPROM_AUDPROC_MSP, "MSP3425" }, + { TVEEPROM_AUDPROC_MSP, "MSP3451" }, + { TVEEPROM_AUDPROC_MSP, "MSP3418" }, + { TVEEPROM_AUDPROC_OTHER, "Type 0x12" }, + { TVEEPROM_AUDPROC_OTHER, "OKI7716" }, /* 20-24 */ - { V4L2_IDENT_MSPX4XX, "MSP4410" }, - { V4L2_IDENT_MSPX4XX, "MSP4420" }, - { V4L2_IDENT_MSPX4XX, "MSP4440" }, - { V4L2_IDENT_MSPX4XX, "MSP4450" }, - { V4L2_IDENT_MSPX4XX, "MSP4408" }, + { TVEEPROM_AUDPROC_MSP, "MSP4410" }, + { TVEEPROM_AUDPROC_MSP, "MSP4420" }, + { TVEEPROM_AUDPROC_MSP, "MSP4440" }, + { TVEEPROM_AUDPROC_MSP, "MSP4450" }, + { TVEEPROM_AUDPROC_MSP, "MSP4408" }, /* 25-29 */ - { V4L2_IDENT_MSPX4XX, "MSP4418" }, - { V4L2_IDENT_MSPX4XX, "MSP4428" }, - { V4L2_IDENT_MSPX4XX, "MSP4448" }, - { V4L2_IDENT_MSPX4XX, "MSP4458" }, - { V4L2_IDENT_MSPX4XX, "Type 0x1d" }, + { TVEEPROM_AUDPROC_MSP, "MSP4418" }, + { TVEEPROM_AUDPROC_MSP, "MSP4428" }, + { TVEEPROM_AUDPROC_MSP, "MSP4448" }, + { TVEEPROM_AUDPROC_MSP, "MSP4458" }, + { TVEEPROM_AUDPROC_MSP, "Type 0x1d" }, /* 30-34 */ - { V4L2_IDENT_AMBIGUOUS, "CX880" }, - { V4L2_IDENT_AMBIGUOUS, "CX881" }, - { V4L2_IDENT_AMBIGUOUS, "CX883" }, - { V4L2_IDENT_AMBIGUOUS, "CX882" }, - { V4L2_IDENT_AMBIGUOUS, "CX25840" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX880" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX881" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX883" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX882" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25840" }, /* 35-39 */ - { V4L2_IDENT_AMBIGUOUS, "CX25841" }, - { V4L2_IDENT_AMBIGUOUS, "CX25842" }, - { V4L2_IDENT_AMBIGUOUS, "CX25843" }, - { V4L2_IDENT_AMBIGUOUS, "CX23418" }, - { V4L2_IDENT_AMBIGUOUS, "CX23885" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25841" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25842" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25843" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23418" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23885" }, /* 40-44 */ - { V4L2_IDENT_AMBIGUOUS, "CX23888" }, - { V4L2_IDENT_AMBIGUOUS, "SAA7131" }, - { V4L2_IDENT_AMBIGUOUS, "CX23887" }, - { V4L2_IDENT_AMBIGUOUS, "SAA7164" }, - { V4L2_IDENT_AMBIGUOUS, "AU8522" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23888" }, + { TVEEPROM_AUDPROC_INTERNAL, "SAA7131" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23887" }, + { TVEEPROM_AUDPROC_INTERNAL, "SAA7164" }, + { TVEEPROM_AUDPROC_INTERNAL, "AU8522" }, }; /* This list is supplied by Hauppauge. Thanks! */ @@ -453,11 +443,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, int i, j, len, done, beenhere, tag, start; int tuner1 = 0, t_format1 = 0, audioic = -1; - char *t_name1 = NULL; + const char *t_name1 = NULL; const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; int tuner2 = 0, t_format2 = 0; - char *t_name2 = NULL; + const char *t_name2 = NULL; const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; memset(tvee, 0, sizeof(*tvee)); @@ -545,10 +535,10 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+2] & 0x7f; - if (audioic < ARRAY_SIZE(audioIC)) - tvee->audio_processor = audioIC[audioic].id; + if (audioic < ARRAY_SIZE(audio_ic)) + tvee->audio_processor = audio_ic[audioic].id; else - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; break; /* case 0x03: tag 'EEInfo' */ @@ -578,10 +568,10 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+1] & 0x7f; - if (audioic < ARRAY_SIZE(audioIC)) - tvee->audio_processor = audioIC[audioic].id; + if (audioic < ARRAY_SIZE(audio_ic)) + tvee->audio_processor = audio_ic[audioic].id; else - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; break; @@ -726,11 +716,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, t_fmt_name2[6], t_fmt_name2[7], t_format2); if (audioic < 0) { tveeprom_info("audio processor is unknown (no idx)\n"); - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; } else { - if (audioic < ARRAY_SIZE(audioIC)) + if (audioic < ARRAY_SIZE(audio_ic)) tveeprom_info("audio processor is %s (idx %d)\n", - audioIC[audioic].name, audioic); + audio_ic[audioic].name, audioic); else tveeprom_info("audio processor is unknown (idx %d)\n", audioic); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 927956b4dca7..e4b0669d49dd 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "em28xx.h" @@ -2669,7 +2668,7 @@ static void em28xx_card_setup(struct em28xx *dev) dev->tuner_type = tv.tuner_type; - if (tv.audio_processor == V4L2_IDENT_MSPX4XX) { + if (tv.audio_processor == TVEEPROM_AUDPROC_MSP) { dev->i2s_speed = 2048000; dev->board.has_msp34xx = 1; } diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h index a8ad75a9152a..4a1191abd936 100644 --- a/include/media/tveeprom.h +++ b/include/media/tveeprom.h @@ -1,6 +1,17 @@ /* */ +enum tveeprom_audio_processor { + /* No audio processor present */ + TVEEPROM_AUDPROC_NONE, + /* The audio processor is internal to the video processor */ + TVEEPROM_AUDPROC_INTERNAL, + /* The audio processor is a MSPXXXX device */ + TVEEPROM_AUDPROC_MSP, + /* The audio processor is another device */ + TVEEPROM_AUDPROC_OTHER, +}; + struct tveeprom { u32 has_radio; /* If has_ir == 0, then it is unknown what the IR capabilities are, -- GitLab From 4b7be2bbe0fa8a0e70a61506dcdf088e3b8a8917 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:47 -0300 Subject: [PATCH 1239/2900] [media] au8522_decoder: remove g_chip_ident op This is no longer needed since the core now handles this through DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/au8522_decoder.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 9d159b48e50b..23a0d05ba426 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "au8522.h" #include "au8522_priv.h" @@ -524,11 +523,8 @@ static int au8522_s_ctrl(struct v4l2_ctrl *ctrl) static int au8522_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct au8522_state *state = to_state(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = au8522_readreg(state, reg->reg & 0xffff); return 0; } @@ -536,11 +532,8 @@ static int au8522_g_register(struct v4l2_subdev *sd, static int au8522_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct au8522_state *state = to_state(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; au8522_writereg(state, reg->reg, reg->val & 0xff); return 0; } @@ -632,20 +625,10 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int au8522_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct au8522_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops au8522_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, - .g_chip_ident = au8522_g_chip_ident, .reset = au8522_reset, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = au8522_g_register, -- GitLab From 5f7105755ffe17840a209c556a6f56f31122304b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:48 -0300 Subject: [PATCH 1240/2900] [media] radio: remove g_chip_ident op This is no longer needed since the core now handles this through DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/saa7706h.c | 10 ---------- drivers/media/radio/tef6862.c | 14 -------------- 2 files changed, 24 deletions(-) diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index 06c06cc9ff25..d1f30d6762d3 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -25,7 +25,6 @@ #include #include #include -#include #define DRIVER_NAME "saa7706h" @@ -349,16 +348,7 @@ static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) return -EINVAL; } -static int saa7706h_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0); -} - static const struct v4l2_subdev_core_ops saa7706h_core_ops = { - .g_chip_ident = saa7706h_g_chip_ident, .queryctrl = saa7706h_queryctrl, .g_ctrl = saa7706h_g_ctrl, .s_ctrl = saa7706h_s_ctrl, diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index 82c6c9475d7c..d78afbb08569 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -25,7 +25,6 @@ #include #include #include -#include #define DRIVER_NAME "tef6862" @@ -136,14 +135,6 @@ static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) return 0; } -static int tef6862_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEF6862, 0); -} - static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = { .g_tuner = tef6862_g_tuner, .s_tuner = tef6862_s_tuner, @@ -151,12 +142,7 @@ static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = { .g_frequency = tef6862_g_frequency, }; -static const struct v4l2_subdev_core_ops tef6862_core_ops = { - .g_chip_ident = tef6862_g_chip_ident, -}; - static const struct v4l2_subdev_ops tef6862_ops = { - .core = &tef6862_core_ops, .tuner = &tef6862_tuner_ops, }; -- GitLab From cc3590dbb8d74fb28a294047886c34ebc0ae52bc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:49 -0300 Subject: [PATCH 1241/2900] [media] indycam: remove g_chip_ident op This is no longer needed since the core now handles this through DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/indycam.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/media/platform/indycam.c b/drivers/media/platform/indycam.c index 548236333cce..f1d192bbcb4c 100644 --- a/drivers/media/platform/indycam.c +++ b/drivers/media/platform/indycam.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "indycam.h" @@ -283,20 +282,9 @@ static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* I2C-interface */ -static int indycam_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct indycam *camera = to_indycam(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM, - camera->version); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops indycam_core_ops = { - .g_chip_ident = indycam_g_chip_ident, .g_ctrl = indycam_g_ctrl, .s_ctrl = indycam_s_ctrl, }; -- GitLab From 6be89daa03a4c99b0d22a59a660b225a592ed0a9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:50 -0300 Subject: [PATCH 1242/2900] [media] soc_camera sensors: remove g_chip_ident op This is no longer needed since the core now handles this through DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/imx074.c | 19 --------- drivers/media/i2c/soc_camera/mt9m001.c | 33 +--------------- drivers/media/i2c/soc_camera/mt9m111.c | 33 +--------------- drivers/media/i2c/soc_camera/mt9t031.c | 32 +-------------- drivers/media/i2c/soc_camera/mt9t112.c | 16 -------- drivers/media/i2c/soc_camera/mt9v022.c | 47 +++++++---------------- drivers/media/i2c/soc_camera/ov2640.c | 16 -------- drivers/media/i2c/soc_camera/ov5642.c | 19 --------- drivers/media/i2c/soc_camera/ov6650.c | 12 ------ drivers/media/i2c/soc_camera/ov772x.c | 16 -------- drivers/media/i2c/soc_camera/ov9640.c | 16 -------- drivers/media/i2c/soc_camera/ov9740.c | 17 -------- drivers/media/i2c/soc_camera/rj54n1cb0c.c | 31 +-------------- drivers/media/i2c/soc_camera/tw9910.c | 14 ------- 14 files changed, 21 insertions(+), 300 deletions(-) diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index a2a5cbbdbe28..a315d4386c8e 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -19,7 +19,6 @@ #include #include -#include /* IMX074 registers */ @@ -251,23 +250,6 @@ static int imx074_s_stream(struct v4l2_subdev *sd, int enable) return reg_write(client, MODE_SELECT, !!enable); } -static int imx074_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_IMX074; - id->revision = 0; - - return 0; -} - static int imx074_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -299,7 +281,6 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { }; static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { - .g_chip_ident = imx074_g_chip_ident, .s_power = imx074_s_power, }; diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index dd9089805757..3f1f437ee1c6 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -17,7 +17,6 @@ #include #include #include -#include #include /* @@ -97,7 +96,6 @@ struct mt9m001 { const struct mt9m001_datafmt *fmt; const struct mt9m001_datafmt *fmts; int num_fmts; - int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned int total_h; unsigned short y_skip_top; /* Lines to skip at the top */ }; @@ -320,36 +318,15 @@ static int mt9m001_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9m001_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9m001 *mt9m001 = to_mt9m001(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9m001->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m001_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 2; reg->val = reg_read(client, reg->reg); @@ -364,12 +341,9 @@ static int mt9m001_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -505,11 +479,9 @@ static int mt9m001_video_probe(struct soc_camera_subdev_desc *ssdd, switch (data) { case 0x8411: case 0x8421: - mt9m001->model = V4L2_IDENT_MT9M001C12ST; mt9m001->fmts = mt9m001_colour_fmts; break; case 0x8431: - mt9m001->model = V4L2_IDENT_MT9M001C12STM; mt9m001->fmts = mt9m001_monochrome_fmts; break; default: @@ -580,7 +552,6 @@ static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { - .g_chip_ident = mt9m001_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9m001_g_register, .s_register = mt9m001_s_register, diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index 8bd4e0d2ea03..1aaca0423df7 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c @@ -19,7 +19,6 @@ #include #include #include -#include /* * MT9M111, MT9M112 and MT9M131: @@ -205,8 +204,6 @@ struct mt9m111 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; struct v4l2_ctrl *gain; - int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code - * from v4l2-chip-ident.h */ struct mt9m111_context *ctx; struct v4l2_rect rect; /* cropping rectangle */ int width; /* output */ @@ -600,24 +597,6 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, return ret; } -static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9m111->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m111_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -625,10 +604,8 @@ static int mt9m111_g_register(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); int val; - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; val = mt9m111_reg_read(client, reg->reg); reg->size = 2; @@ -645,12 +622,9 @@ static int mt9m111_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (mt9m111_reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -856,7 +830,6 @@ static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { - .g_chip_ident = mt9m111_g_chip_ident, .s_power = mt9m111_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9m111_g_register, @@ -923,12 +896,10 @@ static int mt9m111_video_probe(struct i2c_client *client) switch (data) { case 0x143a: /* MT9M111 or MT9M131 */ - mt9m111->model = V4L2_IDENT_MT9M111; dev_info(&client->dev, "Detected a MT9M111/MT9M131 chip ID %x\n", data); break; case 0x148c: /* MT9M112 */ - mt9m111->model = V4L2_IDENT_MT9M112; dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data); break; default: diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 26a15b87a9a2..1d2cc27767fe 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -76,7 +75,6 @@ struct mt9t031 { struct v4l2_ctrl *exposure; }; struct v4l2_rect rect; /* Sensor window */ - int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ u16 xskip; u16 yskip; unsigned int total_h; @@ -391,36 +389,15 @@ static int mt9t031_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9t031_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9t031 *mt9t031 = to_mt9t031(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9t031->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9t031_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) @@ -434,12 +411,9 @@ static int mt9t031_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -650,7 +624,6 @@ static int mt9t031_video_probe(struct i2c_client *client) switch (data) { case 0x1621: - mt9t031->model = V4L2_IDENT_MT9T031; break; default: dev_err(&client->dev, @@ -685,7 +658,6 @@ static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { - .g_chip_ident = mt9t031_g_chip_ident, .s_power = mt9t031_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9t031_g_register, diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index a7256b732804..0391d01e8d25 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -27,7 +27,6 @@ #include #include -#include #include /* you can check PLL/clock info */ @@ -91,7 +90,6 @@ struct mt9t112_priv { struct i2c_client *client; struct v4l2_rect frame; const struct mt9t112_format *format; - int model; int num_formats; u32 flags; /* for flags */ @@ -738,17 +736,6 @@ static int mt9t112_init_camera(const struct i2c_client *client) /************************************************************************ v4l2_subdev_core_ops ************************************************************************/ -static int mt9t112_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9t112_priv *priv = to_mt9t112(client); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9t112_g_register(struct v4l2_subdev *sd, @@ -786,7 +773,6 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on) } static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { - .g_chip_ident = mt9t112_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9t112_g_register, .s_register = mt9t112_s_register, @@ -1061,12 +1047,10 @@ static int mt9t112_camera_probe(struct i2c_client *client) switch (chipid) { case 0x2680: devname = "mt9t111"; - priv->model = V4L2_IDENT_MT9T111; priv->num_formats = 1; break; case 0x2682: devname = "mt9t112"; - priv->model = V4L2_IDENT_MT9T112; priv->num_formats = ARRAY_SIZE(mt9t112_cfmts); break; default: diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index a295e598486f..41ff4535eb0d 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -19,7 +19,6 @@ #include #include #include -#include #include /* @@ -133,6 +132,11 @@ static const struct mt9v02x_register mt9v024_register = { .pixclk_fv_lv = MT9V024_PIXCLK_FV_LV, }; +enum mt9v022_model { + MT9V022IX7ATM, + MT9V022IX7ATC, +}; + struct mt9v022 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; @@ -153,7 +157,7 @@ struct mt9v022 { const struct mt9v022_datafmt *fmts; const struct mt9v02x_register *reg; int num_fmts; - int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ + enum mt9v022_model model; u16 chip_control; u16 chip_version; unsigned short y_skip_top; /* Lines to skip at the top */ @@ -406,12 +410,12 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, switch (mf->code) { case V4L2_MBUS_FMT_Y8_1X8: case V4L2_MBUS_FMT_Y10_1X10: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + if (mt9v022->model != MT9V022IX7ATM) return -EINVAL; break; case V4L2_MBUS_FMT_SBGGR8_1X8: case V4L2_MBUS_FMT_SBGGR10_1X10: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + if (mt9v022->model != MT9V022IX7ATC) return -EINVAL; break; default: @@ -457,36 +461,15 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9v022_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9v022 *mt9v022 = to_mt9v022(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9v022->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v022_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 2; reg->val = reg_read(client, reg->reg); @@ -501,12 +484,9 @@ static int mt9v022_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -706,11 +686,11 @@ static int mt9v022_video_probe(struct i2c_client *client) if (sensor_type && (!strcmp("colour", sensor_type) || !strcmp("color", sensor_type))) { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); - mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + mt9v022->model = MT9V022IX7ATC; mt9v022->fmts = mt9v022_colour_fmts; } else { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); - mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + mt9v022->model = MT9V022IX7ATM; mt9v022->fmts = mt9v022_monochrome_fmts; } @@ -740,7 +720,7 @@ static int mt9v022_video_probe(struct i2c_client *client) mt9v022->fmt = &mt9v022->fmts[0]; dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", - data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? + data, mt9v022->model == MT9V022IX7ATM ? "monochrome" : "colour"); ret = mt9v022_init(client); @@ -768,7 +748,6 @@ static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { - .g_chip_ident = mt9v022_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v022_g_register, .s_register = mt9v022_s_register, diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index e3168424f9ba..7961cba6880a 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -304,7 +303,6 @@ struct ov2640_priv { struct v4l2_ctrl_handler hdl; enum v4l2_mbus_pixelcode cfmt_code; const struct ov2640_win_size *win; - int model; }; /* @@ -723,18 +721,6 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int ov2640_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov2640_priv *priv = to_ov2640(client); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov2640_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -1009,7 +995,6 @@ static int ov2640_video_probe(struct i2c_client *client) switch (VERSION(pid, ver)) { case PID_OV2640: devname = "ov2640"; - priv->model = V4L2_IDENT_OV2640; break; default: dev_err(&client->dev, @@ -1034,7 +1019,6 @@ static const struct v4l2_ctrl_ops ov2640_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { - .g_chip_ident = ov2640_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov2640_g_register, .s_register = ov2640_s_register, diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index 9aa56de69eed..c93a157d1d93 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -24,7 +24,6 @@ #include #include -#include #include /* OV5642 registers */ @@ -848,23 +847,6 @@ static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index, return 0; } -static int ov5642_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_OV5642; - id->revision = 0; - - return 0; -} - static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -966,7 +948,6 @@ static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = { static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = { .s_power = ov5642_s_power, - .g_chip_ident = ov5642_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov5642_get_register, .s_register = ov5642_set_register, diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index 991202d4bbae..d2869d87d3b1 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -32,7 +32,6 @@ #include #include -#include #include /* Register definitions */ @@ -390,16 +389,6 @@ static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -/* Get chip identification */ -static int ov6650_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - id->ident = V4L2_IDENT_OV6650; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov6650_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -879,7 +868,6 @@ static const struct v4l2_ctrl_ops ov6550_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov6650_core_ops = { - .g_chip_ident = ov6650_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov6650_get_register, .s_register = ov6650_set_register, diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index 713d62e349f6..b2f623603986 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -27,7 +27,6 @@ #include #include #include -#include #include /* @@ -399,7 +398,6 @@ struct ov772x_priv { struct ov772x_camera_info *info; const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; - int model; unsigned short flag_vflip:1; unsigned short flag_hflip:1; /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ @@ -620,17 +618,6 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int ov772x_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov772x_priv *priv = to_ov772x(sd); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov772x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -965,11 +952,9 @@ static int ov772x_video_probe(struct ov772x_priv *priv) switch (VERSION(pid, ver)) { case OV7720: devname = "ov7720"; - priv->model = V4L2_IDENT_OV7720; break; case OV7725: devname = "ov7725"; - priv->model = V4L2_IDENT_OV7725; break; default: dev_err(&client->dev, @@ -997,7 +982,6 @@ static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { - .g_chip_ident = ov772x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov772x_g_register, .s_register = ov772x_s_register, diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 20ca62d371c1..6817be329666 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -287,18 +286,6 @@ static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -/* Get chip identification */ -static int ov9640_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov9640_priv *priv = to_ov9640_sensor(sd); - - id->ident = priv->model; - id->revision = priv->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov9640_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -615,12 +602,10 @@ static int ov9640_video_probe(struct i2c_client *client) switch (VERSION(pid, ver)) { case OV9640_V2: devname = "ov9640"; - priv->model = V4L2_IDENT_OV9640; priv->revision = 2; break; case OV9640_V3: devname = "ov9640"; - priv->model = V4L2_IDENT_OV9640; priv->revision = 3; break; default: @@ -644,7 +629,6 @@ static const struct v4l2_ctrl_ops ov9640_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov9640_core_ops = { - .g_chip_ident = ov9640_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov9640_get_register, .s_register = ov9640_set_register, diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 012bd6271124..0bc21a643c08 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -17,7 +17,6 @@ #include #include -#include #include #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) @@ -197,7 +196,6 @@ struct ov9740_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; - int ident; u16 model; u8 revision; u8 manid; @@ -772,18 +770,6 @@ static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -/* Get chip identification */ -static int ov9740_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov9740_priv *priv = to_ov9740(sd); - - id->ident = priv->ident; - id->revision = priv->revision; - - return 0; -} - static int ov9740_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -887,8 +873,6 @@ static int ov9740_video_probe(struct i2c_client *client) goto done; } - priv->ident = V4L2_IDENT_OV9740; - dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, " "Manufacturer 0x%02x, SMIA Version 0x%02x\n", priv->model, priv->revision, priv->manid, priv->smiaver); @@ -927,7 +911,6 @@ static struct v4l2_subdev_video_ops ov9740_video_ops = { }; static struct v4l2_subdev_core_ops ov9740_core_ops = { - .g_chip_ident = ov9740_g_chip_ident, .s_power = ov9740_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov9740_get_register, diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index 1f9ec3b06b4e..81b515c2fb36 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #define RJ54N1_DEV_CODE 0x0400 @@ -1120,37 +1119,16 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, return 0; } -static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_RJ54N1CB0C; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int rj54n1_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || - reg->reg < 0x400 || reg->reg > 0x1fff) + if (reg->reg < 0x400 || reg->reg > 0x1fff) /* Registers > 0x0800 are only available from Sharp support */ return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 1; reg->val = reg_read(client, reg->reg); @@ -1165,14 +1143,10 @@ static int rj54n1_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || - reg->reg < 0x400 || reg->reg > 0x1fff) + if (reg->reg < 0x400 || reg->reg > 0x1fff) /* Registers >= 0x0800 are only available from Sharp support */ return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -1233,7 +1207,6 @@ static const struct v4l2_ctrl_ops rj54n1_ctrl_ops = { }; static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { - .g_chip_ident = rj54n1_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = rj54n1_g_register, .s_register = rj54n1_s_register, diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index bad90b16a6dd..8a2ac244d0b3 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -27,7 +27,6 @@ #include #include -#include #include #define GET_ID(val) ((val & 0xF8) >> 3) @@ -518,18 +517,6 @@ static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) return 0; } -static int tw9910_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tw9910_priv *priv = to_tw9910(client); - - id->ident = V4L2_IDENT_TW9910; - id->revision = priv->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int tw9910_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -823,7 +810,6 @@ static int tw9910_video_probe(struct i2c_client *client) } static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { - .g_chip_ident = tw9910_g_chip_ident, .s_std = tw9910_s_std, .g_std = tw9910_g_std, #ifdef CONFIG_VIDEO_ADV_DEBUG -- GitLab From e12771100c93e101a7a8b302b6c5d57cff7b1551 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:51 -0300 Subject: [PATCH 1243/2900] [media] media/i2c: remove g_chip_ident op This is no longer needed since the core now handles this through DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ad9389b.c | 21 +---- drivers/media/i2c/adv7170.c | 13 --- drivers/media/i2c/adv7175.c | 9 -- drivers/media/i2c/adv7180.c | 10 --- drivers/media/i2c/adv7183.c | 22 ----- drivers/media/i2c/adv7343.c | 10 --- drivers/media/i2c/adv7393.c | 10 --- drivers/media/i2c/adv7604.c | 18 ---- drivers/media/i2c/ak881x.c | 34 +------- drivers/media/i2c/bt819.c | 14 --- drivers/media/i2c/bt856.c | 9 -- drivers/media/i2c/bt866.c | 13 --- drivers/media/i2c/cs5345.c | 17 ---- drivers/media/i2c/cs53l32a.c | 10 --- drivers/media/i2c/cx25840/cx25840-core.c | 14 --- drivers/media/i2c/ks0127.c | 16 ---- drivers/media/i2c/m52790.c | 15 ---- drivers/media/i2c/msp3400-driver.c | 10 --- drivers/media/i2c/mt9m032.c | 9 +- drivers/media/i2c/mt9p031.c | 1 - drivers/media/i2c/mt9v011.c | 24 ------ drivers/media/i2c/noon010pc30.c | 1 - drivers/media/i2c/ov7640.c | 1 - drivers/media/i2c/ov7670.c | 17 ---- drivers/media/i2c/saa6588.c | 9 -- drivers/media/i2c/saa7110.c | 9 -- drivers/media/i2c/saa7115.c | 105 +++++++++++------------ drivers/media/i2c/saa7127.c | 47 ++++------ drivers/media/i2c/saa717x.c | 7 -- drivers/media/i2c/saa7185.c | 9 -- drivers/media/i2c/saa7191.c | 10 --- drivers/media/i2c/tda9840.c | 13 --- drivers/media/i2c/tea6415c.c | 13 --- drivers/media/i2c/tea6420.c | 13 --- drivers/media/i2c/ths7303.c | 25 +----- drivers/media/i2c/tvaudio.c | 9 -- drivers/media/i2c/tvp514x.c | 1 - drivers/media/i2c/tvp5150.c | 24 ------ drivers/media/i2c/tvp7002.c | 34 -------- drivers/media/i2c/tw2804.c | 1 - drivers/media/i2c/upd64031a.c | 17 ---- drivers/media/i2c/upd64083.c | 17 ---- drivers/media/i2c/vp27smpx.c | 9 -- drivers/media/i2c/vpx3220.c | 14 --- drivers/media/i2c/vs6624.c | 22 ----- drivers/media/i2c/wm8739.c | 9 -- drivers/media/i2c/wm8775.c | 9 -- 47 files changed, 73 insertions(+), 671 deletions(-) diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index ade1fec7e040..ba4364dfae66 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -343,10 +342,6 @@ static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = { #ifdef CONFIG_VIDEO_ADV_DEBUG static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = ad9389b_rd(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -354,22 +349,11 @@ static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int ad9389b_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_AD9389B, 0); -} - static int ad9389b_log_status(struct v4l2_subdev *sd) { struct ad9389b_state *state = get_ad9389b_state(sd); @@ -596,7 +580,6 @@ static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled) static const struct v4l2_subdev_core_ops ad9389b_core_ops = { .log_status = ad9389b_log_status, - .g_chip_ident = ad9389b_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ad9389b_g_register, .s_register = ad9389b_s_register, @@ -1303,8 +1286,8 @@ static int ad9389b_remove(struct i2c_client *client) /* ----------------------------------------------------------------------- */ static struct i2c_device_id ad9389b_id[] = { - { "ad9389b", V4L2_IDENT_AD9389B }, - { "ad9889b", V4L2_IDENT_AD9389B }, + { "ad9389b", 0 }, + { "ad9889b", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ad9389b_id); diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c index d07689d44354..04bb29720aaf 100644 --- a/drivers/media/i2c/adv7170.c +++ b/drivers/media/i2c/adv7170.c @@ -36,7 +36,6 @@ #include #include #include -#include MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); @@ -317,19 +316,8 @@ static int adv7170_s_fmt(struct v4l2_subdev *sd, return ret; } -static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops adv7170_core_ops = { - .g_chip_ident = adv7170_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops adv7170_video_ops = { .s_std_output = adv7170_s_std_output, .s_routing = adv7170_s_routing, @@ -339,7 +327,6 @@ static const struct v4l2_subdev_video_ops adv7170_video_ops = { }; static const struct v4l2_subdev_ops adv7170_ops = { - .core = &adv7170_core_ops, .video = &adv7170_video_ops, }; diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c index eaefa50b8d28..b88f3b3d5ed9 100644 --- a/drivers/media/i2c/adv7175.c +++ b/drivers/media/i2c/adv7175.c @@ -32,7 +32,6 @@ #include #include #include -#include MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -355,13 +354,6 @@ static int adv7175_s_fmt(struct v4l2_subdev *sd, return ret; } -static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); -} - static int adv7175_s_power(struct v4l2_subdev *sd, int on) { if (on) @@ -375,7 +367,6 @@ static int adv7175_s_power(struct v4l2_subdev *sd, int on) /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7175_core_ops = { - .g_chip_ident = adv7175_g_chip_ident, .init = adv7175_init, .s_power = adv7175_s_power, }; diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index 11f13a83a64b..d7d99f1c69e4 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #define ADV7180_INPUT_CONTROL_REG 0x00 @@ -274,14 +273,6 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) return ret; } -static int adv7180_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0); -} - static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7180_state *state = to_state(sd); @@ -450,7 +441,6 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = { }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { - .g_chip_ident = adv7180_g_chip_ident, .s_std = adv7180_s_std, }; diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 7c48e22b41a2..980815d37bb1 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -481,25 +480,9 @@ static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int adv7183_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - /* 0x11 for adv7183, 0x13 for adv7183b */ - rev = adv7183_read(sd, ADV7183_IDENT); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = adv7183_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -507,10 +490,6 @@ static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -525,7 +504,6 @@ static const struct v4l2_subdev_core_ops adv7183_core_ops = { .g_std = adv7183_g_std, .s_std = adv7183_s_std, .reset = adv7183_reset, - .g_chip_ident = adv7183_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = adv7183_g_register, .s_register = adv7183_s_register, diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 9fc2b985df0e..7606218ec4a7 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -28,7 +28,6 @@ #include #include -#include #include #include "adv7343_regs.h" @@ -311,21 +310,12 @@ static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7343_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0); -} - static const struct v4l2_ctrl_ops adv7343_ctrl_ops = { .s_ctrl = adv7343_s_ctrl, }; static const struct v4l2_subdev_core_ops adv7343_core_ops = { .log_status = adv7343_log_status, - .g_chip_ident = adv7343_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index ec505098598a..558f19154eb9 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -33,7 +33,6 @@ #include #include -#include #include #include "adv7393_regs.h" @@ -301,21 +300,12 @@ static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7393_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7393, 0); -} - static const struct v4l2_ctrl_ops adv7393_ctrl_ops = { .s_ctrl = adv7393_s_ctrl, }; static const struct v4l2_subdev_core_ops adv7393_core_ops = { .log_status = adv7393_log_status, - .g_chip_ident = adv7393_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 5528cd15cc67..1d675b58fd71 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -38,7 +38,6 @@ #include #include #include -#include #include static int debug; @@ -643,10 +642,6 @@ static void adv7604_inv_register(struct v4l2_subdev *sd) static int adv7604_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->size = 1; switch (reg->reg >> 8) { case 0: @@ -699,10 +694,6 @@ static int adv7604_g_register(struct v4l2_subdev *sd, static int adv7604_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; switch (reg->reg >> 8) { case 0: io_write(sd, reg->reg & 0xff, reg->val & 0xff); @@ -980,14 +971,6 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7604_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7604, 0); -} - /* ----------------------------------------------------------------------- */ static inline bool no_power(struct v4l2_subdev *sd) @@ -1783,7 +1766,6 @@ static const struct v4l2_subdev_core_ops adv7604_core_ops = { .s_ctrl = v4l2_subdev_s_ctrl, .queryctrl = v4l2_subdev_queryctrl, .querymenu = v4l2_subdev_querymenu, - .g_chip_ident = adv7604_g_chip_ident, .interrupt_service_routine = adv7604_isr, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = adv7604_g_register, diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index b918c3f29cbe..fcd8a3f626fa 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -33,7 +32,6 @@ struct ak881x { struct v4l2_subdev subdev; struct ak881x_pdata *pdata; unsigned int lines; - int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */ char revision; /* DEVICE_REVISION content */ }; @@ -62,36 +60,15 @@ static struct ak881x *to_ak881x(const struct i2c_client *client) return container_of(i2c_get_clientdata(client), struct ak881x, subdev); } -static int ak881x_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ak881x *ak881x = to_ak881x(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = ak881x->id; - id->revision = ak881x->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ak881x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + if (reg->reg > 0x26) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) @@ -105,12 +82,9 @@ static int ak881x_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + if (reg->reg > 0x26) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -229,7 +203,6 @@ static int ak881x_s_stream(struct v4l2_subdev *sd, int enable) } static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = { - .g_chip_ident = ak881x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ak881x_g_register, .s_register = ak881x_s_register, @@ -274,10 +247,7 @@ static int ak881x_probe(struct i2c_client *client, switch (data) { case 0x13: - ak881x->id = V4L2_IDENT_AK8813; - break; case 0x14: - ak881x->id = V4L2_IDENT_AK8814; break; default: dev_err(&client->dev, diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index ee9ed67e7910..ae1eac01bbc7 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,6 @@ struct bt819 { unsigned char reg[32]; v4l2_std_id norm; - int ident; int input; int enable; }; @@ -373,14 +371,6 @@ static int bt819_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct bt819 *decoder = to_bt819(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops bt819_ctrl_ops = { @@ -388,7 +378,6 @@ static const struct v4l2_ctrl_ops bt819_ctrl_ops = { }; static const struct v4l2_subdev_core_ops bt819_core_ops = { - .g_chip_ident = bt819_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -435,15 +424,12 @@ static int bt819_probe(struct i2c_client *client, switch (ver & 0xf0) { case 0x70: name = "bt819a"; - decoder->ident = V4L2_IDENT_BT819A; break; case 0x60: name = "bt817a"; - decoder->ident = V4L2_IDENT_BT817A; break; case 0x20: name = "bt815a"; - decoder->ident = V4L2_IDENT_BT815A; break; default: v4l2_dbg(1, debug, sd, diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c index 7e5011163b62..7fc163d0253c 100644 --- a/drivers/media/i2c/bt856.c +++ b/drivers/media/i2c/bt856.c @@ -36,7 +36,6 @@ #include #include #include -#include MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -177,17 +176,9 @@ static int bt856_s_routing(struct v4l2_subdev *sd, return 0; } -static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt856_core_ops = { - .g_chip_ident = bt856_g_chip_ident, .init = bt856_init, }; diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c index 9355b924b471..a8bf10fc665d 100644 --- a/drivers/media/i2c/bt866.c +++ b/drivers/media/i2c/bt866.c @@ -36,7 +36,6 @@ #include #include #include -#include MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -175,26 +174,14 @@ static int bt866_s_routing(struct v4l2_subdev *sd, bt866_write(client, 0xdc, val); #endif -static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops bt866_core_ops = { - .g_chip_ident = bt866_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops bt866_video_ops = { .s_std_output = bt866_s_std_output, .s_routing = bt866_s_routing, }; static const struct v4l2_subdev_ops bt866_ops = { - .core = &bt866_core_ops, .video = &bt866_video_ops, }; diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index 2661757c3a8c..34b76a9e7515 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -24,7 +24,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); @@ -99,10 +98,6 @@ static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl) #ifdef CONFIG_VIDEO_ADV_DEBUG static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->size = 1; reg->val = cs5345_read(sd, reg->reg & 0x1f); return 0; @@ -110,22 +105,11 @@ static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int cs5345_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff); return 0; } #endif -static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_CS5345, 0); -} - static int cs5345_log_status(struct v4l2_subdev *sd) { u8 v = cs5345_read(sd, 0x09) & 7; @@ -148,7 +132,6 @@ static const struct v4l2_ctrl_ops cs5345_ctrl_ops = { static const struct v4l2_subdev_core_ops cs5345_core_ops = { .log_status = cs5345_log_status, - .g_chip_ident = cs5345_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index 1082fb775ab2..27400c16ef9a 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -28,7 +28,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); @@ -104,14 +103,6 @@ static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, - chip, V4L2_IDENT_CS53l32A, 0); -} - static int cs53l32a_log_status(struct v4l2_subdev *sd) { struct cs53l32a_state *state = to_state(sd); @@ -130,7 +121,6 @@ static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = { static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { .log_status = cs53l32a_log_status, - .g_chip_ident = cs53l32a_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index b81e32f371ae..6fbdad4fe054 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include "cx25840-core.h" @@ -1662,8 +1661,6 @@ static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->size = 1; reg->val = cx25840_read(client, reg->reg & 0x0fff); return 0; @@ -1673,8 +1670,6 @@ static int cx25840_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); return 0; } @@ -1934,14 +1929,6 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) return 0; } -static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct cx25840_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); -} - static int cx25840_log_status(struct v4l2_subdev *sd) { struct cx25840_state *state = to_state(sd); @@ -5047,7 +5034,6 @@ static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { static const struct v4l2_subdev_core_ops cx25840_core_ops = { .log_status = cx25840_log_status, - .g_chip_ident = cx25840_g_chip_ident, .g_ctrl = v4l2_subdev_g_ctrl, .s_ctrl = v4l2_subdev_s_ctrl, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index c7227763240e..b5223e850a26 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -42,7 +42,6 @@ #include #include #include -#include #include "ks0127.h" MODULE_DESCRIPTION("KS0127 video decoder driver"); @@ -200,7 +199,6 @@ struct adjust { struct ks0127 { struct v4l2_subdev sd; v4l2_std_id norm; - int ident; u8 regs[256]; }; @@ -371,12 +369,9 @@ static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) ****************************************************************************/ static void ks0127_init(struct v4l2_subdev *sd) { - struct ks0127 *ks = to_ks0127(sd); u8 *table = reg_defaults; int i; - ks->ident = V4L2_IDENT_KS0127; - v4l2_dbg(1, debug, sd, "reset\n"); msleep(1); @@ -397,7 +392,6 @@ static void ks0127_init(struct v4l2_subdev *sd) if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) { - ks->ident = V4L2_IDENT_KS0122S; v4l2_dbg(1, debug, sd, "ks0122s found\n"); return; } @@ -408,7 +402,6 @@ static void ks0127_init(struct v4l2_subdev *sd) break; case 9: - ks->ident = V4L2_IDENT_KS0127B; v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n"); break; @@ -646,18 +639,9 @@ static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) return ks0127_status(sd, status, NULL); } -static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ks0127 *ks = to_ks0127(sd); - - return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ks0127_core_ops = { - .g_chip_ident = ks0127_g_chip_ident, .s_std = ks0127_s_std, }; diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 3eeb546be6d9..bf476358704d 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -29,7 +29,6 @@ #include #include #include -#include MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch"); MODULE_AUTHOR("Hans Verkuil"); @@ -83,10 +82,7 @@ static int m52790_s_routing(struct v4l2_subdev *sd, static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; if (reg->reg != 0) return -EINVAL; reg->size = 1; @@ -97,10 +93,7 @@ static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; if (reg->reg != 0) return -EINVAL; state->input = reg->val & 0x0303; @@ -110,13 +103,6 @@ static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif -static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_M52790, 0); -} - static int m52790_log_status(struct v4l2_subdev *sd) { struct m52790_state *state = to_state(sd); @@ -132,7 +118,6 @@ static int m52790_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops m52790_core_ops = { .log_status = m52790_log_status, - .g_chip_ident = m52790_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = m52790_g_register, .s_register = m52790_s_register, diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index ae92c20790e3..8190fec68080 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -570,15 +570,6 @@ static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) return 0; } -static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct msp_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, - (state->rev1 << 16) | state->rev2); -} - static int msp_log_status(struct v4l2_subdev *sd) { struct msp_state *state = to_state(sd); @@ -651,7 +642,6 @@ static const struct v4l2_ctrl_ops msp_ctrl_ops = { static const struct v4l2_subdev_core_ops msp_core_ops = { .log_status = msp_log_status, - .g_chip_ident = msp_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index cca704e02f79..846b15f0bf64 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -554,10 +554,8 @@ static int mt9m032_g_register(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); int val; - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; val = mt9m032_read(client, reg->reg); if (val < 0) @@ -575,12 +573,9 @@ static int mt9m032_s_register(struct v4l2_subdev *sd, struct mt9m032 *sensor = to_mt9m032(sd); struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - return mt9m032_write(client, reg->reg, reg->val); } #endif diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index bf49899945f8..fe3414866a63 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 141919bf77fc..f74698cf14c9 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -407,11 +406,6 @@ static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt static int mt9v011_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - reg->val = mt9v011_read(sd, reg->reg & 0xff); reg->size = 2; @@ -421,29 +415,12 @@ static int mt9v011_g_register(struct v4l2_subdev *sd, static int mt9v011_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); return 0; } #endif -static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - u16 version; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, - version); -} - static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl) { struct mt9v011 *core = @@ -485,7 +462,6 @@ static struct v4l2_ctrl_ops mt9v011_ctrl_ops = { static const struct v4l2_subdev_core_ops mt9v011_core_ops = { .reset = mt9v011_reset, - .g_chip_ident = mt9v011_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v011_g_register, .s_register = mt9v011_s_register, diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 2284b02102db..271d0b7967a6 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c index 5e117abaa2eb..faa64baf09e8 100644 --- a/drivers/media/i2c/ov7640.c +++ b/drivers/media/i2c/ov7640.c @@ -20,7 +20,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("OmniVision ov7640 sensor driver"); diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index b030279810d3..e8a1ce204036 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -1462,23 +1461,12 @@ static const struct v4l2_ctrl_ops ov7670_ctrl_ops = { .g_volatile_ctrl = ov7670_g_volatile_ctrl, }; -static int ov7670_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned char val = 0; int ret; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; ret = ov7670_read(sd, reg->reg & 0xff, &val); reg->val = val; reg->size = 1; @@ -1487,10 +1475,6 @@ static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -1499,7 +1483,6 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { - .g_chip_ident = ov7670_g_chip_ident, .reset = ov7670_reset, .init = ov7670_init, #ifdef CONFIG_VIDEO_ADV_DEBUG diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index 729e78d94222..70bc72e795d0 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -33,7 +33,6 @@ #include #include -#include /* insmod options */ @@ -443,17 +442,9 @@ static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) return 0; } -static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { - .g_chip_ident = saa6588_g_chip_ident, .ioctl = saa6588_ioctl, }; diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index e4026aa93f42..532105de96f0 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -35,7 +35,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); @@ -352,13 +351,6 @@ static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops saa7110_ctrl_ops = { @@ -366,7 +358,6 @@ static const struct v4l2_ctrl_ops saa7110_ctrl_ops = { }; static const struct v4l2_subdev_core_ops saa7110_core_ops = { - .g_chip_ident = saa7110_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 4daa81c55a82..90c43f3fb0f1 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -63,6 +62,16 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +enum saa711x_model { + SAA7111A, + SAA7111, + SAA7113, + GM7113C, + SAA7114, + SAA7115, + SAA7118, +}; + struct saa711x_state { struct v4l2_subdev sd; struct v4l2_ctrl_handler hdl; @@ -80,7 +89,7 @@ struct saa711x_state { int radio; int width; int height; - u32 ident; + enum saa711x_model ident; u32 audclk_freq; u32 crystal_freq; bool ucgc; @@ -111,10 +120,10 @@ static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value) /* Sanity routine to check if a register is present */ static int saa711x_has_reg(const int id, const u8 reg) { - if (id == V4L2_IDENT_SAA7111) + if (id == SAA7111) return reg < 0x20 && reg != 0x01 && reg != 0x0f && (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; - if (id == V4L2_IDENT_SAA7111A) + if (id == SAA7111A) return reg < 0x20 && reg != 0x01 && reg != 0x0f && reg != 0x14 && reg != 0x18 && reg != 0x19 && reg != 0x1d && reg != 0x1e; @@ -127,18 +136,18 @@ static int saa711x_has_reg(const int id, const u8 reg) return 0; switch (id) { - case V4L2_IDENT_GM7113C: + case GM7113C: return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20; - case V4L2_IDENT_SAA7113: + case SAA7113: return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) && reg != 0x5d && reg < 0x63; - case V4L2_IDENT_SAA7114: + case SAA7114: return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) && (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 && reg != 0x81 && reg < 0xf0; - case V4L2_IDENT_SAA7115: + case SAA7115: return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe); - case V4L2_IDENT_SAA7118: + case SAA7118: return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) && (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 && (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0; @@ -955,14 +964,14 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. if (std & V4L2_STD_525_60) { v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); - if (state->ident == V4L2_IDENT_GM7113C) + if (state->ident == GM7113C) saa711x_writeregs(sd, gm7113c_cfg_60hz_video); else saa711x_writeregs(sd, saa7115_cfg_60hz_video); saa711x_set_size(sd, 720, 480); } else { v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); - if (state->ident == V4L2_IDENT_GM7113C) + if (state->ident == GM7113C) saa711x_writeregs(sd, gm7113c_cfg_50hz_video); else saa711x_writeregs(sd, saa7115_cfg_50hz_video); @@ -978,8 +987,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) 011 NTSC N (3.58MHz) PAL M (3.58MHz) 100 reserved NTSC-Japan (3.58MHz) */ - if (state->ident <= V4L2_IDENT_SAA7113 || - state->ident == V4L2_IDENT_GM7113C) { + if (state->ident <= SAA7113 || + state->ident == GM7113C) { u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; if (std == V4L2_STD_PAL_M) { @@ -998,9 +1007,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) /* restart task B if needed */ int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10; - if (taskb && state->ident == V4L2_IDENT_SAA7114) { + if (taskb && state->ident == SAA7114) saa711x_writeregs(sd, saa7115_cfg_vbi_on); - } /* switch audio mode too! */ saa711x_s_clock_freq(sd, state->audclk_freq); @@ -1022,7 +1030,7 @@ static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_forma #else /* SAA7113 and SAA7118 also should support VBI - Need testing */ - if (state->ident != V4L2_IDENT_SAA7115) + if (state->ident != SAA7115) return; #endif @@ -1244,14 +1252,14 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { struct saa711x_state *state = to_state(sd); - u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0; + u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0; v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", input, output); /* saa7111/3 does not have these inputs */ - if ((state->ident <= V4L2_IDENT_SAA7113 || - state->ident == V4L2_IDENT_GM7113C) && + if ((state->ident <= SAA7113 || + state->ident == GM7113C) && (input == SAA7115_COMPOSITE4 || input == SAA7115_COMPOSITE5)) { return -EINVAL; @@ -1266,7 +1274,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, state->input = input; /* saa7111 has slightly different input numbering */ - if (state->ident <= V4L2_IDENT_SAA7111A) { + if (state->ident <= SAA7111A) { if (input >= SAA7115_COMPOSITE4) input -= 2; /* saa7111 specific */ @@ -1289,13 +1297,13 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); state->output = output; - if (state->ident == V4L2_IDENT_SAA7114 || - state->ident == V4L2_IDENT_SAA7115) { + if (state->ident == SAA7114 || + state->ident == SAA7115) { saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | (state->output & 0x01)); } - if (state->ident > V4L2_IDENT_SAA7111A) { + if (state->ident > SAA7111A) { if (config & SAA7115_IDQ_IS_DEFAULT) saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20); else @@ -1308,7 +1316,7 @@ static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) { struct saa711x_state *state = to_state(sd); - if (state->ident > V4L2_IDENT_SAA7111A) + if (state->ident > SAA7111A) return -EINVAL; saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | (val ? 0x80 : 0)); @@ -1398,7 +1406,7 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); - if (state->ident == V4L2_IDENT_SAA7115) { + if (state->ident == SAA7115) { reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e); @@ -1449,7 +1457,7 @@ static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) int reg1f; *status = V4L2_IN_ST_NO_SIGNAL; - if (state->ident == V4L2_IDENT_SAA7115) + if (state->ident == SAA7115) reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80) @@ -1460,10 +1468,6 @@ static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = saa711x_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -1471,23 +1475,11 @@ static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct saa711x_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); -} - static int saa711x_log_status(struct v4l2_subdev *sd) { struct saa711x_state *state = to_state(sd); @@ -1496,7 +1488,7 @@ static int saa711x_log_status(struct v4l2_subdev *sd) int vcr; v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq); - if (state->ident != V4L2_IDENT_SAA7115) { + if (state->ident != SAA7115) { /* status for the saa7114 */ reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); signalOk = (reg1f & 0xc1) == 0x81; @@ -1547,7 +1539,6 @@ static const struct v4l2_ctrl_ops saa711x_ctrl_ops = { static const struct v4l2_subdev_core_ops saa711x_core_ops = { .log_status = saa711x_log_status, - .g_chip_ident = saa711x_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -1650,21 +1641,21 @@ static int saa711x_detect_chip(struct i2c_client *client, if (chip_ver[0] & 0xf0) { snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id); v4l_info(client, "saa7111a variant found\n"); - return V4L2_IDENT_SAA7111A; + return SAA7111A; } - return V4L2_IDENT_SAA7111; + return SAA7111; case '3': - return V4L2_IDENT_SAA7113; + return SAA7113; case '4': - return V4L2_IDENT_SAA7114; + return SAA7114; case '5': - return V4L2_IDENT_SAA7115; + return SAA7115; case '8': - return V4L2_IDENT_SAA7118; + return SAA7118; default: v4l2_info(client, "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n"); - return V4L2_IDENT_SAA7111; + return SAA7111; } } @@ -1695,7 +1686,7 @@ static int saa711x_detect_chip(struct i2c_client *client, "It seems to be a %s chip (%*ph) @ 0x%x.\n", name, 16, chip_ver, client->addr << 1); - return V4L2_IDENT_GM7113C; + return GM7113C; } /* Chip was not discovered. Return its ID and don't bind */ @@ -1774,19 +1765,19 @@ static int saa711x_probe(struct i2c_client *client, /* init to 60hz/48khz */ state->crystal_freq = SAA7115_FREQ_24_576_MHZ; switch (state->ident) { - case V4L2_IDENT_SAA7111: - case V4L2_IDENT_SAA7111A: + case SAA7111: + case SAA7111A: saa711x_writeregs(sd, saa7111_init); break; - case V4L2_IDENT_GM7113C: - case V4L2_IDENT_SAA7113: + case GM7113C: + case SAA7113: saa711x_writeregs(sd, saa7113_init); break; default: state->crystal_freq = SAA7115_FREQ_32_11_MHZ; saa711x_writeregs(sd, saa7115_init_auto_input); } - if (state->ident > V4L2_IDENT_SAA7111A) + if (state->ident > SAA7111A) saa711x_writeregs(sd, saa7115_init_misc); saa711x_set_v4lstd(sd, V4L2_STD_NTSC); v4l2_ctrl_handler_setup(hdl); diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index d9c388103e7a..264b755bedce 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -54,7 +54,6 @@ #include #include #include -#include #include static int debug; @@ -251,10 +250,15 @@ static struct i2c_reg_value saa7127_init_config_50hz_secam[] = { ********************************************************************** */ +enum saa712x_model { + SAA7127, + SAA7129, +}; + struct saa7127_state { struct v4l2_subdev sd; v4l2_std_id std; - u32 ident; + enum saa712x_model ident; enum saa7127_input_type input_type; enum saa7127_output_type output_type; int video_enable; @@ -482,7 +486,7 @@ static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std) inittab = saa7127_init_config_60hz; state->reg_61 = SAA7127_60HZ_DAC_CONTROL; - } else if (state->ident == V4L2_IDENT_SAA7129 && + } else if (state->ident == SAA7129 && (std & V4L2_STD_SECAM) && !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) { @@ -517,7 +521,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_COMPOSITE: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x20; /* CVBS only */ else state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ @@ -525,7 +529,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_SVIDEO: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x18; /* Y + C */ else state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */ @@ -543,7 +547,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_BOTH: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x38; else state->reg_2d = 0xbf; @@ -661,10 +665,6 @@ static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_v #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = saa7127_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -672,23 +672,11 @@ static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct saa7127_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); -} - static int saa7127_log_status(struct v4l2_subdev *sd) { struct saa7127_state *state = to_state(sd); @@ -708,7 +696,6 @@ static int saa7127_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops saa7127_core_ops = { .log_status = saa7127_log_status, - .g_chip_ident = saa7127_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = saa7127_g_register, .s_register = saa7127_s_register, @@ -777,10 +764,10 @@ static int saa7127_probe(struct i2c_client *client, if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, read_result); - state->ident = V4L2_IDENT_SAA7129; + state->ident = SAA7129; strlcpy(client->name, "saa7129", I2C_NAME_SIZE); } else { - state->ident = V4L2_IDENT_SAA7127; + state->ident = SAA7127; strlcpy(client->name, "saa7127", I2C_NAME_SIZE); } } @@ -804,7 +791,7 @@ static int saa7127_probe(struct i2c_client *client, saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); saa7127_set_video_enable(sd, 1); - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) saa7127_write_inittab(sd, saa7129_init_config_extra); return 0; } @@ -825,10 +812,10 @@ static int saa7127_remove(struct i2c_client *client) static struct i2c_device_id saa7127_id[] = { { "saa7127_auto", 0 }, /* auto-detection */ - { "saa7126", V4L2_IDENT_SAA7127 }, - { "saa7127", V4L2_IDENT_SAA7127 }, - { "saa7128", V4L2_IDENT_SAA7129 }, - { "saa7129", V4L2_IDENT_SAA7129 }, + { "saa7126", SAA7127 }, + { "saa7127", SAA7127 }, + { "saa7128", SAA7129 }, + { "saa7129", SAA7129 }, { } }; MODULE_DEVICE_TABLE(i2c, saa7127_id); diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index 330a04c58939..401ca114ab99 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -977,10 +977,6 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = saa717x_read(sd, reg->reg); reg->size = 1; return 0; @@ -988,12 +984,9 @@ static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); u16 addr = reg->reg & 0xffff; u8 val = reg->val & 0xff; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; saa717x_write(sd, addr, val); return 0; } diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c index e95a0edc7f3e..f56c1c88b27d 100644 --- a/drivers/media/i2c/saa7185.c +++ b/drivers/media/i2c/saa7185.c @@ -32,7 +32,6 @@ #include #include #include -#include MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -285,17 +284,9 @@ static int saa7185_s_routing(struct v4l2_subdev *sd, return 0; } -static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7185_core_ops = { - .g_chip_ident = saa7185_g_chip_ident, .init = saa7185_init, }; diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c index 84f7899a4044..08dcaecbeb98 100644 --- a/drivers/media/i2c/saa7191.c +++ b/drivers/media/i2c/saa7191.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "saa7191.h" @@ -567,18 +566,9 @@ static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) } -static int saa7191_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7191_core_ops = { - .g_chip_ident = saa7191_g_chip_ident, .g_ctrl = saa7191_g_ctrl, .s_ctrl = saa7191_s_ctrl, .s_std = saa7191_s_std, diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index 3f1266246ca3..fbdff8b24eec 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -31,7 +31,6 @@ #include #include #include -#include MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("tda9840 driver"); @@ -145,26 +144,14 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) return 0; } -static int tda9840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TDA9840, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tda9840_core_ops = { - .g_chip_ident = tda9840_g_chip_ident, -}; - static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { .s_tuner = tda9840_s_tuner, .g_tuner = tda9840_g_tuner, }; static const struct v4l2_subdev_ops tda9840_ops = { - .core = &tda9840_core_ops, .tuner = &tda9840_tuner_ops, }; diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index 52ebc384e453..bbe1a99fda36 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "tea6415c.h" MODULE_AUTHOR("Michael Hunold "); @@ -119,25 +118,13 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd, return ret; } -static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tea6415c_core_ops = { - .g_chip_ident = tea6415c_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops tea6415c_video_ops = { .s_routing = tea6415c_s_routing, }; static const struct v4l2_subdev_ops tea6415c_ops = { - .core = &tea6415c_core_ops, .video = &tea6415c_video_ops, }; diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 1f869742e3fe..30a8d75771af 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "tea6420.h" MODULE_AUTHOR("Michael Hunold "); @@ -90,25 +89,13 @@ static int tea6420_s_routing(struct v4l2_subdev *sd, return 0; } -static int tea6420_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6420, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tea6420_core_ops = { - .g_chip_ident = tea6420_g_chip_ident, -}; - static const struct v4l2_subdev_audio_ops tea6420_audio_ops = { .s_routing = tea6420_s_routing, }; static const struct v4l2_subdev_ops tea6420_ops = { - .core = &tea6420_core_ops, .audio = &tea6420_audio_ops, }; diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index b954195cfbe7..2e17abc77310 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -26,7 +26,6 @@ #include #include -#include #include #define THS7303_CHANNEL_1 1 @@ -212,15 +211,6 @@ static int ths7303_s_dv_timings(struct v4l2_subdev *sd, return ths7303_config(sd); } -static int ths7303_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ths7303_state *state = to_state(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->driver_data, 0); -} - static const struct v4l2_subdev_video_ops ths7303_video_ops = { .s_stream = ths7303_s_stream, .s_std_output = ths7303_s_std_output, @@ -232,11 +222,6 @@ static const struct v4l2_subdev_video_ops ths7303_video_ops = { static int ths7303_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - reg->size = 1; reg->val = ths7303_read(sd, reg->reg); return 0; @@ -245,11 +230,6 @@ static int ths7303_g_register(struct v4l2_subdev *sd, static int ths7303_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - ths7303_write(sd, reg->reg, reg->val); return 0; } @@ -336,7 +316,6 @@ static int ths7303_log_status(struct v4l2_subdev *sd) } static const struct v4l2_subdev_core_ops ths7303_core_ops = { - .g_chip_ident = ths7303_g_chip_ident, .log_status = ths7303_log_status, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ths7303_g_register, @@ -398,8 +377,8 @@ static int ths7303_remove(struct i2c_client *client) } static const struct i2c_device_id ths7303_id[] = { - {"ths7303", V4L2_IDENT_THS7303}, - {"ths7353", V4L2_IDENT_THS7353}, + {"ths7303", 0}, + {"ths7353", 0}, {}, }; diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index fc69e9c27343..38135402019e 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -38,7 +38,6 @@ #include #include -#include #include #include @@ -1838,13 +1837,6 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen return 0; } -static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0); -} - static int tvaudio_log_status(struct v4l2_subdev *sd) { struct CHIPSTATE *chip = to_state(sd); @@ -1863,7 +1855,6 @@ static const struct v4l2_ctrl_ops tvaudio_ctrl_ops = { static const struct v4l2_subdev_core_ops tvaudio_core_ops = { .log_status = tvaudio_log_status, - .g_chip_ident = tvaudio_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 7438e015d879..b5c17eb89b4e 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index b3cf26628c09..bef528233f7e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "tvp5150_reg.h" @@ -1031,29 +1030,11 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - rev = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER) << 8 | - tvp5150_read(sd, TVP5150_ROM_MINOR_VER); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5150, - rev); -} - - #ifdef CONFIG_VIDEO_ADV_DEBUG static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { int res; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; res = tvp5150_read(sd, reg->reg & 0xff); if (res < 0) { v4l2_err(sd, "%s: failed with error = %d\n", __func__, res); @@ -1067,10 +1048,6 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -1094,7 +1071,6 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .log_status = tvp5150_log_status, .s_std = tvp5150_s_std, .reset = tvp5150_reset, - .g_chip_ident = tvp5150_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index f339e6faca90..c2d0280ef3dc 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include "tvp7002_reg.h" @@ -532,29 +531,6 @@ static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg, *err = tvp7002_write(sd, reg, val); } -/* - * tvp7002_g_chip_ident() - Get chip identification number - * @sd: ptr to v4l2_subdev struct - * @chip: ptr to v4l2_dbg_chip_ident struct - * - * Obtains the chip's identification number. - * Returns zero or -EINVAL if read operation fails. - */ -static int tvp7002_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - u8 rev; - int error; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - error = tvp7002_read(sd, TVP7002_CHIP_REV, &rev); - - if (error < 0) - return error; - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev); -} - /* * tvp7002_write_inittab() - Write initialization values * @sd: ptr to v4l2_subdev struct @@ -741,13 +717,9 @@ static int tvp7002_query_dv_timings(struct v4l2_subdev *sd, static int tvp7002_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); u8 val; int ret; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - ret = tvp7002_read(sd, reg->reg & 0xff, &val); reg->val = val; return ret; @@ -764,11 +736,6 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, static int tvp7002_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff); } #endif @@ -933,7 +900,6 @@ tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, /* V4L2 core operation handlers */ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { - .g_chip_ident = tvp7002_g_chip_ident, .log_status = tvp7002_log_status, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c index 41a5c9b31006..f58607df6193 100644 --- a/drivers/media/i2c/tw2804.c +++ b/drivers/media/i2c/tw2804.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #define TW2804_REG_AUTOGAIN 0x02 diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 13a4cf8bebdf..d248e6a12b8e 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -27,7 +27,6 @@ #include #include #include -#include #include /* --------------------- read registers functions define -------------------- */ @@ -147,13 +146,6 @@ static int upd64031a_s_routing(struct v4l2_subdev *sd, return upd64031a_s_frequency(sd, NULL); } -static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64031A, 0); -} - static int upd64031a_log_status(struct v4l2_subdev *sd) { v4l2_info(sd, "Status: SA00=0x%02x SA01=0x%02x\n", @@ -164,10 +156,6 @@ static int upd64031a_log_status(struct v4l2_subdev *sd) #ifdef CONFIG_VIDEO_ADV_DEBUG static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = upd64031a_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -175,10 +163,6 @@ static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -188,7 +172,6 @@ static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_re static const struct v4l2_subdev_core_ops upd64031a_core_ops = { .log_status = upd64031a_log_status, - .g_chip_ident = upd64031a_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = upd64031a_g_register, .s_register = upd64031a_s_register, diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index e296639ab90e..3a152ce7258a 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -27,7 +27,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("uPD64083 driver"); @@ -122,10 +121,6 @@ static int upd64083_s_routing(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = upd64083_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -133,22 +128,11 @@ static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register static int upd64083_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; upd64083_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64083, 0); -} - static int upd64083_log_status(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -165,7 +149,6 @@ static int upd64083_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops upd64083_core_ops = { .log_status = upd64083_log_status, - .g_chip_ident = upd64083_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = upd64083_g_register, .s_register = upd64083_s_register, diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index 208a095d7bcc..6a3a3ff7ee6a 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -29,7 +29,6 @@ #include #include #include -#include MODULE_DESCRIPTION("vp27smpx driver"); MODULE_AUTHOR("Hans Verkuil"); @@ -112,13 +111,6 @@ static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VP27SMPX, 0); -} - static int vp27smpx_log_status(struct v4l2_subdev *sd) { struct vp27smpx_state *state = to_state(sd); @@ -132,7 +124,6 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { .log_status = vp27smpx_log_status, - .g_chip_ident = vp27smpx_g_chip_ident, .s_std = vp27smpx_s_std, }; diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index f02e74b9b1ac..4c57d8a67c22 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -27,7 +27,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); @@ -49,7 +48,6 @@ struct vpx3220 { unsigned char reg[255]; v4l2_std_id norm; - int ident; int input; int enable; }; @@ -442,14 +440,6 @@ static int vpx3220_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct vpx3220 *decoder = to_vpx3220(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = { @@ -457,7 +447,6 @@ static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = { }; static const struct v4l2_subdev_core_ops vpx3220_core_ops = { - .g_chip_ident = vpx3220_g_chip_ident, .init = vpx3220_init, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, @@ -528,7 +517,6 @@ static int vpx3220_probe(struct i2c_client *client, ver = i2c_smbus_read_byte_data(client, 0x00); pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) + i2c_smbus_read_byte_data(client, 0x01); - decoder->ident = V4L2_IDENT_VPX3220A; if (ver == 0xec) { switch (pn) { case 0x4680: @@ -536,11 +524,9 @@ static int vpx3220_probe(struct i2c_client *client, break; case 0x4260: name = "vpx3216b"; - decoder->ident = V4L2_IDENT_VPX3216B; break; case 0x4280: name = "vpx3214c"; - decoder->ident = V4L2_IDENT_VPX3214C; break; } } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index d2209a35c510..25bdd9312fea 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -722,25 +721,9 @@ static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int vs6624_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) - | vs6624_read(sd, VS6624_FW_VSN_MINOR); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; reg->val = vs6624_read(sd, reg->reg & 0xffff); reg->size = 1; return 0; @@ -748,10 +731,6 @@ static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); return 0; } @@ -762,7 +741,6 @@ static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { }; static const struct v4l2_subdev_core_ops vs6624_core_ops = { - .g_chip_ident = vs6624_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = vs6624_g_register, .s_register = vs6624_s_register, diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index ac3faa7bab2d..3be73f6a40e9 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -29,7 +29,6 @@ #include #include #include -#include #include MODULE_DESCRIPTION("wm8739 driver"); @@ -160,13 +159,6 @@ static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq) return 0; } -static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8739, 0); -} - static int wm8739_log_status(struct v4l2_subdev *sd) { struct wm8739_state *state = to_state(sd); @@ -184,7 +176,6 @@ static const struct v4l2_ctrl_ops wm8739_ctrl_ops = { static const struct v4l2_subdev_core_ops wm8739_core_ops = { .log_status = wm8739_log_status, - .g_chip_ident = wm8739_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 75ded82d513f..3f584a7d0781 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -158,13 +157,6 @@ static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8775, 0); -} - static int wm8775_log_status(struct v4l2_subdev *sd) { struct wm8775_state *state = to_state(sd); @@ -188,7 +180,6 @@ static const struct v4l2_ctrl_ops wm8775_ctrl_ops = { static const struct v4l2_subdev_core_ops wm8775_core_ops = { .log_status = wm8775_log_status, - .g_chip_ident = wm8775_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, -- GitLab From 29d6a98b3381f5d94f56d4c0cd65a8cf7fb9419a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:52 -0300 Subject: [PATCH 1244/2900] [media] cx25840: remove the v4l2-chip-ident.h include Replace the V4L2_IDENT_ macros from v4l2-chip-ident.h with driver specific defines. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/cx25840/cx25840-core.c | 50 ++++++++++++------------ drivers/media/i2c/cx25840/cx25840-core.h | 34 ++++++++++------ 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 6fbdad4fe054..2e3771d57354 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -497,7 +497,7 @@ static void cx23885_initialize(struct i2c_client *client) /* Sys PLL */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide @@ -510,7 +510,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x42c, 0x42600000); cx25840_write4(client, 0x44c, 0x161f1000); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: /* * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide @@ -518,7 +518,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x11c, 0x01d1744c); cx25840_write4(client, 0x118, 0x00000416); break; - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: default: /* * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz @@ -545,7 +545,7 @@ static void cx23885_initialize(struct i2c_client *client) /* HVR1850 */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* 888/HVR1250 specific */ cx25840_write4(client, 0x10c, 0x13333333); cx25840_write4(client, 0x108, 0x00000515); @@ -569,7 +569,7 @@ static void cx23885_initialize(struct i2c_client *client) * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz * 368.64 MHz before post divide @@ -579,7 +579,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: /* * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz * 368.64 MHz before post divide @@ -588,7 +588,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: default: /* * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz @@ -5110,18 +5110,18 @@ static u32 get_cx2388x_ident(struct i2c_client *client) ret = cx25840_read4(client, 0x300); if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { /* No DIF */ - ret = V4L2_IDENT_CX23885_AV; + ret = CX23885_AV; } else { /* CX23887 has a broken DIF, but the registers * appear valid (but unused), good enough to detect. */ - ret = V4L2_IDENT_CX23887_AV; + ret = CX23887_AV; } } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ - ret = V4L2_IDENT_CX23888_AV; + ret = CX23888_AV; } else { v4l_err(client, "Unable to detect h/w, assuming cx23887\n"); - ret = V4L2_IDENT_CX23887_AV; + ret = CX23887_AV; } /* Back into digital power down */ @@ -5135,7 +5135,7 @@ static int cx25840_probe(struct i2c_client *client, struct cx25840_state *state; struct v4l2_subdev *sd; int default_volume; - u32 id = V4L2_IDENT_NONE; + u32 id; u16 device_id; /* Check if the adapter supports the needed features */ @@ -5151,14 +5151,14 @@ static int cx25840_probe(struct i2c_client *client, /* The high byte of the device ID should be * 0x83 for the cx2583x and 0x84 for the cx2584x */ if ((device_id & 0xff00) == 0x8300) { - id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + id = CX25836 + ((device_id >> 4) & 0xf) - 6; } else if ((device_id & 0xff00) == 0x8400) { - id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); + id = CX25840 + ((device_id >> 4) & 0xf); } else if (device_id == 0x0000) { id = get_cx2388x_ident(client); } else if ((device_id & 0xfff0) == 0x5A30) { /* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ - id = V4L2_IDENT_CX2310X_AV; + id = CX2310X_AV; } else if ((device_id & 0xff) == (device_id >> 8)) { v4l_err(client, "likely a confused/unresponsive cx2388[578] A/V decoder" @@ -5180,26 +5180,26 @@ static int cx25840_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &cx25840_ops); switch (id) { - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX2310X_AV: + case CX2310X_AV: v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", device_id, client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX25840: - case V4L2_IDENT_CX25841: - case V4L2_IDENT_CX25842: - case V4L2_IDENT_CX25843: + case CX25840: + case CX25841: + case CX25842: + case CX25843: /* Note: revision '(device_id & 0x0f) == 2' was never built. The marking skips from 0x1 == 22 to 0x3 == 23. */ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", @@ -5208,8 +5208,8 @@ static int cx25840_probe(struct i2c_client *client, : (device_id & 0x0f), client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX25836: - case V4L2_IDENT_CX25837: + case CX25836: + case CX25837: default: v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", (device_id & 0xfff0) >> 4, device_id & 0x0f, diff --git a/drivers/media/i2c/cx25840/cx25840-core.h b/drivers/media/i2c/cx25840/cx25840-core.h index bd4ada28b490..37bc04217c44 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.h +++ b/drivers/media/i2c/cx25840/cx25840-core.h @@ -23,12 +23,24 @@ #include #include -#include #include #include struct cx25840_ir_state; +enum cx25840_model { + CX23885_AV, + CX23887_AV, + CX23888_AV, + CX2310X_AV, + CX25840, + CX25841, + CX25842, + CX25843, + CX25836, + CX25837, +}; + struct cx25840_state { struct i2c_client *c; struct v4l2_subdev sd; @@ -46,7 +58,7 @@ struct cx25840_state { u32 audclk_freq; int audmode; int vbi_line_offset; - u32 id; + enum cx25840_model id; u32 rev; int is_initialized; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ @@ -66,35 +78,35 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) static inline bool is_cx2583x(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX25836 || - state->id == V4L2_IDENT_CX25837; + return state->id == CX25836 || + state->id == CX25837; } static inline bool is_cx231xx(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX2310X_AV; + return state->id == CX2310X_AV; } static inline bool is_cx2388x(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23885_AV || - state->id == V4L2_IDENT_CX23887_AV || - state->id == V4L2_IDENT_CX23888_AV; + return state->id == CX23885_AV || + state->id == CX23887_AV || + state->id == CX23888_AV; } static inline bool is_cx23885(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23885_AV; + return state->id == CX23885_AV; } static inline bool is_cx23887(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23887_AV; + return state->id == CX23887_AV; } static inline bool is_cx23888(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23888_AV; + return state->id == CX23888_AV; } /* ----------------------------------------------------------------------- */ -- GitLab From b83007024219c0135aa18ca5e756b3935c3b8e31 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:59:59 -0300 Subject: [PATCH 1245/2900] [media] saa7134: check register address in g_register Prevent reading out-of-range register values. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 737e643be27a..db4cc1c54aa6 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2258,7 +2258,7 @@ static int vidioc_g_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - reg->val = saa_readb(reg->reg); + reg->val = saa_readb(reg->reg & 0xffffff); reg->size = 1; return 0; } @@ -2269,7 +2269,7 @@ static int vidioc_s_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - saa_writeb(reg->reg&0xffffff, reg->val); + saa_writeb(reg->reg & 0xffffff, reg->val); return 0; } #endif -- GitLab From d2cac168160aa7afd472d4a04d0da3f146243710 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:00 -0300 Subject: [PATCH 1246/2900] [media] mxb: check register address when reading/writing a register Prevent out-of-range register accesses. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7146/mxb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 8d177691cd7c..33abe332d175 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -669,6 +669,8 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + if (reg->reg > pci_resource_len(dev->pci, 0) - 4) + return -EINVAL; reg->val = saa7146_read(dev, reg->reg); reg->size = 4; return 0; @@ -678,6 +680,8 @@ static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_ { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; + if (reg->reg > pci_resource_len(dev->pci, 0) - 4) + return -EINVAL; saa7146_write(dev, reg->reg, reg->val); return 0; } -- GitLab From 9dd1d6f01750955ae5183f0da73606b314cc1a42 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:01 -0300 Subject: [PATCH 1247/2900] [media] vpbe_display: drop g/s_register ioctls These are no longer needed: register access to subdevices no longer needs the bridge driver to forward them. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpbe_display.c | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index 1c4ba8965797..48cb0da3d2b3 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -1578,31 +1578,6 @@ static int vpbe_display_release(struct file *file) return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vpbe_display_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct v4l2_dbg_match *match = ®->match; - struct vpbe_fh *fh = file->private_data; - struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; - - if (match->type >= 2) { - v4l2_subdev_call(vpbe_dev->venc, - core, - g_register, - reg); - } - - return 0; -} - -static int vpbe_display_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - return 0; -} -#endif - /* vpbe capture ioctl operations */ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { .vidioc_querycap = vpbe_display_querycap, @@ -1629,10 +1604,6 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { .vidioc_s_dv_timings = vpbe_display_s_dv_timings, .vidioc_g_dv_timings = vpbe_display_g_dv_timings, .vidioc_enum_dv_timings = vpbe_display_enum_dv_timings, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpbe_display_g_register, - .vidioc_s_register = vpbe_display_s_register, -#endif }; static struct v4l2_file_operations vpbe_fops = { -- GitLab From 4e032f3f58800a998bae79150909410d7a37206f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:02 -0300 Subject: [PATCH 1248/2900] [media] marvell-ccic: check register address Prevent out-of-range register accesses. Signed-off-by: Hans Verkuil Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/cafe-driver.c | 1 + drivers/media/platform/marvell-ccic/mcam-core.c | 4 ++++ drivers/media/platform/marvell-ccic/mcam-core.h | 1 + drivers/media/platform/marvell-ccic/mmp-driver.c | 1 + 4 files changed, 7 insertions(+) diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index 7b07fc55cd3c..1f079ff33d4b 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -500,6 +500,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); goto out_disable; } + mcam->regs_size = pci_resource_len(pdev, 0); ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); if (ret) goto out_iounmap; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index a187161e980e..c69cfc4413fc 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -1404,6 +1404,8 @@ static int mcam_vidioc_g_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; + if (reg->reg > cam->regs_size - 4) + return -EINVAL; reg->val = mcam_reg_read(cam, reg->reg); reg->size = 4; return 0; @@ -1414,6 +1416,8 @@ static int mcam_vidioc_s_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; + if (reg->reg > cam->regs_size - 4) + return -EINVAL; mcam_reg_write(cam, reg->reg, reg->val); return 0; } diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 46b6ea31e66b..520c8ded9443 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h @@ -101,6 +101,7 @@ struct mcam_camera { */ struct i2c_adapter *i2c_adapter; unsigned char __iomem *regs; + unsigned regs_size; /* size in bytes of the register space */ spinlock_t dev_lock; struct device *dev; /* For messages, dma alloc */ enum mcam_chip_id chip_id; diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index cadad647ce0e..a634888271cd 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -202,6 +202,7 @@ static int mmpcam_probe(struct platform_device *pdev) ret = -ENODEV; goto out_free; } + mcam->regs_size = resource_size(res); /* * Power/clock memory is elsewhere; get it too. Perhaps this * should really be managed outside of this driver? -- GitLab From ead5bc4e0bd94e4540bea60b782e2acdb345b803 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:03 -0300 Subject: [PATCH 1249/2900] [media] au0828: set reg->size The size field wasn't filled in. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 4944a365570a..f6154546b5c0 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1759,6 +1759,7 @@ static int vidioc_g_register(struct file *file, void *priv, struct au0828_dev *dev = fh->dev; reg->val = au0828_read(dev, reg->reg); + reg->size = 1; return 0; } -- GitLab From 04ae4cf2cb0c5963b0ea6554f573705c37172313 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:04 -0300 Subject: [PATCH 1250/2900] [media] cx231xx: the reg->size field wasn't filled in Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-video.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 54cdd4dc455e..990626101718 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1272,36 +1272,43 @@ int cx231xx_g_register(struct file *file, void *priv, (u16)reg->reg, value, 4); reg->val = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24; + reg->size = 4; break; case 1: /* AFE - read byte */ ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, &data, 1); reg->val = data; + reg->size = 1; break; case 2: /* Video Block - read byte */ ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, &data, 1); reg->val = data; + reg->size = 1; break; case 3: /* I2S block - read byte */ ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, &data, 1); reg->val = data; + reg->size = 1; break; case 4: /* AFE - read dword */ ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, (u16)reg->reg, 2, &data, 4); reg->val = data; + reg->size = 4; break; case 5: /* Video Block - read dword */ ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, (u16)reg->reg, 2, &data, 4); reg->val = data; + reg->size = 4; break; case 6: /* I2S Block - read dword */ ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, (u16)reg->reg, 1, &data, 4); reg->val = data; + reg->size = 4; break; default: return -EINVAL; -- GitLab From f82fadcfecb5d4aff0711d63fd321f7fabb0f2fa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:05 -0300 Subject: [PATCH 1251/2900] [media] sn9c20x: the reg->size field wasn't filled in Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/sn9c20x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index 23b71f9f5942..f4453d52801b 100644 --- a/drivers/media/usb/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -1557,6 +1557,7 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; + reg->size = 1; switch (reg->match.addr) { case 0: if (reg->reg < 0x1000 || reg->reg > 0x11ff) @@ -1568,6 +1569,7 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, if (sd->sensor >= SENSOR_MT9V011 && sd->sensor <= SENSOR_MT9M112) { i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); + reg->size = 2; } else { i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); } -- GitLab From 43aea90116c4fd80fd3d77b268b4a52ad8bf7bfb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:06 -0300 Subject: [PATCH 1252/2900] [media] pvrusb2: drop g/s_register ioctls Register access to subdevices no longer needs bridge support for those ioctls. The v4l2 core handles that these days. Signed-off-by: Hans Verkuil Cc: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 36 ------------------------ drivers/media/usb/pvrusb2/pvrusb2-hdw.h | 9 ------ drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 34 ---------------------- 3 files changed, 79 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 01d1c2d47cb5..d32920929660 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -5162,39 +5162,3 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) } while(0); LOCK_GIVE(hdw->ctl_lock); return result; } - - -int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - const struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr) -{ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register req; - int stat = 0; - int okFl = 0; - - req.match = *match; - req.reg = reg_id; - if (setFl) req.val = *val_ptr; - /* It would be nice to know if a sub-device answered the request */ - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); - if (!setFl) *val_ptr = req.val; - if (okFl) { - return stat; - } - return -EINVAL; -#else - return -ENOSYS; -#endif -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 91bae930cd79..1a135cf6ae4e 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -234,15 +234,6 @@ int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index); void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); -/* Direct read/write access to chip's registers: - match - specify criteria to identify target chip (this is a v4l dbg struct) - reg_id - register number to access - setFl - true to set the register, false to read it - val_ptr - storage location for source / result. */ -int pvr2_hdw_register_access(struct pvr2_hdw *, - const struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr); - /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index a8a65fa57930..82f619ba5cca 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -800,36 +800,6 @@ static int pvr2_log_status(struct file *file, void *priv) return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 0, &val); - req->val = val; - return ret; -} - -static int pvr2_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - val = req->val; - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 1, &val); - return ret; -} -#endif - static const struct v4l2_ioctl_ops pvr2_ioctl_ops = { .vidioc_querycap = pvr2_querycap, .vidioc_g_priority = pvr2_g_priority, @@ -864,10 +834,6 @@ static const struct v4l2_ioctl_ops pvr2_ioctl_ops = { .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls, .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls, .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = pvr2_g_register, - .vidioc_s_register = pvr2_s_register, -#endif }; static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) -- GitLab From 15c4fee344eb0b8a4d13a351220e337f2e929779 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:07 -0300 Subject: [PATCH 1253/2900] [media] media/i2c: fill in missing reg->size fields Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Cc: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ak881x.c | 1 + drivers/media/i2c/soc_camera/mt9t031.c | 1 + drivers/media/i2c/soc_camera/tw9910.c | 1 + drivers/media/i2c/tvp7002.c | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index fcd8a3f626fa..c14e66756b98 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -69,6 +69,7 @@ static int ak881x_g_register(struct v4l2_subdev *sd, if (reg->reg > 0x26) return -EINVAL; + reg->size = 1; reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 1d2cc27767fe..8f71c9a02cf0 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -398,6 +398,7 @@ static int mt9t031_g_register(struct v4l2_subdev *sd, if (reg->reg > 0xff) return -EINVAL; + reg->size = 1; reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index 8a2ac244d0b3..b5407dfad4ce 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -527,6 +527,7 @@ static int tw9910_g_register(struct v4l2_subdev *sd, if (reg->reg > 0xff) return -EINVAL; + reg->size = 1; ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index c2d0280ef3dc..36ad565e5a33 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -722,6 +722,7 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, ret = tvp7002_read(sd, reg->reg & 0xff, &val); reg->val = val; + reg->size = 1; return ret; } -- GitLab From a2d0909a687b4d250cc2b7481072e361678745ba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 13 Jun 2013 16:06:08 +0200 Subject: [PATCH 1254/2900] iwlwifi: bump required firmware API version for 3160/7260 As the firmware API has changed significantly and we don't have support code for the old APIs, bump the version to be able to release the version 7 API firmware. Unfortunately this means that the driver in 3.9 and 3.10 can't work, but that's still better than crashing the device/driver there. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-7000.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index d4f3b4864ab1..22b7fa5b971a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -67,16 +67,16 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL7260_UCODE_API_MAX 6 -#define IWL3160_UCODE_API_MAX 6 +#define IWL7260_UCODE_API_MAX 7 +#define IWL3160_UCODE_API_MAX 7 /* Oldest version we won't warn about */ -#define IWL7260_UCODE_API_OK 6 -#define IWL3160_UCODE_API_OK 6 +#define IWL7260_UCODE_API_OK 7 +#define IWL3160_UCODE_API_OK 7 /* Lowest firmware API version supported */ -#define IWL7260_UCODE_API_MIN 6 -#define IWL3160_UCODE_API_MIN 6 +#define IWL7260_UCODE_API_MIN 7 +#define IWL3160_UCODE_API_MIN 7 /* NVM versions */ #define IWL7260_NVM_VERSION 0x0a1d -- GitLab From 771d77339b0f7a236d1fc0ef414469b4282b47a9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:08 -0300 Subject: [PATCH 1255/2900] [media] cx18: fix register range check Ensure that the register is aligned to a dword, otherwise the range check could fail since it assumes dword alignment. Signed-off-by: Hans Verkuil Cc: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 414b0ecccc91..1110bcb14e2f 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -367,6 +367,8 @@ static int cx18_g_register(struct file *file, void *fh, { struct cx18 *cx = fh2id(fh)->cx; + if (reg->reg & 0x3) + return -EINVAL; if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) return -EINVAL; reg->size = 4; @@ -379,6 +381,8 @@ static int cx18_s_register(struct file *file, void *fh, { struct cx18 *cx = fh2id(fh)->cx; + if (reg->reg & 0x3) + return -EINVAL; if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) return -EINVAL; cx18_write_enc(cx, reg->val, reg->reg); -- GitLab From e9dab5897066aa979db5de02d0751db9734bbf71 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:10 -0300 Subject: [PATCH 1256/2900] [media] ivtv: fix register range check Ensure that the register is aligned to a dword, otherwise the range check could fail since it assumes dword alignment. Signed-off-by: Hans Verkuil Cc: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtv-ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 944300f7c60b..807b275a847e 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -696,6 +696,8 @@ static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) { volatile u8 __iomem *reg_start; + if (reg & 0x3) + return -EINVAL; if (reg >= IVTV_REG_OFFSET && reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) reg_start = itv->reg_mem - IVTV_REG_OFFSET; else if (itv->has_cx23415 && reg >= IVTV_DECODER_OFFSET && -- GitLab From abbec2d401d6698db44e632f5adbef2a47e6e812 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:00:11 -0300 Subject: [PATCH 1257/2900] [media] DocBook/media/v4l: update VIDIOC_DBG_ documentation - Remove the "On failure the structure remains unchanged." part since that isn't necessarily true. - Document the 'size' field. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-dbg-g-chip-info.xml | 3 +-- .../DocBook/media/v4l/vidioc-dbg-g-register.xml | 15 ++++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml index e1cece6c5de1..80e8021369f6 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml @@ -73,8 +73,7 @@ fields of a &v4l2-dbg-chip-info; and call VIDIOC_DBG_G_CHIP_INFO with a pointer to this structure. On success the driver stores information about the selected chip in the name and -flags fields. On failure the structure -remains unchanged. +flags fields. When match.type is V4L2_CHIP_MATCH_BRIDGE, diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml index d13bac9e2445..e23285fad3bf 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml @@ -76,7 +76,7 @@ compiled with the CONFIG_VIDEO_ADV_DEBUG option to enable these ioctls. To write a register applications must initialize all fields -of a &v4l2-dbg-register; and call +of a &v4l2-dbg-register; except for size and call VIDIOC_DBG_S_REGISTER with a pointer to this structure. The match.type and match.addr or match.name @@ -91,8 +91,8 @@ written into the register. reg fields, and call VIDIOC_DBG_G_REGISTER with a pointer to this structure. On success the driver stores the register value in the -val field. On failure the structure remains -unchanged. +val field and the size (in bytes) of the +value in size. When match.type is V4L2_CHIP_MATCH_BRIDGE, @@ -150,7 +150,7 @@ LinuxTV v4l-dvb repository; see http://linuxtv.org/repo/ for access instructions. - struct <structname>v4l2_dbg_match</structname> @@ -198,6 +198,11 @@ to the type field.matchHow to match the chip, see . + + __u32 + size + The register size in bytes. + __u64 reg @@ -213,7 +218,7 @@ register.
- Chip Match Types -- GitLab From 2249aa5c97a017be4e3b5bb0e9a3ca2d2ed31b27 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 07:59:57 -0300 Subject: [PATCH 1258/2900] [media] v4l2-framework: replace g_chip_ident by g_std in the examples The framework documentation used the g_chip_ident op as an example. This op has been removed, so replace its use in the examples by the g_std op. Signed-off-by: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 13 ++++++------- Documentation/zh_CN/video4linux/v4l2-framework.txt | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index a300b283a1a0..24353ecab197 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -246,7 +246,6 @@ may be NULL if the subdev driver does not support anything from that category. It looks like this: struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); ... @@ -346,24 +345,24 @@ Afterwards the subdev module can be unloaded and sd->dev == NULL. You can call an ops function either directly: - err = sd->ops->core->g_chip_ident(sd, &chip); + err = sd->ops->core->g_std(sd, &norm); but it is better and easier to use this macro: - err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + err = v4l2_subdev_call(sd, core, g_std, &norm); The macro will to the right NULL pointer checks and returns -ENODEV if subdev -is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is -NULL, or the actual result of the subdev->ops->core->g_chip_ident ops. +is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_std is +NULL, or the actual result of the subdev->ops->core->g_std ops. It is also possible to call all or a subset of the sub-devices: - v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); + v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm); Any subdev that does not support this ops is skipped and error results are ignored. If you want to check for errors use this: - err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm); Any error except -ENOIOCTLCMD will exit the loop with that error. If no errors (except -ENOIOCTLCMD) occurred, then 0 is returned. diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt index 44c1d934c4e3..0da95dbaef34 100644 --- a/Documentation/zh_CN/video4linux/v4l2-framework.txt +++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt @@ -247,7 +247,6 @@ i2c_client 结构体,i2c_set_clientdata() 函数可用于保存一个 v4l2_sub 这些结构体定义如下: struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); ... @@ -337,24 +336,24 @@ subdev->dev 域就指向了 v4l2_device。 注册之设备后,可通过以下方式直接调用其操作函数: - err = sd->ops->core->g_chip_ident(sd, &chip); + err = sd->ops->core->g_std(sd, &norm); 但使用如下宏会比较容易且合适: - err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + err = v4l2_subdev_call(sd, core, g_std, &norm); 这个宏将会做 NULL 指针检查,如果 subdev 为 NULL,则返回-ENODEV;如果 -subdev->core 或 subdev->core->g_chip_ident 为 NULL,则返回 -ENOIOCTLCMD; -否则将返回 subdev->ops->core->g_chip_ident ops 调用的实际结果。 +subdev->core 或 subdev->core->g_std 为 NULL,则返回 -ENOIOCTLCMD; +否则将返回 subdev->ops->core->g_std ops 调用的实际结果。 有时也可能同时调用所有或一系列子设备的某个操作函数: - v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); + v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm); 任何不支持此操作的子设备都会被跳过,并忽略错误返回值。但如果你需要 检查出错码,则可使用如下函数: - err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm); 除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果(除 -ENOIOCTLCMD 外)没有错误发生,则返回 0。 -- GitLab From 8ff618320ce304cf96d84dcacd606d3b7f82c78d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 04:50:11 -0300 Subject: [PATCH 1259/2900] [media] saa7706h: convert to the control framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/saa7706h.c | 56 ++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index d1f30d6762d3..ec805b09c608 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -25,6 +25,7 @@ #include #include #include +#include #define DRIVER_NAME "saa7706h" @@ -126,6 +127,7 @@ struct saa7706h_state { struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; unsigned muted; }; @@ -316,42 +318,32 @@ static int saa7706h_mute(struct v4l2_subdev *sd) return err; } -static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +static int saa7706h_s_ctrl(struct v4l2_ctrl *ctrl) { - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - return -EINVAL; -} - -static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct saa7706h_state *state = to_state(sd); + struct saa7706h_state *state = + container_of(ctrl->handler, struct saa7706h_state, hdl); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = state->muted; - return 0; + if (ctrl->val) + return saa7706h_mute(&state->sd); + return saa7706h_unmute(&state->sd); } return -EINVAL; } -static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) - return saa7706h_mute(sd); - return saa7706h_unmute(sd); - } - return -EINVAL; -} +static const struct v4l2_ctrl_ops saa7706h_ctrl_ops = { + .s_ctrl = saa7706h_s_ctrl, +}; static const struct v4l2_subdev_core_ops saa7706h_core_ops = { - .queryctrl = saa7706h_queryctrl, - .g_ctrl = saa7706h_g_ctrl, - .s_ctrl = saa7706h_s_ctrl, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_ops saa7706h_ops = { @@ -383,13 +375,20 @@ static int saa7706h_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa7706h_ops); + v4l2_ctrl_handler_init(&state->hdl, 4); + v4l2_ctrl_new_std(&state->hdl, &saa7706h_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + sd->ctrl_handler = &state->hdl; + err = state->hdl.error; + if (err) + goto err; + /* check the rom versions */ err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER); if (err < 0) goto err; if (err != SUPPORTED_DSP1_ROM_VER) v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err); - state->muted = 1; /* startup in a muted state */ @@ -401,6 +400,7 @@ static int saa7706h_probe(struct i2c_client *client, err: v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&state->hdl); kfree(to_state(sd)); printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err); @@ -411,9 +411,11 @@ static int saa7706h_probe(struct i2c_client *client, static int saa7706h_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa7706h_state *state = to_state(sd); saa7706h_mute(sd); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&state->hdl); kfree(to_state(sd)); return 0; } -- GitLab From 04de560296158c481570a020748d1239e493617b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:17:42 -0300 Subject: [PATCH 1260/2900] [media] sr030pc30: convert to the control framework Signed-off-by: Hans Verkuil Acked-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/sr030pc30.c | 276 +++++++++++----------------------- 1 file changed, 88 insertions(+), 188 deletions(-) diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index 4c5a9ee60c3e..ae9432637fcb 100644 --- a/drivers/media/i2c/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c @@ -23,6 +23,7 @@ #include #include #include +#include #include static int debug; @@ -142,17 +143,24 @@ module_param(debug, int, 0644); struct sr030pc30_info { struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; const struct sr030pc30_platform_data *pdata; const struct sr030pc30_format *curr_fmt; const struct sr030pc30_frmsize *curr_win; - unsigned int auto_wb:1; - unsigned int auto_exp:1; unsigned int hflip:1; unsigned int vflip:1; unsigned int sleep:1; - unsigned int exposure; - u8 blue_balance; - u8 red_balance; + struct { + /* auto whitebalance control cluster */ + struct v4l2_ctrl *awb; + struct v4l2_ctrl *red; + struct v4l2_ctrl *blue; + }; + struct { + /* auto exposure control cluster */ + struct v4l2_ctrl *autoexp; + struct v4l2_ctrl *exp; + }; u8 i2c_reg_page; }; @@ -173,52 +181,6 @@ struct i2c_regval { u16 val; }; -static const struct v4l2_queryctrl sr030pc30_ctrl[] = { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto White Balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - }, { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Auto Exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = EXPOS_MIN_MS, - .maximum = EXPOS_MAX_MS, - .step = 1, - .default_value = 1, - }, { - } -}; - /* supported resolutions */ static const struct sr030pc30_frmsize sr030pc30_sizes[] = { { @@ -394,48 +356,6 @@ static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd, return ret; } -static inline int sr030pc30_enable_autoexposure(struct v4l2_subdev *sd, int on) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - /* auto anti-flicker is also enabled here */ - int ret = cam_i2c_write(sd, AE_CTL1_REG, on ? 0xDC : 0x0C); - if (!ret) - info->auto_exp = on; - return ret; -} - -static int sr030pc30_set_exposure(struct v4l2_subdev *sd, int value) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - unsigned long expos = value * info->pdata->clk_rate / (8 * 1000); - - int ret = cam_i2c_write(sd, EXP_TIMEH_REG, expos >> 16 & 0xFF); - if (!ret) - ret = cam_i2c_write(sd, EXP_TIMEM_REG, expos >> 8 & 0xFF); - if (!ret) - ret = cam_i2c_write(sd, EXP_TIMEL_REG, expos & 0xFF); - if (!ret) { /* Turn off AE */ - info->exposure = value; - ret = sr030pc30_enable_autoexposure(sd, 0); - } - return ret; -} - -/* Automatic white balance control */ -static int sr030pc30_enable_autowhitebalance(struct v4l2_subdev *sd, int on) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - int ret = cam_i2c_write(sd, AWB_CTL2_REG, on ? 0x2E : 0x2F); - if (!ret) - ret = cam_i2c_write(sd, AWB_CTL1_REG, on ? 0xFB : 0x7B); - if (!ret) - info->auto_wb = on; - - return ret; -} - static int sr030pc30_set_flip(struct v4l2_subdev *sd) { struct sr030pc30_info *info = to_sr030pc30(sd); @@ -498,107 +418,56 @@ static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf) return -EINVAL; } -static int sr030pc30_queryctrl(struct v4l2_subdev *sd, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++) - if (qc->id == sr030pc30_ctrl[i].id) { - *qc = sr030pc30_ctrl[i]; - v4l2_dbg(1, debug, sd, "%s id: %d\n", - __func__, qc->id); - return 0; - } - - return -EINVAL; -} - -static inline int sr030pc30_set_bluebalance(struct v4l2_subdev *sd, int value) -{ - int ret = cam_i2c_write(sd, MWB_BGAIN_REG, value); - if (!ret) - to_sr030pc30(sd)->blue_balance = value; - return ret; -} - -static inline int sr030pc30_set_redbalance(struct v4l2_subdev *sd, int value) -{ - int ret = cam_i2c_write(sd, MWB_RGAIN_REG, value); - if (!ret) - to_sr030pc30(sd)->red_balance = value; - return ret; -} - -static int sr030pc30_s_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) +static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl) { - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++) - if (ctrl->id == sr030pc30_ctrl[i].id) - break; - - if (i == ARRAY_SIZE(sr030pc30_ctrl)) - return -EINVAL; - - if (ctrl->value < sr030pc30_ctrl[i].minimum || - ctrl->value > sr030pc30_ctrl[i].maximum) - return -ERANGE; + struct sr030pc30_info *info = + container_of(ctrl->handler, struct sr030pc30_info, hdl); + struct v4l2_subdev *sd = &info->sd; + int ret = 0; v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n", - __func__, ctrl->id, ctrl->value); + __func__, ctrl->id, ctrl->val); switch (ctrl->id) { case V4L2_CID_AUTO_WHITE_BALANCE: - sr030pc30_enable_autowhitebalance(sd, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - ret = sr030pc30_set_bluebalance(sd, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - ret = sr030pc30_set_redbalance(sd, ctrl->value); - break; - case V4L2_CID_EXPOSURE_AUTO: - sr030pc30_enable_autoexposure(sd, - ctrl->value == V4L2_EXPOSURE_AUTO); - break; - case V4L2_CID_EXPOSURE: - ret = sr030pc30_set_exposure(sd, ctrl->value); - break; - default: - return -EINVAL; - } - - return ret; -} - -static int sr030pc30_g_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - v4l2_dbg(1, debug, sd, "%s: id: %d\n", __func__, ctrl->id); + if (ctrl->is_new) { + ret = cam_i2c_write(sd, AWB_CTL2_REG, + ctrl->val ? 0x2E : 0x2F); + if (!ret) + ret = cam_i2c_write(sd, AWB_CTL1_REG, + ctrl->val ? 0xFB : 0x7B); + } + if (!ret && info->blue->is_new) + ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val); + if (!ret && info->red->is_new) + ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val); + return ret; - switch (ctrl->id) { - case V4L2_CID_AUTO_WHITE_BALANCE: - ctrl->value = info->auto_wb; - break; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = info->blue_balance; - break; - case V4L2_CID_RED_BALANCE: - ctrl->value = info->red_balance; - break; case V4L2_CID_EXPOSURE_AUTO: - ctrl->value = info->auto_exp; - break; - case V4L2_CID_EXPOSURE: - ctrl->value = info->exposure; - break; + /* auto anti-flicker is also enabled here */ + if (ctrl->is_new) + ret = cam_i2c_write(sd, AE_CTL1_REG, + ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C); + if (info->exp->is_new) { + unsigned long expos = info->exp->val; + + expos = expos * info->pdata->clk_rate / (8 * 1000); + + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEH_REG, + expos >> 16 & 0xFF); + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEM_REG, + expos >> 8 & 0xFF); + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEL_REG, + expos & 0xFF); + } + return ret; default: return -EINVAL; } + return 0; } @@ -752,11 +621,19 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on) return ret; } +static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = { + .s_ctrl = sr030pc30_s_ctrl, +}; + static const struct v4l2_subdev_core_ops sr030pc30_core_ops = { .s_power = sr030pc30_s_power, - .queryctrl = sr030pc30_queryctrl, - .s_ctrl = sr030pc30_s_ctrl, - .g_ctrl = sr030pc30_g_ctrl, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_video_ops sr030pc30_video_ops = { @@ -807,6 +684,7 @@ static int sr030pc30_probe(struct i2c_client *client, { struct sr030pc30_info *info; struct v4l2_subdev *sd; + struct v4l2_ctrl_handler *hdl; const struct sr030pc30_platform_data *pdata = client->dev.platform_data; int ret; @@ -830,10 +708,31 @@ static int sr030pc30_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops); + hdl = &info->hdl; + v4l2_ctrl_handler_init(hdl, 6); + info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); + info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_RED_BALANCE, 0, 127, 1, 64); + info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64); + info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1); + info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30); + sd->ctrl_handler = hdl; + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + return err; + } + v4l2_ctrl_auto_cluster(3, &info->awb, 0, false); + v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false); + v4l2_ctrl_handler_setup(hdl); + info->i2c_reg_page = -1; info->hflip = 1; - info->auto_exp = 1; - info->exposure = 30; return 0; } @@ -843,6 +742,7 @@ static int sr030pc30_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(sd->ctrl_handler); return 0; } -- GitLab From bb732ccca29123850ffcacefe51cf2bc7d16e88c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 04:51:42 -0300 Subject: [PATCH 1261/2900] [media] saa6752hs: convert to the control framework Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa6752hs.c | 457 +++++++------------------- 1 file changed, 122 insertions(+), 335 deletions(-) diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index 244b2868dfc8..8adb7b02ab5a 100644 --- a/drivers/media/pci/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,12 @@ static const struct v4l2_format v4l2_format_table[] = struct saa6752hs_state { struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + struct { /* video bitrate mode control cluster */ + struct v4l2_ctrl *video_bitrate_mode; + struct v4l2_ctrl *video_bitrate; + struct v4l2_ctrl *video_bitrate_peak; + }; u32 revision; int has_ac3; struct saa6752hs_mpeg_params params; @@ -360,316 +367,72 @@ static int saa6752hs_set_bitrate(struct i2c_client *client, return 0; } - -static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl) +static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl) { + struct saa6752hs_state *h = + container_of(ctrl->handler, struct saa6752hs_state, hdl); + switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - break; - case V4L2_CID_MPEG_STREAM_PID_PMT: - ctrl->value = params->ts_pid_pmt; - break; - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - ctrl->value = params->ts_pid_audio; - break; - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - ctrl->value = params->ts_pid_video; - break; - case V4L2_CID_MPEG_STREAM_PID_PCR: - ctrl->value = params->ts_pid_pcr; - break; - case V4L2_CID_MPEG_AUDIO_ENCODING: - ctrl->value = params->au_encoding; - break; - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - ctrl->value = params->au_l2_bitrate; - break; - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!has_ac3) - return -EINVAL; - ctrl->value = params->au_ac3_bitrate; - break; - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctrl->value = params->vi_aspect; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctrl->value = params->vi_bitrate * 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - ctrl->value = params->vi_bitrate_peak * 1000; - break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctrl->value = params->vi_bitrate_mode; + /* peak bitrate shall be >= normal bitrate */ + if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + h->video_bitrate_peak->val < h->video_bitrate->val) + h->video_bitrate_peak->val = h->video_bitrate->val; break; - default: - return -EINVAL; } return 0; } -static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl, int set) +static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl) { - int old = 0, new; + struct saa6752hs_state *h = + container_of(ctrl->handler, struct saa6752hs_state, hdl); + struct saa6752hs_mpeg_params *params = &h->params; - new = ctrl->value; switch (ctrl->id) { case V4L2_CID_MPEG_STREAM_TYPE: - old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_STREAM_PID_PMT: - old = params->ts_pid_pmt; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pmt = new; + params->ts_pid_pmt = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_AUDIO: - old = params->ts_pid_audio; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_audio = new; + params->ts_pid_audio = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_VIDEO: - old = params->ts_pid_video; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_video = new; + params->ts_pid_video = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_PCR: - old = params->ts_pid_pcr; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pcr = new; + params->ts_pid_pcr = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_ENCODING: - old = params->au_encoding; - if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && - (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) - return -ERANGE; - params->au_encoding = new; + params->au_encoding = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - old = params->au_l2_bitrate; - if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && - new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) - new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; - params->au_l2_bitrate = new; + params->au_l2_bitrate = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!has_ac3) - return -EINVAL; - old = params->au_ac3_bitrate; - if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && - new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) - new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; - params->au_ac3_bitrate = new; + params->au_ac3_bitrate = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_VIDEO_ENCODING: - old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_VIDEO_ASPECT: - old = params->vi_aspect; - if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && - new != V4L2_MPEG_VIDEO_ASPECT_4x3) - return -ERANGE; - if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) - new = V4L2_MPEG_VIDEO_ASPECT_4x3; - params->vi_aspect = new; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - old = params->vi_bitrate * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate = new / 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - old = params->vi_bitrate_peak * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate_peak = new / 1000; + params->vi_aspect = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - old = params->vi_bitrate_mode; - params->vi_bitrate_mode = new; + params->vi_bitrate_mode = ctrl->val; + params->vi_bitrate = h->video_bitrate->val / 1000; + params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000; + v4l2_ctrl_activate(h->video_bitrate_peak, + ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); break; default: return -EINVAL; } - ctrl->value = new; return 0; } - -static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) -{ - struct saa6752hs_state *h = to_state(sd); - struct saa6752hs_mpeg_params *params = &h->params; - int err; - - switch (qctrl->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); - - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L2_BITRATE_256K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_L2_BITRATE_256K); - - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!h->has_ac3) - return -EINVAL; - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K); - - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); - - case V4L2_CID_MPEG_VIDEO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2); - - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ASPECT_4x3, - V4L2_MPEG_VIDEO_ASPECT_16x9, 1, - V4L2_MPEG_VIDEO_ASPECT_4x3); - - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); - if (err == 0 && - params->vi_bitrate_mode == - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) - qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return err; - - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS); - - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); - case V4L2_CID_MPEG_STREAM_PID_PMT: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); - case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); - - default: - break; - } - return -EINVAL; -} - -static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) -{ - static const u32 mpeg_audio_encoding[] = { - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - V4L2_CTRL_MENU_IDS_END - }; - static const u32 mpeg_audio_ac3_encoding[] = { - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - V4L2_MPEG_AUDIO_ENCODING_AC3, - V4L2_CTRL_MENU_IDS_END - }; - static u32 mpeg_audio_l2_bitrate[] = { - V4L2_MPEG_AUDIO_L2_BITRATE_256K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, - V4L2_CTRL_MENU_IDS_END - }; - static u32 mpeg_audio_ac3_bitrate[] = { - V4L2_MPEG_AUDIO_AC3_BITRATE_256K, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K, - V4L2_CTRL_MENU_IDS_END - }; - struct saa6752hs_state *h = to_state(sd); - struct v4l2_queryctrl qctrl; - int err; - - qctrl.id = qmenu->id; - err = saa6752hs_queryctrl(sd, &qctrl); - if (err) - return err; - switch (qmenu->id) { - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_menu_valid_items(qmenu, - mpeg_audio_l2_bitrate); - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!h->has_ac3) - return -EINVAL; - return v4l2_ctrl_query_menu_valid_items(qmenu, - mpeg_audio_ac3_bitrate); - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_menu_valid_items(qmenu, - h->has_ac3 ? mpeg_audio_ac3_encoding : - mpeg_audio_encoding); - } - return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); -} - static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) { unsigned char buf[9], buf2[4]; @@ -791,58 +554,6 @@ static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) return 0; } -static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) -{ - struct saa6752hs_state *h = to_state(sd); - struct saa6752hs_mpeg_params params; - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - params = h->params; - for (i = 0; i < ctrls->count; i++) { - int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set); - - if (err) { - ctrls->error_idx = i; - return err; - } - } - if (set) - h->params = params; - return 0; -} - -static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - return saa6752hs_do_ext_ctrls(sd, ctrls, 1); -} - -static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - return saa6752hs_do_ext_ctrls(sd, ctrls, 0); -} - -static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - struct saa6752hs_state *h = to_state(sd); - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i); - - if (err) { - ctrls->error_idx = i; - return err; - } - } - return 0; -} - static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); @@ -914,13 +625,20 @@ static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) /* ----------------------------------------------------------------------- */ +static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = { + .try_ctrl = saa6752hs_try_ctrl, + .s_ctrl = saa6752hs_s_ctrl, +}; + static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { .init = saa6752hs_init, - .queryctrl = saa6752hs_queryctrl, - .querymenu = saa6752hs_querymenu, - .g_ext_ctrls = saa6752hs_g_ext_ctrls, - .s_ext_ctrls = saa6752hs_s_ext_ctrls, - .try_ext_ctrls = saa6752hs_try_ext_ctrls, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, .s_std = saa6752hs_s_std, }; @@ -939,6 +657,7 @@ static int saa6752hs_probe(struct i2c_client *client, { struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); struct v4l2_subdev *sd; + struct v4l2_ctrl_handler *hdl; u8 addr = 0x13; u8 data[12]; @@ -955,9 +674,84 @@ static int saa6752hs_probe(struct i2c_client *client, h->has_ac3 = 0; if (h->revision == 0x0206) { h->has_ac3 = 1; - v4l_info(client, "support AC-3\n"); + v4l_info(client, "supports AC-3\n"); } h->params = param_defaults; + + hdl = &h->hdl; + v4l2_ctrl_handler_init(hdl, 14); + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_ENCODING, + h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_L2_BITRATE, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, + ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) | + (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)), + V4L2_MPEG_AUDIO_L2_BITRATE_256K); + + if (h->has_ac3) + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_AC3_BITRATE, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K, + ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | + (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)), + V4L2_MPEG_AUDIO_AC3_BITRATE_256K); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, + ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000), + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, + ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2), + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01, + V4L2_MPEG_VIDEO_ASPECT_4x3); + + h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + 1000000, 27000000, 1000, 8000000); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_MPEG_STREAM_TYPE_MPEG2_TS, + ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS), + V4L2_MPEG_STREAM_TYPE_MPEG2_TS); + + h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259); + sd->ctrl_handler = hdl; + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + kfree(h); + return err; + } + v4l2_ctrl_cluster(3, &h->video_bitrate_mode); + v4l2_ctrl_handler_setup(hdl); h->standard = 0; /* Assume 625 input lines */ return 0; } @@ -967,6 +761,7 @@ static int saa6752hs_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&to_state(sd)->hdl); kfree(to_state(sd)); return 0; } @@ -988,11 +783,3 @@ static struct i2c_driver saa6752hs_driver = { }; module_i2c_driver(saa6752hs_driver); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ -- GitLab From 099f88ee20c4d387a7bd76e0a5765533b1f5b6b0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:25:32 -0300 Subject: [PATCH 1262/2900] [media] radio-tea5764: add support for struct v4l2_device Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 38d563d62595..f6a5471e51aa 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -39,6 +39,7 @@ #include /* I2C */ #include #include +#include #define DRIVER_VERSION "0.0.2" @@ -138,6 +139,7 @@ static int radio_nr = -1; static int use_xtal = RADIO_TEA5764_XTAL; struct tea5764_device { + struct v4l2_device v4l2_dev; struct i2c_client *i2c_client; struct video_device *videodev; struct tea5764_regs regs; @@ -497,6 +499,7 @@ static int tea5764_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tea5764_device *radio; + struct v4l2_device *v4l2_dev; struct tea5764_regs *r; int ret; @@ -505,31 +508,37 @@ static int tea5764_i2c_probe(struct i2c_client *client, if (!radio) return -ENOMEM; + v4l2_dev = &radio->v4l2_dev; + ret = v4l2_device_register(&client->dev, v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); + goto errfr; + } mutex_init(&radio->mutex); radio->i2c_client = client; ret = tea5764_i2c_read(radio); if (ret) - goto errfr; + goto errunreg; r = &radio->regs; PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid); if (r->chipid != TEA5764_CHIPID || (r->manid & 0x0fff) != TEA5764_MANID) { PWARN("This chip is not a TEA5764!"); ret = -EINVAL; - goto errfr; + goto errunreg; } radio->videodev = video_device_alloc(); if (!(radio->videodev)) { ret = -ENOMEM; - goto errfr; + goto errunreg; } - memcpy(radio->videodev, &tea5764_radio_template, - sizeof(tea5764_radio_template)); + *radio->videodev = tea5764_radio_template; i2c_set_clientdata(client, radio); video_set_drvdata(radio->videodev, radio); radio->videodev->lock = &radio->mutex; + radio->videodev->v4l2_dev = v4l2_dev; /* initialize and power off the chip */ tea5764_i2c_read(radio); @@ -547,6 +556,8 @@ static int tea5764_i2c_probe(struct i2c_client *client, return 0; errrel: video_device_release(radio->videodev); +errunreg: + v4l2_device_unregister(v4l2_dev); errfr: kfree(radio); return ret; @@ -560,6 +571,7 @@ static int tea5764_i2c_remove(struct i2c_client *client) if (radio) { tea5764_power_down(radio); video_unregister_device(radio->videodev); + v4l2_device_unregister(&radio->v4l2_dev); kfree(radio); } return 0; -- GitLab From cf9033f9b5d867ae040d37a148cf1c1e645ffe96 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:27:57 -0300 Subject: [PATCH 1263/2900] [media] radio-tea5764: embed struct video_device This simplifies the code as it removes a memory allocation check. Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index f6a5471e51aa..4e0bf644b4f9 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -141,7 +141,7 @@ static int use_xtal = RADIO_TEA5764_XTAL; struct tea5764_device { struct v4l2_device v4l2_dev; struct i2c_client *i2c_client; - struct video_device *videodev; + struct video_device vdev; struct tea5764_regs regs; struct mutex mutex; }; @@ -303,7 +303,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { struct tea5764_device *radio = video_drvdata(file); - struct video_device *dev = radio->videodev; + struct video_device *dev = &radio->vdev; strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); @@ -491,7 +491,7 @@ static struct video_device tea5764_radio_template = { .name = "TEA5764 FM-Radio", .fops = &tea5764_fops, .ioctl_ops = &tea5764_ioctl_ops, - .release = video_device_release, + .release = video_device_release_empty, }; /* I2C probe: check if the device exists and register with v4l if it is */ @@ -528,17 +528,12 @@ static int tea5764_i2c_probe(struct i2c_client *client, goto errunreg; } - radio->videodev = video_device_alloc(); - if (!(radio->videodev)) { - ret = -ENOMEM; - goto errunreg; - } - *radio->videodev = tea5764_radio_template; + radio->vdev = tea5764_radio_template; i2c_set_clientdata(client, radio); - video_set_drvdata(radio->videodev, radio); - radio->videodev->lock = &radio->mutex; - radio->videodev->v4l2_dev = v4l2_dev; + video_set_drvdata(&radio->vdev, radio); + radio->vdev.lock = &radio->mutex; + radio->vdev.v4l2_dev = v4l2_dev; /* initialize and power off the chip */ tea5764_i2c_read(radio); @@ -546,16 +541,14 @@ static int tea5764_i2c_probe(struct i2c_client *client, tea5764_mute(radio, 1); tea5764_power_down(radio); - ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + ret = video_register_device(&radio->vdev, VFL_TYPE_RADIO, radio_nr); if (ret < 0) { PWARN("Could not register video device!"); - goto errrel; + goto errunreg; } PINFO("registered."); return 0; -errrel: - video_device_release(radio->videodev); errunreg: v4l2_device_unregister(v4l2_dev); errfr: @@ -570,7 +563,7 @@ static int tea5764_i2c_remove(struct i2c_client *client) PDEBUG("remove"); if (radio) { tea5764_power_down(radio); - video_unregister_device(radio->videodev); + video_unregister_device(&radio->vdev); v4l2_device_unregister(&radio->v4l2_dev); kfree(radio); } -- GitLab From 16b371784ecf1a2d1d7f04760807b3b8138d369f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:34:18 -0300 Subject: [PATCH 1264/2900] [media] radio-tea5764: convert to the control framework Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 79 ++++++++++------------------- 1 file changed, 26 insertions(+), 53 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 4e0bf644b4f9..5c47a970843e 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -40,6 +40,7 @@ #include #include #include +#include #define DRIVER_VERSION "0.0.2" @@ -139,7 +140,8 @@ static int radio_nr = -1; static int use_xtal = RADIO_TEA5764_XTAL; struct tea5764_device { - struct v4l2_device v4l2_dev; + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler ctrl_handler; struct i2c_client *i2c_client; struct video_device vdev; struct tea5764_regs regs; @@ -189,18 +191,6 @@ static int tea5764_i2c_write(struct tea5764_device *radio) return 0; } -/* V4L2 code related */ -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; - static void tea5764_power_up(struct tea5764_device *radio) { struct tea5764_regs *r = &radio->regs; @@ -293,11 +283,6 @@ static void tea5764_mute(struct tea5764_device *radio, int on) tea5764_i2c_write(radio); } -static int tea5764_is_muted(struct tea5764_device *radio) -{ - return radio->regs.tnctrl & TEA5764_TNCTRL_MU; -} - /* V4L2 vidioc */ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) @@ -391,42 +376,14 @@ static int vidioc_g_frequency(struct file *file, void *priv, return 0; } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tea5764_device *radio = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - tea5764_i2c_read(radio); - ctrl->value = tea5764_is_muted(radio) ? 1 : 0; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) +static int tea5764_s_ctrl(struct v4l2_ctrl *ctrl) { - struct tea5764_device *radio = video_drvdata(file); + struct tea5764_device *radio = + container_of(ctrl->handler, struct tea5764_device, ctrl_handler); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - tea5764_mute(radio, ctrl->value); + tea5764_mute(radio, ctrl->val); return 0; } return -EINVAL; @@ -465,6 +422,10 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } +static const struct v4l2_ctrl_ops tea5764_ctrl_ops = { + .s_ctrl = tea5764_s_ctrl, +}; + /* File system interface */ static const struct v4l2_file_operations tea5764_fops = { .owner = THIS_MODULE, @@ -481,9 +442,6 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { .vidioc_s_input = vidioc_s_input, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, }; /* V4L2 interface */ @@ -500,6 +458,7 @@ static int tea5764_i2c_probe(struct i2c_client *client, { struct tea5764_device *radio; struct v4l2_device *v4l2_dev; + struct v4l2_ctrl_handler *hdl; struct tea5764_regs *r; int ret; @@ -514,6 +473,18 @@ static int tea5764_i2c_probe(struct i2c_client *client, v4l2_err(v4l2_dev, "could not register v4l2_device\n"); goto errfr; } + + hdl = &radio->ctrl_handler; + v4l2_ctrl_handler_init(hdl, 1); + v4l2_ctrl_new_std(hdl, &tea5764_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + v4l2_dev->ctrl_handler = hdl; + if (hdl->error) { + ret = hdl->error; + v4l2_err(v4l2_dev, "Could not register controls\n"); + goto errunreg; + } + mutex_init(&radio->mutex); radio->i2c_client = client; ret = tea5764_i2c_read(radio); @@ -550,6 +521,7 @@ static int tea5764_i2c_probe(struct i2c_client *client, PINFO("registered."); return 0; errunreg: + v4l2_ctrl_handler_free(hdl); v4l2_device_unregister(v4l2_dev); errfr: kfree(radio); @@ -564,6 +536,7 @@ static int tea5764_i2c_remove(struct i2c_client *client) if (radio) { tea5764_power_down(radio); video_unregister_device(&radio->vdev); + v4l2_ctrl_handler_free(&radio->ctrl_handler); v4l2_device_unregister(&radio->v4l2_dev); kfree(radio); } -- GitLab From 827c7cf5135e4ca5b0e7de1ed2ae8c1a362b923c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:35:06 -0300 Subject: [PATCH 1265/2900] [media] radio-tea5764: audio and input ioctls do not apply to radio devices Deleted those ioctls from this driver. Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 37 ----------------------------- 1 file changed, 37 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 5c47a970843e..5a609903d4c5 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -389,39 +389,6 @@ static int tea5764_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - if (i != 0) - return -EINVAL; - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - if (a->index != 0) - return -EINVAL; - - return 0; -} - static const struct v4l2_ctrl_ops tea5764_ctrl_ops = { .s_ctrl = tea5764_s_ctrl, }; @@ -436,10 +403,6 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, }; -- GitLab From cc9231f88edec9e95ce579484e1c862b6d810854 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:36:42 -0300 Subject: [PATCH 1266/2900] [media] radio-tea5764: add device_caps support Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 5a609903d4c5..077d9063cd4f 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -294,7 +294,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->card, dev->name, sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev_name(&dev->dev)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -- GitLab From 090fdf6af8d1baafcdaf44796058f62a73a637bf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 08:39:09 -0300 Subject: [PATCH 1267/2900] [media] radio-tea5764: add prio and control event support Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 077d9063cd4f..c22feedb36f5 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -41,6 +41,7 @@ #include #include #include +#include #define DRIVER_VERSION "0.0.2" @@ -397,6 +398,9 @@ static const struct v4l2_ctrl_ops tea5764_ctrl_ops = { /* File system interface */ static const struct v4l2_file_operations tea5764_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -406,6 +410,9 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* V4L2 interface */ @@ -469,6 +476,7 @@ static int tea5764_i2c_probe(struct i2c_client *client, video_set_drvdata(&radio->vdev, radio); radio->vdev.lock = &radio->mutex; radio->vdev.v4l2_dev = v4l2_dev; + set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); /* initialize and power off the chip */ tea5764_i2c_read(radio); -- GitLab From b73008920a69669d253b2f9268f9f51884684718 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:19:04 -0300 Subject: [PATCH 1268/2900] [media] radio-tea5764: some cleanups and clamp frequency when out-of-range Some small cleanups and when setting the frequency it is now clamped to the valid frequency range instead of returning an error. Signed-off-by: Hans Verkuil Cc: Fabio Belavenuto Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-tea5764.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index c22feedb36f5..036e2f54f4db 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -60,8 +60,8 @@ /* Frequency limits in MHz -- these are European values. For Japanese devices, that would be 76000 and 91000. */ -#define FREQ_MIN 87500 -#define FREQ_MAX 108000 +#define FREQ_MIN 87500U +#define FREQ_MAX 108000U #define FREQ_MUL 16 /* TEA5764 registers */ @@ -309,8 +309,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - memset(v, 0, sizeof(*v)); - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; tea5764_i2c_read(radio); v->rangelow = FREQ_MIN * FREQ_MUL; @@ -343,19 +342,23 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct tea5764_device *radio = video_drvdata(file); + unsigned freq = f->frequency; if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; - if (f->frequency == 0) { + if (freq == 0) { /* We special case this as a power down control. */ tea5764_power_down(radio); - } - if (f->frequency < (FREQ_MIN * FREQ_MUL)) - return -EINVAL; - if (f->frequency > (FREQ_MAX * FREQ_MUL)) + /* Yes, that's what is returned in this case. This + whole special case is non-compliant and should really + be replaced with something better, but changing this + might well break code that depends on this behavior. + So we keep it as-is. */ return -EINVAL; + } + clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); tea5764_power_up(radio); - tea5764_tune(radio, (f->frequency * 125) / 2); + tea5764_tune(radio, (freq * 125) / 2); return 0; } @@ -368,7 +371,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, if (f->tuner != 0) return -EINVAL; tea5764_i2c_read(radio); - memset(f, 0, sizeof(*f)); f->type = V4L2_TUNER_RADIO; if (r->tnctrl & TEA5764_TNCTRL_PUPD0) f->frequency = (tea5764_get_freq(radio) * 2) / 125; -- GitLab From d020f83947c68d9d6e8848fe81cc630ef603d177 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:05:16 -0300 Subject: [PATCH 1269/2900] [media] radio-timb: add device_caps support, remove input/audio ioctls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The audio and input ioctls are not applicable for radio devices, remove them. Also set the device_caps field in v4l2_querycap. Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-timb.c | 35 ++------------------------------ 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index bb7b143b65d1..cecf7d7c2136 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -44,7 +44,8 @@ static int timbradio_vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver)); strlcpy(v->card, "Timberdale Radio", sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -62,34 +63,6 @@ static int timbradio_vidioc_s_tuner(struct file *file, void *priv, return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v); } -static int timbradio_vidioc_g_input(struct file *filp, void *priv, - unsigned int *i) -{ - *i = 0; - return 0; -} - -static int timbradio_vidioc_s_input(struct file *filp, void *priv, - unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int timbradio_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int timbradio_vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; -} - static int timbradio_vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { @@ -131,10 +104,6 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { .vidioc_s_tuner = timbradio_vidioc_s_tuner, .vidioc_g_frequency = timbradio_vidioc_g_frequency, .vidioc_s_frequency = timbradio_vidioc_s_frequency, - .vidioc_g_input = timbradio_vidioc_g_input, - .vidioc_s_input = timbradio_vidioc_s_input, - .vidioc_g_audio = timbradio_vidioc_g_audio, - .vidioc_s_audio = timbradio_vidioc_s_audio, .vidioc_queryctrl = timbradio_vidioc_queryctrl, .vidioc_g_ctrl = timbradio_vidioc_g_ctrl, .vidioc_s_ctrl = timbradio_vidioc_s_ctrl -- GitLab From 38be65abfff07fdbbc4d956b997c214ec9005960 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:28:49 -0300 Subject: [PATCH 1270/2900] [media] radio-timb: convert to the control framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-timb.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index cecf7d7c2136..99694ddf5733 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -77,36 +77,12 @@ static int timbradio_vidioc_g_frequency(struct file *file, void *priv, return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f); } -static int timbradio_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc); -} - -static int timbradio_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl); -} - -static int timbradio_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl); -} - static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { .vidioc_querycap = timbradio_vidioc_querycap, .vidioc_g_tuner = timbradio_vidioc_g_tuner, .vidioc_s_tuner = timbradio_vidioc_s_tuner, .vidioc_g_frequency = timbradio_vidioc_g_frequency, .vidioc_s_frequency = timbradio_vidioc_s_frequency, - .vidioc_queryctrl = timbradio_vidioc_queryctrl, - .vidioc_g_ctrl = timbradio_vidioc_g_ctrl, - .vidioc_s_ctrl = timbradio_vidioc_s_ctrl }; static const struct v4l2_file_operations timbradio_fops = { -- GitLab From 5bd8d2abe1edef2559bcfb23e6028df79f81c6e2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:50:50 -0300 Subject: [PATCH 1271/2900] [media] radio-timb: actually load the requested subdevs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason the tuner and dsp subdevs were never actually loaded. Added the relevant code to do that. Also remove bogus calls to video_device_release_empty(). Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-timb.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 99694ddf5733..1931ef778fcd 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -126,6 +126,15 @@ static int timbradio_probe(struct platform_device *pdev) tr->video_dev.v4l2_dev = &tr->v4l2_dev; + tr->sd_tuner = v4l2_i2c_new_subdev_board(&tr->v4l2_dev, + i2c_get_adapter(pdata->i2c_adapter), pdata->tuner, NULL); + tr->sd_dsp = v4l2_i2c_new_subdev_board(&tr->v4l2_dev, + i2c_get_adapter(pdata->i2c_adapter), pdata->dsp, NULL); + if (tr->sd_tuner == NULL || tr->sd_dsp == NULL) + goto err_video_req; + + tr->v4l2_dev.ctrl_handler = tr->sd_dsp->ctrl_handler; + err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1); if (err) { dev_err(&pdev->dev, "Error reg video\n"); @@ -138,7 +147,6 @@ static int timbradio_probe(struct platform_device *pdev) return 0; err_video_req: - video_device_release_empty(&tr->video_dev); v4l2_device_unregister(&tr->v4l2_dev); err: dev_err(&pdev->dev, "Failed to register: %d\n", err); @@ -151,10 +159,7 @@ static int timbradio_remove(struct platform_device *pdev) struct timbradio *tr = platform_get_drvdata(pdev); video_unregister_device(&tr->video_dev); - video_device_release_empty(&tr->video_dev); - v4l2_device_unregister(&tr->v4l2_dev); - return 0; } -- GitLab From 46821b1d206cbafab54fa0ba6dd80904722326e2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:33:21 -0300 Subject: [PATCH 1272/2900] [media] radio-timb: add control events and prio support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-timb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index 1931ef778fcd..0817964d9172 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -83,10 +85,16 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { .vidioc_s_tuner = timbradio_vidioc_s_tuner, .vidioc_g_frequency = timbradio_vidioc_g_frequency, .vidioc_s_frequency = timbradio_vidioc_s_frequency, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static const struct v4l2_file_operations timbradio_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -118,6 +126,7 @@ static int timbradio_probe(struct platform_device *pdev) tr->video_dev.release = video_device_release_empty; tr->video_dev.minor = -1; tr->video_dev.lock = &tr->lock; + set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags); strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); err = v4l2_device_register(NULL, &tr->v4l2_dev); -- GitLab From fa915996fb4e06a90d15fa485742a77cd8c1642b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:19:55 -0300 Subject: [PATCH 1273/2900] [media] tef6862: clamp frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clamp the frequency to the valid frequency range as per the V4L2 specification. Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/tef6862.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index d78afbb08569..06ac69245ca1 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -30,8 +30,8 @@ #define FREQ_MUL 16000 -#define TEF6862_LO_FREQ (875 * FREQ_MUL / 10) -#define TEF6862_HI_FREQ (108 * FREQ_MUL) +#define TEF6862_LO_FREQ (875U * FREQ_MUL / 10) +#define TEF6862_HI_FREQ (108U * FREQ_MUL) /* Write mode sub addresses */ #define WM_SUB_BANDWIDTH 0x0 @@ -104,6 +104,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen { struct tef6862_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned freq = f->frequency; u16 pll; u8 i2cmsg[3]; int err; @@ -111,7 +112,8 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen if (f->tuner != 0) return -EINVAL; - pll = 1964 + ((f->frequency - TEF6862_LO_FREQ) * 20) / FREQ_MUL; + clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ); + pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL; i2cmsg[0] = (MODE_PRESET << MODE_SHIFT) | WM_SUB_PLLM; i2cmsg[1] = (pll >> 8) & 0xff; i2cmsg[2] = pll & 0xff; @@ -120,7 +122,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen if (err != sizeof(i2cmsg)) return err < 0 ? err : -EIO; - state->freq = f->frequency; + state->freq = freq; return 0; } -- GitLab From 8f9acd236d9e6bd805b0dac2d0ca59dcd89edc99 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:10:46 -0300 Subject: [PATCH 1274/2900] [media] timblogiw: fix querycap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't set version (the core does that for you), fill in device_caps and prefix bus_info with "platform:". Signed-off-by: Hans Verkuil Cc: Richard Röjfors Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/timblogiw.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c index 99861c631798..b557caf5b1a4 100644 --- a/drivers/media/platform/timblogiw.c +++ b/drivers/media/platform/timblogiw.c @@ -239,13 +239,12 @@ static int timblogiw_querycap(struct file *file, void *priv, struct video_device *vdev = video_devdata(file); dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - memset(cap, 0, sizeof(*cap)); strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); - strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); - cap->version = TIMBLOGIW_VERSION_CODE; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -- GitLab From 65a110dfb8f6c307712e3296a0f6312c3a211eb6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:43:15 -0300 Subject: [PATCH 1275/2900] [media] radio-sf16fmi: remove audio/input ioctls The audio and input ioctls do not apply to radio devices. Remove them. Signed-off-by: Hans Verkuil Cc: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index adfcc61bdf0b..c1d51ec72831 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -218,32 +218,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, return -EINVAL; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; -} - static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, @@ -253,10 +227,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, .vidioc_queryctrl = vidioc_queryctrl, -- GitLab From f90842d62b16356a8316528c91d0757a17d3e9e3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:44:14 -0300 Subject: [PATCH 1276/2900] [media] radio-sf16fmi: add device_caps support to querycap Signed-off-by: Hans Verkuil Cc: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index c1d51ec72831..80beda7781bc 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -121,7 +121,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); strlcpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card)); strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } -- GitLab From 96bb42b8ab3d4f15b5e98a65c6d8decf36f3f930 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 06:21:03 -0300 Subject: [PATCH 1277/2900] [media] radio-sf16fmi: clamp frequency Signed-off-by: Hans Verkuil Cc: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 80beda7781bc..9cd0338a3d2b 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -55,8 +55,8 @@ static struct fmi fmi_card; static struct pnp_dev *dev; bool pnp_attached; -#define RSF16_MINFREQ (87 * 16000) -#define RSF16_MAXFREQ (108 * 16000) +#define RSF16_MINFREQ (87U * 16000) +#define RSF16_MAXFREQ (108U * 16000) #define FMI_BIT_TUN_CE (1 << 0) #define FMI_BIT_TUN_CLK (1 << 1) @@ -155,15 +155,14 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct fmi *fmi = video_drvdata(file); + unsigned freq = f->frequency; if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; - if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ) - return -EINVAL; + clamp(freq, RSF16_MINFREQ, RSF16_MAXFREQ); /* rounding in steps of 800 to match the freq that will be used */ - lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins); + lm7000_set_freq((freq / 800) * 800, fmi, fmi_set_pins); return 0; } -- GitLab From 268d06bb765da0bdd17344a6877f5898713a7cbb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:51:06 -0300 Subject: [PATCH 1278/2900] [media] radio-sf16fmi: convert to the control framework Signed-off-by: Hans Verkuil Cc: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 56 +++++++++++++---------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 9cd0338a3d2b..b058f36669ee 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -27,6 +27,7 @@ #include /* outb, outb_p */ #include #include +#include #include "lm7000.h" MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); @@ -44,6 +45,7 @@ module_param(radio_nr, int, 0); struct fmi { struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler hdl; struct video_device vdev; int io; bool mute; @@ -178,46 +180,26 @@ static int vidioc_g_frequency(struct file *file, void *priv, return 0; } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) +static int fmi_s_ctrl(struct v4l2_ctrl *ctrl) { - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct fmi *fmi = video_drvdata(file); + struct fmi *fmi = container_of(ctrl->handler, struct fmi, hdl); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = fmi->mute; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct fmi *fmi = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) + if (ctrl->val) fmi_mute(fmi); else fmi_unmute(fmi); - fmi->mute = ctrl->value; + fmi->mute = ctrl->val; return 0; } return -EINVAL; } +static const struct v4l2_ctrl_ops fmi_ctrl_ops = { + .s_ctrl = fmi_s_ctrl, +}; + static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, .unlocked_ioctl = video_ioctl2, @@ -229,9 +211,6 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, }; /* ladis: this is my card. does any other types exist? */ @@ -281,6 +260,7 @@ static int __init fmi_init(void) { struct fmi *fmi = &fmi_card; struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; + struct v4l2_ctrl_handler *hdl = &fmi->hdl; int res, i; int probe_ports[] = { 0, 0x284, 0x384 }; @@ -333,6 +313,18 @@ static int __init fmi_init(void) return res; } + v4l2_ctrl_handler_init(hdl, 1); + v4l2_ctrl_new_std(hdl, &fmi_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + v4l2_dev->ctrl_handler = hdl; + if (hdl->error) { + res = hdl->error; + v4l2_err(v4l2_dev, "Could not register controls\n"); + v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(v4l2_dev); + return res; + } + strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); fmi->vdev.v4l2_dev = v4l2_dev; fmi->vdev.fops = &fmi_fops; @@ -346,6 +338,7 @@ static int __init fmi_init(void) fmi_mute(fmi); if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_ctrl_handler_free(hdl); v4l2_device_unregister(v4l2_dev); release_region(fmi->io, 2); if (pnp_attached) @@ -361,6 +354,7 @@ static void __exit fmi_exit(void) { struct fmi *fmi = &fmi_card; + v4l2_ctrl_handler_free(&fmi->hdl); video_unregister_device(&fmi->vdev); v4l2_device_unregister(&fmi->v4l2_dev); release_region(fmi->io, 2); -- GitLab From 0dc5d82dcdfcec4d195b70fe8c0a13e5e6dd8d5a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 3 Feb 2013 09:51:59 -0300 Subject: [PATCH 1279/2900] [media] radio-sf16fmi: add control event and prio support Signed-off-by: Hans Verkuil Cc: Ondrej Zary Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index b058f36669ee..9e712c8310f2 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "lm7000.h" MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); @@ -202,6 +203,9 @@ static const struct v4l2_ctrl_ops fmi_ctrl_ops = { static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -211,6 +215,9 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* ladis: this is my card. does any other types exist? */ @@ -330,6 +337,7 @@ static int __init fmi_init(void) fmi->vdev.fops = &fmi_fops; fmi->vdev.ioctl_ops = &fmi_ioctl_ops; fmi->vdev.release = video_device_release_empty; + set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags); video_set_drvdata(&fmi->vdev, fmi); mutex_init(&fmi->lock); -- GitLab From 8c84ac51df883eee994913a33be888553e821005 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:38 -0300 Subject: [PATCH 1280/2900] [media] mcam-core: replace current_norm by g_std The current_norm field is deprecated, replace this by properly implementing g_std. Signed-off-by: Hans Verkuil Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/marvell-ccic/mcam-core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index c69cfc4413fc..0821ed08c122 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -1344,6 +1344,12 @@ static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a) return 0; } +static int mcam_vidioc_g_std(struct file *filp, void *priv, v4l2_std_id *a) +{ + *a = V4L2_STD_NTSC_M; + return 0; +} + /* * G/S_PARM. Most of this is done by the sensor, but we are * the level which controls the number of read buffers. @@ -1433,6 +1439,7 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = { .vidioc_g_input = mcam_vidioc_g_input, .vidioc_s_input = mcam_vidioc_s_input, .vidioc_s_std = mcam_vidioc_s_std, + .vidioc_g_std = mcam_vidioc_g_std, .vidioc_reqbufs = mcam_vidioc_reqbufs, .vidioc_querybuf = mcam_vidioc_querybuf, .vidioc_qbuf = mcam_vidioc_qbuf, @@ -1558,7 +1565,6 @@ static const struct v4l2_file_operations mcam_v4l_fops = { static struct video_device mcam_v4l_template = { .name = "mcam", .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ .fops = &mcam_v4l_fops, .ioctl_ops = &mcam_v4l_ioctl_ops, -- GitLab From d31e545b00057516eac84ff0e2675bf802c2a522 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:39 -0300 Subject: [PATCH 1281/2900] [media] via-camera: replace current_norm by g_std The current_norm field is deprecated. Replace it by properly implementing g_std. Signed-off-by: Hans Verkuil Cc: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/via-camera.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index e3438277b80b..b4f9d03636e3 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -837,6 +837,12 @@ static int viacam_s_std(struct file *filp, void *priv, v4l2_std_id std) return 0; } +static int viacam_g_std(struct file *filp, void *priv, v4l2_std_id *std) +{ + *std = V4L2_STD_NTSC_M; + return 0; +} + /* * Video format stuff. Here is our default format until * user space messes with things. @@ -1163,6 +1169,7 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { .vidioc_g_input = viacam_g_input, .vidioc_s_input = viacam_s_input, .vidioc_s_std = viacam_s_std, + .vidioc_g_std = viacam_g_std, .vidioc_enum_fmt_vid_cap = viacam_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap = viacam_try_fmt_vid_cap, .vidioc_g_fmt_vid_cap = viacam_g_fmt_vid_cap, @@ -1250,7 +1257,6 @@ static struct video_device viacam_v4l_template = { .name = "via-camera", .minor = -1, .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, .fops = &viacam_fops, .ioctl_ops = &viacam_ioctl_ops, .release = video_device_release_empty, /* Check this */ -- GitLab From 5d40810812af73c812613638140c75d351422d9d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:40 -0300 Subject: [PATCH 1282/2900] [media] sh_vou: remove current_norm The current_norm field is deprecated and is replaced by g_std. This driver already implements g_std, so just remove current_norm. Signed-off-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_vou.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index fa8ae7241521..7a9c5e9329f2 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -1282,7 +1282,6 @@ static const struct video_device sh_vou_video_template = { .fops = &sh_vou_fops, .ioctl_ops = &sh_vou_ioctl_ops, .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ - .current_norm = V4L2_STD_NTSC_M, .vfl_dir = VFL_DIR_TX, }; @@ -1321,7 +1320,7 @@ static int sh_vou_probe(struct platform_device *pdev) pix = &vou_dev->pix; /* Fill in defaults */ - vou_dev->std = sh_vou_video_template.current_norm; + vou_dev->std = V4L2_STD_NTSC_M; rect->left = 0; rect->top = 0; rect->width = VOU_MAX_IMAGE_WIDTH; -- GitLab From 2766a7a99950b5a0033b449dacc04070654b0357 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:41 -0300 Subject: [PATCH 1283/2900] [media] soc_camera: remove use of current_norm The current_norm field is deprecated, so don't set it. Since it is set to V4L2_STD_UNKNOWN which is 0 it didn't do anything anyway. Also remove a few other unnecessary uses of V4L2_STD_UNKNOWN. Signed-off-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 68efade15a7c..0252fbb48154 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -235,7 +235,6 @@ static int soc_camera_enum_input(struct file *file, void *priv, /* default is camera */ inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_UNKNOWN; strcpy(inp->name, "Camera"); return 0; @@ -1479,11 +1478,9 @@ static int video_dev_create(struct soc_camera_device *icd) strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); vdev->parent = icd->pdev; - vdev->current_norm = V4L2_STD_UNKNOWN; vdev->fops = &soc_camera_fops; vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; - vdev->tvnorms = V4L2_STD_UNKNOWN; vdev->ctrl_handler = &icd->ctrl_handler; vdev->lock = &ici->host_lock; -- GitLab From 28221f88efcf70814491a9695625d8257282d994 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:43 -0300 Subject: [PATCH 1284/2900] [media] fsl-viu: remove current_norm The use of current_norm is deprecated, so remove it. This driver actually already implements g_std, which overrides current_norm, but the 'std' field was never initialized correctly. This has been fixed as well. Signed-off-by: Hans Verkuil Cc: Anatolij Gustschin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/fsl-viu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 3a6a0dcdc3e4..221ec428a01e 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1475,7 +1475,6 @@ static struct video_device viu_template = { .release = video_device_release, .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, - .current_norm = V4L2_STD_NTSC_M, }; static int viu_of_probe(struct platform_device *op) @@ -1546,6 +1545,7 @@ static int viu_of_probe(struct platform_device *op) viu_dev->vidq.timeout.function = viu_vid_timeout; viu_dev->vidq.timeout.data = (unsigned long)viu_dev; init_timer(&viu_dev->vidq.timeout); + viu_dev->std = V4L2_STD_NTSC_M; viu_dev->first = 1; /* Allocate memory for video device */ -- GitLab From 804be2d4933a44ce76bce3d12b09c5db980523a4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:44 -0300 Subject: [PATCH 1285/2900] [media] tm6000: remove deprecated current_norm Replace current_norm by g_std. Also initialize the standard to the more common NTSC-M format (which is also what current_norm used). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/tm6000/tm6000-cards.c | 2 +- drivers/media/usb/tm6000/tm6000-video.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c index 307d8c5fb7cd..1ccaaddaa307 100644 --- a/drivers/media/usb/tm6000/tm6000-cards.c +++ b/drivers/media/usb/tm6000/tm6000-cards.c @@ -1114,7 +1114,7 @@ static int tm6000_init_dev(struct tm6000_core *dev) /* Default values for STD and resolutions */ dev->width = 720; dev->height = 480; - dev->norm = V4L2_STD_PAL_M; + dev->norm = V4L2_STD_NTSC_M; /* Configure tuner */ tm6000_config_tuner(dev); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index a78de1d1bc9e..cc1aa14996ff 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -1076,6 +1076,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct tm6000_fh *fh = priv; + struct tm6000_core *dev = fh->dev; + + *norm = dev->norm; + return 0; +} + static const char *iname[] = { [TM6000_INPUT_TV] = "Television", [TM6000_INPUT_COMPOSITE1] = "Composite 1", @@ -1134,7 +1143,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) dev->input = i; - rc = vidioc_s_std(file, priv, dev->vfd->current_norm); + rc = vidioc_s_std(file, priv, dev->norm); return rc; } @@ -1547,6 +1556,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1570,7 +1580,6 @@ static struct video_device tm6000_template = { .ioctl_ops = &video_ioctl_ops, .release = video_device_release, .tvnorms = TM6000_STD, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_file_operations radio_fops = { -- GitLab From 8d2d41e92d99e25f7d42fc83fc39096d89caa35e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:45 -0300 Subject: [PATCH 1286/2900] [media] saa7164: replace current_norm by g_std current_norm is deprecated. Replace it by g_std. Signed-off-by: Hans Verkuil Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7164/saa7164-encoder.c | 13 ++++++++++++- drivers/media/pci/saa7164/saa7164-vbi.c | 13 ++++++++++++- drivers/media/pci/saa7164/saa7164.h | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index e4f53a55eab1..7b7ed97b8503 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -228,6 +228,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return -EINVAL; port->encodernorm = saa7164_tvnorms[i]; + port->std = id; /* Update the audio decoder while is not running in * auto detect mode. @@ -239,6 +240,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_port *port = fh->port; + + *id = port->std; + return 0; +} + static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1290,6 +1300,7 @@ static const struct v4l2_file_operations mpeg_fops = { static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1316,7 +1327,6 @@ static struct video_device saa7164_mpeg_template = { .ioctl_ops = &mpeg_ioctl_ops, .minor = -1, .tvnorms = SAA7164_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static struct video_device *saa7164_encoder_alloc( @@ -1383,6 +1393,7 @@ int saa7164_encoder_register(struct saa7164_port *port) port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; port->encoder_params.refdist = 1; port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE; + port->std = V4L2_STD_NTSC_M; if (port->encodernorm.id & V4L2_STD_525_60) port->height = 480; diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 5a1a69b3dd15..552c01ad9f63 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -200,6 +200,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return -EINVAL; port->encodernorm = saa7164_tvnorms[i]; + port->std = id; /* Update the audio decoder while is not running in * auto detect mode. @@ -211,6 +212,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_port *port = fh->port; + + *id = port->std; + return 0; +} + static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1236,6 +1246,7 @@ static const struct v4l2_file_operations vbi_fops = { static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1265,7 +1276,6 @@ static struct video_device saa7164_vbi_template = { .ioctl_ops = &vbi_ioctl_ops, .minor = -1, .tvnorms = SAA7164_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static struct video_device *saa7164_vbi_alloc( @@ -1324,6 +1334,7 @@ int saa7164_vbi_register(struct saa7164_port *port) goto failed; } + port->std = V4L2_STD_NTSC_M; video_set_drvdata(port->v4l_device, port); result = video_register_device(port->v4l_device, VFL_TYPE_VBI, -1); diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 8d9c7e692242..2df47ea28289 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -375,6 +375,7 @@ struct saa7164_port { /* Encoder */ /* Defaults established in saa7164-encoder.c */ struct saa7164_tvnorm encodernorm; + v4l2_std_id std; u32 height; u32 width; u32 freq; -- GitLab From 9c1f5df81300b89c5c5c76b101502dad3977fdcb Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:46 -0300 Subject: [PATCH 1287/2900] [media] cx23885: remove use of deprecated current_norm The use of current_norm can be dropped. The g_std ioctl was already implemented, so current_norm didn't do anything useful anyway. Signed-off-by: Hans Verkuil Cc: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-417.c | 5 +---- drivers/media/pci/cx23885/cx23885-video.c | 7 ++----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 68568d35a692..f4f9ef0d98e2 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1217,8 +1217,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - call_all(dev, core, g_std, id); - + *id = dev->tvnorm; return 0; } @@ -1661,7 +1660,6 @@ static struct v4l2_file_operations mpeg_fops = { }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { - .vidioc_querystd = vidioc_g_std, .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, @@ -1702,7 +1700,6 @@ static struct video_device cx23885_mpeg_template = { .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, .tvnorms = CX23885_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; void cx23885_417_unregister(struct cx23885_dev *dev) diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index ce057398c632..e33d1a7dfdd0 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -1254,8 +1254,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; dprintk(1, "%s()\n", __func__); - call_all(dev, core, g_std, id); - + *id = dev->tvnorm; return 0; } @@ -1743,7 +1742,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, - .vidioc_querystd = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1773,7 +1771,6 @@ static struct video_device cx23885_video_template = { .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX23885_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_file_operations radio_fops = { @@ -1822,7 +1819,7 @@ int cx23885_video_register(struct cx23885_dev *dev) cx23885_vbi_template = cx23885_video_template; strcpy(cx23885_vbi_template.name, "cx23885-vbi"); - dev->tvnorm = cx23885_video_template.current_norm; + dev->tvnorm = V4L2_STD_NTSC_M; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); -- GitLab From 3b8436d9db43a810dd44393733b34fda6e0f0b9d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:47 -0300 Subject: [PATCH 1288/2900] [media] usbvision: replace current_norm by g_std current_norm use is deprecated because it is per-devicenode and if you have more device nodes all dependent on the same video source, then this no longer works. Just implement g_std instead. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index d34c2afe2c24..7ad872a3e31a 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -608,6 +608,14 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct usb_usbvision *usbvision = video_drvdata(file); + + *id = usbvision->tvnorm_id; + return 0; +} + static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { @@ -1248,6 +1256,7 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1274,7 +1283,6 @@ static struct video_device usbvision_video_template = { .name = "usbvision-video", .release = video_device_release, .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL }; @@ -1307,9 +1315,6 @@ static struct video_device usbvision_radio_template = { .name = "usbvision-radio", .release = video_device_release, .ioctl_ops = &usbvision_radio_ioctl_ops, - - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL }; -- GitLab From 776572d95f0a80a3ae732569fd2ee6eadc9c8486 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:48 -0300 Subject: [PATCH 1289/2900] [media] saa7134: drop deprecated current_norm Since this driver properly implements g_std, the current_norm field is actually unused anyway. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-empress.c | 1 - drivers/media/pci/saa7134/saa7134-video.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 05ab2cb7ef3c..973fa65eb3d3 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -471,7 +471,6 @@ static struct video_device saa7134_empress_template = { .ioctl_ops = &ts_ioctl_ops, .tvnorms = SAA7134_NORMS, - .current_norm = V4L2_STD_PAL, }; static void empress_signal_update(struct work_struct *work) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index db4cc1c54aa6..b78d515068a7 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2439,7 +2439,6 @@ struct video_device saa7134_video_template = { .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .tvnorms = SAA7134_NORMS, - .current_norm = V4L2_STD_PAL, }; struct video_device saa7134_radio_template = { -- GitLab From 8f73d3bbf8b1114b1ae5ac8950104b3d5d01c7d2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:49 -0300 Subject: [PATCH 1290/2900] [media] dt3155v4l: remove deprecated current_norm Since this driver provides a g_std op the current_norm field isn't used anyway, so just drop it. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/dt3155v4l/dt3155v4l.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c index c32e0acde4f4..90d6ac469355 100644 --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c @@ -829,7 +829,6 @@ static struct video_device dt3155_vdev = { .minor = -1, .release = video_device_release, .tvnorms = DT3155_CURRENT_NORM, - .current_norm = DT3155_CURRENT_NORM, }; /* same as in drivers/base/dma-coherent.c */ -- GitLab From ca37157506ef53dcf41132aaedab70659509ccee Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 05:36:50 -0300 Subject: [PATCH 1291/2900] [media] v4l2: remove deprecated current_norm support completely The use of current_norm to keep track of the current standard has been deprecated for quite some time. Now that all drivers that were using it have been converted to use g_std we can drop it from the core. It was a bad idea to introduce this at the time: since it is a per-device node field it didn't work for drivers that create multiple nodes, all sharing the same tuner (e.g. video and vbi nodes, or a raw video node and a compressed video node). In addition it was very surprising behavior that g_std was implemented in the core. Often drivers implemented both g_std and current_norm, because they didn't understand how it should be used. Since the benefits were very limited (if they were there at all), it is better to just drop it and require that drivers just implement g_std. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 5 ++-- drivers/media/v4l2-core/v4l2-ioctl.c | 34 ++++------------------------ include/media/v4l2-dev.h | 1 - 3 files changed, 6 insertions(+), 34 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 5923c5dfacd5..2f3fac5345db 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -675,9 +675,8 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf); if (ops->vidioc_s_std) set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); - if (ops->vidioc_g_std || vdev->current_norm) - set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); + SET_VALID_IOCTL(ops, VIDIOC_G_STD, vidioc_g_std); if (is_rx) { SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); @@ -705,7 +704,7 @@ static void determine_valid_ioctls(struct video_device *vdev) if (ops->vidioc_cropcap || ops->vidioc_g_selection) set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && - (ops->vidioc_g_std || vdev->current_norm))) + ops->vidioc_g_std)) set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 60b8c259da96..67745438e6ff 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1364,40 +1364,18 @@ static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, return 0; } -static int v4l_g_std(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) -{ - struct video_device *vfd = video_devdata(file); - v4l2_std_id *id = arg; - - /* Calls the specific handler */ - if (ops->vidioc_g_std) - return ops->vidioc_g_std(file, fh, arg); - if (vfd->current_norm) { - *id = vfd->current_norm; - return 0; - } - return -ENOTTY; -} - static int v4l_s_std(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct video_device *vfd = video_devdata(file); v4l2_std_id id = *(v4l2_std_id *)arg, norm; - int ret; norm = id & vfd->tvnorms; if (vfd->tvnorms && !norm) /* Check if std is supported */ return -EINVAL; /* Calls the specific handler */ - ret = ops->vidioc_s_std(file, fh, norm); - - /* Updates standard information */ - if (ret >= 0) - vfd->current_norm = norm; - return ret; + return ops->vidioc_s_std(file, fh, norm); } static int v4l_querystd(const struct v4l2_ioctl_ops *ops, @@ -1500,7 +1478,6 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { - struct video_device *vfd = video_devdata(file); struct v4l2_streamparm *p = arg; v4l2_std_id std; int ret = check_fmt(file, p->type); @@ -1509,16 +1486,13 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, return ret; if (ops->vidioc_g_parm) return ops->vidioc_g_parm(file, fh, p); - std = vfd->current_norm; if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; p->parm.capture.readbuffers = 2; - if (is_valid_ioctl(vfd, VIDIOC_G_STD) && ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, &std); + ret = ops->vidioc_g_std(file, fh, &std); if (ret == 0) - v4l2_video_std_frame_period(std, - &p->parm.capture.timeperframe); + v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); return ret; } @@ -2055,7 +2029,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), + IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0), IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 95d1c91770f4..b2c3776a1cff 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -129,7 +129,6 @@ struct video_device /* Video standard vars */ v4l2_std_id tvnorms; /* Supported tv norms */ - v4l2_std_id current_norm; /* Current tvnorm */ /* callbacks */ void (*release)(struct video_device *vdev); -- GitLab From 7dd8fbbe50c01ead78483bc42f744d115afec96b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:54 -0300 Subject: [PATCH 1292/2900] [media] adv7183: fix querystd If no signal is detected, return V4L2_STD_UNKNOWN. Otherwise AND the standard with the detected standards. Note that the v4l2 core initializes the std with tvnorms before calling the querystd ioctl. Signed-off-by: Hans Verkuil Cc: Scott Jiang Acked-by: Scott Jiang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7183.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 980815d37bb1..6f738d8e3a8f 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -374,28 +374,28 @@ static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) reg = adv7183_read(sd, ADV7183_STATUS_1); switch ((reg >> 0x4) & 0x7) { case 0: - *std = V4L2_STD_NTSC; + *std &= V4L2_STD_NTSC; break; case 1: - *std = V4L2_STD_NTSC_443; + *std &= V4L2_STD_NTSC_443; break; case 2: - *std = V4L2_STD_PAL_M; + *std &= V4L2_STD_PAL_M; break; case 3: - *std = V4L2_STD_PAL_60; + *std &= V4L2_STD_PAL_60; break; case 4: - *std = V4L2_STD_PAL; + *std &= V4L2_STD_PAL; break; case 5: - *std = V4L2_STD_SECAM; + *std &= V4L2_STD_SECAM; break; case 6: - *std = V4L2_STD_PAL_Nc; + *std &= V4L2_STD_PAL_Nc; break; case 7: - *std = V4L2_STD_SECAM; + *std &= V4L2_STD_SECAM; break; default: *std = V4L2_STD_UNKNOWN; -- GitLab From ddc7f72a3d4049653114647069f8044de5f2499d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:55 -0300 Subject: [PATCH 1293/2900] [media] bt819: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/bt819.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index ae1eac01bbc7..369cf6ff88f7 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -215,15 +215,17 @@ static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) struct bt819 *decoder = to_bt819(sd); int status = bt819_read(decoder, 0x00); int res = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; if ((status & 0x80)) res = 0; + else + std = V4L2_STD_UNKNOWN; if ((status & 0x10)) - std = V4L2_STD_PAL; + std &= V4L2_STD_PAL; else - std = V4L2_STD_NTSC; + std &= V4L2_STD_NTSC; if (pstd) *pstd = std; if (pstatus) -- GitLab From e83c30c723caf5def0eb8eca5b106b39a3dab71c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:56 -0300 Subject: [PATCH 1294/2900] [media] ks0127: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ks0127.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index b5223e850a26..c3e94ae82c03 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -609,17 +609,24 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd { int stat = V4L2_IN_ST_NO_SIGNAL; u8 status; - v4l2_std_id std = V4L2_STD_ALL; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; status = ks0127_read(sd, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ stat = 0; - if (!(status & 0x01)) /* CLOCK set */ + if (!(status & 0x01)) { /* CLOCK set */ stat |= V4L2_IN_ST_NO_COLOR; - if ((status & 0x08)) /* PALDET set */ - std = V4L2_STD_PAL; + std = V4L2_STD_UNKNOWN; + } else { + if ((status & 0x08)) /* PALDET set */ + std &= V4L2_STD_PAL; + else + std &= V4L2_STD_NTSC; + } + if ((status & 0x10)) /* PALDET set */ + std &= V4L2_STD_525_60; else - std = V4L2_STD_NTSC; + std &= V4L2_STD_625_50; if (pstd) *pstd = std; if (pstatus) -- GitLab From 416e87a41d8430b8dc0f1e94f925b6deb71debbc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:57 -0300 Subject: [PATCH 1295/2900] [media] saa7110: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7110.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index 532105de96f0..ac43e929a1d6 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -202,7 +202,7 @@ static v4l2_std_id determine_norm(struct v4l2_subdev *sd) status = saa7110_read(sd); if (status & 0x40) { v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); - return decoder->norm; /* no change*/ + return V4L2_STD_UNKNOWN; } if ((status & 3) == 0) { saa7110_write(sd, 0x06, 0x83); @@ -264,7 +264,7 @@ static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { - *(v4l2_std_id *)std = determine_norm(sd); + *std &= determine_norm(sd); return 0; } -- GitLab From af1f7284da471e68508457da92deab2517d48ff4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:58 -0300 Subject: [PATCH 1296/2900] [media] saa7115: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 90c43f3fb0f1..7fd766ec64c8 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1428,6 +1428,7 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) *std &= V4L2_STD_SECAM; break; default: + *std = V4L2_STD_UNKNOWN; /* Can't detect anything */ break; } @@ -1436,8 +1437,10 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f); /* horizontal/vertical not locked */ - if (reg1f & 0x40) + if (reg1f & 0x40) { + *std = V4L2_STD_UNKNOWN; goto ret; + } if (reg1f & 0x20) *std &= V4L2_STD_525_60; -- GitLab From ec276a5a26200b342c11739b805b637961f660a7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:18:59 -0300 Subject: [PATCH 1297/2900] [media] saa7191: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7191.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c index 08dcaecbeb98..606a4baf944d 100644 --- a/drivers/media/i2c/saa7191.c +++ b/drivers/media/i2c/saa7191.c @@ -271,7 +271,7 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) dprintk("SAA7191 extended signal auto-detection...\n"); - *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; + *norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); @@ -302,7 +302,7 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) if (status & SAA7191_STATUS_FIDT) { /* 60Hz signal -> NTSC */ dprintk("60Hz signal: NTSC\n"); - *norm = V4L2_STD_NTSC; + *norm &= V4L2_STD_NTSC; return 0; } @@ -324,12 +324,13 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); saa7191_s_std(sd, old_norm); - return -EAGAIN; + *norm = V4L2_STD_UNKNOWN; + return 0; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); - *norm = V4L2_STD_PAL; + *norm &= V4L2_STD_PAL; return saa7191_s_std(sd, old_norm); } @@ -349,18 +350,19 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - err = -EAGAIN; + *norm = V4L2_STD_UNKNOWN; goto out; } if (status & SAA7191_STATUS_CODE) { /* Color detected -> SECAM */ dprintk("SECAM\n"); - *norm = V4L2_STD_SECAM; + *norm &= V4L2_STD_SECAM; return saa7191_s_std(sd, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); + *norm = V4L2_STD_UNKNOWN; out: return saa7191_s_std(sd, old_norm); -- GitLab From 55852cbbae45e3bbb5ef7a5f1213ed34ff6209f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:00 -0300 Subject: [PATCH 1298/2900] [media] tvp514x: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index b5c17eb89b4e..b8061b5e3eac 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -542,8 +542,6 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) if (std_id == NULL) return -EINVAL; - *std_id = V4L2_STD_UNKNOWN; - /* To query the standard the TVP514x must power on the ADCs. */ if (!decoder->streaming) { tvp514x_s_stream(sd, 1); @@ -552,8 +550,10 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) /* query the current standard */ current_std = tvp514x_query_current_std(sd); - if (current_std == STD_INVALID) + if (current_std == STD_INVALID) { + *std_id = V4L2_STD_UNKNOWN; return 0; + } input_sel = decoder->input; @@ -594,10 +594,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) } /* check whether signal is locked */ sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); - if (lock_mask != (sync_lock_status & lock_mask)) + if (lock_mask != (sync_lock_status & lock_mask)) { + *std_id = V4L2_STD_UNKNOWN; return 0; /* No input detected */ + } - *std_id = decoder->std_list[current_std].standard.id; + *std_id &= decoder->std_list[current_std].standard.id; v4l2_dbg(1, debug, sd, "Current STD: %s\n", decoder->std_list[current_std].standard.name); -- GitLab From 32cb3b09f4716583921d3244f67893441bfb9af2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:01 -0300 Subject: [PATCH 1299/2900] [media] vpx3220: fix querystd Return V4L2_STD_UNKNOWN if no signal is detected. Otherwise AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/vpx3220.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 4c57d8a67c22..ece90df6a043 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -295,7 +295,7 @@ static int vpx3220_init(struct v4l2_subdev *sd, u32 val) static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) { int res = V4L2_IN_ST_NO_SIGNAL, status; - v4l2_std_id std = 0; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; status = vpx3220_fp_read(sd, 0x0f3); @@ -312,19 +312,21 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst case 0x10: case 0x14: case 0x18: - std = V4L2_STD_PAL; + std &= V4L2_STD_PAL; break; case 0x08: - std = V4L2_STD_SECAM; + std &= V4L2_STD_SECAM; break; case 0x04: case 0x0c: case 0x1c: - std = V4L2_STD_NTSC; + std &= V4L2_STD_NTSC; break; } + } else { + std = V4L2_STD_UNKNOWN; } if (pstd) *pstd = std; -- GitLab From 0bde6c3e4c4d594eb66200e37d9aec6ed45a8543 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:02 -0300 Subject: [PATCH 1300/2900] [media] bttv: fix querystd AND the standard mask with the detected standards. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index bfcfa3e8543e..c6532de0eac7 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1760,9 +1760,9 @@ static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) struct bttv *btv = fh->btv; if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) - *id = V4L2_STD_625_50; + *id &= V4L2_STD_625_50; else - *id = V4L2_STD_525_60; + *id &= V4L2_STD_525_60; return 0; } -- GitLab From 0b1ffb535720c1c8a758dfaef926413e11a4bbce Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:03 -0300 Subject: [PATCH 1301/2900] [media] zoran: remove bogus autodetect mode in set_norm Currently, if the norm set is V4L2_STD_ALL, then autodetect the current standard and use that. This is non-standard behavior, and in fact it hasn't worked for a very long time: before s_std is called in this driver, the v4l2 core will mask it with the tvnorms field. So even if the application passes V4L2_STD_ALL, the zoran driver will always see a subset of that. Since nobody ever complained about this we just remove this non-standard functionality. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/zoran/zoran_driver.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index 1168a84a737d..4ec2708c0dd0 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -1456,29 +1456,6 @@ zoran_set_norm (struct zoran *zr, return -EINVAL; } - if (norm == V4L2_STD_ALL) { - unsigned int status = 0; - v4l2_std_id std = 0; - - decoder_call(zr, video, querystd, &std); - decoder_call(zr, core, s_std, std); - - /* let changes come into effect */ - ssleep(2); - - decoder_call(zr, video, g_input_status, &status); - if (status & V4L2_IN_ST_NO_SIGNAL) { - dprintk(1, - KERN_ERR - "%s: %s - no norm detected\n", - ZR_DEVNAME(zr), __func__); - /* reset norm */ - decoder_call(zr, core, s_std, zr->norm); - return -EIO; - } - - norm = std; - } if (norm & V4L2_STD_SECAM) zr->timing = zr->card.tvn[2]; else if (norm & V4L2_STD_NTSC) -- GitLab From 1a2c6866e35058c8808af37659e0f344f7f79381 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:04 -0300 Subject: [PATCH 1302/2900] [media] v4l2-ioctl: clarify querystd comment Improve the querystd comment. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 67745438e6ff..19e298863e0e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1385,10 +1385,10 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops, v4l2_std_id *p = arg; /* - * If nothing detected, it should return all supported - * standard. - * Drivers just need to mask the std argument, in order - * to remove the standards that don't apply from the mask. + * If no signal is detected, then the driver should return + * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with + * any standards that do not apply removed. + * * This means that tuners, audio and video decoders can join * their efforts to improve the standards detection. */ -- GitLab From f41c4332cfeae59e78aeda6c4eb9d0f4d42adbf2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:05 -0300 Subject: [PATCH 1303/2900] [media] DocBook/media/v4l: clarify the QUERYSTD documentation Explicitly mention that this ioctl should return V4L2_STD_UNKNOWN if not signal was detected. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/vidioc-querystd.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-querystd.xml b/Documentation/DocBook/media/v4l/vidioc-querystd.xml index fe80a183d957..222348542182 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querystd.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querystd.xml @@ -54,7 +54,8 @@ standard automatically. To do so, applications call VIDIOC_QUERYSTD with a pointer to a &v4l2-std-id; type. The driver stores here a set of candidates, this can be a single flag or a set of supported standards if for example the hardware can only -distinguish between 50 and 60 Hz systems. When detection is not +distinguish between 50 and 60 Hz systems. If no signal was detected, +then the driver will return V4L2_STD_UNKNOWN. When detection is not possible or fails, the set must contain all standards supported by the current video input or output. -- GitLab From 26811ae03539c24c618ce989abecb6e62a908e79 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 10:19:06 -0300 Subject: [PATCH 1304/2900] [media] tvp5150: fix s_std support - do exact matching for special formats like PAL-M - drop autodetect support: it's non-standard, and it is bogus as well since there is no way to get back the detected standard since neither g_std nor querystd are implemented. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index bef528233f7e..89c0b13463b7 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -726,13 +726,11 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) /* First tests should be against specific std */ - if (std == V4L2_STD_ALL) { - fmt = VIDEO_STD_AUTO_SWITCH_BIT; /* Autodetect mode */ - } else if (std & V4L2_STD_NTSC_443) { + if (std == V4L2_STD_NTSC_443) { fmt = VIDEO_STD_NTSC_4_43_BIT; - } else if (std & V4L2_STD_PAL_M) { + } else if (std == V4L2_STD_PAL_M) { fmt = VIDEO_STD_PAL_M_BIT; - } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + } else if (std == V4L2_STD_PAL_N || std == V4L2_STD_PAL_Nc) { fmt = VIDEO_STD_PAL_COMBINATION_N_BIT; } else { /* Then, test against generic ones */ -- GitLab From 147351905b6b495f117fd8b7ff927bb61f1234b3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Jun 2013 13:26:17 -0300 Subject: [PATCH 1305/2900] [media] media: i2c: ths8200: driver for TI video encoder The full datasheets are available from TI website:- http://www.ti.com/product/ths8200 Note: This patch adds support only for progressive format as of now. Signed-off-by: Hans Verkuil Signed-off-by: Mats Randgaard Signed-off-by: Martin Bugge Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 9 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ths8200.c | 560 +++++++++++++++++++++++++++++++ drivers/media/i2c/ths8200_regs.h | 161 +++++++++ 4 files changed, 731 insertions(+) create mode 100644 drivers/media/i2c/ths8200.c create mode 100644 drivers/media/i2c/ths8200_regs.h diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 9c04ddb2101e..b2cd8ca51af7 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -434,6 +434,15 @@ config VIDEO_AK881X help Video output driver for AKM AK8813 and AK8814 TV encoders +config VIDEO_THS8200 + tristate "Texas Instruments THS8200 video encoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments THS8200 video encoder. + + To compile this driver as a module, choose M here: the + module will be called ths8200. + comment "Camera sensor devices" config VIDEO_APTINA_PLL diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index b40ea089861a..dc20653bb5ad 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_THS7303) += ths7303.o +obj-$(CONFIG_VIDEO_THS8200) += ths8200.o obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c new file mode 100644 index 000000000000..939682967579 --- /dev/null +++ b/drivers/media/i2c/ths8200.c @@ -0,0 +1,560 @@ +/* + * ths8200 - Texas Instruments THS8200 video encoder driver + * + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include + +#include "ths8200_regs.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-2)"); + +MODULE_DESCRIPTION("Texas Instruments THS8200 video encoder driver"); +MODULE_AUTHOR("Mats Randgaard "); +MODULE_AUTHOR("Martin Bugge "); +MODULE_LICENSE("GPL v2"); + +struct ths8200_state { + struct v4l2_subdev sd; + uint8_t chip_version; + /* Is the ths8200 powered on? */ + bool power_on; + struct v4l2_dv_timings dv_timings; +}; + +static const struct v4l2_dv_timings ths8200_timings[] = { + V4L2_DV_BT_CEA_720X480P59_94, + V4L2_DV_BT_CEA_1280X720P24, + V4L2_DV_BT_CEA_1280X720P25, + V4L2_DV_BT_CEA_1280X720P30, + V4L2_DV_BT_CEA_1280X720P50, + V4L2_DV_BT_CEA_1280X720P60, + V4L2_DV_BT_CEA_1920X1080P24, + V4L2_DV_BT_CEA_1920X1080P25, + V4L2_DV_BT_CEA_1920X1080P30, + V4L2_DV_BT_CEA_1920X1080P50, + V4L2_DV_BT_CEA_1920X1080P60, +}; + +static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ths8200_state, sd); +} + +static inline unsigned hblanking(const struct v4l2_bt_timings *t) +{ + return t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned htotal(const struct v4l2_bt_timings *t) +{ + return t->width + t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned vblanking(const struct v4l2_bt_timings *t) +{ + return t->vfrontporch + t->vsync + t->vbackporch; +} + +static inline unsigned vtotal(const struct v4l2_bt_timings *t) +{ + return t->height + t->vfrontporch + t->vsync + t->vbackporch; +} + +static int ths8200_read(struct v4l2_subdev *sd, u8 reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_read_byte_data(client, reg); +} + +static int ths8200_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + int i; + + for (i = 0; i < 3; i++) { + ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret == 0) + return 0; + } + v4l2_err(sd, "I2C Write Problem\n"); + return ret; +} + +/* To set specific bits in the register, a clear-mask is given (to be AND-ed), + * and then the value-mask (to be OR-ed). + */ +static inline void +ths8200_write_and_or(struct v4l2_subdev *sd, u8 reg, + uint8_t clr_mask, uint8_t val_mask) +{ + ths8200_write(sd, reg, (ths8200_read(sd, reg) & clr_mask) | val_mask); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG + +static int ths8200_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + reg->val = ths8200_read(sd, reg->reg & 0xff); + reg->size = 1; + + return 0; +} + +static int ths8200_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + ths8200_write(sd, reg->reg & 0xff, reg->val & 0xff); + + return 0; +} +#endif + +static void ths8200_print_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings, + const char *txt, bool detailed) +{ + struct v4l2_bt_timings *bt = &timings->bt; + u32 htot, vtot; + + if (timings->type != V4L2_DV_BT_656_1120) + return; + + htot = htotal(bt); + vtot = vtotal(bt); + + v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", + txt, bt->width, bt->height, bt->interlaced ? "i" : "p", + (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, + htot, vtot); + + if (detailed) { + v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", + bt->hfrontporch, + (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", + bt->hsync, bt->hbackporch); + v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", + bt->vfrontporch, + (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", + bt->vsync, bt->vbackporch); + v4l2_info(sd, + " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", + bt->pixelclock, bt->flags, bt->standards); + } +} + +static int ths8200_log_status(struct v4l2_subdev *sd) +{ + struct ths8200_state *state = to_state(sd); + uint8_t reg_03 = ths8200_read(sd, THS8200_CHIP_CTL); + + v4l2_info(sd, "----- Chip status -----\n"); + v4l2_info(sd, "version: %u\n", state->chip_version); + v4l2_info(sd, "power: %s\n", (reg_03 & 0x0c) ? "off" : "on"); + v4l2_info(sd, "reset: %s\n", (reg_03 & 0x01) ? "off" : "on"); + v4l2_info(sd, "test pattern: %s\n", + (reg_03 & 0x20) ? "enabled" : "disabled"); + v4l2_info(sd, "format: %ux%u\n", + ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_MSB) * 256 + + ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), + (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + + ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); + ths8200_print_timings(sd, &state->dv_timings, + "Configured format:", true); + + return 0; +} + +/* Power up/down ths8200 */ +static int ths8200_s_power(struct v4l2_subdev *sd, int on) +{ + struct ths8200_state *state = to_state(sd); + + v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); + + state->power_on = on; + + /* Power up/down - leave in reset state until input video is present */ + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xf2, (on ? 0x00 : 0x0c)); + + return 0; +} + +static const struct v4l2_subdev_core_ops ths8200_core_ops = { + .log_status = ths8200_log_status, + .s_power = ths8200_s_power, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ths8200_g_register, + .s_register = ths8200_s_register, +#endif +}; + +/* ----------------------------------------------------------------------------- + * V4L2 subdev video operations + */ + +static int ths8200_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ths8200_state *state = to_state(sd); + + if (enable && !state->power_on) + ths8200_s_power(sd, true); + + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xfe, + (enable ? 0x01 : 0x00)); + + v4l2_dbg(1, debug, sd, "%s: %sable\n", + __func__, (enable ? "en" : "dis")); + + return 0; +} + +static void ths8200_core_init(struct v4l2_subdev *sd) +{ + /* setup clocks */ + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0x3f, 0xc0); + + /**** Data path control (DATA) ****/ + /* Set FSADJ 700 mV, + * bypass 422-444 interpolation, + * input format 30 bit RGB444 + */ + ths8200_write(sd, THS8200_DATA_CNTL, 0x70); + + /* DTG Mode (Video blocked during blanking + * VESA slave + */ + ths8200_write(sd, THS8200_DTG1_MODE, 0x87); + + /**** Display Timing Generator Control, Part 1 (DTG1). ****/ + + /* Disable embedded syncs on the output by setting + * the amplitude to zero for all channels. + */ + ths8200_write(sd, THS8200_DTG1_Y_SYNC_MSB, 0x2a); + ths8200_write(sd, THS8200_DTG1_CBCR_SYNC_MSB, 0x2a); +} + +static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt) +{ + uint8_t polarity = 0; + uint16_t line_start_active_video = (bt->vsync + bt->vbackporch); + uint16_t line_start_front_porch = (vtotal(bt) - bt->vfrontporch); + + /*** System ****/ + /* Set chip in reset while it is configured */ + ths8200_s_stream(sd, false); + + /* configure video output timings */ + ths8200_write(sd, THS8200_DTG1_SPEC_A, bt->hsync); + ths8200_write(sd, THS8200_DTG1_SPEC_B, bt->hfrontporch); + + /* Zero for progressive scan formats.*/ + if (!bt->interlaced) + ths8200_write(sd, THS8200_DTG1_SPEC_C, 0x00); + + /* Distance from leading edge of h sync to start of active video. + * MSB in 0x2b + */ + ths8200_write(sd, THS8200_DTG1_SPEC_D_LSB, + (bt->hbackporch + bt->hsync) & 0xff); + /* Zero for SDTV-mode. MSB in 0x2b */ + ths8200_write(sd, THS8200_DTG1_SPEC_E_LSB, 0x00); + /* + * MSB for dtg1_spec(d/e/h). See comment for + * corresponding LSB registers. + */ + ths8200_write(sd, THS8200_DTG1_SPEC_DEH_MSB, + ((bt->hbackporch + bt->hsync) & 0x100) >> 1); + + /* h front porch */ + ths8200_write(sd, THS8200_DTG1_SPEC_K_LSB, (bt->hfrontporch) & 0xff); + ths8200_write(sd, THS8200_DTG1_SPEC_K_MSB, + ((bt->hfrontporch) & 0x700) >> 8); + + /* Half the line length. Used to calculate SDTV line types. */ + ths8200_write(sd, THS8200_DTG1_SPEC_G_LSB, (htotal(bt)/2) & 0xff); + ths8200_write(sd, THS8200_DTG1_SPEC_G_MSB, + ((htotal(bt)/2) >> 8) & 0x0f); + + /* Total pixels per line (ex. 720p: 1650) */ + ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_MSB, htotal(bt) >> 8); + ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_LSB, htotal(bt) & 0xff); + + /* Frame height and field height */ + /* Field height should be programmed higher than frame_size for + * progressive scan formats + */ + ths8200_write(sd, THS8200_DTG1_FRAME_FIELD_SZ_MSB, + ((vtotal(bt) >> 4) & 0xf0) + 0x7); + ths8200_write(sd, THS8200_DTG1_FRAME_SZ_LSB, vtotal(bt) & 0xff); + + /* Should be programmed higher than frame_size + * for progressive formats + */ + if (!bt->interlaced) + ths8200_write(sd, THS8200_DTG1_FIELD_SZ_LSB, 0xff); + + /**** Display Timing Generator Control, Part 2 (DTG2). ****/ + /* Set breakpoint line numbers and types + * THS8200 generates line types with different properties. A line type + * that sets all the RGB-outputs to zero is used in the blanking areas, + * while a line type that enable the RGB-outputs is used in active video + * area. The line numbers for start of active video, start of front + * porch and after the last line in the frame must be set with the + * corresponding line types. + * + * Line types: + * 0x9 - Full normal sync pulse: Blocks data when dtg1_pass is off. + * Used in blanking area. + * 0x0 - Active video: Video data is always passed. Used in active + * video area. + */ + ths8200_write_and_or(sd, THS8200_DTG2_BP1_2_MSB, 0x88, + ((line_start_active_video >> 4) & 0x70) + + ((line_start_front_porch >> 8) & 0x07)); + ths8200_write(sd, THS8200_DTG2_BP3_4_MSB, ((vtotal(bt)) >> 4) & 0x70); + ths8200_write(sd, THS8200_DTG2_BP1_LSB, line_start_active_video & 0xff); + ths8200_write(sd, THS8200_DTG2_BP2_LSB, line_start_front_porch & 0xff); + ths8200_write(sd, THS8200_DTG2_BP3_LSB, (vtotal(bt)) & 0xff); + + /* line types */ + ths8200_write(sd, THS8200_DTG2_LINETYPE1, 0x90); + ths8200_write(sd, THS8200_DTG2_LINETYPE2, 0x90); + + /* h sync width transmitted */ + ths8200_write(sd, THS8200_DTG2_HLENGTH_LSB, bt->hsync & 0xff); + ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0x3f, + (bt->hsync >> 2) & 0xc0); + + /* The pixel value h sync is asserted on */ + ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0xe0, + (htotal(bt) >> 8) & 0x1f); + ths8200_write(sd, THS8200_DTG2_HLENGTH_HDLY_LSB, htotal(bt)); + + /* v sync width transmitted */ + ths8200_write(sd, THS8200_DTG2_VLENGTH1_LSB, (bt->vsync) & 0xff); + ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0x3f, + ((bt->vsync) >> 2) & 0xc0); + + /* The pixel value v sync is asserted on */ + ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0xf8, + (vtotal(bt)>>8) & 0x7); + ths8200_write(sd, THS8200_DTG2_VDLY1_LSB, vtotal(bt)); + + /* For progressive video vlength2 must be set to all 0 and vdly2 must + * be set to all 1. + */ + ths8200_write(sd, THS8200_DTG2_VLENGTH2_LSB, 0x00); + ths8200_write(sd, THS8200_DTG2_VLENGTH2_MSB_VDLY2_MSB, 0x07); + ths8200_write(sd, THS8200_DTG2_VDLY2_LSB, 0xff); + + /* Internal delay factors to synchronize the sync pulses and the data */ + /* Experimental values delays (hor 4, ver 1) */ + ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_MSB, (htotal(bt)>>8) & 0x1f); + ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_LSB, (htotal(bt) - 4) & 0xff); + ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_MSB, 0); + ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_LSB, 1); + + /* Polarity of received and transmitted sync signals */ + if (bt->polarities & V4L2_DV_HSYNC_POS_POL) { + polarity |= 0x01; /* HS_IN */ + polarity |= 0x08; /* HS_OUT */ + } + if (bt->polarities & V4L2_DV_VSYNC_POS_POL) { + polarity |= 0x02; /* VS_IN */ + polarity |= 0x10; /* VS_OUT */ + } + + /* RGB mode, no embedded timings */ + /* Timing of video input bus is derived from HS, VS, and FID dedicated + * inputs + */ + ths8200_write(sd, THS8200_DTG2_CNTL, 0x47 | polarity); + + /* leave reset */ + ths8200_s_stream(sd, true); + + v4l2_dbg(1, debug, sd, "%s: frame %dx%d, polarity %d\n" + "horizontal: front porch %d, back porch %d, sync %d\n" + "vertical: sync %d\n", __func__, htotal(bt), vtotal(bt), + polarity, bt->hfrontporch, bt->hbackporch, + bt->hsync, bt->vsync); +} + +static int ths8200_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ths8200_state *state = to_state(sd); + int i; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + if (timings->type != V4L2_DV_BT_656_1120) + return -EINVAL; + + /* TODO Support interlaced formats */ + if (timings->bt.interlaced) { + v4l2_dbg(1, debug, sd, "TODO Support interlaced formats\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(ths8200_timings); i++) { + if (v4l_match_dv_timings(&ths8200_timings[i], timings, 10)) + break; + } + + if (i == ARRAY_SIZE(ths8200_timings)) { + v4l2_dbg(1, debug, sd, "Unsupported format\n"); + return -EINVAL; + } + + timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; + + /* save timings */ + state->dv_timings = *timings; + + ths8200_setup(sd, &timings->bt); + + return 0; +} + +static int ths8200_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ths8200_state *state = to_state(sd); + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + *timings = state->dv_timings; + + return 0; +} + +static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + /* Check requested format index is within range */ + if (timings->index >= ARRAY_SIZE(ths8200_timings)) + return -EINVAL; + + timings->timings = ths8200_timings[timings->index]; + + return 0; +} + +static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + cap->type = V4L2_DV_BT_656_1120; + cap->bt.max_width = 1920; + cap->bt.max_height = 1080; + cap->bt.min_pixelclock = 27000000; + cap->bt.max_pixelclock = 148500000; + cap->bt.standards = V4L2_DV_BT_STD_CEA861; + cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE; + + return 0; +} + +/* Specific video subsystem operation handlers */ +static const struct v4l2_subdev_video_ops ths8200_video_ops = { + .s_stream = ths8200_s_stream, + .s_dv_timings = ths8200_s_dv_timings, + .g_dv_timings = ths8200_g_dv_timings, + .enum_dv_timings = ths8200_enum_dv_timings, + .dv_timings_cap = ths8200_dv_timings_cap, +}; + +/* V4L2 top level operation handlers */ +static const struct v4l2_subdev_ops ths8200_ops = { + .core = &ths8200_core_ops, + .video = &ths8200_video_ops, +}; + +static int ths8200_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ths8200_state *state; + struct v4l2_subdev *sd; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &ths8200_ops); + + state->chip_version = ths8200_read(sd, THS8200_VERSION); + v4l2_dbg(1, debug, sd, "chip version 0x%x\n", state->chip_version); + + ths8200_core_init(sd); + + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + return 0; +} + +static int ths8200_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + ths8200_s_power(sd, false); + + v4l2_device_unregister_subdev(sd); + + return 0; +} + +static struct i2c_device_id ths8200_id[] = { + { "ths8200", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ths8200_id); + +static struct i2c_driver ths8200_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ths8200", + }, + .probe = ths8200_probe, + .remove = ths8200_remove, + .id_table = ths8200_id, +}; + +module_i2c_driver(ths8200_driver); diff --git a/drivers/media/i2c/ths8200_regs.h b/drivers/media/i2c/ths8200_regs.h new file mode 100644 index 000000000000..6bc9fd1111db --- /dev/null +++ b/drivers/media/i2c/ths8200_regs.h @@ -0,0 +1,161 @@ +/* + * ths8200 - Texas Instruments THS8200 video encoder driver + * + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef THS8200_REGS_H +#define THS8200_REGS_H + +/* Register offset macros */ +#define THS8200_VERSION 0x02 +#define THS8200_CHIP_CTL 0x03 +#define THS8200_CSC_R11 0x04 +#define THS8200_CSC_R12 0x05 +#define THS8200_CSC_R21 0x06 +#define THS8200_CSC_R22 0x07 +#define THS8200_CSC_R31 0x08 +#define THS8200_CSC_R32 0x09 +#define THS8200_CSC_G11 0x0a +#define THS8200_CSC_G12 0x0b +#define THS8200_CSC_G21 0x0c +#define THS8200_CSC_G22 0x0d +#define THS8200_CSC_G31 0x0e +#define THS8200_CSC_G32 0x0f +#define THS8200_CSC_B11 0x10 +#define THS8200_CSC_B12 0x11 +#define THS8200_CSC_B21 0x12 +#define THS8200_CSC_B22 0x13 +#define THS8200_CSC_B31 0x14 +#define THS8200_CSC_B32 0x15 +#define THS8200_CSC_OFFS1 0x16 +#define THS8200_CSC_OFFS12 0x17 +#define THS8200_CSC_OFFS23 0x18 +#define THS8200_CSC_OFFS3 0x19 +#define THS8200_TST_CNTL1 0x1a +#define THS8200_TST_CNTL2 0x1b +#define THS8200_DATA_CNTL 0x1c +#define THS8200_DTG1_Y_SYNC1_LSB 0x1d +#define THS8200_DTG1_Y_SYNC2_LSB 0x1e +#define THS8200_DTG1_Y_SYNC3_LSB 0x1f +#define THS8200_DTG1_CBCR_SYNC1_LSB 0x20 +#define THS8200_DTG1_CBCR_SYNC2_LSB 0x21 +#define THS8200_DTG1_CBCR_SYNC3_LSB 0x22 +#define THS8200_DTG1_Y_SYNC_MSB 0x23 +#define THS8200_DTG1_CBCR_SYNC_MSB 0x24 +#define THS8200_DTG1_SPEC_A 0x25 +#define THS8200_DTG1_SPEC_B 0x26 +#define THS8200_DTG1_SPEC_C 0x27 +#define THS8200_DTG1_SPEC_D_LSB 0x28 +#define THS8200_DTG1_SPEC_D1 0x29 +#define THS8200_DTG1_SPEC_E_LSB 0x2a +#define THS8200_DTG1_SPEC_DEH_MSB 0x2b +#define THS8200_DTG1_SPEC_H_LSB 0x2c +#define THS8200_DTG1_SPEC_I_MSB 0x2d +#define THS8200_DTG1_SPEC_I_LSB 0x2e +#define THS8200_DTG1_SPEC_K_LSB 0x2f +#define THS8200_DTG1_SPEC_K_MSB 0x30 +#define THS8200_DTG1_SPEC_K1 0x31 +#define THS8200_DTG1_SPEC_G_LSB 0x32 +#define THS8200_DTG1_SPEC_G_MSB 0x33 +#define THS8200_DTG1_TOT_PIXELS_MSB 0x34 +#define THS8200_DTG1_TOT_PIXELS_LSB 0x35 +#define THS8200_DTG1_FLD_FLIP_LINECNT_MSB 0x36 +#define THS8200_DTG1_LINECNT_LSB 0x37 +#define THS8200_DTG1_MODE 0x38 +#define THS8200_DTG1_FRAME_FIELD_SZ_MSB 0x39 +#define THS8200_DTG1_FRAME_SZ_LSB 0x3a +#define THS8200_DTG1_FIELD_SZ_LSB 0x3b +#define THS8200_DTG1_VESA_CBAR_SIZE 0x3c +#define THS8200_DAC_CNTL_MSB 0x3d +#define THS8200_DAC1_CNTL_LSB 0x3e +#define THS8200_DAC2_CNTL_LSB 0x3f +#define THS8200_DAC3_CNTL_LSB 0x40 +#define THS8200_CSM_CLIP_GY_LOW 0x41 +#define THS8200_CSM_CLIP_BCB_LOW 0x42 +#define THS8200_CSM_CLIP_RCR_LOW 0x43 +#define THS8200_CSM_CLIP_GY_HIGH 0x44 +#define THS8200_CSM_CLIP_BCB_HIGH 0x45 +#define THS8200_CSM_CLIP_RCR_HIGH 0x46 +#define THS8200_CSM_SHIFT_GY 0x47 +#define THS8200_CSM_SHIFT_BCB 0x48 +#define THS8200_CSM_SHIFT_RCR 0x49 +#define THS8200_CSM_GY_CNTL_MULT_MSB 0x4a +#define THS8200_CSM_MULT_BCB_RCR_MSB 0x4b +#define THS8200_CSM_MULT_GY_LSB 0x4c +#define THS8200_CSM_MULT_BCB_LSB 0x4d +#define THS8200_CSM_MULT_RCR_LSB 0x4e +#define THS8200_CSM_MULT_RCR_BCB_CNTL 0x4f +#define THS8200_CSM_MULT_RCR_LSB 0x4e +#define THS8200_DTG2_BP1_2_MSB 0x50 +#define THS8200_DTG2_BP3_4_MSB 0x51 +#define THS8200_DTG2_BP5_6_MSB 0x52 +#define THS8200_DTG2_BP7_8_MSB 0x53 +#define THS8200_DTG2_BP9_10_MSB 0x54 +#define THS8200_DTG2_BP11_12_MSB 0x55 +#define THS8200_DTG2_BP13_14_MSB 0x56 +#define THS8200_DTG2_BP15_16_MSB 0x57 +#define THS8200_DTG2_BP1_LSB 0x58 +#define THS8200_DTG2_BP2_LSB 0x59 +#define THS8200_DTG2_BP3_LSB 0x5a +#define THS8200_DTG2_BP4_LSB 0x5b +#define THS8200_DTG2_BP5_LSB 0x5c +#define THS8200_DTG2_BP6_LSB 0x5d +#define THS8200_DTG2_BP7_LSB 0x5e +#define THS8200_DTG2_BP8_LSB 0x5f +#define THS8200_DTG2_BP9_LSB 0x60 +#define THS8200_DTG2_BP10_LSB 0x61 +#define THS8200_DTG2_BP11_LSB 0x62 +#define THS8200_DTG2_BP12_LSB 0x63 +#define THS8200_DTG2_BP13_LSB 0x64 +#define THS8200_DTG2_BP14_LSB 0x65 +#define THS8200_DTG2_BP15_LSB 0x66 +#define THS8200_DTG2_BP16_LSB 0x67 +#define THS8200_DTG2_LINETYPE1 0x68 +#define THS8200_DTG2_LINETYPE2 0x69 +#define THS8200_DTG2_LINETYPE3 0x6a +#define THS8200_DTG2_LINETYPE4 0x6b +#define THS8200_DTG2_LINETYPE5 0x6c +#define THS8200_DTG2_LINETYPE6 0x6d +#define THS8200_DTG2_LINETYPE7 0x6e +#define THS8200_DTG2_LINETYPE8 0x6f +#define THS8200_DTG2_HLENGTH_LSB 0x70 +#define THS8200_DTG2_HLENGTH_LSB_HDLY_MSB 0x71 +#define THS8200_DTG2_HLENGTH_HDLY_LSB 0x72 +#define THS8200_DTG2_VLENGTH1_LSB 0x73 +#define THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB 0x74 +#define THS8200_DTG2_VDLY1_LSB 0x75 +#define THS8200_DTG2_VLENGTH2_LSB 0x76 +#define THS8200_DTG2_VLENGTH2_MSB_VDLY2_MSB 0x77 +#define THS8200_DTG2_VDLY2_LSB 0x78 +#define THS8200_DTG2_HS_IN_DLY_MSB 0x79 +#define THS8200_DTG2_HS_IN_DLY_LSB 0x7a +#define THS8200_DTG2_VS_IN_DLY_MSB 0x7b +#define THS8200_DTG2_VS_IN_DLY_LSB 0x7c +#define THS8200_DTG2_PIXEL_CNT_MSB 0x7d +#define THS8200_DTG2_PIXEL_CNT_LSB 0x7e +#define THS8200_DTG2_LINE_CNT_MSB 0x7f +#define THS8200_DTG2_LINE_CNT_LSB 0x80 +#define THS8200_DTG2_CNTL 0x82 +#define THS8200_CGMS_CNTL_HEADER 0x83 +#define THS8200_CGMS_PAYLOAD_MSB 0x84 +#define THS8200_CGMS_PAYLOAD_LSB 0x85 +#define THS8200_MISC_PPL_LSB 0x86 +#define THS8200_MISC_PPL_MSB 0x87 +#define THS8200_MISC_LPF_MSB 0x88 +#define THS8200_MISC_LPF_LSB 0x89 + +#endif /* THS8200_REGS_H */ -- GitLab From 8460d519bc5a7145166f8954f08dde5ee75db85a Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Thu, 6 Jun 2013 00:12:17 -0300 Subject: [PATCH 1306/2900] [media] solo6x10: reimplement SAA712x setup routine This cleans up the saa712x setup code and there are no functional changes. Signed-off-by: Ismael Luceno [hans.verkuil@cisco.com: add clarification that this is cleanup only] Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/solo6x10/solo6x10-tw28.c | 112 +++++++++++------- 1 file changed, 66 insertions(+), 46 deletions(-) diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/staging/media/solo6x10/solo6x10-tw28.c index ad00e2b60323..af65ea655f15 100644 --- a/drivers/staging/media/solo6x10/solo6x10-tw28.c +++ b/drivers/staging/media/solo6x10/solo6x10-tw28.c @@ -513,62 +513,82 @@ static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr) #define FIRST_ACTIVE_LINE 0x0008 #define LAST_ACTIVE_LINE 0x0102 -static void saa7128_setup(struct solo_dev *solo_dev) +static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals, + int start, int n) { - int i; - unsigned char regs[128] = { - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + for (;start < n; start++, vals++) { + /* Skip read-only registers */ + switch (start) { + /* case 0x00 ... 0x25: */ + case 0x2e ... 0x37: + case 0x60: + case 0x7d: + continue; + } + solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals); + } +} + +#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \ + | ((FIRST_ACTIVE_LINE & 0x100) >> 4)) + +static void saa712x_setup(struct solo_dev *dev) +{ + const int reg_start = 0x26; + const uint8_t saa7128_regs_ntsc[] = { + /* :0x26 */ + 0x0d, 0x00, + /* :0x28 */ + 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, + /* :0x2e XXX: read-only */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, - 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, 0x00, 0x00, - 0x1c, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, + /* :0x38 */ 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x40 */ 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, + /* :0x50 */ 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, 0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e, + /* :0x60 */ 0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77, - 0x41, 0x88, 0x41, 0x12, 0xed, 0x10, 0x10, 0x00, + 0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00, + /* :0x70 */ + 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, + 0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff, + SAA712x_reg7c, 0x00, 0xff, 0xff, + }, saa7128_regs_pal[] = { + /* :0x26 */ + 0x0d, 0x00, + /* :0x28 */ + 0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f, + /* :0x2e XXX: read-only */ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x38 */ + 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x40 */ + 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, + 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, + /* :0x50 */ + 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, + 0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e, + /* :0x60 */ + 0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77, + 0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00, + /* :0x70 */ 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x08, 0xff, 0x80, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x12, 0x30, + SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff, }; - regs[0x7A] = FIRST_ACTIVE_LINE & 0xff; - regs[0x7B] = LAST_ACTIVE_LINE & 0xff; - regs[0x7C] = ((1 << 7) | - (((LAST_ACTIVE_LINE >> 8) & 1) << 6) | - (((FIRST_ACTIVE_LINE >> 8) & 1) << 4)); - - /* PAL: XXX: We could do a second set of regs to avoid this */ - if (solo_dev->video_type != SOLO_VO_FMT_TYPE_NTSC) { - regs[0x28] = 0xE1; - - regs[0x5A] = 0x0F; - regs[0x61] = 0x02; - regs[0x62] = 0x35; - regs[0x63] = 0xCB; - regs[0x64] = 0x8A; - regs[0x65] = 0x09; - regs[0x66] = 0x2A; - - regs[0x6C] = 0xf1; - regs[0x6E] = 0x20; - - regs[0x7A] = 0x06 + 12; - regs[0x7b] = 0x24 + 12; - regs[0x7c] |= 1 << 6; - } - - /* First 0x25 bytes are read-only? */ - for (i = 0x26; i < 128; i++) { - if (i == 0x60 || i == 0x7D) - continue; - solo_i2c_writebyte(solo_dev, SOLO_I2C_SAA, 0x46, i, regs[i]); - } - - return; + if (dev->video_type == SOLO_VO_FMT_TYPE_PAL) + saa712x_write_regs(dev, saa7128_regs_pal, reg_start, + sizeof(saa7128_regs_pal)); + else + saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start, + sizeof(saa7128_regs_ntsc)); } int solo_tw28_init(struct solo_dev *solo_dev) @@ -609,7 +629,7 @@ int solo_tw28_init(struct solo_dev *solo_dev) return -EINVAL; } - saa7128_setup(solo_dev); + saa712x_setup(solo_dev); for (i = 0; i < solo_dev->tw28_cnt; i++) { if ((solo_dev->tw2865 & (1 << i))) -- GitLab From 8fcd4769de1528cd058590b17d783050a53819da Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 07:57:10 -0300 Subject: [PATCH 1307/2900] [media] saa7134: remove radio/type field from saa7134_fh This information is already available in vfl_type in video_device. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 89 ++++++++--------------- drivers/media/pci/saa7134/saa7134.h | 2 - 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index b78d515068a7..aa1a73ed75a4 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1287,15 +1287,17 @@ static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c) /* ------------------------------------------------------------------ */ -static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) +static struct videobuf_queue *saa7134_queue(struct file *file) { - struct videobuf_queue* q = NULL; + struct video_device *vdev = video_devdata(file); + struct saa7134_fh *fh = file->private_data; + struct videobuf_queue *q = NULL; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: q = &fh->cap; break; - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: q = &fh->vbi; break; default: @@ -1304,12 +1306,14 @@ static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) return q; } -static int saa7134_resource(struct saa7134_fh *fh) +static int saa7134_resource(struct file *file) { - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + struct video_device *vdev = video_devdata(file); + + if (vdev->vfl_type == VFL_TYPE_GRABBER) return RESOURCE_VIDEO; - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + if (vdev->vfl_type == VFL_TYPE_VBI) return RESOURCE_VBI; BUG(); @@ -1321,23 +1325,6 @@ static int video_open(struct file *file) struct video_device *vdev = video_devdata(file); struct saa7134_dev *dev = video_drvdata(file); struct saa7134_fh *fh; - enum v4l2_buf_type type = 0; - int radio = 0; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev), - radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); @@ -1347,8 +1334,6 @@ static int video_open(struct file *file) v4l2_fh_init(&fh->fh, vdev); file->private_data = fh; fh->dev = dev; - fh->radio = radio; - fh->type = type; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); fh->width = 720; fh->height = 576; @@ -1368,7 +1353,7 @@ static int video_open(struct file *file) saa7134_pgtable_alloc(dev->pci,&fh->pt_cap); saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi); - if (fh->radio) { + if (vdev->vfl_type == VFL_TYPE_RADIO) { /* switch to radio mode */ saa7134_tvaudio_setinput(dev,&card(dev).radio); saa_call_all(dev, tuner, s_radio); @@ -1384,19 +1369,20 @@ static int video_open(struct file *file) static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: if (res_locked(fh->dev,RESOURCE_VIDEO)) return -EBUSY; - return videobuf_read_one(saa7134_queue(fh), + return videobuf_read_one(saa7134_queue(file), data, count, ppos, file->f_flags & O_NONBLOCK); - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: if (!res_get(fh->dev,fh,RESOURCE_VBI)) return -EBUSY; - return videobuf_read_stream(saa7134_queue(fh), + return videobuf_read_stream(saa7134_queue(file), data, count, ppos, 1, file->f_flags & O_NONBLOCK); break; @@ -1409,11 +1395,12 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) + if (vdev->vfl_type == VFL_TYPE_VBI) return videobuf_poll_stream(file, &fh->vbi, wait); if (res_check(fh,RESOURCE_VIDEO)) { @@ -1451,6 +1438,7 @@ video_poll(struct file *file, struct poll_table_struct *wait) static int video_release(struct file *file) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; struct saa6588_command cmd; @@ -1489,7 +1477,7 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); saa_call_all(dev, core, s_power, 0); - if (fh->radio) + if (vdev->vfl_type == VFL_TYPE_RADIO) saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); /* free stuff */ @@ -1507,9 +1495,7 @@ static int video_release(struct file *file) static int video_mmap(struct file *file, struct vm_area_struct * vma) { - struct saa7134_fh *fh = file->private_data; - - return videobuf_mmap_mapper(saa7134_queue(fh), vma); + return videobuf_mmap_mapper(saa7134_queue(file), vma); } static ssize_t radio_read(struct file *file, char __user *data, @@ -2057,7 +2043,6 @@ static int saa7134_g_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; saa_call_all(dev, tuner, g_frequency, f); return 0; @@ -2071,10 +2056,6 @@ static int saa7134_s_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; - if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; - if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) - return -EINVAL; mutex_lock(&dev->lock); saa_call_all(dev, tuner, s_frequency, f); @@ -2186,27 +2167,23 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on) static int saa7134_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct saa7134_fh *fh = priv; - return videobuf_reqbufs(saa7134_queue(fh), p); + return videobuf_reqbufs(saa7134_queue(file), p); } static int saa7134_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_querybuf(saa7134_queue(fh), b); + return videobuf_querybuf(saa7134_queue(file), b); } static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_qbuf(saa7134_queue(fh), b); + return videobuf_qbuf(saa7134_queue(file), b); } static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_dqbuf(saa7134_queue(fh), b, + return videobuf_dqbuf(saa7134_queue(file), b, file->f_flags & O_NONBLOCK); } @@ -2215,7 +2192,7 @@ static int saa7134_streamon(struct file *file, void *priv, { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - int res = saa7134_resource(fh); + int res = saa7134_resource(file); if (!res_get(dev, fh, res)) return -EBUSY; @@ -2231,7 +2208,7 @@ static int saa7134_streamon(struct file *file, void *priv, PM_QOS_CPU_DMA_LATENCY, 20); - return videobuf_streamon(saa7134_queue(fh)); + return videobuf_streamon(saa7134_queue(file)); } static int saa7134_streamoff(struct file *file, void *priv, @@ -2240,11 +2217,11 @@ static int saa7134_streamoff(struct file *file, void *priv, int err; struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - int res = saa7134_resource(fh); + int res = saa7134_resource(file); pm_qos_remove_request(&fh->qos_request); - err = videobuf_streamoff(saa7134_queue(fh)); + err = videobuf_streamoff(saa7134_queue(file)); if (err < 0) return err; res_free(dev, fh, res); @@ -2283,9 +2260,7 @@ static int radio_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; saa_call_all(dev, tuner, g_tuner, t); t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index d2ad16c1569a..a103678cd499 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -471,8 +471,6 @@ struct saa7134_dmaqueue { struct saa7134_fh { struct v4l2_fh fh; struct saa7134_dev *dev; - unsigned int radio; - enum v4l2_buf_type type; unsigned int resources; struct pm_qos_request qos_request; -- GitLab From b12262f9472d714341d9d83f47cccd76c977aa0e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 08:22:24 -0300 Subject: [PATCH 1308/2900] [media] saa7134: move the overlay fields from saa7134_fh to saa7134_dev This is global data, not per-filehandle data. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 33 ++++++++++++----------- drivers/media/pci/saa7134/saa7134.h | 9 +++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index aa1a73ed75a4..331eded72ebc 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -872,20 +872,20 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) unsigned long base,control,bpl; int err; - err = verify_preview(dev,&fh->win); + err = verify_preview(dev, &dev->win); if (0 != err) return err; - dev->ovfield = fh->win.field; + dev->ovfield = dev->win.field; dprintk("start_preview %dx%d+%d+%d %s field=%s\n", - fh->win.w.width,fh->win.w.height, - fh->win.w.left,fh->win.w.top, - dev->ovfmt->name,v4l2_field_names[dev->ovfield]); + dev->win.w.width, dev->win.w.height, + dev->win.w.left, dev->win.w.top, + dev->ovfmt->name, v4l2_field_names[dev->ovfield]); /* setup window + clipping */ - set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height, + set_size(dev, TASK_B, dev->win.w.width, dev->win.w.height, V4L2_FIELD_HAS_BOTH(dev->ovfield)); - setup_clipping(dev,fh->clips,fh->nclips, + setup_clipping(dev, dev->clips, dev->nclips, V4L2_FIELD_HAS_BOTH(dev->ovfield)); if (dev->ovfmt->yuv) saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03); @@ -895,8 +895,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) /* dma: setup channel 1 (= Video Task B) */ base = (unsigned long)dev->ovbuf.base; - base += dev->ovbuf.fmt.bytesperline * fh->win.w.top; - base += dev->ovfmt->depth/8 * fh->win.w.left; + base += dev->ovbuf.fmt.bytesperline * dev->win.w.top; + base += dev->ovfmt->depth/8 * dev->win.w.left; bpl = dev->ovbuf.fmt.bytesperline; control = SAA7134_RS_CONTROL_BURST_16; if (dev->ovfmt->bswap) @@ -1572,12 +1572,13 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } - f->fmt.win = fh->win; + f->fmt.win = dev->win; return 0; } @@ -1682,14 +1683,14 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, mutex_lock(&dev->lock); - fh->win = f->fmt.win; - fh->nclips = f->fmt.win.clipcount; + dev->win = f->fmt.win; + dev->nclips = f->fmt.win.clipcount; - if (fh->nclips > 8) - fh->nclips = 8; + if (dev->nclips > 8) + dev->nclips = 8; - if (copy_from_user(fh->clips, f->fmt.win.clips, - sizeof(struct v4l2_clip)*fh->nclips)) { + if (copy_from_user(dev->clips, f->fmt.win.clips, + sizeof(struct v4l2_clip) * dev->nclips)) { mutex_unlock(&dev->lock); return -EFAULT; } diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index a103678cd499..fa21d14ea16e 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -474,11 +474,6 @@ struct saa7134_fh { unsigned int resources; struct pm_qos_request qos_request; - /* video overlay */ - struct v4l2_window win; - struct v4l2_clip clips[8]; - unsigned int nclips; - /* video capture */ struct saa7134_format *fmt; unsigned int width,height; @@ -590,6 +585,10 @@ struct saa7134_dev { struct saa7134_format *ovfmt; unsigned int ovenable; enum v4l2_field ovfield; + struct v4l2_window win; + struct v4l2_clip clips[8]; + unsigned int nclips; + /* video+ts+vbi capture */ struct saa7134_dmaqueue video_q; -- GitLab From 813b9dffa0cfefdd71b262e1ec4ad5f7d1fb8f89 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 08:30:49 -0300 Subject: [PATCH 1309/2900] [media] saa7134: move fmt/width/height from saa7134_fh to saa7134_dev These fields are global, not per-filehandle. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 57 ++++++++++++----------- drivers/media/pci/saa7134/saa7134.h | 4 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 331eded72ebc..30832d38fb54 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1024,38 +1024,38 @@ static int buffer_prepare(struct videobuf_queue *q, int err; /* sanity checks */ - if (NULL == fh->fmt) + if (NULL == dev->fmt) return -EINVAL; - if (fh->width < 48 || - fh->height < 32 || - fh->width/4 > dev->crop_current.width || - fh->height/4 > dev->crop_current.height || - fh->width > dev->crop_bounds.width || - fh->height > dev->crop_bounds.height) + if (dev->width < 48 || + dev->height < 32 || + dev->width/4 > dev->crop_current.width || + dev->height/4 > dev->crop_current.height || + dev->width > dev->crop_bounds.width || + dev->height > dev->crop_bounds.height) return -EINVAL; - size = (fh->width * fh->height * fh->fmt->depth) >> 3; + size = (dev->width * dev->height * dev->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n", - vb->i,fh->width,fh->height,size,v4l2_field_names[field], - fh->fmt->name); - if (buf->vb.width != fh->width || - buf->vb.height != fh->height || + vb->i, dev->width, dev->height, size, v4l2_field_names[field], + dev->fmt->name); + if (buf->vb.width != dev->width || + buf->vb.height != dev->height || buf->vb.size != size || buf->vb.field != field || - buf->fmt != fh->fmt) { + buf->fmt != dev->fmt) { saa7134_dma_free(q,buf); } if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - buf->vb.width = fh->width; - buf->vb.height = fh->height; + buf->vb.width = dev->width; + buf->vb.height = dev->height; buf->vb.size = size; buf->vb.field = field; - buf->fmt = fh->fmt; + buf->fmt = dev->fmt; buf->pt = &fh->pt_cap; dev->video_q.curr = NULL; @@ -1082,8 +1082,9 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { struct saa7134_fh *fh = q->priv_data; + struct saa7134_dev *dev = fh->dev; - *size = fh->fmt->depth * fh->width * fh->height >> 3; + *size = dev->fmt->depth * dev->width * dev->height >> 3; if (0 == *count) *count = gbuffers; *count = saa7134_buffer_count(*size,*count); @@ -1334,9 +1335,6 @@ static int video_open(struct file *file) v4l2_fh_init(&fh->fh, vdev); file->private_data = fh; fh->dev = dev; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - fh->width = 720; - fh->height = 576; videobuf_queue_sg_init(&fh->cap, &video_qops, &dev->pci->dev, &dev->slock, @@ -1556,13 +1554,14 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->cap.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.pixelformat = dev->fmt->fourcc; f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; + (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; return 0; @@ -1652,15 +1651,16 @@ static int saa7134_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; int err; err = saa7134_try_fmt_vid_cap(file, priv, f); if (0 != err) return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; + dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + dev->width = f->fmt.pix.width; + dev->height = f->fmt.pix.height; fh->cap.field = f->fmt.pix.field; return 0; } @@ -2451,6 +2451,9 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.dev = dev; + dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + dev->width = 720; + dev->height = 576; if (saa7134_boards[dev->board].video_out) saa7134_videoport_init(dev); diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index fa21d14ea16e..8a62ff733343 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -475,8 +475,6 @@ struct saa7134_fh { struct pm_qos_request qos_request; /* video capture */ - struct saa7134_format *fmt; - unsigned int width,height; struct videobuf_queue cap; struct saa7134_pgtable pt_cap; @@ -595,6 +593,8 @@ struct saa7134_dev { struct saa7134_dmaqueue vbi_q; unsigned int video_fieldcount; unsigned int vbi_fieldcount; + struct saa7134_format *fmt; + unsigned int width, height; /* various v4l controls */ struct saa7134_tvnorm *tvnorm; /* video */ -- GitLab From 1ee5d8c85aecc0d7b4d0de7473dbc7340ddbb5d4 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Mon, 17 Jun 2013 17:17:58 +0530 Subject: [PATCH 1310/2900] mfd: palmas: Remove code which is not necessary for a device tree boot Remove code which is not necessary for a device tree boot. Boot tested on OMAP5-UEVM board. Signed-off-by: J Keerthy Acked-by: Laxman Dewangan Acked-by: Graeme Gregory Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 106 ------------------------------------------- 1 file changed, 106 deletions(-) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 53e9fe638d32..62fa728d3e04 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -25,77 +25,6 @@ #include #include -enum palmas_ids { - PALMAS_PMIC_ID, - PALMAS_GPIO_ID, - PALMAS_LEDS_ID, - PALMAS_WDT_ID, - PALMAS_RTC_ID, - PALMAS_PWRBUTTON_ID, - PALMAS_GPADC_ID, - PALMAS_RESOURCE_ID, - PALMAS_CLK_ID, - PALMAS_PWM_ID, - PALMAS_USB_ID, -}; - -static struct resource palmas_rtc_resources[] = { - { - .start = PALMAS_RTC_ALARM_IRQ, - .end = PALMAS_RTC_ALARM_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static const struct mfd_cell palmas_children[] = { - { - .name = "palmas-pmic", - .id = PALMAS_PMIC_ID, - }, - { - .name = "palmas-gpio", - .id = PALMAS_GPIO_ID, - }, - { - .name = "palmas-leds", - .id = PALMAS_LEDS_ID, - }, - { - .name = "palmas-wdt", - .id = PALMAS_WDT_ID, - }, - { - .name = "palmas-rtc", - .id = PALMAS_RTC_ID, - .resources = &palmas_rtc_resources[0], - .num_resources = ARRAY_SIZE(palmas_rtc_resources), - }, - { - .name = "palmas-pwrbutton", - .id = PALMAS_PWRBUTTON_ID, - }, - { - .name = "palmas-gpadc", - .id = PALMAS_GPADC_ID, - }, - { - .name = "palmas-resource", - .id = PALMAS_RESOURCE_ID, - }, - { - .name = "palmas-clk", - .id = PALMAS_CLK_ID, - }, - { - .name = "palmas-pwm", - .id = PALMAS_PWM_ID, - }, - { - .name = "palmas-usb", - .id = PALMAS_USB_ID, - } -}; - static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { .reg_bits = 8, @@ -311,7 +240,6 @@ static int palmas_i2c_probe(struct i2c_client *i2c, int ret = 0, i; unsigned int reg, addr; int slave; - struct mfd_cell *children; pdata = dev_get_platdata(&i2c->dev); @@ -472,42 +400,8 @@ static int palmas_i2c_probe(struct i2c_client *i2c, return ret; } - children = kmemdup(palmas_children, sizeof(palmas_children), - GFP_KERNEL); - if (!children) { - ret = -ENOMEM; - goto err_irq; - } - - children[PALMAS_PMIC_ID].platform_data = pdata->pmic_pdata; - children[PALMAS_PMIC_ID].pdata_size = sizeof(*pdata->pmic_pdata); - - children[PALMAS_GPADC_ID].platform_data = pdata->gpadc_pdata; - children[PALMAS_GPADC_ID].pdata_size = sizeof(*pdata->gpadc_pdata); - - children[PALMAS_RESOURCE_ID].platform_data = pdata->resource_pdata; - children[PALMAS_RESOURCE_ID].pdata_size = - sizeof(*pdata->resource_pdata); - - children[PALMAS_USB_ID].platform_data = pdata->usb_pdata; - children[PALMAS_USB_ID].pdata_size = sizeof(*pdata->usb_pdata); - - children[PALMAS_CLK_ID].platform_data = pdata->clk_pdata; - children[PALMAS_CLK_ID].pdata_size = sizeof(*pdata->clk_pdata); - - ret = mfd_add_devices(palmas->dev, -1, - children, ARRAY_SIZE(palmas_children), - NULL, 0, - regmap_irq_get_domain(palmas->irq_data)); - kfree(children); - - if (ret < 0) - goto err_devices; - return ret; -err_devices: - mfd_remove_devices(palmas->dev); err_irq: regmap_del_irq_chip(palmas->irq, palmas->irq_data); err: -- GitLab From 89f3a1422998b35b991c6a059e7acbc99166c5cd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 08:44:58 -0300 Subject: [PATCH 1311/2900] [media] saa7134: move qos_request from saa7134_fh to saa7134_dev This is a global field, not a per-filehandle field. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 4 ++-- drivers/media/pci/saa7134/saa7134.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 30832d38fb54..a7baa246b653 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -2205,7 +2205,7 @@ static int saa7134_streamon(struct file *file, void *priv, * Unfortunately, I lack register-level documentation to check the * Linux FIFO setup and confirm the perfect value. */ - pm_qos_add_request(&fh->qos_request, + pm_qos_add_request(&dev->qos_request, PM_QOS_CPU_DMA_LATENCY, 20); @@ -2220,7 +2220,7 @@ static int saa7134_streamoff(struct file *file, void *priv, struct saa7134_dev *dev = fh->dev; int res = saa7134_resource(file); - pm_qos_remove_request(&fh->qos_request); + pm_qos_remove_request(&dev->qos_request); err = videobuf_streamoff(saa7134_queue(file)); if (err < 0) diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index 8a62ff733343..8d1453a48014 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -472,7 +472,6 @@ struct saa7134_fh { struct v4l2_fh fh; struct saa7134_dev *dev; unsigned int resources; - struct pm_qos_request qos_request; /* video capture */ struct videobuf_queue cap; @@ -595,6 +594,7 @@ struct saa7134_dev { unsigned int vbi_fieldcount; struct saa7134_format *fmt; unsigned int width, height; + struct pm_qos_request qos_request; /* various v4l controls */ struct saa7134_tvnorm *tvnorm; /* video */ -- GitLab From 3a0a5a782abb16f257fb1d8fd874ed054ba9a82d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 31 May 2013 11:48:50 -0300 Subject: [PATCH 1312/2900] [media] saa7134: fix format-related compliance issues - map overlay format values to the supported ranges - set colorspace - zero priv field - fix cliplist handling - fix field handling - initialize ovbuf values Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 74 ++++++++++++++++------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index a7baa246b653..e3457aea6a33 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -825,20 +825,22 @@ static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips, return 0; } -static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) +static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool try) { enum v4l2_field field; int maxw, maxh; - if (NULL == dev->ovbuf.base) + if (!try && (dev->ovbuf.base == NULL || dev->ovfmt == NULL)) return -EINVAL; - if (NULL == dev->ovfmt) - return -EINVAL; - if (win->w.width < 48 || win->w.height < 32) - return -EINVAL; - if (win->clipcount > 2048) - return -EINVAL; - + if (win->w.width < 48) + win->w.width = 48; + if (win->w.height < 32) + win->w.height = 32; + if (win->clipcount > 8) + win->clipcount = 8; + + win->chromakey = 0; + win->global_alpha = 0; field = win->field; maxw = dev->crop_current.width; maxh = dev->crop_current.height; @@ -853,10 +855,9 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) case V4L2_FIELD_BOTTOM: maxh = maxh / 2; break; - case V4L2_FIELD_INTERLACED: - break; default: - return -EINVAL; + field = V4L2_FIELD_INTERLACED; + break; } win->field = field; @@ -872,7 +873,7 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) unsigned long base,control,bpl; int err; - err = verify_preview(dev, &dev->win); + err = verify_preview(dev, &dev->win, false); if (0 != err) return err; @@ -1564,6 +1565,8 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; return 0; } @@ -1572,14 +1575,32 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; + struct v4l2_clip *clips = f->fmt.win.clips; + u32 clipcount = f->fmt.win.clipcount; + int err = 0; + int i; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } + mutex_lock(&dev->lock); f->fmt.win = dev->win; + f->fmt.win.clips = clips; + if (clips == NULL) + clipcount = 0; + if (dev->nclips < clipcount) + clipcount = dev->nclips; + f->fmt.win.clipcount = clipcount; + + for (i = 0; !err && i < clipcount; i++) { + if (copy_to_user(&f->fmt.win.clips[i].c, &dev->clips[i].c, + sizeof(struct v4l2_rect))) + err = -EFAULT; + } + mutex_unlock(&dev->lock); - return 0; + return err; } static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, @@ -1609,10 +1630,9 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, case V4L2_FIELD_BOTTOM: maxh = maxh / 2; break; - case V4L2_FIELD_INTERLACED: - break; default: - return -EINVAL; + field = V4L2_FIELD_INTERLACED; + break; } f->fmt.pix.field = field; @@ -1629,6 +1649,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; return 0; } @@ -1644,7 +1666,9 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv, return -EINVAL; } - return verify_preview(dev, &f->fmt.win); + if (f->fmt.win.clips == NULL) + f->fmt.win.clipcount = 0; + return verify_preview(dev, &f->fmt.win, true); } static int saa7134_s_fmt_vid_cap(struct file *file, void *priv, @@ -1677,7 +1701,9 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } - err = verify_preview(dev, &f->fmt.win); + if (f->fmt.win.clips == NULL) + f->fmt.win.clipcount = 0; + err = verify_preview(dev, &f->fmt.win, true); if (0 != err) return err; @@ -1686,9 +1712,6 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, dev->win = f->fmt.win; dev->nclips = f->fmt.win.clipcount; - if (dev->nclips > 8) - dev->nclips = 8; - if (copy_from_user(dev->clips, f->fmt.win.clips, sizeof(struct v4l2_clip) * dev->nclips)) { mutex_unlock(&dev->lock); @@ -2454,6 +2477,13 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); dev->width = 720; dev->height = 576; + dev->win.w.width = dev->width; + dev->win.w.height = dev->height; + dev->win.field = V4L2_FIELD_INTERLACED; + dev->ovbuf.fmt.width = dev->width; + dev->ovbuf.fmt.height = dev->height; + dev->ovbuf.fmt.pixelformat = dev->fmt->fourcc; + dev->ovbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; if (saa7134_boards[dev->board].video_out) saa7134_videoport_init(dev); -- GitLab From cabc6508984f2d145bdab4a6998072a9e5faf100 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 1 Jun 2013 10:02:38 -0300 Subject: [PATCH 1313/2900] [media] saa7134: fix empress format compliance bugs Fix uninitialized fields and a missing TRY_FMT implementation in saa6752hs. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa6752hs.c | 58 +++++++++++++-------- drivers/media/pci/saa7134/saa7134-empress.c | 13 ++++- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index 8adb7b02ab5a..8ac4b1f2322d 100644 --- a/drivers/media/pci/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c @@ -568,10 +568,36 @@ static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm return 0; } +static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) +{ + int dist_352, dist_480, dist_720; + + f->code = V4L2_MBUS_FMT_FIXED; + + dist_352 = abs(f->width - 352); + dist_480 = abs(f->width - 480); + dist_720 = abs(f->width - 720); + if (dist_720 < dist_480) { + f->width = 720; + f->height = 576; + } else if (dist_480 < dist_352) { + f->width = 480; + f->height = 576; + } else { + f->width = 352; + if (abs(f->height - 576) < abs(f->height - 288)) + f->height = 576; + else + f->height = 288; + } + f->field = V4L2_FIELD_INTERLACED; + f->colorspace = V4L2_COLORSPACE_SMPTE170M; + return 0; +} + static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); - int dist_352, dist_480, dist_720; if (f->code != V4L2_MBUS_FMT_FIXED) return -EINVAL; @@ -588,30 +614,15 @@ static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm D1 | 720x576 | 720x480 */ - dist_352 = abs(f->width - 352); - dist_480 = abs(f->width - 480); - dist_720 = abs(f->width - 720); - if (dist_720 < dist_480) { - f->width = 720; - f->height = 576; + saa6752hs_try_mbus_fmt(sd, f); + if (f->width == 720) h->video_format = SAA6752HS_VF_D1; - } else if (dist_480 < dist_352) { - f->width = 480; - f->height = 576; + else if (f->width == 480) h->video_format = SAA6752HS_VF_2_3_D1; - } else { - f->width = 352; - if (abs(f->height - 576) < - abs(f->height - 288)) { - f->height = 576; - h->video_format = SAA6752HS_VF_1_2_D1; - } else { - f->height = 288; - h->video_format = SAA6752HS_VF_SIF; - } - } - f->field = V4L2_FIELD_INTERLACED; - f->colorspace = V4L2_COLORSPACE_SMPTE170M; + else if (f->height == 576) + h->video_format = SAA6752HS_VF_1_2_D1; + else + h->video_format = SAA6752HS_VF_SIF; return 0; } @@ -644,6 +655,7 @@ static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { .s_mbus_fmt = saa6752hs_s_mbus_fmt, + .try_mbus_fmt = saa6752hs_try_mbus_fmt, .g_mbus_fmt = saa6752hs_g_mbus_fmt, }; diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 973fa65eb3d3..e66bc3d969cf 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -212,7 +212,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv, strlcpy(f->description, "MPEG TS", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; - + f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; } @@ -227,6 +227,8 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } @@ -243,6 +245,8 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } @@ -251,9 +255,16 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_dev *dev = file->private_data; + struct v4l2_mbus_framefmt mbus_fmt; + + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); + saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } -- GitLab From 3080f8c77f277eb87397d639581ebea859f9ea41 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 06:57:19 -0300 Subject: [PATCH 1314/2900] [media] ths8200: fix two compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/i2c/ths8200.c: In function ‘ths8200_g_register’: drivers/media/i2c/ths8200.c:121:21: warning: unused variable ‘client’ [-Wunused-variable] drivers/media/i2c/ths8200.c: In function ‘ths8200_s_register’: drivers/media/i2c/ths8200.c:132:21: warning: unused variable ‘client’ [-Wunused-variable] Signed-off-by: Hans Verkuil Cc: Prabhakar Lad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths8200.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 939682967579..a24f90c5261c 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -118,8 +118,6 @@ ths8200_write_and_or(struct v4l2_subdev *sd, u8 reg, static int ths8200_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - reg->val = ths8200_read(sd, reg->reg & 0xff); reg->size = 1; @@ -129,8 +127,6 @@ static int ths8200_g_register(struct v4l2_subdev *sd, static int ths8200_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - ths8200_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; -- GitLab From 8d4da37c3006f30a7cf75cd7bb33b254afc30279 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sun, 26 May 2013 10:08:54 -0300 Subject: [PATCH 1315/2900] [media] media: i2c: mt9p031: add OF support Add OF support for the mt9p031 sensor driver. Alongside this patch sorts the header inclusion alphabetically. Signed-off-by: Lad, Prabhakar Reviewed-by: Sascha Hauer Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/mt9p031.txt | 40 ++++++++++++++++++ drivers/media/i2c/mt9p031.c | 42 ++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/mt9p031.txt diff --git a/Documentation/devicetree/bindings/media/i2c/mt9p031.txt b/Documentation/devicetree/bindings/media/i2c/mt9p031.txt new file mode 100644 index 000000000000..cb60443ff78f --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/mt9p031.txt @@ -0,0 +1,40 @@ +* Aptina 1/2.5-Inch 5Mp CMOS Digital Image Sensor + +The Aptina MT9P031 is a 1/2.5-inch CMOS active pixel digital image sensor with +an active array size of 2592H x 1944V. It is programmable through a simple +two-wire serial interface. + +Required Properties: +- compatible: value should be either one among the following + (a) "aptina,mt9p031" for mt9p031 sensor + (b) "aptina,mt9p031m" for mt9p031m sensor + +- input-clock-frequency: Input clock frequency. + +- pixel-clock-frequency: Pixel clock frequency. + +Optional Properties: +- reset-gpios: Chip reset GPIO + +For further reading on port node refer to +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + i2c0@1c22000 { + ... + ... + mt9p031@5d { + compatible = "aptina,mt9p031"; + reg = <0x5d>; + reset-gpios = <&gpio3 30 0>; + + port { + mt9p031_1: endpoint { + input-clock-frequency = <6000000>; + pixel-clock-frequency = <96000000>; + }; + }; + }; + ... + }; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index fe3414866a63..1abc86ed2255 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -16,9 +16,10 @@ #include #include #include -#include #include #include +#include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include "aptina-pll.h" @@ -927,10 +929,36 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = { * Driver initialization and probing */ +static struct mt9p031_platform_data * +mt9p031_get_pdata(struct i2c_client *client) +{ + struct mt9p031_platform_data *pdata; + struct device_node *np; + + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) + return client->dev.platform_data; + + np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + if (!np) + return NULL; + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto done; + + pdata->reset = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0); + of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq); + of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq); + +done: + of_node_put(np); + return pdata; +} + static int mt9p031_probe(struct i2c_client *client, const struct i2c_device_id *did) { - struct mt9p031_platform_data *pdata = client->dev.platform_data; + struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct mt9p031 *mt9p031; unsigned int i; @@ -1069,8 +1097,18 @@ static const struct i2c_device_id mt9p031_id[] = { }; MODULE_DEVICE_TABLE(i2c, mt9p031_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id mt9p031_of_match[] = { + { .compatible = "aptina,mt9p031", }, + { .compatible = "aptina,mt9p031m", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt9p031_of_match); +#endif + static struct i2c_driver mt9p031_i2c_driver = { .driver = { + .of_match_table = of_match_ptr(mt9p031_of_match), .name = "mt9p031", }, .probe = mt9p031_probe, -- GitLab From 7997196cb4fda8a5ad3570a5645bdc73024554ca Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 8 Jun 2013 04:50:42 -0300 Subject: [PATCH 1316/2900] [media] mt9p031: Use bulk regulator API The sensor is powered by three supplies. Use the bulk regulator API to enable and disable them instead of performing the operations manually. This fixes a warning caused by ignoring the return value of regulator_enable(). Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9p031.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 1abc86ed2255..4734836fe5a4 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -125,9 +125,7 @@ struct mt9p031 { int power_count; struct clk *clk; - struct regulator *vaa; - struct regulator *vdd; - struct regulator *vdd_io; + struct regulator_bulk_data regulators[3]; enum mt9p031_model model; struct aptina_pll pll; @@ -272,6 +270,8 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) static int mt9p031_power_on(struct mt9p031 *mt9p031) { + int ret; + /* Ensure RESET_BAR is low */ if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 0); @@ -279,9 +279,10 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031) } /* Bring up the supplies */ - regulator_enable(mt9p031->vdd); - regulator_enable(mt9p031->vdd_io); - regulator_enable(mt9p031->vaa); + ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators), + mt9p031->regulators); + if (ret < 0) + return ret; /* Emable clock */ if (mt9p031->clk) @@ -303,9 +304,8 @@ static void mt9p031_power_off(struct mt9p031 *mt9p031) usleep_range(1000, 2000); } - regulator_disable(mt9p031->vaa); - regulator_disable(mt9p031->vdd_io); - regulator_disable(mt9p031->vdd); + regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), + mt9p031->regulators); if (mt9p031->clk) clk_disable_unprepare(mt9p031->clk); @@ -985,14 +985,14 @@ static int mt9p031_probe(struct i2c_client *client, mt9p031->model = did->driver_data; mt9p031->reset = -1; - mt9p031->vaa = devm_regulator_get(&client->dev, "vaa"); - mt9p031->vdd = devm_regulator_get(&client->dev, "vdd"); - mt9p031->vdd_io = devm_regulator_get(&client->dev, "vdd_io"); + mt9p031->regulators[0].supply = "vdd"; + mt9p031->regulators[1].supply = "vdd_io"; + mt9p031->regulators[2].supply = "vaa"; - if (IS_ERR(mt9p031->vaa) || IS_ERR(mt9p031->vdd) || - IS_ERR(mt9p031->vdd_io)) { + ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators); + if (ret < 0) { dev_err(&client->dev, "Unable to get regulators\n"); - return -ENODEV; + return ret; } v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); -- GitLab From 5077ac3b8108007f4a2b4589f2d373cf55453206 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 22 May 2013 11:25:52 -0300 Subject: [PATCH 1317/2900] Properly handle tristate dependencies on USB/PCI menus As USB/PCI/MEDIA_SUPPORT dependencies can be tristate, we can't simply make the bool menu to be dependent on it. Everything below the menu should also depend on it, otherwise, we risk to allow building them with 'y', while only 'm' would be supported. So, add an IF just before everything below, in order to avoid such risks. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/Kconfig | 4 +++- drivers/media/usb/Kconfig | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index d4e2ed3f27e5..53196f1366f3 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -1,6 +1,7 @@ +if PCI && MEDIA_SUPPORT + menuconfig MEDIA_PCI_SUPPORT bool "Media PCI Adapters" - depends on PCI && MEDIA_SUPPORT help Enable media drivers for PCI/PCIe bus. If you have such devices, say Y. @@ -45,3 +46,4 @@ source "drivers/media/pci/ddbridge/Kconfig" endif endif #MEDIA_PCI_SUPPORT +endif #PCI diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index 0d8fe005d1f4..7cac453e34c7 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig @@ -1,8 +1,7 @@ -if USB +if USB && MEDIA_SUPPORT menuconfig MEDIA_USB_SUPPORT bool "Media USB Adapters" - depends on MEDIA_SUPPORT help Enable media drivers for USB bus. If you have such devices, say Y. -- GitLab From e7be28cbfd8b150c5997efc88ed9727b68e636d3 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:56 -0300 Subject: [PATCH 1318/2900] [media] drivers/media/pci/pt1/pt1: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/pt1/pt1.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index e9211086df49..75ce14229e03 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -1225,20 +1225,7 @@ static struct pci_driver pt1_driver = { .id_table = pt1_id_table, }; - -static int __init pt1_init(void) -{ - return pci_register_driver(&pt1_driver); -} - - -static void __exit pt1_cleanup(void) -{ - pci_unregister_driver(&pt1_driver); -} - -module_init(pt1_init); -module_exit(pt1_cleanup); +module_pci_driver(pt1_driver); MODULE_AUTHOR("Takahito HIRANO "); MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver"); -- GitLab From 2c5f81d29c946165ae01c15e70b1bf2e16929009 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:43 -0300 Subject: [PATCH 1319/2900] [media] drivers/media/pci/dm1105/dm1105: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/b2c2/flexcop-pci.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 44f8fb5f17ff..447afbd904a4 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -432,18 +432,7 @@ static struct pci_driver flexcop_pci_driver = { .remove = flexcop_pci_remove, }; -static int __init flexcop_pci_module_init(void) -{ - return pci_register_driver(&flexcop_pci_driver); -} - -static void __exit flexcop_pci_module_exit(void) -{ - pci_unregister_driver(&flexcop_pci_driver); -} - -module_init(flexcop_pci_module_init); -module_exit(flexcop_pci_module_exit); +module_pci_driver(flexcop_pci_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_NAME); -- GitLab From ecef5cc35aefd5bf85abaef9cba74e8ee5a6793a Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:46 -0300 Subject: [PATCH 1320/2900] [media] drivers/media/pci/mantis/hopper_cards: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/mantis/hopper_cards.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index 6fe9fe5293dc..104914a5bf06 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -260,18 +260,7 @@ static struct pci_driver hopper_pci_driver = { .remove = hopper_pci_remove, }; -static int hopper_init(void) -{ - return pci_register_driver(&hopper_pci_driver); -} - -static void hopper_exit(void) -{ - return pci_unregister_driver(&hopper_pci_driver); -} - -module_init(hopper_init); -module_exit(hopper_exit); +module_pci_driver(hopper_pci_driver); MODULE_DESCRIPTION("HOPPER driver"); MODULE_AUTHOR("Manu Abraham"); -- GitLab From 548006ce97e6e6cf63e162d9042ccb78edbd2959 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:49 -0300 Subject: [PATCH 1321/2900] [media] drivers/media/pci/dm1105/dm1105: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/dm1105/dm1105.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 026767bed5cd..ab797fe466d2 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -1241,18 +1241,7 @@ static struct pci_driver dm1105_driver = { .remove = dm1105_remove, }; -static int __init dm1105_init(void) -{ - return pci_register_driver(&dm1105_driver); -} - -static void __exit dm1105_exit(void) -{ - pci_unregister_driver(&dm1105_driver); -} - -module_init(dm1105_init); -module_exit(dm1105_exit); +module_pci_driver(dm1105_driver); MODULE_AUTHOR("Igor M. Liplianin "); MODULE_DESCRIPTION("SDMC DM1105 DVB driver"); -- GitLab From 6eb2fb3170549737207974c2c6ad34bcc2f3025e Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:53 -0300 Subject: [PATCH 1322/2900] [media] drivers/media/pci/pluto2/pluto2: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/pluto2/pluto2.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 2290faee5852..493828500055 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -796,18 +796,7 @@ static struct pci_driver pluto2_driver = { .remove = pluto2_remove, }; -static int __init pluto2_init(void) -{ - return pci_register_driver(&pluto2_driver); -} - -static void __exit pluto2_exit(void) -{ - pci_unregister_driver(&pluto2_driver); -} - -module_init(pluto2_init); -module_exit(pluto2_exit); +module_pci_driver(pluto2_driver); MODULE_AUTHOR("Andreas Oberritter "); MODULE_DESCRIPTION("Pluto2 driver"); -- GitLab From a19b56e5bcbfb24ccd6a16f934f0c7303394bc42 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Sun, 26 May 2013 22:31:39 -0300 Subject: [PATCH 1323/2900] [media] drivers/media/pci/mantis/mantis_cards: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean Signed-off-by: Libo Chen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/mantis/mantis_cards.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 932a0d73a7f8..801fc55b6167 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -290,18 +290,7 @@ static struct pci_driver mantis_pci_driver = { .remove = mantis_pci_remove, }; -static int mantis_init(void) -{ - return pci_register_driver(&mantis_pci_driver); -} - -static void mantis_exit(void) -{ - return pci_unregister_driver(&mantis_pci_driver); -} - -module_init(mantis_init); -module_exit(mantis_exit); +module_pci_driver(mantis_pci_driver); MODULE_DESCRIPTION("MANTIS driver"); MODULE_AUTHOR("Manu Abraham"); -- GitLab From 07342664d3725de4b21478da222593da491afcd8 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 1 Jun 2013 05:38:30 -0300 Subject: [PATCH 1324/2900] [media] pvrusb2: Cocci spatch "memdup.spatch" Signed-off-by: Thomas Meyer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c index 20b6ae0bb40d..1e354747de3f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-io.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c @@ -354,9 +354,9 @@ static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt) if (scnt < sp->buffer_slot_count) { struct pvr2_buffer **nb = NULL; if (scnt) { - nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); + nb = kmemdup(sp->buffers, scnt * sizeof(*nb), + GFP_KERNEL); if (!nb) return -ENOMEM; - memcpy(nb,sp->buffers,scnt * sizeof(*nb)); } kfree(sp->buffers); sp->buffers = nb; -- GitLab From 3c68ef5b2223e084402a4fedbd4c31774f012f4f Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Mon, 10 Jun 2013 15:40:07 -0700 Subject: [PATCH 1325/2900] mwifiex: Add module parameter for regdomain Allow a regulatory domain country code to be specified at boot using a module argument. This overrides the firmware regulatory mode. This patch also enables uAP to operate in 11a mode with hostapd. Signed-off-by: Avinash Patil Signed-off-by: Paul Stewart Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 29 +++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 856aea25052b..ef5fa890a286 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -20,6 +20,9 @@ #include "cfg80211.h" #include "main.h" +static char *reg_alpha2; +module_param(reg_alpha2, charp, 0); + static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { { .max = 2, .types = BIT(NL80211_IFTYPE_STATION), @@ -2485,6 +2488,17 @@ static const struct wiphy_wowlan_support mwifiex_wowlan_support = { }; #endif +static bool mwifiex_is_valid_alpha2(const char *alpha2) +{ + if (!alpha2 || strlen(alpha2) != 2) + return false; + + if (isalpha(alpha2[0]) && isalpha(alpha2[1])) + return true; + + return false; +} + /* * This function registers the device with CFG802.11 subsystem. * @@ -2537,6 +2551,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_CUSTOM_REGULATORY | + WIPHY_FLAG_STRICT_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); @@ -2574,10 +2589,16 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy_free(wiphy); return ret; } - country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); - if (country_code) - dev_info(adapter->dev, - "ignoring F/W country code %2.2s\n", country_code); + + if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) { + wiphy_info(wiphy, "driver hint alpha2: %2.2s\n", reg_alpha2); + regulatory_hint(wiphy, reg_alpha2); + } else { + country_code = mwifiex_11d_code_2_region(adapter->region_code); + if (country_code) + wiphy_info(wiphy, "ignoring F/W country code %2.2s\n", + country_code); + } adapter->wiphy = wiphy; return ret; -- GitLab From 6390d88529835a8ad3563fe01a5da89fa52d6db2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 14 Jun 2013 15:24:24 -0400 Subject: [PATCH 1326/2900] mwifiex: fix memory corruption when unsetting multicast list When trying to unset a previously-set multicast list (i.e. the new list has 0 entries), mwifiex_set_multicast_list() was calling down to mwifiex_request_set_multicast_list() while leaving mcast_list.num_multicast_addr as an uninitialized value. We were arriving at mwifiex_cmd_mac_multicast_adr() which would then proceed to do an often huge memcpy of mcast_list.num_multicast_addr*ETH_ALEN bytes, causing memory corruption and hard to debug crashes. Fix this by setting mcast_list.num_multicast_addr to 0 when no multicast list is provided. Similarly, fix up the logic in mwifiex_request_set_multicast_list() to unset the multicast list that was previously sent to the hardware in such cases. Signed-off-by: Daniel Drake Acked-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/main.c | 5 ++--- drivers/net/wireless/mwifiex/sta_ioctl.c | 18 ++++++++---------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 485871940d3c..e15ab72fb03d 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -669,9 +669,8 @@ static void mwifiex_set_multicast_list(struct net_device *dev) mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; } else { mcast_list.mode = MWIFIEX_MULTICAST_MODE; - if (netdev_mc_count(dev)) - mcast_list.num_multicast_addr = - mwifiex_copy_mcast_addr(&mcast_list, dev); + mcast_list.num_multicast_addr = + mwifiex_copy_mcast_addr(&mcast_list, dev); } mwifiex_request_set_multicast_list(priv, &mcast_list); } diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 1a8a19dbd635..23aa910bc5d0 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -104,16 +104,14 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, } else { priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - if (mcast_list->num_multicast_addr) { - dev_dbg(priv->adapter->dev, - "info: Set multicast list=%d\n", - mcast_list->num_multicast_addr); - /* Send multicast addresses to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list); - } + dev_dbg(priv->adapter->dev, + "info: Set multicast list=%d\n", + mcast_list->num_multicast_addr); + /* Send multicast addresses to firmware */ + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_MAC_MULTICAST_ADR, + HostCmd_ACT_GEN_SET, 0, + mcast_list); } } dev_dbg(priv->adapter->dev, -- GitLab From bac76a3d07133f6d9389689f3693b78f68b77adb Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 17 Jun 2013 07:01:47 +0530 Subject: [PATCH 1327/2900] ath9k: Fix LNA gpio for AR9485 The commit "ath9k: Add custom parameters for CUS198" didn't pass the correct gpio value to ath9k_hw_cfg_output(). Fix it. Reported-by: Felix Fietkau Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 9a00bc0a9304..eae23b910bce 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3576,7 +3576,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) else gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485; - ath9k_hw_cfg_output(ah, AR9300_EXT_LNA_CTL_GPIO_AR9485, + ath9k_hw_cfg_output(ah, gpio, AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); } -- GitLab From 55fee98a6e732bea9f2da986b458e68ea462c584 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 17 Jun 2013 14:24:36 +0530 Subject: [PATCH 1328/2900] ath9k: Fix ANI for AP mode The commit "ath9k: Fix ANI monitoring" reverted an earlier commit that adjusted ANI to improve performance. But, this causes adverse effects in AP mode (as reported by Felix based on an OpenWrt report). Use the older INI/period configuration for now until more testing is done. Cc: Felix Fietkau Cc: Rajkumar Manoharan Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 29 ++++++++++++---------------- drivers/net/wireless/ath/ath9k/ani.h | 6 +++++- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index a68beb19ce4d..4994bea809eb 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -186,6 +186,14 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, entry_ofdm->ofdm_weak_signal_on); } + + if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) { + ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH; + ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI; + } else { + ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI; + ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW; + } } static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) @@ -420,25 +428,12 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, cckPhyErrRate, aniState->ofdmsTurn); - if (aniState->listenTime > 5 * ah->aniperiod) { - /* - * Check if we need to lower immunity if - * 5 ani_periods have passed. - */ - if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && - cckPhyErrRate <= ah->config.cck_trig_low) { + if (aniState->listenTime > ah->aniperiod) { + if (cckPhyErrRate < ah->config.cck_trig_low && + ofdmPhyErrRate < ah->config.ofdm_trig_low) { ath9k_hw_ani_lower_immunity(ah); aniState->ofdmsTurn = !aniState->ofdmsTurn; - } - ath9k_ani_restart(ah); - } else if (aniState->listenTime > ah->aniperiod) { - /* - * Check if immunity has to be raised, - * (either OFDM or CCK). - */ - if (ofdmPhyErrRate > ah->config.ofdm_trig_high && - (cckPhyErrRate <= ah->config.cck_trig_high || - aniState->ofdmsTurn)) { + } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) { ath9k_hw_ani_ofdm_err_trigger(ah); aniState->ofdmsTurn = false; } else if (cckPhyErrRate > ah->config.cck_trig_high) { diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 77a06fd40287..b54a3fb01883 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -20,8 +20,12 @@ #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) /* units are errors per second */ -#define ATH9K_ANI_OFDM_TRIG_HIGH 1000 +#define ATH9K_ANI_OFDM_TRIG_HIGH 3500 +#define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 + #define ATH9K_ANI_OFDM_TRIG_LOW 400 +#define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 + #define ATH9K_ANI_CCK_TRIG_HIGH 600 #define ATH9K_ANI_CCK_TRIG_LOW 300 -- GitLab From 972da7ec493b16b1d06c27832fad971466859fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 17 Jun 2013 18:34:32 +0200 Subject: [PATCH 1329/2900] bcma: update core (en|dis)abling functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadocm updated their code, this may be needed for newer hardware or some corner cases. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/core.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 17b26ce7e051..37a5ffe673d5 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c @@ -9,6 +9,25 @@ #include #include +static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask, + u32 value, int timeout) +{ + unsigned long deadline = jiffies + timeout; + u32 val; + + do { + val = bcma_aread32(core, reg); + if ((val & mask) == value) + return true; + cpu_relax(); + udelay(10); + } while (!time_after_eq(jiffies, deadline)); + + bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); + + return false; +} + bool bcma_core_is_enabled(struct bcma_device *core) { if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) @@ -25,13 +44,15 @@ void bcma_core_disable(struct bcma_device *core, u32 flags) if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) return; - bcma_awrite32(core, BCMA_IOCTL, flags); - bcma_aread32(core, BCMA_IOCTL); - udelay(10); + bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300); bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); bcma_aread32(core, BCMA_RESET_CTL); udelay(1); + + bcma_awrite32(core, BCMA_IOCTL, flags); + bcma_aread32(core, BCMA_IOCTL); + udelay(10); } EXPORT_SYMBOL_GPL(bcma_core_disable); @@ -43,6 +64,7 @@ int bcma_core_enable(struct bcma_device *core, u32 flags) bcma_aread32(core, BCMA_IOCTL); bcma_awrite32(core, BCMA_RESET_CTL, 0); + bcma_aread32(core, BCMA_RESET_CTL); udelay(1); bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); -- GitLab From 39cd206c81f1cc6cc4d3cbafa81734cd3b3c66be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 17 Jun 2013 19:19:19 +0200 Subject: [PATCH 1330/2900] ssb: use const for serial flash hardware table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_sflash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c index 720665ca2bb1..1b9e770f5328 100644 --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c @@ -16,7 +16,7 @@ struct ssb_sflash_tbl_e { u16 numblocks; }; -static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { +static const struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { { "M25P20", 0x11, 0x10000, 4, }, { "M25P40", 0x12, 0x10000, 8, }, @@ -27,7 +27,7 @@ static struct ssb_sflash_tbl_e ssb_sflash_st_tbl[] = { { 0 }, }; -static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { +static const struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { { "SST25WF512", 1, 0x1000, 16, }, { "SST25VF512", 0x48, 0x1000, 16, }, { "SST25WF010", 2, 0x1000, 32, }, @@ -45,7 +45,7 @@ static struct ssb_sflash_tbl_e ssb_sflash_sst_tbl[] = { { 0 }, }; -static struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { +static const struct ssb_sflash_tbl_e ssb_sflash_at_tbl[] = { { "AT45DB011", 0xc, 256, 512, }, { "AT45DB021", 0x14, 256, 1024, }, { "AT45DB041", 0x1c, 256, 2048, }, @@ -73,7 +73,7 @@ static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) /* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) { - struct ssb_sflash_tbl_e *e; + const struct ssb_sflash_tbl_e *e; u32 id, id2; switch (cc->capabilities & SSB_CHIPCO_CAP_FLASHT) { -- GitLab From 4a71053ec5b5f5bf58963b94429d7af920b88ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 17 Jun 2013 19:19:20 +0200 Subject: [PATCH 1331/2900] bcma: use const for serial flash hardware table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/driver_chipcommon_sflash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index e6ed4fe5dced..4d07cce9c5d9 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { u16 numblocks; }; -static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { +static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { { "M25P20", 0x11, 0x10000, 4, }, { "M25P40", 0x12, 0x10000, 8, }, @@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { { 0 }, }; -static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { +static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { { "SST25WF512", 1, 0x1000, 16, }, { "SST25VF512", 0x48, 0x1000, 16, }, { "SST25WF010", 2, 0x1000, 32, }, @@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { { 0 }, }; -static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { +static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { { "AT45DB011", 0xc, 256, 512, }, { "AT45DB021", 0x14, 256, 1024, }, { "AT45DB041", 0x1c, 256, 2048, }, @@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; struct bcma_sflash *sflash = &cc->sflash; - struct bcma_sflash_tbl_e *e; + const struct bcma_sflash_tbl_e *e; u32 id, id2; switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { -- GitLab From e570bd0472b10c9f982fdb58eb39c81445cddb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 17 Jun 2013 19:56:20 +0200 Subject: [PATCH 1332/2900] ssb: add struct for serial flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This data allow writing for example MTD driver. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_sflash.c | 7 +++++++ include/linux/ssb/ssb_driver_mips.h | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c index 1b9e770f5328..205f1c499c46 100644 --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c @@ -73,6 +73,7 @@ static void ssb_sflash_cmd(struct ssb_chipcommon *cc, u32 opcode) /* Initialize serial flash access */ int ssb_sflash_init(struct ssb_chipcommon *cc) { + struct ssb_sflash *sflash = &cc->dev->bus->mipscore.sflash; const struct ssb_sflash_tbl_e *e; u32 id, id2; @@ -131,6 +132,12 @@ int ssb_sflash_init(struct ssb_chipcommon *cc) return -ENOTSUPP; } + sflash->window = SSB_FLASH2; + sflash->blocksize = e->blocksize; + sflash->numblocks = e->numblocks; + sflash->size = sflash->blocksize * sflash->numblocks; + sflash->present = true; + pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", e->name, e->blocksize, e->numblocks); diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h index afe79d40a99e..6535e4718fde 100644 --- a/include/linux/ssb/ssb_driver_mips.h +++ b/include/linux/ssb/ssb_driver_mips.h @@ -20,6 +20,18 @@ struct ssb_pflash { u32 window_size; }; +#ifdef CONFIG_SSB_SFLASH +struct ssb_sflash { + bool present; + u32 window; + u32 blocksize; + u16 numblocks; + u32 size; + + void *priv; +}; +#endif + struct ssb_mipscore { struct ssb_device *dev; @@ -27,6 +39,9 @@ struct ssb_mipscore { struct ssb_serial_port serial_ports[4]; struct ssb_pflash pflash; +#ifdef CONFIG_SSB_SFLASH + struct ssb_sflash sflash; +#endif }; extern void ssb_mipscore_init(struct ssb_mipscore *mcore); -- GitLab From c4d827c5ccc3a49227dbf9d4b248a2e86f388023 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 17 Jun 2013 13:25:49 -0500 Subject: [PATCH 1333/2900] rtlwifi: rtl8192cu: Add new USB ID for TP-Link TL-WN8200ND This is a new device for this driver. Reported-by: Tobias Kluge Signed-off-by: Larry Finger Cc: Tobias Kluge Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 826f085c29dd..2bd598526217 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -359,6 +359,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ + {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/ {} }; -- GitLab From e049ca5e854263c821a15c0e25fe2ae202c365e1 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sun, 2 Jun 2013 22:58:49 -0300 Subject: [PATCH 1334/2900] [media] staging/media: lirc_imon: fix leaks in imon_probe() Error handling of usb_submit_urb() is not as all others in imon_probe(). It just unlocks mutexes and returns nonzero leaving all already allocated resources unfreed. The patch makes sure all the resources are deallocated. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_imon.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 0a2c45dd4475..4afa7da11f37 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -911,8 +911,8 @@ static int imon_probe(struct usb_interface *interface, if (retval) { dev_err(dev, "%s: usb_submit_urb failed for intf0 (%d)\n", __func__, retval); - mutex_unlock(&context->ctx_lock); - goto exit; + alloc_status = 8; + goto unlock; } usb_set_intfdata(interface, context); @@ -937,6 +937,8 @@ static int imon_probe(struct usb_interface *interface, alloc_status_switch: switch (alloc_status) { + case 8: + lirc_unregister_driver(driver->minor); case 7: usb_free_urb(tx_urb); case 6: @@ -959,7 +961,6 @@ static int imon_probe(struct usb_interface *interface, retval = 0; } -exit: mutex_unlock(&driver_lock); return retval; -- GitLab From f3799e93720b8b722944d86f7a2a0599f5a9d716 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 17 May 2013 13:25:21 +0100 Subject: [PATCH 1335/2900] mfd: wm8994: Reset device during probe Ensure that the device is in a known good state. This should have little practical impact as the runtime PM will reset the device shortly after probe but it's neater. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 00e4fe2f3c75..ccdddf919069 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -652,6 +652,17 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) return ret; } + /* Explicitly put the device into reset in case regulators + * don't get disabled in order to ensure we know the device + * state. + */ + ret = wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, + wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET)); + if (ret != 0) { + dev_err(wm8994->dev, "Failed to reset device: %d\n", ret); + return ret; + } + if (regmap_patch) { ret = regmap_register_patch(wm8994->regmap, regmap_patch, patch_regs); -- GitLab From f1a18a10566081abfce1649c2f3884b28fff7372 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 17 May 2013 23:42:02 +0000 Subject: [PATCH 1336/2900] Thermal: CPU Package temperature thermal This driver register CPU digital temperature sensor as a thermal zone at package level. Each package will show up as one zone with at max two trip points. These trip points can be both read and updated. Once a non zero value is set in the trip point, if the package package temperature goes above or below this setting, a thermal notification is generated. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- drivers/thermal/Kconfig | 12 + drivers/thermal/Makefile | 2 +- drivers/thermal/x86_pkg_temp_thermal.c | 642 +++++++++++++++++++++++++ 3 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 drivers/thermal/x86_pkg_temp_thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 5e3c02554d99..245831ccda3e 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -169,4 +169,16 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. +config X86_PKG_TEMP_THERMAL + tristate "X86 package temperature thermal driver" + depends on THERMAL + depends on X86 + select THERMAL_GOV_USER_SPACE + default m + help + Enable this to register CPU digital sensor for package temperature as + thermal zone. Each package will have its own thermal zone. There are + two trip points which can be set by user to get notifications via thermal + notification methods. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index c054d410ac3f..b1cefb8419ae 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -23,4 +23,4 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o - +obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c new file mode 100644 index 000000000000..5de56f671a9d --- /dev/null +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -0,0 +1,642 @@ +/* + * x86_pkg_temp_thermal driver + * Copyright (c) 2013, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc. + * + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* Rate control delay: Idea is to introduce denounce effect +* This should be long enough to avoid reduce events, when +* threshold is set to a temperature, which is constantly +* violated, but at the short enough to take any action. +* The action can be remove threshold or change it to next +* interesting setting. Based on experiments, in around +* every 5 seconds under load will give us a significant +* temperature change. +*/ +#define PKG_TEMP_THERMAL_NOTIFY_DELAY 5000 +static int notify_delay_ms = PKG_TEMP_THERMAL_NOTIFY_DELAY; +module_param(notify_delay_ms, int, 0644); +MODULE_PARM_DESC(notify_delay_ms, + "User space notification delay in milli seconds."); + +/* Number of trip points in thermal zone. Currently it can't +* be more than 2. MSR can allow setting and getting notifications +* for only 2 thresholds. This define enforces this, if there +* is some wrong values returned by cpuid for number of thresholds. +*/ +#define MAX_NUMBER_OF_TRIPS 2 + +struct phy_dev_entry { + struct list_head list; + u16 phys_proc_id; + u16 first_cpu; + u32 tj_max; + int ref_cnt; + u32 start_pkg_therm_low; + u32 start_pkg_therm_high; + struct thermal_zone_device *tzone; +}; + +/* List maintaining number of package instances */ +static LIST_HEAD(phy_dev_list); +static DEFINE_MUTEX(phy_dev_list_mutex); + +/* Interrupt to work function schedule queue */ +static DEFINE_PER_CPU(struct delayed_work, pkg_temp_thermal_threshold_work); + +/* To track if the work is already scheduled on a package */ +static u8 *pkg_work_scheduled; + +/* Spin lock to prevent races with pkg_work_scheduled */ +static spinlock_t pkg_work_lock; +static u16 max_phy_id; + +/* Debug counters to show using debugfs */ +static struct dentry *debugfs; +static unsigned int pkg_interrupt_cnt; +static unsigned int pkg_work_cnt; + +static int pkg_temp_debugfs_init(void) +{ + struct dentry *d; + + debugfs = debugfs_create_dir("pkg_temp_thermal", NULL); + if (!debugfs) + return -ENOENT; + + d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs, + (u32 *)&pkg_interrupt_cnt); + if (!d) + goto err_out; + + d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs, + (u32 *)&pkg_work_cnt); + if (!d) + goto err_out; + + return 0; + +err_out: + debugfs_remove_recursive(debugfs); + return -ENOENT; +} + +static struct phy_dev_entry + *pkg_temp_thermal_get_phy_entry(unsigned int cpu) +{ + u16 phys_proc_id = topology_physical_package_id(cpu); + struct phy_dev_entry *phy_ptr; + + mutex_lock(&phy_dev_list_mutex); + + list_for_each_entry(phy_ptr, &phy_dev_list, list) + if (phy_ptr->phys_proc_id == phys_proc_id) { + mutex_unlock(&phy_dev_list_mutex); + return phy_ptr; + } + + mutex_unlock(&phy_dev_list_mutex); + + return NULL; +} + +/* +* tj-max is is interesting because threshold is set relative to this +* temperature. +*/ +static int get_tj_max(int cpu, u32 *tj_max) +{ + u32 eax, edx; + u32 val; + int err; + + err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); + if (err) + goto err_ret; + else { + val = (eax >> 16) & 0xff; + if (val) + *tj_max = val * 1000; + else { + err = -EINVAL; + goto err_ret; + } + } + + return 0; +err_ret: + *tj_max = 0; + return err; +} + +static int sys_get_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp) +{ + u32 eax, edx; + struct phy_dev_entry *phy_dev_entry; + + phy_dev_entry = tzd->devdata; + rdmsr_on_cpu(phy_dev_entry->first_cpu, MSR_IA32_PACKAGE_THERM_STATUS, + &eax, &edx); + if (eax & 0x80000000) { + *temp = phy_dev_entry->tj_max - + ((eax >> 16) & 0x7f) * 1000; + pr_debug("sys_get_curr_temp %ld\n", *temp); + return 0; + } + + return -EINVAL; +} + +static int sys_get_trip_temp(struct thermal_zone_device *tzd, + int trip, unsigned long *temp) +{ + u32 eax, edx; + struct phy_dev_entry *phy_dev_entry; + u32 mask, shift; + unsigned long thres_reg_value; + int ret; + + if (trip >= MAX_NUMBER_OF_TRIPS) + return -EINVAL; + + phy_dev_entry = tzd->devdata; + + if (trip) { + mask = THERM_MASK_THRESHOLD1; + shift = THERM_SHIFT_THRESHOLD1; + } else { + mask = THERM_MASK_THRESHOLD0; + shift = THERM_SHIFT_THRESHOLD0; + } + + ret = rdmsr_on_cpu(phy_dev_entry->first_cpu, + MSR_IA32_PACKAGE_THERM_INTERRUPT, &eax, &edx); + if (ret < 0) + return -EINVAL; + + thres_reg_value = (eax & mask) >> shift; + if (thres_reg_value) + *temp = phy_dev_entry->tj_max - thres_reg_value * 1000; + else + *temp = 0; + pr_debug("sys_get_trip_temp %ld\n", *temp); + + return 0; +} + +int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, + unsigned long temp) +{ + u32 l, h; + struct phy_dev_entry *phy_dev_entry; + u32 mask, shift, intr; + int ret; + + phy_dev_entry = tzd->devdata; + + if (trip >= MAX_NUMBER_OF_TRIPS || temp >= phy_dev_entry->tj_max) + return -EINVAL; + + ret = rdmsr_on_cpu(phy_dev_entry->first_cpu, + MSR_IA32_PACKAGE_THERM_INTERRUPT, + &l, &h); + if (ret < 0) + return -EINVAL; + + if (trip) { + mask = THERM_MASK_THRESHOLD1; + shift = THERM_SHIFT_THRESHOLD1; + intr = THERM_INT_THRESHOLD1_ENABLE; + } else { + mask = THERM_MASK_THRESHOLD0; + shift = THERM_SHIFT_THRESHOLD0; + intr = THERM_INT_THRESHOLD0_ENABLE; + } + l &= ~mask; + /* + * When users space sets a trip temperature == 0, which is indication + * that, it is no longer interested in receiving notifications. + */ + if (!temp) + l &= ~intr; + else { + l |= (phy_dev_entry->tj_max - temp)/1000 << shift; + l |= intr; + } + + return wrmsr_on_cpu(phy_dev_entry->first_cpu, + MSR_IA32_PACKAGE_THERM_INTERRUPT, + l, h); +} + +static int sys_get_trip_type(struct thermal_zone_device *thermal, + int trip, enum thermal_trip_type *type) +{ + + *type = THERMAL_TRIP_PASSIVE; + + return 0; +} + +/* Thermal zone callback registry */ +static struct thermal_zone_device_ops tzone_ops = { + .get_temp = sys_get_curr_temp, + .get_trip_temp = sys_get_trip_temp, + .get_trip_type = sys_get_trip_type, + .set_trip_temp = sys_set_trip_temp, +}; + +static bool pkg_temp_thermal_platform_thermal_rate_control(void) +{ + return true; +} + +/* Enable threshold interrupt on local package/cpu */ +static inline void enable_pkg_thres_interrupt(void) +{ + u32 l, h; + u8 thres_0, thres_1; + + rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); + /* only enable/disable if it had valid threshold value */ + thres_0 = (l & THERM_MASK_THRESHOLD0) >> THERM_SHIFT_THRESHOLD0; + thres_1 = (l & THERM_MASK_THRESHOLD1) >> THERM_SHIFT_THRESHOLD1; + if (thres_0) + l |= THERM_INT_THRESHOLD0_ENABLE; + if (thres_1) + l |= THERM_INT_THRESHOLD1_ENABLE; + wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); +} + +/* Disable threshold interrupt on local package/cpu */ +static inline void disable_pkg_thres_interrupt(void) +{ + u32 l, h; + rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); + wrmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, + l & (~THERM_INT_THRESHOLD0_ENABLE) & + (~THERM_INT_THRESHOLD1_ENABLE), h); +} + +static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work) +{ + __u64 msr_val; + int cpu = smp_processor_id(); + int phy_id = topology_physical_package_id(cpu); + struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu); + bool notify = false; + + if (!phdev) + return; + + spin_lock(&pkg_work_lock); + ++pkg_work_cnt; + if (unlikely(phy_id > max_phy_id)) { + spin_unlock(&pkg_work_lock); + return; + } + pkg_work_scheduled[phy_id] = 0; + spin_unlock(&pkg_work_lock); + + enable_pkg_thres_interrupt(); + rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); + if (msr_val & THERM_LOG_THRESHOLD0) { + wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, + msr_val & ~THERM_LOG_THRESHOLD0); + notify = true; + } + if (msr_val & THERM_LOG_THRESHOLD1) { + wrmsrl(MSR_IA32_PACKAGE_THERM_STATUS, + msr_val & ~THERM_LOG_THRESHOLD1); + notify = true; + } + if (notify) { + pr_debug("thermal_zone_device_update\n"); + thermal_zone_device_update(phdev->tzone); + } +} + +static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val) +{ + unsigned long flags; + int cpu = smp_processor_id(); + int phy_id = topology_physical_package_id(cpu); + + /* + * When a package is in interrupted state, all CPU's in that package + * are in the same interrupt state. So scheduling on any one CPU in + * the package is enough and simply return for others. + */ + spin_lock_irqsave(&pkg_work_lock, flags); + ++pkg_interrupt_cnt; + if (unlikely(phy_id > max_phy_id) || unlikely(!pkg_work_scheduled) || + pkg_work_scheduled[phy_id]) { + disable_pkg_thres_interrupt(); + spin_unlock_irqrestore(&pkg_work_lock, flags); + return -EINVAL; + } + pkg_work_scheduled[phy_id] = 1; + spin_unlock_irqrestore(&pkg_work_lock, flags); + + disable_pkg_thres_interrupt(); + schedule_delayed_work_on(cpu, + &per_cpu(pkg_temp_thermal_threshold_work, cpu), + msecs_to_jiffies(notify_delay_ms)); + return 0; +} + +static int find_siblings_cpu(int cpu) +{ + int i; + int id = topology_physical_package_id(cpu); + + for_each_online_cpu(i) + if (i != cpu && topology_physical_package_id(i) == id) + return i; + + return 0; +} + +static int pkg_temp_thermal_device_add(unsigned int cpu) +{ + int err; + u32 tj_max; + struct phy_dev_entry *phy_dev_entry; + char buffer[30]; + int thres_count; + u32 eax, ebx, ecx, edx; + + cpuid(6, &eax, &ebx, &ecx, &edx); + thres_count = ebx & 0x07; + if (!thres_count) + return -ENODEV; + + thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); + + err = get_tj_max(cpu, &tj_max); + if (err) + goto err_ret; + + mutex_lock(&phy_dev_list_mutex); + + phy_dev_entry = kzalloc(sizeof(*phy_dev_entry), GFP_KERNEL); + if (!phy_dev_entry) { + err = -ENOMEM; + goto err_ret_unlock; + } + + spin_lock(&pkg_work_lock); + if (topology_physical_package_id(cpu) > max_phy_id) + max_phy_id = topology_physical_package_id(cpu); + pkg_work_scheduled = krealloc(pkg_work_scheduled, + (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); + if (!pkg_work_scheduled) { + spin_unlock(&pkg_work_lock); + err = -ENOMEM; + goto err_ret_free; + } + pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; + spin_unlock(&pkg_work_lock); + + phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu); + phy_dev_entry->first_cpu = cpu; + phy_dev_entry->tj_max = tj_max; + phy_dev_entry->ref_cnt = 1; + snprintf(buffer, sizeof(buffer), "pkg-temp-%d\n", + phy_dev_entry->phys_proc_id); + phy_dev_entry->tzone = thermal_zone_device_register(buffer, + thres_count, + (thres_count == MAX_NUMBER_OF_TRIPS) ? + 0x03 : 0x01, + phy_dev_entry, &tzone_ops, NULL, 0, 0); + if (IS_ERR(phy_dev_entry->tzone)) { + err = PTR_ERR(phy_dev_entry->tzone); + goto err_ret_free; + } + /* Store MSR value for package thermal interrupt, to restore at exit */ + rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, + &phy_dev_entry->start_pkg_therm_low, + &phy_dev_entry->start_pkg_therm_high); + + list_add_tail(&phy_dev_entry->list, &phy_dev_list); + pr_debug("pkg_temp_thermal_device_add :phy_id %d cpu %d\n", + phy_dev_entry->phys_proc_id, cpu); + + mutex_unlock(&phy_dev_list_mutex); + + return 0; + +err_ret_free: + kfree(phy_dev_entry); +err_ret_unlock: + mutex_unlock(&phy_dev_list_mutex); + +err_ret: + return err; +} + +static int pkg_temp_thermal_device_remove(unsigned int cpu) +{ + struct phy_dev_entry *n; + u16 phys_proc_id = topology_physical_package_id(cpu); + struct phy_dev_entry *phdev = + pkg_temp_thermal_get_phy_entry(cpu); + + if (!phdev) + return -ENODEV; + + mutex_lock(&phy_dev_list_mutex); + /* If we are loosing the first cpu for this package, we need change */ + if (phdev->first_cpu == cpu) { + phdev->first_cpu = find_siblings_cpu(cpu); + pr_debug("thermal_device_remove: first cpu switched %d\n", + phdev->first_cpu); + } + /* + * It is possible that no siblings left as this was the last cpu + * going offline. We don't need to worry about this assignment + * as the phydev entry will be removed in this case and + * thermal zone is removed. + */ + --phdev->ref_cnt; + pr_debug("thermal_device_remove: pkg: %d cpu %d ref_cnt %d\n", + phys_proc_id, cpu, phdev->ref_cnt); + if (!phdev->ref_cnt) + list_for_each_entry_safe(phdev, n, &phy_dev_list, list) { + if (phdev->phys_proc_id == phys_proc_id) { + thermal_zone_device_unregister(phdev->tzone); + list_del(&phdev->list); + kfree(phdev); + break; + } + } + mutex_unlock(&phy_dev_list_mutex); + + return 0; +} + +static int get_core_online(unsigned int cpu) +{ + struct cpuinfo_x86 *c = &cpu_data(cpu); + struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu); + + /* Check if there is already an instance for this package */ + if (!phdev) { + if (!cpu_has(c, X86_FEATURE_DTHERM) && + !cpu_has(c, X86_FEATURE_PTS)) + return -ENODEV; + if (pkg_temp_thermal_device_add(cpu)) + return -ENODEV; + } else { + mutex_lock(&phy_dev_list_mutex); + ++phdev->ref_cnt; + pr_debug("get_core_online: cpu %d ref_cnt %d\n", + cpu, phdev->ref_cnt); + mutex_unlock(&phy_dev_list_mutex); + } + INIT_DELAYED_WORK(&per_cpu(pkg_temp_thermal_threshold_work, cpu), + pkg_temp_thermal_threshold_work_fn); + + pr_debug("get_core_online: cpu %d successful\n", cpu); + + return 0; +} + +static void put_core_offline(unsigned int cpu) +{ + if (!pkg_temp_thermal_device_remove(cpu)) + cancel_delayed_work_sync( + &per_cpu(pkg_temp_thermal_threshold_work, cpu)); + + pr_debug("put_core_offline: cpu %d\n", cpu); +} + +static int pkg_temp_thermal_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long) hcpu; + + switch (action) { + case CPU_ONLINE: + case CPU_DOWN_FAILED: + get_core_online(cpu); + break; + case CPU_DOWN_PREPARE: + put_core_offline(cpu); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block pkg_temp_thermal_notifier __refdata = { + .notifier_call = pkg_temp_thermal_cpu_callback, +}; + +static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = { + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, + {} +}; +MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids); + +static int __init pkg_temp_thermal_init(void) +{ + int i; + + if (!x86_match_cpu(pkg_temp_thermal_ids)) + return -ENODEV; + + spin_lock_init(&pkg_work_lock); + platform_thermal_package_notify = + pkg_temp_thermal_platform_thermal_notify; + platform_thermal_package_rate_control = + pkg_temp_thermal_platform_thermal_rate_control; + + get_online_cpus(); + for_each_online_cpu(i) + if (get_core_online(i)) + goto err_ret; + register_hotcpu_notifier(&pkg_temp_thermal_notifier); + put_online_cpus(); + + pkg_temp_debugfs_init(); /* Don't care if fails */ + + return 0; + +err_ret: + get_online_cpus(); + for_each_online_cpu(i) + put_core_offline(i); + put_online_cpus(); + kfree(pkg_work_scheduled); + platform_thermal_package_notify = NULL; + platform_thermal_package_rate_control = NULL; + + return -ENODEV; +} + +static void __exit pkg_temp_thermal_exit(void) +{ + struct phy_dev_entry *phdev, *n; + int i; + + get_online_cpus(); + unregister_hotcpu_notifier(&pkg_temp_thermal_notifier); + mutex_lock(&phy_dev_list_mutex); + list_for_each_entry_safe(phdev, n, &phy_dev_list, list) { + /* Retore old MSR value for package thermal interrupt */ + wrmsr_on_cpu(phdev->first_cpu, + MSR_IA32_PACKAGE_THERM_INTERRUPT, + phdev->start_pkg_therm_low, + phdev->start_pkg_therm_high); + thermal_zone_device_unregister(phdev->tzone); + list_del(&phdev->list); + kfree(phdev); + } + mutex_unlock(&phy_dev_list_mutex); + platform_thermal_package_notify = NULL; + platform_thermal_package_rate_control = NULL; + for_each_online_cpu(i) + cancel_delayed_work_sync( + &per_cpu(pkg_temp_thermal_threshold_work, i)); + put_online_cpus(); + + kfree(pkg_work_scheduled); + + debugfs_remove_recursive(debugfs); +} + +module_init(pkg_temp_thermal_init) +module_exit(pkg_temp_thermal_exit) + +MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver"); +MODULE_AUTHOR("Srinivas Pandruvada "); +MODULE_LICENSE("GPL v2"); -- GitLab From 23be63f48d928cd5a21db58f73c731357e895250 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 17 May 2013 23:42:03 +0000 Subject: [PATCH 1337/2900] Thermal: Documentation for x86 package temperature thermal driver Added documentation describing details of the x86 package temperature thermal driver. Signed-off-by: Srinivas Pandruvada Signed-off-by: Zhang Rui --- .../thermal/x86_pkg_temperature_thermal | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/thermal/x86_pkg_temperature_thermal diff --git a/Documentation/thermal/x86_pkg_temperature_thermal b/Documentation/thermal/x86_pkg_temperature_thermal new file mode 100644 index 000000000000..17a3a4c0a0ca --- /dev/null +++ b/Documentation/thermal/x86_pkg_temperature_thermal @@ -0,0 +1,47 @@ +Kernel driver: x86_pkg_temp_thermal +=================== + +Supported chips: +* x86: with package level thermal management +(Verify using: CPUID.06H:EAX[bit 6] =1) + +Authors: Srinivas Pandruvada + +Reference +--- +Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013): +Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT + +Description +--------- + +This driver register CPU digital temperature package level sensor as a thermal +zone with maximum two user mode configurable trip points. Number of trip points +depends on the capability of the package. Once the trip point is violated, +user mode can receive notification via thermal notification mechanism and can +take any action to control temperature. + + +Threshold management +-------------------- +Each package will register as a thermal zone under /sys/class/thermal. +Example: +/sys/class/thermal/thermal_zone1 + +This contains two trip points: +- trip_point_0_temp +- trip_point_1_temp + +User can set any temperature between 0 to TJ-Max temperature. Temperature units +are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.txt" for +thermal sys-fs details. + +Any value other than 0 in these trip points, can trigger thermal notifications. +Setting 0, stops sending thermal notifications. + +Thermal notifications: To get kobject-uevent notifications, set the thermal zone +policy to "user_space". For example: echo -n "user_space" > policy + + + + -- GitLab From 9601cd159565fa228edc8e5ea3ed2c0ac3fb4d1f Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 30 May 2013 09:20:15 +0000 Subject: [PATCH 1338/2900] MIPS: DEC: remove unbuildable promcon.c promcon.o is built if CONFIG_PROM_CONSOLE is set. But there's no Kconfig symbol PROM_CONSOLE, so promcon.c is unbuildable. Remove it. Signed-off-by: Paul Bolle Acked-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5344/ Signed-off-by: Ralf Baechle --- arch/mips/dec/Makefile | 1 - arch/mips/dec/promcon.c | 54 ----------------------------------------- 2 files changed, 55 deletions(-) delete mode 100644 arch/mips/dec/promcon.c diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile index 9eb2f9c036aa..3d5d2c56de8d 100644 --- a/arch/mips/dec/Makefile +++ b/arch/mips/dec/Makefile @@ -5,6 +5,5 @@ obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \ kn02-irq.o kn02xa-berr.o reset.o setup.o time.o -obj-$(CONFIG_PROM_CONSOLE) += promcon.o obj-$(CONFIG_TC) += tc.o obj-$(CONFIG_CPU_HAS_WB) += wbflush.o diff --git a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c deleted file mode 100644 index c239c25b79ff..000000000000 --- a/arch/mips/dec/promcon.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Wrap-around code for a console using the - * DECstation PROM io-routines. - * - * Copyright (c) 1998 Harald Koerfgen - */ - -#include -#include -#include -#include -#include - -#include - -static void prom_console_write(struct console *co, const char *s, - unsigned count) -{ - unsigned i; - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} - -static int __init prom_console_setup(struct console *co, char *options) -{ - return 0; -} - -static struct console sercons = { - .name = "ttyS", - .write = prom_console_write, - .setup = prom_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Register console. - */ - -static int __init prom_console_init(void) -{ - register_console(&sercons); - - return 0; -} -console_initcall(prom_console_init); -- GitLab From b8061134f83a36b9eb6e38a184f3982f8d8bc58c Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 30 May 2013 09:51:21 +0000 Subject: [PATCH 1339/2900] MIPS: MSP71xx: Remove gpio drivers The PMC MSP71XX gpio drivers were added in v2.6.28, see commit 9fa32c6b02 ("MIPS: PMC MSP71XX gpio drivers"). They are only built if CONFIG_HAVE_GPIO_LIB is set. But the Kconfig symbol HAVE_GPIO_LIB was already removed in v2.6.27, see commit 7444a72eff ("gpiolib: allow user-selection"). So these drivers were never buildable. Perhaps no-one noticed because there are no in tree users of msp71xx_init_gpio() and msp71xx_init_gpio_extended(). Anyhow, these drivers can safely be removed. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5345/ Signed-off-by: Ralf Baechle --- .../mips/include/asm/mach-pmcs-msp71xx/gpio.h | 46 ---- arch/mips/pmcs-msp71xx/Makefile | 1 - arch/mips/pmcs-msp71xx/gpio.c | 216 ------------------ arch/mips/pmcs-msp71xx/gpio_extended.c | 146 ------------ 4 files changed, 409 deletions(-) delete mode 100644 arch/mips/include/asm/mach-pmcs-msp71xx/gpio.h delete mode 100644 arch/mips/pmcs-msp71xx/gpio.c delete mode 100644 arch/mips/pmcs-msp71xx/gpio_extended.c diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/gpio.h b/arch/mips/include/asm/mach-pmcs-msp71xx/gpio.h deleted file mode 100644 index ebdbab973e41..000000000000 --- a/arch/mips/include/asm/mach-pmcs-msp71xx/gpio.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * include/asm-mips/pmc-sierra/msp71xx/gpio.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * @author Patrick Glass - */ - -#ifndef __PMC_MSP71XX_GPIO_H -#define __PMC_MSP71XX_GPIO_H - -/* Max number of gpio's is 28 on chip plus 3 banks of I2C IO Expanders */ -#define ARCH_NR_GPIOS (28 + (3 * 8)) - -/* new generic GPIO API - see Documentation/gpio.txt */ -#include - -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep - -/* Setup calls for the gpio and gpio extended */ -extern void msp71xx_init_gpio(void); -extern void msp71xx_init_gpio_extended(void); -extern int msp71xx_set_output_drive(unsigned gpio, int value); - -/* Custom output drive functionss */ -static inline int gpio_set_output_drive(unsigned gpio, int value) -{ - return msp71xx_set_output_drive(gpio, value); -} - -/* IRQ's are not supported for gpio lines */ -static inline int gpio_to_irq(unsigned gpio) -{ - return -EINVAL; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return -EINVAL; -} - -#endif /* __PMC_MSP71XX_GPIO_H */ diff --git a/arch/mips/pmcs-msp71xx/Makefile b/arch/mips/pmcs-msp71xx/Makefile index cefba7733b73..9201c8b3858d 100644 --- a/arch/mips/pmcs-msp71xx/Makefile +++ b/arch/mips/pmcs-msp71xx/Makefile @@ -3,7 +3,6 @@ # obj-y += msp_prom.o msp_setup.o msp_irq.o \ msp_time.o msp_serial.o msp_elb.o -obj-$(CONFIG_HAVE_GPIO_LIB) += gpio.o gpio_extended.o obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o msp_irq_per.o diff --git a/arch/mips/pmcs-msp71xx/gpio.c b/arch/mips/pmcs-msp71xx/gpio.c deleted file mode 100644 index aaccbe524386..000000000000 --- a/arch/mips/pmcs-msp71xx/gpio.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two - * types of registers. The data register sets the output level when in output - * mode and when in input mode will contain the value at the input. The config - * register sets the various modes for each gpio. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * @author Patrick Glass - */ - -#include -#include -#include -#include -#include -#include - -#define MSP71XX_CFG_OFFSET(gpio) (4 * (gpio)) -#define CONF_MASK 0x0F -#define MSP71XX_GPIO_INPUT 0x01 -#define MSP71XX_GPIO_OUTPUT 0x08 - -#define MSP71XX_GPIO_BASE 0x0B8400000L - -#define to_msp71xx_gpio_chip(c) container_of(c, struct msp71xx_gpio_chip, chip) - -static spinlock_t gpio_lock; - -/* - * struct msp71xx_gpio_chip - container for gpio chip and registers - * @chip: chip structure for the specified gpio bank - * @data_reg: register for reading and writing the gpio pin value - * @config_reg: register to set the mode for the gpio pin bank - * @out_drive_reg: register to set the output drive mode for the gpio pin bank - */ -struct msp71xx_gpio_chip { - struct gpio_chip chip; - void __iomem *data_reg; - void __iomem *config_reg; - void __iomem *out_drive_reg; -}; - -/* - * msp71xx_gpio_get() - return the chip's gpio value - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose value will be returned - * - * It will return 0 if gpio value is low and other if high. - */ -static int msp71xx_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); - - return __raw_readl(msp_chip->data_reg) & (1 << offset); -} - -/* - * msp71xx_gpio_set() - set the output value for the gpio - * @chip: chip structure who controls the specified gpio - * @offset: gpio whose value will be assigned - * @value: logic level to assign to the gpio initially - * - * This will set the gpio bit specified to the desired value. It will set the - * gpio pin low if value is 0 otherwise it will be high. - */ -static void msp71xx_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); - unsigned long flags; - u32 data; - - spin_lock_irqsave(&gpio_lock, flags); - - data = __raw_readl(msp_chip->data_reg); - if (value) - data |= (1 << offset); - else - data &= ~(1 << offset); - __raw_writel(data, msp_chip->data_reg); - - spin_unlock_irqrestore(&gpio_lock, flags); -} - -/* - * msp71xx_set_gpio_mode() - declare the mode for a gpio - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose value will be assigned - * @mode: desired configuration for the gpio (see datasheet) - * - * It will set the gpio pin config to the @mode value passed in. - */ -static int msp71xx_set_gpio_mode(struct gpio_chip *chip, - unsigned offset, int mode) -{ - struct msp71xx_gpio_chip *msp_chip = to_msp71xx_gpio_chip(chip); - const unsigned bit_offset = MSP71XX_CFG_OFFSET(offset); - unsigned long flags; - u32 cfg; - - spin_lock_irqsave(&gpio_lock, flags); - - cfg = __raw_readl(msp_chip->config_reg); - cfg &= ~(CONF_MASK << bit_offset); - cfg |= (mode << bit_offset); - __raw_writel(cfg, msp_chip->config_reg); - - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -} - -/* - * msp71xx_direction_output() - declare the direction mode for a gpio - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose value will be assigned - * @value: logic level to assign to the gpio initially - * - * This call will set the mode for the @gpio to output. It will set the - * gpio pin low if value is 0 otherwise it will be high. - */ -static int msp71xx_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - msp71xx_gpio_set(chip, offset, value); - - return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_OUTPUT); -} - -/* - * msp71xx_direction_input() - declare the direction mode for a gpio - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose to which the value will be assigned - * - * This call will set the mode for the @gpio to input. - */ -static int msp71xx_direction_input(struct gpio_chip *chip, unsigned offset) -{ - return msp71xx_set_gpio_mode(chip, offset, MSP71XX_GPIO_INPUT); -} - -/* - * msp71xx_set_output_drive() - declare the output drive for the gpio line - * @gpio: gpio pin whose output drive you wish to modify - * @value: zero for active drain 1 for open drain drive - * - * This call will set the output drive mode for the @gpio to output. - */ -int msp71xx_set_output_drive(unsigned gpio, int value) -{ - unsigned long flags; - u32 data; - - if (gpio > 15 || gpio < 0) - return -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - - data = __raw_readl((void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); - if (value) - data |= (1 << gpio); - else - data &= ~(1 << gpio); - __raw_writel(data, (void __iomem *)(MSP71XX_GPIO_BASE + 0x190)); - - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -} -EXPORT_SYMBOL(msp71xx_set_output_drive); - -#define MSP71XX_GPIO_BANK(name, dr, cr, base_gpio, num_gpio) \ -{ \ - .chip = { \ - .label = name, \ - .direction_input = msp71xx_direction_input, \ - .direction_output = msp71xx_direction_output, \ - .get = msp71xx_gpio_get, \ - .set = msp71xx_gpio_set, \ - .base = base_gpio, \ - .ngpio = num_gpio \ - }, \ - .data_reg = (void __iomem *)(MSP71XX_GPIO_BASE + dr), \ - .config_reg = (void __iomem *)(MSP71XX_GPIO_BASE + cr), \ - .out_drive_reg = (void __iomem *)(MSP71XX_GPIO_BASE + 0x190), \ -} - -/* - * struct msp71xx_gpio_banks[] - container array of gpio banks - * @chip: chip structure for the specified gpio bank - * @data_reg: register for reading and writing the gpio pin value - * @config_reg: register to set the mode for the gpio pin bank - * - * This array structure defines the gpio banks for the PMC MIPS Processor. - * We specify the bank name, the data register, the config register, base - * starting gpio number, and the number of gpios exposed by the bank. - */ -static struct msp71xx_gpio_chip msp71xx_gpio_banks[] = { - - MSP71XX_GPIO_BANK("GPIO_1_0", 0x170, 0x180, 0, 2), - MSP71XX_GPIO_BANK("GPIO_5_2", 0x174, 0x184, 2, 4), - MSP71XX_GPIO_BANK("GPIO_9_6", 0x178, 0x188, 6, 4), - MSP71XX_GPIO_BANK("GPIO_15_10", 0x17C, 0x18C, 10, 6), -}; - -void __init msp71xx_init_gpio(void) -{ - int i; - - spin_lock_init(&gpio_lock); - - for (i = 0; i < ARRAY_SIZE(msp71xx_gpio_banks); i++) - gpiochip_add(&msp71xx_gpio_banks[i].chip); -} diff --git a/arch/mips/pmcs-msp71xx/gpio_extended.c b/arch/mips/pmcs-msp71xx/gpio_extended.c deleted file mode 100644 index 2a99f360fae4..000000000000 --- a/arch/mips/pmcs-msp71xx/gpio_extended.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Generic PMC MSP71xx EXTENDED (EXD) GPIO handling. The extended gpio is - * a set of hardware registers that have no need for explicit locking as - * it is handled by unique method of writing individual set/clr bits. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * @author Patrick Glass - */ - -#include -#include -#include -#include -#include - -#define MSP71XX_DATA_OFFSET(gpio) (2 * (gpio)) -#define MSP71XX_READ_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 1) -#define MSP71XX_CFG_OUT_OFFSET(gpio) (MSP71XX_DATA_OFFSET(gpio) + 16) -#define MSP71XX_CFG_IN_OFFSET(gpio) (MSP71XX_CFG_OUT_OFFSET(gpio) + 1) - -#define MSP71XX_EXD_GPIO_BASE 0x0BC000000L - -#define to_msp71xx_exd_gpio_chip(c) \ - container_of(c, struct msp71xx_exd_gpio_chip, chip) - -/* - * struct msp71xx_exd_gpio_chip - container for gpio chip and registers - * @chip: chip structure for the specified gpio bank - * @reg: register for control and data of gpio pin - */ -struct msp71xx_exd_gpio_chip { - struct gpio_chip chip; - void __iomem *reg; -}; - -/* - * msp71xx_exd_gpio_get() - return the chip's gpio value - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose value will be returned - * - * It will return 0 if gpio value is low and other if high. - */ -static int msp71xx_exd_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct msp71xx_exd_gpio_chip *msp71xx_chip = - to_msp71xx_exd_gpio_chip(chip); - const unsigned bit = MSP71XX_READ_OFFSET(offset); - - return __raw_readl(msp71xx_chip->reg) & (1 << bit); -} - -/* - * msp71xx_exd_gpio_set() - set the output value for the gpio - * @chip: chip structure who controls the specified gpio - * @offset: gpio whose value will be assigned - * @value: logic level to assign to the gpio initially - * - * This will set the gpio bit specified to the desired value. It will set the - * gpio pin low if value is 0 otherwise it will be high. - */ -static void msp71xx_exd_gpio_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct msp71xx_exd_gpio_chip *msp71xx_chip = - to_msp71xx_exd_gpio_chip(chip); - const unsigned bit = MSP71XX_DATA_OFFSET(offset); - - __raw_writel(1 << (bit + (value ? 1 : 0)), msp71xx_chip->reg); -} - -/* - * msp71xx_exd_direction_output() - declare the direction mode for a gpio - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose value will be assigned - * @value: logic level to assign to the gpio initially - * - * This call will set the mode for the @gpio to output. It will set the - * gpio pin low if value is 0 otherwise it will be high. - */ -static int msp71xx_exd_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct msp71xx_exd_gpio_chip *msp71xx_chip = - to_msp71xx_exd_gpio_chip(chip); - - msp71xx_exd_gpio_set(chip, offset, value); - __raw_writel(1 << MSP71XX_CFG_OUT_OFFSET(offset), msp71xx_chip->reg); - return 0; -} - -/* - * msp71xx_exd_direction_input() - declare the direction mode for a gpio - * @chip: chip structure which controls the specified gpio - * @offset: gpio whose to which the value will be assigned - * - * This call will set the mode for the @gpio to input. - */ -static int msp71xx_exd_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct msp71xx_exd_gpio_chip *msp71xx_chip = - to_msp71xx_exd_gpio_chip(chip); - - __raw_writel(1 << MSP71XX_CFG_IN_OFFSET(offset), msp71xx_chip->reg); - return 0; -} - -#define MSP71XX_EXD_GPIO_BANK(name, exd_reg, base_gpio, num_gpio) \ -{ \ - .chip = { \ - .label = name, \ - .direction_input = msp71xx_exd_direction_input, \ - .direction_output = msp71xx_exd_direction_output, \ - .get = msp71xx_exd_gpio_get, \ - .set = msp71xx_exd_gpio_set, \ - .base = base_gpio, \ - .ngpio = num_gpio, \ - }, \ - .reg = (void __iomem *)(MSP71XX_EXD_GPIO_BASE + exd_reg), \ -} - -/* - * struct msp71xx_exd_gpio_banks[] - container array of gpio banks - * @chip: chip structure for the specified gpio bank - * @reg: register for reading and writing the gpio pin value - * - * This array structure defines the extended gpio banks for the - * PMC MIPS Processor. We specify the bank name, the data/config - * register,the base starting gpio number, and the number of - * gpios exposed by the bank of gpios. - */ -static struct msp71xx_exd_gpio_chip msp71xx_exd_gpio_banks[] = { - - MSP71XX_EXD_GPIO_BANK("GPIO_23_16", 0x188, 16, 8), - MSP71XX_EXD_GPIO_BANK("GPIO_27_24", 0x18C, 24, 4), -}; - -void __init msp71xx_init_gpio_extended(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(msp71xx_exd_gpio_banks); i++) - gpiochip_add(&msp71xx_exd_gpio_banks[i].chip); -} -- GitLab From d3478d5b73efb713378bebb31ac9a11f5a6dc587 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 14 Jun 2013 01:37:29 +0000 Subject: [PATCH 1340/2900] mips: lasat: sysctl: Convert use of typedef ctl_table to struct ctl_table This typedef is unnecessary and should just be removed. Signed-off-by: Joe Perches Cc: Jiri Kosina Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5460/ Signed-off-by: Ralf Baechle --- arch/mips/lasat/sysctl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c index f27694fb2ad1..3b7f65cc4218 100644 --- a/arch/mips/lasat/sysctl.c +++ b/arch/mips/lasat/sysctl.c @@ -39,7 +39,7 @@ /* And the same for proc */ -int proc_dolasatstring(ctl_table *table, int write, +int proc_dolasatstring(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { int r; @@ -54,7 +54,7 @@ int proc_dolasatstring(ctl_table *table, int write, } /* proc function to write EEPROM after changing int entry */ -int proc_dolasatint(ctl_table *table, int write, +int proc_dolasatint(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { int r; @@ -72,7 +72,7 @@ int proc_dolasatint(ctl_table *table, int write, static int rtctmp; /* proc function to read/write RealTime Clock */ -int proc_dolasatrtc(ctl_table *table, int write, +int proc_dolasatrtc(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { struct timespec ts; @@ -97,7 +97,7 @@ int proc_dolasatrtc(ctl_table *table, int write, #endif #ifdef CONFIG_INET -int proc_lasat_ip(ctl_table *table, int write, +int proc_lasat_ip(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { unsigned int ip; @@ -157,7 +157,7 @@ int proc_lasat_ip(ctl_table *table, int write, } #endif -int proc_lasat_prid(ctl_table *table, int write, +int proc_lasat_prid(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { int r; @@ -176,7 +176,7 @@ int proc_lasat_prid(ctl_table *table, int write, extern int lasat_boot_to_service; -static ctl_table lasat_table[] = { +static struct ctl_table lasat_table[] = { { .procname = "cpu-hz", .data = &lasat_board_info.li_cpu_hz, @@ -262,7 +262,7 @@ static ctl_table lasat_table[] = { {} }; -static ctl_table lasat_root_table[] = { +static struct ctl_table lasat_root_table[] = { { .procname = "lasat", .mode = 0555, -- GitLab From c5cdc67a58a22c49f558b450c6f748251ceb2e7b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 13 Jun 2013 22:19:43 +0000 Subject: [PATCH 1341/2900] irqdomain: Remove temporary MIPS workaround code The MIPS interrupt controllers are all registering their own irq_domains now. Drop the MIPS specific code because it is no longer needed. Signed-off-by: Grant Likely Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5458/ Signed-off-by: Ralf Baechle --- kernel/irq/irqdomain.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 54a4d5223238..a341b3d433ad 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -665,18 +665,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller, domain = controller ? irq_find_host(controller) : irq_default_domain; if (!domain) { -#ifdef CONFIG_MIPS - /* - * Workaround to avoid breaking interrupt controller drivers - * that don't yet register an irq_domain. This is temporary - * code. ~~~gcl, Feb 24, 2012 - * - * Scheduled for removal in Linux v3.6. That should be enough - * time. - */ - if (intsize > 0) - return intspec[0]; -#endif pr_warning("no irq domain found for %s !\n", of_node_full_name(controller)); return 0; -- GitLab From eb6db622825b2028df74f490b8c36887cf3c2f50 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 14 Jun 2013 16:33:25 +0300 Subject: [PATCH 1342/2900] net: change sysctl_net_ll_poll into an unsigned int There is no reason for sysctl_net_ll_poll to be an unsigned long. Change it into an unsigned int. Fix the proc handler. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- include/net/ll_poll.h | 5 +++-- net/core/sysctl_net_core.c | 4 ++-- net/socket.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index bc262f88173f..44e2f707cb9f 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -34,7 +34,7 @@ #ifdef CONFIG_NET_LL_RX_POLL struct napi_struct; -extern unsigned long sysctl_net_ll_poll __read_mostly; +extern unsigned int sysctl_net_ll_poll __read_mostly; /* return values from ndo_ll_poll */ #define LL_FLUSH_FAILED -1 @@ -45,7 +45,8 @@ extern unsigned long sysctl_net_ll_poll __read_mostly; static inline cycles_t ll_end_time(void) { - return TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll) + get_cycles(); + return (cycles_t)TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll) + + get_cycles(); } static inline bool sk_valid_ll(struct sock *sk) diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 78c746e016ae..62702c2053de 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -302,9 +302,9 @@ static struct ctl_table net_core_table[] = { { .procname = "low_latency_poll", .data = &sysctl_net_ll_poll, - .maxlen = sizeof(unsigned long), + .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_doulongvec_minmax + .proc_handler = proc_dointvec }, #endif #endif /* CONFIG_NET */ diff --git a/net/socket.c b/net/socket.c index 21fd29f63ed2..caaffa14e87e 100644 --- a/net/socket.c +++ b/net/socket.c @@ -107,7 +107,7 @@ #include #ifdef CONFIG_NET_LL_RX_POLL -unsigned long sysctl_net_ll_poll __read_mostly; +unsigned int sysctl_net_ll_poll __read_mostly; EXPORT_SYMBOL_GPL(sysctl_net_ll_poll); #endif -- GitLab From 9a3c71aa802499e0b1db2788ccc75a56c5f00555 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 14 Jun 2013 16:33:35 +0300 Subject: [PATCH 1343/2900] net: convert low latency sockets to sched_clock() Use sched_clock() instead of get_cycles(). We can use sched_clock() because we don't care much about accuracy. Remove the dependency on X86_TSC Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- include/net/ll_poll.h | 33 +++++++++++++++++---------------- net/Kconfig | 1 - 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 44e2f707cb9f..6930cbd943e2 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -21,10 +21,6 @@ * e1000-devel Mailing List */ -/* - * For now this depends on CONFIG_X86_TSC - */ - #ifndef _LINUX_NET_LL_POLL_H #define _LINUX_NET_LL_POLL_H @@ -40,13 +36,19 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; #define LL_FLUSH_FAILED -1 #define LL_FLUSH_BUSY -2 -/* we don't mind a ~2.5% imprecision */ -#define TSC_MHZ (tsc_khz >> 10) - -static inline cycles_t ll_end_time(void) +/* we can use sched_clock() because we don't care much about precision + * we only care that the average is bounded + */ +static inline u64 ll_end_time(void) { - return (cycles_t)TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll) - + get_cycles(); + u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll); + + /* we don't mind a ~2.5% imprecision + * sysctl_net_ll_poll is a u_int so this can't overflow + */ + end_time = (end_time << 10) + sched_clock(); + + return end_time; } static inline bool sk_valid_ll(struct sock *sk) @@ -55,16 +57,15 @@ static inline bool sk_valid_ll(struct sock *sk) !need_resched() && !signal_pending(current); } -static inline bool can_poll_ll(cycles_t end_time) +static inline bool can_poll_ll(u64 end_time) { - return !time_after((unsigned long)get_cycles(), - (unsigned long)end_time); + return !time_after64(sched_clock(), end_time); } static inline bool sk_poll_ll(struct sock *sk, int nonblock) { - cycles_t end_time = ll_end_time(); const struct net_device_ops *ops; + u64 end_time = ll_end_time(); struct napi_struct *napi; int rc = false; @@ -117,7 +118,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) #else /* CONFIG_NET_LL_RX_POLL */ -static inline cycles_t ll_end_time(void) +static inline u64 ll_end_time(void) { return 0; } @@ -140,7 +141,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) { } -static inline bool can_poll_ll(cycles_t end_time) +static inline bool can_poll_ll(u64 end_time) { return false; } diff --git a/net/Kconfig b/net/Kconfig index d6a9ce6e1800..e591668fb38f 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -245,7 +245,6 @@ config NETPRIO_CGROUP config NET_LL_RX_POLL bool "Low Latency Receive Poll" - depends on X86_TSC default n ---help--- Support Low Latency Receive Queue Poll. -- GitLab From 89bf1b5a683df497c572c4d3bd3f9c9aa919d773 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 14 Jun 2013 16:33:46 +0300 Subject: [PATCH 1344/2900] net: remove NET_LL_RX_POLL config menue Remove NET_LL_RX_POLL from the config menu. Change default to y. Busy polling still needs to be enabled at run time. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- net/Kconfig | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/net/Kconfig b/net/Kconfig index e591668fb38f..51da83943847 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -244,15 +244,8 @@ config NETPRIO_CGROUP a per-interface basis config NET_LL_RX_POLL - bool "Low Latency Receive Poll" - default n - ---help--- - Support Low Latency Receive Queue Poll. - (For network card drivers which support this option.) - When waiting for data in read or poll call directly into the the device driver - to flush packets which may be pending on the device queues into the stack. - - If unsure, say N. + boolean + default y config BQL boolean -- GitLab From dafcc4380deec21d160c31411f33c8813f67f517 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 14 Jun 2013 16:33:57 +0300 Subject: [PATCH 1345/2900] net: add socket option for low latency polling adds a socket option for low latency polling. This allows overriding the global sysctl value with a per-socket one. Unexport sysctl_net_ll_poll since for now it's not needed in modules. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- arch/alpha/include/uapi/asm/socket.h | 2 ++ arch/avr32/include/uapi/asm/socket.h | 2 ++ arch/cris/include/uapi/asm/socket.h | 2 ++ arch/frv/include/uapi/asm/socket.h | 2 ++ arch/h8300/include/uapi/asm/socket.h | 2 ++ arch/ia64/include/uapi/asm/socket.h | 2 ++ arch/m32r/include/uapi/asm/socket.h | 2 ++ arch/mips/include/uapi/asm/socket.h | 2 ++ arch/mn10300/include/uapi/asm/socket.h | 2 ++ arch/parisc/include/uapi/asm/socket.h | 2 ++ arch/powerpc/include/uapi/asm/socket.h | 2 ++ arch/s390/include/uapi/asm/socket.h | 2 ++ arch/sparc/include/uapi/asm/socket.h | 2 ++ arch/xtensa/include/uapi/asm/socket.h | 2 ++ include/net/ll_poll.h | 12 ++++++------ include/net/sock.h | 2 ++ include/uapi/asm-generic/socket.h | 2 ++ net/core/sock.c | 20 ++++++++++++++++++++ net/socket.c | 1 - 19 files changed, 58 insertions(+), 7 deletions(-) diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index eee6ea76bdaf..4885825e498d 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -81,4 +81,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h index 37401f535126..79b61798ebf8 100644 --- a/arch/avr32/include/uapi/asm/socket.h +++ b/arch/avr32/include/uapi/asm/socket.h @@ -74,4 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* __ASM_AVR32_SOCKET_H */ diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h index ba409c9947bc..47b1ec55092d 100644 --- a/arch/cris/include/uapi/asm/socket.h +++ b/arch/cris/include/uapi/asm/socket.h @@ -76,6 +76,8 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h index 31dbb5d8e13d..dbc08520f22c 100644 --- a/arch/frv/include/uapi/asm/socket.h +++ b/arch/frv/include/uapi/asm/socket.h @@ -74,5 +74,7 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h index 5d1c6d0870e6..a38d38a6520b 100644 --- a/arch/h8300/include/uapi/asm/socket.h +++ b/arch/h8300/include/uapi/asm/socket.h @@ -74,4 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h index 6b4329f18b29..d3358b760681 100644 --- a/arch/ia64/include/uapi/asm/socket.h +++ b/arch/ia64/include/uapi/asm/socket.h @@ -83,4 +83,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_IA64_SOCKET_H */ diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h index 2a3b59e0e171..44aaf4639a4a 100644 --- a/arch/m32r/include/uapi/asm/socket.h +++ b/arch/m32r/include/uapi/asm/socket.h @@ -74,4 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_M32R_SOCKET_H */ diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 3b211507be7f..6a07992ba6c6 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -92,4 +92,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h index b4ce844c9391..db80fd3e398b 100644 --- a/arch/mn10300/include/uapi/asm/socket.h +++ b/arch/mn10300/include/uapi/asm/socket.h @@ -74,4 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 70c512a386f7..f866fff9a004 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -73,6 +73,8 @@ #define SO_SELECT_ERR_QUEUE 0x4026 +#define SO_LL 0x4027 + /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. */ diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index a36daf3c6f9a..405fb09bda94 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h @@ -81,4 +81,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index 2dacb306835c..0c5105fbaaf3 100644 --- a/arch/s390/include/uapi/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h @@ -80,4 +80,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _ASM_SOCKET_H */ diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 89f49b68a21c..b46c3fa0b265 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -70,6 +70,8 @@ #define SO_SELECT_ERR_QUEUE 0x0029 +#define SO_LL 0x0030 + /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index a8f44f50e651..b21ace4fc9ba 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h @@ -85,4 +85,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* _XTENSA_SOCKET_H */ diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 6930cbd943e2..fcc7c365cee5 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -39,12 +39,12 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; /* we can use sched_clock() because we don't care much about precision * we only care that the average is bounded */ -static inline u64 ll_end_time(void) +static inline u64 ll_end_time(struct sock *sk) { - u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll); + u64 end_time = ACCESS_ONCE(sk->sk_ll_usec); /* we don't mind a ~2.5% imprecision - * sysctl_net_ll_poll is a u_int so this can't overflow + * sk->sk_ll_usec is a u_int so this can't overflow */ end_time = (end_time << 10) + sched_clock(); @@ -53,7 +53,7 @@ static inline u64 ll_end_time(void) static inline bool sk_valid_ll(struct sock *sk) { - return sysctl_net_ll_poll && sk->sk_napi_id && + return sk->sk_ll_usec && sk->sk_napi_id && !need_resched() && !signal_pending(current); } @@ -65,7 +65,7 @@ static inline bool can_poll_ll(u64 end_time) static inline bool sk_poll_ll(struct sock *sk, int nonblock) { const struct net_device_ops *ops; - u64 end_time = ll_end_time(); + u64 end_time = ll_end_time(sk); struct napi_struct *napi; int rc = false; @@ -118,7 +118,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) #else /* CONFIG_NET_LL_RX_POLL */ -static inline u64 ll_end_time(void) +static inline u64 ll_end_time(struct sock *sk) { return 0; } diff --git a/include/net/sock.h b/include/net/sock.h index ac8e1818380c..21db792bffa5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -230,6 +230,7 @@ struct cg_proto; * @sk_wmem_queued: persistent queue size * @sk_forward_alloc: space allocated forward * @sk_napi_id: id of the last napi context to receive data for sk + * @sk_ll_usec: usecs to busypoll when there is no data * @sk_allocation: allocation mode * @sk_sndbuf: size of send buffer in bytes * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, @@ -328,6 +329,7 @@ struct sock { #endif #ifdef CONFIG_NET_LL_RX_POLL unsigned int sk_napi_id; + unsigned int sk_ll_usec; #endif atomic_t sk_drops; int sk_rcvbuf; diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index c5d2e3a1cf68..ca3a20d772ac 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -76,4 +76,6 @@ #define SO_SELECT_ERR_QUEUE 45 +#define SO_LL 46 + #endif /* __ASM_GENERIC_SOCKET_H */ diff --git a/net/core/sock.c b/net/core/sock.c index 788c0da5eed1..1e744b12fda3 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -913,6 +913,19 @@ int sock_setsockopt(struct socket *sock, int level, int optname, sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool); break; +#ifdef CONFIG_NET_LL_RX_POLL + case SO_LL: + /* allow unprivileged users to decrease the value */ + if ((val > sk->sk_ll_usec) && !capable(CAP_NET_ADMIN)) + ret = -EPERM; + else { + if (val < 0) + ret = -EINVAL; + else + sk->sk_ll_usec = val; + } + break; +#endif default: ret = -ENOPROTOOPT; break; @@ -1170,6 +1183,12 @@ int sock_getsockopt(struct socket *sock, int level, int optname, v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE); break; +#ifdef CONFIG_NET_LL_RX_POLL + case SO_LL: + v.val = sk->sk_ll_usec; + break; +#endif + default: return -ENOPROTOOPT; } @@ -2288,6 +2307,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) #ifdef CONFIG_NET_LL_RX_POLL sk->sk_napi_id = 0; + sk->sk_ll_usec = sysctl_net_ll_poll; #endif /* diff --git a/net/socket.c b/net/socket.c index caaffa14e87e..3eec3f76b49c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -108,7 +108,6 @@ #ifdef CONFIG_NET_LL_RX_POLL unsigned int sysctl_net_ll_poll __read_mostly; -EXPORT_SYMBOL_GPL(sysctl_net_ll_poll); #endif static int sock_no_open(struct inode *irrelevant, struct file *dontcare); -- GitLab From dc7d48635dd3c3fd5360238f7d2c697ff13abe7b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 13 Jun 2013 09:43:29 +0100 Subject: [PATCH 1346/2900] mfd: arizona: Integrate wm8997 into Arizona mfd The wm8997 is a compact, high-performance audio hub CODEC with SLIMbus interfacing, for smartphones, tablets and other portable audio devices based on the Arizona platform. This patch integrates the wm8997 into the Arizona mfd. Signed-off-by: Charles Keepax Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 6 + drivers/mfd/Makefile | 3 + drivers/mfd/arizona-core.c | 27 + drivers/mfd/arizona-i2c.c | 6 + drivers/mfd/arizona-irq.c | 8 + drivers/mfd/arizona.h | 5 + drivers/mfd/wm8997-tables.c | 1525 ++++++++++++++++++++++++++++++ include/linux/mfd/arizona/core.h | 2 + 8 files changed, 1582 insertions(+) create mode 100644 drivers/mfd/wm8997-tables.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index c6eb930fb54d..29f7363f6bc4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1047,6 +1047,12 @@ config MFD_WM5110 help Support for Wolfson Microelectronics WM5110 low power audio SoC +config MFD_WM8997 + bool "Support Wolfson Microelectronics WM8997" + depends on MFD_ARIZONA + help + Support for Wolfson Microelectronics WM8997 low power audio SoC + config MFD_WM8400 bool "Wolfson Microelectronics WM8400" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 31d0f97d6e50..4d70cdb044e0 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -43,6 +43,9 @@ endif ifneq ($(CONFIG_MFD_WM5110),n) obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o endif +ifneq ($(CONFIG_MFD_WM8997),n) +obj-$(CONFIG_MFD_ARIZONA) += wm8997-tables.o +endif obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs += wm831x-auxadc.o diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 74b4481754fd..89a115301a0c 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -554,6 +554,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) const struct of_device_id arizona_of_match[] = { { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, + { .compatible = "wlf,wm8997", .data = (void *)WM8997 }, {}, }; EXPORT_SYMBOL_GPL(arizona_of_match); @@ -586,6 +587,15 @@ static struct mfd_cell wm5110_devs[] = { { .name = "wm5110-codec" }, }; +static struct mfd_cell wm8997_devs[] = { + { .name = "arizona-micsupp" }, + { .name = "arizona-extcon" }, + { .name = "arizona-gpio" }, + { .name = "arizona-haptics" }, + { .name = "arizona-pwm" }, + { .name = "wm8997-codec" }, +}; + int arizona_dev_init(struct arizona *arizona) { struct device *dev = arizona->dev; @@ -608,6 +618,7 @@ int arizona_dev_init(struct arizona *arizona) switch (arizona->type) { case WM5102: case WM5110: + case WM8997: for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++) arizona->core_supplies[i].supply = wm5102_core_supplies[i]; @@ -683,6 +694,7 @@ int arizona_dev_init(struct arizona *arizona) switch (reg) { case 0x5102: case 0x5110: + case 0x8997: break; default: dev_err(arizona->dev, "Unknown device ID: %x\n", reg); @@ -767,6 +779,17 @@ int arizona_dev_init(struct arizona *arizona) } apply_patch = wm5110_patch; break; +#endif +#ifdef CONFIG_MFD_WM8997 + case 0x8997: + type_name = "WM8997"; + if (arizona->type != WM8997) { + dev_err(arizona->dev, "WM8997 registered as %d\n", + arizona->type); + arizona->type = WM8997; + } + apply_patch = wm8997_patch; + break; #endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); @@ -934,6 +957,10 @@ int arizona_dev_init(struct arizona *arizona) ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, ARRAY_SIZE(wm5110_devs), NULL, 0, NULL); break; + case WM8997: + ret = mfd_add_devices(arizona->dev, -1, wm8997_devs, + ARRAY_SIZE(wm8997_devs), NULL, 0, NULL); + break; } if (ret != 0) { diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c index deb267ebf84e..51dbabf7c021 100644 --- a/drivers/mfd/arizona-i2c.c +++ b/drivers/mfd/arizona-i2c.c @@ -44,6 +44,11 @@ static int arizona_i2c_probe(struct i2c_client *i2c, case WM5110: regmap_config = &wm5110_i2c_regmap; break; +#endif +#ifdef CONFIG_MFD_WM8997 + case WM8997: + regmap_config = &wm8997_i2c_regmap; + break; #endif default: dev_err(&i2c->dev, "Unknown device type %ld\n", @@ -80,6 +85,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c) static const struct i2c_device_id arizona_i2c_id[] = { { "wm5102", WM5102 }, { "wm5110", WM5110 }, + { "wm8997", WM8997 }, { } }; MODULE_DEVICE_TABLE(i2c, arizona_i2c_id); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 64cd9b6dac92..88758ab9402b 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -208,6 +208,14 @@ int arizona_irq_init(struct arizona *arizona) ctrlif_error = false; break; #endif +#ifdef CONFIG_MFD_WM8997 + case WM8997: + aod = &wm8997_aod; + irq = &wm8997_irq; + + ctrlif_error = false; + break; +#endif default: BUG_ON("Unknown Arizona class device" == NULL); return -EINVAL; diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h index db55d9854a55..b4cef777df73 100644 --- a/drivers/mfd/arizona.h +++ b/drivers/mfd/arizona.h @@ -25,6 +25,8 @@ extern const struct regmap_config wm5102_spi_regmap; extern const struct regmap_config wm5110_i2c_regmap; extern const struct regmap_config wm5110_spi_regmap; +extern const struct regmap_config wm8997_i2c_regmap; + extern const struct dev_pm_ops arizona_pm_ops; extern const struct of_device_id arizona_of_match[]; @@ -35,6 +37,9 @@ extern const struct regmap_irq_chip wm5102_irq; extern const struct regmap_irq_chip wm5110_aod; extern const struct regmap_irq_chip wm5110_irq; +extern const struct regmap_irq_chip wm8997_aod; +extern const struct regmap_irq_chip wm8997_irq; + int arizona_dev_init(struct arizona *arizona); int arizona_dev_exit(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona); diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c new file mode 100644 index 000000000000..5aa807687777 --- /dev/null +++ b/drivers/mfd/wm8997-tables.c @@ -0,0 +1,1525 @@ +/* + * wm8997-tables.c -- WM8997 data tables + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Charles Keepax + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#include +#include + +#include "arizona.h" + +static const struct reg_default wm8997_reva_patch[] = { + { 0x80, 0x0003 }, + { 0x214, 0x0008 }, + { 0x458, 0x0000 }, + { 0x0081, 0xE022 }, + { 0x294, 0x0000 }, + { 0x80, 0x0000 }, + { 0x171, 0x0000 }, +}; + +/* We use a function so we can use ARRAY_SIZE() */ +int wm8997_patch(struct arizona *arizona) +{ + switch (arizona->rev) { + case 0: + return regmap_register_patch(arizona->regmap, + wm8997_reva_patch, + ARRAY_SIZE(wm8997_reva_patch)); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(wm8997_patch); + +static const struct regmap_irq wm8997_aod_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 }, + [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 }, + [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 }, + [ARIZONA_IRQ_JD_RISE] = { .mask = ARIZONA_JD1_RISE_EINT1 }, +}; + +const struct regmap_irq_chip wm8997_aod = { + .name = "wm8997 AOD", + .status_base = ARIZONA_AOD_IRQ1, + .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, + .ack_base = ARIZONA_AOD_IRQ1, + .num_regs = 1, + .irqs = wm8997_aod_irqs, + .num_irqs = ARRAY_SIZE(wm8997_aod_irqs), +}; +EXPORT_SYMBOL_GPL(wm8997_aod); + +static const struct regmap_irq wm8997_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 }, + [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 }, + [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 }, + [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 }, + + [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1 + }, + [ARIZONA_IRQ_SPK_SHUTDOWN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1 + }, + [ARIZONA_IRQ_HPDET] = { + .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1 + }, + [ARIZONA_IRQ_MICDET] = { + .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1 + }, + [ARIZONA_IRQ_WSEQ_DONE] = { + .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1 + }, + [ARIZONA_IRQ_DRC1_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_UNDERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_OVERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_FLL2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1 + }, + [ARIZONA_IRQ_FLL1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1 + }, + + [ARIZONA_IRQ_AIF2_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF2_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF1_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF1_ERR_EINT1 + }, + [ARIZONA_IRQ_CTRLIF_ERR] = { + .reg_offset = 3, .mask = ARIZONA_CTRLIF_ERR_EINT1 + }, + [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = { + .reg_offset = 3, .mask = ARIZONA_MIXER_DROPPED_SAMPLE_EINT1 + }, + [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_ASYNC_CLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_SYSCLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_SYSCLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_ISRC1_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC1_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_ISRC2_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1 + }, + + [ARIZONA_IRQ_BOOT_DONE] = { + .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_DAC_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_HP_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1 + }, + [ARIZONA_IRQ_FLL2_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1 + }, + [ARIZONA_IRQ_FLL1_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1 + }, +}; + +const struct regmap_irq_chip wm8997_irq = { + .name = "wm8997 IRQ", + .status_base = ARIZONA_INTERRUPT_STATUS_1, + .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK, + .ack_base = ARIZONA_INTERRUPT_STATUS_1, + .num_regs = 5, + .irqs = wm8997_irqs, + .num_irqs = ARRAY_SIZE(wm8997_irqs), +}; +EXPORT_SYMBOL_GPL(wm8997_irq); + +static const struct reg_default wm8997_reg_default[] = { + { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ + { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ + { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ + { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ + { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ + { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ + { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ + { 0x00000023, 0x1000 }, /* R35 - Tone Generator 4 */ + { 0x00000024, 0x0000 }, /* R36 - Tone Generator 5 */ + { 0x00000030, 0x0000 }, /* R48 - PWM Drive 1 */ + { 0x00000031, 0x0100 }, /* R49 - PWM Drive 2 */ + { 0x00000032, 0x0100 }, /* R50 - PWM Drive 3 */ + { 0x00000040, 0x0000 }, /* R64 - Wake control */ + { 0x00000041, 0x0000 }, /* R65 - Sequence control */ + { 0x00000061, 0x01FF }, /* R97 - Sample Rate Sequence Select 1 */ + { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ + { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ + { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ + { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 1 */ + { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 2 */ + { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 3 */ + { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 4 */ + { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ + { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ + { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ + { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ + { 0x00000093, 0x0000 }, /* R147 - Haptics phase 1 duration */ + { 0x00000094, 0x0000 }, /* R148 - Haptics phase 2 intensity */ + { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ + { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ + { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ + { 0x00000100, 0x0002 }, /* R256 - Clock 32k 1 */ + { 0x00000101, 0x0304 }, /* R257 - System Clock 1 */ + { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ + { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ + { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ + { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ + { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ + { 0x00000149, 0x0000 }, /* R329 - Output system clock */ + { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ + { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ + { 0x00000153, 0x0000 }, /* R339 - Rate Estimator 2 */ + { 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */ + { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ + { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ + { 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */ + { 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */ + { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ + { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ + { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ + { 0x00000175, 0x0004 }, /* R373 - FLL1 Control 5 */ + { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ + { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ + { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ + { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ + { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ + { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */ + { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */ + { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */ + { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */ + { 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */ + { 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */ + { 0x00000192, 0x0008 }, /* R402 - FLL2 Control 2 */ + { 0x00000193, 0x0018 }, /* R403 - FLL2 Control 3 */ + { 0x00000194, 0x007D }, /* R404 - FLL2 Control 4 */ + { 0x00000195, 0x0004 }, /* R405 - FLL2 Control 5 */ + { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ + { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ + { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ + { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ + { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ + { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */ + { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */ + { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */ + { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */ + { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ + { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ + { 0x00000210, 0x00D4 }, /* R528 - LDO1 Control 1 */ + { 0x00000212, 0x0000 }, /* R530 - LDO1 Control 2 */ + { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */ + { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ + { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ + { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ + { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ + { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ + { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ + { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ + { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ + { 0x000002C3, 0x0000 }, /* R707 - Mic noise mix control 1 */ + { 0x000002CB, 0x0000 }, /* R715 - Isolation control */ + { 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */ + { 0x00000300, 0x0000 }, /* R768 - Input Enables */ + { 0x00000308, 0x0000 }, /* R776 - Input Rate */ + { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ + { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ + { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ + { 0x00000314, 0x0080 }, /* R788 - IN1R Control */ + { 0x00000315, 0x0180 }, /* R789 - ADC Digital Volume 1R */ + { 0x00000316, 0x0000 }, /* R790 - DMIC1R Control */ + { 0x00000318, 0x2080 }, /* R792 - IN2L Control */ + { 0x00000319, 0x0180 }, /* R793 - ADC Digital Volume 2L */ + { 0x0000031A, 0x0000 }, /* R794 - DMIC2L Control */ + { 0x0000031C, 0x0080 }, /* R796 - IN2R Control */ + { 0x0000031D, 0x0180 }, /* R797 - ADC Digital Volume 2R */ + { 0x0000031E, 0x0000 }, /* R798 - DMIC2R Control */ + { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ + { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ + { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ + { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */ + { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ + { 0x00000412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ + { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ + { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ + { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ + { 0x00000416, 0x0080 }, /* R1046 - DAC Volume Limit 1R */ + { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ + { 0x00000420, 0x0080 }, /* R1056 - Output Path Config 3L */ + { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ + { 0x00000422, 0x0080 }, /* R1058 - DAC Volume Limit 3L */ + { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ + { 0x00000428, 0x0000 }, /* R1064 - Output Path Config 4L */ + { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ + { 0x0000042A, 0x0080 }, /* R1066 - Out Volume 4L */ + { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ + { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ + { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ + { 0x00000432, 0x0080 }, /* R1074 - DAC Volume Limit 5L */ + { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ + { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ + { 0x00000436, 0x0080 }, /* R1078 - DAC Volume Limit 5R */ + { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ + { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ + { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */ + { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ + { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ + { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ + { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ + { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ + { 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */ + { 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */ + { 0x00000505, 0x0040 }, /* R1285 - AIF1 Tx BCLK Rate */ + { 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */ + { 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */ + { 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */ + { 0x00000509, 0x0000 }, /* R1289 - AIF1 Frame Ctrl 3 */ + { 0x0000050A, 0x0001 }, /* R1290 - AIF1 Frame Ctrl 4 */ + { 0x0000050B, 0x0002 }, /* R1291 - AIF1 Frame Ctrl 5 */ + { 0x0000050C, 0x0003 }, /* R1292 - AIF1 Frame Ctrl 6 */ + { 0x0000050D, 0x0004 }, /* R1293 - AIF1 Frame Ctrl 7 */ + { 0x0000050E, 0x0005 }, /* R1294 - AIF1 Frame Ctrl 8 */ + { 0x0000050F, 0x0006 }, /* R1295 - AIF1 Frame Ctrl 9 */ + { 0x00000510, 0x0007 }, /* R1296 - AIF1 Frame Ctrl 10 */ + { 0x00000511, 0x0000 }, /* R1297 - AIF1 Frame Ctrl 11 */ + { 0x00000512, 0x0001 }, /* R1298 - AIF1 Frame Ctrl 12 */ + { 0x00000513, 0x0002 }, /* R1299 - AIF1 Frame Ctrl 13 */ + { 0x00000514, 0x0003 }, /* R1300 - AIF1 Frame Ctrl 14 */ + { 0x00000515, 0x0004 }, /* R1301 - AIF1 Frame Ctrl 15 */ + { 0x00000516, 0x0005 }, /* R1302 - AIF1 Frame Ctrl 16 */ + { 0x00000517, 0x0006 }, /* R1303 - AIF1 Frame Ctrl 17 */ + { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ + { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ + { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ + { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ + { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ + { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ + { 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */ + { 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */ + { 0x00000545, 0x0040 }, /* R1349 - AIF2 Tx BCLK Rate */ + { 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */ + { 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */ + { 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */ + { 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */ + { 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */ + { 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */ + { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ + { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ + { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ + { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ + { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ + { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ + { 0x000005E7, 0x0000 }, /* R1511 - SLIMbus Rates 3 */ + { 0x000005E8, 0x0000 }, /* R1512 - SLIMbus Rates 4 */ + { 0x000005E9, 0x0000 }, /* R1513 - SLIMbus Rates 5 */ + { 0x000005EA, 0x0000 }, /* R1514 - SLIMbus Rates 6 */ + { 0x000005EB, 0x0000 }, /* R1515 - SLIMbus Rates 7 */ + { 0x000005EC, 0x0000 }, /* R1516 - SLIMbus Rates 8 */ + { 0x000005F5, 0x0000 }, /* R1525 - SLIMbus RX Channel Enable */ + { 0x000005F6, 0x0000 }, /* R1526 - SLIMbus TX Channel Enable */ + { 0x00000640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */ + { 0x00000641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */ + { 0x00000642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */ + { 0x00000643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */ + { 0x00000644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */ + { 0x00000645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */ + { 0x00000646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */ + { 0x00000647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */ + { 0x00000648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */ + { 0x00000649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */ + { 0x0000064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */ + { 0x0000064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */ + { 0x0000064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */ + { 0x0000064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */ + { 0x0000064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */ + { 0x0000064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */ + { 0x00000660, 0x0000 }, /* R1632 - MICMIX Input 1 Source */ + { 0x00000661, 0x0080 }, /* R1633 - MICMIX Input 1 Volume */ + { 0x00000662, 0x0000 }, /* R1634 - MICMIX Input 2 Source */ + { 0x00000663, 0x0080 }, /* R1635 - MICMIX Input 2 Volume */ + { 0x00000664, 0x0000 }, /* R1636 - MICMIX Input 3 Source */ + { 0x00000665, 0x0080 }, /* R1637 - MICMIX Input 3 Volume */ + { 0x00000666, 0x0000 }, /* R1638 - MICMIX Input 4 Source */ + { 0x00000667, 0x0080 }, /* R1639 - MICMIX Input 4 Volume */ + { 0x00000668, 0x0000 }, /* R1640 - NOISEMIX Input 1 Source */ + { 0x00000669, 0x0080 }, /* R1641 - NOISEMIX Input 1 Volume */ + { 0x0000066A, 0x0000 }, /* R1642 - NOISEMIX Input 2 Source */ + { 0x0000066B, 0x0080 }, /* R1643 - NOISEMIX Input 2 Volume */ + { 0x0000066C, 0x0000 }, /* R1644 - NOISEMIX Input 3 Source */ + { 0x0000066D, 0x0080 }, /* R1645 - NOISEMIX Input 3 Volume */ + { 0x0000066E, 0x0000 }, /* R1646 - NOISEMIX Input 4 Source */ + { 0x0000066F, 0x0080 }, /* R1647 - NOISEMIX Input 4 Volume */ + { 0x00000680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */ + { 0x00000681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */ + { 0x00000682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */ + { 0x00000683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */ + { 0x00000684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */ + { 0x00000685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */ + { 0x00000686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */ + { 0x00000687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */ + { 0x00000688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */ + { 0x00000689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */ + { 0x0000068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */ + { 0x0000068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */ + { 0x0000068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */ + { 0x0000068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */ + { 0x0000068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */ + { 0x0000068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */ + { 0x000006A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */ + { 0x000006A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */ + { 0x000006A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */ + { 0x000006A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */ + { 0x000006A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */ + { 0x000006A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */ + { 0x000006A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */ + { 0x000006A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */ + { 0x000006B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */ + { 0x000006B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */ + { 0x000006B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */ + { 0x000006B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */ + { 0x000006B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */ + { 0x000006B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */ + { 0x000006B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */ + { 0x000006B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */ + { 0x000006C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */ + { 0x000006C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */ + { 0x000006C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */ + { 0x000006C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */ + { 0x000006C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */ + { 0x000006C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */ + { 0x000006C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */ + { 0x000006C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */ + { 0x000006C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */ + { 0x000006C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */ + { 0x000006CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */ + { 0x000006CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */ + { 0x000006CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */ + { 0x000006CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */ + { 0x000006CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */ + { 0x000006CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */ + { 0x00000700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */ + { 0x00000701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */ + { 0x00000702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */ + { 0x00000703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */ + { 0x00000704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */ + { 0x00000705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */ + { 0x00000706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */ + { 0x00000707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */ + { 0x00000708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */ + { 0x00000709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */ + { 0x0000070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */ + { 0x0000070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */ + { 0x0000070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */ + { 0x0000070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */ + { 0x0000070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */ + { 0x0000070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */ + { 0x00000710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */ + { 0x00000711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */ + { 0x00000712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */ + { 0x00000713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */ + { 0x00000714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */ + { 0x00000715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */ + { 0x00000716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */ + { 0x00000717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */ + { 0x00000718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */ + { 0x00000719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */ + { 0x0000071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */ + { 0x0000071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */ + { 0x0000071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */ + { 0x0000071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */ + { 0x0000071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */ + { 0x0000071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */ + { 0x00000720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */ + { 0x00000721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */ + { 0x00000722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */ + { 0x00000723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */ + { 0x00000724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */ + { 0x00000725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */ + { 0x00000726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */ + { 0x00000727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */ + { 0x00000728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */ + { 0x00000729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */ + { 0x0000072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */ + { 0x0000072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */ + { 0x0000072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */ + { 0x0000072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */ + { 0x0000072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */ + { 0x0000072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */ + { 0x00000730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */ + { 0x00000731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */ + { 0x00000732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */ + { 0x00000733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */ + { 0x00000734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */ + { 0x00000735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */ + { 0x00000736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */ + { 0x00000737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */ + { 0x00000738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */ + { 0x00000739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */ + { 0x0000073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */ + { 0x0000073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */ + { 0x0000073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */ + { 0x0000073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */ + { 0x0000073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */ + { 0x0000073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */ + { 0x00000740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */ + { 0x00000741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */ + { 0x00000742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */ + { 0x00000743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */ + { 0x00000744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */ + { 0x00000745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */ + { 0x00000746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */ + { 0x00000747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */ + { 0x00000748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */ + { 0x00000749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */ + { 0x0000074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */ + { 0x0000074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */ + { 0x0000074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */ + { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ + { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ + { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x000007C0, 0x0000 }, /* R1984 - SLIMTX1MIX Input 1 Source */ + { 0x000007C1, 0x0080 }, /* R1985 - SLIMTX1MIX Input 1 Volume */ + { 0x000007C2, 0x0000 }, /* R1986 - SLIMTX1MIX Input 2 Source */ + { 0x000007C3, 0x0080 }, /* R1987 - SLIMTX1MIX Input 2 Volume */ + { 0x000007C4, 0x0000 }, /* R1988 - SLIMTX1MIX Input 3 Source */ + { 0x000007C5, 0x0080 }, /* R1989 - SLIMTX1MIX Input 3 Volume */ + { 0x000007C6, 0x0000 }, /* R1990 - SLIMTX1MIX Input 4 Source */ + { 0x000007C7, 0x0080 }, /* R1991 - SLIMTX1MIX Input 4 Volume */ + { 0x000007C8, 0x0000 }, /* R1992 - SLIMTX2MIX Input 1 Source */ + { 0x000007C9, 0x0080 }, /* R1993 - SLIMTX2MIX Input 1 Volume */ + { 0x000007CA, 0x0000 }, /* R1994 - SLIMTX2MIX Input 2 Source */ + { 0x000007CB, 0x0080 }, /* R1995 - SLIMTX2MIX Input 2 Volume */ + { 0x000007CC, 0x0000 }, /* R1996 - SLIMTX2MIX Input 3 Source */ + { 0x000007CD, 0x0080 }, /* R1997 - SLIMTX2MIX Input 3 Volume */ + { 0x000007CE, 0x0000 }, /* R1998 - SLIMTX2MIX Input 4 Source */ + { 0x000007CF, 0x0080 }, /* R1999 - SLIMTX2MIX Input 4 Volume */ + { 0x000007D0, 0x0000 }, /* R2000 - SLIMTX3MIX Input 1 Source */ + { 0x000007D1, 0x0080 }, /* R2001 - SLIMTX3MIX Input 1 Volume */ + { 0x000007D2, 0x0000 }, /* R2002 - SLIMTX3MIX Input 2 Source */ + { 0x000007D3, 0x0080 }, /* R2003 - SLIMTX3MIX Input 2 Volume */ + { 0x000007D4, 0x0000 }, /* R2004 - SLIMTX3MIX Input 3 Source */ + { 0x000007D5, 0x0080 }, /* R2005 - SLIMTX3MIX Input 3 Volume */ + { 0x000007D6, 0x0000 }, /* R2006 - SLIMTX3MIX Input 4 Source */ + { 0x000007D7, 0x0080 }, /* R2007 - SLIMTX3MIX Input 4 Volume */ + { 0x000007D8, 0x0000 }, /* R2008 - SLIMTX4MIX Input 1 Source */ + { 0x000007D9, 0x0080 }, /* R2009 - SLIMTX4MIX Input 1 Volume */ + { 0x000007DA, 0x0000 }, /* R2010 - SLIMTX4MIX Input 2 Source */ + { 0x000007DB, 0x0080 }, /* R2011 - SLIMTX4MIX Input 2 Volume */ + { 0x000007DC, 0x0000 }, /* R2012 - SLIMTX4MIX Input 3 Source */ + { 0x000007DD, 0x0080 }, /* R2013 - SLIMTX4MIX Input 3 Volume */ + { 0x000007DE, 0x0000 }, /* R2014 - SLIMTX4MIX Input 4 Source */ + { 0x000007DF, 0x0080 }, /* R2015 - SLIMTX4MIX Input 4 Volume */ + { 0x000007E0, 0x0000 }, /* R2016 - SLIMTX5MIX Input 1 Source */ + { 0x000007E1, 0x0080 }, /* R2017 - SLIMTX5MIX Input 1 Volume */ + { 0x000007E2, 0x0000 }, /* R2018 - SLIMTX5MIX Input 2 Source */ + { 0x000007E3, 0x0080 }, /* R2019 - SLIMTX5MIX Input 2 Volume */ + { 0x000007E4, 0x0000 }, /* R2020 - SLIMTX5MIX Input 3 Source */ + { 0x000007E5, 0x0080 }, /* R2021 - SLIMTX5MIX Input 3 Volume */ + { 0x000007E6, 0x0000 }, /* R2022 - SLIMTX5MIX Input 4 Source */ + { 0x000007E7, 0x0080 }, /* R2023 - SLIMTX5MIX Input 4 Volume */ + { 0x000007E8, 0x0000 }, /* R2024 - SLIMTX6MIX Input 1 Source */ + { 0x000007E9, 0x0080 }, /* R2025 - SLIMTX6MIX Input 1 Volume */ + { 0x000007EA, 0x0000 }, /* R2026 - SLIMTX6MIX Input 2 Source */ + { 0x000007EB, 0x0080 }, /* R2027 - SLIMTX6MIX Input 2 Volume */ + { 0x000007EC, 0x0000 }, /* R2028 - SLIMTX6MIX Input 3 Source */ + { 0x000007ED, 0x0080 }, /* R2029 - SLIMTX6MIX Input 3 Volume */ + { 0x000007EE, 0x0000 }, /* R2030 - SLIMTX6MIX Input 4 Source */ + { 0x000007EF, 0x0080 }, /* R2031 - SLIMTX6MIX Input 4 Volume */ + { 0x000007F0, 0x0000 }, /* R2032 - SLIMTX7MIX Input 1 Source */ + { 0x000007F1, 0x0080 }, /* R2033 - SLIMTX7MIX Input 1 Volume */ + { 0x000007F2, 0x0000 }, /* R2034 - SLIMTX7MIX Input 2 Source */ + { 0x000007F3, 0x0080 }, /* R2035 - SLIMTX7MIX Input 2 Volume */ + { 0x000007F4, 0x0000 }, /* R2036 - SLIMTX7MIX Input 3 Source */ + { 0x000007F5, 0x0080 }, /* R2037 - SLIMTX7MIX Input 3 Volume */ + { 0x000007F6, 0x0000 }, /* R2038 - SLIMTX7MIX Input 4 Source */ + { 0x000007F7, 0x0080 }, /* R2039 - SLIMTX7MIX Input 4 Volume */ + { 0x000007F8, 0x0000 }, /* R2040 - SLIMTX8MIX Input 1 Source */ + { 0x000007F9, 0x0080 }, /* R2041 - SLIMTX8MIX Input 1 Volume */ + { 0x000007FA, 0x0000 }, /* R2042 - SLIMTX8MIX Input 2 Source */ + { 0x000007FB, 0x0080 }, /* R2043 - SLIMTX8MIX Input 2 Volume */ + { 0x000007FC, 0x0000 }, /* R2044 - SLIMTX8MIX Input 3 Source */ + { 0x000007FD, 0x0080 }, /* R2045 - SLIMTX8MIX Input 3 Volume */ + { 0x000007FE, 0x0000 }, /* R2046 - SLIMTX8MIX Input 4 Source */ + { 0x000007FF, 0x0080 }, /* R2047 - SLIMTX8MIX Input 4 Volume */ + { 0x00000880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */ + { 0x00000881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */ + { 0x00000882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */ + { 0x00000883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */ + { 0x00000884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */ + { 0x00000885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */ + { 0x00000886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */ + { 0x00000887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */ + { 0x00000888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */ + { 0x00000889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */ + { 0x0000088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */ + { 0x0000088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */ + { 0x0000088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */ + { 0x0000088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */ + { 0x0000088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */ + { 0x0000088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */ + { 0x00000890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */ + { 0x00000891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */ + { 0x00000892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */ + { 0x00000893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */ + { 0x00000894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */ + { 0x00000895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */ + { 0x00000896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */ + { 0x00000897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */ + { 0x00000898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */ + { 0x00000899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */ + { 0x0000089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */ + { 0x0000089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */ + { 0x0000089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */ + { 0x0000089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */ + { 0x0000089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */ + { 0x0000089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */ + { 0x000008C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */ + { 0x000008C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */ + { 0x000008C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */ + { 0x000008C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */ + { 0x000008C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */ + { 0x000008C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */ + { 0x000008C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */ + { 0x000008C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */ + { 0x000008C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */ + { 0x000008C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */ + { 0x000008CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */ + { 0x000008CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */ + { 0x000008CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */ + { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ + { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ + { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ + { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ + { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ + { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ + { 0x00000903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */ + { 0x00000904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */ + { 0x00000905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */ + { 0x00000906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */ + { 0x00000907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */ + { 0x00000908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */ + { 0x00000909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */ + { 0x0000090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */ + { 0x0000090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */ + { 0x0000090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */ + { 0x0000090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */ + { 0x0000090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */ + { 0x0000090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */ + { 0x00000910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */ + { 0x00000911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */ + { 0x00000912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */ + { 0x00000913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */ + { 0x00000914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */ + { 0x00000915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */ + { 0x00000916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */ + { 0x00000917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */ + { 0x00000918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */ + { 0x00000919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */ + { 0x0000091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */ + { 0x0000091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */ + { 0x0000091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */ + { 0x0000091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */ + { 0x0000091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */ + { 0x0000091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */ + { 0x00000B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */ + { 0x00000B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */ + { 0x00000B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */ + { 0x00000B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */ + { 0x00000B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */ + { 0x00000B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */ + { 0x00000B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */ + { 0x00000B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */ + { 0x00000C00, 0xA101 }, /* R3072 - GPIO1 CTRL */ + { 0x00000C01, 0xA101 }, /* R3073 - GPIO2 CTRL */ + { 0x00000C02, 0xA101 }, /* R3074 - GPIO3 CTRL */ + { 0x00000C03, 0xA101 }, /* R3075 - GPIO4 CTRL */ + { 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */ + { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */ + { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */ + { 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */ + { 0x00000C21, 0x0001 }, /* R3105 - Misc Pad Ctrl 2 */ + { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */ + { 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */ + { 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */ + { 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */ + { 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */ + { 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */ + { 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */ + { 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */ + { 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */ + { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ + { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ + { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ + { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ + { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ + { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ + { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ + { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ + { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */ + { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ + { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ + { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ + { 0x00000E13, 0x03FE }, /* R3603 - EQ1_4 */ + { 0x00000E14, 0x00E0 }, /* R3604 - EQ1_5 */ + { 0x00000E15, 0x1EC4 }, /* R3605 - EQ1_6 */ + { 0x00000E16, 0xF136 }, /* R3606 - EQ1_7 */ + { 0x00000E17, 0x0409 }, /* R3607 - EQ1_8 */ + { 0x00000E18, 0x04CC }, /* R3608 - EQ1_9 */ + { 0x00000E19, 0x1C9B }, /* R3609 - EQ1_10 */ + { 0x00000E1A, 0xF337 }, /* R3610 - EQ1_11 */ + { 0x00000E1B, 0x040B }, /* R3611 - EQ1_12 */ + { 0x00000E1C, 0x0CBB }, /* R3612 - EQ1_13 */ + { 0x00000E1D, 0x16F8 }, /* R3613 - EQ1_14 */ + { 0x00000E1E, 0xF7D9 }, /* R3614 - EQ1_15 */ + { 0x00000E1F, 0x040A }, /* R3615 - EQ1_16 */ + { 0x00000E20, 0x1F14 }, /* R3616 - EQ1_17 */ + { 0x00000E21, 0x058C }, /* R3617 - EQ1_18 */ + { 0x00000E22, 0x0563 }, /* R3618 - EQ1_19 */ + { 0x00000E23, 0x4000 }, /* R3619 - EQ1_20 */ + { 0x00000E24, 0x0B75 }, /* R3620 - EQ1_21 */ + { 0x00000E26, 0x6318 }, /* R3622 - EQ2_1 */ + { 0x00000E27, 0x6300 }, /* R3623 - EQ2_2 */ + { 0x00000E28, 0x0FC8 }, /* R3624 - EQ2_3 */ + { 0x00000E29, 0x03FE }, /* R3625 - EQ2_4 */ + { 0x00000E2A, 0x00E0 }, /* R3626 - EQ2_5 */ + { 0x00000E2B, 0x1EC4 }, /* R3627 - EQ2_6 */ + { 0x00000E2C, 0xF136 }, /* R3628 - EQ2_7 */ + { 0x00000E2D, 0x0409 }, /* R3629 - EQ2_8 */ + { 0x00000E2E, 0x04CC }, /* R3630 - EQ2_9 */ + { 0x00000E2F, 0x1C9B }, /* R3631 - EQ2_10 */ + { 0x00000E30, 0xF337 }, /* R3632 - EQ2_11 */ + { 0x00000E31, 0x040B }, /* R3633 - EQ2_12 */ + { 0x00000E32, 0x0CBB }, /* R3634 - EQ2_13 */ + { 0x00000E33, 0x16F8 }, /* R3635 - EQ2_14 */ + { 0x00000E34, 0xF7D9 }, /* R3636 - EQ2_15 */ + { 0x00000E35, 0x040A }, /* R3637 - EQ2_16 */ + { 0x00000E36, 0x1F14 }, /* R3638 - EQ2_17 */ + { 0x00000E37, 0x058C }, /* R3639 - EQ2_18 */ + { 0x00000E38, 0x0563 }, /* R3640 - EQ2_19 */ + { 0x00000E39, 0x4000 }, /* R3641 - EQ2_20 */ + { 0x00000E3A, 0x0B75 }, /* R3642 - EQ2_21 */ + { 0x00000E3C, 0x6318 }, /* R3644 - EQ3_1 */ + { 0x00000E3D, 0x6300 }, /* R3645 - EQ3_2 */ + { 0x00000E3E, 0x0FC8 }, /* R3646 - EQ3_3 */ + { 0x00000E3F, 0x03FE }, /* R3647 - EQ3_4 */ + { 0x00000E40, 0x00E0 }, /* R3648 - EQ3_5 */ + { 0x00000E41, 0x1EC4 }, /* R3649 - EQ3_6 */ + { 0x00000E42, 0xF136 }, /* R3650 - EQ3_7 */ + { 0x00000E43, 0x0409 }, /* R3651 - EQ3_8 */ + { 0x00000E44, 0x04CC }, /* R3652 - EQ3_9 */ + { 0x00000E45, 0x1C9B }, /* R3653 - EQ3_10 */ + { 0x00000E46, 0xF337 }, /* R3654 - EQ3_11 */ + { 0x00000E47, 0x040B }, /* R3655 - EQ3_12 */ + { 0x00000E48, 0x0CBB }, /* R3656 - EQ3_13 */ + { 0x00000E49, 0x16F8 }, /* R3657 - EQ3_14 */ + { 0x00000E4A, 0xF7D9 }, /* R3658 - EQ3_15 */ + { 0x00000E4B, 0x040A }, /* R3659 - EQ3_16 */ + { 0x00000E4C, 0x1F14 }, /* R3660 - EQ3_17 */ + { 0x00000E4D, 0x058C }, /* R3661 - EQ3_18 */ + { 0x00000E4E, 0x0563 }, /* R3662 - EQ3_19 */ + { 0x00000E4F, 0x4000 }, /* R3663 - EQ3_20 */ + { 0x00000E50, 0x0B75 }, /* R3664 - EQ3_21 */ + { 0x00000E52, 0x6318 }, /* R3666 - EQ4_1 */ + { 0x00000E53, 0x6300 }, /* R3667 - EQ4_2 */ + { 0x00000E54, 0x0FC8 }, /* R3668 - EQ4_3 */ + { 0x00000E55, 0x03FE }, /* R3669 - EQ4_4 */ + { 0x00000E56, 0x00E0 }, /* R3670 - EQ4_5 */ + { 0x00000E57, 0x1EC4 }, /* R3671 - EQ4_6 */ + { 0x00000E58, 0xF136 }, /* R3672 - EQ4_7 */ + { 0x00000E59, 0x0409 }, /* R3673 - EQ4_8 */ + { 0x00000E5A, 0x04CC }, /* R3674 - EQ4_9 */ + { 0x00000E5B, 0x1C9B }, /* R3675 - EQ4_10 */ + { 0x00000E5C, 0xF337 }, /* R3676 - EQ4_11 */ + { 0x00000E5D, 0x040B }, /* R3677 - EQ4_12 */ + { 0x00000E5E, 0x0CBB }, /* R3678 - EQ4_13 */ + { 0x00000E5F, 0x16F8 }, /* R3679 - EQ4_14 */ + { 0x00000E60, 0xF7D9 }, /* R3680 - EQ4_15 */ + { 0x00000E61, 0x040A }, /* R3681 - EQ4_16 */ + { 0x00000E62, 0x1F14 }, /* R3682 - EQ4_17 */ + { 0x00000E63, 0x058C }, /* R3683 - EQ4_18 */ + { 0x00000E64, 0x0563 }, /* R3684 - EQ4_19 */ + { 0x00000E65, 0x4000 }, /* R3685 - EQ4_20 */ + { 0x00000E66, 0x0B75 }, /* R3686 - EQ4_21 */ + { 0x00000E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */ + { 0x00000E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */ + { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ + { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ + { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ + { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ + { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ + { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ + { 0x00000EC5, 0x0000 }, /* R3781 - HPLPF2_2 */ + { 0x00000EC8, 0x0000 }, /* R3784 - HPLPF3_1 */ + { 0x00000EC9, 0x0000 }, /* R3785 - HPLPF3_2 */ + { 0x00000ECC, 0x0000 }, /* R3788 - HPLPF4_1 */ + { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ + { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ + { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ + { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ + { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ + { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ + { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ + { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ + { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ +}; + +static bool wm8997_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_CTRL_IF_I2C1_CFG_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_TONE_GENERATOR_1: + case ARIZONA_TONE_GENERATOR_2: + case ARIZONA_TONE_GENERATOR_3: + case ARIZONA_TONE_GENERATOR_4: + case ARIZONA_TONE_GENERATOR_5: + case ARIZONA_PWM_DRIVE_1: + case ARIZONA_PWM_DRIVE_2: + case ARIZONA_PWM_DRIVE_3: + case ARIZONA_WAKE_CONTROL: + case ARIZONA_SEQUENCE_CONTROL: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3: + case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4: + case ARIZONA_COMFORT_NOISE_GENERATOR: + case ARIZONA_HAPTICS_CONTROL_1: + case ARIZONA_HAPTICS_CONTROL_2: + case ARIZONA_HAPTICS_PHASE_1_INTENSITY: + case ARIZONA_HAPTICS_PHASE_1_DURATION: + case ARIZONA_HAPTICS_PHASE_2_INTENSITY: + case ARIZONA_HAPTICS_PHASE_2_DURATION: + case ARIZONA_HAPTICS_PHASE_3_INTENSITY: + case ARIZONA_HAPTICS_PHASE_3_DURATION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_CLOCK_32K_1: + case ARIZONA_SYSTEM_CLOCK_1: + case ARIZONA_SAMPLE_RATE_1: + case ARIZONA_SAMPLE_RATE_2: + case ARIZONA_SAMPLE_RATE_3: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_CLOCK_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_OUTPUT_SYSTEM_CLOCK: + case ARIZONA_OUTPUT_ASYNC_CLOCK: + case ARIZONA_RATE_ESTIMATOR_1: + case ARIZONA_RATE_ESTIMATOR_2: + case ARIZONA_RATE_ESTIMATOR_3: + case ARIZONA_RATE_ESTIMATOR_4: + case ARIZONA_RATE_ESTIMATOR_5: + case ARIZONA_FLL1_CONTROL_1: + case ARIZONA_FLL1_CONTROL_2: + case ARIZONA_FLL1_CONTROL_3: + case ARIZONA_FLL1_CONTROL_4: + case ARIZONA_FLL1_CONTROL_5: + case ARIZONA_FLL1_CONTROL_6: + case ARIZONA_FLL1_LOOP_FILTER_TEST_1: + case ARIZONA_FLL1_NCO_TEST_0: + case ARIZONA_FLL1_SYNCHRONISER_1: + case ARIZONA_FLL1_SYNCHRONISER_2: + case ARIZONA_FLL1_SYNCHRONISER_3: + case ARIZONA_FLL1_SYNCHRONISER_4: + case ARIZONA_FLL1_SYNCHRONISER_5: + case ARIZONA_FLL1_SYNCHRONISER_6: + case ARIZONA_FLL1_SPREAD_SPECTRUM: + case ARIZONA_FLL1_GPIO_CLOCK: + case ARIZONA_FLL2_CONTROL_1: + case ARIZONA_FLL2_CONTROL_2: + case ARIZONA_FLL2_CONTROL_3: + case ARIZONA_FLL2_CONTROL_4: + case ARIZONA_FLL2_CONTROL_5: + case ARIZONA_FLL2_CONTROL_6: + case ARIZONA_FLL2_LOOP_FILTER_TEST_1: + case ARIZONA_FLL2_NCO_TEST_0: + case ARIZONA_FLL2_SYNCHRONISER_1: + case ARIZONA_FLL2_SYNCHRONISER_2: + case ARIZONA_FLL2_SYNCHRONISER_3: + case ARIZONA_FLL2_SYNCHRONISER_4: + case ARIZONA_FLL2_SYNCHRONISER_5: + case ARIZONA_FLL2_SYNCHRONISER_6: + case ARIZONA_FLL2_SPREAD_SPECTRUM: + case ARIZONA_FLL2_GPIO_CLOCK: + case ARIZONA_MIC_CHARGE_PUMP_1: + case ARIZONA_LDO1_CONTROL_1: + case ARIZONA_LDO2_CONTROL_1: + case ARIZONA_MIC_BIAS_CTRL_1: + case ARIZONA_MIC_BIAS_CTRL_2: + case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_ACCESSORY_DETECT_MODE_1: + case ARIZONA_HEADPHONE_DETECT_1: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MIC_DETECT_1: + case ARIZONA_MIC_DETECT_2: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_NOISE_MIX_CONTROL_1: + case ARIZONA_ISOLATION_CONTROL: + case ARIZONA_JACK_DETECT_ANALOGUE: + case ARIZONA_INPUT_ENABLES: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_INPUT_RATE: + case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_IN1L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1L: + case ARIZONA_DMIC1L_CONTROL: + case ARIZONA_IN1R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1R: + case ARIZONA_DMIC1R_CONTROL: + case ARIZONA_IN2L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2L: + case ARIZONA_DMIC2L_CONTROL: + case ARIZONA_IN2R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2R: + case ARIZONA_DMIC2R_CONTROL: + case ARIZONA_OUTPUT_ENABLES_1: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_OUTPUT_RATE_1: + case ARIZONA_OUTPUT_VOLUME_RAMP: + case ARIZONA_OUTPUT_PATH_CONFIG_1L: + case ARIZONA_DAC_DIGITAL_VOLUME_1L: + case ARIZONA_DAC_VOLUME_LIMIT_1L: + case ARIZONA_NOISE_GATE_SELECT_1L: + case ARIZONA_OUTPUT_PATH_CONFIG_1R: + case ARIZONA_DAC_DIGITAL_VOLUME_1R: + case ARIZONA_DAC_VOLUME_LIMIT_1R: + case ARIZONA_NOISE_GATE_SELECT_1R: + case ARIZONA_OUTPUT_PATH_CONFIG_3L: + case ARIZONA_DAC_DIGITAL_VOLUME_3L: + case ARIZONA_DAC_VOLUME_LIMIT_3L: + case ARIZONA_NOISE_GATE_SELECT_3L: + case ARIZONA_OUTPUT_PATH_CONFIG_4L: + case ARIZONA_DAC_DIGITAL_VOLUME_4L: + case ARIZONA_OUT_VOLUME_4L: + case ARIZONA_NOISE_GATE_SELECT_4L: + case ARIZONA_OUTPUT_PATH_CONFIG_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5L: + case ARIZONA_DAC_VOLUME_LIMIT_5L: + case ARIZONA_NOISE_GATE_SELECT_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5R: + case ARIZONA_DAC_VOLUME_LIMIT_5R: + case ARIZONA_NOISE_GATE_SELECT_5R: + case ARIZONA_DAC_AEC_CONTROL_1: + case ARIZONA_NOISE_GATE_CONTROL: + case ARIZONA_PDM_SPK1_CTRL_1: + case ARIZONA_PDM_SPK1_CTRL_2: + case ARIZONA_AIF1_BCLK_CTRL: + case ARIZONA_AIF1_TX_PIN_CTRL: + case ARIZONA_AIF1_RX_PIN_CTRL: + case ARIZONA_AIF1_RATE_CTRL: + case ARIZONA_AIF1_FORMAT: + case ARIZONA_AIF1_TX_BCLK_RATE: + case ARIZONA_AIF1_RX_BCLK_RATE: + case ARIZONA_AIF1_FRAME_CTRL_1: + case ARIZONA_AIF1_FRAME_CTRL_2: + case ARIZONA_AIF1_FRAME_CTRL_3: + case ARIZONA_AIF1_FRAME_CTRL_4: + case ARIZONA_AIF1_FRAME_CTRL_5: + case ARIZONA_AIF1_FRAME_CTRL_6: + case ARIZONA_AIF1_FRAME_CTRL_7: + case ARIZONA_AIF1_FRAME_CTRL_8: + case ARIZONA_AIF1_FRAME_CTRL_9: + case ARIZONA_AIF1_FRAME_CTRL_10: + case ARIZONA_AIF1_FRAME_CTRL_11: + case ARIZONA_AIF1_FRAME_CTRL_12: + case ARIZONA_AIF1_FRAME_CTRL_13: + case ARIZONA_AIF1_FRAME_CTRL_14: + case ARIZONA_AIF1_FRAME_CTRL_15: + case ARIZONA_AIF1_FRAME_CTRL_16: + case ARIZONA_AIF1_FRAME_CTRL_17: + case ARIZONA_AIF1_FRAME_CTRL_18: + case ARIZONA_AIF1_TX_ENABLES: + case ARIZONA_AIF1_RX_ENABLES: + case ARIZONA_AIF2_BCLK_CTRL: + case ARIZONA_AIF2_TX_PIN_CTRL: + case ARIZONA_AIF2_RX_PIN_CTRL: + case ARIZONA_AIF2_RATE_CTRL: + case ARIZONA_AIF2_FORMAT: + case ARIZONA_AIF2_TX_BCLK_RATE: + case ARIZONA_AIF2_RX_BCLK_RATE: + case ARIZONA_AIF2_FRAME_CTRL_1: + case ARIZONA_AIF2_FRAME_CTRL_2: + case ARIZONA_AIF2_FRAME_CTRL_3: + case ARIZONA_AIF2_FRAME_CTRL_4: + case ARIZONA_AIF2_FRAME_CTRL_11: + case ARIZONA_AIF2_FRAME_CTRL_12: + case ARIZONA_AIF2_TX_ENABLES: + case ARIZONA_AIF2_RX_ENABLES: + case ARIZONA_SLIMBUS_FRAMER_REF_GEAR: + case ARIZONA_SLIMBUS_RATES_1: + case ARIZONA_SLIMBUS_RATES_2: + case ARIZONA_SLIMBUS_RATES_3: + case ARIZONA_SLIMBUS_RATES_4: + case ARIZONA_SLIMBUS_RATES_5: + case ARIZONA_SLIMBUS_RATES_6: + case ARIZONA_SLIMBUS_RATES_7: + case ARIZONA_SLIMBUS_RATES_8: + case ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_PWM1MIX_INPUT_1_SOURCE: + case ARIZONA_PWM1MIX_INPUT_1_VOLUME: + case ARIZONA_PWM1MIX_INPUT_2_SOURCE: + case ARIZONA_PWM1MIX_INPUT_2_VOLUME: + case ARIZONA_PWM1MIX_INPUT_3_SOURCE: + case ARIZONA_PWM1MIX_INPUT_3_VOLUME: + case ARIZONA_PWM1MIX_INPUT_4_SOURCE: + case ARIZONA_PWM1MIX_INPUT_4_VOLUME: + case ARIZONA_PWM2MIX_INPUT_1_SOURCE: + case ARIZONA_PWM2MIX_INPUT_1_VOLUME: + case ARIZONA_PWM2MIX_INPUT_2_SOURCE: + case ARIZONA_PWM2MIX_INPUT_2_VOLUME: + case ARIZONA_PWM2MIX_INPUT_3_SOURCE: + case ARIZONA_PWM2MIX_INPUT_3_VOLUME: + case ARIZONA_PWM2MIX_INPUT_4_SOURCE: + case ARIZONA_PWM2MIX_INPUT_4_VOLUME: + case ARIZONA_MICMIX_INPUT_1_SOURCE: + case ARIZONA_MICMIX_INPUT_1_VOLUME: + case ARIZONA_MICMIX_INPUT_2_SOURCE: + case ARIZONA_MICMIX_INPUT_2_VOLUME: + case ARIZONA_MICMIX_INPUT_3_SOURCE: + case ARIZONA_MICMIX_INPUT_3_VOLUME: + case ARIZONA_MICMIX_INPUT_4_SOURCE: + case ARIZONA_MICMIX_INPUT_4_VOLUME: + case ARIZONA_NOISEMIX_INPUT_1_SOURCE: + case ARIZONA_NOISEMIX_INPUT_1_VOLUME: + case ARIZONA_NOISEMIX_INPUT_2_SOURCE: + case ARIZONA_NOISEMIX_INPUT_2_VOLUME: + case ARIZONA_NOISEMIX_INPUT_3_SOURCE: + case ARIZONA_NOISEMIX_INPUT_3_VOLUME: + case ARIZONA_NOISEMIX_INPUT_4_SOURCE: + case ARIZONA_NOISEMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME: + case ARIZONA_EQ1MIX_INPUT_1_SOURCE: + case ARIZONA_EQ1MIX_INPUT_1_VOLUME: + case ARIZONA_EQ1MIX_INPUT_2_SOURCE: + case ARIZONA_EQ1MIX_INPUT_2_VOLUME: + case ARIZONA_EQ1MIX_INPUT_3_SOURCE: + case ARIZONA_EQ1MIX_INPUT_3_VOLUME: + case ARIZONA_EQ1MIX_INPUT_4_SOURCE: + case ARIZONA_EQ1MIX_INPUT_4_VOLUME: + case ARIZONA_EQ2MIX_INPUT_1_SOURCE: + case ARIZONA_EQ2MIX_INPUT_1_VOLUME: + case ARIZONA_EQ2MIX_INPUT_2_SOURCE: + case ARIZONA_EQ2MIX_INPUT_2_VOLUME: + case ARIZONA_EQ2MIX_INPUT_3_SOURCE: + case ARIZONA_EQ2MIX_INPUT_3_VOLUME: + case ARIZONA_EQ2MIX_INPUT_4_SOURCE: + case ARIZONA_EQ2MIX_INPUT_4_VOLUME: + case ARIZONA_EQ3MIX_INPUT_1_SOURCE: + case ARIZONA_EQ3MIX_INPUT_1_VOLUME: + case ARIZONA_EQ3MIX_INPUT_2_SOURCE: + case ARIZONA_EQ3MIX_INPUT_2_VOLUME: + case ARIZONA_EQ3MIX_INPUT_3_SOURCE: + case ARIZONA_EQ3MIX_INPUT_3_VOLUME: + case ARIZONA_EQ3MIX_INPUT_4_SOURCE: + case ARIZONA_EQ3MIX_INPUT_4_VOLUME: + case ARIZONA_EQ4MIX_INPUT_1_SOURCE: + case ARIZONA_EQ4MIX_INPUT_1_VOLUME: + case ARIZONA_EQ4MIX_INPUT_2_SOURCE: + case ARIZONA_EQ4MIX_INPUT_2_VOLUME: + case ARIZONA_EQ4MIX_INPUT_3_SOURCE: + case ARIZONA_EQ4MIX_INPUT_3_VOLUME: + case ARIZONA_EQ4MIX_INPUT_4_SOURCE: + case ARIZONA_EQ4MIX_INPUT_4_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_4_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_4_VOLUME: + case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE: + case ARIZONA_GPIO1_CTRL: + case ARIZONA_GPIO2_CTRL: + case ARIZONA_GPIO3_CTRL: + case ARIZONA_GPIO4_CTRL: + case ARIZONA_GPIO5_CTRL: + case ARIZONA_IRQ_CTRL_1: + case ARIZONA_GPIO_DEBOUNCE_CONFIG: + case ARIZONA_MISC_PAD_CTRL_1: + case ARIZONA_MISC_PAD_CTRL_2: + case ARIZONA_MISC_PAD_CTRL_3: + case ARIZONA_MISC_PAD_CTRL_4: + case ARIZONA_MISC_PAD_CTRL_5: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_INTERRUPT_STATUS_1_MASK: + case ARIZONA_INTERRUPT_STATUS_3_MASK: + case ARIZONA_INTERRUPT_STATUS_4_MASK: + case ARIZONA_INTERRUPT_STATUS_5_MASK: + case ARIZONA_INTERRUPT_CONTROL: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_IRQ2_STATUS_1_MASK: + case ARIZONA_IRQ2_STATUS_3_MASK: + case ARIZONA_IRQ2_STATUS_4_MASK: + case ARIZONA_IRQ2_STATUS_5_MASK: + case ARIZONA_IRQ2_CONTROL: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_MASK_IRQ1: + case ARIZONA_AOD_IRQ_MASK_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_JACK_DETECT_DEBOUNCE: + case ARIZONA_FX_CTRL1: + case ARIZONA_FX_CTRL2: + case ARIZONA_EQ1_1: + case ARIZONA_EQ1_2: + case ARIZONA_EQ1_3: + case ARIZONA_EQ1_4: + case ARIZONA_EQ1_5: + case ARIZONA_EQ1_6: + case ARIZONA_EQ1_7: + case ARIZONA_EQ1_8: + case ARIZONA_EQ1_9: + case ARIZONA_EQ1_10: + case ARIZONA_EQ1_11: + case ARIZONA_EQ1_12: + case ARIZONA_EQ1_13: + case ARIZONA_EQ1_14: + case ARIZONA_EQ1_15: + case ARIZONA_EQ1_16: + case ARIZONA_EQ1_17: + case ARIZONA_EQ1_18: + case ARIZONA_EQ1_19: + case ARIZONA_EQ1_20: + case ARIZONA_EQ1_21: + case ARIZONA_EQ2_1: + case ARIZONA_EQ2_2: + case ARIZONA_EQ2_3: + case ARIZONA_EQ2_4: + case ARIZONA_EQ2_5: + case ARIZONA_EQ2_6: + case ARIZONA_EQ2_7: + case ARIZONA_EQ2_8: + case ARIZONA_EQ2_9: + case ARIZONA_EQ2_10: + case ARIZONA_EQ2_11: + case ARIZONA_EQ2_12: + case ARIZONA_EQ2_13: + case ARIZONA_EQ2_14: + case ARIZONA_EQ2_15: + case ARIZONA_EQ2_16: + case ARIZONA_EQ2_17: + case ARIZONA_EQ2_18: + case ARIZONA_EQ2_19: + case ARIZONA_EQ2_20: + case ARIZONA_EQ2_21: + case ARIZONA_EQ3_1: + case ARIZONA_EQ3_2: + case ARIZONA_EQ3_3: + case ARIZONA_EQ3_4: + case ARIZONA_EQ3_5: + case ARIZONA_EQ3_6: + case ARIZONA_EQ3_7: + case ARIZONA_EQ3_8: + case ARIZONA_EQ3_9: + case ARIZONA_EQ3_10: + case ARIZONA_EQ3_11: + case ARIZONA_EQ3_12: + case ARIZONA_EQ3_13: + case ARIZONA_EQ3_14: + case ARIZONA_EQ3_15: + case ARIZONA_EQ3_16: + case ARIZONA_EQ3_17: + case ARIZONA_EQ3_18: + case ARIZONA_EQ3_19: + case ARIZONA_EQ3_20: + case ARIZONA_EQ3_21: + case ARIZONA_EQ4_1: + case ARIZONA_EQ4_2: + case ARIZONA_EQ4_3: + case ARIZONA_EQ4_4: + case ARIZONA_EQ4_5: + case ARIZONA_EQ4_6: + case ARIZONA_EQ4_7: + case ARIZONA_EQ4_8: + case ARIZONA_EQ4_9: + case ARIZONA_EQ4_10: + case ARIZONA_EQ4_11: + case ARIZONA_EQ4_12: + case ARIZONA_EQ4_13: + case ARIZONA_EQ4_14: + case ARIZONA_EQ4_15: + case ARIZONA_EQ4_16: + case ARIZONA_EQ4_17: + case ARIZONA_EQ4_18: + case ARIZONA_EQ4_19: + case ARIZONA_EQ4_20: + case ARIZONA_EQ4_21: + case ARIZONA_DRC1_CTRL1: + case ARIZONA_DRC1_CTRL2: + case ARIZONA_DRC1_CTRL3: + case ARIZONA_DRC1_CTRL4: + case ARIZONA_DRC1_CTRL5: + case ARIZONA_HPLPF1_1: + case ARIZONA_HPLPF1_2: + case ARIZONA_HPLPF2_1: + case ARIZONA_HPLPF2_2: + case ARIZONA_HPLPF3_1: + case ARIZONA_HPLPF3_2: + case ARIZONA_HPLPF4_1: + case ARIZONA_HPLPF4_2: + case ARIZONA_ISRC_1_CTRL_1: + case ARIZONA_ISRC_1_CTRL_2: + case ARIZONA_ISRC_1_CTRL_3: + case ARIZONA_ISRC_2_CTRL_1: + case ARIZONA_ISRC_2_CTRL_2: + case ARIZONA_ISRC_2_CTRL_3: + return true; + default: + return false; + } +} + +static bool wm8997_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_FX_CTRL2: + return true; + default: + return false; + } +} + +#define WM8997_MAX_REGISTER 0x31ff + +const struct regmap_config wm8997_i2c_regmap = { + .reg_bits = 32, + .val_bits = 16, + + .max_register = WM8997_MAX_REGISTER, + .readable_reg = wm8997_readable_register, + .volatile_reg = wm8997_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm8997_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm8997_reg_default), +}; +EXPORT_SYMBOL_GPL(wm8997_i2c_regmap); diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h index f797bb9b8b56..5cf8b91ce996 100644 --- a/include/linux/mfd/arizona/core.h +++ b/include/linux/mfd/arizona/core.h @@ -23,6 +23,7 @@ enum arizona_type { WM5102 = 1, WM5110 = 2, + WM8997 = 3, }; #define ARIZONA_IRQ_GP1 0 @@ -121,5 +122,6 @@ int arizona_set_irq_wake(struct arizona *arizona, int irq, int on); int wm5102_patch(struct arizona *arizona); int wm5110_patch(struct arizona *arizona); +int wm8997_patch(struct arizona *arizona); #endif -- GitLab From 8941bbcd572a8860ad03c76e2f3d1dafa820b842 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:36 -0400 Subject: [PATCH 1347/2900] tipc: update code comments to reflect new uapi header path Files tipc.h and tipc_config.h were moved to uapi directory, but the corresponding comments were not updated at the same time. Signed-off-by: Ying Xue Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- include/uapi/linux/tipc.h | 2 +- include/uapi/linux/tipc_config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/tipc.h b/include/uapi/linux/tipc.h index f2d90091cc20..852373d27dbb 100644 --- a/include/uapi/linux/tipc.h +++ b/include/uapi/linux/tipc.h @@ -1,5 +1,5 @@ /* - * include/linux/tipc.h: Include file for TIPC socket interface + * include/uapi/linux/tipc.h: Header for TIPC socket interface * * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005, 2010-2011, Wind River Systems diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index 0b1e3f218a36..6b0bff09b3a7 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h @@ -1,5 +1,5 @@ /* - * include/linux/tipc_config.h: Include file for TIPC configuration interface + * include/uapi/linux/tipc_config.h: Header for TIPC configuration interface * * Copyright (c) 2003-2006, Ericsson AB * Copyright (c) 2005-2007, 2010-2011, Wind River Systems -- GitLab From cc79dd1ba9c1021c2ac6ae200a65ec38ee8db351 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:37 -0400 Subject: [PATCH 1348/2900] tipc: change socket buffer overflow control to respect sk_rcvbuf As per feedback from the netdev community, we change the buffer overflow protection algorithm in receiving sockets so that it always respects the nominal upper limit set in sk_rcvbuf. Instead of scaling up from a small sk_rcvbuf value, which leads to violation of the configured sk_rcvbuf limit, we now calculate the weighted per-message limit by scaling down from a much bigger value, still in the same field, according to the importance priority of the received message. To allow for administrative tunability of the socket receive buffer size, we create a tipc_rmem sysctl variable to allow the user to configure an even bigger value via sysctl command. It is a size of three (min/default/max) to be consistent with things like tcp_rmem. By default, the value initialized in tipc_rmem[1] is equal to the receive socket size needed by a TIPC_CRITICAL_IMPORTANCE message. This value is also set as the default value of sk_rcvbuf. Originally-by: Jon Maloy Cc: Neil Horman Cc: Jon Maloy [Ying: added sysctl variation to Jon's original patch] Signed-off-by: Ying Xue [PG: don't compile sysctl.c if not config'd; add Documentation] Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 17 +++++++++- net/tipc/Makefile | 1 + net/tipc/core.c | 12 +++++-- net/tipc/core.h | 9 +++++ net/tipc/port.h | 2 ++ net/tipc/socket.c | 19 ++++++----- net/tipc/sysctl.c | 64 ++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 net/tipc/sysctl.c diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 85ab72dcdc3c..5369879eafe2 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -26,7 +26,7 @@ Table : Subdirectories in /proc/sys/net ipv4 IP version 4 x25 X.25 protocol ipx IPX token-ring IBM token ring bridge Bridging decnet DEC net - ipv6 IP version 6 + ipv6 IP version 6 tipc TIPC .............................................................................. 1. /proc/sys/net/core - Network core options @@ -207,3 +207,18 @@ IPX. The /proc/net/ipx_route table holds a list of IPX routes. For each route it gives the destination network, the router node (or Directly) and the network address of the router (or Connected) for internal networks. + +6. TIPC +------------------------------------------------------- + +The TIPC protocol now has a tunable for the receive memory, similar to the +tcp_rmem - i.e. a vector of 3 INTEGERs: (min, default, max) + + # cat /proc/sys/net/tipc/tipc_rmem + 4252725 34021800 68043600 + # + +The max value is set to CONN_OVERLOAD_LIMIT, and the default and min values +are scaled (shifted) versions of that same value. Note that the min value +is not at this point in time used in any meaningful way, but the triplet is +preserved in order to be consistent with things like tcp_rmem. diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 4df8e02d9008..02636d0a90cf 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -11,3 +11,4 @@ tipc-y += addr.o bcast.o bearer.o config.o \ socket.o log.o eth_media.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o +tipc-$(CONFIG_SYSCTL) += sysctl.o diff --git a/net/tipc/core.c b/net/tipc/core.c index 7ec2c1eb94f1..b0e42a087291 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -39,6 +39,7 @@ #include "name_table.h" #include "subscr.h" #include "config.h" +#include "port.h" #include @@ -50,7 +51,7 @@ u32 tipc_own_addr __read_mostly; int tipc_max_ports __read_mostly; int tipc_net_id __read_mostly; int tipc_remote_management __read_mostly; - +int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ /** * tipc_buf_acquire - creates a TIPC message buffer @@ -118,6 +119,7 @@ static void tipc_core_stop(void) tipc_nametbl_stop(); tipc_ref_table_stop(); tipc_socket_stop(); + tipc_unregister_sysctl(); } /** @@ -142,13 +144,14 @@ static int tipc_core_start(void) res = tipc_netlink_start(); if (!res) res = tipc_socket_init(); + if (!res) + res = tipc_register_sysctl(); if (res) tipc_core_stop(); return res; } - static int __init tipc_init(void) { int res; @@ -160,6 +163,11 @@ static int __init tipc_init(void) tipc_max_ports = CONFIG_TIPC_PORTS; tipc_net_id = 4711; + sysctl_tipc_rmem[0] = CONN_OVERLOAD_LIMIT >> 4 << TIPC_LOW_IMPORTANCE; + sysctl_tipc_rmem[1] = CONN_OVERLOAD_LIMIT >> 4 << + TIPC_CRITICAL_IMPORTANCE; + sysctl_tipc_rmem[2] = CONN_OVERLOAD_LIMIT; + res = tipc_core_start(); if (res) pr_err("Unable to start in single node mode\n"); diff --git a/net/tipc/core.h b/net/tipc/core.h index 0207db04179a..fe7f2b7c19fe 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -80,6 +80,7 @@ extern u32 tipc_own_addr __read_mostly; extern int tipc_max_ports __read_mostly; extern int tipc_net_id __read_mostly; extern int tipc_remote_management __read_mostly; +extern int sysctl_tipc_rmem[3] __read_mostly; /* * Other global variables @@ -97,6 +98,14 @@ extern void tipc_netlink_stop(void); extern int tipc_socket_init(void); extern void tipc_socket_stop(void); +#ifdef CONFIG_SYSCTL +extern int tipc_register_sysctl(void); +extern void tipc_unregister_sysctl(void); +#else +#define tipc_register_sysctl() 0 +#define tipc_unregister_sysctl() +#endif + /* * TIPC timer and signal code */ diff --git a/net/tipc/port.h b/net/tipc/port.h index fb66e2e5f4d1..2485649c408a 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -43,6 +43,8 @@ #include "node_subscr.h" #define TIPC_FLOW_CONTROL_WIN 512 +#define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \ + SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, struct sk_buff **buf, unsigned char const *data, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 515ce38e4f4c..aba4255f297b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -43,8 +43,6 @@ #define SS_LISTENING -1 /* socket is listening */ #define SS_READY -2 /* socket is connectionless */ -#define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \ - SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ struct tipc_sock { @@ -203,6 +201,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, sock_init_data(sock, sk); sk->sk_backlog_rcv = backlog_rcv; + sk->sk_rcvbuf = sysctl_tipc_rmem[1]; sk->sk_data_ready = tipc_data_ready; sk->sk_write_space = tipc_write_space; tipc_sk(sk)->p = tp_ptr; @@ -1233,10 +1232,10 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) * For all connectionless messages, by default new queue limits are * as belows: * - * TIPC_LOW_IMPORTANCE (5MB) - * TIPC_MEDIUM_IMPORTANCE (10MB) - * TIPC_HIGH_IMPORTANCE (20MB) - * TIPC_CRITICAL_IMPORTANCE (40MB) + * TIPC_LOW_IMPORTANCE (4 MB) + * TIPC_MEDIUM_IMPORTANCE (8 MB) + * TIPC_HIGH_IMPORTANCE (16 MB) + * TIPC_CRITICAL_IMPORTANCE (32 MB) * * Returns overload limit according to corresponding message importance */ @@ -1246,9 +1245,10 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) unsigned int limit; if (msg_connected(msg)) - limit = CONN_OVERLOAD_LIMIT; + limit = sysctl_tipc_rmem[2]; else - limit = sk->sk_rcvbuf << (msg_importance(msg) + 5); + limit = sk->sk_rcvbuf >> TIPC_CRITICAL_IMPORTANCE << + msg_importance(msg); return limit; } @@ -1847,7 +1847,8 @@ static const struct net_proto_family tipc_family_ops = { static struct proto tipc_proto = { .name = "TIPC", .owner = THIS_MODULE, - .obj_size = sizeof(struct tipc_sock) + .obj_size = sizeof(struct tipc_sock), + .sysctl_rmem = sysctl_tipc_rmem }; /** diff --git a/net/tipc/sysctl.c b/net/tipc/sysctl.c new file mode 100644 index 000000000000..f3fef93325a8 --- /dev/null +++ b/net/tipc/sysctl.c @@ -0,0 +1,64 @@ +/* + * net/tipc/sysctl.c: sysctl interface to TIPC subsystem + * + * Copyright (c) 2013, Wind River Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "core.h" + +#include + +static struct ctl_table_header *tipc_ctl_hdr; + +static struct ctl_table tipc_table[] = { + { + .procname = "tipc_rmem", + .data = &sysctl_tipc_rmem, + .maxlen = sizeof(sysctl_tipc_rmem), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + {} +}; + +int tipc_register_sysctl(void) +{ + tipc_ctl_hdr = register_net_sysctl(&init_net, "net/tipc", tipc_table); + if (tipc_ctl_hdr == NULL) + return -ENOMEM; + return 0; +} + +void tipc_unregister_sysctl(void) +{ + unregister_net_sysctl_table(tipc_ctl_hdr); +} -- GitLab From 5d21cb70db0122507cd18f58b4a9112583c1e075 Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Mon, 17 Jun 2013 10:54:38 -0400 Subject: [PATCH 1349/2900] tipc: allow implicit connect for stream sockets TIPC's implied connect feature, aka piggyback connect, allows applications to save one syscall and all SYN/SYN-ACK signalling overhead when setting up a connection. Until now, this has only been supported for SEQPACKET sockets. Here, we make it possible to use this feature even with stream sockets. At the connecting side, the connection is completed when the first data message arrives from the accepting peer. This means that we must allow the connecting user to call blocking recv() before the socket has reached state SS_CONNECTED. So we must must relax the state machine check at recv_stream(), and allow the recv() call even if socket is in state SS_CONNECTING. Signed-off-by: Erik Hugne Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/socket.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index aba4255f297b..d5fa708f037d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -518,8 +518,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, res = -EISCONN; goto exit; } - if ((tport->published) || - ((sock->type == SOCK_STREAM) && (total_len != 0))) { + if (tport->published) { res = -EOPNOTSUPP; goto exit; } @@ -1010,8 +1009,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, lock_sock(sk); - if (unlikely((sock->state == SS_UNCONNECTED) || - (sock->state == SS_CONNECTING))) { + if (unlikely((sock->state == SS_UNCONNECTED))) { res = -ENOTCONN; goto exit; } -- GitLab From c5fa7b3cf3cb22e4ac60485fc2dc187fe012910f Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:39 -0400 Subject: [PATCH 1350/2900] tipc: introduce new TIPC server infrastructure TIPC has two internal servers, one providing a subscription service for topology events, and another providing the configuration interface. These servers have previously been running in BH context, accessing the TIPC-port (aka native) API directly. Apart from these servers, even the TIPC socket implementation is partially built on this API. As this API may simultaneously be called via different paths and in different contexts, a complex and costly lock policiy is required in order to protect TIPC internal resources. To eliminate the need for this complex lock policiy, we introduce a new, generic service API that uses kernel sockets for message passing instead of the native API. Once the toplogy and configuration servers are converted to use this new service, all code pertaining to the native API can be removed. This entails a significant reduction in code amount and complexity, and opens up for a complete rework of the locking policy in TIPC. The new service also solves another problem: As the current topology server works in BH context, it cannot easily be blocked when sending of events fails due to congestion. In such cases events may have to be silently dropped, something that is unacceptable. Therefore, the new service keeps a dedicated outbound queue receiving messages from BH context. Once messages are inserted into this queue, we will immediately schedule a work from a special workqueue. This way, messages/events from the topology server are in reality sent in process context, and the server can block if necessary. Analogously, there is a new workqueue for receiving messages. Once a notification about an arriving message is received in BH context, we schedule a work from the receive workqueue to do the job of receiving the message in process context. As both sending and receive messages are now finished in processes, subscribed events cannot be dropped any more. As of this commit, this new server infrastructure is built, but not actually yet called by the existing TIPC code, but since the conversion changes required in order to use it are significant, the addition is kept here as a separate commit. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/Makefile | 2 +- net/tipc/core.h | 8 +- net/tipc/server.c | 596 ++++++++++++++++++++++++++++++++++++++++++++++ net/tipc/server.h | 94 ++++++++ net/tipc/socket.c | 99 +++++++- 5 files changed, 789 insertions(+), 10 deletions(-) create mode 100644 net/tipc/server.c create mode 100644 net/tipc/server.h diff --git a/net/tipc/Makefile b/net/tipc/Makefile index 02636d0a90cf..b282f7130d2b 100644 --- a/net/tipc/Makefile +++ b/net/tipc/Makefile @@ -8,7 +8,7 @@ tipc-y += addr.o bcast.o bearer.o config.o \ core.o handler.o link.o discover.o msg.o \ name_distr.o subscr.o name_table.o net.o \ netlink.o node.o node_subscr.o port.o ref.o \ - socket.o log.o eth_media.o + socket.o log.o eth_media.o server.o tipc-$(CONFIG_TIPC_MEDIA_IB) += ib_media.o tipc-$(CONFIG_SYSCTL) += sysctl.o diff --git a/net/tipc/core.h b/net/tipc/core.h index fe7f2b7c19fe..be72f8cebc53 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h @@ -1,8 +1,8 @@ /* * net/tipc/core.h: Include file for TIPC global declarations * - * Copyright (c) 2005-2006, Ericsson AB - * Copyright (c) 2005-2007, 2010-2011, Wind River Systems + * Copyright (c) 2005-2006, 2013 Ericsson AB + * Copyright (c) 2005-2007, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,6 +97,10 @@ extern int tipc_netlink_start(void); extern void tipc_netlink_stop(void); extern int tipc_socket_init(void); extern void tipc_socket_stop(void); +extern int tipc_sock_create_local(int type, struct socket **res); +extern void tipc_sock_release_local(struct socket *sock); +extern int tipc_sock_accept_local(struct socket *sock, + struct socket **newsock, int flags); #ifdef CONFIG_SYSCTL extern int tipc_register_sysctl(void); diff --git a/net/tipc/server.c b/net/tipc/server.c new file mode 100644 index 000000000000..19da5abe0fa6 --- /dev/null +++ b/net/tipc/server.c @@ -0,0 +1,596 @@ +/* + * net/tipc/server.c: TIPC server infrastructure + * + * Copyright (c) 2012-2013, Wind River Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "server.h" +#include "core.h" +#include + +/* Number of messages to send before rescheduling */ +#define MAX_SEND_MSG_COUNT 25 +#define MAX_RECV_MSG_COUNT 25 +#define CF_CONNECTED 1 + +#define sock2con(x) ((struct tipc_conn *)(x)->sk_user_data) + +/** + * struct tipc_conn - TIPC connection structure + * @kref: reference counter to connection object + * @conid: connection identifier + * @sock: socket handler associated with connection + * @flags: indicates connection state + * @server: pointer to connected server + * @rwork: receive work item + * @usr_data: user-specified field + * @rx_action: what to do when connection socket is active + * @outqueue: pointer to first outbound message in queue + * @outqueue_lock: controll access to the outqueue + * @outqueue: list of connection objects for its server + * @swork: send work item + */ +struct tipc_conn { + struct kref kref; + int conid; + struct socket *sock; + unsigned long flags; + struct tipc_server *server; + struct work_struct rwork; + int (*rx_action) (struct tipc_conn *con); + void *usr_data; + struct list_head outqueue; + spinlock_t outqueue_lock; + struct work_struct swork; +}; + +/* An entry waiting to be sent */ +struct outqueue_entry { + struct list_head list; + struct kvec iov; + struct sockaddr_tipc dest; +}; + +static void tipc_recv_work(struct work_struct *work); +static void tipc_send_work(struct work_struct *work); +static void tipc_clean_outqueues(struct tipc_conn *con); + +static void tipc_conn_kref_release(struct kref *kref) +{ + struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); + struct tipc_server *s = con->server; + + if (con->sock) { + tipc_sock_release_local(con->sock); + con->sock = NULL; + } + + tipc_clean_outqueues(con); + + if (con->conid) + s->tipc_conn_shutdown(con->conid, con->usr_data); + + kfree(con); +} + +static void conn_put(struct tipc_conn *con) +{ + kref_put(&con->kref, tipc_conn_kref_release); +} + +static void conn_get(struct tipc_conn *con) +{ + kref_get(&con->kref); +} + +static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid) +{ + struct tipc_conn *con; + + spin_lock_bh(&s->idr_lock); + con = idr_find(&s->conn_idr, conid); + if (con) + conn_get(con); + spin_unlock_bh(&s->idr_lock); + return con; +} + +static void sock_data_ready(struct sock *sk, int unused) +{ + struct tipc_conn *con; + + read_lock(&sk->sk_callback_lock); + con = sock2con(sk); + if (con && test_bit(CF_CONNECTED, &con->flags)) { + conn_get(con); + if (!queue_work(con->server->rcv_wq, &con->rwork)) + conn_put(con); + } + read_unlock(&sk->sk_callback_lock); +} + +static void sock_write_space(struct sock *sk) +{ + struct tipc_conn *con; + + read_lock(&sk->sk_callback_lock); + con = sock2con(sk); + if (con && test_bit(CF_CONNECTED, &con->flags)) { + conn_get(con); + if (!queue_work(con->server->send_wq, &con->swork)) + conn_put(con); + } + read_unlock(&sk->sk_callback_lock); +} + +static void tipc_register_callbacks(struct socket *sock, struct tipc_conn *con) +{ + struct sock *sk = sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + + sk->sk_data_ready = sock_data_ready; + sk->sk_write_space = sock_write_space; + sk->sk_user_data = con; + + con->sock = sock; + + write_unlock_bh(&sk->sk_callback_lock); +} + +static void tipc_unregister_callbacks(struct tipc_conn *con) +{ + struct sock *sk = con->sock->sk; + + write_lock_bh(&sk->sk_callback_lock); + sk->sk_user_data = NULL; + write_unlock_bh(&sk->sk_callback_lock); +} + +static void tipc_close_conn(struct tipc_conn *con) +{ + struct tipc_server *s = con->server; + + if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { + spin_lock_bh(&s->idr_lock); + idr_remove(&s->conn_idr, con->conid); + s->idr_in_use--; + spin_unlock_bh(&s->idr_lock); + + tipc_unregister_callbacks(con); + + /* We shouldn't flush pending works as we may be in the + * thread. In fact the races with pending rx/tx work structs + * are harmless for us here as we have already deleted this + * connection from server connection list and set + * sk->sk_user_data to 0 before releasing connection object. + */ + kernel_sock_shutdown(con->sock, SHUT_RDWR); + + conn_put(con); + } +} + +static struct tipc_conn *tipc_alloc_conn(struct tipc_server *s) +{ + struct tipc_conn *con; + int ret; + + con = kzalloc(sizeof(struct tipc_conn), GFP_ATOMIC); + if (!con) + return ERR_PTR(-ENOMEM); + + kref_init(&con->kref); + INIT_LIST_HEAD(&con->outqueue); + spin_lock_init(&con->outqueue_lock); + INIT_WORK(&con->swork, tipc_send_work); + INIT_WORK(&con->rwork, tipc_recv_work); + + spin_lock_bh(&s->idr_lock); + ret = idr_alloc(&s->conn_idr, con, 0, 0, GFP_ATOMIC); + if (ret < 0) { + kfree(con); + spin_unlock_bh(&s->idr_lock); + return ERR_PTR(-ENOMEM); + } + con->conid = ret; + s->idr_in_use++; + spin_unlock_bh(&s->idr_lock); + + set_bit(CF_CONNECTED, &con->flags); + con->server = s; + + return con; +} + +static int tipc_receive_from_sock(struct tipc_conn *con) +{ + struct msghdr msg = {}; + struct tipc_server *s = con->server; + struct sockaddr_tipc addr; + struct kvec iov; + void *buf; + int ret; + + buf = kmem_cache_alloc(s->rcvbuf_cache, GFP_ATOMIC); + if (!buf) { + ret = -ENOMEM; + goto out_close; + } + + iov.iov_base = buf; + iov.iov_len = s->max_rcvbuf_size; + msg.msg_name = &addr; + ret = kernel_recvmsg(con->sock, &msg, &iov, 1, iov.iov_len, + MSG_DONTWAIT); + if (ret <= 0) { + kmem_cache_free(s->rcvbuf_cache, buf); + goto out_close; + } + + s->tipc_conn_recvmsg(con->conid, &addr, con->usr_data, buf, ret); + + kmem_cache_free(s->rcvbuf_cache, buf); + + return 0; + +out_close: + if (ret != -EWOULDBLOCK) + tipc_close_conn(con); + else if (ret == 0) + /* Don't return success if we really got EOF */ + ret = -EAGAIN; + + return ret; +} + +static int tipc_accept_from_sock(struct tipc_conn *con) +{ + struct tipc_server *s = con->server; + struct socket *sock = con->sock; + struct socket *newsock; + struct tipc_conn *newcon; + int ret; + + ret = tipc_sock_accept_local(sock, &newsock, O_NONBLOCK); + if (ret < 0) + return ret; + + newcon = tipc_alloc_conn(con->server); + if (IS_ERR(newcon)) { + ret = PTR_ERR(newcon); + sock_release(newsock); + return ret; + } + + newcon->rx_action = tipc_receive_from_sock; + tipc_register_callbacks(newsock, newcon); + + /* Notify that new connection is incoming */ + newcon->usr_data = s->tipc_conn_new(newcon->conid); + + /* Wake up receive process in case of 'SYN+' message */ + newsock->sk->sk_data_ready(newsock->sk, 0); + return ret; +} + +static struct socket *tipc_create_listen_sock(struct tipc_conn *con) +{ + struct tipc_server *s = con->server; + struct socket *sock = NULL; + int ret; + + ret = tipc_sock_create_local(s->type, &sock); + if (ret < 0) + return NULL; + ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, + (char *)&s->imp, sizeof(s->imp)); + if (ret < 0) + goto create_err; + ret = kernel_bind(sock, (struct sockaddr *)s->saddr, sizeof(*s->saddr)); + if (ret < 0) + goto create_err; + + switch (s->type) { + case SOCK_STREAM: + case SOCK_SEQPACKET: + con->rx_action = tipc_accept_from_sock; + + ret = kernel_listen(sock, 0); + if (ret < 0) + goto create_err; + break; + case SOCK_DGRAM: + case SOCK_RDM: + con->rx_action = tipc_receive_from_sock; + break; + default: + pr_err("Unknown socket type %d\n", s->type); + goto create_err; + } + return sock; + +create_err: + sock_release(sock); + con->sock = NULL; + return NULL; +} + +static int tipc_open_listening_sock(struct tipc_server *s) +{ + struct socket *sock; + struct tipc_conn *con; + + con = tipc_alloc_conn(s); + if (IS_ERR(con)) + return PTR_ERR(con); + + sock = tipc_create_listen_sock(con); + if (!sock) + return -EINVAL; + + tipc_register_callbacks(sock, con); + return 0; +} + +static struct outqueue_entry *tipc_alloc_entry(void *data, int len) +{ + struct outqueue_entry *entry; + void *buf; + + entry = kmalloc(sizeof(struct outqueue_entry), GFP_ATOMIC); + if (!entry) + return NULL; + + buf = kmalloc(len, GFP_ATOMIC); + if (!buf) { + kfree(entry); + return NULL; + } + + memcpy(buf, data, len); + entry->iov.iov_base = buf; + entry->iov.iov_len = len; + + return entry; +} + +static void tipc_free_entry(struct outqueue_entry *e) +{ + kfree(e->iov.iov_base); + kfree(e); +} + +static void tipc_clean_outqueues(struct tipc_conn *con) +{ + struct outqueue_entry *e, *safe; + + spin_lock_bh(&con->outqueue_lock); + list_for_each_entry_safe(e, safe, &con->outqueue, list) { + list_del(&e->list); + tipc_free_entry(e); + } + spin_unlock_bh(&con->outqueue_lock); +} + +int tipc_conn_sendmsg(struct tipc_server *s, int conid, + struct sockaddr_tipc *addr, void *data, size_t len) +{ + struct outqueue_entry *e; + struct tipc_conn *con; + + con = tipc_conn_lookup(s, conid); + if (!con) + return -EINVAL; + + e = tipc_alloc_entry(data, len); + if (!e) { + conn_put(con); + return -ENOMEM; + } + + if (addr) + memcpy(&e->dest, addr, sizeof(struct sockaddr_tipc)); + + spin_lock_bh(&con->outqueue_lock); + list_add_tail(&e->list, &con->outqueue); + spin_unlock_bh(&con->outqueue_lock); + + if (test_bit(CF_CONNECTED, &con->flags)) + if (!queue_work(s->send_wq, &con->swork)) + conn_put(con); + + return 0; +} + +void tipc_conn_terminate(struct tipc_server *s, int conid) +{ + struct tipc_conn *con; + + con = tipc_conn_lookup(s, conid); + if (con) { + tipc_close_conn(con); + conn_put(con); + } +} + +static void tipc_send_to_sock(struct tipc_conn *con) +{ + int count = 0; + struct tipc_server *s = con->server; + struct outqueue_entry *e; + struct msghdr msg; + int ret; + + spin_lock_bh(&con->outqueue_lock); + while (1) { + e = list_entry(con->outqueue.next, struct outqueue_entry, + list); + if ((struct list_head *) e == &con->outqueue) + break; + spin_unlock_bh(&con->outqueue_lock); + + memset(&msg, 0, sizeof(msg)); + msg.msg_flags = MSG_DONTWAIT; + + if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) { + msg.msg_name = &e->dest; + msg.msg_namelen = sizeof(struct sockaddr_tipc); + } + ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1, + e->iov.iov_len); + if (ret == -EWOULDBLOCK || ret == 0) { + cond_resched(); + goto out; + } else if (ret < 0) { + goto send_err; + } + + /* Don't starve users filling buffers */ + if (++count >= MAX_SEND_MSG_COUNT) { + cond_resched(); + count = 0; + } + + spin_lock_bh(&con->outqueue_lock); + list_del(&e->list); + tipc_free_entry(e); + } + spin_unlock_bh(&con->outqueue_lock); +out: + return; + +send_err: + tipc_close_conn(con); +} + +static void tipc_recv_work(struct work_struct *work) +{ + struct tipc_conn *con = container_of(work, struct tipc_conn, rwork); + int count = 0; + + while (test_bit(CF_CONNECTED, &con->flags)) { + if (con->rx_action(con)) + break; + + /* Don't flood Rx machine */ + if (++count >= MAX_RECV_MSG_COUNT) { + cond_resched(); + count = 0; + } + } + conn_put(con); +} + +static void tipc_send_work(struct work_struct *work) +{ + struct tipc_conn *con = container_of(work, struct tipc_conn, swork); + + if (test_bit(CF_CONNECTED, &con->flags)) + tipc_send_to_sock(con); + + conn_put(con); +} + +static void tipc_work_stop(struct tipc_server *s) +{ + destroy_workqueue(s->rcv_wq); + destroy_workqueue(s->send_wq); +} + +static int tipc_work_start(struct tipc_server *s) +{ + s->rcv_wq = alloc_workqueue("tipc_rcv", WQ_UNBOUND, 1); + if (!s->rcv_wq) { + pr_err("can't start tipc receive workqueue\n"); + return -ENOMEM; + } + + s->send_wq = alloc_workqueue("tipc_send", WQ_UNBOUND, 1); + if (!s->send_wq) { + pr_err("can't start tipc send workqueue\n"); + destroy_workqueue(s->rcv_wq); + return -ENOMEM; + } + + return 0; +} + +int tipc_server_start(struct tipc_server *s) +{ + int ret; + + spin_lock_init(&s->idr_lock); + idr_init(&s->conn_idr); + s->idr_in_use = 0; + + s->rcvbuf_cache = kmem_cache_create(s->name, s->max_rcvbuf_size, + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!s->rcvbuf_cache) + return -ENOMEM; + + ret = tipc_work_start(s); + if (ret < 0) { + kmem_cache_destroy(s->rcvbuf_cache); + return ret; + } + s->enabled = 1; + + return tipc_open_listening_sock(s); +} + +void tipc_server_stop(struct tipc_server *s) +{ + struct tipc_conn *con; + int total = 0; + int id; + + if (!s->enabled) + return; + + s->enabled = 0; + spin_lock_bh(&s->idr_lock); + for (id = 0; total < s->idr_in_use; id++) { + con = idr_find(&s->conn_idr, id); + if (con) { + total++; + spin_unlock_bh(&s->idr_lock); + tipc_close_conn(con); + spin_lock_bh(&s->idr_lock); + } + } + spin_unlock_bh(&s->idr_lock); + + tipc_work_stop(s); + kmem_cache_destroy(s->rcvbuf_cache); + idr_destroy(&s->conn_idr); +} diff --git a/net/tipc/server.h b/net/tipc/server.h new file mode 100644 index 000000000000..98b23f20bc0f --- /dev/null +++ b/net/tipc/server.h @@ -0,0 +1,94 @@ +/* + * net/tipc/server.h: Include file for TIPC server code + * + * Copyright (c) 2012-2013, Wind River Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TIPC_SERVER_H +#define _TIPC_SERVER_H + +#include "core.h" + +#define TIPC_SERVER_NAME_LEN 32 + +/** + * struct tipc_server - TIPC server structure + * @conn_idr: identifier set of connection + * @idr_lock: protect the connection identifier set + * @idr_in_use: amount of allocated identifier entry + * @rcvbuf_cache: memory cache of server receive buffer + * @rcv_wq: receive workqueue + * @send_wq: send workqueue + * @max_rcvbuf_size: maximum permitted receive message length + * @tipc_conn_new: callback will be called when new connection is incoming + * @tipc_conn_shutdown: callback will be called when connection is shut down + * @tipc_conn_recvmsg: callback will be called when message arrives + * @saddr: TIPC server address + * @name: server name + * @imp: message importance + * @type: socket type + * @enabled: identify whether server is launched or not + */ +struct tipc_server { + struct idr conn_idr; + spinlock_t idr_lock; + int idr_in_use; + struct kmem_cache *rcvbuf_cache; + struct workqueue_struct *rcv_wq; + struct workqueue_struct *send_wq; + int max_rcvbuf_size; + void *(*tipc_conn_new) (int conid); + void (*tipc_conn_shutdown) (int conid, void *usr_data); + void (*tipc_conn_recvmsg) (int conid, struct sockaddr_tipc *addr, + void *usr_data, void *buf, size_t len); + struct sockaddr_tipc *saddr; + const char name[TIPC_SERVER_NAME_LEN]; + int imp; + int type; + int enabled; +}; + +int tipc_conn_sendmsg(struct tipc_server *s, int conid, + struct sockaddr_tipc *addr, void *data, size_t len); + +/** + * tipc_conn_terminate - terminate connection with server + * + * Note: Must call it in process context since it might sleep + */ +void tipc_conn_terminate(struct tipc_server *s, int conid); + +int tipc_server_start(struct tipc_server *s); + +void tipc_server_stop(struct tipc_server *s); + +#endif diff --git a/net/tipc/socket.c b/net/tipc/socket.c index d5fa708f037d..bd8e2cdeceef 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -2,7 +2,7 @@ * net/tipc/socket.c: TIPC socket API * * Copyright (c) 2001-2007, 2012 Ericsson AB - * Copyright (c) 2004-2008, 2010-2012, Wind River Systems + * Copyright (c) 2004-2008, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,12 +63,15 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); static void wakeupdispatch(struct tipc_port *tport); static void tipc_data_ready(struct sock *sk, int len); static void tipc_write_space(struct sock *sk); +static int release(struct socket *sock); +static int accept(struct socket *sock, struct socket *new_sock, int flags); static const struct proto_ops packet_ops; static const struct proto_ops stream_ops; static const struct proto_ops msg_ops; static struct proto tipc_proto; +static struct proto tipc_proto_kern; static int sockets_enabled; @@ -141,7 +144,7 @@ static void reject_rx_queue(struct sock *sk) } /** - * tipc_create - create a TIPC socket + * tipc_sk_create - create a TIPC socket * @net: network namespace (must be default network) * @sock: pre-allocated socket structure * @protocol: protocol indicator (must be 0) @@ -152,8 +155,8 @@ static void reject_rx_queue(struct sock *sk) * * Returns 0 on success, errno otherwise */ -static int tipc_create(struct net *net, struct socket *sock, int protocol, - int kern) +static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, + int kern) { const struct proto_ops *ops; socket_state state; @@ -183,7 +186,11 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, } /* Allocate socket's protocol area */ - sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); + if (!kern) + sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto); + else + sk = sk_alloc(net, AF_TIPC, GFP_KERNEL, &tipc_proto_kern); + if (sk == NULL) return -ENOMEM; @@ -218,6 +225,78 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, return 0; } +/** + * tipc_sock_create_local - create TIPC socket from inside TIPC module + * @type: socket type - SOCK_RDM or SOCK_SEQPACKET + * + * We cannot use sock_creat_kern here because it bumps module user count. + * Since socket owner and creator is the same module we must make sure + * that module count remains zero for module local sockets, otherwise + * we cannot do rmmod. + * + * Returns 0 on success, errno otherwise + */ +int tipc_sock_create_local(int type, struct socket **res) +{ + int rc; + struct sock *sk; + + rc = sock_create_lite(AF_TIPC, type, 0, res); + if (rc < 0) { + pr_err("Failed to create kernel socket\n"); + return rc; + } + tipc_sk_create(&init_net, *res, 0, 1); + + sk = (*res)->sk; + + return 0; +} + +/** + * tipc_sock_release_local - release socket created by tipc_sock_create_local + * @sock: the socket to be released. + * + * Module reference count is not incremented when such sockets are created, + * so we must keep it from being decremented when they are released. + */ +void tipc_sock_release_local(struct socket *sock) +{ + release(sock); + sock->ops = NULL; + sock_release(sock); +} + +/** + * tipc_sock_accept_local - accept a connection on a socket created + * with tipc_sock_create_local. Use this function to avoid that + * module reference count is inadvertently incremented. + * + * @sock: the accepting socket + * @newsock: reference to the new socket to be created + * @flags: socket flags + */ + +int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, + int flags) +{ + struct sock *sk = sock->sk; + int ret; + + ret = sock_create_lite(sk->sk_family, sk->sk_type, + sk->sk_protocol, newsock); + if (ret < 0) + return ret; + + ret = accept(sock, *newsock, flags); + if (ret < 0) { + sock_release(*newsock); + return ret; + } + (*newsock)->ops = sock->ops; + return ret; +} + /** * release - destroy a TIPC socket * @sock: socket to destroy @@ -1529,7 +1608,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) buf = skb_peek(&sk->sk_receive_queue); - res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); + res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, 1); if (res) goto exit; @@ -1839,7 +1918,7 @@ static const struct proto_ops stream_ops = { static const struct net_proto_family tipc_family_ops = { .owner = THIS_MODULE, .family = AF_TIPC, - .create = tipc_create + .create = tipc_sk_create }; static struct proto tipc_proto = { @@ -1849,6 +1928,12 @@ static struct proto tipc_proto = { .sysctl_rmem = sysctl_tipc_rmem }; +static struct proto tipc_proto_kern = { + .name = "TIPC", + .obj_size = sizeof(struct tipc_sock), + .sysctl_rmem = sysctl_tipc_rmem +}; + /** * tipc_socket_init - initialize TIPC socket interface * -- GitLab From 13a2e89873506d64d7e52f17b571da371a3e25a4 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:40 -0400 Subject: [PATCH 1351/2900] tipc: convert topology server to use new server facility As the new TIPC server infrastructure has been introduced, we can now convert the TIPC topology server to it. We get two benefits from doing this: 1) It simplifies the topology server locking policy. In the original locking policy, we placed one spin lock pointer in the tipc_subscriber structure to reuse the lock of the subscriber's server port, controlling access to members of tipc_subscriber instance. That is, we only used one lock to ensure both tipc_port and tipc_subscriber members were safely accessed. Now we introduce another spin lock for tipc_subscriber structure only protecting themselves, to get a finer granularity locking policy. Moreover, the change will allow us to make the topology server code more readable and maintainable. 2) It fixes a bug where sent subscription events may be lost when the topology port is congested. Using the new service, the topology server now queues sent events into an outgoing buffer, and then wakes up a sender process which has been blocked in workqueue context. The process will keep picking events from the buffer and send them to their respective subscribers, using the kernel socket interface, until the buffer is empty. Even if the socket is congested during transmission there is no risk that events may be dropped, since the sender process may block when needed. Some minor reordering of initialization is done, since we now have a scenario where the topology server must be started after socket initialization has taken place, as the former depends on the latter. And overall, we see a simplification of the TIPC subscriber code in making this changeover. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/core.c | 6 +- net/tipc/socket.c | 3 +- net/tipc/subscr.c | 334 +++++++++++++--------------------------------- net/tipc/subscr.h | 8 +- 4 files changed, 104 insertions(+), 247 deletions(-) diff --git a/net/tipc/core.c b/net/tipc/core.c index b0e42a087291..15bbe99b609d 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -2,7 +2,7 @@ * net/tipc/core.c: TIPC module code * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2006, 2010-2011, Wind River Systems + * Copyright (c) 2005-2006, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,8 +136,6 @@ static int tipc_core_start(void) res = tipc_ref_table_init(tipc_max_ports, tipc_random); if (!res) res = tipc_nametbl_init(); - if (!res) - res = tipc_subscr_start(); if (!res) res = tipc_cfg_init(); if (!res) @@ -146,6 +144,8 @@ static int tipc_core_start(void) res = tipc_socket_init(); if (!res) res = tipc_register_sysctl(); + if (!res) + res = tipc_subscr_start(); if (res) tipc_core_stop(); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index bd8e2cdeceef..d0254157a30d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -402,7 +402,8 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) else if (addr->addrtype != TIPC_ADDR_NAMESEQ) return -EAFNOSUPPORT; - if (addr->addr.nameseq.type < TIPC_RESERVED_TYPES) + if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && + (addr->addr.nameseq.type != TIPC_TOP_SRV)) return -EACCES; return (addr->scope > 0) ? diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 6b42d47029af..f6be92a6973a 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -2,7 +2,7 @@ * net/tipc/subscr.c: TIPC network topology service * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2007, 2010-2011, Wind River Systems + * Copyright (c) 2005-2007, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,33 +41,42 @@ /** * struct tipc_subscriber - TIPC network topology subscriber - * @port_ref: object reference to server port connecting to subscriber - * @lock: pointer to spinlock controlling access to subscriber's server port - * @subscriber_list: adjacent subscribers in top. server's list of subscribers + * @conid: connection identifier to server connecting to subscriber + * @lock: controll access to subscriber * @subscription_list: list of subscription objects for this subscriber */ struct tipc_subscriber { - u32 port_ref; - spinlock_t *lock; - struct list_head subscriber_list; + int conid; + spinlock_t lock; struct list_head subscription_list; }; -/** - * struct top_srv - TIPC network topology subscription service - * @setup_port: reference to TIPC port that handles subscription requests - * @subscription_count: number of active subscriptions (not subscribers!) - * @subscriber_list: list of ports subscribing to service - * @lock: spinlock govering access to subscriber list - */ -struct top_srv { - u32 setup_port; - atomic_t subscription_count; - struct list_head subscriber_list; - spinlock_t lock; +static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, + void *usr_data, void *buf, size_t len); +static void *subscr_named_msg_event(int conid); +static void subscr_conn_shutdown_event(int conid, void *usr_data); + +static atomic_t subscription_count = ATOMIC_INIT(0); + +static struct sockaddr_tipc topsrv_addr __read_mostly = { + .family = AF_TIPC, + .addrtype = TIPC_ADDR_NAMESEQ, + .addr.nameseq.type = TIPC_TOP_SRV, + .addr.nameseq.lower = TIPC_TOP_SRV, + .addr.nameseq.upper = TIPC_TOP_SRV, + .scope = TIPC_NODE_SCOPE }; -static struct top_srv topsrv; +static struct tipc_server topsrv __read_mostly = { + .saddr = &topsrv_addr, + .imp = TIPC_CRITICAL_IMPORTANCE, + .type = SOCK_SEQPACKET, + .max_rcvbuf_size = sizeof(struct tipc_subscr), + .name = "topology_server", + .tipc_conn_recvmsg = subscr_conn_msg_event, + .tipc_conn_new = subscr_named_msg_event, + .tipc_conn_shutdown = subscr_conn_shutdown_event, +}; /** * htohl - convert value to endianness used by destination @@ -81,20 +90,13 @@ static u32 htohl(u32 in, int swap) return swap ? swab32(in) : in; } -/** - * subscr_send_event - send a message containing a tipc_event to the subscriber - * - * Note: Must not hold subscriber's server port lock, since tipc_send() will - * try to take the lock if the message is rejected and returned! - */ -static void subscr_send_event(struct tipc_subscription *sub, - u32 found_lower, - u32 found_upper, - u32 event, - u32 port_ref, +static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, + u32 found_upper, u32 event, u32 port_ref, u32 node) { - struct iovec msg_sect; + struct tipc_subscriber *subscriber = sub->subscriber; + struct kvec msg_sect; + int ret; msg_sect.iov_base = (void *)&sub->evt; msg_sect.iov_len = sizeof(struct tipc_event); @@ -104,7 +106,10 @@ static void subscr_send_event(struct tipc_subscription *sub, sub->evt.found_upper = htohl(found_upper, sub->swap); sub->evt.port.ref = htohl(port_ref, sub->swap); sub->evt.port.node = htohl(node, sub->swap); - tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len); + ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, + msg_sect.iov_base, msg_sect.iov_len); + if (ret < 0) + pr_err("Sending subscription event failed, no memory\n"); } /** @@ -147,21 +152,24 @@ void tipc_subscr_report_overlap(struct tipc_subscription *sub, subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); } -/** - * subscr_timeout - subscription timeout has occurred - */ static void subscr_timeout(struct tipc_subscription *sub) { - struct tipc_port *server_port; + struct tipc_subscriber *subscriber = sub->subscriber; - /* Validate server port reference (in case subscriber is terminating) */ - server_port = tipc_port_lock(sub->server_ref); - if (server_port == NULL) + /* The spin lock per subscriber is used to protect its members */ + spin_lock_bh(&subscriber->lock); + + /* Validate if the connection related to the subscriber is + * closed (in case subscriber is terminating) + */ + if (subscriber->conid == 0) { + spin_unlock_bh(&subscriber->lock); return; + } /* Validate timeout (in case subscription is being cancelled) */ if (sub->timeout == TIPC_WAIT_FOREVER) { - tipc_port_unlock(server_port); + spin_unlock_bh(&subscriber->lock); return; } @@ -171,8 +179,7 @@ static void subscr_timeout(struct tipc_subscription *sub) /* Unlink subscription from subscriber */ list_del(&sub->subscription_list); - /* Release subscriber's server port */ - tipc_port_unlock(server_port); + spin_unlock_bh(&subscriber->lock); /* Notify subscriber of timeout */ subscr_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, @@ -181,64 +188,54 @@ static void subscr_timeout(struct tipc_subscription *sub) /* Now destroy subscription */ k_term_timer(&sub->timer); kfree(sub); - atomic_dec(&topsrv.subscription_count); + atomic_dec(&subscription_count); } /** * subscr_del - delete a subscription within a subscription list * - * Called with subscriber port locked. + * Called with subscriber lock held. */ static void subscr_del(struct tipc_subscription *sub) { tipc_nametbl_unsubscribe(sub); list_del(&sub->subscription_list); kfree(sub); - atomic_dec(&topsrv.subscription_count); + atomic_dec(&subscription_count); } /** * subscr_terminate - terminate communication with a subscriber * - * Called with subscriber port locked. Routine must temporarily release lock - * to enable subscription timeout routine(s) to finish without deadlocking; - * the lock is then reclaimed to allow caller to release it upon return. - * (This should work even in the unlikely event some other thread creates - * a new object reference in the interim that uses this lock; this routine will - * simply wait for it to be released, then claim it.) + * Note: Must call it in process context since it might sleep. */ static void subscr_terminate(struct tipc_subscriber *subscriber) { - u32 port_ref; + tipc_conn_terminate(&topsrv, subscriber->conid); +} + +static void subscr_release(struct tipc_subscriber *subscriber) +{ struct tipc_subscription *sub; struct tipc_subscription *sub_temp; - /* Invalidate subscriber reference */ - port_ref = subscriber->port_ref; - subscriber->port_ref = 0; - spin_unlock_bh(subscriber->lock); + spin_lock_bh(&subscriber->lock); - /* Sever connection to subscriber */ - tipc_shutdown(port_ref); - tipc_deleteport(port_ref); + /* Invalidate subscriber reference */ + subscriber->conid = 0; /* Destroy any existing subscriptions for subscriber */ list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, subscription_list) { if (sub->timeout != TIPC_WAIT_FOREVER) { + spin_unlock_bh(&subscriber->lock); k_cancel_timer(&sub->timer); k_term_timer(&sub->timer); + spin_lock_bh(&subscriber->lock); } subscr_del(sub); } - - /* Remove subscriber from topology server's subscriber list */ - spin_lock_bh(&topsrv.lock); - list_del(&subscriber->subscriber_list); - spin_unlock_bh(&topsrv.lock); - - /* Reclaim subscriber lock */ - spin_lock_bh(subscriber->lock); + spin_unlock_bh(&subscriber->lock); /* Now destroy subscriber */ kfree(subscriber); @@ -247,7 +244,7 @@ static void subscr_terminate(struct tipc_subscriber *subscriber) /** * subscr_cancel - handle subscription cancellation request * - * Called with subscriber port locked. Routine must temporarily release lock + * Called with subscriber lock held. Routine must temporarily release lock * to enable the subscription timeout routine to finish without deadlocking; * the lock is then reclaimed to allow caller to release it upon return. * @@ -274,10 +271,10 @@ static void subscr_cancel(struct tipc_subscr *s, /* Cancel subscription timer (if used), then delete subscription */ if (sub->timeout != TIPC_WAIT_FOREVER) { sub->timeout = TIPC_WAIT_FOREVER; - spin_unlock_bh(subscriber->lock); + spin_unlock_bh(&subscriber->lock); k_cancel_timer(&sub->timer); k_term_timer(&sub->timer); - spin_lock_bh(subscriber->lock); + spin_lock_bh(&subscriber->lock); } subscr_del(sub); } @@ -285,7 +282,7 @@ static void subscr_cancel(struct tipc_subscr *s, /** * subscr_subscribe - create subscription for subscriber * - * Called with subscriber port locked. + * Called with subscriber lock held. */ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, struct tipc_subscriber *subscriber) @@ -304,7 +301,7 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, } /* Refuse subscription if global limit exceeded */ - if (atomic_read(&topsrv.subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { + if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { pr_warn("Subscription rejected, limit reached (%u)\n", TIPC_MAX_SUBSCRIPTIONS); subscr_terminate(subscriber); @@ -335,10 +332,10 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, } INIT_LIST_HEAD(&sub->nameseq_list); list_add(&sub->subscription_list, &subscriber->subscription_list); - sub->server_ref = subscriber->port_ref; + sub->subscriber = subscriber; sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); - atomic_inc(&topsrv.subscription_count); + atomic_inc(&subscription_count); if (sub->timeout != TIPC_WAIT_FOREVER) { k_init_timer(&sub->timer, (Handler)subscr_timeout, (unsigned long)sub); @@ -348,196 +345,51 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, return sub; } -/** - * subscr_conn_shutdown_event - handle termination request from subscriber - * - * Called with subscriber's server port unlocked. - */ -static void subscr_conn_shutdown_event(void *usr_handle, - u32 port_ref, - struct sk_buff **buf, - unsigned char const *data, - unsigned int size, - int reason) +/* Handle one termination request for the subscriber */ +static void subscr_conn_shutdown_event(int conid, void *usr_data) { - struct tipc_subscriber *subscriber = usr_handle; - spinlock_t *subscriber_lock; - - if (tipc_port_lock(port_ref) == NULL) - return; - - subscriber_lock = subscriber->lock; - subscr_terminate(subscriber); - spin_unlock_bh(subscriber_lock); + subscr_release((struct tipc_subscriber *)usr_data); } -/** - * subscr_conn_msg_event - handle new subscription request from subscriber - * - * Called with subscriber's server port unlocked. - */ -static void subscr_conn_msg_event(void *usr_handle, - u32 port_ref, - struct sk_buff **buf, - const unchar *data, - u32 size) +/* Handle one request to create a new subscription for the subscriber */ +static void subscr_conn_msg_event(int conid, struct sockaddr_tipc *addr, + void *usr_data, void *buf, size_t len) { - struct tipc_subscriber *subscriber = usr_handle; - spinlock_t *subscriber_lock; + struct tipc_subscriber *subscriber = usr_data; struct tipc_subscription *sub; - /* - * Lock subscriber's server port (& make a local copy of lock pointer, - * in case subscriber is deleted while processing subscription request) - */ - if (tipc_port_lock(port_ref) == NULL) - return; - - subscriber_lock = subscriber->lock; - - if (size != sizeof(struct tipc_subscr)) { - subscr_terminate(subscriber); - spin_unlock_bh(subscriber_lock); - } else { - sub = subscr_subscribe((struct tipc_subscr *)data, subscriber); - spin_unlock_bh(subscriber_lock); - if (sub != NULL) { - - /* - * We must release the server port lock before adding a - * subscription to the name table since TIPC needs to be - * able to (re)acquire the port lock if an event message - * issued by the subscription process is rejected and - * returned. The subscription cannot be deleted while - * it is being added to the name table because: - * a) the single-threading of the native API port code - * ensures the subscription cannot be cancelled and - * the subscriber connection cannot be broken, and - * b) the name table lock ensures the subscription - * timeout code cannot delete the subscription, - * so the subscription object is still protected. - */ - tipc_nametbl_subscribe(sub); - } - } + spin_lock_bh(&subscriber->lock); + sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber); + if (sub) + tipc_nametbl_subscribe(sub); + spin_unlock_bh(&subscriber->lock); } -/** - * subscr_named_msg_event - handle request to establish a new subscriber - */ -static void subscr_named_msg_event(void *usr_handle, - u32 port_ref, - struct sk_buff **buf, - const unchar *data, - u32 size, - u32 importance, - struct tipc_portid const *orig, - struct tipc_name_seq const *dest) + +/* Handle one request to establish a new subscriber */ +static void *subscr_named_msg_event(int conid) { struct tipc_subscriber *subscriber; - u32 server_port_ref; /* Create subscriber object */ subscriber = kzalloc(sizeof(struct tipc_subscriber), GFP_ATOMIC); if (subscriber == NULL) { pr_warn("Subscriber rejected, no memory\n"); - return; + return NULL; } INIT_LIST_HEAD(&subscriber->subscription_list); - INIT_LIST_HEAD(&subscriber->subscriber_list); - - /* Create server port & establish connection to subscriber */ - tipc_createport(subscriber, - importance, - NULL, - NULL, - subscr_conn_shutdown_event, - NULL, - NULL, - subscr_conn_msg_event, - NULL, - &subscriber->port_ref); - if (subscriber->port_ref == 0) { - pr_warn("Subscriber rejected, unable to create port\n"); - kfree(subscriber); - return; - } - tipc_connect(subscriber->port_ref, orig); - - /* Lock server port (& save lock address for future use) */ - subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock; - - /* Add subscriber to topology server's subscriber list */ - spin_lock_bh(&topsrv.lock); - list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); - spin_unlock_bh(&topsrv.lock); - - /* Unlock server port */ - server_port_ref = subscriber->port_ref; - spin_unlock_bh(subscriber->lock); - - /* Send an ACK- to complete connection handshaking */ - tipc_send(server_port_ref, 0, NULL, 0); + subscriber->conid = conid; + spin_lock_init(&subscriber->lock); - /* Handle optional subscription request */ - if (size != 0) { - subscr_conn_msg_event(subscriber, server_port_ref, - buf, data, size); - } + return (void *)subscriber; } int tipc_subscr_start(void) { - struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; - int res; - - spin_lock_init(&topsrv.lock); - INIT_LIST_HEAD(&topsrv.subscriber_list); - - res = tipc_createport(NULL, - TIPC_CRITICAL_IMPORTANCE, - NULL, - NULL, - NULL, - NULL, - subscr_named_msg_event, - NULL, - NULL, - &topsrv.setup_port); - if (res) - goto failed; - - res = tipc_publish(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); - if (res) { - tipc_deleteport(topsrv.setup_port); - topsrv.setup_port = 0; - goto failed; - } - - return 0; - -failed: - pr_err("Failed to create subscription service\n"); - return res; + return tipc_server_start(&topsrv); } void tipc_subscr_stop(void) { - struct tipc_subscriber *subscriber; - struct tipc_subscriber *subscriber_temp; - spinlock_t *subscriber_lock; - - if (topsrv.setup_port) { - tipc_deleteport(topsrv.setup_port); - topsrv.setup_port = 0; - - list_for_each_entry_safe(subscriber, subscriber_temp, - &topsrv.subscriber_list, - subscriber_list) { - subscriber_lock = subscriber->lock; - spin_lock_bh(subscriber_lock); - subscr_terminate(subscriber); - spin_unlock_bh(subscriber_lock); - } - } + tipc_server_stop(&topsrv); } diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 218d2e07f0cc..43e6d6332a02 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -2,7 +2,7 @@ * net/tipc/subscr.h: Include file for TIPC network topology service * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2007, Wind River Systems + * Copyright (c) 2005-2007, 2012-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,10 +37,14 @@ #ifndef _TIPC_SUBSCR_H #define _TIPC_SUBSCR_H +#include "server.h" + struct tipc_subscription; +struct tipc_subscriber; /** * struct tipc_subscription - TIPC network topology subscription object + * @subscriber: pointer to its subscriber * @seq: name sequence associated with subscription * @timeout: duration of subscription (in ms) * @filter: event filtering to be done for subscription @@ -52,13 +56,13 @@ struct tipc_subscription; * @evt: template for events generated by subscription */ struct tipc_subscription { + struct tipc_subscriber *subscriber; struct tipc_name_seq seq; u32 timeout; u32 filter; struct timer_list timer; struct list_head nameseq_list; struct list_head subscription_list; - u32 server_ref; int swap; struct tipc_event evt; }; -- GitLab From 7d0ab17b74330e39a68ba33099ccda27f794f519 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:41 -0400 Subject: [PATCH 1352/2900] tipc: convert configuration server to use new server facility As the new socket-based TIPC server infrastructure has been introduced, we can now convert the configuration server to use it. Then we can take future steps to simplify the configuration server locking policy. Some minor reordering of initialization is done, due to the dependency on having tipc_socket_init completed. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/config.c | 102 ++++++++++++++++++++-------------------------- net/tipc/core.c | 4 +- net/tipc/socket.c | 3 +- 3 files changed, 49 insertions(+), 60 deletions(-) diff --git a/net/tipc/config.c b/net/tipc/config.c index f67866c765dd..4887ae04f3a5 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -2,7 +2,7 @@ * net/tipc/config.c: TIPC configuration management code * * Copyright (c) 2002-2006, Ericsson AB - * Copyright (c) 2004-2007, 2010-2012, Wind River Systems + * Copyright (c) 2004-2007, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,12 +38,12 @@ #include "port.h" #include "name_table.h" #include "config.h" +#include "server.h" #define REPLY_TRUNCATED "\n" -static u32 config_port_ref; - static DEFINE_SPINLOCK(config_lock); +static struct tipc_server cfgsrv; static const void *req_tlv_area; /* request message TLV area */ static int req_tlv_space; /* request message TLV area size */ @@ -381,33 +381,27 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area return rep_tlv_buf; } -static void cfg_named_msg_event(void *userdata, - u32 port_ref, - struct sk_buff **buf, - const unchar *msg, - u32 size, - u32 importance, - struct tipc_portid const *orig, - struct tipc_name_seq const *dest) +static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, + void *usr_data, void *buf, size_t len) { struct tipc_cfg_msg_hdr *req_hdr; struct tipc_cfg_msg_hdr *rep_hdr; struct sk_buff *rep_buf; + int ret; /* Validate configuration message header (ignore invalid message) */ - req_hdr = (struct tipc_cfg_msg_hdr *)msg; - if ((size < sizeof(*req_hdr)) || - (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || + req_hdr = (struct tipc_cfg_msg_hdr *)buf; + if ((len < sizeof(*req_hdr)) || + (len != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { pr_warn("Invalid configuration message discarded\n"); return; } /* Generate reply for request (if can't, return request) */ - rep_buf = tipc_cfg_do_cmd(orig->node, - ntohs(req_hdr->tcm_type), - msg + sizeof(*req_hdr), - size - sizeof(*req_hdr), + rep_buf = tipc_cfg_do_cmd(addr->addr.id.node, ntohs(req_hdr->tcm_type), + buf + sizeof(*req_hdr), + len - sizeof(*req_hdr), BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); if (rep_buf) { skb_push(rep_buf, sizeof(*rep_hdr)); @@ -415,57 +409,51 @@ static void cfg_named_msg_event(void *userdata, memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); rep_hdr->tcm_len = htonl(rep_buf->len); rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); - } else { - rep_buf = *buf; - *buf = NULL; - } - /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ - tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); + ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, + rep_buf->len); + if (ret < 0) + pr_err("Sending cfg reply message failed, no memory\n"); + + kfree_skb(rep_buf); + } } +static struct sockaddr_tipc cfgsrv_addr __read_mostly = { + .family = AF_TIPC, + .addrtype = TIPC_ADDR_NAMESEQ, + .addr.nameseq.type = TIPC_CFG_SRV, + .addr.nameseq.lower = 0, + .addr.nameseq.upper = 0, + .scope = TIPC_ZONE_SCOPE +}; + +static struct tipc_server cfgsrv __read_mostly = { + .saddr = &cfgsrv_addr, + .imp = TIPC_CRITICAL_IMPORTANCE, + .type = SOCK_RDM, + .max_rcvbuf_size = 64 * 1024, + .name = "cfg_server", + .tipc_conn_recvmsg = cfg_conn_msg_event, + .tipc_conn_new = NULL, + .tipc_conn_shutdown = NULL +}; + int tipc_cfg_init(void) { - struct tipc_name_seq seq; - int res; - - res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE, - NULL, NULL, NULL, - NULL, cfg_named_msg_event, NULL, - NULL, &config_port_ref); - if (res) - goto failed; - - seq.type = TIPC_CFG_SRV; - seq.lower = seq.upper = tipc_own_addr; - res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); - if (res) - goto failed; - - return 0; - -failed: - pr_err("Unable to create configuration service\n"); - return res; + return tipc_server_start(&cfgsrv); } void tipc_cfg_reinit(void) { - struct tipc_name_seq seq; - int res; - - seq.type = TIPC_CFG_SRV; - seq.lower = seq.upper = 0; - tipc_withdraw(config_port_ref, TIPC_ZONE_SCOPE, &seq); + tipc_server_stop(&cfgsrv); - seq.lower = seq.upper = tipc_own_addr; - res = tipc_publish(config_port_ref, TIPC_ZONE_SCOPE, &seq); - if (res) - pr_err("Unable to reinitialize configuration service\n"); + cfgsrv_addr.addr.nameseq.lower = tipc_own_addr; + cfgsrv_addr.addr.nameseq.upper = tipc_own_addr; + tipc_server_start(&cfgsrv); } void tipc_cfg_stop(void) { - tipc_deleteport(config_port_ref); - config_port_ref = 0; + tipc_server_stop(&cfgsrv); } diff --git a/net/tipc/core.c b/net/tipc/core.c index 15bbe99b609d..fd4eeeaa972a 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -136,8 +136,6 @@ static int tipc_core_start(void) res = tipc_ref_table_init(tipc_max_ports, tipc_random); if (!res) res = tipc_nametbl_init(); - if (!res) - res = tipc_cfg_init(); if (!res) res = tipc_netlink_start(); if (!res) @@ -146,6 +144,8 @@ static int tipc_core_start(void) res = tipc_register_sysctl(); if (!res) res = tipc_subscr_start(); + if (!res) + res = tipc_cfg_init(); if (res) tipc_core_stop(); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index d0254157a30d..9510fe8acf45 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -403,7 +403,8 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) return -EAFNOSUPPORT; if ((addr->addr.nameseq.type < TIPC_RESERVED_TYPES) && - (addr->addr.nameseq.type != TIPC_TOP_SRV)) + (addr->addr.nameseq.type != TIPC_TOP_SRV) && + (addr->addr.nameseq.type != TIPC_CFG_SRV)) return -EACCES; return (addr->scope > 0) ? -- GitLab From 198d73b82bf78739f8f11cf7ff567a2e0da1dbef Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:42 -0400 Subject: [PATCH 1353/2900] tipc: delete code orphaned by new server infrastructure Having completed the conversion of the topology server and configuration server to use the new server infrastructure, the following functions become unused, and can be deleted: - tipc_createport() - port_wakeup_sh() - port_dispatcher() - port_dispatcher_sigh() - tipc_send_buf_fast() - tipc_send_buf2port Additionally, the following variables become orphaned, and can be deleted: - tipc_msg_err_event - tipc_named_msg_err_event - tipc_conn_shutdown_event - tipc_msg_event - tipc_named_msg_event - tipc_conn_msg_event - tipc_continue_event - msg_queue_head - msg_queue_tail - queue_lock Deletion is done here in a separate commit in order to allow the actual conversion changes to be more easily viewed. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 36 +----- net/tipc/port.c | 299 +----------------------------------------------- net/tipc/port.h | 53 +-------- 3 files changed, 3 insertions(+), 385 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index a80feee5197a..0a4c3a1bb9cc 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -2,7 +2,7 @@ * net/tipc/link.c: TIPC link code * * Copyright (c) 1996-2007, 2012, Ericsson AB - * Copyright (c) 2004-2007, 2010-2011, Wind River Systems + * Copyright (c) 2004-2007, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1056,40 +1056,6 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, return tipc_link_send_buf(l_ptr, buf); /* All other cases */ } -/* - * tipc_send_buf_fast: Entry for data messages where the - * destination node is known and the header is complete, - * inclusive total message length. - * Returns user data length. - */ -int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) -{ - struct tipc_link *l_ptr; - struct tipc_node *n_ptr; - int res; - u32 selector = msg_origport(buf_msg(buf)) & 1; - u32 dummy; - - read_lock_bh(&tipc_net_lock); - n_ptr = tipc_node_find(destnode); - if (likely(n_ptr)) { - tipc_node_lock(n_ptr); - l_ptr = n_ptr->active_links[selector]; - if (likely(l_ptr)) { - res = link_send_buf_fast(l_ptr, buf, &dummy); - tipc_node_unlock(n_ptr); - read_unlock_bh(&tipc_net_lock); - return res; - } - tipc_node_unlock(n_ptr); - } - read_unlock_bh(&tipc_net_lock); - res = msg_data_sz(buf_msg(buf)); - tipc_reject_msg(buf, TIPC_ERR_NO_NODE); - return res; -} - - /* * tipc_link_send_sections_fast: Entry for messages where the * destination processor is known and the header is complete, diff --git a/net/tipc/port.c b/net/tipc/port.c index 18098cac62f2..0651522c9435 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -2,7 +2,7 @@ * net/tipc/port.c: TIPC port code * * Copyright (c) 1992-2007, Ericsson AB - * Copyright (c) 2004-2008, 2010-2011, Wind River Systems + * Copyright (c) 2004-2008, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,11 +46,7 @@ #define MAX_REJECT_SIZE 1024 -static struct sk_buff *msg_queue_head; -static struct sk_buff *msg_queue_tail; - DEFINE_SPINLOCK(tipc_port_list_lock); -static DEFINE_SPINLOCK(queue_lock); static LIST_HEAD(ports); static void port_handle_node_down(unsigned long ref); @@ -668,215 +664,6 @@ void tipc_port_reinit(void) spin_unlock_bh(&tipc_port_list_lock); } - -/* - * port_dispatcher_sigh(): Signal handler for messages destinated - * to the tipc_port interface. - */ -static void port_dispatcher_sigh(void *dummy) -{ - struct sk_buff *buf; - - spin_lock_bh(&queue_lock); - buf = msg_queue_head; - msg_queue_head = NULL; - spin_unlock_bh(&queue_lock); - - while (buf) { - struct tipc_port *p_ptr; - struct user_port *up_ptr; - struct tipc_portid orig; - struct tipc_name_seq dseq; - void *usr_handle; - int connected; - int peer_invalid; - int published; - u32 message_type; - - struct sk_buff *next = buf->next; - struct tipc_msg *msg = buf_msg(buf); - u32 dref = msg_destport(msg); - - message_type = msg_type(msg); - if (message_type > TIPC_DIRECT_MSG) - goto reject; /* Unsupported message type */ - - p_ptr = tipc_port_lock(dref); - if (!p_ptr) - goto reject; /* Port deleted while msg in queue */ - - orig.ref = msg_origport(msg); - orig.node = msg_orignode(msg); - up_ptr = p_ptr->user_port; - usr_handle = up_ptr->usr_handle; - connected = p_ptr->connected; - peer_invalid = connected && !tipc_port_peer_msg(p_ptr, msg); - published = p_ptr->published; - - if (unlikely(msg_errcode(msg))) - goto err; - - switch (message_type) { - - case TIPC_CONN_MSG:{ - tipc_conn_msg_event cb = up_ptr->conn_msg_cb; - u32 dsz; - - tipc_port_unlock(p_ptr); - if (unlikely(!cb)) - goto reject; - if (unlikely(!connected)) { - if (tipc_connect(dref, &orig)) - goto reject; - } else if (peer_invalid) - goto reject; - dsz = msg_data_sz(msg); - if (unlikely(dsz && - (++p_ptr->conn_unacked >= - TIPC_FLOW_CONTROL_WIN))) - tipc_acknowledge(dref, - p_ptr->conn_unacked); - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), dsz); - break; - } - case TIPC_DIRECT_MSG:{ - tipc_msg_event cb = up_ptr->msg_cb; - - tipc_port_unlock(p_ptr); - if (unlikely(!cb || connected)) - goto reject; - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg), msg_importance(msg), - &orig); - break; - } - case TIPC_MCAST_MSG: - case TIPC_NAMED_MSG:{ - tipc_named_msg_event cb = up_ptr->named_msg_cb; - - tipc_port_unlock(p_ptr); - if (unlikely(!cb || connected || !published)) - goto reject; - dseq.type = msg_nametype(msg); - dseq.lower = msg_nameinst(msg); - dseq.upper = (message_type == TIPC_NAMED_MSG) - ? dseq.lower : msg_nameupper(msg); - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg), msg_importance(msg), - &orig, &dseq); - break; - } - } - if (buf) - kfree_skb(buf); - buf = next; - continue; -err: - switch (message_type) { - - case TIPC_CONN_MSG:{ - tipc_conn_shutdown_event cb = - up_ptr->conn_err_cb; - - tipc_port_unlock(p_ptr); - if (!cb || !connected || peer_invalid) - break; - tipc_disconnect(dref); - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg), msg_errcode(msg)); - break; - } - case TIPC_DIRECT_MSG:{ - tipc_msg_err_event cb = up_ptr->err_cb; - - tipc_port_unlock(p_ptr); - if (!cb || connected) - break; - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg), msg_errcode(msg), &orig); - break; - } - case TIPC_MCAST_MSG: - case TIPC_NAMED_MSG:{ - tipc_named_msg_err_event cb = - up_ptr->named_err_cb; - - tipc_port_unlock(p_ptr); - if (!cb || connected) - break; - dseq.type = msg_nametype(msg); - dseq.lower = msg_nameinst(msg); - dseq.upper = (message_type == TIPC_NAMED_MSG) - ? dseq.lower : msg_nameupper(msg); - skb_pull(buf, msg_hdr_sz(msg)); - cb(usr_handle, dref, &buf, msg_data(msg), - msg_data_sz(msg), msg_errcode(msg), &dseq); - break; - } - } - if (buf) - kfree_skb(buf); - buf = next; - continue; -reject: - tipc_reject_msg(buf, TIPC_ERR_NO_PORT); - buf = next; - } -} - -/* - * port_dispatcher(): Dispatcher for messages destinated - * to the tipc_port interface. Called with port locked. - */ -static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) -{ - buf->next = NULL; - spin_lock_bh(&queue_lock); - if (msg_queue_head) { - msg_queue_tail->next = buf; - msg_queue_tail = buf; - } else { - msg_queue_tail = msg_queue_head = buf; - tipc_k_signal((Handler)port_dispatcher_sigh, 0); - } - spin_unlock_bh(&queue_lock); - return 0; -} - -/* - * Wake up port after congestion: Called with port locked - */ -static void port_wakeup_sh(unsigned long ref) -{ - struct tipc_port *p_ptr; - struct user_port *up_ptr; - tipc_continue_event cb = NULL; - void *uh = NULL; - - p_ptr = tipc_port_lock(ref); - if (p_ptr) { - up_ptr = p_ptr->user_port; - if (up_ptr) { - cb = up_ptr->continue_event_cb; - uh = up_ptr->usr_handle; - } - tipc_port_unlock(p_ptr); - } - if (cb) - cb(uh, ref); -} - - -static void port_wakeup(struct tipc_port *p_ptr) -{ - tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref); -} - void tipc_acknowledge(u32 ref, u32 ack) { struct tipc_port *p_ptr; @@ -893,50 +680,6 @@ void tipc_acknowledge(u32 ref, u32 ack) tipc_net_route_msg(buf); } -/* - * tipc_createport(): user level call. - */ -int tipc_createport(void *usr_handle, - unsigned int importance, - tipc_msg_err_event error_cb, - tipc_named_msg_err_event named_error_cb, - tipc_conn_shutdown_event conn_error_cb, - tipc_msg_event msg_cb, - tipc_named_msg_event named_msg_cb, - tipc_conn_msg_event conn_msg_cb, - tipc_continue_event continue_event_cb, /* May be zero */ - u32 *portref) -{ - struct user_port *up_ptr; - struct tipc_port *p_ptr; - - up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); - if (!up_ptr) { - pr_warn("Port creation failed, no memory\n"); - return -ENOMEM; - } - p_ptr = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, - importance); - if (!p_ptr) { - kfree(up_ptr); - return -ENOMEM; - } - - p_ptr->user_port = up_ptr; - up_ptr->usr_handle = usr_handle; - up_ptr->ref = p_ptr->ref; - up_ptr->err_cb = error_cb; - up_ptr->named_err_cb = named_error_cb; - up_ptr->conn_err_cb = conn_error_cb; - up_ptr->msg_cb = msg_cb; - up_ptr->named_msg_cb = named_msg_cb; - up_ptr->conn_msg_cb = conn_msg_cb; - up_ptr->continue_event_cb = continue_event_cb; - *portref = p_ptr->ref; - tipc_port_unlock(p_ptr); - return 0; -} - int tipc_portimportance(u32 ref, unsigned int *importance) { struct tipc_port *p_ptr; @@ -1322,43 +1065,3 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, } return -ELINKCONG; } - -/** - * tipc_send_buf2port - send message buffer to port identity - */ -int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest, - struct sk_buff *buf, unsigned int dsz) -{ - struct tipc_port *p_ptr; - struct tipc_msg *msg; - int res; - - p_ptr = (struct tipc_port *)tipc_ref_deref(ref); - if (!p_ptr || p_ptr->connected) - return -EINVAL; - - msg = &p_ptr->phdr; - msg_set_type(msg, TIPC_DIRECT_MSG); - msg_set_destnode(msg, dest->node); - msg_set_destport(msg, dest->ref); - msg_set_hdr_sz(msg, BASIC_H_SIZE); - msg_set_size(msg, BASIC_H_SIZE + dsz); - if (skb_cow(buf, BASIC_H_SIZE)) - return -ENOMEM; - - skb_push(buf, BASIC_H_SIZE); - skb_copy_to_linear_data(buf, msg, BASIC_H_SIZE); - - if (in_own_node(dest->node)) - res = tipc_port_recv_msg(buf); - else - res = tipc_send_buf_fast(buf, dest->node); - if (likely(res != -ELINKCONG)) { - if (res > 0) - p_ptr->sent++; - return res; - } - if (port_unreliable(p_ptr)) - return dsz; - return -ELINKCONG; -} diff --git a/net/tipc/port.h b/net/tipc/port.h index 2485649c408a..7fd37c202ce6 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -2,7 +2,7 @@ * net/tipc/port.h: Include file for TIPC port code * * Copyright (c) 1994-2007, Ericsson AB - * Copyright (c) 2004-2007, 2010-2011, Wind River Systems + * Copyright (c) 2004-2007, 2010-2013, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,37 +46,6 @@ #define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \ SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) -typedef void (*tipc_msg_err_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size, int reason, - struct tipc_portid const *attmpt_destid); - -typedef void (*tipc_named_msg_err_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size, int reason, - struct tipc_name_seq const *attmpt_dest); - -typedef void (*tipc_conn_shutdown_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size, int reason); - -typedef void (*tipc_msg_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size, unsigned int importance, - struct tipc_portid const *origin); - -typedef void (*tipc_named_msg_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size, unsigned int importance, - struct tipc_portid const *orig, - struct tipc_name_seq const *dest); - -typedef void (*tipc_conn_msg_event) (void *usr_handle, u32 portref, - struct sk_buff **buf, unsigned char const *data, - unsigned int size); - -typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); - /** * struct user_port - TIPC user port (used with native API) * @usr_handle: user-specified field @@ -87,13 +56,6 @@ typedef void (*tipc_continue_event) (void *usr_handle, u32 portref); struct user_port { void *usr_handle; u32 ref; - tipc_msg_err_event err_cb; - tipc_named_msg_err_event named_err_cb; - tipc_conn_shutdown_event conn_err_cb; - tipc_msg_event msg_cb; - tipc_named_msg_event named_msg_cb; - tipc_conn_msg_event conn_msg_cb; - tipc_continue_event continue_event_cb; }; /** @@ -164,18 +126,8 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, int tipc_reject_msg(struct sk_buff *buf, u32 err); -int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); - void tipc_acknowledge(u32 port_ref, u32 ack); -int tipc_createport(void *usr_handle, - unsigned int importance, tipc_msg_err_event error_cb, - tipc_named_msg_err_event named_error_cb, - tipc_conn_shutdown_event conn_error_cb, tipc_msg_event msg_cb, - tipc_named_msg_event named_msg_cb, - tipc_conn_msg_event conn_msg_cb, - tipc_continue_event continue_event_cb, u32 *portref); - int tipc_deleteport(u32 portref); int tipc_portimportance(u32 portref, unsigned int *importance); @@ -222,9 +174,6 @@ int tipc_send2port(u32 portref, struct tipc_portid const *dest, unsigned int num_sect, struct iovec const *msg_sect, unsigned int total_len); -int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, - struct sk_buff *buf, unsigned int dsz); - int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, unsigned int section_count, struct iovec const *msg, unsigned int total_len); -- GitLab From f1733d7580ff94deb8ea071a293c23939ae0d450 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:43 -0400 Subject: [PATCH 1354/2900] tipc: remove user_port instance from tipc_port structure After the native API has been completely removed, the 'user_port' field in struct tipc_port becomes unused, and can be removed. As a consequence, the "usrmem" argument in tipc_msg_build() is no longer needed, and so we remove that one too. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 18 +++++++----------- net/tipc/msg.c | 15 +++++---------- net/tipc/msg.h | 4 ++-- net/tipc/port.c | 8 +++----- net/tipc/port.h | 14 -------------- 5 files changed, 17 insertions(+), 42 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 0a4c3a1bb9cc..d34429d03c16 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1081,7 +1081,7 @@ int tipc_link_send_sections_fast(struct tipc_port *sender, * (Must not hold any locks while building message.) */ res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, - sender->max_pkt, !sender->user_port, &buf); + sender->max_pkt, &buf); read_lock_bh(&tipc_net_lock); node = tipc_node_find(destaddr); @@ -1216,18 +1216,14 @@ static int link_send_sections_long(struct tipc_port *sender, else sz = fragm_rest; - if (likely(!sender->user_port)) { - if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { + if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { error: - for (; buf_chain; buf_chain = buf) { - buf = buf_chain->next; - kfree_skb(buf_chain); - } - return -EFAULT; + for (; buf_chain; buf_chain = buf) { + buf = buf_chain->next; + kfree_skb(buf_chain); } - } else - skb_copy_to_linear_data_offset(buf, fragm_crs, - sect_crs, sz); + return -EFAULT; + } sect_crs += sz; sect_rest -= sz; fragm_crs += sz; diff --git a/net/tipc/msg.c b/net/tipc/msg.c index f2db8a87d9c5..c2a261322515 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -73,8 +73,8 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, * Returns message data size or errno */ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, - u32 num_sect, unsigned int total_len, - int max_size, int usrmem, struct sk_buff **buf) + u32 num_sect, unsigned int total_len, int max_size, + struct sk_buff **buf) { int dsz, sz, hsz, pos, res, cnt; @@ -92,14 +92,9 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, return -ENOMEM; skb_copy_to_linear_data(*buf, hdr, hsz); for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { - if (likely(usrmem)) - res = !copy_from_user((*buf)->data + pos, - msg_sect[cnt].iov_base, - msg_sect[cnt].iov_len); - else - skb_copy_to_linear_data_offset(*buf, pos, - msg_sect[cnt].iov_base, - msg_sect[cnt].iov_len); + skb_copy_to_linear_data_offset(*buf, pos, + msg_sect[cnt].iov_base, + msg_sect[cnt].iov_len); pos += msg_sect[cnt].iov_len; } if (likely(res)) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index ba2a72beea68..511019a77c9c 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -722,6 +722,6 @@ u32 tipc_msg_tot_importance(struct tipc_msg *m); void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode); int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, - u32 num_sect, unsigned int total_len, - int max_size, int usrmem, struct sk_buff **buf); + u32 num_sect, unsigned int total_len, int max_size, + struct sk_buff **buf); #endif diff --git a/net/tipc/port.c b/net/tipc/port.c index 0651522c9435..f628c84a8f61 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -115,7 +115,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, msg_set_nameupper(hdr, seq->upper); msg_set_hdr_sz(hdr, MCAST_H_SIZE); res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, - !oport->user_port, &buf); + &buf); if (unlikely(!buf)) return res; @@ -234,7 +234,6 @@ struct tipc_port *tipc_createport_raw(void *usr_handle, INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); p_ptr->dispatcher = dispatcher; p_ptr->wakeup = wakeup; - p_ptr->user_port = NULL; k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); INIT_LIST_HEAD(&p_ptr->publications); INIT_LIST_HEAD(&p_ptr->port_list); @@ -271,7 +270,6 @@ int tipc_deleteport(u32 ref) buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); tipc_nodesub_unsubscribe(&p_ptr->subscription); } - kfree(p_ptr->user_port); spin_lock_bh(&tipc_port_list_lock); list_del(&p_ptr->port_list); @@ -444,7 +442,7 @@ int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, int res; res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, - !p_ptr->user_port, &buf); + &buf); if (!buf) return res; @@ -927,7 +925,7 @@ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_se int res; res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, - MAX_MSG_SIZE, !sender->user_port, &buf); + MAX_MSG_SIZE, &buf); if (likely(buf)) tipc_port_recv_msg(buf); return res; diff --git a/net/tipc/port.h b/net/tipc/port.h index 7fd37c202ce6..4779f0a82234 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -46,18 +46,6 @@ #define CONN_OVERLOAD_LIMIT ((TIPC_FLOW_CONTROL_WIN * 2 + 1) * \ SKB_TRUESIZE(TIPC_MAX_USER_MSG_SIZE)) -/** - * struct user_port - TIPC user port (used with native API) - * @usr_handle: user-specified field - * @ref: object reference to associated TIPC port - * - * - */ -struct user_port { - void *usr_handle; - u32 ref; -}; - /** * struct tipc_port - TIPC port structure * @usr_handle: pointer to additional user-defined information about port @@ -74,7 +62,6 @@ struct user_port { * @port_list: adjacent ports in TIPC's global list of ports * @dispatcher: ptr to routine which handles received messages * @wakeup: ptr to routine to call when port is no longer congested - * @user_port: ptr to user port associated with port (if any) * @wait_list: adjacent ports in list of ports waiting on link congestion * @waiting_pkts: * @sent: # of non-empty messages sent by port @@ -101,7 +88,6 @@ struct tipc_port { struct list_head port_list; u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); void (*wakeup)(struct tipc_port *); - struct user_port *user_port; struct list_head wait_list; u32 waiting_pkts; u32 sent; -- GitLab From 3c5db8e4eca36e4f312b49bba99f4c1f6ce0563a Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:44 -0400 Subject: [PATCH 1355/2900] tipc: rename tipc_createport_raw to tipc_createport After the removal of the native API, there is now only one way to to create a TIPC port instance -- the function tipc_createport_raw(). We make it more readable by renaming it to tipc_createport(). Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/port.c | 4 ++-- net/tipc/port.h | 2 +- net/tipc/socket.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index f628c84a8f61..84b2a574f161 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -202,11 +202,11 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) } /** - * tipc_createport_raw - create a generic TIPC port + * tipc_createport - create a generic TIPC port * * Returns pointer to (locked) TIPC port, or NULL if unable to create it */ -struct tipc_port *tipc_createport_raw(void *usr_handle, +struct tipc_port *tipc_createport(void *usr_handle, u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), void (*wakeup)(struct tipc_port *), const u32 importance) diff --git a/net/tipc/port.h b/net/tipc/port.h index 4779f0a82234..45838826f2f8 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -106,7 +106,7 @@ struct tipc_port_list; /* * TIPC port manipulation routines */ -struct tipc_port *tipc_createport_raw(void *usr_handle, +struct tipc_port *tipc_createport(void *usr_handle, u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), void (*wakeup)(struct tipc_port *), const u32 importance); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9510fe8acf45..67f4e1fbf5a1 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -195,8 +195,8 @@ static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, return -ENOMEM; /* Allocate TIPC port for socket to use */ - tp_ptr = tipc_createport_raw(sk, &dispatch, &wakeupdispatch, - TIPC_LOW_IMPORTANCE); + tp_ptr = tipc_createport(sk, &dispatch, &wakeupdispatch, + TIPC_LOW_IMPORTANCE); if (unlikely(!tp_ptr)) { sk_free(sk); return -ENOMEM; -- GitLab From 28e5297281ab85d636aa814a9b65cfb99375d092 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:45 -0400 Subject: [PATCH 1356/2900] tipc: convert config_lock from spinlock to mutex As the configuration server is now running under process context, it's unnecessary for us to have a spinlock serializing the TIPC configuration process. Instead, we replace it with a mutex lock, which gives us more freedom. For instance, we can now call pre-emptable functions within the protected area. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/config.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/net/tipc/config.c b/net/tipc/config.c index 4887ae04f3a5..c301a9a592d8 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c @@ -42,7 +42,7 @@ #define REPLY_TRUNCATED "\n" -static DEFINE_SPINLOCK(config_lock); +static DEFINE_MUTEX(config_mutex); static struct tipc_server cfgsrv; static const void *req_tlv_area; /* request message TLV area */ @@ -181,18 +181,7 @@ static struct sk_buff *cfg_set_own_addr(void) if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); - - /* - * Must temporarily release configuration spinlock while switching into - * networking mode as it calls tipc_eth_media_start(), which may sleep. - * Releasing the lock is harmless as other locally-issued configuration - * commands won't occur until this one completes, and remotely-issued - * configuration commands can't be received until a local configuration - * command to enable the first bearer is received and processed. - */ - spin_unlock_bh(&config_lock); tipc_core_start_net(addr); - spin_lock_bh(&config_lock); return tipc_cfg_reply_none(); } @@ -248,7 +237,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area { struct sk_buff *rep_tlv_buf; - spin_lock_bh(&config_lock); + mutex_lock(&config_mutex); /* Save request and reply details in a well-known location */ req_tlv_area = request_area; @@ -377,7 +366,7 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area /* Return reply buffer */ exit: - spin_unlock_bh(&config_lock); + mutex_unlock(&config_mutex); return rep_tlv_buf; } -- GitLab From c0fee8aca7206264d5e3dcc4e60aaf86501f4ea1 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:46 -0400 Subject: [PATCH 1357/2900] tipc: save sock structure pointer instead of void pointer to tipc_port Directly save sock structure pointer instead of void pointer to avoid unnecessary cast conversions. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/port.c | 4 ++-- net/tipc/port.h | 6 +++--- net/tipc/socket.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/net/tipc/port.c b/net/tipc/port.c index 84b2a574f161..0bb185a3ed4a 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -206,7 +206,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) * * Returns pointer to (locked) TIPC port, or NULL if unable to create it */ -struct tipc_port *tipc_createport(void *usr_handle, +struct tipc_port *tipc_createport(struct sock *sk, u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), void (*wakeup)(struct tipc_port *), const u32 importance) @@ -227,7 +227,7 @@ struct tipc_port *tipc_createport(void *usr_handle, return NULL; } - p_ptr->usr_handle = usr_handle; + p_ptr->sk = sk; p_ptr->max_pkt = MAX_PKT_DEFAULT; p_ptr->ref = ref; INIT_LIST_HEAD(&p_ptr->wait_list); diff --git a/net/tipc/port.h b/net/tipc/port.h index 45838826f2f8..241f529db942 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -48,7 +48,7 @@ /** * struct tipc_port - TIPC port structure - * @usr_handle: pointer to additional user-defined information about port + * @sk: pointer to socket handle * @lock: pointer to spinlock for controlling access to port * @connected: non-zero if port is currently connected to a peer port * @conn_type: TIPC type used when connection was established @@ -74,7 +74,7 @@ * @subscription: "node down" subscription used to terminate failed connections */ struct tipc_port { - void *usr_handle; + struct sock *sk; spinlock_t *lock; int connected; u32 conn_type; @@ -106,7 +106,7 @@ struct tipc_port_list; /* * TIPC port manipulation routines */ -struct tipc_port *tipc_createport(void *usr_handle, +struct tipc_port *tipc_createport(struct sock *sk, u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), void (*wakeup)(struct tipc_port *), const u32 importance); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 67f4e1fbf5a1..14ed54e961b6 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1406,7 +1406,7 @@ static int backlog_rcv(struct sock *sk, struct sk_buff *buf) */ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) { - struct sock *sk = (struct sock *)tport->usr_handle; + struct sock *sk = tport->sk; u32 res; /* @@ -1437,7 +1437,7 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) */ static void wakeupdispatch(struct tipc_port *tport) { - struct sock *sk = (struct sock *)tport->usr_handle; + struct sock *sk = tport->sk; sk->sk_write_space(sk); } -- GitLab From ae8509c420122866344bde1241e31858d0aa2fbc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 17 Jun 2013 10:54:47 -0400 Subject: [PATCH 1358/2900] tipc: cosmetic realignment of function arguments No runtime code changes here. Just a realign of the function arguments to start where the 1st one was, and fit as many args as can be put in an 80 char line. Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/bcast.c | 3 +-- net/tipc/bcast.h | 3 ++- net/tipc/discover.c | 7 +++---- net/tipc/eth_media.c | 2 +- net/tipc/link.c | 18 +++++++----------- net/tipc/msg.c | 4 ++-- net/tipc/msg.h | 4 ++-- net/tipc/name_table.c | 10 +++++----- net/tipc/name_table.h | 11 ++++++----- net/tipc/node_subscr.c | 2 +- net/tipc/port.c | 7 ++++--- net/tipc/port.h | 10 ++++++---- net/tipc/socket.c | 12 ++++++------ net/tipc/subscr.c | 14 ++++---------- net/tipc/subscr.h | 13 ++++--------- 15 files changed, 54 insertions(+), 66 deletions(-) diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e5f3da507823..716de1ac6cb5 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -578,8 +578,7 @@ u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr) * Returns 0 (packet sent successfully) under all circumstances, * since the broadcast link's pseudo-bearer never blocks */ -static int tipc_bcbearer_send(struct sk_buff *buf, - struct tipc_bearer *unused1, +static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, struct tipc_media_addr *unused2) { int bp_index; diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index a93306557e00..6ee587b469fd 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -75,7 +75,8 @@ void tipc_nmap_remove(struct tipc_node_map *nm_ptr, u32 node); /** * tipc_nmap_equal - test for equality of node maps */ -static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, struct tipc_node_map *nm_b) +static inline int tipc_nmap_equal(struct tipc_node_map *nm_a, + struct tipc_node_map *nm_b) { return !memcmp(nm_a, nm_b, sizeof(*nm_a)); } diff --git a/net/tipc/discover.c b/net/tipc/discover.c index eedff58d0387..ecc758c6eacf 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c @@ -70,8 +70,7 @@ struct tipc_link_req { * @dest_domain: network domain of node(s) which should respond to message * @b_ptr: ptr to bearer issuing message */ -static struct sk_buff *tipc_disc_init_msg(u32 type, - u32 dest_domain, +static struct sk_buff *tipc_disc_init_msg(u32 type, u32 dest_domain, struct tipc_bearer *b_ptr) { struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE); @@ -346,8 +345,8 @@ static void disc_timeout(struct tipc_link_req *req) * * Returns 0 if successful, otherwise -errno. */ -int tipc_disc_create(struct tipc_bearer *b_ptr, - struct tipc_media_addr *dest, u32 dest_domain) +int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, + u32 dest_domain) { struct tipc_link_req *req; diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index fc60bea63169..c1aa37fdca2f 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -62,7 +62,7 @@ static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; static int eth_started; static int recv_notification(struct notifier_block *nb, unsigned long evt, - void *dv); + void *dv); /* * Network device notifier info */ diff --git a/net/tipc/link.c b/net/tipc/link.c index d34429d03c16..b852c94a784e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -771,8 +771,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) * link_bundle_buf(): Append contents of a buffer to * the tail of an existing one. */ -static int link_bundle_buf(struct tipc_link *l_ptr, - struct sk_buff *bundler, +static int link_bundle_buf(struct tipc_link *l_ptr, struct sk_buff *bundler, struct sk_buff *buf) { struct tipc_msg *bundler_msg = buf_msg(bundler); @@ -1064,8 +1063,7 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, */ int tipc_link_send_sections_fast(struct tipc_port *sender, struct iovec const *msg_sect, - const u32 num_sect, - unsigned int total_len, + const u32 num_sect, unsigned int total_len, u32 destaddr) { struct tipc_msg *hdr = &sender->phdr; @@ -1155,8 +1153,7 @@ int tipc_link_send_sections_fast(struct tipc_port *sender, */ static int link_send_sections_long(struct tipc_port *sender, struct iovec const *msg_sect, - u32 num_sect, - unsigned int total_len, + u32 num_sect, unsigned int total_len, u32 destaddr) { struct tipc_link *l_ptr; @@ -1408,7 +1405,7 @@ static void link_reset_all(unsigned long addr) } static void link_retransmit_failure(struct tipc_link *l_ptr, - struct sk_buff *buf) + struct sk_buff *buf) { struct tipc_msg *msg = buf_msg(buf); @@ -1863,8 +1860,8 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, * Send protocol message to the other endpoint. */ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, - int probe_msg, u32 gap, u32 tolerance, - u32 priority, u32 ack_mtu) + int probe_msg, u32 gap, u32 tolerance, + u32 priority, u32 ack_mtu) { struct sk_buff *buf = NULL; struct tipc_msg *msg = l_ptr->pmsg; @@ -2107,8 +2104,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) * another bearer. Owner node is locked. */ static void tipc_link_tunnel(struct tipc_link *l_ptr, - struct tipc_msg *tunnel_hdr, - struct tipc_msg *msg, + struct tipc_msg *tunnel_hdr, struct tipc_msg *msg, u32 selector) { struct tipc_link *tunnel; diff --git a/net/tipc/msg.c b/net/tipc/msg.c index c2a261322515..ced60e2fc4f7 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -51,8 +51,8 @@ u32 tipc_msg_tot_importance(struct tipc_msg *m) } -void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, - u32 hsize, u32 destnode) +void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, + u32 destnode) { memset(m, 0, hsize); msg_set_version(m); diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 511019a77c9c..5e4ccf5c27df 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -719,8 +719,8 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) } u32 tipc_msg_tot_importance(struct tipc_msg *m); -void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, - u32 hsize, u32 destnode); +void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, + u32 destnode); int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, u32 num_sect, unsigned int total_len, int max_size, struct sk_buff **buf); diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 24b167914311..09dcd54b04e1 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -440,7 +440,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i * sequence overlapping with the requested sequence */ static void tipc_nameseq_subscribe(struct name_seq *nseq, - struct tipc_subscription *s) + struct tipc_subscription *s) { struct sub_seq *sseq = nseq->sseqs; @@ -662,7 +662,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, * tipc_nametbl_publish - add name publication to network name tables */ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, - u32 scope, u32 port_ref, u32 key) + u32 scope, u32 port_ref, u32 key) { struct publication *publ; @@ -753,7 +753,7 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) * subseq_list - print specified sub-sequence contents into the given buffer */ static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, - u32 index) + u32 index) { char portIdStr[27]; const char *scope_str[] = {"", " zone", " cluster", " node"}; @@ -792,7 +792,7 @@ static int subseq_list(struct sub_seq *sseq, char *buf, int len, u32 depth, * nameseq_list - print specified name sequence contents into the given buffer */ static int nameseq_list(struct name_seq *seq, char *buf, int len, u32 depth, - u32 type, u32 lowbound, u32 upbound, u32 index) + u32 type, u32 lowbound, u32 upbound, u32 index) { struct sub_seq *sseq; char typearea[11]; @@ -849,7 +849,7 @@ static int nametbl_header(char *buf, int len, u32 depth) * nametbl_list - print specified name table contents into the given buffer */ static int nametbl_list(char *buf, int len, u32 depth_info, - u32 type, u32 lowbound, u32 upbound) + u32 type, u32 lowbound, u32 upbound) { struct hlist_head *seq_head; struct name_seq *seq; diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h index 71cb4dc712df..f02f48b9a216 100644 --- a/net/tipc/name_table.h +++ b/net/tipc/name_table.h @@ -87,14 +87,15 @@ extern rwlock_t tipc_nametbl_lock; struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space); u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node); int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, - struct tipc_port_list *dports); + struct tipc_port_list *dports); struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, - u32 scope, u32 port_ref, u32 key); + u32 scope, u32 port_ref, u32 key); int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, - u32 scope, u32 node, u32 ref, u32 key); -struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, - u32 node, u32 ref, u32 key); + u32 scope, u32 node, u32 ref, + u32 key); +struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, u32 node, + u32 ref, u32 key); void tipc_nametbl_subscribe(struct tipc_subscription *s); void tipc_nametbl_unsubscribe(struct tipc_subscription *s); int tipc_nametbl_init(void); diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index 5e34b015da45..8a7384c04add 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c @@ -42,7 +42,7 @@ * tipc_nodesub_subscribe - create "node down" subscription for specified node */ void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, - void *usr_handle, net_ev_handler handle_down) + void *usr_handle, net_ev_handler handle_down) { if (in_own_node(addr)) { node_sub->node = NULL; diff --git a/net/tipc/port.c b/net/tipc/port.c index 0bb185a3ed4a..b3ed2fcab4fb 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c @@ -207,9 +207,10 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) * Returns pointer to (locked) TIPC port, or NULL if unable to create it */ struct tipc_port *tipc_createport(struct sock *sk, - u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), - void (*wakeup)(struct tipc_port *), - const u32 importance) + u32 (*dispatcher)(struct tipc_port *, + struct sk_buff *), + void (*wakeup)(struct tipc_port *), + const u32 importance) { struct tipc_port *p_ptr; struct tipc_msg *msg; diff --git a/net/tipc/port.h b/net/tipc/port.h index 241f529db942..5a7026b9c345 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h @@ -107,8 +107,10 @@ struct tipc_port_list; * TIPC port manipulation routines */ struct tipc_port *tipc_createport(struct sock *sk, - u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), - void (*wakeup)(struct tipc_port *), const u32 importance); + u32 (*dispatcher)(struct tipc_port *, + struct sk_buff *), + void (*wakeup)(struct tipc_port *), + const u32 importance); int tipc_reject_msg(struct sk_buff *buf, u32 err); @@ -126,9 +128,9 @@ int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); int tipc_publish(u32 portref, unsigned int scope, - struct tipc_name_seq const *name_seq); + struct tipc_name_seq const *name_seq); int tipc_withdraw(u32 portref, unsigned int scope, - struct tipc_name_seq const *name_seq); + struct tipc_name_seq const *name_seq); int tipc_connect(u32 portref, struct tipc_portid const *port); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 14ed54e961b6..ce8249c76827 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -278,7 +278,7 @@ void tipc_sock_release_local(struct socket *sock) */ int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, - int flags) + int flags) { struct sock *sk = sock->sk; int ret; @@ -889,7 +889,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) * Returns 0 if successful, otherwise errno */ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, - struct tipc_port *tport) + struct tipc_port *tport) { u32 anc_data[3]; u32 err; @@ -1736,8 +1736,8 @@ static int shutdown(struct socket *sock, int how) * * Returns 0 on success, errno otherwise */ -static int setsockopt(struct socket *sock, - int lvl, int opt, char __user *ov, unsigned int ol) +static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, + unsigned int ol) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); @@ -1795,8 +1795,8 @@ static int setsockopt(struct socket *sock, * * Returns 0 on success, errno otherwise */ -static int getsockopt(struct socket *sock, - int lvl, int opt, char __user *ov, int __user *ol) +static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, + int __user *ol) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index f6be92a6973a..d38bb45d82e9 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -117,10 +117,8 @@ static void subscr_send_event(struct tipc_subscription *sub, u32 found_lower, * * Returns 1 if there is overlap, otherwise 0. */ -int tipc_subscr_overlap(struct tipc_subscription *sub, - u32 found_lower, +int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper) - { if (found_lower < sub->seq.lower) found_lower = sub->seq.lower; @@ -136,13 +134,9 @@ int tipc_subscr_overlap(struct tipc_subscription *sub, * * Protected by nameseq.lock in name_table.c */ -void tipc_subscr_report_overlap(struct tipc_subscription *sub, - u32 found_lower, - u32 found_upper, - u32 event, - u32 port_ref, - u32 node, - int must) +void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, + u32 found_upper, u32 event, u32 port_ref, + u32 node, int must) { if (!tipc_subscr_overlap(sub, found_lower, found_upper)) return; diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 43e6d6332a02..393e417bee3f 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -67,17 +67,12 @@ struct tipc_subscription { struct tipc_event evt; }; -int tipc_subscr_overlap(struct tipc_subscription *sub, - u32 found_lower, +int tipc_subscr_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper); -void tipc_subscr_report_overlap(struct tipc_subscription *sub, - u32 found_lower, - u32 found_upper, - u32 event, - u32 port_ref, - u32 node, - int must_report); +void tipc_subscr_report_overlap(struct tipc_subscription *sub, u32 found_lower, + u32 found_upper, u32 event, u32 port_ref, + u32 node, int must); int tipc_subscr_start(void); -- GitLab From 796c75d0d3ef13cd1df00779abb8b27edb630504 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:48 -0400 Subject: [PATCH 1359/2900] tipc: enhance priority of link protocol packet pfifo_fast is set as default traffic class queueing discipline. This queue has three so called "bands". Within each band, FIFO rules apply. However, as long as there are packets waiting in band 0, band 1 won't be processed. Now all kind of TIPC type packet priorities are never set, that is, their priorities are 0, so they are mapped to band 1 of pfifo_fast qdisc. But, especially during link congestion, if link protocol packet can be sent out as earlier as possible than other type of packets so that protocol packet can arrive at peer endpoint in time, the peer will timely reset its link timeout timer to keep the link alive. So enhancing the priority of link protocol packets can meet the specific demand to avoid unnecessary link reset due to a transient link congestion. Signed-off-by: Ying Xue Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/tipc/link.c b/net/tipc/link.c index b852c94a784e..b6de1aa059f4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -41,6 +41,8 @@ #include "discover.h" #include "config.h" +#include + /* * Error message prefixes */ @@ -1947,6 +1949,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, return; skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg)); + buf->priority = TC_PRIO_CONTROL; /* Defer message if bearer is already blocked */ if (tipc_bearer_blocked(l_ptr->b_ptr)) { -- GitLab From 7410f967ba9bdc14b1e336e5d235929ed878cbfc Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:49 -0400 Subject: [PATCH 1360/2900] tipc: make tipc_link_send_sections_fast exit earlier Once message build request function returns invalid code, the process of sending message cannot continue. So in case of message build failure, tipc_link_send_sections_fast() should return immediately. Signed-off-by: Ying Xue Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index b6de1aa059f4..b6ffa9fab244 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1082,6 +1082,9 @@ int tipc_link_send_sections_fast(struct tipc_port *sender, */ res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, sender->max_pkt, &buf); + /* Exit if build request was invalid */ + if (unlikely(res < 0)) + return res; read_lock_bh(&tipc_net_lock); node = tipc_node_find(destaddr); @@ -1098,10 +1101,6 @@ int tipc_link_send_sections_fast(struct tipc_port *sender, return res; } - /* Exit if build request was invalid */ - if (unlikely(res < 0)) - goto exit; - /* Exit if link (or bearer) is congested */ if (link_congested(l_ptr) || tipc_bearer_blocked(l_ptr->b_ptr)) { -- GitLab From 126c0524648631a0f6fba4d016586b236209fe6f Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:50 -0400 Subject: [PATCH 1361/2900] tipc: fix wrong return value for link_send_sections_long routine When skb buffer cannot be allocated in link_send_sections_long(), -ENOMEM error code instead of -EFAULT should be returned to its caller. Signed-off-by: Ying Xue Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/link.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index b6ffa9fab244..0cc3d9015c5d 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1168,6 +1168,7 @@ static int link_send_sections_long(struct tipc_port *sender, const unchar *sect_crs; int curr_sect; u32 fragm_no; + int res = 0; again: fragm_no = 1; @@ -1215,12 +1216,13 @@ static int link_send_sections_long(struct tipc_port *sender, sz = fragm_rest; if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { + res = -EFAULT; error: for (; buf_chain; buf_chain = buf) { buf = buf_chain->next; kfree_skb(buf_chain); } - return -EFAULT; + return res; } sect_crs += sz; sect_rest -= sz; @@ -1241,8 +1243,10 @@ static int link_send_sections_long(struct tipc_port *sender, msg_set_fragm_no(&fragm_hdr, ++fragm_no); prev = buf; buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE); - if (!buf) + if (!buf) { + res = -ENOMEM; goto error; + } buf->next = NULL; prev->next = buf; -- GitLab From 2537af9dcabbdd6c93c041a955d3a9ae42c0c008 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 17 Jun 2013 10:54:51 -0400 Subject: [PATCH 1362/2900] tipc: remove dev_base_lock use from enable_bearer Convert enable_bearer() to RCU locking with dev_get_by_name(). Based on a similar changeset in commit 840a185d ["aoe: remove dev_base_lock use from aoecmd_cfg_pkts()"] -- quoting that: "dev_base_lock is the legacy way to lock the device list, and is planned to disappear. (writers hold RTNL, readers hold RCU lock)" Signed-off-by: Ying Xue Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- net/tipc/eth_media.c | 13 ++----------- net/tipc/ib_media.c | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index c1aa37fdca2f..40ea40cf6204 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -162,8 +162,7 @@ static void setup_bearer(struct work_struct *work) */ static int enable_bearer(struct tipc_bearer *tb_ptr) { - struct net_device *dev = NULL; - struct net_device *pdev = NULL; + struct net_device *dev; struct eth_bearer *eb_ptr = ð_bearers[0]; struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; @@ -178,15 +177,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) } /* Find device with specified name */ - read_lock(&dev_base_lock); - for_each_netdev(&init_net, pdev) { - if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) { - dev = pdev; - dev_hold(dev); - break; - } - } - read_unlock(&dev_base_lock); + dev = dev_get_by_name(&init_net, driver_name); if (!dev) return -ENODEV; diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c index baa9df4327d9..ad2e1ec4117e 100644 --- a/net/tipc/ib_media.c +++ b/net/tipc/ib_media.c @@ -155,8 +155,7 @@ static void setup_bearer(struct work_struct *work) */ static int enable_bearer(struct tipc_bearer *tb_ptr) { - struct net_device *dev = NULL; - struct net_device *pdev = NULL; + struct net_device *dev; struct ib_bearer *ib_ptr = &ib_bearers[0]; struct ib_bearer *stop = &ib_bearers[MAX_IB_BEARERS]; char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; @@ -171,15 +170,7 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) } /* Find device with specified name */ - read_lock(&dev_base_lock); - for_each_netdev(&init_net, pdev) { - if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) { - dev = pdev; - dev_hold(dev); - break; - } - } - read_unlock(&dev_base_lock); + dev = dev_get_by_name(&init_net, driver_name); if (!dev) return -ENODEV; -- GitLab From 72bb72b0d98847d22c6fae4e170121f3640f0f60 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 17 Jun 2013 13:47:25 -0700 Subject: [PATCH 1363/2900] tg3: Prevent system hang during repeated EEH errors. The current tg3 code assumes the pci_error_handlers to be always called in sequence. In particular, during ->error_detected(), NAPI is disabled and the device is shutdown. The device is later reset and NAPI re-enabled in ->slot_reset() and ->resume(). In EEH, if more than 6 errors are detected in a hour, only ->error_detected() will be called. This will leave the driver in an inconsistent state as NAPI is disabled but netif_running state is still true. When the device is later closed, we'll try to disable NAPI again and it will loop forever. We fix this by closing the device if we encounter any error conditions during the normal sequence of the pci_error_handlers. v2: Remove the changes in tg3_io_resume() based on Benjamin Poirier's feedback. Signed-off-by: Michael Chan Signed-off-by: Nithin Nayak Sujir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 28a645fc68bf..297fc138fa15 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17747,10 +17747,13 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, tg3_full_unlock(tp); done: - if (state == pci_channel_io_perm_failure) + if (state == pci_channel_io_perm_failure) { + tg3_napi_enable(tp); + dev_close(netdev); err = PCI_ERS_RESULT_DISCONNECT; - else + } else { pci_disable_device(pdev); + } rtnl_unlock(); @@ -17796,6 +17799,10 @@ static pci_ers_result_t tg3_io_slot_reset(struct pci_dev *pdev) rc = PCI_ERS_RESULT_RECOVERED; done: + if (rc != PCI_ERS_RESULT_RECOVERED && netif_running(netdev)) { + tg3_napi_enable(tp); + dev_close(netdev); + } rtnl_unlock(); return rc; -- GitLab From 618fa57512c724d1d1a446162ad853249f8ac717 Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Fri, 14 Jun 2013 01:21:45 -0400 Subject: [PATCH 1364/2900] mfd: 88pm800: Fix NULL pointer dereference Move "device_800_init" to fix NULL pointer error when calling "device_gpadc_init" as it needs "subchip->regmap_gpadc" to set registers via regmap interface Signed-off-by: Yi Zhang Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 582bda543520..b2f9f0f9deb3 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -528,24 +528,26 @@ static int pm800_probe(struct i2c_client *client, subchip->gpadc_page_addr = pdata->gpadc_page_addr; chip->subchip = subchip; - ret = device_800_init(chip, pdata); - if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); - goto err_subchip_alloc; - } - ret = pm800_pages_init(chip); if (ret) { dev_err(&client->dev, "pm800_pages_init failed!\n"); goto err_page_init; } + ret = device_800_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + goto err_device_init; + } + if (pdata->plat_config) pdata->plat_config(chip, pdata); + return 0; + +err_device_init: + pm800_pages_exit(chip); err_page_init: - mfd_remove_devices(chip->dev); - device_irq_exit_800(chip); err_subchip_alloc: pm80x_deinit(); out_init: -- GitLab From 46223a19ad566dee955969c9a2cea55ef59f21d8 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:46 -0400 Subject: [PATCH 1365/2900] mfd: 88pm80x: Fix driver name for 88pm800 and 88pm805 88pm800 and 88pm805 shouldnot have the same driver name. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 2 +- drivers/mfd/88pm805.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index b2f9f0f9deb3..080104988d5e 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -569,7 +569,7 @@ static int pm800_remove(struct i2c_client *client) static struct i2c_driver pm800_driver = { .driver = { - .name = "88PM80X", + .name = "88PM800", .owner = THIS_MODULE, .pm = &pm80x_pm_ops, }, diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 65d7ac099b20..d32b54464e85 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -276,7 +276,7 @@ static int pm805_remove(struct i2c_client *client) static struct i2c_driver pm805_driver = { .driver = { - .name = "88PM80X", + .name = "88PM805", .owner = THIS_MODULE, .pm = &pm80x_pm_ops, }, -- GitLab From cb5c5800933d483babed13d78a53fde8c47d93c5 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:47 -0400 Subject: [PATCH 1366/2900] mfd: 88pm800: Initialize mask_invert mask_invert must be set otherwise interrupts cannot be cleared. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 080104988d5e..cca63f255d53 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -362,6 +362,7 @@ static struct regmap_irq_chip pm800_irq_chip = { .status_base = PM800_INT_STATUS1, .mask_base = PM800_INT_ENA_1, .ack_base = PM800_INT_STATUS1, + .mask_invert = 1, }; static int pm800_pages_init(struct pm80x_chip *chip) -- GitLab From 1ef5677e0e45c77ca05e697fb83d4f9b3fe96caf Mon Sep 17 00:00:00 2001 From: Yi Zhang Date: Fri, 14 Jun 2013 01:21:48 -0400 Subject: [PATCH 1367/2900] mfd: 88pm800: 88pm805: Remove "IRQF_TRIGGER_FALLING" flag 88pm800/88pm805 interrupt is asserted low if the events happened. So remove IRQF_TRIGGER_FALLING for irq request. Also, the interrupt wiring is board dependent so do not set IRQF_TRIGGER by default. Signed-off-by: Yi Zhang Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 2 +- drivers/mfd/88pm805.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index cca63f255d53..d2951d749bf3 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -318,7 +318,7 @@ static int device_gpadc_init(struct pm80x_chip *chip, static int device_irq_init_800(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned long flags = IRQF_ONESHOT; int data, mask, ret = -EINVAL; if (!map || !chip->irq) { diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index d32b54464e85..0e82c2a1e842 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -138,7 +138,7 @@ static struct regmap_irq pm805_irqs[] = { static int device_irq_init_805(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned long flags = IRQF_ONESHOT; int data, mask, ret = -EINVAL; if (!map || !chip->irq) { -- GitLab From c750d8e053c08ccb82d814d695e64d1eb602a91a Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:49 -0400 Subject: [PATCH 1368/2900] mfd: 88pm800: Remove the power and gpadc page addr from platform data 88pm800 has two addtional pages - power and gpadc. The address of the pages depends on the address of 88pm800. So do not need pass the address of the power and gpadc in platform data. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 5 +++-- include/linux/mfd/88pm80x.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index d2951d749bf3..6b607adebce1 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -525,8 +525,9 @@ static int pm800_probe(struct i2c_client *client, goto err_subchip_alloc; } - subchip->power_page_addr = pdata->power_page_addr; - subchip->gpadc_page_addr = pdata->gpadc_page_addr; + /* pm800 has 2 addtional pages to support power and gpadc. */ + subchip->power_page_addr = client->addr + 1; + subchip->gpadc_page_addr = client->addr + 2; chip->subchip = subchip; ret = pm800_pages_init(chip); diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index e94537befabd..023e6395da87 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -309,8 +309,6 @@ struct pm80x_chip { struct pm80x_platform_data { struct pm80x_rtc_pdata *rtc; - unsigned short power_page_addr; /* power page I2C address */ - unsigned short gpadc_page_addr; /* gpadc page I2C address */ int irq_mode; /* Clear interrupt by read/write(0/1) */ int batt_det; /* enable/disable */ int (*plat_config)(struct pm80x_chip *chip, -- GitLab From b3ba020652d1659ce3c07314fabffbe124fe49dd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 17 Jun 2013 12:27:17 -0700 Subject: [PATCH 1369/2900] thermal: fix x86_pkg_temp_thermal.c build and Kconfig Fix build error in x86_pkg_temp_thermal.c. It requires that X86_MCE & X86_THERMAL_VECTOR be enabled, so depend on the latter symbol, since it depends on X86_MCE (indirectly). Also, X86_PKG_TEMP_THERMAL is already inside an "if THERMAL" block, so remove that duplicated dependency. ERROR: "platform_thermal_package_rate_control" [drivers/thermal/x86_pkg_temp_thermal.ko] undefined! ERROR: "platform_thermal_package_notify" [drivers/thermal/x86_pkg_temp_thermal.ko] undefined! Signed-off-by: Randy Dunlap Acked-by: Borislav Petkov Signed-off-by: Zhang Rui --- drivers/thermal/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 245831ccda3e..2ff5cb9bff87 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -171,8 +171,7 @@ config INTEL_POWERCLAMP config X86_PKG_TEMP_THERMAL tristate "X86 package temperature thermal driver" - depends on THERMAL - depends on X86 + depends on X86_THERMAL_VECTOR select THERMAL_GOV_USER_SPACE default m help -- GitLab From cedb743f3e8db12cc76a706888792497953e93bb Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 17 Jun 2013 19:30:35 +0200 Subject: [PATCH 1370/2900] bonding: don't call alb_set_slave_mac_addr() while atomic alb_set_slave_mac_addr() sets the mac address in alb mode via dev_set_mac_address(), which might sleep. It's called from alb_handle_addr_collision_on_attach() in atomic context (under read_lock(bond->lock)), thus triggering a bug. Fix this by moving the lock inside alb_handle_addr_collision_on_attach(). v1->v2: As Nikolay Aleksandrov noticed, we can drop the bond->lock completely. Also, use bond_slave_has_mac(), when possible. Signed-off-by: Veaceslav Falico Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 40 +++++----------------------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index a236234d2c27..27fe329bdf83 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1175,16 +1175,13 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla * @slave. * * assumption: this function is called before @slave is attached to the - * bond slave list. - * - * caller must hold the bond lock for write since the mac addresses are compared - * and may be swapped. + * bond slave list. */ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave) { - struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave; + struct slave *tmp_slave1, *free_mac_slave = NULL; struct slave *has_bond_addr = bond->curr_active_slave; - int i, j, found = 0; + int i; if (bond->slave_cnt == 0) { /* this is the first slave */ @@ -1196,15 +1193,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav * slaves in the bond. */ if (!ether_addr_equal_64bits(slave->perm_hwaddr, bond->dev->dev_addr)) { - bond_for_each_slave(bond, tmp_slave1, i) { - if (ether_addr_equal_64bits(tmp_slave1->dev->dev_addr, - slave->dev->dev_addr)) { - found = 1; - break; - } - } - - if (!found) + if (!bond_slave_has_mac(bond, slave->dev->dev_addr)) return 0; /* Try setting slave mac to bond address and fall-through @@ -1215,19 +1204,8 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav /* The slave's address is equal to the address of the bond. * Search for a spare address in the bond for this slave. */ - free_mac_slave = NULL; - bond_for_each_slave(bond, tmp_slave1, i) { - found = 0; - bond_for_each_slave(bond, tmp_slave2, j) { - if (ether_addr_equal_64bits(tmp_slave1->perm_hwaddr, - tmp_slave2->dev->dev_addr)) { - found = 1; - break; - } - } - - if (!found) { + if (!bond_slave_has_mac(bond, tmp_slave1->perm_hwaddr)) { /* no slave has tmp_slave1's perm addr * as its curr addr */ @@ -1607,15 +1585,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) return res; } - /* caller must hold the bond lock for write since the mac addresses - * are compared and may be swapped. - */ - read_lock(&bond->lock); - res = alb_handle_addr_collision_on_attach(bond, slave); - - read_unlock(&bond->lock); - if (res) { return res; } -- GitLab From 32bc9b46d840d08e1c8f58eaf500d0e596c33659 Mon Sep 17 00:00:00 2001 From: Chris Healy Date: Mon, 17 Jun 2013 07:25:06 -0700 Subject: [PATCH 1371/2900] fec: Add support to restart autonegotiate Add ethtool operation to restart autonegotiation via the PHY. Tested on i.MX28EVK. Signed-off-by: Chris Healy Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index c540055e4f4f..46f2544fd1a7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1435,6 +1435,17 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, return 0; } +static int fec_enet_nway_reset(struct net_device *dev) +{ + struct fec_enet_private *fep = netdev_priv(dev); + struct phy_device *phydev = fep->phy_dev; + + if (!phydev) + return -ENODEV; + + return genphy_restart_aneg(phydev); +} + static const struct ethtool_ops fec_enet_ethtool_ops = { .get_pauseparam = fec_enet_get_pauseparam, .set_pauseparam = fec_enet_set_pauseparam, @@ -1443,6 +1454,7 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .get_drvinfo = fec_enet_get_drvinfo, .get_link = ethtool_op_get_link, .get_ts_info = fec_enet_get_ts_info, + .nway_reset = fec_enet_nway_reset, }; static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -- GitLab From 939cfa75a0cea97aa60cb88e3722baefdceb4e72 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 17 Jun 2013 11:40:04 +0200 Subject: [PATCH 1372/2900] net: sctp: get rid of t_new macro for kzalloc t_new rather obfuscates things where everyone else is using actual function names instead of that macro, so replace it with kzalloc, which is the function t_new wraps. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 3 --- net/sctp/associola.c | 2 +- net/sctp/bind_addr.c | 2 +- net/sctp/endpointola.c | 3 ++- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 2 +- net/sctp/transport.c | 2 +- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index cd89510eab2a..b9f136ad5a5a 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -575,9 +575,6 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\ /* Round an int up to the next multiple of 4. */ #define WORD_ROUND(s) (((s)+3)&~3) -/* Make a new instance of type. */ -#define t_new(type, flags) kzalloc(sizeof(type), flags) - /* Compare two timevals. */ #define tv_lt(s, t) \ (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec)) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 756025c98e85..bf6e6bd553c0 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -355,7 +355,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, { struct sctp_association *asoc; - asoc = t_new(struct sctp_association, gfp); + asoc = kzalloc(sizeof(*asoc), gfp); if (!asoc) goto fail; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 41145fe31813..64977ea0f9c5 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -162,7 +162,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, struct sctp_sockaddr_entry *addr; /* Add the address to the bind address list. */ - addr = t_new(struct sctp_sockaddr_entry, gfp); + addr = kzalloc(sizeof(*addr), gfp); if (!addr) return -ENOMEM; diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 5fbd7bc6bb11..a8b26741c0af 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -192,9 +192,10 @@ struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp) struct sctp_endpoint *ep; /* Build a local endpoint. */ - ep = t_new(struct sctp_endpoint, gfp); + ep = kzalloc(sizeof(*ep), gfp); if (!ep) goto fail; + if (!sctp_endpoint_init(ep, sk, gfp)) goto fail_init; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index fffc7b62a9a8..4f3e13b31fcc 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -402,7 +402,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, read_lock_bh(&in6_dev->lock); list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { /* Add the address to the local list. */ - addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); + addr = kzalloc(sizeof(*addr), GFP_ATOMIC); if (addr) { addr->a.v6.sin6_family = AF_INET6; addr->a.v6.sin6_port = 0; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index eaee00c61139..fad7d1b67be5 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -153,7 +153,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { /* Add the address to the local list. */ - addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); + addr = kzalloc(sizeof(*addr), GFP_ATOMIC); if (addr) { addr->a.v4.sin_family = AF_INET; addr->a.v4.sin_port = 0; diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 098f1d5f769e..5d3c71bbd197 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -116,7 +116,7 @@ struct sctp_transport *sctp_transport_new(struct net *net, { struct sctp_transport *transport; - transport = t_new(struct sctp_transport, gfp); + transport = kzalloc(sizeof(*transport), gfp); if (!transport) goto fail; -- GitLab From dda9192851dcf904b4d1095480834f2a4f814ae3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 17 Jun 2013 11:40:05 +0200 Subject: [PATCH 1373/2900] net: sctp: remove SCTP_STATIC macro SCTP_STATIC is just another define for the static keyword. It's use is inconsistent in the SCTP code anyway and it was introduced in the initial implementation of SCTP in 2.5. We have a regression suite in lksctp-tools, but this is for user space only, so noone makes use of this macro anymore. The kernel test suite for 2.5 is incompatible with the current SCTP code anyway. So simply Remove it, to be more consistent with the rest of the kernel code. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 8 ----- net/sctp/chunk.c | 2 +- net/sctp/input.c | 4 +-- net/sctp/ipv6.c | 4 +-- net/sctp/protocol.c | 4 +-- net/sctp/sm_make_chunk.c | 10 +++--- net/sctp/socket.c | 78 +++++++++++++++++++--------------------- net/sctp/tsnmap.c | 10 +++--- net/sctp/ulpevent.c | 10 +++--- 9 files changed, 57 insertions(+), 73 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index b9f136ad5a5a..6321c081118f 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -99,14 +99,6 @@ #define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT #endif - -/* Certain internal static functions need to be exported when - * compiled into the test frame. - */ -#ifndef SCTP_STATIC -#define SCTP_STATIC static -#endif - /* * Function declarations. */ diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 69ce21e3716f..7135fc0c087a 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -66,7 +66,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg) } /* Allocate and initialize datamsg. */ -SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp) +static struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp) { struct sctp_datamsg *msg; msg = kmalloc(sizeof(struct sctp_datamsg), gfp); diff --git a/net/sctp/input.c b/net/sctp/input.c index 6533d81a638d..4cfc74699a3f 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -903,11 +903,11 @@ static struct sctp_association *__sctp_lookup_association( } /* Look up an association. BH-safe. */ -SCTP_STATIC +static struct sctp_association *sctp_lookup_association(struct net *net, const union sctp_addr *laddr, const union sctp_addr *paddr, - struct sctp_transport **transportp) + struct sctp_transport **transportp) { struct sctp_association *asoc; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 4f3e13b31fcc..adeaa0e64f52 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -145,8 +145,8 @@ static struct notifier_block sctp_inet6addr_notifier = { }; /* ICMP error handler. */ -SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - u8 type, u8 code, int offset, __be32 info) +static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) { struct inet6_dev *idev; struct sock *sk; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index fad7d1b67be5..57b568c38ef6 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1312,7 +1312,7 @@ static struct pernet_operations sctp_net_ops = { }; /* Initialize the universe into something sensible. */ -SCTP_STATIC __init int sctp_init(void) +static __init int sctp_init(void) { int i; int status = -EINVAL; @@ -1499,7 +1499,7 @@ SCTP_STATIC __init int sctp_init(void) } /* Exit handler for the SCTP protocol. */ -SCTP_STATIC __exit void sctp_exit(void) +static __exit void sctp_exit(void) { /* BUG. This should probably do something useful like clean * up all the remaining associations and all that memory. diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index cf579e71cff0..fc8548743ed5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -68,9 +68,8 @@ #include #include -SCTP_STATIC -struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, - __u8 type, __u8 flags, int paylen); +static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, + __u8 type, __u8 flags, int paylen); static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, const struct sctp_association *asoc, const struct sctp_chunk *init_chunk, @@ -1353,9 +1352,8 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk) /* Create a new chunk, setting the type and flags headers from the * arguments, reserving enough space for a 'paylen' byte payload. */ -SCTP_STATIC -struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, - __u8 type, __u8 flags, int paylen) +static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, + __u8 type, __u8 flags, int paylen) { struct sctp_chunk *retval; sctp_chunkhdr_t *chunk_hdr; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 510dc79a32a1..75fe92ac2e9c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -84,11 +84,6 @@ #include #include -/* WARNING: Please do not remove the SCTP_STATIC attribute to - * any of the functions below as they are used to export functions - * used by a project regression testsuite. - */ - /* Forward declarations for internal helper functions. */ static int sctp_writeable(struct sock *sk); static void sctp_wfree(struct sk_buff *skb); @@ -279,7 +274,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, * sockaddr_in6 [RFC 2553]), * addr_len - the size of the address structure. */ -SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) +static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) { int retval = 0; @@ -333,7 +328,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, } /* Bind a local address either to an endpoint or to an association. */ -SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) +static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) { struct net *net = sock_net(sk); struct sctp_sock *sp = sctp_sk(sk); @@ -964,9 +959,9 @@ int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw) * * Returns 0 if ok, <0 errno code on error. */ -SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, - struct sockaddr __user *addrs, - int addrs_size, int op) +static int sctp_setsockopt_bindx(struct sock* sk, + struct sockaddr __user *addrs, + int addrs_size, int op) { struct sockaddr *kaddrs; int err; @@ -1312,7 +1307,7 @@ static int __sctp_connect(struct sock* sk, * * Returns >=0 if ok, <0 errno code on error. */ -SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk, +static int __sctp_setsockopt_connectx(struct sock* sk, struct sockaddr __user *addrs, int addrs_size, sctp_assoc_t *assoc_id) @@ -1350,9 +1345,9 @@ SCTP_STATIC int __sctp_setsockopt_connectx(struct sock* sk, * This is an older interface. It's kept for backward compatibility * to the option that doesn't provide association id. */ -SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk, - struct sockaddr __user *addrs, - int addrs_size) +static int sctp_setsockopt_connectx_old(struct sock* sk, + struct sockaddr __user *addrs, + int addrs_size) { return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL); } @@ -1363,9 +1358,9 @@ SCTP_STATIC int sctp_setsockopt_connectx_old(struct sock* sk, * indication to the call. Error is always negative and association id is * always positive. */ -SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, - struct sockaddr __user *addrs, - int addrs_size) +static int sctp_setsockopt_connectx(struct sock* sk, + struct sockaddr __user *addrs, + int addrs_size) { sctp_assoc_t assoc_id = 0; int err = 0; @@ -1386,9 +1381,9 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, * addrs_num structure member. That way we can re-use the existing * code. */ -SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, - char __user *optval, - int __user *optlen) +static int sctp_getsockopt_connectx3(struct sock* sk, int len, + char __user *optval, + int __user *optlen) { struct sctp_getaddrs_old param; sctp_assoc_t assoc_id = 0; @@ -1464,7 +1459,7 @@ SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, * shutdown phase does not finish during this period, close() will * return but the graceful shutdown phase continues in the system. */ -SCTP_STATIC void sctp_close(struct sock *sk, long timeout) +static void sctp_close(struct sock *sk, long timeout) { struct net *net = sock_net(sk); struct sctp_endpoint *ep; @@ -1573,10 +1568,10 @@ static int sctp_error(struct sock *sk, int flags, int err) */ /* BUG: We do not implement the equivalent of sk_stream_wait_memory(). */ -SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *); +static int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *); -SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, - struct msghdr *msg, size_t msg_len) +static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t msg_len) { struct net *net = sock_net(sk); struct sctp_sock *sp; @@ -2034,9 +2029,9 @@ static int sctp_skb_pull(struct sk_buff *skb, int len) */ static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); -SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, - struct msghdr *msg, size_t len, int noblock, - int flags, int *addr_len) +static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len, int noblock, + int flags, int *addr_len) { struct sctp_ulpevent *event = NULL; struct sctp_sock *sp = sctp_sk(sk); @@ -3565,8 +3560,8 @@ static int sctp_setsockopt_paddr_thresholds(struct sock *sk, * optval - the buffer to store the value of the option. * optlen - the size of the buffer. */ -SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, unsigned int optlen) +static int sctp_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen) { int retval = 0; @@ -3725,8 +3720,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, * * len: the size of the address. */ -SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, - int addr_len) +static int sctp_connect(struct sock *sk, struct sockaddr *addr, + int addr_len) { int err = 0; struct sctp_af *af; @@ -3752,7 +3747,7 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, } /* FIXME: Write comments. */ -SCTP_STATIC int sctp_disconnect(struct sock *sk, int flags) +static int sctp_disconnect(struct sock *sk, int flags) { return -EOPNOTSUPP; /* STUB */ } @@ -3764,7 +3759,7 @@ SCTP_STATIC int sctp_disconnect(struct sock *sk, int flags) * descriptor will be returned from accept() to represent the newly * formed association. */ -SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) +static struct sock *sctp_accept(struct sock *sk, int flags, int *err) { struct sctp_sock *sp; struct sctp_endpoint *ep; @@ -3817,7 +3812,7 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) } /* The SCTP ioctl handler. */ -SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) +static int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) { int rc = -ENOTCONN; @@ -3859,7 +3854,7 @@ SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) * initialized the SCTP-specific portion of the sock. * The sock structure should already be zero-filled memory. */ -SCTP_STATIC int sctp_init_sock(struct sock *sk) +static int sctp_init_sock(struct sock *sk) { struct net *net = sock_net(sk); struct sctp_sock *sp; @@ -3993,7 +3988,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) } /* Cleanup any SCTP per socket resources. */ -SCTP_STATIC void sctp_destroy_sock(struct sock *sk) +static void sctp_destroy_sock(struct sock *sk) { struct sctp_sock *sp; @@ -4028,7 +4023,7 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) * Disables further send and receive operations * and initiates the SCTP shutdown sequence. */ -SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) +static void sctp_shutdown(struct sock *sk, int how) { struct net *net = sock_net(sk); struct sctp_endpoint *ep; @@ -5700,8 +5695,8 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, return 0; } -SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user *optlen) +static int sctp_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) { int retval = 0; int len; @@ -6046,7 +6041,7 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) /* * Move a socket to LISTENING state. */ -SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog) +static int sctp_listen_start(struct sock *sk, int backlog) { struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -6333,8 +6328,7 @@ static int sctp_autobind(struct sock *sk) * msg_control * points here */ -SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, - sctp_cmsgs_t *cmsgs) +static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) { struct cmsghdr *cmsg; struct msghdr *my_msg = (struct msghdr *)msg; diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 396c45174e5b..b46019568a86 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -161,8 +161,8 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, /* Initialize a Gap Ack Block iterator from memory being provided. */ -SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map, - struct sctp_tsnmap_iter *iter) +static void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map, + struct sctp_tsnmap_iter *iter) { /* Only start looking one past the Cumulative TSN Ack Point. */ iter->start = map->cumulative_tsn_ack_point + 1; @@ -171,9 +171,9 @@ SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map, /* Get the next Gap Ack Blocks. Returns 0 if there was not another block * to get. */ -SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, - struct sctp_tsnmap_iter *iter, - __u16 *start, __u16 *end) +static int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map, + struct sctp_tsnmap_iter *iter, + __u16 *start, __u16 *end) { int ended = 0; __u16 start_ = 0, end_ = 0, offset; diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 10c018a5b9fe..44a45dbee4df 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -57,9 +57,9 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); /* Initialize an ULP event from an given skb. */ -SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, - int msg_flags, - unsigned int len) +static void sctp_ulpevent_init(struct sctp_ulpevent *event, + int msg_flags, + unsigned int len) { memset(event, 0, sizeof(struct sctp_ulpevent)); event->msg_flags = msg_flags; @@ -67,8 +67,8 @@ SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, } /* Create a new sctp_ulpevent. */ -SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, - gfp_t gfp) +static struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, + gfp_t gfp) { struct sctp_ulpevent *event; struct sk_buff *skb; -- GitLab From b32369f117bbdb009a6b410ec0926a88a83002b4 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 14 Jun 2013 17:58:31 +0900 Subject: [PATCH 1374/2900] net, atm/ambassader: convert skb->tail into skb_tail_pointer(skb) The change set of 27a884dc, "[SK_BUFF]: Convert skb->tail to sk_buff_data_t" converted skb->tail from pointer into sk_buff_data_t. It missed skb->tail in drivers/atm/ambassador.c. This patch converts skb->tail into skb_tail_pointer(skb). Found by inspection. Compile tested only. Cc: Simon Horman Cc: Chas Williams Signed-off-by: Isaku Yamahata Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/atm/ambassador.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 77a7480dc4d1..62a76076b548 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -1403,7 +1403,7 @@ static void amb_free_rx_skb (struct atm_vcc * atm_vcc, struct sk_buff * skb) { rx.host_address = cpu_to_be32 (virt_to_bus (skb->data)); skb->data = skb->head; - skb->tail = skb->head; + skb_reset_tail_pointer(skb); skb->len = 0; if (!rx_give (dev, &rx, pool)) { -- GitLab From 499e2e6fcb9351844d721e4bd3f1184d879bd178 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 14 Jun 2013 17:58:32 +0900 Subject: [PATCH 1375/2900] net, scsi/csgb4i: convert skb->transport_header into skb_transport_header(skb) The change set of 1a37e412, "net: Use 16bits for *_headers fields of struct skbuff" converted from sk_buff_data_t into 16bit integer. So skb->tail needs to be converted to skb_tail_pointer(skb). Found by inspection. Compile tested only. Cc: Simon Horman Cc: Li RongQing Cc: linux-scsi@vger.kernel.org Signed-off-by: Isaku Yamahata Acked-by: Simon Horman Signed-off-by: David S. Miller --- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 3fecf35ba292..9138d4edfa5c 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -358,7 +358,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb) return DIV_ROUND_UP(skb->len, 8); flits = skb_transport_offset(skb) / 8; cnt = skb_shinfo(skb)->nr_frags; - if (skb->tail != skb->transport_header) + if (skb_tail_pointer(skb) != skb_transport_header(skb)) cnt++; return flits + sgl_len(cnt); } -- GitLab From 18f1d0541241855d928608ce6ce325e4cdad222d Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 14 Jun 2013 17:58:33 +0900 Subject: [PATCH 1376/2900] mv643xx_eth.c: convert skb->end into skb_end_poitner(skb) The change set of 4305b541 "[SK_BUFF]: Convert skb->end to sk_buff_data_t" converted skb->end from pointer to sk_buff_data_t. The pointed value should be accessed via skb_end_pointer(). Since arm or ppc arch doesn't define NET_SKBUFF_DATA_USES_OFFSET, skb->end is effectively pointer. So it doesn't cause a real problem. But this patch is good for consistency. Found by inspection. Compile test only. Cc: Simon Horman Cc: Lennert Buytenhek Signed-off-by: Isaku Yamahata Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index c7f9fb33ce95..510d50603a02 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -621,7 +621,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget) rx_desc = rxq->rx_desc_area + rx; - size = skb->end - skb->data; + size = skb_end_pointer(skb) - skb->data; rx_desc->buf_ptr = dma_map_single(mp->dev->dev.parent, skb->data, size, DMA_FROM_DEVICE); -- GitLab From 511efbbbc8ff210dae7feaf263d7f855ea357cbe Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 14 Jun 2013 17:58:34 +0900 Subject: [PATCH 1377/2900] pxa168_eth: convert skb->end into skb_end_pointer(skb) The change set of 4305b541, "[SK_BUFF]: Convert skb->end to sk_buff_data_t" converted skb->end from pointer type to sk_buff_data_t. The pointed value should be accessed via skb_end_pointer(). Since arm arch doesn't define NET_SKBUFF_DATA_USES_OFFSET, skb->end is effectively pointer. So it doesn't cause a real problem. But this patch is good for consistency. Found by inspection. Compile tested only. Cc: Simon Horman Signed-off-by: Isaku Yamahata Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/pxa168_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 2602cf7ba642..ec20508f0d6b 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -357,7 +357,7 @@ static void rxq_refill(struct net_device *dev) /* Get 'used' Rx descriptor */ used_rx_desc = pep->rx_used_desc_q; p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc]; - size = skb->end - skb->data; + size = skb_end_pointer(skb) - skb->data; p_used_rx_desc->buf_ptr = dma_map_single(NULL, skb->data, size, -- GitLab From a267a6041fdb690de9570dab20a5f0fa417c8c9f Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 14 Jun 2013 17:58:35 +0900 Subject: [PATCH 1378/2900] staging/rtl8192u: convert skb->tail into skb_tail_pointer(skb) The change set of 7a884dc "[SK_BUFF]: Convert skb->tail to sk_buff_data_t" converted skb->tail from pointer into sk_buff_data_t. Thus skb->tail is not always pointer, the area pointed by skb->tail should be accessed via skb_tail_pointer(). Found by inspection. Compile tested only. Cc: Simon Horman Cc: Greg Kroah-Hartman Cc: devel@driverdev.osuosl.org Signed-off-by: Isaku Yamahata Reviewed-by: Simon Horman Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller --- drivers/staging/rtl8192u/r8192U_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 71f5cde9ed1c..a18430e2abbd 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -1271,8 +1271,8 @@ struct sk_buff *DrvAggr_Aggregation(struct net_device *dev, struct ieee80211_drv /* Subframe drv Tx descriptor and firmware info setting */ skb = pSendList->tx_agg_frames[i]; tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)agg_skb->tail; - tx_fwinfo = (tx_fwinfo_819x_usb *)(agg_skb->tail + sizeof(tx_desc_819x_usb_aggr_subframe)); + tx_agg_desc = (tx_desc_819x_usb_aggr_subframe *)skb_tail_pointer(agg_skb); + tx_fwinfo = (tx_fwinfo_819x_usb *)(skb_tail_pointer(agg_skb) + sizeof(tx_desc_819x_usb_aggr_subframe)); memset(tx_fwinfo,0,sizeof(tx_fwinfo_819x_usb)); /* DWORD 0 */ -- GitLab From 52705344d00512f0bb48c66478582bd10eb1750f Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:50 -0400 Subject: [PATCH 1379/2900] mfd: 88pm800: Enhance error handling for sub pages probe/remove pm800_pages_init and pm800_pages_exit are called by pm800_probe. Change the code to enhance error handling and remove unused code at pm800_pages_init/exit and pm800_probe. Signed-off-by: Yi Zhang Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 81 +++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 6b607adebce1..4ebb2e215bac 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -370,50 +371,64 @@ static int pm800_pages_init(struct pm80x_chip *chip) struct pm80x_subchip *subchip; struct i2c_client *client = chip->client; + int ret = 0; + subchip = chip->subchip; - /* PM800 block power: i2c addr 0x31 */ - if (subchip->power_page_addr) { - subchip->power_page = - i2c_new_dummy(client->adapter, subchip->power_page_addr); - subchip->regmap_power = - devm_regmap_init_i2c(subchip->power_page, - &pm80x_regmap_config); - i2c_set_clientdata(subchip->power_page, chip); - } else - dev_info(chip->dev, - "PM800 block power 0x31: No power_page_addr\n"); - - /* PM800 block GPADC: i2c addr 0x32 */ - if (subchip->gpadc_page_addr) { - subchip->gpadc_page = i2c_new_dummy(client->adapter, - subchip->gpadc_page_addr); - subchip->regmap_gpadc = - devm_regmap_init_i2c(subchip->gpadc_page, - &pm80x_regmap_config); - i2c_set_clientdata(subchip->gpadc_page, chip); - } else - dev_info(chip->dev, - "PM800 block GPADC 0x32: No gpadc_page_addr\n"); + if (!subchip || !subchip->power_page_addr || !subchip->gpadc_page_addr) + return -ENODEV; + + /* PM800 block power page */ + subchip->power_page = i2c_new_dummy(client->adapter, + subchip->power_page_addr); + if (subchip->power_page == NULL) { + ret = -ENODEV; + goto out; + } - return 0; + subchip->regmap_power = devm_regmap_init_i2c(subchip->power_page, + &pm80x_regmap_config); + if (IS_ERR(subchip->regmap_power)) { + ret = PTR_ERR(subchip->regmap_power); + dev_err(chip->dev, + "Failed to allocate regmap_power: %d\n", ret); + goto out; + } + + i2c_set_clientdata(subchip->power_page, chip); + + /* PM800 block GPADC */ + subchip->gpadc_page = i2c_new_dummy(client->adapter, + subchip->gpadc_page_addr); + if (subchip->gpadc_page == NULL) { + ret = -ENODEV; + goto out; + } + + subchip->regmap_gpadc = devm_regmap_init_i2c(subchip->gpadc_page, + &pm80x_regmap_config); + if (IS_ERR(subchip->regmap_gpadc)) { + ret = PTR_ERR(subchip->regmap_gpadc); + dev_err(chip->dev, + "Failed to allocate regmap_gpadc: %d\n", ret); + goto out; + } + i2c_set_clientdata(subchip->gpadc_page, chip); + +out: + return ret; } static void pm800_pages_exit(struct pm80x_chip *chip) { struct pm80x_subchip *subchip; - regmap_exit(chip->regmap); - i2c_unregister_device(chip->client); - subchip = chip->subchip; - if (subchip->power_page) { - regmap_exit(subchip->regmap_power); + + if (subchip && subchip->power_page) i2c_unregister_device(subchip->power_page); - } - if (subchip->gpadc_page) { - regmap_exit(subchip->regmap_gpadc); + + if (subchip && subchip->gpadc_page) i2c_unregister_device(subchip->gpadc_page); - } } static int device_800_init(struct pm80x_chip *chip, -- GitLab From 03dcc544bff9ff36b9ac5e2b992a7a4890e6edc4 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:51 -0400 Subject: [PATCH 1380/2900] mfd: 88pm80x: Change chip id definition and detection Change the chip id definition and detection and then: 1. We no longer need to add PM800_CHIP_XXX for the coming revision. 2. We no longer need to pass driver_data in i2c_device_id as we can distinguish the chips from the CHIP_ID register. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 42 +++++---------------------------- drivers/mfd/88pm805.c | 16 +++---------- drivers/mfd/88pm80x.c | 47 +++++++++++++++++++++++++++++++------ include/linux/mfd/88pm80x.h | 7 ++---- 4 files changed, 51 insertions(+), 61 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 4ebb2e215bac..2c0b4155181f 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -28,8 +28,6 @@ #include #include -#define PM800_CHIP_ID (0x00) - /* Interrupt Registers */ #define PM800_INT_STATUS1 (0x05) #define PM800_ONKEY_INT_STS1 (1 << 0) @@ -114,20 +112,11 @@ enum { PM800_MAX_IRQ, }; -enum { - /* Procida */ - PM800_CHIP_A0 = 0x60, - PM800_CHIP_A1 = 0x61, - PM800_CHIP_B0 = 0x62, - PM800_CHIP_C0 = 0x63, - PM800_CHIP_END = PM800_CHIP_C0, - - /* Make sure to update this to the last stepping */ - PM8XXX_CHIP_END = PM800_CHIP_END -}; +/* PM800: generation identification number */ +#define PM800_CHIP_GEN_ID_NUM 0x3 static const struct i2c_device_id pm80x_id_table[] = { - {"88PM800", CHIP_PM800}, + {"88PM800", 0}, {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); @@ -434,28 +423,9 @@ static void pm800_pages_exit(struct pm80x_chip *chip) static int device_800_init(struct pm80x_chip *chip, struct pm80x_platform_data *pdata) { - int ret, pmic_id; + int ret; unsigned int val; - ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val); - if (ret < 0) { - dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); - goto out; - } - - pmic_id = val & PM80X_VERSION_MASK; - - if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) { - chip->version = val; - dev_info(chip->dev, - "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val); - } else { - dev_err(chip->dev, - "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val); - ret = -EINVAL; - goto out; - } - /* * alarm wake up bit will be clear in device_irq_init(), * read before that @@ -523,7 +493,7 @@ static int pm800_probe(struct i2c_client *client, struct pm80x_platform_data *pdata = client->dev.platform_data; struct pm80x_subchip *subchip; - ret = pm80x_init(client, id); + ret = pm80x_init(client); if (ret) { dev_err(&client->dev, "pm800_init fail\n"); goto out_init; @@ -553,7 +523,7 @@ static int pm800_probe(struct i2c_client *client, ret = device_800_init(chip, pdata); if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + dev_err(chip->dev, "Failed to initialize 88pm800 devices\n"); goto err_device_init; } diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c index 0e82c2a1e842..521602231c7b 100644 --- a/drivers/mfd/88pm805.c +++ b/drivers/mfd/88pm805.c @@ -29,10 +29,8 @@ #include #include -#define PM805_CHIP_ID (0x00) - static const struct i2c_device_id pm80x_id_table[] = { - {"88PM805", CHIP_PM805}, + {"88PM805", 0}, {} /* NULL terminated */ }; MODULE_DEVICE_TABLE(i2c, pm80x_id_table); @@ -192,7 +190,6 @@ static struct regmap_irq_chip pm805_irq_chip = { static int device_805_init(struct pm80x_chip *chip) { int ret = 0; - unsigned int val; struct regmap *map = chip->regmap; if (!map) { @@ -200,13 +197,6 @@ static int device_805_init(struct pm80x_chip *chip) return -EINVAL; } - ret = regmap_read(map, PM805_CHIP_ID, &val); - if (ret < 0) { - dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); - goto out_irq_init; - } - chip->version = val; - chip->regmap_irq_chip = &pm805_irq_chip; ret = device_irq_init_805(chip); @@ -239,7 +229,7 @@ static int pm805_probe(struct i2c_client *client, struct pm80x_chip *chip; struct pm80x_platform_data *pdata = client->dev.platform_data; - ret = pm80x_init(client, id); + ret = pm80x_init(client); if (ret) { dev_err(&client->dev, "pm805_init fail!\n"); goto out_init; @@ -249,7 +239,7 @@ static int pm805_probe(struct i2c_client *client, ret = device_805_init(chip); if (ret) { - dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + dev_err(chip->dev, "Failed to initialize 88pm805 devices\n"); goto err_805_init; } diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c index f736a46eb8c0..5e72f65ef94c 100644 --- a/drivers/mfd/88pm80x.c +++ b/drivers/mfd/88pm80x.c @@ -18,6 +18,23 @@ #include #include +/* 88pm80x chips have same definition for chip id register. */ +#define PM80X_CHIP_ID (0x00) +#define PM80X_CHIP_ID_NUM(x) (((x) >> 5) & 0x7) +#define PM80X_CHIP_ID_REVISION(x) ((x) & 0x1F) + +struct pm80x_chip_mapping { + unsigned int id; + int type; +}; + +static struct pm80x_chip_mapping chip_mapping[] = { + /* 88PM800 chip id number */ + {0x3, CHIP_PM800}, + /* 88PM805 chip id number */ + {0x0, CHIP_PM805}, +}; + /* * workaround: some registers needed by pm805 are defined in pm800, so * need to use this global variable to maintain the relation between @@ -31,12 +48,13 @@ const struct regmap_config pm80x_regmap_config = { }; EXPORT_SYMBOL_GPL(pm80x_regmap_config); -int pm80x_init(struct i2c_client *client, - const struct i2c_device_id *id) + +int pm80x_init(struct i2c_client *client) { struct pm80x_chip *chip; struct regmap *map; - int ret = 0; + unsigned int val; + int i, ret = 0; chip = devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL); @@ -51,10 +69,6 @@ int pm80x_init(struct i2c_client *client, return ret; } - chip->id = id->driver_data; - if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) - return -EINVAL; - chip->client = client; chip->regmap = map; @@ -64,6 +78,25 @@ int pm80x_init(struct i2c_client *client, dev_set_drvdata(chip->dev, chip); i2c_set_clientdata(chip->client, chip); + ret = regmap_read(chip->regmap, PM80X_CHIP_ID, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(chip_mapping); i++) { + if (chip_mapping[i].id == PM80X_CHIP_ID_NUM(val)) { + chip->type = chip_mapping[i].type; + break; + } + } + + if (i == ARRAY_SIZE(chip_mapping)) { + dev_err(chip->dev, + "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val); + return -EINVAL; + } + device_init_wakeup(&client->dev, 1); /* diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 023e6395da87..4a66a5633031 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -17,7 +17,6 @@ #include #include -#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */ enum { CHIP_INVALID = 0, CHIP_PM800, @@ -299,8 +298,7 @@ struct pm80x_chip { struct regmap *regmap; struct regmap_irq_chip *regmap_irq_chip; struct regmap_irq_chip_data *irq_data; - unsigned char version; - int id; + int type; int irq; int irq_mode; unsigned long wu_flag; @@ -361,7 +359,6 @@ static inline int pm80x_dev_resume(struct device *dev) } #endif -extern int pm80x_init(struct i2c_client *client, - const struct i2c_device_id *id); +extern int pm80x_init(struct i2c_client *client); extern int pm80x_deinit(void); #endif /* __LINUX_MFD_88PM80X_H */ -- GitLab From 3a3ece5415bd7a4bc7923906369525943332fc1a Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:52 -0400 Subject: [PATCH 1381/2900] mfd: 88pm800: Enhance sub devices initialization Separate the devices initialization into different functions. It makes the probe function clearer. Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 61 +++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 2c0b4155181f..a475fb3c2d0c 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -305,6 +305,40 @@ static int device_gpadc_init(struct pm80x_chip *chip, return ret; } +static int device_onkey_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, + NULL); + if (ret) { + dev_err(chip->dev, "Failed to add onkey subdev\n"); + return ret; + } + + return 0; +} + +static int device_rtc_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + rtc_devs[0].platform_data = pdata->rtc; + rtc_devs[0].pdata_size = + pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0; + ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], + ARRAY_SIZE(rtc_devs), NULL, 0, NULL); + if (ret) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + return ret; + } + + return 0; +} + static int device_irq_init_800(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; @@ -454,27 +488,16 @@ static int device_800_init(struct pm80x_chip *chip, goto out; } - ret = - mfd_add_devices(chip->dev, 0, &onkey_devs[0], - ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0, - NULL); - if (ret < 0) { + ret = device_onkey_init(chip, pdata); + if (ret) { dev_err(chip->dev, "Failed to add onkey subdev\n"); goto out_dev; - } else - dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__); - - if (pdata && pdata->rtc) { - rtc_devs[0].platform_data = pdata->rtc; - rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); - ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], - ARRAY_SIZE(rtc_devs), NULL, 0, NULL); - if (ret < 0) { - dev_err(chip->dev, "Failed to add rtc subdev\n"); - goto out_dev; - } else - dev_info(chip->dev, - "[%s]:Added mfd rtc_devs\n", __func__); + } + + ret = device_rtc_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + goto out; } return 0; -- GitLab From 2d3aa0569cc111b7567cb082c2f8ab32e2245e49 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Fri, 14 Jun 2013 01:21:53 -0400 Subject: [PATCH 1382/2900] mfd: 88pm800: Add regulator sub device Signed-off-by: Chao Xie Signed-off-by: Samuel Ortiz --- drivers/mfd/88pm800.c | 28 ++++++++++++++++++++++++++++ include/linux/mfd/88pm80x.h | 8 ++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index a475fb3c2d0c..6c954835d61e 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -157,6 +157,13 @@ static struct mfd_cell onkey_devs[] = { }, }; +static struct mfd_cell regulator_devs[] = { + { + .name = "88pm80x-regulator", + .id = -1, + }, +}; + static const struct regmap_irq pm800_irqs[] = { /* INT0 */ [PM800_IRQ_ONKEY] = { @@ -339,6 +346,21 @@ static int device_rtc_init(struct pm80x_chip *chip, return 0; } +static int device_regulator_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret; + + ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[0], + ARRAY_SIZE(regulator_devs), NULL, 0, NULL); + if (ret) { + dev_err(chip->dev, "Failed to add regulator subdev\n"); + return ret; + } + + return 0; +} + static int device_irq_init_800(struct pm80x_chip *chip) { struct regmap *map = chip->regmap; @@ -500,6 +522,12 @@ static int device_800_init(struct pm80x_chip *chip, goto out; } + ret = device_regulator_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "Failed to add regulators subdev\n"); + goto out; + } + return 0; out_dev: mfd_remove_devices(chip->dev); diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h index 4a66a5633031..97cb283cc8e1 100644 --- a/include/linux/mfd/88pm80x.h +++ b/include/linux/mfd/88pm80x.h @@ -307,6 +307,14 @@ struct pm80x_chip { struct pm80x_platform_data { struct pm80x_rtc_pdata *rtc; + /* + * For the regulator not defined, set regulators[not_defined] to be + * NULL. num_regulators are the number of regulators supposed to be + * initialized. If all regulators are not defined, set num_regulators + * to be 0. + */ + struct regulator_init_data *regulators[PM800_ID_RG_MAX]; + unsigned int num_regulators; int irq_mode; /* Clear interrupt by read/write(0/1) */ int batt_det; /* enable/disable */ int (*plat_config)(struct pm80x_chip *chip, -- GitLab From b4d0fe9c906deb00ad0b1690817f96aff21aee29 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 27 May 2013 10:28:56 +0800 Subject: [PATCH 1383/2900] mfd: lpc_ich: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code cleaner. Signed-off-by: Libo Chen Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 330cd44771be..9682bee80d53 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -983,18 +983,7 @@ static struct pci_driver lpc_ich_driver = { .remove = lpc_ich_remove, }; -static int __init lpc_ich_init(void) -{ - return pci_register_driver(&lpc_ich_driver); -} - -static void __exit lpc_ich_exit(void) -{ - pci_unregister_driver(&lpc_ich_driver); -} - -module_init(lpc_ich_init); -module_exit(lpc_ich_exit); +module_pci_driver(lpc_ich_driver); MODULE_AUTHOR("Aaron Sierra "); MODULE_DESCRIPTION("LPC interface for Intel ICH"); -- GitLab From 55098ff79f22bbc35f80cb13d24fda3423159c9d Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 31 May 2013 14:44:54 -0700 Subject: [PATCH 1384/2900] mfd: twl4030: Allow IRQ wake enable to succeed on subchip IRQs The genirq IRQ wake method will default to failure if the irq_chip does not provide a set_wake method. However, for TWL4030 sub-chip IRQs, we want the wake enable to succeed even though we don't provide a set_wake method. This allows sub-chip IRQs to still be flagged as wakeup capable, and allow them to wakeup from suspend (or abort suspend if they fire during suspend.) To fix, use the IRQCHIP_SKIP_SET_WAKE flag in the irq_chip. Signed-off-by: Kevin Hilman Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index a5f9888aa19c..3fa7df21c5e3 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -573,6 +573,7 @@ static struct irq_chip twl4030_sih_irq_chip = { .irq_set_type = twl4030_sih_set_type, .irq_bus_lock = twl4030_sih_bus_lock, .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock, + .flags = IRQCHIP_SKIP_SET_WAKE, }; /*----------------------------------------------------------------------*/ -- GitLab From 6378c1e511d97218f33936f47888095023c9ffaf Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Jun 2013 12:39:43 -0700 Subject: [PATCH 1385/2900] mfd: ssbi: Add MODULE_DEVICE_TABLE This allows the ssbi module to be autoloaded on boot. Cc: David Brown Signed-off-by: Stephen Boyd Signed-off-by: Samuel Ortiz --- drivers/mfd/ssbi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index f32da0258a8e..e561d3be54a5 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -350,6 +350,7 @@ static struct of_device_id ssbi_match_table[] = { { .compatible = "qcom,ssbi" }, {} }; +MODULE_DEVICE_TABLE(of, ssbi_match_table); static struct platform_driver ssbi_driver = { .probe = ssbi_probe, -- GitLab From e578438820cdca91cb5eab477ec062236433ce5f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Jun 2013 12:39:44 -0700 Subject: [PATCH 1386/2900] mfd: ssbi: Use devm_* and simplify code Use devm_ioremap_resource and devm_kzalloc to simplify error paths and reduce lines of code. Also use dev_err() to keep consistency and drop the .remove function because the devm functions take care of what it's doing besides the now obsolete platform_set_drvdata() which we can just drop. Finally, use module_platform_driver() to save some more lines. Cc: David Brown Signed-off-by: Stephen Boyd Acked-by: Lee Jones Signed-off-by: Samuel Ortiz --- drivers/mfd/ssbi.c | 69 ++++++++-------------------------------------- 1 file changed, 11 insertions(+), 58 deletions(-) diff --git a/drivers/mfd/ssbi.c b/drivers/mfd/ssbi.c index e561d3be54a5..102a22844297 100644 --- a/drivers/mfd/ssbi.c +++ b/drivers/mfd/ssbi.c @@ -268,35 +268,23 @@ static int ssbi_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; struct resource *mem_res; struct ssbi *ssbi; - int ret = 0; const char *type; - ssbi = kzalloc(sizeof(struct ssbi), GFP_KERNEL); - if (!ssbi) { - pr_err("can not allocate ssbi_data\n"); + ssbi = devm_kzalloc(&pdev->dev, sizeof(*ssbi), GFP_KERNEL); + if (!ssbi) return -ENOMEM; - } mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - pr_err("missing mem resource\n"); - ret = -EINVAL; - goto err_get_mem_res; - } + ssbi->base = devm_ioremap_resource(&pdev->dev, mem_res); + if (IS_ERR(ssbi->base)) + return PTR_ERR(ssbi->base); - ssbi->base = ioremap(mem_res->start, resource_size(mem_res)); - if (!ssbi->base) { - pr_err("ioremap of 0x%p failed\n", (void *)mem_res->start); - ret = -EINVAL; - goto err_ioremap; - } platform_set_drvdata(pdev, ssbi); type = of_get_property(np, "qcom,controller-type", NULL); if (type == NULL) { - pr_err("Missing qcom,controller-type property\n"); - ret = -EINVAL; - goto err_ssbi_controller; + dev_err(&pdev->dev, "Missing qcom,controller-type property\n"); + return -EINVAL; } dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type); if (strcmp(type, "ssbi") == 0) @@ -306,9 +294,8 @@ static int ssbi_probe(struct platform_device *pdev) else if (strcmp(type, "pmic-arbiter") == 0) ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER; else { - pr_err("Unknown qcom,controller-type\n"); - ret = -EINVAL; - goto err_ssbi_controller; + dev_err(&pdev->dev, "Unknown qcom,controller-type\n"); + return -EINVAL; } if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { @@ -321,29 +308,7 @@ static int ssbi_probe(struct platform_device *pdev) spin_lock_init(&ssbi->lock); - ret = of_platform_populate(np, NULL, NULL, &pdev->dev); - if (ret) - goto err_ssbi_controller; - - return 0; - -err_ssbi_controller: - platform_set_drvdata(pdev, NULL); - iounmap(ssbi->base); -err_ioremap: -err_get_mem_res: - kfree(ssbi); - return ret; -} - -static int ssbi_remove(struct platform_device *pdev) -{ - struct ssbi *ssbi = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - iounmap(ssbi->base); - kfree(ssbi); - return 0; + return of_platform_populate(np, NULL, NULL, &pdev->dev); } static struct of_device_id ssbi_match_table[] = { @@ -354,25 +319,13 @@ MODULE_DEVICE_TABLE(of, ssbi_match_table); static struct platform_driver ssbi_driver = { .probe = ssbi_probe, - .remove = ssbi_remove, .driver = { .name = "ssbi", .owner = THIS_MODULE, .of_match_table = ssbi_match_table, }, }; - -static int __init ssbi_init(void) -{ - return platform_driver_register(&ssbi_driver); -} -module_init(ssbi_init); - -static void __exit ssbi_exit(void) -{ - platform_driver_unregister(&ssbi_driver); -} -module_exit(ssbi_exit) +module_platform_driver(ssbi_driver); MODULE_LICENSE("GPL v2"); MODULE_VERSION("1.0"); -- GitLab From b01147140a2a609d91538fdfec8e2d688d379662 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 12 Jun 2013 14:55:40 +0200 Subject: [PATCH 1387/2900] iwlwifi: mvm: allow firmware crashes to wake system for debug When the D3 firmware crashes, it can be helpful for debugging to resume the system to get the SRAM snapshot to see why it crashed. Allow enabling this with a debugfs option. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/d3.c | 6 ++++++ drivers/net/wireless/iwlwifi/mvm/debugfs.c | 3 +++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + 3 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 8c49db02c9c1..7e5e5c2f9f87 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1026,6 +1026,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, if (ret) goto out; +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvm->d3_wake_sysassert) + d3_cfg_cmd_data.wakeup_flags |= + cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR); +#endif + /* must be last -- this switches firmware state */ ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); if (ret) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index b7643c16201f..63d19d94b018 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -939,6 +939,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); + if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, + mvm->debugfs_dir, &mvm->d3_wake_sysassert)) + goto err; #endif /* diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index ad39a22f79fa..fbc0acb52191 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -460,6 +460,7 @@ struct iwl_mvm { #ifdef CONFIG_PM_SLEEP int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; #ifdef CONFIG_IWLWIFI_DEBUGFS + u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ bool d3_test_active; bool store_d3_resume_sram; void *d3_resume_sram; -- GitLab From bc53cd49fcaa604cbef219c964df0db9c8ef452e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 18 Jun 2013 06:29:56 +0300 Subject: [PATCH 1388/2900] iwlwifi: remove bt_ch_announce module param This parameter is really not useful, remove it. Leave the variable in priv in case someone wants to play with it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/main.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-drv.c | 6 ------ drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 -- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 7aa9c8dc33ef..71db0895602d 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1355,8 +1355,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? true : false; - /* enable/disable bt channel inhibition */ - priv->bt_ch_announce = iwlwifi_mod_params.bt_ch_announce; + /* bt channel inhibition enabled*/ + priv->bt_ch_announce = true; IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", (priv->bt_ch_announce) ? "On" : "Off"); diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 4f886133639a..01b9763f7314 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1112,7 +1112,6 @@ struct iwl_mod_params iwlwifi_mod_params = { .plcp_check = true, .bt_coex_active = true, .power_level = IWL_POWER_INDEX_1, - .bt_ch_announce = true, .auto_agg = true, .wd_disable = true, /* the rest are 0 by default */ @@ -1221,11 +1220,6 @@ module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(bt_ch_inhibition, iwlwifi_mod_params.bt_ch_announce, - bool, S_IRUGO); -MODULE_PARM_DESC(bt_ch_inhibition, - "Enable BT channel inhibition (default: enable)"); - module_param_named(plcp_check, iwlwifi_mod_params.plcp_check, bool, S_IRUGO); MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index d4ad505b0a4b..e2e64924c90d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -101,7 +101,6 @@ enum iwl_power_level { * @power_level: power level, default = 1 * @debug_level: levels are IWL_DL_* * @ant_coupling: antenna coupling in dB, default = 0 - * @bt_ch_announce: BT channel inhibition, default = enable * @auto_agg: enable agg. without check, default = true */ struct iwl_mod_params { @@ -119,7 +118,6 @@ struct iwl_mod_params { u32 debug_level; #endif int ant_coupling; - bool bt_ch_announce; bool auto_agg; char *nvm_file; }; -- GitLab From 8b5bf33575e112328af1e3cb233c7b162fe2cacd Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 18 Jun 2013 06:31:37 +0300 Subject: [PATCH 1389/2900] iwlwifi: remove plcp_check module parameter Nobody will ever wants to run without this. Make it true always. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/rx.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-drv.c | 4 ---- drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 2f3fd160ab44..5d31a1a15849 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c @@ -335,8 +335,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv, if (msecs < 99) return; - if (iwlwifi_mod_params.plcp_check && - !iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) + if (!iwlagn_good_plcp_health(priv, cur_ofdm, cur_ofdm_ht, msecs)) iwl_force_rf_reset(priv, false); } diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 01b9763f7314..b88bdec56bf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1109,7 +1109,6 @@ void iwl_drv_stop(struct iwl_drv *drv) /* shared module parameters */ struct iwl_mod_params iwlwifi_mod_params = { .restart_fw = true, - .plcp_check = true, .bt_coex_active = true, .power_level = IWL_POWER_INDEX_1, .auto_agg = true, @@ -1220,9 +1219,6 @@ module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling, MODULE_PARM_DESC(antenna_coupling, "specify antenna coupling in dB (defualt: 0 dB)"); -module_param_named(plcp_check, iwlwifi_mod_params.plcp_check, bool, S_IRUGO); -MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); - module_param_named(wd_disable, iwlwifi_mod_params.wd_disable, int, S_IRUGO); MODULE_PARM_DESC(wd_disable, "Disable stuck queue watchdog timer 0=system default, " diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index e2e64924c90d..367b6c18bba4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -93,7 +93,6 @@ enum iwl_power_level { * use IWL_DISABLE_HT_* constants * @amsdu_size_8K: enable 8K amsdu size, default = 0 * @restart_fw: restart firmware, default = 1 - * @plcp_check: enable plcp health check, default = true * @wd_disable: enable stuck queue check, default = 0 * @bt_coex_active: enable bt coex, default = true * @led_mode: system default, default = 0 @@ -108,7 +107,6 @@ struct iwl_mod_params { unsigned int disable_11n; int amsdu_size_8K; bool restart_fw; - bool plcp_check; int wd_disable; bool bt_coex_active; int led_mode; -- GitLab From 44cc429cad4efd1f248b73bf6d692dfa5370dd58 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 18 Jun 2013 06:33:49 +0300 Subject: [PATCH 1390/2900] iwlwifi: remove auto_agg module parameter If someone wants to disable AMPDU, there is the 11n_disable module parameter. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/rs.c | 29 ++++++++----------- drivers/net/wireless/iwlwifi/iwl-drv.c | 6 ---- drivers/net/wireless/iwlwifi/iwl-modparams.h | 2 -- drivers/net/wireless/iwlwifi/mvm/rs.c | 30 ++++++++------------ 4 files changed, 24 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 94314a8e1029..99d989a4510b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -419,23 +419,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, load = rs_tl_get_load(lq_data, tid); - if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { - IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", - sta->addr, tid); - ret = ieee80211_start_tx_ba_session(sta, tid, 5000); - if (ret == -EAGAIN) { - /* - * driver and mac80211 is out of sync - * this might be cause by reloading firmware - * stop the tx ba session here - */ - IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", - tid); - ieee80211_stop_tx_ba_session(sta, tid); - } - } else { - IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d " - "because load = %u\n", tid, load); + IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", + sta->addr, tid); + ret = ieee80211_start_tx_ba_session(sta, tid, 5000); + if (ret == -EAGAIN) { + /* + * driver and mac80211 is out of sync + * this might be cause by reloading firmware + * stop the tx ba session here + */ + IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", + tid); + ieee80211_stop_tx_ba_session(sta, tid); } return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index b88bdec56bf0..59b1e40f0507 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -1111,7 +1111,6 @@ struct iwl_mod_params iwlwifi_mod_params = { .restart_fw = true, .bt_coex_active = true, .power_level = IWL_POWER_INDEX_1, - .auto_agg = true, .wd_disable = true, /* the rest are 0 by default */ }; @@ -1260,8 +1259,3 @@ module_param_named(power_level, iwlwifi_mod_params.power_level, int, S_IRUGO); MODULE_PARM_DESC(power_level, "default power save level (range from 1 - 5, default: 1)"); - -module_param_named(auto_agg, iwlwifi_mod_params.auto_agg, - bool, S_IRUGO); -MODULE_PARM_DESC(auto_agg, - "enable agg w/o check traffic load (default: enable)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index 367b6c18bba4..a1f580c0c6c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h @@ -100,7 +100,6 @@ enum iwl_power_level { * @power_level: power level, default = 1 * @debug_level: levels are IWL_DL_* * @ant_coupling: antenna coupling in dB, default = 0 - * @auto_agg: enable agg. without check, default = true */ struct iwl_mod_params { int sw_crypto; @@ -116,7 +115,6 @@ struct iwl_mod_params { u32 debug_level; #endif int ant_coupling; - bool auto_agg; char *nvm_file; }; diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index d6beec765d65..d87876f5793f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -412,24 +412,18 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, return ret; } - if ((iwlwifi_mod_params.auto_agg) || (load > IWL_AGG_LOAD_THRESHOLD)) { - IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", - sta->addr, tid); - ret = ieee80211_start_tx_ba_session(sta, tid, 5000); - if (ret == -EAGAIN) { - /* - * driver and mac80211 is out of sync - * this might be cause by reloading firmware - * stop the tx ba session here - */ - IWL_ERR(mvm, "Fail start Tx agg on tid: %d\n", - tid); - ieee80211_stop_tx_ba_session(sta, tid); - } - } else { - IWL_DEBUG_HT(mvm, - "Aggregation not enabled for tid %d because load = %u\n", - tid, load); + IWL_DEBUG_HT(mvm, "Starting Tx agg: STA: %pM tid: %d\n", + sta->addr, tid); + ret = ieee80211_start_tx_ba_session(sta, tid, 5000); + if (ret == -EAGAIN) { + /* + * driver and mac80211 is out of sync + * this might be cause by reloading firmware + * stop the tx ba session here + */ + IWL_ERR(mvm, "Fail start Tx agg on tid: %d\n", + tid); + ieee80211_stop_tx_ba_session(sta, tid); } return ret; } -- GitLab From 49464ae502680e362be519ac024a0f5998faaa7e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Jun 2013 23:13:31 +0200 Subject: [PATCH 1391/2900] iwlwifi: remove testmode The old nl80211 testmode is no longer useful in iwlwifi, we're moving towards a new model internally and there's no open tool to use it, so remove it. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/Kconfig | 10 - drivers/net/wireless/iwlwifi/Makefile | 1 - drivers/net/wireless/iwlwifi/dvm/Makefile | 1 - drivers/net/wireless/iwlwifi/dvm/agn.h | 37 - drivers/net/wireless/iwlwifi/dvm/dev.h | 13 +- drivers/net/wireless/iwlwifi/dvm/lib.c | 6 - drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 - drivers/net/wireless/iwlwifi/dvm/main.c | 11 - drivers/net/wireless/iwlwifi/dvm/rs.c | 14 - drivers/net/wireless/iwlwifi/dvm/rx.c | 37 +- drivers/net/wireless/iwlwifi/dvm/testmode.c | 471 ----------- drivers/net/wireless/iwlwifi/dvm/tx.c | 12 - drivers/net/wireless/iwlwifi/iwl-test.c | 852 -------------------- drivers/net/wireless/iwlwifi/iwl-test.h | 161 ---- drivers/net/wireless/iwlwifi/iwl-testmode.h | 309 ------- drivers/net/wireless/iwlwifi/iwl-trans.h | 2 - drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 - 17 files changed, 12 insertions(+), 1928 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/dvm/testmode.c delete mode 100644 drivers/net/wireless/iwlwifi/iwl-test.c delete mode 100644 drivers/net/wireless/iwlwifi/iwl-test.h delete mode 100644 drivers/net/wireless/iwlwifi/iwl-testmode.h diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 56c2040a955b..cbaa5c2c410f 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -128,16 +128,6 @@ config IWLWIFI_DEVICE_TRACING occur. endmenu -config IWLWIFI_DEVICE_TESTMODE - def_bool y - depends on IWLWIFI - depends on NL80211_TESTMODE - help - This option enables the testmode support for iwlwifi device through - NL80211_TESTMODE. This provide the capabilities of enable user space - validation applications to interacts with the device through the - generic netlink message via NL80211_TESTMODE channel. - config IWLWIFI_P2P def_bool y bool "iwlwifi experimental P2P support" diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index f55a758b87f6..1fa64429bcc2 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -13,7 +13,6 @@ iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwlwifi-objs += $(iwlwifi-m) iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o -iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o ccflags-y += -D__CHECK_ENDIAN__ -I$(src) diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile index 5ff76b204141..dce7ab2e0c4b 100644 --- a/drivers/net/wireless/iwlwifi/dvm/Makefile +++ b/drivers/net/wireless/iwlwifi/dvm/Makefile @@ -8,6 +8,5 @@ iwldvm-objs += scan.o led.o iwldvm-objs += rxon.o devices.o iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o -iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index de2c9514bef6..18355110deff 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h @@ -405,43 +405,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) extern int iwl_alive_start(struct iwl_priv *priv); -/* testmode support */ -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - -extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, - int len); -extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct netlink_callback *cb, - void *data, int len); -extern void iwl_testmode_init(struct iwl_priv *priv); -extern void iwl_testmode_free(struct iwl_priv *priv); - -#else - -static inline -int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) -{ - return -ENOSYS; -} - -static inline -int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, - struct netlink_callback *cb, - void *data, int len) -{ - return -ENOSYS; -} - -static inline void iwl_testmode_init(struct iwl_priv *priv) -{ -} - -static inline void iwl_testmode_free(struct iwl_priv *priv) -{ -} -#endif - #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, enum iwl_rxon_context_id ctxid); diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h index f1b8df16dbba..310a6783051e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/iwlwifi/dvm/dev.h @@ -52,8 +52,6 @@ #include "rs.h" #include "tt.h" -#include "iwl-test.h" - /* CT-KILL constants */ #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ #define CT_KILL_THRESHOLD 114 /* in Celsius */ @@ -691,10 +689,6 @@ struct iwl_priv { struct iwl_spectrum_notification measure_report; u8 measurement_status; -#define IWL_OWNERSHIP_DRIVER 0 -#define IWL_OWNERSHIP_TM 1 - u8 ucode_owner; - /* ucode beacon time */ u32 ucode_beacon_time; int missed_beacon_threshold; @@ -889,7 +883,7 @@ struct iwl_priv { #endif /* CONFIG_IWLWIFI_DEBUGFS */ struct iwl_nvm_data *nvm_data; - /* eeprom blob for debugfs/testmode */ + /* eeprom blob for debugfs */ u8 *eeprom_blob; size_t eeprom_blob_size; @@ -905,11 +899,6 @@ struct iwl_priv { unsigned long blink_on, blink_off; bool led_registered; -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - struct iwl_test tst; - u32 tm_fixed_rate; -#endif - /* WoWLAN GTK rekey data */ u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN]; __le64 replay_ctr; diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 9879550a0fea..3d5bdc4217a8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -1288,12 +1288,6 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!(cmd->flags & CMD_ASYNC)) lockdep_assert_held(&priv->mutex); - if (priv->ucode_owner == IWL_OWNERSHIP_TM && - !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); - return -EIO; - } - return iwl_trans_send_cmd(priv->trans, cmd); } diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index c0039a992909..593aaf4d90f8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1765,8 +1765,6 @@ struct ieee80211_ops iwlagn_hw_ops = { .remain_on_channel = iwlagn_mac_remain_on_channel, .cancel_remain_on_channel = iwlagn_mac_cancel_remain_on_channel, .rssi_callback = iwlagn_mac_rssi_callback, - CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd) - CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump) .set_tim = iwlagn_mac_set_tim, }; diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 71db0895602d..3952ddf2ddb2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -1105,8 +1105,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->agg_tids_count = 0; - priv->ucode_owner = IWL_OWNERSHIP_DRIVER; - priv->rx_statistics_jiffies = jiffies; /* Choose which receivers/antennas to use */ @@ -1172,12 +1170,6 @@ static void iwl_option_config(struct iwl_priv *priv) IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n"); #endif -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE enabled\n"); -#else - IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TESTMODE disabled\n"); -#endif - #ifdef CONFIG_IWLWIFI_P2P IWL_INFO(priv, "CONFIG_IWLWIFI_P2P enabled\n"); #else @@ -1451,7 +1443,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ********************/ iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); - iwl_testmode_init(priv); iwl_power_initialize(priv); iwl_tt_initialize(priv); @@ -1488,7 +1479,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, iwlagn_mac_unregister(priv); out_destroy_workqueue: iwl_tt_exit(priv); - iwl_testmode_free(priv); iwl_cancel_deferred_work(priv); destroy_workqueue(priv->workqueue); priv->workqueue = NULL; @@ -1510,7 +1500,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); - iwl_testmode_free(priv); iwlagn_mac_unregister(priv); iwl_tt_exit(priv); diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 99d989a4510b..18e746b53b16 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -351,12 +351,6 @@ static void rs_program_fix_rate(struct iwl_priv *priv, lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - /* testmode has higher priority to overwirte the fixed rate */ - if (priv->tm_fixed_rate) - lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; -#endif - IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); @@ -1078,11 +1072,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, if (sta && sta->supp_rates[sband->band]) rs_rate_scale_perform(priv, skb, sta, lq_sta); -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE) - if ((priv->tm_fixed_rate) && - (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate)) - rs_program_fix_rate(priv, lq_sta); -#endif if (priv->lib->bt_params && priv->lib->bt_params->advanced_bt_coexist) rs_bt_update_lq(priv, ctx, lq_sta); } @@ -2908,9 +2897,6 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - priv->tm_fixed_rate = 0; -#endif #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c index 5d31a1a15849..d71776dd1e6a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/iwlwifi/dvm/rx.c @@ -1119,32 +1119,17 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, */ iwl_notification_wait_notify(&priv->notif_wait, pkt); -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - /* - * RX data may be forwarded to userspace in one - * of two cases: the user owns the fw through testmode or when - * the user requested to monitor the rx w/o affecting the regular flow. - * In these cases the iwl_test object will handle forwarding the rx - * data to user space. - * Note that if the ownership flag != IWL_OWNERSHIP_TM the flow - * continues. - */ - iwl_test_rx(&priv->tst, rxb); -#endif - - if (priv->ucode_owner != IWL_OWNERSHIP_TM) { - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->rx_handlers_stats[pkt->hdr.cmd]++; - err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n", - iwl_dvm_get_cmd_string(pkt->hdr.cmd), - pkt->hdr.cmd); - } + /* Based on type of command response or notification, + * handle those that need handling via function in + * rx_handlers table. See iwl_setup_rx_handlers() */ + if (priv->rx_handlers[pkt->hdr.cmd]) { + priv->rx_handlers_stats[pkt->hdr.cmd]++; + err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); + } else { + /* No handling needed */ + IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n", + iwl_dvm_get_cmd_string(pkt->hdr.cmd), + pkt->hdr.cmd); } return err; } diff --git a/drivers/net/wireless/iwlwifi/dvm/testmode.c b/drivers/net/wireless/iwlwifi/dvm/testmode.c deleted file mode 100644 index b89b9d9b9969..000000000000 --- a/drivers/net/wireless/iwlwifi/dvm/testmode.c +++ /dev/null @@ -1,471 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-debug.h" -#include "iwl-trans.h" -#include "dev.h" -#include "agn.h" -#include "iwl-test.h" -#include "iwl-testmode.h" - -static int iwl_testmode_send_cmd(struct iwl_op_mode *op_mode, - struct iwl_host_cmd *cmd) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - return iwl_dvm_send_cmd(priv, cmd); -} - -static bool iwl_testmode_valid_hw_addr(u32 addr) -{ - if (iwlagn_hw_valid_rtc_data_addr(addr)) - return true; - - if (IWLAGN_RTC_INST_LOWER_BOUND <= addr && - addr < IWLAGN_RTC_INST_UPPER_BOUND) - return true; - - return false; -} - -static u32 iwl_testmode_get_fw_ver(struct iwl_op_mode *op_mode) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - return priv->fw->ucode_ver; -} - -static struct sk_buff* -iwl_testmode_alloc_reply(struct iwl_op_mode *op_mode, int len) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - return cfg80211_testmode_alloc_reply_skb(priv->hw->wiphy, len); -} - -static int iwl_testmode_reply(struct iwl_op_mode *op_mode, struct sk_buff *skb) -{ - return cfg80211_testmode_reply(skb); -} - -static struct sk_buff *iwl_testmode_alloc_event(struct iwl_op_mode *op_mode, - int len) -{ - struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - return cfg80211_testmode_alloc_event_skb(priv->hw->wiphy, len, - GFP_ATOMIC); -} - -static void iwl_testmode_event(struct iwl_op_mode *op_mode, struct sk_buff *skb) -{ - return cfg80211_testmode_event(skb, GFP_ATOMIC); -} - -static struct iwl_test_ops tst_ops = { - .send_cmd = iwl_testmode_send_cmd, - .valid_hw_addr = iwl_testmode_valid_hw_addr, - .get_fw_ver = iwl_testmode_get_fw_ver, - .alloc_reply = iwl_testmode_alloc_reply, - .reply = iwl_testmode_reply, - .alloc_event = iwl_testmode_alloc_event, - .event = iwl_testmode_event, -}; - -void iwl_testmode_init(struct iwl_priv *priv) -{ - iwl_test_init(&priv->tst, priv->trans, &tst_ops); -} - -void iwl_testmode_free(struct iwl_priv *priv) -{ - iwl_test_free(&priv->tst); -} - -static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) -{ - struct iwl_notification_wait calib_wait; - static const u8 calib_complete[] = { - CALIBRATION_COMPLETE_NOTIFICATION - }; - int ret; - - iwl_init_notification_wait(&priv->notif_wait, &calib_wait, - calib_complete, ARRAY_SIZE(calib_complete), - NULL, NULL); - ret = iwl_init_alive_start(priv); - if (ret) { - IWL_ERR(priv, "Fail init calibration: %d\n", ret); - goto cfg_init_calib_error; - } - - ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ); - if (ret) - IWL_ERR(priv, "Error detecting" - " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); - return ret; - -cfg_init_calib_error: - iwl_remove_notification(&priv->notif_wait, &calib_wait); - return ret; -} - -/* - * This function handles the user application commands for driver. - * - * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the - * handlers respectively. - * - * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned - * value of the actual command execution is replied to the user application. - * - * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP - * is used for carry the message while IWL_TM_ATTR_COMMAND must set to - * IWL_TM_CMD_DEV2APP_SYNC_RSP. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - struct iwl_trans *trans = priv->trans; - struct sk_buff *skb; - unsigned char *rsp_data_ptr = NULL; - int status = 0, rsp_data_len = 0; - u32 inst_size = 0, data_size = 0; - const struct fw_img *img; - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: - rsp_data_ptr = (unsigned char *)priv->cfg->name; - rsp_data_len = strlen(priv->cfg->name); - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - rsp_data_len + 20); - if (!skb) { - IWL_ERR(priv, "Memory allocation fail\n"); - return -ENOMEM; - } - if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_SYNC_RSP) || - nla_put(skb, IWL_TM_ATTR_SYNC_RSP, - rsp_data_len, rsp_data_ptr)) - goto nla_put_failure; - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_ERR(priv, "Error sending msg : %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: - status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); - if (status) - IWL_ERR(priv, "Error loading init ucode: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: - iwl_testmode_cfg_init_calib(priv); - priv->ucode_loaded = false; - iwl_trans_stop_device(trans); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: - status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR); - if (status) { - IWL_ERR(priv, - "Error loading runtime ucode: %d\n", status); - break; - } - status = iwl_alive_start(priv); - if (status) - IWL_ERR(priv, - "Error starting the device: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: - iwl_scan_cancel_timeout(priv, 200); - priv->ucode_loaded = false; - iwl_trans_stop_device(trans); - status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); - if (status) { - IWL_ERR(priv, - "Error loading WOWLAN ucode: %d\n", status); - break; - } - status = iwl_alive_start(priv); - if (status) - IWL_ERR(priv, - "Error starting the device: %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_GET_EEPROM: - if (priv->eeprom_blob) { - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - priv->eeprom_blob_size + 20); - if (!skb) { - IWL_ERR(priv, "Memory allocation fail\n"); - return -ENOMEM; - } - if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_EEPROM_RSP) || - nla_put(skb, IWL_TM_ATTR_EEPROM, - priv->eeprom_blob_size, - priv->eeprom_blob)) - goto nla_put_failure; - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_ERR(priv, "Error sending msg : %d\n", - status); - } else - return -ENODATA; - break; - - case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: - if (!tb[IWL_TM_ATTR_FIXRATE]) { - IWL_ERR(priv, "Missing fixrate setting\n"); - return -ENOMSG; - } - priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); - break; - - case IWL_TM_CMD_APP2DEV_GET_FW_INFO: - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); - if (!skb) { - IWL_ERR(priv, "Memory allocation fail\n"); - return -ENOMEM; - } - if (!priv->ucode_loaded) { - IWL_ERR(priv, "No uCode has not been loaded\n"); - return -EINVAL; - } else { - img = &priv->fw->img[priv->cur_ucode]; - inst_size = img->sec[IWL_UCODE_SECTION_INST].len; - data_size = img->sec[IWL_UCODE_SECTION_DATA].len; - } - if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) || - nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) || - nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size)) - goto nla_put_failure; - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_ERR(priv, "Error sending msg : %d\n", status); - break; - - default: - IWL_ERR(priv, "Unknown testmode driver command ID\n"); - return -ENOSYS; - } - return status; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - -/* - * This function handles the user application switch ucode ownership. - * - * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and - * decide who the current owner of the uCode - * - * If the current owner is OWNERSHIP_TM, then the only host command - * can deliver to uCode is from testmode, all the other host commands - * will dropped. - * - * default driver is the owner of uCode in normal operational mode - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - u8 owner; - - if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { - IWL_ERR(priv, "Missing ucode owner\n"); - return -ENOMSG; - } - - owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); - if (owner == IWL_OWNERSHIP_DRIVER) { - priv->ucode_owner = owner; - iwl_test_enable_notifications(&priv->tst, false); - } else if (owner == IWL_OWNERSHIP_TM) { - priv->ucode_owner = owner; - iwl_test_enable_notifications(&priv->tst, true); - } else { - IWL_ERR(priv, "Invalid owner\n"); - return -EINVAL; - } - return 0; -} - -/* The testmode gnl message handler that takes the gnl message from the - * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then - * invoke the corresponding handlers. - * - * This function is invoked when there is user space application sending - * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated - * by nl80211. - * - * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before - * dispatching it to the corresponding handler. - * - * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; - * -ENOSYS is replied to the user application if the command is unknown; - * Otherwise, the command is dispatched to the respective handler. - * - * @hw: ieee80211_hw object that represents the device - * @data: pointer to user space message - * @len: length in byte of @data - */ -int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) -{ - struct nlattr *tb[IWL_TM_ATTR_MAX]; - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - int result; - - result = iwl_test_parse(&priv->tst, tb, data, len); - if (result) - return result; - - /* in case multiple accesses to the device happens */ - mutex_lock(&priv->mutex); - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_UCODE: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: - case IWL_TM_CMD_APP2DEV_END_TRACE: - case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: - case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: - case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: - case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: - case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: - result = iwl_test_handle_cmd(&priv->tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: - case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: - case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: - case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: - case IWL_TM_CMD_APP2DEV_GET_EEPROM: - case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: - case IWL_TM_CMD_APP2DEV_GET_FW_INFO: - IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); - result = iwl_testmode_driver(hw, tb); - break; - - case IWL_TM_CMD_APP2DEV_OWNERSHIP: - IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); - result = iwl_testmode_ownership(hw, tb); - break; - - default: - IWL_ERR(priv, "Unknown testmode command\n"); - result = -ENOSYS; - break; - } - mutex_unlock(&priv->mutex); - - if (result) - IWL_ERR(priv, "Test cmd failed result=%d\n", result); - return result; -} - -int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, - struct netlink_callback *cb, - void *data, int len) -{ - struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); - int result; - u32 cmd; - - if (cb->args[3]) { - /* offset by 1 since commands start at 0 */ - cmd = cb->args[3] - 1; - } else { - struct nlattr *tb[IWL_TM_ATTR_MAX]; - - result = iwl_test_parse(&priv->tst, tb, data, len); - if (result) - return result; - - cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); - cb->args[3] = cmd + 1; - } - - /* in case multiple accesses to the device happens */ - mutex_lock(&priv->mutex); - result = iwl_test_dump(&priv->tst, cmd, skb, cb); - mutex_unlock(&priv->mutex); - return result; -} diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 353a053b4eb1..5ee983faa679 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -162,18 +162,6 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if (ieee80211_is_data(fc)) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; -#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE - if (priv->tm_fixed_rate) { - /* - * rate overwrite by testmode - * we not only send lq command to change rate - * we also re-enforce per data pkt base. - */ - tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK; - memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, - sizeof(tx_cmd->rate_n_flags)); - } -#endif return; } else if (ieee80211_is_back_req(fc)) tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-test.c b/drivers/net/wireless/iwlwifi/iwl-test.c deleted file mode 100644 index 5cfd55b86ed3..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-test.c +++ /dev/null @@ -1,852 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include -#include - -#include "iwl-drv.h" -#include "iwl-io.h" -#include "iwl-fh.h" -#include "iwl-prph.h" -#include "iwl-trans.h" -#include "iwl-test.h" -#include "iwl-csr.h" -#include "iwl-testmode.h" - -/* - * Periphery registers absolute lower bound. This is used in order to - * differentiate registery access through HBUS_TARG_PRPH_* and - * HBUS_TARG_MEM_* accesses. - */ -#define IWL_ABS_PRPH_START (0xA00000) - -/* - * The TLVs used in the gnl message policy between the kernel module and - * user space application. iwl_testmode_gnl_msg_policy is to be carried - * through the NL80211_CMD_TESTMODE channel regulated by nl80211. - * See iwl-testmode.h - */ -static -struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { - [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, - [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, - [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, - [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, - [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, - - [IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, }, - [IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, }, - [IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, }, - - [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, - [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, - [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, - [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, - [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, - - [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, }, -}; - -static inline void iwl_test_trace_clear(struct iwl_test *tst) -{ - memset(&tst->trace, 0, sizeof(struct iwl_test_trace)); -} - -static void iwl_test_trace_stop(struct iwl_test *tst) -{ - if (!tst->trace.enabled) - return; - - if (tst->trace.cpu_addr && tst->trace.dma_addr) - dma_free_coherent(tst->trans->dev, - tst->trace.tsize, - tst->trace.cpu_addr, - tst->trace.dma_addr); - - iwl_test_trace_clear(tst); -} - -static inline void iwl_test_mem_clear(struct iwl_test *tst) -{ - memset(&tst->mem, 0, sizeof(struct iwl_test_mem)); -} - -static inline void iwl_test_mem_stop(struct iwl_test *tst) -{ - if (!tst->mem.in_read) - return; - - iwl_test_mem_clear(tst); -} - -/* - * Initializes the test object - * During the lifetime of the test object it is assumed that the transport is - * started. The test object should be stopped before the transport is stopped. - */ -void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans, - struct iwl_test_ops *ops) -{ - tst->trans = trans; - tst->ops = ops; - - iwl_test_trace_clear(tst); - iwl_test_mem_clear(tst); -} -EXPORT_SYMBOL_GPL(iwl_test_init); - -/* - * Stop the test object - */ -void iwl_test_free(struct iwl_test *tst) -{ - iwl_test_mem_stop(tst); - iwl_test_trace_stop(tst); -} -EXPORT_SYMBOL_GPL(iwl_test_free); - -static inline int iwl_test_send_cmd(struct iwl_test *tst, - struct iwl_host_cmd *cmd) -{ - return tst->ops->send_cmd(tst->trans->op_mode, cmd); -} - -static inline bool iwl_test_valid_hw_addr(struct iwl_test *tst, u32 addr) -{ - return tst->ops->valid_hw_addr(addr); -} - -static inline u32 iwl_test_fw_ver(struct iwl_test *tst) -{ - return tst->ops->get_fw_ver(tst->trans->op_mode); -} - -static inline struct sk_buff* -iwl_test_alloc_reply(struct iwl_test *tst, int len) -{ - return tst->ops->alloc_reply(tst->trans->op_mode, len); -} - -static inline int iwl_test_reply(struct iwl_test *tst, struct sk_buff *skb) -{ - return tst->ops->reply(tst->trans->op_mode, skb); -} - -static inline struct sk_buff* -iwl_test_alloc_event(struct iwl_test *tst, int len) -{ - return tst->ops->alloc_event(tst->trans->op_mode, len); -} - -static inline void -iwl_test_event(struct iwl_test *tst, struct sk_buff *skb) -{ - return tst->ops->event(tst->trans->op_mode, skb); -} - -/* - * This function handles the user application commands to the fw. The fw - * commands are sent in a synchronuous manner. In case that the user requested - * to get commands response, it is send to the user. - */ -static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) -{ - struct iwl_host_cmd cmd; - struct iwl_rx_packet *pkt; - struct sk_buff *skb; - void *reply_buf; - u32 reply_len; - int ret; - bool cmd_want_skb; - - memset(&cmd, 0, sizeof(struct iwl_host_cmd)); - - if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || - !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { - IWL_ERR(tst->trans, "Missing fw command mandatory fields\n"); - return -ENOMSG; - } - - cmd.flags = CMD_ON_DEMAND | CMD_SYNC; - cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]); - if (cmd_want_skb) - cmd.flags |= CMD_WANT_SKB; - - cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); - cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); - cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - IWL_DEBUG_INFO(tst->trans, "test fw cmd=0x%x, flags 0x%x, len %d\n", - cmd.id, cmd.flags, cmd.len[0]); - - ret = iwl_test_send_cmd(tst, &cmd); - if (ret) { - IWL_ERR(tst->trans, "Failed to send hcmd\n"); - return ret; - } - if (!cmd_want_skb) - return ret; - - /* Handling return of SKB to the user */ - pkt = cmd.resp_pkt; - if (!pkt) { - IWL_ERR(tst->trans, "HCMD received a null response packet\n"); - return ret; - } - - reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - skb = iwl_test_alloc_reply(tst, reply_len + 20); - reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL); - if (!skb || !reply_buf) { - kfree_skb(skb); - kfree(reply_buf); - return -ENOMEM; - } - - /* The reply is in a page, that we cannot send to user space. */ - iwl_free_resp(&cmd); - - if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || - nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf)) - goto nla_put_failure; - return iwl_test_reply(tst, skb); - -nla_put_failure: - IWL_DEBUG_INFO(tst->trans, "Failed creating NL attributes\n"); - kfree(reply_buf); - kfree_skb(skb); - return -ENOMSG; -} - -/* - * Handles the user application commands for register access. - */ -static int iwl_test_reg(struct iwl_test *tst, struct nlattr **tb) -{ - u32 ofs, val32, cmd; - u8 val8; - struct sk_buff *skb; - int status = 0; - struct iwl_trans *trans = tst->trans; - - if (!tb[IWL_TM_ATTR_REG_OFFSET]) { - IWL_ERR(trans, "Missing reg offset\n"); - return -ENOMSG; - } - - ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); - IWL_DEBUG_INFO(trans, "test reg access cmd offset=0x%x\n", ofs); - - cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); - - /* - * Allow access only to FH/CSR/HBUS in direct mode. - * Since we don't have the upper bounds for the CSR and HBUS segments, - * we will use only the upper bound of FH for sanity check. - */ - if (ofs >= FH_MEM_UPPER_BOUND) { - IWL_ERR(trans, "offset out of segment (0x0 - 0x%x)\n", - FH_MEM_UPPER_BOUND); - return -EINVAL; - } - - switch (cmd) { - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - val32 = iwl_read_direct32(tst->trans, ofs); - IWL_DEBUG_INFO(trans, "32 value to read 0x%x\n", val32); - - skb = iwl_test_alloc_reply(tst, 20); - if (!skb) { - IWL_ERR(trans, "Memory allocation fail\n"); - return -ENOMEM; - } - if (nla_put_u32(skb, IWL_TM_ATTR_REG_VALUE32, val32)) - goto nla_put_failure; - status = iwl_test_reply(tst, skb); - if (status < 0) - IWL_ERR(trans, "Error sending msg : %d\n", status); - break; - - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_ERR(trans, "Missing value to write\n"); - return -ENOMSG; - } else { - val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); - IWL_DEBUG_INFO(trans, "32b write val=0x%x\n", val32); - iwl_write_direct32(tst->trans, ofs, val32); - } - break; - - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - if (!tb[IWL_TM_ATTR_REG_VALUE8]) { - IWL_ERR(trans, "Missing value to write\n"); - return -ENOMSG; - } else { - val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); - IWL_DEBUG_INFO(trans, "8b write val=0x%x\n", val8); - iwl_write8(tst->trans, ofs, val8); - } - break; - - default: - IWL_ERR(trans, "Unknown test register cmd ID\n"); - return -ENOMSG; - } - - return status; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - -/* - * Handles the request to start FW tracing. Allocates of the trace buffer - * and sends a reply to user space with the address of the allocated buffer. - */ -static int iwl_test_trace_begin(struct iwl_test *tst, struct nlattr **tb) -{ - struct sk_buff *skb; - int status = 0; - - if (tst->trace.enabled) - return -EBUSY; - - if (!tb[IWL_TM_ATTR_TRACE_SIZE]) - tst->trace.size = TRACE_BUFF_SIZE_DEF; - else - tst->trace.size = - nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); - - if (!tst->trace.size) - return -EINVAL; - - if (tst->trace.size < TRACE_BUFF_SIZE_MIN || - tst->trace.size > TRACE_BUFF_SIZE_MAX) - return -EINVAL; - - tst->trace.tsize = tst->trace.size + TRACE_BUFF_PADD; - tst->trace.cpu_addr = dma_alloc_coherent(tst->trans->dev, - tst->trace.tsize, - &tst->trace.dma_addr, - GFP_KERNEL); - if (!tst->trace.cpu_addr) - return -ENOMEM; - - tst->trace.enabled = true; - tst->trace.trace_addr = (u8 *)PTR_ALIGN(tst->trace.cpu_addr, 0x100); - - memset(tst->trace.trace_addr, 0x03B, tst->trace.size); - - skb = iwl_test_alloc_reply(tst, sizeof(tst->trace.dma_addr) + 20); - if (!skb) { - IWL_ERR(tst->trans, "Memory allocation fail\n"); - iwl_test_trace_stop(tst); - return -ENOMEM; - } - - if (nla_put(skb, IWL_TM_ATTR_TRACE_ADDR, - sizeof(tst->trace.dma_addr), - (u64 *)&tst->trace.dma_addr)) - goto nla_put_failure; - - status = iwl_test_reply(tst, skb); - if (status < 0) - IWL_ERR(tst->trans, "Error sending msg : %d\n", status); - - tst->trace.nchunks = DIV_ROUND_UP(tst->trace.size, - DUMP_CHUNK_SIZE); - - return status; - -nla_put_failure: - kfree_skb(skb); - if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) == - IWL_TM_CMD_APP2DEV_BEGIN_TRACE) - iwl_test_trace_stop(tst); - return -EMSGSIZE; -} - -/* - * Handles indirect read from the periphery or the SRAM. The read is performed - * to a temporary buffer. The user space application should later issue a dump - */ -static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size) -{ - struct iwl_trans *trans = tst->trans; - unsigned long flags; - int i; - - if (size & 0x3) - return -EINVAL; - - tst->mem.size = size; - tst->mem.addr = kmalloc(tst->mem.size, GFP_KERNEL); - if (tst->mem.addr == NULL) - return -ENOMEM; - - /* Hard-coded periphery absolute address */ - if (IWL_ABS_PRPH_START <= addr && - addr < IWL_ABS_PRPH_START + PRPH_END) { - if (!iwl_trans_grab_nic_access(trans, false, &flags)) { - return -EIO; - } - iwl_write32(trans, HBUS_TARG_PRPH_RADDR, - addr | (3 << 24)); - for (i = 0; i < size; i += 4) - *(u32 *)(tst->mem.addr + i) = - iwl_read32(trans, HBUS_TARG_PRPH_RDAT); - iwl_trans_release_nic_access(trans, &flags); - } else { /* target memory (SRAM) */ - iwl_trans_read_mem(trans, addr, tst->mem.addr, - tst->mem.size / 4); - } - - tst->mem.nchunks = - DIV_ROUND_UP(tst->mem.size, DUMP_CHUNK_SIZE); - tst->mem.in_read = true; - return 0; - -} - -/* - * Handles indirect write to the periphery or SRAM. The is performed to a - * temporary buffer. - */ -static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr, - u32 size, unsigned char *buf) -{ - struct iwl_trans *trans = tst->trans; - u32 val, i; - unsigned long flags; - - if (IWL_ABS_PRPH_START <= addr && - addr < IWL_ABS_PRPH_START + PRPH_END) { - /* Periphery writes can be 1-3 bytes long, or DWORDs */ - if (size < 4) { - memcpy(&val, buf, size); - if (!iwl_trans_grab_nic_access(trans, false, &flags)) - return -EIO; - iwl_write32(trans, HBUS_TARG_PRPH_WADDR, - (addr & 0x0000FFFF) | - ((size - 1) << 24)); - iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); - iwl_trans_release_nic_access(trans, &flags); - } else { - if (size % 4) - return -EINVAL; - for (i = 0; i < size; i += 4) - iwl_write_prph(trans, addr+i, - *(u32 *)(buf+i)); - } - } else if (iwl_test_valid_hw_addr(tst, addr)) { - iwl_trans_write_mem(trans, addr, buf, size / 4); - } else { - return -EINVAL; - } - return 0; -} - -/* - * Handles the user application commands for indirect read/write - * to/from the periphery or the SRAM. - */ -static int iwl_test_indirect_mem(struct iwl_test *tst, struct nlattr **tb) -{ - u32 addr, size, cmd; - unsigned char *buf; - - /* Both read and write should be blocked, for atomicity */ - if (tst->mem.in_read) - return -EBUSY; - - cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); - if (!tb[IWL_TM_ATTR_MEM_ADDR]) { - IWL_ERR(tst->trans, "Error finding memory offset address\n"); - return -ENOMSG; - } - addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]); - if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) { - IWL_ERR(tst->trans, "Error finding size for memory reading\n"); - return -ENOMSG; - } - size = nla_get_u32(tb[IWL_TM_ATTR_BUFFER_SIZE]); - - if (cmd == IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ) { - return iwl_test_indirect_read(tst, addr, size); - } else { - if (!tb[IWL_TM_ATTR_BUFFER_DUMP]) - return -EINVAL; - buf = (unsigned char *)nla_data(tb[IWL_TM_ATTR_BUFFER_DUMP]); - return iwl_test_indirect_write(tst, addr, size, buf); - } -} - -/* - * Enable notifications to user space - */ -static int iwl_test_notifications(struct iwl_test *tst, - struct nlattr **tb) -{ - tst->notify = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]); - return 0; -} - -/* - * Handles the request to get the device id - */ -static int iwl_test_get_dev_id(struct iwl_test *tst, struct nlattr **tb) -{ - u32 devid = tst->trans->hw_id; - struct sk_buff *skb; - int status; - - IWL_DEBUG_INFO(tst->trans, "hw version: 0x%x\n", devid); - - skb = iwl_test_alloc_reply(tst, 20); - if (!skb) { - IWL_ERR(tst->trans, "Memory allocation fail\n"); - return -ENOMEM; - } - - if (nla_put_u32(skb, IWL_TM_ATTR_DEVICE_ID, devid)) - goto nla_put_failure; - status = iwl_test_reply(tst, skb); - if (status < 0) - IWL_ERR(tst->trans, "Error sending msg : %d\n", status); - - return 0; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - -/* - * Handles the request to get the FW version - */ -static int iwl_test_get_fw_ver(struct iwl_test *tst, struct nlattr **tb) -{ - struct sk_buff *skb; - int status; - u32 ver = iwl_test_fw_ver(tst); - - IWL_DEBUG_INFO(tst->trans, "uCode version raw: 0x%x\n", ver); - - skb = iwl_test_alloc_reply(tst, 20); - if (!skb) { - IWL_ERR(tst->trans, "Memory allocation fail\n"); - return -ENOMEM; - } - - if (nla_put_u32(skb, IWL_TM_ATTR_FW_VERSION, ver)) - goto nla_put_failure; - - status = iwl_test_reply(tst, skb); - if (status < 0) - IWL_ERR(tst->trans, "Error sending msg : %d\n", status); - - return 0; - -nla_put_failure: - kfree_skb(skb); - return -EMSGSIZE; -} - -/* - * Parse the netlink message and validate that the IWL_TM_ATTR_CMD exists - */ -int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, - void *data, int len) -{ - int result; - - result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, - iwl_testmode_gnl_msg_policy); - if (result) { - IWL_ERR(tst->trans, "Fail parse gnl msg: %d\n", result); - return result; - } - - /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ - if (!tb[IWL_TM_ATTR_COMMAND]) { - IWL_ERR(tst->trans, "Missing testmode command type\n"); - return -ENOMSG; - } - return 0; -} -IWL_EXPORT_SYMBOL(iwl_test_parse); - -/* - * Handle test commands. - * Returns 1 for unknown commands (not handled by the test object); negative - * value in case of error. - */ -int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb) -{ - int result; - - switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_UCODE: - IWL_DEBUG_INFO(tst->trans, "test cmd to uCode\n"); - result = iwl_test_fw_cmd(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - IWL_DEBUG_INFO(tst->trans, "test cmd to register\n"); - result = iwl_test_reg(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_BEGIN_TRACE: - IWL_DEBUG_INFO(tst->trans, "test uCode trace cmd to driver\n"); - result = iwl_test_trace_begin(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_END_TRACE: - iwl_test_trace_stop(tst); - result = 0; - break; - - case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: - case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: - IWL_DEBUG_INFO(tst->trans, "test indirect memory cmd\n"); - result = iwl_test_indirect_mem(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_NOTIFICATIONS: - IWL_DEBUG_INFO(tst->trans, "test notifications cmd\n"); - result = iwl_test_notifications(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: - IWL_DEBUG_INFO(tst->trans, "test get FW ver cmd\n"); - result = iwl_test_get_fw_ver(tst, tb); - break; - - case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: - IWL_DEBUG_INFO(tst->trans, "test Get device ID cmd\n"); - result = iwl_test_get_dev_id(tst, tb); - break; - - default: - IWL_DEBUG_INFO(tst->trans, "Unknown test command\n"); - result = 1; - break; - } - return result; -} -IWL_EXPORT_SYMBOL(iwl_test_handle_cmd); - -static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb, - struct netlink_callback *cb) -{ - int idx, length; - - if (!tst->trace.enabled || !tst->trace.trace_addr) - return -EFAULT; - - idx = cb->args[4]; - if (idx >= tst->trace.nchunks) - return -ENOENT; - - length = DUMP_CHUNK_SIZE; - if (((idx + 1) == tst->trace.nchunks) && - (tst->trace.size % DUMP_CHUNK_SIZE)) - length = tst->trace.size % - DUMP_CHUNK_SIZE; - - if (nla_put(skb, IWL_TM_ATTR_TRACE_DUMP, length, - tst->trace.trace_addr + (DUMP_CHUNK_SIZE * idx))) - goto nla_put_failure; - - cb->args[4] = ++idx; - return 0; - - nla_put_failure: - return -ENOBUFS; -} - -static int iwl_test_buffer_dump(struct iwl_test *tst, struct sk_buff *skb, - struct netlink_callback *cb) -{ - int idx, length; - - if (!tst->mem.in_read) - return -EFAULT; - - idx = cb->args[4]; - if (idx >= tst->mem.nchunks) { - iwl_test_mem_stop(tst); - return -ENOENT; - } - - length = DUMP_CHUNK_SIZE; - if (((idx + 1) == tst->mem.nchunks) && - (tst->mem.size % DUMP_CHUNK_SIZE)) - length = tst->mem.size % DUMP_CHUNK_SIZE; - - if (nla_put(skb, IWL_TM_ATTR_BUFFER_DUMP, length, - tst->mem.addr + (DUMP_CHUNK_SIZE * idx))) - goto nla_put_failure; - - cb->args[4] = ++idx; - return 0; - - nla_put_failure: - return -ENOBUFS; -} - -/* - * Handle dump commands. - * Returns 1 for unknown commands (not handled by the test object); negative - * value in case of error. - */ -int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, - struct netlink_callback *cb) -{ - int result; - - switch (cmd) { - case IWL_TM_CMD_APP2DEV_READ_TRACE: - IWL_DEBUG_INFO(tst->trans, "uCode trace cmd\n"); - result = iwl_test_trace_dump(tst, skb, cb); - break; - - case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP: - IWL_DEBUG_INFO(tst->trans, "testmode sram dump cmd\n"); - result = iwl_test_buffer_dump(tst, skb, cb); - break; - - default: - result = 1; - break; - } - return result; -} -IWL_EXPORT_SYMBOL(iwl_test_dump); - -/* - * Multicast a spontaneous messages from the device to the user space. - */ -static void iwl_test_send_rx(struct iwl_test *tst, - struct iwl_rx_cmd_buffer *rxb) -{ - struct sk_buff *skb; - struct iwl_rx_packet *data; - int length; - - data = rxb_addr(rxb); - length = le32_to_cpu(data->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - - /* the length doesn't include len_n_flags field, so add it manually */ - length += sizeof(__le32); - - skb = iwl_test_alloc_event(tst, length + 20); - if (skb == NULL) { - IWL_ERR(tst->trans, "Out of memory for message to user\n"); - return; - } - - if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, - IWL_TM_CMD_DEV2APP_UCODE_RX_PKT) || - nla_put(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data)) - goto nla_put_failure; - - iwl_test_event(tst, skb); - return; - -nla_put_failure: - kfree_skb(skb); - IWL_ERR(tst->trans, "Ouch, overran buffer, check allocation!\n"); -} - -/* - * Called whenever a Rx frames is recevied from the device. If notifications to - * the user space are requested, sends the frames to the user. - */ -void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb) -{ - if (tst->notify) - iwl_test_send_rx(tst, rxb); -} -IWL_EXPORT_SYMBOL(iwl_test_rx); diff --git a/drivers/net/wireless/iwlwifi/iwl-test.h b/drivers/net/wireless/iwlwifi/iwl-test.h deleted file mode 100644 index 8fbd21704840..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-test.h +++ /dev/null @@ -1,161 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#ifndef __IWL_TEST_H__ -#define __IWL_TEST_H__ - -#include -#include "iwl-trans.h" - -struct iwl_test_trace { - u32 size; - u32 tsize; - u32 nchunks; - u8 *cpu_addr; - u8 *trace_addr; - dma_addr_t dma_addr; - bool enabled; -}; - -struct iwl_test_mem { - u32 size; - u32 nchunks; - u8 *addr; - bool in_read; -}; - -/* - * struct iwl_test_ops: callback to the op mode - * - * The structure defines the callbacks that the op_mode should handle, - * inorder to handle logic that is out of the scope of iwl_test. The - * op_mode must set all the callbacks. - - * @send_cmd: handler that is used by the test object to request the - * op_mode to send a command to the fw. - * - * @valid_hw_addr: handler that is used by the test object to request the - * op_mode to check if the given address is a valid address. - * - * @get_fw_ver: handler used to get the FW version. - * - * @alloc_reply: handler used by the test object to request the op_mode - * to allocate an skb for sending a reply to the user, and initialize - * the skb. It is assumed that the test object only fills the required - * attributes. - * - * @reply: handler used by the test object to request the op_mode to reply - * to a request. The skb is an skb previously allocated by the the - * alloc_reply callback. - I - * @alloc_event: handler used by the test object to request the op_mode - * to allocate an skb for sending an event, and initialize - * the skb. It is assumed that the test object only fills the required - * attributes. - * - * @reply: handler used by the test object to request the op_mode to send - * an event. The skb is an skb previously allocated by the the - * alloc_event callback. - */ -struct iwl_test_ops { - int (*send_cmd)(struct iwl_op_mode *op_modes, - struct iwl_host_cmd *cmd); - bool (*valid_hw_addr)(u32 addr); - u32 (*get_fw_ver)(struct iwl_op_mode *op_mode); - - struct sk_buff *(*alloc_reply)(struct iwl_op_mode *op_mode, int len); - int (*reply)(struct iwl_op_mode *op_mode, struct sk_buff *skb); - struct sk_buff* (*alloc_event)(struct iwl_op_mode *op_mode, int len); - void (*event)(struct iwl_op_mode *op_mode, struct sk_buff *skb); -}; - -struct iwl_test { - struct iwl_trans *trans; - struct iwl_test_ops *ops; - struct iwl_test_trace trace; - struct iwl_test_mem mem; - bool notify; -}; - -void iwl_test_init(struct iwl_test *tst, struct iwl_trans *trans, - struct iwl_test_ops *ops); - -void iwl_test_free(struct iwl_test *tst); - -int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb, - void *data, int len); - -int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb); - -int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb, - struct netlink_callback *cb); - -void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb); - -static inline void iwl_test_enable_notifications(struct iwl_test *tst, - bool enable) -{ - tst->notify = enable; -} - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h deleted file mode 100644 index 98f48a9afc98..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ /dev/null @@ -1,309 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2010 - 2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __IWL_TESTMODE_H__ -#define __IWL_TESTMODE_H__ - -#include - - -/* - * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and - * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). - * The command ID is carried with IWL_TM_ATTR_COMMAND. - * - * @IWL_TM_CMD_APP2DEV_UCODE: - * commands from user application to the uCode, - * the actual uCode host command ID is carried with - * IWL_TM_ATTR_UCODE_CMD_ID - * - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - * commands from user applicaiton to access register - * - * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name - * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image - * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration - * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image - * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data - * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS - * commands fom user space for pure driver level operations - * - * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE: - * @IWL_TM_CMD_APP2DEV_END_TRACE: - * @IWL_TM_CMD_APP2DEV_READ_TRACE: - * commands fom user space for uCode trace operations - * - * @IWL_TM_CMD_DEV2APP_SYNC_RSP: - * commands from kernel space to carry the synchronous response - * to user application - * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT: - * commands from kernel space to multicast the spontaneous messages - * to user application, or reply of host commands - * @IWL_TM_CMD_DEV2APP_EEPROM_RSP: - * commands from kernel space to carry the eeprom response - * to user application - * - * @IWL_TM_CMD_APP2DEV_OWNERSHIP: - * commands from user application to own change the ownership of the uCode - * if application has the ownership, the only host command from - * testmode will deliver to uCode. Default owner is driver - * - * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Wake On Wireless LAN uCode image - * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version - * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device - * @IWL_TM_CMD_APP2DEV_GET_FW_INFO: - * retrieve information of existing loaded uCode image - * - * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ: - * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP: - * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE: - * Commands to read/write data from periphery or SRAM memory ranges. - * Fore reading, a READ command is sent from the userspace and the data - * is returned when the user calls a DUMP command. - * For writing, only a WRITE command is used. - * @IWL_TM_CMD_APP2DEV_NOTIFICATIONS: - * Command to enable/disable notifications (currently RX packets) from the - * driver to userspace. - */ -enum iwl_tm_cmd_t { - IWL_TM_CMD_APP2DEV_UCODE = 1, - IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 = 2, - IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 = 3, - IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8 = 4, - IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5, - IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6, - IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7, - IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW = 8, - IWL_TM_CMD_APP2DEV_GET_EEPROM = 9, - IWL_TM_CMD_APP2DEV_FIXRATE_REQ = 10, - IWL_TM_CMD_APP2DEV_BEGIN_TRACE = 11, - IWL_TM_CMD_APP2DEV_END_TRACE = 12, - IWL_TM_CMD_APP2DEV_READ_TRACE = 13, - IWL_TM_CMD_DEV2APP_SYNC_RSP = 14, - IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15, - IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16, - IWL_TM_CMD_APP2DEV_OWNERSHIP = 17, - RESERVED_18 = 18, - RESERVED_19 = 19, - RESERVED_20 = 20, - RESERVED_21 = 21, - IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, - IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23, - IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24, - IWL_TM_CMD_APP2DEV_GET_FW_INFO = 25, - IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26, - IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27, - IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28, - IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29, - IWL_TM_CMD_MAX = 30, -}; - -/* - * Atrribute filed in testmode command - * See enum iwl_tm_cmd_t. - * - * @IWL_TM_ATTR_NOT_APPLICABLE: - * The attribute is not applicable or invalid - * @IWL_TM_ATTR_COMMAND: - * From user space to kernel space: - * the command either destines to ucode, driver, or register; - * From kernel space to user space: - * the command either carries synchronous response, - * or the spontaneous message multicast from the device; - * - * @IWL_TM_ATTR_UCODE_CMD_ID: - * @IWL_TM_ATTR_UCODE_CMD_DATA: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, - * The mandatory fields are : - * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; - * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload - * to the ucode - * - * @IWL_TM_ATTR_REG_OFFSET: - * @IWL_TM_ATTR_REG_VALUE8: - * @IWL_TM_ATTR_REG_VALUE32: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, - * The mandatory fields are: - * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; - * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value - * - * @IWL_TM_ATTR_SYNC_RSP: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, - * The mandatory fields are: - * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user - * application command - * - * @IWL_TM_ATTR_UCODE_RX_PKT: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, - * The mandatory fields are: - * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user - * application - * - * @IWL_TM_ATTR_EEPROM: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, - * The mandatory fields are: - * IWL_TM_ATTR_EEPROM for the data content responging to the user - * application - * - * @IWL_TM_ATTR_TRACE_ADDR: - * @IWL_TM_ATTR_TRACE_SIZE: - * @IWL_TM_ATTR_TRACE_DUMP: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, - * The mandatory fields are: - * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address - * IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size - * IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump - * - * @IWL_TM_ATTR_FIXRATE: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, - * The mandatory fields are: - * IWL_TM_ATTR_FIXRATE for the fixed rate - * - * @IWL_TM_ATTR_UCODE_OWNER: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP, - * The mandatory fields are: - * IWL_TM_ATTR_UCODE_OWNER for the new owner - * - * @IWL_TM_ATTR_MEM_ADDR: - * @IWL_TM_ATTR_BUFFER_SIZE: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ - * or IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE. - * The mandatory fields are: - * IWL_TM_ATTR_MEM_ADDR for the address in SRAM/periphery to read/write - * IWL_TM_ATTR_BUFFER_SIZE for the buffer size of data to read/write. - * - * @IWL_TM_ATTR_BUFFER_DUMP: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP, - * IWL_TM_ATTR_BUFFER_DUMP is used for the data that was read. - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE, - * this attribute contains the data to write. - * - * @IWL_TM_ATTR_FW_VERSION: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION, - * IWL_TM_ATTR_FW_VERSION for the uCode version - * - * @IWL_TM_ATTR_DEVICE_ID: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID, - * IWL_TM_ATTR_DEVICE_ID for the device ID information - * - * @IWL_TM_ATTR_FW_TYPE: - * @IWL_TM_ATTR_FW_INST_SIZE: - * @IWL_TM_ATTR_FW_DATA_SIZE: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_INFO, - * The mandatory fields are: - * IWL_TM_ATTR_FW_TYPE for the uCode type (INIT/RUNTIME/...) - * IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section - * IWL_TM_ATTR_FW_DATA_SIZE for the size of data section - * - * @IWL_TM_ATTR_UCODE_CMD_SKB: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag - * indicates that the user wants to receive the response of the command - * in a reply SKB. If it's not present, the response is not returned. - * @IWL_TM_ATTR_ENABLE_NOTIFICATIONS: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this - * flag enables (if present) or disables (if not) the forwarding - * to userspace. - */ -enum iwl_tm_attr_t { - IWL_TM_ATTR_NOT_APPLICABLE = 0, - IWL_TM_ATTR_COMMAND = 1, - IWL_TM_ATTR_UCODE_CMD_ID = 2, - IWL_TM_ATTR_UCODE_CMD_DATA = 3, - IWL_TM_ATTR_REG_OFFSET = 4, - IWL_TM_ATTR_REG_VALUE8 = 5, - IWL_TM_ATTR_REG_VALUE32 = 6, - IWL_TM_ATTR_SYNC_RSP = 7, - IWL_TM_ATTR_UCODE_RX_PKT = 8, - IWL_TM_ATTR_EEPROM = 9, - IWL_TM_ATTR_TRACE_ADDR = 10, - IWL_TM_ATTR_TRACE_SIZE = 11, - IWL_TM_ATTR_TRACE_DUMP = 12, - IWL_TM_ATTR_FIXRATE = 13, - IWL_TM_ATTR_UCODE_OWNER = 14, - IWL_TM_ATTR_MEM_ADDR = 15, - IWL_TM_ATTR_BUFFER_SIZE = 16, - IWL_TM_ATTR_BUFFER_DUMP = 17, - IWL_TM_ATTR_FW_VERSION = 18, - IWL_TM_ATTR_DEVICE_ID = 19, - IWL_TM_ATTR_FW_TYPE = 20, - IWL_TM_ATTR_FW_INST_SIZE = 21, - IWL_TM_ATTR_FW_DATA_SIZE = 22, - IWL_TM_ATTR_UCODE_CMD_SKB = 23, - IWL_TM_ATTR_ENABLE_NOTIFICATION = 24, - IWL_TM_ATTR_MAX = 25, -}; - -/* uCode trace buffer */ -#define TRACE_BUFF_SIZE_MAX 0x200000 -#define TRACE_BUFF_SIZE_MIN 0x20000 -#define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN -#define TRACE_BUFF_PADD 0x2000 - -/* Maximum data size of each dump it packet */ -#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024) - -/* Address offset of data segment in SRAM */ -#define SRAM_DATA_SEG_OFFSET 0x800000 - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index be4b2ac3dbbf..8d91422c5982 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -183,14 +183,12 @@ struct iwl_rx_packet { * @CMD_ASYNC: Return right away and don't want for the response * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the * response. The caller needs to call iwl_free_resp when done. - * @CMD_ON_DEMAND: This command is sent by the test mode pipe. */ enum CMD_MODE { CMD_SYNC = 0, CMD_ASYNC = BIT(0), CMD_WANT_SKB = BIT(1), CMD_SEND_IN_RFKILL = BIT(2), - CMD_ON_DEMAND = BIT(3), }; #define DEF_CMD_PAYLOAD_SIZE 320 diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index fbc0acb52191..7d216ddecf42 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -73,7 +73,6 @@ #include "iwl-trans.h" #include "iwl-notif-wait.h" #include "iwl-eeprom-parse.h" -#include "iwl-test.h" #include "iwl-trans.h" #include "sta.h" #include "fw-api.h" -- GitLab From a1193be83b4bb173228f04870afd6a4174b19130 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Fri, 14 Jun 2013 14:15:19 +0200 Subject: [PATCH 1392/2900] nl80211: use attributes to parse beacons only the attributes are required and not the whole netlink info, as the function accesses the attributes only anyway. This makes it easier to parse nested beacon IEs later. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 53 ++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e4028197b75d..1c4f7daea6c7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2882,61 +2882,58 @@ static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info) return err; } -static int nl80211_parse_beacon(struct genl_info *info, +static int nl80211_parse_beacon(struct nlattr *attrs[], struct cfg80211_beacon_data *bcn) { bool haveinfo = false; - if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || - !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) + if (!is_valid_ie_attr(attrs[NL80211_ATTR_BEACON_TAIL]) || + !is_valid_ie_attr(attrs[NL80211_ATTR_IE]) || + !is_valid_ie_attr(attrs[NL80211_ATTR_IE_PROBE_RESP]) || + !is_valid_ie_attr(attrs[NL80211_ATTR_IE_ASSOC_RESP])) return -EINVAL; memset(bcn, 0, sizeof(*bcn)); - if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { - bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); - bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); + if (attrs[NL80211_ATTR_BEACON_HEAD]) { + bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); + bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); if (!bcn->head_len) return -EINVAL; haveinfo = true; } - if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { - bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); - bcn->tail_len = - nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); + if (attrs[NL80211_ATTR_BEACON_TAIL]) { + bcn->tail = nla_data(attrs[NL80211_ATTR_BEACON_TAIL]); + bcn->tail_len = nla_len(attrs[NL80211_ATTR_BEACON_TAIL]); haveinfo = true; } if (!haveinfo) return -EINVAL; - if (info->attrs[NL80211_ATTR_IE]) { - bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); - bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); + if (attrs[NL80211_ATTR_IE]) { + bcn->beacon_ies = nla_data(attrs[NL80211_ATTR_IE]); + bcn->beacon_ies_len = nla_len(attrs[NL80211_ATTR_IE]); } - if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { + if (attrs[NL80211_ATTR_IE_PROBE_RESP]) { bcn->proberesp_ies = - nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); + nla_data(attrs[NL80211_ATTR_IE_PROBE_RESP]); bcn->proberesp_ies_len = - nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); + nla_len(attrs[NL80211_ATTR_IE_PROBE_RESP]); } - if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { + if (attrs[NL80211_ATTR_IE_ASSOC_RESP]) { bcn->assocresp_ies = - nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); + nla_data(attrs[NL80211_ATTR_IE_ASSOC_RESP]); bcn->assocresp_ies_len = - nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); + nla_len(attrs[NL80211_ATTR_IE_ASSOC_RESP]); } - if (info->attrs[NL80211_ATTR_PROBE_RESP]) { - bcn->probe_resp = - nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); - bcn->probe_resp_len = - nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]); + if (attrs[NL80211_ATTR_PROBE_RESP]) { + bcn->probe_resp = nla_data(attrs[NL80211_ATTR_PROBE_RESP]); + bcn->probe_resp_len = nla_len(attrs[NL80211_ATTR_PROBE_RESP]); } return 0; @@ -3015,7 +3012,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) !info->attrs[NL80211_ATTR_BEACON_HEAD]) return -EINVAL; - err = nl80211_parse_beacon(info, ¶ms.beacon); + err = nl80211_parse_beacon(info->attrs, ¶ms.beacon); if (err) return err; @@ -3167,7 +3164,7 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) if (!wdev->beacon_interval) return -EINVAL; - err = nl80211_parse_beacon(info, ¶ms); + err = nl80211_parse_beacon(info->attrs, ¶ms); if (err) return err; -- GitLab From f81a9dedaff434604c7fc3d9c299d277b76db0a8 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 13 Jun 2013 15:54:41 -0700 Subject: [PATCH 1393/2900] mac80211: update mesh beacon on workqueue Instead of updating the mesh beacon immediately when requested (which would require the sdata_lock()), defer it to the mac80211 workqueue. Fixes yet another deadlock on calling sta_info_flush() with the sdata_lock() held from ieee80211_stop_mesh(). We could just drop the sdata_lock() around the mesh_sta_cleanup() call, but this path is also taken from several non-locked error paths. Signed-off-by: Thomas Pedersen [fix comment position] Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mesh.c | 53 +++++++++++++++++++++++++++++--------- net/mac80211/mesh.h | 2 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a4dfb0be53d7..194be3de16dd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -544,6 +544,7 @@ struct ieee80211_if_mesh { struct timer_list mesh_path_root_timer; unsigned long wrkq_flags; + unsigned long mbss_changed; u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; size_t mesh_id_len; diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6c33af482df4..d5dea94216e4 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -161,11 +161,8 @@ void mesh_sta_cleanup(struct sta_info *sta) del_timer_sync(&sta->plink_timer); } - if (changed) { - sdata_lock(sdata); + if (changed) ieee80211_mbss_info_change_notify(sdata, changed); - sdata_unlock(sdata); - } } int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) @@ -719,14 +716,18 @@ ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata) void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed) { - if (sdata->vif.bss_conf.enable_beacon && - (changed & (BSS_CHANGED_BEACON | - BSS_CHANGED_HT | - BSS_CHANGED_BASIC_RATES | - BSS_CHANGED_BEACON_INT))) - if (ieee80211_mesh_rebuild_beacon(sdata)) - return; - ieee80211_bss_info_change_notify(sdata, changed); + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + unsigned long bits = changed; + u32 bit; + + if (!bits) + return; + + /* if we race with running work, worst case this work becomes a noop */ + for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) + set_bit(bit, &ifmsh->mbss_changed); + set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); + ieee80211_queue_work(&sdata->local->hw, &sdata->work); } int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) @@ -799,6 +800,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); del_timer_sync(&sdata->u.mesh.mesh_path_timer); + /* clear any mesh work (for next join) we may have accrued */ + ifmsh->wrkq_flags = 0; + ifmsh->mbss_changed = 0; + local->fif_other_bss--; atomic_dec(&local->iff_allmultis); ieee80211_configure_filter(local); @@ -965,6 +970,28 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, sdata_unlock(sdata); } +static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + u32 bit, changed = 0; + + for_each_set_bit(bit, &ifmsh->mbss_changed, + sizeof(changed) * BITS_PER_BYTE) { + clear_bit(bit, &ifmsh->mbss_changed); + changed |= BIT(bit); + } + + if (sdata->vif.bss_conf.enable_beacon && + (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_HT | + BSS_CHANGED_BASIC_RATES | + BSS_CHANGED_BEACON_INT))) + if (ieee80211_mesh_rebuild_beacon(sdata)) + return; + + ieee80211_bss_info_change_notify(sdata, changed); +} + void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; @@ -995,6 +1022,8 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) mesh_sync_adjust_tbtt(sdata); + if (test_and_clear_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags)) + mesh_bss_info_changed(sdata); out: sdata_unlock(sdata); } diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 01a28bca6e9b..2bc7fd2f787d 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -58,6 +58,7 @@ enum mesh_path_flags { * @MESH_WORK_ROOT: the mesh root station needs to send a frame * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other * mesh nodes + * @MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes */ enum mesh_deferred_task_flags { MESH_WORK_HOUSEKEEPING, @@ -65,6 +66,7 @@ enum mesh_deferred_task_flags { MESH_WORK_GROW_MPP_TABLE, MESH_WORK_ROOT, MESH_WORK_DRIFT_ADJUST, + MESH_WORK_MBSS_CHANGED, }; /** -- GitLab From 2f301ab29e4656af824592363039d8f6bd5a9f68 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 16 May 2013 13:00:28 +0200 Subject: [PATCH 1394/2900] nl80211/cfg80211: add 5 and 10 MHz defines and wiphy flag Add defines for 5 and 10 MHz channel width and fix channel handling functions accordingly. Also check for and report the WIPHY_FLAG_SUPPORTS_5_10_MHZ capability. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer [fix spelling in comment] Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 4 +++ net/wireless/chan.c | 57 +++++++++++++++++++++++++++++++----- net/wireless/nl80211.c | 21 ++++++++++--- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6a43c34ce96f..316f34bb8e6e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2342,6 +2342,7 @@ struct cfg80211_ops { * responds to probe-requests in hardware. * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX. * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call. + * @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -2365,6 +2366,7 @@ enum wiphy_flags { WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19), WIPHY_FLAG_OFFCHAN_TX = BIT(20), WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21), + WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22), }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index ca6facf4df0c..861e5eba3953 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2758,6 +2758,8 @@ enum nl80211_channel_type { * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 * attribute must be provided as well + * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel + * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel */ enum nl80211_chan_width { NL80211_CHAN_WIDTH_20_NOHT, @@ -2766,6 +2768,8 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_80, NL80211_CHAN_WIDTH_80P80, NL80211_CHAN_WIDTH_160, + NL80211_CHAN_WIDTH_5, + NL80211_CHAN_WIDTH_10, }; /** diff --git a/net/wireless/chan.c b/net/wireless/chan.c index fd556ac05fdb..50f6195c8b70 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -54,6 +54,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) control_freq = chandef->chan->center_freq; switch (chandef->width) { + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT: if (chandef->center_freq1 != control_freq) @@ -152,6 +154,12 @@ static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c) int width; switch (c->width) { + case NL80211_CHAN_WIDTH_5: + width = 5; + break; + case NL80211_CHAN_WIDTH_10: + width = 10; + break; case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT: width = 20; @@ -194,6 +202,16 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, if (c1->width == c2->width) return NULL; + /* + * can't be compatible if one of them is 5 or 10 MHz, + * but they don't have the same width. + */ + if (c1->width == NL80211_CHAN_WIDTH_5 || + c1->width == NL80211_CHAN_WIDTH_10 || + c2->width == NL80211_CHAN_WIDTH_5 || + c2->width == NL80211_CHAN_WIDTH_10) + return NULL; + if (c1->width == NL80211_CHAN_WIDTH_20_NOHT || c1->width == NL80211_CHAN_WIDTH_20) return c2; @@ -264,11 +282,17 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy, u32 bandwidth) { struct ieee80211_channel *c; - u32 freq; + u32 freq, start_freq, end_freq; + + if (bandwidth <= 20) { + start_freq = center_freq; + end_freq = center_freq; + } else { + start_freq = center_freq - bandwidth/2 + 10; + end_freq = center_freq + bandwidth/2 - 10; + } - for (freq = center_freq - bandwidth/2 + 10; - freq <= center_freq + bandwidth/2 - 10; - freq += 20) { + for (freq = start_freq; freq <= end_freq; freq += 20) { c = ieee80211_get_channel(wiphy, freq); if (!c) return -EINVAL; @@ -310,11 +334,17 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 prohibited_flags) { struct ieee80211_channel *c; - u32 freq; + u32 freq, start_freq, end_freq; + + if (bandwidth <= 20) { + start_freq = center_freq; + end_freq = center_freq; + } else { + start_freq = center_freq - bandwidth/2 + 10; + end_freq = center_freq + bandwidth/2 - 10; + } - for (freq = center_freq - bandwidth/2 + 10; - freq <= center_freq + bandwidth/2 - 10; - freq += 20) { + for (freq = start_freq; freq <= end_freq; freq += 20) { c = ieee80211_get_channel(wiphy, freq); if (!c) return false; @@ -349,6 +379,12 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, control_freq = chandef->chan->center_freq; switch (chandef->width) { + case NL80211_CHAN_WIDTH_5: + width = 5; + break; + case NL80211_CHAN_WIDTH_10: + width = 10; + break; case NL80211_CHAN_WIDTH_20: if (!ht_cap->ht_supported) return false; @@ -405,6 +441,11 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, if (width > 20) prohibited_flags |= IEEE80211_CHAN_NO_OFDM; + /* 5 and 10 MHz are only defined for the OFDM PHY */ + if (width < 20) + prohibited_flags |= IEEE80211_CHAN_NO_OFDM; + + if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1, width, prohibited_flags)) return false; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1c4f7daea6c7..4ab1ffa9df11 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1188,6 +1188,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) && + nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) + goto nla_put_failure; (*split_start)++; if (split) @@ -1731,6 +1734,11 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, IEEE80211_CHAN_DISABLED)) return -EINVAL; + if ((chandef->width == NL80211_CHAN_WIDTH_5 || + chandef->width == NL80211_CHAN_WIDTH_10) && + !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ)) + return -EINVAL; + return 0; } @@ -6280,11 +6288,16 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef)) return -EINVAL; - if (ibss.chandef.width > NL80211_CHAN_WIDTH_40) - return -EINVAL; - if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && - !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)) + switch (ibss.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + break; + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS) + break; + default: return -EINVAL; + } ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; -- GitLab From 30e747326378caec9ad13515bc9bde2e41b1fee3 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 16 May 2013 13:00:29 +0200 Subject: [PATCH 1395/2900] nl80211: add rate flags for 5/10 Mhz channels Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 316f34bb8e6e..e3a39fc9a296 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -188,6 +188,8 @@ struct ieee80211_channel { * when used with 802.11g (on the 2.4 GHz band); filled by the * core code when registering the wiphy. * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode. + * @IEEE80211_RATE_SUPPORTS_5MHZ: Rate can be used in 5 MHz mode + * @IEEE80211_RATE_SUPPORTS_10MHZ: Rate can be used in 10 MHz mode */ enum ieee80211_rate_flags { IEEE80211_RATE_SHORT_PREAMBLE = 1<<0, @@ -195,6 +197,8 @@ enum ieee80211_rate_flags { IEEE80211_RATE_MANDATORY_B = 1<<2, IEEE80211_RATE_MANDATORY_G = 1<<3, IEEE80211_RATE_ERP_G = 1<<4, + IEEE80211_RATE_SUPPORTS_5MHZ = 1<<5, + IEEE80211_RATE_SUPPORTS_10MHZ = 1<<6, }; /** @@ -432,6 +436,30 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, const struct cfg80211_chan_def *chandef, u32 prohibited_flags); +/** + * ieee80211_chandef_rate_flags - returns rate flags for a channel + * + * In some channel types, not all rates may be used - for example CCK + * rates may not be used in 5/10 MHz channels. + * + * @chandef: channel definition for the channel + * + * Returns: rate flags which apply for this channel + */ +static inline enum ieee80211_rate_flags +ieee80211_chandef_rate_flags(struct cfg80211_chan_def *chandef) +{ + switch (chandef->width) { + case NL80211_CHAN_WIDTH_5: + return IEEE80211_RATE_SUPPORTS_5MHZ; + case NL80211_CHAN_WIDTH_10: + return IEEE80211_RATE_SUPPORTS_10MHZ; + default: + break; + } + return 0; +} + /** * enum survey_info_flags - survey information flags * -- GitLab From 0418a445838749c51cf1e31a9c7ace6685ae87cd Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 16 May 2013 13:00:31 +0200 Subject: [PATCH 1396/2900] mac80211: fix various components for the new 5 and 10 MHz widths This is a collection of minor fixes: * don't allow HT IEs in IBSS for 5/10 MHz * don't allow HT IEs in Mesh for 5/10 MHz * don't downgrade from/to 5 and 10 MHz channels * don't try HT rates for 5 and 10 MHz channels when selecting rates Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 2 ++ net/mac80211/mesh.c | 4 +++- net/mac80211/mesh_plink.c | 8 +++++++- net/mac80211/mlme.c | 12 ++++++++++++ net/mac80211/rate.c | 8 +++++++- 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index caa4b4f7f6e4..3789c85282a0 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -176,6 +176,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, /* add HT capability and information IEs */ if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && + chandef.width != NL80211_CHAN_WIDTH_5 && + chandef.width != NL80211_CHAN_WIDTH_10 && sband->ht_cap.ht_supported) { pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d5dea94216e4..447f41bbe744 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -416,7 +416,9 @@ int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, sband = local->hw.wiphy->bands[band]; if (!sband->ht_cap.ht_supported || - sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 || + sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10) return 0; if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 09bebed99416..02c05fa15c20 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -154,8 +154,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) u16 ht_opmode; bool non_ht_sta = false, ht20_sta = false; - if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) + switch (sdata->vif.bss_conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: return 0; + default: + break; + } rcu_read_lock(); list_for_each_entry_rcu(sta, &local->sta_list, list) { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 87f2d4df31f8..e0939eb79060 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -190,6 +190,12 @@ static u32 chandef_downgrade(struct cfg80211_chan_def *c) c->width = NL80211_CHAN_WIDTH_20_NOHT; ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; break; + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: + WARN_ON_ONCE(1); + /* keep c->width */ + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; + break; } WARN_ON_ONCE(!cfg80211_chandef_valid(c)); @@ -3771,6 +3777,12 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, */ ret = ieee80211_vif_use_channel(sdata, &chandef, IEEE80211_CHANCTX_SHARED); + + /* don't downgrade for 5 and 10 MHz channels, though. */ + if (chandef.width == NL80211_CHAN_WIDTH_5 || + chandef.width == NL80211_CHAN_WIDTH_10) + return ret; + while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) { ifmgd->flags |= chandef_downgrade(&chandef); ret = ieee80211_vif_use_channel(sdata, &chandef, diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index d3f414fe67e0..dbbcd57b0fc6 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -397,8 +397,14 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, return; /* if HT BSS, and we handle a data frame, also try HT rates */ - if (chan_width == NL80211_CHAN_WIDTH_20_NOHT) + switch (chan_width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: return; + default: + break; + } alt_rate.idx = 0; /* keep protection flags */ -- GitLab From 3aede78aad2a7e39a81b4b0caa771d40254a6787 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Thu, 16 May 2013 13:00:36 +0200 Subject: [PATCH 1397/2900] mac80211: change IBSS channel state to chandef This should make some parts cleaner and is also required for handling 5/10 MHz properly. Signed-off-by: Simon Wunderlich Signed-off-by: Mathias Kretschmer Signed-off-by: Johannes Berg --- net/mac80211/ibss.c | 22 +++++++++++----------- net/mac80211/ieee80211_i.h | 3 +-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3789c85282a0..eaacfd27061c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -81,7 +81,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); + chandef = ifibss->chandef; if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { chandef.width = NL80211_CHAN_WIDTH_20; chandef.center_freq1 = chan->center_freq; @@ -516,7 +516,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, set_sta_flag(sta, WLAN_STA_WME); if (sta && elems->ht_operation && elems->ht_cap_elem && - sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { + sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT && + sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_5 && + sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_10) { /* we both use HT */ struct ieee80211_ht_cap htcap_ie; struct cfg80211_chan_def chandef; @@ -531,8 +533,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * fall back to HT20 if we don't use or use * the other extension channel */ - if (cfg80211_get_chandef_type(&chandef) != - sdata->u.ibss.channel_type) + if (chandef.center_freq1 != + sdata->u.ibss.chandef.center_freq1) htcap_ie.cap_info &= cpu_to_le16(~IEEE80211_HT_CAP_SUP_WIDTH_20_40); @@ -571,7 +573,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, /* different channel */ if (sdata->u.ibss.fixed_channel && - sdata->u.ibss.channel != cbss->channel) + sdata->u.ibss.chandef.chan != cbss->channel) goto put_bss; /* different SSID */ @@ -761,7 +763,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) sdata->drop_unencrypted = 0; __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, - ifibss->channel, ifibss->basic_rates, + ifibss->chandef.chan, ifibss->basic_rates, capability, 0, true); } @@ -793,7 +795,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) if (ifibss->fixed_bssid) bssid = ifibss->bssid; if (ifibss->fixed_channel) - chan = ifibss->channel; + chan = ifibss->chandef.chan; if (!is_zero_ether_addr(ifibss->bssid)) bssid = ifibss->bssid; cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, @@ -1060,9 +1062,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.beacon_int = params->beacon_interval; - sdata->u.ibss.channel = params->chandef.chan; - sdata->u.ibss.channel_type = - cfg80211_get_chandef_type(¶ms->chandef); + sdata->u.ibss.chandef = params->chandef; sdata->u.ibss.fixed_channel = params->channel_fixed; if (params->ie) { @@ -1121,7 +1121,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) if (ifibss->privacy) capability |= WLAN_CAPABILITY_PRIVACY; - cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel, + cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->chandef.chan, ifibss->bssid, ifibss->ssid, ifibss->ssid_len, WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 194be3de16dd..1bfc3955005c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -504,8 +504,7 @@ struct ieee80211_if_ibss { u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len, ie_len; u8 *ie; - struct ieee80211_channel *channel; - enum nl80211_channel_type channel_type; + struct cfg80211_chan_def chandef; unsigned long ibss_join_req; /* probe response/beacon for IBSS */ -- GitLab From f746caa3fcd23663489bb6d4b41091b75a16efa2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 20:04:36 +0200 Subject: [PATCH 1398/2900] MIPS: --- arch/mips/include/uapi/asm/resource.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/include/uapi/asm/resource.h b/arch/mips/include/uapi/asm/resource.h index 87cb3085269c..b26439d4ab0b 100644 --- a/arch/mips/include/uapi/asm/resource.h +++ b/arch/mips/include/uapi/asm/resource.h @@ -26,7 +26,7 @@ * but we keep the old value on MIPS32, * for compatibility: */ -#ifdef CONFIG_32BIT +#ifndef __mips64 # define RLIM_INFINITY 0x7fffffffUL #endif -- GitLab From cfb9a4e7a0d821902e8cf77cabd34ef76e214e9d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 21:06:52 +0200 Subject: [PATCH 1399/2900] MIPS: : Don't reference CONFIG_* symbols. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/swab.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/uapi/asm/swab.h b/arch/mips/include/uapi/asm/swab.h index 97c2f81b4b43..ac9a8f9cd1fb 100644 --- a/arch/mips/include/uapi/asm/swab.h +++ b/arch/mips/include/uapi/asm/swab.h @@ -13,7 +13,7 @@ #define __SWAB_64_THRU_32__ -#ifdef CONFIG_CPU_MIPSR2 +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) static inline __attribute_const__ __u16 __arch_swab16(__u16 x) { @@ -39,10 +39,10 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) #define __arch_swab32 __arch_swab32 /* - * Having already checked for CONFIG_CPU_MIPSR2, enable the - * optimized version for 64-bit kernel on r2 CPUs. + * Having already checked for MIPS R2, enable the optimized version for + * 64-bit kernel on r2 CPUs. */ -#ifdef CONFIG_64BIT +#ifdef __mips64 static inline __attribute_const__ __u64 __arch_swab64(__u64 x) { __asm__( @@ -54,6 +54,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x) return x; } #define __arch_swab64 __arch_swab64 -#endif /* CONFIG_64BIT */ -#endif /* CONFIG_CPU_MIPSR2 */ +#endif /* __mips64 */ +#endif /* MIPS R2 or newer */ #endif /* _ASM_SWAB_H */ -- GitLab From cfceb5e210d28d5dbc4d10e2a9191f4a81c4cece Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 21:16:15 +0200 Subject: [PATCH 1400/2900] MIPS: : Don't reference CONFIG_* symbols. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/msgbuf.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/mips/include/uapi/asm/msgbuf.h b/arch/mips/include/uapi/asm/msgbuf.h index 0d6c7f14de31..df849e87d9ae 100644 --- a/arch/mips/include/uapi/asm/msgbuf.h +++ b/arch/mips/include/uapi/asm/msgbuf.h @@ -14,25 +14,25 @@ struct msqid64_ds { struct ipc64_perm msg_perm; -#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEB__) unsigned long __unused1; #endif __kernel_time_t msg_stime; /* last msgsnd time */ -#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEL__) unsigned long __unused1; #endif -#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEB__) unsigned long __unused2; #endif __kernel_time_t msg_rtime; /* last msgrcv time */ -#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEL__) unsigned long __unused2; #endif -#if defined(CONFIG_32BIT) && !defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEB__) unsigned long __unused3; #endif __kernel_time_t msg_ctime; /* last change time */ -#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_LITTLE_ENDIAN) +#if !defined(__mips64) && defined(__MIPSEL__) unsigned long __unused3; #endif unsigned long msg_cbytes; /* current number of bytes on queue */ -- GitLab From c8d5c685647f7ce73ed642a9130e930ab69178d4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 12 Jun 2013 21:23:52 +0200 Subject: [PATCH 1401/2900] MIPS: : Don't reference CONFIG_* symbols. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/siginfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h index 6a8714193fb9..b7a23064841f 100644 --- a/arch/mips/include/uapi/asm/siginfo.h +++ b/arch/mips/include/uapi/asm/siginfo.h @@ -25,10 +25,10 @@ struct siginfo; /* * Careful to keep union _sifields from shifting ... */ -#ifdef CONFIG_32BIT +#if __SIZEOF_LONG__ == 4 #define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int)) #endif -#ifdef CONFIG_64BIT +#if __SIZEOF_LONG__ == 8 #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #endif -- GitLab From 39205750efa6d335fac4f9bcd32b49c7e71c12b7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 01:29:24 +0200 Subject: [PATCH 1402/2900] MIPS: Oceton: Fix build error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB, CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION, CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT and CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT are all undefined: arch/mips/cavium-octeon/setup.c: In function ‘prom_init’: arch/mips/cavium-octeon/setup.c:715:12: error: unused variable ‘ebase’ [-Werror=unused-variable] Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 01b1b3f94feb..1bcc144da287 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -7,6 +7,7 @@ * Copyright (C) 2008, 2009 Wind River Systems * written by Ralf Baechle */ +#include #include #include #include @@ -712,7 +713,7 @@ void __init prom_init(void) if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) { pr_info("Skipping L2 locking due to reduced L2 cache size\n"); } else { - uint32_t ebase = read_c0_ebase() & 0x3ffff000; + uint32_t __maybe_unused ebase = read_c0_ebase() & 0x3ffff000; #ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB /* TLB refill */ cvmx_l2c_lock_mem_region(ebase, 0x100); -- GitLab From 368b062509fac95c1e403ae4d2ff25fd4ca151fe Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 20 Jun 2013 16:10:50 +0200 Subject: [PATCH 1403/2900] MIPS: Octeon: Fix build error if CONFIG_BUG=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC init/do_mounts.o In file included from /home/ralf/src/linux/linux-mips/arch/mips/include/asm/dma-mapping.h:10:0, from include/linux/dma-mapping.h:76, from include/linux/skbuff.h:33, from include/linux/icmpv6.h:4, from include/linux/ipv6.h:59, from include/net/ipv6.h:16, from include/linux/sunrpc/clnt.h:26, from include/linux/nfs_fs.h:30, from init/do_mounts.c:30: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:24:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem_page’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:30:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_addr_to_phys’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:36:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_supported’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:47:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_mapping_error’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:63:1: warning: no return statement in function returning non-void [-Wreturn-type] LD init/mounts.o CC init/init_task.o In file included from /home/ralf/src/linux/linux-mips/arch/mips/include/asm/dma-mapping.h:10:0, from include/linux/dma-mapping.h:76, from include/linux/skbuff.h:33, from include/linux/netfilter.h:5, from include/net/netns/netfilter.h:5, from include/net/net_namespace.h:20, from include/linux/init_task.h:14, from init/init_task.c:1: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:24:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem_page’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:30:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_addr_to_phys’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:36:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_supported’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:47:1: warning: no return statement in function returning non-void [-Wreturn-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_mapping_error’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:63:1: warning: no return statement in function returning non-void [-Wreturn-type] LD init/built-in.o CC arch/mips/cavium-octeon/setup.o In file included from /home/ralf/src/linux/linux-mips/arch/mips/include/asm/dma-mapping.h:10:0, from include/linux/dma-mapping.h:76, from include/asm-generic/pci-dma-compat.h:7, from /home/ralf/src/linux/linux-mips/arch/mips/include/asm/pci.h:129, from include/linux/pci.h:1451, from /home/ralf/src/linux/linux-mips/arch/mips/include/asm/octeon/pci-octeon.h:12, from arch/mips/cavium-octeon/setup.c:41: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:24:1: error: no return statement in function returning non-void [-Werror=return-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_map_dma_mem_page’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:30:1: error: no return statement in function returning non-void [-Werror=return-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_addr_to_phys’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:36:1: error: no return statement in function returning non-void [-Werror=return-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_supported’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:47:1: error: no return statement in function returning non-void [-Werror=return-type] /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h: In function ‘plat_dma_mapping_error’: /home/ralf/src/linux/linux-mips/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h:63:1: error: no return statement in function returning non-void [-Werror=return-type] cc1: all warnings being treated as errors make[2]: *** [arch/mips/cavium-octeon/setup.o] Error 1 make[1]: *** [arch/mips/cavium-octeon] Error 2 make: *** [arch/mips] Error 2 [ralf@linux-mips.org: while at it, also include directly.] Signed-off-by: David Daney Patchwork: https://patchwork.linux-mips.org/patch/5519/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h index be8fb4240cec..47fb247f9663 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h +++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h @@ -13,6 +13,8 @@ #ifndef __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H #define __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H +#include + struct device; extern void octeon_pci_dma_init(void); @@ -21,18 +23,21 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) { BUG(); + return 0; } static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) { BUG(); + return 0; } static inline unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr) { BUG(); + return 0; } static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, @@ -44,6 +49,7 @@ static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, static inline int plat_dma_supported(struct device *dev, u64 mask) { BUG(); + return 0; } static inline void plat_extra_sync_for_device(struct device *dev) @@ -60,6 +66,7 @@ static inline int plat_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { BUG(); + return 0; } dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr); -- GitLab From 52874a5e3917dde3b081521b014d6e4b226aacff Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 18 Jun 2013 14:20:40 +0200 Subject: [PATCH 1404/2900] Revert "mac80211: in IBSS use the Auth frame to trigger STA reinsertion" This reverts commit 6d810f10325522cfcf498dc6d64b9f96e1f5153f In this way an IBSS station will not use the AUTH messages to trigger a state reinitialisation anymore. The behaviour was racy and was not working properly. It has been introduced to help wpa_supplicant to support IBSS/RSN, however all the logic is now getting moved into wpa_s itself which will also be in charge of handling the AUTH messages thanks to the mgmt frame registration. If userspace does not register for receiving AUTH frames then mac80211 will still reply by itself. At the same time, the auth frame registration counter can be removed since it is not needed anymore. Signed-off-by: Antonio Quartulli [remove unused variable] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 11 ---------- net/mac80211/ibss.c | 41 +++++++------------------------------- net/mac80211/ieee80211_i.h | 1 - 3 files changed, 7 insertions(+), 46 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 64cf294c2b96..18ba7ed3ef0b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2924,19 +2924,8 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, u16 frame_type, bool reg) { struct ieee80211_local *local = wiphy_priv(wiphy); - struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); switch (frame_type) { - case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; - - if (reg) - ifibss->auth_frame_registrations++; - else - ifibss->auth_frame_registrations--; - } - break; case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: if (reg) local->probe_req_reg++; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index eaacfd27061c..ea7b9c2c7e66 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -300,8 +300,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, tsf, false); } -static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, - bool auth) +static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta) __acquires(RCU) { struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -323,20 +322,12 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, /* If it fails, maybe we raced another insertion? */ if (sta_info_insert_rcu(sta)) return sta_info_get(sdata, addr); - if (auth && !sdata->u.ibss.auth_frame_registrations) { - ibss_dbg(sdata, - "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", - sdata->vif.addr, addr, sdata->u.ibss.bssid); - ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0, - addr, sdata->u.ibss.bssid, NULL, 0, 0, 0); - } return sta; } static struct sta_info * -ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, const u8 *addr, - u32 supp_rates, bool auth) +ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, + const u8 *addr, u32 supp_rates) __acquires(RCU) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; @@ -387,7 +378,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, sta->sta.supp_rates[band] = supp_rates | ieee80211_mandatory_rates(sband); - return ieee80211_ibss_finish_sta(sta, auth); + return ieee80211_ibss_finish_sta(sta); } static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata, @@ -409,8 +400,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, size_t len) { u16 auth_alg, auth_transaction; - struct sta_info *sta; - u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; sdata_assert_lock(sdata); @@ -427,22 +416,6 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) return; - sta_info_destroy_addr(sdata, mgmt->sa); - sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); - rcu_read_unlock(); - - /* - * if we have any problem in allocating the new station, we reply with a - * DEAUTH frame to tell the other end that we had a problem - */ - if (!sta) { - ieee80211_send_deauth_disassoc(sdata, sdata->u.ibss.bssid, - IEEE80211_STYPE_DEAUTH, - WLAN_REASON_UNSPECIFIED, true, - deauth_frame_buf); - return; - } - /* * IEEE 802.11 standard does not require authentication in IBSS * networks and most implementations do not seem to use it. @@ -508,7 +481,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, } else { rcu_read_unlock(); sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, - mgmt->sa, supp_rates, true); + mgmt->sa, supp_rates); } } @@ -614,7 +587,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ieee80211_sta_join_ibss(sdata, bss); supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, - supp_rates, true); + supp_rates); rcu_read_unlock(); } @@ -986,7 +959,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) list_del(&sta->list); spin_unlock_bh(&ifibss->incomplete_lock); - ieee80211_ibss_finish_sta(sta, true); + ieee80211_ibss_finish_sta(sta); rcu_read_unlock(); spin_lock_bh(&ifibss->incomplete_lock); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1bfc3955005c..00d71e9a8fb8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -498,7 +498,6 @@ struct ieee80211_if_ibss { bool privacy; bool control_port; - unsigned int auth_frame_registrations; u8 bssid[ETH_ALEN] __aligned(2); u8 ssid[IEEE80211_MAX_SSID_LEN]; -- GitLab From 069e2b351de67e7a837b15b3d26c65c19b790cc3 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 14 Jun 2013 19:55:13 +0000 Subject: [PATCH 1405/2900] slob: Rework #ifdeffery in slab.h Make the SLOB specific stuff harmonize more with the way the other allocators do it. Create the typical kmalloc constants for that purpose. SLOB does not support it but the constants help us avoid #ifdefs. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- include/linux/slab.h | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 0c621752caa6..9690c14eb7fb 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -169,11 +169,7 @@ struct kmem_cache { struct list_head list; /* List of all slab caches on the system */ }; -#define KMALLOC_MAX_SIZE (1UL << 30) - -#include - -#else /* CONFIG_SLOB */ +#endif /* CONFIG_SLOB */ /* * Kmalloc array related definitions @@ -195,7 +191,9 @@ struct kmem_cache { #ifndef KMALLOC_SHIFT_LOW #define KMALLOC_SHIFT_LOW 5 #endif -#else +#endif + +#ifdef CONFIG_SLUB /* * SLUB allocates up to order 2 pages directly and otherwise * passes the request to the page allocator. @@ -207,6 +205,19 @@ struct kmem_cache { #endif #endif +#ifdef CONFIG_SLOB +/* + * SLOB passes all page size and larger requests to the page allocator. + * No kmalloc array is necessary since objects of different sizes can + * be allocated from the same page. + */ +#define KMALLOC_SHIFT_MAX 30 +#define KMALLOC_SHIFT_HIGH PAGE_SHIFT +#ifndef KMALLOC_SHIFT_LOW +#define KMALLOC_SHIFT_LOW 3 +#endif +#endif + /* Maximum allocatable size */ #define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_MAX) /* Maximum size for which we actually use a slab cache */ @@ -221,6 +232,7 @@ struct kmem_cache { #define KMALLOC_MIN_SIZE (1 << KMALLOC_SHIFT_LOW) #endif +#ifndef CONFIG_SLOB extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1]; #ifdef CONFIG_ZONE_DMA extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1]; @@ -275,13 +287,18 @@ static __always_inline int kmalloc_index(size_t size) /* Will never be reached. Needed because the compiler may complain */ return -1; } +#endif /* !CONFIG_SLOB */ #ifdef CONFIG_SLAB #include -#elif defined(CONFIG_SLUB) +#endif + +#ifdef CONFIG_SLUB #include -#else -#error "Unknown slab allocator" +#endif + +#ifdef CONFIG_SLOB +#include #endif /* @@ -291,6 +308,7 @@ static __always_inline int kmalloc_index(size_t size) */ static __always_inline int kmalloc_size(int n) { +#ifndef CONFIG_SLOB if (n > 2) return 1 << n; @@ -299,10 +317,9 @@ static __always_inline int kmalloc_size(int n) if (n == 2 && KMALLOC_MIN_SIZE <= 64) return 192; - +#endif return 0; } -#endif /* !CONFIG_SLOB */ /* * Setting ARCH_SLAB_MINALIGN in arch headers allows a different alignment. -- GitLab From 143353104983f5af2c6087203b83312e58f3dc86 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 10:13:39 +0530 Subject: [PATCH 1406/2900] ath9k: Merge HWTIMER debug level with BTCOEX Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 13 ++++++------- drivers/net/wireless/ath/ath9k/hw.c | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 4521342c62cc..daeafeff186b 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -239,13 +239,12 @@ enum ATH_DEBUG { ATH_DBG_CONFIG = 0x00000200, ATH_DBG_FATAL = 0x00000400, ATH_DBG_PS = 0x00000800, - ATH_DBG_HWTIMER = 0x00001000, - ATH_DBG_BTCOEX = 0x00002000, - ATH_DBG_WMI = 0x00004000, - ATH_DBG_BSTUCK = 0x00008000, - ATH_DBG_MCI = 0x00010000, - ATH_DBG_DFS = 0x00020000, - ATH_DBG_WOW = 0x00040000, + ATH_DBG_BTCOEX = 0x00001000, + ATH_DBG_WMI = 0x00002000, + ATH_DBG_BSTUCK = 0x00004000, + ATH_DBG_MCI = 0x00008000, + ATH_DBG_DFS = 0x00010000, + ATH_DBG_WOW = 0x00020000, ATH_DBG_ANY = 0xffffffff }; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca9d9cd14ddb..5324c3346af8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -3042,7 +3042,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, timer_next = tsf + trig_timeout; - ath_dbg(ath9k_hw_common(ah), HWTIMER, + ath_dbg(ath9k_hw_common(ah), BTCOEX, "current tsf %x period %x timer_next %x\n", tsf, timer_period, timer_next); @@ -3141,7 +3141,7 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &thresh_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - ath_dbg(common, HWTIMER, "TSF overflow for Gen timer %d\n", + ath_dbg(common, BTCOEX, "TSF overflow for Gen timer %d\n", index); timer->overflow(timer->arg); } @@ -3150,7 +3150,7 @@ void ath_gen_timer_isr(struct ath_hw *ah) index = rightmost_index(timer_table, &trigger_mask); timer = timer_table->timers[index]; BUG_ON(!timer); - ath_dbg(common, HWTIMER, + ath_dbg(common, BTCOEX, "Gen timer[%d] trigger\n", index); timer->trigger(timer->arg); } -- GitLab From df401907b8cb2f6868ecbe82eaf029c3c9097674 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 10:13:40 +0530 Subject: [PATCH 1407/2900] ath9k: Convert a couple of debug messages Use the REGULATORY debug level to print the target power details. EEPROM can be used for other purposes and this spams the log. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index eae23b910bce..1e86977d3322 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4562,7 +4562,7 @@ static void ar9003_hw_get_target_power_eeprom(struct ath_hw *ah, is2GHz); for (i = 0; i < ar9300RateSize; i++) { - ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n", + ath_dbg(common, REGULATORY, "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); } } @@ -5288,7 +5288,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, return; for (i = 0; i < ar9300RateSize; i++) { - ath_dbg(common, EEPROM, "TPC[%02d] 0x%08x\n", + ath_dbg(common, REGULATORY, "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); } -- GitLab From 745a84e5c0675e41d38d93936ea5328da6bcc50c Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 10:13:41 +0530 Subject: [PATCH 1408/2900] ath9k: Update AR9462 2.0 initvals Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 999ab08c34e6..f00e9451a623 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -78,7 +78,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, -- GitLab From 51dbd0a897a995b44c2db04e29f224ae8fb8559b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 10:13:42 +0530 Subject: [PATCH 1409/2900] ath9k: Add support for 5G-XLNA/AR9462 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 18 +- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 27 ++ .../wireless/ath/ath9k/ar9462_2p0_initvals.h | 265 ++++++++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 1 + 4 files changed, 310 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index a3523c969a3a..ce748afd7f1a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -627,9 +627,22 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) { - if (AR_SREV_9462_20(ah)) + if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_mixed_rx_gain_table_2p0); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + ar9462_2p0_baseband_postamble_5g_xlna); + } +} + +static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) +{ + if (AR_SREV_9462_20(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p0_5g_xlna_only_rxgain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + ar9462_2p0_baseband_postamble_5g_xlna); + } } static void ar9003_rx_gain_table_apply(struct ath_hw *ah) @@ -645,6 +658,9 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) case 2: ar9003_rx_gain_table_mode2(ah); break; + case 3: + ar9003_rx_gain_table_mode3(ah); + break; } } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index bc483128efcd..df919e2b61d5 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -735,6 +735,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, return -EINVAL; } + /* + * SOC, MAC, BB, RADIO initvals. + */ for (i = 0; i < ATH_INI_NUM_SPLIT; i++) { ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); @@ -746,11 +749,29 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, modesIndex); } + /* + * RXGAIN initvals. + */ REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); + + if (AR_SREV_9462_20(ah)) { + /* + * 5G-XLNA + */ + if ((ar9003_hw_get_rx_gain_idx(ah) == 2) || + (ar9003_hw_get_rx_gain_idx(ah) == 3)) { + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + modesIndex, regWrites); + } + } + if (AR_SREV_9550(ah)) REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, regWrites); + /* + * TXGAIN initvals. + */ if (AR_SREV_9550(ah)) { int modes_txgain_index; @@ -772,8 +793,14 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites); + /* + * Clock frequency initvals. + */ REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites); + /* + * JAPAN regulatory. + */ if (chan->channel == 2484) ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1); diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index f00e9451a623..bcd0cae1048d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -1449,4 +1449,269 @@ static const u32 ar9462_common_mixed_rx_gain_table_2p0[][2] = { {0x0000b1fc, 0x00000196}, }; +static const u32 ar9462_2p0_baseband_postamble_5g_xlna[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, +}; + +static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x2a2d2f32}, + {0x0000b084, 0x21232328}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + #endif /* INITVALS_9462_2P0_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ed7d4fcbdcab..e07663964463 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -892,6 +892,7 @@ struct ath_hw { struct ar5416IniArray iniCckfirJapan2484; struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray ini_radio_post_sys2ant; + struct ar5416IniArray ini_modes_rxgain_5g_xlna; struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; -- GitLab From e861ef523cd91270d108edc394e648b1f9e6fbd5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 10:13:43 +0530 Subject: [PATCH 1410/2900] ath9k: Modify IDs to identify CUS230 CUS198 and CUS230 are similar cards, both are AR9485 + xLNA solutions. But, the subsystem IDs differ - identify CUS230 explicitly to make things clearer. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 7 +++++-- drivers/net/wireless/ath/ath9k/pci.c | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 74965eefbd1c..1a0a1688502c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -632,6 +632,7 @@ void ath_ant_comb_update(struct ath_softc *sc); /********************/ #define ATH9K_PCI_CUS198 0x0001 +#define ATH9K_PCI_CUS230 0x0002 /* * Default cache line size, in bytes. diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 7c2ed1cef9b7..0d17415a8a84 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -521,11 +521,14 @@ static void ath9k_init_platform(struct ath_softc *sc) if (common->bus_ops->ath_bus_type != ATH_PCI) return; - if (sc->driver_data & ATH9K_PCI_CUS198) { + if (sc->driver_data & (ATH9K_PCI_CUS198 | + ATH9K_PCI_CUS230)) { ah->config.xlna_gpio = 9; ah->config.xatten_margin_cfg = true; - ath_info(common, "Set parameters for CUS198\n"); + ath_info(common, "Set parameters for %s\n", + (sc->driver_data & ATH9K_PCI_CUS198) ? + "CUS198" : "CUS230"); } } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 4ac00b4b0d25..ddf0d78dbc48 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -51,16 +51,18 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { PCI_VENDOR_ID_AZWAVE, 0x2126), .driver_data = ATH9K_PCI_CUS198 }, + + /* PCI-E CUS230 */ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0032, PCI_VENDOR_ID_AZWAVE, 0x2152), - .driver_data = ATH9K_PCI_CUS198 }, + .driver_data = ATH9K_PCI_CUS230 }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, 0x0032, PCI_VENDOR_ID_FOXCONN, 0xE075), - .driver_data = ATH9K_PCI_CUS198 }, + .driver_data = ATH9K_PCI_CUS230 }, { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ -- GitLab From 7b5d6043de31290de98e9232cbd9a07968aef5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 18 Jun 2013 07:33:40 +0200 Subject: [PATCH 1411/2900] ssb: register serial flash as platform device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows writing MTD driver working as a platform driver. In platform_data it will receive struct ssb_sflash, which contains all important data about flash (window, size). Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_sflash.c | 19 +++++++++++++++++++ drivers/ssb/main.c | 8 ++++++++ drivers/ssb/ssb_private.h | 4 ++++ 3 files changed, 31 insertions(+) diff --git a/drivers/ssb/driver_chipcommon_sflash.c b/drivers/ssb/driver_chipcommon_sflash.c index 205f1c499c46..e84cf04f4416 100644 --- a/drivers/ssb/driver_chipcommon_sflash.c +++ b/drivers/ssb/driver_chipcommon_sflash.c @@ -9,6 +9,19 @@ #include "ssb_private.h" +static struct resource ssb_sflash_resource = { + .name = "ssb_sflash", + .start = SSB_FLASH2, + .end = 0, + .flags = IORESOURCE_MEM | IORESOURCE_READONLY, +}; + +struct platform_device ssb_sflash_dev = { + .name = "ssb_sflash", + .resource = &ssb_sflash_resource, + .num_resources = 1, +}; + struct ssb_sflash_tbl_e { char *name; u32 id; @@ -141,6 +154,12 @@ int ssb_sflash_init(struct ssb_chipcommon *cc) pr_info("Found %s serial flash (blocksize: 0x%X, blocks: %d)\n", e->name, e->blocksize, e->numblocks); + /* Prepare platform device, but don't register it yet. It's too early, + * malloc (required by device_private_init) is not available yet. */ + ssb_sflash_dev.resource[0].end = ssb_sflash_dev.resource[0].start + + sflash->size; + ssb_sflash_dev.dev.platform_data = sflash; + pr_err("Serial flash support is not implemented yet!\n"); return -ENOTSUPP; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 812775a4bfb6..e55ddf7cd7c2 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -553,6 +553,14 @@ static int ssb_devices_register(struct ssb_bus *bus) } #endif +#ifdef CONFIG_SSB_SFLASH + if (bus->mipscore.sflash.present) { + err = platform_device_register(&ssb_sflash_dev); + if (err) + pr_err("Error registering serial flash\n"); + } +#endif + return 0; error: /* Unwind the already registered devices. */ diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 4671f17f09af..eb507a50a564 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h @@ -243,6 +243,10 @@ static inline int ssb_sflash_init(struct ssb_chipcommon *cc) extern struct platform_device ssb_pflash_dev; #endif +#ifdef CONFIG_SSB_SFLASH +extern struct platform_device ssb_sflash_dev; +#endif + #ifdef CONFIG_SSB_DRIVER_EXTIF extern u32 ssb_extif_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt, u32 ticks); extern u32 ssb_extif_watchdog_timer_set_ms(struct bcm47xx_wdt *wdt, u32 ms); -- GitLab From e57426720f04587da79865176176f581cf79a11a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Jun 2013 10:28:46 +0300 Subject: [PATCH 1412/2900] ath10k: off by one sanity check This should be >= ARRAY_SIZE() instead of > ARRAY_SIZE(). Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 8e4e8327d33e..c8e905669701 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1772,7 +1772,7 @@ static irqreturn_t ath10k_pci_per_engine_handler(int irq, void *arg) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ce_id = irq - ar_pci->pdev->irq - MSI_ASSIGN_CE_INITIAL; - if (ce_id < 0 || ce_id > ARRAY_SIZE(ar_pci->pipe_info)) { + if (ce_id < 0 || ce_id >= ARRAY_SIZE(ar_pci->pipe_info)) { ath10k_warn("unexpected/invalid irq %d ce_id %d\n", irq, ce_id); return IRQ_HANDLED; } -- GitLab From 12eea64003abcb10563eaefc98ce0aeb58b05f61 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 15:42:36 +0530 Subject: [PATCH 1413/2900] ath9k: Add PCI IDs for CUS217 CUS217 is a card based on AR9462. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 2 ++ drivers/net/wireless/ath/ath9k/pci.c | 13 +++++++++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1a0a1688502c..04b2d3ea728f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -633,6 +633,7 @@ void ath_ant_comb_update(struct ath_softc *sc); #define ATH9K_PCI_CUS198 0x0001 #define ATH9K_PCI_CUS230 0x0002 +#define ATH9K_PCI_CUS217 0x0004 /* * Default cache line size, in bytes. diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0d17415a8a84..1e555d899469 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -529,6 +529,8 @@ static void ath9k_init_platform(struct ath_softc *sc) ath_info(common, "Set parameters for %s\n", (sc->driver_data & ATH9K_PCI_CUS198) ? "CUS198" : "CUS230"); + } else if (sc->driver_data & ATH9K_PCI_CUS217) { + ath_info(common, "CUS217 card detected\n"); } } diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index ddf0d78dbc48..b096bb2c28c8 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -66,6 +66,19 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ + + /* PCI-E CUS217 */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_AZWAVE, + 0x2116), + .driver_data = ATH9K_PCI_CUS217 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x11AD, /* LITEON */ + 0x6661), + .driver_data = ATH9K_PCI_CUS217 }, + { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */ -- GitLab From a86ff3cf47b3ba868214bfb8d2181409913ccbbe Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 15:42:37 +0530 Subject: [PATCH 1414/2900] ath9k: Add initvals required for CUS217 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index bcd0cae1048d..1d6b705ba110 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -1714,4 +1714,19 @@ static const u32 ar9462_2p0_5g_xlna_only_rxgain[][2] = { {0x0000b1fc, 0x00000196}, }; +static const u32 ar9462_2p0_baseband_core_mix_rxgain[][2] = { + /* Addr allmodes */ + {0x00009fd0, 0x0a2d6b93}, +}; + +static const u32 ar9462_2p0_baseband_postamble_mix_rxgain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, + {0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da}, + {0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8}, + {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e}, +}; + #endif /* INITVALS_9462_2P0_H */ -- GitLab From c177fabe20c60d0670bbf2fcc83440ae37fc4553 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 18 Jun 2013 15:42:38 +0530 Subject: [PATCH 1415/2900] ath9k: Program initvals for CUS217 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++++ drivers/net/wireless/ath/ath9k/ar9003_phy.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ce748afd7f1a..671aaa7e7337 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -630,6 +630,10 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_mixed_rx_gain_table_2p0); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, + ar9462_2p0_baseband_core_mix_rxgain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, + ar9462_2p0_baseband_postamble_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index df919e2b61d5..df84d20e1092 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -755,6 +755,16 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); if (AR_SREV_9462_20(ah)) { + /* + * CUS217 mix LNA mode. + */ + if (ar9003_hw_get_rx_gain_idx(ah) == 2) { + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core, + 1, regWrites); + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble, + modesIndex, regWrites); + } + /* * 5G-XLNA */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e07663964463..cd74b3afef7d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -893,6 +893,8 @@ struct ath_hw { struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray ini_radio_post_sys2ant; struct ar5416IniArray ini_modes_rxgain_5g_xlna; + struct ar5416IniArray ini_modes_rxgain_bb_core; + struct ar5416IniArray ini_modes_rxgain_bb_postamble; struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; -- GitLab From 7d747037b0642f6d939d6b0bb255b938b5f3c3ab Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Tue, 18 Jun 2013 13:29:22 +0200 Subject: [PATCH 1416/2900] brcmfmac: Only use credits for bcmc when firmware indicates it. The firmware will sent an event message when bc/mc traffic should be sent to the device using credit mechanism. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/fweh.h | 3 +- .../wireless/brcm80211/brcmfmac/fwsignal.c | 32 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 6ec5db9c60a5..e679214b3c98 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -101,7 +101,8 @@ struct brcmf_event; BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \ BRCMF_ENUM_DEF(DCS_REQUEST, 73) \ BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ - BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) + BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ + BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) #define BRCMF_ENUM_DEF(id, val) \ BRCMF_E_##id = (val), diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 70f70cea7f7d..1d8fa7dfa53d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -426,6 +426,7 @@ struct brcmf_fws_info { struct brcmf_fws_stats stats; struct brcmf_fws_hanger hanger; enum brcmf_fws_fcmode fcmode; + bool bcmc_credit_check; struct brcmf_fws_macdesc_table desc; struct workqueue_struct *fws_wq; struct work_struct fws_dequeue_work; @@ -1438,6 +1439,20 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, return 0; } +static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp, + const struct brcmf_event_msg *e, + void *data) +{ + struct brcmf_fws_info *fws = ifp->drvr->fws; + ulong flags; + + brcmf_fws_lock(ifp->drvr, flags); + if (fws) + fws->bcmc_credit_check = true; + brcmf_fws_unlock(ifp->drvr, flags); + return 0; +} + int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, struct sk_buff *skb) { @@ -1806,6 +1821,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) eh->h_dest, multicast, fifo); brcmf_fws_lock(drvr, flags); + /* multicast credit support is conditional, setting + * flag to false to assure credit is consumed below. + */ + if (fws->bcmc_credit_check) + multicast = false; + if (skcb->mac->suppressed || fws->bus_flow_blocked || brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) || @@ -1878,7 +1899,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) brcmf_fws_lock(fws->drvr, flags); for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked; fifo--) { - while (fws->fifo_credit[fifo]) { + while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && + (fifo == BRCMF_FWS_FIFO_BCMC))) { skb = brcmf_fws_deq(fws, fifo); if (!skb) break; @@ -1947,6 +1969,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr) brcmf_err("register credit map handler failed\n"); goto fail; } + rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT, + brcmf_fws_notify_bcmc_credit_support); + if (rc < 0) { + brcmf_err("register bcmc credit handler failed\n"); + brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP); + goto fail; + } /* setting the iovar may fail if feature is unsupported * so leave the rc as is so driver initialization can @@ -1971,6 +2000,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr) return 0; fail_event: + brcmf_fweh_unregister(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT); brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP); fail: brcmf_fws_deinit(drvr); -- GitLab From 4e89dfca87ae5a97c616c6ac9b2a9a15cc28903d Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 18 Jun 2013 13:29:23 +0200 Subject: [PATCH 1417/2900] brcmfmac: rename variable prec to more appropriate name, ie. fifo The term prec (precedence) is different from the fifo number. Rename use of prec with fifo to be consistent and clear. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 1d8fa7dfa53d..e66b723c1279 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -839,7 +839,7 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, struct brcmf_fws_mac_descriptor *entry, - int prec, bool send_immediately) + int fifo, bool send_immediately) { struct sk_buff *skb; struct brcmf_bus *bus; @@ -848,10 +848,10 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws, u32 len; /* check delayedQ and suppressQ in one call using bitmap */ - if (brcmu_pktq_mlen(&entry->psq, 3 << (prec * 2)) == 0) - entry->traffic_pending_bmp &= ~NBITVAL(prec); + if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0) + entry->traffic_pending_bmp &= ~NBITVAL(fifo); else - entry->traffic_pending_bmp |= NBITVAL(prec); + entry->traffic_pending_bmp |= NBITVAL(fifo); entry->send_tim_signal = false; if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) -- GitLab From ae66460989f1dd62da760c6123820d9741315260 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 18 Jun 2013 13:29:24 +0200 Subject: [PATCH 1418/2900] brcmfmac: remove dependency with nl80211.h The firmware-signalling code used NL80211_NUM_ACS, but it has its own definition enum brcmf_fws_fifo, which is more appropriate to use. This effectively removes the need to include nl80211.h. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index e66b723c1279..b702f3e6d882 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -142,7 +141,7 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id) #define BRCMF_FWS_FLOWCONTROL_HIWATER 128 #define BRCMF_FWS_FLOWCONTROL_LOWATER 64 -#define BRCMF_FWS_PSQ_PREC_COUNT ((NL80211_NUM_ACS + 1) * 2) +#define BRCMF_FWS_PSQ_PREC_COUNT ((BRCMF_FWS_FIFO_COUNT + 1) * 2) #define BRCMF_FWS_PSQ_LEN 256 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01 -- GitLab From 1ab083a3752760ec7751a7fa43db555d2d6f1e6a Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 18 Jun 2013 13:29:25 +0200 Subject: [PATCH 1419/2900] brcmfmac: consolidate mac_descriptor related function names Just cleaning up and being consistent in naming operations related to struct brcmf_fws_mac_descriptor objects. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index b702f3e6d882..13e75c4b1a6b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -631,8 +631,8 @@ static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws, desc->interface_id); } -static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, - u8 *addr, u8 ifidx) +static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc, + u8 *addr, u8 ifidx) { brcmf_dbg(TRACE, "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx); @@ -648,7 +648,7 @@ static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc, } static -void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc) +void brcmf_fws_macdesc_deinit(struct brcmf_fws_mac_descriptor *desc) { brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id); @@ -659,7 +659,7 @@ void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc) } static struct brcmf_fws_mac_descriptor * -brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) +brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea) { struct brcmf_fws_mac_descriptor *entry; int i; @@ -678,8 +678,7 @@ brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea) } static struct brcmf_fws_mac_descriptor* -brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, - u8 *da) +brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da) { struct brcmf_fws_mac_descriptor *entry = &fws->desc.other; bool multicast; @@ -695,7 +694,7 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, goto done; } - entry = brcmf_fws_mac_descriptor_lookup(fws, da); + entry = brcmf_fws_macdesc_lookup(fws, da); if (IS_ERR(entry)) entry = ifp->fws_desc; @@ -703,9 +702,9 @@ brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, struct brcmf_if *ifp, return entry; } -static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws, - struct brcmf_fws_mac_descriptor *entry, - int fifo) +static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws, + struct brcmf_fws_mac_descriptor *entry, + int fifo) { struct brcmf_fws_mac_descriptor *if_entry; bool closed; @@ -728,9 +727,9 @@ static bool brcmf_fws_mac_desc_closed(struct brcmf_fws_info *fws, return closed || !(entry->ac_bitmap & BIT(fifo)); } -static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws, - struct brcmf_fws_mac_descriptor *entry, - int ifidx) +static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws, + struct brcmf_fws_mac_descriptor *entry, + int ifidx) { if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) { brcmf_fws_psq_flush(fws, &entry->psq, ifidx); @@ -782,9 +781,9 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) /* cleanup individual nodes */ table = &fws->desc.nodes[0]; for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) - brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx); + brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx); - brcmf_fws_mac_desc_cleanup(fws, &fws->desc.other, ifidx); + brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx); brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx); brcmf_fws_hanger_cleanup(fws, matchfn, ifidx); } @@ -924,18 +923,18 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) if (entry->occupied) { brcmf_dbg(TRACE, "deleting %s mac %pM\n", entry->name, addr); - brcmf_fws_mac_desc_cleanup(fws, entry, -1); - brcmf_fws_clear_mac_descriptor(entry); + brcmf_fws_macdesc_cleanup(fws, entry, -1); + brcmf_fws_macdesc_deinit(entry); } else fws->stats.mac_update_failed++; return 0; } - existing = brcmf_fws_mac_descriptor_lookup(fws, addr); + existing = brcmf_fws_macdesc_lookup(fws, addr); if (IS_ERR(existing)) { if (!entry->occupied) { entry->mac_handle = mac_handle; - brcmf_fws_init_mac_descriptor(entry, addr, ifidx); + brcmf_fws_macdesc_init(entry, addr, ifidx); brcmf_fws_macdesc_set_name(fws, entry); brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); @@ -949,7 +948,7 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) memcpy(entry, existing, offsetof(struct brcmf_fws_mac_descriptor, psq)); entry->mac_handle = mac_handle; - brcmf_fws_clear_mac_descriptor(existing); + brcmf_fws_macdesc_deinit(existing); brcmf_fws_macdesc_set_name(fws, entry); brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, addr); @@ -1189,7 +1188,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) for (i = 0; i < num_nodes; i++) { entry = &table[(node_pos + i) % num_nodes]; if (!entry->occupied || - brcmf_fws_mac_desc_closed(fws, entry, fifo)) + brcmf_fws_macdesc_closed(fws, entry, fifo)) continue; if (entry->suppressed) @@ -1810,7 +1809,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) /* set control buffer information */ skcb->if_flags = 0; - skcb->mac = brcmf_fws_find_mac_desc(fws, ifp, eh->h_dest); + skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest); skcb->state = BRCMF_FWS_SKBSTATE_NEW; brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); if (!multicast) @@ -1828,7 +1827,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) if (skcb->mac->suppressed || fws->bus_flow_blocked || - brcmf_fws_mac_desc_closed(fws, skcb->mac, fifo) || + brcmf_fws_macdesc_closed(fws, skcb->mac, fifo) || brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) || (!multicast && brcmf_fws_consume_credit(fws, fifo, skb) < 0)) { @@ -1850,7 +1849,7 @@ void brcmf_fws_reset_interface(struct brcmf_if *ifp) if (!entry) return; - brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); + brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx); } void brcmf_fws_add_interface(struct brcmf_if *ifp) @@ -1863,7 +1862,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp) entry = &fws->desc.iface[ifp->ifidx]; ifp->fws_desc = entry; - brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx); + brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx); brcmf_fws_macdesc_set_name(fws, entry); brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); @@ -1881,7 +1880,7 @@ void brcmf_fws_del_interface(struct brcmf_if *ifp) brcmf_fws_lock(ifp->drvr, flags); ifp->fws_desc = NULL; brcmf_dbg(TRACE, "deleting %s\n", entry->name); - brcmf_fws_clear_mac_descriptor(entry); + brcmf_fws_macdesc_deinit(entry); brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx); brcmf_fws_unlock(ifp->drvr, flags); } @@ -1986,7 +1985,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr) } brcmf_fws_hanger_init(&drvr->fws->hanger); - brcmf_fws_init_mac_descriptor(&drvr->fws->desc.other, NULL, 0); + brcmf_fws_macdesc_init(&drvr->fws->desc.other, NULL, 0); brcmf_fws_macdesc_set_name(drvr->fws, &drvr->fws->desc.other); brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); -- GitLab From fccfe93036312f3ad35d37c2ca960f104c6e7f21 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Tue, 18 Jun 2013 13:29:26 +0200 Subject: [PATCH 1420/2900] brcmfmac: simplify dpc handling using atomic operations Instead of allocating an empty list item and queue that for the dpc data worker to dequeue an atomic counter is used. Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 70 ++++--------------- 1 file changed, 12 insertions(+), 58 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 6f3d181659ef..d4db0c7cd692 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -495,8 +495,7 @@ struct brcmf_sdio { struct workqueue_struct *brcmf_wq; struct work_struct datawork; - struct list_head dpc_tsklst; - spinlock_t dpc_tl_lock; + atomic_t dpc_tskcnt; const struct firmware *firmware; u32 fw_ptr; @@ -2061,23 +2060,6 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) } } -static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus) -{ - struct list_head *new_hd; - unsigned long flags; - - if (in_interrupt()) - new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC); - else - new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL); - if (new_hd == NULL) - return; - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_add_tail(new_hd, &bus->dpc_tsklst); - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); -} - static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) { u8 idx; @@ -2312,7 +2294,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) (!atomic_read(&bus->fcstate) && brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && data_ok(bus)) || PKT_AVAILABLE()) { - brcmf_sdbrcm_adddpctsk(bus); + atomic_inc(&bus->dpc_tskcnt); } /* If we're done for now, turn off clock request. */ @@ -2342,7 +2324,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; - unsigned long flags; brcmf_dbg(TRACE, "Enter\n"); @@ -2381,14 +2362,9 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) qcount[prec] = pktq_plen(&bus->txq, prec); #endif - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - if (list_empty(&bus->dpc_tsklst)) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); - - brcmf_sdbrcm_adddpctsk(bus); + if (atomic_read(&bus->dpc_tskcnt) == 0) { + atomic_inc(&bus->dpc_tskcnt); queue_work(bus->brcmf_wq, &bus->datawork); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); } return ret; @@ -2525,7 +2501,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; - unsigned long flags; brcmf_dbg(TRACE, "Enter\n"); @@ -2612,18 +2587,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) } while (ret < 0 && retries++ < TXRETRIES); } - spin_lock_irqsave(&bus->dpc_tl_lock, flags); if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && - list_empty(&bus->dpc_tsklst)) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); - + atomic_read(&bus->dpc_tskcnt) == 0) { bus->activity = false; sdio_claim_host(bus->sdiodev->func[1]); brcmf_dbg(INFO, "idle\n"); brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); sdio_release_host(bus->sdiodev->func[1]); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); } if (ret) @@ -3451,7 +3421,7 @@ void brcmf_sdbrcm_isr(void *arg) if (!bus->intr) brcmf_err("isr w/o interrupt configured!\n"); - brcmf_sdbrcm_adddpctsk(bus); + atomic_inc(&bus->dpc_tskcnt); queue_work(bus->brcmf_wq, &bus->datawork); } @@ -3460,7 +3430,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) #ifdef DEBUG struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); #endif /* DEBUG */ - unsigned long flags; brcmf_dbg(TIMER, "Enter\n"); @@ -3476,11 +3445,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) if (!bus->intr || (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - if (list_empty(&bus->dpc_tsklst)) { + if (atomic_read(&bus->dpc_tskcnt) == 0) { u8 devpend; - spin_unlock_irqrestore(&bus->dpc_tl_lock, - flags); + sdio_claim_host(bus->sdiodev->func[1]); devpend = brcmf_sdio_regrb(bus->sdiodev, SDIO_CCCR_INTx, @@ -3489,9 +3456,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); - } else { - spin_unlock_irqrestore(&bus->dpc_tl_lock, - flags); } /* If there is something, make like the ISR and @@ -3500,7 +3464,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) bus->sdcnt.pollcnt++; atomic_set(&bus->ipend, 1); - brcmf_sdbrcm_adddpctsk(bus); + atomic_inc(&bus->dpc_tskcnt); queue_work(bus->brcmf_wq, &bus->datawork); } } @@ -3566,20 +3530,11 @@ static void brcmf_sdio_dataworker(struct work_struct *work) { struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, datawork); - struct list_head *cur_hd, *tmp_hd; - unsigned long flags; - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) { - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); + while (atomic_read(&bus->dpc_tskcnt)) { brcmf_sdbrcm_dpc(bus); - - spin_lock_irqsave(&bus->dpc_tl_lock, flags); - list_del(cur_hd); - kfree(cur_hd); + atomic_dec(&bus->dpc_tskcnt); } - spin_unlock_irqrestore(&bus->dpc_tl_lock, flags); } static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) @@ -3927,8 +3882,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->watchdog_tsk = NULL; } /* Initialize DPC thread */ - INIT_LIST_HEAD(&bus->dpc_tsklst); - spin_lock_init(&bus->dpc_tl_lock); + atomic_set(&bus->dpc_tskcnt, 0); /* Assign bus interface call back */ bus->sdiodev->bus_if->dev = bus->sdiodev->dev; -- GitLab From 16035d51b3e49e6e90b2e324feb437ed7893b045 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Tue, 18 Jun 2013 13:29:27 +0200 Subject: [PATCH 1421/2900] brcmfmac: remove redundant chip ID check in dhd_sdio There is an ID table registered to SDIO stack which consists of all SDIO devices supported by brcmfmac. It is not necessary to have an extra check. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index d4db0c7cd692..cb22f2f51453 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -3509,23 +3509,6 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) return (atomic_read(&bus->ipend) > 0); } -static bool brcmf_sdbrcm_chipmatch(u16 chipid) -{ - if (chipid == BCM43143_CHIP_ID) - return true; - if (chipid == BCM43241_CHIP_ID) - return true; - if (chipid == BCM4329_CHIP_ID) - return true; - if (chipid == BCM4330_CHIP_ID) - return true; - if (chipid == BCM4334_CHIP_ID) - return true; - if (chipid == BCM4335_CHIP_ID) - return true; - return false; -} - static void brcmf_sdio_dataworker(struct work_struct *work) { struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, @@ -3622,11 +3605,6 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) goto fail; } - if (!brcmf_sdbrcm_chipmatch((u16) bus->ci->chip)) { - brcmf_err("unsupported chip: 0x%04x\n", bus->ci->chip); - goto fail; - } - if (brcmf_sdbrcm_kso_init(bus)) { brcmf_err("error enabling KSO\n"); goto fail; -- GitLab From 78b3f1c5be8fdb3c83d21a357b1f8e89f5e18a6b Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Tue, 18 Jun 2013 13:29:28 +0200 Subject: [PATCH 1422/2900] brcmfmac: replace brcmf_sdioh_request_buffer with brcmf_sdio_buffrw Introducing a new SDIO block data access interface function brcmf_sdio_buffrw. It will act as a unified interface function for any block data access to WiFi dongle through SDIO interface. This patch enables the support for single skb transmission. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh.c | 58 +++++++++++++++---- .../brcm80211/brcmfmac/bcmsdh_sdmmc.c | 41 +------------ .../wireless/brcm80211/brcmfmac/sdio_host.h | 8 +-- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 4891e3df2058..32a205e0b063 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -303,6 +303,49 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, *ret = retval; } +/** + * brcmf_sdio_buffrw - SDIO interface function for block data access + * @sdiodev: brcmfmac sdio device + * @fn: SDIO function number + * @write: direction flag + * @addr: dongle memory address as source/destination + * @pkt: skb pointer + * + * This function takes the respbonsibility as the interface function to MMC + * stack for block data access. It assumes that the skb passed down by the + * caller has already been padded and aligned. + */ +static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, + bool write, u32 addr, struct sk_buff *pkt) +{ + uint len; + + brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); + if (brcmf_pm_resume_error(sdiodev)) + return -EIO; + + /* Single skb use the standard mmc interface */ + if (!pkt->next) { + len = pkt->len + 3; + len &= (uint)~3; + + if (write) + return sdio_memcpy_toio(sdiodev->func[fn], addr, + ((u8 *)(pkt->data)), len); + else if (fn == 1) + return sdio_memcpy_fromio(sdiodev->func[fn], + ((u8 *)(pkt->data)), addr, + len); + else + /* function 2 read is FIFO operation */ + return sdio_readsb(sdiodev->func[fn], + ((u8 *)(pkt->data)), addr, len); + } + + brcmf_err("skb chain is not supported yet.\n"); + return -EOPNOTSUPP; +} + static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, uint flags, uint width, u32 *addr) { @@ -355,7 +398,6 @@ int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint flags, struct sk_buff *pkt) { - uint incr_fix; uint width; int err = 0; @@ -367,9 +409,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (err) goto done; - incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, - fn, addr, pkt); + err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); done: return err; @@ -424,7 +464,6 @@ int brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint flags, struct sk_buff *pkt) { - uint incr_fix; uint width; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; @@ -446,13 +485,11 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, addr &= SBSDIO_SB_OFT_ADDR_MASK; - incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; if (width == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, - addr, pkt); + err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pkt); done: return err; @@ -501,9 +538,8 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, skb_put(pkt, dsize); if (write) memcpy(pkt->data, data, dsize); - bcmerror = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, - write, SDIO_FUNC_1, - sdaddr, pkt); + bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, + sdaddr, pkt); if (bcmerror) { brcmf_err("membytes transfer failed\n"); break; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 11400b39cf0b..7a3c5bf33e03 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -66,7 +66,7 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; -static bool +bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) { bool is_err = false; @@ -76,7 +76,7 @@ brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev) return is_err; } -static void +void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, wait_queue_head_t *wq) { #ifdef CONFIG_PM_SLEEP @@ -283,43 +283,6 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, return err_ret; } -/* - * This function takes a single DMA-able packet. - */ -int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, - uint fix_inc, uint write, uint func, uint addr, - struct sk_buff *pkt) -{ - int status; - uint pkt_len; - bool fifo = (fix_inc == SDIOH_DATA_FIX); - - brcmf_dbg(SDIO, "Enter\n"); - - if (pkt == NULL) - return -EINVAL; - pkt_len = pkt->len; - - brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); - if (brcmf_pm_resume_error(sdiodev)) - return -EIO; - - pkt_len += 3; - pkt_len &= (uint)~3; - - status = brcmf_sdioh_request_data(sdiodev, write, fifo, func, - addr, pkt, pkt_len); - if (status) { - brcmf_err("%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - write ? "TX" : "RX", pkt, addr, pkt_len, status); - } else { - brcmf_dbg(SDIO, "%s xfr'd %p, addr=0x%05x, len=%d\n", - write ? "TX" : "RX", pkt, addr, pkt_len); - } - - return status; -} - static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) { /* read 24 bits and return valid 17 bit addr */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 7c1b6332747e..991c1501f7e1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -274,10 +274,6 @@ brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, /* read or write any buffer using cmd53 */ extern int -brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, - uint fix_inc, uint rw, uint fnc_num, u32 addr, - struct sk_buff *pkt); -extern int brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, uint write, uint func, uint addr, struct sk_buff_head *pktq); @@ -291,4 +287,8 @@ extern void brcmf_sdbrcm_disconnect(void *ptr); extern void brcmf_sdbrcm_isr(void *arg); extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick); + +extern void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev, + wait_queue_head_t *wq); +extern bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev); #endif /* _BRCM_SDH_H_ */ -- GitLab From 354b75bfdbef02739af39acdbf804549c4626816 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Tue, 18 Jun 2013 13:29:29 +0200 Subject: [PATCH 1423/2900] brcmfmac: add sdio sg list support Add scatter gather list support for better rx glom performance. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh.c | 149 ++++++++++++++++-- .../brcm80211/brcmfmac/bcmsdh_sdmmc.c | 73 --------- .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 82 +--------- .../wireless/brcm80211/brcmfmac/sdio_host.h | 7 - 4 files changed, 137 insertions(+), 174 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 32a205e0b063..3f8e69c29146 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -22,9 +22,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -316,34 +318,138 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, * caller has already been padded and aligned. */ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, - bool write, u32 addr, struct sk_buff *pkt) + bool write, u32 addr, struct sk_buff_head *pktlist) { - uint len; + unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; + unsigned int max_blks, max_req_sz; + unsigned short max_seg_sz, seg_sz; + unsigned char *pkt_data; + struct sk_buff *pkt_next = NULL; + struct mmc_request mmc_req; + struct mmc_command mmc_cmd; + struct mmc_data mmc_dat; + struct sg_table st; + struct scatterlist *sgl; + struct mmc_host *host; + int ret = 0; + + if (!pktlist->qlen) + return -EINVAL; brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); if (brcmf_pm_resume_error(sdiodev)) return -EIO; /* Single skb use the standard mmc interface */ - if (!pkt->next) { - len = pkt->len + 3; - len &= (uint)~3; + if (pktlist->qlen == 1) { + pkt_next = pktlist->next; + req_sz = pkt_next->len + 3; + req_sz &= (uint)~3; if (write) return sdio_memcpy_toio(sdiodev->func[fn], addr, - ((u8 *)(pkt->data)), len); + ((u8 *)(pkt_next->data)), + req_sz); else if (fn == 1) return sdio_memcpy_fromio(sdiodev->func[fn], - ((u8 *)(pkt->data)), addr, - len); + ((u8 *)(pkt_next->data)), + addr, req_sz); else /* function 2 read is FIFO operation */ return sdio_readsb(sdiodev->func[fn], - ((u8 *)(pkt->data)), addr, len); + ((u8 *)(pkt_next->data)), addr, + req_sz); } - brcmf_err("skb chain is not supported yet.\n"); - return -EOPNOTSUPP; + host = sdiodev->func[fn]->card->host; + func_blk_sz = sdiodev->func[fn]->cur_blksize; + /* Blocks per command is limited by host count, host transfer + * size and the maximum for IO_RW_EXTENDED of 511 blocks. + */ + max_blks = min_t(unsigned int, host->max_blk_count, 511u); + max_req_sz = min_t(unsigned int, host->max_req_size, + max_blks * func_blk_sz); + max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); + max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen); + seg_sz = pktlist->qlen; + pkt_offset = 0; + pkt_next = pktlist->next; + + if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) + return -ENOMEM; + + while (seg_sz) { + req_sz = 0; + sg_cnt = 0; + memset(&mmc_req, 0, sizeof(struct mmc_request)); + memset(&mmc_cmd, 0, sizeof(struct mmc_command)); + memset(&mmc_dat, 0, sizeof(struct mmc_data)); + sgl = st.sgl; + /* prep sg table */ + while (pkt_next != (struct sk_buff *)pktlist) { + pkt_data = pkt_next->data + pkt_offset; + sg_data_sz = pkt_next->len - pkt_offset; + if (sg_data_sz > host->max_seg_size) + sg_data_sz = host->max_seg_size; + if (sg_data_sz > max_req_sz - req_sz) + sg_data_sz = max_req_sz - req_sz; + + sg_set_buf(sgl, pkt_data, sg_data_sz); + + sg_cnt++; + sgl = sg_next(sgl); + req_sz += sg_data_sz; + pkt_offset += sg_data_sz; + if (pkt_offset == pkt_next->len) { + pkt_offset = 0; + pkt_next = pkt_next->next; + } + + if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz) + break; + } + seg_sz -= sg_cnt; + + if (req_sz % func_blk_sz != 0) { + brcmf_err("sg request length %u is not %u aligned\n", + req_sz, func_blk_sz); + sg_free_table(&st); + return -ENOTBLK; + } + mmc_dat.sg = st.sgl; + mmc_dat.sg_len = sg_cnt; + mmc_dat.blksz = func_blk_sz; + mmc_dat.blocks = req_sz / func_blk_sz; + mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + mmc_cmd.opcode = SD_IO_RW_EXTENDED; + mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */ + mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */ + mmc_cmd.arg |= 1<<27; /* block mode */ + /* incrementing addr for function 1 */ + mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0; + mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */ + mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */ + mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + mmc_req.cmd = &mmc_cmd; + mmc_req.data = &mmc_dat; + if (fn == 1) + addr += req_sz; + + mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card); + mmc_wait_for_req(host, &mmc_req); + + ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error; + if (ret != 0) { + brcmf_err("CMD53 sg block %s failed %d\n", + write ? "write" : "read", ret); + ret = -EIO; + break; + } + } + + sg_free_table(&st); + + return ret; } static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, @@ -400,6 +506,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, { uint width; int err = 0; + struct sk_buff_head pkt_list; brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pkt->len); @@ -409,7 +516,10 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (err) goto done; - err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); + skb_queue_head_init(&pkt_list); + skb_queue_tail(&pkt_list, pkt); + err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list); + skb_dequeue_tail(&pkt_list); done: return err; @@ -431,8 +541,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, goto done; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, - pktq); + err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq); done: return err; @@ -467,6 +576,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint width; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; + struct sk_buff_head pkt_list; brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pkt->len); @@ -489,7 +599,10 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, if (width == 4) addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pkt); + skb_queue_head_init(&pkt_list); + skb_queue_tail(&pkt_list, pkt); + err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list); + skb_dequeue_tail(&pkt_list); done: return err; @@ -503,6 +616,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, struct sk_buff *pkt; u32 sdaddr; uint dsize; + struct sk_buff_head pkt_list; dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); pkt = dev_alloc_skb(dsize); @@ -511,6 +625,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, return -EIO; } pkt->priority = 0; + skb_queue_head_init(&pkt_list); /* Determine initial transfer parameters */ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; @@ -538,8 +653,10 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address, skb_put(pkt, dsize); if (write) memcpy(pkt->data, data, dsize); + skb_queue_tail(&pkt_list, pkt); bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, - sdaddr, pkt); + sdaddr, &pkt_list); + skb_dequeue_tail(&pkt_list); if (bcmerror) { brcmf_err("membytes transfer failed\n"); break; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 7a3c5bf33e03..289e386f01f6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -211,78 +211,6 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, return err_ret; } -/* precondition: host controller is claimed */ -static int -brcmf_sdioh_request_data(struct brcmf_sdio_dev *sdiodev, uint write, bool fifo, - uint func, uint addr, struct sk_buff *pkt, uint pktlen) -{ - int err_ret = 0; - - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pkt->data)), pktlen); - } else if (write) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pkt->data)), pktlen); - } else if (fifo) { - err_ret = sdio_readsb(sdiodev->func[func], - ((u8 *) (pkt->data)), addr, pktlen); - } else { - err_ret = sdio_memcpy_fromio(sdiodev->func[func], - ((u8 *) (pkt->data)), - addr, pktlen); - } - - return err_ret; -} - -/* - * This function takes a queue of packets. The packets on the queue - * are assumed to be properly aligned by the caller. - */ -int -brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, - uint write, uint func, uint addr, - struct sk_buff_head *pktq) -{ - bool fifo = (fix_inc == SDIOH_DATA_FIX); - u32 SGCount = 0; - int err_ret = 0; - - struct sk_buff *pkt; - - brcmf_dbg(SDIO, "Enter\n"); - - brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); - if (brcmf_pm_resume_error(sdiodev)) - return -EIO; - - skb_queue_walk(pktq, pkt) { - uint pkt_len = pkt->len; - pkt_len += 3; - pkt_len &= 0xFFFFFFFC; - - err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func, - addr, pkt, pkt_len); - if (err_ret) { - brcmf_err("%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - write ? "TX" : "RX", pkt, SGCount, addr, - pkt_len, err_ret); - } else { - brcmf_dbg(SDIO, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n", - write ? "TX" : "RX", pkt, SGCount, addr, - pkt_len); - } - if (!fifo) - addr += pkt_len; - - SGCount++; - } - - brcmf_dbg(SDIO, "Exit\n"); - return err_ret; -} - static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) { /* read 24 bits and return valid 17 bit addr */ @@ -431,7 +359,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, atomic_set(&sdiodev->suspend, false); init_waitqueue_head(&sdiodev->request_byte_wait); init_waitqueue_head(&sdiodev->request_word_wait); - init_waitqueue_head(&sdiodev->request_chain_wait); init_waitqueue_head(&sdiodev->request_buffer_wait); brcmf_dbg(SDIO, "F2 found, calling brcmf_sdio_probe...\n"); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index cb22f2f51453..264111968320 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -448,8 +448,6 @@ struct brcmf_sdio { uint rxblen; /* Allocated length of rxbuf */ u8 *rxctl; /* Aligned pointer into rxbuf */ u8 *rxctl_orig; /* pointer for freeing rxctl */ - u8 *databuf; /* Buffer for receiving big glom packet */ - u8 *dataptr; /* Aligned pointer into databuf */ uint rxlen; /* Length of valid data in buffer */ spinlock_t rxctl_lock; /* protection lock for ctrl frame resources */ @@ -473,8 +471,6 @@ struct brcmf_sdio { s32 idletime; /* Control for activity timeout */ s32 idlecount; /* Activity timeout counter */ s32 idleclock; /* How to set bus driver when idle */ - s32 sd_rxchain; - bool use_rxchain; /* If brcmf should use PKT chains */ bool rxflow_mode; /* Rx flow control mode */ bool rxflow; /* Is rx flow control on */ bool alp_only; /* Don't use HT clock (ALP only) */ @@ -1025,29 +1021,6 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; } -/* copy a buffer into a pkt buffer chain */ -static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_sdio *bus, uint len) -{ - uint n, ret = 0; - struct sk_buff *p; - u8 *buf; - - buf = bus->dataptr; - - /* copy the data */ - skb_queue_walk(&bus->glom, p) { - n = min_t(uint, p->len, len); - memcpy(p->data, buf, n); - buf += n; - len -= n; - ret += n; - if (!len) - break; - } - - return ret; -} - /* return total length of buffer chain */ static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus) { @@ -1201,8 +1174,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) int errcode; u8 doff, sfdoff; - bool usechain = bus->use_rxchain; - struct brcmf_sdio_read rd_new; /* If packets, issue read(s) and send up packet chain */ @@ -1237,7 +1208,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) if (sublen % BRCMF_SDALIGN) { brcmf_err("sublen %d not multiple of %d\n", sublen, BRCMF_SDALIGN); - usechain = false; } totlen += sublen; @@ -1304,27 +1274,9 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) * packet and and copy into the chain. */ sdio_claim_host(bus->sdiodev->func[1]); - if (usechain) { - errcode = brcmf_sdcard_recv_chain(bus->sdiodev, - bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, &bus->glom); - } else if (bus->dataptr) { - errcode = brcmf_sdcard_recv_buf(bus->sdiodev, - bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, - bus->dataptr, dlen); - sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen); - if (sublen != dlen) { - brcmf_err("FAILED TO COPY, dlen %d sublen %d\n", - dlen, sublen); - errcode = -1; - } - pnext = NULL; - } else { - brcmf_err("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", - dlen); - errcode = -1; - } + errcode = brcmf_sdcard_recv_chain(bus->sdiodev, + bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, &bus->glom); sdio_release_host(bus->sdiodev->func[1]); bus->sdcnt.f2rxdata++; @@ -3527,9 +3479,6 @@ static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) kfree(bus->rxbuf); bus->rxctl = bus->rxbuf = NULL; bus->rxlen = 0; - - kfree(bus->databuf); - bus->databuf = NULL; } static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) @@ -3542,29 +3491,10 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) ALIGNMENT) + BRCMF_SDALIGN; bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC); if (!(bus->rxbuf)) - goto fail; - } - - /* Allocate buffer to receive glomed packet */ - bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC); - if (!(bus->databuf)) { - /* release rxbuf which was already located as above */ - if (!bus->rxblen) - kfree(bus->rxbuf); - goto fail; + return false; } - /* Align the buffer */ - if ((unsigned long)bus->databuf % BRCMF_SDALIGN) - bus->dataptr = bus->databuf + (BRCMF_SDALIGN - - ((unsigned long)bus->databuf % BRCMF_SDALIGN)); - else - bus->dataptr = bus->databuf; - return true; - -fail: - return false; } static bool @@ -3703,10 +3633,6 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) bus->blocksize = bus->sdiodev->func[2]->cur_blksize; bus->roundup = min(max_roundup, bus->blocksize); - /* bus module does not support packet chaining */ - bus->use_rxchain = false; - bus->sd_rxchain = false; - /* SR state */ bus->sleeping = false; bus->sr_enabled = false; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 991c1501f7e1..793df66fe0bf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -170,7 +170,6 @@ struct brcmf_sdio_dev { atomic_t suspend; /* suspend flag */ wait_queue_head_t request_byte_wait; wait_queue_head_t request_word_wait; - wait_queue_head_t request_chain_wait; wait_queue_head_t request_buffer_wait; struct device *dev; struct brcmf_bus *bus_if; @@ -272,12 +271,6 @@ brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc, uint addr, u32 *word, uint nbyte); -/* read or write any buffer using cmd53 */ -extern int -brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, - uint write, uint func, uint addr, - struct sk_buff_head *pktq); - /* Watchdog timer interface for pm ops */ extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable); -- GitLab From ff7b0c2c2430b5b116108441cbd0680efbef68d1 Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Sun, 16 Jun 2013 18:43:04 +0200 Subject: [PATCH 1424/2900] kconfig/lxdialog: Use new mininimum resize definitions in conf_choice() This is a cleanup which uses the proper (new) definitions and does not change current behaviour. Signed-off-by: Sedat Dilek Reviewed-by: "Yann E. MORIN" Tested-by: "Yann E. MORIN" Signed-off-by: "Yann E. MORIN" --- Yann had some more ideas on improvements: "What would be nice is an improvement that scales the choice window to the number of entries in the choice. If there are a lot of choice entries, then the choice popup grows in height (but does not overflow the screen of course). So, instead of seeing only 6 entries, we'd see as much as possible in the current screen. Ditto for the width: the popup adapts to the longest prompt (but does not overflow the screen either, of course), so prompts are not truncated." NOTE: This patch requires [1]. [1] http://marc.info/?l=linux-kbuild&m=137128726917166&w=2 --- scripts/kconfig/mconf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 387dc8daf7b2..2396c5be31ad 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -825,7 +825,9 @@ static void conf_choice(struct menu *menu) dialog_clear(); res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), _(radiolist_instructions), - 15, 70, 6); + MENUBOX_HEIGTH_MIN, + MENUBOX_WIDTH_MIN, + CHECKLIST_HEIGTH_MIN); selected = item_activate_selected(); switch (res) { case 0: -- GitLab From 1376391621654cc369c5e8b60497f7c184f0ed47 Mon Sep 17 00:00:00 2001 From: Dirk Gouders Date: Wed, 8 May 2013 17:29:42 +0200 Subject: [PATCH 1425/2900] kconfig/lxdialog: handle newline characters in print_autowrap() When exiting menuconfig with unsaved changes, a dialog like the following is shown: Do you wish to save your new configuration ? to continue. The author of the dialog text specified a newline after the '?', and probably expected it to be processed, so let print_autowrap() handle newlines propperly. Also, reword that dialog's second phrase with a real sentence. Signed-off-by: Dirk Gouders Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" [yann.morin.1998@free.fr: very slightly tweak the commit message] Signed-off-by: Yann E. MORIN --- scripts/kconfig/lxdialog/util.c | 31 +++++++++++++++++-------------- scripts/kconfig/mconf.c | 4 ++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index 78fe4e9d8778..0fa567eb68c6 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c @@ -371,27 +371,19 @@ void print_title(WINDOW *dialog, const char *title, int width) /* * Print a string of text in a window, automatically wrap around to the * next line if the string is too long to fit on one line. Newline - * characters '\n' are replaced by spaces. We start on a new line + * characters '\n' are propperly processed. We start on a new line * if there is no room for at least 4 nonblanks following a double-space. */ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { int newl, cur_x, cur_y; - int i, prompt_len, room, wlen; - char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + int prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; strcpy(tempstr, prompt); prompt_len = strlen(tempstr); - /* - * Remove newlines - */ - for (i = 0; i < prompt_len; i++) { - if (tempstr[i] == '\n') - tempstr[i] = ' '; - } - if (prompt_len <= width - x * 2) { /* If prompt is short */ wmove(win, y, (width - prompt_len) / 2); waddstr(win, tempstr); @@ -401,7 +393,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) newl = 1; word = tempstr; while (word && *word) { - sp = strchr(word, ' '); + sp = strpbrk(word, "\n "); + if (sp && *sp == '\n') + newline_separator = sp; + if (sp) *sp++ = 0; @@ -413,7 +408,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) if (wlen > room || (newl && wlen < 4 && sp && wlen + 1 + strlen(sp) > room - && (!(sp2 = strchr(sp, ' ')) + && (!(sp2 = strpbrk(sp, "\n ")) || wlen + 1 + (sp2 - sp) > room))) { cur_y++; cur_x = x; @@ -421,7 +416,15 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) wmove(win, cur_y, cur_x); waddstr(win, word); getyx(win, cur_y, cur_x); - cur_x++; + + /* Move to the next line if the word separator was a newline */ + if (newline_separator) { + cur_y++; + cur_x = x; + newline_separator = 0; + } else + cur_x++; + if (sp && *sp == ' ') { cur_x++; /* double space */ while (*++sp == ' ') ; diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 2396c5be31ad..cb8cf4ae0ef3 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -958,8 +958,8 @@ static int handle_exit(void) dialog_clear(); if (conf_get_changed()) res = dialog_yesno(NULL, - _("Do you wish to save your new configuration ?\n" - " to continue."), + _("Do you wish to save your new configuration?\n" + "(Press to continue kernel configuration.)"), 6, 60); else res = -1; -- GitLab From 4f2de3e19983dafca264b672152b36e4962ca1c3 Mon Sep 17 00:00:00 2001 From: Dirk Gouders Date: Sun, 12 May 2013 12:30:49 +0200 Subject: [PATCH 1426/2900] mconf: use function calls instead of ncurses' variables LINES and COLS According to the documentation [1], LINES and COLS are initialized by initscr(); it does not say anything about the behavior when windows are resized. Do not rely on the current implementation of ncurses that updates these variables on resize, but use the propper function calls to get window dimensions. init_dialog() could make use of the variables, but for the sake of consistency we do not change it's current use of the macro getmaxyx(). [1] ncurses(3X) Signed-off-by: Dirk Gouders Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" Signed-off-by: Yann E. MORIN --- scripts/kconfig/lxdialog/checklist.c | 4 ++-- scripts/kconfig/lxdialog/inputbox.c | 4 ++-- scripts/kconfig/lxdialog/menubox.c | 4 ++-- scripts/kconfig/lxdialog/textbox.c | 4 ++-- scripts/kconfig/lxdialog/util.c | 13 +++++++++---- scripts/kconfig/lxdialog/yesno.c | 4 ++-- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c index 30340571190e..3b15c08ec1fa 100644 --- a/scripts/kconfig/lxdialog/checklist.c +++ b/scripts/kconfig/lxdialog/checklist.c @@ -140,8 +140,8 @@ int dialog_checklist(const char *title, const char *prompt, int height, max_choice = MIN(list_height, item_count()); /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index 7b01add415a8..447a582198c9 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c @@ -62,8 +62,8 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c index 00d28410adc9..92b89a6cb35a 100644 --- a/scripts/kconfig/lxdialog/menubox.c +++ b/scripts/kconfig/lxdialog/menubox.c @@ -203,8 +203,8 @@ int dialog_menu(const char *title, const char *prompt, max_choice = MIN(menu_height, item_count()); /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index 907cdcb397c1..1773319b95e7 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c @@ -98,8 +98,8 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, width = 0; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index 0fa567eb68c6..58a8289dd650 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c @@ -254,7 +254,12 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr) void dialog_clear(void) { - attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + int lines, columns; + + lines = getmaxy(stdscr); + columns = getmaxx(stdscr); + + attr_clear(stdscr, lines, columns, dlg.screen.atr); /* Display background title if it exists ... - SLH */ if (dlg.backtitle != NULL) { int i, len = 0, skip = 0; @@ -269,10 +274,10 @@ void dialog_clear(void) } wmove(stdscr, 1, 1); - if (len > COLS - 2) { + if (len > columns - 2) { const char *ellipsis = "[...] "; waddstr(stdscr, ellipsis); - skip = len - (COLS - 2 - strlen(ellipsis)); + skip = len - (columns - 2 - strlen(ellipsis)); } for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { @@ -298,7 +303,7 @@ void dialog_clear(void) skip--; } - for (i = len + 1; i < COLS - 1; i++) + for (i = len + 1; i < columns - 1; i++) waddch(stdscr, ACS_HLINE); } wnoutrefresh(stdscr); diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c index abb0c392e01b..676fb2f824a3 100644 --- a/scripts/kconfig/lxdialog/yesno.c +++ b/scripts/kconfig/lxdialog/yesno.c @@ -51,8 +51,8 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); -- GitLab From e0b42605e685a0833303e1d4dde277c99d9e17b5 Mon Sep 17 00:00:00 2001 From: Dirk Gouders Date: Mon, 13 May 2013 11:23:58 +0200 Subject: [PATCH 1427/2900] nconf: use function calls instead of ncurses' variables LINES and COLS According to the documentation [1], LINES and COLS are initialized by initscr(); it does not say anything about the behavior when windows are resized. Do not rely on the current implementation of ncurses that updates these variables on resize, but use the propper function calls or macros to get window dimensions. The use of the variables in main() was OK, but for the sake of consistency it was modified to use the macro getmaxyx(). [1] ncurses(3X) Signed-off-by: Dirk Gouders Reviewed-by: "Yann E. MORIN" [yann.morin.1998@free.fr: declare 'lines' and 'columns' on a single line] Signed-off-by: Yann E. MORIN --- scripts/kconfig/nconf.c | 21 ++++++++++++++------- scripts/kconfig/nconf.gui.c | 20 +++++++++++--------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index dbf31edd22b2..aac85d37b69b 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -365,15 +365,16 @@ static void print_function_line(void) int i; int offset = 1; const int skip = 1; + int lines = getmaxy(stdscr); for (i = 0; i < function_keys_num; i++) { (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); - mvwprintw(main_window, LINES-3, offset, + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].key_str); (void) wattrset(main_window, attributes[FUNCTION_TEXT]); offset += strlen(function_keys[i].key_str); - mvwprintw(main_window, LINES-3, + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].func); offset += strlen(function_keys[i].func) + skip; @@ -954,7 +955,7 @@ static void show_menu(const char *prompt, const char *instructions, clear(); (void) wattrset(main_window, attributes[NORMAL]); - print_in_middle(stdscr, 1, 0, COLS, + print_in_middle(stdscr, 1, 0, getmaxx(stdscr), menu_backtitle, attributes[MAIN_HEADING]); @@ -1455,14 +1456,18 @@ static void conf_save(void) void setup_windows(void) { + int lines, columns; + + getmaxyx(stdscr, lines, columns); + if (main_window != NULL) delwin(main_window); /* set up the menu and menu window */ - main_window = newwin(LINES-2, COLS-2, 2, 1); + main_window = newwin(lines-2, columns-2, 2, 1); keypad(main_window, TRUE); - mwin_max_lines = LINES-7; - mwin_max_cols = COLS-6; + mwin_max_lines = lines-7; + mwin_max_cols = columns-6; /* panels order is from bottom to top */ new_panel(main_window); @@ -1470,6 +1475,7 @@ void setup_windows(void) int main(int ac, char **av) { + int lines, columns; char *mode; setlocale(LC_ALL, ""); @@ -1495,7 +1501,8 @@ int main(int ac, char **av) keypad(stdscr, TRUE); curs_set(0); - if (COLS < 75 || LINES < 20) { + getmaxyx(stdscr, lines, columns); + if (columns < 75 || lines < 20) { endwin(); printf("Your terminal should have at " "least 20 lines and 75 columns\n"); diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c index 9f8c44ecc703..8275f0e55106 100644 --- a/scripts/kconfig/nconf.gui.c +++ b/scripts/kconfig/nconf.gui.c @@ -276,8 +276,8 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) total_width = max(msg_width, btns_width); /* place dialog in middle of screen */ - y = (LINES-(msg_lines+4))/2; - x = (COLS-(total_width+4))/2; + y = (getmaxy(stdscr)-(msg_lines+4))/2; + x = (getmaxx(stdscr)-(total_width+4))/2; /* create the windows */ @@ -387,8 +387,8 @@ int dialog_inputbox(WINDOW *main_window, prompt_width = max(prompt_width, strlen(title)); /* place dialog in middle of screen */ - y = (LINES-(prompt_lines+4))/2; - x = (COLS-(prompt_width+4))/2; + y = (getmaxy(stdscr)-(prompt_lines+4))/2; + x = (getmaxx(stdscr)-(prompt_width+4))/2; strncpy(result, init, *result_len); @@ -545,7 +545,7 @@ void show_scroll_win(WINDOW *main_window, { int res; int total_lines = get_line_no(text); - int x, y; + int x, y, lines, columns; int start_x = 0, start_y = 0; int text_lines = 0, text_cols = 0; int total_cols = 0; @@ -556,6 +556,8 @@ void show_scroll_win(WINDOW *main_window, WINDOW *pad; PANEL *panel; + getmaxyx(stdscr, lines, columns); + /* find the widest line of msg: */ total_lines = get_line_no(text); for (i = 0; i < total_lines; i++) { @@ -569,14 +571,14 @@ void show_scroll_win(WINDOW *main_window, (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); fill_window(pad, text); - win_lines = min(total_lines+4, LINES-2); - win_cols = min(total_cols+2, COLS-2); + win_lines = min(total_lines+4, lines-2); + win_cols = min(total_cols+2, columns-2); text_lines = max(win_lines-4, 0); text_cols = max(win_cols-2, 0); /* place window in middle of screen */ - y = (LINES-win_lines)/2; - x = (COLS-win_cols)/2; + y = (lines-win_lines)/2; + x = (columns-win_cols)/2; win = newwin(win_lines, win_cols, y, x); keypad(win, TRUE); -- GitLab From 1278ebdbc3167883f32095491990fbdc7cdf8b5e Mon Sep 17 00:00:00 2001 From: Dirk Gouders Date: Sun, 19 May 2013 21:49:34 +0200 Subject: [PATCH 1428/2900] mconf/nconf: mark empty menus/menuconfigs different from non-empty ones Submenus are sometimes empty and it would be nice if there is something that notifies us that we should not expect any content _before_ we enter a submenu. A new function menu_is_empty() was introduced and empty menus and menuconfigs are now marked by "----" as opposed to non-empty ones that are marked by "--->". This scheme was suggested by "Yann E. MORIN" . Signed-off-by: Dirk Gouders Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/lkc_proto.h | 1 + scripts/kconfig/mconf.c | 11 ++++++----- scripts/kconfig/menu.c | 16 ++++++++++++++++ scripts/kconfig/nconf.c | 16 ++++++++-------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index ef1a7381f956..ecdb9659b67d 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -14,6 +14,7 @@ P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); /* menu.c */ P(rootmenu,struct menu,); +P(menu_is_empty, bool, (struct menu *menu)); P(menu_is_visible, bool, (struct menu *menu)); P(menu_has_prompt, bool, (struct menu *menu)); P(menu_get_prompt,const char *,(struct menu *menu)); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index cb8cf4ae0ef3..6ee4aaea9d87 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -48,7 +48,7 @@ static const char mconf_readme[] = N_( "----------\n" "o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" " you wish to change or submenu wish to select and press .\n" -" Submenus are designated by \"--->\".\n" +" Submenus are designated by \"--->\", empty ones by \"----\".\n" "\n" " Shortcut: Press the option's highlighted letter (hotkey).\n" " Pressing a hotkey more than once will sequence\n" @@ -176,7 +176,7 @@ static const char mconf_readme[] = N_( "\n"), menu_instructions[] = N_( "Arrow keys navigate the menu. " - " selects submenus --->. " + " selects submenus ---> (or empty submenus ----). " "Highlighted letters are hotkeys. " "Pressing includes, excludes, modularizes features. " "Press to exit, for Help, for Search. " @@ -498,8 +498,9 @@ static void build_conf(struct menu *menu) menu->data ? "-->" : "++>", indent + 1, ' ', prompt); } else - item_make(" %*c%s --->", indent + 1, ' ', prompt); - + item_make(" %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); item_set_tag('m'); item_set_data(menu); if (single_menu_mode && menu->data) @@ -630,7 +631,7 @@ static void build_conf(struct menu *menu) (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt->type == P_MENU) { - item_add_str(" --->"); + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; } } diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index b5c7d90df9df..6d11c8f63eb0 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -430,6 +430,22 @@ bool menu_has_prompt(struct menu *menu) return true; } +/* + * Determine if a menu is empty. + * A menu is considered empty if it contains no or only + * invisible entries. + */ +bool menu_is_empty(struct menu *menu) +{ + struct menu *child; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) + return(false); + } + return(true); +} + bool menu_is_visible(struct menu *menu) { struct menu *child; diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index aac85d37b69b..0183153c2095 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -45,8 +45,8 @@ static const char nconf_global_help[] = N_( " to remove it. You may press the key to cycle through the\n" "available options.\n" "\n" -"A trailing \"--->\" designates a submenu.\n" -"\n" +"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n" +"empty submenu.\n" "\n" "Menu navigation keys\n" "----------------------------------------------------------------------\n" @@ -131,7 +131,7 @@ static const char nconf_global_help[] = N_( "\n"), menu_no_f_instructions[] = N_( "Legend: [*] built-in [ ] excluded module < > module capable.\n" -"Submenus are designated by a trailing \"--->\".\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" "\n" "Use the following keys to navigate the menus:\n" "Move up or down with and .\n" @@ -148,7 +148,7 @@ menu_no_f_instructions[] = N_( "For help related to the current menu entry press or .\n"), menu_instructions[] = N_( "Legend: [*] built-in [ ] excluded module < > module capable.\n" -"Submenus are designated by a trailing \"--->\".\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" "\n" "Use the following keys to navigate the menus:\n" "Move up or down with or .\n" @@ -760,9 +760,9 @@ static void build_conf(struct menu *menu) indent + 1, ' ', prompt); } else item_make(menu, 'm', - " %*c%s --->", - indent + 1, - ' ', prompt); + " %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); if (single_menu_mode && menu->data) goto conf_childs; @@ -904,7 +904,7 @@ static void build_conf(struct menu *menu) (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt && menu->prompt->type == P_MENU) { - item_add_str(" --->"); + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; } } -- GitLab From 7387778510b7deaff866277877c5550c3a14f1fb Mon Sep 17 00:00:00 2001 From: Clement Chauplannaz Date: Sun, 12 May 2013 21:08:51 +0200 Subject: [PATCH 1429/2900] scripts/config: replace hard-coded script name by a dynamic value The script `config' prints its name in usage() function. It is currently hard-coded to value `config'. However, the script may be reused under a different name in contexts other than the Linux Kernel. Replace the hard-coded value `config' by the name of the script at runtime. Signed-off-by: Clement Chauplannaz Acked-by: Andi Kleen Signed-off-by: Yann E. MORIN --- scripts/config | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/config b/scripts/config index bb4d3deb6d1c..6b3272ef6ec7 100755 --- a/scripts/config +++ b/scripts/config @@ -1,6 +1,8 @@ #!/bin/bash # Manipulate options in a .config file from the command line +myname=${0##*/} + # If no prefix forced, use the default CONFIG_ CONFIG_="${CONFIG_-CONFIG_}" @@ -8,7 +10,7 @@ usage() { cat >&2 < Date: Sun, 28 Apr 2013 17:33:15 +0200 Subject: [PATCH 1430/2900] kconfig/conf: fix randconfig setting multiple symbols in a choice Currently, randconfig may set more than one symbol in a given choice. Given this config file: config A bool "A" if A choice bool "B/C/D" config B bool "B" config C bool "C" config D bool "D" endchoice endif # A Then randconfig generates such .config files (case where A is not set is not shown below for brevity), and where only the right-most .config is valid: CONFIG_A=y CONFIG_A=y CONFIG_A=y CONFIG_B=y CONFIG_B=y CONFIG_B=y CONFIG_C=y # CONFIG_C is not set # CONFIG_C is not set # CONFIG_D is not set CONFIG_D=y # CONFIG_D is not set That is, in a randomised choice, the first symbol is always selected, and at most one other symbol may be selected. This is due to symbol randomised in a choice not being properly flagged as having a value. Fix that by flagging those symbols adequately: have a user-defined value, and be not valid (to force recalculation of the symbol). Note: if the choice is not conditional, then the randomisation is properly done. Reported-by: Matthieu CASTET Signed-off-by: Matthieu CASTET [yann.morin.1998@free.fr: independently re-done the same patch as Matthieu, as pointed out by Sedat] Cc: Arnaud Lacombe Cc: Sedat Dilek Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/confdata.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 35e0f164ef81..d36bc1f1d563 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -1077,6 +1077,9 @@ static void randomize_choice_values(struct symbol *csym) else { sym->def[S_DEF_USER].tri = no; } + sym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + sym->flags &= ~SYMBOL_VALID; } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ -- GitLab From e85ac12443da72d79dbf7c55c12e4b16b8923d87 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Mon, 20 May 2013 23:17:34 +0200 Subject: [PATCH 1431/2900] kconfig/conf: accept a base-16 seed for randconfig Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/conf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index bde5b95c8c19..94521c7712c3 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -527,7 +527,7 @@ int main(int ac, char **av) seed_env = getenv("KCONFIG_SEED"); if( seed_env && *seed_env ) { char *endp; - int tmp = (int)strtol(seed_env, &endp, 10); + int tmp = (int)strtol(seed_env, &endp, 0); if (*endp == '\0') { seed = tmp; } -- GitLab From a5f6d795f5941e97e757b643a6482968a66c6150 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Mon, 20 May 2013 23:09:03 +0200 Subject: [PATCH 1432/2900] kconfig/conf: print the seed used to initialise the RNG for randconfig ... so the user has a chance to reproduce a test-case. Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/conf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 94521c7712c3..38616c14c071 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -532,6 +532,7 @@ int main(int ac, char **av) seed = tmp; } } + fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); srand(seed); break; } -- GitLab From 646093a29f85630d8efe2aa38fa585d2c3ea2e46 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 19 Jun 2013 10:32:32 +0800 Subject: [PATCH 1433/2900] bcm63xx_enet: fix return value check in bcm_enet_shared_probe() In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Introduce by commit 0ae99b5fede6f3a8d252d50bb4aba29544295219 (bcm63xx_enet: split DMA channel register accesses) Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index 8f1ac023bb03..b1bcd4ba4744 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -2862,8 +2862,8 @@ static int bcm_enet_shared_probe(struct platform_device *pdev) for (i = 0; i < 3; i++) { res = platform_get_resource(pdev, IORESOURCE_MEM, i); p[i] = devm_ioremap_resource(&pdev->dev, res); - if (!p[i]) - return -ENOMEM; + if (IS_ERR(p[i])) + return PTR_ERR(p[i]); } memcpy(bcm_enet_shared_base, p, sizeof(bcm_enet_shared_base)); -- GitLab From 637d6895f8f5ecc041ca6f521f544bb3d5699416 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:17:56 +0200 Subject: [PATCH 1434/2900] mfd: twl4030-power: Split from twl-core into a dedicated module For now, the call to twl4030-power is hard-wired inside twl-core. To ease the future transition to DT, make twl4030-power as a separate module, like what is already done for twl4030-audio and others. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- drivers/mfd/twl-core.c | 12 +++++++---- drivers/mfd/twl4030-power.c | 43 ++++++++++++++++++++++++++++--------- include/linux/i2c/twl.h | 1 - 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 8d9bc10c5312..dbd52b373b27 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -1023,6 +1023,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); } + if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) { + child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power", + pdata->power, sizeof(*pdata->power), false, + 0, 0); + if (IS_ERR(child)) + return PTR_ERR(child); + } + return 0; } @@ -1234,10 +1242,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) WARN(status < 0, "Error: reading twl_idcode register value\n"); } - /* load power event scripts */ - if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata && pdata->power) - twl4030_power_init(pdata->power); - /* Maybe init the T2 Interrupt subsystem */ if (client->irq) { if (twl_class_is_4030()) { diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index dd362c1078e1..94bcbeed1d62 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -507,8 +507,9 @@ void twl4030_power_off(void) pr_err("TWL4030 Unable to power off\n"); } -void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) +int twl4030_power_probe(struct platform_device *pdev) { + struct twl4030_power_data *pdata = pdev->dev.platform_data; int err = 0; int i; struct twl4030_resconfig *resconfig; @@ -524,14 +525,14 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) if (err) goto unlock; - for (i = 0; i < twl4030_scripts->num; i++) { - err = load_twl4030_script(twl4030_scripts->scripts[i], address); + for (i = 0; i < pdata->num; i++) { + err = load_twl4030_script(pdata->scripts[i], address); if (err) goto load; - address += twl4030_scripts->scripts[i]->size; + address += pdata->scripts[i]->size; } - resconfig = twl4030_scripts->resource_config; + resconfig = pdata->resource_config; if (resconfig) { while (resconfig->resource) { err = twl4030_configure_resource(resconfig); @@ -543,7 +544,7 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) } /* Board has to be wired properly to use this feature */ - if (twl4030_scripts->use_poweroff && !pm_power_off) { + if (pdata->use_poweroff && !pm_power_off) { /* Default for SEQ_OFFSYNC is set, lets ensure this */ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, TWL4030_PM_MASTER_CFG_P123_TRANSITION); @@ -568,18 +569,40 @@ void twl4030_power_init(struct twl4030_power_data *twl4030_scripts) TWL4030_PM_MASTER_PROTECT_KEY); if (err) pr_err("TWL4030 Unable to relock registers\n"); - return; + return err; unlock: if (err) pr_err("TWL4030 Unable to unlock registers\n"); - return; + return err; load: if (err) pr_err("TWL4030 failed to load scripts\n"); - return; + return err; resource: if (err) pr_err("TWL4030 failed to configure resource\n"); - return; + return err; +} + +static int twl4030_power_remove(struct platform_device *pdev) +{ + return 0; } + +static struct platform_driver twl4030_power_driver = { + .driver = { + .name = "twl4030_power", + .owner = THIS_MODULE, + }, + .probe = twl4030_power_probe, + .remove = twl4030_power_remove, +}; + +module_platform_driver(twl4030_power_driver); + +MODULE_AUTHOR("Nokia Corporation"); +MODULE_AUTHOR("Texas Instruments, Inc."); +MODULE_DESCRIPTION("Power management for TWL4030"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:twl4030_power"); diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 488debbef895..2167c0d00abf 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -658,7 +658,6 @@ struct twl4030_power_data { bool use_poweroff; /* Board is wired for TWL poweroff */ }; -extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts); extern int twl4030_remove_script(u8 flags); extern void twl4030_power_off(void); -- GitLab From f58cb407632ecf0ec01627b8a61852d5585b573d Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:17:57 +0200 Subject: [PATCH 1435/2900] mfd: twl4030-power: Simplify probing of power scripts and resources Increase lisibility when probing power scripts and resources by creating dedicated functions. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-power.c | 60 ++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 94bcbeed1d62..d36622d0f98a 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -492,6 +492,39 @@ int twl4030_remove_script(u8 flags) return err; } +int twl4030_power_configure_scripts(struct twl4030_power_data *pdata) +{ + int err; + int i; + u8 address = twl4030_start_script_address; + + for (i = 0; i < pdata->num; i++) { + err = load_twl4030_script(pdata->scripts[i], address); + if (err) + return err; + address += pdata->scripts[i]->size; + } + + return 0; +} + +int twl4030_power_configure_resources(struct twl4030_power_data *pdata) +{ + struct twl4030_resconfig *resconfig = pdata->resource_config; + int err; + + if (resconfig) { + while (resconfig->resource) { + err = twl4030_configure_resource(resconfig); + if (err) + return err; + resconfig++; + } + } + + return 0; +} + /* * In master mode, start the power off sequence. * After a successful execution, TWL shuts down the power to the SoC @@ -511,9 +544,7 @@ int twl4030_power_probe(struct platform_device *pdev) { struct twl4030_power_data *pdata = pdev->dev.platform_data; int err = 0; - int i; - struct twl4030_resconfig *resconfig; - u8 val, address = twl4030_start_script_address; + u8 val; err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, TWL4030_PM_MASTER_PROTECT_KEY); @@ -525,23 +556,12 @@ int twl4030_power_probe(struct platform_device *pdev) if (err) goto unlock; - for (i = 0; i < pdata->num; i++) { - err = load_twl4030_script(pdata->scripts[i], address); - if (err) - goto load; - address += pdata->scripts[i]->size; - } - - resconfig = pdata->resource_config; - if (resconfig) { - while (resconfig->resource) { - err = twl4030_configure_resource(resconfig); - if (err) - goto resource; - resconfig++; - - } - } + err = twl4030_power_configure_scripts(pdata); + if (err) + goto load; + err = twl4030_power_configure_resources(pdata); + if (err) + goto resource; /* Board has to be wired properly to use this feature */ if (pdata->use_poweroff && !pm_power_off) { -- GitLab From b0fc1da4d0359d3cce8f12e0f014aed0704ae202 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:17:58 +0200 Subject: [PATCH 1436/2900] mfd: twl4030-power: Start transition to DT Support for loading twl4030-power module via devicetree. For now, when booting with a DT, only the poweroff callback feature is supported through the ti,use_poweroff property. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- .../devicetree/bindings/mfd/twl4030-power.txt | 28 ++++++++++++ drivers/mfd/twl4030-power.c | 45 ++++++++++++++++--- 2 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/twl4030-power.txt diff --git a/Documentation/devicetree/bindings/mfd/twl4030-power.txt b/Documentation/devicetree/bindings/mfd/twl4030-power.txt new file mode 100644 index 000000000000..8e15ec35ac99 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/twl4030-power.txt @@ -0,0 +1,28 @@ +Texas Instruments TWL family (twl4030) reset and power management module + +The power management module inside the TWL family provides several facilities +to control the power resources, including power scripts. For now, the +binding only supports the complete shutdown of the system after poweroff. + +Required properties: +- compatible : must be "ti,twl4030-power" + +Optional properties: +- ti,use_poweroff: With this flag, the chip will initiates an ACTIVE-to-OFF or + SLEEP-to-OFF transition when the system poweroffs. + +Example: +&i2c1 { + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + interrupt-parent = <&intc>; + + twl_power: power { + compatible = "ti,twl4030-power"; + ti,use_poweroff; + }; + }; +}; diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index d36622d0f98a..5b2848280f4b 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -540,12 +541,30 @@ void twl4030_power_off(void) pr_err("TWL4030 Unable to power off\n"); } +static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata, + struct device_node *node) +{ + if (pdata && pdata->use_poweroff) + return true; + + if (of_property_read_bool(node, "ti,use_poweroff")) + return true; + + return false; +} + int twl4030_power_probe(struct platform_device *pdev) { struct twl4030_power_data *pdata = pdev->dev.platform_data; + struct device_node *node = pdev->dev.of_node; int err = 0; u8 val; + if (!pdata && !node) { + dev_err(&pdev->dev, "Platform data is missing\n"); + return -EINVAL; + } + err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, TWL4030_PM_MASTER_PROTECT_KEY); if (err) @@ -556,15 +575,18 @@ int twl4030_power_probe(struct platform_device *pdev) if (err) goto unlock; - err = twl4030_power_configure_scripts(pdata); - if (err) - goto load; - err = twl4030_power_configure_resources(pdata); - if (err) - goto resource; + if (pdata) { + /* TODO: convert to device tree */ + err = twl4030_power_configure_scripts(pdata); + if (err) + goto load; + err = twl4030_power_configure_resources(pdata); + if (err) + goto resource; + } /* Board has to be wired properly to use this feature */ - if (pdata->use_poweroff && !pm_power_off) { + if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) { /* Default for SEQ_OFFSYNC is set, lets ensure this */ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, TWL4030_PM_MASTER_CFG_P123_TRANSITION); @@ -610,10 +632,19 @@ static int twl4030_power_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id twl4030_power_of_match[] = { + {.compatible = "ti,twl4030-power", }, + { }, +}; +MODULE_DEVICE_TABLE(of, twl4030_power_of_match); +#endif + static struct platform_driver twl4030_power_driver = { .driver = { .name = "twl4030_power", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_power_of_match), }, .probe = twl4030_power_probe, .remove = twl4030_power_remove, -- GitLab From e77a4c2fdd549efbd4897522d83005f9a5f81c87 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:17:59 +0200 Subject: [PATCH 1437/2900] mfd: twl4030-power: Simplify error path Remove unnecessary goto statements, causing duplicated if conditions. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-power.c | 38 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 5b2848280f4b..d027581e7eb2 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -567,22 +567,27 @@ int twl4030_power_probe(struct platform_device *pdev) err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) - goto unlock; - - err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, + err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, + TWL4030_PM_MASTER_KEY_CFG2, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) - goto unlock; + + if (err) { + pr_err("TWL4030 Unable to unlock registers\n"); + return err; + } if (pdata) { /* TODO: convert to device tree */ err = twl4030_power_configure_scripts(pdata); - if (err) - goto load; + if (err) { + pr_err("TWL4030 failed to load scripts\n"); + return err; + } err = twl4030_power_configure_resources(pdata); - if (err) - goto resource; + if (err) { + pr_err("TWL4030 failed to configure resource\n"); + return err; + } } /* Board has to be wired properly to use this feature */ @@ -612,19 +617,6 @@ int twl4030_power_probe(struct platform_device *pdev) if (err) pr_err("TWL4030 Unable to relock registers\n"); return err; - -unlock: - if (err) - pr_err("TWL4030 Unable to unlock registers\n"); - return err; -load: - if (err) - pr_err("TWL4030 failed to load scripts\n"); - return err; -resource: - if (err) - pr_err("TWL4030 failed to configure resource\n"); - return err; } static int twl4030_power_remove(struct platform_device *pdev) -- GitLab From cb3cabd6788dd8c2e87dc7262a45a24e063681a3 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Tue, 18 Jun 2013 15:18:00 +0200 Subject: [PATCH 1438/2900] mfd: twl4030-power: Fix relocking on error If an error occurs when loading power scripts or resources, the registers are not correctly relocked. Fix it. Signed-off-by: Florian Vaussard Signed-off-by: Samuel Ortiz --- drivers/mfd/twl4030-power.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index d027581e7eb2..a5fd3c738211 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -558,6 +558,7 @@ int twl4030_power_probe(struct platform_device *pdev) struct twl4030_power_data *pdata = pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; int err = 0; + int err2 = 0; u8 val; if (!pdata && !node) { @@ -581,12 +582,12 @@ int twl4030_power_probe(struct platform_device *pdev) err = twl4030_power_configure_scripts(pdata); if (err) { pr_err("TWL4030 failed to load scripts\n"); - return err; + goto relock; } err = twl4030_power_configure_resources(pdata); if (err) { pr_err("TWL4030 failed to configure resource\n"); - return err; + goto relock; } } @@ -612,10 +613,13 @@ int twl4030_power_probe(struct platform_device *pdev) } relock: - err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, + err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, TWL4030_PM_MASTER_PROTECT_KEY); - if (err) + if (err2) { pr_err("TWL4030 Unable to relock registers\n"); + return err2; + } + return err; } -- GitLab From c8eaed458e2cfbd906dbbe1af49aa028f59cc132 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Jun 2013 15:35:40 +0530 Subject: [PATCH 1439/2900] mfd: davinci_voicecodec: Convert to use devm_* APIs devm_* APIs are device managed and make code simpler. Signed-off-by: Sachin Kamat Signed-off-by: Lee Jones --- drivers/mfd/davinci_voicecodec.c | 48 ++++++-------------------- include/linux/mfd/davinci_voicecodec.h | 2 -- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c index b6e297363946..fb64398506e9 100644 --- a/drivers/mfd/davinci_voicecodec.c +++ b/drivers/mfd/davinci_voicecodec.c @@ -46,7 +46,7 @@ void davinci_vc_write(struct davinci_vc *davinci_vc, static int __init davinci_vc_probe(struct platform_device *pdev) { struct davinci_vc *davinci_vc; - struct resource *res, *mem; + struct resource *res; struct mfd_cell *cell = NULL; int ret; @@ -58,7 +58,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) return -ENOMEM; } - davinci_vc->clk = clk_get(&pdev->dev, NULL); + davinci_vc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(davinci_vc->clk)) { dev_dbg(&pdev->dev, "could not get the clock for voice codec\n"); @@ -67,35 +67,18 @@ static int __init davinci_vc_probe(struct platform_device *pdev) clk_enable(davinci_vc->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mem resource\n"); - ret = -ENODEV; - goto fail2; - } - - davinci_vc->pbase = res->start; - davinci_vc->base_size = resource_size(res); - mem = request_mem_region(davinci_vc->pbase, davinci_vc->base_size, - pdev->name); - if (!mem) { - dev_err(&pdev->dev, "VCIF region already claimed\n"); - ret = -EBUSY; - goto fail2; - } - - davinci_vc->base = ioremap(davinci_vc->pbase, davinci_vc->base_size); - if (!davinci_vc->base) { - dev_err(&pdev->dev, "can't ioremap mem resource.\n"); - ret = -ENOMEM; - goto fail3; + davinci_vc->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(davinci_vc->base)) { + ret = PTR_ERR(davinci_vc->base); + goto fail; } res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!res) { dev_err(&pdev->dev, "no DMA resource\n"); ret = -ENXIO; - goto fail4; + goto fail; } davinci_vc->davinci_vcif.dma_tx_channel = res->start; @@ -106,7 +89,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev) if (!res) { dev_err(&pdev->dev, "no DMA resource\n"); ret = -ENXIO; - goto fail4; + goto fail; } davinci_vc->davinci_vcif.dma_rx_channel = res->start; @@ -132,19 +115,13 @@ static int __init davinci_vc_probe(struct platform_device *pdev) DAVINCI_VC_CELLS, NULL, 0, NULL); if (ret != 0) { dev_err(&pdev->dev, "fail to register client devices\n"); - goto fail4; + goto fail; } return 0; -fail4: - iounmap(davinci_vc->base); -fail3: - release_mem_region(davinci_vc->pbase, davinci_vc->base_size); -fail2: +fail: clk_disable(davinci_vc->clk); - clk_put(davinci_vc->clk); - davinci_vc->clk = NULL; return ret; } @@ -155,12 +132,7 @@ static int davinci_vc_remove(struct platform_device *pdev) mfd_remove_devices(&pdev->dev); - iounmap(davinci_vc->base); - release_mem_region(davinci_vc->pbase, davinci_vc->base_size); - clk_disable(davinci_vc->clk); - clk_put(davinci_vc->clk); - davinci_vc->clk = NULL; return 0; } diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 0ab61320ffa8..94c53d4819c7 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -112,8 +112,6 @@ struct davinci_vc { /* Memory resources */ void __iomem *base; - resource_size_t pbase; - size_t base_size; /* MFD cells */ struct mfd_cell cells[DAVINCI_VC_CELLS]; -- GitLab From 3f9850f26241f1d4f9ed49eaa70e043a3bb24a7c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 19 Jun 2013 10:47:06 +0800 Subject: [PATCH 1440/2900] mfd: htc-egpio: Use devm_ioremap_nocache() instead of ioremap_nocache() Replace probe-time ioremap_nocache() call with devm_ioremap_nocache() to avoid iounmap() missing and get rid of the corresponding iounmap() call on remove. Signed-off-by: Wei Yongjun Signed-off-by: Lee Jones --- drivers/mfd/htc-egpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index f2e0ad4b332e..26aca545084b 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c @@ -286,7 +286,8 @@ static int __init egpio_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) goto fail; - ei->base_addr = ioremap_nocache(res->start, resource_size(res)); + ei->base_addr = devm_ioremap_nocache(&pdev->dev, res->start, + resource_size(res)); if (!ei->base_addr) goto fail; pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr); @@ -380,7 +381,6 @@ static int __exit egpio_remove(struct platform_device *pdev) irq_set_chained_handler(ei->chained_irq, NULL); device_init_wakeup(&pdev->dev, 0); } - iounmap(ei->base_addr); return 0; } -- GitLab From 8eb12b98163deaafae82e7dde044709919e4fdfa Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Tue, 11 Jun 2013 11:56:02 +0100 Subject: [PATCH 1441/2900] mfd: vexpress: Make the driver optional for arm and arm64 The driver can be used on either arm or arm64 platforms, but the latter doesn't have any platform-specific configuration options, so it must be possible to manually enable the driver. As the gpiolib is optional for arm64 arch, the gpio/led code must be compiled conditionally. Signed-off-by: Pawel Moll Acked-by: Catalin Marinas Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 3 ++- drivers/mfd/vexpress-sysreg.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 29f7363f6bc4..3e3be603cf82 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1151,7 +1151,8 @@ config MCP_UCB1200_TS endmenu config VEXPRESS_CONFIG - bool + bool "ARM Versatile Express platform infrastructure" + depends on ARM || ARM64 help Platform configuration infrastructure for the ARM Ltd. Versatile Express. diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index 96a020b1dcd1..981bef4b7ebc 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c @@ -351,6 +351,8 @@ void __init vexpress_sysreg_of_early_init(void) } +#ifdef CONFIG_GPIOLIB + #define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \ [VEXPRESS_GPIO_##_name] = { \ .reg = _reg, \ @@ -445,6 +447,8 @@ struct gpio_led_platform_data vexpress_sysreg_leds_pdata = { .leds = vexpress_sysreg_leds, }; +#endif + static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -480,6 +484,9 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) setup_timer(&vexpress_sysreg_config_timer, vexpress_sysreg_config_complete, 0); + vexpress_sysreg_dev = &pdev->dev; + +#ifdef CONFIG_GPIOLIB vexpress_sysreg_gpio_chip.dev = &pdev->dev; err = gpiochip_add(&vexpress_sysreg_gpio_chip); if (err) { @@ -490,11 +497,10 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) return err; } - vexpress_sysreg_dev = &pdev->dev; - platform_device_register_data(vexpress_sysreg_dev, "leds-gpio", PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata, sizeof(vexpress_sysreg_leds_pdata)); +#endif device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); -- GitLab From 7bb151b23b40c32c85f5116827a87fc23f0be4c4 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 11 Jun 2013 06:50:49 -0300 Subject: [PATCH 1442/2900] [media] davinci_vpfe: Clean up media entity after unregistering subdev media_entity_cleanup() frees the links array which will be accessed by media_entity_remove_links() called by v4l2_device_unregister_subdev(). Signed-off-by: Sakari Ailus Reviewed-by: Sylwester Nawrocki Acked-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/dm365_ipipe.c | 4 ++-- drivers/staging/media/davinci_vpfe/dm365_ipipeif.c | 4 ++-- drivers/staging/media/davinci_vpfe/dm365_isif.c | 4 ++-- drivers/staging/media/davinci_vpfe/dm365_resizer.c | 14 +++++++------- drivers/staging/media/davinci_vpfe/vpfe_video.c | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 05673ed45ce4..766a071b0a22 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1751,10 +1751,10 @@ static const struct media_entity_operations ipipe_media_ops = { */ void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe) { - /* cleanup entity */ - media_entity_cleanup(&vpfe_ipipe->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&vpfe_ipipe->subdev); + /* cleanup entity */ + media_entity_cleanup(&vpfe_ipipe->subdev.entity); } /* diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index b2f4ef84f3db..59540cd4bb98 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c @@ -947,10 +947,10 @@ void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif) /* unregister video device */ vpfe_video_unregister(&ipipeif->video_in); - /* cleanup entity */ - media_entity_cleanup(&ipipeif->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&ipipeif->subdev); + /* cleanup entity */ + media_entity_cleanup(&ipipeif->subdev.entity); } int diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 5829360f74c9..ff48fce94fcb 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -1750,10 +1750,10 @@ static const struct media_entity_operations isif_media_ops = { void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif) { vpfe_video_unregister(&isif->video_out); - /* cleanup entity */ - media_entity_cleanup(&isif->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&isif->subdev); + /* cleanup entity */ + media_entity_cleanup(&isif->subdev.entity); } static void isif_restore_defaults(struct vpfe_isif_device *isif) diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 126f84c4cb64..8e13bd494c98 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -1777,14 +1777,14 @@ void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz) vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out); vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out); - /* cleanup entity */ - media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev); v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev); v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev); + /* cleanup entity */ + media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); + media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); + media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); } /* @@ -1865,12 +1865,12 @@ int vpfe_resizer_register_entities(struct vpfe_resizer_device *resizer, vpfe_video_unregister(&resizer->resizer_b.video_out); out_video_out2_register: vpfe_video_unregister(&resizer->resizer_a.video_out); - media_entity_cleanup(&resizer->crop_resizer.subdev.entity); - media_entity_cleanup(&resizer->resizer_a.subdev.entity); - media_entity_cleanup(&resizer->resizer_b.subdev.entity); v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev); v4l2_device_unregister_subdev(&resizer->resizer_a.subdev); v4l2_device_unregister_subdev(&resizer->resizer_b.subdev); + media_entity_cleanup(&resizer->crop_resizer.subdev.entity); + media_entity_cleanup(&resizer->resizer_a.subdev.entity); + media_entity_cleanup(&resizer->resizer_b.subdev.entity); return ret; } diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index cb5410b390ef..24d98a6866bb 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -1614,7 +1614,7 @@ int vpfe_video_register(struct vpfe_video_device *video, void vpfe_video_unregister(struct vpfe_video_device *video) { if (video_is_registered(&video->video_dev)) { - media_entity_cleanup(&video->video_dev.entity); video_unregister_device(&video->video_dev); + media_entity_cleanup(&video->video_dev.entity); } } -- GitLab From 2a3e7256851b642f35c3bb550be77b815486b469 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 11 Jun 2013 06:50:48 -0300 Subject: [PATCH 1443/2900] [media] smiapp: Clean up media entity after unregistering subdev media_entity_cleanup() frees the links array which will be accessed by media_entity_remove_links() called by v4l2_device_unregister_subdev(). Signed-off-by: Sakari Ailus Reviewed-by: Sylwester Nawrocki Acked-by: Laurent Pinchart Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/smiapp/smiapp-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index c38545419045..7ac7580f85c9 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2848,8 +2848,8 @@ static int smiapp_remove(struct i2c_client *client) device_remove_file(&client->dev, &dev_attr_nvm); for (i = 0; i < sensor->ssds_used; i++) { - media_entity_cleanup(&sensor->ssds[i].sd.entity); v4l2_device_unregister_subdev(&sensor->ssds[i].sd); + media_entity_cleanup(&sensor->ssds[i].sd.entity); } smiapp_free_controls(sensor); -- GitLab From 7349cec14d63251d093a213f7d40ed3c732b3734 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 9 May 2013 08:29:32 -0300 Subject: [PATCH 1444/2900] [media] media: Add a function removing all links of a media entity This function allows to remove all media entity's links to other entities, leaving no references to a media entity's links array at its remote entities. Currently, when a driver of some entity is removed it will free its media entities links[] array, leaving dangling pointers at other entities that are part of same media graph. This is troublesome when drivers of a media device entities are in separate kernel modules, removing only some modules will leave others in an incorrect state. This function is intended to be used when an entity is being unregistered from a media device. With an assumption that normally the media links should be created between media entities registered to a media device, with the graph mutex held. Signed-off-by: Sylwester Nawrocki Reviewed-by: Andrzej Hajda Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 50 ++++++++++++++++++++++++++++++++++++ include/media/media-entity.h | 3 +++ 2 files changed, 53 insertions(+) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index df72f7d99d80..cb30ffbd5ba8 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -429,6 +429,56 @@ media_entity_create_link(struct media_entity *source, u16 source_pad, } EXPORT_SYMBOL_GPL(media_entity_create_link); +void __media_entity_remove_links(struct media_entity *entity) +{ + unsigned int i; + + for (i = 0; i < entity->num_links; i++) { + struct media_link *link = &entity->links[i]; + struct media_entity *remote; + unsigned int r = 0; + + if (link->source->entity == entity) + remote = link->sink->entity; + else + remote = link->source->entity; + + while (r < remote->num_links) { + struct media_link *rlink = &remote->links[r]; + + if (rlink != link->reverse) { + r++; + continue; + } + + if (link->source->entity == entity) + remote->num_backlinks--; + + if (--remote->num_links == 0) + break; + + /* Insert last entry in place of the dropped link. */ + *rlink = remote->links[remote->num_links]; + } + } + + entity->num_links = 0; + entity->num_backlinks = 0; +} +EXPORT_SYMBOL_GPL(__media_entity_remove_links); + +void media_entity_remove_links(struct media_entity *entity) +{ + /* Do nothing if the entity is not registered. */ + if (entity->parent == NULL) + return; + + mutex_lock(&entity->parent->graph_mutex); + __media_entity_remove_links(entity); + mutex_unlock(&entity->parent->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_entity_remove_links); + static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) { int ret; diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 4eefedcaa66d..06bacf937d61 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -128,6 +128,9 @@ void media_entity_cleanup(struct media_entity *entity); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +void __media_entity_remove_links(struct media_entity *entity); +void media_entity_remove_links(struct media_entity *entity); + int __media_entity_setup_link(struct media_link *link, u32 flags); int media_entity_setup_link(struct media_link *link, u32 flags); struct media_link *media_entity_find_link(struct media_pad *source, -- GitLab From c2efd3e6e04942aa8206ca26c855eabf67cfdbc0 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 9 May 2013 08:29:33 -0300 Subject: [PATCH 1445/2900] [media] V4L: Remove all links of the media entity when unregistering subdev Remove all links of the subdev's media entity after internal_ops 'unregistered' call and right before unregistering the entity from a media device. It is assumed here that an unregistered (orphan) media entity cannot have links to other entities registered to a media device. It is also assumed the media links should be created/removed with the media graph's mutex held. The above implies that the caller of v4l2_device_unregister_subdev() must not hold the graph's mutex. Reviewed-by: Andrzej Hajda Signed-off-by: Kyungmin Park Acked-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 8ed5da2170bf..2dbfebc0ca85 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -269,8 +269,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) sd->v4l2_dev = NULL; #if defined(CONFIG_MEDIA_CONTROLLER) - if (v4l2_dev->mdev) + if (v4l2_dev->mdev) { + media_entity_remove_links(&sd->entity); media_device_unregister_entity(&sd->entity); + } #endif video_unregister_device(sd->devnode); module_put(sd->owner); -- GitLab From e2e324d70defce7ffc4668085dc3c8ae580074e5 Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Sun, 2 Jun 2013 14:30:09 -0300 Subject: [PATCH 1446/2900] [media] r820t: remove redundant initializations in r820t_attach() fe->tuner_priv and fe->ops.tuner_ops are initialized twice in r820t_attach(). Remove the redundant initializations and also move fe->ops.tuner_ops initialization outside of the mutex lock (as in the xc4000 tuner code for example). Signed-off-by: Gianluca Gennari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 64f97389d5b0..63062a9b4003 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -2310,8 +2310,6 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, break; } - memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, sizeof(r820t_tuner_ops)); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -2326,15 +2324,14 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, tuner_info("Rafael Micro r820t successfully identified\n"); - fe->tuner_priv = priv; - memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, - sizeof(struct dvb_tuner_ops)); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); mutex_unlock(&r820t_list_mutex); + memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, + sizeof(struct dvb_tuner_ops)); + return fe; err: if (fe->ops.i2c_gate_ctrl) -- GitLab From 757d7ace565c06e1302ba7c9244d839455e13881 Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Sun, 2 Jun 2013 14:31:19 -0300 Subject: [PATCH 1447/2900] [media] r820t: avoid potential memcpy buffer overflow in shadow_store() The memcpy in shadow_store() could exceed buffer limits when r > 0. Signed-off-by: Gianluca Gennari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 63062a9b4003..0a5f96be08f1 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -364,8 +364,8 @@ static void shadow_store(struct r820t_priv *priv, u8 reg, const u8 *val, } if (len <= 0) return; - if (len > NUM_REGS) - len = NUM_REGS; + if (len > NUM_REGS - r) + len = NUM_REGS - r; tuner_dbg("%s: prev reg=%02x len=%d: %*ph\n", __func__, r + REG_SHADOW_START, len, len, val); -- GitLab From bbf94616261e080507e43b07eea0d633462b00dc Mon Sep 17 00:00:00 2001 From: Gianluca Gennari Date: Mon, 17 Jun 2013 20:32:45 -0300 Subject: [PATCH 1448/2900] [media] r820t: fix imr calibration The r820t_imr() calibration function of the Rafael Micro R820T tuner generates this error at every tune attempt: r820t 0-001a: No valid PLL values for 2252021 kHz! The function was inspired by the original Realtek driver for rtl2832 devices with the r820t tuner; anyway, in the original code the XTAL frequency of the tuner was expressed in KHz, while in the kernel driver it is expressed in Hz; so the calibration failed because of an out-of-range initial value. The final result of the computation is then passed to the r820t_set_mux() and r820t_set_pll() functions, but the conversion from KHz to Hz is already correctly implemented. Signed-off-by: Gianluca Gennari Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 0a5f96be08f1..1c23666468cf 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -1857,9 +1857,9 @@ static int r820t_imr(struct r820t_priv *priv, unsigned imr_mem, bool im_flag) int reg18, reg19, reg1f; if (priv->cfg->xtal > 24000000) - ring_ref = priv->cfg->xtal / 2; + ring_ref = priv->cfg->xtal / 2000; else - ring_ref = priv->cfg->xtal; + ring_ref = priv->cfg->xtal / 1000; n_ring = 15; for (n = 0; n < 16; n++) { -- GitLab From c778edb5bdb7a96712848493273762427a51e200 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 17 Jun 2013 20:56:40 -0300 Subject: [PATCH 1449/2900] [media] mxl111sf: don't redefine pr_err/info/debug Remove the silly redefines of pr_err/info/debug. This improves readability and it also gets rid of a bunch of warnings when compiling this driver for older kernels using the compatibility media_build system. Signed-off-by: Hans Verkuil Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | 8 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 90 +++++++++---------- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index ef4c65fcbb73..879c529640f7 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -31,8 +31,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); if (mxl111sf_tuner_debug) \ mxl_printk(KERN_DEBUG, fmt, ##arg) -#define err pr_err - /* ------------------------------------------------------------------------ */ struct mxl111sf_tuner_state { @@ -113,7 +111,7 @@ static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq, filt_bw = 63; break; default: - err("%s: invalid bandwidth setting!", __func__); + pr_err("%s: invalid bandwidth setting!", __func__); return NULL; } @@ -304,12 +302,12 @@ static int mxl111sf_tuner_set_params(struct dvb_frontend *fe) bw = 8; break; default: - err("%s: bandwidth not set!", __func__); + pr_err("%s: bandwidth not set!", __func__); return -EINVAL; } break; default: - err("%s: modulation type not supported!", __func__); + pr_err("%s: modulation type not supported!", __func__); return -EINVAL; } ret = mxl1x1sf_tune_rf(fe, c->frequency, bw); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index efdcb15358f1..e97964ef7f56 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -52,12 +52,6 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -#define deb_info pr_debug -#define deb_reg pr_debug -#define deb_adv pr_debug -#define err pr_err -#define info pr_info - int mxl111sf_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { @@ -65,7 +59,7 @@ int mxl111sf_ctrl_msg(struct dvb_usb_device *d, int ret; u8 sndbuf[1+wlen]; - deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); + pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); memset(sndbuf, 0, 1+wlen); @@ -98,12 +92,12 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) if (buf[0] == addr) *data = buf[1]; else { - err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", + pr_err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", addr, buf[0], buf[1]); ret = -EINVAL; } - deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); + pr_debug("R: (0x%02x, 0x%02x)\n", addr, *data); fail: return ret; } @@ -113,11 +107,11 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) u8 buf[] = { addr, data }; int ret; - deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); + pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) - err("error writing reg: 0x%02x, val: 0x%02x", addr, data); + pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; } @@ -134,7 +128,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state, #if 1 /* dont know why this usually errors out on the first try */ if (mxl_fail(ret)) - err("error writing addr: 0x%02x, mask: 0x%02x, " + pr_err("error writing addr: 0x%02x, mask: 0x%02x, " "data: 0x%02x, retrying...", addr, mask, data); ret = mxl111sf_read_reg(state, addr, &val); @@ -167,7 +161,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, ctrl_reg_info[i].mask, ctrl_reg_info[i].data); if (mxl_fail(ret)) { - err("failed on reg #%d (0x%02x)", i, + pr_err("failed on reg #%d (0x%02x)", i, ctrl_reg_info[i].addr); break; } @@ -225,7 +219,7 @@ static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) mxl_rev = "UNKNOWN REVISION"; break; } - info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); + pr_info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); fail: return ret; } @@ -239,7 +233,7 @@ static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) " on first probe attempt"); \ ___ret = mxl1x1sf_get_chip_info(state); \ if (mxl_fail(___ret)) \ - err("failed to get chip info during probe"); \ + pr_err("failed to get chip info during probe"); \ else \ mxl_debug("probe needed a retry " \ "in order to succeed."); \ @@ -270,14 +264,14 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); mutex_lock(&state->fe_lock); state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); err = mxl1x1sf_soft_reset(state); mxl_fail(err); @@ -326,7 +320,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; @@ -344,7 +338,7 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -368,7 +362,7 @@ static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -394,7 +388,7 @@ static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -424,7 +418,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -432,7 +426,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; adap_state->gpio_mode = state->gpio_mode; @@ -495,7 +489,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -503,7 +497,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -580,7 +574,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -588,7 +582,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -667,7 +661,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -675,7 +669,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -742,7 +736,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -750,7 +744,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; adap_state->gpio_mode = state->gpio_mode; @@ -802,7 +796,7 @@ static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, } #define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ - err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ + pr_err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ __func__, __LINE__, \ (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ pwr0, pwr1, pwr2, pwr3) @@ -868,7 +862,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) struct mxl111sf_state *state = adap_to_priv(adap); int i; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); for (i = 0; i < state->num_frontends; i++) { if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state, @@ -902,7 +896,7 @@ static int mxl111sf_init(struct dvb_usb_device *d) ret = get_chip_info(state); if (mxl_fail(ret)) - err("failed to get chip info during probe"); + pr_err("failed to get chip info during probe"); mutex_init(&state->fe_lock); @@ -950,7 +944,7 @@ static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -970,7 +964,7 @@ static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -990,7 +984,7 @@ static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_attach_demod(adap, 0); if (ret < 0) @@ -1006,7 +1000,7 @@ static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint) { - deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint); + pr_debug("%s: endpoint=%d size=8192\n", __func__, endpoint); stream->type = USB_BULK; stream->count = 5; stream->endpoint = endpoint; @@ -1016,7 +1010,7 @@ static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *strea static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream, u8 endpoint, int framesperurb, int framesize) { - deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint, + pr_debug("%s: endpoint=%d size=%d\n", __func__, endpoint, framesperurb * framesize); stream->type = USB_ISOC; stream->count = 5; @@ -1035,7 +1029,7 @@ static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *strea static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1076,7 +1070,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = { static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1117,7 +1111,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = { static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_RAW; if (dvb_usb_mxl111sf_isoc) @@ -1158,7 +1152,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = { static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1184,7 +1178,7 @@ static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1228,7 +1222,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1260,7 +1254,7 @@ static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1306,7 +1300,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = { static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1332,7 +1326,7 @@ static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep4_streaming_ctrl(fe, onoff); -- GitLab From 907d109bc212bc1193fb01b5c320e8c9a850bbf4 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Mon, 3 Jun 2013 14:12:02 -0300 Subject: [PATCH 1450/2900] [media] em28xx: extend GPIO register definitions for the em25xx, em276x/7x/8x, em2874/174/84 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The em25xx/em276x/7x/8x provides 4 GPIO register sets, each of them consisting of separate read and a write registers. The same registers are also used by the em2874/174/84. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 88 ++++++++++++------------- drivers/media/usb/em28xx/em28xx-dvb.c | 62 ++++++++--------- drivers/media/usb/em28xx/em28xx-reg.h | 15 ++++- 3 files changed, 89 insertions(+), 76 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index e4b0669d49dd..c0b853541f09 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -285,14 +285,14 @@ static struct em28xx_reg_seq dikom_dk300_digital[] = { /* Reset for the most [digital] boards */ static struct em28xx_reg_seq leadership_digital[] = { - {EM2874_R80_GPIO, 0x70, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x70, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq leadership_reset[] = { - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - {EM2874_R80_GPIO, 0xb0, 0xff, 10}, - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xb0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -301,25 +301,25 @@ static struct em28xx_reg_seq leadership_reset[] = { * GPIO_7 - LED */ static struct em28xx_reg_seq pctv_290e[] = { - {EM2874_R80_GPIO, 0x00, 0xff, 80}, - {EM2874_R80_GPIO, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 80}, + {EM2874_R80_GPIO_P0_CTRL, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ {-1, -1, -1, -1}, }; #if 0 static struct em28xx_reg_seq terratec_h5_gpio[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_h5_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10}, { -1, -1, -1, -1}, }; #endif @@ -335,39 +335,39 @@ static struct em28xx_reg_seq terratec_h5_digital[] = { * GPIO_7 - LED (green LED) */ static struct em28xx_reg_seq pctv_460e[] = { - {EM2874_R80_GPIO, 0x01, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0x01, 0xff, 50}, {0x0d, 0xff, 0xff, 50}, - {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x41, 0xff, 50}, /* GPIO_6=1 */ {0x0d, 0x42, 0xff, 50}, - {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x61, 0xff, 50}, /* GPIO_5=1 */ { -1, -1, -1, -1}, }; static struct em28xx_reg_seq c3tech_digital_duo_digital[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xfd, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0xf9, 0xff, 35}, - {EM2874_R80_GPIO, 0xfd, 0xff, 10}, - {EM2874_R80_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xfe, 0xff, 10}, - {EM2874_R80_GPIO, 0xbe, 0xff, 10}, - {EM2874_R80_GPIO, 0xfe, 0xff, 20}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, /* xc5000 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xf9, 0xff, 35}, + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xbe, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 20}, { -1, -1, -1, -1}, }; #if 0 static struct em28xx_reg_seq hauppauge_930c_gpio[] = { - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x4f, 0xff, 10}, /* xc5000 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x4f, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq hauppauge_930c_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10}, { -1, -1, -1, -1}, }; #endif @@ -378,9 +378,9 @@ static struct em28xx_reg_seq hauppauge_930c_digital[] = { * GPIO_7 - LED, 0=active */ static struct em28xx_reg_seq maxmedia_ub425_tc[] = { - {EM2874_R80_GPIO, 0x83, 0xff, 100}, - {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ + {EM2874_R80_GPIO_P0_CTRL, 0x83, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ {-1, -1, -1, -1}, }; @@ -391,9 +391,9 @@ static struct em28xx_reg_seq maxmedia_ub425_tc[] = { * GPIO_7: LED, 1=active */ static struct em28xx_reg_seq pctv_510e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ { -1, -1, -1, -1}, }; @@ -404,10 +404,10 @@ static struct em28xx_reg_seq pctv_510e[] = { * GPIO_7: LED, 1=active */ static struct em28xx_reg_seq pctv_520e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ { -1, -1, -1, -1}, }; @@ -2947,13 +2947,13 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2874: chip_name = "em2874"; - dev->reg_gpio_num = EM2874_R80_GPIO; + dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; case CHIP_ID_EM28174: chip_name = "em28174"; - dev->reg_gpio_num = EM2874_R80_GPIO; + dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; @@ -2963,7 +2963,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2884: chip_name = "em2884"; - dev->reg_gpio_num = EM2874_R80_GPIO; + dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 42ede686ab69..69aed825f583 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -421,23 +421,23 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) int i; struct em28xx_reg_seq hauppauge_hvr930c_init[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, - {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xfb, 0xff, 0x32}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0xb8}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq hauppauge_hvr930c_end[] = { - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, - - {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO_P0_CTRL, 0xaf, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x76}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x40}, + + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, { -1, -1, -1, -1}, }; @@ -488,15 +488,15 @@ static void terratec_h5_init(struct em28xx *dev) int i; struct em28xx_reg_seq terratec_h5_init[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_h5_end[] = { - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, { -1, -1, -1, -1}, }; struct { @@ -544,14 +544,14 @@ static void terratec_htc_stick_init(struct em28xx *dev) */ struct em28xx_reg_seq terratec_htc_stick_init[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xe6, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_htc_stick_end[] = { - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, { -1, -1, -1, -1}, }; @@ -591,15 +591,15 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev) struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xb2, 0xff, 100}, - {EM2874_R80_GPIO, 0xb2, 0xff, 50}, - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { - {EM2874_R80_GPIO, 0xa6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, { -1, -1, -1, -1}, }; diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 622871db04aa..0233c5bedc55 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -193,7 +193,20 @@ #define EM2874_R50_IR_CONFIG 0x50 #define EM2874_R51_IR 0x51 #define EM2874_R5F_TS_ENABLE 0x5f -#define EM2874_R80_GPIO 0x80 + +/* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ +/* + * NOTE: not all ports are bonded out; + * Some ports are multiplexed with special function I/O + */ +#define EM2874_R80_GPIO_P0_CTRL 0x80 +#define EM2874_R81_GPIO_P1_CTRL 0x81 +#define EM2874_R82_GPIO_P2_CTRL 0x82 +#define EM2874_R83_GPIO_P3_CTRL 0x83 +#define EM2874_R84_GPIO_P0_STATE 0x84 +#define EM2874_R85_GPIO_P1_STATE 0x85 +#define EM2874_R86_GPIO_P2_STATE 0x86 +#define EM2874_R87_GPIO_P3_STATE 0x87 /* em2874 IR config register (0x50) */ #define EM2874_IR_NEC 0x00 -- GitLab From c074fc4c2990d48acab78d304054a6ff212f3d53 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Mon, 3 Jun 2013 14:12:03 -0300 Subject: [PATCH 1451/2900] [media] em28xx: improve em2820-em2873/83 GPIO port register definitions and descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add definition for GPIO register 0x09 (reading/input) - extend the information the chip variants that support GPIO registers 0x08/0x09 - rename EM28XX_R08_GPIO to EM2820_R08_GPIO_CTRL Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 128 ++++++++++++------------ drivers/media/usb/em28xx/em28xx-dvb.c | 6 +- drivers/media/usb/em28xx/em28xx-reg.h | 5 +- 3 files changed, 70 insertions(+), 69 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index c0b853541f09..6ee4bed730dd 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -82,26 +82,26 @@ static void em28xx_pre_card_setup(struct em28xx *dev); /* Reset for the most [analog] boards */ static struct em28xx_reg_seq default_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Reset for the most [digital] boards */ static struct em28xx_reg_seq default_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 analog */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2d, ~EM_GPIO_4, 10}, {0x05, 0xff, 0x10, 10}, { -1, -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x04, 0x0f, 10}, {EM2880_R04_GPO, 0x0c, 0x0f, 10}, { -1, -1, -1, -1}, @@ -109,14 +109,14 @@ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { /* Board Hauppauge WinTV HVR 900 (R2) digital */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x0c, 0x0f, 10}, { -1, -1, -1, -1}, }; /* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { - {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x69, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; @@ -127,11 +127,11 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { /* Board - EM2882 Kworld 315U digital */ static struct em28xx_reg_seq em2882_kworld_315u_digital[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, {EM2880_R04_GPO, 0x04, 0xff, 10}, {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7e, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x7e, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -144,13 +144,13 @@ static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = { }; static struct em28xx_reg_seq kworld_330u_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x00, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq kworld_330u_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -162,12 +162,12 @@ static struct em28xx_reg_seq kworld_330u_digital[] = { GOP3 - s5h1409 reset */ static struct em28xx_reg_seq evga_indtube_analog[] = { - {EM28XX_R08_GPIO, 0x79, 0xff, 60}, + {EM2820_R08_GPIO_CTRL, 0x79, 0xff, 60}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq evga_indtube_digital[] = { - {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, + {EM2820_R08_GPIO_CTRL, 0x7a, 0xff, 1}, {EM2880_R04_GPO, 0x04, 0xff, 10}, {EM2880_R04_GPO, 0x0c, 0xff, 1}, { -1, -1, -1, -1}, @@ -185,31 +185,31 @@ static struct em28xx_reg_seq evga_indtube_digital[] = { * EM_GPIO_7 - currently unknown */ static struct em28xx_reg_seq kworld_a340_digital[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Pinnacle Hybrid Pro eb1a:2881 */ static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { - {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0xfd, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */ {EM2880_R04_GPO, 0x0c, 0xff, 1}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x00, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -218,66 +218,66 @@ static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { GPIO4 - CU1216L NIM Other GPIOs seems to be don't care. */ static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = { - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xde, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7f, 0xff, 10}, - {EM28XX_R08_GPIO, 0x6f, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xde, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x7f, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x6f, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {-1, -1, -1, -1}, }; /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Mute/unmute */ static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { - {EM28XX_R08_GPIO, 5, 7, 10}, + {EM2820_R08_GPIO_CTRL, 5, 7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { - {EM28XX_R08_GPIO, 4, 7, 10}, + {EM2820_R08_GPIO_CTRL, 4, 7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq compro_mute_gpio[] = { - {EM28XX_R08_GPIO, 6, 7, 10}, + {EM2820_R08_GPIO_CTRL, 6, 7, 10}, { -1, -1, -1, -1}, }; /* Terratec AV350 */ static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x7f, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq silvercrest_reg_seq[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x01, 0xf7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq vc211a_enable[] = { - {EM28XX_R08_GPIO, 0xff, 0x07, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x07, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x0f, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x0b, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq dikom_dk300_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -309,7 +309,7 @@ static struct em28xx_reg_seq pctv_290e[] = { #if 0 static struct em28xx_reg_seq terratec_h5_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, @@ -2299,9 +2299,9 @@ static void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x6d); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x7d); msleep(10); break; case EM2870_BOARD_COMPRO_VIDEOMATE: @@ -2311,45 +2311,45 @@ static void em28xx_pre_card_setup(struct em28xx *dev) msleep(10); em28xx_write_reg(dev, EM2880_R04_GPO, 0x01); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfc); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xdc); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfc); mdelay(70); break; case EM2870_BOARD_TERRATEC_XS_MT2060: /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); break; case EM2870_BOARD_PINNACLE_PCTV_DVB: /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); break; case EM2820_BOARD_GADMEI_UTV310: case EM2820_BOARD_MSI_VOX_USB_2: /* enables audio for that devices */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); break; case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); msleep(10); em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); msleep(10); @@ -2375,13 +2375,13 @@ static void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2820_BOARD_IODATA_GVMVP_SZ: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); msleep(70); break; } @@ -2677,12 +2677,12 @@ static void em28xx_card_setup(struct em28xx *dev) case EM2882_BOARD_KWORLD_ATSC_315U: em28xx_write_reg(dev, 0x0d, 0x42); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); msleep(10); break; case EM2820_BOARD_KWORLD_PVRTV2800RF: /* GPIO enables sound on KWORLD PVR TV 2800RF */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf9); break; case EM2820_BOARD_UNKNOWN: case EM2800_BOARD_UNKNOWN: @@ -2898,7 +2898,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, /* Set the default GPO/GPIO for legacy devices */ dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; + dev->reg_gpio_num = EM2820_R08_GPIO_CTRL; dev->wait_after_write = 5; @@ -3086,7 +3086,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, if (dev->board.has_msp34xx) { /* Send a reset to other chips via gpio */ - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + retval = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7); if (retval < 0) { em28xx_errdev("%s: em28xx_write_reg - " "msp34xx(1) failed! error [%d]\n", @@ -3095,7 +3095,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, } msleep(3); - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + retval = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); if (retval < 0) { em28xx_errdev("%s: em28xx_write_reg - " "msp34xx(2) failed! error [%d]\n", diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 69aed825f583..bb1e8dca80cd 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -487,7 +487,7 @@ static void terratec_h5_init(struct em28xx *dev) { int i; struct em28xx_reg_seq terratec_h5_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, @@ -543,7 +543,7 @@ static void terratec_htc_stick_init(struct em28xx *dev) * 0xb6: unknown (does not affect DVB-T). */ struct em28xx_reg_seq terratec_htc_stick_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, @@ -590,7 +590,7 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev) int i; struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 0233c5bedc55..af39ddbe01e0 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -49,8 +49,9 @@ /* GPIO/GPO registers */ -#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ -#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ +#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ +#define EM2820_R08_GPIO_CTRL 0x08 /* em2820-em2873/83 only */ +#define EM2820_R09_GPIO_STATE 0x09 /* em2820-em2873/83 only */ #define EM28XX_R06_I2C_CLK 0x06 -- GitLab From bc677fff1cde38ce8e14d6a2cb703a9fb134ab98 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Mon, 3 Jun 2013 14:12:04 -0300 Subject: [PATCH 1452/2900] [media] em28xx: move snapshot button bit definition for reg 0x0C from em28xx-input.c to em28xx.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 1 - drivers/media/usb/em28xx/em28xx-reg.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 466b19d0d767..ea181e4b68c5 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -32,7 +32,6 @@ #define EM28XX_SNAPSHOT_KEY KEY_CAMERA #define EM28XX_SBUTTON_QUERY_INTERVAL 500 -#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 static unsigned int ir_debug; module_param(ir_debug, int, 0644); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index af39ddbe01e0..0e0477847965 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -68,7 +68,8 @@ #define EM28XX_R0A_CHIPID 0x0a -#define EM28XX_R0C_USBSUSP 0x0c /* */ +#define EM28XX_R0C_USBSUSP 0x0c +#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 /* 1=button pressed, needs reset */ #define EM28XX_R0E_AUDIOSRC 0x0e #define EM28XX_R0F_XCLK 0x0f -- GitLab From 6914d70ecf53e90814fd6d4c8e413b3a8f708d38 Mon Sep 17 00:00:00 2001 From: Frank Schaefer Date: Mon, 3 Jun 2013 14:12:05 -0300 Subject: [PATCH 1453/2900] [media] em28xx: remove GPIO register caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIO register caching is the result of wrong assumptions and incomplete knowledge about the GPIO registers and their functionality. Today, we know that it is not needed. It is also limited to a single register and therefore incomplete (newer chips are using multiple registers). Instead of extending the caching, get rid of it, because it has no real benefits and just bloats/complicates the code. Signed-off-by: Frank Schäfer Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 12 ----------- drivers/media/usb/em28xx/em28xx-core.c | 27 ++----------------------- drivers/media/usb/em28xx/em28xx.h | 6 ------ 3 files changed, 2 insertions(+), 43 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 6ee4bed730dd..dc65742c4bbc 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2896,10 +2896,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, em28xx_set_model(dev); - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM2820_R08_GPIO_CTRL; - dev->wait_after_write = 5; /* Based on the Chip ID, set the device configuration */ @@ -2947,13 +2943,11 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2874: chip_name = "em2874"; - dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; case CHIP_ID_EM28174: chip_name = "em28174"; - dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; @@ -2963,7 +2957,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2884: chip_name = "em2884"; - dev->reg_gpio_num = EM2874_R80_GPIO_P0_CTRL; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; @@ -2992,11 +2985,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, return 0; } - /* Prepopulate cached GPO register content */ - retval = em28xx_read_reg(dev, dev->reg_gpo_num); - if (retval >= 0) - dev->reg_gpo = retval; - em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index a802128ce9c5..fc157af5234a 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -193,23 +193,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) { - int rc; - - rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); - - /* Stores GPO/GPIO values at the cache, if changed - Only write values should be stored, since input on a GPIO - register will return the input bits. - Not sure what happens on reading GPO register. - */ - if (rc >= 0) { - if (reg == dev->reg_gpo_num) - dev->reg_gpo = buf[0]; - else if (reg == dev->reg_gpio_num) - dev->reg_gpio = buf[0]; - } - - return rc; + return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); } EXPORT_SYMBOL_GPL(em28xx_write_regs); @@ -231,14 +215,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, int oldval; u8 newval; - /* Uses cache for gpo/gpio registers */ - if (reg == dev->reg_gpo_num) - oldval = dev->reg_gpo; - else if (reg == dev->reg_gpio_num) - oldval = dev->reg_gpio; - else - oldval = em28xx_read_reg(dev, reg); - + oldval = em28xx_read_reg(dev, reg); if (oldval < 0) return oldval; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 59a95802aa68..205e9038b1c0 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -637,12 +637,6 @@ struct em28xx { enum em28xx_mode mode; - /* register numbers for GPO/GPIO registers */ - u16 reg_gpo_num, reg_gpio_num; - - /* Caches GPO and GPIO registers */ - unsigned char reg_gpo, reg_gpio; - /* Snapshot button */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; -- GitLab From 414abbd2cd4c2618895f02ed3a76ec6647281436 Mon Sep 17 00:00:00 2001 From: Soeren Moch Date: Wed, 5 Jun 2013 21:26:23 -0300 Subject: [PATCH 1454/2900] [media] media: dmxdev: remove dvb_ringbuffer_flush() on writer side In dvb_ringbuffer lock-less synchronizationof reader and writer threads is done with separateread and write pointers. Sincedvb_ringbuffer_flush() modifies the read pointer, this function must not be called from the writer thread. This patch removes the dvb_ringbuffer_flush() calls in the dmxdev ringbuffer write functions, this fixes Oopses "Unable to handle kernel paging request" I could observe for the call chaindvb_demux_read ->dvb_dmxdev_buffer_read -> dvb_ringbuffer_read_user -> __copy_to_user (the reader side of the ringbuffer). The flush calls at the write side are not necessary anyway since ringbuffer_flush is also called in dvb_dmxdev_buffer_read() when an error condition is set in the ringbuffer. This patch should also be applied to stable kernels. Signed-off-by: Soeren Moch CC: Reviewed-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dmxdev.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index a1a3a5159d71..0b4616b87195 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -377,10 +377,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len); } - if (ret < 0) { - dvb_ringbuffer_flush(&dmxdevfilter->buffer); + if (ret < 0) dmxdevfilter->buffer.error = ret; - } if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) dmxdevfilter->state = DMXDEV_STATE_DONE; spin_unlock(&dmxdevfilter->dev->lock); @@ -416,10 +414,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); if (ret == buffer1_len) ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); - if (ret < 0) { - dvb_ringbuffer_flush(buffer); + if (ret < 0) buffer->error = ret; - } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; -- GitLab From 86e8cf98de3e74bbfb0003501e0004bf1e5e2618 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jun 2013 10:57:22 +0200 Subject: [PATCH 1455/2900] nl80211: use small state buffer for wiphy_dump Avoid parsing the original dump message again and again by allocating a small state struct that is used by the functions involved in the dump, storing this struct in cb->args[0]. This reduces the memory allocation size as well. Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 210 +++++++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 94 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f8ffb9a59c83..7dc3343427c1 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1111,10 +1111,16 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg, return 0; } +struct nl80211_dump_wiphy_state { + s64 filter_wiphy; + long start; + long split_start, band_start, chan_start; + bool split; +}; + static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, struct sk_buff *msg, u32 portid, u32 seq, - int flags, bool split, long *split_start, - long *band_start, long *chan_start) + int flags, struct nl80211_dump_wiphy_state *state) { void *hdr; struct nlattr *nl_bands, *nl_band; @@ -1125,19 +1131,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, int i; const struct ieee80211_txrx_stypes *mgmt_stypes = dev->wiphy.mgmt_stypes; - long start = 0, start_chan = 0, start_band = 0; u32 features; hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_WIPHY); if (!hdr) return -ENOBUFS; - /* allow always using the variables */ - if (!split) { - split_start = &start; - band_start = &start_band; - chan_start = &start_chan; - } + if (WARN_ON(!state)) + return -EINVAL; if (nla_put_u32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx) || nla_put_string(msg, NL80211_ATTR_WIPHY_NAME, @@ -1146,7 +1147,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, cfg80211_rdev_list_generation)) goto nla_put_failure; - switch (*split_start) { + switch (state->split_start) { case 0: if (nla_put_u8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, dev->wiphy.retry_short) || @@ -1192,8 +1193,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ)) goto nla_put_failure; - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 1: if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, @@ -1237,22 +1238,23 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, } } - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 2: if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, dev->wiphy.interface_modes)) goto nla_put_failure; - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 3: nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); if (!nl_bands) goto nla_put_failure; - for (band = *band_start; band < IEEE80211_NUM_BANDS; band++) { + for (band = state->band_start; + band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = dev->wiphy.bands[band]; @@ -1264,12 +1266,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, if (!nl_band) goto nla_put_failure; - switch (*chan_start) { + switch (state->chan_start) { case 0: if (nl80211_send_band_rateinfo(msg, sband)) goto nla_put_failure; - (*chan_start)++; - if (split) + state->chan_start++; + if (state->split) break; default: /* add frequencies */ @@ -1278,7 +1280,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, if (!nl_freqs) goto nla_put_failure; - for (i = *chan_start - 1; + for (i = state->chan_start - 1; i < sband->n_channels; i++) { nl_freq = nla_nest_start(msg, i); @@ -1287,26 +1289,27 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, chan = &sband->channels[i]; - if (nl80211_msg_put_channel(msg, chan, - split)) + if (nl80211_msg_put_channel( + msg, chan, + state->split)) goto nla_put_failure; nla_nest_end(msg, nl_freq); - if (split) + if (state->split) break; } if (i < sband->n_channels) - *chan_start = i + 2; + state->chan_start = i + 2; else - *chan_start = 0; + state->chan_start = 0; nla_nest_end(msg, nl_freqs); } nla_nest_end(msg, nl_band); - if (split) { + if (state->split) { /* start again here */ - if (*chan_start) + if (state->chan_start) band--; break; } @@ -1314,14 +1317,14 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, nla_nest_end(msg, nl_bands); if (band < IEEE80211_NUM_BANDS) - *band_start = band + 1; + state->band_start = band + 1; else - *band_start = 0; + state->band_start = 0; /* if bands & channels are done, continue outside */ - if (*band_start == 0 && *chan_start == 0) - (*split_start)++; - if (split) + if (state->band_start == 0 && state->chan_start == 0) + state->split_start++; + if (state->split) break; case 4: nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS); @@ -1387,7 +1390,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, } CMD(start_p2p_device, START_P2P_DEVICE); CMD(set_mcast_rate, SET_MCAST_RATE); - if (split) { + if (state->split) { CMD(crit_proto_start, CRIT_PROTOCOL_START); CMD(crit_proto_stop, CRIT_PROTOCOL_STOP); } @@ -1411,8 +1414,8 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, } nla_nest_end(msg, nl_cmds); - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 5: if (dev->ops->remain_on_channel && @@ -1428,29 +1431,30 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, if (nl80211_send_mgmt_stypes(msg, mgmt_stypes)) goto nla_put_failure; - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 6: #ifdef CONFIG_PM - if (nl80211_send_wowlan(msg, dev, split)) + if (nl80211_send_wowlan(msg, dev, state->split)) goto nla_put_failure; - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; #else - (*split_start)++; + state->split_start++; #endif case 7: if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, dev->wiphy.software_iftypes)) goto nla_put_failure; - if (nl80211_put_iface_combinations(&dev->wiphy, msg, split)) + if (nl80211_put_iface_combinations(&dev->wiphy, msg, + state->split)) goto nla_put_failure; - (*split_start)++; - if (split) + state->split_start++; + if (state->split) break; case 8: if ((dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && @@ -1464,7 +1468,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, * dump is split, otherwise it makes it too big. Therefore * only advertise it in that case. */ - if (split) + if (state->split) features |= NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; if (nla_put_u32(msg, NL80211_ATTR_FEATURE_FLAGS, features)) goto nla_put_failure; @@ -1491,7 +1495,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, * case we'll continue with more data in the next round, * but break unconditionally so unsplit data stops here. */ - (*split_start)++; + state->split_start++; break; case 9: if (dev->wiphy.extended_capabilities && @@ -1510,7 +1514,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, goto nla_put_failure; /* done */ - *split_start = 0; + state->split_start = 0; break; } return genlmsg_end(msg, hdr); @@ -1520,66 +1524,76 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, return -EMSGSIZE; } +static int nl80211_dump_wiphy_parse(struct sk_buff *skb, + struct netlink_callback *cb, + struct nl80211_dump_wiphy_state *state) +{ + struct nlattr **tb = nl80211_fam.attrbuf; + int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, + tb, nl80211_fam.maxattr, nl80211_policy); + /* ignore parse errors for backward compatibility */ + if (ret) + return 0; + + state->split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; + if (tb[NL80211_ATTR_WIPHY]) + state->filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); + if (tb[NL80211_ATTR_WDEV]) + state->filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; + if (tb[NL80211_ATTR_IFINDEX]) { + struct net_device *netdev; + struct cfg80211_registered_device *rdev; + int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); + + netdev = dev_get_by_index(sock_net(skb->sk), ifidx); + if (!netdev) + return -ENODEV; + if (netdev->ieee80211_ptr) { + rdev = wiphy_to_dev( + netdev->ieee80211_ptr->wiphy); + state->filter_wiphy = rdev->wiphy_idx; + } + dev_put(netdev); + } + + return 0; +} + static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) { int idx = 0, ret; - int start = cb->args[0]; + struct nl80211_dump_wiphy_state *state = (void *)cb->args[0]; struct cfg80211_registered_device *dev; - s64 filter_wiphy = -1; - bool split = false; - struct nlattr **tb; - int res; - - /* will be zeroed in nlmsg_parse() */ - tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL); - if (!tb) - return -ENOMEM; rtnl_lock(); - res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, - tb, NL80211_ATTR_MAX, nl80211_policy); - if (res == 0) { - split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; - if (tb[NL80211_ATTR_WIPHY]) - filter_wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]); - if (tb[NL80211_ATTR_WDEV]) - filter_wiphy = nla_get_u64(tb[NL80211_ATTR_WDEV]) >> 32; - if (tb[NL80211_ATTR_IFINDEX]) { - struct net_device *netdev; - int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); - - netdev = dev_get_by_index(sock_net(skb->sk), ifidx); - if (!netdev) { - rtnl_unlock(); - kfree(tb); - return -ENODEV; - } - if (netdev->ieee80211_ptr) { - dev = wiphy_to_dev( - netdev->ieee80211_ptr->wiphy); - filter_wiphy = dev->wiphy_idx; - } - dev_put(netdev); + if (!state) { + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + state->filter_wiphy = -1; + ret = nl80211_dump_wiphy_parse(skb, cb, state); + if (ret) { + kfree(state); + rtnl_unlock(); + return ret; } + cb->args[0] = (long)state; } - kfree(tb); list_for_each_entry(dev, &cfg80211_rdev_list, list) { if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) continue; - if (++idx <= start) + if (++idx <= state->start) continue; - if (filter_wiphy != -1 && dev->wiphy_idx != filter_wiphy) + if (state->filter_wiphy != -1 && + state->filter_wiphy != dev->wiphy_idx) continue; /* attempt to fit multiple wiphy data chunks into the skb */ do { ret = nl80211_send_wiphy(dev, skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, - NLM_F_MULTI, - split, &cb->args[1], - &cb->args[2], - &cb->args[3]); + NLM_F_MULTI, state); if (ret < 0) { /* * If sending the wiphy data didn't fit (ENOBUFS @@ -1604,27 +1618,34 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) idx--; break; } - } while (cb->args[1] > 0); + } while (state->split_start > 0); break; } rtnl_unlock(); - cb->args[0] = idx; + state->start = idx; return skb->len; } +static int nl80211_dump_wiphy_done(struct netlink_callback *cb) +{ + kfree((void *)cb->args[0]); + return 0; +} + static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *msg; struct cfg80211_registered_device *dev = info->user_ptr[0]; + struct nl80211_dump_wiphy_state state = {}; msg = nlmsg_new(4096, GFP_KERNEL); if (!msg) return -ENOMEM; if (nl80211_send_wiphy(dev, msg, info->snd_portid, info->snd_seq, 0, - false, NULL, NULL, NULL) < 0) { + &state) < 0) { nlmsg_free(msg); return -ENOBUFS; } @@ -8418,6 +8439,7 @@ static struct genl_ops nl80211_ops[] = { .cmd = NL80211_CMD_GET_WIPHY, .doit = nl80211_get_wiphy, .dumpit = nl80211_dump_wiphy, + .done = nl80211_dump_wiphy_done, .policy = nl80211_policy, /* can be retrieved by unprivileged users */ .internal_flags = NL80211_FLAG_NEED_WIPHY | @@ -9038,13 +9060,13 @@ static struct genl_multicast_group nl80211_regulatory_mcgrp = { void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) { struct sk_buff *msg; + struct nl80211_dump_wiphy_state state = {}; msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) return; - if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, - false, NULL, NULL, NULL) < 0) { + if (nl80211_send_wiphy(rdev, msg, 0, 0, 0, &state) < 0) { nlmsg_free(msg); return; } -- GitLab From 959867fa55d0cb55fb3d08656e5e62607167617f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jun 2013 13:05:42 +0200 Subject: [PATCH 1456/2900] cfg80211: require passing BSS struct back to cfg80211_assoc_timeout Doing so will allow us to hold the BSS (not just ref it) over the association process, thus ensuring that it doesn't time out and gets invisible to the user (e.g. in 'iw wlan0 link'.) This also fixes a leak in mac80211 where it doesn't always release the BSS struct properly in all cases where calling this function. This leak was reported by Ben Greear. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 16 ++++++++-------- net/mac80211/mlme.c | 15 +++++++-------- net/wireless/mlme.c | 8 +++++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e3a39fc9a296..7b0730aeb892 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1459,7 +1459,8 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); * This structure provides information needed to complete IEEE 802.11 * authentication. * - * @bss: The BSS to authenticate with. + * @bss: The BSS to authenticate with, the callee must obtain a reference + * to it if it needs to keep it. * @auth_type: Authentication type (algorithm) * @ie: Extra IEs to add to Authentication frame or %NULL * @ie_len: Length of ie buffer in octets @@ -1497,11 +1498,10 @@ enum cfg80211_assoc_req_flags { * * This structure provides information needed to complete IEEE 802.11 * (re)association. - * @bss: The BSS to associate with. If the call is successful the driver - * is given a reference that it must release, normally via a call to - * cfg80211_send_rx_assoc(), or, if association timed out, with a - * call to cfg80211_put_bss() (in addition to calling - * cfg80211_send_assoc_timeout()) + * @bss: The BSS to associate with. If the call is successful the driver is + * given a reference that it must give back to cfg80211_send_rx_assoc() + * or to cfg80211_assoc_timeout(). To ensure proper refcounting, new + * association requests while already associating must be rejected. * @ie: Extra IEs to add to (Re)Association Request frame or %NULL * @ie_len: Length of ie buffer in octets * @use_mfp: Use management frame protection (IEEE 802.11w) in this association @@ -3522,11 +3522,11 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, /** * cfg80211_assoc_timeout - notification of timed out association * @dev: network device - * @addr: The MAC address of the device with which the association timed out + * @bss: The BSS entry with which association timed out. * * This function may sleep. The caller must hold the corresponding wdev's mutex. */ -void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr); +void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss); /** * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 34d54fe81483..ae31968d42d3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2795,8 +2795,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ ieee80211_destroy_assoc_data(sdata, false); - cfg80211_put_bss(sdata->local->hw.wiphy, bss); - cfg80211_assoc_timeout(sdata->dev, mgmt->bssid); + cfg80211_assoc_timeout(sdata->dev, bss); return; } sdata_info(sdata, "associated\n"); @@ -3513,13 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) time_after(jiffies, ifmgd->assoc_data->timeout)) { if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || ieee80211_do_assoc(sdata)) { - u8 bssid[ETH_ALEN]; - - memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN); + struct cfg80211_bss *bss = ifmgd->assoc_data->bss; ieee80211_destroy_assoc_data(sdata, false); - - cfg80211_assoc_timeout(sdata->dev, bssid); + cfg80211_assoc_timeout(sdata->dev, bss); } } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) run_again(sdata, ifmgd->assoc_data->timeout); @@ -4445,8 +4441,11 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) cancel_work_sync(&ifmgd->chswitch_work); sdata_lock(sdata); - if (ifmgd->assoc_data) + if (ifmgd->assoc_data) { + struct cfg80211_bss *bss = ifmgd->assoc_data->bss; ieee80211_destroy_assoc_data(sdata, false); + cfg80211_assoc_timeout(sdata->dev, bss); + } if (ifmgd->auth_data) ieee80211_destroy_auth_data(sdata, false); del_timer_sync(&ifmgd->timer); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index a61a44bc6cf0..dd6f79d7bd2e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -131,16 +131,18 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr) } EXPORT_SYMBOL(cfg80211_auth_timeout); -void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr) +void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct wiphy *wiphy = wdev->wiphy; struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); - trace_cfg80211_send_assoc_timeout(dev, addr); + trace_cfg80211_send_assoc_timeout(dev, bss->bssid); - nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); + nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL); cfg80211_sme_assoc_timeout(wdev); + + cfg80211_put_bss(wiphy, bss); } EXPORT_SYMBOL(cfg80211_assoc_timeout); -- GitLab From f1940c5730f0f0555e42afbcf629be7f7fbbce8e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jun 2013 13:21:15 +0200 Subject: [PATCH 1457/2900] cfg80211: hold BSS over association process This fixes the potential issue that the BSS struct that we use and later assign to wdev->current_bss is removed from the scan list while associating. Also warn when we don't have a BSS struct in connect_result unless it's from a driver that only has the connect() API. Signed-off-by: Johannes Berg --- net/wireless/mlme.c | 4 ++++ net/wireless/sme.c | 15 ++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index dd6f79d7bd2e..bfac5e186f57 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -38,6 +38,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, * frame instead of reassoc. */ if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { + cfg80211_unhold_bss(bss_from_pub(bss)); cfg80211_put_bss(wiphy, bss); return; } @@ -142,6 +143,7 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss) nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL); cfg80211_sme_assoc_timeout(wdev); + cfg80211_unhold_bss(bss_from_pub(bss)); cfg80211_put_bss(wiphy, bss); } EXPORT_SYMBOL(cfg80211_assoc_timeout); @@ -309,6 +311,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, goto out; err = rdev_assoc(rdev, dev, req); + if (!err) + cfg80211_hold_bss(bss_from_pub(req->bss)); out: if (err) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index ae7e2cbf45cb..c0bf781d4fbe 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -615,19 +615,24 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(wdev->connect_keys); wdev->connect_keys = NULL; wdev->ssid_len = 0; - cfg80211_put_bss(wdev->wiphy, bss); + if (bss) { + cfg80211_unhold_bss(bss_from_pub(bss)); + cfg80211_put_bss(wdev->wiphy, bss); + } return; } - if (!bss) + if (!bss) { + WARN_ON_ONCE(!wiphy_to_dev(wdev->wiphy)->ops->connect); bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (WARN_ON(!bss)) - return; + if (WARN_ON(!bss)) + return; + cfg80211_hold_bss(bss_from_pub(bss)); + } - cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); cfg80211_upload_connect_keys(wdev); -- GitLab From 10d0b9030a3f86e1e26c710c7580524d7787d688 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 18 Jun 2013 13:25:05 -0500 Subject: [PATCH 1458/2900] rtlwifi: rtl8192cu: Fix duplicate if test A typo causes routine rtl92cu_phy_rf6052_set_cck_txpower() to test the same condition twice. The problem was found using cppcheck-1.49, and the proper fix was verified against the pre-mac80211 version of the code. This patch was originally included as commit 1288aa4, but was accidentally reverted in a later patch. Reported-by: David Binderman [original report] Reported-by: Andrea Morello [report of accidental reversion] Signed-off-by: Larry Finger Cc: stable [back to 2.6.39] Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 953f1a0f8532..2119313a737b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tx_agc[RF90_PATH_A] = 0x10101010; tx_agc[RF90_PATH_B] = 0x10101010; } else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) { + TXHIGHPWRLEVEL_LEVEL2) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; } else{ -- GitLab From f2bbb07729f04bd8efa3f3285f19ba0609e42017 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 18 Jun 2013 16:36:56 -0700 Subject: [PATCH 1459/2900] mwifiex: code rearrangement for better readability Use negative check (if(!bss_desc)) and return failure instead of failing a NULL check later in mwifiex_check_network_compatibility() routine. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_ioctl.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 23aa910bc5d0..15b5457fa4e5 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -255,25 +255,24 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, } if (priv->bss_mode == NL80211_IFTYPE_STATION) { + u8 config_bands; + /* Infra mode */ ret = mwifiex_deauthenticate(priv, NULL); if (ret) goto done; - if (bss_desc) { - u8 config_bands = 0; + if (!bss_desc) + return -1; - if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) - == HostCmd_SCAN_RADIO_TYPE_BG) - config_bands = BAND_B | BAND_G | BAND_GN | - BAND_GAC; - else - config_bands = BAND_A | BAND_AN | BAND_AAC; + if (mwifiex_band_to_radio_type(bss_desc->bss_band) == + HostCmd_SCAN_RADIO_TYPE_BG) + config_bands = BAND_B | BAND_G | BAND_GN | BAND_GAC; + else + config_bands = BAND_A | BAND_AN | BAND_AAC; - if (!((config_bands | adapter->fw_bands) & - ~adapter->fw_bands)) - adapter->config_bands = config_bands; - } + if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) + adapter->config_bands = config_bands; ret = mwifiex_check_network_compatibility(priv, bss_desc); if (ret) -- GitLab From 86a9c4a28b2c1a367d340db53570ebea02f33fca Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 19 Jun 2013 13:35:31 +0200 Subject: [PATCH 1460/2900] brcm80211: fix null pointer access Do not unconditionally access the chan variable in brcmf_cfg80211_mgmt_tx() as it may be NULL. Use freq instead. Introduced by c2ff8cad64233b539c71a27e2a6e324001143ef0 ("brcm80211: make mgmt_tx in brcmfmac accept a NULL channel") Reported-by: Dan Carpenter Signed-off-by: Antonio Quartulli Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 71f4db5fde99..277b37ae7126 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4050,8 +4050,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, le16_to_cpu(action_frame->len)); brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n", - *cookie, le16_to_cpu(action_frame->len), - chan->center_freq); + *cookie, le16_to_cpu(action_frame->len), freq); ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg), af_params); -- GitLab From 2a7305c88d245f104c3d6bd3babafb029fd07477 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 19 Jun 2013 08:49:05 -0700 Subject: [PATCH 1461/2900] mwifiex: add basic 11h support for station This patch adds code to parse requested AP's 11h capabilities and add 11h information in association request. Also, deauth is sent to the AP after receiving channel switch announcement event from firmware. This happens when AP advertises WLAN_EID_CHANNEL_SWITCH IE in it's beacon. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Paul Stewart Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11h.c | 101 +++++++++++++++++++++++ drivers/net/wireless/mwifiex/Makefile | 1 + drivers/net/wireless/mwifiex/fw.h | 14 ++++ drivers/net/wireless/mwifiex/join.c | 2 + drivers/net/wireless/mwifiex/main.h | 7 ++ drivers/net/wireless/mwifiex/scan.c | 19 +++++ drivers/net/wireless/mwifiex/sta_event.c | 8 ++ drivers/net/wireless/mwifiex/sta_ioctl.c | 3 + 8 files changed, 155 insertions(+) create mode 100644 drivers/net/wireless/mwifiex/11h.c diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c new file mode 100644 index 000000000000..8d683070bdb3 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11h.c @@ -0,0 +1,101 @@ +/* + * Marvell Wireless LAN device driver: 802.11h + * + * Copyright (C) 2013, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +#include "main.h" +#include "fw.h" + + +/* This function appends 11h info to a buffer while joining an + * infrastructure BSS + */ +static void +mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, + struct mwifiex_bssdescriptor *bss_desc) +{ + struct mwifiex_ie_types_header *ie_header; + struct mwifiex_ie_types_pwr_capability *cap; + struct mwifiex_ie_types_local_pwr_constraint *constraint; + struct ieee80211_supported_band *sband; + u8 radio_type; + int i; + + if (!buffer || !(*buffer)) + return; + + radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); + sband = priv->wdev->wiphy->bands[radio_type]; + + cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; + cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); + cap->header.len = cpu_to_le16(2); + cap->min_pwr = 0; + cap->max_pwr = 0; + *buffer += sizeof(*cap); + + constraint = (struct mwifiex_ie_types_local_pwr_constraint *)*buffer; + constraint->header.type = cpu_to_le16(WLAN_EID_PWR_CONSTRAINT); + constraint->header.len = cpu_to_le16(2); + constraint->chan = bss_desc->channel; + constraint->constraint = bss_desc->local_constraint; + *buffer += sizeof(*constraint); + + ie_header = (struct mwifiex_ie_types_header *)*buffer; + ie_header->type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ie_header->len = cpu_to_le16(2 * sband->n_channels + 2); + *buffer += sizeof(*ie_header); + *(*buffer)++ = WLAN_EID_SUPPORTED_CHANNELS; + *(*buffer)++ = 2 * sband->n_channels; + for (i = 0; i < sband->n_channels; i++) { + *(*buffer)++ = ieee80211_frequency_to_channel( + sband->channels[i].center_freq); + *(*buffer)++ = 1; /* one channel in the subband */ + } +} + +/* Enable or disable the 11h extensions in the firmware */ +static int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) +{ + u32 enable = flag; + + return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, DOT11H_I, &enable); +} + +/* This functions processes TLV buffer for a pending BSS Join command. + * + * Activate 11h functionality in the firmware if the spectrum management + * capability bit is found in the network we are joining. Also, necessary + * TLVs are set based on requested network's 11h capability. + */ +void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, + struct mwifiex_bssdescriptor *bss_desc) +{ + if (bss_desc->sensed_11h) { + /* Activate 11h functions in firmware, turns on capability + * bit + */ + mwifiex_11h_activate(priv, true); + bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; + mwifiex_11h_process_infra_join(priv, buffer, bss_desc); + } else { + /* Deactivate 11h functions in the firmware */ + mwifiex_11h_activate(priv, false); + bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; + } +} diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index ecf28464367f..a42a506fd32b 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile @@ -40,6 +40,7 @@ mwifiex-y += sta_rx.o mwifiex-y += uap_txrx.o mwifiex-y += cfg80211.o mwifiex-y += ethtool.o +mwifiex-y += 11h.o mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o obj-$(CONFIG_MWIFIEX) += mwifiex.o diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index d6ada7354c14..b6fbbf64cf96 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -438,6 +438,7 @@ enum P2P_MODES { #define EVENT_BW_CHANGE 0x00000048 #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c #define EVENT_HOSTWAKE_STAIE 0x0000004d +#define EVENT_CHANNEL_SWITCH_ANN 0x00000050 #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_ID_MASK 0xffff @@ -975,6 +976,7 @@ enum SNMP_MIB_INDEX { LONG_RETRY_LIM_I = 7, FRAG_THRESH_I = 8, DOT11D_I = 9, + DOT11H_I = 10, }; #define MAX_SNMP_BUF_SIZE 128 @@ -1206,6 +1208,18 @@ struct host_cmd_ds_sta_deauth { __le16 reason; } __packed; +struct mwifiex_ie_types_pwr_capability { + struct mwifiex_ie_types_header header; + s8 min_pwr; + s8 max_pwr; +}; + +struct mwifiex_ie_types_local_pwr_constraint { + struct mwifiex_ie_types_header header; + u8 chan; + u8 constraint; +}; + struct mwifiex_ie_types_wmm_param_set { struct mwifiex_ie_types_header header; u8 wmm_ie[1]; diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 122175af18c6..1c8a771e8e81 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -534,6 +534,8 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); + mwifiex_11h_process_join(priv, &pos, bss_desc); + cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); /* Set the Capability info at last */ diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 0832c2437daf..95a6f5269c6c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -309,6 +309,9 @@ struct mwifiex_bssdescriptor { u16 wapi_offset; u8 *beacon_buf; u32 beacon_buf_size; + u8 sensed_11h; + u8 local_constraint; + u8 chan_sw_ie_present; }; struct mwifiex_current_bss_params { @@ -1119,6 +1122,10 @@ u8 *mwifiex_11d_code_2_region(u8 code); void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, struct mwifiex_sta_node *node); +void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, + struct mwifiex_bssdescriptor *bss_desc); +int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); + extern const struct ethtool_ops mwifiex_ethtool_ops; #ifdef CONFIG_DEBUG_FS diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 801b6b728379..284d68bf6acc 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -391,6 +391,12 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, return 0; } + if (bss_desc->chan_sw_ie_present) { + dev_err(adapter->dev, + "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n"); + return -1; + } + if (mwifiex_is_bss_wapi(priv, bss_desc)) { dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); return 0; @@ -1169,6 +1175,19 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, bss_entry->erp_flags = *(current_ptr + 2); break; + case WLAN_EID_PWR_CONSTRAINT: + bss_entry->local_constraint = *(current_ptr + 2); + bss_entry->sensed_11h = true; + break; + + case WLAN_EID_CHANNEL_SWITCH: + bss_entry->chan_sw_ie_present = true; + case WLAN_EID_PWR_CAPABILITY: + case WLAN_EID_TPC_REPORT: + case WLAN_EID_QUIET: + bss_entry->sensed_11h = true; + break; + case WLAN_EID_EXT_SUPP_RATES: /* * Only process extended supported rate diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 41aafc7454ed..d28c92005cce 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -427,6 +427,14 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) break; + case EVENT_CHANNEL_SWITCH_ANN: + dev_dbg(adapter->dev, "event: Channel Switch Announcement\n"); + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_802_11_DEAUTHENTICATE, + HostCmd_ACT_GEN_SET, 0, + priv->curr_bss_params.bss_descriptor.mac_address); + break; + default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 15b5457fa4e5..498add76a46d 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -178,6 +178,9 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, */ bss_desc->disable_11ac = true; + if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT) + bss_desc->sensed_11h = true; + return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); } -- GitLab From b887664d882ee4f6a67e0bf05e5f141d32fcc067 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 18 Jun 2013 16:36:58 -0700 Subject: [PATCH 1462/2900] mwifiex: channel switch handling for station After receiving channel switch announcement from AP, scan and association on that channel is blocked for DFS_CHAN_MOVE_TIME (10 seconds). Hence station will be able to connect to the AP, once it is moved to new channel. Signed-off-by: Amitkumar Karwar Signed-off-by: Bing Zhao Signed-off-by: Paul Stewart Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 2 ++ drivers/net/wireless/mwifiex/init.c | 3 +++ drivers/net/wireless/mwifiex/main.h | 20 ++++++++++++++++++++ drivers/net/wireless/mwifiex/scan.c | 18 ++++++++++++++++++ drivers/net/wireless/mwifiex/sta_event.c | 3 +++ drivers/net/wireless/mwifiex/sta_ioctl.c | 8 ++++++++ 6 files changed, 54 insertions(+) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b6fbbf64cf96..1b45aa533300 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -245,6 +245,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HT_BW_20 0 #define HT_BW_40 1 +#define DFS_CHAN_MOVE_TIME 10000 + #define HostCmd_CMD_GET_HW_SPEC 0x0003 #define HostCmd_CMD_802_11_SCAN 0x0006 #define HostCmd_CMD_802_11_GET_LOG 0x000b diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 2fe31dcaa6ef..caaf4bd56b30 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -133,6 +133,9 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->scan_block = false; + priv->csa_chan = 0; + priv->csa_expire_time = 0; + return mwifiex_add_bss_prio_tbl(priv); } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 95a6f5269c6c..3da73d36acdf 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -513,6 +513,8 @@ struct mwifiex_private { u32 mgmt_frame_mask; struct mwifiex_roc_cfg roc_cfg; bool scan_aborting; + u8 csa_chan; + unsigned long csa_expire_time; }; enum mwifiex_ba_status { @@ -1021,6 +1023,24 @@ static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) return (*(u32 *)skb->data == PKT_TYPE_MGMT); } +/* This function retrieves channel closed for operation by Channel + * Switch Announcement. + */ +static inline u8 +mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv) +{ + if (!priv->csa_chan) + return 0; + + /* Clear csa channel, if DFS channel move time has passed */ + if (jiffies > priv->csa_expire_time) { + priv->csa_chan = 0; + priv->csa_expire_time = 0; + } + + return priv->csa_chan; +} + int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, u32 func_init_shutdown); int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 284d68bf6acc..c447d9bd1aa9 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -575,6 +575,9 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, return -1; } + /* Check csa channel expiry before preparing scan list */ + mwifiex_11h_get_csa_closed_channel(priv); + chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); /* Set the temp channel struct pointer to the start of the desired @@ -604,6 +607,11 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, while (tlv_idx < max_chan_per_scan && tmp_chan_list->chan_number && !done_early) { + if (tmp_chan_list->chan_number == priv->csa_chan) { + tmp_chan_list++; + continue; + } + dev_dbg(priv->adapter->dev, "info: Scan: Chan(%3d), Radio(%d)," " Mode(%d, %d), Dur(%d)\n", @@ -1594,6 +1602,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, goto check_next_scan; } + /* Check csa channel expiry before parsing scan response */ + mwifiex_11h_get_csa_closed_channel(priv); + bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); dev_dbg(adapter->dev, "info: SCAN_RESP: bss_descript_size %d\n", bytes_left); @@ -1746,6 +1757,13 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, struct ieee80211_channel *chan; u8 band; + /* Skip entry if on csa closed channel */ + if (channel == priv->csa_chan) { + dev_dbg(adapter->dev, + "Dropping entry on csa closed channel\n"); + continue; + } + band = BAND_G; if (chan_band_tlv) { chan_band = diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index d28c92005cce..ea265ec0e522 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -429,6 +429,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_CHANNEL_SWITCH_ANN: dev_dbg(adapter->dev, "event: Channel Switch Announcement\n"); + priv->csa_expire_time = + jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); + priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel; ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, HostCmd_ACT_GEN_SET, 0, diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 498add76a46d..206c3e038072 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -281,6 +281,14 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, if (ret) goto done; + if (mwifiex_11h_get_csa_closed_channel(priv) == + (u8)bss_desc->channel) { + dev_err(adapter->dev, + "Attempt to reconnect on csa closed chan(%d)\n", + bss_desc->channel); + goto done; + } + dev_dbg(adapter->dev, "info: SSID found in scan list ... " "associating...\n"); -- GitLab From e12d0271774fea9fddf1e2a7952a0bffb2ee8e8b Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 10 May 2013 17:12:28 -0400 Subject: [PATCH 1463/2900] nohz: Warn if the machine can not perform nohz_full If the user configures NO_HZ_FULL and defines nohz_full=XXX on the kernel command line, or enables NO_HZ_FULL_ALL, but nohz fails due to the machine having a unstable clock, warn about it. We do not want users thinking that they are getting the benefit of nohz when their machine can not support it. Signed-off-by: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Andrew Morton Cc: Thomas Gleixner Cc: H. Peter Anvin Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Li Zhong Signed-off-by: Frederic Weisbecker --- kernel/time/tick-sched.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f4208138fbf4..d87d22cb9bf2 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -178,6 +178,11 @@ static bool can_stop_full_tick(void) */ if (!sched_clock_stable) { trace_tick_stop(0, "unstable sched clock\n"); + /* + * Don't allow the user to think they can get + * full NO_HZ with this machine. + */ + WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock"); return false; } #endif -- GitLab From b8900bc0217fac8e68085997bee2f05e6db931a2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 6 Jun 2013 15:42:53 +0200 Subject: [PATCH 1464/2900] watchdog: Register / unregister watchdog kthreads on sysctl control The user activation/deactivation of the watchdog through boot parameters or systcl is currently implemented with a dance involving kthreads parking and unparking methods: the threads are unconditionally registered on boot and they park as soon as the user want the watchdog to be disabled. This method involves a few noisy details to handle though: the watchdog kthreads may be unparked anytime due to hotplug operations, after which the watchdog internals have to decide to park again if it is user-disabled. As a result the setup() and unpark() methods need to be able to request a reparking. This is not currently supported in the kthread infrastructure so this piece of the watchdog code only works halfway. Besides, unparking/reparking the watchdog kthreads consume unnecessary cputime on hotplug operations when those could be simply ignored in the first place. As suggested by Srivatsa, let's instead only register the watchdog threads when they are needed. This way we don't need to think about hotplug operations and we don't burden the CPU onlining when the watchdog is simply disabled. Suggested-by: Srivatsa S. Bhat Signed-off-by: Frederic Weisbecker Cc: Srivatsa S. Bhat Cc: Anish Singh Cc: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Li Zhong Cc: Don Zickus --- kernel/watchdog.c | 87 +++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 05039e348f07..52c9a9b91bdd 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -31,7 +31,7 @@ int watchdog_enabled = 1; int __read_mostly watchdog_thresh = 10; -static int __read_mostly watchdog_disabled; +static int __read_mostly watchdog_disabled = 1; static u64 __read_mostly sample_period; static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); @@ -347,11 +347,6 @@ static void watchdog_enable(unsigned int cpu) hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer->function = watchdog_timer_fn; - if (!watchdog_enabled) { - kthread_park(current); - return; - } - /* Enable the perf event */ watchdog_nmi_enable(cpu); @@ -374,6 +369,11 @@ static void watchdog_disable(unsigned int cpu) watchdog_nmi_disable(cpu); } +static void watchdog_cleanup(unsigned int cpu, bool online) +{ + watchdog_disable(cpu); +} + static int watchdog_should_run(unsigned int cpu) { return __this_cpu_read(hrtimer_interrupts) != @@ -475,28 +475,40 @@ static int watchdog_nmi_enable(unsigned int cpu) { return 0; } static void watchdog_nmi_disable(unsigned int cpu) { return; } #endif /* CONFIG_HARDLOCKUP_DETECTOR */ -/* prepare/enable/disable routines */ -/* sysctl functions */ -#ifdef CONFIG_SYSCTL -static void watchdog_enable_all_cpus(void) +static struct smp_hotplug_thread watchdog_threads = { + .store = &softlockup_watchdog, + .thread_should_run = watchdog_should_run, + .thread_fn = watchdog, + .thread_comm = "watchdog/%u", + .setup = watchdog_enable, + .cleanup = watchdog_cleanup, + .park = watchdog_disable, + .unpark = watchdog_enable, +}; + +static int watchdog_enable_all_cpus(void) { - unsigned int cpu; + int err = 0; if (watchdog_disabled) { - watchdog_disabled = 0; - for_each_online_cpu(cpu) - kthread_unpark(per_cpu(softlockup_watchdog, cpu)); + err = smpboot_register_percpu_thread(&watchdog_threads); + if (err) + pr_err("Failed to create watchdog threads, disabled\n"); + else + watchdog_disabled = 0; } + + return err; } +/* prepare/enable/disable routines */ +/* sysctl functions */ +#ifdef CONFIG_SYSCTL static void watchdog_disable_all_cpus(void) { - unsigned int cpu; - if (!watchdog_disabled) { watchdog_disabled = 1; - for_each_online_cpu(cpu) - kthread_park(per_cpu(softlockup_watchdog, cpu)); + smpboot_unregister_percpu_thread(&watchdog_threads); } } @@ -507,14 +519,14 @@ static void watchdog_disable_all_cpus(void) int proc_dowatchdog(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - int ret; + int err, old_thresh, old_enabled; - if (watchdog_disabled < 0) - return -ENODEV; + old_thresh = ACCESS_ONCE(watchdog_thresh); + old_enabled = ACCESS_ONCE(watchdog_enabled); - ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); - if (ret || !write) - return ret; + err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + if (err || !write) + return err; set_sample_period(); /* @@ -523,29 +535,24 @@ int proc_dowatchdog(struct ctl_table *table, int write, * watchdog_*_all_cpus() function takes care of this. */ if (watchdog_enabled && watchdog_thresh) - watchdog_enable_all_cpus(); + err = watchdog_enable_all_cpus(); else watchdog_disable_all_cpus(); - return ret; + /* Restore old values on failure */ + if (err) { + watchdog_thresh = old_thresh; + watchdog_enabled = old_enabled; + } + + return err; } #endif /* CONFIG_SYSCTL */ -static struct smp_hotplug_thread watchdog_threads = { - .store = &softlockup_watchdog, - .thread_should_run = watchdog_should_run, - .thread_fn = watchdog, - .thread_comm = "watchdog/%u", - .setup = watchdog_enable, - .park = watchdog_disable, - .unpark = watchdog_enable, -}; - void __init lockup_detector_init(void) { set_sample_period(); - if (smpboot_register_percpu_thread(&watchdog_threads)) { - pr_err("Failed to create watchdog threads, disabled\n"); - watchdog_disabled = -ENODEV; - } + + if (watchdog_enabled) + watchdog_enable_all_cpus(); } -- GitLab From ea7d69e75ac06daa7bc2fca2a8317197e5e3c81c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 19 Jun 2013 23:29:23 +0400 Subject: [PATCH 1465/2900] sh_eth: define/use EESR_RX_CHECK macro sh_eth_interrupt() uses the same Rx interrupt mask twice to check the interrupt status register -- #define EESR_RX_CHECK and use it instead. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 13 ++----------- drivers/net/ethernet/renesas/sh_eth.h | 8 ++++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 8cb600ccaf1d..cd5987ecee4b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1504,23 +1504,14 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) */ intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI; /* Clear interrupt */ - if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | - EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | - cd->tx_check | cd->eesr_err_check)) { + if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) { sh_eth_write(ndev, intr_status, EESR); ret = IRQ_HANDLED; } else goto other_irq; - if (intr_status & (EESR_FRC | /* Frame recv*/ - EESR_RMAF | /* Multi cast address recv*/ - EESR_RRF | /* Bit frame recv */ - EESR_RTLF | /* Long frame recv*/ - EESR_RTSF | /* short frame recv */ - EESR_PRE | /* PHY-LSI recv error */ - EESR_CERF)){ /* recv frame CRC error */ + if (intr_status & EESR_RX_CHECK) sh_eth_rx(ndev, intr_status); - } /* Tx Check */ if (intr_status & cd->tx_check) { diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 729e77e66f19..d05b60b826eb 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -248,6 +248,14 @@ enum EESR_BIT { EESR_CERF = 0x00000001, }; +#define EESR_RX_CHECK (EESR_FRC | /* Frame recv */ \ + EESR_RMAF | /* Multicast address recv */ \ + EESR_RRF | /* Bit frame recv */ \ + EESR_RTLF | /* Long frame recv */ \ + EESR_RTSF | /* Short frame recv */ \ + EESR_PRE | /* PHY-LSI recv error */ \ + EESR_CERF) /* Recv frame CRC error */ + #define DEFAULT_TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | \ EESR_RTO) #define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | \ -- GitLab From 3719109d61ca96746c733538ec776d02a6952640 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 19 Jun 2013 23:30:23 +0400 Subject: [PATCH 1466/2900] sh_eth: add NAPI support The driver hasn't used NAPI so far; implement its support at last... The patch was tested on Renesas R8A77781 BOCK-W board. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 85 +++++++++++++++++++++++---- drivers/net/ethernet/renesas/sh_eth.h | 1 + 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index cd5987ecee4b..5233edab2dd5 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1244,7 +1244,7 @@ static int sh_eth_txfree(struct net_device *ndev) } /* Packet receive function */ -static int sh_eth_rx(struct net_device *ndev, u32 intr_status) +static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) { struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_rxdesc *rxdesc; @@ -1252,6 +1252,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) int entry = mdp->cur_rx % mdp->num_rx_ring; int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx; struct sk_buff *skb; + int exceeded = 0; u16 pkt_len = 0; u32 desc_status; @@ -1263,6 +1264,12 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) if (--boguscnt < 0) break; + if (*quota <= 0) { + exceeded = 1; + break; + } + (*quota)--; + if (!(desc_status & RDFEND)) ndev->stats.rx_length_errors++; @@ -1350,7 +1357,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status) sh_eth_write(ndev, EDRRR_R, EDRRR); } - return 0; + return exceeded; } static void sh_eth_rcv_snd_disable(struct net_device *ndev) @@ -1491,7 +1498,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_cpu_data *cd = mdp->cd; irqreturn_t ret = IRQ_NONE; - unsigned long intr_status; + unsigned long intr_status, intr_enable; spin_lock(&mdp->lock); @@ -1502,25 +1509,41 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) * and we need to fully handle it in sh_eth_error() in order to quench * it as it doesn't get cleared by just writing 1 to the ECI bit... */ - intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI; - /* Clear interrupt */ - if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) { - sh_eth_write(ndev, intr_status, EESR); + intr_enable = sh_eth_read(ndev, EESIPR); + intr_status &= intr_enable | DMAC_M_ECI; + if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) ret = IRQ_HANDLED; - } else + else goto other_irq; - if (intr_status & EESR_RX_CHECK) - sh_eth_rx(ndev, intr_status); + if (intr_status & EESR_RX_CHECK) { + if (napi_schedule_prep(&mdp->napi)) { + /* Mask Rx interrupts */ + sh_eth_write(ndev, intr_enable & ~EESR_RX_CHECK, + EESIPR); + __napi_schedule(&mdp->napi); + } else { + dev_warn(&ndev->dev, + "ignoring interrupt, status 0x%08lx, mask 0x%08lx.\n", + intr_status, intr_enable); + } + } /* Tx Check */ if (intr_status & cd->tx_check) { + /* Clear Tx interrupts */ + sh_eth_write(ndev, intr_status & cd->tx_check, EESR); + sh_eth_txfree(ndev); netif_wake_queue(ndev); } - if (intr_status & cd->eesr_err_check) + if (intr_status & cd->eesr_err_check) { + /* Clear error interrupts */ + sh_eth_write(ndev, intr_status & cd->eesr_err_check, EESR); + sh_eth_error(ndev, intr_status); + } other_irq: spin_unlock(&mdp->lock); @@ -1528,6 +1551,33 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) return ret; } +static int sh_eth_poll(struct napi_struct *napi, int budget) +{ + struct sh_eth_private *mdp = container_of(napi, struct sh_eth_private, + napi); + struct net_device *ndev = napi->dev; + int quota = budget; + unsigned long intr_status; + + for (;;) { + intr_status = sh_eth_read(ndev, EESR); + if (!(intr_status & EESR_RX_CHECK)) + break; + /* Clear Rx interrupts */ + sh_eth_write(ndev, intr_status & EESR_RX_CHECK, EESR); + + if (sh_eth_rx(ndev, intr_status, "a)) + goto out; + } + + napi_complete(napi); + + /* Reenable Rx interrupts */ + sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); +out: + return budget - quota; +} + /* PHY state control function */ static void sh_eth_adjust_link(struct net_device *ndev) { @@ -1839,6 +1889,8 @@ static int sh_eth_open(struct net_device *ndev) if (ret) goto out_free_irq; + napi_enable(&mdp->napi); + return ret; out_free_irq: @@ -1934,6 +1986,8 @@ static int sh_eth_close(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); + napi_disable(&mdp->napi); + netif_stop_queue(ndev); /* Disable interrupts by clearing the interrupt mask. */ @@ -2623,10 +2677,12 @@ static int sh_eth_drv_probe(struct platform_device *pdev) } } + netif_napi_add(ndev, &mdp->napi, sh_eth_poll, 64); + /* network device register */ ret = register_netdev(ndev); if (ret) - goto out_release; + goto out_napi_del; /* mdio bus init */ ret = sh_mdio_init(ndev, pdev->id, pd); @@ -2644,6 +2700,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev) out_unregister: unregister_netdev(ndev); +out_napi_del: + netif_napi_del(&mdp->napi); + out_release: /* net_dev free */ if (ndev) @@ -2656,9 +2715,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev) static int sh_eth_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct sh_eth_private *mdp = netdev_priv(ndev); sh_mdio_release(ndev); unregister_netdev(ndev); + netif_napi_del(&mdp->napi); pm_runtime_disable(&pdev->dev); free_netdev(ndev); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index d05b60b826eb..029744f77af6 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -505,6 +505,7 @@ struct sh_eth_private { u32 cur_tx, dirty_tx; u32 rx_buf_sz; /* Based on MTU+slack. */ int edmac_endian; + struct napi_struct napi; /* MII transceiver section. */ u32 phy_id; /* PHY ID */ struct mii_bus *mii_bus; /* MDIO bus control */ -- GitLab From 8f80899665c4baca5fe18e919a18db818c3e11fa Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Jun 2013 02:22:56 +0400 Subject: [PATCH 1467/2900] sh_eth: remove 'tx_error_check' field of 'struct sh_eth_cpu_data' The 'tx_error_check' field of 'struct sh_eth_cpu_data' is write-only, so remove it along with the DEFAULT_TX_ERROR_CHECK macro. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 14 -------------- drivers/net/ethernet/renesas/sh_eth.h | 3 --- 2 files changed, 17 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 5233edab2dd5..9a8b24e513ca 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -384,7 +384,6 @@ static struct sh_eth_cpu_data r8a777x_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, - .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, .apr = 1, .mpr = 1, @@ -420,7 +419,6 @@ static struct sh_eth_cpu_data sh7724_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, - .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, .apr = 1, .mpr = 1, @@ -457,7 +455,6 @@ static struct sh_eth_cpu_data sh7757_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, - .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, .irq_flags = IRQF_SHARED, .apr = 1, @@ -527,8 +524,6 @@ static struct sh_eth_cpu_data sh7757_data_giga = { .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ EESR_ECI, - .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ - EESR_TFE, .fdr_value = 0x0000072f, .rmcr_value = 0x00000001, @@ -587,8 +582,6 @@ static struct sh_eth_cpu_data sh7734_data = { .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ EESR_ECI, - .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ - EESR_TFE, .apr = 1, .mpr = 1, @@ -616,8 +609,6 @@ static struct sh_eth_cpu_data sh7763_data = { .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ EESR_ECI, - .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ - EESR_TFE, .apr = 1, .mpr = 1, @@ -655,8 +646,6 @@ static struct sh_eth_cpu_data r8a7740_data = { .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ EESR_ECI, - .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ - EESR_TFE, .apr = 1, .mpr = 1, @@ -706,9 +695,6 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd) if (!cd->eesr_err_check) cd->eesr_err_check = DEFAULT_EESR_ERR_CHECK; - - if (!cd->tx_error_check) - cd->tx_error_check = DEFAULT_TX_ERROR_CHECK; } static int sh_eth_check_reset(struct net_device *ndev) diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 029744f77af6..87c7ae9e10cc 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -261,8 +261,6 @@ enum EESR_BIT { #define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | \ EESR_RDE | EESR_RFRMER | EESR_ADE | \ EESR_TFE | EESR_TDE | EESR_ECI) -#define DEFAULT_TX_ERROR_CHECK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | \ - EESR_TFE) /* EESIPR */ enum DMAC_IM_BIT { @@ -468,7 +466,6 @@ struct sh_eth_cpu_data { /* interrupt checking mask */ unsigned long tx_check; unsigned long eesr_err_check; - unsigned long tx_error_check; /* hardware features */ unsigned long irq_flags; /* IRQ configuration flags */ -- GitLab From a80c3de714bc4855747faf5f00e8203fb800e6bb Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Jun 2013 02:24:54 +0400 Subject: [PATCH 1468/2900] sh_eth: remove redundant bits from 'eesipr_value' field initializer For SH7724 'eesipr_value' field initializer includes DMAC_M_RFRMER & DMAC_M_ECI bits which are already contained in 0x01ff009f -- remove them. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 9a8b24e513ca..4b4c586d2c4f 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -414,7 +414,7 @@ static struct sh_eth_cpu_data sh7724_data = { .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD, .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP, - .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x01ff009f, + .eesipr_value = 0x01ff009f, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | -- GitLab From c8bbe37aa60a3ef694df65fed4e905bd4b1bd73c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 20 Jun 2013 02:26:14 +0400 Subject: [PATCH 1469/2900] sh_eth: cleanup 'enum TD_STS_BIT' Fix the comment to 'enum TD_STS_BIT', reformat the values, and add a couple of values missing before (though unused by the driver). Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 87c7ae9e10cc..7540dc35fdb8 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -302,11 +302,11 @@ enum FCFTR_BIT { #define DEFAULT_FIFO_F_D_RFF (FCFTR_RFF2 | FCFTR_RFF1 | FCFTR_RFF0) #define DEFAULT_FIFO_F_D_RFD (FCFTR_RFD2 | FCFTR_RFD1 | FCFTR_RFD0) -/* Transfer descriptor bit */ +/* Transmit descriptor bit */ enum TD_STS_BIT { - TD_TACT = 0x80000000, - TD_TDLE = 0x40000000, TD_TFP1 = 0x20000000, - TD_TFP0 = 0x10000000, + TD_TACT = 0x80000000, TD_TDLE = 0x40000000, + TD_TFP1 = 0x20000000, TD_TFP0 = 0x10000000, + TD_TFE = 0x08000000, TD_TWBI = 0x04000000, }; #define TDF1ST TD_TFP1 #define TDFEND TD_TFP0 -- GitLab From ac8025a643a0e0beb81f3f37ca693364c6b77858 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 13 Jun 2013 22:12:45 +0400 Subject: [PATCH 1470/2900] sh_eth: get R8A7740 Rx descriptor word 0 shift out of #ifdef The only R8A7740 specific #ifdef hindering ARM multiplatform build is left in sh_eth_rx(): it covers the code shifting Rx buffer descriptor word 0 by 16. Get rid of the #ifdef by adding 'shift_rd0' field to the 'struct sh_eth_cpu_data', making the shift dependent on it, and setting it to 1 for the R8A7740 case... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 6 +++--- drivers/net/ethernet/renesas/sh_eth.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 4b4c586d2c4f..7732f11f14ad 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -656,6 +656,7 @@ static struct sh_eth_cpu_data r8a7740_data = { .no_ade = 1, .tsu = 1, .select_mii = 1, + .shift_rd0 = 1, }; static struct sh_eth_cpu_data sh7619_data = { @@ -1259,7 +1260,6 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) if (!(desc_status & RDFEND)) ndev->stats.rx_length_errors++; -#if defined(CONFIG_ARCH_R8A7740) /* * In case of almost all GETHER/ETHERs, the Receive Frame State * (RFS) bits in the Receive Descriptor 0 are from bit 9 to @@ -1267,8 +1267,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) * bits are from bit 25 to bit 16. So, the driver needs right * shifting by 16. */ - desc_status >>= 16; -#endif + if (mdp->cd->shift_rd0) + desc_status >>= 16; if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 | RD_RFS5 | RD_RFS6 | RD_RFS10)) { diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 7540dc35fdb8..a78fb0c424f8 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -481,6 +481,7 @@ struct sh_eth_cpu_data { unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */ unsigned hw_crc:1; /* E-DMAC have CSMR */ unsigned select_mii:1; /* EtherC have RMII_MII (MII select register) */ + unsigned shift_rd0:1; /* shift Rx descriptor word 0 right by 16 */ }; struct sh_eth_private { -- GitLab From 20fd4d1f04da07d09192ad8ad366a70d5125bfaf Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:49:32 -0700 Subject: [PATCH 1471/2900] gre: Simplify gre protocol registration locking. Use cmpxchg() for atomic protocol registration which saves code and data space. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/ipv4/gre.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index b2e805af9b87..1e294d510ac3 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -26,46 +26,32 @@ static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; -static DEFINE_SPINLOCK(gre_proto_lock); int gre_add_protocol(const struct gre_protocol *proto, u8 version) { if (version >= GREPROTO_MAX) - goto err_out; - - spin_lock(&gre_proto_lock); - if (gre_proto[version]) - goto err_out_unlock; - - RCU_INIT_POINTER(gre_proto[version], proto); - spin_unlock(&gre_proto_lock); - return 0; + return -EINVAL; -err_out_unlock: - spin_unlock(&gre_proto_lock); -err_out: - return -1; + return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? + 0 : -EBUSY; } EXPORT_SYMBOL_GPL(gre_add_protocol); int gre_del_protocol(const struct gre_protocol *proto, u8 version) { + int ret; + if (version >= GREPROTO_MAX) - goto err_out; - - spin_lock(&gre_proto_lock); - if (rcu_dereference_protected(gre_proto[version], - lockdep_is_held(&gre_proto_lock)) != proto) - goto err_out_unlock; - RCU_INIT_POINTER(gre_proto[version], NULL); - spin_unlock(&gre_proto_lock); + return -EINVAL; + + ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ? + 0 : -EBUSY; + + if (ret) + return ret; + synchronize_rcu(); return 0; - -err_out_unlock: - spin_unlock(&gre_proto_lock); -err_out: - return -1; } EXPORT_SYMBOL_GPL(gre_del_protocol); -- GitLab From bda7bb46343647f68591366731295a0f3eea59ed Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:49:38 -0700 Subject: [PATCH 1472/2900] gre: Allow multiple protocol listener for gre protocol. Currently there is only one user is allowed to register for gre protocol. Following patch adds de-multiplexer. So that multiple modules can listen on gre protocol e.g. kernel gre devices and ovs. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/gre.h | 24 +++++ net/ipv4/gre.c | 221 +++++++++++++++++++++++++++++++++++++++++++++- net/ipv4/ip_gre.c | 173 ++++++------------------------------ 3 files changed, 267 insertions(+), 151 deletions(-) diff --git a/include/net/gre.h b/include/net/gre.h index 9f03a390c826..c6ea0c72c605 100644 --- a/include/net/gre.h +++ b/include/net/gre.h @@ -7,6 +7,7 @@ #define GREPROTO_CISCO 0 #define GREPROTO_PPTP 1 #define GREPROTO_MAX 2 +#define GRE_IP_PROTO_MAX 2 struct gre_protocol { int (*handler)(struct sk_buff *skb); @@ -22,6 +23,29 @@ struct gre_base_hdr { int gre_add_protocol(const struct gre_protocol *proto, u8 version); int gre_del_protocol(const struct gre_protocol *proto, u8 version); +struct gre_cisco_protocol { + int (*handler)(struct sk_buff *skb, const struct tnl_ptk_info *tpi); + int (*err_handler)(struct sk_buff *skb, u32 info, + const struct tnl_ptk_info *tpi); + u8 priority; +}; + +int gre_cisco_register(struct gre_cisco_protocol *proto); +int gre_cisco_unregister(struct gre_cisco_protocol *proto); + +static inline int ip_gre_calc_hlen(__be16 o_flags) +{ + int addend = 4; + + if (o_flags&TUNNEL_CSUM) + addend += 4; + if (o_flags&TUNNEL_KEY) + addend += 4; + if (o_flags&TUNNEL_SEQ) + addend += 4; + return addend; +} + static inline __be16 gre_flags_to_tnl_flags(__be16 flags) { __be16 tflags = 0; diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 1e294d510ac3..8b9a373890ab 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -13,6 +13,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include +#include #include #include #include @@ -24,8 +26,12 @@ #include #include +#include +#include +#include static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; +static struct gre_cisco_protocol __rcu *gre_cisco_proto_list[GRE_IP_PROTO_MAX]; int gre_add_protocol(const struct gre_protocol *proto, u8 version) { @@ -55,6 +61,173 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) } EXPORT_SYMBOL_GPL(gre_del_protocol); +static __sum16 check_checksum(struct sk_buff *skb) +{ + __sum16 csum = 0; + + switch (skb->ip_summed) { + case CHECKSUM_COMPLETE: + csum = csum_fold(skb->csum); + + if (!csum) + break; + /* Fall through. */ + + case CHECKSUM_NONE: + skb->csum = 0; + csum = __skb_checksum_complete(skb); + skb->ip_summed = CHECKSUM_COMPLETE; + break; + } + + return csum; +} + +static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool *csum_err) +{ + unsigned int ip_hlen = ip_hdrlen(skb); + const struct gre_base_hdr *greh; + __be32 *options; + int hdr_len; + + if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); + if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) + return -EINVAL; + + tpi->flags = gre_flags_to_tnl_flags(greh->flags); + hdr_len = ip_gre_calc_hlen(tpi->flags); + + if (!pskb_may_pull(skb, hdr_len)) + return -EINVAL; + + greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); + tpi->proto = greh->protocol; + + options = (__be32 *)(greh + 1); + if (greh->flags & GRE_CSUM) { + if (check_checksum(skb)) { + *csum_err = true; + return -EINVAL; + } + options++; + } + + if (greh->flags & GRE_KEY) { + tpi->key = *options; + options++; + } else + tpi->key = 0; + + if (unlikely(greh->flags & GRE_SEQ)) { + tpi->seq = *options; + options++; + } else + tpi->seq = 0; + + /* WCCP version 1 and 2 protocol decoding. + * - Change protocol to IP + * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header + */ + if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { + tpi->proto = htons(ETH_P_IP); + if ((*(u8 *)options & 0xF0) != 0x40) { + hdr_len += 4; + if (!pskb_may_pull(skb, hdr_len)) + return -EINVAL; + } + } + return 0; +} + +static int gre_cisco_rcv(struct sk_buff *skb) +{ + struct tnl_ptk_info tpi; + int i; + bool csum_err = false; + + if (parse_gre_header(skb, &tpi, &csum_err) < 0) + goto drop; + + rcu_read_lock(); + for (i = 0; i < GRE_IP_PROTO_MAX; i++) { + struct gre_cisco_protocol *proto; + int ret; + + proto = rcu_dereference(gre_cisco_proto_list[i]); + if (!proto) + continue; + ret = proto->handler(skb, &tpi); + if (ret == PACKET_RCVD) { + rcu_read_unlock(); + return 0; + } + } + rcu_read_unlock(); + + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); +drop: + kfree_skb(skb); + return 0; +} + +static void gre_cisco_err(struct sk_buff *skb, u32 info) +{ + /* All the routers (except for Linux) return only + * 8 bytes of packet payload. It means, that precise relaying of + * ICMP in the real Internet is absolutely infeasible. + * + * Moreover, Cisco "wise men" put GRE key to the third word + * in GRE header. It makes impossible maintaining even soft + * state for keyed + * GRE tunnels with enabled checksum. Tell them "thank you". + * + * Well, I wonder, rfc1812 was written by Cisco employee, + * what the hell these idiots break standards established + * by themselves??? + */ + + const int type = icmp_hdr(skb)->type; + const int code = icmp_hdr(skb)->code; + struct tnl_ptk_info tpi; + bool csum_err = false; + int i; + + if (parse_gre_header(skb, &tpi, &csum_err)) { + if (!csum_err) /* ignore csum errors. */ + return; + } + + if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { + ipv4_update_pmtu(skb, dev_net(skb->dev), info, + skb->dev->ifindex, 0, IPPROTO_GRE, 0); + return; + } + if (type == ICMP_REDIRECT) { + ipv4_redirect(skb, dev_net(skb->dev), skb->dev->ifindex, 0, + IPPROTO_GRE, 0); + return; + } + + rcu_read_lock(); + for (i = 0; i < GRE_IP_PROTO_MAX; i++) { + struct gre_cisco_protocol *proto; + + proto = rcu_dereference(gre_cisco_proto_list[i]); + if (!proto) + continue; + + if (proto->err_handler(skb, info, &tpi) == PACKET_RCVD) + goto out; + + } +out: + rcu_read_unlock(); +} + static int gre_rcv(struct sk_buff *skb) { const struct gre_protocol *proto; @@ -206,27 +379,68 @@ static const struct net_offload gre_offload = { }, }; +static const struct gre_protocol ipgre_protocol = { + .handler = gre_cisco_rcv, + .err_handler = gre_cisco_err, +}; + +int gre_cisco_register(struct gre_cisco_protocol *newp) +{ + struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **) + &gre_cisco_proto_list[newp->priority]; + + return (cmpxchg(proto, NULL, newp) == NULL) ? 0 : -EBUSY; +} +EXPORT_SYMBOL_GPL(gre_cisco_register); + +int gre_cisco_unregister(struct gre_cisco_protocol *del_proto) +{ + struct gre_cisco_protocol **proto = (struct gre_cisco_protocol **) + &gre_cisco_proto_list[del_proto->priority]; + int ret; + + ret = (cmpxchg(proto, del_proto, NULL) == del_proto) ? 0 : -EINVAL; + + if (ret) + return ret; + + synchronize_net(); + return 0; +} +EXPORT_SYMBOL_GPL(gre_cisco_unregister); + static int __init gre_init(void) { pr_info("GRE over IPv4 demultiplexor driver\n"); if (inet_add_protocol(&net_gre_protocol, IPPROTO_GRE) < 0) { pr_err("can't add protocol\n"); - return -EAGAIN; + goto err; + } + + if (gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) { + pr_info("%s: can't add ipgre handler\n", __func__); + goto err_gre; } if (inet_add_offload(&gre_offload, IPPROTO_GRE)) { pr_err("can't add protocol offload\n"); - inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); - return -EAGAIN; + goto err_gso; } return 0; +err_gso: + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); +err_gre: + inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); +err: + return -EAGAIN; } static void __exit gre_exit(void) { inet_del_offload(&gre_offload, IPPROTO_GRE); + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); } @@ -236,4 +450,3 @@ module_exit(gre_exit); MODULE_DESCRIPTION("GRE over IPv4 demultiplexer driver"); MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); MODULE_LICENSE("GPL"); - diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a982657d05e7..19863a81cea1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -121,103 +121,8 @@ static int ipgre_tunnel_init(struct net_device *dev); static int ipgre_net_id __read_mostly; static int gre_tap_net_id __read_mostly; -static __sum16 check_checksum(struct sk_buff *skb) -{ - __sum16 csum = 0; - - switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: - csum = csum_fold(skb->csum); - - if (!csum) - break; - /* Fall through. */ - - case CHECKSUM_NONE: - skb->csum = 0; - csum = __skb_checksum_complete(skb); - skb->ip_summed = CHECKSUM_COMPLETE; - break; - } - - return csum; -} - -static int ip_gre_calc_hlen(__be16 o_flags) -{ - int addend = 4; - - if (o_flags&TUNNEL_CSUM) - addend += 4; - if (o_flags&TUNNEL_KEY) - addend += 4; - if (o_flags&TUNNEL_SEQ) - addend += 4; - return addend; -} - -static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, - bool *csum_err, int *hdr_len) -{ - unsigned int ip_hlen = ip_hdrlen(skb); - const struct gre_base_hdr *greh; - __be32 *options; - - if (unlikely(!pskb_may_pull(skb, sizeof(struct gre_base_hdr)))) - return -EINVAL; - - greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); - if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) - return -EINVAL; - - tpi->flags = gre_flags_to_tnl_flags(greh->flags); - *hdr_len = ip_gre_calc_hlen(tpi->flags); - - if (!pskb_may_pull(skb, *hdr_len)) - return -EINVAL; - - greh = (struct gre_base_hdr *)(skb_network_header(skb) + ip_hlen); - - tpi->proto = greh->protocol; - - options = (__be32 *)(greh + 1); - if (greh->flags & GRE_CSUM) { - if (check_checksum(skb)) { - *csum_err = true; - return -EINVAL; - } - options++; - } - - if (greh->flags & GRE_KEY) { - tpi->key = *options; - options++; - } else - tpi->key = 0; - - if (unlikely(greh->flags & GRE_SEQ)) { - tpi->seq = *options; - options++; - } else - tpi->seq = 0; - - /* WCCP version 1 and 2 protocol decoding. - * - Change protocol to IP - * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header - */ - if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { - tpi->proto = htons(ETH_P_IP); - if ((*(u8 *)options & 0xF0) != 0x40) { - *hdr_len += 4; - if (!pskb_may_pull(skb, *hdr_len)) - return -EINVAL; - } - } - - return 0; -} - -static void ipgre_err(struct sk_buff *skb, u32 info) +static int ipgre_err(struct sk_buff *skb, u32 info, + const struct tnl_ptk_info *tpi) { /* All the routers (except for Linux) return only @@ -239,26 +144,18 @@ static void ipgre_err(struct sk_buff *skb, u32 info) const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; struct ip_tunnel *t; - struct tnl_ptk_info tpi; - int hdr_len; - bool csum_err = false; - - if (parse_gre_header(skb, &tpi, &csum_err, &hdr_len)) { - if (!csum_err) /* ignore csum errors. */ - return; - } switch (type) { default: case ICMP_PARAMETERPROB: - return; + return PACKET_RCVD; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ - return; + return PACKET_RCVD; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, @@ -269,79 +166,61 @@ static void ipgre_err(struct sk_buff *skb, u32 info) break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) - return; + return PACKET_RCVD; break; case ICMP_REDIRECT: break; } - if (tpi.proto == htons(ETH_P_TEB)) + if (tpi->proto == htons(ETH_P_TEB)) itn = net_generic(net, gre_tap_net_id); else itn = net_generic(net, ipgre_net_id); iph = (const struct iphdr *)skb->data; - t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags, - iph->daddr, iph->saddr, tpi.key); + t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, + iph->daddr, iph->saddr, tpi->key); if (t == NULL) - return; + return PACKET_REJECT; - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->parms.link, 0, IPPROTO_GRE, 0); - return; - } - if (type == ICMP_REDIRECT) { - ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0, - IPPROTO_GRE, 0); - return; - } if (t->parms.iph.daddr == 0 || ipv4_is_multicast(t->parms.iph.daddr)) - return; + return PACKET_RCVD; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) - return; + return PACKET_RCVD; if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) t->err_count++; else t->err_count = 1; t->err_time = jiffies; + return PACKET_RCVD; } -static int ipgre_rcv(struct sk_buff *skb) +static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) { struct net *net = dev_net(skb->dev); struct ip_tunnel_net *itn; const struct iphdr *iph; struct ip_tunnel *tunnel; - struct tnl_ptk_info tpi; - int hdr_len; - bool csum_err = false; - - if (parse_gre_header(skb, &tpi, &csum_err, &hdr_len) < 0) - goto drop; - if (tpi.proto == htons(ETH_P_TEB)) + if (tpi->proto == htons(ETH_P_TEB)) itn = net_generic(net, gre_tap_net_id); else itn = net_generic(net, ipgre_net_id); iph = ip_hdr(skb); - tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags, - iph->saddr, iph->daddr, tpi.key); + tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags, + iph->saddr, iph->daddr, tpi->key); if (tunnel) { - ip_tunnel_rcv(tunnel, skb, &tpi, log_ecn_error); - return 0; + ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error); + return PACKET_RCVD; } - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); -drop: - kfree_skb(skb); - return 0; + return PACKET_REJECT; } static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff *skb) @@ -708,9 +587,10 @@ static int ipgre_tunnel_init(struct net_device *dev) return ip_tunnel_init(dev); } -static const struct gre_protocol ipgre_protocol = { - .handler = ipgre_rcv, - .err_handler = ipgre_err, +static struct gre_cisco_protocol ipgre_protocol = { + .handler = ipgre_rcv, + .err_handler = ipgre_err, + .priority = 0, }; static int __net_init ipgre_init_net(struct net *net) @@ -978,7 +858,7 @@ static int __init ipgre_init(void) if (err < 0) goto pnet_tap_faied; - err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO); + err = gre_cisco_register(&ipgre_protocol); if (err < 0) { pr_info("%s: can't add protocol\n", __func__); goto add_proto_failed; @@ -997,7 +877,7 @@ static int __init ipgre_init(void) tap_ops_failed: rtnl_link_unregister(&ipgre_link_ops); rtnl_link_failed: - gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); + gre_cisco_unregister(&ipgre_protocol); add_proto_failed: unregister_pernet_device(&ipgre_tap_net_ops); pnet_tap_faied: @@ -1009,8 +889,7 @@ static void __exit ipgre_fini(void) { rtnl_link_unregister(&ipgre_tap_ops); rtnl_link_unregister(&ipgre_link_ops); - if (gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO) < 0) - pr_info("%s: can't remove protocol\n", __func__); + gre_cisco_unregister(&ipgre_protocol); unregister_pernet_device(&ipgre_tap_net_ops); unregister_pernet_device(&ipgre_net_ops); } -- GitLab From 752f36da68e9136df8918461d651723a43627e04 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:49:45 -0700 Subject: [PATCH 1473/2900] gre: export gre_build_header() function. This is required for ovs gre module. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/gre.h | 2 ++ net/ipv4/gre.c | 32 ++++++++++++++++++++++++++++++++ net/ipv4/ip_gre.c | 40 +--------------------------------------- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/include/net/gre.h b/include/net/gre.h index c6ea0c72c605..cbb9d51d82c1 100644 --- a/include/net/gre.h +++ b/include/net/gre.h @@ -32,6 +32,8 @@ struct gre_cisco_protocol { int gre_cisco_register(struct gre_cisco_protocol *proto); int gre_cisco_unregister(struct gre_cisco_protocol *proto); +void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len); static inline int ip_gre_calc_hlen(__be16 o_flags) { diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 8b9a373890ab..1cbc46536d1f 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -61,6 +61,38 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) } EXPORT_SYMBOL_GPL(gre_del_protocol); +void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, + int hdr_len) +{ + struct gre_base_hdr *greh; + + skb_push(skb, hdr_len); + + greh = (struct gre_base_hdr *)skb->data; + greh->flags = tnl_flags_to_gre_flags(tpi->flags); + greh->protocol = tpi->proto; + + if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) { + __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); + + if (tpi->flags&TUNNEL_SEQ) { + *ptr = tpi->seq; + ptr--; + } + if (tpi->flags&TUNNEL_KEY) { + *ptr = tpi->key; + ptr--; + } + if (tpi->flags&TUNNEL_CSUM && + !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) { + *ptr = 0; + *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, + skb->len, 0)); + } + } +} +EXPORT_SYMBOL_GPL(gre_build_header); + static __sum16 check_checksum(struct sk_buff *skb) { __sum16 csum = 0; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 19863a81cea1..362c7c4c13ca 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -248,40 +248,6 @@ static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff return ERR_PTR(err); } -static struct sk_buff *gre_build_header(struct sk_buff *skb, - const struct tnl_ptk_info *tpi, - int hdr_len) -{ - struct gre_base_hdr *greh; - - skb_push(skb, hdr_len); - - greh = (struct gre_base_hdr *)skb->data; - greh->flags = tnl_flags_to_gre_flags(tpi->flags); - greh->protocol = tpi->proto; - - if (tpi->flags&(TUNNEL_KEY|TUNNEL_CSUM|TUNNEL_SEQ)) { - __be32 *ptr = (__be32 *)(((u8 *)greh) + hdr_len - 4); - - if (tpi->flags&TUNNEL_SEQ) { - *ptr = tpi->seq; - ptr--; - } - if (tpi->flags&TUNNEL_KEY) { - *ptr = tpi->key; - ptr--; - } - if (tpi->flags&TUNNEL_CSUM && - !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) { - *(__sum16 *)ptr = 0; - *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, - skb->len, 0)); - } - } - - return skb; -} - static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, const struct iphdr *tnl_params, __be16 proto) @@ -302,11 +268,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, tpi.seq = htonl(tunnel->o_seqno); /* Push GRE header. */ - skb = gre_build_header(skb, &tpi, tunnel->hlen); - if (unlikely(!skb)) { - dev->stats.tx_dropped++; - return; - } + gre_build_header(skb, &tpi, tunnel->hlen); ip_tunnel_xmit(skb, dev, tnl_params, tnl_params->protocol); } -- GitLab From 45f2e9976cb6fc3f1cc533fd53fe74da5a9dbce4 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:49:51 -0700 Subject: [PATCH 1474/2900] gre: export gre_handle_offloads() function. This is required for OVS GRE offloading. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/gre.h | 1 + net/ipv4/gre.c | 29 +++++++++++++++++++++++++++++ net/ipv4/ip_gre.c | 34 ++-------------------------------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/include/net/gre.h b/include/net/gre.h index cbb9d51d82c1..a5a4ddf05300 100644 --- a/include/net/gre.h +++ b/include/net/gre.h @@ -34,6 +34,7 @@ int gre_cisco_register(struct gre_cisco_protocol *proto); int gre_cisco_unregister(struct gre_cisco_protocol *proto); void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, int hdr_len); +struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum); static inline int ip_gre_calc_hlen(__be16 o_flags) { diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 1cbc46536d1f..5ecc9c49b4dc 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -93,6 +93,35 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, } EXPORT_SYMBOL_GPL(gre_build_header); +struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int err; + + if (likely(!skb->encapsulation)) { + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + } + + if (skb_is_gso(skb)) { + err = skb_unclone(skb, GFP_ATOMIC); + if (unlikely(err)) + goto error; + skb_shinfo(skb)->gso_type |= SKB_GSO_GRE; + return skb; + } else if (skb->ip_summed == CHECKSUM_PARTIAL && gre_csum) { + err = skb_checksum_help(skb); + if (unlikely(err)) + goto error; + } else if (skb->ip_summed != CHECKSUM_PARTIAL) + skb->ip_summed = CHECKSUM_NONE; + + return skb; +error: + kfree_skb(skb); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(gre_handle_offloads); + static __sum16 check_checksum(struct sk_buff *skb) { __sum16 csum = 0; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 362c7c4c13ca..c326e869993a 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -223,31 +223,6 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) return PACKET_REJECT; } -static struct sk_buff *handle_offloads(struct ip_tunnel *tunnel, struct sk_buff *skb) -{ - int err; - - if (skb_is_gso(skb)) { - err = skb_unclone(skb, GFP_ATOMIC); - if (unlikely(err)) - goto error; - skb_shinfo(skb)->gso_type |= SKB_GSO_GRE; - return skb; - } else if (skb->ip_summed == CHECKSUM_PARTIAL && - tunnel->parms.o_flags&TUNNEL_CSUM) { - err = skb_checksum_help(skb); - if (unlikely(err)) - goto error; - } else if (skb->ip_summed != CHECKSUM_PARTIAL) - skb->ip_summed = CHECKSUM_NONE; - - return skb; - -error: - kfree_skb(skb); - return ERR_PTR(err); -} - static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, const struct iphdr *tnl_params, __be16 proto) @@ -255,11 +230,6 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, struct ip_tunnel *tunnel = netdev_priv(dev); struct tnl_ptk_info tpi; - if (likely(!skb->encapsulation)) { - skb_reset_inner_headers(skb); - skb->encapsulation = 1; - } - tpi.flags = tunnel->parms.o_flags; tpi.proto = proto; tpi.key = tunnel->parms.o_key; @@ -279,7 +249,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *tnl_params; - skb = handle_offloads(tunnel, skb); + skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); if (IS_ERR(skb)) goto out; @@ -318,7 +288,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, { struct ip_tunnel *tunnel = netdev_priv(dev); - skb = handle_offloads(tunnel, skb); + skb = gre_handle_offloads(skb, !!(tunnel->parms.o_flags&TUNNEL_CSUM)); if (IS_ERR(skb)) goto out; -- GitLab From 0e6fbc5b6c6218987c93b8c7ca60cf786062899d Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:49:56 -0700 Subject: [PATCH 1475/2900] ip_tunnels: extend iptunnel_xmit() Refactor various ip tunnels xmit functions and extend iptunnel_xmit() so that there is more code sharing. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 32 ++++---------- include/net/ip_tunnels.h | 26 +++++++----- net/ipv4/Makefile | 2 +- net/ipv4/ip_tunnel.c | 38 ++++------------- net/ipv4/ip_tunnel_core.c | 88 +++++++++++++++++++++++++++++++++++++++ net/ipv6/sit.c | 39 +++++------------ 6 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 net/ipv4/ip_tunnel_core.c diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f6dce13c8f89..284c6c00c353 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1021,7 +1021,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct vxlan_dev *vxlan = netdev_priv(dev); struct rtable *rt; const struct iphdr *old_iph; - struct iphdr *iph; struct vxlanhdr *vxh; struct udphdr *uh; struct flowi4 fl4; @@ -1030,6 +1029,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, u32 vni; __be16 df = 0; __u8 tos, ttl; + int err; dst_port = rdst->remote_port ? rdst->remote_port : vxlan->dst_port; vni = rdst->remote_vni; @@ -1097,13 +1097,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, vxlan_encap_bypass(skb, vxlan, dst_vxlan); return NETDEV_TX_OK; } - - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | - IPSKB_REROUTED); - skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); - vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_FLAGS); vxh->vx_vni = htonl(vni << 8); @@ -1118,27 +1111,18 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, uh->len = htons(skb->len); uh->check = 0; - __skb_push(skb, sizeof(*iph)); - skb_reset_network_header(skb); - iph = ip_hdr(skb); - iph->version = 4; - iph->ihl = sizeof(struct iphdr) >> 2; - iph->frag_off = df; - iph->protocol = IPPROTO_UDP; - iph->tos = ip_tunnel_ecn_encap(tos, old_iph, skb); - iph->daddr = dst; - iph->saddr = fl4.saddr; - iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - tunnel_ip_select_ident(skb, old_iph, &rt->dst); - - nf_reset(skb); - vxlan_set_owner(dev, skb); if (handle_offloads(skb)) goto drop; - iptunnel_xmit(skb, dev); + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); + + err = iptunnel_xmit(dev_net(dev), rt, skb, fl4.saddr, dst, + IPPROTO_UDP, tos, ttl, df); + iptunnel_xmit_stats(err, &dev->stats, dev->tstats); + return NETDEV_TX_OK; drop: diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 1be442f89406..b84f1ab09d78 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -155,23 +155,27 @@ static inline void tunnel_ip_select_ident(struct sk_buff *skb, (skb_shinfo(skb)->gso_segs ?: 1) - 1); } -static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev) +int iptunnel_xmit(struct net *net, struct rtable *rt, + struct sk_buff *skb, + __be32 src, __be32 dst, __u8 proto, + __u8 tos, __u8 ttl, __be16 df); + +static inline void iptunnel_xmit_stats(int err, + struct net_device_stats *err_stats, + struct pcpu_tstats __percpu *stats) { - int err; - int pkt_len = skb->len - skb_transport_offset(skb); - struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats); + if (err > 0) { + struct pcpu_tstats *tstats = this_cpu_ptr(stats); - nf_reset(skb); - - err = ip_local_out(skb); - if (likely(net_xmit_eval(err) == 0)) { u64_stats_update_begin(&tstats->syncp); - tstats->tx_bytes += pkt_len; + tstats->tx_bytes += err; tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); + } else if (err < 0) { + err_stats->tx_errors++; + err_stats->tx_aborted_errors++; } else { - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; + err_stats->tx_dropped++; } } #endif /* __NET_IP_TUNNELS_H */ diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 7fcf8101d85f..86ded0bac9c7 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -11,7 +11,7 @@ obj-y := route.o inetpeer.o protocol.o \ tcp_offload.o datagram.o raw.o udp.o udplite.o \ udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o fib_trie.o \ - inet_fragment.o ping.o + inet_fragment.o ping.o ip_tunnel_core.o obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index e189db409b0e..a06a2ed49597 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -491,19 +491,17 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, { struct ip_tunnel *tunnel = netdev_priv(dev); const struct iphdr *inner_iph; - struct iphdr *iph; struct flowi4 fl4; u8 tos, ttl; __be16 df; struct rtable *rt; /* Route to the other host */ - struct net_device *tdev; /* Device to other host */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst; int mtu; + int err; inner_iph = (const struct iphdr *)skb_inner_network_header(skb); - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); dst = tnl_params->daddr; if (dst == 0) { /* NBMA tunnel */ @@ -571,14 +569,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, dev->stats.tx_carrier_errors++; goto tx_error; } - tdev = rt->dst.dev; - - if (tdev == dev) { + if (rt->dst.dev == dev) { ip_rt_put(rt); dev->stats.collisions++; goto tx_error; } - df = tnl_params->frag_off; if (df) @@ -596,6 +591,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, if (!skb_is_gso(skb) && (inner_iph->frag_off&htons(IP_DF)) && mtu < ntohs(inner_iph->tot_len)) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); ip_rt_put(rt); goto tx_error; @@ -646,8 +642,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ttl = ip4_dst_hoplimit(&rt->dst); } - max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr) - + rt->dst.header_len; + max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + + rt->dst.header_len; if (max_headroom > dev->needed_headroom) { dev->needed_headroom = max_headroom; if (skb_cow_head(skb, dev->needed_headroom)) { @@ -657,27 +653,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, } } - skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); - - /* Push down and install the IP header. */ - skb_push(skb, sizeof(struct iphdr)); - skb_reset_network_header(skb); - - iph = ip_hdr(skb); - inner_iph = (const struct iphdr *)skb_inner_network_header(skb); + err = iptunnel_xmit(dev_net(dev), rt, skb, + fl4.saddr, fl4.daddr, protocol, + ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df); + iptunnel_xmit_stats(err, &dev->stats, dev->tstats); - iph->version = 4; - iph->ihl = sizeof(struct iphdr) >> 2; - iph->frag_off = df; - iph->protocol = protocol; - iph->tos = ip_tunnel_ecn_encap(tos, inner_iph, skb); - iph->daddr = fl4.daddr; - iph->saddr = fl4.saddr; - iph->ttl = ttl; - tunnel_ip_select_ident(skb, inner_iph, &rt->dst); - - iptunnel_xmit(skb, dev); return; #if IS_ENABLED(CONFIG_IPV6) diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c new file mode 100644 index 000000000000..927687e83f18 --- /dev/null +++ b/net/ipv4/ip_tunnel_core.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013 Nicira, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int iptunnel_xmit(struct net *net, struct rtable *rt, + struct sk_buff *skb, + __be32 src, __be32 dst, __u8 proto, + __u8 tos, __u8 ttl, __be16 df) +{ + int pkt_len = skb->len; + struct iphdr *iph; + int err; + + nf_reset(skb); + secpath_reset(skb); + skb->rxhash = 0; + skb_dst_drop(skb); + skb_dst_set(skb, &rt->dst); + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + + /* Push down and install the IP header. */ + __skb_push(skb, sizeof(struct iphdr)); + skb_reset_network_header(skb); + + iph = ip_hdr(skb); + + iph->version = 4; + iph->ihl = sizeof(struct iphdr) >> 2; + iph->frag_off = df; + iph->protocol = proto; + iph->tos = tos; + iph->daddr = dst; + iph->saddr = src; + iph->ttl = ttl; + tunnel_ip_select_ident(skb, + (const struct iphdr *)skb_inner_network_header(skb), + &rt->dst); + + err = ip_local_out(skb); + if (unlikely(net_xmit_eval(err))) + pkt_len = 0; + return pkt_len; +} +EXPORT_SYMBOL_GPL(iptunnel_xmit); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 6b9c1f128eaf..76bb8de435b2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -723,13 +723,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, __be16 df = tiph->frag_off; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ - struct iphdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst = tiph->daddr; struct flowi4 fl4; int mtu; const struct in6_addr *addr6; int addr_type; + u8 ttl; + int err; if (skb->protocol != htons(ETH_P_IPV6)) goto tx_error; @@ -872,34 +873,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, skb = new_skb; iph6 = ipv6_hdr(skb); } - - skb->transport_header = skb->network_header; - skb_push(skb, sizeof(struct iphdr)); - skb_reset_network_header(skb); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); - IPCB(skb)->flags = 0; - skb_dst_drop(skb); - skb_dst_set(skb, &rt->dst); - - /* - * Push down and install the IPIP header. - */ - - iph = ip_hdr(skb); - iph->version = 4; - iph->ihl = sizeof(struct iphdr)>>2; - iph->frag_off = df; - iph->protocol = IPPROTO_IPV6; - iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); - iph->daddr = fl4.daddr; - iph->saddr = fl4.saddr; - - if ((iph->ttl = tiph->ttl) == 0) - iph->ttl = iph6->hop_limit; - - skb->ip_summed = CHECKSUM_NONE; - ip_select_ident(iph, skb_dst(skb), NULL); - iptunnel_xmit(skb, dev); + ttl = tiph->ttl; + if (ttl == 0) + ttl = iph6->hop_limit; + tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); + + err = iptunnel_xmit(dev_net(dev), rt, skb, fl4.saddr, fl4.daddr, + IPPROTO_IPV6, tos, ttl, df); + iptunnel_xmit_stats(err, &dev->stats, dev->tstats); return NETDEV_TX_OK; tx_error_icmp: -- GitLab From 3d7b46cd20e300bd6989fb1f43d46f1b9645816e Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:02 -0700 Subject: [PATCH 1476/2900] ip_tunnel: push generic protocol handling to ip_tunnel module. Process skb tunnel header before sending packet to protocol handler. this allows code sharing between gre and ovs gre modules. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 1 + net/ipv4/gre.c | 3 ++- net/ipv4/ip_tunnel.c | 30 ++++++------------------------ net/ipv4/ip_tunnel_core.c | 34 ++++++++++++++++++++++++++++++++++ net/ipv4/ipip.c | 6 +++++- net/ipv6/sit.c | 7 ++++++- 6 files changed, 54 insertions(+), 27 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index b84f1ab09d78..32e130b560fa 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -155,6 +155,7 @@ static inline void tunnel_ip_select_ident(struct sk_buff *skb, (skb_shinfo(skb)->gso_segs ?: 1) - 1); } +int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); int iptunnel_xmit(struct net *net, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c index 5ecc9c49b4dc..ba4803e609b5 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre.c @@ -201,7 +201,8 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, return -EINVAL; } } - return 0; + + return iptunnel_pull_header(skb, hdr_len, tpi->proto); } static int gre_cisco_rcv(struct sk_buff *skb) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index a06a2ed49597..bd227e5ea9da 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -408,13 +408,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, const struct iphdr *iph = ip_hdr(skb); int err; - secpath_reset(skb); - - skb->protocol = tpi->proto; - - skb->mac_header = skb->network_header; - __pskb_pull(skb, tunnel->hlen); - skb_postpull_rcsum(skb, skb_transport_header(skb), tunnel->hlen); #ifdef CONFIG_NET_IPGRE_BROADCAST if (ipv4_is_multicast(iph->daddr)) { /* Looped back packet, drop it! */ @@ -442,23 +435,6 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, tunnel->i_seqno = ntohl(tpi->seq) + 1; } - /* Warning: All skb pointers will be invalidated! */ - if (tunnel->dev->type == ARPHRD_ETHER) { - if (!pskb_may_pull(skb, ETH_HLEN)) { - tunnel->dev->stats.rx_length_errors++; - tunnel->dev->stats.rx_errors++; - goto drop; - } - - iph = ip_hdr(skb); - skb->protocol = eth_type_trans(skb, tunnel->dev); - skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); - } - - skb->pkt_type = PACKET_HOST; - __skb_tunnel_rx(skb, tunnel->dev); - - skb_reset_network_header(skb); err = IP_ECN_decapsulate(iph, skb); if (unlikely(err)) { if (log_ecn_error) @@ -477,6 +453,12 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + if (tunnel->dev->type == ARPHRD_ETHER) { + skb->protocol = eth_type_trans(skb, tunnel->dev); + skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); + } else { + skb->dev = tunnel->dev; + } gro_cells_receive(&tunnel->gro_cells, skb); return 0; diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 927687e83f18..7167b08977df 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -86,3 +86,37 @@ int iptunnel_xmit(struct net *net, struct rtable *rt, return pkt_len; } EXPORT_SYMBOL_GPL(iptunnel_xmit); + +int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto) +{ + if (unlikely(!pskb_may_pull(skb, hdr_len))) + return -ENOMEM; + + skb_pull_rcsum(skb, hdr_len); + + if (inner_proto == htons(ETH_P_TEB)) { + struct ethhdr *eh = (struct ethhdr *)skb->data; + + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + return -ENOMEM; + + if (likely(ntohs(eh->h_proto) >= ETH_P_802_3_MIN)) + skb->protocol = eh->h_proto; + else + skb->protocol = htons(ETH_P_802_2); + + } else { + skb->protocol = inner_proto; + } + + nf_reset(skb); + secpath_reset(skb); + if (!skb->l4_rxhash) + skb->rxhash = 0; + skb_dst_drop(skb); + skb->vlan_tci = 0; + skb_set_queue_mapping(skb, 0); + skb->pkt_type = PACKET_HOST; + return 0; +} +EXPORT_SYMBOL_GPL(iptunnel_pull_header); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 9df7ecd393f2..e6905fbda2a2 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -188,8 +188,12 @@ static int ipip_rcv(struct sk_buff *skb) struct net *net = dev_net(skb->dev); struct ip_tunnel_net *itn = net_generic(net, ipip_net_id); struct ip_tunnel *tunnel; - const struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph; + if (iptunnel_pull_header(skb, 0, tpi.proto)) + goto drop; + + iph = ip_hdr(skb); tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, iph->saddr, iph->daddr, 0); if (tunnel) { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 76bb8de435b2..6cee844678e2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -640,9 +640,14 @@ static const struct tnl_ptk_info tpi = { static int ipip_rcv(struct sk_buff *skb) { - const struct iphdr *iph = ip_hdr(skb); + const struct iphdr *iph; struct ip_tunnel *tunnel; + if (iptunnel_pull_header(skb, 0, tpi.proto)) + goto drop; + + iph = ip_hdr(skb); + tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), skb->dev, iph->saddr, iph->daddr); if (tunnel != NULL) { -- GitLab From 9a628224a61bbcd2b50b3ec96e661fbbb49b619a Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:07 -0700 Subject: [PATCH 1477/2900] ip_tunnel: Add dont fragment flag. This flag will be used by ovs tunneling. Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 32e130b560fa..10bbb4273f7d 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -73,6 +73,7 @@ struct ip_tunnel { #define TUNNEL_REC __cpu_to_be16(0x20) #define TUNNEL_VERSION __cpu_to_be16(0x40) #define TUNNEL_NO_KEY __cpu_to_be16(0x80) +#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) struct tnl_ptk_info { __be16 flags; -- GitLab From 74f84a5726c7d08c27745305e67474b8645c541d Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:12 -0700 Subject: [PATCH 1478/2900] openvswitch: Copy individual actions. Rather than validating actions and then copying all actiaons in one block, following patch does same operation in single pass. This validate and copy action one by one. This is required for ovs tunneling patch. This patch does not change any functionality. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 271 ++++++++++++++++++++++++++++++------- net/openvswitch/flow.c | 10 +- net/openvswitch/flow.h | 2 +- 3 files changed, 225 insertions(+), 58 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 0f783d9fa00d..f14816b80b80 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -464,16 +464,89 @@ static int flush_flows(struct datapath *dp) return 0; } -static int validate_actions(const struct nlattr *attr, - const struct sw_flow_key *key, int depth); +static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, int attr_len) +{ + + struct sw_flow_actions *acts; + int new_acts_size; + int req_size = NLA_ALIGN(attr_len); + int next_offset = offsetof(struct sw_flow_actions, actions) + + (*sfa)->actions_len; + + if (req_size <= (ksize(*sfa) - next_offset)) + goto out; + + new_acts_size = ksize(*sfa) * 2; + + if (new_acts_size > MAX_ACTIONS_BUFSIZE) { + if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) + return ERR_PTR(-EMSGSIZE); + new_acts_size = MAX_ACTIONS_BUFSIZE; + } + + acts = ovs_flow_actions_alloc(new_acts_size); + if (IS_ERR(acts)) + return (void *)acts; + + memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len); + acts->actions_len = (*sfa)->actions_len; + kfree(*sfa); + *sfa = acts; + +out: + (*sfa)->actions_len += req_size; + return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset); +} + +static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len) +{ + struct nlattr *a; + + a = reserve_sfa_size(sfa, nla_attr_size(len)); + if (IS_ERR(a)) + return PTR_ERR(a); + + a->nla_type = attrtype; + a->nla_len = nla_attr_size(len); + + if (data) + memcpy(nla_data(a), data, len); + memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len)); + + return 0; +} + +static inline int add_nested_action_start(struct sw_flow_actions **sfa, int attrtype) +{ + int used = (*sfa)->actions_len; + int err; + + err = add_action(sfa, attrtype, NULL, 0); + if (err) + return err; + + return used; +} -static int validate_sample(const struct nlattr *attr, - const struct sw_flow_key *key, int depth) +static inline void add_nested_action_end(struct sw_flow_actions *sfa, int st_offset) +{ + struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions + st_offset); + + a->nla_len = sfa->actions_len - st_offset; +} + +static int validate_and_copy_actions(const struct nlattr *attr, + const struct sw_flow_key *key, int depth, + struct sw_flow_actions **sfa); + +static int validate_and_copy_sample(const struct nlattr *attr, + const struct sw_flow_key *key, int depth, + struct sw_flow_actions **sfa) { const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1]; const struct nlattr *probability, *actions; const struct nlattr *a; - int rem; + int rem, start, err, st_acts; memset(attrs, 0, sizeof(attrs)); nla_for_each_nested(a, attr, rem) { @@ -492,7 +565,26 @@ static int validate_sample(const struct nlattr *attr, actions = attrs[OVS_SAMPLE_ATTR_ACTIONS]; if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) return -EINVAL; - return validate_actions(actions, key, depth + 1); + + /* validation done, copy sample action. */ + start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE); + if (start < 0) + return start; + err = add_action(sfa, OVS_SAMPLE_ATTR_PROBABILITY, nla_data(probability), sizeof(u32)); + if (err) + return err; + st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS); + if (st_acts < 0) + return st_acts; + + err = validate_and_copy_actions(actions, key, depth + 1, sfa); + if (err) + return err; + + add_nested_action_end(*sfa, st_acts); + add_nested_action_end(*sfa, start); + + return 0; } static int validate_tp_port(const struct sw_flow_key *flow_key) @@ -606,8 +698,24 @@ static int validate_userspace(const struct nlattr *attr) return 0; } -static int validate_actions(const struct nlattr *attr, - const struct sw_flow_key *key, int depth) +static int copy_action(const struct nlattr *from, + struct sw_flow_actions **sfa) +{ + int totlen = NLA_ALIGN(from->nla_len); + struct nlattr *to; + + to = reserve_sfa_size(sfa, from->nla_len); + if (IS_ERR(to)) + return PTR_ERR(to); + + memcpy(to, from, totlen); + return 0; +} + +static int validate_and_copy_actions(const struct nlattr *attr, + const struct sw_flow_key *key, + int depth, + struct sw_flow_actions **sfa) { const struct nlattr *a; int rem, err; @@ -627,12 +735,14 @@ static int validate_actions(const struct nlattr *attr, }; const struct ovs_action_push_vlan *vlan; int type = nla_type(a); + bool skip_copy; if (type > OVS_ACTION_ATTR_MAX || (action_lens[type] != nla_len(a) && action_lens[type] != (u32)-1)) return -EINVAL; + skip_copy = false; switch (type) { case OVS_ACTION_ATTR_UNSPEC: return -EINVAL; @@ -667,14 +777,20 @@ static int validate_actions(const struct nlattr *attr, break; case OVS_ACTION_ATTR_SAMPLE: - err = validate_sample(a, key, depth); + err = validate_and_copy_sample(a, key, depth, sfa); if (err) return err; + skip_copy = true; break; default: return -EINVAL; } + if (!skip_copy) { + err = copy_action(a, sfa); + if (err) + return err; + } } if (rem > 0) @@ -742,18 +858,16 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]); if (err) goto err_flow_free; - - err = validate_actions(a[OVS_PACKET_ATTR_ACTIONS], &flow->key, 0); - if (err) - goto err_flow_free; - flow->hash = ovs_flow_hash(&flow->key, key_len); - - acts = ovs_flow_actions_alloc(a[OVS_PACKET_ATTR_ACTIONS]); + acts = ovs_flow_actions_alloc(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); err = PTR_ERR(acts); if (IS_ERR(acts)) goto err_flow_free; + + err = validate_and_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], &flow->key, 0, &acts); rcu_assign_pointer(flow->sf_acts, acts); + if (err) + goto err_flow_free; OVS_CB(packet)->flow = flow; packet->priority = flow->key.phy.priority; @@ -843,6 +957,66 @@ static struct genl_multicast_group ovs_dp_flow_multicast_group = { .name = OVS_FLOW_MCGROUP }; +static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb); +static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb) +{ + const struct nlattr *a; + struct nlattr *start; + int err = 0, rem; + + start = nla_nest_start(skb, OVS_ACTION_ATTR_SAMPLE); + if (!start) + return -EMSGSIZE; + + nla_for_each_nested(a, attr, rem) { + int type = nla_type(a); + struct nlattr *st_sample; + + switch (type) { + case OVS_SAMPLE_ATTR_PROBABILITY: + if (nla_put(skb, OVS_SAMPLE_ATTR_PROBABILITY, sizeof(u32), nla_data(a))) + return -EMSGSIZE; + break; + case OVS_SAMPLE_ATTR_ACTIONS: + st_sample = nla_nest_start(skb, OVS_SAMPLE_ATTR_ACTIONS); + if (!st_sample) + return -EMSGSIZE; + err = actions_to_attr(nla_data(a), nla_len(a), skb); + if (err) + return err; + nla_nest_end(skb, st_sample); + break; + } + } + + nla_nest_end(skb, start); + return err; +} + +static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb) +{ + const struct nlattr *a; + int rem, err; + + nla_for_each_attr(a, attr, len, rem) { + int type = nla_type(a); + + switch (type) { + case OVS_ACTION_ATTR_SAMPLE: + err = sample_action_to_attr(a, skb); + if (err) + return err; + break; + default: + if (nla_put(skb, type, nla_len(a), nla_data(a))) + return -EMSGSIZE; + break; + } + } + + return 0; +} + static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts) { return NLMSG_ALIGN(sizeof(struct ovs_header)) @@ -860,6 +1034,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, { const int skb_orig_len = skb->len; const struct sw_flow_actions *sf_acts; + struct nlattr *start; struct ovs_flow_stats stats; struct ovs_header *ovs_header; struct nlattr *nla; @@ -913,10 +1088,19 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, * This can only fail for dump operations because the skb is always * properly sized for single flows. */ - err = nla_put(skb, OVS_FLOW_ATTR_ACTIONS, sf_acts->actions_len, - sf_acts->actions); - if (err < 0 && skb_orig_len) - goto error; + start = nla_nest_start(skb, OVS_FLOW_ATTR_ACTIONS); + if (start) { + err = actions_to_attr(sf_acts->actions, sf_acts->actions_len, skb); + if (!err) + nla_nest_end(skb, start); + else { + if (skb_orig_len) + goto error; + + nla_nest_cancel(skb, start); + } + } else if (skb_orig_len) + goto nla_put_failure; return genlmsg_end(skb, ovs_header); @@ -961,6 +1145,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) struct sk_buff *reply; struct datapath *dp; struct flow_table *table; + struct sw_flow_actions *acts = NULL; int error; int key_len; @@ -974,9 +1159,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) /* Validate actions. */ if (a[OVS_FLOW_ATTR_ACTIONS]) { - error = validate_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, 0); - if (error) + acts = ovs_flow_actions_alloc(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); + error = PTR_ERR(acts); + if (IS_ERR(acts)) goto error; + + error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, 0, &acts); + if (error) + goto err_kfree; } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { error = -EINVAL; goto error; @@ -991,8 +1181,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) table = ovsl_dereference(dp->table); flow = ovs_flow_tbl_lookup(table, &key, key_len); if (!flow) { - struct sw_flow_actions *acts; - /* Bail out if we're not allowed to create a new flow. */ error = -ENOENT; if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) @@ -1019,11 +1207,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) flow->key = key; clear_stats(flow); - /* Obtain actions. */ - acts = ovs_flow_actions_alloc(a[OVS_FLOW_ATTR_ACTIONS]); - error = PTR_ERR(acts); - if (IS_ERR(acts)) - goto error_free_flow; rcu_assign_pointer(flow->sf_acts, acts); /* Put flow in bucket. */ @@ -1036,7 +1219,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) } else { /* We found a matching flow. */ struct sw_flow_actions *old_acts; - struct nlattr *acts_attrs; /* Bail out if we're not allowed to modify an existing flow. * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL @@ -1051,21 +1233,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) /* Update actions. */ old_acts = ovsl_dereference(flow->sf_acts); - acts_attrs = a[OVS_FLOW_ATTR_ACTIONS]; - if (acts_attrs && - (old_acts->actions_len != nla_len(acts_attrs) || - memcmp(old_acts->actions, nla_data(acts_attrs), - old_acts->actions_len))) { - struct sw_flow_actions *new_acts; - - new_acts = ovs_flow_actions_alloc(acts_attrs); - error = PTR_ERR(new_acts); - if (IS_ERR(new_acts)) - goto err_unlock_ovs; - - rcu_assign_pointer(flow->sf_acts, new_acts); - ovs_flow_deferred_free_acts(old_acts); - } + rcu_assign_pointer(flow->sf_acts, acts); + ovs_flow_deferred_free_acts(old_acts); reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, info->snd_seq, OVS_FLOW_CMD_NEW); @@ -1086,10 +1255,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) ovs_dp_flow_multicast_group.id, PTR_ERR(reply)); return 0; -error_free_flow: - ovs_flow_free(flow); err_unlock_ovs: ovs_unlock(); +err_kfree: + kfree(acts); error: return error; } @@ -1866,8 +2035,8 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info) goto exit_unlock; } - reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq, - OVS_VPORT_CMD_DEL); + reply = ovs_vport_cmd_build_info(vport, info->snd_portid, + info->snd_seq, OVS_VPORT_CMD_DEL); err = PTR_ERR(reply); if (IS_ERR(reply)) goto exit_unlock; @@ -1896,8 +2065,8 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(vport)) goto exit_unlock; - reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq, - OVS_VPORT_CMD_NEW); + reply = ovs_vport_cmd_build_info(vport, info->snd_portid, + info->snd_seq, OVS_VPORT_CMD_NEW); err = PTR_ERR(reply); if (IS_ERR(reply)) goto exit_unlock; diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 093c191d4fc2..940d4b803ff5 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -198,20 +198,18 @@ void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb) spin_unlock(&flow->lock); } -struct sw_flow_actions *ovs_flow_actions_alloc(const struct nlattr *actions) +struct sw_flow_actions *ovs_flow_actions_alloc(int size) { - int actions_len = nla_len(actions); struct sw_flow_actions *sfa; - if (actions_len > MAX_ACTIONS_BUFSIZE) + if (size > MAX_ACTIONS_BUFSIZE) return ERR_PTR(-EINVAL); - sfa = kmalloc(sizeof(*sfa) + actions_len, GFP_KERNEL); + sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL); if (!sfa) return ERR_PTR(-ENOMEM); - sfa->actions_len = actions_len; - nla_memcpy(sfa->actions, actions, actions_len); + sfa->actions_len = 0; return sfa; } diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 2a83e2141f08..e370f6246ee9 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -130,7 +130,7 @@ struct sw_flow *ovs_flow_alloc(void); void ovs_flow_deferred_free(struct sw_flow *); void ovs_flow_free(struct sw_flow *flow); -struct sw_flow_actions *ovs_flow_actions_alloc(const struct nlattr *); +struct sw_flow_actions *ovs_flow_actions_alloc(int actions_len); void ovs_flow_deferred_free_acts(struct sw_flow_actions *); int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *, -- GitLab From 7d5437c709ded4f152cb8b305d17972d6707f20c Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:18 -0700 Subject: [PATCH 1479/2900] openvswitch: Add tunneling interface. Add ovs tunnel interface for set tunnel action for userspace. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Signed-off-by: David S. Miller --- include/uapi/linux/openvswitch.h | 18 ++++ net/openvswitch/actions.c | 4 + net/openvswitch/datapath.c | 78 ++++++++++++++++- net/openvswitch/datapath.h | 3 + net/openvswitch/flow.c | 125 +++++++++++++++++++++++++++ net/openvswitch/flow.h | 19 ++++ net/openvswitch/vport-internal_dev.c | 2 +- net/openvswitch/vport-netdev.c | 2 +- net/openvswitch/vport.c | 4 +- net/openvswitch/vport.h | 3 +- 10 files changed, 251 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index 424672db7f12..b15a445927d6 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -246,11 +246,29 @@ enum ovs_key_attr { OVS_KEY_ATTR_ARP, /* struct ovs_key_arp */ OVS_KEY_ATTR_ND, /* struct ovs_key_nd */ OVS_KEY_ATTR_SKB_MARK, /* u32 skb mark */ + OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */ + +#ifdef __KERNEL__ + OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */ +#endif __OVS_KEY_ATTR_MAX }; #define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1) +enum ovs_tunnel_key_attr { + OVS_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */ + OVS_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */ + OVS_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */ + OVS_TUNNEL_KEY_ATTR_TOS, /* u8 Tunnel IP ToS. */ + OVS_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */ + OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */ + OVS_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */ + __OVS_TUNNEL_KEY_ATTR_MAX +}; + +#define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1) + /** * enum ovs_frag_type - IPv4 and IPv6 fragment type * @OVS_FRAG_TYPE_NONE: Packet is not a fragment. diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 596d6373399d..22c5f399f1cf 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -436,6 +436,10 @@ static int execute_set_action(struct sk_buff *skb, skb->mark = nla_get_u32(nested_attr); break; + case OVS_KEY_ATTR_IPV4_TUNNEL: + OVS_CB(skb)->tun_key = nla_data(nested_attr); + break; + case OVS_KEY_ATTR_ETHERNET: err = set_eth_addr(skb, nla_data(nested_attr)); break; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index f14816b80b80..bbd310646bc8 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -362,6 +362,14 @@ static int queue_gso_packets(struct net *net, int dp_ifindex, static size_t key_attr_size(void) { return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */ + + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */ + + nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */ + + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */ + + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */ + + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */ + + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */ + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */ + + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */ + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */ + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ @@ -600,8 +608,30 @@ static int validate_tp_port(const struct sw_flow_key *flow_key) return -EINVAL; } +static int validate_and_copy_set_tun(const struct nlattr *attr, + struct sw_flow_actions **sfa) +{ + struct ovs_key_ipv4_tunnel tun_key; + int err, start; + + err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &tun_key); + if (err) + return err; + + start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET); + if (start < 0) + return start; + + err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key, sizeof(tun_key)); + add_nested_action_end(*sfa, start); + + return err; +} + static int validate_set(const struct nlattr *a, - const struct sw_flow_key *flow_key) + const struct sw_flow_key *flow_key, + struct sw_flow_actions **sfa, + bool *set_tun) { const struct nlattr *ovs_key = nla_data(a); int key_type = nla_type(ovs_key); @@ -611,18 +641,27 @@ static int validate_set(const struct nlattr *a, return -EINVAL; if (key_type > OVS_KEY_ATTR_MAX || - nla_len(ovs_key) != ovs_key_lens[key_type]) + (ovs_key_lens[key_type] != nla_len(ovs_key) && + ovs_key_lens[key_type] != -1)) return -EINVAL; switch (key_type) { const struct ovs_key_ipv4 *ipv4_key; const struct ovs_key_ipv6 *ipv6_key; + int err; case OVS_KEY_ATTR_PRIORITY: case OVS_KEY_ATTR_SKB_MARK: case OVS_KEY_ATTR_ETHERNET: break; + case OVS_KEY_ATTR_TUNNEL: + *set_tun = true; + err = validate_and_copy_set_tun(a, sfa); + if (err) + return err; + break; + case OVS_KEY_ATTR_IPV4: if (flow_key->eth.type != htons(ETH_P_IP)) return -EINVAL; @@ -771,7 +810,7 @@ static int validate_and_copy_actions(const struct nlattr *attr, break; case OVS_ACTION_ATTR_SET: - err = validate_set(a, key); + err = validate_set(a, key, sfa, &skip_copy); if (err) return err; break; @@ -993,6 +1032,33 @@ static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb) return err; } +static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) +{ + const struct nlattr *ovs_key = nla_data(a); + int key_type = nla_type(ovs_key); + struct nlattr *start; + int err; + + switch (key_type) { + case OVS_KEY_ATTR_IPV4_TUNNEL: + start = nla_nest_start(skb, OVS_ACTION_ATTR_SET); + if (!start) + return -EMSGSIZE; + + err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key)); + if (err) + return err; + nla_nest_end(skb, start); + break; + default: + if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key)) + return -EMSGSIZE; + break; + } + + return 0; +} + static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb) { const struct nlattr *a; @@ -1002,6 +1068,12 @@ static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *s int type = nla_type(a); switch (type) { + case OVS_ACTION_ATTR_SET: + err = set_action_to_attr(a, skb); + if (err) + return err; + break; + case OVS_ACTION_ATTR_SAMPLE: err = sample_action_to_attr(a, skb); if (err) diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 16b840695216..e88ebc2f1c54 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -88,9 +88,12 @@ struct datapath { /** * struct ovs_skb_cb - OVS data in skb CB * @flow: The flow associated with this packet. May be %NULL if no flow. + * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the + * packet is not being tunneled. */ struct ovs_skb_cb { struct sw_flow *flow; + struct ovs_key_ipv4_tunnel *tun_key; }; #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 940d4b803ff5..976a8b766a6a 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -603,6 +604,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, memset(key, 0, sizeof(*key)); key->phy.priority = skb->priority; + if (OVS_CB(skb)->tun_key) + memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key)); key->phy.in_port = in_port; key->phy.skb_mark = skb->mark; @@ -818,6 +821,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6), [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp), [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd), + [OVS_KEY_ATTR_TUNNEL] = -1, }; static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_len, @@ -955,6 +959,105 @@ static int parse_flow_nlattrs(const struct nlattr *attr, return 0; } +int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr, + struct ovs_key_ipv4_tunnel *tun_key) +{ + struct nlattr *a; + int rem; + bool ttl = false; + + memset(tun_key, 0, sizeof(*tun_key)); + + nla_for_each_nested(a, attr, rem) { + int type = nla_type(a); + static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = { + [OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64), + [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32), + [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32), + [OVS_TUNNEL_KEY_ATTR_TOS] = 1, + [OVS_TUNNEL_KEY_ATTR_TTL] = 1, + [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0, + [OVS_TUNNEL_KEY_ATTR_CSUM] = 0, + }; + + if (type > OVS_TUNNEL_KEY_ATTR_MAX || + ovs_tunnel_key_lens[type] != nla_len(a)) + return -EINVAL; + + switch (type) { + case OVS_TUNNEL_KEY_ATTR_ID: + tun_key->tun_id = nla_get_be64(a); + tun_key->tun_flags |= TUNNEL_KEY; + break; + case OVS_TUNNEL_KEY_ATTR_IPV4_SRC: + tun_key->ipv4_src = nla_get_be32(a); + break; + case OVS_TUNNEL_KEY_ATTR_IPV4_DST: + tun_key->ipv4_dst = nla_get_be32(a); + break; + case OVS_TUNNEL_KEY_ATTR_TOS: + tun_key->ipv4_tos = nla_get_u8(a); + break; + case OVS_TUNNEL_KEY_ATTR_TTL: + tun_key->ipv4_ttl = nla_get_u8(a); + ttl = true; + break; + case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: + tun_key->tun_flags |= TUNNEL_DONT_FRAGMENT; + break; + case OVS_TUNNEL_KEY_ATTR_CSUM: + tun_key->tun_flags |= TUNNEL_CSUM; + break; + default: + return -EINVAL; + + } + } + if (rem > 0) + return -EINVAL; + + if (!tun_key->ipv4_dst) + return -EINVAL; + + if (!ttl) + return -EINVAL; + + return 0; +} + +int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb, + const struct ovs_key_ipv4_tunnel *tun_key) +{ + struct nlattr *nla; + + nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL); + if (!nla) + return -EMSGSIZE; + + if (tun_key->tun_flags & TUNNEL_KEY && + nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, tun_key->tun_id)) + return -EMSGSIZE; + if (tun_key->ipv4_src && + nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tun_key->ipv4_src)) + return -EMSGSIZE; + if (nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, tun_key->ipv4_dst)) + return -EMSGSIZE; + if (tun_key->ipv4_tos && + nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, tun_key->ipv4_tos)) + return -EMSGSIZE; + if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, tun_key->ipv4_ttl)) + return -EMSGSIZE; + if ((tun_key->tun_flags & TUNNEL_DONT_FRAGMENT) && + nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT)) + return -EMSGSIZE; + if ((tun_key->tun_flags & TUNNEL_CSUM) && + nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM)) + return -EMSGSIZE; + + nla_nest_end(skb, nla); + return 0; +} + /** * ovs_flow_from_nlattrs - parses Netlink attributes into a flow key. * @swkey: receives the extracted flow key. @@ -997,6 +1100,14 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK); } + if (attrs & (1 << OVS_KEY_ATTR_TUNNEL)) { + err = ovs_ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], &swkey->tun_key); + if (err) + return err; + + attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL); + } + /* Data attributes. */ if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET))) return -EINVAL; @@ -1135,17 +1246,21 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, const struct nlattr *attr) { + struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key; const struct nlattr *nla; int rem; flow->key.phy.in_port = DP_MAX_PORTS; flow->key.phy.priority = 0; flow->key.phy.skb_mark = 0; + memset(tun_key, 0, sizeof(flow->key.tun_key)); nla_for_each_nested(nla, attr, rem) { int type = nla_type(nla); if (type <= OVS_KEY_ATTR_MAX && ovs_key_lens[type] > 0) { + int err; + if (nla_len(nla) != ovs_key_lens[type]) return -EINVAL; @@ -1154,6 +1269,12 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, flow->key.phy.priority = nla_get_u32(nla); break; + case OVS_KEY_ATTR_TUNNEL: + err = ovs_ipv4_tun_from_nlattr(nla, tun_key); + if (err) + return err; + break; + case OVS_KEY_ATTR_IN_PORT: if (nla_get_u32(nla) >= DP_MAX_PORTS) return -EINVAL; @@ -1180,6 +1301,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority)) goto nla_put_failure; + if (swkey->tun_key.ipv4_dst && + ovs_ipv4_tun_to_nlattr(skb, &swkey->tun_key)) + goto nla_put_failure; + if (swkey->phy.in_port != DP_MAX_PORTS && nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) goto nla_put_failure; diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index e370f6246ee9..aec5e43f690b 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -40,7 +40,22 @@ struct sw_flow_actions { struct nlattr actions[]; }; +/* Used to memset ovs_key_ipv4_tunnel padding. */ +#define OVS_TUNNEL_KEY_SIZE \ + (offsetof(struct ovs_key_ipv4_tunnel, ipv4_ttl) + \ + FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, ipv4_ttl)) + +struct ovs_key_ipv4_tunnel { + __be64 tun_id; + __be32 ipv4_src; + __be32 ipv4_dst; + u16 tun_flags; + u8 ipv4_tos; + u8 ipv4_ttl; +}; + struct sw_flow_key { + struct ovs_key_ipv4_tunnel tun_key; /* Encapsulating tunnel key. */ struct { u32 priority; /* Packet QoS priority. */ u32 skb_mark; /* SKB mark. */ @@ -179,5 +194,9 @@ u32 ovs_flow_hash(const struct sw_flow_key *key, int key_len); struct sw_flow *ovs_flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *idx); extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; +int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr, + struct ovs_key_ipv4_tunnel *tun_key); +int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb, + const struct ovs_key_ipv4_tunnel *tun_key); #endif /* flow.h */ diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index e284c7e1fec4..98d3edbbc235 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -67,7 +67,7 @@ static struct rtnl_link_stats64 *internal_dev_get_stats(struct net_device *netde static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) { rcu_read_lock(); - ovs_vport_receive(internal_dev_priv(netdev)->vport, skb); + ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL); rcu_read_unlock(); return 0; } diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 40de815b4213..5982f3f62835 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -51,7 +51,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb) skb_push(skb, ETH_HLEN); ovs_skb_postpush_rcsum(skb, skb->data, ETH_HLEN); - ovs_vport_receive(vport, skb); + ovs_vport_receive(vport, skb, NULL); return; error: diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 176d449351eb..413287a1877f 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -325,7 +325,8 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb) * Must be called with rcu_read_lock. The packet cannot be shared and * skb->data should point to the Ethernet header. */ -void ovs_vport_receive(struct vport *vport, struct sk_buff *skb) +void ovs_vport_receive(struct vport *vport, struct sk_buff *skb, + struct ovs_key_ipv4_tunnel *tun_key) { struct pcpu_tstats *stats; @@ -335,6 +336,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb) stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); + OVS_CB(skb)->tun_key = tun_key; ovs_dp_process_received_packet(vport, skb); } diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 293278c4c2df..2d961aedd71d 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -184,7 +184,8 @@ static inline struct vport *vport_from_priv(const void *priv) return (struct vport *)(priv - ALIGN(sizeof(struct vport), VPORT_ALIGN)); } -void ovs_vport_receive(struct vport *, struct sk_buff *); +void ovs_vport_receive(struct vport *, struct sk_buff *, + struct ovs_key_ipv4_tunnel *); void ovs_vport_record_error(struct vport *, enum vport_err_type err_type); /* List of statically compiled vport implementations. Don't forget to also -- GitLab From ffe3f4321745e743dd179ec2b12180c01ba0d3aa Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:23 -0700 Subject: [PATCH 1480/2900] openvswitch: Expand action buffer size. MAX_ACTIONS_BUFSIZE limits action list size, set tunnel action needs extra space on action list, for now increase max actions list limit. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Signed-off-by: David S. Miller --- net/openvswitch/flow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index aec5e43f690b..bfe80b960759 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -159,7 +159,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, const struct nlattr *attr); -#define MAX_ACTIONS_BUFSIZE (16 * 1024) +#define MAX_ACTIONS_BUFSIZE (32 * 1024) #define TBL_MIN_BUCKETS 1024 struct flow_table { -- GitLab From a3e82996a8874c4cfe8c7f1be4d552018d8cba7e Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:28 -0700 Subject: [PATCH 1481/2900] openvswitch: Optimize flow key match for non tunnel flows. Following patch adds start offset for sw_flow-key, so that we can skip tunneling information in key for non-tunnel flows. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 7 ++---- net/openvswitch/flow.c | 49 ++++++++++++++++++++++++++++---------- net/openvswitch/flow.h | 6 ++--- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index bbd310646bc8..f7e3a0d84c40 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -894,10 +894,9 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) if (err) goto err_flow_free; - err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]); + err = ovs_flow_metadata_from_nlattrs(flow, key_len, a[OVS_PACKET_ATTR_KEY]); if (err) goto err_flow_free; - flow->hash = ovs_flow_hash(&flow->key, key_len); acts = ovs_flow_actions_alloc(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); err = PTR_ERR(acts); if (IS_ERR(acts)) @@ -1276,14 +1275,12 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) error = PTR_ERR(flow); goto err_unlock_ovs; } - flow->key = key; clear_stats(flow); rcu_assign_pointer(flow->sf_acts, acts); /* Put flow in bucket. */ - flow->hash = ovs_flow_hash(&key, key_len); - ovs_flow_tbl_insert(table, flow); + ovs_flow_tbl_insert(table, flow, &key, key_len); reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, info->snd_seq, diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 976a8b766a6a..5c519b121e1b 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -353,6 +353,14 @@ struct sw_flow *ovs_flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *la return NULL; } +static void __flow_tbl_insert(struct flow_table *table, struct sw_flow *flow) +{ + struct hlist_head *head; + head = find_bucket(table, flow->hash); + hlist_add_head_rcu(&flow->hash_node[table->node_ver], head); + table->count++; +} + static void flow_table_copy_flows(struct flow_table *old, struct flow_table *new) { int old_ver; @@ -369,7 +377,7 @@ static void flow_table_copy_flows(struct flow_table *old, struct flow_table *new head = flex_array_get(old->buckets, i); hlist_for_each_entry(flow, head, hash_node[old_ver]) - ovs_flow_tbl_insert(new, flow); + __flow_tbl_insert(new, flow); } old->keep_flows = true; } @@ -763,9 +771,18 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, return error; } -u32 ovs_flow_hash(const struct sw_flow_key *key, int key_len) +static u32 ovs_flow_hash(const struct sw_flow_key *key, int key_start, int key_len) +{ + return jhash2((u32 *)((u8 *)key + key_start), + DIV_ROUND_UP(key_len - key_start, sizeof(u32)), 0); +} + +static int flow_key_start(struct sw_flow_key *key) { - return jhash2((u32 *)key, DIV_ROUND_UP(key_len, sizeof(u32)), 0); + if (key->tun_key.ipv4_dst) + return 0; + else + return offsetof(struct sw_flow_key, phy); } struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *table, @@ -773,28 +790,31 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *table, { struct sw_flow *flow; struct hlist_head *head; + u8 *_key; + int key_start; u32 hash; - hash = ovs_flow_hash(key, key_len); + key_start = flow_key_start(key); + hash = ovs_flow_hash(key, key_start, key_len); + _key = (u8 *) key + key_start; head = find_bucket(table, hash); hlist_for_each_entry_rcu(flow, head, hash_node[table->node_ver]) { if (flow->hash == hash && - !memcmp(&flow->key, key, key_len)) { + !memcmp((u8 *)&flow->key + key_start, _key, key_len - key_start)) { return flow; } } return NULL; } -void ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow) +void ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, + struct sw_flow_key *key, int key_len) { - struct hlist_head *head; - - head = find_bucket(table, flow->hash); - hlist_add_head_rcu(&flow->hash_node[table->node_ver], head); - table->count++; + flow->hash = ovs_flow_hash(key, flow_key_start(key), key_len); + memcpy(&flow->key, key, sizeof(flow->key)); + __flow_tbl_insert(table, flow); } void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow) @@ -1235,6 +1255,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, /** * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. * @flow: Receives extracted in_port, priority, tun_key and skb_mark. + * @key_len: Length of key in @flow. Used for calculating flow hash. * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute * sequence. * @@ -1243,7 +1264,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, * get the metadata, that is, the parts of the flow key that cannot be * extracted from the packet itself. */ -int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, +int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, int key_len, const struct nlattr *attr) { struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key; @@ -1289,6 +1310,10 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, } if (rem) return -EINVAL; + + flow->hash = ovs_flow_hash(&flow->key, + flow_key_start(&flow->key), key_len); + return 0; } diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index bfe80b960759..999842f247a0 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -156,7 +156,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, const struct nlattr *); -int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, +int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, int key_len, const struct nlattr *attr); #define MAX_ACTIONS_BUFSIZE (32 * 1024) @@ -188,9 +188,9 @@ void ovs_flow_tbl_deferred_destroy(struct flow_table *table); struct flow_table *ovs_flow_tbl_alloc(int new_size); struct flow_table *ovs_flow_tbl_expand(struct flow_table *table); struct flow_table *ovs_flow_tbl_rehash(struct flow_table *table); -void ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow); +void ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, + struct sw_flow_key *key, int key_len); void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow); -u32 ovs_flow_hash(const struct sw_flow_key *key, int key_len); struct sw_flow *ovs_flow_tbl_next(struct flow_table *table, u32 *bucket, u32 *idx); extern const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1]; -- GitLab From aa310701e787087dbfbccf1409982a96e16c57a6 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 17 Jun 2013 17:50:33 -0700 Subject: [PATCH 1482/2900] openvswitch: Add gre tunnel support. Add gre vport implementation. Most of gre protocol processing is pushed to gre module. It make use of gre demultiplexer therefore it can co-exist with linux device based gre tunnels. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross Signed-off-by: David S. Miller --- include/uapi/linux/openvswitch.h | 1 + net/openvswitch/Kconfig | 2 + net/openvswitch/Makefile | 3 +- net/openvswitch/datapath.h | 1 + net/openvswitch/flow.h | 18 +- net/openvswitch/vport-gre.c | 274 +++++++++++++++++++++++++++++++ net/openvswitch/vport.c | 19 +++ net/openvswitch/vport.h | 7 + 8 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 net/openvswitch/vport-gre.c diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h index b15a445927d6..c55efaaa9bb4 100644 --- a/include/uapi/linux/openvswitch.h +++ b/include/uapi/linux/openvswitch.h @@ -164,6 +164,7 @@ enum ovs_vport_type { OVS_VPORT_TYPE_UNSPEC, OVS_VPORT_TYPE_NETDEV, /* network device */ OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */ + OVS_VPORT_TYPE_GRE, /* GRE tunnel. */ __OVS_VPORT_TYPE_MAX }; diff --git a/net/openvswitch/Kconfig b/net/openvswitch/Kconfig index d9ea33c361be..9fbc04a31ed6 100644 --- a/net/openvswitch/Kconfig +++ b/net/openvswitch/Kconfig @@ -19,6 +19,8 @@ config OPENVSWITCH which is able to accept configuration from a variety of sources and translate it into packet processing rules. + Open vSwitch GRE support depends on CONFIG_NET_IPGRE_DEMUX. + See http://openvswitch.org for more information and userspace utilities. diff --git a/net/openvswitch/Makefile b/net/openvswitch/Makefile index 15e7384745c1..01bddb2991e3 100644 --- a/net/openvswitch/Makefile +++ b/net/openvswitch/Makefile @@ -10,5 +10,6 @@ openvswitch-y := \ dp_notify.o \ flow.o \ vport.o \ + vport-gre.o \ vport-internal_dev.o \ - vport-netdev.o \ + vport-netdev.o diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index e88ebc2f1c54..a91486484916 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h @@ -122,6 +122,7 @@ struct dp_upcall_info { struct ovs_net { struct list_head dps; struct work_struct dp_notify_work; + struct vport_net vport_net; }; extern int ovs_net_id; diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 999842f247a0..66ef7220293e 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -49,11 +49,27 @@ struct ovs_key_ipv4_tunnel { __be64 tun_id; __be32 ipv4_src; __be32 ipv4_dst; - u16 tun_flags; + __be16 tun_flags; u8 ipv4_tos; u8 ipv4_ttl; }; +static inline void ovs_flow_tun_key_init(struct ovs_key_ipv4_tunnel *tun_key, + const struct iphdr *iph, __be64 tun_id, + __be16 tun_flags) +{ + tun_key->tun_id = tun_id; + tun_key->ipv4_src = iph->saddr; + tun_key->ipv4_dst = iph->daddr; + tun_key->ipv4_tos = iph->tos; + tun_key->ipv4_ttl = iph->ttl; + tun_key->tun_flags = tun_flags; + + /* clear struct padding. */ + memset((unsigned char *) tun_key + OVS_TUNNEL_KEY_SIZE, 0, + sizeof(*tun_key) - OVS_TUNNEL_KEY_SIZE); +} + struct sw_flow_key { struct ovs_key_ipv4_tunnel tun_key; /* Encapsulating tunnel key. */ struct { diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c new file mode 100644 index 000000000000..3a8d1900aa78 --- /dev/null +++ b/net/openvswitch/vport-gre.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2007-2013 Nicira, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifdef CONFIG_NET_IPGRE_DEMUX +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "datapath.h" +#include "vport.h" + +/* Returns the least-significant 32 bits of a __be64. */ +static __be32 be64_get_low32(__be64 x) +{ +#ifdef __BIG_ENDIAN + return (__force __be32)x; +#else + return (__force __be32)((__force u64)x >> 32); +#endif +} + +static __be16 filter_tnl_flags(__be16 flags) +{ + return flags & (TUNNEL_CSUM | TUNNEL_KEY); +} + +static struct sk_buff *__build_header(struct sk_buff *skb, + int tunnel_hlen) +{ + const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key; + struct tnl_ptk_info tpi; + + skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM)); + if (IS_ERR(skb)) + return NULL; + + tpi.flags = filter_tnl_flags(tun_key->tun_flags); + tpi.proto = htons(ETH_P_TEB); + tpi.key = be64_get_low32(tun_key->tun_id); + tpi.seq = 0; + gre_build_header(skb, &tpi, tunnel_hlen); + + return skb; +} + +static __be64 key_to_tunnel_id(__be32 key, __be32 seq) +{ +#ifdef __BIG_ENDIAN + return (__force __be64)((__force u64)seq << 32 | (__force u32)key); +#else + return (__force __be64)((__force u64)key << 32 | (__force u32)seq); +#endif +} + +/* Called with rcu_read_lock and BH disabled. */ +static int gre_rcv(struct sk_buff *skb, + const struct tnl_ptk_info *tpi) +{ + struct ovs_key_ipv4_tunnel tun_key; + struct ovs_net *ovs_net; + struct vport *vport; + __be64 key; + + ovs_net = net_generic(dev_net(skb->dev), ovs_net_id); + vport = rcu_dereference(ovs_net->vport_net.gre_vport); + if (unlikely(!vport)) + return PACKET_REJECT; + + key = key_to_tunnel_id(tpi->key, tpi->seq); + ovs_flow_tun_key_init(&tun_key, ip_hdr(skb), key, + filter_tnl_flags(tpi->flags)); + + ovs_vport_receive(vport, skb, &tun_key); + return PACKET_RCVD; +} + +static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) +{ + struct net *net = ovs_dp_get_net(vport->dp); + struct flowi4 fl; + struct rtable *rt; + int min_headroom; + int tunnel_hlen; + __be16 df; + int err; + + if (unlikely(!OVS_CB(skb)->tun_key)) { + err = -EINVAL; + goto error; + } + + /* Route lookup */ + memset(&fl, 0, sizeof(fl)); + fl.daddr = OVS_CB(skb)->tun_key->ipv4_dst; + fl.saddr = OVS_CB(skb)->tun_key->ipv4_src; + fl.flowi4_tos = RT_TOS(OVS_CB(skb)->tun_key->ipv4_tos); + fl.flowi4_mark = skb->mark; + fl.flowi4_proto = IPPROTO_GRE; + + rt = ip_route_output_key(net, &fl); + if (IS_ERR(rt)) + return PTR_ERR(rt); + + tunnel_hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_key->tun_flags); + + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + + tunnel_hlen + sizeof(struct iphdr) + + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); + if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { + int head_delta = SKB_DATA_ALIGN(min_headroom - + skb_headroom(skb) + + 16); + err = pskb_expand_head(skb, max_t(int, head_delta, 0), + 0, GFP_ATOMIC); + if (unlikely(err)) + goto err_free_rt; + } + + if (vlan_tx_tag_present(skb)) { + if (unlikely(!__vlan_put_tag(skb, + skb->vlan_proto, + vlan_tx_tag_get(skb)))) { + err = -ENOMEM; + goto err_free_rt; + } + skb->vlan_tci = 0; + } + + /* Push Tunnel header. */ + skb = __build_header(skb, tunnel_hlen); + if (unlikely(!skb)) { + err = 0; + goto err_free_rt; + } + + df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? + htons(IP_DF) : 0; + + skb->local_df = 1; + + return iptunnel_xmit(net, rt, skb, fl.saddr, + OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE, + OVS_CB(skb)->tun_key->ipv4_tos, + OVS_CB(skb)->tun_key->ipv4_ttl, df); +err_free_rt: + ip_rt_put(rt); +error: + return err; +} + +static struct gre_cisco_protocol gre_protocol = { + .handler = gre_rcv, + .priority = 1, +}; + +static int gre_ports; +static int gre_init(void) +{ + int err; + + gre_ports++; + if (gre_ports > 1) + return 0; + + err = gre_cisco_register(&gre_protocol); + if (err) + pr_warn("cannot register gre protocol handler\n"); + + return err; +} + +static void gre_exit(void) +{ + gre_ports--; + if (gre_ports > 0) + return; + + gre_cisco_unregister(&gre_protocol); +} + +static const char *gre_get_name(const struct vport *vport) +{ + return vport_priv(vport); +} + +static struct vport *gre_create(const struct vport_parms *parms) +{ + struct net *net = ovs_dp_get_net(parms->dp); + struct ovs_net *ovs_net; + struct vport *vport; + int err; + + err = gre_init(); + if (err) + return ERR_PTR(err); + + ovs_net = net_generic(net, ovs_net_id); + if (ovsl_dereference(ovs_net->vport_net.gre_vport)) { + vport = ERR_PTR(-EEXIST); + goto error; + } + + vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms); + if (IS_ERR(vport)) + goto error; + + strncpy(vport_priv(vport), parms->name, IFNAMSIZ); + rcu_assign_pointer(ovs_net->vport_net.gre_vport, vport); + return vport; + +error: + gre_exit(); + return vport; +} + +static void gre_tnl_destroy(struct vport *vport) +{ + struct net *net = ovs_dp_get_net(vport->dp); + struct ovs_net *ovs_net; + + ovs_net = net_generic(net, ovs_net_id); + + rcu_assign_pointer(ovs_net->vport_net.gre_vport, NULL); + ovs_vport_deferred_free(vport); + gre_exit(); +} + +const struct vport_ops ovs_gre_vport_ops = { + .type = OVS_VPORT_TYPE_GRE, + .create = gre_create, + .destroy = gre_tnl_destroy, + .get_name = gre_get_name, + .send = gre_tnl_send, +}; +#endif diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 413287a1877f..f52dfb9cb5a7 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -38,6 +38,10 @@ static const struct vport_ops *vport_ops_list[] = { &ovs_netdev_vport_ops, &ovs_internal_vport_ops, + +#ifdef CONFIG_NET_IPGRE_DEMUX + &ovs_gre_vport_ops, +#endif }; /* Protected by RCU read lock for reading, ovs_mutex for writing. */ @@ -404,3 +408,18 @@ void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type) spin_unlock(&vport->stats_lock); } + +static void free_vport_rcu(struct rcu_head *rcu) +{ + struct vport *vport = container_of(rcu, struct vport, rcu); + + ovs_vport_free(vport); +} + +void ovs_vport_deferred_free(struct vport *vport) +{ + if (!vport) + return; + + call_rcu(&vport->rcu, free_vport_rcu); +} diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 2d961aedd71d..376045c42f8b 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -34,6 +34,11 @@ struct vport_parms; /* The following definitions are for users of the vport subsytem: */ +/* The following definitions are for users of the vport subsytem: */ +struct vport_net { + struct vport __rcu *gre_vport; +}; + int ovs_vport_init(void); void ovs_vport_exit(void); @@ -152,6 +157,7 @@ enum vport_err_type { struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *, const struct vport_parms *); void ovs_vport_free(struct vport *); +void ovs_vport_deferred_free(struct vport *vport); #define VPORT_ALIGN 8 @@ -192,6 +198,7 @@ void ovs_vport_record_error(struct vport *, enum vport_err_type err_type); * add yours to the list at the top of vport.c. */ extern const struct vport_ops ovs_netdev_vport_ops; extern const struct vport_ops ovs_internal_vport_ops; +extern const struct vport_ops ovs_gre_vport_ops; static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb, const void *start, unsigned int len) -- GitLab From 9e77a2b837bbd7197da966f0915e8f1ddb2ca850 Mon Sep 17 00:00:00 2001 From: Amir Vadai Date: Tue, 18 Jun 2013 16:18:27 +0300 Subject: [PATCH 1483/2900] net/mlx4_en: Add Low Latency Socket (LLS) support Add basic support for LLS. Signed-off-by: Amir Vadai Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 3 + .../net/ethernet/mellanox/mlx4/en_netdev.c | 43 ++++++- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 15 ++- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 121 ++++++++++++++++++ 4 files changed, 178 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 1e6c594d6d04..3e2d5047cdb3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -139,6 +139,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, if (!cq->is_tx) { netif_napi_add(cq->dev, &cq->napi, mlx4_en_poll_rx_cq, 64); + napi_hash_add(&cq->napi); napi_enable(&cq->napi); } @@ -162,6 +163,8 @@ void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) { if (!cq->is_tx) { napi_disable(&cq->napi); + napi_hash_del(&cq->napi); + synchronize_rcu(); netif_napi_del(&cq->napi); } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index ade276cca0e6..ab9ec91d1f70 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,30 @@ int mlx4_en_setup_tc(struct net_device *dev, u8 up) return 0; } +#ifdef CONFIG_NET_LL_RX_POLL +/* must be called with local_bh_disable()d */ +static int mlx4_en_low_latency_recv(struct napi_struct *napi) +{ + struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi); + struct net_device *dev = cq->dev; + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_rx_ring *rx_ring = &priv->rx_ring[cq->ring]; + int done; + + if (!priv->port_up) + return LL_FLUSH_FAILED; + + if (!mlx4_en_cq_lock_poll(cq)) + return LL_FLUSH_BUSY; + + done = mlx4_en_process_rx_cq(dev, cq, 4); + + mlx4_en_cq_unlock_poll(cq); + + return done; +} +#endif /* CONFIG_NET_LL_RX_POLL */ + #ifdef CONFIG_RFS_ACCEL struct mlx4_en_filter { @@ -1445,6 +1470,8 @@ int mlx4_en_start_port(struct net_device *dev) for (i = 0; i < priv->rx_ring_num; i++) { cq = &priv->rx_cq[i]; + mlx4_en_cq_init_lock(cq); + err = mlx4_en_activate_cq(priv, cq, i); if (err) { en_err(priv, "Failed activating Rx CQ\n"); @@ -1694,10 +1721,19 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) /* Free RX Rings */ for (i = 0; i < priv->rx_ring_num; i++) { + struct mlx4_en_cq *cq = &priv->rx_cq[i]; + + local_bh_disable(); + while (!mlx4_en_cq_lock_napi(cq)) { + pr_info("CQ %d locked\n", i); + mdelay(1); + } + local_bh_enable(); + mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); - while (test_bit(NAPI_STATE_SCHED, &priv->rx_cq[i].napi.state)) + while (test_bit(NAPI_STATE_SCHED, &cq->napi.state)) msleep(1); - mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]); + mlx4_en_deactivate_cq(priv, cq); } /* close port*/ @@ -2090,6 +2126,9 @@ static const struct net_device_ops mlx4_netdev_ops = { #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = mlx4_en_filter_rfs, #endif +#ifdef CONFIG_NET_LL_RX_POLL + .ndo_ll_poll = mlx4_en_low_latency_recv, +#endif }; static const struct net_device_ops mlx4_netdev_ops_master = { diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 02aee1ebd203..9c57581b021c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -31,6 +31,7 @@ * */ +#include #include #include #include @@ -656,8 +657,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud * - DIX Ethernet (type interpretation) * - TCP/IP (v4) * - without IP options - * - not an IP fragment */ - if (dev->features & NETIF_F_GRO) { + * - not an IP fragment + * - no LLS polling in progress + */ + if (!mlx4_en_cq_ll_polling(cq) && + (dev->features & NETIF_F_GRO)) { struct sk_buff *gro_skb = napi_get_frags(&cq->napi); if (!gro_skb) goto next; @@ -737,6 +741,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud timestamp); } + skb_mark_ll(skb, &cq->napi); + /* Push it up the stack */ netif_receive_skb(skb); @@ -781,8 +787,13 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) struct mlx4_en_priv *priv = netdev_priv(dev); int done; + if (!mlx4_en_cq_lock_napi(cq)) + return budget; + done = mlx4_en_process_rx_cq(dev, cq, budget); + mlx4_en_cq_unlock_napi(cq); + /* If we used up all the quota - we're probably not done yet... */ if (done == budget) INC_PERF_COUNTER(priv->pstats.napi_quota); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index b1f51c1f635c..11c862e4e69d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -310,6 +310,19 @@ struct mlx4_en_cq { u16 moder_cnt; struct mlx4_cqe *buf; #define MLX4_EN_OPCODE_ERROR 0x1e + +#ifdef CONFIG_NET_LL_RX_POLL + unsigned int state; +#define MLX4_EN_CQ_STATE_IDLE 0 +#define MLX4_EN_CQ_STATE_NAPI 1 /* NAPI owns this CQ */ +#define MLX4_EN_CQ_STATE_POLL 2 /* poll owns this CQ */ +#define MLX4_CQ_LOCKED (MLX4_EN_CQ_STATE_NAPI | MLX4_EN_CQ_STATE_POLL) +#define MLX4_EN_CQ_STATE_NAPI_YIELD 4 /* NAPI yielded this CQ */ +#define MLX4_EN_CQ_STATE_POLL_YIELD 8 /* poll yielded this CQ */ +#define CQ_YIELD (MLX4_EN_CQ_STATE_NAPI_YIELD | MLX4_EN_CQ_STATE_POLL_YIELD) +#define CQ_USER_PEND (MLX4_EN_CQ_STATE_POLL | MLX4_EN_CQ_STATE_POLL_YIELD) + spinlock_t poll_lock; /* protects from LLS/napi conflicts */ +#endif /* CONFIG_NET_LL_RX_POLL */ }; struct mlx4_en_port_profile { @@ -562,6 +575,114 @@ struct mlx4_mac_entry { struct rcu_head rcu; }; +#ifdef CONFIG_NET_LL_RX_POLL +static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq) +{ + spin_lock_init(&cq->poll_lock); + cq->state = MLX4_EN_CQ_STATE_IDLE; +} + +/* called from the device poll rutine to get ownership of a cq */ +static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq) +{ + int rc = true; + spin_lock(&cq->poll_lock); + if (cq->state & MLX4_CQ_LOCKED) { + WARN_ON(cq->state & MLX4_EN_CQ_STATE_NAPI); + cq->state |= MLX4_EN_CQ_STATE_NAPI_YIELD; + rc = false; + } else + /* we don't care if someone yielded */ + cq->state = MLX4_EN_CQ_STATE_NAPI; + spin_unlock(&cq->poll_lock); + return rc; +} + +/* returns true is someone tried to get the cq while napi had it */ +static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq) +{ + int rc = false; + spin_lock(&cq->poll_lock); + WARN_ON(cq->state & (MLX4_EN_CQ_STATE_POLL | + MLX4_EN_CQ_STATE_NAPI_YIELD)); + + if (cq->state & MLX4_EN_CQ_STATE_POLL_YIELD) + rc = true; + cq->state = MLX4_EN_CQ_STATE_IDLE; + spin_unlock(&cq->poll_lock); + return rc; +} + +/* called from mlx4_en_low_latency_poll() */ +static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq) +{ + int rc = true; + spin_lock_bh(&cq->poll_lock); + if ((cq->state & MLX4_CQ_LOCKED)) { + struct net_device *dev = cq->dev; + struct mlx4_en_priv *priv = netdev_priv(dev); + struct mlx4_en_rx_ring *rx_ring = &priv->rx_ring[cq->ring]; + + cq->state |= MLX4_EN_CQ_STATE_POLL_YIELD; + rc = false; + } else + /* preserve yield marks */ + cq->state |= MLX4_EN_CQ_STATE_POLL; + spin_unlock_bh(&cq->poll_lock); + return rc; +} + +/* returns true if someone tried to get the cq while it was locked */ +static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq) +{ + int rc = false; + spin_lock_bh(&cq->poll_lock); + WARN_ON(cq->state & (MLX4_EN_CQ_STATE_NAPI)); + + if (cq->state & MLX4_EN_CQ_STATE_POLL_YIELD) + rc = true; + cq->state = MLX4_EN_CQ_STATE_IDLE; + spin_unlock_bh(&cq->poll_lock); + return rc; +} + +/* true if a socket is polling, even if it did not get the lock */ +static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq) +{ + WARN_ON(!(cq->state & MLX4_CQ_LOCKED)); + return cq->state & CQ_USER_PEND; +} +#else +static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq) +{ +} + +static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq) +{ + return true; +} + +static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq) +{ + return false; +} + +static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq) +{ + return false; +} + +static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq) +{ + return false; +} + +static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq) +{ + return false; +} +#endif /* CONFIG_NET_LL_RX_POLL */ + #define MLX4_EN_WOL_DO_MODIFY (1ULL << 63) void mlx4_en_update_loopback_state(struct net_device *dev, -- GitLab From 8501841a4483e678ebd1b7872019621244d0098a Mon Sep 17 00:00:00 2001 From: Amir Vadai Date: Tue, 18 Jun 2013 16:18:28 +0300 Subject: [PATCH 1484/2900] net/mlx4_en: Low Latency recv statistics Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx4/en_ethtool.c | 20 ++++++++++++++++++- .../net/ethernet/mellanox/mlx4/en_netdev.c | 4 ++++ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 6 ++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index c9e6b62dd000..727874f575ce 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -222,7 +222,12 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset) switch (sset) { case ETH_SS_STATS: return (priv->stats_bitmap ? bit_count : NUM_ALL_STATS) + - (priv->tx_ring_num + priv->rx_ring_num) * 2; + (priv->tx_ring_num * 2) + +#ifdef CONFIG_NET_LL_RX_POLL + (priv->rx_ring_num * 5); +#else + (priv->rx_ring_num * 2); +#endif case ETH_SS_TEST: return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2; @@ -271,6 +276,11 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev, for (i = 0; i < priv->rx_ring_num; i++) { data[index++] = priv->rx_ring[i].packets; data[index++] = priv->rx_ring[i].bytes; +#ifdef CONFIG_NET_LL_RX_POLL + data[index++] = priv->rx_ring[i].yields; + data[index++] = priv->rx_ring[i].misses; + data[index++] = priv->rx_ring[i].cleaned; +#endif } spin_unlock_bh(&priv->stats_lock); @@ -334,6 +344,14 @@ static void mlx4_en_get_strings(struct net_device *dev, "rx%d_packets", i); sprintf(data + (index++) * ETH_GSTRING_LEN, "rx%d_bytes", i); +#ifdef CONFIG_NET_LL_RX_POLL + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_napi_yield", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_misses", i); + sprintf(data + (index++) * ETH_GSTRING_LEN, + "rx%d_cleaned", i); +#endif } break; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index ab9ec91d1f70..7299ada876c2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -85,6 +85,10 @@ static int mlx4_en_low_latency_recv(struct napi_struct *napi) return LL_FLUSH_BUSY; done = mlx4_en_process_rx_cq(dev, cq, 4); + if (likely(done)) + rx_ring->cleaned += done; + else + rx_ring->misses++; mlx4_en_cq_unlock_poll(cq); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 11c862e4e69d..57192a8f1d5e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -290,6 +290,11 @@ struct mlx4_en_rx_ring { void *rx_info; unsigned long bytes; unsigned long packets; +#ifdef CONFIG_NET_LL_RX_POLL + unsigned long yields; + unsigned long misses; + unsigned long cleaned; +#endif unsigned long csum_ok; unsigned long csum_none; int hwtstamp_rx_filter; @@ -625,6 +630,7 @@ static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq) cq->state |= MLX4_EN_CQ_STATE_POLL_YIELD; rc = false; + rx_ring->yields++; } else /* preserve yield marks */ cq->state |= MLX4_EN_CQ_STATE_POLL; -- GitLab From 8f20aa575c0a69ccbdce325818f2b3878bfed61c Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 19 Jun 2013 01:36:04 +0300 Subject: [PATCH 1485/2900] bnx2x: add support for ndo_ll_poll Adds ndo_ll_poll method and locking for FPs between LL and the napi. When receiving a packet we use skb_mark_ll to record the napi it came from. Add each napi to the napi_hash right after netif_napi_add(). Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 125 ++++++++++++++++++ .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 67 +++++++++- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 23 +++- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 + 4 files changed, 208 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index f76597e5fa55..edda716fdce4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -485,6 +485,21 @@ struct bnx2x_fastpath { struct bnx2x *bp; /* parent */ struct napi_struct napi; + +#ifdef CONFIG_NET_LL_RX_POLL + unsigned int state; +#define BNX2X_FP_STATE_IDLE 0 +#define BNX2X_FP_STATE_NAPI (1 << 0) /* NAPI owns this FP */ +#define BNX2X_FP_STATE_POLL (1 << 1) /* poll owns this FP */ +#define BNX2X_FP_STATE_NAPI_YIELD (1 << 2) /* NAPI yielded this FP */ +#define BNX2X_FP_STATE_POLL_YIELD (1 << 3) /* poll yielded this FP */ +#define BNX2X_FP_YIELD (BNX2X_FP_STATE_NAPI_YIELD | BNX2X_FP_STATE_POLL_YIELD) +#define BNX2X_FP_LOCKED (BNX2X_FP_STATE_NAPI | BNX2X_FP_STATE_POLL) +#define BNX2X_FP_USER_PEND (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_POLL_YIELD) + /* protect state */ + spinlock_t lock; +#endif /* CONFIG_NET_LL_RX_POLL */ + union host_hc_status_block status_blk; /* chip independent shortcuts into sb structure */ __le16 *sb_index_values; @@ -557,6 +572,116 @@ struct bnx2x_fastpath { #define bnx2x_fp_stats(bp, fp) (&((bp)->fp_stats[(fp)->index])) #define bnx2x_fp_qstats(bp, fp) (&((bp)->fp_stats[(fp)->index].eth_q_stats)) +#ifdef CONFIG_NET_LL_RX_POLL +static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp) +{ + spin_lock_init(&fp->lock); + fp->state = BNX2X_FP_STATE_IDLE; +} + +/* called from the device poll routine to get ownership of a FP */ +static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) +{ + bool rc = true; + + spin_lock(&fp->lock); + if (fp->state & BNX2X_FP_LOCKED) { + WARN_ON(fp->state & BNX2X_FP_STATE_NAPI); + fp->state |= BNX2X_FP_STATE_NAPI_YIELD; + rc = false; + } else { + /* we don't care if someone yielded */ + fp->state = BNX2X_FP_STATE_NAPI; + } + spin_unlock(&fp->lock); + return rc; +} + +/* returns true is someone tried to get the FP while napi had it */ +static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp) +{ + bool rc = false; + + spin_lock(&fp->lock); + WARN_ON(fp->state & + (BNX2X_FP_STATE_POLL | BNX2X_FP_STATE_NAPI_YIELD)); + + if (fp->state & BNX2X_FP_STATE_POLL_YIELD) + rc = true; + fp->state = BNX2X_FP_STATE_IDLE; + spin_unlock(&fp->lock); + return rc; +} + +/* called from bnx2x_low_latency_poll() */ +static inline bool bnx2x_fp_lock_poll(struct bnx2x_fastpath *fp) +{ + bool rc = true; + + spin_lock_bh(&fp->lock); + if ((fp->state & BNX2X_FP_LOCKED)) { + fp->state |= BNX2X_FP_STATE_POLL_YIELD; + rc = false; + } else { + /* preserve yield marks */ + fp->state |= BNX2X_FP_STATE_POLL; + } + spin_unlock_bh(&fp->lock); + return rc; +} + +/* returns true if someone tried to get the FP while it was locked */ +static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) +{ + bool rc = false; + + spin_lock_bh(&fp->lock); + WARN_ON(fp->state & BNX2X_FP_STATE_NAPI); + + if (fp->state & BNX2X_FP_STATE_POLL_YIELD) + rc = true; + fp->state = BNX2X_FP_STATE_IDLE; + spin_unlock_bh(&fp->lock); + return rc; +} + +/* true if a socket is polling, even if it did not get the lock */ +static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp) +{ + WARN_ON(!(fp->state & BNX2X_FP_LOCKED)); + return fp->state & BNX2X_FP_USER_PEND; +} +#else +static inline void bnx2x_fp_init_lock(struct bnx2x_fastpath *fp) +{ +} + +static inline bool bnx2x_fp_lock_napi(struct bnx2x_fastpath *fp) +{ + return true; +} + +static inline bool bnx2x_fp_unlock_napi(struct bnx2x_fastpath *fp) +{ + return false; +} + +static inline bool bnx2x_fp_lock_poll(struct bnx2x_fastpath *fp) +{ + return false; +} + +static inline bool bnx2x_fp_unlock_poll(struct bnx2x_fastpath *fp) +{ + return false; +} + +static inline bool bnx2x_fp_ll_polling(struct bnx2x_fastpath *fp) +{ + return false; +} +#endif /* CONFIG_NET_LL_RX_POLL */ + /* Use 2500 as a mini-jumbo MTU for FCoE */ #define BNX2X_FCOE_MINI_JUMBO_MTU 2500 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 4e42bdd7c522..20eefa6809e6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "bnx2x_cmn.h" #include "bnx2x_init.h" @@ -999,8 +1000,13 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) PARSING_FLAGS_VLAN) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), le16_to_cpu(cqe_fp->vlan_tag)); - napi_gro_receive(&fp->napi, skb); + skb_mark_ll(skb, &fp->napi); + + if (bnx2x_fp_ll_polling(fp)) + netif_receive_skb(skb); + else + napi_gro_receive(&fp->napi, skb); next_rx: rx_buf->data = NULL; @@ -1755,32 +1761,46 @@ static void bnx2x_napi_enable_cnic(struct bnx2x *bp) { int i; - for_each_rx_queue_cnic(bp, i) + for_each_rx_queue_cnic(bp, i) { + bnx2x_fp_init_lock(&bp->fp[i]); napi_enable(&bnx2x_fp(bp, i, napi)); + } } static void bnx2x_napi_enable(struct bnx2x *bp) { int i; - for_each_eth_queue(bp, i) + for_each_eth_queue(bp, i) { + bnx2x_fp_init_lock(&bp->fp[i]); napi_enable(&bnx2x_fp(bp, i, napi)); + } } static void bnx2x_napi_disable_cnic(struct bnx2x *bp) { int i; - for_each_rx_queue_cnic(bp, i) + local_bh_disable(); + for_each_rx_queue_cnic(bp, i) { napi_disable(&bnx2x_fp(bp, i, napi)); + while (!bnx2x_fp_lock_napi(&bp->fp[i])) + mdelay(1); + } + local_bh_enable(); } static void bnx2x_napi_disable(struct bnx2x *bp) { int i; - for_each_eth_queue(bp, i) + local_bh_disable(); + for_each_eth_queue(bp, i) { napi_disable(&bnx2x_fp(bp, i, napi)); + while (!bnx2x_fp_lock_napi(&bp->fp[i])) + mdelay(1); + } + local_bh_enable(); } void bnx2x_netif_start(struct bnx2x *bp) @@ -3039,6 +3059,8 @@ int bnx2x_poll(struct napi_struct *napi, int budget) return 0; } #endif + if (!bnx2x_fp_lock_napi(fp)) + return work_done; for_each_cos_in_tx_queue(fp, cos) if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos])) @@ -3048,12 +3070,15 @@ int bnx2x_poll(struct napi_struct *napi, int budget) work_done += bnx2x_rx_int(fp, budget - work_done); /* must not complete if we consumed full budget */ - if (work_done >= budget) + if (work_done >= budget) { + bnx2x_fp_unlock_napi(fp); break; + } } /* Fall out from the NAPI loop if needed */ - if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { + if (!bnx2x_fp_unlock_napi(fp) && + !(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { /* No need to update SB for FCoE L2 ring as long as * it's connected to the default SB and the SB @@ -3095,6 +3120,34 @@ int bnx2x_poll(struct napi_struct *napi, int budget) return work_done; } +#ifdef CONFIG_NET_LL_RX_POLL +/* must be called with local_bh_disable()d */ +int bnx2x_low_latency_recv(struct napi_struct *napi) +{ + struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, + napi); + struct bnx2x *bp = fp->bp; + int found = 0; + + if ((bp->state == BNX2X_STATE_CLOSED) || + (bp->state == BNX2X_STATE_ERROR) || + (bp->flags & (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG))) + return LL_FLUSH_FAILED; + + if (!bnx2x_fp_lock_poll(fp)) + return LL_FLUSH_BUSY; + + if (bnx2x_has_rx_work(fp)) { + bnx2x_update_fpsb_idx(fp); + found = bnx2x_rx_int(fp, 4); + } + + bnx2x_fp_unlock_poll(fp); + + return found; +} +#endif + /* we split the first BD into headers and data BDs * to ease the pain of our fellow microcode engineers * we use one mapping for both BDs diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 650bb52155a8..a1a5cdca114c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -604,6 +604,13 @@ int bnx2x_enable_msi(struct bnx2x *bp); */ int bnx2x_poll(struct napi_struct *napi, int budget); +/** + * bnx2x_low_latency_recv - LL callback + * + * @napi: napi structure + */ +int bnx2x_low_latency_recv(struct napi_struct *napi); + /** * bnx2x_alloc_mem_bp - allocate memories outsize main driver structure * @@ -846,9 +853,11 @@ static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp) int i; /* Add NAPI objects */ - for_each_rx_queue_cnic(bp, i) + for_each_rx_queue_cnic(bp, i) { netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, NAPI_POLL_WEIGHT); + napi_hash_add(&bnx2x_fp(bp, i, napi)); + } } static inline void bnx2x_add_all_napi(struct bnx2x *bp) @@ -856,25 +865,31 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp) int i; /* Add NAPI objects */ - for_each_eth_queue(bp, i) + for_each_eth_queue(bp, i) { netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), bnx2x_poll, NAPI_POLL_WEIGHT); + napi_hash_add(&bnx2x_fp(bp, i, napi)); + } } static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp) { int i; - for_each_rx_queue_cnic(bp, i) + for_each_rx_queue_cnic(bp, i) { + napi_hash_del(&bnx2x_fp(bp, i, napi)); netif_napi_del(&bnx2x_fp(bp, i, napi)); + } } static inline void bnx2x_del_all_napi(struct bnx2x *bp) { int i; - for_each_eth_queue(bp, i) + for_each_eth_queue(bp, i) { + napi_hash_del(&bnx2x_fp(bp, i, napi)); netif_napi_del(&bnx2x_fp(bp, i, napi)); + } } int bnx2x_set_int_mode(struct bnx2x *bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 658b9fd0275f..e2e870568455 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12013,6 +12013,10 @@ static const struct net_device_ops bnx2x_netdev_ops = { #ifdef NETDEV_FCOE_WWNN .ndo_fcoe_get_wwn = bnx2x_fcoe_get_wwn, #endif + +#ifdef CONFIG_NET_LL_RX_POLL + .ndo_ll_poll = bnx2x_low_latency_recv, +#endif }; static int bnx2x_set_coherency_mask(struct bnx2x *bp) -- GitLab From 75b2945988274078bccf4c0b84e90c77b4fcaf96 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Wed, 19 Jun 2013 01:36:05 +0300 Subject: [PATCH 1486/2900] bnx2x: replace mechanism to check for next available packet Check next packet availability by validating that HW has finished CQE placement. This saves latency of another dma transaction performed to update SB indexes. Signed-off-by: Dmitry Kravkov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 49 ++++++++----------- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 26 +++++++--- .../net/ethernet/broadcom/bnx2x/bnx2x_hsi.h | 3 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 1 - 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 20eefa6809e6..ca7f2bb08f44 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -804,40 +804,32 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) { struct bnx2x *bp = fp->bp; u16 bd_cons, bd_prod, bd_prod_fw, comp_ring_cons; - u16 hw_comp_cons, sw_comp_cons, sw_comp_prod; + u16 sw_comp_cons, sw_comp_prod; int rx_pkt = 0; + union eth_rx_cqe *cqe; + struct eth_fast_path_rx_cqe *cqe_fp; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return 0; #endif - /* CQ "next element" is of the size of the regular element, - that's why it's ok here */ - hw_comp_cons = le16_to_cpu(*fp->rx_cons_sb); - if ((hw_comp_cons & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - hw_comp_cons++; - bd_cons = fp->rx_bd_cons; bd_prod = fp->rx_bd_prod; bd_prod_fw = bd_prod; sw_comp_cons = fp->rx_comp_cons; sw_comp_prod = fp->rx_comp_prod; - /* Memory barrier necessary as speculative reads of the rx - * buffer can be ahead of the index in the status block - */ - rmb(); + comp_ring_cons = RCQ_BD(sw_comp_cons); + cqe = &fp->rx_comp_ring[comp_ring_cons]; + cqe_fp = &cqe->fast_path_cqe; DP(NETIF_MSG_RX_STATUS, - "queue[%d]: hw_comp_cons %u sw_comp_cons %u\n", - fp->index, hw_comp_cons, sw_comp_cons); + "queue[%d]: sw_comp_cons %u\n", fp->index, sw_comp_cons); - while (sw_comp_cons != hw_comp_cons) { + while (BNX2X_IS_CQE_COMPLETED(cqe_fp)) { struct sw_rx_bd *rx_buf = NULL; struct sk_buff *skb; - union eth_rx_cqe *cqe; - struct eth_fast_path_rx_cqe *cqe_fp; u8 cqe_fp_flags; enum eth_rx_cqe_type cqe_fp_type; u16 len, pad, queue; @@ -849,12 +841,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) return 0; #endif - comp_ring_cons = RCQ_BD(sw_comp_cons); bd_prod = RX_BD(bd_prod); bd_cons = RX_BD(bd_cons); - cqe = &fp->rx_comp_ring[comp_ring_cons]; - cqe_fp = &cqe->fast_path_cqe; cqe_fp_flags = cqe_fp->type_error_flags; cqe_fp_type = cqe_fp_flags & ETH_FAST_PATH_RX_CQE_TYPE; @@ -1018,8 +1007,15 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) sw_comp_prod = NEXT_RCQ_IDX(sw_comp_prod); sw_comp_cons = NEXT_RCQ_IDX(sw_comp_cons); + /* mark CQE as free */ + BNX2X_SEED_CQE(cqe_fp); + if (rx_pkt == budget) break; + + comp_ring_cons = RCQ_BD(sw_comp_cons); + cqe = &fp->rx_comp_ring[comp_ring_cons]; + cqe_fp = &cqe->fast_path_cqe; } /* while */ fp->rx_bd_cons = bd_cons; @@ -1055,8 +1051,6 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) #endif /* Handle Rx and Tx according to MSI-X vector */ - prefetch(fp->rx_cons_sb); - for_each_cos_in_tx_queue(fp, cos) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); @@ -3137,10 +3131,8 @@ int bnx2x_low_latency_recv(struct napi_struct *napi) if (!bnx2x_fp_lock_poll(fp)) return LL_FLUSH_BUSY; - if (bnx2x_has_rx_work(fp)) { - bnx2x_update_fpsb_idx(fp); + if (bnx2x_has_rx_work(fp)) found = bnx2x_rx_int(fp, 4); - } bnx2x_fp_unlock_poll(fp); @@ -4339,10 +4331,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) &bnx2x_fp(bp, index, rx_desc_mapping), sizeof(struct eth_rx_bd) * NUM_RX_BD); - BNX2X_PCI_ALLOC(bnx2x_fp(bp, index, rx_comp_ring), - &bnx2x_fp(bp, index, rx_comp_mapping), - sizeof(struct eth_fast_path_rx_cqe) * - NUM_RCQ_BD); + /* Seed all CQEs by 1s */ + BNX2X_PCI_FALLOC(bnx2x_fp(bp, index, rx_comp_ring), + &bnx2x_fp(bp, index, rx_comp_mapping), + sizeof(struct eth_fast_path_rx_cqe) * + NUM_RCQ_BD); /* SGE ring */ BNX2X_ALLOC(bnx2x_fp(bp, index, rx_page_ring), diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index a1a5cdca114c..c07a6d054cfe 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -59,6 +59,16 @@ extern int int_mode; (unsigned long long)(*y), x); \ } while (0) +#define BNX2X_PCI_FALLOC(x, y, size) \ + do { \ + x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \ + if (x == NULL) \ + goto alloc_mem_err; \ + memset((void *)x, 0xFFFFFFFF, size); \ + DP(NETIF_MSG_HW, "BNX2X_PCI_FALLOC: Physical %Lx Virtual %p\n",\ + (unsigned long long)(*y), x); \ + } while (0) + #define BNX2X_ALLOC(x, size) \ do { \ x = kzalloc(size, GFP_KERNEL); \ @@ -805,16 +815,18 @@ static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp) return false; } +#define BNX2X_IS_CQE_COMPLETED(cqe_fp) (cqe_fp->marker == 0x0) +#define BNX2X_SEED_CQE(cqe_fp) (cqe_fp->marker = 0xFFFFFFFF) static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp) { - u16 rx_cons_sb; + u16 cons; + union eth_rx_cqe *cqe; + struct eth_fast_path_rx_cqe *cqe_fp; - /* Tell compiler that status block fields can change */ - barrier(); - rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); - if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) - rx_cons_sb++; - return (fp->rx_comp_cons != rx_cons_sb); + cons = RCQ_BD(fp->rx_comp_cons); + cqe = &fp->rx_comp_ring[cons]; + cqe_fp = &cqe->fast_path_cqe; + return BNX2X_IS_CQE_COMPLETED(cqe_fp); } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 5ef3f964e544..5018e52ae2ad 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -3818,7 +3818,8 @@ struct eth_fast_path_rx_cqe { __le16 len_on_bd; struct parsing_flags pars_flags; union eth_sgl_or_raw_data sgl_or_raw_data; - __le32 reserved1[8]; + __le32 reserved1[7]; + u32 marker; }; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index e2e870568455..f0d21faf71ec 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -1866,7 +1866,6 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) mask = 0x2 << (fp->index + CNIC_SUPPORT(bp)); if (status & mask) { /* Handle Rx or Tx according to SB id */ - prefetch(fp->rx_cons_sb); for_each_cos_in_tx_queue(fp, cos) prefetch(fp->txdata_ptr[cos]->tx_cons_sb); prefetch(&fp->sb_running_index[SM_RX_ID]); -- GitLab From 1a891cf19cdfb645827969cc6aeaeebdefeb87b2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 12 Jun 2013 13:16:25 -0400 Subject: [PATCH 1487/2900] tracing: Add binary '&' filter for events There are some cases when filtering on a set flag of a field of a tracepoint is useful. But currently the only filtering commands for numbered fields is ==, !=, <, <=, >, >=. This does not help when you just want to trace if a specific flag is set. For example: > # sudo trace-cmd record -e brcmfmac:brcmf_dbg -f 'level & 0x40000' > disable all > enable brcmfmac:brcmf_dbg > path = /sys/kernel/debug/tracing/events/brcmfmac/brcmf_dbg/enable > (level & 0x40000) > ^ > parse_error: Invalid operator > When trying to trace brcmf_dbg when level has its 1 << 18 bit set, the filter fails to perform. By allowing a binary '&' operation, this gives the user the ability to test a bit. Note, a binary '|' is not added, as it doesn't make sense as fields must be compared to constants (for now), and ORing a constant will always return true. Link: http://lkml.kernel.org/r/1371057385.9844.261.camel@gandalf.local.home Suggested-by: Arend van Spriel Tested-by: Arend van Spriel Signed-off-by: Steven Rostedt --- Documentation/trace/events.txt | 2 +- kernel/trace/trace_events_filter.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index bb24c2a0e870..41911240c65c 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -183,7 +183,7 @@ The relational-operators depend on the type of the field being tested: The operators available for numeric fields are: -==, !=, <, <=, >, >= +==, !=, <, <=, >, >=, & And for string fields they are: diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index e1b653f7e1ca..0d883dc057d6 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -44,6 +44,7 @@ enum filter_op_ids OP_LE, OP_GT, OP_GE, + OP_BAND, OP_NONE, OP_OPEN_PAREN, }; @@ -54,6 +55,7 @@ struct filter_op { int precedence; }; +/* Order must be the same as enum filter_op_ids above */ static struct filter_op filter_ops[] = { { OP_OR, "||", 1 }, { OP_AND, "&&", 2 }, @@ -64,6 +66,7 @@ static struct filter_op filter_ops[] = { { OP_LE, "<=", 5 }, { OP_GT, ">", 5 }, { OP_GE, ">=", 5 }, + { OP_BAND, "&", 6 }, { OP_NONE, "OP_NONE", 0 }, { OP_OPEN_PAREN, "(", 0 }, }; @@ -156,6 +159,9 @@ static int filter_pred_##type(struct filter_pred *pred, void *event) \ case OP_GE: \ match = (*addr >= val); \ break; \ + case OP_BAND: \ + match = (*addr & val); \ + break; \ default: \ break; \ } \ -- GitLab From c3e13c7c0605677a2c94957b39157f4501cea9a8 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 17 Jun 2013 10:59:17 -0400 Subject: [PATCH 1488/2900] tracing: Update documentation on tracepoint glob matching b0f1a59a "tracing/filters: Use a different op for glob match" added glob matching to tracepoint filter strings. It uses the ftrace function tracing glob matching facility that allows for the wild card character (*) to be used at the start and/or end of the matching string. But the documentation still states that the filtering only allows for exact string matches. Cc: Li Zefan Signed-off-by: Steven Rostedt --- Documentation/trace/events.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index 41911240c65c..37732a220d33 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -187,9 +187,18 @@ The operators available for numeric fields are: And for string fields they are: -==, != +==, !=, ~ -Currently, only exact string matches are supported. +The glob (~) only accepts a wild card character (*) at the start and or +end of the string. For example: + + prev_comm ~ "*sh" + prev_comm ~ "sh*" + prev_comm ~ "*sh*" + +But does not allow for it to be within the string: + + prev_comm ~ "ba*sh" <-- is invalid 5.2 Setting filters ------------------- -- GitLab From de7edd31457b626e54a0b2a7e8ff4d65492f01ad Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 14 Jun 2013 16:21:43 -0400 Subject: [PATCH 1489/2900] tracing: Disable tracing on warning Add a traceoff_on_warning option in both the kernel command line as well as a sysctl option. When set, any WARN*() function that is hit will cause the tracing_on variable to be cleared, which disables writing to the ring buffer. This is useful especially when tracing a bug with function tracing. When a warning is hit, the print caused by the warning can flood the trace with the functions that producing the output for the warning. This can make the resulting trace useless by either hiding where the bug happened, or worse, by overflowing the buffer and losing the trace of the bug totally. Acked-by: Peter Zijlstra Signed-off-by: Steven Rostedt --- Documentation/kernel-parameters.txt | 13 +++++++++++++ include/linux/ftrace.h | 5 +++++ kernel/panic.c | 3 +++ kernel/sysctl.c | 7 +++++++ kernel/trace/trace.c | 17 +++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6e3b18a8afc6..729d0b9803b7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -3069,6 +3069,19 @@ bytes respectively. Such letter suffixes can also be entirely omitted. See also Documentation/trace/ftrace.txt "trace options" section. + traceoff_on_warning + [FTRACE] enable this option to disable tracing when a + warning is hit. This turns off "tracing_on". Tracing can + be enabled again by echoing '1' into the "tracing_on" + file located in /sys/kernel/debug/tracing/ + + This option is useful, as it disables the trace before + the WARNING dump is called, which prevents the trace to + be filled with content caused by the warning output. + + This option can also be set at run time via the sysctl + option: kernel/traceoff_on_warning + transparent_hugepage= [KNL] Format: [always|madvise|never] diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index e48ed1d7876d..9f15c0064c50 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -824,10 +824,15 @@ enum ftrace_dump_mode; extern enum ftrace_dump_mode ftrace_dump_on_oops; +extern void disable_trace_on_warning(void); +extern int __disable_trace_on_warning; + #ifdef CONFIG_PREEMPT #define INIT_TRACE_RECURSION .trace_recursion = 0, #endif +#else /* CONFIG_TRACING */ +static inline void disable_trace_on_warning(void) { } #endif /* CONFIG_TRACING */ #ifndef INIT_TRACE_RECURSION diff --git a/kernel/panic.c b/kernel/panic.c index 167ec097ce8b..4cea6cc628ab 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -399,6 +400,8 @@ struct slowpath_args { static void warn_slowpath_common(const char *file, int line, void *caller, unsigned taint, struct slowpath_args *args) { + disable_trace_on_warning(); + printk(KERN_WARNING "------------[ cut here ]------------\n"); printk(KERN_WARNING "WARNING: at %s:%d %pS()\n", file, line, caller); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9edcf456e0fc..5b0f18c12800 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -600,6 +600,13 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "traceoff_on_warning", + .data = &__disable_trace_on_warning, + .maxlen = sizeof(__disable_trace_on_warning), + .mode = 0644, + .proc_handler = proc_dointvec, + }, #endif #ifdef CONFIG_MODULES { diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 5f4a09c12e0b..c4c9296b1916 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -115,6 +115,9 @@ cpumask_var_t __read_mostly tracing_buffer_mask; enum ftrace_dump_mode ftrace_dump_on_oops; +/* When set, tracing will stop when a WARN*() is hit */ +int __disable_trace_on_warning; + static int tracing_set_tracer(const char *buf); #define MAX_TRACER_SIZE 100 @@ -149,6 +152,13 @@ static int __init set_ftrace_dump_on_oops(char *str) } __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); +static int __init stop_trace_on_warning(char *str) +{ + __disable_trace_on_warning = 1; + return 1; +} +__setup("traceoff_on_warning=", stop_trace_on_warning); + static int __init boot_alloc_snapshot(char *str) { allocate_snapshot = true; @@ -170,6 +180,7 @@ static int __init set_trace_boot_options(char *str) } __setup("trace_options=", set_trace_boot_options); + unsigned long long ns2usecs(cycle_t nsec) { nsec += 500; @@ -562,6 +573,12 @@ void tracing_off(void) } EXPORT_SYMBOL_GPL(tracing_off); +void disable_trace_on_warning(void) +{ + if (__disable_trace_on_warning) + tracing_off(); +} + /** * tracing_is_on - show state of ring buffers enabled */ -- GitLab From 195a84d91e92ee3fe571a2086a6db7e17bf5bc7c Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Fri, 14 Jun 2013 10:10:38 +0800 Subject: [PATCH 1490/2900] tracing/kprobes: Remove unnecessary checking of trace_probe_is_enabled Since tp->flags assignment was moved into function enable_trace_probe(), there is no need to use trace_probe_is_enabled to check flags in the same function. Remove the unnecessary checking. Link: http://lkml.kernel.org/r/51BA7B9E.3040807@huawei.com Acked-by: Masami Hiramatsu Cc: Frederic Weisbecker Cc: Oleg Nesterov Cc: Srikar Dronamraju Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 9f46e98ba8f2..f2374172ba7b 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -240,8 +240,7 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) } else tp->flags |= TP_FLAG_PROFILE; - if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && - !trace_probe_has_gone(tp)) { + if (trace_probe_is_registered(tp) && !trace_probe_has_gone(tp)) { if (trace_probe_is_return(tp)) ret = enable_kretprobe(&tp->rp); else -- GitLab From 52d85d763086594f139bf7d3a5641abeb91d9f57 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Wed, 12 Jun 2013 12:03:18 +0200 Subject: [PATCH 1491/2900] ftrace: Fix stddev calculation in function profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When FUNCTION_GRAPH_TRACER is enabled, ftrace can profile kernel functions and print basic statistics about them. Unfortunately, running stddev calculation is wrong. This patch corrects it implementing Welford’s method: s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) . Link: http://lkml.kernel.org/r/1371031398-24048-1-git-send-email-juri.lelli@gmail.com Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Juri Lelli Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 800a8a2fbddb..26e19105cdcc 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -641,12 +641,18 @@ static int function_stat_show(struct seq_file *m, void *v) if (rec->counter <= 1) stddev = 0; else { - stddev = rec->time_squared - rec->counter * avg * avg; + /* + * Apply Welford's method: + * s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2) + */ + stddev = rec->counter * rec->time_squared - + rec->time * rec->time; + /* * Divide only 1000 for ns^2 -> us^2 conversion. * trace_print_graph_duration will divide 1000 again. */ - do_div(stddev, (rec->counter - 1) * 1000); + do_div(stddev, rec->counter * (rec->counter - 1) * 1000); } trace_seq_init(&s); -- GitLab From cf89d6b2803ab99ac596f95d585c3057d2be645c Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 20 Jun 2013 10:01:32 +0800 Subject: [PATCH 1492/2900] neigh: no need to call lookup_neigh_parms in neigh_parms_alloc neigh_table.parms always exist and is initialized,kmemdup can use it to create new neigh_parms, actually lookup_neigh_parms here will return neigh_table.parms too. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- net/core/neighbour.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index decaa4b9db2f..53eab513955a 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1429,15 +1429,11 @@ static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl, struct neigh_parms *neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl) { - struct neigh_parms *p, *ref; + struct neigh_parms *p; struct net *net = dev_net(dev); const struct net_device_ops *ops = dev->netdev_ops; - ref = lookup_neigh_parms(tbl, net, 0); - if (!ref) - return NULL; - - p = kmemdup(ref, sizeof(*p), GFP_KERNEL); + p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL); if (p) { p->tbl = tbl; atomic_set(&p->refcnt, 1); -- GitLab From 170d6f99541600ec7512f1d2b0b0c349009098d2 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 20 Jun 2013 10:01:33 +0800 Subject: [PATCH 1493/2900] neigh: only allow init_net to change the default neigh_parms Though we don't export the /proc/sys/net/ipv[4,6]/neigh/default/ directory to the un-init_net, but we can still use cmd such as "ip ntable change name arp_cache locktime 129" to change the locktime of default neigh_parms. This patch disallows the un-init_net to find out the neigh_table.parms. So the un-init_net will failed to influence the init_net. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 53eab513955a..86f9b165bbba 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1419,7 +1419,7 @@ static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl, for (p = &tbl->parms; p; p = p->next) { if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) || - (!p->dev && !ifindex)) + (!p->dev && !ifindex && net_eq(net, &init_net))) return p; } -- GitLab From dc25c676f54addb10e598daa9da9b8dd4fd487ab Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 20 Jun 2013 10:01:34 +0800 Subject: [PATCH 1494/2900] neigh: disallow un-init_net to change thresh of neigh thresh and interval are global resources, only init net can change them. Signed-off-by: Gao feng Signed-off-by: David S. Miller --- net/core/neighbour.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 86f9b165bbba..2569ab2cafbe 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2049,6 +2049,12 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh) } } + err = -ENOENT; + if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || + tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) && + !net_eq(net, &init_net)) + goto errout_tbl_lock; + if (tb[NDTA_THRESH1]) tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); -- GitLab From eea86af6b1e18d6fa8dc959e3ddc0100f27aff9f Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 19 Jun 2013 12:51:20 +0200 Subject: [PATCH 1495/2900] net: sock: adapt SOCK_MIN_RCVBUF and SOCK_MIN_SNDBUF The current situation is that SOCK_MIN_RCVBUF is 2048 + sizeof(struct sk_buff)) while SOCK_MIN_SNDBUF is 2048. Since in both cases, skb->truesize is used for sk_{r,w}mem_alloc accounting, we should have both sizes adjusted via defining a TCP_SKB_MIN_TRUESIZE. Further, as Eric Dumazet points out, the minimal skb truesize in transmit path is SKB_TRUESIZE(2048) after commit f07d960df33c5 ("tcp: avoid frag allocation for small frames"), and tcp_sendmsg() tries to limit skb size to half the congestion window, meaning we try to build two skbs at minimum. Thus, having SOCK_MIN_SNDBUF as 2048 can hit a small regression for some applications setting to low SO_SNDBUF / SO_RCVBUF. Note that we define a TCP_SKB_MIN_TRUESIZE, because SKB_TRUESIZE(2048) adds SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), but in case of TCP skbs, the skb_shared_info is part of the 2048 bytes allocation for skb->head. The minor adaption in sk_stream_moderate_sndbuf() is to silence a warning by using a typed max macro, as similarly done in SOCK_MIN_RCVBUF occurences, that would appear otherwise. Suggested-by: Eric Dumazet Signed-off-by: Daniel Borkmann Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 21db792bffa5..ea6206ccc896 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2047,18 +2047,21 @@ static inline void sk_wake_async(struct sock *sk, int how, int band) sock_wake_async(sk->sk_socket, how, band); } -#define SOCK_MIN_SNDBUF 2048 -/* - * Since sk_rmem_alloc sums skb->truesize, even a small frame might need - * sizeof(sk_buff) + MTU + padding, unless net driver perform copybreak +/* Since sk_{r,w}mem_alloc sums skb->truesize, even a small frame might + * need sizeof(sk_buff) + MTU + padding, unless net driver perform copybreak. + * Note: for send buffers, TCP works better if we can build two skbs at + * minimum. */ -#define SOCK_MIN_RCVBUF (2048 + sizeof(struct sk_buff)) +#define TCP_SKB_MIN_TRUESIZE (2048 + sizeof(struct sk_buff)) + +#define SOCK_MIN_SNDBUF (TCP_SKB_MIN_TRUESIZE * 2) +#define SOCK_MIN_RCVBUF TCP_SKB_MIN_TRUESIZE static inline void sk_stream_moderate_sndbuf(struct sock *sk) { if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) { sk->sk_sndbuf = min(sk->sk_sndbuf, sk->sk_wmem_queued >> 1); - sk->sk_sndbuf = max(sk->sk_sndbuf, SOCK_MIN_SNDBUF); + sk->sk_sndbuf = max_t(u32, sk->sk_sndbuf, SOCK_MIN_SNDBUF); } } -- GitLab From c2ff682a6f5c5ae2cb23b32bb4fd7a6fb059d4fc Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 19 Jun 2013 12:03:13 +0200 Subject: [PATCH 1496/2900] sit: fix an oops when IFLA_IPTUN_PROTO is not set The use of this attribute has been added in 32b8a8e59c9c (sit: add IPv4 over IPv4 support). It is optional, by default proto is IPPROTO_IPV6. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 6cee844678e2..f639866b3dcf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1296,7 +1296,7 @@ static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[]) { u8 proto; - if (!data) + if (!data || !data[IFLA_IPTUN_PROTO]) return 0; proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); -- GitLab From 257a3feb3f144783184adb2df930331cbe36ff25 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Fri, 14 Jun 2013 15:54:51 +0530 Subject: [PATCH 1497/2900] be2net: use pci_vfs_assigned()/pci_num_vf() instead of be_find_vfs() be_find_vfs() is no longer needed as the common PCI calls provide the same functionality. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 31 +++------------------ 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 98efc29eaa55..cd69ac79f565 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1262,30 +1262,6 @@ static int be_set_vf_tx_rate(struct net_device *netdev, return status; } -static int be_find_vfs(struct be_adapter *adapter, int vf_state) -{ - struct pci_dev *dev, *pdev = adapter->pdev; - int vfs = 0, assigned_vfs = 0, pos; - u16 offset, stride; - - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); - if (!pos) - return 0; - pci_read_config_word(pdev, pos + PCI_SRIOV_VF_OFFSET, &offset); - pci_read_config_word(pdev, pos + PCI_SRIOV_VF_STRIDE, &stride); - - dev = pci_get_device(pdev->vendor, PCI_ANY_ID, NULL); - while (dev) { - if (dev->is_virtfn && pci_physfn(dev) == pdev) { - vfs++; - if (dev->dev_flags & PCI_DEV_FLAGS_ASSIGNED) - assigned_vfs++; - } - dev = pci_get_device(pdev->vendor, PCI_ANY_ID, dev); - } - return (vf_state == ASSIGNED) ? assigned_vfs : vfs; -} - static void be_eqd_update(struct be_adapter *adapter, struct be_eq_obj *eqo) { struct be_rx_stats *stats = rx_stats(&adapter->rx_obj[eqo->idx]); @@ -2797,7 +2773,7 @@ static void be_vf_clear(struct be_adapter *adapter) struct be_vf_cfg *vf_cfg; u32 vf; - if (be_find_vfs(adapter, ASSIGNED)) { + if (pci_vfs_assigned(adapter->pdev)) { dev_warn(&adapter->pdev->dev, "VFs are assigned to VMs: not disabling VFs\n"); goto done; @@ -2899,7 +2875,7 @@ static int be_vf_setup(struct be_adapter *adapter) int status, old_vfs, vf; struct device *dev = &adapter->pdev->dev; - old_vfs = be_find_vfs(adapter, ENABLED); + old_vfs = pci_num_vf(adapter->pdev); if (old_vfs) { dev_info(dev, "%d VFs are already enabled\n", old_vfs); if (old_vfs != num_vfs) @@ -4200,9 +4176,10 @@ static void be_worker(struct work_struct *work) schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } +/* If any VFs are already enabled don't FLR the PF */ static bool be_reset_required(struct be_adapter *adapter) { - return be_find_vfs(adapter, ENABLED) > 0 ? false : true; + return pci_num_vf(adapter->pdev) ? false : true; } static char *mc_name(struct be_adapter *adapter) -- GitLab From b88ec38d139c0aadc5fa48dff2b62e7b874a573d Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Tue, 18 Jun 2013 13:44:52 +0200 Subject: [PATCH 1498/2900] bonding: trivial: make alb use bond_slave_has_mac() Also, cleanup bond_alb_handle_active_change() from 2 identical ifs. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 53 +++++++--------------------------- 1 file changed, 11 insertions(+), 42 deletions(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 27fe329bdf83..4ea8ed150d46 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1129,6 +1129,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla { int perm_curr_diff; int perm_bond_diff; + struct slave *found_slave; perm_curr_diff = !ether_addr_equal_64bits(slave->perm_hwaddr, slave->dev->dev_addr); @@ -1136,21 +1137,12 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla bond->dev->dev_addr); if (perm_curr_diff && perm_bond_diff) { - struct slave *tmp_slave; - int i, found = 0; - - bond_for_each_slave(bond, tmp_slave, i) { - if (ether_addr_equal_64bits(slave->perm_hwaddr, - tmp_slave->dev->dev_addr)) { - found = 1; - break; - } - } + found_slave = bond_slave_has_mac(bond, slave->perm_hwaddr); - if (found) { + if (found_slave) { /* locking: needs RTNL and nothing else */ - alb_swap_mac_addr(slave, tmp_slave); - alb_fasten_mac_swap(bond, slave, tmp_slave); + alb_swap_mac_addr(slave, found_slave); + alb_fasten_mac_swap(bond, slave, found_slave); } } } @@ -1668,7 +1660,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave __acquires(&bond->curr_slave_lock) { struct slave *swap_slave; - int i; if (bond->curr_active_slave == new_slave) { return; @@ -1690,17 +1681,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave /* set the new curr_active_slave to the bonds mac address * i.e. swap mac addresses of old curr_active_slave and new curr_active_slave */ - if (!swap_slave) { - struct slave *tmp_slave; - /* find slave that is holding the bond's mac address */ - bond_for_each_slave(bond, tmp_slave, i) { - if (ether_addr_equal_64bits(tmp_slave->dev->dev_addr, - bond->dev->dev_addr)) { - swap_slave = tmp_slave; - break; - } - } - } + if (!swap_slave) + swap_slave = bond_slave_has_mac(bond, bond->dev->dev_addr); /* * Arrange for swap_slave and new_slave to temporarily be @@ -1721,15 +1703,11 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave if (swap_slave) { /* swap mac address */ alb_swap_mac_addr(swap_slave, new_slave); - } else { - /* set the new_slave to the bond mac address */ - alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); - } - - if (swap_slave) { alb_fasten_mac_swap(bond, swap_slave, new_slave); read_lock(&bond->lock); } else { + /* set the new_slave to the bond mac address */ + alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr); read_lock(&bond->lock); alb_send_learning_packets(new_slave, bond->dev->dev_addr); } @@ -1746,9 +1724,8 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) { struct bonding *bond = netdev_priv(bond_dev); struct sockaddr *sa = addr; - struct slave *slave, *swap_slave; + struct slave *swap_slave; int res; - int i; if (!is_valid_ether_addr(sa->sa_data)) { return -EADDRNOTAVAIL; @@ -1769,15 +1746,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) return 0; } - swap_slave = NULL; - - bond_for_each_slave(bond, slave, i) { - if (ether_addr_equal_64bits(slave->dev->dev_addr, - bond_dev->dev_addr)) { - swap_slave = slave; - break; - } - } + swap_slave = bond_slave_has_mac(bond, bond_dev->dev_addr); if (swap_slave) { alb_swap_mac_addr(swap_slave, bond->curr_active_slave); -- GitLab From 9ef71e0c820987c899e454e2e7ef94bc2d4c8d04 Mon Sep 17 00:00:00 2001 From: Weiping Pan Date: Tue, 18 Jun 2013 21:00:31 +0800 Subject: [PATCH 1499/2900] tcp:typo unset should be unsent Signed-off-by: Weiping Pan Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3dd46eab3b05..e2c1333ee318 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -185,7 +185,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) u32 tcp_default_init_rwnd(u32 mss) { /* Initial receive window should be twice of TCP_INIT_CWND to - * enable proper sending of new unset data during fast recovery + * enable proper sending of new unsent data during fast recovery * (RFC 3517, Section 4, NextSeg() rule (2)). Further place a * limit when mss is larger than 1460. */ -- GitLab From a1606c7dc64d8449676d7e840dd2cd0c4e0a0c57 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 18 Jun 2013 03:24:51 +0100 Subject: [PATCH 1500/2900] net: Move MII out from under NET_CORE and hide it All drivers that select MII also need to select NET_CORE because MII depends on it. This is a bit ridiculous because NET_CORE is just a menu option that doesn't enable any code by itself. There is also no need for it to be a visible option, since its users all select it. Signed-off-by: Ben Hutchings Acked-by: Jeff Kirsher Signed-off-by: David S. Miller --- arch/cris/arch-v10/drivers/Kconfig | 1 - arch/cris/arch-v32/drivers/Kconfig | 1 - drivers/net/Kconfig | 10 +++------- drivers/net/ethernet/3com/Kconfig | 1 - drivers/net/ethernet/Kconfig | 4 ---- drivers/net/ethernet/adaptec/Kconfig | 1 - drivers/net/ethernet/adi/Kconfig | 1 - drivers/net/ethernet/allwinner/Kconfig | 1 - drivers/net/ethernet/amd/Kconfig | 2 -- drivers/net/ethernet/atheros/Kconfig | 4 ---- drivers/net/ethernet/broadcom/Kconfig | 2 -- drivers/net/ethernet/cirrus/Kconfig | 1 - drivers/net/ethernet/davicom/Kconfig | 1 - drivers/net/ethernet/dec/tulip/Kconfig | 1 - drivers/net/ethernet/dlink/Kconfig | 1 - drivers/net/ethernet/faraday/Kconfig | 1 - drivers/net/ethernet/freescale/fs_enet/Kconfig | 1 - drivers/net/ethernet/icplus/Kconfig | 1 - drivers/net/ethernet/intel/Kconfig | 1 - drivers/net/ethernet/micrel/Kconfig | 4 ---- drivers/net/ethernet/nuvoton/Kconfig | 1 - drivers/net/ethernet/oki-semi/pch_gbe/Kconfig | 1 - drivers/net/ethernet/packetengines/Kconfig | 1 - drivers/net/ethernet/rdc/Kconfig | 1 - drivers/net/ethernet/realtek/Kconfig | 3 --- drivers/net/ethernet/renesas/Kconfig | 1 - drivers/net/ethernet/sgi/Kconfig | 1 - drivers/net/ethernet/sis/Kconfig | 2 -- drivers/net/ethernet/smsc/Kconfig | 5 ----- drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 - drivers/net/ethernet/via/Kconfig | 2 -- drivers/net/usb/Kconfig | 4 ---- drivers/staging/silicom/Kconfig | 1 - 33 files changed, 3 insertions(+), 61 deletions(-) diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 5f2cdb3e428c..8eab0c61d57b 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -4,7 +4,6 @@ config ETRAX_ETHERNET bool "Ethernet support" depends on ETRAX_ARCH_V10 select ETHERNET - select NET_CORE select MII help This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index c55971a40c34..91c4e54ca904 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -4,7 +4,6 @@ config ETRAX_ETHERNET bool "Ethernet support" depends on ETRAX_ARCH_V32 select ETHERNET - select NET_CORE select MII help This option enables the ETRAX FS built-in 10/100Mbit Ethernet diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 3835321b8cf3..00aba08f01a9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -25,6 +25,9 @@ menuconfig NETDEVICES # that for each of the symbols. if NETDEVICES +config MII + tristate + config NET_CORE default y bool "Network core driver support" @@ -100,13 +103,6 @@ config NET_FC adaptor below. You also should have said Y to "SCSI support" and "SCSI generic support". -config MII - tristate "Generic Media Independent Interface device support" - help - Most ethernet controllers have MII transceiver either as an external - or internal device. It is safe to say Y or M here even if your - ethernet card lacks MII. - config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig index 1c71c763f680..f00c76377b44 100644 --- a/drivers/net/ethernet/3com/Kconfig +++ b/drivers/net/ethernet/3com/Kconfig @@ -67,7 +67,6 @@ config PCMCIA_3C589 config VORTEX tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support" depends on (PCI || EISA) && HAS_IOPORT - select NET_CORE select MII ---help--- This option enables driver support for a large number of 10Mbps and diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 18fd6fbeb109..a989669b353a 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -64,7 +64,6 @@ config JME tristate "JMicron(R) PCI-Express Gigabit Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver supports the PCI-Express gigabit ethernet adapters @@ -96,7 +95,6 @@ config FEALNX tristate "Myson MTD-8xx PCI Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- Say Y here to support the Myson MTD-800 family of PCI-based Ethernet @@ -107,7 +105,6 @@ source "drivers/net/ethernet/8390/Kconfig" config NET_NETX tristate "NetX Ethernet support" - select NET_CORE select MII depends on ARCH_NETX ---help--- @@ -125,7 +122,6 @@ source "drivers/net/ethernet/oki-semi/Kconfig" config ETHOC tristate "OpenCores 10/100 Mbps Ethernet MAC support" depends on HAS_IOMEM && HAS_DMA - select NET_CORE select MII select PHYLIB select CRC32 diff --git a/drivers/net/ethernet/adaptec/Kconfig b/drivers/net/ethernet/adaptec/Kconfig index 0bff571b1bb3..5c804bbe3dab 100644 --- a/drivers/net/ethernet/adaptec/Kconfig +++ b/drivers/net/ethernet/adaptec/Kconfig @@ -22,7 +22,6 @@ config ADAPTEC_STARFIRE tristate "Adaptec Starfire/DuraLAN support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig index a9481606bbcd..f952fff6a9a9 100644 --- a/drivers/net/ethernet/adi/Kconfig +++ b/drivers/net/ethernet/adi/Kconfig @@ -23,7 +23,6 @@ config BFIN_MAC tristate "Blackfin on-chip MAC support" depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537) select CRC32 - select NET_CORE select MII select PHYLIB select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE diff --git a/drivers/net/ethernet/allwinner/Kconfig b/drivers/net/ethernet/allwinner/Kconfig index 66d35324f31e..53ad213e865b 100644 --- a/drivers/net/ethernet/allwinner/Kconfig +++ b/drivers/net/ethernet/allwinner/Kconfig @@ -24,7 +24,6 @@ config SUN4I_EMAC depends on ARCH_SUNXI depends on OF select CRC32 - select NET_CORE select MII select PHYLIB ---help--- diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index 13d74aa4033d..562df46e0a82 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -34,7 +34,6 @@ config AMD8111_ETH tristate "AMD 8111 (new PCI LANCE) support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- If you have an AMD 8111-based PCI LANCE ethernet card, @@ -60,7 +59,6 @@ config PCNET32 tristate "AMD PCnet32 PCI support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- If you have a PCnet32 or PCnetPCI based network (Ethernet) card, diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig index ad6aa1e98348..39e8d6cc8843 100644 --- a/drivers/net/ethernet/atheros/Kconfig +++ b/drivers/net/ethernet/atheros/Kconfig @@ -22,7 +22,6 @@ config ATL2 tristate "Atheros L2 Fast Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver supports the Atheros L2 fast ethernet adapter. @@ -34,7 +33,6 @@ config ATL1 tristate "Atheros/Attansic L1 Gigabit Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver supports the Atheros/Attansic L1 gigabit ethernet @@ -47,7 +45,6 @@ config ATL1E tristate "Atheros L1E Gigabit Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver supports the Atheros L1E gigabit ethernet adapter. @@ -59,7 +56,6 @@ config ATL1C tristate "Atheros L1C Gigabit Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver supports the Atheros L1C gigabit ethernet adapter. diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 3e69b3f88099..1d680baf43d6 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -22,7 +22,6 @@ config B44 tristate "Broadcom 440x/47xx ethernet support" depends on SSB_POSSIBLE && HAS_DMA select SSB - select NET_CORE select MII ---help--- If you have a network (Ethernet) controller of this type, say Y @@ -54,7 +53,6 @@ config B44_PCI config BCM63XX_ENET tristate "Broadcom 63xx internal mac support" depends on BCM63XX - select NET_CORE select MII select PHYLIB help diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig index 8388e36cf08f..7403dff8f14a 100644 --- a/drivers/net/ethernet/cirrus/Kconfig +++ b/drivers/net/ethernet/cirrus/Kconfig @@ -44,7 +44,6 @@ config CS89x0_PLATFORM config EP93XX_ETH tristate "EP93xx Ethernet support" depends on ARM && ARCH_EP93XX - select NET_CORE select MII help This is a driver for the ethernet hardware included in EP93xx CPUs. diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig index 9745fe5e8039..316c5e5a92ad 100644 --- a/drivers/net/ethernet/davicom/Kconfig +++ b/drivers/net/ethernet/davicom/Kconfig @@ -6,7 +6,6 @@ config DM9000 tristate "DM9000 support" depends on ARM || BLACKFIN || MIPS || COLDFIRE select CRC32 - select NET_CORE select MII ---help--- Support for DM9000 chipset. diff --git a/drivers/net/ethernet/dec/tulip/Kconfig b/drivers/net/ethernet/dec/tulip/Kconfig index 1df33c799c00..eb9ba6e97d04 100644 --- a/drivers/net/ethernet/dec/tulip/Kconfig +++ b/drivers/net/ethernet/dec/tulip/Kconfig @@ -126,7 +126,6 @@ config WINBOND_840 tristate "Winbond W89c840 Ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver is for the Winbond W89c840 chip. It also works with diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig index ee26ce78e270..c543ac11ce08 100644 --- a/drivers/net/ethernet/dlink/Kconfig +++ b/drivers/net/ethernet/dlink/Kconfig @@ -36,7 +36,6 @@ config SUNDANCE tristate "Sundance Alta support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver is for the Sundance "Alta" chip. diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig index b8974b9e3b47..5918c6891694 100644 --- a/drivers/net/ethernet/faraday/Kconfig +++ b/drivers/net/ethernet/faraday/Kconfig @@ -21,7 +21,6 @@ if NET_VENDOR_FARADAY config FTMAC100 tristate "Faraday FTMAC100 10/100 Ethernet support" depends on ARM - select NET_CORE select MII ---help--- This driver supports the FTMAC100 10/100 Ethernet controller diff --git a/drivers/net/ethernet/freescale/fs_enet/Kconfig b/drivers/net/ethernet/freescale/fs_enet/Kconfig index 268414d9f2cb..be92229f2c2a 100644 --- a/drivers/net/ethernet/freescale/fs_enet/Kconfig +++ b/drivers/net/ethernet/freescale/fs_enet/Kconfig @@ -1,7 +1,6 @@ config FS_ENET tristate "Freescale Ethernet Driver" depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x) - select NET_CORE select MII select PHYLIB diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig index 5119ef18953b..14a66e9d2e26 100644 --- a/drivers/net/ethernet/icplus/Kconfig +++ b/drivers/net/ethernet/icplus/Kconfig @@ -5,7 +5,6 @@ config IP1000 tristate "IP1000 Gigabit Ethernet support" depends on PCI - select NET_CORE select MII ---help--- This driver supports IP1000 gigabit Ethernet cards. diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 05f7264c51f7..f0e7ed20a750 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -20,7 +20,6 @@ if NET_VENDOR_INTEL config E100 tristate "Intel(R) PRO/100+ support" depends on PCI - select NET_CORE select MII ---help--- This driver supports Intel(R) PRO/100 family of adapters. diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig index fe42fc00d8d3..d16b11ed2e52 100644 --- a/drivers/net/ethernet/micrel/Kconfig +++ b/drivers/net/ethernet/micrel/Kconfig @@ -22,7 +22,6 @@ if NET_VENDOR_MICREL config ARM_KS8695_ETHER tristate "KS8695 Ethernet support" depends on ARM && ARCH_KS8695 - select NET_CORE select MII ---help--- If you wish to compile a kernel for the KS8695 and want to @@ -39,7 +38,6 @@ config KS8842 config KS8851 tristate "Micrel KS8851 SPI" depends on SPI - select NET_CORE select MII select CRC32 select EEPROM_93CX6 @@ -49,7 +47,6 @@ config KS8851 config KS8851_MLL tristate "Micrel KS8851 MLL" depends on HAS_IOMEM - select NET_CORE select MII ---help--- This platform driver is for Micrel KS8851 Address/data bus @@ -58,7 +55,6 @@ config KS8851_MLL config KSZ884X_PCI tristate "Micrel KSZ8841/2 PCI" depends on PCI - select NET_CORE select MII select CRC32 ---help--- diff --git a/drivers/net/ethernet/nuvoton/Kconfig b/drivers/net/ethernet/nuvoton/Kconfig index 334c17183095..01182b559473 100644 --- a/drivers/net/ethernet/nuvoton/Kconfig +++ b/drivers/net/ethernet/nuvoton/Kconfig @@ -22,7 +22,6 @@ config W90P910_ETH tristate "Nuvoton w90p910 Ethernet support" depends on ARM && ARCH_W90X900 select PHYLIB - select NET_CORE select MII ---help--- Say Y here if you want to use built-in Ethernet ports diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index 34d05bf72b2e..cb22341a14a8 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -5,7 +5,6 @@ config PCH_GBE tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" depends on PCI - select NET_CORE select MII select PTP_1588_CLOCK_PCH ---help--- diff --git a/drivers/net/ethernet/packetengines/Kconfig b/drivers/net/ethernet/packetengines/Kconfig index cbbeca3f8c5c..8d5180043c70 100644 --- a/drivers/net/ethernet/packetengines/Kconfig +++ b/drivers/net/ethernet/packetengines/Kconfig @@ -21,7 +21,6 @@ if NET_PACKET_ENGINE config HAMACHI tristate "Packet Engines Hamachi GNIC-II support" depends on PCI - select NET_CORE select MII ---help--- If you have a Gigabit Ethernet card of this type, say Y and read diff --git a/drivers/net/ethernet/rdc/Kconfig b/drivers/net/ethernet/rdc/Kconfig index c8ba4b3494c1..2055f7eb2ba9 100644 --- a/drivers/net/ethernet/rdc/Kconfig +++ b/drivers/net/ethernet/rdc/Kconfig @@ -22,7 +22,6 @@ config R6040 tristate "RDC R6040 Fast Ethernet Adapter support" depends on PCI select CRC32 - select NET_CORE select MII select PHYLIB ---help--- diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig index 783fa8b5cde7..ae5d027096ed 100644 --- a/drivers/net/ethernet/realtek/Kconfig +++ b/drivers/net/ethernet/realtek/Kconfig @@ -37,7 +37,6 @@ config 8139CP tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on @@ -52,7 +51,6 @@ config 8139TOO tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on @@ -107,7 +105,6 @@ config R8169 depends on PCI select FW_LOADER select CRC32 - select NET_CORE select MII ---help--- Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 267eac054fa4..544514e66187 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -5,7 +5,6 @@ config SH_ETH tristate "Renesas SuperH Ethernet support" select CRC32 - select NET_CORE select MII select MDIO_BITBANG select PHYLIB diff --git a/drivers/net/ethernet/sgi/Kconfig b/drivers/net/ethernet/sgi/Kconfig index c1c4bb868a3b..e832f46660c9 100644 --- a/drivers/net/ethernet/sgi/Kconfig +++ b/drivers/net/ethernet/sgi/Kconfig @@ -22,7 +22,6 @@ config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" depends on PCI && SGI_IP27 select CRC32 - select NET_CORE select MII ---help--- If you have a network (Ethernet) card of this type, say Y and read diff --git a/drivers/net/ethernet/sis/Kconfig b/drivers/net/ethernet/sis/Kconfig index f1135cc1bd48..68d052b09af1 100644 --- a/drivers/net/ethernet/sis/Kconfig +++ b/drivers/net/ethernet/sis/Kconfig @@ -22,7 +22,6 @@ config SIS900 tristate "SiS 900/7016 PCI Fast Ethernet Adapter support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This is a driver for the Fast Ethernet PCI network cards based on @@ -39,7 +38,6 @@ config SIS190 tristate "SiS190/SiS191 gigabit ethernet support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index ff9e99474039..068fc44d37e1 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -37,7 +37,6 @@ config SMC9194 config SMC91X tristate "SMC 91C9x/91C1xxx support" select CRC32 - select NET_CORE select MII depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \ MN10300 || COLDFIRE || ARM64) @@ -57,7 +56,6 @@ config PCMCIA_SMC91C92 tristate "SMC 91Cxx PCMCIA support" depends on PCMCIA select CRC32 - select NET_CORE select MII ---help--- Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA @@ -70,7 +68,6 @@ config EPIC100 tristate "SMC EtherPower II" depends on PCI select CRC32 - select NET_CORE select MII ---help--- This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC, @@ -81,7 +78,6 @@ config EPIC100 config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 - select NET_CORE select MII depends on (ARM || SUPERH || MN10300) ---help--- @@ -99,7 +95,6 @@ config SMSC911X tristate "SMSC LAN911x/LAN921x families embedded ethernet support" depends on HAS_IOMEM select CRC32 - select NET_CORE select MII select PHYLIB ---help--- diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 43c1f3223322..6e52c0f74cd9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -1,7 +1,6 @@ config STMMAC_ETH tristate "STMicroelectronics 10/100/1000 Ethernet driver" depends on HAS_IOMEM && HAS_DMA - select NET_CORE select MII select PHYLIB select CRC32 diff --git a/drivers/net/ethernet/via/Kconfig b/drivers/net/ethernet/via/Kconfig index 6a87097d88c0..8a049a2b4474 100644 --- a/drivers/net/ethernet/via/Kconfig +++ b/drivers/net/ethernet/via/Kconfig @@ -21,7 +21,6 @@ config VIA_RHINE tristate "VIA Rhine support" depends on PCI select CRC32 - select NET_CORE select MII ---help--- If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A), @@ -47,7 +46,6 @@ config VIA_VELOCITY depends on (PCI || USE_OF) select CRC32 select CRC_CCITT - select NET_CORE select MII ---help--- If you have a VIA "Velocity" based network card say Y here. diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 287cc624b90b..d84bfd4109a4 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -67,7 +67,6 @@ config USB_KAWETH config USB_PEGASUS tristate "USB Pegasus/Pegasus-II based ethernet device support" - select NET_CORE select MII ---help--- Say Y here if you know you have Pegasus or Pegasus-II based adapter. @@ -83,7 +82,6 @@ config USB_PEGASUS config USB_RTL8150 tristate "USB RTL8150 based ethernet device support" - select NET_CORE select MII help Say Y here if you have RTL8150 based usb-ethernet adapter. @@ -95,7 +93,6 @@ config USB_RTL8150 config USB_RTL8152 tristate "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" - select NET_CORE select MII help This option adds support for Realtek RTL8152 based USB 2.0 @@ -106,7 +103,6 @@ config USB_RTL8152 config USB_USBNET tristate "Multi-purpose USB Networking Framework" - select NET_CORE select MII ---help--- This driver supports several kinds of network links over USB, diff --git a/drivers/staging/silicom/Kconfig b/drivers/staging/silicom/Kconfig index eda2e7d73645..fc082db628ec 100644 --- a/drivers/staging/silicom/Kconfig +++ b/drivers/staging/silicom/Kconfig @@ -32,7 +32,6 @@ config BPCTL depends on PCI && NET depends on m select SBYPASS - select NET_CORE select MII ---help--- If you have a network (Ethernet) controller of this type, say Y -- GitLab From d6cf7a86ce50ab9aded00a01ba55b6cd6b87209d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 18 Jun 2013 03:27:29 +0100 Subject: [PATCH 1501/2900] at91_ether: Do not select NET_CORE This has no dependency on any of the drivers under NET_CORE. Signed-off-by: Ben Hutchings Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 768285ec10f4..8030cc0396fd 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -23,7 +23,6 @@ if NET_CADENCE config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" depends on GENERIC_HARDIRQS && HAS_DMA - select NET_CORE select MACB ---help--- If you wish to compile a kernel for the AT91RM9200 and enable -- GitLab From 2206209e758e3d930a550bacfc0db6303e2df6bd Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 18 Jun 2013 03:37:05 +0100 Subject: [PATCH 1502/2900] net: Add missing dependencies on NETDEVICES ETRAX_ETHERNET selects ETHERNET and MII, which depend on NETDEVICES. I don't think anything should select NETDEVICES, so make it a dependency. It also doesn't need to select or depend on ETHERNET, which has nothing to do with the Ethernet library functions. BPCTL selects MII, which depends on NETDEVICES. But everything in the drivers/staging/silicom directory is related to net devices, so make NET_VENDOR_SILICOM depend on NETDEVICES and remove the now-redundant dependencies on NET. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- arch/cris/arch-v10/drivers/Kconfig | 3 +-- arch/cris/arch-v32/drivers/Kconfig | 3 +-- drivers/staging/silicom/Kconfig | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 8eab0c61d57b..daf5f19b61a1 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -2,8 +2,7 @@ if ETRAX_ARCH_V10 config ETRAX_ETHERNET bool "Ethernet support" - depends on ETRAX_ARCH_V10 - select ETHERNET + depends on ETRAX_ARCH_V10 && NETDEVICES select MII help This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index 91c4e54ca904..4f223506a2aa 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -2,8 +2,7 @@ if ETRAX_ARCH_V32 config ETRAX_ETHERNET bool "Ethernet support" - depends on ETRAX_ARCH_V32 - select ETHERNET + depends on ETRAX_ARCH_V32 && NETDEVICES select MII help This option enables the ETRAX FS built-in 10/100Mbit Ethernet diff --git a/drivers/staging/silicom/Kconfig b/drivers/staging/silicom/Kconfig index fc082db628ec..6651bd819bc8 100644 --- a/drivers/staging/silicom/Kconfig +++ b/drivers/staging/silicom/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_SILICOM bool "Silicom devices" default y - depends on PCI + depends on PCI && NETDEVICES ---help--- If you have a network card (Ethernet) belonging to this class, say Y. @@ -19,7 +19,7 @@ if NET_VENDOR_SILICOM config SBYPASS tristate "Silicom BypassCTL library support" - depends on PCI && NET + depends on PCI depends on m ---help--- If you have a network (Ethernet) controller of this type, say Y @@ -29,7 +29,7 @@ config SBYPASS config BPCTL tristate "Silicom BypassCTL net support" - depends on PCI && NET + depends on PCI depends on m select SBYPASS select MII -- GitLab From b8a39dd292af453f42ebcdbad229f7d9d1282ec2 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 18 Jun 2013 16:05:39 +0800 Subject: [PATCH 1503/2900] Bnx2x: remove redundant D0 power state set Pci_enable_device() will set device power state to D0, so it's no need to do it again in bnx2x_init_dev(). Also remove redundant PM Cap find code, because pci core has been saved the pci device pm cap value. Signed-off-by: Yijing Wang Cc: Eilon Greenstein Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Acked-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f0d21faf71ec..c962d66a1a79 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12091,7 +12091,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, } if (IS_PF(bp)) { - bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + bp->pm_cap = pdev->pm_cap; if (bp->pm_cap == 0) { dev_err(&bp->pdev->dev, "Cannot find power management capability, aborting\n"); @@ -12140,8 +12140,6 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, } BNX2X_DEV_INFO("me reg PF num: %d\n", bp->pf_num); - bnx2x_set_power_state(bp, PCI_D0); - /* clean indirect addresses */ pci_write_config_dword(bp->pdev, PCICFG_GRC_ADDRESS, PCICFG_VENDOR_ID_OFFSET); -- GitLab From f9c7da5eaf10fa1d7a91b83aefc6fb8e3a4ad39c Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 18 Jun 2013 16:06:37 +0800 Subject: [PATCH 1504/2900] amd8111e: use pdev->pm_cap instead of pci_find_capability(.., PCI_CAP_ID_PM) Pci core has been saved pm cap register offset by pdev->pm_cap in pci_pm_init() in init path. So we can use pdev->pm_cap instead of using pci_find_capability(pdev, PCI_CAP_ID_PM) for better performance and simplified code. Signed-off-by: Yijing Wang Cc: "David S. Miller" Cc: Patrick McHardy Cc: Bill Pemberton Cc: Greg Kroah-Hartman Cc: netdev@vger.kernel.org (open list:NETWORKING DRIVERS) Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/amd8111e.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index bc71aec1159d..1b1429d5d5c2 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1813,7 +1813,7 @@ static const struct net_device_ops amd8111e_netdev_ops = { static int amd8111e_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err,i,pm_cap; + int err, i; unsigned long reg_addr,reg_len; struct amd8111e_priv* lp; struct net_device* dev; @@ -1842,7 +1842,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev, pci_set_master(pdev); /* Find power-management capability. */ - if((pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM))==0){ + if (!pdev->pm_cap) { printk(KERN_ERR "amd8111e: No Power Management capability, " "exiting.\n"); err = -ENODEV; @@ -1875,7 +1875,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev, lp = netdev_priv(dev); lp->pci_dev = pdev; lp->amd8111e_net_dev = dev; - lp->pm_cap = pm_cap; + lp->pm_cap = pdev->pm_cap; spin_lock_init(&lp->lock); -- GitLab From 85768271315bd368c86a0783bf0c85019afbabec Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 18 Jun 2013 16:12:37 +0800 Subject: [PATCH 1505/2900] bnx2: use pdev->pm_cap instead of pci_find_capability(.., PCI_CAP_ID_PM) Pci core has been saved pm cap register offset by pdev->pm_cap in pci_pm_init() in init path. So we can use pdev->pm_cap instead of using pci_find_capability(pdev, PCI_CAP_ID_PM) for better performance and simplified code. Signed-off-by: Yijing Wang Cc: Michael Chan Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 1a1b23eb13dc..6a2de1d79ff6 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -8104,7 +8104,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) pci_set_master(pdev); - bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + bp->pm_cap = pdev->pm_cap; if (bp->pm_cap == 0) { dev_err(&pdev->dev, "Cannot find power management capability, aborting\n"); -- GitLab From 2c0740e4e122239bcf6127fd2063733c5fb20c93 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 17 Jun 2013 22:26:52 -0400 Subject: [PATCH 1506/2900] sctp: Convert __list_for_each use to list_for_each Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- net/sctp/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 57b568c38ef6..1de49c802d83 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -178,7 +178,7 @@ static void sctp_get_local_addr_list(struct net *net) rcu_read_lock(); for_each_netdev_rcu(net, dev) { - __list_for_each(pos, &sctp_address_families) { + list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); af->copy_addrlist(&net->sctp.local_addr_list, dev); } -- GitLab From bcefe17cffd06efdda3e7ad679ea743236e6271a Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sat, 15 Jun 2013 09:39:18 +0800 Subject: [PATCH 1507/2900] tcp: introduce a per-route knob for quick ack In previous discussions, I tried to find some reasonable heuristics for delayed ACK, however this seems not possible, according to Eric: "ACKS might also be delayed because of bidirectional traffic, and is more controlled by the application response time. TCP stack can not easily estimate it." "ACK can be incredibly useful to recover from losses in a short time. The vast majority of TCP sessions are small lived, and we send one ACK per received segment anyway at beginning or retransmits to let the sender smoothly increase its cwnd, so an auto-tuning facility wont help them that much." and according to David: "ACKs are the only information we have to detect loss. And, for the same reasons that TCP VEGAS is fundamentally broken, we cannot measure the pipe or some other receiver-side-visible piece of information to determine when it's "safe" to stretch ACK. And even if it's "safe", we should not do it so that losses are accurately detected and we don't spuriously retransmit. The only way to know when the bandwidth increases is to "test" it, by sending more and more packets until drops happen. That's why all successful congestion control algorithms must operate on explicited tested pieces of information. Similarly, it's not really possible to universally know if it's safe to stretch ACK or not." It still makes sense to enable or disable quick ack mode like what TCP_QUICK_ACK does. Similar to TCP_QUICK_ACK option, but for people who can't modify the source code and still wants to control TCP delayed ACK behavior. As David suggested, this should belong to per-path scope, since different pathes may want different behaviors. Cc: Eric Dumazet Cc: Rick Jones Cc: Stephen Hemminger Cc: "David S. Miller" Cc: Thomas Graf CC: David Laight Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/uapi/linux/rtnetlink.h | 2 ++ net/ipv4/tcp_input.c | 5 ++++- net/ipv4/tcp_output.c | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 7a2144e1afae..eb0f1a554d7b 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -386,6 +386,8 @@ enum { #define RTAX_RTO_MIN RTAX_RTO_MIN RTAX_INITRWND, #define RTAX_INITRWND RTAX_INITRWND + RTAX_QUICKACK, +#define RTAX_QUICKACK RTAX_QUICKACK __RTAX_MAX }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 46271cdcf088..28af45abe062 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3717,6 +3717,7 @@ void tcp_reset(struct sock *sk) static void tcp_fin(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + const struct dst_entry *dst; inet_csk_schedule_ack(sk); @@ -3728,7 +3729,9 @@ static void tcp_fin(struct sock *sk) case TCP_ESTABLISHED: /* Move to CLOSE_WAIT */ tcp_set_state(sk, TCP_CLOSE_WAIT); - inet_csk(sk)->icsk_ack.pingpong = 1; + dst = __sk_dst_get(sk); + if (!dst || !dst_metric(dst, RTAX_QUICKACK)) + inet_csk(sk)->icsk_ack.pingpong = 1; break; case TCP_CLOSE_WAIT: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e2c1333ee318..3d609490f118 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -160,6 +160,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp, { struct inet_connection_sock *icsk = inet_csk(sk); const u32 now = tcp_time_stamp; + const struct dst_entry *dst = __sk_dst_get(sk); if (sysctl_tcp_slow_start_after_idle && (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)) @@ -170,8 +171,9 @@ static void tcp_event_data_sent(struct tcp_sock *tp, /* If it is a reply for ato after last received * packet, enter pingpong mode. */ - if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato) - icsk->icsk_ack.pingpong = 1; + if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato && + (!dst || !dst_metric(dst, RTAX_QUICKACK))) + icsk->icsk_ack.pingpong = 1; } /* Account for an ACK we sent. */ -- GitLab From c9364636dcb01a6fc37ca2c6a51c5aa0c663013c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 15 Jun 2013 03:30:10 -0700 Subject: [PATCH 1508/2900] htb: refactor struct htb_sched fields for performance htb_sched structures are big, and source of false sharing on SMP. Every time a packet is queued or dequeue, many cache lines must be touched because structures are not lay out properly. By carefully splitting htb_sched in two parts, and define sub structures to increase data locality, we can improve performance dramatically on SMP. New htb_prio structure can also be used in htb_class to increase data locality. I got 26 % performance increase on a 24 threads machine, with 200 concurrent netperf in TCP_RR mode, using a HTB hierarchy of 4 classes. Signed-off-by: Eric Dumazet Cc: Tom Herbert Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 181 +++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 86 deletions(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 7954e73d118a..c2124ea29f45 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -76,6 +76,20 @@ enum htb_cmode { HTB_CAN_SEND /* class can send */ }; +struct htb_prio { + union { + struct rb_root row; + struct rb_root feed; + }; + struct rb_node *ptr; + /* When class changes from state 1->2 and disconnects from + * parent's feed then we lost ptr value and start from the + * first child again. Here we store classid of the + * last valid ptr (used when ptr is NULL). + */ + u32 last_ptr_id; +}; + /* interior & leaf nodes; props specific to leaves are marked L: * To reduce false sharing, place mostly read fields at beginning, * and mostly written ones at the end. @@ -112,19 +126,12 @@ struct htb_class { union { struct htb_class_leaf { - struct Qdisc *q; - int deficit[TC_HTB_MAXDEPTH]; struct list_head drop_list; + int deficit[TC_HTB_MAXDEPTH]; + struct Qdisc *q; } leaf; struct htb_class_inner { - struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ - struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ - /* When class changes from state 1->2 and disconnects from - * parent's feed then we lost ptr value and start from the - * first child again. Here we store classid of the - * last valid ptr (used when ptr is NULL). - */ - u32 last_ptr_id[TC_HTB_NUMPRIO]; + struct htb_prio clprio[TC_HTB_NUMPRIO]; } inner; } un; s64 pq_key; @@ -135,40 +142,39 @@ struct htb_class { struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ }; +struct htb_level { + struct rb_root wait_pq; + struct htb_prio hprio[TC_HTB_NUMPRIO]; +}; + struct htb_sched { struct Qdisc_class_hash clhash; - struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ - - /* self list - roots of self generating tree */ - struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - int row_mask[TC_HTB_MAXDEPTH]; - struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; + int defcls; /* class where unclassified flows go to */ + int rate2quantum; /* quant = rate / rate2quantum */ - /* self wait list - roots of wait PQs per row */ - struct rb_root wait_pq[TC_HTB_MAXDEPTH]; + /* filters for qdisc itself */ + struct tcf_proto *filter_list; - /* time of nearest event per level (row) */ - s64 near_ev_cache[TC_HTB_MAXDEPTH]; +#define HTB_WARN_TOOMANYEVENTS 0x1 + unsigned int warned; /* only one warning */ + int direct_qlen; + struct work_struct work; - int defcls; /* class where unclassified flows go to */ + /* non shaped skbs; let them go directly thru */ + struct sk_buff_head direct_queue; + long direct_pkts; - /* filters for qdisc itself */ - struct tcf_proto *filter_list; + struct qdisc_watchdog watchdog; - int rate2quantum; /* quant = rate / rate2quantum */ - s64 now; /* cached dequeue time */ - struct qdisc_watchdog watchdog; + s64 now; /* cached dequeue time */ + struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ - /* non shaped skbs; let them go directly thru */ - struct sk_buff_head direct_queue; - int direct_qlen; /* max qlen of above */ + /* time of nearest event per level (row) */ + s64 near_ev_cache[TC_HTB_MAXDEPTH]; - long direct_pkts; + int row_mask[TC_HTB_MAXDEPTH]; -#define HTB_WARN_TOOMANYEVENTS 0x1 - unsigned int warned; /* only one warning */ - struct work_struct work; + struct htb_level hlevel[TC_HTB_MAXDEPTH]; }; /* find class in global hash table using given handle */ @@ -284,7 +290,7 @@ static void htb_add_to_id_tree(struct rb_root *root, static void htb_add_to_wait_tree(struct htb_sched *q, struct htb_class *cl, s64 delay) { - struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL; + struct rb_node **p = &q->hlevel[cl->level].wait_pq.rb_node, *parent = NULL; cl->pq_key = q->now + delay; if (cl->pq_key == q->now) @@ -304,7 +310,7 @@ static void htb_add_to_wait_tree(struct htb_sched *q, p = &parent->rb_left; } rb_link_node(&cl->pq_node, parent, p); - rb_insert_color(&cl->pq_node, &q->wait_pq[cl->level]); + rb_insert_color(&cl->pq_node, &q->hlevel[cl->level].wait_pq); } /** @@ -331,7 +337,7 @@ static inline void htb_add_class_to_row(struct htb_sched *q, while (mask) { int prio = ffz(~mask); mask &= ~(1 << prio); - htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio); + htb_add_to_id_tree(&q->hlevel[cl->level].hprio[prio].row, cl, prio); } } @@ -357,16 +363,18 @@ static inline void htb_remove_class_from_row(struct htb_sched *q, struct htb_class *cl, int mask) { int m = 0; + struct htb_level *hlevel = &q->hlevel[cl->level]; while (mask) { int prio = ffz(~mask); + struct htb_prio *hprio = &hlevel->hprio[prio]; mask &= ~(1 << prio); - if (q->ptr[cl->level][prio] == cl->node + prio) - htb_next_rb_node(q->ptr[cl->level] + prio); + if (hprio->ptr == cl->node + prio) + htb_next_rb_node(&hprio->ptr); - htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio); - if (!q->row[cl->level][prio].rb_node) + htb_safe_rb_erase(cl->node + prio, &hprio->row); + if (!hprio->row.rb_node) m |= 1 << prio; } q->row_mask[cl->level] &= ~m; @@ -390,13 +398,13 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) int prio = ffz(~m); m &= ~(1 << prio); - if (p->un.inner.feed[prio].rb_node) + if (p->un.inner.clprio[prio].feed.rb_node) /* parent already has its feed in use so that * reset bit in mask as parent is already ok */ mask &= ~(1 << prio); - htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio); + htb_add_to_id_tree(&p->un.inner.clprio[prio].feed, cl, prio); } p->prio_activity |= mask; cl = p; @@ -426,18 +434,19 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) int prio = ffz(~m); m &= ~(1 << prio); - if (p->un.inner.ptr[prio] == cl->node + prio) { + if (p->un.inner.clprio[prio].ptr == cl->node + prio) { /* we are removing child which is pointed to from * parent feed - forget the pointer but remember * classid */ - p->un.inner.last_ptr_id[prio] = cl->common.classid; - p->un.inner.ptr[prio] = NULL; + p->un.inner.clprio[prio].last_ptr_id = cl->common.classid; + p->un.inner.clprio[prio].ptr = NULL; } - htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio); + htb_safe_rb_erase(cl->node + prio, + &p->un.inner.clprio[prio].feed); - if (!p->un.inner.feed[prio].rb_node) + if (!p->un.inner.clprio[prio].feed.rb_node) mask |= 1 << prio; } @@ -652,7 +661,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, htb_change_class_mode(q, cl, &diff); if (old_mode != cl->cmode) { if (old_mode != HTB_CAN_SEND) - htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); + htb_safe_rb_erase(&cl->pq_node, &q->hlevel[cl->level].wait_pq); if (cl->cmode != HTB_CAN_SEND) htb_add_to_wait_tree(q, cl, diff); } @@ -672,7 +681,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, * next pending event (0 for no event in pq, q->now for too many events). * Note: Applied are events whose have cl->pq_key <= q->now. */ -static s64 htb_do_events(struct htb_sched *q, int level, +static s64 htb_do_events(struct htb_sched *q, const int level, unsigned long start) { /* don't run for longer than 2 jiffies; 2 is used instead of @@ -680,10 +689,12 @@ static s64 htb_do_events(struct htb_sched *q, int level, * too soon */ unsigned long stop_at = start + 2; + struct rb_root *wait_pq = &q->hlevel[level].wait_pq; + while (time_before(jiffies, stop_at)) { struct htb_class *cl; s64 diff; - struct rb_node *p = rb_first(&q->wait_pq[level]); + struct rb_node *p = rb_first(wait_pq); if (!p) return 0; @@ -692,7 +703,7 @@ static s64 htb_do_events(struct htb_sched *q, int level, if (cl->pq_key > q->now) return cl->pq_key; - htb_safe_rb_erase(p, q->wait_pq + level); + htb_safe_rb_erase(p, wait_pq); diff = min_t(s64, q->now - cl->t_c, cl->mbuffer); htb_change_class_mode(q, cl, &diff); if (cl->cmode != HTB_CAN_SEND) @@ -736,8 +747,7 @@ static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, * * Find leaf where current feed pointers points to. */ -static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, - struct rb_node **pptr, u32 * pid) +static struct htb_class *htb_lookup_leaf(struct htb_prio *hprio, const int prio) { int i; struct { @@ -746,10 +756,10 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, u32 *pid; } stk[TC_HTB_MAXDEPTH], *sp = stk; - BUG_ON(!tree->rb_node); - sp->root = tree->rb_node; - sp->pptr = pptr; - sp->pid = pid; + BUG_ON(!hprio->row.rb_node); + sp->root = hprio->row.rb_node; + sp->pptr = &hprio->ptr; + sp->pid = &hprio->last_ptr_id; for (i = 0; i < 65535; i++) { if (!*sp->pptr && *sp->pid) { @@ -776,12 +786,15 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, } } else { struct htb_class *cl; + struct htb_prio *clp; + cl = rb_entry(*sp->pptr, struct htb_class, node[prio]); if (!cl->level) return cl; - (++sp)->root = cl->un.inner.feed[prio].rb_node; - sp->pptr = cl->un.inner.ptr + prio; - sp->pid = cl->un.inner.last_ptr_id + prio; + clp = &cl->un.inner.clprio[prio]; + (++sp)->root = clp->feed.rb_node; + sp->pptr = &clp->ptr; + sp->pid = &clp->last_ptr_id; } } WARN_ON(1); @@ -791,15 +804,16 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, /* dequeues packet at given priority and level; call only if * you are sure that there is active class at prio/level */ -static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, - int level) +static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, const int prio, + const int level) { struct sk_buff *skb = NULL; struct htb_class *cl, *start; + struct htb_level *hlevel = &q->hlevel[level]; + struct htb_prio *hprio = &hlevel->hprio[prio]; + /* look initial class up in the row */ - start = cl = htb_lookup_leaf(q->row[level] + prio, prio, - q->ptr[level] + prio, - q->last_ptr_id[level] + prio); + start = cl = htb_lookup_leaf(hprio, prio); do { next: @@ -819,9 +833,7 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, if ((q->row_mask[level] & (1 << prio)) == 0) return NULL; - next = htb_lookup_leaf(q->row[level] + prio, - prio, q->ptr[level] + prio, - q->last_ptr_id[level] + prio); + next = htb_lookup_leaf(hprio, prio); if (cl == start) /* fix start if we just deleted it */ start = next; @@ -834,11 +846,9 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, break; qdisc_warn_nonwc("htb", cl->un.leaf.q); - htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> - ptr[0]) + prio); - cl = htb_lookup_leaf(q->row[level] + prio, prio, - q->ptr[level] + prio, - q->last_ptr_id[level] + prio); + htb_next_rb_node(level ? &cl->parent->un.inner.clprio[prio].ptr: + &q->hlevel[0].hprio[prio].ptr); + cl = htb_lookup_leaf(hprio, prio); } while (cl != start); @@ -847,8 +857,8 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb); if (cl->un.leaf.deficit[level] < 0) { cl->un.leaf.deficit[level] += cl->quantum; - htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> - ptr[0]) + prio); + htb_next_rb_node(level ? &cl->parent->un.inner.clprio[prio].ptr : + &q->hlevel[0].hprio[prio].ptr); } /* this used to be after charge_class but this constelation * gives us slightly better performance @@ -888,15 +898,14 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) for (level = 0; level < TC_HTB_MAXDEPTH; level++) { /* common case optimization - skip event handler quickly */ int m; - s64 event; + s64 event = q->near_ev_cache[level]; - if (q->now >= q->near_ev_cache[level]) { + if (q->now >= event) { event = htb_do_events(q, level, start_at); if (!event) event = q->now + NSEC_PER_SEC; q->near_ev_cache[level] = event; - } else - event = q->near_ev_cache[level]; + } if (next_event > event) next_event = event; @@ -976,10 +985,8 @@ static void htb_reset(struct Qdisc *sch) qdisc_watchdog_cancel(&q->watchdog); __skb_queue_purge(&q->direct_queue); sch->q.qlen = 0; - memset(q->row, 0, sizeof(q->row)); + memset(q->hlevel, 0, sizeof(q->hlevel)); memset(q->row_mask, 0, sizeof(q->row_mask)); - memset(q->wait_pq, 0, sizeof(q->wait_pq)); - memset(q->ptr, 0, sizeof(q->ptr)); for (i = 0; i < TC_HTB_NUMPRIO; i++) INIT_LIST_HEAD(q->drops + i); } @@ -1200,7 +1207,8 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, WARN_ON(cl->level || !cl->un.leaf.q || cl->prio_activity); if (parent->cmode != HTB_CAN_SEND) - htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level); + htb_safe_rb_erase(&parent->pq_node, + &q->hlevel[parent->level].wait_pq); parent->level = 0; memset(&parent->un.inner, 0, sizeof(parent->un.inner)); @@ -1289,7 +1297,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) htb_deactivate(q, cl); if (cl->cmode != HTB_CAN_SEND) - htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); + htb_safe_rb_erase(&cl->pq_node, + &q->hlevel[cl->level].wait_pq); if (last_child) htb_parent_to_leaf(q, cl, new_q); @@ -1411,7 +1420,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, /* remove from evt list because of level change */ if (parent->cmode != HTB_CAN_SEND) { - htb_safe_rb_erase(&parent->pq_node, q->wait_pq); + htb_safe_rb_erase(&parent->pq_node, &q->hlevel[0].wait_pq); parent->cmode = HTB_CAN_SEND; } parent->level = (parent->parent ? parent->parent->level -- GitLab From af92e5425e4a7cfbc9b85dc268acfaadb551cc56 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Sat, 15 Jun 2013 23:04:56 +0300 Subject: [PATCH 1509/2900] inet: frag , remove an empty ifdef. This patch removes an empty ifdef from inet_frag_intern() in net/ipv4/inet_fragment.c. commit b67bfe0d42cac56c512dd5da4b1b347a23f4b70a (hlist: drop the node parameter from iterators) removed hlist from net/ipv4/inet_fragment.c, but did not remove the enclosing ifdef command, which is now empty. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/ipv4/inet_fragment.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 7e06641e36ae..4b864430a8c4 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -247,8 +247,6 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, { struct inet_frag_bucket *hb; struct inet_frag_queue *qp; -#ifdef CONFIG_SMP -#endif unsigned int hash; read_lock(&f->lock); /* Protects against hash rebuild */ -- GitLab From 9e8cda3ba84e1b85ff11b5d31ac80a753e7f9547 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 13 Jun 2013 19:37:53 -0700 Subject: [PATCH 1510/2900] ipv6: Convert use of typedef ctl_table to struct ctl_table This typedef is unnecessary and should just be removed. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ipv6.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index ab47582f6c0b..5fe564985171 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -859,8 +859,8 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; } #endif #ifdef CONFIG_SYSCTL -extern ctl_table ipv6_route_table_template[]; -extern ctl_table ipv6_icmp_table_template[]; +extern struct ctl_table ipv6_route_table_template[]; +extern struct ctl_table ipv6_icmp_table_template[]; extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); -- GitLab From fedaf4ffc224a194e2d13a3ec2abe5df0bc94258 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 13 Jun 2013 19:37:54 -0700 Subject: [PATCH 1511/2900] ndisc: Convert use of typedef ctl_table to struct ctl_table This typedef is unnecessary and should just be removed. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ndisc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 745bf741e029..949d77528f2f 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -230,7 +230,7 @@ extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, void __user *buffer, size_t *lenp, loff_t *ppos); -int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, +int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen); #endif -- GitLab From 997174705458d2abdbc31ba1594bf2a4503cb41a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 18 Jun 2013 15:35:39 +0530 Subject: [PATCH 1512/2900] mfd: davinci_voicecodec: Fix build breakage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the missing header file to fix the following build error: drivers/mfd/davinci_voicecodec.c: In function ‘davinci_vc_probe’: drivers/mfd/davinci_voicecodec.c:86:3: error: implicit declaration of function ‘io_v2p’ [-Werror=implicit-function-declaration] (dma_addr_t)(io_v2p(davinci_vc->base) + DAVINCI_VC_WFIFO); Signed-off-by: Sachin Kamat Signed-off-by: Samuel Ortiz --- include/linux/mfd/davinci_voicecodec.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h index 94c53d4819c7..810aee7e53eb 100644 --- a/include/linux/mfd/davinci_voicecodec.h +++ b/include/linux/mfd/davinci_voicecodec.h @@ -28,6 +28,7 @@ #include #include +#include /* * Register values. -- GitLab From 89ce43fbbce525f99991ed060b1302bd3fdae9c6 Mon Sep 17 00:00:00 2001 From: Graeme Gregory Date: Wed, 19 Jun 2013 15:24:02 +0300 Subject: [PATCH 1513/2900] mfd: twl-core: Change TWL6025 references to TWL6032 The TWL6025 was never released beyond sample form and was replaced by the PhoenixLite range of chips - TWL6032. Change the references to reference the TWL6032 class and name the registers to twl6032 in line with an actual released chip name to avoid confusion. Currently there are no users of TWL6025 in the code. Signed-off-by: Graeme Gregory Signed-off-by: Oleksandr Kozaruk Acked-by: Lee Jones Reviwed-by: Mark Brown Signed-off-by: Samuel Ortiz --- .../bindings/regulator/twl-regulator.txt | 26 +++---- .../devicetree/bindings/usb/twlxxxx-usb.txt | 2 +- drivers/mfd/twl-core.c | 46 +++++------ drivers/regulator/twl-regulator.c | 76 +++++++++---------- drivers/usb/phy/phy-twl6030-usb.c | 2 +- include/linux/i2c/twl.h | 30 ++++---- 6 files changed, 91 insertions(+), 91 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/twl-regulator.txt b/Documentation/devicetree/bindings/regulator/twl-regulator.txt index 658749b90b97..75b0c1669504 100644 --- a/Documentation/devicetree/bindings/regulator/twl-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/twl-regulator.txt @@ -18,20 +18,20 @@ For twl6030 regulators/LDOs - "ti,twl6030-vdd1" for VDD1 SMPS - "ti,twl6030-vdd2" for VDD2 SMPS - "ti,twl6030-vdd3" for VDD3 SMPS -For twl6025 regulators/LDOs +For twl6032 regulators/LDOs - compatible: - - "ti,twl6025-ldo1" for LDO1 LDO - - "ti,twl6025-ldo2" for LDO2 LDO - - "ti,twl6025-ldo3" for LDO3 LDO - - "ti,twl6025-ldo4" for LDO4 LDO - - "ti,twl6025-ldo5" for LDO5 LDO - - "ti,twl6025-ldo6" for LDO6 LDO - - "ti,twl6025-ldo7" for LDO7 LDO - - "ti,twl6025-ldoln" for LDOLN LDO - - "ti,twl6025-ldousb" for LDOUSB LDO - - "ti,twl6025-smps3" for SMPS3 SMPS - - "ti,twl6025-smps4" for SMPS4 SMPS - - "ti,twl6025-vio" for VIO SMPS + - "ti,twl6032-ldo1" for LDO1 LDO + - "ti,twl6032-ldo2" for LDO2 LDO + - "ti,twl6032-ldo3" for LDO3 LDO + - "ti,twl6032-ldo4" for LDO4 LDO + - "ti,twl6032-ldo5" for LDO5 LDO + - "ti,twl6032-ldo6" for LDO6 LDO + - "ti,twl6032-ldo7" for LDO7 LDO + - "ti,twl6032-ldoln" for LDOLN LDO + - "ti,twl6032-ldousb" for LDOUSB LDO + - "ti,twl6032-smps3" for SMPS3 SMPS + - "ti,twl6032-smps4" for SMPS4 SMPS + - "ti,twl6032-vio" for VIO SMPS For twl4030 regulators/LDOs - compatible: - "ti,twl4030-vaux1" for VAUX1 LDO diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt index 36b9aede3f40..0aee0ad3f035 100644 --- a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt +++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt @@ -8,7 +8,7 @@ TWL6030 USB COMPARATOR usb interrupt number that raises VBUS interrupts when the controller has to act as device - usb-supply : phandle to the regulator device tree node. It should be vusb - if it is twl6030 or ldousb if it is twl6025 subclass. + if it is twl6030 or ldousb if it is twl6032 subclass. twl6030-usb { compatible = "ti,twl6030-usb"; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index dbd52b373b27..7f150d94d295 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -118,7 +118,7 @@ #define TWL6030_BASEADD_GASGAUGE 0x00C0 #define TWL6030_BASEADD_PIH 0x00D0 #define TWL6030_BASEADD_CHARGER 0x00E0 -#define TWL6025_BASEADD_CHARGER 0x00DA +#define TWL6032_BASEADD_CHARGER 0x00DA #define TWL6030_BASEADD_LED 0x00F4 /* subchip/slave 2 0x4A - DFT */ @@ -718,9 +718,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, | REGULATOR_CHANGE_STATUS, }; - if (features & TWL6025_SUBCLASS) { + if (features & TWL6032_SUBCLASS) { usb3v3.supply = "ldousb"; - regulator = TWL6025_REG_LDOUSB; + regulator = TWL6032_REG_LDOUSB; } else { usb3v3.supply = "vusb"; regulator = TWL6030_REG_VUSB; @@ -747,8 +747,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, usb3v3.dev_name = dev_name(child); } else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) { - if (features & TWL6025_SUBCLASS) - child = add_regulator(TWL6025_REG_LDOUSB, + if (features & TWL6032_SUBCLASS) + child = add_regulator(TWL6032_REG_LDOUSB, pdata->ldousb, features); else child = add_regulator(TWL6030_REG_VUSB, @@ -872,7 +872,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, /* twl6030 regulators */ if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - !(features & TWL6025_SUBCLASS)) { + !(features & TWL6032_SUBCLASS)) { child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1, features); if (IS_ERR(child)) @@ -952,60 +952,60 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, return PTR_ERR(child); } - /* twl6025 regulators */ + /* twl6032 regulators */ if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() && - (features & TWL6025_SUBCLASS)) { - child = add_regulator(TWL6025_REG_LDO5, pdata->ldo5, + (features & TWL6032_SUBCLASS)) { + child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO1, pdata->ldo1, + child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO7, pdata->ldo7, + child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO6, pdata->ldo6, + child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDOLN, pdata->ldoln, + child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO2, pdata->ldo2, + child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO4, pdata->ldo4, + child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_LDO3, pdata->ldo3, + child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_SMPS3, pdata->smps3, + child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_SMPS4, pdata->smps4, + child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4, features); if (IS_ERR(child)) return PTR_ERR(child); - child = add_regulator(TWL6025_REG_VIO, pdata->vio6025, + child = add_regulator(TWL6032_REG_VIO, pdata->vio6025, features); if (IS_ERR(child)) return PTR_ERR(child); @@ -1184,10 +1184,10 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) if ((id->driver_data) & TWL6030_CLASS) { twl_priv->twl_id = TWL6030_CLASS_ID; twl_priv->twl_map = &twl6030_map[0]; - /* The charger base address is different in twl6025 */ - if ((id->driver_data) & TWL6025_SUBCLASS) + /* The charger base address is different in twl6032 */ + if ((id->driver_data) & TWL6032_SUBCLASS) twl_priv->twl_map[TWL_MODULE_MAIN_CHARGE].base = - TWL6025_BASEADD_CHARGER; + TWL6032_BASEADD_CHARGER; twl_regmap_config = twl6030_regmap_config; } else { twl_priv->twl_id = TWL4030_CLASS_ID; @@ -1296,7 +1296,7 @@ static const struct i2c_device_id twl_ids[] = { { "tps65921", TPS_SUBSET }, /* fewer LDOs; no codec, no LED and vibrator. Charger in USB module*/ { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ - { "twl6025", TWL6030_CLASS | TWL6025_SUBCLASS }, /* "Phoenix lite" */ + { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */ { /* end of list */ }, }; MODULE_DEVICE_TABLE(i2c, twl_ids); diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index fb6e67d74ffb..93bc4f456da4 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -109,7 +109,7 @@ struct twlreg_info { #define SMPS_OFFSET_EN BIT(0) #define SMPS_EXTENDED_EN BIT(1) -/* twl6025 SMPS EPROM values */ +/* twl6032 SMPS EPROM values */ #define TWL6030_SMPS_OFFSET 0xB0 #define TWL6030_SMPS_MULT 0xB3 #define SMPS_MULTOFFSET_SMPS4 BIT(0) @@ -173,7 +173,7 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev) struct twlreg_info *info = rdev_get_drvdata(rdev); int grp = 0, val; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) { + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) { grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -211,7 +211,7 @@ static int twl6030reg_enable(struct regulator_dev *rdev) int grp = 0; int ret; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) return grp; @@ -245,7 +245,7 @@ static int twl6030reg_disable(struct regulator_dev *rdev) int grp = 0; int ret; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; /* For 6030, set the off state for all grps enabled */ @@ -339,7 +339,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) int grp = 0; int val; - if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) + if (!(twl_class_is_6030() && (info->features & TWL6032_SUBCLASS))) grp = twlreg_grp(rdev); if (grp < 0) @@ -899,14 +899,14 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ }, \ } -#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ -static const struct twlreg_info TWL6025_INFO_##label = { \ +#define TWL6032_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) \ +static const struct twlreg_info TWL6032_INFO_##label = { \ .base = offset, \ .min_mV = min_mVolts, \ .max_mV = max_mVolts, \ .desc = { \ .name = #label, \ - .id = TWL6025_REG_##label, \ + .id = TWL6032_REG_##label, \ .n_voltages = 32, \ .ops = &twl6030ldo_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -933,14 +933,14 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \ }, \ } -#define TWL6025_ADJUSTABLE_SMPS(label, offset) \ +#define TWL6032_ADJUSTABLE_SMPS(label, offset) \ static const struct twlreg_info TWLSMPS_INFO_##label = { \ .base = offset, \ .min_mV = 600, \ .max_mV = 2100, \ .desc = { \ .name = #label, \ - .id = TWL6025_REG_##label, \ + .id = TWL6032_REG_##label, \ .n_voltages = 63, \ .ops = &twlsmps_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -981,15 +981,15 @@ TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300); TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300); TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300); /* 6025 are renamed compared to 6030 versions */ -TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); -TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); +TWL6032_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); @@ -1001,9 +1001,9 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0); TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0); TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0); TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); -TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34); -TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10); -TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); +TWL6032_ADJUSTABLE_SMPS(SMPS3, 0x34); +TWL6032_ADJUSTABLE_SMPS(SMPS4, 0x10); +TWL6032_ADJUSTABLE_SMPS(VIO, 0x16); static u8 twl_get_smps_offset(void) { @@ -1031,7 +1031,7 @@ static u8 twl_get_smps_mult(void) #define TWL4030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL4030, label) #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label) -#define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label) +#define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label) #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label) #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label) @@ -1060,15 +1060,15 @@ static const struct of_device_id twl_of_match[] = { TWL6030_OF_MATCH("ti,twl6030-vmmc", VMMC), TWL6030_OF_MATCH("ti,twl6030-vpp", VPP), TWL6030_OF_MATCH("ti,twl6030-vusim", VUSIM), - TWL6025_OF_MATCH("ti,twl6025-ldo2", LDO2), - TWL6025_OF_MATCH("ti,twl6025-ldo4", LDO4), - TWL6025_OF_MATCH("ti,twl6025-ldo3", LDO3), - TWL6025_OF_MATCH("ti,twl6025-ldo5", LDO5), - TWL6025_OF_MATCH("ti,twl6025-ldo1", LDO1), - TWL6025_OF_MATCH("ti,twl6025-ldo7", LDO7), - TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), - TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), - TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), + TWL6032_OF_MATCH("ti,twl6032-ldo2", LDO2), + TWL6032_OF_MATCH("ti,twl6032-ldo4", LDO4), + TWL6032_OF_MATCH("ti,twl6032-ldo3", LDO3), + TWL6032_OF_MATCH("ti,twl6032-ldo5", LDO5), + TWL6032_OF_MATCH("ti,twl6032-ldo1", LDO1), + TWL6032_OF_MATCH("ti,twl6032-ldo7", LDO7), + TWL6032_OF_MATCH("ti,twl6032-ldo6", LDO6), + TWL6032_OF_MATCH("ti,twl6032-ldoln", LDOLN), + TWL6032_OF_MATCH("ti,twl6032-ldousb", LDOUSB), TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), @@ -1080,9 +1080,9 @@ static const struct of_device_id twl_of_match[] = { TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB), TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8), TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1), - TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3), - TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4), - TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO), + TWLSMPS_OF_MATCH("ti,twl6032-smps3", SMPS3), + TWLSMPS_OF_MATCH("ti,twl6032-smps4", SMPS4), + TWLSMPS_OF_MATCH("ti,twl6032-vio", VIO), {}, }; MODULE_DEVICE_TABLE(of, twl_of_match); @@ -1163,19 +1163,19 @@ static int twlreg_probe(struct platform_device *pdev) } switch (id) { - case TWL6025_REG_SMPS3: + case TWL6032_REG_SMPS3: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3) info->flags |= SMPS_OFFSET_EN; break; - case TWL6025_REG_SMPS4: + case TWL6032_REG_SMPS4: if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4) info->flags |= SMPS_OFFSET_EN; break; - case TWL6025_REG_VIO: + case TWL6032_REG_VIO: if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO) info->flags |= SMPS_EXTENDED_EN; if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 9de7ada90a8b..1753bd367e0a 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -347,7 +347,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) if (np) { twl->regulator = "usb"; } else if (pdata) { - if (pdata->features & TWL6025_SUBCLASS) + if (pdata->features & TWL6032_SUBCLASS) twl->regulator = "ldousb"; else twl->regulator = "vusb"; diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 2167c0d00abf..81cbbdb96aae 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h @@ -725,7 +725,7 @@ struct twl4030_platform_data { struct regulator_init_data *clk32kg; struct regulator_init_data *v1v8; struct regulator_init_data *v2v1; - /* TWL6025 LDO regulators */ + /* TWL6032 LDO regulators */ struct regulator_init_data *ldo1; struct regulator_init_data *ldo2; struct regulator_init_data *ldo3; @@ -735,7 +735,7 @@ struct twl4030_platform_data { struct regulator_init_data *ldo7; struct regulator_init_data *ldoln; struct regulator_init_data *ldousb; - /* TWL6025 DCDC regulators */ + /* TWL6032 DCDC regulators */ struct regulator_init_data *smps3; struct regulator_init_data *smps4; struct regulator_init_data *vio6025; @@ -752,7 +752,7 @@ struct twl_regulator_driver_data { #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ #define TWL5031 BIT(2) /* twl5031 has different registers */ #define TWL6030_CLASS BIT(3) /* TWL6030 class */ -#define TWL6025_SUBCLASS BIT(4) /* TWL6025 has changed registers */ +#define TWL6032_SUBCLASS BIT(4) /* TWL6032 has changed registers */ #define TWL4030_ALLOW_UNSUPPORTED BIT(5) /* Some voltages are possible * but not officially supported. * This flag is necessary to @@ -839,20 +839,20 @@ static inline int twl4030charger_usb_en(int enable) { return 0; } #define TWL6030_REG_CLK32KG 48 /* LDOs on 6025 have different names */ -#define TWL6025_REG_LDO2 49 -#define TWL6025_REG_LDO4 50 -#define TWL6025_REG_LDO3 51 -#define TWL6025_REG_LDO5 52 -#define TWL6025_REG_LDO1 53 -#define TWL6025_REG_LDO7 54 -#define TWL6025_REG_LDO6 55 -#define TWL6025_REG_LDOLN 56 -#define TWL6025_REG_LDOUSB 57 +#define TWL6032_REG_LDO2 49 +#define TWL6032_REG_LDO4 50 +#define TWL6032_REG_LDO3 51 +#define TWL6032_REG_LDO5 52 +#define TWL6032_REG_LDO1 53 +#define TWL6032_REG_LDO7 54 +#define TWL6032_REG_LDO6 55 +#define TWL6032_REG_LDOLN 56 +#define TWL6032_REG_LDOUSB 57 /* 6025 DCDC supplies */ -#define TWL6025_REG_SMPS3 58 -#define TWL6025_REG_SMPS4 59 -#define TWL6025_REG_VIO 60 +#define TWL6032_REG_SMPS3 58 +#define TWL6032_REG_SMPS4 59 +#define TWL6032_REG_VIO 60 #endif /* End of __TWL4030_H */ -- GitLab From 283aae8ab88e695a660c610d6535ca44bc5b8835 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Wed, 19 Jun 2013 17:04:25 -0700 Subject: [PATCH 1514/2900] mfd: lpc_ich: iTCO_wdt patch for Intel Coleto Creek DeviceIDs This patch adds the LPC Controller DeviceIDs for iTCO Watchdog for the Intel Coleto Creek PCH. Signed-off-by: Seth Heasley Signed-off-by: Samuel Ortiz --- drivers/mfd/lpc_ich.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index 9682bee80d53..24033324c17a 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -52,6 +52,7 @@ * document number TBD : Lynx Point-LP * document number TBD : Wellsburg * document number TBD : Avoton SoC + * document number TBD : Coleto Creek */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -209,6 +210,7 @@ enum lpc_chipsets { LPC_LPT_LP, /* Lynx Point-LP */ LPC_WBG, /* Wellsburg */ LPC_AVN, /* Avoton SoC */ + LPC_COLETO, /* Coleto Creek */ }; struct lpc_ich_info lpc_chipset_info[] = { @@ -497,6 +499,10 @@ struct lpc_ich_info lpc_chipset_info[] = { .name = "Avoton SoC", .iTCO_version = 1, }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, }; /* @@ -714,6 +720,7 @@ static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = { { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, lpc_ich_ids); -- GitLab From ad522f4e351d020714959d9570baf3de7fcbad11 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Wed, 19 Jun 2013 11:27:47 +0530 Subject: [PATCH 1515/2900] mfd: palmas: Check if irq is valid Check if irq value obtained is valid. If it is not valid then skip the irq request step and go ahead with the probe. Signed-off-by: J Keerthy Reviewed-by: Mark Brown Reviewed-by: Stephen Warren Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index 62fa728d3e04..b24bee3d00b4 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -290,6 +290,11 @@ static int palmas_i2c_probe(struct i2c_client *i2c, } } + if (!palmas->irq) { + dev_warn(palmas->dev, "IRQ missing: skipping irq request\n"); + goto no_irq; + } + /* Change interrupt line output polarity */ if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH) reg = PALMAS_POLARITY_CTRL_INT_POLARITY; @@ -316,6 +321,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, if (ret < 0) goto err; +no_irq: slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, PALMAS_PRIMARY_SECONDARY_PAD1); -- GitLab From 130ffbc2638ddc290fcbabe1b9ce6a5d333a6a97 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 12 Jun 2013 17:54:51 +0200 Subject: [PATCH 1516/2900] netfilter: check return code from nla_parse_tested These are the only calls under net/ that do not check nla_parse_nested() for its error code, but simply continue execution. If parsing of netlink attributes fails, we should return with an error instead of continuing. In nearly all of these calls we have a policy attached, that is being type verified during nla_parse_nested(), which we would miss checking for otherwise. Signed-off-by: Daniel Borkmann Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_netlink.c | 30 +++++++++++++++++++++------- net/netfilter/nfnetlink_cthelper.c | 16 +++++++++++---- net/netfilter/nfnetlink_cttimeout.c | 6 ++++-- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 6d0f8a17c5b7..f83a52298efe 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -828,7 +828,9 @@ ctnetlink_parse_tuple_ip(struct nlattr *attr, struct nf_conntrack_tuple *tuple) struct nf_conntrack_l3proto *l3proto; int ret = 0; - nla_parse_nested(tb, CTA_IP_MAX, attr, NULL); + ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL); + if (ret < 0) + return ret; rcu_read_lock(); l3proto = __nf_ct_l3proto_find(tuple->src.l3num); @@ -895,7 +897,9 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[], memset(tuple, 0, sizeof(*tuple)); - nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy); + err = nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy); + if (err < 0) + return err; if (!tb[CTA_TUPLE_IP]) return -EINVAL; @@ -946,9 +950,12 @@ static inline int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, struct nlattr **helpinfo) { + int err; struct nlattr *tb[CTA_HELP_MAX+1]; - nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy); + err = nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy); + if (err < 0) + return err; if (!tb[CTA_HELP_NAME]) return -EINVAL; @@ -1431,7 +1438,9 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[] struct nf_conntrack_l4proto *l4proto; int err = 0; - nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy); + err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy); + if (err < 0) + return err; rcu_read_lock(); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); @@ -1452,9 +1461,12 @@ static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = { static inline int change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) { + int err; struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; - nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); + err = nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); + if (err < 0) + return err; if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) return -EINVAL; @@ -2115,7 +2127,9 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) struct nlattr *cda[CTA_MAX+1]; int ret; - nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); + ret = nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); + if (ret < 0) + return ret; spin_lock_bh(&nf_conntrack_lock); ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); @@ -2710,7 +2724,9 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr, struct nf_conntrack_tuple nat_tuple = {}; int err; - nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); + err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); + if (err < 0) + return err; if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) return -EINVAL; diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index a191b6db657e..9e287cb56a04 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -67,9 +67,12 @@ static int nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, const struct nlattr *attr) { + int err; struct nlattr *tb[NFCTH_TUPLE_MAX+1]; - nla_parse_nested(tb, NFCTH_TUPLE_MAX, attr, nfnl_cthelper_tuple_pol); + err = nla_parse_nested(tb, NFCTH_TUPLE_MAX, attr, nfnl_cthelper_tuple_pol); + if (err < 0) + return err; if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) return -EINVAL; @@ -121,9 +124,12 @@ static int nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy, const struct nlattr *attr) { + int err; struct nlattr *tb[NFCTH_POLICY_MAX+1]; - nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, nfnl_cthelper_expect_pol); + err = nla_parse_nested(tb, NFCTH_POLICY_MAX, attr, nfnl_cthelper_expect_pol); + if (err < 0) + return err; if (!tb[NFCTH_POLICY_NAME] || !tb[NFCTH_POLICY_EXPECT_MAX] || @@ -153,8 +159,10 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, struct nf_conntrack_expect_policy *expect_policy; struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; - nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, - nfnl_cthelper_expect_policy_set); + ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, + nfnl_cthelper_expect_policy_set); + if (ret < 0) + return ret; if (!tb[NFCTH_POLICY_SET_NUM]) return -EINVAL; diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 65074dfb9383..50580494148d 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -59,8 +59,10 @@ ctnl_timeout_parse_policy(struct ctnl_timeout *timeout, if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) { struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1]; - nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, - attr, l4proto->ctnl_timeout.nla_policy); + ret = nla_parse_nested(tb, l4proto->ctnl_timeout.nlattr_max, + attr, l4proto->ctnl_timeout.nla_policy); + if (ret < 0) + return ret; ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, &timeout->data); -- GitLab From 6547a221871f139cc56328a38105d47c14874cbe Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 13 Jun 2013 17:31:28 +0200 Subject: [PATCH 1517/2900] netfilter: nf_conntrack: avoid large timeout for mid-stream pickup When loose tracking is enabled (default), non-syn packets cause creation of new conntracks in established state with default timeout for established state (5 days). This causes the table to fill up with UNREPLIED when the 'new ack' packet happened to be the last-ack of a previous, already timed-out connection. Consider: A 192.168.x.52792 > 10.184.y.80: F, 426:426(0) ack 9237 win 255 B 10.184.y.80 > 192.168.x.52792: ., ack 427 win 123 <61 second pause> C 10.184.y.80 > 192.168.x.52792: F, 9237:9237(0) ack 427 win 123 D 192.168.x.52792 > 10.184.y.80: ., ack 9238 win 255 B moves conntrack to CLOSE_WAIT and will kill it after 60 second timeout, C is ignored (FIN set), but last packet (D) causes new ct with 5-days timeout. Use UNACK timeout (5 minutes) instead to get rid of these entries sooner when in ESTABLISHED state without having seen traffic in both directions. Signed-off-by: Florian Westphal Acked-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_proto_tcp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 4d4d8f1d01fc..7dcc376eea5f 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1043,6 +1043,12 @@ static int tcp_packet(struct nf_conn *ct, nf_ct_kill_acct(ct, ctinfo, skb); return NF_ACCEPT; } + /* ESTABLISHED without SEEN_REPLY, i.e. mid-connection + * pickup with loose=1. Avoid large ESTABLISHED timeout. + */ + if (new_state == TCP_CONNTRACK_ESTABLISHED && + timeout > timeouts[TCP_CONNTRACK_UNACK]) + timeout = timeouts[TCP_CONNTRACK_UNACK]; } else if (!test_bit(IPS_ASSURED_BIT, &ct->status) && (old_state == TCP_CONNTRACK_SYN_RECV || old_state == TCP_CONNTRACK_ESTABLISHED) -- GitLab From 1ffb0be3ad6186b421921de91092917f0b3ee3e2 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Wed, 19 Jun 2013 11:27:48 +0530 Subject: [PATCH 1518/2900] mfd: palmas: Add SMPS10_BOOST feature The SMPS10 regulator is not presesnt in all the variants of the PALMAS PMIC family. Hence adding a feature to distingush between them. Signed-off-by: J Keerthy Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 29 ++++++++++++++++++++-------- drivers/regulator/palmas-regulator.c | 3 +++ include/linux/mfd/palmas.h | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index b24bee3d00b4..a4e53caa76cd 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include static const struct regmap_config palmas_regmap_config[PALMAS_NUM_CLIENTS] = { { @@ -231,6 +231,16 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c, palmas_set_pdata_irq_flag(i2c, pdata); } +static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; + +static const struct of_device_id of_palmas_match_tbl[] = { + { + .compatible = "ti,palmas", + .data = &palmas_features, + }, + { }, +}; + static int palmas_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -238,8 +248,9 @@ static int palmas_i2c_probe(struct i2c_client *i2c, struct palmas_platform_data *pdata; struct device_node *node = i2c->dev.of_node; int ret = 0, i; - unsigned int reg, addr; + unsigned int reg, addr, *features; int slave; + const struct of_device_id *match; pdata = dev_get_platdata(&i2c->dev); @@ -261,9 +272,16 @@ static int palmas_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, palmas); palmas->dev = &i2c->dev; - palmas->id = id->driver_data; palmas->irq = i2c->irq; + match = of_match_device(of_match_ptr(of_palmas_match_tbl), &i2c->dev); + + if (!match) + return -ENODATA; + + features = (unsigned int *)match->data; + palmas->features = *features; + for (i = 0; i < PALMAS_NUM_CLIENTS; i++) { if (i == 0) palmas->i2c_clients[i] = i2c; @@ -433,11 +451,6 @@ static const struct i2c_device_id palmas_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); -static struct of_device_id of_palmas_match_tbl[] = { - { .compatible = "ti,palmas", }, - { /* end */ } -}; - static struct i2c_driver palmas_i2c_driver = { .driver = { .name = "palmas", diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 3ae44ac12a94..1ae1e83448cf 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -838,6 +838,9 @@ static int palmas_regulators_probe(struct platform_device *pdev) continue; ramp_delay_support = true; break; + case PALMAS_REG_SMPS10: + if (!PALMAS_PMIC_HAS(palmas, SMPS10_BOOST)) + continue; } if ((id == PALMAS_REG_SMPS6) || (id == PALMAS_REG_SMPS8)) diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index 8f21daf62fb5..98058caa7aca 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -32,6 +32,19 @@ ((a) == PALMAS_CHIP_ID)) #define is_palmas_charger(a) ((a) == PALMAS_CHIP_CHARGER_ID) +/** + * Palmas PMIC feature types + * + * PALMAS_PMIC_FEATURE_SMPS10_BOOST - used when the PMIC provides SMPS10_BOOST + * regulator. + * + * PALMAS_PMIC_HAS(b, f) - macro to check if a bandgap device is capable of a + * specific feature (above) or not. Return non-zero, if yes. + */ +#define PALMAS_PMIC_FEATURE_SMPS10_BOOST BIT(0) +#define PALMAS_PMIC_HAS(b, f) \ + ((b)->features & PALMAS_PMIC_FEATURE_ ## f) + struct palmas_pmic; struct palmas_gpadc; struct palmas_resource; @@ -46,6 +59,7 @@ struct palmas { /* Stored chip id */ int id; + unsigned int features; /* IRQ Data */ int irq; u32 irq_mask; -- GitLab From 21bfd4706268c85c9d17ca2fd48de3b19c9d40db Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Jun 2013 10:27:38 +0300 Subject: [PATCH 1519/2900] RDMA/cxgb3: Timeout condition is never true This is a static checker fix. "count" is unsigned so it's never -1. Since "count" is 16 bits and the addition operation is implicitly casted to int then there is no wrapping here. Signed-off-by: Dan Carpenter Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb3/iwch_qp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index e5649e8b215d..b57c0befd962 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -883,7 +883,8 @@ u16 iwch_rqes_posted(struct iwch_qp *qhp) { union t3_wr *wqe = qhp->wq.queue; u16 count = 0; - while ((count+1) != 0 && fw_riwrh_opcode((struct fw_riwrh *)wqe) == T3_WR_RCV) { + + while (count < USHRT_MAX && fw_riwrh_opcode((struct fw_riwrh *)wqe) == T3_WR_RCV) { count++; wqe++; } -- GitLab From f29fa1cf340e21085672ccfeb6d66f292208567e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 19 Jun 2013 10:40:09 +0800 Subject: [PATCH 1520/2900] IB/ehca: Fix error return code in ehca_create_slab_caches() Fix to return -ENOMEM in the kmem_cache_create() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index f8a62918a88d..8f43093edace 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -211,6 +211,7 @@ static int ehca_create_slab_caches(void) if (!ctblk_cache) { ehca_gen_err("Cannot create ctblk SLAB cache."); ehca_cleanup_small_qp_cache(); + ret = -ENOMEM; goto create_slab_caches6; } #endif -- GitLab From 27159f5087f9ff59fdc42958a31bca3a291b9f67 Mon Sep 17 00:00:00 2001 From: "Gottumukkala, Naresh" Date: Wed, 5 Jun 2013 08:50:46 +0000 Subject: [PATCH 1521/2900] RDMA/ocrdma: Remove use_cnt for queues Remove use_cnt. Rely on IB midlayer to keep track of the use count. Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma.h | 4 --- drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 1 - drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 39 +-------------------- 3 files changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 48970af23679..21d99f6fb367 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -97,7 +97,6 @@ struct ocrdma_queue_info { u16 id; /* qid, where to ring the doorbell. */ u16 head, tail; bool created; - atomic_t used; /* Number of valid elements in the queue */ }; struct ocrdma_eq { @@ -198,7 +197,6 @@ struct ocrdma_cq { struct ocrdma_ucontext *ucontext; dma_addr_t pa; u32 len; - atomic_t use_cnt; /* head of all qp's sq and rq for which cqes need to be flushed * by the software. @@ -210,7 +208,6 @@ struct ocrdma_pd { struct ib_pd ibpd; struct ocrdma_dev *dev; struct ocrdma_ucontext *uctx; - atomic_t use_cnt; u32 id; int num_dpp_qp; u32 dpp_page; @@ -246,7 +243,6 @@ struct ocrdma_srq { struct ocrdma_qp_hwq_info rq; struct ocrdma_pd *pd; - atomic_t use_cnt; u32 id; u64 *rqe_wr_id_tbl; u32 *idx_bit_fields; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 71942af4fce9..910b706a91c7 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -128,7 +128,6 @@ static inline struct ocrdma_mqe *ocrdma_get_mqe(struct ocrdma_dev *dev) static inline void ocrdma_mq_inc_head(struct ocrdma_dev *dev) { dev->mq.sq.head = (dev->mq.sq.head + 1) & (OCRDMA_MQ_LEN - 1); - atomic_inc(&dev->mq.sq.used); } static inline void *ocrdma_get_mqe_rsp(struct ocrdma_dev *dev) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index b29a4246ef41..38c145b28f5c 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -398,7 +398,6 @@ struct ib_pd *ocrdma_alloc_pd(struct ib_device *ibdev, kfree(pd); return ERR_PTR(status); } - atomic_set(&pd->use_cnt, 0); if (udata && context) { status = ocrdma_copy_pd_uresp(pd, context, udata); @@ -419,12 +418,6 @@ int ocrdma_dealloc_pd(struct ib_pd *ibpd) int status; u64 usr_db; - if (atomic_read(&pd->use_cnt)) { - ocrdma_err("%s(%d) pd=0x%x is in use.\n", - __func__, dev->id, pd->id); - status = -EFAULT; - goto dealloc_err; - } status = ocrdma_mbx_dealloc_pd(dev, pd); if (pd->uctx) { u64 dpp_db = dev->nic_info.dpp_unmapped_addr + @@ -436,7 +429,6 @@ int ocrdma_dealloc_pd(struct ib_pd *ibpd) ocrdma_del_mmap(pd->uctx, usr_db, dev->nic_info.db_page_size); } kfree(pd); -dealloc_err: return status; } @@ -474,7 +466,6 @@ static struct ocrdma_mr *ocrdma_alloc_lkey(struct ib_pd *ibpd, return ERR_PTR(-ENOMEM); } mr->pd = pd; - atomic_inc(&pd->use_cnt); mr->ibmr.lkey = mr->hwmr.lkey; if (mr->hwmr.remote_wr || mr->hwmr.remote_rd) mr->ibmr.rkey = mr->hwmr.lkey; @@ -664,7 +655,6 @@ struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len, if (status) goto mbx_err; mr->pd = pd; - atomic_inc(&pd->use_cnt); mr->ibmr.lkey = mr->hwmr.lkey; if (mr->hwmr.remote_wr || mr->hwmr.remote_rd) mr->ibmr.rkey = mr->hwmr.lkey; @@ -689,7 +679,6 @@ int ocrdma_dereg_mr(struct ib_mr *ib_mr) if (mr->hwmr.fr_mr == 0) ocrdma_free_mr_pbl_tbl(dev, &mr->hwmr); - atomic_dec(&mr->pd->use_cnt); /* it could be user registered memory. */ if (mr->umem) ib_umem_release(mr->umem); @@ -752,7 +741,6 @@ struct ib_cq *ocrdma_create_cq(struct ib_device *ibdev, int entries, int vector, spin_lock_init(&cq->cq_lock); spin_lock_init(&cq->comp_handler_lock); - atomic_set(&cq->use_cnt, 0); INIT_LIST_HEAD(&cq->sq_head); INIT_LIST_HEAD(&cq->rq_head); cq->dev = dev; @@ -799,9 +787,6 @@ int ocrdma_destroy_cq(struct ib_cq *ibcq) struct ocrdma_cq *cq = get_ocrdma_cq(ibcq); struct ocrdma_dev *dev = cq->dev; - if (atomic_read(&cq->use_cnt)) - return -EINVAL; - status = ocrdma_mbx_destroy_cq(dev, cq); if (cq->ucontext) { @@ -1023,15 +1008,6 @@ static void ocrdma_set_qp_init_params(struct ocrdma_qp *qp, qp->state = OCRDMA_QPS_RST; } -static void ocrdma_set_qp_use_cnt(struct ocrdma_qp *qp, struct ocrdma_pd *pd) -{ - atomic_inc(&pd->use_cnt); - atomic_inc(&qp->sq_cq->use_cnt); - atomic_inc(&qp->rq_cq->use_cnt); - if (qp->srq) - atomic_inc(&qp->srq->use_cnt); - qp->ibqp.qp_num = qp->id; -} static void ocrdma_store_gsi_qp_cq(struct ocrdma_dev *dev, struct ib_qp_init_attr *attrs) @@ -1099,7 +1075,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd, goto cpy_err; } ocrdma_store_gsi_qp_cq(dev, attrs); - ocrdma_set_qp_use_cnt(qp, pd); + qp->ibqp.qp_num = qp->id; mutex_unlock(&dev->dev_lock); return &qp->ibqp; @@ -1475,11 +1451,6 @@ int ocrdma_destroy_qp(struct ib_qp *ibqp) ocrdma_del_flush_qp(qp); - atomic_dec(&qp->pd->use_cnt); - atomic_dec(&qp->sq_cq->use_cnt); - atomic_dec(&qp->rq_cq->use_cnt); - if (qp->srq) - atomic_dec(&qp->srq->use_cnt); kfree(qp->wqe_wr_id_tbl); kfree(qp->rqe_wr_id_tbl); kfree(qp); @@ -1565,14 +1536,12 @@ struct ib_srq *ocrdma_create_srq(struct ib_pd *ibpd, goto arm_err; } - atomic_set(&srq->use_cnt, 0); if (udata) { status = ocrdma_copy_srq_uresp(srq, udata); if (status) goto arm_err; } - atomic_inc(&pd->use_cnt); return &srq->ibsrq; arm_err: @@ -1618,18 +1587,12 @@ int ocrdma_destroy_srq(struct ib_srq *ibsrq) srq = get_ocrdma_srq(ibsrq); dev = srq->dev; - if (atomic_read(&srq->use_cnt)) { - ocrdma_err("%s(%d) err, srq=0x%x in use\n", - __func__, dev->id, srq->id); - return -EAGAIN; - } status = ocrdma_mbx_destroy_srq(dev, srq); if (srq->pd->uctx) ocrdma_del_mmap(srq->pd->uctx, (u64) srq->rq.pa, srq->rq.len); - atomic_dec(&srq->pd->use_cnt); kfree(srq->idx_bit_fields); kfree(srq->rqe_wr_id_tbl); kfree(srq); -- GitLab From b1d58b99194a121a44ec77571f84f62a6ccd6431 Mon Sep 17 00:00:00 2001 From: Naresh Gottumukkala Date: Mon, 10 Jun 2013 04:42:38 +0000 Subject: [PATCH 1522/2900] RDMA/ocrdma: Use MCC_CREATE_EXT_V1 for MCC create Use MCC_CREATE_EXT_V1 to create MCC_queue to receive RoCE events. Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 39 ++++++++--------------- drivers/infiniband/hw/ocrdma/ocrdma_sli.h | 20 ++---------- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 910b706a91c7..f671d5d9ce3a 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -563,32 +563,19 @@ static int ocrdma_mbx_create_mq(struct ocrdma_dev *dev, memset(cmd, 0, sizeof(*cmd)); num_pages = PAGES_4K_SPANNED(mq->va, mq->size); - if (dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { - ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ, - OCRDMA_SUBSYS_COMMON, sizeof(*cmd)); - cmd->v0.pages = num_pages; - cmd->v0.async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID; - cmd->v0.async_cqid_valid = (cq->id << 1); - cmd->v0.cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) << - OCRDMA_CREATE_MQ_RING_SIZE_SHIFT); - cmd->v0.cqid_ringsize |= - (cq->id << OCRDMA_CREATE_MQ_V0_CQ_ID_SHIFT); - cmd->v0.valid = OCRDMA_CREATE_MQ_VALID; - pa = &cmd->v0.pa[0]; - } else { - ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ_EXT, - OCRDMA_SUBSYS_COMMON, sizeof(*cmd)); - cmd->req.rsvd_version = 1; - cmd->v1.cqid_pages = num_pages; - cmd->v1.cqid_pages |= (cq->id << OCRDMA_CREATE_MQ_CQ_ID_SHIFT); - cmd->v1.async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID; - cmd->v1.async_event_bitmap = Bit(20); - cmd->v1.async_cqid_ringsize = cq->id; - cmd->v1.async_cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) << - OCRDMA_CREATE_MQ_RING_SIZE_SHIFT); - cmd->v1.valid = OCRDMA_CREATE_MQ_VALID; - pa = &cmd->v1.pa[0]; - } + ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ_EXT, + OCRDMA_SUBSYS_COMMON, sizeof(*cmd)); + cmd->req.rsvd_version = 1; + cmd->cqid_pages = num_pages; + cmd->cqid_pages |= (cq->id << OCRDMA_CREATE_MQ_CQ_ID_SHIFT); + cmd->async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID; + cmd->async_event_bitmap = Bit(20); + cmd->async_cqid_ringsize = cq->id; + cmd->async_cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) << + OCRDMA_CREATE_MQ_RING_SIZE_SHIFT); + cmd->valid = OCRDMA_CREATE_MQ_VALID; + pa = &cmd->pa[0]; + ocrdma_build_q_pages(pa, num_pages, mq->dma, PAGE_SIZE_4K); status = be_roce_mcc_cmd(dev->nic_info.netdev, cmd, sizeof(*cmd), NULL, NULL); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h index c75cbdfa87e7..cd0512f1fb5b 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h @@ -608,16 +608,8 @@ enum { OCRDMA_CREATE_MQ_ASYNC_CQ_VALID = Bit(0) }; -struct ocrdma_create_mq_v0 { - u32 pages; - u32 cqid_ringsize; - u32 valid; - u32 async_cqid_valid; - u32 rsvd; - struct ocrdma_pa pa[8]; -} __packed; - -struct ocrdma_create_mq_v1 { +struct ocrdma_create_mq_req { + struct ocrdma_mbx_hdr req; u32 cqid_pages; u32 async_event_bitmap; u32 async_cqid_ringsize; @@ -627,14 +619,6 @@ struct ocrdma_create_mq_v1 { struct ocrdma_pa pa[8]; } __packed; -struct ocrdma_create_mq_req { - struct ocrdma_mbx_hdr req; - union { - struct ocrdma_create_mq_v0 v0; - struct ocrdma_create_mq_v1 v1; - }; -} __packed; - struct ocrdma_create_mq_rsp { struct ocrdma_mbx_rsp rsp; u32 id; -- GitLab From ef99c4c2ed63cb0deb94ea70fb47c2d6294e302e Mon Sep 17 00:00:00 2001 From: Naresh Gottumukkala Date: Mon, 10 Jun 2013 04:42:39 +0000 Subject: [PATCH 1523/2900] RDMA/ocrdma: Replace ocrdma_err with pr_err Remove private macro ocrdma_err and replace with standard pr_err. Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma.h | 2 - drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 44 +++++----- drivers/infiniband/hw/ocrdma/ocrdma_main.c | 6 +- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 92 ++++++++++----------- 4 files changed, 70 insertions(+), 74 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 21d99f6fb367..9d82d097e25a 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -42,8 +42,6 @@ #define OCRDMA_ROCE_DEV_VERSION "1.0.0" #define OCRDMA_NODE_DESC "Emulex OneConnect RoCE HCA" -#define ocrdma_err(format, arg...) printk(KERN_ERR format, ##arg) - #define OCRDMA_MAX_AH 512 #define OCRDMA_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index f671d5d9ce3a..76c9e192ddcc 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -731,7 +731,7 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev, qp_event = 0; srq_event = 0; dev_event = 0; - ocrdma_err("%s() unknown type=0x%x\n", __func__, type); + pr_err("%s() unknown type=0x%x\n", __func__, type); break; } @@ -761,8 +761,8 @@ static void ocrdma_process_acqe(struct ocrdma_dev *dev, void *ae_cqe) if (evt_code == OCRDMA_ASYNC_EVE_CODE) ocrdma_dispatch_ibevent(dev, cqe); else - ocrdma_err("%s(%d) invalid evt code=0x%x\n", - __func__, dev->id, evt_code); + pr_err("%s(%d) invalid evt code=0x%x\n", __func__, + dev->id, evt_code); } static void ocrdma_process_mcqe(struct ocrdma_dev *dev, struct ocrdma_mcqe *cqe) @@ -776,8 +776,8 @@ static void ocrdma_process_mcqe(struct ocrdma_dev *dev, struct ocrdma_mcqe *cqe) dev->mqe_ctx.cmd_done = true; wake_up(&dev->mqe_ctx.cmd_wait); } else - ocrdma_err("%s() cqe for invalid tag0x%x.expected=0x%x\n", - __func__, cqe->tag_lo, dev->mqe_ctx.tag); + pr_err("%s() cqe for invalid tag0x%x.expected=0x%x\n", + __func__, cqe->tag_lo, dev->mqe_ctx.tag); } static int ocrdma_mq_cq_handler(struct ocrdma_dev *dev, u16 cq_id) @@ -796,7 +796,7 @@ static int ocrdma_mq_cq_handler(struct ocrdma_dev *dev, u16 cq_id) else if (cqe->valid_ae_cmpl_cons & OCRDMA_MCQE_CMPL_MASK) ocrdma_process_mcqe(dev, cqe); else - ocrdma_err("%s() cqe->compl is not set.\n", __func__); + pr_err("%s() cqe->compl is not set.\n", __func__); memset(cqe, 0, sizeof(struct ocrdma_mcqe)); ocrdma_mcq_inc_tail(dev); } @@ -855,7 +855,7 @@ static void ocrdma_qp_cq_handler(struct ocrdma_dev *dev, u16 cq_idx) cq = dev->cq_tbl[cq_idx]; if (cq == NULL) { - ocrdma_err("%s%d invalid id=0x%x\n", __func__, dev->id, cq_idx); + pr_err("%s%d invalid id=0x%x\n", __func__, dev->id, cq_idx); return; } spin_lock_irqsave(&cq->cq_lock, flags); @@ -957,7 +957,7 @@ static int ocrdma_mbx_cmd(struct ocrdma_dev *dev, struct ocrdma_mqe *mqe) rsp = ocrdma_get_mqe_rsp(dev); ocrdma_copy_le32_to_cpu(mqe, rsp, (sizeof(*mqe))); if (cqe_status || ext_status) { - ocrdma_err + pr_err ("%s() opcode=0x%x, cqe_status=0x%x, ext_status=0x%x\n", __func__, (rsp->u.rsp.subsys_op & OCRDMA_MBX_RSP_OPCODE_MASK) >> @@ -1339,8 +1339,8 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq, if (dpp_cq) return -EINVAL; if (entries > dev->attr.max_cqe) { - ocrdma_err("%s(%d) max_cqe=0x%x, requester_cqe=0x%x\n", - __func__, dev->id, dev->attr.max_cqe, entries); + pr_err("%s(%d) max_cqe=0x%x, requester_cqe=0x%x\n", + __func__, dev->id, dev->attr.max_cqe, entries); return -EINVAL; } if (dpp_cq && (dev->nic_info.dev_family != OCRDMA_GEN2_FAMILY)) @@ -1607,7 +1607,7 @@ int ocrdma_reg_mr(struct ocrdma_dev *dev, status = ocrdma_mbx_reg_mr(dev, hwmr, pdid, cur_pbl_cnt, hwmr->pbe_size, last); if (status) { - ocrdma_err("%s() status=%d\n", __func__, status); + pr_err("%s() status=%d\n", __func__, status); return status; } /* if there is no more pbls to register then exit. */ @@ -1630,7 +1630,7 @@ int ocrdma_reg_mr(struct ocrdma_dev *dev, break; } if (status) - ocrdma_err("%s() err. status=%d\n", __func__, status); + pr_err("%s() err. status=%d\n", __func__, status); return status; } @@ -1827,8 +1827,8 @@ static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd, status = ocrdma_build_q_conf(&max_wqe_allocated, dev->attr.wqe_size, &hw_pages, &hw_page_size); if (status) { - ocrdma_err("%s() req. max_send_wr=0x%x\n", __func__, - max_wqe_allocated); + pr_err("%s() req. max_send_wr=0x%x\n", __func__, + max_wqe_allocated); return -EINVAL; } qp->sq.max_cnt = max_wqe_allocated; @@ -1877,8 +1877,8 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd, status = ocrdma_build_q_conf(&max_rqe_allocated, dev->attr.rqe_size, &hw_pages, &hw_page_size); if (status) { - ocrdma_err("%s() req. max_recv_wr=0x%x\n", __func__, - attrs->cap.max_recv_wr + 1); + pr_err("%s() req. max_recv_wr=0x%x\n", __func__, + attrs->cap.max_recv_wr + 1); return status; } qp->rq.max_cnt = max_rqe_allocated; @@ -2073,10 +2073,10 @@ int ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs, if (qp->rq.va) dma_free_coherent(&pdev->dev, qp->rq.len, qp->rq.va, qp->rq.pa); rq_err: - ocrdma_err("%s(%d) rq_err\n", __func__, dev->id); + pr_err("%s(%d) rq_err\n", __func__, dev->id); dma_free_coherent(&pdev->dev, qp->sq.len, qp->sq.va, qp->sq.pa); sq_err: - ocrdma_err("%s(%d) sq_err\n", __func__, dev->id); + pr_err("%s(%d) sq_err\n", __func__, dev->id); kfree(cmd); return status; } @@ -2113,7 +2113,7 @@ int ocrdma_resolve_dgid(struct ocrdma_dev *dev, union ib_gid *dgid, else if (rdma_link_local_addr(&in6)) rdma_get_ll_mac(&in6, mac_addr); else { - ocrdma_err("%s() fail to resolve mac_addr.\n", __func__); + pr_err("%s() fail to resolve mac_addr.\n", __func__); return -EINVAL; } return 0; @@ -2348,8 +2348,8 @@ int ocrdma_mbx_create_srq(struct ocrdma_srq *srq, dev->attr.rqe_size, &hw_pages, &hw_page_size); if (status) { - ocrdma_err("%s() req. max_wr=0x%x\n", __func__, - srq_attr->attr.max_wr); + pr_err("%s() req. max_wr=0x%x\n", __func__, + srq_attr->attr.max_wr); status = -EINVAL; goto ret; } @@ -2600,7 +2600,7 @@ int ocrdma_init_hw(struct ocrdma_dev *dev) ocrdma_destroy_qp_eqs(dev); qpeq_err: ocrdma_destroy_eq(dev, &dev->meq); - ocrdma_err("%s() status=%d\n", __func__, status); + pr_err("%s() status=%d\n", __func__, status); return status; } diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 48928c8e7774..ded416f1adea 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -378,7 +378,7 @@ static int ocrdma_alloc_resources(struct ocrdma_dev *dev) spin_lock_init(&dev->flush_q_lock); return 0; alloc_err: - ocrdma_err("%s(%d) error.\n", __func__, dev->id); + pr_err("%s(%d) error.\n", __func__, dev->id); return -ENOMEM; } @@ -396,7 +396,7 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info) dev = (struct ocrdma_dev *)ib_alloc_device(sizeof(struct ocrdma_dev)); if (!dev) { - ocrdma_err("Unable to allocate ib device\n"); + pr_err("Unable to allocate ib device\n"); return NULL; } dev->mbx_cmd = kzalloc(sizeof(struct ocrdma_mqe_emb_cmd), GFP_KERNEL); @@ -437,7 +437,7 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info) idr_err: kfree(dev->mbx_cmd); ib_dealloc_device(&dev->ibdev); - ocrdma_err("%s() leaving. ret=%d\n", __func__, status); + pr_err("%s() leaving. ret=%d\n", __func__, status); return NULL; } diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 38c145b28f5c..882a8198d820 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -114,8 +114,8 @@ int ocrdma_query_port(struct ib_device *ibdev, dev = get_ocrdma_dev(ibdev); if (port > 1) { - ocrdma_err("%s(%d) invalid_port=0x%x\n", __func__, - dev->id, port); + pr_err("%s(%d) invalid_port=0x%x\n", __func__, + dev->id, port); return -EINVAL; } netdev = dev->nic_info.netdev; @@ -155,8 +155,7 @@ int ocrdma_modify_port(struct ib_device *ibdev, u8 port, int mask, dev = get_ocrdma_dev(ibdev); if (port > 1) { - ocrdma_err("%s(%d) invalid_port=0x%x\n", __func__, - dev->id, port); + pr_err("%s(%d) invalid_port=0x%x\n", __func__, dev->id, port); return -EINVAL; } return 0; @@ -442,8 +441,8 @@ static struct ocrdma_mr *ocrdma_alloc_lkey(struct ib_pd *ibpd, struct ocrdma_dev *dev = pd->dev; if (acc & IB_ACCESS_REMOTE_WRITE && !(acc & IB_ACCESS_LOCAL_WRITE)) { - ocrdma_err("%s(%d) leaving err, invalid access rights\n", - __func__, dev->id); + pr_err("%s(%d) leaving err, invalid access rights\n", + __func__, dev->id); return ERR_PTR(-EINVAL); } @@ -703,8 +702,8 @@ static int ocrdma_copy_cq_uresp(struct ocrdma_cq *cq, struct ib_udata *udata, uresp.phase_change = cq->phase_change ? 1 : 0; status = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); if (status) { - ocrdma_err("%s(%d) copy error cqid=0x%x.\n", - __func__, cq->dev->id, cq->id); + pr_err("%s(%d) copy error cqid=0x%x.\n", + __func__, cq->dev->id, cq->id); goto err; } uctx = get_ocrdma_ucontext(ib_ctx); @@ -822,57 +821,56 @@ static int ocrdma_check_qp_params(struct ib_pd *ibpd, struct ocrdma_dev *dev, if (attrs->qp_type != IB_QPT_GSI && attrs->qp_type != IB_QPT_RC && attrs->qp_type != IB_QPT_UD) { - ocrdma_err("%s(%d) unsupported qp type=0x%x requested\n", - __func__, dev->id, attrs->qp_type); + pr_err("%s(%d) unsupported qp type=0x%x requested\n", + __func__, dev->id, attrs->qp_type); return -EINVAL; } if (attrs->cap.max_send_wr > dev->attr.max_wqe) { - ocrdma_err("%s(%d) unsupported send_wr=0x%x requested\n", - __func__, dev->id, attrs->cap.max_send_wr); - ocrdma_err("%s(%d) supported send_wr=0x%x\n", - __func__, dev->id, dev->attr.max_wqe); + pr_err("%s(%d) unsupported send_wr=0x%x requested\n", + __func__, dev->id, attrs->cap.max_send_wr); + pr_err("%s(%d) supported send_wr=0x%x\n", + __func__, dev->id, dev->attr.max_wqe); return -EINVAL; } if (!attrs->srq && (attrs->cap.max_recv_wr > dev->attr.max_rqe)) { - ocrdma_err("%s(%d) unsupported recv_wr=0x%x requested\n", - __func__, dev->id, attrs->cap.max_recv_wr); - ocrdma_err("%s(%d) supported recv_wr=0x%x\n", - __func__, dev->id, dev->attr.max_rqe); + pr_err("%s(%d) unsupported recv_wr=0x%x requested\n", + __func__, dev->id, attrs->cap.max_recv_wr); + pr_err("%s(%d) supported recv_wr=0x%x\n", + __func__, dev->id, dev->attr.max_rqe); return -EINVAL; } if (attrs->cap.max_inline_data > dev->attr.max_inline_data) { - ocrdma_err("%s(%d) unsupported inline data size=0x%x" - " requested\n", __func__, dev->id, - attrs->cap.max_inline_data); - ocrdma_err("%s(%d) supported inline data size=0x%x\n", - __func__, dev->id, dev->attr.max_inline_data); + pr_err("%s(%d) unsupported inline data size=0x%x requested\n", + __func__, dev->id, attrs->cap.max_inline_data); + pr_err("%s(%d) supported inline data size=0x%x\n", + __func__, dev->id, dev->attr.max_inline_data); return -EINVAL; } if (attrs->cap.max_send_sge > dev->attr.max_send_sge) { - ocrdma_err("%s(%d) unsupported send_sge=0x%x requested\n", - __func__, dev->id, attrs->cap.max_send_sge); - ocrdma_err("%s(%d) supported send_sge=0x%x\n", - __func__, dev->id, dev->attr.max_send_sge); + pr_err("%s(%d) unsupported send_sge=0x%x requested\n", + __func__, dev->id, attrs->cap.max_send_sge); + pr_err("%s(%d) supported send_sge=0x%x\n", + __func__, dev->id, dev->attr.max_send_sge); return -EINVAL; } if (attrs->cap.max_recv_sge > dev->attr.max_recv_sge) { - ocrdma_err("%s(%d) unsupported recv_sge=0x%x requested\n", - __func__, dev->id, attrs->cap.max_recv_sge); - ocrdma_err("%s(%d) supported recv_sge=0x%x\n", - __func__, dev->id, dev->attr.max_recv_sge); + pr_err("%s(%d) unsupported recv_sge=0x%x requested\n", + __func__, dev->id, attrs->cap.max_recv_sge); + pr_err("%s(%d) supported recv_sge=0x%x\n", + __func__, dev->id, dev->attr.max_recv_sge); return -EINVAL; } /* unprivileged user space cannot create special QP */ if (ibpd->uobject && attrs->qp_type == IB_QPT_GSI) { - ocrdma_err + pr_err ("%s(%d) Userspace can't create special QPs of type=0x%x\n", __func__, dev->id, attrs->qp_type); return -EINVAL; } /* allow creating only one GSI type of QP */ if (attrs->qp_type == IB_QPT_GSI && dev->gsi_qp_created) { - ocrdma_err("%s(%d) GSI special QPs already created.\n", - __func__, dev->id); + pr_err("%s(%d) GSI special QPs already created.\n", + __func__, dev->id); return -EINVAL; } /* verify consumer QPs are not trying to use GSI QP's CQ */ @@ -881,8 +879,8 @@ static int ocrdma_check_qp_params(struct ib_pd *ibpd, struct ocrdma_dev *dev, (dev->gsi_sqcq == get_ocrdma_cq(attrs->recv_cq)) || (dev->gsi_rqcq == get_ocrdma_cq(attrs->send_cq)) || (dev->gsi_rqcq == get_ocrdma_cq(attrs->recv_cq))) { - ocrdma_err("%s(%d) Consumer QP cannot use GSI CQs.\n", - __func__, dev->id); + pr_err("%s(%d) Consumer QP cannot use GSI CQs.\n", + __func__, dev->id); return -EINVAL; } } @@ -934,7 +932,7 @@ static int ocrdma_copy_qp_uresp(struct ocrdma_qp *qp, } status = ib_copy_to_udata(udata, &uresp, sizeof(uresp)); if (status) { - ocrdma_err("%s(%d) user copy error.\n", __func__, dev->id); + pr_err("%s(%d) user copy error.\n", __func__, dev->id); goto err; } status = ocrdma_add_mmap(pd->uctx, uresp.sq_page_addr[0], @@ -1088,7 +1086,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd, kfree(qp->wqe_wr_id_tbl); kfree(qp->rqe_wr_id_tbl); kfree(qp); - ocrdma_err("%s(%d) error=%d\n", __func__, dev->id, status); + pr_err("%s(%d) error=%d\n", __func__, dev->id, status); gen_err: return ERR_PTR(status); } @@ -1138,10 +1136,10 @@ int ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, spin_unlock_irqrestore(&qp->q_lock, flags); if (!ib_modify_qp_is_ok(old_qps, new_qps, ibqp->qp_type, attr_mask)) { - ocrdma_err("%s(%d) invalid attribute mask=0x%x specified for " - "qpn=0x%x of type=0x%x old_qps=0x%x, new_qps=0x%x\n", - __func__, dev->id, attr_mask, qp->id, ibqp->qp_type, - old_qps, new_qps); + pr_err("%s(%d) invalid attribute mask=0x%x specified for\n" + "qpn=0x%x of type=0x%x old_qps=0x%x, new_qps=0x%x\n", + __func__, dev->id, attr_mask, qp->id, ibqp->qp_type, + old_qps, new_qps); goto param_err; } @@ -1640,9 +1638,9 @@ static int ocrdma_build_inline_sges(struct ocrdma_qp *qp, { if (wr->send_flags & IB_SEND_INLINE) { if (wr->sg_list[0].length > qp->max_inline_data) { - ocrdma_err("%s() supported_len=0x%x," - " unspported len req=0x%x\n", __func__, - qp->max_inline_data, wr->sg_list[0].length); + pr_err("%s() supported_len=0x%x,\n" + " unspported len req=0x%x\n", __func__, + qp->max_inline_data, wr->sg_list[0].length); return -EINVAL; } memcpy(sge, @@ -2057,8 +2055,8 @@ static void ocrdma_update_wc(struct ocrdma_qp *qp, struct ib_wc *ibwc, break; default: ibwc->status = IB_WC_GENERAL_ERR; - ocrdma_err("%s() invalid opcode received = 0x%x\n", - __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK); + pr_err("%s() invalid opcode received = 0x%x\n", + __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK); break; }; } -- GitLab From f6ddcf71070d01a7bb34818dd3aaf4bdac5386fa Mon Sep 17 00:00:00 2001 From: Naresh Gottumukkala Date: Mon, 10 Jun 2013 04:42:40 +0000 Subject: [PATCH 1524/2900] RDMA/ocrdma: Set bad_wr in error case Fix post_send to set the bad_wr in error case. Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 882a8198d820..06215301a675 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1734,12 +1734,14 @@ int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, spin_lock_irqsave(&qp->q_lock, flags); if (qp->state != OCRDMA_QPS_RTS && qp->state != OCRDMA_QPS_SQD) { spin_unlock_irqrestore(&qp->q_lock, flags); + *bad_wr = wr; return -EINVAL; } while (wr) { if (ocrdma_hwq_free_cnt(&qp->sq) == 0 || wr->num_sge > qp->sq.max_sges) { + *bad_wr = wr; status = -ENOMEM; break; } -- GitLab From df176ea0743fd0fb0514c862797f6bd8c08ab42e Mon Sep 17 00:00:00 2001 From: Naresh Gottumukkala Date: Mon, 10 Jun 2013 04:42:41 +0000 Subject: [PATCH 1525/2900] RDMA/ocrdma: Change macros to inline funtions Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma.h | 43 +++++++++++++++++++-- drivers/infiniband/hw/ocrdma/ocrdma_sli.h | 15 ------- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 +- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 9d82d097e25a..7aa7f0f15f8e 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -290,10 +290,6 @@ struct ocrdma_qp { u8 *ird_q_va; }; -#define OCRDMA_GET_NUM_POSTED_SHIFT_VAL(qp) \ - (((qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) && \ - (qp->id < 64)) ? 24 : 16) - struct ocrdma_hw_mr { struct ocrdma_dev *dev; u32 lkey; @@ -384,4 +380,43 @@ static inline struct ocrdma_srq *get_ocrdma_srq(struct ib_srq *ibsrq) return container_of(ibsrq, struct ocrdma_srq, ibsrq); } + +static inline int ocrdma_get_num_posted_shift(struct ocrdma_qp *qp) +{ + return ((qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY && + qp->id < 64) ? 24 : 16); +} + +static inline int is_cqe_valid(struct ocrdma_cq *cq, struct ocrdma_cqe *cqe) +{ + int cqe_valid; + cqe_valid = le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_VALID; + return ((cqe_valid == cq->phase) ? 1 : 0); +} + +static inline int is_cqe_for_sq(struct ocrdma_cqe *cqe) +{ + return (le32_to_cpu(cqe->flags_status_srcqpn) & + OCRDMA_CQE_QTYPE) ? 0 : 1; +} + +static inline int is_cqe_invalidated(struct ocrdma_cqe *cqe) +{ + return (le32_to_cpu(cqe->flags_status_srcqpn) & + OCRDMA_CQE_INVALIDATE) ? 1 : 0; +} + +static inline int is_cqe_imm(struct ocrdma_cqe *cqe) +{ + return (le32_to_cpu(cqe->flags_status_srcqpn) & + OCRDMA_CQE_IMM) ? 1 : 0; +} + +static inline int is_cqe_wr_imm(struct ocrdma_cqe *cqe) +{ + return (le32_to_cpu(cqe->flags_status_srcqpn) & + OCRDMA_CQE_WRITE_IMM) ? 1 : 0; +} + + #endif diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h index cd0512f1fb5b..36b062da2aea 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h @@ -1534,21 +1534,6 @@ struct ocrdma_cqe { u32 flags_status_srcqpn; /* w3 */ } __packed; -#define is_cqe_valid(cq, cqe) \ - (((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_VALID)\ - == cq->phase) ? 1 : 0) -#define is_cqe_for_sq(cqe) \ - ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_QTYPE) ? 0 : 1) -#define is_cqe_for_rq(cqe) \ - ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_QTYPE) ? 1 : 0) -#define is_cqe_invalidated(cqe) \ - ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_INVALIDATE) ? \ - 1 : 0) -#define is_cqe_imm(cqe) \ - ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_IMM) ? 1 : 0) -#define is_cqe_wr_imm(cqe) \ - ((le32_to_cpu(cqe->flags_status_srcqpn) & OCRDMA_CQE_WRITE_IMM) ? 1 : 0) - struct ocrdma_sge { u32 addr_hi; u32 addr_lo; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 06215301a675..dcfbab177faa 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -1819,7 +1819,7 @@ int ocrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, static void ocrdma_ring_rq_db(struct ocrdma_qp *qp) { - u32 val = qp->rq.dbid | (1 << OCRDMA_GET_NUM_POSTED_SHIFT_VAL(qp)); + u32 val = qp->rq.dbid | (1 << ocrdma_get_num_posted_shift(qp)); iowrite32(val, qp->rq_db); } -- GitLab From 9884bcdca30ae9f29a0d6af4a4577826b00c5d94 Mon Sep 17 00:00:00 2001 From: Naresh Gottumukkala Date: Mon, 10 Jun 2013 04:42:42 +0000 Subject: [PATCH 1526/2900] RDMA/ocrdma: Reorg structures to avoid padding Reorg structures to better packing to avoid cacheline padding. Signed-off-by: Naresh Gottumukkala Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h index 7aa7f0f15f8e..d540180a8e42 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -236,15 +236,16 @@ struct ocrdma_srq { struct ib_srq ibsrq; struct ocrdma_dev *dev; u8 __iomem *db; + struct ocrdma_qp_hwq_info rq; + u64 *rqe_wr_id_tbl; + u32 *idx_bit_fields; + u32 bit_fields_len; + /* provide synchronization to multiple context(s) posting rqe */ spinlock_t q_lock ____cacheline_aligned; - struct ocrdma_qp_hwq_info rq; struct ocrdma_pd *pd; u32 id; - u64 *rqe_wr_id_tbl; - u32 *idx_bit_fields; - u32 bit_fields_len; }; struct ocrdma_qp { @@ -252,8 +253,6 @@ struct ocrdma_qp { struct ocrdma_dev *dev; u8 __iomem *sq_db; - /* provide synchronization to multiple context(s) posting wqe, rqe */ - spinlock_t q_lock ____cacheline_aligned; struct ocrdma_qp_hwq_info sq; struct { uint64_t wrid; @@ -263,6 +262,9 @@ struct ocrdma_qp { uint8_t rsvd[3]; } *wqe_wr_id_tbl; u32 max_inline_data; + + /* provide synchronization to multiple context(s) posting wqe, rqe */ + spinlock_t q_lock ____cacheline_aligned; struct ocrdma_cq *sq_cq; /* list maintained per CQ to flush SQ errors */ struct list_head sq_entry; -- GitLab From 3c00ea82c724fab0b98f15428a804cb45eb9ad38 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 19 May 2013 20:45:15 +0200 Subject: [PATCH 1527/2900] watchdog: Rename confusing state variable We have two very conflicting state variable names in the watchdog: * watchdog_enabled: This one reflects the user interface. It's set to 1 by default and can be overriden with boot options or sysctl/procfs interface. * watchdog_disabled: This is the internal toggle state that tells if watchdog threads, timers and NMI events are currently running or not. This state mostly depends on the user settings. It's a convenient state latch. Now we really need to find clearer names because those are just too confusing to encourage deep review. watchdog_enabled now becomes watchdog_user_enabled to reflect its purpose as an interface. watchdog_disabled becomes watchdog_running to suggest its role as a pure internal state. Signed-off-by: Frederic Weisbecker Cc: Srivatsa S. Bhat Cc: Anish Singh Cc: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Li Zhong Cc: Don Zickus --- include/linux/nmi.h | 2 +- kernel/sysctl.c | 4 ++-- kernel/watchdog.c | 30 +++++++++++++++--------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/linux/nmi.h b/include/linux/nmi.h index db50840e6355..6a45fb583ff1 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -46,7 +46,7 @@ static inline bool trigger_all_cpu_backtrace(void) #ifdef CONFIG_LOCKUP_DETECTOR int hw_nmi_is_cpu_stuck(struct pt_regs *); u64 hw_nmi_get_sample_period(int watchdog_thresh); -extern int watchdog_enabled; +extern int watchdog_user_enabled; extern int watchdog_thresh; struct ctl_table; extern int proc_dowatchdog(struct ctl_table *, int , diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9edcf456e0fc..b0805652c4ff 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -801,7 +801,7 @@ static struct ctl_table kern_table[] = { #if defined(CONFIG_LOCKUP_DETECTOR) { .procname = "watchdog", - .data = &watchdog_enabled, + .data = &watchdog_user_enabled, .maxlen = sizeof (int), .mode = 0644, .proc_handler = proc_dowatchdog, @@ -828,7 +828,7 @@ static struct ctl_table kern_table[] = { }, { .procname = "nmi_watchdog", - .data = &watchdog_enabled, + .data = &watchdog_user_enabled, .maxlen = sizeof (int), .mode = 0644, .proc_handler = proc_dowatchdog, diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 52c9a9b91bdd..51c4f34d258e 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -29,9 +29,9 @@ #include #include -int watchdog_enabled = 1; +int watchdog_user_enabled = 1; int __read_mostly watchdog_thresh = 10; -static int __read_mostly watchdog_disabled = 1; +static int __read_mostly watchdog_running; static u64 __read_mostly sample_period; static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); @@ -63,7 +63,7 @@ static int __init hardlockup_panic_setup(char *str) else if (!strncmp(str, "nopanic", 7)) hardlockup_panic = 0; else if (!strncmp(str, "0", 1)) - watchdog_enabled = 0; + watchdog_user_enabled = 0; return 1; } __setup("nmi_watchdog=", hardlockup_panic_setup); @@ -82,7 +82,7 @@ __setup("softlockup_panic=", softlockup_panic_setup); static int __init nowatchdog_setup(char *str) { - watchdog_enabled = 0; + watchdog_user_enabled = 0; return 1; } __setup("nowatchdog", nowatchdog_setup); @@ -90,7 +90,7 @@ __setup("nowatchdog", nowatchdog_setup); /* deprecated */ static int __init nosoftlockup_setup(char *str) { - watchdog_enabled = 0; + watchdog_user_enabled = 0; return 1; } __setup("nosoftlockup", nosoftlockup_setup); @@ -158,7 +158,7 @@ void touch_all_softlockup_watchdogs(void) #ifdef CONFIG_HARDLOCKUP_DETECTOR void touch_nmi_watchdog(void) { - if (watchdog_enabled) { + if (watchdog_user_enabled) { unsigned cpu; for_each_present_cpu(cpu) { @@ -490,12 +490,12 @@ static int watchdog_enable_all_cpus(void) { int err = 0; - if (watchdog_disabled) { + if (!watchdog_running) { err = smpboot_register_percpu_thread(&watchdog_threads); if (err) pr_err("Failed to create watchdog threads, disabled\n"); else - watchdog_disabled = 0; + watchdog_running = 1; } return err; @@ -506,8 +506,8 @@ static int watchdog_enable_all_cpus(void) #ifdef CONFIG_SYSCTL static void watchdog_disable_all_cpus(void) { - if (!watchdog_disabled) { - watchdog_disabled = 1; + if (watchdog_running) { + watchdog_running = 0; smpboot_unregister_percpu_thread(&watchdog_threads); } } @@ -522,7 +522,7 @@ int proc_dowatchdog(struct ctl_table *table, int write, int err, old_thresh, old_enabled; old_thresh = ACCESS_ONCE(watchdog_thresh); - old_enabled = ACCESS_ONCE(watchdog_enabled); + old_enabled = ACCESS_ONCE(watchdog_user_enabled); err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (err || !write) @@ -531,10 +531,10 @@ int proc_dowatchdog(struct ctl_table *table, int write, set_sample_period(); /* * Watchdog threads shouldn't be enabled if they are - * disabled. The 'watchdog_disabled' variable check in + * disabled. The 'watchdog_running' variable check in * watchdog_*_all_cpus() function takes care of this. */ - if (watchdog_enabled && watchdog_thresh) + if (watchdog_user_enabled && watchdog_thresh) err = watchdog_enable_all_cpus(); else watchdog_disable_all_cpus(); @@ -542,7 +542,7 @@ int proc_dowatchdog(struct ctl_table *table, int write, /* Restore old values on failure */ if (err) { watchdog_thresh = old_thresh; - watchdog_enabled = old_enabled; + watchdog_user_enabled = old_enabled; } return err; @@ -553,6 +553,6 @@ void __init lockup_detector_init(void) { set_sample_period(); - if (watchdog_enabled) + if (watchdog_user_enabled) watchdog_enable_all_cpus(); } -- GitLab From 940be35ac0139530d7554aa2352a8388e3d4adca Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 7 Jun 2013 13:35:42 +0200 Subject: [PATCH 1528/2900] watchdog: Boot-disable by default on full dynticks When the watchdog runs, it prevents the full dynticks CPUs from stopping their tick because the hard lockup detector uses perf events internally, which in turn rely on the periodic tick. Since this is a rather confusing behaviour that is not easy to track down and identify for those who want to test CONFIG_NO_HZ_FULL, let's default disable the watchdog on boot time when full dynticks is enabled. The user can still enable it later on runtime using proc or sysctl. Reported-by: Steven Rostedt Suggested-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Andrew Morton Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Li Zhong Cc: Don Zickus Cc: Srivatsa S. Bhat Cc: Anish Singh --- kernel/watchdog.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 51c4f34d258e..1241d8c91d5e 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -553,6 +553,14 @@ void __init lockup_detector_init(void) { set_sample_period(); +#ifdef CONFIG_NO_HZ_FULL + if (watchdog_user_enabled) { + watchdog_user_enabled = 0; + pr_warning("Disabled lockup detectors by default for full dynticks\n"); + pr_warning("You can reactivate it with 'sysctl -w kernel.watchdog=1'\n"); + } +#endif + if (watchdog_user_enabled) watchdog_enable_all_cpus(); } -- GitLab From 5b8621a68fdcd2baf1d3b413726f913a5254d46a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 8 Jun 2013 13:47:31 +0200 Subject: [PATCH 1529/2900] nohz: Remove obsolete check for full dynticks CPUs to be RCU nocbs Building full dynticks now implies that all CPUs are forced into RCU nocb mode through CONFIG_RCU_NOCB_CPU_ALL. The dynamic check has become useless. Signed-off-by: Frederic Weisbecker Cc: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Andrew Morton Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Li Zhong Cc: Borislav Petkov --- kernel/time/tick-sched.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index d87d22cb9bf2..b15750139260 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -351,16 +351,6 @@ void __init tick_nohz_init(void) } cpu_notifier(tick_nohz_cpu_down_callback, 0); - - /* Make sure full dynticks CPU are also RCU nocbs */ - for_each_cpu(cpu, nohz_full_mask) { - if (!rcu_is_nocb_cpu(cpu)) { - pr_warning("NO_HZ: CPU %d is not RCU nocb: " - "cleared from nohz_full range", cpu); - cpumask_clear_cpu(cpu, nohz_full_mask); - } - } - cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), nohz_full_mask); pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf); } -- GitLab From 68651ff6373421fff7452a0fdeed589801a26b6d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 02:26:34 +0200 Subject: [PATCH 1530/2900] MIPS: Octeon: Fix build error if CONFIG_MTD=n Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 3595affb9772..e3fd50cc709c 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -13,10 +13,11 @@ CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o -obj-y += dma-octeon.o flash_setup.o +obj-y += dma-octeon.o obj-y += octeon-memcpy.o obj-y += executive/ +obj-$(CONFIG_MTD) += flash_setup.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_OCTEON_ILM) += oct_ilm.o -- GitLab From 27f62b9f294b7e2019c94c385abda43a0af6bb8b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 02:45:53 +0200 Subject: [PATCH 1531/2900] RAPIDIO: IDT_GEN2: Fix build error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/rapidio/switches/idt_gen2.o drivers/rapidio/switches/idt_gen2.c: In function ‘idtg2_show_errlog’: drivers/rapidio/switches/idt_gen2.c:379:30: error: ‘PAGE_SIZE’ undeclared (first use in this function) drivers/rapidio/switches/idt_gen2.c:379:30: note: each undeclared identifier is reported only once for each function it appears in Signed-off-by: Ralf Baechle Acked-by: Alexandre Bounine --- drivers/rapidio/switches/idt_gen2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index 809b7a3336ba..5d3b0f014d35 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c @@ -15,6 +15,8 @@ #include #include #include + +#include #include "../rio.h" #define LOCAL_RTE_CONF_DESTID_SEL 0x010070 -- GitLab From d01140df6a32554728ab055f2d82f8028a73d2f5 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Mon, 13 May 2013 15:22:42 -0700 Subject: [PATCH 1532/2900] iommu/vt-d: Downgrade the warning if enabling irq remapping fails This triggers on a MacBook Pro. See https://bugzilla.redhat.com/show_bug.cgi?id=948262 for the problem report. Signed-off-by: Andy Lutomirski Signed-off-by: Joerg Roedel --- drivers/iommu/intel_irq_remapping.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 5b19b2d6ec2d..f71673dbb23d 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -664,8 +664,7 @@ static int __init intel_enable_irq_remapping(void) */ if (x2apic_present) - WARN(1, KERN_WARNING - "Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); + pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); return -1; } -- GitLab From 7cef33471a35c6973ddad2926e9e88c52e9e1c1b Mon Sep 17 00:00:00 2001 From: "Li, Zhen-Hua" Date: Mon, 20 May 2013 15:57:32 +0800 Subject: [PATCH 1533/2900] iommu/vt-d: DMAR reporting table needs at least one DRHD In intel vt-d spec , chapter 8.1 , DMA Remapping Reporting Structure. In the end of the table, it says: Remapping Structures[] - A list of structures. The list will contain one or more DMA Remapping Hardware Unit Definition (DRHD) structures, and zero or more Reserved Memory Region Reporting (RMRR) and Root Port ATS Capability Reporting (ATSR) structures. These structures are described below. So, there should be at least one DRHD structure in DMA Remapping reporting table. If there is no DRHD found, a warning is necessary. Signed-off-by: Li, Zhen-Hua Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index a7967ceb79e6..785675a56a10 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -309,6 +309,7 @@ parse_dmar_table(void) struct acpi_table_dmar *dmar; struct acpi_dmar_header *entry_header; int ret = 0; + int drhd_count = 0; /* * Do it again, earlier dmar_tbl mapping could be mapped with @@ -347,6 +348,7 @@ parse_dmar_table(void) switch (entry_header->type) { case ACPI_DMAR_TYPE_HARDWARE_UNIT: + drhd_count++; ret = dmar_parse_one_drhd(entry_header); break; case ACPI_DMAR_TYPE_RESERVED_MEMORY: @@ -371,6 +373,8 @@ parse_dmar_table(void) entry_header = ((void *)entry_header + entry_header->length); } + if (drhd_count == 0) + pr_warn(FW_BUG "No DRHD structure found in DMAR table\n"); return ret; } -- GitLab From 2abfcfbcf02972f939196dce0ddf8dd470f23907 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 30 May 2013 18:10:38 -0500 Subject: [PATCH 1534/2900] iommu/omap: fix printk formats for dma_addr_t Fixed the following printk format warnings for dma_addr_t for OMAP IOMMU. drivers/iommu/omap-iommu.c: In function 'omap_iommu_iova_to_phys': drivers/iommu/omap-iommu.c:1238:4: warning: format '%lx' expects type 'long unsigned int', but argument 4 has type 'dma_addr_t' drivers/iommu/omap-iommu.c:1245:4: warning: format '%lx' expects type 'long unsigned int', but argument 4 has type 'dma_addr_t' Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index e02e5d71745b..0cc658c21c93 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -1235,14 +1235,16 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain, else if (iopte_is_large(*pte)) ret = omap_iommu_translate(*pte, da, IOLARGE_MASK); else - dev_err(dev, "bogus pte 0x%x, da 0x%lx", *pte, da); + dev_err(dev, "bogus pte 0x%x, da 0x%llx", *pte, + (unsigned long long)da); } else { if (iopgd_is_section(*pgd)) ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK); else if (iopgd_is_super(*pgd)) ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK); else - dev_err(dev, "bogus pgd 0x%x, da 0x%lx", *pgd, da); + dev_err(dev, "bogus pgd 0x%x, da 0x%llx", *pgd, + (unsigned long long)da); } return ret; -- GitLab From b6c2e09f74a1f95aa77b478b40b41538a2ccb8f0 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 30 May 2013 18:10:59 -0500 Subject: [PATCH 1535/2900] iommu/omap: fix checkpatch warnings in omap iommu code This patch fixes the checkpatch warnings in omap iommu code, most of them are related to broken strings. Signed-off-by: Suman Anna Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu.c | 9 ++++----- drivers/iommu/omap-iopgtable.h | 2 +- drivers/iommu/omap-iovmm.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 0cc658c21c93..0ba3766240d5 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -833,16 +833,15 @@ static irqreturn_t iommu_fault_handler(int irq, void *data) iopgd = iopgd_offset(obj, da); if (!iopgd_is_table(*iopgd)) { - dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p " - "*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd); + dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:px%08x\n", + obj->name, errs, da, iopgd, *iopgd); return IRQ_NONE; } iopte = iopte_offset(iopgd, da); - dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x " - "pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd, - iopte, *iopte); + dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x pte:0x%p *pte:0x%08x\n", + obj->name, errs, da, iopgd, *iopgd, iopte, *iopte); return IRQ_NONE; } diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h index cd4ae9e5b0c6..f4003d568a92 100644 --- a/drivers/iommu/omap-iopgtable.h +++ b/drivers/iommu/omap-iopgtable.h @@ -95,4 +95,4 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask) #define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) #define to_iommu(dev) \ - (struct omap_iommu *)platform_get_drvdata(to_platform_device(dev)) + ((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))) diff --git a/drivers/iommu/omap-iovmm.c b/drivers/iommu/omap-iovmm.c index 46d875690739..d14725984153 100644 --- a/drivers/iommu/omap-iovmm.c +++ b/drivers/iommu/omap-iovmm.c @@ -102,8 +102,8 @@ static size_t sgtable_len(const struct sg_table *sgt) } if (i && sg->offset) { - pr_err("%s: sg[%d] offset not allowed in internal " - "entries\n", __func__, i); + pr_err("%s: sg[%d] offset not allowed in internal entries\n", + __func__, i); return 0; } -- GitLab From c14d26905d256565052dce99c35b02470162e679 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 30 May 2013 12:39:18 -0600 Subject: [PATCH 1536/2900] iommu/{vt-d,amd}: Remove multifunction assumption around grouping If a device is multifunction and does not have ACS enabled then we assume that the entire package lacks ACS and use function 0 as the base of the group. The PCIe spec however states that components are permitted to implement ACS on some, none, or all of their applicable functions. It's therefore conceivable that function 0 may be fully independent and support ACS while other functions do not. Instead use the lowest function of the slot that does not have ACS enabled as the base of the group. This may be the current device, which is intentional. So long as we use a consistent algorithm, all the non-ACS functions will be grouped together and ACS functions will get separate groups. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 25 +++++++++++++++++++------ drivers/iommu/intel-iommu.c | 25 +++++++++++++++++++------ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 21d02b0d907c..5a02d0776a66 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -287,14 +287,27 @@ static struct pci_dev *get_isolation_root(struct pci_dev *pdev) /* * If it's a multifunction device that does not support our - * required ACS flags, add to the same group as function 0. + * required ACS flags, add to the same group as lowest numbered + * function that also does not suport the required ACS flags. */ if (dma_pdev->multifunction && - !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) - swap_pci_ref(&dma_pdev, - pci_get_slot(dma_pdev->bus, - PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), - 0))); + !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { + u8 i, slot = PCI_SLOT(dma_pdev->devfn); + + for (i = 0; i < 8; i++) { + struct pci_dev *tmp; + + tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); + if (!tmp) + continue; + + if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { + swap_pci_ref(&dma_pdev, tmp); + break; + } + pci_dev_put(tmp); + } + } /* * Devices on the root bus go through the iommu. If that's not us, diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b4f0e28dfa41..eec0d3e04bf5 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4182,14 +4182,27 @@ static int intel_iommu_add_device(struct device *dev) /* * If it's a multifunction device that does not support our - * required ACS flags, add to the same group as function 0. + * required ACS flags, add to the same group as lowest numbered + * function that also does not suport the required ACS flags. */ if (dma_pdev->multifunction && - !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) - swap_pci_ref(&dma_pdev, - pci_get_slot(dma_pdev->bus, - PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), - 0))); + !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) { + u8 i, slot = PCI_SLOT(dma_pdev->devfn); + + for (i = 0; i < 8; i++) { + struct pci_dev *tmp; + + tmp = pci_get_slot(dma_pdev->bus, PCI_DEVFN(slot, i)); + if (!tmp) + continue; + + if (!pci_acs_enabled(tmp, REQ_ACS_FLAGS)) { + swap_pci_ref(&dma_pdev, tmp); + break; + } + pci_dev_put(tmp); + } + } /* * Devices on the root bus go through the iommu. If that's not us, -- GitLab From bd13969b952491149e641d3dab24fa59b98f82e9 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 17 Jun 2013 19:57:34 -0600 Subject: [PATCH 1537/2900] iommu: Split iommu_unmaps iommu_map splits requests into pages that the iommu driver reports that it can handle. The iommu_unmap path does not do the same. This can cause problems not only from callers that might expect the same behavior as the map path, but even from the failure path of iommu_map, should it fail at a point where it has mapped and needs to unwind a set of pages that the iommu driver cannot handle directly. amd_iommu, for example, will BUG_ON if asked to unmap a non power of 2 size. Fix this by extracting and generalizing the sizing code from the iommu_map path and use it for both map and unmap. Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 63 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index d8f98b14e2fe..4b0b56b0501d 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -754,6 +754,38 @@ int iommu_domain_has_cap(struct iommu_domain *domain, } EXPORT_SYMBOL_GPL(iommu_domain_has_cap); +static size_t iommu_pgsize(struct iommu_domain *domain, + unsigned long addr_merge, size_t size) +{ + unsigned int pgsize_idx; + size_t pgsize; + + /* Max page size that still fits into 'size' */ + pgsize_idx = __fls(size); + + /* need to consider alignment requirements ? */ + if (likely(addr_merge)) { + /* Max page size allowed by address */ + unsigned int align_pgsize_idx = __ffs(addr_merge); + pgsize_idx = min(pgsize_idx, align_pgsize_idx); + } + + /* build a mask of acceptable page sizes */ + pgsize = (1UL << (pgsize_idx + 1)) - 1; + + /* throw away page sizes not supported by the hardware */ + pgsize &= domain->ops->pgsize_bitmap; + + /* make sure we're still sane */ + BUG_ON(!pgsize); + + /* pick the biggest page */ + pgsize_idx = __fls(pgsize); + pgsize = 1UL << pgsize_idx; + + return pgsize; +} + int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { @@ -785,32 +817,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, (unsigned long)paddr, (unsigned long)size); while (size) { - unsigned long pgsize, addr_merge = iova | paddr; - unsigned int pgsize_idx; - - /* Max page size that still fits into 'size' */ - pgsize_idx = __fls(size); - - /* need to consider alignment requirements ? */ - if (likely(addr_merge)) { - /* Max page size allowed by both iova and paddr */ - unsigned int align_pgsize_idx = __ffs(addr_merge); - - pgsize_idx = min(pgsize_idx, align_pgsize_idx); - } - - /* build a mask of acceptable page sizes */ - pgsize = (1UL << (pgsize_idx + 1)) - 1; - - /* throw away page sizes not supported by the hardware */ - pgsize &= domain->ops->pgsize_bitmap; - - /* make sure we're still sane */ - BUG_ON(!pgsize); - - /* pick the biggest page */ - pgsize_idx = __fls(pgsize); - pgsize = 1UL << pgsize_idx; + size_t pgsize = iommu_pgsize(domain, iova | paddr, size); pr_debug("mapping: iova 0x%lx pa 0x%lx pgsize %lu\n", iova, (unsigned long)paddr, pgsize); @@ -863,9 +870,9 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) * or we hit an area that isn't mapped. */ while (unmapped < size) { - size_t left = size - unmapped; + size_t pgsize = iommu_pgsize(domain, iova, size - unmapped); - unmapped_page = domain->ops->unmap(domain, iova, left); + unmapped_page = domain->ops->unmap(domain, iova, pgsize); if (!unmapped_page) break; -- GitLab From 681f130f39e10087475383e6771b9366e26bab0c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 20 Jun 2013 05:52:22 -0700 Subject: [PATCH 1538/2900] netfilter: xt_socket: add XT_SOCKET_NOWILDCARD flag xt_socket module can be a nice replacement to conntrack module in some cases (SYN filtering for example) But it lacks the ability to match the 3rd packet of TCP handshake (ACK coming from the client). Add a XT_SOCKET_NOWILDCARD flag to disable the wildcard mechanism. The wildcard is the legacy socket match behavior, that ignores LISTEN sockets bound to INADDR_ANY (or ipv6 equivalent) iptables -I INPUT -p tcp --syn -j SYN_CHAIN iptables -I INPUT -m socket --nowildcard -j ACCEPT Signed-off-by: Eric Dumazet Cc: Patrick McHardy Cc: Jesper Dangaard Brouer Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/xt_socket.h | 7 +++ net/netfilter/xt_socket.c | 70 +++++++++++++++++++++--- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/include/uapi/linux/netfilter/xt_socket.h b/include/uapi/linux/netfilter/xt_socket.h index 26d7217bd4f1..6315e2ac3474 100644 --- a/include/uapi/linux/netfilter/xt_socket.h +++ b/include/uapi/linux/netfilter/xt_socket.h @@ -5,10 +5,17 @@ enum { XT_SOCKET_TRANSPARENT = 1 << 0, + XT_SOCKET_NOWILDCARD = 1 << 1, }; struct xt_socket_mtinfo1 { __u8 flags; }; +#define XT_SOCKET_FLAGS_V1 XT_SOCKET_TRANSPARENT + +struct xt_socket_mtinfo2 { + __u8 flags; +}; +#define XT_SOCKET_FLAGS_V2 (XT_SOCKET_TRANSPARENT | XT_SOCKET_NOWILDCARD) #endif /* _XT_SOCKET_H */ diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 02704245710e..f8b71911037a 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -163,8 +163,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, bool wildcard; bool transparent = true; - /* Ignore sockets listening on INADDR_ANY */ - wildcard = (sk->sk_state != TCP_TIME_WAIT && + /* Ignore sockets listening on INADDR_ANY, + * unless XT_SOCKET_NOWILDCARD is set + */ + wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && + sk->sk_state != TCP_TIME_WAIT && inet_sk(sk)->inet_rcv_saddr == 0); /* Ignore non-transparent sockets, @@ -197,7 +200,7 @@ socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par) } static bool -socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par) +socket_mt4_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) { return socket_match(skb, par, par->matchinfo); } @@ -259,7 +262,7 @@ extract_icmp6_fields(const struct sk_buff *skb, } static bool -socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) +socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) { struct ipv6hdr *iph = ipv6_hdr(skb); struct udphdr _hdr, *hp = NULL; @@ -302,8 +305,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) bool wildcard; bool transparent = true; - /* Ignore sockets listening on INADDR_ANY */ - wildcard = (sk->sk_state != TCP_TIME_WAIT && + /* Ignore sockets listening on INADDR_ANY + * unless XT_SOCKET_NOWILDCARD is set + */ + wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) && + sk->sk_state != TCP_TIME_WAIT && ipv6_addr_any(&inet6_sk(sk)->rcv_saddr)); /* Ignore non-transparent sockets, @@ -331,6 +337,28 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) } #endif +static int socket_mt_v1_check(const struct xt_mtchk_param *par) +{ + const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; + + if (info->flags & ~XT_SOCKET_FLAGS_V1) { + pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1); + return -EINVAL; + } + return 0; +} + +static int socket_mt_v2_check(const struct xt_mtchk_param *par) +{ + const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo; + + if (info->flags & ~XT_SOCKET_FLAGS_V2) { + pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2); + return -EINVAL; + } + return 0; +} + static struct xt_match socket_mt_reg[] __read_mostly = { { .name = "socket", @@ -345,7 +373,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = { .name = "socket", .revision = 1, .family = NFPROTO_IPV4, - .match = socket_mt4_v1, + .match = socket_mt4_v1_v2, + .checkentry = socket_mt_v1_check, .matchsize = sizeof(struct xt_socket_mtinfo1), .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN), @@ -356,7 +385,32 @@ static struct xt_match socket_mt_reg[] __read_mostly = { .name = "socket", .revision = 1, .family = NFPROTO_IPV6, - .match = socket_mt6_v1, + .match = socket_mt6_v1_v2, + .checkentry = socket_mt_v1_check, + .matchsize = sizeof(struct xt_socket_mtinfo1), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN), + .me = THIS_MODULE, + }, +#endif + { + .name = "socket", + .revision = 2, + .family = NFPROTO_IPV4, + .match = socket_mt4_v1_v2, + .checkentry = socket_mt_v2_check, + .matchsize = sizeof(struct xt_socket_mtinfo1), + .hooks = (1 << NF_INET_PRE_ROUTING) | + (1 << NF_INET_LOCAL_IN), + .me = THIS_MODULE, + }, +#ifdef XT_SOCKET_HAVE_IPV6 + { + .name = "socket", + .revision = 2, + .family = NFPROTO_IPV6, + .match = socket_mt6_v1_v2, + .checkentry = socket_mt_v2_check, .matchsize = sizeof(struct xt_socket_mtinfo1), .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN), -- GitLab From 8d36eb01da5d371feffa280e501377b5c450f5a5 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:07 -0700 Subject: [PATCH 1539/2900] RDMA/cma: Define native IB address Define AF_IB and sockaddr_ib to allow the rdma_cm to use native IB addressing. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- include/linux/socket.h | 2 + include/rdma/ib.h | 89 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 include/rdma/ib.h diff --git a/include/linux/socket.h b/include/linux/socket.h index b10ce4b341ea..230c04bda3e2 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -167,6 +167,7 @@ struct ucred { #define AF_PPPOX 24 /* PPPoX sockets */ #define AF_WANPIPE 25 /* Wanpipe API Sockets */ #define AF_LLC 26 /* Linux LLC */ +#define AF_IB 27 /* Native InfiniBand address */ #define AF_CAN 29 /* Controller Area Network */ #define AF_TIPC 30 /* TIPC sockets */ #define AF_BLUETOOTH 31 /* Bluetooth sockets */ @@ -211,6 +212,7 @@ struct ucred { #define PF_PPPOX AF_PPPOX #define PF_WANPIPE AF_WANPIPE #define PF_LLC AF_LLC +#define PF_IB AF_IB #define PF_CAN AF_CAN #define PF_TIPC AF_TIPC #define PF_BLUETOOTH AF_BLUETOOTH diff --git a/include/rdma/ib.h b/include/rdma/ib.h new file mode 100644 index 000000000000..cf8f9e700e48 --- /dev/null +++ b/include/rdma/ib.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(_RDMA_IB_H) +#define _RDMA_IB_H + +#include + +struct ib_addr { + union { + __u8 uib_addr8[16]; + __be16 uib_addr16[8]; + __be32 uib_addr32[4]; + __be64 uib_addr64[2]; + } ib_u; +#define sib_addr8 ib_u.uib_addr8 +#define sib_addr16 ib_u.uib_addr16 +#define sib_addr32 ib_u.uib_addr32 +#define sib_addr64 ib_u.uib_addr64 +#define sib_raw ib_u.uib_addr8 +#define sib_subnet_prefix ib_u.uib_addr64[0] +#define sib_interface_id ib_u.uib_addr64[1] +}; + +static inline int ib_addr_any(const struct ib_addr *a) +{ + return ((a->sib_addr64[0] | a->sib_addr64[1]) == 0); +} + +static inline int ib_addr_loopback(const struct ib_addr *a) +{ + return ((a->sib_addr32[0] | a->sib_addr32[1] | + a->sib_addr32[2] | (a->sib_addr32[3] ^ htonl(1))) == 0); +} + +static inline void ib_addr_set(struct ib_addr *addr, + __be32 w1, __be32 w2, __be32 w3, __be32 w4) +{ + addr->sib_addr32[0] = w1; + addr->sib_addr32[1] = w2; + addr->sib_addr32[2] = w3; + addr->sib_addr32[3] = w4; +} + +static inline int ib_addr_cmp(const struct ib_addr *a1, const struct ib_addr *a2) +{ + return memcmp(a1, a2, sizeof(struct ib_addr)); +} + +struct sockaddr_ib { + unsigned short int sib_family; /* AF_IB */ + __be16 sib_pkey; + __be32 sib_flowinfo; + struct ib_addr sib_addr; + __be64 sib_sid; + __be64 sib_sid_mask; + __u64 sib_scope_id; +}; + +#endif /* _RDMA_IB_H */ -- GitLab From c8dea2f9f078395ebac7c92aeb919f02ff3fca88 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:08 -0700 Subject: [PATCH 1540/2900] RDMA/cma: Allow enabling reuseaddr in any state The rdma_cm only allows setting reuseaddr if the corresponding rdma_cm_id is in the idle state. Allow setting this value in other states. This brings the behavior more inline with sockets. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 34fbc2f60a09..fde428bd2dad 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2097,7 +2097,7 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse) id_priv = container_of(id, struct rdma_id_private, id); spin_lock_irqsave(&id_priv->lock, flags); - if (id_priv->state == RDMA_CM_IDLE) { + if (reuse || id_priv->state == RDMA_CM_IDLE) { id_priv->reuseaddr = reuse; ret = 0; } else { -- GitLab From 2e2d190c5eb05d5a2615f4092e5fe821710404f9 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:09 -0700 Subject: [PATCH 1541/2900] RDMA/cma: Include AF_IB in loopback and any address checks Enhance checks for loopback and any address to support AF_IB in addition to AF_INET and AF_INT6. This will allow future patches to use AF_IB when binding and resolving addresses. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 40 +++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index fde428bd2dad..22a23a73745e 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -679,26 +680,30 @@ EXPORT_SYMBOL(rdma_init_qp_attr); static inline int cma_zero_addr(struct sockaddr *addr) { - struct in6_addr *ip6; - - if (addr->sa_family == AF_INET) - return ipv4_is_zeronet( - ((struct sockaddr_in *)addr)->sin_addr.s_addr); - else { - ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr; - return (ip6->s6_addr32[0] | ip6->s6_addr32[1] | - ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0; + switch (addr->sa_family) { + case AF_INET: + return ipv4_is_zeronet(((struct sockaddr_in *)addr)->sin_addr.s_addr); + case AF_INET6: + return ipv6_addr_any(&((struct sockaddr_in6 *) addr)->sin6_addr); + case AF_IB: + return ib_addr_any(&((struct sockaddr_ib *) addr)->sib_addr); + default: + return 0; } } static inline int cma_loopback_addr(struct sockaddr *addr) { - if (addr->sa_family == AF_INET) - return ipv4_is_loopback( - ((struct sockaddr_in *) addr)->sin_addr.s_addr); - else - return ipv6_addr_loopback( - &((struct sockaddr_in6 *) addr)->sin6_addr); + switch (addr->sa_family) { + case AF_INET: + return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr); + case AF_INET6: + return ipv6_addr_loopback(&((struct sockaddr_in6 *) addr)->sin6_addr); + case AF_IB: + return ib_addr_loopback(&((struct sockaddr_ib *) addr)->sib_addr); + default: + return 0; + } } static inline int cma_any_addr(struct sockaddr *addr) @@ -715,9 +720,12 @@ static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst) case AF_INET: return ((struct sockaddr_in *) src)->sin_addr.s_addr != ((struct sockaddr_in *) dst)->sin_addr.s_addr; - default: + case AF_INET6: return ipv6_addr_cmp(&((struct sockaddr_in6 *) src)->sin6_addr, &((struct sockaddr_in6 *) dst)->sin6_addr); + default: + return ib_addr_cmp(&((struct sockaddr_ib *) src)->sib_addr, + &((struct sockaddr_ib *) dst)->sib_addr); } } -- GitLab From ef560861c01c301cde3da154eb9c1c2619924c3a Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:10 -0700 Subject: [PATCH 1542/2900] IB/addr: Add AF_IB support to ip_addr_size Add support for AF_IB to ip_addr_size, and rename the function to account for the change. Give the compiler more control over whether the call should be inline or not by moving the definition into the .c file, removing the static inline, and exporting it. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 20 ++++++++++++++++++-- drivers/infiniband/core/cma.c | 12 ++++++------ include/rdma/ib_addr.h | 6 +----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index eaec8d7a3b73..e90f2b2eabd7 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -45,6 +45,7 @@ #include #include #include +#include MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("IB Address Translation"); @@ -70,6 +71,21 @@ static LIST_HEAD(req_list); static DECLARE_DELAYED_WORK(work, process_req); static struct workqueue_struct *addr_wq; +int rdma_addr_size(struct sockaddr *addr) +{ + switch (addr->sa_family) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + case AF_IB: + return sizeof(struct sockaddr_ib); + default: + return 0; + } +} +EXPORT_SYMBOL(rdma_addr_size); + void rdma_addr_register_client(struct rdma_addr_client *client) { atomic_set(&client->refcount, 1); @@ -369,12 +385,12 @@ int rdma_resolve_ip(struct rdma_addr_client *client, goto err; } - memcpy(src_in, src_addr, ip_addr_size(src_addr)); + memcpy(src_in, src_addr, rdma_addr_size(src_addr)); } else { src_in->sa_family = dst_addr->sa_family; } - memcpy(dst_in, dst_addr, ip_addr_size(dst_addr)); + memcpy(dst_in, dst_addr, rdma_addr_size(dst_addr)); req->addr = addr; req->callback = callback; req->context = context; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 22a23a73745e..2b1041c5844c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1584,7 +1584,7 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, dev_id_priv->state = RDMA_CM_ADDR_BOUND; memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr, - ip_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr)); + rdma_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr)); cma_attach_to_dev(dev_id_priv, cma_dev); list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); @@ -1989,7 +1989,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, event.status = status; } else { memcpy(&id_priv->id.route.addr.src_addr, src_addr, - ip_addr_size(src_addr)); + rdma_addr_size(src_addr)); event.event = RDMA_CM_EVENT_ADDR_RESOLVED; } @@ -2079,7 +2079,7 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return -EINVAL; atomic_inc(&id_priv->refcount); - memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr)); + memcpy(&id->route.addr.dst_addr, dst_addr, rdma_addr_size(dst_addr)); if (cma_any_addr(dst_addr)) ret = cma_resolve_loopback(id_priv); else @@ -2399,7 +2399,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) goto err1; } - memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); + memcpy(&id->route.addr.src_addr, addr, rdma_addr_size(addr)); if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) { if (addr->sa_family == AF_INET) id_priv->afonly = 1; @@ -3178,7 +3178,7 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr, if (!mc) return -ENOMEM; - memcpy(&mc->addr, addr, ip_addr_size(addr)); + memcpy(&mc->addr, addr, rdma_addr_size(addr)); mc->context = context; mc->id_priv = id_priv; @@ -3223,7 +3223,7 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) id_priv = container_of(id, struct rdma_id_private, id); spin_lock_irq(&id_priv->lock); list_for_each_entry(mc, &id_priv->mc_list, list) { - if (!memcmp(&mc->addr, addr, ip_addr_size(addr))) { + if (!memcmp(&mc->addr, addr, rdma_addr_size(addr))) { list_del(&mc->list); spin_unlock_irq(&id_priv->lock); diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 99965395c5f3..f3ac0f2c4c66 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -102,11 +102,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr); int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, const unsigned char *dst_dev_addr); -static inline int ip_addr_size(struct sockaddr *addr) -{ - return addr->sa_family == AF_INET6 ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); -} +int rdma_addr_size(struct sockaddr *addr); static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr) { -- GitLab From 58afdcb7382234ebd780e43b17edde92a5853cca Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:11 -0700 Subject: [PATCH 1543/2900] RDMA/cma: Update port reservation to support AF_IB The AF_IB uses a 64-bit service id (SID), which the user can control through the use of a mask. The rdma_cm will assign values to the unmasked portions of the SID based on the selected port space and port number. Because the IB spec divides the SID range into several regions, a SID/mask combination may fall into one of the existing port space ranges as defined by the RDMA CM IP Annex. Map the AF_IB SID to the correct RDMA port space. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 107 +++++++++++++++++++++++++++------- include/rdma/rdma_cm.h | 5 ++ 2 files changed, 91 insertions(+), 21 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 2b1041c5844c..8465c6adaddb 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -729,12 +729,22 @@ static int cma_addr_cmp(struct sockaddr *src, struct sockaddr *dst) } } -static inline __be16 cma_port(struct sockaddr *addr) +static __be16 cma_port(struct sockaddr *addr) { - if (addr->sa_family == AF_INET) + struct sockaddr_ib *sib; + + switch (addr->sa_family) { + case AF_INET: return ((struct sockaddr_in *) addr)->sin_port; - else + case AF_INET6: return ((struct sockaddr_in6 *) addr)->sin6_port; + case AF_IB: + sib = (struct sockaddr_ib *) addr; + return htons((u16) (be64_to_cpu(sib->sib_sid) & + be64_to_cpu(sib->sib_sid_mask))); + default: + return 0; + } } static inline int cma_any_port(struct sockaddr *addr) @@ -2139,10 +2149,29 @@ EXPORT_SYMBOL(rdma_set_afonly); static void cma_bind_port(struct rdma_bind_list *bind_list, struct rdma_id_private *id_priv) { - struct sockaddr_in *sin; + struct sockaddr *addr; + struct sockaddr_ib *sib; + u64 sid, mask; + __be16 port; - sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; - sin->sin_port = htons(bind_list->port); + addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; + port = htons(bind_list->port); + + switch (addr->sa_family) { + case AF_INET: + ((struct sockaddr_in *) addr)->sin_port = port; + break; + case AF_INET6: + ((struct sockaddr_in6 *) addr)->sin6_port = port; + break; + case AF_IB: + sib = (struct sockaddr_ib *) addr; + sid = be64_to_cpu(sib->sib_sid); + mask = be64_to_cpu(sib->sib_sid_mask); + sib->sib_sid = cpu_to_be64((sid & mask) | (u64) ntohs(port)); + sib->sib_sid_mask = cpu_to_be64(~0ULL); + break; + } id_priv->bind_list = bind_list; hlist_add_head(&id_priv->node, &bind_list->owners); } @@ -2269,31 +2298,67 @@ static int cma_bind_listen(struct rdma_id_private *id_priv) return ret; } -static int cma_get_port(struct rdma_id_private *id_priv) +static struct idr *cma_select_inet_ps(struct rdma_id_private *id_priv) { - struct idr *ps; - int ret; - switch (id_priv->id.ps) { case RDMA_PS_SDP: - ps = &sdp_ps; - break; + return &sdp_ps; case RDMA_PS_TCP: - ps = &tcp_ps; - break; + return &tcp_ps; case RDMA_PS_UDP: - ps = &udp_ps; - break; + return &udp_ps; case RDMA_PS_IPOIB: - ps = &ipoib_ps; - break; + return &ipoib_ps; case RDMA_PS_IB: - ps = &ib_ps; - break; + return &ib_ps; default: - return -EPROTONOSUPPORT; + return NULL; + } +} + +static struct idr *cma_select_ib_ps(struct rdma_id_private *id_priv) +{ + struct idr *ps = NULL; + struct sockaddr_ib *sib; + u64 sid_ps, mask, sid; + + sib = (struct sockaddr_ib *) &id_priv->id.route.addr.src_addr; + mask = be64_to_cpu(sib->sib_sid_mask) & RDMA_IB_IP_PS_MASK; + sid = be64_to_cpu(sib->sib_sid) & mask; + + if ((id_priv->id.ps == RDMA_PS_IB) && (sid == (RDMA_IB_IP_PS_IB & mask))) { + sid_ps = RDMA_IB_IP_PS_IB; + ps = &ib_ps; + } else if (((id_priv->id.ps == RDMA_PS_IB) || (id_priv->id.ps == RDMA_PS_TCP)) && + (sid == (RDMA_IB_IP_PS_TCP & mask))) { + sid_ps = RDMA_IB_IP_PS_TCP; + ps = &tcp_ps; + } else if (((id_priv->id.ps == RDMA_PS_IB) || (id_priv->id.ps == RDMA_PS_UDP)) && + (sid == (RDMA_IB_IP_PS_UDP & mask))) { + sid_ps = RDMA_IB_IP_PS_UDP; + ps = &udp_ps; } + if (ps) { + sib->sib_sid = cpu_to_be64(sid_ps | ntohs(cma_port((struct sockaddr *) sib))); + sib->sib_sid_mask = cpu_to_be64(RDMA_IB_IP_PS_MASK | + be64_to_cpu(sib->sib_sid_mask)); + } + return ps; +} + +static int cma_get_port(struct rdma_id_private *id_priv) +{ + struct idr *ps; + int ret; + + if (id_priv->id.route.addr.src_addr.ss_family != AF_IB) + ps = cma_select_inet_ps(id_priv); + else + ps = cma_select_ib_ps(id_priv); + if (!ps) + return -EPROTONOSUPPORT; + mutex_lock(&lock); if (cma_any_port((struct sockaddr *) &id_priv->id.route.addr.src_addr)) ret = cma_alloc_any_port(ps, id_priv); diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index ad3a3142383a..1e6c3c7af898 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -70,6 +70,11 @@ enum rdma_port_space { RDMA_PS_UDP = 0x0111, }; +#define RDMA_IB_IP_PS_MASK 0xFFFFFFFFFFFF0000ULL +#define RDMA_IB_IP_PS_TCP 0x0000000001060000ULL +#define RDMA_IB_IP_PS_UDP 0x0000000001110000ULL +#define RDMA_IB_IP_PS_IB 0x00000000013F0000ULL + struct rdma_addr { struct sockaddr_storage src_addr; struct sockaddr_storage dst_addr; -- GitLab From 680f920a2e24725e694d9958a08226384750217b Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:12 -0700 Subject: [PATCH 1544/2900] RDMA/cma: Allow user to specify AF_IB when binding Modify rdma_bind_addr to allow the user to specify AF_IB when binding to a device. AF_IB indicates that the user is not mapping an IP address to the native IB addressing. (The mapping may have already been done, or is not needed) Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 8465c6adaddb..1e9f3115ee91 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -359,6 +359,27 @@ static int find_gid_port(struct ib_device *device, union ib_gid *gid, u8 port_nu return -EADDRNOTAVAIL; } +static void cma_translate_ib(struct sockaddr_ib *sib, struct rdma_dev_addr *dev_addr) +{ + dev_addr->dev_type = ARPHRD_INFINIBAND; + rdma_addr_set_sgid(dev_addr, (union ib_gid *) &sib->sib_addr); + ib_addr_set_pkey(dev_addr, ntohs(sib->sib_pkey)); +} + +static int cma_translate_addr(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) +{ + int ret; + + if (addr->sa_family != AF_IB) { + ret = rdma_translate_ip(addr, dev_addr); + } else { + cma_translate_ib((struct sockaddr_ib *) addr, dev_addr); + ret = 0; + } + + return ret; +} + static int cma_acquire_dev(struct rdma_id_private *id_priv) { struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; @@ -1136,8 +1157,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); } else { - ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr, - &rt->addr.dev_addr); + ret = cma_translate_addr((struct sockaddr *) &rt->addr.src_addr, + &rt->addr.dev_addr); if (ret) goto err; } @@ -1176,8 +1197,8 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, ip_ver, port, src, dst); if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { - ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, - &id->route.addr.dev_addr); + ret = cma_translate_addr((struct sockaddr *) &id->route.addr.src_addr, + &id->route.addr.dev_addr); if (ret) goto err; } @@ -2443,7 +2464,8 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) struct rdma_id_private *id_priv; int ret; - if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6) + if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6 && + addr->sa_family != AF_IB) return -EAFNOSUPPORT; id_priv = container_of(id, struct rdma_id_private, id); @@ -2455,7 +2477,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) goto err1; if (!cma_any_addr(addr)) { - ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); + ret = cma_translate_addr(addr, &id->route.addr.dev_addr); if (ret) goto err1; -- GitLab From 6a3e362d3ce60d6a9f634572486c2c21a4ccfe69 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:13 -0700 Subject: [PATCH 1545/2900] RDMA/cma: Do not modify sa_family when setting loopback address cma_resolve_loopback is called after an rdma_cm_id has been bound to a specific sa_family and port. Once the source sa_family for the id has been set, do not modify it. Only the actual IP address portion of the source address needs to be set. As part of this fix, we can simplify setting the source address by moving the loopback address assignment from cma_resolve_loopback to cma_bind_loopback. cma_bind_loopback is only invoked when the source address is the loopback address. Finally, add loopback support for AF_IB as part of the change. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 1e9f3115ee91..316ddc38aa13 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1952,6 +1952,23 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) } EXPORT_SYMBOL(rdma_resolve_route); +static void cma_set_loopback(struct sockaddr *addr) +{ + switch (addr->sa_family) { + case AF_INET: + ((struct sockaddr_in *) addr)->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + break; + case AF_INET6: + ipv6_addr_set(&((struct sockaddr_in6 *) addr)->sin6_addr, + 0, 0, 0, htonl(1)); + break; + default: + ib_addr_set(&((struct sockaddr_ib *) addr)->sib_addr, + 0, 0, 0, htonl(1)); + break; + } +} + static int cma_bind_loopback(struct rdma_id_private *id_priv) { struct cma_device *cma_dev; @@ -1992,6 +2009,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); id_priv->id.port_num = p; cma_attach_to_dev(id_priv, cma_dev); + cma_set_loopback((struct sockaddr *) &id_priv->id.route.addr.src_addr); out: mutex_unlock(&lock); return ret; @@ -2039,7 +2057,6 @@ static void addr_handler(int status, struct sockaddr *src_addr, static int cma_resolve_loopback(struct rdma_id_private *id_priv) { struct cma_work *work; - struct sockaddr *src, *dst; union ib_gid gid; int ret; @@ -2056,18 +2073,6 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); - src = (struct sockaddr *) &id_priv->id.route.addr.src_addr; - if (cma_zero_addr(src)) { - dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr; - if ((src->sa_family = dst->sa_family) == AF_INET) { - ((struct sockaddr_in *)src)->sin_addr = - ((struct sockaddr_in *)dst)->sin_addr; - } else { - ((struct sockaddr_in6 *)src)->sin6_addr = - ((struct sockaddr_in6 *)dst)->sin6_addr; - } - } - work->id = id_priv; INIT_WORK(&work->work, cma_work_handler); work->old_state = RDMA_CM_ADDR_QUERY; -- GitLab From f4753834b5d06cae9a1d5453c96760571876a014 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:14 -0700 Subject: [PATCH 1546/2900] RDMA/cma: Add helper functions to return id address information Provide inline helpers to extract source and destination address data from the rdma_cm_id. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 138 +++++++++++++++++----------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 316ddc38aa13..90694530757a 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -311,6 +311,21 @@ static void cma_release_dev(struct rdma_id_private *id_priv) mutex_unlock(&lock); } +static inline struct sockaddr *cma_src_addr(struct rdma_id_private *id_priv) +{ + return (struct sockaddr *) &id_priv->id.route.addr.src_addr; +} + +static inline struct sockaddr *cma_dst_addr(struct rdma_id_private *id_priv) +{ + return (struct sockaddr *) &id_priv->id.route.addr.dst_addr; +} + +static inline unsigned short cma_family(struct rdma_id_private *id_priv) +{ + return id_priv->id.route.addr.src_addr.ss_family; +} + static int cma_set_qkey(struct rdma_id_private *id_priv) { struct ib_sa_mcmember_rec rec; @@ -900,8 +915,7 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv, cma_cancel_route(id_priv); break; case RDMA_CM_LISTEN: - if (cma_any_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr) - && !id_priv->cma_dev) + if (cma_any_addr(cma_src_addr(id_priv)) && !id_priv->cma_dev) cma_cancel_listens(id_priv); break; default: @@ -1138,6 +1152,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, if (IS_ERR(id)) return NULL; + id_priv = container_of(id, struct rdma_id_private, id); cma_save_net_info(&id->route.addr, &listen_id->route.addr, ip_ver, port, src, dst); @@ -1152,19 +1167,17 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, if (rt->num_paths == 2) rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; - if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) { + if (cma_any_addr(cma_src_addr(id_priv))) { rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND; rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); } else { - ret = cma_translate_addr((struct sockaddr *) &rt->addr.src_addr, - &rt->addr.dev_addr); + ret = cma_translate_addr(cma_src_addr(id_priv), &rt->addr.dev_addr); if (ret) goto err; } rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); - id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = RDMA_CM_CONNECT; return id_priv; @@ -1188,7 +1201,7 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, if (IS_ERR(id)) return NULL; - + id_priv = container_of(id, struct rdma_id_private, id); if (cma_get_net_info(ib_event->private_data, listen_id->ps, &ip_ver, &port, &src, &dst)) goto err; @@ -1197,13 +1210,11 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, ip_ver, port, src, dst); if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { - ret = cma_translate_addr((struct sockaddr *) &id->route.addr.src_addr, - &id->route.addr.dev_addr); + ret = cma_translate_addr(cma_src_addr(id_priv), &id->route.addr.dev_addr); if (ret) goto err; } - id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = RDMA_CM_CONNECT; return id_priv; err: @@ -1386,9 +1397,9 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) event.event = RDMA_CM_EVENT_DISCONNECTED; break; case IW_CM_EVENT_CONNECT_REPLY: - sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + sin = (struct sockaddr_in *) cma_src_addr(id_priv); *sin = iw_event->local_addr; - sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr; + sin = (struct sockaddr_in *) cma_dst_addr(id_priv); *sin = iw_event->remote_addr; switch (iw_event->status) { case 0: @@ -1486,9 +1497,9 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, cm_id->context = conn_id; cm_id->cm_handler = cma_iw_handler; - sin = (struct sockaddr_in *) &new_cm_id->route.addr.src_addr; + sin = (struct sockaddr_in *) cma_src_addr(conn_id); *sin = iw_event->local_addr; - sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr; + sin = (struct sockaddr_in *) cma_dst_addr(conn_id); *sin = iw_event->remote_addr; ret = ib_query_device(conn_id->id.device, &attr); @@ -1545,7 +1556,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv) id_priv->cm_id.ib = id; - addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; + addr = cma_src_addr(id_priv); svc_id = cma_get_service_id(id_priv->id.ps, addr); if (cma_any_addr(addr) && !id_priv->afonly) ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); @@ -1576,7 +1587,7 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog) id_priv->cm_id.iw = id; - sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + sin = (struct sockaddr_in *) cma_src_addr(id_priv); id_priv->cm_id.iw->local_addr = *sin; ret = iw_cm_listen(id_priv->cm_id.iw, backlog); @@ -1614,8 +1625,8 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, dev_id_priv = container_of(id, struct rdma_id_private, id); dev_id_priv->state = RDMA_CM_ADDR_BOUND; - memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr, - rdma_addr_size((struct sockaddr *) &id_priv->id.route.addr.src_addr)); + memcpy(cma_src_addr(dev_id_priv), cma_src_addr(id_priv), + rdma_addr_size(cma_src_addr(id_priv))); cma_attach_to_dev(dev_id_priv, cma_dev); list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); @@ -1673,29 +1684,28 @@ static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec, static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, struct cma_work *work) { - struct rdma_addr *addr = &id_priv->id.route.addr; + struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr; struct ib_sa_path_rec path_rec; ib_sa_comp_mask comp_mask; struct sockaddr_in6 *sin6; memset(&path_rec, 0, sizeof path_rec); - rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); - rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); - path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr)); + rdma_addr_get_sgid(dev_addr, &path_rec.sgid); + rdma_addr_get_dgid(dev_addr, &path_rec.dgid); + path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); path_rec.numb_path = 1; path_rec.reversible = 1; - path_rec.service_id = cma_get_service_id(id_priv->id.ps, - (struct sockaddr *) &addr->dst_addr); + path_rec.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH | IB_SA_PATH_REC_REVERSIBLE | IB_SA_PATH_REC_SERVICE_ID; - if (addr->src_addr.ss_family == AF_INET) { + if (cma_family(id_priv) == AF_INET) { path_rec.qos_class = cpu_to_be16((u16) id_priv->tos); comp_mask |= IB_SA_PATH_REC_QOS_CLASS; } else { - sin6 = (struct sockaddr_in6 *) &addr->src_addr; + sin6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); path_rec.traffic_class = (u8) (be32_to_cpu(sin6->sin6_flowinfo) >> 20); comp_mask |= IB_SA_PATH_REC_TRAFFIC_CLASS; } @@ -2009,7 +2019,7 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); id_priv->id.port_num = p; cma_attach_to_dev(id_priv, cma_dev); - cma_set_loopback((struct sockaddr *) &id_priv->id.route.addr.src_addr); + cma_set_loopback(cma_src_addr(id_priv)); out: mutex_unlock(&lock); return ret; @@ -2037,8 +2047,7 @@ static void addr_handler(int status, struct sockaddr *src_addr, event.event = RDMA_CM_EVENT_ADDR_ERROR; event.status = status; } else { - memcpy(&id_priv->id.route.addr.src_addr, src_addr, - rdma_addr_size(src_addr)); + memcpy(cma_src_addr(id_priv), src_addr, rdma_addr_size(src_addr)); event.event = RDMA_CM_EVENT_ADDR_RESOLVED; } @@ -2115,11 +2124,11 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return -EINVAL; atomic_inc(&id_priv->refcount); - memcpy(&id->route.addr.dst_addr, dst_addr, rdma_addr_size(dst_addr)); + memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); if (cma_any_addr(dst_addr)) ret = cma_resolve_loopback(id_priv); else - ret = rdma_resolve_ip(&addr_client, (struct sockaddr *) &id->route.addr.src_addr, + ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv), dst_addr, &id->route.addr.dev_addr, timeout_ms, addr_handler, id_priv); if (ret) @@ -2180,7 +2189,7 @@ static void cma_bind_port(struct rdma_bind_list *bind_list, u64 sid, mask; __be16 port; - addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; + addr = cma_src_addr(id_priv); port = htons(bind_list->port); switch (addr->sa_family) { @@ -2268,7 +2277,7 @@ static int cma_check_port(struct rdma_bind_list *bind_list, struct rdma_id_private *cur_id; struct sockaddr *addr, *cur_addr; - addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; + addr = cma_src_addr(id_priv); hlist_for_each_entry(cur_id, &bind_list->owners, node) { if (id_priv == cur_id) continue; @@ -2277,7 +2286,7 @@ static int cma_check_port(struct rdma_bind_list *bind_list, cur_id->reuseaddr) continue; - cur_addr = (struct sockaddr *) &cur_id->id.route.addr.src_addr; + cur_addr = cma_src_addr(cur_id); if (id_priv->afonly && cur_id->afonly && (addr->sa_family != cur_addr->sa_family)) continue; @@ -2297,7 +2306,7 @@ static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) unsigned short snum; int ret; - snum = ntohs(cma_port((struct sockaddr *) &id_priv->id.route.addr.src_addr)); + snum = ntohs(cma_port(cma_src_addr(id_priv))); if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) return -EACCES; @@ -2348,7 +2357,7 @@ static struct idr *cma_select_ib_ps(struct rdma_id_private *id_priv) struct sockaddr_ib *sib; u64 sid_ps, mask, sid; - sib = (struct sockaddr_ib *) &id_priv->id.route.addr.src_addr; + sib = (struct sockaddr_ib *) cma_src_addr(id_priv); mask = be64_to_cpu(sib->sib_sid_mask) & RDMA_IB_IP_PS_MASK; sid = be64_to_cpu(sib->sib_sid) & mask; @@ -2378,7 +2387,7 @@ static int cma_get_port(struct rdma_id_private *id_priv) struct idr *ps; int ret; - if (id_priv->id.route.addr.src_addr.ss_family != AF_IB) + if (cma_family(id_priv) != AF_IB) ps = cma_select_inet_ps(id_priv); else ps = cma_select_ib_ps(id_priv); @@ -2386,7 +2395,7 @@ static int cma_get_port(struct rdma_id_private *id_priv) return -EPROTONOSUPPORT; mutex_lock(&lock); - if (cma_any_port((struct sockaddr *) &id_priv->id.route.addr.src_addr)) + if (cma_any_port(cma_src_addr(id_priv))) ret = cma_alloc_any_port(ps, id_priv); else ret = cma_use_port(ps, id_priv); @@ -2421,8 +2430,8 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) id_priv = container_of(id, struct rdma_id_private, id); if (id_priv->state == RDMA_CM_IDLE) { - ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET; - ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr); + id->route.addr.src_addr.ss_family = AF_INET; + ret = rdma_bind_addr(id, cma_src_addr(id_priv)); if (ret) return ret; } @@ -2491,7 +2500,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) goto err1; } - memcpy(&id->route.addr.src_addr, addr, rdma_addr_size(addr)); + memcpy(cma_src_addr(id_priv), addr, rdma_addr_size(addr)); if (!(id_priv->options & (1 << CMA_OPTION_AFONLY))) { if (addr->sa_family == AF_INET) id_priv->afonly = 1; @@ -2514,19 +2523,18 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) } EXPORT_SYMBOL(rdma_bind_addr); -static int cma_format_hdr(void *hdr, enum rdma_port_space ps, - struct rdma_route *route) +static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) { struct cma_hdr *cma_hdr; struct sdp_hh *sdp_hdr; - if (route->addr.src_addr.ss_family == AF_INET) { + if (cma_family(id_priv) == AF_INET) { struct sockaddr_in *src4, *dst4; - src4 = (struct sockaddr_in *) &route->addr.src_addr; - dst4 = (struct sockaddr_in *) &route->addr.dst_addr; + src4 = (struct sockaddr_in *) cma_src_addr(id_priv); + dst4 = (struct sockaddr_in *) cma_dst_addr(id_priv); - switch (ps) { + switch (id_priv->id.ps) { case RDMA_PS_SDP: sdp_hdr = hdr; if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) @@ -2548,10 +2556,10 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps, } else { struct sockaddr_in6 *src6, *dst6; - src6 = (struct sockaddr_in6 *) &route->addr.src_addr; - dst6 = (struct sockaddr_in6 *) &route->addr.dst_addr; + src6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); + dst6 = (struct sockaddr_in6 *) cma_dst_addr(id_priv); - switch (ps) { + switch (id_priv->id.ps) { case RDMA_PS_SDP: sdp_hdr = hdr; if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) @@ -2642,7 +2650,6 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, struct rdma_conn_param *conn_param) { struct ib_cm_sidr_req_param req; - struct rdma_route *route; struct ib_cm_id *id; int ret; @@ -2659,8 +2666,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, memcpy((void *) req.private_data + sizeof(struct cma_hdr), conn_param->private_data, conn_param->private_data_len); - route = &id_priv->id.route; - ret = cma_format_hdr((void *) req.private_data, id_priv->id.ps, route); + ret = cma_format_hdr((void *) req.private_data, id_priv); if (ret) goto out; @@ -2672,9 +2678,8 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, } id_priv->cm_id.ib = id; - req.path = route->path_rec; - req.service_id = cma_get_service_id(id_priv->id.ps, - (struct sockaddr *) &route->addr.dst_addr); + req.path = id_priv->id.route.path_rec; + req.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8); req.max_cm_retries = CMA_MAX_CM_RETRIES; @@ -2719,7 +2724,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, id_priv->cm_id.ib = id; route = &id_priv->id.route; - ret = cma_format_hdr(private_data, id_priv->id.ps, route); + ret = cma_format_hdr(private_data, id_priv); if (ret) goto out; req.private_data = private_data; @@ -2728,8 +2733,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, if (route->num_paths == 2) req.alternate_path = &route->path_rec[1]; - req.service_id = cma_get_service_id(id_priv->id.ps, - (struct sockaddr *) &route->addr.dst_addr); + req.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); req.qp_num = id_priv->qp_num; req.qp_type = id_priv->id.qp_type; req.starting_psn = id_priv->seq_num; @@ -2768,10 +2772,10 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, id_priv->cm_id.iw = cm_id; - sin = (struct sockaddr_in*) &id_priv->id.route.addr.src_addr; + sin = (struct sockaddr_in *) cma_src_addr(id_priv); cm_id->local_addr = *sin; - sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr; + sin = (struct sockaddr_in *) cma_dst_addr(id_priv); cm_id->remote_addr = *sin; ret = cma_modify_qp_rtr(id_priv, conn_param); @@ -3536,29 +3540,29 @@ static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) id_stats->bound_dev_if = id->route.addr.dev_addr.bound_dev_if; - if (id->route.addr.src_addr.ss_family == AF_INET) { + if (cma_family(id_priv) == AF_INET) { if (ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_in), - &id->route.addr.src_addr, + cma_src_addr(id_priv), RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { goto out; } if (ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_in), - &id->route.addr.dst_addr, + cma_dst_addr(id_priv), RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { goto out; } - } else if (id->route.addr.src_addr.ss_family == AF_INET6) { + } else if (cma_family(id_priv) == AF_INET6) { if (ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_in6), - &id->route.addr.src_addr, + cma_src_addr(id_priv), RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { goto out; } if (ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_in6), - &id->route.addr.dst_addr, + cma_dst_addr(id_priv), RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { goto out; } -- GitLab From b0569e40753aa4f742cfd792447a093ab7937563 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:15 -0700 Subject: [PATCH 1547/2900] RDMA/cma: Restrict AF_IB loopback to binding to IB devices only If a user specifies AF_IB as the source address for a loopback connection, limit the resolution to IB devices only. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 90694530757a..524cf986d9fa 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1981,26 +1981,38 @@ static void cma_set_loopback(struct sockaddr *addr) static int cma_bind_loopback(struct rdma_id_private *id_priv) { - struct cma_device *cma_dev; + struct cma_device *cma_dev, *cur_dev; struct ib_port_attr port_attr; union ib_gid gid; u16 pkey; int ret; u8 p; + cma_dev = NULL; mutex_lock(&lock); - if (list_empty(&dev_list)) { + list_for_each_entry(cur_dev, &dev_list, list) { + if (cma_family(id_priv) == AF_IB && + rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) + continue; + + if (!cma_dev) + cma_dev = cur_dev; + + for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { + if (!ib_query_port(cur_dev->device, p, &port_attr) && + port_attr.state == IB_PORT_ACTIVE) { + cma_dev = cur_dev; + goto port_found; + } + } + } + + if (!cma_dev) { ret = -ENODEV; goto out; } - list_for_each_entry(cma_dev, &dev_list, list) - for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p) - if (!ib_query_port(cma_dev->device, p, &port_attr) && - port_attr.state == IB_PORT_ACTIVE) - goto port_found; p = 1; - cma_dev = list_entry(dev_list.next, struct cma_device, list); port_found: ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid); -- GitLab From 4ae7152e0bf98ac91a2835dce07f6fdb9f6407bd Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:16 -0700 Subject: [PATCH 1548/2900] RDMA/cma: Verify that source and dest sa_family are the same Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 524cf986d9fa..9f6e719cf620 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1849,14 +1849,9 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) struct rdma_addr *addr = &route->addr; struct cma_work *work; int ret; - struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr; - struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr; struct net_device *ndev = NULL; u16 vid; - if (src_addr->sin_family != dst_addr->sin_family) - return -EINVAL; - work = kzalloc(sizeof *work, GFP_KERNEL); if (!work) return -ENOMEM; @@ -2132,6 +2127,9 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, return ret; } + if (cma_family(id_priv) != dst_addr->sa_family) + return -EINVAL; + if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) return -EINVAL; -- GitLab From f17df3b0dede861e3c3e20225731fcbe1b1041c3 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:17 -0700 Subject: [PATCH 1549/2900] RDMA/cma: Add support for AF_IB to rdma_resolve_addr() Allow the user to specify the remote address using AF_IB format. When AF_IB is used, the remote address simply needs to be recorded, and no resolution using ARP is done. The local address may still need to be matched with a local IB device. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 106 ++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9f6e719cf620..7a159af08630 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -438,6 +438,61 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) return ret; } +/* + * Select the source IB device and address to reach the destination IB address. + */ +static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev, *cur_dev; + struct sockaddr_ib *addr; + union ib_gid gid, sgid, *dgid; + u16 pkey, index; + u8 port, p; + int i; + + cma_dev = NULL; + addr = (struct sockaddr_ib *) cma_dst_addr(id_priv); + dgid = (union ib_gid *) &addr->sib_addr; + pkey = ntohs(addr->sib_pkey); + + list_for_each_entry(cur_dev, &dev_list, list) { + if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB) + continue; + + for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { + if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index)) + continue; + + for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i, &gid); i++) { + if (!memcmp(&gid, dgid, sizeof(gid))) { + cma_dev = cur_dev; + sgid = gid; + port = p; + goto found; + } + + if (!cma_dev && (gid.global.subnet_prefix == + dgid->global.subnet_prefix)) { + cma_dev = cur_dev; + sgid = gid; + port = p; + } + } + } + } + + if (!cma_dev) + return -ENODEV; + +found: + cma_attach_to_dev(id_priv, cma_dev); + id_priv->id.port_num = port; + addr = (struct sockaddr_ib *) cma_src_addr(id_priv); + memcpy(&addr->sib_addr, &sgid, sizeof sgid); + cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); + return 0; +} + static void cma_deref_id(struct rdma_id_private *id_priv) { if (atomic_dec_and_test(&id_priv->refcount)) @@ -2101,14 +2156,48 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) return ret; } +static int cma_resolve_ib_addr(struct rdma_id_private *id_priv) +{ + struct cma_work *work; + int ret; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) + return -ENOMEM; + + if (!id_priv->cma_dev) { + ret = cma_resolve_ib_dev(id_priv); + if (ret) + goto err; + } + + rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, (union ib_gid *) + &(((struct sockaddr_ib *) &id_priv->id.route.addr.dst_addr)->sib_addr)); + + work->id = id_priv; + INIT_WORK(&work->work, cma_work_handler); + work->old_state = RDMA_CM_ADDR_QUERY; + work->new_state = RDMA_CM_ADDR_RESOLVED; + work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; + queue_work(cma_wq, &work->work); + return 0; +err: + kfree(work); + return ret; +} + static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, struct sockaddr *dst_addr) { if (!src_addr || !src_addr->sa_family) { src_addr = (struct sockaddr *) &id->route.addr.src_addr; - if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) { + src_addr->sa_family = dst_addr->sa_family; + if (dst_addr->sa_family == AF_INET6) { ((struct sockaddr_in6 *) src_addr)->sin6_scope_id = ((struct sockaddr_in6 *) dst_addr)->sin6_scope_id; + } else if (dst_addr->sa_family == AF_IB) { + ((struct sockaddr_ib *) src_addr)->sib_pkey = + ((struct sockaddr_ib *) dst_addr)->sib_pkey; } } return rdma_bind_addr(id, src_addr); @@ -2135,12 +2224,17 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, atomic_inc(&id_priv->refcount); memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); - if (cma_any_addr(dst_addr)) + if (cma_any_addr(dst_addr)) { ret = cma_resolve_loopback(id_priv); - else - ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv), - dst_addr, &id->route.addr.dev_addr, - timeout_ms, addr_handler, id_priv); + } else { + if (dst_addr->sa_family == AF_IB) { + ret = cma_resolve_ib_addr(id_priv); + } else { + ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv), + dst_addr, &id->route.addr.dev_addr, + timeout_ms, addr_handler, id_priv); + } + } if (ret) goto err; -- GitLab From f68194ca88ecca70e7e9064949d9d1f6e4b3a647 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:18 -0700 Subject: [PATCH 1550/2900] RDMA/cma: Add support for AF_IB to rdma_resolve_route() Allow rdma_resolve_route() to handle the case where the user specified the source and destination addresses using AF_IB. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 7a159af08630..66cb043ddd49 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1743,6 +1743,7 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, struct ib_sa_path_rec path_rec; ib_sa_comp_mask comp_mask; struct sockaddr_in6 *sin6; + struct sockaddr_ib *sib; memset(&path_rec, 0, sizeof path_rec); rdma_addr_get_sgid(dev_addr, &path_rec.sgid); @@ -1756,13 +1757,21 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH | IB_SA_PATH_REC_REVERSIBLE | IB_SA_PATH_REC_SERVICE_ID; - if (cma_family(id_priv) == AF_INET) { + switch (cma_family(id_priv)) { + case AF_INET: path_rec.qos_class = cpu_to_be16((u16) id_priv->tos); comp_mask |= IB_SA_PATH_REC_QOS_CLASS; - } else { + break; + case AF_INET6: sin6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); path_rec.traffic_class = (u8) (be32_to_cpu(sin6->sin6_flowinfo) >> 20); comp_mask |= IB_SA_PATH_REC_TRAFFIC_CLASS; + break; + case AF_IB: + sib = (struct sockaddr_ib *) cma_src_addr(id_priv); + path_rec.traffic_class = (u8) (be32_to_cpu(sib->sib_flowinfo) >> 20); + comp_mask |= IB_SA_PATH_REC_TRAFFIC_CLASS; + break; } id_priv->query_id = ib_sa_path_rec_get(&sa_client, id_priv->id.device, -- GitLab From 496ce3ce17f4b4f1b5f6edf9d2aedc4787a31c2f Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:19 -0700 Subject: [PATCH 1551/2900] RDMA/cma: Add support for AF_IB to cma_get_service_id() cma_get_service_id() forms the service ID based on the port space and port number of the rdma_cm_id. Extend the call to support AF_IB, which contains the service ID directly. This will be needed to support any arbitrary SID. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 66cb043ddd49..f1dd0ca34d83 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1379,6 +1379,9 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr) { + if (addr->sa_family == AF_IB) + return ((struct sockaddr_ib *) addr)->sib_sid; + return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr))); } -- GitLab From 01602f113f7ceee51e04edd1db972b79bedfe3aa Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:20 -0700 Subject: [PATCH 1552/2900] RDMA/cma: Remove unused SDP related code The SDP protocol was never merged upstream. Remove unused SDP related code from the RDMA CM. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 176 ++++++---------------------------- 1 file changed, 31 insertions(+), 145 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index f1dd0ca34d83..daec9319502d 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -80,7 +80,6 @@ static LIST_HEAD(dev_list); static LIST_HEAD(listen_any_list); static DEFINE_MUTEX(lock); static struct workqueue_struct *cma_wq; -static DEFINE_IDR(sdp_ps); static DEFINE_IDR(tcp_ps); static DEFINE_IDR(udp_ps); static DEFINE_IDR(ipoib_ps); @@ -196,24 +195,7 @@ struct cma_hdr { union cma_ip_addr dst_addr; }; -struct sdp_hh { - u8 bsdh[16]; - u8 sdp_version; /* Major version: 7:4 */ - u8 ip_version; /* IP version: 7:4 */ - u8 sdp_specific1[10]; - __be16 port; - __be16 sdp_specific2; - union cma_ip_addr src_addr; - union cma_ip_addr dst_addr; -}; - -struct sdp_hah { - u8 bsdh[16]; - u8 sdp_version; -}; - #define CMA_VERSION 0x00 -#define SDP_MAJ_VERSION 0x2 static int cma_comp(struct rdma_id_private *id_priv, enum rdma_cm_state comp) { @@ -262,21 +244,6 @@ static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); } -static inline u8 sdp_get_majv(u8 sdp_version) -{ - return sdp_version >> 4; -} - -static inline u8 sdp_get_ip_ver(struct sdp_hh *hh) -{ - return hh->ip_version >> 4; -} - -static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) -{ - hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF); -} - static void cma_attach_to_dev(struct rdma_id_private *id_priv, struct cma_device *cma_dev) { @@ -847,27 +814,13 @@ static int cma_get_net_info(void *hdr, enum rdma_port_space ps, u8 *ip_ver, __be16 *port, union cma_ip_addr **src, union cma_ip_addr **dst) { - switch (ps) { - case RDMA_PS_SDP: - if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) != - SDP_MAJ_VERSION) - return -EINVAL; - - *ip_ver = sdp_get_ip_ver(hdr); - *port = ((struct sdp_hh *) hdr)->port; - *src = &((struct sdp_hh *) hdr)->src_addr; - *dst = &((struct sdp_hh *) hdr)->dst_addr; - break; - default: - if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) - return -EINVAL; + if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) + return -EINVAL; - *ip_ver = cma_get_ip_ver(hdr); - *port = ((struct cma_hdr *) hdr)->port; - *src = &((struct cma_hdr *) hdr)->src_addr; - *dst = &((struct cma_hdr *) hdr)->dst_addr; - break; - } + *ip_ver = cma_get_ip_ver(hdr); + *port = ((struct cma_hdr *) hdr)->port; + *src = &((struct cma_hdr *) hdr)->src_addr; + *dst = &((struct cma_hdr *) hdr)->dst_addr; if (*ip_ver != 4 && *ip_ver != 6) return -EINVAL; @@ -914,12 +867,7 @@ static void cma_save_net_info(struct rdma_addr *addr, static inline int cma_user_data_offset(enum rdma_port_space ps) { - switch (ps) { - case RDMA_PS_SDP: - return 0; - default: - return sizeof(struct cma_hdr); - } + return sizeof(struct cma_hdr); } static void cma_cancel_route(struct rdma_id_private *id_priv) @@ -1085,16 +1033,6 @@ static int cma_rep_recv(struct rdma_id_private *id_priv) return ret; } -static int cma_verify_rep(struct rdma_id_private *id_priv, void *data) -{ - if (id_priv->id.ps == RDMA_PS_SDP && - sdp_get_majv(((struct sdp_hah *) data)->sdp_version) != - SDP_MAJ_VERSION) - return -EINVAL; - - return 0; -} - static void cma_set_rep_event_data(struct rdma_cm_event *event, struct ib_cm_rep_event_param *rep_data, void *private_data) @@ -1129,15 +1067,13 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) event.status = -ETIMEDOUT; break; case IB_CM_REP_RECEIVED: - event.status = cma_verify_rep(id_priv, ib_event->private_data); - if (event.status) - event.event = RDMA_CM_EVENT_CONNECT_ERROR; - else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) { + if (id_priv->id.qp) { event.status = cma_rep_recv(id_priv); event.event = event.status ? RDMA_CM_EVENT_CONNECT_ERROR : RDMA_CM_EVENT_ESTABLISHED; - } else + } else { event.event = RDMA_CM_EVENT_CONNECT_RESPONSE; + } cma_set_rep_event_data(&event, &ib_event->param.rep_rcvd, ib_event->private_data); break; @@ -1389,49 +1325,31 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, struct ib_cm_compare_data *compare) { struct cma_hdr *cma_data, *cma_mask; - struct sdp_hh *sdp_data, *sdp_mask; __be32 ip4_addr; struct in6_addr ip6_addr; memset(compare, 0, sizeof *compare); cma_data = (void *) compare->data; cma_mask = (void *) compare->mask; - sdp_data = (void *) compare->data; - sdp_mask = (void *) compare->mask; switch (addr->sa_family) { case AF_INET: ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; - if (ps == RDMA_PS_SDP) { - sdp_set_ip_ver(sdp_data, 4); - sdp_set_ip_ver(sdp_mask, 0xF); - sdp_data->dst_addr.ip4.addr = ip4_addr; - sdp_mask->dst_addr.ip4.addr = htonl(~0); - } else { - cma_set_ip_ver(cma_data, 4); - cma_set_ip_ver(cma_mask, 0xF); - if (!cma_any_addr(addr)) { - cma_data->dst_addr.ip4.addr = ip4_addr; - cma_mask->dst_addr.ip4.addr = htonl(~0); - } + cma_set_ip_ver(cma_data, 4); + cma_set_ip_ver(cma_mask, 0xF); + if (!cma_any_addr(addr)) { + cma_data->dst_addr.ip4.addr = ip4_addr; + cma_mask->dst_addr.ip4.addr = htonl(~0); } break; case AF_INET6: ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr; - if (ps == RDMA_PS_SDP) { - sdp_set_ip_ver(sdp_data, 6); - sdp_set_ip_ver(sdp_mask, 0xF); - sdp_data->dst_addr.ip6 = ip6_addr; - memset(&sdp_mask->dst_addr.ip6, 0xFF, - sizeof sdp_mask->dst_addr.ip6); - } else { - cma_set_ip_ver(cma_data, 6); - cma_set_ip_ver(cma_mask, 0xF); - if (!cma_any_addr(addr)) { - cma_data->dst_addr.ip6 = ip6_addr; - memset(&cma_mask->dst_addr.ip6, 0xFF, - sizeof cma_mask->dst_addr.ip6); - } + cma_set_ip_ver(cma_data, 6); + cma_set_ip_ver(cma_mask, 0xF); + if (!cma_any_addr(addr)) { + cma_data->dst_addr.ip6 = ip6_addr; + memset(&cma_mask->dst_addr.ip6, 0xFF, + sizeof cma_mask->dst_addr.ip6); } break; default: @@ -2452,8 +2370,6 @@ static int cma_bind_listen(struct rdma_id_private *id_priv) static struct idr *cma_select_inet_ps(struct rdma_id_private *id_priv) { switch (id_priv->id.ps) { - case RDMA_PS_SDP: - return &sdp_ps; case RDMA_PS_TCP: return &tcp_ps; case RDMA_PS_UDP: @@ -2642,58 +2558,29 @@ EXPORT_SYMBOL(rdma_bind_addr); static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) { struct cma_hdr *cma_hdr; - struct sdp_hh *sdp_hdr; + cma_hdr = hdr; + cma_hdr->cma_version = CMA_VERSION; if (cma_family(id_priv) == AF_INET) { struct sockaddr_in *src4, *dst4; src4 = (struct sockaddr_in *) cma_src_addr(id_priv); dst4 = (struct sockaddr_in *) cma_dst_addr(id_priv); - switch (id_priv->id.ps) { - case RDMA_PS_SDP: - sdp_hdr = hdr; - if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) - return -EINVAL; - sdp_set_ip_ver(sdp_hdr, 4); - sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; - sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; - sdp_hdr->port = src4->sin_port; - break; - default: - cma_hdr = hdr; - cma_hdr->cma_version = CMA_VERSION; - cma_set_ip_ver(cma_hdr, 4); - cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; - cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; - cma_hdr->port = src4->sin_port; - break; - } + cma_set_ip_ver(cma_hdr, 4); + cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + cma_hdr->port = src4->sin_port; } else { struct sockaddr_in6 *src6, *dst6; src6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); dst6 = (struct sockaddr_in6 *) cma_dst_addr(id_priv); - switch (id_priv->id.ps) { - case RDMA_PS_SDP: - sdp_hdr = hdr; - if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) - return -EINVAL; - sdp_set_ip_ver(sdp_hdr, 6); - sdp_hdr->src_addr.ip6 = src6->sin6_addr; - sdp_hdr->dst_addr.ip6 = dst6->sin6_addr; - sdp_hdr->port = src6->sin6_port; - break; - default: - cma_hdr = hdr; - cma_hdr->cma_version = CMA_VERSION; - cma_set_ip_ver(cma_hdr, 6); - cma_hdr->src_addr.ip6 = src6->sin6_addr; - cma_hdr->dst_addr.ip6 = dst6->sin6_addr; - cma_hdr->port = src6->sin6_port; - break; - } + cma_set_ip_ver(cma_hdr, 6); + cma_hdr->src_addr.ip6 = src6->sin6_addr; + cma_hdr->dst_addr.ip6 = dst6->sin6_addr; + cma_hdr->port = src6->sin6_port; } return 0; } @@ -3747,7 +3634,6 @@ static void __exit cma_cleanup(void) rdma_addr_unregister_client(&addr_client); ib_sa_unregister_client(&sa_client); destroy_workqueue(cma_wq); - idr_destroy(&sdp_ps); idr_destroy(&tcp_ps); idr_destroy(&udp_ps); idr_destroy(&ipoib_ps); -- GitLab From 862e6389a78992d4ee44bf4f60051fe560470320 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:35:18 -0700 Subject: [PATCH 1553/2900] target: Add transport_cmd_check_stop write_pending bit This patch adds a new transport_cmd_check_stop() parameter for signaling when TRANSPORT_WRITE_PENDING needs to be set. This allows transport_generic_new_cmd() to avoid the extra lock acquire/release of ->t_state_lock in the fast path for DMA_TO_DEVICE operations ahead of transport_cmd_check_stop() + se_tfo->write_pending(). Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 21e315874a54..39319efe50c1 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -446,11 +446,15 @@ static void target_remove_from_state_list(struct se_cmd *cmd) spin_unlock_irqrestore(&dev->execute_task_lock, flags); } -static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists) +static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists, + bool write_pending) { unsigned long flags; spin_lock_irqsave(&cmd->t_state_lock, flags); + if (write_pending) + cmd->t_state = TRANSPORT_WRITE_PENDING; + /* * Determine if IOCTL context caller in requesting the stopping of this * command for LUN shutdown purposes. @@ -515,7 +519,7 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists) static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd) { - return transport_cmd_check_stop(cmd, true); + return transport_cmd_check_stop(cmd, true, false); } static void transport_lun_remove_cmd(struct se_cmd *cmd) @@ -2116,12 +2120,7 @@ transport_generic_new_cmd(struct se_cmd *cmd) target_execute_cmd(cmd); return 0; } - - spin_lock_irq(&cmd->t_state_lock); - cmd->t_state = TRANSPORT_WRITE_PENDING; - spin_unlock_irq(&cmd->t_state_lock); - - transport_cmd_check_stop(cmd, false); + transport_cmd_check_stop(cmd, false, true); ret = cmd->se_tfo->write_pending(cmd); if (ret == -EAGAIN || ret == -ENOMEM) @@ -2319,7 +2318,7 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun) pr_debug("ConfigFS ITT[0x%08x] - CMD_T_STOP, skipping\n", cmd->se_tfo->get_task_tag(cmd)); spin_unlock_irqrestore(&cmd->t_state_lock, flags); - transport_cmd_check_stop(cmd, false); + transport_cmd_check_stop(cmd, false, false); return -EPERM; } cmd->transport_state |= CMD_T_LUN_FE_STOP; @@ -2427,7 +2426,7 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun) spin_unlock_irqrestore(&cmd->t_state_lock, cmd_flags); - transport_cmd_check_stop(cmd, false); + transport_cmd_check_stop(cmd, false, false); complete(&cmd->transport_lun_fe_stop_comp); spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags); continue; -- GitLab From 0b66818ac6de67a6125ae203272fb76e79b3a20f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:36:41 -0700 Subject: [PATCH 1554/2900] target: Drop unnecessary CMD_T_DEV_ACTIVE check from transport_lun_remove_cmd This patch drops an unnecessary acquire/release of se_cmd->t_state_lock within transport_lun_remove_cmd() when checking CMD_T_DEV_ACTIVE for invoking target_remove_from_state_list(). For all fast path completion cases, transport_lun_remove_cmd() is always called ahead of transport_cmd_check_stop(), and since transport_cmd_check_stop() is calling target_remove_from_state_list() when remove_from_lists=true, the t_state_lock usage in transport_lun_remove_cmd() can safely be removed. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 39319efe50c1..bc37666bc941 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -530,13 +530,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) if (!lun) return; - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (cmd->transport_state & CMD_T_DEV_ACTIVE) { - cmd->transport_state &= ~CMD_T_DEV_ACTIVE; - target_remove_from_state_list(cmd); - } - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - spin_lock_irqsave(&lun->lun_cmd_lock, flags); if (!list_empty(&cmd->se_lun_node)) list_del_init(&cmd->se_lun_node); -- GitLab From c1c35d52251b0941a72b0cdb862e85f0eba6b1bb Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 02:00:06 -0700 Subject: [PATCH 1555/2900] target: Remove legacy t_fe_count + avoid t_state_lock access in transport_put_cmd This patch removes legacy se_cmd->t_fe_count usage in order to avoid se_cmd->t_state_lock access within transport_put_cmd() during normal fast path se_cmd descriptor release. Also drop the left-over parameter usage within core_tmr_handle_tas_abort() Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_tmr.c | 12 ++---------- drivers/target/target_core_transport.c | 18 ------------------ include/target/target_core_base.h | 1 - 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index d0b4dd95b91e..0d7cacb91107 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -85,13 +85,8 @@ void core_tmr_release_req( static void core_tmr_handle_tas_abort( struct se_node_acl *tmr_nacl, struct se_cmd *cmd, - int tas, - int fe_count) + int tas) { - if (!fe_count) { - transport_cmd_finish_abort(cmd, 1); - return; - } /* * TASK ABORTED status (TAS) bit support */ @@ -253,7 +248,6 @@ static void core_tmr_drain_state_list( LIST_HEAD(drain_task_list); struct se_cmd *cmd, *next; unsigned long flags; - int fe_count; /* * Complete outstanding commands with TASK_ABORTED SAM status. @@ -329,12 +323,10 @@ static void core_tmr_drain_state_list( spin_lock_irqsave(&cmd->t_state_lock, flags); target_stop_cmd(cmd, &flags); - fe_count = atomic_read(&cmd->t_fe_count); - cmd->transport_state |= CMD_T_ABORTED; spin_unlock_irqrestore(&cmd->t_state_lock, flags); - core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); + core_tmr_handle_tas_abort(tmr_nacl, cmd, tas); } } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index bc37666bc941..01cdee47f75e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1968,21 +1968,6 @@ static int transport_release_cmd(struct se_cmd *cmd) */ static int transport_put_cmd(struct se_cmd *cmd) { - unsigned long flags; - - spin_lock_irqsave(&cmd->t_state_lock, flags); - if (atomic_read(&cmd->t_fe_count) && - !atomic_dec_and_test(&cmd->t_fe_count)) { - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - return 0; - } - - if (cmd->transport_state & CMD_T_DEV_ACTIVE) { - cmd->transport_state &= ~CMD_T_DEV_ACTIVE; - target_remove_from_state_list(cmd); - } - spin_unlock_irqrestore(&cmd->t_state_lock, flags); - transport_free_pages(cmd); return transport_release_cmd(cmd); } @@ -2100,9 +2085,6 @@ transport_generic_new_cmd(struct se_cmd *cmd) if (ret < 0) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } - - atomic_inc(&cmd->t_fe_count); - /* * If this command is not a write we can execute it right here, * for write buffers we need to notify the fabric driver first diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 8952ee9f7cef..891ea1f81832 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -454,7 +454,6 @@ struct se_cmd { unsigned char *t_task_cdb; unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; unsigned long long t_task_lba; - atomic_t t_fe_count; unsigned int transport_state; #define CMD_T_ABORTED (1 << 0) #define CMD_T_ACTIVE (1 << 1) -- GitLab From 1a398b973184342f30ab97711b9c38fd75df0384 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:40:27 -0700 Subject: [PATCH 1556/2900] target: Avoid extra t_state_lock access in __target_execute_cmd This patch makes target_execute_cmd() set CMD_T_BUSY|CMD_T_SENT while holding se_cmd->t_state_lock, in order to avoid the extra aquire/release in __target_execute_cmd(). It also clears these bits in case of a target_handle_task_attr() failure. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 01cdee47f75e..e9ba012e82a9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1580,10 +1580,6 @@ static void __target_execute_cmd(struct se_cmd *cmd) { sense_reason_t ret; - spin_lock_irq(&cmd->t_state_lock); - cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT); - spin_unlock_irq(&cmd->t_state_lock); - if (cmd->execute_cmd) { ret = cmd->execute_cmd(cmd); if (ret) { @@ -1690,11 +1686,17 @@ void target_execute_cmd(struct se_cmd *cmd) } cmd->t_state = TRANSPORT_PROCESSING; - cmd->transport_state |= CMD_T_ACTIVE; + cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT; spin_unlock_irq(&cmd->t_state_lock); - if (!target_handle_task_attr(cmd)) - __target_execute_cmd(cmd); + if (target_handle_task_attr(cmd)) { + spin_lock_irq(&cmd->t_state_lock); + cmd->transport_state &= ~CMD_T_BUSY|CMD_T_SENT; + spin_unlock_irq(&cmd->t_state_lock); + return; + } + + __target_execute_cmd(cmd); } EXPORT_SYMBOL(target_execute_cmd); -- GitLab From b28e545c4ddd7b594c64e8f3d9c2891eda253afc Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:58:04 -0700 Subject: [PATCH 1557/2900] target: Drop unnecessary t_state_lock access for SCF_SUPPORTED_SAM_OPCODE assignment This patch drops the se_cmd->t_state_lock access around SCF_SUPPORTED_SAM_OPCODE assignment within target_setup_cmd_from_cdb(). Original v4.0 target code required this as fabrics would be checking for this values in different process contexts for setup and I/O submission. Given that modern v4.1 target code performs setup and I/O submission from the same process context, this t_state_lock access is no longer required. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e9ba012e82a9..94c5b323db3c 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1089,7 +1089,6 @@ sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) { struct se_device *dev = cmd->se_dev; - unsigned long flags; sense_reason_t ret; /* @@ -1149,9 +1148,7 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) if (ret) return ret; - spin_lock_irqsave(&cmd->t_state_lock, flags); cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE; - spin_unlock_irqrestore(&cmd->t_state_lock, flags); spin_lock(&cmd->se_lun->lun_sep_lock); if (cmd->se_lun->lun_sep) -- GitLab From b9da5826df3936671ea67bc33f6fc8c2020526b8 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:58:49 -0700 Subject: [PATCH 1558/2900] iscsi-target: Avoid unnecessary t_state_lock during unsolicited data-out check In modern iscsi-target code, the setup and I/O submission is done within a single process context, so there is no need to acquire se_cmd->t_state_lock while checking SCF_SUPPORTED_SAM_OPCODE for determining when unsolicited data-out should be dumped. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d7705e5824fb..cc43d4163adc 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1277,7 +1277,6 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, struct iscsi_data *hdr = (struct iscsi_data *)buf; struct iscsi_cmd *cmd = NULL; struct se_cmd *se_cmd; - unsigned long flags; u32 payload_length = ntoh24(hdr->dlength); int rc; @@ -1356,14 +1355,9 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, */ /* Something's amiss if we're not in WRITE_PENDING state... */ - spin_lock_irqsave(&se_cmd->t_state_lock, flags); WARN_ON(se_cmd->t_state != TRANSPORT_WRITE_PENDING); - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); - - spin_lock_irqsave(&se_cmd->t_state_lock, flags); if (!(se_cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE)) dump_unsolicited_data = 1; - spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); if (dump_unsolicited_data) { /* -- GitLab From ca24976ac815aeb17bf1707a96231409c57afac2 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 02:06:14 -0700 Subject: [PATCH 1559/2900] target: Drop legacy se_cmd->check_release bit Now with iscsi-target using modern se_cmd->cmd_kref accounting in v3.10 code, it's safe to go ahead and drop the legacy release codepath + se_cmd->check_release bit in transport_release_cmd() Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 8 +------- include/target/target_core_base.h | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 94c5b323db3c..ae40addd4ce0 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1952,11 +1952,7 @@ static int transport_release_cmd(struct se_cmd *cmd) * If this cmd has been setup with target_get_sess_cmd(), drop * the kref and call ->release_cmd() in kref callback. */ - if (cmd->check_release != 0) - return target_put_sess_cmd(cmd->se_sess, cmd); - - cmd->se_tfo->release_cmd(cmd); - return 1; + return target_put_sess_cmd(cmd->se_sess, cmd); } /** @@ -2175,8 +2171,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd, goto out; } list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); - se_cmd->check_release = 1; - out: spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); return ret; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 891ea1f81832..9fd7a60f47f0 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -420,8 +420,6 @@ struct se_cmd { int sam_task_attr; /* Transport protocol dependent state, see transport_state_table */ enum transport_state_table t_state; - /* Used to signal cmd->se_tfo->check_release_cmd() usage per cmd */ - unsigned check_release:1; unsigned cmd_wait_set:1; unsigned unknown_data_length:1; /* See se_cmd_flags_table */ -- GitLab From 6c131d0c583cd5ceb2b497ae2dbeeae180d3573d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 01:44:48 -0700 Subject: [PATCH 1560/2900] vhost/scsi: Drop unnecessary wait_for_tasks=true usage with transport_generic_free_cmd This patch changes vhost_scsi_free_cmd() to call transport_generic_free_cmd() with wait_for_tasks=false in order to avoid the extra se_cmd->t_state_lock access for the wait_for_tasks=true case. This is unnecessary because vhost_scsi_free_cmd() is only ever called by vhost_scsi_complete_cmd_work() after TCM completion handoff, and by vhost_scsi_handle_vq() exception code before TCM submission handoff, so there is never a case where se_cmd is still active from TCM's perspective when transport_generic_free_cmd() is called. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Asias He Cc: Michael S. Tsirkin Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/vhost/scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 701420297225..aacf71ea001e 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -557,7 +557,7 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; /* TODO locking against target/backend threads? */ - transport_generic_free_cmd(se_cmd, 1); + transport_generic_free_cmd(se_cmd, 0); if (tv_cmd->tvc_sgl_count) { u32 i; -- GitLab From 084ed45b3846ffb803a6cd6d631c1723e77689e0 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 6 Jun 2013 02:20:41 -0700 Subject: [PATCH 1561/2900] vhost/scsi: Convert to se_cmd->cmd_kref TARGET_SCF_ACK_KREF usage This patch coverts vhost/scsi to se_cmd->cmd_kref TARGET_SCF_ACK_KREF usage, instead of assuming that vhost_scsi_free_cmd() is always called before TCM processing is completed in the response fast path. This includes adding vhost_scsi_check_stop_free() -> target_put_sess_cmd() to perform the second se_cmd->cmd_kref put, and moving vhost_scsi_free_cmd() resource release into tcm_vhost_release_cmd() that is invoked once the last se_cmd->cmd_kref put occurs. Cc: Christoph Hellwig Cc: Roland Dreier Cc: Kent Overstreet Cc: Asias He Cc: Michael S. Tsirkin Cc: Or Gerlitz Cc: Moussa Ba Signed-off-by: Nicholas Bellinger --- drivers/vhost/scsi.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index aacf71ea001e..1e5e82042f84 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -446,7 +446,19 @@ static u32 tcm_vhost_tpg_get_inst_index(struct se_portal_group *se_tpg) static void tcm_vhost_release_cmd(struct se_cmd *se_cmd) { - return; + struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, + struct tcm_vhost_cmd, tvc_se_cmd); + + if (tv_cmd->tvc_sgl_count) { + u32 i; + for (i = 0; i < tv_cmd->tvc_sgl_count; i++) + put_page(sg_page(&tv_cmd->tvc_sgl[i])); + + kfree(tv_cmd->tvc_sgl); + } + + tcm_vhost_put_inflight(tv_cmd->inflight); + kfree(tv_cmd); } static int tcm_vhost_shutdown_session(struct se_session *se_sess) @@ -559,17 +571,11 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) /* TODO locking against target/backend threads? */ transport_generic_free_cmd(se_cmd, 0); - if (tv_cmd->tvc_sgl_count) { - u32 i; - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_sgl[i])); - - kfree(tv_cmd->tvc_sgl); - } - - tcm_vhost_put_inflight(tv_cmd->inflight); +} - kfree(tv_cmd); +static int vhost_scsi_check_stop_free(struct se_cmd *se_cmd) +{ + return target_put_sess_cmd(se_cmd->se_sess, se_cmd); } static void tcm_vhost_do_evt_work(struct vhost_scsi *vs, @@ -847,7 +853,7 @@ static void tcm_vhost_submission_work(struct work_struct *work) tv_cmd->tvc_cdb, &tv_cmd->tvc_sense_buf[0], tv_cmd->tvc_lun, tv_cmd->tvc_exp_data_len, tv_cmd->tvc_task_attr, tv_cmd->tvc_data_direction, - 0, sg_ptr, tv_cmd->tvc_sgl_count, + TARGET_SCF_ACK_KREF, sg_ptr, tv_cmd->tvc_sgl_count, sg_bidi_ptr, sg_no_bidi); if (rc < 0) { transport_send_check_condition_and_sense(se_cmd, @@ -2008,6 +2014,7 @@ static struct target_core_fabric_ops tcm_vhost_ops = { .tpg_release_fabric_acl = tcm_vhost_release_fabric_acl, .tpg_get_inst_index = tcm_vhost_tpg_get_inst_index, .release_cmd = tcm_vhost_release_cmd, + .check_stop_free = vhost_scsi_check_stop_free, .shutdown_session = tcm_vhost_shutdown_session, .close_session = tcm_vhost_close_session, .sess_get_index = tcm_vhost_sess_get_index, -- GitLab From 08234e3adc7a299c9213bcfa0b5e97c359129670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Engel?= Date: Wed, 12 Jun 2013 16:27:54 -0400 Subject: [PATCH 1562/2900] qla_target: remove qlt_check_fcport_exist Comment from original 2012 patch: In all our testing this function has never returned true. However, the dropping of hardware_lock necessary to call this function seems to cause a use-after-free we manage to hit rather frequently. Given this cost-benefit ratio, I'm willing to remove some 100 lines of code. And since the same problem exists around shutdown_sess and put_sess, this patch changes them from taking the hardware_lock to requiring the hardware_lock to be taken. In most cases the caller already had the lock and had to drop it for the called method to reacquire it. At best that hurts performance and in rare instances it causes races with fatal consequences. We dropped the original 2012 patch when upgrading our kernel and it took us nearly half a year to discover we still need it. (nab: Fix qla_tgt_sess reference in tcm_qla2xxx_put_sess) Signed-off-by: Joern Engel Cc: Giridhar Malavali Cc: Chad Dupuis Signed-off-by: Nicholas Bellinger --- drivers/scsi/qla2xxx/qla_target.c | 151 +++-------------------------- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 6 +- 2 files changed, 17 insertions(+), 140 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index fcdc22306cab..83a8f7a9ec76 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -544,102 +544,6 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id, return res; } -static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, - struct qla_tgt_sess *sess) -{ - struct qla_hw_data *ha = vha->hw; - struct qla_port_24xx_data *pmap24; - bool res, found = false; - int rc, i; - uint16_t loop_id = 0xFFFF; /* to eliminate compiler's warning */ - uint16_t entries; - void *pmap; - int pmap_len; - fc_port_t *fcport; - int global_resets; - unsigned long flags; - -retry: - global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); - - rc = qla2x00_get_node_name_list(vha, &pmap, &pmap_len); - if (rc != QLA_SUCCESS) { - res = false; - goto out; - } - - pmap24 = pmap; - entries = pmap_len/sizeof(*pmap24); - - for (i = 0; i < entries; ++i) { - if (!memcmp(sess->port_name, pmap24[i].port_name, WWN_SIZE)) { - loop_id = le16_to_cpu(pmap24[i].loop_id); - found = true; - break; - } - } - - kfree(pmap); - - if (!found) { - res = false; - goto out; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf046, - "qlt_check_fcport_exist(): loop_id %d", loop_id); - - fcport = kzalloc(sizeof(*fcport), GFP_KERNEL); - if (fcport == NULL) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf047, - "qla_target(%d): Allocation of tmp FC port failed", - vha->vp_idx); - res = false; - goto out; - } - - fcport->loop_id = loop_id; - - rc = qla2x00_get_port_database(vha, fcport, 0); - if (rc != QLA_SUCCESS) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf048, - "qla_target(%d): Failed to retrieve fcport " - "information -- get_port_database() returned %x " - "(loop_id=0x%04x)", vha->vp_idx, rc, loop_id); - res = false; - goto out_free_fcport; - } - - if (global_resets != - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf002, - "qla_target(%d): global reset during session discovery" - " (counter was %d, new %d), retrying", - vha->vp_idx, global_resets, - atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count)); - goto retry; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003, - "Updating sess %p s_id %x:%x:%x, loop_id %d) to d_id %x:%x:%x, " - "loop_id %d", sess, sess->s_id.b.domain, sess->s_id.b.al_pa, - sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, - (fcport->flags & FCF_CONF_COMP_SUPPORTED)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - res = true; - -out_free_fcport: - kfree(fcport); - -out: - return res; -} - /* ha->hardware_lock supposed to be held on entry */ static void qlt_undelete_sess(struct qla_tgt_sess *sess) { @@ -663,43 +567,13 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) sess = list_entry(tgt->del_sess_list.next, typeof(*sess), del_list_entry); if (time_after_eq(jiffies, sess->expires)) { - bool cancel; - qlt_undelete_sess(sess); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - cancel = qlt_check_fcport_exist(vha, sess); - - if (cancel) { - if (sess->deleted) { - /* - * sess was again deleted while we were - * discovering it - */ - spin_lock_irqsave(&ha->hardware_lock, - flags); - continue; - } - - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf049, - "qla_target(%d): cancel deletion of " - "session for port %02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x (loop ID %d), because " - " it isn't deleted by firmware", - vha->vp_idx, sess->port_name[0], - sess->port_name[1], sess->port_name[2], - sess->port_name[3], sess->port_name[4], - sess->port_name[5], sess->port_name[6], - sess->port_name[7], sess->loop_id); - } else { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, - "Timeout: sess %p about to be deleted\n", - sess); - ha->tgt.tgt_ops->shutdown_sess(sess); - ha->tgt.tgt_ops->put_sess(sess); - } - - spin_lock_irqsave(&ha->hardware_lock, flags); + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, + "Timeout: sess %p about to be deleted\n", + sess); + ha->tgt.tgt_ops->shutdown_sess(sess); + ha->tgt.tgt_ops->put_sess(sess); } else { schedule_delayed_work(&tgt->sess_del_work, jiffies - sess->expires); @@ -884,9 +758,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) sess->loop_id); sess->local = 0; } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); } void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) @@ -2706,7 +2579,9 @@ static void qlt_do_work(struct work_struct *work) /* * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( */ + spin_lock_irqsave(&ha->hardware_lock, flags); ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return; out_term: @@ -2718,9 +2593,9 @@ static void qlt_do_work(struct work_struct *work) spin_lock_irqsave(&ha->hardware_lock, flags); qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); kmem_cache_free(qla_tgt_cmd_cachep, cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); if (sess) ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); } /* ha->hardware_lock supposed to be held on entry */ @@ -4169,16 +4044,16 @@ static void qlt_abort_work(struct qla_tgt *tgt, rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); if (rc != 0) goto out_term; - spin_unlock_irqrestore(&ha->hardware_lock, flags); ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return; out_term: qlt_24xx_send_abts_resp(vha, &prm->abts, FCP_TMF_REJECTED, false); - spin_unlock_irqrestore(&ha->hardware_lock, flags); if (sess) ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); } static void qlt_tmr_work(struct qla_tgt *tgt, @@ -4226,16 +4101,16 @@ static void qlt_tmr_work(struct qla_tgt *tgt, rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); if (rc != 0) goto out_term; - spin_unlock_irqrestore(&ha->hardware_lock, flags); ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); return; out_term: qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1); - spin_unlock_irqrestore(&ha->hardware_lock, flags); if (sess) ha->tgt.tgt_ops->put_sess(sess); + spin_unlock_irqrestore(&ha->hardware_lock, flags); } static void qlt_sess_work_fn(struct work_struct *work) diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7a3870f385f6..bb7eb909f0b1 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -795,12 +795,14 @@ static void tcm_qla2xxx_put_session(struct se_session *se_sess) static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) { - tcm_qla2xxx_put_session(sess->se_sess); + assert_spin_locked(&sess->vha->hw->hardware_lock); + kref_put(&sess->se_sess->sess_kref, tcm_qla2xxx_release_session); } static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) { - tcm_qla2xxx_shutdown_session(sess->se_sess); + assert_spin_locked(&sess->vha->hw->hardware_lock); + target_sess_cmd_list_set_waiting(sess->se_sess); } static struct se_node_acl *tcm_qla2xxx_make_nodeacl( -- GitLab From 5c34c403b72395e59cad64a75fb0b772b0ab9cd4 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 20 Jun 2013 20:22:58 +0200 Subject: [PATCH 1563/2900] iommu/amd: Fix memory leak in free_pagetable The IOMMU pagetables can have up to 6 levels, but the code in free_pagetable() only releases the first 3 levels. Fix this leak by releasing all levels. Reported-by: Alex Williamson Signed-off-by: Joerg Roedel Reviewed-by: Alex Williamson --- drivers/iommu/amd_iommu.c | 73 ++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 21d02b0d907c..5cde682377a0 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1893,34 +1893,59 @@ static void domain_id_free(int id) write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); } +#define DEFINE_FREE_PT_FN(LVL, FN) \ +static void free_pt_##LVL (unsigned long __pt) \ +{ \ + unsigned long p; \ + u64 *pt; \ + int i; \ + \ + pt = (u64 *)__pt; \ + \ + for (i = 0; i < 512; ++i) { \ + if (!IOMMU_PTE_PRESENT(pt[i])) \ + continue; \ + \ + p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \ + FN(p); \ + } \ + free_page((unsigned long)pt); \ +} + +DEFINE_FREE_PT_FN(l2, free_page) +DEFINE_FREE_PT_FN(l3, free_pt_l2) +DEFINE_FREE_PT_FN(l4, free_pt_l3) +DEFINE_FREE_PT_FN(l5, free_pt_l4) +DEFINE_FREE_PT_FN(l6, free_pt_l5) + static void free_pagetable(struct protection_domain *domain) { - int i, j; - u64 *p1, *p2, *p3; - - p1 = domain->pt_root; - - if (!p1) - return; - - for (i = 0; i < 512; ++i) { - if (!IOMMU_PTE_PRESENT(p1[i])) - continue; + unsigned long root = (unsigned long)domain->pt_root; - p2 = IOMMU_PTE_PAGE(p1[i]); - for (j = 0; j < 512; ++j) { - if (!IOMMU_PTE_PRESENT(p2[j])) - continue; - p3 = IOMMU_PTE_PAGE(p2[j]); - free_page((unsigned long)p3); - } - - free_page((unsigned long)p2); + switch (domain->mode) { + case PAGE_MODE_NONE: + break; + case PAGE_MODE_1_LEVEL: + free_page(root); + break; + case PAGE_MODE_2_LEVEL: + free_pt_l2(root); + break; + case PAGE_MODE_3_LEVEL: + free_pt_l3(root); + break; + case PAGE_MODE_4_LEVEL: + free_pt_l4(root); + break; + case PAGE_MODE_5_LEVEL: + free_pt_l5(root); + break; + case PAGE_MODE_6_LEVEL: + free_pt_l6(root); + break; + default: + BUG(); } - - free_page((unsigned long)p1); - - domain->pt_root = NULL; } static void free_gcr3_tbl_level1(u64 *tbl) -- GitLab From fbaa1a6d852aa6878059acb18cbc336746795a56 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:21 -0700 Subject: [PATCH 1564/2900] RDMA/cma: Merge cma_get/save_net_info With the removal of SDP related code, we can merge cma_get_net_info() with cma_save_net_info(), since we're only ever dealing with a single header format. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 124 +++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 55 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index daec9319502d..112a192eae9c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -810,59 +810,87 @@ static inline int cma_any_port(struct sockaddr *addr) return !cma_port(addr); } -static int cma_get_net_info(void *hdr, enum rdma_port_space ps, - u8 *ip_ver, __be16 *port, - union cma_ip_addr **src, union cma_ip_addr **dst) +static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct ib_sa_path_rec *path) { - if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) - return -EINVAL; + struct sockaddr_ib *listen_ib, *ib; - *ip_ver = cma_get_ip_ver(hdr); - *port = ((struct cma_hdr *) hdr)->port; - *src = &((struct cma_hdr *) hdr)->src_addr; - *dst = &((struct cma_hdr *) hdr)->dst_addr; + listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr; + ib = (struct sockaddr_ib *) &id->route.addr.src_addr; + ib->sib_family = listen_ib->sib_family; + ib->sib_pkey = path->pkey; + ib->sib_flowinfo = path->flow_label; + memcpy(&ib->sib_addr, &path->sgid, 16); + ib->sib_sid = listen_ib->sib_sid; + ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL); + ib->sib_scope_id = listen_ib->sib_scope_id; - if (*ip_ver != 4 && *ip_ver != 6) - return -EINVAL; - return 0; + ib = (struct sockaddr_ib *) &id->route.addr.dst_addr; + ib->sib_family = listen_ib->sib_family; + ib->sib_pkey = path->pkey; + ib->sib_flowinfo = path->flow_label; + memcpy(&ib->sib_addr, &path->dgid, 16); } -static void cma_save_net_info(struct rdma_addr *addr, - struct rdma_addr *listen_addr, - u8 ip_ver, __be16 port, - union cma_ip_addr *src, union cma_ip_addr *dst) +static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) { struct sockaddr_in *listen4, *ip4; + + listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr; + ip4 = (struct sockaddr_in *) &id->route.addr.src_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; + ip4->sin_port = listen4->sin_port; + + ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; + ip4->sin_port = hdr->port; +} + +static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct cma_hdr *hdr) +{ struct sockaddr_in6 *listen6, *ip6; - switch (ip_ver) { + listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr; + ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = hdr->dst_addr.ip6; + ip6->sin6_port = listen6->sin6_port; + + ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = hdr->src_addr.ip6; + ip6->sin6_port = hdr->port; +} + +static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, + struct ib_cm_event *ib_event) +{ + struct cma_hdr *hdr; + + if (listen_id->route.addr.src_addr.ss_family == AF_IB) { + cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path); + return 0; + } + + hdr = ib_event->private_data; + if (hdr->cma_version != CMA_VERSION) + return -EINVAL; + + switch (cma_get_ip_ver(hdr)) { case 4: - listen4 = (struct sockaddr_in *) &listen_addr->src_addr; - ip4 = (struct sockaddr_in *) &addr->src_addr; - ip4->sin_family = listen4->sin_family; - ip4->sin_addr.s_addr = dst->ip4.addr; - ip4->sin_port = listen4->sin_port; - - ip4 = (struct sockaddr_in *) &addr->dst_addr; - ip4->sin_family = listen4->sin_family; - ip4->sin_addr.s_addr = src->ip4.addr; - ip4->sin_port = port; + cma_save_ip4_info(id, listen_id, hdr); break; case 6: - listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr; - ip6 = (struct sockaddr_in6 *) &addr->src_addr; - ip6->sin6_family = listen6->sin6_family; - ip6->sin6_addr = dst->ip6; - ip6->sin6_port = listen6->sin6_port; - - ip6 = (struct sockaddr_in6 *) &addr->dst_addr; - ip6->sin6_family = listen6->sin6_family; - ip6->sin6_addr = src->ip6; - ip6->sin6_port = port; + cma_save_ip6_info(id, listen_id, hdr); break; default: - break; + return -EINVAL; } + return 0; } static inline int cma_user_data_offset(enum rdma_port_space ps) @@ -1129,23 +1157,16 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, struct rdma_id_private *id_priv; struct rdma_cm_id *id; struct rdma_route *rt; - union cma_ip_addr *src, *dst; - __be16 port; - u8 ip_ver; int ret; - if (cma_get_net_info(ib_event->private_data, listen_id->ps, - &ip_ver, &port, &src, &dst)) - return NULL; - id = rdma_create_id(listen_id->event_handler, listen_id->context, listen_id->ps, ib_event->param.req_rcvd.qp_type); if (IS_ERR(id)) return NULL; id_priv = container_of(id, struct rdma_id_private, id); - cma_save_net_info(&id->route.addr, &listen_id->route.addr, - ip_ver, port, src, dst); + if (cma_save_net_info(id, listen_id, ib_event)) + goto err; rt = &id->route; rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; @@ -1182,9 +1203,6 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, { struct rdma_id_private *id_priv; struct rdma_cm_id *id; - union cma_ip_addr *src, *dst; - __be16 port; - u8 ip_ver; int ret; id = rdma_create_id(listen_id->event_handler, listen_id->context, @@ -1193,13 +1211,9 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, return NULL; id_priv = container_of(id, struct rdma_id_private, id); - if (cma_get_net_info(ib_event->private_data, listen_id->ps, - &ip_ver, &port, &src, &dst)) + if (cma_save_net_info(id, listen_id, ib_event)) goto err; - cma_save_net_info(&id->route.addr, &listen_id->route.addr, - ip_ver, port, src, dst); - if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { ret = cma_translate_addr(cma_src_addr(id_priv), &id->route.addr.dev_addr); if (ret) -- GitLab From e8160e15930969de709ba9b46df9571448b78ce5 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:22 -0700 Subject: [PATCH 1565/2900] RDMA/cma: Expose private data when using AF_IB If the source or destination address is AF_IB, then do not reserve a portion of the private data in the IB CM REQ or SIDR REQ messages for the cma header. Instead, all private data should be exported to the user. When AF_IB is used, the rdma cm does not have sufficient information to fill in the cma header. Additionally, this will be necessary to support any IB connection through the rdma cm interface, Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 56 +++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 112a192eae9c..7a9b033e37ce 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -893,9 +893,9 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id return 0; } -static inline int cma_user_data_offset(enum rdma_port_space ps) +static inline int cma_user_data_offset(struct rdma_id_private *id_priv) { - return sizeof(struct cma_hdr); + return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); } static void cma_cancel_route(struct rdma_id_private *id_priv) @@ -1265,7 +1265,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) return -ECONNABORTED; memset(&event, 0, sizeof event); - offset = cma_user_data_offset(listen_id->id.ps); + offset = cma_user_data_offset(listen_id); event.event = RDMA_CM_EVENT_CONNECT_REQUEST; if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) { conn_id = cma_new_udp_id(&listen_id->id, ib_event); @@ -2585,7 +2585,7 @@ static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv) cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; cma_hdr->port = src4->sin_port; - } else { + } else if (cma_family(id_priv) == AF_INET6) { struct sockaddr_in6 *src6, *dst6; src6 = (struct sockaddr_in6 *) cma_src_addr(id_priv); @@ -2668,24 +2668,30 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, { struct ib_cm_sidr_req_param req; struct ib_cm_id *id; - int ret; + int offset, ret; - req.private_data_len = sizeof(struct cma_hdr) + - conn_param->private_data_len; + offset = cma_user_data_offset(id_priv); + req.private_data_len = offset + conn_param->private_data_len; if (req.private_data_len < conn_param->private_data_len) return -EINVAL; - req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC); - if (!req.private_data) - return -ENOMEM; + if (req.private_data_len) { + req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC); + if (!req.private_data) + return -ENOMEM; + } else { + req.private_data = NULL; + } if (conn_param->private_data && conn_param->private_data_len) - memcpy((void *) req.private_data + sizeof(struct cma_hdr), + memcpy((void *) req.private_data + offset, conn_param->private_data, conn_param->private_data_len); - ret = cma_format_hdr((void *) req.private_data, id_priv); - if (ret) - goto out; + if (req.private_data) { + ret = cma_format_hdr((void *) req.private_data, id_priv); + if (ret) + goto out; + } id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler, id_priv); @@ -2720,14 +2726,18 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, int offset, ret; memset(&req, 0, sizeof req); - offset = cma_user_data_offset(id_priv->id.ps); + offset = cma_user_data_offset(id_priv); req.private_data_len = offset + conn_param->private_data_len; if (req.private_data_len < conn_param->private_data_len) return -EINVAL; - private_data = kzalloc(req.private_data_len, GFP_ATOMIC); - if (!private_data) - return -ENOMEM; + if (req.private_data_len) { + private_data = kzalloc(req.private_data_len, GFP_ATOMIC); + if (!private_data) + return -ENOMEM; + } else { + private_data = NULL; + } if (conn_param->private_data && conn_param->private_data_len) memcpy(private_data + offset, conn_param->private_data, @@ -2741,10 +2751,12 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, id_priv->cm_id.ib = id; route = &id_priv->id.route; - ret = cma_format_hdr(private_data, id_priv); - if (ret) - goto out; - req.private_data = private_data; + if (private_data) { + ret = cma_format_hdr(private_data, id_priv); + if (ret) + goto out; + req.private_data = private_data; + } req.primary_path = &route->path_rec[0]; if (route->num_paths == 2) -- GitLab From 5c438135adf90b33cb00e5351becf1e557bbdd9d Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:23 -0700 Subject: [PATCH 1566/2900] RDMA/cma: Set qkey for AF_IB Allow the user to specify the qkey when using AF_IB. The qkey is added to struct rdma_ucm_conn_param in place of a reserved field, but for backwards compatability, is only accessed if the associated rdma_cm_id is using AF_IB. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 35 +++++++++++++++++++------------- drivers/infiniband/core/ucma.c | 8 +++++--- include/rdma/rdma_cm.h | 1 + include/uapi/rdma/rdma_user_cm.h | 2 +- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 7a9b033e37ce..96d0b9a6e15e 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -293,16 +293,25 @@ static inline unsigned short cma_family(struct rdma_id_private *id_priv) return id_priv->id.route.addr.src_addr.ss_family; } -static int cma_set_qkey(struct rdma_id_private *id_priv) +static int cma_set_qkey(struct rdma_id_private *id_priv, u32 qkey) { struct ib_sa_mcmember_rec rec; int ret = 0; - if (id_priv->qkey) + if (id_priv->qkey) { + if (qkey && id_priv->qkey != qkey) + return -EINVAL; return 0; + } + + if (qkey) { + id_priv->qkey = qkey; + return 0; + } switch (id_priv->id.ps) { case RDMA_PS_UDP: + case RDMA_PS_IB: id_priv->qkey = RDMA_UDP_QKEY; break; case RDMA_PS_IPOIB: @@ -689,7 +698,7 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv, *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT; if (id_priv->id.qp_type == IB_QPT_UD) { - ret = cma_set_qkey(id_priv); + ret = cma_set_qkey(id_priv, 0); if (ret) return ret; @@ -2624,15 +2633,10 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id, event.status = ib_event->param.sidr_rep_rcvd.status; break; } - ret = cma_set_qkey(id_priv); + ret = cma_set_qkey(id_priv, rep->qkey); if (ret) { event.event = RDMA_CM_EVENT_ADDR_ERROR; - event.status = -EINVAL; - break; - } - if (id_priv->qkey != rep->qkey) { - event.event = RDMA_CM_EVENT_UNREACHABLE; - event.status = -EINVAL; + event.status = ret; break; } ib_init_ah_from_path(id_priv->id.device, id_priv->id.port_num, @@ -2922,7 +2926,7 @@ static int cma_accept_iw(struct rdma_id_private *id_priv, } static int cma_send_sidr_rep(struct rdma_id_private *id_priv, - enum ib_cm_sidr_status status, + enum ib_cm_sidr_status status, u32 qkey, const void *private_data, int private_data_len) { struct ib_cm_sidr_rep_param rep; @@ -2931,7 +2935,7 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv, memset(&rep, 0, sizeof rep); rep.status = status; if (status == IB_SIDR_SUCCESS) { - ret = cma_set_qkey(id_priv); + ret = cma_set_qkey(id_priv, qkey); if (ret) return ret; rep.qp_num = id_priv->qp_num; @@ -2965,11 +2969,12 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) if (id->qp_type == IB_QPT_UD) { if (conn_param) ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, + conn_param->qkey, conn_param->private_data, conn_param->private_data_len); else ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, - NULL, 0); + 0, NULL, 0); } else { if (conn_param) ret = cma_accept_ib(id_priv, conn_param); @@ -3030,7 +3035,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, switch (rdma_node_get_transport(id->device->node_type)) { case RDMA_TRANSPORT_IB: if (id->qp_type == IB_QPT_UD) - ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, + ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT, 0, private_data, private_data_len); else ret = ib_send_cm_rej(id_priv->cm_id.ib, @@ -3091,6 +3096,8 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) cma_disable_callback(id_priv, RDMA_CM_ADDR_RESOLVED)) return 0; + if (!status) + status = cma_set_qkey(id_priv, be32_to_cpu(multicast->rec.qkey)); mutex_lock(&id_priv->qp_mutex); if (!status && id_priv->id.qp) status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid, diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 5ca44cd9b00c..e813774bf7a7 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -709,7 +709,8 @@ static ssize_t ucma_query_route(struct ucma_file *file, return ret; } -static void ucma_copy_conn_param(struct rdma_conn_param *dst, +static void ucma_copy_conn_param(struct rdma_cm_id *id, + struct rdma_conn_param *dst, struct rdma_ucm_conn_param *src) { dst->private_data = src->private_data; @@ -721,6 +722,7 @@ static void ucma_copy_conn_param(struct rdma_conn_param *dst, dst->rnr_retry_count = src->rnr_retry_count; dst->srq = src->srq; dst->qp_num = src->qp_num; + dst->qkey = (id->route.addr.src_addr.ss_family == AF_IB) ? src->qkey : 0; } static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf, @@ -741,7 +743,7 @@ static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf, if (IS_ERR(ctx)) return PTR_ERR(ctx); - ucma_copy_conn_param(&conn_param, &cmd.conn_param); + ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param); ret = rdma_connect(ctx->cm_id, &conn_param); ucma_put_ctx(ctx); return ret; @@ -784,7 +786,7 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf, return PTR_ERR(ctx); if (cmd.conn_param.valid) { - ucma_copy_conn_param(&conn_param, &cmd.conn_param); + ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param); mutex_lock(&file->mut); ret = rdma_accept(ctx->cm_id, &conn_param); if (!ret) diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index 1e6c3c7af898..966f90ba8d8a 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -98,6 +98,7 @@ struct rdma_conn_param { /* Fields below ignored if a QP is created on the rdma_cm_id. */ u8 srq; u32 qp_num; + u32 qkey; }; struct rdma_ud_param { diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 1ee9239ff8c2..29de08f603ac 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -131,7 +131,7 @@ struct rdma_ucm_query_route_resp { struct rdma_ucm_conn_param { __u32 qp_num; - __u32 reserved; + __u32 qkey; __u8 private_data[RDMA_MAX_PRIVATE_DATA]; __u8 private_data_len; __u8 srq; -- GitLab From 94d0c939416480066d4e4d69e0d3c217bc083cea Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:24 -0700 Subject: [PATCH 1567/2900] RDMA/cma: Only listen on IB devices when using AF_IB If an rdma_cm_id is bound to AF_IB, with a wild card address, only listen on IB devices. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 96d0b9a6e15e..6a0ee9265015 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1616,6 +1616,10 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv, struct rdma_cm_id *id; int ret; + if (cma_family(id_priv) == AF_IB && + rdma_node_get_transport(cma_dev->device->node_type) != RDMA_TRANSPORT_IB) + return; + id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps, id_priv->id.qp_type); if (IS_ERR(id)) -- GitLab From ee7aed4528fb3c44a36abd79eb23fd5401a5b697 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:25 -0700 Subject: [PATCH 1568/2900] RDMA/ucma: Support querying for AF_IB addresses The sockaddr structure for AF_IB is larger than sockaddr_in6. The rdma cm user space ABI uses the latter to exchange address information between user space and the kernel. To support querying for larger addresses, define a new query command that exchanges data using sockaddr_storage, rather than sockaddr_in6. Unlike the existing query_route command, the new command only returns address information. Route (i.e. path record) data is separated. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 76 +++++++++++++++++++++++++++++++- include/uapi/rdma/rdma_user_cm.h | 22 +++++++-- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index e813774bf7a7..18bdccc0c2ec 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -47,6 +47,7 @@ #include #include #include +#include MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); @@ -649,7 +650,7 @@ static ssize_t ucma_query_route(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) { - struct rdma_ucm_query_route cmd; + struct rdma_ucm_query cmd; struct rdma_ucm_query_route_resp resp; struct ucma_context *ctx; struct sockaddr *addr; @@ -709,6 +710,76 @@ static ssize_t ucma_query_route(struct ucma_file *file, return ret; } +static void ucma_query_device_addr(struct rdma_cm_id *cm_id, + struct rdma_ucm_query_addr_resp *resp) +{ + if (!cm_id->device) + return; + + resp->node_guid = (__force __u64) cm_id->device->node_guid; + resp->port_num = cm_id->port_num; + resp->pkey = (__force __u16) cpu_to_be16( + ib_addr_get_pkey(&cm_id->route.addr.dev_addr)); +} + +static ssize_t ucma_query_addr(struct ucma_context *ctx, + void __user *response, int out_len) +{ + struct rdma_ucm_query_addr_resp resp; + struct sockaddr *addr; + int ret = 0; + + if (out_len < sizeof(resp)) + return -ENOSPC; + + memset(&resp, 0, sizeof resp); + + addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr; + resp.src_size = rdma_addr_size(addr); + memcpy(&resp.src_addr, addr, resp.src_size); + + addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr; + resp.dst_size = rdma_addr_size(addr); + memcpy(&resp.dst_addr, addr, resp.dst_size); + + ucma_query_device_addr(ctx->cm_id, &resp); + + if (copy_to_user(response, &resp, sizeof(resp))) + ret = -EFAULT; + + return ret; +} + +static ssize_t ucma_query(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) +{ + struct rdma_ucm_query cmd; + struct ucma_context *ctx; + void __user *response; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + + response = (void __user *)(unsigned long) cmd.response; + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + switch (cmd.option) { + case RDMA_USER_CM_QUERY_ADDR: + ret = ucma_query_addr(ctx, response, out_len); + break; + default: + ret = -ENOSYS; + break; + } + + ucma_put_ctx(ctx); + return ret; +} + static void ucma_copy_conn_param(struct rdma_cm_id *id, struct rdma_conn_param *dst, struct rdma_ucm_conn_param *src) @@ -1241,7 +1312,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast, [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, - [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id + [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, + [RDMA_USER_CM_CMD_QUERY] = ucma_query }; static ssize_t ucma_write(struct file *filp, const char __user *buf, diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 29de08f603ac..3ea7e7a4d54b 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -61,7 +61,8 @@ enum { RDMA_USER_CM_CMD_NOTIFY, RDMA_USER_CM_CMD_JOIN_MCAST, RDMA_USER_CM_CMD_LEAVE_MCAST, - RDMA_USER_CM_CMD_MIGRATE_ID + RDMA_USER_CM_CMD_MIGRATE_ID, + RDMA_USER_CM_CMD_QUERY }; /* @@ -113,10 +114,14 @@ struct rdma_ucm_resolve_route { __u32 timeout_ms; }; -struct rdma_ucm_query_route { +enum { + RDMA_USER_CM_QUERY_ADDR +}; + +struct rdma_ucm_query { __u64 response; __u32 id; - __u32 reserved; + __u32 option; }; struct rdma_ucm_query_route_resp { @@ -129,6 +134,17 @@ struct rdma_ucm_query_route_resp { __u8 reserved[3]; }; +struct rdma_ucm_query_addr_resp { + __u64 node_guid; + __u8 port_num; + __u8 reserved; + __u16 pkey; + __u16 src_size; + __u16 dst_size; + struct sockaddr_storage src_addr; + struct sockaddr_storage dst_addr; +}; + struct rdma_ucm_conn_param { __u32 qp_num; __u32 qkey; -- GitLab From 2e08b5879e9244fa893fe09f5b887f72f4e6c29b Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:26 -0700 Subject: [PATCH 1569/2900] IB/sa: Export function to pack a path record into wire format Allow converting from struct ib_sa_path_rec to the IB defined SA path record wire format. This will be used to report path data from the rdma cm into user space. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/sa_query.c | 6 ++++++ include/rdma/ib_sa.h | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 934f45e79e5e..9838ca484389 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -652,6 +652,12 @@ void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec) } EXPORT_SYMBOL(ib_sa_unpack_path); +void ib_sa_pack_path(struct ib_sa_path_rec *rec, void *attribute) +{ + ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, attribute); +} +EXPORT_SYMBOL(ib_sa_pack_path); + static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query, int status, struct ib_sa_mad *mad) diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index 8275e539bace..125f8714301d 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h @@ -401,6 +401,12 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr); +/** + * ib_sa_pack_path - Conert a path record from struct ib_sa_path_rec + * to IB MAD wire format. + */ +void ib_sa_pack_path(struct ib_sa_path_rec *rec, void *attribute); + /** * ib_sa_unpack_path - Convert a path record from MAD format to struct * ib_sa_path_rec. @@ -418,4 +424,5 @@ int ib_sa_guid_info_rec_query(struct ib_sa_client *client, void *context), void *context, struct ib_sa_query **sa_query); + #endif /* IB_SA_H */ -- GitLab From ac53b264b2f39e89781e3b855008123dfdb44aea Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:27 -0700 Subject: [PATCH 1570/2900] RDMA/ucma: Support querying when IB paths are not reversible The current query_route call can return up to two path records. The assumption being that one is the primary path, with optional support for an alternate path. In both cases, the paths are assumed to be reversible and are used to send CM MADs. With the ability to manually set IB path data, the rdma cm can eventually be capable of using up to 6 paths per connection: forward primary, reverse primary, forward alternate, reverse alternate, reversible primary path for CM MADs reversible alternate path for CM MADs. (It is unclear at this time if IB routing will complicate this) In order to handle more flexible routing topologies, add a new command to report any number of paths. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 35 ++++++++++++++++++++++++++++++++ include/uapi/rdma/rdma_user_cm.h | 9 +++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 18bdccc0c2ec..722f2ff0400f 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -750,6 +750,38 @@ static ssize_t ucma_query_addr(struct ucma_context *ctx, return ret; } +static ssize_t ucma_query_path(struct ucma_context *ctx, + void __user *response, int out_len) +{ + struct rdma_ucm_query_path_resp *resp; + int i, ret = 0; + + if (out_len < sizeof(*resp)) + return -ENOSPC; + + resp = kzalloc(out_len, GFP_KERNEL); + if (!resp) + return -ENOMEM; + + resp->num_paths = ctx->cm_id->route.num_paths; + for (i = 0, out_len -= sizeof(*resp); + i < resp->num_paths && out_len > sizeof(struct ib_path_rec_data); + i++, out_len -= sizeof(struct ib_path_rec_data)) { + + resp->path_data[i].flags = IB_PATH_GMP | IB_PATH_PRIMARY | + IB_PATH_BIDIRECTIONAL; + ib_sa_pack_path(&ctx->cm_id->route.path_rec[i], + &resp->path_data[i].path_rec); + } + + if (copy_to_user(response, resp, + sizeof(*resp) + (i * sizeof(struct ib_path_rec_data)))) + ret = -EFAULT; + + kfree(resp); + return ret; +} + static ssize_t ucma_query(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -771,6 +803,9 @@ static ssize_t ucma_query(struct ucma_file *file, case RDMA_USER_CM_QUERY_ADDR: ret = ucma_query_addr(ctx, response, out_len); break; + case RDMA_USER_CM_QUERY_PATH: + ret = ucma_query_path(ctx, response, out_len); + break; default: ret = -ENOSYS; break; diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 3ea7e7a4d54b..07eb6cfa926c 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -115,7 +115,8 @@ struct rdma_ucm_resolve_route { }; enum { - RDMA_USER_CM_QUERY_ADDR + RDMA_USER_CM_QUERY_ADDR, + RDMA_USER_CM_QUERY_PATH }; struct rdma_ucm_query { @@ -145,6 +146,12 @@ struct rdma_ucm_query_addr_resp { struct sockaddr_storage dst_addr; }; +struct rdma_ucm_query_path_resp { + __u32 num_paths; + __u32 reserved; + struct ib_path_rec_data path_data[0]; +}; + struct rdma_ucm_conn_param { __u32 qp_num; __u32 qkey; -- GitLab From cf53936f229d81131fef475919f163ce566a205f Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:28 -0700 Subject: [PATCH 1571/2900] RDMA/cma: Export cma_get_service_id() Allow the rdma_ucm to query the IB service ID formed or allocated by the rdma_cm by exporting the cma_get_service_id() functionality. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 13 +++++++------ include/rdma/rdma_cm.h | 7 +++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 6a0ee9265015..32d74c76e638 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1336,13 +1336,14 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) return ret; } -static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr) +__be64 rdma_get_service_id(struct rdma_cm_id *id, struct sockaddr *addr) { if (addr->sa_family == AF_IB) return ((struct sockaddr_ib *) addr)->sib_sid; - return cpu_to_be64(((u64)ps << 16) + be16_to_cpu(cma_port(addr))); + return cpu_to_be64(((u64)id->ps << 16) + be16_to_cpu(cma_port(addr))); } +EXPORT_SYMBOL(rdma_get_service_id); static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, struct ib_cm_compare_data *compare) @@ -1556,7 +1557,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv) id_priv->cm_id.ib = id; addr = cma_src_addr(id_priv); - svc_id = cma_get_service_id(id_priv->id.ps, addr); + svc_id = rdma_get_service_id(&id_priv->id, addr); if (cma_any_addr(addr) && !id_priv->afonly) ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); else { @@ -1699,7 +1700,7 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); path_rec.numb_path = 1; path_rec.reversible = 1; - path_rec.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); + path_rec.service_id = rdma_get_service_id(&id_priv->id, cma_dst_addr(id_priv)); comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH | @@ -2710,7 +2711,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, id_priv->cm_id.ib = id; req.path = id_priv->id.route.path_rec; - req.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); + req.service_id = rdma_get_service_id(&id_priv->id, cma_dst_addr(id_priv)); req.timeout_ms = 1 << (CMA_CM_RESPONSE_TIMEOUT - 8); req.max_cm_retries = CMA_MAX_CM_RETRIES; @@ -2770,7 +2771,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, if (route->num_paths == 2) req.alternate_path = &route->path_rec[1]; - req.service_id = cma_get_service_id(id_priv->id.ps, cma_dst_addr(id_priv)); + req.service_id = rdma_get_service_id(&id_priv->id, cma_dst_addr(id_priv)); req.qp_num = id_priv->qp_num; req.qp_type = id_priv->id.qp_type; req.starting_psn = id_priv->seq_num; diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index 966f90ba8d8a..1ed2088dc9f5 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -373,4 +373,11 @@ int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse); */ int rdma_set_afonly(struct rdma_cm_id *id, int afonly); + /** + * rdma_get_service_id - Return the IB service ID for a specified address. + * @id: Communication identifier associated with the address. + * @addr: Address for the service ID. + */ +__be64 rdma_get_service_id(struct rdma_cm_id *id, struct sockaddr *addr); + #endif /* RDMA_CM_H */ -- GitLab From edaa7a5578988bcf12f68f14fb002bc0c87e2801 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:29 -0700 Subject: [PATCH 1572/2900] RDMA/ucma: Add ability to query GID addresses Part of address resolution is mapping IP addresses to IB GIDs. With the changes to support querying larger addresses and more path records, also provide a way to query IB GIDs after resolution completes. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 50 ++++++++++++++++++++++++++++++++ include/uapi/rdma/rdma_user_cm.h | 3 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 722f2ff0400f..45bb052f573e 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -48,6 +48,7 @@ #include #include #include +#include MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); @@ -782,6 +783,52 @@ static ssize_t ucma_query_path(struct ucma_context *ctx, return ret; } +static ssize_t ucma_query_gid(struct ucma_context *ctx, + void __user *response, int out_len) +{ + struct rdma_ucm_query_addr_resp resp; + struct sockaddr_ib *addr; + int ret = 0; + + if (out_len < sizeof(resp)) + return -ENOSPC; + + memset(&resp, 0, sizeof resp); + + ucma_query_device_addr(ctx->cm_id, &resp); + + addr = (struct sockaddr_ib *) &resp.src_addr; + resp.src_size = sizeof(*addr); + if (ctx->cm_id->route.addr.src_addr.ss_family == AF_IB) { + memcpy(addr, &ctx->cm_id->route.addr.src_addr, resp.src_size); + } else { + addr->sib_family = AF_IB; + addr->sib_pkey = (__force __be16) resp.pkey; + rdma_addr_get_sgid(&ctx->cm_id->route.addr.dev_addr, + (union ib_gid *) &addr->sib_addr); + addr->sib_sid = rdma_get_service_id(ctx->cm_id, (struct sockaddr *) + &ctx->cm_id->route.addr.src_addr); + } + + addr = (struct sockaddr_ib *) &resp.dst_addr; + resp.dst_size = sizeof(*addr); + if (ctx->cm_id->route.addr.dst_addr.ss_family == AF_IB) { + memcpy(addr, &ctx->cm_id->route.addr.dst_addr, resp.dst_size); + } else { + addr->sib_family = AF_IB; + addr->sib_pkey = (__force __be16) resp.pkey; + rdma_addr_get_dgid(&ctx->cm_id->route.addr.dev_addr, + (union ib_gid *) &addr->sib_addr); + addr->sib_sid = rdma_get_service_id(ctx->cm_id, (struct sockaddr *) + &ctx->cm_id->route.addr.dst_addr); + } + + if (copy_to_user(response, &resp, sizeof(resp))) + ret = -EFAULT; + + return ret; +} + static ssize_t ucma_query(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -806,6 +853,9 @@ static ssize_t ucma_query(struct ucma_file *file, case RDMA_USER_CM_QUERY_PATH: ret = ucma_query_path(ctx, response, out_len); break; + case RDMA_USER_CM_QUERY_GID: + ret = ucma_query_gid(ctx, response, out_len); + break; default: ret = -ENOSYS; break; diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 07eb6cfa926c..ea79253ceb13 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -116,7 +116,8 @@ struct rdma_ucm_resolve_route { enum { RDMA_USER_CM_QUERY_ADDR, - RDMA_USER_CM_QUERY_PATH + RDMA_USER_CM_QUERY_PATH, + RDMA_USER_CM_QUERY_GID }; struct rdma_ucm_query { -- GitLab From 05ad94577ecd5a101889d04aa099b738ec5ee34f Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:30 -0700 Subject: [PATCH 1573/2900] RDMA/ucma: Name changes to indicate only IP addresses supported Several commands into the RDMA CM from user space are restricted to supporting addresses which fit into a sockaddr_in6 structure: bind address, resolve address, and join multicast. With the addition of AF_IB, we need to support addresses which are larger than sockaddr_in6. This will be done by adding new commands that exchange address information using sockaddr_storage. However, to support existing applications, we maintain the current commands and structures, but rename them to indicate that they only support IPv4 and v6 addresses. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 60 ++++++++++++++++---------------- include/uapi/rdma/rdma_user_cm.h | 12 +++---- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 45bb052f573e..82fb1e6e1384 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -512,10 +512,10 @@ static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf, return ret; } -static ssize_t ucma_bind_addr(struct ucma_file *file, const char __user *inbuf, +static ssize_t ucma_bind_ip(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) { - struct rdma_ucm_bind_addr cmd; + struct rdma_ucm_bind_ip cmd; struct ucma_context *ctx; int ret; @@ -531,11 +531,11 @@ static ssize_t ucma_bind_addr(struct ucma_file *file, const char __user *inbuf, return ret; } -static ssize_t ucma_resolve_addr(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) +static ssize_t ucma_resolve_ip(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) { - struct rdma_ucm_resolve_addr cmd; + struct rdma_ucm_resolve_ip cmd; struct ucma_context *ctx; int ret; @@ -1178,11 +1178,11 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf, return ret; } -static ssize_t ucma_join_multicast(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) +static ssize_t ucma_join_ip_multicast(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) { - struct rdma_ucm_join_mcast cmd; + struct rdma_ucm_join_ip_mcast cmd; struct rdma_ucm_create_id_resp resp; struct ucma_context *ctx; struct ucma_multicast *mc; @@ -1379,26 +1379,26 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file, static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) = { - [RDMA_USER_CM_CMD_CREATE_ID] = ucma_create_id, - [RDMA_USER_CM_CMD_DESTROY_ID] = ucma_destroy_id, - [RDMA_USER_CM_CMD_BIND_ADDR] = ucma_bind_addr, - [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr, - [RDMA_USER_CM_CMD_RESOLVE_ROUTE]= ucma_resolve_route, - [RDMA_USER_CM_CMD_QUERY_ROUTE] = ucma_query_route, - [RDMA_USER_CM_CMD_CONNECT] = ucma_connect, - [RDMA_USER_CM_CMD_LISTEN] = ucma_listen, - [RDMA_USER_CM_CMD_ACCEPT] = ucma_accept, - [RDMA_USER_CM_CMD_REJECT] = ucma_reject, - [RDMA_USER_CM_CMD_DISCONNECT] = ucma_disconnect, - [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr, - [RDMA_USER_CM_CMD_GET_EVENT] = ucma_get_event, - [RDMA_USER_CM_CMD_GET_OPTION] = NULL, - [RDMA_USER_CM_CMD_SET_OPTION] = ucma_set_option, - [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, - [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast, - [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, - [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, - [RDMA_USER_CM_CMD_QUERY] = ucma_query + [RDMA_USER_CM_CMD_CREATE_ID] = ucma_create_id, + [RDMA_USER_CM_CMD_DESTROY_ID] = ucma_destroy_id, + [RDMA_USER_CM_CMD_BIND_IP] = ucma_bind_ip, + [RDMA_USER_CM_CMD_RESOLVE_IP] = ucma_resolve_ip, + [RDMA_USER_CM_CMD_RESOLVE_ROUTE] = ucma_resolve_route, + [RDMA_USER_CM_CMD_QUERY_ROUTE] = ucma_query_route, + [RDMA_USER_CM_CMD_CONNECT] = ucma_connect, + [RDMA_USER_CM_CMD_LISTEN] = ucma_listen, + [RDMA_USER_CM_CMD_ACCEPT] = ucma_accept, + [RDMA_USER_CM_CMD_REJECT] = ucma_reject, + [RDMA_USER_CM_CMD_DISCONNECT] = ucma_disconnect, + [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr, + [RDMA_USER_CM_CMD_GET_EVENT] = ucma_get_event, + [RDMA_USER_CM_CMD_GET_OPTION] = NULL, + [RDMA_USER_CM_CMD_SET_OPTION] = ucma_set_option, + [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, + [RDMA_USER_CM_CMD_JOIN_IP_MCAST] = ucma_join_ip_multicast, + [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, + [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, + [RDMA_USER_CM_CMD_QUERY] = ucma_query }; static ssize_t ucma_write(struct file *filp, const char __user *buf, diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index ea79253ceb13..79f68f7c9fd2 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -45,8 +45,8 @@ enum { RDMA_USER_CM_CMD_CREATE_ID, RDMA_USER_CM_CMD_DESTROY_ID, - RDMA_USER_CM_CMD_BIND_ADDR, - RDMA_USER_CM_CMD_RESOLVE_ADDR, + RDMA_USER_CM_CMD_BIND_IP, + RDMA_USER_CM_CMD_RESOLVE_IP, RDMA_USER_CM_CMD_RESOLVE_ROUTE, RDMA_USER_CM_CMD_QUERY_ROUTE, RDMA_USER_CM_CMD_CONNECT, @@ -59,7 +59,7 @@ enum { RDMA_USER_CM_CMD_GET_OPTION, RDMA_USER_CM_CMD_SET_OPTION, RDMA_USER_CM_CMD_NOTIFY, - RDMA_USER_CM_CMD_JOIN_MCAST, + RDMA_USER_CM_CMD_JOIN_IP_MCAST, RDMA_USER_CM_CMD_LEAVE_MCAST, RDMA_USER_CM_CMD_MIGRATE_ID, RDMA_USER_CM_CMD_QUERY @@ -96,13 +96,13 @@ struct rdma_ucm_destroy_id_resp { __u32 events_reported; }; -struct rdma_ucm_bind_addr { +struct rdma_ucm_bind_ip { __u64 response; struct sockaddr_in6 addr; __u32 id; }; -struct rdma_ucm_resolve_addr { +struct rdma_ucm_resolve_ip { struct sockaddr_in6 src_addr; struct sockaddr_in6 dst_addr; __u32 id; @@ -216,7 +216,7 @@ struct rdma_ucm_notify { __u32 event; }; -struct rdma_ucm_join_mcast { +struct rdma_ucm_join_ip_mcast { __u64 response; /* rdma_ucm_create_id_resp */ __u64 uid; struct sockaddr_in6 addr; -- GitLab From eebe4c3a62aadb64ba30bde97b96d656e369d934 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:31 -0700 Subject: [PATCH 1574/2900] RDMA/ucma: Allow user space to bind to AF_IB Support user space binding to addresses using AF_IB. Since sockaddr_ib is larger than sockaddr_in6, we need to define a larger structure when binding using AF_IB. This time we use sockaddr_storage to cover future cases. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 27 ++++++++++++++++++++++++++- include/uapi/rdma/rdma_user_cm.h | 10 +++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 82fb1e6e1384..22ed97ef7da3 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -531,6 +531,30 @@ static ssize_t ucma_bind_ip(struct ucma_file *file, const char __user *inbuf, return ret; } +static ssize_t ucma_bind(struct ucma_file *file, const char __user *inbuf, + int in_len, int out_len) +{ + struct rdma_ucm_bind cmd; + struct sockaddr *addr; + struct ucma_context *ctx; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + + addr = (struct sockaddr *) &cmd.addr; + if (cmd.reserved || !cmd.addr_size || (cmd.addr_size != rdma_addr_size(addr))) + return -EINVAL; + + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = rdma_bind_addr(ctx->cm_id, addr); + ucma_put_ctx(ctx); + return ret; +} + static ssize_t ucma_resolve_ip(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -1398,7 +1422,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, [RDMA_USER_CM_CMD_JOIN_IP_MCAST] = ucma_join_ip_multicast, [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, - [RDMA_USER_CM_CMD_QUERY] = ucma_query + [RDMA_USER_CM_CMD_QUERY] = ucma_query, + [RDMA_USER_CM_CMD_BIND] = ucma_bind }; static ssize_t ucma_write(struct file *filp, const char __user *buf, diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 79f68f7c9fd2..895a427bfc91 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -62,7 +62,8 @@ enum { RDMA_USER_CM_CMD_JOIN_IP_MCAST, RDMA_USER_CM_CMD_LEAVE_MCAST, RDMA_USER_CM_CMD_MIGRATE_ID, - RDMA_USER_CM_CMD_QUERY + RDMA_USER_CM_CMD_QUERY, + RDMA_USER_CM_CMD_BIND }; /* @@ -102,6 +103,13 @@ struct rdma_ucm_bind_ip { __u32 id; }; +struct rdma_ucm_bind { + __u32 id; + __u16 addr_size; + __u16 reserved; + struct sockaddr_storage addr; +}; + struct rdma_ucm_resolve_ip { struct sockaddr_in6 src_addr; struct sockaddr_in6 dst_addr; -- GitLab From 209cf2a751f9ff2a516102339e54fcac0176fa78 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:32 -0700 Subject: [PATCH 1575/2900] RDMA/ucma: Allow user space to pass AF_IB into resolve Allow user space applications to call resolve_addr using AF_IB. To support sockaddr_ib, we need to define a new structure capable of handling the larger address size. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucma.c | 30 +++++++++++++++++++++++++++++- include/uapi/rdma/rdma_user_cm.h | 13 ++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 22ed97ef7da3..00ce99044a48 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -577,6 +577,33 @@ static ssize_t ucma_resolve_ip(struct ucma_file *file, return ret; } +static ssize_t ucma_resolve_addr(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) +{ + struct rdma_ucm_resolve_addr cmd; + struct sockaddr *src, *dst; + struct ucma_context *ctx; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + + src = (struct sockaddr *) &cmd.src_addr; + dst = (struct sockaddr *) &cmd.dst_addr; + if (cmd.reserved || (cmd.src_size && (cmd.src_size != rdma_addr_size(src))) || + !cmd.dst_size || (cmd.dst_size != rdma_addr_size(dst))) + return -EINVAL; + + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms); + ucma_put_ctx(ctx); + return ret; +} + static ssize_t ucma_resolve_route(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -1423,7 +1450,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, [RDMA_USER_CM_CMD_QUERY] = ucma_query, - [RDMA_USER_CM_CMD_BIND] = ucma_bind + [RDMA_USER_CM_CMD_BIND] = ucma_bind, + [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr }; static ssize_t ucma_write(struct file *filp, const char __user *buf, diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 895a427bfc91..6d03f9c16f1e 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -63,7 +63,8 @@ enum { RDMA_USER_CM_CMD_LEAVE_MCAST, RDMA_USER_CM_CMD_MIGRATE_ID, RDMA_USER_CM_CMD_QUERY, - RDMA_USER_CM_CMD_BIND + RDMA_USER_CM_CMD_BIND, + RDMA_USER_CM_CMD_RESOLVE_ADDR }; /* @@ -117,6 +118,16 @@ struct rdma_ucm_resolve_ip { __u32 timeout_ms; }; +struct rdma_ucm_resolve_addr { + __u32 id; + __u32 timeout_ms; + __u16 src_size; + __u16 dst_size; + __u32 reserved; + struct sockaddr_storage src_addr; + struct sockaddr_storage dst_addr; +}; + struct rdma_ucm_resolve_route { __u32 id; __u32 timeout_ms; -- GitLab From 5bc2b7b397b02026a0596a7807443a18422733fa Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:33 -0700 Subject: [PATCH 1576/2900] RDMA/ucma: Allow user space to specify AF_IB when joining multicast Allow user space applications to join multicast groups using MGIDs directly. MGIDs may be passed using AF_IB addresses. Since the current multicast join command only supports addresses as large as sockaddr_in6, define a new structure for joining addresses specified using sockaddr_ib. Since AF_IB allows the user to specify the qkey when resolving a remote UD QP address, when joining the multicast group use the qkey value, if one has been assigned. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 9 ++++-- drivers/infiniband/core/ucma.c | 55 +++++++++++++++++++++++++------- include/uapi/rdma/rdma_user_cm.h | 12 ++++++- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 32d74c76e638..3d30c388e043 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3149,6 +3149,8 @@ static void cma_set_mgid(struct rdma_id_private *id_priv, 0xFF10A01B)) { /* IPv6 address is an SA assigned MGID. */ memcpy(mgid, &sin6->sin6_addr, sizeof *mgid); + } else if (addr->sa_family == AF_IB) { + memcpy(mgid, &((struct sockaddr_ib *) addr)->sib_addr, sizeof *mgid); } else if ((addr->sa_family == AF_INET6)) { ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map); if (id_priv->id.ps == RDMA_PS_UDP) @@ -3176,9 +3178,12 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv, if (ret) return ret; + ret = cma_set_qkey(id_priv, 0); + if (ret) + return ret; + cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid); - if (id_priv->id.ps == RDMA_PS_UDP) - rec.qkey = cpu_to_be32(RDMA_UDP_QKEY); + rec.qkey = cpu_to_be32(id_priv->qkey); rdma_addr_get_sgid(dev_addr, &rec.port_gid); rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); rec.join_state = 1; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 00ce99044a48..b0f189be543b 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -1229,23 +1229,23 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf, return ret; } -static ssize_t ucma_join_ip_multicast(struct ucma_file *file, - const char __user *inbuf, - int in_len, int out_len) +static ssize_t ucma_process_join(struct ucma_file *file, + struct rdma_ucm_join_mcast *cmd, int out_len) { - struct rdma_ucm_join_ip_mcast cmd; struct rdma_ucm_create_id_resp resp; struct ucma_context *ctx; struct ucma_multicast *mc; + struct sockaddr *addr; int ret; if (out_len < sizeof(resp)) return -ENOSPC; - if (copy_from_user(&cmd, inbuf, sizeof(cmd))) - return -EFAULT; + addr = (struct sockaddr *) &cmd->addr; + if (cmd->reserved || !cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr))) + return -EINVAL; - ctx = ucma_get_ctx(file, cmd.id); + ctx = ucma_get_ctx(file, cmd->id); if (IS_ERR(ctx)) return PTR_ERR(ctx); @@ -1256,14 +1256,14 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file, goto err1; } - mc->uid = cmd.uid; - memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr); + mc->uid = cmd->uid; + memcpy(&mc->addr, addr, cmd->addr_size); ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc); if (ret) goto err2; resp.id = mc->id; - if (copy_to_user((void __user *)(unsigned long)cmd.response, + if (copy_to_user((void __user *)(unsigned long) cmd->response, &resp, sizeof(resp))) { ret = -EFAULT; goto err3; @@ -1288,6 +1288,38 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file, return ret; } +static ssize_t ucma_join_ip_multicast(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) +{ + struct rdma_ucm_join_ip_mcast cmd; + struct rdma_ucm_join_mcast join_cmd; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + + join_cmd.response = cmd.response; + join_cmd.uid = cmd.uid; + join_cmd.id = cmd.id; + join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); + join_cmd.reserved = 0; + memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size); + + return ucma_process_join(file, &join_cmd, out_len); +} + +static ssize_t ucma_join_multicast(struct ucma_file *file, + const char __user *inbuf, + int in_len, int out_len) +{ + struct rdma_ucm_join_mcast cmd; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + + return ucma_process_join(file, &cmd, out_len); +} + static ssize_t ucma_leave_multicast(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) @@ -1451,7 +1483,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, [RDMA_USER_CM_CMD_QUERY] = ucma_query, [RDMA_USER_CM_CMD_BIND] = ucma_bind, - [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr + [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr, + [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast }; static ssize_t ucma_write(struct file *filp, const char __user *buf, diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 6d03f9c16f1e..99b80abf360a 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h @@ -64,7 +64,8 @@ enum { RDMA_USER_CM_CMD_MIGRATE_ID, RDMA_USER_CM_CMD_QUERY, RDMA_USER_CM_CMD_BIND, - RDMA_USER_CM_CMD_RESOLVE_ADDR + RDMA_USER_CM_CMD_RESOLVE_ADDR, + RDMA_USER_CM_CMD_JOIN_MCAST }; /* @@ -242,6 +243,15 @@ struct rdma_ucm_join_ip_mcast { __u32 id; }; +struct rdma_ucm_join_mcast { + __u64 response; /* rdma_ucma_create_id_resp */ + __u64 uid; + __u32 id; + __u16 addr_size; + __u16 reserved; + struct sockaddr_storage addr; +}; + struct rdma_ucm_get_event { __u64 response; }; -- GitLab From ce117ffac2e933344d0ea01b1cb3b56627fcb6e7 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 29 May 2013 10:09:34 -0700 Subject: [PATCH 1577/2900] RDMA/cma: Export AF_IB statistics Report AF_IB source and destination addresses through netlink interface. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 37 ++++++++++------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 3d30c388e043..f1c279fabe64 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3586,33 +3586,16 @@ static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) id_stats->bound_dev_if = id->route.addr.dev_addr.bound_dev_if; - if (cma_family(id_priv) == AF_INET) { - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in), - cma_src_addr(id_priv), - RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { - goto out; - } - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in), - cma_dst_addr(id_priv), - RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { - goto out; - } - } else if (cma_family(id_priv) == AF_INET6) { - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in6), - cma_src_addr(id_priv), - RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { - goto out; - } - if (ibnl_put_attr(skb, nlh, - sizeof(struct sockaddr_in6), - cma_dst_addr(id_priv), - RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { - goto out; - } - } + if (ibnl_put_attr(skb, nlh, + rdma_addr_size(cma_src_addr(id_priv)), + cma_src_addr(id_priv), + RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) + goto out; + if (ibnl_put_attr(skb, nlh, + rdma_addr_size(cma_src_addr(id_priv)), + cma_dst_addr(id_priv), + RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) + goto out; id_stats->pid = id_priv->owner; id_stats->port_space = id->ps; -- GitLab From 76abbdde2d95a3807d0dc6bf9f84d03d0dbd4f3d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 11 Jun 2013 10:38:59 -0700 Subject: [PATCH 1578/2900] pwm: Add sysfs interface Add a simple sysfs interface to the generic PWM framework. /sys/class/pwm/ `-- pwmchipN/ for each PWM chip |-- export (w/o) ask the kernel to export a PWM channel |-- npwm (r/o) number of PWM channels in this PWM chip |-- pwmX/ for each exported PWM channel | |-- duty_cycle (r/w) duty cycle (in nanoseconds) | |-- enable (r/w) enable/disable PWM | |-- period (r/w) period (in nanoseconds) | `-- polarity (r/w) polarity of PWM (normal/inversed) `-- unexport (w/o) return a PWM channel to the kernel Based on work by Lars Poeschel. Signed-off-by: H Hartley Sweeten Cc: Thierry Reding Cc: Lars Poeschel Cc: Ryan Mallon Cc: Rob Landley Signed-off-by: Thierry Reding --- Documentation/ABI/testing/sysfs-class-pwm | 79 +++++ Documentation/pwm.txt | 37 +++ drivers/pwm/Kconfig | 4 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 25 +- drivers/pwm/sysfs.c | 352 ++++++++++++++++++++++ include/linux/pwm.h | 29 +- 7 files changed, 524 insertions(+), 3 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/sysfs.c diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm new file mode 100644 index 000000000000..c479d77b67c5 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-pwm @@ -0,0 +1,79 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the exported PWM + channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM signal period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty_cycle +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the PWM signal duty cycle in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Sets the output polarity of the PWM signal to "normal" or + "inversed". + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten +Description: + Enable/disable the PWM signal. + 0 is disabled + 1 is enabled diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt index 7d2b4c9b544b..1039b68fe9c6 100644 --- a/Documentation/pwm.txt +++ b/Documentation/pwm.txt @@ -45,6 +45,43 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). +Using PWMs with the sysfs interface +----------------------------------- + +If CONFIG_SYSFS is enabled in your kernel configuration a simple sysfs +interface is provided to use the PWMs from userspace. It is exposed at +/sys/class/pwm/. Each probed PWM controller/chip will be exported as +pwmchipN, where N is the base of the PWM chip. Inside the directory you +will find: + +npwm - The number of PWM channels this chip supports (read-only). + +export - Exports a PWM channel for use with sysfs (write-only). + +unexport - Unexports a PWM channel from sysfs (write-only). + +The PWM channels are numbered using a per-chip index from 0 to npwm-1. + +When a PWM channel is exported a pwmX directory will be created in the +pwmchipN directory it is associated with, where X is the number of the +channel that was exported. The following properties will then be available: + +period - The total period of the PWM signal (read/write). + Value is in nanoseconds and is the sum of the active and inactive + time of the PWM. + +duty_cycle - The active time of the PWM signal (read/write). + Value is in nanoseconds and must be less than the period. + +polarity - Changes the polarity of the PWM signal (read/write). + Writes to this property only work if the PWM chip supports changing + the polarity. The polarity can only be changed if the PWM is not + enabled. Value is the string "normal" or "inversed". + +enable - Enable/disable the PWM signal (read/write). + 0 - disabled + 1 - enabled + Implementing a PWM driver ------------------------- diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index d3fe3205d296..406a4d94ddb9 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -28,6 +28,10 @@ menuconfig PWM if PWM +config PWM_SYSFS + bool + default y if SYSFS + config PWM_AB8500 tristate "AB8500 PWM support" depends on AB8500_CORE && ARCH_U8500 diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index b3afc0a1800b..859692224044 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_PWM) += core.o +obj-$(CONFIG_PWM_SYSFS) += sysfs.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 0cf0f65eb037..dfbfbc521768 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -274,6 +274,8 @@ int pwmchip_add(struct pwm_chip *chip) if (IS_ENABLED(CONFIG_OF)) of_pwmchip_add(chip); + pwmchip_sysfs_export(chip); + out: mutex_unlock(&pwm_lock); return ret; @@ -310,6 +312,8 @@ int pwmchip_remove(struct pwm_chip *chip) free_pwms(chip); + pwmchip_sysfs_unexport(chip); + out: mutex_unlock(&pwm_lock); return ret; @@ -402,10 +406,19 @@ EXPORT_SYMBOL_GPL(pwm_free); */ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) { + int err; + if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns) return -EINVAL; - return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); + err = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); + if (err) + return err; + + pwm->duty_cycle = duty_ns; + pwm->period = period_ns; + + return 0; } EXPORT_SYMBOL_GPL(pwm_config); @@ -418,6 +431,8 @@ EXPORT_SYMBOL_GPL(pwm_config); */ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) { + int err; + if (!pwm || !pwm->chip->ops) return -EINVAL; @@ -427,7 +442,13 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) if (test_bit(PWMF_ENABLED, &pwm->flags)) return -EBUSY; - return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); + err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); + if (err) + return err; + + pwm->polarity = polarity; + + return 0; } EXPORT_SYMBOL_GPL(pwm_set_polarity); diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c new file mode 100644 index 000000000000..8ca5de316d3b --- /dev/null +++ b/drivers/pwm/sysfs.c @@ -0,0 +1,352 @@ +/* + * A simple sysfs interface for the generic PWM framework + * + * Copyright (C) 2013 H Hartley Sweeten + * + * Based on previous work by Lars Poeschel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +struct pwm_export { + struct device child; + struct pwm_device *pwm; +}; + +static struct pwm_export *child_to_pwm_export(struct device *child) +{ + return container_of(child, struct pwm_export, child); +} + +static struct pwm_device *child_to_pwm_device(struct device *child) +{ + struct pwm_export *export = child_to_pwm_export(child); + + return export->pwm; +} + +static ssize_t pwm_period_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_device *pwm = child_to_pwm_device(child); + + return sprintf(buf, "%u\n", pwm->period); +} + +static ssize_t pwm_period_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_device *pwm = child_to_pwm_device(child); + unsigned int val; + int ret; + + ret = kstrtouint(buf, 0, &val); + if (ret) + return ret; + + ret = pwm_config(pwm, pwm->duty_cycle, val); + + return ret ? : size; +} + +static ssize_t pwm_duty_cycle_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_device *pwm = child_to_pwm_device(child); + + return sprintf(buf, "%u\n", pwm->duty_cycle); +} + +static ssize_t pwm_duty_cycle_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_device *pwm = child_to_pwm_device(child); + unsigned int val; + int ret; + + ret = kstrtouint(buf, 0, &val); + if (ret) + return ret; + + ret = pwm_config(pwm, val, pwm->period); + + return ret ? : size; +} + +static ssize_t pwm_enable_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_device *pwm = child_to_pwm_device(child); + int enabled = test_bit(PWMF_ENABLED, &pwm->flags); + + return sprintf(buf, "%d\n", enabled); +} + +static ssize_t pwm_enable_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_device *pwm = child_to_pwm_device(child); + int val, ret; + + ret = kstrtoint(buf, 0, &val); + if (ret) + return ret; + + switch (val) { + case 0: + pwm_disable(pwm); + break; + case 1: + ret = pwm_enable(pwm); + break; + default: + ret = -EINVAL; + break; + } + + return ret ? : size; +} + +static ssize_t pwm_polarity_show(struct device *child, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_device *pwm = child_to_pwm_device(child); + + return sprintf(buf, "%s\n", pwm->polarity ? "inversed" : "normal"); +} + +static ssize_t pwm_polarity_store(struct device *child, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct pwm_device *pwm = child_to_pwm_device(child); + enum pwm_polarity polarity; + int ret; + + if (sysfs_streq(buf, "normal")) + polarity = PWM_POLARITY_NORMAL; + else if (sysfs_streq(buf, "inversed")) + polarity = PWM_POLARITY_INVERSED; + else + return -EINVAL; + + ret = pwm_set_polarity(pwm, polarity); + + return ret ? : size; +} + +static DEVICE_ATTR(period, 0644, pwm_period_show, pwm_period_store); +static DEVICE_ATTR(duty_cycle, 0644, pwm_duty_cycle_show, pwm_duty_cycle_store); +static DEVICE_ATTR(enable, 0644, pwm_enable_show, pwm_enable_store); +static DEVICE_ATTR(polarity, 0644, pwm_polarity_show, pwm_polarity_store); + +static struct attribute *pwm_attrs[] = { + &dev_attr_period.attr, + &dev_attr_duty_cycle.attr, + &dev_attr_enable.attr, + &dev_attr_polarity.attr, + NULL +}; + +static const struct attribute_group pwm_attr_group = { + .attrs = pwm_attrs, +}; + +static const struct attribute_group *pwm_attr_groups[] = { + &pwm_attr_group, + NULL, +}; + +static void pwm_export_release(struct device *child) +{ + struct pwm_export *export = child_to_pwm_export(child); + + kfree(export); +} + +static int pwm_export_child(struct device *parent, struct pwm_device *pwm) +{ + struct pwm_export *export; + int ret; + + if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) + return -EBUSY; + + export = kzalloc(sizeof(*export), GFP_KERNEL); + if (!export) { + clear_bit(PWMF_EXPORTED, &pwm->flags); + return -ENOMEM; + } + + export->pwm = pwm; + + export->child.release = pwm_export_release; + export->child.parent = parent; + export->child.devt = MKDEV(0, 0); + export->child.groups = pwm_attr_groups; + dev_set_name(&export->child, "pwm%u", pwm->hwpwm); + + ret = device_register(&export->child); + if (ret) { + clear_bit(PWMF_EXPORTED, &pwm->flags); + kfree(export); + return ret; + } + + return 0; +} + +static int pwm_unexport_match(struct device *child, void *data) +{ + return child_to_pwm_device(child) == data; +} + +static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) +{ + struct device *child; + + if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) + return -ENODEV; + + child = device_find_child(parent, pwm, pwm_unexport_match); + if (!child) + return -ENODEV; + + /* for device_find_child() */ + put_device(child); + device_unregister(child); + pwm_put(pwm); + + return 0; +} + +static ssize_t pwm_export_store(struct device *parent, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pwm_chip *chip = dev_get_drvdata(parent); + struct pwm_device *pwm; + unsigned int hwpwm; + int ret; + + ret = kstrtouint(buf, 0, &hwpwm); + if (ret < 0) + return ret; + + if (hwpwm >= chip->npwm) + return -ENODEV; + + pwm = pwm_request_from_chip(chip, hwpwm, "sysfs"); + if (IS_ERR(pwm)) + return PTR_ERR(pwm); + + ret = pwm_export_child(parent, pwm); + if (ret < 0) + pwm_put(pwm); + + return ret ? : len; +} + +static ssize_t pwm_unexport_store(struct device *parent, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct pwm_chip *chip = dev_get_drvdata(parent); + unsigned int hwpwm; + int ret; + + ret = kstrtouint(buf, 0, &hwpwm); + if (ret < 0) + return ret; + + if (hwpwm >= chip->npwm) + return -ENODEV; + + ret = pwm_unexport_child(parent, &chip->pwms[hwpwm]); + + return ret ? : len; +} + +static ssize_t pwm_npwm_show(struct device *parent, + struct device_attribute *attr, + char *buf) +{ + const struct pwm_chip *chip = dev_get_drvdata(parent); + + return sprintf(buf, "%u\n", chip->npwm); +} + +static struct device_attribute pwm_chip_attrs[] = { + __ATTR(export, 0200, NULL, pwm_export_store), + __ATTR(unexport, 0200, NULL, pwm_unexport_store), + __ATTR(npwm, 0444, pwm_npwm_show, NULL), + __ATTR_NULL, +}; + +static struct class pwm_class = { + .name = "pwm", + .owner = THIS_MODULE, + .dev_attrs = pwm_chip_attrs, +}; + +static int pwmchip_sysfs_match(struct device *parent, const void *data) +{ + return dev_get_drvdata(parent) == data; +} + +void pwmchip_sysfs_export(struct pwm_chip *chip) +{ + struct device *parent; + + /* + * If device_create() fails the pwm_chip is still usable by + * the kernel its just not exported. + */ + parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip, + "pwmchip%d", chip->base); + if (IS_ERR(parent)) { + dev_warn(chip->dev, + "device_create failed for pwm_chip sysfs export\n"); + } +} + +void pwmchip_sysfs_unexport(struct pwm_chip *chip) +{ + struct device *parent; + + parent = class_find_device(&pwm_class, NULL, chip, + pwmchip_sysfs_match); + if (parent) { + /* for class_find_device() */ + put_device(parent); + device_unregister(parent); + } +} + +static int __init pwm_sysfs_init(void) +{ + return class_register(&pwm_class); +} +subsys_initcall(pwm_sysfs_init); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index a4df2042b79c..f0feafd184a0 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -76,6 +76,7 @@ enum pwm_polarity { enum { PWMF_REQUESTED = 1 << 0, PWMF_ENABLED = 1 << 1, + PWMF_EXPORTED = 1 << 2, }; struct pwm_device { @@ -86,7 +87,9 @@ struct pwm_device { struct pwm_chip *chip; void *chip_data; - unsigned int period; /* in nanoseconds */ + unsigned int period; /* in nanoseconds */ + unsigned int duty_cycle; /* in nanoseconds */ + enum pwm_polarity polarity; }; static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) @@ -100,6 +103,17 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm) return pwm ? pwm->period : 0; } +static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty) +{ + if (pwm) + pwm->duty_cycle = duty; +} + +static inline unsigned int pwm_get_duty_cycle(struct pwm_device *pwm) +{ + return pwm ? pwm->duty_cycle : 0; +} + /* * pwm_set_polarity - configure the polarity of a PWM signal */ @@ -278,4 +292,17 @@ static inline void pwm_add_table(struct pwm_lookup *table, size_t num) } #endif +#ifdef CONFIG_PWM_SYSFS +void pwmchip_sysfs_export(struct pwm_chip *chip); +void pwmchip_sysfs_unexport(struct pwm_chip *chip); +#else +static inline void pwmchip_sysfs_export(struct pwm_chip *chip) +{ +} + +static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) +{ +} +#endif /* CONFIG_PWM_SYSFS */ + #endif /* __LINUX_PWM_H */ -- GitLab From 99b82abb0a35b07310ea6334257829af168c8e08 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 13 Jun 2013 18:54:44 +0200 Subject: [PATCH 1579/2900] pwm: Add Renesas TPU PWM driver The Timer Pulse Unit (TPU) is a 4-channels 16-bit timer used to generate waveforms. This driver exposes PWM functions through the PWM API for other drivers to use. The code is loosely based on the leds-renesas-tpu driver by Magnus Damm and the TPU PWM driver shipped in the Armadillo EVA 800 kernel sources. Signed-off-by: Laurent Pinchart Signed-off-by: Axel Lin Tested-by: Simon Horman Signed-off-by: Thierry Reding --- drivers/pwm/Kconfig | 10 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-renesas-tpu.c | 475 ++++++++++++++++++ include/linux/platform_data/pwm-renesas-tpu.h | 16 + 4 files changed, 502 insertions(+) create mode 100644 drivers/pwm/pwm-renesas-tpu.c create mode 100644 include/linux/platform_data/pwm-renesas-tpu.h diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 406a4d94ddb9..75840b5cea6d 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -128,6 +128,16 @@ config PWM_PXA To compile this driver as a module, choose M here: the module will be called pwm-pxa. +config PWM_RENESAS_TPU + tristate "Renesas TPU PWM support" + depends on ARCH_SHMOBILE + help + This driver exposes the Timer Pulse Unit (TPU) PWM controller found + in Renesas chips through the PWM API. + + To compile this driver as a module, choose M here: the module + will be called pwm-renesas-tpu. + config PWM_SAMSUNG tristate "Samsung PWM support" depends on PLAT_SAMSUNG diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 859692224044..77a8c185c5b2 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o obj-$(CONFIG_PWM_PXA) += pwm-pxa.o +obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c new file mode 100644 index 000000000000..96e0cc488a4e --- /dev/null +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -0,0 +1,475 @@ +/* + * R-Mobile TPU PWM driver + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPU_TSTR 0x00 /* Timer start register (shared) */ + +#define TPU_TCRn 0x00 /* Timer control register */ +#define TPU_TCR_CCLR_NONE (0 << 5) +#define TPU_TCR_CCLR_TGRA (1 << 5) +#define TPU_TCR_CCLR_TGRB (2 << 5) +#define TPU_TCR_CCLR_TGRC (5 << 5) +#define TPU_TCR_CCLR_TGRD (6 << 5) +#define TPU_TCR_CKEG_RISING (0 << 3) +#define TPU_TCR_CKEG_FALLING (1 << 3) +#define TPU_TCR_CKEG_BOTH (2 << 3) +#define TPU_TMDRn 0x04 /* Timer mode register */ +#define TPU_TMDR_BFWT (1 << 6) +#define TPU_TMDR_BFB (1 << 5) +#define TPU_TMDR_BFA (1 << 4) +#define TPU_TMDR_MD_NORMAL (0 << 0) +#define TPU_TMDR_MD_PWM (2 << 0) +#define TPU_TIORn 0x08 /* Timer I/O control register */ +#define TPU_TIOR_IOA_0 (0 << 0) +#define TPU_TIOR_IOA_0_CLR (1 << 0) +#define TPU_TIOR_IOA_0_SET (2 << 0) +#define TPU_TIOR_IOA_0_TOGGLE (3 << 0) +#define TPU_TIOR_IOA_1 (4 << 0) +#define TPU_TIOR_IOA_1_CLR (5 << 0) +#define TPU_TIOR_IOA_1_SET (6 << 0) +#define TPU_TIOR_IOA_1_TOGGLE (7 << 0) +#define TPU_TIERn 0x0c /* Timer interrupt enable register */ +#define TPU_TSRn 0x10 /* Timer status register */ +#define TPU_TCNTn 0x14 /* Timer counter */ +#define TPU_TGRAn 0x18 /* Timer general register A */ +#define TPU_TGRBn 0x1c /* Timer general register B */ +#define TPU_TGRCn 0x20 /* Timer general register C */ +#define TPU_TGRDn 0x24 /* Timer general register D */ + +#define TPU_CHANNEL_OFFSET 0x10 +#define TPU_CHANNEL_SIZE 0x40 + +enum tpu_pin_state { + TPU_PIN_INACTIVE, /* Pin is driven inactive */ + TPU_PIN_PWM, /* Pin is driven by PWM */ + TPU_PIN_ACTIVE, /* Pin is driven active */ +}; + +struct tpu_device; + +struct tpu_pwm_device { + bool timer_on; /* Whether the timer is running */ + + struct tpu_device *tpu; + unsigned int channel; /* Channel number in the TPU */ + + enum pwm_polarity polarity; + unsigned int prescaler; + u16 period; + u16 duty; +}; + +struct tpu_device { + struct platform_device *pdev; + struct tpu_pwm_platform_data *pdata; + struct pwm_chip chip; + spinlock_t lock; + + void __iomem *base; + struct clk *clk; +}; + +#define to_tpu_device(c) container_of(c, struct tpu_device, chip) + +static void tpu_pwm_write(struct tpu_pwm_device *pwm, int reg_nr, u16 value) +{ + void __iomem *base = pwm->tpu->base + TPU_CHANNEL_OFFSET + + pwm->channel * TPU_CHANNEL_SIZE; + + iowrite16(value, base + reg_nr); +} + +static void tpu_pwm_set_pin(struct tpu_pwm_device *pwm, + enum tpu_pin_state state) +{ + static const char * const states[] = { "inactive", "PWM", "active" }; + + dev_dbg(&pwm->tpu->pdev->dev, "%u: configuring pin as %s\n", + pwm->channel, states[state]); + + switch (state) { + case TPU_PIN_INACTIVE: + tpu_pwm_write(pwm, TPU_TIORn, + pwm->polarity == PWM_POLARITY_INVERSED ? + TPU_TIOR_IOA_1 : TPU_TIOR_IOA_0); + break; + case TPU_PIN_PWM: + tpu_pwm_write(pwm, TPU_TIORn, + pwm->polarity == PWM_POLARITY_INVERSED ? + TPU_TIOR_IOA_0_SET : TPU_TIOR_IOA_1_CLR); + break; + case TPU_PIN_ACTIVE: + tpu_pwm_write(pwm, TPU_TIORn, + pwm->polarity == PWM_POLARITY_INVERSED ? + TPU_TIOR_IOA_0 : TPU_TIOR_IOA_1); + break; + } +} + +static void tpu_pwm_start_stop(struct tpu_pwm_device *pwm, int start) +{ + unsigned long flags; + u16 value; + + spin_lock_irqsave(&pwm->tpu->lock, flags); + value = ioread16(pwm->tpu->base + TPU_TSTR); + + if (start) + value |= 1 << pwm->channel; + else + value &= ~(1 << pwm->channel); + + iowrite16(value, pwm->tpu->base + TPU_TSTR); + spin_unlock_irqrestore(&pwm->tpu->lock, flags); +} + +static int tpu_pwm_timer_start(struct tpu_pwm_device *pwm) +{ + int ret; + + if (!pwm->timer_on) { + /* Wake up device and enable clock. */ + pm_runtime_get_sync(&pwm->tpu->pdev->dev); + ret = clk_prepare_enable(pwm->tpu->clk); + if (ret) { + dev_err(&pwm->tpu->pdev->dev, "cannot enable clock\n"); + return ret; + } + pwm->timer_on = true; + } + + /* + * Make sure the channel is stopped, as we need to reconfigure it + * completely. First drive the pin to the inactive state to avoid + * glitches. + */ + tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); + tpu_pwm_start_stop(pwm, false); + + /* + * - Clear TCNT on TGRB match + * - Count on rising edge + * - Set prescaler + * - Output 0 until TGRA, output 1 until TGRB (active low polarity) + * - Output 1 until TGRA, output 0 until TGRB (active high polarity + * - PWM mode + */ + tpu_pwm_write(pwm, TPU_TCRn, TPU_TCR_CCLR_TGRB | TPU_TCR_CKEG_RISING | + pwm->prescaler); + tpu_pwm_write(pwm, TPU_TMDRn, TPU_TMDR_MD_PWM); + tpu_pwm_set_pin(pwm, TPU_PIN_PWM); + tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); + tpu_pwm_write(pwm, TPU_TGRBn, pwm->period); + + dev_dbg(&pwm->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", + pwm->channel, pwm->duty, pwm->period); + + /* Start the channel. */ + tpu_pwm_start_stop(pwm, true); + + return 0; +} + +static void tpu_pwm_timer_stop(struct tpu_pwm_device *pwm) +{ + if (!pwm->timer_on) + return; + + /* Disable channel. */ + tpu_pwm_start_stop(pwm, false); + + /* Stop clock and mark device as idle. */ + clk_disable_unprepare(pwm->tpu->clk); + pm_runtime_put(&pwm->tpu->pdev->dev); + + pwm->timer_on = false; +} + +/* ----------------------------------------------------------------------------- + * PWM API + */ + +static int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *_pwm) +{ + struct tpu_device *tpu = to_tpu_device(chip); + struct tpu_pwm_device *pwm; + + if (_pwm->hwpwm >= TPU_CHANNEL_MAX) + return -EINVAL; + + pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); + if (pwm == NULL) + return -ENOMEM; + + pwm->tpu = tpu; + pwm->channel = _pwm->hwpwm; + pwm->polarity = tpu->pdata ? tpu->pdata->channels[pwm->channel].polarity + : PWM_POLARITY_NORMAL; + pwm->prescaler = 0; + pwm->period = 0; + pwm->duty = 0; + + pwm->timer_on = false; + + pwm_set_chip_data(_pwm, pwm); + + return 0; +} + +static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *_pwm) +{ + struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + + tpu_pwm_timer_stop(pwm); + kfree(pwm); +} + +static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, + int duty_ns, int period_ns) +{ + static const unsigned int prescalers[] = { 1, 4, 16, 64 }; + struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_device *tpu = to_tpu_device(chip); + unsigned int prescaler; + bool duty_only = false; + u32 clk_rate; + u32 period; + u32 duty; + int ret; + + /* + * Pick a prescaler to avoid overflowing the counter. + * TODO: Pick the highest acceptable prescaler. + */ + clk_rate = clk_get_rate(tpu->clk); + + for (prescaler = 0; prescaler < ARRAY_SIZE(prescalers); ++prescaler) { + period = clk_rate / prescalers[prescaler] + / (NSEC_PER_SEC / period_ns); + if (period <= 0xffff) + break; + } + + if (prescaler == ARRAY_SIZE(prescalers) || period == 0) { + dev_err(&tpu->pdev->dev, "clock rate mismatch\n"); + return -ENOTSUPP; + } + + if (duty_ns) { + duty = clk_rate / prescalers[prescaler] + / (NSEC_PER_SEC / duty_ns); + if (duty > period) + return -EINVAL; + } else { + duty = 0; + } + + dev_dbg(&tpu->pdev->dev, + "rate %u, prescaler %u, period %u, duty %u\n", + clk_rate, prescalers[prescaler], period, duty); + + if (pwm->prescaler == prescaler && pwm->period == period) + duty_only = true; + + pwm->prescaler = prescaler; + pwm->period = period; + pwm->duty = duty; + + /* If the channel is disabled we're done. */ + if (!test_bit(PWMF_ENABLED, &_pwm->flags)) + return 0; + + if (duty_only && pwm->timer_on) { + /* + * If only the duty cycle changed and the timer is already + * running, there's no need to reconfigure it completely, Just + * modify the duty cycle. + */ + tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); + dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", pwm->channel, + pwm->duty); + } else { + /* Otherwise perform a full reconfiguration. */ + ret = tpu_pwm_timer_start(pwm); + if (ret < 0) + return ret; + } + + if (duty == 0 || duty == period) { + /* + * To avoid running the timer when not strictly required, handle + * 0% and 100% duty cycles as fixed levels and stop the timer. + */ + tpu_pwm_set_pin(pwm, duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); + tpu_pwm_timer_stop(pwm); + } + + return 0; +} + +static int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *_pwm, + enum pwm_polarity polarity) +{ + struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + + pwm->polarity = polarity; + + return 0; +} + +static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *_pwm) +{ + struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + int ret; + + ret = tpu_pwm_timer_start(pwm); + if (ret < 0) + return ret; + + /* + * To avoid running the timer when not strictly required, handle 0% and + * 100% duty cycles as fixed levels and stop the timer. + */ + if (pwm->duty == 0 || pwm->duty == pwm->period) { + tpu_pwm_set_pin(pwm, pwm->duty ? + TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); + tpu_pwm_timer_stop(pwm); + } + + return 0; +} + +static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *_pwm) +{ + struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + + /* The timer must be running to modify the pin output configuration. */ + tpu_pwm_timer_start(pwm); + tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); + tpu_pwm_timer_stop(pwm); +} + +static const struct pwm_ops tpu_pwm_ops = { + .request = tpu_pwm_request, + .free = tpu_pwm_free, + .config = tpu_pwm_config, + .set_polarity = tpu_pwm_set_polarity, + .enable = tpu_pwm_enable, + .disable = tpu_pwm_disable, + .owner = THIS_MODULE, +}; + +/* ----------------------------------------------------------------------------- + * Probe and remove + */ + +static int tpu_probe(struct platform_device *pdev) +{ + struct tpu_device *tpu; + struct resource *res; + int ret; + + tpu = devm_kzalloc(&pdev->dev, sizeof(*tpu), GFP_KERNEL); + if (tpu == NULL) { + dev_err(&pdev->dev, "failed to allocate driver data\n"); + return -ENOMEM; + } + + tpu->pdata = pdev->dev.platform_data; + + /* Map memory, get clock and pin control. */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get I/O memory\n"); + return -ENXIO; + } + + tpu->base = devm_ioremap_resource(&pdev->dev, res); + if (tpu->base == NULL) { + dev_err(&pdev->dev, "failed to remap I/O memory\n"); + return -ENXIO; + } + + tpu->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tpu->clk)) { + dev_err(&pdev->dev, "cannot get clock\n"); + return PTR_ERR(tpu->clk); + } + + /* Initialize and register the device. */ + platform_set_drvdata(pdev, tpu); + + spin_lock_init(&tpu->lock); + tpu->pdev = pdev; + + tpu->chip.dev = &pdev->dev; + tpu->chip.ops = &tpu_pwm_ops; + tpu->chip.base = -1; + tpu->chip.npwm = TPU_CHANNEL_MAX; + + ret = pwmchip_add(&tpu->chip); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register PWM chip\n"); + return ret; + } + + dev_info(&pdev->dev, "TPU PWM %d registered\n", tpu->pdev->id); + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tpu_remove(struct platform_device *pdev) +{ + struct tpu_device *tpu = platform_get_drvdata(pdev); + int ret; + + ret = pwmchip_remove(&tpu->chip); + if (ret) + return ret; + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static struct platform_driver tpu_driver = { + .probe = tpu_probe, + .remove = tpu_remove, + .driver = { + .name = "renesas-tpu-pwm", + .owner = THIS_MODULE, + } +}; + +module_platform_driver(tpu_driver); + +MODULE_AUTHOR("Laurent Pinchart "); +MODULE_DESCRIPTION("Renesas TPU PWM Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/pwm-renesas-tpu.h b/include/linux/platform_data/pwm-renesas-tpu.h new file mode 100644 index 000000000000..a7220b10ddab --- /dev/null +++ b/include/linux/platform_data/pwm-renesas-tpu.h @@ -0,0 +1,16 @@ +#ifndef __PWM_RENESAS_TPU_H__ +#define __PWM_RENESAS_TPU_H__ + +#include + +#define TPU_CHANNEL_MAX 4 + +struct tpu_pwm_channel_data { + enum pwm_polarity polarity; +}; + +struct tpu_pwm_platform_data { + struct tpu_pwm_channel_data channels[TPU_CHANNEL_MAX]; +}; + +#endif /* __PWM_RENESAS_TPU_H__ */ -- GitLab From facd23664f1d63c33fbc6da52261c8548ed3fbd4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 07:56:06 -0300 Subject: [PATCH 1580/2900] [media] cx88: remove g_chip_ident Remove g_chip_ident from cx88. Also remove the v4l2-chip-ident.h include. The board code used defines from v4l2-chip-ident.h to tell the driver which audio chip is used. Replace this with a cx88-specific enum. Signed-off-by: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx88/cx88-cards.c | 12 ++++++------ drivers/media/pci/cx88/cx88-video.c | 21 ++------------------- drivers/media/pci/cx88/cx88.h | 8 ++++++-- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index a87a0e19593e..e18a7ace08b1 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -744,7 +744,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, /* Some variants use a tda9874 and so need the tvaudio module. */ - .audio_chip = V4L2_IDENT_TVAUDIO, + .audio_chip = CX88_AUDIO_TVAUDIO, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -976,7 +976,7 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .i2sinputcntl = 2, .input = {{ .type = CX88_VMUX_DVB, @@ -1014,7 +1014,7 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, @@ -1376,7 +1376,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -1461,7 +1461,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, /* * gpio0 as reported by Mike Crash */ @@ -1929,7 +1929,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, /* * GPIO0 (WINTV2000) * diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index c7a9be1065c0..5b26ece4aea5 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1353,24 +1353,12 @@ static int vidioc_s_frequency (struct file *file, void *priv, return cx88_set_freq(core, f); } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - if (!v4l2_chip_match_host(&chip->match)) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* cx2388x has a 24-bit register space */ reg->val = cx_read(reg->reg & 0xffffff); reg->size = 4; @@ -1382,8 +1370,6 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; cx_write(reg->reg & 0xffffff, reg->val); return 0; } @@ -1578,7 +1564,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1612,7 +1597,6 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1643,7 +1627,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1794,7 +1777,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ - if (core->board.audio_chip == V4L2_IDENT_WM8775) { + if (core->board.audio_chip == CX88_AUDIO_WM8775) { struct i2c_board_info wm8775_info = { .type = "wm8775", .addr = 0x36 >> 1, @@ -1815,7 +1798,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, } } - if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { + if (core->board.audio_chip == CX88_AUDIO_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 51ce2c0e8bc1..afe0eaea81b4 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -259,6 +258,11 @@ struct cx88_input { unsigned int audioroute:4; }; +enum cx88_audio_chip { + CX88_AUDIO_WM8775, + CX88_AUDIO_TVAUDIO, +}; + struct cx88_board { const char *name; unsigned int tuner_type; @@ -269,7 +273,7 @@ struct cx88_board { struct cx88_input input[MAX_CX88_INPUT]; struct cx88_input radio; enum cx88_board_type mpeg; - unsigned int audio_chip; + enum cx88_audio_chip audio_chip; int num_frontends; /* Used for I2S devices */ -- GitLab From 6ec19898ed6990baa285b8c96a8b1a0d0366bc46 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 08:24:00 -0300 Subject: [PATCH 1581/2900] [media] v4l2: remove obsolete v4l2_chip_match_host() This function is no longer needed since it is now the responsibility of the v4l2 core to check if the DBG_G/S_REGISTER and DBG_G_CHIP_INFO ioctls are called for the bridge driver or not. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 4 ---- drivers/media/v4l2-core/v4l2-common.c | 11 ----------- include/media/v4l2-common.h | 1 - 3 files changed, 16 deletions(-) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 7ad872a3e31a..f0a0b7f2da92 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -467,8 +467,6 @@ static int vidioc_g_register(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int err_code; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* NT100x has a 8-bit register space */ err_code = usbvision_read_reg(usbvision, reg->reg&0xff); if (err_code < 0) { @@ -488,8 +486,6 @@ static int vidioc_s_register(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int err_code; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* NT100x has a 8-bit register space */ err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val); if (err_code < 0) { diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3fed63f4e026..5fd76609e613 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -227,17 +227,6 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) } EXPORT_SYMBOL(v4l2_ctrl_next); -int v4l2_chip_match_host(const struct v4l2_dbg_match *match) -{ - switch (match->type) { - case V4L2_CHIP_MATCH_BRIDGE: - return match->addr == 0; - default: - return 0; - } -} -EXPORT_SYMBOL(v4l2_chip_match_host); - #if IS_ENABLED(CONFIG_I2C) int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match) { diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1d93c48cb371..e7821fb3cd86 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -106,7 +106,6 @@ struct i2c_client; /* forward reference */ int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match); int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, u32 ident, u32 revision); -int v4l2_chip_match_host(const struct v4l2_dbg_match *match); /* ------------------------------------------------------------------------- */ -- GitLab From aee38734d2e2a908c4fd50918f28f19c088abfb9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 10:01:42 -0300 Subject: [PATCH 1582/2900] [media] v4l2-common: remove unused v4l2_chip_match/ident_i2c_client functions Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 47 +-------------------------- include/media/v4l2-common.h | 9 ----- 2 files changed, 1 insertion(+), 55 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 5fd76609e613..3b2a7606bc84 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -61,7 +61,6 @@ #include #include #include -#include #include @@ -227,51 +226,9 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) } EXPORT_SYMBOL(v4l2_ctrl_next); -#if IS_ENABLED(CONFIG_I2C) -int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match) -{ - int len; - - if (c == NULL || match == NULL) - return 0; - - switch (match->type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - if (c->driver == NULL || c->driver->driver.name == NULL) - return 0; - len = strlen(c->driver->driver.name); - return len && !strncmp(c->driver->driver.name, match->name, len); - case V4L2_CHIP_MATCH_I2C_ADDR: - return c->addr == match->addr; - case V4L2_CHIP_MATCH_SUBDEV: - return 1; - default: - return 0; - } -} -EXPORT_SYMBOL(v4l2_chip_match_i2c_client); - -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, - u32 ident, u32 revision) -{ - if (!v4l2_chip_match_i2c_client(c, &chip->match)) - return 0; - if (chip->ident == V4L2_IDENT_NONE) { - chip->ident = ident; - chip->revision = revision; - } - else { - chip->ident = V4L2_IDENT_AMBIGUOUS; - chip->revision = 0; - } - return 0; -} -EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); - -/* ----------------------------------------------------------------- */ - /* I2C Helper functions */ +#if IS_ENABLED(CONFIG_I2C) void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) @@ -290,8 +247,6 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, } EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); - - /* Load an i2c sub-device. */ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, struct i2c_adapter *adapter, struct i2c_board_info *info, diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index e7821fb3cd86..015ff82da73c 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -100,15 +100,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ -/* Register/chip ident helper function */ - -struct i2c_client; /* forward reference */ -int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match); -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, - u32 ident, u32 revision); - -/* ------------------------------------------------------------------------- */ - /* I2C Helper functions */ struct i2c_driver; -- GitLab From 12869145718571ffa4f6e650a6f759934eeca0d9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 09:33:00 -0300 Subject: [PATCH 1583/2900] [media] v4l2-int-device: remove unused chip_ident reference Signed-off-by: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-int-device.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h index e6aa2318367b..0286c95814ff 100644 --- a/include/media/v4l2-int-device.h +++ b/include/media/v4l2-int-device.h @@ -220,8 +220,6 @@ enum v4l2_int_ioctl_num { vidioc_int_reset_num, /* VIDIOC_INT_INIT */ vidioc_int_init_num, - /* VIDIOC_DBG_G_CHIP_IDENT */ - vidioc_int_g_chip_ident_num, /* * @@ -303,6 +301,5 @@ V4L2_INT_WRAPPER_1(enum_frameintervals, struct v4l2_frmivalenum, *); V4L2_INT_WRAPPER_0(reset); V4L2_INT_WRAPPER_0(init); -V4L2_INT_WRAPPER_1(g_chip_ident, int, *); #endif -- GitLab From b71c99801e18eb172ae34851daf25044a3bf644a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 10:03:01 -0300 Subject: [PATCH 1584/2900] [media] v4l2-core: remove support for obsolete VIDIOC_DBG_G_CHIP_IDENT This has been replaced by the new and much better VIDIOC_DBG_G_CHIP_INFO. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 - drivers/media/v4l2-core/v4l2-dev.c | 1 - drivers/media/v4l2-core/v4l2-ioctl.c | 28 -- include/media/v4l2-chip-ident.h | 354 ------------------ include/media/v4l2-ioctl.h | 2 - include/media/v4l2-subdev.h | 4 +- include/uapi/linux/videodev2.h | 17 +- 7 files changed, 4 insertions(+), 403 deletions(-) delete mode 100644 include/media/v4l2-chip-ident.h diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index f1295519f285..8f7a6a454a4c 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -1074,7 +1074,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_TRY_DECODER_CMD: case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_G_CHIP_IDENT: case VIDIOC_S_HW_FREQ_SEEK: case VIDIOC_S_DV_TIMINGS: case VIDIOC_G_DV_TIMINGS: diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 2f3fac5345db..0c061e16502e 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -596,7 +596,6 @@ static void determine_valid_ioctls(struct video_device *vdev) set_bit(_IOC_NR(VIDIOC_DBG_G_REGISTER), valid_ioctls); set_bit(_IOC_NR(VIDIOC_DBG_S_REGISTER), valid_ioctls); #endif - SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident); /* yes, really vidioc_subscribe_event */ SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event); SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 423cbf948600..c9d9f01d21bc 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* Zero out the end of the struct pointed to by p. Everything after, but @@ -619,20 +618,6 @@ static void v4l_print_decoder_cmd(const void *arg, bool write_only) pr_info("pts=%llu\n", p->stop.pts); } -static void v4l_print_dbg_chip_ident(const void *arg, bool write_only) -{ - const struct v4l2_dbg_chip_ident *p = arg; - - pr_cont("type=%u, ", p->match.type); - if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) - pr_cont("name=%.*s, ", - (int)sizeof(p->match.name), p->match.name); - else - pr_cont("addr=%u, ", p->match.addr); - pr_cont("chip_ident=%u, revision=0x%x\n", - p->ident, p->revision); -} - static void v4l_print_dbg_chip_info(const void *arg, bool write_only) { const struct v4l2_dbg_chip_info *p = arg; @@ -1813,18 +1798,6 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, #endif } -static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) -{ - struct v4l2_dbg_chip_ident *p = arg; - - p->ident = V4L2_IDENT_NONE; - p->revision = 0; - if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) - return -EINVAL; - return ops->vidioc_g_chip_ident(file, fh, p); -} - static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2074,7 +2047,6 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), - IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0), IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h deleted file mode 100644 index 543f89c18896..000000000000 --- a/include/media/v4l2-chip-ident.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - v4l2 chip identifiers header - - This header provides a list of chip identifiers that can be returned - through the VIDIOC_DBG_G_CHIP_IDENT ioctl. - - Copyright (C) 2007 Hans Verkuil - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef V4L2_CHIP_IDENT_H_ -#define V4L2_CHIP_IDENT_H_ - -/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ - -/* KEEP THIS LIST ORDERED BY ID! - Otherwise it will be hard to see which ranges are already in use when - adding support to a new chip family. */ -enum { - /* general idents: reserved range 0-49 */ - V4L2_IDENT_NONE = 0, /* No chip matched */ - V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */ - V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */ - - /* module tvaudio: reserved range 50-99 */ - V4L2_IDENT_TVAUDIO = 50, /* A tvaudio chip, unknown which it is exactly */ - - /* Sony IMX074 */ - V4L2_IDENT_IMX074 = 74, - - /* module saa7110: just ident 100 */ - V4L2_IDENT_SAA7110 = 100, - - /* module saa7115: reserved range 101-149 */ - V4L2_IDENT_SAA7111 = 101, - V4L2_IDENT_SAA7111A = 102, - V4L2_IDENT_SAA7113 = 103, - V4L2_IDENT_SAA7114 = 104, - V4L2_IDENT_SAA7115 = 105, - V4L2_IDENT_SAA7118 = 108, - - V4L2_IDENT_GM7113C = 140, - - /* module saa7127: reserved range 150-199 */ - V4L2_IDENT_SAA7127 = 157, - V4L2_IDENT_SAA7129 = 159, - - /* module cx25840: reserved range 200-249 */ - V4L2_IDENT_CX25836 = 236, - V4L2_IDENT_CX25837 = 237, - V4L2_IDENT_CX25840 = 240, - V4L2_IDENT_CX25841 = 241, - V4L2_IDENT_CX25842 = 242, - V4L2_IDENT_CX25843 = 243, - - /* OmniVision sensors: reserved range 250-299 */ - V4L2_IDENT_OV7670 = 250, - V4L2_IDENT_OV7720 = 251, - V4L2_IDENT_OV7725 = 252, - V4L2_IDENT_OV7660 = 253, - V4L2_IDENT_OV9650 = 254, - V4L2_IDENT_OV9655 = 255, - V4L2_IDENT_SOI968 = 256, - V4L2_IDENT_OV9640 = 257, - V4L2_IDENT_OV6650 = 258, - V4L2_IDENT_OV2640 = 259, - V4L2_IDENT_OV9740 = 260, - V4L2_IDENT_OV5642 = 261, - - /* module saa7146: reserved range 300-309 */ - V4L2_IDENT_SAA7146 = 300, - - /* Conexant MPEG encoder/decoders: reserved range 400-420 */ - V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ - V4L2_IDENT_CX23415 = 415, - V4L2_IDENT_CX23416 = 416, - V4L2_IDENT_CX23417 = 417, - V4L2_IDENT_CX23418 = 418, - - /* module bt819: reserved range 810-819 */ - V4L2_IDENT_BT815A = 815, - V4L2_IDENT_BT817A = 817, - V4L2_IDENT_BT819A = 819, - - /* module au0828 */ - V4L2_IDENT_AU0828 = 828, - - /* module bttv: ident 848 + 849 */ - V4L2_IDENT_BT848 = 848, - V4L2_IDENT_BT849 = 849, - - /* module bt856: just ident 856 */ - V4L2_IDENT_BT856 = 856, - - /* module bt866: just ident 866 */ - V4L2_IDENT_BT866 = 866, - - /* module bttv: ident 878 + 879 */ - V4L2_IDENT_BT878 = 878, - V4L2_IDENT_BT879 = 879, - - /* module ks0127: reserved range 1120-1129 */ - V4L2_IDENT_KS0122S = 1122, - V4L2_IDENT_KS0127 = 1127, - V4L2_IDENT_KS0127B = 1128, - - /* module indycam: just ident 2000 */ - V4L2_IDENT_INDYCAM = 2000, - - /* module vp27smpx: just ident 2700 */ - V4L2_IDENT_VP27SMPX = 2700, - - /* module vpx3220: reserved range: 3210-3229 */ - V4L2_IDENT_VPX3214C = 3214, - V4L2_IDENT_VPX3216B = 3216, - V4L2_IDENT_VPX3220A = 3220, - - /* VX855 just ident 3409 */ - /* Other via devs could use 3314, 3324, 3327, 3336, 3364, 3353 */ - V4L2_IDENT_VIA_VX855 = 3409, - - /* module tvp5150 */ - V4L2_IDENT_TVP5150 = 5150, - - /* module saa5246a: just ident 5246 */ - V4L2_IDENT_SAA5246A = 5246, - - /* module saa5249: just ident 5249 */ - V4L2_IDENT_SAA5249 = 5249, - - /* module cs5345: just ident 5345 */ - V4L2_IDENT_CS5345 = 5345, - - /* module tea6415c: just ident 6415 */ - V4L2_IDENT_TEA6415C = 6415, - - /* module tea6420: just ident 6420 */ - V4L2_IDENT_TEA6420 = 6420, - - /* module saa6588: just ident 6588 */ - V4L2_IDENT_SAA6588 = 6588, - - /* module vs6624: just ident 6624 */ - V4L2_IDENT_VS6624 = 6624, - - /* module saa6752hs: reserved range 6750-6759 */ - V4L2_IDENT_SAA6752HS = 6752, - V4L2_IDENT_SAA6752HS_AC3 = 6753, - - /* modules tef6862: just ident 6862 */ - V4L2_IDENT_TEF6862 = 6862, - - /* module tvp7002: just ident 7002 */ - V4L2_IDENT_TVP7002 = 7002, - - /* module adv7170: just ident 7170 */ - V4L2_IDENT_ADV7170 = 7170, - - /* module adv7175: just ident 7175 */ - V4L2_IDENT_ADV7175 = 7175, - - /* module adv7180: just ident 7180 */ - V4L2_IDENT_ADV7180 = 7180, - - /* module adv7183: just ident 7183 */ - V4L2_IDENT_ADV7183 = 7183, - - /* module saa7185: just ident 7185 */ - V4L2_IDENT_SAA7185 = 7185, - - /* module saa7191: just ident 7191 */ - V4L2_IDENT_SAA7191 = 7191, - - /* module ths7303: just ident 7303 */ - V4L2_IDENT_THS7303 = 7303, - - /* module adv7343: just ident 7343 */ - V4L2_IDENT_ADV7343 = 7343, - - /* module ths7353: just ident 7353 */ - V4L2_IDENT_THS7353 = 7353, - - /* module adv7393: just ident 7393 */ - V4L2_IDENT_ADV7393 = 7393, - - /* module adv7604: just ident 7604 */ - V4L2_IDENT_ADV7604 = 7604, - - /* module saa7706h: just ident 7706 */ - V4L2_IDENT_SAA7706H = 7706, - - /* module mt9v011, just ident 8243 */ - V4L2_IDENT_MT9V011 = 8243, - - /* module wm8739: just ident 8739 */ - V4L2_IDENT_WM8739 = 8739, - - /* module wm8775: just ident 8775 */ - V4L2_IDENT_WM8775 = 8775, - - /* Marvell controllers starting at 8801 */ - V4L2_IDENT_CAFE = 8801, - V4L2_IDENT_ARMADA610 = 8802, - - /* AKM AK8813/AK8814 */ - V4L2_IDENT_AK8813 = 8813, - V4L2_IDENT_AK8814 = 8814, - - /* module cx23885 and cx25840 */ - V4L2_IDENT_CX23885 = 8850, - V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */ - V4L2_IDENT_CX23887 = 8870, - V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */ - V4L2_IDENT_CX23888 = 8880, - V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ - V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ - - /* module ad9389b: just ident 9389 */ - V4L2_IDENT_AD9389B = 9389, - - /* module tda9840: just ident 9840 */ - V4L2_IDENT_TDA9840 = 9840, - - /* module tw9910: just ident 9910 */ - V4L2_IDENT_TW9910 = 9910, - - /* module sn9c20x: just ident 10000 */ - V4L2_IDENT_SN9C20X = 10000, - - /* module cx231xx and cx25840 */ - V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */ - V4L2_IDENT_CX23100 = 23100, - V4L2_IDENT_CX23101 = 23101, - V4L2_IDENT_CX23102 = 23102, - - /* module msp3400: reserved range 34000-34999 for msp34xx */ - V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only - use internally (tveeprom.c). */ - - V4L2_IDENT_MSP3400B = 34002, - V4L2_IDENT_MSP3400C = 34003, - V4L2_IDENT_MSP3400D = 34004, - V4L2_IDENT_MSP3400G = 34007, - V4L2_IDENT_MSP3401G = 34017, - V4L2_IDENT_MSP3402G = 34027, - V4L2_IDENT_MSP3405D = 34054, - V4L2_IDENT_MSP3405G = 34057, - V4L2_IDENT_MSP3407D = 34074, - V4L2_IDENT_MSP3407G = 34077, - - V4L2_IDENT_MSP3410B = 34102, - V4L2_IDENT_MSP3410C = 34103, - V4L2_IDENT_MSP3410D = 34104, - V4L2_IDENT_MSP3410G = 34107, - V4L2_IDENT_MSP3411G = 34117, - V4L2_IDENT_MSP3412G = 34127, - V4L2_IDENT_MSP3415D = 34154, - V4L2_IDENT_MSP3415G = 34157, - V4L2_IDENT_MSP3417D = 34174, - V4L2_IDENT_MSP3417G = 34177, - - V4L2_IDENT_MSP3420G = 34207, - V4L2_IDENT_MSP3421G = 34217, - V4L2_IDENT_MSP3422G = 34227, - V4L2_IDENT_MSP3425G = 34257, - V4L2_IDENT_MSP3427G = 34277, - - V4L2_IDENT_MSP3430G = 34307, - V4L2_IDENT_MSP3431G = 34317, - V4L2_IDENT_MSP3435G = 34357, - V4L2_IDENT_MSP3437G = 34377, - - V4L2_IDENT_MSP3440G = 34407, - V4L2_IDENT_MSP3441G = 34417, - V4L2_IDENT_MSP3442G = 34427, - V4L2_IDENT_MSP3445G = 34457, - V4L2_IDENT_MSP3447G = 34477, - - V4L2_IDENT_MSP3450G = 34507, - V4L2_IDENT_MSP3451G = 34517, - V4L2_IDENT_MSP3452G = 34527, - V4L2_IDENT_MSP3455G = 34557, - V4L2_IDENT_MSP3457G = 34577, - - V4L2_IDENT_MSP3460G = 34607, - V4L2_IDENT_MSP3461G = 34617, - V4L2_IDENT_MSP3465G = 34657, - V4L2_IDENT_MSP3467G = 34677, - - /* module msp3400: reserved range 44000-44999 for msp44xx */ - V4L2_IDENT_MSP4400G = 44007, - V4L2_IDENT_MSP4408G = 44087, - V4L2_IDENT_MSP4410G = 44107, - V4L2_IDENT_MSP4418G = 44187, - V4L2_IDENT_MSP4420G = 44207, - V4L2_IDENT_MSP4428G = 44287, - V4L2_IDENT_MSP4440G = 44407, - V4L2_IDENT_MSP4448G = 44487, - V4L2_IDENT_MSP4450G = 44507, - V4L2_IDENT_MSP4458G = 44587, - - /* Micron CMOS sensor chips: 45000-45099 */ - V4L2_IDENT_MT9M001C12ST = 45000, - V4L2_IDENT_MT9M001C12STM = 45005, - V4L2_IDENT_MT9M111 = 45007, - V4L2_IDENT_MT9M112 = 45008, - V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ - V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ - V4L2_IDENT_MT9T031 = 45020, - V4L2_IDENT_MT9T111 = 45021, - V4L2_IDENT_MT9T112 = 45022, - V4L2_IDENT_MT9V111 = 45031, - V4L2_IDENT_MT9V112 = 45032, - - /* HV7131R CMOS sensor: just ident 46000 */ - V4L2_IDENT_HV7131R = 46000, - - /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ - V4L2_IDENT_RJ54N1CB0C = 51980, - - /* module m52790: just ident 52790 */ - V4L2_IDENT_M52790 = 52790, - - /* module cs53132a: just ident 53132 */ - V4L2_IDENT_CS53l32A = 53132, - - /* modules upd61151 MPEG2 encoder: just ident 54000 */ - V4L2_IDENT_UPD61161 = 54000, - /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */ - V4L2_IDENT_UPD61162 = 54001, - - /* module upd64031a: just ident 64031 */ - V4L2_IDENT_UPD64031A = 64031, - - /* module upd64083: just ident 64083 */ - V4L2_IDENT_UPD64083 = 64083, - - /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */ -}; - -#endif diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 931652f0e2af..e0b74a430b3a 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -247,8 +247,6 @@ struct v4l2_ioctl_ops { int (*vidioc_g_chip_info) (struct file *file, void *fh, struct v4l2_dbg_chip_info *chip); #endif - int (*vidioc_g_chip_ident) (struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip); int (*vidioc_enum_framesizes) (struct file *file, void *fh, struct v4l2_frmsizeenum *fsize); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 5298d678d0f3..21fc9e16d7be 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -88,7 +88,6 @@ struct v4l2_decode_vbi_line { /* Core ops: it is highly recommended to implement at least these ops: - g_chip_ident log_status g_register s_register @@ -145,7 +144,6 @@ struct v4l2_subdev_io_pin_config { performed later. It must not sleep. *Called from an IRQ context*. */ struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n, struct v4l2_subdev_io_pin_config *pincfg); @@ -660,7 +658,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, /* Call an ops of a v4l2_subdev, doing the right checks against NULL pointers. - Example: err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + Example: err = v4l2_subdev_call(sd, core, s_std, norm); */ #define v4l2_subdev_call(sd, o, f, args...) \ (!(sd) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 2c5e67a45436..95ef4551edc1 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1787,11 +1787,13 @@ struct v4l2_event_subscription { /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ #define V4L2_CHIP_MATCH_BRIDGE 0 /* Match against chip ID on the bridge (0 for the bridge) */ +#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ + +/* The following four defines are no longer in use */ #define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE #define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ #define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ #define V4L2_CHIP_MATCH_AC97 3 /* Match against ancillary AC97 chip */ -#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ struct v4l2_dbg_match { __u32 type; /* Match type */ @@ -1808,13 +1810,6 @@ struct v4l2_dbg_register { __u64 val; } __attribute__ ((packed)); -/* VIDIOC_DBG_G_CHIP_IDENT */ -struct v4l2_dbg_chip_ident { - struct v4l2_dbg_match match; - __u32 ident; /* chip identifier as specified in */ - __u32 revision; /* chip revision, chip specific */ -} __attribute__ ((packed)); - #define V4L2_CHIP_FL_READABLE (1 << 0) #define V4L2_CHIP_FL_WRITABLE (1 << 1) @@ -1915,12 +1910,6 @@ struct v4l2_create_buffers { #define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) #define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) -/* Experimental, meant for debugging, testing and internal use. - Never use this ioctl in applications! - Note: this ioctl is deprecated in favor of VIDIOC_DBG_G_CHIP_INFO and - will go away in the future. */ -#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) - #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) -- GitLab From a6edca3c1b4e78c099a426bbe1e724bf70cf3515 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 09:45:23 -0300 Subject: [PATCH 1585/2900] [media] DocBook: remove references to the dropped VIDIOC_DBG_G_CHIP_IDENT ioctl Signed-off-by: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 14 +- Documentation/DocBook/media/v4l/v4l2.xml | 11 +- .../media/v4l/vidioc-dbg-g-chip-ident.xml | 271 ------------------ .../media/v4l/vidioc-dbg-g-chip-info.xml | 17 +- .../media/v4l/vidioc-dbg-g-register.xml | 40 +-- 5 files changed, 24 insertions(+), 329 deletions(-) delete mode 100644 Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index f43542ae2981..0c7195e3e093 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2254,7 +2254,7 @@ video encoding. The VIDIOC_G_CHIP_IDENT ioctl was renamed -to VIDIOC_G_CHIP_IDENT_OLD and &VIDIOC-DBG-G-CHIP-IDENT; +to VIDIOC_G_CHIP_IDENT_OLD and VIDIOC_DBG_G_CHIP_IDENT was introduced in its place. The old struct v4l2_chip_ident was renamed to v4l2_chip_ident_old. @@ -2513,6 +2513,16 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 3.11 + + + Remove obsolete VIDIOC_DBG_G_CHIP_IDENT ioctl. + + + +
+
Relation of V4L2 to other Linux multimedia APIs @@ -2596,7 +2606,7 @@ and may change in the future. ioctls. - &VIDIOC-DBG-G-CHIP-IDENT; ioctl. + &VIDIOC-DBG-G-CHIP-INFO; ioctl. &VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index bfe823dd0f31..8469fe13945c 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -140,6 +140,14 @@ structs, ioctls) must be noted in more detail in the history chapter (compat.xml), along with the possible impact on existing drivers and applications. --> + + 3.11 + 2013-05-26 + hv + Remove obsolete VIDIOC_DBG_G_CHIP_IDENT ioctl. + + + 3.10 2013-03-25 @@ -493,7 +501,7 @@ and discussions on the V4L mailing list. Video for Linux Two API Specification - Revision 3.10 + Revision 3.11 &sub-common; @@ -547,7 +555,6 @@ and discussions on the V4L mailing list. &sub-create-bufs; &sub-cropcap; - &sub-dbg-g-chip-ident; &sub-dbg-g-chip-info; &sub-dbg-g-register; &sub-decoder-cmd; diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml deleted file mode 100644 index 921e18550d26..000000000000 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml +++ /dev/null @@ -1,271 +0,0 @@ - - - ioctl VIDIOC_DBG_G_CHIP_IDENT - &manvol; - - - - VIDIOC_DBG_G_CHIP_IDENT - Identify the chips on a TV card - - - - - - int ioctl - int fd - int request - struct v4l2_dbg_chip_ident -*argp - - - - - - Arguments - - - - fd - - &fd; - - - - request - - VIDIOC_DBG_G_CHIP_IDENT - - - - argp - - - - - - - - - Description - - - Experimental - - This is an experimental interface and may change in -the future. - - - For driver debugging purposes this ioctl allows test -applications to query the driver about the chips present on the TV -card. Regular applications must not use it. When you found a chip -specific bug, please contact the linux-media mailing list (&v4l-ml;) -so it can be fixed. - - To query the driver applications must initialize the -match.type and -match.addr or match.name -fields of a &v4l2-dbg-chip-ident; -and call VIDIOC_DBG_G_CHIP_IDENT with a pointer to -this structure. On success the driver stores information about the -selected chip in the ident and -revision fields. On failure the structure -remains unchanged. - - When match.type is -V4L2_CHIP_MATCH_HOST, -match.addr selects the nth non-&i2c; chip -on the TV card. You can enumerate all chips by starting at zero and -incrementing match.addr by one until -VIDIOC_DBG_G_CHIP_IDENT fails with an &EINVAL;. -The number zero always selects the host chip, ⪚ the chip connected -to the PCI or USB bus. - - When match.type is -V4L2_CHIP_MATCH_I2C_DRIVER, -match.name contains the I2C driver name. -For instance -"saa7127" will match any chip -supported by the saa7127 driver, regardless of its &i2c; bus address. -When multiple chips supported by the same driver are present, the -ioctl will return V4L2_IDENT_AMBIGUOUS in the -ident field. - - When match.type is -V4L2_CHIP_MATCH_I2C_ADDR, -match.addr selects a chip by its 7 bit -&i2c; bus address. - - When match.type is -V4L2_CHIP_MATCH_AC97, -match.addr selects the nth AC97 chip -on the TV card. You can enumerate all chips by starting at zero and -incrementing match.addr by one until -VIDIOC_DBG_G_CHIP_IDENT fails with an &EINVAL;. - - On success, the ident field will -contain a chip ID from the Linux -media/v4l2-chip-ident.h header file, and the -revision field will contain a driver -specific value, or zero if no particular revision is associated with -this chip. - - When the driver could not identify the selected chip, -ident will contain -V4L2_IDENT_UNKNOWN. When no chip matched -the ioctl will succeed but the -ident field will contain -V4L2_IDENT_NONE. If multiple chips matched, -ident will contain -V4L2_IDENT_AMBIGUOUS. In all these cases the -revision field remains unchanged. - - This ioctl is optional, not all drivers may support it. It -was introduced in Linux 2.6.21, but the API was changed to the -one described here in 2.6.29. - - We recommended the v4l2-dbg -utility over calling this ioctl directly. It is available from the -LinuxTV v4l-dvb repository; see http://linuxtv.org/repo/ for -access instructions. - - -
- struct <structname>v4l2_dbg_match</structname> - - &cs-ustr; - - - __u32 - type - See for a list of -possible types. - - - union - (anonymous) - - - - __u32 - addr - Match a chip by this number, interpreted according -to the type field. - - - - char - name[32] - Match a chip by this name, interpreted according -to the type field. - - - -
- - - struct <structname>v4l2_dbg_chip_ident</structname> - - &cs-str; - - - struct v4l2_dbg_match - match - How to match the chip, see . - - - __u32 - ident - A chip identifier as defined in the Linux -media/v4l2-chip-ident.h header file, or one of -the values from . - - - __u32 - revision - A chip revision, chip and driver specific. - - - -
- - - - Chip Match Types - - &cs-def; - - - V4L2_CHIP_MATCH_BRIDGE - 0 - Match the nth chip on the card, zero for the - bridge chip. Does not match sub-devices. - - - V4L2_CHIP_MATCH_I2C_DRIVER - 1 - Match an &i2c; chip by its driver name. - - - V4L2_CHIP_MATCH_I2C_ADDR - 2 - Match a chip by its 7 bit &i2c; bus address. - - - V4L2_CHIP_MATCH_AC97 - 3 - Match the nth anciliary AC97 chip. - - - V4L2_CHIP_MATCH_SUBDEV - 4 - Match the nth sub-device. Can't be used with this ioctl. - - - -
- - - - Chip Identifiers - - &cs-def; - - - V4L2_IDENT_NONE - 0 - No chip matched. - - - V4L2_IDENT_AMBIGUOUS - 1 - Multiple chips matched. - - - V4L2_IDENT_UNKNOWN - 2 - A chip is present at this address, but the driver -could not identify it. - - - -
- - - - &return-value; - - - - EINVAL - - The match_type is invalid. - - - - - diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml index 80e8021369f6..4c4603c135fe 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml @@ -131,7 +131,7 @@ to the type field. char name[32] Match a chip by this name, interpreted according -to the type field. +to the type field. Currently unused. @@ -181,21 +181,6 @@ is set, then the driver supports reading registers from the device. If Match the nth chip on the card, zero for the bridge chip. Does not match sub-devices. - - V4L2_CHIP_MATCH_I2C_DRIVER - 1 - Match an &i2c; chip by its driver name. Can't be used with this ioctl. - - - V4L2_CHIP_MATCH_I2C_ADDR - 2 - Match a chip by its 7 bit &i2c; bus address. Can't be used with this ioctl. - - - V4L2_CHIP_MATCH_AC97 - 3 - Match the nth anciliary AC97 chip. Can't be used with this ioctl. - V4L2_CHIP_MATCH_SUBDEV 4 diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml index e23285fad3bf..32c4bde9d4b8 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml @@ -101,27 +101,6 @@ on the TV card. The number zero always selects the host chip, ⪚ the chip connected to the PCI or USB bus. You can find out which chips are present with the &VIDIOC-DBG-G-CHIP-INFO; ioctl. - When match.type is -V4L2_CHIP_MATCH_I2C_DRIVER, -match.name contains the I2C driver name. -For instance -"saa7127" will match any chip -supported by the saa7127 driver, regardless of its &i2c; bus address. -When multiple chips supported by the same driver are present, the -effect of these ioctls is undefined. Again with the -&VIDIOC-DBG-G-CHIP-INFO; ioctl you can find out which &i2c; chips are -present. - - When match.type is -V4L2_CHIP_MATCH_I2C_ADDR, -match.addr selects a chip by its 7 bit &i2c; -bus address. - - When match.type is -V4L2_CHIP_MATCH_AC97, -match.addr selects the nth AC97 chip -on the TV card. - When match.type is V4L2_CHIP_MATCH_SUBDEV, match.addr selects the nth sub-device. @@ -160,7 +139,7 @@ access instructions. __u32 type - See for a list of + See for a list of possible types. @@ -179,7 +158,7 @@ to the type field. char name[32] Match a chip by this name, interpreted according -to the type field. +to the type field. Currently unused. @@ -231,21 +210,6 @@ register. Match the nth chip on the card, zero for the bridge chip. Does not match sub-devices. - - V4L2_CHIP_MATCH_I2C_DRIVER - 1 - Match an &i2c; chip by its driver name. - - - V4L2_CHIP_MATCH_I2C_ADDR - 2 - Match a chip by its 7 bit &i2c; bus address. - - - V4L2_CHIP_MATCH_AC97 - 3 - Match the nth anciliary AC97 chip. - V4L2_CHIP_MATCH_SUBDEV 4 -- GitLab From da6a855320a6e056add76ea0503b01efdbb0de36 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 26 May 2013 10:31:01 -0300 Subject: [PATCH 1586/2900] [media] DocBook: remove obsolete note from the dbg_g_register doc Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-dbg-g-register.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml index 32c4bde9d4b8..3d038e75d12b 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml @@ -105,15 +105,6 @@ present with the &VIDIOC-DBG-G-CHIP-INFO; ioctl. V4L2_CHIP_MATCH_SUBDEV, match.addr selects the nth sub-device. - - Success not guaranteed - - Due to a flaw in the Linux &i2c; bus driver these ioctls may -return successfully without actually reading or writing a register. To -catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-INFO; -call confirming the presence of the selected &i2c; chip. - - These ioctls are optional, not all drivers may support them. However when a driver supports these ioctls it must also support &VIDIOC-DBG-G-CHIP-INFO;. Conversely it may support -- GitLab From 7feeb1482153575bc9221eff098e9a1313522dfe Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 29 May 2013 06:22:02 -0300 Subject: [PATCH 1587/2900] [media] cx88: fix register mask Ensure that the register is aligned to a dword, otherwise the read could read out-of-range data. Signed-off-by: Hans Verkuil Cc: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx88/cx88-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index 5b26ece4aea5..ecf21d9f1f34 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1360,7 +1360,7 @@ static int vidioc_g_register (struct file *file, void *fh, struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; /* cx2388x has a 24-bit register space */ - reg->val = cx_read(reg->reg & 0xffffff); + reg->val = cx_read(reg->reg & 0xfffffc); reg->size = 4; return 0; } @@ -1370,7 +1370,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - cx_write(reg->reg & 0xffffff, reg->val); + cx_write(reg->reg & 0xfffffc, reg->val); return 0; } #endif -- GitLab From 9e882e3bc97c7774b93f3db483d2e75767b5cad1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 06:04:04 -0300 Subject: [PATCH 1588/2900] [media] v4l2-device: check if already unregistered It was possible to unregister an already unregistered v4l2_device struct. Add a check whether that already happened and just return if that was the case. Also refuse to register a v4l2_device if both the dev and name fields are empty. A warning was already produced in that case, but since the name field is now used to detect whether or not the v4l2_device was already unregistered this particular combination should be rejected. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-device.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 2dbfebc0ca85..02d1b6327117 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -44,7 +44,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) v4l2_dev->dev = dev; if (dev == NULL) { /* If dev == NULL, then name must be filled in by the caller */ - WARN_ON(!v4l2_dev->name[0]); + if (WARN_ON(!v4l2_dev->name[0])) + return -EINVAL; return 0; } @@ -105,7 +106,9 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; - if (v4l2_dev == NULL) + /* Just return if v4l2_dev is NULL or if it was already + * unregistered before. */ + if (v4l2_dev == NULL || !v4l2_dev->name[0]) return; v4l2_device_disconnect(v4l2_dev); @@ -135,6 +138,8 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) } #endif } + /* Mark as unregistered, thus preventing duplicate unregistrations */ + v4l2_dev->name[0] = '\0'; } EXPORT_SYMBOL_GPL(v4l2_device_unregister); -- GitLab From 14381c26771f1a7d6acc57e4c944a9813596e6cf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 09:27:41 -0300 Subject: [PATCH 1589/2900] [media] soc_camera: replace vdev->parent by vdev->v4l2_dev The parent field will eventually disappear to be replaced by v4l2_dev. soc_camera does provide a v4l2_device struct but did not point to it in struct video_device. This is now fixed. Now the video nodes can be found under the correct platform bus, and the advanced debug ioctls work correctly as well (the core implementation of those ioctls requires that v4l2_dev is set correctly). Signed-off-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 5 +++-- include/media/soc_camera.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index fcdd8734f3ec..5099eebf994d 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -524,7 +524,7 @@ static int soc_camera_open(struct file *file) return -ENODEV; } - icd = dev_get_drvdata(vdev->parent); + icd = video_get_drvdata(vdev); ici = to_soc_camera_host(icd->parent); ret = try_module_get(ici->ops->owner) ? 0 : -ENODEV; @@ -1477,7 +1477,7 @@ static int video_dev_create(struct soc_camera_device *icd) strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); - vdev->parent = icd->pdev; + vdev->v4l2_dev = &ici->v4l2_dev; vdev->fops = &soc_camera_fops; vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; @@ -1500,6 +1500,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd) if (!icd->parent) return -ENODEV; + video_set_drvdata(icd->vdev, icd); ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { dev_err(icd->pdev, "video_register_device failed: %d\n", ret); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index ff77d08c30fd..31a4bfe42194 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -346,9 +346,9 @@ static inline struct soc_camera_subdev_desc *soc_camera_i2c_to_desc(const struct return client->dev.platform_data; } -static inline struct v4l2_subdev *soc_camera_vdev_to_subdev(const struct video_device *vdev) +static inline struct v4l2_subdev *soc_camera_vdev_to_subdev(struct video_device *vdev) { - struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); + struct soc_camera_device *icd = video_get_drvdata(vdev); return soc_camera_to_subdev(icd); } -- GitLab From 874d91db7840d405d62450ac9b65867494ef7179 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 07:27:37 -0300 Subject: [PATCH 1590/2900] [media] cx23885-417: use v4l2_dev instead of the deprecated parent field Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-417.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index f4f9ef0d98e2..e3fc2c71808a 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1732,7 +1732,7 @@ static struct video_device *cx23885_video_dev_alloc( *vfd = *template; snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", cx23885_boards[tsport->dev->board].name, type); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } -- GitLab From 9592bd0a9e74c344f674663137e5ccff7a39f7d0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 07:30:08 -0300 Subject: [PATCH 1591/2900] [media] zoran: use v4l2_dev instead of the deprecated parent field Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/zoran/zoran_card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index bb53d2488ad0..923d59a321f8 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -1050,7 +1050,7 @@ static int zr36057_init (struct zoran *zr) * Now add the template and register the device unit. */ memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); - zr->video_dev->parent = &zr->pci_dev->dev; + zr->video_dev->v4l2_dev = &zr->v4l2_dev; strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); /* It's not a mem2mem device, but you can both capture and output from one and the same device. This should really be split up into two -- GitLab From f1741fa8dd4a561e883cf60f103c40eda8790d80 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 05:46:30 -0300 Subject: [PATCH 1592/2900] [media] sn9c102_core: add v4l2_device and replace parent with v4l2_dev This driver did not yet support struct v4l2_device, so add it. This make it possible to replace the deprecated parent field with the v4l2_dev field, allowing the eventual removal of the parent field. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/sn9c102/sn9c102.h | 3 +++ drivers/media/usb/sn9c102/sn9c102_core.c | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/sn9c102/sn9c102.h b/drivers/media/usb/sn9c102/sn9c102.h index 2bc153e869be..8a917f060503 100644 --- a/drivers/media/usb/sn9c102/sn9c102.h +++ b/drivers/media/usb/sn9c102/sn9c102.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,8 @@ static DECLARE_RWSEM(sn9c102_dev_lock); struct sn9c102_device { struct video_device* v4ldev; + struct v4l2_device v4l2_dev; + enum sn9c102_bridge bridge; struct sn9c102_sensor sensor; diff --git a/drivers/media/usb/sn9c102/sn9c102_core.c b/drivers/media/usb/sn9c102/sn9c102_core.c index c957e9aa6077..2cb44de2b92c 100644 --- a/drivers/media/usb/sn9c102/sn9c102_core.c +++ b/drivers/media/usb/sn9c102/sn9c102_core.c @@ -1737,6 +1737,7 @@ static void sn9c102_release_resources(struct kref *kref) video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + v4l2_device_unregister(&cam->v4l2_dev); usb_put_dev(cam->usbdev); kfree(cam->control_buffer); kfree(cam); @@ -3254,6 +3255,13 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->usbdev = udev; + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) { + dev_err(&intf->dev, "v4l2_device_register failed\n"); + err = -ENOMEM; + goto fail; + } + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { DBG(1, "kzalloc() failed"); err = -ENOMEM; @@ -3325,7 +3333,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); cam->v4ldev->fops = &sn9c102_fops; cam->v4ldev->release = video_device_release; - cam->v4ldev->parent = &udev->dev; + cam->v4ldev->v4l2_dev = &cam->v4l2_dev; init_completion(&cam->probe); @@ -3377,6 +3385,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) kfree(cam->control_buffer); if (cam->v4ldev) video_device_release(cam->v4ldev); + v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); } return err; @@ -3407,6 +3416,8 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) wake_up_interruptible_all(&cam->wait_open); + v4l2_device_disconnect(&cam->v4l2_dev); + kref_put(&cam->kref, sn9c102_release_resources); up_write(&sn9c102_dev_lock); -- GitLab From d66de790c77b98589b93cb327bde2cddd2a4c2cc Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 05:49:50 -0300 Subject: [PATCH 1593/2900] [media] saa7164: add v4l2_device and replace parent with v4l2_dev This driver did not yet support struct v4l2_device, so add it. This make it possible to replace the deprecated parent field with the v4l2_dev field, allowing the eventual removal of the parent field. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7164/saa7164-core.c | 7 +++++++ drivers/media/pci/saa7164/saa7164-encoder.c | 2 +- drivers/media/pci/saa7164/saa7164-vbi.c | 2 +- drivers/media/pci/saa7164/saa7164.h | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 7618fdae811e..5d27865784c5 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1196,6 +1196,11 @@ static int saa7164_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + if (v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev)) { + dev_err(&pci_dev->dev, "v4l2_device_register failed\n"); + goto fail_free; + } + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { @@ -1367,6 +1372,7 @@ static int saa7164_initdev(struct pci_dev *pci_dev, fail_irq: saa7164_dev_unregister(dev); fail_free: + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return err; } @@ -1439,6 +1445,7 @@ static void saa7164_finidev(struct pci_dev *pci_dev) mutex_unlock(&devlist); saa7164_dev_unregister(dev); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); } diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 7b7ed97b8503..9266965412c3 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -1348,7 +1348,7 @@ static struct video_device *saa7164_encoder_alloc( snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7164_boards[dev->board].name); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 552c01ad9f63..6e025fea2542 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -1297,7 +1297,7 @@ static struct video_device *saa7164_vbi_alloc( snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7164_boards[dev->board].name); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 2df47ea28289..8b29e8990301 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -63,6 +63,7 @@ #include #include #include +#include #include "saa7164-reg.h" #include "saa7164-types.h" @@ -427,6 +428,8 @@ struct saa7164_dev { struct list_head devlist; atomic_t refcount; + struct v4l2_device v4l2_dev; + /* pci stuff */ struct pci_dev *pci; unsigned char pci_rev, pci_lat; -- GitLab From a28fbd04facbffe9374f25c3a19c54ce4f186361 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 10 Jun 2013 09:16:25 -0300 Subject: [PATCH 1594/2900] [media] pvrusb2: use v4l2_dev instead of the deprecated parent field Signed-off-by: Hans Verkuil Acked-by: Mike Isely Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 4 ++++ drivers/media/usb/pvrusb2/pvrusb2-hdw.h | 4 ++++ drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 7 ++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index d32920929660..c4d51d78f837 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2704,6 +2704,10 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) pvr2_hdw_render_useless(hdw); } +void pvr2_hdw_set_v4l2_dev(struct pvr2_hdw *hdw, struct video_device *vdev) +{ + vdev->v4l2_dev = &hdw->v4l2_dev; +} /* Destroy hardware interaction structure */ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 1a135cf6ae4e..41847076f51a 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -22,6 +22,7 @@ #include #include +#include #include "pvrusb2-io.h" #include "pvrusb2-ctrl.h" @@ -138,6 +139,9 @@ const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *); /* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *); +/* Sets v4l2_dev of a video_device struct */ +void pvr2_hdw_set_v4l2_dev(struct pvr2_hdw *, struct video_device *); + /* Get the number of defined controls */ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *); diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 82f619ba5cca..d77069e12dc4 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -870,8 +871,8 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip) { if (!dip) return; - if (!dip->devbase.parent) return; - dip->devbase.parent = NULL; + if (!dip->devbase.v4l2_dev->dev) return; + dip->devbase.v4l2_dev->dev = NULL; device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE); } @@ -1321,7 +1322,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { mindevnum = nr_ptr[unit_number]; } - dip->devbase.parent = &usbdev->dev; + pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase); if ((video_register_device(&dip->devbase, dip->v4l_type, mindevnum) < 0) && (video_register_device(&dip->devbase, -- GitLab From b60f9aa1a9fcf69df963c1f06ee0594d836f6760 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 06:02:38 -0300 Subject: [PATCH 1595/2900] [media] f_uvc: add v4l2_device and replace parent with v4l2_dev This driver did not yet support struct v4l2_device, so add it. This make it possible to replace the deprecated parent field with the v4l2_dev field, allowing the eventual removal of the parent field. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/usb/gadget/f_uvc.c | 9 ++++++++- drivers/usb/gadget/uvc.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 38dcedddc52c..1d06567ff41e 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -413,7 +413,7 @@ uvc_register_video(struct uvc_device *uvc) if (video == NULL) return -ENOMEM; - video->parent = &cdev->gadget->dev; + video->v4l2_dev = &uvc->v4l2_dev; video->fops = &uvc_v4l2_fops; video->release = video_device_release; strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); @@ -570,6 +570,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "uvc_function_unbind\n"); video_unregister_device(uvc->vdev); + v4l2_device_unregister(&uvc->v4l2_dev); uvc->control_ep->driver_data = NULL; uvc->video.ep->driver_data = NULL; @@ -697,6 +698,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) if ((ret = usb_function_deactivate(f)) < 0) goto error; + if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { + printk(KERN_INFO "v4l2_device_register failed\n"); + goto error; + } + /* Initialise video. */ ret = uvc_video_init(&uvc->video); if (ret < 0) @@ -712,6 +718,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) return 0; error: + v4l2_device_unregister(&uvc->v4l2_dev); if (uvc->vdev) video_device_release(uvc->vdev); diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 817e9e19cecf..7a9111de8054 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -57,6 +57,7 @@ struct uvc_event #include #include #include +#include #include "uvc_queue.h" @@ -145,6 +146,7 @@ enum uvc_state struct uvc_device { struct video_device *vdev; + struct v4l2_device v4l2_dev; enum uvc_state state; struct usb_function func; struct uvc_video video; -- GitLab From 7a86969bd65eb7f19ea1c281c686a75429be950a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 06:03:27 -0300 Subject: [PATCH 1596/2900] [media] omap24xxcam: add v4l2_device and replace parent with v4l2_dev This driver did not yet support struct v4l2_device, so add it. This make it possible to replace the deprecated parent field with the v4l2_dev field, allowing the eventual removal of the parent field. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap24xxcam.c | 9 ++++++++- drivers/media/platform/omap24xxcam.h | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/omap24xxcam.c b/drivers/media/platform/omap24xxcam.c index debb44ceb185..d2b440c842b3 100644 --- a/drivers/media/platform/omap24xxcam.c +++ b/drivers/media/platform/omap24xxcam.c @@ -1656,7 +1656,7 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) } vfd->release = video_device_release; - vfd->parent = cam->dev; + vfd->v4l2_dev = &cam->v4l2_dev; strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); vfd->fops = &omap24xxcam_fops; @@ -1752,6 +1752,11 @@ static int omap24xxcam_probe(struct platform_device *pdev) cam->dev = &pdev->dev; + if (v4l2_device_register(&pdev->dev, &cam->v4l2_dev)) { + dev_err(&pdev->dev, "v4l2_device_register failed\n"); + goto err; + } + /* * Impose a lower limit on the amount of memory allocated for * capture. We require at least enough memory to double-buffer @@ -1849,6 +1854,8 @@ static int omap24xxcam_remove(struct platform_device *pdev) cam->mmio_base_phys = 0; } + v4l2_device_unregister(&cam->v4l2_dev); + kfree(cam); return 0; diff --git a/drivers/media/platform/omap24xxcam.h b/drivers/media/platform/omap24xxcam.h index c4395956a493..7f6f79155537 100644 --- a/drivers/media/platform/omap24xxcam.h +++ b/drivers/media/platform/omap24xxcam.h @@ -29,6 +29,7 @@ #include #include +#include /* * @@ -462,6 +463,8 @@ struct omap24xxcam_device { */ struct mutex mutex; + struct v4l2_device v4l2_dev; + /*** general driver state information ***/ atomic_t users; /* -- GitLab From d481c581dfe43be11a17728b5c84c2d4b5beecb2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jun 2013 10:57:10 -0300 Subject: [PATCH 1597/2900] [media] saa7134: use v4l2_dev instead of the deprecated parent field Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-empress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index e66bc3d969cf..3022eb2a7925 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -511,7 +511,7 @@ static int empress_init(struct saa7134_dev *dev) if (NULL == dev->empress_dev) return -ENOMEM; *(dev->empress_dev) = saa7134_empress_template; - dev->empress_dev->parent = &dev->pci->dev; + dev->empress_dev->v4l2_dev = &dev->v4l2_dev; dev->empress_dev->release = video_device_release; snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name), "%s empress (%s)", dev->name, -- GitLab From 1c1d86a1ea07506c070cfb217a009d53990bdeb0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 11:15:12 -0300 Subject: [PATCH 1598/2900] [media] v4l2: always require v4l2_dev, rename parent to dev_parent The last set of drivers still using the parent field of video_device instead of the v4l2_dev field have been converted, so v4l2_dev is now always set. A proper pointer to v4l2_dev is necessary these days otherwise the advanced debugging ioctls will not work when addressing sub-devices. It also ensures that the core can always go from a video_device struct to the top-level v4l2_device struct. There is still one single use case for the parent pointer: if there are multiple busses, each being the parent of one or more video nodes, and if they all share the same v4l2_device struct. In that case one still needs a parent pointer since the v4l2_device struct can only refer to a single parent device. The cx88 driver is one such case. Unfortunately, the cx88 failed to set the parent pointer since 3.6. The next patch will correct this. In order to support this use-case the parent pointer is only renamed to dev_parent, not removed altogether. It has been renamed to ensure that the compiler will catch any (possibly out-of-tree) drivers that were missed during the conversion. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dev.c | 34 ++++++++++++---------------- drivers/media/v4l2-core/v4l2-ioctl.c | 7 +----- include/media/v4l2-dev.h | 4 ++-- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 0c061e16502e..c8859d6ff6ad 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -495,8 +495,8 @@ static const struct file_operations v4l2_fops = { }; /** - * get_index - assign stream index number based on parent device - * @vdev: video_device to assign index number to, vdev->parent should be assigned + * get_index - assign stream index number based on v4l2_dev + * @vdev: video_device to assign index number to, vdev->v4l2_dev should be assigned * * Note that when this is called the new device has not yet been registered * in the video_device array, but it was able to obtain a minor number. @@ -514,15 +514,11 @@ static int get_index(struct video_device *vdev) static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - /* Some drivers do not set the parent. In that case always return 0. */ - if (vdev->parent == NULL) - return 0; - bitmap_zero(used, VIDEO_NUM_DEVICES); for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && - video_device[i]->parent == vdev->parent) { + video_device[i]->v4l2_dev == vdev->v4l2_dev) { set_bit(video_device[i]->index, used); } } @@ -775,6 +771,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, /* the release callback MUST be present */ if (WARN_ON(!vdev->release)) return -EINVAL; + /* the v4l2_dev pointer MUST be present */ + if (WARN_ON(!vdev->v4l2_dev)) + return -EINVAL; /* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); @@ -802,16 +801,14 @@ int __video_register_device(struct video_device *vdev, int type, int nr, vdev->vfl_type = type; vdev->cdev = NULL; - if (vdev->v4l2_dev) { - if (vdev->v4l2_dev->dev) - vdev->parent = vdev->v4l2_dev->dev; - if (vdev->ctrl_handler == NULL) - vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; - /* If the prio state pointer is NULL, then use the v4l2_device - prio state. */ - if (vdev->prio == NULL) - vdev->prio = &vdev->v4l2_dev->prio; - } + if (vdev->dev_parent == NULL) + vdev->dev_parent = vdev->v4l2_dev->dev; + if (vdev->ctrl_handler == NULL) + vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; + /* If the prio state pointer is NULL, then use the v4l2_device + prio state. */ + if (vdev->prio == NULL) + vdev->prio = &vdev->v4l2_dev->prio; /* Part 2: find a free minor, device node number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES @@ -896,8 +893,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr, /* Part 4: register the device with sysfs */ vdev->dev.class = &video_class; vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); - if (vdev->parent) - vdev->dev.parent = vdev->parent; + vdev->dev.parent = vdev->dev_parent; dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); ret = device_register(&vdev->dev); if (ret < 0) { diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index c9d9f01d21bc..68e6b5e912ff 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1813,12 +1813,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, p->flags |= V4L2_CHIP_FL_WRITABLE; if (ops->vidioc_g_register) p->flags |= V4L2_CHIP_FL_READABLE; - if (vfd->v4l2_dev) - strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); - else if (vfd->parent) - strlcpy(p->name, vfd->parent->driver->name, sizeof(p->name)); - else - strlcpy(p->name, "bridge", sizeof(p->name)); + strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); if (ops->vidioc_g_chip_info) return ops->vidioc_g_chip_info(file, fh, arg); if (p->match.addr) diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index b2c3776a1cff..c768c9f8abc2 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -96,9 +96,9 @@ struct video_device struct device dev; /* v4l device */ struct cdev *cdev; /* character device */ - /* Set either parent or v4l2_dev if your driver uses v4l2_device */ - struct device *parent; /* device parent */ struct v4l2_device *v4l2_dev; /* v4l2_device parent */ + /* Only set parent if that can't be deduced from v4l2_dev */ + struct device *dev_parent; /* device parent */ /* Control handler associated with this device node. May be NULL. */ struct v4l2_ctrl_handler *ctrl_handler; -- GitLab From e5715cfb2802cb5988f856f84454645772f4e2f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 11:23:44 -0300 Subject: [PATCH 1599/2900] [media] cx88: set dev_parent to the correct parent PCI bus The cx88 driver has one v4l2_device, but the video nodes are owned by two different PCI busses. So the dev_parent pointer should be set to the correct parent bus, otherwise sysfs won't show the correct device hierarchy. This broke starting in 3.6 after a driver change, so this patch resurrects the correct behavior. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx88/cx88-core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index c8f3dcc579d4..ad59dc9235ae 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -1034,7 +1034,14 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, if (NULL == vfd) return NULL; *vfd = *template_; + /* + * The dev pointer of v4l2_device is NULL, instead we set the + * video_device dev_parent pointer to the correct PCI bus device. + * This driver is a rare example where there is one v4l2_device, + * but the video nodes have different parent (PCI) devices. + */ vfd->v4l2_dev = &core->v4l2_dev; + vfd->dev_parent = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); -- GitLab From 7cb59509a74da98721ac169431a9a0bd372e29b0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Jun 2013 11:28:08 -0300 Subject: [PATCH 1600/2900] [media] v4l2-framework: update documentation 'parent' was renamed to 'dev_parent'. Clarify how/when this should be used. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 24353ecab197..b5e6347b720f 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -574,9 +574,13 @@ of the video device exits. The default video_device_release() callback just calls kfree to free the allocated memory. +There is also a video_device_release_empty() function that does nothing +(is empty) and can be used if the struct is embedded and there is nothing +to do when it is released. + You should also set these fields: -- v4l2_dev: set to the v4l2_device parent device. +- v4l2_dev: must be set to the v4l2_device parent device. - name: set to something descriptive and unique. @@ -613,15 +617,16 @@ You should also set these fields: If you want to have a separate priority state per (group of) device node(s), then you can point it to your own struct v4l2_prio_state. -- parent: you only set this if v4l2_device was registered with NULL as +- dev_parent: you only set this if v4l2_device was registered with NULL as the parent device struct. This only happens in cases where one hardware device has multiple PCI devices that all share the same v4l2_device core. The cx88 driver is an example of this: one core v4l2_device struct, but - it is used by both an raw video PCI device (cx8800) and a MPEG PCI device - (cx8802). Since the v4l2_device cannot be associated with a particular - PCI device it is setup without a parent device. But when the struct - video_device is setup you do know which parent PCI device to use. + it is used by both a raw video PCI device (cx8800) and a MPEG PCI device + (cx8802). Since the v4l2_device cannot be associated with two PCI devices + at the same time it is setup without a parent device. But when the struct + video_device is initialized you *do* know which parent PCI device to use and + so you set dev_device to the correct PCI device. - flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct -- GitLab From 746cb2c31f7d88bac5453e3af45d95670a00ffe8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 21 Jun 2013 11:19:10 -0300 Subject: [PATCH 1601/2900] [media] pvrusb2: Remove unused variable drivers/media/usb/pvrusb2/pvrusb2-v4l2.c: In function 'pvr2_v4l2_dev_init': drivers/media/usb/pvrusb2/pvrusb2-v4l2.c:1268:21: warning: variable 'usbdev' set but not used [-Wunused-but-set-variable] This warning is due to changeset a28fbd04facb, with removed the usage of usbdev inside pvr2_v4l2_dev_init(). Signed-off-by: Mauro Carvalho Chehab Cc: Hans Verkuil Cc: Mike Isely --- drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index d77069e12dc4..7c280f35eea9 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -1265,7 +1265,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, struct pvr2_v4l2 *vp, int v4l_type) { - struct usb_device *usbdev; int mindevnum; int unit_number; struct pvr2_hdw *hdw; @@ -1273,7 +1272,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, dip->v4lp = vp; hdw = vp->channel.mc_head->hdw; - usbdev = pvr2_hdw_get_dev(hdw); dip->v4l_type = v4l_type; switch (v4l_type) { case VFL_TYPE_GRABBER: -- GitLab From 01105690c40ceafc28df15e8b3eae6cd668229d5 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:41 -0300 Subject: [PATCH 1602/2900] [media] media: davinci: vpif: remove unwanted header mach/hardware.h and sort the includes alphabetically This patch removes unwanted header include of mach/hardware.h and along side sorts the header inclusion alphabetically. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index ea82a8bd2803..761c8259a8af 100644 --- a/drivers/media/platform/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -17,18 +17,16 @@ * GNU General Public License for more details. */ +#include #include +#include +#include #include #include -#include -#include -#include -#include #include +#include #include -#include - #include "vpif.h" MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver"); -- GitLab From c7f808d19d344a33f6687a0558553a415eca2902 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:42 -0300 Subject: [PATCH 1603/2900] [media] media: davinci: vpif: Convert to devm_* api Use devm_ioremap_resource instead of reques_mem_region()/ioremap(). This ensures more consistent error values and simplifies error paths. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index 761c8259a8af..164c1b7b4e6f 100644 --- a/drivers/media/platform/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -37,8 +37,6 @@ MODULE_LICENSE("GPL"); #define VPIF_CH2_MAX_MODES (15) #define VPIF_CH3_MAX_MODES (02) -static resource_size_t res_len; -static struct resource *res; spinlock_t vpif_lock; void __iomem *vpif_base; @@ -421,23 +419,12 @@ EXPORT_SYMBOL(vpif_channel_getfid); static int vpif_probe(struct platform_device *pdev) { - int status = 0; + static struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - vpif_base = ioremap(res->start, res_len); - if (!vpif_base) { - status = -EBUSY; - goto fail; - } + vpif_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(vpif_base)) + return PTR_ERR(vpif_base); pm_runtime_enable(&pdev->dev); pm_runtime_get(&pdev->dev); @@ -445,17 +432,11 @@ static int vpif_probe(struct platform_device *pdev) spin_lock_init(&vpif_lock); dev_info(&pdev->dev, "vpif probe success\n"); return 0; - -fail: - release_mem_region(res->start, res_len); - return status; } static int vpif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - iounmap(vpif_base); - release_mem_region(res->start, res_len); return 0; } -- GitLab From 079b3852b76a186b7c4e858420eee165c9837178 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:43 -0300 Subject: [PATCH 1604/2900] [media] media: davinci: vpif: remove unnecessary braces around defines This patch removes unnecessary braces around defines. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index 164c1b7b4e6f..cd08e5248387 100644 --- a/drivers/media/platform/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -32,10 +32,10 @@ MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver"); MODULE_LICENSE("GPL"); -#define VPIF_CH0_MAX_MODES (22) -#define VPIF_CH1_MAX_MODES (02) -#define VPIF_CH2_MAX_MODES (15) -#define VPIF_CH3_MAX_MODES (02) +#define VPIF_CH0_MAX_MODES 22 +#define VPIF_CH1_MAX_MODES 2 +#define VPIF_CH2_MAX_MODES 15 +#define VPIF_CH3_MAX_MODES 2 spinlock_t vpif_lock; -- GitLab From 410ca6053e3c216b8ca0b05f45d6cd76b334a459 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:44 -0300 Subject: [PATCH 1605/2900] [media] media: davinci: vpif_capture: move the freeing of irq and global variables to remove() Ideally the freeing of irq's and the global variables needs to be done in the remove() rather than module_exit(), this patch moves the freeing up of irq's and freeing the memory allocated to channel objects to remove() callback of struct platform_driver. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index d004531e740d..7d3c449d9d7d 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2159,17 +2159,27 @@ static __init int vpif_probe(struct platform_device *pdev) */ static int vpif_remove(struct platform_device *device) { - int i; struct channel_obj *ch; + struct resource *res; + int irq_num, i = 0; + + while ((res = platform_get_resource(device, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, + (void *)(&vpif_obj.dev[i]->channel_id)); + i++; + } v4l2_device_unregister(&vpif_obj.v4l2_dev); + kfree(vpif_obj.sd); /* un-register device */ for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ ch = vpif_obj.dev[i]; /* Unregister video device */ video_unregister_device(ch->video_dev); + kfree(vpif_obj.dev[i]); } return 0; } @@ -2281,24 +2291,7 @@ static __init int vpif_init(void) */ static void vpif_cleanup(void) { - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - platform_driver_unregister(&vpif_driver); - - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); } /* Function for module initialization and cleanup */ -- GitLab From fe424b2fc2674a13b7746b2cb3b0eb88b1fe182d Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:45 -0300 Subject: [PATCH 1606/2900] [media] media: davinci: vpif_capture: use module_platform_driver() This patch uses module_platform_driver() to simplify the code. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 7d3c449d9d7d..091c7a4c8226 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2270,30 +2270,4 @@ static __refdata struct platform_driver vpif_driver = { .remove = vpif_remove, }; -/** - * vpif_init: initialize the vpif driver - * - * This function registers device and driver to the kernel, requests irq - * handler and allocates memory - * for channel objects - */ -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/** - * vpif_cleanup : This function clean up the vpif capture resources - * - * This will un-registers device and driver to the kernel, frees - * requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - platform_driver_unregister(&vpif_driver); -} - -/* Function for module initialization and cleanup */ -module_init(vpif_init); -module_exit(vpif_cleanup); +module_platform_driver(vpif_driver); -- GitLab From b2de4f2584b717cb5a0d0d40a3d2fba1c2063f34 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:46 -0300 Subject: [PATCH 1607/2900] [media] media: davinci: vpif_capture: Convert to devm_* api use devm_request_irq() instead of request_irq(). This ensures more consistent error values and simplifies error paths. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 091c7a4c8226..a4e0eab47289 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2016,14 +2016,14 @@ static __init int vpif_probe(struct platform_device *pdev) while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Capture", (void *) - (&vpif_obj.dev[res_idx]->channel_id))) { - err = -EBUSY; - for (j = 0; j < i; j++) - free_irq(j, (void *) - (&vpif_obj.dev[res_idx]->channel_id)); - goto vpif_int_err; + err = devm_request_irq(&pdev->dev, i, vpif_channel_isr, + IRQF_SHARED, "VPIF_Capture", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; + goto vpif_unregister; + } } res_idx++; @@ -2040,7 +2040,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_int_err; + goto vpif_unregister; } /* Initialize field of video device */ @@ -2141,13 +2141,9 @@ static __init int vpif_probe(struct platform_device *pdev) /* Note: does nothing if ch->video_dev == NULL */ video_device_release(ch->video_dev); } -vpif_int_err: +vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); - for (i = 0; i < res_idx; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - for (j = res->start; j <= res->end; j++) - free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); - } + return err; } @@ -2160,15 +2156,7 @@ static __init int vpif_probe(struct platform_device *pdev) static int vpif_remove(struct platform_device *device) { struct channel_obj *ch; - struct resource *res; - int irq_num, i = 0; - - while ((res = platform_get_resource(device, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } + int i; v4l2_device_unregister(&vpif_obj.v4l2_dev); -- GitLab From a76a0b338112580593af0f68327e3cc204d4d8e7 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:47 -0300 Subject: [PATCH 1608/2900] [media] media: davinci: vpif_capture: remove unnecessary loop for IRQ resource For vpif capture driver each IRQ resource contains a single IRQ so drop the second loop. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_capture.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a4e0eab47289..5514175bbd07 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -2015,16 +2015,13 @@ static __init int vpif_probe(struct platform_device *pdev) } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { - for (i = res->start; i <= res->end; i++) { - err = devm_request_irq(&pdev->dev, i, vpif_channel_isr, - IRQF_SHARED, "VPIF_Capture", - (void *)(&vpif_obj.dev[res_idx]-> - channel_id)); - if (err) { - err = -EINVAL; - goto vpif_unregister; - - } + err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, + IRQF_SHARED, "VPIF_Capture", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; + goto vpif_unregister; } res_idx++; } -- GitLab From 0b361583a5e15bcf4b686cf02bd2cc3925e4005d Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:48 -0300 Subject: [PATCH 1609/2900] [media] media: davinci: vpif_display: move the freeing of irq and global variables to remove() Ideally the freeing of irq's and the global variables needs to be done in the remove() rather than module_exit(), this patch moves the freeing up of irq's and freeing the memory allocated to channel objects to remove() callback of struct platform_driver. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 6c521f23e40e..371af34a71be 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1829,10 +1829,20 @@ static __init int vpif_probe(struct platform_device *pdev) static int vpif_remove(struct platform_device *device) { struct channel_obj *ch; - int i; + struct resource *res; + int irq_num; + int i = 0; + + while ((res = platform_get_resource(device, IORESOURCE_IRQ, i))) { + for (irq_num = res->start; irq_num <= res->end; irq_num++) + free_irq(irq_num, + (void *)(&vpif_obj.dev[i]->channel_id)); + i++; + } v4l2_device_unregister(&vpif_obj.v4l2_dev); + kfree(vpif_obj.sd); /* un-register device */ for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ @@ -1841,6 +1851,7 @@ static int vpif_remove(struct platform_device *device) video_unregister_device(ch->video_dev); ch->video_dev = NULL; + kfree(vpif_obj.dev[i]); } return 0; @@ -1938,24 +1949,7 @@ static __init int vpif_init(void) */ static void vpif_cleanup(void) { - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - platform_driver_unregister(&vpif_driver); - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); } module_init(vpif_init); -- GitLab From b8d067b601696f303c6623c7c1c4b7cd6e2c8321 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:49 -0300 Subject: [PATCH 1610/2900] [media] media: davinci: vpif_display: use module_platform_driver() This patch uses module_platform_driver() to simplify the code. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 371af34a71be..473d1a9dd1af 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1937,20 +1937,4 @@ static __refdata struct platform_driver vpif_driver = { .remove = vpif_remove, }; -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/* - * vpif_cleanup: This function un-registers device and driver to the kernel, - * frees requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - platform_driver_unregister(&vpif_driver); -} - -module_init(vpif_init); -module_exit(vpif_cleanup); +module_platform_driver(vpif_driver); -- GitLab From 9c63e01e2b671c2810b8fbc94278a2c3c1f0491c Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:50 -0300 Subject: [PATCH 1611/2900] [media] media: davinci: vpif_display: Convert to devm_* api use devm_request_irq() instead of request_irq(). This ensures more consistent error values and simplifies error paths. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 473d1a9dd1af..1bf289d64343 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1652,15 +1652,14 @@ static __init int vpif_probe(struct platform_device *pdev) while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Display", (void *) - (&vpif_obj.dev[res_idx]->channel_id))) { - err = -EBUSY; - for (j = 0; j < i; j++) - free_irq(j, (void *) - (&vpif_obj.dev[res_idx]->channel_id)); + err = devm_request_irq(&pdev->dev, i, vpif_channel_isr, + IRQF_SHARED, "VPIF_Display", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; vpif_err("VPIF IRQ request failed\n"); - goto vpif_int_err; + goto vpif_unregister; } } res_idx++; @@ -1678,7 +1677,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_int_err; + goto vpif_unregister; } /* Initialize field of video device */ @@ -1812,13 +1811,8 @@ static __init int vpif_probe(struct platform_device *pdev) /* Note: does nothing if ch->video_dev == NULL */ video_device_release(ch->video_dev); } -vpif_int_err: +vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); - for (i = 0; i < res_idx; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - for (j = res->start; j <= res->end; j++) - free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); - } return err; } @@ -1829,16 +1823,7 @@ static __init int vpif_probe(struct platform_device *pdev) static int vpif_remove(struct platform_device *device) { struct channel_obj *ch; - struct resource *res; - int irq_num; - int i = 0; - - while ((res = platform_get_resource(device, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } + int i; v4l2_device_unregister(&vpif_obj.v4l2_dev); -- GitLab From 379d2cf4b5267ac94f8b4569545bd524e0cca29a Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 17 Jun 2013 11:20:51 -0300 Subject: [PATCH 1612/2900] [media] media: davinci: vpif_display: remove unnecessary loop for IRQ resource For vpif display driver each IRQ resource contains a single IRQ so drop the second loop. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/vpif_display.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 1bf289d64343..e6e573650250 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1651,16 +1651,14 @@ static __init int vpif_probe(struct platform_device *pdev) } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { - for (i = res->start; i <= res->end; i++) { - err = devm_request_irq(&pdev->dev, i, vpif_channel_isr, - IRQF_SHARED, "VPIF_Display", - (void *)(&vpif_obj.dev[res_idx]-> - channel_id)); - if (err) { - err = -EINVAL; - vpif_err("VPIF IRQ request failed\n"); - goto vpif_unregister; - } + err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, + IRQF_SHARED, "VPIF_Display", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; + vpif_err("VPIF IRQ request failed\n"); + goto vpif_unregister; } res_idx++; } -- GitLab From b610b5928dc04095b9b24b83e4ddbb399d933611 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 4 Jun 2013 12:26:23 -0300 Subject: [PATCH 1613/2900] [media] media: i2c: tvp514x: add OF support add OF support for the tvp514x driver. Signed-off-by: Lad, Prabhakar Acked-by: Laurent Pinchart Cc: Hans Verkuil Cc: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski Cc: Sylwester Nawrocki Cc: Sakari Ailus Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: devicetree-discuss@lists.ozlabs.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: davinci-linux-open-source@linux.davincidsp.com Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/tvp514x.txt | 44 +++++++++++++ drivers/media/i2c/tvp514x.c | 62 +++++++++++++++++-- 2 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/tvp514x.txt diff --git a/Documentation/devicetree/bindings/media/i2c/tvp514x.txt b/Documentation/devicetree/bindings/media/i2c/tvp514x.txt new file mode 100644 index 000000000000..46752cc71f2e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp514x.txt @@ -0,0 +1,44 @@ +* Texas Instruments TVP514x video decoder + +The TVP5146/TVP5146m2/TVP5147/TVP5147m1 device is high quality, single-chip +digital video decoder that digitizes and decodes all popular baseband analog +video formats into digital video component. The tvp514x decoder supports analog- +to-digital (A/D) conversion of component RGB and YPbPr signals as well as A/D +conversion and decoding of NTSC, PAL and SECAM composite and S-video into +component YCbCr. + +Required Properties : +- compatible : value should be either one among the following + (a) "ti,tvp5146" for tvp5146 decoder. + (b) "ti,tvp5146m2" for tvp5146m2 decoder. + (c) "ti,tvp5147" for tvp5147 decoder. + (d) "ti,tvp5147m1" for tvp5147m1 decoder. + +- hsync-active: HSYNC Polarity configuration for endpoint. + +- vsync-active: VSYNC Polarity configuration for endpoint. + +- pclk-sample: Clock polarity of the endpoint. + +For further reading on port node refer to Documentation/devicetree/bindings/ +media/video-interfaces.txt. + +Example: + + i2c0@1c22000 { + ... + ... + tvp514x@5c { + compatible = "ti,tvp5146"; + reg = <0x5c>; + + port { + tvp514x_1: endpoint { + hsync-active = <1>; + vsync-active = <1>; + pclk-sample = <0>; + }; + }; + }; + ... + }; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index b8061b5e3eac..864eb14ae9b1 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1056,6 +1057,42 @@ static struct tvp514x_decoder tvp514x_dev = { }; +static struct tvp514x_platform_data * +tvp514x_get_pdata(struct i2c_client *client) +{ + struct tvp514x_platform_data *pdata; + struct v4l2_of_endpoint bus_cfg; + struct device_node *endpoint; + unsigned int flags; + + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) + return client->dev.platform_data; + + endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + if (!endpoint) + return NULL; + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto done; + + v4l2_of_parse_endpoint(endpoint, &bus_cfg); + flags = bus_cfg.bus.parallel.flags; + + if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + pdata->hs_polarity = 1; + + if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + pdata->vs_polarity = 1; + + if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + pdata->clk_polarity = 1; + +done: + of_node_put(endpoint); + return pdata; +} + /** * tvp514x_probe() - decoder driver i2c probe handler * @client: i2c driver client device structure @@ -1067,19 +1104,20 @@ static struct tvp514x_decoder tvp514x_dev = { static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); struct tvp514x_decoder *decoder; struct v4l2_subdev *sd; int ret; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - if (!client->dev.platform_data) { - v4l2_err(client, "No platform data!!\n"); - return -ENODEV; - } - decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; @@ -1091,7 +1129,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) sizeof(tvp514x_reg_list_default)); /* Copy board specific information here */ - decoder->pdata = client->dev.platform_data; + decoder->pdata = pdata; /** * Fetch platform specific data, and configure the @@ -1231,8 +1269,20 @@ static const struct i2c_device_id tvp514x_id[] = { MODULE_DEVICE_TABLE(i2c, tvp514x_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp514x_of_match[] = { + { .compatible = "ti,tvp5146", }, + { .compatible = "ti,tvp5146m2", }, + { .compatible = "ti,tvp5147", }, + { .compatible = "ti,tvp5147m1", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp514x_of_match); +#endif + static struct i2c_driver tvp514x_driver = { .driver = { + .of_match_table = of_match_ptr(tvp514x_of_match), .owner = THIS_MODULE, .name = TVP514X_MODULE_NAME, }, -- GitLab From 090c65b694c362adb19ec9c27de216a808ee443c Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 10 Jun 2013 17:32:29 -0300 Subject: [PATCH 1614/2900] [media] usbvision-video: fix memory leak of alt_max_pkt_size 1. usbvision->alt_max_pkt_size is not deallocated anywhere. 2. if allocation of usbvision->alt_max_pkt_size fails, there is no proper deallocation of already acquired resources. The patch adds kfree(usbvision->alt_max_pkt_size) to usbvision_release() as soon as other deallocations happen there. It calls usbvision_release() if allocation of usbvision->alt_max_pkt_size fails as soon as usbvision_release() is safe to work with incompletely initialized usbvision structure. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index f0a0b7f2da92..5c9e3123ad2e 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1460,6 +1460,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); + kfree(usbvision->alt_max_pkt_size); usb_free_urb(usbvision->ctrl_urb); @@ -1575,6 +1576,7 @@ static int usbvision_probe(struct usb_interface *intf, usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { dev_err(&intf->dev, "usbvision: out of memory!\n"); + usbvision_release(usbvision); return -ENOMEM; } -- GitLab From 9291682ea490756157cd26dcc94fd46bd725df6b Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 14 Jun 2013 17:01:38 -0300 Subject: [PATCH 1615/2900] [media] radio-sf16fmi: Add module name to bus_info Fix v4l2-compliance in VIDIOC_QUERYCAP by changing "ISA" to "ISA:radio-sf16fmi". Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 9e712c8310f2..ed7299d42a24 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -123,7 +123,7 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); strlcpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card)); - strlcpy(v->bus_info, "ISA", sizeof(v->bus_info)); + strlcpy(v->bus_info, "ISA:radio-sf16fmi", sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; -- GitLab From d9ec089ef248064ec9b3d027ed707ac6e0a3f2aa Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 14 Jun 2013 17:01:39 -0300 Subject: [PATCH 1616/2900] [media] radio-sf16fmi: Set frequency during init Set freqency during initialization to fix v4l2-compliance error. This also fixes VIDIOC_G_FREQUENCY always returning zero (broken by me during LM7000 conversion). Signed-off-by: Ondrej Zary Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-sf16fmi.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index ed7299d42a24..6f4318ff0db3 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -50,7 +50,7 @@ struct fmi struct video_device vdev; int io; bool mute; - unsigned long curfreq; /* freq in kHz */ + u32 curfreq; /* freq in kHz */ struct mutex lock; }; @@ -118,6 +118,14 @@ static inline int fmi_getsigstr(struct fmi *fmi) return (res & 2) ? 0 : 0xFFFF; } +static void fmi_set_freq(struct fmi *fmi) +{ + fmi->curfreq = clamp(fmi->curfreq, RSF16_MINFREQ, RSF16_MAXFREQ); + /* rounding in steps of 800 to match the freq + that will be used */ + lm7000_set_freq((fmi->curfreq / 800) * 800, fmi, fmi_set_pins); +} + static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { @@ -158,14 +166,13 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct fmi *fmi = video_drvdata(file); - unsigned freq = f->frequency; if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; - clamp(freq, RSF16_MINFREQ, RSF16_MAXFREQ); - /* rounding in steps of 800 to match the freq - that will be used */ - lm7000_set_freq((freq / 800) * 800, fmi, fmi_set_pins); + + fmi->curfreq = f->frequency; + fmi_set_freq(fmi); + return 0; } @@ -342,8 +349,10 @@ static int __init fmi_init(void) mutex_init(&fmi->lock); - /* mute card - prevents noisy bootups */ - fmi_mute(fmi); + /* mute card and set default frequency */ + fmi->mute = 1; + fmi->curfreq = RSF16_MINFREQ; + fmi_set_freq(fmi); if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { v4l2_ctrl_handler_free(hdl); -- GitLab From 8fc350abc64f26f84c7f6af40e535edb754f942d Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Sat, 15 Jun 2013 12:34:10 -0300 Subject: [PATCH 1617/2900] [media] media: i2c: ths7303: remove unused member driver_data This patch removes the driver_data member from ths7303_state structure. The driver_data member was intended to differentiate between ths7303 and ths7353 chip and get the g_chip_ident, But as of now g_chip_ident is obsolete, so there is no need of driver_data. Signed-off-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ths7303.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 2e17abc77310..0a2dacbd7a63 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -38,7 +38,6 @@ struct ths7303_state { struct v4l2_bt_timings bt; int std_id; int stream_on; - int driver_data; }; enum ths7303_filter_mode { @@ -355,9 +354,6 @@ static int ths7303_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &ths7303_ops); - /* store the driver data to differntiate the chip */ - state->driver_data = (int)id->driver_data; - /* set to default 480I_576I filter mode */ if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) { v4l_err(client, "Setting to 480I_576I filter mode failed!\n"); -- GitLab From f3d27f34fdd7701e499617d2c1d94480a98f6d07 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 17 Jun 2013 10:29:06 -0300 Subject: [PATCH 1618/2900] [media] usbtv: Add driver for Fushicai USBTV007 video frame grabber Reverse-engineered driver for cheapo video digitizer, made from observations of Windows XP driver. The protocol is not yet completely understood, so far we don't provide any controls, only support a single format out of three and don't support the audio device. Signed-off-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/Kconfig | 1 + drivers/media/usb/Makefile | 1 + drivers/media/usb/usbtv/Kconfig | 10 + drivers/media/usb/usbtv/Makefile | 1 + drivers/media/usb/usbtv/usbtv.c | 696 +++++++++++++++++++++++++++++++ 5 files changed, 709 insertions(+) create mode 100644 drivers/media/usb/usbtv/Kconfig create mode 100644 drivers/media/usb/usbtv/Makefile create mode 100644 drivers/media/usb/usbtv/usbtv.c diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index 7cac453e34c7..cfe8056b91aa 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig @@ -18,6 +18,7 @@ source "drivers/media/usb/zr364xx/Kconfig" source "drivers/media/usb/stkwebcam/Kconfig" source "drivers/media/usb/s2255/Kconfig" source "drivers/media/usb/sn9c102/Kconfig" +source "drivers/media/usb/usbtv/Kconfig" endif if MEDIA_ANALOG_TV_SUPPORT diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile index 7f51d7e5f739..0935f47497a6 100644 --- a/drivers/media/usb/Makefile +++ b/drivers/media/usb/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_VIDEO_STK1160) += stk1160/ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ +obj-$(CONFIG_VIDEO_USBTV) += usbtv/ diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig new file mode 100644 index 000000000000..8864436464bf --- /dev/null +++ b/drivers/media/usb/usbtv/Kconfig @@ -0,0 +1,10 @@ +config VIDEO_USBTV + tristate "USBTV007 video capture support" + depends on VIDEO_DEV + select VIDEOBUF2_VMALLOC + + ---help--- + This is a video4linux2 driver for USBTV007 based video capture devices. + + To compile this driver as a module, choose M here: the + module will be called usbtv diff --git a/drivers/media/usb/usbtv/Makefile b/drivers/media/usb/usbtv/Makefile new file mode 100644 index 000000000000..28b872fa94e1 --- /dev/null +++ b/drivers/media/usb/usbtv/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_USBTV) += usbtv.o diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c new file mode 100644 index 000000000000..bf43f874685e --- /dev/null +++ b/drivers/media/usb/usbtv/usbtv.c @@ -0,0 +1,696 @@ +/* + * Fushicai USBTV007 Video Grabber Driver + * + * Product web site: + * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html + * + * Following LWN articles were very useful in construction of this driver: + * Video4Linux2 API series: http://lwn.net/Articles/203924/ + * videobuf2 API explanation: http://lwn.net/Articles/447435/ + * Thanks go to Jonathan Corbet for providing this quality documentation. + * He is awesome. + * + * Copyright (c) 2013 Lubomir Rintel + * All rights reserved. + * No physical hardware was harmed running Windows during the + * reverse-engineering activity + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Hardware. */ +#define USBTV_VIDEO_ENDP 0x81 +#define USBTV_BASE 0xc000 +#define USBTV_REQUEST_REG 12 + +/* Number of concurrent isochronous urbs submitted. + * Higher numbers was seen to overly saturate the USB bus. */ +#define USBTV_ISOC_TRANSFERS 16 +#define USBTV_ISOC_PACKETS 8 + +#define USBTV_WIDTH 720 +#define USBTV_HEIGHT 480 + +#define USBTV_CHUNK_SIZE 256 +#define USBTV_CHUNK 240 +#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ + / 2 / USBTV_CHUNK) + +/* Chunk header. */ +#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ + == 0x88000000) +#define USBTV_FRAME_ID(chunk) ((be32_to_cpu(chunk[0]) & 0x00ff0000) >> 16) +#define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) +#define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) + +/* A single videobuf2 frame buffer. */ +struct usbtv_buf { + struct vb2_buffer vb; + struct list_head list; +}; + +/* Per-device structure. */ +struct usbtv { + struct device *dev; + struct usb_device *udev; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct vb2_queue vb2q; + struct mutex v4l2_lock; + struct mutex vb2q_lock; + + /* List of videobuf2 buffers protected by a lock. */ + spinlock_t buflock; + struct list_head bufs; + + /* Number of currently processed frame, useful find + * out when a new one begins. */ + u32 frame_id; + + int iso_size; + unsigned int sequence; + struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; +}; + +static int usbtv_setup_capture(struct usbtv *usbtv) +{ + int ret; + int pipe = usb_rcvctrlpipe(usbtv->udev, 0); + int i; + static const u16 protoregs[][2] = { + /* These seem to enable the device. */ + { USBTV_BASE + 0x0008, 0x0001 }, + { USBTV_BASE + 0x01d0, 0x00ff }, + { USBTV_BASE + 0x01d9, 0x0002 }, + + /* These seem to influence color parameters, such as + * brightness, etc. */ + { USBTV_BASE + 0x0239, 0x0040 }, + { USBTV_BASE + 0x0240, 0x0000 }, + { USBTV_BASE + 0x0241, 0x0000 }, + { USBTV_BASE + 0x0242, 0x0002 }, + { USBTV_BASE + 0x0243, 0x0080 }, + { USBTV_BASE + 0x0244, 0x0012 }, + { USBTV_BASE + 0x0245, 0x0090 }, + { USBTV_BASE + 0x0246, 0x0000 }, + + { USBTV_BASE + 0x0278, 0x002d }, + { USBTV_BASE + 0x0279, 0x000a }, + { USBTV_BASE + 0x027a, 0x0032 }, + { 0xf890, 0x000c }, + { 0xf894, 0x0086 }, + + { USBTV_BASE + 0x00ac, 0x00c0 }, + { USBTV_BASE + 0x00ad, 0x0000 }, + { USBTV_BASE + 0x00a2, 0x0012 }, + { USBTV_BASE + 0x00a3, 0x00e0 }, + { USBTV_BASE + 0x00a4, 0x0028 }, + { USBTV_BASE + 0x00a5, 0x0082 }, + { USBTV_BASE + 0x00a7, 0x0080 }, + { USBTV_BASE + 0x0000, 0x0014 }, + { USBTV_BASE + 0x0006, 0x0003 }, + { USBTV_BASE + 0x0090, 0x0099 }, + { USBTV_BASE + 0x0091, 0x0090 }, + { USBTV_BASE + 0x0094, 0x0068 }, + { USBTV_BASE + 0x0095, 0x0070 }, + { USBTV_BASE + 0x009c, 0x0030 }, + { USBTV_BASE + 0x009d, 0x00c0 }, + { USBTV_BASE + 0x009e, 0x00e0 }, + { USBTV_BASE + 0x0019, 0x0006 }, + { USBTV_BASE + 0x008c, 0x00ba }, + { USBTV_BASE + 0x0101, 0x00ff }, + { USBTV_BASE + 0x010c, 0x00b3 }, + { USBTV_BASE + 0x01b2, 0x0080 }, + { USBTV_BASE + 0x01b4, 0x00a0 }, + { USBTV_BASE + 0x014c, 0x00ff }, + { USBTV_BASE + 0x014d, 0x00ca }, + { USBTV_BASE + 0x0113, 0x0053 }, + { USBTV_BASE + 0x0119, 0x008a }, + { USBTV_BASE + 0x013c, 0x0003 }, + { USBTV_BASE + 0x0150, 0x009c }, + { USBTV_BASE + 0x0151, 0x0071 }, + { USBTV_BASE + 0x0152, 0x00c6 }, + { USBTV_BASE + 0x0153, 0x0084 }, + { USBTV_BASE + 0x0154, 0x00bc }, + { USBTV_BASE + 0x0155, 0x00a0 }, + { USBTV_BASE + 0x0156, 0x00a0 }, + { USBTV_BASE + 0x0157, 0x009c }, + { USBTV_BASE + 0x0158, 0x001f }, + { USBTV_BASE + 0x0159, 0x0006 }, + { USBTV_BASE + 0x015d, 0x0000 }, + + { USBTV_BASE + 0x0284, 0x0088 }, + { USBTV_BASE + 0x0003, 0x0004 }, + { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x0100, 0x00d3 }, + { USBTV_BASE + 0x010e, 0x0068 }, + { USBTV_BASE + 0x010f, 0x009c }, + { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0115, 0x0015 }, + { USBTV_BASE + 0x0117, 0x0000 }, + { USBTV_BASE + 0x0118, 0x00fc }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0001 }, + { USBTV_BASE + 0x0254, 0x005f }, + { USBTV_BASE + 0x025a, 0x0012 }, + { USBTV_BASE + 0x025b, 0x0001 }, + { USBTV_BASE + 0x0263, 0x001c }, + { USBTV_BASE + 0x0266, 0x0011 }, + { USBTV_BASE + 0x0267, 0x0005 }, + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, + }; + + for (i = 0; i < ARRAY_SIZE(protoregs); i++) { + u16 index = protoregs[i][0]; + u16 value = protoregs[i][1]; + + ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, NULL, 0, 0); + if (ret < 0) + return ret; + } + + return 0; +} + +/* Called for each 256-byte image chunk. + * First word identifies the chunk, followed by 240 words of image + * data and padding. */ +static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) +{ + int frame_id, odd, chunk_no; + u32 *frame; + struct usbtv_buf *buf; + unsigned long flags; + + /* Ignore corrupted lines. */ + if (!USBTV_MAGIC_OK(chunk)) + return; + frame_id = USBTV_FRAME_ID(chunk); + odd = USBTV_ODD(chunk); + chunk_no = USBTV_CHUNK_NO(chunk); + + /* Deinterlace. TODO: Use interlaced frame format. */ + chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3; + chunk_no += !odd * 3; + + if (chunk_no >= USBTV_CHUNKS) + return; + + /* Beginning of a frame. */ + if (chunk_no == 0) + usbtv->frame_id = frame_id; + + spin_lock_irqsave(&usbtv->buflock, flags); + if (list_empty(&usbtv->bufs)) { + /* No free buffers. Userspace likely too slow. */ + spin_unlock_irqrestore(&usbtv->buflock, flags); + return; + } + + /* First available buffer. */ + buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); + frame = vb2_plane_vaddr(&buf->vb, 0); + + /* Copy the chunk. */ + memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], + USBTV_CHUNK * sizeof(chunk[1])); + + /* Last chunk in a frame, signalling an end */ + if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) { + int size = vb2_plane_size(&buf->vb, 0); + + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; + buf->vb.v4l2_buf.sequence = usbtv->sequence++; + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + vb2_set_plane_payload(&buf->vb, 0, size); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + list_del(&buf->list); + } + + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +/* Got image data. Each packet contains a number of 256-word chunks we + * compose the image from. */ +static void usbtv_iso_cb(struct urb *ip) +{ + int ret; + int i; + struct usbtv *usbtv = (struct usbtv *)ip->context; + + switch (ip->status) { + /* All fine. */ + case 0: + break; + /* Device disconnected or capture stopped? */ + case -ENODEV: + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + return; + /* Unknown error. Retry. */ + default: + dev_warn(usbtv->dev, "Bad response for ISO request.\n"); + goto resubmit; + } + + for (i = 0; i < ip->number_of_packets; i++) { + int size = ip->iso_frame_desc[i].actual_length; + unsigned char *data = ip->transfer_buffer + + ip->iso_frame_desc[i].offset; + int offset; + + for (offset = 0; USBTV_CHUNK_SIZE * offset < size; offset++) + usbtv_image_chunk(usbtv, + (u32 *)&data[USBTV_CHUNK_SIZE * offset]); + } + +resubmit: + ret = usb_submit_urb(ip, GFP_ATOMIC); + if (ret < 0) + dev_warn(usbtv->dev, "Could not resubmit ISO URB\n"); +} + +static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) +{ + struct urb *ip; + int size = usbtv->iso_size; + int i; + + ip = usb_alloc_urb(USBTV_ISOC_PACKETS, GFP_KERNEL); + if (ip == NULL) + return NULL; + + ip->dev = usbtv->udev; + ip->context = usbtv; + ip->pipe = usb_rcvisocpipe(usbtv->udev, USBTV_VIDEO_ENDP); + ip->interval = 1; + ip->transfer_flags = URB_ISO_ASAP; + ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, + GFP_KERNEL); + ip->complete = usbtv_iso_cb; + ip->number_of_packets = USBTV_ISOC_PACKETS; + ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS; + for (i = 0; i < USBTV_ISOC_PACKETS; i++) { + ip->iso_frame_desc[i].offset = size * i; + ip->iso_frame_desc[i].length = size; + } + + return ip; +} + +static void usbtv_stop(struct usbtv *usbtv) +{ + int i; + unsigned long flags; + + /* Cancel running transfers. */ + for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) { + struct urb *ip = usbtv->isoc_urbs[i]; + if (ip == NULL) + continue; + usb_kill_urb(ip); + kfree(ip->transfer_buffer); + usb_free_urb(ip); + usbtv->isoc_urbs[i] = NULL; + } + + /* Return buffers to userspace. */ + spin_lock_irqsave(&usbtv->buflock, flags); + while (!list_empty(&usbtv->bufs)) { + struct usbtv_buf *buf = list_first_entry(&usbtv->bufs, + struct usbtv_buf, list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + list_del(&buf->list); + } + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +static int usbtv_start(struct usbtv *usbtv) +{ + int i; + int ret; + + ret = usb_set_interface(usbtv->udev, 0, 0); + if (ret < 0) + return ret; + + ret = usbtv_setup_capture(usbtv); + if (ret < 0) + return ret; + + ret = usb_set_interface(usbtv->udev, 0, 1); + if (ret < 0) + return ret; + + for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) { + struct urb *ip; + + ip = usbtv_setup_iso_transfer(usbtv); + if (ip == NULL) { + ret = -ENOMEM; + goto start_fail; + } + usbtv->isoc_urbs[i] = ip; + + ret = usb_submit_urb(ip, GFP_KERNEL); + if (ret < 0) + goto start_fail; + } + + return 0; + +start_fail: + usbtv_stop(usbtv); + return ret; +} + +struct usb_device_id usbtv_id_table[] = { + { USB_DEVICE(0x1b71, 0x3002) }, + {} +}; +MODULE_DEVICE_TABLE(usb, usbtv_id_table); + +static int usbtv_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct usbtv *dev = video_drvdata(file); + + strlcpy(cap->driver, "usbtv", sizeof(cap->driver)); + strlcpy(cap->card, "usbtv", sizeof(cap->card)); + usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE; + cap->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int usbtv_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index > 0) + return -EINVAL; + + strlcpy(i->name, "Composite", sizeof(i->name)); + i->type = V4L2_INPUT_TYPE_CAMERA; + i->std = V4L2_STD_525_60; + return 0; +} + +static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + + strlcpy(f->description, "16 bpp YUY2, 4:2:2, packed", + sizeof(f->description)); + f->pixelformat = V4L2_PIX_FMT_YUYV; + return 0; +} + +static int usbtv_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + f->fmt.pix.width = USBTV_WIDTH; + f->fmt.pix.height = USBTV_HEIGHT; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.bytesperline = USBTV_WIDTH * 2; + f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; + return 0; +} + +static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + *norm = V4L2_STD_525_60; + return 0; +} + +static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int usbtv_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + return 0; +} + +static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) +{ + if (norm & V4L2_STD_525_60) + return 0; + return -EINVAL; +} + +struct v4l2_ioctl_ops usbtv_ioctl_ops = { + .vidioc_querycap = usbtv_querycap, + .vidioc_enum_input = usbtv_enum_input, + .vidioc_enum_fmt_vid_cap = usbtv_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_g_std = usbtv_g_std, + .vidioc_s_std = usbtv_s_std, + .vidioc_g_input = usbtv_g_input, + .vidioc_s_input = usbtv_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, +}; + +struct v4l2_file_operations usbtv_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, +}; + +static int usbtv_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, + unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) +{ + if (*nbuffers < 2) + *nbuffers = 2; + *nplanes = 1; + sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); + + return 0; +} + +static void usbtv_buf_queue(struct vb2_buffer *vb) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue); + struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb); + unsigned long flags; + + if (usbtv->udev == NULL) { + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + return; + } + + spin_lock_irqsave(&usbtv->buflock, flags); + list_add_tail(&buf->list, &usbtv->bufs); + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vq); + + if (usbtv->udev == NULL) + return -ENODEV; + + return usbtv_start(usbtv); +} + +static int usbtv_stop_streaming(struct vb2_queue *vq) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vq); + + if (usbtv->udev == NULL) + return -ENODEV; + + usbtv_stop(usbtv); + return 0; +} + +struct vb2_ops usbtv_vb2_ops = { + .queue_setup = usbtv_queue_setup, + .buf_queue = usbtv_buf_queue, + .start_streaming = usbtv_start_streaming, + .stop_streaming = usbtv_stop_streaming, +}; + +static void usbtv_release(struct v4l2_device *v4l2_dev) +{ + struct usbtv *usbtv = container_of(v4l2_dev, struct usbtv, v4l2_dev); + + v4l2_device_unregister(&usbtv->v4l2_dev); + vb2_queue_release(&usbtv->vb2q); + kfree(usbtv); +} + +static int usbtv_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + int size; + struct device *dev = &intf->dev; + struct usbtv *usbtv; + + /* Checks that the device is what we think it is. */ + if (intf->num_altsetting != 2) + return -ENODEV; + if (intf->altsetting[1].desc.bNumEndpoints != 4) + return -ENODEV; + + /* Packet size is split into 11 bits of base size and count of + * extra multiplies of it.*/ + size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc); + size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1); + + /* Device structure */ + usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL); + if (usbtv == NULL) + return -ENOMEM; + usbtv->dev = dev; + usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); + usbtv->iso_size = size; + spin_lock_init(&usbtv->buflock); + mutex_init(&usbtv->v4l2_lock); + mutex_init(&usbtv->vb2q_lock); + INIT_LIST_HEAD(&usbtv->bufs); + + /* videobuf2 structure */ + usbtv->vb2q.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + usbtv->vb2q.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; + usbtv->vb2q.drv_priv = usbtv; + usbtv->vb2q.buf_struct_size = sizeof(struct usbtv_buf); + usbtv->vb2q.ops = &usbtv_vb2_ops; + usbtv->vb2q.mem_ops = &vb2_vmalloc_memops; + usbtv->vb2q.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + usbtv->vb2q.lock = &usbtv->vb2q_lock; + ret = vb2_queue_init(&usbtv->vb2q); + if (ret < 0) { + dev_warn(dev, "Could not initialize videobuf2 queue\n"); + goto usbtv_fail; + } + + /* v4l2 structure */ + usbtv->v4l2_dev.release = usbtv_release; + ret = v4l2_device_register(dev, &usbtv->v4l2_dev); + if (ret < 0) { + dev_warn(dev, "Could not register v4l2 device\n"); + goto v4l2_fail; + } + + usb_set_intfdata(intf, usbtv); + + /* Video structure */ + strlcpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name)); + usbtv->vdev.v4l2_dev = &usbtv->v4l2_dev; + usbtv->vdev.release = video_device_release_empty; + usbtv->vdev.fops = &usbtv_fops; + usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; + usbtv->vdev.tvnorms = V4L2_STD_525_60; + usbtv->vdev.queue = &usbtv->vb2q; + usbtv->vdev.lock = &usbtv->v4l2_lock; + set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); + video_set_drvdata(&usbtv->vdev, usbtv); + ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1); + if (ret < 0) { + dev_warn(dev, "Could not register video device\n"); + goto vdev_fail; + } + + dev_info(dev, "Fushicai USBTV007 Video Grabber\n"); + return 0; + +vdev_fail: + v4l2_device_unregister(&usbtv->v4l2_dev); +v4l2_fail: + vb2_queue_release(&usbtv->vb2q); +usbtv_fail: + kfree(usbtv); + + return ret; +} + +static void usbtv_disconnect(struct usb_interface *intf) +{ + struct usbtv *usbtv = usb_get_intfdata(intf); + + mutex_lock(&usbtv->vb2q_lock); + mutex_lock(&usbtv->v4l2_lock); + + usbtv_stop(usbtv); + usb_set_intfdata(intf, NULL); + video_unregister_device(&usbtv->vdev); + v4l2_device_disconnect(&usbtv->v4l2_dev); + usb_put_dev(usbtv->udev); + usbtv->udev = NULL; + + mutex_unlock(&usbtv->v4l2_lock); + mutex_unlock(&usbtv->vb2q_lock); + + v4l2_device_put(&usbtv->v4l2_dev); +} + +MODULE_AUTHOR("Lubomir Rintel"); +MODULE_DESCRIPTION("Fushicai USBTV007 Video Grabber Driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +struct usb_driver usbtv_usb_driver = { + .name = "usbtv", + .id_table = usbtv_id_table, + .probe = usbtv_probe, + .disconnect = usbtv_disconnect, +}; + +module_usb_driver(usbtv_usb_driver); -- GitLab From 5e7db0389fd05ba8721df3978b76156917cb4256 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 19 Jun 2013 16:57:40 -0300 Subject: [PATCH 1619/2900] [media] go7007: fix return 0 for unsupported devices in go7007_usb_probe() probe() should not return 0 for unsupported devices, but go7007_usb_probe() does. The patch fixes it to return -ENODEV. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/go7007/go7007-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 50066e01a6ed..46ed83245035 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1124,7 +1124,7 @@ static int go7007_usb_probe(struct usb_interface *intf, case GO7007_BOARDID_LIFEVIEW_LR192: printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra " "is not supported. Sorry!\n"); - return 0; + return -ENODEV; name = "Lifeview TV Walker Ultra"; board = &board_lifeview_lr192; break; @@ -1140,7 +1140,7 @@ static int go7007_usb_probe(struct usb_interface *intf, default: printk(KERN_ERR "go7007-usb: unknown board ID %d!\n", (unsigned int)id->driver_info); - return 0; + return -ENODEV; } go = go7007_alloc(&board->main_info, &intf->dev); -- GitLab From cd9b22685e4ccd728550d51fbe108c473f89df4f Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 21 Jun 2013 09:37:50 -0600 Subject: [PATCH 1620/2900] vfio: Convert type1 iommu to use rbtree We need to keep track of all the DMA mappings of an iommu container so that it can be automatically unmapped when the user releases the file descriptor. We currently do this using a simple list, where we merge entries with contiguous iovas and virtual addresses. Using a tree for this is a bit more efficient and allows us to use common code instead of inventing our own. Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 190 ++++++++++++++++---------------- 1 file changed, 96 insertions(+), 94 deletions(-) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 6f3fbc48a6c7..0e863b3ddcab 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -31,6 +31,7 @@ #include #include #include /* pci_bus_type */ +#include #include #include #include @@ -50,13 +51,13 @@ MODULE_PARM_DESC(allow_unsafe_interrupts, struct vfio_iommu { struct iommu_domain *domain; struct mutex lock; - struct list_head dma_list; + struct rb_root dma_list; struct list_head group_list; bool cache; }; struct vfio_dma { - struct list_head next; + struct rb_node node; dma_addr_t iova; /* Device address */ unsigned long vaddr; /* Process virtual addr */ long npage; /* Number of pages */ @@ -75,6 +76,49 @@ struct vfio_group { #define NPAGE_TO_SIZE(npage) ((size_t)(npage) << PAGE_SHIFT) +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu, + dma_addr_t start, size_t size) +{ + struct rb_node *node = iommu->dma_list.rb_node; + + while (node) { + struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node); + + if (start + size <= dma->iova) + node = node->rb_left; + else if (start >= dma->iova + NPAGE_TO_SIZE(dma->npage)) + node = node->rb_right; + else + return dma; + } + + return NULL; +} + +static void vfio_insert_dma(struct vfio_iommu *iommu, struct vfio_dma *new) +{ + struct rb_node **link = &iommu->dma_list.rb_node, *parent = NULL; + struct vfio_dma *dma; + + while (*link) { + parent = *link; + dma = rb_entry(parent, struct vfio_dma, node); + + if (new->iova + NPAGE_TO_SIZE(new->npage) <= dma->iova) + link = &(*link)->rb_left; + else + link = &(*link)->rb_right; + } + + rb_link_node(&new->node, parent, link); + rb_insert_color(&new->node, &iommu->dma_list); +} + +static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *old) +{ + rb_erase(&old->node, &iommu->dma_list); +} + struct vwork { struct mm_struct *mm; long npage; @@ -289,31 +333,8 @@ static int __vfio_dma_map(struct vfio_iommu *iommu, dma_addr_t iova, return 0; } -static inline bool ranges_overlap(dma_addr_t start1, size_t size1, - dma_addr_t start2, size_t size2) -{ - if (start1 < start2) - return (start2 - start1 < size1); - else if (start2 < start1) - return (start1 - start2 < size2); - return (size1 > 0 && size2 > 0); -} - -static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu, - dma_addr_t start, size_t size) -{ - struct vfio_dma *dma; - - list_for_each_entry(dma, &iommu->dma_list, next) { - if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage), - start, size)) - return dma; - } - return NULL; -} - -static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, - size_t size, struct vfio_dma *dma) +static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, + size_t size, struct vfio_dma *dma) { struct vfio_dma *split; long npage_lo, npage_hi; @@ -322,10 +343,9 @@ static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, if (start <= dma->iova && start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) { vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); - list_del(&dma->next); - npage_lo = dma->npage; + vfio_remove_dma(iommu, dma); kfree(dma); - return npage_lo; + return 0; } /* Overlap low address of existing range */ @@ -339,7 +359,7 @@ static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, dma->iova += overlap; dma->vaddr += overlap; dma->npage -= npage_lo; - return npage_lo; + return 0; } /* Overlap high address of existing range */ @@ -351,7 +371,7 @@ static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, vfio_dma_unmap(iommu, start, npage_hi, dma->prot); dma->npage -= npage_hi; - return npage_hi; + return 0; } /* Split existing */ @@ -370,16 +390,16 @@ static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, split->iova = start + size; split->vaddr = dma->vaddr + NPAGE_TO_SIZE(npage_lo) + size; split->prot = dma->prot; - list_add(&split->next, &iommu->dma_list); - return size >> PAGE_SHIFT; + vfio_insert_dma(iommu, split); + return 0; } static int vfio_dma_do_unmap(struct vfio_iommu *iommu, struct vfio_iommu_type1_dma_unmap *unmap) { - long ret = 0, npage = unmap->size >> PAGE_SHIFT; - struct vfio_dma *dma, *tmp; uint64_t mask; + struct vfio_dma *dma; + int ret = 0; mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1; @@ -393,25 +413,19 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, mutex_lock(&iommu->lock); - list_for_each_entry_safe(dma, tmp, &iommu->dma_list, next) { - if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage), - unmap->iova, unmap->size)) { - ret = vfio_remove_dma_overlap(iommu, unmap->iova, - unmap->size, dma); - if (ret > 0) - npage -= ret; - if (ret < 0 || npage == 0) - break; - } - } + while (!ret && (dma = vfio_find_dma(iommu, + unmap->iova, unmap->size))) + ret = vfio_remove_dma_overlap(iommu, unmap->iova, + unmap->size, dma); + mutex_unlock(&iommu->lock); - return ret > 0 ? 0 : (int)ret; + return ret; } static int vfio_dma_do_map(struct vfio_iommu *iommu, struct vfio_iommu_type1_dma_map *map) { - struct vfio_dma *dma, *pdma = NULL; + struct vfio_dma *dma; dma_addr_t iova = map->iova; unsigned long locked, lock_limit, vaddr = map->vaddr; size_t size = map->size; @@ -452,6 +466,10 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, if (!npage) return -EINVAL; + dma = kzalloc(sizeof *dma, GFP_KERNEL); + if (!dma) + return -ENOMEM; + mutex_lock(&iommu->lock); if (vfio_find_dma(iommu, iova, size)) { @@ -473,62 +491,45 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, if (ret) goto out_lock; + dma->npage = npage; + dma->iova = iova; + dma->vaddr = vaddr; + dma->prot = prot; + /* Check if we abut a region below - nothing below 0 */ if (iova) { - dma = vfio_find_dma(iommu, iova - 1, 1); - if (dma && dma->prot == prot && - dma->vaddr + NPAGE_TO_SIZE(dma->npage) == vaddr) { - - dma->npage += npage; - iova = dma->iova; - vaddr = dma->vaddr; + struct vfio_dma *tmp = vfio_find_dma(iommu, iova - 1, 1); + if (tmp && tmp->prot == prot && + tmp->vaddr + NPAGE_TO_SIZE(tmp->npage) == vaddr) { + vfio_remove_dma(iommu, tmp); + dma->npage += tmp->npage; + dma->iova = iova = tmp->iova; + dma->vaddr = vaddr = tmp->vaddr; + kfree(tmp); npage = dma->npage; size = NPAGE_TO_SIZE(npage); - - pdma = dma; } } /* Check if we abut a region above - nothing above ~0 + 1 */ if (iova + size) { - dma = vfio_find_dma(iommu, iova + size, 1); - if (dma && dma->prot == prot && - dma->vaddr == vaddr + size) { - - dma->npage += npage; - dma->iova = iova; - dma->vaddr = vaddr; - - /* - * If merged above and below, remove previously - * merged entry. New entry covers it. - */ - if (pdma) { - list_del(&pdma->next); - kfree(pdma); - } - pdma = dma; + struct vfio_dma *tmp = vfio_find_dma(iommu, iova + size, 1); + if (tmp && tmp->prot == prot && + tmp->vaddr == vaddr + size) { + vfio_remove_dma(iommu, tmp); + dma->npage += tmp->npage; + kfree(tmp); + npage = dma->npage; + size = NPAGE_TO_SIZE(npage); } } - /* Isolated, new region */ - if (!pdma) { - dma = kzalloc(sizeof *dma, GFP_KERNEL); - if (!dma) { - ret = -ENOMEM; - vfio_dma_unmap(iommu, iova, npage, prot); - goto out_lock; - } - - dma->npage = npage; - dma->iova = iova; - dma->vaddr = vaddr; - dma->prot = prot; - list_add(&dma->next, &iommu->dma_list); - } + vfio_insert_dma(iommu, dma); out_lock: mutex_unlock(&iommu->lock); + if (ret) + kfree(dma); return ret; } @@ -606,7 +607,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&iommu->group_list); - INIT_LIST_HEAD(&iommu->dma_list); + iommu->dma_list = RB_ROOT; mutex_init(&iommu->lock); /* @@ -640,7 +641,7 @@ static void vfio_iommu_type1_release(void *iommu_data) { struct vfio_iommu *iommu = iommu_data; struct vfio_group *group, *group_tmp; - struct vfio_dma *dma, *dma_tmp; + struct rb_node *node; list_for_each_entry_safe(group, group_tmp, &iommu->group_list, next) { iommu_detach_group(iommu->domain, group->iommu_group); @@ -648,9 +649,10 @@ static void vfio_iommu_type1_release(void *iommu_data) kfree(group); } - list_for_each_entry_safe(dma, dma_tmp, &iommu->dma_list, next) { + while ((node = rb_first(&iommu->dma_list))) { + struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node); vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); - list_del(&dma->next); + vfio_remove_dma(iommu, dma); kfree(dma); } -- GitLab From 166fd7d94afdac040b28c473e45241820ca522a2 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 21 Jun 2013 09:38:02 -0600 Subject: [PATCH 1621/2900] vfio: hugepage support for vfio_iommu_type1 We currently send all mappings to the iommu in PAGE_SIZE chunks, which prevents the iommu from enabling support for larger page sizes. We still need to pin pages, which means we step through them in PAGE_SIZE chunks, but we can batch up contiguous physical memory chunks to allow the iommu the opportunity to use larger pages. The approach here is a bit different that the one currently used for legacy KVM device assignment. Rather than looking at the vma page size and using that as the maximum size to pass to the iommu, we instead simply look at whether the next page is physically contiguous. This means we might ask the iommu to map a 4MB region, while legacy KVM might limit itself to a maximum of 2MB. Splitting our mapping path also allows us to be smarter about locked memory because we can more easily unwind if the user attempts to exceed the limit. Therefore, rather than assuming that a mapping will result in locked memory, we test each page as it is pinned to determine whether it locks RAM vs an mmap'd MMIO region. This should result in better locking granularity and less locked page fudge factors in userspace. The unmap path uses the same algorithm as legacy KVM. We don't want to track the pfn for each mapping ourselves, but we need the pfn in order to unpin pages. We therefore ask the iommu for the iova to physical address translation, ask it to unpin a page, and see how many pages were actually unpinned. iommus supporting large pages will often return something bigger than a page here, which we know will be physically contiguous and we can unpin a batch of pfns. iommus not supporting large mappings won't see an improvement in batching here as they only unmap a page at a time. With this change, we also make a clarification to the API for mapping and unmapping DMA. We can only guarantee unmaps at the same granularity as used for the original mapping. In other words, unmapping a subregion of a previous mapping is not guaranteed and may result in a larger or smaller unmapping than requested. The size field in the unmapping structure is updated to reflect this. Previously this was unmodified on mapping, always returning the the requested unmap size. This is now updated to return the actual unmap size on success, allowing userspace to appropriately track mappings. Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 523 +++++++++++++++++++++----------- include/uapi/linux/vfio.h | 8 +- 2 files changed, 344 insertions(+), 187 deletions(-) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 0e863b3ddcab..6654a7eb42d3 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -60,7 +60,7 @@ struct vfio_dma { struct rb_node node; dma_addr_t iova; /* Device address */ unsigned long vaddr; /* Process virtual addr */ - long npage; /* Number of pages */ + size_t size; /* Map size (bytes) */ int prot; /* IOMMU_READ/WRITE */ }; @@ -74,8 +74,6 @@ struct vfio_group { * into DMA'ble space using the IOMMU */ -#define NPAGE_TO_SIZE(npage) ((size_t)(npage) << PAGE_SHIFT) - static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu, dma_addr_t start, size_t size) { @@ -86,7 +84,7 @@ static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu, if (start + size <= dma->iova) node = node->rb_left; - else if (start >= dma->iova + NPAGE_TO_SIZE(dma->npage)) + else if (start >= dma->iova + dma->size) node = node->rb_right; else return dma; @@ -104,7 +102,7 @@ static void vfio_insert_dma(struct vfio_iommu *iommu, struct vfio_dma *new) parent = *link; dma = rb_entry(parent, struct vfio_dma, node); - if (new->iova + NPAGE_TO_SIZE(new->npage) <= dma->iova) + if (new->iova + new->size <= dma->iova) link = &(*link)->rb_left; else link = &(*link)->rb_right; @@ -144,8 +142,8 @@ static void vfio_lock_acct(long npage) struct vwork *vwork; struct mm_struct *mm; - if (!current->mm) - return; /* process exited */ + if (!current->mm || !npage) + return; /* process exited or nothing to do */ if (down_write_trylock(¤t->mm->mmap_sem)) { current->mm->locked_vm += npage; @@ -217,33 +215,6 @@ static int put_pfn(unsigned long pfn, int prot) return 0; } -/* Unmap DMA region */ -static long __vfio_dma_do_unmap(struct vfio_iommu *iommu, dma_addr_t iova, - long npage, int prot) -{ - long i, unlocked = 0; - - for (i = 0; i < npage; i++, iova += PAGE_SIZE) { - unsigned long pfn; - - pfn = iommu_iova_to_phys(iommu->domain, iova) >> PAGE_SHIFT; - if (pfn) { - iommu_unmap(iommu->domain, iova, PAGE_SIZE); - unlocked += put_pfn(pfn, prot); - } - } - return unlocked; -} - -static void vfio_dma_unmap(struct vfio_iommu *iommu, dma_addr_t iova, - long npage, int prot) -{ - long unlocked; - - unlocked = __vfio_dma_do_unmap(iommu, iova, npage, prot); - vfio_lock_acct(-unlocked); -} - static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn) { struct page *page[1]; @@ -270,79 +241,142 @@ static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn) return ret; } -/* Map DMA region */ -static int __vfio_dma_map(struct vfio_iommu *iommu, dma_addr_t iova, - unsigned long vaddr, long npage, int prot) +/* + * Attempt to pin pages. We really don't want to track all the pfns and + * the iommu can only map chunks of consecutive pfns anyway, so get the + * first page and all consecutive pages with the same locking. + */ +static long vfio_pin_pages(unsigned long vaddr, long npage, + int prot, unsigned long *pfn_base) { - dma_addr_t start = iova; - long i, locked = 0; - int ret; + unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + bool lock_cap = capable(CAP_IPC_LOCK); + long ret, i; - /* Verify that pages are not already mapped */ - for (i = 0; i < npage; i++, iova += PAGE_SIZE) - if (iommu_iova_to_phys(iommu->domain, iova)) - return -EBUSY; + if (!current->mm) + return -ENODEV; - iova = start; + ret = vaddr_get_pfn(vaddr, prot, pfn_base); + if (ret) + return ret; - if (iommu->cache) - prot |= IOMMU_CACHE; + if (is_invalid_reserved_pfn(*pfn_base)) + return 1; - /* - * XXX We break mappings into pages and use get_user_pages_fast to - * pin the pages in memory. It's been suggested that mlock might - * provide a more efficient mechanism, but nothing prevents the - * user from munlocking the pages, which could then allow the user - * access to random host memory. We also have no guarantee from the - * IOMMU API that the iommu driver can unmap sub-pages of previous - * mappings. This means we might lose an entire range if a single - * page within it is unmapped. Single page mappings are inefficient, - * but provide the most flexibility for now. - */ - for (i = 0; i < npage; i++, iova += PAGE_SIZE, vaddr += PAGE_SIZE) { + if (!lock_cap && current->mm->locked_vm + 1 > limit) { + put_pfn(*pfn_base, prot); + pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, + limit << PAGE_SHIFT); + return -ENOMEM; + } + + /* Lock all the consecutive pages from pfn_base */ + for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) { unsigned long pfn = 0; ret = vaddr_get_pfn(vaddr, prot, &pfn); - if (ret) { - __vfio_dma_do_unmap(iommu, start, i, prot); - return ret; + if (ret) + break; + + if (pfn != *pfn_base + i || is_invalid_reserved_pfn(pfn)) { + put_pfn(pfn, prot); + break; } + if (!lock_cap && current->mm->locked_vm + i + 1 > limit) { + put_pfn(pfn, prot); + pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", + __func__, limit << PAGE_SHIFT); + break; + } + } + + vfio_lock_acct(i); + + return i; +} + +static long vfio_unpin_pages(unsigned long pfn, long npage, + int prot, bool do_accounting) +{ + unsigned long unlocked = 0; + long i; + + for (i = 0; i < npage; i++) + unlocked += put_pfn(pfn++, prot); + + if (do_accounting) + vfio_lock_acct(-unlocked); + + return unlocked; +} + +static int vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, + dma_addr_t iova, size_t *size) +{ + dma_addr_t start = iova, end = iova + *size; + long unlocked = 0; + + while (iova < end) { + size_t unmapped; + phys_addr_t phys; + /* - * Only add actual locked pages to accounting - * XXX We're effectively marking a page locked for every - * IOVA page even though it's possible the user could be - * backing multiple IOVAs with the same vaddr. This over- - * penalizes the user process, but we currently have no - * easy way to do this properly. + * We use the IOMMU to track the physical address. This + * saves us from having a lot more entries in our mapping + * tree. The downside is that we don't track the size + * used to do the mapping. We request unmap of a single + * page, but expect IOMMUs that support large pages to + * unmap a larger chunk. */ - if (!is_invalid_reserved_pfn(pfn)) - locked++; - - ret = iommu_map(iommu->domain, iova, - (phys_addr_t)pfn << PAGE_SHIFT, - PAGE_SIZE, prot); - if (ret) { - /* Back out mappings on error */ - put_pfn(pfn, prot); - __vfio_dma_do_unmap(iommu, start, i, prot); - return ret; + phys = iommu_iova_to_phys(iommu->domain, iova); + if (WARN_ON(!phys)) { + iova += PAGE_SIZE; + continue; } + + unmapped = iommu_unmap(iommu->domain, iova, PAGE_SIZE); + if (!unmapped) + break; + + unlocked += vfio_unpin_pages(phys >> PAGE_SHIFT, + unmapped >> PAGE_SHIFT, + dma->prot, false); + iova += unmapped; } - vfio_lock_acct(locked); + + vfio_lock_acct(-unlocked); + + *size = iova - start; + return 0; } static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, - size_t size, struct vfio_dma *dma) + size_t *size, struct vfio_dma *dma) { + size_t offset, overlap, tmp; struct vfio_dma *split; - long npage_lo, npage_hi; + int ret; + + /* + * Existing dma region is completely covered, unmap all. This is + * the likely case since userspace tends to map and unmap buffers + * in one shot rather than multiple mappings within a buffer. + */ + if (likely(start <= dma->iova && + start + *size >= dma->iova + dma->size)) { + *size = dma->size; + ret = vfio_unmap_unpin(iommu, dma, dma->iova, size); + if (ret) + return ret; + + /* + * Did we remove more than we have? Should never happen + * since a vfio_dma is contiguous in iova and vaddr. + */ + WARN_ON(*size != dma->size); - /* Existing dma region is completely covered, unmap all */ - if (start <= dma->iova && - start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) { - vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); vfio_remove_dma(iommu, dma); kfree(dma); return 0; @@ -350,47 +384,79 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, /* Overlap low address of existing range */ if (start <= dma->iova) { - size_t overlap; + overlap = start + *size - dma->iova; + ret = vfio_unmap_unpin(iommu, dma, dma->iova, &overlap); + if (ret) + return ret; - overlap = start + size - dma->iova; - npage_lo = overlap >> PAGE_SHIFT; + vfio_remove_dma(iommu, dma); - vfio_dma_unmap(iommu, dma->iova, npage_lo, dma->prot); - dma->iova += overlap; - dma->vaddr += overlap; - dma->npage -= npage_lo; + /* + * Check, we may have removed to whole vfio_dma. If not + * fixup and re-insert. + */ + if (overlap < dma->size) { + dma->iova += overlap; + dma->vaddr += overlap; + dma->size -= overlap; + vfio_insert_dma(iommu, dma); + } + *size = overlap; return 0; } /* Overlap high address of existing range */ - if (start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) { - size_t overlap; + if (start + *size >= dma->iova + dma->size) { + offset = start - dma->iova; + overlap = dma->size - offset; - overlap = dma->iova + NPAGE_TO_SIZE(dma->npage) - start; - npage_hi = overlap >> PAGE_SHIFT; + ret = vfio_unmap_unpin(iommu, dma, start, &overlap); + if (ret) + return ret; + + /* + * We may have unmapped the entire vfio_dma if the user is + * trying to unmap a sub-region of what was originally + * mapped. If anything left, we can resize in place since + * iova is unchanged. + */ + if (overlap < dma->size) + dma->size -= overlap; + else + vfio_remove_dma(iommu, dma); - vfio_dma_unmap(iommu, start, npage_hi, dma->prot); - dma->npage -= npage_hi; + *size = overlap; return 0; } /* Split existing */ - npage_lo = (start - dma->iova) >> PAGE_SHIFT; - npage_hi = dma->npage - (size >> PAGE_SHIFT) - npage_lo; + offset = start - dma->iova; - split = kzalloc(sizeof *split, GFP_KERNEL); - if (!split) - return -ENOMEM; + ret = vfio_unmap_unpin(iommu, dma, start, size); + if (ret) + return ret; - vfio_dma_unmap(iommu, start, size >> PAGE_SHIFT, dma->prot); + WARN_ON(!*size); + tmp = dma->size; - dma->npage = npage_lo; + /* + * Resize the lower vfio_dma in place, insert new for remaining + * upper segment. + */ + dma->size = offset; + + if (offset + *size < tmp) { + split = kzalloc(sizeof(*split), GFP_KERNEL); + if (!split) + return -ENOMEM; + + split->size = tmp - offset - *size; + split->iova = dma->iova + offset + *size; + split->vaddr = dma->vaddr + offset + *size; + split->prot = dma->prot; + vfio_insert_dma(iommu, split); + } - split->npage = npage_hi; - split->iova = start + size; - split->vaddr = dma->vaddr + NPAGE_TO_SIZE(npage_lo) + size; - split->prot = dma->prot; - vfio_insert_dma(iommu, split); return 0; } @@ -399,6 +465,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, { uint64_t mask; struct vfio_dma *dma; + size_t unmapped = 0, size; int ret = 0; mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1; @@ -408,30 +475,66 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, if (unmap->size & mask) return -EINVAL; - /* XXX We still break these down into PAGE_SIZE */ WARN_ON(mask & PAGE_MASK); mutex_lock(&iommu->lock); - while (!ret && (dma = vfio_find_dma(iommu, - unmap->iova, unmap->size))) - ret = vfio_remove_dma_overlap(iommu, unmap->iova, - unmap->size, dma); + while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) { + size = unmap->size; + ret = vfio_remove_dma_overlap(iommu, unmap->iova, &size, dma); + if (ret) + break; + unmapped += size; + } mutex_unlock(&iommu->lock); + + /* + * We may unmap more than requested, update the unmap struct so + * userspace can know. + */ + unmap->size = unmapped; + + return ret; +} + +/* + * Turns out AMD IOMMU has a page table bug where it won't map large pages + * to a region that previously mapped smaller pages. This should be fixed + * soon, so this is just a temporary workaround to break mappings down into + * PAGE_SIZE. Better to map smaller pages than nothing. + */ +static int map_try_harder(struct vfio_iommu *iommu, dma_addr_t iova, + unsigned long pfn, long npage, int prot) +{ + long i; + int ret; + + for (i = 0; i < npage; i++, pfn++, iova += PAGE_SIZE) { + ret = iommu_map(iommu->domain, iova, + (phys_addr_t)pfn << PAGE_SHIFT, + PAGE_SIZE, prot); + if (ret) + break; + } + + for (; i < npage && i > 0; i--, iova -= PAGE_SIZE) + iommu_unmap(iommu->domain, iova, PAGE_SIZE); + return ret; } static int vfio_dma_do_map(struct vfio_iommu *iommu, struct vfio_iommu_type1_dma_map *map) { - struct vfio_dma *dma; - dma_addr_t iova = map->iova; - unsigned long locked, lock_limit, vaddr = map->vaddr; + dma_addr_t end, iova; + unsigned long vaddr = map->vaddr; size_t size = map->size; + long npage; int ret = 0, prot = 0; uint64_t mask; - long npage; + + end = map->iova + map->size; mask = ((uint64_t)1 << __ffs(iommu->domain->ops->pgsize_bitmap)) - 1; @@ -444,92 +547,138 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, if (!prot) return -EINVAL; /* No READ/WRITE? */ + if (iommu->cache) + prot |= IOMMU_CACHE; + if (vaddr & mask) return -EINVAL; - if (iova & mask) + if (map->iova & mask) return -EINVAL; - if (size & mask) + if (!map->size || map->size & mask) return -EINVAL; - /* XXX We still break these down into PAGE_SIZE */ WARN_ON(mask & PAGE_MASK); /* Don't allow IOVA wrap */ - if (iova + size && iova + size < iova) + if (end && end < map->iova) return -EINVAL; /* Don't allow virtual address wrap */ - if (vaddr + size && vaddr + size < vaddr) - return -EINVAL; - - npage = size >> PAGE_SHIFT; - if (!npage) + if (vaddr + map->size && vaddr + map->size < vaddr) return -EINVAL; - dma = kzalloc(sizeof *dma, GFP_KERNEL); - if (!dma) - return -ENOMEM; - mutex_lock(&iommu->lock); - if (vfio_find_dma(iommu, iova, size)) { - ret = -EBUSY; - goto out_lock; + if (vfio_find_dma(iommu, map->iova, map->size)) { + mutex_unlock(&iommu->lock); + return -EEXIST; } - /* account for locked pages */ - locked = current->mm->locked_vm + npage; - lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; - if (locked > lock_limit && !capable(CAP_IPC_LOCK)) { - pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", - __func__, rlimit(RLIMIT_MEMLOCK)); - ret = -ENOMEM; - goto out_lock; - } + for (iova = map->iova; iova < end; iova += size, vaddr += size) { + struct vfio_dma *dma = NULL; + unsigned long pfn; + long i; + + /* Pin a contiguous chunk of memory */ + npage = vfio_pin_pages(vaddr, (end - iova) >> PAGE_SHIFT, + prot, &pfn); + if (npage <= 0) { + WARN_ON(!npage); + ret = (int)npage; + break; + } - ret = __vfio_dma_map(iommu, iova, vaddr, npage, prot); - if (ret) - goto out_lock; - - dma->npage = npage; - dma->iova = iova; - dma->vaddr = vaddr; - dma->prot = prot; - - /* Check if we abut a region below - nothing below 0 */ - if (iova) { - struct vfio_dma *tmp = vfio_find_dma(iommu, iova - 1, 1); - if (tmp && tmp->prot == prot && - tmp->vaddr + NPAGE_TO_SIZE(tmp->npage) == vaddr) { - vfio_remove_dma(iommu, tmp); - dma->npage += tmp->npage; - dma->iova = iova = tmp->iova; - dma->vaddr = vaddr = tmp->vaddr; - kfree(tmp); - npage = dma->npage; - size = NPAGE_TO_SIZE(npage); + /* Verify pages are not already mapped */ + for (i = 0; i < npage; i++) { + if (iommu_iova_to_phys(iommu->domain, + iova + (i << PAGE_SHIFT))) { + vfio_unpin_pages(pfn, npage, prot, true); + ret = -EBUSY; + break; + } + } + + ret = iommu_map(iommu->domain, iova, + (phys_addr_t)pfn << PAGE_SHIFT, + npage << PAGE_SHIFT, prot); + if (ret) { + if (ret != -EBUSY || + map_try_harder(iommu, iova, pfn, npage, prot)) { + vfio_unpin_pages(pfn, npage, prot, true); + break; + } + } + + size = npage << PAGE_SHIFT; + + /* + * Check if we abut a region below - nothing below 0. + * This is the most likely case when mapping chunks of + * physically contiguous regions within a virtual address + * range. Update the abutting entry in place since iova + * doesn't change. + */ + if (likely(iova)) { + struct vfio_dma *tmp; + tmp = vfio_find_dma(iommu, iova - 1, 1); + if (tmp && tmp->prot == prot && + tmp->vaddr + tmp->size == vaddr) { + tmp->size += size; + + iova = tmp->iova; + size = tmp->size; + vaddr = tmp->vaddr; + dma = tmp; + } + } + + /* Check if we abut a region above - nothing above ~0 + 1 */ + if (likely(iova + size)) { + struct vfio_dma *tmp; + + tmp = vfio_find_dma(iommu, iova + size, 1); + if (tmp && tmp->prot == prot && + tmp->vaddr == vaddr + size) { + vfio_remove_dma(iommu, tmp); + if (dma) + dma->size += tmp->size; + else + size += tmp->size; + kfree(tmp); + } } - } - /* Check if we abut a region above - nothing above ~0 + 1 */ - if (iova + size) { - struct vfio_dma *tmp = vfio_find_dma(iommu, iova + size, 1); - if (tmp && tmp->prot == prot && - tmp->vaddr == vaddr + size) { - vfio_remove_dma(iommu, tmp); - dma->npage += tmp->npage; - kfree(tmp); - npage = dma->npage; - size = NPAGE_TO_SIZE(npage); + if (!dma) { + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) { + iommu_unmap(iommu->domain, iova, size); + vfio_unpin_pages(pfn, npage, prot, true); + ret = -ENOMEM; + break; + } + + dma->size = size; + dma->iova = iova; + dma->vaddr = vaddr; + dma->prot = prot; + vfio_insert_dma(iommu, dma); } } - vfio_insert_dma(iommu, dma); + if (ret) { + struct vfio_dma *tmp; + iova = map->iova; + size = map->size; + while ((tmp = vfio_find_dma(iommu, iova, size))) { + if (vfio_remove_dma_overlap(iommu, iova, &size, tmp)) { + pr_warn("%s: Error rolling back failed map\n", + __func__); + break; + } + } + } -out_lock: mutex_unlock(&iommu->lock); - if (ret) - kfree(dma); return ret; } @@ -651,9 +800,8 @@ static void vfio_iommu_type1_release(void *iommu_data) while ((node = rb_first(&iommu->dma_list))) { struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node); - vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot); - vfio_remove_dma(iommu, dma); - kfree(dma); + size_t size = dma->size; + vfio_remove_dma_overlap(iommu, dma->iova, &size, dma); } iommu_domain_free(iommu->domain); @@ -708,6 +856,7 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, } else if (cmd == VFIO_IOMMU_UNMAP_DMA) { struct vfio_iommu_type1_dma_unmap unmap; + long ret; minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size); @@ -717,7 +866,11 @@ static long vfio_iommu_type1_ioctl(void *iommu_data, if (unmap.argsz < minsz || unmap.flags) return -EINVAL; - return vfio_dma_do_unmap(iommu, &unmap); + ret = vfio_dma_do_unmap(iommu, &unmap); + if (ret) + return ret; + + return copy_to_user((void __user *)arg, &unmap, minsz); } return -ENOTTY; diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h index 284ff2436829..513600612995 100644 --- a/include/uapi/linux/vfio.h +++ b/include/uapi/linux/vfio.h @@ -361,10 +361,14 @@ struct vfio_iommu_type1_dma_map { #define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) /** - * VFIO_IOMMU_UNMAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 14, struct vfio_dma_unmap) + * VFIO_IOMMU_UNMAP_DMA - _IOWR(VFIO_TYPE, VFIO_BASE + 14, + * struct vfio_dma_unmap) * * Unmap IO virtual addresses using the provided struct vfio_dma_unmap. - * Caller sets argsz. + * Caller sets argsz. The actual unmapped size is returned in the size + * field. No guarantee is made to the user that arbitrary unmaps of iova + * or size different from those used in the original mapping call will + * succeed. */ struct vfio_iommu_type1_dma_unmap { __u32 argsz; -- GitLab From 5c6c2b21ecc9adfc47cfaf93404937b6ecd8395d Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 21 Jun 2013 09:38:11 -0600 Subject: [PATCH 1622/2900] vfio: Provide module option to disable vfio_iommu_type1 hugepage support Add a module option to vfio_iommu_type1 to disable IOMMU hugepage support. This causes iommu_map to only be called with single page mappings, disabling the IOMMU driver's ability to use hugepages. This option can be enabled by loading vfio_iommu_type1 with disable_hugepages=1 or dynamically through sysfs. If enabled dynamically, only new mappings are restricted. Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 6654a7eb42d3..8a2be4e40f22 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -48,6 +48,12 @@ module_param_named(allow_unsafe_interrupts, MODULE_PARM_DESC(allow_unsafe_interrupts, "Enable VFIO IOMMU support for on platforms without interrupt remapping support."); +static bool disable_hugepages; +module_param_named(disable_hugepages, + disable_hugepages, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(disable_hugepages, + "Disable VFIO IOMMU support for IOMMU hugepages."); + struct vfio_iommu { struct iommu_domain *domain; struct mutex lock; @@ -270,6 +276,11 @@ static long vfio_pin_pages(unsigned long vaddr, long npage, return -ENOMEM; } + if (unlikely(disable_hugepages)) { + vfio_lock_acct(1); + return 1; + } + /* Lock all the consecutive pages from pfn_base */ for (i = 1, vaddr += PAGE_SIZE; i < npage; i++, vaddr += PAGE_SIZE) { unsigned long pfn = 0; -- GitLab From b0e59b85abd42f8a525ff032d5063457e1378808 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Fri, 21 Jun 2013 09:43:21 -0600 Subject: [PATCH 1623/2900] vfio: fix documentation Signed-off-by: Alexey Kardashevskiy Signed-off-by: Alex Williamson --- Documentation/vfio.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt index 8eda3635a17d..e71782a4f2a4 100644 --- a/Documentation/vfio.txt +++ b/Documentation/vfio.txt @@ -172,12 +172,12 @@ group and can access them as follows: struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; /* Create a new container */ - container = open("/dev/vfio/vfio, O_RDWR); + container = open("/dev/vfio/vfio", O_RDWR); if (ioctl(container, VFIO_GET_API_VERSION) != VFIO_API_VERSION) /* Unknown API version */ - if (!ioctl(container, VFIO_CHECK_EXTENSION, VFIO_X86_IOMMU)) + if (!ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) /* Doesn't support the IOMMU driver we want. */ /* Open the group */ @@ -193,7 +193,7 @@ group and can access them as follows: ioctl(group, VFIO_GROUP_SET_CONTAINER, &container); /* Enable the IOMMU model we want */ - ioctl(container, VFIO_SET_IOMMU, VFIO_X86_IOMMU) + ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU) /* Get addition IOMMU info */ ioctl(container, VFIO_IOMMU_GET_INFO, &iommu_info); -- GitLab From 23946ef1658dc7f3d8e2fbdbb2110b4cc4267654 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 12:32:32 +0200 Subject: [PATCH 1624/2900] MIPS: Move gas macro MAPPED_KERNEL_SETUP_TLB to IP27-specific code. It's IP27-specific and can only cause trouble in head.S. Signed-off-by: Ralf Baechle --- .../include/asm/mach-ip27/kernel-entry-init.h | 39 +++++++++++++++++++ arch/mips/kernel/head.S | 39 ------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/arch/mips/include/asm/mach-ip27/kernel-entry-init.h b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h index a323efb720dc..3f6bc85ea61d 100644 --- a/arch/mips/include/asm/mach-ip27/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h @@ -23,6 +23,45 @@ dsrl \res, NSRI_NODEID_SHFT .endm + /* + * inputs are the text nasid in t1, data nasid in t2. + */ + .macro MAPPED_KERNEL_SETUP_TLB +#ifdef CONFIG_MAPPED_KERNEL + /* + * This needs to read the nasid - assume 0 for now. + * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0, + * 0+DVG in tlblo_1. + */ + dli t0, 0xffffffffc0000000 + dmtc0 t0, CP0_ENTRYHI + li t0, 0x1c000 # Offset of text into node memory + dsll t1, NASID_SHFT # Shift text nasid into place + dsll t2, NASID_SHFT # Same for data nasid + or t1, t1, t0 # Physical load address of kernel text + or t2, t2, t0 # Physical load address of kernel data + dsrl t1, 12 # 4K pfn + dsrl t2, 12 # 4K pfn + dsll t1, 6 # Get pfn into place + dsll t2, 6 # Get pfn into place + li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) + or t0, t0, t1 + mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr + li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) + or t0, t0, t2 + mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr + li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M + mtc0 t0, CP0_PAGEMASK + li t0, 0 # KMAP_INX + mtc0 t0, CP0_INDEX + li t0, 1 + mtc0 t0, CP0_WIRED + tlbwi +#else + mtc0 zero, CP0_WIRED +#endif + .endm + /* * Intentionally empty macro, used in head.S. Override in * arch/mips/mach-xxx/kernel-entry-init.h when necessary. diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index c61cdaed2b1d..099912324423 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -27,45 +27,6 @@ #include - /* - * inputs are the text nasid in t1, data nasid in t2. - */ - .macro MAPPED_KERNEL_SETUP_TLB -#ifdef CONFIG_MAPPED_KERNEL - /* - * This needs to read the nasid - assume 0 for now. - * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0, - * 0+DVG in tlblo_1. - */ - dli t0, 0xffffffffc0000000 - dmtc0 t0, CP0_ENTRYHI - li t0, 0x1c000 # Offset of text into node memory - dsll t1, NASID_SHFT # Shift text nasid into place - dsll t2, NASID_SHFT # Same for data nasid - or t1, t1, t0 # Physical load address of kernel text - or t2, t2, t0 # Physical load address of kernel data - dsrl t1, 12 # 4K pfn - dsrl t2, 12 # 4K pfn - dsll t1, 6 # Get pfn into place - dsll t2, 6 # Get pfn into place - li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) - or t0, t0, t1 - mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr - li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) - or t0, t0, t2 - mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr - li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M - mtc0 t0, CP0_PAGEMASK - li t0, 0 # KMAP_INX - mtc0 t0, CP0_INDEX - li t0, 1 - mtc0 t0, CP0_WIRED - tlbwi -#else - mtc0 zero, CP0_WIRED -#endif - .endm - /* * For the moment disable interrupts, mark the kernel mode and * set ST0_KX so that the CPU does not spit fire when using -- GitLab From 28963b1e2054f8c0ea968717ecf68c5fa2da6745 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 13:40:09 +0200 Subject: [PATCH 1625/2900] MIPS: IP27: Fix build error with CONFIG_MAPPED_KERNEL Some of the TLB bit definitions in have become rather complex and are no longer usable from assembler resulting in an explosion like this: AS arch/mips/kernel/head.o arch/mips/kernel/head.S: Assembler messages: arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: Illegal operands `li $12,(((1<<((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1))|(1<<(((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1)+1))|(5<<(((((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1)+1)+1)+1)))>>6)' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: missing ')' arch/mips/kernel/head.S:147: Error: Illegal operands `li $12,(((1<<((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1))|(1<<(((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1)+1))|(1<<((((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1)+1)+1))|(5<<(((((cpu_has_rixi?(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1))))+1:(cpu_has_rixi?((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))+1:((((((cpu_has_rixi?(0):(0)+1)+1)+1)+1)))))+1)+1)+1)+1)))>>6)' make[2]: *** [arch/mips/kernel/head.o] Error 1 Since now MAPPED_KERNEL_SETUP_TLB is in platform-specific code it's safe to hardcode the TLB bits there. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ip27/kernel-entry-init.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/mach-ip27/kernel-entry-init.h b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h index 3f6bc85ea61d..b087cb83da3a 100644 --- a/arch/mips/include/asm/mach-ip27/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-ip27/kernel-entry-init.h @@ -23,6 +23,14 @@ dsrl \res, NSRI_NODEID_SHFT .endm +/* + * TLB bits + */ +#define PAGE_GLOBAL (1 << 6) +#define PAGE_VALID (1 << 7) +#define PAGE_DIRTY (1 << 8) +#define CACHE_CACHABLE_COW (5 << 9) + /* * inputs are the text nasid in t1, data nasid in t2. */ @@ -44,10 +52,10 @@ dsrl t2, 12 # 4K pfn dsll t1, 6 # Get pfn into place dsll t2, 6 # Get pfn into place - li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6) + li t0, ((PAGE_GLOBAL | PAGE_VALID | CACHE_CACHABLE_COW) >> 6) or t0, t0, t1 mtc0 t0, CP0_ENTRYLO0 # physaddr, VG, cach exlwr - li t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6) + li t0, ((PAGE_GLOBAL | PAGE_VALID | PAGE_DIRTY | CACHE_CACHABLE_COW) >> 6) or t0, t0, t2 mtc0 t0, CP0_ENTRYLO1 # physaddr, DVG, cach exlwr li t0, 0x1ffe000 # MAPPED_KERN_TLBMASK, TLBPGMASK_16M -- GitLab From 8ea2b8b605d0053fc87abde56ff42b19520322f0 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 14:04:16 +0200 Subject: [PATCH 1626/2900] MIPS: IP27: Fix build errors with CONFIG_PCI disabled. LD init/built-in.o arch/mips/built-in.o: In function `startup_bridge_irq': ip27-irq.c:(.text+0x434): undefined reference to `irq_to_slot' ip27-irq.c:(.text+0x43c): undefined reference to `irq_to_slot' ip27-irq.c:(.text+0x460): undefined reference to `irq_to_bridge' ip27-irq.c:(.text+0x464): undefined reference to `irq_to_bridge' arch/mips/built-in.o: In function `shutdown_bridge_irq': ip27-irq.c:(.text+0x564): undefined reference to `irq_to_bridge' ip27-irq.c:(.text+0x56c): undefined reference to `irq_to_bridge' ip27-irq.c:(.text+0x5a0): undefined reference to `irq_to_slot' ip27-irq.c:(.text+0x5a4): undefined reference to `irq_to_slot' Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip27/Makefile | 1 + arch/mips/sgi-ip27/ip27-irq-pci.c | 266 ++++++++++++++++++++++++++++++ arch/mips/sgi-ip27/ip27-irq.c | 214 ------------------------ 3 files changed, 267 insertions(+), 214 deletions(-) create mode 100644 arch/mips/sgi-ip27/ip27-irq-pci.c diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index 1f29e761d691..da8f6816d346 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -7,4 +7,5 @@ obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \ ip27-xtalk.o obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o +obj-$(CONFIG_PCI) += ip27-irq-pci.o obj-$(CONFIG_SMP) += ip27-smp.o diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c new file mode 100644 index 000000000000..ec22ec5600f3 --- /dev/null +++ b/arch/mips/sgi-ip27/ip27-irq-pci.c @@ -0,0 +1,266 @@ +/* + * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. + * + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999 - 2001 Kanoj Sarcar + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the appropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +extern struct bridge_controller *irq_to_bridge[]; +extern int irq_to_slot[]; + +/* + * use these macros to get the encoded nasid and widget id + * from the irq value + */ +#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] +#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] + +static inline int alloc_level(int cpu, int irq) +{ + struct hub_data *hub = hub_data(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + int level; + + level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); + if (level >= LEVELS_PER_SLICE) + panic("Cpu %d flooded with devices", cpu); + + __set_bit(level, hub->irq_alloc_mask); + si->level_to_irq[level] = irq; + + return level; +} + +static inline int find_level(cpuid_t *cpunum, int irq) +{ + int cpu, i; + + for_each_online_cpu(cpu) { + struct slice_data *si = cpu_data[cpu].data; + + for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) + if (si->level_to_irq[i] == irq) { + *cpunum = cpu; + + return i; + } + } + + panic("Could not identify cpu/level for irq %d", irq); +} + +static int intr_connect_level(int cpu, int bit) +{ + nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + + set_bit(bit, si->irq_enable_mask); + + if (!cputoslice(cpu)) { + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); + } else { + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); + } + + return 0; +} + +static int intr_disconnect_level(int cpu, int bit) +{ + nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + + clear_bit(bit, si->irq_enable_mask); + + if (!cputoslice(cpu)) { + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); + } else { + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); + } + + return 0; +} + +/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int startup_bridge_irq(struct irq_data *d) +{ + struct bridge_controller *bc; + bridgereg_t device; + bridge_t *bridge; + int pin, swlevel; + cpuid_t cpu; + + pin = SLOT_FROM_PCI_IRQ(d->irq); + bc = IRQ_TO_BRIDGE(d->irq); + bridge = bc->base; + + pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = find_level(&cpu, d->irq); + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); + bridge->b_int_enable |= (1 << pin); + bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ + + /* + * Enable sending of an interrupt clear packt to the hub on a high to + * low transition of the interrupt pin. + * + * IRIX sets additional bits in the address which are documented as + * reserved in the bridge docs. + */ + bridge->b_int_mode |= (1UL << pin); + + /* + * We assume the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge->b_int_device; + device &= ~(7 << (pin*3)); + device |= (pin << (pin*3)); + bridge->b_int_device = device; + + bridge->b_wid_tflush; + + intr_connect_level(cpu, swlevel); + + return 0; /* Never anything pending. */ +} + +/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ +static void shutdown_bridge_irq(struct irq_data *d) +{ + struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); + bridge_t *bridge = bc->base; + int pin, swlevel; + cpuid_t cpu; + + pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); + pin = SLOT_FROM_PCI_IRQ(d->irq); + + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = find_level(&cpu, d->irq); + intr_disconnect_level(cpu, swlevel); + + bridge->b_int_enable &= ~(1 << pin); + bridge->b_wid_tflush; +} + +static inline void enable_bridge_irq(struct irq_data *d) +{ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + intr_connect_level(cpu, swlevel); +} + +static inline void disable_bridge_irq(struct irq_data *d) +{ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + intr_disconnect_level(cpu, swlevel); +} + +static struct irq_chip bridge_irq_type = { + .name = "bridge", + .irq_startup = startup_bridge_irq, + .irq_shutdown = shutdown_bridge_irq, + .irq_mask = disable_bridge_irq, + .irq_unmask = enable_bridge_irq, +}; + +void register_bridge_irq(unsigned int irq) +{ + irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); +} + +int request_bridge_irq(struct bridge_controller *bc) +{ + int irq = allocate_irqno(); + int swlevel, cpu; + nasid_t nasid; + + if (irq < 0) + return irq; + + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + cpu = bc->irq_cpu; + swlevel = alloc_level(cpu, irq); + if (unlikely(swlevel < 0)) { + free_irqno(irq); + + return -EAGAIN; + } + + /* Make sure it's not already pending when we connect it. */ + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + REMOTE_HUB_CLR_INTR(nasid, swlevel); + + intr_connect_level(cpu, swlevel); + + register_bridge_irq(irq); + + return irq; +} diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 2315cfeb2687..3fbaef97a1b8 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -54,50 +53,6 @@ extern asmlinkage void ip27_irq(void); -extern struct bridge_controller *irq_to_bridge[]; -extern int irq_to_slot[]; - -/* - * use these macros to get the encoded nasid and widget id - * from the irq value - */ -#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] -#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] - -static inline int alloc_level(int cpu, int irq) -{ - struct hub_data *hub = hub_data(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - int level; - - level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); - if (level >= LEVELS_PER_SLICE) - panic("Cpu %d flooded with devices", cpu); - - __set_bit(level, hub->irq_alloc_mask); - si->level_to_irq[level] = irq; - - return level; -} - -static inline int find_level(cpuid_t *cpunum, int irq) -{ - int cpu, i; - - for_each_online_cpu(cpu) { - struct slice_data *si = cpu_data[cpu].data; - - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) - if (si->level_to_irq[i] == irq) { - *cpunum = cpu; - - return i; - } - } - - panic("Could not identify cpu/level for irq %d", irq); -} - /* * Find first bit set */ @@ -204,175 +159,6 @@ static void ip27_hub_error(void) panic("CPU %d got a hub error interrupt", smp_processor_id()); } -static int intr_connect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - set_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -static int intr_disconnect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - clear_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int startup_bridge_irq(struct irq_data *d) -{ - struct bridge_controller *bc; - bridgereg_t device; - bridge_t *bridge; - int pin, swlevel; - cpuid_t cpu; - - pin = SLOT_FROM_PCI_IRQ(d->irq); - bc = IRQ_TO_BRIDGE(d->irq); - bridge = bc->base; - - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); - bridge->b_int_enable |= (1 << pin); - bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ - - /* - * Enable sending of an interrupt clear packt to the hub on a high to - * low transition of the interrupt pin. - * - * IRIX sets additional bits in the address which are documented as - * reserved in the bridge docs. - */ - bridge->b_int_mode |= (1UL << pin); - - /* - * We assume the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge->b_int_device; - device &= ~(7 << (pin*3)); - device |= (pin << (pin*3)); - bridge->b_int_device = device; - - bridge->b_wid_tflush; - - intr_connect_level(cpu, swlevel); - - return 0; /* Never anything pending. */ -} - -/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static void shutdown_bridge_irq(struct irq_data *d) -{ - struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); - bridge_t *bridge = bc->base; - int pin, swlevel; - cpuid_t cpu; - - pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); - pin = SLOT_FROM_PCI_IRQ(d->irq); - - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, d->irq); - intr_disconnect_level(cpu, swlevel); - - bridge->b_int_enable &= ~(1 << pin); - bridge->b_wid_tflush; -} - -static inline void enable_bridge_irq(struct irq_data *d) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_connect_level(cpu, swlevel); -} - -static inline void disable_bridge_irq(struct irq_data *d) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ - intr_disconnect_level(cpu, swlevel); -} - -static struct irq_chip bridge_irq_type = { - .name = "bridge", - .irq_startup = startup_bridge_irq, - .irq_shutdown = shutdown_bridge_irq, - .irq_mask = disable_bridge_irq, - .irq_unmask = enable_bridge_irq, -}; - -void register_bridge_irq(unsigned int irq) -{ - irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); -} - -int request_bridge_irq(struct bridge_controller *bc) -{ - int irq = allocate_irqno(); - int swlevel, cpu; - nasid_t nasid; - - if (irq < 0) - return irq; - - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - cpu = bc->irq_cpu; - swlevel = alloc_level(cpu, irq); - if (unlikely(swlevel < 0)) { - free_irqno(irq); - - return -EAGAIN; - } - - /* Make sure it's not already pending when we connect it. */ - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - REMOTE_HUB_CLR_INTR(nasid, swlevel); - - intr_connect_level(cpu, swlevel); - - register_bridge_irq(irq); - - return irq; -} - asmlinkage void plat_irq_dispatch(void) { unsigned long pending = read_c0_cause() & read_c0_status(); -- GitLab From 73ec78b06ecadb2ce67aae2509e8683ad8b92d14 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 13 Jun 2013 14:05:03 +0200 Subject: [PATCH 1627/2900] MIPS: IP27: Fix build errors with CONFIG_PCI disabled. LD init/built-in.o arch/mips/built-in.o: In function `xtalk_probe_node': (.cpuinit.text+0x67c): undefined reference to `bridge_probe' arch/mips/built-in.o: In function `xtalk_probe_node': (.cpuinit.text+0x7d8): undefined reference to `bridge_probe' Signed-off-by: Ralf Baechle --- arch/mips/include/asm/xtalk/xtalk.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/mips/include/asm/xtalk/xtalk.h b/arch/mips/include/asm/xtalk/xtalk.h index 680e7efebbaf..26d2ed1fa917 100644 --- a/arch/mips/include/asm/xtalk/xtalk.h +++ b/arch/mips/include/asm/xtalk/xtalk.h @@ -47,6 +47,15 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t; #define XIO_PORT(x) ((xwidgetnum_t)(((x)&XIO_PORT_BITS) >> XIO_PORT_SHIFT)) #define XIO_PACK(p, o) ((((uint64_t)(p))< Date: Thu, 13 Jun 2013 14:34:50 +0200 Subject: [PATCH 1628/2900] MIPS: IP27: Fix build error if CONFIG_PCI=y and CONFIG_NUMA disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Then will define cpp macro as default definition for pcibus_to_node resulting in: CC arch/mips/pci/pci-ip27.o arch/mips/pci/pci-ip27.c:220:7: error: expected identifier or ‘(’ before ‘void’ arch/mips/pci/pci-ip27.c:220:12: error: expected ‘)’ before ‘(’ token make[1]: *** [arch/mips/pci/pci-ip27.o] Error 1 Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ip27.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 6eb65e44d9e4..7b2ac81e1f59 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -217,6 +217,7 @@ static void pci_fixup_ioc3(struct pci_dev *d) pci_disable_swapping(d); } +#ifdef CONFIG_NUMA int pcibus_to_node(struct pci_bus *bus) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); @@ -224,6 +225,7 @@ int pcibus_to_node(struct pci_bus *bus) return bc->nasid; } EXPORT_SYMBOL(pcibus_to_node); +#endif /* CONFIG_NUMA */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, pci_fixup_ioc3); -- GitLab From d949b4fe6d23dd92b5fa48cbf7af90ca32beed2e Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 12 Jun 2013 17:28:33 +0000 Subject: [PATCH 1629/2900] MIPS: Octeon: Don't clobber bootloader data structures. Commit abe77f90dc (MIPS: Octeon: Add kexec and kdump support) added a bootmem region for the kernel image itself. The problem is that this is rounded up to a 0x100000 boundary, which is memory that may not be owned by the kernel. Depending on the kernel's configuration based size, this 'extra' memory may contain data passed from the bootloader to the kernel itself, which if clobbered makes the kernel crash in various ways. The fix: Quit rounding the size up, so that we only use memory assigned to the kernel. Signed-off-by: David Daney Cc: Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5449/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 1bcc144da287..2a75ff249e71 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -997,7 +997,7 @@ void __init plat_mem_setup(void) cvmx_bootmem_unlock(); /* Add the memory region for the kernel. */ kernel_start = (unsigned long) _text; - kernel_size = ALIGN(_end - _text, 0x100000); + kernel_size = _end - _text; /* Adjust for physical offset. */ kernel_start &= ~0xffffffff80000000ULL; -- GitLab From 25c87eae1725ed77a8b44d782a86abdc279b4ede Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 11 Jun 2013 08:49:50 +0000 Subject: [PATCH 1630/2900] lib/Kconfig.debug: Restrict FRAME_POINTER for MIPS FAULT_INJECTION_STACKTRACE_FILTER selects FRAME_POINTER but that symbol is not available for MIPS. Fixes the following problem on a randconfig: warning: (LOCKDEP && FAULT_INJECTION_STACKTRACE_FILTER && LATENCYTOP && KMEMCHECK) selects FRAME_POINTER which has unmet direct dependencies (DEBUG_KERNEL && (CRIS || M68K || FRV || UML || AVR32 || SUPERH || BLACKFIN || MN10300 || METAG) || ARCH_WANT_FRAME_POINTERS) Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5441/ Signed-off-by: Ralf Baechle --- lib/Kconfig.debug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 566cf2bc08ea..74fdc5cf4adc 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1272,7 +1272,7 @@ config FAULT_INJECTION_STACKTRACE_FILTER depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT depends on !X86_64 select STACKTRACE - select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND + select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND help Provide stacktrace filter for fault-injection capabilities -- GitLab From 2f963bfbd84207776725db82287b73cfeeab8a92 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 19 Feb 2013 02:00:39 +0200 Subject: [PATCH 1631/2900] MIPS: Loongson: Fix random early boot hang Some Loongson boards (e.g. Lemote FuLoong mini-PC) use ISA/southbridge device (CS5536 general purpose timer) for the timer interrupt. It starts running early and is already enabled during the PCI configuration, during which there is a small window in pci_read_base() when the register access is temporarily disabled. If the timer interrupts at this point, the system will hang. Fix this by adding a fixup that keeps the register access always enabled. The hang the patch fixes usually looks like this: [ 0.844000] pci 0000:00:0e.0: [1022:2090] type 00 class 0x060100 [ 0.848000] pci 0000:00:0e.0: reg 10: [io 0xb410-0xb417] [ 0.852000] pci 0000:00:0e.0: reg 14: [io 0xb000-0xb0ff] [ 0.856000] pci 0000:00:0e.0: reg 18: [io 0xb380-0xb3bf] [ 28.140000] BUG: soft lockup - CPU#0 stuck for 23s! [swapper:1] [ 28.140000] Modules linked in: [ 28.140000] irq event stamp: 37965 [ 28.140000] hardirqs last enabled at (37964): [] restore_partial+0x6c/0x13c [ 28.140000] hardirqs last disabled at (37965): [] handle_int+0x144/0x15c [ 28.140000] softirqs last enabled at (24316): [] __do_softirq+0x1cc/0x258 [ 28.140000] softirqs last disabled at (24327): [] do_softirq+0xc8/0xd0 [ 28.140000] Cpu 0 [ 28.140000] $ 0 : 0000000000000000 00000000140044e1 980000009f090000 0000000000000001 [ 28.140000] $ 4 : 980000009f090000 0000000000000000 0000000000000100 03b7fff87fbde011 [ 28.140000] $ 8 : ffffffff812b1928 000000000001e000 043ffff87fbde011 fffffff87fbde011 [ 28.140000] $12 : 000000000000000e ffffffff807a0000 0000000000000698 0000000000000000 [ 28.140000] $16 : 0000000000000002 ffffffff81055e20 ffffffff80786810 0000000000000000 [ 28.140000] $20 : 000000000000000a ffffffff807bc244 ffffffff807e6350 ffffffff80770000 [ 28.140000] $24 : 0000000000000d80 00000000fffedbe0 [ 28.140000] $28 : 980000009f07c000 980000009f07fa10 ffffffff81050000 ffffffff802380f8 [ 28.140000] Hi : 0000000000d0fc00 [ 28.140000] Lo : 0000000000f82b40 [ 28.140000] epc : ffffffff8023810c __do_softirq+0xe4/0x258 [ 28.140000] Not tainted [ 28.140000] ra : ffffffff802380f8 __do_softirq+0xd0/0x258 [ 28.140000] Status: 140044e3 KX SX UX KERNEL EXL IE [ 28.140000] Cause : 10008400 [ 28.140000] PrId : 00006303 (ICT Loongson-2) Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/4958/ Signed-off-by: Ralf Baechle --- arch/mips/loongson/common/cs5536/cs5536_isa.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c index a6eb2e853d94..924be39e7733 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_isa.c +++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c @@ -13,6 +13,7 @@ * option) any later version. */ +#include #include #include @@ -314,3 +315,16 @@ u32 pci_isa_read_reg(int reg) return conf_data; } + +/* + * The mfgpt timer interrupt is running early, so we must keep the south bridge + * mmio always enabled. Otherwise we may race with the PCI configuration which + * may temporarily disable it. When that happens and the timer interrupt fires, + * we are not able to clear it and the system will hang. + */ +static void cs5536_isa_mmio_always_on(struct pci_dev *dev) +{ + dev->mmio_always_on = 1; +} +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, + PCI_CLASS_BRIDGE_ISA, 8, cs5536_isa_mmio_always_on); -- GitLab From 2ddbc4e2f9729ce62f9286868eab6f1523f00d67 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 13 Jun 2013 19:55:04 +0000 Subject: [PATCH 1632/2900] MIPS: sead3: Fix ability to perform a soft reset. The soft reset register address and reset value to be written are incorrect for the SEAD-3 platform. This patch fixes them such that the SEAD-3 can actually perform a soft reset instead of causing an exception. Also remove usage of 'include/asm/mips-boards/generic.h' header file. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5454/ Signed-off-by: Ralf Baechle --- arch/mips/mti-sead3/sead3-reset.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c index 20475c5e7b9c..e6fb24414a70 100644 --- a/arch/mips/mti-sead3/sead3-reset.c +++ b/arch/mips/mti-sead3/sead3-reset.c @@ -9,7 +9,9 @@ #include #include -#include + +#define SOFTRES_REG 0x1f000050 +#define GORESET 0x4d static void mips_machine_restart(char *command) { @@ -35,5 +37,4 @@ static int __init mips_reboot_setup(void) return 0; } - arch_initcall(mips_reboot_setup); -- GitLab From 36a29af4bed7169f3332c44846576243d5abe9a5 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 13 Jun 2013 19:55:05 +0000 Subject: [PATCH 1633/2900] MIPS: malta: Move defines of reset registers and values. Remove usage of 'include/asm/mips-boards/generic.h' header file. Instead, move the defines for SOFTRES_REG and GORESET local to the platform file. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5455/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-reset.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index 329420536241..791101216cc2 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -27,7 +27,9 @@ #include #include -#include + +#define SOFTRES_REG 0x1f000500 +#define GORESET 0x42 static void mips_machine_restart(char *command) { -- GitLab From b72d9a4ef322f55f159df144bc702d9643e5a221 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 13 Jun 2013 19:55:06 +0000 Subject: [PATCH 1634/2900] MIPS: malta: Remove software reset defines from generic header. Remove the software reset register and reset value definitions from the 'include/asm/mips-boards/generic.h' header file. Also clean up header and whitespace in platform file. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5456/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mips-boards/generic.h | 6 ----- arch/mips/mti-malta/malta-reset.c | 29 ++++----------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h index bd9746fbe4af..48616816bcbc 100644 --- a/arch/mips/include/asm/mips-boards/generic.h +++ b/arch/mips/include/asm/mips-boards/generic.h @@ -23,12 +23,6 @@ #define ASCII_DISPLAY_WORD_BASE 0x1f000410 #define ASCII_DISPLAY_POS_BASE 0x1f000418 -/* - * Reset register. - */ -#define SOFTRES_REG 0x1f000500 -#define GORESET 0x42 - /* * Revision register. */ diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index 791101216cc2..d627d4b2b47f 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -1,31 +1,14 @@ /* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Reset the MIPS boards. - * */ -#include +#include #include -#include #include #define SOFTRES_REG 0x1f000500 @@ -47,7 +30,6 @@ static void mips_machine_halt(void) __raw_writel(GORESET, softres_reg); } - static int __init mips_reboot_setup(void) { _machine_restart = mips_machine_restart; @@ -56,5 +38,4 @@ static int __init mips_reboot_setup(void) return 0; } - arch_initcall(mips_reboot_setup); -- GitLab From 9b1f812acb607bcdfafd8cacec89f9b736e2be0c Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 13 Jun 2013 20:10:47 +0000 Subject: [PATCH 1635/2900] MIPS/OCTEON: Override default address space layout. OCTEON II cannot execute code in the default CAC_BASE space, so we supply a value (0x8000000000000000) that does work. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5457/ Signed-off-by: Ralf Baechle --- .../include/asm/mach-cavium-octeon/spaces.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 arch/mips/include/asm/mach-cavium-octeon/spaces.h diff --git a/arch/mips/include/asm/mach-cavium-octeon/spaces.h b/arch/mips/include/asm/mach-cavium-octeon/spaces.h new file mode 100644 index 000000000000..daa91accf5ab --- /dev/null +++ b/arch/mips/include/asm/mach-cavium-octeon/spaces.h @@ -0,0 +1,24 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 Cavium, Inc. + */ +#ifndef _ASM_MACH_CAVIUM_OCTEON_SPACES_H +#define _ASM_MACH_CAVIUM_OCTEON_SPACES_H + +#include + +#ifdef CONFIG_64BIT +/* They are all the same and some OCTEON II cores cannot handle 0xa8.. */ +#define CAC_BASE _AC(0x8000000000000000, UL) +#define UNCAC_BASE _AC(0x8000000000000000, UL) +#define IO_BASE _AC(0x8000000000000000, UL) + + +#endif /* CONFIG_64BIT */ + +#include + +#endif /* _ASM_MACH_CAVIUM_OCTEON_SPACES_H */ -- GitLab From 970cb7b963885afff070b315d85a56808bdf2788 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 07:42:11 +0000 Subject: [PATCH 1636/2900] MIPS: ath79: Fix argument for the ap136_pc_init function ap136_pci_init expects a u8 pointer as an argument. Fixes the following build problem on a randconfig: arch/mips/ath79/mach-ap136.c:151:2: error: too many arguments to function 'ap136_pci_init' Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5476/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/mach-ap136.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ath79/mach-ap136.c b/arch/mips/ath79/mach-ap136.c index 479dd4b1d0d2..07eac58c3641 100644 --- a/arch/mips/ath79/mach-ap136.c +++ b/arch/mips/ath79/mach-ap136.c @@ -132,7 +132,7 @@ static void __init ap136_pci_init(u8 *eeprom) ath79_register_pci(); } #else -static inline void ap136_pci_init(void) {} +static inline void ap136_pci_init(u8 *eeprom) {} #endif /* CONFIG_PCI */ static void __init ap136_setup(void) -- GitLab From d6095cace181603a1200652c4b249ff648c205a8 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 13:00:41 +0000 Subject: [PATCH 1637/2900] MIPS: sibyte: Remove unused variable. Fixes the following build problem: arch/mips/sibyte/sb1250/bus_watcher.c: In function 'sibyte_bw_int': arch/mips/sibyte/sb1250/bus_watcher.c:179:7: error: unused variable 'bw_buf' [-Werror=unused-variable] Signed-off-by: Markos Chandras Cc: sibyte-users@bitmover.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5481/ Signed-off-by: Ralf Baechle --- arch/mips/sibyte/sb1250/bus_watcher.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c index 8871e3345bff..d0ca7b91c417 100644 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ b/arch/mips/sibyte/sb1250/bus_watcher.c @@ -175,9 +175,6 @@ static irqreturn_t sibyte_bw_int(int irq, void *data) #ifdef CONFIG_SIBYTE_BW_TRACE int i; #endif -#ifndef CONFIG_PROC_FS - char bw_buf[1024]; -#endif #ifdef CONFIG_SIBYTE_BW_TRACE csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); -- GitLab From 0156915cc0202e87cac1c8507b2b71eb899a9652 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 13:00:37 +0000 Subject: [PATCH 1638/2900] MIPS: Sibyte: Add missing sched.h header It's needed for the TASK_INTERRUPTIBLE definition. Fixes the following build problem: arch/mips/sibyte/common/sb_tbprof.c:235:4: error: 'TASK_INTERRUPTIBLE' undeclared (first use in this function) [ralf@linux-mips.org: Ideally sched.h should be included into the actual user of TASK_INTERRUPTIBLE, but that seems way too risky that close to a release.] Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: sibyte-users@bitmover.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5479/ Signed-off-by: Ralf Baechle --- arch/mips/sibyte/common/sb_tbprof.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c index 2188b39a1251..059e28c8fd97 100644 --- a/arch/mips/sibyte/common/sb_tbprof.c +++ b/arch/mips/sibyte/common/sb_tbprof.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include -- GitLab From 39b6f3aa1979ad7df42474d3c63bbc7e25bd31e4 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 13:00:36 +0000 Subject: [PATCH 1639/2900] MIPS: sibyte: Declare the cfe_write() buffer as constant The write() prototype expects a const char * as argument so declare it as such. Fixes the following build problem: arch/mips/sibyte/common/cfe_console.c:23:5: error: passing argument 2 of 'cfe_write' discards 'const' qualifier from pointer target type [-Werror] arch/mips/sibyte/common/cfe_console.c:34:4: error: passing argument 2 of 'cfe_write' makes pointer from integer without a cast [-Werror] Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: sibyte-users@bitmover.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5485/ Signed-off-by: Ralf Baechle --- arch/mips/fw/cfe/cfe_api.c | 4 ++-- arch/mips/include/asm/fw/cfe/cfe_api.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/mips/fw/cfe/cfe_api.c b/arch/mips/fw/cfe/cfe_api.c index d06dc5a6b8d3..cf84f01931c5 100644 --- a/arch/mips/fw/cfe/cfe_api.c +++ b/arch/mips/fw/cfe/cfe_api.c @@ -406,12 +406,12 @@ int cfe_setenv(char *name, char *val) return xiocb.xiocb_status; } -int cfe_write(int handle, unsigned char *buffer, int length) +int cfe_write(int handle, const char *buffer, int length) { return cfe_writeblk(handle, 0, buffer, length); } -int cfe_writeblk(int handle, s64 offset, unsigned char *buffer, int length) +int cfe_writeblk(int handle, s64 offset, const char *buffer, int length) { struct cfe_xiocb xiocb; diff --git a/arch/mips/include/asm/fw/cfe/cfe_api.h b/arch/mips/include/asm/fw/cfe/cfe_api.h index 17347551a1b2..a0ea69e91e2e 100644 --- a/arch/mips/include/asm/fw/cfe/cfe_api.h +++ b/arch/mips/include/asm/fw/cfe/cfe_api.h @@ -115,8 +115,8 @@ int cfe_read(int handle, unsigned char *buffer, int length); int cfe_readblk(int handle, int64_t offset, unsigned char *buffer, int length); int cfe_setenv(char *name, char *val); -int cfe_write(int handle, unsigned char *buffer, int length); -int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer, +int cfe_write(int handle, const char *buffer, int length); +int cfe_writeblk(int handle, int64_t offset, const char *buffer, int length); #endif /* CFE_API_H */ -- GitLab From 55e9741a323fb77a11c368de51f8a4fa757311df Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 19 Jun 2013 19:25:06 +0200 Subject: [PATCH 1640/2900] MIPS: Sibyte: Fix build for SIBYTE_BW_TRACE on BCM1x55 and BCM1x80. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC arch/mips/mm/cerr-sb1.o arch/mips/mm/cerr-sb1.c: In function ‘sb1_cache_error’: arch/mips/mm/cerr-sb1.c:186:98: error: ‘M_BCM1480_SCD_TRACE_CFG_FREEZE’ undeclared (first use in this function) arch/mips/mm/cerr-sb1.c:186:98: note: each undeclared identifier is reported only once for each function it appears in make[1]: *** [arch/mips/mm/cerr-sb1.o] Error 1 This happens because 8deab1144b553548fb2f1b51affdd36dcd652aaa [[MIPS] Updated Sibyte headers] changed the headers but not all the users. Signed-off-by: Ralf Baechle Reported-by: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/5511/ --- arch/mips/mm/cerr-sb1.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c index 576add33bf5b..ee5c1ff861ae 100644 --- a/arch/mips/mm/cerr-sb1.c +++ b/arch/mips/mm/cerr-sb1.c @@ -182,11 +182,7 @@ asmlinkage void sb1_cache_error(void) #ifdef CONFIG_SIBYTE_BW_TRACE /* Freeze the trace buffer now */ -#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); -#else csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); -#endif printk("Trace buffer frozen\n"); #endif -- GitLab From ae5b0e0973ae1326809084aa3243a97f180cc903 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 19 Jun 2013 20:18:55 +0200 Subject: [PATCH 1641/2900] MIPS: Sibyte: Fix bus watcher build for BCM1x55 and BCM1x80. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC arch/mips/sibyte/bcm1480/bus_watcher.o CHK kernel/config_data.h arch/mips/sibyte/bcm1480/bus_watcher.c: In function ‘check_bus_watcher’: arch/mips/sibyte/bcm1480/bus_watcher.c:86:82: error: ‘A_SCD_BUS_ERR_STATUS_DEBUG’ undeclared (first use in this function) arch/mips/sibyte/bcm1480/bus_watcher.c:86:82: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [arch/mips/sibyte/bcm1480/bus_watcher.o] Error 1 make[2]: *** [arch/mips/sibyte/bcm1480] Error 2 make[1]: *** [arch/mips/sibyte] Error 2 make: *** [arch/mips] Error 2 The register moved around though it's otherwise the same but because of the changed address it now also has a different name. Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/5514/ Reported-by: Markos Chandras --- arch/mips/sibyte/common/Makefile | 1 + arch/mips/sibyte/{sb1250 => common}/bus_watcher.c | 11 ++++++++++- arch/mips/sibyte/sb1250/Makefile | 1 - 3 files changed, 11 insertions(+), 2 deletions(-) rename arch/mips/sibyte/{sb1250 => common}/bus_watcher.c (94%) diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile index 36aa700cc40c..b3d6bf23a662 100644 --- a/arch/mips/sibyte/common/Makefile +++ b/arch/mips/sibyte/common/Makefile @@ -1,3 +1,4 @@ obj-y := cfe.o +obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/common/bus_watcher.c similarity index 94% rename from arch/mips/sibyte/sb1250/bus_watcher.c rename to arch/mips/sibyte/common/bus_watcher.c index d0ca7b91c417..5581844c9194 100644 --- a/arch/mips/sibyte/sb1250/bus_watcher.c +++ b/arch/mips/sibyte/common/bus_watcher.c @@ -37,6 +37,9 @@ #include #include #include +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) +#include +#endif struct bw_stats_struct { @@ -81,9 +84,15 @@ void check_bus_watcher(void) #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* Destructive read, clears register and interrupt */ status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); -#else +#elif defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250) /* Use non-destructive register */ status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG)); +#elif defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + /* Use non-destructive register */ + /* Same as 1250 except BUS_ERR_STATUS_DEBUG is in a different place. */ + status = csr_in32(IOADDR(A_BCM1480_BUS_ERR_STATUS_DEBUG)); +#else +#error bus watcher being built for unknown Sibyte SOC! #endif if (!(status & 0x7fffffff)) { printk("Using last values reaped by bus watcher driver\n"); diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile index d3d969de407b..cdc4c56c3e29 100644 --- a/arch/mips/sibyte/sb1250/Makefile +++ b/arch/mips/sibyte/sb1250/Makefile @@ -1,4 +1,3 @@ obj-y := setup.o irq.o time.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o -- GitLab From 6793f55cbc84d8520e79c67583f60058b4364daa Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 13:00:38 +0000 Subject: [PATCH 1642/2900] MIPS: sibyte: Amend dependencies for SIBYTE_BUS_WATCHER SIBYTE_BUS_WATCHER is only visible if CONFIG_SIBYTE_BCM112X or CONFIG_SIBYTE_SB1250 is selected according to the arch/mips/sibyte/Makefile. This fixes the following build problem: arch/mips/mm/cerr-sb1.c:254: undefined reference to `check_bus_watcher' Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: sibyte-users@bitmover.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5482/ Signed-off-by: Ralf Baechle --- arch/mips/sibyte/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig index 01cc1a749c73..5fbd3605d24f 100644 --- a/arch/mips/sibyte/Kconfig +++ b/arch/mips/sibyte/Kconfig @@ -147,7 +147,8 @@ config SIBYTE_CFE_CONSOLE config SIBYTE_BUS_WATCHER bool "Support for Bus Watcher statistics" - depends on SIBYTE_SB1xxx_SOC + depends on SIBYTE_SB1xxx_SOC && \ + (SIBYTE_BCM112X || SIBYTE_SB1250) help Handle and keep statistics on the bus error interrupts (COR_ECC, BAD_ECC, IO_BUS). -- GitLab From c37441c127e000869a960a866fe2207626935e4f Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 07:53:47 +0000 Subject: [PATCH 1643/2900] MIPS: powertv: Drop SYS_HAS_EARLY_PRINTK PowerTV does not provide a prom_putchar function needed for early printk so remove this symbol for this platform. Fixes the following problem when EARLY_PRINTK is enabled for powertv: arch/mips/kernel/early_printk.c:24: undefined reference to `prom_putchar' arch/mips/kernel/early_printk.c:23: undefined reference to `prom_putchar' Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5477/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 49f98bf9e89d..cd8fed8eb9ea 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -419,7 +419,6 @@ config POWERTV select CSRC_POWERTV select DMA_NONCOHERENT select HW_HAS_PCI - select SYS_HAS_EARLY_PRINTK select SYS_HAS_CPU_MIPS32_R2 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN -- GitLab From c5e1503fd0428ed3a2e5e48734f47c9f4dfe5a3d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sat, 15 Jun 2013 15:34:40 +0000 Subject: [PATCH 1644/2900] MIPS: Fix execution hazard during watchpoint register probe Writing a value to a WatchLo* register creates an execution hazard, so if its value is then read before that hazard is cleared then said value may be invalid. The mips_probe_watch_registers function must therefore clear the execution hazard between setting the match bits in a WatchLo* register & reading the register back in order to check which are set. This fixes intermittent incorrect watchpoint register probing on some MIPS cores such as interAptiv & proAptiv. Signed-off-by: Paul Burton Reviewed-by: James Hogan Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/5474/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/watch.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index 7726f6157d9e..cbdc4de85bb4 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -111,6 +111,7 @@ __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) * disable the register. */ write_c0_watchlo0(7); + back_to_back_c0_hazard(); t = read_c0_watchlo0(); write_c0_watchlo0(0); c->watch_reg_masks[0] = t & 7; @@ -121,12 +122,14 @@ __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) c->watch_reg_use_cnt = 1; t = read_c0_watchhi0(); write_c0_watchhi0(t | 0xff8); + back_to_back_c0_hazard(); t = read_c0_watchhi0(); c->watch_reg_masks[0] |= (t & 0xff8); if ((t & 0x80000000) == 0) return; write_c0_watchlo1(7); + back_to_back_c0_hazard(); t = read_c0_watchlo1(); write_c0_watchlo1(0); c->watch_reg_masks[1] = t & 7; @@ -135,12 +138,14 @@ __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) c->watch_reg_use_cnt = 2; t = read_c0_watchhi1(); write_c0_watchhi1(t | 0xff8); + back_to_back_c0_hazard(); t = read_c0_watchhi1(); c->watch_reg_masks[1] |= (t & 0xff8); if ((t & 0x80000000) == 0) return; write_c0_watchlo2(7); + back_to_back_c0_hazard(); t = read_c0_watchlo2(); write_c0_watchlo2(0); c->watch_reg_masks[2] = t & 7; @@ -149,12 +154,14 @@ __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) c->watch_reg_use_cnt = 3; t = read_c0_watchhi2(); write_c0_watchhi2(t | 0xff8); + back_to_back_c0_hazard(); t = read_c0_watchhi2(); c->watch_reg_masks[2] |= (t & 0xff8); if ((t & 0x80000000) == 0) return; write_c0_watchlo3(7); + back_to_back_c0_hazard(); t = read_c0_watchlo3(); write_c0_watchlo3(0); c->watch_reg_masks[3] = t & 7; @@ -163,6 +170,7 @@ __cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) c->watch_reg_use_cnt = 4; t = read_c0_watchhi3(); write_c0_watchhi3(t | 0xff8); + back_to_back_c0_hazard(); t = read_c0_watchhi3(); c->watch_reg_masks[3] |= (t & 0xff8); if ((t & 0x80000000) == 0) -- GitLab From 318883517ebc56e1f9068597e9875f578016e225 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:38 +0000 Subject: [PATCH 1645/2900] MIPS: BCM63XX: remove bogus Kconfig selects Remove the bogus selects on USB-related symbols for 6345 and 6338, not only we do not yet support USB on BCM63XX, but they also cause the following warnings: warning: (BCM63XX_CPU_6338 && BCM63XX_CPU_6345) selects USB_OHCI_BIG_ENDIAN_MMIO which has unmet direct dependencies (USB_SUPPORT && USB && USB_OHCI_HCD) warning: (BCM63XX_CPU_6338 && BCM63XX_CPU_6345) selects USB_OHCI_BIG_ENDIAN_DESC which has unmet direct dependencies (USB_SUPPORT && USB && USB_OHCI_HCD) make[4]: Leaving directory `/home/florian/dev/linux' Just get rid of these bogus Kconfig selects because neither 6345 nor 6338 actually have built-in USB host controllers. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: http://patchwork.linux-mips.org/patch/5497/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/Kconfig | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index 5639662fd503..165727daa602 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -8,14 +8,9 @@ config BCM63XX_CPU_6328 config BCM63XX_CPU_6338 bool "support 6338 CPU" select HW_HAS_PCI - select USB_ARCH_HAS_OHCI - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO config BCM63XX_CPU_6345 bool "support 6345 CPU" - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO config BCM63XX_CPU_6348 bool "support 6348 CPU" -- GitLab From cd6cbde6b01b6e82662cad392c0d177b4af17443 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 19 Jun 2013 10:57:33 +0200 Subject: [PATCH 1646/2900] WATCHDOG: sb_wdog: Fix 32 bit build failure Fixes the following linking problem: drivers/watchdog/sb_wdog.c:211: undefined reference to `__udivdi3' This results from reading a 64 bit register, then dividing the value by 1000000. For 32 bit kernels gcc will use the helper function __udivdi3 from libgcc which the kernel intentionally doesn't provide. In the read registerbits 23..63 are always zero and only bits 0..22 are signficant. So a simple cast to truncate the read value to 32 bits fixes the issue. Reported and initial patch by Markos Chandras . Signed-off-by: Ralf Baechle Reported-by: Markos Chandras --- drivers/watchdog/sb_wdog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 25c7a3f9652d..ea5d84a1fdad 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -208,7 +208,7 @@ static long sbwdog_ioctl(struct file *file, unsigned int cmd, * get the remaining count from the ... count register * which is 1*8 before the config register */ - ret = put_user(__raw_readq(user_dog - 8) / 1000000, p); + ret = put_user((u32)__raw_readq(user_dog - 8) / 1000000, p); break; } return ret; -- GitLab From b90b3802624e1f2a509f3e9f39775d94ec4762d7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 7 May 2013 14:10:24 +0200 Subject: [PATCH 1647/2900] MIPS: Fix rtlx build error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC arch/mips/kernel/rtlx.o /home/ralf/src/linux/upstream-sfr/arch/mips/kernel/rtlx.c: In function ‘file_write’: /home/ralf/src/linux/upstream-sfr/arch/mips/kernel/rtlx.c:439:23: error: unused variable ‘rt’ [-Werror=unused-variable] /home/ralf/src/linux/upstream-sfr/arch/mips/kernel/rtlx.c: In function ‘rtlx_module_init’: /home/ralf/src/linux/upstream-sfr/arch/mips/kernel/rtlx.c:523:3: error: implicit declaration of function ‘set_vi_handler’ [-Werror=implicit-function-declaration] cc1: all warnings being treated as errors Caused by 496ad9aa8ef448058e36ca7a787c61f2e63f0f54 [new helper: file_inode(file)]. Signed-off-by: Ralf Baechle --- arch/mips/kernel/rtlx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 6fa198db8999..d763f11e35e2 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -437,7 +437,6 @@ static ssize_t file_write(struct file *file, const char __user * buffer, size_t count, loff_t * ppos) { int minor = iminor(file_inode(file)); - struct rtlx_channel *rt = &rtlx->channel[minor]; /* any space left... */ if (!rtlx_write_poll(minor)) { -- GitLab From 73acc7df534ff458a81435178dab3ea037ed6d78 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 20 Jun 2013 14:56:17 +0200 Subject: [PATCH 1648/2900] MIPS: Fix TLBR-use hazards for R2 cores in the TLB reload handlers MIPS R2 documents state that an execution hazard barrier is needed after a TLBR before reading EntryLo. Original patch by Leonid Yegoshin . Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/5526/ --- arch/mips/mm/tlbex.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index afeef93f81a7..f0f4dc44f394 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1935,6 +1935,19 @@ static void __cpuinit build_r4000_tlb_load_handler(void) uasm_i_nop(&p); uasm_i_tlbr(&p); + + switch (current_cpu_type()) { + default: + if (cpu_has_mips_r2) { + uasm_i_ehb(&p); + + case CPU_CAVIUM_OCTEON: + case CPU_CAVIUM_OCTEON_PLUS: + case CPU_CAVIUM_OCTEON2: + break; + } + } + /* Examine entrylo 0 or 1 based on ptr. */ if (use_bbit_insns()) { uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); @@ -1989,6 +2002,19 @@ static void __cpuinit build_r4000_tlb_load_handler(void) uasm_i_nop(&p); uasm_i_tlbr(&p); + + switch (current_cpu_type()) { + default: + if (cpu_has_mips_r2) { + uasm_i_ehb(&p); + + case CPU_CAVIUM_OCTEON: + case CPU_CAVIUM_OCTEON_PLUS: + case CPU_CAVIUM_OCTEON2: + break; + } + } + /* Examine entrylo 0 or 1 based on ptr. */ if (use_bbit_insns()) { uasm_i_bbit0(&p, wr.r2, ilog2(sizeof(pte_t)), 8); -- GitLab From dfb033f09e2a98a89b7a09f7e913f0b791dd01e1 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 20 Jun 2013 12:32:30 +0000 Subject: [PATCH 1649/2900] MIPS: microMIPS: Fix POOL16C minor opcode enum As pointed out by Maciej, POOL16C minor opcodes were mostly shifted by one bit. Correct those opcodes, and also add jraddiusp to the enum. Signed-off-by: Tony Wu Cc: Maciej W. Rozycki Acked-by: Steven J. Hill Cc: david.daney@cavium.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5527/ Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/inst.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 0f4aec2ad1e6..e5a676e3d3c0 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -409,10 +409,11 @@ enum mm_32f_73_minor_op { enum mm_16c_minor_op { mm_lwm16_op = 0x04, mm_swm16_op = 0x05, - mm_jr16_op = 0x18, - mm_jrc_op = 0x1a, - mm_jalr16_op = 0x1c, - mm_jalrs16_op = 0x1e, + mm_jr16_op = 0x0c, + mm_jrc_op = 0x0d, + mm_jalr16_op = 0x0e, + mm_jalrs16_op = 0x0f, + mm_jraddiusp_op = 0x18, }; /* -- GitLab From 98505ff9f2fa1a1b33d90d39ab76a54a3b189ee2 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 9 Apr 2013 06:15:58 -0300 Subject: [PATCH 1650/2900] [media] soc-camera: remove two unused configs The last users of Kconfig symbols MX3_VIDEO and VIDEO_MX2_HOSTSUPPORT were removed in v3.2. Their Kconfig entries can be removed now. Signed-off-by: Paul Bolle Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index b139b525bb16..ffd00106b205 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -27,14 +27,10 @@ config VIDEO_MX1 ---help--- This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface -config MX3_VIDEO - bool - config VIDEO_MX3 tristate "i.MX3x Camera Sensor Interface driver" depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA select VIDEOBUF2_DMA_CONTIG - select MX3_VIDEO ---help--- This is a v4l2 driver for the i.MX3x Camera Sensor Interface @@ -66,14 +62,10 @@ config VIDEO_OMAP1 ---help--- This is a v4l2 driver for the TI OMAP1 camera interface -config VIDEO_MX2_HOSTSUPPORT - bool - config VIDEO_MX2 tristate "i.MX27 Camera Sensor Interface driver" depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27 select VIDEOBUF2_DMA_CONTIG - select VIDEO_MX2_HOSTSUPPORT ---help--- This is a v4l2 driver for the i.MX27 Camera Sensor Interface -- GitLab From cbdb1f9db40d2131c00430d2638530b711af89e2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 06:29:08 -0300 Subject: [PATCH 1651/2900] [media] soc_camera: Constify dev_pm_ops in mt9t031.c Silences the following warning: WARNING: struct dev_pm_ops should normally be const Signed-off-by: Sachin Kamat Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/mt9t031.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 8f71c9a02cf0..b3dfeb6d1037 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -570,7 +570,7 @@ static int mt9t031_runtime_resume(struct device *dev) return 0; } -static struct dev_pm_ops mt9t031_dev_pm_ops = { +static const struct dev_pm_ops mt9t031_dev_pm_ops = { .runtime_suspend = mt9t031_runtime_suspend, .runtime_resume = mt9t031_runtime_resume, }; -- GitLab From 8b0706802fede74a2ee0341499f0b4586118a7d3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 30 Apr 2013 06:29:09 -0300 Subject: [PATCH 1652/2900] [media] soc_camera: Fix checkpatch warning in ov9640.c Silences the following warning: WARNING: please, no space before tabs Signed-off-by: Sachin Kamat Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/ov9640.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 6817be329666..7d1f10f301d3 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -60,7 +60,7 @@ static const struct ov9640_reg ov9640_regs_dflt[] = { /* Configurations * NOTE: for YUV, alter the following registers: - * COM12 |= OV9640_COM12_YUV_AVG + * COM12 |= OV9640_COM12_YUV_AVG * * for RGB, alter the following registers: * COM7 |= OV9640_COM7_RGB -- GitLab From 721110b34cd9fe411182398850aeb5f6cb204935 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 13 May 2013 06:19:20 -0300 Subject: [PATCH 1653/2900] [media] soc_camera/sh_mobile_csi2: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/sh_mobile_csi2.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index 09cb4fc88f34..13a1f8f13f65 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c @@ -340,18 +340,13 @@ static int sh_csi2_probe(struct platform_device *pdev) ret = v4l2_device_register_subdev(pdata->v4l2_dev, &priv->subdev); dev_dbg(&pdev->dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret); if (ret < 0) - goto esdreg; + return ret; pm_runtime_enable(&pdev->dev); dev_dbg(&pdev->dev, "CSI2 probed.\n"); return 0; - -esdreg: - platform_set_drvdata(pdev, NULL); - - return ret; } static int sh_csi2_remove(struct platform_device *pdev) @@ -360,7 +355,6 @@ static int sh_csi2_remove(struct platform_device *pdev) v4l2_device_unregister_subdev(&priv->subdev); pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From f253f184186324dceaad10fd61e2e427177eb485 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 13 May 2013 06:19:21 -0300 Subject: [PATCH 1654/2900] [media] soc_camera_platform: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat [g.liakhovetski@gmx.de: further simplified return statement] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/soc_camera_platform.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index 1b7a88ca195b..bdf909d2ec35 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -137,7 +137,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) struct soc_camera_platform_priv *priv; struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; - int ret; if (!p) return -EINVAL; @@ -165,15 +164,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev) v4l2_set_subdevdata(&priv->subdev, p); strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); - ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); - if (ret) - goto evdrs; - - return ret; - -evdrs: - platform_set_drvdata(pdev, NULL); - return ret; + return v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); } static int soc_camera_platform_remove(struct platform_device *pdev) @@ -183,7 +174,6 @@ static int soc_camera_platform_remove(struct platform_device *pdev) p->icd->control = NULL; v4l2_device_unregister_subdev(&priv->subdev); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From be843eeb0c91eeafabeed9a7acadd1a47c978915 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 24 May 2013 08:25:06 -0300 Subject: [PATCH 1655/2900] [media] soc_camera: mt9t112: Remove empty function After the switch to devm_* functions, the 'remove' function does not do anything. Delete it. Signed-off-by: Sachin Kamat Cc: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/mt9t112.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index 0391d01e8d25..9b276dde5ac8 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -1102,11 +1102,6 @@ static int mt9t112_probe(struct i2c_client *client, return ret; } -static int mt9t112_remove(struct i2c_client *client) -{ - return 0; -} - static const struct i2c_device_id mt9t112_id[] = { { "mt9t112", 0 }, { } @@ -1118,7 +1113,6 @@ static struct i2c_driver mt9t112_i2c_driver = { .name = "mt9t112", }, .probe = mt9t112_probe, - .remove = mt9t112_remove, .id_table = mt9t112_id, }; -- GitLab From f88b50ad6851632a0ff78bfa658e3b5484510969 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 24 May 2013 08:25:07 -0300 Subject: [PATCH 1656/2900] [media] soc_camera: tw9910: Remove empty function After the switch to devm_* functions, the 'remove' function does not do anything. Delete it. Signed-off-by: Sachin Kamat Cc: Kuninori Morimoto Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/tw9910.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index b5407dfad4ce..b15e1d8194da 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -925,11 +925,6 @@ static int tw9910_probe(struct i2c_client *client, return tw9910_video_probe(client); } -static int tw9910_remove(struct i2c_client *client) -{ - return 0; -} - static const struct i2c_device_id tw9910_id[] = { { "tw9910", 0 }, { } @@ -941,7 +936,6 @@ static struct i2c_driver tw9910_i2c_driver = { .name = "tw9910", }, .probe = tw9910_probe, - .remove = tw9910_remove, .id_table = tw9910_id, }; -- GitLab From 5a442b765a74264f765eb5f1c67720019aaeb172 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 1 Jun 2013 06:56:26 -0300 Subject: [PATCH 1657/2900] [media] media: Cocci spatch "ptr_ret.spatch" Use the PTR_RET() macro to simplify error processing. Signed-off-by: Thomas Meyer Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_veu.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 59a9deefb242..aa4cca371cbf 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -359,10 +359,7 @@ static int sh_veu_context_init(struct sh_veu_dev *veu) veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu, sh_veu_queue_init); - if (IS_ERR(veu->m2m_ctx)) - return PTR_ERR(veu->m2m_ctx); - - return 0; + return PTR_RET(veu->m2m_ctx); } static int sh_veu_querycap(struct file *file, void *priv, -- GitLab From 4ef72e347112a834fbd6944565b1f63d4af19c8a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 25 Apr 2013 08:05:15 -0300 Subject: [PATCH 1658/2900] [media] V4L2: soc-camera: remove unneeded include path soc-camera isn't sufficiently broken to include any files from the drivers/media/i2c/soc_camera directory in its core or host driver files:-) Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 136b7f8ff10d..bedb0428852b 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -10,5 +10,3 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o - -ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera -- GitLab From b9d4b2da35d44117831c3382710f12a1f9965ed5 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Mon, 10 Jun 2013 16:00:54 -0300 Subject: [PATCH 1659/2900] [media] ttusb-budget: fix memory leak in ttusb_probe() If something goes wrong starting from i2c_add_adapter(), ttusb->iso_urb[] and ttusb itself are not deallocated. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index 21b9049c7b3f..f8a60c197534 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c @@ -1768,6 +1768,8 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i i2c_del_adapter(&ttusb->i2c_adap); err_unregister_adapter: dvb_unregister_adapter (&ttusb->adapter); + ttusb_free_iso_urbs(ttusb); + kfree(ttusb); return result; } -- GitLab From f7f6ce2d09c86bd80ee11bd654a1ac1e8f5dfe13 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 08:21:12 -0300 Subject: [PATCH 1660/2900] [media] soc-camera: move common code to soc_camera.c All soc-camera host drivers include a pointer to an soc-camera device in their host private struct to check, that only one client is connected. Move this common code to soc_camera.c. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/atmel-isi.c | 10 +---- .../media/platform/soc_camera/mx1_camera.c | 20 +++------- .../media/platform/soc_camera/mx2_camera.c | 13 +------ .../media/platform/soc_camera/mx3_camera.c | 9 ----- .../media/platform/soc_camera/omap1_camera.c | 14 +------ .../media/platform/soc_camera/pxa_camera.c | 18 ++------- .../soc_camera/sh_mobile_ceu_camera.c | 13 +------ .../media/platform/soc_camera/soc_camera.c | 38 ++++++++++++++++--- include/media/soc_camera.h | 1 + 9 files changed, 49 insertions(+), 87 deletions(-) diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 1abbb36d0755..c9e080a57a60 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -102,7 +102,6 @@ struct atmel_isi { struct list_head video_buffer_list; struct frame_buffer *active; - struct soc_camera_device *icd; struct soc_camera_host soc_host; }; @@ -367,7 +366,7 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer) /* Check if already in a frame */ if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) { - dev_err(isi->icd->parent, "Already in frame handling.\n"); + dev_err(isi->soc_host.icd->parent, "Already in frame handling.\n"); return; } @@ -753,9 +752,6 @@ static int isi_camera_add_device(struct soc_camera_device *icd) struct atmel_isi *isi = ici->priv; int ret; - if (isi->icd) - return -EBUSY; - ret = clk_enable(isi->pclk); if (ret) return ret; @@ -766,7 +762,6 @@ static int isi_camera_add_device(struct soc_camera_device *icd) return ret; } - isi->icd = icd; dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -777,11 +772,8 @@ static void isi_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; - BUG_ON(icd != isi->icd); - clk_disable(isi->mck); clk_disable(isi->pclk); - isi->icd = NULL; dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n", icd->devnum); diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index a3fd8d63546c..5f9ec8efd978 100644 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c @@ -104,7 +104,6 @@ struct mx1_buffer { */ struct mx1_camera_dev { struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct mx1_camera_pdata *pdata; struct mx1_buffer *active; struct resource *res; @@ -220,7 +219,7 @@ static int mx1_videobuf_prepare(struct videobuf_queue *vq, static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) { struct videobuf_buffer *vbuf = &pcdev->active->vb; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; int ret; if (unlikely(!pcdev->active)) { @@ -331,7 +330,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, static void mx1_camera_dma_irq(int channel, void *data) { struct mx1_camera_dev *pcdev = data; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; struct mx1_buffer *buf; struct videobuf_buffer *vb; unsigned long flags; @@ -389,7 +388,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->icd->parent, + dev_dbg(pcdev->soc_host.icd->parent, "System clock %lukHz, target freq %dkHz, divisor %lu\n", lcdclk / 1000, mclk / 1000, div); @@ -400,7 +399,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->icd->parent, "Activate device\n"); + dev_dbg(pcdev->soc_host.icd->parent, "Activate device\n"); clk_prepare_enable(pcdev->clk); @@ -416,7 +415,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->icd->parent, "Deactivate device\n"); + dev_dbg(pcdev->soc_host.icd->parent, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -433,16 +432,11 @@ static int mx1_camera_add_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; - if (pcdev->icd) - return -EBUSY; - dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", icd->devnum); mx1_camera_activate(pcdev); - pcdev->icd = icd; - return 0; } @@ -452,8 +446,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) struct mx1_camera_dev *pcdev = ici->priv; unsigned int csicr1; - BUG_ON(icd != pcdev->icd); - /* disable interrupts */ csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK; __raw_writel(csicr1, pcdev->base + CSICR1); @@ -465,8 +457,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) icd->devnum); mx1_camera_deactivate(pcdev); - - pcdev->icd = NULL; } static int mx1_camera_set_bus_param(struct soc_camera_device *icd) diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 5bbeb43e4531..772e0710f59b 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -236,7 +236,6 @@ enum mx2_camera_type { struct mx2_camera_dev { struct device *dev; struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct clk *clk_emma_ahb, *clk_emma_ipg; struct clk *clk_csi_ahb, *clk_csi_per; @@ -394,8 +393,8 @@ static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, writel(phys, pcdev->base_emma + PRP_DEST_Y_PTR - 0x14 * bufnum); if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { - u32 imgsize = pcdev->icd->user_height * - pcdev->icd->user_width; + u32 imgsize = pcdev->soc_host.icd->user_height * + pcdev->soc_host.icd->user_width; writel(phys + imgsize, pcdev->base_emma + PRP_DEST_CB_PTR - 0x14 * bufnum); @@ -424,9 +423,6 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) int ret; u32 csicr1; - if (pcdev->icd) - return -EBUSY; - ret = clk_prepare_enable(pcdev->clk_csi_ahb); if (ret < 0) return ret; @@ -441,7 +437,6 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) pcdev->csicr1 = csicr1; writel(pcdev->csicr1, pcdev->base_csi + CSICR1); - pcdev->icd = icd; pcdev->frame_count = 0; dev_info(icd->parent, "Camera driver attached to camera %d\n", @@ -460,14 +455,10 @@ static void mx2_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; - BUG_ON(icd != pcdev->icd); - dev_info(icd->parent, "Camera driver detached from camera %d\n", icd->devnum); mx2_camera_deactivate(pcdev); - - pcdev->icd = NULL; } /* diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 5da337736cd8..71b9b191957c 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -94,7 +94,6 @@ struct mx3_camera_dev { * Interface. If anyone ever builds hardware to enable more than one * camera _simultaneously_, they will have to modify this driver too */ - struct soc_camera_device *icd; struct clk *clk; void __iomem *base; @@ -517,13 +516,9 @@ static int mx3_camera_add_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; - if (mx3_cam->icd) - return -EBUSY; - mx3_camera_activate(mx3_cam, icd); mx3_cam->buf_total = 0; - mx3_cam->icd = icd; dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", icd->devnum); @@ -538,8 +533,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) struct mx3_camera_dev *mx3_cam = ici->priv; struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - BUG_ON(icd != mx3_cam->icd); - if (*ichan) { dma_release_channel(&(*ichan)->dma_chan); *ichan = NULL; @@ -547,8 +540,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) clk_disable_unprepare(mx3_cam->clk); - mx3_cam->icd = NULL; - dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", icd->devnum); } diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 9689a6e89b7f..c42c23e4eb72 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -150,7 +150,6 @@ struct omap1_cam_buf { struct omap1_cam_dev { struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct clk *clk; unsigned int irq; @@ -564,7 +563,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev, { struct omap1_cam_buf *buf = pcdev->active; struct videobuf_buffer *vb; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; if (WARN_ON(!buf)) { suspend_capture(pcdev); @@ -790,7 +789,7 @@ static void dma_isr(int channel, unsigned short status, void *data) static irqreturn_t cam_isr(int irq, void *data) { struct omap1_cam_dev *pcdev = data; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; struct omap1_cam_buf *buf = pcdev->active; u32 it_status; unsigned long flags; @@ -904,9 +903,6 @@ static int omap1_cam_add_device(struct soc_camera_device *icd) struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; - if (pcdev->icd) - return -EBUSY; - clk_enable(pcdev->clk); /* setup sensor clock */ @@ -941,8 +937,6 @@ static int omap1_cam_add_device(struct soc_camera_device *icd) sensor_reset(pcdev, false); - pcdev->icd = icd; - dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", icd->devnum); return 0; @@ -954,8 +948,6 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd) struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; - BUG_ON(icd != pcdev->icd); - suspend_capture(pcdev); disable_capture(pcdev); @@ -974,8 +966,6 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd) clk_disable(pcdev->clk); - pcdev->icd = NULL; - dev_dbg(icd->parent, "OMAP1 Camera driver detached from camera %d\n", icd->devnum); } diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index d665242e8207..686edf7c016c 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -200,7 +200,6 @@ struct pxa_camera_dev { * interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ - struct soc_camera_device *icd; struct clk *clk; unsigned int irq; @@ -966,13 +965,8 @@ static int pxa_camera_add_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; - if (pcdev->icd) - return -EBUSY; - pxa_camera_activate(pcdev); - pcdev->icd = icd; - dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", icd->devnum); @@ -985,8 +979,6 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; - BUG_ON(icd != pcdev->icd); - dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", icd->devnum); @@ -999,8 +991,6 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) DCSR(pcdev->dma_chans[2]) = 0; pxa_camera_deactivate(pcdev); - - pcdev->icd = NULL; } static int test_platform_param(struct pxa_camera_dev *pcdev, @@ -1596,8 +1586,8 @@ static int pxa_camera_suspend(struct device *dev) pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3); pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4); - if (pcdev->icd) { - struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); + if (pcdev->soc_host.icd) { + struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->soc_host.icd); ret = v4l2_subdev_call(sd, core, s_power, 0); if (ret == -ENOIOCTLCMD) ret = 0; @@ -1622,8 +1612,8 @@ static int pxa_camera_resume(struct device *dev) __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3); __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4); - if (pcdev->icd) { - struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); + if (pcdev->soc_host.icd) { + struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->soc_host.icd); ret = v4l2_subdev_call(sd, core, s_power, 1); if (ret == -ENOIOCTLCMD) ret = 0; diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 143d29fe0137..5b7d8e1dd448 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -95,7 +95,6 @@ struct sh_mobile_ceu_buffer { struct sh_mobile_ceu_dev { struct soc_camera_host ici; - struct soc_camera_device *icd; struct platform_device *csi2_pdev; unsigned int irq; @@ -163,7 +162,7 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) { int i, success = 0; - struct soc_camera_device *icd = pcdev->icd; + struct soc_camera_device *icd = pcdev->ici.icd; ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ @@ -277,7 +276,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, */ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { - struct soc_camera_device *icd = pcdev->icd; + struct soc_camera_device *icd = pcdev->ici.icd; dma_addr_t phys_addr_top, phys_addr_bottom; unsigned long top1, top2; unsigned long bottom1, bottom2; @@ -552,9 +551,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) struct v4l2_subdev *csi2_sd; int ret; - if (pcdev->icd) - return -EBUSY; - dev_info(icd->parent, "SuperH Mobile CEU driver attached to camera %d\n", icd->devnum); @@ -583,7 +579,6 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) */ if (ret == -ENODEV && csi2_sd) csi2_sd->grp_id = 0; - pcdev->icd = icd; return 0; } @@ -595,8 +590,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) struct sh_mobile_ceu_dev *pcdev = ici->priv; struct v4l2_subdev *csi2_sd = find_csi2(pcdev); - BUG_ON(icd != pcdev->icd); - v4l2_subdev_call(csi2_sd, core, s_power, 0); if (csi2_sd) csi2_sd->grp_id = 0; @@ -618,8 +611,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) dev_info(icd->parent, "SuperH Mobile CEU driver detached from camera %d\n", icd->devnum); - - pcdev->icd = NULL; } /* diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 5099eebf994d..1e831009f914 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -504,6 +504,32 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd, return ici->ops->set_bus_param(icd); } +static int soc_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + + if (ici->icd) + return -EBUSY; + + ret = ici->ops->add(icd); + if (!ret) + ici->icd = icd; + + return ret; +} + +static void soc_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (WARN_ON(icd != ici->icd)) + return; + + ici->ops->remove(icd); + ici->icd = NULL; +} + static int soc_camera_open(struct file *file) { struct video_device *vdev = video_devdata(file); @@ -567,7 +593,7 @@ static int soc_camera_open(struct file *file) if (sdesc->subdev_desc.reset) sdesc->subdev_desc.reset(icd->pdev); - ret = ici->ops->add(icd); + ret = soc_camera_add_device(icd); if (ret < 0) { dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; @@ -618,7 +644,7 @@ static int soc_camera_open(struct file *file) eresume: __soc_camera_power_off(icd); epower: - ici->ops->remove(icd); + soc_camera_remove_device(icd); eiciadd: icd->use_count--; mutex_unlock(&ici->host_lock); @@ -644,7 +670,7 @@ static int soc_camera_close(struct file *file) vb2_queue_release(&icd->vb2_vidq); __soc_camera_power_off(icd); - ici->ops->remove(icd); + soc_camera_remove_device(icd); } if (icd->streamer == file) @@ -1137,7 +1163,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) ssdd->reset(icd->pdev); mutex_lock(&ici->host_lock); - ret = ici->ops->add(icd); + ret = soc_camera_add_device(icd); mutex_unlock(&ici->host_lock); if (ret < 0) goto eadd; @@ -1210,7 +1236,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->field = mf.field; } - ici->ops->remove(icd); + soc_camera_remove_device(icd); mutex_unlock(&ici->host_lock); @@ -1233,7 +1259,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->vdev = NULL; evdc: mutex_lock(&ici->host_lock); - ici->ops->remove(icd); + soc_camera_remove_device(icd); mutex_unlock(&ici->host_lock); eadd: v4l2_ctrl_handler_free(&icd->ctrl_handler); diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 31a4bfe42194..db23a8f0c26b 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -64,6 +64,7 @@ struct soc_camera_host { struct mutex host_lock; /* Protect pipeline modifications */ unsigned char nr; /* Host number */ u32 capabilities; + struct soc_camera_device *icd; /* Currently attached client */ void *priv; const char *drv_name; struct soc_camera_host_ops *ops; -- GitLab From eb569cf9db804e6ba34b3a1812415e59d5e43d1a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 08:51:36 -0300 Subject: [PATCH 1661/2900] [media] soc-camera: add host clock callbacks to start and stop the master clock Currently soc-camera uses a single camera host callback to activate the interface master clock and to configure the interface for a specific client. However, during probing we might not have the information about a client, we just need to activate the clock. Add new camera host driver callbacks to only start and stop the clock without and client-specific configuration. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/soc_camera.c | 19 +++++++++++++++++-- include/media/soc_camera.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 1e831009f914..3cc086036070 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -512,10 +512,23 @@ static int soc_camera_add_device(struct soc_camera_device *icd) if (ici->icd) return -EBUSY; + if (ici->ops->clock_start) { + ret = ici->ops->clock_start(ici); + if (ret < 0) + return ret; + } + ret = ici->ops->add(icd); - if (!ret) - ici->icd = icd; + if (ret < 0) + goto eadd; + + ici->icd = icd; + return 0; + +eadd: + if (ici->ops->clock_stop) + ici->ops->clock_stop(ici); return ret; } @@ -527,6 +540,8 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) return; ici->ops->remove(icd); + if (ici->ops->clock_stop) + ici->ops->clock_stop(ici); ici->icd = NULL; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index db23a8f0c26b..dfa24df960df 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -74,6 +74,8 @@ struct soc_camera_host_ops { struct module *owner; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); + int (*clock_start)(struct soc_camera_host *); + void (*clock_stop)(struct soc_camera_host *); /* * .get_formats() is called for each client device format, but * .put_formats() is only called once. Further, if any of the calls to -- GitLab From 39b553dbb4a75debf814a261e58f09347eef337f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 08:56:00 -0300 Subject: [PATCH 1662/2900] [media] pxa-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the pxa-camera driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/pxa_camera.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 686edf7c016c..d4df305fcc18 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -955,33 +955,39 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) return IRQ_HANDLED; } +static int pxa_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void pxa_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on PXA quick capture interface * Called with .host_lock held */ -static int pxa_camera_add_device(struct soc_camera_device *icd) +static int pxa_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; pxa_camera_activate(pcdev); - dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", - icd->devnum); - return 0; } /* Called with .host_lock held */ -static void pxa_camera_remove_device(struct soc_camera_device *icd) +static void pxa_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; - dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", - icd->devnum); - /* disable capture, disable interrupts */ __raw_writel(0x3ff, pcdev->base + CICR0); @@ -1630,6 +1636,8 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .owner = THIS_MODULE, .add = pxa_camera_add_device, .remove = pxa_camera_remove_device, + .clock_start = pxa_camera_clock_start, + .clock_stop = pxa_camera_clock_stop, .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, .put_formats = pxa_camera_put_formats, -- GitLab From b5dbfe46e40fa3fd9a6dd43f20cc71050fe5ef2d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 09:38:00 -0300 Subject: [PATCH 1663/2900] [media] omap1-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the omap1-camera driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/omap1_camera.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index c42c23e4eb72..6769193c7c7b 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -893,13 +893,26 @@ static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset) CAM_WRITE(pcdev, GPIO, !reset); } +static int omap1_cam_add_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void omap1_cam_remove_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, + "OMAP1 Camera driver detached from camera %d\n", icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on OMAP1 camera sensor interface */ -static int omap1_cam_add_device(struct soc_camera_device *icd) +static int omap1_cam_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; @@ -937,14 +950,11 @@ static int omap1_cam_add_device(struct soc_camera_device *icd) sensor_reset(pcdev, false); - dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", - icd->devnum); return 0; } -static void omap1_cam_remove_device(struct soc_camera_device *icd) +static void omap1_cam_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; @@ -965,9 +975,6 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN); clk_disable(pcdev->clk); - - dev_dbg(icd->parent, - "OMAP1 Camera driver detached from camera %d\n", icd->devnum); } /* Duplicate standard formats based on host capability of byte swapping */ @@ -1525,6 +1532,8 @@ static struct soc_camera_host_ops omap1_host_ops = { .owner = THIS_MODULE, .add = omap1_cam_add_device, .remove = omap1_cam_remove_device, + .clock_start = omap1_cam_clock_start, + .clock_stop = omap1_cam_clock_stop, .get_formats = omap1_cam_get_formats, .set_crop = omap1_cam_set_crop, .set_fmt = omap1_cam_set_fmt, -- GitLab From ffebad7948ee0e9c619ae6e87d99437d907fc7e3 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 09:56:09 -0300 Subject: [PATCH 1664/2900] [media] atmel-isi: move interface activation and deactivation to clock callbacks When adding and removing a client, the atmel-isi camera host driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/atmel-isi.c | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index c9e080a57a60..104485632501 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -745,10 +745,23 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, return formats; } -/* Called with .host_lock held */ static int isi_camera_add_device(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void isi_camera_remove_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n", + icd->devnum); +} + +/* Called with .host_lock held */ +static int isi_camera_clock_start(struct soc_camera_host *ici) +{ struct atmel_isi *isi = ici->priv; int ret; @@ -762,21 +775,16 @@ static int isi_camera_add_device(struct soc_camera_device *icd) return ret; } - dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", - icd->devnum); return 0; } + /* Called with .host_lock held */ -static void isi_camera_remove_device(struct soc_camera_device *icd) +static void isi_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; clk_disable(isi->mck); clk_disable(isi->pclk); - - dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n", - icd->devnum); } static unsigned int isi_camera_poll(struct file *file, poll_table *pt) @@ -880,6 +888,8 @@ static struct soc_camera_host_ops isi_soc_camera_host_ops = { .owner = THIS_MODULE, .add = isi_camera_add_device, .remove = isi_camera_remove_device, + .clock_start = isi_camera_clock_start, + .clock_stop = isi_camera_clock_stop, .set_fmt = isi_camera_set_fmt, .try_fmt = isi_camera_try_fmt, .get_formats = isi_camera_get_formats, -- GitLab From 663ccaf4cd61f510e8a8e9bb913d2ee9b1e94932 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 11:24:43 -0300 Subject: [PATCH 1665/2900] [media] mx3-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the mx3-camera driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/mx3_camera.c | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 71b9b191957c..1047e3e8db77 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -460,8 +460,7 @@ static int mx3_camera_init_videobuf(struct vb2_queue *q, } /* First part of ipu_csi_init_interface() */ -static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, - struct soc_camera_device *icd) +static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam) { u32 conf; long rate; @@ -505,31 +504,40 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, clk_prepare_enable(mx3_cam->clk); rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); - dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + dev_dbg(mx3_cam->soc_host.v4l2_dev.dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); if (rate) clk_set_rate(mx3_cam->clk, rate); } -/* Called with .host_lock held */ static int mx3_camera_add_device(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx3_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", + icd->devnum); +} + +/* Called with .host_lock held */ +static int mx3_camera_clock_start(struct soc_camera_host *ici) +{ struct mx3_camera_dev *mx3_cam = ici->priv; - mx3_camera_activate(mx3_cam, icd); + mx3_camera_activate(mx3_cam); mx3_cam->buf_total = 0; - dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", - icd->devnum); - return 0; } /* Called with .host_lock held */ -static void mx3_camera_remove_device(struct soc_camera_device *icd) +static void mx3_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; @@ -539,9 +547,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd) } clk_disable_unprepare(mx3_cam->clk); - - dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", - icd->devnum); } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -1124,6 +1129,8 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx3_camera_add_device, .remove = mx3_camera_remove_device, + .clock_start = mx3_camera_clock_start, + .clock_stop = mx3_camera_clock_stop, .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, -- GitLab From 6b417c897000515e308ff45687319f8ede1ccdd2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 11:49:13 -0300 Subject: [PATCH 1666/2900] [media] mx2-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the mx2-camera driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/mx2_camera.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 772e0710f59b..45a0276be4e5 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -412,13 +412,26 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) writel(0, pcdev->base_emma + PRP_CNTL); } +static int mx2_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx2_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on mx2 camera sensor interface */ -static int mx2_camera_add_device(struct soc_camera_device *icd) +static int mx2_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; int ret; u32 csicr1; @@ -439,9 +452,6 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) pcdev->frame_count = 0; - dev_info(icd->parent, "Camera driver attached to camera %d\n", - icd->devnum); - return 0; exit_csi_ahb: @@ -450,14 +460,10 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) return ret; } -static void mx2_camera_remove_device(struct soc_camera_device *icd) +static void mx2_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; - dev_info(icd->parent, "Camera driver detached from camera %d\n", - icd->devnum); - mx2_camera_deactivate(pcdev); } @@ -1271,6 +1277,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx2_camera_add_device, .remove = mx2_camera_remove_device, + .clock_start = mx2_camera_clock_start, + .clock_stop = mx2_camera_clock_stop, .set_fmt = mx2_camera_set_fmt, .set_crop = mx2_camera_set_crop, .get_formats = mx2_camera_get_formats, -- GitLab From d71042c1fa1c3b32bfd55151eef6b2e104301a11 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 12:06:32 -0300 Subject: [PATCH 1667/2900] [media] mx1-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the mx1-camera driver only activates and deactivates its camera interface respectively, which doesn't include any client-specific actions. Move this functionality into .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/mx1_camera.c | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index 5f9ec8efd978..fea3e61476ae 100644 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c @@ -399,7 +399,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->soc_host.icd->parent, "Activate device\n"); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n"); clk_prepare_enable(pcdev->clk); @@ -415,7 +415,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->soc_host.icd->parent, "Deactivate device\n"); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -423,26 +423,35 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) clk_disable_unprepare(pcdev->clk); } +static int mx1_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx1_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on i.MX1/i.MXL camera sensor interface */ -static int mx1_camera_add_device(struct soc_camera_device *icd) +static int mx1_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; - dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", - icd->devnum); - mx1_camera_activate(pcdev); return 0; } -static void mx1_camera_remove_device(struct soc_camera_device *icd) +static void mx1_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; unsigned int csicr1; @@ -453,9 +462,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) /* Stop DMA engine */ imx_dma_disable(pcdev->dma_chan); - dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n", - icd->devnum); - mx1_camera_deactivate(pcdev); } @@ -669,6 +675,8 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx1_camera_add_device, .remove = mx1_camera_remove_device, + .clock_start = mx1_camera_clock_start, + .clock_stop = mx1_camera_clock_stop, .set_bus_param = mx1_camera_set_bus_param, .set_fmt = mx1_camera_set_fmt, .try_fmt = mx1_camera_try_fmt, -- GitLab From 0ff6a6e8fb6915e68b93ff169b1eb66c0ba15d56 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 12:54:20 -0300 Subject: [PATCH 1668/2900] [media] sh-mobile-ceu-camera: move interface activation and deactivation to clock callbacks When adding and removing a client, the sh-mobile-ceu-camera driver activates and, respectively, deactivates its camera interface and, if necessary, the CSI2 controller. Only handling of the CSI2 interface is client-specific and is only needed, when a data-exchange with the client is taking place. Move the rest to .clock_start() and .clock_stop() callbacks. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../soc_camera/sh_mobile_ceu_camera.c | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 5b7d8e1dd448..9037472e9ced 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -162,7 +162,6 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) { int i, success = 0; - struct soc_camera_device *icd = pcdev->ici.icd; ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ @@ -186,7 +185,7 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) if (2 != success) { - dev_warn(icd->pdev, "soft reset time out\n"); + dev_warn(pcdev->ici.v4l2_dev.dev, "soft reset time out\n"); return -EIO; } @@ -543,35 +542,21 @@ static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev) return NULL; } -/* Called with .host_lock held */ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_subdev *csi2_sd; + struct v4l2_subdev *csi2_sd = find_csi2(pcdev); int ret; - dev_info(icd->parent, - "SuperH Mobile CEU driver attached to camera %d\n", - icd->devnum); - - pm_runtime_get_sync(ici->v4l2_dev.dev); - - pcdev->buf_total = 0; - - ret = sh_mobile_ceu_soft_reset(pcdev); - - csi2_sd = find_csi2(pcdev); if (csi2_sd) { csi2_sd->grp_id = soc_camera_grp_id(icd); v4l2_set_subdev_hostdata(csi2_sd, icd); } ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { - pm_runtime_put(ici->v4l2_dev.dev); + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) return ret; - } /* * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver @@ -580,19 +565,48 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) if (ret == -ENODEV && csi2_sd) csi2_sd->grp_id = 0; + dev_info(icd->parent, + "SuperH Mobile CEU driver attached to camera %d\n", + icd->devnum); + return 0; } -/* Called with .host_lock held */ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct v4l2_subdev *csi2_sd = find_csi2(pcdev); + dev_info(icd->parent, + "SuperH Mobile CEU driver detached from camera %d\n", + icd->devnum); + v4l2_subdev_call(csi2_sd, core, s_power, 0); if (csi2_sd) csi2_sd->grp_id = 0; +} + +/* Called with .host_lock held */ +static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) +{ + struct sh_mobile_ceu_dev *pcdev = ici->priv; + int ret; + + pm_runtime_get_sync(ici->v4l2_dev.dev); + + pcdev->buf_total = 0; + + ret = sh_mobile_ceu_soft_reset(pcdev); + + return 0; +} + +/* Called with .host_lock held */ +static void sh_mobile_ceu_clock_stop(struct soc_camera_host *ici) +{ + struct sh_mobile_ceu_dev *pcdev = ici->priv; + /* disable capture, disable interrupts */ ceu_write(pcdev, CEIER, 0); sh_mobile_ceu_soft_reset(pcdev); @@ -607,10 +621,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) spin_unlock_irq(&pcdev->lock); pm_runtime_put(ici->v4l2_dev.dev); - - dev_info(icd->parent, - "SuperH Mobile CEU driver detached from camera %d\n", - icd->devnum); } /* @@ -2027,6 +2037,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, + .clock_start = sh_mobile_ceu_clock_start, + .clock_stop = sh_mobile_ceu_clock_stop, .get_formats = sh_mobile_ceu_get_formats, .put_formats = sh_mobile_ceu_put_formats, .get_crop = sh_mobile_ceu_get_crop, -- GitLab From a78fcc11264b824d9651b55abfeedd16d5cd8415 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 13:19:58 -0300 Subject: [PATCH 1669/2900] [media] soc-camera: make .clock_{start,stop} compulsory, .add / .remove optional All existing soc-camera host drivers use .clock_start() and .clock_stop() callbacks to activate and deactivate their camera interfaces, whereas .add() and .remove() callbacks are usually dummy. Make the former two compulsory and the latter two optional. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/soc_camera.c | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 3cc086036070..24393a14aaf6 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -512,23 +512,22 @@ static int soc_camera_add_device(struct soc_camera_device *icd) if (ici->icd) return -EBUSY; - if (ici->ops->clock_start) { - ret = ici->ops->clock_start(ici); + ret = ici->ops->clock_start(ici); + if (ret < 0) + return ret; + + if (ici->ops->add) { + ret = ici->ops->add(icd); if (ret < 0) - return ret; + goto eadd; } - ret = ici->ops->add(icd); - if (ret < 0) - goto eadd; - ici->icd = icd; return 0; eadd: - if (ici->ops->clock_stop) - ici->ops->clock_stop(ici); + ici->ops->clock_stop(ici); return ret; } @@ -539,9 +538,9 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) if (WARN_ON(icd != ici->icd)) return; - ici->ops->remove(icd); - if (ici->ops->clock_stop) - ici->ops->clock_stop(ici); + if (ici->ops->remove) + ici->ops->remove(icd); + ici->ops->clock_stop(ici); ici->icd = NULL; } @@ -1383,8 +1382,8 @@ int soc_camera_host_register(struct soc_camera_host *ici) ((!ici->ops->init_videobuf || !ici->ops->reqbufs) && !ici->ops->init_videobuf2) || - !ici->ops->add || - !ici->ops->remove || + !ici->ops->clock_start || + !ici->ops->clock_stop || !ici->ops->poll || !ici->v4l2_dev.dev) return -EINVAL; -- GitLab From 90438926e807bca4f80237f436bc7d904151fc2b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 4 Apr 2013 14:21:54 -0300 Subject: [PATCH 1670/2900] [media] soc-camera: don't attach the client to the host during probing During client probing we only have to turn on the host's clock, no need to actually attach the client to the host. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 24393a14aaf6..fa8a728b7a5d 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1177,7 +1177,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) ssdd->reset(icd->pdev); mutex_lock(&ici->host_lock); - ret = soc_camera_add_device(icd); + ret = ici->ops->clock_start(ici); mutex_unlock(&ici->host_lock); if (ret < 0) goto eadd; @@ -1250,7 +1250,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->field = mf.field; } - soc_camera_remove_device(icd); + ici->ops->clock_stop(ici); mutex_unlock(&ici->host_lock); @@ -1273,7 +1273,7 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->vdev = NULL; evdc: mutex_lock(&ici->host_lock); - soc_camera_remove_device(icd); + ici->ops->clock_stop(ici); mutex_unlock(&ici->host_lock); eadd: v4l2_ctrl_handler_free(&icd->ctrl_handler); -- GitLab From f146e4e79a6f5d457553dfe2ac66b93c7a39f676 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 17 Sep 2012 07:42:55 -0300 Subject: [PATCH 1671/2900] [media] sh-mobile-ceu-camera: add primitive OF support Add an OF hook to sh_mobile_ceu_camera.c, no properties so far. Booting with DT also requires platform data to be optional. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../soc_camera/sh_mobile_ceu_camera.c | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 9037472e9ced..fcc13d8eb070 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,7 @@ struct sh_mobile_ceu_dev { enum v4l2_field field; int sequence; + unsigned long flags; unsigned int image_mode:1; unsigned int is_16bit:1; @@ -706,7 +708,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) } /* CSI2 special configuration */ - if (pcdev->pdata->csi2) { + if (pcdev->csi2_pdev) { in_width = ((in_width - 2) * 2); left_offset *= 2; } @@ -810,7 +812,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) /* Make choises, based on platform preferences */ if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { - if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW) + if (pcdev->flags & SH_CEU_FLAG_HSYNC_LOW) common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; else common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; @@ -818,7 +820,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { - if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW) + if (pcdev->flags & SH_CEU_FLAG_VSYNC_LOW) common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; else common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; @@ -873,11 +875,11 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; - if (pcdev->pdata->csi2) /* CSI2 mode */ + if (pcdev->csi2_pdev) /* CSI2 mode */ value |= 3 << 12; else if (pcdev->is_16bit) value |= 1 << 12; - else if (pcdev->pdata->flags & SH_CEU_FLAG_LOWER_8BIT) + else if (pcdev->flags & SH_CEU_FLAG_LOWER_8BIT) value |= 2 << 12; ceu_write(pcdev, CAMCR, value); @@ -1052,7 +1054,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int return 0; } - if (!pcdev->pdata->csi2) { + if (!pcdev->pdata || !pcdev->pdata->csi2) { /* Are there any restrictions in the CSI-2 case? */ ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) @@ -2107,13 +2109,17 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) init_completion(&pcdev->complete); pcdev->pdata = pdev->dev.platform_data; - if (!pcdev->pdata) { + if (!pcdev->pdata && !pdev->dev.of_node) { dev_err(&pdev->dev, "CEU platform data not set.\n"); return -EINVAL; } - pcdev->max_width = pcdev->pdata->max_width ? : 2560; - pcdev->max_height = pcdev->pdata->max_height ? : 1920; + /* TODO: implement per-device bus flags */ + if (pcdev->pdata) { + pcdev->max_width = pcdev->pdata->max_width ? : 2560; + pcdev->max_height = pcdev->pdata->max_height ? : 1920; + pcdev->flags = pcdev->pdata->flags; + } base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) @@ -2168,7 +2174,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_free_ctx; /* CSI2 interfacing */ - csi2 = pcdev->pdata->csi2; + csi2 = pcdev->pdata ? pcdev->pdata->csi2 : NULL; if (csi2) { struct platform_device *csi2_pdev = platform_device_alloc("sh-mobile-csi2", csi2->id); @@ -2290,10 +2296,17 @@ static const struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { .runtime_resume = sh_mobile_ceu_runtime_nop, }; +static const struct of_device_id sh_mobile_ceu_of_match[] = { + { .compatible = "renesas,sh-mobile-ceu" }, + { } +}; +MODULE_DEVICE_TABLE(of, sh_mobile_ceu_of_match); + static struct platform_driver sh_mobile_ceu_driver = { .driver = { .name = "sh_mobile_ceu", .pm = &sh_mobile_ceu_dev_pm_ops, + .of_match_table = sh_mobile_ceu_of_match, }, .probe = sh_mobile_ceu_probe, .remove = sh_mobile_ceu_remove, -- GitLab From 812e8b22ea55218449de310a666dd1ce16f924ed Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 17 Sep 2012 07:48:33 -0300 Subject: [PATCH 1672/2900] [media] sh-mobile-ceu-driver: support max width and height in DT Some CEU implementations have non-standard (larger) maximum supported width and height values. Add two OF properties to specify them. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/sh_mobile_ceu.txt | 18 +++++++++++++++ .../soc_camera/sh_mobile_ceu_camera.c | 23 +++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/sh_mobile_ceu.txt diff --git a/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt b/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt new file mode 100644 index 000000000000..1ce4e46bcbb7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt @@ -0,0 +1,18 @@ +Bindings, specific for the sh_mobile_ceu_camera.c driver: + - compatible: Should be "renesas,sh-mobile-ceu" + - reg: register base and size + - interrupts: the interrupt number + - interrupt-parent: the interrupt controller + - renesas,max-width: maximum image width, supported on this SoC + - renesas,max-height: maximum image height, supported on this SoC + +Example: + +ceu0: ceu@0xfe910000 { + compatible = "renesas,sh-mobile-ceu"; + reg = <0xfe910000 0xa0>; + interrupt-parent = <&intcs>; + interrupts = <0x880>; + renesas,max-width = <8188>; + renesas,max-height = <8188>; +}; diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index fcc13d8eb070..b0f0995fc80b 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -2116,11 +2116,30 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) /* TODO: implement per-device bus flags */ if (pcdev->pdata) { - pcdev->max_width = pcdev->pdata->max_width ? : 2560; - pcdev->max_height = pcdev->pdata->max_height ? : 1920; + pcdev->max_width = pcdev->pdata->max_width; + pcdev->max_height = pcdev->pdata->max_height; pcdev->flags = pcdev->pdata->flags; } + if (!pcdev->max_width) { + unsigned int v; + err = of_property_read_u32(pdev->dev.of_node, "renesas,max-width", &v); + if (!err) + pcdev->max_width = v; + + if (!pcdev->max_width) + pcdev->max_width = 2560; + } + if (!pcdev->max_height) { + unsigned int v; + err = of_property_read_u32(pdev->dev.of_node, "renesas,max-height", &v); + if (!err) + pcdev->max_height = v; + + if (!pcdev->max_height) + pcdev->max_height = 1920; + } + base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); -- GitLab From ff5430de70e8137daccecfa1211509f95fcc8d25 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 4 Dec 2012 07:42:15 -0300 Subject: [PATCH 1673/2900] [media] V4L2: add temporary clock helpers Typical video devices like camera sensors require an external clock source. Many such devices cannot even access their hardware registers without a running clock. These clock sources should be controlled by their consumers. This should be performed, using the generic clock framework. Unfortunately so far only very few systems have been ported to that framework. This patch adds a set of temporary helpers, mimicking the generic clock API, to V4L2. Platforms, adopting the clock API, should switch to using it. Eventually this temporary API should be removed. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 2 +- drivers/media/v4l2-core/v4l2-clk.c | 242 +++++++++++++++++++++++++++++ include/media/v4l2-clk.h | 54 +++++++ 3 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 drivers/media/v4l2-core/v4l2-clk.c create mode 100644 include/media/v4l2-clk.h diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index aa50c46314b7..628c6307e978 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -5,7 +5,7 @@ tuner-objs := tuner-core.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o v4l2-subdev.o + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o ifeq ($(CONFIG_COMPAT),y) videodev-objs += v4l2-compat-ioctl32.o endif diff --git a/drivers/media/v4l2-core/v4l2-clk.c b/drivers/media/v4l2-core/v4l2-clk.c new file mode 100644 index 000000000000..b67de8642b5a --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-clk.c @@ -0,0 +1,242 @@ +/* + * V4L2 clock service + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static DEFINE_MUTEX(clk_lock); +static LIST_HEAD(clk_list); + +static struct v4l2_clk *v4l2_clk_find(const char *dev_id, const char *id) +{ + struct v4l2_clk *clk; + + list_for_each_entry(clk, &clk_list, list) { + if (strcmp(dev_id, clk->dev_id)) + continue; + + if (!id || !clk->id || !strcmp(clk->id, id)) + return clk; + } + + return ERR_PTR(-ENODEV); +} + +struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id) +{ + struct v4l2_clk *clk; + + mutex_lock(&clk_lock); + clk = v4l2_clk_find(dev_name(dev), id); + + if (!IS_ERR(clk)) + atomic_inc(&clk->use_count); + mutex_unlock(&clk_lock); + + return clk; +} +EXPORT_SYMBOL(v4l2_clk_get); + +void v4l2_clk_put(struct v4l2_clk *clk) +{ + struct v4l2_clk *tmp; + + if (IS_ERR(clk)) + return; + + mutex_lock(&clk_lock); + + list_for_each_entry(tmp, &clk_list, list) + if (tmp == clk) + atomic_dec(&clk->use_count); + + mutex_unlock(&clk_lock); +} +EXPORT_SYMBOL(v4l2_clk_put); + +static int v4l2_clk_lock_driver(struct v4l2_clk *clk) +{ + struct v4l2_clk *tmp; + int ret = -ENODEV; + + mutex_lock(&clk_lock); + + list_for_each_entry(tmp, &clk_list, list) + if (tmp == clk) { + ret = !try_module_get(clk->ops->owner); + if (ret) + ret = -EFAULT; + break; + } + + mutex_unlock(&clk_lock); + + return ret; +} + +static void v4l2_clk_unlock_driver(struct v4l2_clk *clk) +{ + module_put(clk->ops->owner); +} + +int v4l2_clk_enable(struct v4l2_clk *clk) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + + if (++clk->enable == 1 && clk->ops->enable) { + ret = clk->ops->enable(clk); + if (ret < 0) + clk->enable--; + } + + mutex_unlock(&clk->lock); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_enable); + +/* + * You might Oops if you try to disabled a disabled clock, because then the + * driver isn't locked and could have been unloaded by now, so, don't do that + */ +void v4l2_clk_disable(struct v4l2_clk *clk) +{ + int enable; + + mutex_lock(&clk->lock); + + enable = --clk->enable; + if (WARN(enable < 0, "Unbalanced %s() on %s:%s!\n", __func__, + clk->dev_id, clk->id)) + clk->enable++; + else if (!enable && clk->ops->disable) + clk->ops->disable(clk); + + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); +} +EXPORT_SYMBOL(v4l2_clk_disable); + +unsigned long v4l2_clk_get_rate(struct v4l2_clk *clk) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + if (!clk->ops->get_rate) + ret = -ENOSYS; + else + ret = clk->ops->get_rate(clk); + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_get_rate); + +int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + if (!clk->ops->set_rate) + ret = -ENOSYS; + else + ret = clk->ops->set_rate(clk, rate); + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_set_rate); + +struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops, + const char *dev_id, + const char *id, void *priv) +{ + struct v4l2_clk *clk; + int ret; + + if (!ops || !dev_id) + return ERR_PTR(-EINVAL); + + clk = kzalloc(sizeof(struct v4l2_clk), GFP_KERNEL); + if (!clk) + return ERR_PTR(-ENOMEM); + + clk->id = kstrdup(id, GFP_KERNEL); + clk->dev_id = kstrdup(dev_id, GFP_KERNEL); + if ((id && !clk->id) || !clk->dev_id) { + ret = -ENOMEM; + goto ealloc; + } + clk->ops = ops; + clk->priv = priv; + atomic_set(&clk->use_count, 0); + mutex_init(&clk->lock); + + mutex_lock(&clk_lock); + if (!IS_ERR(v4l2_clk_find(dev_id, id))) { + mutex_unlock(&clk_lock); + ret = -EEXIST; + goto eexist; + } + list_add_tail(&clk->list, &clk_list); + mutex_unlock(&clk_lock); + + return clk; + +eexist: +ealloc: + kfree(clk->id); + kfree(clk->dev_id); + kfree(clk); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(v4l2_clk_register); + +void v4l2_clk_unregister(struct v4l2_clk *clk) +{ + if (WARN(atomic_read(&clk->use_count), + "%s(): Refusing to unregister ref-counted %s:%s clock!\n", + __func__, clk->dev_id, clk->id)) + return; + + mutex_lock(&clk_lock); + list_del(&clk->list); + mutex_unlock(&clk_lock); + + kfree(clk->id); + kfree(clk->dev_id); + kfree(clk); +} +EXPORT_SYMBOL(v4l2_clk_unregister); diff --git a/include/media/v4l2-clk.h b/include/media/v4l2-clk.h new file mode 100644 index 000000000000..0503a90b48bb --- /dev/null +++ b/include/media/v4l2-clk.h @@ -0,0 +1,54 @@ +/* + * V4L2 clock service + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ATTENTION: This is a temporary API and it shall be replaced by the generic + * clock API, when the latter becomes widely available. + */ + +#ifndef MEDIA_V4L2_CLK_H +#define MEDIA_V4L2_CLK_H + +#include +#include +#include + +struct module; +struct device; + +struct v4l2_clk { + struct list_head list; + const struct v4l2_clk_ops *ops; + const char *dev_id; + const char *id; + int enable; + struct mutex lock; /* Protect the enable count */ + atomic_t use_count; + void *priv; +}; + +struct v4l2_clk_ops { + struct module *owner; + int (*enable)(struct v4l2_clk *clk); + void (*disable)(struct v4l2_clk *clk); + unsigned long (*get_rate)(struct v4l2_clk *clk); + int (*set_rate)(struct v4l2_clk *clk, unsigned long); +}; + +struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops, + const char *dev_name, + const char *name, void *priv); +void v4l2_clk_unregister(struct v4l2_clk *clk); +struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id); +void v4l2_clk_put(struct v4l2_clk *clk); +int v4l2_clk_enable(struct v4l2_clk *clk); +void v4l2_clk_disable(struct v4l2_clk *clk); +unsigned long v4l2_clk_get_rate(struct v4l2_clk *clk); +int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate); + +#endif -- GitLab From 668773b84604926519e2baf444f382f88d799d41 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 10 Jun 2013 15:07:35 -0300 Subject: [PATCH 1674/2900] [media] V4L2: add a device pointer to struct v4l2_subdev It is often useful to have simple means to get from a subdevice to the underlying physical device. This patch adds such a pointer to struct v4l2_subdev and sets it accordingly in the I2C and SPI cases. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Tested-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 2 ++ include/media/v4l2-subdev.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3b2a7606bc84..a95e5e23403f 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -237,6 +237,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, sd->flags |= V4L2_SUBDEV_FL_IS_I2C; /* the owner is the same as the i2c_client's driver owner */ sd->owner = client->driver->driver.owner; + sd->dev = &client->dev; /* i2c_client and v4l2_subdev point to one another */ v4l2_set_subdevdata(sd, client); i2c_set_clientdata(client, sd); @@ -370,6 +371,7 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, sd->flags |= V4L2_SUBDEV_FL_IS_SPI; /* the owner is the same as the spi_device's driver owner */ sd->owner = spi->dev.driver->owner; + sd->dev = &spi->dev; /* spi_device and v4l2_subdev point to one another */ v4l2_set_subdevdata(sd, spi); spi_set_drvdata(spi, sd); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 21fc9e16d7be..5fbb266405f9 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -583,6 +583,8 @@ struct v4l2_subdev { void *host_priv; /* subdev device node */ struct video_device *devnode; + /* pointer to the physical device, if any */ + struct device *dev; }; #define media_entity_to_v4l2_subdev(ent) \ -- GitLab From e9e310491bdbc8c0f33ea0e2ce65eff345a01f71 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 8 Jan 2013 07:06:31 -0300 Subject: [PATCH 1675/2900] [media] V4L2: support asynchronous subdevice registration Currently bridge device drivers register devices for all subdevices synchronously, typically, during their probing. E.g. if an I2C CMOS sensor is attached to a video bridge device, the bridge driver will create an I2C device and wait for the respective I2C driver to probe. This makes linking of devices straight forward, but this approach cannot be used with intrinsically asynchronous and unordered device registration systems like the Flattened Device Tree. To support such systems this patch adds an asynchronous subdevice registration framework to V4L2. To use it respective (e.g. I2C) subdevice drivers must register themselves with the framework. A bridge driver on the other hand must register notification callbacks, that will be called upon various related events. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Tested-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Makefile | 3 +- drivers/media/v4l2-core/v4l2-async.c | 280 +++++++++++++++++++++++++++ include/media/v4l2-async.h | 105 ++++++++++ include/media/v4l2-subdev.h | 8 + 4 files changed, 395 insertions(+), 1 deletion(-) create mode 100644 drivers/media/v4l2-core/v4l2-async.c create mode 100644 include/media/v4l2-async.h diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index 628c6307e978..4c33b8d6520c 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -5,7 +5,8 @@ tuner-objs := tuner-core.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \ + v4l2-async.o ifeq ($(CONFIG_COMPAT),y) videodev-objs += v4l2-compat-ioctl32.o endif diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c new file mode 100644 index 000000000000..c80ffb4ba567 --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -0,0 +1,280 @@ +/* + * V4L2 asynchronous subdevice registration API + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) +{ + struct i2c_client *client = i2c_verify_client(dev); + return client && + asd->bus_type == V4L2_ASYNC_BUS_I2C && + asd->match.i2c.adapter_id == client->adapter->nr && + asd->match.i2c.address == client->addr; +} + +static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd) +{ + return asd->bus_type == V4L2_ASYNC_BUS_PLATFORM && + !strcmp(asd->match.platform.name, dev_name(dev)); +} + +static LIST_HEAD(subdev_list); +static LIST_HEAD(notifier_list); +static DEFINE_MUTEX(list_lock); + +static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + struct v4l2_async_subdev *asd; + bool (*match)(struct device *, + struct v4l2_async_subdev *); + + list_for_each_entry(asd, ¬ifier->waiting, list) { + /* bus_type has been verified valid before */ + switch (asd->bus_type) { + case V4L2_ASYNC_BUS_CUSTOM: + match = asd->match.custom.match; + if (!match) + /* Match always */ + return asd; + break; + case V4L2_ASYNC_BUS_PLATFORM: + match = match_platform; + break; + case V4L2_ASYNC_BUS_I2C: + match = match_i2c; + break; + default: + /* Cannot happen, unless someone breaks us */ + WARN_ON(true); + return NULL; + } + + /* match cannot be NULL here */ + if (match(sd->dev, asd)) + return asd; + } + + return NULL; +} + +static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl, + struct v4l2_async_subdev *asd) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + int ret; + + /* Remove from the waiting list */ + list_del(&asd->list); + asdl->asd = asd; + asdl->notifier = notifier; + + if (notifier->bound) { + ret = notifier->bound(notifier, sd, asd); + if (ret < 0) + return ret; + } + /* Move from the global subdevice list to notifier's done */ + list_move(&asdl->list, ¬ifier->done); + + ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); + if (ret < 0) { + if (notifier->unbind) + notifier->unbind(notifier, sd, asd); + return ret; + } + + if (list_empty(¬ifier->waiting) && notifier->complete) + return notifier->complete(notifier); + + return 0; +} + +static void v4l2_async_cleanup(struct v4l2_async_subdev_list *asdl) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + + v4l2_device_unregister_subdev(sd); + /* Subdevice driver will reprobe and put asdl back onto the list */ + list_del_init(&asdl->list); + asdl->asd = NULL; + sd->dev = NULL; +} + +int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, + struct v4l2_async_notifier *notifier) +{ + struct v4l2_async_subdev_list *asdl, *tmp; + struct v4l2_async_subdev *asd; + int i; + + if (!notifier->num_subdevs || notifier->num_subdevs > V4L2_MAX_SUBDEVS) + return -EINVAL; + + notifier->v4l2_dev = v4l2_dev; + INIT_LIST_HEAD(¬ifier->waiting); + INIT_LIST_HEAD(¬ifier->done); + + for (i = 0; i < notifier->num_subdevs; i++) { + asd = notifier->subdev[i]; + + switch (asd->bus_type) { + case V4L2_ASYNC_BUS_CUSTOM: + case V4L2_ASYNC_BUS_PLATFORM: + case V4L2_ASYNC_BUS_I2C: + break; + default: + dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, + "Invalid bus-type %u on %p\n", + asd->bus_type, asd); + return -EINVAL; + } + list_add_tail(&asd->list, ¬ifier->waiting); + } + + mutex_lock(&list_lock); + + /* Keep also completed notifiers on the list */ + list_add(¬ifier->list, ¬ifier_list); + + list_for_each_entry_safe(asdl, tmp, &subdev_list, list) { + int ret; + + asd = v4l2_async_belongs(notifier, asdl); + if (!asd) + continue; + + ret = v4l2_async_test_notify(notifier, asdl, asd); + if (ret < 0) { + mutex_unlock(&list_lock); + return ret; + } + } + + mutex_unlock(&list_lock); + + return 0; +} +EXPORT_SYMBOL(v4l2_async_notifier_register); + +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +{ + struct v4l2_async_subdev_list *asdl, *tmp; + unsigned int notif_n_subdev = notifier->num_subdevs; + unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); + struct device *dev[n_subdev]; + int i = 0; + + mutex_lock(&list_lock); + + list_del(¬ifier->list); + + list_for_each_entry_safe(asdl, tmp, ¬ifier->done, list) { + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + + dev[i] = get_device(sd->dev); + + v4l2_async_cleanup(asdl); + + /* If we handled USB devices, we'd have to lock the parent too */ + device_release_driver(dev[i++]); + + if (notifier->unbind) + notifier->unbind(notifier, sd, sd->asdl.asd); + } + + mutex_unlock(&list_lock); + + while (i--) { + struct device *d = dev[i]; + + if (d && device_attach(d) < 0) { + const char *name = "(none)"; + int lock = device_trylock(d); + + if (lock && d->driver) + name = d->driver->name; + dev_err(d, "Failed to re-probe to %s\n", name); + if (lock) + device_unlock(d); + } + put_device(d); + } + /* + * Don't care about the waiting list, it is initialised and populated + * upon notifier registration. + */ +} +EXPORT_SYMBOL(v4l2_async_notifier_unregister); + +int v4l2_async_register_subdev(struct v4l2_subdev *sd) +{ + struct v4l2_async_subdev_list *asdl = &sd->asdl; + struct v4l2_async_notifier *notifier; + + mutex_lock(&list_lock); + + INIT_LIST_HEAD(&asdl->list); + + list_for_each_entry(notifier, ¬ifier_list, list) { + struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, asdl); + if (asd) { + int ret = v4l2_async_test_notify(notifier, asdl, asd); + mutex_unlock(&list_lock); + return ret; + } + } + + /* None matched, wait for hot-plugging */ + list_add(&asdl->list, &subdev_list); + + mutex_unlock(&list_lock); + + return 0; +} +EXPORT_SYMBOL(v4l2_async_register_subdev); + +void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) +{ + struct v4l2_async_subdev_list *asdl = &sd->asdl; + struct v4l2_async_notifier *notifier = asdl->notifier; + + if (!asdl->asd) { + if (!list_empty(&asdl->list)) + v4l2_async_cleanup(asdl); + return; + } + + mutex_lock(&list_lock); + + list_add(&asdl->asd->list, ¬ifier->waiting); + + v4l2_async_cleanup(asdl); + + if (notifier->unbind) + notifier->unbind(notifier, sd, sd->asdl.asd); + + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(v4l2_async_unregister_subdev); diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h new file mode 100644 index 000000000000..c3ec6ac75f7e --- /dev/null +++ b/include/media/v4l2-async.h @@ -0,0 +1,105 @@ +/* + * V4L2 asynchronous subdevice registration API + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef V4L2_ASYNC_H +#define V4L2_ASYNC_H + +#include +#include + +struct device; +struct v4l2_device; +struct v4l2_subdev; +struct v4l2_async_notifier; + +/* A random max subdevice number, used to allocate an array on stack */ +#define V4L2_MAX_SUBDEVS 128U + +enum v4l2_async_bus_type { + V4L2_ASYNC_BUS_CUSTOM, + V4L2_ASYNC_BUS_PLATFORM, + V4L2_ASYNC_BUS_I2C, +}; + +/** + * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * @bus_type: subdevice bus type to select the appropriate matching method + * @match: union of per-bus type matching data sets + * @list: used to link struct v4l2_async_subdev objects, waiting to be + * probed, to a notifier->waiting list + */ +struct v4l2_async_subdev { + enum v4l2_async_bus_type bus_type; + union { + struct { + const char *name; + } platform; + struct { + int adapter_id; + unsigned short address; + } i2c; + struct { + bool (*match)(struct device *, + struct v4l2_async_subdev *); + void *priv; + } custom; + } match; + + /* v4l2-async core private: not to be used by drivers */ + struct list_head list; +}; + +/** + * v4l2_async_subdev_list - provided by subdevices + * @list: links struct v4l2_async_subdev_list objects to a global list + * before probing, and onto notifier->done after probing + * @asd: pointer to respective struct v4l2_async_subdev + * @notifier: pointer to managing notifier + */ +struct v4l2_async_subdev_list { + struct list_head list; + struct v4l2_async_subdev *asd; + struct v4l2_async_notifier *notifier; +}; + +/** + * v4l2_async_notifier - v4l2_device notifier data + * @num_subdevs:number of subdevices + * @subdev: array of pointers to subdevice descriptors + * @v4l2_dev: pointer to struct v4l2_device + * @waiting: list of struct v4l2_async_subdev, waiting for their drivers + * @done: list of struct v4l2_async_subdev_list, already probed + * @list: member in a global list of notifiers + * @bound: a subdevice driver has successfully probed one of subdevices + * @complete: all subdevices have been probed successfully + * @unbind: a subdevice is leaving + */ +struct v4l2_async_notifier { + unsigned int num_subdevs; + struct v4l2_async_subdev **subdev; + struct v4l2_device *v4l2_dev; + struct list_head waiting; + struct list_head done; + struct list_head list; + int (*bound)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); + int (*complete)(struct v4l2_async_notifier *notifier); + void (*unbind)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); +}; + +int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, + struct v4l2_async_notifier *notifier); +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); +int v4l2_async_register_subdev(struct v4l2_subdev *sd); +void v4l2_async_unregister_subdev(struct v4l2_subdev *sd); +#endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 5fbb266405f9..3250cc5e7925 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -585,8 +586,15 @@ struct v4l2_subdev { struct video_device *devnode; /* pointer to the physical device, if any */ struct device *dev; + struct v4l2_async_subdev_list asdl; }; +static inline struct v4l2_subdev *v4l2_async_to_subdev( + struct v4l2_async_subdev_list *asdl) +{ + return container_of(asdl, struct v4l2_subdev, asdl); +} + #define media_entity_to_v4l2_subdev(ent) \ container_of(ent, struct v4l2_subdev, entity) #define vdev_to_v4l2_subdev(vdev) \ -- GitLab From 9aea470b399d797e88be08985c489855759c6c60 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 21 Dec 2012 13:01:55 -0300 Subject: [PATCH 1676/2900] [media] soc-camera: switch I2C subdevice drivers to use v4l2-clk Instead of centrally enabling and disabling subdevice master clocks in soc-camera core, let subdevice drivers do that themselves, using the V4L2 clock API and soc-camera convenience wrappers. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/imx074.c | 18 +- drivers/media/i2c/soc_camera/mt9m001.c | 17 +- drivers/media/i2c/soc_camera/mt9m111.c | 20 ++- drivers/media/i2c/soc_camera/mt9t031.c | 19 +- drivers/media/i2c/soc_camera/mt9t112.c | 25 ++- drivers/media/i2c/soc_camera/mt9v022.c | 17 +- drivers/media/i2c/soc_camera/ov2640.c | 19 +- drivers/media/i2c/soc_camera/ov5642.c | 20 ++- drivers/media/i2c/soc_camera/ov6650.c | 17 +- drivers/media/i2c/soc_camera/ov772x.c | 15 +- drivers/media/i2c/soc_camera/ov9640.c | 17 +- drivers/media/i2c/soc_camera/ov9640.h | 1 + drivers/media/i2c/soc_camera/ov9740.c | 18 +- drivers/media/i2c/soc_camera/rj54n1cb0c.c | 17 +- drivers/media/i2c/soc_camera/tw9910.c | 24 ++- .../media/platform/soc_camera/soc_camera.c | 162 ++++++++++++++---- .../platform/soc_camera/soc_camera_platform.c | 2 +- include/media/soc_camera.h | 13 +- 18 files changed, 362 insertions(+), 79 deletions(-) diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index a315d4386c8e..2d8367891801 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -18,6 +18,7 @@ #include #include +#include #include /* IMX074 registers */ @@ -76,6 +77,7 @@ struct imx074_datafmt { struct imx074 { struct v4l2_subdev subdev; const struct imx074_datafmt *fmt; + struct v4l2_clk *clk; }; static const struct imx074_datafmt imx074_colour_fmts[] = { @@ -254,8 +256,9 @@ static int imx074_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct imx074 *priv = to_imx074(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int imx074_g_mbus_config(struct v4l2_subdev *sd, @@ -412,6 +415,7 @@ static int imx074_probe(struct i2c_client *client, struct imx074 *priv; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd) { dev_err(&client->dev, "IMX074: missing platform data!\n"); @@ -432,13 +436,23 @@ static int imx074_probe(struct i2c_client *client, priv->fmt = &imx074_colour_fmts[0]; - return imx074_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = imx074_video_probe(client); + if (ret < 0) + v4l2_clk_put(priv->clk); + + return ret; } static int imx074_remove(struct i2c_client *client) { struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct imx074 *priv = to_imx074(client); + v4l2_clk_put(priv->clk); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 3f1f437ee1c6..df97033fa6ef 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -93,6 +94,7 @@ struct mt9m001 { struct v4l2_ctrl *exposure; }; struct v4l2_rect rect; /* Sensor window */ + struct v4l2_clk *clk; const struct mt9m001_datafmt *fmt; const struct mt9m001_datafmt *fmts; int num_fmts; @@ -355,8 +357,9 @@ static int mt9m001_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, mt9m001->clk, on); } static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) @@ -681,9 +684,18 @@ static int mt9m001_probe(struct i2c_client *client, mt9m001->rect.width = MT9M001_MAX_WIDTH; mt9m001->rect.height = MT9M001_MAX_HEIGHT; + mt9m001->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9m001->clk)) { + ret = PTR_ERR(mt9m001->clk); + goto eclkget; + } + ret = mt9m001_video_probe(ssdd, client); - if (ret) + if (ret) { + v4l2_clk_put(mt9m001->clk); +eclkget: v4l2_ctrl_handler_free(&mt9m001->hdl); + } return ret; } @@ -693,6 +705,7 @@ static int mt9m001_remove(struct i2c_client *client) struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(mt9m001->clk); v4l2_device_unregister_subdev(&mt9m001->subdev); v4l2_ctrl_handler_free(&mt9m001->hdl); mt9m001_video_remove(ssdd); diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index 1aaca0423df7..de3605df47c5 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -206,6 +207,7 @@ struct mt9m111 { struct v4l2_ctrl *gain; struct mt9m111_context *ctx; struct v4l2_rect rect; /* cropping rectangle */ + struct v4l2_clk *clk; int width; /* output */ int height; /* sizes */ struct mutex power_lock; /* lock to protect power_count */ @@ -775,14 +777,14 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); int ret; - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk); if (ret < 0) return ret; ret = mt9m111_resume(mt9m111); if (ret < 0) { dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); } return ret; @@ -794,7 +796,7 @@ static void mt9m111_power_off(struct mt9m111 *mt9m111) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); mt9m111_suspend(mt9m111); - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); } static int mt9m111_s_power(struct v4l2_subdev *sd, int on) @@ -973,9 +975,18 @@ static int mt9m111_probe(struct i2c_client *client, mt9m111->lastpage = -1; mutex_init(&mt9m111->power_lock); + mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9m111->clk)) { + ret = PTR_ERR(mt9m111->clk); + goto eclkget; + } + ret = mt9m111_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9m111->clk); +eclkget: v4l2_ctrl_handler_free(&mt9m111->hdl); + } return ret; } @@ -984,6 +995,7 @@ static int mt9m111_remove(struct i2c_client *client) { struct mt9m111 *mt9m111 = to_mt9m111(client); + v4l2_clk_put(mt9m111->clk); v4l2_device_unregister_subdev(&mt9m111->subdev); v4l2_ctrl_handler_free(&mt9m111->hdl); diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index b3dfeb6d1037..47d18d0bafe7 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -75,6 +76,7 @@ struct mt9t031 { struct v4l2_ctrl *exposure; }; struct v4l2_rect rect; /* Sensor window */ + struct v4l2_clk *clk; u16 xskip; u16 yskip; unsigned int total_h; @@ -585,16 +587,17 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on) struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct video_device *vdev = soc_camera_i2c_to_vdev(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; if (on) { - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); if (ret < 0) return ret; vdev->dev.type = &mt9t031_dev_type; } else { vdev->dev.type = NULL; - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); } return 0; @@ -785,9 +788,18 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; + mt9t031->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9t031->clk)) { + ret = PTR_ERR(mt9t031->clk); + goto eclkget; + } + ret = mt9t031_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9t031->clk); +eclkget: v4l2_ctrl_handler_free(&mt9t031->hdl); + } return ret; } @@ -796,6 +808,7 @@ static int mt9t031_remove(struct i2c_client *client) { struct mt9t031 *mt9t031 = to_mt9t031(client); + v4l2_clk_put(mt9t031->clk); v4l2_device_unregister_subdev(&mt9t031->subdev); v4l2_ctrl_handler_free(&mt9t031->hdl); diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index 9b276dde5ac8..46f431a13782 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -27,6 +27,7 @@ #include #include +#include #include /* you can check PLL/clock info */ @@ -89,6 +90,7 @@ struct mt9t112_priv { struct mt9t112_camera_info *info; struct i2c_client *client; struct v4l2_rect frame; + struct v4l2_clk *clk; const struct mt9t112_format *format; int num_formats; u32 flags; @@ -768,8 +770,9 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9t112_priv *priv = to_mt9t112(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { @@ -1092,16 +1095,29 @@ static int mt9t112_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + ret = mt9t112_camera_probe(client); - if (ret) - return ret; /* Cannot fail: using the default supported pixel code */ - mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); + if (!ret) + mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); + else + v4l2_clk_put(priv->clk); return ret; } +static int mt9t112_remove(struct i2c_client *client) +{ + struct mt9t112_priv *priv = to_mt9t112(client); + + v4l2_clk_put(priv->clk); + return 0; +} + static const struct i2c_device_id mt9t112_id[] = { { "mt9t112", 0 }, { } @@ -1113,6 +1129,7 @@ static struct i2c_driver mt9t112_i2c_driver = { .name = "mt9t112", }, .probe = mt9t112_probe, + .remove = mt9t112_remove, .id_table = mt9t112_id, }; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 41ff4535eb0d..f9f95f815b1a 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -19,6 +19,7 @@ #include #include #include +#include #include /* @@ -153,6 +154,7 @@ struct mt9v022 { struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; struct v4l2_rect rect; /* Sensor window */ + struct v4l2_clk *clk; const struct mt9v022_datafmt *fmt; const struct mt9v022_datafmt *fmts; const struct mt9v02x_register *reg; @@ -498,8 +500,9 @@ static int mt9v022_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, mt9v022->clk, on); } static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) @@ -936,9 +939,18 @@ static int mt9v022_probe(struct i2c_client *client, mt9v022->rect.width = MT9V022_MAX_WIDTH; mt9v022->rect.height = MT9V022_MAX_HEIGHT; + mt9v022->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9v022->clk)) { + ret = PTR_ERR(mt9v022->clk); + goto eclkget; + } + ret = mt9v022_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9v022->clk); +eclkget: v4l2_ctrl_handler_free(&mt9v022->hdl); + } return ret; } @@ -948,6 +960,7 @@ static int mt9v022_remove(struct i2c_client *client) struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(mt9v022->clk); v4l2_device_unregister_subdev(&mt9v022->subdev); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index 7961cba6880a..6c6b1c3b45e3 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -302,6 +303,7 @@ struct ov2640_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; enum v4l2_mbus_pixelcode cfmt_code; + struct v4l2_clk *clk; const struct ov2640_win_size *win; }; @@ -758,8 +760,9 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov2640_priv *priv = to_ov2640(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } /* Select the nearest higher resolution for capture */ @@ -1097,11 +1100,20 @@ static int ov2640_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov2640_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); - else + } else { dev_info(&adapter->dev, "OV2640 Probed\n"); + } return ret; } @@ -1110,6 +1122,7 @@ static int ov2640_remove(struct i2c_client *client) { struct ov2640_priv *priv = to_ov2640(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index c93a157d1d93..0a5c5d4fedd6 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -24,6 +24,7 @@ #include #include +#include #include /* OV5642 registers */ @@ -609,6 +610,7 @@ struct ov5642 { struct v4l2_subdev subdev; const struct ov5642_datafmt *fmt; struct v4l2_rect crop_rect; + struct v4l2_clk *clk; /* blanking information */ int total_width; @@ -917,12 +919,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov5642 *priv = to_ov5642(client); int ret; if (!on) - return soc_camera_power_off(&client->dev, ssdd); + return soc_camera_power_off(&client->dev, ssdd, priv->clk); - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); if (ret < 0) return ret; @@ -1002,6 +1005,7 @@ static int ov5642_probe(struct i2c_client *client, { struct ov5642 *priv; struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd) { dev_err(&client->dev, "OV5642: missing platform data!\n"); @@ -1023,13 +1027,23 @@ static int ov5642_probe(struct i2c_client *client, priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH; priv->total_height = BLANKING_MIN_HEIGHT; - return ov5642_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = ov5642_video_probe(client); + if (ret < 0) + v4l2_clk_put(priv->clk); + + return ret; } static int ov5642_remove(struct i2c_client *client) { struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov5642 *priv = to_ov5642(client); + v4l2_clk_put(priv->clk); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index d2869d87d3b1..ab01598ec83f 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -32,6 +32,7 @@ #include #include +#include #include /* Register definitions */ @@ -195,6 +196,7 @@ struct ov6650 { struct v4l2_ctrl *blue; struct v4l2_ctrl *red; }; + struct v4l2_clk *clk; bool half_scale; /* scale down output by 2 */ struct v4l2_rect rect; /* sensor cropping window */ unsigned long pclk_limit; /* from host */ @@ -425,8 +427,9 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov6650 *priv = to_ov6650(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) @@ -1013,9 +1016,18 @@ static int ov6650_probe(struct i2c_client *client, priv->code = V4L2_MBUS_FMT_YUYV8_2X8; priv->colorspace = V4L2_COLORSPACE_JPEG; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov6650_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -1024,6 +1036,7 @@ static int ov6650_remove(struct i2c_client *client) { struct ov6650 *priv = to_ov6650(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index b2f623603986..7f2b3c8926af 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -395,6 +396,7 @@ struct ov772x_win_size { struct ov772x_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; struct ov772x_camera_info *info; const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; @@ -655,8 +657,9 @@ static int ov772x_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov772x_priv *priv = to_ov772x(sd); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) @@ -1072,13 +1075,22 @@ static int ov772x_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov772x_video_probe(priv); if (ret < 0) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); } else { priv->cfmt = &ov772x_cfmts[0]; priv->win = &ov772x_win_sizes[0]; } + return ret; } @@ -1086,6 +1098,7 @@ static int ov772x_remove(struct i2c_client *client) { struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 7d1f10f301d3..e968c3fdbd9e 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -324,8 +325,9 @@ static int ov9640_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } /* select nearest higher resolution for capture */ @@ -700,10 +702,18 @@ static int ov9640_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; - ret = ov9640_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } - if (ret) + ret = ov9640_video_probe(client); + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -713,6 +723,7 @@ static int ov9640_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov9640_priv *priv = to_ov9640_sensor(sd); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov9640.h b/drivers/media/i2c/soc_camera/ov9640.h index 6b33a972c83c..65d13ff17536 100644 --- a/drivers/media/i2c/soc_camera/ov9640.h +++ b/drivers/media/i2c/soc_camera/ov9640.h @@ -199,6 +199,7 @@ struct ov9640_reg { struct ov9640_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; int model; int revision; diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 0bc21a643c08..ea76863dfdb4 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -17,6 +17,7 @@ #include #include +#include #include #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) @@ -195,6 +196,7 @@ struct ov9740_reg { struct ov9740_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; u16 model; u8 revision; @@ -778,7 +780,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) int ret; if (on) { - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); if (ret < 0) return ret; @@ -792,7 +794,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) priv->current_enable = true; } - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, priv->clk); } return 0; @@ -958,9 +960,18 @@ static int ov9740_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov9740_video_probe(client); - if (ret < 0) + if (ret < 0) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -969,6 +980,7 @@ static int ov9740_remove(struct i2c_client *client) { struct ov9740_priv *priv = i2c_get_clientdata(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index 81b515c2fb36..7e6d97847874 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -150,6 +151,7 @@ struct rj54n1_clock_div { struct rj54n1 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; struct rj54n1_clock_div clk_div; const struct rj54n1_datafmt *fmt; struct v4l2_rect rect; /* Sensor window */ @@ -1158,8 +1160,9 @@ static int rj54n1_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct rj54n1 *rj54n1 = to_rj54n1(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, rj54n1->clk, on); } static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) @@ -1355,9 +1358,18 @@ static int rj54n1_probe(struct i2c_client *client, rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); + rj54n1->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(rj54n1->clk)) { + ret = PTR_ERR(rj54n1->clk); + goto eclkget; + } + ret = rj54n1_video_probe(client, rj54n1_priv); - if (ret < 0) + if (ret < 0) { + v4l2_clk_put(rj54n1->clk); +eclkget: v4l2_ctrl_handler_free(&rj54n1->hdl); + } return ret; } @@ -1367,6 +1379,7 @@ static int rj54n1_remove(struct i2c_client *client) struct rj54n1 *rj54n1 = to_rj54n1(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(rj54n1->clk); v4l2_device_unregister_subdev(&rj54n1->subdev); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index b15e1d8194da..ab54628d9411 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -27,6 +27,7 @@ #include #include +#include #include #define GET_ID(val) ((val & 0xF8) >> 3) @@ -227,6 +228,7 @@ struct tw9910_scale_ctrl { struct tw9910_priv { struct v4l2_subdev subdev; + struct v4l2_clk *clk; struct tw9910_video_info *info; const struct tw9910_scale_ctrl *scale; v4l2_std_id norm; @@ -558,8 +560,9 @@ static int tw9910_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct tw9910_priv *priv = to_tw9910(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) @@ -899,6 +902,7 @@ static int tw9910_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd || !ssdd->drv_priv) { dev_err(&client->dev, "TW9910: missing platform data!\n"); @@ -922,7 +926,22 @@ static int tw9910_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); - return tw9910_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = tw9910_video_probe(client); + if (ret < 0) + v4l2_clk_put(priv->clk); + + return ret; +} + +static int tw9910_remove(struct i2c_client *client) +{ + struct tw9910_priv *priv = to_tw9910(client); + v4l2_clk_put(priv->clk); + return 0; } static const struct i2c_device_id tw9910_id[] = { @@ -936,6 +955,7 @@ static struct i2c_driver tw9910_i2c_driver = { .name = "tw9910", }, .probe = tw9910_probe, + .remove = tw9910_remove, .id_table = tw9910_id, }; diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index fa8a728b7a5d..fe3930e882e1 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -50,13 +51,19 @@ static LIST_HEAD(hosts); static LIST_HEAD(devices); static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ -int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) +int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk) { - int ret = regulator_bulk_enable(ssdd->num_regulators, + int ret = clk ? v4l2_clk_enable(clk) : 0; + if (ret < 0) { + dev_err(dev, "Cannot enable clock\n"); + return ret; + } + ret = regulator_bulk_enable(ssdd->num_regulators, ssdd->regulators); if (ret < 0) { dev_err(dev, "Cannot enable regulators\n"); - return ret; + goto eregenable;; } if (ssdd->power) { @@ -64,16 +71,25 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) if (ret < 0) { dev_err(dev, "Platform failed to power-on the camera.\n"); - regulator_bulk_disable(ssdd->num_regulators, - ssdd->regulators); + goto epwron; } } + return 0; + +epwron: + regulator_bulk_disable(ssdd->num_regulators, + ssdd->regulators); +eregenable: + if (clk) + v4l2_clk_disable(clk); + return ret; } EXPORT_SYMBOL(soc_camera_power_on); -int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd) +int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk) { int ret = 0; int err; @@ -94,6 +110,9 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd ret = ret ? : err; } + if (clk) + v4l2_clk_disable(clk); + return ret; } EXPORT_SYMBOL(soc_camera_power_off); @@ -512,9 +531,11 @@ static int soc_camera_add_device(struct soc_camera_device *icd) if (ici->icd) return -EBUSY; - ret = ici->ops->clock_start(ici); - if (ret < 0) - return ret; + if (!icd->clk) { + ret = ici->ops->clock_start(ici); + if (ret < 0) + return ret; + } if (ici->ops->add) { ret = ici->ops->add(icd); @@ -527,7 +548,8 @@ static int soc_camera_add_device(struct soc_camera_device *icd) return 0; eadd: - ici->ops->clock_stop(ici); + if (!icd->clk) + ici->ops->clock_stop(ici); return ret; } @@ -540,7 +562,8 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) if (ici->ops->remove) ici->ops->remove(icd); - ici->ops->clock_stop(ici); + if (!icd->clk) + ici->ops->clock_stop(ici); ici->icd = NULL; } @@ -1094,6 +1117,57 @@ static void scan_add_host(struct soc_camera_host *ici) mutex_unlock(&list_lock); } +/* + * It is invalid to call v4l2_clk_enable() after a successful probing + * asynchronously outside of V4L2 operations, i.e. with .host_lock not held. + */ +static int soc_camera_clk_enable(struct v4l2_clk *clk) +{ + struct soc_camera_device *icd = clk->priv; + struct soc_camera_host *ici; + + if (!icd || !icd->parent) + return -ENODEV; + + ici = to_soc_camera_host(icd->parent); + + if (!try_module_get(ici->ops->owner)) + return -ENODEV; + + /* + * If a different client is currently being probed, the host will tell + * you to go + */ + return ici->ops->clock_start(ici); +} + +static void soc_camera_clk_disable(struct v4l2_clk *clk) +{ + struct soc_camera_device *icd = clk->priv; + struct soc_camera_host *ici; + + if (!icd || !icd->parent) + return; + + ici = to_soc_camera_host(icd->parent); + + ici->ops->clock_stop(ici); + + module_put(ici->ops->owner); +} + +/* + * Eventually, it would be more logical to make the respective host the clock + * owner, but then we would have to copy this struct for each ici. Besides, it + * would introduce the circular dependency problem, unless we port all client + * drivers to release the clock, when not in use. + */ +static const struct v4l2_clk_ops soc_camera_clk_ops = { + .owner = THIS_MODULE, + .enable = soc_camera_clk_enable, + .disable = soc_camera_clk_disable, +}; + #ifdef CONFIG_I2C_BOARDINFO static int soc_camera_init_i2c(struct soc_camera_device *icd, struct soc_camera_desc *sdesc) @@ -1103,19 +1177,32 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, struct soc_camera_host_desc *shd = &sdesc->host_desc; struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); struct v4l2_subdev *subdev; + char clk_name[V4L2_SUBDEV_NAME_SIZE]; + int ret; if (!adap) { dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", shd->i2c_adapter_id); - goto ei2cga; + return -ENODEV; } shd->board_info->platform_data = &sdesc->subdev_desc; + snprintf(clk_name, sizeof(clk_name), "%d-%04x", + shd->i2c_adapter_id, shd->board_info->addr); + + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + if (IS_ERR(icd->clk)) { + ret = PTR_ERR(icd->clk); + goto eclkreg; + } + subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, shd->board_info, NULL); - if (!subdev) + if (!subdev) { + ret = -ENODEV; goto ei2cnd; + } client = v4l2_get_subdevdata(subdev); @@ -1124,9 +1211,11 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, return 0; ei2cnd: + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; +eclkreg: i2c_put_adapter(adap); -ei2cga: - return -ENODEV; + return ret; } static void soc_camera_free_i2c(struct soc_camera_device *icd) @@ -1139,6 +1228,8 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd) v4l2_device_unregister_subdev(i2c_get_clientdata(client)); i2c_unregister_device(client); i2c_put_adapter(adap); + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; } #else #define soc_camera_init_i2c(icd, sdesc) (-ENODEV) @@ -1176,26 +1267,31 @@ static int soc_camera_probe(struct soc_camera_device *icd) if (ssdd->reset) ssdd->reset(icd->pdev); - mutex_lock(&ici->host_lock); - ret = ici->ops->clock_start(ici); - mutex_unlock(&ici->host_lock); - if (ret < 0) - goto eadd; - /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) goto evdc; + /* + * ..._video_start() will create a device node, video_register_device() + * itself is protected against concurrent open() calls, but we also have + * to protect our data also during client probing. + */ + mutex_lock(&ici->host_lock); + /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ if (shd->board_info) { ret = soc_camera_init_i2c(icd, sdesc); if (ret < 0) - goto eadddev; + goto eadd; } else if (!shd->add_device || !shd->del_device) { ret = -EINVAL; - goto eadddev; + goto eadd; } else { + ret = ici->ops->clock_start(ici); + if (ret < 0) + goto eadd; + if (shd->module_name) ret = request_module(shd->module_name); @@ -1231,13 +1327,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->field = V4L2_FIELD_ANY; - /* - * ..._video_start() will create a device node, video_register_device() - * itself is protected against concurrent open() calls, but we also have - * to protect our data. - */ - mutex_lock(&ici->host_lock); - ret = soc_camera_video_start(icd); if (ret < 0) goto evidstart; @@ -1250,14 +1339,14 @@ static int soc_camera_probe(struct soc_camera_device *icd) icd->field = mf.field; } - ici->ops->clock_stop(ici); + if (!shd->board_info) + ici->ops->clock_stop(ici); mutex_unlock(&ici->host_lock); return 0; evidstart: - mutex_unlock(&ici->host_lock); soc_camera_free_user_formats(icd); eiufmt: ectrl: @@ -1266,16 +1355,15 @@ static int soc_camera_probe(struct soc_camera_device *icd) } else { shd->del_device(icd); module_put(control->driver->owner); - } enodrv: eadddev: + ici->ops->clock_stop(ici); + } +eadd: video_device_release(icd->vdev); icd->vdev = NULL; -evdc: - mutex_lock(&ici->host_lock); - ici->ops->clock_stop(ici); mutex_unlock(&ici->host_lock); -eadd: +evdc: v4l2_ctrl_handler_free(&icd->ctrl_handler); return ret; } diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index bdf909d2ec35..ceaddfb85e49 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -54,7 +54,7 @@ static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on) { struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); - return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, on); + return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, NULL, on); } static struct v4l2_subdev_core_ops platform_subdev_core_ops = { diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index dfa24df960df..f582323fafb7 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -49,6 +49,7 @@ struct soc_camera_device { /* soc_camera.c private count. Only accessed with .host_lock held */ int use_count; struct file *streamer; /* stream owner */ + struct v4l2_clk *clk; union { struct videobuf_queue vb_vidq; struct vb2_queue vb2_vidq; @@ -325,14 +326,16 @@ static inline void soc_camera_limit_side(int *start, int *length, unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, const struct v4l2_mbus_config *cfg); -int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd); -int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd); +int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk); +int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk); static inline int soc_camera_set_power(struct device *dev, - struct soc_camera_subdev_desc *ssdd, bool on) + struct soc_camera_subdev_desc *ssdd, struct v4l2_clk *clk, bool on) { - return on ? soc_camera_power_on(dev, ssdd) - : soc_camera_power_off(dev, ssdd); + return on ? soc_camera_power_on(dev, ssdd, clk) + : soc_camera_power_off(dev, ssdd, clk); } /* This is only temporary here - until v4l2-subdev begins to link to video_device */ -- GitLab From e09da11da49c6fd625be52d8b60bbbbe225a9db6 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 26 Dec 2012 12:44:11 -0300 Subject: [PATCH 1677/2900] [media] soc-camera: add V4L2-async support Add support for asynchronous subdevice probing, using the v4l2-async API. The legacy synchronous mode is still supported too, which allows to gradually update drivers and platforms. The selected approach adds a notifier for each struct soc_camera_device instance, i.e. for each video device node, even when there are multiple such instances registered with a single soc-camera host simultaneously. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/soc_camera.c | 527 +++++++++++++++--- include/media/soc_camera.h | 23 +- 2 files changed, 464 insertions(+), 86 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index fe3930e882e1..2e47b5127d4b 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -21,22 +21,23 @@ #include #include #include -#include #include +#include #include +#include #include #include -#include #include #include +#include +#include #include #include #include #include #include #include -#include /* Default to VGA resolution */ #define DEFAULT_WIDTH 640 @@ -47,23 +48,39 @@ (icd)->vb_vidq.streaming : \ vb2_is_streaming(&(icd)->vb2_vidq)) +#define MAP_MAX_NUM 32 +static DECLARE_BITMAP(device_map, MAP_MAX_NUM); static LIST_HEAD(hosts); static LIST_HEAD(devices); -static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ +/* + * Protects lists and bitmaps of hosts and devices. + * Lock nesting: Ok to take ->host_lock under list_lock. + */ +static DEFINE_MUTEX(list_lock); + +struct soc_camera_async_client { + struct v4l2_async_subdev *sensor; + struct v4l2_async_notifier notifier; + struct platform_device *pdev; + struct list_head list; /* needed for clean up */ +}; + +static int soc_camera_video_start(struct soc_camera_device *icd); +static int video_dev_create(struct soc_camera_device *icd); int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, struct v4l2_clk *clk) { int ret = clk ? v4l2_clk_enable(clk) : 0; if (ret < 0) { - dev_err(dev, "Cannot enable clock\n"); + dev_err(dev, "Cannot enable clock: %d\n", ret); return ret; } ret = regulator_bulk_enable(ssdd->num_regulators, ssdd->regulators); if (ret < 0) { dev_err(dev, "Cannot enable regulators\n"); - goto eregenable;; + goto eregenable; } if (ssdd->power) { @@ -117,6 +134,14 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd } EXPORT_SYMBOL(soc_camera_power_off); +int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) +{ + + return devm_regulator_bulk_get(dev, ssdd->num_regulators, + ssdd->regulators); +} +EXPORT_SYMBOL(soc_camera_power_init); + static int __soc_camera_power_on(struct soc_camera_device *icd) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -532,7 +557,9 @@ static int soc_camera_add_device(struct soc_camera_device *icd) return -EBUSY; if (!icd->clk) { + mutex_lock(&ici->clk_lock); ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); if (ret < 0) return ret; } @@ -548,8 +575,11 @@ static int soc_camera_add_device(struct soc_camera_device *icd) return 0; eadd: - if (!icd->clk) + if (!icd->clk) { + mutex_lock(&ici->clk_lock); ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); + } return ret; } @@ -562,8 +592,11 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) if (ici->ops->remove) ici->ops->remove(icd); - if (!icd->clk) + if (!icd->clk) { + mutex_lock(&ici->clk_lock); ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); + } ici->icd = NULL; } @@ -672,8 +705,8 @@ static int soc_camera_open(struct file *file) return 0; /* - * First four errors are entered with the .host_lock held - * and use_count == 1 + * All errors are entered with the .host_lock held, first four also + * with use_count == 1 */ einitvb: esfmt: @@ -1098,7 +1131,8 @@ static int soc_camera_s_parm(struct file *file, void *fh, return -ENOIOCTLCMD; } -static int soc_camera_probe(struct soc_camera_device *icd); +static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd); /* So far this function cannot fail */ static void scan_add_host(struct soc_camera_host *ici) @@ -1107,12 +1141,20 @@ static void scan_add_host(struct soc_camera_host *ici) mutex_lock(&list_lock); - list_for_each_entry(icd, &devices, list) { + list_for_each_entry(icd, &devices, list) if (icd->iface == ici->nr) { + struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); + struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; + + /* The camera could have been already on, try to reset */ + if (ssdd->reset) + ssdd->reset(icd->pdev); + icd->parent = ici->v4l2_dev.dev; - soc_camera_probe(icd); + + /* Ignore errors */ + soc_camera_probe(ici, icd); } - } mutex_unlock(&list_lock); } @@ -1125,6 +1167,7 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk) { struct soc_camera_device *icd = clk->priv; struct soc_camera_host *ici; + int ret; if (!icd || !icd->parent) return -ENODEV; @@ -1138,7 +1181,10 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk) * If a different client is currently being probed, the host will tell * you to go */ - return ici->ops->clock_start(ici); + mutex_lock(&ici->clk_lock); + ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); + return ret; } static void soc_camera_clk_disable(struct v4l2_clk *clk) @@ -1151,7 +1197,9 @@ static void soc_camera_clk_disable(struct v4l2_clk *clk) ici = to_soc_camera_host(icd->parent); + mutex_lock(&ici->clk_lock); ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); module_put(ici->ops->owner); } @@ -1168,18 +1216,117 @@ static const struct v4l2_clk_ops soc_camera_clk_ops = { .disable = soc_camera_clk_disable, }; +static int soc_camera_dyn_pdev(struct soc_camera_desc *sdesc, + struct soc_camera_async_client *sasc) +{ + struct platform_device *pdev; + int ret, i; + + mutex_lock(&list_lock); + i = find_first_zero_bit(device_map, MAP_MAX_NUM); + if (i < MAP_MAX_NUM) + set_bit(i, device_map); + mutex_unlock(&list_lock); + if (i >= MAP_MAX_NUM) + return -ENOMEM; + + pdev = platform_device_alloc("soc-camera-pdrv", i); + if (!pdev) + return -ENOMEM; + + ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc)); + if (ret < 0) { + platform_device_put(pdev); + return ret; + } + + sasc->pdev = pdev; + + return 0; +} + +static struct soc_camera_device *soc_camera_add_pdev(struct soc_camera_async_client *sasc) +{ + struct platform_device *pdev = sasc->pdev; + int ret; + + ret = platform_device_add(pdev); + if (ret < 0 || !pdev->dev.driver) + return NULL; + + return platform_get_drvdata(pdev); +} + +/* Locking: called with .host_lock held */ +static int soc_camera_probe_finish(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_mbus_framefmt mf; + int ret; + + sd->grp_id = soc_camera_grp_id(icd); + v4l2_set_subdev_hostdata(sd, icd); + + ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); + if (ret < 0) + return ret; + + ret = soc_camera_add_device(icd); + if (ret < 0) { + dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); + return ret; + } + + /* At this point client .probe() should have run already */ + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eusrfmt; + + icd->field = V4L2_FIELD_ANY; + + ret = soc_camera_video_start(icd); + if (ret < 0) + goto evidstart; + + /* Try to improve our guess of a reasonable window format */ + if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { + icd->user_width = mf.width; + icd->user_height = mf.height; + icd->colorspace = mf.colorspace; + icd->field = mf.field; + } + soc_camera_remove_device(icd); + + return 0; + +evidstart: + soc_camera_free_user_formats(icd); +eusrfmt: + soc_camera_remove_device(icd); + + return ret; +} + #ifdef CONFIG_I2C_BOARDINFO -static int soc_camera_init_i2c(struct soc_camera_device *icd, +static int soc_camera_i2c_init(struct soc_camera_device *icd, struct soc_camera_desc *sdesc) { struct i2c_client *client; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct soc_camera_host *ici; struct soc_camera_host_desc *shd = &sdesc->host_desc; - struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); + struct i2c_adapter *adap; struct v4l2_subdev *subdev; char clk_name[V4L2_SUBDEV_NAME_SIZE]; int ret; + /* First find out how we link the main client */ + if (icd->sasc) { + /* Async non-OF probing handled by the subdevice list */ + return -EPROBE_DEFER; + } + + ici = to_soc_camera_host(icd->parent); + adap = i2c_get_adapter(shd->i2c_adapter_id); if (!adap) { dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", shd->i2c_adapter_id); @@ -1212,42 +1359,202 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, return 0; ei2cnd: v4l2_clk_unregister(icd->clk); - icd->clk = NULL; eclkreg: + icd->clk = NULL; i2c_put_adapter(adap); return ret; } -static void soc_camera_free_i2c(struct soc_camera_device *icd) +static void soc_camera_i2c_free(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct i2c_adapter *adap = client->adapter; + struct i2c_adapter *adap; icd->control = NULL; + if (icd->sasc) + return; + + adap = client->adapter; v4l2_device_unregister_subdev(i2c_get_clientdata(client)); i2c_unregister_device(client); i2c_put_adapter(adap); v4l2_clk_unregister(icd->clk); icd->clk = NULL; } + +/* + * V4L2 asynchronous notifier callbacks. They are all called under a v4l2-async + * internal global mutex, therefore cannot race against other asynchronous + * events. Until notifier->complete() (soc_camera_async_complete()) is called, + * the video device node is not registered and no V4L fops can occur. Unloading + * of the host driver also calls a v4l2-async function, so also there we're + * protected. + */ +static int soc_camera_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (asd == sasc->sensor && !WARN_ON(icd->control)) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + + /* + * Only now we get subdevice-specific information like + * regulators, flags, callbacks, etc. + */ + if (client) { + struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); + struct soc_camera_subdev_desc *ssdd = + soc_camera_i2c_to_desc(client); + if (ssdd) { + memcpy(&sdesc->subdev_desc, ssdd, + sizeof(sdesc->subdev_desc)); + if (ssdd->reset) + ssdd->reset(icd->pdev); + } + + icd->control = &client->dev; + } + } + + return 0; +} + +static void soc_camera_async_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (icd->clk) { + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; + } +} + +static int soc_camera_async_complete(struct v4l2_async_notifier *notifier) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (to_soc_camera_control(icd)) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + + mutex_lock(&list_lock); + ret = soc_camera_probe(ici, icd); + mutex_unlock(&list_lock); + if (ret < 0) + return ret; + } + + return 0; +} + +static int scan_async_group(struct soc_camera_host *ici, + struct v4l2_async_subdev **asd, int size) +{ + struct soc_camera_async_subdev *sasd; + struct soc_camera_async_client *sasc; + struct soc_camera_device *icd; + struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; + char clk_name[V4L2_SUBDEV_NAME_SIZE]; + int ret, i; + + /* First look for a sensor */ + for (i = 0; i < size; i++) { + sasd = container_of(asd[i], struct soc_camera_async_subdev, asd); + if (sasd->role == SOCAM_SUBDEV_DATA_SOURCE) + break; + } + + if (i == size || asd[i]->bus_type != V4L2_ASYNC_BUS_I2C) { + /* All useless */ + dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); + return -ENODEV; + } + + /* Or shall this be managed by the soc-camera device? */ + sasc = devm_kzalloc(ici->v4l2_dev.dev, sizeof(*sasc), GFP_KERNEL); + if (!sasc) + return -ENOMEM; + + /* HACK: just need a != NULL */ + sdesc.host_desc.board_info = ERR_PTR(-ENODATA); + + ret = soc_camera_dyn_pdev(&sdesc, sasc); + if (ret < 0) + return ret; + + sasc->sensor = &sasd->asd; + + icd = soc_camera_add_pdev(sasc); + if (!icd) { + platform_device_put(sasc->pdev); + return -ENOMEM; + } + + sasc->notifier.subdev = asd; + sasc->notifier.num_subdevs = size; + sasc->notifier.bound = soc_camera_async_bound; + sasc->notifier.unbind = soc_camera_async_unbind; + sasc->notifier.complete = soc_camera_async_complete; + + icd->sasc = sasc; + icd->parent = ici->v4l2_dev.dev; + + snprintf(clk_name, sizeof(clk_name), "%d-%04x", + sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address); + + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + if (IS_ERR(icd->clk)) { + ret = PTR_ERR(icd->clk); + goto eclkreg; + } + + ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); + if (!ret) + return 0; + + v4l2_clk_unregister(icd->clk); +eclkreg: + icd->clk = NULL; + platform_device_unregister(sasc->pdev); + dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); + + return ret; +} + +static void scan_async_host(struct soc_camera_host *ici) +{ + struct v4l2_async_subdev **asd; + int j; + + for (j = 0, asd = ici->asd; ici->asd_sizes[j]; j++) { + scan_async_group(ici, asd, ici->asd_sizes[j]); + asd += ici->asd_sizes[j]; + } +} #else -#define soc_camera_init_i2c(icd, sdesc) (-ENODEV) -#define soc_camera_free_i2c(icd) do {} while (0) +#define soc_camera_i2c_init(icd, sdesc) (-ENODEV) +#define soc_camera_i2c_free(icd) do {} while (0) +#define scan_async_host(ici) do {} while (0) #endif -static int soc_camera_video_start(struct soc_camera_device *icd); -static int video_dev_create(struct soc_camera_device *icd); /* Called during host-driver probe */ -static int soc_camera_probe(struct soc_camera_device *icd) +static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); struct soc_camera_host_desc *shd = &sdesc->host_desc; - struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; struct device *control = NULL; - struct v4l2_subdev *sd; - struct v4l2_mbus_framefmt mf; int ret; dev_info(icd->pdev, "Probing %s\n", dev_name(icd->pdev)); @@ -1263,10 +1570,6 @@ static int soc_camera_probe(struct soc_camera_device *icd) if (ret < 0) return ret; - /* The camera could have been already on, try to reset */ - if (ssdd->reset) - ssdd->reset(icd->pdev); - /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) @@ -1277,18 +1580,19 @@ static int soc_camera_probe(struct soc_camera_device *icd) * itself is protected against concurrent open() calls, but we also have * to protect our data also during client probing. */ - mutex_lock(&ici->host_lock); /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ if (shd->board_info) { - ret = soc_camera_init_i2c(icd, sdesc); - if (ret < 0) + ret = soc_camera_i2c_init(icd, sdesc); + if (ret < 0 && ret != -EPROBE_DEFER) goto eadd; } else if (!shd->add_device || !shd->del_device) { ret = -EINVAL; goto eadd; } else { + mutex_lock(&ici->clk_lock); ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); if (ret < 0) goto eadd; @@ -1312,57 +1616,33 @@ static int soc_camera_probe(struct soc_camera_device *icd) } } - sd = soc_camera_to_subdev(icd); - sd->grp_id = soc_camera_grp_id(icd); - v4l2_set_subdev_hostdata(sd, icd); - - ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); - if (ret < 0) - goto ectrl; - - /* At this point client .probe() should have run already */ - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; - - icd->field = V4L2_FIELD_ANY; - - ret = soc_camera_video_start(icd); - if (ret < 0) - goto evidstart; - - /* Try to improve our guess of a reasonable window format */ - if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { - icd->user_width = mf.width; - icd->user_height = mf.height; - icd->colorspace = mf.colorspace; - icd->field = mf.field; - } - - if (!shd->board_info) - ici->ops->clock_stop(ici); - + mutex_lock(&ici->host_lock); + ret = soc_camera_probe_finish(icd); mutex_unlock(&ici->host_lock); + if (ret < 0) + goto efinish; return 0; -evidstart: - soc_camera_free_user_formats(icd); -eiufmt: -ectrl: +efinish: if (shd->board_info) { - soc_camera_free_i2c(icd); + soc_camera_i2c_free(icd); } else { shd->del_device(icd); module_put(control->driver->owner); enodrv: eadddev: + mutex_lock(&ici->clk_lock); ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); } eadd: video_device_release(icd->vdev); icd->vdev = NULL; - mutex_unlock(&ici->host_lock); + if (icd->vdev) { + video_device_release(icd->vdev); + icd->vdev = NULL; + } evdc: v4l2_ctrl_handler_free(&icd->ctrl_handler); return ret; @@ -1370,15 +1650,15 @@ static int soc_camera_probe(struct soc_camera_device *icd) /* * This is called on device_unregister, which only means we have to disconnect - * from the host, but not remove ourselves from the device list + * from the host, but not remove ourselves from the device list. With + * asynchronous client probing this can also be called without + * soc_camera_probe_finish() having run. Careful with clean up. */ static int soc_camera_remove(struct soc_camera_device *icd) { struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); struct video_device *vdev = icd->vdev; - BUG_ON(!icd->parent); - v4l2_ctrl_handler_free(&icd->ctrl_handler); if (vdev) { video_unregister_device(vdev); @@ -1386,15 +1666,27 @@ static int soc_camera_remove(struct soc_camera_device *icd) } if (sdesc->host_desc.board_info) { - soc_camera_free_i2c(icd); + soc_camera_i2c_free(icd); } else { - struct device_driver *drv = to_soc_camera_control(icd)->driver; + struct device *dev = to_soc_camera_control(icd); + struct device_driver *drv = dev ? dev->driver : NULL; if (drv) { sdesc->host_desc.del_device(icd); module_put(drv->owner); } } - soc_camera_free_user_formats(icd); + + if (icd->num_user_formats) + soc_camera_free_user_formats(icd); + + if (icd->clk) { + /* For the synchronous case */ + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; + } + + if (icd->sasc) + platform_device_unregister(icd->sasc->pdev); return 0; } @@ -1505,7 +1797,18 @@ int soc_camera_host_register(struct soc_camera_host *ici) mutex_unlock(&list_lock); mutex_init(&ici->host_lock); - scan_add_host(ici); + mutex_init(&ici->clk_lock); + + if (ici->asd_sizes) + /* + * No OF, host with a list of subdevices. Don't try to mix + * modes by initialising some groups statically and some + * dynamically! + */ + scan_async_host(ici); + else + /* Legacy: static platform devices from board data */ + scan_add_host(ici); return 0; @@ -1518,13 +1821,30 @@ EXPORT_SYMBOL(soc_camera_host_register); /* Unregister all clients! */ void soc_camera_host_unregister(struct soc_camera_host *ici) { - struct soc_camera_device *icd; + struct soc_camera_device *icd, *tmp; + struct soc_camera_async_client *sasc; + LIST_HEAD(notifiers); mutex_lock(&list_lock); - list_del(&ici->list); list_for_each_entry(icd, &devices, list) - if (icd->iface == ici->nr && to_soc_camera_control(icd)) + if (icd->iface == ici->nr && icd->sasc) { + /* as long as we hold the device, sasc won't be freed */ + get_device(icd->pdev); + list_add(&icd->sasc->list, ¬ifiers); + } + mutex_unlock(&list_lock); + + list_for_each_entry(sasc, ¬ifiers, list) { + /* Must call unlocked to avoid AB-BA dead-lock */ + v4l2_async_notifier_unregister(&sasc->notifier); + put_device(&sasc->pdev->dev); + } + + mutex_lock(&list_lock); + + list_for_each_entry_safe(icd, tmp, &devices, list) + if (icd->iface == ici->nr) soc_camera_remove(icd); mutex_unlock(&list_lock); @@ -1539,6 +1859,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) struct soc_camera_device *ix; int num = -1, i; + mutex_lock(&list_lock); for (i = 0; i < 256 && num < 0; i++) { num = i; /* Check if this index is available on this interface */ @@ -1550,18 +1871,34 @@ static int soc_camera_device_register(struct soc_camera_device *icd) } } - if (num < 0) + if (num < 0) { /* * ok, we have 256 cameras on this host... * man, stay reasonable... */ + mutex_unlock(&list_lock); return -ENOMEM; + } icd->devnum = num; icd->use_count = 0; icd->host_priv = NULL; + /* + * Dynamically allocated devices set the bit earlier, but it doesn't hurt setting + * it again + */ + i = to_platform_device(icd->pdev)->id; + if (i < 0) + /* One static (legacy) soc-camera platform device */ + i = 0; + if (i >= MAP_MAX_NUM) { + mutex_unlock(&list_lock); + return -EBUSY; + } + set_bit(i, device_map); list_add_tail(&icd->list, &devices); + mutex_unlock(&list_lock); return 0; } @@ -1655,6 +1992,12 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) if (!icd) return -ENOMEM; + /* + * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below + * regulator allocation is a dummy. They will be really requested later + * in soc_camera_async_bind(). Also note, that in that case regulators + * are attached to the I2C device and not to the camera platform device. + */ ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, ssdd->regulators); if (ret < 0) @@ -1679,11 +2022,25 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) static int soc_camera_pdrv_remove(struct platform_device *pdev) { struct soc_camera_device *icd = platform_get_drvdata(pdev); + int i; if (!icd) return -EINVAL; - list_del(&icd->list); + i = pdev->id; + if (i < 0) + i = 0; + + /* + * In synchronous mode with static platform devices this is called in a + * loop from drivers/base/dd.c::driver_detach(), no parallel execution, + * no need to lock. In asynchronous case the caller - + * soc_camera_host_unregister() - already holds the lock + */ + if (test_bit(i, device_map)) { + clear_bit(i, device_map); + list_del(&icd->list); + } return 0; } diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index f582323fafb7..906ed98c6e95 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -19,11 +19,13 @@ #include #include #include +#include #include #include struct file; struct soc_camera_desc; +struct soc_camera_async_client; struct soc_camera_device { struct list_head list; /* list of all registered devices */ @@ -50,6 +52,9 @@ struct soc_camera_device { int use_count; struct file *streamer; /* stream owner */ struct v4l2_clk *clk; + /* Asynchronous subdevice management */ + struct soc_camera_async_client *sasc; + /* video buffer queue */ union { struct videobuf_queue vb_vidq; struct vb2_queue vb2_vidq; @@ -59,16 +64,30 @@ struct soc_camera_device { /* Host supports programmable stride */ #define SOCAM_HOST_CAP_STRIDE (1 << 0) +enum soc_camera_subdev_role { + SOCAM_SUBDEV_DATA_SOURCE = 1, + SOCAM_SUBDEV_DATA_SINK, + SOCAM_SUBDEV_DATA_PROCESSOR, +}; + +struct soc_camera_async_subdev { + struct v4l2_async_subdev asd; + enum soc_camera_subdev_role role; +}; + struct soc_camera_host { struct v4l2_device v4l2_dev; struct list_head list; - struct mutex host_lock; /* Protect pipeline modifications */ + struct mutex host_lock; /* Main synchronisation lock */ + struct mutex clk_lock; /* Protect pipeline modifications */ unsigned char nr; /* Host number */ u32 capabilities; struct soc_camera_device *icd; /* Currently attached client */ void *priv; const char *drv_name; struct soc_camera_host_ops *ops; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + int *asd_sizes; /* 0-terminated array of asd group sizes */ }; struct soc_camera_host_ops { @@ -161,6 +180,7 @@ struct soc_camera_host_desc { }; /* + * Platform data for "soc-camera-pdrv" * This MUST be kept binary-identical to struct soc_camera_link below, until * it is completely replaced by this one, after which we can split it into its * two components. @@ -326,6 +346,7 @@ static inline void soc_camera_limit_side(int *start, int *length, unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, const struct v4l2_mbus_config *cfg); +int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd); int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, struct v4l2_clk *clk); int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, -- GitLab From 676d2d4f08ccdfab45867aaf1edeeb923b45bdc1 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 3 Jan 2013 15:06:35 -0300 Subject: [PATCH 1678/2900] [media] sh_mobile_ceu_camera: add asynchronous subdevice probing support Use the v4l2-async API to support asynchronous subdevice probing, including the CSI2 subdevice. Synchronous probing is still supported too. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../soc_camera/sh_mobile_ceu_camera.c | 134 ++++++++++----- .../platform/soc_camera/sh_mobile_csi2.c | 153 ++++++++++-------- include/media/sh_mobile_ceu.h | 2 + include/media/sh_mobile_csi2.h | 2 +- 4 files changed, 190 insertions(+), 101 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index b0f0995fc80b..d1b410b75cc1 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -96,6 +97,10 @@ struct sh_mobile_ceu_buffer { struct sh_mobile_ceu_dev { struct soc_camera_host ici; + /* Asynchronous CSI2 linking */ + struct v4l2_async_subdev *csi2_asd; + struct v4l2_subdev *csi2_sd; + /* Synchronous probing compatibility */ struct platform_device *csi2_pdev; unsigned int irq; @@ -185,7 +190,6 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) udelay(1); } - if (2 != success) { dev_warn(pcdev->ici.v4l2_dev.dev, "soft reset time out\n"); return -EIO; @@ -534,16 +538,29 @@ static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev) { struct v4l2_subdev *sd; - if (!pcdev->csi2_pdev) - return NULL; + if (pcdev->csi2_sd) + return pcdev->csi2_sd; - v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) - if (&pcdev->csi2_pdev->dev == v4l2_get_subdevdata(sd)) - return sd; + if (pcdev->csi2_asd) { + char name[] = "sh-mobile-csi2"; + v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) + if (!strncmp(name, sd->name, sizeof(name) - 1)) { + pcdev->csi2_sd = sd; + return sd; + } + } return NULL; } +static struct v4l2_subdev *csi2_subdev(struct sh_mobile_ceu_dev *pcdev, + struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = pcdev->csi2_sd; + + return sd && sd->grp_id == soc_camera_grp_id(icd) ? sd : NULL; +} + static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); @@ -564,12 +581,12 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver * has not found this soc-camera device among its clients */ - if (ret == -ENODEV && csi2_sd) + if (csi2_sd && ret == -ENODEV) csi2_sd->grp_id = 0; dev_info(icd->parent, - "SuperH Mobile CEU driver attached to camera %d\n", - icd->devnum); + "SuperH Mobile CEU%s driver attached to camera %d\n", + csi2_sd && csi2_sd->grp_id ? "/CSI-2" : "", icd->devnum); return 0; } @@ -585,8 +602,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) icd->devnum); v4l2_subdev_call(csi2_sd, core, s_power, 0); - if (csi2_sd) - csi2_sd->grp_id = 0; } /* Called with .host_lock held */ @@ -708,7 +723,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) } /* CSI2 special configuration */ - if (pcdev->csi2_pdev) { + if (csi2_subdev(pcdev, icd)) { in_width = ((in_width - 2) * 2); left_offset *= 2; } @@ -765,13 +780,7 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev, struct soc_camera_device *icd) { - if (pcdev->csi2_pdev) { - struct v4l2_subdev *csi2_sd = find_csi2(pcdev); - if (csi2_sd && csi2_sd->grp_id == soc_camera_grp_id(icd)) - return csi2_sd; - } - - return soc_camera_to_subdev(icd); + return csi2_subdev(pcdev, icd) ? : soc_camera_to_subdev(icd); } #define CEU_BUS_FLAGS (V4L2_MBUS_MASTER | \ @@ -875,7 +884,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; - if (pcdev->csi2_pdev) /* CSI2 mode */ + if (csi2_subdev(pcdev, icd)) /* CSI2 mode */ value |= 3 << 12; else if (pcdev->is_16bit) value |= 1 << 12; @@ -1054,7 +1063,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int return 0; } - if (!pcdev->pdata || !pcdev->pdata->csi2) { + if (!csi2_subdev(pcdev, icd)) { /* Are there any restrictions in the CSI-2 case? */ ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) @@ -2084,7 +2093,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; unsigned int irq; - int err = 0; + int err, i; struct bus_wait wait = { .completion = COMPLETION_INITIALIZER_ONSTACK(wait.completion), .notifier.notifier_call = bus_notify, @@ -2188,31 +2197,60 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_free_clk; } - err = soc_camera_host_register(&pcdev->ici); - if (err) - goto exit_free_ctx; + if (pcdev->pdata && pcdev->pdata->asd_sizes) { + struct v4l2_async_subdev **asd; + char name[] = "sh-mobile-csi2"; + int j; + + /* + * CSI2 interfacing: several groups can use CSI2, pick up the + * first one + */ + asd = pcdev->pdata->asd; + for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { + for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { + dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", + __func__, i, (*asd)->bus_type); + if ((*asd)->bus_type == V4L2_ASYNC_BUS_PLATFORM && + !strncmp(name, (*asd)->match.platform.name, + sizeof(name) - 1)) { + pcdev->csi2_asd = *asd; + break; + } + } + if (pcdev->csi2_asd) + break; + } + + pcdev->ici.asd = pcdev->pdata->asd; + pcdev->ici.asd_sizes = pcdev->pdata->asd_sizes; + } - /* CSI2 interfacing */ + /* Legacy CSI2 interfacing */ csi2 = pcdev->pdata ? pcdev->pdata->csi2 : NULL; if (csi2) { + /* + * TODO: remove this once all users are converted to + * asynchronous CSI2 probing. If it has to be kept, csi2 + * platform device resources have to be added, using + * platform_device_add_resources() + */ struct platform_device *csi2_pdev = platform_device_alloc("sh-mobile-csi2", csi2->id); struct sh_csi2_pdata *csi2_pdata = csi2->platform_data; if (!csi2_pdev) { err = -ENOMEM; - goto exit_host_unregister; + goto exit_free_ctx; } pcdev->csi2_pdev = csi2_pdev; - err = platform_device_add_data(csi2_pdev, csi2_pdata, sizeof(*csi2_pdata)); + err = platform_device_add_data(csi2_pdev, csi2_pdata, + sizeof(*csi2_pdata)); if (err < 0) goto exit_pdev_put; - csi2_pdata = csi2_pdev->dev.platform_data; - csi2_pdata->v4l2_dev = &pcdev->ici.v4l2_dev; - csi2_pdev->resource = csi2->resource; csi2_pdev->num_resources = csi2->num_resources; @@ -2254,17 +2292,38 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) err = -ENODEV; goto exit_pdev_unregister; } + + pcdev->csi2_sd = platform_get_drvdata(csi2_pdev); + } + + err = soc_camera_host_register(&pcdev->ici); + if (err) + goto exit_csi2_unregister; + + if (csi2) { + err = v4l2_device_register_subdev(&pcdev->ici.v4l2_dev, + pcdev->csi2_sd); + dev_dbg(&pdev->dev, "%s(): ret(register_subdev) = %d\n", + __func__, err); + if (err < 0) + goto exit_host_unregister; + /* v4l2_device_register_subdev() took a reference too */ + module_put(pcdev->csi2_sd->owner); } return 0; -exit_pdev_unregister: - platform_device_del(pcdev->csi2_pdev); -exit_pdev_put: - pcdev->csi2_pdev->resource = NULL; - platform_device_put(pcdev->csi2_pdev); exit_host_unregister: soc_camera_host_unregister(&pcdev->ici); +exit_csi2_unregister: + if (csi2) { + module_put(pcdev->csi2_pdev->dev.driver->owner); +exit_pdev_unregister: + platform_device_del(pcdev->csi2_pdev); +exit_pdev_put: + pcdev->csi2_pdev->resource = NULL; + platform_device_put(pcdev->csi2_pdev); + } exit_free_ctx: vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); exit_free_clk: @@ -2324,6 +2383,7 @@ MODULE_DEVICE_TABLE(of, sh_mobile_ceu_of_match); static struct platform_driver sh_mobile_ceu_driver = { .driver = { .name = "sh_mobile_ceu", + .owner = THIS_MODULE, .pm = &sh_mobile_ceu_dev_pm_ops, .of_match_table = sh_mobile_ceu_of_match, }, @@ -2349,5 +2409,5 @@ module_exit(sh_mobile_ceu_exit); MODULE_DESCRIPTION("SuperH Mobile CEU driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.6"); +MODULE_VERSION("0.1.0"); MODULE_ALIAS("platform:sh_mobile_ceu"); diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index 13a1f8f13f65..05dd21a35d63 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c @@ -36,7 +36,6 @@ struct sh_csi2 { struct v4l2_subdev subdev; - struct list_head list; unsigned int irq; unsigned long mipi_flags; void __iomem *base; @@ -44,6 +43,8 @@ struct sh_csi2 { struct sh_csi2_client_config *client; }; +static void sh_csi2_hwinit(struct sh_csi2 *priv); + static int sh_csi2_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { @@ -132,10 +133,58 @@ static int sh_csi2_s_fmt(struct v4l2_subdev *sd, static int sh_csi2_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | - V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | - V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH; - cfg->type = V4L2_MBUS_PARALLEL; + struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); + + if (!priv->mipi_flags) { + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); + struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); + struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; + unsigned long common_flags, csi2_flags; + struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,}; + int ret; + + /* Check if we can support this camera */ + csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | + V4L2_MBUS_CSI2_1_LANE; + + switch (pdata->type) { + case SH_CSI2C: + if (priv->client->lanes != 1) + csi2_flags |= V4L2_MBUS_CSI2_2_LANE; + break; + case SH_CSI2I: + switch (priv->client->lanes) { + default: + csi2_flags |= V4L2_MBUS_CSI2_4_LANE; + case 3: + csi2_flags |= V4L2_MBUS_CSI2_3_LANE; + case 2: + csi2_flags |= V4L2_MBUS_CSI2_2_LANE; + } + } + + ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &client_cfg); + if (ret == -ENOIOCTLCMD) + common_flags = csi2_flags; + else if (!ret) + common_flags = soc_mbus_config_compatible(&client_cfg, + csi2_flags); + else + common_flags = 0; + + if (!common_flags) + return -EINVAL; + + /* All good: camera MIPI configuration supported */ + priv->mipi_flags = common_flags; + } + + if (cfg) { + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | + V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_PARALLEL; + } return 0; } @@ -146,8 +195,17 @@ static int sh_csi2_s_mbus_config(struct v4l2_subdev *sd, struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); - struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2, - .flags = priv->mipi_flags}; + struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,}; + int ret = sh_csi2_g_mbus_config(sd, NULL); + + if (ret < 0) + return ret; + + pm_runtime_get_sync(&priv->pdev->dev); + + sh_csi2_hwinit(priv); + + client_cfg.flags = priv->mipi_flags; return v4l2_subdev_call(client_sd, video, s_mbus_config, &client_cfg); } @@ -202,19 +260,19 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv) static int sh_csi2_client_connect(struct sh_csi2 *priv) { - struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; - struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev); - struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); struct device *dev = v4l2_get_subdevdata(&priv->subdev); - struct v4l2_mbus_config cfg; - unsigned long common_flags, csi2_flags; - int i, ret; + struct sh_csi2_pdata *pdata = dev->platform_data; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev); + int i; if (priv->client) return -EBUSY; for (i = 0; i < pdata->num_clients; i++) - if (&pdata->clients[i].pdev->dev == icd->pdev) + if ((pdata->clients[i].pdev && + &pdata->clients[i].pdev->dev == icd->pdev) || + (icd->control && + strcmp(pdata->clients[i].name, dev_name(icd->control)))) break; dev_dbg(dev, "%s(%p): found #%d\n", __func__, dev, i); @@ -222,46 +280,8 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv) if (i == pdata->num_clients) return -ENODEV; - /* Check if we can support this camera */ - csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_1_LANE; - - switch (pdata->type) { - case SH_CSI2C: - if (pdata->clients[i].lanes != 1) - csi2_flags |= V4L2_MBUS_CSI2_2_LANE; - break; - case SH_CSI2I: - switch (pdata->clients[i].lanes) { - default: - csi2_flags |= V4L2_MBUS_CSI2_4_LANE; - case 3: - csi2_flags |= V4L2_MBUS_CSI2_3_LANE; - case 2: - csi2_flags |= V4L2_MBUS_CSI2_2_LANE; - } - } - - cfg.type = V4L2_MBUS_CSI2; - ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &cfg); - if (ret == -ENOIOCTLCMD) - common_flags = csi2_flags; - else if (!ret) - common_flags = soc_mbus_config_compatible(&cfg, - csi2_flags); - else - common_flags = 0; - - if (!common_flags) - return -EINVAL; - - /* All good: camera MIPI configuration supported */ - priv->mipi_flags = common_flags; priv->client = pdata->clients + i; - pm_runtime_get_sync(dev); - - sh_csi2_hwinit(priv); - return 0; } @@ -304,11 +324,18 @@ static int sh_csi2_probe(struct platform_device *pdev) /* Platform data specify the PHY, lanes, ECC, CRC */ struct sh_csi2_pdata *pdata = pdev->dev.platform_data; + if (!pdata) + return -EINVAL; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL); + if (!priv) + return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); /* Interrupt unused so far */ irq = platform_get_irq(pdev, 0); - if (!res || (int)irq <= 0 || !pdata) { + if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n"); return -ENODEV; } @@ -319,10 +346,6 @@ static int sh_csi2_probe(struct platform_device *pdev) return -EINVAL; } - priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL); - if (!priv) - return -ENOMEM; - priv->irq = irq; priv->base = devm_ioremap_resource(&pdev->dev, res); @@ -330,15 +353,17 @@ static int sh_csi2_probe(struct platform_device *pdev) return PTR_ERR(priv->base); priv->pdev = pdev; - platform_set_drvdata(pdev, priv); + priv->subdev.owner = THIS_MODULE; + priv->subdev.dev = &pdev->dev; + platform_set_drvdata(pdev, &priv->subdev); v4l2_subdev_init(&priv->subdev, &sh_csi2_subdev_ops); v4l2_set_subdevdata(&priv->subdev, &pdev->dev); snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s.mipi-csi", - dev_name(pdata->v4l2_dev->dev)); - ret = v4l2_device_register_subdev(pdata->v4l2_dev, &priv->subdev); - dev_dbg(&pdev->dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret); + dev_name(&pdev->dev)); + + ret = v4l2_async_register_subdev(&priv->subdev); if (ret < 0) return ret; @@ -351,9 +376,11 @@ static int sh_csi2_probe(struct platform_device *pdev) static int sh_csi2_remove(struct platform_device *pdev) { - struct sh_csi2 *priv = platform_get_drvdata(pdev); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + struct sh_csi2 *priv = container_of(subdev, struct sh_csi2, subdev); - v4l2_device_unregister_subdev(&priv->subdev); + v4l2_async_unregister_subdev(&priv->subdev); + v4l2_device_unregister_subdev(subdev); pm_runtime_disable(&pdev->dev); return 0; diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index 6fdb6adf6b2b..8937241e5f37 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h @@ -22,6 +22,8 @@ struct sh_mobile_ceu_info { int max_width; int max_height; struct sh_mobile_ceu_companion *csi2; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + int *asd_sizes; /* 0-terminated array pf asd group sizes */ }; #endif /* __ASM_SH_MOBILE_CEU_H__ */ diff --git a/include/media/sh_mobile_csi2.h b/include/media/sh_mobile_csi2.h index c586c4f7f16b..14030db51f13 100644 --- a/include/media/sh_mobile_csi2.h +++ b/include/media/sh_mobile_csi2.h @@ -33,6 +33,7 @@ struct sh_csi2_client_config { unsigned char lanes; /* bitmask[3:0] */ unsigned char channel; /* 0..3 */ struct platform_device *pdev; /* client platform device */ + const char *name; /* async matching: client name */ }; struct v4l2_device; @@ -42,7 +43,6 @@ struct sh_csi2_pdata { unsigned int flags; struct sh_csi2_client_config *clients; int num_clients; - struct v4l2_device *v4l2_dev; }; #endif -- GitLab From ee17608d6aa04a86e253a9130d6c6d00892f132b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 26 Dec 2012 13:13:46 -0300 Subject: [PATCH 1679/2900] [media] imx074: support asynchronous probing Both synchronous and asynchronous imx074 subdevice probing is supported by this patch. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/imx074.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index 2d8367891801..1d384a371b41 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -437,13 +438,24 @@ static int imx074_probe(struct i2c_client *client, priv->fmt = &imx074_colour_fmts[0]; priv->clk = v4l2_clk_get(&client->dev, "mclk"); - if (IS_ERR(priv->clk)) - return PTR_ERR(priv->clk); + if (IS_ERR(priv->clk)) { + dev_info(&client->dev, "Error %ld getting clock\n", PTR_ERR(priv->clk)); + return -EPROBE_DEFER; + } + + ret = soc_camera_power_init(&client->dev, ssdd); + if (ret < 0) + goto epwrinit; ret = imx074_video_probe(client); if (ret < 0) - v4l2_clk_put(priv->clk); + goto eprobe; + return v4l2_async_register_subdev(&priv->subdev); + +epwrinit: +eprobe: + v4l2_clk_put(priv->clk); return ret; } @@ -452,7 +464,9 @@ static int imx074_remove(struct i2c_client *client) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct imx074 *priv = to_imx074(client); + v4l2_async_unregister_subdev(&priv->subdev); v4l2_clk_put(priv->clk); + if (ssdd->free_bus) ssdd->free_bus(ssdd); -- GitLab From 8469ba39a6b77917e8879680aed17229bf72f263 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Thu, 30 May 2013 18:25:25 -0400 Subject: [PATCH 1680/2900] IB/qib: Add DCA support This patch adds DCA cache warming for systems that support DCA. The code uses cpu affinity notification to react to an affinity change from a user mode program like irqbalance and (re-)program the chip accordingly. This notification avoids reading the current cpu on every interrupt. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn [ Add Kconfig dependency on SMP && GENERIC_HARDIRQS to avoid failure to build due to undefined struct irq_affinity_notify. - Roland ] Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/Kconfig | 8 + drivers/infiniband/hw/qib/qib.h | 13 + drivers/infiniband/hw/qib/qib_iba6120.c | 10 + drivers/infiniband/hw/qib/qib_iba7220.c | 10 + drivers/infiniband/hw/qib/qib_iba7322.c | 334 +++++++++++++++++++++++- drivers/infiniband/hw/qib/qib_init.c | 41 +++ 6 files changed, 404 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/hw/qib/Kconfig b/drivers/infiniband/hw/qib/Kconfig index 1e603a375069..d03ca4c1ff25 100644 --- a/drivers/infiniband/hw/qib/Kconfig +++ b/drivers/infiniband/hw/qib/Kconfig @@ -5,3 +5,11 @@ config INFINIBAND_QIB This is a low-level driver for Intel PCIe QLE InfiniBand host channel adapters. This driver does not support the Intel HyperTransport card (model QHT7140). + +config INFINIBAND_QIB_DCA + bool "QIB DCA support" + depends on INFINIBAND_QIB && DCA && SMP && GENERIC_HARDIRQS && !(INFINIBAND_QIB=y && DCA=m) + default y + ---help--- + Setting this enables DCA support on some Intel chip sets + with the iba7322 HCA. diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 4d11575c2010..cecbd43f9212 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -428,9 +428,19 @@ struct qib_verbs_txreq { #define ACTIVITY_TIMER 5 #define MAX_NAME_SIZE 64 + +#ifdef CONFIG_INFINIBAND_QIB_DCA +struct qib_irq_notify; +#endif + struct qib_msix_entry { struct msix_entry msix; void *arg; +#ifdef CONFIG_INFINIBAND_QIB_DCA + int dca; + int rcv; + struct qib_irq_notify *notifier; +#endif char name[MAX_NAME_SIZE]; cpumask_var_t mask; }; @@ -828,6 +838,9 @@ struct qib_devdata { struct qib_ctxtdata *); void (*f_writescratch)(struct qib_devdata *, u32); int (*f_tempsense_rd)(struct qib_devdata *, int regnum); +#ifdef CONFIG_INFINIBAND_QIB_DCA + int (*f_notify_dca)(struct qib_devdata *, unsigned long event); +#endif char *boardname; /* human readable board info */ diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 0232ae56b1fa..84e593d6007b 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -3464,6 +3464,13 @@ static int qib_6120_tempsense_rd(struct qib_devdata *dd, int regnum) return -ENXIO; } +#ifdef CONFIG_INFINIBAND_QIB_DCA +static int qib_6120_notify_dca(struct qib_devdata *dd, unsigned long event) +{ + return 0; +} +#endif + /* Dummy function, as 6120 boards never disable EEPROM Write */ static int qib_6120_eeprom_wen(struct qib_devdata *dd, int wen) { @@ -3539,6 +3546,9 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, dd->f_xgxs_reset = qib_6120_xgxs_reset; dd->f_writescratch = writescratch; dd->f_tempsense_rd = qib_6120_tempsense_rd; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dd->f_notify_dca = qib_6120_notify_dca; +#endif /* * Do remaining pcie setup and save pcie values in dd. * Any error printing is already done by the init code. diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 64d0ecb90cdc..454c2e7668fe 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -4513,6 +4513,13 @@ static int qib_7220_tempsense_rd(struct qib_devdata *dd, int regnum) return ret; } +#ifdef CONFIG_INFINIBAND_QIB_DCA +static int qib_7220_notify_dca(struct qib_devdata *dd, unsigned long event) +{ + return 0; +} +#endif + /* Dummy function, as 7220 boards never disable EEPROM Write */ static int qib_7220_eeprom_wen(struct qib_devdata *dd, int wen) { @@ -4587,6 +4594,9 @@ struct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev, dd->f_xgxs_reset = qib_7220_xgxs_reset; dd->f_writescratch = writescratch; dd->f_tempsense_rd = qib_7220_tempsense_rd; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dd->f_notify_dca = qib_7220_notify_dca; +#endif /* * Do remaining pcie setup and save pcie values in dd. * Any error printing is already done by the init code. diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 3f6b21e9dc11..46ffea033be0 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef CONFIG_INFINIBAND_QIB_DCA +#include +#endif #include "qib.h" #include "qib_7322_regs.h" @@ -519,6 +522,14 @@ static const u8 qib_7322_physportstate[0x20] = { [0x17] = IB_PHYSPORTSTATE_CFG_TRAIN }; +#ifdef CONFIG_INFINIBAND_QIB_DCA +struct qib_irq_notify { + int rcv; + void *arg; + struct irq_affinity_notify notify; +}; +#endif + struct qib_chip_specific { u64 __iomem *cregbase; u64 *cntrs; @@ -546,6 +557,12 @@ struct qib_chip_specific { u32 lastbuf_for_pio; u32 stay_in_freeze; u32 recovery_ports_initted; +#ifdef CONFIG_INFINIBAND_QIB_DCA + u32 dca_ctrl; + int rhdr_cpu[18]; + int sdma_cpu[2]; + u64 dca_rcvhdr_ctrl[5]; /* B, C, D, E, F */ +#endif struct qib_msix_entry *msix_entries; unsigned long *sendchkenable; unsigned long *sendgrhchk; @@ -642,28 +659,76 @@ static struct { irq_handler_t handler; int lsb; int port; /* 0 if not port-specific, else port # */ + int dca; } irq_table[] = { - { "", qib_7322intr, -1, 0 }, + { "", qib_7322intr, -1, 0, 0 }, { " (buf avail)", qib_7322bufavail, - SYM_LSB(IntStatus, SendBufAvail), 0 }, + SYM_LSB(IntStatus, SendBufAvail), 0, 0}, { " (sdma 0)", sdma_intr, - SYM_LSB(IntStatus, SDmaInt_0), 1 }, + SYM_LSB(IntStatus, SDmaInt_0), 1, 1 }, { " (sdma 1)", sdma_intr, - SYM_LSB(IntStatus, SDmaInt_1), 2 }, + SYM_LSB(IntStatus, SDmaInt_1), 2, 1 }, { " (sdmaI 0)", sdma_idle_intr, - SYM_LSB(IntStatus, SDmaIdleInt_0), 1 }, + SYM_LSB(IntStatus, SDmaIdleInt_0), 1, 1}, { " (sdmaI 1)", sdma_idle_intr, - SYM_LSB(IntStatus, SDmaIdleInt_1), 2 }, + SYM_LSB(IntStatus, SDmaIdleInt_1), 2, 1}, { " (sdmaP 0)", sdma_progress_intr, - SYM_LSB(IntStatus, SDmaProgressInt_0), 1 }, + SYM_LSB(IntStatus, SDmaProgressInt_0), 1, 1 }, { " (sdmaP 1)", sdma_progress_intr, - SYM_LSB(IntStatus, SDmaProgressInt_1), 2 }, + SYM_LSB(IntStatus, SDmaProgressInt_1), 2, 1 }, { " (sdmaC 0)", sdma_cleanup_intr, - SYM_LSB(IntStatus, SDmaCleanupDone_0), 1 }, + SYM_LSB(IntStatus, SDmaCleanupDone_0), 1, 0 }, { " (sdmaC 1)", sdma_cleanup_intr, - SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 }, + SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 , 0}, }; +#ifdef CONFIG_INFINIBAND_QIB_DCA + +static const struct dca_reg_map { + int shadow_inx; + int lsb; + u64 mask; + u16 regno; +} dca_rcvhdr_reg_map[] = { + { 0, SYM_LSB(DCACtrlB, RcvHdrq0DCAOPH), + ~SYM_MASK(DCACtrlB, RcvHdrq0DCAOPH) , KREG_IDX(DCACtrlB) }, + { 0, SYM_LSB(DCACtrlB, RcvHdrq1DCAOPH), + ~SYM_MASK(DCACtrlB, RcvHdrq1DCAOPH) , KREG_IDX(DCACtrlB) }, + { 0, SYM_LSB(DCACtrlB, RcvHdrq2DCAOPH), + ~SYM_MASK(DCACtrlB, RcvHdrq2DCAOPH) , KREG_IDX(DCACtrlB) }, + { 0, SYM_LSB(DCACtrlB, RcvHdrq3DCAOPH), + ~SYM_MASK(DCACtrlB, RcvHdrq3DCAOPH) , KREG_IDX(DCACtrlB) }, + { 1, SYM_LSB(DCACtrlC, RcvHdrq4DCAOPH), + ~SYM_MASK(DCACtrlC, RcvHdrq4DCAOPH) , KREG_IDX(DCACtrlC) }, + { 1, SYM_LSB(DCACtrlC, RcvHdrq5DCAOPH), + ~SYM_MASK(DCACtrlC, RcvHdrq5DCAOPH) , KREG_IDX(DCACtrlC) }, + { 1, SYM_LSB(DCACtrlC, RcvHdrq6DCAOPH), + ~SYM_MASK(DCACtrlC, RcvHdrq6DCAOPH) , KREG_IDX(DCACtrlC) }, + { 1, SYM_LSB(DCACtrlC, RcvHdrq7DCAOPH), + ~SYM_MASK(DCACtrlC, RcvHdrq7DCAOPH) , KREG_IDX(DCACtrlC) }, + { 2, SYM_LSB(DCACtrlD, RcvHdrq8DCAOPH), + ~SYM_MASK(DCACtrlD, RcvHdrq8DCAOPH) , KREG_IDX(DCACtrlD) }, + { 2, SYM_LSB(DCACtrlD, RcvHdrq9DCAOPH), + ~SYM_MASK(DCACtrlD, RcvHdrq9DCAOPH) , KREG_IDX(DCACtrlD) }, + { 2, SYM_LSB(DCACtrlD, RcvHdrq10DCAOPH), + ~SYM_MASK(DCACtrlD, RcvHdrq10DCAOPH) , KREG_IDX(DCACtrlD) }, + { 2, SYM_LSB(DCACtrlD, RcvHdrq11DCAOPH), + ~SYM_MASK(DCACtrlD, RcvHdrq11DCAOPH) , KREG_IDX(DCACtrlD) }, + { 3, SYM_LSB(DCACtrlE, RcvHdrq12DCAOPH), + ~SYM_MASK(DCACtrlE, RcvHdrq12DCAOPH) , KREG_IDX(DCACtrlE) }, + { 3, SYM_LSB(DCACtrlE, RcvHdrq13DCAOPH), + ~SYM_MASK(DCACtrlE, RcvHdrq13DCAOPH) , KREG_IDX(DCACtrlE) }, + { 3, SYM_LSB(DCACtrlE, RcvHdrq14DCAOPH), + ~SYM_MASK(DCACtrlE, RcvHdrq14DCAOPH) , KREG_IDX(DCACtrlE) }, + { 3, SYM_LSB(DCACtrlE, RcvHdrq15DCAOPH), + ~SYM_MASK(DCACtrlE, RcvHdrq15DCAOPH) , KREG_IDX(DCACtrlE) }, + { 4, SYM_LSB(DCACtrlF, RcvHdrq16DCAOPH), + ~SYM_MASK(DCACtrlF, RcvHdrq16DCAOPH) , KREG_IDX(DCACtrlF) }, + { 4, SYM_LSB(DCACtrlF, RcvHdrq17DCAOPH), + ~SYM_MASK(DCACtrlF, RcvHdrq17DCAOPH) , KREG_IDX(DCACtrlF) }, +}; +#endif + /* ibcctrl bits */ #define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1 /* cycle through TS1/TS2 till OK */ @@ -686,6 +751,13 @@ static void write_7322_init_portregs(struct qib_pportdata *); static void setup_7322_link_recovery(struct qib_pportdata *, u32); static void check_7322_rxe_status(struct qib_pportdata *); static u32 __iomem *qib_7322_getsendbuf(struct qib_pportdata *, u64, u32 *); +#ifdef CONFIG_INFINIBAND_QIB_DCA +static void qib_setup_dca(struct qib_devdata *dd); +static void setup_dca_notifier(struct qib_devdata *dd, + struct qib_msix_entry *m); +static void reset_dca_notifier(struct qib_devdata *dd, + struct qib_msix_entry *m); +#endif /** * qib_read_ureg32 - read 32-bit virtualized per-context register @@ -2558,6 +2630,162 @@ static void qib_setup_7322_setextled(struct qib_pportdata *ppd, u32 on) qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink); } +#ifdef CONFIG_INFINIBAND_QIB_DCA + +static int qib_7322_notify_dca(struct qib_devdata *dd, unsigned long event) +{ + switch (event) { + case DCA_PROVIDER_ADD: + if (dd->flags & QIB_DCA_ENABLED) + break; + if (!dca_add_requester(&dd->pcidev->dev)) { + qib_devinfo(dd->pcidev, "DCA enabled\n"); + dd->flags |= QIB_DCA_ENABLED; + qib_setup_dca(dd); + } + break; + case DCA_PROVIDER_REMOVE: + if (dd->flags & QIB_DCA_ENABLED) { + dca_remove_requester(&dd->pcidev->dev); + dd->flags &= ~QIB_DCA_ENABLED; + dd->cspec->dca_ctrl = 0; + qib_write_kreg(dd, KREG_IDX(DCACtrlA), + dd->cspec->dca_ctrl); + } + break; + } + return 0; +} + +static void qib_update_rhdrq_dca(struct qib_ctxtdata *rcd, int cpu) +{ + struct qib_devdata *dd = rcd->dd; + struct qib_chip_specific *cspec = dd->cspec; + + if (!(dd->flags & QIB_DCA_ENABLED)) + return; + if (cspec->rhdr_cpu[rcd->ctxt] != cpu) { + const struct dca_reg_map *rmp; + + cspec->rhdr_cpu[rcd->ctxt] = cpu; + rmp = &dca_rcvhdr_reg_map[rcd->ctxt]; + cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] &= rmp->mask; + cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] |= + (u64) dca3_get_tag(&dd->pcidev->dev, cpu) << rmp->lsb; + qib_devinfo(dd->pcidev, + "Ctxt %d cpu %d dca %llx\n", rcd->ctxt, cpu, + (long long) cspec->dca_rcvhdr_ctrl[rmp->shadow_inx]); + qib_write_kreg(dd, rmp->regno, + cspec->dca_rcvhdr_ctrl[rmp->shadow_inx]); + cspec->dca_ctrl |= SYM_MASK(DCACtrlA, RcvHdrqDCAEnable); + qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl); + } +} + +static void qib_update_sdma_dca(struct qib_pportdata *ppd, int cpu) +{ + struct qib_devdata *dd = ppd->dd; + struct qib_chip_specific *cspec = dd->cspec; + unsigned pidx = ppd->port - 1; + + if (!(dd->flags & QIB_DCA_ENABLED)) + return; + if (cspec->sdma_cpu[pidx] != cpu) { + cspec->sdma_cpu[pidx] = cpu; + cspec->dca_rcvhdr_ctrl[4] &= ~(ppd->hw_pidx ? + SYM_MASK(DCACtrlF, SendDma1DCAOPH) : + SYM_MASK(DCACtrlF, SendDma0DCAOPH)); + cspec->dca_rcvhdr_ctrl[4] |= + (u64) dca3_get_tag(&dd->pcidev->dev, cpu) << + (ppd->hw_pidx ? + SYM_LSB(DCACtrlF, SendDma1DCAOPH) : + SYM_LSB(DCACtrlF, SendDma0DCAOPH)); + qib_devinfo(dd->pcidev, + "sdma %d cpu %d dca %llx\n", ppd->hw_pidx, cpu, + (long long) cspec->dca_rcvhdr_ctrl[4]); + qib_write_kreg(dd, KREG_IDX(DCACtrlF), + cspec->dca_rcvhdr_ctrl[4]); + cspec->dca_ctrl |= ppd->hw_pidx ? + SYM_MASK(DCACtrlA, SendDMAHead1DCAEnable) : + SYM_MASK(DCACtrlA, SendDMAHead0DCAEnable); + qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl); + } +} + +static void qib_setup_dca(struct qib_devdata *dd) +{ + struct qib_chip_specific *cspec = dd->cspec; + int i; + + for (i = 0; i < ARRAY_SIZE(cspec->rhdr_cpu); i++) + cspec->rhdr_cpu[i] = -1; + for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++) + cspec->sdma_cpu[i] = -1; + cspec->dca_rcvhdr_ctrl[0] = + (1ULL << SYM_LSB(DCACtrlB, RcvHdrq0DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlB, RcvHdrq1DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlB, RcvHdrq2DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlB, RcvHdrq3DCAXfrCnt)); + cspec->dca_rcvhdr_ctrl[1] = + (1ULL << SYM_LSB(DCACtrlC, RcvHdrq4DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlC, RcvHdrq5DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlC, RcvHdrq6DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlC, RcvHdrq7DCAXfrCnt)); + cspec->dca_rcvhdr_ctrl[2] = + (1ULL << SYM_LSB(DCACtrlD, RcvHdrq8DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlD, RcvHdrq9DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlD, RcvHdrq10DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlD, RcvHdrq11DCAXfrCnt)); + cspec->dca_rcvhdr_ctrl[3] = + (1ULL << SYM_LSB(DCACtrlE, RcvHdrq12DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlE, RcvHdrq13DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlE, RcvHdrq14DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlE, RcvHdrq15DCAXfrCnt)); + cspec->dca_rcvhdr_ctrl[4] = + (1ULL << SYM_LSB(DCACtrlF, RcvHdrq16DCAXfrCnt)) | + (1ULL << SYM_LSB(DCACtrlF, RcvHdrq17DCAXfrCnt)); + for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++) + qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i, + cspec->dca_rcvhdr_ctrl[i]); + for (i = 0; i < cspec->num_msix_entries; i++) + setup_dca_notifier(dd, &cspec->msix_entries[i]); +} + +static void qib_irq_notifier_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct qib_irq_notify *n = + container_of(notify, struct qib_irq_notify, notify); + int cpu = cpumask_first(mask); + + if (n->rcv) { + struct qib_ctxtdata *rcd = (struct qib_ctxtdata *)n->arg; + qib_update_rhdrq_dca(rcd, cpu); + } else { + struct qib_pportdata *ppd = (struct qib_pportdata *)n->arg; + qib_update_sdma_dca(ppd, cpu); + } +} + +static void qib_irq_notifier_release(struct kref *ref) +{ + struct qib_irq_notify *n = + container_of(ref, struct qib_irq_notify, notify.kref); + struct qib_devdata *dd; + + if (n->rcv) { + struct qib_ctxtdata *rcd = (struct qib_ctxtdata *)n->arg; + dd = rcd->dd; + } else { + struct qib_pportdata *ppd = (struct qib_pportdata *)n->arg; + dd = ppd->dd; + } + qib_devinfo(dd->pcidev, + "release on HCA notify 0x%p n 0x%p\n", ref, n); + kfree(n); +} +#endif + /* * Disable MSIx interrupt if enabled, call generic MSIx code * to cleanup, and clear pending MSIx interrupts. @@ -2575,6 +2803,9 @@ static void qib_7322_nomsix(struct qib_devdata *dd) dd->cspec->num_msix_entries = 0; for (i = 0; i < n; i++) { +#ifdef CONFIG_INFINIBAND_QIB_DCA + reset_dca_notifier(dd, &dd->cspec->msix_entries[i]); +#endif irq_set_affinity_hint( dd->cspec->msix_entries[i].msix.vector, NULL); free_cpumask_var(dd->cspec->msix_entries[i].mask); @@ -2602,6 +2833,15 @@ static void qib_setup_7322_cleanup(struct qib_devdata *dd) { int i; +#ifdef CONFIG_INFINIBAND_QIB_DCA + if (dd->flags & QIB_DCA_ENABLED) { + dca_remove_requester(&dd->pcidev->dev); + dd->flags &= ~QIB_DCA_ENABLED; + dd->cspec->dca_ctrl = 0; + qib_write_kreg(dd, KREG_IDX(DCACtrlA), dd->cspec->dca_ctrl); + } +#endif + qib_7322_free_irq(dd); kfree(dd->cspec->cntrs); kfree(dd->cspec->sendchkenable); @@ -3068,6 +3308,53 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data) return IRQ_HANDLED; } +#ifdef CONFIG_INFINIBAND_QIB_DCA + +static void reset_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m) +{ + if (!m->dca) + return; + qib_devinfo(dd->pcidev, + "Disabling notifier on HCA %d irq %d\n", + dd->unit, + m->msix.vector); + irq_set_affinity_notifier( + m->msix.vector, + NULL); + m->notifier = NULL; +} + +static void setup_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m) +{ + struct qib_irq_notify *n; + + if (!m->dca) + return; + n = kzalloc(sizeof(*n), GFP_KERNEL); + if (n) { + int ret; + + m->notifier = n; + n->notify.irq = m->msix.vector; + n->notify.notify = qib_irq_notifier_notify; + n->notify.release = qib_irq_notifier_release; + n->arg = m->arg; + n->rcv = m->rcv; + qib_devinfo(dd->pcidev, + "set notifier irq %d rcv %d notify %p\n", + n->notify.irq, n->rcv, &n->notify); + ret = irq_set_affinity_notifier( + n->notify.irq, + &n->notify); + if (ret) { + m->notifier = NULL; + kfree(n); + } + } +} + +#endif + /* * Set up our chip-specific interrupt handler. * The interrupt type has already been setup, so @@ -3149,6 +3436,9 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend) void *arg; u64 val; int lsb, reg, sh; +#ifdef CONFIG_INFINIBAND_QIB_DCA + int dca = 0; +#endif dd->cspec->msix_entries[msixnum]. name[sizeof(dd->cspec->msix_entries[msixnum].name) - 1] @@ -3161,6 +3451,9 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend) arg = dd->pport + irq_table[i].port - 1; } else arg = dd; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dca = irq_table[i].dca; +#endif lsb = irq_table[i].lsb; handler = irq_table[i].handler; snprintf(dd->cspec->msix_entries[msixnum].name, @@ -3178,6 +3471,9 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend) continue; if (qib_krcvq01_no_msi && ctxt < 2) continue; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dca = 1; +#endif lsb = QIB_I_RCVAVAIL_LSB + ctxt; handler = qib_7322pintr; snprintf(dd->cspec->msix_entries[msixnum].name, @@ -3203,6 +3499,11 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend) goto try_intx; } dd->cspec->msix_entries[msixnum].arg = arg; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dd->cspec->msix_entries[msixnum].dca = dca; + dd->cspec->msix_entries[msixnum].rcv = + handler == qib_7322pintr; +#endif if (lsb >= 0) { reg = lsb / IBA7322_REDIRECT_VEC_PER_REG; sh = (lsb % IBA7322_REDIRECT_VEC_PER_REG) * @@ -6885,6 +7186,9 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, dd->f_sdma_init_early = qib_7322_sdma_init_early; dd->f_writescratch = writescratch; dd->f_tempsense_rd = qib_7322_tempsense_rd; +#ifdef CONFIG_INFINIBAND_QIB_DCA + dd->f_notify_dca = qib_7322_notify_dca; +#endif /* * Do remaining PCIe setup and save PCIe values in dd. * Any error printing is already done by the init code. @@ -6921,7 +7225,7 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, actual_cnt -= dd->num_pports; tabsize = actual_cnt; - dd->cspec->msix_entries = kmalloc(tabsize * + dd->cspec->msix_entries = kzalloc(tabsize * sizeof(struct qib_msix_entry), GFP_KERNEL); if (!dd->cspec->msix_entries) { qib_dev_err(dd, "No memory for MSIx table\n"); @@ -6941,7 +7245,13 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, /* clear diagctrl register, in case diags were running and crashed */ qib_write_kreg(dd, kr_hwdiagctrl, 0); - +#ifdef CONFIG_INFINIBAND_QIB_DCA + if (!dca_add_requester(&pdev->dev)) { + qib_devinfo(dd->pcidev, "DCA enabled\n"); + dd->flags |= QIB_DCA_ENABLED; + qib_setup_dca(dd); + } +#endif goto bail; bail_cleanup: diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 173f805790da..4b64c885fa0d 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -39,6 +39,9 @@ #include #include #include +#ifdef CONFIG_INFINIBAND_QIB_DCA +#include +#endif #include "qib.h" #include "qib_common.h" @@ -1158,6 +1161,35 @@ struct pci_driver qib_driver = { .err_handler = &qib_pci_err_handler, }; +#ifdef CONFIG_INFINIBAND_QIB_DCA + +static int qib_notify_dca(struct notifier_block *, unsigned long, void *); +static struct notifier_block dca_notifier = { + .notifier_call = qib_notify_dca, + .next = NULL, + .priority = 0 +}; + +static int qib_notify_dca_device(struct device *device, void *data) +{ + struct qib_devdata *dd = dev_get_drvdata(device); + unsigned long event = *(unsigned long *)data; + + return dd->f_notify_dca(dd, event); +} + +static int qib_notify_dca(struct notifier_block *nb, unsigned long event, + void *p) +{ + int rval; + + rval = driver_for_each_device(&qib_driver.driver, NULL, + &event, qib_notify_dca_device); + return rval ? NOTIFY_BAD : NOTIFY_DONE; +} + +#endif + /* * Do all the generic driver unit- and chip-independent memory * allocation and initialization. @@ -1182,6 +1214,9 @@ static int __init qlogic_ib_init(void) */ idr_init(&qib_unit_table); +#ifdef CONFIG_INFINIBAND_QIB_DCA + dca_register_notify(&dca_notifier); +#endif ret = pci_register_driver(&qib_driver); if (ret < 0) { pr_err("Unable to register driver: error %d\n", -ret); @@ -1194,6 +1229,9 @@ static int __init qlogic_ib_init(void) goto bail; /* all OK */ bail_unit: +#ifdef CONFIG_INFINIBAND_QIB_DCA + dca_unregister_notify(&dca_notifier); +#endif idr_destroy(&qib_unit_table); destroy_workqueue(qib_cq_wq); bail_dev: @@ -1217,6 +1255,9 @@ static void __exit qlogic_ib_cleanup(void) "Unable to cleanup counter filesystem: error %d\n", -ret); +#ifdef CONFIG_INFINIBAND_QIB_DCA + dca_unregister_notify(&dca_notifier); +#endif pci_unregister_driver(&qib_driver); destroy_workqueue(qib_cq_wq); -- GitLab From f7cf9a618b48212394c07b169864d20beb23b8e5 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Sat, 15 Jun 2013 17:06:58 -0400 Subject: [PATCH 1681/2900] IB/qib: Remove atomic_inc_not_zero() from QP RCU Follow Documentation/RCU/rcuref.txt guidance in removing atomic_inc_not_zero() from QP RCU implementation. This patch also removes an unneeded synchronize_rcu() in the add path. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_qp.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index a6a2cc2ba260..c1f573a331c7 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. * All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * @@ -222,8 +222,8 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp) unsigned long flags; unsigned n = qpn_hash(dev, qp->ibqp.qp_num); - spin_lock_irqsave(&dev->qpt_lock, flags); atomic_inc(&qp->refcount); + spin_lock_irqsave(&dev->qpt_lock, flags); if (qp->ibqp.qp_num == 0) rcu_assign_pointer(ibp->qp0, qp); @@ -235,7 +235,6 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp) } spin_unlock_irqrestore(&dev->qpt_lock, flags); - synchronize_rcu(); } /* @@ -247,36 +246,39 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp) struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); unsigned n = qpn_hash(dev, qp->ibqp.qp_num); unsigned long flags; + int removed = 1; spin_lock_irqsave(&dev->qpt_lock, flags); if (rcu_dereference_protected(ibp->qp0, lockdep_is_held(&dev->qpt_lock)) == qp) { - atomic_dec(&qp->refcount); rcu_assign_pointer(ibp->qp0, NULL); } else if (rcu_dereference_protected(ibp->qp1, lockdep_is_held(&dev->qpt_lock)) == qp) { - atomic_dec(&qp->refcount); rcu_assign_pointer(ibp->qp1, NULL); } else { struct qib_qp *q; struct qib_qp __rcu **qpp; + removed = 0; qpp = &dev->qp_table[n]; for (; (q = rcu_dereference_protected(*qpp, lockdep_is_held(&dev->qpt_lock))) != NULL; qpp = &q->next) if (q == qp) { - atomic_dec(&qp->refcount); rcu_assign_pointer(*qpp, rcu_dereference_protected(qp->next, lockdep_is_held(&dev->qpt_lock))); + removed = 1; break; } } spin_unlock_irqrestore(&dev->qpt_lock, flags); - synchronize_rcu(); + if (removed) { + synchronize_rcu(); + atomic_dec(&qp->refcount); + } } /** @@ -334,26 +336,25 @@ struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn) { struct qib_qp *qp = NULL; + rcu_read_lock(); if (unlikely(qpn <= 1)) { - rcu_read_lock(); if (qpn == 0) qp = rcu_dereference(ibp->qp0); else qp = rcu_dereference(ibp->qp1); + if (qp) + atomic_inc(&qp->refcount); } else { struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev; unsigned n = qpn_hash(dev, qpn); - rcu_read_lock(); for (qp = rcu_dereference(dev->qp_table[n]); qp; qp = rcu_dereference(qp->next)) - if (qp->ibqp.qp_num == qpn) + if (qp->ibqp.qp_num == qpn) { + atomic_inc(&qp->refcount); break; + } } - if (qp) - if (unlikely(!atomic_inc_not_zero(&qp->refcount))) - qp = NULL; - rcu_read_unlock(); return qp; } -- GitLab From ab4a13d69bf01b098906c60e7598d10752401a56 Mon Sep 17 00:00:00 2001 From: Vinit Agnihotri Date: Sat, 15 Jun 2013 17:11:38 -0400 Subject: [PATCH 1682/2900] IB/qib: Update minor version number External PSM repositories have advanced the minor number for a variety of reasons. The driver needs to increase to avoid warnings. Signed-off-by: Vinit Agnihotri Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_common.h b/drivers/infiniband/hw/qib/qib_common.h index d39e0183ff82..4f255b723ffd 100644 --- a/drivers/infiniband/hw/qib/qib_common.h +++ b/drivers/infiniband/hw/qib/qib_common.h @@ -279,7 +279,7 @@ struct qib_base_info { * may not be implemented; the user code must deal with this if it * cares, or it must abort after initialization reports the difference. */ -#define QIB_USER_SWMINOR 11 +#define QIB_USER_SWMINOR 12 #define QIB_USER_SWVERSION ((QIB_USER_SWMAJOR << 16) | QIB_USER_SWMINOR) -- GitLab From e0f30baca1ebe5547f6760f760b8c4e189fc1203 Mon Sep 17 00:00:00 2001 From: Ramkrishna Vepa Date: Tue, 28 May 2013 12:57:33 -0400 Subject: [PATCH 1683/2900] IB/qib: Add optional NUMA affinity This patch adds context relative numa affinity conditioned on the module parameter numa_aware. The qib_ctxtdata has an additional node_id member and qib_create_ctxtdata() has an addition node_id parameter. The allocations within the hdr queue and eager queue setup routines now take this additional member and adjust allocations as necesary. PSM will pass the either current numa node or the node closest to the HCA depending on numa_aware. Verbs will always use the node closest to the HCA. Reviewed-by: Dean Luick Signed-off-by: Ramkrishna Vepa Signed-off-by: Vinit Agnihotri Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib.h | 7 ++++- drivers/infiniband/hw/qib/qib_file_ops.c | 6 +++- drivers/infiniband/hw/qib/qib_init.c | 39 +++++++++++++++++++----- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index cecbd43f9212..2ee82e6550c7 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -154,6 +154,8 @@ struct qib_ctxtdata { */ /* instead of calculating it */ unsigned ctxt; + /* local node of context */ + int node_id; /* non-zero if ctxt is being shared. */ u16 subctxt_cnt; /* non-zero if ctxt is being shared. */ @@ -1088,6 +1090,8 @@ struct qib_devdata { u16 psxmitwait_check_rate; /* high volume overflow errors defered to tasklet */ struct tasklet_struct error_tasklet; + + int assigned_node_id; /* NUMA node closest to HCA */ }; /* hol_state values */ @@ -1167,7 +1171,7 @@ int qib_create_rcvhdrq(struct qib_devdata *, struct qib_ctxtdata *); int qib_setup_eagerbufs(struct qib_ctxtdata *); void qib_set_ctxtcnt(struct qib_devdata *); int qib_create_ctxts(struct qib_devdata *dd); -struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *, u32); +struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *, u32, int); void qib_init_pportdata(struct qib_pportdata *, struct qib_devdata *, u8, u8); void qib_free_ctxtdata(struct qib_devdata *, struct qib_ctxtdata *); @@ -1458,6 +1462,7 @@ extern unsigned qib_n_krcv_queues; extern unsigned qib_sdma_fetch_arb; extern unsigned qib_compat_ddr_negotiate; extern int qib_special_trigger; +extern unsigned qib_numa_aware; extern struct mutex qib_mutex; diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index b56c9428f3c5..65b2fc3f957c 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1263,8 +1263,12 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt, struct qib_ctxtdata *rcd; void *ptmp = NULL; int ret; + int numa_id; - rcd = qib_create_ctxtdata(ppd, ctxt); + numa_id = qib_numa_aware ? numa_node_id() : + dd->assigned_node_id; + + rcd = qib_create_ctxtdata(ppd, ctxt, numa_id); /* * Allocate memory for use in qib_tid_update() at open to diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 4b64c885fa0d..e02217b5c46d 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -67,6 +67,11 @@ ushort qib_cfgctxts; module_param_named(cfgctxts, qib_cfgctxts, ushort, S_IRUGO); MODULE_PARM_DESC(cfgctxts, "Set max number of contexts to use"); +unsigned qib_numa_aware; +module_param_named(numa_aware, qib_numa_aware, uint, S_IRUGO); +MODULE_PARM_DESC(numa_aware, + "0 -> PSM allocation close to HCA, 1 -> PSM allocation local to process"); + /* * If set, do not write to any regs if avoidable, hack to allow * check for deranged default register values. @@ -124,6 +129,11 @@ int qib_create_ctxts(struct qib_devdata *dd) { unsigned i; int ret; + int local_node_id = pcibus_to_node(dd->pcidev->bus); + + if (local_node_id < 0) + local_node_id = numa_node_id(); + dd->assigned_node_id = local_node_id; /* * Allocate full ctxtcnt array, rather than just cfgctxts, because @@ -146,7 +156,8 @@ int qib_create_ctxts(struct qib_devdata *dd) continue; ppd = dd->pport + (i % dd->num_pports); - rcd = qib_create_ctxtdata(ppd, i); + + rcd = qib_create_ctxtdata(ppd, i, dd->assigned_node_id); if (!rcd) { qib_dev_err(dd, "Unable to allocate ctxtdata for Kernel ctxt, failing\n"); @@ -164,14 +175,16 @@ int qib_create_ctxts(struct qib_devdata *dd) /* * Common code for user and kernel context setup. */ -struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt) +struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt, + int node_id) { struct qib_devdata *dd = ppd->dd; struct qib_ctxtdata *rcd; - rcd = kzalloc(sizeof(*rcd), GFP_KERNEL); + rcd = kzalloc_node(sizeof(*rcd), GFP_KERNEL, node_id); if (rcd) { INIT_LIST_HEAD(&rcd->qp_wait_list); + rcd->node_id = node_id; rcd->ppd = ppd; rcd->dd = dd; rcd->cnt = 1; @@ -1524,6 +1537,7 @@ static void qib_remove_one(struct pci_dev *pdev) int qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd) { unsigned amt; + int old_node_id; if (!rcd->rcvhdrq) { dma_addr_t phys_hdrqtail; @@ -1533,9 +1547,13 @@ int qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd) sizeof(u32), PAGE_SIZE); gfp_flags = (rcd->ctxt >= dd->first_user_ctxt) ? GFP_USER : GFP_KERNEL; + + old_node_id = dev_to_node(&dd->pcidev->dev); + set_dev_node(&dd->pcidev->dev, rcd->node_id); rcd->rcvhdrq = dma_alloc_coherent( &dd->pcidev->dev, amt, &rcd->rcvhdrq_phys, gfp_flags | __GFP_COMP); + set_dev_node(&dd->pcidev->dev, old_node_id); if (!rcd->rcvhdrq) { qib_dev_err(dd, @@ -1551,9 +1569,11 @@ int qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd) } if (!(dd->flags & QIB_NODMA_RTAIL)) { + set_dev_node(&dd->pcidev->dev, rcd->node_id); rcd->rcvhdrtail_kvaddr = dma_alloc_coherent( &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, gfp_flags); + set_dev_node(&dd->pcidev->dev, old_node_id); if (!rcd->rcvhdrtail_kvaddr) goto bail_free; rcd->rcvhdrqtailaddr_phys = phys_hdrqtail; @@ -1597,6 +1617,7 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd) unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff; size_t size; gfp_t gfp_flags; + int old_node_id; /* * GFP_USER, but without GFP_FS, so buffer cache can be @@ -1615,25 +1636,29 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd) size = rcd->rcvegrbuf_size; if (!rcd->rcvegrbuf) { rcd->rcvegrbuf = - kzalloc(chunk * sizeof(rcd->rcvegrbuf[0]), - GFP_KERNEL); + kzalloc_node(chunk * sizeof(rcd->rcvegrbuf[0]), + GFP_KERNEL, rcd->node_id); if (!rcd->rcvegrbuf) goto bail; } if (!rcd->rcvegrbuf_phys) { rcd->rcvegrbuf_phys = - kmalloc(chunk * sizeof(rcd->rcvegrbuf_phys[0]), - GFP_KERNEL); + kmalloc_node(chunk * sizeof(rcd->rcvegrbuf_phys[0]), + GFP_KERNEL, rcd->node_id); if (!rcd->rcvegrbuf_phys) goto bail_rcvegrbuf; } for (e = 0; e < rcd->rcvegrbuf_chunks; e++) { if (rcd->rcvegrbuf[e]) continue; + + old_node_id = dev_to_node(&dd->pcidev->dev); + set_dev_node(&dd->pcidev->dev, rcd->node_id); rcd->rcvegrbuf[e] = dma_alloc_coherent(&dd->pcidev->dev, size, &rcd->rcvegrbuf_phys[e], gfp_flags); + set_dev_node(&dd->pcidev->dev, old_node_id); if (!rcd->rcvegrbuf[e]) goto bail_rcvegrbuf_phys; } -- GitLab From c804f07248895ff9c9dccb6cda703068a0657b6c Mon Sep 17 00:00:00 2001 From: Ramkrishna Vepa Date: Sun, 2 Jun 2013 15:16:11 -0400 Subject: [PATCH 1684/2900] IB/qib: Add dual-rail NUMA awareness for PSM processes The driver currently selects a HCA based on the algorithm that PSM chooses, contexts within a HCA or across. The HCA can also be chosen by the user. Either way, this patch assigns a CPU on the NUMA node local to the selected HCA. This patch also tries to select the HCA closest to the NUMA node of the CPU assigned via taskset to PSM process. If this HCA is unusable then another unit is selected based on the algorithm that is currently enforced or selected by PSM - round robin context selection 'within' or 'across' HCA's. Fixed a bug wherein contexts are setup on the NUMA node on which the processes are opened (setup_ctxt()) and not on the NUMA node that the driver recommends the CPU on. Reviewed-by: Mike Marciniszyn Signed-off-by: Vinit Agnihotri Signed-off-by: Ramkrishna Vepa Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_file_ops.c | 174 ++++++++++++++++------- 1 file changed, 125 insertions(+), 49 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 65b2fc3f957c..df3808a38381 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * @@ -1155,6 +1155,49 @@ static unsigned int qib_poll(struct file *fp, struct poll_table_struct *pt) return pollflag; } +static void assign_ctxt_affinity(struct file *fp, struct qib_devdata *dd) +{ + struct qib_filedata *fd = fp->private_data; + const unsigned int weight = cpumask_weight(¤t->cpus_allowed); + const struct cpumask *local_mask = cpumask_of_pcibus(dd->pcidev->bus); + int local_cpu; + + /* + * If process has NOT already set it's affinity, select and + * reserve a processor for it on the local NUMA node. + */ + if ((weight >= qib_cpulist_count) && + (cpumask_weight(local_mask) <= qib_cpulist_count)) { + for_each_cpu(local_cpu, local_mask) + if (!test_and_set_bit(local_cpu, qib_cpulist)) { + fd->rec_cpu_num = local_cpu; + return; + } + } + + /* + * If process has NOT already set it's affinity, select and + * reserve a processor for it, as a rendevous for all + * users of the driver. If they don't actually later + * set affinity to this cpu, or set it to some other cpu, + * it just means that sooner or later we don't recommend + * a cpu, and let the scheduler do it's best. + */ + if (weight >= qib_cpulist_count) { + int cpu; + cpu = find_first_zero_bit(qib_cpulist, + qib_cpulist_count); + if (cpu == qib_cpulist_count) + qib_dev_err(dd, + "no cpus avail for affinity PID %u\n", + current->pid); + else { + __set_bit(cpu, qib_cpulist); + fd->rec_cpu_num = cpu; + } + } +} + /* * Check that userland and driver are compatible for subcontexts. */ @@ -1259,14 +1302,18 @@ static int init_subctxts(struct qib_devdata *dd, static int setup_ctxt(struct qib_pportdata *ppd, int ctxt, struct file *fp, const struct qib_user_info *uinfo) { + struct qib_filedata *fd = fp->private_data; struct qib_devdata *dd = ppd->dd; struct qib_ctxtdata *rcd; void *ptmp = NULL; int ret; int numa_id; - numa_id = qib_numa_aware ? numa_node_id() : - dd->assigned_node_id; + assign_ctxt_affinity(fp, dd); + + numa_id = qib_numa_aware ? ((fd->rec_cpu_num != -1) ? + cpu_to_node(fd->rec_cpu_num) : + numa_node_id()) : dd->assigned_node_id; rcd = qib_create_ctxtdata(ppd, ctxt, numa_id); @@ -1300,6 +1347,9 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt, goto bail; bailerr: + if (fd->rec_cpu_num != -1) + __clear_bit(fd->rec_cpu_num, qib_cpulist); + dd->rcd[ctxt] = NULL; kfree(rcd); kfree(ptmp); @@ -1489,6 +1539,57 @@ static int qib_open(struct inode *in, struct file *fp) return fp->private_data ? 0 : -ENOMEM; } +static int find_hca(unsigned int cpu, int *unit) +{ + int ret = 0, devmax, npresent, nup, ndev; + + *unit = -1; + + devmax = qib_count_units(&npresent, &nup); + if (!npresent) { + ret = -ENXIO; + goto done; + } + if (!nup) { + ret = -ENETDOWN; + goto done; + } + for (ndev = 0; ndev < devmax; ndev++) { + struct qib_devdata *dd = qib_lookup(ndev); + if (dd) { + if (pcibus_to_node(dd->pcidev->bus) < 0) { + ret = -EINVAL; + goto done; + } + if (cpu_to_node(cpu) == + pcibus_to_node(dd->pcidev->bus)) { + *unit = ndev; + goto done; + } + } + } +done: + return ret; +} + +static int do_qib_user_sdma_queue_create(struct file *fp) +{ + struct qib_filedata *fd = fp->private_data; + struct qib_ctxtdata *rcd = fd->rcd; + struct qib_devdata *dd = rcd->dd; + + if (dd->flags & QIB_HAS_SEND_DMA) + + fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev, + dd->unit, + rcd->ctxt, + fd->subctxt); + if (!fd->pq) + return -ENOMEM; + + return 0; +} + /* * Get ctxt early, so can set affinity prior to memory allocation. */ @@ -1521,61 +1622,36 @@ static int qib_assign_ctxt(struct file *fp, const struct qib_user_info *uinfo) if (qib_compatible_subctxts(swmajor, swminor) && uinfo->spu_subctxt_cnt) { ret = find_shared_ctxt(fp, uinfo); - if (ret) { - if (ret > 0) - ret = 0; - goto done_chk_sdma; + if (ret > 0) { + ret = do_qib_user_sdma_queue_create(fp); + if (!ret) + assign_ctxt_affinity(fp, (ctxt_fp(fp))->dd); + goto done_ok; } } i_minor = iminor(file_inode(fp)) - QIB_USER_MINOR_BASE; if (i_minor) ret = find_free_ctxt(i_minor - 1, fp, uinfo); - else + else { + int unit; + const unsigned int cpu = cpumask_first(¤t->cpus_allowed); + const unsigned int weight = + cpumask_weight(¤t->cpus_allowed); + + if (weight == 1 && !test_bit(cpu, qib_cpulist)) + if (!find_hca(cpu, &unit) && unit >= 0) + if (!find_free_ctxt(unit, fp, uinfo)) { + ret = 0; + goto done_chk_sdma; + } ret = get_a_ctxt(fp, uinfo, alg); - -done_chk_sdma: - if (!ret) { - struct qib_filedata *fd = fp->private_data; - const struct qib_ctxtdata *rcd = fd->rcd; - const struct qib_devdata *dd = rcd->dd; - unsigned int weight; - - if (dd->flags & QIB_HAS_SEND_DMA) { - fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev, - dd->unit, - rcd->ctxt, - fd->subctxt); - if (!fd->pq) - ret = -ENOMEM; - } - - /* - * If process has NOT already set it's affinity, select and - * reserve a processor for it, as a rendezvous for all - * users of the driver. If they don't actually later - * set affinity to this cpu, or set it to some other cpu, - * it just means that sooner or later we don't recommend - * a cpu, and let the scheduler do it's best. - */ - weight = cpumask_weight(tsk_cpus_allowed(current)); - if (!ret && weight >= qib_cpulist_count) { - int cpu; - cpu = find_first_zero_bit(qib_cpulist, - qib_cpulist_count); - if (cpu != qib_cpulist_count) { - __set_bit(cpu, qib_cpulist); - fd->rec_cpu_num = cpu; - } - } else if (weight == 1 && - test_bit(cpumask_first(tsk_cpus_allowed(current)), - qib_cpulist)) - qib_devinfo(dd->pcidev, - "%s PID %u affinity set to cpu %d; already allocated\n", - current->comm, current->pid, - cpumask_first(tsk_cpus_allowed(current))); } +done_chk_sdma: + if (!ret) + ret = do_qib_user_sdma_queue_create(fp); +done_ok: mutex_unlock(&qib_mutex); done: -- GitLab From 85caafe307a06e4f9993c8f3c994a07374c07831 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Tue, 4 Jun 2013 15:05:37 -0400 Subject: [PATCH 1685/2900] IB/qib: Optimize CQ callbacks The current workqueue implemention has the following performance deficiencies on QDR HCAs: - The CQ call backs tend to run on the CPUs processing the receive queues - The single thread queue isn't optimal for multiple HCAs This patch adds a dedicated per HCA bound thread to process CQ callbacks. Reviewed-by: Ramkrishna Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib.h | 5 +- drivers/infiniband/hw/qib/qib_cq.c | 67 ++++++++++++++++++++++++--- drivers/infiniband/hw/qib/qib_init.c | 18 ++----- drivers/infiniband/hw/qib/qib_verbs.h | 10 ++-- 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 2ee82e6550c7..3a78b92cbd4e 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1,7 +1,7 @@ #ifndef _QIB_KERNEL_H #define _QIB_KERNEL_H /* - * Copyright (c) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * @@ -51,6 +51,7 @@ #include #include #include +#include #include "qib_common.h" #include "qib_verbs.h" @@ -1090,6 +1091,8 @@ struct qib_devdata { u16 psxmitwait_check_rate; /* high volume overflow errors defered to tasklet */ struct tasklet_struct error_tasklet; + /* per device cq worker */ + struct kthread_worker *worker; int assigned_node_id; /* NUMA node closest to HCA */ }; diff --git a/drivers/infiniband/hw/qib/qib_cq.c b/drivers/infiniband/hw/qib/qib_cq.c index 5246aa486bbe..ab4e11cfab15 100644 --- a/drivers/infiniband/hw/qib/qib_cq.c +++ b/drivers/infiniband/hw/qib/qib_cq.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2013 Intel Corporation. All rights reserved. * Copyright (c) 2006, 2007, 2008, 2010 QLogic Corporation. All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * @@ -34,8 +35,10 @@ #include #include #include +#include #include "qib_verbs.h" +#include "qib.h" /** * qib_cq_enter - add a new entry to the completion queue @@ -102,13 +105,18 @@ void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int solicited) if (cq->notify == IB_CQ_NEXT_COMP || (cq->notify == IB_CQ_SOLICITED && (solicited || entry->status != IB_WC_SUCCESS))) { - cq->notify = IB_CQ_NONE; - cq->triggered++; + struct kthread_worker *worker; /* * This will cause send_complete() to be called in * another thread. */ - queue_work(qib_cq_wq, &cq->comptask); + smp_rmb(); + worker = cq->dd->worker; + if (likely(worker)) { + cq->notify = IB_CQ_NONE; + cq->triggered++; + queue_kthread_work(worker, &cq->comptask); + } } spin_unlock_irqrestore(&cq->lock, flags); @@ -163,7 +171,7 @@ int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) return npolled; } -static void send_complete(struct work_struct *work) +static void send_complete(struct kthread_work *work) { struct qib_cq *cq = container_of(work, struct qib_cq, comptask); @@ -287,11 +295,12 @@ struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries, * The number of entries should be >= the number requested or return * an error. */ + cq->dd = dd_from_dev(dev); cq->ibcq.cqe = entries; cq->notify = IB_CQ_NONE; cq->triggered = 0; spin_lock_init(&cq->lock); - INIT_WORK(&cq->comptask, send_complete); + init_kthread_work(&cq->comptask, send_complete); wc->head = 0; wc->tail = 0; cq->queue = wc; @@ -323,7 +332,7 @@ int qib_destroy_cq(struct ib_cq *ibcq) struct qib_ibdev *dev = to_idev(ibcq->device); struct qib_cq *cq = to_icq(ibcq); - flush_work(&cq->comptask); + flush_kthread_work(&cq->comptask); spin_lock(&dev->n_cqs_lock); dev->n_cqs_allocated--; spin_unlock(&dev->n_cqs_lock); @@ -483,3 +492,49 @@ int qib_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) bail: return ret; } + +int qib_cq_init(struct qib_devdata *dd) +{ + int ret = 0; + int cpu; + struct task_struct *task; + + if (dd->worker) + return 0; + dd->worker = kzalloc(sizeof(*dd->worker), GFP_KERNEL); + if (!dd->worker) + return -ENOMEM; + init_kthread_worker(dd->worker); + task = kthread_create_on_node( + kthread_worker_fn, + dd->worker, + dd->assigned_node_id, + "qib_cq%d", dd->unit); + if (IS_ERR(task)) + goto task_fail; + cpu = cpumask_first(cpumask_of_node(dd->assigned_node_id)); + kthread_bind(task, cpu); + wake_up_process(task); +out: + return ret; +task_fail: + ret = PTR_ERR(task); + kfree(dd->worker); + dd->worker = NULL; + goto out; +} + +void qib_cq_exit(struct qib_devdata *dd) +{ + struct kthread_worker *worker; + + worker = dd->worker; + if (!worker) + return; + /* blocks future queuing from send_complete() */ + dd->worker = NULL; + smp_wmb(); + flush_kthread_worker(worker); + kthread_stop(worker->task); + kfree(worker); +} diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index e02217b5c46d..ff36903474ea 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -97,8 +97,6 @@ unsigned qib_wc_pat = 1; /* default (1) is to use PAT, not MTRR */ module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO); MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism"); -struct workqueue_struct *qib_cq_wq; - static void verify_interrupt(unsigned long); static struct idr qib_unit_table; @@ -445,6 +443,7 @@ static int loadtime_init(struct qib_devdata *dd) dd->intrchk_timer.function = verify_interrupt; dd->intrchk_timer.data = (unsigned long) dd; + ret = qib_cq_init(dd); done: return ret; } @@ -1215,12 +1214,6 @@ static int __init qlogic_ib_init(void) if (ret) goto bail; - qib_cq_wq = create_singlethread_workqueue("qib_cq"); - if (!qib_cq_wq) { - ret = -ENOMEM; - goto bail_dev; - } - /* * These must be called before the driver is registered with * the PCI subsystem. @@ -1233,7 +1226,7 @@ static int __init qlogic_ib_init(void) ret = pci_register_driver(&qib_driver); if (ret < 0) { pr_err("Unable to register driver: error %d\n", -ret); - goto bail_unit; + goto bail_dev; } /* not fatal if it doesn't work */ @@ -1241,13 +1234,11 @@ static int __init qlogic_ib_init(void) pr_err("Unable to register ipathfs\n"); goto bail; /* all OK */ -bail_unit: +bail_dev: #ifdef CONFIG_INFINIBAND_QIB_DCA dca_unregister_notify(&dca_notifier); #endif idr_destroy(&qib_unit_table); - destroy_workqueue(qib_cq_wq); -bail_dev: qib_dev_cleanup(); bail: return ret; @@ -1273,8 +1264,6 @@ static void __exit qlogic_ib_cleanup(void) #endif pci_unregister_driver(&qib_driver); - destroy_workqueue(qib_cq_wq); - qib_cpulist_count = 0; kfree(qib_cpulist); @@ -1365,6 +1354,7 @@ static void cleanup_device_data(struct qib_devdata *dd) } kfree(tmp); kfree(dd->boardname); + qib_cq_exit(dd); } /* diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index aff8b2c17886..86c2cb3c9caf 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -267,7 +268,8 @@ struct qib_cq_wc { */ struct qib_cq { struct ib_cq ibcq; - struct work_struct comptask; + struct kthread_work comptask; + struct qib_devdata *dd; spinlock_t lock; /* protect changes in this struct */ u8 notify; u8 triggered; @@ -832,8 +834,6 @@ static inline int qib_send_ok(struct qib_qp *qp) !(qp->s_flags & QIB_S_ANY_WAIT_SEND)); } -extern struct workqueue_struct *qib_cq_wq; - /* * This must be called with s_lock held. */ @@ -972,6 +972,10 @@ int qib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr); int qib_destroy_srq(struct ib_srq *ibsrq); +int qib_cq_init(struct qib_devdata *dd); + +void qib_cq_exit(struct qib_devdata *dd); + void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int sig); int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); -- GitLab From ddb8876589702a9396d15d9d4075e6388d0600cf Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Sat, 15 Jun 2013 17:07:03 -0400 Subject: [PATCH 1686/2900] IB/qib: Convert opcode counters to per-context This fix changes the opcode relative counters for receive to per context. Profiling has shown that when mulitple contexts are being used there is a lot of cache activity associated with these counters. The code formerly kept these counters per port, but only provided the interface to read per HCA. This patch converts the read of counters to per HCA and adds the debugfs hooks to be able to read the file as a sequence of opcodes. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/Makefile | 1 + drivers/infiniband/hw/qib/qib.h | 36 ++--- drivers/infiniband/hw/qib/qib_debugfs.c | 166 ++++++++++++++++++++++++ drivers/infiniband/hw/qib/qib_debugfs.h | 45 +++++++ drivers/infiniband/hw/qib/qib_driver.c | 1 - drivers/infiniband/hw/qib/qib_init.c | 41 +++++- drivers/infiniband/hw/qib/qib_verbs.c | 8 +- drivers/infiniband/hw/qib/qib_verbs.h | 9 +- 8 files changed, 284 insertions(+), 23 deletions(-) create mode 100644 drivers/infiniband/hw/qib/qib_debugfs.c create mode 100644 drivers/infiniband/hw/qib/qib_debugfs.h diff --git a/drivers/infiniband/hw/qib/Makefile b/drivers/infiniband/hw/qib/Makefile index f12d7bb8b39f..57f8103e51f8 100644 --- a/drivers/infiniband/hw/qib/Makefile +++ b/drivers/infiniband/hw/qib/Makefile @@ -13,3 +13,4 @@ ib_qib-$(CONFIG_PCI_MSI) += qib_iba6120.o ib_qib-$(CONFIG_X86_64) += qib_wc_x86_64.o ib_qib-$(CONFIG_PPC64) += qib_wc_ppc64.o +ib_qib-$(CONFIG_DEBUG_FS) += qib_debugfs.o diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 3a78b92cbd4e..5453e2b36567 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -115,6 +115,11 @@ struct qib_eep_log_mask { /* * Below contains all data related to a single context (formerly called port). */ + +#ifdef CONFIG_DEBUG_FS +struct qib_opcode_stats_perctx; +#endif + struct qib_ctxtdata { void **rcvegrbuf; dma_addr_t *rcvegrbuf_phys; @@ -225,12 +230,15 @@ struct qib_ctxtdata { u8 redirect_seq_cnt; /* ctxt rcvhdrq head offset */ u32 head; - u32 pkt_count; /* lookaside fields */ struct qib_qp *lookaside_qp; u32 lookaside_qpn; /* QPs waiting for context processing */ struct list_head qp_wait_list; +#ifdef CONFIG_DEBUG_FS + /* verbs stats per CTX */ + struct qib_opcode_stats_perctx *opstats; +#endif }; struct qib_sge_state; @@ -1495,27 +1503,23 @@ extern struct mutex qib_mutex; * first to avoid possible serial port delays from printk. */ #define qib_early_err(dev, fmt, ...) \ - do { \ - dev_err(dev, fmt, ##__VA_ARGS__); \ - } while (0) + dev_err(dev, fmt, ##__VA_ARGS__) #define qib_dev_err(dd, fmt, ...) \ - do { \ - dev_err(&(dd)->pcidev->dev, "%s: " fmt, \ - qib_get_unit_name((dd)->unit), ##__VA_ARGS__); \ - } while (0) + dev_err(&(dd)->pcidev->dev, "%s: " fmt, \ + qib_get_unit_name((dd)->unit), ##__VA_ARGS__) + +#define qib_dev_warn(dd, fmt, ...) \ + dev_warn(&(dd)->pcidev->dev, "%s: " fmt, \ + qib_get_unit_name((dd)->unit), ##__VA_ARGS__) #define qib_dev_porterr(dd, port, fmt, ...) \ - do { \ - dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \ - qib_get_unit_name((dd)->unit), (dd)->unit, (port), \ - ##__VA_ARGS__); \ - } while (0) + dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \ + qib_get_unit_name((dd)->unit), (dd)->unit, (port), \ + ##__VA_ARGS__) #define qib_devinfo(pcidev, fmt, ...) \ - do { \ - dev_info(&(pcidev)->dev, fmt, ##__VA_ARGS__); \ - } while (0) + dev_info(&(pcidev)->dev, fmt, ##__VA_ARGS__) /* * this is used for formatting hw error messages... diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c new file mode 100644 index 000000000000..47d01164cc91 --- /dev/null +++ b/drivers/infiniband/hw/qib/qib_debugfs.c @@ -0,0 +1,166 @@ +#ifdef CONFIG_DEBUG_FS +/* + * Copyright (c) 2013 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include + +#include "qib.h" +#include "qib_verbs.h" +#include "qib_debugfs.h" + +static struct dentry *qib_dbg_root; + +#define DEBUGFS_FILE(name) \ +static const struct seq_operations _##name##_seq_ops = { \ + .start = _##name##_seq_start, \ + .next = _##name##_seq_next, \ + .stop = _##name##_seq_stop, \ + .show = _##name##_seq_show \ +}; \ +static int _##name##_open(struct inode *inode, struct file *s) \ +{ \ + struct seq_file *seq; \ + int ret; \ + ret = seq_open(s, &_##name##_seq_ops); \ + if (ret) \ + return ret; \ + seq = s->private_data; \ + seq->private = inode->i_private; \ + return 0; \ +} \ +static const struct file_operations _##name##_file_ops = { \ + .owner = THIS_MODULE, \ + .open = _##name##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = seq_release \ +}; + +#define DEBUGFS_FILE_CREATE(name) \ +do { \ + struct dentry *ent; \ + ent = debugfs_create_file(#name , 0400, ibd->qib_ibdev_dbg, \ + ibd, &_##name##_file_ops); \ + if (!ent) \ + pr_warn("create of " #name " failed\n"); \ +} while (0) + +static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos) +{ + struct qib_opcode_stats_perctx *opstats; + + if (*pos >= ARRAY_SIZE(opstats->stats)) + return NULL; + return pos; +} + +static void *_opcode_stats_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct qib_opcode_stats_perctx *opstats; + + ++*pos; + if (*pos >= ARRAY_SIZE(opstats->stats)) + return NULL; + return pos; +} + + +static void _opcode_stats_seq_stop(struct seq_file *s, void *v) +{ + /* nothing allocated */ +} + +static int _opcode_stats_seq_show(struct seq_file *s, void *v) +{ + loff_t *spos = v; + loff_t i = *spos, j; + u64 n_packets = 0, n_bytes = 0; + struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; + struct qib_devdata *dd = dd_from_dev(ibd); + + for (j = 0; j < dd->first_user_ctxt; j++) { + if (!dd->rcd[j]) + continue; + n_packets += dd->rcd[j]->opstats->stats[i].n_packets; + n_bytes += dd->rcd[j]->opstats->stats[i].n_bytes; + } + if (!n_packets && !n_bytes) + return SEQ_SKIP; + seq_printf(s, "%02llx %llu/%llu\n", i, + (unsigned long long) n_packets, + (unsigned long long) n_bytes); + + return 0; +} + +DEBUGFS_FILE(opcode_stats) + +void qib_dbg_ibdev_init(struct qib_ibdev *ibd) +{ + char name[10]; + + snprintf(name, sizeof(name), "qib%d", dd_from_dev(ibd)->unit); + ibd->qib_ibdev_dbg = debugfs_create_dir(name, qib_dbg_root); + if (!ibd->qib_ibdev_dbg) { + pr_warn("create of %s failed\n", name); + return; + } + DEBUGFS_FILE_CREATE(opcode_stats); + return; +} + +void qib_dbg_ibdev_exit(struct qib_ibdev *ibd) +{ + if (!qib_dbg_root) + goto out; + debugfs_remove_recursive(ibd->qib_ibdev_dbg); +out: + ibd->qib_ibdev_dbg = NULL; +} + +void qib_dbg_init(void) +{ + qib_dbg_root = debugfs_create_dir(QIB_DRV_NAME, NULL); + if (!qib_dbg_root) + pr_warn("init of debugfs failed\n"); +} + +void qib_dbg_exit(void) +{ + debugfs_remove_recursive(qib_dbg_root); + qib_dbg_root = NULL; +} + +#endif + diff --git a/drivers/infiniband/hw/qib/qib_debugfs.h b/drivers/infiniband/hw/qib/qib_debugfs.h new file mode 100644 index 000000000000..7ae983a91b8b --- /dev/null +++ b/drivers/infiniband/hw/qib/qib_debugfs.h @@ -0,0 +1,45 @@ +#ifndef _QIB_DEBUGFS_H +#define _QIB_DEBUGFS_H + +#ifdef CONFIG_DEBUG_FS +/* + * Copyright (c) 2013 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +struct qib_ibdev; +void qib_dbg_ibdev_init(struct qib_ibdev *ibd); +void qib_dbg_ibdev_exit(struct qib_ibdev *ibd); +void qib_dbg_init(void); +void qib_dbg_exit(void); + +#endif + +#endif /* _QIB_DEBUGFS_H */ diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c index 216092477dfc..5bee08f16d74 100644 --- a/drivers/infiniband/hw/qib/qib_driver.c +++ b/drivers/infiniband/hw/qib/qib_driver.c @@ -558,7 +558,6 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) } rcd->head = l; - rcd->pkt_count += i; /* * Iterate over all QPs waiting to respond. diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index ff36903474ea..fdae42973056 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -46,6 +46,10 @@ #include "qib.h" #include "qib_common.h" #include "qib_mad.h" +#ifdef CONFIG_DEBUG_FS +#include "qib_debugfs.h" +#include "qib_verbs.h" +#endif #undef pr_fmt #define pr_fmt(fmt) QIB_DRV_NAME ": " fmt @@ -188,7 +192,18 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt, rcd->cnt = 1; rcd->ctxt = ctxt; dd->rcd[ctxt] = rcd; - +#ifdef CONFIG_DEBUG_FS + if (ctxt < dd->first_user_ctxt) { /* N/A for PSM contexts */ + rcd->opstats = kzalloc_node(sizeof(*rcd->opstats), + GFP_KERNEL, node_id); + if (!rcd->opstats) { + kfree(rcd); + qib_dev_err(dd, + "Unable to allocate per ctxt stats buffer\n"); + return NULL; + } + } +#endif dd->f_init_ctxt(rcd); /* @@ -959,6 +974,10 @@ void qib_free_ctxtdata(struct qib_devdata *dd, struct qib_ctxtdata *rcd) vfree(rcd->subctxt_uregbase); vfree(rcd->subctxt_rcvegrbuf); vfree(rcd->subctxt_rcvhdr_base); +#ifdef CONFIG_DEBUG_FS + kfree(rcd->opstats); + rcd->opstats = NULL; +#endif kfree(rcd); } @@ -1048,7 +1067,6 @@ static void qib_verify_pioperf(struct qib_devdata *dd) dd->f_set_armlaunch(dd, 1); } - void qib_free_devdata(struct qib_devdata *dd) { unsigned long flags; @@ -1058,6 +1076,9 @@ void qib_free_devdata(struct qib_devdata *dd) list_del(&dd->list); spin_unlock_irqrestore(&qib_devs_lock, flags); +#ifdef CONFIG_DEBUG_FS + qib_dbg_ibdev_exit(&dd->verbs_dev); +#endif ib_dealloc_device(&dd->verbs_dev.ibdev); } @@ -1081,6 +1102,10 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra) goto bail; } +#ifdef CONFIG_DEBUG_FS + qib_dbg_ibdev_init(&dd->verbs_dev); +#endif + idr_preload(GFP_KERNEL); spin_lock_irqsave(&qib_devs_lock, flags); @@ -1096,6 +1121,9 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra) if (ret < 0) { qib_early_err(&pdev->dev, "Could not allocate unit ID: error %d\n", -ret); +#ifdef CONFIG_DEBUG_FS + qib_dbg_ibdev_exit(&dd->verbs_dev); +#endif ib_dealloc_device(&dd->verbs_dev.ibdev); dd = ERR_PTR(ret); goto bail; @@ -1222,6 +1250,9 @@ static int __init qlogic_ib_init(void) #ifdef CONFIG_INFINIBAND_QIB_DCA dca_register_notify(&dca_notifier); +#endif +#ifdef CONFIG_DEBUG_FS + qib_dbg_init(); #endif ret = pci_register_driver(&qib_driver); if (ret < 0) { @@ -1237,6 +1268,9 @@ static int __init qlogic_ib_init(void) bail_dev: #ifdef CONFIG_INFINIBAND_QIB_DCA dca_unregister_notify(&dca_notifier); +#endif +#ifdef CONFIG_DEBUG_FS + qib_dbg_exit(); #endif idr_destroy(&qib_unit_table); qib_dev_cleanup(); @@ -1263,6 +1297,9 @@ static void __exit qlogic_ib_cleanup(void) dca_unregister_notify(&dca_notifier); #endif pci_unregister_driver(&qib_driver); +#ifdef CONFIG_DEBUG_FS + qib_dbg_exit(); +#endif qib_cpulist_count = 0; kfree(qib_cpulist); diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 904c384aa361..092b0bb1bb78 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -645,9 +645,11 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen) } else goto drop; - opcode = be32_to_cpu(ohdr->bth[0]) >> 24; - ibp->opstats[opcode & 0x7f].n_bytes += tlen; - ibp->opstats[opcode & 0x7f].n_packets++; + opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0x7f; +#ifdef CONFIG_DEBUG_FS + rcd->opstats->stats[opcode].n_bytes += tlen; + rcd->opstats->stats[opcode].n_packets++; +#endif /* Get the destination QP number. */ qp_num = be32_to_cpu(ohdr->bth[1]) & QIB_QPN_MASK; diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 86c2cb3c9caf..4a22a85b9f03 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -660,6 +660,10 @@ struct qib_opcode_stats { u64 n_bytes; /* total number of bytes */ }; +struct qib_opcode_stats_perctx { + struct qib_opcode_stats stats[128]; +}; + struct qib_ibport { struct qib_qp __rcu *qp0; struct qib_qp __rcu *qp1; @@ -726,7 +730,6 @@ struct qib_ibport { u8 vl_high_limit; u8 sl_to_vl[16]; - struct qib_opcode_stats opstats[128]; }; @@ -770,6 +773,10 @@ struct qib_ibdev { spinlock_t n_srqs_lock; u32 n_mcast_grps_allocated; /* number of mcast groups allocated */ spinlock_t n_mcast_grps_lock; +#ifdef CONFIG_DEBUG_FS + /* per HCA debugfs */ + struct dentry *qib_ibdev_dbg; +#endif }; struct qib_verbs_counters { -- GitLab From 17db3a92c144a0f8a81c52e94b7110bc86b5067f Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Sat, 15 Jun 2013 17:07:09 -0400 Subject: [PATCH 1687/2900] IB/qib: Add per-context stats interface This patch adds a debugfs stats interface for per kernel contexts packet counts. The code uses the opcode stats count and eliminates the counter in the context. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_debugfs.c | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c index 47d01164cc91..a4e6ee154f19 100644 --- a/drivers/infiniband/hw/qib/qib_debugfs.c +++ b/drivers/infiniband/hw/qib/qib_debugfs.c @@ -126,6 +126,68 @@ static int _opcode_stats_seq_show(struct seq_file *s, void *v) DEBUGFS_FILE(opcode_stats) +static void *_ctx_stats_seq_start(struct seq_file *s, loff_t *pos) +{ + struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; + struct qib_devdata *dd = dd_from_dev(ibd); + + if (!*pos) + return SEQ_START_TOKEN; + if (*pos >= dd->first_user_ctxt) + return NULL; + return pos; +} + +static void *_ctx_stats_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; + struct qib_devdata *dd = dd_from_dev(ibd); + + if (v == SEQ_START_TOKEN) + return pos; + + ++*pos; + if (*pos >= dd->first_user_ctxt) + return NULL; + return pos; +} + +static void _ctx_stats_seq_stop(struct seq_file *s, void *v) +{ + /* nothing allocated */ +} + +static int _ctx_stats_seq_show(struct seq_file *s, void *v) +{ + loff_t *spos; + loff_t i, j; + u64 n_packets = 0; + struct qib_ibdev *ibd = (struct qib_ibdev *)s->private; + struct qib_devdata *dd = dd_from_dev(ibd); + + if (v == SEQ_START_TOKEN) { + seq_puts(s, "Ctx:npkts\n"); + return 0; + } + + spos = v; + i = *spos; + + if (!dd->rcd[i]) + return SEQ_SKIP; + + for (j = 0; j < ARRAY_SIZE(dd->rcd[i]->opstats->stats); j++) + n_packets += dd->rcd[i]->opstats->stats[j].n_packets; + + if (!n_packets) + return SEQ_SKIP; + + seq_printf(s, " %llu:%llu\n", i, n_packets); + return 0; +} + +DEBUGFS_FILE(ctx_stats) + void qib_dbg_ibdev_init(struct qib_ibdev *ibd) { char name[10]; @@ -137,6 +199,7 @@ void qib_dbg_ibdev_init(struct qib_ibdev *ibd) return; } DEBUGFS_FILE_CREATE(opcode_stats); + DEBUGFS_FILE_CREATE(ctx_stats); return; } -- GitLab From 1dd173b01f52c7a197cab20563d5f4967472a852 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Sat, 15 Jun 2013 17:07:14 -0400 Subject: [PATCH 1688/2900] IB/qib: Add qp_stats debug file This adds a seq_file iterator for reporting the QP hash table when the qp_stats file is read. Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_debugfs.c | 54 ++++++++++++++ drivers/infiniband/hw/qib/qib_qp.c | 94 +++++++++++++++++++++++++ drivers/infiniband/hw/qib/qib_verbs.h | 14 +++- 3 files changed, 161 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c index a4e6ee154f19..799a0c3bffc4 100644 --- a/drivers/infiniband/hw/qib/qib_debugfs.c +++ b/drivers/infiniband/hw/qib/qib_debugfs.c @@ -188,6 +188,59 @@ static int _ctx_stats_seq_show(struct seq_file *s, void *v) DEBUGFS_FILE(ctx_stats) +static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos) +{ + struct qib_qp_iter *iter; + loff_t n = *pos; + + iter = qib_qp_iter_init(s->private); + if (!iter) + return NULL; + + while (n--) { + if (qib_qp_iter_next(iter)) { + kfree(iter); + return NULL; + } + } + + return iter; +} + +static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr, + loff_t *pos) +{ + struct qib_qp_iter *iter = iter_ptr; + + (*pos)++; + + if (qib_qp_iter_next(iter)) { + kfree(iter); + return NULL; + } + + return iter; +} + +static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr) +{ + /* nothing for now */ +} + +static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr) +{ + struct qib_qp_iter *iter = iter_ptr; + + if (!iter) + return 0; + + qib_qp_iter_print(s, iter); + + return 0; +} + +DEBUGFS_FILE(qp_stats) + void qib_dbg_ibdev_init(struct qib_ibdev *ibd) { char name[10]; @@ -200,6 +253,7 @@ void qib_dbg_ibdev_init(struct qib_ibdev *ibd) } DEBUGFS_FILE_CREATE(opcode_stats); DEBUGFS_FILE_CREATE(ctx_stats); + DEBUGFS_FILE_CREATE(qp_stats); return; } diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index c1f573a331c7..3cca55b51e54 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef CONFIG_DEBUG_FS +#include +#endif #include "qib.h" @@ -1287,3 +1290,94 @@ void qib_get_credit(struct qib_qp *qp, u32 aeth) } } } + +#ifdef CONFIG_DEBUG_FS + +struct qib_qp_iter { + struct qib_ibdev *dev; + struct qib_qp *qp; + int n; +}; + +struct qib_qp_iter *qib_qp_iter_init(struct qib_ibdev *dev) +{ + struct qib_qp_iter *iter; + + iter = kzalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + return NULL; + + iter->dev = dev; + if (qib_qp_iter_next(iter)) { + kfree(iter); + return NULL; + } + + return iter; +} + +int qib_qp_iter_next(struct qib_qp_iter *iter) +{ + struct qib_ibdev *dev = iter->dev; + int n = iter->n; + int ret = 1; + struct qib_qp *pqp = iter->qp; + struct qib_qp *qp; + + rcu_read_lock(); + for (; n < dev->qp_table_size; n++) { + if (pqp) + qp = rcu_dereference(pqp->next); + else + qp = rcu_dereference(dev->qp_table[n]); + pqp = qp; + if (qp) { + if (iter->qp) + atomic_dec(&iter->qp->refcount); + atomic_inc(&qp->refcount); + rcu_read_unlock(); + iter->qp = qp; + iter->n = n; + return 0; + } + } + rcu_read_unlock(); + if (iter->qp) + atomic_dec(&iter->qp->refcount); + return ret; +} + +static const char * const qp_type_str[] = { + "SMI", "GSI", "RC", "UC", "UD", +}; + +void qib_qp_iter_print(struct seq_file *s, struct qib_qp_iter *iter) +{ + struct qib_swqe *wqe; + struct qib_qp *qp = iter->qp; + + wqe = get_swqe_ptr(qp, qp->s_last); + seq_printf(s, + "N %d QP%u %s %u %u %u f=%x %u %u %u %u %u PSN %x %x %x %x %x (%u %u %u %u %u %u) QP%u LID %x\n", + iter->n, + qp->ibqp.qp_num, + qp_type_str[qp->ibqp.qp_type], + qp->state, + wqe->wr.opcode, + qp->s_hdrwords, + qp->s_flags, + atomic_read(&qp->s_dma_busy), + !list_empty(&qp->iowait), + qp->timeout, + wqe->ssn, + qp->s_lsn, + qp->s_last_psn, + qp->s_psn, qp->s_next_psn, + qp->s_sending_psn, qp->s_sending_hpsn, + qp->s_last, qp->s_acked, qp->s_cur, + qp->s_tail, qp->s_head, qp->s_size, + qp->remote_qpn, + qp->remote_ah_attr.dlid); +} + +#endif diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 4a22a85b9f03..012e2c7575ad 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Intel Corporation. All rights reserved. + * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * @@ -917,6 +917,18 @@ void qib_init_qpn_table(struct qib_devdata *dd, struct qib_qpn_table *qpt); void qib_free_qpn_table(struct qib_qpn_table *qpt); +#ifdef CONFIG_DEBUG_FS + +struct qib_qp_iter; + +struct qib_qp_iter *qib_qp_iter_init(struct qib_ibdev *dev); + +int qib_qp_iter_next(struct qib_qp_iter *iter); + +void qib_qp_iter_print(struct seq_file *s, struct qib_qp_iter *iter); + +#endif + void qib_get_credit(struct qib_qp *qp, u32 aeth); unsigned qib_pkt_delay(u32 plen, u8 snd_mult, u8 rcv_mult); -- GitLab From b52eafcd79728d61cfc75b64c817b5037a31dfe7 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Mon, 10 Jun 2013 16:12:01 +0100 Subject: [PATCH 1689/2900] power/reset: Make the vexpress driver optional on arm and arm64 The driver can be used on either arm or arm64 platforms, but the latter doesn't have any platform-specific configuration options, so it must be possible to manually enable the driver. Signed-off-by: Pawel Moll Acked-by: Catalin Marinas Signed-off-by: Anton Vorontsov --- drivers/power/reset/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 349e9ae8090a..ee039dcead04 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -32,7 +32,8 @@ config POWER_RESET_RESTART user presses a key. u-boot then boots into Linux. config POWER_RESET_VEXPRESS - bool + bool "ARM Versatile Express power-off and reset driver" + depends on ARM || ARM64 depends on POWER_RESET help Power off and reset support for the ARM Ltd. Versatile -- GitLab From c5623556fc61804713b1569b4f748e36956bc6e8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:33 +0300 Subject: [PATCH 1690/2900] Bluetooth: Handle LE L2CAP signalling in its own function The LE L2CAP signalling channel follows its own rules and will continue to evolve independently from the BR/EDR signalling channel. Therefore, it makes sense to have a clear split from BR/EDR by having a dedicated function for handling LE signalling commands. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 53 ++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4be6a264b475..ab9961118181 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -5292,6 +5292,51 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, } } +static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, + struct sk_buff *skb) +{ + u8 *data = skb->data; + int len = skb->len; + struct l2cap_cmd_hdr cmd; + int err; + + l2cap_raw_recv(conn, skb); + + while (len >= L2CAP_CMD_HDR_SIZE) { + u16 cmd_len; + memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE); + data += L2CAP_CMD_HDR_SIZE; + len -= L2CAP_CMD_HDR_SIZE; + + cmd_len = le16_to_cpu(cmd.len); + + BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, + cmd.ident); + + if (cmd_len > len || !cmd.ident) { + BT_DBG("corrupted command"); + break; + } + + err = l2cap_le_sig_cmd(conn, &cmd, data); + if (err) { + struct l2cap_cmd_rej_unk rej; + + BT_ERR("Wrong link type (%d)", err); + + /* FIXME: Map err to a valid reason */ + rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); + l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, + sizeof(rej), &rej); + } + + data += cmd_len; + len -= cmd_len; + } + + kfree_skb(skb); +} + static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) { @@ -5318,11 +5363,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, break; } - if (conn->hcon->type == LE_LINK) - err = l2cap_le_sig_cmd(conn, &cmd, data); - else - err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); - + err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data); if (err) { struct l2cap_cmd_rej_unk rej; @@ -6395,6 +6436,8 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) switch (cid) { case L2CAP_CID_LE_SIGNALING: + l2cap_le_sig_channel(conn, skb); + break; case L2CAP_CID_SIGNALING: l2cap_sig_channel(conn, skb); break; -- GitLab From 073d1cf35fe45d89f5a553c21eea18b504dd6937 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:35 +0300 Subject: [PATCH 1691/2900] Bluetooth: Rename L2CAP_CID_LE_DATA to L2CAP_CID_ATT In future Core Specification versions the ATT CID will be just one of many possible CIDs that can be used for data transfer. Therefore, it makes sense to rename the define for the ATT CID to something less ambigous. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/l2cap.h | 2 +- net/bluetooth/l2cap_core.c | 14 +++++++------- net/bluetooth/l2cap_sock.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index fb94cf13c777..1a966afbbfa8 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -242,7 +242,7 @@ struct l2cap_conn_rsp { #define L2CAP_CID_SIGNALING 0x0001 #define L2CAP_CID_CONN_LESS 0x0002 #define L2CAP_CID_A2MP 0x0003 -#define L2CAP_CID_LE_DATA 0x0004 +#define L2CAP_CID_ATT 0x0004 #define L2CAP_CID_LE_SIGNALING 0x0005 #define L2CAP_CID_SMP 0x0006 #define L2CAP_CID_DYN_START 0x0040 diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ab9961118181..c87f8f94083d 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -504,8 +504,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (conn->hcon->type == LE_LINK) { /* LE connection */ chan->omtu = L2CAP_DEFAULT_MTU; - chan->scid = L2CAP_CID_LE_DATA; - chan->dcid = L2CAP_CID_LE_DATA; + chan->scid = L2CAP_CID_ATT; + chan->dcid = L2CAP_CID_ATT; } else { /* Alloc CID for connection-oriented socket */ chan->scid = l2cap_alloc_cid(conn); @@ -1344,7 +1344,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) BT_DBG(""); /* Check if we have socket listening on cid */ - pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, + pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, conn->src, conn->dst); if (!pchan) return; @@ -1792,7 +1792,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, auth_type = l2cap_get_auth_type(chan); - if (chan->dcid == L2CAP_CID_LE_DATA) + if (chan->dcid == L2CAP_CID_ATT) hcon = hci_connect(hdev, LE_LINK, dst, dst_type, chan->sec_level, auth_type); else @@ -6397,7 +6397,7 @@ static void l2cap_att_channel(struct l2cap_conn *conn, { struct l2cap_chan *chan; - chan = l2cap_global_chan_by_scid(0, L2CAP_CID_LE_DATA, + chan = l2cap_global_chan_by_scid(0, L2CAP_CID_ATT, conn->src, conn->dst); if (!chan) goto drop; @@ -6448,7 +6448,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) l2cap_conless_channel(conn, psm, skb); break; - case L2CAP_CID_LE_DATA: + case L2CAP_CID_ATT: l2cap_att_channel(conn, skb); break; @@ -6574,7 +6574,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) continue; } - if (chan->scid == L2CAP_CID_LE_DATA) { + if (chan->scid == L2CAP_CID_ATT) { if (!status && encrypt) { chan->sec_level = hcon->sec_level; l2cap_chan_ready(chan); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 36fed40c162c..0098af80b213 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -466,7 +466,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) { switch (chan->scid) { - case L2CAP_CID_LE_DATA: + case L2CAP_CID_ATT: if (mtu < L2CAP_LE_MIN_MTU) return false; break; @@ -630,7 +630,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, conn = chan->conn; /*change security for LE channels */ - if (chan->scid == L2CAP_CID_LE_DATA) { + if (chan->scid == L2CAP_CID_ATT) { if (!conn->hcon->out) { err = -EINVAL; break; -- GitLab From f224ca5fc207a9957164e6f42ec6766da0f55d54 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:36 +0300 Subject: [PATCH 1692/2900] Bluetooth: Fix LE vs BR/EDR selection when connecting The choice between LE and BR/EDR should be made on the destination address type instead of the destination CID. This is particularly important when in the future more than one CID will be allowed for LE. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c87f8f94083d..29398293d501 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1792,7 +1792,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, auth_type = l2cap_get_auth_type(chan); - if (chan->dcid == L2CAP_CID_ATT) + if (bdaddr_type_is_le(dst_type)) hcon = hci_connect(hdev, LE_LINK, dst, dst_type, chan->sec_level, auth_type); else -- GitLab From 141d57065afd11977c4d346f64b25350445bf689 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:37 +0300 Subject: [PATCH 1693/2900] Bluetooth: Fix EBUSY condition test in l2cap_chan_connect The current test in l2cap_chan_connect is intended to protect against multiple conflicting connect attempts. However, it assumes that there will ever only be a single CID that is connected to, which is not true. We do need to check for conflicts with connect attempts to the same destination CID but this check is not in anyway specific to LE but can be applied to BR/EDR as well. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 29398293d501..640423b4f411 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1811,16 +1811,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, goto done; } - if (hcon->type == LE_LINK) { - err = 0; - - if (!list_empty(&conn->chan_l)) { - err = -EBUSY; - hci_conn_drop(hcon); - } - - if (err) - goto done; + if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { + hci_conn_drop(hcon); + err = -EBUSY; + goto done; } /* Update source addr of the socket */ -- GitLab From 9f22398ce4baf816535415e65949d03f55a7973a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:38 +0300 Subject: [PATCH 1694/2900] Bluetooth: Fix hardcoding ATT CID in __l2cap_chan_add() Since in the future more than the ATT CID may be permissible we should not be hardcoding it for all LE connections in __l2cap_chan_add(). Instead, the source ATT CID should only be set if the destination is also ATT, and in other cases we should just use the existing dynamic CID allocation function. Assigning scid based on dcid means that whenever __l2cap_chan_add() is called that chan->dcid is properly initialized. l2cap_le_conn_ready() wasn't initializing is properly so this is also taken care of in this patch. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 640423b4f411..4803610187ed 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -504,8 +504,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) if (conn->hcon->type == LE_LINK) { /* LE connection */ chan->omtu = L2CAP_DEFAULT_MTU; - chan->scid = L2CAP_CID_ATT; - chan->dcid = L2CAP_CID_ATT; + if (chan->dcid == L2CAP_CID_ATT) + chan->scid = L2CAP_CID_ATT; + else + chan->scid = l2cap_alloc_cid(conn); } else { /* Alloc CID for connection-oriented socket */ chan->scid = l2cap_alloc_cid(conn); @@ -1357,6 +1359,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!chan) goto clean; + chan->dcid = L2CAP_CID_ATT; + sk = chan->sk; hci_conn_hold(conn->hcon); -- GitLab From d8729922b474eab65ca738028a2e69fb12e2eaa6 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:39 +0300 Subject: [PATCH 1695/2900] Bluetooth: Add clarifying comment to l2cap_conn_ready() There is an extra call to smp_conn_security() for outgoing LE connections from l2cap_conn_ready() but the reason for this call is far from clear. After a bit of commit history research and using git blame I found out that this extra call is for socket-less pairing processes added by commit 160dc6ac1. This patch adds a clarifying comment to the code for this. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4803610187ed..417d17723ee9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1387,6 +1387,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) if (!hcon->out && hcon->type == LE_LINK) l2cap_le_conn_ready(conn); + /* For outgoing pairing which doesn't necessarily have an + * associated socket (e.g. mgmt_pair_device). + */ if (hcon->out && hcon->type == LE_LINK) smp_conn_security(hcon, hcon->pending_sec_level); -- GitLab From 97f57c0b14ad2ef0628fc6db48cd6c08e0e52c50 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:40 +0300 Subject: [PATCH 1696/2900] Bluetooth: Fix duplicate call to l2cap_chan_ready() In l2cap_le_conn_ready() after doing l2cap_chann_add() the LE channel is part of the list which is subsequently iterated in l2cap_conn_ready() in this loop each channel will get l2cap_chan_ready() called which would result in trying to set the channel two times into BT_CONNECTED state. Instead it makes sense to just add the channel but not call chan_ready in l2cap_le_conn_ready, which is what this patch does. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 417d17723ee9..843463ecd7bc 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1371,8 +1371,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) l2cap_chan_add(conn, chan); - l2cap_chan_ready(chan); - clean: release_sock(parent); } -- GitLab From 60bac184c9c7df2299aca4dc45c4b5b486f49a89 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:41 +0300 Subject: [PATCH 1697/2900] Bluetooth: Remove useless sk variable in l2cap_le_conn_ready The sk variable is of quite little use since it's only used to simplify access in the two bt_sk() calls. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 843463ecd7bc..1557c3c774f1 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1340,7 +1340,7 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, static void l2cap_le_conn_ready(struct l2cap_conn *conn) { - struct sock *parent, *sk; + struct sock *parent; struct l2cap_chan *chan, *pchan; BT_DBG(""); @@ -1361,13 +1361,11 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - sk = chan->sk; - hci_conn_hold(conn->hcon); conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; - bacpy(&bt_sk(sk)->src, conn->src); - bacpy(&bt_sk(sk)->dst, conn->dst); + bacpy(&bt_sk(chan->sk)->src, conn->src); + bacpy(&bt_sk(chan->sk)->dst, conn->dst); l2cap_chan_add(conn, chan); -- GitLab From af1c01349ecc2b8ab2c329e4dbd46e9018469bd1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:42 +0300 Subject: [PATCH 1698/2900] Bluetooth: Remove unnecessary L2CAP channel state check In l2cap_att_channel() we're only interested in the BT_CONNECTED state so this state can directly be passed to l2cap_global_chan_by_scid(). This way there's no need to do any additional state check later. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1557c3c774f1..55c6836796f7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6394,16 +6394,13 @@ static void l2cap_att_channel(struct l2cap_conn *conn, { struct l2cap_chan *chan; - chan = l2cap_global_chan_by_scid(0, L2CAP_CID_ATT, + chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, conn->src, conn->dst); if (!chan) goto drop; BT_DBG("chan %p, len %d", chan, skb->len); - if (chan->state != BT_BOUND && chan->state != BT_CONNECTED) - goto drop; - if (chan->imtu < skb->len) goto drop; -- GitLab From 5ee9891dd8a63df1bf2ccd437872ad30a5850449 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:43 +0300 Subject: [PATCH 1699/2900] Bluetooth: Simplify hci_conn_hold/drop logic for L2CAP The L2CAP code has been incrementing the hci_conn reference for each l2cap_chan instance in the l2cap_conn list. Likewise, the reference is dropped each time an l2cap_chan is removed from the list. The reference counting policy with respect to removal has been clear and explicit in the l2cap_chan_del function, however for addition the function calling 2cap_chan_add has always had to do a separate hci_conn_hold call. What made the counting even more hard to follow is that the hci_connect() procedure increments the reference and the L2CAP layer making this call took advantage of it to use it as its own reference. This patch aims to clarify things by having the call to hci_conn_hold inside __l2cap_chan_add, thereby removing the need to do it in the functions calling __l2cap_chan_add. The reference count for hci_connect is still kept as it's necessary for users such as mgmt_pair_device, however for the L2CAP layer it means that an extra call to hci_conn_drop must be performed once l2cap_chan_add has been done. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 55c6836796f7..d7b501ba2716 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -545,6 +545,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) l2cap_chan_hold(chan); + hci_conn_hold(conn->hcon); + list_add(&chan->list, &conn->chan_l); } @@ -1361,7 +1363,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - hci_conn_hold(conn->hcon); conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; bacpy(&bt_sk(chan->sk)->src, conn->src); @@ -1827,6 +1828,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, l2cap_chan_add(conn, chan); l2cap_chan_lock(chan); + /* l2cap_chan_add takes its own ref so we can drop this one */ + hci_conn_drop(hcon); + l2cap_state_change(chan, BT_CONNECT); __set_chan_timer(chan, sk->sk_sndtimeo); @@ -3748,8 +3752,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, sk = chan->sk; - hci_conn_hold(conn->hcon); - bacpy(&bt_sk(sk)->src, conn->src); bacpy(&bt_sk(sk)->dst, conn->dst); chan->psm = psm; -- GitLab From 0cc59a72c723979cf8973aff4df874a5f7a697c7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:44 +0300 Subject: [PATCH 1700/2900] Bluetooth: Remove useless hci_conn disc_timeout setting There's no need to reset disc_timeout in l2cap_le_conn_ready since HCI_DISCONN_TIMEOUT is the default when the hci_conn is created and there should be no way for it to get changed between creation and l2cap_le_conn_ready being called. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d7b501ba2716..8ae6a21cf643 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1363,8 +1363,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; - bacpy(&bt_sk(chan->sk)->src, conn->src); bacpy(&bt_sk(chan->sk)->dst, conn->dst); -- GitLab From 44f3b0fbaa9bfa7a88577ee8c446d0a78cb1d73a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 29 Apr 2013 19:35:45 +0300 Subject: [PATCH 1701/2900] Bluetooth: Fix multiple LE socket handling The LE ATT server socket needs to be superseded by any ATT client sockets. Previously this was done by looking at the hcon->out variable (indicating whether the connection is outgoing or incoming) which is a too crude way of determining whether the server socket needs to be picked or not (an outgoing connection doesn't necessarily mean that an ATT client socket has triggered it). This patch extends the ATT server socket lookup function (l2cap_le_conn_ready) to be used for all LE connections (regardless of the hcon->out value) and adds an internal check into the function for the existence of any ATT client sockets (in which case the server socket should be skipped). For this to work reliably all lookups must be done while the l2cap_conn->chan_lock is held, meaning also that the call to l2cap_chan_add needs to be changed to its lockless __l2cap_chan_add counterpart. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8ae6a21cf643..9af3a76844f7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1353,6 +1353,10 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) if (!pchan) return; + /* Client ATT sockets should override the server one */ + if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) + return; + parent = pchan->sk; lock_sock(parent); @@ -1366,7 +1370,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) bacpy(&bt_sk(chan->sk)->src, conn->src); bacpy(&bt_sk(chan->sk)->dst, conn->dst); - l2cap_chan_add(conn, chan); + __l2cap_chan_add(conn, chan); clean: release_sock(parent); @@ -1379,9 +1383,6 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) BT_DBG("conn %p", conn); - if (!hcon->out && hcon->type == LE_LINK) - l2cap_le_conn_ready(conn); - /* For outgoing pairing which doesn't necessarily have an * associated socket (e.g. mgmt_pair_device). */ @@ -1390,6 +1391,9 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) mutex_lock(&conn->chan_lock); + if (hcon->type == LE_LINK) + l2cap_le_conn_ready(conn); + list_for_each_entry(chan, &conn->chan_l, list) { l2cap_chan_lock(chan); -- GitLab From 1f9b9a5dc5bb8ee360db9d32b2090aac497ae82a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:27 -0300 Subject: [PATCH 1702/2900] Bluetooth: Make inquiry_cache_flush non-static In order to use HCI request framework in start_discovery, we'll need to call inquiry_cache_flush in mgmt.c. Therefore, this patch adds the hci_ prefix to inquiry_cache_flush and makes it non-static. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7cb6d360d147..7c150e4d65b9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -432,6 +432,7 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev, struct inquiry_entry *ie); bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, bool name_known, bool *ssp); +void hci_inquiry_cache_flush(struct hci_dev *hdev); /* ----- HCI Connections ----- */ enum { diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ace5e55fe5a3..43c63877c5b7 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -751,7 +751,7 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state) hdev->discovery.state = state; } -static void inquiry_cache_flush(struct hci_dev *hdev) +void hci_inquiry_cache_flush(struct hci_dev *hdev) { struct discovery_state *cache = &hdev->discovery; struct inquiry_entry *p, *n; @@ -964,7 +964,7 @@ int hci_inquiry(void __user *arg) hci_dev_lock(hdev); if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { - inquiry_cache_flush(hdev); + hci_inquiry_cache_flush(hdev); do_inquiry = 1; } hci_dev_unlock(hdev); @@ -1230,7 +1230,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) cancel_delayed_work_sync(&hdev->le_scan_disable); hci_dev_lock(hdev); - inquiry_cache_flush(hdev); + hci_inquiry_cache_flush(hdev); hci_conn_hash_flush(hdev); hci_dev_unlock(hdev); @@ -1331,7 +1331,7 @@ int hci_dev_reset(__u16 dev) skb_queue_purge(&hdev->cmd_q); hci_dev_lock(hdev); - inquiry_cache_flush(hdev); + hci_inquiry_cache_flush(hdev); hci_conn_hash_flush(hdev); hci_dev_unlock(hdev); @@ -3562,7 +3562,7 @@ int hci_do_inquiry(struct hci_dev *hdev, u8 length) if (test_bit(HCI_INQUIRY, &hdev->flags)) return -EINPROGRESS; - inquiry_cache_flush(hdev); + hci_inquiry_cache_flush(hdev); memset(&cp, 0, sizeof(cp)); memcpy(&cp.lap, lap, sizeof(cp.lap)); -- GitLab From 7c3077207c705d0aa200ce22d49a0376d194dfca Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:28 -0300 Subject: [PATCH 1703/2900] Bluetooth: Update start_discovery to use HCI request This patch modifies the start_discovery function so it uses the HCI request framework. We build the HCI request according to the discovery type (add inquiry or LE scan HCI commands) and run the HCI request. We also register the start_discovery_complete callback which handles mgmt command complete events for this command. This way, we move all start_ discovery mgmt handling code spread in hci_event.c to a single place in mgmt.c. This patch also merges the LE-only and interleaved discovery type cases since these cases are pretty much the same now. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 94 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f8ecbc70293d..434df715448e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2650,11 +2650,51 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev) return err; } +static void start_discovery_complete(struct hci_dev *hdev, u8 status) +{ + BT_DBG("status %d", status); + + if (status) { + hci_dev_lock(hdev); + mgmt_start_discovery_failed(hdev, status); + hci_dev_unlock(hdev); + return; + } + + hci_dev_lock(hdev); + hci_discovery_set_state(hdev, DISCOVERY_FINDING); + hci_dev_unlock(hdev); + + switch (hdev->discovery.type) { + case DISCOV_TYPE_LE: + queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, + LE_SCAN_TIMEOUT_LE_ONLY); + break; + + case DISCOV_TYPE_INTERLEAVED: + queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, + LE_SCAN_TIMEOUT_BREDR_LE); + break; + + case DISCOV_TYPE_BREDR: + break; + + default: + BT_ERR("Invalid discovery type %d", hdev->discovery.type); + } +} + static int start_discovery(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_cp_start_discovery *cp = data; struct pending_cmd *cmd; + struct hci_cp_le_set_scan_param param_cp; + struct hci_cp_le_set_scan_enable enable_cp; + struct hci_cp_inquiry inq_cp; + struct hci_request req; + /* General inquiry access code (GIAC) */ + u8 lap[3] = { 0x33, 0x8b, 0x9e }; int err; BT_DBG("%s", hdev->name); @@ -2687,6 +2727,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, hdev->discovery.type = cp->type; + hci_req_init(&req, hdev); + switch (hdev->discovery.type) { case DISCOV_TYPE_BREDR: if (!lmp_bredr_capable(hdev)) { @@ -2696,10 +2738,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, goto failed; } - err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR); + if (test_bit(HCI_INQUIRY, &hdev->flags)) { + err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_BUSY); + mgmt_pending_remove(cmd); + goto failed; + } + + hci_inquiry_cache_flush(hdev); + + memset(&inq_cp, 0, sizeof(inq_cp)); + memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap)); + inq_cp.length = INQUIRY_LEN_BREDR; + hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp); break; case DISCOV_TYPE_LE: + case DISCOV_TYPE_INTERLEAVED: if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, MGMT_STATUS_NOT_SUPPORTED); @@ -2707,20 +2762,40 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, goto failed; } - err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT, - LE_SCAN_WIN, LE_SCAN_TIMEOUT_LE_ONLY); - break; - - case DISCOV_TYPE_INTERLEAVED: - if (!lmp_host_le_capable(hdev) || !lmp_bredr_capable(hdev)) { + if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && + !lmp_bredr_capable(hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, MGMT_STATUS_NOT_SUPPORTED); mgmt_pending_remove(cmd); goto failed; } - err = hci_le_scan(hdev, LE_SCAN_ACTIVE, LE_SCAN_INT, - LE_SCAN_WIN, LE_SCAN_TIMEOUT_BREDR_LE); + if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_REJECTED); + mgmt_pending_remove(cmd); + goto failed; + } + + if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { + err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_BUSY); + mgmt_pending_remove(cmd); + goto failed; + } + + memset(¶m_cp, 0, sizeof(param_cp)); + param_cp.type = LE_SCAN_ACTIVE; + param_cp.interval = cpu_to_le16(LE_SCAN_INT); + param_cp.window = cpu_to_le16(LE_SCAN_WIN); + hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), + ¶m_cp); + + memset(&enable_cp, 0, sizeof(enable_cp)); + enable_cp.enable = LE_SCAN_ENABLE; + enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), + &enable_cp); break; default: @@ -2730,6 +2805,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, goto failed; } + err = hci_req_run(&req, start_discovery_complete); if (err < 0) mgmt_pending_remove(cmd); else -- GitLab From fef5234a791507a2fe1ccfc85f080523fe762320 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:29 -0300 Subject: [PATCH 1704/2900] Bluetooth: Remove start discovery handling from hci_event.c Since all mgmt start discovery command complete events are now handled in start_discovery_complete callback in mgmt.c, we can remove this handling from hci_event.c. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b93cd2eb5d58..0e71e6c47391 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -943,12 +943,6 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%2.2x", hdev->name, status); - if (status) { - hci_dev_lock(hdev); - mgmt_start_discovery_failed(hdev, status); - hci_dev_unlock(hdev); - return; - } } static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, @@ -965,18 +959,10 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, switch (cp->enable) { case LE_SCAN_ENABLE: - if (status) { - hci_dev_lock(hdev); - mgmt_start_discovery_failed(hdev, status); - hci_dev_unlock(hdev); + if (status) return; - } set_bit(HCI_LE_SCAN, &hdev->dev_flags); - - hci_dev_lock(hdev); - hci_discovery_set_state(hdev, DISCOVERY_FINDING); - hci_dev_unlock(hdev); break; case LE_SCAN_DISABLE: @@ -1077,18 +1063,10 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) if (status) { hci_conn_check_pending(hdev); - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags)) - mgmt_start_discovery_failed(hdev, status); - hci_dev_unlock(hdev); return; } set_bit(HCI_INQUIRY, &hdev->flags); - - hci_dev_lock(hdev); - hci_discovery_set_state(hdev, DISCOVERY_FINDING); - hci_dev_unlock(hdev); } static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) -- GitLab From 41dc2bd6d13bfccc34d05586be2eb65876a5990a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:30 -0300 Subject: [PATCH 1705/2900] Bluetooth: Make mgmt_start_discovery_failed static mgmt_start_discovery_failed is now only used in mgmt.c so we can make it a local function. This patch also moves the mgmt_start_ discovery_failed definition up in mgmt.c to avoid forward declaration. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/mgmt.c | 42 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7c150e4d65b9..ff4e8a5c9ceb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1170,7 +1170,6 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 ssp, u8 *eir, u16 eir_len); int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, s8 rssi, u8 *name, u8 name_len); -int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_interleaved_discovery(struct hci_dev *hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 434df715448e..a9bd271a736e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2650,6 +2650,27 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev) return err; } +static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) +{ + struct pending_cmd *cmd; + u8 type; + int err; + + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + + cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); + if (!cmd) + return -ENOENT; + + type = hdev->discovery.type; + + err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), + &type, sizeof(type)); + mgmt_pending_remove(cmd); + + return err; +} + static void start_discovery_complete(struct hci_dev *hdev, u8 status) { BT_DBG("status %d", status); @@ -4190,27 +4211,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, sizeof(*ev) + eir_len, NULL); } -int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) -{ - struct pending_cmd *cmd; - u8 type; - int err; - - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - - cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev); - if (!cmd) - return -ENOENT; - - type = hdev->discovery.type; - - err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), - &type, sizeof(type)); - mgmt_pending_remove(cmd); - - return err; -} - int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; -- GitLab From 0d8cc935e01c0fd1312a10881f4c0f1c4b4d05ab Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:31 -0300 Subject: [PATCH 1706/2900] Bluetooth: Move discovery macros to hci_core.h Some of discovery macros will be used in hci_core so we need to define them in common place such as hci_core.h. Thus, this patch moves discovery macros to hci_core.h and also adds the DISCOV_ prefix to them. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 10 ++++++++++ net/bluetooth/mgmt.c | 24 ++++++------------------ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ff4e8a5c9ceb..61939a0e6cec 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1115,6 +1115,16 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); BIT(BDADDR_LE_PUBLIC) | \ BIT(BDADDR_LE_RANDOM)) +/* These LE scan and inquiry parameters were chosen according to LE General + * Discovery Procedure specification. + */ +#define DISCOV_LE_SCAN_WIN 0x12 +#define DISCOV_LE_SCAN_INT 0x12 +#define DISCOV_LE_TIMEOUT msecs_to_jiffies(10240) +#define DISCOV_INTERLEAVED_TIMEOUT msecs_to_jiffies(5120) +#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04 +#define DISCOV_BREDR_INQUIRY_LEN 0x08 + int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_index_added(struct hci_dev *hdev); int mgmt_index_removed(struct hci_dev *hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a9bd271a736e..6b31e93af761 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -102,18 +102,6 @@ static const u16 mgmt_events[] = { MGMT_EV_PASSKEY_NOTIFY, }; -/* - * These LE scan and inquiry parameters were chosen according to LE General - * Discovery Procedure specification. - */ -#define LE_SCAN_WIN 0x12 -#define LE_SCAN_INT 0x12 -#define LE_SCAN_TIMEOUT_LE_ONLY msecs_to_jiffies(10240) -#define LE_SCAN_TIMEOUT_BREDR_LE msecs_to_jiffies(5120) - -#define INQUIRY_LEN_BREDR 0x08 /* TGAP(100) */ -#define INQUIRY_LEN_BREDR_LE 0x04 /* TGAP(100)/2 */ - #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) #define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \ @@ -2641,7 +2629,7 @@ int mgmt_interleaved_discovery(struct hci_dev *hdev) hci_dev_lock(hdev); - err = hci_do_inquiry(hdev, INQUIRY_LEN_BREDR_LE); + err = hci_do_inquiry(hdev, DISCOV_INTERLEAVED_INQUIRY_LEN); if (err < 0) hci_discovery_set_state(hdev, DISCOVERY_STOPPED); @@ -2689,12 +2677,12 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status) switch (hdev->discovery.type) { case DISCOV_TYPE_LE: queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, - LE_SCAN_TIMEOUT_LE_ONLY); + DISCOV_LE_TIMEOUT); break; case DISCOV_TYPE_INTERLEAVED: queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, - LE_SCAN_TIMEOUT_BREDR_LE); + DISCOV_INTERLEAVED_TIMEOUT); break; case DISCOV_TYPE_BREDR: @@ -2770,7 +2758,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, memset(&inq_cp, 0, sizeof(inq_cp)); memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap)); - inq_cp.length = INQUIRY_LEN_BREDR; + inq_cp.length = DISCOV_BREDR_INQUIRY_LEN; hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp); break; @@ -2807,8 +2795,8 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, memset(¶m_cp, 0, sizeof(param_cp)); param_cp.type = LE_SCAN_ACTIVE; - param_cp.interval = cpu_to_le16(LE_SCAN_INT); - param_cp.window = cpu_to_le16(LE_SCAN_WIN); + param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); + param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), ¶m_cp); -- GitLab From 4c87eaab01df271c81f6a68e3c28dbd44d348004 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:32 -0300 Subject: [PATCH 1707/2900] Bluetooth: Use HCI request in interleaved discovery In order to have a better HCI error handling in interleaved discovery functionality, we should use the HCI request framework. This patch updates le_scan_disable_work function so it uses the HCI request framework instead of the hci_send_cmd helper. A complete callback is registered (le_scan_disable_work_complete function) so we are able to trigger the inquiry procedure (if we are running the interleaved discovery) or to stop the discovery procedure (if we are running LE-only discovery). This patch also removes the extra logic in hci_cc_le_set_scan_enable to trigger the inquiry procedure and the mgmt_interleaved_discovery function since they become useless. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_core.c | 65 +++++++++++++++++++++++++++++++- net/bluetooth/hci_event.c | 10 ----- net/bluetooth/mgmt.c | 17 --------- 4 files changed, 64 insertions(+), 29 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 61939a0e6cec..b3bdad24c2b9 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1182,7 +1182,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, s8 rssi, u8 *name, u8 name_len); int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); -int mgmt_interleaved_discovery(struct hci_dev *hdev); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); bool mgmt_valid_hdev(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 43c63877c5b7..9270d7ee489d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2067,17 +2067,80 @@ int hci_cancel_le_scan(struct hci_dev *hdev) return 0; } +static void inquiry_complete(struct hci_dev *hdev, u8 status) +{ + if (status) { + BT_ERR("Failed to start inquiry: status %d", status); + + hci_dev_lock(hdev); + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + hci_dev_unlock(hdev); + return; + } +} + +static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status) +{ + /* General inquiry access code (GIAC) */ + u8 lap[3] = { 0x33, 0x8b, 0x9e }; + struct hci_request req; + struct hci_cp_inquiry cp; + int err; + + if (status) { + BT_ERR("Failed to disable LE scanning: status %d", status); + return; + } + + switch (hdev->discovery.type) { + case DISCOV_TYPE_LE: + hci_dev_lock(hdev); + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + hci_dev_unlock(hdev); + break; + + case DISCOV_TYPE_INTERLEAVED: + hci_req_init(&req, hdev); + + memset(&cp, 0, sizeof(cp)); + memcpy(&cp.lap, lap, sizeof(cp.lap)); + cp.length = DISCOV_INTERLEAVED_INQUIRY_LEN; + hci_req_add(&req, HCI_OP_INQUIRY, sizeof(cp), &cp); + + hci_dev_lock(hdev); + + hci_inquiry_cache_flush(hdev); + + err = hci_req_run(&req, inquiry_complete); + if (err) { + BT_ERR("Inquiry request failed: err %d", err); + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + } + + hci_dev_unlock(hdev); + break; + } +} + static void le_scan_disable_work(struct work_struct *work) { struct hci_dev *hdev = container_of(work, struct hci_dev, le_scan_disable.work); struct hci_cp_le_set_scan_enable cp; + struct hci_request req; + int err; BT_DBG("%s", hdev->name); + hci_req_init(&req, hdev); + memset(&cp, 0, sizeof(cp)); + cp.enable = LE_SCAN_DISABLE; + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); - hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); + err = hci_req_run(&req, le_scan_disable_work_complete); + if (err) + BT_ERR("Disable LE scanning request failed: err %d", err); } static void le_scan_work(struct work_struct *work) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0e71e6c47391..faaf1f31345d 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -974,16 +974,6 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, } clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - - if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && - hdev->discovery.state == DISCOVERY_FINDING) { - mgmt_interleaved_discovery(hdev); - } else { - hci_dev_lock(hdev); - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - hci_dev_unlock(hdev); - } - break; default: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 6b31e93af761..743100f3ab9c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2621,23 +2621,6 @@ static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev, return err; } -int mgmt_interleaved_discovery(struct hci_dev *hdev) -{ - int err; - - BT_DBG("%s", hdev->name); - - hci_dev_lock(hdev); - - err = hci_do_inquiry(hdev, DISCOV_INTERLEAVED_INQUIRY_LEN); - if (err < 0) - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - - hci_dev_unlock(hdev); - - return err; -} - static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; -- GitLab From 0e05bba6f6f8c2dca7a13fe0566742277e92df07 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:33 -0300 Subject: [PATCH 1708/2900] Bluetooth: Update stop_discovery to use HCI request This patch modifies the stop_discovery function so it uses the HCI request framework. The HCI request is built according to the current discovery state (inquiry, LE scanning or name resolving) and a complete callback is register to handle the command complete event for the stop discovery command. This way, we move all stop_discovery mgmt handling code spread in hci_event.c to a single place in mgmt.c. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 47 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 743100f3ab9c..c33bc4f4d006 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2808,6 +2808,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, return err; } +static void stop_discovery_complete(struct hci_dev *hdev, u8 status) +{ + BT_DBG("status %d", status); + + hci_dev_lock(hdev); + + if (status) { + mgmt_stop_discovery_failed(hdev, status); + goto unlock; + } + + hci_discovery_set_state(hdev, DISCOVERY_STOPPED); + +unlock: + hci_dev_unlock(hdev); +} + static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { @@ -2815,6 +2832,8 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, struct pending_cmd *cmd; struct hci_cp_remote_name_req_cancel cp; struct inquiry_entry *e; + struct hci_request req; + struct hci_cp_le_set_scan_enable enable_cp; int err; BT_DBG("%s", hdev->name); @@ -2841,12 +2860,20 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, goto unlock; } + hci_req_init(&req, hdev); + switch (hdev->discovery.state) { case DISCOVERY_FINDING: - if (test_bit(HCI_INQUIRY, &hdev->flags)) - err = hci_cancel_inquiry(hdev); - else - err = hci_cancel_le_scan(hdev); + if (test_bit(HCI_INQUIRY, &hdev->flags)) { + hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL); + } else { + cancel_delayed_work(&hdev->le_scan_disable); + + memset(&enable_cp, 0, sizeof(enable_cp)); + enable_cp.enable = LE_SCAN_DISABLE; + hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, + sizeof(enable_cp), &enable_cp); + } break; @@ -2864,16 +2891,22 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, } bacpy(&cp.bdaddr, &e->data.bdaddr); - err = hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ_CANCEL, - sizeof(cp), &cp); + hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), + &cp); break; default: BT_DBG("unknown discovery state %u", hdev->discovery.state); - err = -EFAULT; + + mgmt_pending_remove(cmd); + err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, + MGMT_STATUS_FAILED, &mgmt_cp->type, + sizeof(mgmt_cp->type)); + goto unlock; } + err = hci_req_run(&req, stop_discovery_complete); if (err < 0) mgmt_pending_remove(cmd); else -- GitLab From 82f4785ca7b8d04ca6d0aaa37f1185c779744bc4 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:34 -0300 Subject: [PATCH 1709/2900] Bluetooth: Remove stop discovery handling from hci_event.c Since all mgmt stop discovery command complete events are now handled in stop_discovery_complete callback in mgmt.c, we can remove this handling from hci_event.c. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index faaf1f31345d..27f66dc88c9b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -40,21 +40,13 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%2.2x", hdev->name, status); - if (status) { - hci_dev_lock(hdev); - mgmt_stop_discovery_failed(hdev, status); - hci_dev_unlock(hdev); + if (status) return; - } clear_bit(HCI_INQUIRY, &hdev->flags); smp_mb__after_clear_bit(); /* wake_up_bit advises about this barrier */ wake_up_bit(&hdev->flags, HCI_INQUIRY); - hci_dev_lock(hdev); - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - hci_dev_unlock(hdev); - hci_conn_check_pending(hdev); } @@ -966,12 +958,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, break; case LE_SCAN_DISABLE: - if (status) { - hci_dev_lock(hdev); - mgmt_stop_discovery_failed(hdev, status); - hci_dev_unlock(hdev); + if (status) return; - } clear_bit(HCI_LE_SCAN, &hdev->dev_flags); break; -- GitLab From 1183fdcad42495073045a2d9755e0a6ac2fa874e Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:35 -0300 Subject: [PATCH 1710/2900] Bluetooth: Make mgmt_stop_discovery_failed static mgmt_stop_discovery_failed is now only used in mgmt.c so we can make it a local function. This patch also moves the mgmt_stop_ discovery_failed definition up in mgmt.c to avoid forward declaration. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/mgmt.c | 32 ++++++++++++++++---------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b3bdad24c2b9..1b343ef37871 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1180,7 +1180,6 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 ssp, u8 *eir, u16 eir_len); int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, s8 rssi, u8 *name, u8 name_len); -int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c33bc4f4d006..69d17205745b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2808,6 +2808,22 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, return err; } +static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) +{ + struct pending_cmd *cmd; + int err; + + cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); + if (!cmd) + return -ENOENT; + + err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), + &hdev->discovery.type, sizeof(hdev->discovery.type)); + mgmt_pending_remove(cmd); + + return err; +} + static void stop_discovery_complete(struct hci_dev *hdev, u8 status) { BT_DBG("status %d", status); @@ -4215,22 +4231,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, sizeof(*ev) + eir_len, NULL); } -int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) -{ - struct pending_cmd *cmd; - int err; - - cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); - if (!cmd) - return -ENOENT; - - err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status), - &hdev->discovery.type, sizeof(hdev->discovery.type)); - mgmt_pending_remove(cmd); - - return err; -} - int mgmt_discovering(struct hci_dev *hdev, u8 discovering) { struct mgmt_ev_discovering ev; -- GitLab From 3fd319b830247a3fe5f489e622ab404b618e0906 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:36 -0300 Subject: [PATCH 1711/2900] Bluetooth: Refactor hci_cc_le_set_scan_enable This patch does a trivial refactoring in hci_cc_le_set_scan_enable. Since start and stop discovery command failures are now handled in mgmt layer, the status check became empty. So, we can move it to outside the switch statement. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 27f66dc88c9b..76ff1af05693 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -949,18 +949,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, if (!cp) return; + if (status) + return; + switch (cp->enable) { case LE_SCAN_ENABLE: - if (status) - return; - set_bit(HCI_LE_SCAN, &hdev->dev_flags); break; case LE_SCAN_DISABLE: - if (status) - return; - clear_bit(HCI_LE_SCAN, &hdev->dev_flags); break; -- GitLab From 917eedc56c65ba96a3bab4c346d948e73dd872f1 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:37 -0300 Subject: [PATCH 1712/2900] Bluetooth: Remove LE scan helpers This patch removes the LE scan helpers hci_le_scan and hci_cancel_ le_scan and all code related to it. We now use the HCI request framework in device discovery functionality and these helpers are no longer needed. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 13 ---- net/bluetooth/hci_core.c | 113 ------------------------------- 2 files changed, 126 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1b343ef37871..5de7eb95ef63 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -117,13 +117,6 @@ struct oob_data { u8 randomizer[16]; }; -struct le_scan_params { - u8 type; - u16 interval; - u16 window; - int timeout; -}; - #define HCI_MAX_SHORT_NAME_LENGTH 10 struct amp_assoc { @@ -283,9 +276,6 @@ struct hci_dev { struct delayed_work le_scan_disable; - struct work_struct le_scan; - struct le_scan_params le_scan_params; - __s8 adv_tx_power; __u8 adv_data[HCI_MAX_AD_LENGTH]; __u8 adv_data_len; @@ -1222,9 +1212,6 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], __u8 ltk[16]); int hci_do_inquiry(struct hci_dev *hdev, u8 length); int hci_cancel_inquiry(struct hci_dev *hdev); -int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window, - int timeout); -int hci_cancel_le_scan(struct hci_dev *hdev); u8 bdaddr_to_le(u8 bdaddr_type); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9270d7ee489d..100539fcbfe5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1201,8 +1201,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) { BT_DBG("%s %p", hdev->name, hdev); - cancel_work_sync(&hdev->le_scan); - cancel_delayed_work(&hdev->power_off); hci_req_cancel(hdev, ENODEV); @@ -1991,82 +1989,6 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) return mgmt_device_unblocked(hdev, bdaddr, type); } -static void le_scan_param_req(struct hci_request *req, unsigned long opt) -{ - struct le_scan_params *param = (struct le_scan_params *) opt; - struct hci_cp_le_set_scan_param cp; - - memset(&cp, 0, sizeof(cp)); - cp.type = param->type; - cp.interval = cpu_to_le16(param->interval); - cp.window = cpu_to_le16(param->window); - - hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(cp), &cp); -} - -static void le_scan_enable_req(struct hci_request *req, unsigned long opt) -{ - struct hci_cp_le_set_scan_enable cp; - - memset(&cp, 0, sizeof(cp)); - cp.enable = LE_SCAN_ENABLE; - cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; - - hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); -} - -static int hci_do_le_scan(struct hci_dev *hdev, u8 type, u16 interval, - u16 window, int timeout) -{ - long timeo = msecs_to_jiffies(3000); - struct le_scan_params param; - int err; - - BT_DBG("%s", hdev->name); - - if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) - return -EINPROGRESS; - - param.type = type; - param.interval = interval; - param.window = window; - - hci_req_lock(hdev); - - err = __hci_req_sync(hdev, le_scan_param_req, (unsigned long) ¶m, - timeo); - if (!err) - err = __hci_req_sync(hdev, le_scan_enable_req, 0, timeo); - - hci_req_unlock(hdev); - - if (err < 0) - return err; - - queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, - timeout); - - return 0; -} - -int hci_cancel_le_scan(struct hci_dev *hdev) -{ - BT_DBG("%s", hdev->name); - - if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) - return -EALREADY; - - if (cancel_delayed_work(&hdev->le_scan_disable)) { - struct hci_cp_le_set_scan_enable cp; - - /* Send HCI command to disable LE Scan */ - memset(&cp, 0, sizeof(cp)); - hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); - } - - return 0; -} - static void inquiry_complete(struct hci_dev *hdev, u8 status) { if (status) { @@ -2143,40 +2065,6 @@ static void le_scan_disable_work(struct work_struct *work) BT_ERR("Disable LE scanning request failed: err %d", err); } -static void le_scan_work(struct work_struct *work) -{ - struct hci_dev *hdev = container_of(work, struct hci_dev, le_scan); - struct le_scan_params *param = &hdev->le_scan_params; - - BT_DBG("%s", hdev->name); - - hci_do_le_scan(hdev, param->type, param->interval, param->window, - param->timeout); -} - -int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window, - int timeout) -{ - struct le_scan_params *param = &hdev->le_scan_params; - - BT_DBG("%s", hdev->name); - - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) - return -ENOTSUPP; - - if (work_busy(&hdev->le_scan)) - return -EINPROGRESS; - - param->type = type; - param->interval = interval; - param->window = window; - param->timeout = timeout; - - queue_work(system_long_wq, &hdev->le_scan); - - return 0; -} - /* Alloc HCI device */ struct hci_dev *hci_alloc_dev(void) { @@ -2211,7 +2099,6 @@ struct hci_dev *hci_alloc_dev(void) INIT_WORK(&hdev->cmd_work, hci_cmd_work); INIT_WORK(&hdev->tx_work, hci_tx_work); INIT_WORK(&hdev->power_on, hci_power_on); - INIT_WORK(&hdev->le_scan, le_scan_work); INIT_DELAYED_WORK(&hdev->power_off, hci_power_off); INIT_DELAYED_WORK(&hdev->discov_off, hci_discov_off); -- GitLab From b0434345f2a7330be5277b63606cff26a7965982 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:38 -0300 Subject: [PATCH 1713/2900] Bluetooth: Remove inquiry helpers This patch removes hci_do_inquiry and hci_cancel_inquiry helpers. We now use the HCI request framework in device discovery functionality and these helpers are no longer needed. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci_core.h | 2 -- net/bluetooth/hci_core.c | 30 ------------------------------ 2 files changed, 32 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5de7eb95ef63..f77885ea78c2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1210,8 +1210,6 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, u16 to_multiplier); void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], __u8 ltk[16]); -int hci_do_inquiry(struct hci_dev *hdev, u8 length); -int hci_cancel_inquiry(struct hci_dev *hdev); u8 bdaddr_to_le(u8 bdaddr_type); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 100539fcbfe5..e2e9d409d0f6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3501,36 +3501,6 @@ static void hci_cmd_work(struct work_struct *work) } } -int hci_do_inquiry(struct hci_dev *hdev, u8 length) -{ - /* General inquiry access code (GIAC) */ - u8 lap[3] = { 0x33, 0x8b, 0x9e }; - struct hci_cp_inquiry cp; - - BT_DBG("%s", hdev->name); - - if (test_bit(HCI_INQUIRY, &hdev->flags)) - return -EINPROGRESS; - - hci_inquiry_cache_flush(hdev); - - memset(&cp, 0, sizeof(cp)); - memcpy(&cp.lap, lap, sizeof(cp.lap)); - cp.length = length; - - return hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp); -} - -int hci_cancel_inquiry(struct hci_dev *hdev) -{ - BT_DBG("%s", hdev->name); - - if (!test_bit(HCI_INQUIRY, &hdev->flags)) - return -EALREADY; - - return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); -} - u8 bdaddr_to_le(u8 bdaddr_type) { switch (bdaddr_type) { -- GitLab From 8892d8beb37cb4ea531a5076946d5cc809b04c25 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:39 -0300 Subject: [PATCH 1714/2900] Bluetooth: Remove empty event handler This patch removes the hci_cc_le_set_scan_param event handler. This handler became empty because failures of this event are now handled by start_discovery_complete function in mgmt.c. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 76ff1af05693..db58e72316b9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -929,14 +929,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) -{ - __u8 status = *((__u8 *) skb->data); - - BT_DBG("%s status 0x%2.2x", hdev->name, status); - -} - static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { @@ -2251,10 +2243,6 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cc_user_passkey_neg_reply(hdev, skb); break; - case HCI_OP_LE_SET_SCAN_PARAM: - hci_cc_le_set_scan_param(hdev, skb); - break; - case HCI_OP_LE_SET_ADV_ENABLE: hci_cc_le_set_adv_enable(hdev, skb); break; -- GitLab From 12602d0cc005354a519b3eba443d7912ab71313a Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 30 Apr 2013 15:29:40 -0300 Subject: [PATCH 1715/2900] Bluetooth: Mgmt Device Found Event We only want to send Mgmt Device Found Events if we are running the Device Discovery procedure (started by the MGMT Start Discovery Command). Inquiry or LE scanning triggered by HCI raw interface (e.g. hcitool) or kernel internals should not send Mgmt Device Found Events. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 69d17205745b..7ae737fcf5e7 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4180,6 +4180,9 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, struct mgmt_ev_device_found *ev = (void *) buf; size_t ev_size; + if (!hci_discovery_active(hdev)) + return -EPERM; + /* Leave 5 bytes for a potential CoD field */ if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) return -EINVAL; -- GitLab From 034cbea0931433cf88a1f79a385402604f08bd67 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 14 May 2013 11:44:16 +0300 Subject: [PATCH 1716/2900] Bluetooth: Use HCI_MGMT instead of HCI_LINK_KEYS flag Use HCI_MGMT flag instead of HCI_LINK_KEYS flag. There is a problem with HCI_LINK_KEYS flag since it is set only when link keys are loaded. Otherwise kernel assumes that old interface is used. Signed-off-by: Andrei Emeltchenko Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index db58e72316b9..0437200d92f4 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2611,7 +2611,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s", hdev->name); - if (!test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) + if (!test_bit(HCI_MGMT, &hdev->dev_flags)) return; hci_dev_lock(hdev); @@ -2687,7 +2687,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_conn_drop(conn); } - if (test_bit(HCI_LINK_KEYS, &hdev->dev_flags)) + if (test_bit(HCI_MGMT, &hdev->dev_flags)) hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, ev->key_type, pin_len); -- GitLab From 0a804654af62dfea4899c66561d74d72273b2921 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 14 May 2013 11:44:17 +0300 Subject: [PATCH 1717/2900] Bluetooth: Remove unneeded flag Remove HCI_LINK_KEYS flag since using HCI_MGMT is enough for test that user space expects the kernel managing link keys. Signed-off-by: Andrei Emeltchenko Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 1 - net/bluetooth/mgmt.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index e0512aaef4b8..3c592cf473da 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -107,7 +107,6 @@ enum { HCI_MGMT, HCI_PAIRABLE, HCI_SERVICE_CACHE, - HCI_LINK_KEYS, HCI_DEBUG_KEYS, HCI_UNREGISTER, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7ae737fcf5e7..fedc5399d465 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1736,8 +1736,6 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, hci_link_keys_clear(hdev); - set_bit(HCI_LINK_KEYS, &hdev->dev_flags); - if (cp->debug_keys) set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); else -- GitLab From 673e1dd7ed7701cac8c5c247d152fd3d2da2a4f1 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 13 May 2013 10:07:11 +0800 Subject: [PATCH 1718/2900] Bluetooth: hidp: using strlcpy instead of strncpy, also beautify code. For NULL terminated string, need always let it ended by zero. Since have already called memcpy() to initialize 'ci', so need not redundant initialization. Better use ''if(session->hid) {} else if(session->input) {}"" instead of ''if(session->hid) {}; if(session->input) {};'' Signed-off-by: Chen Gang Reviewed-by: David Herrmann Acked-by: Jiri Kosina Signed-off-by: Gustavo Padovan --- net/bluetooth/hidp/core.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 940f5acb6694..f13a8da441a8 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -76,25 +76,19 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo ci->flags = session->flags; ci->state = BT_CONNECTED; - ci->vendor = 0x0000; - ci->product = 0x0000; - ci->version = 0x0000; - if (session->input) { ci->vendor = session->input->id.vendor; ci->product = session->input->id.product; ci->version = session->input->id.version; if (session->input->name) - strncpy(ci->name, session->input->name, 128); + strlcpy(ci->name, session->input->name, 128); else - strncpy(ci->name, "HID Boot Device", 128); - } - - if (session->hid) { + strlcpy(ci->name, "HID Boot Device", 128); + } else if (session->hid) { ci->vendor = session->hid->vendor; ci->product = session->hid->product; ci->version = session->hid->version; - strncpy(ci->name, session->hid->name, 128); + strlcpy(ci->name, session->hid->name, 128); } } -- GitLab From 502f769662978a2fe99d0caed5e53e3006107381 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 21 May 2013 09:32:06 -0600 Subject: [PATCH 1719/2900] Bluetooth: Add missing reset_resume dev_pm_ops Add missing reset_resume dev_pm_ops. Missing reset_resume results in the following message after power management device test. This change sets reset_resume to btusb_resume(). [ 2506.936134] btusb 1-1.5:1.0: no reset_resume for driver btusb? [ 2506.936137] btusb 1-1.5:1.1: no reset_resume for driver btusb? Signed-off-by: Shuah Khan Signed-off-by: Gustavo Padovan --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 81f12757a842..de4cf4daa2f4 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -1619,6 +1619,7 @@ static struct usb_driver btusb_driver = { #ifdef CONFIG_PM .suspend = btusb_suspend, .resume = btusb_resume, + .reset_resume = btusb_resume, #endif .id_table = btusb_table, .supports_autosuspend = 1, -- GitLab From b8f4e068004859eefac7b1ced59ddb67ca6d2d80 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 13 Jun 2013 12:34:31 +0100 Subject: [PATCH 1720/2900] Bluetooth: Improve comments on the HCI_Delete_Store_Link_Key issue Some Bluetooth controllers doesn't support this command so we first need to check for its support before sending it. This patch adds a lengthful commentary about this. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e2e9d409d0f6..061523eb52a1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -597,7 +597,15 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) struct hci_dev *hdev = req->hdev; u8 p; - /* Only send HCI_Delete_Stored_Link_Key if it is supported */ + /* Some Broadcom based Bluetooth controllers do not support the + * Delete Stored Link Key command. They are clearly indicating its + * absence in the bit mask of supported commands. + * + * Check the supported commands and only if the the command is marked + * as supported send it. If not supported assume that the controller + * does not have actual support for stored link keys which makes this + * command redundant anyway. + */ if (hdev->commands[6] & 0x80) { struct hci_cp_delete_stored_link_key cp; -- GitLab From c6a8af50b89e78f7f429f6189d9db82215cc8873 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 21 Jun 2013 09:33:50 -0600 Subject: [PATCH 1721/2900] iommu: Fix compiler warning on pr_debug Signed-off-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 4b0b56b0501d..ab1fa19ddddb 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -820,7 +820,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, size_t pgsize = iommu_pgsize(domain, iova | paddr, size); pr_debug("mapping: iova 0x%lx pa 0x%lx pgsize %lu\n", iova, - (unsigned long)paddr, pgsize); + (unsigned long)paddr, (unsigned long)pgsize); ret = domain->ops->map(domain, iova, paddr, pgsize, prot); if (ret) -- GitLab From 60d0ca3cfd199b6612bbbbf4999a3470dad38bb1 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Fri, 21 Jun 2013 14:33:19 -0600 Subject: [PATCH 1722/2900] iommu/amd: Only unmap large pages from the first pte If we use a large mapping, the expectation is that only unmaps from the first pte in the superpage are supported. Unmaps from offsets into the superpage should fail (ie. return zero sized unmap). In the current code, unmapping from an offset clears the size of the full mapping starting from an offset. For instance, if we map a 16k physically contiguous range at IOVA 0x0 with a large page, then attempt to unmap 4k at offset 12k, 4 ptes are cleared (12k - 28k) and the unmap returns 16k unmapped. This potentially incorrectly clears valid mappings and confuses drivers like VFIO that use the unmap size to release pinned pages. Fix by refusing to unmap from offsets into the page. Signed-off-by: Alex Williamson Cc: stable@vger.kernel.org Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 5cde682377a0..4b029c17f8d0 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1484,6 +1484,10 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, /* Large PTE found which maps this address */ unmap_size = PTE_PAGE_SIZE(*pte); + + /* Only unmap from the first pte in the page */ + if ((unmap_size - 1) & bus_addr) + break; count = PAGE_SIZE_PTE_COUNT(unmap_size); for (i = 0; i < count; i++) pte[i] = 0ULL; @@ -1493,7 +1497,7 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, unmapped += unmap_size; } - BUG_ON(!is_power_of_2(unmapped)); + BUG_ON(unmapped && !is_power_of_2(unmapped)); return unmapped; } -- GitLab From cdf2bc632ebc9ef512345fe8e6015edfd367e256 Mon Sep 17 00:00:00 2001 From: Christian Kujau Date: Fri, 14 Jun 2013 18:04:34 -0700 Subject: [PATCH 1723/2900] scripts/setlocalversion on write-protected source tree I just stumbled across another[0] issue when scripts/setlocalversion operates on a write-protected source tree. Back then[0] the source tree was on an read-only NFS share, so "test -w" was introduced before "git update-index" was run. This time, the source tree is on read/write NFS share, but the permissions are world-readable and only a specific user (or root) can write. Thus, "test -w ." returns "0" and then runs "git update-index", producing the following message (on a dirty tree): fatal: Unable to create '/usr/local/src/linux-git/.git/index.lock': Permission denied While it says "fatal", compilation continues just fine. However, I don't think a kernel compilation should alter the source tree (or the .git directory) in any way and I don't see how removing "git update-index" could do any harm. The Mercurial and SVN routines in scripts/setlocalversion don't have any tree-modifying commands, AFAICS. So, maybe the patch below would be acceptable. [0] https://patchwork.kernel.org/patch/29718/ Signed-off-by: Christian Kujau Cc: Nico Schottelius Signed-off-by: Michal Marek --- scripts/setlocalversion | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 84b88f109b80..d105a44b68f6 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -71,9 +71,6 @@ scm_version() printf -- '-svn%s' "`git svn find-rev $head`" fi - # Update index only on r/w media - [ -w . ] && git update-index --refresh --unmerged > /dev/null - # Check for uncommitted changes if git diff-index --name-only HEAD | grep -qv "^scripts/package"; then printf '%s' -dirty -- GitLab From b6b4316c8b2fa6af5cee71e7defd09527b9d1cf9 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Sat, 22 Jun 2013 04:12:00 -0400 Subject: [PATCH 1724/2900] qlcnic: Handle qlcnic_alloc_mbx_args() failure qlcnic_alloc_mbx_args() may fail due to failure in memory allocation. This patch checks for failure of qlcnic_alloc_mbx_args() to avoid potential invalid memory access. Signed-off-by: Shahed Shaikh Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 133 ++++++++++++++---- .../ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 6 +- .../net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 125 +++++++++++----- .../ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 6 +- 4 files changed, 206 insertions(+), 64 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index f63a69570256..88e2e23498d3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -844,7 +844,9 @@ void qlcnic_83xx_idc_aen_work(struct work_struct *work) int i, err = 0; adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work); - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK); + if (err) + return; for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++) cmd.req.arg[i] = adapter->ahw->mbox_aen[i]; @@ -1085,8 +1087,10 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) cap |= QLC_83XX_FW_CAP_LRO_MSS; /* set mailbox hdr and capabilities */ - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_CREATE_RX_CTX); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_CREATE_RX_CTX); + if (err) + return err; if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) cmd.req.arg[0] |= (0x3 << 29); @@ -1244,7 +1248,9 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, mbx.intr_id = 0xffff; mbx.src = 0; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); + if (err) + return err; if (qlcnic_sriov_pf_check(adapter) || qlcnic_sriov_vf_check(adapter)) cmd.req.arg[0] |= (0x3 << 29); @@ -1390,8 +1396,11 @@ int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, if (state) { /* Get LED configuration */ - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_GET_LED_CONFIG); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_GET_LED_CONFIG); + if (status) + return status; + status = qlcnic_issue_cmd(adapter, &cmd); if (status) { dev_err(&adapter->pdev->dev, @@ -1405,8 +1414,11 @@ int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, /* Set LED Configuration */ mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) | LSW(QLC_83XX_LED_CONFIG); - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_SET_LED_CONFIG); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_SET_LED_CONFIG); + if (status) + return status; + cmd.req.arg[1] = mbx_in; cmd.req.arg[2] = mbx_in; cmd.req.arg[3] = mbx_in; @@ -1423,8 +1435,11 @@ int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, } else { /* Restoring default LED configuration */ - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_SET_LED_CONFIG); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_SET_LED_CONFIG); + if (status) + return status; + cmd.req.arg[1] = adapter->ahw->mbox_reg[0]; cmd.req.arg[2] = adapter->ahw->mbox_reg[1]; cmd.req.arg[3] = adapter->ahw->mbox_reg[2]; @@ -1494,10 +1509,18 @@ void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, return; if (enable) { - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_INIT_NIC_FUNC); + if (status) + return; + cmd.req.arg[1] = BIT_0 | BIT_31; } else { - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_STOP_NIC_FUNC); + if (status) + return; + cmd.req.arg[1] = BIT_0 | BIT_31; } status = qlcnic_issue_cmd(adapter, &cmd); @@ -1514,7 +1537,10 @@ int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter) struct qlcnic_cmd_args cmd; int err; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG); + if (err) + return err; + cmd.req.arg[1] = adapter->ahw->port_config; err = qlcnic_issue_cmd(adapter, &cmd); if (err) @@ -1528,7 +1554,10 @@ int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter) struct qlcnic_cmd_args cmd; int err; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG); + if (err) + return err; + err = qlcnic_issue_cmd(adapter, &cmd); if (err) dev_info(&adapter->pdev->dev, "Get Port config failed\n"); @@ -1544,7 +1573,10 @@ int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable) u32 temp; struct qlcnic_cmd_args cmd; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT); + if (err) + return err; + temp = adapter->recv_ctx->context_id << 16; cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp; err = qlcnic_issue_cmd(adapter, &cmd); @@ -1575,7 +1607,11 @@ int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) return -EIO; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); + if (err) + return err; + qlcnic_83xx_set_interface_id_promisc(adapter, &temp); cmd.req.arg[1] = (mode ? 1 : 0) | temp; err = qlcnic_issue_cmd(adapter, &cmd); @@ -1762,7 +1798,11 @@ void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, u32 temp = 0, temp_ip; struct qlcnic_cmd_args cmd; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_CONFIGURE_IP_ADDR); + if (err) + return; + qlcnic_83xx_set_interface_id_ipaddr(adapter, &temp); if (mode == QLCNIC_IP_UP) @@ -1801,7 +1841,10 @@ int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode) if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) return 0; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO); + if (err) + return err; + temp = adapter->recv_ctx->context_id << 16; arg1 = lro_bit_mask | temp; cmd.req.arg[1] = arg1; @@ -1823,8 +1866,9 @@ int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable) 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, 0x255b0ec26d5a56daULL }; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS); - + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS); + if (err) + return err; /* * RSS request: * bits 3-0: Rsvd @@ -1930,7 +1974,10 @@ int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) struct qlcnic_cmd_args cmd; u32 mac_low, mac_high; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); + if (err) + return err; + qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd); err = qlcnic_issue_cmd(adapter, &cmd); @@ -1961,7 +2008,10 @@ void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter) if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) return; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL); + if (err) + return; + if (coal->type == QLCNIC_INTR_COAL_TYPE_RX) { temp = adapter->recv_ctx->context_id; cmd.req.arg[1] = QLCNIC_INTR_COAL_TYPE_RX | temp << 16; @@ -2033,7 +2083,10 @@ int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable) return err; } - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH); + if (err) + return err; + cmd.req.arg[1] = (port & 0xf) | BIT_4; err = qlcnic_issue_cmd(adapter, &cmd); @@ -2061,7 +2114,10 @@ int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter, return err; } - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); + if (err) + return err; + cmd.req.arg[1] = (nic->pci_func << 16); cmd.req.arg[2] = 0x1 << 16; cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16); @@ -2093,7 +2149,10 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, u8 op = 0; struct qlcnic_cmd_args cmd; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); + if (err) + return err; + if (func_id != adapter->ahw->pci_func) { temp = func_id << 16; cmd.req.arg[1] = op | BIT_31 | temp; @@ -2140,7 +2199,10 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, int i, err = 0, j = 0; u32 temp; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); + if (err) + return err; + err = qlcnic_issue_cmd(adapter, &cmd); ahw->act_pci_func = 0; @@ -2195,7 +2257,10 @@ int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type) struct qlcnic_cmd_args cmd; max_ints = adapter->ahw->num_msix - 1; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); + if (err) + return err; + cmd.req.arg[1] = max_ints; if (qlcnic_sriov_vf_check(adapter)) @@ -2823,7 +2888,11 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) dev_info(&adapter->pdev->dev, "link state down\n"); return config; } - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS); + + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS); + if (err) + return err; + err = qlcnic_issue_cmd(adapter, &cmd); if (err) { dev_info(&adapter->pdev->dev, @@ -3049,7 +3118,9 @@ void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data) struct net_device *netdev = adapter->netdev; int ret = 0; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS); + ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS); + if (ret) + return; /* Get Tx stats */ cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16); cmd.rsp.num = QLC_83XX_TX_STAT_REGS; @@ -3139,7 +3210,9 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) goto fail_diag_irq; ahw->diag_cnt = 0; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); + ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); + if (ret) + goto fail_diag_irq; if (adapter->flags & QLCNIC_MSIX_ENABLED) intrpt_id = ahw->intr_tbl[0].id; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index aa26250d7374..f073c08de91f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -2083,7 +2083,11 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT); if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) { - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC); + status = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_STOP_NIC_FUNC); + if (status) + return; + cmd.req.arg[1] = BIT_31; status = qlcnic_issue_cmd(adapter, &cmd); if (status) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 9d0ae11589ce..72593a19ad59 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -194,7 +194,10 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter) _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR, _QLCNIC_LINUX_SUBVERSION); - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER); + if (err) + return err; + memcpy(&arg1, drv_string, sizeof(u32)); memcpy(&arg2, drv_string + 4, sizeof(u32)); memcpy(&arg3, drv_string + 8, sizeof(u32)); @@ -222,7 +225,10 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE) return err; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU); + if (err) + return err; + cmd.req.arg[1] = recv_ctx->context_id; cmd.req.arg[2] = mtu; @@ -336,7 +342,10 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) } phys_addr = hostrq_phys_addr; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX); + if (err) + goto out_free_rsp; + cmd.req.arg[1] = MSD(phys_addr); cmd.req.arg[2] = LSD(phys_addr); cmd.req.arg[3] = rq_size; @@ -374,10 +383,10 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) recv_ctx->context_id = le16_to_cpu(prsp->context_id); recv_ctx->virt_port = prsp->virt_port; + qlcnic_free_mbx_args(&cmd); out_free_rsp: dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, - cardrsp_phys_addr); - qlcnic_free_mbx_args(&cmd); + cardrsp_phys_addr); out_free_rq: dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); return err; @@ -389,7 +398,10 @@ void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter) struct qlcnic_cmd_args cmd; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX); + if (err) + return; + cmd.req.arg[1] = recv_ctx->context_id; err = qlcnic_issue_cmd(adapter, &cmd); if (err) @@ -458,7 +470,10 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, phys_addr = rq_phys_addr; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); + if (err) + goto out_free_rsp; + cmd.req.arg[1] = MSD(phys_addr); cmd.req.arg[2] = LSD(phys_addr); cmd.req.arg[3] = rq_size; @@ -474,12 +489,13 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, err = -EIO; } + qlcnic_free_mbx_args(&cmd); + +out_free_rsp: dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, rsp_phys_addr); - out_free_rq: dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); - qlcnic_free_mbx_args(&cmd); return err; } @@ -488,8 +504,11 @@ void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring) { struct qlcnic_cmd_args cmd; + int ret; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX); + ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX); + if (ret) + return; cmd.req.arg[1] = tx_ring->ctx_id; if (qlcnic_issue_cmd(adapter, &cmd)) @@ -504,7 +523,10 @@ qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) int err; struct qlcnic_cmd_args cmd; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT); + if (err) + return err; + cmd.req.arg[1] = config; err = qlcnic_issue_cmd(adapter, &cmd); qlcnic_free_mbx_args(&cmd); @@ -708,7 +730,10 @@ int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) struct qlcnic_cmd_args cmd; u32 mac_low, mac_high; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); + if (err) + return err; + cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8; err = qlcnic_issue_cmd(adapter, &cmd); @@ -747,7 +772,10 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter, nic_info = nic_info_addr; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); + if (err) + goto out_free_dma; + cmd.req.arg[1] = MSD(nic_dma_t); cmd.req.arg[2] = LSD(nic_dma_t); cmd.req.arg[3] = (func_id << 16 | nic_size); @@ -769,9 +797,10 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter, npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu); } + qlcnic_free_mbx_args(&cmd); +out_free_dma: dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, nic_dma_t); - qlcnic_free_mbx_args(&cmd); return err; } @@ -808,7 +837,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); + if (err) + goto out_free_dma; + cmd.req.arg[1] = MSD(nic_dma_t); cmd.req.arg[2] = LSD(nic_dma_t); cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size); @@ -820,9 +852,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, err = -EIO; } - dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, - nic_dma_t); qlcnic_free_mbx_args(&cmd); +out_free_dma: + dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, + nic_dma_t); return err; } @@ -846,7 +879,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, return -ENOMEM; npar = pci_info_addr; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); + if (err) + goto out_free_dma; + cmd.req.arg[1] = MSD(pci_info_dma_t); cmd.req.arg[2] = LSD(pci_info_dma_t); cmd.req.arg[3] = pci_size; @@ -874,9 +910,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, err = -EIO; } + qlcnic_free_mbx_args(&cmd); +out_free_dma: dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, pci_info_dma_t); - qlcnic_free_mbx_args(&cmd); return err; } @@ -897,7 +934,11 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, arg1 = id | (enable_mirroring ? BIT_4 : 0); arg1 |= pci_func << 8; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORTMIRRORING); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_SET_PORTMIRRORING); + if (err) + return err; + cmd.req.arg[1] = arg1; err = qlcnic_issue_cmd(adapter, &cmd); @@ -941,7 +982,11 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; arg1 |= rx_tx << 15 | stats_size << 16; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_GET_ESWITCH_STATS); + if (err) + goto out_free_dma; + cmd.req.arg[1] = arg1; cmd.req.arg[2] = MSD(stats_dma_t); cmd.req.arg[3] = LSD(stats_dma_t); @@ -963,9 +1008,10 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, esw_stats->numbytes = le64_to_cpu(stats->numbytes); } - dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, - stats_dma_t); qlcnic_free_mbx_args(&cmd); +out_free_dma: + dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, + stats_dma_t); return err; } @@ -989,7 +1035,10 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, if (!stats_addr) return -ENOMEM; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS); + err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS); + if (err) + goto out_free_dma; + cmd.req.arg[1] = stats_size << 16; cmd.req.arg[2] = MSD(stats_dma_t); cmd.req.arg[3] = LSD(stats_dma_t); @@ -1020,11 +1069,12 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, "%s: Get mac stats failed, err=%d.\n", __func__, err); } - dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, - stats_dma_t); - qlcnic_free_mbx_args(&cmd); +out_free_dma: + dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, + stats_dma_t); + return err; } @@ -1108,7 +1158,11 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; arg1 |= BIT_14 | rx_tx << 15; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_GET_ESWITCH_STATS); + if (err) + return err; + cmd.req.arg[1] = arg1; err = qlcnic_issue_cmd(adapter, &cmd); qlcnic_free_mbx_args(&cmd); @@ -1127,10 +1181,13 @@ static int __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, struct device *dev = &adapter->pdev->dev; struct qlcnic_cmd_args cmd; u8 pci_func = *arg1 >> 8; - int err = -EIO; + int err; + + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); + if (err) + return err; - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); cmd.req.arg[1] = *arg1; err = qlcnic_issue_cmd(adapter, &cmd); *arg1 = cmd.rsp.arg[1]; @@ -1208,7 +1265,11 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, return err; } - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_ESWITCH); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_CONFIGURE_ESWITCH); + if (err) + return err; + cmd.req.arg[1] = arg1; cmd.req.arg[2] = arg2; err = qlcnic_issue_cmd(adapter, &cmd); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index f67652de5a63..700a46324d09 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -846,7 +846,9 @@ static int qlcnic_irq_test(struct net_device *netdev) goto clear_diag_irq; ahw->diag_cnt = 0; - qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); + ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); + if (ret) + goto free_diag_res; cmd.req.arg[1] = ahw->pci_func; ret = qlcnic_issue_cmd(adapter, &cmd); @@ -858,6 +860,8 @@ static int qlcnic_irq_test(struct net_device *netdev) done: qlcnic_free_mbx_args(&cmd); + +free_diag_res: qlcnic_diag_free_res(netdev, max_sds_rings); clear_diag_irq: -- GitLab From 52e493d01cbf85871f0d1fdaeffdf376444e5d50 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Sat, 22 Jun 2013 04:12:01 -0400 Subject: [PATCH 1725/2900] qlcnic: Secondary unicast MAC address support. Add support for configuring secondary unicast address which will use existing HW filters to store all the unicast MAC addresses and prevent device going into promiscuous mode. Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 8 ++++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 17 ++++++++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 3 ++ .../net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 1 + .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 34 +++++++++------ .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 43 +++++++++++++++---- 6 files changed, 83 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 534e36ed855a..28a12765794d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -426,6 +426,7 @@ struct qlcnic_hardware_context { u8 nic_mode; char diag_cnt; + u16 max_uc_count; u16 port_type; u16 board_type; u16 supported_type; @@ -1494,6 +1495,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t); int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32); void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); +void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); int qlcnic_enable_msix(struct qlcnic_adapter *, u32); /* eSwitch management functions */ @@ -1631,6 +1633,7 @@ struct qlcnic_hardware_ops { int (*config_promisc_mode) (struct qlcnic_adapter *, u32); void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, u16); int (*get_board_info) (struct qlcnic_adapter *); + void (*set_mac_filter_count) (struct qlcnic_adapter *); void (*free_mac_list) (struct qlcnic_adapter *); }; @@ -1846,6 +1849,11 @@ static inline void qlcnic_free_mac_list(struct qlcnic_adapter *adapter) return adapter->ahw->hw_ops->free_mac_list(adapter); } +static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter) +{ + adapter->ahw->hw_ops->set_mac_filter_count(adapter); +} + static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, u32 key) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 88e2e23498d3..ab664107ac9b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -172,6 +172,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { .config_promisc_mode = qlcnic_83xx_nic_set_promisc, .change_l2_filter = qlcnic_83xx_change_l2_filter, .get_board_info = qlcnic_83xx_get_port_info, + .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, .free_mac_list = qlcnic_82xx_free_mac_list, }; @@ -609,6 +610,22 @@ int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) return status; } +void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + u16 act_pci_fn = ahw->act_pci_func; + u16 count; + + ahw->max_mc_count = QLC_83XX_MAX_MC_COUNT; + if (act_pci_fn <= 2) + count = (QLC_83XX_MAX_UC_COUNT - QLC_83XX_MAX_MC_COUNT) / + act_pci_fn; + else + count = (QLC_83XX_LB_MAX_FILTERS - QLC_83XX_MAX_MC_COUNT) / + act_pci_fn; + ahw->max_uc_count = count; +} + void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter) { u32 val; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 1bfe283a9412..e821ee47324a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -393,6 +393,8 @@ enum qlcnic_83xx_states { #define QLC_83XX_LB_MAX_FILTERS 2048 #define QLC_83XX_LB_BUCKET_SIZE 256 #define QLC_83XX_MINIMUM_VECTOR 3 +#define QLC_83XX_MAX_MC_COUNT 38 +#define QLC_83XX_MAX_UC_COUNT 4096 #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000) #define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20) @@ -624,4 +626,5 @@ u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *); u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *); void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); +void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); #endif diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h index c0f0c0d0a790..d262211b03b3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h @@ -672,6 +672,7 @@ enum { #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 10 #define QLCNIC_MAX_MC_COUNT 38 +#define QLCNIC_MAX_UC_COUNT 512 #define QLCNIC_WATCHDOG_TIMEOUTVALUE 5 #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 218978db2963..e7f305d5bb5f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -499,6 +499,7 @@ int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr, u16 vlan) void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) { struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_hardware_context *ahw = adapter->ahw; struct netdev_hw_addr *ha; static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff @@ -515,25 +516,30 @@ void __qlcnic_set_multi(struct net_device *netdev, u16 vlan) if (netdev->flags & IFF_PROMISC) { if (!(adapter->flags & QLCNIC_PROMISC_DISABLED)) mode = VPORT_MISS_MODE_ACCEPT_ALL; - goto send_fw_cmd; - } - - if ((netdev->flags & IFF_ALLMULTI) || - (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) { - mode = VPORT_MISS_MODE_ACCEPT_MULTI; - goto send_fw_cmd; + } else if (netdev->flags & IFF_ALLMULTI) { + if (netdev_mc_count(netdev) > ahw->max_mc_count) { + mode = VPORT_MISS_MODE_ACCEPT_MULTI; + } else if (!netdev_mc_empty(netdev) && + !qlcnic_sriov_vf_check(adapter)) { + netdev_for_each_mc_addr(ha, netdev) + qlcnic_nic_add_mac(adapter, ha->addr, + vlan); + } + if (mode != VPORT_MISS_MODE_ACCEPT_MULTI && + qlcnic_sriov_vf_check(adapter)) + qlcnic_vf_add_mc_list(netdev, vlan); } - if (!netdev_mc_empty(netdev) && !qlcnic_sriov_vf_check(adapter)) { - netdev_for_each_mc_addr(ha, netdev) { + /* configure unicast MAC address, if there is not sufficient space + * to store all the unicast addresses then enable promiscuous mode + */ + if (netdev_uc_count(netdev) > ahw->max_uc_count) { + mode = VPORT_MISS_MODE_ACCEPT_ALL; + } else if (!netdev_uc_empty(netdev)) { + netdev_for_each_uc_addr(ha, netdev) qlcnic_nic_add_mac(adapter, ha->addr, vlan); - } } - if (qlcnic_sriov_vf_check(adapter)) - qlcnic_vf_add_mc_list(netdev, vlan); - -send_fw_cmd: if (!qlcnic_sriov_vf_check(adapter)) { if (mode == VPORT_MISS_MODE_ACCEPT_ALL && !adapter->fdb_mac_learn) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 0ae88355ad51..8e1453ac0035 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -360,12 +360,15 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], return ndo_dflt_fdb_del(ndm, tb, netdev, addr); if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { - if (is_unicast_ether_addr(addr)) - err = qlcnic_nic_del_mac(adapter, addr); - else if (is_multicast_ether_addr(addr)) + if (is_unicast_ether_addr(addr)) { + err = dev_uc_del(netdev, addr); + if (!err) + err = qlcnic_nic_del_mac(adapter, addr); + } else if (is_multicast_ether_addr(addr)) { err = dev_mc_del(netdev, addr); - else + } else { err = -EINVAL; + } } return err; } @@ -388,12 +391,16 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], if (ether_addr_equal(addr, adapter->mac_addr)) return err; - if (is_unicast_ether_addr(addr)) - err = qlcnic_nic_add_mac(adapter, addr, 0); - else if (is_multicast_ether_addr(addr)) + if (is_unicast_ether_addr(addr)) { + if (netdev_uc_count(netdev) < adapter->ahw->max_uc_count) + err = dev_uc_add_excl(netdev, addr); + else + err = -ENOMEM; + } else if (is_multicast_ether_addr(addr)) { err = dev_mc_add_excl(netdev, addr); - else + } else { err = -EINVAL; + } return err; } @@ -505,6 +512,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { .config_promisc_mode = qlcnic_82xx_nic_set_promisc, .change_l2_filter = qlcnic_82xx_change_filter, .get_board_info = qlcnic_82xx_get_board_info, + .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, .free_mac_list = qlcnic_82xx_free_mac_list, }; @@ -1829,6 +1837,22 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter) return err; } +void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + u16 act_pci_fn = ahw->act_pci_func; + u16 count; + + ahw->max_mc_count = QLCNIC_MAX_MC_COUNT; + if (act_pci_fn <= 2) + count = (QLCNIC_MAX_UC_COUNT - QLCNIC_MAX_MC_COUNT) / + act_pci_fn; + else + count = (QLCNIC_LB_MAX_FILTERS - QLCNIC_MAX_MC_COUNT) / + act_pci_fn; + ahw->max_uc_count = count; +} + int qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, int pci_using_dac) @@ -1838,7 +1862,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, adapter->rx_csum = 1; adapter->ahw->mc_enabled = 0; - adapter->ahw->max_mc_count = QLCNIC_MAX_MC_COUNT; + qlcnic_set_mac_filter_count(adapter); netdev->netdev_ops = &qlcnic_netdev_ops; netdev->watchdog_timeo = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ; @@ -1876,6 +1900,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, netdev->features |= NETIF_F_LRO; netdev->hw_features = netdev->features; + netdev->priv_flags |= IFF_UNICAST_FLT; netdev->irq = adapter->msix_entries[0].vector; err = register_netdev(netdev); -- GitLab From 2c4a787847c243b725a7bac510d3ebaa35c90fab Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Sat, 22 Jun 2013 04:12:02 -0400 Subject: [PATCH 1726/2900] qlcnic: Minimize sleep duration within loopback diagnostic test. o Minimize sleep duration and check for adapter status. o Exit from loopback test if adapter reset is detected. Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 57 +++++++++++++------ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 3 +- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index ab664107ac9b..1c463dd562e2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -1676,13 +1676,19 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) /* Poll for link up event before running traffic */ do { - msleep(500); + msleep(QLC_83XX_LB_MSLEEP_COUNT); if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) qlcnic_83xx_process_aen(adapter); - if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { - dev_info(&adapter->pdev->dev, - "Firmware didn't sent link up event to loopback request\n"); + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { + netdev_info(netdev, + "Device is resetting, free LB test resources\n"); + ret = -EIO; + goto free_diag_res; + } + if (loop++ > QLC_83XX_LB_WAIT_COUNT) { + netdev_info(netdev, + "Firmware didn't sent link up event to loopback request\n"); ret = -QLCNIC_FW_NOT_RESPOND; qlcnic_83xx_clear_lb_mode(adapter, mode); goto free_diag_res; @@ -1711,6 +1717,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) { struct qlcnic_hardware_context *ahw = adapter->ahw; + struct net_device *netdev = adapter->netdev; int status = 0, loop = 0; u32 config; @@ -1728,9 +1735,9 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) status = qlcnic_83xx_set_port_config(adapter); if (status) { - dev_err(&adapter->pdev->dev, - "Failed to Set Loopback Mode = 0x%x.\n", - ahw->port_config); + netdev_err(netdev, + "Failed to Set Loopback Mode = 0x%x.\n", + ahw->port_config); ahw->port_config = config; clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); return status; @@ -1738,13 +1745,19 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) /* Wait for Link and IDC Completion AEN */ do { - msleep(300); + msleep(QLC_83XX_LB_MSLEEP_COUNT); if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) qlcnic_83xx_process_aen(adapter); - if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { - dev_err(&adapter->pdev->dev, - "FW did not generate IDC completion AEN\n"); + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { + netdev_info(netdev, + "Device is resetting, free LB test resources\n"); + clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); + return -EIO; + } + if (loop++ > QLC_83XX_LB_WAIT_COUNT) { + netdev_err(netdev, + "Did not receive IDC completion AEN\n"); clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); qlcnic_83xx_clear_lb_mode(adapter, mode); return -EIO; @@ -1759,6 +1772,7 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) { struct qlcnic_hardware_context *ahw = adapter->ahw; + struct net_device *netdev = adapter->netdev; int status = 0, loop = 0; u32 config = ahw->port_config; @@ -1770,9 +1784,9 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) status = qlcnic_83xx_set_port_config(adapter); if (status) { - dev_err(&adapter->pdev->dev, - "Failed to Clear Loopback Mode = 0x%x.\n", - ahw->port_config); + netdev_err(netdev, + "Failed to Clear Loopback Mode = 0x%x.\n", + ahw->port_config); ahw->port_config = config; clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); return status; @@ -1780,13 +1794,20 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) /* Wait for Link and IDC Completion AEN */ do { - msleep(300); + msleep(QLC_83XX_LB_MSLEEP_COUNT); if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) qlcnic_83xx_process_aen(adapter); - if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { - dev_err(&adapter->pdev->dev, - "Firmware didn't sent IDC completion AEN\n"); + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { + netdev_info(netdev, + "Device is resetting, free LB test resources\n"); + clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); + return -EIO; + } + + if (loop++ > QLC_83XX_LB_WAIT_COUNT) { + netdev_err(netdev, + "Did not receive IDC completion AEN\n"); clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); return -EIO; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index e821ee47324a..e356ee87a9a6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -36,7 +36,8 @@ #define QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT 3 #define QLC_83XX_DRV_LOCK_RECOVERY_DELAY 200 #define QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK 0x3 - +#define QLC_83XX_LB_WAIT_COUNT 250 +#define QLC_83XX_LB_MSLEEP_COUNT 20 #define QLC_83XX_NO_NIC_RESOURCE 0x5 #define QLC_83XX_MAC_PRESENT 0xC #define QLC_83XX_MAC_ABSENT 0xD -- GitLab From 9baf1aa9c4c7a7fe52886634c3646fabaa48aa39 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Sat, 22 Jun 2013 04:12:03 -0400 Subject: [PATCH 1727/2900] qlcnic: Add support for PEX DMA method to read memory section of adapter dump This patch adds support to read memory section of adapter dump using PEX DMA method. This method significantly improves total adapter dump collection time. Signed-off-by: Shahed Shaikh Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 3 + .../ethernet/qlogic/qlcnic/qlcnic_minidump.c | 225 +++++++++++++++++- 2 files changed, 221 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 28a12765794d..cc2c2c13f6a0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -393,6 +393,9 @@ struct qlcnic_fw_dump { u32 size; /* total size of the dump */ void *data; /* dump data area */ struct qlcnic_dump_template_hdr *tmpl_hdr; + dma_addr_t phys_addr; + void *dma_buffer; + bool use_pex_dma; }; /* diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 4b9bab18ebd9..ab8a6744d402 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -15,6 +15,7 @@ #define QLC_83XX_MINIDUMP_FLASH 0x520000 #define QLC_83XX_OCM_INDEX 3 #define QLC_83XX_PCI_INDEX 0 +#define QLC_83XX_DMA_ENGINE_INDEX 8 static const u32 qlcnic_ms_read_data[] = { 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC @@ -32,6 +33,16 @@ static const u32 qlcnic_ms_read_data[] = { #define QLCNIC_DUMP_MASK_MAX 0xff +struct qlcnic_pex_dma_descriptor { + u32 read_data_size; + u32 dma_desc_cmd; + u32 src_addr_low; + u32 src_addr_high; + u32 dma_bus_addr_low; + u32 dma_bus_addr_high; + u32 rsvd[6]; +} __packed; + struct qlcnic_common_entry_hdr { u32 type; u32 offset; @@ -90,7 +101,10 @@ struct __ocm { } __packed; struct __mem { - u8 rsvd[24]; + u32 desc_card_addr; + u32 dma_desc_cmd; + u32 start_dma_cmd; + u32 rsvd[3]; u32 addr; u32 size; } __packed; @@ -466,12 +480,12 @@ static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, return l2->no_ops * l2->read_addr_num * sizeof(u32); } -static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, - struct qlcnic_dump_entry *entry, __le32 *buffer) +static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter, + struct __mem *mem, __le32 *buffer, + int *ret) { - u32 addr, data, test, ret = 0; + u32 addr, data, test; int i, reg_read; - struct __mem *mem = &entry->region.mem; reg_read = mem->size; addr = mem->addr; @@ -480,7 +494,8 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, dev_info(&adapter->pdev->dev, "Unaligned memory addr:0x%x size:0x%x\n", addr, reg_read); - return -EINVAL; + *ret = -EINVAL; + return 0; } mutex_lock(&adapter->ahw->mem_lock); @@ -499,7 +514,7 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, if (printk_ratelimit()) { dev_err(&adapter->pdev->dev, "failed to read through agent\n"); - ret = -EINVAL; + *ret = -EIO; goto out; } } @@ -516,6 +531,181 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, return mem->size; } +/* DMA register base address */ +#define QLC_DMA_REG_BASE_ADDR(dma_no) (0x77320000 + (dma_no * 0x10000)) + +/* DMA register offsets w.r.t base address */ +#define QLC_DMA_CMD_BUFF_ADDR_LOW 0 +#define QLC_DMA_CMD_BUFF_ADDR_HI 4 +#define QLC_DMA_CMD_STATUS_CTRL 8 + +#define QLC_PEX_DMA_READ_SIZE (PAGE_SIZE * 16) + +static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter, + struct __mem *mem) +{ + struct qlcnic_dump_template_hdr *tmpl_hdr; + struct device *dev = &adapter->pdev->dev; + u32 dma_no, dma_base_addr, temp_addr; + int i, ret, dma_sts; + + tmpl_hdr = adapter->ahw->fw_dump.tmpl_hdr; + dma_no = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX]; + dma_base_addr = QLC_DMA_REG_BASE_ADDR(dma_no); + + temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_LOW; + ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, + mem->desc_card_addr); + if (ret) + return ret; + + temp_addr = dma_base_addr + QLC_DMA_CMD_BUFF_ADDR_HI; + ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, 0); + if (ret) + return ret; + + temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL; + ret = qlcnic_83xx_wrt_reg_indirect(adapter, temp_addr, + mem->start_dma_cmd); + if (ret) + return ret; + + /* Wait for DMA to complete */ + temp_addr = dma_base_addr + QLC_DMA_CMD_STATUS_CTRL; + for (i = 0; i < 400; i++) { + dma_sts = qlcnic_ind_rd(adapter, temp_addr); + + if (dma_sts & BIT_1) + usleep_range(250, 500); + else + break; + } + + if (i >= 400) { + dev_info(dev, "PEX DMA operation timed out"); + ret = -EIO; + } + + return ret; +} + +static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter, + struct __mem *mem, + __le32 *buffer, int *ret) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + u32 temp, dma_base_addr, size = 0, read_size = 0; + struct qlcnic_pex_dma_descriptor *dma_descr; + struct qlcnic_dump_template_hdr *tmpl_hdr; + struct device *dev = &adapter->pdev->dev; + dma_addr_t dma_phys_addr; + void *dma_buffer; + + tmpl_hdr = fw_dump->tmpl_hdr; + + /* Check if DMA engine is available */ + temp = tmpl_hdr->saved_state[QLC_83XX_DMA_ENGINE_INDEX]; + dma_base_addr = QLC_DMA_REG_BASE_ADDR(temp); + temp = qlcnic_ind_rd(adapter, + dma_base_addr + QLC_DMA_CMD_STATUS_CTRL); + + if (!(temp & BIT_31)) { + dev_info(dev, "%s: DMA engine is not available\n", __func__); + *ret = -EIO; + return 0; + } + + /* Create DMA descriptor */ + dma_descr = kzalloc(sizeof(struct qlcnic_pex_dma_descriptor), + GFP_KERNEL); + if (!dma_descr) { + *ret = -ENOMEM; + return 0; + } + + /* dma_desc_cmd 0:15 = 0 + * dma_desc_cmd 16:19 = mem->dma_desc_cmd 0:3 + * dma_desc_cmd 20:23 = pci function number + * dma_desc_cmd 24:31 = mem->dma_desc_cmd 8:15 + */ + dma_phys_addr = fw_dump->phys_addr; + dma_buffer = fw_dump->dma_buffer; + temp = 0; + temp = mem->dma_desc_cmd & 0xff0f; + temp |= (adapter->ahw->pci_func & 0xf) << 4; + dma_descr->dma_desc_cmd = (temp << 16) & 0xffff0000; + dma_descr->dma_bus_addr_low = LSD(dma_phys_addr); + dma_descr->dma_bus_addr_high = MSD(dma_phys_addr); + dma_descr->src_addr_high = 0; + + /* Collect memory dump using multiple DMA operations if required */ + while (read_size < mem->size) { + if (mem->size - read_size >= QLC_PEX_DMA_READ_SIZE) + size = QLC_PEX_DMA_READ_SIZE; + else + size = mem->size - read_size; + + dma_descr->src_addr_low = mem->addr + read_size; + dma_descr->read_data_size = size; + + /* Write DMA descriptor to MS memory*/ + temp = sizeof(struct qlcnic_pex_dma_descriptor) / 16; + *ret = qlcnic_83xx_ms_mem_write128(adapter, mem->desc_card_addr, + (u32 *)dma_descr, temp); + if (*ret) { + dev_info(dev, "Failed to write DMA descriptor to MS memory at address 0x%x\n", + mem->desc_card_addr); + goto free_dma_descr; + } + + *ret = qlcnic_start_pex_dma(adapter, mem); + if (*ret) { + dev_info(dev, "Failed to start PEX DMA operation\n"); + goto free_dma_descr; + } + + memcpy(buffer, dma_buffer, size); + buffer += size / 4; + read_size += size; + } + +free_dma_descr: + kfree(dma_descr); + + return read_size; +} + +static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, + struct qlcnic_dump_entry *entry, __le32 *buffer) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + struct device *dev = &adapter->pdev->dev; + struct __mem *mem = &entry->region.mem; + u32 data_size; + int ret = 0; + + if (fw_dump->use_pex_dma) { + data_size = qlcnic_read_memory_pexdma(adapter, mem, buffer, + &ret); + if (ret) + dev_info(dev, + "Failed to read memory dump using PEX DMA: mask[0x%x]\n", + entry->hdr.mask); + else + return data_size; + } + + data_size = qlcnic_read_memory_test_agent(adapter, mem, buffer, &ret); + if (ret) { + dev_info(dev, + "Failed to read memory dump using test agent method: mask[0x%x]\n", + entry->hdr.mask); + return 0; + } else { + return data_size; + } +} + static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, __le32 *buffer) { @@ -893,6 +1083,12 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) tmpl_hdr = ahw->fw_dump.tmpl_hdr; tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; + + if ((tmpl_hdr->version & 0xffffff) >= 0x20001) + ahw->fw_dump.use_pex_dma = true; + else + ahw->fw_dump.use_pex_dma = false; + ahw->fw_dump.enable = 1; return 0; @@ -910,7 +1106,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; static const struct qlcnic_dump_operations *fw_dump_ops; + struct device *dev = &adapter->pdev->dev; struct qlcnic_hardware_context *ahw; + void *temp_buffer; ahw = adapter->ahw; @@ -944,6 +1142,16 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; tmpl_hdr->sys_info[1] = adapter->fw_version; + if (fw_dump->use_pex_dma) { + temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE, + &fw_dump->phys_addr, + GFP_KERNEL); + if (!temp_buffer) + fw_dump->use_pex_dma = false; + else + fw_dump->dma_buffer = temp_buffer; + } + if (qlcnic_82xx_check(adapter)) { ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops); fw_dump_ops = qlcnic_fw_dump_ops; @@ -1002,6 +1210,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) return 0; } error: + if (fw_dump->use_pex_dma) + dma_free_coherent(dev, QLC_PEX_DMA_READ_SIZE, + fw_dump->dma_buffer, fw_dump->phys_addr); vfree(fw_dump->data); return -EINVAL; } -- GitLab From db131786445d55c418d27cb2341b86cf16807d9d Mon Sep 17 00:00:00 2001 From: Pratik Pujar Date: Sat, 22 Jun 2013 04:12:04 -0400 Subject: [PATCH 1728/2900] qlcnic: Cleanup of structure qlcnic_hardware_context Signed-off-by: Pratik Pujar Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 2 +- drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 3 ++- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 4 ++-- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index cc2c2c13f6a0..5694d599f659 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -449,7 +449,7 @@ struct qlcnic_hardware_context { u16 max_pci_func; u32 capabilities; - u32 capabilities2; + u32 extra_capability[3]; u32 temp; u32 int_vec_bit; u32 fw_hal_version; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index e7f305d5bb5f..9fcbfd449ac5 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -786,7 +786,8 @@ int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable) word = 0; if (enable) { word = QLCNIC_ENABLE_IPV4_LRO | QLCNIC_NO_DEST_IPV4_CHECK; - if (adapter->ahw->capabilities2 & QLCNIC_FW_CAP2_HW_LRO_IPV6) + if (adapter->ahw->extra_capability[0] & + QLCNIC_FW_CAP2_HW_LRO_IPV6) word |= QLCNIC_ENABLE_IPV6_LRO | QLCNIC_NO_DEST_IPV6_CHECK; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 8e1453ac0035..3963e781a2b4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -994,7 +994,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { u32 temp; temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); - adapter->ahw->capabilities2 = temp; + adapter->ahw->extra_capability[0] = temp; } adapter->ahw->max_mac_filters = nic_info.max_mac_filters; adapter->ahw->max_mtu = nic_info.max_mtu; @@ -1486,7 +1486,7 @@ static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter) u32 capab = 0; if (qlcnic_82xx_check(adapter)) { - if (adapter->ahw->capabilities2 & + if (adapter->ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG) adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; } else { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 7ec030abdf07..10ed82b3baca 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -168,7 +168,7 @@ static int qlcnic_82xx_store_beacon(struct qlcnic_adapter *adapter, if (err) return err; - if ((ahw->capabilities2 & QLCNIC_FW_CAPABILITY_2_BEACON)) { + if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_BEACON) { err = qlcnic_get_beacon_state(adapter, &h_beacon_state); if (!err) { dev_info(&adapter->pdev->dev, -- GitLab From 8af3f33db05c6d0146ad14905145a5c923770856 Mon Sep 17 00:00:00 2001 From: Pratik Pujar Date: Sat, 22 Jun 2013 04:12:05 -0400 Subject: [PATCH 1729/2900] qlcnic: Add support for 'set driver version' in 83XX Issue 'set driver version' during driver load and after reset recovery to notify the driver version to the firmware. Signed-off-by: Pratik Pujar Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 5 ++-- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 9 +++++-- .../ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 1 + .../net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 6 ++--- .../net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 3 ++- .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 25 +++++++++++++------ 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 5694d599f659..955dd858464a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -819,7 +819,7 @@ struct qlcnic_mac_list_s { #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 -#define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 +#define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 /* module types */ @@ -1476,7 +1476,7 @@ int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); -int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *); +int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32); int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); netdev_features_t qlcnic_fix_features(struct net_device *netdev, netdev_features_t features); @@ -1500,6 +1500,7 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32); void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); int qlcnic_enable_msix(struct qlcnic_adapter *, u32); +void qlcnic_set_drv_version(struct qlcnic_adapter *); /* eSwitch management functions */ int qlcnic_config_switch_port(struct qlcnic_adapter *, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 1c463dd562e2..1938812bb0e2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -63,6 +63,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1}, {QLCNIC_CMD_SET_LED_CONFIG, 5, 1}, {QLCNIC_CMD_GET_LED_CONFIG, 1, 5}, + {QLCNIC_CMD_83XX_SET_DRV_VER, 4, 1}, {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26}, {QLCNIC_CMD_CONFIG_VPORT, 4, 4}, {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1}, @@ -2186,16 +2187,17 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, u32 temp; u8 op = 0; struct qlcnic_cmd_args cmd; + struct qlcnic_hardware_context *ahw = adapter->ahw; err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); if (err) return err; - if (func_id != adapter->ahw->pci_func) { + if (func_id != ahw->pci_func) { temp = func_id << 16; cmd.req.arg[1] = op | BIT_31 | temp; } else { - cmd.req.arg[1] = adapter->ahw->pci_func << 16; + cmd.req.arg[1] = ahw->pci_func << 16; } err = qlcnic_issue_cmd(adapter, &cmd); if (err) { @@ -2222,6 +2224,9 @@ int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17; npar_info->max_linkspeed_reg_offset = temp; } + if (npar_info->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) + memcpy(ahw->extra_capability, &cmd.rsp.arg[16], + sizeof(ahw->extra_capability)); out: qlcnic_free_mbx_args(&cmd); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index f073c08de91f..e2d04d5cb9b0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -629,6 +629,7 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) return -EIO; } + qlcnic_set_drv_version(adapter); qlcnic_83xx_idc_attach_driver(adapter); return 0; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 72593a19ad59..0d54fceda960 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -36,7 +36,7 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = { {QLCNIC_CMD_CONFIG_PORT, 4, 1}, {QLCNIC_CMD_TEMP_SIZE, 4, 4}, {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, - {QLCNIC_CMD_SET_DRV_VER, 4, 1}, + {QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1}, {QLCNIC_CMD_GET_LED_STATUS, 4, 2}, }; @@ -182,7 +182,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, return cmd->rsp.arg[0]; } -int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter) +int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter, u32 fw_cmd) { struct qlcnic_cmd_args cmd; u32 arg1, arg2, arg3; @@ -194,7 +194,7 @@ int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter) _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR, _QLCNIC_LINUX_SUBVERSION); - err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER); + err = qlcnic_alloc_mbx_args(&cmd, adapter, fw_cmd); if (err) return err; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index 812fd07baef3..b190c8495a85 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h @@ -86,7 +86,7 @@ enum qlcnic_regs { #define QLCNIC_CMD_BC_EVENT_SETUP 0x31 #define QLCNIC_CMD_CONFIG_VPORT 0x32 #define QLCNIC_CMD_GET_MAC_STATS 0x37 -#define QLCNIC_CMD_SET_DRV_VER 0x38 +#define QLCNIC_CMD_82XX_SET_DRV_VER 0x38 #define QLCNIC_CMD_GET_LED_STATUS 0x3C #define QLCNIC_CMD_CONFIGURE_RSS 0x41 #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 @@ -103,6 +103,7 @@ enum qlcnic_regs { #define QLCNIC_CMD_GET_LINK_STATUS 0x68 #define QLCNIC_CMD_SET_LED_CONFIG 0x69 #define QLCNIC_CMD_GET_LED_CONFIG 0x6A +#define QLCNIC_CMD_83XX_SET_DRV_VER 0x6F #define QLCNIC_CMD_ADD_RCV_RINGS 0x0B #define QLCNIC_INTRPT_INTX 1 diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 3963e781a2b4..0d7a4fd9975c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1985,6 +1985,21 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, return 0; } +void qlcnic_set_drv_version(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + u32 fw_cmd = 0; + + if (qlcnic_82xx_check(adapter)) + fw_cmd = QLCNIC_CMD_82XX_SET_DRV_VER; + else if (qlcnic_83xx_check(adapter)) + fw_cmd = QLCNIC_CMD_83XX_SET_DRV_VER; + + if ((ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) && + (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER)) + qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd); +} + static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1992,7 +2007,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct qlcnic_adapter *adapter = NULL; struct qlcnic_hardware_context *ahw; int err, pci_using_dac = -1; - u32 capab2; char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */ if (pdev->is_virtfn) @@ -2147,13 +2161,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_out_disable_mbx_intr; - if (qlcnic_82xx_check(adapter)) { - if (ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { - capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); - if (capab2 & QLCNIC_FW_CAPABILITY_2_OCBB) - qlcnic_fw_cmd_set_drv_version(adapter); - } - } + qlcnic_set_drv_version(adapter); pci_set_drvdata(pdev, adapter); @@ -3124,6 +3132,7 @@ qlcnic_attach_work(struct work_struct *work) adapter->fw_fail_cnt = 0; adapter->flags &= ~QLCNIC_FW_HANG; clear_bit(__QLCNIC_RESETTING, &adapter->state); + qlcnic_set_drv_version(adapter); if (!qlcnic_clr_drv_state(adapter)) qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, -- GitLab From 486a5bc77a4a83d29b72b17fde229e45a2428194 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Sat, 22 Jun 2013 04:12:06 -0400 Subject: [PATCH 1730/2900] qlcnic: Add support for 83xx suspend and resume. o Implement shutdown and resume handlers for 83xx. o Refactor 82xx shutdown and resume handlers. Signed-off-by: Rajesh Borundia Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 14 ++++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 53 +++++++++++++++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 6 ++ .../ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 17 +++-- .../ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | 23 ++++++- .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 51 ++++++++++++++ .../net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 4 ++ .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 66 ++----------------- .../net/ethernet/qlogic/qlcnic/qlcnic_sriov.h | 2 + .../qlogic/qlcnic/qlcnic_sriov_common.c | 53 +++++++++++++++ 10 files changed, 225 insertions(+), 64 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 955dd858464a..a89e322be28e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1596,6 +1596,8 @@ struct qlcnic_nic_template { void (*napi_del)(struct qlcnic_adapter *); void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); + int (*shutdown)(struct pci_dev *); + int (*resume)(struct qlcnic_adapter *); }; /* Adapter hardware abstraction */ @@ -1800,6 +1802,18 @@ static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter) adapter->ahw->hw_ops->napi_enable(adapter); } +static inline int __qlcnic_shutdown(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + + return adapter->nic_ops->shutdown(pdev); +} + +static inline int __qlcnic_resume(struct qlcnic_adapter *adapter) +{ + return adapter->nic_ops->resume(adapter); +} + static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) { adapter->ahw->hw_ops->napi_disable(adapter); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 1938812bb0e2..0913c623a67e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -186,6 +186,8 @@ static struct qlcnic_nic_template qlcnic_83xx_ops = { .napi_del = qlcnic_83xx_napi_del, .config_ipaddr = qlcnic_83xx_config_ipaddr, .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, + .shutdown = qlcnic_83xx_shutdown, + .resume = qlcnic_83xx_resume, }; void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) @@ -3393,3 +3395,54 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter) } return 0; } + +int qlcnic_83xx_shutdown(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int retval; + + netif_device_detach(netdev); + qlcnic_cancel_idc_work(adapter); + + if (netif_running(netdev)) + qlcnic_down(adapter, netdev); + + qlcnic_83xx_disable_mbx_intr(adapter); + cancel_delayed_work_sync(&adapter->idc_aen_work); + + retval = pci_save_state(pdev); + if (retval) + return retval; + + return 0; +} + +int qlcnic_83xx_resume(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlc_83xx_idc *idc = &ahw->idc; + int err = 0; + + err = qlcnic_83xx_idc_init(adapter); + if (err) + return err; + + if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) { + if (ahw->op_mode == QLCNIC_MGMT_FUNC) { + qlcnic_83xx_set_vnic_opmode(adapter); + } else { + err = qlcnic_83xx_check_vnic_state(adapter); + if (err) + return err; + } + } + + err = qlcnic_83xx_idc_reattach_driver(adapter); + if (err) + return err; + + qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, + idc->delay); + return err; +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index e356ee87a9a6..2548d1403d75 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -628,4 +628,10 @@ u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *); void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); +int qlcnic_83xx_shutdown(struct pci_dev *); +int qlcnic_83xx_resume(struct qlcnic_adapter *); +int qlcnic_83xx_idc_init(struct qlcnic_adapter *); +int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); +int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); +int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); #endif diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index e2d04d5cb9b0..f41dfab1e9a3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -606,7 +606,7 @@ static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter) return 0; } -static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) +int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) { int err; @@ -1135,7 +1135,7 @@ qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter) return 0; } -static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) +int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) { int ret = -EIO; @@ -1554,9 +1554,18 @@ static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev) int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev) { - u8 *p_buff; - u32 addr, count; struct qlcnic_hardware_context *ahw = p_dev->ahw; + u32 addr, count, prev_ver, curr_ver; + u8 *p_buff; + + if (ahw->reset.buff != NULL) { + prev_ver = p_dev->fw_version; + curr_ver = qlcnic_83xx_get_fw_version(p_dev); + if (curr_ver > prev_ver) + kfree(ahw->reset.buff); + else + return 0; + } ahw->reset.seq_error = 0; ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index b5054e1d1710..599d1fda52f2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c @@ -39,7 +39,7 @@ int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock) return 0; } -static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) +int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) { u8 id; int ret = -EBUSY; @@ -218,3 +218,24 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) return 0; } + +int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hardware_context *ahw = adapter->ahw; + struct qlc_83xx_idc *idc = &ahw->idc; + u32 state; + + state = QLCRDX(ahw, QLC_83XX_VNIC_STATE); + while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) { + msleep(1000); + state = QLCRDX(ahw, QLC_83XX_VNIC_STATE); + } + + if (!idc->vnic_wait_limit) { + dev_err(&adapter->pdev->dev, + "vNIC mode not operational, state check timed out.\n"); + return -EIO; + } + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 9fcbfd449ac5..5b5d2edf125d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -1577,3 +1577,54 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *adapter) { qlcnic_pcie_sem_unlock(adapter, 5); } + +int qlcnic_82xx_shutdown(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int retval; + + netif_device_detach(netdev); + + qlcnic_cancel_idc_work(adapter); + + if (netif_running(netdev)) + qlcnic_down(adapter, netdev); + + qlcnic_clr_all_drv_state(adapter, 0); + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + + retval = pci_save_state(pdev); + if (retval) + return retval; + + if (qlcnic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } + + return 0; +} + +int qlcnic_82xx_resume(struct qlcnic_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int err; + + err = qlcnic_start_firmware(adapter); + if (err) { + dev_err(&adapter->pdev->dev, "failed to start firmware\n"); + return err; + } + + if (netif_running(netdev)) { + err = qlcnic_up(adapter, netdev); + if (!err) + qlcnic_restore_indev_addr(netdev, NETDEV_UP); + } + + netif_device_attach(netdev); + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); + return err; +} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index b190c8495a85..2c22504f57aa 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h @@ -199,4 +199,8 @@ void qlcnic_82xx_api_unlock(struct qlcnic_adapter *); void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); void qlcnic_82xx_napi_del(struct qlcnic_adapter *); +int qlcnic_82xx_shutdown(struct pci_dev *); +int qlcnic_82xx_resume(struct qlcnic_adapter *); +void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed); +void qlcnic_fw_poll_work(struct work_struct *work); #endif /* __QLCNIC_HW_H_ */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 0d7a4fd9975c..4528f8ec333b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -59,13 +59,11 @@ static int qlcnic_close(struct net_device *netdev); static void qlcnic_tx_timeout(struct net_device *netdev); static void qlcnic_attach_work(struct work_struct *work); static void qlcnic_fwinit_work(struct work_struct *work); -static void qlcnic_fw_poll_work(struct work_struct *work); #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev); #endif static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding); -static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8); static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); static irqreturn_t qlcnic_tmp_intr(int irq, void *data); @@ -469,6 +467,8 @@ static struct qlcnic_nic_template qlcnic_ops = { .napi_add = qlcnic_82xx_napi_add, .napi_del = qlcnic_82xx_napi_del, .config_ipaddr = qlcnic_82xx_config_ipaddr, + .shutdown = qlcnic_82xx_shutdown, + .resume = qlcnic_82xx_resume, .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, }; @@ -2277,37 +2277,6 @@ static void qlcnic_remove(struct pci_dev *pdev) kfree(ahw); free_netdev(netdev); } -static int __qlcnic_shutdown(struct pci_dev *pdev) -{ - struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdev; - int retval; - - netif_device_detach(netdev); - - qlcnic_cancel_idc_work(adapter); - - if (netif_running(netdev)) - qlcnic_down(adapter, netdev); - - qlcnic_sriov_cleanup(adapter); - if (qlcnic_82xx_check(adapter)) - qlcnic_clr_all_drv_state(adapter, 0); - - clear_bit(__QLCNIC_RESETTING, &adapter->state); - - retval = pci_save_state(pdev); - if (retval) - return retval; - if (qlcnic_82xx_check(adapter)) { - if (qlcnic_wol_supported(adapter)) { - pci_enable_wake(pdev, PCI_D3cold, 1); - pci_enable_wake(pdev, PCI_D3hot, 1); - } - } - - return 0; -} static void qlcnic_shutdown(struct pci_dev *pdev) { @@ -2318,8 +2287,7 @@ static void qlcnic_shutdown(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int -qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) +static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) { int retval; @@ -2331,11 +2299,9 @@ qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int -qlcnic_resume(struct pci_dev *pdev) +static int qlcnic_resume(struct pci_dev *pdev) { struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdev; int err; err = pci_enable_device(pdev); @@ -2346,23 +2312,7 @@ qlcnic_resume(struct pci_dev *pdev) pci_set_master(pdev); pci_restore_state(pdev); - err = qlcnic_start_firmware(adapter); - if (err) { - dev_err(&pdev->dev, "failed to start firmware\n"); - return err; - } - - if (netif_running(netdev)) { - err = qlcnic_up(adapter, netdev); - if (err) - goto done; - - qlcnic_restore_indev_addr(netdev, NETDEV_UP); - } -done: - netif_device_attach(netdev); - qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); - return 0; + return __qlcnic_resume(adapter); } #endif @@ -2701,8 +2651,7 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) return 0; } -static void -qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) +void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) { u32 val; @@ -3213,8 +3162,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) return 1; } -static void -qlcnic_fw_poll_work(struct work_struct *work) +void qlcnic_fw_poll_work(struct work_struct *work) { struct qlcnic_adapter *adapter = container_of(work, struct qlcnic_adapter, fw_work.work); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h index 9176cb015732..0daf660e12a1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h @@ -195,6 +195,8 @@ int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *, int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *, struct qlcnic_info *, u16); int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8); +int qlcnic_sriov_vf_shutdown(struct pci_dev *); +int qlcnic_sriov_vf_resume(struct qlcnic_adapter *); static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index bcd200eff981..d55624993b04 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -76,6 +76,8 @@ static struct qlcnic_nic_template qlcnic_sriov_vf_ops = { .cancel_idc_work = qlcnic_sriov_vf_cancel_fw_work, .napi_add = qlcnic_83xx_napi_add, .napi_del = qlcnic_83xx_napi_del, + .shutdown = qlcnic_sriov_vf_shutdown, + .resume = qlcnic_sriov_vf_resume, .config_ipaddr = qlcnic_83xx_config_ipaddr, .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, }; @@ -1954,3 +1956,54 @@ static void qlcnic_sriov_vf_free_mac_list(struct qlcnic_adapter *adapter) kfree(cur); } } + +int qlcnic_sriov_vf_shutdown(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int retval; + + netif_device_detach(netdev); + qlcnic_cancel_idc_work(adapter); + + if (netif_running(netdev)) + qlcnic_down(adapter, netdev); + + qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_TERM); + qlcnic_sriov_cfg_bc_intr(adapter, 0); + qlcnic_83xx_disable_mbx_intr(adapter); + cancel_delayed_work_sync(&adapter->idc_aen_work); + + retval = pci_save_state(pdev); + if (retval) + return retval; + + return 0; +} + +int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) +{ + struct qlc_83xx_idc *idc = &adapter->ahw->idc; + struct net_device *netdev = adapter->netdev; + int err; + + set_bit(QLC_83XX_MODULE_LOADED, &idc->status); + qlcnic_83xx_enable_mbx_intrpt(adapter); + err = qlcnic_sriov_cfg_bc_intr(adapter, 1); + if (err) + return err; + + err = qlcnic_sriov_channel_cfg_cmd(adapter, QLCNIC_BC_CMD_CHANNEL_INIT); + if (!err) { + if (netif_running(netdev)) { + err = qlcnic_up(adapter, netdev); + if (!err) + qlcnic_restore_indev_addr(netdev, NETDEV_UP); + } + } + + netif_device_attach(netdev); + qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, + idc->delay); + return err; +} -- GitLab From 8640caf60aac7fe30dd622aca41d8336d07d3bd7 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Sat, 22 Jun 2013 04:12:07 -0400 Subject: [PATCH 1731/2900] qlcnic: Update version to 5.2.44 Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index a89e322be28e..b00cf5665eab 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -38,8 +38,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 2 -#define _QLCNIC_LINUX_SUBVERSION 43 -#define QLCNIC_LINUX_VERSIONID "5.2.43" +#define _QLCNIC_LINUX_SUBVERSION 44 +#define QLCNIC_LINUX_VERSIONID "5.2.44" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) -- GitLab From b33698e267ff17a97ecf3ee621a925bb356e9120 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 20 Jun 2013 16:30:00 +0800 Subject: [PATCH 1732/2900] ipv6: remove a useless pr_info() in addrconf_gre_config() This is debug info, should at least be pr_debug(), but given that this code is in upstream for two years, there is no need to keep this debugging printk any more, so just remove it. Cc: Stephen Hemminger Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 80449121afa2..90788a1c6bbc 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2760,8 +2760,6 @@ static void addrconf_gre_config(struct net_device *dev) struct inet6_dev *idev; struct in6_addr addr; - pr_info("%s(%s)\n", __func__, dev->name); - ASSERT_RTNL(); if ((idev = ipv6_find_idev(dev)) == NULL) { -- GitLab From b3a6dfe8178c5159e54117078134fef806a913ca Mon Sep 17 00:00:00 2001 From: Asias He Date: Thu, 20 Jun 2013 17:20:30 +0800 Subject: [PATCH 1733/2900] VSOCK: Introduce vsock_auto_bind helper This peace of code is called three times, let's have a helper for it. Signed-off-by: Asias He Acked-by: Andy King Signed-off-by: David S. Miller --- net/vmw_vsock/af_vsock.c | 49 +++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 3f77f42a3b58..b0b362ad051d 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -165,6 +165,18 @@ static struct list_head vsock_bind_table[VSOCK_HASH_SIZE + 1]; static struct list_head vsock_connected_table[VSOCK_HASH_SIZE]; static DEFINE_SPINLOCK(vsock_table_lock); +/* Autobind this socket to the local address if necessary. */ +static int vsock_auto_bind(struct vsock_sock *vsk) +{ + struct sock *sk = sk_vsock(vsk); + struct sockaddr_vm local_addr; + + if (vsock_addr_bound(&vsk->local_addr)) + return 0; + vsock_addr_init(&local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); + return __vsock_bind(sk, &local_addr); +} + static void vsock_init_tables(void) { int i; @@ -956,15 +968,10 @@ static int vsock_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, lock_sock(sk); - if (!vsock_addr_bound(&vsk->local_addr)) { - struct sockaddr_vm local_addr; - - vsock_addr_init(&local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); - err = __vsock_bind(sk, &local_addr); - if (err != 0) - goto out; + err = vsock_auto_bind(vsk); + if (err) + goto out; - } /* If the provided message contains an address, use that. Otherwise * fall back on the socket's remote handle (if it has been connected). @@ -1038,15 +1045,9 @@ static int vsock_dgram_connect(struct socket *sock, lock_sock(sk); - if (!vsock_addr_bound(&vsk->local_addr)) { - struct sockaddr_vm local_addr; - - vsock_addr_init(&local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY); - err = __vsock_bind(sk, &local_addr); - if (err != 0) - goto out; - - } + err = vsock_auto_bind(vsk); + if (err) + goto out; if (!transport->dgram_allow(remote_addr->svm_cid, remote_addr->svm_port)) { @@ -1163,17 +1164,9 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, memcpy(&vsk->remote_addr, remote_addr, sizeof(vsk->remote_addr)); - /* Autobind this socket to the local address if necessary. */ - if (!vsock_addr_bound(&vsk->local_addr)) { - struct sockaddr_vm local_addr; - - vsock_addr_init(&local_addr, VMADDR_CID_ANY, - VMADDR_PORT_ANY); - err = __vsock_bind(sk, &local_addr); - if (err != 0) - goto out; - - } + err = vsock_auto_bind(vsk); + if (err) + goto out; sk->sk_state = SS_CONNECTING; -- GitLab From dce1a2877778fee172ab74411fcabd77bceb8e12 Mon Sep 17 00:00:00 2001 From: Asias He Date: Thu, 20 Jun 2013 17:20:31 +0800 Subject: [PATCH 1734/2900] VSOCK: Return VMCI_ERROR_NO_MEM when fails to allocate skb vmci_transport_recv_dgram_cb always return VMCI_SUCESS even if we fail to allocate skb, return VMCI_ERROR_NO_MEM instead. Signed-off-by: Asias He Acked-by: Andy King Signed-off-by: David S. Miller --- net/vmw_vsock/vmci_transport.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index daff75200e25..99b511ddb4cb 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -625,13 +625,14 @@ static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg) /* Attach the packet to the socket's receive queue as an sk_buff. */ skb = alloc_skb(size, GFP_ATOMIC); - if (skb) { - /* sk_receive_skb() will do a sock_put(), so hold here. */ - sock_hold(sk); - skb_put(skb, size); - memcpy(skb->data, dg, size); - sk_receive_skb(sk, skb, 0); - } + if (!skb) + return VMCI_ERROR_NO_MEM; + + /* sk_receive_skb() will do a sock_put(), so hold here. */ + sock_hold(sk); + skb_put(skb, size); + memcpy(skb->data, dg, size); + sk_receive_skb(sk, skb, 0); return VMCI_SUCCESS; } -- GitLab From 0fc932467688e1c81fc109a93f323cef4993dc24 Mon Sep 17 00:00:00 2001 From: Asias He Date: Thu, 20 Jun 2013 17:20:32 +0800 Subject: [PATCH 1735/2900] VSOCK: Remove unnecessary label Signed-off-by: Asias He Acked-by: Andy King Signed-off-by: David S. Miller --- net/vmw_vsock/vmci_transport.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 99b511ddb4cb..ffc11df02af2 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -940,10 +940,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work) * reset to prevent that. */ vmci_transport_send_reset(sk, pkt); - goto out; + break; } -out: release_sock(sk); kfree(recv_pkt_info); /* Release reference obtained in the stream callback when we fetched -- GitLab From a49dd9dcb50195b35a5e59eb65b8e56584874630 Mon Sep 17 00:00:00 2001 From: Asias He Date: Thu, 20 Jun 2013 17:20:33 +0800 Subject: [PATCH 1736/2900] VSOCK: Fix VSOCK_HASH and VSOCK_CONN_HASH If we mod with VSOCK_HASH_SIZE -1, we get 0, 1, .... 249. Actually, we have vsock_bind_table[0 ... 250] and vsock_connected_table[0 .. 250]. In this case the last entry will never be used. We should mod with VSOCK_HASH_SIZE instead. Signed-off-by: Asias He Acked-by: Andy King Signed-off-by: David S. Miller --- net/vmw_vsock/af_vsock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index b0b362ad051d..593071dabd1c 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -144,18 +144,18 @@ EXPORT_SYMBOL_GPL(vm_sockets_get_local_cid); * VSOCK_HASH_SIZE + 1 so that vsock_bind_table[0] through * vsock_bind_table[VSOCK_HASH_SIZE - 1] are for bound sockets and * vsock_bind_table[VSOCK_HASH_SIZE] is for unbound sockets. The hash function - * mods with VSOCK_HASH_SIZE - 1 to ensure this. + * mods with VSOCK_HASH_SIZE to ensure this. */ #define VSOCK_HASH_SIZE 251 #define MAX_PORT_RETRIES 24 -#define VSOCK_HASH(addr) ((addr)->svm_port % (VSOCK_HASH_SIZE - 1)) +#define VSOCK_HASH(addr) ((addr)->svm_port % VSOCK_HASH_SIZE) #define vsock_bound_sockets(addr) (&vsock_bind_table[VSOCK_HASH(addr)]) #define vsock_unbound_sockets (&vsock_bind_table[VSOCK_HASH_SIZE]) /* XXX This can probably be implemented in a better way. */ #define VSOCK_CONN_HASH(src, dst) \ - (((src)->svm_cid ^ (dst)->svm_port) % (VSOCK_HASH_SIZE - 1)) + (((src)->svm_cid ^ (dst)->svm_port) % VSOCK_HASH_SIZE) #define vsock_connected_sockets(src, dst) \ (&vsock_connected_table[VSOCK_CONN_HASH(src, dst)]) #define vsock_connected_sockets_vsk(vsk) \ -- GitLab From 78c3bcc5d1af64f51d9f30b0f5a2d1985bf69734 Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Thu, 20 Jun 2013 17:39:08 +0300 Subject: [PATCH 1737/2900] bnx2x: Improve PF behaviour toward VF If PF is unloaded with loaded VFs, signal towards VFs so they can detect this gracefully. Signed-off-by: Ariel Elior Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein ---- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 ++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 3 +++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 23 +++++++++++++++++++--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 24 ++++++++++++++++++++--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 ++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 12 +++++++++++- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 5 ++++- 7 files changed, 63 insertions(+), 8 deletions(-) Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 ++ .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 3 +++ .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 23 +++++++++++++++--- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 24 ++++++++++++++++--- .../net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 ++ .../net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 12 +++++++++- .../net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h | 5 +++- 7 files changed, 63 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index edda716fdce4..dedbd76c033e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1330,6 +1330,7 @@ enum { BNX2X_SP_RTNL_AFEX_F_UPDATE, BNX2X_SP_RTNL_ENABLE_SRIOV, BNX2X_SP_RTNL_VFPF_MCAST, + BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN, BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, BNX2X_SP_RTNL_HYPERVISOR_VLAN, }; @@ -1500,6 +1501,7 @@ struct bnx2x { #define USING_SINGLE_MSIX_FLAG (1 << 20) #define BC_SUPPORTS_DCBX_MSG_NON_PMF (1 << 21) #define IS_VF_FLAG (1 << 22) +#define INTERRUPTS_ENABLED_FLAG (1 << 23) #define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ca7f2bb08f44..d342c5a34afc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2871,6 +2871,9 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link) bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; smp_mb(); + /* indicate to VFs that the PF is going down */ + bnx2x_iov_channel_down(bp); + if (CNIC_LOADED(bp)) bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index c962d66a1a79..7a7e326b3509 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -5457,9 +5457,19 @@ static void bnx2x_timer(unsigned long data) bnx2x_stats_handle(bp, STATS_EVENT_UPDATE); /* sample pf vf bulletin board for new posts from pf */ - if (IS_VF(bp)) + if (IS_VF(bp)) { bnx2x_sample_bulletin(bp); + /* if channel is down we need to self destruct */ + if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN) { + smp_mb__before_clear_bit(); + set_bit(BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN, + &bp->sp_rtnl_state); + smp_mb__after_clear_bit(); + schedule_delayed_work(&bp->sp_rtnl_task, 0); + } + } + mod_timer(&bp->timer, jiffies + bp->current_interval); } @@ -9620,6 +9630,13 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) "sending set mcast vf pf channel message from rtnl sp-task\n"); bnx2x_vfpf_set_mcast(bp->dev); } + if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN, + &bp->sp_rtnl_state)){ + if (!test_bit(__LINK_STATE_NOCARRIER, &bp->dev->state)) { + bnx2x_tx_disable(bp); + BNX2X_ERR("PF indicated channel is not servicable anymore. This means this VF device is no longer operational\n"); + } + } if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE, &bp->sp_rtnl_state)) { @@ -12814,6 +12831,8 @@ static void __bnx2x_remove(struct pci_dev *pdev, rtnl_unlock(); } + bnx2x_iov_remove_one(bp); + /* Power on: we can't let PCI layer write to us while we are in D3 */ if (IS_PF(bp)) bnx2x_set_power_state(bp, PCI_D0); @@ -12828,8 +12847,6 @@ static void __bnx2x_remove(struct pci_dev *pdev, /* Make sure RESET task is not scheduled before continuing */ cancel_delayed_work_sync(&bp->sp_rtnl_task); - bnx2x_iov_remove_one(bp); - /* send message via vfpf channel to release the resources of this vf */ if (IS_VF(bp)) bnx2x_vfpf_release(bp); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 8a556dd888d5..2a8ad6d4b540 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1459,13 +1459,11 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) struct bnx2x_virtf *vf = bnx2x_vf_by_abs_fid(bp, abs_vfid); if (!vf) - goto unknown_dev; + return false; dev = pci_get_bus_and_slot(vf->bus, vf->devfn); if (dev) return bnx2x_is_pcie_pending(dev); - -unknown_dev: return false; } @@ -3469,3 +3467,23 @@ int bnx2x_open_epilog(struct bnx2x *bp) return 0; } + +void bnx2x_iov_channel_down(struct bnx2x *bp) +{ + int vf_idx; + struct pf_vf_bulletin_content *bulletin; + + if (!IS_SRIOV(bp)) + return; + + for_each_vf(bp, vf_idx) { + /* locate this VFs bulletin board and update the channel down + * bit + */ + bulletin = BP_VF_BULLETIN(bp, vf_idx); + bulletin->valid_bitmap |= 1 << CHANNEL_DOWN; + + /* update vf bulletin board */ + bnx2x_post_vf_bulletin(bp, vf_idx); + } +} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index f08c604a4fbd..9fc029ed9547 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -761,6 +761,7 @@ static inline int bnx2x_vf_headroom(struct bnx2x *bp) } void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp); int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs); +void bnx2x_iov_channel_down(struct bnx2x *bp); int bnx2x_open_epilog(struct bnx2x *bp); #else /* CONFIG_BNX2X_SRIOV */ @@ -817,6 +818,7 @@ static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; } static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {} static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; } +static inline void bnx2x_iov_channel_down(struct bnx2x *bp) {} static inline int bnx2x_open_epilog(struct bnx2x *bp) {return 0; } #endif /* CONFIG_BNX2X_SRIOV */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 861809d3154b..2088063151d6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -113,7 +113,7 @@ static int bnx2x_send_msg2pf(struct bnx2x *bp, u8 *done, dma_addr_t msg_mapping) { struct cstorm_vf_zone_data __iomem *zone_data = REG_ADDR(bp, PXP_VF_ADDR_CSDM_GLOBAL_START); - int tout = 600, interval = 100; /* wait for 60 seconds */ + int tout = 100, interval = 100; /* wait for 10 seconds */ if (*done) { BNX2X_ERR("done was non zero before message to pf was sent\n"); @@ -121,6 +121,16 @@ static int bnx2x_send_msg2pf(struct bnx2x *bp, u8 *done, dma_addr_t msg_mapping) return -EINVAL; } + /* if PF indicated channel is down avoid sending message. Return success + * so calling flow can continue + */ + bnx2x_sample_bulletin(bp); + if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN) { + DP(BNX2X_MSG_IOV, "detecting channel down. Aborting message\n"); + *done = PFVF_STATUS_SUCCESS; + return 0; + } + /* Write message address */ writel(U64_LO(msg_mapping), &zone_data->non_trigger.vf_pf_channel.msg_addr_lo); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h index 41708faab575..f3ad174a3a63 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h @@ -331,7 +331,10 @@ struct pf_vf_bulletin_content { #define VLAN_VALID 1 /* when set, the vf should not access * the vfpf channel */ - +#define CHANNEL_DOWN 2 /* vfpf channel is disabled. VFs are not + * to attempt to send messages on the + * channel after this bit is set + */ u8 mac[ETH_ALEN]; u8 mac_padding[2]; -- GitLab From af902ae4432ba8650a5f16a2cca58507a5f566bd Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Thu, 20 Jun 2013 17:39:09 +0300 Subject: [PATCH 1738/2900] bnx2x: VF ndo sanity If iproute2 VF callbacks are invoked before PF is loaded, abort gracefully. Signed-off-by: Ariel Elior Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index 2a8ad6d4b540..f6177baf20b7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -3083,6 +3083,11 @@ void bnx2x_disable_sriov(struct bnx2x *bp) static int bnx2x_vf_ndo_sanity(struct bnx2x *bp, int vfidx, struct bnx2x_virtf *vf) { + if (bp->state != BNX2X_STATE_OPEN) { + BNX2X_ERR("vf ndo called though PF is down\n"); + return -EINVAL; + } + if (!IS_SRIOV(bp)) { BNX2X_ERR("vf ndo called though sriov is disabled\n"); return -EINVAL; -- GitLab From 03c22ea3f0951f7c5395fe8348cb15100815268a Mon Sep 17 00:00:00 2001 From: Ariel Elior Date: Thu, 20 Jun 2013 17:39:10 +0300 Subject: [PATCH 1739/2900] bnx2x: improve VF timings Wait 100ms for FLR to complete in parallel over all VFs instead of serializing the waits (which can amount to several seconds with 64 VFs). Signed-off-by: Ariel Elior Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index f6177baf20b7..bda4d7e7fe7b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1469,9 +1469,6 @@ static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid) { - /* Wait 100ms */ - msleep(100); - /* Verify no pending pci transactions */ if (bnx2x_vf_is_pcie_pending(bp, abs_vfid)) BNX2X_ERR("PCIE Transactions still pending\n"); @@ -2174,6 +2171,9 @@ int bnx2x_iov_nic_init(struct bnx2x *bp) DP(BNX2X_MSG_IOV, "num of vfs: %d\n", (bp)->vfdb->sriov.nr_virtfn); + /* let FLR complete ... */ + msleep(100); + /* initialize vf database */ for_each_vf(bp, vfid) { struct bnx2x_virtf *vf = BP_VF(bp, vfid); @@ -2775,6 +2775,10 @@ int bnx2x_vf_init(struct bnx2x *bp, struct bnx2x_virtf *vf, dma_addr_t *sb_map) vf->abs_vfid, vf->state); return -EINVAL; } + + /* let FLR complete ... */ + msleep(100); + /* FLR cleanup epilogue */ if (bnx2x_vf_flr_clnup_epilog(bp, vf->abs_vfid)) return -EBUSY; -- GitLab From b8e0d884cba6b9cd6e43adfaab9e67096ee8fb28 Mon Sep 17 00:00:00 2001 From: Yaniv Rosner Date: Thu, 20 Jun 2013 17:39:11 +0300 Subject: [PATCH 1740/2900] bnx2x: Fix 20G KR2 support claims Don't claim 20G is supported if the speed is unsupported by the phys (reflected by various ethtools and ndos). Signed-off-by: Yaniv Rosner Signed-off-by: Yuval Mintz Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 7a7e326b3509..d468fe48093a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10558,6 +10558,10 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) if (!(bp->link_params.speed_cap_mask[idx] & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) bp->port.supported[idx] &= ~SUPPORTED_10000baseT_Full; + + if (!(bp->link_params.speed_cap_mask[idx] & + PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) + bp->port.supported[idx] &= ~SUPPORTED_20000baseKR2_Full; } BNX2X_DEV_INFO("supported 0x%x 0x%x\n", bp->port.supported[0], -- GitLab From 60877a32bce00041528576e6b8df5abe9251fa73 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 20 Jun 2013 01:15:51 -0700 Subject: [PATCH 1741/2900] net: allow large number of tx queues netif_alloc_netdev_queues() uses kcalloc() to allocate memory for the "struct netdev_queue *_tx" array. For large number of tx queues, kcalloc() might fail, so this patch does a fallback to vzalloc(). As vmalloc() adds overhead on a critical network path, add __GFP_REPEAT to kzalloc() flags to do this fallback only when really needed. Signed-off-by: Eric Dumazet Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- net/core/dev.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index fa007dba6beb..722f633926e0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -130,6 +130,7 @@ #include #include #include +#include #include "net-sysfs.h" @@ -5253,17 +5254,28 @@ static void netdev_init_one_queue(struct net_device *dev, #endif } +static void netif_free_tx_queues(struct net_device *dev) +{ + if (is_vmalloc_addr(dev->_tx)) + vfree(dev->_tx); + else + kfree(dev->_tx); +} + static int netif_alloc_netdev_queues(struct net_device *dev) { unsigned int count = dev->num_tx_queues; struct netdev_queue *tx; + size_t sz = count * sizeof(*tx); - BUG_ON(count < 1); - - tx = kcalloc(count, sizeof(struct netdev_queue), GFP_KERNEL); - if (!tx) - return -ENOMEM; + BUG_ON(count < 1 || count > 0xffff); + tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + if (!tx) { + tx = vzalloc(sz); + if (!tx) + return -ENOMEM; + } dev->_tx = tx; netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL); @@ -5811,7 +5823,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, free_pcpu: free_percpu(dev->pcpu_refcnt); - kfree(dev->_tx); + netif_free_tx_queues(dev); #ifdef CONFIG_RPS kfree(dev->_rx); #endif @@ -5836,7 +5848,7 @@ void free_netdev(struct net_device *dev) release_net(dev_net(dev)); - kfree(dev->_tx); + netif_free_tx_queues(dev); #ifdef CONFIG_RPS kfree(dev->_rx); #endif -- GitLab From 7c77602f57da3f526fa7cf7bb02c49d3397c0729 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Fri, 21 Jun 2013 15:37:25 +0800 Subject: [PATCH 1742/2900] bridge: fix a typo in comments Cc: Stephen Hemminger Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 31952a103949..81befac015e1 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1012,7 +1012,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br, #endif /* - * Add port to rotuer_list + * Add port to router_list * list is maintained ordered by pointer value * and locked by br->multicast_lock and RCU */ -- GitLab From 479b1a5825f68f9b63d26a13ca25ffbb7d2617ad Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 20 Jun 2013 15:08:14 -0700 Subject: [PATCH 1743/2900] openvswitch: Use correct config guard. This bug was introduced by commit aa310701e787087 (openvswitch: Add gre tunnel support.) Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/vport-gre.c | 2 +- net/openvswitch/vport.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 3a8d1900aa78..943e5c431354 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c @@ -16,7 +16,7 @@ * 02110-1301, USA */ -#ifdef CONFIG_NET_IPGRE_DEMUX +#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index f52dfb9cb5a7..ba81294219ac 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -39,7 +39,7 @@ static const struct vport_ops *vport_ops_list[] = { &ovs_netdev_vport_ops, &ovs_internal_vport_ops, -#ifdef CONFIG_NET_IPGRE_DEMUX +#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) &ovs_gre_vport_ops, #endif }; -- GitLab From 5243b6ac9ed1310f2329b3d0a830a55589e518ea Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Fri, 21 Jun 2013 16:17:11 -0700 Subject: [PATCH 1744/2900] ip_tunnel: Protect tunnel functions with CONFIG_INET guard. Tunnel constants can be used in generic code but in these cases the inline functions in ip_tunnels.h cause compilation problems if CONFIG_INET is not set. CC: Pravin Shelar Reported-by: Randy Dunlap Signed-off-by: Jesse Gross Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 10bbb4273f7d..b0d982471a5c 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -93,6 +93,8 @@ struct ip_tunnel_net { struct net_device *fb_tunnel_dev; }; +#ifdef CONFIG_INET + int ip_tunnel_init(struct net_device *dev); void ip_tunnel_uninit(struct net_device *dev); void ip_tunnel_dellink(struct net_device *dev, struct list_head *head); @@ -180,4 +182,7 @@ static inline void iptunnel_xmit_stats(int err, err_stats->tx_dropped++; } } + +#endif /* CONFIG_INET */ + #endif /* __NET_IP_TUNNELS_H */ -- GitLab From 07cc61bfc0e5d9da80e353365717d45d29db0081 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Jun 2013 09:20:08 +0300 Subject: [PATCH 1745/2900] xen-netback: double free on unload There is a typo here, "i" vs "j", so we would crash on module_exit(). Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index a0b50ad2ef31..130bcb217d2c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1968,8 +1968,8 @@ static void __exit netback_fini(void) del_timer_sync(&netbk->net_timer); kthread_stop(netbk->task); for (j = 0; j < MAX_PENDING_REQS; j++) { - if (netbk->mmap_pages[i]) - __free_page(netbk->mmap_pages[i]); + if (netbk->mmap_pages[j]) + __free_page(netbk->mmap_pages[j]); } } -- GitLab From aeb193ea6cef28e33589de05ef932424f8e19bde Mon Sep 17 00:00:00 2001 From: Wedson Almeida Filho Date: Sun, 23 Jun 2013 23:33:48 -0700 Subject: [PATCH 1746/2900] net: Unmap fragment page once iterator is done Callers of skb_seq_read() are currently forced to call skb_abort_seq_read() even when consuming all the data because the last call to skb_seq_read (the one that returns 0 to indicate the end) fails to unmap the last fragment page. With this patch callers will be allowed to traverse the SKB data by calling skb_prepare_seq_read() once and repeatedly calling skb_seq_read() as originally intended (and documented in the original commit 677e90eda), that is, only call skb_abort_seq_read() if the sequential read is actually aborted. Signed-off-by: Wedson Almeida Filho Signed-off-by: David S. Miller --- drivers/scsi/libiscsi_tcp.c | 1 - net/batman-adv/main.c | 1 - net/core/skbuff.c | 7 ++++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 552e8a2b6f5f..448eae850b9c 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -906,7 +906,6 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb, ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n", consumed); *status = ISCSI_TCP_SKB_DONE; - skb_abort_seq_read(&seq); goto skb_done; } BUG_ON(segment->copied >= segment->size); diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 51aafd669cbb..08125f3f6064 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -473,7 +473,6 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr) crc = crc32c(crc, data, len); consumed += len; } - skb_abort_seq_read(&st); return htonl(crc); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index edf37578e21e..9f73eca29fbe 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2541,8 +2541,13 @@ unsigned int skb_seq_read(unsigned int consumed, const u8 **data, unsigned int block_limit, abs_offset = consumed + st->lower_offset; skb_frag_t *frag; - if (unlikely(abs_offset >= st->upper_offset)) + if (unlikely(abs_offset >= st->upper_offset)) { + if (st->frag_data) { + kunmap_atomic(st->frag_data); + st->frag_data = NULL; + } return 0; + } next_skb: block_limit = skb_headlen(st->cur_skb) + st->stepped_offset; -- GitLab From 37173488400704f1a05656616cd12baa9e03173b Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 24 Jun 2013 11:04:10 +0300 Subject: [PATCH 1747/2900] bnx2x: Fix compilation with no IOV support This fixes an issue caused by submit 78c3bcc5d1af64f51d9f30b0f5a2d1985bf69734 `bnx2x: Improve PF behaviour toward VF', which made the bnx2x driver fail compilation when PCI_IOV is not set. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 14 ++------------ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 14 ++++++++++++++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h | 2 ++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index d468fe48093a..73189888766d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -5457,18 +5457,8 @@ static void bnx2x_timer(unsigned long data) bnx2x_stats_handle(bp, STATS_EVENT_UPDATE); /* sample pf vf bulletin board for new posts from pf */ - if (IS_VF(bp)) { - bnx2x_sample_bulletin(bp); - - /* if channel is down we need to self destruct */ - if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN) { - smp_mb__before_clear_bit(); - set_bit(BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN, - &bp->sp_rtnl_state); - smp_mb__after_clear_bit(); - schedule_delayed_work(&bp->sp_rtnl_task, 0); - } - } + if (IS_VF(bp)) + bnx2x_timer_sriov(bp); mod_timer(&bp->timer, jiffies + bp->current_interval); } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index bda4d7e7fe7b..95861efb5051 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -3426,6 +3426,20 @@ enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp) return PFVF_BULLETIN_UPDATED; } +void bnx2x_timer_sriov(struct bnx2x *bp) +{ + bnx2x_sample_bulletin(bp); + + /* if channel is down we need to self destruct */ + if (bp->old_bulletin.valid_bitmap & 1 << CHANNEL_DOWN) { + smp_mb__before_clear_bit(); + set_bit(BNX2X_SP_RTNL_VFPF_CHANNEL_DOWN, + &bp->sp_rtnl_state); + smp_mb__after_clear_bit(); + schedule_delayed_work(&bp->sp_rtnl_task, 0); + } +} + void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) { /* vf doorbells are embedded within the regview */ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 9fc029ed9547..d143a7cdbbbe 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -751,6 +751,7 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp, } enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp); +void bnx2x_timer_sriov(struct bnx2x *bp); void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp); int bnx2x_vf_pci_alloc(struct bnx2x *bp); int bnx2x_enable_sriov(struct bnx2x *bp); @@ -809,6 +810,7 @@ static inline enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp { return PFVF_BULLETIN_UNCHANGED; } +static inline void bnx2x_timer_sriov(struct bnx2x *bp) {} static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp) { -- GitLab From 6197ca8272d16b0c7f95764a2c88eb976347e38b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 23 Jun 2013 12:29:04 -0700 Subject: [PATCH 1748/2900] iommu: Use %pa and %zx instead of casting printk supports using %pa for phys_addr_t and %zx for size_t so use those instead of %lx and casts to unsigned long. Other miscellaneous changes around this: Always use 0x%zx for size instead of one use of decimal. Coalesce format and align arguments. Signed-off-by: Joe Perches Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ab1fa19ddddb..fbe9ca734f8f 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -807,20 +807,18 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, * size of the smallest page supported by the hardware */ if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) { - pr_err("unaligned: iova 0x%lx pa 0x%lx size 0x%lx min_pagesz " - "0x%x\n", iova, (unsigned long)paddr, - (unsigned long)size, min_pagesz); + pr_err("unaligned: iova 0x%lx pa 0x%pa size 0x%zx min_pagesz 0x%x\n", + iova, &paddr, size, min_pagesz); return -EINVAL; } - pr_debug("map: iova 0x%lx pa 0x%lx size 0x%lx\n", iova, - (unsigned long)paddr, (unsigned long)size); + pr_debug("map: iova 0x%lx pa 0x%pa size 0x%zx\n", iova, &paddr, size); while (size) { size_t pgsize = iommu_pgsize(domain, iova | paddr, size); - pr_debug("mapping: iova 0x%lx pa 0x%lx pgsize %lu\n", iova, - (unsigned long)paddr, (unsigned long)pgsize); + pr_debug("mapping: iova 0x%lx pa 0x%pa pgsize 0x%zx\n", + iova, &paddr, pgsize); ret = domain->ops->map(domain, iova, paddr, pgsize, prot); if (ret) @@ -857,13 +855,12 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) * by the hardware */ if (!IS_ALIGNED(iova | size, min_pagesz)) { - pr_err("unaligned: iova 0x%lx size 0x%lx min_pagesz 0x%x\n", - iova, (unsigned long)size, min_pagesz); + pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n", + iova, size, min_pagesz); return -EINVAL; } - pr_debug("unmap this: iova 0x%lx size 0x%lx\n", iova, - (unsigned long)size); + pr_debug("unmap this: iova 0x%lx size 0x%zx\n", iova, size); /* * Keep iterating until we either unmap 'size' bytes (or more) @@ -876,8 +873,8 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) if (!unmapped_page) break; - pr_debug("unmapped: iova 0x%lx size %lx\n", iova, - (unsigned long)unmapped_page); + pr_debug("unmapped: iova 0x%lx size 0x%zx\n", + iova, unmapped_page); iova += unmapped_page; unmapped += unmapped_page; -- GitLab From 4124e6e291a7b1a21ea7c28c8f9899d050103308 Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Thu, 20 Jun 2013 16:35:16 +0530 Subject: [PATCH 1749/2900] mfd: palmas: Add TPS659038 PMIC support The Patch adds TPS659038 PMIC support in the palmas mfd driver. The TPS659038 has almost the same registers as of the earlier supported variants of PALMAS family such as the TWL6035. The critical differences between TPS659038 and TWL6035 being: 1) TPS659038 has nothing related to battery charging and back up battery stuff. 2) TPS659038 does not have does not have SMPS10(Boost) step up convertor. 3) TPS659038 does not have Battery detection and anything related to battery. 4) SD card detection, Battery presence detection, Vibrator, USB OTG are missing when compared to TWL6035. Signed-off-by: J Keerthy Signed-off-by: Samuel Ortiz --- drivers/mfd/palmas.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index a4e53caa76cd..e4d1c706df8b 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c @@ -232,12 +232,17 @@ static void palmas_dt_to_pdata(struct i2c_client *i2c, } static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; +static unsigned int tps659038_features; static const struct of_device_id of_palmas_match_tbl[] = { { .compatible = "ti,palmas", .data = &palmas_features, }, + { + .compatible = "ti,tps659038", + .data = &tps659038_features, + }, { }, }; -- GitLab From 43620a17945b598e707ef897b3866914f9f9056c Mon Sep 17 00:00:00 2001 From: Kevin Strasser Date: Sun, 23 Jun 2013 21:00:03 -0700 Subject: [PATCH 1750/2900] mfd: Kontron PLD mfd driver Add core MFD driver for the on-board PLD found on some Kontron embedded modules. The PLD device may provide functions like watchdog, GPIO, UART and I2C bus. The following modules are supported: * COMe-bIP# * COMe-bPC2 (ETXexpress-PC) * COMe-bSC# (ETXexpress-SC T#) * COMe-cCT6 * COMe-cDC2 (microETXexpress-DC) * COMe-cPC2 (microETXexpress-PC) * COMe-mCT10 * ETX-OH Originally-From: Michael Brunner Signed-off-by: Kevin Strasser Acked-by: Guenter Roeck Acked-by: Darren Hart Acked-by: Thomas Gleixner Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 21 ++ drivers/mfd/Makefile | 1 + drivers/mfd/kempld-core.c | 641 +++++++++++++++++++++++++++++++++++++ include/linux/mfd/kempld.h | 125 ++++++++ 4 files changed, 788 insertions(+) create mode 100644 drivers/mfd/kempld-core.c create mode 100644 include/linux/mfd/kempld.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3e3be603cf82..3bb2932eafb1 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -242,6 +242,27 @@ config MFD_JZ4740_ADC Say yes here if you want support for the ADC unit in the JZ4740 SoC. This driver is necessary for jz4740-battery and jz4740-hwmon driver. +config MFD_KEMPLD + tristate "Kontron module PLD device" + select MFD_CORE + help + This is the core driver for the PLD (Programmable Logic Device) found + on some Kontron ETX and COMexpress (ETXexpress) modules. The PLD + device may provide functions like watchdog, GPIO, UART and I2C bus. + + The following modules are supported: + * COMe-bIP# + * COMe-bPC2 (ETXexpress-PC) + * COMe-bSC# (ETXexpress-SC T#) + * COMe-cCT6 + * COMe-cDC2 (microETXexpress-DC) + * COMe-cPC2 (microETXexpress-PC) + * COMe-mCT10 + * ETX-OH + + This driver can also be built as a module. If so, the module + will be called kempld-core. + config MFD_88PM800 tristate "Marvell 88PM800" depends on I2C=y && GENERIC_HARDIRQS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4d70cdb044e0..3c90051ffa5a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -129,6 +129,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o +obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o obj-$(CONFIG_LPC_SCH) += lpc_sch.o obj-$(CONFIG_LPC_ICH) += lpc_ich.o obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c new file mode 100644 index 000000000000..686a4565acb6 --- /dev/null +++ b/drivers/mfd/kempld-core.c @@ -0,0 +1,641 @@ +/* + * Kontron PLD MFD core driver + * + * Copyright (c) 2010-2013 Kontron Europe GmbH + * Author: Michael Brunner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_ID_LEN 4 +static char force_device_id[MAX_ID_LEN + 1] = ""; +module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0); +MODULE_PARM_DESC(force_device_id, "Override detected product"); + +/* + * Get hardware mutex to block firmware from accessing the pld. + * It is possible for the firmware may hold the mutex for an extended length of + * time. This function will block until access has been granted. + */ +static void kempld_get_hardware_mutex(struct kempld_device_data *pld) +{ + /* The mutex bit will read 1 until access has been granted */ + while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY) + msleep(1); +} + +static void kempld_release_hardware_mutex(struct kempld_device_data *pld) +{ + /* The harware mutex is released when 1 is written to the mutex bit. */ + iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); +} + +static int kempld_get_info_generic(struct kempld_device_data *pld) +{ + u16 version; + u8 spec; + + kempld_get_mutex(pld); + + version = kempld_read16(pld, KEMPLD_VERSION); + spec = kempld_read8(pld, KEMPLD_SPEC); + pld->info.buildnr = kempld_read16(pld, KEMPLD_BUILDNR); + + pld->info.minor = KEMPLD_VERSION_GET_MINOR(version); + pld->info.major = KEMPLD_VERSION_GET_MAJOR(version); + pld->info.number = KEMPLD_VERSION_GET_NUMBER(version); + pld->info.type = KEMPLD_VERSION_GET_TYPE(version); + + if (spec == 0xff) { + pld->info.spec_minor = 0; + pld->info.spec_major = 1; + } else { + pld->info.spec_minor = KEMPLD_SPEC_GET_MINOR(spec); + pld->info.spec_major = KEMPLD_SPEC_GET_MAJOR(spec); + } + + if (pld->info.spec_major > 0) + pld->feature_mask = kempld_read16(pld, KEMPLD_FEATURE); + else + pld->feature_mask = 0; + + kempld_release_mutex(pld); + + return 0; +} + +enum kempld_cells { + KEMPLD_I2C = 0, + KEMPLD_WDT, + KEMPLD_GPIO, + KEMPLD_UART, +}; + +static struct mfd_cell kempld_devs[] = { + [KEMPLD_I2C] = { + .name = "kempld-i2c", + }, + [KEMPLD_WDT] = { + .name = "kempld-wdt", + }, + [KEMPLD_GPIO] = { + .name = "kempld-gpio", + }, + [KEMPLD_UART] = { + .name = "kempld-uart", + }, +}; + +#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_devs) + +static int kempld_register_cells_generic(struct kempld_device_data *pld) +{ + struct mfd_cell devs[KEMPLD_MAX_DEVS]; + int i = 0; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C) + devs[i++] = kempld_devs[KEMPLD_I2C]; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG) + devs[i++] = kempld_devs[KEMPLD_WDT]; + + if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO) + devs[i++] = kempld_devs[KEMPLD_GPIO]; + + if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART) + devs[i++] = kempld_devs[KEMPLD_UART]; + + return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL); +} + +static struct resource kempld_ioresource = { + .start = KEMPLD_IOINDEX, + .end = KEMPLD_IODATA, + .flags = IORESOURCE_IO, +}; + +static const struct kempld_platform_data kempld_platform_data_generic = { + .pld_clock = KEMPLD_CLK, + .ioresource = &kempld_ioresource, + .get_hardware_mutex = kempld_get_hardware_mutex, + .release_hardware_mutex = kempld_release_hardware_mutex, + .get_info = kempld_get_info_generic, + .register_cells = kempld_register_cells_generic, +}; + +static struct platform_device *kempld_pdev; + +static int kempld_create_platform_device(const struct dmi_system_id *id) +{ + struct kempld_platform_data *pdata = id->driver_data; + int ret; + + kempld_pdev = platform_device_alloc("kempld", -1); + if (!kempld_pdev) + return -ENOMEM; + + ret = platform_device_add_data(kempld_pdev, pdata, sizeof(*pdata)); + if (ret) + goto err; + + ret = platform_device_add_resources(kempld_pdev, pdata->ioresource, 1); + if (ret) + goto err; + + ret = platform_device_add(kempld_pdev); + if (ret) + goto err; + + return 0; +err: + platform_device_put(kempld_pdev); + return ret; +} + +/** + * kempld_read8 - read 8 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u8 kempld_read8(struct kempld_device_data *pld, u8 index) +{ + iowrite8(index, pld->io_index); + return ioread8(pld->io_data); +} +EXPORT_SYMBOL_GPL(kempld_read8); + +/** + * kempld_write8 - write 8 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data) +{ + iowrite8(index, pld->io_index); + iowrite8(data, pld->io_data); +} +EXPORT_SYMBOL_GPL(kempld_write8); + +/** + * kempld_read16 - read 16 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u16 kempld_read16(struct kempld_device_data *pld, u8 index) +{ + return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8; +} +EXPORT_SYMBOL_GPL(kempld_read16); + +/** + * kempld_write16 - write 16 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data) +{ + kempld_write8(pld, index, (u8)data); + kempld_write8(pld, index + 1, (u8)(data >> 8)); +} +EXPORT_SYMBOL_GPL(kempld_write16); + +/** + * kempld_read32 - read 32 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * + * kempld_get_mutex must be called prior to calling this function. + */ +u32 kempld_read32(struct kempld_device_data *pld, u8 index) +{ + return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16; +} +EXPORT_SYMBOL_GPL(kempld_read32); + +/** + * kempld_write32 - write 32 bit register + * @pld: kempld_device_data structure describing the PLD + * @index: register index on the chip + * @data: new register value + * + * kempld_get_mutex must be called prior to calling this function. + */ +void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data) +{ + kempld_write16(pld, index, (u16)data); + kempld_write16(pld, index + 2, (u16)(data >> 16)); +} +EXPORT_SYMBOL_GPL(kempld_write32); + +/** + * kempld_get_mutex - acquire PLD mutex + * @pld: kempld_device_data structure describing the PLD + */ +void kempld_get_mutex(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + mutex_lock(&pld->lock); + pdata->get_hardware_mutex(pld); +} +EXPORT_SYMBOL_GPL(kempld_get_mutex); + +/** + * kempld_release_mutex - release PLD mutex + * @pld: kempld_device_data structure describing the PLD + */ +void kempld_release_mutex(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + pdata->release_hardware_mutex(pld); + mutex_unlock(&pld->lock); +} +EXPORT_SYMBOL_GPL(kempld_release_mutex); + +/** + * kempld_get_info - update device specific information + * @pld: kempld_device_data structure describing the PLD + * + * This function calls the configured board specific kempld_get_info_XXXX + * function which is responsible for gathering information about the specific + * hardware. The information is then stored within the pld structure. + */ +static int kempld_get_info(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + return pdata->get_info(pld); +} + +/* + * kempld_register_cells - register cell drivers + * + * This function registers cell drivers for the detected hardware by calling + * the configured kempld_register_cells_XXXX function which is responsible + * to detect and register the needed cell drivers. + */ +static int kempld_register_cells(struct kempld_device_data *pld) +{ + struct kempld_platform_data *pdata = pld->dev->platform_data; + + return pdata->register_cells(pld); +} + +static int kempld_detect_device(struct kempld_device_data *pld) +{ + char *version_type; + u8 index_reg; + int ret; + + mutex_lock(&pld->lock); + + /* Check for empty IO space */ + index_reg = ioread8(pld->io_index); + if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) { + mutex_unlock(&pld->lock); + return -ENODEV; + } + + /* Release hardware mutex if aquired */ + if (!(index_reg & KEMPLD_MUTEX_KEY)) + iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); + + mutex_unlock(&pld->lock); + + ret = kempld_get_info(pld); + if (ret) + return ret; + + switch (pld->info.type) { + case 0: + version_type = "release"; + break; + case 1: + version_type = "debug"; + break; + case 2: + version_type = "custom"; + break; + default: + version_type = "unspecified"; + } + + dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number); + dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n", + version_type, pld->info.major, pld->info.minor, + pld->info.buildnr, pld->info.spec_major, + pld->info.spec_minor); + + return kempld_register_cells(pld); +} + +static int kempld_probe(struct platform_device *pdev) +{ + struct kempld_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct kempld_device_data *pld; + struct resource *ioport; + int ret; + + pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); + if (!pld) + return -ENOMEM; + + ioport = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!ioport) + return -EINVAL; + + pld->io_base = devm_ioport_map(dev, ioport->start, + ioport->end - ioport->start); + if (!pld->io_base) + return -ENOMEM; + + pld->io_index = pld->io_base; + pld->io_data = pld->io_base + 1; + pld->pld_clock = pdata->pld_clock; + pld->dev = dev; + + mutex_init(&pld->lock); + platform_set_drvdata(pdev, pld); + + ret = kempld_detect_device(pld); + if (ret) + return ret; + + return 0; +} + +static int kempld_remove(struct platform_device *pdev) +{ + struct kempld_device_data *pld = platform_get_drvdata(pdev); + struct kempld_platform_data *pdata = pld->dev->platform_data; + + mfd_remove_devices(&pdev->dev); + pdata->release_hardware_mutex(pld); + + return 0; +} + +static struct platform_driver kempld_driver = { + .driver = { + .name = "kempld", + .owner = THIS_MODULE, + }, + .probe = kempld_probe, + .remove = kempld_remove, +}; + +static struct dmi_system_id __initdata kempld_dmi_table[] = { + { + .ident = "CCR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CCR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bIP6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-SC T6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXe-SC T6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CHR6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bSC6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETXexpress-PC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-bPC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "CNTX", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "PXT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "FRI2", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BIOS_VERSION, "FRI2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "FRI2", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "MBR1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "ETX-OH"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "nETXe-TT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NTC1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "NUP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-mCT"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-DC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNP1", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cDC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "microETXexpress-PC"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UNTG", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cPC2"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, { + .ident = "UUP6", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"), + DMI_MATCH(DMI_BOARD_NAME, "COMe-cCT6"), + }, + .driver_data = (void *)&kempld_platform_data_generic, + .callback = kempld_create_platform_device, + }, + {} +}; +MODULE_DEVICE_TABLE(dmi, kempld_dmi_table); + +static int __init kempld_init(void) +{ + const struct dmi_system_id *id; + int ret; + + if (force_device_id[0]) { + for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) + if (strstr(id->ident, force_device_id)) + if (id->callback && id->callback(id)) + break; + if (id->matches[0].slot == DMI_NONE) + return -ENODEV; + } else { + if (!dmi_check_system(kempld_dmi_table)) + return -ENODEV; + } + + ret = platform_driver_register(&kempld_driver); + if (ret) + return ret; + + return 0; +} + +static void __exit kempld_exit(void) +{ + if (kempld_pdev) + platform_device_unregister(kempld_pdev); + + platform_driver_unregister(&kempld_driver); +} + +module_init(kempld_init); +module_exit(kempld_exit); + +MODULE_DESCRIPTION("KEM PLD Core Driver"); +MODULE_AUTHOR("Michael Brunner "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:kempld-core"); diff --git a/include/linux/mfd/kempld.h b/include/linux/mfd/kempld.h new file mode 100644 index 000000000000..b911ef3add03 --- /dev/null +++ b/include/linux/mfd/kempld.h @@ -0,0 +1,125 @@ +/* + * Kontron PLD driver definitions + * + * Copyright (c) 2010-2012 Kontron Europe GmbH + * Author: Michael Brunner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + */ + +#ifndef _LINUX_MFD_KEMPLD_H_ +#define _LINUX_MFD_KEMPLD_H_ + +/* kempld register definitions */ +#define KEMPLD_IOINDEX 0xa80 +#define KEMPLD_IODATA 0xa81 +#define KEMPLD_MUTEX_KEY 0x80 +#define KEMPLD_VERSION 0x00 +#define KEMPLD_VERSION_LSB 0x00 +#define KEMPLD_VERSION_MSB 0x01 +#define KEMPLD_VERSION_GET_MINOR(x) (x & 0x1f) +#define KEMPLD_VERSION_GET_MAJOR(x) ((x >> 5) & 0x1f) +#define KEMPLD_VERSION_GET_NUMBER(x) ((x >> 10) & 0xf) +#define KEMPLD_VERSION_GET_TYPE(x) ((x >> 14) & 0x3) +#define KEMPLD_BUILDNR 0x02 +#define KEMPLD_BUILDNR_LSB 0x02 +#define KEMPLD_BUILDNR_MSB 0x03 +#define KEMPLD_FEATURE 0x04 +#define KEMPLD_FEATURE_LSB 0x04 +#define KEMPLD_FEATURE_MSB 0x05 +#define KEMPLD_FEATURE_BIT_I2C (1 << 0) +#define KEMPLD_FEATURE_BIT_WATCHDOG (1 << 1) +#define KEMPLD_FEATURE_BIT_GPIO (1 << 2) +#define KEMPLD_FEATURE_MASK_UART (7 << 3) +#define KEMPLD_FEATURE_BIT_NMI (1 << 8) +#define KEMPLD_FEATURE_BIT_SMI (1 << 9) +#define KEMPLD_FEATURE_BIT_SCI (1 << 10) +#define KEMPLD_SPEC 0x06 +#define KEMPLD_SPEC_GET_MINOR(x) (x & 0x0f) +#define KEMPLD_SPEC_GET_MAJOR(x) ((x >> 4) & 0x0f) +#define KEMPLD_IRQ_GPIO 0x35 +#define KEMPLD_IRQ_I2C 0x36 +#define KEMPLD_CFG 0x37 +#define KEMPLD_CFG_GPIO_I2C_MUX (1 << 0) +#define KEMPLD_CFG_BIOS_WP (1 << 7) + +#define KEMPLD_CLK 33333333 + +#define KEMPLD_TYPE_RELEASE 0x0 +#define KEMPLD_TYPE_DEBUG 0x1 +#define KEMPLD_TYPE_CUSTOM 0x2 + +/** + * struct kempld_info - PLD device information structure + * @major: PLD major revision + * @minor: PLD minor revision + * @buildnr: PLD build number + * @number: PLD board specific index + * @type: PLD type + * @spec_major: PLD FW specification major revision + * @spec_minor: PLD FW specification minor revision + */ +struct kempld_info { + unsigned int major; + unsigned int minor; + unsigned int buildnr; + unsigned int number; + unsigned int type; + unsigned int spec_major; + unsigned int spec_minor; +}; + +/** + * struct kempld_device_data - Internal representation of the PLD device + * @io_base: Pointer to the IO memory + * @io_index: Pointer to the IO index register + * @io_data: Pointer to the IO data register + * @pld_clock: PLD clock frequency + * @feature_mask: PLD feature mask + * @dev: Pointer to kernel device structure + * @info: KEMPLD info structure + * @lock: PLD mutex + */ +struct kempld_device_data { + void __iomem *io_base; + void __iomem *io_index; + void __iomem *io_data; + u32 pld_clock; + u32 feature_mask; + struct device *dev; + struct kempld_info info; + struct mutex lock; +}; + +/** + * struct kempld_platform_data - PLD hardware configuration structure + * @pld_clock: PLD clock frequency + * @gpio_base GPIO base pin number + * @ioresource: IO addresses of the PLD + * @get_mutex: PLD specific get_mutex callback + * @release_mutex: PLD specific release_mutex callback + * @get_info: PLD specific get_info callback + * @register_cells: PLD specific register_cells callback + */ +struct kempld_platform_data { + u32 pld_clock; + int gpio_base; + struct resource *ioresource; + void (*get_hardware_mutex) (struct kempld_device_data *); + void (*release_hardware_mutex) (struct kempld_device_data *); + int (*get_info) (struct kempld_device_data *); + int (*register_cells) (struct kempld_device_data *); +}; + +extern void kempld_get_mutex(struct kempld_device_data *pld); +extern void kempld_release_mutex(struct kempld_device_data *pld); +extern u8 kempld_read8(struct kempld_device_data *pld, u8 index); +extern void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data); +extern u16 kempld_read16(struct kempld_device_data *pld, u8 index); +extern void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data); +extern u32 kempld_read32(struct kempld_device_data *pld, u8 index); +extern void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data); + +#endif /* _LINUX_MFD_KEMPLD_H_ */ -- GitLab From c398ff00f55d56bec8eb116e9ad3d226998230fa Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Mon, 24 Jun 2013 08:48:37 -0400 Subject: [PATCH 1751/2900] kbuild: fix error when building from src rpm The following issue can be reproduced with Linus' tree on an x86_64 server. >+ cp /home/user/rpmbuild-test/BUILDROOT/kernel-3.9.2.x86_64/boot/vmlinuz-3.9.2 >cp: missing destination file operand after >/home/user/rpmbuild-test/BUILDROOT/kernel-3.9.2-1.x86_64/boot/vmlinuz-3.9.2' >Try `cp --help' for more information. >error: Bad exit status from /var/tmp/rpm-tmp.R4o0iI (%install) Here are the commands to reproduce: make defconfig make rpm-pkg Use the resulting src rpm to build as follows: mkdir ~/rpmbuild-test cd ~/rpmbuild-test rpmbuild --rebuild --define "_topdir `pwd`" -vv ~/rpmbuild/SRPMS/kernel-3.10.0_rc1+-1.src.rpm The issue is because the %install script uses $KBUILD_IMAGE and it hasn't been set since it is only available in the kbuild system and not in the %install script. This patch adds a Makefile target to emit the image_name that can be used and modifies the mkspec to use the dynamic name in %install. Signed-off-by: Mike Marciniszyn Signed-off-by: Michal Marek --- Makefile | 6 +++++- scripts/package/mkspec | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd11e8857604..6280aa192c36 100644 --- a/Makefile +++ b/Makefile @@ -1116,6 +1116,7 @@ help: @echo ' gtags - Generate GNU GLOBAL index' @echo ' kernelrelease - Output the release version string' @echo ' kernelversion - Output the version stored in Makefile' + @echo ' image_name - Output the image name' @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ echo ' (default: $(INSTALL_HDR_PATH))'; \ echo '' @@ -1310,7 +1311,7 @@ export_report: endif #ifeq ($(config-targets),1) endif #ifeq ($(mixed-targets),1) -PHONY += checkstack kernelrelease kernelversion +PHONY += checkstack kernelrelease kernelversion image_name # UML needs a little special treatment here. It wants to use the host # toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone @@ -1331,6 +1332,9 @@ kernelrelease: kernelversion: @echo $(KERNELVERSION) +image_name: + @echo $(KBUILD_IMAGE) + # Clear a bunch of variables before executing the submake tools/: FORCE $(Q)mkdir -p $(objtree)/tools diff --git a/scripts/package/mkspec b/scripts/package/mkspec index fbbfd08853d3..fdd3fbf4d4a4 100755 --- a/scripts/package/mkspec +++ b/scripts/package/mkspec @@ -74,6 +74,7 @@ echo "" fi echo "%install" +echo 'KBUILD_IMAGE=$(make image_name)' echo "%ifarch ia64" echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules' echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware' -- GitLab From 6f390908e58113b9199424749c32a05181ff69d9 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 19 Jun 2013 14:06:25 -0700 Subject: [PATCH 1752/2900] wireless: Make sure __cfg80211_connect_result always puts bss Otherwise, we can leak a bss reference. Signed-off-by: Ben Greear Signed-off-by: Johannes Berg --- net/wireless/sme.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index c0bf781d4fbe..32dac8cdd2e3 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -557,6 +557,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); * SME event handling */ +/* This method must consume bss one way or another */ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, @@ -572,8 +573,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, ASSERT_WDEV_LOCK(wdev); if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && - wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { + cfg80211_put_bss(wdev->wiphy, bss); return; + } nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid, req_ie, req_ie_len, -- GitLab From 0e3a39b5620bc84f25ffb0592b05b0350e8b0520 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 19 Jun 2013 14:06:27 -0700 Subject: [PATCH 1753/2900] wireless: add comments about bss refcounting Should help the next person that tries to understand the bss refcounting logic. Signed-off-by: Ben Greear Signed-off-by: Johannes Berg --- net/wireless/scan.c | 4 ++++ net/wireless/sme.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index dd01b58fa78c..ae8c186b50d6 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -523,6 +523,7 @@ static int cmp_bss(struct cfg80211_bss *a, } } +/* Returned bss is reference counted and must be cleaned up appropriately. */ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, const u8 *bssid, @@ -678,6 +679,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, return true; } +/* Returned bss is reference counted and must be cleaned up appropriately. */ static struct cfg80211_internal_bss * cfg80211_bss_update(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *tmp) @@ -866,6 +868,7 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, return channel; } +/* Returned bss is reference counted and must be cleaned up appropriately. */ struct cfg80211_bss* cfg80211_inform_bss(struct wiphy *wiphy, struct ieee80211_channel *channel, @@ -923,6 +926,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_inform_bss); +/* Returned bss is reference counted and must be cleaned up appropriately. */ struct cfg80211_bss * cfg80211_inform_bss_frame(struct wiphy *wiphy, struct ieee80211_channel *channel, diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 32dac8cdd2e3..1d3cfb1a3f28 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -239,6 +239,7 @@ void cfg80211_conn_work(struct work_struct *work) rtnl_unlock(); } +/* Returned bss is reference counted and must be cleaned up appropriately. */ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -699,6 +700,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, } EXPORT_SYMBOL(cfg80211_connect_result); +/* Consumes bss object one way or another */ void __cfg80211_roamed(struct wireless_dev *wdev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, @@ -775,6 +777,7 @@ void cfg80211_roamed(struct net_device *dev, } EXPORT_SYMBOL(cfg80211_roamed); +/* Consumes bss object one way or another */ void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, -- GitLab From f9bef3df52fe61067e4c1c6cfb2037cb6b259a6a Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 19 Jun 2013 14:06:26 -0700 Subject: [PATCH 1754/2900] wireless: check for dangling wdev->current_bss pointer If it *is* still set when the netdev is being deleted, then we are about to leak a pointer. Warn and clean up in that case. Signed-off-by: Ben Greear Signed-off-by: Johannes Berg --- net/wireless/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/wireless/core.c b/net/wireless/core.c index 4224e7554a76..672459b9483b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -934,6 +934,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, * freed. */ cfg80211_process_wdev_events(wdev); + + if (WARN_ON(wdev->current_bss)) { + cfg80211_unhold_bss(wdev->current_bss); + cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + wdev->current_bss = NULL; + } break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) -- GitLab From a33d402610d2d3a422136defe8237f4ddfb69fd9 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Sun, 23 Jun 2013 12:51:21 +0200 Subject: [PATCH 1755/2900] cfg80211: fix compilation warning for cfg80211_leave_all() The following compilation issue popped up moving from v3.10-rc1 to v3.10-rc6 after merging wireless-testing. net/wireless/sysfs.c:86:13: error: 'cfg80211_leave_all' defined but not used [-Werror=unused-function] The function is only called when CONFIG_PM is enabled. Moving the function under CONFIG_PM as well. Signed-off-by: Arend van Spriel Signed-off-by: Johannes Berg --- net/wireless/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 360a42c6f694..a23253e06358 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -83,6 +83,7 @@ static int wiphy_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +#ifdef CONFIG_PM static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) { struct wireless_dev *wdev; @@ -91,7 +92,6 @@ static void cfg80211_leave_all(struct cfg80211_registered_device *rdev) cfg80211_leave(rdev, wdev); } -#ifdef CONFIG_PM static int wiphy_suspend(struct device *dev, pm_message_t state) { struct cfg80211_registered_device *rdev = dev_to_rdev(dev); -- GitLab From ac49e1a8969eeb819c4fc2eced9ee9ef9f35a4a9 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 20 Jun 2013 23:50:58 -0700 Subject: [PATCH 1756/2900] mac80211: allow self-protected frame tx without sta Useful for userspace mesh to authenticate and peer without a station entry, since both steps may fail anyway. Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 93120de776f0..8184d121ff09 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2827,7 +2827,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, !rcu_access_pointer(sdata->bss->beacon)) need_offchan = true; if (!ieee80211_is_action(mgmt->frame_control) || - mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) + mgmt->u.action.category == WLAN_CATEGORY_PUBLIC || + mgmt->u.action.category == WLAN_CATEGORY_SELF_PROTECTED) break; rcu_read_lock(); sta = sta_info_get(sdata, mgmt->da); -- GitLab From 6c7c4cbfd5f59c04a40af67ad72d14e19215ef36 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 20 Jun 2013 23:50:59 -0700 Subject: [PATCH 1757/2900] mac80211: initialize power mode for mesh STAs Previously the default mesh STA nonpeer power mode was UNKNOWN (0) make the default mesh STA power mode ACTIVE, to prevent unnecessary frame buffering while peering is not yet complete. Fixes a panic in ath9k_htc when adding stations from userspace, and mcast buffered frames are later released. Thanks to Bob Copeland for his help debugging this. Signed-off-by: Thomas Pedersen Signed-off-by: Johannes Berg --- net/mac80211/sta_info.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index aaf68d297221..aeb967a0aeed 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -347,6 +347,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, if (ieee80211_vif_is_mesh(&sdata->vif) && !sdata->u.mesh.user_mpm) init_timer(&sta->plink_timer); + sta->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; #endif memcpy(sta->sta.addr, addr, ETH_ALEN); -- GitLab From b7153984074e51a50dad905871b705e0d67aa147 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:09 -0700 Subject: [PATCH 1758/2900] vxlan: fix out of order operation on module removal If vxlan is removed with active vxlan's it would crash because rtnl_link_unregister (which calls vxlan_dellink), was invoked before unregister_pernet_device (which calls vxlan_stop). Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 284c6c00c353..d3005d3a768d 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1771,8 +1771,8 @@ late_initcall(vxlan_init_module); static void __exit vxlan_cleanup_module(void) { - rtnl_link_unregister(&vxlan_link_ops); unregister_pernet_device(&vxlan_net_ops); + rtnl_link_unregister(&vxlan_link_ops); rcu_barrier(); } module_exit(vxlan_cleanup_module); -- GitLab From 758c57d16adcbec3c03e85f0c9a5b4ca31f6c507 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:09 -0700 Subject: [PATCH 1759/2900] vxlan: fix crash from work pending on module removal Switch to using a per module work queue so that all the socket deletion callbacks are done when module is removed. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d3005d3a768d..eb94bf5812cb 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -148,6 +148,7 @@ struct vxlan_dev { /* salt for hash table */ static u32 vxlan_salt __read_mostly; +static struct workqueue_struct *vxlan_wq; /* Virtual Network hash table head */ static inline struct hlist_head *vni_head(struct vxlan_sock *vs, u32 id) @@ -1631,7 +1632,7 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head) if (--vs->refcnt == 0) { hlist_del_rcu(&vs->hlist); - schedule_work(&vs->del_work); + queue_work(vxlan_wq, &vs->del_work); } } @@ -1750,6 +1751,10 @@ static int __init vxlan_init_module(void) { int rc; + vxlan_wq = alloc_workqueue("vxlan", 0, 0); + if (!vxlan_wq) + return -ENOMEM; + get_random_bytes(&vxlan_salt, sizeof(vxlan_salt)); rc = register_pernet_device(&vxlan_net_ops); @@ -1765,6 +1770,7 @@ static int __init vxlan_init_module(void) out2: unregister_pernet_device(&vxlan_net_ops); out1: + destroy_workqueue(vxlan_wq); return rc; } late_initcall(vxlan_init_module); @@ -1773,6 +1779,7 @@ static void __exit vxlan_cleanup_module(void) { unregister_pernet_device(&vxlan_net_ops); rtnl_link_unregister(&vxlan_link_ops); + destroy_workqueue(vxlan_wq); rcu_barrier(); } module_exit(vxlan_cleanup_module); -- GitLab From 7c47cedf43a8b3086c3dcf26cbc058747ee21bec Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:10 -0700 Subject: [PATCH 1760/2900] vxlan: move IGMP join/leave to work queue Do join/leave from work queue to avoid lock inversion problems between normal socket and RTNL. The code comes out cleaner as well. Uses Cong Wang's suggestion to turn refcnt into a real atomic since now need to handle case where last use of socket is IGMP worker. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 103 +++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 63 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index eb94bf5812cb..b061c98474ee 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -85,7 +85,7 @@ struct vxlan_sock { struct hlist_node hlist; struct rcu_head rcu; struct work_struct del_work; - unsigned int refcnt; + atomic_t refcnt; struct socket *sock; struct hlist_head vni_list[VNI_HASH_SIZE]; }; @@ -131,6 +131,7 @@ struct vxlan_dev { __u8 ttl; u32 flags; /* VXLAN_F_* below */ + struct work_struct igmp_work; unsigned long age_interval; struct timer_list age_timer; spinlock_t hash_lock; @@ -648,76 +649,58 @@ static bool vxlan_snoop(struct net_device *dev, /* See if multicast group is already in use by other ID */ -static bool vxlan_group_used(struct vxlan_net *vn, - const struct vxlan_dev *this) +static bool vxlan_group_used(struct vxlan_net *vn, __be32 remote_ip) { struct vxlan_dev *vxlan; list_for_each_entry(vxlan, &vn->vxlan_list, next) { - if (vxlan == this) - continue; - if (!netif_running(vxlan->dev)) continue; - if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip) + if (vxlan->default_dst.remote_ip == remote_ip) return true; } return false; } -/* kernel equivalent to IP_ADD_MEMBERSHIP */ -static int vxlan_join_group(struct net_device *dev) +static void vxlan_sock_hold(struct vxlan_sock *vs) { - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct sock *sk = vxlan->vn_sock->sock->sk; - struct ip_mreqn mreq = { - .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, - .imr_ifindex = vxlan->default_dst.remote_ifindex, - }; - int err; - - /* Already a member of group */ - if (vxlan_group_used(vn, vxlan)) - return 0; + atomic_inc(&vs->refcnt); +} - /* Need to drop RTNL to call multicast join */ - rtnl_unlock(); - lock_sock(sk); - err = ip_mc_join_group(sk, &mreq); - release_sock(sk); - rtnl_lock(); +static void vxlan_sock_release(struct vxlan_sock *vs) +{ + if (!atomic_dec_and_test(&vs->refcnt)) + return; - return err; + hlist_del_rcu(&vs->hlist); + queue_work(vxlan_wq, &vs->del_work); } - -/* kernel equivalent to IP_DROP_MEMBERSHIP */ -static int vxlan_leave_group(struct net_device *dev) +/* Callback to update multicast group membership. + * Scheduled when vxlan goes up/down. + */ +static void vxlan_igmp_work(struct work_struct *work) { - struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - int err = 0; - struct sock *sk = vxlan->vn_sock->sock->sk; + struct vxlan_dev *vxlan = container_of(work, struct vxlan_dev, igmp_work); + struct vxlan_net *vn = net_generic(dev_net(vxlan->dev), vxlan_net_id); + struct vxlan_sock *vs = vxlan->vn_sock; + struct sock *sk = vs->sock->sk; struct ip_mreqn mreq = { .imr_multiaddr.s_addr = vxlan->default_dst.remote_ip, .imr_ifindex = vxlan->default_dst.remote_ifindex, }; - /* Only leave group when last vxlan is done. */ - if (vxlan_group_used(vn, vxlan)) - return 0; - - /* Need to drop RTNL to call multicast leave */ - rtnl_unlock(); lock_sock(sk); - err = ip_mc_leave_group(sk, &mreq); + if (vxlan_group_used(vn, vxlan->default_dst.remote_ip)) + ip_mc_join_group(sk, &mreq); + else + ip_mc_leave_group(sk, &mreq); release_sock(sk); - rtnl_lock(); - return err; + vxlan_sock_release(vs); + dev_put(vxlan->dev); } /* Callback from net/ipv4/udp.c to receive packets */ @@ -1249,12 +1232,11 @@ static int vxlan_init(struct net_device *dev) static int vxlan_open(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); - int err; if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { - err = vxlan_join_group(dev); - if (err) - return err; + vxlan_sock_hold(vxlan->vn_sock); + dev_hold(dev); + queue_work(vxlan_wq, &vxlan->igmp_work); } if (vxlan->age_interval) @@ -1285,8 +1267,11 @@ static int vxlan_stop(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); - if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) - vxlan_leave_group(dev); + if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { + vxlan_sock_hold(vxlan->vn_sock); + dev_hold(dev); + queue_work(vxlan_wq, &vxlan->igmp_work); + } del_timer_sync(&vxlan->age_timer); @@ -1355,6 +1340,7 @@ static void vxlan_setup(struct net_device *dev) INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); + INIT_WORK(&vxlan->igmp_work, vxlan_igmp_work); init_timer_deferrable(&vxlan->age_timer); vxlan->age_timer.function = vxlan_cleanup; @@ -1498,8 +1484,8 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) udp_sk(sk)->encap_type = 1; udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv; udp_encap_enable(); + atomic_set(&vs->refcnt, 1); - vs->refcnt = 1; return vs; } @@ -1589,7 +1575,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, vs = vxlan_find_port(net, vxlan->dst_port); if (vs) - ++vs->refcnt; + atomic_inc(&vs->refcnt); else { /* Drop lock because socket create acquires RTNL lock */ rtnl_unlock(); @@ -1606,12 +1592,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, err = register_netdevice(dev); if (err) { - if (--vs->refcnt == 0) { - rtnl_unlock(); - sk_release_kernel(vs->sock->sk); - kfree(vs); - rtnl_lock(); - } + vxlan_sock_release(vs); return err; } @@ -1629,11 +1610,7 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head) hlist_del_rcu(&vxlan->hlist); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); - - if (--vs->refcnt == 0) { - hlist_del_rcu(&vs->hlist); - queue_work(vxlan_wq, &vs->del_work); - } + vxlan_sock_release(vs); } static size_t vxlan_get_size(const struct net_device *dev) -- GitLab From 8385f50a03a8ad3d2c6d76b1117c959261ab7a1c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:10 -0700 Subject: [PATCH 1761/2900] vxlan: send notification when MAC migrates When learned entry migrates to another IP send a notification that entry has changed. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index b061c98474ee..1f2aa26550e9 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -629,6 +629,7 @@ static bool vxlan_snoop(struct net_device *dev, f->remote.remote_ip = src_ip; f->updated = jiffies; + vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); } else { /* learned new entry */ spin_lock(&vxlan->hash_lock); -- GitLab From 1c51a9159ddefa5119724a4c7da3fd3ef44b68d5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:11 -0700 Subject: [PATCH 1762/2900] vxlan: fix race caused by dropping rtnl_unlock It is possible for two cpu's to race creating vxlan device. For most cases this is harmless, but the ability to assign "next avaliable vxlan device" relies on rtnl lock being held across the whole operation. Therfore two instances of calling: ip li add vxlan%d vxlan ... could collide and create two devices with same name. To fix this defer creation of socket to a work queue, and handle possible races there. Introduce a lock to ensure that changes to vxlan socket hash list is SMP safe. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 111 +++++++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 1f2aa26550e9..71da8be98801 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -94,6 +94,7 @@ struct vxlan_sock { struct vxlan_net { struct list_head vxlan_list; struct hlist_head sock_list[PORT_HASH_SIZE]; + spinlock_t sock_lock; }; struct vxlan_rdst { @@ -131,7 +132,9 @@ struct vxlan_dev { __u8 ttl; u32 flags; /* VXLAN_F_* below */ + struct work_struct sock_work; struct work_struct igmp_work; + unsigned long age_interval; struct timer_list age_timer; spinlock_t hash_lock; @@ -151,6 +154,8 @@ struct vxlan_dev { static u32 vxlan_salt __read_mostly; static struct workqueue_struct *vxlan_wq; +static void vxlan_sock_work(struct work_struct *work); + /* Virtual Network hash table head */ static inline struct hlist_head *vni_head(struct vxlan_sock *vs, u32 id) { @@ -670,12 +675,15 @@ static void vxlan_sock_hold(struct vxlan_sock *vs) atomic_inc(&vs->refcnt); } -static void vxlan_sock_release(struct vxlan_sock *vs) +static void vxlan_sock_release(struct vxlan_net *vn, struct vxlan_sock *vs) { if (!atomic_dec_and_test(&vs->refcnt)) return; + spin_lock(&vn->sock_lock); hlist_del_rcu(&vs->hlist); + spin_unlock(&vn->sock_lock); + queue_work(vxlan_wq, &vs->del_work); } @@ -700,7 +708,7 @@ static void vxlan_igmp_work(struct work_struct *work) ip_mc_leave_group(sk, &mreq); release_sock(sk); - vxlan_sock_release(vs); + vxlan_sock_release(vn, vs); dev_put(vxlan->dev); } @@ -1222,10 +1230,29 @@ static void vxlan_cleanup(unsigned long arg) /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); + struct vxlan_sock *vs; + __u32 vni = vxlan->default_dst.remote_vni; + dev->tstats = alloc_percpu(struct pcpu_tstats); if (!dev->tstats) return -ENOMEM; + spin_lock(&vn->sock_lock); + vs = vxlan_find_port(dev_net(dev), vxlan->dst_port); + if (vs) { + /* If we have a socket with same port already, reuse it */ + atomic_inc(&vs->refcnt); + vxlan->vn_sock = vs; + hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); + } else { + /* otherwise make new socket outside of RTNL */ + dev_hold(dev); + queue_work(vxlan_wq, &vxlan->sock_work); + } + spin_unlock(&vn->sock_lock); + return 0; } @@ -1233,9 +1260,14 @@ static int vxlan_init(struct net_device *dev) static int vxlan_open(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_sock *vs = vxlan->vn_sock; + + /* socket hasn't been created */ + if (!vs) + return -ENOTCONN; if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { - vxlan_sock_hold(vxlan->vn_sock); + vxlan_sock_hold(vs); dev_hold(dev); queue_work(vxlan_wq, &vxlan->igmp_work); } @@ -1267,9 +1299,10 @@ static void vxlan_flush(struct vxlan_dev *vxlan) static int vxlan_stop(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_sock *vs = vxlan->vn_sock; - if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { - vxlan_sock_hold(vxlan->vn_sock); + if (vs && IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) { + vxlan_sock_hold(vs); dev_hold(dev); queue_work(vxlan_wq, &vxlan->igmp_work); } @@ -1342,6 +1375,7 @@ static void vxlan_setup(struct net_device *dev) INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); INIT_WORK(&vxlan->igmp_work, vxlan_igmp_work); + INIT_WORK(&vxlan->sock_work, vxlan_sock_work); init_timer_deferrable(&vxlan->age_timer); vxlan->age_timer.function = vxlan_cleanup; @@ -1433,7 +1467,6 @@ static void vxlan_del_work(struct work_struct *work) kfree_rcu(vs, rcu); } -/* Create new listen socket if needed */ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) { struct vxlan_sock *vs; @@ -1490,13 +1523,52 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) return vs; } +/* Scheduled at device creation to bind to a socket */ +static void vxlan_sock_work(struct work_struct *work) +{ + struct vxlan_dev *vxlan + = container_of(work, struct vxlan_dev, sock_work); + struct net_device *dev = vxlan->dev; + struct net *net = dev_net(dev); + __u32 vni = vxlan->default_dst.remote_vni; + __be16 port = vxlan->dst_port; + struct vxlan_net *vn = net_generic(net, vxlan_net_id); + struct vxlan_sock *nvs, *ovs; + + nvs = vxlan_socket_create(net, port); + if (IS_ERR(nvs)) { + netdev_err(vxlan->dev, "Can not create UDP socket, %ld\n", + PTR_ERR(nvs)); + goto out; + } + + spin_lock(&vn->sock_lock); + /* Look again to see if can reuse socket */ + ovs = vxlan_find_port(net, port); + if (ovs) { + atomic_inc(&ovs->refcnt); + vxlan->vn_sock = ovs; + hlist_add_head_rcu(&vxlan->hlist, vni_head(ovs, vni)); + spin_unlock(&vn->sock_lock); + + sk_release_kernel(nvs->sock->sk); + kfree(nvs); + } else { + vxlan->vn_sock = nvs; + hlist_add_head_rcu(&nvs->hlist, vs_head(net, port)); + hlist_add_head_rcu(&vxlan->hlist, vni_head(nvs, vni)); + spin_unlock(&vn->sock_lock); + } +out: + dev_put(dev); +} + static int vxlan_newlink(struct net *net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; - struct vxlan_sock *vs; __u32 vni; int err; @@ -1574,31 +1646,13 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, return -EEXIST; } - vs = vxlan_find_port(net, vxlan->dst_port); - if (vs) - atomic_inc(&vs->refcnt); - else { - /* Drop lock because socket create acquires RTNL lock */ - rtnl_unlock(); - vs = vxlan_socket_create(net, vxlan->dst_port); - rtnl_lock(); - if (IS_ERR(vs)) - return PTR_ERR(vs); - - hlist_add_head_rcu(&vs->hlist, vs_head(net, vxlan->dst_port)); - } - vxlan->vn_sock = vs; - SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); err = register_netdevice(dev); - if (err) { - vxlan_sock_release(vs); + if (err) return err; - } list_add(&vxlan->next, &vn->vxlan_list); - hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); return 0; } @@ -1606,12 +1660,14 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; hlist_del_rcu(&vxlan->hlist); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); - vxlan_sock_release(vs); + if (vs) + vxlan_sock_release(vn, vs); } static size_t vxlan_get_size(const struct net_device *dev) @@ -1700,6 +1756,7 @@ static __net_init int vxlan_init_net(struct net *net) unsigned int h; INIT_LIST_HEAD(&vn->vxlan_list); + spin_lock_init(&vn->sock_lock); for (h = 0; h < PORT_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vn->sock_list[h]); -- GitLab From ebf4063e869d959daf75efb4ef1c7bc80dcd4800 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:11 -0700 Subject: [PATCH 1763/2900] vxlan: move cleanup to uninit Put destruction of per-cpu statistics removal in ndo_uninit since it is created by ndo_init. This also avoids any problems that might be cause by destructor being called after module removed. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 71da8be98801..500f9ce437ec 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1256,6 +1256,17 @@ static int vxlan_init(struct net_device *dev) return 0; } +static void vxlan_uninit(struct net_device *dev) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); + struct vxlan_sock *vs = vxlan->vn_sock; + + if (vs) + vxlan_sock_release(vn, vs); + free_percpu(dev->tstats); +} + /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { @@ -1321,6 +1332,7 @@ static void vxlan_set_multicast_list(struct net_device *dev) static const struct net_device_ops vxlan_netdev_ops = { .ndo_init = vxlan_init, + .ndo_uninit = vxlan_uninit, .ndo_open = vxlan_open, .ndo_stop = vxlan_stop, .ndo_start_xmit = vxlan_xmit, @@ -1339,12 +1351,6 @@ static struct device_type vxlan_type = { .name = "vxlan", }; -static void vxlan_free(struct net_device *dev) -{ - free_percpu(dev->tstats); - free_netdev(dev); -} - /* Initialize the device structure. */ static void vxlan_setup(struct net_device *dev) { @@ -1357,7 +1363,7 @@ static void vxlan_setup(struct net_device *dev) dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM; dev->netdev_ops = &vxlan_netdev_ops; - dev->destructor = vxlan_free; + dev->destructor = free_netdev; SET_NETDEV_DEVTYPE(dev, &vxlan_type); dev->tx_queue_len = 0; @@ -1660,14 +1666,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, static void vxlan_dellink(struct net_device *dev, struct list_head *head) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); - struct vxlan_sock *vs = vxlan->vn_sock; hlist_del_rcu(&vxlan->hlist); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); - if (vs) - vxlan_sock_release(vn, vs); } static size_t vxlan_get_size(const struct net_device *dev) -- GitLab From 4ad169300a7350a034b86c543070aed109882a86 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:11 -0700 Subject: [PATCH 1764/2900] vxlan: make vxlan_xmit_one void The function vxlan_xmit_one always returns NETDEV_TX_OK, so there is no point in keeping track of return values etc. Signed-off-by: Stephen Hemminger Acked-by: David L Stevens --- drivers/net/vxlan.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 500f9ce437ec..e65241c3d176 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1008,8 +1008,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, } } -static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, - struct vxlan_rdst *rdst, bool did_rsc) +static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + struct vxlan_rdst *rdst, bool did_rsc) { struct vxlan_dev *vxlan = netdev_priv(dev); struct rtable *rt; @@ -1032,7 +1032,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (did_rsc) { /* short-circuited back to local bridge */ vxlan_encap_bypass(skb, vxlan, vxlan); - return NETDEV_TX_OK; + return; } goto drop; } @@ -1088,7 +1088,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (!dst_vxlan) goto tx_error; vxlan_encap_bypass(skb, vxlan, dst_vxlan); - return NETDEV_TX_OK; + return; } vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_FLAGS); @@ -1116,7 +1116,7 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, IPPROTO_UDP, tos, ttl, df); iptunnel_xmit_stats(err, &dev->stats, dev->tstats); - return NETDEV_TX_OK; + return; drop: dev->stats.tx_dropped++; @@ -1126,7 +1126,6 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dev->stats.tx_errors++; tx_free: dev_kfree_skb(skb); - return NETDEV_TX_OK; } /* Transmit local packets over Vxlan @@ -1142,7 +1141,6 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) bool did_rsc = false; struct vxlan_rdst *rdst0, *rdst; struct vxlan_fdb *f; - int rc1, rc; skb_reset_mac_header(skb); eth = eth_hdr(skb); @@ -1170,24 +1168,18 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) } else rdst0 = &f->remote; - rc = NETDEV_TX_OK; /* if there are multiple destinations, send copies */ for (rdst = rdst0->remote_next; rdst; rdst = rdst->remote_next) { struct sk_buff *skb1; skb1 = skb_clone(skb, GFP_ATOMIC); - if (skb1) { - rc1 = vxlan_xmit_one(skb1, dev, rdst, did_rsc); - if (rc == NETDEV_TX_OK) - rc = rc1; - } + if (skb1) + vxlan_xmit_one(skb1, dev, rdst, did_rsc); } - rc1 = vxlan_xmit_one(skb, dev, rdst0, did_rsc); - if (rc == NETDEV_TX_OK) - rc = rc1; - return rc; + vxlan_xmit_one(skb, dev, rdst0, did_rsc); + return NETDEV_TX_OK; } /* Walk the forwarding table and purge stale entries */ -- GitLab From 3e61aa8f0a68e6e007c223688f442be04a44b0f4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:12 -0700 Subject: [PATCH 1765/2900] vxlan: convert remotes list to list_rcu Based on initial work by Mike Rapoport Use list macros and RCU for tracking multiple remotes. Note: this code assumes list always has at least one entry, because delete is not supported. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 97 +++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e65241c3d176..117b7fa6f33b 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -102,7 +102,7 @@ struct vxlan_rdst { __be16 remote_port; u32 remote_vni; u32 remote_ifindex; - struct vxlan_rdst *remote_next; + struct list_head list; }; /* Forwarding table entry */ @@ -111,7 +111,7 @@ struct vxlan_fdb { struct rcu_head rcu; unsigned long updated; /* jiffies */ unsigned long used; - struct vxlan_rdst remote; + struct list_head remotes; u16 state; /* see ndm_state */ u8 flags; /* see ndm_flags */ u8 eth_addr[ETH_ALEN]; @@ -170,6 +170,14 @@ static inline struct hlist_head *vs_head(struct net *net, __be16 port) return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; } +/* First remote destination for a forwarding entry. + * Guaranteed to be non-NULL because remotes are never deleted. + */ +static inline struct vxlan_rdst *first_remote(struct vxlan_fdb *fdb) +{ + return list_first_or_null_rcu(&fdb->remotes, struct vxlan_rdst, list); +} + /* Find VXLAN socket based on network namespace and UDP port */ static struct vxlan_sock *vxlan_find_port(struct net *net, __be16 port) { @@ -275,7 +283,7 @@ static inline size_t vxlan_nlmsg_size(void) } static void vxlan_fdb_notify(struct vxlan_dev *vxlan, - const struct vxlan_fdb *fdb, int type) + struct vxlan_fdb *fdb, int type) { struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; @@ -285,7 +293,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, if (skb == NULL) goto errout; - err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, &fdb->remote); + err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, first_remote(fdb)); if (err < 0) { /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); @@ -304,11 +312,16 @@ static void vxlan_ip_miss(struct net_device *dev, __be32 ipa) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb f; + struct vxlan_rdst remote; memset(&f, 0, sizeof f); f.state = NUD_STALE; - f.remote.remote_ip = ipa; /* goes to NDA_DST */ - f.remote.remote_vni = VXLAN_N_VID; + + remote.remote_ip = ipa; /* goes to NDA_DST */ + remote.remote_vni = VXLAN_N_VID; + + INIT_LIST_HEAD(&f.remotes); + list_add_rcu(&remote.list, &f.remotes); vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); } @@ -318,6 +331,7 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) struct vxlan_fdb f; memset(&f, 0, sizeof f); + INIT_LIST_HEAD(&f.remotes); f.state = NUD_STALE; memcpy(f.eth_addr, eth_addr, ETH_ALEN); @@ -377,17 +391,17 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, static int vxlan_fdb_append(struct vxlan_fdb *f, __be32 ip, __be16 port, __u32 vni, __u32 ifindex) { - struct vxlan_rdst *rd_prev, *rd; + struct vxlan_rdst *rd; - rd_prev = NULL; - for (rd = &f->remote; rd; rd = rd->remote_next) { + /* protected by vxlan->hash_lock */ + list_for_each_entry(rd, &f->remotes, list) { if (rd->remote_ip == ip && rd->remote_port == port && rd->remote_vni == vni && rd->remote_ifindex == ifindex) return 0; - rd_prev = rd; } + rd = kmalloc(sizeof(*rd), GFP_ATOMIC); if (rd == NULL) return -ENOBUFS; @@ -395,8 +409,9 @@ static int vxlan_fdb_append(struct vxlan_fdb *f, rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; - rd->remote_next = NULL; - rd_prev->remote_next = rd; + + list_add_tail_rcu(&rd->list, &f->remotes); + return 1; } @@ -448,16 +463,14 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, return -ENOMEM; notify = 1; - f->remote.remote_ip = ip; - f->remote.remote_port = port; - f->remote.remote_vni = vni; - f->remote.remote_ifindex = ifindex; - f->remote.remote_next = NULL; f->state = state; f->flags = ndm_flags; f->updated = f->used = jiffies; + INIT_LIST_HEAD(&f->remotes); memcpy(f->eth_addr, mac, ETH_ALEN); + vxlan_fdb_append(f, ip, port, vni, ifindex); + ++vxlan->addrcnt; hlist_add_head_rcu(&f->hlist, vxlan_fdb_head(vxlan, mac)); @@ -472,13 +485,10 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, static void vxlan_fdb_free(struct rcu_head *head) { struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); + struct vxlan_rdst *rd, *nd; - while (f->remote.remote_next) { - struct vxlan_rdst *rd = f->remote.remote_next; - - f->remote.remote_next = rd->remote_next; + list_for_each_entry_safe(rd, nd, &f->remotes, list) kfree(rd); - } kfree(f); } @@ -588,23 +598,24 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { struct vxlan_rdst *rd; - for (rd = &f->remote; rd; rd = rd->remote_next) { - if (idx < cb->args[0]) - goto skip; + if (idx < cb->args[0]) + goto skip; + + list_for_each_entry_rcu(rd, &f->remotes, list) { err = vxlan_fdb_info(skb, vxlan, f, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, NLM_F_MULTI, rd); if (err < 0) - break; -skip: - ++idx; + goto out; } +skip: + ++idx; } } - +out: return idx; } @@ -620,7 +631,9 @@ static bool vxlan_snoop(struct net_device *dev, f = vxlan_find_mac(vxlan, src_mac); if (likely(f)) { - if (likely(f->remote.remote_ip == src_ip)) + struct vxlan_rdst *rdst = first_remote(f); + + if (likely(rdst->remote_ip == src_ip)) return false; /* Don't migrate static entries, drop packets */ @@ -630,9 +643,9 @@ static bool vxlan_snoop(struct net_device *dev, if (net_ratelimit()) netdev_info(dev, "%pM migrated from %pI4 to %pI4\n", - src_mac, &f->remote.remote_ip, &src_ip); + src_mac, &rdst->remote_ip, &src_ip); - f->remote.remote_ip = src_ip; + rdst->remote_ip = src_ip; f->updated = jiffies; vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH); } else { @@ -866,7 +879,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb) } f = vxlan_find_mac(vxlan, n->ha); - if (f && f->remote.remote_ip == htonl(INADDR_ANY)) { + if (f && first_remote(f)->remote_ip == htonl(INADDR_ANY)) { /* bridge-local neighbor */ neigh_release(n); goto out; @@ -1165,17 +1178,17 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) (vxlan->flags & VXLAN_F_L2MISS) && !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); - } else - rdst0 = &f->remote; - + } else { + rdst = rdst0 = first_remote(f); - /* if there are multiple destinations, send copies */ - for (rdst = rdst0->remote_next; rdst; rdst = rdst->remote_next) { - struct sk_buff *skb1; + /* if there are multiple destinations, send copies */ + list_for_each_entry_continue_rcu(rdst, &f->remotes, list) { + struct sk_buff *skb1; - skb1 = skb_clone(skb, GFP_ATOMIC); - if (skb1) - vxlan_xmit_one(skb1, dev, rdst, did_rsc); + skb1 = skb_clone(skb, GFP_ATOMIC); + if (skb1) + vxlan_xmit_one(skb1, dev, rdst, did_rsc); + } } vxlan_xmit_one(skb, dev, rdst0, did_rsc); -- GitLab From 9daaa397b3e18282715eeb0d7be79ea5bbadc119 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:12 -0700 Subject: [PATCH 1766/2900] vxlan: port module param should be ushort UDP ports are limited to 16 bits. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 117b7fa6f33b..f89a58bb3f26 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -70,8 +70,8 @@ struct vxlanhdr { * The IANA assigned port is 4789, but the Linux default is 8472 * for compatability with early adopters. */ -static unsigned int vxlan_port __read_mostly = 8472; -module_param_named(udp_port, vxlan_port, uint, 0444); +static unsigned short vxlan_port __read_mostly = 8472; +module_param_named(udp_port, vxlan_port, ushort, 0444); MODULE_PARM_DESC(udp_port, "Destination UDP port"); static bool log_ecn_error = true; -- GitLab From bb3fd6878a983f36c994bfbd71b01b2625ddf52b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:40 -0700 Subject: [PATCH 1767/2900] vxlan: Use initializer for dummy structures For the notification code, a couple of places build fdb entries on the stack, use structure initialization instead and fix formatting. Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f89a58bb3f26..d2b9ab79c9ae 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -311,14 +311,13 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, static void vxlan_ip_miss(struct net_device *dev, __be32 ipa) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_fdb f; - struct vxlan_rdst remote; - - memset(&f, 0, sizeof f); - f.state = NUD_STALE; - - remote.remote_ip = ipa; /* goes to NDA_DST */ - remote.remote_vni = VXLAN_N_VID; + struct vxlan_fdb f = { + .state = NUD_STALE, + }; + struct vxlan_rdst remote = { + .remote_ip = ipa, /* goes to NDA_DST */ + .remote_vni = VXLAN_N_VID, + }; INIT_LIST_HEAD(&f.remotes); list_add_rcu(&remote.list, &f.remotes); @@ -328,11 +327,11 @@ static void vxlan_ip_miss(struct net_device *dev, __be32 ipa) static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) { - struct vxlan_fdb f; + struct vxlan_fdb f = { + .state = NUD_STALE, + }; - memset(&f, 0, sizeof f); INIT_LIST_HEAD(&f.remotes); - f.state = NUD_STALE; memcpy(f.eth_addr, eth_addr, ETH_ALEN); vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH); @@ -1485,6 +1484,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) struct sockaddr_in vxlan_addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_ANY), + .sin_port = port, }; int rc; unsigned int h; @@ -1510,8 +1510,6 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port) sk = vs->sock->sk; sk_change_net(sk, net); - vxlan_addr.sin_port = port; - rc = kernel_bind(vs->sock, (struct sockaddr *) &vxlan_addr, sizeof(vxlan_addr)); if (rc < 0) { -- GitLab From 234f5b73794435f065c5fb13371415fe46956a4b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 17 Jun 2013 14:16:41 -0700 Subject: [PATCH 1768/2900] vxlan: cosmetic cleanup's Fix whitespace and spelling Signed-off-by: Stephen Hemminger Acked-by: David L Stevens --- drivers/net/vxlan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d2b9ab79c9ae..3b03cd4bdf37 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -68,7 +68,7 @@ struct vxlanhdr { /* UDP port for VXLAN traffic. * The IANA assigned port is 4789, but the Linux default is 8472 - * for compatability with early adopters. + * for compatibility with early adopters. */ static unsigned short vxlan_port __read_mostly = 8472; module_param_named(udp_port, vxlan_port, ushort, 0444); @@ -210,9 +210,9 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port) /* Fill in neighbour message in skbuff. */ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, - const struct vxlan_fdb *fdb, - u32 portid, u32 seq, int type, unsigned int flags, - const struct vxlan_rdst *rdst) + const struct vxlan_fdb *fdb, + u32 portid, u32 seq, int type, unsigned int flags, + const struct vxlan_rdst *rdst) { unsigned long now = jiffies; struct nda_cacheinfo ci; @@ -1031,7 +1031,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct flowi4 fl4; __be32 dst; __be16 src_port, dst_port; - u32 vni; + u32 vni; __be16 df = 0; __u8 tos, ttl; int err; -- GitLab From 193b40aeb537b59eaa36e3dfaabedc2025332ebf Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Mon, 6 May 2013 14:57:47 +0200 Subject: [PATCH 1769/2900] kconfig: sort found symbols by relevance When searching for symbols, return the symbols sorted by relevance. Sorting is done as thus: - first, symbols that match exactly - then, alphabetical sort Since the search can be a regexp, it is possible that more than one symbol matches exactly. In this case, we can't decide which to sort first, so we fallback to alphabeticall sort. Explain this (new!) sorting heuristic in the documentation. Reported-by: Jean Delvare Signed-off-by: "Yann E. MORIN" Cc: Jean Delvare Cc: Michal Marek Cc: Roland Eggner Cc: Wang YanQing -- Changes v1->v2: - drop the previous, complex heuristic in favour of a simpler heuristic that is both easier to understand, *and* to maintain (Jean) - explain sorting heuristic in the doc (Jean) --- Documentation/kbuild/kconfig.txt | 13 ++++++ scripts/kconfig/symbol.c | 78 ++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt index 3f429ed8b3b8..e9f9e767f82a 100644 --- a/Documentation/kbuild/kconfig.txt +++ b/Documentation/kbuild/kconfig.txt @@ -174,6 +174,19 @@ Searching in menuconfig: /^hotplug + When searching, symbols are sorted thus: + - exact match first: an exact match is when the search matches + the complete symbol name; + - alphabetical order: when two symbols do not match exactly, + they are sorted in alphabetical order (in the user's current + locale). + For example: ^ATH.K matches: + ATH5K ATH9K ATH5K_AHB ATH5K_DEBUG [...] ATH6KL ATH6KL_DEBUG + [...] ATH9K_AHB ATH9K_BTCOEX_SUPPORT ATH9K_COMMON [...] + of which only ATH5K and ATH9K match exactly and so are sorted + first (and in alphabetical order), then come all other symbols, + sorted in alphabetical order. + ______________________________________________________________________ User interface options for 'menuconfig' diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index ab8f4c835933..387d55483882 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -954,38 +954,98 @@ const char *sym_escape_string_value(const char *in) return res; } +struct sym_match { + struct symbol *sym; + off_t so, eo; +}; + +/* Compare matched symbols as thus: + * - first, symbols that match exactly + * - then, alphabetical sort + */ +static int sym_rel_comp( const void *sym1, const void *sym2 ) +{ + struct sym_match *s1 = *(struct sym_match **)sym1; + struct sym_match *s2 = *(struct sym_match **)sym2; + int l1, l2; + + /* Exact match: + * - if matched length on symbol s1 is the length of that symbol, + * then this symbol should come first; + * - if matched length on symbol s2 is the length of that symbol, + * then this symbol should come first. + * Note: since the search can be a regexp, both symbols may match + * exactly; if this is the case, we can't decide which comes first, + * and we fallback to sorting alphabetically. + */ + l1 = s1->eo - s1->so; + l2 = s2->eo - s2->so; + if (l1 == strlen(s1->sym->name) && l2 != strlen(s2->sym->name)) + return -1; + if (l1 != strlen(s1->sym->name) && l2 == strlen(s2->sym->name)) + return 1; + + /* As a fallback, sort symbols alphabetically */ + return strcmp(s1->sym->name, s2->sym->name); +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; + struct sym_match **sym_match_arr = NULL; int i, cnt, size; regex_t re; + regmatch_t match[1]; cnt = size = 0; /* Skip if empty */ if (strlen(pattern) == 0) return NULL; - if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE)) return NULL; for_all_symbols(i, sym) { + struct sym_match *tmp_sym_match; if (sym->flags & SYMBOL_CONST || !sym->name) continue; - if (regexec(&re, sym->name, 0, NULL, 0)) + if (regexec(&re, sym->name, 1, match, 0)) continue; if (cnt + 1 >= size) { - void *tmp = sym_arr; + void *tmp; size += 16; - sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); - if (!sym_arr) { - free(tmp); - return NULL; + tmp = realloc(sym_match_arr, size * sizeof(struct sym_match *)); + if (!tmp) { + goto sym_re_search_free; } + sym_match_arr = tmp; } sym_calc_value(sym); - sym_arr[cnt++] = sym; + tmp_sym_match = (struct sym_match*)malloc(sizeof(struct sym_match)); + if (!tmp_sym_match) + goto sym_re_search_free; + tmp_sym_match->sym = sym; + /* As regexec return 0, we know we have a match, so + * we can use match[0].rm_[se]o without further checks + */ + tmp_sym_match->so = match[0].rm_so; + tmp_sym_match->eo = match[0].rm_eo; + sym_match_arr[cnt++] = tmp_sym_match; } - if (sym_arr) + if (sym_match_arr) { + qsort(sym_match_arr, cnt, sizeof(struct sym_match*), sym_rel_comp); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); + if (!sym_arr) + goto sym_re_search_free; + for (i = 0; i < cnt; i++) + sym_arr[i] = sym_match_arr[i]->sym; sym_arr[cnt] = NULL; + } +sym_re_search_free: + if (sym_match_arr) { + for (i = 0; i < cnt; i++) + free(sym_match_arr[i]); + free(sym_match_arr); + } regfree(&re); return sym_arr; -- GitLab From a1ce636f560336ba007bfabb15b167ff31b592cf Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Mon, 24 Jun 2013 20:01:37 +0200 Subject: [PATCH 1770/2900] kconfig/[mn]conf: make it explicit in the search box that a regexp is possible Reported-by: Jean Delvare Signed-off-by: "Yann E. MORIN" Cc: Jean Delvare Cc: Michal Marek --- scripts/kconfig/mconf.c | 2 +- scripts/kconfig/nconf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 6ee4aaea9d87..18d3dc93d718 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -401,7 +401,7 @@ static void search_conf(void) struct subtitle_part stpart; title = str_new(); - str_printf( &title, _("Enter %s (sub)string to search for " + str_printf( &title, _("Enter %s (sub)string or regexp to search for " "(with or without \"%s\")"), CONFIG_, CONFIG_); again: diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 0183153c2095..7975d8d258c3 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -695,7 +695,7 @@ static void search_conf(void) int dres; title = str_new(); - str_printf( &title, _("Enter %s (sub)string to search for " + str_printf( &title, _("Enter %s (sub)string or regexp to search for " "(with or without \"%s\")"), CONFIG_, CONFIG_); again: -- GitLab From 3b9a19e08960e5cdad5253998637653e592a3c29 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Sun, 28 Apr 2013 22:36:38 +0200 Subject: [PATCH 1771/2900] kconfig: loop as long as we changed some symbols in randconfig Because of choice-in-a-choice constructs, it can happen that not all symbols are assigned a value during randconfig, leading in rare cases to this situation: ---8<--- choice-in-choice.in choice bool "A/B/C" config A bool "A" config B bool "B" if B choice bool "E/F" config E bool "E" config F bool "F" endchoice endif # B config C bool "C" endchoice ---8<--- $ ./scripts/kconfig/conf --randconfig choice-in-choice.in [--SNIP--] $ ./scripts/kconfig/conf --silentoldconfig choice-in-choice.in 2. B (B) 3. C (C) choice[1-3]: 2 E/F > 1. E (E) (NEW) 2. F (F) (NEW) choice[1-2]: aborted! Console input/output is redirected. Run 'make oldconfig' to update configuration. Fix this by looping in randconfig for as long as some symbol gets assigned a value. Note: this was spotted with the USB EHCI Debug Device Gadget (USB_G_DBGP), which uses this choice-in-a-choice construct, and exhibits this problem. The example above is just a stripped-down minimalist test-case. Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/conf.c | 3 ++- scripts/kconfig/confdata.c | 18 ++++++++++++++---- scripts/kconfig/lkc.h | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 38616c14c071..d19944f9c3ac 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -654,7 +654,8 @@ int main(int ac, char **av) conf_set_all_new_symbols(def_default); break; case randconfig: - conf_set_all_new_symbols(def_random); + /* Really nothing to do in this loop */ + while (conf_set_all_new_symbols(def_random)) ; break; case defconfig: conf_set_all_new_symbols(def_default); diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index d36bc1f1d563..c55c227af463 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void)) conf_changed_callback = fn; } -static void randomize_choice_values(struct symbol *csym) +static bool randomize_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym) * In both cases stop. */ if (csym->curr.tri != yes) - return; + return false; prop = sym_get_choice_prop(csym); @@ -1084,6 +1084,8 @@ static void randomize_choice_values(struct symbol *csym) csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ csym->flags &= ~(SYMBOL_VALID); + + return true; } void set_all_choice_values(struct symbol *csym) @@ -1106,7 +1108,7 @@ void set_all_choice_values(struct symbol *csym) csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); } -void conf_set_all_new_symbols(enum conf_def_mode mode) +bool conf_set_all_new_symbols(enum conf_def_mode mode) { struct symbol *sym, *csym; int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y @@ -1154,6 +1156,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) exit( 1 ); } } + bool has_changed = false; for_all_symbols(i, sym) { if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) @@ -1161,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) switch (sym_get_type(sym)) { case S_BOOLEAN: case S_TRISTATE: + has_changed = true; switch (mode) { case def_yes: sym->def[S_DEF_USER].tri = yes; @@ -1219,6 +1223,12 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) sym_calc_value(csym); if (mode == def_random) - randomize_choice_values(csym); + has_changed = randomize_choice_values(csym); + else { + set_all_choice_values(csym); + has_changed = true; + } } + + return has_changed; } diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 0c8d4191ca87..09f4edfdc911 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -86,7 +86,7 @@ const char *conf_get_autoconfig_name(void); char *conf_get_default_confname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); -void conf_set_all_new_symbols(enum conf_def_mode mode); +bool conf_set_all_new_symbols(enum conf_def_mode mode); void set_all_choice_values(struct symbol *csym); struct conf_printer { -- GitLab From 8357b48549e17b3e4e402c7f977b65708922e60f Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Tue, 18 Jun 2013 19:35:29 +0200 Subject: [PATCH 1772/2900] kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG Currently, randconfig does randomise choice entries, unless KCONFIG_ALLCONFIG is specified. For example, given those two files (Thomas' test-case): ---8<--- Config.test.in config OPTIONA bool "Option A" choice prompt "This is a choice" config CHOICE_OPTIONA bool "Choice Option A" config CHOICE_OPTIONB bool "Choice Option B" endchoice config OPTIONB bool "Option B" ---8<--- Config.test.in ---8<--- config.defaults CONFIG_OPTIONA=y ---8<--- config.defaults And running: ./scripts/kconfig/conf --randconfig Config.test.in does properly randomise the two choice symbols (and the two booleans). However, running: KCONFIG_ALLCONFIG=config.defaults \ ./scripts/kconfig/conf --randconfig Config.test.in does *not* reandomise the two choice entries, and only CHOICE_OPTIONA will ever be selected. (OPTIONA will always be set (expected), and OPTIONB will be be properly randomised (expected).) This patch defers setting that a choice has a value until a symbol for that choice is indeed set, so that choices are properly randomised when KCONFIG_ALLCONFIG is set, but not if a symbol for that choice is set. Reported-by: Thomas Petazzoni Signed-off-by: "Yann E. MORIN" Cc: Thomas Petazzoni Cc: Michal Marek Cc: Sam Ravnborg Cc: Sedat Dilek Cc: Arnd Bergmann Cc: Stephen Rothwell --- Changes v3 -> v4 - fix previous issue where some choices would not be set, which would cause silentoldconfig to ask for them and was then breaking this workflow (as reported by Arnd and Sedat): KCONFIG_ALLCONFIG=foo.defconfig make randconfig make silentoldconfig /dev/null 2>&1 make silentoldconfig /dev/null 2>&1 || break done which did not break at all. - change done in v3 (below) is already fixed by a previous patch Changes v2 -> v3 - ensure only one symbol is set in a choice Changes v1 -> v2: - further postpone setting that a choice has a value until one is indeed set - do not print symbols that are part of an invisible choice --- scripts/kconfig/confdata.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index c55c227af463..3e39208ad20e 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -288,8 +288,6 @@ int conf_read_simple(const char *name, int def) for_all_symbols(i, sym) { sym->flags |= SYMBOL_CHANGED; sym->flags &= ~(def_flags|SYMBOL_VALID); - if (sym_is_choice(sym)) - sym->flags |= def_flags; switch (sym->type) { case S_INT: case S_HEX: @@ -379,13 +377,13 @@ int conf_read_simple(const char *name, int def) case mod: if (cs->def[def].tri == yes) { conf_warning("%s creates inconsistent choice state", sym->name); - cs->flags &= ~def_flags; } break; case yes: if (cs->def[def].tri != no) conf_warning("override: %s changes choice state", sym->name); cs->def[def].val = sym; + cs->flags |= def_flags; break; } cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); @@ -791,6 +789,8 @@ int conf_write(const char *name) sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) goto next; + if (sym_is_choice_value(sym) && !menu_is_visible(menu->parent)) + goto next; sym->flags &= ~SYMBOL_WRITE; conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); -- GitLab From 156652bbedfbc0f3410759ccebe5c94edb7ce6c3 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 19 Jun 2013 14:02:14 -0700 Subject: [PATCH 1773/2900] ath9k_htc: Support reporting tx and rx chain mask. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc.h | 2 + .../net/wireless/ath/ath9k/htc_drv_debug.c | 16 +------- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 ++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 38 +++++++++++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 69581031f2cd..6bd556d203ae 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -583,6 +583,8 @@ bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); +struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv); + #ifdef CONFIG_MAC80211_LEDS void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 87110de577ef..632d13da43e2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -496,21 +496,7 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, ssize_t retval = 0; char *buf; - /* - * This can be done since all the 3 EEPROM families have the - * same base header upto a certain point, and we are interested in - * the data only upto that point. - */ - - if (AR_SREV_9271(priv->ah)) - pBase = (struct base_eep_header *) - &priv->ah->eeprom.map4k.baseEepHeader; - else if (priv->ah->hw_version.usbdev == AR9280_USB) - pBase = (struct base_eep_header *) - &priv->ah->eeprom.def.baseEepHeader; - else if (priv->ah->hw_version.usbdev == AR9287_USB) - pBase = (struct base_eep_header *) - &priv->ah->eeprom.map9287.baseEepHeader; + pBase = ath9k_htc_get_eeprom_base(priv); if (pBase == NULL) { ath_err(common, "Unknown EEPROM type\n"); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index bb0ba9e3e083..925c5b0b1cde 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -716,6 +716,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, struct ieee80211_hw *hw) { struct ath_common *common = ath9k_hw_common(priv->ah); + struct base_eep_header *pBase; hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | @@ -771,6 +772,12 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); } + pBase = ath9k_htc_get_eeprom_base(priv); + if (pBase) { + hw->wiphy->available_antennas_rx = pBase->rxMask; + hw->wiphy->available_antennas_tx = pBase->txMask; + } + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index eaa94feb4333..ef68857f9363 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1774,6 +1774,43 @@ static int ath9k_htc_get_stats(struct ieee80211_hw *hw, return 0; } +struct base_eep_header *ath9k_htc_get_eeprom_base(struct ath9k_htc_priv *priv) +{ + struct base_eep_header *pBase = NULL; + /* + * This can be done since all the 3 EEPROM families have the + * same base header upto a certain point, and we are interested in + * the data only upto that point. + */ + + if (AR_SREV_9271(priv->ah)) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.map4k.baseEepHeader; + else if (priv->ah->hw_version.usbdev == AR9280_USB) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.def.baseEepHeader; + else if (priv->ah->hw_version.usbdev == AR9287_USB) + pBase = (struct base_eep_header *) + &priv->ah->eeprom.map9287.baseEepHeader; + return pBase; +} + + +static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, + u32 *rx_ant) +{ + struct ath9k_htc_priv *priv = hw->priv; + struct base_eep_header *pBase = ath9k_htc_get_eeprom_base(priv); + if (pBase) { + *tx_ant = pBase->txMask; + *rx_ant = pBase->rxMask; + } else { + *tx_ant = 0; + *rx_ant = 0; + } + return 0; +} + struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, .start = ath9k_htc_start, @@ -1799,4 +1836,5 @@ struct ieee80211_ops ath9k_htc_ops = { .set_coverage_class = ath9k_htc_set_coverage_class, .set_bitrate_mask = ath9k_htc_set_bitrate_mask, .get_stats = ath9k_htc_get_stats, + .get_antenna = ath9k_htc_get_antenna, }; -- GitLab From 68185a4b37d8790196c7441cb3020cc489d9835f Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 19 Jun 2013 14:02:15 -0700 Subject: [PATCH 1774/2900] ath9k_htc: Add ethtool stats support. This provides some of the same info found in the ath9k_htc debugfs through the standard ethtool stats API. This logic is only supported when ath9k_htc debugfs kernel feature is enabled, since that is the only time stats are actually gathered. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hif_usb.c | 8 +- drivers/net/wireless/ath/ath9k/htc.h | 14 ++++ .../net/wireless/ath/ath9k/htc_drv_debug.c | 81 +++++++++++++++++++ drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 ++ 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index f5dda84176c3..9e582e14da74 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -234,10 +234,15 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, struct sk_buff *skb; while ((skb = __skb_dequeue(queue)) != NULL) { +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + int ln = skb->len; +#endif ath9k_htc_txcompletion_cb(hif_dev->htc_handle, skb, txok); - if (txok) + if (txok) { TX_STAT_INC(skb_success); + TX_STAT_ADD(skb_success_bytes, ln); + } else TX_STAT_INC(skb_failed); } @@ -620,6 +625,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, err: for (i = 0; i < pool_index; i++) { + RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len); ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], skb_pool[i]->len, USB_WLAN_RX_PIPE); RX_STAT_INC(skb_completed); diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6bd556d203ae..055d7c25e090 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -324,7 +324,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) #ifdef CONFIG_ATH9K_HTC_DEBUGFS #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) +#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) +#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a) #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) @@ -337,6 +339,7 @@ struct ath_tx_stats { u32 buf_completed; u32 skb_queued; u32 skb_success; + u32 skb_success_bytes; u32 skb_failed; u32 cab_queued; u32 queue_stats[IEEE80211_NUM_ACS]; @@ -345,6 +348,7 @@ struct ath_tx_stats { struct ath_rx_stats { u32 skb_allocated; u32 skb_completed; + u32 skb_completed_bytes; u32 skb_dropped; u32 err_crc; u32 err_decrypt_crc; @@ -362,10 +366,20 @@ struct ath9k_debug { struct ath_rx_stats rx_stats; }; +void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data); +int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset); +void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data); #else #define TX_STAT_INC(c) do { } while (0) +#define TX_STAT_ADD(c, a) do { } while (0) #define RX_STAT_INC(c) do { } while (0) +#define RX_STAT_ADD(c, a) do { } while (0) #define CAB_STAT_INC do { } while (0) #define TX_QSTAT_INC(c) do { } while (0) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 632d13da43e2..7416d58a122c 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c @@ -902,6 +902,87 @@ static const struct file_operations fops_modal_eeprom = { .llseek = default_llseek, }; + +/* Ethtool support for get-stats */ +#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO" +static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_pkts_nic", + "tx_bytes_nic", + "rx_pkts_nic", + "rx_bytes_nic", + + AMKSTR(d_tx_pkts), + + "d_rx_crc_err", + "d_rx_decrypt_crc_err", + "d_rx_phy_err", + "d_rx_mic_err", + "d_rx_pre_delim_crc_err", + "d_rx_post_delim_crc_err", + "d_rx_decrypt_busy_err", + + "d_rx_phyerr_radar", + "d_rx_phyerr_ofdm_timing", + "d_rx_phyerr_cck_timing", + +}; +#define ATH9K_HTC_SSTATS_LEN ARRAY_SIZE(ath9k_htc_gstrings_stats) + +void ath9k_htc_get_et_strings(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset == ETH_SS_STATS) + memcpy(data, *ath9k_htc_gstrings_stats, + sizeof(ath9k_htc_gstrings_stats)); +} + +int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset) +{ + if (sset == ETH_SS_STATS) + return ATH9K_HTC_SSTATS_LEN; + return 0; +} + +#define STXBASE priv->debug.tx_stats +#define SRXBASE priv->debug.rx_stats +#define ASTXQ(a) \ + data[i++] = STXBASE.a[IEEE80211_AC_BE]; \ + data[i++] = STXBASE.a[IEEE80211_AC_BK]; \ + data[i++] = STXBASE.a[IEEE80211_AC_VI]; \ + data[i++] = STXBASE.a[IEEE80211_AC_VO] + +void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct ath9k_htc_priv *priv = hw->priv; + int i = 0; + + data[i++] = STXBASE.skb_success; + data[i++] = STXBASE.skb_success_bytes; + data[i++] = SRXBASE.skb_completed; + data[i++] = SRXBASE.skb_completed_bytes; + + ASTXQ(queue_stats); + + data[i++] = SRXBASE.err_crc; + data[i++] = SRXBASE.err_decrypt_crc; + data[i++] = SRXBASE.err_phy; + data[i++] = SRXBASE.err_mic; + data[i++] = SRXBASE.err_pre_delim; + data[i++] = SRXBASE.err_post_delim; + data[i++] = SRXBASE.err_decrypt_busy; + + data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR]; + data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING]; + data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING]; + + WARN_ON(i != ATH9K_HTC_SSTATS_LEN); +} + + int ath9k_htc_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ef68857f9363..be6baf7f6510 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1837,4 +1837,10 @@ struct ieee80211_ops ath9k_htc_ops = { .set_bitrate_mask = ath9k_htc_set_bitrate_mask, .get_stats = ath9k_htc_get_stats, .get_antenna = ath9k_htc_get_antenna, + +#ifdef CONFIG_ATH9K_HTC_DEBUGFS + .get_et_sset_count = ath9k_htc_get_et_sset_count, + .get_et_stats = ath9k_htc_get_et_stats, + .get_et_strings = ath9k_htc_get_et_strings, +#endif }; -- GitLab From f56e121df34563475f71efab38287b9ac028fe8c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 20 Jun 2013 15:11:31 +0200 Subject: [PATCH 1775/2900] ath9k: fix queue depth accounting in ath_tx_txqaddbuf ath_tx_txqaddbuf assumes that all the linked buffers in the queue passed to it are part of the same A-MPDU or MPDU. The CAB queue rework violates this assumption, which can cause the internal queue depth to go negative. Fix this by increasing the counter for all slots of [bf, bf->bf_lastbf] Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7e19d9b5214e..bfb58a5f2fd0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1778,9 +1778,13 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, } if (!internal) { - txq->axq_depth++; - if (bf_is_ampdu_not_probing(bf)) - txq->axq_ampdu_depth++; + while (bf) { + txq->axq_depth++; + if (bf_is_ampdu_not_probing(bf)) + txq->axq_ampdu_depth++; + + bf = bf->bf_lastbf->bf_next; + } } } -- GitLab From 5d9e3bc21c57d600b706a31454d5cf2f68c24f53 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 21 Jun 2013 10:42:19 +0800 Subject: [PATCH 1776/2900] ipw2200: fix error return code in ipw_load() Fix to return -ENOMEM in the ipw_rx_queue_alloc() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/ipw2200.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index d96257b79a84..312fa0e42e6f 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -3548,6 +3548,7 @@ static int ipw_load(struct ipw_priv *priv) ipw_rx_queue_reset(priv, priv->rxq); if (!priv->rxq) { IPW_ERROR("Unable to initialize Rx queue\n"); + rc = -ENOMEM; goto error; } -- GitLab From 7258416c517c79b2ebb30b61d8c6807a04dc6b25 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 20 Jun 2013 23:03:12 -0400 Subject: [PATCH 1777/2900] cw1200: Fix up a large pile of sparse warnings Most of these relate to endianness problems, and are purely cosmetic. But a couple of them were legit -- listen interval parsing and some of the rate selection code would malfunction on BE systems. There's still one cosmetic warning remaining, in the (admittedly) ugly code in cw1200_spi.c. It's there because the hardware needs 16-bit SPI transfers, but many SPI controllers only operate 8 bits at a time. If there's a cleaner way of handling this, I'm all ears. Signed-off-by: Solomon Peachy Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/cw1200.h | 2 +- drivers/net/wireless/cw1200/cw1200_spi.c | 32 ++++++++++------- drivers/net/wireless/cw1200/hwio.c | 18 +++++----- drivers/net/wireless/cw1200/hwio.h | 31 ++++++++-------- drivers/net/wireless/cw1200/main.c | 4 +-- drivers/net/wireless/cw1200/queue.c | 2 +- drivers/net/wireless/cw1200/sta.c | 23 ++++++------ drivers/net/wireless/cw1200/txrx.c | 9 +++-- drivers/net/wireless/cw1200/wsm.c | 33 +++++++++-------- drivers/net/wireless/cw1200/wsm.h | 45 +++++++++++------------- 10 files changed, 102 insertions(+), 97 deletions(-) diff --git a/drivers/net/wireless/cw1200/cw1200.h b/drivers/net/wireless/cw1200/cw1200.h index 243e96353d13..1ad7d3602520 100644 --- a/drivers/net/wireless/cw1200/cw1200.h +++ b/drivers/net/wireless/cw1200/cw1200.h @@ -267,7 +267,7 @@ struct cw1200_common { struct delayed_work bss_loss_work; spinlock_t bss_loss_lock; /* Protect BSS loss state */ int bss_loss_state; - int bss_loss_confirm_id; + u32 bss_loss_confirm_id; int delayed_link_loss; struct work_struct bss_params_work; diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 953bd1904d3d..d06376014bcd 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -61,7 +61,7 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, void *dst, int count) { int ret, i; - uint16_t regaddr; + u16 regaddr; struct spi_message m; struct spi_transfer t_addr = { @@ -76,15 +76,18 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; regaddr |= SET_READ; regaddr |= (count>>1); - regaddr = cpu_to_le16(regaddr); #ifdef SPI_DEBUG - pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, - le16_to_cpu(regaddr)); + pr_info("READ : %04d from 0x%02x (%04x)\n", count, addr, regaddr); #endif + /* Header is LE16 */ + regaddr = cpu_to_le16(regaddr); + + /* We have to byteswap if the SPI bus is limited to 8b operation + or we are running on a Big Endian system + */ #if defined(__LITTLE_ENDIAN) - /* We have to byteswap if the SPI bus is limited to 8b operation */ if (self->func->bits_per_word == 8) #endif regaddr = swab16(regaddr); @@ -104,8 +107,10 @@ static int cw1200_spi_memcpy_fromio(struct hwbus_priv *self, printk("\n"); #endif + /* We have to byteswap if the SPI bus is limited to 8b operation + or we are running on a Big Endian system + */ #if defined(__LITTLE_ENDIAN) - /* We have to byteswap if the SPI bus is limited to 8b operation */ if (self->func->bits_per_word == 8) #endif { @@ -122,7 +127,7 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self, const void *src, int count) { int rval, i; - uint16_t regaddr; + u16 regaddr; struct spi_transfer t_addr = { .tx_buf = ®addr, .len = sizeof(regaddr), @@ -136,20 +141,23 @@ static int cw1200_spi_memcpy_toio(struct hwbus_priv *self, regaddr = (SDIO_TO_SPI_ADDR(addr))<<12; regaddr &= SET_WRITE; regaddr |= (count>>1); - regaddr = cpu_to_le16(regaddr); #ifdef SPI_DEBUG - pr_info("WRITE: %04d to 0x%02x (%04x)\n", count, addr, - le16_to_cpu(regaddr)); + pr_info("WRITE: %04d to 0x%02x (%04x)\n", count, addr, regaddr); #endif + /* Header is LE16 */ + regaddr = cpu_to_le16(regaddr); + + /* We have to byteswap if the SPI bus is limited to 8b operation + or we are running on a Big Endian system + */ #if defined(__LITTLE_ENDIAN) - /* We have to byteswap if the SPI bus is limited to 8b operation */ if (self->func->bits_per_word == 8) #endif { uint16_t *buf = (uint16_t *)src; - regaddr = swab16(regaddr); + regaddr = swab16(regaddr); for (i = 0; i < ((count + 1) >> 1); i++) buf[i] = swab16(buf[i]); } diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c index dad3fb331818..ff230b7aeedd 100644 --- a/drivers/net/wireless/cw1200/hwio.c +++ b/drivers/net/wireless/cw1200/hwio.c @@ -69,31 +69,33 @@ static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr, static inline int __cw1200_reg_read_32(struct cw1200_common *priv, u16 addr, u32 *val) { - int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); - *val = le32_to_cpu(*val); + __le32 tmp; + int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0); + *val = le32_to_cpu(tmp); return i; } static inline int __cw1200_reg_write_32(struct cw1200_common *priv, u16 addr, u32 val) { - val = cpu_to_le32(val); - return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); + __le32 tmp = cpu_to_le32(val); + return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0); } static inline int __cw1200_reg_read_16(struct cw1200_common *priv, u16 addr, u16 *val) { - int i = __cw1200_reg_read(priv, addr, val, sizeof(*val), 0); - *val = le16_to_cpu(*val); + __le16 tmp; + int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0); + *val = le16_to_cpu(tmp); return i; } static inline int __cw1200_reg_write_16(struct cw1200_common *priv, u16 addr, u16 val) { - val = cpu_to_le16(val); - return __cw1200_reg_write(priv, addr, &val, sizeof(val), 0); + __le16 tmp = cpu_to_le16(val); + return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0); } int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf, diff --git a/drivers/net/wireless/cw1200/hwio.h b/drivers/net/wireless/cw1200/hwio.h index 563329cfead6..ddf52669dc5b 100644 --- a/drivers/net/wireless/cw1200/hwio.h +++ b/drivers/net/wireless/cw1200/hwio.h @@ -169,35 +169,34 @@ int cw1200_reg_write(struct cw1200_common *priv, u16 addr, static inline int cw1200_reg_read_16(struct cw1200_common *priv, u16 addr, u16 *val) { - u32 tmp; + __le32 tmp; int i; i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp)); - tmp = le32_to_cpu(tmp); - *val = tmp & 0xffff; + *val = le32_to_cpu(tmp) & 0xfffff; return i; } static inline int cw1200_reg_write_16(struct cw1200_common *priv, u16 addr, u16 val) { - u32 tmp = val; - tmp = cpu_to_le32(tmp); + __le32 tmp = cpu_to_le32((u32)val); return cw1200_reg_write(priv, addr, &tmp, sizeof(tmp)); } static inline int cw1200_reg_read_32(struct cw1200_common *priv, u16 addr, u32 *val) { - int i = cw1200_reg_read(priv, addr, val, sizeof(*val)); - *val = le32_to_cpu(*val); + __le32 tmp; + int i = cw1200_reg_read(priv, addr, &tmp, sizeof(tmp)); + *val = le32_to_cpu(tmp); return i; } static inline int cw1200_reg_write_32(struct cw1200_common *priv, u16 addr, u32 val) { - val = cpu_to_le32(val); - return cw1200_reg_write(priv, addr, &val, sizeof(val)); + __le32 tmp = cpu_to_le32(val); + return cw1200_reg_write(priv, addr, &tmp, sizeof(val)); } int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf, @@ -224,22 +223,24 @@ static inline int cw1200_ahb_read(struct cw1200_common *priv, u32 addr, static inline int cw1200_apb_read_32(struct cw1200_common *priv, u32 addr, u32 *val) { - int i = cw1200_apb_read(priv, addr, val, sizeof(*val)); - *val = le32_to_cpu(*val); + __le32 tmp; + int i = cw1200_apb_read(priv, addr, &tmp, sizeof(tmp)); + *val = le32_to_cpu(tmp); return i; } static inline int cw1200_apb_write_32(struct cw1200_common *priv, u32 addr, u32 val) { - val = cpu_to_le32(val); - return cw1200_apb_write(priv, addr, &val, sizeof(val)); + __le32 tmp = cpu_to_le32(val); + return cw1200_apb_write(priv, addr, &tmp, sizeof(val)); } static inline int cw1200_ahb_read_32(struct cw1200_common *priv, u32 addr, u32 *val) { - int i = cw1200_ahb_read(priv, addr, val, sizeof(*val)); - *val = le32_to_cpu(*val); + __le32 tmp; + int i = cw1200_ahb_read(priv, addr, &tmp, sizeof(tmp)); + *val = le32_to_cpu(tmp); return i; } diff --git a/drivers/net/wireless/cw1200/main.c b/drivers/net/wireless/cw1200/main.c index da885036ca5f..3724e739cbf4 100644 --- a/drivers/net/wireless/cw1200/main.c +++ b/drivers/net/wireless/cw1200/main.c @@ -238,8 +238,8 @@ static const struct ieee80211_ops cw1200_ops = { /*.cancel_remain_on_channel = cw1200_cancel_remain_on_channel, */ }; -int cw1200_ba_rx_tids = -1; -int cw1200_ba_tx_tids = -1; +static int cw1200_ba_rx_tids = -1; +static int cw1200_ba_tx_tids = -1; module_param(cw1200_ba_rx_tids, int, 0644); module_param(cw1200_ba_tx_tids, int, 0644); MODULE_PARM_DESC(cw1200_ba_rx_tids, "Block ACK RX TIDs"); diff --git a/drivers/net/wireless/cw1200/queue.c b/drivers/net/wireless/cw1200/queue.c index 8510454d5db1..9c3925f58d79 100644 --- a/drivers/net/wireless/cw1200/queue.c +++ b/drivers/net/wireless/cw1200/queue.c @@ -355,7 +355,7 @@ int cw1200_queue_get(struct cw1200_queue *queue, *tx = (struct wsm_tx *)item->skb->data; *tx_info = IEEE80211_SKB_CB(item->skb); *txpriv = &item->txpriv; - (*tx)->packet_id = __cpu_to_le32(item->packet_id); + (*tx)->packet_id = item->packet_id; list_move_tail(&item->head, &queue->pending); ++queue->num_pending; --queue->link_map_cache[item->txpriv.link_id]; diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index 4cd0352b508d..7365674366f4 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -621,7 +621,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, mutex_lock(&priv->conf_mutex); if (queue < dev->queues) { - old_uapsd_flags = priv->uapsd_info.uapsd_flags; + old_uapsd_flags = le16_to_cpu(priv->uapsd_info.uapsd_flags); WSM_TX_QUEUE_SET(&priv->tx_queue_params, queue, 0, 0, 0); ret = wsm_set_tx_queue_params(priv, @@ -645,7 +645,7 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, ret = cw1200_set_uapsd_param(priv, &priv->edca); if (!ret && priv->setbssparams_done && (priv->join_status == CW1200_JOIN_STATUS_STA) && - (old_uapsd_flags != priv->uapsd_info.uapsd_flags)) + (old_uapsd_flags != le16_to_cpu(priv->uapsd_info.uapsd_flags))) ret = cw1200_set_pm(priv, &priv->powersave_mode); } } else { @@ -1089,18 +1089,18 @@ static int cw1200_parse_sdd_file(struct cw1200_common *priv) ret = -1; break; } - v = le16_to_cpu(*((u16 *)(p + 2))); + v = le16_to_cpu(*((__le16 *)(p + 2))); if (!v) /* non-zero means this is enabled */ break; - v = le16_to_cpu(*((u16 *)(p + 4))); + v = le16_to_cpu(*((__le16 *)(p + 4))); priv->conf_listen_interval = (v >> 7) & 0x1F; pr_debug("PTA found; Listen Interval %d\n", priv->conf_listen_interval); break; } case SDD_REFERENCE_FREQUENCY_ELT_ID: { - u16 clk = le16_to_cpu(*((u16 *)(p + 2))); + u16 clk = le16_to_cpu(*((__le16 *)(p + 2))); if (clk != priv->hw_refclk) pr_warn("SDD file doesn't match configured refclk (%d vs %d)\n", clk, priv->hw_refclk); @@ -1785,9 +1785,9 @@ static int cw1200_set_btcoexinfo(struct cw1200_common *priv) } else { pr_debug("[STA] STA has non ERP rates\n"); /* B only mode */ - arg.internalTxRate = (__ffs(priv->association_mode.basic_rate_set)); + arg.internalTxRate = (__ffs(le32_to_cpu(priv->association_mode.basic_rate_set))); } - arg.nonErpInternalTxRate = (__ffs(priv->association_mode.basic_rate_set)); + arg.nonErpInternalTxRate = (__ffs(le32_to_cpu(priv->association_mode.basic_rate_set))); } else { /* P2P mode */ arg.internalTxRate = (__ffs(priv->bss_params.operational_rate_set & ~0xF)); @@ -1908,7 +1908,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, if (info->assoc || info->ibss_joined) { struct ieee80211_sta *sta = NULL; - u32 val = 0; + __le32 htprot = 0; if (info->dtim_period) priv->join_dtim_period = info->dtim_period; @@ -1935,19 +1935,18 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, /* Non Greenfield stations present */ if (priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) - val |= WSM_NON_GREENFIELD_STA_PRESENT; + htprot |= cpu_to_le32(WSM_NON_GREENFIELD_STA_PRESENT); /* Set HT protection method */ - val |= (priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2; + htprot |= cpu_to_le32((priv->ht_info.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) << 2); /* TODO: * STBC_param.dual_cts * STBC_param.LSIG_TXOP_FILL */ - val = cpu_to_le32(val); wsm_write_mib(priv, WSM_MIB_ID_SET_HT_PROTECTION, - &val, sizeof(val)); + &htprot, sizeof(htprot)); priv->association_mode.greenfield = cw1200_ht_greenfield(&priv->ht_info); diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c index 44ca10cb0d39..5862c373d714 100644 --- a/drivers/net/wireless/cw1200/txrx.c +++ b/drivers/net/wireless/cw1200/txrx.c @@ -599,15 +599,15 @@ cw1200_tx_h_bt(struct cw1200_common *priv, } else if (ieee80211_is_data(t->hdr->frame_control)) { /* Skip LLC SNAP header (+6) */ u8 *payload = &t->skb->data[t->hdrlen]; - u16 *ethertype = (u16 *)&payload[6]; - if (*ethertype == __be16_to_cpu(ETH_P_PAE)) + __be16 *ethertype = (__be16 *)&payload[6]; + if (be16_to_cpu(*ethertype) == ETH_P_PAE) priority = WSM_EPTA_PRIORITY_EAPOL; } else if (ieee80211_is_assoc_req(t->hdr->frame_control) || ieee80211_is_reassoc_req(t->hdr->frame_control)) { struct ieee80211_mgmt *mgt_frame = (struct ieee80211_mgmt *)t->hdr; - if (mgt_frame->u.assoc_req.listen_interval < + if (le16_to_cpu(mgt_frame->u.assoc_req.listen_interval) < priv->listen_interval) { pr_debug("Modified Listen Interval to %d from %d\n", priv->listen_interval, @@ -615,8 +615,7 @@ cw1200_tx_h_bt(struct cw1200_common *priv, /* Replace listen interval derieved from * the one read from SDD */ - mgt_frame->u.assoc_req.listen_interval = - priv->listen_interval; + mgt_frame->u.assoc_req.listen_interval = cpu_to_le16(priv->listen_interval); } } diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index d95094fdcc50..cbb74d7a9be5 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -42,19 +42,19 @@ (buf)->data += size; \ } while (0) -#define __WSM_GET(buf, type, cvt) \ +#define __WSM_GET(buf, type, type2, cvt) \ ({ \ type val; \ if ((buf)->data + sizeof(type) > (buf)->end) \ goto underflow; \ - val = cvt(*(type *)(buf)->data); \ + val = cvt(*(type2 *)(buf)->data); \ (buf)->data += sizeof(type); \ val; \ }) -#define WSM_GET8(buf) __WSM_GET(buf, u8, (u8)) -#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16_to_cpu) -#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32_to_cpu) +#define WSM_GET8(buf) __WSM_GET(buf, u8, u8, (u8)) +#define WSM_GET16(buf) __WSM_GET(buf, u16, __le16, __le16_to_cpu) +#define WSM_GET32(buf) __WSM_GET(buf, u32, __le32, __le32_to_cpu) #define WSM_PUT(buf, ptr, size) \ do { \ @@ -65,18 +65,18 @@ (buf)->data += size; \ } while (0) -#define __WSM_PUT(buf, val, type, cvt) \ +#define __WSM_PUT(buf, val, type, type2, cvt) \ do { \ if ((buf)->data + sizeof(type) > (buf)->end) \ if (wsm_buf_reserve((buf), sizeof(type))) \ goto nomem; \ - *(type *)(buf)->data = cvt(val); \ + *(type2 *)(buf)->data = cvt(val); \ (buf)->data += sizeof(type); \ } while (0) -#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, (u8)) -#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __cpu_to_le16) -#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __cpu_to_le32) +#define WSM_PUT8(buf, val) __WSM_PUT(buf, val, u8, u8, (u8)) +#define WSM_PUT16(buf, val) __WSM_PUT(buf, val, u16, __le16, __cpu_to_le16) +#define WSM_PUT32(buf, val) __WSM_PUT(buf, val, u32, __le32, __cpu_to_le32) static void wsm_buf_reset(struct wsm_buf *buf); static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size); @@ -931,8 +931,8 @@ static int wsm_event_indication(struct cw1200_common *priv, struct wsm_buf *buf) if (!event) return -ENOMEM; - event->evt.id = __le32_to_cpu(WSM_GET32(buf)); - event->evt.data = __le32_to_cpu(WSM_GET32(buf)); + event->evt.id = WSM_GET32(buf); + event->evt.data = WSM_GET32(buf); pr_debug("[WSM] Event: %d(%d)\n", event->evt.id, event->evt.data); @@ -1311,7 +1311,7 @@ int wsm_handle_rx(struct cw1200_common *priv, u16 id, wsm_buf.begin = (u8 *)&wsm[0]; wsm_buf.data = (u8 *)&wsm[1]; - wsm_buf.end = &wsm_buf.begin[__le32_to_cpu(wsm->len)]; + wsm_buf.end = &wsm_buf.begin[__le16_to_cpu(wsm->len)]; pr_debug("[WSM] <<< 0x%.4X (%td)\n", id, wsm_buf.end - wsm_buf.begin); @@ -1550,7 +1550,7 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, */ pr_debug("[WSM] Convert probe request to scan.\n"); wsm_lock_tx_async(priv); - priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); + priv->pending_frame_id = wsm->packet_id; if (queue_delayed_work(priv->workqueue, &priv->scan.probe_work, 0) <= 0) wsm_unlock_tx(priv); @@ -1558,15 +1558,14 @@ static bool wsm_handle_tx_data(struct cw1200_common *priv, break; case do_drop: pr_debug("[WSM] Drop frame (0x%.4X).\n", fctl); - BUG_ON(cw1200_queue_remove(queue, - __le32_to_cpu(wsm->packet_id))); + BUG_ON(cw1200_queue_remove(queue, wsm->packet_id)); handled = true; break; case do_wep: pr_debug("[WSM] Issue set_default_wep_key.\n"); wsm_lock_tx_async(priv); priv->wep_default_key_id = tx_info->control.hw_key->keyidx; - priv->pending_frame_id = __le32_to_cpu(wsm->packet_id); + priv->pending_frame_id = wsm->packet_id; if (queue_work(priv->workqueue, &priv->wep_key_work) <= 0) wsm_unlock_tx(priv); handled = true; diff --git a/drivers/net/wireless/cw1200/wsm.h b/drivers/net/wireless/cw1200/wsm.h index 2816171f7a1d..7afc613c3706 100644 --- a/drivers/net/wireless/cw1200/wsm.h +++ b/drivers/net/wireless/cw1200/wsm.h @@ -806,7 +806,7 @@ struct wsm_tx { struct wsm_hdr hdr; /* Packet identifier that meant to be used in completion. */ - __le32 packet_id; + u32 packet_id; /* Note this is actually a cookie */ /* WSM_TRANSMIT_RATE_... */ u8 max_tx_rate; @@ -825,18 +825,18 @@ struct wsm_tx { u8 flags; /* Should be 0. */ - __le32 reserved; + u32 reserved; /* The elapsed time in TUs, after the initial transmission */ /* of an MSDU, after which further attempts to transmit */ /* the MSDU shall be terminated. Overrides the global */ /* dot11MaxTransmitMsduLifeTime setting [optional] */ /* Device will set the default value if this is 0. */ - __le32 expire_time; + u32 expire_time; /* WSM_HT_TX_... */ __le32 ht_tx_parameters; -}; +} __packed; /* = sizeof(generic hi hdr) + sizeof(wsm hdr) + sizeof(alignment) */ #define WSM_TX_EXTRA_HEADROOM (28) @@ -846,10 +846,10 @@ struct wsm_tx { struct wsm_rx { /* WSM_STATUS_... */ - __le32 status; + u32 status; /* Specifies the channel of the received packet. */ - __le16 channel_number; + u16 channel_number; /* WSM_TRANSMIT_RATE_... */ u8 rx_rate; @@ -859,11 +859,8 @@ struct wsm_rx { u8 rcpi_rssi; /* WSM_RX_STATUS_... */ - __le32 flags; - - /* Payload */ - u8 data[0]; -} __packed; + u32 flags; +}; /* = sizeof(generic hi hdr) + sizeof(wsm hdr) */ #define WSM_RX_EXTRA_HEADROOM (16) @@ -1119,22 +1116,22 @@ int wsm_set_tx_queue_params(struct cw1200_common *priv, #define WSM_EDCA_PARAMS_RESP_ID 0x0413 struct wsm_edca_queue_params { /* CWmin (in slots) for the access class. */ - __le16 cwmin; + u16 cwmin; /* CWmax (in slots) for the access class. */ - __le16 cwmax; + u16 cwmax; /* AIFS (in slots) for the access class. */ - __le16 aifns; + u16 aifns; /* TX OP Limit (in microseconds) for the access class. */ - __le16 txop_limit; + u16 txop_limit; /* dot11MaxReceiveLifetime to be used for the specified */ /* the access class. Overrides the global */ /* dot11MaxReceiveLifetime value */ - __le32 max_rx_lifetime; -} __packed; + u32 max_rx_lifetime; +}; struct wsm_edca_params { /* NOTE: index is a linux queue id. */ @@ -1147,12 +1144,12 @@ struct wsm_edca_params { __uapsd) \ do { \ struct wsm_edca_queue_params *p = &(__edca)->params[__queue]; \ - p->cwmin = (__cw_min); \ - p->cwmax = (__cw_max); \ - p->aifns = (__aifs); \ - p->txop_limit = ((__txop) * TXOP_UNIT); \ - p->max_rx_lifetime = (__lifetime); \ - (__edca)->uapsd_enable[__queue] = (__uapsd); \ + p->cwmin = __cw_min; \ + p->cwmax = __cw_max; \ + p->aifns = __aifs; \ + p->txop_limit = ((__txop) * TXOP_UNIT); \ + p->max_rx_lifetime = __lifetime; \ + (__edca)->uapsd_enable[__queue] = (__uapsd); \ } while (0) int wsm_set_edca_params(struct cw1200_common *priv, @@ -1475,7 +1472,7 @@ static inline int wsm_set_template_frame(struct cw1200_common *priv, u8 *p = skb_push(arg->skb, 4); p[0] = arg->frame_type; p[1] = arg->rate; - ((u16 *)p)[1] = __cpu_to_le16(arg->skb->len - 4); + ((__le16 *)p)[1] = __cpu_to_le16(arg->skb->len - 4); ret = wsm_write_mib(priv, WSM_MIB_ID_TEMPLATE_FRAME, p, arg->skb->len); skb_pull(arg->skb, 4); return ret; -- GitLab From fca3c21d5659f21edbf30a80b706cbc00f368659 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 21 Jun 2013 11:11:52 +0530 Subject: [PATCH 1778/2900] ath9k: Enable WoW only for supported models Since platform support is required for WoW, identify and and enable Wow only for supported cards. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/pci.c | 57 ++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 04b2d3ea728f..c1224b5a257b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -634,6 +634,7 @@ void ath_ant_comb_update(struct ath_softc *sc); #define ATH9K_PCI_CUS198 0x0001 #define ATH9K_PCI_CUS230 0x0002 #define ATH9K_PCI_CUS217 0x0004 +#define ATH9K_PCI_WOW 0x0008 /* * Default cache line size, in bytes. diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1e555d899469..16f8b201642b 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -837,6 +837,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) #ifdef CONFIG_PM_SLEEP if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && + (sc->driver_data & ATH9K_PCI_WOW) && device_can_wakeup(sc->dev)) hw->wiphy->wowlan = &ath9k_wowlan_support; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b096bb2c28c8..c585c9b35973 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -79,6 +79,63 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { 0x6661), .driver_data = ATH9K_PCI_CUS217 }, + /* AR9462 with WoW support */ + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_ATHEROS, + 0x3117), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_LENOVO, + 0x3214), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_ATTANSIC, + 0x0091), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_AZWAVE, + 0x2110), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_ASUSTEK, + 0x850E), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x11AD, /* LITEON */ + 0x6631), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x11AD, /* LITEON */ + 0x6641), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + PCI_VENDOR_ID_HP, + 0x1864), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x14CD, /* USI */ + 0x0063), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x14CD, /* USI */ + 0x0064), + .driver_data = ATH9K_PCI_WOW }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, + 0x0034, + 0x10CF, /* Fujitsu */ + 0x1783), + .driver_data = ATH9K_PCI_WOW }, + { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */ -- GitLab From 428e3cf5f98cf9528586854b1c4f9f9f76f54b4e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 21 Jun 2013 15:26:20 +0300 Subject: [PATCH 1779/2900] ipw2x00: printing the wrong array in debug code Smatch complains that this is a read past the end of the array. It turns out we are printing the wrong array here. Signed-off-by: Dan Carpenter Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2x00/libipw_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index 95a1ca1e895c..9ffe65931b29 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1195,7 +1195,7 @@ static int libipw_parse_info_param(struct libipw_info_element #ifdef CONFIG_LIBIPW_DEBUG p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", - network->rates[i]); + network->rates_ex[i]); #endif if (libipw_is_ofdm_rate (info_element->data[i])) { -- GitLab From 0a6f3a8ebaf13407523c2c7d575b4ca2debd23ba Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 22 Jun 2013 13:13:25 +0200 Subject: [PATCH 1780/2900] rt2x00: read 5GHz TX power values from the correct offset The current code uses the same index value both for the channel information array and for the TX power table. The index starts from 14, however the index of the TX power table must start from zero. Fix it, in order to get the correct TX power value for a given channel. The changes in rt61pci.c and rt73usb.c are compile tested only. Signed-off-by: Gabor Juhos Cc: stable@vger.kernel.org Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.c | 3 ++- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3aa30ddcbfea..4072242b2452 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6254,8 +6254,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); for (i = 14; i < spec->num_channels; i++) { - info[i].default_power1 = default_power1[i]; - info[i].default_power2 = default_power2[i]; + info[i].default_power1 = default_power1[i - 14]; + info[i].default_power2 = default_power2[i - 14]; } } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 53754bc66d05..54d3ddfc9888 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2825,7 +2825,8 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 14; i < spec->num_channels; i++) { info[i].max_power = MAX_TXPOWER; - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + info[i].default_power1 = + TXPOWER_FROM_DEV(tx_power[i - 14]); } } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1616ed484ceb..1d3880e09a13 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2167,7 +2167,8 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 14; i < spec->num_channels; i++) { info[i].max_power = MAX_TXPOWER; - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + info[i].default_power1 = + TXPOWER_FROM_DEV(tx_power[i - 14]); } } -- GitLab From a53aff5da60b5c8c4d416f80040e6e7edb7f12df Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 22 Jun 2013 16:31:58 +0200 Subject: [PATCH 1781/2900] rt2x00: rt2800pci: don't use TXWI_DESC_SIZE directly Different chipsets may use different TXWI descriptor size. Instead of using a hardcoded value, use the 'queue->winfo_size' which holds the correct value for a given device. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 7c7478219bbc..e66491829507 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -637,6 +637,7 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, struct queue_entry_priv_mmio *entry_priv = entry->priv_data; __le32 *txd = entry_priv->desc; u32 word; + const unsigned int txwi_size = entry->queue->winfo_size; /* * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 @@ -659,14 +660,14 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry, !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W1_BURST, test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE); + rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); rt2x00_desc_write(txd, 1, word); word = 0; rt2x00_set_field32(&word, TXD_W2_SD_PTR1, - skbdesc->skb_dma + TXWI_DESC_SIZE); + skbdesc->skb_dma + txwi_size); rt2x00_desc_write(txd, 2, word); word = 0; -- GitLab From 150cc692673018d195bb90cbc3ae353ffda2625d Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 22 Jun 2013 16:31:59 +0200 Subject: [PATCH 1782/2900] rt2x00: rt2800: unify [RT]XWI_SIZE defines Use common names instead of chip specific ones. The patch contains no functional changes, but it makes it easier to add support for further descriptor sizes. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 10 ++++++---- drivers/net/wireless/rt2x00/rt2800pci.c | 6 +++--- drivers/net/wireless/rt2x00/rt2800usb.c | 8 ++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index a7630d5ec892..fe43d011f004 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2625,11 +2625,13 @@ struct mac_iveiv_entry { /* * DMA descriptor defines. */ -#define TXWI_DESC_SIZE (4 * sizeof(__le32)) -#define RXWI_DESC_SIZE (4 * sizeof(__le32)) -#define TXWI_DESC_SIZE_5592 (5 * sizeof(__le32)) -#define RXWI_DESC_SIZE_5592 (6 * sizeof(__le32)) +#define TXWI_DESC_SIZE_4WORDS (4 * sizeof(__le32)) +#define TXWI_DESC_SIZE_5WORDS (5 * sizeof(__le32)) + +#define RXWI_DESC_SIZE_4WORDS (4 * sizeof(__le32)) +#define RXWI_DESC_SIZE_6WORDS (6 * sizeof(__le32)) + /* * TX WI structure */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index e66491829507..00055627eb8d 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1194,7 +1194,7 @@ static void rt2800pci_queue_init(struct data_queue *queue) queue->limit = 128; queue->data_size = AGGREGATION_SIZE; queue->desc_size = RXD_DESC_SIZE; - queue->winfo_size = RXWI_DESC_SIZE; + queue->winfo_size = RXWI_DESC_SIZE_4WORDS; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; @@ -1205,7 +1205,7 @@ static void rt2800pci_queue_init(struct data_queue *queue) queue->limit = 64; queue->data_size = AGGREGATION_SIZE; queue->desc_size = TXD_DESC_SIZE; - queue->winfo_size = TXWI_DESC_SIZE; + queue->winfo_size = TXWI_DESC_SIZE_4WORDS; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; @@ -1213,7 +1213,7 @@ static void rt2800pci_queue_init(struct data_queue *queue) queue->limit = 8; queue->data_size = 0; /* No DMA required for beacons */ queue->desc_size = TXD_DESC_SIZE; - queue->winfo_size = TXWI_DESC_SIZE; + queue->winfo_size = TXWI_DESC_SIZE_4WORDS; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 7edd903dd749..840833b26bfa 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -855,11 +855,11 @@ static void rt2800usb_queue_init(struct data_queue *queue) unsigned short txwi_size, rxwi_size; if (rt2x00_rt(rt2x00dev, RT5592)) { - txwi_size = TXWI_DESC_SIZE_5592; - rxwi_size = RXWI_DESC_SIZE_5592; + txwi_size = TXWI_DESC_SIZE_5WORDS; + rxwi_size = RXWI_DESC_SIZE_6WORDS; } else { - txwi_size = TXWI_DESC_SIZE; - rxwi_size = RXWI_DESC_SIZE; + txwi_size = TXWI_DESC_SIZE_4WORDS; + rxwi_size = RXWI_DESC_SIZE_4WORDS; } switch (queue->qid) { -- GitLab From 99b55bd22a4ecfc70e4bf36e69d26c4c219f3bfb Mon Sep 17 00:00:00 2001 From: Kirshenbaum Erez Date: Sun, 23 Jun 2013 12:59:34 +0300 Subject: [PATCH 1783/2900] wil6210: set vring index for all descriptors The vring index (MAC queue id) must be set in all TX descriptors otherwise HW will fail to release descriptors for a specific vring (disconnect or vring switch flows). This is normally occurs when fragmentation required, if vring index will not be the same for all SKB descriptors HW will fail to flush this MAC queue. Signed-off-by: Kirshenbaum Erez Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index e1c492b9dfef..73d6c2dd08a4 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -621,7 +621,8 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, return NULL; } -static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len) +static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, + int vring_index) { wil_desc_addr_set(&d->dma.addr, pa); d->dma.ip_length = 0; @@ -630,7 +631,7 @@ static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len) d->dma.error = 0; d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ d->dma.length = cpu_to_le16((u16)len); - d->dma.d0 = 0; + d->dma.d0 = (vring_index << DMA_CFG_DESC_TX_0_QID_POS); d->mac.d[0] = 0; d->mac.d[1] = 0; d->mac.d[2] = 0; @@ -684,7 +685,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, if (unlikely(dma_mapping_error(dev, pa))) return -EINVAL; /* 1-st segment */ - wil_tx_desc_map(d, pa, skb_headlen(skb)); + wil_tx_desc_map(d, pa, skb_headlen(skb), vring_index); d->mac.d[2] |= ((nr_frags + 1) << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); if (nr_frags) @@ -701,7 +702,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, pa))) goto dma_error; - wil_tx_desc_map(d, pa, len); + wil_tx_desc_map(d, pa, len, vring_index); vring->ctx[i] = NULL; *_d = *d; } @@ -709,7 +710,6 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); - d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); *_d = *d; wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4, -- GitLab From 668b2bbd7fd5a87e54e83b621658d4290811c4a0 Mon Sep 17 00:00:00 2001 From: Kirshenbaum Erez Date: Sun, 23 Jun 2013 12:59:35 +0300 Subject: [PATCH 1784/2900] wil6210: add HW write-back option in TX descriptor Map BIT 9 in TX DMA DWARD 0 as HW write back option. We must turn on this option in the last TX descriptor, this is required for old HW compatability. This option indicate to HW that WB is required for this descriptor. Signed-off-by: Kirshenbaum Erez Signed-off-by: Vladimir Kondratiev Signed-off-by: John W. Linville --- drivers/net/wireless/ath/wil6210/txrx.c | 2 +- drivers/net/wireless/ath/wil6210/txrx.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 73d6c2dd08a4..d240b24e1ccf 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -708,7 +708,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, } /* for the last seg only */ d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); - d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ + d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS); d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); *_d = *d; diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 23c0781cdb93..859aea68a1fa 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -201,6 +201,10 @@ struct vring_tx_mac { #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 +#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_POS 9 +#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_LEN 1 +#define DMA_CFG_DESC_TX_0_CMD_MARK_WB_MSK 0x200 + #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 -- GitLab From 73e088ed17c2880a963cc760a78af8a06d4a4d9d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 23 Jun 2013 18:14:43 -0500 Subject: [PATCH 1785/2900] rtlwifi: rtl8723ae: Fix typo in firmware names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver loads its firmware from files rtlwifi/rtl8723fw*.bin, but the MODULE_FIRMWARE macros refer to rtlwifi/RTL8723aefw*.bin. Signed-off-by: Larry Finger Cc: Stable [3.8+] Reported-by: Axel Köllhofer Signed-off-by: John W. Linville --- drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c index e4c4cdc3eb67..d9ee2efffe5f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c @@ -251,7 +251,7 @@ static struct rtl_hal_cfg rtl8723ae_hal_cfg = { .bar_id = 2, .write_readback = true, .name = "rtl8723ae_pci", - .fw_name = "rtlwifi/rtl8723aefw.bin", + .fw_name = "rtlwifi/rtl8723fw.bin", .ops = &rtl8723ae_hal_ops, .mod_params = &rtl8723ae_mod_params, .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, @@ -353,8 +353,8 @@ MODULE_AUTHOR("Realtek WlanFAE "); MODULE_AUTHOR("Larry Finger "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek 8723E 802.11n PCI wireless"); -MODULE_FIRMWARE("rtlwifi/rtl8723aefw.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8723aefw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723fw.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723fw_B.bin"); module_param_named(swenc, rtl8723ae_mod_params.sw_crypto, bool, 0444); module_param_named(debug, rtl8723ae_mod_params.debug, int, 0444); -- GitLab From 7c676d953f21f70298830df9875e39166147e915 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 24 Jun 2013 18:18:43 +0530 Subject: [PATCH 1786/2900] ath9k: Add version macros for AR9462 2.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/reg.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index f7c90cc58d56..5af97442ac37 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -806,6 +806,7 @@ #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_VERSION_9462 0x280 #define AR_SREV_REVISION_9462_20 2 +#define AR_SREV_REVISION_9462_21 3 #define AR_SREV_VERSION_9565 0x2C0 #define AR_SREV_REVISION_9565_10 0 #define AR_SREV_VERSION_9550 0x400 @@ -911,10 +912,18 @@ #define AR_SREV_9462(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) - #define AR_SREV_9462_20(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) +#define AR_SREV_9462_21(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21)) +#define AR_SREV_9462_20_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) +#define AR_SREV_9462_21_OR_LATER(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21)) #define AR_SREV_9565(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) -- GitLab From 12c75ef8c38f9224f9921b6a8fcf8a68ccdf81d4 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 24 Jun 2013 18:18:44 +0530 Subject: [PATCH 1787/2900] ath9k: Add initvals for AR9462 2.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- .../wireless/ath/ath9k/ar9462_2p1_initvals.h | 1774 +++++++++++++++++ 1 file changed, 1774 insertions(+) create mode 100644 drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h new file mode 100644 index 000000000000..4dbc294df7e3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h @@ -0,0 +1,1774 @@ +/* + * Copyright (c) 2010-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9462_2P1_H +#define INITVALS_9462_2P1_H + +/* AR9462 2.1 */ + +static const u32 ar9462_2p1_mac_core[][2] = { + /* Addr allmodes */ + {0x00000008, 0x00000000}, + {0x00000030, 0x000e0085}, + {0x00000034, 0x00000005}, + {0x00000040, 0x00000000}, + {0x00000044, 0x00000000}, + {0x00000048, 0x00000008}, + {0x0000004c, 0x00000010}, + {0x00000050, 0x00000000}, + {0x00001040, 0x002ffc0f}, + {0x00001044, 0x002ffc0f}, + {0x00001048, 0x002ffc0f}, + {0x0000104c, 0x002ffc0f}, + {0x00001050, 0x002ffc0f}, + {0x00001054, 0x002ffc0f}, + {0x00001058, 0x002ffc0f}, + {0x0000105c, 0x002ffc0f}, + {0x00001060, 0x002ffc0f}, + {0x00001064, 0x002ffc0f}, + {0x000010f0, 0x00000100}, + {0x00001270, 0x00000000}, + {0x000012b0, 0x00000000}, + {0x000012f0, 0x00000000}, + {0x0000143c, 0x00000000}, + {0x0000147c, 0x00000000}, + {0x00001810, 0x0f000003}, + {0x00008000, 0x00000000}, + {0x00008004, 0x00000000}, + {0x00008008, 0x00000000}, + {0x0000800c, 0x00000000}, + {0x00008018, 0x00000000}, + {0x00008020, 0x00000000}, + {0x00008038, 0x00000000}, + {0x0000803c, 0x00080000}, + {0x00008040, 0x00000000}, + {0x00008044, 0x00000000}, + {0x00008048, 0x00000000}, + {0x0000804c, 0xffffffff}, + {0x00008054, 0x00000000}, + {0x00008058, 0x00000000}, + {0x0000805c, 0x000fc78f}, + {0x00008060, 0x0000000f}, + {0x00008064, 0x00000000}, + {0x00008070, 0x00000310}, + {0x00008074, 0x00000020}, + {0x00008078, 0x00000000}, + {0x0000809c, 0x0000000f}, + {0x000080a0, 0x00000000}, + {0x000080a4, 0x02ff0000}, + {0x000080a8, 0x0e070605}, + {0x000080ac, 0x0000000d}, + {0x000080b0, 0x00000000}, + {0x000080b4, 0x00000000}, + {0x000080b8, 0x00000000}, + {0x000080bc, 0x00000000}, + {0x000080c0, 0x2a800000}, + {0x000080c4, 0x06900168}, + {0x000080c8, 0x13881c20}, + {0x000080cc, 0x01f40000}, + {0x000080d0, 0x00252500}, + {0x000080d4, 0x00b00005}, + {0x000080d8, 0x00400002}, + {0x000080dc, 0x00000000}, + {0x000080e0, 0xffffffff}, + {0x000080e4, 0x0000ffff}, + {0x000080e8, 0x3f3f3f3f}, + {0x000080ec, 0x00000000}, + {0x000080f0, 0x00000000}, + {0x000080f4, 0x00000000}, + {0x000080fc, 0x00020000}, + {0x00008100, 0x00000000}, + {0x00008108, 0x00000052}, + {0x0000810c, 0x00000000}, + {0x00008110, 0x00000000}, + {0x00008114, 0x000007ff}, + {0x00008118, 0x000000aa}, + {0x0000811c, 0x00003210}, + {0x00008124, 0x00000000}, + {0x00008128, 0x00000000}, + {0x0000812c, 0x00000000}, + {0x00008130, 0x00000000}, + {0x00008134, 0x00000000}, + {0x00008138, 0x00000000}, + {0x0000813c, 0x0000ffff}, + {0x00008144, 0xffffffff}, + {0x00008168, 0x00000000}, + {0x0000816c, 0x00000000}, + {0x00008170, 0x18486e00}, + {0x00008174, 0x33332210}, + {0x00008178, 0x00000000}, + {0x0000817c, 0x00020000}, + {0x000081c4, 0x33332210}, + {0x000081c8, 0x00000000}, + {0x000081cc, 0x00000000}, + {0x000081d4, 0x00000000}, + {0x000081ec, 0x00000000}, + {0x000081f0, 0x00000000}, + {0x000081f4, 0x00000000}, + {0x000081f8, 0x00000000}, + {0x000081fc, 0x00000000}, + {0x00008240, 0x00100000}, + {0x00008244, 0x0010f400}, + {0x00008248, 0x00000800}, + {0x0000824c, 0x0001e800}, + {0x00008250, 0x00000000}, + {0x00008254, 0x00000000}, + {0x00008258, 0x00000000}, + {0x0000825c, 0x40000000}, + {0x00008260, 0x00080922}, + {0x00008264, 0x99c00010}, + {0x00008268, 0xffffffff}, + {0x0000826c, 0x0000ffff}, + {0x00008270, 0x00000000}, + {0x00008274, 0x40000000}, + {0x00008278, 0x003e4180}, + {0x0000827c, 0x00000004}, + {0x00008284, 0x0000002c}, + {0x00008288, 0x0000002c}, + {0x0000828c, 0x000000ff}, + {0x00008294, 0x00000000}, + {0x00008298, 0x00000000}, + {0x0000829c, 0x00000000}, + {0x00008300, 0x00000140}, + {0x00008314, 0x00000000}, + {0x0000831c, 0x0000010d}, + {0x00008328, 0x00000000}, + {0x0000832c, 0x0000001f}, + {0x00008330, 0x00000302}, + {0x00008334, 0x00000700}, + {0x00008338, 0xffff0000}, + {0x0000833c, 0x02400000}, + {0x00008340, 0x000107ff}, + {0x00008344, 0xaa48107b}, + {0x00008348, 0x008f0000}, + {0x0000835c, 0x00000000}, + {0x00008360, 0xffffffff}, + {0x00008364, 0xffffffff}, + {0x00008368, 0x00000000}, + {0x00008370, 0x00000000}, + {0x00008374, 0x000000ff}, + {0x00008378, 0x00000000}, + {0x0000837c, 0x00000000}, + {0x00008380, 0xffffffff}, + {0x00008384, 0xffffffff}, + {0x00008390, 0xffffffff}, + {0x00008394, 0xffffffff}, + {0x00008398, 0x00000000}, + {0x0000839c, 0x00000000}, + {0x000083a4, 0x0000fa14}, + {0x000083a8, 0x000f0c00}, + {0x000083ac, 0x33332210}, + {0x000083b0, 0x33332210}, + {0x000083b4, 0x33332210}, + {0x000083b8, 0x33332210}, + {0x000083bc, 0x00000000}, + {0x000083c0, 0x00000000}, + {0x000083c4, 0x00000000}, + {0x000083c8, 0x00000000}, + {0x000083cc, 0x00000200}, + {0x000083d0, 0x000301ff}, +}; + +static const u32 ar9462_2p1_mac_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, + {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, + {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, + {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, + {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, + {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, + {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, + {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9462_2p1_baseband_core[][2] = { + /* Addr allmodes */ + {0x00009800, 0xafe68e30}, + {0x00009804, 0xfd14e000}, + {0x00009808, 0x9c0a9f6b}, + {0x0000980c, 0x04900000}, + {0x00009814, 0x9280c00a}, + {0x00009818, 0x00000000}, + {0x0000981c, 0x00020028}, + {0x00009834, 0x6400a290}, + {0x00009838, 0x0108ecff}, + {0x0000983c, 0x0d000600}, + {0x00009880, 0x201fff00}, + {0x00009884, 0x00001042}, + {0x000098a4, 0x00200400}, + {0x000098b0, 0x32440bbe}, + {0x000098d0, 0x004b6a8e}, + {0x000098d4, 0x00000820}, + {0x000098dc, 0x00000000}, + {0x000098e4, 0x01ffffff}, + {0x000098e8, 0x01ffffff}, + {0x000098ec, 0x01ffffff}, + {0x000098f0, 0x00000000}, + {0x000098f4, 0x00000000}, + {0x00009bf0, 0x80000000}, + {0x00009c04, 0xff55ff55}, + {0x00009c08, 0x0320ff55}, + {0x00009c0c, 0x00000000}, + {0x00009c10, 0x00000000}, + {0x00009c14, 0x00046384}, + {0x00009c18, 0x05b6b440}, + {0x00009c1c, 0x00b6b440}, + {0x00009d00, 0xc080a333}, + {0x00009d04, 0x40206c10}, + {0x00009d08, 0x009c4060}, + {0x00009d0c, 0x9883800a}, + {0x00009d10, 0x01834061}, + {0x00009d14, 0x00c0040b}, + {0x00009d18, 0x00000000}, + {0x00009e08, 0x0038230c}, + {0x00009e24, 0x990bb515}, + {0x00009e28, 0x0c6f0000}, + {0x00009e30, 0x06336f77}, + {0x00009e34, 0x6af6532f}, + {0x00009e38, 0x0cc80c00}, + {0x00009e40, 0x15262820}, + {0x00009e4c, 0x00001004}, + {0x00009e50, 0x00ff03f1}, + {0x00009e54, 0xe4c555c2}, + {0x00009e58, 0xfd857722}, + {0x00009e5c, 0xe9198724}, + {0x00009fc0, 0x803e4788}, + {0x00009fc4, 0x0001efb5}, + {0x00009fcc, 0x40000014}, + {0x00009fd0, 0x0a193b93}, + {0x0000a20c, 0x00000000}, + {0x0000a220, 0x00000000}, + {0x0000a224, 0x00000000}, + {0x0000a228, 0x10002310}, + {0x0000a23c, 0x00000000}, + {0x0000a244, 0x0c000000}, + {0x0000a2a0, 0x00000001}, + {0x0000a2c0, 0x00000001}, + {0x0000a2c8, 0x00000000}, + {0x0000a2cc, 0x18c43433}, + {0x0000a2d4, 0x00000000}, + {0x0000a2ec, 0x00000000}, + {0x0000a2f0, 0x00000000}, + {0x0000a2f4, 0x00000000}, + {0x0000a2f8, 0x00000000}, + {0x0000a344, 0x00000000}, + {0x0000a34c, 0x00000000}, + {0x0000a350, 0x0000a000}, + {0x0000a364, 0x00000000}, + {0x0000a370, 0x00000000}, + {0x0000a390, 0x00000001}, + {0x0000a394, 0x00000444}, + {0x0000a398, 0x001f0e0f}, + {0x0000a39c, 0x0075393f}, + {0x0000a3a0, 0xb79f6427}, + {0x0000a3c0, 0x20202020}, + {0x0000a3c4, 0x22222220}, + {0x0000a3c8, 0x20200020}, + {0x0000a3cc, 0x20202020}, + {0x0000a3d0, 0x20202020}, + {0x0000a3d4, 0x20202020}, + {0x0000a3d8, 0x20202020}, + {0x0000a3dc, 0x20202020}, + {0x0000a3e0, 0x20202020}, + {0x0000a3e4, 0x20202020}, + {0x0000a3e8, 0x20202020}, + {0x0000a3ec, 0x20202020}, + {0x0000a3f0, 0x00000000}, + {0x0000a3f4, 0x00000006}, + {0x0000a3f8, 0x0c9bd380}, + {0x0000a3fc, 0x000f0f01}, + {0x0000a400, 0x8fa91f01}, + {0x0000a404, 0x00000000}, + {0x0000a408, 0x0e79e5c6}, + {0x0000a40c, 0x00820820}, + {0x0000a414, 0x1ce739ce}, + {0x0000a418, 0x2d001dce}, + {0x0000a434, 0x00000000}, + {0x0000a438, 0x00001801}, + {0x0000a43c, 0x00100000}, + {0x0000a444, 0x00000000}, + {0x0000a448, 0x05000080}, + {0x0000a44c, 0x00000001}, + {0x0000a450, 0x00010000}, + {0x0000a454, 0x07000000}, + {0x0000a644, 0xbfad9d74}, + {0x0000a648, 0x0048060a}, + {0x0000a64c, 0x00002037}, + {0x0000a670, 0x03020100}, + {0x0000a674, 0x09080504}, + {0x0000a678, 0x0d0c0b0a}, + {0x0000a67c, 0x13121110}, + {0x0000a680, 0x31301514}, + {0x0000a684, 0x35343332}, + {0x0000a688, 0x00000036}, + {0x0000a690, 0x00000838}, + {0x0000a6b0, 0x0000000a}, + {0x0000a6b4, 0x00512c01}, + {0x0000a7c0, 0x00000000}, + {0x0000a7c4, 0xfffffffc}, + {0x0000a7c8, 0x00000000}, + {0x0000a7cc, 0x00000000}, + {0x0000a7d0, 0x00000000}, + {0x0000a7d4, 0x00000004}, + {0x0000a7dc, 0x00000000}, + {0x0000a7f0, 0x80000000}, + {0x0000a8d0, 0x004b6a8e}, + {0x0000a8d4, 0x00000820}, + {0x0000a8dc, 0x00000000}, + {0x0000a8f0, 0x00000000}, + {0x0000a8f4, 0x00000000}, + {0x0000abf0, 0x80000000}, + {0x0000b2d0, 0x00000080}, + {0x0000b2d4, 0x00000000}, + {0x0000b2ec, 0x00000000}, + {0x0000b2f0, 0x00000000}, + {0x0000b2f4, 0x00000000}, + {0x0000b2f8, 0x00000000}, + {0x0000b408, 0x0e79e5c0}, + {0x0000b40c, 0x00820820}, + {0x0000b420, 0x00000000}, + {0x0000b6b0, 0x0000000a}, + {0x0000b6b4, 0x00000001}, +}; + +static const u32 ar9462_2p1_baseband_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, + {0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, + {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, + {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, + {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, + {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, + {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2}, + {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, + {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e}, + {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, + {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, + {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, + {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, + {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, + {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, + {0x0000a204, 0x01318fc0, 0x01318fc4, 0x01318fc4, 0x01318fc0}, + {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, + {0x0000a22c, 0x01026a2f, 0x01026a27, 0x01026a2f, 0x01026a2f}, + {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, + {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, + {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, + {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, + {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, + {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, + {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, + {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, + {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, + {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, + {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, + {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, + {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, + {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, + {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, + {0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00}, + {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, + {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, + {0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, + {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, + {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, + {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, + {0x0000b284, 0x00000000, 0x00000000, 0x00000550, 0x00000550}, +}; + +static const u32 ar9462_2p1_radio_core[][2] = { + /* Addr allmodes */ + {0x00016000, 0x36db6db6}, + {0x00016004, 0x6db6db40}, + {0x00016008, 0x73f00000}, + {0x0001600c, 0x00000000}, + {0x00016010, 0x6d820001}, + {0x00016040, 0x7f80fff8}, + {0x0001604c, 0x2699e04f}, + {0x00016050, 0x6db6db6c}, + {0x00016058, 0x6c200000}, + {0x00016080, 0x000c0000}, + {0x00016084, 0x9a68048c}, + {0x00016088, 0x54214514}, + {0x0001608c, 0x1203040b}, + {0x00016090, 0x24926490}, + {0x00016098, 0xd2888888}, + {0x000160a0, 0x0a108ffe}, + {0x000160a4, 0x812fc491}, + {0x000160a8, 0x423c8000}, + {0x000160b4, 0x92000000}, + {0x000160b8, 0x0285dddc}, + {0x000160bc, 0x02908888}, + {0x000160c0, 0x00adb6d0}, + {0x000160c4, 0x6db6db60}, + {0x000160c8, 0x6db6db6c}, + {0x000160cc, 0x0de6c1b0}, + {0x00016100, 0x3fffbe04}, + {0x00016104, 0xfff80000}, + {0x00016108, 0x00200400}, + {0x00016110, 0x00000000}, + {0x00016144, 0x02084080}, + {0x00016148, 0x000080c0}, + {0x00016280, 0x050a0001}, + {0x00016284, 0x3d841418}, + {0x00016288, 0x00000000}, + {0x0001628c, 0xe3000000}, + {0x00016290, 0xa1005080}, + {0x00016294, 0x00000020}, + {0x00016298, 0x54a82900}, + {0x00016340, 0x121e4276}, + {0x00016344, 0x00300000}, + {0x00016400, 0x36db6db6}, + {0x00016404, 0x6db6db40}, + {0x00016408, 0x73f00000}, + {0x0001640c, 0x00000000}, + {0x00016410, 0x6c800001}, + {0x00016440, 0x7f80fff8}, + {0x0001644c, 0x4699e04f}, + {0x00016450, 0x6db6db6c}, + {0x00016500, 0x3fffbe04}, + {0x00016504, 0xfff80000}, + {0x00016508, 0x00200400}, + {0x00016510, 0x00000000}, + {0x00016544, 0x02084080}, + {0x00016548, 0x000080c0}, +}; + +static const u32 ar9462_2p1_radio_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x0001609c, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524, 0x0b8ee524}, + {0x000160b0, 0x01d67f70, 0x01d67f70, 0x01d67f70, 0x01d67f70}, + {0x0001610c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, + {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, +}; + +static const u32 ar9462_2p1_soc_preamble[][2] = { + /* Addr allmodes */ + {0x000040a4, 0x00a0c1c9}, + {0x00007020, 0x00000000}, + {0x00007034, 0x00000002}, + {0x00007038, 0x000004c2}, +}; + +static const u32 ar9462_2p1_soc_postamble[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033}, +}; + +static const u32 ar9462_2p1_radio_postamble_sys2ant[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808}, + {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, + {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +}; + +static const u32 ar9462_2p1_common_rx_gain[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x01910190}, + {0x0000a030, 0x01930192}, + {0x0000a034, 0x01950194}, + {0x0000a038, 0x038a0196}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x22222229}, + {0x0000a084, 0x1d1d1d1d}, + {0x0000a088, 0x1d1d1d1d}, + {0x0000a08c, 0x1d1d1d1d}, + {0x0000a090, 0x171d1d1d}, + {0x0000a094, 0x11111717}, + {0x0000a098, 0x00030311}, + {0x0000a09c, 0x00000000}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x2a2d2f32}, + {0x0000b084, 0x21232328}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9462_2p1_common_mixed_rx_gain[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x2a2d2f32}, + {0x0000b084, 0x21232328}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9462_2p1_baseband_core_mix_rxgain[][2] = { + /* Addr allmodes */ + {0x00009fd0, 0x0a2d6b93}, +}; + +static const u32 ar9462_2p1_baseband_postamble_mix_rxgain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009820, 0x206a022e, 0x206a022e, 0x206a01ae, 0x206a01ae}, + {0x00009824, 0x63c640de, 0x5ac640d0, 0x63c640da, 0x63c640da}, + {0x00009828, 0x0796be89, 0x0696b081, 0x0916be81, 0x0916be81}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000d8, 0x6c4000d8}, + {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec86d2e, 0x7ec86d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32395c5e}, +}; + +static const u32 ar9462_2p1_baseband_postamble_5g_xlna[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, +}; + +static const u32 ar9462_2p1_common_wo_xlna_rx_gain[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x32323232}, + {0x0000b084, 0x2f2f3232}, + {0x0000b088, 0x23282a2d}, + {0x0000b08c, 0x1c1e2123}, + {0x0000b090, 0x14171919}, + {0x0000b094, 0x0e0e1214}, + {0x0000b098, 0x03050707}, + {0x0000b09c, 0x00030303}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9462_2p1_common_5g_xlna_only_rx_gain[][2] = { + /* Addr allmodes */ + {0x0000a000, 0x00010000}, + {0x0000a004, 0x00030002}, + {0x0000a008, 0x00050004}, + {0x0000a00c, 0x00810080}, + {0x0000a010, 0x00830082}, + {0x0000a014, 0x01810180}, + {0x0000a018, 0x01830182}, + {0x0000a01c, 0x01850184}, + {0x0000a020, 0x01890188}, + {0x0000a024, 0x018b018a}, + {0x0000a028, 0x018d018c}, + {0x0000a02c, 0x03820190}, + {0x0000a030, 0x03840383}, + {0x0000a034, 0x03880385}, + {0x0000a038, 0x038a0389}, + {0x0000a03c, 0x038c038b}, + {0x0000a040, 0x0390038d}, + {0x0000a044, 0x03920391}, + {0x0000a048, 0x03940393}, + {0x0000a04c, 0x03960395}, + {0x0000a050, 0x00000000}, + {0x0000a054, 0x00000000}, + {0x0000a058, 0x00000000}, + {0x0000a05c, 0x00000000}, + {0x0000a060, 0x00000000}, + {0x0000a064, 0x00000000}, + {0x0000a068, 0x00000000}, + {0x0000a06c, 0x00000000}, + {0x0000a070, 0x00000000}, + {0x0000a074, 0x00000000}, + {0x0000a078, 0x00000000}, + {0x0000a07c, 0x00000000}, + {0x0000a080, 0x29292929}, + {0x0000a084, 0x29292929}, + {0x0000a088, 0x29292929}, + {0x0000a08c, 0x29292929}, + {0x0000a090, 0x22292929}, + {0x0000a094, 0x1d1d2222}, + {0x0000a098, 0x0c111117}, + {0x0000a09c, 0x00030303}, + {0x0000a0a0, 0x00000000}, + {0x0000a0a4, 0x00000000}, + {0x0000a0a8, 0x00000000}, + {0x0000a0ac, 0x00000000}, + {0x0000a0b0, 0x00000000}, + {0x0000a0b4, 0x00000000}, + {0x0000a0b8, 0x00000000}, + {0x0000a0bc, 0x00000000}, + {0x0000a0c0, 0x001f0000}, + {0x0000a0c4, 0x01000101}, + {0x0000a0c8, 0x011e011f}, + {0x0000a0cc, 0x011c011d}, + {0x0000a0d0, 0x02030204}, + {0x0000a0d4, 0x02010202}, + {0x0000a0d8, 0x021f0200}, + {0x0000a0dc, 0x0302021e}, + {0x0000a0e0, 0x03000301}, + {0x0000a0e4, 0x031e031f}, + {0x0000a0e8, 0x0402031d}, + {0x0000a0ec, 0x04000401}, + {0x0000a0f0, 0x041e041f}, + {0x0000a0f4, 0x0502041d}, + {0x0000a0f8, 0x05000501}, + {0x0000a0fc, 0x051e051f}, + {0x0000a100, 0x06010602}, + {0x0000a104, 0x061f0600}, + {0x0000a108, 0x061d061e}, + {0x0000a10c, 0x07020703}, + {0x0000a110, 0x07000701}, + {0x0000a114, 0x00000000}, + {0x0000a118, 0x00000000}, + {0x0000a11c, 0x00000000}, + {0x0000a120, 0x00000000}, + {0x0000a124, 0x00000000}, + {0x0000a128, 0x00000000}, + {0x0000a12c, 0x00000000}, + {0x0000a130, 0x00000000}, + {0x0000a134, 0x00000000}, + {0x0000a138, 0x00000000}, + {0x0000a13c, 0x00000000}, + {0x0000a140, 0x001f0000}, + {0x0000a144, 0x01000101}, + {0x0000a148, 0x011e011f}, + {0x0000a14c, 0x011c011d}, + {0x0000a150, 0x02030204}, + {0x0000a154, 0x02010202}, + {0x0000a158, 0x021f0200}, + {0x0000a15c, 0x0302021e}, + {0x0000a160, 0x03000301}, + {0x0000a164, 0x031e031f}, + {0x0000a168, 0x0402031d}, + {0x0000a16c, 0x04000401}, + {0x0000a170, 0x041e041f}, + {0x0000a174, 0x0502041d}, + {0x0000a178, 0x05000501}, + {0x0000a17c, 0x051e051f}, + {0x0000a180, 0x06010602}, + {0x0000a184, 0x061f0600}, + {0x0000a188, 0x061d061e}, + {0x0000a18c, 0x07020703}, + {0x0000a190, 0x07000701}, + {0x0000a194, 0x00000000}, + {0x0000a198, 0x00000000}, + {0x0000a19c, 0x00000000}, + {0x0000a1a0, 0x00000000}, + {0x0000a1a4, 0x00000000}, + {0x0000a1a8, 0x00000000}, + {0x0000a1ac, 0x00000000}, + {0x0000a1b0, 0x00000000}, + {0x0000a1b4, 0x00000000}, + {0x0000a1b8, 0x00000000}, + {0x0000a1bc, 0x00000000}, + {0x0000a1c0, 0x00000000}, + {0x0000a1c4, 0x00000000}, + {0x0000a1c8, 0x00000000}, + {0x0000a1cc, 0x00000000}, + {0x0000a1d0, 0x00000000}, + {0x0000a1d4, 0x00000000}, + {0x0000a1d8, 0x00000000}, + {0x0000a1dc, 0x00000000}, + {0x0000a1e0, 0x00000000}, + {0x0000a1e4, 0x00000000}, + {0x0000a1e8, 0x00000000}, + {0x0000a1ec, 0x00000000}, + {0x0000a1f0, 0x00000396}, + {0x0000a1f4, 0x00000396}, + {0x0000a1f8, 0x00000396}, + {0x0000a1fc, 0x00000196}, + {0x0000b000, 0x00010000}, + {0x0000b004, 0x00030002}, + {0x0000b008, 0x00050004}, + {0x0000b00c, 0x00810080}, + {0x0000b010, 0x00830082}, + {0x0000b014, 0x01810180}, + {0x0000b018, 0x01830182}, + {0x0000b01c, 0x01850184}, + {0x0000b020, 0x02810280}, + {0x0000b024, 0x02830282}, + {0x0000b028, 0x02850284}, + {0x0000b02c, 0x02890288}, + {0x0000b030, 0x028b028a}, + {0x0000b034, 0x0388028c}, + {0x0000b038, 0x038a0389}, + {0x0000b03c, 0x038c038b}, + {0x0000b040, 0x0390038d}, + {0x0000b044, 0x03920391}, + {0x0000b048, 0x03940393}, + {0x0000b04c, 0x03960395}, + {0x0000b050, 0x00000000}, + {0x0000b054, 0x00000000}, + {0x0000b058, 0x00000000}, + {0x0000b05c, 0x00000000}, + {0x0000b060, 0x00000000}, + {0x0000b064, 0x00000000}, + {0x0000b068, 0x00000000}, + {0x0000b06c, 0x00000000}, + {0x0000b070, 0x00000000}, + {0x0000b074, 0x00000000}, + {0x0000b078, 0x00000000}, + {0x0000b07c, 0x00000000}, + {0x0000b080, 0x2a2d2f32}, + {0x0000b084, 0x21232328}, + {0x0000b088, 0x19191c1e}, + {0x0000b08c, 0x12141417}, + {0x0000b090, 0x07070e0e}, + {0x0000b094, 0x03030305}, + {0x0000b098, 0x00000003}, + {0x0000b09c, 0x00000000}, + {0x0000b0a0, 0x00000000}, + {0x0000b0a4, 0x00000000}, + {0x0000b0a8, 0x00000000}, + {0x0000b0ac, 0x00000000}, + {0x0000b0b0, 0x00000000}, + {0x0000b0b4, 0x00000000}, + {0x0000b0b8, 0x00000000}, + {0x0000b0bc, 0x00000000}, + {0x0000b0c0, 0x003f0020}, + {0x0000b0c4, 0x00400041}, + {0x0000b0c8, 0x0140005f}, + {0x0000b0cc, 0x0160015f}, + {0x0000b0d0, 0x017e017f}, + {0x0000b0d4, 0x02410242}, + {0x0000b0d8, 0x025f0240}, + {0x0000b0dc, 0x027f0260}, + {0x0000b0e0, 0x0341027e}, + {0x0000b0e4, 0x035f0340}, + {0x0000b0e8, 0x037f0360}, + {0x0000b0ec, 0x04400441}, + {0x0000b0f0, 0x0460045f}, + {0x0000b0f4, 0x0541047f}, + {0x0000b0f8, 0x055f0540}, + {0x0000b0fc, 0x057f0560}, + {0x0000b100, 0x06400641}, + {0x0000b104, 0x0660065f}, + {0x0000b108, 0x067e067f}, + {0x0000b10c, 0x07410742}, + {0x0000b110, 0x075f0740}, + {0x0000b114, 0x077f0760}, + {0x0000b118, 0x07800781}, + {0x0000b11c, 0x07a0079f}, + {0x0000b120, 0x07c107bf}, + {0x0000b124, 0x000007c0}, + {0x0000b128, 0x00000000}, + {0x0000b12c, 0x00000000}, + {0x0000b130, 0x00000000}, + {0x0000b134, 0x00000000}, + {0x0000b138, 0x00000000}, + {0x0000b13c, 0x00000000}, + {0x0000b140, 0x003f0020}, + {0x0000b144, 0x00400041}, + {0x0000b148, 0x0140005f}, + {0x0000b14c, 0x0160015f}, + {0x0000b150, 0x017e017f}, + {0x0000b154, 0x02410242}, + {0x0000b158, 0x025f0240}, + {0x0000b15c, 0x027f0260}, + {0x0000b160, 0x0341027e}, + {0x0000b164, 0x035f0340}, + {0x0000b168, 0x037f0360}, + {0x0000b16c, 0x04400441}, + {0x0000b170, 0x0460045f}, + {0x0000b174, 0x0541047f}, + {0x0000b178, 0x055f0540}, + {0x0000b17c, 0x057f0560}, + {0x0000b180, 0x06400641}, + {0x0000b184, 0x0660065f}, + {0x0000b188, 0x067e067f}, + {0x0000b18c, 0x07410742}, + {0x0000b190, 0x075f0740}, + {0x0000b194, 0x077f0760}, + {0x0000b198, 0x07800781}, + {0x0000b19c, 0x07a0079f}, + {0x0000b1a0, 0x07c107bf}, + {0x0000b1a4, 0x000007c0}, + {0x0000b1a8, 0x00000000}, + {0x0000b1ac, 0x00000000}, + {0x0000b1b0, 0x00000000}, + {0x0000b1b4, 0x00000000}, + {0x0000b1b8, 0x00000000}, + {0x0000b1bc, 0x00000000}, + {0x0000b1c0, 0x00000000}, + {0x0000b1c4, 0x00000000}, + {0x0000b1c8, 0x00000000}, + {0x0000b1cc, 0x00000000}, + {0x0000b1d0, 0x00000000}, + {0x0000b1d4, 0x00000000}, + {0x0000b1d8, 0x00000000}, + {0x0000b1dc, 0x00000000}, + {0x0000b1e0, 0x00000000}, + {0x0000b1e4, 0x00000000}, + {0x0000b1e8, 0x00000000}, + {0x0000b1ec, 0x00000000}, + {0x0000b1f0, 0x00000396}, + {0x0000b1f4, 0x00000396}, + {0x0000b1f8, 0x00000396}, + {0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9462_2p1_modes_low_ob_db_tx_gain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, + {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, + {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, + {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, + {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, + {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, + {0x00016048, 0x64992060, 0x64992060, 0x64992060, 0x64992060}, + {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, + {0x00016444, 0x012482d4, 0x012482d4, 0x012482d4, 0x012482d4}, + {0x00016448, 0x64992000, 0x64992000, 0x64992000, 0x64992000}, + {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, +}; + +static const u32 ar9462_2p1_modes_high_ob_db_tx_gain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de}, + {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, + {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, + {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, + {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84}, + {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0}, + {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4}, + {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, + {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, + {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, + {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, + {0x00016048, 0x8db49060, 0x8db49060, 0x8db49060, 0x8db49060}, + {0x00016054, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, + {0x00016444, 0x056d82e4, 0x056d82e4, 0x056d82e4, 0x056d82e4}, + {0x00016448, 0x8db49000, 0x8db49000, 0x8db49000, 0x8db49000}, + {0x00016454, 0x6db60000, 0x6db60000, 0x6db60000, 0x6db60000}, +}; + +static const u32 ar9462_2p1_modes_mix_ob_db_tx_gain[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de}, + {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400}, + {0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402}, + {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640}, + {0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec}, + {0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0}, + {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4}, + {0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +}; + +static const u32 ar9462_2p1_modes_fast_clock[][3] = { + /* Addr 5G_HT20 5G_HT40 */ + {0x00001030, 0x00000268, 0x000004d0}, + {0x00001070, 0x0000018c, 0x00000318}, + {0x000010b0, 0x00000fd0, 0x00001fa0}, + {0x00008014, 0x044c044c, 0x08980898}, + {0x0000801c, 0x148ec02b, 0x148ec057}, + {0x00008318, 0x000044c0, 0x00008980}, + {0x00009e00, 0x0372131c, 0x0372131c}, + {0x0000a230, 0x0000400b, 0x00004016}, + {0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9462_2p1_baseband_core_txfir_coeff_japan_2484[][2] = { + /* Addr allmodes */ + {0x0000a398, 0x00000000}, + {0x0000a39c, 0x6f7f0301}, + {0x0000a3a0, 0xca9228ee}, +}; + +#endif /* INITVALS_9462_2P1_H */ -- GitLab From d567e4eb80593b55690eda4be17ed6289630107e Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 24 Jun 2013 18:18:45 +0530 Subject: [PATCH 1788/2900] ath9k: Program initvals for AR9462 2.1 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 59 +++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 671aaa7e7337..3101c399bc33 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -24,6 +24,7 @@ #include "ar955x_1p0_initvals.h" #include "ar9580_1p0_initvals.h" #include "ar9462_2p0_initvals.h" +#include "ar9462_2p1_initvals.h" #include "ar9565_1p0_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -197,6 +198,31 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, ar9485_1_1_pcie_phy_clkreq_disable_L1); + } else if (AR_SREV_9462_21(ah)) { + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], + ar9462_2p1_mac_core); + INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], + ar9462_2p1_mac_postamble); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], + ar9462_2p1_baseband_core); + INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], + ar9462_2p1_baseband_postamble); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], + ar9462_2p1_radio_core); + INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], + ar9462_2p1_radio_postamble); + INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant, + ar9462_2p1_radio_postamble_sys2ant); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], + ar9462_2p1_soc_preamble); + INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], + ar9462_2p1_soc_postamble); + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p1_common_rx_gain); + INIT_INI_ARRAY(&ah->iniModesFastClock, + ar9462_2p1_modes_fast_clock); + INIT_INI_ARRAY(&ah->iniCckfirJapan2484, + ar9462_2p1_baseband_core_txfir_coeff_japan_2484); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core); @@ -407,6 +433,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_lowest_ob_db_tx_gain_table); + else if (AR_SREV_9462_21(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9462_2p1_modes_low_ob_db_tx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_modes_low_ob_db_tx_gain_table_2p0); @@ -438,6 +467,9 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) else if (AR_SREV_9550(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar955x_1p0_modes_no_xpa_tx_gain_table); + else if (AR_SREV_9462_21(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9462_2p1_modes_high_ob_db_tx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_modes_high_ob_db_tx_gain_table_2p0); @@ -507,6 +539,9 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9580_1p0_mixed_ob_db_tx_gain_table); + else if (AR_SREV_9462_21(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9462_2p1_modes_mix_ob_db_tx_gain); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_mixed_ob_db_tx_gain_table_2p2); @@ -584,6 +619,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9580_1p0_rx_gain_table); + else if (AR_SREV_9462_21(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p1_common_rx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_rx_gain_table_2p0); @@ -606,6 +644,9 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9485Common_wo_xlna_rx_gain_1_1); + else if (AR_SREV_9462_21(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p1_common_wo_xlna_rx_gain); else if (AR_SREV_9462_20(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_wo_xlna_rx_gain_table_2p0); @@ -627,7 +668,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) { - if (AR_SREV_9462_20(ah)) { + if (AR_SREV_9462_21(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p1_common_mixed_rx_gain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, + ar9462_2p1_baseband_core_mix_rxgain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, + ar9462_2p1_baseband_postamble_mix_rxgain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + ar9462_2p1_baseband_postamble_5g_xlna); + } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_common_mixed_rx_gain_table_2p0); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_core, @@ -641,7 +691,12 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) { - if (AR_SREV_9462_20(ah)) { + if (AR_SREV_9462_21(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9462_2p1_common_5g_xlna_only_rx_gain); + INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + ar9462_2p1_baseband_postamble_5g_xlna); + } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_2p0_5g_xlna_only_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, -- GitLab From 2b5e54e22f596bcd9ec0018f228a2606e016a108 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 24 Jun 2013 18:18:46 +0530 Subject: [PATCH 1789/2900] ath9k: Add support for AR9462 2.1 Various parts of the HW code are applicable for both v2.0 and v2.1. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 7 ++++--- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 +++--- drivers/net/wireless/ath/ath9k/ar9003_phy.h | 4 ++-- drivers/net/wireless/ath/ath9k/hw.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 1e86977d3322..d105e43d22e1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3606,7 +3606,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE * SWITCH_TABLE_COM_SPDT_WLAN_IDLE */ - if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) { + if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565(ah)) { value = ar9003_switch_com_spdt_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_SWITCH_TABLE_COM_SPDT_ALL, value); @@ -4059,8 +4059,9 @@ static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah) { u32 data, ko, kg; - if (!AR_SREV_9462_20(ah)) + if (!AR_SREV_9462_20_OR_LATER(ah)) return; + ar9300_otp_read_word(ah, 1, &data); ko = data & 0xff; kg = (data >> 8) & 0xff; @@ -4752,7 +4753,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah, AR_PHY_TPC_19_ALPHA_THERM, temp_slope); } - if (AR_SREV_9462_20(ah)) + if (AR_SREV_9462_20_OR_LATER(ah)) REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1, AR_PHY_TPC_19_B1_ALPHA_THERM, temp_slope); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index df84d20e1092..1f694ab3cc78 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -743,7 +743,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex); - if (i == ATH_INI_POST && AR_SREV_9462_20(ah)) + if (i == ATH_INI_POST && AR_SREV_9462_20_OR_LATER(ah)) ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant, modesIndex); @@ -754,7 +754,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, */ REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); - if (AR_SREV_9462_20(ah)) { + if (AR_SREV_9462_20_OR_LATER(ah)) { /* * CUS217 mix LNA mode. */ @@ -1512,7 +1512,7 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah, ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex); ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex); - if (AR_SREV_9462_20(ah)) + if (AR_SREV_9462_20_OR_LATER(ah)) ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant, modesIndex); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 5013c731f9f6..d4d39f305a0b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -954,7 +954,7 @@ #define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208) #define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c) #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) -#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_AR9462(ah) ? \ +#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + (AR_SREV_9462_20_OR_LATER(ah) ? \ 0x280 : 0x240)) #define AR_PHY_TPC_19_B1 (AR_SM1_BASE + 0x240) #define AR_PHY_TPC_19_B1_ALPHA_THERM 0xff @@ -1048,7 +1048,7 @@ #define AR_GLB_GPIO_CONTROL (AR_GLB_BASE) #define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44) #define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \ - (AR_SREV_9462_20(_ah) ? 0x4c : 0x50)) + (AR_SREV_9462_20_OR_LATER(_ah) ? 0x4c : 0x50)) #define AR_GLB_STATUS (AR_GLB_BASE + 0x48) /* diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 5324c3346af8..4ca0cb060106 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -2599,7 +2599,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) pCap->hw_caps |= ATH9K_HW_CAP_MCI; - if (AR_SREV_9462_20(ah)) + if (AR_SREV_9462_20_OR_LATER(ah)) pCap->hw_caps |= ATH9K_HW_CAP_RTT; } -- GitLab From b28405b0f25c91b52350fd558c219f08e5033eaf Mon Sep 17 00:00:00 2001 From: Alexandre Rames Date: Thu, 21 Mar 2013 16:41:43 +0000 Subject: [PATCH 1790/2900] sfc: Fix EEH with legacy interrupts. PCI legacy interrupts are level-triggered, and we cannot mask them up on an isolated device. Instead, disable the IRQ at the controller until we have recovered. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 7 ++++++- drivers/net/ethernet/sfc/efx.h | 1 + drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/nic.c | 10 ++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 46cc11d5e205..787c9ebc17ee 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "net_driver.h" #include "efx.h" #include "nic.h" @@ -1427,6 +1428,10 @@ static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq) BUG_ON(efx->state == STATE_DISABLED); + if (efx->eeh_disabled_legacy_irq) { + enable_irq(efx->legacy_irq); + efx->eeh_disabled_legacy_irq = false; + } if (efx->legacy_irq) efx->legacy_irq_enabled = true; efx_nic_enable_interrupts(efx); @@ -2365,7 +2370,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) * Returns 0 if the recovery mechanisms are unsuccessful. * Returns a non-zero value otherwise. */ -static int efx_try_recovery(struct efx_nic *efx) +int efx_try_recovery(struct efx_nic *efx) { #ifdef CONFIG_EEH /* A PCI error can occur and not be seen by EEH because nothing diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 8372da239b43..bdb30bbb0c97 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -124,6 +124,7 @@ extern const struct ethtool_ops efx_ethtool_ops; extern int efx_reset(struct efx_nic *efx, enum reset_type method); extern void efx_reset_down(struct efx_nic *efx, enum reset_type method); extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok); +extern int efx_try_recovery(struct efx_nic *efx); /* Global */ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 9a2914cfd345..2dec48bed274 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -788,6 +788,7 @@ struct efx_nic { const struct efx_nic_type *type; int legacy_irq; bool legacy_irq_enabled; + bool eeh_disabled_legacy_irq; struct workqueue_struct *workqueue; char workqueue_name[16]; struct work_struct reset_work; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index b0503cd8c2a0..39432d3d1fe9 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -1579,6 +1579,16 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx_readd(efx, ®, FR_BZ_INT_ISR0); queues = EFX_EXTRACT_DWORD(reg, 0, 31); + /* Legacy interrupts are disabled too late by the EEH kernel + * code. Disable them earlier. + * If an EEH error occurred, the read will have returned all ones. + */ + if (EFX_DWORD_IS_ALL_ONES(reg) && efx_try_recovery(efx) && + !efx->eeh_disabled_legacy_irq) { + disable_irq_nosync(efx->legacy_irq); + efx->eeh_disabled_legacy_irq = true; + } + /* Handle non-event-queue sources */ if (queues & (1U << efx->irq_level)) { syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); -- GitLab From c99dffc4170b23455f9ee9e56baf5f77a68ca4c8 Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Mon, 8 Apr 2013 12:49:48 +0100 Subject: [PATCH 1791/2900] sfc: Enable RX checksum offload for packets not handled by GRO Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/rx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index a7dfe36cabf4..b915e09b8691 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -598,6 +598,8 @@ static void efx_rx_deliver(struct efx_channel *channel, u8 *eh, /* Set the SKB flags */ skb_checksum_none_assert(skb); + if (likely(rx_buf->flags & EFX_RX_PKT_CSUMMED)) + skb->ip_summed = CHECKSUM_UNNECESSARY; if (channel->type->receive_skb) if (channel->type->receive_skb(channel, skb)) -- GitLab From d4ef5b6f374dfbef2c1e00cea73c3b76109f6246 Mon Sep 17 00:00:00 2001 From: Jon Cooper Date: Mon, 8 Apr 2013 12:55:58 +0100 Subject: [PATCH 1792/2900] sfc: Increase size of RX SKB header area This allows the SKB to hold the headers without reallocation more often. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index b915e09b8691..6efff3d030b6 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -36,7 +36,7 @@ #define EFX_RECYCLE_RING_SIZE_NOIOMMU (2 * EFX_RX_PREFERRED_BATCH) /* Size of buffer allocated for skb header area. */ -#define EFX_SKB_HEADERS 64u +#define EFX_SKB_HEADERS 128u /* This is the percentage fill level below which new RX descriptors * will be added to the RX descriptor ring. -- GitLab From 62ebac926b7a5cd7cb6dc02a8d6fa925fa206a23 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 8 Apr 2013 17:34:58 +0100 Subject: [PATCH 1793/2900] sfc: Report software timestamping capabilities The kernel can generate software receive timestamps and we should report those for all ports regardless of hardware capabilities. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/ethtool.c | 16 +++++++++++++++- drivers/net/ethernet/sfc/nic.h | 4 ++-- drivers/net/ethernet/sfc/ptp.c | 13 +++++-------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 6e768175e7e0..1fc21458413d 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -1114,6 +1114,20 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev, return 0; } +int efx_ethtool_get_ts_info(struct net_device *net_dev, + struct ethtool_ts_info *ts_info) +{ + struct efx_nic *efx = netdev_priv(net_dev); + + /* Software capabilities */ + ts_info->so_timestamping = (SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE); + ts_info->phc_index = -1; + + efx_ptp_get_ts_info(efx, ts_info); + return 0; +} + static int efx_ethtool_get_module_eeprom(struct net_device *net_dev, struct ethtool_eeprom *ee, u8 *data) @@ -1176,7 +1190,7 @@ const struct ethtool_ops efx_ethtool_ops = { .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, - .get_ts_info = efx_ptp_get_ts_info, + .get_ts_info = efx_ethtool_get_ts_info, .get_module_info = efx_ethtool_get_module_info, .get_module_eeprom = efx_ethtool_get_module_eeprom, }; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 1b0003323498..d63c2991a751 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -254,8 +254,8 @@ extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, struct ethtool_ts_info; extern void efx_ptp_probe(struct efx_nic *efx); extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd); -extern int efx_ptp_get_ts_info(struct net_device *net_dev, - struct ethtool_ts_info *ts_info); +extern void efx_ptp_get_ts_info(struct efx_nic *efx, + struct ethtool_ts_info *ts_info); extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb); extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 9a95abf2dedf..b495394a6dfa 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1203,18 +1203,16 @@ static int efx_ptp_ts_init(struct efx_nic *efx, struct hwtstamp_config *init) return 0; } -int -efx_ptp_get_ts_info(struct net_device *net_dev, struct ethtool_ts_info *ts_info) +void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info) { - struct efx_nic *efx = netdev_priv(net_dev); struct efx_ptp_data *ptp = efx->ptp_data; if (!ptp) - return -EOPNOTSUPP; + return; - ts_info->so_timestamping = (SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE); + ts_info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE); ts_info->phc_index = ptp_clock_index(ptp->phc_clock); ts_info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON; ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE | @@ -1224,7 +1222,6 @@ efx_ptp_get_ts_info(struct net_device *net_dev, struct ethtool_ts_info *ts_info) 1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT | 1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC | 1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); - return 0; } int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd) -- GitLab From 3ea84c5492e19daa478fad42f97b7dda9289e71c Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Fri, 10 May 2013 16:51:33 -0700 Subject: [PATCH 1794/2900] sfc: Enable accelerated RFS on vlans As far as I know, the hardware doesn't support matching on both IP fields and vlan tag, but it can at least match on the IP fields. Signed-off-by: Andy Lutomirski Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/filter.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c index 2397f0e8d3eb..b74a60ab9ac7 100644 --- a/drivers/net/ethernet/sfc/filter.c +++ b/drivers/net/ethernet/sfc/filter.c @@ -1185,8 +1185,21 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, nhoff = skb_network_offset(skb); - if (skb->protocol != htons(ETH_P_IP)) + if (skb->protocol == htons(ETH_P_8021Q)) { + EFX_BUG_ON_PARANOID(skb_headlen(skb) < + nhoff + sizeof(struct vlan_hdr)); + if (((const struct vlan_hdr *)skb->data + nhoff)-> + h_vlan_encapsulated_proto != htons(ETH_P_IP)) + return -EPROTONOSUPPORT; + + /* This is IP over 802.1q VLAN. We can't filter on the + * IP 5-tuple and the vlan together, so just strip the + * vlan header and filter on the IP part. + */ + nhoff += sizeof(struct vlan_hdr); + } else if (skb->protocol != htons(ETH_P_IP)) { return -EPROTONOSUPPORT; + } /* RFS must validate the IP header length before calling us */ EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip)); -- GitLab From d07df8ec089cc72dded73dac5cf564ef9bba2fa1 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 16 May 2013 18:38:11 +0100 Subject: [PATCH 1795/2900] sfc: Define and set RX buffer flag for packets parsed as TCP This will be useful for shortcutting some software packet parsing. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/net_driver.h | 1 + drivers/net/ethernet/sfc/nic.c | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 2dec48bed274..f4c7e6b67743 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -243,6 +243,7 @@ struct efx_rx_buffer { #define EFX_RX_BUF_LAST_IN_PAGE 0x0001 #define EFX_RX_PKT_CSUMMED 0x0002 #define EFX_RX_PKT_DISCARD 0x0004 +#define EFX_RX_PKT_TCP 0x0040 /** * struct efx_rx_page_state - Page-based rx buffer state diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 39432d3d1fe9..f2b864c14ca9 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -1080,12 +1080,21 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) rx_ev_hdr_type = EFX_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE); if (likely(rx_ev_pkt_ok)) { - /* If packet is marked as OK and packet type is TCP/IP or - * UDP/IP, then we can rely on the hardware checksum. + /* If packet is marked as OK then we can rely on the + * hardware checksum and classification. */ - flags = (rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP || - rx_ev_hdr_type == FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP) ? - EFX_RX_PKT_CSUMMED : 0; + flags = 0; + switch (rx_ev_hdr_type) { + case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP: + flags |= EFX_RX_PKT_TCP; + /* fall through */ + case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP: + flags |= EFX_RX_PKT_CSUMMED; + /* fall through */ + case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER: + case FSE_AZ_RX_EV_HDR_TYPE_OTHER: + break; + } } else { flags = efx_handle_rx_not_ok(rx_queue, event); } -- GitLab From e79255de8581fac7c77dba443d5e79bbc6e72a1f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 16 May 2013 18:38:13 +0100 Subject: [PATCH 1796/2900] sfc: Do not pass non-TCP packets into GRO code GRO can handle non-TCP packets and pass them up without coalescing, but it has to do some extra work to parse the packet which we can bypass using the hardware parse result. (This condition yields a false negative for TCP/IPv6 packets received by Falcon, but its performance is already poor in that case due to lack of checksum offload.) Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 6efff3d030b6..5c45118cc03a 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -629,7 +629,7 @@ void __efx_rx_packet(struct efx_channel *channel) if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) rx_buf->flags &= ~EFX_RX_PKT_CSUMMED; - if (!channel->type->receive_skb) + if ((rx_buf->flags & EFX_RX_PKT_TCP) && !channel->type->receive_skb) efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh); else efx_rx_deliver(channel, eh, rx_buf, channel->rx_pkt_n_frags); -- GitLab From 1899c111a535e43046b14ae13639747d9d2544d6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 22 May 2013 18:03:35 +0100 Subject: [PATCH 1797/2900] sfc: Fix IRQ cleanup in case of a probe failure The lifetime of an irq_cpu_rmap is odd: we have to allocate it before installing IRQ handlers and free it before removing the IRQ handlers. As a result of this asymmetry, it was omitted from some failure paths. On another failure path, we could try to remove IRQ handlers we had not yet installed. Move the irq_cpu_rmap allocation and freeing alongside IRQ handler installation and removal, in efx_nic_{init,fini}_interrupts(). Count the number of IRQ handlers successfully installed and only remove those on the failure path. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 33 ------------------------- drivers/net/ethernet/sfc/nic.c | 45 ++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 787c9ebc17ee..e7284a2caffa 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include "net_driver.h" @@ -1284,29 +1283,6 @@ static unsigned int efx_wanted_parallelism(struct efx_nic *efx) return count; } -static int -efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries) -{ -#ifdef CONFIG_RFS_ACCEL - unsigned int i; - int rc; - - efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels); - if (!efx->net_dev->rx_cpu_rmap) - return -ENOMEM; - for (i = 0; i < efx->n_rx_channels; i++) { - rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap, - xentries[i].vector); - if (rc) { - free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap); - efx->net_dev->rx_cpu_rmap = NULL; - return rc; - } - } -#endif - return 0; -} - /* Probe the number and type of interrupts we are able to obtain, and * the resulting numbers of channels and RX queues. */ @@ -1360,11 +1336,6 @@ static int efx_probe_interrupts(struct efx_nic *efx) efx->n_tx_channels = n_channels; efx->n_rx_channels = n_channels; } - rc = efx_init_rx_cpu_rmap(efx, xentries); - if (rc) { - pci_disable_msix(efx->pci_dev); - return rc; - } for (i = 0; i < efx->n_channels; i++) efx_get_channel(efx, i)->irq = xentries[i].vector; @@ -2608,10 +2579,6 @@ static void efx_pci_remove_main(struct efx_nic *efx) BUG_ON(efx->state == STATE_READY); cancel_work_sync(&efx->reset_work); -#ifdef CONFIG_RFS_ACCEL - free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap); - efx->net_dev->rx_cpu_rmap = NULL; -#endif efx_stop_interrupts(efx, false); efx_nic_fini_interrupt(efx); efx_fini_port(efx); diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index f2b864c14ca9..56ed3bc71e00 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "net_driver.h" #include "bitfield.h" #include "efx.h" @@ -1706,6 +1707,7 @@ void efx_nic_push_rx_indir_table(struct efx_nic *efx) int efx_nic_init_interrupt(struct efx_nic *efx) { struct efx_channel *channel; + unsigned int n_irqs; int rc; if (!EFX_INT_MODE_USE_MSI(efx)) { @@ -1726,7 +1728,19 @@ int efx_nic_init_interrupt(struct efx_nic *efx) return 0; } +#ifdef CONFIG_RFS_ACCEL + if (efx->interrupt_mode == EFX_INT_MODE_MSIX) { + efx->net_dev->rx_cpu_rmap = + alloc_irq_cpu_rmap(efx->n_rx_channels); + if (!efx->net_dev->rx_cpu_rmap) { + rc = -ENOMEM; + goto fail1; + } + } +#endif + /* Hook MSI or MSI-X interrupt */ + n_irqs = 0; efx_for_each_channel(channel, efx) { rc = request_irq(channel->irq, efx_msi_interrupt, IRQF_PROBE_SHARED, /* Not shared */ @@ -1737,13 +1751,31 @@ int efx_nic_init_interrupt(struct efx_nic *efx) "failed to hook IRQ %d\n", channel->irq); goto fail2; } + ++n_irqs; + +#ifdef CONFIG_RFS_ACCEL + if (efx->interrupt_mode == EFX_INT_MODE_MSIX && + channel->channel < efx->n_rx_channels) { + rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap, + channel->irq); + if (rc) + goto fail2; + } +#endif } return 0; fail2: - efx_for_each_channel(channel, efx) +#ifdef CONFIG_RFS_ACCEL + free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap); + efx->net_dev->rx_cpu_rmap = NULL; +#endif + efx_for_each_channel(channel, efx) { + if (n_irqs-- == 0) + break; free_irq(channel->irq, &efx->channel[channel->channel]); + } fail1: return rc; } @@ -1753,11 +1785,14 @@ void efx_nic_fini_interrupt(struct efx_nic *efx) struct efx_channel *channel; efx_oword_t reg; +#ifdef CONFIG_RFS_ACCEL + free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap); + efx->net_dev->rx_cpu_rmap = NULL; +#endif + /* Disable MSI/MSI-X interrupts */ - efx_for_each_channel(channel, efx) { - if (channel->irq) - free_irq(channel->irq, &efx->channel[channel->channel]); - } + efx_for_each_channel(channel, efx) + free_irq(channel->irq, &efx->channel[channel->channel]); /* ACK legacy interrupt */ if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) -- GitLab From 636d73da27e83ce4882f8823f79063bb37980961 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 12 Jun 2013 18:09:08 +0100 Subject: [PATCH 1798/2900] sfc: Improve test for IOMMU in use The device::iommu_group field may be set even if no IOMMU is in use. iommu_present() is still a better indicator, although it doesn't tell us whether *our* device is affected. Reported-by: Alex Williamson Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 5c45118cc03a..65646cd7af8e 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -677,7 +677,7 @@ static void efx_init_rx_recycle_ring(struct efx_nic *efx, #ifdef CONFIG_PPC64 bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU; #else - if (efx->pci_dev->dev.iommu_group) + if (iommu_present(&pci_bus_type)) bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU; else bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_NOIOMMU; -- GitLab From d3c5f47ee2d16497fafaf2f26b0ffeb5c3d4e721 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 24 Jun 2013 12:43:40 -0700 Subject: [PATCH 1799/2900] net: Restore unintentional reverts. This restores commits: c573972c111eb4c6b3f3250ad71e7c75cc799833 1a5904342c7380ceddd61c0b37544d752d0b1433 da2e2c214953f37c2a6be20226537ca5a329724c which initially accidently went into 'net', were reverted there, and then properly placed into 'net-next'. But the next net --> net-next merge accidently wiped them out again. Reported-by: Paul Gortmaker Signed-off-by: David S. Miller --- drivers/net/ethernet/apple/bmac.c | 1 - drivers/net/ethernet/korina.c | 1 - drivers/net/ethernet/sun/sunbmac.c | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c index 714dcfe3a469..a597b766f080 100644 --- a/drivers/net/ethernet/apple/bmac.c +++ b/drivers/net/ethernet/apple/bmac.c @@ -1016,7 +1016,6 @@ static void bmac_set_multicast(struct net_device *dev) static void bmac_set_multicast(struct net_device *dev) { struct netdev_hw_addr *ha; - int i; unsigned short rx_cfg; u32 crc; diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 64646eb39e8b..270e65f21102 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -483,7 +483,6 @@ static void korina_multicast_list(struct net_device *dev) unsigned long flags; struct netdev_hw_addr *ha; u32 recognise = ETH_ARC_AB; /* always accept broadcasts */ - int i; /* Set promiscuous mode */ if (dev->flags & IFF_PROMISC) diff --git a/drivers/net/ethernet/sun/sunbmac.c b/drivers/net/ethernet/sun/sunbmac.c index 09b4f8c0b199..0d43fa9ff980 100644 --- a/drivers/net/ethernet/sun/sunbmac.c +++ b/drivers/net/ethernet/sun/sunbmac.c @@ -995,7 +995,6 @@ static void bigmac_set_multicast(struct net_device *dev) struct bigmac *bp = netdev_priv(dev); void __iomem *bregs = bp->bregs; struct netdev_hw_addr *ha; - int i; u32 tmp, crc; /* Disable the receiver. The bit self-clears when -- GitLab From c94e15c5cb4d02579321382871eb87e17d10858e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 23 Jun 2013 09:07:19 +0800 Subject: [PATCH 1800/2900] RDMA/ocrdma: Fix error return code in ocrdma_set_create_qp_rq_cmd() Fix to return -ENOMEM in the alloc dma coherent error case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ocrdma/ocrdma_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 76c9e192ddcc..0965278dd2ed 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -1886,7 +1886,7 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd, qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL); if (!qp->rq.va) - return status; + return -ENOMEM; memset(qp->rq.va, 0, len); qp->rq.pa = pa; qp->rq.len = len; -- GitLab From 80b15043e3450e730d30b71c099ab00d75a551ce Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 21 Jun 2013 11:24:27 +0800 Subject: [PATCH 1801/2900] IB/core: Fix error return code in add_port() Fix to return -ENOMEM in the add_port() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Roland Dreier --- drivers/infiniband/core/sysfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 246fdc151652..d9b78c4d0aad 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -545,8 +545,10 @@ static int add_port(struct ib_device *device, int port_num, p->gid_group.name = "gids"; p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len); - if (!p->gid_group.attrs) + if (!p->gid_group.attrs) { + ret = -ENOMEM; goto err_remove_pma; + } ret = sysfs_create_group(&p->kobj, &p->gid_group); if (ret) @@ -555,8 +557,10 @@ static int add_port(struct ib_device *device, int port_num, p->pkey_group.name = "pkeys"; p->pkey_group.attrs = alloc_group_attrs(show_port_pkey, attr.pkey_tbl_len); - if (!p->pkey_group.attrs) + if (!p->pkey_group.attrs) { + ret = -ENOMEM; goto err_remove_gid; + } ret = sysfs_create_group(&p->kobj, &p->pkey_group); if (ret) -- GitLab From 77e2af0312b12dccd5043a7cc9cd49ab6a212996 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 21 Jun 2013 19:38:06 +0200 Subject: [PATCH 1802/2900] net: if_arp: add ARPHRD_NETLINK type This small patch adds the definition of ARPHRD_NETLINK which can for example be used by netlink monitoring devices as device type. So that sockaddr_ll can pick it up and based on that choose the correct packet dissector. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/uapi/linux/if_arp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h index 82c7d1bdadeb..d7fea3496f32 100644 --- a/include/uapi/linux/if_arp.h +++ b/include/uapi/linux/if_arp.h @@ -93,6 +93,7 @@ #define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ #define ARPHRD_CAIF 822 /* CAIF media type */ #define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ +#define ARPHRD_NETLINK 824 /* Netlink header */ #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ #define ARPHRD_NONE 0xFFFE /* zero header length */ -- GitLab From bcbde0d449eda7afa8f63280b165c8300dbd00e2 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 21 Jun 2013 19:38:07 +0200 Subject: [PATCH 1803/2900] net: netlink: virtual tap device management Similarly to the networking receive path with ptype_all taps, we add the possibility to register netdevices that are for ARPHRD_NETLINK to the netlink subsystem, so that those can be used for netlink analyzers resp. debuggers. We do not offer a direct callback function as out-of-tree modules could do crap with it. Instead, a netdevice must be registered properly and only receives a clone, managed by the netlink layer. Symbols are exported as GPL-only. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/linux/netlink.h | 10 ++++ net/netlink/af_netlink.c | 107 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f78b430f4af5..86fde81ac2e6 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -145,4 +145,14 @@ static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, return __netlink_dump_start(ssk, skb, nlh, control); } +struct netlink_tap { + struct net_device *dev; + struct module *module; + struct list_head list; +}; + +extern int netlink_add_tap(struct netlink_tap *nt); +extern int __netlink_remove_tap(struct netlink_tap *nt); +extern int netlink_remove_tap(struct netlink_tap *nt); + #endif /* __LINUX_NETLINK_H */ diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 275d901d7e46..6967fbcca6c5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,9 @@ static atomic_t nl_table_users = ATOMIC_INIT(0); static ATOMIC_NOTIFIER_HEAD(netlink_chain); +static DEFINE_SPINLOCK(netlink_tap_lock); +static struct list_head netlink_tap_all __read_mostly; + static inline u32 netlink_group_mask(u32 group) { return group ? 1 << (group - 1) : 0; @@ -111,6 +115,100 @@ static inline struct hlist_head *nl_portid_hashfn(struct nl_portid_hash *hash, u return &hash->table[jhash_1word(portid, hash->rnd) & hash->mask]; } +int netlink_add_tap(struct netlink_tap *nt) +{ + if (unlikely(nt->dev->type != ARPHRD_NETLINK)) + return -EINVAL; + + spin_lock(&netlink_tap_lock); + list_add_rcu(&nt->list, &netlink_tap_all); + spin_unlock(&netlink_tap_lock); + + if (nt->module) + __module_get(nt->module); + + return 0; +} +EXPORT_SYMBOL_GPL(netlink_add_tap); + +int __netlink_remove_tap(struct netlink_tap *nt) +{ + bool found = false; + struct netlink_tap *tmp; + + spin_lock(&netlink_tap_lock); + + list_for_each_entry(tmp, &netlink_tap_all, list) { + if (nt == tmp) { + list_del_rcu(&nt->list); + found = true; + goto out; + } + } + + pr_warn("__netlink_remove_tap: %p not found\n", nt); +out: + spin_unlock(&netlink_tap_lock); + + if (found && nt->module) + module_put(nt->module); + + return found ? 0 : -ENODEV; +} +EXPORT_SYMBOL_GPL(__netlink_remove_tap); + +int netlink_remove_tap(struct netlink_tap *nt) +{ + int ret; + + ret = __netlink_remove_tap(nt); + synchronize_net(); + + return ret; +} +EXPORT_SYMBOL_GPL(netlink_remove_tap); + +static int __netlink_deliver_tap_skb(struct sk_buff *skb, + struct net_device *dev) +{ + struct sk_buff *nskb; + int ret = -ENOMEM; + + dev_hold(dev); + nskb = skb_clone(skb, GFP_ATOMIC); + if (nskb) { + nskb->dev = dev; + ret = dev_queue_xmit(nskb); + if (unlikely(ret > 0)) + ret = net_xmit_errno(ret); + } + + dev_put(dev); + return ret; +} + +static void __netlink_deliver_tap(struct sk_buff *skb) +{ + int ret; + struct netlink_tap *tmp; + + list_for_each_entry_rcu(tmp, &netlink_tap_all, list) { + ret = __netlink_deliver_tap_skb(skb, tmp->dev); + if (unlikely(ret)) + break; + } +} + +static void netlink_deliver_tap(struct sk_buff *skb) +{ + rcu_read_lock(); + + if (unlikely(!list_empty(&netlink_tap_all))) + __netlink_deliver_tap(skb); + + rcu_read_unlock(); +} + static void netlink_overrun(struct sock *sk) { struct netlink_sock *nlk = nlk_sk(sk); @@ -1518,6 +1616,8 @@ static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) { int len = skb->len; + netlink_deliver_tap(skb); + #ifdef CONFIG_NETLINK_MMAP if (netlink_skb_is_mmaped(skb)) netlink_queue_mmaped_skb(sk, skb); @@ -1578,6 +1678,11 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb, ret = -ECONNREFUSED; if (nlk->netlink_rcv != NULL) { + /* We could do a netlink_deliver_tap(skb) here as well + * but since this is intended for the kernel only, we + * should rather let it stay under the hood. + */ + ret = skb->len; netlink_skb_set_owner_r(skb, sk); NETLINK_CB(skb).sk = ssk; @@ -2975,6 +3080,8 @@ static int __init netlink_proto_init(void) nl_table[i].compare = netlink_compare; } + INIT_LIST_HEAD(&netlink_tap_all); + netlink_add_usersock_entry(); sock_register(&netlink_family_ops); -- GitLab From e4fc408e0e99fd2e009c8b3702d9637f5554fd5c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 21 Jun 2013 19:38:08 +0200 Subject: [PATCH 1804/2900] packet: nlmon: virtual netlink monitoring device for packet sockets Currently, there is no good possibility to debug netlink traffic that is being exchanged between kernel and user space. Therefore, this patch implements a netlink virtual device, so that netlink messages will be made visible to PF_PACKET sockets. Once there was an approach with a similar idea [1], but it got forgotten somehow. I think it makes most sense to accept the "overhead" of an extra netlink net device over implementing the same functionality from PF_PACKET sockets once again into netlink sockets. We have BPF filters that can already be easily applied which even have netlink extensions, we have RX_RING zero-copy between kernel- and user space that can be reused, and much more features. So instead of re-implementing all of this, we simply pass the skb to a given PF_PACKET socket for further analysis. Another nice benefit that comes from that is that no code needs to be changed in user space packet analyzers (maybe adding a dissector, but not more), thus out of the box, we can already capture pcap files of netlink traffic to debug/troubleshoot netlink problems. Also thanks goes to Thomas Graf, Flavio Leitner, Jesper Dangaard Brouer. [1] http://marc.info/?l=linux-netdev&m=113813401516110 Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/Kconfig | 10 +++ drivers/net/Makefile | 1 + drivers/net/nlmon.c | 170 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 drivers/net/nlmon.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 00aba08f01a9..b45b240889f5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -240,6 +240,16 @@ config VIRTIO_NET This is the virtual network driver for virtio. It can be used with lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. +config NLMON + tristate "Virtual netlink monitoring device" + ---help--- + This option enables a monitoring net device for netlink skbs. The + purpose of this is to analyze netlink messages with packet sockets. + Thus applications like tcpdump will be able to see local netlink + messages if they tap into the netlink device, record pcaps for further + diagnostics, etc. This is mostly intended for developers or support + to debug netlink issues. If unsure, say N. + endif # NET_CORE config SUNGEM_PHY diff --git a/drivers/net/Makefile b/drivers/net/Makefile index ef3d090efedf..3fef8a81c0f6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_TUN) += tun.o obj-$(CONFIG_VETH) += veth.o obj-$(CONFIG_VIRTIO_NET) += virtio_net.o obj-$(CONFIG_VXLAN) += vxlan.o +obj-$(CONFIG_NLMON) += nlmon.o # # Networking Drivers diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c new file mode 100644 index 000000000000..dc364be6e61e --- /dev/null +++ b/drivers/net/nlmon.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include + +struct pcpu_lstats { + u64 packets; + u64 bytes; + struct u64_stats_sync syncp; +}; + +static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int len = skb->len; + struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats); + + u64_stats_update_begin(&stats->syncp); + stats->bytes += len; + stats->packets++; + u64_stats_update_end(&stats->syncp); + + dev_kfree_skb(skb); + + return NETDEV_TX_OK; +} + +static int nlmon_is_valid_mtu(int new_mtu) +{ + return new_mtu >= sizeof(struct nlmsghdr) && new_mtu <= INT_MAX; +} + +static int nlmon_change_mtu(struct net_device *dev, int new_mtu) +{ + if (!nlmon_is_valid_mtu(new_mtu)) + return -EINVAL; + + dev->mtu = new_mtu; + return 0; +} + +static int nlmon_dev_init(struct net_device *dev) +{ + dev->lstats = alloc_percpu(struct pcpu_lstats); + + return dev->lstats == NULL ? -ENOMEM : 0; +} + +static void nlmon_dev_uninit(struct net_device *dev) +{ + free_percpu(dev->lstats); +} + +static struct netlink_tap nlmon_tap; + +static int nlmon_open(struct net_device *dev) +{ + return netlink_add_tap(&nlmon_tap); +} + +static int nlmon_close(struct net_device *dev) +{ + return netlink_remove_tap(&nlmon_tap); +} + +static struct rtnl_link_stats64 * +nlmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + int i; + u64 bytes = 0, packets = 0; + + for_each_possible_cpu(i) { + const struct pcpu_lstats *nl_stats; + u64 tbytes, tpackets; + unsigned int start; + + nl_stats = per_cpu_ptr(dev->lstats, i); + + do { + start = u64_stats_fetch_begin_bh(&nl_stats->syncp); + tbytes = nl_stats->bytes; + tpackets = nl_stats->packets; + } while (u64_stats_fetch_retry_bh(&nl_stats->syncp, start)); + + packets += tpackets; + bytes += tbytes; + } + + stats->rx_packets = packets; + stats->tx_packets = 0; + + stats->rx_bytes = bytes; + stats->tx_bytes = 0; + + return stats; +} + +static u32 always_on(struct net_device *dev) +{ + return 1; +} + +static const struct ethtool_ops nlmon_ethtool_ops = { + .get_link = always_on, +}; + +static const struct net_device_ops nlmon_ops = { + .ndo_init = nlmon_dev_init, + .ndo_uninit = nlmon_dev_uninit, + .ndo_open = nlmon_open, + .ndo_stop = nlmon_close, + .ndo_start_xmit = nlmon_xmit, + .ndo_get_stats64 = nlmon_get_stats64, + .ndo_change_mtu = nlmon_change_mtu, +}; + +static struct netlink_tap nlmon_tap __read_mostly = { + .module = THIS_MODULE, +}; + +static void nlmon_setup(struct net_device *dev) +{ + dev->type = ARPHRD_NETLINK; + dev->tx_queue_len = 0; + + dev->netdev_ops = &nlmon_ops; + dev->ethtool_ops = &nlmon_ethtool_ops; + dev->destructor = free_netdev; + + dev->features = NETIF_F_FRAGLIST | NETIF_F_HIGHDMA; + dev->flags = IFF_NOARP; + + /* That's rather a softlimit here, which, of course, + * can be altered. Not a real MTU, but what is to be + * expected in most cases. + */ + dev->mtu = NLMSG_GOODSIZE; +} + +static __init int nlmon_register(void) +{ + int err; + struct net_device *nldev; + + nldev = nlmon_tap.dev = alloc_netdev(0, "netlink", nlmon_setup); + if (unlikely(nldev == NULL)) + return -ENOMEM; + + err = register_netdev(nldev); + if (unlikely(err)) + free_netdev(nldev); + + return err; +} + +static __exit void nlmon_unregister(void) +{ + struct net_device *nldev = nlmon_tap.dev; + + unregister_netdev(nldev); +} + +module_init(nlmon_register); +module_exit(nlmon_unregister); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Daniel Borkmann "); +MODULE_AUTHOR("Mathieu Geli "); +MODULE_DESCRIPTION("Netlink monitoring device"); -- GitLab From 05959be7b646e8755a9339ad13e3b87849249f90 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 22 Jun 2013 11:23:58 -0300 Subject: [PATCH 1805/2900] [media] uvc: Depend on VIDEO_V4L2 The uvcvideo driver lost its dependency on VIDEO_V4L2 during the big media directory reorganization. Add it back. Reported-by: Randy Dunlap Signed-off-by: Laurent Pinchart Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/usb/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 541c9f1e4c6a..6ed85efabcaa 100644 --- a/drivers/media/usb/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig @@ -1,5 +1,6 @@ config USB_VIDEO_CLASS tristate "USB Video Class (UVC)" + depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC ---help--- Support for the USB Video Class (UVC). Currently only video -- GitLab From 778de368964c5b7e8100cde9f549992d521e9c89 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 14 Jun 2013 16:07:47 -0700 Subject: [PATCH 1806/2900] iscsi/isert-target: Refactor ISCSI_OP_NOOP RX handling This patch refactors ISCSI_OP_NOOP handling within iscsi-target in order to handle iscsi_nopout payloads in a transport specific manner. This includes splitting existing iscsit_handle_nop_out() into iscsit_setup_nop_out() and iscsit_process_nop_out() calls, and makes iscsit_handle_nop_out() be only used internally by traditional iscsi socket calls. Next update iser-target code to use new callers and add FIXME for the handling iscsi_nopout payloads. Also fix reject response handling in iscsit_setup_nop_out() to use proper iscsit_add_reject_from_cmd(). v2: Fix uninitialized iscsit_handle_nop_out() payload_length usage (Fengguang) v3: Remove left-over dead code in iscsit_setup_nop_out() (DanC) Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 23 +++- drivers/target/iscsi/iscsi_target.c | 174 ++++++++++++------------ include/target/iscsi/iscsi_transport.h | 6 +- 3 files changed, 115 insertions(+), 88 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 41712f096515..c48c9481025c 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1000,6 +1000,25 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn, return 0; } +static int +isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, + struct iser_rx_desc *rx_desc, unsigned char *buf) +{ + struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; + struct iscsi_conn *conn = isert_conn->conn; + struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf; + int rc; + + rc = iscsit_setup_nop_out(conn, cmd, hdr); + if (rc < 0) + return rc; + /* + * FIXME: Add support for NOPOUT payload using unsolicited RDMA payload + */ + + return iscsit_process_nop_out(conn, cmd, hdr); +} + static int isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, uint32_t read_stag, uint64_t read_va, @@ -1032,7 +1051,9 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, if (!cmd) break; - ret = iscsit_handle_nop_out(conn, cmd, (unsigned char *)hdr); + isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd); + ret = isert_handle_nop_out(isert_conn, isert_cmd, + rx_desc, (unsigned char *)hdr); break; case ISCSI_OP_SCSI_DATA_OUT: ret = isert_handle_iscsi_dataout(isert_conn, rx_desc, diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index cc43d4163adc..f684627244bf 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1535,24 +1535,16 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed); } -int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, - unsigned char *buf) +int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct iscsi_nopout *hdr) { - unsigned char *ping_data = NULL; - int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size; - u32 checksum, data_crc, padding = 0, payload_length; - struct iscsi_cmd *cmd_p = NULL; - struct kvec *iov = NULL; - struct iscsi_nopout *hdr; - - hdr = (struct iscsi_nopout *) buf; - payload_length = ntoh24(hdr->dlength); + u32 payload_length = ntoh24(hdr->dlength); if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { pr_err("NOPOUT ITT is reserved, but Immediate Bit is" " not set, protocol error.\n"); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, + 1, 0, (unsigned char *)hdr, cmd); } if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { @@ -1560,8 +1552,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, " greater than MaxXmitDataSegmentLength: %u, protocol" " error.\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, + 1, 0, (unsigned char *)hdr, cmd); } pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," @@ -1577,11 +1569,6 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * can contain ping data. */ if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { - if (!cmd) - return iscsit_add_reject( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); - cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT; cmd->i_state = ISTATE_SEND_NOPIN; cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? @@ -1593,8 +1580,87 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, cmd->data_direction = DMA_NONE; } + return 0; +} +EXPORT_SYMBOL(iscsit_setup_nop_out); + +int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct iscsi_nopout *hdr) +{ + struct iscsi_cmd *cmd_p = NULL; + int cmdsn_ret = 0; + /* + * Initiator is expecting a NopIN ping reply.. + */ + if (hdr->itt != RESERVED_ITT) { + BUG_ON(!cmd); + + spin_lock_bh(&conn->cmd_lock); + list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); + spin_unlock_bh(&conn->cmd_lock); + + iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); + + if (hdr->opcode & ISCSI_OP_IMMEDIATE) { + iscsit_add_cmd_to_response_queue(cmd, conn, + cmd->i_state); + return 0; + } + + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) + return 0; + + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + return iscsit_add_reject_from_cmd( + ISCSI_REASON_PROTOCOL_ERROR, + 1, 0, (unsigned char *)hdr, cmd); + + return 0; + } + /* + * This was a response to a unsolicited NOPIN ping. + */ + if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) { + cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt)); + if (!cmd_p) + return -EINVAL; + + iscsit_stop_nopin_response_timer(conn); + + cmd_p->i_state = ISTATE_REMOVE; + iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state); + + iscsit_start_nopin_timer(conn); + return 0; + } + /* + * Otherwise, initiator is not expecting a NOPIN is response. + * Just ignore for now. + */ + return 0; +} +EXPORT_SYMBOL(iscsit_process_nop_out); + +static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + unsigned char *buf) +{ + unsigned char *ping_data = NULL; + struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf; + struct kvec *iov = NULL; + u32 payload_length = ntoh24(hdr->dlength); + int ret; + + ret = iscsit_setup_nop_out(conn, cmd, hdr); + if (ret < 0) + return ret; + /* + * Handle NOP-OUT payload for traditional iSCSI sockets + */ if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { - rx_size = payload_length; + u32 checksum, data_crc, padding = 0; + int niov = 0, rx_got, rx_size = payload_length; + ping_data = kzalloc(payload_length + 1, GFP_KERNEL); if (!ping_data) { pr_err("Unable to allocate memory for" @@ -1673,76 +1739,14 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, pr_debug("Ping Data: \"%s\"\n", ping_data); } - if (hdr->itt != RESERVED_ITT) { - if (!cmd) { - pr_err("Checking CmdSN for NOPOUT," - " but cmd is NULL!\n"); - return -1; - } - /* - * Initiator is expecting a NopIN ping reply, - */ - spin_lock_bh(&conn->cmd_lock); - list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); - spin_unlock_bh(&conn->cmd_lock); - - iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); - - if (hdr->opcode & ISCSI_OP_IMMEDIATE) { - iscsit_add_cmd_to_response_queue(cmd, conn, - cmd->i_state); - return 0; - } - - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); - if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { - ret = 0; - goto ping_out; - } - if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); - - return 0; - } - - if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) { - /* - * This was a response to a unsolicited NOPIN ping. - */ - cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt)); - if (!cmd_p) - return -1; - - iscsit_stop_nopin_response_timer(conn); - - cmd_p->i_state = ISTATE_REMOVE; - iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state); - iscsit_start_nopin_timer(conn); - } else { - /* - * Initiator is not expecting a NOPIN is response. - * Just ignore for now. - * - * iSCSI v19-91 10.18 - * "A NOP-OUT may also be used to confirm a changed - * ExpStatSN if another PDU will not be available - * for a long time." - */ - ret = 0; - goto out; - } - - return 0; + return iscsit_process_nop_out(conn, cmd, hdr); out: if (cmd) iscsit_free_cmd(cmd, false); -ping_out: + kfree(ping_data); return ret; } -EXPORT_SYMBOL(iscsit_handle_nop_out); int iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index 23a87d0cd72c..ecb53ea6d1c7 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -45,8 +45,10 @@ extern int iscsit_check_dataout_hdr(struct iscsi_conn *, unsigned char *, struct iscsi_cmd **); extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *, bool); -extern int iscsit_handle_nop_out(struct iscsi_conn *, struct iscsi_cmd *, - unsigned char *); +extern int iscsit_setup_nop_out(struct iscsi_conn *, struct iscsi_cmd *, + struct iscsi_nopout *); +extern int iscsit_process_nop_out(struct iscsi_conn *, struct iscsi_cmd *, + struct iscsi_nopout *); extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *); extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *, -- GitLab From 64534aa79496a3bc4f750a695fe9e978ab46e91d Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 14 Jun 2013 16:46:16 -0700 Subject: [PATCH 1807/2900] iscsi-target: Refactor ISCSI_OP_TEXT RX handling This patch refactors ISCSI_OP_TEXT handling within iscsi-target in order to handle iscsi_text payloads in a transport specific manner. This includes splitting current iscsit_handle_text_cmd() into iscsit_setup_text_cmd() and iscsit_process_text_cmd() calls, and makes iscsit_handle_text_cmd be only used internally by traditional iscsi socket calls. Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 158 ++++++++++++++----------- include/target/iscsi/iscsi_transport.h | 4 + 2 files changed, 94 insertions(+), 68 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f684627244bf..ae312c5d8a45 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1960,45 +1960,93 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd); /* #warning FIXME: Support Text Command parameters besides SendTargets */ -static int iscsit_handle_text_cmd( - struct iscsi_conn *conn, - unsigned char *buf) +int +iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct iscsi_text *hdr) { - char *text_ptr, *text_in; - int cmdsn_ret, niov = 0, rx_got, rx_size; - u32 checksum = 0, data_crc = 0, payload_length; - u32 padding = 0, pad_bytes = 0, text_length = 0; - struct iscsi_cmd *cmd; - struct kvec iov[3]; - struct iscsi_text *hdr; - - hdr = (struct iscsi_text *) buf; - payload_length = ntoh24(hdr->dlength); + u32 payload_length = ntoh24(hdr->dlength); if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { pr_err("Unable to accept text parameter length: %u" "greater than MaxXmitDataSegmentLength %u.\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, + 1, 0, (unsigned char *)hdr, cmd); } pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," " ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn, hdr->exp_statsn, payload_length); - rx_size = text_length = payload_length; - if (text_length) { - text_in = kzalloc(text_length, GFP_KERNEL); + cmd->iscsi_opcode = ISCSI_OP_TEXT; + cmd->i_state = ISTATE_SEND_TEXTRSP; + cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); + conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; + cmd->targ_xfer_tag = 0xFFFFFFFF; + cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); + cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); + cmd->data_direction = DMA_NONE; + + return 0; +} +EXPORT_SYMBOL(iscsit_setup_text_cmd); + +int +iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + struct iscsi_text *hdr) +{ + int cmdsn_ret; + + spin_lock_bh(&conn->cmd_lock); + list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); + spin_unlock_bh(&conn->cmd_lock); + + iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); + + if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + return iscsit_add_reject_from_cmd( + ISCSI_REASON_PROTOCOL_ERROR, + 1, 0, (unsigned char *)hdr, cmd); + return 0; + } + + return iscsit_execute_cmd(cmd, 0); +} +EXPORT_SYMBOL(iscsit_process_text_cmd); + +static int +iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + unsigned char *buf) +{ + struct iscsi_text *hdr = (struct iscsi_text *)buf; + char *text_in = NULL; + u32 payload_length = ntoh24(hdr->dlength); + int rx_size, rc; + + rc = iscsit_setup_text_cmd(conn, cmd, hdr); + if (rc < 0) + return rc; + + rx_size = payload_length; + if (payload_length) { + char *text_ptr; + u32 checksum = 0, data_crc = 0; + u32 padding = 0, pad_bytes = 0; + int niov = 0, rx_got; + struct kvec iov[3]; + + text_in = kzalloc(payload_length, GFP_KERNEL); if (!text_in) { pr_err("Unable to allocate memory for" " incoming text parameters\n"); - return -1; + goto reject; } memset(iov, 0, 3 * sizeof(struct kvec)); iov[niov].iov_base = text_in; - iov[niov++].iov_len = text_length; + iov[niov++].iov_len = payload_length; padding = ((-payload_length) & 3); if (padding != 0) { @@ -2015,14 +2063,12 @@ static int iscsit_handle_text_cmd( } rx_got = rx_data(conn, &iov[0], niov, rx_size); - if (rx_got != rx_size) { - kfree(text_in); - return -1; - } + if (rx_got != rx_size) + goto reject; if (conn->conn_ops->DataDigest) { iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, - text_in, text_length, + text_in, payload_length, padding, (u8 *)&pad_bytes, (u8 *)&data_crc); @@ -2034,8 +2080,7 @@ static int iscsit_handle_text_cmd( pr_err("Unable to recover from" " Text Data digest failure while in" " ERL=0.\n"); - kfree(text_in); - return -1; + goto reject; } else { /* * Silently drop this PDU and let the @@ -2050,68 +2095,40 @@ static int iscsit_handle_text_cmd( } else { pr_debug("Got CRC32C DataDigest" " 0x%08x for %u bytes of text data.\n", - checksum, text_length); + checksum, payload_length); } } - text_in[text_length - 1] = '\0'; + text_in[payload_length - 1] = '\0'; pr_debug("Successfully read %d bytes of text" - " data.\n", text_length); + " data.\n", payload_length); if (strncmp("SendTargets", text_in, 11) != 0) { pr_err("Received Text Data that is not" " SendTargets, cannot continue.\n"); - kfree(text_in); - return -1; + goto reject; } text_ptr = strchr(text_in, '='); if (!text_ptr) { pr_err("No \"=\" separator found in Text Data," " cannot continue.\n"); - kfree(text_in); - return -1; + goto reject; } if (strncmp("=All", text_ptr, 4) != 0) { pr_err("Unable to locate All value for" " SendTargets key, cannot continue.\n"); - kfree(text_in); - return -1; + goto reject; } -/*#warning Support SendTargets=(iSCSI Target Name/Nothing) values. */ kfree(text_in); } - cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); - if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); - - cmd->iscsi_opcode = ISCSI_OP_TEXT; - cmd->i_state = ISTATE_SEND_TEXTRSP; - cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); - conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; - cmd->targ_xfer_tag = 0xFFFFFFFF; - cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); - cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); - cmd->data_direction = DMA_NONE; - - spin_lock_bh(&conn->cmd_lock); - list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); - spin_unlock_bh(&conn->cmd_lock); - - iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); + return iscsit_process_text_cmd(conn, cmd, hdr); - if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); - if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); - - return 0; - } - - return iscsit_execute_cmd(cmd, 0); +reject: + kfree(text_in); + return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, + 0, 0, buf, cmd); } +EXPORT_SYMBOL(iscsit_handle_text_cmd); int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn) { @@ -3947,7 +3964,12 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); break; case ISCSI_OP_TEXT: - ret = iscsit_handle_text_cmd(conn, buf); + cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); + if (!cmd) + return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, + 1, buf, conn); + + ret = iscsit_handle_text_cmd(conn, cmd, buf); break; case ISCSI_OP_LOGOUT: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ecb53ea6d1c7..90f3b60d30c4 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -53,6 +53,10 @@ extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *); extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *); +extern int iscsit_setup_text_cmd(struct iscsi_conn *, struct iscsi_cmd *, + struct iscsi_text *); +extern int iscsit_process_text_cmd(struct iscsi_conn *, struct iscsi_cmd *, + struct iscsi_text *); extern void iscsit_build_rsp_pdu(struct iscsi_cmd *, struct iscsi_conn *, bool, struct iscsi_scsi_rsp *); extern void iscsit_build_nopin_rsp(struct iscsi_cmd *, struct iscsi_conn *, -- GitLab From 7ae8639c9d6d5aba7990b4fad3506ff7b4667a45 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 25 Jun 2013 01:21:06 -0700 Subject: [PATCH 1808/2900] tcp: remove invalid __rcu annotation struct tcp_fastopen_context has a field named tfm, which is a pointer to a crypto_cipher structure. It currently has a __rcu annotation, which is not needed at all. tcp_fastopen_ctx is the pointer fetched by rcu_dereference(), but once we have a pointer to current tcp_fastopen_context, we do not use/need rcu_dereference() to access tfm. This fixes a lot of sparse errors like the following : net/ipv4/tcp_fastopen.c:21:31: warning: incorrect type in argument 1 (different address spaces) net/ipv4/tcp_fastopen.c:21:31: expected struct crypto_cipher *tfm net/ipv4/tcp_fastopen.c:21:31: got struct crypto_cipher [noderef] *tfm Signed-off-by: Eric Dumazet Cc: Jerry Chu Signed-off-by: David S. Miller --- include/net/tcp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 6fa80831dc40..d1980054ec75 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1319,9 +1319,9 @@ void tcp_fastopen_cookie_gen(__be32 addr, struct tcp_fastopen_cookie *foc); /* Fastopen key context */ struct tcp_fastopen_context { - struct crypto_cipher __rcu *tfm; - __u8 key[TCP_FASTOPEN_KEY_LENGTH]; - struct rcu_head rcu; + struct crypto_cipher *tfm; + __u8 key[TCP_FASTOPEN_KEY_LENGTH]; + struct rcu_head rcu; }; /* write queue abstraction */ -- GitLab From 6da334ee0c101fc5ecf62f2b1e11b1524be7b159 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 25 Jun 2013 01:30:11 -0700 Subject: [PATCH 1809/2900] ipv6: add include file to suppress sparse warnings commit f88c91ddba95 ("ipv6: statically link register_inet6addr_notifier()" added following sparse warnings : net/ipv6/addrconf_core.c:83:5: warning: symbol 'register_inet6addr_notifier' was not declared. Should it be static? net/ipv6/addrconf_core.c:89:5: warning: symbol 'unregister_inet6addr_notifier' was not declared. Should it be static? net/ipv6/addrconf_core.c:95:5: warning: symbol 'inet6addr_notifier_call_chain' was not declared. Should it be static? Signed-off-by: Eric Dumazet Cc: Cong Wang Signed-off-by: David S. Miller --- net/ipv6/addrconf_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 72104562c864..d2f87427244b 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -5,6 +5,7 @@ #include #include +#include #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) -- GitLab From c957d09ffda417f6c8e3d1f10e2b05228607d6d7 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Tue, 25 Jun 2013 08:50:11 +0300 Subject: [PATCH 1810/2900] bnx2x: Remove sparse and coccinelle warnings This patch solves several sparse issues as well as an unneeded semicolon found via coccinelle. Signed-off-by: Yuval Mintz Signed-off-by: Dmitry Kravkov Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 9 ++++++--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 8 +++++--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index d342c5a34afc..ec3aa1d451e8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1722,7 +1722,7 @@ static int bnx2x_req_irq(struct bnx2x *bp) return request_irq(irq, bnx2x_interrupt, flags, bp->dev->name, bp->dev); } -int bnx2x_setup_irqs(struct bnx2x *bp) +static int bnx2x_setup_irqs(struct bnx2x *bp) { int rc = 0; if (bp->flags & USING_MSIX_FLAG && @@ -3543,9 +3543,12 @@ static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb, /* outer IP header info */ if (xmit_type & XMIT_CSUM_V4) { struct iphdr *iph = ip_hdr(skb); + u16 csum = (__force u16)(~iph->check) - + (__force u16)iph->tot_len - + (__force u16)iph->frag_off; + pbd2->fw_ip_csum_wo_len_flags_frag = - bswab16(csum_fold((~iph->check) - - iph->tot_len - iph->frag_off)); + bswab16(csum_fold((__force __wsum)csum)); } else { pbd2->fw_ip_hdr_to_payload_w = hlen_w - ((sizeof(struct ipv6hdr)) >> 1); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 7c6faebb1838..b8c067d1a0f2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1391,7 +1391,7 @@ static bool bnx2x_is_nvm_accessible(struct bnx2x *bp) bp->pm_cap + PCI_PM_CTRL, &pm); if ((rc && !netif_running(dev)) || - (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != PCI_D0))) + (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != (__force u16)PCI_D0))) return false; return true; @@ -1610,8 +1610,10 @@ static int bnx2x_nvram_write1(struct bnx2x *bp, u32 offset, u8 *data_buf, */ val = be32_to_cpu(val_be); - val &= ~le32_to_cpu(0xff << BYTE_OFFSET(offset)); - val |= le32_to_cpu(*data_buf << BYTE_OFFSET(offset)); + val &= ~le32_to_cpu((__force __le32) + (0xff << BYTE_OFFSET(offset))); + val |= le32_to_cpu((__force __le32) + (*data_buf << BYTE_OFFSET(offset))); rc = bnx2x_nvram_write_dword(bp, align_offset, val, cmd_flags); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 73189888766d..740518bbcb5f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -615,7 +615,7 @@ void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32) if (rc) { BNX2X_ERR("DMAE returned failure %d\n", rc); bnx2x_panic(); - }; + } } static void bnx2x_write_dmae_phys_len(struct bnx2x *bp, dma_addr_t phys_addr, -- GitLab From e715c3a939071bacf33296b0b8dc58a29bbc5cf8 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 18 Jun 2013 05:34:58 +0300 Subject: [PATCH 1811/2900] iwlwifi: mvm: add BT-Coex LUT for 1x1 products 1x1 products will need a special LUT. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-config.h | 1 + drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 0189b9050f22..83b9ff6ff3ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -222,6 +222,7 @@ struct iwl_cfg { const u32 max_inst_size; u8 valid_tx_ant; u8 valid_rx_ant; + bool bt_shared_single_ant; u16 nvm_ver; u16 nvm_calib_ver; /* params not likely to change within a device family */ diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 9a4d94a1f90d..dbd622a3929c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c @@ -202,6 +202,22 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { cpu_to_le32(0x00000000), }; +/* single shared antenna */ +static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = { + cpu_to_le32(0x40000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x44000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x40000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0x44000000), + cpu_to_le32(0x00000000), + cpu_to_le32(0xC0004000), + cpu_to_le32(0xF0005000), + cpu_to_le32(0xC0004000), + cpu_to_le32(0xF0005000), +}; + int iwl_send_bt_init_conf(struct iwl_mvm *mvm) { struct iwl_bt_coex_cmd cmd = { @@ -225,7 +241,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) BT_VALID_REDUCED_TX_POWER | BT_VALID_LUT); - if (is_loose_coex()) + if (mvm->cfg->bt_shared_single_ant) + memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup, + sizeof(iwl_single_shared_ant_lookup)); + else if (is_loose_coex()) memcpy(&cmd.decision_lut, iwl_loose_lookup, sizeof(iwl_tight_lookup)); else -- GitLab From dafe6c4335d042fa6573f40795ccfadc4e4fc7c6 Mon Sep 17 00:00:00 2001 From: eytan lifshitz Date: Tue, 18 Jun 2013 14:28:56 +0300 Subject: [PATCH 1812/2900] iwlwifi: mvm: add thermal throttling debugging Add prints visible to the user when entering and exiting thrermal throttling, because so users can tell that the NIC is getting too hot (and throughput will decrease.) Signed-off-by: eytan lifshitz Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/tt.c | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7d216ddecf42..1c6476eac496 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -352,12 +352,14 @@ struct iwl_tt_params { * @dynamic_smps: Is thermal throttling enabled dynamic_smps? * @tx_backoff: The current thremal throttling tx backoff in uSec. * @params: Parameters to configure the thermal throttling algorithm. + * @throttle: Is thermal throttling is active? */ struct iwl_mvm_tt_mgmt { struct delayed_work ct_kill_exit; bool dynamic_smps; u32 tx_backoff; const struct iwl_tt_params *params; + bool throttle; }; struct iwl_mvm { diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index a7e3b8ddf22b..d6ae7f16ac11 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -427,6 +427,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) const struct iwl_tt_params *params = mvm->thermal_throttle.params; struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; s32 temperature = mvm->temperature; + bool throttle_enable = false; int i; u32 tx_backoff; @@ -445,6 +446,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_tt_smps_iterator, mvm); + throttle_enable = true; } else if (tt->dynamic_smps && temperature <= params->dynamic_smps_exit) { IWL_DEBUG_TEMP(mvm, "Disable dynamic SMPS\n"); @@ -456,10 +458,12 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) } if (params->support_tx_protection) { - if (temperature >= params->tx_protection_entry) + if (temperature >= params->tx_protection_entry) { iwl_mvm_tt_tx_protection(mvm, true); - else if (temperature <= params->tx_protection_exit) + throttle_enable = true; + } else if (temperature <= params->tx_protection_exit) { iwl_mvm_tt_tx_protection(mvm, false); + } } if (params->support_tx_backoff) { @@ -469,9 +473,22 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm) break; tx_backoff = params->tx_backoff[i].backoff; } + if (tx_backoff != 0) + throttle_enable = true; if (tt->tx_backoff != tx_backoff) iwl_mvm_tt_tx_backoff(mvm, tx_backoff); } + + if (!tt->throttle && throttle_enable) { + IWL_WARN(mvm, + "Due to high temperature thermal throttling initiated\n"); + tt->throttle = true; + } else if (tt->throttle && !tt->dynamic_smps && tt->tx_backoff == 0 && + temperature <= params->tx_protection_exit) { + IWL_WARN(mvm, + "Temperature is back to normal thermal throttling stopped\n"); + tt->throttle = false; + } } static const struct iwl_tt_params iwl7000_tt_params = { @@ -502,6 +519,7 @@ void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); tt->params = &iwl7000_tt_params; + tt->throttle = false; INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); } -- GitLab From 3a3cb92e1daf2f2627df0a1f8c9577501663fef3 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 13 Jun 2013 08:30:12 +0300 Subject: [PATCH 1813/2900] iwlwifi: mvm: Change the settings of AP beacon time In case that an AP/GO interface is started while there is a station/P2P client associated, need to make sure that the AP/GO beacon time is far enough from the station's one in oder to allow the station to receive the DTIM beacons and the following traffic etc. To resolve this, when the AP is started, check if there is an active station interface, and guarantee that the AP/GO TBTT is far enough from the station one. Signed-off-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 56 +++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 273b0cc197ab..94aae9c8562c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -865,6 +865,30 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, return ret; } +struct iwl_mvm_mac_ap_iterator_data { + struct iwl_mvm *mvm; + struct ieee80211_vif *vif; + u32 beacon_device_ts; + u16 beacon_int; +}; + +/* Find the beacon_device_ts and beacon_int for a managed interface */ +static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_mac_ap_iterator_data *data = _data; + + if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) + return; + + /* Station client has higher priority over P2P client*/ + if (vif->p2p && data->beacon_device_ts) + return; + + data->beacon_device_ts = vif->bss_conf.sync_device_ts; + data->beacon_int = vif->bss_conf.beacon_int; +} + /* * Fill the specific data for mac context of type AP of P2P GO */ @@ -874,6 +898,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, bool add) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_mac_ap_iterator_data data = { + .mvm = mvm, + .vif = vif, + .beacon_device_ts = 0 + }; ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int); ctxt_ap->bi_reciprocal = @@ -887,16 +916,33 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); /* - * Only read the system time when the MAC is being added, when we + * Only set the beacon time when the MAC is being added, when we * just modify the MAC then we should keep the time -- the firmware * can otherwise have a "jumping" TBTT. */ - if (add) - mvmvif->ap_beacon_time = - iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG); + if (add) { + /* + * If there is a station/P2P client interface which is + * associated, set the AP's TBTT far enough from the station's + * TBTT. Otherwise, set it to the current system time + */ + ieee80211_iterate_active_interfaces_atomic( + mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, + iwl_mvm_mac_ap_iterator, &data); + + if (data.beacon_device_ts) { + u32 rand = (prandom_u32() % (80 - 20)) + 20; + mvmvif->ap_beacon_time = data.beacon_device_ts + + ieee80211_tu_to_usec(data.beacon_int * rand / + 100); + } else { + mvmvif->ap_beacon_time = + iwl_read_prph(mvm->trans, + DEVICE_SYSTEM_TIME_REG); + } + } ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time); - ctxt_ap->beacon_tsf = 0; /* unused */ /* TODO: Assume that the beacon id == mac context id */ -- GitLab From c7df1f4bdaef7e0c860011a0cc979f6c3684b09a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 20 Jun 2013 20:59:34 +0200 Subject: [PATCH 1814/2900] iwlwifi: pcie: rework RX buffer list init and freeing The PCIe code has an array of buffer descriptors (RXBs) that have pages and DMA mappings attached. In regular use, the array isn't used and the buffers are either on the hardware receive queue or the rx_free/rx_used lists for recycling. Occasionally, during module unload, we'd see a warning from this: WARNING: at lib/list_debug.c:32 __list_add+0x91/0xa0() list_add corruption. prev->next should be next (c31c98cc), but was c31c80bc. (prev=c31c80bc). Pid: 519, comm: rmmod Tainted: G W O 3.4.24-dev #3 Call Trace: [] warn_slowpath_common+0x72/0xa0 [] warn_slowpath_fmt+0x33/0x40 [] __list_add+0x91/0xa0 [] iwl_pcie_rxq_free_rbs+0xcc/0xe0 [iwlwifi] [] iwl_pcie_rx_free+0x3f/0x210 [iwlwifi] [] iwl_trans_pcie_free+0x2a/0x90 [iwlwifi] The reason for this seems to be that in iwl_pcie_rxq_free_rbs() we use the array to free all buffers (the hardware receive queue isn't in use any more at this point). The function also adds all buffers to rx_used because it's also used during initialisation (when no freeing happens.) This can cause the warning because it may add entries to the list that are already on it. Luckily, this is harmless because it can only happen when the entire data structure is freed anyway, since during init both lists are initialized from scratch. Disentangle this code and treat init and free separately. During init we just need to put them onto the list after freeing all buffers (for switching between 4k/8k buffers); during free no list manipulations are necessary at all. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/rx.c | 43 ++++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 3688dc5ba1ac..25e25ea1489d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -355,19 +355,16 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) struct iwl_rxq *rxq = &trans_pcie->rxq; int i; - /* Fill the rx_used queue with _all_ of the Rx buffers */ + lockdep_assert_held(&rxq->lock); + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].page != NULL) { - dma_unmap_page(trans->dev, rxq->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, - trans_pcie->rx_page_order); - rxq->pool[i].page = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); + if (!rxq->pool[i].page) + continue; + dma_unmap_page(trans->dev, rxq->pool[i].page_dma, + PAGE_SIZE << trans_pcie->rx_page_order, + DMA_FROM_DEVICE); + __free_pages(rxq->pool[i].page, trans_pcie->rx_page_order); + rxq->pool[i].page = NULL; } } @@ -491,6 +488,20 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } +static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) +{ + int i; + + lockdep_assert_held(&rxq->lock); + + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + rxq->free_count = 0; + + for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) + list_add(&rxq->pool[i].list, &rxq->rx_used); +} + int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -505,13 +516,12 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) } spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - INIT_WORK(&trans_pcie->rx_replenish, - iwl_pcie_rx_replenish_work); + INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work); + /* free all first - we might be reconfigured for a different size */ iwl_pcie_rxq_free_rbs(trans); + iwl_pcie_rx_init_rxb_lists(rxq); for (i = 0; i < RX_QUEUE_SIZE; i++) rxq->queue[i] = NULL; @@ -520,7 +530,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; rxq->write_actual = 0; - rxq->free_count = 0; memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); spin_unlock_irqrestore(&rxq->lock, flags); -- GitLab From fecba09e424e58444a0b206031632d62977b79ec Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 20 Jun 2013 21:56:49 +0200 Subject: [PATCH 1815/2900] iwlwifi: always use 'rxq' as RX queue struct name A few places use just 'q', use 'rxq' there like all other places. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/rx.c | 28 ++++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 25e25ea1489d..fd848cd1583e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -110,9 +110,10 @@ /* * iwl_rxq_space - Return number of free slots available in queue. */ -static int iwl_rxq_space(const struct iwl_rxq *q) +static int iwl_rxq_space(const struct iwl_rxq *rxq) { - int s = q->read - q->write; + int s = rxq->read - rxq->write; + if (s <= 0) s += RX_QUEUE_SIZE; /* keep some buffer to not confuse full and empty queue */ @@ -143,21 +144,22 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) /* * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue */ -static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) +static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, + struct iwl_rxq *rxq) { unsigned long flags; u32 reg; - spin_lock_irqsave(&q->lock, flags); + spin_lock_irqsave(&rxq->lock, flags); - if (q->need_update == 0) + if (rxq->need_update == 0) goto exit_unlock; if (trans->cfg->base_params->shadow_reg_enable) { /* shadow register enabled */ /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); + rxq->write_actual = (rxq->write & ~0x7); + iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); } else { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -175,22 +177,22 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_rxq *q) goto exit_unlock; } - q->write_actual = (q->write & ~0x7); + rxq->write_actual = (rxq->write & ~0x7); iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, - q->write_actual); + rxq->write_actual); /* Else device is assumed to be awake */ } else { /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); + rxq->write_actual = (rxq->write & ~0x7); iwl_write_direct32(trans, FH_RSCSR_CHNL0_WPTR, - q->write_actual); + rxq->write_actual); } } - q->need_update = 0; + rxq->need_update = 0; exit_unlock: - spin_unlock_irqrestore(&q->lock, flags); + spin_unlock_irqrestore(&rxq->lock, flags); } /* -- GitLab From cfb4e624314b657ea5831505a380d932f3313a7a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 20 Jun 2013 22:02:05 +0200 Subject: [PATCH 1816/2900] iwlwifi: always use 'trans_pcie' name A few places use 'pcie_trans' which is a bit non-standard, use 'trans_pcie' there as well. Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/trans.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 197dbe0a868c..826c15602c46 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -838,8 +838,9 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, unsigned long *flags) { int ret; - struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); - spin_lock_irqsave(&pcie_trans->reg_lock, *flags); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + + spin_lock_irqsave(&trans_pcie->reg_lock, *flags); /* this bit wakes up the NIC */ __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, @@ -875,7 +876,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, WARN_ONCE(1, "Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n", val); - spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); + spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); return false; } } @@ -884,22 +885,22 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent, * Fool sparse by faking we release the lock - sparse will * track nic_access anyway. */ - __release(&pcie_trans->reg_lock); + __release(&trans_pcie->reg_lock); return true; } static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, unsigned long *flags) { - struct iwl_trans_pcie *pcie_trans = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - lockdep_assert_held(&pcie_trans->reg_lock); + lockdep_assert_held(&trans_pcie->reg_lock); /* * Fool sparse by faking we acquiring the lock - sparse will * track nic_access anyway. */ - __acquire(&pcie_trans->reg_lock); + __acquire(&trans_pcie->reg_lock); __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); @@ -910,7 +911,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans, * scheduled on different CPUs (after we drop reg_lock). */ mmiowb(); - spin_unlock_irqrestore(&pcie_trans->reg_lock, *flags); + spin_unlock_irqrestore(&trans_pcie->reg_lock, *flags); } static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, -- GitLab From 00cf99ee00c9f1241359c8ee5ca9230318e27a57 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 25 Jun 2013 10:09:57 +0800 Subject: [PATCH 1817/2900] pwm: renesas-tpu: fix return value check in tpu_probe() In case of error, the function devm_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Signed-off-by: Wei Yongjun Reviewed-by: Axel Lin Acked-by: Laurent Pinchart Signed-off-by: Thierry Reding --- drivers/pwm/pwm-renesas-tpu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 96e0cc488a4e..03c1aa3c48a2 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -410,10 +410,8 @@ static int tpu_probe(struct platform_device *pdev) } tpu->base = devm_ioremap_resource(&pdev->dev, res); - if (tpu->base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - return -ENXIO; - } + if (IS_ERR(tpu->base)) + return PTR_ERR(tpu->base); tpu->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tpu->clk)) { -- GitLab From bd4ace2a36e7c87bb5f3eceb54d3b304d395dcf0 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Thu, 21 Mar 2013 17:14:14 +0200 Subject: [PATCH 1818/2900] iwlwifi: mvm: Add support for Low Power RX To improve power consumption in idle associated mode FW may lower RX power. This low linearity mode is acceptable for listening low rate RX such as beacons and groupcast. The driver enables LPRX only if PM is enabled and associated AP's beacon TX rate is 1Mbps or 6Mbps. LPRX RSSI threshold is used to limit a range where LPRX is applied. Signed-off-by: Alexander Bondar Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 24 ++++++++++++++++++- .../net/wireless/iwlwifi/mvm/fw-api-power.h | 5 ++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 ++++ drivers/net/wireless/iwlwifi/mvm/power.c | 22 +++++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 63d19d94b018..e56ed2a84888 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -344,6 +344,13 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, case MVM_DEBUGFS_PM_DISABLE_POWER_OFF: IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val); dbgfs_pm->disable_power_off = val; + case MVM_DEBUGFS_PM_LPRX_ENA: + IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled"); + dbgfs_pm->lprx_ena = val; + break; + case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD: + IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); + dbgfs_pm->lprx_rssi_threshold = val; break; } } @@ -387,6 +394,17 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file, if (sscanf(buf + 18, "%d", &val) != 1) return -EINVAL; param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF; + } else if (!strncmp("lprx=", buf, 5)) { + if (sscanf(buf + 5, "%d", &val) != 1) + return -EINVAL; + param = MVM_DEBUGFS_PM_LPRX_ENA; + } else if (!strncmp("lprx_rssi_threshold=", buf, 20)) { + if (sscanf(buf + 20, "%d", &val) != 1) + return -EINVAL; + if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val < + POWER_LPRX_RSSI_THRESHOLD_MIN) + return -EINVAL; + param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; } else { return -EINVAL; } @@ -421,7 +439,7 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file, le32_to_cpu(cmd.skip_dtim_periods)); pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n", iwlmvm_mod_params.power_scheme); - pos += scnprintf(buf+pos, bufsz-pos, "flags = %d\n", + pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n", le16_to_cpu(cmd.flags)); pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n", cmd.keep_alive_seconds); @@ -435,6 +453,10 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file, le32_to_cpu(cmd.rx_data_timeout)); pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n", le32_to_cpu(cmd.tx_data_timeout)); + if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) + pos += scnprintf(buf+pos, bufsz-pos, + "lprx_rssi_threshold = %d\n", + le32_to_cpu(cmd.lprx_rssi_threshold)); } return simple_read_from_buffer(user_buf, count, ppos, buf, pos); diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index d8e19290b0f3..a6da359a80c3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -66,6 +66,11 @@ /* Power Management Commands, Responses, Notifications */ +/* Radio LP RX Energy Threshold measured in dBm */ +#define POWER_LPRX_RSSI_THRESHOLD 75 +#define POWER_LPRX_RSSI_THRESHOLD_MAX 94 +#define POWER_LPRX_RSSI_THRESHOLD_MIN 30 + /** * enum iwl_scan_flags - masks for power table command flags * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index c6ba553845cd..d40d7db185d6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -158,6 +158,8 @@ enum iwl_dbgfs_pm_mask { MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3), MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4), MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), + MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), + MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), }; struct iwl_dbgfs_pm { @@ -167,6 +169,8 @@ struct iwl_dbgfs_pm { bool skip_over_dtim; u8 skip_dtim_periods; bool disable_power_off; + bool lprx_ena; + u32 lprx_rssi_threshold; int mask; }; diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 3760a33ca3a4..e7ca965a89b8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -137,11 +137,12 @@ static void iwl_mvm_power_log(struct iwl_mvm *mvm, le32_to_cpu(cmd->rx_data_timeout)); IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", le32_to_cpu(cmd->tx_data_timeout)); - IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", - cmd->lprx_rssi_threshold); if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", le32_to_cpu(cmd->skip_dtim_periods)); + if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) + IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", + le32_to_cpu(cmd->lprx_rssi_threshold)); } } @@ -181,6 +182,14 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); + if (vif->bss_conf.beacon_rate && + (vif->bss_conf.beacon_rate->bitrate == 10 || + vif->bss_conf.beacon_rate->bitrate == 60)) { + cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); + cmd->lprx_rssi_threshold = + cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD); + } + dtimper = hw->conf.ps_dtim_period ?: 1; /* Check if radar detection is required on current channel */ @@ -236,6 +245,15 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) cmd->skip_dtim_periods = cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods); + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { + if (mvmvif->dbgfs_pm.lprx_ena) + cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); + else + cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); + } + if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) + cmd->lprx_rssi_threshold = + cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold); #endif /* CONFIG_IWLWIFI_DEBUGFS */ } -- GitLab From 0be0aea2ffa2be1590c86dc226291939bd5535b0 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 25 Jun 2013 10:29:27 +0000 Subject: [PATCH 1819/2900] MIPS: Sibyte: Platform: Add load address for CONFIG_SIBYTE_LITTLESUR Fixes the following build problem: mips-linux-gnu-ld:arch/mips/kernel/vmlinux.lds:253: syntax error because VMLINUX_LOAD_ADDRESS was an empty string for that platform so the vmlinux.lds.S created an invalid section entry on line 50. Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: sibyte-users@bitmover.com Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5548/ Signed-off-by: Ralf Baechle --- arch/mips/sibyte/Platform | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform index d03a07516f83..1bf90dcd49d2 100644 --- a/arch/mips/sibyte/Platform +++ b/arch/mips/sibyte/Platform @@ -41,3 +41,4 @@ load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000 load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000 load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000 load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000 +load-$(CONFIG_SIBYTE_LITTLESUR) := 0xffffffff80100000 -- GitLab From 5bd807659bfd5d5a393b2269dc3e9699dddd9ad6 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 24 Jun 2013 14:42:21 +0000 Subject: [PATCH 1820/2900] MIPS: SNI: pcimt: Guard sni_controller with CONFIG_PCI Fixes the following build problem: arch/mips/sni/pcimt.c:188:30: error: 'sni_controller' defined but not used [-Werror=unused-variable] Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5547/ Signed-off-by: Ralf Baechle --- arch/mips/sni/pcimt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c index cec4b8ca1438..12336c2a649c 100644 --- a/arch/mips/sni/pcimt.c +++ b/arch/mips/sni/pcimt.c @@ -185,6 +185,7 @@ static void __init sni_pcimt_resource_init(void) extern struct pci_ops sni_pcimt_ops; +#ifdef CONFIG_PCI static struct pci_controller sni_controller = { .pci_ops = &sni_pcimt_ops, .mem_resource = &sni_mem_resource, @@ -193,6 +194,7 @@ static struct pci_controller sni_controller = { .io_offset = 0x00000000UL, .io_map_base = SNI_PORT_BASE }; +#endif static void enable_pcimt_irq(struct irq_data *d) { -- GitLab From 6a72015d3c3602dd969e79510486807c481a0e1b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Jun 2013 17:10:28 +0200 Subject: [PATCH 1821/2900] MIPS: SNI: pcit: Fix build error with CONFIG_PCI=n disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC arch/mips/sni/pcit.o arch/mips/sni/pcit.c:150:30: warning: ‘sni_pcit_controller’ defined but not used [-Wunused-variable] Signed-off-by: Ralf Baechle --- arch/mips/sni/pcit.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c index 7cddd03d1fea..05bb51676e82 100644 --- a/arch/mips/sni/pcit.c +++ b/arch/mips/sni/pcit.c @@ -128,13 +128,6 @@ static struct resource pcit_io_resources[] = { } }; -static struct resource sni_mem_resource = { - .start = 0x18000000UL, - .end = 0x1fbfffffUL, - .name = "PCIT PCI MEM", - .flags = IORESOURCE_MEM -}; - static void __init sni_pcit_resource_init(void) { int i; @@ -147,6 +140,14 @@ static void __init sni_pcit_resource_init(void) extern struct pci_ops sni_pcit_ops; +#ifdef CONFIG_PCI +static struct resource sni_mem_resource = { + .start = 0x18000000UL, + .end = 0x1fbfffffUL, + .name = "PCIT PCI MEM", + .flags = IORESOURCE_MEM +}; + static struct pci_controller sni_pcit_controller = { .pci_ops = &sni_pcit_ops, .mem_resource = &sni_mem_resource, @@ -155,6 +156,7 @@ static struct pci_controller sni_pcit_controller = { .io_offset = 0x00000000UL, .io_map_base = SNI_PORT_BASE }; +#endif /* CONFIG_PCI */ static void enable_pcit_irq(struct irq_data *d) { -- GitLab From a3d9086bb121a6459c9ed0452e3c58891a504785 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Fri, 21 Jun 2013 17:48:48 +0000 Subject: [PATCH 1822/2900] MIPS: Flush TLB handlers directly after writing them When having enabled MIPS_PGD_C0_CONTEXT, trap_init() might call the generated tlbmiss_handler_setup_pgd before it was committed to memory, causing boot failures: trap_init() |- per_cpu_trap_init() | |- TLBMISS_HANDLER_SETUP() | |- tlbmiss_handler_setup_pgd() |- flush_tlb_handlers() To avoid this, move flush_tlb_handlers() into build_tlb_refill_handler() right after they were generated. We can do this as the cache handling is initialized just before creating the tlb handlers. This issue was introduced in 3d8bfdd0307223de678962f1c1907a7cec549136 ("MIPS: Use C0_KScratch (if present) to hold PGD pointer."). Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: Jayachandran C Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/5539/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/traps.c | 2 -- arch/mips/mm/tlbex.c | 30 ++++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a75ae40184aa..8ef484c6b9d8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1627,7 +1627,6 @@ void *set_vi_handler(int n, vi_handler_t addr) } extern void tlb_init(void); -extern void flush_tlb_handlers(void); /* * Timer interrupt @@ -1956,7 +1955,6 @@ void __init trap_init(void) set_handler(0x080, &except_vec3_generic, 0x80); local_flush_icache_range(ebase, ebase + 0x400); - flush_tlb_handlers(); sort_extable(__start___dbe_table, __stop___dbe_table); diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index f0f4dc44f394..7f6cd461dac5 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2181,6 +2181,20 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); } +static void __cpuinit flush_tlb_handlers(void) +{ + local_flush_icache_range((unsigned long)handle_tlbl, + (unsigned long)handle_tlbl + sizeof(handle_tlbl)); + local_flush_icache_range((unsigned long)handle_tlbs, + (unsigned long)handle_tlbs + sizeof(handle_tlbs)); + local_flush_icache_range((unsigned long)handle_tlbm, + (unsigned long)handle_tlbm + sizeof(handle_tlbm)); +#ifdef CONFIG_MIPS_PGD_C0_CONTEXT + local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, + (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); +#endif +} + void __cpuinit build_tlb_refill_handler(void) { /* @@ -2213,6 +2227,7 @@ void __cpuinit build_tlb_refill_handler(void) build_r3000_tlb_load_handler(); build_r3000_tlb_store_handler(); build_r3000_tlb_modify_handler(); + flush_tlb_handlers(); run_once++; } #else @@ -2240,23 +2255,10 @@ void __cpuinit build_tlb_refill_handler(void) build_r4000_tlb_modify_handler(); if (!cpu_has_local_ebase) build_r4000_tlb_refill_handler(); + flush_tlb_handlers(); run_once++; } if (cpu_has_local_ebase) build_r4000_tlb_refill_handler(); } } - -void __cpuinit flush_tlb_handlers(void) -{ - local_flush_icache_range((unsigned long)handle_tlbl, - (unsigned long)handle_tlbl + sizeof(handle_tlbl)); - local_flush_icache_range((unsigned long)handle_tlbs, - (unsigned long)handle_tlbs + sizeof(handle_tlbs)); - local_flush_icache_range((unsigned long)handle_tlbm, - (unsigned long)handle_tlbm + sizeof(handle_tlbm)); -#ifdef CONFIG_MIPS_PGD_C0_CONTEXT - local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, - (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); -#endif -} -- GitLab From 60d9d4c6dbd1bad80fb9a77775fc704302a563c9 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 20 Jun 2013 00:26:31 -0700 Subject: [PATCH 1823/2900] vxlan: Fix sparse warnings. Fix following sparse warnings. drivers/net/vxlan.c:238:44: warning: incorrect type in argument 3 (different base types) drivers/net/vxlan.c:238:44: expected restricted __be32 [usertype] value drivers/net/vxlan.c:238:44: got unsigned int const [unsigned] [usertype] remote_vni drivers/net/vxlan.c:1735:18: warning: incorrect type in initializer (different signedness) drivers/net/vxlan.c:1735:18: expected int *id drivers/net/vxlan.c:1735:18: got unsigned int static [toplevel] * Signed-off-by: Pravin B Shelar Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 3b03cd4bdf37..212a25601fa6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -78,7 +78,7 @@ static bool log_ecn_error = true; module_param(log_ecn_error, bool, 0644); MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); -static unsigned int vxlan_net_id; +static int vxlan_net_id; /* per UDP socket information */ struct vxlan_sock { @@ -250,7 +250,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, nla_put_be16(skb, NDA_PORT, rdst->remote_port)) goto nla_put_failure; if (rdst->remote_vni != vxlan->default_dst.remote_vni && - nla_put_be32(skb, NDA_VNI, rdst->remote_vni)) + nla_put_u32(skb, NDA_VNI, rdst->remote_vni)) goto nla_put_failure; if (rdst->remote_ifindex && nla_put_u32(skb, NDA_IFINDEX, rdst->remote_ifindex)) -- GitLab From afbd8bae9c798c5cdbe4439d3a50536b5438247c Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:51 +0300 Subject: [PATCH 1824/2900] vxlan: add implicit fdb entry for default destination Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 68 ++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 212a25601fa6..bdfe46e50c49 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -80,6 +80,8 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); static int vxlan_net_id; +static const u8 all_zeros_mac[ETH_ALEN]; + /* per UDP socket information */ struct vxlan_sock { struct hlist_node hlist; @@ -1151,7 +1153,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) struct vxlan_dev *vxlan = netdev_priv(dev); struct ethhdr *eth; bool did_rsc = false; - struct vxlan_rdst *rdst0, *rdst; + struct vxlan_rdst *rdst; struct vxlan_fdb *f; skb_reset_mac_header(skb); @@ -1171,26 +1173,27 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) } if (f == NULL) { - rdst0 = &vxlan->default_dst; - - if (rdst0->remote_ip == htonl(INADDR_ANY) && - (vxlan->flags & VXLAN_F_L2MISS) && - !is_multicast_ether_addr(eth->h_dest)) - vxlan_fdb_miss(vxlan, eth->h_dest); - } else { - rdst = rdst0 = first_remote(f); + f = vxlan_find_mac(vxlan, all_zeros_mac); + if (f == NULL) { + if ((vxlan->flags & VXLAN_F_L2MISS) && + !is_multicast_ether_addr(eth->h_dest)) + vxlan_fdb_miss(vxlan, eth->h_dest); + + dev->stats.tx_dropped++; + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + } - /* if there are multiple destinations, send copies */ - list_for_each_entry_continue_rcu(rdst, &f->remotes, list) { - struct sk_buff *skb1; + list_for_each_entry_rcu(rdst, &f->remotes, list) { + struct sk_buff *skb1; - skb1 = skb_clone(skb, GFP_ATOMIC); - if (skb1) - vxlan_xmit_one(skb1, dev, rdst, did_rsc); - } + skb1 = skb_clone(skb, GFP_ATOMIC); + if (skb1) + vxlan_xmit_one(skb1, dev, rdst, did_rsc); } - vxlan_xmit_one(skb, dev, rdst0, did_rsc); + dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -1260,12 +1263,25 @@ static int vxlan_init(struct net_device *dev) return 0; } +static void vxlan_fdb_delete_defualt(struct vxlan_dev *vxlan) +{ + struct vxlan_fdb *f; + + spin_lock_bh(&vxlan->hash_lock); + f = __vxlan_find_mac(vxlan, all_zeros_mac); + if (f) + vxlan_fdb_destroy(vxlan, f); + spin_unlock_bh(&vxlan->hash_lock); +} + static void vxlan_uninit(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; + vxlan_fdb_delete_defualt(vxlan); + if (vs) vxlan_sock_release(vn, vs); free_percpu(dev->tstats); @@ -1304,7 +1320,9 @@ static void vxlan_flush(struct vxlan_dev *vxlan) hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); - vxlan_fdb_destroy(vxlan, f); + /* the all_zeros_mac entry is deleted at vxlan_uninit */ + if (!is_zero_ether_addr(f->eth_addr)) + vxlan_fdb_destroy(vxlan, f); } } spin_unlock_bh(&vxlan->hash_lock); @@ -1657,10 +1675,22 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); - err = register_netdevice(dev); + /* create an fdb entry for default destination */ + err = vxlan_fdb_create(vxlan, all_zeros_mac, + vxlan->default_dst.remote_ip, + NUD_REACHABLE|NUD_PERMANENT, + NLM_F_EXCL|NLM_F_CREATE, + vxlan->dst_port, vxlan->default_dst.remote_vni, + vxlan->default_dst.remote_ifindex, NTF_SELF); if (err) return err; + err = register_netdevice(dev); + if (err) { + vxlan_fdb_delete_defualt(vxlan); + return err; + } + list_add(&vxlan->next, &vn->vxlan_list); return 0; -- GitLab From a5e7c10a7ec244f272703f36f339c967efe1fc0d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:52 +0300 Subject: [PATCH 1825/2900] vxlan: introduce vxlan_fdb_find_rdst which will be reused by vxlan_fdb_delete Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index bdfe46e50c49..306bd94efa89 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -388,21 +388,34 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, return f; } -/* Add/update destinations for multicast */ -static int vxlan_fdb_append(struct vxlan_fdb *f, - __be32 ip, __be16 port, __u32 vni, __u32 ifindex) +/* caller should hold vxlan->hash_lock */ +static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f, + __be32 ip, __be16 port, + __u32 vni, __u32 ifindex) { struct vxlan_rdst *rd; - /* protected by vxlan->hash_lock */ list_for_each_entry(rd, &f->remotes, list) { if (rd->remote_ip == ip && rd->remote_port == port && rd->remote_vni == vni && rd->remote_ifindex == ifindex) - return 0; + return rd; } + return NULL; +} + +/* Add/update destinations for multicast */ +static int vxlan_fdb_append(struct vxlan_fdb *f, + __be32 ip, __be16 port, __u32 vni, __u32 ifindex) +{ + struct vxlan_rdst *rd; + + rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); + if (rd) + return 0; + rd = kmalloc(sizeof(*rd), GFP_ATOMIC); if (rd == NULL) return -ENOBUFS; -- GitLab From f0b074be7b61a800e39053d73dabf850649c1c8f Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:53 +0300 Subject: [PATCH 1826/2900] vxlan: introduce vxlan_fdb_parse which will be reused by vxlan_fdb_delete Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 81 ++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 306bd94efa89..ee7cc71e57fd 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -518,58 +518,77 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) call_rcu(&f->rcu, vxlan_fdb_free); } -/* Add static entry (via netlink) */ -static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], - struct net_device *dev, - const unsigned char *addr, u16 flags) +static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan, + __be32 *ip, __be16 *port, u32 *vni, u32 *ifindex) { - struct vxlan_dev *vxlan = netdev_priv(dev); struct net *net = dev_net(vxlan->dev); - __be32 ip; - __be16 port; - u32 vni, ifindex; - int err; - - if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { - pr_info("RTM_NEWNEIGH with invalid state %#x\n", - ndm->ndm_state); - return -EINVAL; - } - - if (tb[NDA_DST] == NULL) - return -EINVAL; - if (nla_len(tb[NDA_DST]) != sizeof(__be32)) - return -EAFNOSUPPORT; + if (tb[NDA_DST]) { + if (nla_len(tb[NDA_DST]) != sizeof(__be32)) + return -EAFNOSUPPORT; - ip = nla_get_be32(tb[NDA_DST]); + *ip = nla_get_be32(tb[NDA_DST]); + } else { + *ip = htonl(INADDR_ANY); + } if (tb[NDA_PORT]) { if (nla_len(tb[NDA_PORT]) != sizeof(__be16)) return -EINVAL; - port = nla_get_be16(tb[NDA_PORT]); - } else - port = vxlan->dst_port; + *port = nla_get_be16(tb[NDA_PORT]); + } else { + *port = vxlan->dst_port; + } if (tb[NDA_VNI]) { if (nla_len(tb[NDA_VNI]) != sizeof(u32)) return -EINVAL; - vni = nla_get_u32(tb[NDA_VNI]); - } else - vni = vxlan->default_dst.remote_vni; + *vni = nla_get_u32(tb[NDA_VNI]); + } else { + *vni = vxlan->default_dst.remote_vni; + } if (tb[NDA_IFINDEX]) { struct net_device *tdev; if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) return -EINVAL; - ifindex = nla_get_u32(tb[NDA_IFINDEX]); - tdev = dev_get_by_index(net, ifindex); + *ifindex = nla_get_u32(tb[NDA_IFINDEX]); + tdev = dev_get_by_index(net, *ifindex); if (!tdev) return -EADDRNOTAVAIL; dev_put(tdev); - } else - ifindex = 0; + } else { + *ifindex = 0; + } + + return 0; +} + +/* Add static entry (via netlink) */ +static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 flags) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + /* struct net *net = dev_net(vxlan->dev); */ + __be32 ip; + __be16 port; + u32 vni, ifindex; + int err; + + if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { + pr_info("RTM_NEWNEIGH with invalid state %#x\n", + ndm->ndm_state); + return -EINVAL; + } + + if (tb[NDA_DST] == NULL) + return -EINVAL; + + err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); + if (err) + return err; spin_lock_bh(&vxlan->hash_lock); err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags, -- GitLab From bc7892ba39992c6d645e906f1d52a626395b4b11 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:54 +0300 Subject: [PATCH 1827/2900] vxlan: allow removal of single destination from fdb entry When the last item is deleted from the remote destinations list, the fdb entry is destroyed. Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ee7cc71e57fd..c1825201f9e2 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -105,6 +105,7 @@ struct vxlan_rdst { u32 remote_vni; u32 remote_ifindex; struct list_head list; + struct rcu_head rcu; }; /* Forwarding table entry */ @@ -496,6 +497,12 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, return 0; } +static void vxlan_fdb_free_rdst(struct rcu_head *head) +{ + struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); + kfree(rd); +} + static void vxlan_fdb_free(struct rcu_head *head) { struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); @@ -605,14 +612,43 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb *f; - int err = -ENOENT; + struct vxlan_rdst *rd = NULL; + __be32 ip; + __be16 port; + u32 vni, ifindex; + int err; + + err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); + if (err) + return err; + + err = -ENOENT; spin_lock_bh(&vxlan->hash_lock); f = vxlan_find_mac(vxlan, addr); - if (f) { - vxlan_fdb_destroy(vxlan, f); - err = 0; + if (!f) + goto out; + + if (ip != htonl(INADDR_ANY)) { + rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); + if (!rd) + goto out; + } + + err = 0; + + /* remove a destination if it's not the only one on the list, + * otherwise destroy the fdb entry + */ + if (rd && !list_is_singular(&f->remotes)) { + list_del_rcu(&rd->list); + call_rcu(&rd->rcu, vxlan_fdb_free_rdst); + goto out; } + + vxlan_fdb_destroy(vxlan, f); + +out: spin_unlock_bh(&vxlan->hash_lock); return err; -- GitLab From f693dff7107063f0ce08502052b78c4d4feb0e87 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:55 +0300 Subject: [PATCH 1828/2900] rtnetlink: allow using zero MAC address in rtnl_fdb_{add,del} This is required for multiple default destinations management in VXLAN Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- net/core/rtnetlink.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9007533867f0..3de740834d1f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2109,10 +2109,6 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) } addr = nla_data(tb[NDA_LLADDR]); - if (is_zero_ether_addr(addr)) { - pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ether address\n"); - return -EINVAL; - } err = -EOPNOTSUPP; @@ -2210,10 +2206,6 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh) } addr = nla_data(tb[NDA_LLADDR]); - if (is_zero_ether_addr(addr)) { - pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ether address\n"); - return -EINVAL; - } err = -EOPNOTSUPP; -- GitLab From 58e4c767046a35f11a55af6ce946054ddf4a8580 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Tue, 25 Jun 2013 16:01:56 +0300 Subject: [PATCH 1829/2900] vxlan: fdb: allow specifying multiple destinations for zero MAC The zero MAC entry in the fdb is used as default destination. With multiple default destinations it is possible to use vxlan in environments that disable multicast on the infrastructure level, e.g. public clouds. Signed-off-by: Mike Rapoport Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index c1825201f9e2..3e75f9726c33 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -458,7 +458,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, notify = 1; } if ((flags & NLM_F_APPEND) && - is_multicast_ether_addr(f->eth_addr)) { + (is_multicast_ether_addr(f->eth_addr) || + is_zero_ether_addr(f->eth_addr))) { int rc = vxlan_fdb_append(f, ip, port, vni, ifindex); if (rc < 0) -- GitLab From 98c33c5a971bbca31160e5e4a362496c4d702357 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 24 Jun 2013 18:31:24 +0100 Subject: [PATCH 1830/2900] documentation/iommu: Add description of ARM System MMU binding This patch adds a description of the device tree binding for the ARM System MMU architecture. Cc: Rob Herring Cc: Andreas Herrmann Cc: Joerg Roedel Acked-by: Grant Likely Signed-off-by: Will Deacon Acked-by: Andreas Herrmann Signed-off-by: Joerg Roedel --- .../devicetree/bindings/iommu/arm,smmu.txt | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Documentation/devicetree/bindings/iommu/arm,smmu.txt diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt new file mode 100644 index 000000000000..e34c6cdd8ba8 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt @@ -0,0 +1,70 @@ +* ARM System MMU Architecture Implementation + +ARM SoCs may contain an implementation of the ARM System Memory +Management Unit Architecture, which can be used to provide 1 or 2 stages +of address translation to bus masters external to the CPU. + +The SMMU may also raise interrupts in response to various fault +conditions. + +** System MMU required properties: + +- compatible : Should be one of: + + "arm,smmu-v1" + "arm,smmu-v2" + "arm,mmu-400" + "arm,mmu-500" + + depending on the particular implementation and/or the + version of the architecture implemented. + +- reg : Base address and size of the SMMU. + +- #global-interrupts : The number of global interrupts exposed by the + device. + +- interrupts : Interrupt list, with the first #global-irqs entries + corresponding to the global interrupts and any + following entries corresponding to context interrupts, + specified in order of their indexing by the SMMU. + + For SMMUv2 implementations, there must be exactly one + interrupt per context bank. In the case of a single, + combined interrupt, it must be listed multiple times. + +- mmu-masters : A list of phandles to device nodes representing bus + masters for which the SMMU can provide a translation + and their corresponding StreamIDs (see example below). + Each device node linked from this list must have a + "#stream-id-cells" property, indicating the number of + StreamIDs associated with it. + +** System MMU optional properties: + +- smmu-parent : When multiple SMMUs are chained together, this + property can be used to provide a phandle to the + parent SMMU (that is the next SMMU on the path going + from the mmu-masters towards memory) node for this + SMMU. + +Example: + + smmu { + compatible = "arm,smmu-v1"; + reg = <0xba5e0000 0x10000>; + #global-interrupts = <2>; + interrupts = <0 32 4>, + <0 33 4>, + <0 34 4>, /* This is the first context interrupt */ + <0 35 4>, + <0 36 4>, + <0 37 4>; + + /* + * Two DMA controllers, the first with two StreamIDs (0xd01d + * and 0xd01e) and the second with only one (0xd11c). + */ + mmu-masters = <&dma0 0xd01d 0xd01e>, + <&dma1 0xd11c>; + }; -- GitLab From 45ae7cff3684ab45f57fc13fc242c8546536a84e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 24 Jun 2013 18:31:25 +0100 Subject: [PATCH 1831/2900] iommu/arm: Add support for ARM Ltd. System MMU architecture This patch adds support for SMMUs implementing the ARM System MMU architecture versions 1 or 2. Both arm and arm64 are supported, although the v7s descriptor format is not used. Cc: Rob Herring Cc: Andreas Herrmann Cc: Olav Haugan Cc: Joerg Roedel Signed-off-by: Will Deacon Acked-by: Andreas Herrmann Signed-off-by: Joerg Roedel --- drivers/iommu/Kconfig | 13 + drivers/iommu/Makefile | 1 + drivers/iommu/arm-smmu.c | 1969 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 1983 insertions(+) create mode 100644 drivers/iommu/arm-smmu.c diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index c332fb98480d..957cfd4f8065 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -261,4 +261,17 @@ config SHMOBILE_IOMMU_L1SIZE default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB +config ARM_SMMU + bool "ARM Ltd. System MMU (SMMU) Support" + depends on ARM64 || (ARM_LPAE && OF) + select IOMMU_API + select ARM_DMA_USE_IOMMU if ARM + help + Support for implementations of the ARM System MMU architecture + versions 1 and 2. The driver supports both v7l and v8l table + formats with 4k and 64k page sizes. + + Say Y here if your SoC includes an IOMMU device implementing + the ARM SMMU architecture. + endif # IOMMU_SUPPORT diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index ef0e5207ad69..bbe7041212dd 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_OF_IOMMU) += of_iommu.o obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o +obj-$(CONFIG_ARM_SMMU) += arm-smmu.o obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c new file mode 100644 index 000000000000..ebd0a4cff049 --- /dev/null +++ b/drivers/iommu/arm-smmu.c @@ -0,0 +1,1969 @@ +/* + * IOMMU API for ARM architected SMMU implementations. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2013 ARM Limited + * + * Author: Will Deacon + * + * This driver currently supports: + * - SMMUv1 and v2 implementations + * - Stream-matching and stream-indexing + * - v7/v8 long-descriptor format + * - Non-secure access to the SMMU + * - 4k and 64k pages, with contiguous pte hints. + * - Up to 39-bit addressing + * - Context fault reporting + */ + +#define pr_fmt(fmt) "arm-smmu: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* Maximum number of stream IDs assigned to a single device */ +#define MAX_MASTER_STREAMIDS 8 + +/* Maximum number of context banks per SMMU */ +#define ARM_SMMU_MAX_CBS 128 + +/* Maximum number of mapping groups per SMMU */ +#define ARM_SMMU_MAX_SMRS 128 + +/* Number of VMIDs per SMMU */ +#define ARM_SMMU_NUM_VMIDS 256 + +/* SMMU global address space */ +#define ARM_SMMU_GR0(smmu) ((smmu)->base) +#define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) + +/* Page table bits */ +#define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) +#define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) +#define ARM_SMMU_PTE_AF (((pteval_t)1) << 10) +#define ARM_SMMU_PTE_SH_NS (((pteval_t)0) << 8) +#define ARM_SMMU_PTE_SH_OS (((pteval_t)2) << 8) +#define ARM_SMMU_PTE_SH_IS (((pteval_t)3) << 8) + +#if PAGE_SIZE == SZ_4K +#define ARM_SMMU_PTE_CONT_ENTRIES 16 +#elif PAGE_SIZE == SZ_64K +#define ARM_SMMU_PTE_CONT_ENTRIES 32 +#else +#define ARM_SMMU_PTE_CONT_ENTRIES 1 +#endif + +#define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES) +#define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1)) +#define ARM_SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t)) + +/* Stage-1 PTE */ +#define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6) +#define ARM_SMMU_PTE_AP_RDONLY (((pteval_t)2) << 6) +#define ARM_SMMU_PTE_ATTRINDX_SHIFT 2 + +/* Stage-2 PTE */ +#define ARM_SMMU_PTE_HAP_FAULT (((pteval_t)0) << 6) +#define ARM_SMMU_PTE_HAP_READ (((pteval_t)1) << 6) +#define ARM_SMMU_PTE_HAP_WRITE (((pteval_t)2) << 6) +#define ARM_SMMU_PTE_MEMATTR_OIWB (((pteval_t)0xf) << 2) +#define ARM_SMMU_PTE_MEMATTR_NC (((pteval_t)0x5) << 2) +#define ARM_SMMU_PTE_MEMATTR_DEV (((pteval_t)0x1) << 2) + +/* Configuration registers */ +#define ARM_SMMU_GR0_sCR0 0x0 +#define sCR0_CLIENTPD (1 << 0) +#define sCR0_GFRE (1 << 1) +#define sCR0_GFIE (1 << 2) +#define sCR0_GCFGFRE (1 << 4) +#define sCR0_GCFGFIE (1 << 5) +#define sCR0_USFCFG (1 << 10) +#define sCR0_VMIDPNE (1 << 11) +#define sCR0_PTM (1 << 12) +#define sCR0_FB (1 << 13) +#define sCR0_BSU_SHIFT 14 +#define sCR0_BSU_MASK 0x3 + +/* Identification registers */ +#define ARM_SMMU_GR0_ID0 0x20 +#define ARM_SMMU_GR0_ID1 0x24 +#define ARM_SMMU_GR0_ID2 0x28 +#define ARM_SMMU_GR0_ID3 0x2c +#define ARM_SMMU_GR0_ID4 0x30 +#define ARM_SMMU_GR0_ID5 0x34 +#define ARM_SMMU_GR0_ID6 0x38 +#define ARM_SMMU_GR0_ID7 0x3c +#define ARM_SMMU_GR0_sGFSR 0x48 +#define ARM_SMMU_GR0_sGFSYNR0 0x50 +#define ARM_SMMU_GR0_sGFSYNR1 0x54 +#define ARM_SMMU_GR0_sGFSYNR2 0x58 +#define ARM_SMMU_GR0_PIDR0 0xfe0 +#define ARM_SMMU_GR0_PIDR1 0xfe4 +#define ARM_SMMU_GR0_PIDR2 0xfe8 + +#define ID0_S1TS (1 << 30) +#define ID0_S2TS (1 << 29) +#define ID0_NTS (1 << 28) +#define ID0_SMS (1 << 27) +#define ID0_PTFS_SHIFT 24 +#define ID0_PTFS_MASK 0x2 +#define ID0_PTFS_V8_ONLY 0x2 +#define ID0_CTTW (1 << 14) +#define ID0_NUMIRPT_SHIFT 16 +#define ID0_NUMIRPT_MASK 0xff +#define ID0_NUMSMRG_SHIFT 0 +#define ID0_NUMSMRG_MASK 0xff + +#define ID1_PAGESIZE (1 << 31) +#define ID1_NUMPAGENDXB_SHIFT 28 +#define ID1_NUMPAGENDXB_MASK 7 +#define ID1_NUMS2CB_SHIFT 16 +#define ID1_NUMS2CB_MASK 0xff +#define ID1_NUMCB_SHIFT 0 +#define ID1_NUMCB_MASK 0xff + +#define ID2_OAS_SHIFT 4 +#define ID2_OAS_MASK 0xf +#define ID2_IAS_SHIFT 0 +#define ID2_IAS_MASK 0xf +#define ID2_UBS_SHIFT 8 +#define ID2_UBS_MASK 0xf +#define ID2_PTFS_4K (1 << 12) +#define ID2_PTFS_16K (1 << 13) +#define ID2_PTFS_64K (1 << 14) + +#define PIDR2_ARCH_SHIFT 4 +#define PIDR2_ARCH_MASK 0xf + +/* Global TLB invalidation */ +#define ARM_SMMU_GR0_STLBIALL 0x60 +#define ARM_SMMU_GR0_TLBIVMID 0x64 +#define ARM_SMMU_GR0_TLBIALLNSNH 0x68 +#define ARM_SMMU_GR0_TLBIALLH 0x6c +#define ARM_SMMU_GR0_sTLBGSYNC 0x70 +#define ARM_SMMU_GR0_sTLBGSTATUS 0x74 +#define sTLBGSTATUS_GSACTIVE (1 << 0) +#define TLB_LOOP_TIMEOUT 1000000 /* 1s! */ + +/* Stream mapping registers */ +#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) +#define SMR_VALID (1 << 31) +#define SMR_MASK_SHIFT 16 +#define SMR_MASK_MASK 0x7fff +#define SMR_ID_SHIFT 0 +#define SMR_ID_MASK 0x7fff + +#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) +#define S2CR_CBNDX_SHIFT 0 +#define S2CR_CBNDX_MASK 0xff +#define S2CR_TYPE_SHIFT 16 +#define S2CR_TYPE_MASK 0x3 +#define S2CR_TYPE_TRANS (0 << S2CR_TYPE_SHIFT) +#define S2CR_TYPE_BYPASS (1 << S2CR_TYPE_SHIFT) +#define S2CR_TYPE_FAULT (2 << S2CR_TYPE_SHIFT) + +/* Context bank attribute registers */ +#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) +#define CBAR_VMID_SHIFT 0 +#define CBAR_VMID_MASK 0xff +#define CBAR_S1_MEMATTR_SHIFT 12 +#define CBAR_S1_MEMATTR_MASK 0xf +#define CBAR_S1_MEMATTR_WB 0xf +#define CBAR_TYPE_SHIFT 16 +#define CBAR_TYPE_MASK 0x3 +#define CBAR_TYPE_S2_TRANS (0 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_BYPASS (1 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_FAULT (2 << CBAR_TYPE_SHIFT) +#define CBAR_TYPE_S1_TRANS_S2_TRANS (3 << CBAR_TYPE_SHIFT) +#define CBAR_IRPTNDX_SHIFT 24 +#define CBAR_IRPTNDX_MASK 0xff + +#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2)) +#define CBA2R_RW64_32BIT (0 << 0) +#define CBA2R_RW64_64BIT (1 << 0) + +/* Translation context bank */ +#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1)) +#define ARM_SMMU_CB(smmu, n) ((n) * (smmu)->pagesize) + +#define ARM_SMMU_CB_SCTLR 0x0 +#define ARM_SMMU_CB_RESUME 0x8 +#define ARM_SMMU_CB_TTBCR2 0x10 +#define ARM_SMMU_CB_TTBR0_LO 0x20 +#define ARM_SMMU_CB_TTBR0_HI 0x24 +#define ARM_SMMU_CB_TTBCR 0x30 +#define ARM_SMMU_CB_S1_MAIR0 0x38 +#define ARM_SMMU_CB_FSR 0x58 +#define ARM_SMMU_CB_FAR_LO 0x60 +#define ARM_SMMU_CB_FAR_HI 0x64 +#define ARM_SMMU_CB_FSYNR0 0x68 + +#define SCTLR_S1_ASIDPNE (1 << 12) +#define SCTLR_CFCFG (1 << 7) +#define SCTLR_CFIE (1 << 6) +#define SCTLR_CFRE (1 << 5) +#define SCTLR_E (1 << 4) +#define SCTLR_AFE (1 << 2) +#define SCTLR_TRE (1 << 1) +#define SCTLR_M (1 << 0) +#define SCTLR_EAE_SBOP (SCTLR_AFE | SCTLR_TRE) + +#define RESUME_RETRY (0 << 0) +#define RESUME_TERMINATE (1 << 0) + +#define TTBCR_EAE (1 << 31) + +#define TTBCR_PASIZE_SHIFT 16 +#define TTBCR_PASIZE_MASK 0x7 + +#define TTBCR_TG0_4K (0 << 14) +#define TTBCR_TG0_64K (1 << 14) + +#define TTBCR_SH0_SHIFT 12 +#define TTBCR_SH0_MASK 0x3 +#define TTBCR_SH_NS 0 +#define TTBCR_SH_OS 2 +#define TTBCR_SH_IS 3 + +#define TTBCR_ORGN0_SHIFT 10 +#define TTBCR_IRGN0_SHIFT 8 +#define TTBCR_RGN_MASK 0x3 +#define TTBCR_RGN_NC 0 +#define TTBCR_RGN_WBWA 1 +#define TTBCR_RGN_WT 2 +#define TTBCR_RGN_WB 3 + +#define TTBCR_SL0_SHIFT 6 +#define TTBCR_SL0_MASK 0x3 +#define TTBCR_SL0_LVL_2 0 +#define TTBCR_SL0_LVL_1 1 + +#define TTBCR_T1SZ_SHIFT 16 +#define TTBCR_T0SZ_SHIFT 0 +#define TTBCR_SZ_MASK 0xf + +#define TTBCR2_SEP_SHIFT 15 +#define TTBCR2_SEP_MASK 0x7 + +#define TTBCR2_PASIZE_SHIFT 0 +#define TTBCR2_PASIZE_MASK 0x7 + +/* Common definitions for PASize and SEP fields */ +#define TTBCR2_ADDR_32 0 +#define TTBCR2_ADDR_36 1 +#define TTBCR2_ADDR_40 2 +#define TTBCR2_ADDR_42 3 +#define TTBCR2_ADDR_44 4 +#define TTBCR2_ADDR_48 5 + +#define MAIR_ATTR_SHIFT(n) ((n) << 3) +#define MAIR_ATTR_MASK 0xff +#define MAIR_ATTR_DEVICE 0x04 +#define MAIR_ATTR_NC 0x44 +#define MAIR_ATTR_WBRWA 0xff +#define MAIR_ATTR_IDX_NC 0 +#define MAIR_ATTR_IDX_CACHE 1 +#define MAIR_ATTR_IDX_DEV 2 + +#define FSR_MULTI (1 << 31) +#define FSR_SS (1 << 30) +#define FSR_UUT (1 << 8) +#define FSR_ASF (1 << 7) +#define FSR_TLBLKF (1 << 6) +#define FSR_TLBMCF (1 << 5) +#define FSR_EF (1 << 4) +#define FSR_PF (1 << 3) +#define FSR_AFF (1 << 2) +#define FSR_TF (1 << 1) + +#define FSR_IGN (FSR_AFF | FSR_ASF | FSR_TLBMCF | \ + FSR_TLBLKF) +#define FSR_FAULT (FSR_MULTI | FSR_SS | FSR_UUT | \ + FSR_EF | FSR_PF | FSR_TF) + +#define FSYNR0_WNR (1 << 4) + +struct arm_smmu_smr { + u8 idx; + u16 mask; + u16 id; +}; + +struct arm_smmu_master { + struct device_node *of_node; + + /* + * The following is specific to the master's position in the + * SMMU chain. + */ + struct rb_node node; + int num_streamids; + u16 streamids[MAX_MASTER_STREAMIDS]; + + /* + * We only need to allocate these on the root SMMU, as we + * configure unmatched streams to bypass translation. + */ + struct arm_smmu_smr *smrs; +}; + +struct arm_smmu_device { + struct device *dev; + struct device_node *parent_of_node; + + void __iomem *base; + unsigned long size; + unsigned long pagesize; + +#define ARM_SMMU_FEAT_COHERENT_WALK (1 << 0) +#define ARM_SMMU_FEAT_STREAM_MATCH (1 << 1) +#define ARM_SMMU_FEAT_TRANS_S1 (1 << 2) +#define ARM_SMMU_FEAT_TRANS_S2 (1 << 3) +#define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4) + u32 features; + int version; + + u32 num_context_banks; + u32 num_s2_context_banks; + DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS); + atomic_t irptndx; + + u32 num_mapping_groups; + DECLARE_BITMAP(smr_map, ARM_SMMU_MAX_SMRS); + + unsigned long input_size; + unsigned long s1_output_size; + unsigned long s2_output_size; + + u32 num_global_irqs; + u32 num_context_irqs; + unsigned int *irqs; + + DECLARE_BITMAP(vmid_map, ARM_SMMU_NUM_VMIDS); + + struct list_head list; + struct rb_root masters; +}; + +struct arm_smmu_cfg { + struct arm_smmu_device *smmu; + u8 vmid; + u8 cbndx; + u8 irptndx; + u32 cbar; + pgd_t *pgd; +}; + +struct arm_smmu_domain { + /* + * A domain can span across multiple, chained SMMUs and requires + * all devices within the domain to follow the same translation + * path. + */ + struct arm_smmu_device *leaf_smmu; + struct arm_smmu_cfg root_cfg; + phys_addr_t output_mask; + + spinlock_t lock; +}; + +static DEFINE_SPINLOCK(arm_smmu_devices_lock); +static LIST_HEAD(arm_smmu_devices); + +static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, + struct device_node *dev_node) +{ + struct rb_node *node = smmu->masters.rb_node; + + while (node) { + struct arm_smmu_master *master; + master = container_of(node, struct arm_smmu_master, node); + + if (dev_node < master->of_node) + node = node->rb_left; + else if (dev_node > master->of_node) + node = node->rb_right; + else + return master; + } + + return NULL; +} + +static int insert_smmu_master(struct arm_smmu_device *smmu, + struct arm_smmu_master *master) +{ + struct rb_node **new, *parent; + + new = &smmu->masters.rb_node; + parent = NULL; + while (*new) { + struct arm_smmu_master *this; + this = container_of(*new, struct arm_smmu_master, node); + + parent = *new; + if (master->of_node < this->of_node) + new = &((*new)->rb_left); + else if (master->of_node > this->of_node) + new = &((*new)->rb_right); + else + return -EEXIST; + } + + rb_link_node(&master->node, parent, new); + rb_insert_color(&master->node, &smmu->masters); + return 0; +} + +static int register_smmu_master(struct arm_smmu_device *smmu, + struct device *dev, + struct of_phandle_args *masterspec) +{ + int i; + struct arm_smmu_master *master; + + master = find_smmu_master(smmu, masterspec->np); + if (master) { + dev_err(dev, + "rejecting multiple registrations for master device %s\n", + masterspec->np->name); + return -EBUSY; + } + + if (masterspec->args_count > MAX_MASTER_STREAMIDS) { + dev_err(dev, + "reached maximum number (%d) of stream IDs for master device %s\n", + MAX_MASTER_STREAMIDS, masterspec->np->name); + return -ENOSPC; + } + + master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL); + if (!master) + return -ENOMEM; + + master->of_node = masterspec->np; + master->num_streamids = masterspec->args_count; + + for (i = 0; i < master->num_streamids; ++i) + master->streamids[i] = masterspec->args[i]; + + return insert_smmu_master(smmu, master); +} + +static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu) +{ + struct arm_smmu_device *parent; + + if (!smmu->parent_of_node) + return NULL; + + spin_lock(&arm_smmu_devices_lock); + list_for_each_entry(parent, &arm_smmu_devices, list) + if (parent->dev->of_node == smmu->parent_of_node) + goto out_unlock; + + parent = NULL; + dev_warn(smmu->dev, + "Failed to find SMMU parent despite parent in DT\n"); +out_unlock: + spin_unlock(&arm_smmu_devices_lock); + return parent; +} + +static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end) +{ + int idx; + + do { + idx = find_next_zero_bit(map, end, start); + if (idx == end) + return -ENOSPC; + } while (test_and_set_bit(idx, map)); + + return idx; +} + +static void __arm_smmu_free_bitmap(unsigned long *map, int idx) +{ + clear_bit(idx, map); +} + +/* Wait for any pending TLB invalidations to complete */ +static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu) +{ + int count = 0; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC); + while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS) + & sTLBGSTATUS_GSACTIVE) { + cpu_relax(); + if (++count == TLB_LOOP_TIMEOUT) { + dev_err_ratelimited(smmu->dev, + "TLB sync timed out -- SMMU may be deadlocked\n"); + return; + } + udelay(1); + } +} + +static irqreturn_t arm_smmu_context_fault(int irq, void *dev) +{ + int flags, ret; + u32 fsr, far, fsynr, resume; + unsigned long iova; + struct iommu_domain *domain = dev; + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu = root_cfg->smmu; + void __iomem *cb_base; + + cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); + fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); + + if (!(fsr & FSR_FAULT)) + return IRQ_NONE; + + if (fsr & FSR_IGN) + dev_err_ratelimited(smmu->dev, + "Unexpected context fault (fsr 0x%u)\n", + fsr); + + fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); + flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; + + far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_LO); + iova = far; +#ifdef CONFIG_64BIT + far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_HI); + iova |= ((unsigned long)far << 32); +#endif + + if (!report_iommu_fault(domain, smmu->dev, iova, flags)) { + ret = IRQ_HANDLED; + resume = RESUME_RETRY; + } else { + ret = IRQ_NONE; + resume = RESUME_TERMINATE; + } + + /* Clear the faulting FSR */ + writel(fsr, cb_base + ARM_SMMU_CB_FSR); + + /* Retry or terminate any stalled transactions */ + if (fsr & FSR_SS) + writel_relaxed(resume, cb_base + ARM_SMMU_CB_RESUME); + + return ret; +} + +static irqreturn_t arm_smmu_global_fault(int irq, void *dev) +{ + u32 gfsr, gfsynr0, gfsynr1, gfsynr2; + struct arm_smmu_device *smmu = dev; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + gfsr = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSR); + gfsynr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR0); + gfsynr1 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR1); + gfsynr2 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sGFSYNR2); + + dev_err_ratelimited(smmu->dev, + "Unexpected global fault, this could be serious\n"); + dev_err_ratelimited(smmu->dev, + "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 0x%08x\n", + gfsr, gfsynr0, gfsynr1, gfsynr2); + + writel(gfsr, gr0_base + ARM_SMMU_GR0_sGFSR); + return IRQ_NONE; +} + +static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) +{ + u32 reg; + bool stage1; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu = root_cfg->smmu; + void __iomem *cb_base, *gr0_base, *gr1_base; + + gr0_base = ARM_SMMU_GR0(smmu); + gr1_base = ARM_SMMU_GR1(smmu); + stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS; + cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); + + /* CBAR */ + reg = root_cfg->cbar | + (root_cfg->vmid << CBAR_VMID_SHIFT); + if (smmu->version == 1) + reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; + + /* Use the weakest memory type, so it is overridden by the pte */ + if (stage1) + reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); + writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); + + if (smmu->version > 1) { + /* CBA2R */ +#ifdef CONFIG_64BIT + reg = CBA2R_RW64_64BIT; +#else + reg = CBA2R_RW64_32BIT; +#endif + writel_relaxed(reg, + gr1_base + ARM_SMMU_GR1_CBA2R(root_cfg->cbndx)); + + /* TTBCR2 */ + switch (smmu->input_size) { + case 32: + reg = (TTBCR2_ADDR_32 << TTBCR2_SEP_SHIFT); + break; + case 36: + reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT); + break; + case 39: + reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT); + break; + case 42: + reg = (TTBCR2_ADDR_42 << TTBCR2_SEP_SHIFT); + break; + case 44: + reg = (TTBCR2_ADDR_44 << TTBCR2_SEP_SHIFT); + break; + case 48: + reg = (TTBCR2_ADDR_48 << TTBCR2_SEP_SHIFT); + break; + } + + switch (smmu->s1_output_size) { + case 32: + reg |= (TTBCR2_ADDR_32 << TTBCR2_PASIZE_SHIFT); + break; + case 36: + reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT); + break; + case 39: + reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT); + break; + case 42: + reg |= (TTBCR2_ADDR_42 << TTBCR2_PASIZE_SHIFT); + break; + case 44: + reg |= (TTBCR2_ADDR_44 << TTBCR2_PASIZE_SHIFT); + break; + case 48: + reg |= (TTBCR2_ADDR_48 << TTBCR2_PASIZE_SHIFT); + break; + } + + if (stage1) + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR2); + } + + /* TTBR0 */ + reg = __pa(root_cfg->pgd); +#ifndef __BIG_ENDIAN + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); + reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI); +#else + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_HI); + reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); +#endif + + /* + * TTBCR + * We use long descriptor, with inner-shareable WBWA tables in TTBR0. + */ + if (smmu->version > 1) { + if (PAGE_SIZE == SZ_4K) + reg = TTBCR_TG0_4K; + else + reg = TTBCR_TG0_64K; + + if (!stage1) { + switch (smmu->s2_output_size) { + case 32: + reg |= (TTBCR2_ADDR_32 << TTBCR_PASIZE_SHIFT); + break; + case 36: + reg |= (TTBCR2_ADDR_36 << TTBCR_PASIZE_SHIFT); + break; + case 40: + reg |= (TTBCR2_ADDR_40 << TTBCR_PASIZE_SHIFT); + break; + case 42: + reg |= (TTBCR2_ADDR_42 << TTBCR_PASIZE_SHIFT); + break; + case 44: + reg |= (TTBCR2_ADDR_44 << TTBCR_PASIZE_SHIFT); + break; + case 48: + reg |= (TTBCR2_ADDR_48 << TTBCR_PASIZE_SHIFT); + break; + } + } else { + reg |= (64 - smmu->s1_output_size) << TTBCR_T0SZ_SHIFT; + } + } else { + reg = 0; + } + + reg |= TTBCR_EAE | + (TTBCR_SH_IS << TTBCR_SH0_SHIFT) | + (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) | + (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) | + (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT); + writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR); + + /* MAIR0 (stage-1 only) */ + if (stage1) { + reg = (MAIR_ATTR_NC << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_NC)) | + (MAIR_ATTR_WBRWA << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_CACHE)) | + (MAIR_ATTR_DEVICE << MAIR_ATTR_SHIFT(MAIR_ATTR_IDX_DEV)); + writel_relaxed(reg, cb_base + ARM_SMMU_CB_S1_MAIR0); + } + + /* Nuke the TLB */ + writel_relaxed(root_cfg->vmid, gr0_base + ARM_SMMU_GR0_TLBIVMID); + arm_smmu_tlb_sync(smmu); + + /* SCTLR */ + reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_M | SCTLR_EAE_SBOP; + if (stage1) + reg |= SCTLR_S1_ASIDPNE; +#ifdef __BIG_ENDIAN + reg |= SCTLR_E; +#endif + writel(reg, cb_base + ARM_SMMU_CB_SCTLR); +} + +static int arm_smmu_init_domain_context(struct iommu_domain *domain, + struct device *dev) +{ + int irq, ret, start; + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu, *parent; + + /* + * Walk the SMMU chain to find the root device for this chain. + * We assume that no masters have translations which terminate + * early, and therefore check that the root SMMU does indeed have + * a StreamID for the master in question. + */ + parent = dev->archdata.iommu; + smmu_domain->output_mask = -1; + do { + smmu = parent; + smmu_domain->output_mask &= (1ULL << smmu->s2_output_size) - 1; + } while ((parent = find_parent_smmu(smmu))); + + if (!find_smmu_master(smmu, dev->of_node)) { + dev_err(dev, "unable to find root SMMU for device\n"); + return -ENODEV; + } + + ret = __arm_smmu_alloc_bitmap(smmu->vmid_map, 0, ARM_SMMU_NUM_VMIDS); + if (IS_ERR_VALUE(ret)) + return ret; + + root_cfg->vmid = ret; + if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) { + /* + * We will likely want to change this if/when KVM gets + * involved. + */ + root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS; + start = smmu->num_s2_context_banks; + } else if (smmu->features & ARM_SMMU_FEAT_TRANS_S2) { + root_cfg->cbar = CBAR_TYPE_S2_TRANS; + start = 0; + } else { + root_cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS; + start = smmu->num_s2_context_banks; + } + + ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, + smmu->num_context_banks); + if (IS_ERR_VALUE(ret)) + goto out_free_vmid; + + root_cfg->cbndx = ret; + + if (smmu->version == 1) { + root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); + root_cfg->irptndx %= smmu->num_context_irqs; + } else { + root_cfg->irptndx = root_cfg->cbndx; + } + + irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx]; + ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED, + "arm-smmu-context-fault", domain); + if (IS_ERR_VALUE(ret)) { + dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n", + root_cfg->irptndx, irq); + root_cfg->irptndx = -1; + goto out_free_context; + } + + root_cfg->smmu = smmu; + arm_smmu_init_context_bank(smmu_domain); + return ret; + +out_free_context: + __arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx); +out_free_vmid: + __arm_smmu_free_bitmap(smmu->vmid_map, root_cfg->vmid); + return ret; +} + +static void arm_smmu_destroy_domain_context(struct iommu_domain *domain) +{ + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu = root_cfg->smmu; + int irq; + + if (!smmu) + return; + + if (root_cfg->irptndx != -1) { + irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx]; + free_irq(irq, domain); + } + + __arm_smmu_free_bitmap(smmu->vmid_map, root_cfg->vmid); + __arm_smmu_free_bitmap(smmu->context_map, root_cfg->cbndx); +} + +static int arm_smmu_domain_init(struct iommu_domain *domain) +{ + struct arm_smmu_domain *smmu_domain; + pgd_t *pgd; + + /* + * Allocate the domain and initialise some of its data structures. + * We can't really do anything meaningful until we've added a + * master. + */ + smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL); + if (!smmu_domain) + return -ENOMEM; + + pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); + if (!pgd) + goto out_free_domain; + smmu_domain->root_cfg.pgd = pgd; + + spin_lock_init(&smmu_domain->lock); + domain->priv = smmu_domain; + return 0; + +out_free_domain: + kfree(smmu_domain); + return -ENOMEM; +} + +static void arm_smmu_free_ptes(pmd_t *pmd) +{ + pgtable_t table = pmd_pgtable(*pmd); + pgtable_page_dtor(table); + __free_page(table); +} + +static void arm_smmu_free_pmds(pud_t *pud) +{ + int i; + pmd_t *pmd, *pmd_base = pmd_offset(pud, 0); + + pmd = pmd_base; + for (i = 0; i < PTRS_PER_PMD; ++i) { + if (pmd_none(*pmd)) + continue; + + arm_smmu_free_ptes(pmd); + pmd++; + } + + pmd_free(NULL, pmd_base); +} + +static void arm_smmu_free_puds(pgd_t *pgd) +{ + int i; + pud_t *pud, *pud_base = pud_offset(pgd, 0); + + pud = pud_base; + for (i = 0; i < PTRS_PER_PUD; ++i) { + if (pud_none(*pud)) + continue; + + arm_smmu_free_pmds(pud); + pud++; + } + + pud_free(NULL, pud_base); +} + +static void arm_smmu_free_pgtables(struct arm_smmu_domain *smmu_domain) +{ + int i; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + pgd_t *pgd, *pgd_base = root_cfg->pgd; + + /* + * Recursively free the page tables for this domain. We don't + * care about speculative TLB filling, because the TLB will be + * nuked next time this context bank is re-allocated and no devices + * currently map to these tables. + */ + pgd = pgd_base; + for (i = 0; i < PTRS_PER_PGD; ++i) { + if (pgd_none(*pgd)) + continue; + arm_smmu_free_puds(pgd); + pgd++; + } + + kfree(pgd_base); +} + +static void arm_smmu_domain_destroy(struct iommu_domain *domain) +{ + struct arm_smmu_domain *smmu_domain = domain->priv; + arm_smmu_destroy_domain_context(domain); + arm_smmu_free_pgtables(smmu_domain); + kfree(smmu_domain); +} + +static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, + struct arm_smmu_master *master) +{ + int i; + struct arm_smmu_smr *smrs; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)) + return 0; + + if (master->smrs) + return -EEXIST; + + smrs = kmalloc(sizeof(*smrs) * master->num_streamids, GFP_KERNEL); + if (!smrs) { + dev_err(smmu->dev, "failed to allocate %d SMRs for master %s\n", + master->num_streamids, master->of_node->name); + return -ENOMEM; + } + + /* Allocate the SMRs on the root SMMU */ + for (i = 0; i < master->num_streamids; ++i) { + int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0, + smmu->num_mapping_groups); + if (IS_ERR_VALUE(idx)) { + dev_err(smmu->dev, "failed to allocate free SMR\n"); + goto err_free_smrs; + } + + smrs[i] = (struct arm_smmu_smr) { + .idx = idx, + .mask = 0, /* We don't currently share SMRs */ + .id = master->streamids[i], + }; + } + + /* It worked! Now, poke the actual hardware */ + for (i = 0; i < master->num_streamids; ++i) { + u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT | + smrs[i].mask << SMR_MASK_SHIFT; + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx)); + } + + master->smrs = smrs; + return 0; + +err_free_smrs: + while (--i >= 0) + __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx); + kfree(smrs); + return -ENOSPC; +} + +static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, + struct arm_smmu_master *master) +{ + int i; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + struct arm_smmu_smr *smrs = master->smrs; + + /* Invalidate the SMRs before freeing back to the allocator */ + for (i = 0; i < master->num_streamids; ++i) { + u8 idx = smrs[i].idx; + writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); + __arm_smmu_free_bitmap(smmu->smr_map, idx); + } + + master->smrs = NULL; + kfree(smrs); +} + +static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu, + struct arm_smmu_master *master) +{ + int i; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + for (i = 0; i < master->num_streamids; ++i) { + u16 sid = master->streamids[i]; + writel_relaxed(S2CR_TYPE_BYPASS, + gr0_base + ARM_SMMU_GR0_S2CR(sid)); + } +} + +static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, + struct arm_smmu_master *master) +{ + int i, ret; + struct arm_smmu_device *parent, *smmu = smmu_domain->root_cfg.smmu; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + ret = arm_smmu_master_configure_smrs(smmu, master); + if (ret) + return ret; + + /* Bypass the leaves */ + smmu = smmu_domain->leaf_smmu; + while ((parent = find_parent_smmu(smmu))) { + /* + * We won't have a StreamID match for anything but the root + * smmu, so we only need to worry about StreamID indexing, + * where we must install bypass entries in the S2CRs. + */ + if (smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) + continue; + + arm_smmu_bypass_stream_mapping(smmu, master); + smmu = parent; + } + + /* Now we're at the root, time to point at our context bank */ + for (i = 0; i < master->num_streamids; ++i) { + u32 idx, s2cr; + idx = master->smrs ? master->smrs[i].idx : master->streamids[i]; + s2cr = (S2CR_TYPE_TRANS << S2CR_TYPE_SHIFT) | + (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT); + writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); + } + + return 0; +} + +static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain, + struct arm_smmu_master *master) +{ + struct arm_smmu_device *smmu = smmu_domain->root_cfg.smmu; + + /* + * We *must* clear the S2CR first, because freeing the SMR means + * that it can be re-allocated immediately. + */ + arm_smmu_bypass_stream_mapping(smmu, master); + arm_smmu_master_free_smrs(smmu, master); +} + +static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) +{ + int ret = -EINVAL; + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_device *device_smmu = dev->archdata.iommu; + struct arm_smmu_master *master; + + if (!device_smmu) { + dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); + return -ENXIO; + } + + /* + * Sanity check the domain. We don't currently support domains + * that cross between different SMMU chains. + */ + spin_lock(&smmu_domain->lock); + if (!smmu_domain->leaf_smmu) { + /* Now that we have a master, we can finalise the domain */ + ret = arm_smmu_init_domain_context(domain, dev); + if (IS_ERR_VALUE(ret)) + goto err_unlock; + + smmu_domain->leaf_smmu = device_smmu; + } else if (smmu_domain->leaf_smmu != device_smmu) { + dev_err(dev, + "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", + dev_name(smmu_domain->leaf_smmu->dev), + dev_name(device_smmu->dev)); + goto err_unlock; + } + spin_unlock(&smmu_domain->lock); + + /* Looks ok, so add the device to the domain */ + master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); + if (!master) + return -ENODEV; + + return arm_smmu_domain_add_master(smmu_domain, master); + +err_unlock: + spin_unlock(&smmu_domain->lock); + return ret; +} + +static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) +{ + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_master *master; + + master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); + if (master) + arm_smmu_domain_remove_master(smmu_domain, master); +} + +static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, + size_t size) +{ + unsigned long offset = (unsigned long)addr & ~PAGE_MASK; + + /* + * If the SMMU can't walk tables in the CPU caches, treat them + * like non-coherent DMA since we need to flush the new entries + * all the way out to memory. There's no possibility of recursion + * here as the SMMU table walker will not be wired through another + * SMMU. + */ + if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)) + dma_map_page(smmu->dev, virt_to_page(addr), offset, size, + DMA_TO_DEVICE); +} + +static bool arm_smmu_pte_is_contiguous_range(unsigned long addr, + unsigned long end) +{ + return !(addr & ~ARM_SMMU_PTE_CONT_MASK) && + (addr + ARM_SMMU_PTE_CONT_SIZE <= end); +} + +static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, + unsigned long addr, unsigned long end, + unsigned long pfn, int flags, int stage) +{ + pte_t *pte, *start; + pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF; + + if (pmd_none(*pmd)) { + /* Allocate a new set of tables */ + pgtable_t table = alloc_page(PGALLOC_GFP); + if (!table) + return -ENOMEM; + + arm_smmu_flush_pgtable(smmu, page_address(table), + ARM_SMMU_PTE_HWTABLE_SIZE); + pgtable_page_ctor(table); + pmd_populate(NULL, pmd, table); + arm_smmu_flush_pgtable(smmu, pmd, sizeof(*pmd)); + } + + if (stage == 1) { + pteval |= ARM_SMMU_PTE_AP_UNPRIV; + if (!(flags & IOMMU_WRITE) && (flags & IOMMU_READ)) + pteval |= ARM_SMMU_PTE_AP_RDONLY; + + if (flags & IOMMU_CACHE) + pteval |= (MAIR_ATTR_IDX_CACHE << + ARM_SMMU_PTE_ATTRINDX_SHIFT); + } else { + pteval |= ARM_SMMU_PTE_HAP_FAULT; + if (flags & IOMMU_READ) + pteval |= ARM_SMMU_PTE_HAP_READ; + if (flags & IOMMU_WRITE) + pteval |= ARM_SMMU_PTE_HAP_WRITE; + if (flags & IOMMU_CACHE) + pteval |= ARM_SMMU_PTE_MEMATTR_OIWB; + else + pteval |= ARM_SMMU_PTE_MEMATTR_NC; + } + + /* If no access, create a faulting entry to avoid TLB fills */ + if (!(flags & (IOMMU_READ | IOMMU_WRITE))) + pteval &= ~ARM_SMMU_PTE_PAGE; + + pteval |= ARM_SMMU_PTE_SH_IS; + start = pmd_page_vaddr(*pmd) + pte_index(addr); + pte = start; + + /* + * Install the page table entries. This is fairly complicated + * since we attempt to make use of the contiguous hint in the + * ptes where possible. The contiguous hint indicates a series + * of ARM_SMMU_PTE_CONT_ENTRIES ptes mapping a physically + * contiguous region with the following constraints: + * + * - The region start is aligned to ARM_SMMU_PTE_CONT_SIZE + * - Each pte in the region has the contiguous hint bit set + * + * This complicates unmapping (also handled by this code, when + * neither IOMMU_READ or IOMMU_WRITE are set) because it is + * possible, yet highly unlikely, that a client may unmap only + * part of a contiguous range. This requires clearing of the + * contiguous hint bits in the range before installing the new + * faulting entries. + * + * Note that re-mapping an address range without first unmapping + * it is not supported, so TLB invalidation is not required here + * and is instead performed at unmap and domain-init time. + */ + do { + int i = 1; + pteval &= ~ARM_SMMU_PTE_CONT; + + if (arm_smmu_pte_is_contiguous_range(addr, end)) { + i = ARM_SMMU_PTE_CONT_ENTRIES; + pteval |= ARM_SMMU_PTE_CONT; + } else if (pte_val(*pte) & + (ARM_SMMU_PTE_CONT | ARM_SMMU_PTE_PAGE)) { + int j; + pte_t *cont_start; + unsigned long idx = pte_index(addr); + + idx &= ~(ARM_SMMU_PTE_CONT_ENTRIES - 1); + cont_start = pmd_page_vaddr(*pmd) + idx; + for (j = 0; j < ARM_SMMU_PTE_CONT_ENTRIES; ++j) + pte_val(*(cont_start + j)) &= ~ARM_SMMU_PTE_CONT; + + arm_smmu_flush_pgtable(smmu, cont_start, + sizeof(*pte) * + ARM_SMMU_PTE_CONT_ENTRIES); + } + + do { + *pte = pfn_pte(pfn, __pgprot(pteval)); + } while (pte++, pfn++, addr += PAGE_SIZE, --i); + } while (addr != end); + + arm_smmu_flush_pgtable(smmu, start, sizeof(*pte) * (pte - start)); + return 0; +} + +static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, + unsigned long addr, unsigned long end, + phys_addr_t phys, int flags, int stage) +{ + int ret; + pmd_t *pmd; + unsigned long next, pfn = __phys_to_pfn(phys); + +#ifndef __PAGETABLE_PMD_FOLDED + if (pud_none(*pud)) { + pmd = pmd_alloc_one(NULL, addr); + if (!pmd) + return -ENOMEM; + } else +#endif + pmd = pmd_offset(pud, addr); + + do { + next = pmd_addr_end(addr, end); + ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, + flags, stage); + pud_populate(NULL, pud, pmd); + arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); + phys += next - addr; + } while (pmd++, addr = next, addr < end); + + return ret; +} + +static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, + unsigned long addr, unsigned long end, + phys_addr_t phys, int flags, int stage) +{ + int ret = 0; + pud_t *pud; + unsigned long next; + +#ifndef __PAGETABLE_PUD_FOLDED + if (pgd_none(*pgd)) { + pud = pud_alloc_one(NULL, addr); + if (!pud) + return -ENOMEM; + } else +#endif + pud = pud_offset(pgd, addr); + + do { + next = pud_addr_end(addr, end); + ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys, + flags, stage); + pgd_populate(NULL, pud, pgd); + arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); + phys += next - addr; + } while (pud++, addr = next, addr < end); + + return ret; +} + +static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, + unsigned long iova, phys_addr_t paddr, + size_t size, int flags) +{ + int ret, stage; + unsigned long end; + phys_addr_t input_mask, output_mask; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + pgd_t *pgd = root_cfg->pgd; + struct arm_smmu_device *smmu = root_cfg->smmu; + + if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { + stage = 2; + output_mask = (1ULL << smmu->s2_output_size) - 1; + } else { + stage = 1; + output_mask = (1ULL << smmu->s1_output_size) - 1; + } + + if (!pgd) + return -EINVAL; + + if (size & ~PAGE_MASK) + return -EINVAL; + + input_mask = (1ULL << smmu->input_size) - 1; + if ((phys_addr_t)iova & ~input_mask) + return -ERANGE; + + if (paddr & ~output_mask) + return -ERANGE; + + spin_lock(&smmu_domain->lock); + pgd += pgd_index(iova); + end = iova + size; + do { + unsigned long next = pgd_addr_end(iova, end); + + ret = arm_smmu_alloc_init_pud(smmu, pgd, iova, next, paddr, + flags, stage); + if (ret) + goto out_unlock; + + paddr += next - iova; + iova = next; + } while (pgd++, iova != end); + +out_unlock: + spin_unlock(&smmu_domain->lock); + + /* Ensure new page tables are visible to the hardware walker */ + if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) + dsb(); + + return ret; +} + +static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int flags) +{ + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_device *smmu = smmu_domain->leaf_smmu; + + if (!smmu_domain || !smmu) + return -ENODEV; + + /* Check for silent address truncation up the SMMU chain. */ + if ((phys_addr_t)iova & ~smmu_domain->output_mask) + return -ERANGE; + + return arm_smmu_handle_mapping(smmu_domain, iova, paddr, size, flags); +} + +static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, + size_t size) +{ + int ret; + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu = root_cfg->smmu; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + + ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0); + writel_relaxed(root_cfg->vmid, gr0_base + ARM_SMMU_GR0_TLBIVMID); + arm_smmu_tlb_sync(smmu); + return ret ? ret : size; +} + +static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, + dma_addr_t iova) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + struct arm_smmu_domain *smmu_domain = domain->priv; + struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; + struct arm_smmu_device *smmu = root_cfg->smmu; + + spin_lock(&smmu_domain->lock); + pgd = root_cfg->pgd; + if (!pgd) + goto err_unlock; + + pgd += pgd_index(iova); + if (pgd_none_or_clear_bad(pgd)) + goto err_unlock; + + pud = pud_offset(pgd, iova); + if (pud_none_or_clear_bad(pud)) + goto err_unlock; + + pmd = pmd_offset(pud, iova); + if (pmd_none_or_clear_bad(pmd)) + goto err_unlock; + + pte = pmd_page_vaddr(*pmd) + pte_index(iova); + if (pte_none(pte)) + goto err_unlock; + + spin_unlock(&smmu_domain->lock); + return __pfn_to_phys(pte_pfn(*pte)) | (iova & ~PAGE_MASK); + +err_unlock: + spin_unlock(&smmu_domain->lock); + dev_warn(smmu->dev, + "invalid (corrupt?) page tables detected for iova 0x%llx\n", + (unsigned long long)iova); + return -EINVAL; +} + +static int arm_smmu_domain_has_cap(struct iommu_domain *domain, + unsigned long cap) +{ + unsigned long caps = 0; + struct arm_smmu_domain *smmu_domain = domain->priv; + + if (smmu_domain->root_cfg.smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) + caps |= IOMMU_CAP_CACHE_COHERENCY; + + return !!(cap & caps); +} + +static int arm_smmu_add_device(struct device *dev) +{ + struct arm_smmu_device *child, *parent, *smmu; + struct arm_smmu_master *master = NULL; + + spin_lock(&arm_smmu_devices_lock); + list_for_each_entry(parent, &arm_smmu_devices, list) { + smmu = parent; + + /* Try to find a child of the current SMMU. */ + list_for_each_entry(child, &arm_smmu_devices, list) { + if (child->parent_of_node == parent->dev->of_node) { + /* Does the child sit above our master? */ + master = find_smmu_master(child, dev->of_node); + if (master) { + smmu = NULL; + break; + } + } + } + + /* We found some children, so keep searching. */ + if (!smmu) { + master = NULL; + continue; + } + + master = find_smmu_master(smmu, dev->of_node); + if (master) + break; + } + spin_unlock(&arm_smmu_devices_lock); + + if (!master) + return -ENODEV; + + dev->archdata.iommu = smmu; + return 0; +} + +static void arm_smmu_remove_device(struct device *dev) +{ + dev->archdata.iommu = NULL; +} + +static struct iommu_ops arm_smmu_ops = { + .domain_init = arm_smmu_domain_init, + .domain_destroy = arm_smmu_domain_destroy, + .attach_dev = arm_smmu_attach_dev, + .detach_dev = arm_smmu_detach_dev, + .map = arm_smmu_map, + .unmap = arm_smmu_unmap, + .iova_to_phys = arm_smmu_iova_to_phys, + .domain_has_cap = arm_smmu_domain_has_cap, + .add_device = arm_smmu_add_device, + .remove_device = arm_smmu_remove_device, + .pgsize_bitmap = (SECTION_SIZE | + ARM_SMMU_PTE_CONT_SIZE | + PAGE_SIZE), +}; + +static void arm_smmu_device_reset(struct arm_smmu_device *smmu) +{ + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + int i = 0; + u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); + + /* Mark all SMRn as invalid and all S2CRn as bypass */ + for (i = 0; i < smmu->num_mapping_groups; ++i) { + writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i)); + writel_relaxed(S2CR_TYPE_BYPASS, gr0_base + ARM_SMMU_GR0_S2CR(i)); + } + + /* Invalidate the TLB, just in case */ + writel_relaxed(0, gr0_base + ARM_SMMU_GR0_STLBIALL); + writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); + writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); + + /* Enable fault reporting */ + scr0 |= (sCR0_GFRE | sCR0_GFIE | sCR0_GCFGFRE | sCR0_GCFGFIE); + + /* Disable TLB broadcasting. */ + scr0 |= (sCR0_VMIDPNE | sCR0_PTM); + + /* Enable client access, but bypass when no mapping is found */ + scr0 &= ~(sCR0_CLIENTPD | sCR0_USFCFG); + + /* Disable forced broadcasting */ + scr0 &= ~sCR0_FB; + + /* Don't upgrade barriers */ + scr0 &= ~(sCR0_BSU_MASK << sCR0_BSU_SHIFT); + + /* Push the button */ + arm_smmu_tlb_sync(smmu); + writel(scr0, gr0_base + ARM_SMMU_GR0_sCR0); +} + +static int arm_smmu_id_size_to_bits(int size) +{ + switch (size) { + case 0: + return 32; + case 1: + return 36; + case 2: + return 40; + case 3: + return 42; + case 4: + return 44; + case 5: + default: + return 48; + } +} + +static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) +{ + unsigned long size; + void __iomem *gr0_base = ARM_SMMU_GR0(smmu); + u32 id; + + dev_notice(smmu->dev, "probing hardware configuration...\n"); + + /* Primecell ID */ + id = readl_relaxed(gr0_base + ARM_SMMU_GR0_PIDR2); + smmu->version = ((id >> PIDR2_ARCH_SHIFT) & PIDR2_ARCH_MASK) + 1; + dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version); + + /* ID0 */ + id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID0); +#ifndef CONFIG_64BIT + if (((id >> ID0_PTFS_SHIFT) & ID0_PTFS_MASK) == ID0_PTFS_V8_ONLY) { + dev_err(smmu->dev, "\tno v7 descriptor support!\n"); + return -ENODEV; + } +#endif + if (id & ID0_S1TS) { + smmu->features |= ARM_SMMU_FEAT_TRANS_S1; + dev_notice(smmu->dev, "\tstage 1 translation\n"); + } + + if (id & ID0_S2TS) { + smmu->features |= ARM_SMMU_FEAT_TRANS_S2; + dev_notice(smmu->dev, "\tstage 2 translation\n"); + } + + if (id & ID0_NTS) { + smmu->features |= ARM_SMMU_FEAT_TRANS_NESTED; + dev_notice(smmu->dev, "\tnested translation\n"); + } + + if (!(smmu->features & + (ARM_SMMU_FEAT_TRANS_S1 | ARM_SMMU_FEAT_TRANS_S2 | + ARM_SMMU_FEAT_TRANS_NESTED))) { + dev_err(smmu->dev, "\tno translation support!\n"); + return -ENODEV; + } + + if (id & ID0_CTTW) { + smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK; + dev_notice(smmu->dev, "\tcoherent table walk\n"); + } + + if (id & ID0_SMS) { + u32 smr, sid, mask; + + smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH; + smmu->num_mapping_groups = (id >> ID0_NUMSMRG_SHIFT) & + ID0_NUMSMRG_MASK; + if (smmu->num_mapping_groups == 0) { + dev_err(smmu->dev, + "stream-matching supported, but no SMRs present!\n"); + return -ENODEV; + } + + smr = SMR_MASK_MASK << SMR_MASK_SHIFT; + smr |= (SMR_ID_MASK << SMR_ID_SHIFT); + writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0)); + smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); + + mask = (smr >> SMR_MASK_SHIFT) & SMR_MASK_MASK; + sid = (smr >> SMR_ID_SHIFT) & SMR_ID_MASK; + if ((mask & sid) != sid) { + dev_err(smmu->dev, + "SMR mask bits (0x%x) insufficient for ID field (0x%x)\n", + mask, sid); + return -ENODEV; + } + + dev_notice(smmu->dev, + "\tstream matching with %u register groups, mask 0x%x", + smmu->num_mapping_groups, mask); + } + + /* ID1 */ + id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID1); + smmu->pagesize = (id & ID1_PAGESIZE) ? SZ_64K : SZ_4K; + + /* Check that we ioremapped enough */ + size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); + size *= (smmu->pagesize << 1); + if (smmu->size < size) + dev_warn(smmu->dev, + "device is 0x%lx bytes but only mapped 0x%lx!\n", + size, smmu->size); + + smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & + ID1_NUMS2CB_MASK; + smmu->num_context_banks = (id >> ID1_NUMCB_SHIFT) & ID1_NUMCB_MASK; + if (smmu->num_s2_context_banks > smmu->num_context_banks) { + dev_err(smmu->dev, "impossible number of S2 context banks!\n"); + return -ENODEV; + } + dev_notice(smmu->dev, "\t%u context banks (%u stage-2 only)\n", + smmu->num_context_banks, smmu->num_s2_context_banks); + + /* ID2 */ + id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2); + size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & ID2_IAS_MASK); + + /* + * Stage-1 output limited by stage-2 input size due to pgd + * allocation (PTRS_PER_PGD). + */ +#ifdef CONFIG_64BIT + /* Current maximum output size of 39 bits */ + smmu->s1_output_size = min(39UL, size); +#else + smmu->s1_output_size = min(32UL, size); +#endif + + /* The stage-2 output mask is also applied for bypass */ + size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); + smmu->s2_output_size = min((unsigned long)PHYS_MASK_SHIFT, size); + + if (smmu->version == 1) { + smmu->input_size = 32; + } else { +#ifdef CONFIG_64BIT + size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; + size = min(39, arm_smmu_id_size_to_bits(size)); +#else + size = 32; +#endif + smmu->input_size = size; + + if ((PAGE_SIZE == SZ_4K && !(id & ID2_PTFS_4K)) || + (PAGE_SIZE == SZ_64K && !(id & ID2_PTFS_64K)) || + (PAGE_SIZE != SZ_4K && PAGE_SIZE != SZ_64K)) { + dev_err(smmu->dev, "CPU page size 0x%lx unsupported\n", + PAGE_SIZE); + return -ENODEV; + } + } + + dev_notice(smmu->dev, + "\t%lu-bit VA, %lu-bit IPA, %lu-bit PA\n", + smmu->input_size, smmu->s1_output_size, smmu->s2_output_size); + return 0; +} + +static int arm_smmu_device_dt_probe(struct platform_device *pdev) +{ + struct resource *res; + struct arm_smmu_device *smmu; + struct device_node *dev_node; + struct device *dev = &pdev->dev; + struct rb_node *node; + struct of_phandle_args masterspec; + int num_irqs, i, err; + + smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); + if (!smmu) { + dev_err(dev, "failed to allocate arm_smmu_device\n"); + return -ENOMEM; + } + smmu->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing base address/size\n"); + return -ENODEV; + } + + smmu->size = resource_size(res); + smmu->base = devm_request_and_ioremap(dev, res); + if (!smmu->base) + return -EADDRNOTAVAIL; + + if (of_property_read_u32(dev->of_node, "#global-interrupts", + &smmu->num_global_irqs)) { + dev_err(dev, "missing #global-interrupts property\n"); + return -ENODEV; + } + + num_irqs = 0; + while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) { + num_irqs++; + if (num_irqs > smmu->num_global_irqs) + smmu->num_context_irqs++; + } + + if (num_irqs < smmu->num_global_irqs) { + dev_warn(dev, "found %d interrupts but expected at least %d\n", + num_irqs, smmu->num_global_irqs); + smmu->num_global_irqs = num_irqs; + } + smmu->num_context_irqs = num_irqs - smmu->num_global_irqs; + + smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs, + GFP_KERNEL); + if (!smmu->irqs) { + dev_err(dev, "failed to allocate %d irqs\n", num_irqs); + return -ENOMEM; + } + + for (i = 0; i < num_irqs; ++i) { + int irq = platform_get_irq(pdev, i); + if (irq < 0) { + dev_err(dev, "failed to get irq index %d\n", i); + return -ENODEV; + } + smmu->irqs[i] = irq; + } + + i = 0; + smmu->masters = RB_ROOT; + while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters", + "#stream-id-cells", i, + &masterspec)) { + err = register_smmu_master(smmu, dev, &masterspec); + if (err) { + dev_err(dev, "failed to add master %s\n", + masterspec.np->name); + goto out_put_masters; + } + + i++; + } + dev_notice(dev, "registered %d master devices\n", i); + + if ((dev_node = of_parse_phandle(dev->of_node, "smmu-parent", 0))) + smmu->parent_of_node = dev_node; + + err = arm_smmu_device_cfg_probe(smmu); + if (err) + goto out_put_parent; + + if (smmu->version > 1 && + smmu->num_context_banks != smmu->num_context_irqs) { + dev_err(dev, + "found only %d context interrupt(s) but %d required\n", + smmu->num_context_irqs, smmu->num_context_banks); + goto out_put_parent; + } + + arm_smmu_device_reset(smmu); + + for (i = 0; i < smmu->num_global_irqs; ++i) { + err = request_irq(smmu->irqs[i], + arm_smmu_global_fault, + IRQF_SHARED, + "arm-smmu global fault", + smmu); + if (err) { + dev_err(dev, "failed to request global IRQ %d (%u)\n", + i, smmu->irqs[i]); + goto out_free_irqs; + } + } + + INIT_LIST_HEAD(&smmu->list); + spin_lock(&arm_smmu_devices_lock); + list_add(&smmu->list, &arm_smmu_devices); + spin_unlock(&arm_smmu_devices_lock); + return 0; + +out_free_irqs: + while (i--) + free_irq(smmu->irqs[i], smmu); + +out_put_parent: + if (smmu->parent_of_node) + of_node_put(smmu->parent_of_node); + +out_put_masters: + for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { + struct arm_smmu_master *master; + master = container_of(node, struct arm_smmu_master, node); + of_node_put(master->of_node); + } + + return err; +} + +static int arm_smmu_device_remove(struct platform_device *pdev) +{ + int i; + struct device *dev = &pdev->dev; + struct arm_smmu_device *curr, *smmu = NULL; + struct rb_node *node; + + spin_lock(&arm_smmu_devices_lock); + list_for_each_entry(curr, &arm_smmu_devices, list) { + if (curr->dev == dev) { + smmu = curr; + list_del(&smmu->list); + break; + } + } + spin_unlock(&arm_smmu_devices_lock); + + if (!smmu) + return -ENODEV; + + if (smmu->parent_of_node) + of_node_put(smmu->parent_of_node); + + for (node = rb_first(&smmu->masters); node; node = rb_next(node)) { + struct arm_smmu_master *master; + master = container_of(node, struct arm_smmu_master, node); + of_node_put(master->of_node); + } + + if (!bitmap_empty(smmu->vmid_map, ARM_SMMU_NUM_VMIDS)) + dev_err(dev, "removing device with active domains!\n"); + + for (i = 0; i < smmu->num_global_irqs; ++i) + free_irq(smmu->irqs[i], smmu); + + /* Turn the thing off */ + writel(sCR0_CLIENTPD, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_sCR0); + return 0; +} + +#ifdef CONFIG_OF +static struct of_device_id arm_smmu_of_match[] = { + { .compatible = "arm,smmu-v1", }, + { .compatible = "arm,smmu-v2", }, + { .compatible = "arm,mmu-400", }, + { .compatible = "arm,mmu-500", }, + { }, +}; +MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +#endif + +static struct platform_driver arm_smmu_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "arm-smmu", + .of_match_table = of_match_ptr(arm_smmu_of_match), + }, + .probe = arm_smmu_device_dt_probe, + .remove = arm_smmu_device_remove, +}; + +static int __init arm_smmu_init(void) +{ + int ret; + + ret = platform_driver_register(&arm_smmu_driver); + if (ret) + return ret; + + /* Oh, for a proper bus abstraction */ + if (!iommu_present(&platform_bus_type)); + bus_set_iommu(&platform_bus_type, &arm_smmu_ops); + + if (!iommu_present(&amba_bustype)); + bus_set_iommu(&amba_bustype, &arm_smmu_ops); + + return 0; +} + +static void __exit arm_smmu_exit(void) +{ + return platform_driver_unregister(&arm_smmu_driver); +} + +module_init(arm_smmu_init); +module_exit(arm_smmu_exit); + +MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); +MODULE_AUTHOR("Will Deacon "); +MODULE_LICENSE("GPL v2"); -- GitLab From b8f9879ea9d9b697f8864f219ad98c5779e6ee04 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 24 Jun 2013 18:31:26 +0100 Subject: [PATCH 1832/2900] MAINTAINERS: add entry for ARM system MMU driver Add myself as maintainer for the ARM system MMU driver. Acked-by: Grant Likely Signed-off-by: Will Deacon Signed-off-by: Joerg Roedel --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5be702cc8449..1eb2a7261787 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1310,6 +1310,12 @@ T: git git://git.xilinx.com/linux-xlnx.git S: Supported F: arch/arm/mach-zynq/ +ARM SMMU DRIVER +M: Will Deacon +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: drivers/iommu/arm-smmu.c + ARM64 PORT (AARCH64 ARCHITECTURE) M: Catalin Marinas M: Will Deacon -- GitLab From f5bfdbf252ad54aa4b6f765cbe89750087fcc155 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 25 Jun 2013 16:01:44 -0600 Subject: [PATCH 1833/2900] vfio/type1: Fix missed frees and zero sized removes With hugepage support we can only properly aligned and sized ranges. We only guarantee that we can unmap the same ranges mapped and not arbitrary sub-ranges. This means we might not free anything or might free more than requested. The vfio unmap interface started storing the unmapped size to return to userspace to handle this. This patch fixes a few places where we don't properly handle those cases, moves a memory allocation to a place where failure is an option and checks our loops to make sure we don't get into an infinite loop trying to remove an overlap. Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 77 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 8a2be4e40f22..98231d10890c 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -370,6 +370,9 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, struct vfio_dma *split; int ret; + if (!*size) + return 0; + /* * Existing dma region is completely covered, unmap all. This is * the likely case since userspace tends to map and unmap buffers @@ -411,7 +414,9 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, dma->vaddr += overlap; dma->size -= overlap; vfio_insert_dma(iommu, dma); - } + } else + kfree(dma); + *size = overlap; return 0; } @@ -425,48 +430,41 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, if (ret) return ret; - /* - * We may have unmapped the entire vfio_dma if the user is - * trying to unmap a sub-region of what was originally - * mapped. If anything left, we can resize in place since - * iova is unchanged. - */ - if (overlap < dma->size) - dma->size -= overlap; - else - vfio_remove_dma(iommu, dma); - + dma->size -= overlap; *size = overlap; return 0; } /* Split existing */ + split = kzalloc(sizeof(*split), GFP_KERNEL); + if (!split) + return -ENOMEM; + offset = start - dma->iova; ret = vfio_unmap_unpin(iommu, dma, start, size); if (ret) return ret; - WARN_ON(!*size); + if (!*size) { + kfree(split); + return -EINVAL; + } + tmp = dma->size; - /* - * Resize the lower vfio_dma in place, insert new for remaining - * upper segment. - */ + /* Resize the lower vfio_dma in place, before the below insert */ dma->size = offset; - if (offset + *size < tmp) { - split = kzalloc(sizeof(*split), GFP_KERNEL); - if (!split) - return -ENOMEM; - + /* Insert new for remainder, assuming it didn't all get unmapped */ + if (likely(offset + *size < tmp)) { split->size = tmp - offset - *size; split->iova = dma->iova + offset + *size; split->vaddr = dma->vaddr + offset + *size; split->prot = dma->prot; vfio_insert_dma(iommu, split); - } + } else + kfree(split); return 0; } @@ -483,7 +481,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, if (unmap->iova & mask) return -EINVAL; - if (unmap->size & mask) + if (!unmap->size || unmap->size & mask) return -EINVAL; WARN_ON(mask & PAGE_MASK); @@ -493,7 +491,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu, while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) { size = unmap->size; ret = vfio_remove_dma_overlap(iommu, unmap->iova, &size, dma); - if (ret) + if (ret || !size) break; unmapped += size; } @@ -635,7 +633,6 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, if (tmp && tmp->prot == prot && tmp->vaddr + tmp->size == vaddr) { tmp->size += size; - iova = tmp->iova; size = tmp->size; vaddr = tmp->vaddr; @@ -643,19 +640,28 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, } } - /* Check if we abut a region above - nothing above ~0 + 1 */ + /* + * Check if we abut a region above - nothing above ~0 + 1. + * If we abut above and below, remove and free. If only + * abut above, remove, modify, reinsert. + */ if (likely(iova + size)) { struct vfio_dma *tmp; - tmp = vfio_find_dma(iommu, iova + size, 1); if (tmp && tmp->prot == prot && tmp->vaddr == vaddr + size) { vfio_remove_dma(iommu, tmp); - if (dma) + if (dma) { dma->size += tmp->size; - else + kfree(tmp); + } else { size += tmp->size; - kfree(tmp); + tmp->size = size; + tmp->iova = iova; + tmp->vaddr = vaddr; + vfio_insert_dma(iommu, tmp); + dma = tmp; + } } } @@ -681,11 +687,10 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, iova = map->iova; size = map->size; while ((tmp = vfio_find_dma(iommu, iova, size))) { - if (vfio_remove_dma_overlap(iommu, iova, &size, tmp)) { - pr_warn("%s: Error rolling back failed map\n", - __func__); + int r = vfio_remove_dma_overlap(iommu, iova, + &size, tmp); + if (WARN_ON(r || !size)) break; - } } } @@ -813,6 +818,8 @@ static void vfio_iommu_type1_release(void *iommu_data) struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node); size_t size = dma->size; vfio_remove_dma_overlap(iommu, dma->iova, &size, dma); + if (WARN_ON(!size)) + break; } iommu_domain_free(iommu->domain); -- GitLab From 6d6768c61b39a2184bc11bb0342e4f7f35642bcc Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 25 Jun 2013 16:06:54 -0600 Subject: [PATCH 1834/2900] vfio: Limit group opens vfio_group_fops_open attempts to limit concurrent sessions by disallowing opens once group->container is set. This really doesn't do what we want and allow for inconsistent behavior, for instance a group can be opened twice, then a container set giving the user two file descriptors to the group. But then it won't allow more to be opened. There's not much reason to have the group opened multiple times since most access is through devices or the container, so complete what the original code intended and only allow a single instance. Signed-off-by: Alex Williamson --- drivers/vfio/vfio.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 6d78736563de..d30f44da8762 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -76,6 +76,7 @@ struct vfio_group { struct notifier_block nb; struct list_head vfio_next; struct list_head container_next; + atomic_t opened; }; struct vfio_device { @@ -206,6 +207,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) INIT_LIST_HEAD(&group->device_list); mutex_init(&group->device_lock); atomic_set(&group->container_users, 0); + atomic_set(&group->opened, 0); group->iommu_group = iommu_group; group->nb.notifier_call = vfio_iommu_group_notifier; @@ -1236,12 +1238,22 @@ static long vfio_group_fops_compat_ioctl(struct file *filep, static int vfio_group_fops_open(struct inode *inode, struct file *filep) { struct vfio_group *group; + int opened; group = vfio_group_get_from_minor(iminor(inode)); if (!group) return -ENODEV; + /* Do we need multiple instances of the group open? Seems not. */ + opened = atomic_cmpxchg(&group->opened, 0, 1); + if (opened) { + vfio_group_put(group); + return -EBUSY; + } + + /* Is something still in use from a previous open? */ if (group->container) { + atomic_dec(&group->opened); vfio_group_put(group); return -EBUSY; } @@ -1259,6 +1271,8 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep) vfio_group_try_dissolve_container(group); + atomic_dec(&group->opened); + vfio_group_put(group); return 0; -- GitLab From 819bc78f539038e3203f63342e20b75d7660d232 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 24 Jun 2013 13:21:48 +0200 Subject: [PATCH 1835/2900] netiucv: remove unused macro If someone is interested to dump something they may consider to use print_hex_dump() or print_hex_dump_bytes() kernel helpers. Signed-off-by: Andy Shevchenko Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/netiucv.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 9ca3996f65b2..279ad504ec3c 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -130,26 +130,6 @@ static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level) /** * some more debug stuff */ -#define IUCV_HEXDUMP16(importance,header,ptr) \ -PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ - "%02x %02x %02x %02x %02x %02x %02x %02x\n", \ - *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \ - *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \ - *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \ - *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \ - *(((char*)ptr)+12),*(((char*)ptr)+13), \ - *(((char*)ptr)+14),*(((char*)ptr)+15)); \ -PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ - "%02x %02x %02x %02x %02x %02x %02x %02x\n", \ - *(((char*)ptr)+16),*(((char*)ptr)+17), \ - *(((char*)ptr)+18),*(((char*)ptr)+19), \ - *(((char*)ptr)+20),*(((char*)ptr)+21), \ - *(((char*)ptr)+22),*(((char*)ptr)+23), \ - *(((char*)ptr)+24),*(((char*)ptr)+25), \ - *(((char*)ptr)+26),*(((char*)ptr)+27), \ - *(((char*)ptr)+28),*(((char*)ptr)+29), \ - *(((char*)ptr)+30),*(((char*)ptr)+31)); - #define PRINTK_HEADER " iucv: " /* for debugging */ /* dummy device to make sure netiucv_pm functions are called */ -- GitLab From fe44014a8287b372e22ef4daf7b682e6378b784f Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Mon, 24 Jun 2013 13:21:49 +0200 Subject: [PATCH 1836/2900] qeth: Increase default MTU for OSA devices Increase the default MTU for real OSA devices in layer 2 mode to 1500 Bytes for increased compatibility. Signed-off-by: Stefan Raspl Signed-off-by: Frank Blaschka Reviewed-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6cd0fc1b203a..f161a10a6579 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2198,11 +2198,11 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card) case QETH_LINK_TYPE_LANE_TR: return 2000; default: - return 1492; + return card->options.layer2 ? 1500 : 1492; } case QETH_CARD_TYPE_OSM: case QETH_CARD_TYPE_OSX: - return 1492; + return card->options.layer2 ? 1500 : 1492; default: return 1500; } @@ -2275,9 +2275,10 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, card->info.max_mtu = mtu; card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE; } else { - card->info.initial_mtu = qeth_get_initial_mtu_for_card(card); card->info.max_mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU( iob->data); + card->info.initial_mtu = min(card->info.max_mtu, + qeth_get_initial_mtu_for_card(card)); card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; } -- GitLab From a0c98523d7d71e0276f3cb127bc0c6d4fc85907a Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 24 Jun 2013 13:21:50 +0200 Subject: [PATCH 1837/2900] qeth: change default standard blkt settings for OSA blkt settings (or LAN idle settings) for an OSA Express card determine when and how often an OSA Express card tells the operating system about new incoming packets. The semantic of these settings has changed starting with OSA Express3. Currently the qeth standard settings apply to OSA Express2 and older generations of OSA Express cards, while new generations of OSA Express cards require extra coding of their reasonable default. To cover future OSA Express generations the qeth default standard blkt setting is now the desired setting for OSA generations starting with OSA Express3, while the fixed set of older OSA Express cards receives its blkt settings explicitly. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Reviewed-by: Stefan Raspl Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f161a10a6579..d7d036bf8715 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1729,14 +1729,14 @@ static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd) QETH_DBF_TEXT(SETUP, 2, "cfgblkt"); if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && - (prcd[76] == 0xF5 || prcd[76] == 0xF6)) { - card->info.blkt.time_total = 250; - card->info.blkt.inter_packet = 5; - card->info.blkt.inter_packet_jumbo = 15; - } else { + prcd[76] >= 0xF1 && prcd[76] <= 0xF4) { card->info.blkt.time_total = 0; card->info.blkt.inter_packet = 0; card->info.blkt.inter_packet_jumbo = 0; + } else { + card->info.blkt.time_total = 250; + card->info.blkt.inter_packet = 5; + card->info.blkt.inter_packet_jumbo = 15; } } -- GitLab From ede88671664128b811e7c709bead39f5b3f3abcf Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Mon, 24 Jun 2013 13:21:51 +0200 Subject: [PATCH 1838/2900] qeth: Fix crash on initial MTU size change When the initial MTU size is changed prior to any activity on the device (e.g. by attaching a z/VM vNIC already configured in Linux to a guestLAN), we call dev_kfree_skb_irq(NULL) which results in a kernel panic. Adding a proper check for NULL pointers to address this issue. Signed-off-by: Stefan Raspl Signed-off-by: Frank Blaschka Reviewed-by: Ursula Braun Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d7d036bf8715..e4ca70475190 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1282,8 +1282,10 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) qeth_free_cq(card); cancel_delayed_work_sync(&card->buffer_reclaim_work); - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) - dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb); + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { + if (card->qdio.in_q->bufs[j].rx_skb) + dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb); + } kfree(card->qdio.in_q); card->qdio.in_q = NULL; /* inbound buffer pool */ -- GitLab From 6541aa52a0f9911b0d9d9df14b1da3147a98f58b Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Mon, 24 Jun 2013 13:21:52 +0200 Subject: [PATCH 1839/2900] qeth: use default napi weight Since commit 82dc3c63c692b1e1d59378ecee948ac88e034aad "net: introduce NAPI_POLL_WEIGHT" network drivers receive a warning when they use napi weight higher than NAPI_POLL_WEIGHT. This patch reduces QETH_NAPI_WEIGHT from 128 to 64 (NAPI_POLL_WEIGHT). Signed-off-by: Sebastian Ott Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index c4f392d5db4c..41ef94320ee8 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -738,7 +738,7 @@ struct qeth_rx { int qdio_err; }; -#define QETH_NAPI_WEIGHT 128 +#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT struct qeth_card { struct list_head list; -- GitLab From 51151a16a60f0a886a0b1e4a0697001198af50c4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 23 Jun 2013 08:17:56 -0700 Subject: [PATCH 1840/2900] mlx4: allow order-0 memory allocations in RX path Signed-off-by: Eric Dumazet mlx4 exclusively uses order-2 allocations in RX path, which are likely to fail under memory pressure. We therefore drop frames more than needed. This patch tries order-3, order-2, order-1 and finally order-0 allocations to keep good performance, yet allow allocations if/when memory gets fragmented. By using larger pages, and avoiding unnecessary get_page()/put_page() on compound pages, this patch improves performance as well, lowering false sharing on struct page. Also use GFP_KERNEL allocations in initialization path, as allocating 12 MB (390 order-3 pages) can easily fail with GFP_ATOMIC. Signed-off-by: Eric Dumazet Cc: Amir Vadai Acked-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 169 ++++++++++--------- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 12 +- 2 files changed, 95 insertions(+), 86 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 9c57581b021c..76997b93fdfe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -43,40 +43,64 @@ #include "mlx4_en.h" +static int mlx4_alloc_pages(struct mlx4_en_priv *priv, + struct mlx4_en_rx_alloc *page_alloc, + const struct mlx4_en_frag_info *frag_info, + gfp_t _gfp) +{ + int order; + struct page *page; + dma_addr_t dma; + + for (order = MLX4_EN_ALLOC_PREFER_ORDER; ;) { + gfp_t gfp = _gfp; + + if (order) + gfp |= __GFP_COMP | __GFP_NOWARN; + page = alloc_pages(gfp, order); + if (likely(page)) + break; + if (--order < 0 || + ((PAGE_SIZE << order) < frag_info->frag_size)) + return -ENOMEM; + } + dma = dma_map_page(priv->ddev, page, 0, PAGE_SIZE << order, + PCI_DMA_FROMDEVICE); + if (dma_mapping_error(priv->ddev, dma)) { + put_page(page); + return -ENOMEM; + } + page_alloc->size = PAGE_SIZE << order; + page_alloc->page = page; + page_alloc->dma = dma; + page_alloc->offset = frag_info->frag_align; + /* Not doing get_page() for each frag is a big win + * on asymetric workloads. + */ + atomic_set(&page->_count, page_alloc->size / frag_info->frag_stride); + return 0; +} + static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv, struct mlx4_en_rx_desc *rx_desc, struct mlx4_en_rx_alloc *frags, - struct mlx4_en_rx_alloc *ring_alloc) + struct mlx4_en_rx_alloc *ring_alloc, + gfp_t gfp) { struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS]; - struct mlx4_en_frag_info *frag_info; + const struct mlx4_en_frag_info *frag_info; struct page *page; dma_addr_t dma; int i; for (i = 0; i < priv->num_frags; i++) { frag_info = &priv->frag_info[i]; - if (ring_alloc[i].offset == frag_info->last_offset) { - page = alloc_pages(GFP_ATOMIC | __GFP_COMP, - MLX4_EN_ALLOC_ORDER); - if (!page) - goto out; - dma = dma_map_page(priv->ddev, page, 0, - MLX4_EN_ALLOC_SIZE, PCI_DMA_FROMDEVICE); - if (dma_mapping_error(priv->ddev, dma)) { - put_page(page); - goto out; - } - page_alloc[i].page = page; - page_alloc[i].dma = dma; - page_alloc[i].offset = frag_info->frag_align; - } else { - page_alloc[i].page = ring_alloc[i].page; - get_page(ring_alloc[i].page); - page_alloc[i].dma = ring_alloc[i].dma; - page_alloc[i].offset = ring_alloc[i].offset + - frag_info->frag_stride; - } + page_alloc[i] = ring_alloc[i]; + page_alloc[i].offset += frag_info->frag_stride; + if (page_alloc[i].offset + frag_info->frag_stride <= ring_alloc[i].size) + continue; + if (mlx4_alloc_pages(priv, &page_alloc[i], frag_info, gfp)) + goto out; } for (i = 0; i < priv->num_frags; i++) { @@ -88,14 +112,16 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv, return 0; - out: while (i--) { frag_info = &priv->frag_info[i]; - if (ring_alloc[i].offset == frag_info->last_offset) + if (page_alloc[i].page != ring_alloc[i].page) { dma_unmap_page(priv->ddev, page_alloc[i].dma, - MLX4_EN_ALLOC_SIZE, PCI_DMA_FROMDEVICE); - put_page(page_alloc[i].page); + page_alloc[i].size, PCI_DMA_FROMDEVICE); + page = page_alloc[i].page; + atomic_set(&page->_count, 1); + put_page(page); + } } return -ENOMEM; } @@ -104,12 +130,12 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, struct mlx4_en_rx_alloc *frags, int i) { - struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; - if (frags[i].offset == frag_info->last_offset) { - dma_unmap_page(priv->ddev, frags[i].dma, MLX4_EN_ALLOC_SIZE, + if (frags[i].offset + frag_info->frag_stride > frags[i].size) + dma_unmap_page(priv->ddev, frags[i].dma, frags[i].size, PCI_DMA_FROMDEVICE); - } + if (frags[i].page) put_page(frags[i].page); } @@ -117,35 +143,28 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring) { - struct mlx4_en_rx_alloc *page_alloc; int i; + struct mlx4_en_rx_alloc *page_alloc; for (i = 0; i < priv->num_frags; i++) { - page_alloc = &ring->page_alloc[i]; - page_alloc->page = alloc_pages(GFP_ATOMIC | __GFP_COMP, - MLX4_EN_ALLOC_ORDER); - if (!page_alloc->page) - goto out; + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; - page_alloc->dma = dma_map_page(priv->ddev, page_alloc->page, 0, - MLX4_EN_ALLOC_SIZE, PCI_DMA_FROMDEVICE); - if (dma_mapping_error(priv->ddev, page_alloc->dma)) { - put_page(page_alloc->page); - page_alloc->page = NULL; + if (mlx4_alloc_pages(priv, &ring->page_alloc[i], + frag_info, GFP_KERNEL)) goto out; - } - page_alloc->offset = priv->frag_info[i].frag_align; - en_dbg(DRV, priv, "Initialized allocator:%d with page:%p\n", - i, page_alloc->page); } return 0; out: while (i--) { + struct page *page; + page_alloc = &ring->page_alloc[i]; dma_unmap_page(priv->ddev, page_alloc->dma, - MLX4_EN_ALLOC_SIZE, PCI_DMA_FROMDEVICE); - put_page(page_alloc->page); + page_alloc->size, PCI_DMA_FROMDEVICE); + page = page_alloc->page; + atomic_set(&page->_count, 1); + put_page(page); page_alloc->page = NULL; } return -ENOMEM; @@ -158,13 +177,18 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv, int i; for (i = 0; i < priv->num_frags; i++) { + const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; + page_alloc = &ring->page_alloc[i]; en_dbg(DRV, priv, "Freeing allocator:%d count:%d\n", i, page_count(page_alloc->page)); dma_unmap_page(priv->ddev, page_alloc->dma, - MLX4_EN_ALLOC_SIZE, PCI_DMA_FROMDEVICE); - put_page(page_alloc->page); + page_alloc->size, PCI_DMA_FROMDEVICE); + while (page_alloc->offset + frag_info->frag_stride < page_alloc->size) { + put_page(page_alloc->page); + page_alloc->offset += frag_info->frag_stride; + } page_alloc->page = NULL; } } @@ -195,13 +219,14 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv, } static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv, - struct mlx4_en_rx_ring *ring, int index) + struct mlx4_en_rx_ring *ring, int index, + gfp_t gfp) { struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride); struct mlx4_en_rx_alloc *frags = ring->rx_info + (index << priv->log_rx_info); - return mlx4_en_alloc_frags(priv, rx_desc, frags, ring->page_alloc); + return mlx4_en_alloc_frags(priv, rx_desc, frags, ring->page_alloc, gfp); } static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring) @@ -235,7 +260,8 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv) ring = &priv->rx_ring[ring_ind]; if (mlx4_en_prepare_rx_desc(priv, ring, - ring->actual_size)) { + ring->actual_size, + GFP_KERNEL)) { if (ring->actual_size < MLX4_EN_MIN_RX_SIZE) { en_err(priv, "Failed to allocate " "enough rx buffers\n"); @@ -450,11 +476,11 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, DMA_FROM_DEVICE); /* Save page reference in skb */ - get_page(frags[nr].page); __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size); skb_frags_rx[nr].page_offset = frags[nr].offset; skb->truesize += frag_info->frag_stride; + frags[nr].page = NULL; } /* Adjust size of last fragment to match actual length */ if (nr > 0) @@ -547,7 +573,7 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv, int index = ring->prod & ring->size_mask; while ((u32) (ring->prod - ring->cons) < ring->actual_size) { - if (mlx4_en_prepare_rx_desc(priv, ring, index)) + if (mlx4_en_prepare_rx_desc(priv, ring, index, GFP_ATOMIC)) break; ring->prod++; index = ring->prod & ring->size_mask; @@ -805,21 +831,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget) return done; } - -/* Calculate the last offset position that accommodates a full fragment - * (assuming fagment size = stride-align) */ -static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align) -{ - u16 res = MLX4_EN_ALLOC_SIZE % stride; - u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align; - - en_dbg(DRV, priv, "Calculated last offset for stride:%d align:%d " - "res:%d offset:%d\n", stride, align, res, offset); - return offset; -} - - -static int frag_sizes[] = { +static const int frag_sizes[] = { FRAG_SZ0, FRAG_SZ1, FRAG_SZ2, @@ -847,9 +859,6 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) priv->frag_info[i].frag_stride = ALIGN(frag_sizes[i], SMP_CACHE_BYTES); } - priv->frag_info[i].last_offset = mlx4_en_last_alloc_offset( - priv, priv->frag_info[i].frag_stride, - priv->frag_info[i].frag_align); buf_size += priv->frag_info[i].frag_size; i++; } @@ -861,13 +870,13 @@ void mlx4_en_calc_rx_buf(struct net_device *dev) en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d " "num_frags:%d):\n", eff_mtu, priv->num_frags); for (i = 0; i < priv->num_frags; i++) { - en_dbg(DRV, priv, " frag:%d - size:%d prefix:%d align:%d " - "stride:%d last_offset:%d\n", i, - priv->frag_info[i].frag_size, - priv->frag_info[i].frag_prefix_size, - priv->frag_info[i].frag_align, - priv->frag_info[i].frag_stride, - priv->frag_info[i].last_offset); + en_err(priv, + " frag:%d - size:%d prefix:%d align:%d stride:%d\n", + i, + priv->frag_info[i].frag_size, + priv->frag_info[i].frag_prefix_size, + priv->frag_info[i].frag_align, + priv->frag_info[i].frag_stride); } } diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 57192a8f1d5e..35fb60e2320c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -96,7 +96,8 @@ /* Use the maximum between 16384 and a single page */ #define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384) -#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE) + +#define MLX4_EN_ALLOC_PREFER_ORDER PAGE_ALLOC_COSTLY_ORDER /* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU * and 4K allocations) */ @@ -234,9 +235,10 @@ struct mlx4_en_tx_desc { #define MLX4_EN_CX3_HIGH_ID 0x1005 struct mlx4_en_rx_alloc { - struct page *page; - dma_addr_t dma; - u16 offset; + struct page *page; + dma_addr_t dma; + u32 offset; + u32 size; }; struct mlx4_en_tx_ring { @@ -439,8 +441,6 @@ struct mlx4_en_frag_info { u16 frag_prefix_size; u16 frag_stride; u16 frag_align; - u16 last_offset; - }; #ifdef CONFIG_MLX4_EN_DCB -- GitLab From b7b1bfce0bb68bd8f6e62a28295922785cc63781 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Sun, 23 Jun 2013 18:39:01 +0200 Subject: [PATCH 1841/2900] ipv6: split duplicate address detection and router solicitation timer This patch splits the timers for duplicate address detection and router solicitations apart. The router solicitations timer goes into inet6_dev and the dad timer stays in inet6_ifaddr. The reason behind this patch is to reduce the number of unneeded router solicitations send out by the host if additional link-local addresses are created. Currently we send out RS for every link-local address on an interface. If the RS timer fires we pick a source address with ipv6_get_lladdr. This change could hurt people adding additional link-local addresses and specifying these addresses in the radvd clients section because we no longer guarantee that we use every ll address as source address in router solicitations. Cc: Flavio Leitner Cc: Hideaki YOSHIFUJI Cc: David Stevens Signed-off-by: Hannes Frederic Sowa Reviewed-by: Flavio Leitner Signed-off-by: David S. Miller --- include/net/if_inet6.h | 8 +- net/ipv6/addrconf.c | 164 +++++++++++++++++++++++------------------ 2 files changed, 97 insertions(+), 75 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index e07feb456d19..e4c5a2d2ba34 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -50,7 +50,7 @@ struct inet6_ifaddr { int state; - __u8 probes; + __u8 dad_probes; __u8 flags; __u16 scope; @@ -58,7 +58,7 @@ struct inet6_ifaddr { unsigned long cstamp; /* created timestamp */ unsigned long tstamp; /* updated timestamp */ - struct timer_list timer; + struct timer_list dad_timer; struct inet6_dev *idev; struct rt6_info *rt; @@ -195,6 +195,10 @@ struct inet6_dev { struct neigh_parms *nd_parms; struct ipv6_devconf cnf; struct ipv6_devstat stats; + + struct timer_list rs_timer; + __u8 rs_probes; + unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ struct rcu_head rcu; }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 90788a1c6bbc..c06bc76280b2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -253,37 +253,32 @@ static inline bool addrconf_qdisc_ok(const struct net_device *dev) return !qdisc_tx_is_noop(dev); } -static void addrconf_del_timer(struct inet6_ifaddr *ifp) +static void addrconf_del_rs_timer(struct inet6_dev *idev) { - if (del_timer(&ifp->timer)) + if (del_timer(&idev->rs_timer)) + __in6_dev_put(idev); +} + +static void addrconf_del_dad_timer(struct inet6_ifaddr *ifp) +{ + if (del_timer(&ifp->dad_timer)) __in6_ifa_put(ifp); } -enum addrconf_timer_t { - AC_NONE, - AC_DAD, - AC_RS, -}; +static void addrconf_mod_rs_timer(struct inet6_dev *idev, + unsigned long when) +{ + if (!timer_pending(&idev->rs_timer)) + in6_dev_hold(idev); + mod_timer(&idev->rs_timer, jiffies + when); +} -static void addrconf_mod_timer(struct inet6_ifaddr *ifp, - enum addrconf_timer_t what, - unsigned long when) +static void addrconf_mod_dad_timer(struct inet6_ifaddr *ifp, + unsigned long when) { - if (!del_timer(&ifp->timer)) + if (!timer_pending(&ifp->dad_timer)) in6_ifa_hold(ifp); - - switch (what) { - case AC_DAD: - ifp->timer.function = addrconf_dad_timer; - break; - case AC_RS: - ifp->timer.function = addrconf_rs_timer; - break; - default: - break; - } - ifp->timer.expires = jiffies + when; - add_timer(&ifp->timer); + mod_timer(&ifp->dad_timer, jiffies + when); } static int snmp6_alloc_dev(struct inet6_dev *idev) @@ -326,6 +321,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) WARN_ON(!list_empty(&idev->addr_list)); WARN_ON(idev->mc_list != NULL); + WARN_ON(timer_pending(&idev->rs_timer)); #ifdef NET_REFCNT_DEBUG pr_debug("%s: %s\n", __func__, dev ? dev->name : "NIL"); @@ -357,7 +353,8 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) rwlock_init(&ndev->lock); ndev->dev = dev; INIT_LIST_HEAD(&ndev->addr_list); - + setup_timer(&ndev->rs_timer, addrconf_rs_timer, + (unsigned long)ndev); memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); ndev->cnf.mtu6 = dev->mtu; ndev->cnf.sysctl = NULL; @@ -776,7 +773,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) in6_dev_put(ifp->idev); - if (del_timer(&ifp->timer)) + if (del_timer(&ifp->dad_timer)) pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); if (ifp->state != INET6_IFADDR_STATE_DEAD) { @@ -869,9 +866,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, spin_lock_init(&ifa->lock); spin_lock_init(&ifa->state_lock); - init_timer(&ifa->timer); + setup_timer(&ifa->dad_timer, addrconf_dad_timer, + (unsigned long)ifa); INIT_HLIST_NODE(&ifa->addr_lst); - ifa->timer.data = (unsigned long) ifa; ifa->scope = scope; ifa->prefix_len = pfxlen; ifa->flags = flags | IFA_F_TENTATIVE; @@ -994,7 +991,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) } write_unlock_bh(&idev->lock); - addrconf_del_timer(ifp); + addrconf_del_dad_timer(ifp); ipv6_ifa_notify(RTM_DELADDR, ifp); @@ -1447,6 +1444,23 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, } EXPORT_SYMBOL(ipv6_dev_get_saddr); +static int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, + unsigned char banned_flags) +{ + struct inet6_ifaddr *ifp; + int err = -EADDRNOTAVAIL; + + list_for_each_entry(ifp, &idev->addr_list, if_list) { + if (ifp->scope == IFA_LINK && + !(ifp->flags & banned_flags)) { + *addr = ifp->addr; + err = 0; + break; + } + } + return err; +} + int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags) { @@ -1456,17 +1470,8 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, rcu_read_lock(); idev = __in6_dev_get(dev); if (idev) { - struct inet6_ifaddr *ifp; - read_lock_bh(&idev->lock); - list_for_each_entry(ifp, &idev->addr_list, if_list) { - if (ifp->scope == IFA_LINK && - !(ifp->flags & banned_flags)) { - *addr = ifp->addr; - err = 0; - break; - } - } + err = __ipv6_get_lladdr(idev, addr, banned_flags); read_unlock_bh(&idev->lock); } rcu_read_unlock(); @@ -1580,7 +1585,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) { if (ifp->flags&IFA_F_PERMANENT) { spin_lock_bh(&ifp->lock); - addrconf_del_timer(ifp); + addrconf_del_dad_timer(ifp); ifp->flags |= IFA_F_TENTATIVE; if (dad_failed) ifp->flags |= IFA_F_DADFAILED; @@ -3036,7 +3041,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) hlist_for_each_entry_rcu(ifa, h, addr_lst) { if (ifa->idev == idev) { hlist_del_init_rcu(&ifa->addr_lst); - addrconf_del_timer(ifa); + addrconf_del_dad_timer(ifa); goto restart; } } @@ -3045,6 +3050,8 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_lock_bh(&idev->lock); + addrconf_del_rs_timer(idev); + /* Step 2: clear flags for stateless addrconf */ if (!how) idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); @@ -3074,7 +3081,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) while (!list_empty(&idev->addr_list)) { ifa = list_first_entry(&idev->addr_list, struct inet6_ifaddr, if_list); - addrconf_del_timer(ifa); + addrconf_del_dad_timer(ifa); list_del(&ifa->if_list); @@ -3116,10 +3123,10 @@ static int addrconf_ifdown(struct net_device *dev, int how) static void addrconf_rs_timer(unsigned long data) { - struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; - struct inet6_dev *idev = ifp->idev; + struct inet6_dev *idev = (struct inet6_dev *)data; + struct in6_addr lladdr; - read_lock(&idev->lock); + write_lock(&idev->lock); if (idev->dead || !(idev->if_flags & IF_READY)) goto out; @@ -3130,18 +3137,19 @@ static void addrconf_rs_timer(unsigned long data) if (idev->if_flags & IF_RA_RCVD) goto out; - spin_lock(&ifp->lock); - if (ifp->probes++ < idev->cnf.rtr_solicits) { - /* The wait after the last probe can be shorter */ - addrconf_mod_timer(ifp, AC_RS, - (ifp->probes == idev->cnf.rtr_solicits) ? - idev->cnf.rtr_solicit_delay : - idev->cnf.rtr_solicit_interval); - spin_unlock(&ifp->lock); + if (idev->rs_probes++ < idev->cnf.rtr_solicits) { + if (!__ipv6_get_lladdr(idev, &lladdr, IFA_F_TENTATIVE)) + ndisc_send_rs(idev->dev, &lladdr, + &in6addr_linklocal_allrouters); + else + goto out; - ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); + /* The wait after the last probe can be shorter */ + addrconf_mod_rs_timer(idev, (idev->rs_probes == + idev->cnf.rtr_solicits) ? + idev->cnf.rtr_solicit_delay : + idev->cnf.rtr_solicit_interval); } else { - spin_unlock(&ifp->lock); /* * Note: we do not support deprecated "all on-link" * assumption any longer. @@ -3150,8 +3158,8 @@ static void addrconf_rs_timer(unsigned long data) } out: - read_unlock(&idev->lock); - in6_ifa_put(ifp); + write_unlock(&idev->lock); + in6_dev_put(idev); } /* @@ -3167,8 +3175,8 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) else rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); - ifp->probes = idev->cnf.dad_transmits; - addrconf_mod_timer(ifp, AC_DAD, rand_num); + ifp->dad_probes = idev->cnf.dad_transmits; + addrconf_mod_dad_timer(ifp, rand_num); } static void addrconf_dad_start(struct inet6_ifaddr *ifp) @@ -3229,40 +3237,40 @@ static void addrconf_dad_timer(unsigned long data) struct inet6_dev *idev = ifp->idev; struct in6_addr mcaddr; - if (!ifp->probes && addrconf_dad_end(ifp)) + if (!ifp->dad_probes && addrconf_dad_end(ifp)) goto out; - read_lock(&idev->lock); + write_lock(&idev->lock); if (idev->dead || !(idev->if_flags & IF_READY)) { - read_unlock(&idev->lock); + write_unlock(&idev->lock); goto out; } spin_lock(&ifp->lock); if (ifp->state == INET6_IFADDR_STATE_DEAD) { spin_unlock(&ifp->lock); - read_unlock(&idev->lock); + write_unlock(&idev->lock); goto out; } - if (ifp->probes == 0) { + if (ifp->dad_probes == 0) { /* * DAD was successful */ ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); spin_unlock(&ifp->lock); - read_unlock(&idev->lock); + write_unlock(&idev->lock); addrconf_dad_completed(ifp); goto out; } - ifp->probes--; - addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); + ifp->dad_probes--; + addrconf_mod_dad_timer(ifp, ifp->idev->nd_parms->retrans_time); spin_unlock(&ifp->lock); - read_unlock(&idev->lock); + write_unlock(&idev->lock); /* send a neighbour solicitation for our addr */ addrconf_addr_solict_mult(&ifp->addr, &mcaddr); @@ -3274,6 +3282,9 @@ static void addrconf_dad_timer(unsigned long data) static void addrconf_dad_completed(struct inet6_ifaddr *ifp) { struct net_device *dev = ifp->idev->dev; + struct in6_addr lladdr; + + addrconf_del_dad_timer(ifp); /* * Configure the address for reception. Now it is valid. @@ -3294,13 +3305,20 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) * [...] as part of DAD [...] there is no need * to delay again before sending the first RS */ - ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); + if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE)) + ndisc_send_rs(dev, &lladdr, + &in6addr_linklocal_allrouters); + else + return; - spin_lock_bh(&ifp->lock); - ifp->probes = 1; + write_lock_bh(&ifp->idev->lock); + spin_lock(&ifp->lock); + ifp->idev->rs_probes = 1; ifp->idev->if_flags |= IF_RS_SENT; - addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval); - spin_unlock_bh(&ifp->lock); + addrconf_mod_rs_timer(ifp->idev, + ifp->idev->cnf.rtr_solicit_interval); + spin_unlock(&ifp->lock); + write_unlock_bh(&ifp->idev->lock); } } -- GitLab From 876fd05ddbae03166e7037fca957b55bb3be6594 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 24 Jun 2013 00:22:20 +0200 Subject: [PATCH 1842/2900] ipv6: don't disable interface if last ipv6 address is removed The reason behind this change is that as soon as we delete the last ipv6 address of an interface we also lose the /proc/sys/net/ipv6/conf/ directory. This seems to be a usability problem for me. I don't see any reason why we should shutdown ipv6 on that interface in such cases. Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c06bc76280b2..e799a8838ed0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2507,12 +2507,6 @@ static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *p read_unlock_bh(&idev->lock); ipv6_del_addr(ifp); - - /* If the last address is deleted administratively, - disable IPv6 on this interface. - */ - if (list_empty(&idev->addr_list)) - addrconf_ifdown(idev->dev, 1); return 0; } } -- GitLab From 2b9651d72d3fc1a9053ae1a323f8407e1f63b436 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 24 Jun 2013 22:03:28 +0200 Subject: [PATCH 1843/2900] ipv6: remove old token ipv6 address as soon as possible If the tokenized ip address is re-set on an interface we depend on the arrival of a new router advertisment to call addrconf_verify to clean up the old address (which valid_lft is now set to 0). Old addresses can linger around for a longer time if e.g. the source of router advertisments vanishes. So, call addrconf_verify immediately after setting the new tokenized address to get rid of the old tokenized addresses. Cc: Daniel Borkmann Signed-off-by: Hannes Frederic Sowa Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e799a8838ed0..afaf3cdadf58 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4375,6 +4375,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) } write_unlock_bh(&idev->lock); + addrconf_verify(0); return 0; } -- GitLab From 8850494a33cc67bbf31d2e3ce630d0f4e14efa56 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Tue, 25 Jun 2013 12:09:29 +0300 Subject: [PATCH 1844/2900] net/mlx4_en: Fix resource leak in error flow Wrong condition was used when calling iounmap. Signed-off-by: Dotan Barak Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index a5c9df07a7d0..a071cda2dd04 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -310,7 +310,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev) err_mr: (void) mlx4_mr_free(dev, &mdev->mr); err_map: - if (!mdev->uar_map) + if (mdev->uar_map) iounmap(mdev->uar_map); err_uar: mlx4_uar_free(dev, &mdev->priv_uar); -- GitLab From 6123db2ec529f1d1865298388e129a6aad2fae17 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 25 Jun 2013 12:09:30 +0300 Subject: [PATCH 1845/2900] net/mlx4_en: Do not query stats when device port is down There are no counters allocated to the eth device when the port is down, so this query is meaningless at that time. It also leads to querying incorrect counters (since the counter_index is not valid when the device port is down). Signed-off-by: Jack Morgenstein Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 7299ada876c2..c0b02d7bcc2f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1375,12 +1375,13 @@ static void mlx4_en_do_get_stats(struct work_struct *work) mutex_lock(&mdev->state_lock); if (mdev->device_up) { - err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0); - if (err) - en_dbg(HW, priv, "Could not update stats\n"); + if (priv->port_up) { + err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0); + if (err) + en_dbg(HW, priv, "Could not update stats\n"); - if (priv->port_up) mlx4_en_auto_moderation(priv); + } queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); } -- GitLab From 4801ae70d80dc815997e3cb6bca1dfe36d1594fd Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Tue, 25 Jun 2013 12:09:31 +0300 Subject: [PATCH 1846/2900] net/mlx4_en: Move register_netdev() to the end of initialization function To avoid a race between the open function and everything that happens after register_netdev() move it to be the last operation called. Signed-off-by: Eugenia Emantayev Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index c0b02d7bcc2f..1f0f8170d79d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2323,6 +2323,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, mdev->pndev[port] = dev; netif_carrier_off(dev); + mlx4_en_set_default_moderation(priv); + err = register_netdev(dev); if (err) { en_err(priv, "Netdev registration failed for port %d\n", port); @@ -2354,7 +2356,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, en_err(priv, "Failed Initializing port\n"); goto out; } - mlx4_en_set_default_moderation(priv); queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) -- GitLab From 9e19b54554fac0a1c1c92f0a10b29d216b84a470 Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Tue, 25 Jun 2013 12:09:32 +0300 Subject: [PATCH 1847/2900] net/mlx4_en: Change log level from error to debug for vlan related messages The port vlan table size is 126 (used for IBoE) so after 126 we will not have space and the user need to see it only in debug print and not error. Signed-off-by: Aviad Yehezkel Reviewed-by: Yevgeny Petrilin Signed-off-by: Eugenia Emantayev Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 1f0f8170d79d..f256a734e021 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -405,7 +405,7 @@ static int mlx4_en_vlan_rx_add_vid(struct net_device *dev, en_err(priv, "Failed configuring VLAN filter\n"); } if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx)) - en_err(priv, "failed adding vlan %d\n", vid); + en_dbg(HW, priv, "failed adding vlan %d\n", vid); mutex_unlock(&mdev->state_lock); return 0; @@ -428,7 +428,7 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx)) mlx4_unregister_vlan(mdev->dev, priv->port, idx); else - en_err(priv, "could not find vid %d in cache\n", vid); + en_dbg(HW, priv, "could not find vid %d in cache\n", vid); if (mdev->device_up && priv->port_up) { err = mlx4_SET_VLAN_FLTR(mdev->dev, priv); -- GitLab From 0cc5c8bf11852dec3225fda2f53a599243095d23 Mon Sep 17 00:00:00 2001 From: Eugenia Emantayev Date: Tue, 25 Jun 2013 12:09:33 +0300 Subject: [PATCH 1848/2900] net/mlx4_en: Fix a race between napi poll function and RX ring cleanup The RX rings were cleaned while there was still possible RX traffic completion handling. Change the sequance of events so that the port is closed and the QPs are being stopped before RX cleanup. Signed-off-by: Eugenia Emantayev Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f256a734e021..f1dcddcb8050 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1635,6 +1635,9 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) return; } + /* close port*/ + mlx4_CLOSE_PORT(mdev->dev, priv->port); + /* Synchronize with tx routine */ netif_tx_lock_bh(dev); if (detach) @@ -1735,14 +1738,11 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) } local_bh_enable(); - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); while (test_bit(NAPI_STATE_SCHED, &cq->napi.state)) msleep(1); + mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); mlx4_en_deactivate_cq(priv, cq); } - - /* close port*/ - mlx4_CLOSE_PORT(mdev->dev, priv->port); } static void mlx4_en_restart(struct work_struct *work) -- GitLab From b944ebec787be9396978b0f7773f99e751330196 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Tue, 25 Jun 2013 12:09:34 +0300 Subject: [PATCH 1849/2900] net/mlx4_en: Add prints when TX timeout occurs Print a warning when a TX timeout is detected Signed-off-by: Yevgeny Petrilin Signed-off-by: Eugenia Emantayev Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f1dcddcb8050..caf204770569 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1236,10 +1236,19 @@ static void mlx4_en_tx_timeout(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; + int i; if (netif_msg_timer(priv)) en_warn(priv, "Tx timeout called on port:%d\n", priv->port); + for (i = 0; i < priv->tx_ring_num; i++) { + if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, i))) + continue; + en_warn(priv, "TX timeout on queue: %d, QP: 0x%x, CQ: 0x%x, Cons: 0x%x, Prod: 0x%x\n", + i, priv->tx_ring[i].qpn, priv->tx_ring[i].cqn, + priv->tx_ring[i].cons, priv->tx_ring[i].prod); + } + priv->port_stats.tx_timeout++; en_dbg(DRV, priv, "Scheduling watchdog\n"); queue_work(mdev->workqueue, &priv->watchdog_task); -- GitLab From 42f1e9020e22d64d18292c6cb9182f4beeb43cad Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Tue, 25 Jun 2013 12:09:35 +0300 Subject: [PATCH 1850/2900] net/mlx4_en: Remove an unnecessary test Since this variable is now part of a structure and not allocated dynamically, this test is irrelevant now. Signed-off-by: Dotan Barak Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c index 0f91222ea3d7..9d4a1ea030d8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c @@ -207,9 +207,6 @@ static int mlx4_en_dcbnl_ieee_getmaxrate(struct net_device *dev, struct mlx4_en_priv *priv = netdev_priv(dev); int i; - if (!priv->maxrate) - return -EINVAL; - for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) maxrate->tc_maxrate[i] = priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB; -- GitLab From 618fad954b9becf095f1b52391af29f743ff4662 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Tue, 25 Jun 2013 12:09:36 +0300 Subject: [PATCH 1851/2900] net/mlx4_core: Replace sscanf() with kstrtoint() It is not safe to use sscanf. Signed-off-by: Dotan Barak Signed-off-by: Vladimir Sokolovsky Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 2f4a26039e80..81e4529092a3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -839,11 +839,11 @@ static ssize_t set_port_ib_mtu(struct device *dev, return -EINVAL; } - err = sscanf(buf, "%d", &mtu); - if (err > 0) + err = kstrtoint(buf, 0, &mtu); + if (!err) ibta_mtu = int_to_ibta_mtu(mtu); - if (err <= 0 || ibta_mtu < 0) { + if (err || ibta_mtu < 0) { mlx4_err(mdev, "%s is invalid IBTA mtu\n", buf); return -EINVAL; } -- GitLab From 674925edb466b027d7c61993ebe3250fb8989ee0 Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Tue, 25 Jun 2013 12:09:37 +0300 Subject: [PATCH 1852/2900] net/mlx4_core: Add warning in case of command timeouts Warning prints when there are command timeout to help debugging future failures. Signed-off-by: Dotan Barak Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index ea1e03896353..df04c8206ebe 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -257,6 +257,8 @@ static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op, if (!wait_for_completion_timeout(&context->done, msecs_to_jiffies(timeout))) { + mlx4_warn(dev, "communication channel command 0x%x timed out\n", + op); err = -EBUSY; goto out; } @@ -486,6 +488,8 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, } if (cmd_pending(dev)) { + mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", + op); err = -ETIMEDOUT; goto out; } @@ -549,6 +553,8 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, if (!wait_for_completion_timeout(&context->done, msecs_to_jiffies(timeout))) { + mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", + op); err = -EBUSY; goto out; } -- GitLab From 30e514a71753ac3fd0ddea1411d5602ccbe14acf Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 25 Jun 2013 12:09:38 +0300 Subject: [PATCH 1853/2900] net/mlx4_core: Fail device init if num_vfs is negative Should not allow negative num_vfs Signed-off-by: Jack Morgenstein Signed-off-by: Vladimir Sokolovsky Signed-off-by: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 81e4529092a3..56160a2bb57b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2077,6 +2077,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data) num_vfs, MLX4_MAX_NUM_VF); return -EINVAL; } + + if (num_vfs < 0) { + pr_err("num_vfs module parameter cannot be negative\n"); + return -EINVAL; + } /* * Check for BARs. */ -- GitLab From f072d7aba79c73c3bb4ff1a9b58be5525d755d27 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:25 +0200 Subject: [PATCH 1854/2900] net: sctp: remove TEST_FRAME ifdef We do neither ship a test_frame.h, nor will this be compatible with the 2.5 out-of-tree lksctp kernel test suite anyway. So remove this artefact. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 6321c081118f..15214a825f92 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -188,11 +188,6 @@ extern struct kmem_cache *sctp_bucket_cachep __read_mostly; * Section: Macros, externs, and inlines */ - -#ifdef TEST_FRAME -#include -#else - /* spin lock wrappers. */ #define sctp_spin_lock_irqsave(lock, flags) spin_lock_irqsave(lock, flags) #define sctp_spin_unlock_irqrestore(lock, flags) \ @@ -218,8 +213,6 @@ extern struct kmem_cache *sctp_bucket_cachep __read_mostly; #define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field) #define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) -#endif /* !TEST_FRAME */ - /* sctp mib definitions */ enum { SCTP_MIB_NUM = 0, -- GitLab From d36f82b2435690d8742235d7bdc5bb5e878077e3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:26 +0200 Subject: [PATCH 1855/2900] ktime: add ms_to_ktime() and ktime_add_ms() helpers Add two ktime helper functions that i) convert a given msec value to a ktime structure and ii) that adds a msec value to a ktime structure. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/linux/ktime.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/ktime.h b/include/linux/ktime.h index bbca12804d12..b4fa5e4cd158 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -323,6 +323,11 @@ static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec) return ktime_add_ns(kt, usec * 1000); } +static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec) +{ + return ktime_add_ns(kt, msec * NSEC_PER_MSEC); +} + static inline ktime_t ktime_sub_us(const ktime_t kt, const u64 usec) { return ktime_sub_ns(kt, usec * 1000); @@ -366,7 +371,15 @@ extern void ktime_get_ts(struct timespec *ts); static inline ktime_t ns_to_ktime(u64 ns) { static const ktime_t ktime_zero = { .tv64 = 0 }; + return ktime_add_ns(ktime_zero, ns); } +static inline ktime_t ms_to_ktime(u64 ms) +{ + static const ktime_t ktime_zero = { .tv64 = 0 }; + + return ktime_add_ms(ktime_zero, ms); +} + #endif -- GitLab From 52db882f3fc2903014e638ee91e690085fe37fdb Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:27 +0200 Subject: [PATCH 1856/2900] net: sctp: migrate cookie life from timeval to ktime Currently, SCTP code defines its own timeval functions (since timeval is rarely used inside the kernel by others), namely tv_lt() and TIMEVAL_ADD() macros, that operate on SCTP cookie expiration. We might as well remove all those, and operate directly on ktime structures for a couple of reasons: ktime is available on all archs; complexity of ktime calculations depending on the arch is less than (reduces to a simple arithmetic operations on archs with BITS_PER_LONG == 64 or CONFIG_KTIME_SCALAR) or equal to timeval functions (other archs); code becomes more readable; macros can be thrown out. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 18 ------------------ include/net/sctp/structs.h | 6 +++--- net/sctp/associola.c | 8 +------- net/sctp/sm_make_chunk.c | 19 ++++++++----------- net/sctp/socket.c | 14 +++----------- 5 files changed, 15 insertions(+), 50 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 15214a825f92..e6b95bc4d8e6 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -560,24 +560,6 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\ /* Round an int up to the next multiple of 4. */ #define WORD_ROUND(s) (((s)+3)&~3) -/* Compare two timevals. */ -#define tv_lt(s, t) \ - (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec)) - -/* Add tv1 to tv2. */ -#define TIMEVAL_ADD(tv1, tv2) \ -({ \ - suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \ - time_t secs = (tv2).tv_sec + (tv1).tv_sec; \ -\ - if (usecs >= 1000000) { \ - usecs -= 1000000; \ - secs++; \ - } \ - (tv2).tv_sec = secs; \ - (tv2).tv_usec = usecs; \ -}) - /* External references. */ extern struct proto sctp_prot; diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 1bd4c4144fe8..e745c92a1532 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -54,7 +54,7 @@ #ifndef __sctp_structs_h__ #define __sctp_structs_h__ -#include /* We get struct timespec. */ +#include #include /* linux/in.h needs this!! */ #include /* We get struct sockaddr_in. */ #include /* We get struct in6_addr */ @@ -284,7 +284,7 @@ struct sctp_cookie { __u32 peer_ttag; /* When does this cookie expire? */ - struct timeval expiration; + ktime_t expiration; /* Number of inbound/outbound streams which are set * and negotiated during the INIT process. @@ -1537,7 +1537,7 @@ struct sctp_association { sctp_state_t state; /* The cookie life I award for any cookie. */ - struct timeval cookie_life; + ktime_t cookie_life; /* Overall : The overall association error count. * Error Count : [Clear this any time I get something.] diff --git a/net/sctp/associola.c b/net/sctp/associola.c index bf6e6bd553c0..9a383a8774e8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -102,13 +102,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port); asoc->state = SCTP_STATE_CLOSED; - - /* Set these values from the socket values, a conversion between - * millsecons to seconds/microseconds must also be done. - */ - asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000; - asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000) - * 1000; + asoc->cookie_life = ms_to_ktime(sp->assocparams.sasoc_cookie_life); asoc->frag_point = 0; asoc->user_frag = sp->user_frag; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index fc8548743ed5..dd71f1f9ba10 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1630,8 +1630,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, cookie->c.adaptation_ind = asoc->peer.adaptation_ind; /* Set an expiration time for the cookie. */ - do_gettimeofday(&cookie->c.expiration); - TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration); + cookie->c.expiration = ktime_add(asoc->cookie_life, + ktime_get()); /* Copy the peer's init packet. */ memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr, @@ -1680,7 +1680,7 @@ struct sctp_association *sctp_unpack_cookie( unsigned int len; sctp_scope_t scope; struct sk_buff *skb = chunk->skb; - struct timeval tv; + ktime_t kt; struct hash_desc desc; /* Header size is static data prior to the actual cookie, including @@ -1757,11 +1757,11 @@ struct sctp_association *sctp_unpack_cookie( * down the new association establishment instead of every packet. */ if (sock_flag(ep->base.sk, SOCK_TIMESTAMP)) - skb_get_timestamp(skb, &tv); + kt = skb_get_ktime(skb); else - do_gettimeofday(&tv); + kt = ktime_get(); - if (!asoc && tv_lt(bear_cookie->expiration, tv)) { + if (!asoc && ktime_compare(bear_cookie->expiration, kt) < 0) { /* * Section 3.3.10.3 Stale Cookie Error (3) * @@ -1773,9 +1773,7 @@ struct sctp_association *sctp_unpack_cookie( len = ntohs(chunk->chunk_hdr->length); *errp = sctp_make_op_error_space(asoc, chunk, len); if (*errp) { - suseconds_t usecs = (tv.tv_sec - - bear_cookie->expiration.tv_sec) * 1000000L + - tv.tv_usec - bear_cookie->expiration.tv_usec; + suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration)); __be32 n = htonl(usecs); sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, @@ -2514,8 +2512,7 @@ static int sctp_process_param(struct sctp_association *asoc, /* Suggested Cookie Life span increment's unit is msec, * (1/1000sec). */ - asoc->cookie_life.tv_sec += stale / 1000; - asoc->cookie_life.tv_usec += (stale % 1000) * 1000; + asoc->cookie_life = ktime_add_ms(asoc->cookie_life, stale); break; case SCTP_PARAM_HOST_NAME_ADDRESS: diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 32db19ba4a21..4c47e5578d71 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -2910,13 +2910,8 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, unsig asoc->max_retrans = assocparams.sasoc_asocmaxrxt; } - if (assocparams.sasoc_cookie_life != 0) { - asoc->cookie_life.tv_sec = - assocparams.sasoc_cookie_life / 1000; - asoc->cookie_life.tv_usec = - (assocparams.sasoc_cookie_life % 1000) - * 1000; - } + if (assocparams.sasoc_cookie_life != 0) + asoc->cookie_life = ms_to_ktime(assocparams.sasoc_cookie_life); } else { /* Set the values to the endpoint */ struct sctp_sock *sp = sctp_sk(sk); @@ -5074,10 +5069,7 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len, assocparams.sasoc_asocmaxrxt = asoc->max_retrans; assocparams.sasoc_peer_rwnd = asoc->peer.rwnd; assocparams.sasoc_local_rwnd = asoc->a_rwnd; - assocparams.sasoc_cookie_life = (asoc->cookie_life.tv_sec - * 1000) + - (asoc->cookie_life.tv_usec - / 1000); + assocparams.sasoc_cookie_life = ktime_to_ms(asoc->cookie_life); list_for_each(pos, &asoc->peer.transport_addr_list) { cnt ++; -- GitLab From b527fe693304d244b6103dc9f8a87150e71c29f7 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:28 +0200 Subject: [PATCH 1857/2900] net: sctp: minor: sctp_seq_dump_local_addrs add missing newline A trailing newline has been forgotten to add into the WARN(). Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 0c83162a6bf8..62526c477050 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -138,7 +138,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo peer = asoc->peer.primary_path; if (unlikely(peer == NULL)) { - WARN(1, "Association %p with NULL primary path!", asoc); + WARN(1, "Association %p with NULL primary path!\n", asoc); return; } -- GitLab From 0a2fbac197441ebeafbbef09d4bbc0b5e73716d7 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:29 +0200 Subject: [PATCH 1858/2900] net: sctp: decouple cleaning some socket data from endpoint Rather instead of having the endpoint clean the garbage from the socket, use a sk_destruct handler sctp_destruct_sock(), that does the job for that when there are no more references on the socket. At least do this for our crypto transform through crypto_free_hash() that is allocated when in listening state. Also, perform sctp_put_port() only when sk is valid. At a later point in time we can still determine if there's an option of placing this into sk_prot->unhash() or sctp_endpoint_free() without any races. For now, leave it in sctp_endpoint_destroy() though. Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/endpointola.c | 19 ++++++++++--------- net/sctp/socket.c | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index a8b26741c0af..b26999d508ba 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -247,10 +247,9 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) /* Final destructor for endpoint. */ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) { - SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); + struct sock *sk; - /* Free up the HMAC transform. */ - crypto_free_hash(sctp_sk(ep->base.sk)->hmac); + SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); /* Free the digest buffer */ kfree(ep->digest); @@ -271,13 +270,15 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) memset(ep->secret_key, 0, sizeof(ep->secret_key)); - /* Remove and free the port */ - if (sctp_sk(ep->base.sk)->bind_hash) - sctp_put_port(ep->base.sk); - /* Give up our hold on the sock. */ - if (ep->base.sk) - sock_put(ep->base.sk); + sk = ep->base.sk; + if (sk != NULL) { + /* Remove and free the port */ + if (sctp_sk(sk)->bind_hash) + sctp_put_port(sk); + + sock_put(sk); + } kfree(ep); SCTP_DBG_OBJCNT_DEC(ep); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4c47e5578d71..ba9359c20c8a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -93,6 +93,7 @@ static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p); static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); static void sctp_wait_for_close(struct sock *sk, long timeo); +static void sctp_destruct_sock(struct sock *sk); static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt, union sctp_addr *addr, int len); static int sctp_bindx_add(struct sock *, struct sockaddr *, int); @@ -3966,6 +3967,8 @@ static int sctp_init_sock(struct sock *sk) sp->hmac = NULL; + sk->sk_destruct = sctp_destruct_sock; + SCTP_DBG_OBJCNT_INC(sock); local_bh_disable(); @@ -4008,6 +4011,17 @@ static void sctp_destroy_sock(struct sock *sk) local_bh_enable(); } +/* Triggered when there are no references on the socket anymore */ +static void sctp_destruct_sock(struct sock *sk) +{ + struct sctp_sock *sp = sctp_sk(sk); + + /* Free up the HMAC transform. */ + crypto_free_hash(sp->hmac); + + inet_sock_destruct(sk); +} + /* API 4.1.7 shutdown() - TCP Style Syntax * int shutdown(int socket, int how); * @@ -6848,7 +6862,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, newsk->sk_reuse = sk->sk_reuse; newsk->sk_shutdown = sk->sk_shutdown; - newsk->sk_destruct = inet_sock_destruct; + newsk->sk_destruct = sctp_destruct_sock; newsk->sk_family = sk->sk_family; newsk->sk_protocol = IPPROTO_SCTP; newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; -- GitLab From 62208f12451f723cd9e9f1d6d22866a61545e488 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 25 Jun 2013 18:17:30 +0200 Subject: [PATCH 1859/2900] net: sctp: simplify sctp_get_port No need to have an extra ret variable when we directly can return the value of sctp_get_port_local(). Signed-off-by: Daniel Borkmann Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ba9359c20c8a..66fcdcfe1b74 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6036,7 +6036,6 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) */ static int sctp_get_port(struct sock *sk, unsigned short snum) { - long ret; union sctp_addr addr; struct sctp_af *af = sctp_sk(sk)->pf->af; @@ -6045,9 +6044,7 @@ static int sctp_get_port(struct sock *sk, unsigned short snum) addr.v4.sin_port = htons(snum); /* Note: sk->sk_num gets filled in if ephemeral port request. */ - ret = sctp_get_port_local(sk, &addr); - - return ret ? 1 : 0; + return !!sctp_get_port_local(sk, &addr); } /* -- GitLab From e4f2379db6c6823c5d4a4c2c912df00c65de51d7 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 24 Jun 2013 09:54:27 +0400 Subject: [PATCH 1860/2900] ethernet/arc/arc_emac - Add new driver Driver for non-standard on-chip ethernet device ARC EMAC 10/100, instantiated in some legacy ARC (Synopsys) FPGA Boards such as ARCAngel4/ML50x. Signed-off-by: Alexey Brodkin Cc: Andy Shevchenko Cc: Francois Romieu Cc: Joe Perches Cc: Vineet Gupta Cc: Mischa Jonker Cc: Arnd Bergmann Cc: Grant Likely Cc: Rob Herring Cc: Paul Gortmaker Cc: "David S. Miller" Cc: linux-kernel@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org Cc: Florian Fainelli Cc: David Laight Signed-off-by: David S. Miller --- .../devicetree/bindings/net/arc_emac.txt | 38 + drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/Makefile | 1 + drivers/net/ethernet/arc/Kconfig | 31 + drivers/net/ethernet/arc/Makefile | 6 + drivers/net/ethernet/arc/emac.h | 214 +++++ drivers/net/ethernet/arc/emac_main.c | 806 ++++++++++++++++++ drivers/net/ethernet/arc/emac_mdio.c | 152 ++++ 8 files changed, 1249 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/arc_emac.txt create mode 100644 drivers/net/ethernet/arc/Kconfig create mode 100644 drivers/net/ethernet/arc/Makefile create mode 100644 drivers/net/ethernet/arc/emac.h create mode 100644 drivers/net/ethernet/arc/emac_main.c create mode 100644 drivers/net/ethernet/arc/emac_mdio.c diff --git a/Documentation/devicetree/bindings/net/arc_emac.txt b/Documentation/devicetree/bindings/net/arc_emac.txt new file mode 100644 index 000000000000..bcbc3f009158 --- /dev/null +++ b/Documentation/devicetree/bindings/net/arc_emac.txt @@ -0,0 +1,38 @@ +* Synopsys ARC EMAC 10/100 Ethernet driver (EMAC) + +Required properties: +- compatible: Should be "snps,arc-emac" +- reg: Address and length of the register set for the device +- interrupts: Should contain the EMAC interrupts +- clock-frequency: CPU frequency. It is needed to calculate and set polling +period of EMAC. +- max-speed: Maximum supported data-rate in Mbit/s. In some HW configurations +bandwidth of external memory controller might be a limiting factor. That's why +it's required to specify which data-rate is supported on current SoC or FPGA. +For example if only 10 Mbit/s is supported (10BASE-T) set "10". If 100 Mbit/s is +supported (100BASE-TX) set "100". +- phy: PHY device attached to the EMAC via MDIO bus + +Child nodes of the driver are the individual PHY devices connected to the +MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus. + +Optional properties: +- mac-address: 6 bytes, mac address + +Examples: + + ethernet@c0fc2000 { + compatible = "snps,arc-emac"; + reg = <0xc0fc2000 0x3c>; + interrupts = <6>; + mac-address = [ 00 11 22 33 44 55 ]; + clock-frequency = <80000000>; + max-speed = <100>; + phy = <&phy0>; + + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <1>; + }; + }; diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index a989669b353a..2037080c504d 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/Kconfig" source "drivers/net/ethernet/alteon/Kconfig" source "drivers/net/ethernet/amd/Kconfig" source "drivers/net/ethernet/apple/Kconfig" +source "drivers/net/ethernet/arc/Kconfig" source "drivers/net/ethernet/atheros/Kconfig" source "drivers/net/ethernet/cadence/Kconfig" source "drivers/net/ethernet/adi/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 009da27b6e26..390bd0bfaa27 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ obj-$(CONFIG_NET_VENDOR_AMD) += amd/ obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ +obj-$(CONFIG_NET_VENDOR_ARC) += arc/ obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ obj-$(CONFIG_NET_CADENCE) += cadence/ obj-$(CONFIG_NET_BFIN) += adi/ diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig new file mode 100644 index 000000000000..514c57fd26f1 --- /dev/null +++ b/drivers/net/ethernet/arc/Kconfig @@ -0,0 +1,31 @@ +# +# ARC EMAC network device configuration +# + +config NET_VENDOR_ARC + bool "ARC devices" + default y + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about ARC cards. If you say Y, you will be asked for + your specific card in the following questions. + +if NET_VENDOR_ARC + +config ARC_EMAC + tristate "ARC EMAC support" + select MII + select PHYLIB + depends on OF_IRQ + depends on OF_NET + ---help--- + On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x + non-standard on-chip ethernet device ARC EMAC 10/100 is used. + Say Y here if you have such a board. If unsure, say N. + +endif # NET_VENDOR_ARC diff --git a/drivers/net/ethernet/arc/Makefile b/drivers/net/ethernet/arc/Makefile new file mode 100644 index 000000000000..00c8657637d5 --- /dev/null +++ b/drivers/net/ethernet/arc/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the ARC network device drivers. +# + +arc_emac-objs := emac_main.o emac_mdio.o +obj-$(CONFIG_ARC_EMAC) += arc_emac.o diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h new file mode 100644 index 000000000000..dc08678bf9a4 --- /dev/null +++ b/drivers/net/ethernet/arc/emac.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2004-2013 Synopsys, Inc. (www.synopsys.com) + * + * Registers and bits definitions of ARC EMAC + */ + +#ifndef ARC_EMAC_H +#define ARC_EMAC_H + +#include +#include +#include +#include + +/* STATUS and ENABLE Register bit masks */ +#define TXINT_MASK (1<<0) /* Transmit interrupt */ +#define RXINT_MASK (1<<1) /* Receive interrupt */ +#define ERR_MASK (1<<2) /* Error interrupt */ +#define TXCH_MASK (1<<3) /* Transmit chaining error interrupt */ +#define MSER_MASK (1<<4) /* Missed packet counter error */ +#define RXCR_MASK (1<<8) /* RXCRCERR counter rolled over */ +#define RXFR_MASK (1<<9) /* RXFRAMEERR counter rolled over */ +#define RXFL_MASK (1<<10) /* RXOFLOWERR counter rolled over */ +#define MDIO_MASK (1<<12) /* MDIO complete interrupt */ +#define TXPL_MASK (1<<31) /* Force polling of BD by EMAC */ + +/* CONTROL Register bit masks */ +#define EN_MASK (1<<0) /* VMAC enable */ +#define TXRN_MASK (1<<3) /* TX enable */ +#define RXRN_MASK (1<<4) /* RX enable */ +#define DSBC_MASK (1<<8) /* Disable receive broadcast */ +#define ENFL_MASK (1<<10) /* Enable Full-duplex */ +#define PROM_MASK (1<<11) /* Promiscuous mode */ + +/* Buffer descriptor INFO bit masks */ +#define OWN_MASK (1<<31) /* 0-CPU owns buffer, 1-EMAC owns buffer */ +#define FIRST_MASK (1<<16) /* First buffer in chain */ +#define LAST_MASK (1<<17) /* Last buffer in chain */ +#define LEN_MASK 0x000007FF /* last 11 bits */ +#define CRLS (1<<21) +#define DEFR (1<<22) +#define DROP (1<<23) +#define RTRY (1<<24) +#define LTCL (1<<28) +#define UFLO (1<<29) + +#define FOR_EMAC OWN_MASK +#define FOR_CPU 0 + +/* ARC EMAC register set combines entries for MAC and MDIO */ +enum { + R_ID = 0, + R_STATUS, + R_ENABLE, + R_CTRL, + R_POLLRATE, + R_RXERR, + R_MISS, + R_TX_RING, + R_RX_RING, + R_ADDRL, + R_ADDRH, + R_LAFL, + R_LAFH, + R_MDIO, +}; + +#define TX_TIMEOUT (400*HZ/1000) /* Transmission timeout */ + +#define ARC_EMAC_NAPI_WEIGHT 40 /* Workload for NAPI */ + +#define EMAC_BUFFER_SIZE 1536 /* EMAC buffer size */ + +/** + * struct arc_emac_bd - EMAC buffer descriptor (BD). + * + * @info: Contains status information on the buffer itself. + * @data: 32-bit byte addressable pointer to the packet data. + */ +struct arc_emac_bd { + __le32 info; + dma_addr_t data; +}; + +/* Number of Rx/Tx BD's */ +#define RX_BD_NUM 128 +#define TX_BD_NUM 128 + +#define RX_RING_SZ (RX_BD_NUM * sizeof(struct arc_emac_bd)) +#define TX_RING_SZ (TX_BD_NUM * sizeof(struct arc_emac_bd)) + +/** + * struct buffer_state - Stores Rx/Tx buffer state. + * @sk_buff: Pointer to socket buffer. + * @addr: Start address of DMA-mapped memory region. + * @len: Length of DMA-mapped memory region. + */ +struct buffer_state { + struct sk_buff *skb; + DEFINE_DMA_UNMAP_ADDR(addr); + DEFINE_DMA_UNMAP_LEN(len); +}; + +/** + * struct arc_emac_priv - Storage of EMAC's private information. + * @dev: Pointer to the current device. + * @ndev: Pointer to the current network device. + * @phy_dev: Pointer to attached PHY device. + * @bus: Pointer to the current MII bus. + * @regs: Base address of EMAC memory-mapped control registers. + * @napi: Structure for NAPI. + * @stats: Network device statistics. + * @rxbd: Pointer to Rx BD ring. + * @txbd: Pointer to Tx BD ring. + * @rxbd_dma: DMA handle for Rx BD ring. + * @txbd_dma: DMA handle for Tx BD ring. + * @rx_buff: Storage for Rx buffers states. + * @tx_buff: Storage for Tx buffers states. + * @txbd_curr: Index of Tx BD to use on the next "ndo_start_xmit". + * @txbd_dirty: Index of Tx BD to free on the next Tx interrupt. + * @last_rx_bd: Index of the last Rx BD we've got from EMAC. + * @link: PHY's last seen link state. + * @duplex: PHY's last set duplex mode. + * @speed: PHY's last set speed. + * @max_speed: Maximum supported by current system network data-rate. + */ +struct arc_emac_priv { + /* Devices */ + struct device *dev; + struct net_device *ndev; + struct phy_device *phy_dev; + struct mii_bus *bus; + + void __iomem *regs; + + struct napi_struct napi; + struct net_device_stats stats; + + struct arc_emac_bd *rxbd; + struct arc_emac_bd *txbd; + + dma_addr_t rxbd_dma; + dma_addr_t txbd_dma; + + struct buffer_state rx_buff[RX_BD_NUM]; + struct buffer_state tx_buff[TX_BD_NUM]; + unsigned int txbd_curr; + unsigned int txbd_dirty; + + unsigned int last_rx_bd; + + unsigned int link; + unsigned int duplex; + unsigned int speed; + unsigned int max_speed; +}; + +/** + * arc_reg_set - Sets EMAC register with provided value. + * @priv: Pointer to ARC EMAC private data structure. + * @reg: Register offset from base address. + * @value: Value to set in register. + */ +static inline void arc_reg_set(struct arc_emac_priv *priv, int reg, int value) +{ + iowrite32(value, priv->regs + reg * sizeof(int)); +} + +/** + * arc_reg_get - Gets value of specified EMAC register. + * @priv: Pointer to ARC EMAC private data structure. + * @reg: Register offset from base address. + * + * returns: Value of requested register. + */ +static inline unsigned int arc_reg_get(struct arc_emac_priv *priv, int reg) +{ + return ioread32(priv->regs + reg * sizeof(int)); +} + +/** + * arc_reg_or - Applies mask to specified EMAC register - ("reg" | "mask"). + * @priv: Pointer to ARC EMAC private data structure. + * @reg: Register offset from base address. + * @mask: Mask to apply to specified register. + * + * This function reads initial register value, then applies provided mask + * to it and then writes register back. + */ +static inline void arc_reg_or(struct arc_emac_priv *priv, int reg, int mask) +{ + unsigned int value = arc_reg_get(priv, reg); + arc_reg_set(priv, reg, value | mask); +} + +/** + * arc_reg_clr - Applies mask to specified EMAC register - ("reg" & ~"mask"). + * @priv: Pointer to ARC EMAC private data structure. + * @reg: Register offset from base address. + * @mask: Mask to apply to specified register. + * + * This function reads initial register value, then applies provided mask + * to it and then writes register back. + */ +static inline void arc_reg_clr(struct arc_emac_priv *priv, int reg, int mask) +{ + unsigned int value = arc_reg_get(priv, reg); + arc_reg_set(priv, reg, value & ~mask); +} + +int arc_mdio_probe(struct platform_device *pdev, struct arc_emac_priv *priv); +int arc_mdio_remove(struct arc_emac_priv *priv); + +#endif /* ARC_EMAC_H */ diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c new file mode 100644 index 000000000000..20345f6bf894 --- /dev/null +++ b/drivers/net/ethernet/arc/emac_main.c @@ -0,0 +1,806 @@ +/* + * Copyright (C) 2004-2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the ARC EMAC 10100 (hardware revision 5) + * + * Contributors: + * Amit Bhor + * Sameer Dhavale + * Vineet Gupta + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "emac.h" + +#define DRV_NAME "arc_emac" +#define DRV_VERSION "1.0" + +/** + * arc_emac_adjust_link - Adjust the PHY link duplex. + * @ndev: Pointer to the net_device structure. + * + * This function is called to change the duplex setting after auto negotiation + * is done by the PHY. + */ +static void arc_emac_adjust_link(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + struct phy_device *phy_dev = priv->phy_dev; + unsigned int reg, state_changed = 0; + + if (priv->link != phy_dev->link) { + priv->link = phy_dev->link; + state_changed = 1; + } + + if (priv->speed != phy_dev->speed) { + priv->speed = phy_dev->speed; + state_changed = 1; + } + + if (priv->duplex != phy_dev->duplex) { + reg = arc_reg_get(priv, R_CTRL); + + if (DUPLEX_FULL == phy_dev->duplex) + reg |= ENFL_MASK; + else + reg &= ~ENFL_MASK; + + arc_reg_set(priv, R_CTRL, reg); + priv->duplex = phy_dev->duplex; + state_changed = 1; + } + + if (state_changed) + phy_print_status(phy_dev); +} + +/** + * arc_emac_get_settings - Get PHY settings. + * @ndev: Pointer to net_device structure. + * @cmd: Pointer to ethtool_cmd structure. + * + * This implements ethtool command for getting PHY settings. If PHY could + * not be found, the function returns -ENODEV. This function calls the + * relevant PHY ethtool API to get the PHY settings. + * Issue "ethtool ethX" under linux prompt to execute this function. + */ +static int arc_emac_get_settings(struct net_device *ndev, + struct ethtool_cmd *cmd) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + + return phy_ethtool_gset(priv->phy_dev, cmd); +} + +/** + * arc_emac_set_settings - Set PHY settings as passed in the argument. + * @ndev: Pointer to net_device structure. + * @cmd: Pointer to ethtool_cmd structure. + * + * This implements ethtool command for setting various PHY settings. If PHY + * could not be found, the function returns -ENODEV. This function calls the + * relevant PHY ethtool API to set the PHY. + * Issue e.g. "ethtool -s ethX speed 1000" under linux prompt to execute this + * function. + */ +static int arc_emac_set_settings(struct net_device *ndev, + struct ethtool_cmd *cmd) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + return phy_ethtool_sset(priv->phy_dev, cmd); +} + +/** + * arc_emac_get_drvinfo - Get EMAC driver information. + * @ndev: Pointer to net_device structure. + * @info: Pointer to ethtool_drvinfo structure. + * + * This implements ethtool command for getting the driver information. + * Issue "ethtool -i ethX" under linux prompt to execute this function. + */ +static void arc_emac_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); +} + +static const struct ethtool_ops arc_emac_ethtool_ops = { + .get_settings = arc_emac_get_settings, + .set_settings = arc_emac_set_settings, + .get_drvinfo = arc_emac_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +#define FIRST_OR_LAST_MASK (FIRST_MASK | LAST_MASK) + +/** + * arc_emac_tx_clean - clears processed by EMAC Tx BDs. + * @ndev: Pointer to the network device. + */ +static void arc_emac_tx_clean(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &priv->stats; + unsigned int i; + + for (i = 0; i < TX_BD_NUM; i++) { + unsigned int *txbd_dirty = &priv->txbd_dirty; + struct arc_emac_bd *txbd = &priv->txbd[*txbd_dirty]; + struct buffer_state *tx_buff = &priv->tx_buff[*txbd_dirty]; + struct sk_buff *skb = tx_buff->skb; + unsigned int info = le32_to_cpu(txbd->info); + + *txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM; + + if ((info & FOR_EMAC) || !txbd->data) + break; + + if (unlikely(info & (DROP | DEFR | LTCL | UFLO))) { + stats->tx_errors++; + stats->tx_dropped++; + + if (info & DEFR) + stats->tx_carrier_errors++; + + if (info & LTCL) + stats->collisions++; + + if (info & UFLO) + stats->tx_fifo_errors++; + } else if (likely(info & FIRST_OR_LAST_MASK)) { + stats->tx_packets++; + stats->tx_bytes += skb->len; + } + + dma_unmap_single(&ndev->dev, dma_unmap_addr(&tx_buff, addr), + dma_unmap_len(&tx_buff, len), DMA_TO_DEVICE); + + /* return the sk_buff to system */ + dev_kfree_skb_irq(skb); + + txbd->data = 0; + txbd->info = 0; + + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); + } +} + +/** + * arc_emac_rx - processing of Rx packets. + * @ndev: Pointer to the network device. + * @budget: How many BDs to process on 1 call. + * + * returns: Number of processed BDs + * + * Iterate through Rx BDs and deliver received packages to upper layer. + */ +static int arc_emac_rx(struct net_device *ndev, int budget) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int work_done; + + for (work_done = 0; work_done <= budget; work_done++) { + unsigned int *last_rx_bd = &priv->last_rx_bd; + struct net_device_stats *stats = &priv->stats; + struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd]; + struct arc_emac_bd *rxbd = &priv->rxbd[*last_rx_bd]; + unsigned int buflen = EMAC_BUFFER_SIZE; + unsigned int pktlen, info = le32_to_cpu(rxbd->info); + struct sk_buff *skb; + dma_addr_t addr; + + if (unlikely((info & OWN_MASK) == FOR_EMAC)) + break; + + /* Make a note that we saw a packet at this BD. + * So next time, driver starts from this + 1 + */ + *last_rx_bd = (*last_rx_bd + 1) % RX_BD_NUM; + + if (unlikely((info & FIRST_OR_LAST_MASK) != + FIRST_OR_LAST_MASK)) { + /* We pre-allocate buffers of MTU size so incoming + * packets won't be split/chained. + */ + if (net_ratelimit()) + netdev_err(ndev, "incomplete packet received\n"); + + /* Return ownership to EMAC */ + rxbd->info = cpu_to_le32(FOR_EMAC | buflen); + stats->rx_errors++; + stats->rx_length_errors++; + continue; + } + + pktlen = info & LEN_MASK; + stats->rx_packets++; + stats->rx_bytes += pktlen; + skb = rx_buff->skb; + skb_put(skb, pktlen); + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + + dma_unmap_single(&ndev->dev, dma_unmap_addr(&rx_buff, addr), + dma_unmap_len(&rx_buff, len), DMA_FROM_DEVICE); + + /* Prepare the BD for next cycle */ + rx_buff->skb = netdev_alloc_skb_ip_align(ndev, buflen); + if (unlikely(!rx_buff->skb)) { + stats->rx_errors++; + /* Because receive_skb is below, increment rx_dropped */ + stats->rx_dropped++; + continue; + } + + /* receive_skb only if new skb was allocated to avoid holes */ + netif_receive_skb(skb); + + addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data, + buflen, DMA_FROM_DEVICE); + if (dma_mapping_error(&ndev->dev, addr)) { + if (net_ratelimit()) + netdev_err(ndev, "cannot dma map\n"); + dev_kfree_skb(rx_buff->skb); + stats->rx_errors++; + continue; + } + dma_unmap_addr_set(&rx_buff, mapping, addr); + dma_unmap_len_set(&rx_buff, len, buflen); + + rxbd->data = cpu_to_le32(rx_buff->skb->data); + + /* Make sure pointer to data buffer is set */ + wmb(); + + /* Return ownership to EMAC */ + rxbd->info = cpu_to_le32(FOR_EMAC | buflen); + } + + return work_done; +} + +/** + * arc_emac_poll - NAPI poll handler. + * @napi: Pointer to napi_struct structure. + * @budget: How many BDs to process on 1 call. + * + * returns: Number of processed BDs + */ +static int arc_emac_poll(struct napi_struct *napi, int budget) +{ + struct net_device *ndev = napi->dev; + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int work_done; + + arc_emac_tx_clean(ndev); + + work_done = arc_emac_rx(ndev, budget); + if (work_done < budget) { + napi_complete(napi); + arc_reg_or(priv, R_ENABLE, RXINT_MASK); + } + + return work_done; +} + +/** + * arc_emac_intr - Global interrupt handler for EMAC. + * @irq: irq number. + * @dev_instance: device instance. + * + * returns: IRQ_HANDLED for all cases. + * + * ARC EMAC has only 1 interrupt line, and depending on bits raised in + * STATUS register we may tell what is a reason for interrupt to fire. + */ +static irqreturn_t arc_emac_intr(int irq, void *dev_instance) +{ + struct net_device *ndev = dev_instance; + struct arc_emac_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &priv->stats; + unsigned int status; + + status = arc_reg_get(priv, R_STATUS); + status &= ~MDIO_MASK; + + /* Reset all flags except "MDIO complete" */ + arc_reg_set(priv, R_STATUS, status); + + if (status & RXINT_MASK) { + if (likely(napi_schedule_prep(&priv->napi))) { + arc_reg_clr(priv, R_ENABLE, RXINT_MASK); + __napi_schedule(&priv->napi); + } + } + + if (status & ERR_MASK) { + /* MSER/RXCR/RXFR/RXFL interrupt fires on corresponding + * 8-bit error counter overrun. + */ + + if (status & MSER_MASK) { + stats->rx_missed_errors += 0x100; + stats->rx_errors += 0x100; + } + + if (status & RXCR_MASK) { + stats->rx_crc_errors += 0x100; + stats->rx_errors += 0x100; + } + + if (status & RXFR_MASK) { + stats->rx_frame_errors += 0x100; + stats->rx_errors += 0x100; + } + + if (status & RXFL_MASK) { + stats->rx_over_errors += 0x100; + stats->rx_errors += 0x100; + } + } + + return IRQ_HANDLED; +} + +/** + * arc_emac_open - Open the network device. + * @ndev: Pointer to the network device. + * + * returns: 0, on success or non-zero error value on failure. + * + * This function sets the MAC address, requests and enables an IRQ + * for the EMAC device and starts the Tx queue. + * It also connects to the phy device. + */ +static int arc_emac_open(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + struct phy_device *phy_dev = priv->phy_dev; + struct arc_emac_bd *bd; + struct sk_buff *skb; + int i; + + phy_dev->autoneg = AUTONEG_ENABLE; + phy_dev->speed = 0; + phy_dev->duplex = 0; + phy_dev->advertising = phy_dev->supported; + + if (priv->max_speed > 100) { + phy_dev->advertising &= PHY_GBIT_FEATURES; + } else if (priv->max_speed <= 100) { + phy_dev->advertising &= PHY_BASIC_FEATURES; + if (priv->max_speed <= 10) { + phy_dev->advertising &= ~SUPPORTED_100baseT_Half; + phy_dev->advertising &= ~SUPPORTED_100baseT_Full; + } + } + + /* Allocate and set buffers for Rx BD's */ + bd = priv->rxbd; + for (i = 0; i < RX_BD_NUM; i++) { + skb = netdev_alloc_skb_ip_align(ndev, EMAC_BUFFER_SIZE); + if (unlikely(!skb)) + return -ENOMEM; + + priv->rx_buff[i].skb = skb; + bd->data = cpu_to_le32(skb->data); + + /* Make sure pointer to data buffer is set */ + wmb(); + + /* Set ownership to EMAC */ + bd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); + bd++; + } + + priv->last_rx_bd = 0; + + /* Clean Tx BD's */ + memset(priv->txbd, 0, TX_RING_SZ); + + /* Initialize logical address filter */ + arc_reg_set(priv, R_LAFL, 0); + arc_reg_set(priv, R_LAFH, 0); + + /* Set BD ring pointers for device side */ + arc_reg_set(priv, R_RX_RING, (unsigned int)priv->rxbd_dma); + arc_reg_set(priv, R_TX_RING, (unsigned int)priv->txbd_dma); + + /* Enable interrupts */ + arc_reg_set(priv, R_ENABLE, RXINT_MASK | ERR_MASK); + + /* Set CONTROL */ + arc_reg_set(priv, R_CTRL, + (RX_BD_NUM << 24) | /* RX BD table length */ + (TX_BD_NUM << 16) | /* TX BD table length */ + TXRN_MASK | RXRN_MASK); + + napi_enable(&priv->napi); + + /* Enable EMAC */ + arc_reg_or(priv, R_CTRL, EN_MASK); + + phy_start_aneg(priv->phy_dev); + + netif_start_queue(ndev); + + return 0; +} + +/** + * arc_emac_stop - Close the network device. + * @ndev: Pointer to the network device. + * + * This function stops the Tx queue, disables interrupts and frees the IRQ for + * the EMAC device. + * It also disconnects the PHY device associated with the EMAC device. + */ +static int arc_emac_stop(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + + napi_disable(&priv->napi); + netif_stop_queue(ndev); + + /* Disable interrupts */ + arc_reg_clr(priv, R_ENABLE, RXINT_MASK | ERR_MASK); + + /* Disable EMAC */ + arc_reg_clr(priv, R_CTRL, EN_MASK); + + return 0; +} + +/** + * arc_emac_stats - Get system network statistics. + * @ndev: Pointer to net_device structure. + * + * Returns the address of the device statistics structure. + * Statistics are updated in interrupt handler. + */ +static struct net_device_stats *arc_emac_stats(struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &priv->stats; + unsigned long miss, rxerr; + u8 rxcrc, rxfram, rxoflow; + + rxerr = arc_reg_get(priv, R_RXERR); + miss = arc_reg_get(priv, R_MISS); + + rxcrc = rxerr; + rxfram = rxerr >> 8; + rxoflow = rxerr >> 16; + + stats->rx_errors += miss; + stats->rx_errors += rxcrc + rxfram + rxoflow; + + stats->rx_over_errors += rxoflow; + stats->rx_frame_errors += rxfram; + stats->rx_crc_errors += rxcrc; + stats->rx_missed_errors += miss; + + return stats; +} + +/** + * arc_emac_tx - Starts the data transmission. + * @skb: sk_buff pointer that contains data to be Transmitted. + * @ndev: Pointer to net_device structure. + * + * returns: NETDEV_TX_OK, on success + * NETDEV_TX_BUSY, if any of the descriptors are not free. + * + * This function is invoked from upper layers to initiate transmission. + */ +static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + unsigned int len, *txbd_curr = &priv->txbd_curr; + struct net_device_stats *stats = &priv->stats; + __le32 *info = &priv->txbd[*txbd_curr].info; + dma_addr_t addr; + + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + + len = max_t(unsigned int, ETH_ZLEN, skb->len); + + /* EMAC still holds this buffer in its possession. + * CPU must not modify this buffer descriptor + */ + if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC)) { + netif_stop_queue(ndev); + return NETDEV_TX_BUSY; + } + + addr = dma_map_single(&ndev->dev, (void *)skb->data, len, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(&ndev->dev, addr))) { + stats->tx_dropped++; + stats->tx_errors++; + dev_kfree_skb(skb); + return NETDEV_TX_OK; + } + dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], mapping, addr); + dma_unmap_len_set(&priv->tx_buff[*txbd_curr], len, len); + + priv->tx_buff[*txbd_curr].skb = skb; + priv->txbd[*txbd_curr].data = cpu_to_le32(skb->data); + + /* Make sure pointer to data buffer is set */ + wmb(); + + *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); + + /* Increment index to point to the next BD */ + *txbd_curr = (*txbd_curr + 1) % TX_BD_NUM; + + /* Get "info" of the next BD */ + info = &priv->txbd[*txbd_curr].info; + + /* Check if if Tx BD ring is full - next BD is still owned by EMAC */ + if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC)) + netif_stop_queue(ndev); + + arc_reg_set(priv, R_STATUS, TXPL_MASK); + + skb_tx_timestamp(skb); + + return NETDEV_TX_OK; +} + +/** + * arc_emac_set_address - Set the MAC address for this device. + * @ndev: Pointer to net_device structure. + * @p: 6 byte Address to be written as MAC address. + * + * This function copies the HW address from the sockaddr structure to the + * net_device structure and updates the address in HW. + * + * returns: -EBUSY if the net device is busy or 0 if the address is set + * successfully. + */ +static int arc_emac_set_address(struct net_device *ndev, void *p) +{ + struct arc_emac_priv *priv = netdev_priv(ndev); + struct sockaddr *addr = p; + unsigned int addr_low, addr_hi; + + if (netif_running(ndev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); + + addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]); + addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]); + + arc_reg_set(priv, R_ADDRL, addr_low); + arc_reg_set(priv, R_ADDRH, addr_hi); + + return 0; +} + +static const struct net_device_ops arc_emac_netdev_ops = { + .ndo_open = arc_emac_open, + .ndo_stop = arc_emac_stop, + .ndo_start_xmit = arc_emac_tx, + .ndo_set_mac_address = arc_emac_set_address, + .ndo_get_stats = arc_emac_stats, +}; + +static int arc_emac_probe(struct platform_device *pdev) +{ + struct resource res_regs, res_irq; + struct device_node *phy_node; + struct arc_emac_priv *priv; + struct net_device *ndev; + const char *mac_addr; + unsigned int id, clock_frequency; + int err; + + if (!pdev->dev.of_node) + return -ENODEV; + + /* Get PHY from device tree */ + phy_node = of_parse_phandle(pdev->dev.of_node, "phy", 0); + if (!phy_node) { + dev_err(&pdev->dev, "failed to retrieve phy description from device tree\n"); + return -ENODEV; + } + + /* Get EMAC registers base address from device tree */ + err = of_address_to_resource(pdev->dev.of_node, 0, &res_regs); + if (err) { + dev_err(&pdev->dev, "failed to retrieve registers base from device tree\n"); + return -ENODEV; + } + + /* Get CPU clock frequency from device tree */ + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &clock_frequency)) { + dev_err(&pdev->dev, "failed to retrieve from device tree\n"); + return -EINVAL; + } + + /* Get IRQ from device tree */ + err = of_irq_to_resource(pdev->dev.of_node, 0, &res_irq); + if (!err) { + dev_err(&pdev->dev, "failed to retrieve value from device tree\n"); + return -ENODEV; + } + + ndev = alloc_etherdev(sizeof(struct arc_emac_priv)); + if (!ndev) + return -ENOMEM; + + SET_NETDEV_DEV(ndev, &pdev->dev); + + ndev->netdev_ops = &arc_emac_netdev_ops; + ndev->ethtool_ops = &arc_emac_ethtool_ops; + ndev->watchdog_timeo = TX_TIMEOUT; + /* FIXME :: no multicast support yet */ + ndev->flags &= ~IFF_MULTICAST; + + priv = netdev_priv(ndev); + priv->dev = &pdev->dev; + priv->ndev = ndev; + + priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); + if (IS_ERR(priv->regs)) { + err = PTR_ERR(priv->regs); + goto out; + } + dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); + + id = arc_reg_get(priv, R_ID); + + /* Check for EMAC revision 5 or 7, magic number */ + if (!(id == 0x0005fd02 || id == 0x0007fd02)) { + dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); + err = -ENODEV; + goto out; + } + dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); + + /* Set poll rate so that it polls every 1 ms */ + arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); + + /* Get max speed of operation from device tree */ + if (of_property_read_u32(pdev->dev.of_node, "max-speed", + &priv->max_speed)) { + dev_err(&pdev->dev, "failed to retrieve from device tree\n"); + err = -EINVAL; + goto out; + } + + ndev->irq = res_irq.start; + dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq); + + /* Register interrupt handler for device */ + err = devm_request_irq(&pdev->dev, ndev->irq, arc_emac_intr, 0, + ndev->name, ndev); + if (err) { + dev_err(&pdev->dev, "could not allocate IRQ\n"); + goto out; + } + + /* Get MAC address from device tree */ + mac_addr = of_get_mac_address(pdev->dev.of_node); + + if (!mac_addr || !is_valid_ether_addr(mac_addr)) + eth_hw_addr_random(ndev); + else + memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); + + dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); + + /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ + priv->rxbd = dmam_alloc_coherent(&pdev->dev, RX_RING_SZ + TX_RING_SZ, + &priv->rxbd_dma, GFP_KERNEL); + + if (!priv->rxbd) { + dev_err(&pdev->dev, "failed to allocate data buffers\n"); + err = -ENOMEM; + goto out; + } + + priv->txbd = priv->rxbd + RX_BD_NUM; + + priv->txbd_dma = priv->rxbd_dma + RX_RING_SZ; + dev_dbg(&pdev->dev, "EMAC Device addr: Rx Ring [0x%x], Tx Ring[%x]\n", + (unsigned int)priv->rxbd_dma, (unsigned int)priv->txbd_dma); + + err = arc_mdio_probe(pdev, priv); + if (err) { + dev_err(&pdev->dev, "failed to probe MII bus\n"); + goto out; + } + + priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (!priv->phy_dev) { + dev_err(&pdev->dev, "of_phy_connect() failed\n"); + err = -ENODEV; + goto out; + } + + dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", + priv->phy_dev->drv->name, priv->phy_dev->phy_id); + + netif_napi_add(ndev, &priv->napi, arc_emac_poll, ARC_EMAC_NAPI_WEIGHT); + + err = register_netdev(ndev); + if (err) { + netif_napi_del(&priv->napi); + dev_err(&pdev->dev, "failed to register network device\n"); + goto out; + } + + return 0; + +out: + free_netdev(ndev); + return err; +} + +static int arc_emac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct arc_emac_priv *priv = netdev_priv(ndev); + + phy_disconnect(priv->phy_dev); + priv->phy_dev = NULL; + arc_mdio_remove(priv); + unregister_netdev(ndev); + netif_napi_del(&priv->napi); + free_netdev(ndev); + + return 0; +} + +static const struct of_device_id arc_emac_dt_ids[] = { + { .compatible = "snps,arc-emac" }, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, arc_emac_dt_ids); + +static struct platform_driver arc_emac_driver = { + .probe = arc_emac_probe, + .remove = arc_emac_remove, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = arc_emac_dt_ids, + }, +}; + +module_platform_driver(arc_emac_driver); + +MODULE_AUTHOR("Alexey Brodkin "); +MODULE_DESCRIPTION("ARC EMAC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/arc/emac_mdio.c b/drivers/net/ethernet/arc/emac_mdio.c new file mode 100644 index 000000000000..26ba2423f33a --- /dev/null +++ b/drivers/net/ethernet/arc/emac_mdio.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2004-2013 Synopsys, Inc. (www.synopsys.com) + * + * MDIO implementation for ARC EMAC + */ + +#include +#include +#include + +#include "emac.h" + +/* Number of seconds we wait for "MDIO complete" flag to appear */ +#define ARC_MDIO_COMPLETE_POLL_COUNT 1 + +/** + * arc_mdio_complete_wait - Waits until MDIO transaction is completed. + * @priv: Pointer to ARC EMAC private data structure. + * + * returns: 0 on success, -ETIMEDOUT on a timeout. + */ +static int arc_mdio_complete_wait(struct arc_emac_priv *priv) +{ + unsigned int i; + + for (i = 0; i < ARC_MDIO_COMPLETE_POLL_COUNT * 40; i++) { + unsigned int status = arc_reg_get(priv, R_STATUS); + + status &= MDIO_MASK; + + if (status) { + /* Reset "MDIO complete" flag */ + arc_reg_set(priv, R_STATUS, status); + return 0; + } + + msleep(25); + } + + return -ETIMEDOUT; +} + +/** + * arc_mdio_read - MDIO interface read function. + * @bus: Pointer to MII bus structure. + * @phy_addr: Address of the PHY device. + * @reg_num: PHY register to read. + * + * returns: The register contents on success, -ETIMEDOUT on a timeout. + * + * Reads the contents of the requested register from the requested PHY + * address. + */ +static int arc_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) +{ + struct arc_emac_priv *priv = bus->priv; + unsigned int value; + int error; + + arc_reg_set(priv, R_MDIO, + 0x60020000 | (phy_addr << 23) | (reg_num << 18)); + + error = arc_mdio_complete_wait(priv); + if (error < 0) + return error; + + value = arc_reg_get(priv, R_MDIO) & 0xffff; + + dev_dbg(priv->dev, "arc_mdio_read(phy_addr=%i, reg_num=%x) = %x\n", + phy_addr, reg_num, value); + + return value; +} + +/** + * arc_mdio_write - MDIO interface write function. + * @bus: Pointer to MII bus structure. + * @phy_addr: Address of the PHY device. + * @reg_num: PHY register to write to. + * @value: Value to be written into the register. + * + * returns: 0 on success, -ETIMEDOUT on a timeout. + * + * Writes the value to the requested register. + */ +static int arc_mdio_write(struct mii_bus *bus, int phy_addr, + int reg_num, u16 value) +{ + struct arc_emac_priv *priv = bus->priv; + + dev_dbg(priv->dev, + "arc_mdio_write(phy_addr=%i, reg_num=%x, value=%x)\n", + phy_addr, reg_num, value); + + arc_reg_set(priv, R_MDIO, + 0x50020000 | (phy_addr << 23) | (reg_num << 18) | value); + + return arc_mdio_complete_wait(priv); +} + +/** + * arc_mdio_probe - MDIO probe function. + * @pdev: Pointer to platform device. + * @priv: Pointer to ARC EMAC private data structure. + * + * returns: 0 on success, -ENOMEM when mdiobus_alloc + * (to allocate memory for MII bus structure) fails. + * + * Sets up and registers the MDIO interface. + */ +int arc_mdio_probe(struct platform_device *pdev, struct arc_emac_priv *priv) +{ + struct mii_bus *bus; + int error; + + bus = mdiobus_alloc(); + if (!bus) + return -ENOMEM; + + priv->bus = bus; + bus->priv = priv; + bus->parent = priv->dev; + bus->name = "Synopsys MII Bus", + bus->read = &arc_mdio_read; + bus->write = &arc_mdio_write; + + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); + + error = of_mdiobus_register(bus, pdev->dev.of_node); + if (error) { + dev_err(priv->dev, "cannot register MDIO bus %s\n", bus->name); + mdiobus_free(bus); + return error; + } + + return 0; +} + +/** + * arc_mdio_remove - MDIO remove function. + * @priv: Pointer to ARC EMAC private data structure. + * + * Unregisters the MDIO and frees any associate memory for MII bus. + */ +int arc_mdio_remove(struct arc_emac_priv *priv) +{ + mdiobus_unregister(priv->bus); + mdiobus_free(priv->bus); + priv->bus = NULL; + + return 0; +} -- GitLab From 2d48d67fa8cd129ea85ea02d91b4a793286866f8 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 24 Jun 2013 10:28:03 +0300 Subject: [PATCH 1861/2900] net: poll/select low latency socket support select/poll busy-poll support. Split sysctl value into two separate ones, one for read and one for poll. updated Documentation/sysctl/net.txt Add a new poll flag POLL_LL. When this flag is set, sock_poll will call sk_poll_ll if possible. sock_poll sets this flag in its return value to indicate to select/poll when a socket that can busy poll is found. When poll/select have nothing to report, call the low-level sock_poll again until we are out of time or we find something. Once the system call finds something, it stops setting POLL_LL, so it can return the result to the user ASAP. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 18 +++++++++++++++-- fs/select.c | 34 +++++++++++++++++++++++++++----- include/net/ll_poll.h | 35 +++++++++++++++++++++------------ include/uapi/asm-generic/poll.h | 2 ++ net/core/sock.c | 2 +- net/core/sysctl_net_core.c | 8 ++++++++ net/socket.c | 14 ++++++++++++- 7 files changed, 91 insertions(+), 22 deletions(-) diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index 5369879eafe2..e658bbfb641f 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -50,13 +50,27 @@ The maximum number of packets that kernel can handle on a NAPI interrupt, it's a Per-CPU variable. Default: 64 -low_latency_poll +low_latency_read ---------------- -Low latency busy poll timeout. (needs CONFIG_NET_LL_RX_POLL) +Low latency busy poll timeout for socket reads. (needs CONFIG_NET_LL_RX_POLL) Approximate time in us to spin waiting for packets on the device queue. +This sets the default value of the SO_LL socket option. +Can be set or overridden per socket by setting socket option SO_LL. Recommended value is 50. May increase power usage. Default: 0 (off) +low_latency_poll +---------------- +Low latency busy poll timeout for poll and select. (needs CONFIG_NET_LL_RX_POLL) +Approximate time in us to spin waiting for packets on the device queue. +Recommended value depends on the number of sockets you poll on. +For several sockets 50, for several hundreds 100. +For more than that you probably want to use epoll. +Note that only sockets with SO_LL set will be busy polled, so you want to either +selectively set SO_LL on those sockets or set sysctl.net.low_latency_read globally. +May increase power usage. +Default: 0 (off) + rmem_default ------------ diff --git a/fs/select.c b/fs/select.c index 8c1c96c27062..79b876eb91da 100644 --- a/fs/select.c +++ b/fs/select.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -384,9 +385,10 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) #define POLLEX_SET (POLLPRI) static inline void wait_key_set(poll_table *wait, unsigned long in, - unsigned long out, unsigned long bit) + unsigned long out, unsigned long bit, + unsigned int ll_flag) { - wait->_key = POLLEX_SET; + wait->_key = POLLEX_SET | ll_flag; if (in & bit) wait->_key |= POLLIN_SET; if (out & bit) @@ -400,6 +402,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) poll_table *wait; int retval, i, timed_out = 0; unsigned long slack = 0; + unsigned int ll_flag = POLL_LL; + u64 ll_time = ll_end_time(); rcu_read_lock(); retval = max_select_fd(n, fds); @@ -422,6 +426,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) retval = 0; for (;;) { unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; + bool can_ll = false; inp = fds->in; outp = fds->out; exp = fds->ex; rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; @@ -449,7 +454,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) f_op = f.file->f_op; mask = DEFAULT_POLLMASK; if (f_op && f_op->poll) { - wait_key_set(wait, in, out, bit); + wait_key_set(wait, in, out, + bit, ll_flag); mask = (*f_op->poll)(f.file, wait); } fdput(f); @@ -468,6 +474,11 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) retval++; wait->_qproc = NULL; } + if (mask & POLL_LL) + can_ll = true; + /* got something, stop busy polling */ + if (retval) + ll_flag = 0; } } if (res_in) @@ -486,6 +497,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) break; } + if (can_ll && can_poll_ll(ll_time)) + continue; + /* * If this is the first loop and we have a timeout * given, then we convert to ktime_t and set the to @@ -717,7 +731,8 @@ struct poll_list { * pwait poll_table will be used by the fd-provided poll handler for waiting, * if pwait->_qproc is non-NULL. */ -static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) +static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait, + bool *can_ll, unsigned int ll_flag) { unsigned int mask; int fd; @@ -731,7 +746,10 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) mask = DEFAULT_POLLMASK; if (f.file->f_op && f.file->f_op->poll) { pwait->_key = pollfd->events|POLLERR|POLLHUP; + pwait->_key |= ll_flag; mask = f.file->f_op->poll(f.file, pwait); + if (mask & POLL_LL) + *can_ll = true; } /* Mask out unneeded events. */ mask &= pollfd->events | POLLERR | POLLHUP; @@ -750,6 +768,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list, ktime_t expire, *to = NULL; int timed_out = 0, count = 0; unsigned long slack = 0; + unsigned int ll_flag = POLL_LL; + u64 ll_time = ll_end_time(); /* Optimise the no-wait case */ if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { @@ -762,6 +782,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, for (;;) { struct poll_list *walk; + bool can_ll = false; for (walk = list; walk != NULL; walk = walk->next) { struct pollfd * pfd, * pfd_end; @@ -776,9 +797,10 @@ static int do_poll(unsigned int nfds, struct poll_list *list, * this. They'll get immediately deregistered * when we break out and return. */ - if (do_pollfd(pfd, pt)) { + if (do_pollfd(pfd, pt, &can_ll, ll_flag)) { count++; pt->_qproc = NULL; + ll_flag = 0; } } } @@ -795,6 +817,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list, if (count || timed_out) break; + if (can_ll && can_poll_ll(ll_time)) + continue; /* * If this is the first loop and we have a timeout * given, then we convert to ktime_t and set the to diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index fcc7c365cee5..5bf2b3a6129e 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -30,6 +30,7 @@ #ifdef CONFIG_NET_LL_RX_POLL struct napi_struct; +extern unsigned int sysctl_net_ll_read __read_mostly; extern unsigned int sysctl_net_ll_poll __read_mostly; /* return values from ndo_ll_poll */ @@ -38,17 +39,18 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; /* we can use sched_clock() because we don't care much about precision * we only care that the average is bounded + * we don't mind a ~2.5% imprecision so <<10 instead of *1000 + * sk->sk_ll_usec is a u_int so this can't overflow */ -static inline u64 ll_end_time(struct sock *sk) +static inline u64 ll_sk_end_time(struct sock *sk) { - u64 end_time = ACCESS_ONCE(sk->sk_ll_usec); - - /* we don't mind a ~2.5% imprecision - * sk->sk_ll_usec is a u_int so this can't overflow - */ - end_time = (end_time << 10) + sched_clock(); + return ((u64)ACCESS_ONCE(sk->sk_ll_usec) << 10) + sched_clock(); +} - return end_time; +/* in poll/select we use the global sysctl_net_ll_poll value */ +static inline u64 ll_end_time(void) +{ + return ((u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10) + sched_clock(); } static inline bool sk_valid_ll(struct sock *sk) @@ -62,10 +64,13 @@ static inline bool can_poll_ll(u64 end_time) return !time_after64(sched_clock(), end_time); } +/* when used in sock_poll() nonblock is known at compile time to be true + * so the loop and end_time will be optimized out + */ static inline bool sk_poll_ll(struct sock *sk, int nonblock) { + u64 end_time = nonblock ? 0 : ll_sk_end_time(sk); const struct net_device_ops *ops; - u64 end_time = ll_end_time(sk); struct napi_struct *napi; int rc = false; @@ -84,7 +89,6 @@ static inline bool sk_poll_ll(struct sock *sk, int nonblock) goto out; do { - rc = ops->ndo_ll_poll(napi); if (rc == LL_FLUSH_FAILED) @@ -95,8 +99,8 @@ static inline bool sk_poll_ll(struct sock *sk, int nonblock) NET_ADD_STATS_BH(sock_net(sk), LINUX_MIB_LOWLATENCYRXPACKETS, rc); - } while (skb_queue_empty(&sk->sk_receive_queue) - && can_poll_ll(end_time) && !nonblock); + } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && + can_poll_ll(end_time)); rc = !skb_queue_empty(&sk->sk_receive_queue); out: @@ -118,7 +122,12 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) #else /* CONFIG_NET_LL_RX_POLL */ -static inline u64 ll_end_time(struct sock *sk) +static inline u64 sk_ll_end_time(struct sock *sk) +{ + return 0; +} + +static inline u64 ll_end_time(void) { return 0; } diff --git a/include/uapi/asm-generic/poll.h b/include/uapi/asm-generic/poll.h index 9ce7f44aebd2..4aee586979ca 100644 --- a/include/uapi/asm-generic/poll.h +++ b/include/uapi/asm-generic/poll.h @@ -30,6 +30,8 @@ #define POLLFREE 0x4000 /* currently only for epoll */ +#define POLL_LL 0x8000 + struct pollfd { int fd; short events; diff --git a/net/core/sock.c b/net/core/sock.c index 1e744b12fda3..b6c619f4d47b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2307,7 +2307,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) #ifdef CONFIG_NET_LL_RX_POLL sk->sk_napi_id = 0; - sk->sk_ll_usec = sysctl_net_ll_poll; + sk->sk_ll_usec = sysctl_net_ll_read; #endif /* diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 62702c2053de..afc677eadd93 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -306,6 +306,14 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "low_latency_read", + .data = &sysctl_net_ll_read, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec + }, +# #endif #endif /* CONFIG_NET */ { diff --git a/net/socket.c b/net/socket.c index 3eec3f76b49c..4da14cbd49b6 100644 --- a/net/socket.c +++ b/net/socket.c @@ -107,6 +107,7 @@ #include #ifdef CONFIG_NET_LL_RX_POLL +unsigned int sysctl_net_ll_read __read_mostly; unsigned int sysctl_net_ll_poll __read_mostly; #endif @@ -1147,13 +1148,24 @@ EXPORT_SYMBOL(sock_create_lite); /* No kernel lock held - perfect */ static unsigned int sock_poll(struct file *file, poll_table *wait) { + unsigned int ll_flag = 0; struct socket *sock; /* * We can't return errors to poll, so it's either yes or no. */ sock = file->private_data; - return sock->ops->poll(file, sock, wait); + + if (sk_valid_ll(sock->sk)) { + /* this socket can poll_ll so tell the system call */ + ll_flag = POLL_LL; + + /* once, only if requested by syscall */ + if (wait && (wait->_key & POLL_LL)) + sk_poll_ll(sock->sk, 1); + } + + return ll_flag | sock->ops->poll(file, sock, wait); } static int sock_mmap(struct file *file, struct vm_area_struct *vma) -- GitLab From 441ac0fcaadc76ad09771812382345001dd2b813 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 25 Jun 2013 16:04:19 -0400 Subject: [PATCH 1862/2900] macvtap: Convert to using rtnl lock Macvtap uses a private lock to protect the relationship between macvtap_queue and macvlan_dev. The private lock is not needed since the relationship is managed by user via open(), release(), and dellink() calls. dellink() already happens under rtnl, so we can safely convert open() and release(), and use it in ioctl() as well. Suggested by Eric Dumazet. Signed-off-by: Vlad Yasevich Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 62 +++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5a76f20776af..efbf2eb6ae78 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -69,7 +69,7 @@ static const struct proto_ops macvtap_socket_ops; * RCU usage: * The macvtap_queue and the macvlan_dev are loosely coupled, the * pointers from one to the other can only be read while rcu_read_lock - * or macvtap_lock is held. + * or rtnl is held. * * Both the file and the macvlan_dev hold a reference on the macvtap_queue * through sock_hold(&q->sk). When the macvlan_dev goes away first, @@ -81,7 +81,6 @@ static const struct proto_ops macvtap_socket_ops; * file or the dev. The data structure is freed through __sk_free * when both our references and any pending SKBs are gone. */ -static DEFINE_SPINLOCK(macvtap_lock); static int macvtap_enable_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) @@ -89,7 +88,7 @@ static int macvtap_enable_queue(struct net_device *dev, struct file *file, struct macvlan_dev *vlan = netdev_priv(dev); int err = -EINVAL; - spin_lock(&macvtap_lock); + ASSERT_RTNL(); if (q->enabled) goto out; @@ -101,7 +100,6 @@ static int macvtap_enable_queue(struct net_device *dev, struct file *file, vlan->numvtaps++; out: - spin_unlock(&macvtap_lock); return err; } @@ -111,7 +109,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvlan_dev *vlan = netdev_priv(dev); int err = -EBUSY; - spin_lock(&macvtap_lock); + rtnl_lock(); if (vlan->numqueues == MAX_MACVTAP_QUEUES) goto out; @@ -130,26 +128,25 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, vlan->numqueues++; out: - spin_unlock(&macvtap_lock); + rtnl_unlock(); return err; } -static int __macvtap_disable_queue(struct macvtap_queue *q) +static int macvtap_disable_queue(struct macvtap_queue *q) { struct macvlan_dev *vlan; struct macvtap_queue *nq; - vlan = rcu_dereference_protected(q->vlan, - lockdep_is_held(&macvtap_lock)); - + ASSERT_RTNL(); if (!q->enabled) return -EINVAL; + vlan = rtnl_dereference(q->vlan); + if (vlan) { int index = q->queue_index; BUG_ON(index >= vlan->numvtaps); - nq = rcu_dereference_protected(vlan->taps[vlan->numvtaps - 1], - lockdep_is_held(&macvtap_lock)); + nq = rtnl_dereference(vlan->taps[vlan->numvtaps - 1]); nq->queue_index = index; rcu_assign_pointer(vlan->taps[index], nq); @@ -162,17 +159,6 @@ static int __macvtap_disable_queue(struct macvtap_queue *q) return 0; } -static int macvtap_disable_queue(struct macvtap_queue *q) -{ - int err; - - spin_lock(&macvtap_lock); - err = __macvtap_disable_queue(q); - spin_unlock(&macvtap_lock); - - return err; -} - /* * The file owning the queue got closed, give up both * the reference that the files holds as well as the @@ -185,12 +171,12 @@ static void macvtap_put_queue(struct macvtap_queue *q) { struct macvlan_dev *vlan; - spin_lock(&macvtap_lock); - vlan = rcu_dereference_protected(q->vlan, - lockdep_is_held(&macvtap_lock)); + rtnl_lock(); + vlan = rtnl_dereference(q->vlan); + if (vlan) { if (q->enabled) - BUG_ON(__macvtap_disable_queue(q)); + BUG_ON(macvtap_disable_queue(q)); vlan->numqueues--; RCU_INIT_POINTER(q->vlan, NULL); @@ -198,7 +184,7 @@ static void macvtap_put_queue(struct macvtap_queue *q) list_del_init(&q->next); } - spin_unlock(&macvtap_lock); + rtnl_unlock(); synchronize_rcu(); sock_put(&q->sk); @@ -260,7 +246,7 @@ static void macvtap_del_queues(struct net_device *dev) struct macvtap_queue *q, *tmp, *qlist[MAX_MACVTAP_QUEUES]; int i, j = 0; - spin_lock(&macvtap_lock); + ASSERT_RTNL(); list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) { list_del_init(&q->next); qlist[j++] = q; @@ -275,9 +261,6 @@ static void macvtap_del_queues(struct net_device *dev) BUG_ON(vlan->numqueues); /* guarantee that any future macvtap_set_queue will fail */ vlan->numvtaps = MAX_MACVTAP_QUEUES; - spin_unlock(&macvtap_lock); - - synchronize_rcu(); for (--j; j >= 0; j--) sock_put(&qlist[j]->sk); @@ -941,11 +924,10 @@ static struct macvlan_dev *macvtap_get_vlan(struct macvtap_queue *q) { struct macvlan_dev *vlan; - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); + ASSERT_RTNL(); + vlan = rtnl_dereference(q->vlan); if (vlan) dev_hold(vlan->dev); - rcu_read_unlock_bh(); return vlan; } @@ -1008,21 +990,27 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return ret; case TUNGETIFF: + rtnl_lock(); vlan = macvtap_get_vlan(q); - if (!vlan) + if (!vlan) { + rtnl_unlock(); return -ENOLINK; + } ret = 0; if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) || put_user(q->flags, &ifr->ifr_flags)) ret = -EFAULT; macvtap_put_vlan(vlan); + rtnl_unlock(); return ret; case TUNSETQUEUE: if (get_user(u, &ifr->ifr_flags)) return -EFAULT; - return macvtap_ioctl_set_queue(file, u); + rtnl_lock(); + ret = macvtap_ioctl_set_queue(file, u); + rtnl_unlock(); case TUNGETFEATURES: if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR | -- GitLab From ac4e4af1e59e16a018527ffa58d9d3f30bb96ca9 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 25 Jun 2013 16:04:20 -0400 Subject: [PATCH 1863/2900] macvtap: Consistently use rcu functions Currently macvtap uses rcu_bh functions in its user facing fuction macvtap_get_user() and macvtap_put_user(). However, its packet handlers use normal rcu as the rcu_read_lock() is taken in netif_receive_skb(). We can safely discontinue the usage or rcu with bh disabled. Signed-off-by: Vlad Yasevich Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index efbf2eb6ae78..d7856a8f589a 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -754,8 +754,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, skb_probe_transport_header(skb, ETH_HLEN); - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); + rcu_read_lock(); + vlan = rcu_dereference(q->vlan); /* copy skb_ubuf_info for callback when skb has no error */ if (zerocopy) { skb_shinfo(skb)->destructor_arg = m->msg_control; @@ -766,7 +766,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, macvlan_start_xmit(skb, vlan->dev); else kfree_skb(skb); - rcu_read_unlock_bh(); + rcu_read_unlock(); return total_len; @@ -774,11 +774,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, kfree_skb(skb); err: - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); + rcu_read_lock(); + vlan = rcu_dereference(q->vlan); if (vlan) vlan->dev->stats.tx_dropped++; - rcu_read_unlock_bh(); + rcu_read_unlock(); return err; } @@ -854,11 +854,11 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, copied += len; done: - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); + rcu_read_lock(); + vlan = rcu_dereference(q->vlan); if (vlan) macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); - rcu_read_unlock_bh(); + rcu_read_unlock(); return ret ? ret : copied; } -- GitLab From 2be5c76794b0e570aa87b012df5ac864ce668a74 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 25 Jun 2013 16:04:21 -0400 Subject: [PATCH 1864/2900] macvtap: Let TUNSETOFFLOAD actually controll offload features. When the user issues TUNSETOFFLOAD ioctl, macvtap does not do anything other then to verify arguments. This patch adds functionality to allow users to actually control offload features. NETIF_F_GSO and NETIF_F_GRO are always on, but the rest of the features can be controlled. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 10 ++++++ drivers/net/macvtap.c | 65 +++++++++++++++++++++++++++++++++++++- include/linux/if_macvlan.h | 2 ++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d811b06e2ccd..18373b6ae37d 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -638,6 +638,14 @@ static int macvlan_ethtool_get_settings(struct net_device *dev, return __ethtool_get_settings(vlan->lowerdev, cmd); } +static netdev_features_t macvlan_fix_features(struct net_device *dev, + netdev_features_t features) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + return features & (vlan->set_features | ~MACVLAN_FEATURES); +} + static const struct ethtool_ops macvlan_ethtool_ops = { .get_link = ethtool_op_get_link, .get_settings = macvlan_ethtool_get_settings, @@ -651,6 +659,7 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_stop = macvlan_stop, .ndo_start_xmit = macvlan_start_xmit, .ndo_change_mtu = macvlan_change_mtu, + .ndo_fix_features = macvlan_fix_features, .ndo_change_rx_flags = macvlan_change_rx_flags, .ndo_set_mac_address = macvlan_set_mac_address, .ndo_set_rx_mode = macvlan_set_mac_lists, @@ -791,6 +800,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, vlan->port = port; vlan->receive = receive; vlan->forward = forward; + vlan->set_features = MACVLAN_FEATURES; vlan->mode = MACVLAN_MODE_VEPA; if (data && data[IFLA_MACVLAN_MODE]) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index d7856a8f589a..7eab01975ed1 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -65,6 +65,9 @@ static struct cdev macvtap_cdev; static const struct proto_ops macvtap_socket_ops; +#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ + NETIF_F_TSO6 | NETIF_F_UFO) +#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) /* * RCU usage: * The macvtap_queue and the macvlan_dev are loosely coupled, the @@ -349,6 +352,11 @@ static int macvtap_newlink(struct net *src_net, struct macvlan_dev *vlan = netdev_priv(dev); INIT_LIST_HEAD(&vlan->queue_list); + /* Since macvlan supports all offloads by default, make + * tap support all offloads also. + */ + vlan->tap_features = TUN_OFFLOADS; + /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ @@ -958,6 +966,58 @@ static int macvtap_ioctl_set_queue(struct file *file, unsigned int flags) return ret; } +static int set_offload(struct macvtap_queue *q, unsigned long arg) +{ + struct macvlan_dev *vlan; + netdev_features_t features; + netdev_features_t feature_mask = 0; + + vlan = rtnl_dereference(q->vlan); + if (!vlan) + return -ENOLINK; + + features = vlan->dev->features; + + if (arg & TUN_F_CSUM) { + feature_mask = NETIF_F_HW_CSUM; + + if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) { + if (arg & TUN_F_TSO_ECN) + feature_mask |= NETIF_F_TSO_ECN; + if (arg & TUN_F_TSO4) + feature_mask |= NETIF_F_TSO; + if (arg & TUN_F_TSO6) + feature_mask |= NETIF_F_TSO6; + } + + if (arg & TUN_F_UFO) + feature_mask |= NETIF_F_UFO; + } + + /* tun/tap driver inverts the usage for TSO offloads, where + * setting the TSO bit means that the userspace wants to + * accept TSO frames and turning it off means that user space + * does not support TSO. + * For macvtap, we have to invert it to mean the same thing. + * When user space turns off TSO, we turn off GSO/LRO so that + * user-space will not receive TSO frames. + */ + if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) + features |= RX_OFFLOADS; + else + features &= ~RX_OFFLOADS; + + /* tap_features are the same as features on tun/tap and + * reflect user expectations. + */ + vlan->tap_features = vlan->dev->features & + (feature_mask | ~TUN_OFFLOADS); + vlan->set_features = features; + netdev_update_features(vlan->dev); + + return 0; +} + /* * provide compatibility with generic tun/tap interface */ @@ -1050,7 +1110,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, got enabled for forwarded frames */ if (!(q->flags & IFF_VNET_HDR)) return -EINVAL; - return 0; + rtnl_lock(); + ret = set_offload(q, arg); + rtnl_unlock(); + return ret; default: return -EINVAL; diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index f49a9f66c3d9..ddd33fd5904d 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -65,6 +65,7 @@ struct macvlan_dev { DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ); + netdev_features_t set_features; enum macvlan_mode mode; u16 flags; int (*receive)(struct sk_buff *skb); @@ -75,6 +76,7 @@ struct macvlan_dev { struct list_head queue_list; int numvtaps; int numqueues; + netdev_features_t tap_features; int minor; }; -- GitLab From 3e4f8b787370978733ca6cae452720a4f0c296b8 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Tue, 25 Jun 2013 16:04:22 -0400 Subject: [PATCH 1865/2900] macvtap: Perform GSO on forwarding path. When macvtap forwards skb to its tap, it needs to check if GSO needs to be performed. This is sometimes necessary when the HW device performed GRO, but the guest reading from the tap does not support it (ex: Windows 7). Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 7eab01975ed1..5bfaecdd2354 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -276,14 +276,44 @@ static void macvtap_del_queues(struct net_device *dev) */ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) { + struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *q = macvtap_get_queue(dev, skb); + netdev_features_t features; if (!q) goto drop; if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) goto drop; - skb_queue_tail(&q->sk.sk_receive_queue, skb); + skb->dev = dev; + /* Apply the forward feature mask so that we perform segmentation + * according to users wishes. + */ + features = netif_skb_features(skb) & vlan->tap_features; + if (netif_needs_gso(skb, features)) { + struct sk_buff *segs = __skb_gso_segment(skb, features, false); + + if (IS_ERR(segs)) + goto drop; + + if (!segs) { + skb_queue_tail(&q->sk.sk_receive_queue, skb); + goto wake_up; + } + + kfree_skb(skb); + while (segs) { + struct sk_buff *nskb = segs->next; + + segs->next = NULL; + skb_queue_tail(&q->sk.sk_receive_queue, segs); + segs = nskb; + } + } else { + skb_queue_tail(&q->sk.sk_receive_queue, skb); + } + +wake_up: wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); return NET_RX_SUCCESS; -- GitLab From 762375766143aba42e74713f8364b4953c40a354 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Mon, 24 Jun 2013 19:46:54 +0800 Subject: [PATCH 1866/2900] doc: fix some syntax errors in netlink mmap sample code Cc: Patrick McHardy Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- Documentation/networking/netlink_mmap.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt index e6088baf109d..5cc600587778 100644 --- a/Documentation/networking/netlink_mmap.txt +++ b/Documentation/networking/netlink_mmap.txt @@ -274,9 +274,9 @@ This example assumes some ring parameters of the ring setup are available. /* Get next frame header */ hdr = rx_ring + frame_offset; - if (hdr->nm_status == NL_MMAP_STATUS_VALID) + if (hdr->nm_status == NL_MMAP_STATUS_VALID) { /* Regular memory mapped frame */ - nlh = (void *hdr) + NL_MMAP_HDRLEN; + nlh = (void *)hdr + NL_MMAP_HDRLEN; len = hdr->nm_len; /* Release empty message immediately. May happen -- GitLab From 6892b41d9701283085b655c6086fb57a5d63fa47 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 25 Jun 2013 21:24:51 +0530 Subject: [PATCH 1867/2900] net: davinci: emac: Convert to devm_* api Use devm_ioremap_resource instead of devm_request_mem_region()/devm_ioremap() and devm_request_irq() instead of request_irq(). This ensures more consistent error values and simplifies error paths. Signed-off-by: Lad, Prabhakar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_emac.c | 49 +++++--------------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index efb6f65a8be3..7a66f9c33159 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1532,7 +1532,7 @@ static int emac_dev_open(struct net_device *ndev) struct device *emac_dev = &ndev->dev; u32 cnt; struct resource *res; - int q, m, ret; + int ret; int i = 0; int k = 0; struct emac_priv *priv = netdev_priv(ndev); @@ -1567,8 +1567,9 @@ static int emac_dev_open(struct net_device *ndev) while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { for (i = res->start; i <= res->end; i++) { - if (request_irq(i, emac_irq, IRQF_DISABLED, - ndev->name, ndev)) + if (devm_request_irq(&priv->pdev->dev, i, emac_irq, + IRQF_DISABLED, + ndev->name, ndev)) goto rollback; } k++; @@ -1641,15 +1642,7 @@ static int emac_dev_open(struct net_device *ndev) rollback: - dev_err(emac_dev, "DaVinci EMAC: request_irq() failed"); - - for (q = k; k >= 0; k--) { - for (m = i; m >= res->start; m--) - free_irq(m, ndev); - res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k-1); - m = res->end; - } - + dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); ret = -EBUSY; err: pm_runtime_put(&priv->pdev->dev); @@ -1667,9 +1660,6 @@ static int emac_dev_open(struct net_device *ndev) */ static int emac_dev_stop(struct net_device *ndev) { - struct resource *res; - int i = 0; - int irq_num; struct emac_priv *priv = netdev_priv(ndev); struct device *emac_dev = &ndev->dev; @@ -1685,13 +1675,6 @@ static int emac_dev_stop(struct net_device *ndev) if (priv->phydev) phy_disconnect(priv->phydev); - /* Free IRQ */ - while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, priv->ndev); - i++; - } - if (netif_msg_drv(priv)) dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); @@ -1856,7 +1839,7 @@ static int davinci_emac_probe(struct platform_device *pdev) struct resource *res; struct net_device *ndev; struct emac_priv *priv; - unsigned long size, hw_ram_addr; + unsigned long hw_ram_addr; struct emac_platform_data *pdata; struct device *emac_dev; struct cpdma_params dma_params; @@ -1907,25 +1890,11 @@ static int davinci_emac_probe(struct platform_device *pdev) emac_dev = &ndev->dev; /* Get EMAC platform data */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev,"error getting res\n"); - rc = -ENOENT; - goto no_pdata; - } - priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; - size = resource_size(res); - if (!devm_request_mem_region(&pdev->dev, res->start, - size, ndev->name)) { - dev_err(&pdev->dev, "failed request_mem_region() for regs\n"); - rc = -ENXIO; - goto no_pdata; - } - - priv->remap_addr = devm_ioremap(&pdev->dev, res->start, size); - if (!priv->remap_addr) { + priv->remap_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->remap_addr)) { dev_err(&pdev->dev, "unable to map IO\n"); - rc = -ENOMEM; + rc = PTR_ERR(priv->remap_addr); goto no_pdata; } priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset; -- GitLab From 151328c828795574bed6ce8b37c3d0bd586e162f Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 25 Jun 2013 21:24:52 +0530 Subject: [PATCH 1868/2900] net: davinci_emac: simplify the OF parser code This patch cleans up the OF parser code, removes unnecessary checks on of_property_read_*() and guards davinci_emac_of_match table with CONFIG_OF. Signed-off-by: Lad, Prabhakar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_emac.c | 67 +++++++++----------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 7a66f9c33159..f118d7133128 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1754,29 +1754,22 @@ static const struct net_device_ops emac_netdev_ops = { #endif }; -#ifdef CONFIG_OF -static struct emac_platform_data - *davinci_emac_of_get_pdata(struct platform_device *pdev, - struct emac_priv *priv) +static struct emac_platform_data * +davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) { struct device_node *np; struct emac_platform_data *pdata = NULL; const u8 *mac_addr; - u32 data; - int ret; - pdata = pdev->dev.platform_data; - if (!pdata) { - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - goto nodata; - } + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) + return pdev->dev.platform_data; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; np = pdev->dev.of_node; - if (!np) - goto nodata; - else - pdata->version = EMAC_VERSION_2; + pdata->version = EMAC_VERSION_2; if (!is_valid_ether_addr(pdata->mac_addr)) { mac_addr = of_get_mac_address(np); @@ -1784,47 +1777,31 @@ static struct emac_platform_data memcpy(pdata->mac_addr, mac_addr, ETH_ALEN); } - ret = of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", &data); - if (!ret) - pdata->ctrl_reg_offset = data; + of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", + &pdata->ctrl_reg_offset); - ret = of_property_read_u32(np, "ti,davinci-ctrl-mod-reg-offset", - &data); - if (!ret) - pdata->ctrl_mod_reg_offset = data; + of_property_read_u32(np, "ti,davinci-ctrl-mod-reg-offset", + &pdata->ctrl_mod_reg_offset); - ret = of_property_read_u32(np, "ti,davinci-ctrl-ram-offset", &data); - if (!ret) - pdata->ctrl_ram_offset = data; + of_property_read_u32(np, "ti,davinci-ctrl-ram-offset", + &pdata->ctrl_ram_offset); - ret = of_property_read_u32(np, "ti,davinci-ctrl-ram-size", &data); - if (!ret) - pdata->ctrl_ram_size = data; + of_property_read_u32(np, "ti,davinci-ctrl-ram-size", + &pdata->ctrl_ram_size); - ret = of_property_read_u32(np, "ti,davinci-rmii-en", &data); - if (!ret) - pdata->rmii_en = data; + of_property_read_u8(np, "ti,davinci-rmii-en", &pdata->rmii_en); - ret = of_property_read_u32(np, "ti,davinci-no-bd-ram", &data); - if (!ret) - pdata->no_bd_ram = data; + pdata->no_bd_ram = of_property_read_bool(np, "ti,davinci-no-bd-ram"); priv->phy_node = of_parse_phandle(np, "phy-handle", 0); if (!priv->phy_node) pdata->phy_id = ""; pdev->dev.platform_data = pdata; -nodata: + return pdata; } -#else -static struct emac_platform_data - *davinci_emac_of_get_pdata(struct platform_device *pdev, - struct emac_priv *priv) -{ - return pdev->dev.platform_data; -} -#endif + /** * davinci_emac_probe - EMAC device probe * @pdev: The DaVinci EMAC device that we are removing @@ -2045,11 +2022,13 @@ static const struct dev_pm_ops davinci_emac_pm_ops = { .resume = davinci_emac_resume, }; +#if IS_ENABLED(CONFIG_OF) static const struct of_device_id davinci_emac_of_match[] = { {.compatible = "ti,davinci-dm6467-emac", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_emac_of_match); +#endif /* davinci_emac_driver: EMAC platform driver structure */ static struct platform_driver davinci_emac_driver = { -- GitLab From 277e2a84c12e0d4af77d0f0a52623211eb6ab223 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Tue, 25 Jun 2013 21:24:53 +0530 Subject: [PATCH 1869/2900] net: davinci_mdio: gaurd the DT code with IS_ENABLED(CONFIG_OF) guard the davinci_mdio_of_mtable table and davinci_mdio_probe_dt() with CONFIG_OF. Signed-off-by: Lad, Prabhakar Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_mdio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index c47f0dbcebb5..dac6f5832d18 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -291,6 +291,7 @@ static int davinci_mdio_write(struct mii_bus *bus, int phy_id, return 0; } +#if IS_ENABLED(CONFIG_OF) static int davinci_mdio_probe_dt(struct mdio_platform_data *data, struct platform_device *pdev) { @@ -308,7 +309,7 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data, return 0; } - +#endif static int davinci_mdio_probe(struct platform_device *pdev) { @@ -477,11 +478,13 @@ static const struct dev_pm_ops davinci_mdio_pm_ops = { .resume_early = davinci_mdio_resume, }; +#if IS_ENABLED(CONFIG_OF) static const struct of_device_id davinci_mdio_of_mtable[] = { { .compatible = "ti,davinci_mdio", }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, davinci_mdio_of_mtable); +#endif static struct platform_driver davinci_mdio_driver = { .driver = { -- GitLab From 87a7b84b588c2ddbde890890855aef18ec34174e Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:29 +0200 Subject: [PATCH 1870/2900] bonding: add helper function bond_get_targets_ip(targets, ip) Add function bond_get_targets_ip(targets, ip) which searches through targets array of ips (arp_targets) and returns the position of first match. If ip == 0, returns the first free slot. On failure to find the ip or free slot, return -1. Use it to verify if the arp we've received is valid and in sysfs. v1->v2: Fix "[2/6] bonding: add helper function bond_get_targets_ip(targets, ip)", per Nikolay's advice, to verify if source ip != 0.0.0.0, otherwise we might update 'null' arp_ip_targets' last_rx. Also, address style. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 21 ++++++------- drivers/net/bonding/bond_sysfs.c | 54 +++++++++++++------------------- drivers/net/bonding/bonding.h | 16 ++++++++++ 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3b31c19972d4..976d28e3498a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2610,19 +2610,16 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) { - int i; - __be32 *targets = bond->params.arp_targets; + if (!sip || !bond_has_this_ip(bond, tip)) { + pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip); + return; + } - for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { - pr_debug("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n", - &sip, &tip, i, &targets[i], - bond_has_this_ip(bond, tip)); - if (sip == targets[i]) { - if (bond_has_this_ip(bond, tip)) - slave->last_arp_rx = jiffies; - return; - } + if (bond_get_targets_ip(bond->params.arp_targets, sip) == -1) { + pr_debug("bva: sip %pI4 not found in targets\n", &sip); + return; } + slave->last_arp_rx = jiffies; } static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, @@ -4839,7 +4836,7 @@ static int __net_init bond_net_init(struct net *net) bond_create_proc_dir(bn); bond_create_sysfs(bn); - + return 0; } diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index f8bee4c0cbf1..ece57f146a60 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -591,7 +591,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, const char *buf, size_t count) { __be32 newtarget; - int i = 0, done = 0, ret = count; + int i = 0, ret = -EINVAL; struct bonding *bond = to_bond(d); __be32 *targets; @@ -602,57 +602,44 @@ static ssize_t bonding_store_arp_targets(struct device *d, if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { pr_err("%s: invalid ARP target %pI4 specified for addition\n", bond->dev->name, &newtarget); - ret = -EINVAL; goto out; } - /* look for an empty slot to put the target in, and check for dupes */ - for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { - if (targets[i] == newtarget) { /* duplicate */ - pr_err("%s: ARP target %pI4 is already present\n", - bond->dev->name, &newtarget); - ret = -EINVAL; - goto out; - } - if (targets[i] == 0) { - pr_info("%s: adding ARP target %pI4.\n", - bond->dev->name, &newtarget); - done = 1; - targets[i] = newtarget; - } + + if (bond_get_targets_ip(targets, newtarget) != -1) { /* dup */ + pr_err("%s: ARP target %pI4 is already present\n", + bond->dev->name, &newtarget); + goto out; } - if (!done) { + + i = bond_get_targets_ip(targets, 0); /* first free slot */ + if (i == -1) { pr_err("%s: ARP target table is full!\n", bond->dev->name); - ret = -EINVAL; goto out; } + pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, + &newtarget); + targets[i] = newtarget; } else if (buf[0] == '-') { if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { pr_err("%s: invalid ARP target %pI4 specified for removal\n", bond->dev->name, &newtarget); - ret = -EINVAL; goto out; } - for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { - if (targets[i] == newtarget) { - int j; - pr_info("%s: removing ARP target %pI4.\n", - bond->dev->name, &newtarget); - for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++) - targets[j] = targets[j+1]; - - targets[j] = 0; - done = 1; - } - } - if (!done) { + i = bond_get_targets_ip(targets, newtarget); + if (i == -1) { pr_info("%s: unable to remove nonexistent ARP target %pI4.\n", bond->dev->name, &newtarget); - ret = -EINVAL; goto out; } + + pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, + &newtarget); + for (; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) + targets[i] = targets[i+1]; + targets[i] = 0; } else { pr_err("no command found in arp_ip_targets file for bond %s. Use + or -.\n", bond->dev->name); @@ -660,6 +647,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; } + ret = count; out: return ret; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c990b42cf7a1..486e532f77e4 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -464,6 +464,22 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond, return NULL; } +/* Check if the ip is present in arp ip list, or first free slot if ip == 0 + * Returns -1 if not found, index if found + */ +static inline int bond_get_targets_ip(__be32 *targets, __be32 ip) +{ + int i; + + for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) + if (targets[i] == ip) + return i; + else if (targets[i] == 0) + break; + + return -1; +} + /* exported from bond_main.c */ extern int bond_net_id; extern const struct bond_parm_tbl bond_lacp_tbl[]; -- GitLab From 0afee4e8b9fe4b5f58734b2f28e980dd58d3e3cb Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:30 +0200 Subject: [PATCH 1871/2900] bonding: don't add duplicate targets to arp_ip_target Print a warning and skip them. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 976d28e3498a..1645130c0a60 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4588,7 +4588,11 @@ static int bond_check_params(struct bond_params *params) arp_ip_target[i]); arp_interval = 0; } else { - arp_target[arp_ip_count++] = ip; + if (bond_get_targets_ip(arp_target, ip) == -1) + arp_target[arp_ip_count++] = ip; + else + pr_warning("Warning: duplicate address %pI4 in arp_ip_target, skipping\n", + &ip); } } -- GitLab From 2c14610210978512271dd6fe21d6f55b789d9a80 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:31 +0200 Subject: [PATCH 1872/2900] bonding: don't validate arp if we don't have to Currently, we validate all the incoming arps if arp_validate not 0. However, we don't have to validate backup slaves if arp_validate == active and vice versa, so return early in bond_arp_rcv() in these cases. It works correctly now because we verify arp_validate in slave_last_rx(), however we're just doing useless work in bond_arp_rcv(). Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1645130c0a60..7fe9802c9eec 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2634,6 +2634,10 @@ static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, return RX_HANDLER_ANOTHER; read_lock(&bond->lock); + + if (!slave_do_arp_validate(bond, slave)) + goto out_unlock; + alen = arp_hdr_len(bond->dev); pr_debug("bond_arp_rcv: bond %s skb->dev %s\n", -- GitLab From aeea64ac717a920ea655b061e37b14fbc872f7db Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:32 +0200 Subject: [PATCH 1873/2900] bonding: don't trust arp requests unless active slave really works Currently, if we receive any arp packet on a backup slave in active-backup mode and arp_validate enabled, we suppose that it's an arp request, swap source/target ip and try to validate it. This optimization gives us virtually no downtime in the most common situation (active and backup slaves are in the same broadcast domain and the active slave failed). However, if we can't reach the arp_ip_target(s), we end up in an endless loop of reselecting slaves, because we receive our arp requests, sent by the active slave, and think that backup slaves are up, thus selecting them as active and, again, sending arp requests, which fool our backup slaves. Fix this by not validating the swapped arp packets if the current active slave didn't receive any arp reply after it was selected as active. This way we will only accept arp requests if we know that the current active slave can actually reach arp_ip_target. v3->v4: Obey 80 lines and make checkpatch.pl happy, per Sergei's suggestion. v1->v3: No change. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7fe9802c9eec..d3a70c0d0edd 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2677,10 +2677,17 @@ static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, * configuration, the ARP probe will (hopefully) travel from * the active, through one switch, the router, then the other * switch before reaching the backup. + * + * We 'trust' the arp requests if there is an active slave and + * it received valid arp reply(s) after it became active. This + * is done to avoid endless looping when we can't reach the + * arp_ip_target and fool ourselves with our own arp requests. */ if (bond_is_active_slave(slave)) bond_validate_arp(bond, slave, sip, tip); - else + else if (bond->curr_active_slave && + time_after(slave_last_rx(bond, bond->curr_active_slave), + bond->curr_active_slave->jiffies)) bond_validate_arp(bond, slave, tip, sip); out_unlock: -- GitLab From d7d35c681fb4eae1fab3d93698e26a106ca7e79e Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:33 +0200 Subject: [PATCH 1874/2900] bonding: doc: some details on backup slave arp validation Add some details to bonding documentation on how backup slave arp validation works. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- Documentation/networking/bonding.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index e7454fcc9176..adee3b4a75cb 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -303,6 +303,12 @@ arp_validate such a situation, validation of backup slaves must be disabled. + The validation of ARP requests on backup slaves is mainly + helping bonding to decide which slaves are more likely to + work in case of the active slave failure, it doesn't really + guarantee that the backup slave will work if it's selected + as the next active slave. + This option is useful in network configurations in which multiple bonding hosts are concurrently issuing ARPs to one or more targets beyond a common switch. Should the link between -- GitLab From 8599b52e14a1611dcb563289421bee76751f1d53 Mon Sep 17 00:00:00 2001 From: Veaceslav Falico Date: Mon, 24 Jun 2013 11:49:34 +0200 Subject: [PATCH 1875/2900] bonding: add an option to fail when any of arp_ip_target is inaccessible Currently, we fail only when all of the ips in arp_ip_target are gone. However, in some situations we might need to fail if even one host from arp_ip_target becomes unavailable. All situations, obviously, rely on the idea that we need *completely* functional network, with all interfaces/addresses working correctly. One real world example might be: vlans on top on bond (hybrid port). If bond and vlans have ips assigned and we have their peers monitored via arp_ip_target - in case of switch misconfiguration (trunk/access port), slave driver malfunction or tagged/untagged traffic dropped on the way - we will be able to switch to another slave. Though any other configuration needs that if we need to have access to all arp_ip_targets. This patch adds this possibility by adding a new parameter - arp_all_targets (both as a module parameter and as a sysfs knob). It can be set to: 0 or any (the default) - which works exactly as it's working now - the slave is up if any of the arp_ip_targets are up. 1 or all - the slave is up if all of the arp_ip_targets are up. This parameter can be changed on the fly (via sysfs), and requires the mode to be active-backup and arp_validate to be enabled (it obeys the arp_validate config on which slaves to validate). Internally it's done through: 1) Add target_last_arp_rx[BOND_MAX_ARP_TARGETS] array to slave struct. It's an array of jiffies, meaning that slave->target_last_arp_rx[i] is the last time we've received arp from bond->params.arp_targets[i] on this slave. 2) If we successfully validate an arp from bond->params.arp_targets[i] in bond_validate_arp() - update the slave->target_last_arp_rx[i] with the current jiffies value. 3) When getting slave's last_rx via slave_last_rx(), we return the oldest time when we've received an arp from any address in bond->params.arp_targets[]. If the value of arp_all_targets == 0 - we still work the same way as before. Also, update the documentation to reflect the new parameter. v3->v4: Kill the forgotten rtnl_unlock(), rephrase the documentation part to be more clear, don't fail setting arp_all_targets if arp_validate is not set - it has no effect anyway but can be easier to set up. Also, print a warning if the last arp_ip_target is removed while the arp_interval is on, but not the arp_validate. v2->v3: Use _bh spinlock, remove useless rtnl_lock() and use jiffies for new arp_ip_target last arp, instead of slave_last_rx(). On bond_enslave(), use the same initialization value for target_last_arp_rx[] as is used for the default last_arp_rx, to avoid useless interface flaps. Also, instead of failing to remove the last arp_ip_target just print a warning - otherwise it might break existing scripts. v1->v2: Correctly handle adding/removing hosts in arp_ip_target - we need to shift/initialize all slave's target_last_arp_rx. Also, don't fail module loading on arp_all_targets misconfiguration, just disable it, and some minor style fixes. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller --- Documentation/networking/bonding.txt | 19 +++++++ drivers/net/bonding/bond_main.c | 33 +++++++++++- drivers/net/bonding/bond_sysfs.c | 79 ++++++++++++++++++++++++---- drivers/net/bonding/bonding.h | 30 ++++++++++- 4 files changed, 147 insertions(+), 14 deletions(-) diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index adee3b4a75cb..87bbcfee2e06 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt @@ -321,6 +321,25 @@ arp_validate This option was added in bonding version 3.1.0. +arp_all_targets + + Specifies the quantity of arp_ip_targets that must be reachable + in order for the ARP monitor to consider a slave as being up. + This option affects only active-backup mode for slaves with + arp_validation enabled. + + Possible values are: + + any or 0 + + consider the slave up only when any of the arp_ip_targets + is reachable + + all or 1 + + consider the slave up only when all of the arp_ip_targets + are reachable + downdelay Specifies the time, in milliseconds, to wait before disabling diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d3a70c0d0edd..142d55dc526e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -104,6 +104,7 @@ static char *xmit_hash_policy; static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; static char *arp_validate; +static char *arp_all_targets; static char *fail_over_mac; static int all_slaves_active = 0; static struct bond_params bonding_defaults; @@ -166,6 +167,8 @@ module_param(arp_validate, charp, 0); MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes; " "0 for none (default), 1 for active, " "2 for backup, 3 for all"); +module_param(arp_all_targets, charp, 0); +MODULE_PARM_DESC(arp_all_targets, "fail on any/all arp targets timeout; 0 for any (default), 1 for all"); module_param(fail_over_mac, charp, 0); MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to " "the same MAC; 0 for none (default), " @@ -216,6 +219,12 @@ const struct bond_parm_tbl xmit_hashtype_tbl[] = { { NULL, -1}, }; +const struct bond_parm_tbl arp_all_targets_tbl[] = { +{ "any", BOND_ARP_TARGETS_ANY}, +{ "all", BOND_ARP_TARGETS_ALL}, +{ NULL, -1}, +}; + const struct bond_parm_tbl arp_validate_tbl[] = { { "none", BOND_ARP_VALIDATE_NONE}, { "active", BOND_ARP_VALIDATE_ACTIVE}, @@ -1483,7 +1492,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) struct slave *new_slave = NULL; struct sockaddr addr; int link_reporting; - int res = 0; + int res = 0, i; if (!bond->params.use_carrier && slave_dev->ethtool_ops->get_link == NULL && @@ -1712,6 +1721,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) new_slave->last_arp_rx = jiffies - (msecs_to_jiffies(bond->params.arp_interval) + 1); + for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) + new_slave->target_last_arp_rx[i] = new_slave->last_arp_rx; if (bond->params.miimon && !bond->params.use_carrier) { link_reporting = bond_check_dev_link(bond, slave_dev, 1); @@ -2610,16 +2621,20 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) { + int i; + if (!sip || !bond_has_this_ip(bond, tip)) { pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip); return; } - if (bond_get_targets_ip(bond->params.arp_targets, sip) == -1) { + i = bond_get_targets_ip(bond->params.arp_targets, sip); + if (i == -1) { pr_debug("bva: sip %pI4 not found in targets\n", &sip); return; } slave->last_arp_rx = jiffies; + slave->target_last_arp_rx[i] = jiffies; } static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, @@ -4409,6 +4424,7 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl) static int bond_check_params(struct bond_params *params) { int arp_validate_value, fail_over_mac_value, primary_reselect_value, i; + int arp_all_targets_value; /* * Convert string parameters. @@ -4634,6 +4650,18 @@ static int bond_check_params(struct bond_params *params) } else arp_validate_value = 0; + arp_all_targets_value = 0; + if (arp_all_targets) { + arp_all_targets_value = bond_parse_parm(arp_all_targets, + arp_all_targets_tbl); + + if (arp_all_targets_value == -1) { + pr_err("Error: invalid arp_all_targets_value \"%s\"\n", + arp_all_targets); + arp_all_targets_value = 0; + } + } + if (miimon) { pr_info("MII link monitoring set to %d ms\n", miimon); } else if (arp_interval) { @@ -4698,6 +4726,7 @@ static int bond_check_params(struct bond_params *params) params->num_peer_notif = num_peer_notif; params->arp_interval = arp_interval; params->arp_validate = arp_validate_value; + params->arp_all_targets = arp_all_targets_value; params->updelay = updelay; params->downdelay = downdelay; params->use_carrier = use_carrier; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index ece57f146a60..dc36a3d7d9e9 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -443,6 +443,44 @@ static ssize_t bonding_store_arp_validate(struct device *d, static DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); +/* + * Show and set arp_all_targets. + */ +static ssize_t bonding_show_arp_all_targets(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct bonding *bond = to_bond(d); + int value = bond->params.arp_all_targets; + + return sprintf(buf, "%s %d\n", arp_all_targets_tbl[value].modename, + value); +} + +static ssize_t bonding_store_arp_all_targets(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bonding *bond = to_bond(d); + int new_value; + + new_value = bond_parse_parm(buf, arp_all_targets_tbl); + if (new_value < 0) { + pr_err("%s: Ignoring invalid arp_all_targets value %s\n", + bond->dev->name, buf); + return -EINVAL; + } + pr_info("%s: setting arp_all_targets to %s (%d).\n", + bond->dev->name, arp_all_targets_tbl[new_value].modename, + new_value); + + bond->params.arp_all_targets = new_value; + + return count; +} + +static DEVICE_ATTR(arp_all_targets, S_IRUGO | S_IWUSR, + bonding_show_arp_all_targets, bonding_store_arp_all_targets); /* * Show and store fail_over_mac. User only allowed to change the @@ -590,10 +628,11 @@ static ssize_t bonding_store_arp_targets(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - __be32 newtarget; - int i = 0, ret = -EINVAL; struct bonding *bond = to_bond(d); - __be32 *targets; + struct slave *slave; + __be32 newtarget, *targets; + unsigned long *targets_rx; + int ind, i, j, ret = -EINVAL; targets = bond->params.arp_targets; newtarget = in_aton(buf + 1); @@ -611,8 +650,8 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; } - i = bond_get_targets_ip(targets, 0); /* first free slot */ - if (i == -1) { + ind = bond_get_targets_ip(targets, 0); /* first free slot */ + if (ind == -1) { pr_err("%s: ARP target table is full!\n", bond->dev->name); goto out; @@ -620,7 +659,12 @@ static ssize_t bonding_store_arp_targets(struct device *d, pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, &newtarget); - targets[i] = newtarget; + /* not to race with bond_arp_rcv */ + write_lock_bh(&bond->lock); + bond_for_each_slave(bond, slave, i) + slave->target_last_arp_rx[ind] = jiffies; + targets[ind] = newtarget; + write_unlock_bh(&bond->lock); } else if (buf[0] == '-') { if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { pr_err("%s: invalid ARP target %pI4 specified for removal\n", @@ -628,18 +672,32 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; } - i = bond_get_targets_ip(targets, newtarget); - if (i == -1) { - pr_info("%s: unable to remove nonexistent ARP target %pI4.\n", + ind = bond_get_targets_ip(targets, newtarget); + if (ind == -1) { + pr_err("%s: unable to remove nonexistent ARP target %pI4.\n", bond->dev->name, &newtarget); goto out; } + if (ind == 0 && !targets[1] && bond->params.arp_interval) + pr_warn("%s: removing last arp target with arp_interval on\n", + bond->dev->name); + pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, &newtarget); - for (; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) + + write_lock_bh(&bond->lock); + bond_for_each_slave(bond, slave, i) { + targets_rx = slave->target_last_arp_rx; + j = ind; + for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++) + targets_rx[j] = targets_rx[j+1]; + targets_rx[j] = 0; + } + for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) targets[i] = targets[i+1]; targets[i] = 0; + write_unlock_bh(&bond->lock); } else { pr_err("no command found in arp_ip_targets file for bond %s. Use + or -.\n", bond->dev->name); @@ -1623,6 +1681,7 @@ static struct attribute *per_bond_attrs[] = { &dev_attr_mode.attr, &dev_attr_fail_over_mac.attr, &dev_attr_arp_validate.attr, + &dev_attr_arp_all_targets.attr, &dev_attr_arp_interval.attr, &dev_attr_arp_ip_target.attr, &dev_attr_downdelay.attr, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 486e532f77e4..3fb73cc8c34a 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -144,6 +144,7 @@ struct bond_params { u8 num_peer_notif; int arp_interval; int arp_validate; + int arp_all_targets; int use_carrier; int fail_over_mac; int updelay; @@ -179,6 +180,7 @@ struct slave { int delay; unsigned long jiffies; unsigned long last_arp_rx; + unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS]; s8 link; /* one of BOND_LINK_XXXX */ s8 new_link; u8 backup:1, /* indicates backup slave. Value corresponds with @@ -322,6 +324,9 @@ static inline bool bond_is_active_slave(struct slave *slave) #define BOND_FOM_ACTIVE 1 #define BOND_FOM_FOLLOW 2 +#define BOND_ARP_TARGETS_ANY 0 +#define BOND_ARP_TARGETS_ALL 1 + #define BOND_ARP_VALIDATE_NONE 0 #define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE) #define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP) @@ -334,11 +339,31 @@ static inline int slave_do_arp_validate(struct bonding *bond, return bond->params.arp_validate & (1 << bond_slave_state(slave)); } +/* Get the oldest arp which we've received on this slave for bond's + * arp_targets. + */ +static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond, + struct slave *slave) +{ + int i = 1; + unsigned long ret = slave->target_last_arp_rx[0]; + + for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++) + if (time_before(slave->target_last_arp_rx[i], ret)) + ret = slave->target_last_arp_rx[i]; + + return ret; +} + static inline unsigned long slave_last_rx(struct bonding *bond, struct slave *slave) { - if (slave_do_arp_validate(bond, slave)) - return slave->last_arp_rx; + if (slave_do_arp_validate(bond, slave)) { + if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) + return slave_oldest_target_arp_rx(bond, slave); + else + return slave->last_arp_rx; + } return slave->dev->last_rx; } @@ -486,6 +511,7 @@ extern const struct bond_parm_tbl bond_lacp_tbl[]; extern const struct bond_parm_tbl bond_mode_tbl[]; extern const struct bond_parm_tbl xmit_hashtype_tbl[]; extern const struct bond_parm_tbl arp_validate_tbl[]; +extern const struct bond_parm_tbl arp_all_targets_tbl[]; extern const struct bond_parm_tbl fail_over_mac_tbl[]; extern const struct bond_parm_tbl pri_reselect_tbl[]; extern struct bond_parm_tbl ad_select_tbl[]; -- GitLab From 537f7f8494be4219eb0ef47121ea16a6f9f0f49e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 25 Jun 2013 09:34:36 -0700 Subject: [PATCH 1876/2900] bridge: check for zero ether address in fdb add The check for all-zero ether address was removed from rtnetlink core, since Vxlan uses all-zero ether address to signify default address. Need to add check back in for bridge. Signed-off-by: Stephen Hemminger --- net/bridge/br_fdb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index ebfa4443c69b..60aca9109a50 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -707,6 +707,11 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], } } + if (is_zero_ether_addr(addr)) { + pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); + return -EINVAL; + } + p = br_port_get_rtnl(dev); if (p == NULL) { pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", -- GitLab From ba609e9bf15bd7df35e2c06a2e5aaf9ab9289b10 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 25 Jun 2013 17:06:01 -0700 Subject: [PATCH 1877/2900] vxlan: fix function name spelling Signed-off-by: Stephen Hemminger --- drivers/net/vxlan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 3e75f9726c33..227b54a1f88a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1332,7 +1332,7 @@ static int vxlan_init(struct net_device *dev) return 0; } -static void vxlan_fdb_delete_defualt(struct vxlan_dev *vxlan) +static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan) { struct vxlan_fdb *f; @@ -1349,7 +1349,7 @@ static void vxlan_uninit(struct net_device *dev) struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_sock *vs = vxlan->vn_sock; - vxlan_fdb_delete_defualt(vxlan); + vxlan_fdb_delete_default(vxlan); if (vs) vxlan_sock_release(vn, vs); @@ -1756,7 +1756,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, err = register_netdevice(dev); if (err) { - vxlan_fdb_delete_defualt(vxlan); + vxlan_fdb_delete_default(vxlan); return err; } -- GitLab From 889c8a68b8483a8b3482ac440af3ad7368c58555 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 14 Jun 2013 18:49:55 -0700 Subject: [PATCH 1878/2900] iscsi-target: Refactor ISCSI_OP_TEXT_RSP TX handling This patch refactoring existing iscsit_send_text_rsp() in order to handle iscsi_text_rsp payloads in a transport specific manner. This includes the addition of iscsit_build_text_rsp() to build the response payload and initialize ISCSI_OP_TEXT_RSP. v2: Make iscsit_build_text_rsp() determine extra padding bytes, and drop legacy padding calculation for traditional iSCSI text responses within iscsit_send_text_rsp() Reported-by: Or Gerlitz Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 77 ++++++++++++++------------ include/target/iscsi/iscsi_transport.h | 2 + 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ae312c5d8a45..1f79a168f1c1 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3461,52 +3461,62 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) return payload_len; } -/* - * FIXME: Add support for F_BIT and C_BIT when the length is longer than - * MaxRecvDataSegmentLength. - */ -static int iscsit_send_text_rsp( - struct iscsi_cmd *cmd, - struct iscsi_conn *conn) +int +iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, + struct iscsi_text_rsp *hdr) { - struct iscsi_text_rsp *hdr; - struct kvec *iov; - u32 padding = 0, tx_size = 0; - int text_length, iov_count = 0; + int text_length, padding; text_length = iscsit_build_sendtargets_response(cmd); if (text_length < 0) return text_length; + hdr->opcode = ISCSI_OP_TEXT_RSP; + hdr->flags |= ISCSI_FLAG_CMD_FINAL; padding = ((-text_length) & 3); - if (padding != 0) { - memset(cmd->buf_ptr + text_length, 0, padding); - pr_debug("Attaching %u additional bytes for" - " padding.\n", padding); - } - - hdr = (struct iscsi_text_rsp *) cmd->pdu; - memset(hdr, 0, ISCSI_HDR_LEN); - hdr->opcode = ISCSI_OP_TEXT_RSP; - hdr->flags |= ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, text_length); - hdr->itt = cmd->init_task_tag; - hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); - cmd->stat_sn = conn->stat_sn++; - hdr->statsn = cpu_to_be32(cmd->stat_sn); + hdr->itt = cmd->init_task_tag; + hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag); + cmd->stat_sn = conn->stat_sn++; + hdr->statsn = cpu_to_be32(cmd->stat_sn); iscsit_increment_maxcmdsn(cmd, conn->sess); - hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); - hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); + hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); + hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); - iov = &cmd->iov_misc[0]; + pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x," + " Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn, + text_length, conn->cid); + + return text_length + padding; +} +EXPORT_SYMBOL(iscsit_build_text_rsp); +/* + * FIXME: Add support for F_BIT and C_BIT when the length is longer than + * MaxRecvDataSegmentLength. + */ +static int iscsit_send_text_rsp( + struct iscsi_cmd *cmd, + struct iscsi_conn *conn) +{ + struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu; + struct kvec *iov; + u32 tx_size = 0; + int text_length, iov_count = 0, rc; + + rc = iscsit_build_text_rsp(cmd, conn, hdr); + if (rc < 0) + return rc; + + text_length = rc; + iov = &cmd->iov_misc[0]; iov[iov_count].iov_base = cmd->pdu; iov[iov_count++].iov_len = ISCSI_HDR_LEN; iov[iov_count].iov_base = cmd->buf_ptr; - iov[iov_count++].iov_len = text_length + padding; + iov[iov_count++].iov_len = text_length; - tx_size += (ISCSI_HDR_LEN + text_length + padding); + tx_size += (ISCSI_HDR_LEN + text_length); if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; @@ -3522,7 +3532,7 @@ static int iscsit_send_text_rsp( if (conn->conn_ops->DataDigest) { iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, - cmd->buf_ptr, (text_length + padding), + cmd->buf_ptr, text_length, 0, NULL, (u8 *)&cmd->data_crc); iov[iov_count].iov_base = &cmd->data_crc; @@ -3530,16 +3540,13 @@ static int iscsit_send_text_rsp( tx_size += ISCSI_CRC_LEN; pr_debug("Attaching DataDigest for %u bytes of text" - " data, CRC 0x%08x\n", (text_length + padding), + " data, CRC 0x%08x\n", text_length, cmd->data_crc); } cmd->iov_misc_count = iov_count; cmd->tx_size = tx_size; - pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x," - " Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn, - text_length, conn->cid); return 0; } diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index 90f3b60d30c4..ce991ba9e887 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -63,6 +63,8 @@ extern void iscsit_build_nopin_rsp(struct iscsi_cmd *, struct iscsi_conn *, struct iscsi_nopin *, bool); extern void iscsit_build_task_mgt_rsp(struct iscsi_cmd *, struct iscsi_conn *, struct iscsi_tm_rsp *); +extern int iscsit_build_text_rsp(struct iscsi_cmd *, struct iscsi_conn *, + struct iscsi_text_rsp *); extern void iscsit_build_reject(struct iscsi_cmd *, struct iscsi_conn *, struct iscsi_reject *); extern int iscsit_build_logout_rsp(struct iscsi_cmd *, struct iscsi_conn *, -- GitLab From a4a1139b242f03dfb8a5d7a86fa674bda1cf60b2 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 26 Jun 2013 11:49:26 +0400 Subject: [PATCH 1879/2900] arc_emac: fix compile-time errors & warnings on PPC64 As reported by "kbuild test robot" there were some errors and warnings on attempt to build kernel with "make ARCH=powerpc allmodconfig". And this patch addresses both errors and warnings. Below is a list of introduced changes: 1. Fix compile-time errors (misspellings in "dma_unmap_single") on PPC. 2. Use DMA address instead of "skb->data" as a pointer to data buffer. This fixed warnings on pointer to int conversion on 64-bit systems. 3. Re-implemented initial allocation of Rx buffers in "arc_emac_open" in the same way they're re-allocated during operation (receiving packets). So once again DMA address could be used instead of "skb->data". 4. Explicitly use EMAC_BUFFER_SIZE for Rx buffers allocation. Signed-off-by: Alexey Brodkin Cc: netdev@vger.kernel.org Cc: Andy Shevchenko Cc: Francois Romieu Cc: Joe Perches Cc: Vineet Gupta Cc: Mischa Jonker Cc: Arnd Bergmann Cc: Grant Likely Cc: Rob Herring Cc: Paul Gortmaker Cc: linux-kernel@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org Cc: Florian Fainelli Cc: David Laight Signed-off-by: David S. Miller --- drivers/net/ethernet/arc/emac_main.c | 65 +++++++++++++++++----------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 20345f6bf894..f1b121ee5525 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -171,8 +171,8 @@ static void arc_emac_tx_clean(struct net_device *ndev) stats->tx_bytes += skb->len; } - dma_unmap_single(&ndev->dev, dma_unmap_addr(&tx_buff, addr), - dma_unmap_len(&tx_buff, len), DMA_TO_DEVICE); + dma_unmap_single(&ndev->dev, dma_unmap_addr(tx_buff, addr), + dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); /* return the sk_buff to system */ dev_kfree_skb_irq(skb); @@ -204,7 +204,6 @@ static int arc_emac_rx(struct net_device *ndev, int budget) struct net_device_stats *stats = &priv->stats; struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd]; struct arc_emac_bd *rxbd = &priv->rxbd[*last_rx_bd]; - unsigned int buflen = EMAC_BUFFER_SIZE; unsigned int pktlen, info = le32_to_cpu(rxbd->info); struct sk_buff *skb; dma_addr_t addr; @@ -226,7 +225,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget) netdev_err(ndev, "incomplete packet received\n"); /* Return ownership to EMAC */ - rxbd->info = cpu_to_le32(FOR_EMAC | buflen); + rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); stats->rx_errors++; stats->rx_length_errors++; continue; @@ -240,11 +239,12 @@ static int arc_emac_rx(struct net_device *ndev, int budget) skb->dev = ndev; skb->protocol = eth_type_trans(skb, ndev); - dma_unmap_single(&ndev->dev, dma_unmap_addr(&rx_buff, addr), - dma_unmap_len(&rx_buff, len), DMA_FROM_DEVICE); + dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr), + dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE); /* Prepare the BD for next cycle */ - rx_buff->skb = netdev_alloc_skb_ip_align(ndev, buflen); + rx_buff->skb = netdev_alloc_skb_ip_align(ndev, + EMAC_BUFFER_SIZE); if (unlikely(!rx_buff->skb)) { stats->rx_errors++; /* Because receive_skb is below, increment rx_dropped */ @@ -256,7 +256,7 @@ static int arc_emac_rx(struct net_device *ndev, int budget) netif_receive_skb(skb); addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data, - buflen, DMA_FROM_DEVICE); + EMAC_BUFFER_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(&ndev->dev, addr)) { if (net_ratelimit()) netdev_err(ndev, "cannot dma map\n"); @@ -264,16 +264,16 @@ static int arc_emac_rx(struct net_device *ndev, int budget) stats->rx_errors++; continue; } - dma_unmap_addr_set(&rx_buff, mapping, addr); - dma_unmap_len_set(&rx_buff, len, buflen); + dma_unmap_addr_set(rx_buff, addr, addr); + dma_unmap_len_set(rx_buff, len, EMAC_BUFFER_SIZE); - rxbd->data = cpu_to_le32(rx_buff->skb->data); + rxbd->data = cpu_to_le32(addr); /* Make sure pointer to data buffer is set */ wmb(); /* Return ownership to EMAC */ - rxbd->info = cpu_to_le32(FOR_EMAC | buflen); + rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); } return work_done; @@ -376,8 +376,6 @@ static int arc_emac_open(struct net_device *ndev) { struct arc_emac_priv *priv = netdev_priv(ndev); struct phy_device *phy_dev = priv->phy_dev; - struct arc_emac_bd *bd; - struct sk_buff *skb; int i; phy_dev->autoneg = AUTONEG_ENABLE; @@ -395,25 +393,40 @@ static int arc_emac_open(struct net_device *ndev) } } + priv->last_rx_bd = 0; + /* Allocate and set buffers for Rx BD's */ - bd = priv->rxbd; for (i = 0; i < RX_BD_NUM; i++) { - skb = netdev_alloc_skb_ip_align(ndev, EMAC_BUFFER_SIZE); - if (unlikely(!skb)) + dma_addr_t addr; + unsigned int *last_rx_bd = &priv->last_rx_bd; + struct arc_emac_bd *rxbd = &priv->rxbd[*last_rx_bd]; + struct buffer_state *rx_buff = &priv->rx_buff[*last_rx_bd]; + + rx_buff->skb = netdev_alloc_skb_ip_align(ndev, + EMAC_BUFFER_SIZE); + if (unlikely(!rx_buff->skb)) + return -ENOMEM; + + addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data, + EMAC_BUFFER_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(&ndev->dev, addr)) { + netdev_err(ndev, "cannot dma map\n"); + dev_kfree_skb(rx_buff->skb); return -ENOMEM; + } + dma_unmap_addr_set(rx_buff, addr, addr); + dma_unmap_len_set(rx_buff, len, EMAC_BUFFER_SIZE); - priv->rx_buff[i].skb = skb; - bd->data = cpu_to_le32(skb->data); + rxbd->data = cpu_to_le32(addr); /* Make sure pointer to data buffer is set */ wmb(); - /* Set ownership to EMAC */ - bd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); - bd++; - } + /* Return ownership to EMAC */ + rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE); - priv->last_rx_bd = 0; + *last_rx_bd = (*last_rx_bd + 1) % RX_BD_NUM; + } /* Clean Tx BD's */ memset(priv->txbd, 0, TX_RING_SZ); @@ -543,11 +556,11 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) dev_kfree_skb(skb); return NETDEV_TX_OK; } - dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], mapping, addr); + dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr); dma_unmap_len_set(&priv->tx_buff[*txbd_curr], len, len); priv->tx_buff[*txbd_curr].skb = skb; - priv->txbd[*txbd_curr].data = cpu_to_le32(skb->data); + priv->txbd[*txbd_curr].data = cpu_to_le32(addr); /* Make sure pointer to data buffer is set */ wmb(); -- GitLab From bba54de5bdd107d3841b560f1a9cb0ed06e79533 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sun, 16 Jun 2013 09:09:36 +0300 Subject: [PATCH 1880/2900] ipvs: provide iph to schedulers Before now the schedulers needed access only to IP addresses and it was easy to get them from skb by using ip_vs_fill_iph_addr_only. New changes for the SH scheduler will need the protocol and ports which is difficult to get from skb for the IPv6 case. As we have all the data in the iph structure, to avoid the same slow lookups provide the iph to schedulers. Signed-off-by: Julian Anastasov Acked-by: Hans Schillstrom Signed-off-by: Simon Horman --- include/net/ip_vs.h | 28 ++-------------------------- net/netfilter/ipvs/ip_vs_core.c | 4 ++-- net/netfilter/ipvs/ip_vs_dh.c | 10 ++++------ net/netfilter/ipvs/ip_vs_lblc.c | 12 +++++------- net/netfilter/ipvs/ip_vs_lblcr.c | 12 +++++------- net/netfilter/ipvs/ip_vs_lc.c | 3 ++- net/netfilter/ipvs/ip_vs_nq.c | 3 ++- net/netfilter/ipvs/ip_vs_rr.c | 3 ++- net/netfilter/ipvs/ip_vs_sed.c | 3 ++- net/netfilter/ipvs/ip_vs_sh.c | 10 ++++------ net/netfilter/ipvs/ip_vs_wlc.c | 3 ++- net/netfilter/ipvs/ip_vs_wrr.c | 3 ++- 12 files changed, 34 insertions(+), 60 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 4405886980c7..f5faf859876e 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -197,31 +197,6 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr) } } -/* This function is a faster version of ip_vs_fill_iph_skb(). - * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()). - * This is used by the some of the ip_vs_*_schedule() functions. - * (Mostly done to avoid ABI breakage of external schedulers) - */ -static inline void -ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb, - struct ip_vs_iphdr *iphdr) -{ -#ifdef CONFIG_IP_VS_IPV6 - if (af == AF_INET6) { - const struct ipv6hdr *iph = - (struct ipv6hdr *)skb_network_header(skb); - iphdr->saddr.in6 = iph->saddr; - iphdr->daddr.in6 = iph->daddr; - } else -#endif - { - const struct iphdr *iph = - (struct iphdr *)skb_network_header(skb); - iphdr->saddr.ip = iph->saddr; - iphdr->daddr.ip = iph->daddr; - } -} - static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst, const union nf_inet_addr *src) { @@ -814,7 +789,8 @@ struct ip_vs_scheduler { /* selecting a server from the given service */ struct ip_vs_dest* (*schedule)(struct ip_vs_service *svc, - const struct sk_buff *skb); + const struct sk_buff *skb, + struct ip_vs_iphdr *iph); }; /* The persistence engine object */ diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 05565d2b3a61..e9b0330f220d 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -305,7 +305,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, * return *ignored=0 i.e. ICMP and NF_DROP */ sched = rcu_dereference(svc->scheduler); - dest = sched->schedule(svc, skb); + dest = sched->schedule(svc, skb, iph); if (!dest) { IP_VS_DBG(1, "p-schedule: no dest found.\n"); kfree(param.pe_data); @@ -452,7 +452,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, } sched = rcu_dereference(svc->scheduler); - dest = sched->schedule(svc, skb); + dest = sched->schedule(svc, skb, iph); if (dest == NULL) { IP_VS_DBG(1, "Schedule: no dest found.\n"); return NULL; diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c index ccab120df45e..c3b84546ea9e 100644 --- a/net/netfilter/ipvs/ip_vs_dh.c +++ b/net/netfilter/ipvs/ip_vs_dh.c @@ -214,18 +214,16 @@ static inline int is_overloaded(struct ip_vs_dest *dest) * Destination hashing scheduling */ static struct ip_vs_dest * -ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest; struct ip_vs_dh_state *s; - struct ip_vs_iphdr iph; - - ip_vs_fill_iph_addr_only(svc->af, skb, &iph); IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); s = (struct ip_vs_dh_state *) svc->sched_data; - dest = ip_vs_dh_get(svc->af, s, &iph.daddr); + dest = ip_vs_dh_get(svc->af, s, &iph->daddr); if (!dest || !(dest->flags & IP_VS_DEST_F_AVAILABLE) || atomic_read(&dest->weight) <= 0 @@ -235,7 +233,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) } IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", - IP_VS_DBG_ADDR(svc->af, &iph.daddr), + IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 44595b8ae37f..1383b0eadc0e 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -487,19 +487,17 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) * Locality-Based (weighted) Least-Connection scheduling */ static struct ip_vs_dest * -ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_lblc_table *tbl = svc->sched_data; - struct ip_vs_iphdr iph; struct ip_vs_dest *dest = NULL; struct ip_vs_lblc_entry *en; - ip_vs_fill_iph_addr_only(svc->af, skb, &iph); - IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); /* First look in our cache */ - en = ip_vs_lblc_get(svc->af, tbl, &iph.daddr); + en = ip_vs_lblc_get(svc->af, tbl, &iph->daddr); if (en) { /* We only hold a read lock, but this is atomic */ en->lastuse = jiffies; @@ -529,12 +527,12 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) /* If we fail to create a cache entry, we'll just use the valid dest */ spin_lock_bh(&svc->sched_lock); if (!tbl->dead) - ip_vs_lblc_new(tbl, &iph.daddr, dest); + ip_vs_lblc_new(tbl, &iph->daddr, dest); spin_unlock_bh(&svc->sched_lock); out: IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", - IP_VS_DBG_ADDR(svc->af, &iph.daddr), + IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); return dest; diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 876937db0bf4..3cd85b2fc67c 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -655,19 +655,17 @@ is_overloaded(struct ip_vs_dest *dest, struct ip_vs_service *svc) * Locality-Based (weighted) Least-Connection scheduling */ static struct ip_vs_dest * -ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_lblcr_table *tbl = svc->sched_data; - struct ip_vs_iphdr iph; struct ip_vs_dest *dest; struct ip_vs_lblcr_entry *en; - ip_vs_fill_iph_addr_only(svc->af, skb, &iph); - IP_VS_DBG(6, "%s(): Scheduling...\n", __func__); /* First look in our cache */ - en = ip_vs_lblcr_get(svc->af, tbl, &iph.daddr); + en = ip_vs_lblcr_get(svc->af, tbl, &iph->daddr); if (en) { en->lastuse = jiffies; @@ -718,12 +716,12 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) /* If we fail to create a cache entry, we'll just use the valid dest */ spin_lock_bh(&svc->sched_lock); if (!tbl->dead) - ip_vs_lblcr_new(tbl, &iph.daddr, dest); + ip_vs_lblcr_new(tbl, &iph->daddr, dest); spin_unlock_bh(&svc->sched_lock); out: IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", - IP_VS_DBG_ADDR(svc->af, &iph.daddr), + IP_VS_DBG_ADDR(svc->af, &iph->daddr), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); return dest; diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c index 5128e338a749..2bdcb1cf2127 100644 --- a/net/netfilter/ipvs/ip_vs_lc.c +++ b/net/netfilter/ipvs/ip_vs_lc.c @@ -26,7 +26,8 @@ * Least Connection scheduling */ static struct ip_vs_dest * -ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest, *least = NULL; unsigned int loh = 0, doh; diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c index 646cfd4baa73..d8d9860934fe 100644 --- a/net/netfilter/ipvs/ip_vs_nq.c +++ b/net/netfilter/ipvs/ip_vs_nq.c @@ -55,7 +55,8 @@ ip_vs_nq_dest_overhead(struct ip_vs_dest *dest) * Weighted Least Connection scheduling */ static struct ip_vs_dest * -ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest, *least = NULL; unsigned int loh = 0, doh; diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c index c35986c793d9..176b87c35e34 100644 --- a/net/netfilter/ipvs/ip_vs_rr.c +++ b/net/netfilter/ipvs/ip_vs_rr.c @@ -55,7 +55,8 @@ static int ip_vs_rr_del_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest) * Round-Robin Scheduling */ static struct ip_vs_dest * -ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct list_head *p; struct ip_vs_dest *dest, *last; diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c index f3205925359a..a5284cc3d882 100644 --- a/net/netfilter/ipvs/ip_vs_sed.c +++ b/net/netfilter/ipvs/ip_vs_sed.c @@ -59,7 +59,8 @@ ip_vs_sed_dest_overhead(struct ip_vs_dest *dest) * Weighted Least Connection scheduling */ static struct ip_vs_dest * -ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest, *least; unsigned int loh, doh; diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index a65edfe4b16c..e0d5d1653566 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c @@ -227,18 +227,16 @@ static inline int is_overloaded(struct ip_vs_dest *dest) * Source Hashing scheduling */ static struct ip_vs_dest * -ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest; struct ip_vs_sh_state *s; - struct ip_vs_iphdr iph; - - ip_vs_fill_iph_addr_only(svc->af, skb, &iph); IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n"); s = (struct ip_vs_sh_state *) svc->sched_data; - dest = ip_vs_sh_get(svc->af, s, &iph.saddr); + dest = ip_vs_sh_get(svc->af, s, &iph->saddr); if (!dest || !(dest->flags & IP_VS_DEST_F_AVAILABLE) || atomic_read(&dest->weight) <= 0 @@ -248,7 +246,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) } IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n", - IP_VS_DBG_ADDR(svc->af, &iph.saddr), + IP_VS_DBG_ADDR(svc->af, &iph->saddr), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c index c60a81c4ce9a..6dc1fa128840 100644 --- a/net/netfilter/ipvs/ip_vs_wlc.c +++ b/net/netfilter/ipvs/ip_vs_wlc.c @@ -31,7 +31,8 @@ * Weighted Least Connection scheduling */ static struct ip_vs_dest * -ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest, *least; unsigned int loh, doh; diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c index 0e68555bceb9..0546cd572d6b 100644 --- a/net/netfilter/ipvs/ip_vs_wrr.c +++ b/net/netfilter/ipvs/ip_vs_wrr.c @@ -162,7 +162,8 @@ static int ip_vs_wrr_dest_changed(struct ip_vs_service *svc, * Weighted Round-Robin Scheduling */ static struct ip_vs_dest * -ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) +ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, + struct ip_vs_iphdr *iph) { struct ip_vs_dest *dest, *last, *stop = NULL; struct ip_vs_wrr_mark *mark = svc->sched_data; -- GitLab From c6c96c188336b2b95d5f14facd101f1e4165a9d3 Mon Sep 17 00:00:00 2001 From: Alexander Frolkin Date: Thu, 13 Jun 2013 08:56:15 +0100 Subject: [PATCH 1881/2900] ipvs: sloppy TCP and SCTP This adds support for sloppy TCP and SCTP modes to IPVS. When enabled (sysctls net.ipv4.vs.sloppy_tcp and net.ipv4.vs.sloppy_sctp), allows IPVS to create connection state on any packet, not just a TCP SYN (or SCTP INIT). This allows connections to fail over from one IPVS director to another mid-flight. Signed-off-by: Alexander Frolkin Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 24 ++++++++++++++++++++++++ net/netfilter/ipvs/ip_vs_ctl.c | 14 ++++++++++++++ net/netfilter/ipvs/ip_vs_proto_sctp.c | 18 ++++++++++-------- net/netfilter/ipvs/ip_vs_proto_tcp.c | 14 ++++++++------ 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index f5faf859876e..95860dfdfbe3 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -978,6 +978,8 @@ struct netns_ipvs { int sysctl_sync_sock_size; int sysctl_cache_bypass; int sysctl_expire_nodest_conn; + int sysctl_sloppy_tcp; + int sysctl_sloppy_sctp; int sysctl_expire_quiescent_template; int sysctl_sync_threshold[2]; unsigned int sysctl_sync_refresh_period; @@ -1020,6 +1022,8 @@ struct netns_ipvs { #define DEFAULT_SYNC_THRESHOLD 3 #define DEFAULT_SYNC_PERIOD 50 #define DEFAULT_SYNC_VER 1 +#define DEFAULT_SLOPPY_TCP 0 +#define DEFAULT_SLOPPY_SCTP 0 #define DEFAULT_SYNC_REFRESH_PERIOD (0U * HZ) #define DEFAULT_SYNC_RETRIES 0 #define IPVS_SYNC_WAKEUP_RATE 8 @@ -1056,6 +1060,16 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) return ipvs->sysctl_sync_ver; } +static inline int sysctl_sloppy_tcp(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sloppy_tcp; +} + +static inline int sysctl_sloppy_sctp(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sloppy_sctp; +} + static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) { return ACCESS_ONCE(ipvs->sysctl_sync_ports); @@ -1109,6 +1123,16 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) return DEFAULT_SYNC_VER; } +static inline int sysctl_sloppy_tcp(struct netns_ipvs *ipvs) +{ + return DEFAULT_SLOPPY_TCP; +} + +static inline int sysctl_sloppy_sctp(struct netns_ipvs *ipvs) +{ + return DEFAULT_SLOPPY_SCTP; +} + static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) { return 1; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 47e510819f54..da035fc01eb2 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1738,6 +1738,18 @@ static struct ctl_table vs_vars[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "sloppy_tcp", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "sloppy_sctp", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { .procname = "expire_quiescent_template", .maxlen = sizeof(int), @@ -3723,6 +3735,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) tbl[idx++].data = &ipvs->sysctl_sync_sock_size; tbl[idx++].data = &ipvs->sysctl_cache_bypass; tbl[idx++].data = &ipvs->sysctl_expire_nodest_conn; + tbl[idx++].data = &ipvs->sysctl_sloppy_tcp; + tbl[idx++].data = &ipvs->sysctl_sloppy_sctp; tbl[idx++].data = &ipvs->sysctl_expire_quiescent_template; ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD; ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD; diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 86464881cd20..df29d6417043 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -15,6 +15,7 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, { struct net *net; struct ip_vs_service *svc; + struct netns_ipvs *ipvs; sctp_chunkhdr_t _schunkh, *sch; sctp_sctphdr_t *sh, _sctph; @@ -27,13 +28,14 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, if (sch == NULL) return 0; net = skb_net(skb); + ipvs = net_ipvs(net); rcu_read_lock(); - if ((sch->type == SCTP_CID_INIT) && + if ((sch->type == SCTP_CID_INIT || sysctl_sloppy_sctp(ipvs)) && (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, &iph->daddr, sh->dest))) { int ignored; - if (ip_vs_todrop(net_ipvs(net))) { + if (ip_vs_todrop(ipvs)) { /* * It seems that we are very loaded. * We have to drop this packet :( @@ -232,21 +234,21 @@ static struct ipvs_sctp_nextstate * STATE : IP_VS_SCTP_S_NONE */ /*next state *//*event */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ }, diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 50a15944c6c1..e3a697234a98 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c @@ -39,6 +39,7 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, struct net *net; struct ip_vs_service *svc; struct tcphdr _tcph, *th; + struct netns_ipvs *ipvs; th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); if (th == NULL) { @@ -46,14 +47,15 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, return 0; } net = skb_net(skb); + ipvs = net_ipvs(net); /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ rcu_read_lock(); - if (th->syn && + if ((th->syn || sysctl_sloppy_tcp(ipvs)) && !th->rst && (svc = ip_vs_service_find(net, af, skb->mark, iph->protocol, &iph->daddr, th->dest))) { int ignored; - if (ip_vs_todrop(net_ipvs(net))) { + if (ip_vs_todrop(ipvs)) { /* * It seems that we are very loaded. * We have to drop this packet :( @@ -401,7 +403,7 @@ static struct tcp_states_t tcp_states [] = { /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }}, -/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, +/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }}, /* OUTPUT */ @@ -415,7 +417,7 @@ static struct tcp_states_t tcp_states [] = { /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }}, /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, -/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, +/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, }; @@ -424,7 +426,7 @@ static struct tcp_states_t tcp_states_dos [] = { /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSA }}, /*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sSA }}, -/*ack*/ {{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI, sSA }}, +/*ack*/ {{sES, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI, sSA }}, /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, /* OUTPUT */ @@ -438,7 +440,7 @@ static struct tcp_states_t tcp_states_dos [] = { /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA */ /*syn*/ {{sSA, sES, sES, sSR, sSA, sSA, sSA, sSA, sSA, sSA, sSA }}, /*fin*/ {{sCL, sFW, sSS, sTW, sFW, sTW, sCL, sCW, sLA, sLI, sTW }}, -/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, +/*ack*/ {{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }}, /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }}, }; -- GitLab From 61e7c420b4b2a797ac209106ba743ab6ebe984d8 Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 18 Jun 2013 10:08:07 +0300 Subject: [PATCH 1882/2900] ipvs: replace the SCTP state machine Convert the SCTP state table, so that it is more readable. Change the states to be according to the diagram in RFC 2960 and add more states suitable for middle box. Still, such change in states adds incompatibility if systems in sync setup include this change and others do not include it. With this change we also have proper transitions in INPUT-ONLY mode (DR/TUN) where we see packets only from client. Now we should not switch to 10-second CLOSED state at a time when we should stay in ESTABLISHED state. The short names for states are because we have 16-char space in ipvsadm and 11-char limit for the connection list format. It is a sequence of the TCP implementation where the longest state name is ESTABLISHED. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 21 +- net/netfilter/ipvs/ip_vs_proto_sctp.c | 854 +++++--------------------- net/netfilter/ipvs/ip_vs_sync.c | 7 +- 3 files changed, 168 insertions(+), 714 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 95860dfdfbe3..e667df171003 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -380,17 +380,18 @@ enum { */ enum ip_vs_sctp_states { IP_VS_SCTP_S_NONE, - IP_VS_SCTP_S_INIT_CLI, - IP_VS_SCTP_S_INIT_SER, - IP_VS_SCTP_S_INIT_ACK_CLI, - IP_VS_SCTP_S_INIT_ACK_SER, - IP_VS_SCTP_S_ECHO_CLI, - IP_VS_SCTP_S_ECHO_SER, + IP_VS_SCTP_S_INIT1, + IP_VS_SCTP_S_INIT, + IP_VS_SCTP_S_COOKIE_SENT, + IP_VS_SCTP_S_COOKIE_REPLIED, + IP_VS_SCTP_S_COOKIE_WAIT, + IP_VS_SCTP_S_COOKIE, + IP_VS_SCTP_S_COOKIE_ECHOED, IP_VS_SCTP_S_ESTABLISHED, - IP_VS_SCTP_S_SHUT_CLI, - IP_VS_SCTP_S_SHUT_SER, - IP_VS_SCTP_S_SHUT_ACK_CLI, - IP_VS_SCTP_S_SHUT_ACK_SER, + IP_VS_SCTP_S_SHUTDOWN_SENT, + IP_VS_SCTP_S_SHUTDOWN_RECEIVED, + IP_VS_SCTP_S_SHUTDOWN_ACK_SENT, + IP_VS_SCTP_S_REJECTED, IP_VS_SCTP_S_CLOSED, IP_VS_SCTP_S_LAST }; diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index df29d6417043..3c0da8728036 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -185,710 +185,159 @@ sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) return 1; } -struct ipvs_sctp_nextstate { - int next_state; -}; enum ipvs_sctp_event_t { - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_DATA_SER, - IP_VS_SCTP_EVE_INIT_CLI, - IP_VS_SCTP_EVE_INIT_SER, - IP_VS_SCTP_EVE_INIT_ACK_CLI, - IP_VS_SCTP_EVE_INIT_ACK_SER, - IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, - IP_VS_SCTP_EVE_COOKIE_ECHO_SER, - IP_VS_SCTP_EVE_COOKIE_ACK_CLI, - IP_VS_SCTP_EVE_COOKIE_ACK_SER, - IP_VS_SCTP_EVE_ABORT_CLI, - IP_VS_SCTP_EVE__ABORT_SER, - IP_VS_SCTP_EVE_SHUT_CLI, - IP_VS_SCTP_EVE_SHUT_SER, - IP_VS_SCTP_EVE_SHUT_ACK_CLI, - IP_VS_SCTP_EVE_SHUT_ACK_SER, - IP_VS_SCTP_EVE_SHUT_COM_CLI, - IP_VS_SCTP_EVE_SHUT_COM_SER, - IP_VS_SCTP_EVE_LAST + IP_VS_SCTP_DATA = 0, /* DATA, SACK, HEARTBEATs */ + IP_VS_SCTP_INIT, + IP_VS_SCTP_INIT_ACK, + IP_VS_SCTP_COOKIE_ECHO, + IP_VS_SCTP_COOKIE_ACK, + IP_VS_SCTP_SHUTDOWN, + IP_VS_SCTP_SHUTDOWN_ACK, + IP_VS_SCTP_SHUTDOWN_COMPLETE, + IP_VS_SCTP_ERROR, + IP_VS_SCTP_ABORT, + IP_VS_SCTP_EVENT_LAST }; -static enum ipvs_sctp_event_t sctp_events[256] = { - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_INIT_CLI, - IP_VS_SCTP_EVE_INIT_ACK_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_ABORT_CLI, - IP_VS_SCTP_EVE_SHUT_CLI, - IP_VS_SCTP_EVE_SHUT_ACK_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, - IP_VS_SCTP_EVE_COOKIE_ACK_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_DATA_CLI, - IP_VS_SCTP_EVE_SHUT_COM_CLI, +/* RFC 2960, 3.2 Chunk Field Descriptions */ +static __u8 sctp_events[] = { + [SCTP_CID_DATA] = IP_VS_SCTP_DATA, + [SCTP_CID_INIT] = IP_VS_SCTP_INIT, + [SCTP_CID_INIT_ACK] = IP_VS_SCTP_INIT_ACK, + [SCTP_CID_SACK] = IP_VS_SCTP_DATA, + [SCTP_CID_HEARTBEAT] = IP_VS_SCTP_DATA, + [SCTP_CID_HEARTBEAT_ACK] = IP_VS_SCTP_DATA, + [SCTP_CID_ABORT] = IP_VS_SCTP_ABORT, + [SCTP_CID_SHUTDOWN] = IP_VS_SCTP_SHUTDOWN, + [SCTP_CID_SHUTDOWN_ACK] = IP_VS_SCTP_SHUTDOWN_ACK, + [SCTP_CID_ERROR] = IP_VS_SCTP_ERROR, + [SCTP_CID_COOKIE_ECHO] = IP_VS_SCTP_COOKIE_ECHO, + [SCTP_CID_COOKIE_ACK] = IP_VS_SCTP_COOKIE_ACK, + [SCTP_CID_ECN_ECNE] = IP_VS_SCTP_DATA, + [SCTP_CID_ECN_CWR] = IP_VS_SCTP_DATA, + [SCTP_CID_SHUTDOWN_COMPLETE] = IP_VS_SCTP_SHUTDOWN_COMPLETE, }; -static struct ipvs_sctp_nextstate - sctp_states_table[IP_VS_SCTP_S_LAST][IP_VS_SCTP_EVE_LAST] = { - /* - * STATE : IP_VS_SCTP_S_NONE - */ - /*next state *//*event */ - {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ }, - }, - /* - * STATE : IP_VS_SCTP_S_INIT_CLI - * Cient sent INIT and is waiting for reply from server(In ECHO_WAIT) - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ECHO_CLI */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_ECHO_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_INIT_SER - * Server sent INIT and waiting for INIT ACK from the client - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_INIT_ACK_CLI - * Client sent INIT ACK and waiting for ECHO from the server - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK has been resent by the client, let us stay is in - * the same state - */ - {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - /* - * INIT_ACK sent by the server, close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * ECHO by client, it should not happen, close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - /* - * ECHO by server, this is what we are expecting, move to ECHO_SER - */ - {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, it should not happen, close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - /* - * Unexpected COOKIE ACK from server, staty in the same state - */ - {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_INIT_ACK_SER - * Server sent INIT ACK and waiting for ECHO from the client - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * Unexpected INIT_ACK by the client, let us close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - /* - * INIT_ACK resent by the server, let us move to same state - */ - {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client send the ECHO, this is what we are expecting, - * move to ECHO_CLI - */ - {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - /* - * ECHO received from the server, Not sure what to do, - * let us close it - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, let us stay in the same state - */ - {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - /* - * COOKIE ACK from server, hmm... this should not happen, lets close - * the connection. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_ECHO_CLI - * Cient sent ECHO and waiting COOKEI ACK from the Server - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK has been by the client, let us close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client resent the ECHO, let us stay in the same state - */ - {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - /* - * ECHO received from the server, Not sure what to do, - * let us close it - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, this shoud not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - /* - * COOKIE ACK from server, this is what we are awaiting,lets move to - * ESTABLISHED. - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_ECHO_SER - * Server sent ECHO and waiting COOKEI ACK from the client - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - /* - * INIT_ACK has been by the server, let us close the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent the ECHO, not sure what to do, let's close the - * connection. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - /* - * ECHO resent by the server, stay in the same state - */ - {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, this is what we are expecting, let's move - * to ESTABLISHED. - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - /* - * COOKIE ACK from server, this should not happen, lets close the - * connection. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_ESTABLISHED - * Association established - */ - {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the - * peer and peer shall move to the ESTABISHED. if it doesn't handle - * it will send ERROR chunk. So, stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, not sure what to do stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - /* - * SHUTDOWN from the client, move to SHUDDOWN_CLI - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - /* - * SHUTDOWN from the server, move to SHUTDOWN_SER - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, - /* - * client sent SHUDTDOWN_ACK, this should not happen, let's close - * the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_SHUT_CLI - * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server - */ - /* - * We received the data chuck, keep the state unchanged. I assume - * that still data chuncks can be received by both the peers in - * SHUDOWN state - */ - - {{IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the - * peer and peer shall move to the ESTABISHED. if it doesn't handle - * it will send ERROR chunk. So, stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, not sure what to do stay in the same state - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - /* - * SHUTDOWN resent from the client, move to SHUDDOWN_CLI - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - /* - * SHUTDOWN from the server, move to SHUTDOWN_SER - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, - /* - * client sent SHUDTDOWN_ACK, this should not happen, let's close - * the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - /* - * Server sent SHUTDOWN ACK, this is what we are expecting, let's move - * to SHUDOWN_ACK_SER - */ - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - /* - * SHUTDOWN COM from client, this should not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_SHUT_SER - * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client - */ - /* - * We received the data chuck, keep the state unchanged. I assume - * that still data chuncks can be received by both the peers in - * SHUDOWN state - */ - - {{IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the - * peer and peer shall move to the ESTABISHED. if it doesn't handle - * it will send ERROR chunk. So, stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, not sure what to do stay in the same state - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - /* - * SHUTDOWN resent from the client, move to SHUDDOWN_CLI - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - /* - * SHUTDOWN resent from the server, move to SHUTDOWN_SER - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, - /* - * client sent SHUDTDOWN_ACK, this is what we are expecting, let's - * move to SHUT_ACK_CLI - */ - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - /* - * Server sent SHUTDOWN ACK, this should not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - /* - * SHUTDOWN COM from client, this should not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - - /* - * State : IP_VS_SCTP_S_SHUT_ACK_CLI - * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server - */ - /* - * We received the data chuck, keep the state unchanged. I assume - * that still data chuncks can be received by both the peers in - * SHUDOWN state - */ - - {{IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the - * peer and peer shall move to the ESTABISHED. if it doesn't handle - * it will send ERROR chunk. So, stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, not sure what to do stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - /* - * SHUTDOWN sent from the client, move to SHUDDOWN_CLI - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - /* - * SHUTDOWN sent from the server, move to SHUTDOWN_SER - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, - /* - * client resent SHUDTDOWN_ACK, let's stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - /* - * Server sent SHUTDOWN ACK, this should not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - /* - * SHUTDOWN COM from client, this should not happen, let's close the - * connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - /* - * SHUTDOWN COMPLETE from server this is what we are expecting. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - - /* - * State : IP_VS_SCTP_S_SHUT_ACK_SER - * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client - */ - /* - * We received the data chuck, keep the state unchanged. I assume - * that still data chuncks can be received by both the peers in - * SHUDOWN state - */ +/* SCTP States: + * See RFC 2960, 4. SCTP Association State Diagram + * + * New states (not in diagram): + * - INIT1 state: use shorter timeout for dropped INIT packets + * - REJECTED state: use shorter timeout if INIT is rejected with ABORT + * - INIT, COOKIE_SENT, COOKIE_REPLIED, COOKIE states: for better debugging + * + * The states are as seen in real server. In the diagram, INIT1, INIT, + * COOKIE_SENT and COOKIE_REPLIED processing happens in CLOSED state. + * + * States as per packets from client (C) and server (S): + * + * Setup of client connection: + * IP_VS_SCTP_S_INIT1: First C:INIT sent, wait for S:INIT-ACK + * IP_VS_SCTP_S_INIT: Next C:INIT sent, wait for S:INIT-ACK + * IP_VS_SCTP_S_COOKIE_SENT: S:INIT-ACK sent, wait for C:COOKIE-ECHO + * IP_VS_SCTP_S_COOKIE_REPLIED: C:COOKIE-ECHO sent, wait for S:COOKIE-ACK + * + * Setup of server connection: + * IP_VS_SCTP_S_COOKIE_WAIT: S:INIT sent, wait for C:INIT-ACK + * IP_VS_SCTP_S_COOKIE: C:INIT-ACK sent, wait for S:COOKIE-ECHO + * IP_VS_SCTP_S_COOKIE_ECHOED: S:COOKIE-ECHO sent, wait for C:COOKIE-ACK + */ - {{IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, - /* - * We have got an INIT from client. From the spec.“Upon receipt of - * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with - * an INIT ACK using the same parameters it sent in its original - * INIT chunk (including its Initiate Tag, unchanged”). - */ - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - /* - * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, - * “If an INIT ACK is received by an endpoint in any state other - * than the COOKIE-WAIT state, the endpoint should discard the - * INIT ACK chunk”. Stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - /* - * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the - * peer and peer shall move to the ESTABISHED. if it doesn't handle - * it will send ERROR chunk. So, stay in the same state - */ - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - /* - * COOKIE ACK from client, not sure what to do stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - /* - * SHUTDOWN sent from the client, move to SHUDDOWN_CLI - */ - {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - /* - * SHUTDOWN sent from the server, move to SHUTDOWN_SER - */ - {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, - /* - * client sent SHUDTDOWN_ACK, this should not happen let's close - * the connection. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - /* - * Server resent SHUTDOWN ACK, stay in the same state - */ - {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - /* - * SHUTDOWN COM from client, this what we are expecting, let's close - * the connection - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - /* - * SHUTDOWN COMPLETE from server this should not happen. - */ - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - }, - /* - * State : IP_VS_SCTP_S_CLOSED - */ - {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, - {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, - {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, - {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } - } +#define sNO IP_VS_SCTP_S_NONE +#define sI1 IP_VS_SCTP_S_INIT1 +#define sIN IP_VS_SCTP_S_INIT +#define sCS IP_VS_SCTP_S_COOKIE_SENT +#define sCR IP_VS_SCTP_S_COOKIE_REPLIED +#define sCW IP_VS_SCTP_S_COOKIE_WAIT +#define sCO IP_VS_SCTP_S_COOKIE +#define sCE IP_VS_SCTP_S_COOKIE_ECHOED +#define sES IP_VS_SCTP_S_ESTABLISHED +#define sSS IP_VS_SCTP_S_SHUTDOWN_SENT +#define sSR IP_VS_SCTP_S_SHUTDOWN_RECEIVED +#define sSA IP_VS_SCTP_S_SHUTDOWN_ACK_SENT +#define sRJ IP_VS_SCTP_S_REJECTED +#define sCL IP_VS_SCTP_S_CLOSED + +static const __u8 sctp_states + [IP_VS_DIR_LAST][IP_VS_SCTP_EVENT_LAST][IP_VS_SCTP_S_LAST] = { + { /* INPUT */ +/* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ +/* d */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* i */{sI1, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN}, +/* i_a */{sCW, sCW, sCW, sCS, sCR, sCO, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_e */{sCR, sIN, sIN, sCR, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_a */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sES, sES, sSS, sSR, sSA, sRJ, sCL}, +/* s */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL}, +/* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sES, sCL, sSR, sCL, sRJ, sCL}, +/* s_c */{sCL, sCL, sCL, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sCL, sRJ, sCL}, +/* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCL, sES, sSS, sSR, sSA, sRJ, sCL}, +/* ab */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, + }, + { /* OUTPUT */ +/* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ +/* d */{sES, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* i */{sCW, sCW, sCW, sCW, sCW, sCW, sCW, sCW, sES, sCW, sCW, sCW, sCW, sCW}, +/* i_a */{sCS, sCS, sCS, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_e */{sCE, sCE, sCE, sCE, sCE, sCE, sCE, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_a */{sES, sES, sES, sES, sES, sES, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL}, +/* s */{sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSS, sSR, sSA, sRJ, sCL}, +/* s_a */{sSA, sSA, sSA, sSA, sSA, sCW, sCO, sCE, sES, sSA, sSA, sSA, sRJ, sCL}, +/* s_c */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* err */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* ab */{sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, + }, + { /* INPUT-ONLY */ +/* sNO, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL*/ +/* d */{sES, sI1, sIN, sCS, sCR, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* i */{sI1, sIN, sIN, sIN, sIN, sIN, sCO, sCE, sES, sSS, sSR, sSA, sIN, sIN}, +/* i_a */{sCE, sCE, sCE, sCE, sCE, sCE, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_e */{sES, sES, sES, sES, sES, sES, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* c_a */{sES, sI1, sIN, sES, sES, sCW, sES, sES, sES, sSS, sSR, sSA, sRJ, sCL}, +/* s */{sSR, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sSR, sSS, sSR, sSA, sRJ, sCL}, +/* s_a */{sCL, sIN, sIN, sCS, sCR, sCW, sCO, sCE, sCL, sCL, sSR, sCL, sRJ, sCL}, +/* s_c */{sCL, sCL, sCL, sCL, sCL, sCW, sCO, sCE, sES, sSS, sCL, sCL, sRJ, sCL}, +/* err */{sCL, sI1, sIN, sCS, sCR, sCW, sCO, sCE, sES, sSS, sSR, sSA, sRJ, sCL}, +/* ab */{sCL, sCL, sCL, sCL, sCL, sRJ, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, + }, }; -/* - * Timeout table[state] - */ +#define IP_VS_SCTP_MAX_RTO ((60 + 1) * HZ) + +/* Timeout table[state] */ static const int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = { - [IP_VS_SCTP_S_NONE] = 2 * HZ, - [IP_VS_SCTP_S_INIT_CLI] = 1 * 60 * HZ, - [IP_VS_SCTP_S_INIT_SER] = 1 * 60 * HZ, - [IP_VS_SCTP_S_INIT_ACK_CLI] = 1 * 60 * HZ, - [IP_VS_SCTP_S_INIT_ACK_SER] = 1 * 60 * HZ, - [IP_VS_SCTP_S_ECHO_CLI] = 1 * 60 * HZ, - [IP_VS_SCTP_S_ECHO_SER] = 1 * 60 * HZ, - [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, - [IP_VS_SCTP_S_SHUT_CLI] = 1 * 60 * HZ, - [IP_VS_SCTP_S_SHUT_SER] = 1 * 60 * HZ, - [IP_VS_SCTP_S_SHUT_ACK_CLI] = 1 * 60 * HZ, - [IP_VS_SCTP_S_SHUT_ACK_SER] = 1 * 60 * HZ, - [IP_VS_SCTP_S_CLOSED] = 10 * HZ, - [IP_VS_SCTP_S_LAST] = 2 * HZ, + [IP_VS_SCTP_S_NONE] = 2 * HZ, + [IP_VS_SCTP_S_INIT1] = (0 + 3 + 1) * HZ, + [IP_VS_SCTP_S_INIT] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_COOKIE_SENT] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_COOKIE_REPLIED] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_COOKIE_WAIT] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_COOKIE] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_COOKIE_ECHOED] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, + [IP_VS_SCTP_S_SHUTDOWN_SENT] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_SHUTDOWN_RECEIVED] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_REJECTED] = (0 + 3 + 1) * HZ, + [IP_VS_SCTP_S_CLOSED] = IP_VS_SCTP_MAX_RTO, + [IP_VS_SCTP_S_LAST] = 2 * HZ, }; static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = { - [IP_VS_SCTP_S_NONE] = "NONE", - [IP_VS_SCTP_S_INIT_CLI] = "INIT_CLI", - [IP_VS_SCTP_S_INIT_SER] = "INIT_SER", - [IP_VS_SCTP_S_INIT_ACK_CLI] = "INIT_ACK_CLI", - [IP_VS_SCTP_S_INIT_ACK_SER] = "INIT_ACK_SER", - [IP_VS_SCTP_S_ECHO_CLI] = "COOKIE_ECHO_CLI", - [IP_VS_SCTP_S_ECHO_SER] = "COOKIE_ECHO_SER", - [IP_VS_SCTP_S_ESTABLISHED] = "ESTABISHED", - [IP_VS_SCTP_S_SHUT_CLI] = "SHUTDOWN_CLI", - [IP_VS_SCTP_S_SHUT_SER] = "SHUTDOWN_SER", - [IP_VS_SCTP_S_SHUT_ACK_CLI] = "SHUTDOWN_ACK_CLI", - [IP_VS_SCTP_S_SHUT_ACK_SER] = "SHUTDOWN_ACK_SER", - [IP_VS_SCTP_S_CLOSED] = "CLOSED", - [IP_VS_SCTP_S_LAST] = "BUG!" + [IP_VS_SCTP_S_NONE] = "NONE", + [IP_VS_SCTP_S_INIT1] = "INIT1", + [IP_VS_SCTP_S_INIT] = "INIT", + [IP_VS_SCTP_S_COOKIE_SENT] = "C-SENT", + [IP_VS_SCTP_S_COOKIE_REPLIED] = "C-REPLIED", + [IP_VS_SCTP_S_COOKIE_WAIT] = "C-WAIT", + [IP_VS_SCTP_S_COOKIE] = "COOKIE", + [IP_VS_SCTP_S_COOKIE_ECHOED] = "C-ECHOED", + [IP_VS_SCTP_S_ESTABLISHED] = "ESTABLISHED", + [IP_VS_SCTP_S_SHUTDOWN_SENT] = "S-SENT", + [IP_VS_SCTP_S_SHUTDOWN_RECEIVED] = "S-RECEIVED", + [IP_VS_SCTP_S_SHUTDOWN_ACK_SENT] = "S-ACK-SENT", + [IP_VS_SCTP_S_REJECTED] = "REJECTED", + [IP_VS_SCTP_S_CLOSED] = "CLOSED", + [IP_VS_SCTP_S_LAST] = "BUG!", }; @@ -945,17 +394,20 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, } } - event = sctp_events[chunk_type]; + event = (chunk_type < sizeof(sctp_events)) ? + sctp_events[chunk_type] : IP_VS_SCTP_DATA; - /* - * If the direction is IP_VS_DIR_OUTPUT, this event is from server - */ - if (direction == IP_VS_DIR_OUTPUT) - event++; - /* - * get next state + /* Update direction to INPUT_ONLY if necessary + * or delete NO_OUTPUT flag if output packet detected */ - next_state = sctp_states_table[cp->state][event].next_state; + if (cp->flags & IP_VS_CONN_F_NOOUTPUT) { + if (direction == IP_VS_DIR_OUTPUT) + cp->flags &= ~IP_VS_CONN_F_NOOUTPUT; + else + direction = IP_VS_DIR_INPUT_ONLY; + } + + next_state = sctp_states[direction][event][cp->state]; if (next_state != cp->state) { struct ip_vs_dest *dest = cp->dest; diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index f6046d9af8d3..2fc66394d86d 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -461,9 +461,10 @@ static int ip_vs_sync_conn_needed(struct netns_ipvs *ipvs, } else if (unlikely(cp->protocol == IPPROTO_SCTP)) { if (!((1 << cp->state) & ((1 << IP_VS_SCTP_S_ESTABLISHED) | - (1 << IP_VS_SCTP_S_CLOSED) | - (1 << IP_VS_SCTP_S_SHUT_ACK_CLI) | - (1 << IP_VS_SCTP_S_SHUT_ACK_SER)))) + (1 << IP_VS_SCTP_S_SHUTDOWN_SENT) | + (1 << IP_VS_SCTP_S_SHUTDOWN_RECEIVED) | + (1 << IP_VS_SCTP_S_SHUTDOWN_ACK_SENT) | + (1 << IP_VS_SCTP_S_CLOSED)))) return 0; force = cp->state != cp->old_state; if (force && cp->state != IP_VS_SCTP_S_ESTABLISHED) -- GitLab From acaac5d8bbedf6bd96f53960780942e1ad90d70e Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Tue, 18 Jun 2013 10:08:08 +0300 Subject: [PATCH 1883/2900] ipvs: drop SCTP connections depending on state Drop SCTP connections under load (dropentry context) depending on the protocol state, just like for TCP: INIT conns are dropped immediately, established are dropped randomly while connections in progress or shutdown are skipped. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- net/netfilter/ipvs/ip_vs_conn.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index c8c52a98590b..4c8e5c0aa1ab 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1231,6 +1231,18 @@ void ip_vs_random_dropentry(struct net *net) default: continue; } + } else if (cp->protocol == IPPROTO_SCTP) { + switch (cp->state) { + case IP_VS_SCTP_S_INIT1: + case IP_VS_SCTP_S_INIT: + break; + case IP_VS_SCTP_S_ESTABLISHED: + if (todrop_entry(cp)) + break; + continue; + default: + continue; + } } else { if (!todrop_entry(cp)) continue; -- GitLab From eba3b5a78799d21dea05118b294524958f0ab592 Mon Sep 17 00:00:00 2001 From: Alexander Frolkin Date: Wed, 19 Jun 2013 10:54:25 +0100 Subject: [PATCH 1884/2900] ipvs: SH fallback and L4 hashing By default the SH scheduler rejects connections that are hashed onto a realserver of weight 0. This patch adds a flag to make SH choose a different realserver in this case, instead of rejecting the connection. The patch also adds a flag to make SH include the source port (TCP, UDP, SCTP) in the hash as well as the source address. This basically allows for deterministic round-robin load balancing (i.e., where any director in a cluster of directors with identical config will send the same packet the same way). The flags are service flags (IP_VS_SVC_F_SCHED*) so that these options can be set per service. They are set using a new option to ipvsadm. Signed-off-by: Alexander Frolkin Acked-by: Julian Anastasov Signed-off-by: Simon Horman --- include/uapi/linux/ip_vs.h | 6 ++ net/netfilter/ipvs/ip_vs_sh.c | 100 +++++++++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h index a24537725e80..29458223d044 100644 --- a/include/uapi/linux/ip_vs.h +++ b/include/uapi/linux/ip_vs.h @@ -20,6 +20,12 @@ #define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ #define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ #define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */ +#define IP_VS_SVC_F_SCHED1 0x0008 /* scheduler flag 1 */ +#define IP_VS_SVC_F_SCHED2 0x0010 /* scheduler flag 2 */ +#define IP_VS_SVC_F_SCHED3 0x0020 /* scheduler flag 3 */ + +#define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */ +#define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */ /* * Destination Server Flags diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index e0d5d1653566..f16c027df15b 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c @@ -48,6 +48,10 @@ #include +#include +#include +#include + /* * IPVS SH bucket @@ -71,10 +75,19 @@ struct ip_vs_sh_state { struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE]; }; +/* Helper function to determine if server is unavailable */ +static inline bool is_unavailable(struct ip_vs_dest *dest) +{ + return atomic_read(&dest->weight) <= 0 || + dest->flags & IP_VS_DEST_F_OVERLOAD; +} + /* * Returns hash value for IPVS SH entry */ -static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr) +static inline unsigned int +ip_vs_sh_hashkey(int af, const union nf_inet_addr *addr, + __be16 port, unsigned int offset) { __be32 addr_fold = addr->ip; @@ -83,7 +96,8 @@ static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *ad addr_fold = addr->ip6[0]^addr->ip6[1]^ addr->ip6[2]^addr->ip6[3]; #endif - return (ntohl(addr_fold)*2654435761UL) & IP_VS_SH_TAB_MASK; + return (offset + (ntohs(port) + ntohl(addr_fold))*2654435761UL) & + IP_VS_SH_TAB_MASK; } @@ -91,12 +105,42 @@ static inline unsigned int ip_vs_sh_hashkey(int af, const union nf_inet_addr *ad * Get ip_vs_dest associated with supplied parameters. */ static inline struct ip_vs_dest * -ip_vs_sh_get(int af, struct ip_vs_sh_state *s, const union nf_inet_addr *addr) +ip_vs_sh_get(struct ip_vs_service *svc, struct ip_vs_sh_state *s, + const union nf_inet_addr *addr, __be16 port) { - return rcu_dereference(s->buckets[ip_vs_sh_hashkey(af, addr)].dest); + unsigned int hash = ip_vs_sh_hashkey(svc->af, addr, port, 0); + struct ip_vs_dest *dest = rcu_dereference(s->buckets[hash].dest); + + return (!dest || is_unavailable(dest)) ? NULL : dest; } +/* As ip_vs_sh_get, but with fallback if selected server is unavailable */ +static inline struct ip_vs_dest * +ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s, + const union nf_inet_addr *addr, __be16 port) +{ + unsigned int offset; + unsigned int hash; + struct ip_vs_dest *dest; + + for (offset = 0; offset < IP_VS_SH_TAB_SIZE; offset++) { + hash = ip_vs_sh_hashkey(svc->af, addr, port, offset); + dest = rcu_dereference(s->buckets[hash].dest); + if (!dest) + break; + if (is_unavailable(dest)) + IP_VS_DBG_BUF(6, "SH: selected unavailable server " + "%s:%d (offset %d)", + IP_VS_DBG_ADDR(svc->af, &dest->addr), + ntohs(dest->port), offset); + else + return dest; + } + + return NULL; +} + /* * Assign all the hash buckets of the specified table with the service. */ @@ -213,13 +257,33 @@ static int ip_vs_sh_dest_changed(struct ip_vs_service *svc, } -/* - * If the dest flags is set with IP_VS_DEST_F_OVERLOAD, - * consider that the server is overloaded here. - */ -static inline int is_overloaded(struct ip_vs_dest *dest) +/* Helper function to get port number */ +static inline __be16 +ip_vs_sh_get_port(const struct sk_buff *skb, struct ip_vs_iphdr *iph) { - return dest->flags & IP_VS_DEST_F_OVERLOAD; + __be16 port; + struct tcphdr _tcph, *th; + struct udphdr _udph, *uh; + sctp_sctphdr_t _sctph, *sh; + + switch (iph->protocol) { + case IPPROTO_TCP: + th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph); + port = th->source; + break; + case IPPROTO_UDP: + uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph); + port = uh->source; + break; + case IPPROTO_SCTP: + sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph); + port = sh->source; + break; + default: + port = 0; + } + + return port; } @@ -232,15 +296,21 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb, { struct ip_vs_dest *dest; struct ip_vs_sh_state *s; + __be16 port = 0; IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n"); + if (svc->flags & IP_VS_SVC_F_SCHED_SH_PORT) + port = ip_vs_sh_get_port(skb, iph); + s = (struct ip_vs_sh_state *) svc->sched_data; - dest = ip_vs_sh_get(svc->af, s, &iph->saddr); - if (!dest - || !(dest->flags & IP_VS_DEST_F_AVAILABLE) - || atomic_read(&dest->weight) <= 0 - || is_overloaded(dest)) { + + if (svc->flags & IP_VS_SVC_F_SCHED_SH_FALLBACK) + dest = ip_vs_sh_get_fallback(svc, s, &iph->saddr, port); + else + dest = ip_vs_sh_get(svc, s, &iph->saddr, port); + + if (!dest) { ip_vs_scheduler_err(svc, "no destination available"); return NULL; } -- GitLab From 4d0c875dcc4923476f364e83912d134da2df224c Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Mon, 24 Jun 2013 22:44:41 +0300 Subject: [PATCH 1885/2900] ipvs: add sync_persist_mode flag Add sync_persist_mode flag to reduce sync traffic by syncing only persistent templates. Signed-off-by: Julian Anastasov Tested-by: Aleksey Chudov Signed-off-by: Simon Horman --- Documentation/networking/ipvs-sysctl.txt | 13 +++++++++++++ include/net/ip_vs.h | 11 +++++++++++ net/netfilter/ipvs/ip_vs_ctl.c | 7 +++++++ net/netfilter/ipvs/ip_vs_sync.c | 12 ++++++++++++ 4 files changed, 43 insertions(+) diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt index 9573d0c48c6e..7a3c04729591 100644 --- a/Documentation/networking/ipvs-sysctl.txt +++ b/Documentation/networking/ipvs-sysctl.txt @@ -181,6 +181,19 @@ snat_reroute - BOOLEAN always be the same as the original route so it is an optimisation to disable snat_reroute and avoid the recalculation. +sync_persist_mode - INTEGER + default 0 + + Controls the synchronisation of connections when using persistence + + 0: All types of connections are synchronised + 1: Attempt to reduce the synchronisation traffic depending on + the connection type. For persistent services avoid synchronisation + for normal connections, do it only for persistence templates. + In such case, for TCP and SCTP it may need enabling sloppy_tcp and + sloppy_sctp flags on backup servers. For non-persistent services + such optimization is not applied, mode 0 is assumed. + sync_version - INTEGER default 1 diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e667df171003..f0d70f066f3d 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -975,6 +975,7 @@ struct netns_ipvs { int sysctl_snat_reroute; int sysctl_sync_ver; int sysctl_sync_ports; + int sysctl_sync_persist_mode; unsigned long sysctl_sync_qlen_max; int sysctl_sync_sock_size; int sysctl_cache_bypass; @@ -1076,6 +1077,11 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) return ACCESS_ONCE(ipvs->sysctl_sync_ports); } +static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sync_persist_mode; +} + static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) { return ipvs->sysctl_sync_qlen_max; @@ -1139,6 +1145,11 @@ static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) return 1; } +static inline int sysctl_sync_persist_mode(struct netns_ipvs *ipvs) +{ + return 0; +} + static inline unsigned long sysctl_sync_qlen_max(struct netns_ipvs *ipvs) { return IPVS_SYNC_QLEN_MAX; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index da035fc01eb2..c8148e487386 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1714,6 +1714,12 @@ static struct ctl_table vs_vars[] = { .mode = 0644, .proc_handler = &proc_do_sync_ports, }, + { + .procname = "sync_persist_mode", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { .procname = "sync_qlen_max", .maxlen = sizeof(unsigned long), @@ -3729,6 +3735,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) tbl[idx++].data = &ipvs->sysctl_sync_ver; ipvs->sysctl_sync_ports = 1; tbl[idx++].data = &ipvs->sysctl_sync_ports; + tbl[idx++].data = &ipvs->sysctl_sync_persist_mode; ipvs->sysctl_sync_qlen_max = nr_free_buffer_pages() / 32; tbl[idx++].data = &ipvs->sysctl_sync_qlen_max; ipvs->sysctl_sync_sock_size = 0; diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 2fc66394d86d..f4484719f3e6 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -425,6 +425,16 @@ ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs) return sb; } +/* Check if connection is controlled by persistence */ +static inline bool in_persistence(struct ip_vs_conn *cp) +{ + for (cp = cp->control; cp; cp = cp->control) { + if (cp->flags & IP_VS_CONN_F_TEMPLATE) + return true; + } + return false; +} + /* Check if conn should be synced. * pkts: conn packets, use sysctl_sync_threshold to avoid packet check * - (1) sync_refresh_period: reduce sync rate. Additionally, retry @@ -447,6 +457,8 @@ static int ip_vs_sync_conn_needed(struct netns_ipvs *ipvs, /* Check if we sync in current state */ if (unlikely(cp->flags & IP_VS_CONN_F_TEMPLATE)) force = 0; + else if (unlikely(sysctl_sync_persist_mode(ipvs) && in_persistence(cp))) + return 0; else if (likely(cp->protocol == IPPROTO_TCP)) { if (!((1 << cp->state) & ((1 << IP_VS_TCP_S_ESTABLISHED) | -- GitLab From d0667186eb0eab78dcca9f75af6ed03873ca8d9f Mon Sep 17 00:00:00 2001 From: JunweiZhang Date: Wed, 26 Jun 2013 16:40:05 +0800 Subject: [PATCH 1886/2900] kernel: remove unnecessary head file ip_vs.h is not necessary for sysctl_binary.c. prepare for the next patch to avoid compile issue. Signed-off-by: JunweiZhang Signed-off-by: Nicolas Dichtel Reviewed-by: Julian Anastasov Signed-off-by: Simon Horman --- kernel/sysctl_binary.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index aea4a9ea6fc8..b609213ca9a2 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c @@ -3,7 +3,6 @@ #include "../fs/xfs/xfs_sysctl.h" #include #include -#include #include #include #include -- GitLab From 8b4d14d8eb36874daf159d33dcccd4746a6f3189 Mon Sep 17 00:00:00 2001 From: JunweiZhang Date: Wed, 26 Jun 2013 16:40:06 +0800 Subject: [PATCH 1887/2900] netns: exclude ipvs from struct net when IPVS disabled no real problem is fixed, just save a few bytes in net_namespace structure. Signed-off-by: JunweiZhang Signed-off-by: Nicolas Dichtel Reviewed-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/net_namespace.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 495bc57f292c..84e37b1ca9e1 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -115,7 +115,9 @@ struct net { #ifdef CONFIG_XFRM struct netns_xfrm xfrm; #endif +#if IS_ENABLED(CONFIG_IP_VS) struct netns_ipvs *ipvs; +#endif struct sock *diag_nlsk; atomic_t rt_genid; atomic_t fnhe_genid; -- GitLab From 218a12f1f41f6fdce18d084e5ddd3c6439db0983 Mon Sep 17 00:00:00 2001 From: Graeme Smecher Date: Sat, 8 Jun 2013 09:52:08 -0700 Subject: [PATCH 1888/2900] microblaze: Don't mark arch_kgdb_ops as const. Other architectures don't do it, and it conflicts with the extern'd definition in include/linux/kgdb.h. The patch fails checkpatch but it reflects current functions declaration and solved compilation error. Signed-off-by: Graeme Smecher CC: Michal Simek CC: linux-kernel@vger.kernel.org Signed-off-by: Michal Simek --- arch/microblaze/kernel/kgdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c index 8adc92443100..09a5e8286137 100644 --- a/arch/microblaze/kernel/kgdb.c +++ b/arch/microblaze/kernel/kgdb.c @@ -141,7 +141,7 @@ void kgdb_arch_exit(void) /* * Global data */ -const struct kgdb_arch arch_kgdb_ops = { +struct kgdb_arch arch_kgdb_ops = { #ifdef __MICROBLAZEEL__ .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */ #else -- GitLab From c421cee4e897c50688e04639189b4f5f4c8e57c6 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 26 Jun 2013 11:07:11 +0200 Subject: [PATCH 1889/2900] microblaze: Enable KGDB in defconfig Enable KGDB in defconfig to be sure that support is regularly compiled. Signed-off-by: Michal Simek --- arch/microblaze/configs/mmu_defconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index 3649a8b150c0..deaf45ab6429 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_FHANDLE=y @@ -81,6 +80,9 @@ CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_SLAB=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_INFO=y +CONFIG_KGDB=y +CONFIG_KGDB_TESTS=y +CONFIG_KGDB_KDB=y CONFIG_EARLY_PRINTK=y CONFIG_KEYS=y CONFIG_ENCRYPTED_KEYS=y -- GitLab From 71077bc8db67f560453d62c48e3bec467ec6b37f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Jun 2013 00:25:02 +0800 Subject: [PATCH 1890/2900] pwm: renesas-tpu: Add MODULE_ALIAS to make module auto loading work This driver can be built as module, add MODULE_ALIAS to make module auto loading work. Signed-off-by: Axel Lin Signed-off-by: Thierry Reding --- drivers/pwm/pwm-renesas-tpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 03c1aa3c48a2..2600892782c1 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -471,3 +471,4 @@ module_platform_driver(tpu_driver); MODULE_AUTHOR("Laurent Pinchart "); MODULE_DESCRIPTION("Renesas TPU PWM Driver"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:renesas-tpu-pwm"); -- GitLab From 490f16171119a16e05d670306c105f3b45c38837 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Tue, 25 Jun 2013 23:37:44 +0200 Subject: [PATCH 1891/2900] Revert "kconfig: fix randomising choice entries in presence of KCONFIG_ALLCONFIG" This reverts commit 8357b48549e17b3e4e402c7f977b65708922e60f. It breaks more stuff than it fixes. Reported-by: Fengguang Wu Reported-by: Sedat Dilek Signed-off-by: "Yann E. MORIN" Cc: Fengguang Wu Cc: Sedat Dilek Cc: Sam Ravnborg Cc: Stephen Rothwell Cc: Alexandre Bounine Cc: Matt Porter Signed-off-by: Michal Marek --- scripts/kconfig/confdata.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 3e39208ad20e..c55c227af463 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -288,6 +288,8 @@ int conf_read_simple(const char *name, int def) for_all_symbols(i, sym) { sym->flags |= SYMBOL_CHANGED; sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; switch (sym->type) { case S_INT: case S_HEX: @@ -377,13 +379,13 @@ int conf_read_simple(const char *name, int def) case mod: if (cs->def[def].tri == yes) { conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; } break; case yes: if (cs->def[def].tri != no) conf_warning("override: %s changes choice state", sym->name); cs->def[def].val = sym; - cs->flags |= def_flags; break; } cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); @@ -789,8 +791,6 @@ int conf_write(const char *name) sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) goto next; - if (sym_is_choice_value(sym) && !menu_is_visible(menu->parent)) - goto next; sym->flags &= ~SYMBOL_WRITE; conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); -- GitLab From 22baa407f9e67636a3fd740a552f8f5e06cf8db5 Mon Sep 17 00:00:00 2001 From: Mitko Haralanov Date: Wed, 26 Jun 2013 10:46:22 -0400 Subject: [PATCH 1892/2900] IB/qib: New transmitter tunning settings for Dell 1.1 backplane The Dell blade chassis got an updated backplane which requires new transmitter tuning settings. Signed-off-by: Mitko Haralanov Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_iba7322.c | 59 ++++++++++++++++--------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 46ffea033be0..f7c4b44b1f93 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -590,7 +590,7 @@ struct vendor_txdds_ent { static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ -#define TXDDS_EXTRA_SZ 13 /* number of extra tx settings entries */ +#define TXDDS_EXTRA_SZ 18 /* number of extra tx settings entries */ #define TXDDS_MFG_SZ 2 /* number of mfg tx settings entries */ #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ @@ -7466,15 +7466,20 @@ static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = { { 0, 0, 0, 1 }, /* QMH7342 backplane settings */ { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ - { 0, 0, 0, 11 }, /* QME7342 backplane settings */ { 0, 0, 0, 3 }, /* QMH7342 backplane settings */ { 0, 0, 0, 4 }, /* QMH7342 backplane settings */ + { 0, 1, 4, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 3, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 12 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 14 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 2, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 7 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 6 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 8 }, /* QME7342 backplane settings 1.1 */ }; static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = { @@ -7483,15 +7488,20 @@ static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = { { 0, 0, 0, 7 }, /* QMH7342 backplane settings */ { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ - { 0, 0, 0, 13 }, /* QME7342 backplane settings */ { 0, 0, 0, 9 }, /* QMH7342 backplane settings */ { 0, 0, 0, 10 }, /* QMH7342 backplane settings */ + { 0, 1, 4, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 3, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 12 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 14 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 2, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 7 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 6 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 8 }, /* QME7342 backplane settings 1.1 */ }; static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { @@ -7500,15 +7510,20 @@ static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { { 0, 1, 0, 5 }, /* QMH7342 backplane settings */ { 0, 1, 0, 6 }, /* QMH7342 backplane settings */ { 0, 1, 0, 8 }, /* QMH7342 backplane settings */ - { 0, 1, 12, 10 }, /* QME7342 backplane setting */ - { 0, 1, 12, 11 }, /* QME7342 backplane setting */ - { 0, 1, 12, 12 }, /* QME7342 backplane setting */ - { 0, 1, 12, 14 }, /* QME7342 backplane setting */ - { 0, 1, 12, 6 }, /* QME7342 backplane setting */ - { 0, 1, 12, 7 }, /* QME7342 backplane setting */ - { 0, 1, 12, 8 }, /* QME7342 backplane setting */ { 0, 1, 0, 10 }, /* QMH7342 backplane settings */ { 0, 1, 0, 12 }, /* QMH7342 backplane settings */ + { 0, 1, 4, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 3, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 12 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 14 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 2, 15 }, /* QME7342 backplane settings 1.0 */ + { 0, 1, 0, 11 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 7 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 9 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 6 }, /* QME7342 backplane settings 1.1 */ + { 0, 1, 0, 8 }, /* QME7342 backplane settings 1.1 */ }; static const struct txdds_ent txdds_extra_mfg[TXDDS_MFG_SZ] = { -- GitLab From 963b89e80d9fb7f22fc2688428e121b410b76504 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 26 Jun 2013 17:40:33 +0200 Subject: [PATCH 1893/2900] sit: fix 4in4 + IPsec scenario Since commit 32b8a8e59c9c "sit: add IPv4 over IPv4 support", tunnel->parms.iph.protocol is 0 when both 4in4 and 6in4 are setup, but xfrm_lookup() is called only when proto is != 0, thus we need to pass the real value. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index bd227e5ea9da..3b00d81c8f1e 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -542,7 +542,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, } rt = ip_route_output_tunnel(dev_net(dev), &fl4, - tunnel->parms.iph.protocol, + protocol, dst, tnl_params->saddr, tunnel->parms.o_key, RT_TOS(tos), -- GitLab From fed1bf8dc76cd102892379fce59b9ba237afd438 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 20 Jun 2013 01:27:27 +0800 Subject: [PATCH 1894/2900] pwm: pca9685: Fix wrong argument to set MODE1_SLEEP bit Current code actually does not set MODE1_SLEEP bit because the new value for bitmask (0x1) is wrong. To set MODE1_SLEEP bit, we should pass MODE1_SLEEP as the new value for bitmask. Signed-off-by: Axel Lin Reviewed-by: Steffen Trumtrar Signed-off-by: Thierry Reding --- drivers/pwm/pwm-pca9685.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index c9f9e65415f3..3fb775ded0df 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -190,7 +190,7 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) if (--pca->active_cnt == 0) regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, - 0x1); + MODE1_SLEEP); } static const struct pwm_ops pca9685_pwm_ops = { @@ -264,7 +264,8 @@ static int pca9685_pwm_remove(struct i2c_client *client) { struct pca9685 *pca = i2c_get_clientdata(client); - regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, 0x1); + regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, + MODE1_SLEEP); return pwmchip_remove(&pca->chip); } -- GitLab From b388f15fd14c3ae62deb9a059464aa99b524ea4a Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Wed, 26 Jun 2013 14:38:04 +0200 Subject: [PATCH 1895/2900] pwm: pwm-tiehrpwm: Use clk_enable/disable instead clk_prepare/unprepare. This was found when using pwm-led on am33xx and enable heartbeat trigger. [ 808.624876] ================================= [ 808.629443] [ INFO: inconsistent lock state ] [ 808.634021] 3.9.0 #2 Not tainted [ 808.637415] --------------------------------- [ 808.641981] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. [ 808.648288] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 808.653494] (prepare_lock){+.?.+.}, at: [] clk_unprepare+0x15/0x24 [ 808.661040] {SOFTIRQ-ON-W} state was registered at: [ 808.666155] [] __lock_acquire+0x411/0x824 [ 808.671465] [] lock_acquire+0x41/0x50 [ 808.676412] [] mutex_lock_nested+0x31/0x1d8 [ 808.681912] [] clk_prepare+0x15/0x28 [ 808.686764] [] _init+0x117/0x1e0 [ 808.691256] [] omap_hwmod_for_each+0x29/0x3c [ 808.696842] [] __omap_hwmod_setup_all+0x17/0x2c [ 808.702696] [] do_one_initcall+0xc3/0x10c [ 808.708017] [] kernel_init_freeable+0xa7/0x134 [ 808.713778] [] kernel_init+0x7/0x98 [ 808.718544] [] ret_from_fork+0x11/0x3c [ 808.723583] irq event stamp: 1379172 [ 808.727328] hardirqs last enabled at (1379172): [] _raw_spin_unlock_irqrestore+0x21/0x30 [ 808.736828] hardirqs last disabled at (1379171): [] _raw_spin_lock_irqsave+0x13/0x38 [ 808.745876] softirqs last enabled at (1379164): [] irq_enter+0x49/0x4c [ 808.753747] softirqs last disabled at (1379165): [] irq_exit+0x63/0x88 [ 808.761518] [ 808.761518] other info that might help us debug this: [ 808.768373] Possible unsafe locking scenario: [ 808.768373] [ 808.774578] CPU0 [ 808.777141] ---- [ 808.779705] lock(prepare_lock); [ 808.783186] [ 808.785929] lock(prepare_lock); [ 808.789595] [ 808.789595] *** DEADLOCK *** [ 808.789595] [ 808.795805] 1 lock held by swapper/0: [ 808.799643] #0: (((&heartbeat_data->timer))){+.-...}, at: [] call_timer_fn+0x0/0x90 [ 808.808814] [ 808.808814] stack backtrace: [ 808.813402] [] (unwind_backtrace+0x1/0x98) from [] (print_usage_bug.part.25+0x16d/0x1cc) [ 808.823721] [] (print_usage_bug.part.25+0x16d/0x1cc) from [] (mark_lock+0x18d/0x434) [ 808.833669] [] (mark_lock+0x18d/0x434) from [] (__lock_acquire+0x3e1/0x824) [ 808.842803] [] (__lock_acquire+0x3e1/0x824) from [] (lock_acquire+0x41/0x50) [ 808.852031] [] (lock_acquire+0x41/0x50) from [] (mutex_lock_nested+0x31/0x1d8) [ 808.861433] [] (mutex_lock_nested+0x31/0x1d8) from [] (clk_unprepare+0x15/0x24) [ 808.870930] [] (clk_unprepare+0x15/0x24) from [] (ehrpwm_pwm_disable+0x5f/0x80) [ 808.880431] [] (ehrpwm_pwm_disable+0x5f/0x80) from [] (pwm_disable+0x27/0x28) [ 808.889751] [] (pwm_disable+0x27/0x28) from [] (led_heartbeat_function+0x3f/0xb0) [ 808.899431] [] (led_heartbeat_function+0x3f/0xb0) from [] (call_timer_fn+0x45/0x90) [ 808.909288] [] (call_timer_fn+0x45/0x90) from [] (run_timer_softirq+0x105/0x17c) [ 808.918884] [] (run_timer_softirq+0x105/0x17c) from [] (__do_softirq+0xa5/0x150) [ 808.928486] [] (__do_softirq+0xa5/0x150) from [] (irq_exit+0x63/0x88) [ 808.937098] [] (irq_exit+0x63/0x88) from [] (handle_IRQ+0x21/0x54) [ 808.945415] [] (handle_IRQ+0x21/0x54) from [] (omap3_intc_handle_irq+0x5d/0x68) [ 808.954900] [] (omap3_intc_handle_irq+0x5d/0x68) from [] (__irq_svc+0x3f/0x64) [ 808.964287] Exception stack(0xc05b1f68 to 0xc05b1fb0) [ 808.969587] 1f60: 00000001 00000001 00000000 00000000 c05b0000 c0619748 [ 808.978158] 1f80: c05b0000 c05b0000 c0619748 413fc082 00000000 00000000 01000000 c05b1fb0 [ 808.986719] 1fa0: c004f989 c000d6f0 400f0033 ffffffff [ 808.992024] [] (__irq_svc+0x3f/0x64) from [] (cpu_idle+0x60/0x98) [ 809.000250] [] (cpu_idle+0x60/0x98) from [] (start_kernel+0x1e9/0x234) Remove non atomic clk api calls and use only atomic for enable/disable because can be called from atomic context (led_heartbeat_function is timer callback). Signed-off-by: Marek Belisko Signed-off-by: Thierry Reding --- drivers/pwm/pwm-tiehrpwm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 48a485c2e422..aa4c5586f53b 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -359,7 +359,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) configure_polarity(pc, pwm->hwpwm); /* Enable TBCLK before enabling PWM device */ - ret = clk_prepare_enable(pc->tbclk); + ret = clk_enable(pc->tbclk); if (ret) { pr_err("Failed to enable TBCLK for %s\n", dev_name(pc->chip.dev)); @@ -395,7 +395,7 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); /* Disabling TBCLK on PWM disable */ - clk_disable_unprepare(pc->tbclk); + clk_disable(pc->tbclk); /* Stop Time base counter */ ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); @@ -482,6 +482,12 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) return PTR_ERR(pc->tbclk); } + ret = clk_prepare(pc->tbclk); + if (ret < 0) { + dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret); + return ret; + } + ret = pwmchip_add(&pc->chip); if (ret < 0) { dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); @@ -508,6 +514,7 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pwmchip_remove(&pc->chip); + clk_unprepare(pc->tbclk); return ret; } @@ -515,6 +522,8 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev) { struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); + clk_unprepare(pc->tbclk); + pm_runtime_get_sync(&pdev->dev); /* * Due to hardware misbehaviour, acknowledge of the stop_req -- GitLab From 77ecaace6c5487eae8ede633ad51478511a8e125 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Wed, 26 Jun 2013 03:41:49 +0200 Subject: [PATCH 1896/2900] ipv6: rearm router solicitaion timer when setting new tokenized address When a new tokenized address gets installed we send out just one router solicition. We should send out `rtr_solicits' in case one router advertisment got lost. So, rearm the timer as we do in addrconf_dad_complete. Cc: Daniel Borkmann Signed-off-by: Hannes Frederic Sowa Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index afaf3cdadf58..4e4cc1fc26d1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4361,8 +4361,11 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) write_lock_bh(&idev->lock); - if (update_rs) + if (update_rs) { idev->if_flags |= IF_RS_SENT; + idev->rs_probes = 1; + addrconf_mod_rs_timer(idev, idev->cnf.rtr_solicit_interval); + } /* Well, that's kinda nasty ... */ list_for_each_entry(ifp, &idev->addr_list, if_list) { -- GitLab From 38ae92dc215e939897f17861d658f882d0eaab0f Mon Sep 17 00:00:00 2001 From: Chris Healy Date: Tue, 25 Jun 2013 23:18:52 -0700 Subject: [PATCH 1897/2900] fec: Add support for reading RMON registers Add ethtool operation to read RMON registers. Tested against net-next on i.MX28. v2: make conditional on #ifndef CONFIG_M5272 Signed-off-by: Chris Healy Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 55 +++++++++++ drivers/net/ethernet/freescale/fec_main.c | 114 ++++++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index e3ed6c5ae801..8362a0399afb 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -60,6 +60,61 @@ #define BM_MIIGSK_CFGR_RMII 0x01 #define BM_MIIGSK_CFGR_FRCONT_10M 0x40 +#define RMON_T_DROP 0x200 /* Count of frames not cntd correctly */ +#define RMON_T_PACKETS 0x204 /* RMON TX packet count */ +#define RMON_T_BC_PKT 0x208 /* RMON TX broadcast pkts */ +#define RMON_T_MC_PKT 0x20C /* RMON TX multicast pkts */ +#define RMON_T_CRC_ALIGN 0x210 /* RMON TX pkts with CRC align err */ +#define RMON_T_UNDERSIZE 0x214 /* RMON TX pkts < 64 bytes, good CRC */ +#define RMON_T_OVERSIZE 0x218 /* RMON TX pkts > MAX_FL bytes good CRC */ +#define RMON_T_FRAG 0x21C /* RMON TX pkts < 64 bytes, bad CRC */ +#define RMON_T_JAB 0x220 /* RMON TX pkts > MAX_FL bytes, bad CRC */ +#define RMON_T_COL 0x224 /* RMON TX collision count */ +#define RMON_T_P64 0x228 /* RMON TX 64 byte pkts */ +#define RMON_T_P65TO127 0x22C /* RMON TX 65 to 127 byte pkts */ +#define RMON_T_P128TO255 0x230 /* RMON TX 128 to 255 byte pkts */ +#define RMON_T_P256TO511 0x234 /* RMON TX 256 to 511 byte pkts */ +#define RMON_T_P512TO1023 0x238 /* RMON TX 512 to 1023 byte pkts */ +#define RMON_T_P1024TO2047 0x23C /* RMON TX 1024 to 2047 byte pkts */ +#define RMON_T_P_GTE2048 0x240 /* RMON TX pkts > 2048 bytes */ +#define RMON_T_OCTETS 0x244 /* RMON TX octets */ +#define IEEE_T_DROP 0x248 /* Count of frames not counted crtly */ +#define IEEE_T_FRAME_OK 0x24C /* Frames tx'd OK */ +#define IEEE_T_1COL 0x250 /* Frames tx'd with single collision */ +#define IEEE_T_MCOL 0x254 /* Frames tx'd with multiple collision */ +#define IEEE_T_DEF 0x258 /* Frames tx'd after deferral delay */ +#define IEEE_T_LCOL 0x25C /* Frames tx'd with late collision */ +#define IEEE_T_EXCOL 0x260 /* Frames tx'd with excesv collisions */ +#define IEEE_T_MACERR 0x264 /* Frames tx'd with TX FIFO underrun */ +#define IEEE_T_CSERR 0x268 /* Frames tx'd with carrier sense err */ +#define IEEE_T_SQE 0x26C /* Frames tx'd with SQE err */ +#define IEEE_T_FDXFC 0x270 /* Flow control pause frames tx'd */ +#define IEEE_T_OCTETS_OK 0x274 /* Octet count for frames tx'd w/o err */ +#define RMON_R_PACKETS 0x284 /* RMON RX packet count */ +#define RMON_R_BC_PKT 0x288 /* RMON RX broadcast pkts */ +#define RMON_R_MC_PKT 0x28C /* RMON RX multicast pkts */ +#define RMON_R_CRC_ALIGN 0x290 /* RMON RX pkts with CRC alignment err */ +#define RMON_R_UNDERSIZE 0x294 /* RMON RX pkts < 64 bytes, good CRC */ +#define RMON_R_OVERSIZE 0x298 /* RMON RX pkts > MAX_FL bytes good CRC */ +#define RMON_R_FRAG 0x29C /* RMON RX pkts < 64 bytes, bad CRC */ +#define RMON_R_JAB 0x2A0 /* RMON RX pkts > MAX_FL bytes, bad CRC */ +#define RMON_R_RESVD_O 0x2A4 /* Reserved */ +#define RMON_R_P64 0x2A8 /* RMON RX 64 byte pkts */ +#define RMON_R_P65TO127 0x2AC /* RMON RX 65 to 127 byte pkts */ +#define RMON_R_P128TO255 0x2B0 /* RMON RX 128 to 255 byte pkts */ +#define RMON_R_P256TO511 0x2B4 /* RMON RX 256 to 511 byte pkts */ +#define RMON_R_P512TO1023 0x2B8 /* RMON RX 512 to 1023 byte pkts */ +#define RMON_R_P1024TO2047 0x2BC /* RMON RX 1024 to 2047 byte pkts */ +#define RMON_R_P_GTE2048 0x2C0 /* RMON RX pkts > 2048 bytes */ +#define RMON_R_OCTETS 0x2C4 /* RMON RX octets */ +#define IEEE_R_DROP 0x2C8 /* Count frames not counted correctly */ +#define IEEE_R_FRAME_OK 0x2CC /* Frames rx'd OK */ +#define IEEE_R_CRC 0x2D0 /* Frames rx'd with CRC err */ +#define IEEE_R_ALIGN 0x2D4 /* Frames rx'd with alignment err */ +#define IEEE_R_MACERR 0x2D8 /* Receive FIFO overflow count */ +#define IEEE_R_FDXFC 0x2DC /* Flow control pause frames rx'd */ +#define IEEE_R_OCTETS_OK 0x2E0 /* Octet cnt for frames rx'd w/o err */ + #else #define FEC_ECNTRL 0x000 /* Ethernet control reg */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 46f2544fd1a7..ed6180e7db2f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -604,6 +604,14 @@ fec_restart(struct net_device *ndev, int duplex) if (fep->bufdesc_ex) ecntl |= (1 << 4); +#ifndef CONFIG_M5272 + /* Disable, clear, and enable the MIB */ + writel(1 << 31, fep->hwp + FEC_MIB_CTRLSTAT); + for (i = RMON_T_DROP; i < IEEE_R_OCTETS_OK; i++) + writel(0, fep->hwp + i); + writel(0, fep->hwp + FEC_MIB_CTRLSTAT); +#endif + /* And last, enable the transmit and receive processing */ writel(ecntl, fep->hwp + FEC_ECNTRL); writel(0, fep->hwp + FEC_R_DES_ACTIVE); @@ -1435,6 +1443,107 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, return 0; } +#ifndef CONFIG_M5272 +static const struct fec_stat { + char name[ETH_GSTRING_LEN]; + u16 offset; +} fec_stats[] = { + /* RMON TX */ + { "tx_dropped", RMON_T_DROP }, + { "tx_packets", RMON_T_PACKETS }, + { "tx_broadcast", RMON_T_BC_PKT }, + { "tx_multicast", RMON_T_MC_PKT }, + { "tx_crc_errors", RMON_T_CRC_ALIGN }, + { "tx_undersize", RMON_T_UNDERSIZE }, + { "tx_oversize", RMON_T_OVERSIZE }, + { "tx_fragment", RMON_T_FRAG }, + { "tx_jabber", RMON_T_JAB }, + { "tx_collision", RMON_T_COL }, + { "tx_64byte", RMON_T_P64 }, + { "tx_65to127byte", RMON_T_P65TO127 }, + { "tx_128to255byte", RMON_T_P128TO255 }, + { "tx_256to511byte", RMON_T_P256TO511 }, + { "tx_512to1023byte", RMON_T_P512TO1023 }, + { "tx_1024to2047byte", RMON_T_P1024TO2047 }, + { "tx_GTE2048byte", RMON_T_P_GTE2048 }, + { "tx_octets", RMON_T_OCTETS }, + + /* IEEE TX */ + { "IEEE_tx_drop", IEEE_T_DROP }, + { "IEEE_tx_frame_ok", IEEE_T_FRAME_OK }, + { "IEEE_tx_1col", IEEE_T_1COL }, + { "IEEE_tx_mcol", IEEE_T_MCOL }, + { "IEEE_tx_def", IEEE_T_DEF }, + { "IEEE_tx_lcol", IEEE_T_LCOL }, + { "IEEE_tx_excol", IEEE_T_EXCOL }, + { "IEEE_tx_macerr", IEEE_T_MACERR }, + { "IEEE_tx_cserr", IEEE_T_CSERR }, + { "IEEE_tx_sqe", IEEE_T_SQE }, + { "IEEE_tx_fdxfc", IEEE_T_FDXFC }, + { "IEEE_tx_octets_ok", IEEE_T_OCTETS_OK }, + + /* RMON RX */ + { "rx_packets", RMON_R_PACKETS }, + { "rx_broadcast", RMON_R_BC_PKT }, + { "rx_multicast", RMON_R_MC_PKT }, + { "rx_crc_errors", RMON_R_CRC_ALIGN }, + { "rx_undersize", RMON_R_UNDERSIZE }, + { "rx_oversize", RMON_R_OVERSIZE }, + { "rx_fragment", RMON_R_FRAG }, + { "rx_jabber", RMON_R_JAB }, + { "rx_64byte", RMON_R_P64 }, + { "rx_65to127byte", RMON_R_P65TO127 }, + { "rx_128to255byte", RMON_R_P128TO255 }, + { "rx_256to511byte", RMON_R_P256TO511 }, + { "rx_512to1023byte", RMON_R_P512TO1023 }, + { "rx_1024to2047byte", RMON_R_P1024TO2047 }, + { "rx_GTE2048byte", RMON_R_P_GTE2048 }, + { "rx_octets", RMON_R_OCTETS }, + + /* IEEE RX */ + { "IEEE_rx_drop", IEEE_R_DROP }, + { "IEEE_rx_frame_ok", IEEE_R_FRAME_OK }, + { "IEEE_rx_crc", IEEE_R_CRC }, + { "IEEE_rx_align", IEEE_R_ALIGN }, + { "IEEE_rx_macerr", IEEE_R_MACERR }, + { "IEEE_rx_fdxfc", IEEE_R_FDXFC }, + { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK }, +}; + +static void fec_enet_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct fec_enet_private *fep = netdev_priv(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(fec_stats); i++) + data[i] = readl(fep->hwp + fec_stats[i].offset); +} + +static void fec_enet_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) +{ + int i; + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(fec_stats); i++) + memcpy(data + i * ETH_GSTRING_LEN, + fec_stats[i].name, ETH_GSTRING_LEN); + break; + } +} + +static int fec_enet_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(fec_stats); + default: + return -EOPNOTSUPP; + } +} +#endif + static int fec_enet_nway_reset(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); @@ -1455,6 +1564,11 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { .get_link = ethtool_op_get_link, .get_ts_info = fec_enet_get_ts_info, .nway_reset = fec_enet_nway_reset, +#ifndef CONFIG_M5272 + .get_ethtool_stats = fec_enet_get_ethtool_stats, + .get_strings = fec_enet_get_strings, + .get_sset_count = fec_enet_get_sset_count, +#endif }; static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -- GitLab From 3f90b82df110ef9cb33761b56ca85ae0d0372d4a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 27 Jun 2013 02:04:25 +0200 Subject: [PATCH 1898/2900] MIPS: tlbex: Fix size of area to be flushed. Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 7f6cd461dac5..2f88fd3a64cf 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -2191,7 +2191,7 @@ static void __cpuinit flush_tlb_handlers(void) (unsigned long)handle_tlbm + sizeof(handle_tlbm)); #ifdef CONFIG_MIPS_PGD_C0_CONTEXT local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, - (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); + (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(tlbmiss_handler_setup_pgd_array)); #endif } -- GitLab From b5c46787df1f28b0a24499e275491ba9a505c8ec Mon Sep 17 00:00:00 2001 From: J Keerthy Date: Thu, 20 Jun 2013 16:32:15 +0530 Subject: [PATCH 1899/2900] regulator: palmas: Add TPS659038 support Add TPS659038 support. Signed-off-by: J Keerthy Acked-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/regulator/palmas-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 1ae1e83448cf..d0c87856dd25 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -1054,6 +1054,7 @@ static struct of_device_id of_palmas_match_tbl[] = { { .compatible = "ti,tps65913-pmic", }, { .compatible = "ti,tps65914-pmic", }, { .compatible = "ti,tps80036-pmic", }, + { .compatible = "ti,tps659038-pmic", }, { /* end */ } }; -- GitLab From 30caa4b763bf5973800633de55bae586ab443f78 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 10 Jun 2013 23:12:56 -0300 Subject: [PATCH 1900/2900] ARM: imx: prepare for removal of flexcan_platform_data As there are no imx in-tree users of flexcan_platform_data, this patch removes the possibility to register a flexcan device with platform data. The functionality to swith on/off CAN transceivers is added to DT via regulators in a later patch. Compile time tested with imx_v4_v5_defconfig and imx_v6_v7_defconfig. Acked-by: Shawn Guo Acked-by: Sascha Hauer Signed-off-by: Marc Kleine-Budde --- arch/arm/mach-imx/devices-imx25.h | 8 ++++---- arch/arm/mach-imx/devices-imx35.h | 8 ++++---- arch/arm/mach-imx/devices/devices-common.h | 4 +--- arch/arm/mach-imx/devices/platform-flexcan.c | 5 ++--- arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | 2 +- arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | 2 +- arch/arm/mach-imx/mach-mx25_3ds.c | 2 +- arch/arm/mach-imx/mach-pcm043.c | 2 +- 8 files changed, 15 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h index 0d2922bc575c..769563fdeaa0 100644 --- a/arch/arm/mach-imx/devices-imx25.h +++ b/arch/arm/mach-imx/devices-imx25.h @@ -13,10 +13,10 @@ extern const struct imx_fec_data imx25_fec_data; imx_add_fec(&imx25_fec_data, pdata) extern const struct imx_flexcan_data imx25_flexcan_data[]; -#define imx25_add_flexcan(id, pdata) \ - imx_add_flexcan(&imx25_flexcan_data[id], pdata) -#define imx25_add_flexcan0(pdata) imx25_add_flexcan(0, pdata) -#define imx25_add_flexcan1(pdata) imx25_add_flexcan(1, pdata) +#define imx25_add_flexcan(id) \ + imx_add_flexcan(&imx25_flexcan_data[id]) +#define imx25_add_flexcan0() imx25_add_flexcan(0) +#define imx25_add_flexcan1() imx25_add_flexcan(1) extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data; #define imx25_add_fsl_usb2_udc(pdata) \ diff --git a/arch/arm/mach-imx/devices-imx35.h b/arch/arm/mach-imx/devices-imx35.h index e2675f1b141c..780d8240281b 100644 --- a/arch/arm/mach-imx/devices-imx35.h +++ b/arch/arm/mach-imx/devices-imx35.h @@ -17,10 +17,10 @@ extern const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data; imx_add_fsl_usb2_udc(&imx35_fsl_usb2_udc_data, pdata) extern const struct imx_flexcan_data imx35_flexcan_data[]; -#define imx35_add_flexcan(id, pdata) \ - imx_add_flexcan(&imx35_flexcan_data[id], pdata) -#define imx35_add_flexcan0(pdata) imx35_add_flexcan(0, pdata) -#define imx35_add_flexcan1(pdata) imx35_add_flexcan(1, pdata) +#define imx35_add_flexcan(id) \ + imx_add_flexcan(&imx35_flexcan_data[id]) +#define imx35_add_flexcan0() imx35_add_flexcan(0) +#define imx35_add_flexcan1() imx35_add_flexcan(1) extern const struct imx_imx2_wdt_data imx35_imx2_wdt_data; #define imx35_add_imx2_wdt() \ diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h index 453e20bc2657..c13b76b9f6b3 100644 --- a/arch/arm/mach-imx/devices/devices-common.h +++ b/arch/arm/mach-imx/devices/devices-common.h @@ -50,7 +50,6 @@ struct platform_device *__init imx_add_fec( const struct imx_fec_data *data, const struct fec_platform_data *pdata); -#include struct imx_flexcan_data { int id; resource_size_t iobase; @@ -58,8 +57,7 @@ struct imx_flexcan_data { resource_size_t irq; }; struct platform_device *__init imx_add_flexcan( - const struct imx_flexcan_data *data, - const struct flexcan_platform_data *pdata); + const struct imx_flexcan_data *data); #include struct imx_fsl_usb2_udc_data { diff --git a/arch/arm/mach-imx/devices/platform-flexcan.c b/arch/arm/mach-imx/devices/platform-flexcan.c index 1078bf0a94ef..55d61eaf63c6 100644 --- a/arch/arm/mach-imx/devices/platform-flexcan.c +++ b/arch/arm/mach-imx/devices/platform-flexcan.c @@ -38,8 +38,7 @@ const struct imx_flexcan_data imx35_flexcan_data[] __initconst = { #endif /* ifdef CONFIG_SOC_IMX35 */ struct platform_device *__init imx_add_flexcan( - const struct imx_flexcan_data *data, - const struct flexcan_platform_data *pdata) + const struct imx_flexcan_data *data) { struct resource res[] = { { @@ -54,5 +53,5 @@ struct platform_device *__init imx_add_flexcan( }; return imx_add_platform_device("flexcan", data->id, - res, ARRAY_SIZE(res), pdata, sizeof(*pdata)); + res, ARRAY_SIZE(res), NULL, 0); } diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index e2b70f4c1a2c..e77cc3af6db2 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c @@ -279,7 +279,7 @@ void __init eukrea_mbimxsd25_baseboard_init(void) imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata); imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); - imx25_add_flexcan1(NULL); + imx25_add_flexcan1(); imx25_add_sdhci_esdhc_imx(0, &sd1_pdata); gpio_request(GPIO_LED1, "LED1"); diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index 5a2d5ef12dd5..14d6c8249b76 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c @@ -287,7 +287,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void) imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata); - imx35_add_flexcan1(NULL); + imx35_add_flexcan1(); imx35_add_sdhci_esdhc_imx(0, &sd1_pdata); gpio_request(GPIO_LED1, "LED1"); diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index 8bcda688a006..13490c203050 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -249,7 +249,7 @@ static void __init mx25pdk_init(void) imx25_add_imx_i2c0(&mx25_3ds_i2c0_data); gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn"); - imx25_add_flexcan0(NULL); + imx25_add_flexcan0(); } static void __init mx25pdk_timer_init(void) diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 8ed533f0f8ca..b726cb1c5fdd 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -385,7 +385,7 @@ static void __init pcm043_init(void) if (!otg_mode_host) imx35_add_fsl_usb2_udc(&otg_device_pdata); - imx35_add_flexcan1(NULL); + imx35_add_flexcan1(); imx35_add_sdhci_esdhc_imx(0, &sd1_pdata); } -- GitLab From b7c4114b07bbacfe0aee1d04ad1ade9e42309620 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Jun 2013 23:12:57 -0300 Subject: [PATCH 1901/2900] can: flexcan: Use a regulator to control the CAN transceiver Instead of using a GPIO to turn on/off the CAN transceiver, it is better to use a regulator as some systems may use a PMIC to power the CAN transceiver. Acked-by: Shawn Guo Signed-off-by: Fabio Estevam Signed-off-by: Marc Kleine-Budde --- .../bindings/net/can/fsl-flexcan.txt | 2 + arch/arm/boot/dts/imx28-evk.dts | 12 +++++ arch/arm/mach-mxs/mach-mxs.c | 50 +------------------ drivers/net/can/flexcan.c | 25 +++++----- 4 files changed, 28 insertions(+), 61 deletions(-) diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt index 8ff324eaa889..56d6cc336e1c 100644 --- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt +++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt @@ -16,6 +16,8 @@ Optional properties: - clock-frequency : The oscillator frequency driving the flexcan device +- xceiver-supply: Regulator that powers the CAN transceiver + Example: can@1c000 { diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts index 3637bf3b1d59..1f0d38d7b16f 100644 --- a/arch/arm/boot/dts/imx28-evk.dts +++ b/arch/arm/boot/dts/imx28-evk.dts @@ -155,12 +155,14 @@ can0: can@80032000 { pinctrl-names = "default"; pinctrl-0 = <&can0_pins_a>; + xceiver-supply = <®_can_3v3>; status = "okay"; }; can1: can@80034000 { pinctrl-names = "default"; pinctrl-0 = <&can1_pins_a>; + xceiver-supply = <®_can_3v3>; status = "okay"; }; }; @@ -319,6 +321,16 @@ gpio = <&gpio3 30 0>; enable-active-high; }; + + reg_can_3v3: can-3v3 { + compatible = "regulator-fixed"; + regulator-name = "can-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 13 0>; + enable-active-high; + }; + }; sound { diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 5b62b6489d4b..97b8a44101cd 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -60,41 +59,6 @@ static inline void __mxs_togl(u32 mask, void __iomem *reg) __raw_writel(mask, reg + MXS_TOG_ADDR); } -/* - * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers - */ -#define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) - -static int flexcan0_en, flexcan1_en; - -static void mx28evk_flexcan_switch(void) -{ - if (flexcan0_en || flexcan1_en) - gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); - else - gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); -} - -static void mx28evk_flexcan0_switch(int enable) -{ - flexcan0_en = enable; - mx28evk_flexcan_switch(); -} - -static void mx28evk_flexcan1_switch(int enable) -{ - flexcan1_en = enable; - mx28evk_flexcan_switch(); -} - -static struct flexcan_platform_data flexcan_pdata[2]; - -static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), - OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), - { /* sentinel */ } -}; - #define OCOTP_WORD_OFFSET 0x20 #define OCOTP_WORD_COUNT 0x20 @@ -254,15 +218,6 @@ static void __init imx28_evk_init(void) mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); } -static void __init imx28_evk_post_init(void) -{ - if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, - "flexcan-switch")) { - flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; - flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; - } -} - static int apx4devkit_phy_fixup(struct phy_device *phy) { phy->dev_flags |= MICREL_PHY_50MHZ_CLK; @@ -374,13 +329,10 @@ static void __init mxs_machine_init(void) cfa10049_init(); of_platform_populate(NULL, of_default_bus_match_table, - mxs_auxdata_lookup, NULL); + NULL, NULL); if (of_machine_is_compatible("karo,tx28")) tx28_post_init(); - - if (of_machine_is_compatible("fsl,imx28-evk")) - imx28_evk_post_init(); } #define MX23_CLKCTRL_RESET_OFFSET 0x120 diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index f873b9f8d4d4..7b0be0910f4b 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #define DRV_NAME "flexcan" @@ -211,6 +211,7 @@ struct flexcan_priv { struct clk *clk_per; struct flexcan_platform_data *pdata; const struct flexcan_devtype_data *devtype_data; + struct regulator *reg_xceiver; }; static struct flexcan_devtype_data fsl_p1010_devtype_data = { @@ -258,15 +259,6 @@ static inline void flexcan_write(u32 val, void __iomem *addr) } #endif -/* - * Swtich transceiver on or off - */ -static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) -{ - if (priv->pdata && priv->pdata->transceiver_switch) - priv->pdata->transceiver_switch(on); -} - static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, u32 reg_esr) { @@ -799,7 +791,11 @@ static int flexcan_chip_start(struct net_device *dev) if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) flexcan_write(0x0, ®s->rxfgmask); - flexcan_transceiver_switch(priv, 1); + if (priv->reg_xceiver) { + err = regulator_enable(priv->reg_xceiver); + if (err) + goto out; + } /* synchronize with the can bus */ reg_mcr = flexcan_read(®s->mcr); @@ -842,7 +838,8 @@ static void flexcan_chip_stop(struct net_device *dev) reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; flexcan_write(reg, ®s->mcr); - flexcan_transceiver_switch(priv, 0); + if (priv->reg_xceiver) + regulator_disable(priv->reg_xceiver); priv->can.state = CAN_STATE_STOPPED; return; @@ -1084,6 +1081,10 @@ static int flexcan_probe(struct platform_device *pdev) priv->pdata = pdev->dev.platform_data; priv->devtype_data = devtype_data; + priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); + if (IS_ERR(priv->reg_xceiver)) + priv->reg_xceiver = NULL; + netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); dev_set_drvdata(&pdev->dev, dev); -- GitLab From baffd2e8d9a562021f046ed52195aaac91a51412 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 10 Jun 2013 23:12:58 -0300 Subject: [PATCH 1902/2900] ARM: imx: flexcan: Remove platform file As there are no more users of the flexcan platform file, let's remove it. Cc: Sascha Hauer Acked-by: Shawn Guo Signed-off-by: Fabio Estevam Signed-off-by: Marc Kleine-Budde --- include/linux/can/platform/flexcan.h | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 include/linux/can/platform/flexcan.h diff --git a/include/linux/can/platform/flexcan.h b/include/linux/can/platform/flexcan.h deleted file mode 100644 index 72b713ab57e9..000000000000 --- a/include/linux/can/platform/flexcan.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2010 Marc Kleine-Budde - * - * This file is released under the GPLv2 - * - */ - -#ifndef __CAN_PLATFORM_FLEXCAN_H -#define __CAN_PLATFORM_FLEXCAN_H - -/** - * struct flexcan_platform_data - flex CAN controller platform data - * @transceiver_enable: - called to power on/off the transceiver - * - */ -struct flexcan_platform_data { - void (*transceiver_switch)(int enable); -}; - -#endif /* __CAN_PLATFORM_FLEXCAN_H */ -- GitLab From 1f3e4b0cc4deb9d740261273fbbf5ea95c8434d0 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 12 Jun 2013 17:00:39 +0530 Subject: [PATCH 1903/2900] can: at91_can: Use of_match_ptr() of_match_ptr() eliminates having an #ifdef returning NULL for the case when OF is disabled. Signed-off-by: Sachin Kamat Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index ce8421ac453a..dbbe97ae121e 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1264,8 +1264,6 @@ static const struct of_device_id at91_can_dt_ids[] = { } }; MODULE_DEVICE_TABLE(of, at91_can_dt_ids); -#else -#define at91_can_dt_ids NULL #endif static const struct at91_devtype_data *at91_can_get_driver_data(struct platform_device *pdev) @@ -1424,7 +1422,7 @@ static struct platform_driver at91_can_driver = { .driver = { .name = KBUILD_MODNAME, .owner = THIS_MODULE, - .of_match_table = at91_can_dt_ids, + .of_match_table = of_match_ptr(at91_can_dt_ids), }, .id_table = at91_can_id_table, }; -- GitLab From fca9661c6c8926171a49f6ac57adc65290f10caf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 12 May 2013 20:12:38 +0200 Subject: [PATCH 1904/2900] mmc: jz4740: Use clk_prepare_enable/clk_disable_unprepare In preparation to switching the jz4740 clk driver to the common clk framework, update the clk enable/disable calls to clk_prepare_enable/clk_disable_unprepare. Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 1c47b3473ce3..c4f3872d06a7 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -626,7 +626,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) gpio_set_value(host->pdata->gpio_power, !host->pdata->power_active_low); host->cmdat |= JZ_MMC_CMDAT_INIT; - clk_enable(host->clk); + clk_prepare_enable(host->clk); break; case MMC_POWER_ON: break; @@ -634,7 +634,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (gpio_is_valid(host->pdata->gpio_power)) gpio_set_value(host->pdata->gpio_power, host->pdata->power_active_low); - clk_disable(host->clk); + clk_disable_unprepare(host->clk); break; } -- GitLab From ec0a7517dc25b4cca8a694fd61e09771bffba022 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:11 +0200 Subject: [PATCH 1905/2900] mmc: return mmc_of_parse() errors to caller In addition to just logging errors encountered during DT parsing or allocating GPIO slots for CD/WP, mmc_of_parse() now returns with an error. In particular, this is needed if the GPIO allocation may return EPROBE_DEFER. Signed-off-by: Simon Baatz Reviewed-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/host.c | 30 +++++++++++++++++++++++++----- include/linux/mmc/host.h | 2 +- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 2a3593d9f87d..89f58498409a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -306,7 +306,7 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) * parse the properties and set respective generic mmc-host flags and * parameters. */ -void mmc_of_parse(struct mmc_host *host) +int mmc_of_parse(struct mmc_host *host) { struct device_node *np; u32 bus_width; @@ -315,7 +315,7 @@ void mmc_of_parse(struct mmc_host *host) int len, ret, gpio; if (!host->parent || !host->parent->of_node) - return; + return 0; np = host->parent->of_node; @@ -338,6 +338,7 @@ void mmc_of_parse(struct mmc_host *host) default: dev_err(host->parent, "Invalid \"bus-width\" value %ud!\n", bus_width); + return -EINVAL; } /* f_max is obtained from the optional "max-frequency" property */ @@ -367,18 +368,22 @@ void mmc_of_parse(struct mmc_host *host) host->caps |= MMC_CAP_NEEDS_POLL; gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags); + if (gpio == -EPROBE_DEFER) + return gpio; if (gpio_is_valid(gpio)) { if (!(flags & OF_GPIO_ACTIVE_LOW)) gpio_inv_cd = true; ret = mmc_gpio_request_cd(host, gpio); - if (ret < 0) + if (ret < 0) { dev_err(host->parent, "Failed to request CD GPIO #%d: %d!\n", gpio, ret); - else + return ret; + } else { dev_info(host->parent, "Got CD GPIO #%d.\n", gpio); + } } if (explicit_inv_cd ^ gpio_inv_cd) @@ -389,14 +394,23 @@ void mmc_of_parse(struct mmc_host *host) explicit_inv_wp = of_property_read_bool(np, "wp-inverted"); gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags); + if (gpio == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto out; + } if (gpio_is_valid(gpio)) { if (!(flags & OF_GPIO_ACTIVE_LOW)) gpio_inv_wp = true; ret = mmc_gpio_request_ro(host, gpio); - if (ret < 0) + if (ret < 0) { dev_err(host->parent, "Failed to request WP GPIO: %d!\n", ret); + goto out; + } else { + dev_info(host->parent, "Got WP GPIO #%d.\n", + gpio); + } } if (explicit_inv_wp ^ gpio_inv_wp) host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; @@ -413,6 +427,12 @@ void mmc_of_parse(struct mmc_host *host) host->pm_caps |= MMC_PM_KEEP_POWER; if (of_find_property(np, "enable-sdio-wakeup", &len)) host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; + + return 0; + +out: + mmc_gpio_free_cd(host); + return ret; } EXPORT_SYMBOL(mmc_of_parse); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 2e34ee5cefce..eb2e6e1e5a3e 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -369,7 +369,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *); int mmc_add_host(struct mmc_host *); void mmc_remove_host(struct mmc_host *); void mmc_free_host(struct mmc_host *); -void mmc_of_parse(struct mmc_host *host); +int mmc_of_parse(struct mmc_host *host); static inline void *mmc_priv(struct mmc_host *host) { -- GitLab From 2c9054dc102742e1683b5d879f7472fb712b7324 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:12 +0200 Subject: [PATCH 1906/2900] mmc: sh_mmcif: handle mmc_of_parse() errors during probe Signed-off-by: Simon Baatz Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mmcif.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 8ef5efad45d0..6706b5e3b974 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1370,7 +1370,11 @@ static int sh_mmcif_probe(struct platform_device *pdev) ret = -ENOMEM; goto ealloch; } - mmc_of_parse(mmc); + + ret = mmc_of_parse(mmc); + if (ret < 0) + goto eofparse; + host = mmc_priv(mmc); host->mmc = mmc; host->addr = reg; @@ -1465,6 +1469,7 @@ static int sh_mmcif_probe(struct platform_device *pdev) clk_put(host->hclk); eclkget: pm_runtime_disable(&pdev->dev); +eofparse: mmc_free_host(mmc); ealloch: iounmap(reg); -- GitLab From 274a752b1adc7e756acb283edc188f27fb3be6f8 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:13 +0200 Subject: [PATCH 1907/2900] mmc: tmio-mmc: handle mmc_of_parse() errors during probe Signed-off-by: Simon Baatz Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/tmio_mmc_pio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index f29470835a4f..b72edb72f7d2 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -1001,7 +1001,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host, if (!mmc) return -ENOMEM; - mmc_of_parse(mmc); + ret = mmc_of_parse(mmc); + if (ret < 0) + goto host_free; pdata->dev = &pdev->dev; _host = mmc_priv(mmc); -- GitLab From b88576965b9518018c604865212294719ca2744f Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:14 +0200 Subject: [PATCH 1908/2900] mmc: mxcmmc: handle mmc_of_parse() errors during probe Signed-off-by: Simon Baatz Signed-off-by: Chris Ball --- drivers/mmc/host/mxcmmc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 786448a10f15..c174c6a0d224 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1067,7 +1067,9 @@ static int mxcmci_probe(struct platform_device *pdev) goto out_release_mem; } - mmc_of_parse(mmc); + ret = mmc_of_parse(mmc); + if (ret) + goto out_free; mmc->ops = &mxcmci_ops; /* For devicetree parsing, the bus width is read from devicetree */ -- GitLab From d2cf6071cc09337eb68d960bcba94d2998de6172 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:15 +0200 Subject: [PATCH 1909/2900] mmc: sdhci-pxav3: handle mmc_of_parse() errors during probe Signed-off-by: Simon Baatz Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pxav3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 56d9bee93d8f..d29f81097334 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -252,7 +252,9 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev); if (match) { - mmc_of_parse(host->mmc); + ret = mmc_of_parse(host->mmc); + if (ret) + goto err_of_parse; sdhci_get_of_property(pdev); pdata = pxav3_get_mmc_pdata(dev); } else if (pdata) { @@ -313,10 +315,11 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) return 0; +err_of_parse: +err_cd_req: err_add_host: clk_disable_unprepare(clk); clk_put(clk); -err_cd_req: err_clk_get: sdhci_pltfm_free(pdev); kfree(pxa); -- GitLab From 47caa84fb61ac94e675c08fb45f50918766688bd Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:16 +0200 Subject: [PATCH 1910/2900] mmc: tegra: handle mmc_of_parse() errors during probe Signed-off-by: Simon Baatz Tested-by: Stephen Warren Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-tegra.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index c8b058283a06..5b7b2eba8a54 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -205,7 +205,7 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { }; MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); -static void sdhci_tegra_parse_dt(struct device *dev) +static int sdhci_tegra_parse_dt(struct device *dev) { struct device_node *np = dev->of_node; struct sdhci_host *host = dev_get_drvdata(dev); @@ -213,7 +213,7 @@ static void sdhci_tegra_parse_dt(struct device *dev) struct sdhci_tegra *tegra_host = pltfm_host->priv; tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); - mmc_of_parse(host->mmc); + return mmc_of_parse(host->mmc); } static int sdhci_tegra_probe(struct platform_device *pdev) @@ -245,7 +245,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev) tegra_host->soc_data = soc_data; pltfm_host->priv = tegra_host; - sdhci_tegra_parse_dt(&pdev->dev); + rc = sdhci_tegra_parse_dt(&pdev->dev); + if (rc) + goto err_parse_dt; if (gpio_is_valid(tegra_host->power_gpio)) { rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); @@ -279,6 +281,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) if (gpio_is_valid(tegra_host->power_gpio)) gpio_free(tegra_host->power_gpio); err_power_req: +err_parse_dt: err_alloc_tegra_host: sdhci_pltfm_free(pdev); return rc; -- GitLab From 2cd1722496de794d336e4670d8de1e46fa84b773 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 9 Jun 2013 22:14:18 +0200 Subject: [PATCH 1911/2900] mmc: mvsdio: use standard MMC device-tree binding parser mmc_of_parse() Instead of parsing the DT binding on our own, use the standard parser mmc_of_parse(), introduced by commit 6c56e7a. Signed-off-by: Simon Baatz Tested-by: Andrew Lunn Signed-off-by: Chris Ball --- drivers/mmc/host/mvsdio.c | 73 +++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index d08fe6ae9bf8..4ddd83f98658 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -35,7 +35,7 @@ #define DRIVER_NAME "mvsdio" -static int maxfreq = MVSD_CLOCKRATE_MAX; +static int maxfreq; static int nodma; struct mvsd_host { @@ -685,7 +685,6 @@ static int __init mvsd_probe(struct platform_device *pdev) const struct mbus_dram_target_info *dram; struct resource *r; int ret, irq; - int gpio_card_detect, gpio_write_protect; struct pinctrl *pinctrl; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -718,6 +717,20 @@ static int __init mvsd_probe(struct platform_device *pdev) if (!IS_ERR(host->clk)) clk_prepare_enable(host->clk); + mmc->ops = &mvsd_ops; + + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); + mmc->f_max = MVSD_CLOCKRATE_MAX; + + mmc->max_blk_size = 2048; + mmc->max_blk_count = 65535; + + mmc->max_segs = 1; + mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + if (np) { if (IS_ERR(host->clk)) { dev_err(&pdev->dev, "DT platforms must have a clock associated\n"); @@ -726,35 +739,38 @@ static int __init mvsd_probe(struct platform_device *pdev) } host->base_clock = clk_get_rate(host->clk) / 2; - gpio_card_detect = of_get_named_gpio(np, "cd-gpios", 0); - gpio_write_protect = of_get_named_gpio(np, "wp-gpios", 0); + ret = mmc_of_parse(mmc); + if (ret < 0) + goto out; } else { const struct mvsdio_platform_data *mvsd_data; + mvsd_data = pdev->dev.platform_data; if (!mvsd_data) { ret = -ENXIO; goto out; } + mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | + MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; host->base_clock = mvsd_data->clock / 2; - gpio_card_detect = mvsd_data->gpio_card_detect ? : -EINVAL; - gpio_write_protect = mvsd_data->gpio_write_protect ? : -EINVAL; - } - - mmc->ops = &mvsd_ops; - - mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | - MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; - - mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); - mmc->f_max = maxfreq; + /* GPIO 0 regarded as invalid for backward compatibility */ + if (mvsd_data->gpio_card_detect && + gpio_is_valid(mvsd_data->gpio_card_detect)) { + ret = mmc_gpio_request_cd(mmc, + mvsd_data->gpio_card_detect); + if (ret) + goto out; + } else { + mmc->caps |= MMC_CAP_NEEDS_POLL; + } - mmc->max_blk_size = 2048; - mmc->max_blk_count = 65535; + if (mvsd_data->gpio_write_protect && + gpio_is_valid(mvsd_data->gpio_write_protect)) + mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect); + } - mmc->max_segs = 1; - mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; - mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; + if (maxfreq) + mmc->f_max = maxfreq; spin_lock_init(&host->lock); @@ -777,15 +793,6 @@ static int __init mvsd_probe(struct platform_device *pdev) goto out; } - if (gpio_is_valid(gpio_card_detect)) { - ret = mmc_gpio_request_cd(mmc, gpio_card_detect); - if (ret) - goto out; - } else - mmc->caps |= MMC_CAP_NEEDS_POLL; - - mmc_gpio_request_ro(mmc, gpio_write_protect); - setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); platform_set_drvdata(pdev, mmc); ret = mmc_add_host(mmc); @@ -793,10 +800,10 @@ static int __init mvsd_probe(struct platform_device *pdev) goto out; if (!(mmc->caps & MMC_CAP_NEEDS_POLL)) - dev_notice(&pdev->dev, "using GPIO %d for card detection\n", - gpio_card_detect); + dev_notice(&pdev->dev, "using GPIO for card detection\n"); else - dev_notice(&pdev->dev, "lacking card detect (fall back to polling)\n"); + dev_notice(&pdev->dev, + "lacking card detect (fall back to polling)\n"); return 0; out: -- GitLab From 0b856f4ecb7b82c56ba2c3c624a4b5c865398cc6 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Tue, 14 May 2013 13:49:09 +0800 Subject: [PATCH 1912/2900] mmc: sdhci-sirf: let device core setup the default pin configuration With device core now able to setup the default pin configuration, the call to devm_pinctrl_get_select_default can be removed. And the pin configuration code based on the deprecated Samsung specific gpio bindings is also removed. Acked-by: Linus Walleij Signed-off-by: Barry Song Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-sirf.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index 09805af0526d..ccf12dd93616 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "sdhci-pltfm.h" struct sdhci_sirf_priv { @@ -46,15 +45,8 @@ static int sdhci_sirf_probe(struct platform_device *pdev) struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_sirf_priv *priv; - struct pinctrl *pinctrl; int ret; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - dev_err(&pdev->dev, "unable to get pinmux"); - return PTR_ERR(pinctrl); - } - priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_sirf_priv), GFP_KERNEL); if (!priv) { -- GitLab From 6636bad839d9936e73e48c4841eda83a58fcdb53 Mon Sep 17 00:00:00 2001 From: Yuvaraj Kumar C D Date: Tue, 21 May 2013 15:08:43 +0530 Subject: [PATCH 1913/2900] mmc: core: Update the ext-csd.rev check for eMMC5.1 With the new eMMC5.1 spec, there is a new EXT_CSD register with the revision number(EXT_CSD_REV) 7. This patch updates the check for ext-csd.rev number as 7. Signed-off-by: Alim Akhtar Signed-off-by: Yuvaraj Kumar C D Reviewed-by: Doug Anderson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 3a69b947130b..913260990829 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -293,7 +293,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; - if (card->ext_csd.rev > 6) { + if (card->ext_csd.rev > 7) { pr_err("%s: unrecognised EXT_CSD revision %d\n", mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; -- GitLab From dcac5fe3cfad106ba5369bc0f6bbcf111e21ddc6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 27 Jun 2013 10:49:16 -0400 Subject: [PATCH 1914/2900] mmc: mxs-mmc: Let device core handle pinctrl Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for handling pinctrl. So remove devm_pinctrl_get_select_default() from the driver. Signed-off-by: Fabio Estevam Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index c26280469b05..f38d75f46f78 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -580,7 +579,6 @@ static int mxs_mmc_probe(struct platform_device *pdev) struct mxs_mmc_host *host; struct mmc_host *mmc; struct resource *iores; - struct pinctrl *pinctrl; int ret = 0, irq_err; struct regulator *reg_vmmc; enum of_gpio_flags flags; @@ -620,12 +618,6 @@ static int mxs_mmc_probe(struct platform_device *pdev) } } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto out_mmc_free; - } - ssp->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(ssp->clk)) { ret = PTR_ERR(ssp->clk); -- GitLab From 3f7eec62ecb7e30bd2f7e0fc4432d0d08a1aae46 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 27 May 2013 13:47:57 +0900 Subject: [PATCH 1915/2900] mmc: dw_mmc: change the macro name from DTO to DRTO At Interrupt status register, Bit9 is Data Read Timeout. But we used macro name as the DTO. It could be confused with the Data Transfer Over(DTO)-Bit[3]. It's clearly that is changed the DRTO instead of DTO. Signed-off-by: Jaehoon Chung Reviewed-by: James Hogan Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc.c | 4 ++-- drivers/mmc/host/dw_mmc.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b10e5e12b2ae..7dca5e92dcb4 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -39,7 +39,7 @@ #include "dw_mmc.h" /* Common flag combinations */ -#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \ +#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \ SDMMC_INT_HTO | SDMMC_INT_SBE | \ SDMMC_INT_EBE) #define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ @@ -1093,7 +1093,7 @@ static void dw_mci_tasklet_func(unsigned long priv) status = host->data_status; if (status & DW_MCI_DATA_ERROR_FLAGS) { - if (status & SDMMC_INT_DTO) { + if (status & SDMMC_INT_DRTO) { data->error = -ETIMEDOUT; } else if (status & SDMMC_INT_DCRC) { data->error = -EILSEQ; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0b74189e7ee7..2f52c87bbce9 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -98,7 +98,7 @@ #define SDMMC_INT_HLE BIT(12) #define SDMMC_INT_FRUN BIT(11) #define SDMMC_INT_HTO BIT(10) -#define SDMMC_INT_DTO BIT(9) +#define SDMMC_INT_DRTO BIT(9) #define SDMMC_INT_RTO BIT(8) #define SDMMC_INT_DCRC BIT(7) #define SDMMC_INT_RCRC BIT(6) -- GitLab From 5a0e8074660444010fee40eebcd57aaaf8d44662 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 28 May 2013 13:26:25 +0800 Subject: [PATCH 1916/2900] mmc: sdhci-acpi: fix error return code in sdhci_acpi_add_own_cd() Fix to return a negative error code in the gpio_to_irq() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Reviewed-by: Jingoo Han Acked-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index a51e603acbc5..08a85ec33224 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -189,8 +189,10 @@ static int sdhci_acpi_add_own_cd(struct device *dev, int gpio, goto out; irq = gpio_to_irq(gpio); - if (irq < 0) + if (irq < 0) { + err = irq; goto out_free; + } flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; err = devm_request_irq(dev, irq, sdhci_acpi_sd_cd, flags, "sd_cd", mmc); -- GitLab From 7913ae7d10d82bf9d9af6be6c20281fceb695ec0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 28 May 2013 13:26:50 +0800 Subject: [PATCH 1917/2900] mmc: sh_mobile_sdhi: fix error return code in sh_mobile_sdhi_probe() Fix to return a negative error code instead of 0 when we cannot get IRQ source by platform_get_irq(), as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball --- drivers/mmc/host/sh_mobile_sdhi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index cc4c872cc924..a4316b34df1f 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -273,8 +273,10 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) } /* There must be at least one IRQ source */ - if (!i) + if (!i) { + ret = irq; goto eirq; + } } dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n", -- GitLab From 6e2c0f3ffbb54547edcf1dd92a120ff37988a4d8 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 3 Jun 2013 13:41:03 +0900 Subject: [PATCH 1918/2900] mmc: host: use platform_{get,set}_drvdata() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Acked-by: Michał Mirosław Signed-off-by: Chris Ball --- drivers/mmc/host/cb710-mmc.c | 2 +- drivers/mmc/host/cb710-mmc.h | 2 +- drivers/mmc/host/sh_mobile_sdhi.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 777ca2046b27..9d6e2b844404 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -703,7 +703,7 @@ static int cb710_mmc_init(struct platform_device *pdev) if (!mmc) return -ENOMEM; - dev_set_drvdata(&pdev->dev, mmc); + platform_set_drvdata(pdev, mmc); /* harmless (maybe) magic */ pci_read_config_dword(chip->pdev, 0x48, &val); diff --git a/drivers/mmc/host/cb710-mmc.h b/drivers/mmc/host/cb710-mmc.h index e845c776bdd7..8984ec878fc9 100644 --- a/drivers/mmc/host/cb710-mmc.h +++ b/drivers/mmc/host/cb710-mmc.h @@ -24,7 +24,7 @@ struct cb710_mmc_reader { static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot) { - return dev_get_drvdata(&slot->pdev.dev); + return platform_get_drvdata(&slot->pdev); } static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc) diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index a4316b34df1f..ebea749297c2 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -51,7 +51,7 @@ struct sh_mobile_sdhi { static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f) { - struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); + struct mmc_host *mmc = platform_get_drvdata(pdev); struct tmio_mmc_host *host = mmc_priv(mmc); struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); int ret = clk_enable(priv->clk); @@ -64,7 +64,7 @@ static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev) { - struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); + struct mmc_host *mmc = platform_get_drvdata(pdev); struct tmio_mmc_host *host = mmc_priv(mmc); struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data); clk_disable(priv->clk); @@ -119,7 +119,7 @@ static int sh_mobile_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) static void sh_mobile_sdhi_cd_wakeup(const struct platform_device *pdev) { - mmc_detect_change(dev_get_drvdata(&pdev->dev), msecs_to_jiffies(100)); + mmc_detect_change(platform_get_drvdata(pdev), msecs_to_jiffies(100)); } static const struct sh_mobile_sdhi_ops sdhi_ops = { -- GitLab From e2f6aac6a88138851f81372c5cecc9562aab9352 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 27 Jun 2013 11:17:25 -0400 Subject: [PATCH 1919/2900] mmc: sirf: fix sdhci_pltfm_init sequence Patch "mmc: sdhci: Add size for caller in init+register" changed the interface for sdhci_pltfm_init, while patch "mmc: sdhci-sirf: add mmc host sdhci-pltfm based driver for SiRF SoCs" added a new driver with the old interface. This changes the sirf driver to use the new interface, avoiding one warning, and simplifying the init sequence. Since we're here already, this also adds an error path for failed clk_prepare_enable. Signed-off-by: Arnd Bergmann Acked-by: Christian Daudt Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-sirf.c | 51 ++++++++++++++++------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index ccf12dd93616..62a4a835acc6 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -23,7 +23,7 @@ struct sdhci_sirf_priv { static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = pltfm_host->priv; + struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); return clk_get_rate(priv->clk); } @@ -45,40 +45,35 @@ static int sdhci_sirf_probe(struct platform_device *pdev) struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct sdhci_sirf_priv *priv; + struct clk *clk; + int gpio_cd; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_sirf_priv), - GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "unable to allocate private data"); - return -ENOMEM; - } - - priv->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(priv->clk)) { + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { dev_err(&pdev->dev, "unable to get clock"); - return PTR_ERR(priv->clk); + return PTR_ERR(clk); } - if (pdev->dev.of_node) { - priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node, - "cd-gpios", 0); - } else { - priv->gpio_cd = -EINVAL; - } + if (pdev->dev.of_node) + gpio_cd = of_get_named_gpio(pdev->dev.of_node, "cd-gpios", 0); + else + gpio_cd = -EINVAL; - host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata); - if (IS_ERR(host)) { - ret = PTR_ERR(host); - goto err_sdhci_pltfm_init; - } + host = sdhci_pltfm_init(pdev, &sdhci_sirf_pdata, sizeof(struct sdhci_sirf_priv)); + if (IS_ERR(host)) + return PTR_ERR(host); pltfm_host = sdhci_priv(host); - pltfm_host->priv = priv; + priv = sdhci_pltfm_priv(pltfm_host); + priv->clk = clk; + priv->gpio_cd = gpio_cd; sdhci_get_of_property(pdev); - clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(priv->clk); + if (ret) + goto err_clk_prepare; ret = sdhci_add_host(host); if (ret) @@ -103,8 +98,8 @@ static int sdhci_sirf_probe(struct platform_device *pdev) sdhci_remove_host(host, 0); err_sdhci_add: clk_disable_unprepare(priv->clk); +err_clk_prepare: sdhci_pltfm_free(pdev); -err_sdhci_pltfm_init: return ret; } @@ -112,7 +107,7 @@ static int sdhci_sirf_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = pltfm_host->priv; + struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); sdhci_pltfm_unregister(pdev); @@ -128,7 +123,7 @@ static int sdhci_sirf_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = pltfm_host->priv; + struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret; ret = sdhci_suspend_host(host); @@ -144,7 +139,7 @@ static int sdhci_sirf_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = pltfm_host->priv; + struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret; ret = clk_enable(priv->clk); -- GitLab From fdfa20c1631210d0ca218689204682ea80e170e3 Mon Sep 17 00:00:00 2001 From: Paul Taysom Date: Tue, 4 Jun 2013 14:42:40 -0700 Subject: [PATCH 1920/2900] mmc: reordered shutdown sequence in mmc_bld_remove_req We had a multi-partition SD-Card with two ext2 file systems. The partition table was getting overwritten by a race between the card removal and the unmount of the 2nd ext2 partition. What was observed: 1. Suspend/resume would call to remove the device. The clearing of the device information is done asynchronously. 2. A request is made to unmount the file system (this is called after the removal has started). 3. The remapping table was cleared by the asynchronous part of the device removal. 4. A write request to the super block (block 0 of the partition) was sent down and instead of being remapped to the partition offset, it was remapped to block 0 of the device which is where the partition table is located. 5. Write was queued and written resulting in the overwriting of the partition table with the ext2 super block. 6. The mmc_queue is cleaned up. The mmc card device driver used to access SD cards, was calling del_gendisk before calling mmc_cleanup-queue. The comment in the mmc_blk_remove_req code indicated that it expected del_gendisk to block all further requests from being queued but it doesn't. The mmc driver uses the presences of the mmc_queue to determine if the request should be queued. The fix was to clean up the mmc_queue before the rest of the the delete partition code is called. This prevents the overwriting of the partition table. However, the umount gets an error trying to write the super block. The umount should be issued before the device is removed but that is not always possible. The umount is still needed to cleanup other data structures. Addresses the problem described in http://crbug.com/240815 Signed-off-by: Paul Taysom Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c900d2818aa7..59a13fce774e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2185,6 +2185,14 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) struct mmc_card *card; if (md) { + /* + * Flush remaining requests and free queues. It + * is freeing the queue that stops new requests + * from being accepted. + */ + mmc_cleanup_queue(&md->queue); + if (md->flags & MMC_BLK_PACKED_CMD) + mmc_packed_clean(&md->queue); card = md->queue.card; if (md->disk->flags & GENHD_FL_UP) { device_remove_file(disk_to_dev(md->disk), &md->force_ro); @@ -2193,14 +2201,8 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock); - /* Stop new requests from getting into the queue */ del_gendisk(md->disk); } - - /* Then flush out any already in there */ - mmc_cleanup_queue(&md->queue); - if (md->flags & MMC_BLK_PACKED_CMD) - mmc_packed_clean(&md->queue); mmc_blk_put(md); } } -- GitLab From bcc8766696fe2023b498a4a5c19cf8d2193aa62e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Jun 2013 12:24:10 +0300 Subject: [PATCH 1921/2900] mmc: dw_mmc-pltfm: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Andy Shevchenko Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc-pltfm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 37873f101cdb..526abae74c74 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -25,7 +25,7 @@ #include "dw_mmc.h" int dw_mci_pltfm_register(struct platform_device *pdev, - const struct dw_mci_drv_data *drv_data) + const struct dw_mci_drv_data *drv_data) { struct dw_mci *host; struct resource *regs; @@ -35,10 +35,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev, if (!host) return -ENOMEM; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) - return -ENXIO; - host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) return host->irq; @@ -47,6 +43,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev, host->dev = &pdev->dev; host->irq_flags = 0; host->pdata = pdev->dev.platform_data; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs = devm_ioremap_resource(&pdev->dev, regs); if (IS_ERR(host->regs)) return PTR_ERR(host->regs); -- GitLab From dd369800202f1aeeb23b64fe9d336d67b202c3b2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Jun 2013 12:24:11 +0300 Subject: [PATCH 1922/2900] mmc: dw_mmc: eliminate useless usage of ret In few places usage of ret variable is not needed. This patch simplifies those pieces of code. Signed-off-by: Andy Shevchenko Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc-pci.c | 8 ++------ drivers/mmc/host/dw_mmc-pltfm.c | 17 +++-------------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index 083fcd29c9c6..c469ce624bb8 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c @@ -100,22 +100,18 @@ static void dw_mci_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int dw_mci_pci_suspend(struct device *dev) { - int ret; struct pci_dev *pdev = to_pci_dev(dev); struct dw_mci *host = pci_get_drvdata(pdev); - ret = dw_mci_suspend(host); - return ret; + return dw_mci_suspend(host); } static int dw_mci_pci_resume(struct device *dev) { - int ret; struct pci_dev *pdev = to_pci_dev(dev); struct dw_mci *host = pci_get_drvdata(pdev); - ret = dw_mci_resume(host); - return ret; + return dw_mci_resume(host); } #else #define dw_mci_pci_suspend NULL diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 526abae74c74..2721bd5839cb 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -56,8 +56,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev, } platform_set_drvdata(pdev, host); - ret = dw_mci_probe(host); - return ret; + return dw_mci_probe(host); } EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); @@ -81,26 +80,16 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); */ static int dw_mci_pltfm_suspend(struct device *dev) { - int ret; struct dw_mci *host = dev_get_drvdata(dev); - ret = dw_mci_suspend(host); - if (ret) - return ret; - - return 0; + return dw_mci_suspend(host); } static int dw_mci_pltfm_resume(struct device *dev) { - int ret; struct dw_mci *host = dev_get_drvdata(dev); - ret = dw_mci_resume(host); - if (ret) - return ret; - - return 0; + return dw_mci_resume(host); } #else #define dw_mci_pltfm_suspend NULL -- GitLab From 1395974142bde026da39020a15374a713edbbfb9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 5 Jun 2013 12:24:12 +0300 Subject: [PATCH 1923/2900] mmc: dw_mmc-pci: convert to use pcim_* and devm_* The PCI driver is getting simplier and tidier with pcim_* and devm_* functions in use. Signed-off-by: Andy Shevchenko Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc-pci.c | 50 +++++++++++------------------------ 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index c469ce624bb8..b456b0c35231 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c @@ -21,7 +21,6 @@ #include "dw_mmc.h" #define PCI_BAR_NO 2 -#define COMPLETE_BAR 0 #define SYNOPSYS_DW_MCI_VENDOR_ID 0x700 #define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107 /* Defining the Capabilities */ @@ -38,51 +37,37 @@ static struct dw_mci_board pci_board_data = { }; static int dw_mci_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *entries) + const struct pci_device_id *entries) { struct dw_mci *host; int ret; - ret = pci_enable_device(pdev); + ret = pcim_enable_device(pdev); if (ret) return ret; - if (pci_request_regions(pdev, "dw_mmc_pci")) { - ret = -ENODEV; - goto err_disable_dev; - } - host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); - if (!host) { - ret = -ENOMEM; - goto err_release; - } + host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); + if (!host) + return -ENOMEM; host->irq = pdev->irq; host->irq_flags = IRQF_SHARED; host->dev = &pdev->dev; host->pdata = &pci_board_data; - host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); - if (!host->regs) { - ret = -EIO; - goto err_unmap; - } + ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_NO, pci_name(pdev)); + if (ret) + return ret; + + host->regs = pcim_iomap_table(pdev)[0]; - pci_set_drvdata(pdev, host); ret = dw_mci_probe(host); if (ret) - goto err_probe_failed; - return ret; - -err_probe_failed: - pci_iounmap(pdev, host->regs); -err_unmap: - kfree(host); -err_release: - pci_release_regions(pdev); -err_disable_dev: - pci_disable_device(pdev); - return ret; + return ret; + + pci_set_drvdata(pdev, host); + + return 0; } static void dw_mci_pci_remove(struct pci_dev *pdev) @@ -90,11 +75,6 @@ static void dw_mci_pci_remove(struct pci_dev *pdev) struct dw_mci *host = pci_get_drvdata(pdev); dw_mci_remove(host); - pci_set_drvdata(pdev, NULL); - pci_release_regions(pdev); - pci_iounmap(pdev, host->regs); - kfree(host); - pci_disable_device(pdev); } #ifdef CONFIG_PM_SLEEP -- GitLab From 4d156d50b513116ba701b8d69d7fb870dd370481 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 9 Apr 2013 14:45:00 +0200 Subject: [PATCH 1924/2900] mmc: atmel-mci: remove include Header file not needed anymore as we have removed the calls to cpu_is_xxx() macro. Signed-off-by: Nicolas Ferre Acked-by: Ludovic Desroches Acked-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Chris Ball --- drivers/mmc/host/atmel-mci.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 4aa20531e5f2..bdb84da74952 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -40,8 +40,6 @@ #include #include -#include - #include "atmel-mci-regs.h" #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE) -- GitLab From a82e484e2480583b17be6253b985fa6f582ad20d Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Wed, 5 Jun 2013 14:13:08 +0300 Subject: [PATCH 1925/2900] mmc: card: fixing an false identification of SANITIZE command Inside the routine mmc_blk_ioctl_cmd() the sanitize command is identified according to the value of bits 16-23 of the argument. but what happens if a different command is sent, and only by chance, bits 16-23 contain the value of SANITIZE command ? In that case a SANITIZE command will be falsely identified. In order to prevent such a case, the condition is expanded and now it also checks the opcode itself, and verifies that it is an MMC_SWITCH opcode. Signed-off-by: Yaniv Gardi Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 59a13fce774e..5411bf447369 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -542,7 +542,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_rel_host; } - if (MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) { + if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && + (cmd.opcode == MMC_SWITCH)) { err = ioctl_do_sanitize(card); if (err) -- GitLab From 8ba9580a8045b6d5fed66e13b77599f3d8a77fed Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 5 Jun 2013 15:13:25 +0200 Subject: [PATCH 1926/2900] mmc: sdhci-esdhc: calculate sdclk divider from controller clock The SDCLK is divided down from the host controller clock. Host controller clock may be different from the maximum SDCLK, so get it from the platform, instead of just using the max SDCLK. Signed-off-by: Lucas Stach Acked-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 10 +++++++++- drivers/mmc/host/sdhci-esdhc.h | 9 +++++---- drivers/mmc/host/sdhci-of-esdhc.c | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 98f46704baa6..eb1310ca021e 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -391,6 +391,14 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) return clk_get_rate(pltfm_host->clk) / 256 / 16; } +static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, + unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk)); +} + static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -438,7 +446,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .write_l = esdhc_writel_le, .write_w = esdhc_writew_le, .write_b = esdhc_writeb_le, - .set_clock = esdhc_set_clock, + .set_clock = esdhc_pltfm_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_min_clock = esdhc_pltfm_get_min_clock, .get_ro = esdhc_pltfm_get_ro, diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index d25f9ab9a54d..6f16406c37cd 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -42,7 +42,8 @@ #define ESDHC_HOST_CONTROL_RES 0x05 -static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) +static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock, + unsigned int host_clock) { int pre_div = 2; int div = 1; @@ -56,14 +57,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) + while (host_clock / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; - while (host->max_clk / pre_div / div > clock && div < 16) + while (host_clock / pre_div / div > clock && div < 16) div++; dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", - clock, host->max_clk / pre_div / div); + clock, host_clock / pre_div / div); pre_div >>= 1; div--; diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 37e668f5b992..2b7369729f91 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -200,7 +200,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) } /* Set the clock */ - esdhc_set_clock(host, clock); + esdhc_set_clock(host, clock, host->max_clk); } #ifdef CONFIG_PM -- GitLab From 0ddf03c95bbb4f4ed57281fa7b781472950df749 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 5 Jun 2013 15:13:26 +0200 Subject: [PATCH 1927/2900] mmc: esdhc-imx: parse max-frequency from devicetree In order to make it possible to reduce the SD bus frequency, parse the optional "max-frequency" attribute as documented in devicetree/bindings/mmc/mmc.txt Signed-off-by: Lucas Stach Acked-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc-imx.c | 18 +++++++++++++++++- include/linux/platform_data/mmc-esdhc-imx.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index eb1310ca021e..1dd5ba858754 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -384,6 +384,20 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) } } +static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + struct esdhc_platform_data *boarddata = &imx_data->boarddata; + + u32 f_host = clk_get_rate(pltfm_host->clk); + + if (boarddata->f_max && (boarddata->f_max < f_host)) + return boarddata->f_max; + else + return f_host; +} + static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -447,7 +461,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .write_w = esdhc_writew_le, .write_b = esdhc_writeb_le, .set_clock = esdhc_pltfm_set_clock, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_max_clock = esdhc_pltfm_get_max_clock, .get_min_clock = esdhc_pltfm_get_min_clock, .get_ro = esdhc_pltfm_get_ro, .platform_bus_width = esdhc_pltfm_bus_width, @@ -490,6 +504,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, of_property_read_u32(np, "bus-width", &boarddata->max_bus_width); + of_property_read_u32(np, "max-frequency", &boarddata->f_max); + return 0; } #else diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h index b4a0521ce411..d44912d81578 100644 --- a/include/linux/platform_data/mmc-esdhc-imx.h +++ b/include/linux/platform_data/mmc-esdhc-imx.h @@ -40,5 +40,6 @@ struct esdhc_platform_data { enum wp_types wp_type; enum cd_types cd_type; int max_bus_width; + unsigned int f_max; }; #endif /* __ASM_ARCH_IMX_ESDHC_H */ -- GitLab From 870556a3dfb16d004f8e09dd59a1eddc727fcf0c Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 7 Jun 2013 10:28:29 -0700 Subject: [PATCH 1928/2900] mmc: dw_mmc: Handle late vmmc regulators with EPROBE_DEFER It is possible to specify a regulator that should be turned on when dw_mmc is probed. At the moment dw_mmc will fail to use the regulator properly if the regulator probes after dw_mmc. Fix this problem by honoring EPROBE_DEFER. At the same time move the regulator code out of the slot init code. We only specify one regulator for the whole device and other parts of the code (like suspend/resume) assume that the regulator has only been enabled once. Signed-off-by: Doug Anderson Signed-off-by: Chris Ball --- .../bindings/mmc/synopsis-dw-mshc.txt | 4 +++ drivers/mmc/host/dw_mmc.c | 34 +++++++++++-------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt index 726fd2122a13..d5cc94ecd60e 100644 --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt @@ -55,6 +55,9 @@ Optional properties: * broken-cd: as documented in mmc core bindings. +* vmmc-supply: The phandle to the regulator to use for vmmc. If this is + specified we'll defer probe until we can find this regulator. + Aliases: - All the MSHC controller nodes should be represented in the aliases node using @@ -79,6 +82,7 @@ board specific portions as listed below. broken-cd; fifo-depth = <0x80>; card-detect-delay = <200>; + vmmc-supply = <&buck8>; slot@0 { reg = <0>; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7dca5e92dcb4..957f5d7ea426 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1991,19 +1991,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) #endif /* CONFIG_MMC_DW_IDMAC */ } - host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); - if (IS_ERR(host->vmmc)) { - pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); - host->vmmc = NULL; - } else { - ret = regulator_enable(host->vmmc); - if (ret) { - dev_err(host->dev, - "failed to enable regulator: %d\n", ret); - goto err_setup_bus; - } - } - if (dw_mci_get_cd(mmc)) set_bit(DW_MMC_CARD_PRESENT, &slot->flags); else @@ -2235,11 +2222,29 @@ int dw_mci_probe(struct dw_mci *host) } } + host->vmmc = devm_regulator_get(host->dev, "vmmc"); + if (IS_ERR(host->vmmc)) { + ret = PTR_ERR(host->vmmc); + if (ret == -EPROBE_DEFER) + goto err_clk_ciu; + + dev_info(host->dev, "no vmmc regulator found: %d\n", ret); + host->vmmc = NULL; + } else { + ret = regulator_enable(host->vmmc); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(host->dev, + "regulator_enable fail: %d\n", ret); + goto err_clk_ciu; + } + } + if (!host->bus_hz) { dev_err(host->dev, "Platform data must supply bus speed\n"); ret = -ENODEV; - goto err_clk_ciu; + goto err_regulator; } host->quirks = host->pdata->quirks; @@ -2386,6 +2391,7 @@ int dw_mci_probe(struct dw_mci *host) if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); +err_regulator: if (host->vmmc) regulator_disable(host->vmmc); -- GitLab From 3c6d89ea34605df0f4fe6e6dac5abcb781f82f53 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 7 Jun 2013 10:28:30 -0700 Subject: [PATCH 1929/2900] mmc: dw_mmc: Add the ability to set the ciu clock frequency As of now we rely on code outside of the driver to set the ciu clock frequency. There's no reason to do that. Add support for setting up the clock in the driver during probe. Signed-off-by: Doug Anderson Acked-by: Jaehoon Chung Signed-off-by: Chris Ball --- .../bindings/mmc/synopsis-dw-mshc.txt | 16 ++++++++++++++++ drivers/mmc/host/dw_mmc.c | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt index d5cc94ecd60e..dd31b00f0866 100644 --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt @@ -39,6 +39,19 @@ Required Properties: Optional properties: +* clocks: from common clock binding: handle to biu and ciu clocks for the + bus interface unit clock and the card interface unit clock. + +* clock-names: from common clock binding: Shall be "biu" and "ciu". + If the biu clock is missing we'll simply skip enabling it. If the + ciu clock is missing we'll just assume that the clock is running at + clock-frequency. It is an error to omit both the ciu clock and the + clock-frequency. + +* clock-frequency: should be the frequency (in Hz) of the ciu clock. If this + is specified and the ciu clock is specified then we'll try to set the ciu + clock to this at probe time. + * num-slots: specifies the number of slots supported by the controller. The number of physical slots actually used could be equal or less than the value specified by num-slots. If this property is not specified, the value @@ -70,6 +83,8 @@ board specific portions as listed below. dwmmc0@12200000 { compatible = "snps,dw-mshc"; + clocks = <&clock 351>, <&clock 132>; + clock-names = "biu", "ciu"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; #address-cells = <1>; @@ -77,6 +92,7 @@ board specific portions as listed below. }; dwmmc0@12200000 { + clock-frequency = <400000000>; num-slots = <1>; supports-highspeed; broken-cd; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 957f5d7ea426..ee5f1676f14e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2117,6 +2117,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) struct device_node *np = dev->of_node; const struct dw_mci_drv_data *drv_data = host->drv_data; int idx, ret; + u32 clock_frequency; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -2143,6 +2144,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); + if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) + pdata->bus_hz = clock_frequency; + if (drv_data && drv_data->parse_dt) { ret = drv_data->parse_dt(host); if (ret) @@ -2200,18 +2204,23 @@ int dw_mci_probe(struct dw_mci *host) host->ciu_clk = devm_clk_get(host->dev, "ciu"); if (IS_ERR(host->ciu_clk)) { dev_dbg(host->dev, "ciu clock not available\n"); + host->bus_hz = host->pdata->bus_hz; } else { ret = clk_prepare_enable(host->ciu_clk); if (ret) { dev_err(host->dev, "failed to enable ciu clock\n"); goto err_clk_biu; } - } - if (IS_ERR(host->ciu_clk)) - host->bus_hz = host->pdata->bus_hz; - else + if (host->pdata->bus_hz) { + ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); + if (ret) + dev_warn(host->dev, + "Unable to set bus rate to %ul\n", + host->pdata->bus_hz); + } host->bus_hz = clk_get_rate(host->ciu_clk); + } if (drv_data && drv_data->setup_clock) { ret = drv_data->setup_clock(host); -- GitLab From 9668d765eab78d58e656177db2acb57c249b9c01 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 9 Jun 2013 19:49:24 +0800 Subject: [PATCH 1930/2900] mmc: sdhci: improve card removal check in sdhci_card_event() The following error randomly appears on an imx6q board where gpio is used to implement card-detection when mounting EXT4 rootfs during boot. mmc1: Card removed during transfer! mmc1: Resetting controller. mmcblk0: unknown error -123 sending read/write command, card status 0x900 end_request: I/O error, dev mmcblk0, sector 106744 EXT4-fs error (device mmcblk0p2): ext4_find_entry:1312: inode #5011: comm swapper/0: reading directory lblock 0 It turns out that the error message comes from the card removal check in function sdhci_card_event(). While we have a well implemented function sdhci_do_get_cd() handling all the possible cases of CD, the current code only checks controller internal CD case. That causes problem for other CD cases like gpio on above imx6q board. Improve the check by using sdhci_do_get_cd() to cover all possible CD cases, so that above error on the imx6q board gets fixed. Signed-off-by: Shawn Guo Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c81c2a289dbd..eadb3adf446e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2066,8 +2066,7 @@ static void sdhci_card_event(struct mmc_host *mmc) spin_lock_irqsave(&host->lock, flags); /* Check host->mrq first in case we are runtime suspended */ - if (host->mrq && - !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { + if (host->mrq && !sdhci_do_get_cd(host)) { pr_err("%s: Card removed during transfer!\n", mmc_hostname(host->mmc)); pr_err("%s: Resetting controller.\n", -- GitLab From 331947932dfded1e458af9eee43aec918d7a5dad Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 9 Jun 2013 21:10:01 +0200 Subject: [PATCH 1931/2900] mmc: jz4740: Remove duplicated code. Signed-off-by: Paul Cercueil Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index c4f3872d06a7..b31359da4a75 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -560,11 +560,6 @@ static irqreturn_t jz_mmc_irq(int irq, void *devid) if (cmd->data) cmd->data->error = -EIO; cmd->error = -EIO; - } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | - JZ_MMC_STATUS_CRC_WRITE_ERROR)) { - if (cmd->data) - cmd->data->error = -EIO; - cmd->error = -EIO; } jz4740_mmc_set_irq_enabled(host, irq_reg, false); -- GitLab From 8a489aa10cf84e54de812bd964f3520504460b94 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 9 Jun 2013 21:10:02 +0200 Subject: [PATCH 1932/2900] mmc: jz4740: Fix handling of read errors. For no reason, the code handling write errors was implemented while the code handling read errors was missing. Signed-off-by: Paul Cercueil Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b31359da4a75..3f86592e97a2 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -231,6 +231,14 @@ static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, host->req->cmd->error = -EIO; data->error = -EIO; } + } else if (status & JZ_MMC_STATUS_READ_ERROR_MASK) { + if (status & (JZ_MMC_STATUS_TIMEOUT_READ)) { + host->req->cmd->error = -ETIMEDOUT; + data->error = -ETIMEDOUT; + } else { + host->req->cmd->error = -EIO; + data->error = -EIO; + } } } -- GitLab From 5d5c0350fc9533a1af3a43ee2331fec412679fcf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Jun 2013 21:10:03 +0200 Subject: [PATCH 1933/2900] mmc: jz4740: Use SIMPLE_DEV_PM_OPS It's a bit shorter than open-conding it. While we are at it also make jz4740_mmc_pm_ops static. Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 3f86592e97a2..c97ef6dd5fb6 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -967,7 +967,7 @@ static int jz4740_mmc_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int jz4740_mmc_suspend(struct device *dev) { @@ -991,13 +991,8 @@ static int jz4740_mmc_resume(struct device *dev) return 0; } -const struct dev_pm_ops jz4740_mmc_pm_ops = { - .suspend = jz4740_mmc_suspend, - .resume = jz4740_mmc_resume, - .poweroff = jz4740_mmc_suspend, - .restore = jz4740_mmc_resume, -}; - +static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, + jz4740_mmc_resume); #define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) #else #define JZ4740_MMC_PM_OPS NULL -- GitLab From 58e300af8192d2f33d0e2dd47c9e31fb5d50c417 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Jun 2013 21:10:04 +0200 Subject: [PATCH 1934/2900] mmc: jz4740: Use slot-gpio helpers Use the slot-gpio helpers to handle the write protect and card detect GPIO pins instead of re-implementing the same functionality in the driver. Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 113 +++++++--------------------------- 1 file changed, 23 insertions(+), 90 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index c97ef6dd5fb6..e904e6e57e9b 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -653,35 +654,6 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static int jz4740_mmc_get_ro(struct mmc_host *mmc) -{ - struct jz4740_mmc_host *host = mmc_priv(mmc); - if (!gpio_is_valid(host->pdata->gpio_read_only)) - return -ENOSYS; - - return gpio_get_value(host->pdata->gpio_read_only) ^ - host->pdata->read_only_active_low; -} - -static int jz4740_mmc_get_cd(struct mmc_host *mmc) -{ - struct jz4740_mmc_host *host = mmc_priv(mmc); - if (!gpio_is_valid(host->pdata->gpio_card_detect)) - return -ENOSYS; - - return gpio_get_value(host->pdata->gpio_card_detect) ^ - host->pdata->card_detect_active_low; -} - -static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) -{ - struct jz4740_mmc_host *host = devid; - - mmc_detect_change(host->mmc, HZ / 2); - - return IRQ_HANDLED; -} - static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct jz4740_mmc_host *host = mmc_priv(mmc); @@ -691,8 +663,8 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) static const struct mmc_host_ops jz4740_mmc_ops = { .request = jz4740_mmc_request, .set_ios = jz4740_mmc_set_ios, - .get_ro = jz4740_mmc_get_ro, - .get_cd = jz4740_mmc_get_cd, + .get_ro = mmc_gpio_get_ro, + .get_cd = mmc_gpio_get_cd, .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, }; @@ -727,58 +699,34 @@ static int jz4740_mmc_request_gpio(struct device *dev, int gpio, return 0; } -static int jz4740_mmc_request_gpios(struct platform_device *pdev) +static int jz4740_mmc_request_gpios(struct mmc_host *mmc, + struct platform_device *pdev) { - int ret; struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + int ret = 0; if (!pdata) return 0; - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, - "MMC detect change", false, 0); - if (ret) - goto err; - - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, - "MMC read only", false, 0); - if (ret) - goto err_free_gpio_card_detect; + if (!pdata->card_detect_active_low) + mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; + if (!pdata->read_only_active_low) + mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, - "MMC read only", true, pdata->power_active_low); - if (ret) - goto err_free_gpio_read_only; - - return 0; - -err_free_gpio_read_only: - if (gpio_is_valid(pdata->gpio_read_only)) - gpio_free(pdata->gpio_read_only); -err_free_gpio_card_detect: - if (gpio_is_valid(pdata->gpio_card_detect)) - gpio_free(pdata->gpio_card_detect); -err: - return ret; -} - -static int jz4740_mmc_request_cd_irq(struct platform_device *pdev, - struct jz4740_mmc_host *host) -{ - struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; - - if (!gpio_is_valid(pdata->gpio_card_detect)) - return 0; + if (gpio_is_valid(pdata->gpio_card_detect)) { + ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect); + if (ret) + return ret; + } - host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); - if (host->card_detect_irq < 0) { - dev_warn(&pdev->dev, "Failed to get card detect irq\n"); - return 0; + if (gpio_is_valid(pdata->gpio_read_only)) { + ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only); + if (ret) + return ret; } - return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "MMC card detect", host); + return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, + "MMC read only", true, pdata->power_active_low); } static void jz4740_mmc_free_gpios(struct platform_device *pdev) @@ -790,10 +738,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev) if (gpio_is_valid(pdata->gpio_power)) gpio_free(pdata->gpio_power); - if (gpio_is_valid(pdata->gpio_read_only)) - gpio_free(pdata->gpio_read_only); - if (gpio_is_valid(pdata->gpio_card_detect)) - gpio_free(pdata->gpio_card_detect); } static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) @@ -865,7 +809,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) goto err_iounmap; } - ret = jz4740_mmc_request_gpios(pdev); + ret = jz4740_mmc_request_gpios(mmc, pdev); if (ret) goto err_gpio_bulk_free; @@ -888,17 +832,11 @@ static int jz4740_mmc_probe(struct platform_device* pdev) spin_lock_init(&host->lock); host->irq_mask = 0xffff; - ret = jz4740_mmc_request_cd_irq(pdev, host); - if (ret) { - dev_err(&pdev->dev, "Failed to request card detect irq\n"); - goto err_free_gpios; - } - ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, dev_name(&pdev->dev), host); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); - goto err_free_card_detect_irq; + goto err_free_gpios; } jz4740_mmc_reset(host); @@ -921,9 +859,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) err_free_irq: free_irq(host->irq, host); -err_free_card_detect_irq: - if (host->card_detect_irq >= 0) - free_irq(host->card_detect_irq, host); err_free_gpios: jz4740_mmc_free_gpios(pdev); err_gpio_bulk_free: @@ -951,8 +886,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) mmc_remove_host(host->mmc); free_irq(host->irq, host); - if (host->card_detect_irq >= 0) - free_irq(host->card_detect_irq, host); jz4740_mmc_free_gpios(pdev); jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); -- GitLab From 017d84bd45d1d2e584d01f3875aacbfa481aa95a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Jun 2013 21:10:05 +0200 Subject: [PATCH 1935/2900] mmc: jz4740: Use managed resources Use managed resources for the mmio memory region and the clock. Makes the code a bit shorter. Signed-off-by: Lars-Peter Clausen Signed-off-by: Chris Ball --- drivers/mmc/host/jz4740_mmc.c | 37 ++++++----------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index e904e6e57e9b..0308c9f1cf52 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -121,7 +121,6 @@ struct jz4740_mmc_host { int irq; int card_detect_irq; - struct resource *mem; void __iomem *base; struct mmc_request *req; struct mmc_command *cmd; @@ -755,6 +754,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) struct mmc_host *mmc; struct jz4740_mmc_host *host; struct jz4740_mmc_platform_data *pdata; + struct resource *res; pdata = pdev->dev.platform_data; @@ -774,39 +774,25 @@ static int jz4740_mmc_probe(struct platform_device* pdev) goto err_free_host; } - host->clk = clk_get(&pdev->dev, "mmc"); + host->clk = devm_clk_get(&pdev->dev, "mmc"); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); dev_err(&pdev->dev, "Failed to get mmc clock\n"); goto err_free_host; } - host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!host->mem) { - ret = -ENOENT; - dev_err(&pdev->dev, "Failed to get base platform memory\n"); - goto err_clk_put; - } - - host->mem = request_mem_region(host->mem->start, - resource_size(host->mem), pdev->name); - if (!host->mem) { - ret = -EBUSY; - dev_err(&pdev->dev, "Failed to request base memory region\n"); - goto err_clk_put; - } - - host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + host->base = devm_ioremap_resource(&pdev->dev, res); if (!host->base) { ret = -EBUSY; dev_err(&pdev->dev, "Failed to ioremap base memory\n"); - goto err_release_mem_region; + goto err_free_host; } ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); if (ret) { dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); - goto err_iounmap; + goto err_free_host; } ret = jz4740_mmc_request_gpios(mmc, pdev); @@ -863,12 +849,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) jz4740_mmc_free_gpios(pdev); err_gpio_bulk_free: jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); -err_iounmap: - iounmap(host->base); -err_release_mem_region: - release_mem_region(host->mem->start, resource_size(host->mem)); -err_clk_put: - clk_put(host->clk); err_free_host: mmc_free_host(mmc); @@ -890,11 +870,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) jz4740_mmc_free_gpios(pdev); jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); - iounmap(host->base); - release_mem_region(host->mem->start, resource_size(host->mem)); - - clk_put(host->clk); - mmc_free_host(host->mmc); return 0; -- GitLab From 58a8a4a1a5da4694a3a069de5e0a8c15995e7b5f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:36 +0200 Subject: [PATCH 1936/2900] mmc: core: Remove unnecessary check for the remove callback For every bus_ops type the .remove callback always exist, thus there are no need to check the existence of it, before we decide to call it. Signed-off-by: Ulf Hansson Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e9a104b9e4d3..d2ee2829b313 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2483,9 +2483,7 @@ void mmc_stop_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { /* Calling bus_ops->remove() with a claimed host can deadlock */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - + host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); @@ -2638,8 +2636,7 @@ int mmc_suspend_host(struct mmc_host *host) * bus_ops->remove() with a claimed host can * deadlock.) */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); + host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); @@ -2722,9 +2719,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, break; /* Calling bus_ops->remove() with a claimed host can deadlock */ - if (host->bus_ops->remove) - host->bus_ops->remove(host); - + host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); -- GitLab From 810caddba42a54fe5db4e2664757a9a334ba359c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:37 +0200 Subject: [PATCH 1937/2900] mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE This patch moves the validation for all the suspend prerequisites to be done at SUSPEND_PREPARE notification. Previously in the SDIO case parts of the validation was done from mmc_suspend_host. This patch invents a new pre_suspend bus_ops callback and implements it for SDIO. Returning an error code from it, will mean at SUSPEND_PREPARE notification, the card will be removed before proceeding with the suspend sequence. Signed-off-by: Ulf Hansson Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 25 ++++++++----------------- drivers/mmc/core/core.h | 1 + drivers/mmc/core/sdio.c | 27 +++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d2ee2829b313..7a8a42d3a039 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2628,22 +2628,6 @@ int mmc_suspend_host(struct mmc_host *host) if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); - - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. (Calling - * bus_ops->remove() with a claimed host can - * deadlock.) - */ - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_power_off(host); - mmc_release_host(host); - host->pm_flags = 0; - err = 0; - } } mmc_bus_put(host); @@ -2706,6 +2690,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, struct mmc_host *host = container_of( notify_block, struct mmc_host, pm_notify); unsigned long flags; + int err = 0; switch (mode) { case PM_HIBERNATION_PREPARE: @@ -2715,7 +2700,13 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); - if (!host->bus_ops || host->bus_ops->suspend) + if (!host->bus_ops) + break; + + /* Validate prerequisites for suspend */ + if (host->bus_ops->pre_suspend) + err = host->bus_ops->pre_suspend(host); + if (!err && host->bus_ops->suspend) break; /* Calling bus_ops->remove() with a claimed host can deadlock */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 52a3650307af..79f37cfc373b 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -18,6 +18,7 @@ struct mmc_bus_ops { void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); + int (*pre_suspend)(struct mmc_host *); int (*suspend)(struct mmc_host *); int (*resume)(struct mmc_host *); int (*runtime_suspend)(struct mmc_host *); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 1fbbd1bc55ec..be8cca8d3024 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -910,11 +910,11 @@ static void mmc_sdio_detect(struct mmc_host *host) } /* - * SDIO suspend. We need to suspend all functions separately. + * SDIO pre_suspend. We need to suspend all functions separately. * Therefore all registered functions must have drivers with suspend * and resume methods. Failing that we simply remove the whole card. */ -static int mmc_sdio_suspend(struct mmc_host *host) +static int mmc_sdio_pre_suspend(struct mmc_host *host) { int i, err = 0; @@ -925,8 +925,26 @@ static int mmc_sdio_suspend(struct mmc_host *host) if (!pmops || !pmops->suspend || !pmops->resume) { /* force removal of entire card in that case */ err = -ENOSYS; - } else - err = pmops->suspend(&func->dev); + break; + } + } + } + + return err; +} + +/* + * SDIO suspend. Suspend all functions separately. + */ +static int mmc_sdio_suspend(struct mmc_host *host) +{ + int i, err = 0; + + for (i = 0; i < host->card->sdio_funcs; i++) { + struct sdio_func *func = host->card->sdio_func[i]; + if (func && sdio_func_present(func) && func->dev.driver) { + const struct dev_pm_ops *pmops = func->dev.driver->pm; + err = pmops->suspend(&func->dev); if (err) break; } @@ -1076,6 +1094,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, + .pre_suspend = mmc_sdio_pre_suspend, .suspend = mmc_sdio_suspend, .resume = mmc_sdio_resume, .runtime_suspend = mmc_sdio_runtime_suspend, -- GitLab From 74590263384e5d4601de7f0ee2790477578829ea Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:38 +0200 Subject: [PATCH 1938/2900] mmc: core: Push common suspend|resume code into each bus_ops By moving code from the mmc_suspend|resume_host down into each .suspend|resume bus_ops callback, we get a more flexible solution. Some nice side effects are that we get a better understanding of each bus_ops suspend|resume sequence and the common code don't have to take care of specific corner cases, especially for the SDIO case. Signed-off-by: Ulf Hansson Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/core/core.c | 31 +++---------------------------- drivers/mmc/core/mmc.c | 4 ++++ drivers/mmc/core/sd.c | 4 ++++ drivers/mmc/core/sdio.c | 21 +++++++++++++++++++++ 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 7a8a42d3a039..da3b9078ea65 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2621,9 +2621,6 @@ int mmc_suspend_host(struct mmc_host *host) { int err = 0; - cancel_delayed_work(&host->detect); - mmc_flush_scheduled_work(); - mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) @@ -2631,9 +2628,6 @@ int mmc_suspend_host(struct mmc_host *host) } mmc_bus_put(host); - if (!err && !mmc_card_keep_power(host)) - mmc_power_off(host); - return err; } EXPORT_SYMBOL(mmc_suspend_host); @@ -2644,39 +2638,20 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - int err = 0; + int err; mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { - if (!mmc_card_keep_power(host)) { - mmc_power_up(host); - mmc_select_voltage(host, host->ocr); - /* - * Tell runtime PM core we just powered up the card, - * since it still believes the card is powered off. - * Note that currently runtime PM is only enabled - * for SDIO cards that are MMC_CAP_POWER_OFF_CARD - */ - if (mmc_card_sdio(host->card) && - (host->caps & MMC_CAP_POWER_OFF_CARD)) { - pm_runtime_disable(&host->card->dev); - pm_runtime_set_active(&host->card->dev); - pm_runtime_enable(&host->card->dev); - } - } BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); - if (err) { + if (err) pr_warning("%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); - err = 0; - } } - host->pm_flags &= ~MMC_PM_KEEP_POWER; mmc_bus_put(host); - return err; + return 0; } EXPORT_SYMBOL(mmc_resume_host); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 913260990829..c8c7135c84b0 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1494,6 +1494,8 @@ static int mmc_suspend(struct mmc_host *host) err = mmc_deselect_cards(host); host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); + if (!err) + mmc_power_off(host); out: mmc_release_host(host); return err; @@ -1513,6 +1515,8 @@ static int mmc_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); + mmc_power_up(host); + mmc_select_voltage(host, host->ocr); err = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index aeaae7c3b22b..cacef27b00d1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1075,6 +1075,8 @@ static int mmc_sd_suspend(struct mmc_host *host) if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); host->card->state &= ~MMC_STATE_HIGHSPEED; + if (!err) + mmc_power_off(host); mmc_release_host(host); return err; @@ -1094,6 +1096,8 @@ static int mmc_sd_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); + mmc_power_up(host); + mmc_select_voltage(host, host->ocr); err = mmc_sd_init_card(host, host->ocr, host->card); mmc_release_host(host); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index be8cca8d3024..80d89cff7306 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -963,6 +963,9 @@ static int mmc_sdio_suspend(struct mmc_host *host) mmc_release_host(host); } + if (!err && !mmc_card_keep_power(host)) + mmc_power_off(host); + return err; } @@ -976,6 +979,23 @@ static int mmc_sdio_resume(struct mmc_host *host) /* Basic card reinitialization. */ mmc_claim_host(host); + /* Restore power if needed */ + if (!mmc_card_keep_power(host)) { + mmc_power_up(host); + mmc_select_voltage(host, host->ocr); + /* + * Tell runtime PM core we just powered up the card, + * since it still believes the card is powered off. + * Note that currently runtime PM is only enabled + * for SDIO cards that are MMC_CAP_POWER_OFF_CARD + */ + if (host->caps & MMC_CAP_POWER_OFF_CARD) { + pm_runtime_disable(&host->card->dev); + pm_runtime_set_active(&host->card->dev); + pm_runtime_enable(&host->card->dev); + } + } + /* No need to reinitialize powered-resumed nonremovable cards */ if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { sdio_reset(host); @@ -1013,6 +1033,7 @@ static int mmc_sdio_resume(struct mmc_host *host) } } + host->pm_flags &= ~MMC_PM_KEEP_POWER; return err; } -- GitLab From 986892ca78eeddd9d6b629050fea432979ddd321 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:39 +0200 Subject: [PATCH 1939/2900] mmc: core: Initiate suspend|resume from mmc bus instead of mmc host The host should be responsible to suspend|resume the host and not the card. This patch changes this behaviour, by moving the responsiblity to the mmc bus instead which already holds the card device. The exported functions mmc_suspend|resume_host are now to be considered as depcrecated. Once all host drivers moves away from using them, we can remove them. As of now, a successful error code is always returned. Signed-off-by: Ulf Hansson Tested-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/core/bus.c | 19 ++++++++++++++++--- drivers/mmc/core/core.c | 26 +++----------------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index d9e8c2b7f4c5..3b7ca8ac0e61 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -127,10 +127,16 @@ static int mmc_bus_suspend(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); - int ret = 0; + struct mmc_host *host = card->host; + int ret; - if (dev->driver && drv->suspend) + if (dev->driver && drv->suspend) { ret = drv->suspend(card); + if (ret) + return ret; + } + + ret = host->bus_ops->suspend(host); return ret; } @@ -138,10 +144,17 @@ static int mmc_bus_resume(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); - int ret = 0; + struct mmc_host *host = card->host; + int ret; + + ret = host->bus_ops->resume(host); + if (ret) + pr_warn("%s: error %d during resume (card was removed?)\n", + mmc_hostname(host), ret); if (dev->driver && drv->resume) ret = drv->resume(card); + return ret; } #endif diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index da3b9078ea65..49a5bca418bd 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2619,16 +2619,8 @@ EXPORT_SYMBOL(mmc_cache_ctrl); */ int mmc_suspend_host(struct mmc_host *host) { - int err = 0; - - mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead) { - if (host->bus_ops->suspend) - err = host->bus_ops->suspend(host); - } - mmc_bus_put(host); - - return err; + /* This function is deprecated */ + return 0; } EXPORT_SYMBOL(mmc_suspend_host); @@ -2638,19 +2630,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - int err; - - mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead) { - BUG_ON(!host->bus_ops->resume); - err = host->bus_ops->resume(host); - if (err) - pr_warning("%s: error %d during resume " - "(card was removed?)\n", - mmc_hostname(host), err); - } - mmc_bus_put(host); - + /* This function is deprecated */ return 0; } EXPORT_SYMBOL(mmc_resume_host); -- GitLab From 7628774851751e55362ec7d9d57c9334e656a655 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:40 +0200 Subject: [PATCH 1940/2900] mmc: core: Handle card shutdown from mmc_bus Considering shutdown of the card, the responsibility to initate this sequence shall be driven from the mmc_bus. This patch enables the mmc_bus to handle this sequence properly. A new .shutdown callback is added in the mmc_driver struct which is used to shutdown the blk device. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 15 +++++++++++++-- drivers/mmc/card/mmc_test.c | 5 +++++ drivers/mmc/core/bus.c | 9 +++++++++ include/linux/mmc/card.h | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5411bf447369..cd0b7f4a1ff2 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2403,8 +2403,7 @@ static void mmc_blk_remove(struct mmc_card *card) mmc_set_drvdata(card, NULL); } -#ifdef CONFIG_PM -static int mmc_blk_suspend(struct mmc_card *card) +static int _mmc_blk_suspend(struct mmc_card *card) { struct mmc_blk_data *part_md; struct mmc_blk_data *md = mmc_get_drvdata(card); @@ -2419,6 +2418,17 @@ static int mmc_blk_suspend(struct mmc_card *card) return 0; } +static void mmc_blk_shutdown(struct mmc_card *card) +{ + _mmc_blk_suspend(card); +} + +#ifdef CONFIG_PM +static int mmc_blk_suspend(struct mmc_card *card) +{ + return _mmc_blk_suspend(card); +} + static int mmc_blk_resume(struct mmc_card *card) { struct mmc_blk_data *part_md; @@ -2451,6 +2461,7 @@ static struct mmc_driver mmc_driver = { .remove = mmc_blk_remove, .suspend = mmc_blk_suspend, .resume = mmc_blk_resume, + .shutdown = mmc_blk_shutdown, }; static int __init mmc_blk_init(void) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 759714ed6bee..a69df5216274 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -3025,12 +3025,17 @@ static void mmc_test_remove(struct mmc_card *card) mmc_test_free_dbgfs_file(card); } +static void mmc_test_shutdown(struct mmc_card *card) +{ +} + static struct mmc_driver mmc_driver = { .drv = { .name = "mmc_test", }, .probe = mmc_test_probe, .remove = mmc_test_remove, + .shutdown = mmc_test_shutdown, }; static int __init mmc_test_init(void) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 3b7ca8ac0e61..219bf4b1d97e 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -122,6 +122,14 @@ static int mmc_bus_remove(struct device *dev) return 0; } +static void mmc_bus_shutdown(struct device *dev) +{ + struct mmc_driver *drv = to_mmc_driver(dev->driver); + struct mmc_card *card = mmc_dev_to_card(dev); + + drv->shutdown(card); +} + #ifdef CONFIG_PM_SLEEP static int mmc_bus_suspend(struct device *dev) { @@ -205,6 +213,7 @@ static struct bus_type mmc_bus_type = { .uevent = mmc_bus_uevent, .probe = mmc_bus_probe, .remove = mmc_bus_remove, + .shutdown = mmc_bus_shutdown, .pm = &mmc_bus_pm_ops, }; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 6a98f32670b8..842de3e21e70 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -520,6 +520,7 @@ struct mmc_driver { void (*remove)(struct mmc_card *); int (*suspend)(struct mmc_card *); int (*resume)(struct mmc_card *); + void (*shutdown)(struct mmc_card *); }; extern int mmc_register_driver(struct mmc_driver *); -- GitLab From 6b086bde71243e2596f9d8e3c060119b84110d33 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:41 +0200 Subject: [PATCH 1941/2900] mmc: core: Extend shutdown sequence to handle bus operations By adding an optional .shutdown callback to the bus_ops struct we provide the possibility to let each bus type handle it's shutdown requirements. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/bus.c | 9 +++++++++ drivers/mmc/core/core.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 219bf4b1d97e..4c0decfffb53 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -126,8 +126,17 @@ static void mmc_bus_shutdown(struct device *dev) { struct mmc_driver *drv = to_mmc_driver(dev->driver); struct mmc_card *card = mmc_dev_to_card(dev); + struct mmc_host *host = card->host; + int ret; drv->shutdown(card); + + if (host->bus_ops->shutdown) { + ret = host->bus_ops->shutdown(host); + if (ret) + pr_warn("%s: error %d during shutdown\n", + mmc_hostname(host), ret); + } } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 79f37cfc373b..5345d156493e 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -26,6 +26,7 @@ struct mmc_bus_ops { int (*power_save)(struct mmc_host *); int (*power_restore)(struct mmc_host *); int (*alive)(struct mmc_host *); + int (*shutdown)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); -- GitLab From 5992e78697484d8f58b749f87a06f89f4ba40a47 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:42 +0200 Subject: [PATCH 1942/2900] mmc: core: Add shutdown callback for SD bus_ops For the SD .shutdown callback we re-use the SD suspend function since it performs the relevant actions. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/sd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cacef27b00d1..176d125f5b57 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1170,6 +1170,7 @@ static const struct mmc_bus_ops mmc_sd_ops = { .resume = NULL, .power_restore = mmc_sd_power_restore, .alive = mmc_sd_alive, + .shutdown = mmc_sd_suspend, }; static const struct mmc_bus_ops mmc_sd_ops_unsafe = { @@ -1181,6 +1182,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = { .resume = mmc_sd_resume, .power_restore = mmc_sd_power_restore, .alive = mmc_sd_alive, + .shutdown = mmc_sd_suspend, }; static void mmc_sd_attach_bus_ops(struct mmc_host *host) -- GitLab From 03d071fc8de4ad9b6e7374720ae81b7e928f6075 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:43 +0200 Subject: [PATCH 1943/2900] mmc: core: Handle both poweroff notification types for eMMC Depending on the context of the operation while powering down the card, either POWER_OFF_NOTIFY_SHORT or POWER_OFF_NOTIFY_LONG will be used. In suspend context a short timeout is preferred while a long timeout would be acceptable in a shutdown/hibernation context. We add a new parameter to the mmc_suspend function so we can provide an indication of what notification type to use. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c8c7135c84b0..ab34a39486ae 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1464,12 +1464,11 @@ static void mmc_detect(struct mmc_host *host) } } -/* - * Suspend callback from host. - */ -static int mmc_suspend(struct mmc_host *host) +static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; + unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT : + EXT_CSD_POWER_OFF_LONG; BUG_ON(!host); BUG_ON(!host->card); @@ -1487,7 +1486,7 @@ static int mmc_suspend(struct mmc_host *host) goto out; if (mmc_can_poweroff_notify(host->card)) - err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT); + err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) err = mmc_sleep(host); else if (!mmc_host_is_spi(host)) @@ -1501,6 +1500,14 @@ static int mmc_suspend(struct mmc_host *host) return err; } +/* + * Suspend callback from host. + */ +static int mmc_suspend(struct mmc_host *host) +{ + return _mmc_suspend(host, true); +} + /* * Resume callback from host. * -- GitLab From 486fdbbc1483504cde0314e33e47bc32e9d38186 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:44 +0200 Subject: [PATCH 1944/2900] mmc: core: Add shutdown callback for (e)MMC bus_ops The shutdown sequence of an (e)MMC is very similar to a suspend. We re-use the suspend function and tell it we are not in suspend context. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ab34a39486ae..f670c285613d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1508,6 +1508,14 @@ static int mmc_suspend(struct mmc_host *host) return _mmc_suspend(host, true); } +/* + * Shutdown callback + */ +static int mmc_shutdown(struct mmc_host *host) +{ + return _mmc_suspend(host, false); +} + /* * Resume callback from host. * @@ -1597,6 +1605,7 @@ static const struct mmc_bus_ops mmc_ops = { .resume = NULL, .power_restore = mmc_power_restore, .alive = mmc_alive, + .shutdown = mmc_shutdown, }; static const struct mmc_bus_ops mmc_ops_unsafe = { @@ -1608,6 +1617,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = { .runtime_resume = mmc_runtime_resume, .power_restore = mmc_power_restore, .alive = mmc_alive, + .shutdown = mmc_shutdown, }; static void mmc_attach_bus_ops(struct mmc_host *host) -- GitLab From 43235679341510f58a86eb75ab23cbae4bdc59b8 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:45 +0200 Subject: [PATCH 1945/2900] mmc: core: Enable power_off_notify for eMMC shutdown sequence In suspend mode it is important to save power. If the host is able to cut buth vcc and vccq, the MMC_CAP2_POWEROFF_NOTIFY shall be set. It will mean the card will be completely powered down at suspend and the power off notification cmd will be sent prior power down. It seems common not being able to cut both vcc and vccq for a host. In this situation we issue the sleep cmd in favor of the power off notification cmd, to save more power. While maintainng the above policy, we also want to make use of the power off notification in the shutdown sequence, even in the case were the host has not set MMC_CAP2_POWEROFF_NOTIFY, since we know vcc and vccq will regardless be cut. We accomplish this by always enabling the power off notification byte in the EXT_CSD and issue the power off notification when either MMC_CAP2_POWEROFF_NOTIFY is set or we are executing a shutdown. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f670c285613d..e2946a98a1fa 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1041,11 +1041,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } /* - * If the host supports the power_off_notify capability then - * set the notification byte in the ext_csd register of device + * Enable power_off_notification byte in the ext_csd register */ - if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && - (card->ext_csd.rev >= 6)) { + if (card->ext_csd.rev >= 6) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, @@ -1485,7 +1483,8 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (err) goto out; - if (mmc_can_poweroff_notify(host->card)) + if (mmc_can_poweroff_notify(host->card) && + ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) || !is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) err = mmc_sleep(host); -- GitLab From 53275c2136cc76b6ff26f8bec268c4bef9bab837 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:46 +0200 Subject: [PATCH 1946/2900] mmc: core: Invent MMC_CAP2_FULL_PWR_CYCLE MMC_CAP2_FULL_PWR_CYCLE shall be set by host drivers which are able to do a complete power cycle of the card. In the eMMC case that includes both vcc and vccq. This CAP is providing the protocol layer with important information, needed to take optimized decisions during card initialization and in the suspend/resume sequence. MMC_CAP2_POWEROFF_NOTIFY is replaced by MMC_CAP2_FULL_PWR_CYCLE, since it makes sense to use a wider scope for it. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 2 +- include/linux/mmc/host.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index e2946a98a1fa..e5ed79eb8e3d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1484,7 +1484,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) goto out; if (mmc_can_poweroff_notify(host->card) && - ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) || !is_suspend)) + ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend)) err = mmc_poweroff_notify(host->card, notify_type); else if (mmc_can_sleep(host->card)) err = mmc_sleep(host); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index eb2e6e1e5a3e..3b0c33ae13e1 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -264,7 +264,7 @@ struct mmc_host { #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ -#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ +#define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */ #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ #define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */ #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ -- GitLab From 5a36d6bcdf23e408da1d0cbb5d5ad2a26089e9ca Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 10 Jun 2013 17:03:47 +0200 Subject: [PATCH 1947/2900] mmc: core: Add DT-bindings for MMC_CAP2_FULL_PWR_CYCLE The DT-binding for MMC_CAP2_FULL_PWR_CYCLE, is used to indicate whether it is possible to perform a full power cycle of the card. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- Documentation/devicetree/bindings/mmc/mmc.txt | 1 + drivers/mmc/core/host.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index 85aada2263d5..458b57f199af 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt @@ -28,6 +28,7 @@ Optional properties: - cap-mmc-highspeed: MMC high-speed timing is supported - cap-power-off-card: powering off the card is safe - cap-sdio-irq: enable SDIO IRQ signalling on this interface +- full-pwr-cycle: full power cycle of the card is supported *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line polarity properties, we have to fix the meaning of the "normal" and "inverted" diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 89f58498409a..6fb6f77450cb 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -423,6 +423,8 @@ int mmc_of_parse(struct mmc_host *host) host->caps |= MMC_CAP_POWER_OFF_CARD; if (of_find_property(np, "cap-sdio-irq", &len)) host->caps |= MMC_CAP_SDIO_IRQ; + if (of_find_property(np, "full-pwr-cycle", &len)) + host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; if (of_find_property(np, "keep-power-in-suspend", &len)) host->pm_caps |= MMC_PM_KEEP_POWER; if (of_find_property(np, "enable-sdio-wakeup", &len)) -- GitLab From 0dcaa2499b7d111bd70da5b0976c34210c850fb3 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 27 Jun 2013 11:46:29 -0400 Subject: [PATCH 1948/2900] sdhci-pxav3: Fix runtime PM initialization Commit bb691ae464b77d30e74c66480e98d74e88d6b194 breaks boot on OLPC XO-4, it hangs somewhere inside sdhci_add_host. When pm_runtime_set_autosuspend_delay() was being called, the device's usage counter was 0, causing the PM layer to runtime-suspend the device. We then went on to call sdhci_add_host() on a suspended device, which hung. Fix this by making the driver consistent with the omap_hsmmc driver, both in terms of runtime PM initialization and error handling. Now the device is not runtime-suspended until we exit the probe routine. Signed-off-by: Daniel Drake Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pxav3.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index d29f81097334..bf99359a3a90 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -287,18 +287,15 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) } } - pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS); pm_runtime_use_autosuspend(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, 1); - pm_runtime_get_noresume(&pdev->dev); ret = sdhci_add_host(host); if (ret) { dev_err(&pdev->dev, "failed to add host\n"); - pm_runtime_forbid(&pdev->dev); - pm_runtime_disable(&pdev->dev); goto err_add_host; } @@ -318,6 +315,8 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) err_of_parse: err_cd_req: err_add_host: + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(clk); clk_put(clk); err_clk_get: -- GitLab From 156e14b126ffb6f040bc6f1aff3c51077e42a744 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 12 Jun 2013 08:16:38 +0200 Subject: [PATCH 1949/2900] mmc: sdhci: fix caps2 for HS200 Although the HC supports HS200 (eMMC) the caps2 are always zero; this means there's no way to use the super speed mode (when init the card). If the HC support SDR104, for SD3.0, so it also supports HS200 for eMMC and this patch just sets the MMC_CAP2_HS200 in the host caps2 field. Reported-by: Youssef Triki Signed-off-by: Giuseppe Cavallaro Reviewed-by: Philip Rakity Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 14 +++++++++----- include/linux/mmc/sdhci.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index eadb3adf446e..9bd6ab203843 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1863,7 +1863,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) */ if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && (host->flags & SDHCI_SDR50_NEEDS_TUNING || - host->flags & SDHCI_HS200_NEEDS_TUNING)) + host->flags & SDHCI_SDR104_NEEDS_TUNING)) requires_tuning_nonuhs = true; if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || @@ -2994,9 +2994,13 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ - if (caps[1] & SDHCI_SUPPORT_SDR104) + if (caps[1] & SDHCI_SUPPORT_SDR104) { mmc->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50; - else if (caps[1] & SDHCI_SUPPORT_SDR50) + /* SD3.0: SDR104 is supported so (for eMMC) the caps2 + * field can be promoted to support HS200. + */ + mmc->caps2 |= MMC_CAP2_HS200; + } else if (caps[1] & SDHCI_SUPPORT_SDR50) mmc->caps |= MMC_CAP_UHS_SDR50; if (caps[1] & SDHCI_SUPPORT_DDR50) @@ -3006,9 +3010,9 @@ int sdhci_add_host(struct sdhci_host *host) if (caps[1] & SDHCI_USE_SDR50_TUNING) host->flags |= SDHCI_SDR50_NEEDS_TUNING; - /* Does the host need tuning for HS200? */ + /* Does the host need tuning for SDR104 / HS200? */ if (mmc->caps2 & MMC_CAP2_HS200) - host->flags |= SDHCI_HS200_NEEDS_TUNING; + host->flags |= SDHCI_SDR104_NEEDS_TUNING; /* Driver Type(s) (A, C, D) supported by the host */ if (caps[1] & SDHCI_DRIVER_TYPE_A) diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index ba35bdb87d99..a74518009099 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -127,7 +127,7 @@ struct sdhci_host { #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ -#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ +#define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ unsigned int version; /* SDHCI spec. version */ -- GitLab From eede2111c522264f6260e0a5fb742be31f725a99 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Wed, 12 Jun 2013 10:18:51 -0500 Subject: [PATCH 1950/2900] mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move SDMMC_CMD_USE_HOLD_REG to dw_mmc.h so other platforms can use this define. Signed-off-by: Dinh Nguyen Reviewed-by: Pavel Machek Acked-by: Jaehoon Chung Acked-by: Olof Johansson Acked-by: Seungwon Jeon --- drivers/mmc/host/Kconfig | 8 ++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 140 ++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9ab8f8dee942..1be228998c81 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCI diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index cd3228075553..67718c1b79ce 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index f013e7e3746b..866edef2e820 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) - #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c new file mode 100644 index 000000000000..14b5961a851c --- /dev/null +++ b/drivers/mmc/host/dw_mmc-socfpga.c @@ -0,0 +1,140 @@ +/* + * Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface + * driver + * + * Copyright (C) 2012, Samsung Electronics Co., Ltd. + * Copyright (C) 2013 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Taken from dw_mmc-exynos.c + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h" + +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 +#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \ + ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) + +/* SOCFPGA implementation specific driver private data */ +struct dw_mci_socfpga_priv_data { + u8 ciu_div; /* card interface unit divisor */ + u32 hs_timing; /* bitmask for CIU clock phase shift */ + struct regmap *sysreg; /* regmap for system manager register */ +}; + +static int dw_mci_socfpga_priv_init(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv; + + priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(host->dev, "mem alloc failed for private data\n"); + return -ENOMEM; + } + + priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); + if (IS_ERR(priv->sysreg)) { + dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n"); + return PTR_ERR(priv->sysreg); + } + host->priv = priv; + + return 0; +} + +static int dw_mci_socfpga_setup_clock(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + + clk_disable_unprepare(host->ciu_clk); + regmap_write(priv->sysreg, SYSMGR_SDMMCGRP_CTRL_OFFSET, + priv->hs_timing); + clk_prepare_enable(host->ciu_clk); + + host->bus_hz /= (priv->ciu_div + 1); + return 0; +} + +static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + + if (priv->hs_timing & DRV_CLK_PHASE_SHIFT_SEL_MASK) + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static int dw_mci_socfpga_parse_dt(struct dw_mci *host) +{ + struct dw_mci_socfpga_priv_data *priv = host->priv; + struct device_node *np = host->dev->of_node; + u32 timing[2]; + u32 div = 0; + int ret; + + ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div); + if (ret) + dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1"); + priv->ciu_div = div; + + ret = of_property_read_u32_array(np, + "altr,dw-mshc-sdr-timing", timing, 2); + if (ret) + return ret; + + priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); + return 0; +} + +static const struct dw_mci_drv_data socfpga_drv_data = { + .init = dw_mci_socfpga_priv_init, + .setup_clock = dw_mci_socfpga_setup_clock, + .prepare_command = dw_mci_socfpga_prepare_command, + .parse_dt = dw_mci_socfpga_parse_dt, +}; + +static const struct of_device_id dw_mci_socfpga_match[] = { + { .compatible = "altr,socfpga-dw-mshc", + .data = &socfpga_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match); + +int dw_mci_socfpga_probe(struct platform_device *pdev) +{ + const struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_socfpga_match, pdev->dev.of_node); + drv_data = match->data; + return dw_mci_pltfm_register(pdev, drv_data); +} + +static struct platform_driver dw_mci_socfpga_pltfm_driver = { + .probe = dw_mci_socfpga_probe, + .remove = __exit_p(dw_mci_pltfm_remove), + .driver = { + .name = "dwmmc_socfpga", + .of_match_table = of_match_ptr(dw_mci_socfpga_match), + .pm = &dw_mci_pltfm_pmops, + }, +}; + +module_platform_driver(dw_mci_socfpga_pltfm_driver); + +MODULE_DESCRIPTION("Altera SOCFPGA Specific DW-MSHC Driver Extension"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:dwmmc-socfpga"); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 2f52c87bbce9..81b29941c5b9 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -111,6 +111,7 @@ #define SDMMC_INT_ERROR 0xbfc2 /* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_CMD_USE_HOLD_REG BIT(29) #define SDMMC_CMD_CCS_EXP BIT(23) #define SDMMC_CMD_CEATA_RD BIT(22) #define SDMMC_CMD_UPD_CLK BIT(21) -- GitLab From 51f877ab1ae13680dcb13de7d9b8f7dccb109e44 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 24 Jun 2013 23:03:22 +0200 Subject: [PATCH 1951/2900] rt2x00: rt2800: increase EEPROM_SIZE to 512 bytes Ralink 3T chipsets are using a different EEPROM layout than the others. The EEPROM on these devices contain more data than the others which does not fit into 272 byte which the rt2800 driver actually uses. The Ralink reference driver defines EEPROM_SIZE to 512/1024 bytes for PCI/USB devices respectively. Increase the EEPROM_SIZE constant to 512 bytes, in order to make room for EEPROM data of 3T devices. Signed-off-by: Gabor Juhos Acked-by: Helmut Schaa Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index fe43d011f004..d78c495a86a0 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -100,7 +100,7 @@ #define CSR_REG_BASE 0x1000 #define CSR_REG_SIZE 0x0800 #define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0110 +#define EEPROM_SIZE 0x0200 #define BBP_BASE 0x0000 #define BBP_SIZE 0x00ff #define RF_BASE 0x0004 -- GitLab From 3e23d4e8cef83995558f1a7026ea2b74207445bf Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 24 Jun 2013 23:03:23 +0200 Subject: [PATCH 1952/2900] rt2x00: rt2800lib: turn on secondary PAs/LNAs for 3T/3R devices The secondary PAs/LNAs are turned on only for 2T/2R devices, however these are used for 3T/3R devices as well. Always turn those on if the device uses more than one tx/rx chains. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 4072242b2452..b7119e31e03e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2678,16 +2678,16 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, tx_pin = 0; - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.tx_chain_num == 2) { + if (rt2x00dev->default_ant.tx_chain_num > 1) { + /* Turn on secondary PAs for 2T and for 3T devices*/ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, rf->channel > 14); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, rf->channel <= 14); } - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.rx_chain_num == 2) { + if (rt2x00dev->default_ant.rx_chain_num > 1) { + /* Turn on secondary LNAs for 2R and for 3R devices */ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); } -- GitLab From bb16d4881e1fd2b189f2cb7bee96c3e9b7cfe5f9 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 24 Jun 2013 23:03:24 +0200 Subject: [PATCH 1953/2900] rt2x00: rt2800lib: turn on tertiary PAs/LNAs for 3T/3R devices The 3T/3R devices are using the tertiary PAs/LNAs however those are never turned on. Fix the code to turn on those on for such devices. Also modify the code to use switch statements to improve readability. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 47 ++++++++++++++++++------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b7119e31e03e..25f7dbee2811 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2678,30 +2678,53 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, tx_pin = 0; - if (rt2x00dev->default_ant.tx_chain_num > 1) { - /* Turn on secondary PAs for 2T and for 3T devices*/ + switch (rt2x00dev->default_ant.tx_chain_num) { + case 3: + /* Turn on tertiary PAs */ + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, + rf->channel > 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, + rf->channel <= 14); + /* fall-through */ + case 2: + /* Turn on secondary PAs */ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, rf->channel > 14); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, rf->channel <= 14); + /* fall-through */ + case 1: + /* Turn on primary PAs */ + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, + rf->channel > 14); + if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); + else + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, + rf->channel <= 14); + break; } - if (rt2x00dev->default_ant.rx_chain_num > 1) { - /* Turn on secondary LNAs for 2R and for 3R devices */ + switch (rt2x00dev->default_ant.rx_chain_num) { + case 3: + /* Turn on tertiary LNAs */ + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1); + /* fall-through */ + case 2: + /* Turn on secondary LNAs */ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + /* fall-through */ + case 1: + /* Turn on primary LNAs */ + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + break; } - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); - if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); - else - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, - rf->channel <= 14); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); -- GitLab From 9a54c17636814bce1ee19585231a4a038000c8bd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 25 Jun 2013 12:29:23 +0530 Subject: [PATCH 1954/2900] ath9k: Add mix tx gain table for AR9462 2.0 Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 3 + .../wireless/ath/ath9k/ar9462_2p0_initvals.h | 63 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 3101c399bc33..d402cb32283f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -542,6 +542,9 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah) else if (AR_SREV_9462_21(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9462_2p1_modes_mix_ob_db_tx_gain); + else if (AR_SREV_9462_20(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9462_modes_mix_ob_db_tx_gain_table_2p0); else INIT_INI_ARRAY(&ah->iniModesTxGain, ar9300Modes_mixed_ob_db_tx_gain_table_2p2); diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index 1d6b705ba110..092b9d412e7f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -879,6 +879,69 @@ static const u32 ar9462_2p0_radio_postamble[][5] = { {0x0001650c, 0x48000000, 0x40000000, 0x40000000, 0x40000000}, }; +static const u32 ar9462_modes_mix_ob_db_tx_gain_table_2p0[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ + {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, + {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x0000a410, 0x0000d0da, 0x0000d0da, 0x0000d0de, 0x0000d0de}, + {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, + {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x18022622, 0x18022622, 0x12000400, 0x12000400}, + {0x0000a518, 0x1b022822, 0x1b022822, 0x16000402, 0x16000402}, + {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, + {0x0000a520, 0x22022c41, 0x22022c41, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x28023042, 0x28023042, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x2c023044, 0x2c023044, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x2f023644, 0x2f023644, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x34025643, 0x34025643, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x38025a44, 0x38025a44, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x3b025e45, 0x3b025e45, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x38001640, 0x38001640}, + {0x0000a540, 0x48025e6c, 0x48025e6c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55025eb3, 0x55025eb3, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x62025f56, 0x62025f56, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x66027f56, 0x66027f56, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x70049f56, 0x70049f56, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x751ffff6, 0x751ffff6, 0x5c001eec, 0x5c001eec}, + {0x0000a568, 0x751ffff6, 0x751ffff6, 0x5e001ef0, 0x5e001ef0}, + {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x60001ef4, 0x60001ef4}, + {0x0000a570, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a574, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a578, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x62001ff6, 0x62001ff6}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +}; + static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, -- GitLab From 0847beb2865f5ef1c8626ec1a37def18f3d6c41a Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 25 Jun 2013 22:57:29 +0200 Subject: [PATCH 1955/2900] rt2x00: rt2800lib: fix default TX power check for RT55xx The code writes the default_power2 value into the TX field of the RFCSR50 register, however the condition in the if statement uses default_power1. Due to this, wrong TX power value might be written into the register. Use the correct value in the condition to fix the issue. Compile tested only. Signed-off-by: Gabor Juhos Cc: stable@vger.kernel.org # 3.10 Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 25f7dbee2811..1f80ea5e29dd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2392,7 +2392,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); - if (info->default_power1 > power_bound) + if (info->default_power2 > power_bound) rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); else rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); -- GitLab From 87b1423b71f7ce58186c89920b0cde12a74ee150 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 26 Jun 2013 08:50:50 +0200 Subject: [PATCH 1956/2900] ath10k: fix MSI-X setup failpath Irqs were not freed up correctly upon msi-x setup failure. Signed-off-by: Michal Kazior Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath10k/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c8e905669701..33af4672c909 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1883,9 +1883,10 @@ static int ath10k_pci_start_intr_msix(struct ath10k *ar, int num) ath10k_warn("request_irq(%d) failed %d\n", ar_pci->pdev->irq + i, ret); - for (; i >= MSI_ASSIGN_CE_INITIAL; i--) - free_irq(ar_pci->pdev->irq, ar); + for (i--; i >= MSI_ASSIGN_CE_INITIAL; i--) + free_irq(ar_pci->pdev->irq + i, ar); + free_irq(ar_pci->pdev->irq + MSI_ASSIGN_FW, ar); pci_disable_msi(ar_pci->pdev); return ret; } -- GitLab From 429ff56a4ad5d9568a319f9368cc06c9f4f571af Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 26 Jun 2013 08:54:54 +0200 Subject: [PATCH 1957/2900] ath10k: fix 5ghz channel definitions Nonsense channel flags were being set. Although it doesn't seem this was visible to the user the patch makes sure that channel availability won't be crippled in the future if ath_common behaviour changes. Signed-off-by: Michal Kazior Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath10k/mac.c | 48 +++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3446c989d6a6..725b06799043 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2721,30 +2721,30 @@ static const struct ieee80211_channel ath10k_2ghz_channels[] = { }; static const struct ieee80211_channel ath10k_5ghz_channels[] = { - CHAN5G(36, 5180, 14), - CHAN5G(40, 5200, 15), - CHAN5G(44, 5220, 16), - CHAN5G(48, 5240, 17), - CHAN5G(52, 5260, 18), - CHAN5G(56, 5280, 19), - CHAN5G(60, 5300, 20), - CHAN5G(64, 5320, 21), - CHAN5G(100, 5500, 22), - CHAN5G(104, 5520, 23), - CHAN5G(108, 5540, 24), - CHAN5G(112, 5560, 25), - CHAN5G(116, 5580, 26), - CHAN5G(120, 5600, 27), - CHAN5G(124, 5620, 28), - CHAN5G(128, 5640, 29), - CHAN5G(132, 5660, 30), - CHAN5G(136, 5680, 31), - CHAN5G(140, 5700, 32), - CHAN5G(149, 5745, 33), - CHAN5G(153, 5765, 34), - CHAN5G(157, 5785, 35), - CHAN5G(161, 5805, 36), - CHAN5G(165, 5825, 37), + CHAN5G(36, 5180, 0), + CHAN5G(40, 5200, 0), + CHAN5G(44, 5220, 0), + CHAN5G(48, 5240, 0), + CHAN5G(52, 5260, 0), + CHAN5G(56, 5280, 0), + CHAN5G(60, 5300, 0), + CHAN5G(64, 5320, 0), + CHAN5G(100, 5500, 0), + CHAN5G(104, 5520, 0), + CHAN5G(108, 5540, 0), + CHAN5G(112, 5560, 0), + CHAN5G(116, 5580, 0), + CHAN5G(120, 5600, 0), + CHAN5G(124, 5620, 0), + CHAN5G(128, 5640, 0), + CHAN5G(132, 5660, 0), + CHAN5G(136, 5680, 0), + CHAN5G(140, 5700, 0), + CHAN5G(149, 5745, 0), + CHAN5G(153, 5765, 0), + CHAN5G(157, 5785, 0), + CHAN5G(161, 5805, 0), + CHAN5G(165, 5825, 0), }; static struct ieee80211_rate ath10k_rates[] = { -- GitLab From d847e3e2e4d9d0c2902122a474d7fe62e08d6309 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 26 Jun 2013 08:57:24 +0200 Subject: [PATCH 1958/2900] ath10k: leave MMIC generation to the HW Apparently HW doesn't require us to generate MMIC for TKIP suite. Each frame was 8 bytes longer than it should be and some APs would drop frames that exceed 1520 bytes of 802.11 payload. This could be observed during throughput tests or fragmented IP traffic. Signed-off-by: Michal Kazior Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath10k/mac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 725b06799043..95e306ef4df2 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -54,7 +54,6 @@ static int ath10k_send_key(struct ath10k_vif *arvif, key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; break; case WLAN_CIPHER_SUITE_TKIP: - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; arg.key_cipher = WMI_CIPHER_TKIP; arg.key_txmic_len = 8; arg.key_rxmic_len = 8; -- GitLab From 8960400eeefa73e7fe32dc2b6b5ac529d43a9593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 26 Jun 2013 09:55:54 +0200 Subject: [PATCH 1959/2900] b43: replace B43_BCMA_EXTRA with modparam allhwsupport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows enabling support for extra hardware with just a module param, without kernel/module recompilation. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 6 ------ drivers/net/wireless/b43/main.c | 12 ++++++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 3f21e0ba39ba..51ff0b198d0a 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -31,12 +31,6 @@ config B43_BCMA depends on B43 && (BCMA = y || BCMA = B43) default y -config B43_BCMA_EXTRA - bool "Hardware support that overlaps with the brcmsmac driver" - depends on B43_BCMA - default n if BRCMSMAC - default y - config B43_SSB bool depends on B43 && (SSB = y || SSB = B43) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a95b77ab360e..0e933bb71543 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -113,13 +113,15 @@ static int b43_modparam_pio = 0; module_param_named(pio, b43_modparam_pio, int, 0644); MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); +static int modparam_allhwsupport = !IS_ENABLED(CONFIG_BRCMSMAC); +module_param_named(allhwsupport, modparam_allhwsupport, int, 0444); +MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)"); + #ifdef CONFIG_B43_BCMA static const struct bcma_device_id b43_bcma_tbl[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), -#ifdef CONFIG_B43_BCMA_EXTRA BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), -#endif BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), BCMA_CORETABLE_END }; @@ -5396,6 +5398,12 @@ static int b43_bcma_probe(struct bcma_device *core) struct b43_wl *wl; int err; + if (!modparam_allhwsupport && + (core->id.rev == 0x17 || core->id.rev == 0x18)) { + pr_err("Support for cores revisions 0x17 and 0x18 disabled by module param allhwsupport=0. Try b43.allhwsupport=1\n"); + return -ENOTSUPP; + } + dev = b43_bus_dev_bcma_init(core); if (!dev) return -ENODEV; -- GitLab From 88f9b65d444794bb607f71644362ba0642585206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 26 Jun 2013 10:02:11 +0200 Subject: [PATCH 1960/2900] bcma: add support for BCM43142 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/bcma/bcma_private.h | 2 + drivers/bcma/driver_chipcommon.c | 11 +- drivers/bcma/driver_chipcommon_pmu.c | 123 ++++++++++++++++++++ drivers/bcma/host_pci.c | 1 + drivers/bcma/main.c | 19 +++ drivers/bcma/sprom.c | 1 + include/linux/bcma/bcma.h | 1 + include/linux/bcma/bcma_driver_chipcommon.h | 55 +++++++++ 8 files changed, 211 insertions(+), 2 deletions(-) diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 79595a001204..0215f9ad755c 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -22,6 +22,8 @@ struct bcma_bus; /* main.c */ +bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, + int timeout); int bcma_bus_register(struct bcma_bus *bus); void bcma_bus_unregister(struct bcma_bus *bus); int __init bcma_bus_early_register(struct bcma_bus *bus, diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 036c6744b39b..b068f98920a8 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -140,8 +140,15 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) bcma_core_chipcommon_early_init(cc); if (cc->core->id.rev >= 20) { - bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); - bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); + u32 pullup = 0, pulldown = 0; + + if (cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM43142) { + pullup = 0x402e0; + pulldown = 0x20500; + } + + bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, pullup); + bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, pulldown); } if (cc->capabilities & BCMA_CC_CAP_PMU) diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index edca73af3cc0..5081a8c439cc 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -56,6 +56,109 @@ void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); +static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) +{ + u32 ilp_ctl, alp_hz; + + if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & + BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) + return 0; + + bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, + BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); + usleep_range(1000, 2000); + + ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); + ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; + + bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); + + alp_hz = ilp_ctl * 32768 / 4; + return (alp_hz + 50000) / 100000 * 100; +} + +static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) +{ + struct bcma_bus *bus = cc->core->bus; + u32 freq_tgt_target = 0, freq_tgt_current; + u32 pll0, mask; + + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM43142: + /* pmu2_xtaltab0_adfll_485 */ + switch (xtalfreq) { + case 12000: + freq_tgt_target = 0x50D52; + break; + case 20000: + freq_tgt_target = 0x307FE; + break; + case 26000: + freq_tgt_target = 0x254EA; + break; + case 37400: + freq_tgt_target = 0x19EF8; + break; + case 52000: + freq_tgt_target = 0x12A75; + break; + } + break; + } + + if (!freq_tgt_target) { + bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n", + xtalfreq); + return; + } + + pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0); + freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >> + BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; + + if (freq_tgt_current == freq_tgt_target) { + bcma_debug(bus, "Target TGT frequency already set\n"); + return; + } + + /* Turn off PLL */ + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM43142: + mask = (u32)~(BCMA_RES_4314_HT_AVAIL | + BCMA_RES_4314_MACPHY_CLK_AVAIL); + + bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); + bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); + bcma_wait_value(cc->core, BCMA_CLKCTLST, + BCMA_CLKCTLST_HAVEHT, 0, 20000); + break; + } + + pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK; + pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT; + bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0); + + /* Flush */ + if (cc->pmu.rev >= 2) + bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); + + /* TODO: Do we need to update OTP? */ +} + +static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) +{ + struct bcma_bus *bus = cc->core->bus; + u32 xtalfreq = bcma_pmu_xtalfreq(cc); + + switch (bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM43142: + if (xtalfreq == 0) + xtalfreq = 20000; + bcma_pmu2_pll_init0(cc, xtalfreq); + break; + } +} + static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -66,6 +169,25 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) min_msk = 0x200D; max_msk = 0xFFFF; break; + case BCMA_CHIP_ID_BCM43142: + min_msk = BCMA_RES_4314_LPLDO_PU | + BCMA_RES_4314_PMU_SLEEP_DIS | + BCMA_RES_4314_PMU_BG_PU | + BCMA_RES_4314_CBUCK_LPOM_PU | + BCMA_RES_4314_CBUCK_PFM_PU | + BCMA_RES_4314_CLDO_PU | + BCMA_RES_4314_LPLDO2_LVM | + BCMA_RES_4314_WL_PMU_PU | + BCMA_RES_4314_LDO3P3_PU | + BCMA_RES_4314_OTP_PU | + BCMA_RES_4314_WL_PWRSW_PU | + BCMA_RES_4314_LQ_AVAIL | + BCMA_RES_4314_LOGIC_RET | + BCMA_RES_4314_MEM_SLEEP | + BCMA_RES_4314_MACPHY_RET | + BCMA_RES_4314_WL_CORE_READY; + max_msk = 0x3FFFFFFF; + break; default: bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n", bus->chipinfo.id); @@ -165,6 +287,7 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_NOILPONW); + bcma_pmu_pll_init(cc); bcma_pmu_resources_init(cc); bcma_pmu_workarounds(cc); } diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index fbf2759e7e4e..a355e63a3838 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -275,6 +275,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { 0, }, }; diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index f72f52b4b1dd..0067422ec17d 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -93,6 +93,25 @@ struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, return NULL; } +bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, + int timeout) +{ + unsigned long deadline = jiffies + timeout; + u32 val; + + do { + val = bcma_read32(core, reg); + if ((val & mask) == value) + return true; + cpu_relax(); + udelay(10); + } while (!time_after_eq(jiffies, deadline)); + + bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); + + return false; +} + static void bcma_release_core_dev(struct device *dev) { struct bcma_device *core = container_of(dev, struct bcma_device, dev); diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index de15b4f4b237..72bf4540f565 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -503,6 +503,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) case BCMA_CHIP_ID_BCM4331: present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT; break; + case BCMA_CHIP_ID_BCM43142: case BCMA_CHIP_ID_BCM43224: case BCMA_CHIP_ID_BCM43225: /* for these chips OTP is always available */ diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 2e34db82a643..622fc505d3e1 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -144,6 +144,7 @@ struct bcma_host_ops { /* Chip IDs of PCIe devices */ #define BCMA_CHIP_ID_BCM4313 0x4313 +#define BCMA_CHIP_ID_BCM43142 43142 #define BCMA_CHIP_ID_BCM43224 43224 #define BCMA_PKG_ID_BCM43224_FAB_CSM 0x8 #define BCMA_PKG_ID_BCM43224_FAB_SMIC 0xa diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index b8b09eac60a4..c49e1a159e6e 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -330,6 +330,8 @@ #define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */ #define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */ #define BCMA_CC_PMU_STAT 0x0608 /* PMU status */ +#define BCMA_CC_PMU_STAT_EXT_LPO_AVAIL 0x00000100 +#define BCMA_CC_PMU_STAT_WDRESET 0x00000080 #define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ #define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ #define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ @@ -355,6 +357,11 @@ #define BCMA_CC_REGCTL_DATA 0x065C #define BCMA_CC_PLLCTL_ADDR 0x0660 #define BCMA_CC_PLLCTL_DATA 0x0664 +#define BCMA_CC_PMU_STRAPOPT 0x0668 /* (corerev >= 28) */ +#define BCMA_CC_PMU_XTAL_FREQ 0x066C /* (pmurev >= 10) */ +#define BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK 0x00001FFF +#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_MASK 0x80000000 +#define BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT 31 #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ /* NAND flash MLC controller registers (corerev >= 38) */ #define BCMA_CC_NAND_REVISION 0x0C00 @@ -435,6 +442,23 @@ #define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 #define BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT 0 +/* PMU rev 15 */ +#define BCMA_CC_PMU15_PLL_PLLCTL0 0 +#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_MASK 0x00000003 +#define BCMA_CC_PMU15_PLL_PC0_CLKSEL_SHIFT 0 +#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK 0x003FFFFC +#define BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT 2 +#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_MASK 0x00C00000 +#define BCMA_CC_PMU15_PLL_PC0_PRESCALE_SHIFT 22 +#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_MASK 0x07000000 +#define BCMA_CC_PMU15_PLL_PC0_KPCTRL_SHIFT 24 +#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_MASK 0x38000000 +#define BCMA_CC_PMU15_PLL_PC0_FCNTCTRL_SHIFT 27 +#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_MASK 0x40000000 +#define BCMA_CC_PMU15_PLL_PC0_FDCMODE_SHIFT 30 +#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_MASK 0x80000000 +#define BCMA_CC_PMU15_PLL_PC0_CTRLBIAS_SHIFT 31 + /* ALP clock on pre-PMU chips */ #define BCMA_CC_PMU_ALP_CLOCK 20000000 /* HT clock for systems with PMU-enabled chipcommon */ @@ -507,6 +531,37 @@ #define BCMA_CHIPCTL_5357_I2S_PINS_ENABLE BIT(18) #define BCMA_CHIPCTL_5357_I2CSPI_PINS_ENABLE BIT(19) +#define BCMA_RES_4314_LPLDO_PU BIT(0) +#define BCMA_RES_4314_PMU_SLEEP_DIS BIT(1) +#define BCMA_RES_4314_PMU_BG_PU BIT(2) +#define BCMA_RES_4314_CBUCK_LPOM_PU BIT(3) +#define BCMA_RES_4314_CBUCK_PFM_PU BIT(4) +#define BCMA_RES_4314_CLDO_PU BIT(5) +#define BCMA_RES_4314_LPLDO2_LVM BIT(6) +#define BCMA_RES_4314_WL_PMU_PU BIT(7) +#define BCMA_RES_4314_LNLDO_PU BIT(8) +#define BCMA_RES_4314_LDO3P3_PU BIT(9) +#define BCMA_RES_4314_OTP_PU BIT(10) +#define BCMA_RES_4314_XTAL_PU BIT(11) +#define BCMA_RES_4314_WL_PWRSW_PU BIT(12) +#define BCMA_RES_4314_LQ_AVAIL BIT(13) +#define BCMA_RES_4314_LOGIC_RET BIT(14) +#define BCMA_RES_4314_MEM_SLEEP BIT(15) +#define BCMA_RES_4314_MACPHY_RET BIT(16) +#define BCMA_RES_4314_WL_CORE_READY BIT(17) +#define BCMA_RES_4314_ILP_REQ BIT(18) +#define BCMA_RES_4314_ALP_AVAIL BIT(19) +#define BCMA_RES_4314_MISC_PWRSW_PU BIT(20) +#define BCMA_RES_4314_SYNTH_PWRSW_PU BIT(21) +#define BCMA_RES_4314_RX_PWRSW_PU BIT(22) +#define BCMA_RES_4314_RADIO_PU BIT(23) +#define BCMA_RES_4314_VCO_LDO_PU BIT(24) +#define BCMA_RES_4314_AFE_LDO_PU BIT(25) +#define BCMA_RES_4314_RX_LDO_PU BIT(26) +#define BCMA_RES_4314_TX_LDO_PU BIT(27) +#define BCMA_RES_4314_HT_AVAIL BIT(28) +#define BCMA_RES_4314_MACPHY_CLK_AVAIL BIT(29) + /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ -- GitLab From 2086374658ae580fc0575c9ab7c1ec033458dbf6 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:20:14 +0200 Subject: [PATCH 1961/2900] brcmfmac: simplify transmit path When getting a transmit packet from the networking layer simply enqueue the packet unconditional and have it handled by the dequeue worker. The transfer of the packet to the bus-specific driver part is now done from one context. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 54 ++----------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 13e75c4b1a6b..41f902d0ec2d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1707,37 +1707,6 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) return -ENAVAIL; } -static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo, - struct sk_buff *skb) -{ - struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; - int *credit = &fws->fifo_credit[fifo]; - - if (fifo != BRCMF_FWS_FIFO_AC_BE) - fws->borrow_defer_timestamp = jiffies + - BRCMF_FWS_BORROW_DEFER_PERIOD; - - if (!(*credit)) { - /* Try to borrow a credit from other queue */ - if (fifo != BRCMF_FWS_FIFO_AC_BE || - (brcmf_fws_borrow_credit(fws) != 0)) { - brcmf_dbg(DATA, "ac=%d, credits depleted\n", fifo); - return -ENAVAIL; - } - } else { - (*credit)--; - if (!(*credit)) - fws->fifo_credit_map &= ~(1 << fifo); - } - - brcmf_fws_macdesc_use_req_credit(entry, skb); - - brcmf_dbg(DATA, "ac=%d, credits=%02d:%02d:%02d:%02d\n", fifo, - fws->fifo_credit[0], fws->fifo_credit[1], - fws->fifo_credit[2], fws->fifo_credit[3]); - return 0; -} - static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, struct sk_buff *skb) { @@ -1819,25 +1788,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) eh->h_dest, multicast, fifo); brcmf_fws_lock(drvr, flags); - /* multicast credit support is conditional, setting - * flag to false to assure credit is consumed below. - */ - if (fws->bcmc_credit_check) - multicast = false; - - if (skcb->mac->suppressed || - fws->bus_flow_blocked || - brcmf_fws_macdesc_closed(fws, skcb->mac, fifo) || - brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) || - (!multicast && - brcmf_fws_consume_credit(fws, fifo, skb) < 0)) { - /* enqueue the packet in delayQ */ - drvr->fws->fifo_delay_map |= 1 << fifo; - brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); - } else { - brcmf_fws_commit_skb(fws, fifo, skb); - } + brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); + if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC) + fws->borrow_defer_timestamp = jiffies + + BRCMF_FWS_BORROW_DEFER_PERIOD; brcmf_fws_unlock(drvr, flags); + brcmf_fws_schedule_deq(fws); return 0; } -- GitLab From 2a5d7b026db094d9be7f399bef70afc435f842f7 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:20:15 +0200 Subject: [PATCH 1962/2900] brcmfmac: remove (ab)use of NL80211_NUM_ACS Used NL80211_NUM_ACS to indicate the BCMC fifo used in the driver which has the same value now, but it is a bad idea relying on that. Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 41f902d0ec2d..e4fd13af7597 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1851,7 +1851,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); brcmf_fws_lock(fws->drvr, flags); - for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked; + for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked; fifo--) { while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && (fifo == BRCMF_FWS_FIFO_BCMC))) { -- GitLab From b058d4d258c13c725d5eb0fc5407d87212916966 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 26 Jun 2013 14:20:16 +0200 Subject: [PATCH 1963/2900] brcmfmac: remove SDIO_REQ_ASYNC flag Remove SDIO_REQ_ASYNC from brcmfmac since it is not being used. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 14 +++----------- .../net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 -- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 3f8e69c29146..c9c5ad269eaf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -453,15 +453,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, } static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, - uint flags, uint width, u32 *addr) + uint width, u32 *addr) { uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; - /* Async not implemented yet */ - if (flags & SDIO_REQ_ASYNC) - return -ENOTSUPP; - if (bar0 != sdiodev->sbwad) { err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); if (err) @@ -512,7 +508,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, fn, addr, pkt->len); width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); + err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr); if (err) goto done; @@ -536,7 +532,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, fn, addr, pktq->qlen); width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); + err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr); if (err) goto done; @@ -581,10 +577,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pkt->len); - /* Async not implemented yet */ - if (flags & SDIO_REQ_ASYNC) - return -ENOTSUPP; - if (bar0 != sdiodev->sbwad) { err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); if (err) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 793df66fe0bf..69c03fe7e3d4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -229,8 +229,6 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, #define SDIO_REQ_4BYTE 0x1 /* Fixed address (FIFO) (vs. incrementing address) */ #define SDIO_REQ_FIXED 0x2 -/* Async request (vs. sync request) */ -#define SDIO_REQ_ASYNC 0x4 /* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). * rw: read or write (0/1) -- GitLab From 356bae6fb77b9ed74989bab4d919afd598f921a8 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 26 Jun 2013 14:20:17 +0200 Subject: [PATCH 1964/2900] brcmfmac: use unified dongle address preparation function Introduce a unified dongle backplane address preparation function brcmf_sdio_addrprep to replace duplicate address prep code. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh.c | 79 +++++++------------ .../wireless/brcm80211/brcmfmac/sdio_host.h | 3 - 2 files changed, 27 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index c9c5ad269eaf..70cd0e9cd52b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -162,7 +162,7 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) return 0; } -int +static int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) { int err = 0, i; @@ -193,12 +193,33 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) return err; } +static int +brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr) +{ + uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; + int err = 0; + + if (bar0 != sdiodev->sbwad) { + err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); + if (err) + return err; + + sdiodev->sbwad = bar0; + } + + *addr &= SBSDIO_SB_OFT_ADDR_MASK; + + if (width == 4) + *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + + return 0; +} + int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, void *data, bool write) { u8 func_num, reg_size; - u32 bar; s32 retry = 0; int ret; @@ -218,18 +239,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, func_num = SDIO_FUNC_1; reg_size = 4; - /* Set the window for SB core register */ - bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - if (bar != sdiodev->sbwad) { - ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar); - if (ret != 0) { - memset(data, 0xFF, reg_size); - return ret; - } - sdiodev->sbwad = bar; - } - addr &= SBSDIO_SB_OFT_ADDR_MASK; - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + brcmf_sdio_addrprep(sdiodev, reg_size, &addr); } do { @@ -452,28 +462,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, return ret; } -static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, - uint width, u32 *addr) -{ - uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; - int err = 0; - - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); - if (err) - return err; - - sdiodev->sbwad = bar0; - } - - *addr &= SBSDIO_SB_OFT_ADDR_MASK; - - if (width == 4) - *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - return 0; -} - int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint flags, u8 *buf, uint nbytes) @@ -508,7 +496,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, fn, addr, pkt->len); width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr); + err = brcmf_sdio_addrprep(sdiodev, width, &addr); if (err) goto done; @@ -532,7 +520,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, fn, addr, pktq->qlen); width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr); + err = brcmf_sdio_addrprep(sdiodev, width, &addr); if (err) goto done; @@ -570,33 +558,20 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, uint flags, struct sk_buff *pkt) { uint width; - uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; int err = 0; struct sk_buff_head pkt_list; brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, pkt->len); - if (bar0 != sdiodev->sbwad) { - err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); - if (err) - goto done; - - sdiodev->sbwad = bar0; - } - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - if (width == 4) - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; + brcmf_sdio_addrprep(sdiodev, width, &addr); skb_queue_head_init(&pkt_list); skb_queue_tail(&pkt_list, pkt); err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list); skb_dequeue_tail(&pkt_list); -done: return err; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 69c03fe7e3d4..09786a539950 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -249,9 +249,6 @@ extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn); extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev); -extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, - u32 address); - /* attach, return handler on success, NULL if failed. * The handler shall be provided by all subsequent calls. No local cache * cfghdl points to the starting address of pci device mapped memory -- GitLab From 3b81a6809480f3fc7d9d06562704c8df18ecec00 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Wed, 26 Jun 2013 14:20:18 +0200 Subject: [PATCH 1965/2900] brcmfmac: add broken scatter-gather DMA support DMA engine of some old SDIO host controllers require block size alignment for data length of each scatterlist item. This patch introduces an intermediate buffer list to support this kind of platform. It decreases the throughput because of an extra memcpy in critical data path. So don't turn this on unless it's necessary. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend van Spriel Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../net/wireless/brcm80211/brcmfmac/bcmsdh.c | 78 ++++++++++++++++--- include/linux/platform_data/brcmfmac-sdio.h | 5 ++ 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 70cd0e9cd52b..e3f3c48f86d4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -331,10 +331,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, bool write, u32 addr, struct sk_buff_head *pktlist) { unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset; - unsigned int max_blks, max_req_sz; + unsigned int max_blks, max_req_sz, orig_offset, dst_offset; unsigned short max_seg_sz, seg_sz; - unsigned char *pkt_data; - struct sk_buff *pkt_next = NULL; + unsigned char *pkt_data, *orig_data, *dst_data; + struct sk_buff *pkt_next = NULL, *local_pkt_next; + struct sk_buff_head local_list, *target_list; struct mmc_request mmc_req; struct mmc_command mmc_cmd; struct mmc_data mmc_dat; @@ -371,6 +372,32 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, req_sz); } + target_list = pktlist; + /* for host with broken sg support, prepare a page aligned list */ + __skb_queue_head_init(&local_list); + if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { + req_sz = 0; + skb_queue_walk(pktlist, pkt_next) + req_sz += pkt_next->len; + req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize); + while (req_sz > PAGE_SIZE) { + pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE); + if (pkt_next == NULL) { + ret = -ENOMEM; + goto exit; + } + __skb_queue_tail(&local_list, pkt_next); + req_sz -= PAGE_SIZE; + } + pkt_next = brcmu_pkt_buf_get_skb(req_sz); + if (pkt_next == NULL) { + ret = -ENOMEM; + goto exit; + } + __skb_queue_tail(&local_list, pkt_next); + target_list = &local_list; + } + host = sdiodev->func[fn]->card->host; func_blk_sz = sdiodev->func[fn]->cur_blksize; /* Blocks per command is limited by host count, host transfer @@ -380,13 +407,15 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, max_req_sz = min_t(unsigned int, host->max_req_size, max_blks * func_blk_sz); max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC); - max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen); - seg_sz = pktlist->qlen; + max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen); + seg_sz = target_list->qlen; pkt_offset = 0; - pkt_next = pktlist->next; + pkt_next = target_list->next; - if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) - return -ENOMEM; + if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) { + ret = -ENOMEM; + goto exit; + } while (seg_sz) { req_sz = 0; @@ -396,7 +425,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, memset(&mmc_dat, 0, sizeof(struct mmc_data)); sgl = st.sgl; /* prep sg table */ - while (pkt_next != (struct sk_buff *)pktlist) { + while (pkt_next != (struct sk_buff *)target_list) { pkt_data = pkt_next->data + pkt_offset; sg_data_sz = pkt_next->len - pkt_offset; if (sg_data_sz > host->max_seg_size) @@ -423,8 +452,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, if (req_sz % func_blk_sz != 0) { brcmf_err("sg request length %u is not %u aligned\n", req_sz, func_blk_sz); - sg_free_table(&st); - return -ENOTBLK; + ret = -ENOTBLK; + goto exit; } mmc_dat.sg = st.sgl; mmc_dat.sg_len = sg_cnt; @@ -457,7 +486,34 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, } } + if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) { + local_pkt_next = local_list.next; + orig_offset = 0; + skb_queue_walk(pktlist, pkt_next) { + dst_offset = 0; + do { + req_sz = local_pkt_next->len - orig_offset; + req_sz = min_t(uint, pkt_next->len - dst_offset, + req_sz); + orig_data = local_pkt_next->data + orig_offset; + dst_data = pkt_next->data + dst_offset; + memcpy(dst_data, orig_data, req_sz); + orig_offset += req_sz; + dst_offset += req_sz; + if (orig_offset == local_pkt_next->len) { + orig_offset = 0; + local_pkt_next = local_pkt_next->next; + } + if (dst_offset == pkt_next->len) + break; + } while (!skb_queue_empty(&local_list)); + } + } + +exit: sg_free_table(&st); + while ((pkt_next = __skb_dequeue(&local_list)) != NULL) + brcmu_pkt_buf_free_skb(pkt_next); return ret; } diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h index 1ade657d5fc1..b7174998c24a 100644 --- a/include/linux/platform_data/brcmfmac-sdio.h +++ b/include/linux/platform_data/brcmfmac-sdio.h @@ -90,6 +90,10 @@ void __init brcmfmac_init_pdata(void) * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are * used for registering the irq using request_irq function. * + * broken_sg_support: flag for broken sg list support of SDIO host controller. + * Set this to true if the SDIO host controller has higher align requirement + * than 32 bytes for each scatterlist item. + * * power_on: This function is called by the brcmfmac when the module gets * loaded. This can be particularly useful for low power devices. The platform * spcific routine may for example decide to power up the complete device. @@ -116,6 +120,7 @@ struct brcmfmac_sdio_platform_data { bool oob_irq_supported; unsigned int oob_irq_nr; unsigned long oob_irq_flags; + bool broken_sg_support; void (*power_on)(void); void (*power_off)(void); void (*reset)(void); -- GitLab From 456d0685c7522c661bf5af7930317ffcb710a858 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:35:10 +0200 Subject: [PATCH 1966/2900] brcmfmac: tag packet in the netdev transmit callback Transmit packets needs to be tagged in order to receive a tx status feedback from the firmware. Determine the tag in the netdev transmit callback instead of determining the tag just before transfer to the device. This reduces the number of exception flows and hence makes the driver code simpler. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 130 +++++++----------- 1 file changed, 48 insertions(+), 82 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index e4fd13af7597..44b319292a50 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1575,21 +1575,14 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, return 0; } -static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, +static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, struct sk_buff *p) { struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); struct brcmf_fws_mac_descriptor *entry = skcb->mac; - int rc = 0; - bool first_time; - int hslot = BRCMF_FWS_HANGER_MAXITEMS; - u8 free_ctr; u8 flags; - first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED; - brcmf_skb_if_flags_set_field(p, TRANSMIT, 1); - brcmf_skb_htod_tag_set_field(p, FIFO, fifo); brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation); flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST; if (brcmf_skb_if_flags_get_field(p, REQUESTED)) { @@ -1600,80 +1593,36 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED; } brcmf_skb_htod_tag_set_field(p, FLAGS, flags); - if (first_time) { - /* obtaining free slot may fail, but that will be caught - * by the hanger push. This assures the packet has a BDC - * header upon return. - */ - hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); - free_ctr = entry->seq[fifo]; - brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); - brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr); - rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); - if (rc) - brcmf_err("hanger push failed: rc=%d\n", rc); - } - - if (rc == 0) - brcmf_fws_hdrpush(fws, p); - - return rc; + brcmf_fws_hdrpush(fws, p); } -static void -brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, - struct sk_buff *skb, int fifo) +static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, + struct sk_buff *skb, int fifo) { - /* - put the packet back to the head of queue - - - suppressed packet goes back to suppress sub-queue - - pull out the header, if new or delayed packet - - Note: hslot is used only when header removal is done. - */ struct brcmf_fws_mac_descriptor *entry; - enum brcmf_fws_skb_state state; struct sk_buff *pktout; + int qidx, hslot; int rc = 0; - int hslot; - state = brcmf_skbcb(skb)->state; entry = brcmf_skbcb(skb)->mac; - hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); - - if (entry != NULL) { - if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) { - /* wl-header is saved for suppressed packets */ - pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1, - skb); - if (pktout == NULL) { - brcmf_err("suppress queue full\n"); - rc = -ENOSPC; - } - } else { - /* delay-q packets are going to delay-q */ - pktout = brcmu_pktq_penq_head(&entry->psq, - 2 * fifo, skb); - if (pktout == NULL) { - brcmf_err("delay queue full\n"); - rc = -ENOSPC; - } - - /* free the hanger slot */ - brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout, - true); - - /* decrement sequence count */ - entry->seq[fifo]--; + if (entry->occupied) { + qidx = 2 * fifo; + if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED) + qidx++; + + pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb); + if (pktout == NULL) { + brcmf_err("%s queue %d full\n", entry->name, qidx); + rc = -ENOSPC; } } else { - brcmf_err("no mac entry linked\n"); + brcmf_err("%s entry removed\n", entry->name); rc = -ENOENT; } if (rc) { fws->stats.rollback_failed++; + hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0); } else { @@ -1720,15 +1669,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, if (IS_ERR(entry)) return PTR_ERR(entry); - rc = brcmf_fws_precommit_skb(fws, fifo, skb); - if (rc < 0) { - fws->stats.generic_error++; - goto rollback; - } - - brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags, - skcb->htod); + brcmf_fws_precommit_skb(fws, fifo, skb); rc = brcmf_bus_txdata(bus, skb); + brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name, + skcb->if_flags, skcb->htod, rc); if (rc < 0) { brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); goto rollback; @@ -1737,7 +1681,6 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, entry->transit_count++; if (entry->suppressed) entry->suppr_transit_count++; - entry->seq[fifo]++; fws->stats.pkt2bus++; fws->stats.send_pkts[fifo]++; if (brcmf_skb_if_flags_get_field(skb, REQUESTED)) @@ -1750,6 +1693,24 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, return rc; } +static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p, + int fifo) +{ + struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p); + int rc, hslot; + + hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger); + brcmf_skb_htod_tag_set_field(p, HSLOT, hslot); + brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]); + brcmf_skb_htod_tag_set_field(p, FIFO, fifo); + rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot); + if (!rc) + skcb->mac->seq[fifo]++; + else + fws->stats.generic_error++; + return rc; +} + int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) { struct brcmf_pub *drvr = ifp->drvr; @@ -1778,22 +1739,27 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) /* set control buffer information */ skcb->if_flags = 0; - skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest); skcb->state = BRCMF_FWS_SKBSTATE_NEW; brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); if (!multicast) fifo = brcmf_fws_prio2fifo[skb->priority]; - brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name, - eh->h_dest, multicast, fifo); - brcmf_fws_lock(drvr, flags); - brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC) fws->borrow_defer_timestamp = jiffies + BRCMF_FWS_BORROW_DEFER_PERIOD; + + skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest); + brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name, + eh->h_dest, multicast, fifo); + if (!brcmf_fws_assign_htod(fws, skb, fifo)) { + brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); + brcmf_fws_schedule_deq(fws); + } else { + brcmf_err("drop skb: no hanger slot\n"); + brcmu_pkt_buf_free_skb(skb); + } brcmf_fws_unlock(drvr, flags); - brcmf_fws_schedule_deq(fws); return 0; } -- GitLab From 80898a117895235587b7dde63e3240e4f4d440c1 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:20:20 +0200 Subject: [PATCH 1967/2900] brcmfmac: cleanup debug messages in brcmf_fws_hdrpush() Trivial cleanup of debug messages. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 44b319292a50..e92a3ce58c02 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -796,9 +796,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) u8 fillers; __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod); - brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u (%u), pkttag=0x%08X, hslot=%d\n", - entry->ea, entry->interface_id, - brcmf_skb_if_flags_get_field(skb, INDEX), + brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n", + entry->name, brcmf_skb_if_flags_get_field(skb, INDEX), le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff); if (entry->send_tim_signal) data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; @@ -822,8 +821,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb) wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; wlh[2] = entry->mac_handle; wlh[3] = entry->traffic_pending_bmp; - brcmf_dbg(TRACE, "adding TIM info: %02X:%02X:%02X:%02X\n", - wlh[0], wlh[1], wlh[2], wlh[3]); + brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n", + entry->mac_handle, entry->traffic_pending_bmp); wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2; entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; } -- GitLab From c6a681ab2c73c1296b4214307216dffeb52558df Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:20:21 +0200 Subject: [PATCH 1968/2900] brcmfmac: reduce firmware-signalling locking scope in rx path In the receive path a spinlock is taken upon parsing the TLV signal header. This moves to locking to the TLV handling functions where it protects the data structures. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/fwsignal.c | 77 ++++++++++++------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index e92a3ce58c02..f0d9f7f6c83d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -905,10 +905,26 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi) return 0; } +/* using macro so sparse checking does not complain + * about locking imbalance. + */ +#define brcmf_fws_lock(drvr, flags) \ +do { \ + flags = 0; \ + spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ +} while (0) + +/* using macro so sparse checking does not complain + * about locking imbalance. + */ +#define brcmf_fws_unlock(drvr, flags) \ + spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) + static int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) { struct brcmf_fws_mac_descriptor *entry, *existing; + ulong flags; u8 mac_handle; u8 ifidx; u8 *addr; @@ -922,8 +938,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) if (entry->occupied) { brcmf_dbg(TRACE, "deleting %s mac %pM\n", entry->name, addr); + brcmf_fws_lock(fws->drvr, flags); brcmf_fws_macdesc_cleanup(fws, entry, -1); brcmf_fws_macdesc_deinit(entry); + brcmf_fws_unlock(fws->drvr, flags); } else fws->stats.mac_update_failed++; return 0; @@ -932,11 +950,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) existing = brcmf_fws_macdesc_lookup(fws, addr); if (IS_ERR(existing)) { if (!entry->occupied) { + brcmf_fws_lock(fws->drvr, flags); entry->mac_handle = mac_handle; brcmf_fws_macdesc_init(entry, addr, ifidx); brcmf_fws_macdesc_set_name(fws, entry); brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); + brcmf_fws_unlock(fws->drvr, flags); brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr); } else { fws->stats.mac_update_failed++; @@ -944,11 +964,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) } else { if (entry != existing) { brcmf_dbg(TRACE, "copy mac %s\n", existing->name); + brcmf_fws_lock(fws->drvr, flags); memcpy(entry, existing, offsetof(struct brcmf_fws_mac_descriptor, psq)); entry->mac_handle = mac_handle; brcmf_fws_macdesc_deinit(existing); brcmf_fws_macdesc_set_name(fws, entry); + brcmf_fws_unlock(fws->drvr, flags); brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, addr); } else { @@ -964,7 +986,9 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) { struct brcmf_fws_mac_descriptor *entry; + ulong flags; u8 mac_handle; + int ret; mac_handle = data[0]; entry = &fws->desc.nodes[mac_handle & 0x1F]; @@ -972,26 +996,30 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws, fws->stats.mac_ps_update_failed++; return -ESRCH; } + brcmf_fws_lock(fws->drvr, flags); /* a state update should wipe old credits */ entry->requested_credit = 0; entry->requested_packet = 0; if (type == BRCMF_FWS_TYPE_MAC_OPEN) { entry->state = BRCMF_FWS_STATE_OPEN; - return BRCMF_FWS_RET_OK_SCHEDULE; + ret = BRCMF_FWS_RET_OK_SCHEDULE; } else { entry->state = BRCMF_FWS_STATE_CLOSE; brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false); brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true); + ret = BRCMF_FWS_RET_OK_NOSCHEDULE; } - return BRCMF_FWS_RET_OK_NOSCHEDULE; + brcmf_fws_unlock(fws->drvr, flags); + return ret; } static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) { struct brcmf_fws_mac_descriptor *entry; + ulong flags; u8 ifidx; int ret; @@ -1010,17 +1038,24 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, entry->name); + brcmf_fws_lock(fws->drvr, flags); switch (type) { case BRCMF_FWS_TYPE_INTERFACE_OPEN: entry->state = BRCMF_FWS_STATE_OPEN; - return BRCMF_FWS_RET_OK_SCHEDULE; + ret = BRCMF_FWS_RET_OK_SCHEDULE; + break; case BRCMF_FWS_TYPE_INTERFACE_CLOSE: entry->state = BRCMF_FWS_STATE_CLOSE; - return BRCMF_FWS_RET_OK_NOSCHEDULE; + ret = BRCMF_FWS_RET_OK_NOSCHEDULE; + break; default: ret = -EINVAL; - break; + brcmf_fws_unlock(fws->drvr, flags); + goto fail; } + brcmf_fws_unlock(fws->drvr, flags); + return ret; + fail: fws->stats.if_update_failed++; return ret; @@ -1030,6 +1065,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) { struct brcmf_fws_mac_descriptor *entry; + ulong flags; entry = &fws->desc.nodes[data[1] & 0x1F]; if (!entry->occupied) { @@ -1043,12 +1079,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type, brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n", brcmf_fws_get_tlv_name(type), type, entry->name, data[0], data[2]); + brcmf_fws_lock(fws->drvr, flags); if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) entry->requested_credit = data[0]; else entry->requested_packet = data[0]; entry->ac_bitmap = data[2]; + brcmf_fws_unlock(fws->drvr, flags); return BRCMF_FWS_RET_OK_SCHEDULE; } @@ -1345,6 +1383,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, u8 *data) { + ulong flags; int i; if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { @@ -1353,16 +1392,19 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, } brcmf_dbg(DATA, "enter: data %pM\n", data); + brcmf_fws_lock(fws->drvr, flags); for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) brcmf_fws_return_credits(fws, i, data[i]); brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map, fws->fifo_delay_map); + brcmf_fws_unlock(fws->drvr, flags); return BRCMF_FWS_RET_OK_SCHEDULE; } static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) { + ulong lflags; __le32 status_le; u32 status; u32 hslot; @@ -1376,7 +1418,10 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) hslot = brcmf_txstatus_get_field(status, HSLOT); genbit = brcmf_txstatus_get_field(status, GENERATION); - return brcmf_fws_txs_process(fws, flags, hslot, genbit); + brcmf_fws_lock(fws->drvr, lflags); + brcmf_fws_txs_process(fws, flags, hslot, genbit); + brcmf_fws_unlock(fws->drvr, lflags); + return BRCMF_FWS_RET_OK_NOSCHEDULE; } static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) @@ -1389,21 +1434,6 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) return 0; } -/* using macro so sparse checking does not complain - * about locking imbalance. - */ -#define brcmf_fws_lock(drvr, flags) \ -do { \ - flags = 0; \ - spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \ -} while (0) - -/* using macro so sparse checking does not complain - * about locking imbalance. - */ -#define brcmf_fws_unlock(drvr, flags) \ - spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags)) - static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) @@ -1454,7 +1484,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, struct sk_buff *skb) { struct brcmf_fws_info *fws = drvr->fws; - ulong flags; u8 *signal_data; s16 data_len; u8 type; @@ -1474,9 +1503,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, return 0; } - /* lock during tlv parsing */ - brcmf_fws_lock(drvr, flags); - fws->stats.header_pulls++; data_len = signal_len; signal_data = skb->data; @@ -1570,7 +1596,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, if (skb->len == 0) fws->stats.header_only_pkt++; - brcmf_fws_unlock(drvr, flags); return 0; } -- GitLab From cc1b5463947a009d6303dc6dc436326f34617499 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Jun 2013 14:20:22 +0200 Subject: [PATCH 1969/2900] brcmfmac: remove code and comment for older kernel support In the code of the receive path some code was dealing with how things were done in older kernels. Not really needed for an upstream driver. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/dhd_linux.c | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 8c402e7b97eb..8e8975562ec3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -281,8 +281,6 @@ void brcmf_txflowblock(struct device *dev, bool state) void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) { - unsigned char *eth; - uint len; struct sk_buff *skb, *pnext; struct brcmf_if *ifp; struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -306,33 +304,12 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) continue; } - /* Get the protocol, maintain skb around eth_type_trans() - * The main reason for this hack is for the limitation of - * Linux 2.4 where 'eth_type_trans' uses the - * 'net->hard_header_len' - * to perform skb_pull inside vs ETH_HLEN. Since to avoid - * coping of the packet coming from the network stack to add - * BDC, Hardware header etc, during network interface - * registration - * we set the 'net->hard_header_len' to ETH_HLEN + extra space - * required - * for BDC, Hardware header etc. and not just the ETH_HLEN - */ - eth = skb->data; - len = skb->len; - skb->dev = ifp->ndev; skb->protocol = eth_type_trans(skb, skb->dev); if (skb->pkt_type == PACKET_MULTICAST) ifp->stats.multicast++; - skb->data = eth; - skb->len = len; - - /* Strip header, count, deliver upward */ - skb_pull(skb, ETH_HLEN); - /* Process special event packets */ brcmf_fweh_process_skb(drvr, skb); @@ -348,10 +325,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) netif_rx(skb); else /* If the receive is not processed inside an ISR, - * the softirqd must be woken explicitly to service - * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled - * by netif_rx_ni(), but in earlier kernels, we need - * to do it manually. + * the softirqd must be woken explicitly to service the + * NET_RX_SOFTIRQ. This is handled by netif_rx_ni(). */ netif_rx_ni(skb); } -- GitLab From 0c9acaa8357a334645c96d505528a20f2fd4ac0a Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Wed, 26 Jun 2013 15:06:58 -0700 Subject: [PATCH 1970/2900] ath9k_htc: ifdef out IFTYPE_MESH advertisement This is needed so the interface combination can still be validated when CONFIG_MAC80211_MESH is not enabled. Otherwise wiphy registration fails. Signed-off-by: Thomas Pedersen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 925c5b0b1cde..71a183ffc77f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -701,8 +701,10 @@ static const struct ieee80211_iface_limit if_limits[] = { { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT) }, { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_MESH_POINT) }, +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_P2P_GO) }, }; static const struct ieee80211_iface_combination if_comb = { -- GitLab From 0f817ed52d07873cd39c9d3f6d87fae962dc742f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 27 Jun 2013 13:50:09 -0400 Subject: [PATCH 1971/2900] ath10k: minimally handle new channel width enumeration values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/net/wireless/ath/ath10k/mac.o drivers/net/wireless/ath/ath10k/mac.c: In function ‘chan_to_phymode’: drivers/net/wireless/ath/ath10k/mac.c:229:3: warning: enumeration value ‘NL80211_CHAN_WIDTH_5’ not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/mac.c:229:3: warning: enumeration value ‘NL80211_CHAN_WIDTH_10’ not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/mac.c:247:3: warning: enumeration value ‘NL80211_CHAN_WIDTH_5’ not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/mac.c:247:3: warning: enumeration value ‘NL80211_CHAN_WIDTH_10’ not handled in switch [-Wswitch] Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 95e306ef4df2..da5c333d0d4b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -236,6 +236,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) case NL80211_CHAN_WIDTH_40: phymode = MODE_11NG_HT40; break; + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: @@ -257,6 +259,8 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) case NL80211_CHAN_WIDTH_80: phymode = MODE_11AC_VHT80; break; + case NL80211_CHAN_WIDTH_5: + case NL80211_CHAN_WIDTH_10: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: phymode = MODE_UNKNOWN; -- GitLab From f82935ebd6adf554787c273cdc91d2d6ef1eaf51 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 17 May 2013 14:18:35 +0200 Subject: [PATCH 1972/2900] scripts/mod: Spelling s/DEVICEVTABLE/DEVICETABLE/ Signed-off-by: Geert Uytterhoeven Signed-off-by: Michal Marek --- scripts/mod/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index 75d59fcd48b8..ae21b898aba8 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -15,8 +15,8 @@ endef quiet_cmd_offsets = GEN $@ define cmd_offsets (set -e; \ - echo "#ifndef __DEVICEVTABLE_OFFSETS_H__"; \ - echo "#define __DEVICEVTABLE_OFFSETS_H__"; \ + echo "#ifndef __DEVICETABLE_OFFSETS_H__"; \ + echo "#define __DEVICETABLE_OFFSETS_H__"; \ echo "/*"; \ echo " * DO NOT MODIFY."; \ echo " *"; \ -- GitLab From bd70134396622ea50b14e34dae0810879884d553 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 29 May 2013 13:18:56 +0100 Subject: [PATCH 1973/2900] improve modalias building For one, there's no point in the respective pieces to be rebuilt unconditionally on each and every rebuild. Second there's no need to invent a custom rule for generating the .s file from the .c source - we can simply use the generic rule here. And finally, $(obj) should be used to refer to files in the build tree (rather than spelling out the subdirectory). Signed-off-by: Jan Beulich Signed-off-by: Michal Marek --- scripts/mod/Makefile | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index ae21b898aba8..c11212ff3510 100644 --- a/scripts/mod/Makefile +++ b/scripts/mod/Makefile @@ -29,15 +29,10 @@ define cmd_offsets echo "#endif" ) > $@ endef -# We use internal kbuild rules to avoid the "is up to date" message from make -scripts/mod/devicetable-offsets.s: scripts/mod/devicetable-offsets.c FORCE - $(Q)mkdir -p $(dir $@) - $(call if_changed_dep,cc_s_c) +$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s + $(call if_changed,offsets) -$(obj)/$(devicetable-offsets-file): scripts/mod/devicetable-offsets.s - $(call cmd,offsets) - -targets += $(devicetable-offsets-file) +targets += $(devicetable-offsets-file) devicetable-offsets.s # dependencies on generated files need to be listed explicitly -- GitLab From 1fe0cb848890a3f4dd965fdce8b4108feb03971f Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Wed, 12 Jun 2013 15:20:36 +0200 Subject: [PATCH 1974/2900] IB/srp: Fix remove_one crash due to resource exhaustion If the add_one callback fails during driver load no resources are allocated so there isn't a need to release any resources. Trying to clean the resource may lead to the following kernel panic: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] srp_remove_one+0x31/0x240 [ib_srp] RIP: 0010:[] [] srp_remove_one+0x31/0x240 [ib_srp] Process rmmod (pid: 4562, threadinfo ffff8800dd738000, task ffff8801167e60c0) Call Trace: [] ib_unregister_client+0x4e/0x120 [ib_core] [] srp_cleanup_module+0x15/0x71 [ib_srp] [] sys_delete_module+0x194/0x260 [] system_call_fastpath+0x16/0x1b Signed-off-by: Dotan Barak Reviewed-by: Eli Cohen Signed-off-by: Bart Van Assche Acked-by: Sebastian Riemer Acked-by: David Dillow Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 7ccf3284dda3..368d1606e16f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -2507,6 +2507,8 @@ static void srp_remove_one(struct ib_device *device) struct srp_target_port *target; srp_dev = ib_get_client_data(device, &srp_client); + if (!srp_dev) + return; list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { device_unregister(&host->dev); -- GitLab From 086f44f58855ae18bab19fb794cce6c6d2c6143b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 12 Jun 2013 15:23:04 +0200 Subject: [PATCH 1975/2900] IB/srp: Avoid skipping srp_reset_host() after a transport error The SCSI error handler assumes that the transport layer is operational if an eh_abort_handler() returns SUCCESS. Hence srp_abort() only should return SUCCESS if sending the ABORT TASK task management function succeeded. This patch avoids the SCSI error handler skipping the srp_reset_host() call after a transport layer error. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 368d1606e16f..759c55b9685f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1744,18 +1744,23 @@ static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_request *req = (struct srp_request *) scmnd->host_scribble; + int ret; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); if (!req || !srp_claim_req(target, req, scmnd)) return FAILED; - srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK); + if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK) == 0 || + target->transport_offline) + ret = SUCCESS; + else + ret = FAILED; srp_free_req(target, req, scmnd, 0); scmnd->result = DID_ABORT << 16; scmnd->scsi_done(scmnd); - return SUCCESS; + return ret; } static int srp_reset_device(struct scsi_cmnd *scmnd) -- GitLab From 2742c1dadde602baea6f0547c028154aebd6f1ca Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 12 Jun 2013 15:24:25 +0200 Subject: [PATCH 1976/2900] IB/srp: Skip host settle delay The SRP initiator implements host reset by reconnecting to the SRP target. That means that communication with the target is possible as soon as host reset finished. Hence skip the host settle delay. Signed-off-by: Bart Van Assche Reviewed-by: Sebastian Riemer Reviewed-by: Christoph Hellwig Acked-by: David Dillow Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 759c55b9685f..bc13c8db7fc2 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1951,6 +1951,7 @@ static struct scsi_host_template srp_template = { .eh_abort_handler = srp_abort, .eh_device_reset_handler = srp_reset_device, .eh_host_reset_handler = srp_reset_host, + .skip_settle_delay = true, .sg_tablesize = SRP_DEF_SG_TABLESIZE, .can_queue = SRP_CMD_SQ_SIZE, .this_id = -1, -- GitLab From 621e84d6f373dcb273ebfd772638b8e7dc3c2c48 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 26 Jun 2013 16:11:27 +0200 Subject: [PATCH 1977/2900] dev: introduce skb_scrub_packet() The goal of this new function is to perform all needed cleanup before sending an skb into another netns. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/linux/skbuff.h | 1 + net/core/dev.c | 11 +---------- net/core/skbuff.c | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a7393adea0b5..6b06023e8a08 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2384,6 +2384,7 @@ extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); extern int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); +extern void skb_scrub_packet(struct sk_buff *skb); extern struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); diff --git a/net/core/dev.c b/net/core/dev.c index 722f633926e0..370354a9c5f6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1652,22 +1652,13 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) } } - skb_orphan(skb); - if (unlikely(!is_skb_forwardable(dev, skb))) { atomic_long_inc(&dev->rx_dropped); kfree_skb(skb); return NET_RX_DROP; } - skb->skb_iif = 0; - skb_dst_drop(skb); - skb->tstamp.tv64 = 0; - skb->pkt_type = PACKET_HOST; + skb_scrub_packet(skb); skb->protocol = eth_type_trans(skb, dev); - skb->mark = 0; - secpath_reset(skb); - nf_reset(skb); - nf_reset_trace(skb); return netif_rx(skb); } EXPORT_SYMBOL_GPL(dev_forward_skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9f73eca29fbe..b1fcb8727e56 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3492,3 +3492,26 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, return true; } EXPORT_SYMBOL(skb_try_coalesce); + +/** + * skb_scrub_packet - scrub an skb before sending it to another netns + * + * @skb: buffer to clean + * + * skb_scrub_packet can be used to clean an skb before injecting it in + * another namespace. We have to clear all information in the skb that + * could impact namespace isolation. + */ +void skb_scrub_packet(struct sk_buff *skb) +{ + skb_orphan(skb); + skb->tstamp.tv64 = 0; + skb->pkt_type = PACKET_HOST; + skb->skb_iif = 0; + skb_dst_drop(skb); + skb->mark = 0; + secpath_reset(skb); + nf_reset(skb); + nf_reset_trace(skb); +} +EXPORT_SYMBOL_GPL(skb_scrub_packet); -- GitLab From 5e6700b3bf98fe98d630bf9c939ad4c85ce95592 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 26 Jun 2013 16:11:28 +0200 Subject: [PATCH 1978/2900] sit: add support of x-netns This patch allows to switch the netns when packet is encapsulated or decapsulated. In other word, the encapsulated packet is received in a netns, where the lookup is done to find the tunnel. Once the tunnel is found, the packet is decapsulated and injecting into the corresponding interface which stands to another netns. When one of the two netns is removed, the tunnel is destroyed. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/net/ip_tunnels.h | 1 + net/ipv4/ip_tunnel.c | 10 +++++++++- net/ipv6/sit.c | 42 ++++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index b0d982471a5c..781b3cf86a2f 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -42,6 +42,7 @@ struct ip_tunnel { struct ip_tunnel __rcu *next; struct hlist_node hash_node; struct net_device *dev; + struct net *net; /* netns for packet i/o */ int err_count; /* Number of arrived ICMP errors */ unsigned long err_time; /* Time when the last ICMP error diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 3b00d81c8f1e..394cebc96d22 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -304,6 +304,7 @@ static struct net_device *__ip_tunnel_create(struct net *net, tunnel = netdev_priv(dev); tunnel->parms = *parms; + tunnel->net = net; err = register_netdevice(dev); if (err) @@ -453,6 +454,9 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + if (tunnel->net != dev_net(tunnel->dev)) + skb_scrub_packet(skb); + if (tunnel->dev->type == ARPHRD_ETHER) { skb->protocol = eth_type_trans(skb, tunnel->dev); skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); @@ -541,7 +545,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph); } - rt = ip_route_output_tunnel(dev_net(dev), &fl4, + rt = ip_route_output_tunnel(tunnel->net, &fl4, protocol, dst, tnl_params->saddr, tunnel->parms.o_key, @@ -602,6 +606,9 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, } #endif + if (tunnel->net != dev_net(dev)) + skb_scrub_packet(skb); + if (tunnel->err_count > 0) { if (time_before(jiffies, tunnel->err_time + IPTUNNEL_ERR_TIMEO)) { @@ -888,6 +895,7 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], if (ip_tunnel_find(itn, p, dev->type)) return -EEXIST; + nt->net = net; nt->parms = *p; err = register_netdevice(dev); if (err) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index f639866b3dcf..97a0bfe2c293 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -466,14 +466,14 @@ isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) static void ipip6_tunnel_uninit(struct net_device *dev) { - struct net *net = dev_net(dev); - struct sit_net *sitn = net_generic(net, sit_net_id); + struct ip_tunnel *tunnel = netdev_priv(dev); + struct sit_net *sitn = net_generic(tunnel->net, sit_net_id); if (dev == sitn->fb_tunnel_dev) { RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); } else { - ipip6_tunnel_unlink(sitn, netdev_priv(dev)); - ipip6_tunnel_del_prl(netdev_priv(dev), NULL); + ipip6_tunnel_unlink(sitn, tunnel); + ipip6_tunnel_del_prl(tunnel, NULL); } dev_put(dev); } @@ -621,6 +621,8 @@ static int ipip6_rcv(struct sk_buff *skb) tstats->rx_packets++; tstats->rx_bytes += skb->len; + if (tunnel->net != dev_net(tunnel->dev)) + skb_scrub_packet(skb); netif_rx(skb); return 0; @@ -803,7 +805,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, + rt = ip_route_output_ports(tunnel->net, &fl4, NULL, dst, tiph->saddr, 0, 0, IPPROTO_IPV6, RT_TOS(tos), @@ -858,6 +860,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, tunnel->err_count = 0; } + if (tunnel->net != dev_net(dev)) + skb_scrub_packet(skb); + /* * Okay, now see if we can stuff it in the buffer as-is. */ @@ -944,7 +949,8 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) iph = &tunnel->parms.iph; if (iph->daddr) { - struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, + struct rtable *rt = ip_route_output_ports(tunnel->net, &fl4, + NULL, iph->daddr, iph->saddr, 0, 0, IPPROTO_IPV6, @@ -959,7 +965,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) } if (!tdev && tunnel->parms.link) - tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); + tdev = __dev_get_by_index(tunnel->net, tunnel->parms.link); if (tdev) { dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); @@ -972,7 +978,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) { - struct net *net = dev_net(t->dev); + struct net *net = t->net; struct sit_net *sitn = net_generic(net, sit_net_id); ipip6_tunnel_unlink(sitn, t); @@ -1248,7 +1254,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; dev->iflink = 0; dev->addr_len = 4; - dev->features |= NETIF_F_NETNS_LOCAL; dev->features |= NETIF_F_LLTX; } @@ -1257,6 +1262,7 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; + tunnel->net = dev_net(dev); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -1277,6 +1283,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) struct sit_net *sitn = net_generic(net, sit_net_id); tunnel->dev = dev; + tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); iph->version = 4; @@ -1564,8 +1571,14 @@ static struct xfrm_tunnel ipip_handler __read_mostly = { static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) { + struct net *net = dev_net(sitn->fb_tunnel_dev); + struct net_device *dev, *aux; int prio; + for_each_netdev_safe(net, dev, aux) + if (dev->rtnl_link_ops == &sit_link_ops) + unregister_netdevice_queue(dev, head); + for (prio = 1; prio < 4; prio++) { int h; for (h = 0; h < HASH_SIZE; h++) { @@ -1573,7 +1586,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea t = rtnl_dereference(sitn->tunnels[prio][h]); while (t != NULL) { - unregister_netdevice_queue(t->dev, head); + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (dev_net(t->dev) != net) + unregister_netdevice_queue(t->dev, + head); t = rtnl_dereference(t->next); } } @@ -1598,6 +1616,10 @@ static int __net_init sit_init_net(struct net *net) goto err_alloc_dev; } dev_net_set(sitn->fb_tunnel_dev, net); + /* FB netdevice is special: we have one, and only one per netns. + * Allowing to move it to another netns is clearly unsafe. + */ + sitn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; err = ipip6_fb_tunnel_init(sitn->fb_tunnel_dev); if (err) -- GitLab From 3a36515f729458c8efa0c124c7262d5843ad5c37 Mon Sep 17 00:00:00 2001 From: Pablo Neira Date: Fri, 28 Jun 2013 03:04:23 +0200 Subject: [PATCH 1979/2900] netlink: fix splat in skb_clone with large messages Since (c05cdb1 netlink: allow large data transfers from user-space), netlink splats if it invokes skb_clone on large netlink skbs since: * skb_shared_info was not correctly initialized. * skb->destructor is not set in the cloned skb. This was spotted by trinity: [ 894.990671] BUG: unable to handle kernel paging request at ffffc9000047b001 [ 894.991034] IP: [] skb_clone+0x24/0xc0 [...] [ 894.991034] Call Trace: [ 894.991034] [] nl_fib_input+0x6a/0x240 [ 894.991034] [] ? _raw_read_unlock+0x26/0x40 [ 894.991034] [] netlink_unicast+0x169/0x1e0 [ 894.991034] [] netlink_sendmsg+0x251/0x3d0 Fix it by: 1) introducing a new netlink_skb_clone function that is used in nl_fib_input, that sets our special skb->destructor in the cloned skb. Moreover, handle the release of the large cloned skb head area in the destructor path. 2) not allowing large skbuffs in the netlink broadcast path. I cannot find any reasonable use of the large data transfer using netlink in that path, moreover this helps to skip extra skb_clone handling. I found two more netlink clients that are cloning the skbs, but they are not in the sendmsg path. Therefore, the sole client cloning that I found seems to be the fib frontend. Thanks to Eric Dumazet for helping to address this issue. Reported-by: Fengguang Wu Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- include/linux/netlink.h | 16 ++++++++++++++++ net/ipv4/fib_frontend.c | 2 +- net/netlink/af_netlink.c | 35 ++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 86fde81ac2e6..7a6c396a263b 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -85,6 +85,22 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, void netlink_detachskb(struct sock *sk, struct sk_buff *skb); int netlink_sendskb(struct sock *sk, struct sk_buff *skb); +static inline struct sk_buff * +netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask) +{ + struct sk_buff *nskb; + + nskb = skb_clone(skb, gfp_mask); + if (!nskb) + return NULL; + + /* This is a large skb, set destructor callback to release head */ + if (is_vmalloc_addr(skb->head)) + nskb->destructor = skb->destructor; + + return nskb; +} + /* * skb should fit one page. This choice is good for headerless malloc. * But we should limit to 8K so that userspace does not have to diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 05a4888dede9..b3f627ac4ed8 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -961,7 +961,7 @@ static void nl_fib_input(struct sk_buff *skb) nlmsg_len(nlh) < sizeof(*frn)) return; - skb = skb_clone(skb, GFP_KERNEL); + skb = netlink_skb_clone(skb, GFP_KERNEL); if (skb == NULL) return; nlh = nlmsg_hdr(skb); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6967fbcca6c5..0c61b59175dc 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -849,7 +849,10 @@ static void netlink_skb_destructor(struct sk_buff *skb) } #endif if (is_vmalloc_addr(skb->head)) { - vfree(skb->head); + if (!skb->cloned || + !atomic_dec_return(&(skb_shinfo(skb)->dataref))) + vfree(skb->head); + skb->head = NULL; } if (skb->sk != NULL) @@ -1532,33 +1535,31 @@ struct sock *netlink_getsockbyfilp(struct file *filp) return sock; } -static struct sk_buff *netlink_alloc_large_skb(unsigned int size) +static struct sk_buff *netlink_alloc_large_skb(unsigned int size, + int broadcast) { struct sk_buff *skb; void *data; - if (size <= NLMSG_GOODSIZE) + if (size <= NLMSG_GOODSIZE || broadcast) return alloc_skb(size, GFP_KERNEL); - skb = alloc_skb_head(GFP_KERNEL); - if (skb == NULL) - return NULL; + size = SKB_DATA_ALIGN(size) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); data = vmalloc(size); if (data == NULL) - goto err; + return NULL; - skb->head = data; - skb->data = data; - skb_reset_tail_pointer(skb); - skb->end = skb->tail + size; - skb->len = 0; - skb->destructor = netlink_skb_destructor; + skb = build_skb(data, size); + if (skb == NULL) + vfree(data); + else { + skb->head_frag = 0; + skb->destructor = netlink_skb_destructor; + } return skb; -err: - kfree_skb(skb); - return NULL; } /* @@ -2244,7 +2245,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; - skb = netlink_alloc_large_skb(len); + skb = netlink_alloc_large_skb(len, dst_group); if (skb == NULL) goto out; -- GitLab From 8d2ada77f8a7f8f65fcbf71b23cbac54b64151a6 Mon Sep 17 00:00:00 2001 From: "nikolay@redhat.com" Date: Wed, 26 Jun 2013 17:13:37 +0200 Subject: [PATCH 1980/2900] bonding: remove unnecessary setup_by_slave member We have a member called setup_by_slave in struct bonding to denote if the bond dev has different type than ARPHRD_ETHER, but that is already denoted in bond's netdev type variable if it was setup by the slave, so use that instead of the member. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 5 +---- drivers/net/bonding/bonding.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 142d55dc526e..2e8b9f1e2747 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1382,8 +1382,6 @@ static void bond_compute_features(struct bonding *bond) static void bond_setup_by_slave(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = netdev_priv(bond_dev); - bond_dev->header_ops = slave_dev->header_ops; bond_dev->type = slave_dev->type; @@ -1392,7 +1390,6 @@ static void bond_setup_by_slave(struct net_device *bond_dev, memcpy(bond_dev->broadcast, slave_dev->broadcast, slave_dev->addr_len); - bond->setup_by_slave = 1; } /* On bonding slaves other than the currently active slave, suppress @@ -3187,7 +3184,7 @@ static int bond_slave_netdev_event(unsigned long event, switch (event) { case NETDEV_UNREGISTER: - if (bond->setup_by_slave) + if (bond_dev->type != ARPHRD_ETHER) bond_release_and_destroy(bond_dev, slave_dev); else bond_release(bond_dev, slave_dev); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3fb73cc8c34a..c6c8d03562e5 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -226,7 +226,6 @@ struct bonding { rwlock_t lock; rwlock_t curr_slave_lock; u8 send_peer_notif; - s8 setup_by_slave; u8 igmp_retrans; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry; -- GitLab From 97a1e6396b07581249506952a4c417dc6d2a4f9c Mon Sep 17 00:00:00 2001 From: "nikolay@redhat.com" Date: Wed, 26 Jun 2013 17:13:38 +0200 Subject: [PATCH 1981/2900] bonding: remove unnecessary dev_addr_from_first member In struct bonding there's a member called dev_addr_from_first which is used to denote when the bond dev should clone the first slave's MAC address but since we have netdev's addr_assign_type variable that is not necessary. We clone the first slave's MAC each time we have a random MAC set to the bond device. This has the nice side-effect of also fixing an inconsistency - when the MAC address of the bond dev is set after its creation, but prior to having slaves, it's not kept and the first slave's MAC is cloned. The only way to keep the MAC was to create the bond device with the MAC address set (e.g. through ip link). In all cases if the bond device is left without any slaves - its MAC gets reset to a random one as before. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 7 ++----- drivers/net/bonding/bonding.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2e8b9f1e2747..0da3c126c7c4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1596,7 +1596,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* If this is the first slave, then we need to set the master's hardware * address to be the same as the slave's. */ - if (bond->slave_cnt == 0 && bond->dev_addr_from_first) + if (!bond->slave_cnt && bond->dev->addr_assign_type == NET_ADDR_RANDOM) bond_set_dev_addr(bond->dev, slave_dev); new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); @@ -2041,7 +2041,6 @@ static int __bond_release_one(struct net_device *bond_dev, if (bond->slave_cnt == 0) { bond_set_carrier(bond); eth_hw_addr_random(bond_dev); - bond->dev_addr_from_first = true; if (bond_vlan_used(bond)) { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", @@ -4800,10 +4799,8 @@ static int bond_init(struct net_device *bond_dev) /* Ensure valid dev_addr */ if (is_zero_ether_addr(bond_dev->dev_addr) && - bond_dev->addr_assign_type == NET_ADDR_PERM) { + bond_dev->addr_assign_type == NET_ADDR_PERM) eth_hw_addr_random(bond_dev); - bond->dev_addr_from_first = true; - } return 0; } diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c6c8d03562e5..42d1c6599cba 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -248,7 +248,6 @@ struct bonding { /* debugging support via debugfs */ struct dentry *debug_dir; #endif /* CONFIG_DEBUG_FS */ - bool dev_addr_from_first; }; static inline bool bond_vlan_used(struct bonding *bond) -- GitLab From ae0d67505ca30c635f7763564622c9710913f293 Mon Sep 17 00:00:00 2001 From: "nikolay@redhat.com" Date: Wed, 26 Jun 2013 17:13:39 +0200 Subject: [PATCH 1982/2900] bonding: when cloning a MAC use NET_ADDR_STOLEN A simple semantic change, when a slave's MAC is cloned by the bond master then set addr_assign_type to NET_ADDR_STOLEN instead of NET_ADDR_SET. Also use bond_set_dev_addr() in BOND_FOM_ACTIVE mode to change the bond's MAC address because the assign_type has to be set properly. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 0da3c126c7c4..ec44580b076f 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -833,6 +833,24 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, } } +/** + * bond_set_dev_addr - clone slave's address to bond + * @bond_dev: bond net device + * @slave_dev: slave net device + * + * Should be called with RTNL held. + */ +static void bond_set_dev_addr(struct net_device *bond_dev, + struct net_device *slave_dev) +{ + pr_debug("bond_dev=%p\n", bond_dev); + pr_debug("slave_dev=%p\n", slave_dev); + pr_debug("slave_dev->addr_len=%d\n", slave_dev->addr_len); + memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); + bond_dev->addr_assign_type = NET_ADDR_STOLEN; + call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); +} + /* * bond_do_fail_over_mac * @@ -855,11 +873,9 @@ static void bond_do_fail_over_mac(struct bonding *bond, switch (bond->params.fail_over_mac) { case BOND_FOM_ACTIVE: if (new_active) { - memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, - new_active->dev->addr_len); write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); - call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); + bond_set_dev_addr(bond->dev, new_active->dev); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); } @@ -1290,17 +1306,6 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev) /*---------------------------------- IOCTL ----------------------------------*/ -static void bond_set_dev_addr(struct net_device *bond_dev, - struct net_device *slave_dev) -{ - pr_debug("bond_dev=%p\n", bond_dev); - pr_debug("slave_dev=%p\n", slave_dev); - pr_debug("slave_dev->addr_len=%d\n", slave_dev->addr_len); - memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); - bond_dev->addr_assign_type = NET_ADDR_SET; - call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); -} - static netdev_features_t bond_fix_features(struct net_device *dev, netdev_features_t features) { -- GitLab From d0e63ed9411fb9fe95dac1690deb01f9ccb1701d Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 26 Jun 2013 14:02:18 +0400 Subject: [PATCH 1983/2900] ARC: [plat-arcfpga] Enable arc_emac for ARCAngle4 Board * Add arc_emac to DeviceTree DT description "Documentation/devicetree/bindings/net/arc_emac.txt". * Update defconfig correspondingly [vgupta: tweaked changelog] Signed-off-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/angel4.dts | 16 ++++++++++++++++ arch/arc/configs/fpga_defconfig | 3 +++ arch/arc/plat-arcfpga/include/plat/irq.h | 2 -- arch/arc/plat-arcfpga/include/plat/memmap.h | 2 -- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts index bae4f936cb03..4fb2d6f655bd 100644 --- a/arch/arc/boot/dts/angel4.dts +++ b/arch/arc/boot/dts/angel4.dts @@ -51,5 +51,21 @@ current-speed = <115200>; status = "okay"; }; + + ethernet@c0fc2000 { + compatible = "snps,arc-emac"; + reg = <0xc0fc2000 0x3c>; + interrupts = <6>; + mac-address = [ 00 11 22 33 44 55 ]; + clock-frequency = <80000000>; + max-speed = <100>; + phy = <&phy0>; + + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <1>; + }; + }; }; }; diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig index 95350be6ef6f..2c8ee30e2756 100644 --- a/arch/arc/configs/fpga_defconfig +++ b/arch/arc/configs/fpga_defconfig @@ -38,6 +38,9 @@ CONFIG_INET=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FIRMWARE_IN_KERNEL is not set # CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +CONFIG_ARC_EMAC=y +CONFIG_LXT_PHY=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h index 41e335670f60..6adbc53c3a5b 100644 --- a/arch/arc/plat-arcfpga/include/plat/irq.h +++ b/arch/arc/plat-arcfpga/include/plat/irq.h @@ -16,8 +16,6 @@ #define UART1_IRQ 10 #define UART2_IRQ 11 -#define VMAC_IRQ 6 - #define IDE_IRQ 13 #define PCI_IRQ 14 #define PS2_IRQ 15 diff --git a/arch/arc/plat-arcfpga/include/plat/memmap.h b/arch/arc/plat-arcfpga/include/plat/memmap.h index 1663f3388085..5c78e6135a1f 100644 --- a/arch/arc/plat-arcfpga/include/plat/memmap.h +++ b/arch/arc/plat-arcfpga/include/plat/memmap.h @@ -15,8 +15,6 @@ #define UART0_BASE 0xC0FC1000 #define UART1_BASE 0xC0FC1100 -#define VMAC_REG_BASEADDR 0xC0FC2000 - #define IDE_CONTROLLER_BASE 0xC0FC9000 #define AHB_PCI_HOST_BRG_BASE 0xC0FD0000 -- GitLab From 723e2b801d803035ec7a7c0fe162a6c9fc118164 Mon Sep 17 00:00:00 2001 From: Christian Ruppert Date: Wed, 26 Jun 2013 16:01:28 +0200 Subject: [PATCH 1984/2900] ARC: [TB10x] Updates for irqchip driver Device tree and Kconfig updates for irqchip driver. Signed-off-by: Christian Ruppert Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/abilis_tb100.dtsi | 32 +++++++++++++---------------- arch/arc/boot/dts/abilis_tb101.dtsi | 32 +++++++++++++---------------- arch/arc/boot/dts/abilis_tb10x.dtsi | 32 +++++++++++++---------------- arch/arc/plat-tb10x/Kconfig | 1 + 4 files changed, 43 insertions(+), 54 deletions(-) diff --git a/arch/arc/boot/dts/abilis_tb100.dtsi b/arch/arc/boot/dts/abilis_tb100.dtsi index 941ad118a7e7..d9f8249aa66e 100644 --- a/arch/arc/boot/dts/abilis_tb100.dtsi +++ b/arch/arc/boot/dts/abilis_tb100.dtsi @@ -21,10 +21,6 @@ /include/ "abilis_tb10x.dtsi" -/* interrupt specifiers - * -------------------- - * 0: rising, 1: low, 2: high, 3: falling, - */ / { clock-frequency = <500000000>; /* 500 MHZ */ @@ -173,7 +169,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF140000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -185,7 +181,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF141000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -197,7 +193,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF142000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -209,7 +205,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF143000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -221,7 +217,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF144000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -233,7 +229,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF145000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -245,7 +241,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF146000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -257,7 +253,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF147000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -269,7 +265,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF148000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -281,7 +277,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF149000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -293,7 +289,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14A000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -305,7 +301,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14B000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -317,7 +313,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14C000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -329,7 +325,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14D000 0x1000>; gpio-controller; #gpio-cells = <1>; diff --git a/arch/arc/boot/dts/abilis_tb101.dtsi b/arch/arc/boot/dts/abilis_tb101.dtsi index fd25c212049f..da8ca7941e67 100644 --- a/arch/arc/boot/dts/abilis_tb101.dtsi +++ b/arch/arc/boot/dts/abilis_tb101.dtsi @@ -21,10 +21,6 @@ /include/ "abilis_tb10x.dtsi" -/* interrupt specifiers - * -------------------- - * 0: rising, 1: low, 2: high, 3: falling, - */ / { clock-frequency = <500000000>; /* 500 MHZ */ @@ -182,7 +178,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF140000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -194,7 +190,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF141000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -206,7 +202,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF142000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -218,7 +214,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF143000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -230,7 +226,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF144000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -242,7 +238,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF145000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -254,7 +250,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF146000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -266,7 +262,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF147000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -278,7 +274,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF148000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -290,7 +286,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF149000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -302,7 +298,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14A000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -314,7 +310,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14B000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -326,7 +322,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14C000 0x1000>; gpio-controller; #gpio-cells = <1>; @@ -338,7 +334,7 @@ interrupt-controller; #interrupt-cells = <1>; interrupt-parent = <&tb10x_ictl>; - interrupts = <27 1>; + interrupts = <27 2>; reg = <0xFF14D000 0x1000>; gpio-controller; #gpio-cells = <1>; diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi index b97e3051ba4b..edf56f4749e1 100644 --- a/arch/arc/boot/dts/abilis_tb10x.dtsi +++ b/arch/arc/boot/dts/abilis_tb10x.dtsi @@ -19,10 +19,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* interrupt specifiers - * -------------------- - * 0: rising, 1: low, 2: high, 3: falling, - */ / { compatible = "abilis,arc-tb10x"; @@ -78,7 +74,7 @@ #interrupt-cells = <1>; }; tb10x_ictl: pic@fe002000 { - compatible = "abilis,tb10x_ictl"; + compatible = "abilis,tb10x-ictl"; reg = <0xFE002000 0x20>; interrupt-controller; #interrupt-cells = <2>; @@ -91,7 +87,7 @@ compatible = "snps,dw-apb-uart"; reg = <0xFF100000 0x100>; clock-frequency = <166666666>; - interrupts = <25 1>; + interrupts = <25 8>; reg-shift = <2>; reg-io-width = <4>; interrupt-parent = <&tb10x_ictl>; @@ -100,7 +96,7 @@ compatible = "snps,dwmac-3.70a","snps,dwmac"; reg = <0xFE100000 0x1058>; interrupt-parent = <&tb10x_ictl>; - interrupts = <6 1>; + interrupts = <6 8>; interrupt-names = "macirq"; clocks = <&ahb_clk>; clock-names = "stmmaceth"; @@ -109,7 +105,7 @@ compatible = "snps,dma-spear1340"; reg = <0xFE000000 0x400>; interrupt-parent = <&tb10x_ictl>; - interrupts = <14 1>; + interrupts = <14 8>; dma-channels = <6>; dma-requests = <0>; dma-masters = <1>; @@ -128,7 +124,7 @@ compatible = "snps,designware-i2c"; reg = <0xFF120000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <12 1>; + interrupts = <12 8>; clocks = <&ahb_clk>; }; i2c1: i2c@FF121000 { @@ -137,7 +133,7 @@ compatible = "snps,designware-i2c"; reg = <0xFF121000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <12 1>; + interrupts = <12 8>; clocks = <&ahb_clk>; }; i2c2: i2c@FF122000 { @@ -146,7 +142,7 @@ compatible = "snps,designware-i2c"; reg = <0xFF122000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <12 1>; + interrupts = <12 8>; clocks = <&ahb_clk>; }; i2c3: i2c@FF123000 { @@ -155,7 +151,7 @@ compatible = "snps,designware-i2c"; reg = <0xFF123000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <12 1>; + interrupts = <12 8>; clocks = <&ahb_clk>; }; i2c4: i2c@FF124000 { @@ -164,7 +160,7 @@ compatible = "snps,designware-i2c"; reg = <0xFF124000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <12 1>; + interrupts = <12 8>; clocks = <&ahb_clk>; }; @@ -176,7 +172,7 @@ num-cs = <1>; reg = <0xFE010000 0x20>; interrupt-parent = <&tb10x_ictl>; - interrupts = <26 1>; + interrupts = <26 8>; clocks = <&ahb_clk>; }; spi1: spi@0xFE011000 { @@ -187,7 +183,7 @@ num-cs = <2>; reg = <0xFE011000 0x20>; interrupt-parent = <&tb10x_ictl>; - interrupts = <10 1>; + interrupts = <10 8>; clocks = <&ahb_clk>; }; @@ -195,7 +191,7 @@ compatible = "abilis,tb100-tsm"; reg = <0xff316000 0x400>; interrupt-parent = <&tb10x_ictl>; - interrupts = <17 1>; + interrupts = <17 8>; output-clkdiv = <4>; global-packet-delay = <0x21>; port-packet-delay = <0>; @@ -213,7 +209,7 @@ "cpuctrl", "a6it_int_force"; interrupt-parent = <&tb10x_ictl>; - interrupts = <20 1>, <19 1>; + interrupts = <20 2>, <19 2>; interrupt-names = "cmd_irq", "event_irq"; }; tb10x_mdsc0: tb10x-mdscr@FF300000 { @@ -239,7 +235,7 @@ compatible = "abilis,tb100-wfb"; reg = <0xff319000 0x1000>; interrupt-parent = <&tb10x_ictl>; - interrupts = <16 1>; + interrupts = <16 8>; }; }; }; diff --git a/arch/arc/plat-tb10x/Kconfig b/arch/arc/plat-tb10x/Kconfig index 1d3452100f1f..1ab386bb5da8 100644 --- a/arch/arc/plat-tb10x/Kconfig +++ b/arch/arc/plat-tb10x/Kconfig @@ -22,6 +22,7 @@ menuconfig ARC_PLAT_TB10X select PINCTRL select PINMUX select ARCH_REQUIRE_GPIOLIB + select TB10X_IRQC help Support for platforms based on the TB10x home media gateway SOC by Abilis Systems. TB10x is based on the ARC700 CPU architecture. -- GitLab From a5faeaf9109578e65e1a32e2a3e76c8b47e7dcb6 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 28 Jun 2013 16:04:02 +0200 Subject: [PATCH 1985/2900] writeback: Fix periodic writeback after fs mount Code in blkdev.c moves a device inode to default_backing_dev_info when the last reference to the device is put and moves the device inode back to its bdi when the first reference is acquired. This includes moving to wb.b_dirty list if the device inode is dirty. The code however doesn't setup timer to wake corresponding flusher thread and while wb.b_dirty list is non-empty __mark_inode_dirty() will not set it up either. Thus periodic writeback is effectively disabled until a sync(2) call which can lead to unexpected data loss in case of crash or power failure. Fix the problem by setting up a timer for periodic writeback in case we add the first dirty inode to wb.b_dirty list in bdev_inode_switch_bdi(). Reported-by: Bert De Jonghe CC: stable@vger.kernel.org # >= 3.0 Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- fs/block_dev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 2091db8cdd78..85f5c85ec91c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -58,17 +58,24 @@ static void bdev_inode_switch_bdi(struct inode *inode, struct backing_dev_info *dst) { struct backing_dev_info *old = inode->i_data.backing_dev_info; + bool wakeup_bdi = false; if (unlikely(dst == old)) /* deadlock avoidance */ return; bdi_lock_two(&old->wb, &dst->wb); spin_lock(&inode->i_lock); inode->i_data.backing_dev_info = dst; - if (inode->i_state & I_DIRTY) + if (inode->i_state & I_DIRTY) { + if (bdi_cap_writeback_dirty(dst) && !wb_has_dirty_io(&dst->wb)) + wakeup_bdi = true; list_move(&inode->i_wb_list, &dst->wb.b_dirty); + } spin_unlock(&inode->i_lock); spin_unlock(&old->wb.list_lock); spin_unlock(&dst->wb.list_lock); + + if (wakeup_bdi) + bdi_wakeup_thread_delayed(dst); } /* Kill _all_ buffers and pagecache , dirty or not.. */ -- GitLab From c4d6e6310b90422473f8bd5f9c8d3548f65a38da Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 24 Jun 2013 05:08:05 -0300 Subject: [PATCH 1986/2900] [media] V4L2: sh_vou: add I2C build dependency The sh_vou driver needs CONFIG_I2C or CONFIG_I2C_MODULE to build, add the respective dependency. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 0494d2769fd7..bd99e5055fa1 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -36,7 +36,7 @@ source "drivers/media/platform/blackfin/Kconfig" config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on MEDIA_CAMERA_SUPPORT - depends on VIDEO_DEV && ARCH_SHMOBILE + depends on VIDEO_DEV && ARCH_SHMOBILE && I2C select VIDEOBUF_DMA_CONTIG help Support for the Video Output Unit (VOU) on SuperH SoCs. -- GitLab From fe05e141a4d70d9417fd628133ecb32851f2e136 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 24 Jun 2013 05:13:51 -0300 Subject: [PATCH 1987/2900] [media] V4L2: fix compilation if CONFIG_I2C is undefined i2c_verify_client() is only available, if I2C is enabled. Fix v4l2-async.c compilation if I2C is disabled. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index c80ffb4ba567..aae241730caa 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -24,11 +24,15 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) { +#if IS_ENABLED(CONFIG_I2C) struct i2c_client *client = i2c_verify_client(dev); return client && asd->bus_type == V4L2_ASYNC_BUS_I2C && asd->match.i2c.adapter_id == client->adapter->nr && asd->match.i2c.address == client->addr; +#else + return false; +#endif } static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd) -- GitLab From f687f3263e99e34289e076352fad23974ee072ab Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 24 Jun 2013 05:19:19 -0300 Subject: [PATCH 1988/2900] [media] V4L2: soc-camera: fix uninitialised use compiler warning In scan_async_group() if the size parameter is negative, the sasd pointer will be used uninitialised: drivers/media/platform/soc_camera/soc_camera.c: In function "soc_camera_host_register": drivers/media/platform/soc_camera/soc_camera.c:1514:55: warning: "sasd" may be used uninitialized in this function [-Wmaybe-uninitialized] sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address); ^ drivers/media/platform/soc_camera/soc_camera.c:1464:34: note: "sasd" was declared here struct soc_camera_async_subdev *sasd; Fix this by making "size" and the array, from which it is assigned unsigned. Signed-off-by: Guennadi Liakhovetski Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/soc_camera.c | 2 +- include/media/sh_mobile_ceu.h | 2 +- include/media/soc_camera.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 2e47b5127d4b..2dd0e5272941 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -1459,7 +1459,7 @@ static int soc_camera_async_complete(struct v4l2_async_notifier *notifier) } static int scan_async_group(struct soc_camera_host *ici, - struct v4l2_async_subdev **asd, int size) + struct v4l2_async_subdev **asd, unsigned int size) { struct soc_camera_async_subdev *sasd; struct soc_camera_async_client *sasc; diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index 8937241e5f37..7f57056c22ba 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h @@ -23,7 +23,7 @@ struct sh_mobile_ceu_info { int max_height; struct sh_mobile_ceu_companion *csi2; struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ - int *asd_sizes; /* 0-terminated array pf asd group sizes */ + unsigned int *asd_sizes; /* 0-terminated array pf asd group sizes */ }; #endif /* __ASM_SH_MOBILE_CEU_H__ */ diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 906ed98c6e95..34d2414f2b8c 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -87,7 +87,7 @@ struct soc_camera_host { const char *drv_name; struct soc_camera_host_ops *ops; struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ - int *asd_sizes; /* 0-terminated array of asd group sizes */ + unsigned int *asd_sizes; /* 0-terminated array of asd group sizes */ }; struct soc_camera_host_ops { -- GitLab From c67f1a300a72a67c1fa71cada8380bbe8412d046 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 17 Jun 2013 02:50:33 -0300 Subject: [PATCH 1989/2900] [media] V4L2: add documentation for V4L2 clock helpers and asynchronous probing Add documentation for the V4L2 clock and V4L2 asynchronous probing APIs to v4l2-framework.txt. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 73 +++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index b5e6347b720f..6c4866b49eb5 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -325,8 +325,27 @@ that width, height and the media bus pixel code are equal on both source and sink of the link. Subdev drivers are also free to use this function to perform the checks mentioned above in addition to their own checks. -A device (bridge) driver needs to register the v4l2_subdev with the -v4l2_device: +There are currently two ways to register subdevices with the V4L2 core. The +first (traditional) possibility is to have subdevices registered by bridge +drivers. This can be done when the bridge driver has the complete information +about subdevices connected to it and knows exactly when to register them. This +is typically the case for internal subdevices, like video data processing units +within SoCs or complex PCI(e) boards, camera sensors in USB cameras or connected +to SoCs, which pass information about them to bridge drivers, usually in their +platform data. + +There are however also situations where subdevices have to be registered +asynchronously to bridge devices. An example of such a configuration is a Device +Tree based system where information about subdevices is made available to the +system independently from the bridge devices, e.g. when subdevices are defined +in DT as I2C device nodes. The API used in this second case is described further +below. + +Using one or the other registration method only affects the probing process, the +run-time bridge-subdevice interaction is in both cases the same. + +In the synchronous case a device (bridge) driver needs to register the +v4l2_subdev with the v4l2_device: int err = v4l2_device_register_subdev(v4l2_dev, sd); @@ -393,6 +412,30 @@ controlled through GPIO pins. This distinction is only relevant when setting up the device, but once the subdev is registered it is completely transparent. +In the asynchronous case subdevice probing can be invoked independently of the +bridge driver availability. The subdevice driver then has to verify whether all +the requirements for a successful probing are satisfied. This can include a +check for a master clock availability. If any of the conditions aren't satisfied +the driver might decide to return -EPROBE_DEFER to request further reprobing +attempts. Once all conditions are met the subdevice shall be registered using +the v4l2_async_register_subdev() function. Unregistration is performed using +the v4l2_async_unregister_subdev() call. Subdevices registered this way are +stored in a global list of subdevices, ready to be picked up by bridge drivers. + +Bridge drivers in turn have to register a notifier object with an array of +subdevice descriptors that the bridge device needs for its operation. This is +performed using the v4l2_async_notifier_register() call. To unregister the +notifier the driver has to call v4l2_async_notifier_unregister(). The former of +the two functions takes two arguments: a pointer to struct v4l2_device and a +pointer to struct v4l2_async_notifier. The latter contains a pointer to an array +of pointers to subdevice descriptors of type struct v4l2_async_subdev type. The +V4L2 core will then use these descriptors to match asynchronously registered +subdevices to them. If a match is detected the .bound() notifier callback is +called. After all subdevices have been located the .complete() callback is +called. When a subdevice is removed from the system the .unbind() method is +called. All three callbacks are optional. + + V4L2 sub-device userspace API ----------------------------- @@ -1065,3 +1108,29 @@ available event type is 'class base + 1'. An example on how the V4L2 events may be used can be found in the OMAP 3 ISP driver (drivers/media/platform/omap3isp). + + +V4L2 clocks +----------- + +Many subdevices, like camera sensors, TV decoders and encoders, need a clock +signal to be supplied by the system. Often this clock is supplied by the +respective bridge device. The Linux kernel provides a Common Clock Framework for +this purpose. However, it is not (yet) available on all architectures. Besides, +the nature of the multi-functional (clock, data + synchronisation, I2C control) +connection of subdevices to the system might impose special requirements on the +clock API usage. E.g. V4L2 has to support clock provider driver unregistration +while a subdevice driver is holding a reference to the clock. For these reasons +a V4L2 clock helper API has been developed and is provided to bridge and +subdevice drivers. + +The API consists of two parts: two functions to register and unregister a V4L2 +clock source: v4l2_clk_register() and v4l2_clk_unregister() and calls to control +a clock object, similar to the respective generic clock API calls: +v4l2_clk_get(), v4l2_clk_put(), v4l2_clk_enable(), v4l2_clk_disable(), +v4l2_clk_get_rate(), and v4l2_clk_set_rate(). Clock suppliers have to provide +clock operations that will be called when clock users invoke respective API +methods. + +It is expected that once the CCF becomes available on all relevant +architectures this API will be removed. -- GitLab From eca430c83d3b63df52024d114b7641bd03482f38 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 24 Apr 2013 11:15:30 -0300 Subject: [PATCH 1990/2900] [media] V4L2: sh_mobile_ceu_camera: remove CEU specific data from generic functions Several functions in the sh_mobile_ceu_camera driver implement generic algorithms and can be re-used by other V4L2 camera host drivers too. These functions attempt to optimise scaling and cropping functions of the subdevice, e.g. a camera sensor. This patch makes those functions generic for future re-use by other camera host drivers. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- .../soc_camera/sh_mobile_ceu_camera.c | 130 ++++++++++-------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index d1b410b75cc1..e5b99a889925 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -1005,7 +1005,7 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } -static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); +static int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); static struct soc_camera_device *ctrl_to_icd(struct v4l2_ctrl *ctrl) { @@ -1084,7 +1084,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int /* FIXME: subwindow is lost between close / open */ /* Cache current client geometry */ - ret = client_g_rect(sd, &rect); + ret = soc_camera_client_g_rect(sd, &rect); if (ret < 0) return ret; @@ -1208,18 +1208,23 @@ static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) r1->top + r1->height < r2->top + r2->height; } -static unsigned int scale_down(unsigned int size, unsigned int scale) +static unsigned int soc_camera_shift_scale(unsigned int size, unsigned int shift, + unsigned int scale) { - return (size * 4096 + scale / 2) / scale; + return ((size << shift) + scale / 2) / scale; } -static unsigned int calc_generic_scale(unsigned int input, unsigned int output) +static unsigned int soc_camera_calc_scale(unsigned int input, unsigned int shift, + unsigned int output) { - return (input * 4096 + output / 2) / output; + return soc_camera_shift_scale(input, shift, output); } +#define scale_down(size, scale) soc_camera_shift_scale(size, 12, scale) +#define calc_generic_scale(in, out) soc_camera_shift_scale(in, 12, out) + /* Get and store current client crop */ -static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) +static int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) { struct v4l2_crop crop; struct v4l2_cropcap cap; @@ -1244,10 +1249,8 @@ static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) } /* Client crop has changed, update our sub-rectangle to remain within the area */ -static void update_subrect(struct sh_mobile_ceu_cam *cam) +static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) { - struct v4l2_rect *rect = &cam->rect, *subrect = &cam->subrect; - if (rect->width < subrect->width) subrect->width = rect->width; @@ -1275,19 +1278,18 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam) * 2. if (1) failed, try to double the client image until we get one big enough * 3. if (2) failed, try to request the maximum image */ -static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, - struct v4l2_crop *cam_crop) +static int soc_camera_client_s_crop(struct v4l2_subdev *sd, + struct v4l2_crop *crop, struct v4l2_crop *cam_crop, + struct v4l2_rect *target_rect, struct v4l2_rect *subrect) { - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; struct device *dev = sd->v4l2_dev->dev; - struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_cropcap cap; int ret; unsigned int width, height; v4l2_subdev_call(sd, video, s_crop, crop); - ret = client_g_rect(sd, cam_rect); + ret = soc_camera_client_g_rect(sd, cam_rect); if (ret < 0) return ret; @@ -1299,7 +1301,7 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, /* Even if camera S_CROP failed, but camera rectangle matches */ dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", rect->width, rect->height, rect->left, rect->top); - cam->rect = *cam_rect; + *target_rect = *cam_rect; return 0; } @@ -1365,7 +1367,7 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, cam_rect->top; v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = client_g_rect(sd, cam_rect); + ret = soc_camera_client_g_rect(sd, cam_rect); dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); @@ -1379,15 +1381,15 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, */ *cam_rect = cap.bounds; v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = client_g_rect(sd, cam_rect); + ret = soc_camera_client_g_rect(sd, cam_rect); dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, cam_rect->width, cam_rect->height, cam_rect->left, cam_rect->top); } if (!ret) { - cam->rect = *cam_rect; - update_subrect(cam); + *target_rect = *cam_rect; + update_subrect(target_rect, subrect); } return ret; @@ -1395,15 +1397,13 @@ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, /* Iterative s_mbus_fmt, also updates cached client crop on success */ static int client_s_fmt(struct soc_camera_device *icd, - struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) + struct v4l2_rect *rect, struct v4l2_rect *subrect, + unsigned int max_width, unsigned int max_height, + struct v4l2_mbus_framefmt *mf, bool host_can_scale) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct sh_mobile_ceu_cam *cam = icd->host_priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->parent; unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; - unsigned int max_width, max_height; struct v4l2_cropcap cap; bool ceu_1to1; int ret; @@ -1423,7 +1423,7 @@ static int client_s_fmt(struct soc_camera_device *icd, } ceu_1to1 = false; - if (!ceu_can_scale) + if (!host_can_scale) goto update_cache; cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -1432,8 +1432,10 @@ static int client_s_fmt(struct soc_camera_device *icd, if (ret < 0) return ret; - max_width = min(cap.bounds.width, pcdev->max_width); - max_height = min(cap.bounds.height, pcdev->max_height); + if (max_width > cap.bounds.width) + max_width = cap.bounds.width; + if (max_height > cap.bounds.height) + max_height = cap.bounds.height; /* Camera set a format, but geometry is not precise, try to improve */ tmp_w = mf->width; @@ -1460,29 +1462,36 @@ static int client_s_fmt(struct soc_camera_device *icd, update_cache: /* Update cache */ - ret = client_g_rect(sd, &cam->rect); + ret = soc_camera_client_g_rect(sd, rect); if (ret < 0) return ret; if (ceu_1to1) - cam->subrect = cam->rect; + *subrect = *rect; else - update_subrect(cam); + update_subrect(rect, subrect); return 0; } /** - * @width - on output: user width, mapped back to input - * @height - on output: user height, mapped back to input + * @icd - soc-camera device + * @rect - camera cropping window + * @subrect - part of rect, sent to the user * @mf - in- / output camera output window + * @width - on input: max host input width + * on output: user width, mapped back to input + * @height - on input: max host input height + * on output: user height, mapped back to input + * @host_can_scale - host can scale this pixel format + * @shift - shift, used for scaling */ -static int client_scale(struct soc_camera_device *icd, +static int soc_camera_client_scale(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, struct v4l2_mbus_framefmt *mf, unsigned int *width, unsigned int *height, - bool ceu_can_scale) + bool host_can_scale, unsigned int shift) { - struct sh_mobile_ceu_cam *cam = icd->host_priv; struct device *dev = icd->parent; struct v4l2_mbus_framefmt mf_tmp = *mf; unsigned int scale_h, scale_v; @@ -1492,7 +1501,8 @@ static int client_scale(struct soc_camera_device *icd, * 5. Apply iterative camera S_FMT for camera user window (also updates * client crop cache and the imaginary sub-rectangle). */ - ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); + ret = client_s_fmt(icd, rect, subrect, *width, *height, + &mf_tmp, host_can_scale); if (ret < 0) return ret; @@ -1504,8 +1514,8 @@ static int client_scale(struct soc_camera_device *icd, /* unneeded - it is already in "mf_tmp" */ /* 7. Calculate new client scales. */ - scale_h = calc_generic_scale(cam->rect.width, mf_tmp.width); - scale_v = calc_generic_scale(cam->rect.height, mf_tmp.height); + scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp.width); + scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp.height); mf->width = mf_tmp.width; mf->height = mf_tmp.height; @@ -1515,8 +1525,8 @@ static int client_scale(struct soc_camera_device *icd, * 8. Calculate new CEU crop - apply camera scales to previously * updated "effective" crop. */ - *width = scale_down(cam->subrect.width, scale_h); - *height = scale_down(cam->subrect.height, scale_v); + *width = soc_camera_shift_scale(subrect->width, shift, scale_h); + *height = soc_camera_shift_scale(subrect->height, shift, scale_v); dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); @@ -1559,7 +1569,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * 1. - 2. Apply iterative camera S_CROP for new input window, read back * actual camera rectangle. */ - ret = client_s_crop(icd, &a_writable, &cam_crop); + ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, + &cam->rect, &cam->subrect); if (ret < 0) return ret; @@ -1683,16 +1694,16 @@ static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, * client crop. New scales are calculated from the requested output format and * CEU crop, mapped backed onto the client input (subrect). */ -static void calculate_client_output(struct soc_camera_device *icd, - const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf) +static void soc_camera_calc_client_output(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, + unsigned int shift) { - struct sh_mobile_ceu_cam *cam = icd->host_priv; struct device *dev = icd->parent; - struct v4l2_rect *cam_subrect = &cam->subrect; unsigned int scale_v, scale_h; - if (cam_subrect->width == cam->rect.width && - cam_subrect->height == cam->rect.height) { + if (subrect->width == rect->width && + subrect->height == rect->height) { /* No sub-cropping */ mf->width = pix->width; mf->height = pix->height; @@ -1702,8 +1713,8 @@ static void calculate_client_output(struct soc_camera_device *icd, /* 1.-2. Current camera scales and subwin - cached. */ dev_geo(dev, "2: subwin %ux%u@%u:%u\n", - cam_subrect->width, cam_subrect->height, - cam_subrect->left, cam_subrect->top); + subrect->width, subrect->height, + subrect->left, subrect->top); /* * 3. Calculate new combined scales from input sub-window to requested @@ -1714,8 +1725,8 @@ static void calculate_client_output(struct soc_camera_device *icd, * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF * (128x96) or larger than VGA */ - scale_h = calc_generic_scale(cam_subrect->width, pix->width); - scale_v = calc_generic_scale(cam_subrect->height, pix->height); + scale_h = soc_camera_calc_scale(subrect->width, shift, pix->width); + scale_v = soc_camera_calc_scale(subrect->height, shift, pix->height); dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); @@ -1723,8 +1734,8 @@ static void calculate_client_output(struct soc_camera_device *icd, * 4. Calculate desired client output window by applying combined scales * to client (real) input window. */ - mf->width = scale_down(cam->rect.width, scale_h); - mf->height = scale_down(cam->rect.height, scale_v); + mf->width = soc_camera_shift_scale(rect->width, shift, scale_h); + mf->height = soc_camera_shift_scale(rect->height, shift, scale_v); } /* Similar to set_crop multistage iterative algorithm */ @@ -1739,8 +1750,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_mbus_framefmt mf; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - /* Keep Compiler Happy */ - unsigned int ceu_sub_width = 0, ceu_sub_height = 0; + unsigned int ceu_sub_width = pcdev->max_width, + ceu_sub_height = pcdev->max_height; u16 scale_v, scale_h; int ret; bool image_mode; @@ -1767,7 +1778,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, } /* 1.-4. Calculate desired client output geometry */ - calculate_client_output(icd, pix, &mf); + soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, 12); mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; @@ -1789,8 +1800,9 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); /* 5. - 9. */ - ret = client_scale(icd, &mf, &ceu_sub_width, &ceu_sub_height, - image_mode && V4L2_FIELD_NONE == field); + ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, + &mf, &ceu_sub_width, &ceu_sub_height, + image_mode && V4L2_FIELD_NONE == field, 12); dev_geo(dev, "5-9: client scale return %d\n", ret); -- GitLab From 22e0099ac9a968a4a67fc681864a9ff453bd929f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 25 Apr 2013 08:18:45 -0300 Subject: [PATCH 1991/2900] [media] V4L2: soc-camera: move generic functions into a separate file The sh_mobile_ceu_camera driver implements a generic algorithm for setting up an optimal client and host scaling and cropping configuration. This patch makes those functions available for all drivers. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 4 + drivers/media/platform/soc_camera/Makefile | 4 + .../soc_camera/sh_mobile_ceu_camera.c | 391 +---------------- .../platform/soc_camera/soc_scale_crop.c | 401 ++++++++++++++++++ .../platform/soc_camera/soc_scale_crop.h | 47 ++ 5 files changed, 459 insertions(+), 388 deletions(-) create mode 100644 drivers/media/platform/soc_camera/soc_scale_crop.c create mode 100644 drivers/media/platform/soc_camera/soc_scale_crop.h diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index ffd00106b205..626dcccc37da 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -8,6 +8,9 @@ config SOC_CAMERA over a bus like PCI or USB. For example some i2c camera connected directly to the data bus of an SoC. +config SOC_CAMERA_SCALE_CROP + tristate + config SOC_CAMERA_PLATFORM tristate "platform camera support" depends on SOC_CAMERA @@ -51,6 +54,7 @@ config VIDEO_SH_MOBILE_CEU tristate "SuperH Mobile CEU Interface driver" depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK select VIDEOBUF2_DMA_CONTIG + select SOC_CAMERA_SCALE_CROP ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index bedb0428852b..39186224c16a 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -1,4 +1,8 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o +obj-$(CONFIG_SOC_CAMERA_SCALE_CROP) += soc_scale_crop.o + +# a platform subdevice driver stub, allowing to support cameras by adding a +# couple of callback functions to the board code obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o # soc-camera host drivers have to be linked after camera drivers diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index e5b99a889925..f2de0066089a 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -46,6 +46,8 @@ #include #include +#include "soc_scale_crop.h" + /* register offsets for sh7722 / sh7723 */ #define CAPSR 0x00 /* Capture start register */ @@ -1005,8 +1007,6 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } -static int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); - static struct soc_camera_device *ctrl_to_icd(struct v4l2_ctrl *ctrl) { return container_of(ctrl->handler, struct soc_camera_device, @@ -1194,344 +1194,8 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) icd->host_priv = NULL; } -/* Check if any dimension of r1 is smaller than respective one of r2 */ -static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - return r1->width < r2->width || r1->height < r2->height; -} - -/* Check if r1 fails to cover r2 */ -static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - return r1->left > r2->left || r1->top > r2->top || - r1->left + r1->width < r2->left + r2->width || - r1->top + r1->height < r2->top + r2->height; -} - -static unsigned int soc_camera_shift_scale(unsigned int size, unsigned int shift, - unsigned int scale) -{ - return ((size << shift) + scale / 2) / scale; -} - -static unsigned int soc_camera_calc_scale(unsigned int input, unsigned int shift, - unsigned int output) -{ - return soc_camera_shift_scale(input, shift, output); -} - #define scale_down(size, scale) soc_camera_shift_scale(size, 12, scale) -#define calc_generic_scale(in, out) soc_camera_shift_scale(in, 12, out) - -/* Get and store current client crop */ -static int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) -{ - struct v4l2_crop crop; - struct v4l2_cropcap cap; - int ret; - - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_crop, &crop); - if (!ret) { - *rect = crop.c; - return ret; - } - - /* Camera driver doesn't support .g_crop(), assume default rectangle */ - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (!ret) - *rect = cap.defrect; - - return ret; -} - -/* Client crop has changed, update our sub-rectangle to remain within the area */ -static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) -{ - if (rect->width < subrect->width) - subrect->width = rect->width; - - if (rect->height < subrect->height) - subrect->height = rect->height; - - if (rect->left > subrect->left) - subrect->left = rect->left; - else if (rect->left + rect->width > - subrect->left + subrect->width) - subrect->left = rect->left + rect->width - - subrect->width; - - if (rect->top > subrect->top) - subrect->top = rect->top; - else if (rect->top + rect->height > - subrect->top + subrect->height) - subrect->top = rect->top + rect->height - - subrect->height; -} - -/* - * The common for both scaling and cropping iterative approach is: - * 1. try if the client can produce exactly what requested by the user - * 2. if (1) failed, try to double the client image until we get one big enough - * 3. if (2) failed, try to request the maximum image - */ -static int soc_camera_client_s_crop(struct v4l2_subdev *sd, - struct v4l2_crop *crop, struct v4l2_crop *cam_crop, - struct v4l2_rect *target_rect, struct v4l2_rect *subrect) -{ - struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; - struct device *dev = sd->v4l2_dev->dev; - struct v4l2_cropcap cap; - int ret; - unsigned int width, height; - - v4l2_subdev_call(sd, video, s_crop, crop); - ret = soc_camera_client_g_rect(sd, cam_rect); - if (ret < 0) - return ret; - - /* - * Now cam_crop contains the current camera input rectangle, and it must - * be within camera cropcap bounds - */ - if (!memcmp(rect, cam_rect, sizeof(*rect))) { - /* Even if camera S_CROP failed, but camera rectangle matches */ - dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", - rect->width, rect->height, rect->left, rect->top); - *target_rect = *cam_rect; - return 0; - } - - /* Try to fix cropping, that camera hasn't managed to set */ - dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top, - rect->width, rect->height, rect->left, rect->top); - - /* We need sensor maximum rectangle */ - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (ret < 0) - return ret; - - /* Put user requested rectangle within sensor bounds */ - soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, - cap.bounds.width); - soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, - cap.bounds.height); - - /* - * Popular special case - some cameras can only handle fixed sizes like - * QVGA, VGA,... Take care to avoid infinite loop. - */ - width = max(cam_rect->width, 2); - height = max(cam_rect->height, 2); - - /* - * Loop as long as sensor is not covering the requested rectangle and - * is still within its bounds - */ - while (!ret && (is_smaller(cam_rect, rect) || - is_inside(cam_rect, rect)) && - (cap.bounds.width > width || cap.bounds.height > height)) { - - width *= 2; - height *= 2; - - cam_rect->width = width; - cam_rect->height = height; - - /* - * We do not know what capabilities the camera has to set up - * left and top borders. We could try to be smarter in iterating - * them, e.g., if camera current left is to the right of the - * target left, set it to the middle point between the current - * left and minimum left. But that would add too much - * complexity: we would have to iterate each border separately. - * Instead we just drop to the left and top bounds. - */ - if (cam_rect->left > rect->left) - cam_rect->left = cap.bounds.left; - - if (cam_rect->left + cam_rect->width < rect->left + rect->width) - cam_rect->width = rect->left + rect->width - - cam_rect->left; - - if (cam_rect->top > rect->top) - cam_rect->top = cap.bounds.top; - - if (cam_rect->top + cam_rect->height < rect->top + rect->height) - cam_rect->height = rect->top + rect->height - - cam_rect->top; - - v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = soc_camera_client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - } - - /* S_CROP must not modify the rectangle */ - if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { - /* - * The camera failed to configure a suitable cropping, - * we cannot use the current rectangle, set to max - */ - *cam_rect = cap.bounds; - v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = soc_camera_client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - } - - if (!ret) { - *target_rect = *cam_rect; - update_subrect(target_rect, subrect); - } - - return ret; -} - -/* Iterative s_mbus_fmt, also updates cached client crop on success */ -static int client_s_fmt(struct soc_camera_device *icd, - struct v4l2_rect *rect, struct v4l2_rect *subrect, - unsigned int max_width, unsigned int max_height, - struct v4l2_mbus_framefmt *mf, bool host_can_scale) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; - struct v4l2_cropcap cap; - bool ceu_1to1; - int ret; - - ret = v4l2_device_call_until_err(sd->v4l2_dev, - soc_camera_grp_id(icd), video, - s_mbus_fmt, mf); - if (ret < 0) - return ret; - - dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); - - if (width == mf->width && height == mf->height) { - /* Perfect! The client has done it all. */ - ceu_1to1 = true; - goto update_cache; - } - - ceu_1to1 = false; - if (!host_can_scale) - goto update_cache; - - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (ret < 0) - return ret; - - if (max_width > cap.bounds.width) - max_width = cap.bounds.width; - if (max_height > cap.bounds.height) - max_height = cap.bounds.height; - - /* Camera set a format, but geometry is not precise, try to improve */ - tmp_w = mf->width; - tmp_h = mf->height; - - /* width <= max_width && height <= max_height - guaranteed by try_fmt */ - while ((width > tmp_w || height > tmp_h) && - tmp_w < max_width && tmp_h < max_height) { - tmp_w = min(2 * tmp_w, max_width); - tmp_h = min(2 * tmp_h, max_height); - mf->width = tmp_w; - mf->height = tmp_h; - ret = v4l2_device_call_until_err(sd->v4l2_dev, - soc_camera_grp_id(icd), video, - s_mbus_fmt, mf); - dev_geo(dev, "Camera scaled to %ux%u\n", - mf->width, mf->height); - if (ret < 0) { - /* This shouldn't happen */ - dev_err(dev, "Client failed to set format: %d\n", ret); - return ret; - } - } - -update_cache: - /* Update cache */ - ret = soc_camera_client_g_rect(sd, rect); - if (ret < 0) - return ret; - - if (ceu_1to1) - *subrect = *rect; - else - update_subrect(rect, subrect); - - return 0; -} - -/** - * @icd - soc-camera device - * @rect - camera cropping window - * @subrect - part of rect, sent to the user - * @mf - in- / output camera output window - * @width - on input: max host input width - * on output: user width, mapped back to input - * @height - on input: max host input height - * on output: user height, mapped back to input - * @host_can_scale - host can scale this pixel format - * @shift - shift, used for scaling - */ -static int soc_camera_client_scale(struct soc_camera_device *icd, - struct v4l2_rect *rect, struct v4l2_rect *subrect, - struct v4l2_mbus_framefmt *mf, - unsigned int *width, unsigned int *height, - bool host_can_scale, unsigned int shift) -{ - struct device *dev = icd->parent; - struct v4l2_mbus_framefmt mf_tmp = *mf; - unsigned int scale_h, scale_v; - int ret; - - /* - * 5. Apply iterative camera S_FMT for camera user window (also updates - * client crop cache and the imaginary sub-rectangle). - */ - ret = client_s_fmt(icd, rect, subrect, *width, *height, - &mf_tmp, host_can_scale); - if (ret < 0) - return ret; - - dev_geo(dev, "5: camera scaled to %ux%u\n", - mf_tmp.width, mf_tmp.height); - - /* 6. Retrieve camera output window (g_fmt) */ - - /* unneeded - it is already in "mf_tmp" */ - - /* 7. Calculate new client scales. */ - scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp.width); - scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp.height); - - mf->width = mf_tmp.width; - mf->height = mf_tmp.height; - mf->colorspace = mf_tmp.colorspace; - - /* - * 8. Calculate new CEU crop - apply camera scales to previously - * updated "effective" crop. - */ - *width = soc_camera_shift_scale(subrect->width, shift, scale_h); - *height = soc_camera_shift_scale(subrect->height, shift, scale_v); - - dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); - - return 0; -} +#define calc_generic_scale(in, out) soc_camera_calc_scale(in, 12, out) /* * CEU can scale and crop, but we don't want to waste bandwidth and kill the @@ -1689,55 +1353,6 @@ static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, return 0; } -/* - * Calculate real client output window by applying new scales to the current - * client crop. New scales are calculated from the requested output format and - * CEU crop, mapped backed onto the client input (subrect). - */ -static void soc_camera_calc_client_output(struct soc_camera_device *icd, - struct v4l2_rect *rect, struct v4l2_rect *subrect, - const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, - unsigned int shift) -{ - struct device *dev = icd->parent; - unsigned int scale_v, scale_h; - - if (subrect->width == rect->width && - subrect->height == rect->height) { - /* No sub-cropping */ - mf->width = pix->width; - mf->height = pix->height; - return; - } - - /* 1.-2. Current camera scales and subwin - cached. */ - - dev_geo(dev, "2: subwin %ux%u@%u:%u\n", - subrect->width, subrect->height, - subrect->left, subrect->top); - - /* - * 3. Calculate new combined scales from input sub-window to requested - * user window. - */ - - /* - * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF - * (128x96) or larger than VGA - */ - scale_h = soc_camera_calc_scale(subrect->width, shift, pix->width); - scale_v = soc_camera_calc_scale(subrect->height, shift, pix->height); - - dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); - - /* - * 4. Calculate desired client output window by applying combined scales - * to client (real) input window. - */ - mf->width = soc_camera_shift_scale(rect->width, shift, scale_h); - mf->height = soc_camera_shift_scale(rect->height, shift, scale_v); -} - /* Similar to set_crop multistage iterative algorithm */ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c new file mode 100644 index 000000000000..be7067f55a29 --- /dev/null +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -0,0 +1,401 @@ +/* + * soc-camera generic scaling-cropping manipulation functions + * + * Copyright (C) 2013 Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +#include +#include + +#include "soc_scale_crop.h" + +#ifdef DEBUG_GEOMETRY +#define dev_geo dev_info +#else +#define dev_geo dev_dbg +#endif + +/* Check if any dimension of r1 is smaller than respective one of r2 */ +static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2) +{ + return r1->width < r2->width || r1->height < r2->height; +} + +/* Check if r1 fails to cover r2 */ +static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) +{ + return r1->left > r2->left || r1->top > r2->top || + r1->left + r1->width < r2->left + r2->width || + r1->top + r1->height < r2->top + r2->height; +} + +/* Get and store current client crop */ +int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) +{ + struct v4l2_crop crop; + struct v4l2_cropcap cap; + int ret; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_crop, &crop); + if (!ret) { + *rect = crop.c; + return ret; + } + + /* Camera driver doesn't support .g_crop(), assume default rectangle */ + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (!ret) + *rect = cap.defrect; + + return ret; +} +EXPORT_SYMBOL(soc_camera_client_g_rect); + +/* Client crop has changed, update our sub-rectangle to remain within the area */ +static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) +{ + if (rect->width < subrect->width) + subrect->width = rect->width; + + if (rect->height < subrect->height) + subrect->height = rect->height; + + if (rect->left > subrect->left) + subrect->left = rect->left; + else if (rect->left + rect->width > + subrect->left + subrect->width) + subrect->left = rect->left + rect->width - + subrect->width; + + if (rect->top > subrect->top) + subrect->top = rect->top; + else if (rect->top + rect->height > + subrect->top + subrect->height) + subrect->top = rect->top + rect->height - + subrect->height; +} + +/* + * The common for both scaling and cropping iterative approach is: + * 1. try if the client can produce exactly what requested by the user + * 2. if (1) failed, try to double the client image until we get one big enough + * 3. if (2) failed, try to request the maximum image + */ +int soc_camera_client_s_crop(struct v4l2_subdev *sd, + struct v4l2_crop *crop, struct v4l2_crop *cam_crop, + struct v4l2_rect *target_rect, struct v4l2_rect *subrect) +{ + struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; + struct device *dev = sd->v4l2_dev->dev; + struct v4l2_cropcap cap; + int ret; + unsigned int width, height; + + v4l2_subdev_call(sd, video, s_crop, crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; + + /* + * Now cam_crop contains the current camera input rectangle, and it must + * be within camera cropcap bounds + */ + if (!memcmp(rect, cam_rect, sizeof(*rect))) { + /* Even if camera S_CROP failed, but camera rectangle matches */ + dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", + rect->width, rect->height, rect->left, rect->top); + *target_rect = *cam_rect; + return 0; + } + + /* Try to fix cropping, that camera hasn't managed to set */ + dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top, + rect->width, rect->height, rect->left, rect->top); + + /* We need sensor maximum rectangle */ + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + /* Put user requested rectangle within sensor bounds */ + soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, + cap.bounds.width); + soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, + cap.bounds.height); + + /* + * Popular special case - some cameras can only handle fixed sizes like + * QVGA, VGA,... Take care to avoid infinite loop. + */ + width = max(cam_rect->width, 2); + height = max(cam_rect->height, 2); + + /* + * Loop as long as sensor is not covering the requested rectangle and + * is still within its bounds + */ + while (!ret && (is_smaller(cam_rect, rect) || + is_inside(cam_rect, rect)) && + (cap.bounds.width > width || cap.bounds.height > height)) { + + width *= 2; + height *= 2; + + cam_rect->width = width; + cam_rect->height = height; + + /* + * We do not know what capabilities the camera has to set up + * left and top borders. We could try to be smarter in iterating + * them, e.g., if camera current left is to the right of the + * target left, set it to the middle point between the current + * left and minimum left. But that would add too much + * complexity: we would have to iterate each border separately. + * Instead we just drop to the left and top bounds. + */ + if (cam_rect->left > rect->left) + cam_rect->left = cap.bounds.left; + + if (cam_rect->left + cam_rect->width < rect->left + rect->width) + cam_rect->width = rect->left + rect->width - + cam_rect->left; + + if (cam_rect->top > rect->top) + cam_rect->top = cap.bounds.top; + + if (cam_rect->top + cam_rect->height < rect->top + rect->height) + cam_rect->height = rect->top + rect->height - + cam_rect->top; + + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + } + + /* S_CROP must not modify the rectangle */ + if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { + /* + * The camera failed to configure a suitable cropping, + * we cannot use the current rectangle, set to max + */ + *cam_rect = cap.bounds; + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + } + + if (!ret) { + *target_rect = *cam_rect; + update_subrect(target_rect, subrect); + } + + return ret; +} +EXPORT_SYMBOL(soc_camera_client_s_crop); + +/* Iterative s_mbus_fmt, also updates cached client crop on success */ +static int client_s_fmt(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + unsigned int max_width, unsigned int max_height, + struct v4l2_mbus_framefmt *mf, bool host_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; + struct v4l2_cropcap cap; + bool ceu_1to1; + int ret; + + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, mf); + if (ret < 0) + return ret; + + dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); + + if (width == mf->width && height == mf->height) { + /* Perfect! The client has done it all. */ + ceu_1to1 = true; + goto update_cache; + } + + ceu_1to1 = false; + if (!host_can_scale) + goto update_cache; + + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + if (max_width > cap.bounds.width) + max_width = cap.bounds.width; + if (max_height > cap.bounds.height) + max_height = cap.bounds.height; + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = mf->width; + tmp_h = mf->height; + + /* width <= max_width && height <= max_height - guaranteed by try_fmt */ + while ((width > tmp_w || height > tmp_h) && + tmp_w < max_width && tmp_h < max_height) { + tmp_w = min(2 * tmp_w, max_width); + tmp_h = min(2 * tmp_h, max_height); + mf->width = tmp_w; + mf->height = tmp_h; + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, mf); + dev_geo(dev, "Camera scaled to %ux%u\n", + mf->width, mf->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(dev, "Client failed to set format: %d\n", ret); + return ret; + } + } + +update_cache: + /* Update cache */ + ret = soc_camera_client_g_rect(sd, rect); + if (ret < 0) + return ret; + + if (ceu_1to1) + *subrect = *rect; + else + update_subrect(rect, subrect); + + return 0; +} + +/** + * @icd - soc-camera device + * @rect - camera cropping window + * @subrect - part of rect, sent to the user + * @mf - in- / output camera output window + * @width - on input: max host input width + * on output: user width, mapped back to input + * @height - on input: max host input height + * on output: user height, mapped back to input + * @host_can_scale - host can scale this pixel format + * @shift - shift, used for scaling + */ +int soc_camera_client_scale(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + struct v4l2_mbus_framefmt *mf, + unsigned int *width, unsigned int *height, + bool host_can_scale, unsigned int shift) +{ + struct device *dev = icd->parent; + struct v4l2_mbus_framefmt mf_tmp = *mf; + unsigned int scale_h, scale_v; + int ret; + + /* + * 5. Apply iterative camera S_FMT for camera user window (also updates + * client crop cache and the imaginary sub-rectangle). + */ + ret = client_s_fmt(icd, rect, subrect, *width, *height, + &mf_tmp, host_can_scale); + if (ret < 0) + return ret; + + dev_geo(dev, "5: camera scaled to %ux%u\n", + mf_tmp.width, mf_tmp.height); + + /* 6. Retrieve camera output window (g_fmt) */ + + /* unneeded - it is already in "mf_tmp" */ + + /* 7. Calculate new client scales. */ + scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp.width); + scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp.height); + + mf->width = mf_tmp.width; + mf->height = mf_tmp.height; + mf->colorspace = mf_tmp.colorspace; + + /* + * 8. Calculate new CEU crop - apply camera scales to previously + * updated "effective" crop. + */ + *width = soc_camera_shift_scale(subrect->width, shift, scale_h); + *height = soc_camera_shift_scale(subrect->height, shift, scale_v); + + dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); + + return 0; +} +EXPORT_SYMBOL(soc_camera_client_scale); + +/* + * Calculate real client output window by applying new scales to the current + * client crop. New scales are calculated from the requested output format and + * CEU crop, mapped backed onto the client input (subrect). + */ +void soc_camera_calc_client_output(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, + unsigned int shift) +{ + struct device *dev = icd->parent; + unsigned int scale_v, scale_h; + + if (subrect->width == rect->width && + subrect->height == rect->height) { + /* No sub-cropping */ + mf->width = pix->width; + mf->height = pix->height; + return; + } + + /* 1.-2. Current camera scales and subwin - cached. */ + + dev_geo(dev, "2: subwin %ux%u@%u:%u\n", + subrect->width, subrect->height, + subrect->left, subrect->top); + + /* + * 3. Calculate new combined scales from input sub-window to requested + * user window. + */ + + /* + * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF + * (128x96) or larger than VGA + */ + scale_h = soc_camera_calc_scale(subrect->width, shift, pix->width); + scale_v = soc_camera_calc_scale(subrect->height, shift, pix->height); + + dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); + + /* + * 4. Calculate desired client output window by applying combined scales + * to client (real) input window. + */ + mf->width = soc_camera_shift_scale(rect->width, shift, scale_h); + mf->height = soc_camera_shift_scale(rect->height, shift, scale_v); +} +EXPORT_SYMBOL(soc_camera_calc_client_output); diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.h b/drivers/media/platform/soc_camera/soc_scale_crop.h new file mode 100644 index 000000000000..184a30dff541 --- /dev/null +++ b/drivers/media/platform/soc_camera/soc_scale_crop.h @@ -0,0 +1,47 @@ +/* + * soc-camera generic scaling-cropping manipulation functions + * + * Copyright (C) 2013 Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef SOC_SCALE_CROP_H +#define SOC_SCALE_CROP_H + +#include + +struct soc_camera_device; + +struct v4l2_crop; +struct v4l2_mbus_framefmt; +struct v4l2_pix_format; +struct v4l2_rect; +struct v4l2_subdev; + +static inline unsigned int soc_camera_shift_scale(unsigned int size, + unsigned int shift, unsigned int scale) +{ + return DIV_ROUND_CLOSEST(size << shift, scale); +} + +#define soc_camera_calc_scale(in, shift, out) soc_camera_shift_scale(in, shift, out) + +int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); +int soc_camera_client_s_crop(struct v4l2_subdev *sd, + struct v4l2_crop *crop, struct v4l2_crop *cam_crop, + struct v4l2_rect *target_rect, struct v4l2_rect *subrect); +int soc_camera_client_scale(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + struct v4l2_mbus_framefmt *mf, + unsigned int *width, unsigned int *height, + bool host_can_scale, unsigned int shift); +void soc_camera_calc_client_output(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, + unsigned int shift); + +#endif -- GitLab From 79275a994c2e672b2c3a893a1e2840a204adc3f7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Jun 2013 05:59:23 -0300 Subject: [PATCH 1992/2900] [media] V4L2: soc-camera: remove several CEU references in the generic scaler The scaling / cropping library, that has been extracted from the CEU driver still contained a couple of references to the original hardware. Clean them up. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/soc_camera/soc_scale_crop.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c index be7067f55a29..cbd3a34f4f3f 100644 --- a/drivers/media/platform/soc_camera/soc_scale_crop.c +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -221,7 +221,7 @@ static int client_s_fmt(struct soc_camera_device *icd, struct device *dev = icd->parent; unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; struct v4l2_cropcap cap; - bool ceu_1to1; + bool host_1to1; int ret; ret = v4l2_device_call_until_err(sd->v4l2_dev, @@ -234,11 +234,11 @@ static int client_s_fmt(struct soc_camera_device *icd, if (width == mf->width && height == mf->height) { /* Perfect! The client has done it all. */ - ceu_1to1 = true; + host_1to1 = true; goto update_cache; } - ceu_1to1 = false; + host_1to1 = false; if (!host_can_scale) goto update_cache; @@ -282,7 +282,7 @@ static int client_s_fmt(struct soc_camera_device *icd, if (ret < 0) return ret; - if (ceu_1to1) + if (host_1to1) *subrect = *rect; else update_subrect(rect, subrect); @@ -338,7 +338,7 @@ int soc_camera_client_scale(struct soc_camera_device *icd, mf->colorspace = mf_tmp.colorspace; /* - * 8. Calculate new CEU crop - apply camera scales to previously + * 8. Calculate new host crop - apply camera scales to previously * updated "effective" crop. */ *width = soc_camera_shift_scale(subrect->width, shift, scale_h); @@ -353,7 +353,7 @@ EXPORT_SYMBOL(soc_camera_client_scale); /* * Calculate real client output window by applying new scales to the current * client crop. New scales are calculated from the requested output format and - * CEU crop, mapped backed onto the client input (subrect). + * host crop, mapped backed onto the client input (subrect). */ void soc_camera_calc_client_output(struct soc_camera_device *icd, struct v4l2_rect *rect, struct v4l2_rect *subrect, @@ -384,7 +384,8 @@ void soc_camera_calc_client_output(struct soc_camera_device *icd, /* * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF - * (128x96) or larger than VGA + * (128x96) or larger than VGA. This and similar limitations have to be + * taken into account here. */ scale_h = soc_camera_calc_scale(subrect->width, shift, pix->width); scale_v = soc_camera_calc_scale(subrect->height, shift, pix->height); -- GitLab From 2641ff994d12f9f4199d8261d71d2059a8b96ae1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jun 2013 16:28:14 -0300 Subject: [PATCH 1993/2900] [media] ml86v7667: fix compiler warning build/media_build/v4l/ml86v7667.c: In function 'ml86v7667_s_ctrl': build/media_build/v4l/ml86v7667.c:120:6: warning: variable 'ret' set but not used [-Wunused-but-set-variable] int ret = 0; ^ Signed-off-by: Hans Verkuil Cc: Vladimir Barinov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ml86v7667.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index cd9f86e743b2..efdc873e58d1 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -117,7 +117,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = 0; + int ret; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: -- GitLab From 20420f92474b4ef36635f427aacafa8a80c124a6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jun 2013 16:28:15 -0300 Subject: [PATCH 1994/2900] [media] bfin_capture: fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit media-git/drivers/media/platform/blackfin/bfin_capture.c: In function ‘bcap_probe’: media-git/drivers/media/platform/blackfin/bfin_capture.c:1007:16: warning: ignoring return value of ‘vb2_queue_init’, declared with attribute warn_unused_result [-Wunused-result] vb2_queue_init(q); ^ Signed-off-by: Hans Verkuil Acked-by: Scott Jiang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/blackfin/bfin_capture.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 6652e71ea794..7f838c681cea 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -1004,7 +1004,9 @@ static int bcap_probe(struct platform_device *pdev) q->mem_ops = &vb2_dma_contig_memops; q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - vb2_queue_init(q); + ret = vb2_queue_init(q); + if (ret) + goto err_free_handler; mutex_init(&bcap_dev->mutex); init_completion(&bcap_dev->comp); -- GitLab From fe653786ff9027216d841470b140593f3bf3a695 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jun 2013 16:28:16 -0300 Subject: [PATCH 1995/2900] [media] omap_vout: fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit media-git/drivers/media/platform/omap/omap_vout.c: In function ‘omapvid_init’: media-git/drivers/media/platform/omap/omap_vout.c:382:17: warning: ‘mode’ may be used uninitialized in this function [-Wmaybe-uninitialized] vout->dss_mode = video_mode_to_dss_mode(vout); ^ media-git/drivers/media/platform/omap/omap_vout.c:332:23: note: ‘mode’ was declared here enum omap_color_mode mode; ^ Signed-off-by: Hans Verkuil Cc: Laurent Pinchart Cc: Prabhakar Lad Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap/omap_vout.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index d338b19da544..dfd0a21a0658 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -335,8 +335,6 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout) ovl = ovid->overlays[0]; switch (pix->pixelformat) { - case 0: - break; case V4L2_PIX_FMT_YUYV: mode = OMAP_DSS_COLOR_YUV2; break; @@ -358,6 +356,7 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout) break; default: mode = -EINVAL; + break; } return mode; } -- GitLab From 5a1d3e9f18ceb8d791bdc9a78d8ee10ddc80a6e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 21 Jun 2013 02:05:34 -0300 Subject: [PATCH 1996/2900] [media] v4l2-controls.h: fix copy-and-paste error in comment The comment for the FM_RX class was copied from the DV class unchanged. Fixed. Also made the FM_TX comment consistent with the others. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/v4l2-controls.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 69bd5bb0d5af..e90a88a8708f 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -53,13 +53,13 @@ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ -#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator controls */ #define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ #define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e0000 /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f0000 /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */ -#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */ /* User-class control IDs */ -- GitLab From fd8d30bf20db099eec4d7f7e678e6d6fa8e492b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 21 Jun 2013 16:16:47 -0300 Subject: [PATCH 1997/2900] [media] saa7164: fix compiler warning build/media_build/v4l/saa7164-core.c: In function 'saa7164_initdev': build/media_build/v4l/saa7164-core.c:1192:6: warning: 'err' may be used uninitialized in this function [-Wmaybe-uninitialized] int err, i; ^ Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7164/saa7164-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 5d27865784c5..d37ee37aaefe 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1196,7 +1196,8 @@ static int saa7164_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; - if (v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev)) { + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) { dev_err(&pci_dev->dev, "v4l2_device_register failed\n"); goto fail_free; } -- GitLab From 12d866ecd008ad8c9b818836fe84994ac8f80e18 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Sat, 22 Jun 2013 08:02:52 -0300 Subject: [PATCH 1998/2900] [media] saa7134: Fix sparse warnings by adding __user annotation Adding a __user annotation fixes the following sparse warnings. drivers/media/pci/saa7134/saa7134-video.c:1578:45: warning: incorrect type in initializer (different address spaces) drivers/media/pci/saa7134/saa7134-video.c:1578:45: expected struct v4l2_clip *clips drivers/media/pci/saa7134/saa7134-video.c:1578:45: got struct v4l2_clip [noderef] *clips drivers/media/pci/saa7134/saa7134-video.c:1589:26: warning: incorrect type in assignment (different address spaces) drivers/media/pci/saa7134/saa7134-video.c:1589:26: expected struct v4l2_clip [noderef] *clips drivers/media/pci/saa7134/saa7134-video.c:1589:26: got struct v4l2_clip *clips Signed-off-by: Emil Goode Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index e3457aea6a33..e12bbd8c3f0b 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1575,7 +1575,7 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - struct v4l2_clip *clips = f->fmt.win.clips; + struct v4l2_clip __user *clips = f->fmt.win.clips; u32 clipcount = f->fmt.win.clipcount; int err = 0; int i; -- GitLab From f0a12d0c9272ae24491b983c4982acdacdac1baf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 23 Jun 2013 10:01:35 -0300 Subject: [PATCH 1999/2900] [media] tvp514x: Fix init seqeunce client->driver->id_table will always point to the first entry in the device id table. So all devices will use the same init sequence. Use the id table entry that gets passed to the driver's probe() function to get the right init sequence. Signed-off-by: Lars-Peter Clausen Acked-by: Lad, Prabhakar Tested-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 864eb14ae9b1..03289e57a217 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -123,6 +123,8 @@ struct tvp514x_decoder { /* mc related members */ struct media_pad pad; struct v4l2_mbus_framefmt format; + + struct tvp514x_reg *int_seq; }; /* TVP514x default register values */ @@ -864,7 +866,6 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) { int err = 0; - struct i2c_client *client = v4l2_get_subdevdata(sd); struct tvp514x_decoder *decoder = to_decoder(sd); if (decoder->streaming == enable) @@ -884,11 +885,8 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) } case 1: { - struct tvp514x_reg *int_seq = (struct tvp514x_reg *) - client->driver->id_table->driver_data; - /* Power Up Sequence */ - err = tvp514x_write_regs(sd, int_seq); + err = tvp514x_write_regs(sd, decoder->int_seq); if (err) { v4l2_err(sd, "Unable to turn on decoder\n"); return err; @@ -1128,6 +1126,8 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, sizeof(tvp514x_reg_list_default)); + decoder->int_seq = (struct tvp514x_reg *)id->driver_data; + /* Copy board specific information here */ decoder->pdata = pdata; -- GitLab From ae09e9e73a7d59bf0f8cc92e51c51abbd4cab732 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 22 Jun 2013 02:38:37 -0300 Subject: [PATCH 2000/2900] [media] wl128x: add missing struct v4l2_device This struct is now required for all video device nodes, but it was missing in this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv.h | 2 ++ drivers/media/radio/wl128x/fmdrv_v4l2.c | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h index aac0f025f767..a587c9bac930 100644 --- a/drivers/media/radio/wl128x/fmdrv.h +++ b/drivers/media/radio/wl128x/fmdrv.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #define FM_DRV_VERSION "0.1.1" @@ -202,6 +203,7 @@ struct fmtx_data { /* FM driver operation structure */ struct fmdev { struct video_device *radio_dev; /* V4L2 video device pointer */ + struct v4l2_device v4l2_dev; /* V4L2 top level struct */ struct snd_card *card; /* Card which holds FM mixer controls */ u16 asci_id; spinlock_t rds_buff_lock; /* To protect access to RDS buffer */ diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 5dec323f4247..b55012c11842 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -533,6 +533,11 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) struct v4l2_ctrl *ctrl; int ret; + strlcpy(fmdev->v4l2_dev.name, FM_DRV_NAME, sizeof(fmdev->v4l2_dev.name)); + ret = v4l2_device_register(NULL, &fmdev->v4l2_dev); + if (ret < 0) + return ret; + /* Init mutex for core locking */ mutex_init(&fmdev->mutex); @@ -549,6 +554,7 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) video_set_drvdata(gradio_dev, fmdev); gradio_dev->lock = &fmdev->mutex; + gradio_dev->v4l2_dev = &fmdev->v4l2_dev; /* Register with V4L2 subsystem as RADIO device */ if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) { @@ -611,5 +617,7 @@ void *fm_v4l2_deinit_video_device(void) /* Unregister RADIO device from V4L2 subsystem */ video_unregister_device(gradio_dev); + v4l2_device_unregister(&fmdev->v4l2_dev); + return fmdev; } -- GitLab From 8f484d8767d3d80bc20bb341a4b3e35894ef704b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 27 Jun 2013 02:44:04 -0300 Subject: [PATCH 2001/2900] [media] mem2mem: set missing v4l2_dev pointer The m2m-deinterlace, mem2mem_testdev and mx2_emmaprp drivers didn't set the v4l2_dev pointer in struct video_device, even though a v4l2_device was registered correctly. These days this v4l2_dev pointer must be set correctly, so this patch adds that for these three drivers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/m2m-deinterlace.c | 1 + drivers/media/platform/mem2mem_testdev.c | 3 ++- drivers/media/platform/mx2_emmaprp.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 758564649589..540516ca872c 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -1033,6 +1033,7 @@ static int deinterlace_probe(struct platform_device *pdev) *vfd = deinterlace_videodev; vfd->lock = &pcdev->dev_mutex; + vfd->v4l2_dev = &pcdev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 4cc7f65d7d76..6a17676f9d72 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c @@ -1051,6 +1051,7 @@ static int m2mtest_probe(struct platform_device *pdev) *vfd = m2mtest_videodev; vfd->lock = &dev->dev_mutex; + vfd->v4l2_dev = &dev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { @@ -1061,7 +1062,7 @@ static int m2mtest_probe(struct platform_device *pdev) video_set_drvdata(vfd, dev); snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name); dev->vfd = vfd; - v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME + v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n", vfd->num); setup_timer(&dev->timer, device_isr, (long)dev); diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index f7440e585b6b..c690435853bd 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -937,6 +937,7 @@ static int emmaprp_probe(struct platform_device *pdev) *vfd = emmaprp_videodev; vfd->lock = &pcdev->dev_mutex; + vfd->v4l2_dev = &pcdev->v4l2_dev; video_set_drvdata(vfd, pcdev); snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); -- GitLab From fc84e65fff543564ea5a5f619053101c099353d4 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 24 Jun 2013 11:47:25 -0300 Subject: [PATCH 2002/2900] [media] media: i2c: tvp7002: remove manual setting of subdev name This patch removes manual setting of subdev name in the probe, ideally subdev names must be unique. Signed-off-by: Lad, Prabhakar Cc: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 36ad565e5a33..a4e49483de6a 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -1020,7 +1020,6 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) error = tvp7002_s_dv_timings(sd, &timings); #if defined(CONFIG_MEDIA_CONTROLLER) - strlcpy(sd->name, TVP7002_MODULE_NAME, sizeof(sd->name)); device->pad.flags = MEDIA_PAD_FL_SOURCE; device->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; device->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; -- GitLab From f042ff650f47ea2868e5f89fa76370d4ebe43f4b Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Mon, 24 Jun 2013 11:47:26 -0300 Subject: [PATCH 2003/2900] [media] media: i2c: tvp514x: remove manual setting of subdev name This patch removes manual setting of subdev name in the probe, ideally subdev names must be unique. Signed-off-by: Lad, Prabhakar Cc: Hans Verkuil Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 03289e57a217..9c6d66a9868f 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1148,7 +1148,6 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Register with V4L2 layer as slave device */ sd = &decoder->sd; v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); - strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name)); #if defined(CONFIG_MEDIA_CONTROLLER) decoder->pad.flags = MEDIA_PAD_FL_SOURCE; -- GitLab From 47d1f33ff43e3d4f74fff1892d44d1de34a80be2 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 11 Jun 2013 10:44:38 -0300 Subject: [PATCH 2004/2900] [media] exynos4-is: Drop drvdata handling in fimc-lite for non-dt platforms The FIMC-LITE IP block is available only on platforms instantiated from device tree. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 3 --- drivers/media/platform/exynos4-is/fimc-lite.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 3f76f8abc4b3..00c525c377d8 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1449,9 +1449,6 @@ static int fimc_lite_probe(struct platform_device *pdev) if (of_id) drv_data = (struct flite_drvdata *)of_id->data; fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); - } else { - drv_data = fimc_lite_get_drvdata(pdev); - fimc->index = pdev->id; } if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index c7aa08477830..4b1068425dad 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -56,9 +56,6 @@ struct flite_drvdata { unsigned short out_hor_offs_align; }; -#define fimc_lite_get_drvdata(_pdev) \ - ((struct flite_drvdata *) platform_get_device_id(_pdev)->driver_data) - struct fimc_lite_events { unsigned int data_overflow; }; -- GitLab From 086eca2905d0d1ea6b5e22d62648c6b818c51846 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 14 Jun 2013 12:38:15 -0300 Subject: [PATCH 2005/2900] [media] exynos4-is: Add Exynos5250 SoC support to fimc-lite driver This patch adds support for the Exynos5250 SoC variant of the FIMC-LITE IP. A 'compatible' string is added for Exynos5250 compatible devices and the capture DMA handling is reworked to use the FLITE_REG_CIFCNTSEQ register, masking output DMA buffer address slots. The frame interrupt is enabled so there are now 2 interrupts per frame. This likely can be optimized in future by using any status registers that allow to figure out what the last and the currently written frame buffer is. It would also be more reliable in cases where there are high interrupt service latencies. Signed-off-by: Shaik Ameer Basha Signed-off-by: Arun Kumar K Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park --- .../bindings/media/exynos-fimc-lite.txt | 6 ++- .../media/platform/exynos4-is/fimc-lite-reg.c | 53 +++++++++++++++++-- .../media/platform/exynos4-is/fimc-lite-reg.h | 10 +++- drivers/media/platform/exynos4-is/fimc-lite.c | 50 ++++++++++++++--- drivers/media/platform/exynos4-is/fimc-lite.h | 22 +++++++- 5 files changed, 125 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt index de9f6b78ee51..0bf6fb7fbeab 100644 --- a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt +++ b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt @@ -2,8 +2,10 @@ Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE) Required properties: -- compatible : should be "samsung,exynos4212-fimc-lite" for Exynos4212 and - Exynos4412 SoCs; +- compatible : should be one of: + "samsung,exynos4212-fimc-lite" for Exynos4212/4412 SoCs, + "samsung,exynos5250-fimc-lite" for Exynos5250 compatible + devices; - reg : physical base address and size of the device memory mapped registers; - interrupts : should contain FIMC-LITE interrupt; diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c index eb4f7635f5e0..72a343e3b5e8 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c @@ -2,15 +2,16 @@ * Register interface file for EXYNOS FIMC-LITE (camera interface) driver * * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki + * Author: Sylwester Nawrocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include +#include #include +#include #include #include "fimc-lite-reg.h" @@ -68,7 +69,8 @@ void flite_hw_set_interrupt_mask(struct fimc_lite *dev) if (atomic_read(&dev->out_path) == FIMC_IO_DMA) { intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | FLITE_REG_CIGCTRL_IRQ_LASTEN | - FLITE_REG_CIGCTRL_IRQ_STARTEN; + FLITE_REG_CIGCTRL_IRQ_STARTEN | + FLITE_REG_CIGCTRL_IRQ_ENDEN; } else { /* An output to the FIMC-IS */ intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | @@ -215,6 +217,18 @@ void flite_hw_set_camera_bus(struct fimc_lite *dev, flite_hw_set_camera_port(dev, si->mux_id); } +static void flite_hw_set_pack12(struct fimc_lite *dev, int on) +{ + u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); + + cfg &= ~FLITE_REG_CIODMAFMT_PACK12; + + if (on) + cfg |= FLITE_REG_CIODMAFMT_PACK12; + + writel(cfg, dev->regs + FLITE_REG_CIODMAFMT); +} + static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) { static const u32 pixcode[4][2] = { @@ -250,6 +264,38 @@ void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f) writel(cfg, dev->regs + FLITE_REG_CIOOFF); } +void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf) +{ + unsigned int index; + u32 cfg; + + if (dev->dd->max_dma_bufs == 1) + index = 0; + else + index = buf->index; + + if (index == 0) + writel(buf->paddr, dev->regs + FLITE_REG_CIOSA); + else + writel(buf->paddr, dev->regs + FLITE_REG_CIOSAN(index - 1)); + + cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); + cfg |= BIT(index); + writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); +} + +void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index) +{ + u32 cfg; + + if (dev->dd->max_dma_bufs == 1) + index = 0; + + cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); + cfg &= ~BIT(index); + writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); +} + /* Enable/disable output DMA, set output pixel size and offsets (composition) */ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, bool enable) @@ -267,6 +313,7 @@ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, flite_hw_set_out_order(dev, f); flite_hw_set_dma_window(dev, f); + flite_hw_set_pack12(dev, 0); } void flite_hw_dump_regs(struct fimc_lite *dev, const char *label) diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.h b/drivers/media/platform/exynos4-is/fimc-lite-reg.h index 390383941c19..10a7d7bbcc27 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.h +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.h @@ -120,6 +120,9 @@ /* b0: 1 - camera B, 0 - camera A */ #define FLITE_REG_CIGENERAL_CAM_B (1 << 0) +#define FLITE_REG_CIFCNTSEQ 0x100 +#define FLITE_REG_CIOSAN(x) (0x200 + (4 * (x))) + /* ---------------------------------------------------------------------------- * Function declarations */ @@ -142,9 +145,12 @@ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f); void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on); void flite_hw_dump_regs(struct fimc_lite *dev, const char *label); +void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf); +void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index); -static inline void flite_hw_set_output_addr(struct fimc_lite *dev, u32 paddr) +static inline void flite_hw_set_dma_buf_mask(struct fimc_lite *dev, u32 mask) { - writel(paddr, dev->regs + FLITE_REG_CIOSA); + writel(mask, dev->regs + FLITE_REG_CIFCNTSEQ); } + #endif /* FIMC_LITE_REG_H */ diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 00c525c377d8..07767c8b1c62 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -153,6 +153,7 @@ static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output) flite_hw_set_camera_bus(fimc, si); flite_hw_set_source_format(fimc, &fimc->inp_frame); flite_hw_set_window_offset(fimc, &fimc->inp_frame); + flite_hw_set_dma_buf_mask(fimc, 0); flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output); flite_hw_set_interrupt_mask(fimc); flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); @@ -276,19 +277,23 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) && test_bit(ST_FLITE_RUN, &fimc->state) && - !list_empty(&fimc->active_buf_q) && !list_empty(&fimc->pending_buf_q)) { + vbuf = fimc_lite_pending_queue_pop(fimc); + flite_hw_set_dma_buffer(fimc, vbuf); + fimc_lite_active_queue_add(fimc, vbuf); + } + + if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMEND) && + test_bit(ST_FLITE_RUN, &fimc->state) && + !list_empty(&fimc->active_buf_q)) { vbuf = fimc_lite_active_queue_pop(fimc); ktime_get_ts(&ts); tv = &vbuf->vb.v4l2_buf.timestamp; tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; vbuf->vb.v4l2_buf.sequence = fimc->frame_count++; + flite_hw_mask_dma_buffer(fimc, vbuf->index); vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE); - - vbuf = fimc_lite_pending_queue_pop(fimc); - flite_hw_set_output_addr(fimc, vbuf->paddr); - fimc_lite_active_queue_add(fimc, vbuf); } if (test_bit(ST_FLITE_CONFIG, &fimc->state)) @@ -307,10 +312,16 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) static int start_streaming(struct vb2_queue *q, unsigned int count) { struct fimc_lite *fimc = q->drv_priv; + unsigned long flags; int ret; + spin_lock_irqsave(&fimc->slock, flags); + + fimc->buf_index = 0; fimc->frame_count = 0; + spin_unlock_irqrestore(&fimc->slock, flags); + ret = fimc_lite_hw_init(fimc, false); if (ret) { fimc_lite_reinit(fimc, false); @@ -412,10 +423,14 @@ static void buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&fimc->slock, flags); buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0); + buf->index = fimc->buf_index++; + if (fimc->buf_index >= fimc->reqbufs_count) + fimc->buf_index = 0; + if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) && !test_bit(ST_FLITE_STREAM, &fimc->state) && list_empty(&fimc->active_buf_q)) { - flite_hw_set_output_addr(fimc, buf->paddr); + flite_hw_set_dma_buffer(fimc, buf); fimc_lite_active_queue_add(fimc, buf); } else { fimc_lite_pending_queue_add(fimc, buf); @@ -1451,8 +1466,12 @@ static int fimc_lite_probe(struct platform_device *pdev) fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); } - if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS) + if (!drv_data || fimc->index >= drv_data->num_instances || + fimc->index < 0) { + dev_err(dev, "Wrong %s node alias\n", + dev->of_node->full_name); return -EINVAL; + } fimc->dd = drv_data; fimc->pdev = pdev; @@ -1609,6 +1628,19 @@ static struct flite_drvdata fimc_lite_drvdata_exynos4 = { .out_width_align = 8, .win_hor_offs_align = 2, .out_hor_offs_align = 8, + .max_dma_bufs = 1, + .num_instances = 2, +}; + +/* EXYNOS5250 */ +static struct flite_drvdata fimc_lite_drvdata_exynos5 = { + .max_width = 8192, + .max_height = 8192, + .out_width_align = 8, + .win_hor_offs_align = 2, + .out_hor_offs_align = 8, + .max_dma_bufs = 32, + .num_instances = 3, }; static const struct of_device_id flite_of_match[] = { @@ -1616,6 +1648,10 @@ static const struct of_device_id flite_of_match[] = { .compatible = "samsung,exynos4212-fimc-lite", .data = &fimc_lite_drvdata_exynos4, }, + { + .compatible = "samsung,exynos5250-fimc-lite", + .data = &fimc_lite_drvdata_exynos5, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, flite_of_match); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index 4b1068425dad..c98f3da74870 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -27,7 +27,7 @@ #define FIMC_LITE_DRV_NAME "exynos-fimc-lite" #define FLITE_CLK_NAME "flite" -#define FIMC_LITE_MAX_DEVS 2 +#define FIMC_LITE_MAX_DEVS 3 #define FLITE_REQ_BUFS_MIN 2 /* Bit index definitions for struct fimc_lite::state */ @@ -48,12 +48,26 @@ enum { #define FLITE_SD_PAD_SOURCE_ISP 2 #define FLITE_SD_PADS_NUM 3 +/** + * struct flite_drvdata - FIMC-LITE IP variant data structure + * @max_width: maximum camera interface input width in pixels + * @max_height: maximum camera interface input height in pixels + * @out_width_align: minimum output width alignment in pixels + * @win_hor_offs_align: minimum camera interface crop window horizontal + * offset alignment in pixels + * @out_hor_offs_align: minimum output DMA compose rectangle horizontal + * offset alignment in pixels + * @max_dma_bufs: number of output DMA buffer start address registers + * @num_instances: total number of FIMC-LITE IP instances available + */ struct flite_drvdata { unsigned short max_width; unsigned short max_height; unsigned short out_width_align; unsigned short win_hor_offs_align; unsigned short out_hor_offs_align; + unsigned short max_dma_bufs; + unsigned short num_instances; }; struct fimc_lite_events { @@ -80,12 +94,14 @@ struct flite_frame { * struct flite_buffer - video buffer structure * @vb: vb2 buffer * @list: list head for the buffers queue - * @paddr: precalculated physical address + * @paddr: DMA buffer start address + * @index: DMA start address register's index */ struct flite_buffer { struct vb2_buffer vb; struct list_head list; dma_addr_t paddr; + unsigned short index; }; /** @@ -119,6 +135,7 @@ struct flite_buffer { * @pending_buf_q: pending buffers queue head * @active_buf_q: the queue head of buffers scheduled in hardware * @vb_queue: vb2 buffers queue + * @buf_index: helps to keep track of the DMA start address register index * @active_buf_count: number of video buffers scheduled in hardware * @frame_count: the captured frames counter * @reqbufs_count: the number of buffers requested with REQBUFS ioctl @@ -155,6 +172,7 @@ struct fimc_lite { struct list_head pending_buf_q; struct list_head active_buf_q; struct vb2_queue vb_queue; + unsigned short buf_index; unsigned int frame_count; unsigned int reqbufs_count; -- GitLab From f7354e6c230ec62d221e51aa3f970fd3d5eb2067 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 10:38:23 -0300 Subject: [PATCH 2006/2900] [media] exynos4-is: Add support for Exynos5250 MIPI-CSIS Add compatible property for the Exynos5250 and enable the frame start and frame end interrupts. These interrupts are needed for the Exynos5 FIMC-IS firmware. The driver enables those interrupt only where available, depending on the 'compatible' property. This can be optimized further, by exposing some API at the subdev driver, so the host driver can enable extra interrupts only for the image processing chains involving FIMC-IS. Signed-off-by: Shaik Ameer Basha Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park --- .../bindings/media/samsung-mipi-csis.txt | 4 +- drivers/media/platform/exynos4-is/mipi-csis.c | 67 ++++++++++++++++--- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt index 5f8e28e2484f..be45f0b1a449 100644 --- a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt +++ b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt @@ -5,8 +5,8 @@ Required properties: - compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110), "samsung,exynos4210-csis" for Exynos4210 (S5PC210), - "samsung,exynos4212-csis" for Exynos4212/Exynos4412 - SoC series; + "samsung,exynos4212-csis" for Exynos4212/Exynos4412, + "samsung,exynos5250-csis" for Exynos5250; - reg : offset and length of the register set for the device; - interrupts : should contain MIPI CSIS interrupt; the format of the interrupt specifier depends on the interrupt controller; diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 254d70fe762a..0914230b42de 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -1,8 +1,8 @@ /* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver + * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -66,11 +66,12 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); /* Interrupt mask */ #define S5PCSIS_INTMSK 0x10 -#define S5PCSIS_INTMSK_EN_ALL 0xf000103f #define S5PCSIS_INTMSK_EVEN_BEFORE (1 << 31) #define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30) #define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29) #define S5PCSIS_INTMSK_ODD_AFTER (1 << 28) +#define S5PCSIS_INTMSK_FRAME_START (1 << 27) +#define S5PCSIS_INTMSK_FRAME_END (1 << 26) #define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12) #define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5) #define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4) @@ -78,6 +79,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define S5PCSIS_INTMSK_ERR_ECC (1 << 2) #define S5PCSIS_INTMSK_ERR_CRC (1 << 1) #define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0) +#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL 0xf000103f +#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL 0xfc00103f /* Interrupt source */ #define S5PCSIS_INTSRC 0x14 @@ -88,6 +91,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define S5PCSIS_INTSRC_ODD_AFTER (1 << 28) #define S5PCSIS_INTSRC_ODD (0x3 << 28) #define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28) +#define S5PCSIS_INTSRC_FRAME_START (1 << 27) +#define S5PCSIS_INTSRC_FRAME_END (1 << 26) #define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12) #define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5) #define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4) @@ -151,6 +156,9 @@ static const struct s5pcsis_event s5pcsis_events[] = { { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" }, { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" }, { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" }, + /* Frame start/end */ + { S5PCSIS_INTSRC_FRAME_START, "Frame Start" }, + { S5PCSIS_INTSRC_FRAME_END, "Frame End" }, }; #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) @@ -159,6 +167,11 @@ struct csis_pktbuf { unsigned int len; }; +struct csis_drvdata { + /* Mask of all used interrupts in S5PCSIS_INTMSK register */ + u32 interrupt_mask; +}; + /** * struct csis_state - the driver's internal state data structure * @lock: mutex serializing the subdev and power management operations, @@ -171,6 +184,7 @@ struct csis_pktbuf { * @supplies: CSIS regulator supplies * @clock: CSIS clocks * @irq: requested s5p-mipi-csis irq number + * @interrupt_mask: interrupt mask of the all used interrupts * @flags: the state variable for power and streaming control * @clock_frequency: device bus clock frequency * @hs_settle: HS-RX settle time @@ -193,6 +207,7 @@ struct csis_state { struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; struct clk *clock[NUM_CSIS_CLOCKS]; int irq; + u32 interrupt_mask; u32 flags; u32 clk_frequency; @@ -274,9 +289,10 @@ static const struct csis_pix_format *find_csis_format( static void s5pcsis_enable_interrupts(struct csis_state *state, bool on) { u32 val = s5pcsis_read(state, S5PCSIS_INTMSK); - - val = on ? val | S5PCSIS_INTMSK_EN_ALL : - val & ~S5PCSIS_INTMSK_EN_ALL; + if (on) + val |= state->interrupt_mask; + else + val &= ~state->interrupt_mask; s5pcsis_write(state, S5PCSIS_INTMSK, val); } @@ -771,8 +787,12 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, #define s5pcsis_parse_dt(pdev, state) (-ENOSYS) #endif +static const struct of_device_id s5pcsis_of_match[]; + static int s5pcsis_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; + const struct csis_drvdata *drv_data; struct device *dev = &pdev->dev; struct resource *mem_res; struct csis_state *state; @@ -787,10 +807,19 @@ static int s5pcsis_probe(struct platform_device *pdev) spin_lock_init(&state->slock); state->pdev = pdev; - if (dev->of_node) + if (dev->of_node) { + of_id = of_match_node(s5pcsis_of_match, dev->of_node); + if (WARN_ON(of_id == NULL)) + return -EINVAL; + + drv_data = of_id->data; + state->interrupt_mask = drv_data->interrupt_mask; + ret = s5pcsis_parse_dt(pdev, state); - else + } else { ret = s5pcsis_get_platform_data(pdev, state); + } + if (ret < 0) return ret; @@ -994,9 +1023,25 @@ static const struct dev_pm_ops s5pcsis_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume) }; +static const struct csis_drvdata exynos4_csis_drvdata = { + .interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL, +}; + +static const struct csis_drvdata exynos5_csis_drvdata = { + .interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL, +}; + static const struct of_device_id s5pcsis_of_match[] = { - { .compatible = "samsung,s5pv210-csis" }, - { .compatible = "samsung,exynos4210-csis" }, + { + .compatible = "samsung,s5pv210-csis", + .data = &exynos4_csis_drvdata, + }, { + .compatible = "samsung,exynos4210-csis", + .data = &exynos4_csis_drvdata, + }, { + .compatible = "samsung,exynos5250-csis", + .data = &exynos5_csis_drvdata, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, s5pcsis_of_match); -- GitLab From 72f2a7686cd37324ba5b5111ab294d307f1df50d Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 31 May 2013 10:36:19 -0300 Subject: [PATCH 2007/2900] [media] exynos4-is: Change fimc-is firmware file names This patch changes the firmware file names of the FIMC-IS subsystem. It is needed since there are different firmwares used across various SoC series, e.g. Exynos4 and Exynos5. Also the sensor specific "setfile" name is changed, to account for it depends on an image sensor and is also specific to the FIMC-IS and the SoC. This is a change for a driver merged in 3.10. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-is.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h index 08fa518c34f7..61bb0127e19d 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ b/drivers/media/platform/exynos4-is/fimc-is.h @@ -33,8 +33,8 @@ #define FIMC_IS_DRV_NAME "exynos4-fimc-is" -#define FIMC_IS_FW_FILENAME "fimc_is_fw.bin" -#define FIMC_IS_SETFILE_6A3 "setfile.bin" +#define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" +#define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" #define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ #define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ -- GitLab From 188ab116dd9273bb8950481e7764d7eb4f21afb6 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 14 Jun 2013 19:28:40 -0300 Subject: [PATCH 2008/2900] [media] Documentation: Update driver's directory in video4linux/fimc.txt Update the documentation with the driver's path changed in commit 56fa1a6a6a7da91e7ece8b01b0ae8adb2926e434 [media] s5p-fimc: Change the driver directory to exynos4-is Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/fimc.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Documentation/video4linux/fimc.txt b/Documentation/video4linux/fimc.txt index 25f4d3402722..e51f1b5b7324 100644 --- a/Documentation/video4linux/fimc.txt +++ b/Documentation/video4linux/fimc.txt @@ -1,6 +1,6 @@ Samsung S5P/EXYNOS4 FIMC driver -Copyright (C) 2012 Samsung Electronics Co., Ltd. +Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. --------------------------------------------------------------------------- The FIMC (Fully Interactive Mobile Camera) device available in Samsung @@ -10,7 +10,7 @@ data from LCD controller (FIMD) through the SoC internal writeback data path. There are multiple FIMC instances in the SoCs (up to 4), having slightly different capabilities, like pixel alignment constraints, rotator availability, LCD writeback support, etc. The driver is located at -drivers/media/platform/s5p-fimc directory. +drivers/media/platform/exynos4-is directory. 1. Supported SoCs ================= @@ -36,21 +36,21 @@ Not currently supported: ===================== - media device driver - drivers/media/platform/s5p-fimc/fimc-mdevice.[ch] + drivers/media/platform/exynos4-is/media-dev.[ch] - camera capture video device driver - drivers/media/platform/s5p-fimc/fimc-capture.c + drivers/media/platform/exynos4-is/fimc-capture.c - MIPI-CSI2 receiver subdev - drivers/media/platform/s5p-fimc/mipi-csis.[ch] + drivers/media/platform/exynos4-is/mipi-csis.[ch] - video post-processor (mem-to-mem) - drivers/media/platform/s5p-fimc/fimc-core.c + drivers/media/platform/exynos4-is/fimc-core.c - common files - drivers/media/platform/s5p-fimc/fimc-core.h - drivers/media/platform/s5p-fimc/fimc-reg.h - drivers/media/platform/s5p-fimc/regs-fimc.h + drivers/media/platform/exynos4-is/fimc-core.h + drivers/media/platform/exynos4-is/fimc-reg.h + drivers/media/platform/exynos4-is/regs-fimc.h 4. User space interfaces ======================== @@ -143,7 +143,8 @@ or retrieve the information from /dev/media? with help of the media-ctl tool: 6. Platform support =================== -The machine code (plat-s5p and arch/arm/mach-*) must select following options +The machine code (arch/arm/plat-samsung and arch/arm/mach-*) must select +following options: CONFIG_S5P_DEV_FIMC0 mandatory CONFIG_S5P_DEV_FIMC1 \ -- GitLab From 038f5c4be7e8cc100c35a5aedb2557004c280cfa Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 28 May 2013 18:26:20 -0300 Subject: [PATCH 2009/2900] [media] MAINTAINERS: Update S5P/Exynos FIMC driver entry This change is mainly to update the driver's path changed from drivers/media/platform/s5p-fimc to drivers/media/platform/exynos4-is/. While at it, remove non-existent files rule, move the whole entry to the Samsung drivers section and add the patch tracking system site URL. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5be702cc8449..af77eb1d8293 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1153,15 +1153,6 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/platform/s5p-g2d/ -ARM/SAMSUNG S5P SERIES FIMC SUPPORT -M: Kyungmin Park -M: Sylwester Nawrocki -L: linux-arm-kernel@lists.infradead.org -L: linux-media@vger.kernel.org -S: Maintained -F: arch/arm/plat-samsung/include/plat/*fimc* -F: drivers/media/platform/s5p-fimc/ - ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT M: Kyungmin Park M: Kamil Debski @@ -6965,6 +6956,15 @@ F: drivers/regulator/s5m*.c F: drivers/rtc/rtc-sec.c F: include/linux/mfd/samsung/ +SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS +M: Kyungmin Park +M: Sylwester Nawrocki +L: linux-media@vger.kernel.org +Q: https://patchwork.linuxtv.org/project/linux-media/list/ +S: Supported +F: drivers/media/platform/exynos4-is/ +F: include/media/s5p_fimc.h + SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER M: Sylwester Nawrocki L: linux-media@vger.kernel.org -- GitLab From b1d2dc5c4d39d4e6c405419ad1f444bf59874111 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 20 Jun 2013 10:57:47 -0300 Subject: [PATCH 2010/2900] [media] exynos4-is: Fix format propagation on FIMC-LITE.n subdevs FIMC-LITE subdevs have one sink pad and two source pads on which the image formats are always same. This patch implements missing format propagation from the sink pad to the source pads, to allow user space to negotiate TRY format on whole media pipeline involving FIMC-LITE.n subdevs. The subdev try_fmt helper is simplified. Signed-off-by: Sylwester Nawrocki Signed-off-by: Jacek Anaszewski Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 92 ++++++++++++------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 07767c8b1c62..993bd798f3d2 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -560,37 +560,51 @@ static const struct v4l2_file_operations fimc_lite_fops = { * Format and crop negotiation helpers */ -static const struct fimc_fmt *fimc_lite_try_format(struct fimc_lite *fimc, - u32 *width, u32 *height, - u32 *code, u32 *fourcc, int pad) +static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format) { struct flite_drvdata *dd = fimc->dd; - const struct fimc_fmt *fmt; - unsigned int flags = 0; + struct v4l2_mbus_framefmt *mf = &format->format; + const struct fimc_fmt *fmt = NULL; + + if (format->pad == FLITE_SD_PAD_SINK) { + v4l_bound_align_image(&mf->width, 8, dd->max_width, + ffs(dd->out_width_align) - 1, + &mf->height, 0, dd->max_height, 0, 0); - if (pad == FLITE_SD_PAD_SINK) { - v4l_bound_align_image(width, 8, dd->max_width, - ffs(dd->out_width_align) - 1, - height, 0, dd->max_height, 0, 0); + fmt = fimc_lite_find_format(NULL, &mf->code, 0, 0); + if (WARN_ON(!fmt)) + return NULL; + + mf->code = fmt->mbus_code; } else { - v4l_bound_align_image(width, 8, fimc->inp_frame.rect.width, - ffs(dd->out_width_align) - 1, - height, 0, fimc->inp_frame.rect.height, - 0, 0); - flags = fimc->inp_frame.fmt->flags; - } + struct flite_frame *sink = &fimc->inp_frame; + struct v4l2_mbus_framefmt *sink_fmt; + struct v4l2_rect *rect; - fmt = fimc_lite_find_format(fourcc, code, flags, 0); - if (WARN_ON(!fmt)) - return NULL; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + sink_fmt = v4l2_subdev_get_try_format(fh, + FLITE_SD_PAD_SINK); - if (code) - *code = fmt->mbus_code; - if (fourcc) - *fourcc = fmt->fourcc; + mf->code = sink_fmt->code; + + rect = v4l2_subdev_get_try_crop(fh, + FLITE_SD_PAD_SINK); + } else { + mf->code = sink->fmt->mbus_code; + rect = &sink->rect; + } + + /* Allow changing format only on sink pad */ + mf->width = rect->width; + mf->height = rect->height; + } - v4l2_dbg(1, debug, &fimc->subdev, "code: 0x%x, %dx%d\n", - code ? *code : 0, *width, *height); + mf->field = V4L2_FIELD_NONE; + + v4l2_dbg(1, debug, &fimc->subdev, "code: %#x (%d), %dx%d\n", + mf->code, mf->colorspace, mf->width, mf->height); return fmt; } @@ -1035,6 +1049,15 @@ static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd, return 0; } +static struct v4l2_mbus_framefmt *__fimc_lite_subdev_get_try_fmt( + struct v4l2_subdev_fh *fh, unsigned int pad) +{ + if (pad != FLITE_SD_PAD_SINK) + pad = FLITE_SD_PAD_SOURCE_DMA; + + return v4l2_subdev_get_try_format(fh, pad); +} + static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) @@ -1044,7 +1067,7 @@ static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, struct flite_frame *f = &fimc->inp_frame; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); + mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad); fmt->format = *mf; return 0; } @@ -1090,12 +1113,20 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, return -EBUSY; } - ffmt = fimc_lite_try_format(fimc, &mf->width, &mf->height, - &mf->code, NULL, fmt->pad); + ffmt = fimc_lite_subdev_try_fmt(fimc, fh, fmt); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); + struct v4l2_mbus_framefmt *src_fmt; + + mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad); *mf = fmt->format; + + if (fmt->pad == FLITE_SD_PAD_SINK) { + unsigned int pad = FLITE_SD_PAD_SOURCE_DMA; + src_fmt = __fimc_lite_subdev_get_try_fmt(fh, pad); + *src_fmt = *mf; + } + mutex_unlock(&fimc->lock); return 0; } @@ -1113,11 +1144,6 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, source->rect = sink->rect; source->f_width = mf->width; source->f_height = mf->height; - } else { - /* Allow changing format only on sink pad */ - mf->code = sink->fmt->mbus_code; - mf->width = sink->rect.width; - mf->height = sink->rect.height; } mutex_unlock(&fimc->lock); -- GitLab From a055d97037ad09ad9b87f6a6e74a65a44b942102 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 18 Jun 2013 08:00:42 -0300 Subject: [PATCH 2011/2900] [media] exynos4-is: Set valid initial format at FIMC-LITE Ensure the image resolution and crop rectangle on the FIMC-LITE.n subdevs and fimc-lite.n.capture video nodes is properly configured upon the driver's initialization. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 23 ++++++++++++++++--- drivers/media/platform/exynos4-is/fimc-lite.h | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 993bd798f3d2..4fa2e05186bd 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1281,9 +1281,6 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) int ret; memset(vfd, 0, sizeof(*vfd)); - - fimc->inp_frame.fmt = &fimc_lite_formats[0]; - fimc->out_frame.fmt = &fimc_lite_formats[0]; atomic_set(&fimc->out_path, FIMC_IO_DMA); snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", @@ -1399,6 +1396,23 @@ static const struct v4l2_ctrl_config fimc_lite_ctrl = { .step = 1, }; +static void fimc_lite_set_default_config(struct fimc_lite *fimc) +{ + struct flite_frame *sink = &fimc->inp_frame; + struct flite_frame *source = &fimc->out_frame; + + sink->fmt = &fimc_lite_formats[0]; + sink->f_width = FLITE_DEFAULT_WIDTH; + sink->f_height = FLITE_DEFAULT_HEIGHT; + + sink->rect.width = FLITE_DEFAULT_WIDTH; + sink->rect.height = FLITE_DEFAULT_HEIGHT; + sink->rect.left = 0; + sink->rect.top = 0; + + *source = *sink; +} + static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) { struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler; @@ -1544,8 +1558,11 @@ static int fimc_lite_probe(struct platform_device *pdev) ret = PTR_ERR(fimc->alloc_ctx); goto err_pm; } + pm_runtime_put(dev); + fimc_lite_set_default_config(fimc); + dev_dbg(dev, "FIMC-LITE.%d registered successfully\n", fimc->index); return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index c98f3da74870..7428b2d22b52 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -29,6 +29,8 @@ #define FLITE_CLK_NAME "flite" #define FIMC_LITE_MAX_DEVS 3 #define FLITE_REQ_BUFS_MIN 2 +#define FLITE_DEFAULT_WIDTH 640 +#define FLITE_DEFAULT_HEIGHT 480 /* Bit index definitions for struct fimc_lite::state */ enum { -- GitLab From 5cfaad64d88a1bb52a6f779be02a69a2d50860fb Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 18 Jun 2013 13:42:30 -0300 Subject: [PATCH 2012/2900] [media] exynos4-is: Fix format propagation on FIMC-IS-ISP subdev Ensure TRY formats are propagated from the sink pad to the source pads of the FIMC-IS-ISP subdev and the TRY and ACTIVE formats are separated. [mchehab@redhat.com: Whitespace cleanup] Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-isp.c | 92 ++++++++++++++------ drivers/media/platform/exynos4-is/fimc-isp.h | 3 +- 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index ecb82a9517f3..f859b3cdd409 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -128,31 +128,28 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct fimc_is *is = fimc_isp_to_is(isp); struct v4l2_mbus_framefmt *mf = &fmt->format; - struct v4l2_mbus_framefmt cur_fmt; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); - fmt->format = *mf; + *mf = *v4l2_subdev_get_try_format(fh, fmt->pad); return 0; } mf->colorspace = V4L2_COLORSPACE_SRGB; mutex_lock(&isp->subdev_lock); - __is_get_frame_size(is, &cur_fmt); if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - /* full camera input frame size */ - mf->width = cur_fmt.width + FIMC_ISP_CAC_MARGIN_WIDTH; - mf->height = cur_fmt.height + FIMC_ISP_CAC_MARGIN_HEIGHT; - mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + /* ISP OTF input image format */ + *mf = isp->sink_fmt; } else { - /* crop size */ - mf->width = cur_fmt.width; - mf->height = cur_fmt.height; - mf->code = V4L2_MBUS_FMT_YUV10_1X30; + /* ISP OTF output image format */ + *mf = isp->src_fmt; + + if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { + mf->colorspace = V4L2_COLORSPACE_JPEG; + mf->code = V4L2_MBUS_FMT_YUV10_1X30; + } } mutex_unlock(&isp->subdev_lock); @@ -164,21 +161,37 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, } static void __isp_subdev_try_format(struct fimc_isp *isp, - struct v4l2_subdev_format *fmt) + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) { struct v4l2_mbus_framefmt *mf = &fmt->format; + struct v4l2_mbus_framefmt *format; + + mf->colorspace = V4L2_COLORSPACE_SRGB; if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { v4l_bound_align_image(&mf->width, FIMC_ISP_SINK_WIDTH_MIN, FIMC_ISP_SINK_WIDTH_MAX, 0, &mf->height, FIMC_ISP_SINK_HEIGHT_MIN, FIMC_ISP_SINK_HEIGHT_MAX, 0, 0); - isp->subdev_fmt = *mf; + mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; } else { + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + format = v4l2_subdev_get_try_format(fh, + FIMC_ISP_SD_PAD_SINK); + else + format = &isp->sink_fmt; + /* Allow changing format only on sink pad */ - mf->width = isp->subdev_fmt.width - FIMC_ISP_CAC_MARGIN_WIDTH; - mf->height = isp->subdev_fmt.height - FIMC_ISP_CAC_MARGIN_HEIGHT; - mf->code = isp->subdev_fmt.code; + mf->width = format->width - FIMC_ISP_CAC_MARGIN_WIDTH; + mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT; + + if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { + mf->code = V4L2_MBUS_FMT_YUV10_1X30; + mf->colorspace = V4L2_COLORSPACE_JPEG; + } else { + mf->code = format->code; + } } } @@ -194,24 +207,47 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd, isp_dbg(1, sd, "%s: pad%d: code: 0x%x, %dx%d\n", __func__, fmt->pad, mf->code, mf->width, mf->height); - mf->colorspace = V4L2_COLORSPACE_SRGB; - mutex_lock(&isp->subdev_lock); - __isp_subdev_try_format(isp, fmt); + __isp_subdev_try_format(isp, fh, fmt); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { mf = v4l2_subdev_get_try_format(fh, fmt->pad); *mf = fmt->format; - mutex_unlock(&isp->subdev_lock); - return 0; + + /* Propagate format to the source pads */ + if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { + struct v4l2_subdev_format format = *fmt; + unsigned int pad; + + for (pad = FIMC_ISP_SD_PAD_SRC_FIFO; + pad < FIMC_ISP_SD_PADS_NUM; pad++) { + format.pad = pad; + __isp_subdev_try_format(isp, fh, &format); + mf = v4l2_subdev_get_try_format(fh, pad); + *mf = format.format; + } + } + } else { + if (sd->entity.stream_count == 0) { + if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { + struct v4l2_subdev_format format = *fmt; + + isp->sink_fmt = *mf; + + format.pad = FIMC_ISP_SD_PAD_SRC_DMA; + __isp_subdev_try_format(isp, fh, &format); + + isp->src_fmt = format.format; + __is_set_frame_size(is, &isp->src_fmt); + } else { + isp->src_fmt = *mf; + } + } else { + ret = -EBUSY; + } } - if (sd->entity.stream_count == 0) - __is_set_frame_size(is, mf); - else - ret = -EBUSY; mutex_unlock(&isp->subdev_lock); - return ret; } diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index 756063e77fb8..03bf95ab017b 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -145,7 +145,8 @@ struct fimc_isp { struct vb2_alloc_ctx *alloc_ctx; struct v4l2_subdev subdev; struct media_pad subdev_pads[FIMC_ISP_SD_PADS_NUM]; - struct v4l2_mbus_framefmt subdev_fmt; + struct v4l2_mbus_framefmt src_fmt; + struct v4l2_mbus_framefmt sink_fmt; struct v4l2_ctrl *test_pattern; struct fimc_isp_ctrls ctrls; -- GitLab From 949457305ea602591e1fe060e6d8385a6b4a9516 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 18 Jun 2013 14:50:50 -0300 Subject: [PATCH 2013/2900] [media] exynos4-is: Set valid initial format on FIMC-IS-ISP subdev pads Ensure there is a valid initial resolution and pixel format set at the FIMC-IS-ISP subdev pads. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-isp.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index f859b3cdd409..cf520a7d7f71 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -645,6 +645,22 @@ static const struct v4l2_ctrl_ops fimc_isp_ctrl_ops = { .s_ctrl = fimc_is_s_ctrl, }; +static void __isp_subdev_set_default_format(struct fimc_isp *isp) +{ + struct fimc_is *is = fimc_isp_to_is(isp); + + isp->sink_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + + FIMC_ISP_CAC_MARGIN_WIDTH; + isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + + FIMC_ISP_CAC_MARGIN_HEIGHT; + isp->sink_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10; + + isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; + isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; + isp->src_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10; + __is_set_frame_size(is, &isp->src_fmt); +} + int fimc_isp_subdev_create(struct fimc_isp *isp) { const struct v4l2_ctrl_ops *ops = &fimc_isp_ctrl_ops; @@ -725,6 +741,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp) sd->entity.ops = &fimc_is_subdev_media_ops; v4l2_set_subdevdata(sd, isp); + __isp_subdev_set_default_format(isp); + return 0; } -- GitLab From 3ad8624524e5cae532381461e929bee649a92994 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Tue, 18 Jun 2013 14:56:11 -0300 Subject: [PATCH 2014/2900] [media] exynos4-is: Set valid initial format on FIMC.n subdevs Ensure there are valid initial image formats on the FIMC.n subdev pads. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/exynos4-is/fimc-capture.c | 19 +++++++++++++++++-- drivers/media/platform/exynos4-is/fimc-core.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 2b045b6db569..fb27ff7e1e07 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -1722,8 +1722,8 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, .fmt.pix_mp = { - .width = 640, - .height = 480, + .width = FIMC_DEFAULT_WIDTH, + .height = FIMC_DEFAULT_HEIGHT, .pixelformat = V4L2_PIX_FMT_YUYV, .field = V4L2_FIELD_NONE, .colorspace = V4L2_COLORSPACE_JPEG, @@ -1741,6 +1741,7 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, struct vb2_queue *q = &fimc->vid_cap.vbq; struct fimc_ctx *ctx; struct fimc_vid_cap *vid_cap; + struct fimc_fmt *fmt; int ret = -ENOMEM; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); @@ -1788,6 +1789,20 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, if (ret) goto err_free_ctx; + /* Default format configuration */ + fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); + vid_cap->ci_fmt.width = FIMC_DEFAULT_WIDTH; + vid_cap->ci_fmt.height = FIMC_DEFAULT_HEIGHT; + vid_cap->ci_fmt.code = fmt->mbus_code; + + ctx->s_frame.width = FIMC_DEFAULT_WIDTH; + ctx->s_frame.height = FIMC_DEFAULT_HEIGHT; + ctx->s_frame.fmt = fmt; + + fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_WRITEBACK, 0); + vid_cap->wb_fmt = vid_cap->ci_fmt; + vid_cap->wb_fmt.code = fmt->mbus_code; + vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); if (ret) diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 349c7c01e49a..3d376faec777 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -48,6 +48,8 @@ #define FIMC_DEF_MIN_SIZE 16 #define FIMC_DEF_HEIGHT_ALIGN 2 #define FIMC_DEF_HOR_OFFS_ALIGN 1 +#define FIMC_DEFAULT_WIDTH 640 +#define FIMC_DEFAULT_HEIGHT 480 /* indices to the clocks array */ enum { -- GitLab From 1c26190a8d492adadac4711fe5762d46204b18b0 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 20 Jun 2013 10:49:09 -0300 Subject: [PATCH 2015/2900] [media] exynos4-is: Correct colorspace handling at FIMC-LITE Ensure the colorspace is properly adjusted by the driver for YUV and Bayer image formats. The subdev try_fmt helper is simplified. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/fimc-lite.c | 17 +++++++++++++---- include/media/s5p_fimc.h | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 4fa2e05186bd..08fbfedea90f 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -44,6 +44,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { { .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, .memplanes = 1, @@ -52,6 +53,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, CbYCrY", .fourcc = V4L2_PIX_FMT_UYVY, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_CBYCRY422, .memplanes = 1, @@ -60,6 +62,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, CrYCbY", .fourcc = V4L2_PIX_FMT_VYUY, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_CRYCBY422, .memplanes = 1, @@ -68,6 +71,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_YCRYCB422, .memplanes = 1, @@ -76,6 +80,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW8 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG8, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 8 }, .color = FIMC_FMT_RAW8, .memplanes = 1, @@ -84,6 +89,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW10 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG10, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 10 }, .color = FIMC_FMT_RAW10, .memplanes = 1, @@ -92,6 +98,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW12 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG12, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 12 }, .color = FIMC_FMT_RAW12, .memplanes = 1, @@ -577,6 +584,7 @@ static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc, if (WARN_ON(!fmt)) return NULL; + mf->colorspace = fmt->colorspace; mf->code = fmt->mbus_code; } else { struct flite_frame *sink = &fimc->inp_frame; @@ -588,11 +596,13 @@ static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc, FLITE_SD_PAD_SINK); mf->code = sink_fmt->code; + mf->colorspace = sink_fmt->colorspace; rect = v4l2_subdev_get_try_crop(fh, FLITE_SD_PAD_SINK); } else { mf->code = sink->fmt->mbus_code; + mf->colorspace = sink->fmt->colorspace; rect = &sink->rect; } @@ -696,7 +706,7 @@ static int fimc_lite_g_fmt_mplane(struct file *file, void *fh, pixm->width = frame->f_width; pixm->height = frame->f_height; pixm->field = V4L2_FIELD_NONE; - pixm->colorspace = V4L2_COLORSPACE_JPEG; + pixm->colorspace = fmt->colorspace; return 0; } @@ -739,7 +749,7 @@ static int fimc_lite_try_fmt(struct fimc_lite *fimc, fmt->depth[0]) / 8; pixm->num_planes = fmt->memplanes; pixm->pixelformat = fmt->fourcc; - pixm->colorspace = V4L2_COLORSPACE_JPEG; + pixm->colorspace = fmt->colorspace; pixm->field = V4L2_FIELD_NONE; return 0; } @@ -1071,9 +1081,9 @@ static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, fmt->format = *mf; return 0; } - mf->colorspace = V4L2_COLORSPACE_JPEG; mutex_lock(&fimc->lock); + mf->colorspace = f->fmt->colorspace; mf->code = f->fmt->mbus_code; if (fmt->pad == FLITE_SD_PAD_SINK) { @@ -1102,7 +1112,6 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d\n", fmt->pad, mf->code, mf->width, mf->height); - mf->colorspace = V4L2_COLORSPACE_JPEG; mutex_lock(&fimc->lock); if ((atomic_read(&fimc->out_path) == FIMC_IO_ISP && diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h index 0afadb663bbd..b975c285c8a9 100644 --- a/include/media/s5p_fimc.h +++ b/include/media/s5p_fimc.h @@ -116,6 +116,7 @@ struct s5p_platform_fimc { * @color: the driver's private color format id * @memplanes: number of physically non-contiguous data planes * @colplanes: number of physically contiguous data planes + * @colorspace: v4l2 colorspace (V4L2_COLORSPACE_*) * @depth: per plane driver's private 'number of bits per pixel' * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no) * @flags: flags indicating which operation mode format applies to @@ -127,6 +128,7 @@ struct fimc_fmt { u32 color; u16 memplanes; u16 colplanes; + u8 colorspace; u8 depth[FIMC_MAX_PLANES]; u16 mdataplanes; u16 flags; -- GitLab From a6b3f7614ca690e49e934c291f707b0c19312194 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 28 Jun 2013 21:32:27 +0200 Subject: [PATCH 2016/2900] block: Reserve only one queue tag for sync IO if only 3 tags are available In case a device has three tags available we still reserve two of them for sync IO. That leaves only a single tag for async IO such as writeback from flusher thread which results in poor performance. Allow async IO to consume two tags in case queue has three tag availabe to get a decent async write performance. This patch improves streaming write performance on a machine with such disk from ~21 MB/s to ~52 MB/s. Also postmark throughput in presence of streaming writer improves from 8 to 12 transactions per second so sync IO doesn't seem to be harmed in presence of heavy async writer. Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- block/blk-tag.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/block/blk-tag.c b/block/blk-tag.c index cc345e1d8d4e..3f33d8672268 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -348,9 +348,16 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) */ max_depth = bqt->max_depth; if (!rq_is_sync(rq) && max_depth > 1) { - max_depth -= 2; - if (!max_depth) + switch (max_depth) { + case 2: max_depth = 1; + break; + case 3: + max_depth = 2; + break; + default: + max_depth -= 2; + } if (q->in_flight[BLK_RW_ASYNC] > max_depth) return 1; } -- GitLab From b50df95c8f0703c95625181d2eaf53855c5ebee5 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 28 Jun 2013 18:17:22 -0700 Subject: [PATCH 2017/2900] power_supply: Move of_node out of the #ifdef CONFIG_OF Similar to linux/device.h, move of_node struct member out of the #ifdef CONFIG_OF so that the drivers won't have to mess with #ifdefs in .c files. Signed-off-by: Anton Vorontsov --- include/linux/power_supply.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 3828cefb4f65..804b90643a85 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -162,6 +162,8 @@ union power_supply_propval { const char *strval; }; +struct device_node; + struct power_supply { const char *name; enum power_supply_type type; @@ -173,9 +175,7 @@ struct power_supply { char **supplied_from; size_t num_supplies; -#ifdef CONFIG_OF struct device_node *of_node; -#endif int (*get_property)(struct power_supply *psy, enum power_supply_property psp, -- GitLab From 2054d6e90e26b01ac0f125a42fecba63f226e55e Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 10 Jun 2013 17:26:39 -0400 Subject: [PATCH 2018/2900] power_supply: Add of_node_put to fix refcount of_parse_phandle increments the refcount for a dt node before returning it. Add of_node_put where needed to properly decrement the refcount when we are done using a given node. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/power_supply_core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 1c517c34e4be..3b2d5df45e7a 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -109,8 +109,10 @@ static int __power_supply_populate_supplied_from(struct device *dev, psy->name, epsy->name); psy->supplied_from[i-1] = (char *)epsy->name; psy->num_supplies++; + of_node_put(np); break; } + of_node_put(np); } while (np); return 0; @@ -193,8 +195,10 @@ static int power_supply_check_supplies(struct power_supply *psy) ret = power_supply_find_supply_from_node(np); if (ret) { dev_dbg(psy->dev, "Failed to find supply, defer!\n"); + of_node_put(np); return -EPROBE_DEFER; } + of_node_put(np); } while (np); /* All supplies found, allocate char ** array for filling */ -- GitLab From 89a22b1a9850028bd216457397321db5a5ee18f5 Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 10 Jun 2013 17:26:40 -0400 Subject: [PATCH 2019/2900] sbs-battery: Add dt to power_supply struct By passing in the dt node of this device, we enable the logic for linking power_supplies together from dt. This is specified by adding a "power-supplies" property with a phandle to the charger for a given supply. Enable this logic now for the sbs-battery driver. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/sbs-battery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c index c8c78a74e75a..b5f2a76b6cdf 100644 --- a/drivers/power/sbs-battery.c +++ b/drivers/power/sbs-battery.c @@ -704,6 +704,7 @@ static int sbs_probe(struct i2c_client *client, chip->power_supply.properties = sbs_properties; chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties); chip->power_supply.get_property = sbs_get_property; + chip->power_supply.of_node = client->dev.of_node; /* ignore first notification of external change, it is generated * from the power_supply_register call back */ -- GitLab From 605860bc2495cd584fd639f00806591af0b1fefa Mon Sep 17 00:00:00 2001 From: Rhyland Klein Date: Mon, 10 Jun 2013 17:26:41 -0400 Subject: [PATCH 2020/2900] tps65090-charger: Add dt node to power_supply Passing in the dt node for this charger enables the logic in the core to lookup this device, to see if it is supplying another power_supply, through dt. Signed-off-by: Rhyland Klein Signed-off-by: Anton Vorontsov --- drivers/power/tps65090-charger.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index e628f9813e08..bdd7b9b2546a 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c @@ -255,6 +255,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) cdata->ac.num_properties = ARRAY_SIZE(tps65090_ac_props); cdata->ac.supplied_to = pdata->supplied_to; cdata->ac.num_supplicants = pdata->num_supplicants; + cdata->ac.of_node = pdev->dev.of_node; ret = power_supply_register(&pdev->dev, &cdata->ac); if (ret) { -- GitLab From 3cc9d26966ea02f71258ab0553ebd3388f40533a Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Tue, 25 Jun 2013 14:02:49 +0900 Subject: [PATCH 2021/2900] charger-manager: Fix a bug when it unregisters notifier block of extcon This patch prevents NULL pointer error cauesed by unregistering unregistered exton notifier block. At the probing time of charger manager, it tries to remove extcon notifier block when it fails to initialize them. It has to be applied for only registered one. Otherwise, it'd make kernel panic. To make it work right, it checks extcon_specific_cable_nb's extcon_dev node. If extcon cable notifier block was registered successfully, it has proper extcon_dev pointer if not so it has NULL pointer. Signed-off-by: Jonghwa Lee Signed-off-by: Myungjoo Ham Acked-by: Chanwoo Choi Signed-off-by: Anton Vorontsov --- drivers/power/charger-manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index ba420292628e..8ad9698b55a9 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -1666,7 +1666,9 @@ static int charger_manager_probe(struct platform_device *pdev) charger = &desc->charger_regulators[i]; for (j = 0; j < charger->num_cables; j++) { struct charger_cable *cable = &charger->cables[j]; - extcon_unregister_interest(&cable->extcon_dev); + /* Remove notifier block if only edev exists */ + if (cable->extcon_dev.edev) + extcon_unregister_interest(&cable->extcon_dev); } regulator_put(desc->charger_regulators[i].consumer); -- GitLab From 5a6c2208455f25b3e6f939adc2da59aa00d4806e Mon Sep 17 00:00:00 2001 From: Jonghwa Lee Date: Tue, 25 Jun 2013 14:18:14 +0900 Subject: [PATCH 2022/2900] charger-manager: Fix regulator_get() return check This patch fixes return value checking of regulator_get() in charger-manager driver. The API, regulator_get(), returns ERR_PTR() when it fails to get regulator with given name, not NULL. Signed-off-by: Jonghwa Lee Signed-off-by: Myungjoo Ham Acked-by: Chanwoo Choi Signed-off-by: Anton Vorontsov --- drivers/power/charger-manager.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 8ad9698b55a9..e30e847600bb 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -1239,11 +1239,10 @@ static int charger_manager_register_extcon(struct charger_manager *cm) charger->consumer = regulator_get(cm->dev, charger->regulator_name); - if (charger->consumer == NULL) { + if (IS_ERR(charger->consumer)) { dev_err(cm->dev, "Cannot find charger(%s)\n", charger->regulator_name); - ret = -EINVAL; - goto err; + return PTR_ERR(charger->consumer); } charger->cm = cm; -- GitLab From 1ec047eb4751e331bc61cff0e98f0db67db8b8dc Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 27 Jun 2013 00:06:56 +0200 Subject: [PATCH 2023/2900] ipv6: introduce per-interface counter for dad-completed ipv6 addresses To reduce the number of unnecessary router solicitations, MLDv2 and IGMPv3 messages we need to track the number of valid (as in non-optimistic, no-dad-failed and non-tentative) link-local addresses. Therefore, this patch implements a valid_ll_addr_cnt in struct inet6_dev. We now only emit router solicitations if the first link-local address finishes duplicate address detection. The changes for MLDv2 and IGMPv3 are in a follow-up patch. While there, also simplify one if statement(one minor nit I made in one of my previous patches): if (!...) do(); else return; <> if (...) return; do(); Cc: Flavio Leitner Cc: YOSHIFUJI Hideaki Cc: David Stevens Suggested-by: David Stevens Signed-off-by: Hannes Frederic Sowa Acked-by: Flavio Leitner Signed-off-by: David S. Miller --- include/net/if_inet6.h | 1 + net/ipv6/addrconf.c | 39 +++++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index e4c5a2d2ba34..1628b8f5fb26 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -166,6 +166,7 @@ struct inet6_dev { struct net_device *dev; struct list_head addr_list; + int valid_ll_addr_cnt; struct ifmcaddr6 *mc_list; struct ifmcaddr6 *mc_tomb; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4e4cc1fc26d1..20d92ff2d690 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3277,6 +3277,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) { struct net_device *dev = ifp->idev->dev; struct in6_addr lladdr; + bool send_rs; addrconf_del_dad_timer(ifp); @@ -3290,20 +3291,25 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) router advertisements, start sending router solicitations. */ - if (ipv6_accept_ra(ifp->idev) && - ifp->idev->cnf.rtr_solicits > 0 && - (dev->flags&IFF_LOOPBACK) == 0 && - (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { + read_lock_bh(&ifp->idev->lock); + spin_lock(&ifp->lock); + send_rs = ipv6_accept_ra(ifp->idev) && + ifp->idev->cnf.rtr_solicits > 0 && + (dev->flags&IFF_LOOPBACK) == 0 && + ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL && + ifp->idev->valid_ll_addr_cnt == 1; + spin_unlock(&ifp->lock); + read_unlock_bh(&ifp->idev->lock); + + if (send_rs) { /* * If a host as already performed a random delay * [...] as part of DAD [...] there is no need * to delay again before sending the first RS */ - if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE)) - ndisc_send_rs(dev, &lladdr, - &in6addr_linklocal_allrouters); - else + if (ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE)) return; + ndisc_send_rs(dev, &lladdr, &in6addr_linklocal_allrouters); write_lock_bh(&ifp->idev->lock); spin_lock(&ifp->lock); @@ -4576,6 +4582,19 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, rtnl_set_sk_err(net, RTNLGRP_IPV6_PREFIX, err); } +static void update_valid_ll_addr_cnt(struct inet6_ifaddr *ifp, int count) +{ + write_lock_bh(&ifp->idev->lock); + spin_lock(&ifp->lock); + if (((ifp->flags & (IFA_F_PERMANENT|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC| + IFA_F_DADFAILED)) == IFA_F_PERMANENT) && + (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) + ifp->idev->valid_ll_addr_cnt += count; + WARN_ON(ifp->idev->valid_ll_addr_cnt < 0); + spin_unlock(&ifp->lock); + write_unlock_bh(&ifp->idev->lock); +} + static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) { struct net *net = dev_net(ifp->idev->dev); @@ -4584,6 +4603,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) switch (event) { case RTM_NEWADDR: + update_valid_ll_addr_cnt(ifp, 1); + /* * If the address was optimistic * we inserted the route at the start of @@ -4599,6 +4620,8 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) ifp->idev->dev, 0, 0); break; case RTM_DELADDR: + update_valid_ll_addr_cnt(ifp, -1); + if (ifp->idev->cnf.forwarding) addrconf_leave_anycast(ifp); addrconf_leave_solict(ifp->idev, &ifp->addr); -- GitLab From b173ee488dcc545e77ed482158a2f0d06d7a5860 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 27 Jun 2013 00:07:01 +0200 Subject: [PATCH 2024/2900] ipv6: resend MLD report if a link-local address completes DAD RFC3590/RFC3810 specifies we should resend MLD reports as soon as a valid link-local address is available. We now use the valid_ll_addr_cnt to check if it is necessary to resend a new report. Changes since Flavio Leitner's version: a) adapt for valid_ll_addr_cnt b) resend first reports directly in the path and just arm the timer for mc_qrv-1 resends. Reported-by: Flavio Leitner Cc: Hideaki YOSHIFUJI Cc: David Stevens Signed-off-by: Hannes Frederic Sowa Signed-off-by: Flavio Leitner Signed-off-by: David S. Miller --- include/net/addrconf.h | 1 + include/net/if_inet6.h | 2 ++ net/ipv6/addrconf.c | 17 ++++++++++---- net/ipv6/mcast.c | 52 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 21f702704f24..f68eaf574d7e 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -155,6 +155,7 @@ extern bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, const struct in6_addr *src_addr); +extern void ipv6_mc_dad_complete(struct inet6_dev *idev); /* * identify MLD packets for MLD filter exceptions */ diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 1628b8f5fb26..736b5fb95474 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -174,10 +174,12 @@ struct inet6_dev { unsigned char mc_qrv; unsigned char mc_gq_running; unsigned char mc_ifc_count; + unsigned char mc_dad_count; unsigned long mc_v1_seen; unsigned long mc_maxdelay; struct timer_list mc_gq_timer; /* general query timer */ struct timer_list mc_ifc_timer; /* interface change timer */ + struct timer_list mc_dad_timer; /* dad complete mc timer */ struct ifacaddr6 *ac_list; rwlock_t lock; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 20d92ff2d690..12dd2fec045c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3277,7 +3277,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) { struct net_device *dev = ifp->idev->dev; struct in6_addr lladdr; - bool send_rs; + bool send_rs, send_mld; addrconf_del_dad_timer(ifp); @@ -3293,14 +3293,21 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) read_lock_bh(&ifp->idev->lock); spin_lock(&ifp->lock); - send_rs = ipv6_accept_ra(ifp->idev) && + send_mld = ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL && + ifp->idev->valid_ll_addr_cnt == 1; + send_rs = send_mld && + ipv6_accept_ra(ifp->idev) && ifp->idev->cnf.rtr_solicits > 0 && - (dev->flags&IFF_LOOPBACK) == 0 && - ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL && - ifp->idev->valid_ll_addr_cnt == 1; + (dev->flags&IFF_LOOPBACK) == 0; spin_unlock(&ifp->lock); read_unlock_bh(&ifp->idev->lock); + /* While dad is in progress mld report's source address is in6_addrany. + * Resend with proper ll now. + */ + if (send_mld) + ipv6_mc_dad_complete(ifp->idev); + if (send_rs) { /* * If a host as already performed a random delay diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 72c8bfe06bb4..502c877cbf10 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -999,6 +999,14 @@ static void mld_ifc_start_timer(struct inet6_dev *idev, int delay) in6_dev_hold(idev); } +static void mld_dad_start_timer(struct inet6_dev *idev, int delay) +{ + int tv = net_random() % delay; + + if (!mod_timer(&idev->mc_dad_timer, jiffies+tv+2)) + in6_dev_hold(idev); +} + /* * IGMP handling (alias multicast ICMPv6 messages) */ @@ -1815,6 +1823,46 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) goto out; } +static void mld_resend_report(struct inet6_dev *idev) +{ + if (MLD_V1_SEEN(idev)) { + struct ifmcaddr6 *mcaddr; + read_lock_bh(&idev->lock); + for (mcaddr = idev->mc_list; mcaddr; mcaddr = mcaddr->next) { + if (!(mcaddr->mca_flags & MAF_NOREPORT)) + igmp6_send(&mcaddr->mca_addr, idev->dev, + ICMPV6_MGM_REPORT); + } + read_unlock_bh(&idev->lock); + } else { + mld_send_report(idev, NULL); + } +} + +void ipv6_mc_dad_complete(struct inet6_dev *idev) +{ + idev->mc_dad_count = idev->mc_qrv; + if (idev->mc_dad_count) { + mld_resend_report(idev); + idev->mc_dad_count--; + if (idev->mc_dad_count) + mld_dad_start_timer(idev, idev->mc_maxdelay); + } +} + +static void mld_dad_timer_expire(unsigned long data) +{ + struct inet6_dev *idev = (struct inet6_dev *)data; + + mld_resend_report(idev); + if (idev->mc_dad_count) { + idev->mc_dad_count--; + if (idev->mc_dad_count) + mld_dad_start_timer(idev, idev->mc_maxdelay); + } + __in6_dev_put(idev); +} + static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, const struct in6_addr *psfsrc) { @@ -2232,6 +2280,8 @@ void ipv6_mc_down(struct inet6_dev *idev) idev->mc_gq_running = 0; if (del_timer(&idev->mc_gq_timer)) __in6_dev_put(idev); + if (del_timer(&idev->mc_dad_timer)) + __in6_dev_put(idev); for (i = idev->mc_list; i; i=i->next) igmp6_group_dropped(i); @@ -2268,6 +2318,8 @@ void ipv6_mc_init_dev(struct inet6_dev *idev) idev->mc_ifc_count = 0; setup_timer(&idev->mc_ifc_timer, mld_ifc_timer_expire, (unsigned long)idev); + setup_timer(&idev->mc_dad_timer, mld_dad_timer_expire, + (unsigned long)idev); idev->mc_qrv = MLD_QRV_DEFAULT; idev->mc_maxdelay = IGMP6_UNSOLICITED_IVAL; idev->mc_v1_seen = 0; -- GitLab From 2ffae99d1fac272952b5a395759823717760ce37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 27 Jun 2013 10:27:05 +0300 Subject: [PATCH 2025/2900] ipv4: use next hop exceptions also for input routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d2d68ba9 (ipv4: Cache input routes in fib_info nexthops) assmued that "locally destined, and routed packets, never trigger PMTU events or redirects that will be processed by us". However, it seems that tunnel devices do trigger PMTU events in certain cases. At least ip_gre, ip6_gre, sit, and ipip do use the inner flow's skb_dst(skb)->ops->update_pmtu to propage mtu information from the outer flows. These can cause the inner flow mtu to be decreased. If next hop exceptions are not consulted for pmtu, IP fragmentation will not be done properly for these routes. It also seems that we really need to have the PMTU information always for netfilter TCPMSS clamp-to-pmtu feature to work properly. So for the time being, cache separate copies of input routes for each next hop exception. Signed-off-by: Timo Teräs Reviewed-by: Julian Anastasov Signed-off-by: David S. Miller --- include/net/ip_fib.h | 3 +- net/ipv4/fib_semantics.c | 3 +- net/ipv4/route.c | 65 ++++++++++++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 44424e9dab2a..aac85534d7b5 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -56,7 +56,8 @@ struct fib_nh_exception { u32 fnhe_pmtu; __be32 fnhe_gw; unsigned long fnhe_expires; - struct rtable __rcu *fnhe_rth; + struct rtable __rcu *fnhe_rth_input; + struct rtable __rcu *fnhe_rth_output; unsigned long fnhe_stamp; }; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 8f6cb7a87cd6..d5dbca5ecf62 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -169,7 +169,8 @@ static void free_nh_exceptions(struct fib_nh *nh) next = rcu_dereference_protected(fnhe->fnhe_next, 1); - rt_fibinfo_free(&fnhe->fnhe_rth); + rt_fibinfo_free(&fnhe->fnhe_rth_input); + rt_fibinfo_free(&fnhe->fnhe_rth_output); kfree(fnhe); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f3fa42eac461..a9a54a236832 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -565,10 +565,25 @@ static inline void rt_free(struct rtable *rt) static DEFINE_SPINLOCK(fnhe_lock); +static void fnhe_flush_routes(struct fib_nh_exception *fnhe) +{ + struct rtable *rt; + + rt = rcu_dereference(fnhe->fnhe_rth_input); + if (rt) { + RCU_INIT_POINTER(fnhe->fnhe_rth_input, NULL); + rt_free(rt); + } + rt = rcu_dereference(fnhe->fnhe_rth_output); + if (rt) { + RCU_INIT_POINTER(fnhe->fnhe_rth_output, NULL); + rt_free(rt); + } +} + static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) { struct fib_nh_exception *fnhe, *oldest; - struct rtable *orig; oldest = rcu_dereference(hash->chain); for (fnhe = rcu_dereference(oldest->fnhe_next); fnhe; @@ -576,11 +591,7 @@ static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash) if (time_before(fnhe->fnhe_stamp, oldest->fnhe_stamp)) oldest = fnhe; } - orig = rcu_dereference(oldest->fnhe_rth); - if (orig) { - RCU_INIT_POINTER(oldest->fnhe_rth, NULL); - rt_free(orig); - } + fnhe_flush_routes(oldest); return oldest; } @@ -644,7 +655,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, fnhe->fnhe_expires = max(1UL, expires); } /* Update all cached dsts too */ - rt = rcu_dereference(fnhe->fnhe_rth); + rt = rcu_dereference(fnhe->fnhe_rth_input); + if (rt) + fill_route_from_fnhe(rt, fnhe); + rt = rcu_dereference(fnhe->fnhe_rth_output); if (rt) fill_route_from_fnhe(rt, fnhe); } else { @@ -668,6 +682,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, * stale, so anyone caching it rechecks if this exception * applies to them. */ + rt = rcu_dereference(nh->nh_rth_input); + if (rt) + rt->dst.obsolete = DST_OBSOLETE_KILL; + for_each_possible_cpu(i) { struct rtable __rcu **prt; prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i); @@ -1242,25 +1260,36 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { + struct rtable __rcu **porig; + struct rtable *orig; int genid = fnhe_genid(dev_net(rt->dst.dev)); - struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); + + if (rt_is_input_route(rt)) + porig = &fnhe->fnhe_rth_input; + else + porig = &fnhe->fnhe_rth_output; + orig = rcu_dereference(*porig); if (fnhe->fnhe_genid != genid) { fnhe->fnhe_genid = genid; fnhe->fnhe_gw = 0; fnhe->fnhe_pmtu = 0; fnhe->fnhe_expires = 0; + fnhe_flush_routes(fnhe); + orig = NULL; } fill_route_from_fnhe(rt, fnhe); if (!rt->rt_gateway) rt->rt_gateway = daddr; - rcu_assign_pointer(fnhe->fnhe_rth, rt); - if (orig) - rt_free(orig); + if (!(rt->dst.flags & DST_NOCACHE)) { + rcu_assign_pointer(*porig, rt); + if (orig) + rt_free(orig); + ret = true; + } fnhe->fnhe_stamp = jiffies; - ret = true; } spin_unlock_bh(&fnhe_lock); @@ -1492,6 +1521,7 @@ static int __mkroute_input(struct sk_buff *skb, struct in_device *in_dev, __be32 daddr, __be32 saddr, u32 tos) { + struct fib_nh_exception *fnhe; struct rtable *rth; int err; struct in_device *out_dev; @@ -1538,8 +1568,13 @@ static int __mkroute_input(struct sk_buff *skb, } } + fnhe = find_exception(&FIB_RES_NH(*res), daddr); if (do_cache) { - rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); + if (fnhe != NULL) + rth = rcu_dereference(fnhe->fnhe_rth_input); + else + rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); + if (rt_cache_valid(rth)) { skb_dst_set_noref(skb, &rth->dst); goto out; @@ -1567,7 +1602,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->dst.input = ip_forward; rth->dst.output = ip_output; - rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag); + rt_set_nexthop(rth, daddr, res, fnhe, res->fi, res->type, itag); skb_dst_set(skb, &rth->dst); out: err = 0; @@ -1882,7 +1917,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, fnhe = find_exception(nh, fl4->daddr); if (fnhe) - prth = &fnhe->fnhe_rth; + prth = &fnhe->fnhe_rth_output; else { if (unlikely(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH && -- GitLab From 803dee958390bd3e9e42a31dd8bdc4d1a8fa319f Mon Sep 17 00:00:00 2001 From: David Chang Date: Thu, 27 Jun 2013 17:16:42 +0800 Subject: [PATCH 2026/2900] usbnet: ax88179_178a: Correct a typo in description Correct a typo in description of driver_info, it should be Gigabit Signed-off-by: David Chang Signed-off-by: David S. Miller --- drivers/net/usb/ax88179_178a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index bd8758fa38c1..7ce243bf7088 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1371,7 +1371,7 @@ static int ax88179_stop(struct usbnet *dev) } static const struct driver_info ax88179_info = { - .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet", + .description = "ASIX AX88179 USB 3.0 Gigabit Ethernet", .bind = ax88179_bind, .unbind = ax88179_unbind, .status = ax88179_status, @@ -1384,7 +1384,7 @@ static const struct driver_info ax88179_info = { }; static const struct driver_info ax88178a_info = { - .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet", + .description = "ASIX AX88178A USB 2.0 Gigabit Ethernet", .bind = ax88179_bind, .unbind = ax88179_unbind, .status = ax88179_status, -- GitLab From b8553b89edf73122eba4419cc846a31ebf7bc894 Mon Sep 17 00:00:00 2001 From: David Chang Date: Thu, 27 Jun 2013 17:16:43 +0800 Subject: [PATCH 2027/2900] usbnet: ax88179_178a: add .reset_resume hook I tested with the AX88179 usb dongle, if without .reset_resume hook, after S3/S4 resume you have to enable network interface or reload the dirver module manually otherwise the network interface can not work. Signed-off-by: David Chang Signed-off-by: David S. Miller --- drivers/net/usb/ax88179_178a.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 7ce243bf7088..1e3c302d94fe 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1433,6 +1433,7 @@ static struct usb_driver ax88179_178a_driver = { .probe = usbnet_probe, .suspend = ax88179_suspend, .resume = ax88179_resume, + .reset_resume = ax88179_resume, .disconnect = usbnet_disconnect, .supports_autosuspend = 1, .disable_hub_initiated_lpm = 1, -- GitLab From bd79680956573dd70bfa207af6b143aa94980b96 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 28 Jun 2013 14:02:52 +0300 Subject: [PATCH 2028/2900] pch_gbe: remove inline keyword for exported functions There is no much sense to mark functions inline that are going to be used in the other compile modules. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- .../ethernet/oki-semi/pch_gbe/pch_gbe_api.c | 21 ++++++++++--------- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 2 +- .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.c | 3 +-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c index 5ae03e815ee9..82e72b21a8fb 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c @@ -19,6 +19,7 @@ */ #include "pch_gbe.h" #include "pch_gbe_phy.h" +#include "pch_gbe_api.h" /* bus type values */ #define pch_gbe_bus_type_unknown 0 @@ -112,7 +113,7 @@ static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw) * 0: Successfully * ENOSYS: Function is not registered */ -inline s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw) +s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw) { if (!hw->reg) { pr_err("ERROR: Registers not mapped\n"); @@ -126,7 +127,7 @@ inline s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw) * pch_gbe_hal_get_bus_info - Obtain bus information for adapter * @hw: Pointer to the HW structure */ -inline void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) +void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) { if (!hw->func->get_bus_info) pr_err("ERROR: configuration\n"); @@ -141,7 +142,7 @@ inline void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) * 0: Successfully * ENOSYS: Function is not registered */ -inline s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw) +s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw) { if (!hw->func->init_hw) { pr_err("ERROR: configuration\n"); @@ -159,7 +160,7 @@ inline s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw) * 0: Successfully * Negative value: Failed */ -inline s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, +s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data) { if (!hw->func->read_phy_reg) @@ -176,7 +177,7 @@ inline s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, * 0: Successfully * Negative value: Failed */ -inline s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, +s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data) { if (!hw->func->write_phy_reg) @@ -188,7 +189,7 @@ inline s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, * pch_gbe_hal_phy_hw_reset - Hard PHY reset * @hw: Pointer to the HW structure */ -inline void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw) +void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw) { if (!hw->func->reset_phy) pr_err("ERROR: configuration\n"); @@ -200,7 +201,7 @@ inline void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw) * pch_gbe_hal_phy_sw_reset - Soft PHY reset * @hw: Pointer to the HW structure */ -inline void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) +void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) { if (!hw->func->sw_reset_phy) pr_err("ERROR: configuration\n"); @@ -215,7 +216,7 @@ inline void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) * 0: Successfully * ENOSYS: Function is not registered */ -inline s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw) +s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw) { if (!hw->func->read_mac_addr) { pr_err("ERROR: configuration\n"); @@ -228,7 +229,7 @@ inline s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw) * pch_gbe_hal_power_up_phy - Power up PHY * @hw: Pointer to the HW structure */ -inline void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw) +void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw) { if (hw->func->power_up_phy) hw->func->power_up_phy(hw); @@ -238,7 +239,7 @@ inline void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw) * pch_gbe_hal_power_down_phy - Power down PHY * @hw: Pointer to the HW structure */ -inline void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw) +void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw) { if (hw->func->power_down_phy) hw->func->power_down_phy(hw); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 0c1c65a9ce5e..16d5ffac1981 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -287,7 +287,7 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; } -inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) +static inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) { iowrite32(0x01, &hw->reg->MAC_ADDR_LOAD); } diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c index 28bb9603d736..b97c6575e018 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c @@ -235,7 +235,7 @@ void pch_gbe_phy_power_down(struct pch_gbe_hw *hw) * pch_gbe_phy_set_rgmii - RGMII interface setting * @hw: Pointer to the HW structure */ -inline void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw) +void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw) { pch_gbe_phy_sw_reset(hw); } @@ -270,5 +270,4 @@ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) pch_gbe_phy_read_reg_miic(hw, PHY_PHYSP_CONTROL, &mii_reg); mii_reg |= PHYSP_CTRL_ASSERT_CRS_TX; pch_gbe_phy_write_reg_miic(hw, PHY_PHYSP_CONTROL, mii_reg); - } -- GitLab From 453ca931f515161902dbb325d7f39a992c3059ce Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 28 Jun 2013 14:02:53 +0300 Subject: [PATCH 2029/2900] pch_gbe: convert pr_* to netdev_* We may use nice macros to prefix our messages with proper device name. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- .../net/ethernet/oki-semi/pch_gbe/pch_gbe.h | 2 + .../ethernet/oki-semi/pch_gbe/pch_gbe_api.c | 49 +++- .../oki-semi/pch_gbe/pch_gbe_ethtool.c | 2 +- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 275 ++++++++++-------- .../ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 63 ++-- .../ethernet/oki-semi/pch_gbe/pch_gbe_phy.c | 23 +- 6 files changed, 250 insertions(+), 164 deletions(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h index 7fb7e178c74e..7779036690cc 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h @@ -633,6 +633,8 @@ struct pch_gbe_adapter { struct pci_dev *ptp_pdev; }; +#define pch_gbe_hw_to_adapter(hw) container_of(hw, struct pch_gbe_adapter, hw) + extern const char pch_driver_version[]; /* pch_gbe_main.c */ diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c index 82e72b21a8fb..ff3ad70935a6 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_api.c @@ -71,7 +71,9 @@ static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw) ret_val = pch_gbe_phy_get_id(hw); if (ret_val) { - pr_err("pch_gbe_phy_get_id error\n"); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "pch_gbe_phy_get_id error\n"); return ret_val; } pch_gbe_phy_init_setting(hw); @@ -116,7 +118,9 @@ static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw) s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw) { if (!hw->reg) { - pr_err("ERROR: Registers not mapped\n"); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: Registers not mapped\n"); return -ENOSYS; } pch_gbe_plat_init_function_pointers(hw); @@ -129,10 +133,13 @@ s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw) */ void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) { - if (!hw->func->get_bus_info) - pr_err("ERROR: configuration\n"); - else - hw->func->get_bus_info(hw); + if (!hw->func->get_bus_info) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: configuration\n"); + return; + } + hw->func->get_bus_info(hw); } /** @@ -145,7 +152,9 @@ void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw) s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw) { if (!hw->func->init_hw) { - pr_err("ERROR: configuration\n"); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: configuration\n"); return -ENOSYS; } return hw->func->init_hw(hw); @@ -191,10 +200,13 @@ s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, */ void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw) { - if (!hw->func->reset_phy) - pr_err("ERROR: configuration\n"); - else - hw->func->reset_phy(hw); + if (!hw->func->reset_phy) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: configuration\n"); + return; + } + hw->func->reset_phy(hw); } /** @@ -203,10 +215,13 @@ void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw) */ void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) { - if (!hw->func->sw_reset_phy) - pr_err("ERROR: configuration\n"); - else - hw->func->sw_reset_phy(hw); + if (!hw->func->sw_reset_phy) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: configuration\n"); + return; + } + hw->func->sw_reset_phy(hw); } /** @@ -219,7 +234,9 @@ void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw) s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw) { if (!hw->func->read_mac_addr) { - pr_err("ERROR: configuration\n"); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "ERROR: configuration\n"); return -ENOSYS; } return hw->func->read_mac_addr(hw); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c index 24b787be6062..1129db0cdf82 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c @@ -122,7 +122,7 @@ static int pch_gbe_set_settings(struct net_device *netdev, } ret = mii_ethtool_sset(&adapter->mii, ecmd); if (ret) { - pr_err("Error: mii_ethtool_sset\n"); + netdev_err(netdev, "Error: mii_ethtool_sset\n"); return ret; } hw->mac.link_speed = speed; diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 16d5ffac1981..97db56393197 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -300,6 +300,7 @@ static inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw) */ s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); u32 adr1a, adr1b; adr1a = ioread32(&hw->reg->mac_adr[0].high); @@ -312,7 +313,7 @@ s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw) hw->mac.addr[4] = (u8)(adr1b & 0xFF); hw->mac.addr[5] = (u8)((adr1b >> 8) & 0xFF); - pr_debug("hw->mac.addr : %pM\n", hw->mac.addr); + netdev_dbg(adapter->netdev, "hw->mac.addr : %pM\n", hw->mac.addr); return 0; } @@ -324,6 +325,7 @@ s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw) static void pch_gbe_wait_clr_bit(void *reg, u32 bit) { u32 tmp; + /* wait busy */ tmp = 1000; while ((ioread32(reg) & bit) && --tmp) @@ -340,9 +342,10 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit) */ static void pch_gbe_mac_mar_set(struct pch_gbe_hw *hw, u8 * addr, u32 index) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); u32 mar_low, mar_high, adrmask; - pr_debug("index : 0x%x\n", index); + netdev_dbg(adapter->netdev, "index : 0x%x\n", index); /* * HW expects these in little endian so we reverse the byte order @@ -468,10 +471,11 @@ static void pch_gbe_mac_mc_addr_list_update(struct pch_gbe_hw *hw, */ s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); struct pch_gbe_mac_info *mac = &hw->mac; u32 rx_fctrl; - pr_debug("mac->fc = %u\n", mac->fc); + netdev_dbg(adapter->netdev, "mac->fc = %u\n", mac->fc); rx_fctrl = ioread32(&hw->reg->RX_FCTRL); @@ -493,14 +497,16 @@ s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw) mac->tx_fc_enable = true; break; default: - pr_err("Flow control param set incorrectly\n"); + netdev_err(adapter->netdev, + "Flow control param set incorrectly\n"); return -EINVAL; } if (mac->link_duplex == DUPLEX_HALF) rx_fctrl &= ~PCH_GBE_FL_CTRL_EN; iowrite32(rx_fctrl, &hw->reg->RX_FCTRL); - pr_debug("RX_FCTRL reg : 0x%08x mac->tx_fc_enable : %d\n", - ioread32(&hw->reg->RX_FCTRL), mac->tx_fc_enable); + netdev_dbg(adapter->netdev, + "RX_FCTRL reg : 0x%08x mac->tx_fc_enable : %d\n", + ioread32(&hw->reg->RX_FCTRL), mac->tx_fc_enable); return 0; } @@ -511,10 +517,11 @@ s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw) */ static void pch_gbe_mac_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); u32 addr_mask; - pr_debug("wu_evt : 0x%08x ADDR_MASK reg : 0x%08x\n", - wu_evt, ioread32(&hw->reg->ADDR_MASK)); + netdev_dbg(adapter->netdev, "wu_evt : 0x%08x ADDR_MASK reg : 0x%08x\n", + wu_evt, ioread32(&hw->reg->ADDR_MASK)); if (wu_evt) { /* Set Wake-On-Lan address mask */ @@ -546,6 +553,7 @@ static void pch_gbe_mac_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt) u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg, u16 data) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); u32 data_out = 0; unsigned int i; unsigned long flags; @@ -558,7 +566,7 @@ u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg, udelay(20); } if (i == 0) { - pr_err("pch-gbe.miim won't go Ready\n"); + netdev_err(adapter->netdev, "pch-gbe.miim won't go Ready\n"); spin_unlock_irqrestore(&hw->miim_lock, flags); return 0; /* No way to indicate timeout error */ } @@ -573,9 +581,9 @@ u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg, } spin_unlock_irqrestore(&hw->miim_lock, flags); - pr_debug("PHY %s: reg=%d, data=0x%04X\n", - dir == PCH_GBE_MIIM_OPER_READ ? "READ" : "WRITE", reg, - dir == PCH_GBE_MIIM_OPER_READ ? data_out : data); + netdev_dbg(adapter->netdev, "PHY %s: reg=%d, data=0x%04X\n", + dir == PCH_GBE_MIIM_OPER_READ ? "READ" : "WRITE", reg, + dir == PCH_GBE_MIIM_OPER_READ ? data_out : data); return (u16) data_out; } @@ -585,6 +593,7 @@ u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg, */ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); unsigned long tmp2, tmp3; /* Set Pause packet */ @@ -606,10 +615,13 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) /* Transmit Pause Packet */ iowrite32(PCH_GBE_PS_PKT_RQ, &hw->reg->PAUSE_REQ); - pr_debug("PAUSE_PKT1-5 reg : 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - ioread32(&hw->reg->PAUSE_PKT1), ioread32(&hw->reg->PAUSE_PKT2), - ioread32(&hw->reg->PAUSE_PKT3), ioread32(&hw->reg->PAUSE_PKT4), - ioread32(&hw->reg->PAUSE_PKT5)); + netdev_dbg(adapter->netdev, + "PAUSE_PKT1-5 reg : 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + ioread32(&hw->reg->PAUSE_PKT1), + ioread32(&hw->reg->PAUSE_PKT2), + ioread32(&hw->reg->PAUSE_PKT3), + ioread32(&hw->reg->PAUSE_PKT4), + ioread32(&hw->reg->PAUSE_PKT5)); return; } @@ -669,7 +681,7 @@ static int pch_gbe_init_phy(struct pch_gbe_adapter *adapter) break; } adapter->hw.phy.addr = adapter->mii.phy_id; - pr_debug("phy_addr = %d\n", adapter->mii.phy_id); + netdev_dbg(netdev, "phy_addr = %d\n", adapter->mii.phy_id); if (addr == 32) return -EAGAIN; /* Selected the phy and isolate the rest */ @@ -758,13 +770,15 @@ void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter) */ void pch_gbe_reset(struct pch_gbe_adapter *adapter) { + struct net_device *netdev = adapter->netdev; + pch_gbe_mac_reset_hw(&adapter->hw); /* reprogram multicast address register after reset */ - pch_gbe_set_multi(adapter->netdev); + pch_gbe_set_multi(netdev); /* Setup the receive address. */ pch_gbe_mac_init_rx_addrs(&adapter->hw, PCH_GBE_MAR_ENTRIES); if (pch_gbe_hal_init_hw(&adapter->hw)) - pr_err("Hardware Error\n"); + netdev_err(netdev, "Hardware Error\n"); } /** @@ -778,7 +792,7 @@ static void pch_gbe_free_irq(struct pch_gbe_adapter *adapter) free_irq(adapter->pdev->irq, netdev); if (adapter->have_msi) { pci_disable_msi(adapter->pdev); - pr_debug("call pci_disable_msi\n"); + netdev_dbg(netdev, "call pci_disable_msi\n"); } } @@ -795,7 +809,8 @@ static void pch_gbe_irq_disable(struct pch_gbe_adapter *adapter) ioread32(&hw->reg->INT_ST); synchronize_irq(adapter->pdev->irq); - pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN)); + netdev_dbg(adapter->netdev, "INT_EN reg : 0x%08x\n", + ioread32(&hw->reg->INT_EN)); } /** @@ -809,7 +824,8 @@ static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter) if (likely(atomic_dec_and_test(&adapter->irq_sem))) iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN); ioread32(&hw->reg->INT_ST); - pr_debug("INT_EN reg : 0x%08x\n", ioread32(&hw->reg->INT_EN)); + netdev_dbg(adapter->netdev, "INT_EN reg : 0x%08x\n", + ioread32(&hw->reg->INT_EN)); } @@ -846,9 +862,9 @@ static void pch_gbe_configure_tx(struct pch_gbe_adapter *adapter) struct pch_gbe_hw *hw = &adapter->hw; u32 tdba, tdlen, dctrl; - pr_debug("dma addr = 0x%08llx size = 0x%08x\n", - (unsigned long long)adapter->tx_ring->dma, - adapter->tx_ring->size); + netdev_dbg(adapter->netdev, "dma addr = 0x%08llx size = 0x%08x\n", + (unsigned long long)adapter->tx_ring->dma, + adapter->tx_ring->size); /* Setup the HW Tx Head and Tail descriptor pointers */ tdba = adapter->tx_ring->dma; @@ -894,9 +910,9 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) struct pch_gbe_hw *hw = &adapter->hw; u32 rdba, rdlen, rxdma; - pr_debug("dma adr = 0x%08llx size = 0x%08x\n", - (unsigned long long)adapter->rx_ring->dma, - adapter->rx_ring->size); + netdev_dbg(adapter->netdev, "dma adr = 0x%08llx size = 0x%08x\n", + (unsigned long long)adapter->rx_ring->dma, + adapter->rx_ring->size); pch_gbe_mac_force_mac_fc(hw); @@ -907,9 +923,10 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) rxdma &= ~PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - pr_debug("MAC_RX_EN reg = 0x%08x DMA_CTRL reg = 0x%08x\n", - ioread32(&hw->reg->MAC_RX_EN), - ioread32(&hw->reg->DMA_CTRL)); + netdev_dbg(adapter->netdev, + "MAC_RX_EN reg = 0x%08x DMA_CTRL reg = 0x%08x\n", + ioread32(&hw->reg->MAC_RX_EN), + ioread32(&hw->reg->DMA_CTRL)); /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ @@ -977,7 +994,8 @@ static void pch_gbe_clean_tx_ring(struct pch_gbe_adapter *adapter, buffer_info = &tx_ring->buffer_info[i]; pch_gbe_unmap_and_free_tx_resource(adapter, buffer_info); } - pr_debug("call pch_gbe_unmap_and_free_tx_resource() %d count\n", i); + netdev_dbg(adapter->netdev, + "call pch_gbe_unmap_and_free_tx_resource() %d count\n", i); size = (unsigned long)sizeof(struct pch_gbe_buffer) * tx_ring->count; memset(tx_ring->buffer_info, 0, size); @@ -1009,7 +1027,8 @@ pch_gbe_clean_rx_ring(struct pch_gbe_adapter *adapter, buffer_info = &rx_ring->buffer_info[i]; pch_gbe_unmap_and_free_rx_resource(adapter, buffer_info); } - pr_debug("call pch_gbe_unmap_and_free_rx_resource() %d count\n", i); + netdev_dbg(adapter->netdev, + "call pch_gbe_unmap_and_free_rx_resource() %d count\n", i); size = (unsigned long)sizeof(struct pch_gbe_buffer) * rx_ring->count; memset(rx_ring->buffer_info, 0, size); @@ -1087,7 +1106,7 @@ static void pch_gbe_watchdog(unsigned long data) struct net_device *netdev = adapter->netdev; struct pch_gbe_hw *hw = &adapter->hw; - pr_debug("right now = %ld\n", jiffies); + netdev_dbg(netdev, "right now = %ld\n", jiffies); pch_gbe_update_stats(adapter); if ((mii_link_ok(&adapter->mii)) && (!netif_carrier_ok(netdev))) { @@ -1095,7 +1114,7 @@ static void pch_gbe_watchdog(unsigned long data) netdev->tx_queue_len = adapter->tx_queue_len; /* mii library handles link maintenance tasks */ if (mii_ethtool_gset(&adapter->mii, &cmd)) { - pr_err("ethtool get setting Error\n"); + netdev_err(netdev, "ethtool get setting Error\n"); mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + PCH_GBE_WATCHDOG_PERIOD)); @@ -1213,7 +1232,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, buffer_info->length, DMA_TO_DEVICE); if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) { - pr_err("TX DMA map failed\n"); + netdev_err(adapter->netdev, "TX DMA map failed\n"); buffer_info->dma = 0; buffer_info->time_stamp = 0; tx_ring->next_to_use = ring_num; @@ -1333,13 +1352,13 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) /* When request status is no interruption factor */ if (unlikely(!int_st)) return IRQ_NONE; /* Not our interrupt. End processing. */ - pr_debug("%s occur int_st = 0x%08x\n", __func__, int_st); + netdev_dbg(netdev, "%s occur int_st = 0x%08x\n", __func__, int_st); if (int_st & PCH_GBE_INT_RX_FRAME_ERR) adapter->stats.intr_rx_frame_err_count++; if (int_st & PCH_GBE_INT_RX_FIFO_ERR) if (!adapter->rx_stop_flag) { adapter->stats.intr_rx_fifo_err_count++; - pr_debug("Rx fifo over run\n"); + netdev_dbg(netdev, "Rx fifo over run\n"); adapter->rx_stop_flag = true; int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), @@ -1359,7 +1378,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) /* When Rx descriptor is empty */ if ((int_st & PCH_GBE_INT_RX_DSC_EMP)) { adapter->stats.intr_rx_dsc_empty_count++; - pr_debug("Rx descriptor is empty\n"); + netdev_dbg(netdev, "Rx descriptor is empty\n"); int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_DSC_EMP), &hw->reg->INT_EN); if (hw->mac.tx_fc_enable) { @@ -1382,8 +1401,8 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) __napi_schedule(&adapter->napi); } } - pr_debug("return = 0x%08x INT_EN reg = 0x%08x\n", - IRQ_HANDLED, ioread32(&hw->reg->INT_EN)); + netdev_dbg(netdev, "return = 0x%08x INT_EN reg = 0x%08x\n", + IRQ_HANDLED, ioread32(&hw->reg->INT_EN)); return IRQ_HANDLED; } @@ -1437,9 +1456,10 @@ pch_gbe_alloc_rx_buffers(struct pch_gbe_adapter *adapter, rx_desc->buffer_addr = (buffer_info->dma); rx_desc->gbec_status = DSC_INIT16; - pr_debug("i = %d buffer_info->dma = 0x08%llx buffer_info->length = 0x%x\n", - i, (unsigned long long)buffer_info->dma, - buffer_info->length); + netdev_dbg(netdev, + "i = %d buffer_info->dma = 0x08%llx buffer_info->length = 0x%x\n", + i, (unsigned long long)buffer_info->dma, + buffer_info->length); if (unlikely(++i == rx_ring->count)) i = 0; @@ -1531,12 +1551,13 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, bool cleaned = false; int unused, thresh; - pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); + netdev_dbg(adapter->netdev, "next_to_clean : %d\n", + tx_ring->next_to_clean); i = tx_ring->next_to_clean; tx_desc = PCH_GBE_TX_DESC(*tx_ring, i); - pr_debug("gbec_status:0x%04x dma_status:0x%04x\n", - tx_desc->gbec_status, tx_desc->dma_status); + netdev_dbg(adapter->netdev, "gbec_status:0x%04x dma_status:0x%04x\n", + tx_desc->gbec_status, tx_desc->dma_status); unused = PCH_GBE_DESC_UNUSED(tx_ring); thresh = tx_ring->count - PCH_GBE_TX_WEIGHT; @@ -1544,8 +1565,10 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, { /* current marked clean, tx queue filling up, do extra clean */ int j, k; if (unused < 8) { /* tx queue nearly full */ - pr_debug("clean_tx: transmit queue warning (%x,%x) unused=%d\n", - tx_ring->next_to_clean,tx_ring->next_to_use,unused); + netdev_dbg(adapter->netdev, + "clean_tx: transmit queue warning (%x,%x) unused=%d\n", + tx_ring->next_to_clean, tx_ring->next_to_use, + unused); } /* current marked clean, scan for more that need cleaning. */ @@ -1557,49 +1580,56 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, if (++k >= tx_ring->count) k = 0; /*increment, wrap*/ } if (j < PCH_GBE_TX_WEIGHT) { - pr_debug("clean_tx: unused=%d loops=%d found tx_desc[%x,%x:%x].gbec_status=%04x\n", - unused,j, i,k, tx_ring->next_to_use, tx_desc->gbec_status); + netdev_dbg(adapter->netdev, + "clean_tx: unused=%d loops=%d found tx_desc[%x,%x:%x].gbec_status=%04x\n", + unused, j, i, k, tx_ring->next_to_use, + tx_desc->gbec_status); i = k; /*found one to clean, usu gbec_status==2000.*/ } } while ((tx_desc->gbec_status & DSC_INIT16) == 0x0000) { - pr_debug("gbec_status:0x%04x\n", tx_desc->gbec_status); + netdev_dbg(adapter->netdev, "gbec_status:0x%04x\n", + tx_desc->gbec_status); buffer_info = &tx_ring->buffer_info[i]; skb = buffer_info->skb; cleaned = true; if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_ABT)) { adapter->stats.tx_aborted_errors++; - pr_err("Transfer Abort Error\n"); + netdev_err(adapter->netdev, "Transfer Abort Error\n"); } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CRSER) ) { adapter->stats.tx_carrier_errors++; - pr_err("Transfer Carrier Sense Error\n"); + netdev_err(adapter->netdev, + "Transfer Carrier Sense Error\n"); } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_EXCOL) ) { adapter->stats.tx_aborted_errors++; - pr_err("Transfer Collision Abort Error\n"); + netdev_err(adapter->netdev, + "Transfer Collision Abort Error\n"); } else if ((tx_desc->gbec_status & (PCH_GBE_TXD_GMAC_STAT_SNGCOL | PCH_GBE_TXD_GMAC_STAT_MLTCOL))) { adapter->stats.collisions++; adapter->stats.tx_packets++; adapter->stats.tx_bytes += skb->len; - pr_debug("Transfer Collision\n"); + netdev_dbg(adapter->netdev, "Transfer Collision\n"); } else if ((tx_desc->gbec_status & PCH_GBE_TXD_GMAC_STAT_CMPLT) ) { adapter->stats.tx_packets++; adapter->stats.tx_bytes += skb->len; } if (buffer_info->mapped) { - pr_debug("unmap buffer_info->dma : %d\n", i); + netdev_dbg(adapter->netdev, + "unmap buffer_info->dma : %d\n", i); dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, buffer_info->length, DMA_TO_DEVICE); buffer_info->mapped = false; } if (buffer_info->skb) { - pr_debug("trim buffer_info->skb : %d\n", i); + netdev_dbg(adapter->netdev, + "trim buffer_info->skb : %d\n", i); skb_trim(buffer_info->skb, 0); } tx_desc->gbec_status = DSC_INIT16; @@ -1613,8 +1643,9 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, break; } } - pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n", - cleaned_count); + netdev_dbg(adapter->netdev, + "called pch_gbe_unmap_and_free_tx_resource() %d count\n", + cleaned_count); if (cleaned_count > 0) { /*skip this if nothing cleaned*/ /* Recover from running out of Tx resources in xmit_frame */ spin_lock(&tx_ring->tx_lock); @@ -1622,12 +1653,13 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter, { netif_wake_queue(adapter->netdev); adapter->stats.tx_restart_count++; - pr_debug("Tx wake queue\n"); + netdev_dbg(adapter->netdev, "Tx wake queue\n"); } tx_ring->next_to_clean = i; - pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean); + netdev_dbg(adapter->netdev, "next_to_clean : %d\n", + tx_ring->next_to_clean); spin_unlock(&tx_ring->tx_lock); } return cleaned; @@ -1684,22 +1716,22 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, buffer_info->length, DMA_FROM_DEVICE); buffer_info->mapped = false; - pr_debug("RxDecNo = 0x%04x Status[DMA:0x%02x GBE:0x%04x " - "TCP:0x%08x] BufInf = 0x%p\n", - i, dma_status, gbec_status, tcp_ip_status, - buffer_info); + netdev_dbg(netdev, + "RxDecNo = 0x%04x Status[DMA:0x%02x GBE:0x%04x TCP:0x%08x] BufInf = 0x%p\n", + i, dma_status, gbec_status, tcp_ip_status, + buffer_info); /* Error check */ if (unlikely(gbec_status & PCH_GBE_RXD_GMAC_STAT_NOTOCTAL)) { adapter->stats.rx_frame_errors++; - pr_err("Receive Not Octal Error\n"); + netdev_err(netdev, "Receive Not Octal Error\n"); } else if (unlikely(gbec_status & PCH_GBE_RXD_GMAC_STAT_NBLERR)) { adapter->stats.rx_frame_errors++; - pr_err("Receive Nibble Error\n"); + netdev_err(netdev, "Receive Nibble Error\n"); } else if (unlikely(gbec_status & PCH_GBE_RXD_GMAC_STAT_CRCERR)) { adapter->stats.rx_crc_errors++; - pr_err("Receive CRC Error\n"); + netdev_err(netdev, "Receive CRC Error\n"); } else { /* get receive length */ /* length convert[-3], length includes FCS length */ @@ -1730,8 +1762,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, napi_gro_receive(&adapter->napi, skb); (*work_done)++; - pr_debug("Receive skb->ip_summed: %d length: %d\n", - skb->ip_summed, length); + netdev_dbg(netdev, + "Receive skb->ip_summed: %d length: %d\n", + skb->ip_summed, length); } /* return some buffers to hardware, one at a time is too slow */ if (unlikely(cleaned_count >= PCH_GBE_RX_BUFFER_WRITE)) { @@ -1787,10 +1820,10 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter, tx_desc = PCH_GBE_TX_DESC(*tx_ring, desNo); tx_desc->gbec_status = DSC_INIT16; } - pr_debug("tx_ring->desc = 0x%p tx_ring->dma = 0x%08llx\n" - "next_to_clean = 0x%08x next_to_use = 0x%08x\n", - tx_ring->desc, (unsigned long long)tx_ring->dma, - tx_ring->next_to_clean, tx_ring->next_to_use); + netdev_dbg(adapter->netdev, + "tx_ring->desc = 0x%p tx_ring->dma = 0x%08llx next_to_clean = 0x%08x next_to_use = 0x%08x\n", + tx_ring->desc, (unsigned long long)tx_ring->dma, + tx_ring->next_to_clean, tx_ring->next_to_use); return 0; } @@ -1829,10 +1862,10 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter, rx_desc = PCH_GBE_RX_DESC(*rx_ring, desNo); rx_desc->gbec_status = DSC_INIT16; } - pr_debug("rx_ring->desc = 0x%p rx_ring->dma = 0x%08llx " - "next_to_clean = 0x%08x next_to_use = 0x%08x\n", - rx_ring->desc, (unsigned long long)rx_ring->dma, - rx_ring->next_to_clean, rx_ring->next_to_use); + netdev_dbg(adapter->netdev, + "rx_ring->desc = 0x%p rx_ring->dma = 0x%08llx next_to_clean = 0x%08x next_to_use = 0x%08x\n", + rx_ring->desc, (unsigned long long)rx_ring->dma, + rx_ring->next_to_clean, rx_ring->next_to_use); return 0; } @@ -1886,9 +1919,9 @@ static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter) flags = IRQF_SHARED; adapter->have_msi = false; err = pci_enable_msi(adapter->pdev); - pr_debug("call pci_enable_msi\n"); + netdev_dbg(netdev, "call pci_enable_msi\n"); if (err) { - pr_debug("call pci_enable_msi - Error: %d\n", err); + netdev_dbg(netdev, "call pci_enable_msi - Error: %d\n", err); } else { flags = 0; adapter->have_msi = true; @@ -1896,9 +1929,11 @@ static int pch_gbe_request_irq(struct pch_gbe_adapter *adapter) err = request_irq(adapter->pdev->irq, &pch_gbe_intr, flags, netdev->name, netdev); if (err) - pr_err("Unable to allocate interrupt Error: %d\n", err); - pr_debug("adapter->have_msi : %d flags : 0x%04x return : 0x%04x\n", - adapter->have_msi, flags, err); + netdev_err(netdev, "Unable to allocate interrupt Error: %d\n", + err); + netdev_dbg(netdev, + "adapter->have_msi : %d flags : 0x%04x return : 0x%04x\n", + adapter->have_msi, flags, err); return err; } @@ -1919,7 +1954,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) /* Ensure we have a valid MAC */ if (!is_valid_ether_addr(adapter->hw.mac.addr)) { - pr_err("Error: Invalid MAC address\n"); + netdev_err(netdev, "Error: Invalid MAC address\n"); goto out; } @@ -1933,12 +1968,14 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) err = pch_gbe_request_irq(adapter); if (err) { - pr_err("Error: can't bring device up - irq request failed\n"); + netdev_err(netdev, + "Error: can't bring device up - irq request failed\n"); goto out; } err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count); if (err) { - pr_err("Error: can't bring device up - alloc rx buffers pool failed\n"); + netdev_err(netdev, + "Error: can't bring device up - alloc rx buffers pool failed\n"); goto freeirq; } pch_gbe_alloc_tx_buffers(adapter, tx_ring); @@ -2015,11 +2052,11 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter) /* Initialize the hardware-specific values */ if (pch_gbe_hal_setup_init_funcs(hw)) { - pr_err("Hardware Initialization Failure\n"); + netdev_err(netdev, "Hardware Initialization Failure\n"); return -EIO; } if (pch_gbe_alloc_queues(adapter)) { - pr_err("Unable to allocate memory for queues\n"); + netdev_err(netdev, "Unable to allocate memory for queues\n"); return -ENOMEM; } spin_lock_init(&adapter->hw.miim_lock); @@ -2030,9 +2067,10 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter) pch_gbe_init_stats(adapter); - pr_debug("rx_buffer_len : %d mac.min_frame_size : %d mac.max_frame_size : %d\n", - (u32) adapter->rx_buffer_len, - hw->mac.min_frame_size, hw->mac.max_frame_size); + netdev_dbg(netdev, + "rx_buffer_len : %d mac.min_frame_size : %d mac.max_frame_size : %d\n", + (u32) adapter->rx_buffer_len, + hw->mac.min_frame_size, hw->mac.max_frame_size); return 0; } @@ -2061,7 +2099,7 @@ static int pch_gbe_open(struct net_device *netdev) err = pch_gbe_up(adapter); if (err) goto err_up; - pr_debug("Success End\n"); + netdev_dbg(netdev, "Success End\n"); return 0; err_up: @@ -2072,7 +2110,7 @@ static int pch_gbe_open(struct net_device *netdev) pch_gbe_free_tx_resources(adapter, adapter->tx_ring); err_setup_tx: pch_gbe_reset(adapter); - pr_err("Error End\n"); + netdev_err(netdev, "Error End\n"); return err; } @@ -2116,8 +2154,9 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) { netif_stop_queue(netdev); spin_unlock_irqrestore(&tx_ring->tx_lock, flags); - pr_debug("Return : BUSY next_to use : 0x%08x next_to clean : 0x%08x\n", - tx_ring->next_to_use, tx_ring->next_to_clean); + netdev_dbg(netdev, + "Return : BUSY next_to use : 0x%08x next_to clean : 0x%08x\n", + tx_ring->next_to_use, tx_ring->next_to_clean); return NETDEV_TX_BUSY; } @@ -2152,7 +2191,7 @@ static void pch_gbe_set_multi(struct net_device *netdev) int i; int mc_count; - pr_debug("netdev->flags : 0x%08x\n", netdev->flags); + netdev_dbg(netdev, "netdev->flags : 0x%08x\n", netdev->flags); /* Check for Promiscuous and All Multicast modes */ rctl = ioread32(&hw->reg->RX_MODE); @@ -2192,7 +2231,8 @@ static void pch_gbe_set_multi(struct net_device *netdev) PCH_GBE_MAR_ENTRIES); kfree(mta_list); - pr_debug("RX_MODE reg(check bit31,30 ADD,MLT) : 0x%08x netdev->mc_count : 0x%08x\n", + netdev_dbg(netdev, + "RX_MODE reg(check bit31,30 ADD,MLT) : 0x%08x netdev->mc_count : 0x%08x\n", ioread32(&hw->reg->RX_MODE), mc_count); } @@ -2218,12 +2258,12 @@ static int pch_gbe_set_mac(struct net_device *netdev, void *addr) pch_gbe_mac_mar_set(&adapter->hw, adapter->hw.mac.addr, 0); ret_val = 0; } - pr_debug("ret_val : 0x%08x\n", ret_val); - pr_debug("dev_addr : %pM\n", netdev->dev_addr); - pr_debug("mac_addr : %pM\n", adapter->hw.mac.addr); - pr_debug("MAC_ADR1AB reg : 0x%08x 0x%08x\n", - ioread32(&adapter->hw.reg->mac_adr[0].high), - ioread32(&adapter->hw.reg->mac_adr[0].low)); + netdev_dbg(netdev, "ret_val : 0x%08x\n", ret_val); + netdev_dbg(netdev, "dev_addr : %pM\n", netdev->dev_addr); + netdev_dbg(netdev, "mac_addr : %pM\n", adapter->hw.mac.addr); + netdev_dbg(netdev, "MAC_ADR1AB reg : 0x%08x 0x%08x\n", + ioread32(&adapter->hw.reg->mac_adr[0].high), + ioread32(&adapter->hw.reg->mac_adr[0].low)); return ret_val; } @@ -2245,7 +2285,7 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || (max_frame > PCH_GBE_MAX_JUMBO_FRAME_SIZE)) { - pr_err("Invalid MTU setting\n"); + netdev_err(netdev, "Invalid MTU setting\n"); return -EINVAL; } if (max_frame <= PCH_GBE_FRAME_SIZE_2048) @@ -2274,9 +2314,10 @@ static int pch_gbe_change_mtu(struct net_device *netdev, int new_mtu) adapter->hw.mac.max_frame_size = max_frame; } - pr_debug("max_frame : %d rx_buffer_len : %d mtu : %d max_frame_size : %d\n", - max_frame, (u32) adapter->rx_buffer_len, netdev->mtu, - adapter->hw.mac.max_frame_size); + netdev_dbg(netdev, + "max_frame : %d rx_buffer_len : %d mtu : %d max_frame_size : %d\n", + max_frame, (u32) adapter->rx_buffer_len, netdev->mtu, + adapter->hw.mac.max_frame_size); return 0; } @@ -2317,7 +2358,7 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct pch_gbe_adapter *adapter = netdev_priv(netdev); - pr_debug("cmd : 0x%04x\n", cmd); + netdev_dbg(netdev, "cmd : 0x%04x\n", cmd); if (cmd == SIOCSHWTSTAMP) return hwtstamp_ioctl(netdev, ifr, cmd); @@ -2354,7 +2395,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) bool poll_end_flag = false; bool cleaned = false; - pr_debug("budget : %d\n", budget); + netdev_dbg(adapter->netdev, "budget : %d\n", budget); pch_gbe_clean_rx(adapter, adapter->rx_ring, &work_done, budget); cleaned = pch_gbe_clean_tx(adapter, adapter->tx_ring); @@ -2377,8 +2418,9 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) pch_gbe_enable_dma_rx(&adapter->hw); } - pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", - poll_end_flag, work_done, budget); + netdev_dbg(adapter->netdev, + "poll_end_flag : %d work_done : %d budget : %d\n", + poll_end_flag, work_done, budget); return work_done; } @@ -2435,7 +2477,7 @@ static pci_ers_result_t pch_gbe_io_slot_reset(struct pci_dev *pdev) struct pch_gbe_hw *hw = &adapter->hw; if (pci_enable_device(pdev)) { - pr_err("Cannot re-enable PCI device after reset\n"); + netdev_err(netdev, "Cannot re-enable PCI device after reset\n"); return PCI_ERS_RESULT_DISCONNECT; } pci_set_master(pdev); @@ -2455,7 +2497,8 @@ static void pch_gbe_io_resume(struct pci_dev *pdev) if (netif_running(netdev)) { if (pch_gbe_up(adapter)) { - pr_debug("can't bring device back up after reset\n"); + netdev_dbg(netdev, + "can't bring device back up after reset\n"); return; } } @@ -2509,7 +2552,7 @@ static int pch_gbe_resume(struct device *device) err = pci_enable_device(pdev); if (err) { - pr_err("Cannot enable PCI device from suspend\n"); + netdev_err(netdev, "Cannot enable PCI device from suspend\n"); return err; } pci_set_master(pdev); @@ -2609,7 +2652,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, PCI_DEVFN(12, 4)); if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { - pr_err("Bad ptp filter\n"); + dev_err(&pdev->dev, "Bad ptp filter\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c index 8653c3b81f84..cf7c9b3a255b 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c @@ -237,16 +237,17 @@ static int pch_gbe_validate_option(int *value, case enable_option: switch (*value) { case OPTION_ENABLED: - pr_debug("%s Enabled\n", opt->name); + netdev_dbg(adapter->netdev, "%s Enabled\n", opt->name); return 0; case OPTION_DISABLED: - pr_debug("%s Disabled\n", opt->name); + netdev_dbg(adapter->netdev, "%s Disabled\n", opt->name); return 0; } break; case range_option: if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - pr_debug("%s set to %i\n", opt->name, *value); + netdev_dbg(adapter->netdev, "%s set to %i\n", + opt->name, *value); return 0; } break; @@ -258,7 +259,8 @@ static int pch_gbe_validate_option(int *value, ent = &opt->arg.l.p[i]; if (*value == ent->i) { if (ent->str[0] != '\0') - pr_debug("%s\n", ent->str); + netdev_dbg(adapter->netdev, "%s\n", + ent->str); return 0; } } @@ -268,8 +270,8 @@ static int pch_gbe_validate_option(int *value, BUG(); } - pr_debug("Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); + netdev_dbg(adapter->netdev, "Invalid %s value specified (%i) %s\n", + opt->name, *value, opt->err); *value = opt->def; return -1; } @@ -318,7 +320,8 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) .p = an_list} } }; if (speed || dplx) { - pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n"); + netdev_dbg(adapter->netdev, + "AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n"); hw->phy.autoneg_advertised = opt.def; } else { int tmp = AutoNeg; @@ -332,13 +335,16 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) case 0: hw->mac.autoneg = hw->mac.fc_autoneg = 1; if ((speed || dplx)) - pr_debug("Speed and duplex autonegotiation enabled\n"); + netdev_dbg(adapter->netdev, + "Speed and duplex autonegotiation enabled\n"); hw->mac.link_speed = SPEED_10; hw->mac.link_duplex = DUPLEX_HALF; break; case HALF_DUPLEX: - pr_debug("Half Duplex specified without Speed\n"); - pr_debug("Using Autonegotiation at Half Duplex only\n"); + netdev_dbg(adapter->netdev, + "Half Duplex specified without Speed\n"); + netdev_dbg(adapter->netdev, + "Using Autonegotiation at Half Duplex only\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 1; hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF | PHY_ADVERTISE_100_HALF; @@ -346,8 +352,10 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) hw->mac.link_duplex = DUPLEX_HALF; break; case FULL_DUPLEX: - pr_debug("Full Duplex specified without Speed\n"); - pr_debug("Using Autonegotiation at Full Duplex only\n"); + netdev_dbg(adapter->netdev, + "Full Duplex specified without Speed\n"); + netdev_dbg(adapter->netdev, + "Using Autonegotiation at Full Duplex only\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 1; hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL | PHY_ADVERTISE_100_FULL | @@ -356,8 +364,10 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) hw->mac.link_duplex = DUPLEX_FULL; break; case SPEED_10: - pr_debug("10 Mbps Speed specified without Duplex\n"); - pr_debug("Using Autonegotiation at 10 Mbps only\n"); + netdev_dbg(adapter->netdev, + "10 Mbps Speed specified without Duplex\n"); + netdev_dbg(adapter->netdev, + "Using Autonegotiation at 10 Mbps only\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 1; hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF | PHY_ADVERTISE_10_FULL; @@ -365,22 +375,24 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) hw->mac.link_duplex = DUPLEX_HALF; break; case SPEED_10 + HALF_DUPLEX: - pr_debug("Forcing to 10 Mbps Half Duplex\n"); + netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Half Duplex\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 0; hw->phy.autoneg_advertised = 0; hw->mac.link_speed = SPEED_10; hw->mac.link_duplex = DUPLEX_HALF; break; case SPEED_10 + FULL_DUPLEX: - pr_debug("Forcing to 10 Mbps Full Duplex\n"); + netdev_dbg(adapter->netdev, "Forcing to 10 Mbps Full Duplex\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 0; hw->phy.autoneg_advertised = 0; hw->mac.link_speed = SPEED_10; hw->mac.link_duplex = DUPLEX_FULL; break; case SPEED_100: - pr_debug("100 Mbps Speed specified without Duplex\n"); - pr_debug("Using Autonegotiation at 100 Mbps only\n"); + netdev_dbg(adapter->netdev, + "100 Mbps Speed specified without Duplex\n"); + netdev_dbg(adapter->netdev, + "Using Autonegotiation at 100 Mbps only\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 1; hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF | PHY_ADVERTISE_100_FULL; @@ -388,28 +400,33 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) hw->mac.link_duplex = DUPLEX_HALF; break; case SPEED_100 + HALF_DUPLEX: - pr_debug("Forcing to 100 Mbps Half Duplex\n"); + netdev_dbg(adapter->netdev, + "Forcing to 100 Mbps Half Duplex\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 0; hw->phy.autoneg_advertised = 0; hw->mac.link_speed = SPEED_100; hw->mac.link_duplex = DUPLEX_HALF; break; case SPEED_100 + FULL_DUPLEX: - pr_debug("Forcing to 100 Mbps Full Duplex\n"); + netdev_dbg(adapter->netdev, + "Forcing to 100 Mbps Full Duplex\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 0; hw->phy.autoneg_advertised = 0; hw->mac.link_speed = SPEED_100; hw->mac.link_duplex = DUPLEX_FULL; break; case SPEED_1000: - pr_debug("1000 Mbps Speed specified without Duplex\n"); + netdev_dbg(adapter->netdev, + "1000 Mbps Speed specified without Duplex\n"); goto full_duplex_only; case SPEED_1000 + HALF_DUPLEX: - pr_debug("Half Duplex is not supported at 1000 Mbps\n"); + netdev_dbg(adapter->netdev, + "Half Duplex is not supported at 1000 Mbps\n"); /* fall through */ case SPEED_1000 + FULL_DUPLEX: full_duplex_only: - pr_debug("Using Autonegotiation at 1000 Mbps Full Duplex only\n"); + netdev_dbg(adapter->netdev, + "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); hw->mac.autoneg = hw->mac.fc_autoneg = 1; hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL; hw->mac.link_speed = SPEED_1000; diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c index b97c6575e018..da079073a6c6 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_phy.c @@ -97,6 +97,7 @@ */ s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw) { + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); struct pch_gbe_phy_info *phy = &hw->phy; s32 ret; u16 phy_id1; @@ -115,8 +116,9 @@ s32 pch_gbe_phy_get_id(struct pch_gbe_hw *hw) phy->id = (u32)phy_id1; phy->id = ((phy->id << 6) | ((phy_id2 & 0xFC00) >> 10)); phy->revision = (u32) (phy_id2 & 0x000F); - pr_debug("phy->id : 0x%08x phy->revision : 0x%08x\n", - phy->id, phy->revision); + netdev_dbg(adapter->netdev, + "phy->id : 0x%08x phy->revision : 0x%08x\n", + phy->id, phy->revision); return 0; } @@ -134,7 +136,10 @@ s32 pch_gbe_phy_read_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 *data) struct pch_gbe_phy_info *phy = &hw->phy; if (offset > PHY_MAX_REG_ADDRESS) { - pr_err("PHY Address %d is out of range\n", offset); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "PHY Address %d is out of range\n", + offset); return -EINVAL; } *data = pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_READ, @@ -156,7 +161,10 @@ s32 pch_gbe_phy_write_reg_miic(struct pch_gbe_hw *hw, u32 offset, u16 data) struct pch_gbe_phy_info *phy = &hw->phy; if (offset > PHY_MAX_REG_ADDRESS) { - pr_err("PHY Address %d is out of range\n", offset); + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); + + netdev_err(adapter->netdev, "PHY Address %d is out of range\n", + offset); return -EINVAL; } pch_gbe_mac_ctrl_miim(hw, phy->addr, PCH_GBE_HAL_MIIM_WRITE, @@ -246,15 +254,14 @@ void pch_gbe_phy_set_rgmii(struct pch_gbe_hw *hw) */ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) { - struct pch_gbe_adapter *adapter; + struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw); struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; int ret; u16 mii_reg; - adapter = container_of(hw, struct pch_gbe_adapter, hw); ret = mii_ethtool_gset(&adapter->mii, &cmd); if (ret) - pr_err("Error: mii_ethtool_gset\n"); + netdev_err(adapter->netdev, "Error: mii_ethtool_gset\n"); ethtool_cmd_speed_set(&cmd, hw->mac.link_speed); cmd.duplex = hw->mac.link_duplex; @@ -263,7 +270,7 @@ void pch_gbe_phy_init_setting(struct pch_gbe_hw *hw) pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET); ret = mii_ethtool_sset(&adapter->mii, &cmd); if (ret) - pr_err("Error: mii_ethtool_sset\n"); + netdev_err(adapter->netdev, "Error: mii_ethtool_sset\n"); pch_gbe_phy_sw_reset(hw); -- GitLab From 29cc436cb90da4cabf404d8ceedc762fc7387b15 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 28 Jun 2013 14:02:54 +0300 Subject: [PATCH 2030/2900] pch_gbe: use managed functions pcim_* and devm_* This makes the error handling much more simpler than open-coding everything and in addition makes the probe function smaller an tidier. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 50 ++++++------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 97db56393197..ab1039a95bf9 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -636,15 +636,15 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw) */ static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter) { - adapter->tx_ring = kzalloc(sizeof(*adapter->tx_ring), GFP_KERNEL); + adapter->tx_ring = devm_kzalloc(&adapter->pdev->dev, + sizeof(*adapter->tx_ring), GFP_KERNEL); if (!adapter->tx_ring) return -ENOMEM; - adapter->rx_ring = kzalloc(sizeof(*adapter->rx_ring), GFP_KERNEL); - if (!adapter->rx_ring) { - kfree(adapter->tx_ring); + adapter->rx_ring = devm_kzalloc(&adapter->pdev->dev, + sizeof(*adapter->rx_ring), GFP_KERNEL); + if (!adapter->rx_ring) return -ENOMEM; - } return 0; } @@ -2588,13 +2588,7 @@ static void pch_gbe_remove(struct pci_dev *pdev) pch_gbe_hal_phy_hw_reset(&adapter->hw); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - iounmap(adapter->hw.reg); - pci_release_regions(pdev); free_netdev(netdev); - pci_disable_device(pdev); } static int pch_gbe_probe(struct pci_dev *pdev, @@ -2604,7 +2598,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, struct pch_gbe_adapter *adapter; int ret; - ret = pci_enable_device(pdev); + ret = pcim_enable_device(pdev); if (ret) return ret; @@ -2617,24 +2611,22 @@ static int pch_gbe_probe(struct pci_dev *pdev, if (ret) { dev_err(&pdev->dev, "ERR: No usable DMA " "configuration, aborting\n"); - goto err_disable_device; + return ret; } } } - ret = pci_request_regions(pdev, KBUILD_MODNAME); + ret = pcim_iomap_regions(pdev, 1 << PCH_GBE_PCI_BAR, pci_name(pdev)); if (ret) { dev_err(&pdev->dev, "ERR: Can't reserve PCI I/O and memory resources\n"); - goto err_disable_device; + return ret; } pci_set_master(pdev); netdev = alloc_etherdev((int)sizeof(struct pch_gbe_adapter)); - if (!netdev) { - ret = -ENOMEM; - goto err_release_pci; - } + if (!netdev) + return -ENOMEM; SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); @@ -2642,18 +2634,14 @@ static int pch_gbe_probe(struct pci_dev *pdev, adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; - adapter->hw.reg = pci_iomap(pdev, PCH_GBE_PCI_BAR, 0); - if (!adapter->hw.reg) { - ret = -EIO; - dev_err(&pdev->dev, "Can't ioremap\n"); - goto err_free_netdev; - } + adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR]; adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number, PCI_DEVFN(12, 4)); if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) { dev_err(&pdev->dev, "Bad ptp filter\n"); - return -EINVAL; + ret = -EINVAL; + goto err_free_netdev; } netdev->netdev_ops = &pch_gbe_netdev_ops; @@ -2671,7 +2659,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, /* setup the private structure */ ret = pch_gbe_sw_init(adapter); if (ret) - goto err_iounmap; + goto err_free_netdev; /* Initialize PHY */ ret = pch_gbe_init_phy(adapter); @@ -2727,16 +2715,8 @@ static int pch_gbe_probe(struct pci_dev *pdev, err_free_adapter: pch_gbe_hal_phy_hw_reset(&adapter->hw); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); -err_iounmap: - iounmap(adapter->hw.reg); err_free_netdev: free_netdev(netdev); -err_release_pci: - pci_release_regions(pdev); -err_disable_device: - pci_disable_device(pdev); return ret; } -- GitLab From cf6122be45de68bc773f64e4266db76129ea556f Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 27 Jun 2013 11:40:47 +0200 Subject: [PATCH 2031/2900] drivers: net: cpsw: add newline after MACID log Cosmetic patch to add a newline after logging the device's MACID. Signed-off-by: Daniel Mack Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 101b037a7dce..2c3657adc7cb 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1700,10 +1700,10 @@ static int cpsw_probe(struct platform_device *pdev) if (is_valid_ether_addr(data->slave_data[0].mac_addr)) { memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN); - pr_info("Detected MACID = %pM", priv->mac_addr); + pr_info("Detected MACID = %pM\n", priv->mac_addr); } else { eth_random_addr(priv->mac_addr); - pr_info("Random MACID = %pM", priv->mac_addr); + pr_info("Random MACID = %pM\n", priv->mac_addr); } memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN); -- GitLab From 3b233fe0435518169af03027aedc83d42eb28ac4 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Thu, 27 Jun 2013 13:44:26 +0200 Subject: [PATCH 2032/2900] nlmon: fix comparison in nlmon_is_valid_mtu This patch fixes the following warning introduced in e4fc408e0e99 ("packet: nlmon: virtual netlink monitoring device for packet sockets") reported by Dan Carpenter: warning: "drivers/net/nlmon.c:31 nlmon_is_valid_mtu() warn: always true condition '(new_mtu <= ((~0 >> 1))) => (s32min-s32max <= s32max)'" Thus, we should simply remove the test against INT_MAX. Next to that we also need to explicitly cast the sizeof() case as the comparison is type promoted to unsigned long so negative values are then valid instead of invalid. While at it, this also adds a comment about Netlink and MTUs. Reported-by: Dan Carpenter Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/nlmon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c index dc364be6e61e..a0baf56f5826 100644 --- a/drivers/net/nlmon.c +++ b/drivers/net/nlmon.c @@ -28,7 +28,11 @@ static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev) static int nlmon_is_valid_mtu(int new_mtu) { - return new_mtu >= sizeof(struct nlmsghdr) && new_mtu <= INT_MAX; + /* Note that in netlink we do not really have an upper limit. On + * default, we use NLMSG_GOODSIZE. Here at least we should make + * sure that it's at least the header size. + */ + return new_mtu >= (int) sizeof(struct nlmsghdr); } static int nlmon_change_mtu(struct net_device *dev, int new_mtu) -- GitLab From 1ca01512a2a95aa061c3fc24b7c5d7fad9f606bf Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 27 Jun 2013 20:53:42 +0800 Subject: [PATCH 2033/2900] net/trivial: replace numeric with standard PM state macros Use standard PM state macros PCI_Dx instead of numeric 0/1/2.. Signed-off-by: Yijing Wang Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/ne2k-pci.c | 2 +- drivers/net/ethernet/emulex/benet/be_main.c | 4 ++-- drivers/net/ethernet/intel/e100.c | 4 ++-- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 2 +- drivers/net/ethernet/realtek/8139cp.c | 2 +- drivers/net/ethernet/ti/tlan.c | 2 +- drivers/net/ethernet/via/via-velocity.c | 2 +- drivers/net/wireless/orinoco/orinoco_pci.h | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c index 587a885de259..92201080e07a 100644 --- a/drivers/net/ethernet/8390/ne2k-pci.c +++ b/drivers/net/ethernet/8390/ne2k-pci.c @@ -676,7 +676,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata (pdev); int rc; - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); rc = pci_enable_device(pdev); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index cd69ac79f565..2df48bb0f1ca 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4364,7 +4364,7 @@ static int be_resume(struct pci_dev *pdev) if (status) return status; - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); /* tell fw we're ready to fire cmds */ @@ -4460,7 +4460,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; pci_set_master(pdev); - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); /* Check if card is ok and fw is ready */ diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index d2bea3f07c73..5115ae76a5d1 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -3069,7 +3069,7 @@ static int e100_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); + pci_enable_wake(pdev, PCI_D0, 0); /* disable reverse auto-negotiation */ if (nic->phy == phy_82552_v) { @@ -3160,7 +3160,7 @@ static void e100_io_resume(struct pci_dev *pdev) struct nic *nic = netdev_priv(netdev); /* ack any pending wake events, disable PME */ - pci_enable_wake(pdev, 0, 0); + pci_enable_wake(pdev, PCI_D0, 0); netif_device_attach(netdev); if (netif_running(netdev)) { diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 7be9788ed0f6..967bae8b85c5 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -3299,7 +3299,7 @@ static int myri10ge_resume(struct pci_dev *pdev) if (mgp == NULL) return -EINVAL; netdev = mgp->dev; - pci_set_power_state(pdev, 0); /* zeros conf space as a side effect */ + pci_set_power_state(pdev, PCI_D0); /* zeros conf space as a side effect */ msleep(5); /* give card time to respond */ pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); if (vendor == 0xffff) { diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 03523459c406..e6acb9fa5767 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -1817,7 +1817,7 @@ static int cp_set_eeprom(struct net_device *dev, /* Put the board into D3cold state and wait for WakeUp signal */ static void cp_set_d3_state (struct cp_private *cp) { - pci_enable_wake (cp->pdev, 0, 1); /* Enable PME# generation */ + pci_enable_wake(cp->pdev, PCI_D0, 1); /* Enable PME# generation */ pci_set_power_state (cp->pdev, PCI_D3hot); } diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 59abfbcd0d55..591437e59b90 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -372,7 +372,7 @@ static int tlan_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - pci_enable_wake(pdev, 0, 0); + pci_enable_wake(pdev, PCI_D0, 0); netif_device_attach(dev); if (netif_running(dev)) diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 76919948b4ee..1d6dc41f755d 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -3211,7 +3211,7 @@ static int velocity_resume(struct device *dev) velocity_set_power_state(vptr, PCI_D0); if (vptr->pdev) { - pci_enable_wake(vptr->pdev, 0, 0); + pci_enable_wake(vptr->pdev, PCI_D0, 0); pci_restore_state(vptr->pdev); } diff --git a/drivers/net/wireless/orinoco/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h index ea7231af40a8..43f5b9f5a0b0 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.h +++ b/drivers/net/wireless/orinoco/orinoco_pci.h @@ -38,7 +38,7 @@ static int orinoco_pci_resume(struct pci_dev *pdev) struct net_device *dev = priv->ndev; int err; - pci_set_power_state(pdev, 0); + pci_set_power_state(pdev, PCI_D0); err = pci_enable_device(pdev); if (err) { printk(KERN_ERR "%s: pci_enable_device failed on resume\n", -- GitLab From d36a21da415b8e6545ae8b4eb6b23eea2ce001c8 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 27 Jun 2013 21:00:11 +0800 Subject: [PATCH 2034/2900] ssb/trivial: replace numeric with standard PM state macros Use standard PM state macros PCI_Dx instead of numeric 0/1/2.. Signed-off-by: Yijing Wang Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller --- drivers/ssb/pcihost_wrapper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c index 32ed1fa4a82e..69161bbc4d0b 100644 --- a/drivers/ssb/pcihost_wrapper.c +++ b/drivers/ssb/pcihost_wrapper.c @@ -38,7 +38,7 @@ static int ssb_pcihost_resume(struct pci_dev *dev) struct ssb_bus *ssb = pci_get_drvdata(dev); int err; - pci_set_power_state(dev, 0); + pci_set_power_state(dev, PCI_D0); err = pci_enable_device(dev); if (err) return err; -- GitLab From 94fccb78414a87f3c4bc7049ff8b6e80156944d9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 18 Jun 2013 14:08:00 +0100 Subject: [PATCH 2035/2900] iio: dac: ad7303: fix error return code in ad7303_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad7303.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index 85aeef60dc5f..d546f50f9258 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -235,8 +235,10 @@ static int ad7303_probe(struct spi_device *spi) if (ext_ref) { st->vref_reg = regulator_get(&spi->dev, "REF"); - if (IS_ERR(st->vref_reg)) + if (IS_ERR(st->vref_reg)) { + ret = PTR_ERR(st->vref_reg); goto err_disable_vdd_reg; + } ret = regulator_enable(st->vref_reg); if (ret) -- GitLab From 8bade406649245292d6fcd1947cd7ad2ad8c80c1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 22 Jun 2013 12:00:04 +0100 Subject: [PATCH 2036/2900] iio:trigger: device_unregister->device_del to avoid double free iio_trigger unregistration and freeing has been separated in this code for some time, but it looks like the calls to the device handling were not appropriately updated. Signed-off-by: Jonathan Cameron Reported-by: Otavio Salvador Tested-by: Otavio Salvador Reviewed-by: Lars-Peter Clausen --- drivers/iio/industrialio-trigger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 4d6c7d84e155..ea8a4146620d 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -104,7 +104,7 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) ida_simple_remove(&iio_trigger_ida, trig_info->id); /* Possible issue in here */ - device_unregister(&trig_info->dev); + device_del(&trig_info->dev); } EXPORT_SYMBOL(iio_trigger_unregister); -- GitLab From b57caaaed2bd127fe656e6c145970ed6a05c0125 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 28 Jun 2013 12:56:51 -0700 Subject: [PATCH 2037/2900] kconfig: allow "hex" and "range" to support longs The parsing routines for Kconfig files use strtol(), but store and render values as int. Switch types and formating to long to support a wider range of values. For example, 0x80000000 wasn't representable. Signed-off-by: Kees Cook Tested-by: "Yann E. MORIN" Reviewed-by: "Yann E. MORIN" Signed-off-by: "Yann E. MORIN" --- scripts/kconfig/symbol.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 387d55483882..d550300ec00c 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -136,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym) return NULL; } -static int sym_get_range_val(struct symbol *sym, int base) +static long sym_get_range_val(struct symbol *sym, int base) { sym_calc_value(sym); switch (sym->type) { @@ -155,7 +155,7 @@ static int sym_get_range_val(struct symbol *sym, int base) static void sym_validate_range(struct symbol *sym) { struct property *prop; - int base, val, val2; + long base, val, val2; char str[64]; switch (sym->type) { @@ -179,9 +179,9 @@ static void sym_validate_range(struct symbol *sym) return; } if (sym->type == S_INT) - sprintf(str, "%d", val2); + sprintf(str, "%ld", val2); else - sprintf(str, "0x%x", val2); + sprintf(str, "0x%lx", val2); sym->curr.val = strdup(str); } @@ -594,7 +594,7 @@ bool sym_string_valid(struct symbol *sym, const char *str) bool sym_string_within_range(struct symbol *sym, const char *str) { struct property *prop; - int val; + long val; switch (sym->type) { case S_STRING: -- GitLab From 008aebde9be37e7e1248332b1983976e354327ea Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Sat, 29 Jun 2013 13:16:59 +0200 Subject: [PATCH 2038/2900] bonding: combine pr_debugs in bond_set_dev_addr into one Combine the multiple pr_debugs in bond_set_dev_addr into one pr_debug. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ec44580b076f..742c193881fa 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -843,9 +843,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, static void bond_set_dev_addr(struct net_device *bond_dev, struct net_device *slave_dev) { - pr_debug("bond_dev=%p\n", bond_dev); - pr_debug("slave_dev=%p\n", slave_dev); - pr_debug("slave_dev->addr_len=%d\n", slave_dev->addr_len); + pr_debug("bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", + bond_dev, slave_dev, slave_dev->addr_len); memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); bond_dev->addr_assign_type = NET_ADDR_STOLEN; call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); -- GitLab From 89970d28cb3fd1c678f769d62d077c10ec5340e1 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 30 Jun 2013 11:07:13 +0300 Subject: [PATCH 2039/2900] remoteproc: fix error return code in rproc_fw_boot() Set 'ret' to -EINVAL when needed, so a sensible return value is returned on errors. Signed-off-by: Wei Yongjun [fix additional instances of this bug as well, update commit log] Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 022dc635d01e..7e33536b5c2b 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -815,18 +815,17 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) } rproc->bootaddr = rproc_get_boot_addr(rproc, fw); + ret = -EINVAL; /* look for the resource table */ table = rproc_find_rsc_table(rproc, fw, &tablesz); if (!table) { - ret = -EINVAL; goto clean_up; } /* Verify that resource table in loaded fw is unchanged */ if (rproc->table_csum != crc32(0, table, tablesz)) { dev_err(dev, "resource checksum failed, fw changed?\n"); - ret = -EINVAL; goto clean_up; } @@ -852,8 +851,10 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) * copy this information to device memory. */ loaded_table = rproc_find_loaded_rsc_table(rproc, fw); - if (!loaded_table) + if (!loaded_table) { + ret = -EINVAL; goto clean_up; + } memcpy(loaded_table, rproc->cached_table, tablesz); -- GitLab From 57971159208757a37d44356764911703468a7ca3 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Sun, 30 Jun 2013 11:33:05 +0300 Subject: [PATCH 2040/2900] remoteproc: fix checkpatch errors in remoteproc code This patch fixes relevant checkpatch errors and warnings in the remoteproc source files. Signed-off-by: Suman Anna [drop 80-char-lines checkpatch fixes and update commit log accordingly] Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_debugfs.c | 3 +-- drivers/remoteproc/remoteproc_internal.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 157a57309601..9d30809bb407 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -248,6 +248,5 @@ void __init rproc_init_debugfs(void) void __exit rproc_exit_debugfs(void) { - if (rproc_dbg) - debugfs_remove(rproc_dbg); + debugfs_remove(rproc_dbg); } diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 157e762c1571..70701a50ddfa 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -107,12 +107,12 @@ struct resource_table *rproc_find_rsc_table(struct rproc *rproc, static inline struct resource_table *rproc_find_loaded_rsc_table(struct rproc *rproc, - const struct firmware *fw) + const struct firmware *fw) { if (rproc->fw_ops->find_loaded_rsc_table) return rproc->fw_ops->find_loaded_rsc_table(rproc, fw); - return NULL; + return NULL; } extern const struct rproc_fw_ops rproc_elf_fw_ops; -- GitLab From 496e4ae7dc944faa1721bfda7e9d834d5611a874 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sat, 29 Jun 2013 14:15:47 +0200 Subject: [PATCH 2041/2900] netfilter: nf_queue: add NFQA_SKB_CSUM_NOTVERIFIED info flag The common case is that TCP/IP checksums have already been verified, e.g. by hardware (rx checksum offload), or conntrack. Userspace can use this flag to determine when the checksum has not been validated yet. If the flag is set, this doesn't necessarily mean that the packet has an invalid checksum, e.g. if NIC doesn't support rx checksum. Userspace that sucessfully enabled NFQA_CFG_F_GSO queue feature flag can infer that IP/TCP checksum has already been validated if either the SKB_INFO attribute is not present or the NFQA_SKB_CSUM_NOTVERIFIED flag is unset. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/nfnetlink_queue.h | 2 ++ net/netfilter/nfnetlink_queue_core.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index a2308ae5a73d..3a9b92147339 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h @@ -105,5 +105,7 @@ enum nfqnl_attr_config { #define NFQA_SKB_CSUMNOTREADY (1 << 0) /* packet is GSO (i.e., exceeds device mtu) */ #define NFQA_SKB_GSO (1 << 1) +/* csum not validated (incoming device doesn't support hw checksum, etc.) */ +#define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2) #endif /* _NFNETLINK_QUEUE_H */ diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 299a48ae5dc9..971ea145ab3e 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -280,12 +280,17 @@ nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) skb_shinfo(to)->nr_frags = j; } -static int nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet) +static int +nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet, + bool csum_verify) { __u32 flags = 0; if (packet->ip_summed == CHECKSUM_PARTIAL) flags = NFQA_SKB_CSUMNOTREADY; + else if (csum_verify) + flags = NFQA_SKB_CSUM_NOTVERIFIED; + if (skb_is_gso(packet)) flags |= NFQA_SKB_GSO; @@ -310,6 +315,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, struct net_device *outdev; struct nf_conn *ct = NULL; enum ip_conntrack_info uninitialized_var(ctinfo); + bool csum_verify; size = nlmsg_total_size(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) @@ -327,6 +333,12 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (entskb->tstamp.tv64) size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); + if (entry->hook <= NF_INET_FORWARD || + (entry->hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) + csum_verify = !skb_csum_unnecessary(entskb); + else + csum_verify = false; + outdev = entry->outdev; switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { @@ -476,7 +488,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) goto nla_put_failure; - if (nfqnl_put_packet_info(skb, entskb)) + if (nfqnl_put_packet_info(skb, entskb, csum_verify)) goto nla_put_failure; if (data_len) { -- GitLab From 443c6ae253e96db9a5800a28d7c61131e81c2dee Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 24 Jun 2013 14:39:52 +0200 Subject: [PATCH 2042/2900] mfd: max8998: Add irq domain support This patch adds irq domain support for max8998 interrupts. To keep both non-DT and DT worlds happy, simple domain is used, which is linear when no explicit IRQ base is specified and legacy, with static mapping, otherwise. Signed-off-by: Tomasz Figa Signed-off-by: Samuel Ortiz --- drivers/mfd/Kconfig | 1 + drivers/mfd/max8998-irq.c | 65 ++++++++++++++++++----------- drivers/rtc/rtc-max8998.c | 12 +++++- include/linux/mfd/max8998-private.h | 5 ++- include/linux/mfd/max8998.h | 2 +- 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3bb2932eafb1..aecd6ddcbbbf 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -363,6 +363,7 @@ config MFD_MAX8998 bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select IRQ_DOMAIN help Say yes here to support for Maxim Semiconductor MAX8998 and National Semiconductor LP3974. This is a Power Management IC. diff --git a/drivers/mfd/max8998-irq.c b/drivers/mfd/max8998-irq.c index 5919710dc9ed..c469477eb778 100644 --- a/drivers/mfd/max8998-irq.c +++ b/drivers/mfd/max8998-irq.c @@ -14,6 +14,7 @@ #include #include #include +#include #include struct max8998_irq_data { @@ -99,7 +100,8 @@ static struct max8998_irq_data max8998_irqs[] = { static inline struct max8998_irq_data * irq_to_max8998_irq(struct max8998_dev *max8998, int irq) { - return &max8998_irqs[irq - max8998->irq_base]; + struct irq_data *data = irq_get_irq_data(irq); + return &max8998_irqs[data->hwirq]; } static void max8998_irq_lock(struct irq_data *data) @@ -176,8 +178,14 @@ static irqreturn_t max8998_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8998_IRQ_NR; i++) { - if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) - handle_nested_irq(max8998->irq_base + i); + if (irq_reg[max8998_irqs[i].reg - 1] & max8998_irqs[i].mask) { + irq = irq_find_mapping(max8998->irq_domain, i); + if (WARN_ON(!irq)) { + disable_irq_nosync(max8998->irq); + return IRQ_NONE; + } + handle_nested_irq(irq); + } } return IRQ_HANDLED; @@ -185,27 +193,40 @@ static irqreturn_t max8998_irq_thread(int irq, void *data) int max8998_irq_resume(struct max8998_dev *max8998) { - if (max8998->irq && max8998->irq_base) - max8998_irq_thread(max8998->irq_base, max8998); + if (max8998->irq && max8998->irq_domain) + max8998_irq_thread(max8998->irq, max8998); + return 0; +} + +static int max8998_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max8997_dev *max8998 = d->host_data; + + irq_set_chip_data(irq, max8998); + irq_set_chip_and_handler(irq, &max8998_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif return 0; } +static struct irq_domain_ops max8998_irq_domain_ops = { + .map = max8998_irq_domain_map, +}; + int max8998_irq_init(struct max8998_dev *max8998) { int i; - int cur_irq; int ret; + struct irq_domain *domain; if (!max8998->irq) { dev_warn(max8998->dev, "No interrupt specified, no interrupts\n"); - max8998->irq_base = 0; - return 0; - } - - if (!max8998->irq_base) { - dev_err(max8998->dev, - "No interrupt base specified, no interrupts\n"); return 0; } @@ -221,19 +242,13 @@ int max8998_irq_init(struct max8998_dev *max8998) max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM1, 0xff); max8998_write_reg(max8998->i2c, MAX8998_REG_STATUSM2, 0xff); - /* register with genirq */ - for (i = 0; i < MAX8998_IRQ_NR; i++) { - cur_irq = i + max8998->irq_base; - irq_set_chip_data(cur_irq, max8998); - irq_set_chip_and_handler(cur_irq, &max8998_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif + domain = irq_domain_add_simple(NULL, MAX8998_IRQ_NR, + max8998->irq_base, &max8998_irq_domain_ops, max8998); + if (!domain) { + dev_err(max8998->dev, "could not create irq domain\n"); + return -ENODEV; } + max8998->irq_domain = domain; ret = request_threaded_irq(max8998->irq, NULL, max8998_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index d5af7baa48b5..46f23014759b 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -264,7 +265,6 @@ static int max8998_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->max8998 = max8998; info->rtc = max8998->rtc; - info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0; platform_set_drvdata(pdev, info); @@ -277,6 +277,15 @@ static int max8998_rtc_probe(struct platform_device *pdev) goto out_rtc; } + if (!max8998->irq_domain) + goto no_irq; + + info->irq = irq_create_mapping(max8998->irq_domain, MAX8998_IRQ_ALARM0); + if (!info->irq) { + dev_warn(&pdev->dev, "Failed to map alarm IRQ\n"); + goto no_irq; + } + ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, max8998_rtc_alarm_irq, 0, "rtc-alarm0", info); @@ -284,6 +293,7 @@ static int max8998_rtc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", info->irq, ret); +no_irq: dev_info(&pdev->dev, "RTC CHIP NAME: %s\n", pdev->id_entry->name); if (pdata && pdata->rtc_delay) { info->lp3974_bug_workaround = true; diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index effa5d3b96ae..bfb48b6fcc74 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -132,6 +132,8 @@ enum { #define MAX8998_ENRAMP (1 << 4) +struct irq_domain; + /** * struct max8998_dev - max8998 master device for sub-drivers * @dev: master device of the chip (can be used to access platform data) @@ -153,7 +155,8 @@ struct max8998_dev { struct mutex iolock; struct mutex irqlock; - int irq_base; + unsigned int irq_base; + struct irq_domain *irq_domain; int irq; int ono; u8 irq_masks_cur[MAX8998_NUM_IRQ_REGS]; diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index 6823548d0c0a..75471183b87a 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -100,7 +100,7 @@ struct max8998_regulator_data { struct max8998_platform_data { struct max8998_regulator_data *regulators; int num_regulators; - int irq_base; + unsigned int irq_base; int ono; bool buck_voltage_lock; int buck1_voltage1; -- GitLab From 4280e0b42bd590316a048d66ea356e78c5d0464e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 24 Jun 2013 14:39:53 +0200 Subject: [PATCH 2043/2900] regulator: max8998: Use arrays for specifying voltages in platform data This patch modifies the platform data of max8998 to use arrays for specifying predefined voltages of buck1 and buck2 instead of separate field for each voltage. This allows to simplify the code a bit and will help in adding support for Device Tree, which will be introduced in further patch. Signed-off-by: Tomasz Figa Acked-by: Mark Brown Signed-off-by: Samuel Ortiz --- arch/arm/mach-exynos/mach-universal_c210.c | 8 +- arch/arm/mach-s5pv210/mach-aquila.c | 8 +- arch/arm/mach-s5pv210/mach-goni.c | 8 +- drivers/regulator/max8998.c | 96 +++++++--------------- include/linux/mfd/max8998.h | 16 +--- 5 files changed, 39 insertions(+), 97 deletions(-) diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 74ddb2b55614..f912444cae33 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -540,15 +540,11 @@ static struct max8998_regulator_data lp3974_regulators[] = { static struct max8998_platform_data universal_lp3974_pdata = { .num_regulators = ARRAY_SIZE(lp3974_regulators), .regulators = lp3974_regulators, - .buck1_voltage1 = 1100000, /* INT */ - .buck1_voltage2 = 1000000, - .buck1_voltage3 = 1100000, - .buck1_voltage4 = 1000000, + .buck1_voltage = { 1100000, 1000000, 1100000, 1000000 }, .buck1_set1 = EXYNOS4_GPX0(5), .buck1_set2 = EXYNOS4_GPX0(6), - .buck2_voltage1 = 1200000, /* G3D */ - .buck2_voltage2 = 1100000, .buck1_default_idx = 0, + .buck2_voltage = { 1200000, 1100000 }, .buck2_set3 = EXYNOS4_GPE2(0), .buck2_default_idx = 0, .wakeup = true, diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index ed2b85485b9d..ad40ab0f5dbd 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -377,12 +377,8 @@ static struct max8998_platform_data aquila_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_voltage1 = 1200000, - .buck1_voltage2 = 1200000, - .buck1_voltage3 = 1200000, - .buck1_voltage4 = 1200000, - .buck2_voltage1 = 1200000, - .buck2_voltage2 = 1200000, + .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 }, + .buck2_voltage = { 1200000, 1200000 }, }; #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 30b24ad84f49..e5cd9fbf19e9 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -580,12 +580,8 @@ static struct max8998_platform_data goni_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_voltage1 = 1200000, - .buck1_voltage2 = 1200000, - .buck1_voltage3 = 1200000, - .buck1_voltage4 = 1200000, - .buck2_voltage1 = 1200000, - .buck2_voltage2 = 1200000, + .buck1_voltage = { 1200000, 1200000, 1200000, 1200000 }, + .buck2_voltage = { 1200000, 1200000 }, }; #endif diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index a57a1b15cdba..8c45b93b7334 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -630,6 +630,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) struct max8998_data *max8998; struct i2c_client *i2c; int i, ret, size; + unsigned int v; if (!pdata) { dev_err(pdev->dev.parent, "No platform init data supplied\n"); @@ -688,53 +689,21 @@ static int max8998_pmic_probe(struct platform_device *pdev) gpio_request(pdata->buck1_set2, "MAX8998 BUCK1_SET2"); gpio_direction_output(pdata->buck1_set2, (max8998->buck1_idx >> 1) & 0x1); - /* Set predefined value for BUCK1 register 1 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage1) - i++; - max8998->buck1_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 2 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage2) - i++; - - max8998->buck1_vol[1] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE2, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 3 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage3) - i++; - - max8998->buck1_vol[2] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE3, i); - if (ret) - goto err_out; - - /* Set predefined value for BUCK1 register 4 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck1_voltage4) - i++; - - max8998->buck1_vol[3] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE4, i); - if (ret) - goto err_out; + /* Set predefined values for BUCK1 registers */ + for (v = 0; v < ARRAY_SIZE(pdata->buck1_voltage); ++v) { + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i + < pdata->buck1_voltage[v]) + i++; + + max8998->buck1_vol[v] = i; + ret = max8998_write_reg(i2c, + MAX8998_REG_BUCK1_VOLTAGE1 + v, i); + if (ret) + goto err_out; + } } if (gpio_is_valid(pdata->buck2_set3)) { @@ -750,27 +719,20 @@ static int max8998_pmic_probe(struct platform_device *pdev) gpio_direction_output(pdata->buck2_set3, max8998->buck2_idx & 0x1); - /* BUCK2 register 1 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck2_voltage1) - i++; - max8998->buck2_vol[0] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); - if (ret) - goto err_out; - - /* BUCK2 register 2 */ - i = 0; - while (buck12_voltage_map_desc.min + - buck12_voltage_map_desc.step*i - < pdata->buck2_voltage2) - i++; - max8998->buck2_vol[1] = i; - ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); - if (ret) - goto err_out; + /* Set predefined values for BUCK2 registers */ + for (v = 0; v < ARRAY_SIZE(pdata->buck2_voltage); ++v) { + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i + < pdata->buck2_voltage[v]) + i++; + + max8998->buck2_vol[v] = i; + ret = max8998_write_reg(i2c, + MAX8998_REG_BUCK2_VOLTAGE1 + v, i); + if (ret) + goto err_out; + } } for (i = 0; i < pdata->num_regulators; i++) { diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index 75471183b87a..ca56bb03bc69 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -73,12 +73,8 @@ struct max8998_regulator_data { * @buck_voltage_lock: Do NOT change the values of the following six * registers set by buck?_voltage?. The voltage of BUCK1/2 cannot * be other than the preset values. - * @buck1_voltage1: BUCK1 DVS mode 1 voltage register - * @buck1_voltage2: BUCK1 DVS mode 2 voltage register - * @buck1_voltage3: BUCK1 DVS mode 3 voltage register - * @buck1_voltage4: BUCK1 DVS mode 4 voltage register - * @buck2_voltage1: BUCK2 DVS mode 1 voltage register - * @buck2_voltage2: BUCK2 DVS mode 2 voltage register + * @buck1_voltage: BUCK1 DVS mode 1 voltage registers + * @buck2_voltage: BUCK2 DVS mode 2 voltage registers * @buck1_set1: BUCK1 gpio pin 1 to set output voltage * @buck1_set2: BUCK1 gpio pin 2 to set output voltage * @buck1_default_idx: Default for BUCK1 gpio pin 1, 2 @@ -103,12 +99,8 @@ struct max8998_platform_data { unsigned int irq_base; int ono; bool buck_voltage_lock; - int buck1_voltage1; - int buck1_voltage2; - int buck1_voltage3; - int buck1_voltage4; - int buck2_voltage1; - int buck2_voltage2; + int buck1_voltage[4]; + int buck2_voltage[2]; int buck1_set1; int buck1_set2; int buck1_default_idx; -- GitLab From ee999fb3f17faa3af6028bf7130707fe0d4157a4 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 25 Jun 2013 16:08:10 +0200 Subject: [PATCH 2044/2900] mfd: max8998: Add support for Device Tree This patch adds Device Tree support to max8998 driver. Signed-off-by: Tomasz Figa Acked-by: Mark Brown Signed-off-by: Samuel Ortiz --- .../devicetree/bindings/mfd/max8998.txt | 119 ++++++++++++++++ drivers/mfd/max8998.c | 67 ++++++++- drivers/regulator/max8998.c | 131 +++++++++++++++++- drivers/rtc/rtc-max8998.c | 2 +- include/linux/mfd/max8998-private.h | 2 + include/linux/mfd/max8998.h | 2 + 6 files changed, 316 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/max8998.txt diff --git a/Documentation/devicetree/bindings/mfd/max8998.txt b/Documentation/devicetree/bindings/mfd/max8998.txt new file mode 100644 index 000000000000..23a3650ff2a2 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max8998.txt @@ -0,0 +1,119 @@ +* Maxim MAX8998, National/TI LP3974 multi-function device + +The Maxim MAX8998 is a multi-function device which includes voltage/current +regulators, real time clock, battery charging controller and several +other sub-blocks. It is interfaced using an I2C interface. Each sub-block +is addressed by the host system using different i2c slave address. + +PMIC sub-block +-------------- + +The PMIC sub-block contains a number of voltage and current regulators, +with controllable parameters and dynamic voltage scaling capability. +In addition, it includes a real time clock and battery charging controller +as well. It is accessible at I2C address 0x66. + +Required properties: +- compatible: Should be one of the following: + - "maxim,max8998" for Maxim MAX8998 + - "national,lp3974" or "ti,lp3974" for National/TI LP3974. +- reg: Specifies the i2c slave address of the pmic block. It should be 0x66. + +Optional properties: +- interrupt-parent: Specifies the phandle of the interrupt controller to which + the interrupts from MAX8998 are routed to. +- interrupts: Interrupt specifiers for two interrupt sources. + - First interrupt specifier is for main interrupt. + - Second interrupt specifier is for power-on/-off interrupt. +- max8998,pmic-buck1-dvs-gpios: GPIO specifiers for two host gpios used + for buck 1 dvs. The format of the gpio specifier depends on the gpio + controller. +- max8998,pmic-buck2-dvs-gpio: GPIO specifier for host gpio used + for buck 2 dvs. The format of the gpio specifier depends on the gpio + controller. +- max8998,pmic-buck1-default-dvs-idx: Default voltage setting selected from + the possible 4 options selectable by the dvs gpios. The value of this + property should be 0, 1, 2 or 3. If not specified or out of range, + a default value of 0 is taken. +- max8998,pmic-buck2-default-dvs-idx: Default voltage setting selected from + the possible 2 options selectable by the dvs gpios. The value of this + property should be 0 or 1. If not specified or out of range, a default + value of 0 is taken. +- max8998,pmic-buck-voltage-lock: If present, disallows changing of + preprogrammed buck dvfs voltages. + +Additional properties required if max8998,pmic-buck1-dvs-gpios is defined: +- max8998,pmic-buck1-dvs-voltage: An array of 4 voltage values in microvolts + for buck1 regulator that can be selected using dvs gpio. + +Additional properties required if max8998,pmic-buck2-dvs-gpio is defined: +- max8998,pmic-buck2-dvs-voltage: An array of 2 voltage values in microvolts + for buck2 regulator that can be selected using dvs gpio. + +Regulators: All the regulators of MAX8998 to be instantiated shall be +listed in a child node named 'regulators'. Each regulator is represented +by a child node of the 'regulators' node. + + regulator-name { + /* standard regulator bindings here */ + }; + +Following regulators of the MAX8998 PMIC block are supported. Note that +the 'n' in regulator name, as in LDOn or BUCKn, represents the LDO or BUCK +number as described in MAX8998 datasheet. + + - LDOn + - valid values for n are 2 to 17 + - Example: LDO2, LDO10, LDO17 + - BUCKn + - valid values for n are 1 to 4. + - Example: BUCK1, BUCK2, BUCK3, BUCK4 + + - ENVICHG: Battery Charging Current Monitor Output. This is a fixed + voltage type regulator + + - ESAFEOUT1: (ldo19) + - ESAFEOUT2: (ld020) + +Standard regulator bindings are used inside regulator subnodes. Check + Documentation/devicetree/bindings/regulator/regulator.txt +for more details. + +Example: + + pmic@66 { + compatible = "maxim,max8998-pmic"; + reg = <0x66>; + interrupt-parent = <&wakeup_eint>; + interrupts = <4 0>, <3 0>; + + /* Buck 1 DVS settings */ + max8998,pmic-buck1-default-dvs-idx = <0>; + max8998,pmic-buck1-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */ + <&gpx0 1 1 0 0>; /* SET2 */ + max8998,pmic-buck1-dvs-voltage = <1350000>, <1300000>, + <1000000>, <950000>; + + /* Buck 2 DVS settings */ + max8998,pmic-buck2-default-dvs-idx = <0>; + max8998,pmic-buck2-dvs-gpio = <&gpx0 0 3 0 0>; /* SET3 */ + max8998,pmic-buck2-dvs-voltage = <1350000>, <1300000>; + + /* Regulators to instantiate */ + regulators { + ldo2_reg: LDO2 { + regulator-name = "VDD_ALIVE_1.1V"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + buck1_reg: BUCK1 { + regulator-name = "VDD_ARM_1.2V"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c index d7218cc90945..21af51a499f4 100644 --- a/drivers/mfd/max8998.c +++ b/drivers/mfd/max8998.c @@ -20,12 +20,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -128,6 +131,56 @@ int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask) } EXPORT_SYMBOL(max8998_update_reg); +#ifdef CONFIG_OF +static struct of_device_id max8998_dt_match[] = { + { .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 }, + { .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 }, + { .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 }, + {}, +}; +MODULE_DEVICE_TABLE(of, max8998_dt_match); +#endif + +/* + * Only the common platform data elements for max8998 are parsed here from the + * device tree. Other sub-modules of max8998 such as pmic, rtc and others have + * to parse their own platform data elements from device tree. + * + * The max8998 platform data structure is instantiated here and the drivers for + * the sub-modules need not instantiate another instance while parsing their + * platform data. + */ +static struct max8998_platform_data *max8998_i2c_parse_dt_pdata( + struct device *dev) +{ + struct max8998_platform_data *pd; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return ERR_PTR(-ENOMEM); + + pd->ono = irq_of_parse_and_map(dev->of_node, 1); + + /* + * ToDo: the 'wakeup' member in the platform data is more of a linux + * specfic information. Hence, there is no binding for that yet and + * not parsed here. + */ + return pd; +} + +static inline int max8998_i2c_get_driver_data(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(max8998_dt_match, i2c->dev.of_node); + return (int)match->data; + } + + return (int)id->driver_data; +} + static int max8998_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -139,11 +192,20 @@ static int max8998_i2c_probe(struct i2c_client *i2c, if (max8998 == NULL) return -ENOMEM; + if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) { + pdata = max8998_i2c_parse_dt_pdata(&i2c->dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto err; + } + } + i2c_set_clientdata(i2c, max8998); max8998->dev = &i2c->dev; max8998->i2c = i2c; max8998->irq = i2c->irq; - max8998->type = id->driver_data; + max8998->type = max8998_i2c_get_driver_data(i2c, id); + max8998->pdata = pdata; if (pdata) { max8998->ono = pdata->ono; max8998->irq_base = pdata->irq_base; @@ -158,7 +220,7 @@ static int max8998_i2c_probe(struct i2c_client *i2c, pm_runtime_set_active(max8998->dev); - switch (id->driver_data) { + switch (max8998->type) { case TYPE_LP3974: ret = mfd_add_devices(max8998->dev, -1, lp3974_devs, ARRAY_SIZE(lp3974_devs), @@ -314,6 +376,7 @@ static struct i2c_driver max8998_i2c_driver = { .name = "max8998", .owner = THIS_MODULE, .pm = &max8998_pm, + .of_match_table = of_match_ptr(max8998_dt_match), }, .probe = max8998_i2c_probe, .remove = max8998_i2c_remove, diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 8c45b93b7334..a4c53b2d1aaf 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -28,8 +28,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -589,13 +592,13 @@ static struct regulator_desc regulators[] = { .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, { - .name = "EN32KHz AP", + .name = "EN32KHz-AP", .id = MAX8998_EN32KHZ_AP, .ops = &max8998_others_ops, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }, { - .name = "EN32KHz CP", + .name = "EN32KHz-CP", .id = MAX8998_EN32KHZ_CP, .ops = &max8998_others_ops, .type = REGULATOR_VOLTAGE, @@ -621,10 +624,122 @@ static struct regulator_desc regulators[] = { } }; +static int max8998_pmic_dt_parse_dvs_gpio(struct max8998_dev *iodev, + struct max8998_platform_data *pdata, + struct device_node *pmic_np) +{ + int gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 0); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck1 gpio[0]: %d\n", gpio); + return -EINVAL; + } + pdata->buck1_set1 = gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck1-dvs-gpios", 1); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck1 gpio[1]: %d\n", gpio); + return -EINVAL; + } + pdata->buck1_set2 = gpio; + + gpio = of_get_named_gpio(pmic_np, "max8998,pmic-buck2-dvs-gpio", 0); + if (!gpio_is_valid(gpio)) { + dev_err(iodev->dev, "invalid buck 2 gpio: %d\n", gpio); + return -EINVAL; + } + pdata->buck2_set3 = gpio; + + return 0; +} + +static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, + struct max8998_platform_data *pdata) +{ + struct device_node *pmic_np = iodev->dev->of_node; + struct device_node *regulators_np, *reg_np; + struct max8998_regulator_data *rdata; + unsigned int i; + int ret; + + regulators_np = of_get_child_by_name(pmic_np, "regulators"); + if (!regulators_np) { + dev_err(iodev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + /* count the number of regulators to be supported in pmic */ + pdata->num_regulators = of_get_child_count(regulators_np); + + rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * + pdata->num_regulators, GFP_KERNEL); + if (!rdata) + return -ENOMEM; + + pdata->regulators = rdata; + for (i = 0; i < ARRAY_SIZE(regulators); ++i) { + reg_np = of_get_child_by_name(regulators_np, + regulators[i].name); + if (!reg_np) + continue; + + rdata->id = regulators[i].id; + rdata->initdata = of_get_regulator_init_data( + iodev->dev, reg_np); + rdata->reg_node = reg_np; + ++rdata; + } + pdata->num_regulators = rdata - pdata->regulators; + + ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); + if (ret) + return -EINVAL; + + if (of_find_property(pmic_np, "max8998,pmic-buck-voltage-lock", NULL)) + pdata->buck_voltage_lock = true; + + ret = of_property_read_u32(pmic_np, + "max8998,pmic-buck1-default-dvs-idx", + &pdata->buck1_default_idx); + if (!ret && pdata->buck1_default_idx >= 4) { + pdata->buck1_default_idx = 0; + dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n"); + } + + ret = of_property_read_u32(pmic_np, + "max8998,pmic-buck2-default-dvs-idx", + &pdata->buck2_default_idx); + if (!ret && pdata->buck2_default_idx >= 2) { + pdata->buck2_default_idx = 0; + dev_warn(iodev->dev, "invalid value for default dvs index, using 0 instead\n"); + } + + ret = of_property_read_u32_array(pmic_np, + "max8998,pmic-buck1-dvs-voltage", + pdata->buck1_voltage, + ARRAY_SIZE(pdata->buck1_voltage)); + if (ret) { + dev_err(iodev->dev, "buck1 voltages not specified\n"); + return -EINVAL; + } + + ret = of_property_read_u32_array(pmic_np, + "max8998,pmic-buck2-dvs-voltage", + pdata->buck2_voltage, + ARRAY_SIZE(pdata->buck2_voltage)); + if (ret) { + dev_err(iodev->dev, "buck2 voltages not specified\n"); + return -EINVAL; + } + + return 0; +} + static int max8998_pmic_probe(struct platform_device *pdev) { struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev); + struct max8998_platform_data *pdata = iodev->pdata; struct regulator_config config = { }; struct regulator_dev **rdev; struct max8998_data *max8998; @@ -637,6 +752,12 @@ static int max8998_pmic_probe(struct platform_device *pdev) return -ENODEV; } + if (IS_ENABLED(CONFIG_OF) && iodev->dev->of_node) { + ret = max8998_pmic_dt_parse_pdata(iodev, pdata); + if (ret) + return ret; + } + max8998 = devm_kzalloc(&pdev->dev, sizeof(struct max8998_data), GFP_KERNEL); if (!max8998) @@ -750,13 +871,15 @@ static int max8998_pmic_probe(struct platform_device *pdev) } config.dev = max8998->dev; + config.of_node = pdata->regulators[i].reg_node; config.init_data = pdata->regulators[i].initdata; config.driver_data = max8998; rdev[i] = regulator_register(®ulators[index], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); - dev_err(max8998->dev, "regulator init failed\n"); + dev_err(max8998->dev, "regulator %s init failed (%d)\n", + regulators[index].name, ret); rdev[i] = NULL; goto err; } diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 46f23014759b..042a8734bd28 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -253,7 +253,7 @@ static const struct rtc_class_ops max8998_rtc_ops = { static int max8998_rtc_probe(struct platform_device *pdev) { struct max8998_dev *max8998 = dev_get_drvdata(pdev->dev.parent); - struct max8998_platform_data *pdata = dev_get_platdata(max8998->dev); + struct max8998_platform_data *pdata = max8998->pdata; struct max8998_rtc_info *info; int ret; diff --git a/include/linux/mfd/max8998-private.h b/include/linux/mfd/max8998-private.h index bfb48b6fcc74..84844e0a5704 100644 --- a/include/linux/mfd/max8998-private.h +++ b/include/linux/mfd/max8998-private.h @@ -137,6 +137,7 @@ struct irq_domain; /** * struct max8998_dev - max8998 master device for sub-drivers * @dev: master device of the chip (can be used to access platform data) + * @pdata: platform data for the driver and subdrivers * @i2c: i2c client private data for regulator * @rtc: i2c client private data for rtc * @iolock: mutex for serializing io access @@ -150,6 +151,7 @@ struct irq_domain; */ struct max8998_dev { struct device *dev; + struct max8998_platform_data *pdata; struct i2c_client *i2c; struct i2c_client *rtc; struct mutex iolock; diff --git a/include/linux/mfd/max8998.h b/include/linux/mfd/max8998.h index ca56bb03bc69..e3956a654cbc 100644 --- a/include/linux/mfd/max8998.h +++ b/include/linux/mfd/max8998.h @@ -58,10 +58,12 @@ enum { * max8998_regulator_data - regulator data * @id: regulator id * @initdata: regulator init data (contraints, supplies, ...) + * @reg_node: DT node of regulator (unused on non-DT platforms) */ struct max8998_regulator_data { int id; struct regulator_init_data *initdata; + struct device_node *reg_node; }; /** -- GitLab From e51c288ea15b13c7d9982251c8397853f7cfb18f Mon Sep 17 00:00:00 2001 From: Kevin Strasser Date: Sun, 23 Jun 2013 21:00:06 -0700 Subject: [PATCH 2045/2900] watchdog: Kontron PLD watchdog timer driver Add watchdog timer support for the on-board PLD found on some Kontron embedded modules. Originally-From: Michael Brunner Signed-off-by: Kevin Strasser Acked-by: Guenter Roeck Acked-by: Darren Hart Acked-by: Wim Van Sebroeck Signed-off-by: Samuel Ortiz --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/kempld_wdt.c | 581 ++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+) create mode 100644 drivers/watchdog/kempld_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index e89fc3133972..7460d349df59 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -687,6 +687,17 @@ config HP_WATCHDOG To compile this driver as a module, choose M here: the module will be called hpwdt. +config KEMPLD_WDT + tristate "Kontron COM Watchdog Timer" + depends on MFD_KEMPLD + select WATCHDOG_CORE + help + Support for the PLD watchdog on some Kontron ETX and COMexpress + (ETXexpress) modules + + This driver can also be built as a module. If so, the module will be + called kempld_wdt. + config HPWDT_NMI_DECODING bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" depends on HP_WATCHDOG diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a300b948f254..ec268995b261 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -90,6 +90,7 @@ endif obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o obj-$(CONFIG_IT87_WDT) += it87_wdt.o obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o +obj-$(CONFIG_KEMPLD_WDT) += kempld_wdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c new file mode 100644 index 000000000000..491419e0772a --- /dev/null +++ b/drivers/watchdog/kempld_wdt.c @@ -0,0 +1,581 @@ +/* + * Kontron PLD watchdog driver + * + * Copyright (c) 2010-2013 Kontron Europe GmbH + * Author: Michael Brunner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Note: From the PLD watchdog point of view timeout and pretimeout are + * defined differently than in the kernel. + * First the pretimeout stage runs out before the timeout stage gets + * active. + * + * Kernel/API: P-----| pretimeout + * |-----------------------T timeout + * Watchdog: |-----------------P pretimeout_stage + * |-----T timeout_stage + */ + +#include +#include +#include +#include +#include +#include +#include + +#define KEMPLD_WDT_STAGE_TIMEOUT(x) (0x1b + (x) * 4) +#define KEMPLD_WDT_STAGE_CFG(x) (0x18 + (x)) +#define STAGE_CFG_GET_PRESCALER(x) (((x) & 0x30) >> 4) +#define STAGE_CFG_SET_PRESCALER(x) (((x) & 0x30) << 4) +#define STAGE_CFG_PRESCALER_MASK 0x30 +#define STAGE_CFG_ACTION_MASK 0x7 +#define STAGE_CFG_ASSERT (1 << 3) + +#define KEMPLD_WDT_MAX_STAGES 2 +#define KEMPLD_WDT_KICK 0x16 +#define KEMPLD_WDT_CFG 0x17 +#define KEMPLD_WDT_CFG_ENABLE 0x10 +#define KEMPLD_WDT_CFG_ENABLE_LOCK 0x8 +#define KEMPLD_WDT_CFG_GLOBAL_LOCK 0x80 + +enum { + ACTION_NONE = 0, + ACTION_RESET, + ACTION_NMI, + ACTION_SMI, + ACTION_SCI, + ACTION_DELAY, +}; + +enum { + STAGE_TIMEOUT = 0, + STAGE_PRETIMEOUT, +}; + +enum { + PRESCALER_21 = 0, + PRESCALER_17, + PRESCALER_12, +}; + +const u32 kempld_prescaler[] = { + [PRESCALER_21] = (1 << 21) - 1, + [PRESCALER_17] = (1 << 17) - 1, + [PRESCALER_12] = (1 << 12) - 1, + 0, +}; + +struct kempld_wdt_stage { + unsigned int id; + u32 mask; +}; + +struct kempld_wdt_data { + struct kempld_device_data *pld; + struct watchdog_device wdd; + unsigned int pretimeout; + struct kempld_wdt_stage stage[KEMPLD_WDT_MAX_STAGES]; +#ifdef CONFIG_PM + u8 pm_status_store; +#endif +}; + +#define DEFAULT_TIMEOUT 30 /* seconds */ +#define DEFAULT_PRETIMEOUT 0 + +static unsigned int timeout = DEFAULT_TIMEOUT; +module_param(timeout, uint, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. (>=0, default=" + __MODULE_STRING(DEFAULT_TIMEOUT) ")"); + +static unsigned int pretimeout = DEFAULT_PRETIMEOUT; +module_param(pretimeout, uint, 0); +MODULE_PARM_DESC(pretimeout, + "Watchdog pretimeout in seconds. (>=0, default=" + __MODULE_STRING(DEFAULT_PRETIMEOUT) ")"); + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, + "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static int kempld_wdt_set_stage_action(struct kempld_wdt_data *wdt_data, + struct kempld_wdt_stage *stage, + u8 action) +{ + struct kempld_device_data *pld = wdt_data->pld; + u8 stage_cfg; + + if (!stage || !stage->mask) + return -EINVAL; + + kempld_get_mutex(pld); + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); + stage_cfg &= ~STAGE_CFG_ACTION_MASK; + stage_cfg |= (action & STAGE_CFG_ACTION_MASK); + + if (action == ACTION_RESET) + stage_cfg |= STAGE_CFG_ASSERT; + else + stage_cfg &= ~STAGE_CFG_ASSERT; + + kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg); + kempld_release_mutex(pld); + + return 0; +} + +static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data, + struct kempld_wdt_stage *stage, + unsigned int timeout) +{ + struct kempld_device_data *pld = wdt_data->pld; + u32 prescaler = kempld_prescaler[PRESCALER_21]; + u64 stage_timeout64; + u32 stage_timeout; + u32 remainder; + u8 stage_cfg; + + if (!stage) + return -EINVAL; + + stage_timeout64 = (u64)timeout * pld->pld_clock; + remainder = do_div(stage_timeout64, prescaler); + if (remainder) + stage_timeout64++; + + if (stage_timeout64 > stage->mask) + return -EINVAL; + + stage_timeout = stage_timeout64 & stage->mask; + + kempld_get_mutex(pld); + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); + stage_cfg &= ~STAGE_CFG_PRESCALER_MASK; + stage_cfg |= STAGE_CFG_SET_PRESCALER(prescaler); + kempld_write8(pld, KEMPLD_WDT_STAGE_CFG(stage->id), stage_cfg); + kempld_write32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id), + stage_timeout); + kempld_release_mutex(pld); + + return 0; +} + +/* + * kempld_get_mutex must be called prior to calling this function. + */ +static unsigned int kempld_wdt_get_timeout(struct kempld_wdt_data *wdt_data, + struct kempld_wdt_stage *stage) +{ + struct kempld_device_data *pld = wdt_data->pld; + unsigned int timeout; + u64 stage_timeout; + u32 prescaler; + u32 remainder; + u8 stage_cfg; + + if (!stage->mask) + return 0; + + stage_cfg = kempld_read8(pld, KEMPLD_WDT_STAGE_CFG(stage->id)); + stage_timeout = kempld_read32(pld, KEMPLD_WDT_STAGE_TIMEOUT(stage->id)); + prescaler = kempld_prescaler[STAGE_CFG_GET_PRESCALER(stage_cfg)]; + + stage_timeout = (stage_timeout & stage->mask) * prescaler; + remainder = do_div(stage_timeout, pld->pld_clock); + if (remainder) + stage_timeout++; + + timeout = stage_timeout; + WARN_ON_ONCE(timeout != stage_timeout); + + return timeout; +} + +static int kempld_wdt_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_wdt_stage *pretimeout_stage; + struct kempld_wdt_stage *timeout_stage; + int ret; + + timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; + pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; + + if (pretimeout_stage->mask && wdt_data->pretimeout > 0) + timeout = wdt_data->pretimeout; + + ret = kempld_wdt_set_stage_action(wdt_data, timeout_stage, + ACTION_RESET); + if (ret) + return ret; + ret = kempld_wdt_set_stage_timeout(wdt_data, timeout_stage, + timeout); + if (ret) + return ret; + + wdd->timeout = timeout; + return 0; +} + +static int kempld_wdt_set_pretimeout(struct watchdog_device *wdd, + unsigned int pretimeout) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_wdt_stage *pretimeout_stage; + u8 action = ACTION_NONE; + int ret; + + pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; + + if (!pretimeout_stage->mask) + return -ENXIO; + + if (pretimeout > wdd->timeout) + return -EINVAL; + + if (pretimeout > 0) + action = ACTION_NMI; + + ret = kempld_wdt_set_stage_action(wdt_data, pretimeout_stage, + action); + if (ret) + return ret; + ret = kempld_wdt_set_stage_timeout(wdt_data, pretimeout_stage, + wdd->timeout - pretimeout); + if (ret) + return ret; + + wdt_data->pretimeout = pretimeout; + return 0; +} + +static void kempld_wdt_update_timeouts(struct kempld_wdt_data *wdt_data) +{ + struct kempld_device_data *pld = wdt_data->pld; + struct kempld_wdt_stage *pretimeout_stage; + struct kempld_wdt_stage *timeout_stage; + unsigned int pretimeout, timeout; + + pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; + timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; + + kempld_get_mutex(pld); + pretimeout = kempld_wdt_get_timeout(wdt_data, pretimeout_stage); + timeout = kempld_wdt_get_timeout(wdt_data, timeout_stage); + kempld_release_mutex(pld); + + if (pretimeout) + wdt_data->pretimeout = timeout; + else + wdt_data->pretimeout = 0; + + wdt_data->wdd.timeout = pretimeout + timeout; +} + +static int kempld_wdt_start(struct watchdog_device *wdd) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_device_data *pld = wdt_data->pld; + u8 status; + int ret; + + ret = kempld_wdt_set_timeout(wdd, wdd->timeout); + if (ret) + return ret; + + kempld_get_mutex(pld); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + status |= KEMPLD_WDT_CFG_ENABLE; + kempld_write8(pld, KEMPLD_WDT_CFG, status); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + kempld_release_mutex(pld); + + /* Check if the watchdog was enabled */ + if (!(status & KEMPLD_WDT_CFG_ENABLE)) + return -EACCES; + + return 0; +} + +static int kempld_wdt_stop(struct watchdog_device *wdd) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_device_data *pld = wdt_data->pld; + u8 status; + + kempld_get_mutex(pld); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + status &= ~KEMPLD_WDT_CFG_ENABLE; + kempld_write8(pld, KEMPLD_WDT_CFG, status); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + kempld_release_mutex(pld); + + /* Check if the watchdog was disabled */ + if (status & KEMPLD_WDT_CFG_ENABLE) + return -EACCES; + + return 0; +} + +static int kempld_wdt_keepalive(struct watchdog_device *wdd) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_device_data *pld = wdt_data->pld; + + kempld_get_mutex(pld); + kempld_write8(pld, KEMPLD_WDT_KICK, 'K'); + kempld_release_mutex(pld); + + return 0; +} + +static long kempld_wdt_ioctl(struct watchdog_device *wdd, unsigned int cmd, + unsigned long arg) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + void __user *argp = (void __user *)arg; + int ret = -ENOIOCTLCMD; + int __user *p = argp; + int new_value; + + switch (cmd) { + case WDIOC_SETPRETIMEOUT: + if (get_user(new_value, p)) + return -EFAULT; + ret = kempld_wdt_set_pretimeout(wdd, new_value); + if (ret) + return ret; + ret = kempld_wdt_keepalive(wdd); + break; + case WDIOC_GETPRETIMEOUT: + ret = put_user(wdt_data->pretimeout, (int *)arg); + break; + } + + return ret; +} + +static int kempld_wdt_probe_stages(struct watchdog_device *wdd) +{ + struct kempld_wdt_data *wdt_data = watchdog_get_drvdata(wdd); + struct kempld_device_data *pld = wdt_data->pld; + struct kempld_wdt_stage *pretimeout_stage; + struct kempld_wdt_stage *timeout_stage; + u8 index, data, data_orig; + u32 mask; + int i, j; + + pretimeout_stage = &wdt_data->stage[STAGE_PRETIMEOUT]; + timeout_stage = &wdt_data->stage[STAGE_TIMEOUT]; + + pretimeout_stage->mask = 0; + timeout_stage->mask = 0; + + for (i = 0; i < 3; i++) { + index = KEMPLD_WDT_STAGE_TIMEOUT(i); + mask = 0; + + kempld_get_mutex(pld); + /* Probe each byte individually. */ + for (j = 0; j < 4; j++) { + data_orig = kempld_read8(pld, index + j); + kempld_write8(pld, index + j, 0x00); + data = kempld_read8(pld, index + j); + /* A failed write means this byte is reserved */ + if (data != 0x00) + break; + kempld_write8(pld, index + j, data_orig); + mask |= 0xff << (j * 8); + } + kempld_release_mutex(pld); + + /* Assign available stages to timeout and pretimeout */ + if (!timeout_stage->mask) { + timeout_stage->mask = mask; + timeout_stage->id = i; + } else { + if (pld->feature_mask & KEMPLD_FEATURE_BIT_NMI) { + pretimeout_stage->mask = timeout_stage->mask; + timeout_stage->mask = mask; + pretimeout_stage->id = timeout_stage->id; + timeout_stage->id = i; + } + break; + } + } + + if (!timeout_stage->mask) + return -ENODEV; + + return 0; +} + +static struct watchdog_info kempld_wdt_info = { + .identity = "KEMPLD Watchdog", + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE | + WDIOF_PRETIMEOUT +}; + +static struct watchdog_ops kempld_wdt_ops = { + .owner = THIS_MODULE, + .start = kempld_wdt_start, + .stop = kempld_wdt_stop, + .ping = kempld_wdt_keepalive, + .set_timeout = kempld_wdt_set_timeout, + .ioctl = kempld_wdt_ioctl, +}; + +static int kempld_wdt_probe(struct platform_device *pdev) +{ + struct kempld_device_data *pld = dev_get_drvdata(pdev->dev.parent); + struct kempld_wdt_data *wdt_data; + struct device *dev = &pdev->dev; + struct watchdog_device *wdd; + u8 status; + int ret = 0; + + wdt_data = devm_kzalloc(dev, sizeof(*wdt_data), GFP_KERNEL); + if (!wdt_data) + return -ENOMEM; + + wdt_data->pld = pld; + wdd = &wdt_data->wdd; + wdd->parent = dev; + + kempld_get_mutex(pld); + status = kempld_read8(pld, KEMPLD_WDT_CFG); + kempld_release_mutex(pld); + + /* Enable nowayout if watchdog is already locked */ + if (status & (KEMPLD_WDT_CFG_ENABLE_LOCK | + KEMPLD_WDT_CFG_GLOBAL_LOCK)) { + if (!nowayout) + dev_warn(dev, + "Forcing nowayout - watchdog lock enabled!\n"); + nowayout = true; + } + + wdd->info = &kempld_wdt_info; + wdd->ops = &kempld_wdt_ops; + + watchdog_set_drvdata(wdd, wdt_data); + watchdog_set_nowayout(wdd, nowayout); + + ret = kempld_wdt_probe_stages(wdd); + if (ret) + return ret; + + kempld_wdt_set_timeout(wdd, timeout); + kempld_wdt_set_pretimeout(wdd, pretimeout); + + /* Check if watchdog is already enabled */ + if (status & KEMPLD_WDT_CFG_ENABLE) { + /* Get current watchdog settings */ + kempld_wdt_update_timeouts(wdt_data); + dev_info(dev, "Watchdog was already enabled\n"); + } + + platform_set_drvdata(pdev, wdt_data); + ret = watchdog_register_device(wdd); + if (ret) + return ret; + + dev_info(dev, "Watchdog registered with %ds timeout\n", wdd->timeout); + + return 0; +} + +static void kempld_wdt_shutdown(struct platform_device *pdev) +{ + struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); + + kempld_wdt_stop(&wdt_data->wdd); +} + +static int kempld_wdt_remove(struct platform_device *pdev) +{ + struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); + struct watchdog_device *wdd = &wdt_data->wdd; + int ret = 0; + + if (!nowayout) + ret = kempld_wdt_stop(wdd); + watchdog_unregister_device(wdd); + + return ret; +} + +#ifdef CONFIG_PM +/* Disable watchdog if it is active during suspend */ +static int kempld_wdt_suspend(struct platform_device *pdev, + pm_message_t message) +{ + struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); + struct kempld_device_data *pld = wdt_data->pld; + struct watchdog_device *wdd = &wdt_data->wdd; + + kempld_get_mutex(pld); + wdt_data->pm_status_store = kempld_read8(pld, KEMPLD_WDT_CFG); + kempld_release_mutex(pld); + + kempld_wdt_update_timeouts(wdt_data); + + if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) + return kempld_wdt_stop(wdd); + + return 0; +} + +/* Enable watchdog and configure it if necessary */ +static int kempld_wdt_resume(struct platform_device *pdev) +{ + struct kempld_wdt_data *wdt_data = platform_get_drvdata(pdev); + struct watchdog_device *wdd = &wdt_data->wdd; + + /* + * If watchdog was stopped before suspend be sure it gets disabled + * again, for the case BIOS has enabled it during resume + */ + if (wdt_data->pm_status_store & KEMPLD_WDT_CFG_ENABLE) + return kempld_wdt_start(wdd); + else + return kempld_wdt_stop(wdd); +} +#else +#define kempld_wdt_suspend NULL +#define kempld_wdt_resume NULL +#endif + +static struct platform_driver kempld_wdt_driver = { + .driver = { + .name = "kempld-wdt", + .owner = THIS_MODULE, + }, + .probe = kempld_wdt_probe, + .remove = kempld_wdt_remove, + .shutdown = kempld_wdt_shutdown, + .suspend = kempld_wdt_suspend, + .resume = kempld_wdt_resume, +}; + +module_platform_driver(kempld_wdt_driver); + +MODULE_DESCRIPTION("KEM PLD Watchdog Driver"); +MODULE_AUTHOR("Michael Brunner "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From dc6641822e412ff527e022ec752707ebb034add4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 28 Jun 2013 15:12:23 +0100 Subject: [PATCH 2046/2900] mfd: sec: Remove fields not used since regmap conversion These were all used by the open coded I/O and IRQ implementations and are no longer referenced now that the regmap core variants are used instead. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- include/linux/mfd/samsung/core.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h index f0f4de3b4ccc..378ae8a04c6a 100644 --- a/include/linux/mfd/samsung/core.h +++ b/include/linux/mfd/samsung/core.h @@ -14,8 +14,6 @@ #ifndef __LINUX_MFD_SEC_CORE_H #define __LINUX_MFD_SEC_CORE_H -#define NUM_IRQ_REGS 4 - enum sec_device_type { S5M8751X, S5M8763X, @@ -44,8 +42,6 @@ struct sec_pmic_dev { struct regmap *regmap; struct i2c_client *i2c; struct i2c_client *rtc; - struct mutex iolock; - struct mutex irqlock; int device_type; int irq_base; @@ -53,8 +49,6 @@ struct sec_pmic_dev { struct regmap_irq_chip_data *irq_data; int ono; - u8 irq_masks_cur[NUM_IRQ_REGS]; - u8 irq_masks_cache[NUM_IRQ_REGS]; int type; bool wakeup; }; -- GitLab From 55b5940df9cefcd5cf1ba4b4f538b303b725b546 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 28 Jun 2013 15:14:11 +0100 Subject: [PATCH 2047/2900] MAINTAINERS: Add include directory to MFD file patterns Ensure that get_maintainer.pl does the right thing for header only changes. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 39fd4e794b1e..3d064ab5bc1a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5437,6 +5437,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git S: Supported F: drivers/mfd/ +F: include/linux/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM M: Chris Ball -- GitLab From f820b60582f75e73e83b8505d7e48fe59770f558 Mon Sep 17 00:00:00 2001 From: Takanari Hayama Date: Mon, 1 Jul 2013 16:38:53 +0900 Subject: [PATCH 2048/2900] ARM: shmobile: r8a73a4: Fix resources for SCIFB0 Fix base address and IRQ resources associated with SCIFB0. This bug was introduced by e481a528901d0cd18b5b5fcbdc55207ea3b6ef68 ("ARM: shmobile: r8a73a4 SCIF support V3") which was included in v3.10. Signed-off-by: Takanari Hayama Acked-by: Magnus Damm [ horms+renesas@verge.net.au: Add information about commit and version this bug was added in ] Signed-off-by: Simon Horman Cc: stable@vger.kernel.org --- arch/arm/mach-shmobile/setup-r8a73a4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c index c5a75a7a508f..7f45c2edbca9 100644 --- a/arch/arm/mach-shmobile/setup-r8a73a4.c +++ b/arch/arm/mach-shmobile/setup-r8a73a4.c @@ -62,7 +62,7 @@ enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFB3 }; static const struct plat_sci_port scif[] = { SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */ SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */ - SCIFB_DATA(SCIFB0, 0xe6c50000, gic_spi(145)), /* SCIFB0 */ + SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */ SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */ SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */ SCIFB_DATA(SCIFB3, 0xe6cf0000, gic_spi(151)), /* SCIFB3 */ -- GitLab From 7c9e6150f2e7cbd60e0bc9a19118ca1dc97d2780 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 1 Jul 2013 16:16:10 +0800 Subject: [PATCH 2049/2900] ASoC: mxs: register saif mclk to clock framework Mostly the mxs system design uses saif0 mclk output as the clock source of codec. Since the mclk is implemented as a general divider with the saif clk as the parent clock, let's register the mclk as a basic clk-divider to common clock framework. Then with it being a clock provdier, clk_get() call in codec driver probe function will just work. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index d31dc52fa862..9ad6dccf791d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -662,6 +663,33 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static int mxs_saif_mclk_init(struct platform_device *pdev) +{ + struct mxs_saif *saif = platform_get_drvdata(pdev); + struct device_node *np = pdev->dev.of_node; + struct clk *clk; + int ret; + + clk = clk_register_divider(&pdev->dev, "mxs_saif_mclk", + __clk_get_name(saif->clk), 0, + saif->base + SAIF_CTRL, + BP_SAIF_CTRL_BITCLK_MULT_RATE, 3, + 0, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + if (ret == -EEXIST) + return 0; + dev_err(&pdev->dev, "failed to register mclk: %d\n", ret); + return PTR_ERR(clk); + } + + ret = of_clk_add_provider(np, of_clk_src_simple_get, clk); + if (ret) + return ret; + + return 0; +} + static int mxs_saif_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -769,6 +797,13 @@ static int mxs_saif_probe(struct platform_device *pdev) platform_set_drvdata(pdev, saif); + /* We only support saif0 being tx and clock master */ + if (saif->id == 0) { + ret = mxs_saif_mclk_init(pdev); + if (ret) + dev_warn(&pdev->dev, "failed to init clocks\n"); + } + ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component, &mxs_saif_dai, 1); if (ret) { -- GitLab From e4760363ea14b7b707ba68ab780c8ecf98a84c15 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 1 Jul 2013 15:30:51 +0300 Subject: [PATCH 2050/2900] remoteproc/omap: fix a sparse warning This patch fixes a sparse warning in the omap remoteproc code when OMAP_REMOTEPROC is disabled. include/linux/platform_data/remoteproc-omap.h:76:13: warning: symbol 'omap_rproc_reserve_cma' was not declared. Should it be static? Signed-off-by: Suman Anna Signed-off-by: Ohad Ben-Cohen --- include/linux/platform_data/remoteproc-omap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/platform_data/remoteproc-omap.h b/include/linux/platform_data/remoteproc-omap.h index 3c1c6444ec4b..bfbd12b41162 100644 --- a/include/linux/platform_data/remoteproc-omap.h +++ b/include/linux/platform_data/remoteproc-omap.h @@ -50,7 +50,7 @@ void __init omap_rproc_reserve_cma(void); #else -void __init omap_rproc_reserve_cma(void) +static inline void __init omap_rproc_reserve_cma(void) { } -- GitLab From 23df34155b29674465813b327647cd79722aa659 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 1 Jul 2013 09:38:30 +0000 Subject: [PATCH 2051/2900] MIPS: Boot: Compressed: Remove -fstack-protector from CFLAGS When building with -fstack-protector, gcc emits the __stack_chk_guard and __stack_chk_fail symbols to check for stack stability. These symbols are defined in vmlinux but the generated vmlinux.bin that is used to create the compressed vmlinuz image has no symbol table so the linker can't find these symbols during the final linking phase. As a result of which, we need either to redefine these symbols just for the compressed image or drop the -fstack-protector option when building the compressed image. This patch implements the latter of two options. Fixes the following linking problem: dbg.c:(.text+0x7c): undefined reference to `__stack_chk_guard' dbg.c:(.text+0x80): undefined reference to `__stack_chk_guard' dbg.c:(.text+0xd4): undefined reference to `__stack_chk_guard' dbg.c:(.text+0xec): undefined reference to `__stack_chk_fail' [ralf@linux-mips.org: I'm applying this before the patch that actually adds stack protector support for MIPS. This means, it will not be possible to trigger above error message with any commit from the tree but rather they are what one would hit without this commit.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/5575/ Signed-off-by: Ralf Baechle --- arch/mips/boot/compressed/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index bbaa1d4beb6d..bb1dbf4abb9d 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -18,6 +18,8 @@ BOOT_HEAP_SIZE := 0x400000 # Disable Function Tracer KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//") +KBUILD_CFLAGS := $(filter-out -fstack-protector, $(KBUILD_CFLAGS)) + KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" -- GitLab From 36ecafc5ad17861e2bc1fb12af4cc97680e25942 Mon Sep 17 00:00:00 2001 From: Gregory Fong Date: Wed, 12 Jun 2013 17:08:54 +0000 Subject: [PATCH 2052/2900] MIPS: initial stack protector support Implements basic stack protector support based on ARM version in c743f38013aeff58ef6252601e397b5ba281c633 , with Kconfig option, constant canary value set at boot time, and script to check if compiler actually supports stack protector. Tested by creating a kernel module that writes past end of char[]. Signed-off-by: Gregory Fong Cc: linux-mips@linux-mips.org Cc: Filippo Arcidiacono Cc: Carmelo Amoroso Patchwork: https://patchwork.linux-mips.org/patch/5448/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 13 +++++++++ arch/mips/Makefile | 4 +++ arch/mips/include/asm/stackprotector.h | 40 ++++++++++++++++++++++++++ arch/mips/kernel/process.c | 6 ++++ 4 files changed, 63 insertions(+) create mode 100644 arch/mips/include/asm/stackprotector.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 69bf31062ca4..6dbeb273afc6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2367,6 +2367,19 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config CC_STACKPROTECTOR + bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" + help + This option turns on the -fstack-protector GCC feature. This + feature puts, at the beginning of functions, a canary value on + the stack just before the return address, and validates + the value just before actually returning. Stack based buffer + overflows (that need to overwrite this return address) now also + overwrite the canary, which gets detected and the attack is then + neutralized via a kernel panic. + + This feature requires gcc version 4.2 or above. + config USE_OF bool select OF diff --git a/arch/mips/Makefile b/arch/mips/Makefile index dd58a04ef4bc..37f9ef324f2f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -227,6 +227,10 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) LDFLAGS += -m $(ld-emul) +ifdef CONFIG_CC_STACKPROTECTOR + KBUILD_CFLAGS += -fstack-protector +endif + ifdef CONFIG_MIPS CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ diff --git a/arch/mips/include/asm/stackprotector.h b/arch/mips/include/asm/stackprotector.h new file mode 100644 index 000000000000..eb9b1035e926 --- /dev/null +++ b/arch/mips/include/asm/stackprotector.h @@ -0,0 +1,40 @@ +/* + * GCC stack protector support. + * + * (This is directly adopted from the ARM implementation) + * + * Stack protector works by putting predefined pattern at the start of + * the stack frame and verifying that it hasn't been overwritten when + * returning from the function. The pattern is called stack canary + * and gcc expects it to be defined by a global variable called + * "__stack_chk_guard" on MIPS. This unfortunately means that on SMP + * we cannot have a different canary value per task. + */ + +#ifndef _ASM_STACKPROTECTOR_H +#define _ASM_STACKPROTECTOR_H 1 + +#include +#include + +extern unsigned long __stack_chk_guard; + +/* + * Initialize the stackprotector canary value. + * + * NOTE: this must only be called from functions that never return, + * and it must always be inlined. + */ +static __always_inline void boot_init_stack_canary(void) +{ + unsigned long canary; + + /* Try to get a semi random initial value. */ + get_random_bytes(&canary, sizeof(canary)); + canary ^= LINUX_VERSION_CODE; + + current->stack_canary = canary; + __stack_chk_guard = current->stack_canary; +} + +#endif /* _ASM_STACKPROTECTOR_H */ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index c6a041d9d05d..7d62894f7e23 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -201,6 +201,12 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) return 1; } +#ifdef CONFIG_CC_STACKPROTECTOR +#include +unsigned long __stack_chk_guard __read_mostly; +EXPORT_SYMBOL(__stack_chk_guard); +#endif + /* * */ -- GitLab From 1400eb656760d14274ed08e45824ccbcc366585b Mon Sep 17 00:00:00 2001 From: Gregory Fong Date: Mon, 17 Jun 2013 19:36:07 +0000 Subject: [PATCH 2053/2900] MIPS: r4k,octeon,r2300: stack protector: change canary per task For non-SMP, uses the new random canary value that is stored in the task struct whenever a new task is forked. Based on ARM version in df0698be14c6683606d5df2d83e3ae40f85ed0d9 and subject to the same limitations: the variable GCC expects, __stack_chk_guard, is global, so this will not work on SMP. Quoting Nicolas Pitre : "One way to overcome this GCC limitation would be to locate the __stack_chk_guard variable into a memory page of its own for each CPU, and then use TLB locking to have each CPU see its own page at the same virtual address for each of them." Signed-off-by: Gregory Fong Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5488/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/asm-offsets.c | 3 +++ arch/mips/kernel/octeon_switch.S | 7 +++++++ arch/mips/kernel/r2300_switch.S | 7 +++++++ arch/mips/kernel/r4k_switch.S | 6 ++++++ 4 files changed, 23 insertions(+) diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 0845091ba480..0c2e853c3db4 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -82,6 +82,9 @@ void output_task_defines(void) OFFSET(TASK_FLAGS, task_struct, flags); OFFSET(TASK_MM, task_struct, mm); OFFSET(TASK_PID, task_struct, pid); +#if defined(CONFIG_CC_STACKPROTECTOR) + OFFSET(TASK_STACK_CANARY, task_struct, stack_canary); +#endif DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct)); BLANK(); } diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 22e2aa1e8d37..4204d76af854 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S @@ -71,6 +71,13 @@ mtc0 t0, $11,7 /* CvmMemCtl */ #endif 3: + +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + PTR_L t8, __stack_chk_guard + LONG_L t9, TASK_STACK_CANARY(a1) + LONG_S t9, 0(t8) +#endif + /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index 5266c6ee2b35..38af83f84c4a 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S @@ -65,6 +65,13 @@ LEAF(resume) fpu_save_single a0, t0 # clobbers t0 1: + +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + PTR_L t8, __stack_chk_guard + LONG_L t9, TASK_STACK_CANARY(a1) + LONG_S t9, 0(t8) +#endif + /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 5e51219990aa..921238a6bd26 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -68,6 +68,12 @@ # clobbers t1 1: +#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + PTR_L t8, __stack_chk_guard + LONG_L t9, TASK_STACK_CANARY(a1) + LONG_S t9, 0(t8) +#endif + /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. -- GitLab From 937ad1042572bb3641fcbbc477f5c6b137b3a5e0 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Mon, 3 Jun 2013 14:39:34 +0000 Subject: [PATCH 2054/2900] MIPS: BCM63XX: Handle SW IRQs 0-1 MIPS software IRQs 0 and 1 are used for interprocessor signaling (IPI) on BMIPS SMP. Make the board support code aware of them. Signed-off-by: Kevin Cernekee [jogo@openwrt.org: move sw irqs behind timer irq] Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: John Crispin Cc: Maxime Bizon Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5354/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/irq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index c0ab3887f42e..d744606e19e9 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -294,6 +294,10 @@ asmlinkage void plat_irq_dispatch(void) if (cause & CAUSEF_IP7) do_IRQ(7); + if (cause & CAUSEF_IP0) + do_IRQ(0); + if (cause & CAUSEF_IP1) + do_IRQ(1); if (cause & CAUSEF_IP2) dispatch_internal(); if (!is_ext_irq_cascaded) { -- GitLab From d6e3469832185db579e5b38fa2e0ff1b79f43886 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 3 Jun 2013 14:39:35 +0000 Subject: [PATCH 2055/2900] MIPS: BCM63XX: select BMIPS4350 and default to 2 CPUs for supported SoCs All BCM63XX SoCs starting with BCM6358 have a BMIPS4350 instead of a BMIPS3300, so select it unless support for any of the older SoCs is selected. All BMIPS4350 have only two CPUs, so select the appropriate default. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: John Crispin Cc: Maxime Bizon Cc: Florian Fainelli Cc: Kevin Cernekee Patchwork: https://patchwork.linux-mips.org/patch/5355/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 6dbeb273afc6..26779ccae116 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -126,6 +126,8 @@ config BCM63XX select DMA_NONCOHERENT select IRQ_CPU select SYS_HAS_CPU_MIPS32_R1 + select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348 + select NR_CPUS_DEFAULT_2 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_EARLY_PRINTK -- GitLab From 4b54f06522ed97e7870e7146840fc8169bbcdb48 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Sat, 15 Jun 2013 10:12:46 +0000 Subject: [PATCH 2056/2900] MIPS: remove alloc_pci_controller prototype Commit 610019baddcb4c4c323c12cd44ca7f73d7145d6f ("[MIPS] Remove unused function alloc_pci_controller.") removed the function, but left the prototype in the header file. Remove it as well so people don't get tempted to use it and wonder why it doesn't work. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5473/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pci.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index b8e24fd4cbc5..fa8e0aa250ca 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -52,7 +52,6 @@ struct pci_controller { /* * Used by boards to register their PCI busses before the actual scanning. */ -extern struct pci_controller * alloc_pci_controller(void); extern void register_pci_controller(struct pci_controller *hose); /* -- GitLab From a932fec84c633a5123b7d449a0588018678684cb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 18 Jun 2013 10:40:39 +0200 Subject: [PATCH 2057/2900] MIPS: Use proper include guard symbol for . Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/fcntl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h index 0bda78f70e1e..07afa6fe1e44 100644 --- a/arch/mips/include/uapi/asm/fcntl.h +++ b/arch/mips/include/uapi/asm/fcntl.h @@ -5,8 +5,8 @@ * * Copyright (C) 1995, 96, 97, 98, 99, 2003, 05 Ralf Baechle */ -#ifndef _ASM_FCNTL_H -#define _ASM_FCNTL_H +#ifndef _UAPI_ASM_FCNTL_H +#define _UAPI_ASM_FCNTL_H #define O_APPEND 0x0008 @@ -74,4 +74,4 @@ struct flock { #include -#endif /* _ASM_FCNTL_H */ +#endif /* _UAPI_ASM_FCNTL_H */ -- GitLab From 5a772eee5544f4f84139868f7cd05806b805610d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 18 Jun 2013 13:39:12 +0200 Subject: [PATCH 2058/2900] MIPS: fcntl.h: Use __kernel_off_t, not off_t. Signed-off-by: Ralf Baechle --- arch/mips/include/uapi/asm/fcntl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h index 07afa6fe1e44..314c79b76d2a 100644 --- a/arch/mips/include/uapi/asm/fcntl.h +++ b/arch/mips/include/uapi/asm/fcntl.h @@ -61,8 +61,8 @@ struct flock { short l_type; short l_whence; - off_t l_start; - off_t l_len; + __kernel_off_t l_start; + __kernel_off_t l_len; long l_sysid; __kernel_pid_t l_pid; long pad[4]; -- GitLab From 169c3c164f0dd791dfa023ab02c12cb286a72e6e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:01:10 +0000 Subject: [PATCH 2059/2900] MIPS: Delete Wind River ppmc eval board support. This board has been EOL for many years now; lets not burden people doing build coverage and other tree wide work with working on essentially dead files. [ralf@linux-mips.org: Also remove arch/mips/include/asm/mach-wrppmc/war.h.] Signed-off-by: Paul Gortmaker Cc: linux-mips@linux-mips.org Cc: Paul Gortmaker Patchwork: http://patchwork.linux-mips.org/patch/5503/ Signed-off-by: Ralf Baechle --- arch/mips/Kbuild.platforms | 1 - arch/mips/Kconfig | 23 ---- arch/mips/configs/wrppmc_defconfig | 97 ------------- .../include/asm/mach-wrppmc/mach-gt64120.h | 83 ------------ arch/mips/include/asm/mach-wrppmc/war.h | 24 ---- arch/mips/pci/Makefile | 1 - arch/mips/pci/fixup-wrppmc.c | 37 ----- arch/mips/wrppmc/Makefile | 12 -- arch/mips/wrppmc/Platform | 7 - arch/mips/wrppmc/irq.c | 56 -------- arch/mips/wrppmc/pci.c | 52 ------- arch/mips/wrppmc/reset.c | 41 ------ arch/mips/wrppmc/serial.c | 80 ----------- arch/mips/wrppmc/setup.c | 128 ------------------ arch/mips/wrppmc/time.c | 39 ------ 15 files changed, 681 deletions(-) delete mode 100644 arch/mips/configs/wrppmc_defconfig delete mode 100644 arch/mips/include/asm/mach-wrppmc/mach-gt64120.h delete mode 100644 arch/mips/include/asm/mach-wrppmc/war.h delete mode 100644 arch/mips/pci/fixup-wrppmc.c delete mode 100644 arch/mips/wrppmc/Makefile delete mode 100644 arch/mips/wrppmc/Platform delete mode 100644 arch/mips/wrppmc/irq.c delete mode 100644 arch/mips/wrppmc/pci.c delete mode 100644 arch/mips/wrppmc/reset.c delete mode 100644 arch/mips/wrppmc/serial.c delete mode 100644 arch/mips/wrppmc/setup.c delete mode 100644 arch/mips/wrppmc/time.c diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 4b597d91a8d5..d9d81c219253 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -30,7 +30,6 @@ platforms += sibyte platforms += sni platforms += txx9 platforms += vr41xx -platforms += wrppmc # include the platform specific files include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms)) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 26779ccae116..f4cc348034b7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -712,29 +712,6 @@ config MIKROTIK_RB532 Support the Mikrotik(tm) RouterBoard 532 series, based on the IDT RC32434 SoC. -config WR_PPMC - bool "Wind River PPMC board" - select CEVT_R4K - select CSRC_R4K - select IRQ_CPU - select BOOT_ELF32 - select DMA_NONCOHERENT - select HW_HAS_PCI - select PCI_GT64XXX_PCI0 - select SWAP_IO_SPACE - select SYS_HAS_CPU_MIPS32_R1 - select SYS_HAS_CPU_MIPS32_R2 - select SYS_HAS_CPU_MIPS64_R1 - select SYS_HAS_CPU_NEVADA - select SYS_HAS_CPU_RM7000 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL - select SYS_SUPPORTS_BIG_ENDIAN - select SYS_SUPPORTS_LITTLE_ENDIAN - help - This enables support for the Wind River MIPS32 4KC PPMC evaluation - board, which is based on GT64120 bridge chip. - config CAVIUM_OCTEON_SOC bool "Cavium Networks Octeon SoC based boards" select CEVT_R4K diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig deleted file mode 100644 index 44a451be359e..000000000000 --- a/arch/mips/configs/wrppmc_defconfig +++ /dev/null @@ -1,97 +0,0 @@ -CONFIG_WR_PPMC=y -CONFIG_HZ_1000=y -CONFIG_EXPERIMENTAL=y -# CONFIG_SWAP is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EXPERT=y -CONFIG_KALLSYMS_EXTRA_PASS=y -# CONFIG_EPOLL is not set -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -CONFIG_PCI=y -CONFIG_HOTPLUG_PCI=y -CONFIG_BINFMT_MISC=y -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_MIGRATE=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_IP_PNP_RARP=y -CONFIG_IP_MROUTE=y -CONFIG_ARPD=y -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_TCP_MD5SIG=y -# CONFIG_IPV6 is not set -CONFIG_NETWORK_SECMARK=y -CONFIG_FW_LOADER=m -CONFIG_BLK_DEV_RAM=y -CONFIG_SGI_IOC4=m -CONFIG_NETDEVICES=y -CONFIG_PHYLIB=y -CONFIG_VITESSE_PHY=m -CONFIG_SMSC_PHY=m -CONFIG_NET_ETHERNET=y -CONFIG_NET_PCI=y -CONFIG_E100=y -CONFIG_QLA3XXX=m -CONFIG_CHELSIO_T3=m -CONFIG_NETXEN_NIC=m -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=1 -CONFIG_SERIAL_8250_RUNTIME_UARTS=1 -# CONFIG_HW_RANDOM is not set -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y -CONFIG_DLM=m -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttyS0,115200n8" -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_CBC=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_LRW=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_CAMELLIA=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRC_CCITT=y -CONFIG_CRC16=y -CONFIG_LIBCRC32C=y diff --git a/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h b/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h deleted file mode 100644 index 00fa3684ac98..000000000000 --- a/arch/mips/include/asm/mach-wrppmc/mach-gt64120.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This is a direct copy of the ev96100.h file, with a global - * search and replace. The numbers are the same. - * - * The reason I'm duplicating this is so that the 64120/96100 - * defines won't be confusing in the source code. - */ -#ifndef __ASM_MIPS_GT64120_H -#define __ASM_MIPS_GT64120_H - -/* - * This is the CPU physical memory map of PPMC Board: - * - * 0x00000000-0x03FFFFFF - 64MB SDRAM (SCS[0]#) - * 0x1C000000-0x1C000000 - LED (CS0) - * 0x1C800000-0x1C800007 - UART 16550 port (CS1) - * 0x1F000000-0x1F000000 - MailBox (CS3) - * 0x1FC00000-0x20000000 - 4MB Flash (BOOT CS) - */ - -#define WRPPMC_SDRAM_SCS0_BASE 0x00000000 -#define WRPPMC_SDRAM_SCS0_SIZE 0x04000000 - -#define WRPPMC_UART16550_BASE 0x1C800000 -#define WRPPMC_UART16550_CLOCK 3686400 /* 3.68MHZ */ - -#define WRPPMC_LED_BASE 0x1C000000 -#define WRPPMC_MBOX_BASE 0x1F000000 - -#define WRPPMC_BOOTROM_BASE 0x1FC00000 -#define WRPPMC_BOOTROM_SIZE 0x00400000 /* 4M Flash */ - -#define WRPPMC_MIPS_TIMER_IRQ 7 /* MIPS compare/count timer interrupt */ -#define WRPPMC_UART16550_IRQ 6 -#define WRPPMC_PCI_INTA_IRQ 3 - -/* - * PCI Bus I/O and Memory resources allocation - * - * NOTE: We only have PCI_0 hose interface - */ -#define GT_PCI_MEM_BASE 0x13000000UL -#define GT_PCI_MEM_SIZE 0x02000000UL -#define GT_PCI_IO_BASE 0x11000000UL -#define GT_PCI_IO_SIZE 0x02000000UL - -/* - * PCI interrupts will come in on either the INTA or INTD interrupt lines, - * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our - * boards, they all either come in on IntD or they all come in on IntA, they - * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the - * "requested" interrupt numbers and go through the list whenever we get an - * IntA/D. - * - * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and - * INTD is 11. - */ -#define GT_TIMER 4 -#define GT_INTA 2 -#define GT_INTD 5 - -#ifndef __ASSEMBLY__ - -/* - * GT64120 internal register space base address - */ -extern unsigned long gt64120_base; - -#define GT64120_BASE (gt64120_base) - -/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */ -#undef WRPPMC_EARLY_DEBUG - -#ifdef WRPPMC_EARLY_DEBUG -extern void wrppmc_led_on(int mask); -extern void wrppmc_led_off(int mask); -extern void wrppmc_early_printk(const char *fmt, ...); -#else -#define wrppmc_early_printk(fmt, ...) do {} while (0) -#endif /* WRPPMC_EARLY_DEBUG */ - -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_MIPS_GT64120_H */ diff --git a/arch/mips/include/asm/mach-wrppmc/war.h b/arch/mips/include/asm/mach-wrppmc/war.h deleted file mode 100644 index e86084c0bd6b..000000000000 --- a/arch/mips/include/asm/mach-wrppmc/war.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2002, 2004, 2007 by Ralf Baechle - */ -#ifndef __ASM_MIPS_MACH_WRPPMC_WAR_H -#define __ASM_MIPS_MACH_WRPPMC_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 1 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_WRPPMC_WAR_H */ diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index fa3bcd233138..b56fbc06c60e 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-rbtx4938.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o -obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o obj-$(CONFIG_CAVIUM_OCTEON_SOC) += pci-octeon.o pcie-octeon.o obj-$(CONFIG_CPU_XLR) += pci-xlr.o diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c deleted file mode 100644 index 29737edd121f..000000000000 --- a/arch/mips/pci/fixup-wrppmc.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * fixup-wrppmc.c: PPMC board specific PCI fixup - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com) - */ -#include -#include -#include - -/* PCI interrupt pins */ -#define PCI_INTA 1 -#define PCI_INTB 2 -#define PCI_INTC 3 -#define PCI_INTD 4 - -#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */ - -static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = { - /* 0 INTA INTB INTC INTD */ - [0] = {0, 0, 0, 0, 0}, /* Slot 0: GT64120 PCI bridge */ - [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0}, -}; - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - return pci_irq_tab[slot][pin]; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} diff --git a/arch/mips/wrppmc/Makefile b/arch/mips/wrppmc/Makefile deleted file mode 100644 index 307cc6920ce6..000000000000 --- a/arch/mips/wrppmc/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright 2006 Wind River System, Inc. -# Author: Rongkai.Zhan -# -# Makefile for the Wind River MIPS 4Kc PPMC Eval Board -# - -obj-y += irq.o pci.o reset.o serial.o setup.o time.o diff --git a/arch/mips/wrppmc/Platform b/arch/mips/wrppmc/Platform deleted file mode 100644 index dc78b25b95fe..000000000000 --- a/arch/mips/wrppmc/Platform +++ /dev/null @@ -1,7 +0,0 @@ -# -# Wind River PPMC Board (4KC + GT64120) -# -platform-$(CONFIG_WR_PPMC) += wrppmc/ -cflags-$(CONFIG_WR_PPMC) += \ - -I$(srctree)/arch/mips/include/asm/mach-wrppmc -load-$(CONFIG_WR_PPMC) += 0xffffffff80100000 diff --git a/arch/mips/wrppmc/irq.c b/arch/mips/wrppmc/irq.c deleted file mode 100644 index f237bf4d5c3a..000000000000 --- a/arch/mips/wrppmc/irq.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * irq.c: GT64120 Interrupt Controller - * - * Copyright (C) 2006, Wind River System Inc. - * Author: Rongkai.Zhan, - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include - -#include -#include -#include - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP7) - do_IRQ(WRPPMC_MIPS_TIMER_IRQ); /* CPU Compare/Count internal timer */ - else if (pending & STATUSF_IP6) - do_IRQ(WRPPMC_UART16550_IRQ); /* UART 16550 port */ - else if (pending & STATUSF_IP3) - do_IRQ(WRPPMC_PCI_INTA_IRQ); /* PCI INT_A */ - else - spurious_interrupt(); -} - -/** - * Initialize GT64120 Interrupt Controller - */ -void gt64120_init_pic(void) -{ - /* clear CPU Interrupt Cause Registers */ - GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); - GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); - - /* Disable all interrupts from GT64120 bridge chip */ - GT_WRITE(GT_INTRMASK_OFS, 0x00); - GT_WRITE(GT_HINTRMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); - GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); -} - -void __init arch_init_irq(void) -{ - /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ - mips_cpu_irq_init(); - - gt64120_init_pic(); -} diff --git a/arch/mips/wrppmc/pci.c b/arch/mips/wrppmc/pci.c deleted file mode 100644 index 8b8a0e1a40ca..000000000000 --- a/arch/mips/wrppmc/pci.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * pci.c: GT64120 PCI support. - * - * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include - -#include - -extern struct pci_ops gt64xxx_pci0_ops; - -static struct resource pci0_io_resource = { - .name = "pci_0 io", - .start = GT_PCI_IO_BASE, - .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO, -}; - -static struct resource pci0_mem_resource = { - .name = "pci_0 memory", - .start = GT_PCI_MEM_BASE, - .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller hose_0 = { - .pci_ops = >64xxx_pci0_ops, - .io_resource = &pci0_io_resource, - .mem_resource = &pci0_mem_resource, -}; - -static int __init gt64120_pci_init(void) -{ - (void) GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ - (void) GT_READ(GT_PCI0_BARE_OFS); - - /* reset the whole PCI I/O space range */ - ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; - - register_pci_controller(&hose_0); - return 0; -} - -arch_initcall(gt64120_pci_init); diff --git a/arch/mips/wrppmc/reset.c b/arch/mips/wrppmc/reset.c deleted file mode 100644 index 80beb188ed47..000000000000 --- a/arch/mips/wrppmc/reset.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1997 Ralf Baechle - */ -#include -#include - -#include -#include -#include -#include - -void wrppmc_machine_restart(char *command) -{ - /* - * Ouch, we're still alive ... This time we take the silver bullet ... - * ... and find that we leave the hardware in a state in which the - * kernel in the flush locks up somewhen during of after the PCI - * detection stuff. - */ - local_irq_disable(); - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void wrppmc_machine_halt(void) -{ - local_irq_disable(); - - printk(KERN_NOTICE "You can safely turn off the power\n"); - while (1) { - if (cpu_wait) - cpu_wait(); - } -} diff --git a/arch/mips/wrppmc/serial.c b/arch/mips/wrppmc/serial.c deleted file mode 100644 index 83f0f7d05187..000000000000 --- a/arch/mips/wrppmc/serial.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Registration of WRPPMC UART platform device. - * - * Copyright (C) 2007 Yoichi Yuasa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include - -#include - -static struct resource wrppmc_uart_resource[] __initdata = { - { - .start = WRPPMC_UART16550_BASE, - .end = WRPPMC_UART16550_BASE + 7, - .flags = IORESOURCE_MEM, - }, - { - .start = WRPPMC_UART16550_IRQ, - .end = WRPPMC_UART16550_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct plat_serial8250_port wrppmc_serial8250_port[] = { - { - .irq = WRPPMC_UART16550_IRQ, - .uartclk = WRPPMC_UART16550_CLOCK, - .iotype = UPIO_MEM, - .flags = UPF_IOREMAP | UPF_SKIP_TEST, - .mapbase = WRPPMC_UART16550_BASE, - }, - {}, -}; - -static __init int wrppmc_uart_add(void) -{ - struct platform_device *pdev; - int retval; - - pdev = platform_device_alloc("serial8250", -1); - if (!pdev) - return -ENOMEM; - - pdev->id = PLAT8250_DEV_PLATFORM; - pdev->dev.platform_data = wrppmc_serial8250_port; - - retval = platform_device_add_resources(pdev, wrppmc_uart_resource, - ARRAY_SIZE(wrppmc_uart_resource)); - if (retval) - goto err_free_device; - - retval = platform_device_add(pdev); - if (retval) - goto err_free_device; - - return 0; - -err_free_device: - platform_device_put(pdev); - - return retval; -} -device_initcall(wrppmc_uart_add); diff --git a/arch/mips/wrppmc/setup.c b/arch/mips/wrppmc/setup.c deleted file mode 100644 index ca65c84031a7..000000000000 --- a/arch/mips/wrppmc/setup.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * setup.c: Setup pointers to hardware dependent routines. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -unsigned long gt64120_base = KSEG1ADDR(0x14000000); - -#ifdef WRPPMC_EARLY_DEBUG - -static volatile unsigned char * wrppmc_led = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); - -/* - * PPMC LED control register: - * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) - * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) - * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) - */ -void wrppmc_led_on(int mask) -{ - unsigned char value = *wrppmc_led; - - value &= (0xF8 | mask); - *wrppmc_led = value; -} - -/* If mask = 0, turn off all LEDs */ -void wrppmc_led_off(int mask) -{ - unsigned char value = *wrppmc_led; - - value |= (0x7 & mask); - *wrppmc_led = value; -} - -/* - * We assume that bootloader has initialized UART16550 correctly - */ -void __init wrppmc_early_putc(char ch) -{ - static volatile unsigned char *wrppmc_uart = \ - (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); - unsigned char value; - - /* Wait until Transmit-Holding-Register is empty */ - while (1) { - value = *(wrppmc_uart + 5); - if (value & 0x20) - break; - } - - *wrppmc_uart = ch; -} - -void __init wrppmc_early_printk(const char *fmt, ...) -{ - static char pbuf[256] = {'\0', }; - char *ch = pbuf; - va_list args; - unsigned int i; - - memset(pbuf, 0, 256); - va_start(args, fmt); - i = vsprintf(pbuf, fmt, args); - va_end(args); - - /* Print the string */ - while (*ch != '\0') { - wrppmc_early_putc(*ch); - /* if print '\n', also print '\r' */ - if (*ch++ == '\n') - wrppmc_early_putc('\r'); - } -} -#endif /* WRPPMC_EARLY_DEBUG */ - -void __init prom_free_prom_memory(void) -{ -} - -void __init plat_mem_setup(void) -{ - extern void wrppmc_machine_restart(char *command); - extern void wrppmc_machine_halt(void); - - _machine_restart = wrppmc_machine_restart; - _machine_halt = wrppmc_machine_halt; - pm_power_off = wrppmc_machine_halt; - - /* This makes the operations of 'in/out[bwl]' to the - * physical address ( < KSEG0) can work via KSEG1 - */ - set_io_port_base(KSEG1); -} - -const char *get_system_type(void) -{ - return "Wind River PPMC (GT64120)"; -} - -/* - * Initializes basic routines and structures pointers, memory size (as - * given by the bios and saves the command line. - */ -void __init prom_init(void) -{ - add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); - add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); - - wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", - WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); -} diff --git a/arch/mips/wrppmc/time.c b/arch/mips/wrppmc/time.c deleted file mode 100644 index 668dbd5f12c5..000000000000 --- a/arch/mips/wrppmc/time.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * time.c: MIPS CPU Count/Compare timer hookup - * - * Author: Mark.Zhan, - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) - * Copyright (C) 2006, Wind River System Inc. - */ -#include -#include -#include - -#include -#include - -#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ - -/* - * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect - * - * NOTE: We disable all GT64120 timers, and use MIPS processor internal - * timer as the source of kernel clock tick. - */ -void __init plat_time_init(void) -{ - /* Disable GT64120 timers */ - GT_WRITE(GT_TC_CONTROL_OFS, 0x00); - GT_WRITE(GT_TC0_OFS, 0x00); - GT_WRITE(GT_TC1_OFS, 0x00); - GT_WRITE(GT_TC2_OFS, 0x00); - GT_WRITE(GT_TC3_OFS, 0x00); - - /* Use MIPS compare/count internal timer */ - mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; -} -- GitLab From ae8de61c726f4f2c4b1b4d8263c9c71b82503e0d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:39 +0000 Subject: [PATCH 2060/2900] MIPS: BCM63XX: select BOOT_RAW Enabling BOOT_RAW is mandatory to get a binary image (objcopy from ELF to binary) to work. This does not affect the ELF kernels which are used by CFE on BCM63XX DSL platforms, but is going to be necessary to support BCM63XX on Cable Modem chips such as BCM3368. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/5500/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f4cc348034b7..ba63cdbd13fe 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -121,6 +121,7 @@ config BCM47XX config BCM63XX bool "Broadcom BCM63XX based boards" + select BOOT_RAW select CEVT_R4K select CSRC_R4K select DMA_NONCOHERENT -- GitLab From 7b9334215f53135fb9cbdf0b44833cbc8e7d57b2 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:40 +0000 Subject: [PATCH 2061/2900] MIPS: BCM63XX: add support for BCM3368 Cable Modem The Broadcom BCM3368 Cable Modem SoC is extremely similar to the existing BCM63xx DSL SoCs, in particular BCM6358, therefore little effort in the existing code base is required to get it supported. This patch adds support for the following on-chip peripherals: - two UARTS - GPIO - Ethernet - SPI - PCI - NOR Flash The most noticeable difference with 3368 is that it has its peripheral register at 0xfff8_0000 we check that separately in ioremap.h. Since 3368 is identical to 6358 for its clock and reset bits, we use them verbatim. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/5499/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/Kconfig | 4 + arch/mips/bcm63xx/clk.c | 18 +-- arch/mips/bcm63xx/cpu.c | 28 ++++- arch/mips/bcm63xx/dev-flash.c | 1 + arch/mips/bcm63xx/dev-spi.c | 6 +- arch/mips/bcm63xx/dev-uart.c | 3 +- arch/mips/bcm63xx/irq.c | 19 +++ arch/mips/bcm63xx/prom.c | 4 +- arch/mips/bcm63xx/reset.c | 29 ++++- arch/mips/bcm63xx/setup.c | 3 + .../include/asm/mach-bcm63xx/bcm63xx_cpu.h | 110 ++++++++++++++++++ .../include/asm/mach-bcm63xx/bcm63xx_gpio.h | 1 + .../include/asm/mach-bcm63xx/bcm63xx_regs.h | 45 ++++++- arch/mips/include/asm/mach-bcm63xx/ioremap.h | 4 + arch/mips/pci/pci-bcm63xx.c | 3 +- 15 files changed, 259 insertions(+), 19 deletions(-) diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index 5639662fd503..afe52d4ed3b9 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -1,6 +1,10 @@ menu "CPU support" depends on BCM63XX +config BCM63XX_CPU_3368 + bool "support 3368 CPU" + select HW_HAS_PCI + config BCM63XX_CPU_6328 bool "support 6328 CPU" select HW_HAS_PCI diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index c726a97fc798..fda2690a8ef1 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -84,7 +84,7 @@ static void enetx_set(struct clk *clk, int enable) else clk_disable_unlocked(&clk_enet_misc); - if (BCMCPU_IS_6358()) { + if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { u32 mask; if (clk->id == 0) @@ -110,9 +110,8 @@ static struct clk clk_enet1 = { */ static void ephy_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6358()) - return; - bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable); + if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) + bcm_hwclock_set(CKCTL_6358_EPHY_EN, enable); } @@ -155,9 +154,10 @@ static struct clk clk_enetsw = { */ static void pcm_set(struct clk *clk, int enable) { - if (!BCMCPU_IS_6358()) - return; - bcm_hwclock_set(CKCTL_6358_PCM_EN, enable); + if (BCMCPU_IS_3368()) + bcm_hwclock_set(CKCTL_3368_PCM_EN, enable); + if (BCMCPU_IS_6358()) + bcm_hwclock_set(CKCTL_6358_PCM_EN, enable); } static struct clk clk_pcm = { @@ -211,7 +211,7 @@ static void spi_set(struct clk *clk, int enable) mask = CKCTL_6338_SPI_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_SPI_EN; - else if (BCMCPU_IS_6358()) + else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) mask = CKCTL_6358_SPI_EN; else if (BCMCPU_IS_6362()) mask = CKCTL_6362_SPI_EN; @@ -338,7 +338,7 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_xtm; if (!strcmp(id, "periph")) return &clk_periph; - if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) + if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm")) return &clk_pcm; if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec")) return &clk_ipsec; diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 79fe32df5e96..7e17374a9ae8 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -29,6 +29,14 @@ static u8 bcm63xx_cpu_rev; static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_memory_size; +static const unsigned long bcm3368_regs_base[] = { + __GEN_CPU_REGS_TABLE(3368) +}; + +static const int bcm3368_irqs[] = { + __GEN_CPU_IRQ_TABLE(3368) +}; + static const unsigned long bcm6328_regs_base[] = { __GEN_CPU_REGS_TABLE(6328) }; @@ -116,6 +124,9 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + return 300000000; + case BCM6328_CPU_ID: { unsigned int tmp, mips_pll_fcvo; @@ -266,7 +277,7 @@ static unsigned int detect_memory_size(void) banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; } - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) { val = bcm_memc_readl(MEMC_CFG_REG); rows = (val & MEMC_CFG_ROW_MASK) >> MEMC_CFG_ROW_SHIFT; cols = (val & MEMC_CFG_COL_MASK) >> MEMC_CFG_COL_SHIFT; @@ -302,10 +313,17 @@ void __init bcm63xx_cpu_init(void) chipid_reg = BCM_6345_PERF_BASE; break; case CPU_BMIPS4350: - if ((read_c0_prid() & 0xf0) == 0x10) + switch ((read_c0_prid() & 0xff)) { + case 0x04: + chipid_reg = BCM_3368_PERF_BASE; + break; + case 0x10: chipid_reg = BCM_6345_PERF_BASE; - else + break; + default: chipid_reg = BCM_6368_PERF_BASE; + break; + } break; } @@ -322,6 +340,10 @@ void __init bcm63xx_cpu_init(void) bcm63xx_cpu_rev = (tmp & REV_REVID_MASK) >> REV_REVID_SHIFT; switch (bcm63xx_cpu_id) { + case BCM3368_CPU_ID: + bcm63xx_regs_base = bcm3368_regs_base; + bcm63xx_irqs = bcm3368_irqs; + break; case BCM6328_CPU_ID: bcm63xx_regs_base = bcm6328_regs_base; bcm63xx_irqs = bcm6328_irqs; diff --git a/arch/mips/bcm63xx/dev-flash.c b/arch/mips/bcm63xx/dev-flash.c index 588d1ec622e4..172dd8397178 100644 --- a/arch/mips/bcm63xx/dev-flash.c +++ b/arch/mips/bcm63xx/dev-flash.c @@ -71,6 +71,7 @@ static int __init bcm63xx_detect_flash_type(void) case BCM6348_CPU_ID: /* no way to auto detect so assume parallel */ return BCM63XX_FLASH_TYPE_PARALLEL; + case BCM3368_CPU_ID: case BCM6358_CPU_ID: val = bcm_gpio_readl(GPIO_STRAPBUS_REG); if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL) diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c index 3065bb61820d..d12daed749bc 100644 --- a/arch/mips/bcm63xx/dev-spi.c +++ b/arch/mips/bcm63xx/dev-spi.c @@ -37,7 +37,8 @@ static __init void bcm63xx_spi_regs_init(void) { if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) bcm63xx_regs_spi = bcm6348_regs_spi; - if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || + BCMCPU_IS_6362() || BCMCPU_IS_6368()) bcm63xx_regs_spi = bcm6358_regs_spi; } #else @@ -87,7 +88,8 @@ int __init bcm63xx_spi_register(void) spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH; } - if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) { + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() || + BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; diff --git a/arch/mips/bcm63xx/dev-uart.c b/arch/mips/bcm63xx/dev-uart.c index d6e42c608325..3bc7f3bfc9ad 100644 --- a/arch/mips/bcm63xx/dev-uart.c +++ b/arch/mips/bcm63xx/dev-uart.c @@ -54,7 +54,8 @@ int __init bcm63xx_uart_register(unsigned int id) if (id >= ARRAY_SIZE(bcm63xx_uart_devices)) return -ENODEV; - if (id == 1 && (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())) + if (id == 1 && (!BCMCPU_IS_3368() && !BCMCPU_IS_6358() && + !BCMCPU_IS_6368())) return -ENODEV; if (id == 0) { diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index d744606e19e9..1525f8a3841b 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; #ifndef BCMCPU_RUNTIME_DETECT +#ifdef CONFIG_BCM63XX_CPU_3368 +#define irq_stat_reg PERF_IRQSTAT_3368_REG +#define irq_mask_reg PERF_IRQMASK_3368_REG +#define irq_bits 32 +#define is_ext_irq_cascaded 0 +#define ext_irq_start 0 +#define ext_irq_end 0 +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_3368 +#define ext_irq_cfg_reg2 0 +#endif #ifdef CONFIG_BCM63XX_CPU_6328 #define irq_stat_reg PERF_IRQSTAT_6328_REG #define irq_mask_reg PERF_IRQMASK_6328_REG @@ -140,6 +151,13 @@ static void bcm63xx_init_irq(void) irq_mask_addr = bcm63xx_regset_address(RSET_PERF); switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_3368_REG; + irq_mask_addr += PERF_IRQMASK_3368_REG; + irq_bits = 32; + ext_irq_count = 4; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368; + break; case BCM6328_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6328_REG; irq_mask_addr += PERF_IRQMASK_6328_REG; @@ -479,6 +497,7 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); break; + case BCM3368_CPU_ID: case BCM6328_CPU_ID: case BCM6338_CPU_ID: case BCM6345_CPU_ID: diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index fd698087fbfd..f3ff28f4c258 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -26,7 +26,9 @@ void __init prom_init(void) bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); /* disable all hardware blocks clock for now */ - if (BCMCPU_IS_6328()) + if (BCMCPU_IS_3368()) + mask = CKCTL_3368_ALL_SAFE_EN; + else if (BCMCPU_IS_6328()) mask = CKCTL_6328_ALL_SAFE_EN; else if (BCMCPU_IS_6338()) mask = CKCTL_6338_ALL_SAFE_EN; diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c index 317931c6cf58..acbeb1fe7c57 100644 --- a/arch/mips/bcm63xx/reset.c +++ b/arch/mips/bcm63xx/reset.c @@ -30,6 +30,19 @@ [BCM63XX_RESET_PCIE] = BCM## __cpu ##_RESET_PCIE, \ [BCM63XX_RESET_PCIE_EXT] = BCM## __cpu ##_RESET_PCIE_EXT, +#define BCM3368_RESET_SPI SOFTRESET_3368_SPI_MASK +#define BCM3368_RESET_ENET SOFTRESET_3368_ENET_MASK +#define BCM3368_RESET_USBH 0 +#define BCM3368_RESET_USBD SOFTRESET_3368_USBS_MASK +#define BCM3368_RESET_DSL 0 +#define BCM3368_RESET_SAR 0 +#define BCM3368_RESET_EPHY SOFTRESET_3368_EPHY_MASK +#define BCM3368_RESET_ENETSW 0 +#define BCM3368_RESET_PCM SOFTRESET_3368_PCM_MASK +#define BCM3368_RESET_MPI SOFTRESET_3368_MPI_MASK +#define BCM3368_RESET_PCIE 0 +#define BCM3368_RESET_PCIE_EXT 0 + #define BCM6328_RESET_SPI SOFTRESET_6328_SPI_MASK #define BCM6328_RESET_ENET 0 #define BCM6328_RESET_USBH SOFTRESET_6328_USBH_MASK @@ -117,6 +130,10 @@ /* * core reset bits */ +static const u32 bcm3368_reset_bits[] = { + __GEN_RESET_BITS_TABLE(3368) +}; + static const u32 bcm6328_reset_bits[] = { __GEN_RESET_BITS_TABLE(6328) }; @@ -146,7 +163,10 @@ static int reset_reg; static int __init bcm63xx_reset_bits_init(void) { - if (BCMCPU_IS_6328()) { + if (BCMCPU_IS_3368()) { + reset_reg = PERF_SOFTRESET_6358_REG; + bcm63xx_reset_bits = bcm3368_reset_bits; + } else if (BCMCPU_IS_6328()) { reset_reg = PERF_SOFTRESET_6328_REG; bcm63xx_reset_bits = bcm6328_reset_bits; } else if (BCMCPU_IS_6338()) { @@ -170,6 +190,13 @@ static int __init bcm63xx_reset_bits_init(void) } #else +#ifdef CONFIG_BCM63XX_CPU_3368 +static const u32 bcm63xx_reset_bits[] = { + __GEN_RESET_BITS_TABLE(3368) +}; +#define reset_reg PERF_SOFTRESET_6358_REG +#endif + #ifdef CONFIG_BCM63XX_CPU_6328 static const u32 bcm63xx_reset_bits[] = { __GEN_RESET_BITS_TABLE(6328) diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 24a24445db64..6660c7ddf87b 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void) /* mask and clear all external irq */ switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_3368; + break; case BCM6328_CPU_ID: perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328; break; diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 336228990808..9d3c08e4a7e4 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -9,6 +9,7 @@ * compile time if only one CPU support is enabled (idea stolen from * arm mach-types) */ +#define BCM3368_CPU_ID 0x3368 #define BCM6328_CPU_ID 0x6328 #define BCM6338_CPU_ID 0x6338 #define BCM6345_CPU_ID 0x6345 @@ -22,6 +23,19 @@ u16 __bcm63xx_get_cpu_id(void); u8 bcm63xx_get_cpu_rev(void); unsigned int bcm63xx_get_cpu_freq(void); +#ifdef CONFIG_BCM63XX_CPU_3368 +# ifdef bcm63xx_get_cpu_id +# undef bcm63xx_get_cpu_id +# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id() +# define BCMCPU_RUNTIME_DETECT +# else +# define bcm63xx_get_cpu_id() BCM3368_CPU_ID +# endif +# define BCMCPU_IS_3368() (bcm63xx_get_cpu_id() == BCM3368_CPU_ID) +#else +# define BCMCPU_IS_3368() (0) +#endif + #ifdef CONFIG_BCM63XX_CPU_6328 # ifdef bcm63xx_get_cpu_id # undef bcm63xx_get_cpu_id @@ -190,6 +204,53 @@ enum bcm63xx_regs_set { #define RSET_XTMDMAS_SIZE(chans) (16 * (chans)) #define RSET_RNG_SIZE 20 +/* + * 3368 register sets base address + */ +#define BCM_3368_DSL_LMEM_BASE (0xdeadbeef) +#define BCM_3368_PERF_BASE (0xfff8c000) +#define BCM_3368_TIMER_BASE (0xfff8c040) +#define BCM_3368_WDT_BASE (0xfff8c080) +#define BCM_3368_UART0_BASE (0xfff8c100) +#define BCM_3368_UART1_BASE (0xfff8c120) +#define BCM_3368_GPIO_BASE (0xfff8c080) +#define BCM_3368_SPI_BASE (0xfff8c800) +#define BCM_3368_HSSPI_BASE (0xdeadbeef) +#define BCM_3368_UDC0_BASE (0xdeadbeef) +#define BCM_3368_USBDMA_BASE (0xdeadbeef) +#define BCM_3368_OHCI0_BASE (0xdeadbeef) +#define BCM_3368_OHCI_PRIV_BASE (0xdeadbeef) +#define BCM_3368_USBH_PRIV_BASE (0xdeadbeef) +#define BCM_3368_USBD_BASE (0xdeadbeef) +#define BCM_3368_MPI_BASE (0xfff80000) +#define BCM_3368_PCMCIA_BASE (0xfff80054) +#define BCM_3368_PCIE_BASE (0xdeadbeef) +#define BCM_3368_SDRAM_REGS_BASE (0xdeadbeef) +#define BCM_3368_DSL_BASE (0xdeadbeef) +#define BCM_3368_UBUS_BASE (0xdeadbeef) +#define BCM_3368_ENET0_BASE (0xfff98000) +#define BCM_3368_ENET1_BASE (0xfff98800) +#define BCM_3368_ENETDMA_BASE (0xfff99800) +#define BCM_3368_ENETDMAC_BASE (0xfff99900) +#define BCM_3368_ENETDMAS_BASE (0xfff99a00) +#define BCM_3368_ENETSW_BASE (0xdeadbeef) +#define BCM_3368_EHCI0_BASE (0xdeadbeef) +#define BCM_3368_SDRAM_BASE (0xdeadbeef) +#define BCM_3368_MEMC_BASE (0xfff84000) +#define BCM_3368_DDR_BASE (0xdeadbeef) +#define BCM_3368_M2M_BASE (0xdeadbeef) +#define BCM_3368_ATM_BASE (0xdeadbeef) +#define BCM_3368_XTM_BASE (0xdeadbeef) +#define BCM_3368_XTMDMA_BASE (0xdeadbeef) +#define BCM_3368_XTMDMAC_BASE (0xdeadbeef) +#define BCM_3368_XTMDMAS_BASE (0xdeadbeef) +#define BCM_3368_PCM_BASE (0xfff9c200) +#define BCM_3368_PCMDMA_BASE (0xdeadbeef) +#define BCM_3368_PCMDMAC_BASE (0xdeadbeef) +#define BCM_3368_PCMDMAS_BASE (0xdeadbeef) +#define BCM_3368_RNG_BASE (0xdeadbeef) +#define BCM_3368_MISC_BASE (0xdeadbeef) + /* * 6328 register sets base address */ @@ -620,6 +681,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) #ifdef BCMCPU_RUNTIME_DETECT return bcm63xx_regs_base[set]; #else +#ifdef CONFIG_BCM63XX_CPU_3368 + __GEN_RSET(3368) +#endif #ifdef CONFIG_BCM63XX_CPU_6328 __GEN_RSET(6328) #endif @@ -686,6 +750,52 @@ enum bcm63xx_irq { IRQ_XTM_DMA0, }; +/* + * 3368 irqs + */ +#define BCM_3368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_3368_SPI_IRQ (IRQ_INTERNAL_BASE + 1) +#define BCM_3368_UART0_IRQ (IRQ_INTERNAL_BASE + 2) +#define BCM_3368_UART1_IRQ (IRQ_INTERNAL_BASE + 3) +#define BCM_3368_DSL_IRQ 0 +#define BCM_3368_UDC0_IRQ 0 +#define BCM_3368_OHCI0_IRQ 0 +#define BCM_3368_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) +#define BCM_3368_ENET1_IRQ (IRQ_INTERNAL_BASE + 6) +#define BCM_3368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_3368_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 15) +#define BCM_3368_ENET0_TXDMA_IRQ (IRQ_INTERNAL_BASE + 16) +#define BCM_3368_HSSPI_IRQ 0 +#define BCM_3368_EHCI0_IRQ 0 +#define BCM_3368_USBD_IRQ 0 +#define BCM_3368_USBD_RXDMA0_IRQ 0 +#define BCM_3368_USBD_TXDMA0_IRQ 0 +#define BCM_3368_USBD_RXDMA1_IRQ 0 +#define BCM_3368_USBD_TXDMA1_IRQ 0 +#define BCM_3368_USBD_RXDMA2_IRQ 0 +#define BCM_3368_USBD_TXDMA2_IRQ 0 +#define BCM_3368_ENET1_RXDMA_IRQ (IRQ_INTERNAL_BASE + 17) +#define BCM_3368_ENET1_TXDMA_IRQ (IRQ_INTERNAL_BASE + 18) +#define BCM_3368_PCI_IRQ (IRQ_INTERNAL_BASE + 31) +#define BCM_3368_PCMCIA_IRQ 0 +#define BCM_3368_ATM_IRQ 0 +#define BCM_3368_ENETSW_RXDMA0_IRQ 0 +#define BCM_3368_ENETSW_RXDMA1_IRQ 0 +#define BCM_3368_ENETSW_RXDMA2_IRQ 0 +#define BCM_3368_ENETSW_RXDMA3_IRQ 0 +#define BCM_3368_ENETSW_TXDMA0_IRQ 0 +#define BCM_3368_ENETSW_TXDMA1_IRQ 0 +#define BCM_3368_ENETSW_TXDMA2_IRQ 0 +#define BCM_3368_ENETSW_TXDMA3_IRQ 0 +#define BCM_3368_XTM_IRQ 0 +#define BCM_3368_XTM_DMA0_IRQ 0 + +#define BCM_3368_EXT_IRQ0 (IRQ_INTERNAL_BASE + 25) +#define BCM_3368_EXT_IRQ1 (IRQ_INTERNAL_BASE + 26) +#define BCM_3368_EXT_IRQ2 (IRQ_INTERNAL_BASE + 27) +#define BCM_3368_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28) + + /* * 6328 irqs */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h index 35baa1a60a64..565ff36a1119 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h @@ -11,6 +11,7 @@ static inline unsigned long bcm63xx_gpio_count(void) switch (bcm63xx_get_cpu_id()) { case BCM6328_CPU_ID: return 32; + case BCM3368_CPU_ID: case BCM6358_CPU_ID: return 40; case BCM6338_CPU_ID: diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 3203fe49b34d..654213746b32 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -15,6 +15,39 @@ /* Clock Control register */ #define PERF_CKCTL_REG 0x4 +#define CKCTL_3368_MAC_EN (1 << 3) +#define CKCTL_3368_TC_EN (1 << 5) +#define CKCTL_3368_US_TOP_EN (1 << 6) +#define CKCTL_3368_DS_TOP_EN (1 << 7) +#define CKCTL_3368_APM_EN (1 << 8) +#define CKCTL_3368_SPI_EN (1 << 9) +#define CKCTL_3368_USBS_EN (1 << 10) +#define CKCTL_3368_BMU_EN (1 << 11) +#define CKCTL_3368_PCM_EN (1 << 12) +#define CKCTL_3368_NTP_EN (1 << 13) +#define CKCTL_3368_ACP_B_EN (1 << 14) +#define CKCTL_3368_ACP_A_EN (1 << 15) +#define CKCTL_3368_EMUSB_EN (1 << 17) +#define CKCTL_3368_ENET0_EN (1 << 18) +#define CKCTL_3368_ENET1_EN (1 << 19) +#define CKCTL_3368_USBU_EN (1 << 20) +#define CKCTL_3368_EPHY_EN (1 << 21) + +#define CKCTL_3368_ALL_SAFE_EN (CKCTL_3368_MAC_EN | \ + CKCTL_3368_TC_EN | \ + CKCTL_3368_US_TOP_EN | \ + CKCTL_3368_DS_TOP_EN | \ + CKCTL_3368_APM_EN | \ + CKCTL_3368_SPI_EN | \ + CKCTL_3368_USBS_EN | \ + CKCTL_3368_BMU_EN | \ + CKCTL_3368_PCM_EN | \ + CKCTL_3368_NTP_EN | \ + CKCTL_3368_ACP_B_EN | \ + CKCTL_3368_ACP_A_EN | \ + CKCTL_3368_EMUSB_EN | \ + CKCTL_3368_USBU_EN) + #define CKCTL_6328_PHYMIPS_EN (1 << 0) #define CKCTL_6328_ADSL_QPROC_EN (1 << 1) #define CKCTL_6328_ADSL_AFE_EN (1 << 2) @@ -181,6 +214,7 @@ #define SYS_PLL_SOFT_RESET 0x1 /* Interrupt Mask register */ +#define PERF_IRQMASK_3368_REG 0xc #define PERF_IRQMASK_6328_REG 0x20 #define PERF_IRQMASK_6338_REG 0xc #define PERF_IRQMASK_6345_REG 0xc @@ -190,6 +224,7 @@ #define PERF_IRQMASK_6368_REG 0x20 /* Interrupt Status register */ +#define PERF_IRQSTAT_3368_REG 0x10 #define PERF_IRQSTAT_6328_REG 0x28 #define PERF_IRQSTAT_6338_REG 0x10 #define PERF_IRQSTAT_6345_REG 0x10 @@ -199,6 +234,7 @@ #define PERF_IRQSTAT_6368_REG 0x28 /* External Interrupt Configuration register */ +#define PERF_EXTIRQ_CFG_REG_3368 0x14 #define PERF_EXTIRQ_CFG_REG_6328 0x18 #define PERF_EXTIRQ_CFG_REG_6338 0x14 #define PERF_EXTIRQ_CFG_REG_6345 0x14 @@ -236,6 +272,13 @@ #define PERF_SOFTRESET_6362_REG 0x10 #define PERF_SOFTRESET_6368_REG 0x10 +#define SOFTRESET_3368_SPI_MASK (1 << 0) +#define SOFTRESET_3368_ENET_MASK (1 << 2) +#define SOFTRESET_3368_MPI_MASK (1 << 3) +#define SOFTRESET_3368_EPHY_MASK (1 << 6) +#define SOFTRESET_3368_USBS_MASK (1 << 11) +#define SOFTRESET_3368_PCM_MASK (1 << 13) + #define SOFTRESET_6328_SPI_MASK (1 << 0) #define SOFTRESET_6328_EPHY_MASK (1 << 1) #define SOFTRESET_6328_SAR_MASK (1 << 2) @@ -1293,7 +1336,7 @@ #define SPI_6348_RX_DATA 0x80 #define SPI_6348_RX_DATA_SIZE 0x3f -/* BCM 6358/6262/6368 SPI core */ +/* BCM 3368/6358/6262/6368 SPI core */ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ #define SPI_6358_MSG_CTL_WIDTH 16 #define SPI_6358_MSG_DATA 0x02 diff --git a/arch/mips/include/asm/mach-bcm63xx/ioremap.h b/arch/mips/include/asm/mach-bcm63xx/ioremap.h index 94e3011ba7df..ff15e3b14e7a 100644 --- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h +++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h @@ -11,6 +11,10 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size) static inline int is_bcm63xx_internal_registers(phys_t offset) { switch (bcm63xx_get_cpu_id()) { + case BCM3368_CPU_ID: + if (offset >= 0xfff80000) + return 1; + break; case BCM6338_CPU_ID: case BCM6345_CPU_ID: case BCM6348_CPU_ID: diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index 2eb954239bc5..151d9b5870bb 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -266,7 +266,7 @@ static int __init bcm63xx_register_pci(void) /* setup PCI to local bus access, used by PCI device to target * local RAM while bus mastering */ bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) val = MPI_SP0_REMAP_ENABLE_MASK; else val = 0; @@ -338,6 +338,7 @@ static int __init bcm63xx_pci_init(void) case BCM6328_CPU_ID: case BCM6362_CPU_ID: return bcm63xx_register_pcie(); + case BCM3368_CPU_ID: case BCM6348_CPU_ID: case BCM6358_CPU_ID: case BCM6368_CPU_ID: -- GitLab From d753601a2a5ff67bbc96ce6512a16305bfd293e7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:41 +0000 Subject: [PATCH 2062/2900] MIPS: BCM63XX: recognize Cable Modem firmware format Add the firmware header format which is used by Broadcom Cable Modem SoCs such as the BCM3368 SoC. We export the bcm_hcs firmware format structure because it is used by user-land tools to create firmware images for these SoCs and will later be used by a corresponding MTD parser. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/5496/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/boards/board_bcm963xx.c | 14 +++++++++++-- include/uapi/linux/Kbuild | 1 + include/uapi/linux/bcm933xx_hcs.h | 24 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 include/uapi/linux/bcm933xx_hcs.h diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index a9505c4867e8..46eabb9aff51 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -28,8 +28,12 @@ #include #include +#include + #define PFX "board_bcm963xx: " +#define HCS_OFFSET_128K 0x20000 + static struct board_info board; /* @@ -722,8 +726,9 @@ void __init board_prom_init(void) unsigned int i; u8 *boot_addr, *cfe; char cfe_version[32]; - char *board_name; + char *board_name = NULL; u32 val; + struct bcm_hcs *hcs; /* read base address of boot chip select (0) * 6328/6362 do not have MPI but boot from a fixed address @@ -747,7 +752,12 @@ void __init board_prom_init(void) bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET); - board_name = bcm63xx_nvram_get_name(); + if (BCMCPU_IS_3368()) { + hcs = (struct bcm_hcs *)boot_addr; + board_name = hcs->filename; + } else { + board_name = bcm63xx_nvram_get_name(); + } /* find board by name */ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { if (strncmp(board_name, bcm963xx_boards[i]->name, 16)) diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index ab5d4992e568..ba1c11ab0d11 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -62,6 +62,7 @@ header-y += auxvec.h header-y += ax25.h header-y += b1lli.h header-y += baycom.h +header-y += bcm933xx_hcs.h header-y += bfs_fs.h header-y += binfmts.h header-y += blkpg.h diff --git a/include/uapi/linux/bcm933xx_hcs.h b/include/uapi/linux/bcm933xx_hcs.h new file mode 100644 index 000000000000..d22821831549 --- /dev/null +++ b/include/uapi/linux/bcm933xx_hcs.h @@ -0,0 +1,24 @@ +/* + * Broadcom Cable Modem firmware format + */ + +#ifndef __BCM933XX_HCS_H +#define __BCM933XX_HCS_H + +#include + +struct bcm_hcs { + __u16 magic; + __u16 control; + __u16 rev_maj; + __u16 rev_min; + __u32 build_date; + __u32 filelen; + __u32 ldaddress; + char filename[64]; + __u16 hcs; + __u16 her_znaet_chto; + __u32 crc; +}; + +#endif /* __BCM933XX_HCS */ -- GitLab From 0680dc866d10806c85c40b54bbf8cf5be61206d1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:42 +0000 Subject: [PATCH 2063/2900] MIPS: BCM63XX: provide a MAC address for BCM3368 chips The BCM3368 SoC uses a NVRAM format which is not compatible with the one used by CFE, provide a default MAC address which is suitable for use and which is the default one also being used by the bootloader on these chips. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/5498/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/nvram.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c index a4b8864f9307..e652e578a679 100644 --- a/arch/mips/bcm63xx/nvram.c +++ b/arch/mips/bcm63xx/nvram.c @@ -42,6 +42,7 @@ void __init bcm63xx_nvram_init(void *addr) { unsigned int check_len; u32 crc, expected_crc; + u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff }; /* extract nvram data */ memcpy(&nvram, addr, sizeof(nvram)); @@ -62,6 +63,15 @@ void __init bcm63xx_nvram_init(void *addr) if (crc != expected_crc) pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n", expected_crc, crc); + + /* Cable modems have a different NVRAM which is embedded in the eCos + * firmware and not easily extractible, give at least a MAC address + * pool. + */ + if (BCMCPU_IS_3368()) { + memcpy(nvram.mac_addr_base, hcs_mac_addr, ETH_ALEN); + nvram.mac_addr_count = 2; + } } u8 *bcm63xx_nvram_get_name(void) -- GitLab From 0b35f0c59a601a88ec8c08ebab0b5a733c8de79f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:43 +0000 Subject: [PATCH 2064/2900] MIPS: BCM63XX: let board specify an external GPIO to reset PHY Some boards may need to reset their external PHY or switch they are attached to, add a hook for doing this along with providing custom linux/gpio.h flags for doing this. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5501/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++++ arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 46eabb9aff51..611a420dbfdd 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -883,5 +883,9 @@ int __init board_register_devices(void) platform_device_register(&bcm63xx_gpio_leds); + if (board.ephy_reset_gpio && board.ephy_reset_gpio_flags) + gpio_request_one(board.ephy_reset_gpio, + board.ephy_reset_gpio_flags, "ephy-reset"); + return 0; } diff --git a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h index 682bcf3b492a..5981fe0c3dfb 100644 --- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h +++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h @@ -45,6 +45,12 @@ struct board_info { /* GPIO LEDs */ struct gpio_led leds[5]; + + /* External PHY reset GPIO */ + unsigned int ephy_reset_gpio; + + /* External PHY reset GPIO flags from gpio.h */ + unsigned long ephy_reset_gpio_flags; }; #endif /* ! BOARD_BCM963XX_H_ */ -- GitLab From 450acb0b120ebcdc7d2ea6888b5302a6a5a12420 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 18 Jun 2013 16:55:44 +0000 Subject: [PATCH 2065/2900] MIPS: BCM63XX: add support for the Netgear CVG834G Add support for the Netgear CVG834G and enable the two UARTs, Ethernet on the first MAC, PCI and the two leds. Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5502/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/boards/board_bcm963xx.c | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 611a420dbfdd..d3304dc02aee 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -36,6 +36,38 @@ static struct board_info board; +/* + * known 3368 boards + */ +#ifdef CONFIG_BCM63XX_CPU_3368 +static struct board_info __initdata board_cvg834g = { + .name = "CVG834G_E15R3921", + .expected_cpu_id = 0x3368, + + .has_uart0 = 1, + .has_uart1 = 1, + + .has_enet0 = 1, + .has_pci = 1, + + .enet0 = { + .has_phy = 1, + .use_internal_phy = 1, + }, + + .leds = { + { + .name = "CVG834G:green:power", + .gpio = 37, + .default_trigger= "default-on", + }, + }, + + .ephy_reset_gpio = 36, + .ephy_reset_gpio_flags = GPIOF_INIT_HIGH, +}; +#endif + /* * known 6328 boards */ @@ -643,6 +675,9 @@ static struct board_info __initdata board_DWVS0 = { * all boards */ static const struct board_info __initconst *bcm963xx_boards[] = { +#ifdef CONFIG_BCM63XX_CPU_3368 + &board_cvg834g, +#endif #ifdef CONFIG_BCM63XX_CPU_6328 &board_96328avng, #endif -- GitLab From 5219343f83a033fe5dfcbb0274b5a78e8b2d0fee Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 19 Jun 2013 20:37:26 +0000 Subject: [PATCH 2066/2900] MIPS: OCTEON: Set proper UART clock in internal device trees. Following patch to use generic 8250 drivers will need proper clock information. So when using the internal device tree, populate the "clock-frequency" property with the correct value. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: Jamie Iles Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5515/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 389512e2abd6..7b746e7bf7a1 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -490,8 +490,15 @@ int __init octeon_prune_device_tree(void) if (alias_prop) { uart = fdt_path_offset(initial_boot_params, alias_prop); - if (uart_mask & (1 << i)) + if (uart_mask & (1 << i)) { + __be32 f; + + f = cpu_to_be32(octeon_get_io_clock_rate()); + fdt_setprop_inplace(initial_boot_params, + uart, "clock-frequency", + &f, sizeof(f)); continue; + } pr_debug("Deleting uart%d\n", i); fdt_nop_node(initial_boot_params, uart); fdt_nop_property(initial_boot_params, aliases, -- GitLab From d5f1af7ece96cf52e0b110c72210ac15c2f65438 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 19 Jun 2013 20:37:27 +0000 Subject: [PATCH 2067/2900] tty/8250_dw: Add support for OCTEON UARTS. A few differences needed by OCTEON: o These are DWC UARTS, but have USR at a different offset. o Internal SoC buses require reading back from registers to maintain write ordering. o 8250 on OCTEON appears with 64-bit wide registers, so when using readb/writeb in big endian mode we have to adjust the membase to hit the proper part of the register. o No UCV register, so we hard code some properties. Because OCTEON doesn't have a UCV register, I change where dw8250_setup_port(), which reads the UCV, is called by pushing it in to the OF and ACPI probe functions, and move unchanged dw8250_setup_port() earlier in the file. Signed-off-by: David Daney Acked-by: Greg Kroah-Hartman Cc: Arnd Bergmann Cc: Heikki Krogerus Cc: linux-mips@linux-mips.org Cc: Jamie Iles Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5516/ Acked-by: Arnd Bergmann Reviewed-by: Heikki Krogerus Signed-off-by: Ralf Baechle --- drivers/tty/serial/8250/8250_dw.c | 108 +++++++++++++++++++----------- 1 file changed, 69 insertions(+), 39 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index d07b6af3a937..76a8daadff47 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -29,6 +29,8 @@ #include #include +#include + #include "8250.h" /* Offsets for the DesignWare specific registers */ @@ -57,6 +59,7 @@ struct dw8250_data { int last_lcr; int line; struct clk *clk; + u8 usr_reg; }; static void dw8250_serial_out(struct uart_port *p, int offset, int value) @@ -77,6 +80,13 @@ static unsigned int dw8250_serial_in(struct uart_port *p, int offset) return readb(p->membase + offset); } +/* Read Back (rb) version to ensure register access ording. */ +static void dw8250_serial_out_rb(struct uart_port *p, int offset, int value) +{ + dw8250_serial_out(p, offset, value); + dw8250_serial_in(p, UART_LCR); +} + static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { struct dw8250_data *d = p->private_data; @@ -104,7 +114,7 @@ static int dw8250_handle_irq(struct uart_port *p) return 1; } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR and write the LCR again. */ - (void)p->serial_in(p, DW_UART_USR); + (void)p->serial_in(p, d->usr_reg); p->serial_out(p, UART_LCR, d->last_lcr); return 1; @@ -125,12 +135,60 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) pm_runtime_put_sync_suspend(port->dev); } -static int dw8250_probe_of(struct uart_port *p) +static void dw8250_setup_port(struct uart_8250_port *up) +{ + struct uart_port *p = &up->port; + u32 reg = readl(p->membase + DW_UART_UCV); + + /* + * If the Component Version Register returns zero, we know that + * ADDITIONAL_FEATURES are not enabled. No need to go any further. + */ + if (!reg) + return; + + dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", + (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); + + reg = readl(p->membase + DW_UART_CPR); + if (!reg) + return; + + /* Select the type based on fifo */ + if (reg & DW_UART_CPR_FIFO_MODE) { + p->type = PORT_16550A; + p->flags |= UPF_FIXED_TYPE; + p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); + up->tx_loadsz = p->fifosize; + up->capabilities = UART_CAP_FIFO; + } + + if (reg & DW_UART_CPR_AFCE_MODE) + up->capabilities |= UART_CAP_AFE; +} + +static int dw8250_probe_of(struct uart_port *p, + struct dw8250_data *data) { struct device_node *np = p->dev->of_node; u32 val; - - if (!of_property_read_u32(np, "reg-io-width", &val)) { + bool has_ucv = true; + + if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) { +#ifdef __BIG_ENDIAN + /* + * Low order bits of these 64-bit registers, when + * accessed as a byte, are 7 bytes further down in the + * address space in big endian mode. + */ + p->membase += 7; +#endif + p->serial_out = dw8250_serial_out_rb; + p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; + p->type = PORT_OCTEON; + data->usr_reg = 0x27; + has_ucv = false; + } else if (!of_property_read_u32(np, "reg-io-width", &val)) { switch (val) { case 1: break; @@ -144,6 +202,8 @@ static int dw8250_probe_of(struct uart_port *p) return -EINVAL; } } + if (has_ucv) + dw8250_setup_port(container_of(p, struct uart_8250_port, port)); if (!of_property_read_u32(np, "reg-shift", &val)) p->regshift = val; @@ -168,6 +228,8 @@ static int dw8250_probe_acpi(struct uart_8250_port *up) const struct acpi_device_id *id; struct uart_port *p = &up->port; + dw8250_setup_port(up); + id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev); if (!id) return -ENODEV; @@ -196,38 +258,6 @@ static inline int dw8250_probe_acpi(struct uart_8250_port *up) } #endif /* CONFIG_ACPI */ -static void dw8250_setup_port(struct uart_8250_port *up) -{ - struct uart_port *p = &up->port; - u32 reg = readl(p->membase + DW_UART_UCV); - - /* - * If the Component Version Register returns zero, we know that - * ADDITIONAL_FEATURES are not enabled. No need to go any further. - */ - if (!reg) - return; - - dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n", - (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - - reg = readl(p->membase + DW_UART_CPR); - if (!reg) - return; - - /* Select the type based on fifo */ - if (reg & DW_UART_CPR_FIFO_MODE) { - p->type = PORT_16550A; - p->flags |= UPF_FIXED_TYPE; - p->fifosize = DW_UART_CPR_FIFO_SIZE(reg); - up->tx_loadsz = p->fifosize; - up->capabilities = UART_CAP_FIFO; - } - - if (reg & DW_UART_CPR_AFCE_MODE) - up->capabilities |= UART_CAP_AFE; -} - static int dw8250_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; @@ -259,6 +289,7 @@ static int dw8250_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + data->usr_reg = DW_UART_USR; data->clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(data->clk)) { clk_prepare_enable(data->clk); @@ -270,10 +301,8 @@ static int dw8250_probe(struct platform_device *pdev) uart.port.serial_out = dw8250_serial_out; uart.port.private_data = data; - dw8250_setup_port(&uart); - if (pdev->dev.of_node) { - err = dw8250_probe_of(&uart.port); + err = dw8250_probe_of(&uart.port, data); if (err) return err; } else if (ACPI_HANDLE(&pdev->dev)) { @@ -362,6 +391,7 @@ static const struct dev_pm_ops dw8250_pm_ops = { static const struct of_device_id dw8250_of_match[] = { { .compatible = "snps,dw-apb-uart" }, + { .compatible = "cavium,octeon-3860-uart" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dw8250_of_match); -- GitLab From fde179901e2ebe55ebbbd4c635e1fff322640f7d Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 19 Jun 2013 20:37:28 +0000 Subject: [PATCH 2068/2900] MIPS: OCTEON: Remove custom serial setup code. We will use 8250_dw instead. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: Jamie Iles Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5517/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/Makefile | 2 +- arch/mips/cavium-octeon/serial.c | 109 ------------------------------- 2 files changed, 1 insertion(+), 110 deletions(-) delete mode 100644 arch/mips/cavium-octeon/serial.c diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 3595affb9772..b703583779fb 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -12,7 +12,7 @@ CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt -obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o +obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o obj-y += executive/ diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c deleted file mode 100644 index f393f65f3923..000000000000 --- a/arch/mips/cavium-octeon/serial.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2004-2007 Cavium Networks - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#define DEBUG_UART 1 - -unsigned int octeon_serial_in(struct uart_port *up, int offset) -{ - int rv = cvmx_read_csr((uint64_t)(up->membase + (offset << 3))); - if (offset == UART_IIR && (rv & 0xf) == 7) { - /* Busy interrupt, read the USR (39) and try again. */ - cvmx_read_csr((uint64_t)(up->membase + (39 << 3))); - rv = cvmx_read_csr((uint64_t)(up->membase + (offset << 3))); - } - return rv; -} - -void octeon_serial_out(struct uart_port *up, int offset, int value) -{ - /* - * If bits 6 or 7 of the OCTEON UART's LCR are set, it quits - * working. - */ - if (offset == UART_LCR) - value &= 0x9f; - cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); -} - -static int octeon_serial_probe(struct platform_device *pdev) -{ - int irq, res; - struct resource *res_mem; - struct uart_8250_port up; - - /* All adaptors have an irq. */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - memset(&up, 0, sizeof(up)); - - up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; - up.port.type = PORT_OCTEON; - up.port.iotype = UPIO_MEM; - up.port.regshift = 3; - up.port.dev = &pdev->dev; - - if (octeon_is_simulation()) - /* Make simulator output fast*/ - up.port.uartclk = 115200 * 16; - else - up.port.uartclk = octeon_get_io_clock_rate(); - - up.port.serial_in = octeon_serial_in; - up.port.serial_out = octeon_serial_out; - up.port.irq = irq; - - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res_mem == NULL) { - dev_err(&pdev->dev, "found no memory resource\n"); - return -ENXIO; - } - up.port.mapbase = res_mem->start; - up.port.membase = ioremap(res_mem->start, resource_size(res_mem)); - - res = serial8250_register_8250_port(&up); - - return res >= 0 ? 0 : res; -} - -static struct of_device_id octeon_serial_match[] = { - { - .compatible = "cavium,octeon-3860-uart", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, octeon_serial_match); - -static struct platform_driver octeon_serial_driver = { - .probe = octeon_serial_probe, - .driver = { - .owner = THIS_MODULE, - .name = "octeon_serial", - .of_match_table = octeon_serial_match, - }, -}; - -static int __init octeon_serial_init(void) -{ - return platform_driver_register(&octeon_serial_driver); -} -late_initcall(octeon_serial_init); -- GitLab From 1afb49d0e6429ba3997a3dfccb281bc473c4543e Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 19 Jun 2013 20:37:29 +0000 Subject: [PATCH 2069/2900] MIPS: Update cavium_octeon_defconfig The serial port changes make it advisable to enable the proper UART drivers. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: Jamie Iles Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linux-serial@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5518/ Signed-off-by: Ralf Baechle --- arch/mips/configs/cavium_octeon_defconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig index 1888e5f4d598..dace58268ce1 100644 --- a/arch/mips/configs/cavium_octeon_defconfig +++ b/arch/mips/configs/cavium_octeon_defconfig @@ -1,13 +1,11 @@ CONFIG_CAVIUM_OCTEON_SOC=y CONFIG_CAVIUM_CN63XXP1=y CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2 -CONFIG_SPARSEMEM_MANUAL=y CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_HZ_100=y CONFIG_PREEMPT=y -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y @@ -50,7 +48,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FW_LOADER is not set CONFIG_MTD=y # CONFIG_MTD_OF_PARTS is not set -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_AMDSTD=y @@ -114,6 +111,7 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=2 CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_DW=y # CONFIG_HW_RANDOM is not set CONFIG_I2C=y CONFIG_I2C_OCTEON=y -- GitLab From a7543d6003bcd73b57d5244ce78cfe9462755f90 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Jun 2013 12:57:54 +0200 Subject: [PATCH 2070/2900] MIPS: Sibyte: Remove duplicate but harmless line from Platform file. Signed-off-by: Ralf Baechle --- arch/mips/sibyte/Platform | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform index d03a07516f83..af9ee6afa31a 100644 --- a/arch/mips/sibyte/Platform +++ b/arch/mips/sibyte/Platform @@ -13,7 +13,6 @@ cflags-$(CONFIG_SIBYTE_BCM112X) += \ -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -platform-$(CONFIG_SIBYTE_SB1250) += sibyte/ cflags-$(CONFIG_SIBYTE_SB1250) += \ -I$(srctree)/arch/mips/include/asm/mach-sibyte \ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL -- GitLab From f69df6d33c020d3510a31d142edda3bd2107dff4 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Jun 2013 14:13:13 +0200 Subject: [PATCH 2071/2900] MIPS: Sibyte: Fix comment. Signed-off-by: Ralf Baechle --- arch/mips/sibyte/Platform | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform index af9ee6afa31a..6cb6dcf241f2 100644 --- a/arch/mips/sibyte/Platform +++ b/arch/mips/sibyte/Platform @@ -30,7 +30,8 @@ cflags-$(CONFIG_SIBYTE_BCM1x80) += \ # Sibyte BCM91120C (CRhine) board # Sibyte BCM91125C (CRhone) board # Sibyte BCM91125E (Rhone) board -# Sibyte SWARM board +# Sibyte BCM91250A (SWARM) board +# Sibyte BCM91250C2 (LittleSur) board # Sibyte BCM91x80 (BigSur) board # load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000 -- GitLab From 0dad5d262278d24babbd62241fd238a3a3a0a39a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Jun 2013 16:39:34 +0200 Subject: [PATCH 2072/2900] MIPS: Malta: Move platform-specific PCI code to arch/mips/pci. Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/Makefile | 1 - arch/mips/pci/Makefile | 2 +- arch/mips/{mti-malta/malta-pci.c => pci/pci-malta.c} | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename arch/mips/{mti-malta/malta-pci.c => pci/pci-malta.c} (100%) diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index 0388fc8b5613..72fdedbf76db 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -10,7 +10,6 @@ obj-y := malta-amon.o malta-display.o malta-init.o \ malta-reset.o malta-setup.o malta-time.o obj-$(CONFIG_EARLY_PRINTK) += malta-console.o -obj-$(CONFIG_PCI) += malta-pci.o # FIXME FIXME FIXME obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index b56fbc06c60e..c382042911dd 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o -obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o +obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o diff --git a/arch/mips/mti-malta/malta-pci.c b/arch/mips/pci/pci-malta.c similarity index 100% rename from arch/mips/mti-malta/malta-pci.c rename to arch/mips/pci/pci-malta.c -- GitLab From 1990e5429c2149a30a81ff634215c1aa76560a89 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 26 Jun 2013 17:06:34 +0200 Subject: [PATCH 2073/2900] MIPS: Get rid of MIPS I flag and test macros. MIPS I is the ancestor of all MIPS ISA and architecture variants. Anything ever build in the MIPS empire is either MIPS I or at least contains MIPS I. If it's running Linux, that is. So there is little point in having cpu_has_mips_1 because it will always evaluate as true - though usually only at runtime. Thus there is no point in having the MIPS_CPU_ISA_I ISA flag, so get rid of it. Little complication: traps.c was using a test for a pure MIPS I ISA as a test for an R3000-style cp0. To deal with that, use a check for cpu_has_3kex or cpu_has_4kex instead. cpu_has_3kex is a new macro. At the moment its default implementation is !cpu_has_4kex but this may eventually change if Linux is ever going to support the oddball MIPS processors R6000 and R8000 so users of either of these macros should not make any assumptions. Signed-off-by: Ralf Baechle Patchwork: https://patchwork.linux-mips.org/patch/5551/ --- arch/mips/include/asm/cpu-features.h | 11 ++++++++++- arch/mips/include/asm/cpu.h | 23 +++++++++++------------ arch/mips/kernel/cpu-probe.c | 8 +------- arch/mips/kernel/proc.c | 4 +--- arch/mips/kernel/traps.c | 4 ++-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index e5ec8fcd8afa..9609812bc8f2 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -24,6 +24,16 @@ #ifndef cpu_has_tlb #define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB) #endif + +/* + * For the moment we don't consider R6000 and R8000 so we can assume that + * anything that doesn't support R4000-style exceptions and interrupts is + * R3000-like. Users should still treat these two macro definitions as + * opaque. + */ +#ifndef cpu_has_3kex +#define cpu_has_3kex (!cpu_has_4kex) +#endif #ifndef cpu_has_4kex #define cpu_has_4kex (cpu_data[0].options & MIPS_CPU_4KEX) #endif @@ -136,7 +146,6 @@ #endif #endif -# define cpu_has_mips_1 (cpu_data[0].isa_level & MIPS_CPU_ISA_I) #ifndef cpu_has_mips_2 # define cpu_has_mips_2 (cpu_data[0].isa_level & MIPS_CPU_ISA_II) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index dd86ab205483..632bbe5a79ea 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -282,18 +282,17 @@ enum cpu_type_enum { * ISA Level encodings * */ -#define MIPS_CPU_ISA_I 0x00000001 -#define MIPS_CPU_ISA_II 0x00000002 -#define MIPS_CPU_ISA_III 0x00000004 -#define MIPS_CPU_ISA_IV 0x00000008 -#define MIPS_CPU_ISA_V 0x00000010 -#define MIPS_CPU_ISA_M32R1 0x00000020 -#define MIPS_CPU_ISA_M32R2 0x00000040 -#define MIPS_CPU_ISA_M64R1 0x00000080 -#define MIPS_CPU_ISA_M64R2 0x00000100 - -#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | \ - MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2) +#define MIPS_CPU_ISA_II 0x00000001 +#define MIPS_CPU_ISA_III 0x00000002 +#define MIPS_CPU_ISA_IV 0x00000004 +#define MIPS_CPU_ISA_V 0x00000008 +#define MIPS_CPU_ISA_M32R1 0x00000010 +#define MIPS_CPU_ISA_M32R2 0x00000020 +#define MIPS_CPU_ISA_M64R1 0x00000040 +#define MIPS_CPU_ISA_M64R2 0x00000080 + +#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_II | MIPS_CPU_ISA_M32R1 | \ + MIPS_CPU_ISA_M32R2) #define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \ MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 265c97da6619..f87039dbefe9 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -146,8 +146,7 @@ static void __cpuinit set_isa(struct cpuinfo_mips *c, unsigned int isa) case MIPS_CPU_ISA_IV: c->isa_level |= MIPS_CPU_ISA_IV; case MIPS_CPU_ISA_III: - c->isa_level |= MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | - MIPS_CPU_ISA_III; + c->isa_level |= MIPS_CPU_ISA_II | MIPS_CPU_ISA_III; break; case MIPS_CPU_ISA_M32R2: @@ -156,8 +155,6 @@ static void __cpuinit set_isa(struct cpuinfo_mips *c, unsigned int isa) c->isa_level |= MIPS_CPU_ISA_M32R1; case MIPS_CPU_ISA_II: c->isa_level |= MIPS_CPU_ISA_II; - case MIPS_CPU_ISA_I: - c->isa_level |= MIPS_CPU_ISA_I; break; } } @@ -332,7 +329,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) case PRID_IMP_R2000: c->cputype = CPU_R2000; __cpu_name[cpu] = "R2000"; - set_isa(c, MIPS_CPU_ISA_I); c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) @@ -352,7 +348,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) c->cputype = CPU_R3000; __cpu_name[cpu] = "R3000"; } - set_isa(c, MIPS_CPU_ISA_I); c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE | MIPS_CPU_NOFPUEX; if (__cpu_has_fpu()) @@ -455,7 +450,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) break; #endif case PRID_IMP_TX39: - set_isa(c, MIPS_CPU_ISA_I); c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE; if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) { diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index acb34373679e..8c58d8a84bf3 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c @@ -66,9 +66,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "]\n"); } if (cpu_has_mips_r) { - seq_printf(m, "isa\t\t\t:"); - if (cpu_has_mips_1) - seq_printf(m, "%s", " mips1"); + seq_printf(m, "isa\t\t\t: mips1"); if (cpu_has_mips_2) seq_printf(m, "%s", " mips2"); if (cpu_has_mips_3) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 142d2bede024..d97ea234e2d3 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -265,7 +265,7 @@ static void __show_regs(const struct pt_regs *regs) printk("Status: %08x ", (uint32_t) regs->cp0_status); - if (current_cpu_data.isa_level == MIPS_CPU_ISA_I) { + if (cpu_has_3kex) { if (regs->cp0_status & ST0_KUO) printk("KUo "); if (regs->cp0_status & ST0_IEO) @@ -278,7 +278,7 @@ static void __show_regs(const struct pt_regs *regs) printk("KUc "); if (regs->cp0_status & ST0_IEC) printk("IEc "); - } else { + } else if (cpu_has_4kex) { if (regs->cp0_status & ST0_KX) printk("KX "); if (regs->cp0_status & ST0_SX) -- GitLab From 6ba045f9fbdafb48da42aa8576ea7a3980443136 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Sun, 23 Jun 2013 17:16:19 +0000 Subject: [PATCH 2074/2900] MIPS: Move generated code to .text for microMIPS Prepare of a next patch which will call tlbmiss_handler_setup_pgd on microMIPS. MicroMIPS complains if the called code s not in the .text section. To fix this we generate code into space reserved in arch/mips/mm/tlb-funcs.S While there, move the rest of the generated functions (handle_tlbl, handle_tlbs, handle_tlbm) to the same file. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5542/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mmu_context.h | 6 +-- arch/mips/mm/Makefile | 2 +- arch/mips/mm/tlb-funcs.S | 37 +++++++++++++ arch/mips/mm/tlbex.c | 84 +++++++++++++++-------------- 4 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 arch/mips/mm/tlb-funcs.S diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index 820116067c10..1fed8bdcf2a0 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -28,11 +28,7 @@ #define TLBMISS_HANDLER_SETUP_PGD(pgd) \ do { \ - void (*tlbmiss_handler_setup_pgd)(unsigned long); \ - extern u32 tlbmiss_handler_setup_pgd_array[16]; \ - \ - tlbmiss_handler_setup_pgd = \ - (__typeof__(tlbmiss_handler_setup_pgd)) tlbmiss_handler_setup_pgd_array; \ + extern void tlbmiss_handler_setup_pgd(unsigned long); \ tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \ } while (0) diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile index e87aae1f2e80..7f4f93ab22b7 100644 --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile @@ -4,7 +4,7 @@ obj-y += cache.o dma-default.o extable.o fault.o \ gup.o init.o mmap.o page.o page-funcs.o \ - tlbex.o tlbex-fault.o uasm-mips.o + tlbex.o tlbex-fault.o tlb-funcs.o uasm-mips.o obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o obj-$(CONFIG_64BIT) += pgtable-64.o diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S new file mode 100644 index 000000000000..30a494db99c2 --- /dev/null +++ b/arch/mips/mm/tlb-funcs.S @@ -0,0 +1,37 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Micro-assembler generated tlb handler functions. + * + * Copyright (C) 2013 Broadcom Corporation. + * + * Based on mm/page-funcs.c + * Copyright (C) 2012 MIPS Technologies, Inc. + * Copyright (C) 2012 Ralf Baechle + */ +#include +#include + +#define FASTPATH_SIZE 128 + +LEAF(tlbmiss_handler_setup_pgd) + .space 16 * 4 +END(tlbmiss_handler_setup_pgd) +EXPORT(tlbmiss_handler_setup_pgd_end) + +LEAF(handle_tlbm) + .space FASTPATH_SIZE * 4 +END(handle_tlbm) +EXPORT(handle_tlbm_end) + +LEAF(handle_tlbs) + .space FASTPATH_SIZE * 4 +END(handle_tlbs) +EXPORT(handle_tlbs_end) + +LEAF(handle_tlbl) + .space FASTPATH_SIZE * 4 +END(handle_tlbl) +EXPORT(handle_tlbl_end) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 9b988c050fdd..4712f3cd73b7 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1455,27 +1455,25 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); } -/* - * 128 instructions for the fastpath handler is generous and should - * never be exceeded. - */ -#define FASTPATH_SIZE 128 +extern u32 handle_tlbl[], handle_tlbl_end[]; +extern u32 handle_tlbs[], handle_tlbs_end[]; +extern u32 handle_tlbm[], handle_tlbm_end[]; -u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; -u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; -u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; #ifdef CONFIG_MIPS_PGD_C0_CONTEXT -u32 tlbmiss_handler_setup_pgd_array[16] __cacheline_aligned; +extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[]; static void __cpuinit build_r4000_setup_pgd(void) { const int a0 = 4; const int a1 = 5; u32 *p = tlbmiss_handler_setup_pgd_array; + const int tlbmiss_handler_setup_pgd_size = + tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - memset(tlbmiss_handler_setup_pgd_array, 0, sizeof(tlbmiss_handler_setup_pgd_array)); + memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size * + sizeof(tlbmiss_handler_setup_pgd[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -1503,15 +1501,15 @@ static void __cpuinit build_r4000_setup_pgd(void) uasm_i_jr(&p, 31); UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); } - if (p - tlbmiss_handler_setup_pgd_array > ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)) - panic("tlbmiss_handler_setup_pgd_array space exceeded"); + if (p >= tlbmiss_handler_setup_pgd_end) + panic("tlbmiss_handler_setup_pgd space exceeded"); + uasm_resolve_relocs(relocs, labels); - pr_debug("Wrote tlbmiss_handler_setup_pgd_array (%u instructions).\n", - (unsigned int)(p - tlbmiss_handler_setup_pgd_array)); + pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", + (unsigned int)(p - tlbmiss_handler_setup_pgd)); - dump_handler("tlbmiss_handler", - tlbmiss_handler_setup_pgd_array, - ARRAY_SIZE(tlbmiss_handler_setup_pgd_array)); + dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd, + tlbmiss_handler_setup_pgd_size); } #endif @@ -1756,10 +1754,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, static void __cpuinit build_r3000_tlb_load_handler(void) { u32 *p = handle_tlbl; + const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - memset(handle_tlbl, 0, sizeof(handle_tlbl)); + memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -1773,23 +1772,24 @@ static void __cpuinit build_r3000_tlb_load_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbl) > FASTPATH_SIZE) + if (p >= handle_tlbl_end) panic("TLB load handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbl)); - dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); + dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size); } static void __cpuinit build_r3000_tlb_store_handler(void) { u32 *p = handle_tlbs; + const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - memset(handle_tlbs, 0, sizeof(handle_tlbs)); + memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -1803,23 +1803,24 @@ static void __cpuinit build_r3000_tlb_store_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbs) > FASTPATH_SIZE) + if (p >= handle_tlbs) panic("TLB store handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbs)); - dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); + dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size); } static void __cpuinit build_r3000_tlb_modify_handler(void) { u32 *p = handle_tlbm; + const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; - memset(handle_tlbm, 0, sizeof(handle_tlbm)); + memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -1833,14 +1834,14 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbm) > FASTPATH_SIZE) + if (p >= handle_tlbm_end) panic("TLB modify handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbm)); - dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); + dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size); } #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ @@ -1904,11 +1905,12 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, static void __cpuinit build_r4000_tlb_load_handler(void) { u32 *p = handle_tlbl; + const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; struct work_registers wr; - memset(handle_tlbl, 0, sizeof(handle_tlbl)); + memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -2047,24 +2049,25 @@ static void __cpuinit build_r4000_tlb_load_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbl) > FASTPATH_SIZE) + if (p >= handle_tlbl_end) panic("TLB load handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbl)); - dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); + dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size); } static void __cpuinit build_r4000_tlb_store_handler(void) { u32 *p = handle_tlbs; + const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; struct work_registers wr; - memset(handle_tlbs, 0, sizeof(handle_tlbs)); + memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -2101,24 +2104,25 @@ static void __cpuinit build_r4000_tlb_store_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbs) > FASTPATH_SIZE) + if (p >= handle_tlbs_end) panic("TLB store handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbs)); - dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); + dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size); } static void __cpuinit build_r4000_tlb_modify_handler(void) { u32 *p = handle_tlbm; + const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; struct uasm_label *l = labels; struct uasm_reloc *r = relocs; struct work_registers wr; - memset(handle_tlbm, 0, sizeof(handle_tlbm)); + memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0])); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); @@ -2156,14 +2160,14 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); - if ((p - handle_tlbm) > FASTPATH_SIZE) + if (p >= handle_tlbm_end) panic("TLB modify handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", (unsigned int)(p - handle_tlbm)); - dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); + dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size); } void __cpuinit build_tlb_refill_handler(void) @@ -2235,13 +2239,13 @@ void __cpuinit build_tlb_refill_handler(void) void __cpuinit flush_tlb_handlers(void) { local_flush_icache_range((unsigned long)handle_tlbl, - (unsigned long)handle_tlbl + sizeof(handle_tlbl)); + (unsigned long)handle_tlbl_end); local_flush_icache_range((unsigned long)handle_tlbs, - (unsigned long)handle_tlbs + sizeof(handle_tlbs)); + (unsigned long)handle_tlbs_end); local_flush_icache_range((unsigned long)handle_tlbm, - (unsigned long)handle_tlbm + sizeof(handle_tlbm)); + (unsigned long)handle_tlbm_end); #ifdef CONFIG_MIPS_PGD_C0_CONTEXT - local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, - (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); + local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd, + (unsigned long)tlbmiss_handler_setup_pgd_end); #endif } -- GitLab From a135a9b5d9683ace787c7d86f1e642d9acfacdde Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 23 Jun 2013 20:38:44 +0000 Subject: [PATCH 2075/2900] MIPS: Octeon: Enable interfaces on EdgeRouter Lite Enable interfaces on EdgeRouter Lite. Tested with cavium_octeon_defconfig and busybox shell. DHCP & ping works with eth0, eth1 and eth2. The board type "UBNT_E100" is taken from the sources of the vendor kernel shipped with the product. Signed-off-by: Aaro Koskinen Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5546/ Signed-off-by: Ralf Baechle --- .../cavium-octeon/executive/cvmx-helper-board.c | 13 +++++++++++++ arch/mips/include/asm/octeon/cvmx-bootinfo.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c index 7c6497781895..0a1283ce47f5 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c @@ -181,6 +181,11 @@ int cvmx_helper_board_get_mii_address(int ipd_port) return ipd_port - 16 + 4; else return -1; + case CVMX_BOARD_TYPE_UBNT_E100: + if (ipd_port >= 0 && ipd_port <= 2) + return 7 - ipd_port; + else + return -1; } /* Some unknown board. Somebody forgot to update this function... */ @@ -706,6 +711,14 @@ int __cvmx_helper_board_hardware_enable(int interface) } } } + } else if (cvmx_sysinfo_get()->board_type == + CVMX_BOARD_TYPE_UBNT_E100) { + cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0); + cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0x10); + cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); + cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0x10); + cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(2, interface), 0); + cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(2, interface), 0x10); } return 0; } diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h index 284fa8d773ba..7b7818d1e4d5 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h +++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h @@ -227,6 +227,7 @@ enum cvmx_board_types_enum { * use any numbers in this range. */ CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001, + CVMX_BOARD_TYPE_UBNT_E100 = 20002, CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000, /* The remaining range is reserved for future use. */ @@ -325,6 +326,7 @@ static inline const char *cvmx_board_type_to_string(enum /* Customer private range */ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN) + ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100) ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX) } return "Unsupported Board"; -- GitLab From 8dfdd02a4c9de3aa7f2bfdec515e57340e401c87 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 21 Jun 2013 21:14:53 +0000 Subject: [PATCH 2076/2900] MIPS: Don't save/restore OCTEON wide multiplier state on syscalls. The ABI allows these to be clobbered on syscalls, so only save and restore the multiplier state when the temporary registers need to be preserved. Signed-off-by: David Daney Cc: linux-mips@linux-mips.org Cc: David Daney Patchwork: https://patchwork.linux-mips.org/patch/5540/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/stackframe.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index a89d1b10d027..23fc95e65673 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -69,6 +69,14 @@ LONG_S $24, PT_R24(sp) #ifndef CONFIG_CPU_HAS_SMARTMIPS LONG_S v1, PT_LO(sp) +#endif +#ifdef CONFIG_CPU_CAVIUM_OCTEON + /* + * The Octeon multiplier state is affected by general + * multiply instructions. It must be saved before and + * kernel code might corrupt it + */ + jal octeon_mult_save #endif .endm @@ -218,17 +226,8 @@ ori $28, sp, _THREAD_MASK xori $28, _THREAD_MASK #ifdef CONFIG_CPU_CAVIUM_OCTEON - .set mips64 - pref 0, 0($28) /* Prefetch the current pointer */ - pref 0, PT_R31(sp) /* Prefetch the $31(ra) */ - /* The Octeon multiplier state is affected by general multiply - instructions. It must be saved before and kernel code might - corrupt it */ - jal octeon_mult_save - LONG_L v1, 0($28) /* Load the current pointer */ - /* Restore $31(ra) that was changed by the jal */ - LONG_L ra, PT_R31(sp) - pref 0, 0(v1) /* Prefetch the current thread */ + .set mips64 + pref 0, 0($28) /* Prefetch the current pointer */ #endif .set pop .endm @@ -248,6 +247,10 @@ .endm .macro RESTORE_TEMP +#ifdef CONFIG_CPU_CAVIUM_OCTEON + /* Restore the Octeon multiplier state */ + jal octeon_mult_restore +#endif #ifdef CONFIG_CPU_HAS_SMARTMIPS LONG_L $24, PT_ACX(sp) mtlhx $24 @@ -360,10 +363,6 @@ DVPE 5 # dvpe a1 jal mips_ihb #endif /* CONFIG_MIPS_MT_SMTC */ -#ifdef CONFIG_CPU_CAVIUM_OCTEON - /* Restore the Octeon multiplier state */ - jal octeon_mult_restore -#endif mfc0 a0, CP0_STATUS ori a0, STATMASK xori a0, STATMASK -- GitLab From c214c03512b67e56dea3f4471705f8caae49553a Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 21 Jun 2013 10:13:08 +0000 Subject: [PATCH 2077/2900] MIPS: GIC: Fix gic_set_affinity infinite loop There is an infinite loop in gic_set_affinity. When irq_set_affinity gets called on gic controller, it blocks forever. Signed-off-by: Tony Wu Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5537/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/irq-gic.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index c01b307317a9..5b5ddb231f26 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -219,16 +219,15 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, /* Assumption : cpumask refers to a single CPU */ spin_lock_irqsave(&gic_lock, flags); - for (;;) { - /* Re-route this IRQ */ - GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp)); - /* Update the pcpu_masks */ - for (i = 0; i < NR_CPUS; i++) - clear_bit(irq, pcpu_masks[i].pcpu_mask); - set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); + /* Re-route this IRQ */ + GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp)); + + /* Update the pcpu_masks */ + for (i = 0; i < NR_CPUS; i++) + clear_bit(irq, pcpu_masks[i].pcpu_mask); + set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); - } cpumask_copy(d->affinity, cpumask); spin_unlock_irqrestore(&gic_lock, flags); -- GitLab From 3ddc14add5e6341cf8ef4058c34c67ba7fd15317 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 24 May 2013 20:54:10 +0000 Subject: [PATCH 2078/2900] MIPS: Only set cpu_has_mmips if SYS_SUPPORTS_MICROMIPS As Jonas Gorske said in his patch: Disable cpu_has_mmips for everything but SEAD3 and MALTA. Most of these platforms are from before the micromips introduction, so they are very unlikely to implement it. Reduces an -Os compiled, uncompressed kernel image by 8KiB for BCM63XX. This patch taks a different approach than his, we gate the runtime test for microMIPS by the config symbol SYS_SUPPORTS_MICROMIPS. Signed-off-by: David Daney Cc: Jonas Gorski Cc: Steven J. Hill Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5327/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 9609812bc8f2..8e0c125c59a1 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -109,7 +109,11 @@ #define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) #endif #ifndef cpu_has_mmips -#define cpu_has_mmips (cpu_data[0].options & MIPS_CPU_MICROMIPS) +# ifdef CONFIG_SYS_SUPPORTS_MICROMIPS +# define cpu_has_mmips (cpu_data[0].options & MIPS_CPU_MICROMIPS) +# else +# define cpu_has_mmips 0 +# endif #endif #ifndef cpu_has_vtag_icache #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) -- GitLab From 4df715aaf566110bedb3751ed235a3bacdebbdde Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 26 Jun 2013 18:11:56 +0000 Subject: [PATCH 2079/2900] MIPS: BMIPS: support booting from physical CPU other than 0 BMIPS43xx CPUs have two hardware threads, and on some SoCs such as 3368, the bootloader has configured the system to boot from TP1 instead of the more usual TP0. Create the physical to logical CPU mapping to cope with that, do not remap the software interrupts to be cross CPUs such that we do not have to do use the logical CPU mapping further down the code, and finally, reset the slave TP1 only if booted from TP0. Signed-off-by: Jonas Gorski Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: blogic@openwrt.org Cc: cernekee@gmail.com Patchwork: https://patchwork.linux-mips.org/patch/5553/ Patchwork: https://patchwork.linux-mips.org/patch/5556/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-bmips.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 8e393b8443f7..aea6c0885838 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -63,7 +63,7 @@ static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id); static void __init bmips_smp_setup(void) { - int i; + int i, cpu = 1, boot_cpu = 0; #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) /* arbitration priority */ @@ -72,13 +72,22 @@ static void __init bmips_smp_setup(void) /* NBK and weak order flags */ set_c0_brcm_config_0(0x30000); + /* Find out if we are running on TP0 or TP1 */ + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31)); + /* * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output + * + * If booting from TP1, leave the existing CMT interrupt routing + * such that TP0 responds to SW1 and TP1 responds to SW0. */ - change_c0_brcm_cmt_intr(0xf8018000, - (0x02 << 27) | (0x03 << 15)); + if (boot_cpu == 0) + change_c0_brcm_cmt_intr(0xf8018000, + (0x02 << 27) | (0x03 << 15)); + else + change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27)); /* single core, 2 threads (2 pipelines) */ max_cpus = 2; @@ -106,9 +115,15 @@ static void __init bmips_smp_setup(void) if (!board_ebase_setup) board_ebase_setup = &bmips_ebase_setup; + __cpu_number_map[boot_cpu] = 0; + __cpu_logical_map[0] = boot_cpu; + for (i = 0; i < max_cpus; i++) { - __cpu_number_map[i] = 1; - __cpu_logical_map[i] = 1; + if (i != boot_cpu) { + __cpu_number_map[i] = cpu; + __cpu_logical_map[cpu] = i; + cpu++; + } set_cpu_possible(i, 1); set_cpu_present(i, 1); } @@ -157,7 +172,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) bmips_send_ipi_single(cpu, 0); else { #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) - set_c0_brcm_cmt_ctrl(0x01); + /* Reset slave TP1 if booting from TP0 */ + if (cpu_logical_map(cpu) == 0) + set_c0_brcm_cmt_ctrl(0x01); #elif defined(CONFIG_CPU_BMIPS5000) if (cpu & 0x01) write_c0_brcm_action(ACTION_BOOT_THREAD(cpu)); -- GitLab From fc192e50f868d8f34b15a18c38407f4b9468a31d Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 21 Jun 2013 10:10:46 +0000 Subject: [PATCH 2080/2900] MIPS: Cleanup indentation and whitespace Signed-off-by: Tony Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5536/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/cpu-features.h | 32 +++++++++---------- .../asm/mach-generic/kernel-entry-init.h | 4 +-- arch/mips/include/asm/processor.h | 4 +-- arch/mips/kernel/branch.c | 1 - arch/mips/kernel/unaligned.c | 1 + arch/mips/mm/page.c | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 8e0c125c59a1..1dc086087a72 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -97,13 +97,13 @@ #define cpu_has_mips16 (cpu_data[0].ases & MIPS_ASE_MIPS16) #endif #ifndef cpu_has_mdmx -#define cpu_has_mdmx (cpu_data[0].ases & MIPS_ASE_MDMX) +#define cpu_has_mdmx (cpu_data[0].ases & MIPS_ASE_MDMX) #endif #ifndef cpu_has_mips3d -#define cpu_has_mips3d (cpu_data[0].ases & MIPS_ASE_MIPS3D) +#define cpu_has_mips3d (cpu_data[0].ases & MIPS_ASE_MIPS3D) #endif #ifndef cpu_has_smartmips -#define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS) +#define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS) #endif #ifndef cpu_has_rixi #define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) @@ -125,7 +125,7 @@ #define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC) #endif #ifndef cpu_has_pindexed_dcache -#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) +#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) #endif #ifndef cpu_has_local_ebase #define cpu_has_local_ebase 1 @@ -162,18 +162,18 @@ #ifndef cpu_has_mips_5 # define cpu_has_mips_5 (cpu_data[0].isa_level & MIPS_CPU_ISA_V) #endif -# ifndef cpu_has_mips32r1 +#ifndef cpu_has_mips32r1 # define cpu_has_mips32r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R1) -# endif -# ifndef cpu_has_mips32r2 +#endif +#ifndef cpu_has_mips32r2 # define cpu_has_mips32r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2) -# endif -# ifndef cpu_has_mips64r1 +#endif +#ifndef cpu_has_mips64r1 # define cpu_has_mips64r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1) -# endif -# ifndef cpu_has_mips64r2 +#endif +#ifndef cpu_has_mips64r2 # define cpu_has_mips64r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2) -# endif +#endif /* * Shortcuts ... @@ -195,9 +195,9 @@ * has CLO and CLZ but not DCLO nor DCLZ. For 64-bit kernels * cpu_has_clo_clz also indicates the availability of DCLO and DCLZ. */ -# ifndef cpu_has_clo_clz -# define cpu_has_clo_clz cpu_has_mips_r -# endif +#ifndef cpu_has_clo_clz +#define cpu_has_clo_clz cpu_has_mips_r +#endif #ifndef cpu_has_dsp #define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP) @@ -223,7 +223,7 @@ # define cpu_has_64bits (cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT) # endif # ifndef cpu_has_64bit_zero_reg -# define cpu_has_64bit_zero_reg (cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT) +# define cpu_has_64bit_zero_reg (cpu_data[0].isa_level & MIPS_CPU_ISA_64BIT) # endif # ifndef cpu_has_64bit_gp_regs # define cpu_has_64bit_gp_regs 0 diff --git a/arch/mips/include/asm/mach-generic/kernel-entry-init.h b/arch/mips/include/asm/mach-generic/kernel-entry-init.h index 7e66505fa574..13b0751b010a 100644 --- a/arch/mips/include/asm/mach-generic/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-generic/kernel-entry-init.h @@ -12,8 +12,8 @@ /* Intentionally empty macro, used in head.S. Override in * arch/mips/mach-xxx/kernel-entry-init.h when necessary. */ -.macro kernel_entry_setup -.endm + .macro kernel_entry_setup + .endm /* * Do SMP slave processor setup necessary before we can savely execute C code. diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 016dc4bffc80..3605b844ad87 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -244,8 +244,8 @@ struct thread_struct { unsigned long cp0_baduaddr; /* Last kernel fault accessing USEG */ unsigned long error_code; #ifdef CONFIG_CPU_CAVIUM_OCTEON - struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128))); - struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128))); + struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128))); + struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128))); #endif #ifdef CONFIG_CPU_XLP struct nlm_cop2_state cp2; diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 46c2ad0703a0..4d78bf445a9c 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -467,5 +467,4 @@ int __compute_return_epc(struct pt_regs *regs) printk("%s: unaligned epc - sending SIGBUS.\n", current->comm); force_sig(SIGBUS, current); return -EFAULT; - } diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 3eaa02aa8ae0..8eaf310ffc6c 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -1549,6 +1549,7 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr) ("Unhandled kernel unaligned access or invalid instruction", regs); force_sig(SIGILL, current); } + asmlinkage void do_ade(struct pt_regs *regs) { enum ctx_state prev_state; diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 4eb8dcfaf1ce..2c0bd580b9da 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -232,7 +232,7 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off) uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0); } - } + } } extern u32 __clear_page_start; -- GitLab From 42a111797e8fa961d6168922e873d6b4be87e904 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Fri, 21 Jun 2013 10:09:23 +0000 Subject: [PATCH 2081/2900] MIPS: Fix typos and cleanup comment Signed-off-by: Tony Wu Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5535/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/gic.h | 2 +- arch/mips/kernel/process.c | 3 --- arch/mips/mm/tlbex.c | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 7153b32de18e..b2e3e93dd7d8 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -347,7 +347,7 @@ struct gic_shared_intr_map { #define GIC_CPU_INT2 2 /* . */ #define GIC_CPU_INT3 3 /* . */ #define GIC_CPU_INT4 4 /* . */ -#define GIC_CPU_INT5 5 /* Core Interrupt 5 */ +#define GIC_CPU_INT5 5 /* Core Interrupt 7 */ /* Local GIC interrupts. */ #define GIC_INT_TMR (GIC_CPU_INT5) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 7d62894f7e23..ddc76103e78c 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -207,9 +207,6 @@ unsigned long __stack_chk_guard __read_mostly; EXPORT_SYMBOL(__stack_chk_guard); #endif -/* - * - */ struct mips_frame_info { void *func; unsigned long func_size; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 4712f3cd73b7..357e0fd65e94 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -972,7 +972,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) uasm_i_srl(p, ptr, ptr, 19); #else /* - * smp_processor_id() << 3 is stored in CONTEXT. + * smp_processor_id() << 2 is stored in CONTEXT. */ uasm_i_mfc0(p, ptr, C0_CONTEXT); UASM_i_LA_mostly(p, tmp, pgdc); -- GitLab From 74338805ec6869594d583535f941cb478c94dd73 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 24 May 2013 20:54:08 +0000 Subject: [PATCH 2082/2900] MIPS: Declare emulate_load_store_microMIPS as a static function. It is only used from within a single file, it should not be globally visible. Signed-off-by: David Daney Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5325/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/unaligned.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 8eaf310ffc6c..c369a5d35527 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -685,7 +685,8 @@ const int reg16to32[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; /* Recode table from 16-bit STORE register notation to 32-bit GPR. */ const int reg16to32st[] = { 0, 17, 2, 3, 4, 5, 6, 7 }; -void emulate_load_store_microMIPS(struct pt_regs *regs, void __user * addr) +static void emulate_load_store_microMIPS(struct pt_regs *regs, + void __user *addr) { unsigned long value; unsigned int res; -- GitLab From fe6d29095d4370bed3a525404c45bbd6aa7c191b Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 24 May 2013 20:54:09 +0000 Subject: [PATCH 2083/2900] MIPS: Don't try to decode microMIPS branch instructions where they cannot exist. In mm_isBranchInstr() we can short circuit the entire function if !cpu_has_mmips. Signed-off-by: David Daney Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5326/ Signed-off-by: Ralf Baechle --- arch/mips/math-emu/cp1emu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index f03771900813..e773659ccf9f 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -471,6 +471,9 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, unsigned int fcr31; unsigned int bit; + if (!cpu_has_mmips) + return 0; + switch (insn.mm_i_format.opcode) { case mm_pool32a_op: if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) == -- GitLab From c6213c6c9c189aeb97010673e3129a8929d2223e Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Wed, 5 Jun 2013 21:25:17 +0000 Subject: [PATCH 2084/2900] MIPS: microMIPS: Fix improper definition of ISA exception bit. The ISA exception bit selects whether exceptions are taken in classic or microMIPS mode. This bit is Config3.ISAOnExc and was improperly defined as bits 16 and 17 instead of just bit 16. A new function was added so that platforms could set this bit when running a kernel compiled with only microMIPS instructions. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5377/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mipsregs.h | 2 +- arch/mips/kernel/cpu-probe.c | 3 --- arch/mips/kernel/traps.c | 9 +++++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 87e6207b05e4..fed1c3e9b486 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -596,7 +596,7 @@ #define MIPS_CONF3_RXI (_ULCAST_(1) << 12) #define MIPS_CONF3_ULRI (_ULCAST_(1) << 13) #define MIPS_CONF3_ISA (_ULCAST_(3) << 14) -#define MIPS_CONF3_ISA_OE (_ULCAST_(3) << 16) +#define MIPS_CONF3_ISA_OE (_ULCAST_(1) << 16) #define MIPS_CONF3_VZ (_ULCAST_(1) << 23) #define MIPS_CONF4_MMUSIZEEXT (_ULCAST_(255) << 0) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f87039dbefe9..c7b1b3c5a761 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -269,9 +269,6 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c) c->options |= MIPS_CPU_ULRI; if (config3 & MIPS_CONF3_ISA) c->options |= MIPS_CPU_MICROMIPS; -#ifdef CONFIG_CPU_MICROMIPS - write_c0_config3(read_c0_config3() | MIPS_CONF3_ISA_OE); -#endif if (config3 & MIPS_CONF3_VZ) c->ases |= MIPS_ASE_VZ; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index d97ea234e2d3..b0f3ad26063e 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1878,6 +1878,15 @@ void __init trap_init(void) ebase += (read_c0_ebase() & 0x3ffff000); } + if (cpu_has_mmips) { + unsigned int config3 = read_c0_config3(); + + if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) + write_c0_config3(config3 | MIPS_CONF3_ISA_OE); + else + write_c0_config3(config3 & ~MIPS_CONF3_ISA_OE); + } + if (board_ebase_setup) board_ebase_setup(); per_cpu_trap_init(true); -- GitLab From 271792eff2a272b527ce5aa74d499e346fb851de Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 13:00:40 +0000 Subject: [PATCH 2085/2900] SSB: Kconfig: Amend SSB_EMBEDDED dependencies SSB_EMBEDDED needs functions from driver_pcicore which are only available if SSD_DRIVER_HOSTMODE is selected so make it depend on that symbol. Fixes the following linking problem: drivers/ssb/embedded.c:202: undefined reference to `ssb_pcicore_plat_dev_init' drivers/built-in.o: In function `ssb_pcibios_map_irq': drivers/ssb/embedded.c:247: undefined reference to `ssb_pcicore_pcibios_map_irq' Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: sibyte-users@bitmover.com Cc: netdev@vger.kernel.org Cc: Michael Buesch Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5484/ Acked-by: Florian Fainelli Signed-off-by: Ralf Baechle --- drivers/ssb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 5ff3a4f19443..36171fd2826b 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -144,7 +144,7 @@ config SSB_SFLASH # Assumption: We are on embedded, if we compile the MIPS core. config SSB_EMBEDDED bool - depends on SSB_DRIVER_MIPS + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE default y config SSB_DRIVER_EXTIF -- GitLab From 4287f7915f33c1eb770e22589936cd9cd8a60b45 Mon Sep 17 00:00:00 2001 From: Deng-Cheng Zhu Date: Mon, 8 Apr 2013 15:53:00 +0000 Subject: [PATCH 2086/2900] MIPS: APSP: Remove Now that KSPD is gone, kspd.h has no reason to be there. Signed-off-by: Deng-Cheng Zhu Cc: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: kevink@paralogos.com Cc: macro@linux-mips.org Cc: john@phrozen.org Patchwork: https://patchwork.linux-mips.org/patch/5060/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/kspd.h | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 arch/mips/include/asm/kspd.h diff --git a/arch/mips/include/asm/kspd.h b/arch/mips/include/asm/kspd.h deleted file mode 100644 index ec6832950ace..000000000000 --- a/arch/mips/include/asm/kspd.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - */ - -#ifndef _ASM_KSPD_H -#define _ASM_KSPD_H - -struct kspd_notifications { - void (*kspd_sp_exit)(int sp_id); - - struct list_head list; -}; - -static inline void kspd_notify(struct kspd_notifications *notify) -{ -} - -#endif -- GitLab From ed3ce16c3d2ba7cac321d29ec0a7d21408ea8437 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 20 Jun 2013 14:36:30 +0000 Subject: [PATCH 2087/2900] Revert "MIPS: make CAC_ADDR and UNCAC_ADDR account for PHYS_OFFSET" This reverts commit 3f4579252aa166641861a64f1c2883365ca126c2. It is invalid because the macros CAC_ADDR and UNCAC_ADDR have a kernel virtual address as an argument and also returns a kernel virtual address. Using and physical address PHYS_OFFSET is blatantly wrong for a macro common to multiple platforms. Signed-off-by: Leonid Yegoshin Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5528/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ar7/spaces.h | 7 +++++-- arch/mips/include/asm/mach-ip28/spaces.h | 9 ++++++--- arch/mips/include/asm/page.h | 6 ++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h index ac28f273449c..660ab64c0fc9 100644 --- a/arch/mips/include/asm/mach-ar7/spaces.h +++ b/arch/mips/include/asm/mach-ar7/spaces.h @@ -14,8 +14,11 @@ * This handles the memory map. * We handle pages at KSEG0 for kernels with 32 bit address space. */ -#define PAGE_OFFSET 0x94000000UL -#define PHYS_OFFSET 0x14000000UL +#define PAGE_OFFSET _AC(0x94000000, UL) +#define PHYS_OFFSET _AC(0x14000000, UL) + +#define UNCAC_BASE _AC(0xb4000000, UL) /* 0xa0000000 + PHYS_OFFSET */ +#define IO_BASE UNCAC_BASE #include diff --git a/arch/mips/include/asm/mach-ip28/spaces.h b/arch/mips/include/asm/mach-ip28/spaces.h index 5edf05d9dad8..5d6a76434d00 100644 --- a/arch/mips/include/asm/mach-ip28/spaces.h +++ b/arch/mips/include/asm/mach-ip28/spaces.h @@ -11,11 +11,14 @@ #ifndef _ASM_MACH_IP28_SPACES_H #define _ASM_MACH_IP28_SPACES_H -#define CAC_BASE 0xa800000000000000 +#define CAC_BASE _AC(0xa800000000000000, UL) -#define HIGHMEM_START (~0UL) +#define HIGHMEM_START (~0UL) -#define PHYS_OFFSET _AC(0x20000000, UL) +#define PHYS_OFFSET _AC(0x20000000, UL) + +#define UNCAC_BASE _AC(0xc0000000, UL) /* 0xa0000000 + PHYS_OFFSET */ +#define IO_BASE UNCAC_BASE #include diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index f59552fae917..f6be4741f7e8 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -205,10 +205,8 @@ extern int __virt_addr_valid(const volatile void *kaddr); #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \ - PHYS_OFFSET) -#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \ - PHYS_OFFSET) +#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) +#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) #include #include -- GitLab From 78276207a70e805cc022364218eefb8aa05ea647 Mon Sep 17 00:00:00 2001 From: Leonid Yegoshin Date: Thu, 20 Jun 2013 14:36:42 +0000 Subject: [PATCH 2088/2900] MIPS: Malta: Update GCMP detection. Add GCMP detection for IASim Marvell chip emulation support. Signed-off-by: Leonid Yegoshin Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin Patchwork: https://patchwork.linux-mips.org/patch/5529/ Signed-off-by: Ralf Baechle --- arch/mips/mti-malta/malta-int.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 0a1339ac3ec8..c69da3734699 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -422,8 +422,10 @@ static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = { */ int __init gcmp_probe(unsigned long addr, unsigned long size) { - if (mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) { + if ((mips_revision_sconid != MIPS_REVISION_SCON_ROCIT) && + (mips_revision_sconid != MIPS_REVISION_SCON_GT64120)) { gcmp_present = 0; + pr_debug("GCMP NOT present\n"); return gcmp_present; } -- GitLab From 78857614104a26cdada4c53eea104752042bf5a1 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 17 Jun 2013 08:09:00 +0000 Subject: [PATCH 2089/2900] MIPS: Expose missing pci_io{map,unmap} declarations The GENERIC_PCI_IOMAP does not depend on CONFIG_PCI so move it to the CONFIG_MIPS symbol so it's always selected for MIPS. This fixes the missing pci_iomap declaration for MIPS. Moreover, the pci_iounmap function was not defined in the io.h header file if the CONFIG_PCI symbol is not set, but it should since MIPS is not using CONFIG_GENERIC_IOMAP. This fixes the following problem on a allyesconfig: drivers/net/ethernet/3com/3c59x.c:1031:2: error: implicit declaration of function 'pci_iomap' [-Werror=implicit-function-declaration] drivers/net/ethernet/3com/3c59x.c:1044:3: error: implicit declaration of function 'pci_iounmap' [-Werror=implicit-function-declaration] Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5478/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- arch/mips/include/asm/io.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ba63cdbd13fe..3a3e54cc7703 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -28,6 +28,7 @@ config MIPS select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_PCI_IOMAP select HAVE_ARCH_JUMP_LABEL select ARCH_WANT_IPC_PARSE_VERSION select IRQ_FORCED_THREADING @@ -2391,7 +2392,6 @@ config PCI bool "Support for PCI controller" depends on HW_HAS_PCI select PCI_DOMAINS - select GENERIC_PCI_IOMAP select NO_GENERIC_PCI_IOPORT_MAP help Find out whether you have a PCI motherboard. PCI is the name of a diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index b7e59853fd33..b84e1fb3fabf 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -170,6 +170,11 @@ static inline void * isa_bus_to_virt(unsigned long address) extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags); extern void __iounmap(const volatile void __iomem *addr); +#ifndef CONFIG_PCI +struct pci_dev; +static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} +#endif + static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, unsigned long flags) { -- GitLab From edd4201ebc2f1a7ab2158ad91ddc0af71e58dce7 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 31 May 2013 13:07:44 +0000 Subject: [PATCH 2090/2900] MIPS: define write{b,w,l,q}_relaxed MIPS does define read{b,w,l,q}_relaxed but does not define their write counterparts: write{b,w,l,q}_relaxed. This patch adds the missing definitions for the write*_relaxed I/O accessors. Signed-off-by: Florian Fainelli Acked-by: John Crispin Cc: linux-mips@linux-mips.org Cc: cernekee@gmail.com Cc: jogo@openwrt.org Patchwork: https://patchwork.linux-mips.org/patch/5352/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/io.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index b84e1fb3fabf..3321dd5a8872 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -454,6 +454,11 @@ __BUILDIO(q, u64) #define readl_relaxed readl #define readq_relaxed readq +#define writeb_relaxed writeb +#define writew_relaxed writew +#define writel_relaxed writel +#define writeq_relaxed writeq + #define readb_be(addr) \ __raw_readb((__force unsigned *)(addr)) #define readw_be(addr) \ -- GitLab From a068dde168e0c618e1dc2151a0922254ec3bbf04 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Tue, 18 Jun 2013 08:34:31 +0000 Subject: [PATCH 2091/2900] MIPS: BCM63xx: Add SMP support to prom.c This involves two changes to the BSP code: 1) register_smp_ops() for BMIPS SMP 2) The CPU1 boot vector on some of the BCM63xx platforms conflicts with the special interrupt vector (IV). Move it to 0x8000_0380 at boot time, to resolve the conflict. Signed-off-by: Kevin Cernekee [jogo@openwrt.org: moved SMP ops registration into ifdef guard, changed ifdef guards to if (IS_ENABLED())] Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: John Crispin Cc: Maxime Bizon Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5489/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/prom.c | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index f3ff28f4c258..3b21454c56a0 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -8,7 +8,11 @@ #include #include +#include #include +#include +#include +#include #include #include #include @@ -54,6 +58,43 @@ void __init prom_init(void) /* do low level board init */ board_prom_init(); + + if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) { + /* set up SMP */ + register_smp_ops(&bmips_smp_ops); + + /* + * BCM6328 might not have its second CPU enabled, while BCM6358 + * needs special handling for its shared TLB, so disable SMP + * for now. + */ + if (BCMCPU_IS_6328()) { + bmips_smp_enabled = 0; + } else if (BCMCPU_IS_6358()) { + bmips_smp_enabled = 0; + } + + if (!bmips_smp_enabled) + return; + + /* + * The bootloader has set up the CPU1 reset vector at + * 0xa000_0200. + * This conflicts with the special interrupt vector (IV). + * The bootloader has also set up CPU1 to respond to the wrong + * IPI interrupt. + * Here we will start up CPU1 in the background and ask it to + * reconfigure itself then go back to sleep. + */ + memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20); + __sync(); + set_c0_cause(C_SW0); + cpumask_set_cpu(1, &bmips_booted_mask); + + /* + * FIXME: we really should have some sort of hazard barrier here + */ + } } void __init prom_free_prom_memory(void) -- GitLab From 7ac836ce2aa7b931f6347e554cb65f9e9cc1da57 Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Tue, 18 Jun 2013 08:34:32 +0000 Subject: [PATCH 2092/2900] MIPS: BCM63xx: Enable second core SMP on BCM6328 if available BCM6328 has a OTP which tells us if the second core is available. Signed-off-by: Jonas Gorski Cc: linux-mips@linux-mips.org Cc: John Crispin Cc: Maxime Bizon Cc: Florian Fainelli Cc: Kevin Cernekee Patchwork: https://patchwork.linux-mips.org/patch/5490/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/prom.c | 6 +++++- arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 ++ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 3b21454c56a0..8ac4e095e68e 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -69,7 +69,11 @@ void __init prom_init(void) * for now. */ if (BCMCPU_IS_6328()) { - bmips_smp_enabled = 0; + reg = bcm_readl(BCM_6328_OTP_BASE + + OTP_USER_BITS_6328_REG(3)); + + if (reg & OTP_6328_REG3_TP1_DISABLED) + bmips_smp_enabled = 0; } else if (BCMCPU_IS_6358()) { bmips_smp_enabled = 0; } diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 9d3c08e4a7e4..22390a2a0661 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -296,6 +296,8 @@ enum bcm63xx_regs_set { #define BCM_6328_PCMDMAS_BASE (0xdeadbeef) #define BCM_6328_RNG_BASE (0xdeadbeef) #define BCM_6328_MISC_BASE (0xb0001800) +#define BCM_6328_OTP_BASE (0xb0000600) + /* * 6338 register sets base address */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index 654213746b32..018628fe6f15 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -1477,4 +1477,11 @@ #define PCIE_DEVICE_OFFSET 0x8000 +/************************************************************************* + * _REG relative to RSET_OTP + *************************************************************************/ + +#define OTP_USER_BITS_6328_REG(i) (0x20 + (i) * 4) +#define OTP_6328_REG3_TP1_DISABLED BIT(9) + #endif /* BCM63XX_REGS_H_ */ -- GitLab From 1535ac096d26538888d00881f5026cbc8b6dc20d Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 27 Jun 2013 15:27:59 +0000 Subject: [PATCH 2093/2900] MIPS: SEAD3: Disable L2 cache on SEAD-3. The cores used on the SEAD-3 platform do not have L2 caches, so this option should not be turned on. Originally fixed on public 'linux-mti-3.8' release branch. Signed-off-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5559/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 3a3e54cc7703..567c45b33651 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -342,7 +342,6 @@ config MIPS_SEAD3 select DMA_NONCOHERENT select IRQ_CPU select IRQ_GIC - select MIPS_CPU_SCACHE select MIPS_MSC select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2 -- GitLab From b6356a013a0933e42556c2def806f06caf459acf Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 1 Jul 2013 17:01:56 +0300 Subject: [PATCH 2094/2900] remoteproc: free carveout memories only after unmapping them It is not preferable to have the allocated pages for carveout memories freed before they are unmapped. The code that deals with the cleanup of carveout memories is therefore moved after the corresponding mapping entries were cleaned up. This is mostly a no-op since the remote processors are already stopped when the cleanup function is called, but this will make the cleanup code follow the exact reverse path of allocation. Signed-off-by: Suman Anna Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 7e33536b5c2b..9fef20022ab4 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -762,13 +762,6 @@ static void rproc_resource_cleanup(struct rproc *rproc) kfree(entry); } - /* clean up carveout allocations */ - list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { - dma_free_coherent(dev->parent, entry->len, entry->va, entry->dma); - list_del(&entry->node); - kfree(entry); - } - /* clean up iommu mapping entries */ list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) { size_t unmapped; @@ -783,6 +776,13 @@ static void rproc_resource_cleanup(struct rproc *rproc) list_del(&entry->node); kfree(entry); } + + /* clean up carveout allocations */ + list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { + dma_free_coherent(dev->parent, entry->len, entry->va, entry->dma); + list_del(&entry->node); + kfree(entry); + } } /* -- GitLab From 95cee62cb4776a65229a6b6d5969be56589d95c1 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Mon, 1 Jul 2013 17:23:58 +0300 Subject: [PATCH 2095/2900] remoteproc: Cocci spatch "memdup.spatch" Use kmemdup instead of kmalloc + memcpy. Signed-off-by: Thomas Meyer Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9fef20022ab4..3cd85a638afa 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -914,11 +914,10 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context) * will be stored in the cached_table. Before the device is started, * cached_table will be copied into devic memory. */ - rproc->cached_table = kmalloc(tablesz, GFP_KERNEL); + rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL); if (!rproc->cached_table) goto out; - memcpy(rproc->cached_table, table, tablesz); rproc->table_ptr = rproc->cached_table; /* count the number of notify-ids */ -- GitLab From 8d38ef1948bd415a5cb653a5c0ec16f3402aaca1 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 1 Jul 2013 08:28:58 -0600 Subject: [PATCH 2096/2900] vfio/type1: Fix leak on error path We also don't handle unpinning zero pages as an error on other exits so we can fix that inconsistency by rolling in the next conditional return. Reported-by: Dan Carpenter Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 98231d10890c..a9807dea3887 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -436,6 +436,12 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, } /* Split existing */ + + /* + * Allocate our tracking structure early even though it may not + * be used. An Allocation failure later loses track of pages and + * is more difficult to unwind. + */ split = kzalloc(sizeof(*split), GFP_KERNEL); if (!split) return -ENOMEM; @@ -443,12 +449,9 @@ static int vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start, offset = start - dma->iova; ret = vfio_unmap_unpin(iommu, dma, start, size); - if (ret) - return ret; - - if (!*size) { + if (ret || !*size) { kfree(split); - return -EINVAL; + return ret; } tmp = dma->size; -- GitLab From 99e1c1398f44a056b16e78122133988c82b66d97 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Jun 2013 14:49:58 +0200 Subject: [PATCH 2097/2900] IB/srp: Fail I/O fast if target offline If reconnecting failed we know that no command completion will be received anymore. Hence let the SCSI error handler fail such commands immediately. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bc13c8db7fc2..1f331011653e 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1754,6 +1754,8 @@ static int srp_abort(struct scsi_cmnd *scmnd) SRP_TSK_ABORT_TASK) == 0 || target->transport_offline) ret = SUCCESS; + else if (target->transport_offline) + ret = FAST_IO_FAIL; else ret = FAILED; srp_free_req(target, req, scmnd, 0); -- GitLab From 96fc248a4c6fe1e5ffac4903b39d2dd5cbe2dc9a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Jun 2013 14:51:26 +0200 Subject: [PATCH 2098/2900] IB/srp: Maintain a single connection per I_T nexus An SRP target is required to maintain a single connection between initiator and target. This means that if the 'add_target' attribute is used to create a second connection to a target, the first connection will be logged out and that the SCSI error handler will kick in. The SCSI error handler will cause the SRP initiator to reconnect, which will cause I/O over the second connection to fail. Avoid such ping-pong behavior by disabling relogins. If reconnecting manually is necessary, that is possible by deleting and recreating an rport via sysfs. Signed-off-by: Bart Van Assche Signed-off-by: Sebastian Riemer Acked-by: David Dillow Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 44 +++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 1f331011653e..830ef0037087 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -542,11 +542,11 @@ static void srp_remove_work(struct work_struct *work) WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED); + srp_remove_target(target); + spin_lock(&target->srp_host->target_lock); list_del(&target->list); spin_unlock(&target->srp_host->target_lock); - - srp_remove_target(target); } static void srp_rport_delete(struct srp_rport *rport) @@ -2009,6 +2009,36 @@ static struct class srp_class = { .dev_release = srp_release_dev }; +/** + * srp_conn_unique() - check whether the connection to a target is unique + */ +static bool srp_conn_unique(struct srp_host *host, + struct srp_target_port *target) +{ + struct srp_target_port *t; + bool ret = false; + + if (target->state == SRP_TARGET_REMOVED) + goto out; + + ret = true; + + spin_lock(&host->target_lock); + list_for_each_entry(t, &host->target_list, list) { + if (t != target && + target->id_ext == t->id_ext && + target->ioc_guid == t->ioc_guid && + target->initiator_ext == t->initiator_ext) { + ret = false; + break; + } + } + spin_unlock(&host->target_lock); + +out: + return ret; +} + /* * Target ports are added by writing * @@ -2265,6 +2295,16 @@ static ssize_t srp_create_target(struct device *dev, if (ret) goto err; + if (!srp_conn_unique(target->srp_host, target)) { + shost_printk(KERN_INFO, target->scsi_host, + PFX "Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx\n", + be64_to_cpu(target->id_ext), + be64_to_cpu(target->ioc_guid), + be64_to_cpu(target->initiator_ext)); + ret = -EEXIST; + goto err; + } + if (!host->srp_dev->fmr_pool && !target->allow_ext_sg && target->cmd_sg_cnt < target->sg_tablesize) { pr_warn("No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n"); -- GitLab From 4b5e5f41c8e114bb856347134657eb9e1cccc822 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 28 Jun 2013 14:57:42 +0200 Subject: [PATCH 2099/2900] IB/srp: Make HCA completion vector configurable Several InfiniBand HCAs allow configuring the completion vector per CQ. This allows spreading the workload created by IB completion interrupts over multiple MSI-X vectors and hence over multiple CPU cores. In other words, configuring the completion vector properly not only allows reducing latency on an initiator connected to multiple SRP targets but also allows improving throughput. Signed-off-by: Bart Van Assche Acked-by: David Dillow Signed-off-by: Roland Dreier --- Documentation/ABI/stable/sysfs-driver-ib_srp | 7 ++++++ drivers/infiniband/ulp/srp/ib_srp.c | 26 ++++++++++++++++++-- drivers/infiniband/ulp/srp/ib_srp.h | 1 + 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-driver-ib_srp b/Documentation/ABI/stable/sysfs-driver-ib_srp index 481aae95c7d1..5c53d28f775c 100644 --- a/Documentation/ABI/stable/sysfs-driver-ib_srp +++ b/Documentation/ABI/stable/sysfs-driver-ib_srp @@ -54,6 +54,13 @@ Description: Interface for making ib_srp connect to a new target. ib_srp. Specifying a value that exceeds cmd_sg_entries is only safe with partial memory descriptor list support enabled (allow_ext_sg=1). + * comp_vector, a number in the range 0..n-1 specifying the + MSI-X completion vector. Some HCA's allocate multiple (n) + MSI-X vectors per HCA port. If the IRQ affinity masks of + these interrupts have been configured such that each MSI-X + interrupt is handled by a different CPU then the comp_vector + parameter can be used to spread the SRP completion workload + over multiple CPU's. What: /sys/class/infiniband_srp/srp--/ibdev Date: January 2, 2006 diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 830ef0037087..9b30366cb017 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -231,14 +231,16 @@ static int srp_create_target_ib(struct srp_target_port *target) return -ENOMEM; recv_cq = ib_create_cq(target->srp_host->srp_dev->dev, - srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0); + srp_recv_completion, NULL, target, SRP_RQ_SIZE, + target->comp_vector); if (IS_ERR(recv_cq)) { ret = PTR_ERR(recv_cq); goto err; } send_cq = ib_create_cq(target->srp_host->srp_dev->dev, - srp_send_completion, NULL, target, SRP_SQ_SIZE, 0); + srp_send_completion, NULL, target, SRP_SQ_SIZE, + target->comp_vector); if (IS_ERR(send_cq)) { ret = PTR_ERR(send_cq); goto err_recv_cq; @@ -1898,6 +1900,14 @@ static ssize_t show_local_ib_device(struct device *dev, return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name); } +static ssize_t show_comp_vector(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct srp_target_port *target = host_to_target(class_to_shost(dev)); + + return sprintf(buf, "%d\n", target->comp_vector); +} + static ssize_t show_cmd_sg_entries(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1924,6 +1934,7 @@ static DEVICE_ATTR(req_lim, S_IRUGO, show_req_lim, NULL); static DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); static DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); +static DEVICE_ATTR(comp_vector, S_IRUGO, show_comp_vector, NULL); static DEVICE_ATTR(cmd_sg_entries, S_IRUGO, show_cmd_sg_entries, NULL); static DEVICE_ATTR(allow_ext_sg, S_IRUGO, show_allow_ext_sg, NULL); @@ -1938,6 +1949,7 @@ static struct device_attribute *srp_host_attrs[] = { &dev_attr_zero_req_lim, &dev_attr_local_ib_port, &dev_attr_local_ib_device, + &dev_attr_comp_vector, &dev_attr_cmd_sg_entries, &dev_attr_allow_ext_sg, NULL @@ -2061,6 +2073,7 @@ enum { SRP_OPT_CMD_SG_ENTRIES = 1 << 9, SRP_OPT_ALLOW_EXT_SG = 1 << 10, SRP_OPT_SG_TABLESIZE = 1 << 11, + SRP_OPT_COMP_VECTOR = 1 << 12, SRP_OPT_ALL = (SRP_OPT_ID_EXT | SRP_OPT_IOC_GUID | SRP_OPT_DGID | @@ -2081,6 +2094,7 @@ static const match_table_t srp_opt_tokens = { { SRP_OPT_CMD_SG_ENTRIES, "cmd_sg_entries=%u" }, { SRP_OPT_ALLOW_EXT_SG, "allow_ext_sg=%u" }, { SRP_OPT_SG_TABLESIZE, "sg_tablesize=%u" }, + { SRP_OPT_COMP_VECTOR, "comp_vector=%u" }, { SRP_OPT_ERR, NULL } }; @@ -2236,6 +2250,14 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target) target->sg_tablesize = token; break; + case SRP_OPT_COMP_VECTOR: + if (match_int(args, &token) || token < 0) { + pr_warn("bad comp_vector parameter '%s'\n", p); + goto out; + } + target->comp_vector = token; + break; + default: pr_warn("unknown parameter or missing value '%s' in target creation request\n", p); diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index 66fbedda4571..e641088c14dc 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h @@ -156,6 +156,7 @@ struct srp_target_port { char target_name[32]; unsigned int scsi_id; unsigned int sg_tablesize; + int comp_vector; struct ib_sa_path_rec path; __be16 orig_dgid[8]; -- GitLab From e8ca413558de8ea235a1223074c4ed09616b9034 Mon Sep 17 00:00:00 2001 From: Vu Pham Date: Fri, 28 Jun 2013 14:59:08 +0200 Subject: [PATCH 2100/2900] IB/srp: Bump driver version and release date Signed-off-by: Vu Pham Signed-off-by: Bart Van Assche Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9b30366cb017..9d8b46eafdb2 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -53,8 +53,8 @@ #define DRV_NAME "ib_srp" #define PFX DRV_NAME ": " -#define DRV_VERSION "0.2" -#define DRV_RELDATE "November 1, 2005" +#define DRV_VERSION "1.0" +#define DRV_RELDATE "July 1, 2013" MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator " -- GitLab From b01978cacfd7e3a4ca703b0e48f2e18de8865df5 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 27 Jun 2013 19:05:21 +0300 Subject: [PATCH 2101/2900] net/mlx4_core: Dynamic VST to VST vlan/qos changes Within VST mode, enable modifying the vlan and/or qos for a VF without requiring unbind/rebind. This requires firmware which supports the UPDATE_QP command. (If the command is not available, we fall back to requiring unbind/bind to activate these changes). To avoid race conditions with modify-qp on QPs that are affected by update-qp, this operation is performed on the comm_wq. If the update operation succeeds for all the necessary QPs, a vlan_unregister is performed for the abandoned vlan id. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 122 ++++++++++++++- drivers/net/ethernet/mellanox/mlx4/fw.c | 5 +- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 20 +++ .../ethernet/mellanox/mlx4/resource_tracker.c | 145 +++++++++++++++++- include/linux/mlx4/cmd.h | 1 + include/linux/mlx4/device.h | 3 +- include/linux/mlx4/qp.h | 34 ++++ 7 files changed, 319 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index df04c8206ebe..7b927891dc35 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -112,6 +112,14 @@ enum { GO_BIT_TIMEOUT_MSECS = 10000 }; +enum mlx4_vlan_transition { + MLX4_VLAN_TRANSITION_VST_VST = 0, + MLX4_VLAN_TRANSITION_VST_VGT = 1, + MLX4_VLAN_TRANSITION_VGT_VST = 2, + MLX4_VLAN_TRANSITION_VGT_VGT = 3, +}; + + struct mlx4_cmd_context { struct completion done; int result; @@ -792,6 +800,15 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave, vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); } +int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, + struct mlx4_vhcr *vhcr, + struct mlx4_cmd_mailbox *inbox, + struct mlx4_cmd_mailbox *outbox, + struct mlx4_cmd_info *cmd) +{ + return -EPERM; +} + int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -1225,6 +1242,15 @@ static struct mlx4_cmd_info cmd_info[] = { .verify = NULL, .wrapper = mlx4_GEN_QP_wrapper }, + { + .opcode = MLX4_CMD_UPDATE_QP, + .has_inbox = false, + .has_outbox = false, + .out_is_imm = false, + .encode_slave_id = false, + .verify = NULL, + .wrapper = MLX4_CMD_UPDATE_QP_wrapper + }, { .opcode = MLX4_CMD_CONF_SPECIAL_QP, .has_inbox = false, @@ -1495,6 +1521,72 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, return ret; } + +int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, + int slave, int port) +{ + struct mlx4_vport_oper_state *vp_oper; + struct mlx4_vport_state *vp_admin; + struct mlx4_vf_immed_vlan_work *work; + int err; + int admin_vlan_ix = NO_INDX; + + vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; + vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; + + if (vp_oper->state.default_vlan == vp_admin->default_vlan && + vp_oper->state.default_qos == vp_admin->default_qos) + return 0; + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (!work) + return -ENOMEM; + + if (vp_oper->state.default_vlan != vp_admin->default_vlan) { + err = __mlx4_register_vlan(&priv->dev, port, + vp_admin->default_vlan, + &admin_vlan_ix); + if (err) { + mlx4_warn((&priv->dev), + "No vlan resources slave %d, port %d\n", + slave, port); + return err; + } + work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN; + mlx4_dbg((&(priv->dev)), + "alloc vlan %d idx %d slave %d port %d\n", + (int)(vp_admin->default_vlan), + admin_vlan_ix, slave, port); + } + + /* save original vlan ix and vlan id */ + work->orig_vlan_id = vp_oper->state.default_vlan; + work->orig_vlan_ix = vp_oper->vlan_idx; + + /* handle new qos */ + if (vp_oper->state.default_qos != vp_admin->default_qos) + work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS; + + if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN) + vp_oper->vlan_idx = admin_vlan_ix; + + vp_oper->state.default_vlan = vp_admin->default_vlan; + vp_oper->state.default_qos = vp_admin->default_qos; + + /* iterate over QPs owned by this slave, using UPDATE_QP */ + work->port = port; + work->slave = slave; + work->qos = vp_oper->state.default_qos; + work->vlan_id = vp_oper->state.default_vlan; + work->vlan_ix = vp_oper->vlan_idx; + work->priv = priv; + INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler); + queue_work(priv->mfunc.master.comm_wq, &work->work); + + return 0; +} + + static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave) { int port, err; @@ -2109,11 +2201,18 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) } EXPORT_SYMBOL_GPL(mlx4_set_vf_mac); +static int calculate_transition(u16 oper_vlan, u16 admin_vlan) +{ + return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT)); +} + int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) { struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_vport_state *s_info; + struct mlx4_vport_oper_state *vf_oper; + struct mlx4_vport_state *vf_admin; int slave; + enum mlx4_vlan_transition vlan_trans; if ((!mlx4_is_master(dev)) || !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL)) @@ -2126,12 +2225,25 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) if (slave < 0) return -EINVAL; - s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; + vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; + vf_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; + if ((0 == vlan) && (0 == qos)) - s_info->default_vlan = MLX4_VGT; + vf_admin->default_vlan = MLX4_VGT; else - s_info->default_vlan = vlan; - s_info->default_qos = qos; + vf_admin->default_vlan = vlan; + vf_admin->default_qos = qos; + + vlan_trans = calculate_transition(vf_oper->state.default_vlan, + vf_admin->default_vlan); + + if (priv->mfunc.master.slave_state[slave].active && + dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP && + vlan_trans == MLX4_VLAN_TRANSITION_VST_VST) { + mlx4_info(dev, "updating vf %d port %d config params immediately\n", + vf, port); + mlx4_master_immediate_activate_vlan_qos(priv, slave, port); + } return 0; } EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 569bbe3e7403..8873d6802c80 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -133,7 +133,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [4] = "Automatic MAC reassignment support", [5] = "Time stamping support", [6] = "VST (control vlan insertion/stripping) support", - [7] = "FSM (MAC anti-spoofing) support" + [7] = "FSM (MAC anti-spoofing) support", + [8] = "Dynamic QP updates support" }; int i; @@ -659,6 +660,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) QUERY_DEV_CAP_MAX_COUNTERS_OFFSET); MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); + if (field32 & (1 << 16)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; if (field32 & (1 << 26)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL; if (field32 & (1 << 20)) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 75272935a3f7..5abcb6501e30 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -571,6 +571,24 @@ struct mlx4_cmd { u8 comm_toggle; }; +enum { + MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0, + MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1, +}; +struct mlx4_vf_immed_vlan_work { + struct work_struct work; + struct mlx4_priv *priv; + int flags; + int slave; + int vlan_ix; + int orig_vlan_ix; + u8 port; + u8 qos; + u16 vlan_id; + u16 orig_vlan_id; +}; + + struct mlx4_uar_table { struct mlx4_bitmap bitmap; }; @@ -1218,4 +1236,6 @@ static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev) #define NOT_MASKED_PD_BITS 17 +void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work); + #endif /* MLX4_H */ diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 1157f028a90f..46323a20060c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -101,6 +101,8 @@ struct res_qp { spinlock_t mcg_spl; int local_qpn; atomic_t ref_count; + u32 qpc_flags; + u8 sched_queue; }; enum res_mtt_states { @@ -355,7 +357,7 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, static int update_vport_qp_param(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, - u8 slave) + u8 slave, u32 qpn) { struct mlx4_qp_context *qpc = inbox->buf + 8; struct mlx4_vport_oper_state *vp_oper; @@ -369,9 +371,17 @@ static int update_vport_qp_param(struct mlx4_dev *dev, if (MLX4_VGT != vp_oper->state.default_vlan) { qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff; - if (MLX4_QP_ST_RC == qp_type) + if (MLX4_QP_ST_RC == qp_type || + (MLX4_QP_ST_UD == qp_type && + !mlx4_is_qp_reserved(dev, qpn))) return -EINVAL; + /* the reserved QPs (special, proxy, tunnel) + * do not operate over vlans + */ + if (mlx4_is_qp_reserved(dev, qpn)) + return 0; + /* force strip vlan by clear vsd */ qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); if (0 != vp_oper->state.default_vlan) { @@ -2114,6 +2124,8 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, if (err) return err; qp->local_qpn = local_qpn; + qp->sched_queue = 0; + qp->qpc_flags = be32_to_cpu(qpc->flags); err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); if (err) @@ -2836,6 +2848,9 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, { int err; struct mlx4_qp_context *qpc = inbox->buf + 8; + int qpn = vhcr->in_modifier & 0x7fffff; + struct res_qp *qp; + u8 orig_sched_queue; err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave); if (err) @@ -2844,11 +2859,30 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, update_pkey_index(dev, slave, inbox); update_gid(dev, inbox, (u8)slave); adjust_proxy_tun_qkey(dev, vhcr, qpc); - err = update_vport_qp_param(dev, inbox, slave); + orig_sched_queue = qpc->pri_path.sched_queue; + err = update_vport_qp_param(dev, inbox, slave, qpn); if (err) return err; - return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd); + err = get_res(dev, slave, qpn, RES_QP, &qp); + if (err) + return err; + if (qp->com.from_state != RES_QP_HW) { + err = -EBUSY; + goto out; + } + + err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); +out: + /* if no error, save sched queue value passed in by VF. This is + * essentially the QOS value provided by the VF. This will be useful + * if we allow dynamic changes from VST back to VGT + */ + if (!err) + qp->sched_queue = orig_sched_queue; + + put_res(dev, slave, qpn, RES_QP); + return err; } int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave, @@ -3932,3 +3966,106 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) rem_slave_xrcdns(dev, slave); mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); } + +void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) +{ + struct mlx4_vf_immed_vlan_work *work = + container_of(_work, struct mlx4_vf_immed_vlan_work, work); + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_update_qp_context *upd_context; + struct mlx4_dev *dev = &work->priv->dev; + struct mlx4_resource_tracker *tracker = + &work->priv->mfunc.master.res_tracker; + struct list_head *qp_list = + &tracker->slave_list[work->slave].res_list[RES_QP]; + struct res_qp *qp; + struct res_qp *tmp; + u64 qp_mask = ((1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED) | + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P) | + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED) | + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED) | + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P) | + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED) | + (1ULL << MLX4_UPD_QP_PATH_MASK_VLAN_INDEX) | + (1ULL << MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE)); + + int err; + int port, errors = 0; + u8 vlan_control; + + if (mlx4_is_slave(dev)) { + mlx4_warn(dev, "Trying to update-qp in slave %d\n", + work->slave); + goto out; + } + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + goto out; + + if (!work->vlan_id) + vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; + else + vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED; + + upd_context = mailbox->buf; + upd_context->primary_addr_path_mask = cpu_to_be64(qp_mask); + upd_context->qp_context.pri_path.vlan_control = vlan_control; + upd_context->qp_context.pri_path.vlan_index = work->vlan_ix; + + spin_lock_irq(mlx4_tlock(dev)); + list_for_each_entry_safe(qp, tmp, qp_list, com.list) { + spin_unlock_irq(mlx4_tlock(dev)); + if (qp->com.owner == work->slave) { + if (qp->com.from_state != RES_QP_HW || + !qp->sched_queue || /* no INIT2RTR trans yet */ + mlx4_is_qp_reserved(dev, qp->local_qpn) || + qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)) { + spin_lock_irq(mlx4_tlock(dev)); + continue; + } + port = (qp->sched_queue >> 6 & 1) + 1; + if (port != work->port) { + spin_lock_irq(mlx4_tlock(dev)); + continue; + } + upd_context->qp_context.pri_path.sched_queue = + qp->sched_queue & 0xC7; + upd_context->qp_context.pri_path.sched_queue |= + ((work->qos & 0x7) << 3); + + err = mlx4_cmd(dev, mailbox->dma, + qp->local_qpn & 0xffffff, + 0, MLX4_CMD_UPDATE_QP, + MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE); + if (err) { + mlx4_info(dev, "UPDATE_QP failed for slave %d, " + "port %d, qpn %d (%d)\n", + work->slave, port, qp->local_qpn, + err); + errors++; + } + } + spin_lock_irq(mlx4_tlock(dev)); + } + spin_unlock_irq(mlx4_tlock(dev)); + mlx4_free_cmd_mailbox(dev, mailbox); + + if (errors) + mlx4_err(dev, "%d UPDATE_QP failures for slave %d, port %d\n", + errors, work->slave, work->port); + + /* unregister previous vlan_id if needed and we had no errors + * while updating the QPs + */ + if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors && + NO_INDX != work->orig_vlan_ix) + __mlx4_unregister_vlan(&work->priv->dev, work->port, + work->orig_vlan_ix); +out: + kfree(work); + return; +} diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h index 8074a9711cf1..bb1c8096a7eb 100644 --- a/include/linux/mlx4/cmd.h +++ b/include/linux/mlx4/cmd.h @@ -111,6 +111,7 @@ enum { MLX4_CMD_INIT2INIT_QP = 0x2d, MLX4_CMD_SUSPEND_QP = 0x32, MLX4_CMD_UNSUSPEND_QP = 0x33, + MLX4_CMD_UPDATE_QP = 0x61, /* special QP and management commands */ MLX4_CMD_CONF_SPECIAL_QP = 0x23, MLX4_CMD_MAD_IFC = 0x24, diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index a51b0134ce18..52c23a892bab 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -157,7 +157,8 @@ enum { MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN = 1LL << 4, MLX4_DEV_CAP_FLAG2_TS = 1LL << 5, MLX4_DEV_CAP_FLAG2_VLAN_CONTROL = 1LL << 6, - MLX4_DEV_CAP_FLAG2_FSM = 1LL << 7 + MLX4_DEV_CAP_FLAG2_FSM = 1LL << 7, + MLX4_DEV_CAP_FLAG2_UPDATE_QP = 1LL << 8 }; enum { diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 352eec9df1b8..f43e32aa054a 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h @@ -206,6 +206,40 @@ struct mlx4_qp_context { u32 reserved5[10]; }; +struct mlx4_update_qp_context { + __be64 qp_mask; + __be64 primary_addr_path_mask; + __be64 secondary_addr_path_mask; + u64 reserved1; + struct mlx4_qp_context qp_context; + u64 reserved2[58]; +}; + +enum { + MLX4_UPD_QP_MASK_PM_STATE = 32, + MLX4_UPD_QP_MASK_VSD = 33, +}; + +enum { + MLX4_UPD_QP_PATH_MASK_PKEY_INDEX = 0 + 32, + MLX4_UPD_QP_PATH_MASK_FSM = 1 + 32, + MLX4_UPD_QP_PATH_MASK_MAC_INDEX = 2 + 32, + MLX4_UPD_QP_PATH_MASK_FVL = 3 + 32, + MLX4_UPD_QP_PATH_MASK_CV = 4 + 32, + MLX4_UPD_QP_PATH_MASK_VLAN_INDEX = 5 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN = 6 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED = 7 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P = 8 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED = 9 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED = 10 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P = 11 + 32, + MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED = 12 + 32, + MLX4_UPD_QP_PATH_MASK_FEUP = 13 + 32, + MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE = 14 + 32, + MLX4_UPD_QP_PATH_MASK_IF_COUNTER_INDEX = 15 + 32, + MLX4_UPD_QP_PATH_MASK_FVL_RX = 16 + 32, +}; + enum { /* param3 */ MLX4_STRIP_VLAN = 1 << 30 }; -- GitLab From 0a6eac24583848490e9a9c02daef5e33c997431f Mon Sep 17 00:00:00 2001 From: Rony Efraim Date: Thu, 27 Jun 2013 19:05:22 +0300 Subject: [PATCH 2102/2900] net/mlx4_core: Add HW enforcement to VF link state When the firmware supports the UPDATE_QP command, if the VF link is disabled, block all QPs opened by the VF, by programming the UPDATE_QP command to drop all RX & TX traffic to/from these QPs. Operates only in VST mode. Signed-off-by: Rony Efraim Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 57 ++++++++++++------- drivers/net/ethernet/mellanox/mlx4/mlx4.h | 1 + .../ethernet/mellanox/mlx4/resource_tracker.c | 22 ++++++- include/linux/mlx4/qp.h | 2 + 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 7b927891dc35..707a7d0d08e1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1521,6 +1521,10 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, return ret; } +static int calculate_transition(u16 oper_vlan, u16 admin_vlan) +{ + return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT)); +} int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, int slave, int port) @@ -1528,16 +1532,37 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, struct mlx4_vport_oper_state *vp_oper; struct mlx4_vport_state *vp_admin; struct mlx4_vf_immed_vlan_work *work; + struct mlx4_dev *dev = &(priv->dev); int err; int admin_vlan_ix = NO_INDX; + enum mlx4_vlan_transition vlan_trans; vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; if (vp_oper->state.default_vlan == vp_admin->default_vlan && - vp_oper->state.default_qos == vp_admin->default_qos) + vp_oper->state.default_qos == vp_admin->default_qos && + vp_oper->state.link_state == vp_admin->link_state) return 0; + vlan_trans = calculate_transition(vp_oper->state.default_vlan, + vp_admin->default_vlan); + + if (!(priv->mfunc.master.slave_state[slave].active && + dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP && + vlan_trans == MLX4_VLAN_TRANSITION_VST_VST)) { + /* even if the UPDATE_QP command isn't supported, we still want + * to set this VF link according to the admin directive + */ + vp_oper->state.link_state = vp_admin->link_state; + return -1; + } + + mlx4_dbg(dev, "updating immediately admin params slave %d port %d\n", + slave, port); + mlx4_dbg(dev, "vlan %d QoS %d link down %d\n", vp_admin->default_vlan, + vp_admin->default_qos, vp_admin->link_state); + work = kzalloc(sizeof(*work), GFP_KERNEL); if (!work) return -ENOMEM; @@ -1572,6 +1597,10 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, vp_oper->state.default_vlan = vp_admin->default_vlan; vp_oper->state.default_qos = vp_admin->default_qos; + vp_oper->state.link_state = vp_admin->link_state; + + if (vp_admin->link_state == IFLA_VF_LINK_STATE_DISABLE) + work->flags |= MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE; /* iterate over QPs owned by this slave, using UPDATE_QP */ work->port = port; @@ -2201,10 +2230,6 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) } EXPORT_SYMBOL_GPL(mlx4_set_vf_mac); -static int calculate_transition(u16 oper_vlan, u16 admin_vlan) -{ - return (2 * (oper_vlan == MLX4_VGT) + (admin_vlan == MLX4_VGT)); -} int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) { @@ -2212,7 +2237,6 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) struct mlx4_vport_oper_state *vf_oper; struct mlx4_vport_state *vf_admin; int slave; - enum mlx4_vlan_transition vlan_trans; if ((!mlx4_is_master(dev)) || !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL)) @@ -2234,16 +2258,10 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) vf_admin->default_vlan = vlan; vf_admin->default_qos = qos; - vlan_trans = calculate_transition(vf_oper->state.default_vlan, - vf_admin->default_vlan); - - if (priv->mfunc.master.slave_state[slave].active && - dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP && - vlan_trans == MLX4_VLAN_TRANSITION_VST_VST) { - mlx4_info(dev, "updating vf %d port %d config params immediately\n", + if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) + mlx4_info(dev, + "updating vf %d port %d config will take effect on next VF restart\n", vf, port); - mlx4_master_immediate_activate_vlan_qos(priv, slave, port); - } return 0; } EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan); @@ -2307,7 +2325,6 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_vport_state *s_info; - struct mlx4_vport_oper_state *vp_oper; int slave; u8 link_stat_event; @@ -2337,14 +2354,16 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat link_state, slave, port); return -EINVAL; }; - /* update the admin & oper state on the link state */ s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; - vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; s_info->link_state = link_state; - vp_oper->state.link_state = link_state; /* send event */ mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event); + + if (mlx4_master_immediate_activate_vlan_qos(priv, slave, port)) + mlx4_dbg(dev, + "updating vf %d port %d no link state HW enforcment\n", + vf, port); return 0; } EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 5abcb6501e30..17d9277e33ef 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -574,6 +574,7 @@ struct mlx4_cmd { enum { MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0, MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1, + MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE = 1 << 2, }; struct mlx4_vf_immed_vlan_work { struct work_struct work; diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 46323a20060c..f984a89c27df 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -384,7 +384,17 @@ static int update_vport_qp_param(struct mlx4_dev *dev, /* force strip vlan by clear vsd */ qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); - if (0 != vp_oper->state.default_vlan) { + + if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE && + dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) { + qpc->pri_path.vlan_control = + MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | + MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED | + MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; + } else if (0 != vp_oper->state.default_vlan) { qpc->pri_path.vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | @@ -4002,8 +4012,14 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) goto out; - - if (!work->vlan_id) + if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_LINK_DISABLE) /* block all */ + vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | + MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED | + MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED | + MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; + else if (!work->vlan_id) vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; else diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index f43e32aa054a..262deac02c9e 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h @@ -152,6 +152,8 @@ enum { /* fl */ }; enum { /* vlan_control */ MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED = 1 << 6, + MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED = 1 << 5, /* 802.1p priority tag */ + MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED = 1 << 4, MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED = 1 << 2, MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1, /* 802.1p priority tag */ MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED = 1 << 0 -- GitLab From ef0cc4b1d296ce041e3b24d103177dd70642740c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:13 +0200 Subject: [PATCH 2103/2900] alx: treat flow control correctly in alx_set_pauseparam() Even when alx_setup_speed_duplex() is called, we still need to call alx_cfg_mac_flowcontrol() and set hw->flowctrl if flow control changed. This was a bug I accidentally introduced while simplifying the original driver. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 6fa2aec2bc81..50a91d012bce 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -187,7 +187,8 @@ static int alx_set_pauseparam(struct net_device *netdev, if (reconfig_phy) { err = alx_setup_speed_duplex(hw, hw->adv_cfg, fc); - return err; + if (err) + return err; } /* flow control on mac */ -- GitLab From 17fdd35268f3856702dae5c3c0d8f756ec2c6d2d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:14 +0200 Subject: [PATCH 2104/2900] alx: fix 100mbit/half duplex speed translation 100mbit half duplex is ADVERTISED_100baseT_Half, not ADVERTISED_10baseT_Half. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/alx/hw.c b/drivers/net/ethernet/atheros/alx/hw.c index 220a16ad0e49..dc71cfb6ce61 100644 --- a/drivers/net/ethernet/atheros/alx/hw.c +++ b/drivers/net/ethernet/atheros/alx/hw.c @@ -1134,7 +1134,7 @@ static inline u32 alx_speed_to_ethadv(int speed) case SPEED_100 + DUPLEX_FULL: return ADVERTISED_100baseT_Full; case SPEED_100 + DUPLEX_HALF: - return ADVERTISED_10baseT_Half; + return ADVERTISED_100baseT_Half; case SPEED_10 + DUPLEX_FULL: return ADVERTISED_10baseT_Full; case SPEED_10 + DUPLEX_HALF: -- GitLab From c43861d35a73cfc86ae0506b60e73852849bca6a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:15 +0200 Subject: [PATCH 2105/2900] alx: remove NET_CORE Kconfig select That select doesn't make any sense, remove it. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig index 39e8d6cc8843..58ad37c733bc 100644 --- a/drivers/net/ethernet/atheros/Kconfig +++ b/drivers/net/ethernet/atheros/Kconfig @@ -67,7 +67,6 @@ config ALX tristate "Qualcomm Atheros AR816x/AR817x support" depends on PCI select CRC32 - select NET_CORE select MDIO help This driver supports the Qualcomm Atheros L1F ethernet adapter, -- GitLab From 4a134c39db2d9d6f31c55e7c3773fc33189c9320 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:16 +0200 Subject: [PATCH 2106/2900] alx: make sizes unsigned The ring sizes should be unsigned, pointed out by Ben Hutchings. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/alx.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h index 50b3ae2b143d..d71103dbf2cd 100644 --- a/drivers/net/ethernet/atheros/alx/alx.h +++ b/drivers/net/ethernet/atheros/alx/alx.h @@ -85,16 +85,16 @@ struct alx_priv { struct { dma_addr_t dma; void *virt; - int size; + unsigned int size; } descmem; /* protect int_mask updates */ spinlock_t irq_lock; u32 int_mask; - int tx_ringsz; - int rx_ringsz; - int rxbuf_size; + unsigned int tx_ringsz; + unsigned int rx_ringsz; + unsigned int rxbuf_size; struct napi_struct napi; struct alx_tx_queue txq; -- GitLab From a5b87cc9e0538bf6680d431e0076d778e5bae38e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:17 +0200 Subject: [PATCH 2107/2900] alx: separate link speed/duplex fields As suggested by Ben Hutchings, use separate fields to track current link speed and duplex setting. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/ethtool.c | 31 +---- drivers/net/ethernet/atheros/alx/hw.c | 139 +++++++++------------ drivers/net/ethernet/atheros/alx/hw.h | 24 +++- drivers/net/ethernet/atheros/alx/main.c | 37 +++--- 4 files changed, 106 insertions(+), 125 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 50a91d012bce..5e19e08b691b 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -85,14 +85,8 @@ static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) } } - if (hw->link_speed != SPEED_UNKNOWN) { - ethtool_cmd_speed_set(ecmd, - hw->link_speed - hw->link_speed % 10); - ecmd->duplex = hw->link_speed % 10; - } else { - ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); - ecmd->duplex = DUPLEX_UNKNOWN; - } + ethtool_cmd_speed_set(ecmd, hw->link_speed); + ecmd->duplex = hw->duplex; return 0; } @@ -110,24 +104,11 @@ static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return -EINVAL; adv_cfg = ecmd->advertising | ADVERTISED_Autoneg; } else { - int speed = ethtool_cmd_speed(ecmd); - - switch (speed + ecmd->duplex) { - case SPEED_10 + DUPLEX_HALF: - adv_cfg = ADVERTISED_10baseT_Half; - break; - case SPEED_10 + DUPLEX_FULL: - adv_cfg = ADVERTISED_10baseT_Full; - break; - case SPEED_100 + DUPLEX_HALF: - adv_cfg = ADVERTISED_100baseT_Half; - break; - case SPEED_100 + DUPLEX_FULL: - adv_cfg = ADVERTISED_100baseT_Full; - break; - default: + adv_cfg = alx_speed_to_ethadv(ethtool_cmd_speed(ecmd), + ecmd->duplex); + + if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full) return -EINVAL; - } } hw->adv_cfg = adv_cfg; diff --git a/drivers/net/ethernet/atheros/alx/hw.c b/drivers/net/ethernet/atheros/alx/hw.c index dc71cfb6ce61..aed48a7f1ca6 100644 --- a/drivers/net/ethernet/atheros/alx/hw.c +++ b/drivers/net/ethernet/atheros/alx/hw.c @@ -624,12 +624,12 @@ void alx_start_mac(struct alx_hw *hw) alx_write_mem32(hw, ALX_TXQ0, txq | ALX_TXQ0_EN); mac = hw->rx_ctrl; - if (hw->link_speed % 10 == DUPLEX_FULL) + if (hw->duplex == DUPLEX_FULL) mac |= ALX_MAC_CTRL_FULLD; else mac &= ~ALX_MAC_CTRL_FULLD; ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED, - hw->link_speed >= SPEED_1000 ? ALX_MAC_CTRL_SPEED_1000 : + hw->link_speed == SPEED_1000 ? ALX_MAC_CTRL_SPEED_1000 : ALX_MAC_CTRL_SPEED_10_100); mac |= ALX_MAC_CTRL_TX_EN | ALX_MAC_CTRL_RX_EN; hw->rx_ctrl = mac; @@ -790,28 +790,22 @@ void alx_post_phy_link(struct alx_hw *hw) u16 phy_val, len, agc; u8 revid = alx_hw_revision(hw); bool adj_th = revid == ALX_REV_B0; - int speed; - - if (hw->link_speed == SPEED_UNKNOWN) - speed = SPEED_UNKNOWN; - else - speed = hw->link_speed - hw->link_speed % 10; if (revid != ALX_REV_B0 && !alx_is_rev_a(revid)) return; /* 1000BT/AZ, wrong cable length */ - if (speed != SPEED_UNKNOWN) { + if (hw->link_speed != SPEED_UNKNOWN) { alx_read_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL6, &phy_val); len = ALX_GET_FIELD(phy_val, ALX_CLDCTRL6_CAB_LEN); alx_read_phy_dbg(hw, ALX_MIIDBG_AGC, &phy_val); agc = ALX_GET_FIELD(phy_val, ALX_AGC_2_VGA); - if ((speed == SPEED_1000 && + if ((hw->link_speed == SPEED_1000 && (len > ALX_CLDCTRL6_CAB_LEN_SHORT1G || (len == 0 && agc > ALX_AGC_LONG1G_LIMT))) || - (speed == SPEED_100 && + (hw->link_speed == SPEED_100 && (len > ALX_CLDCTRL6_CAB_LEN_SHORT100M || (len == 0 && agc > ALX_AGC_LONG100M_LIMT)))) { alx_write_phy_dbg(hw, ALX_MIIDBG_AZ_ANADECT, @@ -831,10 +825,10 @@ void alx_post_phy_link(struct alx_hw *hw) /* threshold adjust */ if (adj_th && hw->lnk_patch) { - if (speed == SPEED_100) { + if (hw->link_speed == SPEED_100) { alx_write_phy_dbg(hw, ALX_MIIDBG_MSE16DB, ALX_MSE16DB_UP); - } else if (speed == SPEED_1000) { + } else if (hw->link_speed == SPEED_1000) { /* * Giga link threshold, raise the tolerance of * noise 50% @@ -869,7 +863,7 @@ void alx_post_phy_link(struct alx_hw *hw) * 1. phy link must be established before calling this function * 2. wol option (pattern,magic,link,etc.) is configed before call it. */ -int alx_pre_suspend(struct alx_hw *hw, int speed) +int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex) { u32 master, mac, phy, val; int err = 0; @@ -897,9 +891,9 @@ int alx_pre_suspend(struct alx_hw *hw, int speed) mac |= ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_BRD_EN; if (hw->sleep_ctrl & ALX_SLEEP_CIFS) mac |= ALX_MAC_CTRL_TX_EN; - if (speed % 10 == DUPLEX_FULL) + if (duplex == DUPLEX_FULL) mac |= ALX_MAC_CTRL_FULLD; - if (speed >= SPEED_1000) + if (speed == SPEED_1000) ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED, ALX_MAC_CTRL_SPEED_1000); phy |= ALX_PHY_CTRL_DSPRST_OUT; @@ -938,7 +932,7 @@ bool alx_phy_configured(struct alx_hw *hw) return cfg == hw_cfg; } -int alx_get_phy_link(struct alx_hw *hw, int *speed) +int alx_read_phy_link(struct alx_hw *hw) { struct pci_dev *pdev = hw->pdev; u16 bmsr, giga; @@ -953,7 +947,8 @@ int alx_get_phy_link(struct alx_hw *hw, int *speed) return err; if (!(bmsr & BMSR_LSTATUS)) { - *speed = SPEED_UNKNOWN; + hw->link_speed = SPEED_UNKNOWN; + hw->duplex = DUPLEX_UNKNOWN; return 0; } @@ -967,20 +962,20 @@ int alx_get_phy_link(struct alx_hw *hw, int *speed) switch (giga & ALX_GIGA_PSSR_SPEED) { case ALX_GIGA_PSSR_1000MBS: - *speed = SPEED_1000; + hw->link_speed = SPEED_1000; break; case ALX_GIGA_PSSR_100MBS: - *speed = SPEED_100; + hw->link_speed = SPEED_100; break; case ALX_GIGA_PSSR_10MBS: - *speed = SPEED_10; + hw->link_speed = SPEED_10; break; default: goto wrong_speed; } - *speed += (giga & ALX_GIGA_PSSR_DPLX) ? DUPLEX_FULL : DUPLEX_HALF; - return 1; + hw->duplex = (giga & ALX_GIGA_PSSR_DPLX) ? DUPLEX_FULL : DUPLEX_HALF; + return 0; wrong_speed: dev_err(&pdev->dev, "invalid PHY speed/duplex: 0x%x\n", giga); @@ -1126,81 +1121,67 @@ void alx_configure_basic(struct alx_hw *hw) alx_write_mem32(hw, ALX_WRR, val); } -static inline u32 alx_speed_to_ethadv(int speed) -{ - switch (speed) { - case SPEED_1000 + DUPLEX_FULL: - return ADVERTISED_1000baseT_Full; - case SPEED_100 + DUPLEX_FULL: - return ADVERTISED_100baseT_Full; - case SPEED_100 + DUPLEX_HALF: - return ADVERTISED_100baseT_Half; - case SPEED_10 + DUPLEX_FULL: - return ADVERTISED_10baseT_Full; - case SPEED_10 + DUPLEX_HALF: - return ADVERTISED_10baseT_Half; - default: - return 0; - } -} - -int alx_select_powersaving_speed(struct alx_hw *hw, int *speed) +int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex) { - int i, err, spd; + int i, err; u16 lpa; - err = alx_get_phy_link(hw, &spd); - if (err < 0) + err = alx_read_phy_link(hw); + if (err) return err; - if (spd == SPEED_UNKNOWN) + if (hw->link_speed == SPEED_UNKNOWN) { + *speed = SPEED_UNKNOWN; + *duplex = DUPLEX_UNKNOWN; return 0; + } err = alx_read_phy_reg(hw, MII_LPA, &lpa); if (err) return err; if (!(lpa & LPA_LPACK)) { - *speed = spd; + *speed = hw->link_speed; return 0; } - if (lpa & LPA_10FULL) - *speed = SPEED_10 + DUPLEX_FULL; - else if (lpa & LPA_10HALF) - *speed = SPEED_10 + DUPLEX_HALF; - else if (lpa & LPA_100FULL) - *speed = SPEED_100 + DUPLEX_FULL; - else - *speed = SPEED_100 + DUPLEX_HALF; - - if (*speed != spd) { - err = alx_write_phy_reg(hw, ALX_MII_IER, 0); - if (err) - return err; - err = alx_setup_speed_duplex(hw, - alx_speed_to_ethadv(*speed) | - ADVERTISED_Autoneg, - ALX_FC_ANEG | ALX_FC_RX | - ALX_FC_TX); - if (err) - return err; + if (lpa & LPA_10FULL) { + *speed = SPEED_10; + *duplex = DUPLEX_FULL; + } else if (lpa & LPA_10HALF) { + *speed = SPEED_10; + *duplex = DUPLEX_HALF; + } else if (lpa & LPA_100FULL) { + *speed = SPEED_100; + *duplex = DUPLEX_FULL; + } else { + *speed = SPEED_100; + *duplex = DUPLEX_HALF; + } - /* wait for linkup */ - for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { - int speed2; + if (*speed == hw->link_speed && *duplex == hw->duplex) + return 0; + err = alx_write_phy_reg(hw, ALX_MII_IER, 0); + if (err) + return err; + err = alx_setup_speed_duplex(hw, alx_speed_to_ethadv(*speed, *duplex) | + ADVERTISED_Autoneg, ALX_FC_ANEG | + ALX_FC_RX | ALX_FC_TX); + if (err) + return err; - msleep(100); + /* wait for linkup */ + for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { + msleep(100); - err = alx_get_phy_link(hw, &speed2); - if (err < 0) - return err; - if (speed2 != SPEED_UNKNOWN) - break; - } - if (i == ALX_MAX_SETUP_LNK_CYCLE) - return -ETIMEDOUT; + err = alx_read_phy_link(hw); + if (err < 0) + return err; + if (hw->link_speed != SPEED_UNKNOWN) + break; } + if (i == ALX_MAX_SETUP_LNK_CYCLE) + return -ETIMEDOUT; return 0; } diff --git a/drivers/net/ethernet/atheros/alx/hw.h b/drivers/net/ethernet/atheros/alx/hw.h index 65e723d2172a..a60e35c1c1b5 100644 --- a/drivers/net/ethernet/atheros/alx/hw.h +++ b/drivers/net/ethernet/atheros/alx/hw.h @@ -412,10 +412,11 @@ struct alx_hw { u32 smb_timer; /* SPEED_* + DUPLEX_*, SPEED_UNKNOWN if link is down */ int link_speed; + u8 duplex; /* auto-neg advertisement or force mode config */ - u32 adv_cfg; u8 flowctrl; + u32 adv_cfg; u32 sleep_ctrl; @@ -478,12 +479,12 @@ void alx_reset_pcie(struct alx_hw *hw); void alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en); int alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl); void alx_post_phy_link(struct alx_hw *hw); -int alx_pre_suspend(struct alx_hw *hw, int speed); +int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex); int alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data); int alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data); int alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata); int alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data); -int alx_get_phy_link(struct alx_hw *hw, int *speed); +int alx_read_phy_link(struct alx_hw *hw); int alx_clear_phy_intr(struct alx_hw *hw); int alx_config_wol(struct alx_hw *hw); void alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc); @@ -493,7 +494,22 @@ void alx_set_macaddr(struct alx_hw *hw, const u8 *addr); bool alx_phy_configured(struct alx_hw *hw); void alx_configure_basic(struct alx_hw *hw); void alx_disable_rss(struct alx_hw *hw); -int alx_select_powersaving_speed(struct alx_hw *hw, int *speed); +int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex); bool alx_get_phy_info(struct alx_hw *hw); +static inline u32 alx_speed_to_ethadv(int speed, u8 duplex) +{ + if (speed == SPEED_1000 && duplex == DUPLEX_FULL) + return ADVERTISED_1000baseT_Full; + if (speed == SPEED_100 && duplex == DUPLEX_FULL) + return ADVERTISED_100baseT_Full; + if (speed == SPEED_100 && duplex== DUPLEX_HALF) + return ADVERTISED_100baseT_Half; + if (speed == SPEED_10 && duplex == DUPLEX_FULL) + return ADVERTISED_10baseT_Full; + if (speed == SPEED_10 && duplex == DUPLEX_HALF) + return ADVERTISED_10baseT_Half; + return 0; +} + #endif diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 418de8b13165..148b4b976474 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -712,6 +712,7 @@ static int alx_init_sw(struct alx_priv *alx) hw->dma_chnl = hw->max_dma_chnl; hw->ith_tpd = alx->tx_ringsz / 3; hw->link_speed = SPEED_UNKNOWN; + hw->duplex = DUPLEX_UNKNOWN; hw->adv_cfg = ADVERTISED_Autoneg | ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | @@ -758,6 +759,7 @@ static void alx_halt(struct alx_priv *alx) alx_netif_stop(alx); hw->link_speed = SPEED_UNKNOWN; + hw->duplex = DUPLEX_UNKNOWN; alx_reset_mac(hw); @@ -869,18 +871,18 @@ static void __alx_stop(struct alx_priv *alx) alx_free_rings(alx); } -static const char *alx_speed_desc(u16 speed) +static const char *alx_speed_desc(struct alx_hw *hw) { - switch (speed) { - case SPEED_1000 + DUPLEX_FULL: + switch (alx_speed_to_ethadv(hw->link_speed, hw->duplex)) { + case ADVERTISED_1000baseT_Full: return "1 Gbps Full"; - case SPEED_100 + DUPLEX_FULL: + case ADVERTISED_100baseT_Full: return "100 Mbps Full"; - case SPEED_100 + DUPLEX_HALF: + case ADVERTISED_100baseT_Half: return "100 Mbps Half"; - case SPEED_10 + DUPLEX_FULL: + case ADVERTISED_10baseT_Full: return "10 Mbps Full"; - case SPEED_10 + DUPLEX_HALF: + case ADVERTISED_10baseT_Half: return "10 Mbps Half"; default: return "Unknown speed"; @@ -891,7 +893,8 @@ static void alx_check_link(struct alx_priv *alx) { struct alx_hw *hw = &alx->hw; unsigned long flags; - int speed, old_speed; + int old_speed; + u8 old_duplex; int err; /* clear PHY internal interrupt status, otherwise the main @@ -899,7 +902,9 @@ static void alx_check_link(struct alx_priv *alx) */ alx_clear_phy_intr(hw); - err = alx_get_phy_link(hw, &speed); + old_speed = hw->link_speed; + old_duplex = hw->duplex; + err = alx_read_phy_link(hw); if (err < 0) goto reset; @@ -908,15 +913,12 @@ static void alx_check_link(struct alx_priv *alx) alx_write_mem32(hw, ALX_IMR, alx->int_mask); spin_unlock_irqrestore(&alx->irq_lock, flags); - old_speed = hw->link_speed; - - if (old_speed == speed) + if (old_speed == hw->link_speed) return; - hw->link_speed = speed; - if (speed != SPEED_UNKNOWN) { + if (hw->link_speed != SPEED_UNKNOWN) { netif_info(alx, link, alx->dev, - "NIC Up: %s\n", alx_speed_desc(speed)); + "NIC Up: %s\n", alx_speed_desc(hw)); alx_post_phy_link(hw); alx_enable_aspm(hw, true, true); alx_start_mac(hw); @@ -965,6 +967,7 @@ static int __alx_shutdown(struct pci_dev *pdev, bool *wol_en) struct net_device *netdev = alx->dev; struct alx_hw *hw = &alx->hw; int err, speed; + u8 duplex; netif_device_detach(netdev); @@ -977,13 +980,13 @@ static int __alx_shutdown(struct pci_dev *pdev, bool *wol_en) return err; #endif - err = alx_select_powersaving_speed(hw, &speed); + err = alx_select_powersaving_speed(hw, &speed, &duplex); if (err) return err; err = alx_clear_phy_intr(hw); if (err) return err; - err = alx_pre_suspend(hw, speed); + err = alx_pre_suspend(hw, speed, duplex); if (err) return err; err = alx_config_wol(hw); -- GitLab From 46ab9b347d677976b2b4072837cb4065839c0b80 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:18 +0200 Subject: [PATCH 2108/2900] alx: fix MAC address alignment problem In two places, parts of MAC addresses are used as u32/u16 values. This can cause alignment problems, use put_unaligned and get_unaligned to fix this. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/hw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/hw.c b/drivers/net/ethernet/atheros/alx/hw.c index aed48a7f1ca6..ea99e5d8743f 100644 --- a/drivers/net/ethernet/atheros/alx/hw.c +++ b/drivers/net/ethernet/atheros/alx/hw.c @@ -282,8 +282,8 @@ static bool alx_read_macaddr(struct alx_hw *hw, u8 *addr) mac1 = alx_read_mem32(hw, ALX_STAD1); /* addr should be big-endian */ - *(__be32 *)(addr + 2) = cpu_to_be32(mac0); - *(__be16 *)addr = cpu_to_be16(mac1); + put_unaligned(cpu_to_be32(mac0), (__be32 *)(addr + 2)); + put_unaligned(cpu_to_be16(mac1), (__be16 *)addr); return is_valid_ether_addr(addr); } @@ -326,9 +326,9 @@ void alx_set_macaddr(struct alx_hw *hw, const u8 *addr) u32 val; /* for example: 00-0B-6A-F6-00-DC * STAD0=6AF600DC, STAD1=000B */ - val = be32_to_cpu(*(__be32 *)(addr + 2)); + val = be32_to_cpu(get_unaligned((__be32 *)(addr + 2))); alx_write_mem32(hw, ALX_STAD0, val); - val = be16_to_cpu(*(__be16 *)addr); + val = be16_to_cpu(get_unaligned((__be16 *)addr)); alx_write_mem32(hw, ALX_STAD1, val); } -- GitLab From 7ec5689461989fd80f1cf82ae084f5d50a5e63ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 29 Jun 2013 19:23:19 +0200 Subject: [PATCH 2109/2900] alx: fix ethtool support code A number of places treated features wrongly, listing not-supported features instead of supported ones. Also, the get_drvinfo ethtool callback isn't needed, and alx_get_pauseparam can be simplified. Reported-by: Ben Hutchings Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/ethtool.c | 64 ++++++++++------------ 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 5e19e08b691b..926100626d60 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -46,21 +46,37 @@ #include "reg.h" #include "hw.h" +static u32 alx_get_supported_speeds(struct alx_hw *hw) +{ + u32 supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full; + + if (alx_hw_giga(hw)) + supported |= SUPPORTED_1000baseT_Full; + + BUILD_BUG_ON(SUPPORTED_10baseT_Half != ADVERTISED_10baseT_Half); + BUILD_BUG_ON(SUPPORTED_10baseT_Full != ADVERTISED_10baseT_Full); + BUILD_BUG_ON(SUPPORTED_100baseT_Half != ADVERTISED_100baseT_Half); + BUILD_BUG_ON(SUPPORTED_100baseT_Full != ADVERTISED_100baseT_Full); + BUILD_BUG_ON(SUPPORTED_1000baseT_Full != ADVERTISED_1000baseT_Full); + + return supported; +} static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) { struct alx_priv *alx = netdev_priv(netdev); struct alx_hw *hw = &alx->hw; - ecmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | + ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_TP | - SUPPORTED_Pause; + SUPPORTED_Pause | + SUPPORTED_Asym_Pause; if (alx_hw_giga(hw)) ecmd->supported |= SUPPORTED_1000baseT_Full; + ecmd->supported |= alx_get_supported_speeds(hw); ecmd->advertising = ADVERTISED_TP; if (hw->adv_cfg & ADVERTISED_Autoneg) @@ -68,6 +84,7 @@ static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ecmd->port = PORT_TP; ecmd->phy_address = 0; + if (hw->adv_cfg & ADVERTISED_Autoneg) ecmd->autoneg = AUTONEG_ENABLE; else @@ -100,7 +117,7 @@ static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ASSERT_RTNL(); if (ecmd->autoneg == AUTONEG_ENABLE) { - if (ecmd->advertising & ADVERTISED_1000baseT_Half) + if (ecmd->advertising & ~alx_get_supported_speeds(hw)) return -EINVAL; adv_cfg = ecmd->advertising | ADVERTISED_Autoneg; } else { @@ -121,21 +138,10 @@ static void alx_get_pauseparam(struct net_device *netdev, struct alx_priv *alx = netdev_priv(netdev); struct alx_hw *hw = &alx->hw; - if (hw->flowctrl & ALX_FC_ANEG && - hw->adv_cfg & ADVERTISED_Autoneg) - pause->autoneg = AUTONEG_ENABLE; - else - pause->autoneg = AUTONEG_DISABLE; - - if (hw->flowctrl & ALX_FC_TX) - pause->tx_pause = 1; - else - pause->tx_pause = 0; - - if (hw->flowctrl & ALX_FC_RX) - pause->rx_pause = 1; - else - pause->rx_pause = 0; + pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG && + hw->adv_cfg & ADVERTISED_Autoneg); + pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX); + pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX); } @@ -214,8 +220,7 @@ static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct alx_priv *alx = netdev_priv(netdev); struct alx_hw *hw = &alx->hw; - if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) + if (wol->wolopts & ~(WAKE_MAGIC | WAKE_PHY)) return -EOPNOTSUPP; hw->sleep_ctrl = 0; @@ -230,22 +235,11 @@ static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } -static void alx_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct alx_priv *alx = netdev_priv(netdev); - - strlcpy(drvinfo->driver, alx_drv_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->bus_info, pci_name(alx->hw.pdev), - sizeof(drvinfo->bus_info)); -} - const struct ethtool_ops alx_ethtool_ops = { .get_settings = alx_get_settings, .set_settings = alx_set_settings, .get_pauseparam = alx_get_pauseparam, .set_pauseparam = alx_set_pauseparam, - .get_drvinfo = alx_get_drvinfo, .get_msglevel = alx_get_msglevel, .set_msglevel = alx_set_msglevel, .get_wol = alx_get_wol, -- GitLab From fb825a550a1af75323cee9d62d6fb818384c8c95 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Fri, 28 Jun 2013 16:07:40 -0700 Subject: [PATCH 2110/2900] openvswitch: Add Kconfig dependency on GRE-DEMUX. Openvswitch uses function from NET_IPGRE_DEMUX module. Add Kconfig dependency to fix following compilation errors: http://marc.info/?l=linux-netdev&m=137244035226634 CC: Jesse Gross Reported-by: Randy Dunlap Signed-off-by: Pravin Shelar Acked-by: Randy Dunlap Acked-by: Jesse Gross Signed-off-by: David S. Miller --- net/openvswitch/Kconfig | 16 ++++++++++++++-- net/openvswitch/vport-gre.c | 5 +++-- net/openvswitch/vport.c | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/net/openvswitch/Kconfig b/net/openvswitch/Kconfig index 9fbc04a31ed6..27ee56b688a3 100644 --- a/net/openvswitch/Kconfig +++ b/net/openvswitch/Kconfig @@ -19,8 +19,6 @@ config OPENVSWITCH which is able to accept configuration from a variety of sources and translate it into packet processing rules. - Open vSwitch GRE support depends on CONFIG_NET_IPGRE_DEMUX. - See http://openvswitch.org for more information and userspace utilities. @@ -28,3 +26,17 @@ config OPENVSWITCH called openvswitch. If unsure, say N. + +config OPENVSWITCH_GRE + bool "Open vSwitch GRE tunneling support" + depends on INET + depends on OPENVSWITCH + depends on NET_IPGRE_DEMUX && !(OPENVSWITCH=y && NET_IPGRE_DEMUX=m) + default y + ---help--- + If you say Y here, then the Open vSwitch will be able create GRE + vport. + + Say N to exclude this support and reduce the binary size. + + If unsure, say Y. diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 943e5c431354..493e9775dcda 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c @@ -16,7 +16,7 @@ * 02110-1301, USA */ -#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) +#ifdef CONFIG_OPENVSWITCH_GRE #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include @@ -271,4 +271,5 @@ const struct vport_ops ovs_gre_vport_ops = { .get_name = gre_get_name, .send = gre_tnl_send, }; -#endif + +#endif /* OPENVSWITCH_GRE */ diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index ba81294219ac..d4c7fa04ce08 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -39,7 +39,7 @@ static const struct vport_ops *vport_ops_list[] = { &ovs_netdev_vport_ops, &ovs_internal_vport_ops, -#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) +#ifdef CONFIG_OPENVSWITCH_GRE &ovs_gre_vport_ops, #endif }; -- GitLab From 5c29fb12e8fb8a8105ea048cb160fd79a85a52bb Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 27 Jun 2013 22:46:04 +0200 Subject: [PATCH 2111/2900] ipv6: only apply anti-spoofing checks to not-pointopoint tunnels Because of commit 218774dc341f219bfcf940304a081b121a0e8099 ("ipv6: add anti-spoofing checks for 6to4 and 6rd") the sit driver dropped packets for 2002::/16 destinations and sources even when configured to work as a tunnel with fixed endpoint. We may only apply the 6rd/6to4 anti-spoofing checks if the device is not in pointopoint mode. This was an oversight from me in the above commit, sorry. Thanks to Roman Mamedov for reporting this! Reported-by: Roman Mamedov Cc: David Miller Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 97a0bfe2c293..85ff37b1ce02 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -593,7 +593,7 @@ static int ipip6_rcv(struct sk_buff *skb) tunnel->dev->stats.rx_errors++; goto out; } - } else { + } else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) { if (is_spoofed_6rd(tunnel, iph->saddr, &ipv6_hdr(skb)->saddr) || is_spoofed_6rd(tunnel, iph->daddr, -- GitLab From 52bd4c0c1551daa2efa7bb9e01a2f4ea6d1311bb Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 28 Jun 2013 17:35:48 +0200 Subject: [PATCH 2112/2900] ipv6: fix ecmp lookup when oif is specified There is no reason to skip ECMP lookup when oif is specified, but this implies to check oif given by user when selecting another route. When the new route does not match oif requirement, we simply keep the initial one. Spotted-by: dingzhi Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/route.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7ca87b37c0ef..9ff0b78a9c15 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -83,6 +83,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb, u32 mtu); static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb); +static int rt6_score_route(struct rt6_info *rt, int oif, int strict); #ifdef CONFIG_IPV6_ROUTE_INFO static struct rt6_info *rt6_add_route_info(struct net *net, @@ -394,7 +395,8 @@ static int rt6_info_hash_nhsfn(unsigned int candidate_count, } static struct rt6_info *rt6_multipath_select(struct rt6_info *match, - struct flowi6 *fl6) + struct flowi6 *fl6, int oif, + int strict) { struct rt6_info *sibling, *next_sibling; int route_choosen; @@ -408,6 +410,8 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, &match->rt6i_siblings, rt6i_siblings) { route_choosen--; if (route_choosen == 0) { + if (rt6_score_route(sibling, oif, strict) < 0) + break; match = sibling; break; } @@ -743,7 +747,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net, rt = fn->leaf; rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags); if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0) - rt = rt6_multipath_select(rt, fl6); + rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags); BACKTRACK(net, &fl6->saddr); out: dst_use(&rt->dst, jiffies); @@ -875,8 +879,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, restart: rt = rt6_select(fn, oif, strict | reachable); - if (rt->rt6i_nsiblings && oif == 0) - rt = rt6_multipath_select(rt, fl6); + if (rt->rt6i_nsiblings) + rt = rt6_multipath_select(rt, fl6, oif, strict | reachable); BACKTRACK(net, &fl6->saddr); if (rt == net->ipv6.ip6_null_entry || rt->rt6i_flags & RTF_CACHE) -- GitLab From 772e42b07fbdc650206746e00cb2914e362594a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Thu, 27 Jun 2013 21:18:23 +0200 Subject: [PATCH 2113/2900] net: fec: Fix multicast list setup in fec_restart(). Setup the multicast list of the net_device instead of clearing it blindly. This restores the multicast groups in case of a link down/up event or when resuming from suspend. Signed-off-by: Christoph Muellner Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ed6180e7db2f..5664acd8e0f4 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -59,6 +59,8 @@ #include "fec.h" +static void set_multicast_list(struct net_device *ndev); + #if defined(CONFIG_ARM) #define FEC_ALIGNMENT 0xf #else @@ -470,9 +472,8 @@ fec_restart(struct net_device *ndev, int duplex) /* Clear any outstanding interrupt. */ writel(0xffc00000, fep->hwp + FEC_IEVENT); - /* Reset all multicast. */ - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); - writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + /* Setup multicast filter. */ + set_multicast_list(ndev); #ifndef CONFIG_M5272 writel(0, fep->hwp + FEC_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_HASH_TABLE_LOW); -- GitLab From 383eda32b891002d5064cc97243c94b7cf78137a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 27 Jun 2013 21:57:49 -0700 Subject: [PATCH 2114/2900] xen: Use more current logging styles Instead of mixing printk and pr_ forms, just use pr_ Miscellaneous changes around these conversions: Add a missing newline to avoid message interleaving, coalesce formats, reflow modified lines to 80 columns. Signed-off-by: Joe Perches Acked-by: Ian Campbell Acked-by: Konrad Rzeszutek Wilk Signed-off-by: David S. Miller --- drivers/net/xen-netback/netback.c | 7 +++---- drivers/net/xen-netfront.c | 28 +++++++++++++--------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 130bcb217d2c..64828de25d9a 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1890,9 +1890,8 @@ static int __init netback_init(void) return -ENODEV; if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) { - printk(KERN_INFO - "xen-netback: fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", - fatal_skb_slots, XEN_NETBK_LEGACY_SLOTS_MAX); + pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", + fatal_skb_slots, XEN_NETBK_LEGACY_SLOTS_MAX); fatal_skb_slots = XEN_NETBK_LEGACY_SLOTS_MAX; } @@ -1921,7 +1920,7 @@ static int __init netback_init(void) "netback/%u", group); if (IS_ERR(netbk->task)) { - printk(KERN_ALERT "kthread_create() fails at netback\n"); + pr_alert("kthread_create() fails at netback\n"); del_timer(&netbk->net_timer); rc = PTR_ERR(netbk->task); goto failed_init; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 76a22365d4e9..ff7f111fffee 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -29,6 +29,8 @@ * IN THE SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -385,9 +387,8 @@ static void xennet_tx_buf_gc(struct net_device *dev) skb = np->tx_skbs[id].skb; if (unlikely(gnttab_query_foreign_access( np->grant_tx_ref[id]) != 0)) { - printk(KERN_ALERT "xennet_tx_buf_gc: warning " - "-- grant still in use by backend " - "domain.\n"); + pr_alert("%s: warning -- grant still in use by backend domain\n", + __func__); BUG(); } gnttab_end_foreign_access_ref( @@ -804,14 +805,14 @@ static int xennet_set_skb_gso(struct sk_buff *skb, { if (!gso->u.gso.size) { if (net_ratelimit()) - printk(KERN_WARNING "GSO size must not be zero.\n"); + pr_warn("GSO size must not be zero\n"); return -EINVAL; } /* Currently only TCPv4 S.O. is supported. */ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { if (net_ratelimit()) - printk(KERN_WARNING "Bad GSO type %d.\n", gso->u.gso.type); + pr_warn("Bad GSO type %d\n", gso->u.gso.type); return -EINVAL; } @@ -910,9 +911,8 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb) break; default: if (net_ratelimit()) - printk(KERN_ERR "Attempting to checksum a non-" - "TCP/UDP packet, dropping a protocol" - " %d packet", iph->protocol); + pr_err("Attempting to checksum a non-TCP/UDP packet, dropping a protocol %d packet\n", + iph->protocol); goto out; } @@ -1359,14 +1359,14 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) /* A grant for every tx ring slot */ if (gnttab_alloc_grant_references(TX_MAX_TARGET, &np->gref_tx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); + pr_alert("can't alloc tx grant refs\n"); err = -ENOMEM; goto exit_free_stats; } /* A grant for every rx ring slot */ if (gnttab_alloc_grant_references(RX_MAX_TARGET, &np->gref_rx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); + pr_alert("can't alloc rx grant refs\n"); err = -ENOMEM; goto exit_free_tx; } @@ -1430,16 +1430,14 @@ static int netfront_probe(struct xenbus_device *dev, err = register_netdev(info->netdev); if (err) { - printk(KERN_WARNING "%s: register_netdev err=%d\n", - __func__, err); + pr_warn("%s: register_netdev err=%d\n", __func__, err); goto fail; } err = xennet_sysfs_addif(info->netdev); if (err) { unregister_netdev(info->netdev); - printk(KERN_WARNING "%s: add sysfs failed err=%d\n", - __func__, err); + pr_warn("%s: add sysfs failed err=%d\n", __func__, err); goto fail; } @@ -2116,7 +2114,7 @@ static int __init netif_init(void) if (xen_hvm_domain() && !xen_platform_pci_unplug) return -ENODEV; - printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n"); + pr_info("Initialising Xen virtual ethernet driver\n"); return xenbus_register_frontend(&netfront_driver); } -- GitLab From 0d909dcdeffeee3c42703dc1d17766d94fd47b71 Mon Sep 17 00:00:00 2001 From: Byungho An Date: Fri, 28 Jun 2013 16:35:31 +0900 Subject: [PATCH 2115/2900] net: stmmac: fixed operator typo This patch fixed operator typo from & to ==. Due to incorrect operator, the result is incorrect. Signed-off-by: Byungho An Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ee919ca8b8a0..4fb74a07c01c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -788,13 +788,13 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) int interface = priv->plat->interface; if (priv->dma_cap.pcs) { - if ((interface & PHY_INTERFACE_MODE_RGMII) || - (interface & PHY_INTERFACE_MODE_RGMII_ID) || - (interface & PHY_INTERFACE_MODE_RGMII_RXID) || - (interface & PHY_INTERFACE_MODE_RGMII_TXID)) { + if ((interface == PHY_INTERFACE_MODE_RGMII) || + (interface == PHY_INTERFACE_MODE_RGMII_ID) || + (interface == PHY_INTERFACE_MODE_RGMII_RXID) || + (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { pr_debug("STMMAC: PCS RGMII support enable\n"); priv->pcs = STMMAC_PCS_RGMII; - } else if (interface & PHY_INTERFACE_MODE_SGMII) { + } else if (interface == PHY_INTERFACE_MODE_SGMII) { pr_debug("STMMAC: PCS SGMII support enable\n"); priv->pcs = STMMAC_PCS_SGMII; } -- GitLab From 61369d0259a724606f3941a46d2c75155d66cf2c Mon Sep 17 00:00:00 2001 From: Byungho An Date: Fri, 28 Jun 2013 16:35:32 +0900 Subject: [PATCH 2116/2900] net: stmmac: fixed enh_desc set always zero This patch fixed that enh_desc value is always zero. Due to calling order of stmmac_selec_desc_mode(), enh_desc value is always zero. Even though mac is set to use enhanced dma descriptor, if enh_desc is zero, functions related dma descriptor are not working correctly. Signed-off-by: Byungho An Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4fb74a07c01c..520693385d8d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2566,9 +2566,6 @@ static int stmmac_hw_init(struct stmmac_priv *priv) /* Get and dump the chip ID */ priv->synopsys_id = stmmac_get_synopsys_id(priv); - /* To use alternate (extended) or normal descriptor structures */ - stmmac_selec_desc_mode(priv); - /* To use the chained or ring mode */ if (chain_mode) { priv->hw->chain = &chain_mode_ops; @@ -2603,6 +2600,9 @@ static int stmmac_hw_init(struct stmmac_priv *priv) } else pr_info(" No HW DMA feature register supported"); + /* To use alternate (extended) or normal descriptor structures */ + stmmac_selec_desc_mode(priv); + ret = priv->hw->mac->rx_ipc(priv->ioaddr); if (!ret) { pr_warn(" RX IPC Checksum Offload not configured.\n"); -- GitLab From c9ab4d85de222f3390c67aedc9c18a50e767531e Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 28 Jun 2013 02:37:42 -0700 Subject: [PATCH 2117/2900] neighbour: fix a race in neigh_destroy() There is a race in neighbour code, because neigh_destroy() uses skb_queue_purge(&neigh->arp_queue) without holding neighbour lock, while other parts of the code assume neighbour rwlock is what protects arp_queue Convert all skb_queue_purge() calls to the __skb_queue_purge() variant Use __skb_queue_head_init() instead of skb_queue_head_init() to make clear we do not use arp_queue.lock And hold neigh->lock in neigh_destroy() to close the race. Reported-by: Joe Jin Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/neighbour.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 2569ab2cafbe..b7de821f98df 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -231,7 +231,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) we must kill timers etc. and move it to safe state. */ - skb_queue_purge(&n->arp_queue); + __skb_queue_purge(&n->arp_queue); n->arp_queue_len_bytes = 0; n->output = neigh_blackhole; if (n->nud_state & NUD_VALID) @@ -286,7 +286,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device if (!n) goto out_entries; - skb_queue_head_init(&n->arp_queue); + __skb_queue_head_init(&n->arp_queue); rwlock_init(&n->lock); seqlock_init(&n->ha_lock); n->updated = n->used = now; @@ -708,7 +708,9 @@ void neigh_destroy(struct neighbour *neigh) if (neigh_del_timer(neigh)) pr_warn("Impossible event\n"); - skb_queue_purge(&neigh->arp_queue); + write_lock_bh(&neigh->lock); + __skb_queue_purge(&neigh->arp_queue); + write_unlock_bh(&neigh->lock); neigh->arp_queue_len_bytes = 0; if (dev->netdev_ops->ndo_neigh_destroy) @@ -858,7 +860,7 @@ static void neigh_invalidate(struct neighbour *neigh) neigh->ops->error_report(neigh, skb); write_lock(&neigh->lock); } - skb_queue_purge(&neigh->arp_queue); + __skb_queue_purge(&neigh->arp_queue); neigh->arp_queue_len_bytes = 0; } @@ -1210,7 +1212,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, write_lock_bh(&neigh->lock); } - skb_queue_purge(&neigh->arp_queue); + __skb_queue_purge(&neigh->arp_queue); neigh->arp_queue_len_bytes = 0; } out: -- GitLab From ad6276e0fe724b1c8ac3a0bf138d151665ab2349 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 28 Jun 2013 15:59:26 +0300 Subject: [PATCH 2118/2900] net: fix LLS debug_smp_processor_id() warning Our use of sched_clock is OK because we don't mind the side effects of calling it and occasionally waking up on a different CPU. When CONFIG_DEBUG_PREEMPT is on, disable preempt before calling sched_clock() so we don't trigger a debug_smp_processor_id() warning. Reported-by: Cody P Schafer Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- include/net/ll_poll.h | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 5bf2b3a6129e..6d45e6f6ff4c 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -37,20 +37,40 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; #define LL_FLUSH_FAILED -1 #define LL_FLUSH_BUSY -2 -/* we can use sched_clock() because we don't care much about precision +/* a wrapper to make debug_smp_processor_id() happy + * we can use sched_clock() because we don't care much about precision * we only care that the average is bounded - * we don't mind a ~2.5% imprecision so <<10 instead of *1000 + */ +#ifdef CONFIG_DEBUG_PREEMPT +static inline u64 ll_sched_clock(void) +{ + u64 rc; + + preempt_disable_notrace(); + rc = sched_clock(); + preempt_enable_no_resched_notrace(); + + return rc; +} +#else /* CONFIG_DEBUG_PREEMPT */ +static inline u64 ll_sched_clock(void) +{ + return sched_clock(); +} +#endif /* CONFIG_DEBUG_PREEMPT */ + +/* we don't mind a ~2.5% imprecision so <<10 instead of *1000 * sk->sk_ll_usec is a u_int so this can't overflow */ static inline u64 ll_sk_end_time(struct sock *sk) { - return ((u64)ACCESS_ONCE(sk->sk_ll_usec) << 10) + sched_clock(); + return ((u64)ACCESS_ONCE(sk->sk_ll_usec) << 10) + ll_sched_clock(); } /* in poll/select we use the global sysctl_net_ll_poll value */ static inline u64 ll_end_time(void) { - return ((u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10) + sched_clock(); + return ((u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10) + ll_sched_clock(); } static inline bool sk_valid_ll(struct sock *sk) @@ -61,7 +81,7 @@ static inline bool sk_valid_ll(struct sock *sk) static inline bool can_poll_ll(u64 end_time) { - return !time_after64(sched_clock(), end_time); + return !time_after64(ll_sched_clock(), end_time); } /* when used in sock_poll() nonblock is known at compile time to be true -- GitLab From 91e2fd337839319c7745e2cb84cfbf8cf1426a1a Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Fri, 28 Jun 2013 15:59:35 +0300 Subject: [PATCH 2119/2900] net: avoid calling sched_clock when LLS is off Change Low Latency Sockets code for select and poll so that when LLS is disabled sched_clock() is never called. Also, avoid sending POLL_LL to sockets if disabled. Reported-by: Andi Kleen Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- fs/select.c | 11 +++++++---- include/net/ll_poll.h | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/fs/select.c b/fs/select.c index 79b876eb91da..36540754bad7 100644 --- a/fs/select.c +++ b/fs/select.c @@ -402,7 +402,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) poll_table *wait; int retval, i, timed_out = 0; unsigned long slack = 0; - unsigned int ll_flag = POLL_LL; + unsigned int ll_flag = ll_get_flag(); u64 ll_time = ll_end_time(); rcu_read_lock(); @@ -497,7 +497,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) break; } - if (can_ll && can_poll_ll(ll_time)) + /* only if on, have sockets with POLL_LL and not out of time */ + if (ll_flag && can_ll && can_poll_ll(ll_time)) continue; /* @@ -768,7 +769,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, ktime_t expire, *to = NULL; int timed_out = 0, count = 0; unsigned long slack = 0; - unsigned int ll_flag = POLL_LL; + unsigned int ll_flag = ll_get_flag(); u64 ll_time = ll_end_time(); /* Optimise the no-wait case */ @@ -817,8 +818,10 @@ static int do_poll(unsigned int nfds, struct poll_list *list, if (count || timed_out) break; - if (can_ll && can_poll_ll(ll_time)) + /* only if on, have sockets with POLL_LL and not out of time */ + if (ll_flag && can_ll && can_poll_ll(ll_time)) continue; + /* * If this is the first loop and we have a timeout * given, then we convert to ktime_t and set the to diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 6d45e6f6ff4c..6c06f7c0a22d 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -37,6 +37,11 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; #define LL_FLUSH_FAILED -1 #define LL_FLUSH_BUSY -2 +static inline unsigned int ll_get_flag(void) +{ + return sysctl_net_ll_poll ? POLL_LL : 0; +} + /* a wrapper to make debug_smp_processor_id() happy * we can use sched_clock() because we don't care much about precision * we only care that the average is bounded @@ -67,10 +72,14 @@ static inline u64 ll_sk_end_time(struct sock *sk) return ((u64)ACCESS_ONCE(sk->sk_ll_usec) << 10) + ll_sched_clock(); } -/* in poll/select we use the global sysctl_net_ll_poll value */ +/* in poll/select we use the global sysctl_net_ll_poll value + * only call sched_clock() if enabled + */ static inline u64 ll_end_time(void) { - return ((u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10) + ll_sched_clock(); + u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll); + + return end_time ? (end_time << 10) + ll_sched_clock() : 0; } static inline bool sk_valid_ll(struct sock *sk) @@ -141,6 +150,10 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) } #else /* CONFIG_NET_LL_RX_POLL */ +static inline unsigned long ll_get_flag(void) +{ + return 0; +} static inline u64 sk_ll_end_time(struct sock *sk) { -- GitLab From 442340639194762df7e61e8aabae44a18896eca1 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 14 May 2013 16:53:40 -0400 Subject: [PATCH 2120/2900] svcrpc: introduce init_svc_cred Common helper to zero out fields of the svc_cred. Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/svcauth.h | 7 +++++++ net/sunrpc/auth_gss/svcauth_gss.c | 6 ++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index ff374ab30839..95c956613a9c 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -25,6 +25,13 @@ struct svc_cred { char *cr_principal; /* for gss */ }; +static inline void init_svc_cred(struct svc_cred *cred) +{ + cred->cr_group_info = NULL; + cred->cr_principal = NULL; + cred->cr_gss_mech = NULL; +} + static inline void free_svc_cred(struct svc_cred *cred) { if (cred->cr_group_info) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 29b4ba93ab3c..8d7860ee2398 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -377,8 +377,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp) new->handle.data = tmp->handle.data; tmp->handle.data = NULL; new->mechctx = NULL; - new->cred.cr_group_info = NULL; - new->cred.cr_principal = NULL; + init_svc_cred(&new->cred); } static void @@ -392,9 +391,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp) memset(&new->seqdata, 0, sizeof(new->seqdata)); spin_lock_init(&new->seqdata.sd_lock); new->cred = tmp->cred; - tmp->cred.cr_group_info = NULL; new->cred.cr_principal = tmp->cred.cr_principal; - tmp->cred.cr_principal = NULL; + init_svc_cred(&tmp->cred); } static struct cache_head * -- GitLab From 0dc1531aca7fd1440918bd55844a054e9c29acad Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 14 May 2013 16:07:13 -0400 Subject: [PATCH 2121/2900] svcrpc: store gss mech in svc_cred Store a pointer to the gss mechanism used in the rq_cred and cl_cred. This will make it easier to enforce SP4_MACH_CRED, which needs to compare the mechanism used on the exchange_id with that used on protected operations. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 3 +++ include/linux/sunrpc/gss_api.h | 2 ++ include/linux/sunrpc/svcauth.h | 4 ++++ net/sunrpc/auth_gss/gss_mech_switch.c | 5 ++++- net/sunrpc/auth_gss/svcauth_gss.c | 4 +--- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 72f0c4e9a942..109b43402e82 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1188,6 +1188,9 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source) target->cr_gid = source->cr_gid; target->cr_group_info = source->cr_group_info; get_group_info(target->cr_group_info); + target->cr_gss_mech = source->cr_gss_mech; + if (source->cr_gss_mech) + gss_mech_get(source->cr_gss_mech); return 0; } diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index 161463e59624..1f911ccb2a75 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -151,6 +151,8 @@ struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32); /* Fill in an array with a list of supported pseudoflavors */ int gss_mech_list_pseudoflavors(rpc_authflavor_t *, int); +struct gss_api_mech * gss_mech_get(struct gss_api_mech *); + /* For every successful gss_mech_get or gss_mech_get_by_* call there must be a * corresponding call to gss_mech_put. */ void gss_mech_put(struct gss_api_mech *); diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 95c956613a9c..8d71d6577459 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ struct svc_cred { struct group_info *cr_group_info; u32 cr_flavor; /* pseudoflavor */ char *cr_principal; /* for gss */ + struct gss_api_mech *cr_gss_mech; }; static inline void init_svc_cred(struct svc_cred *cred) @@ -37,6 +39,8 @@ static inline void free_svc_cred(struct svc_cred *cred) if (cred->cr_group_info) put_group_info(cred->cr_group_info); kfree(cred->cr_principal); + gss_mech_put(cred->cr_gss_mech); + init_svc_cred(cred); } struct svc_rqst; /* forward decl */ diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index defa9d33925c..27ce26240932 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -139,11 +139,12 @@ void gss_mech_unregister(struct gss_api_mech *gm) } EXPORT_SYMBOL_GPL(gss_mech_unregister); -static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm) +struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm) { __module_get(gm->gm_owner); return gm; } +EXPORT_SYMBOL(gss_mech_get); static struct gss_api_mech * _gss_mech_get_by_name(const char *name) @@ -360,6 +361,7 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) } return 0; } +EXPORT_SYMBOL(gss_pseudoflavor_to_service); char * gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) @@ -379,6 +381,7 @@ gss_mech_put(struct gss_api_mech * gm) if (gm) module_put(gm->gm_owner); } +EXPORT_SYMBOL(gss_mech_put); /* The mech could probably be determined from the token instead, but it's just * as easy for now to pass it in. */ diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 8d7860ee2398..0265bb3a8689 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -391,7 +391,6 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp) memset(&new->seqdata, 0, sizeof(new->seqdata)); spin_lock_init(&new->seqdata.sd_lock); new->cred = tmp->cred; - new->cred.cr_principal = tmp->cred.cr_principal; init_svc_cred(&tmp->cred); } @@ -485,7 +484,7 @@ static int rsc_parse(struct cache_detail *cd, len = qword_get(&mesg, buf, mlen); if (len < 0) goto out; - gm = gss_mech_get_by_name(buf); + gm = rsci.cred.cr_gss_mech = gss_mech_get_by_name(buf); status = -EOPNOTSUPP; if (!gm) goto out; @@ -515,7 +514,6 @@ static int rsc_parse(struct cache_detail *cd, rscp = rsc_update(cd, &rsci, rscp); status = 0; out: - gss_mech_put(gm); rsc_free(&rsci); if (rscp) cache_put(&rscp->h, cd); -- GitLab From 57266a6e916e2522ea61758a3ee5576b60156791 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sat, 13 Apr 2013 14:27:29 -0400 Subject: [PATCH 2122/2900] nfsd4: implement minimal SP4_MACH_CRED Do a minimal SP4_MACH_CRED implementation suggested by Trond, ignoring the client-provided spo_must_* arrays and just enforcing credential checks for the minimum required operations. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 76 ++++++++++++++++++++++++++++++++++++++------- fs/nfsd/nfs4xdr.c | 22 +++++++++++++ fs/nfsd/state.h | 1 + 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 109b43402e82..2383d24e258f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1265,6 +1265,31 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2) return 0 == strcmp(cr1->cr_principal, cr2->cr_principal); } +static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp) +{ + struct svc_cred *cr = &rqstp->rq_cred; + u32 service; + + service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor); + return service == RPC_GSS_SVC_INTEGRITY || + service == RPC_GSS_SVC_PRIVACY; +} + +static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp) +{ + struct svc_cred *cr = &rqstp->rq_cred; + + if (!cl->cl_mach_cred) + return true; + if (cl->cl_cred.cr_gss_mech != cr->cr_gss_mech) + return false; + if (!svc_rqst_integrity_protected(rqstp)) + return false; + if (!cr->cr_principal) + return false; + return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal); +} + static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) { static u32 current_clientid = 1; @@ -1642,16 +1667,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, if (exid->flags & ~EXCHGID4_FLAG_MASK_A) return nfserr_inval; - /* Currently only support SP4_NONE */ switch (exid->spa_how) { + case SP4_MACH_CRED: + if (!svc_rqst_integrity_protected(rqstp)) + return nfserr_inval; case SP4_NONE: break; default: /* checked by xdr code */ WARN_ON_ONCE(1); case SP4_SSV: return nfserr_encr_alg_unsupp; - case SP4_MACH_CRED: - return nfserr_serverfault; /* no excuse :-/ */ } /* Cases below refer to rfc 5661 section 18.35.4: */ @@ -1666,6 +1691,10 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, status = nfserr_inval; goto out; } + if (!mach_creds_match(conf, rqstp)) { + status = nfserr_wrong_cred; + goto out; + } if (!creds_match) { /* case 9 */ status = nfserr_perm; goto out; @@ -1713,6 +1742,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, goto out; } new->cl_minorversion = cstate->minorversion; + new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED); gen_clid(new, nn); add_to_unconfirmed(new); @@ -1877,6 +1907,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, WARN_ON_ONCE(conf && unconf); if (conf) { + status = nfserr_wrong_cred; + if (!mach_creds_match(conf, rqstp)) + goto out_free_conn; cs_slot = &conf->cl_cs_slot; status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); if (status == nfserr_replay_cache) { @@ -1893,6 +1926,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, status = nfserr_clid_inuse; goto out_free_conn; } + status = nfserr_wrong_cred; + if (!mach_creds_match(unconf, rqstp)) + goto out_free_conn; cs_slot = &unconf->cl_cs_slot; status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); if (status) { @@ -1989,6 +2025,9 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, status = nfserr_badsession; if (!session) goto out; + status = nfserr_wrong_cred; + if (!mach_creds_match(session->se_client, rqstp)) + goto out; status = nfsd4_map_bcts_dir(&bcts->dir); if (status) goto out; @@ -2031,6 +2070,9 @@ nfsd4_destroy_session(struct svc_rqst *r, status = nfserr_badsession; if (!ses) goto out_client_lock; + status = nfserr_wrong_cred; + if (!mach_creds_match(ses->se_client, r)) + goto out_client_lock; status = mark_session_dead_locked(ses); if (status) goto out_client_lock; @@ -2061,26 +2103,31 @@ static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_s return NULL; } -static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) +static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) { struct nfs4_client *clp = ses->se_client; struct nfsd4_conn *c; + __be32 status = nfs_ok; int ret; spin_lock(&clp->cl_lock); c = __nfsd4_find_conn(new->cn_xprt, ses); - if (c) { - spin_unlock(&clp->cl_lock); - free_conn(new); - return; - } + if (c) + goto out_free; + status = nfserr_conn_not_bound_to_session; + if (clp->cl_mach_cred) + goto out_free; __nfsd4_hash_conn(new, ses); spin_unlock(&clp->cl_lock); ret = nfsd4_register_conn(new); if (ret) /* oops; xprt is already down: */ nfsd4_conn_lost(&new->cn_xpt_user); - return; + return nfs_ok; +out_free: + spin_unlock(&clp->cl_lock); + free_conn(new); + return status; } static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session) @@ -2172,8 +2219,10 @@ nfsd4_sequence(struct svc_rqst *rqstp, if (status) goto out_put_session; - nfsd4_sequence_check_conn(conn, session); + status = nfsd4_sequence_check_conn(conn, session); conn = NULL; + if (status) + goto out_put_session; /* Success! bump slot seqid */ slot->sl_seqid = seq->seqid; @@ -2235,7 +2284,10 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta status = nfserr_stale_clientid; goto out; } - + if (!mach_creds_match(clp, rqstp)) { + status = nfserr_wrong_cred; + goto out; + } expire_client(clp); out: nfs4_unlock_state(); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 170ea7e1ae25..3126210383bd 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3321,6 +3321,14 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w return nfserr; } +static const u32 nfs4_minimal_spo_must_enforce[2] = { + [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) | + 1 << (OP_EXCHANGE_ID - 32) | + 1 << (OP_CREATE_SESSION - 32) | + 1 << (OP_DESTROY_SESSION - 32) | + 1 << (OP_DESTROY_CLIENTID - 32) +}; + static __be32 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_exchange_id *exid) @@ -3359,6 +3367,20 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, /* state_protect4_r. Currently only support SP4_NONE */ BUG_ON(exid->spa_how != SP4_NONE); WRITE32(exid->spa_how); + switch (exid->spa_how) { + case SP4_NONE: + break; + case SP4_MACH_CRED: + /* spo_must_enforce bitmap: */ + WRITE32(2); + WRITE32(nfs4_minimal_spo_must_enforce[0]); + WRITE32(nfs4_minimal_spo_must_enforce[1]); + /* empty spo_must_allow bitmap: */ + WRITE32(0); + break; + default: + WARN_ON_ONCE(1); + } /* The server_owner struct */ WRITE64(minor_id); /* Minor id */ diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 274e2a114e05..424d8f5f2317 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -246,6 +246,7 @@ struct nfs4_client { nfs4_verifier cl_verifier; /* generated by client */ time_t cl_time; /* time of last lease renewal */ struct sockaddr_storage cl_addr; /* client ipaddress */ + bool cl_mach_cred; /* SP4_MACH_CRED in force */ struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ -- GitLab From b78724b70599f66a91c6d6c897a81f4f87f549f4 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 15 May 2013 17:34:39 -0400 Subject: [PATCH 2123/2900] nfsd4: fail attempts to request gss on the backchannel We don't support gss on the backchannel. We should state that fact up front rather than just letting things continue and later making the client try to figure out why the backchannel isn't working. Trond suggested instead returning NFS4ERR_NOENT. I think it would be tricky for the client to distinguish between the case "I don't support gss on the backchannel" and "I can't find that in my cache, please create another context and try that instead", and I'd prefer something that currently doesn't have any other meaning for this operation, hence the (somewhat arbitrary) NFS4ERR_ENCR_ALG_UNSUPP. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 2383d24e258f..c4f63399832c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1872,6 +1872,24 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca) return nfs_ok; } +static __be32 nfsd4_check_cb_sec(struct nfsd4_cb_sec *cbs) +{ + switch (cbs->flavor) { + case RPC_AUTH_NULL: + case RPC_AUTH_UNIX: + return nfs_ok; + default: + /* + * GSS case: the spec doesn't allow us to return this + * error. But it also doesn't allow us not to support + * GSS. + * I'd rather this fail hard than return some error the + * client might think it can already handle: + */ + return nfserr_encr_alg_unsupp; + } +} + __be32 nfsd4_create_session(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, @@ -1887,6 +1905,9 @@ nfsd4_create_session(struct svc_rqst *rqstp, if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) return nfserr_inval; + status = nfsd4_check_cb_sec(&cr_ses->cb_sec); + if (status) + return status; status = check_forechannel_attrs(&cr_ses->fore_channel, nn); if (status) return status; @@ -1996,7 +2017,11 @@ __be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state { struct nfsd4_session *session = cstate->session; struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + __be32 status; + status = nfsd4_check_cb_sec(&bc->bc_cb_sec); + if (status) + return status; spin_lock(&nn->client_lock); session->se_cb_prog = bc->bc_cb_program; session->se_cb_sec = bc->bc_cb_sec; -- GitLab From 57569a707082a337e4a61a657521d79cac3528bf Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 17 May 2013 16:25:32 -0400 Subject: [PATCH 2124/2900] nfsd4: allow client to send no cb_sec flavors In testing I notice that some of the pynfs tests forget to send any cb_sec flavors, and that we haven't necessarily errored out in that case before. I'll fix pynfs, but am also inclined to default to trying AUTH_NONE in that case in case this is something clients actually do. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 3126210383bd..171fe5e4af67 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -460,7 +460,11 @@ static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_ /* callback_sec_params4 */ READ_BUF(4); READ32(nr_secflavs); - cbs->flavor = (u32)(-1); + if (nr_secflavs) + cbs->flavor = (u32)(-1); + else + /* Is this legal? Be generous, take it to mean AUTH_NONE: */ + cbs->flavor = 0; for (i = 0; i < nr_secflavs; ++i) { READ_BUF(4); READ32(dummy); -- GitLab From 9a0590aec3ca5e86a64b87e004244abc4dd1faf9 Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Wed, 15 May 2013 14:51:49 -0400 Subject: [PATCH 2125/2900] NFSD: Don't give out read delegations on creates When an exclusive create is done with the mode bits set (aka open(testfile, O_CREAT | O_EXCL, 0777)) this causes a OPEN op followed by a SETATTR op. When a read delegation is given in the OPEN, it causes the SETATTR to delay with EAGAIN until the delegation is recalled. This patch caused exclusive creates to give out a write delegation (which turn into no delegation) which allows the SETATTR seamlessly succeed. Signed-off-by: Steve Dickson [bfields: do this for any CREATE, not just exclusive; comment] Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c4f63399832c..44dcea96bfcb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3113,8 +3113,17 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, goto out; if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) goto out; + /* + * Also, if the file was opened for write or + * create, there's a good chance the client's + * about to write to it, resulting in an + * immediate recall (since we don't support + * write delegations): + */ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) flag = NFS4_OPEN_DELEGATE_WRITE; + else if (open->op_create == NFS4_OPEN_CREATE) + flag = NFS4_OPEN_DELEGATE_WRITE; else flag = NFS4_OPEN_DELEGATE_READ; break; -- GitLab From 99c415156c49571d0f045a8cb56e0bc24225b9d9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 21 May 2013 16:21:25 -0400 Subject: [PATCH 2126/2900] nfsd4: clean up nfs4_open_delegation The nfs4_open_delegation logic is unecessarily baroque. Also stop pretending we support write delegations in several places. Some day we will support write delegations, but when that happens adding back in these flag parameters will be the easy part. For now they're just confusing. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 78 ++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 44dcea96bfcb..fcc0610fe308 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -364,19 +364,12 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp) } static struct nfs4_delegation * -alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) +alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) { struct nfs4_delegation *dp; struct nfs4_file *fp = stp->st_file; dprintk("NFSD alloc_init_deleg\n"); - /* - * Major work on the lease subsystem (for example, to support - * calbacks on stat) will be required before we can support - * write delegations properly. - */ - if (type != NFS4_OPEN_DELEGATE_READ) - return NULL; if (fp->fi_had_conflict) return NULL; if (num_delegations > max_delegations) @@ -397,7 +390,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv INIT_LIST_HEAD(&dp->dl_recall_lru); get_nfs4_file(fp); dp->dl_file = fp; - dp->dl_type = type; + dp->dl_type = NFS4_OPEN_DELEGATE_READ; fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); dp->dl_time = 0; atomic_set(&dp->dl_count, 1); @@ -3020,13 +3013,13 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int f return fl; } -static int nfs4_setlease(struct nfs4_delegation *dp, int flag) +static int nfs4_setlease(struct nfs4_delegation *dp) { struct nfs4_file *fp = dp->dl_file; struct file_lock *fl; int status; - fl = nfs4_alloc_init_lease(dp, flag); + fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ); if (!fl) return -ENOMEM; fl->fl_file = find_readable_file(fp); @@ -3044,12 +3037,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag) return 0; } -static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) +static int nfs4_set_delegation(struct nfs4_delegation *dp) { struct nfs4_file *fp = dp->dl_file; if (!fp->fi_lease) - return nfs4_setlease(dp, flag); + return nfs4_setlease(dp); spin_lock(&recall_lock); if (fp->fi_had_conflict) { spin_unlock(&recall_lock); @@ -3085,6 +3078,9 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) /* * Attempt to hand out a delegation. + * + * Note we don't support write delegations, and won't until the vfs has + * proper support for them. */ static void nfs4_open_delegation(struct net *net, struct svc_fh *fh, @@ -3093,26 +3089,26 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, struct nfs4_delegation *dp; struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); int cb_up; - int status = 0, flag = 0; + int status = 0; cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); - flag = NFS4_OPEN_DELEGATE_NONE; open->op_recall = 0; switch (open->op_claim_type) { case NFS4_OPEN_CLAIM_PREVIOUS: if (!cb_up) open->op_recall = 1; - flag = open->op_delegate_type; - if (flag == NFS4_OPEN_DELEGATE_NONE) - goto out; + if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ) + goto out_no_deleg; break; case NFS4_OPEN_CLAIM_NULL: - /* Let's not give out any delegations till everyone's - * had the chance to reclaim theirs.... */ + /* + * Let's not give out any delegations till everyone's + * had the chance to reclaim theirs.... + */ if (locks_in_grace(net)) - goto out; + goto out_no_deleg; if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) - goto out; + goto out_no_deleg; /* * Also, if the file was opened for write or * create, there's a good chance the client's @@ -3121,20 +3117,17 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, * write delegations): */ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) - flag = NFS4_OPEN_DELEGATE_WRITE; - else if (open->op_create == NFS4_OPEN_CREATE) - flag = NFS4_OPEN_DELEGATE_WRITE; - else - flag = NFS4_OPEN_DELEGATE_READ; + goto out_no_deleg; + if (open->op_create == NFS4_OPEN_CREATE) + goto out_no_deleg; break; default: - goto out; + goto out_no_deleg; } - - dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag); + dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh); if (dp == NULL) goto out_no_deleg; - status = nfs4_set_delegation(dp, flag); + status = nfs4_set_delegation(dp); if (status) goto out_free; @@ -3142,24 +3135,21 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", STATEID_VAL(&dp->dl_stid.sc_stateid)); -out: - open->op_delegate_type = flag; - if (flag == NFS4_OPEN_DELEGATE_NONE) { - if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && - open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) - dprintk("NFSD: WARNING: refusing delegation reclaim\n"); - - /* 4.1 client asking for a delegation? */ - if (open->op_deleg_want) - nfsd4_open_deleg_none_ext(open, status); - } + open->op_delegate_type = NFS4_OPEN_DELEGATE_READ; return; out_free: unhash_stid(&dp->dl_stid); nfs4_put_delegation(dp); out_no_deleg: - flag = NFS4_OPEN_DELEGATE_NONE; - goto out; + open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; + if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && + open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) + dprintk("NFSD: WARNING: refusing delegation reclaim\n"); + + /* 4.1 client asking for a delegation? */ + if (open->op_deleg_want) + nfsd4_open_deleg_none_ext(open, status); + return; } static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, -- GitLab From 247500820ebd02ad87525db5d9b199e5b66f6636 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 21 Jun 2013 11:48:11 -0400 Subject: [PATCH 2127/2900] nfsd4: fix decoding of compounds across page boundaries A freebsd NFSv4.0 client was getting rare IO errors expanding a tarball. A network trace showed the server returning BAD_XDR on the final getattr of a getattr+write+getattr compound. The final getattr started on a page boundary. I believe the Linux client ignores errors on the post-write getattr, and that that's why we haven't seen this before. Cc: stable@vger.kernel.org Reported-by: Rick Macklem Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 171fe5e4af67..e34f5ebfc811 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -167,8 +167,8 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) */ memcpy(p, argp->p, avail); /* step to next page */ - argp->p = page_address(argp->pagelist[0]); argp->pagelist++; + argp->p = page_address(argp->pagelist[0]); if (argp->pagelen < PAGE_SIZE) { argp->end = argp->p + (argp->pagelen>>2); argp->pagelen = 0; -- GitLab From 590b743143eae8db40abdfd1ab20bc51ee0ee5db Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 21 Jun 2013 17:06:29 -0400 Subject: [PATCH 2128/2900] nfsd4: minor read_buf cleanup The code to step to the next page seems reasonably self-contained. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index e34f5ebfc811..c102d2509a2a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -139,6 +139,19 @@ xdr_error: \ } \ } while (0) +static void next_decode_page(struct nfsd4_compoundargs *argp) +{ + argp->pagelist++; + argp->p = page_address(argp->pagelist[0]); + if (argp->pagelen < PAGE_SIZE) { + argp->end = argp->p + (argp->pagelen>>2); + argp->pagelen = 0; + } else { + argp->end = argp->p + (PAGE_SIZE>>2); + argp->pagelen -= PAGE_SIZE; + } +} + static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) { /* We want more bytes than seem to be available. @@ -166,16 +179,7 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) * guarantee p points to at least nbytes bytes. */ memcpy(p, argp->p, avail); - /* step to next page */ - argp->pagelist++; - argp->p = page_address(argp->pagelist[0]); - if (argp->pagelen < PAGE_SIZE) { - argp->end = argp->p + (argp->pagelen>>2); - argp->pagelen = 0; - } else { - argp->end = argp->p + (PAGE_SIZE>>2); - argp->pagelen -= PAGE_SIZE; - } + next_decode_page(argp); memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); argp->p += XDR_QUADLEN(nbytes - avail); return p; -- GitLab From cf3aa02cb4a0c5af5557dd47f15a08a7df33182a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 26 Jun 2013 11:09:06 -0400 Subject: [PATCH 2129/2900] svcrpc: fix handling of too-short rpc's If we detect that an rpc is too short, we abort and close the connection. Except, there's a bug here: we're leaving sk_datalen nonzero without leaving any pages in the sk_pages array. The most likely result of the inconsistency is a subsequent crash in svc_tcp_clear_pages. Also demote the BUG_ON in svc_tcp_clear_pages to a WARN. Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- net/sunrpc/svcsock.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 0f679df7d072..df74919c81c0 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -917,7 +917,10 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk) len = svsk->sk_datalen; npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { - BUG_ON(svsk->sk_pages[i] == NULL); + if (svsk->sk_pages[i] == NULL) { + WARN_ON_ONCE(1); + continue; + } put_page(svsk->sk_pages[i]); svsk->sk_pages[i] = NULL; } @@ -1092,8 +1095,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) goto err_noclose; } - if (svc_sock_reclen(svsk) < 8) + if (svc_sock_reclen(svsk) < 8) { + svsk->sk_datalen = 0; goto err_delete; /* client is nuts. */ + } rqstp->rq_arg.len = svsk->sk_datalen; rqstp->rq_arg.page_base = 0; -- GitLab From 1f691b07c5dc51b2055834f58c0f351defd97f27 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 26 Jun 2013 10:55:40 -0400 Subject: [PATCH 2130/2900] svcrpc: don't error out on small tcp fragment Though clients we care about mostly don't do this, it is possible for rpc requests to be sent in multiple fragments. Here we have a sanity check to ensure that the final received rpc isn't too small--except that the number we're actually checking is the length of just the final fragment, not of the whole rpc. So a perfectly legal rpc that's unluckily fragmented could cause the server to close the connection here. Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- net/sunrpc/svcsock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index df74919c81c0..305374d4fb98 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1095,7 +1095,7 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) goto err_noclose; } - if (svc_sock_reclen(svsk) < 8) { + if (svsk->sk_datalen < 8) { svsk->sk_datalen = 0; goto err_delete; /* client is nuts. */ } -- GitLab From 89f6c3362cb5a6bce96dbe6aa15b4749c2262b21 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 19 Jun 2013 15:47:37 -0400 Subject: [PATCH 2131/2900] nfsd4: delegation-based open reclaims should bypass permissions We saw a v4.0 client's create fail as follows: - open create succeeds and gets a read delegation - client attempts to set mode on new file, gets DELAY while server recalls delegation. - client attempts a CLAIM_DELEGATE_CUR open using the delegation, gets error because of new file mode. This probably can't happen on a recent kernel since we're no longer giving out delegations on create opens. Nevertheless, it's a bug--reclaim opens should bypass permission checks. Reported-by: Steve Dickson Reported-by: Trond Myklebust Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 1a1ff247bc59..a7cee864e7b2 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -296,7 +296,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru nfsd4_set_open_owner_reply_cache(cstate, open, resfh); accmode = NFSD_MAY_NOP; - if (open->op_created) + if (open->op_created || + open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR) accmode |= NFSD_MAY_OWNER_OVERRIDE; status = do_open_permission(rqstp, resfh, open, accmode); set_change_info(&open->op_cinfo, current_fh); -- GitLab From 0a262ffb75275e48caa17e80b96504354e94f6c2 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 17 Jun 2013 17:29:40 -0400 Subject: [PATCH 2132/2900] nfsd4: do not throw away 4.1 lock state on last unlock This reverts commit eb2099f31b0f090684a64ef8df44a30ff7c45fc2 "nfsd4: release lockowners on last unlock in 4.1 case". Trond identified language in rfc 5661 section 8.2.4 which forbids this behavior: Stateids associated with byte-range locks are an exception. They remain valid even if a LOCKU frees all remaining locks, so long as the open file with which they are associated remains open, unless the client frees the stateids via the FREE_STATEID operation. And bakeathon 2013 testing found a 4.1 freebsd client was getting an incorrect BAD_STATEID return from a FREE_STATEID in the above situation and then failing. The spec language honestly was probably a mistake but at this point with implementations already following it we're probably stuck with that. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fcc0610fe308..a7d8a11943ee 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4514,7 +4514,6 @@ __be32 nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_locku *locku) { - struct nfs4_lockowner *lo; struct nfs4_ol_stateid *stp; struct file *filp = NULL; struct file_lock *file_lock = NULL; @@ -4547,10 +4546,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfserr_jukebox; goto out; } - lo = lockowner(stp->st_stateowner); locks_init_lock(file_lock); file_lock->fl_type = F_UNLCK; - file_lock->fl_owner = (fl_owner_t)lo; + file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); file_lock->fl_pid = current->tgid; file_lock->fl_file = filp; file_lock->fl_flags = FL_POSIX; @@ -4569,11 +4567,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, update_stateid(&stp->st_stid.sc_stateid); memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); - if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) { - WARN_ON_ONCE(cstate->replay_owner); - release_lockowner(lo); - } - out: nfsd4_bump_seqid(cstate, status); if (!cstate->replay_owner) -- GitLab From d08d32e6e5c0fee127d3b20d70f5b59d8af0a261 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 21 Jun 2013 11:05:32 -0400 Subject: [PATCH 2133/2900] nfsd4: return delegation immediately if lease fails This case shouldn't happen--the administrator shouldn't really allow other applications access to the export until clients have had the chance to reclaim their state--but if it does then we should set the "return this lease immediately" bit on the reply. That still leaves some small races, but it's the best the protocol allows us to do in the case a lease is ripped out from under us.... Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a7d8a11943ee..d44a4bf71cef 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3143,8 +3143,10 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh, out_no_deleg: open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE; if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && - open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) + open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) { dprintk("NFSD: WARNING: refusing delegation reclaim\n"); + open->op_recall = 1; + } /* 4.1 client asking for a delegation? */ if (open->op_deleg_want) -- GitLab From f9e1aedc6c79f18bb56caa3735b94217c4ec1e0c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Jun 2013 12:53:42 +1000 Subject: [PATCH 2134/2900] sunrpc/cache: remove races with queuing an upcall. We currently queue an upcall after setting CACHE_PENDING, and dequeue after clearing CACHE_PENDING. So a request should only be present when CACHE_PENDING is set. However we don't combine the test and the enqueue/dequeue in a protected region, so it is possible (if unlikely) for a race to result in a request being queued without CACHE_PENDING set, or a request to be absent despite CACHE_PENDING. So: include a test for CACHE_PENDING inside the regions of enqueue and dequeue where queue_lock is held, and abort the operation if the value is not as expected. Also remove the early 'return' from cache_dequeue() to ensure that it always removes all entries: As there is no locking between setting CACHE_PENDING and calling sunrpc_cache_pipe_upcall it is not inconceivable for some other thread to clear CACHE_PENDING and then someone else to set it and call sunrpc_cache_pipe_upcall, both before the original threads completed the call. With this, it perfectly safe and correct to: - call cache_dequeue() if and only if we have just cleared CACHE_PENDING - call sunrpc_cache_pipe_upcall() (via cache_make_upcall) if and only if we have just set CACHE_PENDING. Reported-by: Bodo Stroesser Signed-off-by: NeilBrown Signed-off-by: Bodo Stroesser Signed-off-by: J. Bruce Fields --- net/sunrpc/cache.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 3b3f14fc02c5..8e964ae8d7b5 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1036,23 +1036,32 @@ static int cache_release(struct inode *inode, struct file *filp, static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) { - struct cache_queue *cq; + struct cache_queue *cq, *tmp; + struct cache_request *cr; + struct list_head dequeued; + + INIT_LIST_HEAD(&dequeued); spin_lock(&queue_lock); - list_for_each_entry(cq, &detail->queue, list) + list_for_each_entry_safe(cq, tmp, &detail->queue, list) if (!cq->reader) { - struct cache_request *cr = container_of(cq, struct cache_request, q); + cr = container_of(cq, struct cache_request, q); if (cr->item != ch) continue; + if (test_bit(CACHE_PENDING, &ch->flags)) + /* Lost a race and it is pending again */ + break; if (cr->readers != 0) continue; - list_del(&cr->q.list); - spin_unlock(&queue_lock); - cache_put(cr->item, detail); - kfree(cr->buf); - kfree(cr); - return; + list_move(&cr->q.list, &dequeued); } spin_unlock(&queue_lock); + while (!list_empty(&dequeued)) { + cr = list_entry(dequeued.next, struct cache_request, q.list); + list_del(&cr->q.list); + cache_put(cr->item, detail); + kfree(cr->buf); + kfree(cr); + } } /* @@ -1166,6 +1175,7 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) char *buf; struct cache_request *crq; + int ret = 0; if (!detail->cache_request) return -EINVAL; @@ -1191,10 +1201,18 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) crq->len = 0; crq->readers = 0; spin_lock(&queue_lock); - list_add_tail(&crq->q.list, &detail->queue); + if (test_bit(CACHE_PENDING, &h->flags)) + list_add_tail(&crq->q.list, &detail->queue); + else + /* Lost a race, no longer PENDING, so don't enqueue */ + ret = -EAGAIN; spin_unlock(&queue_lock); wake_up(&queue_wait); - return 0; + if (ret == -EAGAIN) { + kfree(buf); + kfree(crq); + } + return ret; } EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); -- GitLab From 2a1c7f53fd31e46f51780b61eb99fffef4c3c5a6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Jun 2013 12:53:42 +1000 Subject: [PATCH 2135/2900] sunrpc/cache: use cache_fresh_unlocked consistently and correctly. cache_fresh_unlocked() is called when a cache entry has been updated and ensures that if there were any pending upcalls, they are cleared. So every time we update a cache entry, we should call this, and this should be the only way that we try to clear pending calls (that sort of uniformity makes code sooo much easier to read). try_to_negate_entry() will (possibly) mark an entry as negative. If it doesn't, it is because the entry already is VALID. So the entry will be valid on exit, so it is appropriate to call cache_fresh_unlocked(). So tidy up try_to_negate_entry() to do that, and remove partial open-coded cache_fresh_unlocked() from the one call-site of try_to_negate_entry(). In the other branch of the 'switch(cache_make_upcall())', we again have a partial open-coded version of cache_fresh_unlocked(). Replace that with a real call. And again in cache_clean(), use a real call to cache_fresh_unlocked(). These call sites might previously have called cache_revisit_request() if CACHE_PENDING wasn't set. This is never necessary because cache_revisit_request() can only do anything if the item is in the cache_defer_hash, However any time that an item is added to the cache_defer_hash (setup_deferral), the code immediately tests CACHE_PENDING, and removes the entry again if it is clear. So all other places we only need to 'cache_revisit_request' if we've just cleared CACHE_PENDING. Reported-by: Bodo Stroesser Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields --- net/sunrpc/cache.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 8e964ae8d7b5..29c463396a2d 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -228,15 +228,14 @@ static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h write_lock(&detail->hash_lock); rv = cache_is_valid(h); - if (rv != -EAGAIN) { - write_unlock(&detail->hash_lock); - return rv; + if (rv == -EAGAIN) { + set_bit(CACHE_NEGATIVE, &h->flags); + cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); + rv = -ENOENT; } - set_bit(CACHE_NEGATIVE, &h->flags); - cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY); write_unlock(&detail->hash_lock); cache_fresh_unlocked(h, detail); - return -ENOENT; + return rv; } /* @@ -275,13 +274,10 @@ int cache_check(struct cache_detail *detail, if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { switch (cache_make_upcall(detail, h)) { case -EINVAL: - clear_bit(CACHE_PENDING, &h->flags); - cache_revisit_request(h); rv = try_to_negate_entry(detail, h); break; case -EAGAIN: - clear_bit(CACHE_PENDING, &h->flags); - cache_revisit_request(h); + cache_fresh_unlocked(h, detail); break; } } @@ -457,9 +453,7 @@ static int cache_clean(void) current_index ++; spin_unlock(&cache_list_lock); if (ch) { - if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) - cache_dequeue(current_detail, ch); - cache_revisit_request(ch); + cache_fresh_unlocked(ch, d); cache_put(ch, d); } } else -- GitLab From 013920eb5db97e99a4c30c8400f1c616e2a8b0a2 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Jun 2013 12:53:42 +1000 Subject: [PATCH 2136/2900] sunrpc/cache: ensure items removed from cache do not have pending upcalls. It is possible for a race to set CACHE_PENDING after cache_clean() has removed a cache entry from the cache. If CACHE_PENDING is still set when the entry is finally 'put', the cache_dequeue() will never happen and we can leak memory. So set a new flag 'CACHE_CLEANED' when we remove something from the cache, and don't queue any upcall if it is set. If CACHE_PENDING is set before CACHE_CLEANED, the call that cache_clean() makes to cache_fresh_unlocked() will free memory as needed. If CACHE_PENDING is set after CACHE_CLEANED, the test in sunrpc_cache_pipe_upcall will ensure that the memory is not allocated. Reported-by: Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/cache.h | 1 + net/sunrpc/cache.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 303399b1ba59..8419f7dbdab2 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -57,6 +57,7 @@ struct cache_head { #define CACHE_VALID 0 /* Entry contains valid data */ #define CACHE_NEGATIVE 1 /* Negative entry - there is no match for the key */ #define CACHE_PENDING 2 /* An upcall has been sent but no reply received yet*/ +#define CACHE_CLEANED 3 /* Entry has been cleaned from cache */ #define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */ diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 29c463396a2d..b12144c5edd0 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(cache_check); * a current pointer into that list and into the table * for that entry. * - * Each time clean_cache is called it finds the next non-empty entry + * Each time cache_clean is called it finds the next non-empty entry * in the current table and walks the list in that entry * looking for entries that can be removed. * @@ -453,6 +453,7 @@ static int cache_clean(void) current_index ++; spin_unlock(&cache_list_lock); if (ch) { + set_bit(CACHE_CLEANED, &ch->flags); cache_fresh_unlocked(ch, d); cache_put(ch, d); } @@ -1178,6 +1179,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h) warn_no_listener(detail); return -EINVAL; } + if (test_bit(CACHE_CLEANED, &h->flags)) + /* Too late to make an upcall */ + return -EAGAIN; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) -- GitLab From 7715cde86857d4bb40f43f1ee971cf906eaf1b9c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Jun 2013 12:53:42 +1000 Subject: [PATCH 2137/2900] net/sunrpc: xpt_auth_cache should be ignored when expired. commit d202cce8963d9268ff355a386e20243e8332b308 sunrpc: never return expired entries in sunrpc_cache_lookup moved the 'entry is expired' test from cache_check to sunrpc_cache_lookup, so that it happened early and some races could safely be ignored. However the ip_map (in svcauth_unix.c) has a separate single-item cache which allows quick lookup without locking. An entry in this case would not be subject to the expiry test and so could be used well after it has expired. This is not normally a big problem because the first time it is used after it is expired an up-call will be scheduled to refresh the entry (if it hasn't been scheduled already) and the old entry will then be invalidated. So on the second attempt to use it after it has expired, ip_map_cached_get will discard it. However that is subtle and not ideal, so replace the "!cache_valid" test with "cache_is_expired". In doing this we drop the test on the "CACHE_VALID" bit. This is unnecessary as the bit is never cleared, and an entry will only be cached if the bit is set. Reported-by: Bodo Stroesser Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/cache.h | 48 ++++++++++++++++-------------------- net/sunrpc/cache.c | 6 ----- net/sunrpc/svcauth_unix.c | 4 +-- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 8419f7dbdab2..6ce690de447f 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -149,6 +149,24 @@ struct cache_deferred_req { int too_many); }; +/* + * timestamps kept in the cache are expressed in seconds + * since boot. This is the best for measuring differences in + * real time. + */ +static inline time_t seconds_since_boot(void) +{ + struct timespec boot; + getboottime(&boot); + return get_seconds() - boot.tv_sec; +} + +static inline time_t convert_to_wallclock(time_t sinceboot) +{ + struct timespec boot; + getboottime(&boot); + return boot.tv_sec + sinceboot; +} extern const struct file_operations cache_file_operations_pipefs; extern const struct file_operations content_file_operations_pipefs; @@ -182,15 +200,10 @@ static inline void cache_put(struct cache_head *h, struct cache_detail *cd) kref_put(&h->ref, cd->cache_put); } -static inline int cache_valid(struct cache_head *h) +static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h) { - /* If an item has been unhashed pending removal when - * the refcount drops to 0, the expiry_time will be - * set to 0. We don't want to consider such items - * valid in this context even though CACHE_VALID is - * set. - */ - return (h->expiry_time != 0 && test_bit(CACHE_VALID, &h->flags)); + return (h->expiry_time < seconds_since_boot()) || + (detail->flush_time > h->last_refresh); } extern int cache_check(struct cache_detail *detail, @@ -251,25 +264,6 @@ static inline int get_uint(char **bpp, unsigned int *anint) return 0; } -/* - * timestamps kept in the cache are expressed in seconds - * since boot. This is the best for measuring differences in - * real time. - */ -static inline time_t seconds_since_boot(void) -{ - struct timespec boot; - getboottime(&boot); - return get_seconds() - boot.tv_sec; -} - -static inline time_t convert_to_wallclock(time_t sinceboot) -{ - struct timespec boot; - getboottime(&boot); - return boot.tv_sec + sinceboot; -} - static inline time_t get_expiry(char **bpp) { int rv; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index b12144c5edd0..5478a015ab00 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -50,12 +50,6 @@ static void cache_init(struct cache_head *h) h->last_refresh = now; } -static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h) -{ - return (h->expiry_time < seconds_since_boot()) || - (detail->flush_time > h->last_refresh); -} - struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, struct cache_head *key, int hash) { diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 06bdf5a1082c..a98853dfccdc 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -347,13 +347,13 @@ ip_map_cached_get(struct svc_xprt *xprt) spin_lock(&xprt->xpt_lock); ipm = xprt->xpt_auth_cache; if (ipm != NULL) { - if (!cache_valid(&ipm->h)) { + sn = net_generic(xprt->xpt_net, sunrpc_net_id); + if (cache_is_expired(sn->ip_map_cache, &ipm->h)) { /* * The entry has been invalidated since it was * remembered, e.g. by a second mount from the * same IP address. */ - sn = net_generic(xprt->xpt_net, sunrpc_net_id); xprt->xpt_auth_cache = NULL; spin_unlock(&xprt->xpt_lock); cache_put(&ipm->h, sn->ip_map_cache); -- GitLab From 0bebc633f1428163c9659fd16b34c745e60a0757 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 13 Jun 2013 12:53:42 +1000 Subject: [PATCH 2138/2900] sunrpc: Don't schedule an upcall on a replaced cache entry. When a cache entry is replaced, the "expiry_time" get set to zero by a call to "cache_fresh_locked(..., 0)" at the end of "sunrpc_cache_update". This low expiry time makes cache_check() think that the 'refresh_age' is negative, so the 'age' is comparatively large and a refresh is triggered. However refreshing a replaced entry it pointless, it cannot achieve anything useful. So teach cache_check to ignore a low refresh_age when expiry_time is zero. Reported-by: Bodo Stroesser Signed-off-by: NeilBrown Signed-off-by: J. Bruce Fields --- net/sunrpc/cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 5478a015ab00..49eb37010aa3 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -262,7 +262,8 @@ int cache_check(struct cache_detail *detail, if (rqstp == NULL) { if (rv == -EAGAIN) rv = -ENOENT; - } else if (rv == -EAGAIN || age > refresh_age/2) { + } else if (rv == -EAGAIN || + (h->expiry_time != 0 && age > refresh_age/2)) { dprintk("RPC: Want update, refage=%ld, age=%ld\n", refresh_age, age); if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { -- GitLab From da002d8924a49e8d8e289d07d46339e12dd56899 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Jul 2013 20:56:18 +0100 Subject: [PATCH 2139/2900] mfd: wm8994: Remove duplicate check for active JACKDET Probably the result of a mismerge or rebase failing to notice that the hunk had already been applied. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8994-core.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index ccdddf919069..781115e8dca9 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -259,20 +259,6 @@ static int wm8994_suspend(struct device *dev) break; } - switch (wm8994->type) { - case WM1811: - ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2); - if (ret < 0) { - dev_err(dev, "Failed to read jackdet: %d\n", ret); - } else if (ret & WM1811_JACKDET_MODE_MASK) { - dev_dbg(dev, "CODEC still active, ignoring suspend\n"); - return 0; - } - break; - default: - break; - } - /* Disable LDO pulldowns while the device is suspended if we * don't know that something will be driving them. */ if (!wm8994->ldo_ena_always_driven) -- GitLab From 25f311fa58c18c19ae1348336265ccb8368638f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Jul 2013 23:02:19 +0100 Subject: [PATCH 2140/2900] mfd: sec: Provide max_register to regmap Enable debugfs register dumps and greater error checking within the regmap API providing the maximum register to the regmap API. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/sec-core.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index cc896d1c1cdd..79767681483a 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include static struct mfd_cell s5m8751_devs[] = { @@ -105,6 +108,26 @@ static struct regmap_config sec_regmap_config = { .val_bits = 8, }; +static struct regmap_config s2mps11_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S2MPS11_REG_L38CTRL, +}; + +static struct regmap_config s5m8763_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S5M8763_REG_LBCNFG2, +}; + +static struct regmap_config s5m8767_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = S5M8767_REG_LDO28CTRL, +}; #ifdef CONFIG_OF /* @@ -160,6 +183,7 @@ static int sec_pmic_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct sec_platform_data *pdata = i2c->dev.platform_data; + const struct regmap_config *regmap; struct sec_pmic_dev *sec_pmic; int ret; @@ -190,7 +214,22 @@ static int sec_pmic_probe(struct i2c_client *i2c, sec_pmic->pdata = pdata; } - sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); + switch (sec_pmic->device_type) { + case S2MPS11X: + regmap = &s2mps11_regmap_config; + break; + case S5M8763X: + regmap = &s5m8763_regmap_config; + break; + case S5M8767X: + regmap = &s5m8767_regmap_config; + break; + default: + regmap = &sec_regmap_config; + break; + } + + sec_pmic->regmap = devm_regmap_init_i2c(i2c, regmap); if (IS_ERR(sec_pmic->regmap)) { ret = PTR_ERR(sec_pmic->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", -- GitLab From 5a008ffa73b4401251d548c10cadac6f8a67cfb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 28 Jun 2013 17:17:49 +0200 Subject: [PATCH 2141/2900] net: qmi_wwan: fixup Sierra Wireless MC8305 entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MC8305 module got an additional entry added based solely on information from a Windows driver *.inf file. We now have the actual descriptor layout from one of these modules, and it consists of two alternate configurations where cfg #1 is a normal Gobi 2k layout and cfg #2 is MBIM only, using interface numbers 5 and 6 for MBIM control and data. The extra Windows driver entry for interface number 5 was most likely a bug. Deleting the bogus entry to avoid unnecessary qmi_wwan probe failures when using the MBIM configuration. Reported-by: Lana Black Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index d095d0d3056b..1d1021c50bc9 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -625,7 +625,6 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x1199, 0x9009)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9011)}, /* Sierra Wireless Gobi 2000 Modem device (MC8305) */ - {QMI_FIXED_INTF(0x1199, 0x9011, 5)}, /* alternate interface number!? */ {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ -- GitLab From aa3aba1cbcbe823bba623c7cab33d84ddf0fb6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 28 Jun 2013 17:17:50 +0200 Subject: [PATCH 2142/2900] net: qmi_wwan: add Option GTM681W MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A standard Gobi 3000 reference design module. Reported-by: Richard Weinberger Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 1d1021c50bc9..e4a0843b9bb6 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -612,6 +612,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x0af0, 0x8120)}, /* Option GTM681W */ {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ -- GitLab From d0b5e516298fba30774e2df22cfbd00ecb09c298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Fri, 28 Jun 2013 17:17:51 +0200 Subject: [PATCH 2143/2900] net: qmi_wwan: add TP-LINK MA260 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index e4a0843b9bb6..6de110263109 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -582,6 +582,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ + {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ {QMI_FIXED_INTF(0x1e2d, 0x12d1, 4)}, /* Cinterion PLxx */ -- GitLab From 6e94a780374ed31b280f939d4757e8d7858dff16 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 27 Jun 2013 10:58:31 -0400 Subject: [PATCH 2144/2900] tracing: Failed to create system directory Running the following: # cd /sys/kernel/debug/tracing # echo p:i do_sys_open > kprobe_events # echo p:j schedule >> kprobe_events # cat kprobe_events p:kprobes/i do_sys_open p:kprobes/j schedule # echo p:i do_sys_open >> kprobe_events # cat kprobe_events p:kprobes/j schedule p:kprobes/i do_sys_open # ls /sys/kernel/debug/tracing/events/kprobes/ enable filter j Notice that the 'i' is missing from the kprobes directory. The console produces: "Failed to create system directory kprobes" This is because kprobes passes in a allocated name for the system and the ftrace event subsystem saves off that name instead of creating a duplicate for it. But the kprobes may free the system name making the pointer to it invalid. This bug was introduced by 92edca073c37 "tracing: Use direct field, type and system names" which switched from using kstrdup() on the system name in favor of just keeping apointer to it, as the internal ftrace event system names are static and exist for the life of the computer being booted. Instead of reverting back to duplicating system names again, we can use core_kernel_data() to determine if the passed in name was allocated or static. Then use the MSB of the ref_count to be a flag to keep track if the name was allocated or not. Then we can still save from having to duplicate strings that will always exist, but still copy the ones that may be freed. Cc: stable@vger.kernel.org # 3.10 Reported-by: "zhangwei(Jovi)" Reported-by: Masami Hiramatsu Tested-by: Masami Hiramatsu Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 41 +++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index f57b01574a30..903a0bf2685e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -41,6 +41,23 @@ static LIST_HEAD(ftrace_common_fields); static struct kmem_cache *field_cachep; static struct kmem_cache *file_cachep; +#define SYSTEM_FL_FREE_NAME (1 << 31) + +static inline int system_refcount(struct event_subsystem *system) +{ + return system->ref_count & ~SYSTEM_FL_FREE_NAME; +} + +static int system_refcount_inc(struct event_subsystem *system) +{ + return (system->ref_count++) & ~SYSTEM_FL_FREE_NAME; +} + +static int system_refcount_dec(struct event_subsystem *system) +{ + return (--system->ref_count) & ~SYSTEM_FL_FREE_NAME; +} + /* Double loops, do not use break, only goto's work */ #define do_for_each_event_file(tr, file) \ list_for_each_entry(tr, &ftrace_trace_arrays, list) { \ @@ -344,8 +361,8 @@ static void __put_system(struct event_subsystem *system) { struct event_filter *filter = system->filter; - WARN_ON_ONCE(system->ref_count == 0); - if (--system->ref_count) + WARN_ON_ONCE(system_refcount(system) == 0); + if (system_refcount_dec(system)) return; list_del(&system->list); @@ -354,13 +371,15 @@ static void __put_system(struct event_subsystem *system) kfree(filter->filter_string); kfree(filter); } + if (system->ref_count & SYSTEM_FL_FREE_NAME) + kfree(system->name); kfree(system); } static void __get_system(struct event_subsystem *system) { - WARN_ON_ONCE(system->ref_count == 0); - system->ref_count++; + WARN_ON_ONCE(system_refcount(system) == 0); + system_refcount_inc(system); } static void __get_system_dir(struct ftrace_subsystem_dir *dir) @@ -374,7 +393,7 @@ static void __put_system_dir(struct ftrace_subsystem_dir *dir) { WARN_ON_ONCE(dir->ref_count == 0); /* If the subsystem is about to be freed, the dir must be too */ - WARN_ON_ONCE(dir->subsystem->ref_count == 1 && dir->ref_count != 1); + WARN_ON_ONCE(system_refcount(dir->subsystem) == 1 && dir->ref_count != 1); __put_system(dir->subsystem); if (!--dir->ref_count) @@ -1274,7 +1293,15 @@ create_new_subsystem(const char *name) return NULL; system->ref_count = 1; - system->name = name; + + /* Only allocate if dynamic (kprobes and modules) */ + if (!core_kernel_data((unsigned long)name)) { + system->ref_count |= SYSTEM_FL_FREE_NAME; + system->name = kstrdup(name, GFP_KERNEL); + if (!system->name) + goto out_free; + } else + system->name = name; system->filter = NULL; @@ -1287,6 +1314,8 @@ create_new_subsystem(const char *name) return system; out_free: + if (system->ref_count & SYSTEM_FL_FREE_NAME) + kfree(system->name); kfree(system); return NULL; } -- GitLab From 288e984e622336bab8bc3dfdf2f190816362d9a1 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 20 Jun 2013 19:38:06 +0200 Subject: [PATCH 2145/2900] tracing/kprobes: Avoid perf_trace_buf_*() if ->perf_events is empty perf_trace_buf_prepare() + perf_trace_buf_submit() make no sense if this task/CPU has no active counters. Change kprobe_perf_func() and kretprobe_perf_func() to check call->perf_events beforehand and return if this list is empty. For example, "perf record -e some_probe -p1". Only /sbin/init will report, all other threads which hit the same probe will do perf_trace_buf_prepare/perf_trace_buf_submit just to realize that nobody wants perf_swevent_event(). Link: http://lkml.kernel.org/r/20130620173806.GA13151@redhat.com Acked-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index f2374172ba7b..c35bebe53ffe 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1156,6 +1156,10 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) int size, __size, dsize; int rctx; + head = this_cpu_ptr(call->perf_events); + if (hlist_empty(head)) + return; + dsize = __get_data_size(tp, regs); __size = sizeof(*entry) + tp->size + dsize; size = ALIGN(__size + sizeof(u32), sizeof(u64)); @@ -1171,8 +1175,6 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) entry->ip = (unsigned long)tp->rp.kp.addr; memset(&entry[1], 0, dsize); store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); - - head = this_cpu_ptr(call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head, NULL); } @@ -1188,6 +1190,10 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, int size, __size, dsize; int rctx; + head = this_cpu_ptr(call->perf_events); + if (hlist_empty(head)) + return; + dsize = __get_data_size(tp, regs); __size = sizeof(*entry) + tp->size + dsize; size = ALIGN(__size + sizeof(u32), sizeof(u64)); @@ -1203,8 +1209,6 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, entry->func = (unsigned long)tp->rp.kp.addr; entry->ret_ip = (unsigned long)ri->ret_addr; store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); - - head = this_cpu_ptr(call->perf_events); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head, NULL); } -- GitLab From 3fe3d6193e7cd7b4dd2bde10772f048bdefea4ee Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 20 Jun 2013 19:38:09 +0200 Subject: [PATCH 2146/2900] tracing/kprobes: Kill probe_enable_lock enable_trace_probe() and disable_trace_probe() should not worry about serialization, the caller (perf_trace_init or __ftrace_set_clr_event) holds event_mutex. They are also called by kprobe_trace_self_tests_init(), but this __init function can't race with itself or trace_events.c And note that this code depended on event_mutex even before 41a7dd420c which introduced probe_enable_lock. In fact it assumes that the caller kprobe_register() can never race with itself. Otherwise, say, tp->flags manipulations are racy. Link: http://lkml.kernel.org/r/20130620173809.GA13158@redhat.com Acked-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 43 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index c35bebe53ffe..282f86cfd304 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -183,16 +183,15 @@ static struct trace_probe *find_trace_probe(const char *event, return NULL; } +/* + * This and enable_trace_probe/disable_trace_probe rely on event_mutex + * held by the caller, __ftrace_set_clr_event(). + */ static int trace_probe_nr_files(struct trace_probe *tp) { - struct ftrace_event_file **file; + struct ftrace_event_file **file = rcu_dereference_raw(tp->files); int ret = 0; - /* - * Since all tp->files updater is protected by probe_enable_lock, - * we don't need to lock an rcu_read_lock. - */ - file = rcu_dereference_raw(tp->files); if (file) while (*(file++)) ret++; @@ -200,8 +199,6 @@ static int trace_probe_nr_files(struct trace_probe *tp) return ret; } -static DEFINE_MUTEX(probe_enable_lock); - /* * Enable trace_probe * if the file is NULL, enable "perf" handler, or enable "trace" handler. @@ -211,8 +208,6 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) { int ret = 0; - mutex_lock(&probe_enable_lock); - if (file) { struct ftrace_event_file **new, **old; int n = trace_probe_nr_files(tp); @@ -223,7 +218,7 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) GFP_KERNEL); if (!new) { ret = -ENOMEM; - goto out_unlock; + goto out; } memcpy(new, old, n * sizeof(struct ftrace_event_file *)); new[n] = file; @@ -246,10 +241,7 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) else ret = enable_kprobe(&tp->rp.kp); } - - out_unlock: - mutex_unlock(&probe_enable_lock); - + out: return ret; } @@ -282,8 +274,6 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) { int ret = 0; - mutex_lock(&probe_enable_lock); - if (file) { struct ftrace_event_file **new, **old; int n = trace_probe_nr_files(tp); @@ -292,7 +282,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) old = rcu_dereference_raw(tp->files); if (n == 0 || trace_probe_file_index(tp, file) < 0) { ret = -EINVAL; - goto out_unlock; + goto out; } if (n == 1) { /* Remove the last file */ @@ -303,7 +293,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) GFP_KERNEL); if (!new) { ret = -ENOMEM; - goto out_unlock; + goto out; } /* This copy & check loop copies the NULL stopper too */ @@ -326,10 +316,7 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) else disable_kprobe(&tp->rp.kp); } - - out_unlock: - mutex_unlock(&probe_enable_lock); - + out: return ret; } @@ -1214,6 +1201,12 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, } #endif /* CONFIG_PERF_EVENTS */ +/* + * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. + * + * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe + * lockless, but we can't race with this __init function. + */ static __kprobes int kprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data) @@ -1379,6 +1372,10 @@ find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr) return NULL; } +/* + * Nobody but us can call enable_trace_probe/disable_trace_probe at this + * stage, we can do this lockless. + */ static __init int kprobe_trace_self_tests_init(void) { int ret, warn = 0; -- GitLab From a439059610ecd257dba29a612729132e470d118f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 29 Jun 2013 00:08:04 -0500 Subject: [PATCH 2147/2900] tracing: Simplify code for showing of soft disabled flag Rather than enumerating each permutation, build the enable state string up from the combination of states. This also allows for the simpler addition of more states. Link: http://lkml.kernel.org/r/9aff5af6dee2f5a40ca30df41c39d5f33e998d7a.1372479499.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 903a0bf2685e..7ee08b95c384 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -638,17 +638,17 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct ftrace_event_file *file = filp->private_data; - char *buf; + char buf[4] = "0"; - if (file->flags & FTRACE_EVENT_FL_ENABLED) { - if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) - buf = "0*\n"; - else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE) - buf = "1*\n"; - else - buf = "1\n"; - } else - buf = "0\n"; + if (file->flags & FTRACE_EVENT_FL_ENABLED && + !(file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)) + strcpy(buf, "1"); + + if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED || + file->flags & FTRACE_EVENT_FL_SOFT_MODE) + strcat(buf, "*"); + + strcat(buf, "\n"); return simple_read_from_buffer(ubuf, cnt, ppos, buf, strlen(buf)); } -- GitLab From 44a6a4ee1aed0eada8f21e6db81b4cd099788f82 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 29 Jun 2013 00:08:05 -0500 Subject: [PATCH 2148/2900] tracing: Add missing syscall_metadata comment Add the missing syscall_metadata description for the enter_fields struct member. Link: http://lkml.kernel.org/r/74c3407cd1e5d37f2c5aaca637aa4d35f66f1aa2.1372479499.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- include/trace/syscall.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/trace/syscall.h b/include/trace/syscall.h index 84bc4197e736..fed853f3d7aa 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h @@ -16,6 +16,7 @@ * @nb_args: number of parameters it takes * @types: list of types as strings * @args: list of args as strings (args[i] matches types[i]) + * @enter_fields: list of fields for syscall_enter trace event * @enter_event: associated syscall_enter trace event * @exit_event: associated syscall_exit trace event */ -- GitLab From 3baa5e4cf224b8a55220cc841bb475e164b84ceb Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 29 Jun 2013 00:08:07 -0500 Subject: [PATCH 2149/2900] tracing: Fix disabling of soft disable The comment on the soft disable 'disable' case of __ftrace_event_enable_disable() states that the soft disable bit should be cleared in that case, but currently only the soft mode bit is actually cleared. This essentially leaves the standard non-soft-enable enable/disable paths as the only way to clear the soft disable flag, but the soft disable bit should also be cleared when removing a trigger with '!'. Also, the SOFT_DISABLED bit should never be set if SOFT_MODE is cleared. This fixes the above discrepancies. Link: http://lkml.kernel.org/r/b9c68dd50bc07019e6c67d3f9b29be4ef1b2badb.1372479499.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 7ee08b95c384..5892470bc2ee 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -291,9 +291,11 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, } call->class->reg(call, TRACE_REG_UNREGISTER, file); } - /* If in SOFT_MODE, just set the SOFT_DISABLE_BIT */ + /* If in SOFT_MODE, just set the SOFT_DISABLE_BIT, else clear it */ if (file->flags & FTRACE_EVENT_FL_SOFT_MODE) set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); + else + clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); break; case 1: /* -- GitLab From b04d52e368e2cf526abb2bab61f304eaea126af2 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 20 Jun 2013 19:38:14 +0200 Subject: [PATCH 2150/2900] tracing/kprobes: Turn trace_probe->files into list_head I think that "ftrace_event_file *trace_probe[]" complicates the code for no reason, turn it into list_head to simplify the code. enable_trace_probe() no longer needs synchronize_sched(). This needs the extra sizeof(list_head) memory for every attached ftrace_event_file, hopefully not a problem in this case. Link: http://lkml.kernel.org/r/20130620173814.GA13165@redhat.com Acked-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 138 ++++++++++-------------------------- 1 file changed, 37 insertions(+), 101 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 282f86cfd304..405b5b0f903e 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -35,12 +35,17 @@ struct trace_probe { const char *symbol; /* symbol name */ struct ftrace_event_class class; struct ftrace_event_call call; - struct ftrace_event_file * __rcu *files; + struct list_head files; ssize_t size; /* trace entry size */ unsigned int nr_args; struct probe_arg args[]; }; +struct event_file_link { + struct ftrace_event_file *file; + struct list_head list; +}; + #define SIZEOF_TRACE_PROBE(n) \ (offsetof(struct trace_probe, args) + \ (sizeof(struct probe_arg) * (n))) @@ -150,6 +155,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, goto error; INIT_LIST_HEAD(&tp->list); + INIT_LIST_HEAD(&tp->files); return tp; error: kfree(tp->call.name); @@ -183,22 +189,6 @@ static struct trace_probe *find_trace_probe(const char *event, return NULL; } -/* - * This and enable_trace_probe/disable_trace_probe rely on event_mutex - * held by the caller, __ftrace_set_clr_event(). - */ -static int trace_probe_nr_files(struct trace_probe *tp) -{ - struct ftrace_event_file **file = rcu_dereference_raw(tp->files); - int ret = 0; - - if (file) - while (*(file++)) - ret++; - - return ret; -} - /* * Enable trace_probe * if the file is NULL, enable "perf" handler, or enable "trace" handler. @@ -209,29 +199,18 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) int ret = 0; if (file) { - struct ftrace_event_file **new, **old; - int n = trace_probe_nr_files(tp); - - old = rcu_dereference_raw(tp->files); - /* 1 is for new one and 1 is for stopper */ - new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), - GFP_KERNEL); - if (!new) { + struct event_file_link *link; + + link = kmalloc(sizeof(*link), GFP_KERNEL); + if (!link) { ret = -ENOMEM; goto out; } - memcpy(new, old, n * sizeof(struct ftrace_event_file *)); - new[n] = file; - /* The last one keeps a NULL */ - rcu_assign_pointer(tp->files, new); - tp->flags |= TP_FLAG_TRACE; + link->file = file; + list_add_tail_rcu(&link->list, &tp->files); - if (old) { - /* Make sure the probe is done with old files */ - synchronize_sched(); - kfree(old); - } + tp->flags |= TP_FLAG_TRACE; } else tp->flags |= TP_FLAG_PROFILE; @@ -245,24 +224,16 @@ enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) return ret; } -static int -trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) +static struct event_file_link * +find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file) { - struct ftrace_event_file **files; - int i; + struct event_file_link *link; - /* - * Since all tp->files updater is protected by probe_enable_lock, - * we don't need to lock an rcu_read_lock. - */ - files = rcu_dereference_raw(tp->files); - if (files) { - for (i = 0; files[i]; i++) - if (files[i] == file) - return i; - } + list_for_each_entry(link, &tp->files, list) + if (link->file == file) + return link; - return -1; + return NULL; } /* @@ -275,38 +246,23 @@ disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) int ret = 0; if (file) { - struct ftrace_event_file **new, **old; - int n = trace_probe_nr_files(tp); - int i, j; + struct event_file_link *link; - old = rcu_dereference_raw(tp->files); - if (n == 0 || trace_probe_file_index(tp, file) < 0) { + link = find_event_file_link(tp, file); + if (!link) { ret = -EINVAL; goto out; } - if (n == 1) { /* Remove the last file */ - tp->flags &= ~TP_FLAG_TRACE; - new = NULL; - } else { - new = kzalloc(n * sizeof(struct ftrace_event_file *), - GFP_KERNEL); - if (!new) { - ret = -ENOMEM; - goto out; - } - - /* This copy & check loop copies the NULL stopper too */ - for (i = 0, j = 0; j < n && i < n + 1; i++) - if (old[i] != file) - new[j++] = old[i]; - } + list_del_rcu(&link->list); + /* synchronize with kprobe_trace_func/kretprobe_trace_func */ + synchronize_sched(); + kfree(link); - rcu_assign_pointer(tp->files, new); + if (!list_empty(&tp->files)) + goto out; - /* Make sure the probe is done with old files */ - synchronize_sched(); - kfree(old); + tp->flags &= ~TP_FLAG_TRACE; } else tp->flags &= ~TP_FLAG_PROFILE; @@ -871,20 +827,10 @@ __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, static __kprobes void kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) { - /* - * Note: preempt is already disabled around the kprobe handler. - * However, we still need an smp_read_barrier_depends() corresponding - * to smp_wmb() in rcu_assign_pointer() to access the pointer. - */ - struct ftrace_event_file **file = rcu_dereference_raw(tp->files); - - if (unlikely(!file)) - return; + struct event_file_link *link; - while (*file) { - __kprobe_trace_func(tp, regs, *file); - file++; - } + list_for_each_entry_rcu(link, &tp->files, list) + __kprobe_trace_func(tp, regs, link->file); } /* Kretprobe handler */ @@ -931,20 +877,10 @@ static __kprobes void kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, struct pt_regs *regs) { - /* - * Note: preempt is already disabled around the kprobe handler. - * However, we still need an smp_read_barrier_depends() corresponding - * to smp_wmb() in rcu_assign_pointer() to access the pointer. - */ - struct ftrace_event_file **file = rcu_dereference_raw(tp->files); - - if (unlikely(!file)) - return; + struct event_file_link *link; - while (*file) { - __kretprobe_trace_func(tp, ri, regs, *file); - file++; - } + list_for_each_entry_rcu(link, &tp->files, list) + __kretprobe_trace_func(tp, ri, regs, link->file); } /* Event entry printers */ -- GitLab From 10246fa35d4ffdfe472185d4cbf9c2dfd9a9f023 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 1 Jul 2013 15:58:24 -0400 Subject: [PATCH 2151/2900] tracing: Use flag buffer_disabled for irqsoff tracer If the ring buffer is disabled and the irqsoff tracer records a trace it will clear out its buffer and lose the data it had previously recorded. Currently there's a callback when writing to the tracing_of file, but if tracing is disabled via the function tracer trigger, it will not inform the irqsoff tracer to stop recording. By using the "mirror" flag (buffer_disabled) in the trace_array, that keeps track of the status of the trace_array's buffer, it gives the irqsoff tracer a fast way to know if it should record a new trace or not. The flag may be a little behind the real state of the buffer, but it should not affect the trace too much. It's more important for the irqsoff tracer to be fast. Reported-by: Dave Jones Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 101 ++++++++++++++++++++++++----------- kernel/trace/trace_irqsoff.c | 4 +- 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c4c9296b1916..0dc50711d656 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -226,9 +226,24 @@ cycle_t ftrace_now(int cpu) return ts; } +/** + * tracing_is_enabled - Show if global_trace has been disabled + * + * Shows if the global trace has been enabled or not. It uses the + * mirror flag "buffer_disabled" to be used in fast paths such as for + * the irqsoff tracer. But it may be inaccurate due to races. If you + * need to know the accurate state, use tracing_is_on() which is a little + * slower, but accurate. + */ int tracing_is_enabled(void) { - return tracing_is_on(); + /* + * For quick access (irqsoff uses this in fast path), just + * return the mirror variable of the state of the ring buffer. + * It's a little racy, but we don't really care. + */ + smp_rmb(); + return !global_trace.buffer_disabled; } /* @@ -341,6 +356,23 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE | TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION; +void tracer_tracing_on(struct trace_array *tr) +{ + if (tr->trace_buffer.buffer) + ring_buffer_record_on(tr->trace_buffer.buffer); + /* + * This flag is looked at when buffers haven't been allocated + * yet, or by some tracers (like irqsoff), that just want to + * know if the ring buffer has been disabled, but it can handle + * races of where it gets disabled but we still do a record. + * As the check is in the fast path of the tracers, it is more + * important to be fast than accurate. + */ + tr->buffer_disabled = 0; + /* Make the flag seen by readers */ + smp_wmb(); +} + /** * tracing_on - enable tracing buffers * @@ -349,15 +381,7 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | */ void tracing_on(void) { - if (global_trace.trace_buffer.buffer) - ring_buffer_record_on(global_trace.trace_buffer.buffer); - /* - * This flag is only looked at when buffers haven't been - * allocated yet. We don't really care about the race - * between setting this flag and actually turning - * on the buffer. - */ - global_trace.buffer_disabled = 0; + tracer_tracing_on(&global_trace); } EXPORT_SYMBOL_GPL(tracing_on); @@ -551,6 +575,23 @@ void tracing_snapshot_alloc(void) EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); #endif /* CONFIG_TRACER_SNAPSHOT */ +void tracer_tracing_off(struct trace_array *tr) +{ + if (tr->trace_buffer.buffer) + ring_buffer_record_off(tr->trace_buffer.buffer); + /* + * This flag is looked at when buffers haven't been allocated + * yet, or by some tracers (like irqsoff), that just want to + * know if the ring buffer has been disabled, but it can handle + * races of where it gets disabled but we still do a record. + * As the check is in the fast path of the tracers, it is more + * important to be fast than accurate. + */ + tr->buffer_disabled = 1; + /* Make the flag seen by readers */ + smp_wmb(); +} + /** * tracing_off - turn off tracing buffers * @@ -561,15 +602,7 @@ EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); */ void tracing_off(void) { - if (global_trace.trace_buffer.buffer) - ring_buffer_record_off(global_trace.trace_buffer.buffer); - /* - * This flag is only looked at when buffers haven't been - * allocated yet. We don't really care about the race - * between setting this flag and actually turning - * on the buffer. - */ - global_trace.buffer_disabled = 1; + tracer_tracing_off(&global_trace); } EXPORT_SYMBOL_GPL(tracing_off); @@ -579,14 +612,25 @@ void disable_trace_on_warning(void) tracing_off(); } +/** + * tracer_tracing_is_on - show real state of ring buffer enabled + * @tr : the trace array to know if ring buffer is enabled + * + * Shows real state of the ring buffer if it is enabled or not. + */ +int tracer_tracing_is_on(struct trace_array *tr) +{ + if (tr->trace_buffer.buffer) + return ring_buffer_record_is_on(tr->trace_buffer.buffer); + return !tr->buffer_disabled; +} + /** * tracing_is_on - show state of ring buffers enabled */ int tracing_is_on(void) { - if (global_trace.trace_buffer.buffer) - return ring_buffer_record_is_on(global_trace.trace_buffer.buffer); - return !global_trace.buffer_disabled; + return tracer_tracing_is_on(&global_trace); } EXPORT_SYMBOL_GPL(tracing_is_on); @@ -3958,7 +4002,7 @@ static int tracing_wait_pipe(struct file *filp) * * iter->pos will be 0 if we haven't read anything. */ - if (!tracing_is_enabled() && iter->pos) + if (!tracing_is_on() && iter->pos) break; } @@ -5631,15 +5675,10 @@ rb_simple_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { struct trace_array *tr = filp->private_data; - struct ring_buffer *buffer = tr->trace_buffer.buffer; char buf[64]; int r; - if (buffer) - r = ring_buffer_record_is_on(buffer); - else - r = 0; - + r = tracer_tracing_is_on(tr); r = sprintf(buf, "%d\n", r); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); @@ -5661,11 +5700,11 @@ rb_simple_write(struct file *filp, const char __user *ubuf, if (buffer) { mutex_lock(&trace_types_lock); if (val) { - ring_buffer_record_on(buffer); + tracer_tracing_on(tr); if (tr->current_trace->start) tr->current_trace->start(tr); } else { - ring_buffer_record_off(buffer); + tracer_tracing_off(tr); if (tr->current_trace->stop) tr->current_trace->stop(tr); } diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index b19d065a28cb..2aefbee93a6d 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -373,7 +373,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip) struct trace_array_cpu *data; unsigned long flags; - if (likely(!tracer_enabled)) + if (!tracer_enabled || !tracing_is_enabled()) return; cpu = raw_smp_processor_id(); @@ -416,7 +416,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip) else return; - if (!tracer_enabled) + if (!tracer_enabled || !tracing_is_enabled()) return; data = per_cpu_ptr(tr->trace_buffer.data, cpu); -- GitLab From cf6735a4b103b801753748531e3658cdc8cafa5e Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 20 Jun 2013 19:38:11 +0200 Subject: [PATCH 2152/2900] tracing/kprobes: Don't pass addr=ip to perf_trace_buf_submit() kprobe_perf_func() and kretprobe_perf_func() pass addr=ip to perf_trace_buf_submit() for no reason. This sets perf_sample_data->addr for PERF_SAMPLE_ADDR, we already have perf_sample_data->ip initialized if PERF_SAMPLE_IP. Link: http://lkml.kernel.org/r/20130620173811.GA13161@redhat.com Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 405b5b0f903e..7ed6976493c8 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1098,8 +1098,7 @@ kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) entry->ip = (unsigned long)tp->rp.kp.addr; memset(&entry[1], 0, dsize); store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); - perf_trace_buf_submit(entry, size, rctx, - entry->ip, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); } /* Kretprobe profile handler */ @@ -1132,8 +1131,7 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, entry->func = (unsigned long)tp->rp.kp.addr; entry->ret_ip = (unsigned long)ri->ret_addr; store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); - perf_trace_buf_submit(entry, size, rctx, - entry->ret_ip, 1, regs, head, NULL); + perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); } #endif /* CONFIG_PERF_EVENTS */ -- GitLab From f1ed7c741fcd0c3d7d318e7c19813d89934b9296 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Thu, 27 Jun 2013 22:18:06 -0400 Subject: [PATCH 2153/2900] ftrace: Do not run selftest if command line parameter is set If the kernel command line ftrace filter parameters are set (ftrace_filter or ftrace_notrace), force the function self test to pass, with a warning why it was forced. If the user adds a filter to the kernel command line, it is assumed that they know what they are doing, and the self test should just not run instead of failing (which disables function tracing) or clearing the filter, as that will probably annoy the user. If the user wants the selftest to run, the message will tell them why it did not. Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 5 +++++ kernel/trace/trace.h | 1 + kernel/trace/trace_selftest.c | 18 ++++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 26e19105cdcc..67708f46baae 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3537,8 +3537,12 @@ EXPORT_SYMBOL_GPL(ftrace_set_global_notrace); static char ftrace_notrace_buf[FTRACE_FILTER_SIZE] __initdata; static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata; +/* Used by function selftest to not test if filter is set */ +bool ftrace_filter_param __initdata; + static int __init set_ftrace_notrace(char *str) { + ftrace_filter_param = true; strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE); return 1; } @@ -3546,6 +3550,7 @@ __setup("ftrace_notrace=", set_ftrace_notrace); static int __init set_ftrace_filter(char *str) { + ftrace_filter_param = true; strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE); return 1; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 711ca7d3e7f1..a88939e666b7 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -776,6 +776,7 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags) extern struct list_head ftrace_pids; #ifdef CONFIG_FUNCTION_TRACER +extern bool ftrace_filter_param __initdata; static inline int ftrace_trace_task(struct task_struct *task) { if (list_empty(&ftrace_pids)) diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 2901e3b88590..a7329b7902f8 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -640,13 +640,20 @@ trace_selftest_function_regs(void) * Enable ftrace, sleep 1/10 second, and then read the trace * buffer to see if all is in order. */ -int +__init int trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) { int save_ftrace_enabled = ftrace_enabled; unsigned long count; int ret; +#ifdef CONFIG_DYNAMIC_FTRACE + if (ftrace_filter_param) { + printk(KERN_CONT " ... kernel command line filter set: force PASS ... "); + return 0; + } +#endif + /* make sure msleep has been recorded */ msleep(1); @@ -727,13 +734,20 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace) * Pretty much the same than for the function tracer from which the selftest * has been borrowed. */ -int +__init int trace_selftest_startup_function_graph(struct tracer *trace, struct trace_array *tr) { int ret; unsigned long count; +#ifdef CONFIG_DYNAMIC_FTRACE + if (ftrace_filter_param) { + printk(KERN_CONT " ... kernel command line filter set: force PASS ... "); + return 0; + } +#endif + /* * Simulate the init() callback but we attach a watchdog callback * to detect and recover from possible hangs -- GitLab From aec0a40a6f78843c0ce73f7398230ee5184f896d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 28 Jun 2013 07:40:57 -0700 Subject: [PATCH 2154/2900] netem: use rb tree to implement the time queue Following typical setup to implement a ~100 ms RTT and big amount of reorders has very poor performance because netem implements the time queue using a linked list. ----------------------------------------------------------- ETH=eth0 IFB=ifb0 modprobe ifb ip link set dev $IFB up tc qdisc add dev $ETH ingress 2>/dev/null tc filter add dev $ETH parent ffff: \ protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress \ redirect dev $IFB ethtool -K $ETH gro off tso off gso off tc qdisc add dev $IFB root netem delay 50ms 10ms limit 100000 tc qd add dev $ETH root netem delay 50ms limit 100000 --------------------------------------------------------- Switch netem time queue to a rb tree, so this kind of setup can work at high speed. Signed-off-by: Eric Dumazet Cc: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/sch_netem.c | 109 ++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 24 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 3d2acc7a9c80..ed0082cf8eff 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,8 @@ */ struct netem_sched_data { - /* internal t(ime)fifo qdisc uses sch->q and sch->limit */ + /* internal t(ime)fifo qdisc uses t_root and sch->limit */ + struct rb_root t_root; /* optional qdisc for classful handling (NULL at netem init) */ struct Qdisc *qdisc; @@ -128,10 +130,35 @@ struct netem_sched_data { */ struct netem_skb_cb { psched_time_t time_to_send; + ktime_t tstamp_save; }; +/* Because space in skb->cb[] is tight, netem overloads skb->next/prev/tstamp + * to hold a rb_node structure. + * + * If struct sk_buff layout is changed, the following checks will complain. + */ +static struct rb_node *netem_rb_node(struct sk_buff *skb) +{ + BUILD_BUG_ON(offsetof(struct sk_buff, next) != 0); + BUILD_BUG_ON(offsetof(struct sk_buff, prev) != + offsetof(struct sk_buff, next) + sizeof(skb->next)); + BUILD_BUG_ON(offsetof(struct sk_buff, tstamp) != + offsetof(struct sk_buff, prev) + sizeof(skb->prev)); + BUILD_BUG_ON(sizeof(struct rb_node) > sizeof(skb->next) + + sizeof(skb->prev) + + sizeof(skb->tstamp)); + return (struct rb_node *)&skb->next; +} + +static struct sk_buff *netem_rb_to_skb(struct rb_node *rb) +{ + return (struct sk_buff *)rb; +} + static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb) { + /* we assume we can use skb next/prev/tstamp as storage for rb_node */ qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb)); return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data; } @@ -333,20 +360,23 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { - struct sk_buff_head *list = &sch->q; + struct netem_sched_data *q = qdisc_priv(sch); psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; - struct sk_buff *skb = skb_peek_tail(list); + struct rb_node **p = &q->t_root.rb_node, *parent = NULL; - /* Optimize for add at tail */ - if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) - return __skb_queue_tail(list, nskb); + while (*p) { + struct sk_buff *skb; - skb_queue_reverse_walk(list, skb) { + parent = *p; + skb = netem_rb_to_skb(parent); if (tnext >= netem_skb_cb(skb)->time_to_send) - break; + p = &parent->rb_right; + else + p = &parent->rb_left; } - - __skb_queue_after(list, skb, nskb); + rb_link_node(netem_rb_node(nskb), parent, p); + rb_insert_color(netem_rb_node(nskb), &q->t_root); + sch->q.qlen++; } /* @@ -436,23 +466,28 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) now = psched_get_time(); if (q->rate) { - struct sk_buff_head *list = &sch->q; + struct sk_buff *last; - if (!skb_queue_empty(list)) { + if (!skb_queue_empty(&sch->q)) + last = skb_peek_tail(&sch->q); + else + last = netem_rb_to_skb(rb_last(&q->t_root)); + if (last) { /* * Last packet in queue is reference point (now), * calculate this time bonus and subtract * from delay. */ - delay -= netem_skb_cb(skb_peek_tail(list))->time_to_send - now; + delay -= netem_skb_cb(last)->time_to_send - now; delay = max_t(psched_tdiff_t, 0, delay); - now = netem_skb_cb(skb_peek_tail(list))->time_to_send; + now = netem_skb_cb(last)->time_to_send; } delay += packet_len_2_sched_time(skb->len, q); } cb->time_to_send = now + delay; + cb->tstamp_save = skb->tstamp; ++q->counter; tfifo_enqueue(skb, sch); } else { @@ -476,6 +511,21 @@ static unsigned int netem_drop(struct Qdisc *sch) unsigned int len; len = qdisc_queue_drop(sch); + + if (!len) { + struct rb_node *p = rb_first(&q->t_root); + + if (p) { + struct sk_buff *skb = netem_rb_to_skb(p); + + rb_erase(p, &q->t_root); + sch->q.qlen--; + skb->next = NULL; + skb->prev = NULL; + len = qdisc_pkt_len(skb); + kfree_skb(skb); + } + } if (!len && q->qdisc && q->qdisc->ops->drop) len = q->qdisc->ops->drop(q->qdisc); if (len) @@ -488,19 +538,32 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) { struct netem_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; + struct rb_node *p; if (qdisc_is_throttled(sch)) return NULL; tfifo_dequeue: - skb = qdisc_peek_head(sch); + skb = __skb_dequeue(&sch->q); if (skb) { - const struct netem_skb_cb *cb = netem_skb_cb(skb); +deliver: + sch->qstats.backlog -= qdisc_pkt_len(skb); + qdisc_unthrottled(sch); + qdisc_bstats_update(sch, skb); + return skb; + } + p = rb_first(&q->t_root); + if (p) { + skb = netem_rb_to_skb(p); /* if more time remaining? */ - if (cb->time_to_send <= psched_get_time()) { - __skb_unlink(skb, &sch->q); - sch->qstats.backlog -= qdisc_pkt_len(skb); + if (netem_skb_cb(skb)->time_to_send <= psched_get_time()) { + rb_erase(p, &q->t_root); + + sch->q.qlen--; + skb->next = NULL; + skb->prev = NULL; + skb->tstamp = netem_skb_cb(skb)->tstamp_save; #ifdef CONFIG_NET_CLS_ACT /* @@ -522,10 +585,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) } goto tfifo_dequeue; } -deliver: - qdisc_unthrottled(sch); - qdisc_bstats_update(sch, skb); - return skb; + goto deliver; } if (q->qdisc) { @@ -533,7 +593,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) if (skb) goto deliver; } - qdisc_watchdog_schedule(&q->watchdog, cb->time_to_send); + qdisc_watchdog_schedule(&q->watchdog, + netem_skb_cb(skb)->time_to_send); } if (q->qdisc) { -- GitLab From 2d71619c59fac95a5415a326162fa046161b938c Mon Sep 17 00:00:00 2001 From: Alexander Z Lam Date: Mon, 1 Jul 2013 15:31:24 -0700 Subject: [PATCH 2155/2900] tracing: Make trace_marker use the correct per-instance buffer The trace_marker file was present for each new instance created, but it added the trace mark to the global trace buffer instead of to the instance's buffer. Link: http://lkml.kernel.org/r/1372717885-4543-2-git-send-email-azl@google.com Cc: David Sharp Cc: Vaibhav Nagarnaik Cc: Alexander Z Lam Cc: stable@vger.kernel.org # 3.10 Signed-off-by: Alexander Z Lam Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 0dc50711d656..e04e7119633d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4391,6 +4391,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) { unsigned long addr = (unsigned long)ubuf; + struct trace_array *tr = filp->private_data; struct ring_buffer_event *event; struct ring_buffer *buffer; struct print_entry *entry; @@ -4450,7 +4451,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, local_save_flags(irq_flags); size = sizeof(*entry) + cnt + 2; /* possible \n added */ - buffer = global_trace.trace_buffer.buffer; + buffer = tr->trace_buffer.buffer; event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size, irq_flags, preempt_count()); if (!event) { -- GitLab From 4ccb93ce7439b63c31bc7597bfffd13567fa483d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 28 Jun 2013 12:13:52 -0400 Subject: [PATCH 2156/2900] x25: Fix broken locking in ioctl error paths. Two of the x25 ioctl cases have error paths that break out of the function without unlocking the socket, leading to this warning: ================================================ [ BUG: lock held when returning to user space! ] 3.10.0-rc7+ #36 Not tainted ------------------------------------------------ trinity-child2/31407 is leaving the kernel with locks still held! 1 lock held by trinity-child2/31407: #0: (sk_lock-AF_X25){+.+.+.}, at: [] x25_ioctl+0x8a/0x740 [x25] Signed-off-by: Dave Jones Signed-off-by: David S. Miller --- net/x25/af_x25.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 1d964e23853f..45a3ab5612c1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1583,11 +1583,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25CALLACCPTAPPRV: { rc = -EINVAL; lock_sock(sk); - if (sk->sk_state != TCP_CLOSE) - break; - clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); + if (sk->sk_state == TCP_CLOSE) { + clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); + rc = 0; + } release_sock(sk); - rc = 0; break; } @@ -1595,14 +1595,15 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = -EINVAL; lock_sock(sk); if (sk->sk_state != TCP_ESTABLISHED) - break; + goto out_sendcallaccpt_release; /* must call accptapprv above */ if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags)) - break; + goto out_sendcallaccpt_release; x25_write_internal(sk, X25_CALL_ACCEPTED); x25->state = X25_STATE_3; - release_sock(sk); rc = 0; +out_sendcallaccpt_release: + release_sock(sk); break; } -- GitLab From b1a5a34bd0b8767ea689e68f8ea513e9710b671e Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Sat, 29 Jun 2013 00:15:51 +0800 Subject: [PATCH 2157/2900] net: Swap ver and type in pppoe_hdr Ver and type in pppoe_hdr should be swapped as defined by RFC2516 section-4. Signed-off-by: David S. Miller --- include/uapi/linux/if_pppox.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/if_pppox.h b/include/uapi/linux/if_pppox.h index 0b46fd57c8f6..e36a4aecd311 100644 --- a/include/uapi/linux/if_pppox.h +++ b/include/uapi/linux/if_pppox.h @@ -135,11 +135,11 @@ struct pppoe_tag { struct pppoe_hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 ver : 4; __u8 type : 4; + __u8 ver : 4; #elif defined(__BIG_ENDIAN_BITFIELD) - __u8 type : 4; __u8 ver : 4; + __u8 type : 4; #else #error "Please fix " #endif -- GitLab From 1eb14ea1e6bcd11d6d0ba937fc39808bb4d3453e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 1 Jul 2013 20:48:07 +0900 Subject: [PATCH 2158/2900] ARM: shmobile: emev2 GIO3 resource fix Fix GIO3 base addresses for EMEV2. This bug was introduced by 088efd9273b5076a0aead479aa31f1066d182b3e ("mach-shmobile: Emma Mobile EV2 GPIO support V3") which was included in v3.5. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman Cc: stable@vger.kernel.org --- arch/arm/mach-shmobile/setup-emev2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c index 899a86c31ec9..1ccddd228112 100644 --- a/arch/arm/mach-shmobile/setup-emev2.c +++ b/arch/arm/mach-shmobile/setup-emev2.c @@ -287,14 +287,14 @@ static struct gpio_em_config gio3_config = { static struct resource gio3_resources[] = { [0] = { .name = "GIO_096", - .start = 0xe0050100, - .end = 0xe005012b, + .start = 0xe0050180, + .end = 0xe00501ab, .flags = IORESOURCE_MEM, }, [1] = { .name = "GIO_096", - .start = 0xe0050140, - .end = 0xe005015f, + .start = 0xe00501c0, + .end = 0xe00501df, .flags = IORESOURCE_MEM, }, [2] = { -- GitLab From a82274151af2b075163e3c42c828529dee311487 Mon Sep 17 00:00:00 2001 From: Alexander Z Lam Date: Mon, 1 Jul 2013 19:37:54 -0700 Subject: [PATCH 2159/2900] tracing: Protect ftrace_trace_arrays list in trace_events.c There are multiple places where the ftrace_trace_arrays list is accessed in trace_events.c without the trace_types_lock held. Link: http://lkml.kernel.org/r/1372732674-22726-1-git-send-email-azl@google.com Cc: Vaibhav Nagarnaik Cc: David Sharp Cc: Alexander Z Lam Cc: stable@vger.kernel.org # 3.10 Signed-off-by: Alexander Z Lam Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 2 +- kernel/trace/trace.h | 2 ++ kernel/trace/trace_events.c | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e04e7119633d..e36da7ff59bf 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -266,7 +266,7 @@ static struct tracer *trace_types __read_mostly; /* * trace_types_lock is used to protect the trace_types list. */ -static DEFINE_MUTEX(trace_types_lock); +DEFINE_MUTEX(trace_types_lock); /* * serialize the access of the ring buffer diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index a88939e666b7..2c3cba59552d 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -224,6 +224,8 @@ enum { extern struct list_head ftrace_trace_arrays; +extern struct mutex trace_types_lock; + /* * The global tracer (top) should be the first trace array added, * but we check the flag anyway. diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 5892470bc2ee..35c6f23c71b2 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1008,6 +1008,7 @@ static int subsystem_open(struct inode *inode, struct file *filp) int ret; /* Make sure the system still exists */ + mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); list_for_each_entry(tr, &ftrace_trace_arrays, list) { list_for_each_entry(dir, &tr->systems, list) { @@ -1023,6 +1024,7 @@ static int subsystem_open(struct inode *inode, struct file *filp) } exit_loop: mutex_unlock(&event_mutex); + mutex_unlock(&trace_types_lock); if (!system) return -ENODEV; @@ -1617,6 +1619,7 @@ static void __add_event_to_tracers(struct ftrace_event_call *call, int trace_add_event_call(struct ftrace_event_call *call) { int ret; + mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); ret = __register_event(call, NULL); @@ -1624,11 +1627,13 @@ int trace_add_event_call(struct ftrace_event_call *call) __add_event_to_tracers(call, NULL); mutex_unlock(&event_mutex); + mutex_unlock(&trace_types_lock); return ret; } /* - * Must be called under locking both of event_mutex and trace_event_sem. + * Must be called under locking of trace_types_lock, event_mutex and + * trace_event_sem. */ static void __trace_remove_event_call(struct ftrace_event_call *call) { @@ -1640,11 +1645,13 @@ static void __trace_remove_event_call(struct ftrace_event_call *call) /* Remove an event_call */ void trace_remove_event_call(struct ftrace_event_call *call) { + mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); down_write(&trace_event_sem); __trace_remove_event_call(call); up_write(&trace_event_sem); mutex_unlock(&event_mutex); + mutex_unlock(&trace_types_lock); } #define for_each_event(event, start, end) \ @@ -1788,6 +1795,7 @@ static int trace_module_notify(struct notifier_block *self, { struct module *mod = data; + mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); switch (val) { case MODULE_STATE_COMING: @@ -1798,6 +1806,7 @@ static int trace_module_notify(struct notifier_block *self, break; } mutex_unlock(&event_mutex); + mutex_unlock(&trace_types_lock); return 0; } -- GitLab From 4f6de4d51f4a3ab06a85e91e708cc89a513ef30c Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 2 Jul 2013 15:35:11 +0930 Subject: [PATCH 2160/2900] module: don't modify argument of module_kallsyms_lookup_name() If we pass a pointer to a const string in the form "module:symbol" module_kallsyms_lookup_name() will try to split the string at the colon, i.e., will try to modify r/o data. That will, in fact, fail on a kernel with enabled CONFIG_DEBUG_RODATA. Avoid modifying the passed string in module_kallsyms_lookup_name(), modify find_module_all() instead to pass it the module name length. Signed-off-by: Mathias Krause Signed-off-by: Rusty Russell --- kernel/module.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index b049939177f6..a1951aba7a03 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -455,7 +455,7 @@ const struct kernel_symbol *find_symbol(const char *name, EXPORT_SYMBOL_GPL(find_symbol); /* Search for module by name: must hold module_mutex. */ -static struct module *find_module_all(const char *name, +static struct module *find_module_all(const char *name, size_t len, bool even_unformed) { struct module *mod; @@ -463,7 +463,7 @@ static struct module *find_module_all(const char *name, list_for_each_entry(mod, &modules, list) { if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) continue; - if (strcmp(mod->name, name) == 0) + if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) return mod; } return NULL; @@ -471,7 +471,7 @@ static struct module *find_module_all(const char *name, struct module *find_module(const char *name) { - return find_module_all(name, false); + return find_module_all(name, strlen(name), false); } EXPORT_SYMBOL_GPL(find_module); @@ -3027,7 +3027,7 @@ static bool finished_loading(const char *name) bool ret; mutex_lock(&module_mutex); - mod = find_module_all(name, true); + mod = find_module_all(name, strlen(name), true); ret = !mod || mod->state == MODULE_STATE_LIVE || mod->state == MODULE_STATE_GOING; mutex_unlock(&module_mutex); @@ -3165,7 +3165,8 @@ static int add_unformed_module(struct module *mod) again: mutex_lock(&module_mutex); - if ((old = find_module_all(mod->name, true)) != NULL) { + old = find_module_all(mod->name, strlen(mod->name), true); + if (old != NULL) { if (old->state == MODULE_STATE_COMING || old->state == MODULE_STATE_UNFORMED) { /* Wait in case it fails to load. */ @@ -3576,10 +3577,8 @@ unsigned long module_kallsyms_lookup_name(const char *name) /* Don't lock: we're in enough trouble already. */ preempt_disable(); if ((colon = strchr(name, ':')) != NULL) { - *colon = '\0'; - if ((mod = find_module(name)) != NULL) + if ((mod = find_module_all(name, colon - name, false)) != NULL) ret = mod_find_symname(mod, colon+1); - *colon = ':'; } else { list_for_each_entry_rcu(mod, &modules, list) { if (mod->state == MODULE_STATE_UNFORMED) -- GitLab From b634d130e46a093ddf716ae9cf1bfa258ede36cf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 2 Jul 2013 15:35:11 +0930 Subject: [PATCH 2161/2900] There is no /sys/parameters There is no such path as /sys/parameters, module parameters live in /sys/module/*/parameters. Signed-off-by: Jean Delvare Cc: Rusty Russell Signed-off-by: Rusty Russell --- include/linux/moduleparam.h | 2 +- kernel/params.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 137b4198fc03..27d9da3f86ff 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -439,7 +439,7 @@ extern struct kernel_param_ops param_ops_string; extern int param_set_copystring(const char *val, const struct kernel_param *); extern int param_get_string(char *buffer, const struct kernel_param *kp); -/* for exporting parameters in /sys/parameters */ +/* for exporting parameters in /sys/module/.../parameters */ struct module; diff --git a/kernel/params.c b/kernel/params.c index 53b958fcd639..440e65d1a544 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -787,7 +787,7 @@ static void __init kernel_add_sysfs_param(const char *name, } /* - * param_sysfs_builtin - add contents in /sys/parameters for built-in modules + * param_sysfs_builtin - add sysfs parameters for built-in modules * * Add module_parameters to sysfs for "modules" built into the kernel. * -- GitLab From 86f120031a21fe4e7333a84f55d9e243c781e6e9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 2 Jul 2013 15:35:11 +0930 Subject: [PATCH 2162/2900] ABI: Clarify when /sys/module/MODULENAME is created /sys/module/MODULENAME is not created unconditionally. This can be confusing so document the current conditions. Signed-off-by: Jean Delvare Cc: Rusty Russell Cc: Rob Landley Signed-off-by: Rusty Russell --- Documentation/ABI/stable/sysfs-module | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module index a0dd21c6db59..6272ae5fb366 100644 --- a/Documentation/ABI/stable/sysfs-module +++ b/Documentation/ABI/stable/sysfs-module @@ -4,9 +4,13 @@ Description: /sys/module/MODULENAME The name of the module that is in the kernel. This - module name will show up either if the module is built - directly into the kernel, or if it is loaded as a - dynamic module. + module name will always show up if the module is loaded as a + dynamic module. If it is built directly into the kernel, it + will only show up if it has a version or at least one + parameter. + + Note: The conditions of creation in the built-in case are not + by design and may be removed in the future. /sys/module/MODULENAME/parameters This directory contains individual files that are each -- GitLab From 54041d8a73337411b485ff76957fb106cb5d40d0 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 2 Jul 2013 15:35:12 +0930 Subject: [PATCH 2163/2900] modules: don't fail to load on unknown parameters. Although parameters are supposed to be part of the kernel API, experimental parameters are often removed. In addition, downgrading a kernel might cause previously-working modules to fail to load. On balance, it's probably better to warn, and load the module anyway. This may let through a typo, but at least the logs will show it. Reported-by: Andy Lutomirski Signed-off-by: Rusty Russell --- kernel/module.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/module.c b/kernel/module.c index a1951aba7a03..5184877ce98a 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3212,6 +3212,17 @@ static int complete_formation(struct module *mod, struct load_info *info) return err; } +static int unknown_module_param_cb(char *param, char *val, const char *modname) +{ + /* Check for magic 'dyndbg' arg */ + int ret = ddebug_dyndbg_module_param_cb(param, val, modname); + if (ret != 0) { + printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n", + modname, param); + } + return 0; +} + /* Allocate and load the module: note that size of section 0 is always zero, and we rely on this for optional sections. */ static int load_module(struct load_info *info, const char __user *uargs, @@ -3298,7 +3309,7 @@ static int load_module(struct load_info *info, const char __user *uargs, /* Module is ready to execute: parsing args may do that. */ err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, - -32768, 32767, &ddebug_dyndbg_module_param_cb); + -32768, 32767, unknown_module_param_cb); if (err < 0) goto bug_cleanup; -- GitLab From 95cc2c02cfe08b8bb910d2563725f96a5c48c327 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 2 Jul 2013 15:35:12 +0930 Subject: [PATCH 2164/2900] Fix comment typo "CONFIG_PAE" Signed-off-by: Paul Bolle Signed-off-by: Rusty Russell --- drivers/lguest/page_tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 5b9ac32801c7..a35d8d100165 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -70,7 +70,7 @@ /*H:320 * The page table code is curly enough to need helper functions to keep it * clear and clean. The kernel itself provides many of them; one advantage - * of insisting that the Guest and Host use the same CONFIG_PAE setting. + * of insisting that the Guest and Host use the same CONFIG_X86_PAE setting. * * There are two functions which return pointers to the shadow (aka "real") * page tables. -- GitLab From f11335db5e3901f6afc2eafa03a3b970562538b2 Mon Sep 17 00:00:00 2001 From: Andrew Vagin Date: Tue, 2 Jul 2013 15:35:13 +0930 Subject: [PATCH 2165/2900] virtio-pci: fix leaks of msix_affinity_masks vp_dev->msix_vectors should be initialized before allocating msix_affinity_masks, otherwise vp_free_vectors will not free these objects. unreferenced object 0xffff88010f969d88 (size 512): comm "systemd-udevd", pid 158, jiffies 4294673645 (age 80.545s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [] kmemleak_alloc+0x5e/0xc0 [] kmem_cache_alloc_node_trace+0x141/0x2c0 [] alloc_cpumask_var_node+0x23/0x80 [] alloc_cpumask_var+0xe/0x10 [] vp_try_to_find_vqs+0x25d/0x810 [] vp_find_vqs+0x81/0xb0 [] init_vqs+0x85/0x120 [virtio_balloon] [] virtballoon_probe+0xf9/0x1a0 [virtio_balloon] [] virtio_dev_probe+0xde/0x140 [] driver_probe_device+0x98/0x3a0 [] __driver_attach+0xab/0xb0 [] bus_for_each_dev+0x94/0xb0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x200/0x280 [] driver_register+0x74/0x160 [] register_virtio_driver+0x20/0x40 v2: change msix_vectors uncoditionaly in vp_free_vectors Cc: Rusty Russell Cc: "Michael S. Tsirkin" Cc: Jason Wang Signed-off-by: Andrew Vagin Acked-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: Rusty Russell --- drivers/virtio/virtio_pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index a7ce73029f59..1aba255b5879 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -289,9 +289,9 @@ static void vp_free_vectors(struct virtio_device *vdev) pci_disable_msix(vp_dev->pci_dev); vp_dev->msix_enabled = 0; - vp_dev->msix_vectors = 0; } + vp_dev->msix_vectors = 0; vp_dev->msix_used_vectors = 0; kfree(vp_dev->msix_names); vp_dev->msix_names = NULL; @@ -309,6 +309,8 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, unsigned i, v; int err = -ENOMEM; + vp_dev->msix_vectors = nvectors; + vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, GFP_KERNEL); if (!vp_dev->msix_entries) @@ -336,7 +338,6 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, err = -ENOSPC; if (err) goto error; - vp_dev->msix_vectors = nvectors; vp_dev->msix_enabled = 1; /* Set the vector used for configuration */ -- GitLab From 8c6bab4f3874d31804a00782c48a8f244a0d3cc0 Mon Sep 17 00:00:00 2001 From: Luiz Capitulino Date: Tue, 2 Jul 2013 15:35:13 +0930 Subject: [PATCH 2166/2900] virtio_balloon: leak_balloon(): only tell host if we got pages deflated balloon_page_dequeue() can return NULL. If it does for the first page being freed then leak_balloon() will create a scatter list with len=0. Which in turn seems to generate an invalid virtio request. I didn't get this in practice, I found it by code review. On the other hand, such an invalid virtio request will cause errors in QEMU and fill_balloon() also performs the same check implemented by this commit. This bug was introduced in e2250429. Signed-off-by: Luiz Capitulino Acked-by: Rafael Aquini Signed-off-by: Andrew Morton Signed-off-by: Rusty Russell Cc: stable@kernel.org # 3.9 --- drivers/virtio/virtio_balloon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index bd3ae324a1a2..71af7b5abe01 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -191,7 +191,8 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num) * virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); * is true, we *have* to do it in this order */ - tell_host(vb, vb->deflate_vq); + if (vb->num_pfns != 0) + tell_host(vb, vb->deflate_vq); mutex_unlock(&vb->balloon_lock); release_pages_by_pfn(vb->pfns, vb->num_pfns); } -- GitLab From 8fd9a6365eb8a79a2d8f0e0baa01f4db6345e8dd Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 2 Jul 2013 15:35:13 +0930 Subject: [PATCH 2167/2900] tools/lguest: fix missing rmb(). The virtio spec was missing a barrier in example code, so I went back to look at the lguest code. Indeed, we need one. Signed-off-by: Rusty Russell --- tools/lguest/lguest.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 07a03452c227..49ed25b5bbb9 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -177,6 +177,7 @@ static struct termios orig_term; * in precise order. */ #define wmb() __asm__ __volatile__("" : : : "memory") +#define rmb() __asm__ __volatile__("" : : : "memory") #define mb() __asm__ __volatile__("" : : : "memory") /* Wrapper for the last available index. Makes it easier to change. */ @@ -676,6 +677,12 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, errx(1, "Guest moved used index from %u to %u", last_avail, vq->vring.avail->idx); + /* + * Make sure we read the descriptor number *after* we read the ring + * update; don't let the cpu or compiler change the order. + */ + rmb(); + /* * Grab the next descriptor number they're advertising, and increment * the index we've seen. @@ -694,6 +701,12 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq, desc = vq->vring.desc; i = head; + /* + * We have to read the descriptor after we read the descriptor number, + * but there's a data dependency there so the CPU shouldn't reorder + * that: no rmb() required. + */ + /* * If this is an indirect entry, then this buffer contains a descriptor * table which we handle as if it's any normal descriptor chain. -- GitLab From 0d69a65e97fc8090ee83c8639137b4b5c8ece237 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 2 Jul 2013 15:35:14 +0930 Subject: [PATCH 2168/2900] tools/lguest: real barriers. Lguest guests are UP, but the host is probably SMP, so real barriers are required in case the device thread and the guest are on different CPUs. Signed-off-by: Rusty Russell --- tools/lguest/lguest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index 49ed25b5bbb9..a64f5cb0c15b 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -177,8 +177,8 @@ static struct termios orig_term; * in precise order. */ #define wmb() __asm__ __volatile__("" : : : "memory") -#define rmb() __asm__ __volatile__("" : : : "memory") -#define mb() __asm__ __volatile__("" : : : "memory") +#define rmb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory") +#define mb() __asm__ __volatile__("lock; addl $0,0(%%esp)" : : : "memory") /* Wrapper for the last available index. Makes it easier to change. */ #define lg_last_avail(vq) ((vq)->last_avail_idx) -- GitLab From 1067964305df131ede2c08c2f3c9b3892640f1c6 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 28 Jun 2013 19:49:39 +0200 Subject: [PATCH 2169/2900] lib: vsprintf: add IPv4/v6 generic %p[Ii]S[pfs] format specifier In order to avoid making code that deals with printing both, IPv4 and IPv6 addresses, unnecessary complicated as for example ... if (sa.sa_family == AF_INET6) printk("... %pI6 ...", ..sin6_addr); else printk("... %pI4 ...", ..sin_addr.s_addr); ... it would be better to introduce a format specifier that can deal with those kind of situations internally; just as we have a "struct sockaddr" for generic mapping into "struct sockaddr_in" or "struct sockaddr_in6" as e.g. done in "union sctp_addr". Then, we could reduce the above statement into something like: printk("... %pIS ..", &sockaddr); In case our pointer is NULL, pointer() then deals with that already at an earlier point in time internally. While we're at it, support for both %piS/%pIS, where 'S' stands for sockaddr, comes (almost) for free. Additionally to that, postfix specifiers 'p', 'f' and 's' are supported as suggested and initially implemented in 2009 by Joe Perches [1]. Handling of those additional specifiers orientate on the initial RFC that was proposed. Also we support IPv6 compressed format specified by 'c' and various other IPv4 extensions as stated in the documentation part. Likely, there are many other areas than just SCTP in the kernel to make use of this extension as well. [1] http://patchwork.ozlabs.org/patch/31480/ Signed-off-by: Daniel Borkmann CC: Joe Perches CC: linux-kernel@vger.kernel.org Signed-off-by: David S. Miller --- Documentation/printk-formats.txt | 32 ++++++++ lib/vsprintf.c | 124 ++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 2 deletions(-) diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt index 3af5ae6c9c11..3e8cb73ac43c 100644 --- a/Documentation/printk-formats.txt +++ b/Documentation/printk-formats.txt @@ -121,6 +121,38 @@ IPv6 addresses: print a compressed IPv6 address as described by http://tools.ietf.org/html/rfc5952 +IPv4/IPv6 addresses (generic, with port, flowinfo, scope): + + %pIS 1.2.3.4 or 0001:0002:0003:0004:0005:0006:0007:0008 + %piS 001.002.003.004 or 00010002000300040005000600070008 + %pISc 1.2.3.4 or 1:2:3:4:5:6:7:8 + %pISpc 1.2.3.4:12345 or [1:2:3:4:5:6:7:8]:12345 + %p[Ii]S[pfschnbl] + + For printing an IP address without the need to distinguish whether it's + of type AF_INET or AF_INET6, a pointer to a valid 'struct sockaddr', + specified through 'IS' or 'iS', can be passed to this format specifier. + + The additional 'p', 'f', and 's' specifiers are used to specify port + (IPv4, IPv6), flowinfo (IPv6) and scope (IPv6). Ports have a ':' prefix, + flowinfo a '/' and scope a '%', each followed by the actual value. + + In case of an IPv6 address the compressed IPv6 address as described by + http://tools.ietf.org/html/rfc5952 is being used if the additional + specifier 'c' is given. The IPv6 address is surrounded by '[', ']' in + case of additional specifiers 'p', 'f' or 's' as suggested by + https://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07 + + In case of IPv4 addresses, the additional 'h', 'n', 'b', and 'l' + specifiers can be used as well and are ignored in case of an IPv6 + address. + + Further examples: + + %pISfc 1.2.3.4 or [1:2:3:4:5:6:7:8]/123456789 + %pISsc 1.2.3.4 or [1:2:3:4:5:6:7:8]%1234567890 + %pISpfc 1.2.3.4:12345 or [1:2:3:4:5:6:7:8]:12345/123456789 + UUID/GUID addresses: %pUb 00010203-0405-0607-0809-0a0b0c0d0e0f diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e149c6416384..31febc0b70df 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -922,6 +922,103 @@ char *ip4_addr_string(char *buf, char *end, const u8 *addr, return string(buf, end, ip4_addr, spec); } +static noinline_for_stack +char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa, + struct printf_spec spec, const char *fmt) +{ + bool have_p = false, have_s = false, have_f = false, have_c = false; + char ip6_addr[sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + + sizeof(":12345") + sizeof("/123456789") + + sizeof("%1234567890")]; + char *p = ip6_addr, *pend = ip6_addr + sizeof(ip6_addr); + const u8 *addr = (const u8 *) &sa->sin6_addr; + char fmt6[2] = { fmt[0], '6' }; + u8 off = 0; + + fmt++; + while (isalpha(*++fmt)) { + switch (*fmt) { + case 'p': + have_p = true; + break; + case 'f': + have_f = true; + break; + case 's': + have_s = true; + break; + case 'c': + have_c = true; + break; + } + } + + if (have_p || have_s || have_f) { + *p = '['; + off = 1; + } + + if (fmt6[0] == 'I' && have_c) + p = ip6_compressed_string(ip6_addr + off, addr); + else + p = ip6_string(ip6_addr + off, addr, fmt6); + + if (have_p || have_s || have_f) + *p++ = ']'; + + if (have_p) { + *p++ = ':'; + p = number(p, pend, ntohs(sa->sin6_port), spec); + } + if (have_f) { + *p++ = '/'; + p = number(p, pend, ntohl(sa->sin6_flowinfo & + IPV6_FLOWINFO_MASK), spec); + } + if (have_s) { + *p++ = '%'; + p = number(p, pend, sa->sin6_scope_id, spec); + } + *p = '\0'; + + return string(buf, end, ip6_addr, spec); +} + +static noinline_for_stack +char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa, + struct printf_spec spec, const char *fmt) +{ + bool have_p = false; + char *p, ip4_addr[sizeof("255.255.255.255") + sizeof(":12345")]; + char *pend = ip4_addr + sizeof(ip4_addr); + const u8 *addr = (const u8 *) &sa->sin_addr.s_addr; + char fmt4[3] = { fmt[0], '4', 0 }; + + fmt++; + while (isalpha(*++fmt)) { + switch (*fmt) { + case 'p': + have_p = true; + break; + case 'h': + case 'l': + case 'n': + case 'b': + fmt4[2] = *fmt; + break; + } + } + + p = ip4_string(ip4_addr, addr, fmt4); + if (have_p) { + *p++ = ':'; + p = number(p, pend, ntohs(sa->sin_port), spec); + } + *p = '\0'; + + return string(buf, end, ip4_addr, spec); +} + static noinline_for_stack char *uuid_string(char *buf, char *end, const u8 *addr, struct printf_spec spec, const char *fmt) @@ -1007,11 +1104,17 @@ int kptr_restrict __read_mostly; * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) * IPv6 uses colon separated network-order 16 bit hex with leading 0's + * [S][pfs] + * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to + * [4] or [6] and is able to print port [p], flowinfo [f], scope [s] * - 'i' [46] for 'raw' IPv4/IPv6 addresses * IPv6 omits the colons (01020304...0f) * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) - * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order - * - 'I6c' for IPv6 addresses printed as specified by + * [S][pfs] + * Generic IPv4/IPv6 address (struct sockaddr *) that falls back to + * [4] or [6] and is able to print port [p], flowinfo [f], scope [s] + * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order + * - 'I[6S]c' for IPv6 addresses printed as specified by * http://tools.ietf.org/html/rfc5952 * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" @@ -1093,6 +1196,21 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, return ip6_addr_string(buf, end, ptr, spec, fmt); case '4': return ip4_addr_string(buf, end, ptr, spec, fmt); + case 'S': { + const union { + struct sockaddr raw; + struct sockaddr_in v4; + struct sockaddr_in6 v6; + } *sa = ptr; + + switch (sa->raw.sa_family) { + case AF_INET: + return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt); + case AF_INET6: + return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt); + default: + return string(buf, end, "(invalid address)", spec); + }} } break; case 'U': @@ -1370,6 +1488,8 @@ int format_decode(const char *fmt, struct printf_spec *spec) * %pI6 print an IPv6 address with colons * %pi6 print an IPv6 address without colons * %pI6c print an IPv6 address as specified by RFC 5952 + * %pIS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address + * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper * case. * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 -- GitLab From bb33381d0c97cdee25f2cdab540b6e2bd16fa03b Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 28 Jun 2013 19:49:40 +0200 Subject: [PATCH 2170/2900] net: sctp: rework debugging framework to use pr_debug and friends We should get rid of all own SCTP debug printk macros and use the ones that the kernel offers anyway instead. This makes the code more readable and conform to the kernel code, and offers all the features of dynamic debbuging that pr_debug() et al has, such as only turning on/off portions of debug messages at runtime through debugfs. The runtime cost of having CONFIG_DYNAMIC_DEBUG enabled, but none of the debug statements printing, is negligible [1]. If kernel debugging is completly turned off, then these statements will also compile into "empty" functions. While we're at it, we also need to change the Kconfig option as it /now/ only refers to the ifdef'ed code portions in outqueue.c that enable further debugging/tracing of SCTP transaction fields. Also, since SCTP_ASSERT code was enabled with this Kconfig option and has now been removed, we transform those code parts into WARNs resp. where appropriate BUG_ONs so that those bugs can be more easily detected as probably not many people have SCTP debugging permanently turned on. To turn on all SCTP debugging, the following steps are needed: # mount -t debugfs none /sys/kernel/debug # echo -n 'module sctp +p' > /sys/kernel/debug/dynamic_debug/control This can be done more fine-grained on a per file, per line basis and others as described in [2]. [1] https://www.kernel.org/doc/ols/2009/ols2009-pages-39-46.pdf [2] Documentation/dynamic-debug-howto.txt Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/net/sctp/sctp.h | 75 ----------------- net/sctp/Kconfig | 12 +-- net/sctp/associola.c | 67 ++++++++-------- net/sctp/chunk.c | 5 +- net/sctp/debug.c | 4 - net/sctp/endpointola.c | 5 +- net/sctp/input.c | 6 +- net/sctp/inqueue.c | 9 +-- net/sctp/ipv6.c | 21 ++--- net/sctp/output.c | 40 ++++------ net/sctp/outqueue.c | 160 ++++++++++++++++--------------------- net/sctp/protocol.c | 48 +++++------ net/sctp/sm_make_chunk.c | 25 +++--- net/sctp/sm_sideeffect.c | 96 ++++++++++------------ net/sctp/sm_statefuns.c | 77 +++++++++++------- net/sctp/socket.c | 168 +++++++++++++++++++-------------------- net/sctp/transport.c | 49 ++++++------ 17 files changed, 383 insertions(+), 484 deletions(-) diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index e6b95bc4d8e6..d8e37ecea691 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -83,16 +83,6 @@ #include #include - -/* Set SCTP_DEBUG flag via config if not already set. */ -#ifndef SCTP_DEBUG -#ifdef CONFIG_SCTP_DBG_MSG -#define SCTP_DEBUG 1 -#else -#define SCTP_DEBUG 0 -#endif /* CONFIG_SCTP_DBG */ -#endif /* SCTP_DEBUG */ - #ifdef CONFIG_IP_SCTP_MODULE #define SCTP_PROTOSW_FLAG 0 #else /* static! */ @@ -270,61 +260,6 @@ static inline void sctp_max_rto(struct sctp_association *asoc, } } -/* Print debugging messages. */ -#if SCTP_DEBUG -extern int sctp_debug_flag; -#define SCTP_DEBUG_PRINTK(fmt, args...) \ -do { \ - if (sctp_debug_flag) \ - printk(KERN_DEBUG pr_fmt(fmt), ##args); \ -} while (0) -#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) \ -do { \ - if (sctp_debug_flag) \ - pr_cont(fmt, ##args); \ -} while (0) -#define SCTP_DEBUG_PRINTK_IPADDR(fmt_lead, fmt_trail, \ - args_lead, addr, args_trail...) \ -do { \ - const union sctp_addr *_addr = (addr); \ - if (sctp_debug_flag) { \ - if (_addr->sa.sa_family == AF_INET6) { \ - printk(KERN_DEBUG \ - pr_fmt(fmt_lead "%pI6" fmt_trail), \ - args_lead, \ - &_addr->v6.sin6_addr, \ - args_trail); \ - } else { \ - printk(KERN_DEBUG \ - pr_fmt(fmt_lead "%pI4" fmt_trail), \ - args_lead, \ - &_addr->v4.sin_addr.s_addr, \ - args_trail); \ - } \ - } \ -} while (0) -#define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } -#define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } - -#define SCTP_ASSERT(expr, str, func) \ - if (!(expr)) { \ - SCTP_DEBUG_PRINTK("Assertion Failed: %s(%s) at %s:%s:%d\n", \ - str, (#expr), __FILE__, __func__, __LINE__); \ - func; \ - } - -#else /* SCTP_DEBUG */ - -#define SCTP_DEBUG_PRINTK(whatever...) -#define SCTP_DEBUG_PRINTK_CONT(fmt, args...) -#define SCTP_DEBUG_PRINTK_IPADDR(whatever...) -#define SCTP_ENABLE_DEBUG -#define SCTP_DISABLE_DEBUG -#define SCTP_ASSERT(expr, str, func) - -#endif /* SCTP_DEBUG */ - - /* * Macros for keeping a global reference of object allocations. */ @@ -597,16 +532,6 @@ static inline int param_type2af(__be16 type) } } -/* Perform some sanity checks. */ -static inline int sctp_sanity_check(void) -{ - SCTP_ASSERT(sizeof(struct sctp_ulpevent) <= - sizeof(((struct sk_buff *)0)->cb), - "SCTP: ulpevent does not fit in skb!\n", return 0); - - return 1; -} - /* Warning: The following hash functions assume a power of two 'size'. */ /* This is the hash function for the SCTP port hash table. */ static inline int sctp_phashfn(struct net *net, __u16 lport) diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index cf4852814e0c..d80bf1aebaed 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -30,7 +30,8 @@ menuconfig IP_SCTP homing at either or both ends of an association." To compile this protocol support as a module, choose M here: the - module will be called sctp. + module will be called sctp. Debug messages are handeled by the + kernel's dynamic debugging framework. If in doubt, say N. @@ -48,13 +49,14 @@ config NET_SCTPPROBE To compile this code as a module, choose M here: the module will be called sctp_probe. -config SCTP_DBG_MSG - bool "SCTP: Debug messages" +config SCTP_DBG_TSNS + bool "SCTP: Debug transactions" help - If you say Y, this will enable verbose debugging messages. + If you say Y, this will enable transaction debugging, visible + from the kernel's dynamic debugging framework. If unsure, say N. However, if you are running into problems, use - this option to gather detailed trace information + this option to gather outqueue trace information. config SCTP_DBG_OBJCNT bool "SCTP: Debug object counts" diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 9a383a8774e8..bce5b79662a6 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -357,7 +357,8 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, goto fail_init; SCTP_DBG_OBJCNT_INC(assoc); - SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc); + + pr_debug("Created asoc %p\n", asoc); return asoc; @@ -455,7 +456,10 @@ void sctp_association_free(struct sctp_association *asoc) /* Cleanup and free up an association. */ static void sctp_association_destroy(struct sctp_association *asoc) { - SCTP_ASSERT(asoc->base.dead, "Assoc is not dead", return); + if (unlikely(!asoc->base.dead)) { + WARN(1, "Attempt to destroy undead association %p!\n", asoc); + return; + } sctp_endpoint_put(asoc->ep); sock_put(asoc->base.sk); @@ -536,11 +540,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, struct list_head *pos; struct sctp_transport *transport; - SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", - " port: %d\n", - asoc, - (&peer->ipaddr), - ntohs(peer->ipaddr.v4.sin_port)); + pr_debug("%s: association:%p addr:%pISpc\n", + __func__, asoc, &peer->ipaddr.sa); /* If we are to remove the current retran_path, update it * to the next peer before removing this peer from the list. @@ -636,12 +637,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, /* AF_INET and AF_INET6 share common port field. */ port = ntohs(addr->v4.sin_port); - SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", - " port: %d state:%d\n", - asoc, - addr, - port, - peer_state); + pr_debug("%s: association:%p addr:%pISpc state:%d\n", __func__, + asoc, &addr->sa, peer_state); /* Set the port if it has not been set yet. */ if (0 == asoc->peer.port) @@ -708,8 +705,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, else asoc->pathmtu = peer->pathmtu; - SCTP_DEBUG_PRINTK("sctp_assoc_add_peer:association %p PMTU set to " - "%d\n", asoc, asoc->pathmtu); + pr_debug("%s: association:%p PMTU set to %d\n", __func__, asoc, + asoc->pathmtu); + peer->pmtu_pending = 0; asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu); @@ -1349,12 +1347,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) else t = asoc->peer.retran_path; - SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" - " %p addr: ", - " port: %d\n", - asoc, - (&t->ipaddr), - ntohs(t->ipaddr.v4.sin_port)); + pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, + &t->ipaddr.sa); } /* Choose the transport for sending retransmit packet. */ @@ -1401,8 +1395,8 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc) asoc->frag_point = sctp_frag_point(asoc, pmtu); } - SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n", - __func__, asoc, asoc->pathmtu, asoc->frag_point); + pr_debug("%s: asoc:%p, pmtu:%d, frag_point:%d\n", __func__, asoc, + asoc->pathmtu, asoc->frag_point); } /* Should we send a SACK to update our peer? */ @@ -1454,9 +1448,9 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) asoc->rwnd_press -= change; } - SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) " - "- %u\n", __func__, asoc, len, asoc->rwnd, - asoc->rwnd_over, asoc->a_rwnd); + pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", + __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, + asoc->a_rwnd); /* Send a window update SACK if the rwnd has increased by at least the * minimum of the association's PMTU and half of the receive buffer. @@ -1465,9 +1459,11 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) */ if (sctp_peer_needs_update(asoc)) { asoc->a_rwnd = asoc->rwnd; - SCTP_DEBUG_PRINTK("%s: Sending window update SACK- asoc: %p " - "rwnd: %u a_rwnd: %u\n", __func__, - asoc, asoc->rwnd, asoc->a_rwnd); + + pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " + "a_rwnd:%u\n", __func__, asoc, asoc->rwnd, + asoc->a_rwnd); + sack = sctp_make_sack(asoc); if (!sack) return; @@ -1489,8 +1485,10 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) int rx_count; int over = 0; - SCTP_ASSERT(asoc->rwnd, "rwnd zero", return); - SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return); + if (unlikely(!asoc->rwnd || asoc->rwnd_over)) + pr_debug("%s: association:%p has asoc->rwnd:%u, " + "asoc->rwnd_over:%u!\n", __func__, asoc, + asoc->rwnd, asoc->rwnd_over); if (asoc->ep->rcvbuf_policy) rx_count = atomic_read(&asoc->rmem_alloc); @@ -1515,9 +1513,10 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) asoc->rwnd_over = len - asoc->rwnd; asoc->rwnd = 0; } - SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u, %u)\n", - __func__, asoc, len, asoc->rwnd, - asoc->rwnd_over, asoc->rwnd_press); + + pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", + __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, + asoc->rwnd_press); } /* Build the bind address list for the association based on info from the diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 7135fc0c087a..5780565f5b7d 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -193,8 +193,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, msg->expires_at = jiffies + msecs_to_jiffies(sinfo->sinfo_timetolive); msg->can_abandon = 1; - SCTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ld jiffies:%ld\n", - __func__, msg, msg->expires_at, jiffies); + + pr_debug("%s: msg:%p expires_at:%ld jiffies:%ld\n", __func__, + msg, msg->expires_at, jiffies); } /* This is the biggest possible DATA chunk that can fit into diff --git a/net/sctp/debug.c b/net/sctp/debug.c index ec997cfe0a7e..f4998780d6df 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c @@ -47,10 +47,6 @@ #include -#if SCTP_DEBUG -int sctp_debug_flag = 1; /* Initially enable DEBUG */ -#endif /* SCTP_DEBUG */ - /* These are printable forms of Chunk ID's from section 3.1. */ static const char *const sctp_cid_tbl[SCTP_NUM_BASE_CHUNK_TYPES] = { "DATA", diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index b26999d508ba..9e3d257de0e0 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -249,7 +249,10 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) { struct sock *sk; - SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); + if (unlikely(!ep->base.dead)) { + WARN(1, "Attempt to destroy undead endpoint %p!\n", ep); + return; + } /* Free the digest buffer */ kfree(ep->digest); diff --git a/net/sctp/input.c b/net/sctp/input.c index 4cfc74699a3f..3fa4d858c35a 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -454,8 +454,6 @@ void sctp_icmp_proto_unreachable(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t) { - SCTP_DEBUG_PRINTK("%s\n", __func__); - if (sock_owned_by_user(sk)) { if (timer_pending(&t->proto_unreach_timer)) return; @@ -464,10 +462,12 @@ void sctp_icmp_proto_unreachable(struct sock *sk, jiffies + (HZ/20))) sctp_association_hold(asoc); } - } else { struct net *net = sock_net(sk); + pr_debug("%s: unrecognized next header type " + "encountered!\n", __func__); + if (del_timer(&t->proto_unreach_timer)) sctp_association_put(asoc); diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 3221d073448c..cb25f040fed0 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -219,10 +219,10 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) chunk->end_of_packet = 1; } - SCTP_DEBUG_PRINTK("+++sctp_inq_pop+++ chunk %p[%s]," - " length %d, skb->len %d\n",chunk, - sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)), - ntohs(chunk->chunk_hdr->length), chunk->skb->len); + pr_debug("+++sctp_inq_pop+++ chunk:%p[%s], length:%d, skb->len:%d\n", + chunk, sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)), + ntohs(chunk->chunk_hdr->length), chunk->skb->len); + return chunk; } @@ -238,4 +238,3 @@ void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback) { INIT_WORK(&q->immediate, callback); } - diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index adeaa0e64f52..09ffcc912d23 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -239,9 +239,8 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) fl6.daddr = *rt0->addr; } - SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", - __func__, skb, skb->len, - &fl6.saddr, &fl6.daddr); + pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, + skb->len, &fl6.saddr, &fl6.daddr); SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); @@ -276,7 +275,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) fl6->flowi6_oif = daddr->v6.sin6_scope_id; - SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); + pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr); if (asoc) fl6->fl6_sport = htons(asoc->base.bind_addr.port); @@ -284,7 +283,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, if (saddr) { fl6->saddr = saddr->v6.sin6_addr; fl6->fl6_sport = saddr->v6.sin6_port; - SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); + + pr_debug("src=%pI6 - ", &fl6->saddr); } dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); @@ -348,13 +348,16 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, out: if (!IS_ERR_OR_NULL(dst)) { struct rt6_info *rt; + rt = (struct rt6_info *)dst; t->dst = dst; - SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", - &rt->rt6i_dst.addr, &fl6->saddr); + + pr_debug("rt6_dst:%pI6 rt6_src:%pI6\n", &rt->rt6i_dst.addr, + &fl6->saddr); } else { t->dst = NULL; - SCTP_DEBUG_PRINTK("NO ROUTE\n"); + + pr_debug("no route\n"); } } @@ -377,7 +380,7 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, struct flowi6 *fl6 = &fl->u.ip6; union sctp_addr *saddr = &t->saddr; - SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst); + pr_debug("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst); if (t->dst) { saddr->v6.sin6_family = AF_INET6; diff --git a/net/sctp/output.c b/net/sctp/output.c index bbef4a7a9b56..a46d1eb41762 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -93,8 +93,7 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, { struct sctp_chunk *chunk = NULL; - SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, - packet, vtag); + pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); packet->vtag = vtag; @@ -119,8 +118,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet, struct sctp_association *asoc = transport->asoc; size_t overhead; - SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __func__, - packet, transport); + pr_debug("%s: packet:%p transport:%p\n", __func__, packet, transport); packet->transport = transport; packet->source_port = sport; @@ -145,7 +143,7 @@ void sctp_packet_free(struct sctp_packet *packet) { struct sctp_chunk *chunk, *tmp; - SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet); + pr_debug("%s: packet:%p\n", __func__, packet); list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { list_del_init(&chunk->list); @@ -167,8 +165,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, sctp_xmit_t retval; int error = 0; - SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, - packet, chunk); + pr_debug("%s: packet:%p chunk:%p\n", __func__, packet, chunk); switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) { case SCTP_XMIT_PMTU_FULL: @@ -334,8 +331,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, { sctp_xmit_t retval = SCTP_XMIT_OK; - SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __func__, packet, - chunk); + pr_debug("%s: packet:%p chunk:%p\n", __func__, packet, chunk); /* Data chunks are special. Before seeing what else we can * bundle into this packet, check to see if we are allowed to @@ -402,7 +398,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) unsigned char *auth = NULL; /* pointer to auth in skb data */ __u32 cksum_buf_len = sizeof(struct sctphdr); - SCTP_DEBUG_PRINTK("%s: packet:%p\n", __func__, packet); + pr_debug("%s: packet:%p\n", __func__, packet); /* Do NOT generate a chunkless packet. */ if (list_empty(&packet->chunk_list)) @@ -472,7 +468,9 @@ int sctp_packet_transmit(struct sctp_packet *packet) * * [This whole comment explains WORD_ROUND() below.] */ - SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); + + pr_debug("***sctp_transmit_packet***\n"); + list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) { list_del_init(&chunk->list); if (sctp_chunk_is_data(chunk)) { @@ -505,16 +503,13 @@ int sctp_packet_transmit(struct sctp_packet *packet) memcpy(skb_put(nskb, chunk->skb->len), chunk->skb->data, chunk->skb->len); - SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n", - "*** Chunk", chunk, - sctp_cname(SCTP_ST_CHUNK( - chunk->chunk_hdr->type)), - chunk->has_tsn ? "TSN" : "No TSN", - chunk->has_tsn ? - ntohl(chunk->subh.data_hdr->tsn) : 0, - "length", ntohs(chunk->chunk_hdr->length), - "chunk->skb->len", chunk->skb->len, - "rtt_in_progress", chunk->rtt_in_progress); + pr_debug("*** Chunk:%p[%s] %s 0x%x, length:%d, chunk->skb->len:%d, " + "rtt_in_progress:%d\n", chunk, + sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)), + chunk->has_tsn ? "TSN" : "No TSN", + chunk->has_tsn ? ntohl(chunk->subh.data_hdr->tsn) : 0, + ntohs(chunk->chunk_hdr->length), chunk->skb->len, + chunk->rtt_in_progress); /* * If this is a control chunk, this is our last @@ -606,8 +601,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) } } - SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n", - nskb->len); + pr_debug("***sctp_transmit_packet*** skb->len:%d\n", nskb->len); nskb->local_df = packet->ipfragok; (*tp->af_specific->sctp_xmit)(nskb, tp); diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index be35e2dbcc9a..511b3b35d609 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -299,10 +299,10 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) struct net *net = sock_net(q->asoc->base.sk); int error = 0; - SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", - q, chunk, chunk && chunk->chunk_hdr ? - sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) - : "Illegal Chunk"); + pr_debug("%s: outq:%p, chunk:%p[%s]\n", __func__, q, chunk, + chunk && chunk->chunk_hdr ? + sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : + "illegal chunk"); /* If it is data, queue it up, otherwise, send it * immediately. @@ -328,10 +328,10 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) break; default: - SCTP_DEBUG_PRINTK("outqueueing (%p, %p[%s])\n", - q, chunk, chunk && chunk->chunk_hdr ? - sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) - : "Illegal Chunk"); + pr_debug("%s: outqueueing: outq:%p, chunk:%p[%s])\n", + __func__, q, chunk, chunk && chunk->chunk_hdr ? + sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : + "illegal chunk"); sctp_outq_tail_data(q, chunk); if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) @@ -460,14 +460,10 @@ void sctp_retransmit_mark(struct sctp_outq *q, } } - SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, " - "cwnd: %d, ssthresh: %d, flight_size: %d, " - "pba: %d\n", __func__, - transport, reason, - transport->cwnd, transport->ssthresh, - transport->flight_size, - transport->partial_bytes_acked); - + pr_debug("%s: transport:%p, reason:%d, cwnd:%d, ssthresh:%d, " + "flight_size:%d, pba:%d\n", __func__, transport, reason, + transport->cwnd, transport->ssthresh, transport->flight_size, + transport->partial_bytes_acked); } /* Mark all the eligible packets on a transport for retransmission and force @@ -1014,19 +1010,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) sctp_transport_burst_limited(transport); } - SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ", - q, chunk, - chunk && chunk->chunk_hdr ? - sctp_cname(SCTP_ST_CHUNK( - chunk->chunk_hdr->type)) - : "Illegal Chunk"); - - SCTP_DEBUG_PRINTK("TX TSN 0x%x skb->head " - "%p skb->users %d.\n", - ntohl(chunk->subh.data_hdr->tsn), - chunk->skb ?chunk->skb->head : NULL, - chunk->skb ? - atomic_read(&chunk->skb->users) : -1); + pr_debug("%s: outq:%p, chunk:%p[%s], tx-tsn:0x%x skb->head:%p " + "skb->users:%d\n", + __func__, q, chunk, chunk && chunk->chunk_hdr ? + sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) : + "illegal chunk", ntohl(chunk->subh.data_hdr->tsn), + chunk->skb ? chunk->skb->head : NULL, chunk->skb ? + atomic_read(&chunk->skb->users) : -1); /* Add the chunk to the packet. */ status = sctp_packet_transmit_chunk(packet, chunk, 0); @@ -1038,10 +1028,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) /* We could not append this chunk, so put * the chunk back on the output queue. */ - SCTP_DEBUG_PRINTK("sctp_outq_flush: could " - "not transmit TSN: 0x%x, status: %d\n", - ntohl(chunk->subh.data_hdr->tsn), - status); + pr_debug("%s: could not transmit tsn:0x%x, status:%d\n", + __func__, ntohl(chunk->subh.data_hdr->tsn), + status); + sctp_outq_head_data(q, chunk); goto sctp_flush_out; break; @@ -1284,11 +1274,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) sctp_generate_fwdtsn(q, sack_ctsn); - SCTP_DEBUG_PRINTK("%s: sack Cumulative TSN Ack is 0x%x.\n", - __func__, sack_ctsn); - SCTP_DEBUG_PRINTK("%s: Cumulative TSN Ack of association, " - "%p is 0x%x. Adv peer ack point: 0x%x\n", - __func__, asoc, ctsn, asoc->adv_peer_ack_point); + pr_debug("%s: sack cumulative tsn ack:0x%x\n", __func__, sack_ctsn); + pr_debug("%s: cumulative tsn ack of assoc:%p is 0x%x, " + "advertised peer ack point:0x%x\n", __func__, asoc, ctsn, + asoc->adv_peer_ack_point); /* See if all chunks are acked. * Make sure the empty queue handler will get run later. @@ -1304,7 +1293,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) goto finish; } - SCTP_DEBUG_PRINTK("sack queue is empty.\n"); + pr_debug("%s: sack queue is empty\n", __func__); finish: return q->empty; } @@ -1348,7 +1337,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, /* These state variables are for coherent debug output. --xguo */ -#if SCTP_DEBUG +#ifdef CONFIG_SCTP_DBG_TSNS __u32 dbg_ack_tsn = 0; /* An ACKed TSN range starts here... */ __u32 dbg_last_ack_tsn = 0; /* ...and finishes here. */ __u32 dbg_kept_tsn = 0; /* An un-ACKed range starts here... */ @@ -1359,7 +1348,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, * -1: We need to initialize. */ int dbg_prt_state = -1; -#endif /* SCTP_DEBUG */ +#endif /* CONFIG_SCTP_DBG_TSNS */ sack_ctsn = ntohl(sack->cum_tsn_ack); @@ -1483,7 +1472,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, list_add_tail(lchunk, &tlist); } -#if SCTP_DEBUG +#ifdef CONFIG_SCTP_DBG_TSNS switch (dbg_prt_state) { case 0: /* last TSN was ACKed */ if (dbg_last_ack_tsn + 1 == tsn) { @@ -1497,42 +1486,39 @@ static void sctp_check_transmitted(struct sctp_outq *q, /* Display the end of the * current range. */ - SCTP_DEBUG_PRINTK_CONT("-%08x", - dbg_last_ack_tsn); + pr_cont("-%08x", dbg_last_ack_tsn); } /* Start a new range. */ - SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); + pr_cont(",%08x", tsn); dbg_ack_tsn = tsn; break; case 1: /* The last TSN was NOT ACKed. */ if (dbg_last_kept_tsn != dbg_kept_tsn) { /* Display the end of current range. */ - SCTP_DEBUG_PRINTK_CONT("-%08x", - dbg_last_kept_tsn); + pr_cont("-%08x", dbg_last_kept_tsn); } - SCTP_DEBUG_PRINTK_CONT("\n"); - + pr_cont("\n"); /* FALL THROUGH... */ default: /* This is the first-ever TSN we examined. */ /* Start a new range of ACK-ed TSNs. */ - SCTP_DEBUG_PRINTK("ACKed: %08x", tsn); + pr_debug("ACKed: %08x", tsn); + dbg_prt_state = 0; dbg_ack_tsn = tsn; } dbg_last_ack_tsn = tsn; -#endif /* SCTP_DEBUG */ +#endif /* CONFIG_SCTP_DBG_TSNS */ } else { if (tchunk->tsn_gap_acked) { - SCTP_DEBUG_PRINTK("%s: Receiver reneged on " - "data TSN: 0x%x\n", - __func__, - tsn); + pr_debug("%s: receiver reneged on data TSN:0x%x\n", + __func__, tsn); + tchunk->tsn_gap_acked = 0; if (tchunk->transport) @@ -1552,7 +1538,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, list_add_tail(lchunk, &tlist); -#if SCTP_DEBUG +#ifdef CONFIG_SCTP_DBG_TSNS /* See the above comments on ACK-ed TSNs. */ switch (dbg_prt_state) { case 1: @@ -1560,50 +1546,47 @@ static void sctp_check_transmitted(struct sctp_outq *q, break; if (dbg_last_kept_tsn != dbg_kept_tsn) - SCTP_DEBUG_PRINTK_CONT("-%08x", - dbg_last_kept_tsn); + pr_cont("-%08x", dbg_last_kept_tsn); - SCTP_DEBUG_PRINTK_CONT(",%08x", tsn); + pr_cont(",%08x", tsn); dbg_kept_tsn = tsn; break; case 0: if (dbg_last_ack_tsn != dbg_ack_tsn) - SCTP_DEBUG_PRINTK_CONT("-%08x", - dbg_last_ack_tsn); - SCTP_DEBUG_PRINTK_CONT("\n"); + pr_cont("-%08x", dbg_last_ack_tsn); + pr_cont("\n"); /* FALL THROUGH... */ default: - SCTP_DEBUG_PRINTK("KEPT: %08x",tsn); + pr_debug("KEPT: %08x", tsn); + dbg_prt_state = 1; dbg_kept_tsn = tsn; } dbg_last_kept_tsn = tsn; -#endif /* SCTP_DEBUG */ +#endif /* CONFIG_SCTP_DBG_TSNS */ } } -#if SCTP_DEBUG +#ifdef CONFIG_SCTP_DBG_TSNS /* Finish off the last range, displaying its ending TSN. */ switch (dbg_prt_state) { case 0: - if (dbg_last_ack_tsn != dbg_ack_tsn) { - SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_ack_tsn); - } else { - SCTP_DEBUG_PRINTK_CONT("\n"); - } - break; - + if (dbg_last_ack_tsn != dbg_ack_tsn) + pr_cont("-%08x\n", dbg_last_ack_tsn); + else + pr_cont("\n"); + break; case 1: - if (dbg_last_kept_tsn != dbg_kept_tsn) { - SCTP_DEBUG_PRINTK_CONT("-%08x\n", dbg_last_kept_tsn); - } else { - SCTP_DEBUG_PRINTK_CONT("\n"); - } + if (dbg_last_kept_tsn != dbg_kept_tsn) + pr_cont("-%08x\n", dbg_last_kept_tsn); + else + pr_cont("\n"); + break; } -#endif /* SCTP_DEBUG */ +#endif /* CONFIG_SCTP_DBG_TSNS */ if (transport) { if (bytes_acked) { struct sctp_association *asoc = transport->asoc; @@ -1676,9 +1659,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, !list_empty(&tlist) && (sack_ctsn+2 == q->asoc->next_tsn) && q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) { - SCTP_DEBUG_PRINTK("%s: SACK received for zero " - "window probe: %u\n", - __func__, sack_ctsn); + pr_debug("%s: sack received for zero window " + "probe:%u\n", __func__, sack_ctsn); + q->asoc->overall_error_count = 0; transport->error_count = 0; } @@ -1739,10 +1722,8 @@ static void sctp_mark_missing(struct sctp_outq *q, count_of_newacks, tsn)) { chunk->tsn_missing_report++; - SCTP_DEBUG_PRINTK( - "%s: TSN 0x%x missing counter: %d\n", - __func__, tsn, - chunk->tsn_missing_report); + pr_debug("%s: tsn:0x%x missing counter:%d\n", + __func__, tsn, chunk->tsn_missing_report); } } /* @@ -1762,11 +1743,10 @@ static void sctp_mark_missing(struct sctp_outq *q, if (do_fast_retransmit) sctp_retransmit(q, transport, SCTP_RTXR_FAST_RTX); - SCTP_DEBUG_PRINTK("%s: transport: %p, cwnd: %d, " - "ssthresh: %d, flight_size: %d, pba: %d\n", - __func__, transport, transport->cwnd, - transport->ssthresh, transport->flight_size, - transport->partial_bytes_acked); + pr_debug("%s: transport:%p, cwnd:%d, ssthresh:%d, " + "flight_size:%d, pba:%d\n", __func__, transport, + transport->cwnd, transport->ssthresh, + transport->flight_size, transport->partial_bytes_acked); } } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1de49c802d83..4a17494d736c 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -451,8 +451,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, fl4->fl4_sport = saddr->v4.sin_port; } - SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", - __func__, &fl4->daddr, &fl4->saddr); + pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr, + &fl4->saddr); rt = ip_route_output_key(sock_net(sk), fl4); if (!IS_ERR(rt)) @@ -513,10 +513,10 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, out: t->dst = dst; if (dst) - SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", - &fl4->daddr, &fl4->saddr); + pr_debug("rt_dst:%pI4, rt_src:%pI4\n", + &fl4->daddr, &fl4->saddr); else - SCTP_DEBUG_PRINTK("NO ROUTE\n"); + pr_debug("no route\n"); } /* For v4, the source address is cached in the route entry(dst). So no need @@ -604,9 +604,9 @@ static void sctp_addr_wq_timeout_handler(unsigned long arg) spin_lock_bh(&net->sctp.addr_wq_lock); list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { - SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", - " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state, - addrw); + pr_debug("%s: the first ent in wq:%p is addr:%pISc for cmd:%d at " + "entry:%p\n", __func__, &net->sctp.addr_waitq, &addrw->a.sa, + addrw->state, addrw); #if IS_ENABLED(CONFIG_IPV6) /* Now we send an ASCONF for each association */ @@ -623,8 +623,10 @@ static void sctp_addr_wq_timeout_handler(unsigned long arg) addrw->state == SCTP_ADDR_NEW) { unsigned long timeo_val; - SCTP_DEBUG_PRINTK("sctp_timo_handler: this is on DAD, trying %d sec later\n", - SCTP_ADDRESS_TICK_DELAY); + pr_debug("%s: this is on DAD, trying %d sec " + "later\n", __func__, + SCTP_ADDRESS_TICK_DELAY); + timeo_val = jiffies; timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); mod_timer(&net->sctp.addr_wq_timer, timeo_val); @@ -641,7 +643,7 @@ static void sctp_addr_wq_timeout_handler(unsigned long arg) continue; sctp_bh_lock_sock(sk); if (sctp_asconf_mgmt(sp, addrw) < 0) - SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n"); + pr_debug("%s: sctp_asconf_mgmt failed\n", __func__); sctp_bh_unlock_sock(sk); } #if IS_ENABLED(CONFIG_IPV6) @@ -707,9 +709,10 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm addrw = sctp_addr_wq_lookup(net, addr); if (addrw) { if (addrw->state != cmd) { - SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", - " in wq %p\n", addrw->state, &addrw->a, - &net->sctp.addr_waitq); + pr_debug("%s: offsets existing entry for %d, addr:%pISc " + "in wq:%p\n", __func__, addrw->state, &addrw->a.sa, + &net->sctp.addr_waitq); + list_del(&addrw->list); kfree(addrw); } @@ -725,8 +728,9 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm } addrw->state = cmd; list_add_tail(&addrw->list, &net->sctp.addr_waitq); - SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", - " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq); + + pr_debug("%s: add new entry for cmd:%d, addr:%pISc in wq:%p\n", + __func__, addrw->state, &addrw->a.sa, &net->sctp.addr_waitq); if (!timer_pending(&net->sctp.addr_wq_timer)) { timeo_val = jiffies; @@ -952,15 +956,14 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, { struct inet_sock *inet = inet_sk(skb->sk); - SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", - __func__, skb, skb->len, - &transport->fl.u.ip4.saddr, - &transport->fl.u.ip4.daddr); + pr_debug("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", __func__, skb, + skb->len, &transport->fl.u.ip4.saddr, &transport->fl.u.ip4.daddr); inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); + return ip_queue_xmit(skb, &transport->fl); } @@ -1321,9 +1324,8 @@ static __init int sctp_init(void) int max_share; int order; - /* SCTP_DEBUG sanity check. */ - if (!sctp_sanity_check()) - goto out; + BUILD_BUG_ON(sizeof(struct sctp_ulpevent) > + sizeof(((struct sk_buff *) 0)->cb)); /* Allocate bind_bucket and chunk caches. */ status = -ENOBUFS; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index dd71f1f9ba10..362ae6e2fd93 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -741,7 +741,8 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) memset(gabs, 0, sizeof(gabs)); ctsn = sctp_tsnmap_get_ctsn(map); - SCTP_DEBUG_PRINTK("sackCTSNAck sent: 0x%x.\n", ctsn); + + pr_debug("%s: sackCTSNAck sent:0x%x\n", __func__, ctsn); /* How much room is needed in the chunk? */ num_gabs = sctp_tsnmap_num_gabs(map, gabs); @@ -1287,10 +1288,8 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, if (!retval) goto nodata; - - if (!sk) { - SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb); - } + if (!sk) + pr_debug("%s: chunkifying skb:%p w/o an sk\n", __func__, skb); INIT_LIST_HEAD(&retval->list); retval->skb = skb; @@ -2191,8 +2190,9 @@ static sctp_ierror_t sctp_verify_param(struct net *net, break; fallthrough: default: - SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", - ntohs(param.p->type), cid); + pr_debug("%s: unrecognized param:%d for chunk:%d\n", + __func__, ntohs(param.p->type), cid); + retval = sctp_process_unk_param(asoc, param, chunk, err_chunk); break; } @@ -2516,7 +2516,7 @@ static int sctp_process_param(struct sctp_association *asoc, break; case SCTP_PARAM_HOST_NAME_ADDRESS: - SCTP_DEBUG_PRINTK("unimplemented SCTP_HOST_NAME_ADDRESS\n"); + pr_debug("%s: unimplemented SCTP_HOST_NAME_ADDRESS\n", __func__); break; case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES: @@ -2662,8 +2662,8 @@ static int sctp_process_param(struct sctp_association *asoc, * called prior to this routine. Simply log the error * here. */ - SCTP_DEBUG_PRINTK("Ignoring param: %d for association %p.\n", - ntohs(param.p->type), asoc); + pr_debug("%s: ignoring param:%d for association:%p.\n", + __func__, ntohs(param.p->type), asoc); break; } @@ -2805,7 +2805,10 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc, totallen += paramlen; totallen += addr_param_len; del_pickup = 1; - SCTP_DEBUG_PRINTK("mkasconf_update_ip: picked same-scope del_pending addr, totallen for all addresses is %d\n", totallen); + + pr_debug("%s: picked same-scope del_pending addr, " + "totallen for all addresses is %d\n", + __func__, totallen); } } diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index ff91f47b0239..cf6f84518222 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -257,7 +257,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) sctp_bh_lock_sock(asoc->base.sk); if (sock_owned_by_user(asoc->base.sk)) { - SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + pr_debug("%s: sock is busy\n", __func__); /* Try again later. */ if (!mod_timer(&transport->T3_rtx_timer, jiffies + (HZ/20))) @@ -297,9 +297,8 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc, sctp_bh_lock_sock(asoc->base.sk); if (sock_owned_by_user(asoc->base.sk)) { - SCTP_DEBUG_PRINTK("%s:Sock is busy: timer %d\n", - __func__, - timeout_type); + pr_debug("%s: sock is busy: timer %d\n", __func__, + timeout_type); /* Try again later. */ if (!mod_timer(&asoc->timers[timeout_type], jiffies + (HZ/20))) @@ -377,7 +376,7 @@ void sctp_generate_heartbeat_event(unsigned long data) sctp_bh_lock_sock(asoc->base.sk); if (sock_owned_by_user(asoc->base.sk)) { - SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + pr_debug("%s: sock is busy\n", __func__); /* Try again later. */ if (!mod_timer(&transport->hb_timer, jiffies + (HZ/20))) @@ -415,7 +414,7 @@ void sctp_generate_proto_unreach_event(unsigned long data) sctp_bh_lock_sock(asoc->base.sk); if (sock_owned_by_user(asoc->base.sk)) { - SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + pr_debug("%s: sock is busy\n", __func__); /* Try again later. */ if (!mod_timer(&transport->proto_unreach_timer, @@ -521,11 +520,9 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, if (transport->state != SCTP_INACTIVE && (transport->error_count > transport->pathmaxrxt)) { - SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", - " transport IP: port:%d failed.\n", - asoc, - (&transport->ipaddr), - ntohs(transport->ipaddr.v4.sin_port)); + pr_debug("%s: association:%p transport addr:%pISpc failed\n", + __func__, asoc, &transport->ipaddr.sa); + sctp_assoc_control_transport(asoc, transport, SCTP_TRANSPORT_DOWN, SCTP_FAILED_THRESHOLD); @@ -804,8 +801,7 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, asoc->state = state; - SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", - asoc, sctp_state_tbl[state]); + pr_debug("%s: asoc:%p[%s]\n", __func__, asoc, sctp_state_tbl[state]); if (sctp_style(sk, TCP)) { /* Change the sk->sk_state of a TCP-style socket that has @@ -1017,15 +1013,11 @@ static void sctp_cmd_t1_timer_update(struct sctp_association *asoc, asoc->timeouts[timer] = asoc->max_init_timeo; } asoc->init_cycle++; - SCTP_DEBUG_PRINTK( - "T1 %s Timeout adjustment" - " init_err_counter: %d" - " cycle: %d" - " timeout: %ld\n", - name, - asoc->init_err_counter, - asoc->init_cycle, - asoc->timeouts[timer]); + + pr_debug("%s: T1[%s] timeout adjustment init_err_counter:%d" + " cycle:%d timeout:%ld\n", __func__, name, + asoc->init_err_counter, asoc->init_cycle, + asoc->timeouts[timer]); } } @@ -1080,23 +1072,19 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc) * main flow of sctp_do_sm() to keep attention focused on the real * functionality there. */ -#define DEBUG_PRE \ - SCTP_DEBUG_PRINTK("sctp_do_sm prefn: " \ - "ep %p, %s, %s, asoc %p[%s], %s\n", \ - ep, sctp_evttype_tbl[event_type], \ - (*debug_fn)(subtype), asoc, \ - sctp_state_tbl[state], state_fn->name) - -#define DEBUG_POST \ - SCTP_DEBUG_PRINTK("sctp_do_sm postfn: " \ - "asoc %p, status: %s\n", \ - asoc, sctp_status_tbl[status]) - -#define DEBUG_POST_SFX \ - SCTP_DEBUG_PRINTK("sctp_do_sm post sfx: error %d, asoc %p[%s]\n", \ - error, asoc, \ - sctp_state_tbl[(asoc && sctp_id2assoc(ep->base.sk, \ - sctp_assoc2id(asoc)))?asoc->state:SCTP_STATE_CLOSED]) +#define debug_pre_sfn() \ + pr_debug("%s[pre-fn]: ep:%p, %s, %s, asoc:%p[%s], %s\n", __func__, \ + ep, sctp_evttype_tbl[event_type], (*debug_fn)(subtype), \ + asoc, sctp_state_tbl[state], state_fn->name) + +#define debug_post_sfn() \ + pr_debug("%s[post-fn]: asoc:%p, status:%s\n", __func__, asoc, \ + sctp_status_tbl[status]) + +#define debug_post_sfx() \ + pr_debug("%s[post-sfx]: error:%d, asoc:%p[%s]\n", __func__, error, \ + asoc, sctp_state_tbl[(asoc && sctp_id2assoc(ep->base.sk, \ + sctp_assoc2id(asoc))) ? asoc->state : SCTP_STATE_CLOSED]) /* * This is the master state machine processing function. @@ -1116,7 +1104,6 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, sctp_disposition_t status; int error = 0; typedef const char *(printfn_t)(sctp_subtype_t); - static printfn_t *table[] = { NULL, sctp_cname, sctp_tname, sctp_oname, sctp_pname, }; @@ -1129,21 +1116,18 @@ int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, sctp_init_cmd_seq(&commands); - DEBUG_PRE; + debug_pre_sfn(); status = (*state_fn->fn)(net, ep, asoc, subtype, event_arg, &commands); - DEBUG_POST; + debug_post_sfn(); error = sctp_side_effects(event_type, subtype, state, ep, asoc, event_arg, status, &commands, gfp); - DEBUG_POST_SFX; + debug_post_sfx(); return error; } -#undef DEBUG_PRE -#undef DEBUG_POST - /***************************************************************** * This the master state function side effect processing function. *****************************************************************/ @@ -1172,9 +1156,9 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype, switch (status) { case SCTP_DISPOSITION_DISCARD: - SCTP_DEBUG_PRINTK("Ignored sctp protocol event - state %d, " - "event_type %d, event_id %d\n", - state, event_type, subtype.chunk); + pr_debug("%s: ignored sctp protocol event - state:%d, " + "event_type:%d, event_id:%d\n", __func__, state, + event_type, subtype.chunk); break; case SCTP_DISPOSITION_NOMEM: @@ -1425,18 +1409,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_CHUNK_ULP: /* Send a chunk to the sockets layer. */ - SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n", - "chunk_up:", cmd->obj.chunk, - "ulpq:", &asoc->ulpq); + pr_debug("%s: sm_sideff: chunk_up:%p, ulpq:%p\n", + __func__, cmd->obj.chunk, &asoc->ulpq); + sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.chunk, GFP_ATOMIC); break; case SCTP_CMD_EVENT_ULP: /* Send a notification to the sockets layer. */ - SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n", - "event_up:",cmd->obj.ulpevent, - "ulpq:",&asoc->ulpq); + pr_debug("%s: sm_sideff: event_up:%p, ulpq:%p\n", + __func__, cmd->obj.ulpevent, &asoc->ulpq); + sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ulpevent); break; @@ -1601,7 +1585,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, break; case SCTP_CMD_REPORT_BAD_TAG: - SCTP_DEBUG_PRINTK("vtag mismatch!\n"); + pr_debug("%s: vtag mismatch!\n", __func__); break; case SCTP_CMD_STRIKE: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b3d186856513..f6b7109195a6 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1179,9 +1179,9 @@ sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net, /* Check if the timestamp looks valid. */ if (time_after(hbinfo->sent_at, jiffies) || time_after(jiffies, hbinfo->sent_at + max_interval)) { - SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp " - "received for transport: %p\n", - __func__, link); + pr_debug("%s: HEARTBEAT ACK with invalid timestamp received " + "for transport:%p\n", __func__, link); + return SCTP_DISPOSITION_DISCARD; } @@ -2562,7 +2562,8 @@ static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net, const struct sctp_association *asoc, struct sctp_transport *transport) { - SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); + pr_debug("%s: ABORT received (INIT)\n", __func__); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_CLOSED)); SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); @@ -2572,6 +2573,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net, /* CMD_INIT_FAILED will DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_PERR(error)); + return SCTP_DISPOSITION_ABORT; } @@ -2637,8 +2639,9 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(struct net *net, ctsn = ntohl(sdh->cum_tsn_ack); if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { - SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn); - SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point); + pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, + asoc->ctsn_ack_point); + return SCTP_DISPOSITION_DISCARD; } @@ -2721,8 +2724,9 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(struct net *net, ctsn = ntohl(sdh->cum_tsn_ack); if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { - SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn); - SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point); + pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, + asoc->ctsn_ack_point); + return SCTP_DISPOSITION_DISCARD; } @@ -3174,8 +3178,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net, * Point indicates an out-of-order SACK. */ if (TSN_lt(ctsn, asoc->ctsn_ack_point)) { - SCTP_DEBUG_PRINTK("ctsn %x\n", ctsn); - SCTP_DEBUG_PRINTK("ctsn_ack_point %x\n", asoc->ctsn_ack_point); + pr_debug("%s: ctsn:%x, ctsn_ack_point:%x\n", __func__, ctsn, + asoc->ctsn_ack_point); + return SCTP_DISPOSITION_DISCARD; } @@ -3859,7 +3864,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net, skb_pull(chunk->skb, len); tsn = ntohl(fwdtsn_hdr->new_cum_tsn); - SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn); + pr_debug("%s: TSN 0x%x\n", __func__, tsn); /* The TSN is too high--silently discard the chunk and count on it * getting retransmitted later. @@ -3927,7 +3932,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( skb_pull(chunk->skb, len); tsn = ntohl(fwdtsn_hdr->new_cum_tsn); - SCTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __func__, tsn); + pr_debug("%s: TSN 0x%x\n", __func__, tsn); /* The TSN is too high--silently discard the chunk and count on it * getting retransmitted later. @@ -4166,7 +4171,7 @@ sctp_disposition_t sctp_sf_unk_chunk(struct net *net, struct sctp_chunk *err_chunk; sctp_chunkhdr_t *hdr; - SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk); + pr_debug("%s: processing unknown chunk id:%d\n", __func__, type.chunk); if (!sctp_vtag_verify(unk_chunk, asoc)) return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); @@ -4256,7 +4261,8 @@ sctp_disposition_t sctp_sf_discard_chunk(struct net *net, return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, commands); - SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk); + pr_debug("%s: chunk:%d is discarded\n", __func__, type.chunk); + return SCTP_DISPOSITION_DISCARD; } @@ -5184,7 +5190,9 @@ sctp_disposition_t sctp_sf_ignore_primitive( void *arg, sctp_cmd_seq_t *commands) { - SCTP_DEBUG_PRINTK("Primitive type %d is ignored.\n", type.primitive); + pr_debug("%s: primitive type:%d is ignored\n", __func__, + type.primitive); + return SCTP_DISPOSITION_DISCARD; } @@ -5379,7 +5387,9 @@ sctp_disposition_t sctp_sf_ignore_other(struct net *net, void *arg, sctp_cmd_seq_t *commands) { - SCTP_DEBUG_PRINTK("The event other type %d is ignored\n", type.other); + pr_debug("%s: the event other type:%d is ignored\n", + __func__, type.other); + return SCTP_DISPOSITION_DISCARD; } @@ -5527,7 +5537,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(struct net *net, struct sctp_bind_addr *bp; int attempts = asoc->init_err_counter + 1; - SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); + pr_debug("%s: timer T1 expired (INIT)\n", __func__); + SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS); if (attempts <= asoc->max_init_attempts) { @@ -5546,9 +5557,10 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(struct net *net, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); } else { - SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" - " max_init_attempts: %d\n", - attempts, asoc->max_init_attempts); + pr_debug("%s: giving up on INIT, attempts:%d " + "max_init_attempts:%d\n", __func__, attempts, + asoc->max_init_attempts); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, @@ -5588,7 +5600,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(struct net *net, struct sctp_chunk *repl = NULL; int attempts = asoc->init_err_counter + 1; - SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); + pr_debug("%s: timer T1 expired (COOKIE-ECHO)\n", __func__); + SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS); if (attempts <= asoc->max_init_attempts) { @@ -5636,7 +5649,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(struct net *net, { struct sctp_chunk *reply = NULL; - SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); + pr_debug("%s: timer T2 expired\n", __func__); + SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS); ((struct sctp_association *)asoc)->shutdown_retries++; @@ -5777,7 +5791,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(struct net *net, { struct sctp_chunk *reply = NULL; - SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); + pr_debug("%s: timer T5 expired\n", __func__); + SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); reply = sctp_make_abort(asoc, NULL, 0); @@ -5892,7 +5907,8 @@ sctp_disposition_t sctp_sf_timer_ignore(struct net *net, void *arg, sctp_cmd_seq_t *commands) { - SCTP_DEBUG_PRINTK("Timer %d ignored.\n", type.chunk); + pr_debug("%s: timer %d ignored\n", __func__, type.chunk); + return SCTP_DISPOSITION_CONSUME; } @@ -6102,7 +6118,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); tsn = ntohl(data_hdr->tsn); - SCTP_DEBUG_PRINTK("eat_data: TSN 0x%x.\n", tsn); + pr_debug("%s: TSN 0x%x\n", __func__, tsn); /* ASSERT: Now skb->data is really the user data. */ @@ -6179,12 +6195,12 @@ static int sctp_eat_data(const struct sctp_association *asoc, */ if (sctp_tsnmap_has_gap(map) && (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { - SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); + pr_debug("%s: reneging for tsn:%u\n", __func__, tsn); deliver = SCTP_CMD_RENEGE; } else { - SCTP_DEBUG_PRINTK("Discard tsn: %u len: %Zd, " - "rwnd: %d\n", tsn, datalen, - asoc->rwnd); + pr_debug("%s: discard tsn:%u len:%zu, rwnd:%d\n", + __func__, tsn, datalen, asoc->rwnd); + return SCTP_IERROR_IGNORE_TSN; } } @@ -6199,7 +6215,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, if (*sk->sk_prot_creator->memory_pressure) { if (sctp_tsnmap_has_gap(map) && (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { - SCTP_DEBUG_PRINTK("Under Pressure! Reneging for tsn:%u\n", tsn); + pr_debug("%s: under pressure, reneging for tsn:%u\n", + __func__, tsn); deliver = SCTP_CMD_RENEGE; } } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 66fcdcfe1b74..d5c6a2870473 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -281,8 +281,8 @@ static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) sctp_lock_sock(sk); - SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", - sk, addr, addr_len); + pr_debug("%s: sk:%p, addr:%p, addr_len:%d\n", __func__, sk, + addr, addr_len); /* Disallow binding twice. */ if (!sctp_sk(sk)->ep->base.bind_addr.port) @@ -342,19 +342,15 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) /* Common sockaddr verification. */ af = sctp_sockaddr_af(sp, addr, len); if (!af) { - SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", - sk, addr, len); + pr_debug("%s: sk:%p, newaddr:%p, len:%d EINVAL\n", + __func__, sk, addr, len); return -EINVAL; } snum = ntohs(addr->v4.sin_port); - SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", - ", port: %d, new port: %d, len: %d)\n", - sk, - addr, - bp->port, snum, - len); + pr_debug("%s: sk:%p, new addr:%pISc, port:%d, new port:%d, len:%d\n", + __func__, sk, &addr->sa, bp->port, snum, len); /* PF specific bind() address verification. */ if (!sp->pf->bind_verify(sp, addr)) @@ -368,9 +364,8 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) if (!snum) snum = bp->port; else if (snum != bp->port) { - SCTP_DEBUG_PRINTK("sctp_do_bind:" - " New port %d does not match existing port " - "%d.\n", snum, bp->port); + pr_debug("%s: new port %d doesn't match existing port " + "%d\n", __func__, snum, bp->port); return -EINVAL; } } @@ -468,8 +463,8 @@ static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) struct sockaddr *sa_addr; struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n", - sk, addrs, addrcnt); + pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", __func__, sk, + addrs, addrcnt); addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { @@ -535,11 +530,10 @@ static int sctp_send_asconf_add_ip(struct sock *sk, sp = sctp_sk(sk); ep = sp->ep; - SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", - __func__, sk, addrs, addrcnt); + pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", + __func__, sk, addrs, addrcnt); list_for_each_entry(asoc, &ep->asocs, asocs) { - if (!asoc->peer.asconf_capable) continue; @@ -646,8 +640,8 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) union sctp_addr *sa_addr; struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", - sk, addrs, addrcnt); + pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", + __func__, sk, addrs, addrcnt); addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { @@ -740,8 +734,8 @@ static int sctp_send_asconf_del_ip(struct sock *sk, sp = sctp_sk(sk); ep = sp->ep; - SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n", - __func__, sk, addrs, addrcnt); + pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", + __func__, sk, addrs, addrcnt); list_for_each_entry(asoc, &ep->asocs, asocs) { @@ -808,9 +802,11 @@ static int sctp_send_asconf_del_ip(struct sock *sk, sin6 = (struct sockaddr_in6 *)addrs; asoc->asconf_addr_del_pending->v6.sin6_addr = sin6->sin6_addr; } - SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ", - " at %p\n", asoc, asoc->asconf_addr_del_pending, - asoc->asconf_addr_del_pending); + + pr_debug("%s: keep the last address asoc:%p %pISc at %p\n", + __func__, asoc, &asoc->asconf_addr_del_pending->sa, + asoc->asconf_addr_del_pending); + asoc->src_out_of_asoc_ok = 1; stored = 1; goto skip_mkasconf; @@ -972,8 +968,8 @@ static int sctp_setsockopt_bindx(struct sock* sk, void *addr_buf; struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p" - " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); + pr_debug("%s: sk:%p addrs:%p addrs_size:%d opt:%d\n", + __func__, sk, addrs, addrs_size, op); if (unlikely(addrs_size <= 0)) return -EINVAL; @@ -1231,10 +1227,9 @@ static int __sctp_connect(struct sock* sk, asoc = NULL; out_free: + pr_debug("%s: took out_free path with asoc:%p kaddrs:%p err:%d\n", + __func__, asoc, kaddrs, err); - SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" - " kaddrs: %p err: %d\n", - asoc, kaddrs, err); if (asoc) { /* sctp_primitive_ASSOCIATE may have added this association * To the hash table, try to unhash it, just in case, its a noop @@ -1316,8 +1311,8 @@ static int __sctp_setsockopt_connectx(struct sock* sk, int err = 0; struct sockaddr *kaddrs; - SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", - __func__, sk, addrs, addrs_size); + pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n", + __func__, sk, addrs, addrs_size); if (unlikely(addrs_size <= 0)) return -EINVAL; @@ -1468,7 +1463,7 @@ static void sctp_close(struct sock *sk, long timeout) struct list_head *pos, *temp; unsigned int data_was_unread; - SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); + pr_debug("%s: sk:%p, timeout:%ld\n", __func__, sk, timeout); sctp_lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -1594,14 +1589,12 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, struct sctp_datamsg *datamsg; int msg_flags = msg->msg_flags; - SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n", - sk, msg, msg_len); - err = 0; sp = sctp_sk(sk); ep = sp->ep; - SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); + pr_debug("%s: sk:%p, msg:%p, msg_len:%zu ep:%p\n", __func__, sk, + msg, msg_len, ep); /* We cannot send a message over a TCP-style listening socket. */ if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { @@ -1611,9 +1604,8 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* Parse out the SCTP CMSGs. */ err = sctp_msghdr_parse(msg, &cmsgs); - if (err) { - SCTP_DEBUG_PRINTK("msghdr parse err = %x\n", err); + pr_debug("%s: msghdr parse err:%x\n", __func__, err); goto out_nounlock; } @@ -1645,8 +1637,8 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, associd = sinfo->sinfo_assoc_id; } - SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n", - msg_len, sinfo_flags); + pr_debug("%s: msg_len:%zu, sinfo_flags:0x%x\n", __func__, + msg_len, sinfo_flags); /* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */ if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) { @@ -1675,7 +1667,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, transport = NULL; - SCTP_DEBUG_PRINTK("About to look up association.\n"); + pr_debug("%s: about to look up association\n", __func__); sctp_lock_sock(sk); @@ -1705,7 +1697,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } if (asoc) { - SCTP_DEBUG_PRINTK("Just looked up association: %p.\n", asoc); + pr_debug("%s: just looked up association:%p\n", __func__, asoc); /* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED * socket that has an association in CLOSED state. This can @@ -1718,8 +1710,9 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } if (sinfo_flags & SCTP_EOF) { - SCTP_DEBUG_PRINTK("Shutting down association: %p\n", - asoc); + pr_debug("%s: shutting down association:%p\n", + __func__, asoc); + sctp_primitive_SHUTDOWN(net, asoc, NULL); err = 0; goto out_unlock; @@ -1732,7 +1725,9 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } - SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); + pr_debug("%s: aborting association:%p\n", + __func__, asoc); + sctp_primitive_ABORT(net, asoc, chunk); err = 0; goto out_unlock; @@ -1741,7 +1736,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* Do we need to create the association? */ if (!asoc) { - SCTP_DEBUG_PRINTK("There is no association yet.\n"); + pr_debug("%s: there is no association yet\n", __func__); if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) { err = -EINVAL; @@ -1840,7 +1835,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, } /* ASSERT: we have a valid association at this point. */ - SCTP_DEBUG_PRINTK("We have a valid association.\n"); + pr_debug("%s: we have a valid association\n", __func__); if (!sinfo) { /* If the user didn't specify SNDRCVINFO, make up one with @@ -1909,7 +1904,8 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, err = sctp_primitive_ASSOCIATE(net, asoc, NULL); if (err < 0) goto out_free; - SCTP_DEBUG_PRINTK("We associated primitively.\n"); + + pr_debug("%s: we associated primitively\n", __func__); } /* Break the message into multiple chunks of maximum size. */ @@ -1936,17 +1932,15 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, */ err = sctp_primitive_SEND(net, asoc, datamsg); /* Did the lower layer accept the chunk? */ - if (err) + if (err) { sctp_datamsg_free(datamsg); - else - sctp_datamsg_put(datamsg); + goto out_free; + } - SCTP_DEBUG_PRINTK("We sent primitively.\n"); + pr_debug("%s: we sent primitively\n", __func__); - if (err) - goto out_free; - else - err = msg_len; + sctp_datamsg_put(datamsg); + err = msg_len; /* If we are already past ASSOCIATE, the lower * layers are responsible for association cleanup. @@ -2041,10 +2035,9 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, int err = 0; int skb_len; - SCTP_DEBUG_PRINTK("sctp_recvmsg(%s: %p, %s: %p, %s: %zd, %s: %d, %s: " - "0x%x, %s: %p)\n", "sk", sk, "msghdr", msg, - "len", len, "knoblauch", noblock, - "flags", flags, "addr_len", addr_len); + pr_debug("%s: sk:%p, msghdr:%p, len:%zd, noblock:%d, flags:0x%x, " + "addr_len:%p)\n", __func__, sk, msg, len, noblock, flags, + addr_len); sctp_lock_sock(sk); @@ -3086,7 +3079,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva err = sctp_send_asconf(asoc, chunk); - SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); + pr_debug("%s: we set peer primary addr primitively\n", __func__); return err; } @@ -3561,8 +3554,7 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, { int retval = 0; - SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n", - sk, optname); + pr_debug("%s: sk:%p, optname:%d\n", __func__, sk, optname); /* I can hardly begin to describe how wrong this is. This is * so broken as to be worse than useless. The API draft @@ -3724,8 +3716,8 @@ static int sctp_connect(struct sock *sk, struct sockaddr *addr, sctp_lock_sock(sk); - SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", - __func__, sk, addr, addr_len); + pr_debug("%s: sk:%p, sockaddr:%p, addr_len:%d\n", __func__, sk, + addr, addr_len); /* Validate addr_len before calling common connect/connectx routine. */ af = sctp_get_af_specific(addr->sa_family); @@ -3855,7 +3847,7 @@ static int sctp_init_sock(struct sock *sk) struct net *net = sock_net(sk); struct sctp_sock *sp; - SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk); + pr_debug("%s: sk:%p\n", __func__, sk); sp = sctp_sk(sk); @@ -3990,7 +3982,7 @@ static void sctp_destroy_sock(struct sock *sk) { struct sctp_sock *sp; - SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk); + pr_debug("%s: sk:%p\n", __func__, sk); /* Release our hold on the endpoint. */ sp = sctp_sk(sk); @@ -4123,9 +4115,9 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, goto out; } - SCTP_DEBUG_PRINTK("sctp_getsockopt_sctp_status(%d): %d %d %d\n", - len, status.sstat_state, status.sstat_rwnd, - status.sstat_assoc_id); + pr_debug("%s: len:%d, state:%d, rwnd:%d, assoc_id:%d\n", + __func__, len, status.sstat_state, status.sstat_rwnd, + status.sstat_assoc_id); if (copy_to_user(optval, &status, len)) { retval = -EFAULT; @@ -4333,8 +4325,8 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval return PTR_ERR(newfile); } - SCTP_DEBUG_PRINTK("%s: sk: %p newsk: %p sd: %d\n", - __func__, sk, newsock->sk, retval); + pr_debug("%s: sk:%p, newsk:%p, sd:%d\n", __func__, sk, newsock->sk, + retval); /* Return the fd mapped to the new socket. */ if (put_user(len, optlen)) { @@ -4467,7 +4459,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, trans = sctp_addr_id2transport(sk, ¶ms.spp_address, params.spp_assoc_id); if (!trans) { - SCTP_DEBUG_PRINTK("Failed no transport\n"); + pr_debug("%s: failed no transport\n", __func__); return -EINVAL; } } @@ -4478,7 +4470,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, */ asoc = sctp_id2assoc(sk, params.spp_assoc_id); if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) { - SCTP_DEBUG_PRINTK("Failed no association\n"); + pr_debug("%s: failed no association\n", __func__); return -EINVAL; } @@ -5698,8 +5690,7 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, if (put_user(len, optlen)) return -EFAULT; - SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n", - len, sas.sas_assoc_id); + pr_debug("%s: len:%d, assoc_id:%d\n", __func__, len, sas.sas_assoc_id); if (copy_to_user(optval, &sas, len)) return -EFAULT; @@ -5713,8 +5704,7 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, int retval = 0; int len; - SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", - sk, optname); + pr_debug("%s: sk:%p, optname:%d\n", __func__, sk, optname); /* I can hardly begin to describe how wrong this is. This is * so broken as to be worse than useless. The API draft @@ -5894,7 +5884,8 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) snum = ntohs(addr->v4.sin_port); - SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum); + pr_debug("%s: begins, snum:%d\n", __func__, snum); + sctp_local_bh_disable(); if (snum == 0) { @@ -5960,7 +5951,8 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) int reuse = sk->sk_reuse; struct sock *sk2; - SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); + pr_debug("%s: found a possible match\n", __func__); + if (pp->fastreuse && sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING) goto success; @@ -5990,7 +5982,8 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) goto fail_unlock; } } - SCTP_DEBUG_PRINTK("sctp_get_port(): Found a match\n"); + + pr_debug("%s: found a match\n", __func__); } pp_not_found: /* If there was a hash table miss, create a new port. */ @@ -6479,8 +6472,8 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, timeo = sock_rcvtimeo(sk, noblock); - SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n", - timeo, MAX_SCHEDULE_TIMEOUT); + pr_debug("%s: timeo:%ld, max:%ld\n", __func__, timeo, + MAX_SCHEDULE_TIMEOUT); do { /* Again only user level code calls this function, @@ -6611,8 +6604,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, long current_timeo = *timeo_p; DEFINE_WAIT(wait); - SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n", - asoc, (long)(*timeo_p), msg_len); + pr_debug("%s: asoc:%p, timeo:%ld, msg_len:%zu\n", __func__, asoc, + *timeo_p, msg_len); /* Increment the association's refcnt. */ sctp_association_hold(asoc); @@ -6718,8 +6711,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p) long current_timeo = *timeo_p; DEFINE_WAIT(wait); - SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __func__, asoc, - (long)(*timeo_p)); + pr_debug("%s: asoc:%p, timeo:%ld\n", __func__, asoc, *timeo_p); /* Increment the association's refcnt. */ sctp_association_hold(asoc); diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 5d3c71bbd197..bdbbc3fd7c14 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -176,7 +176,10 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head) */ static void sctp_transport_destroy(struct sctp_transport *transport) { - SCTP_ASSERT(transport->dead, "Transport is not dead", return); + if (unlikely(!transport->dead)) { + WARN(1, "Attempt to destroy undead transport %p!\n", transport); + return; + } call_rcu(&transport->rcu, sctp_transport_destroy_rcu); @@ -317,11 +320,9 @@ void sctp_transport_put(struct sctp_transport *transport) /* Update transport's RTO based on the newly calculated RTT. */ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) { - /* Check for valid transport. */ - SCTP_ASSERT(tp, "NULL transport", return); - - /* We should not be doing any RTO updates unless rto_pending is set. */ - SCTP_ASSERT(tp->rto_pending, "rto_pending not set", return); + if (unlikely(!tp->rto_pending)) + /* We should not be doing any RTO updates unless rto_pending is set. */ + pr_debug("%s: rto_pending not set on transport %p!\n", __func__, tp); if (tp->rttvar || tp->srtt) { struct net *net = sock_net(tp->asoc->base.sk); @@ -377,9 +378,8 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) */ tp->rto_pending = 0; - SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d " - "rttvar: %d, rto: %ld\n", __func__, - tp, rtt, tp->srtt, tp->rttvar, tp->rto); + pr_debug("%s: transport:%p, rtt:%d, srtt:%d rttvar:%d, rto:%ld\n", + __func__, tp, rtt, tp->srtt, tp->rttvar, tp->rto); } /* This routine updates the transport's cwnd and partial_bytes_acked @@ -433,12 +433,11 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, cwnd += pmtu; else cwnd += bytes_acked; - SCTP_DEBUG_PRINTK("%s: SLOW START: transport: %p, " - "bytes_acked: %d, cwnd: %d, ssthresh: %d, " - "flight_size: %d, pba: %d\n", - __func__, - transport, bytes_acked, cwnd, - ssthresh, flight_size, pba); + + pr_debug("%s: slow start: transport:%p, bytes_acked:%d, " + "cwnd:%d, ssthresh:%d, flight_size:%d, pba:%d\n", + __func__, transport, bytes_acked, cwnd, ssthresh, + flight_size, pba); } else { /* RFC 2960 7.2.2 Whenever cwnd is greater than ssthresh, * upon each SACK arrival that advances the Cumulative TSN Ack @@ -459,12 +458,12 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport, cwnd += pmtu; pba = ((cwnd < pba) ? (pba - cwnd) : 0); } - SCTP_DEBUG_PRINTK("%s: CONGESTION AVOIDANCE: " - "transport: %p, bytes_acked: %d, cwnd: %d, " - "ssthresh: %d, flight_size: %d, pba: %d\n", - __func__, - transport, bytes_acked, cwnd, - ssthresh, flight_size, pba); + + pr_debug("%s: congestion avoidance: transport:%p, " + "bytes_acked:%d, cwnd:%d, ssthresh:%d, " + "flight_size:%d, pba:%d\n", __func__, + transport, bytes_acked, cwnd, ssthresh, + flight_size, pba); } transport->cwnd = cwnd; @@ -558,10 +557,10 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, } transport->partial_bytes_acked = 0; - SCTP_DEBUG_PRINTK("%s: transport: %p reason: %d cwnd: " - "%d ssthresh: %d\n", __func__, - transport, reason, - transport->cwnd, transport->ssthresh); + + pr_debug("%s: transport:%p, reason:%d, cwnd:%d, ssthresh:%d\n", + __func__, transport, reason, transport->cwnd, + transport->ssthresh); } /* Apply Max.Burst limit to the congestion window: -- GitLab From 6c734fb8592f6768170e48e7102cb2f0a1bb9759 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sat, 29 Jun 2013 12:02:59 +0800 Subject: [PATCH 2171/2900] gre: fix a regression in ioctl When testing GRE tunnel, I got: # ip tunnel show get tunnel gre0 failed: Invalid argument get tunnel gre1 failed: Invalid argument This is a regression introduced by commit c54419321455631079c7d ("GRE: Refactor GRE tunneling code.") because previously we only check the parameters for SIOCADDTUNNEL and SIOCCHGTUNNEL, after that commit, the check is moved for all commands. So, just check for SIOCADDTUNNEL and SIOCCHGTUNNEL. After this patch I got: # ip tunnel show gre0: gre/ip remote any local any ttl inherit nopmtudisc gre1: gre/ip remote 192.168.122.101 local 192.168.122.45 ttl inherit Cc: Pravin B Shelar Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c326e869993a..1f6eab66f7ce 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -314,10 +314,11 @@ static int ipgre_tunnel_ioctl(struct net_device *dev, if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) return -EFAULT; - if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || - p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || - ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) { - return -EINVAL; + if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { + if (p.iph.version != 4 || p.iph.protocol != IPPROTO_GRE || + p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF)) || + ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING))) + return -EINVAL; } p.i_flags = gre_flags_to_tnl_flags(p.i_flags); p.o_flags = gre_flags_to_tnl_flags(p.o_flags); -- GitLab From ab6c7a0a43c2eaafa57583822b619b22637b49c7 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sat, 29 Jun 2013 13:00:57 +0800 Subject: [PATCH 2172/2900] vti: remove duplicated code to fix a memory leak vti module allocates dev->tstats twice: in vti_fb_tunnel_init() and in vti_tunnel_init(), this lead to a memory leak of dev->tstats. Just remove the duplicated operations in vti_fb_tunnel_init(). (candidate for -stable) Cc: Stephen Hemminger Cc: Saurabh Mohan Cc: "David S. Miller" Signed-off-by: Cong Wang Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv4/ip_vti.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index c118f6b576bb..17cc0ffa8c0d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -606,17 +606,10 @@ static int __net_init vti_fb_tunnel_init(struct net_device *dev) struct iphdr *iph = &tunnel->parms.iph; struct vti_net *ipn = net_generic(dev_net(dev), vti_net_id); - tunnel->dev = dev; - strcpy(tunnel->parms.name, dev->name); - iph->version = 4; iph->protocol = IPPROTO_IPIP; iph->ihl = 5; - dev->tstats = alloc_percpu(struct pcpu_tstats); - if (!dev->tstats) - return -ENOMEM; - dev_hold(dev); rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); return 0; -- GitLab From 8965779d2c0e6ab246c82a405236b1fb2adae6b2 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Sat, 29 Jun 2013 21:30:49 +0800 Subject: [PATCH 2173/2900] ipv6,mcast: always hold idev->lock before mca_lock dingtianhong reported the following deadlock detected by lockdep: ====================================================== [ INFO: possible circular locking dependency detected ] 3.4.24.05-0.1-default #1 Not tainted ------------------------------------------------------- ksoftirqd/0/3 is trying to acquire lock: (&ndev->lock){+.+...}, at: [] ipv6_get_lladdr+0x74/0x120 but task is already holding lock: (&mc->mca_lock){+.+...}, at: [] mld_send_report+0x40/0x150 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&mc->mca_lock){+.+...}: [] validate_chain+0x637/0x730 [] __lock_acquire+0x2f7/0x500 [] lock_acquire+0x114/0x150 [] rt_spin_lock+0x4a/0x60 [] igmp6_group_added+0x3b/0x120 [] ipv6_mc_up+0x38/0x60 [] ipv6_find_idev+0x3d/0x80 [] addrconf_notify+0x3d5/0x4b0 [] notifier_call_chain+0x3f/0x80 [] raw_notifier_call_chain+0x11/0x20 [] call_netdevice_notifiers+0x32/0x60 [] __dev_notify_flags+0x34/0x80 [] dev_change_flags+0x40/0x70 [] do_setlink+0x237/0x8a0 [] rtnl_newlink+0x3ec/0x600 [] rtnetlink_rcv_msg+0x160/0x310 [] netlink_rcv_skb+0x89/0xb0 [] rtnetlink_rcv+0x27/0x40 [] netlink_unicast+0x140/0x180 [] netlink_sendmsg+0x33e/0x380 [] sock_sendmsg+0x112/0x130 [] __sys_sendmsg+0x44e/0x460 [] sys_sendmsg+0x44/0x70 [] system_call_fastpath+0x16/0x1b -> #0 (&ndev->lock){+.+...}: [] check_prev_add+0x3de/0x440 [] validate_chain+0x637/0x730 [] __lock_acquire+0x2f7/0x500 [] lock_acquire+0x114/0x150 [] rt_read_lock+0x42/0x60 [] ipv6_get_lladdr+0x74/0x120 [] mld_newpack+0xb6/0x160 [] add_grhead+0xab/0xc0 [] add_grec+0x3ab/0x460 [] mld_send_report+0x5a/0x150 [] igmp6_timer_handler+0x4e/0xb0 [] call_timer_fn+0xca/0x1d0 [] run_timer_softirq+0x1df/0x2e0 [] handle_pending_softirqs+0xf7/0x1f0 [] __do_softirq_common+0x7b/0xf0 [] __thread_do_softirq+0x1af/0x210 [] run_ksoftirqd+0xe1/0x1f0 [] kthread+0xae/0xc0 [] kernel_thread_helper+0x4/0x10 actually we can just hold idev->lock before taking pmc->mca_lock, and avoid taking idev->lock again when iterating idev->addr_list, since the upper callers of mld_newpack() already take read_lock_bh(&idev->lock). Reported-by: dingtianhong Cc: dingtianhong Cc: Hideaki YOSHIFUJI Cc: David S. Miller Cc: Hannes Frederic Sowa Tested-by: Ding Tianhong Tested-by: Chen Weilong Signed-off-by: Cong Wang Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/addrconf.h | 3 +++ net/ipv6/addrconf.c | 4 ++-- net/ipv6/mcast.c | 18 ++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index f68eaf574d7e..c7b181cb47a6 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -86,6 +86,9 @@ extern int ipv6_dev_get_saddr(struct net *net, const struct in6_addr *daddr, unsigned int srcprefs, struct in6_addr *saddr); +extern int __ipv6_get_lladdr(struct inet6_dev *idev, + struct in6_addr *addr, + unsigned char banned_flags); extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 12dd2fec045c..75fd93bdd0d3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1444,8 +1444,8 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, } EXPORT_SYMBOL(ipv6_dev_get_saddr); -static int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, - unsigned char banned_flags) +int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, + unsigned char banned_flags) { struct inet6_ifaddr *ifp; int err = -EADDRNOTAVAIL; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 502c877cbf10..99cd65c715cd 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1351,8 +1351,9 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb, hdr->daddr = *daddr; } -static struct sk_buff *mld_newpack(struct net_device *dev, int size) +static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) { + struct net_device *dev = idev->dev; struct net *net = dev_net(dev); struct sock *sk = net->ipv6.igmp_sk; struct sk_buff *skb; @@ -1377,7 +1378,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) skb_reserve(skb, hlen); - if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { + if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { /* : * use unspecified address as the source address * when a valid link-local address is not available. @@ -1474,7 +1475,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, struct mld2_grec *pgr; if (!skb) - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(pmc->idev, dev->mtu); if (!skb) return NULL; pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec)); @@ -1494,7 +1495,8 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) { - struct net_device *dev = pmc->idev->dev; + struct inet6_dev *idev = pmc->idev; + struct net_device *dev = idev->dev; struct mld2_report *pmr; struct mld2_grec *pgr = NULL; struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; @@ -1523,7 +1525,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) mld_sendpack(skb); - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(idev, dev->mtu); } } first = 1; @@ -1550,7 +1552,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, pgr->grec_nsrcs = htons(scount); if (skb) mld_sendpack(skb); - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(idev, dev->mtu); first = 1; scount = 0; } @@ -1605,8 +1607,8 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) struct sk_buff *skb = NULL; int type; + read_lock_bh(&idev->lock); if (!pmc) { - read_lock_bh(&idev->lock); for (pmc=idev->mc_list; pmc; pmc=pmc->next) { if (pmc->mca_flags & MAF_NOREPORT) continue; @@ -1618,7 +1620,6 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) skb = add_grec(skb, pmc, type, 0, 0); spin_unlock_bh(&pmc->mca_lock); } - read_unlock_bh(&idev->lock); } else { spin_lock_bh(&pmc->mca_lock); if (pmc->mca_sfcount[MCAST_EXCLUDE]) @@ -1628,6 +1629,7 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) skb = add_grec(skb, pmc, type, 0, 0); spin_unlock_bh(&pmc->mca_lock); } + read_unlock_bh(&idev->lock); if (skb) mld_sendpack(skb); } -- GitLab From d8eb8f9963a55ccf6ebafa4bfdb9f70c17067825 Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Sat, 29 Jun 2013 15:39:19 +0200 Subject: [PATCH 2174/2900] qmi_wwan: add ONDA MT689DC device ID (fwd) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Another QMI-speaking device by ZTE, re-branded by ONDA! I'm connected ovr this device's QMI interface right now, so I can say I tested it! :) Note: a follow-up patch was posted to the linux-usb mailing list, to prevent the option driver from binding to the device's QMI interface, making it unusable. Signed-off-by: Enrico Mioso Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6de110263109..cdddb396e4f8 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -523,6 +523,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0019, 3)}, /* ONDA MT689DC */ {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, -- GitLab From 15627e847e4356ebdd49e7c3f10a671819995be6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 1 Jul 2013 00:13:27 +0100 Subject: [PATCH 2175/2900] cassini: Make missing firmware non-fatal The firmware patch for the Saturn PHY fixes a bug, but is not absolutely essential. And its licence is unclear, so it is not included in all distributions. Just log an error message and continue if it is missing or invalid. References: http://bugs.debian.org/712674 Signed-off-by: Ben Hutchings Tested-by: Jose Andres Arias Velichko (against 3.2) Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/cassini.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 4c682a3d0424..759441b29e53 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -808,44 +808,43 @@ static int cas_reset_mii_phy(struct cas *cp) return limit <= 0; } -static int cas_saturn_firmware_init(struct cas *cp) +static void cas_saturn_firmware_init(struct cas *cp) { const struct firmware *fw; const char fw_name[] = "sun/cassini.bin"; int err; if (PHY_NS_DP83065 != cp->phy_id) - return 0; + return; err = request_firmware(&fw, fw_name, &cp->pdev->dev); if (err) { pr_err("Failed to load firmware \"%s\"\n", fw_name); - return err; + return; } if (fw->size < 2) { pr_err("bogus length %zu in \"%s\"\n", fw->size, fw_name); - err = -EINVAL; goto out; } cp->fw_load_addr= fw->data[1] << 8 | fw->data[0]; cp->fw_size = fw->size - 2; cp->fw_data = vmalloc(cp->fw_size); - if (!cp->fw_data) { - err = -ENOMEM; + if (!cp->fw_data) goto out; - } memcpy(cp->fw_data, &fw->data[2], cp->fw_size); out: release_firmware(fw); - return err; } static void cas_saturn_firmware_load(struct cas *cp) { int i; + if (!cp->fw_data) + return; + cas_phy_powerdown(cp); /* expanded memory access mode */ @@ -5083,8 +5082,7 @@ static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (cas_check_invariants(cp)) goto err_out_iounmap; if (cp->cas_flags & CAS_FLAG_SATURN) - if (cas_saturn_firmware_init(cp)) - goto err_out_iounmap; + cas_saturn_firmware_init(cp); cp->init_block = (struct cas_init_block *) pci_alloc_consistent(pdev, sizeof(struct cas_init_block), -- GitLab From e02010adeeb21ef56d6b9b68c785ed1ecc832aee Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 1 Jul 2013 11:31:36 +0200 Subject: [PATCH 2176/2900] net: sctp: get rid of SCTP_DBG_TSNS entirely After having reworked the debugging framework, Neil and Vlad agreed to get rid of the leftover SCTP_DBG_TSNS code for a couple of reasons: We can use systemtap scripts to investigate these things, we now have pr_debug() helpers that make life easier, and if we really need anything else besides those tools, we will be forced to come up with something better than we have there. Therefore, get rid of this ifdef debugging code entirely for now. Signed-off-by: Daniel Borkmann CC: Vlad Yasevich CC: Neil Horman Acked-by: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/Kconfig | 9 ---- net/sctp/outqueue.c | 105 -------------------------------------------- 2 files changed, 114 deletions(-) diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index d80bf1aebaed..71c1a598d9bc 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -49,15 +49,6 @@ config NET_SCTPPROBE To compile this code as a module, choose M here: the module will be called sctp_probe. -config SCTP_DBG_TSNS - bool "SCTP: Debug transactions" - help - If you say Y, this will enable transaction debugging, visible - from the kernel's dynamic debugging framework. - - If unsure, say N. However, if you are running into problems, use - this option to gather outqueue trace information. - config SCTP_DBG_OBJCNT bool "SCTP: Debug object counts" depends on PROC_FS diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 511b3b35d609..cb80a8e060b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1335,21 +1335,6 @@ static void sctp_check_transmitted(struct sctp_outq *q, int bytes_acked = 0; int migrate_bytes = 0; - /* These state variables are for coherent debug output. --xguo */ - -#ifdef CONFIG_SCTP_DBG_TSNS - __u32 dbg_ack_tsn = 0; /* An ACKed TSN range starts here... */ - __u32 dbg_last_ack_tsn = 0; /* ...and finishes here. */ - __u32 dbg_kept_tsn = 0; /* An un-ACKed range starts here... */ - __u32 dbg_last_kept_tsn = 0; /* ...and finishes here. */ - - /* 0 : The last TSN was ACKed. - * 1 : The last TSN was NOT ACKed (i.e. KEPT). - * -1: We need to initialize. - */ - int dbg_prt_state = -1; -#endif /* CONFIG_SCTP_DBG_TSNS */ - sack_ctsn = ntohl(sack->cum_tsn_ack); INIT_LIST_HEAD(&tlist); @@ -1471,49 +1456,6 @@ static void sctp_check_transmitted(struct sctp_outq *q, */ list_add_tail(lchunk, &tlist); } - -#ifdef CONFIG_SCTP_DBG_TSNS - switch (dbg_prt_state) { - case 0: /* last TSN was ACKed */ - if (dbg_last_ack_tsn + 1 == tsn) { - /* This TSN belongs to the - * current ACK range. - */ - break; - } - - if (dbg_last_ack_tsn != dbg_ack_tsn) { - /* Display the end of the - * current range. - */ - pr_cont("-%08x", dbg_last_ack_tsn); - } - - /* Start a new range. */ - pr_cont(",%08x", tsn); - dbg_ack_tsn = tsn; - break; - - case 1: /* The last TSN was NOT ACKed. */ - if (dbg_last_kept_tsn != dbg_kept_tsn) { - /* Display the end of current range. */ - pr_cont("-%08x", dbg_last_kept_tsn); - } - - pr_cont("\n"); - /* FALL THROUGH... */ - default: - /* This is the first-ever TSN we examined. */ - /* Start a new range of ACK-ed TSNs. */ - pr_debug("ACKed: %08x", tsn); - - dbg_prt_state = 0; - dbg_ack_tsn = tsn; - } - - dbg_last_ack_tsn = tsn; -#endif /* CONFIG_SCTP_DBG_TSNS */ - } else { if (tchunk->tsn_gap_acked) { pr_debug("%s: receiver reneged on data TSN:0x%x\n", @@ -1537,56 +1479,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, } list_add_tail(lchunk, &tlist); - -#ifdef CONFIG_SCTP_DBG_TSNS - /* See the above comments on ACK-ed TSNs. */ - switch (dbg_prt_state) { - case 1: - if (dbg_last_kept_tsn + 1 == tsn) - break; - - if (dbg_last_kept_tsn != dbg_kept_tsn) - pr_cont("-%08x", dbg_last_kept_tsn); - - pr_cont(",%08x", tsn); - dbg_kept_tsn = tsn; - break; - - case 0: - if (dbg_last_ack_tsn != dbg_ack_tsn) - pr_cont("-%08x", dbg_last_ack_tsn); - - pr_cont("\n"); - /* FALL THROUGH... */ - default: - pr_debug("KEPT: %08x", tsn); - - dbg_prt_state = 1; - dbg_kept_tsn = tsn; - } - - dbg_last_kept_tsn = tsn; -#endif /* CONFIG_SCTP_DBG_TSNS */ } } -#ifdef CONFIG_SCTP_DBG_TSNS - /* Finish off the last range, displaying its ending TSN. */ - switch (dbg_prt_state) { - case 0: - if (dbg_last_ack_tsn != dbg_ack_tsn) - pr_cont("-%08x\n", dbg_last_ack_tsn); - else - pr_cont("\n"); - break; - case 1: - if (dbg_last_kept_tsn != dbg_kept_tsn) - pr_cont("-%08x\n", dbg_last_kept_tsn); - else - pr_cont("\n"); - break; - } -#endif /* CONFIG_SCTP_DBG_TSNS */ if (transport) { if (bytes_acked) { struct sctp_association *asoc = transport->asoc; -- GitLab From 058eec4116935c5640299913e1e0715e87ec622a Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Mon, 1 Jul 2013 17:23:05 +0200 Subject: [PATCH 2177/2900] bnx2x: remove zeroing of dump data buffer There is no need to initialize the dump data with zeros. data is allocated with vzalloc, so it's already zero-filled. More importantly, the memset is harmful, because dump->len (the length requested by userspace) can be bigger than the allocated buffer (whose size is determined by asking the driver's .get_dump_flag method). Signed-off-by: Michal Schmidt Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index b8c067d1a0f2..4f75ae854b3d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -985,8 +985,6 @@ static int bnx2x_get_dump_data(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); struct dump_header dump_hdr = {0}; - memset(p, 0, dump->len); - /* Disable parity attentions as long as following dump may * cause false alarms by reading never written registers. We * will re-enable parity attentions right after the dump. -- GitLab From 5bb680d6cbe36de9d7ba12b05f845c91a8692318 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Mon, 1 Jul 2013 17:23:06 +0200 Subject: [PATCH 2178/2900] bnx2x: fix dump flag handling bnx2x interprets the dump flag as an index of a register preset. It is important to validate the index to avoid out of bounds memory accesses. Signed-off-by: Michal Schmidt Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 3 +++ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 4f75ae854b3d..cf5cebc358b8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -959,6 +959,9 @@ static int bnx2x_set_dump(struct net_device *dev, struct ethtool_dump *val) struct bnx2x *bp = netdev_priv(dev); /* Use the ethtool_dump "flag" field as the dump preset index */ + if (val->flag < 1 || val->flag > DUMP_MAX_PRESETS) + return -EINVAL; + bp->dump_preset_idx = val->flag; return 0; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 740518bbcb5f..15a528bda87c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11636,6 +11636,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) bp->min_msix_vec_cnt = 2; BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt); + bp->dump_preset_idx = 1; + return rc; } -- GitLab From 8cc2d927c26a677415a9d0d23b9a043107f948c3 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Mon, 1 Jul 2013 17:23:20 +0200 Subject: [PATCH 2179/2900] bnx2x: fill in sane dump flag information bnx2x did not set dump->version in its .get_dump_flag() method. Let's set it to BNX2X_DUMP_VERSION. It's not a particularly nice number (0x50acff01 currently), but at least it's something deterministic. dump->flag should report the value previously set using ethtool -W. Signed-off-by: Michal Schmidt Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index cf5cebc358b8..c5f225101684 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -971,12 +971,12 @@ static int bnx2x_get_dump_flag(struct net_device *dev, { struct bnx2x *bp = netdev_priv(dev); + dump->version = BNX2X_DUMP_VERSION; + dump->flag = bp->dump_preset_idx; /* Calculate the requested preset idx length */ dump->len = bnx2x_get_preset_regs_len(dev, bp->dump_preset_idx); DP(BNX2X_MSG_ETHTOOL, "Get dump preset %d length=%d\n", bp->dump_preset_idx, dump->len); - - dump->flag = ETHTOOL_GET_DUMP_DATA; return 0; } -- GitLab From c590b5e2f05b5e98e614382582b7ae4cddb37599 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Mon, 1 Jul 2013 17:23:30 +0200 Subject: [PATCH 2180/2900] ethtool: make .get_dump_data() harder to misuse by drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the patch "bnx2x: remove zeroing of dump data buffer" showed, it is too easy implement .get_dump_data incorrectly in a driver. Let's make sure drivers cannot get confused by userspace requesting a too big dump. Also WARN if the driver sets dump->len to something weird and make sure the length reported to userspace is the actual length of data copied to userspace. Signed-off-by: Michal Schmidt Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/ethtool.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 9255bbdf81ff..ab5fa6336c84 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1320,10 +1320,19 @@ static int ethtool_get_dump_data(struct net_device *dev, if (ret) return ret; - len = (tmp.len > dump.len) ? dump.len : tmp.len; + len = min(tmp.len, dump.len); if (!len) return -EFAULT; + /* Don't ever let the driver think there's more space available + * than it requested with .get_dump_flag(). + */ + dump.len = len; + + /* Always allocate enough space to hold the whole thing so that the + * driver does not need to check the length and bother with partial + * dumping. + */ data = vzalloc(tmp.len); if (!data) return -ENOMEM; @@ -1331,6 +1340,16 @@ static int ethtool_get_dump_data(struct net_device *dev, if (ret) goto out; + /* There are two sane possibilities: + * 1. The driver's .get_dump_data() does not touch dump.len. + * 2. Or it may set dump.len to how much it really writes, which + * should be tmp.len (or len if it can do a partial dump). + * In any case respond to userspace with the actual length of data + * it's receiving. + */ + WARN_ON(dump.len != len && dump.len != tmp.len); + dump.len = len; + if (copy_to_user(useraddr, &dump, sizeof(dump))) { ret = -EFAULT; goto out; -- GitLab From 37beae65fa4a683b2f17f3472708ab58d134b03c Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 1 Jul 2013 18:09:50 +0200 Subject: [PATCH 2181/2900] tools: selftests: psock_tpacket: get rid of macro wrappers The TPACKET_V3 test code consists of a lot of unecessary macro wrappers that rather obfuscate what members are accessed in what way. So get rid of them and make the code more readable. Also credit Chetan for providing tpacket_v3 example code. Furthermore, get rid of private offset usage, as we do not need it here. Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- tools/testing/selftests/net/psock_tpacket.c | 59 +++++++-------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/tools/testing/selftests/net/psock_tpacket.c b/tools/testing/selftests/net/psock_tpacket.c index c41b58640a05..24adf709bd9d 100644 --- a/tools/testing/selftests/net/psock_tpacket.c +++ b/tools/testing/selftests/net/psock_tpacket.c @@ -1,6 +1,7 @@ /* * Copyright 2013 Red Hat, Inc. * Author: Daniel Borkmann + * Chetan Loke (TPACKET_V3 usage example) * * A basic test of packet socket's TPACKET_V1/TPACKET_V2/TPACKET_V3 behavior. * @@ -71,18 +72,8 @@ # define __align_tpacket(x) __attribute__((aligned(TPACKET_ALIGN(x)))) #endif -#define BLOCK_STATUS(x) ((x)->h1.block_status) -#define BLOCK_NUM_PKTS(x) ((x)->h1.num_pkts) -#define BLOCK_O2FP(x) ((x)->h1.offset_to_first_pkt) -#define BLOCK_LEN(x) ((x)->h1.blk_len) -#define BLOCK_SNUM(x) ((x)->h1.seq_num) -#define BLOCK_O2PRIV(x) ((x)->offset_to_priv) -#define BLOCK_PRIV(x) ((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x))) -#define BLOCK_HDR_LEN (ALIGN_8(sizeof(struct block_desc))) -#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) -#define BLOCK_PLUS_PRIV(sz_pri) (BLOCK_HDR_LEN + ALIGN_8((sz_pri))) - #define NUM_PACKETS 100 +#define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) struct ring { struct iovec *rd; @@ -476,41 +467,30 @@ static uint64_t __v3_prev_block_seq_num = 0; void __v3_test_block_seq_num(struct block_desc *pbd) { - if (__v3_prev_block_seq_num + 1 != BLOCK_SNUM(pbd)) { + if (__v3_prev_block_seq_num + 1 != pbd->h1.seq_num) { fprintf(stderr, "\nprev_block_seq_num:%"PRIu64", expected " "seq:%"PRIu64" != actual seq:%"PRIu64"\n", __v3_prev_block_seq_num, __v3_prev_block_seq_num + 1, - (uint64_t) BLOCK_SNUM(pbd)); + (uint64_t) pbd->h1.seq_num); exit(1); } - __v3_prev_block_seq_num = BLOCK_SNUM(pbd); + __v3_prev_block_seq_num = pbd->h1.seq_num; } static void __v3_test_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) { - if (BLOCK_NUM_PKTS(pbd)) { - if (bytes != BLOCK_LEN(pbd)) { - fprintf(stderr, "\nblock:%u with %upackets, expected " - "len:%u != actual len:%u\n", block_num, - BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd)); - exit(1); - } - } else { - if (BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(13)) { - fprintf(stderr, "\nblock:%u, expected len:%lu != " - "actual len:%u\n", block_num, BLOCK_HDR_LEN, - BLOCK_LEN(pbd)); - exit(1); - } + if (pbd->h1.num_pkts && bytes != pbd->h1.blk_len) { + fprintf(stderr, "\nblock:%u with %upackets, expected " + "len:%u != actual len:%u\n", block_num, + pbd->h1.num_pkts, bytes, pbd->h1.blk_len); + exit(1); } } static void __v3_test_block_header(struct block_desc *pbd, const int block_num) { - uint32_t block_status = BLOCK_STATUS(pbd); - - if ((block_status & TP_STATUS_USER) == 0) { + if ((pbd->h1.block_status & TP_STATUS_USER) == 0) { fprintf(stderr, "\nblock %u: not in TP_STATUS_USER\n", block_num); exit(1); } @@ -520,14 +500,15 @@ static void __v3_test_block_header(struct block_desc *pbd, const int block_num) static void __v3_walk_block(struct block_desc *pbd, const int block_num) { - int num_pkts = BLOCK_NUM_PKTS(pbd), i; - unsigned long bytes = 0; - unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(13); + int num_pkts = pbd->h1.num_pkts, i; + unsigned long bytes = 0, bytes_with_padding = ALIGN_8(sizeof(*pbd)); struct tpacket3_hdr *ppd; __v3_test_block_header(pbd, block_num); - ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd)); + ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + + pbd->h1.offset_to_first_pkt); + for (i = 0; i < num_pkts; ++i) { bytes += ppd->tp_snaplen; @@ -551,7 +532,7 @@ static void __v3_walk_block(struct block_desc *pbd, const int block_num) void __v3_flush_block(struct block_desc *pbd) { - BLOCK_STATUS(pbd) = TP_STATUS_KERNEL; + pbd->h1.block_status = TP_STATUS_KERNEL; __sync_synchronize(); } @@ -577,7 +558,7 @@ static void walk_v3_rx(int sock, struct ring *ring) while (total_packets < NUM_PACKETS * 2) { pbd = (struct block_desc *) ring->rd[block_num].iov_base; - while ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) + while ((pbd->h1.block_status & TP_STATUS_USER) == 0) poll(&pfd, 1, 1); __v3_walk_block(pbd, block_num); @@ -624,8 +605,8 @@ static void __v1_v2_fill(struct ring *ring, unsigned int blocks) static void __v3_fill(struct ring *ring, unsigned int blocks) { ring->req3.tp_retire_blk_tov = 64; - ring->req3.tp_sizeof_priv = 13; - ring->req3.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH; + ring->req3.tp_sizeof_priv = 0; + ring->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH; ring->req3.tp_block_size = getpagesize() << 2; ring->req3.tp_frame_size = TPACKET_ALIGNMENT << 7; -- GitLab From a05b1019cfe5250baf24e26e2e7112cf66054114 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 1 Jul 2013 18:10:36 +0200 Subject: [PATCH 2182/2900] net: sctp: prevent checksum.h from double inclusion The header file checksum.h is missing proper defines that prevents it from double inclusion. Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Signed-off-by: David S. Miller --- include/net/sctp/checksum.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/net/sctp/checksum.h b/include/net/sctp/checksum.h index 5a2110d3176d..0cb08e6fb6df 100644 --- a/include/net/sctp/checksum.h +++ b/include/net/sctp/checksum.h @@ -42,6 +42,9 @@ * be incorporated into the next SCTP release. */ +#ifndef __sctp_checksum_h__ +#define __sctp_checksum_h__ + #include #include #include @@ -81,3 +84,5 @@ static inline __le32 sctp_end_cksum(__u32 crc32) { return cpu_to_le32(~crc32); } + +#endif /* __sctp_checksum_h__ */ -- GitLab From a7599398a312fd7b81aba0188ca4749f781f5a52 Mon Sep 17 00:00:00 2001 From: Aaron Marburg Date: Tue, 2 Jul 2013 10:00:06 +1200 Subject: [PATCH 2183/2900] net: ipheth: Add USB ID for iPad mini Adds the USB device ID (0x12ab) to the ipheth network-over-USB-tethering driver for iOS devices. Applied and tested against mainline tag v3.10 (as well as 3.8.x and 3.6.y kernel for Raspbian on Raspberry pi) Signed-off-by: Aaron Marburg Signed-off-by: David S. Miller --- drivers/net/usb/ipheth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 534d8becbbdc..ff8594d8dd2d 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -60,6 +60,7 @@ #define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_4 0x1297 #define USB_PRODUCT_IPAD 0x129a +#define USB_PRODUCT_IPAD_MINI 0x12ab #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 #define USB_PRODUCT_IPHONE_5 0x12a8 @@ -106,6 +107,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPAD, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { USB_DEVICE_AND_INTERFACE_INFO( USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, -- GitLab From b48410b4dc9c7306df21e508cc6739a55c350eb8 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 1 Jul 2013 22:19:45 +0300 Subject: [PATCH 2184/2900] ipv4: remove fib_update_nh_saddrs() declaration. This patch removes the fib_update_nh_saddrs() declaration from include/net/ip_fib.h, as the fib_update_nh_saddrs() method was removed in coomit 436c3b6 ("ipv4: Invalidate nexthop cache nh_saddr more correctly"). Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/ip_fib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index aac85534d7b5..cbf2be37c91a 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -291,7 +291,6 @@ static inline int fib_num_tclassid_users(struct net *net) extern int ip_fib_check_default(__be32 gw, struct net_device *dev); extern int fib_sync_down_dev(struct net_device *dev, int force); extern int fib_sync_down_addr(struct net *net, __be32 local); -extern void fib_update_nh_saddrs(struct net_device *dev); extern int fib_sync_up(struct net_device *dev); extern void fib_select_multipath(struct fib_result *res); -- GitLab From 4787c368a9bca39e173d702389ee2eaf0520abc1 Mon Sep 17 00:00:00 2001 From: Seiji Aguchi Date: Fri, 28 Jun 2013 14:02:11 -0400 Subject: [PATCH 2185/2900] x86/tracing: Add irq_enter/exit() in smp_trace_reschedule_interrupt() Reschedule vector tracepoints may be called in cpu idle state. This causes lockdep check warning below. The tracepoint requires rcu but for accuracy it also requires irq_enter() (tracepoints record the irq context), thus, the tracepoint interrupt handler should be calling irq_enter() and not rcu_irq_enter() (irq_enter() calls rcu_irq_enter()). So, add irq_enter/exit() to smp_trace_reschedule_interrupt() with common pre/post processing functions, smp_entering_irq() and exiting_irq() (exiting_irq() calls just irq_exit() in arch/x86/include/asm/apic.h), because these can be shared among reschedule, call_function, and call_function_single vectors. [ 50.720557] Testing event reschedule_exit: [ 50.721349] [ 50.721502] =============================== [ 50.721835] [ INFO: suspicious RCU usage. ] [ 50.722169] 3.10.0-rc6-00004-gcf910e8 #190 Not tainted [ 50.722582] ------------------------------- [ 50.722915] /c/kernel-tests/src/linux/arch/x86/include/asm/trace/irq_vectors.h:50 suspicious rcu_dereference_check() usage! [ 50.723770] [ 50.723770] other info that might help us debug this: [ 50.723770] [ 50.724385] [ 50.724385] RCU used illegally from idle CPU! [ 50.724385] rcu_scheduler_active = 1, debug_locks = 0 [ 50.725232] RCU used illegally from extended quiescent state! [ 50.725690] no locks held by swapper/0/0. [ 50.726010] [ 50.726010] stack backtrace: [...] Signed-off-by: Seiji Aguchi Reviewed-by: Steven Rostedt Link: http://lkml.kernel.org/r/51CDCFA3.9080101@hds.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/smp.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index f4fe0b8879e0..cdaa347dfcad 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -265,23 +265,30 @@ void smp_reschedule_interrupt(struct pt_regs *regs) */ } -void smp_trace_reschedule_interrupt(struct pt_regs *regs) +static inline void smp_entering_irq(void) { ack_APIC_irq(); + irq_enter(); +} + +void smp_trace_reschedule_interrupt(struct pt_regs *regs) +{ + /* + * Need to call irq_enter() before calling the trace point. + * __smp_reschedule_interrupt() calls irq_enter/exit() too (in + * scheduler_ipi(). This is OK, since those functions are allowed + * to nest. + */ + smp_entering_irq(); trace_reschedule_entry(RESCHEDULE_VECTOR); __smp_reschedule_interrupt(); trace_reschedule_exit(RESCHEDULE_VECTOR); + exiting_irq(); /* * KVM uses this interrupt to force a cpu out of guest mode */ } -static inline void call_function_entering_irq(void) -{ - ack_APIC_irq(); - irq_enter(); -} - static inline void __smp_call_function_interrupt(void) { generic_smp_call_function_interrupt(); @@ -290,14 +297,14 @@ static inline void __smp_call_function_interrupt(void) void smp_call_function_interrupt(struct pt_regs *regs) { - call_function_entering_irq(); + smp_entering_irq(); __smp_call_function_interrupt(); exiting_irq(); } void smp_trace_call_function_interrupt(struct pt_regs *regs) { - call_function_entering_irq(); + smp_entering_irq(); trace_call_function_entry(CALL_FUNCTION_VECTOR); __smp_call_function_interrupt(); trace_call_function_exit(CALL_FUNCTION_VECTOR); @@ -312,14 +319,14 @@ static inline void __smp_call_function_single_interrupt(void) void smp_call_function_single_interrupt(struct pt_regs *regs) { - call_function_entering_irq(); + smp_entering_irq(); __smp_call_function_single_interrupt(); exiting_irq(); } void smp_trace_call_function_single_interrupt(struct pt_regs *regs) { - call_function_entering_irq(); + smp_entering_irq(); trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR); __smp_call_function_single_interrupt(); trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR); -- GitLab From 8ef2c3bca599710a410cbecb4867e27728fef043 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Tue, 2 Jul 2013 00:08:54 +0100 Subject: [PATCH 2186/2900] xen-netback: xenbus.c: use more current logging styles Convert one printk to pr_. Add a missing newline in several places to avoid message interleaving, coalesce formats, reflow modified lines to 80 columns. Signed-off-by: Joe Perches Signed-off-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/xenbus.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 04bd860d16a9..1fe48fe364ed 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -130,7 +130,7 @@ static int netback_probe(struct xenbus_device *dev, "feature-split-event-channels", "%u", separate_tx_rx_irq); if (err) - pr_debug("Error writing feature-split-event-channels"); + pr_debug("Error writing feature-split-event-channels\n"); err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) @@ -145,7 +145,7 @@ static int netback_probe(struct xenbus_device *dev, xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, err, "%s", message); fail: - pr_debug("failed"); + pr_debug("failed\n"); netback_remove(dev); return err; } @@ -228,15 +228,14 @@ static void frontend_changed(struct xenbus_device *dev, { struct backend_info *be = dev_get_drvdata(&dev->dev); - pr_debug("frontend state %s", xenbus_strstate(frontend_state)); + pr_debug("frontend state %s\n", xenbus_strstate(frontend_state)); be->frontend_state = frontend_state; switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk(KERN_INFO "%s: %s: prepare for reconnect\n", - __func__, dev->nodename); + pr_info("%s: prepare for reconnect\n", dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } break; -- GitLab From f3ad89217fa8088203b6c040584987028d524456 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 2 Jul 2013 08:57:47 +0800 Subject: [PATCH 2187/2900] net: ethernet: davinci_emac: remove redundant dev_err call in davinci_emac_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Acked-by: Lad, Prabhakar Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_emac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index f118d7133128..07b176bcf929 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1870,7 +1870,6 @@ static int davinci_emac_probe(struct platform_device *pdev) priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; priv->remap_addr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->remap_addr)) { - dev_err(&pdev->dev, "unable to map IO\n"); rc = PTR_ERR(priv->remap_addr); goto no_pdata; } -- GitLab From e1558a93b61962710733dc8c11a2bc765607f1cd Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 2 Jul 2013 09:02:07 +0800 Subject: [PATCH 2188/2900] l2tp: add missing .owner to struct pppox_proto Add missing .owner of struct pppox_proto. This prevents the module from being removed from underneath its users. Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- net/l2tp/l2tp_ppp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 8dec6876dc50..5ebee2ded9e9 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -1793,7 +1793,8 @@ static const struct proto_ops pppol2tp_ops = { static const struct pppox_proto pppol2tp_proto = { .create = pppol2tp_create, - .ioctl = pppol2tp_ioctl + .ioctl = pppol2tp_ioctl, + .owner = THIS_MODULE, }; #ifdef CONFIG_L2TP_V3 -- GitLab From 3b7b514f44bff05d26a6499c4d4fac2a83938e6e Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 2 Jul 2013 14:49:34 +0800 Subject: [PATCH 2189/2900] ipip: fix a regression in ioctl This is a regression introduced by commit fd58156e456d9f68fe0448 (IPIP: Use ip-tunneling code.) Similar to GRE tunnel, previously we only check the parameters for SIOCADDTUNNEL and SIOCCHGTUNNEL, after that commit, the check is moved for all commands. So, just check for SIOCADDTUNNEL and SIOCCHGTUNNEL. Also, the check for i_key, o_key etc. is suspicious too, which did not exist before, reset them before passing to ip_tunnel_ioctl(). Cc: Pravin B Shelar Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv4/ipip.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index e6905fbda2a2..51fc2a1dcdd3 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -244,11 +244,13 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) return -EFAULT; - if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP || - p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) - return -EINVAL; - if (p.i_key || p.o_key || p.i_flags || p.o_flags) - return -EINVAL; + if (cmd == SIOCADDTUNNEL || cmd == SIOCCHGTUNNEL) { + if (p.iph.version != 4 || p.iph.protocol != IPPROTO_IPIP || + p.iph.ihl != 5 || (p.iph.frag_off&htons(~IP_DF))) + return -EINVAL; + } + + p.i_key = p.o_key = p.i_flags = p.o_flags = 0; if (p.iph.ttl) p.iph.frag_off |= htons(IP_DF); -- GitLab From 06efce71166b222b6715c73700f5e9b228d68999 Mon Sep 17 00:00:00 2001 From: Jim Baxter Date: Thu, 27 Jun 2013 19:25:08 +0100 Subject: [PATCH 2190/2900] net: fec: Fix Transmitted bytes counter The tx_bytes field was not being updated so the network card statistics showed 0.0B transmitted. Signed-off-by: Jim Baxter Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 5664acd8e0f4..aff8a5cd17c7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -739,6 +739,7 @@ fec_enet_tx(struct net_device *ndev) ndev->stats.tx_carrier_errors++; } else { ndev->stats.tx_packets++; + ndev->stats.tx_bytes += bdp->cbd_datlen; } if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) && -- GitLab From 1fc4c84d49558ceca04761abd3f7eb5224af75b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sat, 29 Jun 2013 12:03:06 +0200 Subject: [PATCH 2191/2900] net: cdc_ether: allow combined control and data interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Icera based Huawei modems handled by this driver are not completely CDC ECM compliant, using the same USB interface for both control and data. The CDC functional descriptors include a Union naming this interface as both master and slave, so it is supportable by relaxing the descriptor parsing in case these interfaces are identical. This has been tested on a Huawei K3806 and verified to add support for that device. Reported-and-tested-by: Enrico Mioso Signed-off-by: Bjørn Mork Acked-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 04ee044dde51..4393f1483126 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -215,6 +215,10 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } + /* some devices merge these - skip class check */ + if (info->control == info->data) + goto next_desc; + /* a data interface altsetting does the real i/o */ d = &info->data->cur_altsetting->desc; if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { @@ -304,19 +308,23 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) /* claim data interface and set it up ... with side effects. * network traffic can't flow until an altsetting is enabled. */ - status = usb_driver_claim_interface(driver, info->data, dev); - if (status < 0) - return status; + if (info->data != info->control) { + status = usb_driver_claim_interface(driver, info->data, dev); + if (status < 0) + return status; + } status = usbnet_get_endpoints(dev, info->data); if (status < 0) { /* ensure immediate exit from usbnet_disconnect */ usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); + if (info->data != info->control) + usb_driver_release_interface(driver, info->data); return status; } /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ - dev->status = NULL; + if (info->data != info->control) + dev->status = NULL; if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { struct usb_endpoint_descriptor *desc; @@ -349,6 +357,10 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) struct cdc_state *info = (void *) &dev->data; struct usb_driver *driver = driver_of(intf); + /* combined interface - nothing to do */ + if (info->data == info->control) + return; + /* disconnect master --> disconnect slave */ if (intf == info->control && info->data) { /* ensure immediate exit from usbnet_disconnect */ -- GitLab From 0429ffeff460c4302bd1520e696bafe446e15181 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 13:10:28 +0100 Subject: [PATCH 2192/2900] ASoC: samsung: Remove obsolete GPIO based DT pinmuxing Since the Samsung platforms have moved to pinctrl for pin muxing and that is handled in the core the old GPIO based muxing code can just be removed. Something similar had been submitted by Thomas Abraham back in March but a resubmission following review never happened. Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 66 +++-------------------------------------- 1 file changed, 4 insertions(+), 62 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 82ebb1a51479..7a1734697434 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1016,52 +1016,6 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec) return i2s; } -#ifdef CONFIG_OF -static int samsung_i2s_parse_dt_gpio(struct i2s_dai *i2s) -{ - struct device *dev = &i2s->pdev->dev; - int index, gpio, ret; - - for (index = 0; index < 7; index++) { - gpio = of_get_gpio(dev->of_node, index); - if (!gpio_is_valid(gpio)) { - dev_err(dev, "invalid gpio[%d]: %d\n", index, gpio); - goto free_gpio; - } - - ret = gpio_request(gpio, dev_name(dev)); - if (ret) { - dev_err(dev, "gpio [%d] request failed\n", gpio); - goto free_gpio; - } - i2s->gpios[index] = gpio; - } - return 0; - -free_gpio: - while (--index >= 0) - gpio_free(i2s->gpios[index]); - return -EINVAL; -} - -static void samsung_i2s_dt_gpio_free(struct i2s_dai *i2s) -{ - unsigned int index; - for (index = 0; index < 7; index++) - gpio_free(i2s->gpios[index]); -} -#else -static int samsung_i2s_parse_dt_gpio(struct i2s_dai *dai) -{ - return -EINVAL; -} - -static void samsung_i2s_dt_gpio_free(struct i2s_dai *dai) -{ -} - -#endif - static const struct of_device_id exynos_i2s_match[]; static inline int samsung_i2s_get_driver_data(struct platform_device *pdev) @@ -1235,18 +1189,10 @@ static int samsung_i2s_probe(struct platform_device *pdev) pri_dai->sec_dai = sec_dai; } - if (np) { - if (samsung_i2s_parse_dt_gpio(pri_dai)) { - dev_err(&pdev->dev, "Unable to configure gpio\n"); - ret = -EINVAL; - goto err; - } - } else { - if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { - dev_err(&pdev->dev, "Unable to configure gpio\n"); - ret = -EINVAL; - goto err; - } + if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) { + dev_err(&pdev->dev, "Unable to configure gpio\n"); + ret = -EINVAL; + goto err; } snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component, @@ -1267,14 +1213,10 @@ static int samsung_i2s_remove(struct platform_device *pdev) { struct i2s_dai *i2s, *other; struct resource *res; - struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data; i2s = dev_get_drvdata(&pdev->dev); other = i2s->pri_dai ? : i2s->sec_dai; - if (!i2s_pdata->cfg_gpio && pdev->dev.of_node) - samsung_i2s_dt_gpio_free(i2s->pri_dai); - if (other) { other->pri_dai = NULL; other->sec_dai = NULL; -- GitLab From 0c1dcfd53b1066c411d3885cf8156abf59694360 Mon Sep 17 00:00:00 2001 From: Sebastian Hesselbarth Date: Tue, 11 Jun 2013 08:38:50 +0200 Subject: [PATCH 2193/2900] clocksource: Add Marvell Orion SoC timer This patch add a DT enabled driver for timers found on Marvell Orion SoCs (Kirkwood, Dove, Orion5x, and Discovery Innovation). It installs a free- running clocksource on timer0 and a clockevent source on timer1. Corresponding device tree documentation is also added. Signed-off-by: Sebastian Hesselbarth Signed-off-by: Daniel Lezcano Tested-by: Ezequiel Garcia Tested-by: Andrew Lunn --- .../bindings/timer/marvell,orion-timer.txt | 17 ++ drivers/clocksource/Kconfig | 5 + drivers/clocksource/Makefile | 1 + drivers/clocksource/time-orion.c | 150 ++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/marvell,orion-timer.txt create mode 100644 drivers/clocksource/time-orion.c diff --git a/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt new file mode 100644 index 000000000000..62bb8260cf6a --- /dev/null +++ b/Documentation/devicetree/bindings/timer/marvell,orion-timer.txt @@ -0,0 +1,17 @@ +Marvell Orion SoC timer + +Required properties: +- compatible: shall be "marvell,orion-timer" +- reg: base address of the timer register starting with TIMERS CONTROL register +- interrupt-parent: phandle of the bridge interrupt controller +- interrupts: should contain the interrupts for Timer0 and Timer1 +- clocks: phandle of timer reference clock (tclk) + +Example: + timer: timer { + compatible = "marvell,orion-timer"; + reg = <0x20300 0x20>; + interrupt-parent = <&bridge_intc>; + interrupts = <1>, <2>; + clocks = <&core_clk 0>; + }; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 0a04257edf65..c082e3e4bd0a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -25,6 +25,11 @@ config DW_APB_TIMER_OF config ARMADA_370_XP_TIMER bool +config ORION_TIMER + select CLKSRC_OF + select CLKSRC_MMIO + bool + config SUN4I_TIMER bool diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 9ba8b4d867e3..49bea7fad85c 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o +obj-$(CONFIG_ORION_TIMER) += time-orion.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_ARCH_MARCO) += timer-marco.o obj-$(CONFIG_ARCH_MXS) += mxs_timer.o diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c new file mode 100644 index 000000000000..ecbeb6810215 --- /dev/null +++ b/drivers/clocksource/time-orion.c @@ -0,0 +1,150 @@ +/* + * Marvell Orion SoC timer handling. + * + * Sebastian Hesselbarth + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Timer 0 is used as free-running clocksource, while timer 1 is + * used as clock_event_device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_CTRL 0x00 +#define TIMER0_EN BIT(0) +#define TIMER0_RELOAD_EN BIT(1) +#define TIMER1_EN BIT(2) +#define TIMER1_RELOAD_EN BIT(3) +#define TIMER0_RELOAD 0x10 +#define TIMER0_VAL 0x14 +#define TIMER1_RELOAD 0x18 +#define TIMER1_VAL 0x1c + +#define ORION_ONESHOT_MIN 1 +#define ORION_ONESHOT_MAX 0xfffffffe + +static void __iomem *timer_base; +static DEFINE_SPINLOCK(timer_ctrl_lock); + +/* + * Thread-safe access to TIMER_CTRL register + * (shared with watchdog timer) + */ +void orion_timer_ctrl_clrset(u32 clr, u32 set) +{ + spin_lock(&timer_ctrl_lock); + writel((readl(timer_base + TIMER_CTRL) & ~clr) | set, + timer_base + TIMER_CTRL); + spin_unlock(&timer_ctrl_lock); +} +EXPORT_SYMBOL(orion_timer_ctrl_clrset); + +/* + * Free-running clocksource handling. + */ +static u32 notrace orion_read_sched_clock(void) +{ + return ~readl(timer_base + TIMER0_VAL); +} + +/* + * Clockevent handling. + */ +static u32 ticks_per_jiffy; + +static int orion_clkevt_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + /* setup and enable one-shot timer */ + writel(delta, timer_base + TIMER1_VAL); + orion_timer_ctrl_clrset(TIMER1_RELOAD_EN, TIMER1_EN); + + return 0; +} + +static void orion_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *dev) +{ + if (mode == CLOCK_EVT_MODE_PERIODIC) { + /* setup and enable periodic timer at 1/HZ intervals */ + writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); + writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); + orion_timer_ctrl_clrset(0, TIMER1_RELOAD_EN | TIMER1_EN); + } else { + /* disable timer */ + orion_timer_ctrl_clrset(TIMER1_RELOAD_EN | TIMER1_EN, 0); + } +} + +static struct clock_event_device orion_clkevt = { + .name = "orion_event", + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, + .shift = 32, + .rating = 300, + .set_next_event = orion_clkevt_next_event, + .set_mode = orion_clkevt_mode, +}; + +static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) +{ + orion_clkevt.event_handler(&orion_clkevt); + return IRQ_HANDLED; +} + +static struct irqaction orion_clkevt_irq = { + .name = "orion_event", + .flags = IRQF_TIMER, + .handler = orion_clkevt_irq_handler, +}; + +static void __init orion_timer_init(struct device_node *np) +{ + struct clk *clk; + int irq; + + /* timer registers are shared with watchdog timer */ + timer_base = of_iomap(np, 0); + if (!timer_base) + panic("%s: unable to map resource\n", np->name); + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) + panic("%s: unable to get clk\n", np->name); + clk_prepare_enable(clk); + + /* we are only interested in timer1 irq */ + irq = irq_of_parse_and_map(np, 1); + if (irq <= 0) + panic("%s: unable to parse timer1 irq\n", np->name); + + /* setup timer0 as free-running clocksource */ + writel(~0, timer_base + TIMER0_VAL); + writel(~0, timer_base + TIMER0_RELOAD); + orion_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | TIMER0_EN); + clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource", + clk_get_rate(clk), 300, 32, + clocksource_mmio_readl_down); + setup_sched_clock(orion_read_sched_clock, 32, clk_get_rate(clk)); + + /* setup timer1 as clockevent timer */ + if (setup_irq(irq, &orion_clkevt_irq)) + panic("%s: unable to setup irq\n", np->name); + + ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ; + orion_clkevt.cpumask = cpumask_of(0); + orion_clkevt.irq = irq; + clockevents_config_and_register(&orion_clkevt, clk_get_rate(clk), + ORION_ONESHOT_MIN, ORION_ONESHOT_MAX); +} +CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init); -- GitLab From ff451961a8b2a17667a7bfa39c86fb9b351445db Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 1 Jul 2013 22:50:29 -0400 Subject: [PATCH 2194/2900] tracing: Add trace_array_get/put() to handle instance refs better Commit a695cb58162 "tracing: Prevent deleting instances when they are being read" tried to fix a race between deleting a trace instance and reading contents of a trace file. But it wasn't good enough. The following could crash the kernel: # cd /sys/kernel/debug/tracing/instances # ( while :; do mkdir foo; rmdir foo; done ) & # ( while :; do cat foo/trace &> /dev/null; done ) & Luckily this can only be done by root user, but it should be fixed regardless. The problem is that a delete of the file can happen after the reader starts to open the file but before it grabs the trace_types_mutex. The solution is to validate the trace array before using it. If the trace array does not exist in the list of trace arrays, then it returns -ENODEV. There's a possibility that a trace_array could be deleted and a new one created and the open would open its file instead. But that is very minor as it will just return the data of the new trace array, it may confuse the user but it will not crash the system. As this can only be done by root anyway, the race will only occur if root is deleting what its trying to read at the same time. Cc: stable@vger.kernel.org # 3.10 Reported-by: Alexander Lam Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 83 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e36da7ff59bf..6be9df1aa513 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -204,6 +204,37 @@ static struct trace_array global_trace; LIST_HEAD(ftrace_trace_arrays); +int trace_array_get(struct trace_array *this_tr) +{ + struct trace_array *tr; + int ret = -ENODEV; + + mutex_lock(&trace_types_lock); + list_for_each_entry(tr, &ftrace_trace_arrays, list) { + if (tr == this_tr) { + tr->ref++; + ret = 0; + break; + } + } + mutex_unlock(&trace_types_lock); + + return ret; +} + +static void __trace_array_put(struct trace_array *this_tr) +{ + WARN_ON(!this_tr->ref); + this_tr->ref--; +} + +void trace_array_put(struct trace_array *this_tr) +{ + mutex_lock(&trace_types_lock); + __trace_array_put(this_tr); + mutex_unlock(&trace_types_lock); +} + int filter_current_check_discard(struct ring_buffer *buffer, struct ftrace_event_call *call, void *rec, struct ring_buffer_event *event) @@ -2831,10 +2862,9 @@ static const struct seq_operations tracer_seq_ops = { }; static struct trace_iterator * -__tracing_open(struct inode *inode, struct file *file, bool snapshot) +__tracing_open(struct trace_array *tr, struct trace_cpu *tc, + struct inode *inode, struct file *file, bool snapshot) { - struct trace_cpu *tc = inode->i_private; - struct trace_array *tr = tc->tr; struct trace_iterator *iter; int cpu; @@ -2913,8 +2943,6 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot) tracing_iter_reset(iter, cpu); } - tr->ref++; - mutex_unlock(&trace_types_lock); return iter; @@ -2944,17 +2972,20 @@ static int tracing_release(struct inode *inode, struct file *file) struct trace_array *tr; int cpu; - if (!(file->f_mode & FMODE_READ)) + /* Writes do not use seq_file, need to grab tr from inode */ + if (!(file->f_mode & FMODE_READ)) { + struct trace_cpu *tc = inode->i_private; + + trace_array_put(tc->tr); return 0; + } iter = m->private; tr = iter->tr; + trace_array_put(tr); mutex_lock(&trace_types_lock); - WARN_ON(!tr->ref); - tr->ref--; - for_each_tracing_cpu(cpu) { if (iter->buffer_iter[cpu]) ring_buffer_read_finish(iter->buffer_iter[cpu]); @@ -2973,20 +3004,23 @@ static int tracing_release(struct inode *inode, struct file *file) kfree(iter->trace); kfree(iter->buffer_iter); seq_release_private(inode, file); + return 0; } static int tracing_open(struct inode *inode, struct file *file) { + struct trace_cpu *tc = inode->i_private; + struct trace_array *tr = tc->tr; struct trace_iterator *iter; int ret = 0; + if (trace_array_get(tr) < 0) + return -ENODEV; + /* If this file was open for write, then erase contents */ if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { - struct trace_cpu *tc = inode->i_private; - struct trace_array *tr = tc->tr; - if (tc->cpu == RING_BUFFER_ALL_CPUS) tracing_reset_online_cpus(&tr->trace_buffer); else @@ -2994,12 +3028,16 @@ static int tracing_open(struct inode *inode, struct file *file) } if (file->f_mode & FMODE_READ) { - iter = __tracing_open(inode, file, false); + iter = __tracing_open(tr, tc, inode, file, false); if (IS_ERR(iter)) ret = PTR_ERR(iter); else if (trace_flags & TRACE_ITER_LATENCY_FMT) iter->iter_flags |= TRACE_FILE_LAT_FMT; } + + if (ret < 0) + trace_array_put(tr); + return ret; } @@ -4575,12 +4613,16 @@ struct ftrace_buffer_info { static int tracing_snapshot_open(struct inode *inode, struct file *file) { struct trace_cpu *tc = inode->i_private; + struct trace_array *tr = tc->tr; struct trace_iterator *iter; struct seq_file *m; int ret = 0; + if (trace_array_get(tr) < 0) + return -ENODEV; + if (file->f_mode & FMODE_READ) { - iter = __tracing_open(inode, file, true); + iter = __tracing_open(tr, tc, inode, file, true); if (IS_ERR(iter)) ret = PTR_ERR(iter); } else { @@ -4593,13 +4635,16 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) kfree(m); return -ENOMEM; } - iter->tr = tc->tr; + iter->tr = tr; iter->trace_buffer = &tc->tr->max_buffer; iter->cpu_file = tc->cpu; m->private = iter; file->private_data = m; } + if (ret < 0) + trace_array_put(tr); + return ret; } @@ -4680,9 +4725,12 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, static int tracing_snapshot_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; + int ret; + + ret = tracing_release(inode, file); if (file->f_mode & FMODE_READ) - return tracing_release(inode, file); + return ret; /* If write only, the seq_file is just a stub */ if (m) @@ -4927,8 +4975,7 @@ static int tracing_buffers_release(struct inode *inode, struct file *file) mutex_lock(&trace_types_lock); - WARN_ON(!iter->tr->ref); - iter->tr->ref--; + __trace_array_put(iter->tr); if (info->spare) ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare); -- GitLab From 7aa2d05299f92ab73591988ab514f0ddc98138f3 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 2 Jul 2013 09:13:44 +0000 Subject: [PATCH 2195/2900] MIPS: BCM63xx: CLK: Add dummy clk_{set,round}_rate() functions Several drivers use the clk_{set,round}_rate() functions that need to be defined in the platform's clock code. The Broadcom BCM63xx platform hardcodes the clock rate so we create new clk_{set,round}_rate() functions which just return 0 like those in include/linux/clk.h for the common clock framework do. Also fixes the following build problem on a randconfig: drivers/built-in.o: In function `nop_usb_xceiv_probe': phy-nop.c:(.text+0x3ec26c): undefined reference to `clk_set_rate' Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Acked-by: Florian Fainelli Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5580/ Signed-off-by: Ralf Baechle --- arch/mips/bcm63xx/clk.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index fda2690a8ef1..43da4ae04cc2 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -318,6 +318,18 @@ unsigned long clk_get_rate(struct clk *clk) EXPORT_SYMBOL(clk_get_rate); +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} +EXPORT_SYMBOL_GPL(clk_round_rate); + struct clk *clk_get(struct device *dev, const char *id) { if (!strcmp(id, "enet0")) -- GitLab From 704e6460ab75af0735b1ca7c0dcaa4ff0a4001b2 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Fri, 28 Jun 2013 11:25:27 +0000 Subject: [PATCH 2196/2900] MIPS: Kconfig: Add missing MODULES dependency to VPE_LOADER The vpe.c code uses the 'struct module' which is only available if CONFIG_MODULES is selected. Also fixes the following build problem on a lantiq allmodconfig: In file included from arch/mips/kernel/vpe.c:41:0: include/linux/moduleloader.h: In function 'apply_relocate': include/linux/moduleloader.h:48:63: error: dereferencing pointer to incomplete type include/linux/moduleloader.h: In function 'apply_relocate_add': include/linux/moduleloader.h:70:63: error: dereferencing pointer to incomplete type Signed-off-by: Markos Chandras Reviewed-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5562/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 567c45b33651..1e7a40e00bc0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1929,7 +1929,7 @@ config MIPS_MT_FPAFF config MIPS_VPE_LOADER bool "VPE loader support." - depends on SYS_SUPPORTS_MULTITHREADING + depends on SYS_SUPPORTS_MULTITHREADING && MODULES select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI select MIPS_MT -- GitLab From 7b85af63034818e43aee6c1d7bf1c7c6796a9073 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Mon, 1 Jul 2013 23:34:22 -0400 Subject: [PATCH 2197/2900] tracing: Get trace_array ref counts when accessing trace files When a trace file is opened that may access a trace array, it must increment its ref count to prevent it from being deleted. Cc: stable@vger.kernel.org # 3.10 Reported-by: Alexander Lam Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 121 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 112 insertions(+), 9 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6be9df1aa513..6d9bd9b43e43 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2965,6 +2965,43 @@ int tracing_open_generic(struct inode *inode, struct file *filp) return 0; } +/* + * Open and update trace_array ref count. + * Must have the current trace_array passed to it. + */ +int tracing_open_generic_tr(struct inode *inode, struct file *filp) +{ + struct trace_array *tr = inode->i_private; + + if (tracing_disabled) + return -ENODEV; + + if (trace_array_get(tr) < 0) + return -ENODEV; + + filp->private_data = inode->i_private; + + return 0; + +} + +int tracing_open_generic_tc(struct inode *inode, struct file *filp) +{ + struct trace_cpu *tc = inode->i_private; + struct trace_array *tr = tc->tr; + + if (tracing_disabled) + return -ENODEV; + + if (trace_array_get(tr) < 0) + return -ENODEV; + + filp->private_data = inode->i_private; + + return 0; + +} + static int tracing_release(struct inode *inode, struct file *file) { struct seq_file *m = file->private_data; @@ -3008,6 +3045,32 @@ static int tracing_release(struct inode *inode, struct file *file) return 0; } +static int tracing_release_generic_tr(struct inode *inode, struct file *file) +{ + struct trace_array *tr = inode->i_private; + + trace_array_put(tr); + return 0; +} + +static int tracing_release_generic_tc(struct inode *inode, struct file *file) +{ + struct trace_cpu *tc = inode->i_private; + struct trace_array *tr = tc->tr; + + trace_array_put(tr); + return 0; +} + +static int tracing_single_release_tr(struct inode *inode, struct file *file) +{ + struct trace_array *tr = inode->i_private; + + trace_array_put(tr); + + return single_release(inode, file); +} + static int tracing_open(struct inode *inode, struct file *file) { struct trace_cpu *tc = inode->i_private; @@ -3394,9 +3457,14 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, static int tracing_trace_options_open(struct inode *inode, struct file *file) { + struct trace_array *tr = inode->i_private; + if (tracing_disabled) return -ENODEV; + if (trace_array_get(tr) < 0) + return -ENODEV; + return single_open(file, tracing_trace_options_show, inode->i_private); } @@ -3404,7 +3472,7 @@ static const struct file_operations tracing_iter_fops = { .open = tracing_trace_options_open, .read = seq_read, .llseek = seq_lseek, - .release = single_release, + .release = tracing_single_release_tr, .write = tracing_trace_options_write, }; @@ -3892,6 +3960,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) if (tracing_disabled) return -ENODEV; + if (trace_array_get(tr) < 0) + return -ENODEV; + mutex_lock(&trace_types_lock); /* create a buffer to store the information to pass to userspace */ @@ -3944,6 +4015,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) fail: kfree(iter->trace); kfree(iter); + __trace_array_put(tr); mutex_unlock(&trace_types_lock); return ret; } @@ -3951,6 +4023,8 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) static int tracing_release_pipe(struct inode *inode, struct file *file) { struct trace_iterator *iter = file->private_data; + struct trace_cpu *tc = inode->i_private; + struct trace_array *tr = tc->tr; mutex_lock(&trace_types_lock); @@ -3964,6 +4038,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) kfree(iter->trace); kfree(iter); + trace_array_put(tr); + return 0; } @@ -4421,6 +4497,8 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp) /* resize the ring buffer to 0 */ tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS); + trace_array_put(tr); + return 0; } @@ -4597,10 +4675,20 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, static int tracing_clock_open(struct inode *inode, struct file *file) { + struct trace_array *tr = inode->i_private; + int ret; + if (tracing_disabled) return -ENODEV; - return single_open(file, tracing_clock_show, inode->i_private); + if (trace_array_get(tr)) + return -ENODEV; + + ret = single_open(file, tracing_clock_show, inode->i_private); + if (ret < 0) + trace_array_put(tr); + + return ret; } struct ftrace_buffer_info { @@ -4796,34 +4884,38 @@ static const struct file_operations tracing_pipe_fops = { }; static const struct file_operations tracing_entries_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_tc, .read = tracing_entries_read, .write = tracing_entries_write, .llseek = generic_file_llseek, + .release = tracing_release_generic_tc, }; static const struct file_operations tracing_total_entries_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_tr, .read = tracing_total_entries_read, .llseek = generic_file_llseek, + .release = tracing_release_generic_tr, }; static const struct file_operations tracing_free_buffer_fops = { + .open = tracing_open_generic_tr, .write = tracing_free_buffer_write, .release = tracing_free_buffer_release, }; static const struct file_operations tracing_mark_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_tr, .write = tracing_mark_write, .llseek = generic_file_llseek, + .release = tracing_release_generic_tr, }; static const struct file_operations trace_clock_fops = { .open = tracing_clock_open, .read = seq_read, .llseek = seq_lseek, - .release = single_release, + .release = tracing_single_release_tr, .write = tracing_clock_write, }; @@ -4851,13 +4943,19 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) struct trace_cpu *tc = inode->i_private; struct trace_array *tr = tc->tr; struct ftrace_buffer_info *info; + int ret; if (tracing_disabled) return -ENODEV; + if (trace_array_get(tr) < 0) + return -ENODEV; + info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + if (!info) { + trace_array_put(tr); return -ENOMEM; + } mutex_lock(&trace_types_lock); @@ -4875,7 +4973,11 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) mutex_unlock(&trace_types_lock); - return nonseekable_open(inode, filp); + ret = nonseekable_open(inode, filp); + if (ret < 0) + trace_array_put(tr); + + return ret; } static unsigned int @@ -5765,9 +5867,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf, } static const struct file_operations rb_simple_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_tr, .read = rb_simple_read, .write = rb_simple_write, + .release = tracing_release_generic_tr, .llseek = default_llseek, }; -- GitLab From d96760f98e8eb9d35a2eace586d8b93b0e58cbd5 Mon Sep 17 00:00:00 2001 From: Girish K S Date: Thu, 27 Jun 2013 12:26:53 +0530 Subject: [PATCH 2198/2900] spi: s3c64xx: add missing check for polling mode After the patch "spi/s3c64xx: Fix non-dmaengine usage" with commit id 563b444e33810f3120838620c990480304e24e63 submitted by Mark Brown, the spi device detection in polling mode breaks. This revealed the missing check for polling during dma prepare. This patch adds the missing check. Signed-off-by: Girish K S Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index eb53df27e7ea..63e2070c6c14 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -434,6 +434,9 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) dma_cap_mask_t mask; int ret; + if (is_polling(sdd)) + return 0; + dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); -- GitLab From 7cc47d139f9a815a91bd9e7377063238c69a0423 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 30 Jun 2013 14:37:11 +1000 Subject: [PATCH 2199/2900] cxgb3: Missing rtnl lock in error recovery When exercising error injection on IBM pseries machine, I hit the following warning: [ 251.450043] RTAS: event: 89, Type: Platform Error, Severity: 2 [ 253.549822] cxgb3 0006:01:00.0: enabling device (0140 -> 0142) [ 253.713560] cxgb3 0006:01:00.0: adapter recovering, PEX ERR 0x100 [ 254.895437] RTNL: assertion failed at net/core/dev.c (2031) [ 254.895467] CPU: 6 PID: 5449 Comm: eehd Tainted: G W 3.10.0-rc7-00157-gea461ab #19 [ 254.895474] Call Trace: [ 254.895483] [c000000fac56f7d0] [c000000000014dcc] .show_stack+0x7c/0x1f0 (unreliable) [ 254.895493] [c000000fac56f8a0] [c0000000007ba318] .dump_stack+0x28/0x3c [ 254.895500] [c000000fac56f910] [c0000000006c0384] .netif_set_real_num_tx_queues+0x224/0x230 [ 254.895515] [c000000fac56f9b0] [d00000000ef35510] .cxgb_open+0x80/0x3f0 [cxgb3] [ 254.895525] [c000000fac56fa50] [d00000000ef35914] .t3_resume_ports+0x94/0x100 [cxgb3] [ 254.895533] [c000000fac56fae0] [c00000000005fc8c] .eeh_report_resume+0x8c/0xd0 [ 254.895539] [c000000fac56fb60] [c00000000005e9fc] .eeh_pe_dev_traverse+0x9c/0x190 [ 254.895545] [c000000fac56fc10] [c000000000060000] .eeh_handle_event+0x110/0x330 [ 254.895551] [c000000fac56fca0] [c000000000060350] .eeh_event_handler+0x130/0x1a0 [ 254.895558] [c000000fac56fd30] [c0000000000ad758] .kthread+0xe8/0xf0 [ 254.895566] [c000000fac56fe30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x80 It appears that t3_resume_ports() is called with the rtnl_lock held from the fatal error task but not from the PCI error callbacks. This fixes it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 71497e835f42..b650951791dd 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -3037,7 +3037,9 @@ static void t3_io_resume(struct pci_dev *pdev) CH_ALERT(adapter, "adapter recovering, PEX ERR 0x%x\n", t3_read_reg(adapter, A_PCIE_PEX_ERR)); + rtnl_lock(); t3_resume_ports(adapter); + rtnl_unlock(); } static const struct pci_error_handlers t3_err_handler = { -- GitLab From b9eef55c2ab33053ae236b5d383965f9ee6a0094 Mon Sep 17 00:00:00 2001 From: Jim Baxter Date: Mon, 1 Jul 2013 14:57:54 +0100 Subject: [PATCH 2200/2900] net: fec: Fix RMON registers on imx6 commit 38ae92d "fec: Add support for reading RMON registers" causes the imx6Q to crash. This fixes it by only enabling the RMON registers, the registers are already cleared by the MAC being reset. Signed-off-by: Jim Baxter Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index aff8a5cd17c7..b6768821757b 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -606,11 +606,8 @@ fec_restart(struct net_device *ndev, int duplex) ecntl |= (1 << 4); #ifndef CONFIG_M5272 - /* Disable, clear, and enable the MIB */ - writel(1 << 31, fep->hwp + FEC_MIB_CTRLSTAT); - for (i = RMON_T_DROP; i < IEEE_R_OCTETS_OK; i++) - writel(0, fep->hwp + i); - writel(0, fep->hwp + FEC_MIB_CTRLSTAT); + /* Enable the MIB statistic event counters */ + writel(0 << 31, fep->hwp + FEC_MIB_CTRLSTAT); #endif /* And last, enable the transmit and receive processing */ -- GitLab From 8822b64a0fa64a5dd1dfcf837c5b0be83f8c05d1 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 1 Jul 2013 20:21:30 +0200 Subject: [PATCH 2201/2900] ipv6: call udp_push_pending_frames when uncorking a socket with AF_INET pending data We accidentally call down to ip6_push_pending_frames when uncorking pending AF_INET data on a ipv6 socket. This results in the following splat (from Dave Jones): skbuff: skb_under_panic: text:ffffffff816765f6 len:48 put:40 head:ffff88013deb6df0 data:ffff88013deb6dec tail:0x2c end:0xc0 dev: ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:126! invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: dccp_ipv4 dccp 8021q garp bridge stp dlci mpoa snd_seq_dummy sctp fuse hidp tun bnep nfnetlink scsi_transport_iscsi rfcomm can_raw can_bcm af_802154 appletalk caif_socket can caif ipt_ULOG x25 rose af_key pppoe pppox ipx phonet irda llc2 ppp_generic slhc p8023 psnap p8022 llc crc_ccitt atm bluetooth +netrom ax25 nfc rfkill rds af_rxrpc coretemp hwmon kvm_intel kvm crc32c_intel snd_hda_codec_realtek ghash_clmulni_intel microcode pcspkr snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep usb_debug snd_seq snd_seq_device snd_pcm e1000e snd_page_alloc snd_timer ptp snd pps_core soundcore xfs libcrc32c CPU: 2 PID: 8095 Comm: trinity-child2 Not tainted 3.10.0-rc7+ #37 task: ffff8801f52c2520 ti: ffff8801e6430000 task.ti: ffff8801e6430000 RIP: 0010:[] [] skb_panic+0x63/0x65 RSP: 0018:ffff8801e6431de8 EFLAGS: 00010282 RAX: 0000000000000086 RBX: ffff8802353d3cc0 RCX: 0000000000000006 RDX: 0000000000003b90 RSI: ffff8801f52c2ca0 RDI: ffff8801f52c2520 RBP: ffff8801e6431e08 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000001 R12: ffff88022ea0c800 R13: ffff88022ea0cdf8 R14: ffff8802353ecb40 R15: ffffffff81cc7800 FS: 00007f5720a10740(0000) GS:ffff880244c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000005862000 CR3: 000000022843c000 CR4: 00000000001407e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000600 Stack: ffff88013deb6dec 000000000000002c 00000000000000c0 ffffffff81a3f6e4 ffff8801e6431e18 ffffffff8159a9aa ffff8801e6431e90 ffffffff816765f6 ffffffff810b756b 0000000700000002 ffff8801e6431e40 0000fea9292aa8c0 Call Trace: [] skb_push+0x3a/0x40 [] ip6_push_pending_frames+0x1f6/0x4d0 [] ? mark_held_locks+0xbb/0x140 [] udp_v6_push_pending_frames+0x2b9/0x3d0 [] ? udplite_getfrag+0x20/0x20 [] udp_lib_setsockopt+0x1aa/0x1f0 [] ? fget_light+0x387/0x4f0 [] udpv6_setsockopt+0x34/0x40 [] sock_common_setsockopt+0x14/0x20 [] SyS_setsockopt+0x71/0xd0 [] tracesys+0xdd/0xe2 Code: 00 00 48 89 44 24 10 8b 87 d8 00 00 00 48 89 44 24 08 48 8b 87 e8 00 00 00 48 c7 c7 c0 04 aa 81 48 89 04 24 31 c0 e8 e1 7e ff ff <0f> 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 48 89 e5 0f 0b 55 RIP [] skb_panic+0x63/0x65 RSP This patch adds a check if the pending data is of address family AF_INET and directly calls udp_push_ending_frames from udp_v6_push_pending_frames if that is the case. This bug was found by Dave Jones with trinity. (Also move the initialization of fl6 below the AF_INET check, even if not strictly necessary.) Cc: Dave Jones Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/net/udp.h | 1 + net/ipv4/udp.c | 3 ++- net/ipv6/udp.c | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/net/udp.h b/include/net/udp.h index b30a71a51839..74c10ec5e74f 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum, extern void udp_err(struct sk_buff *, u32); extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len); +extern int udp_push_pending_frames(struct sock *sk); extern void udp_flush_pending_frames(struct sock *sk); extern int udp_rcv(struct sk_buff *skb); extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 959502afd8d9..6b270e53c207 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -800,7 +800,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) /* * Push out all pending data as one UDP datagram. Socket is locked. */ -static int udp_push_pending_frames(struct sock *sk) +int udp_push_pending_frames(struct sock *sk) { struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); @@ -819,6 +819,7 @@ static int udp_push_pending_frames(struct sock *sk) up->pending = 0; return err; } +EXPORT_SYMBOL(udp_push_pending_frames); int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index f77e34c5a0e2..b6f31437a1f8 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -959,11 +959,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) struct udphdr *uh; struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); - struct flowi6 *fl6 = &inet->cork.fl.u.ip6; + struct flowi6 *fl6; int err = 0; int is_udplite = IS_UDPLITE(sk); __wsum csum = 0; + if (up->pending == AF_INET) + return udp_push_pending_frames(sk); + + fl6 = &inet->cork.fl.u.ip6; + /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) goto out; -- GitLab From 75a493e60ac4bbe2e977e7129d6d8cbb0dd236be Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Tue, 2 Jul 2013 08:04:05 +0200 Subject: [PATCH 2202/2900] ipv6: ip6_append_data_mtu did not care about pmtudisc and frag_size If the socket had an IPV6_MTU value set, ip6_append_data_mtu lost track of this when appending the second frame on a corked socket. This results in the following splat: [37598.993962] ------------[ cut here ]------------ [37598.994008] kernel BUG at net/core/skbuff.c:2064! [37598.994008] invalid opcode: 0000 [#1] SMP [37598.994008] Modules linked in: tcp_lp uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core videodev media vfat fat usb_storage fuse ebtable_nat xt_CHECKSUM bridge stp llc ipt_MASQUERADE nf_conntrack_netbios_ns nf_conntrack_broadcast ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat +nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i cxgb3 mdio libcxgbi ib_iser rdma_cm ib_addr iw_cm ib_cm ib_sa ib_mad ib_core iscsi_tcp libiscsi_tcp libiscsi +scsi_transport_iscsi rfcomm bnep iTCO_wdt iTCO_vendor_support snd_hda_codec_conexant arc4 iwldvm mac80211 snd_hda_intel acpi_cpufreq mperf coretemp snd_hda_codec microcode cdc_wdm cdc_acm [37598.994008] snd_hwdep cdc_ether snd_seq snd_seq_device usbnet mii joydev btusb snd_pcm bluetooth i2c_i801 e1000e lpc_ich mfd_core ptp iwlwifi pps_core snd_page_alloc mei cfg80211 snd_timer thinkpad_acpi snd tpm_tis soundcore rfkill tpm tpm_bios vhost_net tun macvtap macvlan kvm_intel kvm uinput binfmt_misc +dm_crypt i915 i2c_algo_bit drm_kms_helper drm i2c_core wmi video [37598.994008] CPU 0 [37598.994008] Pid: 27320, comm: t2 Not tainted 3.9.6-200.fc18.x86_64 #1 LENOVO 27744PG/27744PG [37598.994008] RIP: 0010:[] [] skb_copy_and_csum_bits+0x325/0x330 [37598.994008] RSP: 0018:ffff88003670da18 EFLAGS: 00010202 [37598.994008] RAX: ffff88018105c018 RBX: 0000000000000004 RCX: 00000000000006c0 [37598.994008] RDX: ffff88018105a6c0 RSI: ffff88018105a000 RDI: ffff8801e1b0aa00 [37598.994008] RBP: ffff88003670da78 R08: 0000000000000000 R09: ffff88018105c040 [37598.994008] R10: ffff8801e1b0aa00 R11: 0000000000000000 R12: 000000000000fff8 [37598.994008] R13: 00000000000004fc R14: 00000000ffff0504 R15: 0000000000000000 [37598.994008] FS: 00007f28eea59740(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000 [37598.994008] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [37598.994008] CR2: 0000003d935789e0 CR3: 00000000365cb000 CR4: 00000000000407f0 [37598.994008] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [37598.994008] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [37598.994008] Process t2 (pid: 27320, threadinfo ffff88003670c000, task ffff88022c162ee0) [37598.994008] Stack: [37598.994008] ffff88022e098a00 ffff88020f973fc0 0000000000000008 00000000000004c8 [37598.994008] ffff88020f973fc0 00000000000004c4 ffff88003670da78 ffff8801e1b0a200 [37598.994008] 0000000000000018 00000000000004c8 ffff88020f973fc0 00000000000004c4 [37598.994008] Call Trace: [37598.994008] [] ip6_append_data+0xccf/0xfe0 [37598.994008] [] ? ip_copy_metadata+0x1a0/0x1a0 [37598.994008] [] ? _raw_spin_lock_bh+0x16/0x40 [37598.994008] [] udpv6_sendmsg+0x1ed/0xc10 [37598.994008] [] ? sock_has_perm+0x75/0x90 [37598.994008] [] inet_sendmsg+0x63/0xb0 [37598.994008] [] ? selinux_socket_sendmsg+0x23/0x30 [37598.994008] [] sock_sendmsg+0xb0/0xe0 [37598.994008] [] ? __switch_to+0x181/0x4a0 [37598.994008] [] sys_sendto+0x12d/0x180 [37598.994008] [] ? __audit_syscall_entry+0x94/0xf0 [37598.994008] [] ? syscall_trace_enter+0x231/0x240 [37598.994008] [] tracesys+0xdd/0xe2 [37598.994008] Code: fe 07 00 00 48 c7 c7 04 28 a6 81 89 45 a0 4c 89 4d b8 44 89 5d a8 e8 1b ac b1 ff 44 8b 5d a8 4c 8b 4d b8 8b 45 a0 e9 cf fe ff ff <0f> 0b 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 48 [37598.994008] RIP [] skb_copy_and_csum_bits+0x325/0x330 [37598.994008] RSP [37599.007323] ---[ end trace d69f6a17f8ac8eee ]--- While there, also check if path mtu discovery is activated for this socket. The logic was adapted from ip6_append_data when first writing on the corked socket. This bug was introduced with commit 0c1833797a5a6ec23ea9261d979aa18078720b74 ("ipv6: fix incorrect ipsec fragment"). v2: a) Replace IPV6_PMTU_DISC_DO with IPV6_PMTUDISC_PROBE. b) Don't pass ipv6_pinfo to ip6_append_data_mtu (suggestion by Gao feng, thanks!). c) Change mtu to unsigned int, else we get a warning about non-matching types because of the min()-macro type-check. Acked-by: Gao feng Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index dae1949019d7..be7589ef5cf9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1093,11 +1093,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; } -static void ip6_append_data_mtu(int *mtu, +static void ip6_append_data_mtu(unsigned int *mtu, int *maxfraglen, unsigned int fragheaderlen, struct sk_buff *skb, - struct rt6_info *rt) + struct rt6_info *rt, + bool pmtuprobe) { if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { if (skb == NULL) { @@ -1109,7 +1110,9 @@ static void ip6_append_data_mtu(int *mtu, * this fragment is not first, the headers * space is regarded as data space. */ - *mtu = dst_mtu(rt->dst.path); + *mtu = min(*mtu, pmtuprobe ? + rt->dst.dev->mtu : + dst_mtu(rt->dst.path)); } *maxfraglen = ((*mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); @@ -1126,11 +1129,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, struct ipv6_pinfo *np = inet6_sk(sk); struct inet_cork *cork; struct sk_buff *skb, *skb_prev = NULL; - unsigned int maxfraglen, fragheaderlen; + unsigned int maxfraglen, fragheaderlen, mtu; int exthdrlen; int dst_exthdrlen; int hh_len; - int mtu; int copy; int err; int offset = 0; @@ -1287,7 +1289,9 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, /* update mtu and maxfraglen if necessary */ if (skb == NULL || skb_prev == NULL) ip6_append_data_mtu(&mtu, &maxfraglen, - fragheaderlen, skb, rt); + fragheaderlen, skb, rt, + np->pmtudisc == + IPV6_PMTUDISC_PROBE); skb_prev = skb; -- GitLab From 7e6d4da837385d9aa2e5fd84e0a6042cddc9e708 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 2 Jul 2013 10:55:31 +0200 Subject: [PATCH 2203/2900] nlmon: use standard rtnetlink link api for add/del devices It is not nice when netdev is created right after module load and with some implicit name. So rather change nlmon to use standard rtnl link API. Signed-off-by: Jiri Pirko Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/nlmon.c | 49 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c index a0baf56f5826..b57ce5f48962 100644 --- a/drivers/net/nlmon.c +++ b/drivers/net/nlmon.c @@ -4,6 +4,7 @@ #include #include #include +#include struct pcpu_lstats { u64 packets; @@ -56,16 +57,24 @@ static void nlmon_dev_uninit(struct net_device *dev) free_percpu(dev->lstats); } -static struct netlink_tap nlmon_tap; +struct nlmon { + struct netlink_tap nt; +}; static int nlmon_open(struct net_device *dev) { - return netlink_add_tap(&nlmon_tap); + struct nlmon *nlmon = netdev_priv(dev); + + nlmon->nt.dev = dev; + nlmon->nt.module = THIS_MODULE; + return netlink_add_tap(&nlmon->nt); } static int nlmon_close(struct net_device *dev) { - return netlink_remove_tap(&nlmon_tap); + struct nlmon *nlmon = netdev_priv(dev); + + return netlink_remove_tap(&nlmon->nt); } static struct rtnl_link_stats64 * @@ -119,10 +128,6 @@ static const struct net_device_ops nlmon_ops = { .ndo_change_mtu = nlmon_change_mtu, }; -static struct netlink_tap nlmon_tap __read_mostly = { - .module = THIS_MODULE, -}; - static void nlmon_setup(struct net_device *dev) { dev->type = ARPHRD_NETLINK; @@ -142,27 +147,28 @@ static void nlmon_setup(struct net_device *dev) dev->mtu = NLMSG_GOODSIZE; } -static __init int nlmon_register(void) +static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[]) { - int err; - struct net_device *nldev; - - nldev = nlmon_tap.dev = alloc_netdev(0, "netlink", nlmon_setup); - if (unlikely(nldev == NULL)) - return -ENOMEM; + if (tb[IFLA_ADDRESS]) + return -EINVAL; + return 0; +} - err = register_netdev(nldev); - if (unlikely(err)) - free_netdev(nldev); +static struct rtnl_link_ops nlmon_link_ops __read_mostly = { + .kind = "nlmon", + .priv_size = sizeof(struct nlmon), + .setup = nlmon_setup, + .validate = nlmon_validate, +}; - return err; +static __init int nlmon_register(void) +{ + return rtnl_link_register(&nlmon_link_ops); } static __exit void nlmon_unregister(void) { - struct net_device *nldev = nlmon_tap.dev; - - unregister_netdev(nldev); + rtnl_link_unregister(&nlmon_link_ops); } module_init(nlmon_register); @@ -172,3 +178,4 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Daniel Borkmann "); MODULE_AUTHOR("Mathieu Geli "); MODULE_DESCRIPTION("Netlink monitoring device"); +MODULE_ALIAS_RTNL_LINK("nlmon"); -- GitLab From 1c297a66654a3295ae87e2b7f3724d214eb2b5ec Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 1 Jul 2013 15:20:00 +0100 Subject: [PATCH 2204/2900] iio: Fix iio_channel_has_info Since the info_mask split, iio_channel_has_info() is not working correctly. info_mask_separate and info_mask_shared_by_type, it is not possible to compare them directly with the iio_chan_info_enum enum. Correct that bit using the BIT() macro. Cc: # 3.10.x Signed-off-by: Alexandre Belloni Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 8d171f427632..3d35b7023591 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -211,8 +211,8 @@ struct iio_chan_spec { static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, enum iio_chan_info_enum type) { - return (chan->info_mask_separate & type) | - (chan->info_mask_shared_by_type & type); + return (chan->info_mask_separate & BIT(type)) | + (chan->info_mask_shared_by_type & BIT(type)); } #define IIO_ST(si, rb, sb, sh) \ -- GitLab From 8e2e2fa47129532a30cff6c25a47078dc97d9260 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 2 Jul 2013 15:30:53 -0400 Subject: [PATCH 2205/2900] tracing: Add trace_array_get/put() to event handling Commit a695cb58162 "tracing: Prevent deleting instances when they are being read" tried to fix a race between deleting a trace instance and reading contents of a trace file. But it wasn't good enough. The following could crash the kernel: # cd /sys/kernel/debug/tracing/instances # ( while :; do mkdir foo; rmdir foo; done ) & # ( while :; do echo 1 > foo/events/sched/sched_switch 2> /dev/null; done ) & Luckily this can only be done by root user, but it should be fixed regardless. The problem is that a delete of the file can happen after the write to the event is opened, but before the enabling happens. The solution is to make sure the trace_array is available before succeeding in opening for write, and incerment the ref counter while opened. Now the instance can be deleted when the events are writing to the buffer, but the deletion of the instance will disable all events before the instance is actually deleted. Cc: stable@vger.kernel.org # 3.10 Reported-by: Alexander Lam Signed-off-by: Steven Rostedt --- kernel/trace/trace.h | 3 ++ kernel/trace/trace_events.c | 55 ++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2c3cba59552d..c7fbf93f1b7c 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -226,6 +226,9 @@ extern struct list_head ftrace_trace_arrays; extern struct mutex trace_types_lock; +extern int trace_array_get(struct trace_array *tr); +extern void trace_array_put(struct trace_array *tr); + /* * The global tracer (top) should be the first trace array added, * but we check the flag anyway. diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 35c6f23c71b2..920e08fb53b3 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -409,6 +409,35 @@ static void put_system(struct ftrace_subsystem_dir *dir) mutex_unlock(&event_mutex); } +/* + * Open and update trace_array ref count. + * Must have the current trace_array passed to it. + */ +static int tracing_open_generic_file(struct inode *inode, struct file *filp) +{ + struct ftrace_event_file *file = inode->i_private; + struct trace_array *tr = file->tr; + int ret; + + if (trace_array_get(tr) < 0) + return -ENODEV; + + ret = tracing_open_generic(inode, filp); + if (ret < 0) + trace_array_put(tr); + return ret; +} + +static int tracing_release_generic_file(struct inode *inode, struct file *filp) +{ + struct ftrace_event_file *file = inode->i_private; + struct trace_array *tr = file->tr; + + trace_array_put(tr); + + return 0; +} + /* * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. */ @@ -1032,9 +1061,17 @@ static int subsystem_open(struct inode *inode, struct file *filp) /* Some versions of gcc think dir can be uninitialized here */ WARN_ON(!dir); + /* Still need to increment the ref count of the system */ + if (trace_array_get(tr) < 0) { + put_system(dir); + return -ENODEV; + } + ret = tracing_open_generic(inode, filp); - if (ret < 0) + if (ret < 0) { + trace_array_put(tr); put_system(dir); + } return ret; } @@ -1045,16 +1082,23 @@ static int system_tr_open(struct inode *inode, struct file *filp) struct trace_array *tr = inode->i_private; int ret; + if (trace_array_get(tr) < 0) + return -ENODEV; + /* Make a temporary dir that has no system but points to tr */ dir = kzalloc(sizeof(*dir), GFP_KERNEL); - if (!dir) + if (!dir) { + trace_array_put(tr); return -ENOMEM; + } dir->tr = tr; ret = tracing_open_generic(inode, filp); - if (ret < 0) + if (ret < 0) { + trace_array_put(tr); kfree(dir); + } filp->private_data = dir; @@ -1065,6 +1109,8 @@ static int subsystem_release(struct inode *inode, struct file *file) { struct ftrace_subsystem_dir *dir = file->private_data; + trace_array_put(dir->tr); + /* * If dir->subsystem is NULL, then this is a temporary * descriptor that was made for a trace_array to enable @@ -1192,9 +1238,10 @@ static const struct file_operations ftrace_set_event_fops = { }; static const struct file_operations ftrace_enable_fops = { - .open = tracing_open_generic, + .open = tracing_open_generic_file, .read = event_enable_read, .write = event_enable_write, + .release = tracing_release_generic_file, .llseek = default_llseek, }; -- GitLab From 1bc2774d866444c5b316fd1dc2b782f20c762cf4 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Tue, 2 Jul 2013 23:22:47 +0300 Subject: [PATCH 2206/2900] net: convert lls to use time_in_range() Time in range will fail safely if we move to a different cpu with an extremely large clock skew. Add time_in_range64() and convert lls to use it. changelog: v2 - fixed double call to sched_clock in can_poll_ll - fixed checkpatchisms Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- fs/select.c | 10 ++++++---- include/linux/jiffies.h | 4 ++++ include/net/ll_poll.h | 26 +++++++++++++++++--------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/fs/select.c b/fs/select.c index 36540754bad7..f28a58592725 100644 --- a/fs/select.c +++ b/fs/select.c @@ -403,7 +403,8 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) int retval, i, timed_out = 0; unsigned long slack = 0; unsigned int ll_flag = ll_get_flag(); - u64 ll_time = ll_end_time(); + u64 ll_start = ll_start_time(ll_flag); + u64 ll_time = ll_run_time(); rcu_read_lock(); retval = max_select_fd(n, fds); @@ -498,7 +499,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) } /* only if on, have sockets with POLL_LL and not out of time */ - if (ll_flag && can_ll && can_poll_ll(ll_time)) + if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time)) continue; /* @@ -770,7 +771,8 @@ static int do_poll(unsigned int nfds, struct poll_list *list, int timed_out = 0, count = 0; unsigned long slack = 0; unsigned int ll_flag = ll_get_flag(); - u64 ll_time = ll_end_time(); + u64 ll_start = ll_start_time(ll_flag); + u64 ll_time = ll_run_time(); /* Optimise the no-wait case */ if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { @@ -819,7 +821,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, break; /* only if on, have sockets with POLL_LL and not out of time */ - if (ll_flag && can_ll && can_poll_ll(ll_time)) + if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time)) continue; /* diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 8fb8edf12417..97ba4e78a37e 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -139,6 +139,10 @@ static inline u64 get_jiffies_64(void) ((__s64)(a) - (__s64)(b) >= 0)) #define time_before_eq64(a,b) time_after_eq64(b,a) +#define time_in_range64(a, b, c) \ + (time_after_eq64(a, b) && \ + time_before_eq64(a, c)) + /* * These four macros compare jiffies and 'a' for convenience. */ diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 6c06f7c0a22d..b76f004f18a9 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -67,19 +67,23 @@ static inline u64 ll_sched_clock(void) /* we don't mind a ~2.5% imprecision so <<10 instead of *1000 * sk->sk_ll_usec is a u_int so this can't overflow */ -static inline u64 ll_sk_end_time(struct sock *sk) +static inline u64 ll_sk_run_time(struct sock *sk) { - return ((u64)ACCESS_ONCE(sk->sk_ll_usec) << 10) + ll_sched_clock(); + return (u64)ACCESS_ONCE(sk->sk_ll_usec) << 10; } /* in poll/select we use the global sysctl_net_ll_poll value * only call sched_clock() if enabled */ -static inline u64 ll_end_time(void) +static inline u64 ll_run_time(void) { - u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll); + return (u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10; +} - return end_time ? (end_time << 10) + ll_sched_clock() : 0; +/* if flag is not set we don't need to know the time */ +static inline u64 ll_start_time(unsigned int flag) +{ + return flag ? ll_sched_clock() : 0; } static inline bool sk_valid_ll(struct sock *sk) @@ -88,9 +92,12 @@ static inline bool sk_valid_ll(struct sock *sk) !need_resched() && !signal_pending(current); } -static inline bool can_poll_ll(u64 end_time) +/* careful! time_in_range64 will evaluate now twice */ +static inline bool can_poll_ll(u64 start_time, u64 run_time) { - return !time_after64(ll_sched_clock(), end_time); + u64 now = ll_sched_clock(); + + return time_in_range64(now, start_time, start_time + run_time); } /* when used in sock_poll() nonblock is known at compile time to be true @@ -98,7 +105,8 @@ static inline bool can_poll_ll(u64 end_time) */ static inline bool sk_poll_ll(struct sock *sk, int nonblock) { - u64 end_time = nonblock ? 0 : ll_sk_end_time(sk); + u64 start_time = ll_start_time(!nonblock); + u64 run_time = ll_sk_run_time(sk); const struct net_device_ops *ops; struct napi_struct *napi; int rc = false; @@ -129,7 +137,7 @@ static inline bool sk_poll_ll(struct sock *sk, int nonblock) LINUX_MIB_LOWLATENCYRXPACKETS, rc); } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && - can_poll_ll(end_time)); + can_poll_ll(start_time, run_time)); rc = !skb_queue_empty(&sk->sk_receive_queue); out: -- GitLab From 06a23fe31ca3992863721f21bdb0307af93da807 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 2 Jul 2013 20:30:10 +0900 Subject: [PATCH 2207/2900] core/dev: set pkt_type after eth_type_trans() in dev_forward_skb() The dev_forward_skb() assignment of pkt_type should be done after the call to eth_type_trans(). ip-encapsulated packets can be handled by localhost. But skb->pkt_type can be PACKET_OTHERHOST when packet comes via veth into ip tunnel device. In that case, the packet is dropped by ip_rcv(). Although this example uses gretap. l2tp-eth also has same issue. For l2tp-eth case, add dummy device for ip address and ip l2tp command. netns A | root netns | netns B veth<->veth=bridge=gretap <-loop back-> gretap=bridge=veth<->veth arp packet -> pkt_type BROADCAST------------>ip_rcv()------------------------> <- arp reply pkt_type ip_rcv()<-----------------OTHERHOST drop sample operations ip link add tapa type gretap remote 172.17.107.4 local 172.17.107.3 ip link add tapb type gretap remote 172.17.107.3 local 172.17.107.4 ip link set tapa up ip link set tapb up ip address add 172.17.107.3 dev tapa ip address add 172.17.107.4 dev tapb ip route get 172.17.107.3 > local 172.17.107.3 dev lo src 172.17.107.3 > cache ip route get 172.17.107.4 > local 172.17.107.4 dev lo src 172.17.107.4 > cache ip link add vetha type veth peer name vetha-peer ip link add vethb type veth peer name vethb-peer brctl addbr bra brctl addbr brb brctl addif bra tapa brctl addif bra vetha-peer brctl addif brb tapb brctl addif brb vethb-peer brctl show > bridge name bridge id STP enabled interfaces > bra 8000.6ea21e758ff1 no tapa > vetha-peer > brb 8000.420020eb92d5 no tapb > vethb-peer ip link set vetha-peer up ip link set vethb-peer up ip link set bra up ip link set brb up ip netns add a ip netns add b ip link set vetha netns a ip link set vethb netns b ip netns exec a ip address add 10.0.0.3/24 dev vetha ip netns exec b ip address add 10.0.0.4/24 dev vethb ip netns exec a ip link set vetha up ip netns exec b ip link set vethb up ip netns exec a arping -I vetha 10.0.0.4 ARPING 10.0.0.4 from 10.0.0.3 vetha ^CSent 2 probes (2 broadcast(s)) Received 0 response(s) Cc: Jason Wang Cc: "Michael S. Tsirkin" Cc: Eric Dumazet Cc: Patrick McHardy Cc: Hong Zhiguo Cc: Rami Rosen Cc: Tom Parkin Cc: Cong Wang Cc: Pravin B Shelar Cc: Jesse Gross Cc: dev@openvswitch.org Signed-off-by: Isaku Yamahata Signed-off-by: David S. Miller --- net/core/dev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 370354a9c5f6..6a93cd8cd264 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1659,6 +1659,12 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) } skb_scrub_packet(skb); skb->protocol = eth_type_trans(skb, dev); + + /* eth_type_trans() can set pkt_type. + * clear pkt_type _after_ calling eth_type_trans() + */ + skb->pkt_type = PACKET_HOST; + return netif_rx(skb); } EXPORT_SYMBOL_GPL(dev_forward_skb); -- GitLab From 83d7af64ac9eaf4f4db7228677bc25f23c383790 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Tue, 2 Jul 2013 14:12:36 +0200 Subject: [PATCH 2208/2900] stmmac: dity-up and rework the driver debug levels Prior this patch, the internal debugging was based on ifdef and also some printk were useless because many info are exposed via ethtool. This patch remove all the ifdef defines and now we only use netif_msg_XXX levels. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/common.h | 10 -- .../ethernet/stmicro/stmmac/dwmac1000_core.c | 57 +++----- .../ethernet/stmicro/stmmac/dwmac1000_dma.c | 10 +- .../ethernet/stmicro/stmmac/dwmac100_core.c | 4 - .../ethernet/stmicro/stmmac/dwmac100_dma.c | 8 +- .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 72 ++++------ .../net/ethernet/stmicro/stmmac/enh_desc.c | 95 ++++---------- .../net/ethernet/stmicro/stmmac/norm_desc.c | 4 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 124 ++++++------------ 9 files changed, 117 insertions(+), 267 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 7788fbe44f0a..9911b9323f00 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -38,16 +38,6 @@ #include "descs.h" #include "mmc.h" -#undef CHIP_DEBUG_PRINT -/* Turn-on extra printk debug for MAC core, dma and descriptors */ -/* #define CHIP_DEBUG_PRINT */ - -#ifdef CHIP_DEBUG_PRINT -#define CHIP_DBG(fmt, args...) printk(fmt, ## args) -#else -#define CHIP_DBG(fmt, args...) do { } while (0) -#endif - /* Synopsys Core versions */ #define DWMAC_CORE_3_40 0x34 #define DWMAC_CORE_3_50 0x35 diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 7e05e8d0f1c2..cdd926832e27 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -91,8 +91,8 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) unsigned int value = 0; unsigned int perfect_addr_number; - CHIP_DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", - __func__, netdev_mc_count(dev), netdev_uc_count(dev)); + pr_debug("%s: # mcasts %d, # unicast %d\n", __func__, + netdev_mc_count(dev), netdev_uc_count(dev)); if (dev->flags & IFF_PROMISC) value = GMAC_FRAME_FILTER_PR; @@ -152,7 +152,7 @@ static void dwmac1000_set_filter(struct net_device *dev, int id) #endif writel(value, ioaddr + GMAC_FRAME_FILTER); - CHIP_DBG(KERN_INFO "\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n", + pr_debug("\tFilter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER), readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); } @@ -162,18 +162,18 @@ static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, { unsigned int flow = 0; - CHIP_DBG(KERN_DEBUG "GMAC Flow-Control:\n"); + pr_debug("GMAC Flow-Control:\n"); if (fc & FLOW_RX) { - CHIP_DBG(KERN_DEBUG "\tReceive Flow-Control ON\n"); + pr_debug("\tReceive Flow-Control ON\n"); flow |= GMAC_FLOW_CTRL_RFE; } if (fc & FLOW_TX) { - CHIP_DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n"); + pr_debug("\tTransmit Flow-Control ON\n"); flow |= GMAC_FLOW_CTRL_TFE; } if (duplex) { - CHIP_DBG(KERN_DEBUG "\tduplex mode: PAUSE %d\n", pause_time); + pr_debug("\tduplex mode: PAUSE %d\n", pause_time); flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); } @@ -185,11 +185,11 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode) unsigned int pmt = 0; if (mode & WAKE_MAGIC) { - CHIP_DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); + pr_debug("GMAC: WOL Magic frame\n"); pmt |= power_down | magic_pkt_en; } if (mode & WAKE_UCAST) { - CHIP_DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); + pr_debug("GMAC: WOL on global unicast\n"); pmt |= global_unicast; } @@ -203,23 +203,13 @@ static int dwmac1000_irq_status(void __iomem *ioaddr, int ret = 0; /* Not used events (e.g. MMC interrupts) are not handled. */ - if ((intr_status & mmc_tx_irq)) { - CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n", - readl(ioaddr + GMAC_MMC_TX_INTR)); + if ((intr_status & mmc_tx_irq)) x->mmc_tx_irq_n++; - } - if (unlikely(intr_status & mmc_rx_irq)) { - CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n", - readl(ioaddr + GMAC_MMC_RX_INTR)); + if (unlikely(intr_status & mmc_rx_irq)) x->mmc_rx_irq_n++; - } - if (unlikely(intr_status & mmc_rx_csum_offload_irq)) { - CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n", - readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); + if (unlikely(intr_status & mmc_rx_csum_offload_irq)) x->mmc_rx_csum_offload_irq_n++; - } if (unlikely(intr_status & pmt_irq)) { - CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n"); /* clear the PMT bits 5 and 6 by reading the PMT status reg */ readl(ioaddr + GMAC_PMT); x->irq_receive_pmt_irq_n++; @@ -229,32 +219,22 @@ static int dwmac1000_irq_status(void __iomem *ioaddr, /* Clean LPI interrupt by reading the Reg 12 */ ret = readl(ioaddr + LPI_CTRL_STATUS); - if (ret & LPI_CTRL_STATUS_TLPIEN) { - CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n"); + if (ret & LPI_CTRL_STATUS_TLPIEN) x->irq_tx_path_in_lpi_mode_n++; - } - if (ret & LPI_CTRL_STATUS_TLPIEX) { - CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n"); + if (ret & LPI_CTRL_STATUS_TLPIEX) x->irq_tx_path_exit_lpi_mode_n++; - } - if (ret & LPI_CTRL_STATUS_RLPIEN) { - CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n"); + if (ret & LPI_CTRL_STATUS_RLPIEN) x->irq_rx_path_in_lpi_mode_n++; - } - if (ret & LPI_CTRL_STATUS_RLPIEX) { - CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n"); + if (ret & LPI_CTRL_STATUS_RLPIEX) x->irq_rx_path_exit_lpi_mode_n++; - } } if ((intr_status & pcs_ane_irq) || (intr_status & pcs_link_irq)) { - CHIP_DBG(KERN_INFO "GMAC PCS ANE IRQ\n"); readl(ioaddr + GMAC_AN_STATUS); x->irq_pcs_ane_n++; } if (intr_status & rgmii_irq) { u32 status = readl(ioaddr + GMAC_S_R_GMII); - CHIP_DBG(KERN_INFO "GMAC RGMII/SGMII interrupt\n"); x->irq_rgmii_n++; /* Save and dump the link status. */ @@ -271,11 +251,12 @@ static int dwmac1000_irq_status(void __iomem *ioaddr, x->pcs_speed = SPEED_10; x->pcs_link = 1; - pr_debug("Link is Up - %d/%s\n", (int)x->pcs_speed, + pr_debug("%s: Link is Up - %d/%s\n", __func__, + (int)x->pcs_speed, x->pcs_duplex ? "Full" : "Half"); } else { x->pcs_link = 0; - pr_debug("Link is Down\n"); + pr_debug("%s: Link is Down\n", __func__); } } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index 2c431b616058..0c2058a69fd2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -116,7 +116,7 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, u32 csr6 = readl(ioaddr + DMA_CONTROL); if (txmode == SF_DMA_MODE) { - CHIP_DBG(KERN_DEBUG "GMAC: enable TX store and forward mode\n"); + pr_debug("GMAC: enable TX store and forward mode\n"); /* Transmit COE type 2 cannot be done in cut-through mode. */ csr6 |= DMA_CONTROL_TSF; /* Operating on second frame increase the performance @@ -124,8 +124,7 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, */ csr6 |= DMA_CONTROL_OSF; } else { - CHIP_DBG(KERN_DEBUG "GMAC: disabling TX SF (threshold %d)\n", - txmode); + pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode); csr6 &= ~DMA_CONTROL_TSF; csr6 &= DMA_CONTROL_TC_TX_MASK; /* Set the transmit threshold */ @@ -142,11 +141,10 @@ static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, } if (rxmode == SF_DMA_MODE) { - CHIP_DBG(KERN_DEBUG "GMAC: enable RX store and forward mode\n"); + pr_debug("GMAC: enable RX store and forward mode\n"); csr6 |= DMA_CONTROL_RSF; } else { - CHIP_DBG(KERN_DEBUG "GMAC: disable RX SF mode (threshold %d)\n", - rxmode); + pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode); csr6 &= ~DMA_CONTROL_RSF; csr6 &= DMA_CONTROL_TC_RX_MASK; if (rxmode <= 32) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index 007bb2be3f10..5857d677dac1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -135,10 +135,6 @@ static void dwmac100_set_filter(struct net_device *dev, int id) } writel(value, ioaddr + MAC_CONTROL); - - CHIP_DBG(KERN_INFO "%s: Filter: 0x%08x Hash: HI 0x%08x, LO 0x%08x\n", - __func__, readl(ioaddr + MAC_CONTROL), - readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW)); } static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index 67551c154138..7d1dce9e7ffc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -90,14 +90,14 @@ static void dwmac100_dump_dma_regs(void __iomem *ioaddr) { int i; - CHIP_DBG(KERN_DEBUG "DWMAC 100 DMA CSR\n"); + pr_debug("DWMAC 100 DMA CSR\n"); for (i = 0; i < 9; i++) pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i, (DMA_BUS_MODE + i * 4), readl(ioaddr + DMA_BUS_MODE + i * 4)); - CHIP_DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n", - DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR)); - CHIP_DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n", + + pr_debug("\tCSR20 (0x%x): 0x%08x, CSR21 (0x%x): 0x%08x\n", + DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR), DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR)); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 491d7e930603..484e3cf9c414 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -24,13 +24,6 @@ #include "common.h" #include "dwmac_dma.h" -#undef DWMAC_DMA_DEBUG -#ifdef DWMAC_DMA_DEBUG -#define DWMAC_LIB_DBG(fmt, args...) printk(fmt, ## args) -#else -#define DWMAC_LIB_DBG(fmt, args...) do { } while (0) -#endif - #define GMAC_HI_REG_AE 0x80000000 /* CSR1 enables the transmit DMA to check for new descriptor */ @@ -85,24 +78,24 @@ static void show_tx_process_state(unsigned int status) switch (state) { case 0: - pr_info("- TX (Stopped): Reset or Stop command\n"); + pr_debug("- TX (Stopped): Reset or Stop command\n"); break; case 1: - pr_info("- TX (Running):Fetching the Tx desc\n"); + pr_debug("- TX (Running):Fetching the Tx desc\n"); break; case 2: - pr_info("- TX (Running): Waiting for end of tx\n"); + pr_debug("- TX (Running): Waiting for end of tx\n"); break; case 3: - pr_info("- TX (Running): Reading the data " + pr_debug("- TX (Running): Reading the data " "and queuing the data into the Tx buf\n"); break; case 6: - pr_info("- TX (Suspended): Tx Buff Underflow " + pr_debug("- TX (Suspended): Tx Buff Underflow " "or an unavailable Transmit descriptor\n"); break; case 7: - pr_info("- TX (Running): Closing Tx descriptor\n"); + pr_debug("- TX (Running): Closing Tx descriptor\n"); break; default: break; @@ -116,29 +109,29 @@ static void show_rx_process_state(unsigned int status) switch (state) { case 0: - pr_info("- RX (Stopped): Reset or Stop command\n"); + pr_debug("- RX (Stopped): Reset or Stop command\n"); break; case 1: - pr_info("- RX (Running): Fetching the Rx desc\n"); + pr_debug("- RX (Running): Fetching the Rx desc\n"); break; case 2: - pr_info("- RX (Running):Checking for end of pkt\n"); + pr_debug("- RX (Running):Checking for end of pkt\n"); break; case 3: - pr_info("- RX (Running): Waiting for Rx pkt\n"); + pr_debug("- RX (Running): Waiting for Rx pkt\n"); break; case 4: - pr_info("- RX (Suspended): Unavailable Rx buf\n"); + pr_debug("- RX (Suspended): Unavailable Rx buf\n"); break; case 5: - pr_info("- RX (Running): Closing Rx descriptor\n"); + pr_debug("- RX (Running): Closing Rx descriptor\n"); break; case 6: - pr_info("- RX(Running): Flushing the current frame" + pr_debug("- RX(Running): Flushing the current frame" " from the Rx buf\n"); break; case 7: - pr_info("- RX (Running): Queuing the Rx frame" + pr_debug("- RX (Running): Queuing the Rx frame" " from the Rx buf into memory\n"); break; default: @@ -154,51 +147,37 @@ int dwmac_dma_interrupt(void __iomem *ioaddr, /* read the status register (CSR5) */ u32 intr_status = readl(ioaddr + DMA_STATUS); - DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status); #ifdef DWMAC_DMA_DEBUG - /* It displays the DMA process states (CSR5 register) */ + /* Enable it to monitor DMA rx/tx status in case of critical problems */ + pr_debug("%s: [CSR5: 0x%08x]\n", __func__, intr_status); show_tx_process_state(intr_status); show_rx_process_state(intr_status); #endif /* ABNORMAL interrupts */ if (unlikely(intr_status & DMA_STATUS_AIS)) { - DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: "); if (unlikely(intr_status & DMA_STATUS_UNF)) { - DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n"); ret = tx_hard_error_bump_tc; x->tx_undeflow_irq++; } - if (unlikely(intr_status & DMA_STATUS_TJT)) { - DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n"); + if (unlikely(intr_status & DMA_STATUS_TJT)) x->tx_jabber_irq++; - } - if (unlikely(intr_status & DMA_STATUS_OVF)) { - DWMAC_LIB_DBG(KERN_INFO "recv overflow\n"); + + if (unlikely(intr_status & DMA_STATUS_OVF)) x->rx_overflow_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RU)) { - DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n"); + + if (unlikely(intr_status & DMA_STATUS_RU)) x->rx_buf_unav_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RPS)) { - DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n"); + if (unlikely(intr_status & DMA_STATUS_RPS)) x->rx_process_stopped_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RWT)) { - DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n"); + if (unlikely(intr_status & DMA_STATUS_RWT)) x->rx_watchdog_irq++; - } - if (unlikely(intr_status & DMA_STATUS_ETI)) { - DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n"); + if (unlikely(intr_status & DMA_STATUS_ETI)) x->tx_early_irq++; - } if (unlikely(intr_status & DMA_STATUS_TPS)) { - DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n"); x->tx_process_stopped_irq++; ret = tx_hard_error; } if (unlikely(intr_status & DMA_STATUS_FBI)) { - DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n"); x->fatal_bus_error_irq++; ret = tx_hard_error; } @@ -224,12 +203,11 @@ int dwmac_dma_interrupt(void __iomem *ioaddr, /* Optional hardware blocks, interrupts should be disabled */ if (unlikely(intr_status & (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) - pr_info("%s: unexpected status %08x\n", __func__, intr_status); + pr_warn("%s: unexpected status %08x\n", __func__, intr_status); /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS); - DWMAC_LIB_DBG(KERN_INFO "\n\n"); return ret; } diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index 0fbc8fafa706..7e6628a91514 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -33,54 +33,40 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x, struct net_device_stats *stats = (struct net_device_stats *)data; if (unlikely(p->des01.etx.error_summary)) { - CHIP_DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx); - if (unlikely(p->des01.etx.jabber_timeout)) { - CHIP_DBG(KERN_ERR "\tjabber_timeout error\n"); + if (unlikely(p->des01.etx.jabber_timeout)) x->tx_jabber++; - } if (unlikely(p->des01.etx.frame_flushed)) { - CHIP_DBG(KERN_ERR "\tframe_flushed error\n"); x->tx_frame_flushed++; dwmac_dma_flush_tx_fifo(ioaddr); } if (unlikely(p->des01.etx.loss_carrier)) { - CHIP_DBG(KERN_ERR "\tloss_carrier error\n"); x->tx_losscarrier++; stats->tx_carrier_errors++; } if (unlikely(p->des01.etx.no_carrier)) { - CHIP_DBG(KERN_ERR "\tno_carrier error\n"); x->tx_carrier++; stats->tx_carrier_errors++; } - if (unlikely(p->des01.etx.late_collision)) { - CHIP_DBG(KERN_ERR "\tlate_collision error\n"); + if (unlikely(p->des01.etx.late_collision)) stats->collisions += p->des01.etx.collision_count; - } - if (unlikely(p->des01.etx.excessive_collisions)) { - CHIP_DBG(KERN_ERR "\texcessive_collisions\n"); + + if (unlikely(p->des01.etx.excessive_collisions)) stats->collisions += p->des01.etx.collision_count; - } - if (unlikely(p->des01.etx.excessive_deferral)) { - CHIP_DBG(KERN_INFO "\texcessive tx_deferral\n"); + + if (unlikely(p->des01.etx.excessive_deferral)) x->tx_deferred++; - } if (unlikely(p->des01.etx.underflow_error)) { - CHIP_DBG(KERN_ERR "\tunderflow error\n"); dwmac_dma_flush_tx_fifo(ioaddr); x->tx_underflow++; } - if (unlikely(p->des01.etx.ip_header_error)) { - CHIP_DBG(KERN_ERR "\tTX IP header csum error\n"); + if (unlikely(p->des01.etx.ip_header_error)) x->tx_ip_header_error++; - } if (unlikely(p->des01.etx.payload_error)) { - CHIP_DBG(KERN_ERR "\tAddr/Payload csum error\n"); x->tx_payload_error++; dwmac_dma_flush_tx_fifo(ioaddr); } @@ -88,15 +74,12 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x, ret = -1; } - if (unlikely(p->des01.etx.deferred)) { - CHIP_DBG(KERN_INFO "GMAC TX status: tx deferred\n"); + if (unlikely(p->des01.etx.deferred)) x->tx_deferred++; - } + #ifdef STMMAC_VLAN_TAG_USED - if (p->des01.etx.vlan_frame) { - CHIP_DBG(KERN_INFO "GMAC TX status: VLAN frame\n"); + if (p->des01.etx.vlan_frame) x->tx_vlan++; - } #endif return ret; @@ -123,30 +106,20 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err) * 0 1 1 | COE bypassed.. no IPv4/6 frame * 0 1 0 | Reserved. */ - if (status == 0x0) { - CHIP_DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n"); + if (status == 0x0) ret = llc_snap; - } else if (status == 0x4) { - CHIP_DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n"); + else if (status == 0x4) ret = good_frame; - } else if (status == 0x5) { - CHIP_DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n"); + else if (status == 0x5) ret = csum_none; - } else if (status == 0x6) { - CHIP_DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n"); + else if (status == 0x6) ret = csum_none; - } else if (status == 0x7) { - CHIP_DBG(KERN_ERR - "RX Des0 status: IPv4/6 Header and Payload Error.\n"); + else if (status == 0x7) ret = csum_none; - } else if (status == 0x1) { - CHIP_DBG(KERN_ERR - "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n"); + else if (status == 0x1) ret = discard_frame; - } else if (status == 0x3) { - CHIP_DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n"); + else if (status == 0x3) ret = discard_frame; - } return ret; } @@ -208,36 +181,26 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, struct net_device_stats *stats = (struct net_device_stats *)data; if (unlikely(p->des01.erx.error_summary)) { - CHIP_DBG(KERN_ERR "GMAC RX Error Summary 0x%08x\n", - p->des01.erx); if (unlikely(p->des01.erx.descriptor_error)) { - CHIP_DBG(KERN_ERR "\tdescriptor error\n"); x->rx_desc++; stats->rx_length_errors++; } - if (unlikely(p->des01.erx.overflow_error)) { - CHIP_DBG(KERN_ERR "\toverflow error\n"); + if (unlikely(p->des01.erx.overflow_error)) x->rx_gmac_overflow++; - } if (unlikely(p->des01.erx.ipc_csum_error)) - CHIP_DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n"); + pr_err("\tIPC Csum Error/Giant frame\n"); if (unlikely(p->des01.erx.late_collision)) { - CHIP_DBG(KERN_ERR "\tlate_collision error\n"); - stats->collisions++; stats->collisions++; } - if (unlikely(p->des01.erx.receive_watchdog)) { - CHIP_DBG(KERN_ERR "\treceive_watchdog error\n"); + if (unlikely(p->des01.erx.receive_watchdog)) x->rx_watchdog++; - } - if (unlikely(p->des01.erx.error_gmii)) { - CHIP_DBG(KERN_ERR "\tReceive Error\n"); + + if (unlikely(p->des01.erx.error_gmii)) x->rx_mii++; - } + if (unlikely(p->des01.erx.crc_error)) { - CHIP_DBG(KERN_ERR "\tCRC error\n"); x->rx_crc++; stats->rx_crc_errors++; } @@ -251,30 +214,24 @@ static int enh_desc_get_rx_status(void *data, struct stmmac_extra_stats *x, ret = enh_desc_coe_rdes0(p->des01.erx.ipc_csum_error, p->des01.erx.frame_type, p->des01.erx.rx_mac_addr); - if (unlikely(p->des01.erx.dribbling)) { - CHIP_DBG(KERN_ERR "GMAC RX: dribbling error\n"); + if (unlikely(p->des01.erx.dribbling)) x->dribbling_bit++; - } + if (unlikely(p->des01.erx.sa_filter_fail)) { - CHIP_DBG(KERN_ERR "GMAC RX : Source Address filter fail\n"); x->sa_rx_filter_fail++; ret = discard_frame; } if (unlikely(p->des01.erx.da_filter_fail)) { - CHIP_DBG(KERN_ERR "GMAC RX : Dest Address filter fail\n"); x->da_rx_filter_fail++; ret = discard_frame; } if (unlikely(p->des01.erx.length_error)) { - CHIP_DBG(KERN_ERR "GMAC RX: length_error error\n"); x->rx_length++; ret = discard_frame; } #ifdef STMMAC_VLAN_TAG_USED - if (p->des01.erx.vlan_tag) { - CHIP_DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n"); + if (p->des01.erx.vlan_tag) x->rx_vlan++; - } #endif return ret; diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index 11775b99afc5..35ad4f427ae2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -52,10 +52,8 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x, ret = -1; } - if (p->des01.etx.vlan_frame) { - CHIP_DBG(KERN_INFO "GMAC TX status: VLAN frame\n"); + if (p->des01.etx.vlan_frame) x->tx_vlan++; - } if (unlikely(p->des01.tx.deferred)) x->tx_deferred++; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 520693385d8d..62e31054bd24 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -51,32 +51,6 @@ #include "stmmac_ptp.h" #include "stmmac.h" -#undef STMMAC_DEBUG -/*#define STMMAC_DEBUG*/ -#ifdef STMMAC_DEBUG -#define DBG(nlevel, klevel, fmt, args...) \ - ((void)(netif_msg_##nlevel(priv) && \ - printk(KERN_##klevel fmt, ## args))) -#else -#define DBG(nlevel, klevel, fmt, args...) do { } while (0) -#endif - -#undef STMMAC_RX_DEBUG -/*#define STMMAC_RX_DEBUG*/ -#ifdef STMMAC_RX_DEBUG -#define RX_DBG(fmt, args...) printk(fmt, ## args) -#else -#define RX_DBG(fmt, args...) do { } while (0) -#endif - -#undef STMMAC_XMIT_DEBUG -/*#define STMMAC_XMIT_DEBUG*/ -#ifdef STMMAC_XMIT_DEBUG -#define TX_DBG(fmt, args...) printk(fmt, ## args) -#else -#define TX_DBG(fmt, args...) do { } while (0) -#endif - #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) #define JUMBO_LEN 9000 @@ -214,19 +188,17 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv) } } -#if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG) static void print_pkt(unsigned char *buf, int len) { int j; - pr_info("len = %d byte, buf addr: 0x%p", len, buf); + pr_debug("len = %d byte, buf addr: 0x%p", len, buf); for (j = 0; j < len; j++) { if ((j % 16) == 0) - pr_info("\n %03x:", j); - pr_info(" %02x", buf[j]); + pr_debug("\n %03x:", j); + pr_debug(" %02x", buf[j]); } - pr_info("\n"); + pr_debug("\n"); } -#endif /* minimum number of free TX descriptors required to wake up TX process */ #define STMMAC_TX_THRESH(x) (x->dma_tx_size/4) @@ -698,9 +670,6 @@ static void stmmac_adjust_link(struct net_device *dev) if (phydev == NULL) return; - DBG(probe, DEBUG, "stmmac_adjust_link: called. address %d link %d\n", - phydev->addr, phydev->link); - spin_lock_irqsave(&priv->lock, flags); if (phydev->link) { @@ -772,8 +741,6 @@ static void stmmac_adjust_link(struct net_device *dev) stmmac_eee_adjust(priv); spin_unlock_irqrestore(&priv->lock, flags); - - DBG(probe, DEBUG, "stmmac_adjust_link: exiting\n"); } /** @@ -1014,8 +981,9 @@ static void init_dma_desc_rings(struct net_device *dev) if (bfsize < BUF_SIZE_16KiB) bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); - DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n", - txsize, rxsize, bfsize); + if (netif_msg_probe(priv)) + pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__, + txsize, rxsize, bfsize); if (priv->extend_desc) { priv->dma_erx = dma_alloc_coherent(priv->device, rxsize * @@ -1051,12 +1019,13 @@ static void init_dma_desc_rings(struct net_device *dev) GFP_KERNEL); priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), GFP_KERNEL); - if (netif_msg_drv(priv)) + if (netif_msg_probe(priv)) { pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); - /* RX INITIALIZATION */ - DBG(probe, INFO, "stmmac: SKB addresses:\nskb\t\tskb data\tdma data\n"); + /* RX INITIALIZATION */ + pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n"); + } for (i = 0; i < rxsize; i++) { struct dma_desc *p; if (priv->extend_desc) @@ -1067,8 +1036,10 @@ static void init_dma_desc_rings(struct net_device *dev) if (stmmac_init_rx_buffers(priv, p, i)) break; - DBG(probe, INFO, "[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], - priv->rx_skbuff[i]->data, priv->rx_skbuff_dma[i]); + if (netif_msg_probe(priv)) + pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], + priv->rx_skbuff[i]->data, + (unsigned int)priv->rx_skbuff_dma[i]); } priv->cur_rx = 0; priv->dirty_rx = (unsigned int)(i - rxsize); @@ -1243,8 +1214,9 @@ static void stmmac_tx_clean(struct stmmac_priv *priv) stmmac_get_tx_hwtstamp(priv, entry, skb); } - TX_DBG("%s: curr %d, dirty %d\n", __func__, - priv->cur_tx, priv->dirty_tx); + if (netif_msg_tx_done(priv)) + pr_debug("%s: curr %d, dirty %d\n", __func__, + priv->cur_tx, priv->dirty_tx); if (likely(priv->tx_skbuff_dma[entry])) { dma_unmap_single(priv->device, @@ -1269,7 +1241,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv) netif_tx_lock(priv->dev); if (netif_queue_stopped(priv->dev) && stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) { - TX_DBG("%s: restart transmit\n", __func__); + if (netif_msg_tx_done(priv)) + pr_debug("%s: restart transmit\n", __func__); netif_wake_queue(priv->dev); } netif_tx_unlock(priv->dev); @@ -1658,7 +1631,7 @@ static int stmmac_open(struct net_device *dev) pr_warn("%s: failed debugFS registration\n", __func__); #endif /* Start the ball rolling... */ - DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); + pr_debug("%s: DMA RX/TX processes started...\n", dev->name); priv->hw->dma->start_tx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr); @@ -1800,16 +1773,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) entry = priv->cur_tx % txsize; -#ifdef STMMAC_XMIT_DEBUG - if ((skb->len > ETH_FRAME_LEN) || nfrags) - pr_debug("%s: [entry %d]: skb addr %p len: %d nopagedlen: %d\n" - "\tn_frags: %d - ip_summed: %d - %s gso\n" - "\ttx_count_frames %d\n", __func__, entry, - skb, skb->len, nopaged_len, nfrags, skb->ip_summed, - !skb_is_gso(skb) ? "isn't" : "is", - priv->tx_count_frames); -#endif - csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); if (priv->extend_desc) @@ -1819,12 +1782,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) first = desc; -#ifdef STMMAC_XMIT_DEBUG - if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN)) - pr_debug("\tskb len: %d, nopaged_len: %d,\n" - "\t\tn_frags: %d, ip_summed: %d\n", - skb->len, nopaged_len, nfrags, skb->ip_summed); -#endif priv->tx_skbuff[entry] = skb; /* To program the descriptors according to the size of the frame */ @@ -1860,7 +1817,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) else desc = priv->dma_tx + entry; - TX_DBG("\t[entry %d] segment len: %d\n", entry, len); desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, DMA_TO_DEVICE); priv->tx_skbuff_dma[entry] = desc->des2; @@ -1884,8 +1840,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) if (priv->tx_coal_frames > priv->tx_count_frames) { priv->hw->desc->clear_tx_ic(desc); priv->xstats.tx_reset_ic_bit++; - TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry, - priv->tx_count_frames); mod_timer(&priv->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer)); } else @@ -1897,22 +1851,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->cur_tx++; -#ifdef STMMAC_XMIT_DEBUG if (netif_msg_pktdata(priv)) { - pr_info("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d", + pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d", __func__, (priv->cur_tx % txsize), (priv->dirty_tx % txsize), entry, first, nfrags); + if (priv->extend_desc) stmmac_display_ring((void *)priv->dma_etx, txsize, 1); else stmmac_display_ring((void *)priv->dma_tx, txsize, 0); - pr_info(">>> frame to be transmitted: "); + pr_debug(">>> frame to be transmitted: "); print_pkt(skb->data, skb->len); } -#endif if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { - TX_DBG("%s: stop transmitted packets\n", __func__); + if (netif_msg_hw(priv)) + pr_debug("%s: stop transmitted packets\n", __func__); netif_stop_queue(dev); } @@ -1972,7 +1926,8 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) priv->hw->ring->refill_desc3(priv, p); - RX_DBG(KERN_INFO "\trefill entry #%d\n", entry); + if (netif_msg_rx_status(priv)) + pr_debug("\trefill entry #%d\n", entry); } wmb(); priv->hw->desc->set_rx_owner(p); @@ -1995,15 +1950,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) unsigned int count = 0; int coe = priv->plat->rx_coe; -#ifdef STMMAC_RX_DEBUG - if (netif_msg_hw(priv)) { - pr_debug(">>> stmmac_rx: descriptor ring:\n"); + if (netif_msg_rx_status(priv)) { + pr_debug("%s: descriptor ring:\n", __func__); if (priv->extend_desc) stmmac_display_ring((void *)priv->dma_erx, rxsize, 1); else stmmac_display_ring((void *)priv->dma_rx, rxsize, 0); } -#endif while (count < limit) { int status; struct dma_desc *p; @@ -2057,15 +2010,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) */ if (unlikely(status != llc_snap)) frame_len -= ETH_FCS_LEN; -#ifdef STMMAC_RX_DEBUG - if (frame_len > ETH_FRAME_LEN) - pr_debug("\tRX frame size %d, COE status: %d\n", - frame_len, status); - if (netif_msg_hw(priv)) + if (netif_msg_rx_status(priv)) { pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", p, entry, p->des2); -#endif + if (frame_len > ETH_FRAME_LEN) + pr_debug("\tframe size %d, COE: %d\n", + frame_len, status); + } skb = priv->rx_skbuff[entry]; if (unlikely(!skb)) { pr_err("%s: Inconsistent Rx descriptor chain\n", @@ -2082,12 +2034,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) dma_unmap_single(priv->device, priv->rx_skbuff_dma[entry], priv->dma_buf_sz, DMA_FROM_DEVICE); -#ifdef STMMAC_RX_DEBUG + if (netif_msg_pktdata(priv)) { - pr_info(" frame received (%dbytes)", frame_len); + pr_debug("frame received (%dbytes)", frame_len); print_pkt(skb->data, frame_len); } -#endif + skb->protocol = eth_type_trans(skb, priv->dev); if (unlikely(!coe)) -- GitLab From 8a59bd3e9b296b93b905b5509c4ff540ee0e00bf Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Tue, 2 Jul 2013 18:39:36 +0200 Subject: [PATCH 2209/2900] sctp: use get_unused_fd_flags(0) instead of get_unused_fd() Macro get_unused_fd() is used to allocate a file descriptor with default flags. Those default flags (0) can be "unsafe": O_CLOEXEC must be used by default to not leak file descriptor across exec(). Instead of macro get_unused_fd(), functions anon_inode_getfd() or get_unused_fd_flags() should be used with flags given by userspace. If not possible, flags should be set to O_CLOEXEC to provide userspace with a default safe behavor. In a further patch, get_unused_fd() will be removed so that new code start using anon_inode_getfd() or get_unused_fd_flags() with correct flags. This patch replaces calls to get_unused_fd() with equivalent call to get_unused_fd_flags(0) to preserve current behavor for existing code. The hard coded flag value (0) should be reviewed on a per-subsystem basis, and, if possible, set to O_CLOEXEC. Signed-off-by: Yann Droneaud Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d5c6a2870473..c6670d2e3f8d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4312,7 +4312,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval goto out; /* Map the socket to an unused fd that can be returned to the user. */ - retval = get_unused_fd(); + retval = get_unused_fd_flags(0); if (retval < 0) { sock_release(newsock); goto out; -- GitLab From b6dc01a43aaca24e6e6928e24d9b37ba599f1e3c Mon Sep 17 00:00:00 2001 From: James Chapman Date: Tue, 2 Jul 2013 20:28:58 +0100 Subject: [PATCH 2210/2900] l2tp: do data sequence number handling in a separate func This change moves some code handling data sequence numbers into a separate function to avoid too much indentation. This is to prepare for some changes to data sequence number handling in subsequent patches. Signed-off-by: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 54 ++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 6984c3a353cd..5ca29659171d 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -542,6 +542,38 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, return __skb_checksum_complete(skb); } +/* If packet has sequence numbers, queue it if acceptable. Returns 0 if + * acceptable, else non-zero. + */ +static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) +{ + if (session->reorder_timeout != 0) { + /* Packet reordering enabled. Add skb to session's + * reorder queue, in order of ns. + */ + l2tp_recv_queue_skb(session, skb); + } else { + /* Packet reordering disabled. Discard out-of-sequence + * packets + */ + if (L2TP_SKB_CB(skb)->ns != session->nr) { + atomic_long_inc(&session->stats.rx_seq_discards); + l2tp_dbg(session, L2TP_MSG_SEQ, + "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", + session->name, L2TP_SKB_CB(skb)->ns, + L2TP_SKB_CB(skb)->length, session->nr, + skb_queue_len(&session->reorder_q)); + goto discard; + } + skb_queue_tail(&session->reorder_q, skb); + } + + return 0; + +discard: + return 1; +} + /* Do receive processing of L2TP data frames. We handle both L2TPv2 * and L2TPv3 data frames here. * @@ -757,26 +789,8 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, * enabled. Saved L2TP protocol info is stored in skb->sb[]. */ if (L2TP_SKB_CB(skb)->has_seq) { - if (session->reorder_timeout != 0) { - /* Packet reordering enabled. Add skb to session's - * reorder queue, in order of ns. - */ - l2tp_recv_queue_skb(session, skb); - } else { - /* Packet reordering disabled. Discard out-of-sequence - * packets - */ - if (L2TP_SKB_CB(skb)->ns != session->nr) { - atomic_long_inc(&session->stats.rx_seq_discards); - l2tp_dbg(session, L2TP_MSG_SEQ, - "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", - session->name, L2TP_SKB_CB(skb)->ns, - L2TP_SKB_CB(skb)->length, session->nr, - skb_queue_len(&session->reorder_q)); - goto discard; - } - skb_queue_tail(&session->reorder_q, skb); - } + if (l2tp_recv_data_seq(session, skb)) + goto discard; } else { /* No sequence numbers. Add the skb to the tail of the * reorder queue. This ensures that it will be -- GitLab From 8a1631d588a39e826f4248e60310498d5266c6fa Mon Sep 17 00:00:00 2001 From: James Chapman Date: Tue, 2 Jul 2013 20:28:59 +0100 Subject: [PATCH 2211/2900] l2tp: make datapath sequence number support RFC-compliant The L2TP datapath is not currently RFC-compliant when sequence numbers are used in L2TP data packets. According to the L2TP RFC, any received sequence number NR greater than or equal to the next expected NR is acceptable, where the "greater than or equal to" test is determined by the NR wrap point. This differs for L2TPv2 and L2TPv3, so add state in the session context to hold the max NR value and the NR window size in order to do the acceptable sequence number value check. These might be configurable later, but for now we derive it from the tunnel L2TP version, which determines the sequence number field size. Signed-off-by: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 36 +++++++++++++++++++++++++++++++----- net/l2tp/l2tp_core.h | 2 ++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 5ca29659171d..735cc06971ef 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -414,10 +414,7 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff * if (L2TP_SKB_CB(skb)->has_seq) { /* Bump our Nr */ session->nr++; - if (tunnel->version == L2TP_HDR_VER_2) - session->nr &= 0xffff; - else - session->nr &= 0xffffff; + session->nr &= session->nr_max; l2tp_dbg(session, L2TP_MSG_SEQ, "%s: updated nr to %hu\n", session->name, session->nr); @@ -542,11 +539,34 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk, return __skb_checksum_complete(skb); } +static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) +{ + u32 nws; + + if (nr >= session->nr) + nws = nr - session->nr; + else + nws = (session->nr_max + 1) - (session->nr - nr); + + return nws < session->nr_window_size; +} + /* If packet has sequence numbers, queue it if acceptable. Returns 0 if * acceptable, else non-zero. */ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) { + if (!l2tp_seq_check_rx_window(session, L2TP_SKB_CB(skb)->ns)) { + /* Packet sequence number is outside allowed window. + * Discard it. + */ + l2tp_dbg(session, L2TP_MSG_SEQ, + "%s: pkt %u len %d discarded, outside window, nr=%u\n", + session->name, L2TP_SKB_CB(skb)->ns, + L2TP_SKB_CB(skb)->length, session->nr); + goto discard; + } + if (session->reorder_timeout != 0) { /* Packet reordering enabled. Add skb to session's * reorder queue, in order of ns. @@ -556,7 +576,8 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) /* Packet reordering disabled. Discard out-of-sequence * packets */ - if (L2TP_SKB_CB(skb)->ns != session->nr) { + if ((L2TP_SKB_CB(skb)->ns != session->nr) && + (!session->reorder_skip)) { atomic_long_inc(&session->stats.rx_seq_discards); l2tp_dbg(session, L2TP_MSG_SEQ, "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", @@ -1826,6 +1847,11 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn session->session_id = session_id; session->peer_session_id = peer_session_id; session->nr = 0; + if (tunnel->version == L2TP_HDR_VER_2) + session->nr_max = 0xffff; + else + session->nr_max = 0xffffff; + session->nr_window_size = session->nr_max / 2; sprintf(&session->name[0], "sess %u/%u", tunnel->tunnel_id, session->session_id); diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 485a490fd990..4b9a3b724423 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -102,6 +102,8 @@ struct l2tp_session { u32 nr; /* session NR state (receive) */ u32 ns; /* session NR state (send) */ struct sk_buff_head reorder_q; /* receive reorder queue */ + u32 nr_max; /* max NR. Depends on tunnel */ + u32 nr_window_size; /* NR window size */ struct hlist_node hlist; /* Hash list node */ atomic_t ref_count; -- GitLab From a0dbd822273ce7660bf35525d61d7a8ac5e679a3 Mon Sep 17 00:00:00 2001 From: James Chapman Date: Tue, 2 Jul 2013 20:29:00 +0100 Subject: [PATCH 2212/2900] l2tp: make datapath resilient to packet loss when sequence numbers enabled If L2TP data sequence numbers are enabled and reordering is not enabled, data reception stops if a packet is lost since the kernel waits for a sequence number that is never resent. (When reordering is enabled, data reception restarts when the reorder timeout expires.) If no reorder timeout is set, we should count the number of in-sequence packets after the out-of-sequence (OOS) condition is detected, and reset sequence number state after a number of such packets are received. For now, the number of in-sequence packets while in OOS state which cause the sequence number state to be reset is hard-coded to 5. This could be configurable later. Signed-off-by: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_core.c | 36 +++++++++++++++++++++++++++++++----- net/l2tp/l2tp_core.h | 3 +++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 735cc06971ef..feae495a0a30 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -572,12 +572,33 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) * reorder queue, in order of ns. */ l2tp_recv_queue_skb(session, skb); + goto out; + } + + /* Packet reordering disabled. Discard out-of-sequence packets, while + * tracking the number if in-sequence packets after the first OOS packet + * is seen. After nr_oos_count_max in-sequence packets, reset the + * sequence number to re-enable packet reception. + */ + if (L2TP_SKB_CB(skb)->ns == session->nr) { + skb_queue_tail(&session->reorder_q, skb); } else { - /* Packet reordering disabled. Discard out-of-sequence - * packets - */ - if ((L2TP_SKB_CB(skb)->ns != session->nr) && - (!session->reorder_skip)) { + u32 nr_oos = L2TP_SKB_CB(skb)->ns; + u32 nr_next = (session->nr_oos + 1) & session->nr_max; + + if (nr_oos == nr_next) + session->nr_oos_count++; + else + session->nr_oos_count = 0; + + session->nr_oos = nr_oos; + if (session->nr_oos_count > session->nr_oos_count_max) { + session->reorder_skip = 1; + l2tp_dbg(session, L2TP_MSG_SEQ, + "%s: %d oos packets received. Resetting sequence numbers\n", + session->name, session->nr_oos_count); + } + if (!session->reorder_skip) { atomic_long_inc(&session->stats.rx_seq_discards); l2tp_dbg(session, L2TP_MSG_SEQ, "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n", @@ -589,6 +610,7 @@ static int l2tp_recv_data_seq(struct l2tp_session *session, struct sk_buff *skb) skb_queue_tail(&session->reorder_q, skb); } +out: return 0; discard: @@ -1852,6 +1874,10 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn else session->nr_max = 0xffffff; session->nr_window_size = session->nr_max / 2; + session->nr_oos_count_max = 4; + + /* Use NR of first received packet */ + session->reorder_skip = 1; sprintf(&session->name[0], "sess %u/%u", tunnel->tunnel_id, session->session_id); diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 4b9a3b724423..66a559b104b6 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -104,6 +104,9 @@ struct l2tp_session { struct sk_buff_head reorder_q; /* receive reorder queue */ u32 nr_max; /* max NR. Depends on tunnel */ u32 nr_window_size; /* NR window size */ + u32 nr_oos; /* NR of last OOS packet */ + int nr_oos_count; /* For OOS recovery */ + int nr_oos_count_max; struct hlist_node hlist; /* Hash list node */ atomic_t ref_count; -- GitLab From 23a3647bc4f93bac3776c66dc2c7f7f68b3cd662 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Tue, 2 Jul 2013 10:57:33 -0700 Subject: [PATCH 2213/2900] ip_tunnels: Use skb-len to PMTU check. In path mtu check, ip header total length works for gre device but not for gre-tap device. Use skb len which is consistent for all tunneling types. This is old bug in gre. This also fixes mtu calculation bug introduced by commit c54419321455631079c7d (GRE: Refactor GRE tunneling code). Reported-by: Timo Teras Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 99 ++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 394cebc96d22..945734b2f209 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -472,6 +472,54 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(ip_tunnel_rcv); +static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + struct rtable *rt, __be16 df) +{ + struct ip_tunnel *tunnel = netdev_priv(dev); + int pkt_size = skb->len - tunnel->hlen; + int mtu; + + if (df) + mtu = dst_mtu(&rt->dst) - dev->hard_header_len + - sizeof(struct iphdr) - tunnel->hlen; + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + + if (skb_dst(skb)) + skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); + + if (skb->protocol == htons(ETH_P_IP)) { + if (!skb_is_gso(skb) && + (df & htons(IP_DF)) && mtu < pkt_size) { + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); + return -E2BIG; + } + } +#if IS_ENABLED(CONFIG_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) { + struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); + + if (rt6 && mtu < dst_mtu(skb_dst(skb)) && + mtu >= IPV6_MIN_MTU) { + if ((tunnel->parms.iph.daddr && + !ipv4_is_multicast(tunnel->parms.iph.daddr)) || + rt6->rt6i_dst.plen == 128) { + rt6->rt6i_flags |= RTF_MODIFIED; + dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); + } + } + + if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && + mtu < pkt_size) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + return -E2BIG; + } + } +#endif + return 0; +} + void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, const struct iphdr *tnl_params, const u8 protocol) { @@ -483,7 +531,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, struct rtable *rt; /* Route to the other host */ unsigned int max_headroom; /* The extra header space needed */ __be32 dst; - int mtu; int err; inner_iph = (const struct iphdr *)skb_inner_network_header(skb); @@ -560,51 +607,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, dev->stats.collisions++; goto tx_error; } - df = tnl_params->frag_off; - if (df) - mtu = dst_mtu(&rt->dst) - dev->hard_header_len - - sizeof(struct iphdr); - else - mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; - - if (skb_dst(skb)) - skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); - - if (skb->protocol == htons(ETH_P_IP)) { - df |= (inner_iph->frag_off&htons(IP_DF)); - - if (!skb_is_gso(skb) && - (inner_iph->frag_off&htons(IP_DF)) && - mtu < ntohs(inner_iph->tot_len)) { - memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); - ip_rt_put(rt); - goto tx_error; - } - } -#if IS_ENABLED(CONFIG_IPV6) - else if (skb->protocol == htons(ETH_P_IPV6)) { - struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); - - if (rt6 && mtu < dst_mtu(skb_dst(skb)) && - mtu >= IPV6_MIN_MTU) { - if ((tunnel->parms.iph.daddr && - !ipv4_is_multicast(tunnel->parms.iph.daddr)) || - rt6->rt6i_dst.plen == 128) { - rt6->rt6i_flags |= RTF_MODIFIED; - dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); - } - } - - if (!skb_is_gso(skb) && mtu >= IPV6_MIN_MTU && - mtu < skb->len) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - ip_rt_put(rt); - goto tx_error; - } + if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) { + ip_rt_put(rt); + goto tx_error; } -#endif if (tunnel->net != dev_net(dev)) skb_scrub_packet(skb); @@ -631,6 +638,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ttl = ip4_dst_hoplimit(&rt->dst); } + df = tnl_params->frag_off; + if (skb->protocol == htons(ETH_P_IP)) + df |= (inner_iph->frag_off&htons(IP_DF)); + max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + rt->dst.header_len; if (max_headroom > dev->needed_headroom) { -- GitLab From 9cc98f01e270b206a8a513418afd81b23535bd10 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 25 Jun 2013 18:36:05 -0700 Subject: [PATCH 2214/2900] ARM: Make multi_v7_defconfig usable on hardware This updates multi_v7_defconfig to boot on at least Tegra2 Seaboard and Panda ES. I lack working hardware for most of the platforms that were enabled to compare with, so I could only verify those two for now. Still, I enabled all of the available ones for build coverage purposes. Beyond base platforms, things like PRINTK_TIME, filesystems, MMC, USB, INET and UNIX networking was enabled. I'm sure we'll keep adding more over time, but this gets us off the ground for semi-regular boot testing. Acked-by: Tony Lindgren Acked-by: Stephen Warren Signed-off-by: Olof Johansson --- arch/arm/configs/multi_v7_defconfig | 121 +++++++++++++++++++++------- 1 file changed, 93 insertions(+), 28 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 340d550c12b0..6d8d3c456b5f 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -1,88 +1,153 @@ -CONFIG_EXPERIMENTAL=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_BLK_DEV_INITRD=y CONFIG_ARCH_MVEBU=y CONFIG_MACH_ARMADA_370=y -CONFIG_ARCH_SIRF=y CONFIG_MACH_ARMADA_XP=y +CONFIG_ARCH_BCM=y +CONFIG_GPIO_PCA953X=y CONFIG_ARCH_HIGHBANK=y +CONFIG_ARCH_KEYSTONE=y +CONFIG_ARCH_MXC=y +CONFIG_MACH_IMX51_DT=y +CONFIG_SOC_IMX53=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +CONFIG_SOC_VF610=y +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_SOC_OMAP5=y +CONFIG_SOC_AM43XX=y +CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SOCFPGA=y -CONFIG_ARCH_SUNXI=y -CONFIG_ARCH_WM8850=y -# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set -CONFIG_ARCH_ZYNQ=y -CONFIG_ARM_ERRATA_754322=y CONFIG_PLAT_SPEAR=y CONFIG_ARCH_SPEAR13XX=y CONFIG_MACH_SPEAR1310=y CONFIG_MACH_SPEAR1340=y +CONFIG_ARCH_STI=y +CONFIG_ARCH_SUNXI=y +CONFIG_ARCH_SIRF=y +CONFIG_ARCH_TEGRA=y +CONFIG_ARCH_TEGRA_2x_SOC=y +CONFIG_ARCH_TEGRA_3x_SOC=y +CONFIG_ARCH_TEGRA_114_SOC=y +CONFIG_TEGRA_PCI=y +CONFIG_TEGRA_EMC_SCALING_ENABLE=y +CONFIG_ARCH_U8500=y +CONFIG_MACH_SNOWBALL=y +CONFIG_MACH_UX500_DT=y +CONFIG_ARCH_VEXPRESS=y +CONFIG_ARCH_VEXPRESS_CA9X4=y +CONFIG_ARCH_VIRT=y +CONFIG_ARCH_WM8850=y +CONFIG_ARCH_ZYNQ=y CONFIG_SMP=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_AEABI=y -CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y CONFIG_ARM_APPENDED_DTB=y -CONFIG_VFP=y -CONFIG_NEON=y CONFIG_NET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y CONFIG_BLK_DEV_SD=y CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y CONFIG_SATA_HIGHBANK=y CONFIG_SATA_MV=y -CONFIG_SATA_AHCI_PLATFORM=y CONFIG_NETDEVICES=y -CONFIG_SUN4I_EMAC=y CONFIG_NET_CALXEDA_XGMAC=y CONFIG_SMSC911X=y CONFIG_STMMAC_ETH=y +CONFIG_KEYBOARD_SPEAR=y CONFIG_SERIO_AMBAKMI=y -CONFIG_MDIO_SUN4I=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y -CONFIG_KEYBOARD_SPEAR=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_SIRFSOC=y CONFIG_SERIAL_SIRFSOC_CONSOLE=y +CONFIG_SERIAL_TEGRA=y CONFIG_SERIAL_VT8500=y CONFIG_SERIAL_VT8500_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_IPMI_HANDLER=y -CONFIG_IPMI_SI=y -CONFIG_I2C=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_SIRF=y +CONFIG_I2C_TEGRA=y CONFIG_SPI=y CONFIG_SPI_PL022=y CONFIG_SPI_SIRF=y -CONFIG_GPIO_PL061=y -CONFIG_FB=y +CONFIG_SPI_TEGRA114=y +CONFIG_SPI_TEGRA20_SLINK=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_TWL4030=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_AB8500=y +CONFIG_REGULATOR_TPS51632=y +CONFIG_REGULATOR_TPS62360=y +CONFIG_REGULATOR_TWL4030=y +CONFIG_REGULATOR_VEXPRESS=y +CONFIG_DRM=y +CONFIG_TEGRA_HOST1X=y +CONFIG_DRM_TEGRA=y CONFIG_FB_ARMCLCD=y CONFIG_FB_WM8505=y -CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FB_SIMPLE=y CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_ISP1760_HCD=y CONFIG_USB_STORAGE=y +CONFIG_AB8500_USB=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_OMAP_USB2=y +CONFIG_OMAP_USB3=y +CONFIG_SAMSUNG_USB2PHY=y +CONFIG_SAMSUNG_USB3PHY=y +CONFIG_USB_GPIO_VBUS=y +CONFIG_USB_ISP1301=y +CONFIG_USB_MXS_PHY=y CONFIG_MMC=y CONFIG_MMC_ARMMMCI=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_TEGRA=y CONFIG_MMC_SDHCI_SPEAR=y -CONFIG_MMC_WMT=y +CONFIG_MMC_OMAP=y +CONFIG_MMC_OMAP_HS=y CONFIG_EDAC=y CONFIG_EDAC_MM_EDAC=y CONFIG_EDAC_HIGHBANK_MC=y CONFIG_EDAC_HIGHBANK_L2=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TWL4030=y CONFIG_RTC_DRV_PL031=y CONFIG_RTC_DRV_VT8500=y -CONFIG_PWM=y -CONFIG_PWM_VT8500=y +CONFIG_RTC_DRV_TEGRA=y CONFIG_DMADEVICES=y -CONFIG_PL330_DMA=y -CONFIG_SIRF_DMA=y CONFIG_DW_DMAC=y +CONFIG_TEGRA20_APB_DMA=y +CONFIG_STE_DMA40=y +CONFIG_SIRF_DMA=y +CONFIG_TI_EDMA=y +CONFIG_PL330_DMA=y +CONFIG_IMX_SDMA=y +CONFIG_IMX_DMA=y +CONFIG_MXS_DMA=y +CONFIG_DMA_OMAP=y +CONFIG_PWM=y +CONFIG_PWM_VT8500=y +CONFIG_EXT4_FS=y +CONFIG_TMPFS=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOCKUP_DETECTOR=y -- GitLab From 2a6c24afab70dbcfee49f4c76e1511eec1a3298b Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 2 Jul 2013 14:48:23 -0400 Subject: [PATCH 2215/2900] tracing: Fix race between deleting buffer and setting events While analyzing the code, I discovered that there's a potential race between deleting a trace instance and setting events. There are a few races that can occur if events are being traced as the buffer is being deleted. Mostly the problem comes with freeing the descriptor used by the trace event callback. To prevent problems like this, the events are disabled before the buffer is deleted. The problem with the current solution is that the event_mutex is let go between disabling the events and freeing the files, which means that the events could be enabled again while the freeing takes place. Cc: stable@vger.kernel.org # 3.10 Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 920e08fb53b3..7d854290bf81 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -441,14 +441,14 @@ static int tracing_release_generic_file(struct inode *inode, struct file *filp) /* * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. */ -static int __ftrace_set_clr_event(struct trace_array *tr, const char *match, - const char *sub, const char *event, int set) +static int +__ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match, + const char *sub, const char *event, int set) { struct ftrace_event_file *file; struct ftrace_event_call *call; int ret = -EINVAL; - mutex_lock(&event_mutex); list_for_each_entry(file, &tr->events, list) { call = file->event_call; @@ -474,6 +474,17 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match, ret = 0; } + + return ret; +} + +static int __ftrace_set_clr_event(struct trace_array *tr, const char *match, + const char *sub, const char *event, int set) +{ + int ret; + + mutex_lock(&event_mutex); + ret = __ftrace_set_clr_event_nolock(tr, match, sub, event, set); mutex_unlock(&event_mutex); return ret; @@ -2408,11 +2419,11 @@ early_event_add_tracer(struct dentry *parent, struct trace_array *tr) int event_trace_del_tracer(struct trace_array *tr) { - /* Disable any running events */ - __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0); - mutex_lock(&event_mutex); + /* Disable any running events */ + __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0); + down_write(&trace_event_sem); __trace_remove_event_dirs(tr); debugfs_remove_recursive(tr->event_dir); -- GitLab From fa44063f9ef163c3a4c8d8c0465bb8a056b42035 Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Thu, 13 Jun 2013 14:21:51 +0800 Subject: [PATCH 2216/2900] uprobes: Fix return value in error handling path When wrong argument is passed into uprobe_events it does not return an error: [root@jovi tracing]# echo 'p:myprobe /bin/bash' > uprobe_events [root@jovi tracing]# The proper response is: [root@jovi tracing]# echo 'p:myprobe /bin/bash' > uprobe_events -bash: echo: write error: Invalid argument Link: http://lkml.kernel.org/r/51B964FF.5000106@huawei.com Cc: Frederic Weisbecker Cc: Cc: stable@vger.kernel.org # 3.5+ Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace_uprobe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 32494fb0ee64..d5d0cd368a56 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -283,8 +283,10 @@ static int create_trace_uprobe(int argc, char **argv) return -EINVAL; } arg = strchr(argv[1], ':'); - if (!arg) + if (!arg) { + ret = -EINVAL; goto fail_address_parse; + } *arg++ = '\0'; filename = argv[1]; -- GitLab From 11034ae9c20f4057a6127fc965906417978e69b2 Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Wed, 10 Apr 2013 11:26:23 +0800 Subject: [PATCH 2217/2900] tracing: Fix irqs-off tag display in syscall tracing All syscall tracing irqs-off tags are wrong, the syscall enter entry doesn't disable irqs. [root@jovi tracing]#echo "syscalls:sys_enter_open" > set_event [root@jovi tracing]# cat trace # tracer: nop # # entries-in-buffer/entries-written: 13/13 #P:2 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | irqbalance-513 [000] d... 56115.496766: sys_open(filename: 804e1a6, flags: 0, mode: 1b6) irqbalance-513 [000] d... 56115.497008: sys_open(filename: 804e1bb, flags: 0, mode: 1b6) sendmail-771 [000] d... 56115.827982: sys_open(filename: b770e6d1, flags: 0, mode: 1b6) The reason is syscall tracing doesn't record irq_flags into buffer. The proper display is: [root@jovi tracing]#echo "syscalls:sys_enter_open" > set_event [root@jovi tracing]# cat trace # tracer: nop # # entries-in-buffer/entries-written: 14/14 #P:2 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | irqbalance-514 [001] .... 46.213921: sys_open(filename: 804e1a6, flags: 0, mode: 1b6) irqbalance-514 [001] .... 46.214160: sys_open(filename: 804e1bb, flags: 0, mode: 1b6) <...>-920 [001] .... 47.307260: sys_open(filename: 4e82a0c5, flags: 80000, mode: 0) Link: http://lkml.kernel.org/r/1365564393-10972-3-git-send-email-jovi.zhangwei@huawei.com Cc: stable@vger.kernel.org # 2.6.35 Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace_syscalls.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 8f2ac73c7a5f..322e16461072 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -306,6 +306,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) struct syscall_metadata *sys_data; struct ring_buffer_event *event; struct ring_buffer *buffer; + unsigned long irq_flags; + int pc; int syscall_nr; int size; @@ -321,9 +323,12 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; + local_save_flags(irq_flags); + pc = preempt_count(); + buffer = tr->trace_buffer.buffer; event = trace_buffer_lock_reserve(buffer, - sys_data->enter_event->event.type, size, 0, 0); + sys_data->enter_event->event.type, size, irq_flags, pc); if (!event) return; @@ -333,7 +338,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) if (!filter_current_check_discard(buffer, sys_data->enter_event, entry, event)) - trace_current_buffer_unlock_commit(buffer, event, 0, 0); + trace_current_buffer_unlock_commit(buffer, event, + irq_flags, pc); } static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) @@ -343,6 +349,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) struct syscall_metadata *sys_data; struct ring_buffer_event *event; struct ring_buffer *buffer; + unsigned long irq_flags; + int pc; int syscall_nr; syscall_nr = trace_get_syscall_nr(current, regs); @@ -355,9 +363,13 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) if (!sys_data) return; + local_save_flags(irq_flags); + pc = preempt_count(); + buffer = tr->trace_buffer.buffer; event = trace_buffer_lock_reserve(buffer, - sys_data->exit_event->event.type, sizeof(*entry), 0, 0); + sys_data->exit_event->event.type, sizeof(*entry), + irq_flags, pc); if (!event) return; @@ -367,7 +379,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) if (!filter_current_check_discard(buffer, sys_data->exit_event, entry, event)) - trace_current_buffer_unlock_commit(buffer, event, 0, 0); + trace_current_buffer_unlock_commit(buffer, event, + irq_flags, pc); } static int reg_event_syscall_enter(struct ftrace_event_file *file, -- GitLab From 5280bcef91e706770cc1706eb97353e3513322b9 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 2 Jul 2013 19:59:57 -0400 Subject: [PATCH 2218/2900] tracing: Make tracer_tracing_{off,on,is_on}() static I have patches that will use tracer_tracing_on/off/is_on() in other files, but as they are not ready to be merged yet, and Fengguang Wu's sparse scripts pointed out that these functions were not declared anywhere, I'll make them static for now. When these functions are required to be used elsewhere, I'll remove the static then. Reported-by: kbuild test robot Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 6d9bd9b43e43..48aceb8a0328 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -387,7 +387,7 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE | TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION; -void tracer_tracing_on(struct trace_array *tr) +static void tracer_tracing_on(struct trace_array *tr) { if (tr->trace_buffer.buffer) ring_buffer_record_on(tr->trace_buffer.buffer); @@ -606,7 +606,7 @@ void tracing_snapshot_alloc(void) EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); #endif /* CONFIG_TRACER_SNAPSHOT */ -void tracer_tracing_off(struct trace_array *tr) +static void tracer_tracing_off(struct trace_array *tr) { if (tr->trace_buffer.buffer) ring_buffer_record_off(tr->trace_buffer.buffer); @@ -649,7 +649,7 @@ void disable_trace_on_warning(void) * * Shows real state of the ring buffer if it is enabled or not. */ -int tracer_tracing_is_on(struct trace_array *tr) +static int tracer_tracing_is_on(struct trace_array *tr) { if (tr->trace_buffer.buffer) return ring_buffer_record_is_on(tr->trace_buffer.buffer); -- GitLab From 4480361c3c592fcbce3ef74e030719f0715e3a7e Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Wed, 10 Apr 2013 11:26:28 +0800 Subject: [PATCH 2219/2900] tracing: Remove TRACE_EVENT_TYPE enum definition TRACE_EVENT_TYPE enum is not used at present, remove it. Link: http://lkml.kernel.org/r/1365564393-10972-8-git-send-email-jovi.zhangwei@huawei.com Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index c7fbf93f1b7c..1cbba04976b4 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -907,12 +907,6 @@ static inline void trace_branch_disable(void) /* set ring buffers to default size if not already done so */ int tracing_update_buffers(void); -/* trace event type bit fields, not numeric */ -enum { - TRACE_EVENT_TYPE_PRINTF = 1, - TRACE_EVENT_TYPE_RAW = 2, -}; - struct ftrace_event_field { struct list_head link; const char *name; -- GitLab From 8de1eb02778b64f8b292db531cf39a429f84315f Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Wed, 10 Apr 2013 11:26:30 +0800 Subject: [PATCH 2220/2900] tracing: Remove ftrace() function The only caller of function ftrace(...) was removed a long time ago, so remove the function body as well. Link: http://lkml.kernel.org/r/1365564393-10972-10-git-send-email-jovi.zhangwei@huawei.com Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 9 --------- kernel/trace/trace.h | 5 ----- 2 files changed, 14 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 48aceb8a0328..f6fed9e51c64 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1637,15 +1637,6 @@ trace_function(struct trace_array *tr, __buffer_unlock_commit(buffer, event); } -void -ftrace(struct trace_array *tr, struct trace_array_cpu *data, - unsigned long ip, unsigned long parent_ip, unsigned long flags, - int pc) -{ - if (likely(!atomic_read(&data->disabled))) - trace_function(tr, ip, parent_ip, flags, pc); -} - #ifdef CONFIG_STACKTRACE #define FTRACE_STACK_MAX_ENTRIES (PAGE_SIZE / sizeof(unsigned long)) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 1cbba04976b4..a4ed382dea2f 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -559,11 +559,6 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu); void poll_wait_pipe(struct trace_iterator *iter); -void ftrace(struct trace_array *tr, - struct trace_array_cpu *data, - unsigned long ip, - unsigned long parent_ip, - unsigned long flags, int pc); void tracing_sched_switch_trace(struct trace_array *tr, struct task_struct *prev, struct task_struct *next, -- GitLab From dcc302232c1f9b3ca16f6b8ee190eb0b1a8a0da3 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 2 Jul 2013 20:30:52 -0400 Subject: [PATCH 2221/2900] tracing: Make tracing_open_generic_{tr,tc}() static I have patches that will use tracing_open_generic_tr/tc() in other files, but as they are not ready to be merged yet, and Fengguang Wu's sparse scripts pointed out that these functions were not declared anywhere, I'll make them static for now. When these functions are required to be used elsewhere, I'll remove the static then. Reported-by: kbuild test robot Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index f6fed9e51c64..dc473b51415f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2960,7 +2960,7 @@ int tracing_open_generic(struct inode *inode, struct file *filp) * Open and update trace_array ref count. * Must have the current trace_array passed to it. */ -int tracing_open_generic_tr(struct inode *inode, struct file *filp) +static int tracing_open_generic_tr(struct inode *inode, struct file *filp) { struct trace_array *tr = inode->i_private; @@ -2976,7 +2976,7 @@ int tracing_open_generic_tr(struct inode *inode, struct file *filp) } -int tracing_open_generic_tc(struct inode *inode, struct file *filp) +static int tracing_open_generic_tc(struct inode *inode, struct file *filp) { struct trace_cpu *tc = inode->i_private; struct trace_array *tr = tc->tr; -- GitLab From 8d8022e8aba85192e937f1f0f7450e256d66ae5c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 3 Jul 2013 10:06:28 +0930 Subject: [PATCH 2222/2900] module: do percpu allocation after uniqueness check. No, really! v3.8-rc1-5-g1fb9341 was supposed to stop parallel kvm loads exhausting percpu memory on large machines: Now we have a new state MODULE_STATE_UNFORMED, we can insert the module into the list (and thus guarantee its uniqueness) before we allocate the per-cpu region. In my defence, it didn't actually say the patch did this. Just that we "can". This patch actually *does* it. Signed-off-by: Rusty Russell Tested-by: Jim Hull Cc: stable@kernel.org # 3.8 --- kernel/module.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index 5184877ce98a..d1a161be7b04 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2940,7 +2940,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) { /* Module within temporary copy. */ struct module *mod; - Elf_Shdr *pcpusec; int err; mod = setup_load_info(info, flags); @@ -2955,17 +2954,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) err = module_frob_arch_sections(info->hdr, info->sechdrs, info->secstrings, mod); if (err < 0) - goto out; + return ERR_PTR(err); - pcpusec = &info->sechdrs[info->index.pcpu]; - if (pcpusec->sh_size) { - /* We have a special allocation for this section. */ - err = percpu_modalloc(mod, - pcpusec->sh_size, pcpusec->sh_addralign); - if (err) - goto out; - pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC; - } + /* We will do a special allocation for per-cpu sections later. */ + info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; /* Determine total sizes, and put offsets in sh_entsize. For now this is done generically; there doesn't appear to be any @@ -2976,17 +2968,22 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) /* Allocate and move to the final place */ err = move_module(mod, info); if (err) - goto free_percpu; + return ERR_PTR(err); /* Module has been copied to its final place now: return it. */ mod = (void *)info->sechdrs[info->index.mod].sh_addr; kmemleak_load_module(mod, info); return mod; +} -free_percpu: - percpu_modfree(mod); -out: - return ERR_PTR(err); +static int alloc_module_percpu(struct module *mod, struct load_info *info) +{ + Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; + if (!pcpusec->sh_size) + return 0; + + /* We have a special allocation for this section. */ + return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign); } /* mod is no longer valid after this! */ @@ -3262,6 +3259,11 @@ static int load_module(struct load_info *info, const char __user *uargs, } #endif + /* To avoid stressing percpu allocator, do this once we're unique. */ + err = alloc_module_percpu(mod, info); + if (err) + goto unlink_mod; + /* Now module is in final location, initialize linked lists, etc. */ err = module_unload_init(mod); if (err) -- GitLab From 9eb76d7797b892a1dad4f2efb6f786681306dd13 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 3 Jul 2013 10:06:29 +0930 Subject: [PATCH 2223/2900] module: cleanup call chain. Fold alloc_module_percpu into percpu_modalloc(). Signed-off-by: Rusty Russell --- kernel/module.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/kernel/module.c b/kernel/module.c index d1a161be7b04..c18107942ac2 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod) return mod->percpu; } -static int percpu_modalloc(struct module *mod, - unsigned long size, unsigned long align) +static int percpu_modalloc(struct module *mod, struct load_info *info) { + Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; + unsigned long align = pcpusec->sh_addralign; + + if (!pcpusec->sh_size) + return 0; + if (align > PAGE_SIZE) { printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", mod->name, align, PAGE_SIZE); align = PAGE_SIZE; } - mod->percpu = __alloc_reserved_percpu(size, align); + mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align); if (!mod->percpu) { printk(KERN_WARNING "%s: Could not allocate %lu bytes percpu data\n", - mod->name, size); + mod->name, (unsigned long)pcpusec->sh_size); return -ENOMEM; } - mod->percpu_size = size; + mod->percpu_size = pcpusec->sh_size; return 0; } @@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod) { return NULL; } -static inline int percpu_modalloc(struct module *mod, - unsigned long size, unsigned long align) +static int percpu_modalloc(struct module *mod, struct load_info *info) { - return -ENOMEM; + /* UP modules shouldn't have this section: ENOMEM isn't quite right */ + if (info->sechdrs[info->index.pcpu].sh_size != 0) + return -ENOMEM; + return 0; } static inline void percpu_modfree(struct module *mod) { @@ -2976,16 +2983,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) return mod; } -static int alloc_module_percpu(struct module *mod, struct load_info *info) -{ - Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; - if (!pcpusec->sh_size) - return 0; - - /* We have a special allocation for this section. */ - return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign); -} - /* mod is no longer valid after this! */ static void module_deallocate(struct module *mod, struct load_info *info) { @@ -3260,7 +3257,7 @@ static int load_module(struct load_info *info, const char __user *uargs, #endif /* To avoid stressing percpu allocator, do this once we're unique. */ - err = alloc_module_percpu(mod, info); + err = percpu_modalloc(mod, info); if (err) goto unlink_mod; -- GitLab From 57691a1e27a7d1995775b7e25e2ec0d7a415edc0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 27 Jun 2013 23:29:25 -0700 Subject: [PATCH 2224/2900] Input: ads7846 - make sure we do not change platform data Let's declare platform data a const pointer so that we don't accitentally change it. Also fetch it with dev_get_platdata(). Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 84ccf140c1bb..5ff041995198 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -961,9 +961,9 @@ static int ads7846_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); static int ads7846_setup_pendown(struct spi_device *spi, - struct ads7846 *ts) + struct ads7846 *ts, + const struct ads7846_platform_data *pdata) { - struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; /* @@ -1003,7 +1003,7 @@ static int ads7846_setup_pendown(struct spi_device *spi, * use formula #2 for pressure, not #3. */ static void ads7846_setup_spi_msg(struct ads7846 *ts, - const struct ads7846_platform_data *pdata) + const struct ads7846_platform_data *pdata) { struct spi_message *m = &ts->msg[0]; struct spi_transfer *x = ts->xfer; @@ -1203,10 +1203,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, static int ads7846_probe(struct spi_device *spi) { + const struct ads7846_platform_data *pdata = dev_get_platdata(&spi->dev); struct ads7846 *ts; struct ads7846_packet *packet; struct input_dev *input_dev; - struct ads7846_platform_data *pdata = spi->dev.platform_data; unsigned long irq_flags; int err; @@ -1281,7 +1281,7 @@ static int ads7846_probe(struct spi_device *spi) ts->filter = ads7846_no_filter; } - err = ads7846_setup_pendown(spi, ts); + err = ads7846_setup_pendown(spi, ts, pdata); if (err) goto err_cleanup_filter; -- GitLab From a608026eacaee59cf0f1fa5caad60320f5b4a373 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 27 Jun 2013 23:42:17 -0700 Subject: [PATCH 2225/2900] Input: ads7846 - add device tree bindings Signed-off-by: Daniel Mack Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/ads7846.txt | 91 ++++++++++++++ drivers/input/touchscreen/ads7846.c | 115 ++++++++++++++++-- 2 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/ads7846.txt diff --git a/Documentation/devicetree/bindings/input/ads7846.txt b/Documentation/devicetree/bindings/input/ads7846.txt new file mode 100644 index 000000000000..5f7619c22743 --- /dev/null +++ b/Documentation/devicetree/bindings/input/ads7846.txt @@ -0,0 +1,91 @@ +Device tree bindings for TI's ADS7843, ADS7845, ADS7846, ADS7873, TSC2046 +SPI driven touch screen controllers. + +The node for this driver must be a child node of a SPI controller, hence +all mandatory properties described in + + Documentation/devicetree/bindings/spi/spi-bus.txt + +must be specified. + +Additional required properties: + + compatible Must be one of the following, depending on the + model: + "ti,tsc2046" + "ti,ads7843" + "ti,ads7845" + "ti,ads7846" + "ti,ads7873" + + interrupt-parent + interrupts An interrupt node describing the IRQ line the chip's + !PENIRQ pin is connected to. + vcc-supply A regulator node for the supply voltage. + + +Optional properties: + + ti,vref-delay-usecs vref supply delay in usecs, 0 for + external vref (u16). + ti,vref-mv The VREF voltage, in millivolts (u16). + ti,keep-vref-on set to keep vref on for differential + measurements as well + ti,swap-xy swap x and y axis + ti,settle-delay-usec Settling time of the analog signals; + a function of Vcc and the capacitance + on the X/Y drivers. If set to non-zero, + two samples are taken with settle_delay + us apart, and the second one is used. + ~150 uSec with 0.01uF caps (u16). + ti,penirq-recheck-delay-usecs If set to non-zero, after samples are + taken this delay is applied and penirq + is rechecked, to help avoid false + events. This value is affected by the + material used to build the touch layer + (u16). + ti,x-plate-ohms Resistance of the X-plate, + in Ohms (u16). + ti,y-plate-ohms Resistance of the Y-plate, + in Ohms (u16). + ti,x-min Minimum value on the X axis (u16). + ti,y-min Minimum value on the Y axis (u16). + ti,x-max Maximum value on the X axis (u16). + ti,y-max Minimum value on the Y axis (u16). + ti,pressure-min Minimum reported pressure value + (threshold) - u16. + ti,pressure-max Maximum reported pressure value (u16). + ti,debounce-max Max number of additional readings per + sample (u16). + ti,debounce-tol Tolerance used for filtering (u16). + ti,debounce-rep Additional consecutive good readings + required after the first two (u16). + ti,pendown-gpio-debounce Platform specific debounce time for the + pendown-gpio (u32). + pendown-gpio GPIO handle describing the pin the !PENIRQ + line is connected to. + linux,wakeup use any event on touchscreen as wakeup event. + + +Example for a TSC2046 chip connected to an McSPI controller of an OMAP SoC:: + + spi_controller { + tsc2046@0 { + reg = <0>; /* CS0 */ + compatible = "ti,tsc2046"; + interrupt-parent = <&gpio1>; + interrupts = <8 0>; /* BOOT6 / GPIO 8 */ + spi-max-frequency = <1000000>; + pendown-gpio = <&gpio1 8 0>; + vcc-supply = <®_vcc3>; + + ti,x-min = /bits/ 16 <0>; + ti,x-max = /bits/ 16 <8000>; + ti,y-min = /bits/ 16 <0>; + ti,y-max = /bits/ 16 <4800>; + ti,x-plate-ohms = /bits/ 16 <40>; + ti,pressure-max = /bits/ 16 <255>; + + linux,wakeup; + }; + }; diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 5ff041995198..ea195360747e 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -1201,9 +1204,87 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts, spi_message_add_tail(x, m); } +#ifdef CONFIG_OF +static const struct of_device_id ads7846_dt_ids[] = { + { .compatible = "ti,tsc2046", .data = (void *) 7846 }, + { .compatible = "ti,ads7843", .data = (void *) 7843 }, + { .compatible = "ti,ads7845", .data = (void *) 7845 }, + { .compatible = "ti,ads7846", .data = (void *) 7846 }, + { .compatible = "ti,ads7873", .data = (void *) 7873 }, + { } +}; +MODULE_DEVICE_TABLE(of, ads7846_dt_ids); + +static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) +{ + struct ads7846_platform_data *pdata; + struct device_node *node = dev->of_node; + const struct of_device_id *match; + + if (!node) { + dev_err(dev, "Device does not have associated DT data\n"); + return ERR_PTR(-EINVAL); + } + + match = of_match_device(ads7846_dt_ids, dev); + if (!match) { + dev_err(dev, "Unknown device model\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->model = (unsigned long)match->data; + + of_property_read_u16(node, "ti,vref-delay-usecs", + &pdata->vref_delay_usecs); + of_property_read_u16(node, "ti,vref-mv", &pdata->vref_mv); + pdata->keep_vref_on = of_property_read_bool(node, "ti,keep-vref-on"); + + pdata->swap_xy = of_property_read_bool(node, "ti,swap-xy"); + + of_property_read_u16(node, "ti,settle-delay-usec", + &pdata->settle_delay_usecs); + of_property_read_u16(node, "ti,penirq-recheck-delay-usecs", + &pdata->penirq_recheck_delay_usecs); + + of_property_read_u16(node, "ti,x-plate-ohms", &pdata->x_plate_ohms); + of_property_read_u16(node, "ti,y-plate-ohms", &pdata->y_plate_ohms); + + of_property_read_u16(node, "ti,x-min", &pdata->x_min); + of_property_read_u16(node, "ti,y-min", &pdata->y_min); + of_property_read_u16(node, "ti,x-max", &pdata->x_max); + of_property_read_u16(node, "ti,y-max", &pdata->y_max); + + of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min); + of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max); + + of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max); + of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol); + of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep); + + of_property_read_u32(node, "ti,pendown-gpio-debounce", + &pdata->gpio_pendown_debounce); + + pdata->wakeup = of_property_read_bool(node, "linux,wakeup"); + + pdata->gpio_pendown = of_get_named_gpio(dev->of_node, "pendown-gpio", 0); + + return pdata; +} +#else +static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) +{ + dev_err(dev, "no platform data defined\n"); + return ERR_PTR(-EINVAL); +} +#endif + static int ads7846_probe(struct spi_device *spi) { - const struct ads7846_platform_data *pdata = dev_get_platdata(&spi->dev); + const struct ads7846_platform_data *pdata; struct ads7846 *ts; struct ads7846_packet *packet; struct input_dev *input_dev; @@ -1212,22 +1293,18 @@ static int ads7846_probe(struct spi_device *spi) if (!spi->irq) { dev_dbg(&spi->dev, "no IRQ?\n"); - return -ENODEV; - } - - if (!pdata) { - dev_dbg(&spi->dev, "no platform data?\n"); - return -ENODEV; + return -EINVAL; } /* don't exceed max specified sample rate */ if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { - dev_dbg(&spi->dev, "f(sample) %d KHz?\n", + dev_err(&spi->dev, "f(sample) %d KHz?\n", (spi->max_speed_hz/SAMPLE_BITS)/1000); return -EINVAL; } - /* We'd set TX word size 8 bits and RX word size to 13 bits ... except + /* + * We'd set TX word size 8 bits and RX word size to 13 bits ... except * that even if the hardware can do that, the SPI controller driver * may not. So we stick to very-portable 8 bit words, both RX and TX. */ @@ -1250,17 +1327,25 @@ static int ads7846_probe(struct spi_device *spi) ts->packet = packet; ts->spi = spi; ts->input = input_dev; - ts->vref_mv = pdata->vref_mv; - ts->swap_xy = pdata->swap_xy; mutex_init(&ts->lock); init_waitqueue_head(&ts->wait); + pdata = dev_get_platdata(&spi->dev); + if (!pdata) { + pdata = ads7846_probe_dt(&spi->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } + ts->model = pdata->model ? : 7846; ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; ts->pressure_max = pdata->pressure_max ? : ~0; + ts->vref_mv = pdata->vref_mv; + ts->swap_xy = pdata->swap_xy; + if (pdata->filter != NULL) { if (pdata->filter_init != NULL) { err = pdata->filter_init(pdata, &ts->filter_data); @@ -1370,6 +1455,13 @@ static int ads7846_probe(struct spi_device *spi) device_init_wakeup(&spi->dev, pdata->wakeup); + /* + * If device does not carry platform data we must have allocated it + * when parsing DT data. + */ + if (!dev_get_platdata(&spi->dev)) + devm_kfree(&spi->dev, (void *)pdata); + return 0; err_remove_attr_group: @@ -1437,6 +1529,7 @@ static struct spi_driver ads7846_driver = { .name = "ads7846", .owner = THIS_MODULE, .pm = &ads7846_pm, + .of_match_table = of_match_ptr(ads7846_dt_ids), }, .probe = ads7846_probe, .remove = ads7846_remove, -- GitLab From 419076f59fc5916bd200b45225c83437b37ab189 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Wed, 3 Jul 2013 06:41:24 +0300 Subject: [PATCH 2226/2900] net: lls fix build with allnoconfig correct placeholder declarations to prevent build breakage when !CONFIG_NET_LL_RX_POLL Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- include/net/ll_poll.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index b76f004f18a9..0d620ba19bc5 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -163,12 +163,12 @@ static inline unsigned long ll_get_flag(void) return 0; } -static inline u64 sk_ll_end_time(struct sock *sk) +static inline u64 ll_start_time(unsigned int flag) { return 0; } -static inline u64 ll_end_time(void) +static inline u64 ll_run_time(void) { return 0; } @@ -191,7 +191,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) { } -static inline bool can_poll_ll(u64 end_time) +static inline bool can_poll_ll(u64 start_time, u64 run_time) { return false; } -- GitLab From 39e24a16283c6780a9049db75a91bcf6b5943b9a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 24 Jun 2013 15:06:57 +0530 Subject: [PATCH 2227/2900] regulator: s5m8767: Update s5m8767-regulator bindings document s5m8767 regulator is used on Exynos platforms which use pin controller to configure GPIOs. Update the example accordingly. [This had previously been broken by code changes which failed to update the documentation -- broonie] Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- .../bindings/regulator/s5m8767-regulator.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt index a35ff99003a5..7364f7114fbd 100644 --- a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt @@ -103,13 +103,13 @@ Example: s5m8767,pmic-buck-default-dvs-idx = <0>; - s5m8767,pmic-buck-dvs-gpios = <&gpx0 0 1 0 0>, /* DVS1 */ - <&gpx0 1 1 0 0>, /* DVS2 */ - <&gpx0 2 1 0 0>; /* DVS3 */ + s5m8767,pmic-buck-dvs-gpios = <&gpx0 0 0>, /* DVS1 */ + <&gpx0 1 0>, /* DVS2 */ + <&gpx0 2 0>; /* DVS3 */ - s5m8767,pmic-buck-ds-gpios = <&gpx2 3 1 0 0>, /* SET1 */ - <&gpx2 4 1 0 0>, /* SET2 */ - <&gpx2 5 1 0 0>; /* SET3 */ + s5m8767,pmic-buck-ds-gpios = <&gpx2 3 0>, /* SET1 */ + <&gpx2 4 0>, /* SET2 */ + <&gpx2 5 0>; /* SET3 */ s5m8767,pmic-buck2-dvs-voltage = <1350000>, <1300000>, <1250000>, <1200000>, -- GitLab From d50235b7bc3ee0a0427984d763ea7534149531b4 Mon Sep 17 00:00:00 2001 From: Jianpeng Ma Date: Wed, 3 Jul 2013 13:25:24 +0200 Subject: [PATCH 2228/2900] elevator: Fix a race in elevator switching There's a race between elevator switching and normal io operation. Because the allocation of struct elevator_queue and struct elevator_data don't in a atomic operation.So there are have chance to use NULL ->elevator_data. For example: Thread A: Thread B blk_queu_bio elevator_switch spin_lock_irq(q->queue_block) elevator_alloc elv_merge elevator_init_fn Because call elevator_alloc, it can't hold queue_lock and the ->elevator_data is NULL.So at the same time, threadA call elv_merge and nedd some info of elevator_data.So the crash happened. Move the elevator_alloc into func elevator_init_fn, it make the operations in a atomic operation. Using the follow method can easy reproduce this bug 1:dd if=/dev/sdb of=/dev/null 2:while true;do echo noop > scheduler;echo deadline > scheduler;done The test method also use this method. Signed-off-by: Jianpeng Ma Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 17 ++++++++++++++--- block/deadline-iosched.c | 16 +++++++++++++--- block/elevator.c | 25 +++++-------------------- block/noop-iosched.c | 17 ++++++++++++++--- include/linux/elevator.h | 6 +++++- 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index d5cd3131c57a..d5bbdcfd0dab 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4347,18 +4347,28 @@ static void cfq_exit_queue(struct elevator_queue *e) kfree(cfqd); } -static int cfq_init_queue(struct request_queue *q) +static int cfq_init_queue(struct request_queue *q, struct elevator_type *e) { struct cfq_data *cfqd; struct blkcg_gq *blkg __maybe_unused; int i, ret; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); - if (!cfqd) + if (!cfqd) { + kobject_put(&eq->kobj); return -ENOMEM; + } + eq->elevator_data = cfqd; cfqd->queue = q; - q->elevator->elevator_data = cfqd; + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); /* Init root service tree */ cfqd->grp_service_tree = CFQ_RB_ROOT; @@ -4433,6 +4443,7 @@ static int cfq_init_queue(struct request_queue *q) out_free: kfree(cfqd); + kobject_put(&eq->kobj); return ret; } diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index ba19a3afab79..20614a332362 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -337,13 +337,21 @@ static void deadline_exit_queue(struct elevator_queue *e) /* * initialize elevator private data (deadline_data). */ -static int deadline_init_queue(struct request_queue *q) +static int deadline_init_queue(struct request_queue *q, struct elevator_type *e) { struct deadline_data *dd; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node); - if (!dd) + if (!dd) { + kobject_put(&eq->kobj); return -ENOMEM; + } + eq->elevator_data = dd; INIT_LIST_HEAD(&dd->fifo_list[READ]); INIT_LIST_HEAD(&dd->fifo_list[WRITE]); @@ -355,7 +363,9 @@ static int deadline_init_queue(struct request_queue *q) dd->front_merges = 1; dd->fifo_batch = fifo_batch; - q->elevator->elevator_data = dd; + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); return 0; } diff --git a/block/elevator.c b/block/elevator.c index eba5b04c29b1..668394d18588 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -150,7 +150,7 @@ void __init load_default_elevator_module(void) static struct kobj_type elv_ktype; -static struct elevator_queue *elevator_alloc(struct request_queue *q, +struct elevator_queue *elevator_alloc(struct request_queue *q, struct elevator_type *e) { struct elevator_queue *eq; @@ -170,6 +170,7 @@ static struct elevator_queue *elevator_alloc(struct request_queue *q, elevator_put(e); return NULL; } +EXPORT_SYMBOL(elevator_alloc); static void elevator_release(struct kobject *kobj) { @@ -221,16 +222,7 @@ int elevator_init(struct request_queue *q, char *name) } } - q->elevator = elevator_alloc(q, e); - if (!q->elevator) - return -ENOMEM; - - err = e->ops.elevator_init_fn(q); - if (err) { - kobject_put(&q->elevator->kobj); - return err; - } - + err = e->ops.elevator_init_fn(q, e); return 0; } EXPORT_SYMBOL(elevator_init); @@ -935,16 +927,9 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) spin_unlock_irq(q->queue_lock); /* allocate, init and register new elevator */ - err = -ENOMEM; - q->elevator = elevator_alloc(q, new_e); - if (!q->elevator) - goto fail_init; - - err = new_e->ops.elevator_init_fn(q); - if (err) { - kobject_put(&q->elevator->kobj); + err = new_e->ops.elevator_init_fn(q, new_e); + if (err) goto fail_init; - } if (registered) { err = elv_register_queue(q); diff --git a/block/noop-iosched.c b/block/noop-iosched.c index 5d1bf70e33d5..3de89d4690f3 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c @@ -59,16 +59,27 @@ noop_latter_request(struct request_queue *q, struct request *rq) return list_entry(rq->queuelist.next, struct request, queuelist); } -static int noop_init_queue(struct request_queue *q) +static int noop_init_queue(struct request_queue *q, struct elevator_type *e) { struct noop_data *nd; + struct elevator_queue *eq; + + eq = elevator_alloc(q, e); + if (!eq) + return -ENOMEM; nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node); - if (!nd) + if (!nd) { + kobject_put(&eq->kobj); return -ENOMEM; + } + eq->elevator_data = nd; INIT_LIST_HEAD(&nd->queue); - q->elevator->elevator_data = nd; + + spin_lock_irq(q->queue_lock); + q->elevator = eq; + spin_unlock_irq(q->queue_lock); return 0; } diff --git a/include/linux/elevator.h b/include/linux/elevator.h index acd0312d46fb..306dd8cd0b6f 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -7,6 +7,7 @@ #ifdef CONFIG_BLOCK struct io_cq; +struct elevator_type; typedef int (elevator_merge_fn) (struct request_queue *, struct request **, struct bio *); @@ -35,7 +36,8 @@ typedef void (elevator_put_req_fn) (struct request *); typedef void (elevator_activate_req_fn) (struct request_queue *, struct request *); typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct request *); -typedef int (elevator_init_fn) (struct request_queue *); +typedef int (elevator_init_fn) (struct request_queue *, + struct elevator_type *e); typedef void (elevator_exit_fn) (struct elevator_queue *); struct elevator_ops @@ -155,6 +157,8 @@ extern int elevator_init(struct request_queue *, char *); extern void elevator_exit(struct elevator_queue *); extern int elevator_change(struct request_queue *, const char *); extern bool elv_rq_merge_ok(struct request *, struct bio *); +extern struct elevator_queue *elevator_alloc(struct request_queue *, + struct elevator_type *); /* * Helper functions. -- GitLab From 04130cc973a96df33b1429024fd6dec59fa35a84 Mon Sep 17 00:00:00 2001 From: Daniel Tang Date: Sun, 9 Jun 2013 12:33:55 +1000 Subject: [PATCH 2229/2900] Fix a build warning in scripts/mod/file2alias.c On some systems, __used is already defined in sys/cdefs.h and causes a build warning: scripts/mod/file2alias.c:85:1: warning: "__used" redefined In file included from /usr/include/stdio.h:64, from scripts/mod/modpost.h:1, from scripts/mod/file2alias.c:13: /usr/include/sys/cdefs.h:146:1: warning: this is the location of the previous definition This adds an extra check before defining the __used macro to see if the macro was already defined elsewhere. Signed-off-by: Daniel Tang Signed-off-by: Michal Marek --- scripts/mod/file2alias.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 45f9a3377dcd..ab554564569a 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -79,10 +79,12 @@ struct devtable **__start___devtable, **__stop___devtable; extern struct devtable *__start___devtable[], *__stop___devtable[]; #endif /* __MACH__ */ -#if __GNUC__ == 3 && __GNUC_MINOR__ < 3 -# define __used __attribute__((__unused__)) -#else -# define __used __attribute__((__used__)) +#if !defined(__used) +# if __GNUC__ == 3 && __GNUC_MINOR__ < 3 +# define __used __attribute__((__unused__)) +# else +# define __used __attribute__((__used__)) +# endif #endif /* Define a variable f that holds the value of field f of struct devid -- GitLab From 9f310dedfecdf53974e6e7c21d8d4dc7e8ab8c14 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 1 Jul 2013 15:07:05 -0600 Subject: [PATCH 2230/2900] ARM: tegra: fix VBUS regulator GPIO polarity in DT Commit 4c94c8b "ARM: tegra: update device trees for USB binding rework" added regulator definitions for GPIO-controlled USB VBUS. However, none of these contained the essential DT property enable-active-high. Add this so that the regulator definitions are correct. Signed-off-by: Stephen Warren Signed-off-by: Arnd Bergmann --- arch/arm/boot/dts/tegra20-seaboard.dts | 1 + arch/arm/boot/dts/tegra20-trimslice.dts | 1 + arch/arm/boot/dts/tegra20-whistler.dts | 2 ++ 3 files changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index ab177b406b78..365760b33a26 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -828,6 +828,7 @@ regulator-name = "vdd_vbus_wup1"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; + enable-active-high; gpio = <&gpio 24 0>; /* PD0 */ }; }; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index 170159910455..ed4b901b0227 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -410,6 +410,7 @@ regulator-name = "usb1_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; + enable-active-high; gpio = <&gpio 170 0>; /* PV2 */ }; }; diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index ea078ab8edeb..ab67c94db280 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -586,6 +586,7 @@ regulator-name = "vbus1"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; + enable-active-high; gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ }; @@ -595,6 +596,7 @@ regulator-name = "vbus3"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; + enable-active-high; gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ }; }; -- GitLab From d2aae8477cd00325bb7c7c7e95be488088900c48 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 2 May 2013 14:50:37 +0200 Subject: [PATCH 2231/2900] Makefile: Fix install error with make -j option Make modules_install fails with -j option: DEPMOD Usage: .../.source/linux/scripts/depmod.sh /sbin/depmod make[1]: *** [_modinst_post] Error 1 Adding kernelrelease dependency to fix this. Signed-off-by: Robert Richter Cc: Signed-off-by: Michal Marek --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6280aa192c36..29339b430126 100644 --- a/Makefile +++ b/Makefile @@ -981,7 +981,7 @@ _modinst_: # boot a modules.dep even before / is mounted read-write. However the # boot script depmod is the master version. PHONY += _modinst_post -_modinst_post: _modinst_ +_modinst_post: include/config/kernel.release _modinst_ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst $(call cmd,depmod) -- GitLab From 90d06a46835ba73deffb483970fdc2bffa4bb274 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 18 Jun 2013 14:49:29 -0700 Subject: [PATCH 2232/2900] coccicheck: span checks across CPUs This adds parallelism by default to the "coccicheck" target using spatch's "-max" and "-index" arguments. Signed-off-by: Kees Cook Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- Documentation/coccinelle.txt | 5 +++++ scripts/coccicheck | 31 ++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Documentation/coccinelle.txt b/Documentation/coccinelle.txt index 18de78599dd4..408439d07889 100644 --- a/Documentation/coccinelle.txt +++ b/Documentation/coccinelle.txt @@ -91,6 +91,11 @@ To enable verbose messages set the V= variable, for example: make coccicheck MODE=report V=1 +By default, coccicheck tries to run as parallel as possible. To change +the parallelism, set the J= variable. For example, to run across 4 CPUs: + + make coccicheck MODE=report J=4 + Using Coccinelle with a single semantic patch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/scripts/coccicheck b/scripts/coccicheck index 9d8780cdbcd4..ad8e8ffd3c7e 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -2,15 +2,24 @@ SPATCH="`which ${SPATCH:=spatch}`" +trap kill_running SIGTERM SIGINT +declare -a SPATCH_PID + # The verbosity may be set by the environmental parameter V= # as for example with 'make V=1 coccicheck' if [ -n "$V" -a "$V" != "0" ]; then - VERBOSE=1 + VERBOSE="$V" else VERBOSE=0 fi +if [ -z "$J" ]; then + NPROC=$(getconf _NPROCESSORS_ONLN) +else + NPROC="$J" +fi + FLAGS="$SPFLAGS -very_quiet" # spatch only allows include directories with the syntax "-I include" @@ -69,12 +78,28 @@ if [ "$ONLINE" = "0" ] ; then fi run_cmd() { + local i if [ $VERBOSE -ne 0 ] ; then - echo "Running: $@" + echo "Running ($NPROC in parallel): $@" fi - eval $@ + for i in $(seq 0 $(( NPROC - 1)) ); do + eval "$@ -max $NPROC -index $i &" + SPATCH_PID[$i]=$! + if [ $VERBOSE -eq 2 ] ; then + echo "${SPATCH_PID[$i]} running" + fi + done + wait } +kill_running() { + for i in $(seq $(( NPROC - 1 )) ); do + if [ $VERBOSE -eq 2 ] ; then + echo "Killing ${SPATCH_PID[$i]}" + fi + kill ${SPATCH_PID[$i]} 2>/dev/null + done +} coccinelle () { COCCI="$1" -- GitLab From 4b92b2aa98d917a379512b82cf94ea1ffcfc97af Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Thu, 20 Jun 2013 13:10:55 +0200 Subject: [PATCH 2233/2900] Coccinelle: Update section of MAINTAINERS Add Documentation/coccinelle.txt in the COCCINELLE section. Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 73b1b3a38ff0..2d940510f42b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2103,6 +2103,7 @@ L: cocci@systeme.lip6.fr (moderated for non-subscribers) T: git git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git misc W: http://coccinelle.lip6.fr/ S: Supported +F: Documentation/coccinelle.txt F: scripts/coccinelle/ F: scripts/coccicheck -- GitLab From 78a95b9b4b3dcb53736a1834e8557d3e1668562a Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Thu, 20 Jun 2013 14:00:19 +0200 Subject: [PATCH 2234/2900] Coccinelle: Update the documentation - The new default mode is 'report'. - The available modes are detailed a bit more. - Some information about the use of spatch options are also given concerning the use of indexing tools. Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- Documentation/coccinelle.txt | 39 ++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Documentation/coccinelle.txt b/Documentation/coccinelle.txt index 408439d07889..81a329fcd532 100644 --- a/Documentation/coccinelle.txt +++ b/Documentation/coccinelle.txt @@ -48,7 +48,7 @@ A Coccinelle-specific target is defined in the top level Makefile. This target is named 'coccicheck' and calls the 'coccicheck' front-end in the 'scripts' directory. -Four modes are defined: patch, report, context, and org. The mode to +Four basic modes are defined: patch, report, context, and org. The mode to use is specified by setting the MODE variable with 'MODE='. 'patch' proposes a fix, when possible. @@ -62,18 +62,24 @@ diff-like style.Lines of interest are indicated with '-'. 'org' generates a report in the Org mode format of Emacs. Note that not all semantic patches implement all modes. For easy use -of Coccinelle, the default mode is "chain" which tries the previous -modes in the order above until one succeeds. +of Coccinelle, the default mode is "report". -To make a report for every semantic patch, run the following command: +Two other modes provide some common combinations of these modes. - make coccicheck MODE=report +'chain' tries the previous modes in the order above until one succeeds. -NB: The 'report' mode is the default one. +'rep+ctxt' runs successively the report mode and the context mode. + It should be used with the C option (described later) + which checks the code on a file basis. -To produce patches, run: +Examples: + To make a report for every semantic patch, run the following command: - make coccicheck MODE=patch + make coccicheck MODE=report + + To produce patches, run: + + make coccicheck MODE=patch The coccicheck target applies every semantic patch available in the @@ -129,26 +135,33 @@ To check only newly edited code, use the value 2 for the C flag, i.e. make C=2 CHECK="scripts/coccicheck" +In these modes, which works on a file basis, there is no information +about semantic patches displayed, and no commit message proposed. + This runs every semantic patch in scripts/coccinelle by default. The COCCI variable may additionally be used to only apply a single semantic patch as shown in the previous section. -The "chain" mode is the default. You can select another one with the +The "report" mode is the default. You can select another one with the MODE variable explained above. -In this mode, there is no information about semantic patches -displayed, and no commit message proposed. - Additional flags ~~~~~~~~~~~~~~~~~~ Additional flags can be passed to spatch through the SPFLAGS variable. - make SPFLAGS=--use_glimpse coccicheck + make SPFLAGS=--use-glimpse coccicheck + make SPFLAGS=--use-idutils coccicheck See spatch --help to learn more about spatch options. +Note that the '--use-glimpse' and '--use-idutils' options +require external tools for indexing the code. None of them is +thus active by default. However, by indexing the code with +one of these tools, and according to the cocci file used, +spatch could proceed the entire code base more quickly. + Proposing new semantic patches ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- GitLab From f7b167113753e95ae61383e234f8d10142782ace Mon Sep 17 00:00:00 2001 From: "strnape1@fel.cvut.cz" Date: Wed, 8 May 2013 23:03:08 +0200 Subject: [PATCH 2235/2900] scripts: Coccinelle script for pci_free_consistent() Created coccinelle script for reporting missing pci_free_consistent() calls. Signed-off-by: Petr Strnad Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- .../coccinelle/free/pci_free_consistent.cocci | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 scripts/coccinelle/free/pci_free_consistent.cocci diff --git a/scripts/coccinelle/free/pci_free_consistent.cocci b/scripts/coccinelle/free/pci_free_consistent.cocci new file mode 100644 index 000000000000..43600ccb62a8 --- /dev/null +++ b/scripts/coccinelle/free/pci_free_consistent.cocci @@ -0,0 +1,52 @@ +/// Find missing pci_free_consistent for every pci_alloc_consistent. +/// +// Confidence: Moderate +// Copyright: (C) 2013 Petr Strnad. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Keywords: pci_free_consistent, pci_alloc_consistent +// Options: --no-includes --include-headers + +virtual report +virtual org + +@search@ +local idexpression id; +expression x,y,z,e; +position p1,p2; +type T; +@@ + +id = pci_alloc_consistent@p1(x,y,&z) +... when != e = id +if (id == NULL || ...) { ... return ...; } +... when != pci_free_consistent(x,y,id,z) + when != if (id) { ... pci_free_consistent(x,y,id,z) ... } + when != if (y) { ... pci_free_consistent(x,y,id,z) ... } + when != e = (T)id + when exists +( +return 0; +| +return 1; +| +return id; +| +return@p2 ...; +) + +@script:python depends on report@ +p1 << search.p1; +p2 << search.p2; +@@ + +msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line) +coccilib.report.print_report(p2[0],msg) + +@script:python depends on org@ +p1 << search.p1; +p2 << search.p2; +@@ + +msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line) +cocci.print_main(msg,p1) +cocci.print_secs("",p2) -- GitLab From b35310627f396efcc25d71fb343b3aa02039d20d Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Tue, 25 Jun 2013 20:13:37 -0500 Subject: [PATCH 2236/2900] tools/include: use stdint types for user-space byteshift headers Commit a07f7672d7cf0ff0d6e548a9feb6e0bd016d9c6c added user-space copies of the byteshift headers to be used by hostprogs, changing e.g. u8 to __u8. However, in order to cross-compile the kernel from a non-Linux system, stdint.h types need to be used instead of linux/types.h types. Signed-off-by: Yaakov Selkowitz Signed-off-by: Michal Marek --- tools/include/tools/be_byteshift.h | 34 +++++++++++++++--------------- tools/include/tools/le_byteshift.h | 34 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/tools/include/tools/be_byteshift.h b/tools/include/tools/be_byteshift.h index f4912e2668ba..84c17d836578 100644 --- a/tools/include/tools/be_byteshift.h +++ b/tools/include/tools/be_byteshift.h @@ -1,68 +1,68 @@ #ifndef _TOOLS_BE_BYTESHIFT_H #define _TOOLS_BE_BYTESHIFT_H -#include +#include -static inline __u16 __get_unaligned_be16(const __u8 *p) +static inline uint16_t __get_unaligned_be16(const uint8_t *p) { return p[0] << 8 | p[1]; } -static inline __u32 __get_unaligned_be32(const __u8 *p) +static inline uint32_t __get_unaligned_be32(const uint8_t *p) { return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; } -static inline __u64 __get_unaligned_be64(const __u8 *p) +static inline uint64_t __get_unaligned_be64(const uint8_t *p) { - return (__u64)__get_unaligned_be32(p) << 32 | + return (uint64_t)__get_unaligned_be32(p) << 32 | __get_unaligned_be32(p + 4); } -static inline void __put_unaligned_be16(__u16 val, __u8 *p) +static inline void __put_unaligned_be16(uint16_t val, uint8_t *p) { *p++ = val >> 8; *p++ = val; } -static inline void __put_unaligned_be32(__u32 val, __u8 *p) +static inline void __put_unaligned_be32(uint32_t val, uint8_t *p) { __put_unaligned_be16(val >> 16, p); __put_unaligned_be16(val, p + 2); } -static inline void __put_unaligned_be64(__u64 val, __u8 *p) +static inline void __put_unaligned_be64(uint64_t val, uint8_t *p) { __put_unaligned_be32(val >> 32, p); __put_unaligned_be32(val, p + 4); } -static inline __u16 get_unaligned_be16(const void *p) +static inline uint16_t get_unaligned_be16(const void *p) { - return __get_unaligned_be16((const __u8 *)p); + return __get_unaligned_be16((const uint8_t *)p); } -static inline __u32 get_unaligned_be32(const void *p) +static inline uint32_t get_unaligned_be32(const void *p) { - return __get_unaligned_be32((const __u8 *)p); + return __get_unaligned_be32((const uint8_t *)p); } -static inline __u64 get_unaligned_be64(const void *p) +static inline uint64_t get_unaligned_be64(const void *p) { - return __get_unaligned_be64((const __u8 *)p); + return __get_unaligned_be64((const uint8_t *)p); } -static inline void put_unaligned_be16(__u16 val, void *p) +static inline void put_unaligned_be16(uint16_t val, void *p) { __put_unaligned_be16(val, p); } -static inline void put_unaligned_be32(__u32 val, void *p) +static inline void put_unaligned_be32(uint32_t val, void *p) { __put_unaligned_be32(val, p); } -static inline void put_unaligned_be64(__u64 val, void *p) +static inline void put_unaligned_be64(uint64_t val, void *p) { __put_unaligned_be64(val, p); } diff --git a/tools/include/tools/le_byteshift.h b/tools/include/tools/le_byteshift.h index c99d45a68bda..8fe9f2488ec7 100644 --- a/tools/include/tools/le_byteshift.h +++ b/tools/include/tools/le_byteshift.h @@ -1,68 +1,68 @@ #ifndef _TOOLS_LE_BYTESHIFT_H #define _TOOLS_LE_BYTESHIFT_H -#include +#include -static inline __u16 __get_unaligned_le16(const __u8 *p) +static inline uint16_t __get_unaligned_le16(const uint8_t *p) { return p[0] | p[1] << 8; } -static inline __u32 __get_unaligned_le32(const __u8 *p) +static inline uint32_t __get_unaligned_le32(const uint8_t *p) { return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; } -static inline __u64 __get_unaligned_le64(const __u8 *p) +static inline uint64_t __get_unaligned_le64(const uint8_t *p) { - return (__u64)__get_unaligned_le32(p + 4) << 32 | + return (uint64_t)__get_unaligned_le32(p + 4) << 32 | __get_unaligned_le32(p); } -static inline void __put_unaligned_le16(__u16 val, __u8 *p) +static inline void __put_unaligned_le16(uint16_t val, uint8_t *p) { *p++ = val; *p++ = val >> 8; } -static inline void __put_unaligned_le32(__u32 val, __u8 *p) +static inline void __put_unaligned_le32(uint32_t val, uint8_t *p) { __put_unaligned_le16(val >> 16, p + 2); __put_unaligned_le16(val, p); } -static inline void __put_unaligned_le64(__u64 val, __u8 *p) +static inline void __put_unaligned_le64(uint64_t val, uint8_t *p) { __put_unaligned_le32(val >> 32, p + 4); __put_unaligned_le32(val, p); } -static inline __u16 get_unaligned_le16(const void *p) +static inline uint16_t get_unaligned_le16(const void *p) { - return __get_unaligned_le16((const __u8 *)p); + return __get_unaligned_le16((const uint8_t *)p); } -static inline __u32 get_unaligned_le32(const void *p) +static inline uint32_t get_unaligned_le32(const void *p) { - return __get_unaligned_le32((const __u8 *)p); + return __get_unaligned_le32((const uint8_t *)p); } -static inline __u64 get_unaligned_le64(const void *p) +static inline uint64_t get_unaligned_le64(const void *p) { - return __get_unaligned_le64((const __u8 *)p); + return __get_unaligned_le64((const uint8_t *)p); } -static inline void put_unaligned_le16(__u16 val, void *p) +static inline void put_unaligned_le16(uint16_t val, void *p) { __put_unaligned_le16(val, p); } -static inline void put_unaligned_le32(__u32 val, void *p) +static inline void put_unaligned_le32(uint32_t val, void *p) { __put_unaligned_le32(val, p); } -static inline void put_unaligned_le64(__u64 val, void *p) +static inline void put_unaligned_le64(uint64_t val, void *p) { __put_unaligned_le64(val, p); } -- GitLab From c1b40e447af8695666d4c11cfec4a7407e6a124d Mon Sep 17 00:00:00 2001 From: Stuart Menefy Date: Wed, 26 Jun 2013 12:48:38 +0100 Subject: [PATCH 2237/2900] clocksource: arm_global_timer: Add ARM global timer support This is a simple driver for the global timer module found in the Cortex A9-MP cores from revision r1p0 onwards. This should be able to perform the functions of the system timer and the local timer in an SMP system. The global timer has the following features: The global timer is a 64-bit incrementing counter with an auto-incrementing feature. It continues incrementing after sending interrupts. The global timer is memory mapped in the private memory region. The global timer is accessible to all Cortex-A9 processors in the cluster. Each Cortex-A9 processor has a private 64-bit comparator that is used to assert a private interrupt when the global timer has reached the comparator value. All the Cortex-A9 processors in a design use the banked ID, ID27, for this interrupt. ID27 is sent to the Interrupt Controller as a Private Peripheral Interrupt. The global timer is clocked by PERIPHCLK. Signed-off-by: Stuart Menefy Signed-off-by: Srinivas Kandagatla CC: Arnd Bergmann CC: Rob Herring CC: Linus Walleij CC: Will Deacon CC: Thomas Gleixner Signed-off-by: Daniel Lezcano --- .../devicetree/bindings/arm/global_timer.txt | 24 ++ drivers/clocksource/Kconfig | 13 + drivers/clocksource/Makefile | 1 + drivers/clocksource/arm_global_timer.c | 321 ++++++++++++++++++ 4 files changed, 359 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/global_timer.txt create mode 100644 drivers/clocksource/arm_global_timer.c diff --git a/Documentation/devicetree/bindings/arm/global_timer.txt b/Documentation/devicetree/bindings/arm/global_timer.txt new file mode 100644 index 000000000000..1e548981eda4 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/global_timer.txt @@ -0,0 +1,24 @@ + +* ARM Global Timer + Cortex-A9 are often associated with a per-core Global timer. + +** Timer node required properties: + +- compatible : Should be "arm,cortex-a9-global-timer" + Driver supports versions r2p0 and above. + +- interrupts : One interrupt to each core + +- reg : Specify the base address and the size of the GT timer + register window. + +- clocks : Should be phandle to a clock. + +Example: + + timer@2c000600 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0x2c000600 0x20>; + interrupts = <1 13 0xf01>; + clocks = <&arm_periph_clk>; + }; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c082e3e4bd0a..42c8eccb1e86 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -72,6 +72,19 @@ config ARM_ARCH_TIMER bool select CLKSRC_OF if OF +config ARM_GLOBAL_TIMER + bool + select CLKSRC_OF if OF + help + This options enables support for the ARM global timer unit + +config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK + bool + depends on ARM_GLOBAL_TIMER + default y + help + Use ARM global timer clock source as sched_clock + config CLKSRC_METAG_GENERIC def_bool y if METAG help diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 49bea7fad85c..8b00c5cebfa4 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -31,5 +31,6 @@ obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o +obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c new file mode 100644 index 000000000000..db8afc7427a6 --- /dev/null +++ b/drivers/clocksource/arm_global_timer.c @@ -0,0 +1,321 @@ +/* + * drivers/clocksource/arm_global_timer.c + * + * Copyright (C) 2013 STMicroelectronics (R&D) Limited. + * Author: Stuart Menefy + * Author: Srinivas Kandagatla + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define GT_COUNTER0 0x00 +#define GT_COUNTER1 0x04 + +#define GT_CONTROL 0x08 +#define GT_CONTROL_TIMER_ENABLE BIT(0) /* this bit is NOT banked */ +#define GT_CONTROL_COMP_ENABLE BIT(1) /* banked */ +#define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */ +#define GT_CONTROL_AUTO_INC BIT(3) /* banked */ + +#define GT_INT_STATUS 0x0c +#define GT_INT_STATUS_EVENT_FLAG BIT(0) + +#define GT_COMP0 0x10 +#define GT_COMP1 0x14 +#define GT_AUTO_INC 0x18 + +/* + * We are expecting to be clocked by the ARM peripheral clock. + * + * Note: it is assumed we are using a prescaler value of zero, so this is + * the units for all operations. + */ +static void __iomem *gt_base; +static unsigned long gt_clk_rate; +static int gt_ppi; +static struct clock_event_device __percpu *gt_evt; + +/* + * To get the value from the Global Timer Counter register proceed as follows: + * 1. Read the upper 32-bit timer counter register + * 2. Read the lower 32-bit timer counter register + * 3. Read the upper 32-bit timer counter register again. If the value is + * different to the 32-bit upper value read previously, go back to step 2. + * Otherwise the 64-bit timer counter value is correct. + */ +static u64 gt_counter_read(void) +{ + u64 counter; + u32 lower; + u32 upper, old_upper; + + upper = readl_relaxed(gt_base + GT_COUNTER1); + do { + old_upper = upper; + lower = readl_relaxed(gt_base + GT_COUNTER0); + upper = readl_relaxed(gt_base + GT_COUNTER1); + } while (upper != old_upper); + + counter = upper; + counter <<= 32; + counter |= lower; + return counter; +} + +/** + * To ensure that updates to comparator value register do not set the + * Interrupt Status Register proceed as follows: + * 1. Clear the Comp Enable bit in the Timer Control Register. + * 2. Write the lower 32-bit Comparator Value Register. + * 3. Write the upper 32-bit Comparator Value Register. + * 4. Set the Comp Enable bit and, if necessary, the IRQ enable bit. + */ +static void gt_compare_set(unsigned long delta, int periodic) +{ + u64 counter = gt_counter_read(); + unsigned long ctrl; + + counter += delta; + ctrl = GT_CONTROL_TIMER_ENABLE; + writel(ctrl, gt_base + GT_CONTROL); + writel(lower_32_bits(counter), gt_base + GT_COMP0); + writel(upper_32_bits(counter), gt_base + GT_COMP1); + + if (periodic) { + writel(delta, gt_base + GT_AUTO_INC); + ctrl |= GT_CONTROL_AUTO_INC; + } + + ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE; + writel(ctrl, gt_base + GT_CONTROL); +} + +static void gt_clockevent_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + unsigned long ctrl; + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1); + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + ctrl = readl(gt_base + GT_CONTROL); + ctrl &= ~(GT_CONTROL_COMP_ENABLE | + GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC); + writel(ctrl, gt_base + GT_CONTROL); + break; + default: + break; + } +} + +static int gt_clockevent_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + gt_compare_set(evt, 0); + return 0; +} + +static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + if (!(readl_relaxed(gt_base + GT_INT_STATUS) & + GT_INT_STATUS_EVENT_FLAG)) + return IRQ_NONE; + + /** + * ERRATA 740657( Global Timer can send 2 interrupts for + * the same event in single-shot mode) + * Workaround: + * Either disable single-shot mode. + * Or + * Modify the Interrupt Handler to avoid the + * offending sequence. This is achieved by clearing + * the Global Timer flag _after_ having incremented + * the Comparator register value to a higher value. + */ + if (evt->mode == CLOCK_EVT_MODE_ONESHOT) + gt_compare_set(ULONG_MAX, 0); + + writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static int __cpuinit gt_clockevents_init(struct clock_event_device *clk) +{ + int cpu = smp_processor_id(); + + clk->name = "arm_global_timer"; + clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + clk->set_mode = gt_clockevent_set_mode; + clk->set_next_event = gt_clockevent_set_next_event; + clk->cpumask = cpumask_of(cpu); + clk->rating = 300; + clk->irq = gt_ppi; + clockevents_config_and_register(clk, gt_clk_rate, + 1, 0xffffffff); + enable_percpu_irq(clk->irq, IRQ_TYPE_NONE); + return 0; +} + +static void gt_clockevents_stop(struct clock_event_device *clk) +{ + gt_clockevent_set_mode(CLOCK_EVT_MODE_UNUSED, clk); + disable_percpu_irq(clk->irq); +} + +static cycle_t gt_clocksource_read(struct clocksource *cs) +{ + return gt_counter_read(); +} + +static struct clocksource gt_clocksource = { + .name = "arm_global_timer", + .rating = 300, + .read = gt_clocksource_read, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK +static u32 notrace gt_sched_clock_read(void) +{ + return gt_counter_read(); +} +#endif + +static void __init gt_clocksource_init(void) +{ + writel(0, gt_base + GT_CONTROL); + writel(0, gt_base + GT_COUNTER0); + writel(0, gt_base + GT_COUNTER1); + /* enables timer on all the cores */ + writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); + +#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK + setup_sched_clock(gt_sched_clock_read, 32, gt_clk_rate); +#endif + clocksource_register_hz(>_clocksource, gt_clk_rate); +} + +static int __cpuinit gt_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + gt_clockevents_init(this_cpu_ptr(gt_evt)); + break; + case CPU_DYING: + gt_clockevents_stop(this_cpu_ptr(gt_evt)); + break; + } + + return NOTIFY_OK; +} +static struct notifier_block gt_cpu_nb __cpuinitdata = { + .notifier_call = gt_cpu_notify, +}; + +static void __init global_timer_of_register(struct device_node *np) +{ + struct clk *gt_clk; + int err = 0; + + /* + * In r2p0 the comparators for each processor with the global timer + * fire when the timer value is greater than or equal to. In previous + * revisions the comparators fired when the timer value was equal to. + */ + if ((read_cpuid_id() & 0xf0000f) < 0x200000) { + pr_warn("global-timer: non support for this cpu version.\n"); + return; + } + + gt_ppi = irq_of_parse_and_map(np, 0); + if (!gt_ppi) { + pr_warn("global-timer: unable to parse irq\n"); + return; + } + + gt_base = of_iomap(np, 0); + if (!gt_base) { + pr_warn("global-timer: invalid base address\n"); + return; + } + + gt_clk = of_clk_get(np, 0); + if (!IS_ERR(gt_clk)) { + err = clk_prepare_enable(gt_clk); + if (err) + goto out_unmap; + } else { + pr_warn("global-timer: clk not found\n"); + err = -EINVAL; + goto out_unmap; + } + + gt_clk_rate = clk_get_rate(gt_clk); + gt_evt = alloc_percpu(struct clock_event_device); + if (!gt_evt) { + pr_warn("global-timer: can't allocate memory\n"); + err = -ENOMEM; + goto out_clk; + } + + err = request_percpu_irq(gt_ppi, gt_clockevent_interrupt, + "gt", gt_evt); + if (err) { + pr_warn("global-timer: can't register interrupt %d (%d)\n", + gt_ppi, err); + goto out_free; + } + + err = register_cpu_notifier(>_cpu_nb); + if (err) { + pr_warn("global-timer: unable to register cpu notifier.\n"); + goto out_irq; + } + + /* Immediately configure the timer on the boot CPU */ + gt_clocksource_init(); + gt_clockevents_init(this_cpu_ptr(gt_evt)); + + return; + +out_irq: + free_percpu_irq(gt_ppi, gt_evt); +out_free: + free_percpu(gt_evt); +out_clk: + clk_disable_unprepare(gt_clk); +out_unmap: + iounmap(gt_base); + WARN(err, "ARM Global timer register failed (%d)\n", err); +} + +/* Only tested on r2p2 and r3p0 */ +CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer", + global_timer_of_register); -- GitLab From 90068348b7566c83efbf1985d7853a831aabfaf4 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Mon, 24 Jun 2013 16:50:55 +0530 Subject: [PATCH 2238/2900] regulator: s2mps11: Convert ramp rate to uV/us and set default ramp rate This patch makes driver to use uV/us as units of ramp_delay. It makes driver in compliance with regulator framework and make ramp rate precise. This patch also sets default ramp rate in regulator descriptor which can be used in case if case ramp rate is not set in regulator constraints. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 7 ++++++- include/linux/mfd/samsung/s2mps11.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index c9f16e17920f..2f62564ca936 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -42,7 +42,7 @@ static int get_ramp_delay(int ramp_delay) { unsigned char cnt = 0; - ramp_delay /= 6; + ramp_delay /= 6250; while (true) { ramp_delay = ramp_delay >> 1; @@ -113,6 +113,7 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN1, \ .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B1CTRL2 + (num - 1) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B1CTRL1 + (num - 1) * 2, \ @@ -128,6 +129,7 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN1, \ .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B5CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B5CTRL1, \ @@ -143,6 +145,7 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN1, \ .uV_step = S2MPS11_BUCK_STEP1, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B6CTRL2 + (num - 6) * 2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B6CTRL1 + (num - 6) * 2, \ @@ -158,6 +161,7 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN3, \ .uV_step = S2MPS11_BUCK_STEP3, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B9CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B9CTRL1, \ @@ -173,6 +177,7 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN2, \ .uV_step = S2MPS11_BUCK_STEP2, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ + .ramp_delay = S2MPS11_RAMP_DELAY, \ .vsel_reg = S2MPS11_REG_B10CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ .enable_reg = S2MPS11_REG_B10CTRL1, \ diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index ad2252f239d7..4e94dc65f987 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -189,6 +189,7 @@ enum s2mps11_regulators { #define S2MPS11_ENABLE_SHIFT 0x06 #define S2MPS11_LDO_N_VOLTAGES (S2MPS11_LDO_VSEL_MASK + 1) #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) +#define S2MPS11_RAMP_DELAY 25000 /* uV/us */ #define S2MPS11_PMIC_EN_SHIFT 6 #define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3) -- GitLab From f91d1b63a4e096d3023aaaafec9d9d3aff25997f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 1 Jul 2013 17:40:00 +0100 Subject: [PATCH 2239/2900] iio: inkern: fix iio_convert_raw_to_processed_unlocked When reading IIO_CHAN_INFO_OFFSET, the return value of iio_channel_read() for success will be IIO_VAL*, checking for 0 is not correct. Without this fix the offset applied by iio drivers will be ignored when converting a raw value to one in appropriate base units (e.g mV) in a IIO client drivers that use iio_convert_raw_to_processed including iio-hwmon. Cc: # 3.10.x Signed-off-by: Alexandre Belloni Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 98ddc323add0..0cf5f8e06cfc 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -451,7 +451,7 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, int ret; ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET); - if (ret == 0) + if (ret >= 0) raw64 += offset; scale_type = iio_channel_read(chan, &scale_val, &scale_val2, -- GitLab From e1b1fa66a0398f0b52ae79a2bdc7de87c205d074 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 29 Jun 2013 22:20:00 +0100 Subject: [PATCH 2240/2900] iio: mxs-lradc: Fix misuse of iio->trig The struct iio_dev .trig field is to be used only by the IIO core, the driver shall not fill this field. This fixes ugly crash when the driver is compiled as a module and the module is rmmod'd. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Jonathan Cameron Cc: Shawn Guo Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/mxs-lradc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index d92c97a59d61..c5edf1cad07a 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -661,12 +661,13 @@ static int mxs_lradc_trigger_init(struct iio_dev *iio) { int ret; struct iio_trigger *trig; + struct mxs_lradc *lradc = iio_priv(iio); trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id); if (trig == NULL) return -ENOMEM; - trig->dev.parent = iio->dev.parent; + trig->dev.parent = lradc->dev; iio_trigger_set_drvdata(trig, iio); trig->ops = &mxs_lradc_trigger_ops; @@ -676,15 +677,17 @@ static int mxs_lradc_trigger_init(struct iio_dev *iio) return ret; } - iio->trig = trig; + lradc->trig = trig; return 0; } static void mxs_lradc_trigger_remove(struct iio_dev *iio) { - iio_trigger_unregister(iio->trig); - iio_trigger_free(iio->trig); + struct mxs_lradc *lradc = iio_priv(iio); + + iio_trigger_unregister(lradc->trig); + iio_trigger_free(lradc->trig); } static int mxs_lradc_buffer_preenable(struct iio_dev *iio) -- GitLab From 4d47dde47f7dd95042fa56283d948f50dd4b509c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BF=A0=E5=B1=B1?= Date: Sun, 30 Jun 2013 17:09:28 +0800 Subject: [PATCH 2241/2900] kbuild: create directory for dir/file.o MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When add a obj with dir to obj-y, like this obj-y += dir/file.o The $(obj)/dir not created, this patch fix this. When try to add a file(which in a subdir) to my board's obj-y, the build progress crashed. For example, I use at91rm9200ek board, and in kernel dir run: mkdir objtree make O=objtree at91rm9200_defconfig mkdir arch/arm/mach-at91/dir touch arch/arm/mach-at91/dir/file.c and edit arch/arm/mach-at91/dir/file.c to add some code. then edit arch/arm/mach-at91/Makefile, change the following line: obj-$(CONFIG_MACH_AT91RM9200EK) += board-rm9200ek.o to: obj-$(CONFIG_MACH_AT91RM9200EK) += board-rm9200ek.o dir/file.o Now build it: make O=objtree Then the error appears: ... CC arch/arm/mach-at91/board-rm9200dk.o CC arch/arm/mach-at91/board-rm9200ek.o CC arch/arm/mach-at91/dir/file.o linux-2.6/arch/arm/mach-at91/dir/file.c:5: fatal error: opening dependency file arch/arm/mach-at91/dir/.file.o.d: No such file or directory Check the objtree: LANG=en ls objtree/arch/arm/mach-at91/dir ls: cannot access objtree/arch/arm/mach-at91/dir: No such file or directory It's apparently that the target dir not created for file.o Check kbuild source code. It seems that kbuild create dirs for that in $(obj-dirs). But if the dir need not to create a built-in.o, It should never in $(obj-dirs). So I make this patch to make sure It in $(obj-dirs) this bug caused by commit f5fb976520a53f45f8bbf2e851f16b3b5558d485 Signed-off-by: 张忠山 Signed-off-by: Michal Marek --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index e5c81aa60778..a5c05ae95225 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -63,7 +63,7 @@ multi-objs := $(multi-objs-y) $(multi-objs-m) subdir-obj-y := $(filter %/built-in.o, $(obj-y)) # $(obj-dirs) is a list of directories that contain object files -obj-dirs := $(dir $(multi-objs) $(subdir-obj-y)) +obj-dirs := $(dir $(multi-objs) $(obj-y)) # Replace multi-part objects by their individual parts, look at local dir only real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) -- GitLab From 93f14468491747d6d3efd0b3a42785b1d51a127a Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Thu, 20 Jun 2013 13:10:56 +0200 Subject: [PATCH 2242/2900] Coccinelle: Update the options used to the new option scheme spatch has changed its option scheme. E.g., --no_show_diff is now --no-show-diff This patch updates: - scripts/coccicheck - Semantic patches under scripts/coccinelle/ Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- scripts/coccicheck | 28 +++++++++---------- .../api/alloc/drop_kmalloc_cast.cocci | 2 +- .../coccinelle/api/alloc/kzalloc-simple.cocci | 2 +- scripts/coccinelle/api/d_find_alias.cocci | 2 +- .../api/devm_request_and_ioremap.cocci | 2 +- scripts/coccinelle/api/kstrdup.cocci | 2 +- scripts/coccinelle/api/memdup.cocci | 2 +- scripts/coccinelle/api/memdup_user.cocci | 2 +- scripts/coccinelle/api/ptr_ret.cocci | 2 +- scripts/coccinelle/api/simple_open.cocci | 2 +- scripts/coccinelle/free/devm_free.cocci | 2 +- scripts/coccinelle/free/kfree.cocci | 2 +- scripts/coccinelle/free/kfreeaddr.cocci | 2 +- scripts/coccinelle/iterators/fen.cocci | 2 +- scripts/coccinelle/iterators/itnull.cocci | 2 +- .../iterators/list_entry_update.cocci | 2 +- .../coccinelle/iterators/use_after_iter.cocci | 2 +- scripts/coccinelle/locks/call_kern.cocci | 2 +- scripts/coccinelle/locks/double_lock.cocci | 2 +- scripts/coccinelle/locks/flags.cocci | 2 +- scripts/coccinelle/locks/mini_lock.cocci | 2 +- scripts/coccinelle/misc/boolinit.cocci | 2 +- scripts/coccinelle/misc/cstptr.cocci | 2 +- scripts/coccinelle/misc/doubleinit.cocci | 2 +- scripts/coccinelle/misc/ifaddr.cocci | 2 +- scripts/coccinelle/misc/ifcol.cocci | 2 +- scripts/coccinelle/misc/noderef.cocci | 2 +- scripts/coccinelle/misc/orplus.cocci | 2 +- scripts/coccinelle/misc/warn.cocci | 2 +- scripts/coccinelle/null/eno.cocci | 2 +- scripts/coccinelle/null/kmerr.cocci | 2 +- scripts/coccinelle/tests/doublebitand.cocci | 2 +- scripts/coccinelle/tests/doubletest.cocci | 2 +- scripts/coccinelle/tests/odd_ptr_err.cocci | 2 +- 34 files changed, 47 insertions(+), 47 deletions(-) diff --git a/scripts/coccicheck b/scripts/coccicheck index ad8e8ffd3c7e..d3757adb1260 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -20,7 +20,7 @@ else NPROC="$J" fi -FLAGS="$SPFLAGS -very_quiet" +FLAGS="$SPFLAGS --very-quiet" # spatch only allows include directories with the syntax "-I include" # while gcc also allows "-Iinclude" and "-include include" @@ -36,14 +36,14 @@ if [ "$C" = "1" -o "$C" = "2" ]; then else ONLINE=0 if [ "$KBUILD_EXTMOD" = "" ] ; then - OPTIONS="-dir $srctree $COCCIINCLUDE" + OPTIONS="--dir $srctree $COCCIINCLUDE" else - OPTIONS="-dir $KBUILD_EXTMOD $COCCIINCLUDE" + OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE" fi fi if [ "$KBUILD_EXTMOD" != "" ] ; then - OPTIONS="-patch $srctree $OPTIONS" + OPTIONS="--patch $srctree $OPTIONS" fi if [ ! -x "$SPATCH" ]; then @@ -67,7 +67,7 @@ if [ "$MODE" = "chain" ] ; then echo 'All available modes will be tried (in that order): patch, report, context, org' fi elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then - FLAGS="$FLAGS -no_show_diff" + FLAGS="$FLAGS --no-show-diff" fi if [ "$ONLINE" = "0" ] ; then @@ -83,7 +83,7 @@ run_cmd() { echo "Running ($NPROC in parallel): $@" fi for i in $(seq 0 $(( NPROC - 1)) ); do - eval "$@ -max $NPROC -index $i &" + eval "$@ --max $NPROC --index $i &" SPATCH_PID[$i]=$! if [ $VERBOSE -eq 2 ] ; then echo "${SPATCH_PID[$i]} running" @@ -106,7 +106,7 @@ coccinelle () { OPT=`grep "Option" $COCCI | cut -d':' -f2` -# The option '-parse_cocci' can be used to syntactically check the SmPL files. +# The option '--parse-cocci' can be used to syntactically check the SmPL files. # # $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null @@ -147,20 +147,20 @@ coccinelle () { if [ "$MODE" = "chain" ] ; then run_cmd $SPATCH -D patch \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ + $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ run_cmd $SPATCH -D report \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ + $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || \ run_cmd $SPATCH -D context \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ + $FLAGS --cocci-file $COCCI $OPT $OPTIONS || \ run_cmd $SPATCH -D org \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 + $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff || exit 1 elif [ "$MODE" = "rep+ctxt" ] ; then run_cmd $SPATCH -D report \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff && \ + $FLAGS --cocci-file $COCCI $OPT $OPTIONS --no-show-diff && \ run_cmd $SPATCH -D context \ - $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 + $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 else - run_cmd $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 + run_cmd $SPATCH -D $MODE $FLAGS --cocci-file $COCCI $OPT $OPTIONS || exit 1 fi } diff --git a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci index 7d4771d449c3..bd5d08b882ee 100644 --- a/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci +++ b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci @@ -5,7 +5,7 @@ // Confidence: High // Copyright: 2009,2010 Nicolas Palix, DIKU. GPLv2. // URL: http://coccinelle.lip6.fr/ -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers // // Keywords: kmalloc, kzalloc, kcalloc // Version min: < 2.6.12 kmalloc diff --git a/scripts/coccinelle/api/alloc/kzalloc-simple.cocci b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci index 046b9b16f8f9..52c55e4fa67d 100644 --- a/scripts/coccinelle/api/alloc/kzalloc-simple.cocci +++ b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci @@ -9,7 +9,7 @@ // Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2. // Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/rules/kzalloc.html -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers // // Keywords: kmalloc, kzalloc // Version min: < 2.6.12 kmalloc diff --git a/scripts/coccinelle/api/d_find_alias.cocci b/scripts/coccinelle/api/d_find_alias.cocci index a9694a8d3e5a..9594c9f7eb8d 100644 --- a/scripts/coccinelle/api/d_find_alias.cocci +++ b/scripts/coccinelle/api/d_find_alias.cocci @@ -4,7 +4,7 @@ // // Confidence: Moderate // URL: http://coccinelle.lip6.fr/ -// Options: -include_headers +// Options: --include-headers virtual context virtual org diff --git a/scripts/coccinelle/api/devm_request_and_ioremap.cocci b/scripts/coccinelle/api/devm_request_and_ioremap.cocci index 46beb81406ab..562ec88b6352 100644 --- a/scripts/coccinelle/api/devm_request_and_ioremap.cocci +++ b/scripts/coccinelle/api/devm_request_and_ioremap.cocci @@ -10,7 +10,7 @@ // Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual org diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci index 07a74b2c6196..09cba54ed0cf 100644 --- a/scripts/coccinelle/api/kstrdup.cocci +++ b/scripts/coccinelle/api/kstrdup.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci index 4dceab6d54de..3d1aa71b7579 100644 --- a/scripts/coccinelle/api/memdup.cocci +++ b/scripts/coccinelle/api/memdup.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci index 2b131a8a1306..c606231b0e46 100644 --- a/scripts/coccinelle/api/memdup_user.cocci +++ b/scripts/coccinelle/api/memdup_user.cocci @@ -7,7 +7,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci index 15f076fdecbe..2274638d005b 100644 --- a/scripts/coccinelle/api/ptr_ret.cocci +++ b/scripts/coccinelle/api/ptr_ret.cocci @@ -5,7 +5,7 @@ // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers // // Keywords: ERR_PTR, PTR_ERR, PTR_RET // Version min: 2.6.39 diff --git a/scripts/coccinelle/api/simple_open.cocci b/scripts/coccinelle/api/simple_open.cocci index 05962f7be155..b67e174f3d95 100644 --- a/scripts/coccinelle/api/simple_open.cocci +++ b/scripts/coccinelle/api/simple_open.cocci @@ -4,7 +4,7 @@ /// // Confidence: High // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual report diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci index 0a1e36146d76..3d9349012bb3 100644 --- a/scripts/coccinelle/free/devm_free.cocci +++ b/scripts/coccinelle/free/devm_free.cocci @@ -18,7 +18,7 @@ // Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci index d9ae6d89c2f5..577b78056990 100644 --- a/scripts/coccinelle/free/kfree.cocci +++ b/scripts/coccinelle/free/kfree.cocci @@ -10,7 +10,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/free/kfreeaddr.cocci b/scripts/coccinelle/free/kfreeaddr.cocci index 662e997da834..ce8aacc314cb 100644 --- a/scripts/coccinelle/free/kfreeaddr.cocci +++ b/scripts/coccinelle/free/kfreeaddr.cocci @@ -4,7 +4,7 @@ // Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci index 0a40af828c43..48c152f224e1 100644 --- a/scripts/coccinelle/iterators/fen.cocci +++ b/scripts/coccinelle/iterators/fen.cocci @@ -7,7 +7,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci index 259899f6838e..f58732b56a40 100644 --- a/scripts/coccinelle/iterators/itnull.cocci +++ b/scripts/coccinelle/iterators/itnull.cocci @@ -11,7 +11,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/iterators/list_entry_update.cocci b/scripts/coccinelle/iterators/list_entry_update.cocci index b2967475679b..873f444e7137 100644 --- a/scripts/coccinelle/iterators/list_entry_update.cocci +++ b/scripts/coccinelle/iterators/list_entry_update.cocci @@ -9,7 +9,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/iterators/use_after_iter.cocci b/scripts/coccinelle/iterators/use_after_iter.cocci index 06284c57a951..f085f5968c52 100644 --- a/scripts/coccinelle/iterators/use_after_iter.cocci +++ b/scripts/coccinelle/iterators/use_after_iter.cocci @@ -11,7 +11,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci index 8f10b49603c3..669b24436248 100644 --- a/scripts/coccinelle/locks/call_kern.cocci +++ b/scripts/coccinelle/locks/call_kern.cocci @@ -9,7 +9,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/locks/double_lock.cocci b/scripts/coccinelle/locks/double_lock.cocci index 63b24e682fad..002752f97dca 100644 --- a/scripts/coccinelle/locks/double_lock.cocci +++ b/scripts/coccinelle/locks/double_lock.cocci @@ -8,7 +8,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci index 1c4ffe6fd846..debd70e46267 100644 --- a/scripts/coccinelle/locks/flags.cocci +++ b/scripts/coccinelle/locks/flags.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci index 3267d7410bd5..47f649b0ea87 100644 --- a/scripts/coccinelle/locks/mini_lock.cocci +++ b/scripts/coccinelle/locks/mini_lock.cocci @@ -11,7 +11,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/misc/boolinit.cocci b/scripts/coccinelle/misc/boolinit.cocci index 97ce41ce8135..b9abed49cd95 100644 --- a/scripts/coccinelle/misc/boolinit.cocci +++ b/scripts/coccinelle/misc/boolinit.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ -// Options: -include_headers +// Options: --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/misc/cstptr.cocci b/scripts/coccinelle/misc/cstptr.cocci index d42564484528..f0368b3d4563 100644 --- a/scripts/coccinelle/misc/cstptr.cocci +++ b/scripts/coccinelle/misc/cstptr.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci index cf74a00cf597..c0c3371d25e0 100644 --- a/scripts/coccinelle/misc/doubleinit.cocci +++ b/scripts/coccinelle/misc/doubleinit.cocci @@ -8,7 +8,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/ifaddr.cocci b/scripts/coccinelle/misc/ifaddr.cocci index 3e4089a77000..8aebd1875e75 100644 --- a/scripts/coccinelle/misc/ifaddr.cocci +++ b/scripts/coccinelle/misc/ifaddr.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/ifcol.cocci b/scripts/coccinelle/misc/ifcol.cocci index b7ed91dbeb95..d0d00ef1f12a 100644 --- a/scripts/coccinelle/misc/ifcol.cocci +++ b/scripts/coccinelle/misc/ifcol.cocci @@ -13,7 +13,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/noderef.cocci b/scripts/coccinelle/misc/noderef.cocci index c1707214e602..80a831c91161 100644 --- a/scripts/coccinelle/misc/noderef.cocci +++ b/scripts/coccinelle/misc/noderef.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/orplus.cocci b/scripts/coccinelle/misc/orplus.cocci index 4a28cef1484e..81fabf379390 100644 --- a/scripts/coccinelle/misc/orplus.cocci +++ b/scripts/coccinelle/misc/orplus.cocci @@ -7,7 +7,7 @@ // Copyright: (C) 2013 Gilles Muller, INRIA/LIP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual org virtual report diff --git a/scripts/coccinelle/misc/warn.cocci b/scripts/coccinelle/misc/warn.cocci index fda8c3558e4f..d2e5b6cedb84 100644 --- a/scripts/coccinelle/misc/warn.cocci +++ b/scripts/coccinelle/misc/warn.cocci @@ -5,7 +5,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci index ed961a1f7d11..9bd29aa83399 100644 --- a/scripts/coccinelle/null/eno.cocci +++ b/scripts/coccinelle/null/eno.cocci @@ -6,7 +6,7 @@ // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context diff --git a/scripts/coccinelle/null/kmerr.cocci b/scripts/coccinelle/null/kmerr.cocci index 949bf656c64c..5354a7903ccb 100644 --- a/scripts/coccinelle/null/kmerr.cocci +++ b/scripts/coccinelle/null/kmerr.cocci @@ -10,7 +10,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/tests/doublebitand.cocci b/scripts/coccinelle/tests/doublebitand.cocci index 9ba73d05a77e..72f1572aaec3 100644 --- a/scripts/coccinelle/tests/doublebitand.cocci +++ b/scripts/coccinelle/tests/doublebitand.cocci @@ -10,7 +10,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/tests/doubletest.cocci b/scripts/coccinelle/tests/doubletest.cocci index 13a2c0e8a4bf..78d74c22ca12 100644 --- a/scripts/coccinelle/tests/doubletest.cocci +++ b/scripts/coccinelle/tests/doubletest.cocci @@ -8,7 +8,7 @@ // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual context virtual org diff --git a/scripts/coccinelle/tests/odd_ptr_err.cocci b/scripts/coccinelle/tests/odd_ptr_err.cocci index e8dd8a6b28a2..cfe0a35cf2dd 100644 --- a/scripts/coccinelle/tests/odd_ptr_err.cocci +++ b/scripts/coccinelle/tests/odd_ptr_err.cocci @@ -7,7 +7,7 @@ // Copyright: (C) 2012 Gilles Muller, INRIA. GPLv2. // URL: http://coccinelle.lip6.fr/ // Comments: -// Options: -no_includes -include_headers +// Options: --no-includes --include-headers virtual patch virtual context -- GitLab From ec97946ed038f4b3faa587bc76152b198805b0c4 Mon Sep 17 00:00:00 2001 From: Nicolas Palix Date: Wed, 3 Jul 2013 16:41:01 +0200 Subject: [PATCH 2243/2900] Coccinelle: Update information about the minimal version required The naming convention of options has changed one year ago. The options have been recently updated in the cocci file and in scripts/coccicheck. This patch also adds this information in the documentation. Signed-off-by: Nicolas Palix Signed-off-by: Michal Marek --- Documentation/coccinelle.txt | 19 ++++++++----------- scripts/coccicheck | 5 +++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Documentation/coccinelle.txt b/Documentation/coccinelle.txt index 81a329fcd532..7f773d51fdd9 100644 --- a/Documentation/coccinelle.txt +++ b/Documentation/coccinelle.txt @@ -6,15 +6,17 @@ Copyright 2010 Gilles Muller Getting Coccinelle ~~~~~~~~~~~~~~~~~~~~ -The semantic patches included in the kernel use the 'virtual rule' -feature which was introduced in Coccinelle version 0.1.11. +The semantic patches included in the kernel use features and options +which are provided by Coccinelle version 1.0.0-rc11 and above. +Using earlier versions will fail as the option names used by +the Coccinelle files and coccicheck have been updated. -Coccinelle (>=0.2.0) is available through the package manager +Coccinelle is available through the package manager of many distributions, e.g. : - - Debian (>=squeeze) - - Fedora (>=13) - - Ubuntu (>=10.04 Lucid Lynx) + - Debian + - Fedora + - Ubuntu - OpenSUSE - Arch Linux - NetBSD @@ -36,11 +38,6 @@ as a regular user, and install it with sudo make install -The semantic patches in the kernel will work best with Coccinelle version -0.2.4 or later. Using earlier versions may incur some parse errors in the -semantic patch code, but any results that are obtained should still be -correct. - Using Coccinelle on the Linux kernel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/scripts/coccicheck b/scripts/coccicheck index d3757adb1260..bbf901afb606 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -1,5 +1,10 @@ #!/bin/bash +# +# This script requires at least spatch +# version 1.0.0-rc11. +# + SPATCH="`which ${SPATCH:=spatch}`" trap kill_running SIGTERM SIGINT -- GitLab From c50cd357887acf9fd7af3a5d492911bd825555a2 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 1 Jul 2013 19:24:00 +0200 Subject: [PATCH 2244/2900] net: gre: move GSO functions to gre_offload Similarly to TCP/UDP offloading, move all related GRE functions to gre_offload.c to make things more explicit and similar to the rest of the code. Suggested-by: Eric Dumazet Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/net/gre.h | 4 + net/ipv4/Makefile | 1 + net/ipv4/{gre.c => gre_demux.c} | 106 +------------------------- net/ipv4/gre_offload.c | 127 ++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 103 deletions(-) rename net/ipv4/{gre.c => gre_demux.c} (79%) create mode 100644 net/ipv4/gre_offload.c diff --git a/include/net/gre.h b/include/net/gre.h index a5a4ddf05300..57e4afdf7879 100644 --- a/include/net/gre.h +++ b/include/net/gre.h @@ -32,6 +32,10 @@ struct gre_cisco_protocol { int gre_cisco_register(struct gre_cisco_protocol *proto); int gre_cisco_unregister(struct gre_cisco_protocol *proto); + +int gre_offload_init(void); +void gre_offload_exit(void); + void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, int hdr_len); struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum); diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 86ded0bac9c7..4b81e91c80fe 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o obj-$(CONFIG_IP_MROUTE) += ipmr.o obj-$(CONFIG_NET_IPIP) += ipip.o +gre-y := gre_demux.o gre_offload.o obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o obj-$(CONFIG_NET_IPGRE) += ip_gre.o obj-$(CONFIG_NET_IPVTI) += ip_vti.o diff --git a/net/ipv4/gre.c b/net/ipv4/gre_demux.c similarity index 79% rename from net/ipv4/gre.c rename to net/ipv4/gre_demux.c index ba4803e609b5..736c9fc3ef93 100644 --- a/net/ipv4/gre.c +++ b/net/ipv4/gre_demux.c @@ -334,113 +334,12 @@ static void gre_err(struct sk_buff *skb, u32 info) rcu_read_unlock(); } -static struct sk_buff *gre_gso_segment(struct sk_buff *skb, - netdev_features_t features) -{ - struct sk_buff *segs = ERR_PTR(-EINVAL); - netdev_features_t enc_features; - int ghl = GRE_HEADER_SECTION; - struct gre_base_hdr *greh; - int mac_len = skb->mac_len; - __be16 protocol = skb->protocol; - int tnl_hlen; - bool csum; - - if (unlikely(skb_shinfo(skb)->gso_type & - ~(SKB_GSO_TCPV4 | - SKB_GSO_TCPV6 | - SKB_GSO_UDP | - SKB_GSO_DODGY | - SKB_GSO_TCP_ECN | - SKB_GSO_GRE))) - goto out; - - if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) - goto out; - - greh = (struct gre_base_hdr *)skb_transport_header(skb); - - if (greh->flags & GRE_KEY) - ghl += GRE_HEADER_SECTION; - if (greh->flags & GRE_SEQ) - ghl += GRE_HEADER_SECTION; - if (greh->flags & GRE_CSUM) { - ghl += GRE_HEADER_SECTION; - csum = true; - } else - csum = false; - - /* setup inner skb. */ - skb->protocol = greh->protocol; - skb->encapsulation = 0; - - if (unlikely(!pskb_may_pull(skb, ghl))) - goto out; - __skb_pull(skb, ghl); - skb_reset_mac_header(skb); - skb_set_network_header(skb, skb_inner_network_offset(skb)); - skb->mac_len = skb_inner_network_offset(skb); - - /* segment inner packet. */ - enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); - segs = skb_mac_gso_segment(skb, enc_features); - if (!segs || IS_ERR(segs)) - goto out; - - skb = segs; - tnl_hlen = skb_tnl_header_len(skb); - do { - __skb_push(skb, ghl); - if (csum) { - __be32 *pcsum; - - if (skb_has_shared_frag(skb)) { - int err; - - err = __skb_linearize(skb); - if (err) { - kfree_skb(segs); - segs = ERR_PTR(err); - goto out; - } - } - - greh = (struct gre_base_hdr *)(skb->data); - pcsum = (__be32 *)(greh + 1); - *pcsum = 0; - *(__sum16 *)pcsum = csum_fold(skb_checksum(skb, 0, skb->len, 0)); - } - __skb_push(skb, tnl_hlen - ghl); - - skb_reset_mac_header(skb); - skb_set_network_header(skb, mac_len); - skb->mac_len = mac_len; - skb->protocol = protocol; - } while ((skb = skb->next)); -out: - return segs; -} - -static int gre_gso_send_check(struct sk_buff *skb) -{ - if (!skb->encapsulation) - return -EINVAL; - return 0; -} - static const struct net_protocol net_gre_protocol = { .handler = gre_rcv, .err_handler = gre_err, .netns_ok = 1, }; -static const struct net_offload gre_offload = { - .callbacks = { - .gso_send_check = gre_gso_send_check, - .gso_segment = gre_gso_segment, - }, -}; - static const struct gre_protocol ipgre_protocol = { .handler = gre_cisco_rcv, .err_handler = gre_cisco_err, @@ -485,7 +384,7 @@ static int __init gre_init(void) goto err_gre; } - if (inet_add_offload(&gre_offload, IPPROTO_GRE)) { + if (gre_offload_init()) { pr_err("can't add protocol offload\n"); goto err_gso; } @@ -501,7 +400,8 @@ static int __init gre_init(void) static void __exit gre_exit(void) { - inet_del_offload(&gre_offload, IPPROTO_GRE); + gre_offload_exit(); + gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO); inet_del_protocol(&net_gre_protocol, IPPROTO_GRE); } diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c new file mode 100644 index 000000000000..a9d8cd2bff4b --- /dev/null +++ b/net/ipv4/gre_offload.c @@ -0,0 +1,127 @@ +/* + * IPV4 GSO/GRO offload support + * Linux INET implementation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * GRE GSO support + */ + +#include +#include +#include + +static int gre_gso_send_check(struct sk_buff *skb) +{ + if (!skb->encapsulation) + return -EINVAL; + return 0; +} + +static struct sk_buff *gre_gso_segment(struct sk_buff *skb, + netdev_features_t features) +{ + struct sk_buff *segs = ERR_PTR(-EINVAL); + netdev_features_t enc_features; + int ghl = GRE_HEADER_SECTION; + struct gre_base_hdr *greh; + int mac_len = skb->mac_len; + __be16 protocol = skb->protocol; + int tnl_hlen; + bool csum; + + if (unlikely(skb_shinfo(skb)->gso_type & + ~(SKB_GSO_TCPV4 | + SKB_GSO_TCPV6 | + SKB_GSO_UDP | + SKB_GSO_DODGY | + SKB_GSO_TCP_ECN | + SKB_GSO_GRE))) + goto out; + + if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) + goto out; + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + + if (greh->flags & GRE_KEY) + ghl += GRE_HEADER_SECTION; + if (greh->flags & GRE_SEQ) + ghl += GRE_HEADER_SECTION; + if (greh->flags & GRE_CSUM) { + ghl += GRE_HEADER_SECTION; + csum = true; + } else + csum = false; + + /* setup inner skb. */ + skb->protocol = greh->protocol; + skb->encapsulation = 0; + + if (unlikely(!pskb_may_pull(skb, ghl))) + goto out; + + __skb_pull(skb, ghl); + skb_reset_mac_header(skb); + skb_set_network_header(skb, skb_inner_network_offset(skb)); + skb->mac_len = skb_inner_network_offset(skb); + + /* segment inner packet. */ + enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); + segs = skb_mac_gso_segment(skb, enc_features); + if (!segs || IS_ERR(segs)) + goto out; + + skb = segs; + tnl_hlen = skb_tnl_header_len(skb); + do { + __skb_push(skb, ghl); + if (csum) { + __be32 *pcsum; + + if (skb_has_shared_frag(skb)) { + int err; + + err = __skb_linearize(skb); + if (err) { + kfree_skb(segs); + segs = ERR_PTR(err); + goto out; + } + } + + greh = (struct gre_base_hdr *)(skb->data); + pcsum = (__be32 *)(greh + 1); + *pcsum = 0; + *(__sum16 *)pcsum = csum_fold(skb_checksum(skb, 0, skb->len, 0)); + } + __skb_push(skb, tnl_hlen - ghl); + + skb_reset_mac_header(skb); + skb_set_network_header(skb, mac_len); + skb->mac_len = mac_len; + skb->protocol = protocol; + } while ((skb = skb->next)); +out: + return segs; +} + +static const struct net_offload gre_offload = { + .callbacks = { + .gso_send_check = gre_gso_send_check, + .gso_segment = gre_gso_segment, + }, +}; + +int __init gre_offload_init(void) +{ + return inet_add_offload(&gre_offload, IPPROTO_GRE); +} + +void __exit gre_offload_exit(void) +{ + inet_del_offload(&gre_offload, IPPROTO_GRE); +} -- GitLab From bc2bebe8de8ed4ba6482c9cc370b0dd72ffe8cd2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Jul 2013 21:48:11 +0200 Subject: [PATCH 2245/2900] alx: remove WoL support Unfortunately, WoL is broken and the system will immediately resume after suspending, and I can't seem to figure out why. Remove WoL support until the issue can be found. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/ethtool.c | 36 ----- drivers/net/ethernet/atheros/alx/hw.c | 155 --------------------- drivers/net/ethernet/atheros/alx/hw.h | 5 - drivers/net/ethernet/atheros/alx/main.c | 142 ++----------------- 4 files changed, 15 insertions(+), 323 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 926100626d60..45b36507abc1 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -201,40 +201,6 @@ static void alx_set_msglevel(struct net_device *netdev, u32 data) alx->msg_enable = data; } -static void alx_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct alx_priv *alx = netdev_priv(netdev); - struct alx_hw *hw = &alx->hw; - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = 0; - - if (hw->sleep_ctrl & ALX_SLEEP_WOL_MAGIC) - wol->wolopts |= WAKE_MAGIC; - if (hw->sleep_ctrl & ALX_SLEEP_WOL_PHY) - wol->wolopts |= WAKE_PHY; -} - -static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct alx_priv *alx = netdev_priv(netdev); - struct alx_hw *hw = &alx->hw; - - if (wol->wolopts & ~(WAKE_MAGIC | WAKE_PHY)) - return -EOPNOTSUPP; - - hw->sleep_ctrl = 0; - - if (wol->wolopts & WAKE_MAGIC) - hw->sleep_ctrl |= ALX_SLEEP_WOL_MAGIC; - if (wol->wolopts & WAKE_PHY) - hw->sleep_ctrl |= ALX_SLEEP_WOL_PHY; - - device_set_wakeup_enable(&alx->hw.pdev->dev, hw->sleep_ctrl); - - return 0; -} - const struct ethtool_ops alx_ethtool_ops = { .get_settings = alx_get_settings, .set_settings = alx_set_settings, @@ -242,7 +208,5 @@ const struct ethtool_ops alx_ethtool_ops = { .set_pauseparam = alx_set_pauseparam, .get_msglevel = alx_get_msglevel, .set_msglevel = alx_set_msglevel, - .get_wol = alx_get_wol, - .set_wol = alx_set_wol, .get_link = ethtool_op_get_link, }; diff --git a/drivers/net/ethernet/atheros/alx/hw.c b/drivers/net/ethernet/atheros/alx/hw.c index ea99e5d8743f..1e8c24a3cb4e 100644 --- a/drivers/net/ethernet/atheros/alx/hw.c +++ b/drivers/net/ethernet/atheros/alx/hw.c @@ -332,16 +332,6 @@ void alx_set_macaddr(struct alx_hw *hw, const u8 *addr) alx_write_mem32(hw, ALX_STAD1, val); } -static void alx_enable_osc(struct alx_hw *hw) -{ - u32 val; - - /* rising edge */ - val = alx_read_mem32(hw, ALX_MISC); - alx_write_mem32(hw, ALX_MISC, val & ~ALX_MISC_INTNLOSC_OPEN); - alx_write_mem32(hw, ALX_MISC, val | ALX_MISC_INTNLOSC_OPEN); -} - static void alx_reset_osc(struct alx_hw *hw, u8 rev) { u32 val, val2; @@ -858,66 +848,6 @@ void alx_post_phy_link(struct alx_hw *hw) } } - -/* NOTE: - * 1. phy link must be established before calling this function - * 2. wol option (pattern,magic,link,etc.) is configed before call it. - */ -int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex) -{ - u32 master, mac, phy, val; - int err = 0; - - master = alx_read_mem32(hw, ALX_MASTER); - master &= ~ALX_MASTER_PCLKSEL_SRDS; - mac = hw->rx_ctrl; - /* 10/100 half */ - ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED, ALX_MAC_CTRL_SPEED_10_100); - mac &= ~(ALX_MAC_CTRL_FULLD | ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_TX_EN); - - phy = alx_read_mem32(hw, ALX_PHY_CTRL); - phy &= ~(ALX_PHY_CTRL_DSPRST_OUT | ALX_PHY_CTRL_CLS); - phy |= ALX_PHY_CTRL_RST_ANALOG | ALX_PHY_CTRL_HIB_PULSE | - ALX_PHY_CTRL_HIB_EN; - - /* without any activity */ - if (!(hw->sleep_ctrl & ALX_SLEEP_ACTIVE)) { - err = alx_write_phy_reg(hw, ALX_MII_IER, 0); - if (err) - return err; - phy |= ALX_PHY_CTRL_IDDQ | ALX_PHY_CTRL_POWER_DOWN; - } else { - if (hw->sleep_ctrl & (ALX_SLEEP_WOL_MAGIC | ALX_SLEEP_CIFS)) - mac |= ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_BRD_EN; - if (hw->sleep_ctrl & ALX_SLEEP_CIFS) - mac |= ALX_MAC_CTRL_TX_EN; - if (duplex == DUPLEX_FULL) - mac |= ALX_MAC_CTRL_FULLD; - if (speed == SPEED_1000) - ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED, - ALX_MAC_CTRL_SPEED_1000); - phy |= ALX_PHY_CTRL_DSPRST_OUT; - err = alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, - ALX_MIIEXT_S3DIG10, - ALX_MIIEXT_S3DIG10_SL); - if (err) - return err; - } - - alx_enable_osc(hw); - hw->rx_ctrl = mac; - alx_write_mem32(hw, ALX_MASTER, master); - alx_write_mem32(hw, ALX_MAC_CTRL, mac); - alx_write_mem32(hw, ALX_PHY_CTRL, phy); - - /* set val of PDLL D3PLLOFF */ - val = alx_read_mem32(hw, ALX_PDLL_TRNS1); - val |= ALX_PDLL_TRNS1_D3PLLOFF_EN; - alx_write_mem32(hw, ALX_PDLL_TRNS1, val); - - return 0; -} - bool alx_phy_configured(struct alx_hw *hw) { u32 cfg, hw_cfg; @@ -990,26 +920,6 @@ int alx_clear_phy_intr(struct alx_hw *hw) return alx_read_phy_reg(hw, ALX_MII_ISR, &isr); } -int alx_config_wol(struct alx_hw *hw) -{ - u32 wol = 0; - int err = 0; - - /* turn on magic packet event */ - if (hw->sleep_ctrl & ALX_SLEEP_WOL_MAGIC) - wol |= ALX_WOL0_MAGIC_EN | ALX_WOL0_PME_MAGIC_EN; - - /* turn on link up event */ - if (hw->sleep_ctrl & ALX_SLEEP_WOL_PHY) { - wol |= ALX_WOL0_LINK_EN | ALX_WOL0_PME_LINK; - /* only link up can wake up */ - err = alx_write_phy_reg(hw, ALX_MII_IER, ALX_IER_LINK_UP); - } - alx_write_mem32(hw, ALX_WOL0, wol); - - return err; -} - void alx_disable_rss(struct alx_hw *hw) { u32 ctrl = alx_read_mem32(hw, ALX_RXQ0); @@ -1121,71 +1031,6 @@ void alx_configure_basic(struct alx_hw *hw) alx_write_mem32(hw, ALX_WRR, val); } -int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex) -{ - int i, err; - u16 lpa; - - err = alx_read_phy_link(hw); - if (err) - return err; - - if (hw->link_speed == SPEED_UNKNOWN) { - *speed = SPEED_UNKNOWN; - *duplex = DUPLEX_UNKNOWN; - return 0; - } - - err = alx_read_phy_reg(hw, MII_LPA, &lpa); - if (err) - return err; - - if (!(lpa & LPA_LPACK)) { - *speed = hw->link_speed; - return 0; - } - - if (lpa & LPA_10FULL) { - *speed = SPEED_10; - *duplex = DUPLEX_FULL; - } else if (lpa & LPA_10HALF) { - *speed = SPEED_10; - *duplex = DUPLEX_HALF; - } else if (lpa & LPA_100FULL) { - *speed = SPEED_100; - *duplex = DUPLEX_FULL; - } else { - *speed = SPEED_100; - *duplex = DUPLEX_HALF; - } - - if (*speed == hw->link_speed && *duplex == hw->duplex) - return 0; - err = alx_write_phy_reg(hw, ALX_MII_IER, 0); - if (err) - return err; - err = alx_setup_speed_duplex(hw, alx_speed_to_ethadv(*speed, *duplex) | - ADVERTISED_Autoneg, ALX_FC_ANEG | - ALX_FC_RX | ALX_FC_TX); - if (err) - return err; - - /* wait for linkup */ - for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) { - msleep(100); - - err = alx_read_phy_link(hw); - if (err < 0) - return err; - if (hw->link_speed != SPEED_UNKNOWN) - break; - } - if (i == ALX_MAX_SETUP_LNK_CYCLE) - return -ETIMEDOUT; - - return 0; -} - bool alx_get_phy_info(struct alx_hw *hw) { u16 devs1, devs2; diff --git a/drivers/net/ethernet/atheros/alx/hw.h b/drivers/net/ethernet/atheros/alx/hw.h index a60e35c1c1b5..96f3b4381e17 100644 --- a/drivers/net/ethernet/atheros/alx/hw.h +++ b/drivers/net/ethernet/atheros/alx/hw.h @@ -418,8 +418,6 @@ struct alx_hw { u8 flowctrl; u32 adv_cfg; - u32 sleep_ctrl; - spinlock_t mdio_lock; struct mdio_if_info mdio; u16 phy_id[2]; @@ -479,14 +477,12 @@ void alx_reset_pcie(struct alx_hw *hw); void alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en); int alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl); void alx_post_phy_link(struct alx_hw *hw); -int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex); int alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data); int alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data); int alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata); int alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data); int alx_read_phy_link(struct alx_hw *hw); int alx_clear_phy_intr(struct alx_hw *hw); -int alx_config_wol(struct alx_hw *hw); void alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc); void alx_start_mac(struct alx_hw *hw); int alx_reset_mac(struct alx_hw *hw); @@ -494,7 +490,6 @@ void alx_set_macaddr(struct alx_hw *hw, const u8 *addr); bool alx_phy_configured(struct alx_hw *hw); void alx_configure_basic(struct alx_hw *hw); void alx_disable_rss(struct alx_hw *hw); -int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex); bool alx_get_phy_info(struct alx_hw *hw); static inline u32 alx_speed_to_ethadv(int speed, u8 duplex) diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 148b4b976474..0e0b242a9dd4 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -706,7 +706,6 @@ static int alx_init_sw(struct alx_priv *alx) alx->rxbuf_size = ALIGN(ALX_RAW_MTU(hw->mtu), 8); alx->tx_ringsz = 256; alx->rx_ringsz = 512; - hw->sleep_ctrl = ALX_SLEEP_WOL_MAGIC | ALX_SLEEP_WOL_PHY; hw->imt = 200; alx->int_mask = ALX_ISR_MISC; hw->dma_chnl = hw->max_dma_chnl; @@ -961,66 +960,6 @@ static int alx_stop(struct net_device *netdev) return 0; } -static int __alx_shutdown(struct pci_dev *pdev, bool *wol_en) -{ - struct alx_priv *alx = pci_get_drvdata(pdev); - struct net_device *netdev = alx->dev; - struct alx_hw *hw = &alx->hw; - int err, speed; - u8 duplex; - - netif_device_detach(netdev); - - if (netif_running(netdev)) - __alx_stop(alx); - -#ifdef CONFIG_PM_SLEEP - err = pci_save_state(pdev); - if (err) - return err; -#endif - - err = alx_select_powersaving_speed(hw, &speed, &duplex); - if (err) - return err; - err = alx_clear_phy_intr(hw); - if (err) - return err; - err = alx_pre_suspend(hw, speed, duplex); - if (err) - return err; - err = alx_config_wol(hw); - if (err) - return err; - - *wol_en = false; - if (hw->sleep_ctrl & ALX_SLEEP_ACTIVE) { - netif_info(alx, wol, netdev, - "wol: ctrl=%X, speed=%X\n", - hw->sleep_ctrl, speed); - device_set_wakeup_enable(&pdev->dev, true); - *wol_en = true; - } - - pci_disable_device(pdev); - - return 0; -} - -static void alx_shutdown(struct pci_dev *pdev) -{ - int err; - bool wol_en; - - err = __alx_shutdown(pdev, &wol_en); - if (!err) { - pci_wake_from_d3(pdev, wol_en); - pci_set_power_state(pdev, PCI_D3hot); - } else { - dev_err(&pdev->dev, "shutdown fail %d\n", err); - } -} - static void alx_link_check(struct work_struct *work) { struct alx_priv *alx; @@ -1399,8 +1338,6 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_unmap; } - device_set_wakeup_enable(&pdev->dev, hw->sleep_ctrl); - netdev_info(netdev, "Qualcomm Atheros AR816x/AR817x Ethernet [%pM]\n", netdev->dev_addr); @@ -1445,22 +1382,12 @@ static void alx_remove(struct pci_dev *pdev) static int alx_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - int err; - bool wol_en; - - err = __alx_shutdown(pdev, &wol_en); - if (err) { - dev_err(&pdev->dev, "shutdown fail in suspend %d\n", err); - return err; - } - - if (wol_en) { - pci_prepare_to_sleep(pdev); - } else { - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - } + struct alx_priv *alx = pci_get_drvdata(pdev); + if (!netif_running(alx->dev)) + return 0; + netif_device_detach(alx->dev); + __alx_stop(alx); return 0; } @@ -1468,49 +1395,20 @@ static int alx_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct alx_priv *alx = pci_get_drvdata(pdev); - struct net_device *netdev = alx->dev; - struct alx_hw *hw = &alx->hw; - int err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_save_state(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - hw->link_speed = SPEED_UNKNOWN; - alx->int_mask = ALX_ISR_MISC; - - alx_reset_pcie(hw); - alx_reset_phy(hw); - - err = alx_reset_mac(hw); - if (err) { - netif_err(alx, hw, alx->dev, - "resume:reset_mac fail %d\n", err); - return -EIO; - } - - err = alx_setup_speed_duplex(hw, hw->adv_cfg, hw->flowctrl); - if (err) { - netif_err(alx, hw, alx->dev, - "resume:setup_speed_duplex fail %d\n", err); - return -EIO; - } - - if (netif_running(netdev)) { - err = __alx_open(alx, true); - if (err) - return err; - } - - netif_device_attach(netdev); - return err; + if (!netif_running(alx->dev)) + return 0; + netif_device_attach(alx->dev); + return __alx_open(alx, true); } + +static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume); +#define ALX_PM_OPS (&alx_pm_ops) +#else +#define ALX_PM_OPS NULL #endif + static pci_ers_result_t alx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { @@ -1553,8 +1451,6 @@ static pci_ers_result_t alx_pci_error_slot_reset(struct pci_dev *pdev) } pci_set_master(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); alx_reset_pcie(hw); if (!alx_reset_mac(hw)) @@ -1590,13 +1486,6 @@ static const struct pci_error_handlers alx_err_handlers = { .resume = alx_pci_error_resume, }; -#ifdef CONFIG_PM_SLEEP -static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume); -#define ALX_PM_OPS (&alx_pm_ops) -#else -#define ALX_PM_OPS NULL -#endif - static DEFINE_PCI_DEVICE_TABLE(alx_pci_tbl) = { { PCI_VDEVICE(ATTANSIC, ALX_DEV_ID_AR8161), .driver_data = ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG }, @@ -1614,7 +1503,6 @@ static struct pci_driver alx_driver = { .id_table = alx_pci_tbl, .probe = alx_probe, .remove = alx_remove, - .shutdown = alx_shutdown, .err_handler = &alx_err_handlers, .driver.pm = ALX_PM_OPS, }; -- GitLab From cdffcf1bc721032d261a7a9da353b41f0d830410 Mon Sep 17 00:00:00 2001 From: Jim Baxter Date: Tue, 2 Jul 2013 22:52:56 +0100 Subject: [PATCH 2246/2900] net: fec: Add VLAN receive HW support. This enables the driver to take advantage of the FEC VLAN indicator to improve performance. Signed-off-by: Jim Baxter Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 3 ++ drivers/net/ethernet/freescale/fec_main.c | 62 +++++++++++++++++++---- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 8362a0399afb..2b0a0ea4f8e7 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -203,6 +203,9 @@ struct bufdesc_ex { #define BD_ENET_RX_CL ((ushort)0x0001) #define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ +/* Enhanced buffer descriptor control/status used by Ethernet receive */ +#define BD_ENET_RX_VLAN 0x00000004 + /* Buffer descriptor control/status used by Ethernet transmit. */ #define BD_ENET_TX_READY ((ushort)0x8000) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 1f7ff2268bd0..d3ad5ea711d3 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -54,6 +54,7 @@ #include #include #include +#include #include @@ -90,6 +91,8 @@ static void set_multicast_list(struct net_device *ndev); #define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) /* Controller has hardware checksum support */ #define FEC_QUIRK_HAS_CSUM (1 << 5) +/* Controller has hardware vlan support */ +#define FEC_QUIRK_HAS_VLAN (1 << 6) static struct platform_device_id fec_devtype[] = { { @@ -108,7 +111,8 @@ static struct platform_device_id fec_devtype[] = { }, { .name = "imx6q-fec", .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | - FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM, + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | + FEC_QUIRK_HAS_VLAN, }, { .name = "mvf600-fec", .driver_data = FEC_QUIRK_ENET_MAC, @@ -179,11 +183,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII) #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF)) -/* The FEC stores dest/src/type, data, and checksum for receive packets. +/* The FEC stores dest/src/type/vlan, data, and checksum for receive packets. */ -#define PKT_MAXBUF_SIZE 1518 +#define PKT_MAXBUF_SIZE 1522 #define PKT_MINBUF_SIZE 64 -#define PKT_MAXBLR_SIZE 1520 +#define PKT_MAXBLR_SIZE 1536 /* FEC receive acceleration */ #define FEC_RACC_IPDIS (1 << 1) @@ -806,6 +810,9 @@ fec_enet_rx(struct net_device *ndev, int budget) ushort pkt_len; __u8 *data; int pkt_received = 0; + struct bufdesc_ex *ebdp = NULL; + bool vlan_packet_rcvd = false; + u16 vlan_tag; #ifdef CONFIG_M532x flush_cache_all(); @@ -869,6 +876,24 @@ fec_enet_rx(struct net_device *ndev, int budget) if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); + /* Extract the enhanced buffer descriptor */ + ebdp = NULL; + if (fep->bufdesc_ex) + ebdp = (struct bufdesc_ex *)bdp; + + /* If this is a VLAN packet remove the VLAN Tag */ + vlan_packet_rcvd = false; + if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && + fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) { + /* Push and remove the vlan tag */ + struct vlan_hdr *vlan_header = + (struct vlan_hdr *) (data + ETH_HLEN); + vlan_tag = ntohs(vlan_header->h_vlan_TCI); + pkt_len -= VLAN_HLEN; + + vlan_packet_rcvd = true; + } + /* This does 16 byte alignment, exactly what we need. * The packet length includes FCS, but we don't want to * include that when passing upstream as it messes up @@ -879,9 +904,18 @@ fec_enet_rx(struct net_device *ndev, int budget) if (unlikely(!skb)) { ndev->stats.rx_dropped++; } else { + int payload_offset = (2 * ETH_ALEN); skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len - 4); /* Make room */ - skb_copy_to_linear_data(skb, data, pkt_len - 4); + + /* Extract the frame data without the VLAN header. */ + skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN)); + if (vlan_packet_rcvd) + payload_offset = (2 * ETH_ALEN) + VLAN_HLEN; + skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN), + data + payload_offset, + pkt_len - 4 - (2 * ETH_ALEN)); + skb->protocol = eth_type_trans(skb, ndev); /* Get receive timestamp from the skb */ @@ -889,8 +923,6 @@ fec_enet_rx(struct net_device *ndev, int budget) struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); unsigned long flags; - struct bufdesc_ex *ebdp = - (struct bufdesc_ex *)bdp; memset(shhwtstamps, 0, sizeof(*shhwtstamps)); @@ -901,9 +933,7 @@ fec_enet_rx(struct net_device *ndev, int budget) } if (fep->bufdesc_ex && - (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { - struct bufdesc_ex *ebdp = - (struct bufdesc_ex *)bdp; + (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) { /* don't check it */ skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -912,6 +942,12 @@ fec_enet_rx(struct net_device *ndev, int budget) } } + /* Handle received VLAN packets */ + if (vlan_packet_rcvd) + __vlan_hwaccel_put_tag(skb, + htons(ETH_P_8021Q), + vlan_tag); + if (!skb_defer_rx_timestamp(skb)) napi_gro_receive(&fep->napi, skb); } @@ -1924,6 +1960,12 @@ static int fec_enet_init(struct net_device *ndev) writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT); + if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN) { + /* enable hw VLAN support */ + ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; + } + if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) { /* enable hw accelerator */ ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM -- GitLab From 4bc41b84e9b4d904f68cba2dbe0c60a5428c27c4 Mon Sep 17 00:00:00 2001 From: Joe Stringer Date: Wed, 3 Jul 2013 16:04:25 +0900 Subject: [PATCH 2247/2900] core: Copy inner_protocol in copy_skb_header() inner_protocol was added to struct sk_buff in 0d89d2035fe063461a5ddb609b2c12e7fb006e44 ("MPLS: Add limited GSO support"), which is scheduled to be included in v3.11. That patch did not update __copy_skb_header to copy the inner_protocol. Signed-off-by: Joe Stringer Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- net/core/skbuff.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 77971a35d6e1..724bb7cb173f 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -697,6 +697,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->transport_header = old->transport_header; new->network_header = old->network_header; new->mac_header = old->mac_header; + new->inner_protocol = old->inner_protocol; new->inner_transport_header = old->inner_transport_header; new->inner_network_header = old->inner_network_header; new->inner_mac_header = old->inner_mac_header; -- GitLab From 9caf83c32be1dabf000ab7dc8430fba4f7d89e65 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Jul 2013 12:37:46 +0300 Subject: [PATCH 2248/2900] net/mlx4: fix small memory leak on error "work" needs to be freed before returning on this error path. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 707a7d0d08e1..299d0184f983 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1572,6 +1572,7 @@ int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv, vp_admin->default_vlan, &admin_vlan_ix); if (err) { + kfree(work); mlx4_warn((&priv->dev), "No vlan resources slave %d, port %d\n", slave, port); -- GitLab From 9eb5bf838d06aa6ddebe4aca6b5cedcf2eb53b86 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 3 Jul 2013 05:02:22 -0700 Subject: [PATCH 2249/2900] net: sock: fix TCP_SKB_MIN_TRUESIZE commit eea86af6b1e18d ("net: sock: adapt SOCK_MIN_RCVBUF and SOCK_MIN_SNDBUF") forgot the sk_buff alignment taken into account in __alloc_skb() : skb->truesize = SKB_TRUESIZE(size); While above commit fixed the sender issue, the receiver is still dropping the second packet (on loopback device), because the receiver socket can not really hold two skbs : First packet truesize already is above sk_rcvbuf, so even TCP coalescing cannot help. On a typical 64bit build, each tcp skb truesize is 2304, instead of 2272 Signed-off-by: Eric Dumazet Cc: Daniel Borkmann Cc: Neal Cardwell Acked-by: Neal Cardwell Tested-by: Neal Cardwell Signed-off-by: David S. Miller --- include/net/sock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index ea6206ccc896..95a5a2c6925a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2052,7 +2052,7 @@ static inline void sk_wake_async(struct sock *sk, int how, int band) * Note: for send buffers, TCP works better if we can build two skbs at * minimum. */ -#define TCP_SKB_MIN_TRUESIZE (2048 + sizeof(struct sk_buff)) +#define TCP_SKB_MIN_TRUESIZE (2048 + SKB_DATA_ALIGN(sizeof(struct sk_buff))) #define SOCK_MIN_SNDBUF (TCP_SKB_MIN_TRUESIZE * 2) #define SOCK_MIN_RCVBUF TCP_SKB_MIN_TRUESIZE -- GitLab From 36b7bfe09b6deb71bf387852465245783c9a6208 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 3 Jul 2013 14:04:14 -0700 Subject: [PATCH 2250/2900] netem: fix possible NULL deref in netem_dequeue() commit aec0a40a6f7884 ("netem: use rb tree to implement the time queue") added a regression if a child qdisc is attached to netem, as we perform a NULL dereference. Fix this by adding a temporary variable to cache netem_skb_cb(skb)->time_to_send. Reported-by: Dan Carpenter Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_netem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ed0082cf8eff..82f6016d89ab 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -554,10 +554,13 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) } p = rb_first(&q->t_root); if (p) { + psched_time_t time_to_send; + skb = netem_rb_to_skb(p); /* if more time remaining? */ - if (netem_skb_cb(skb)->time_to_send <= psched_get_time()) { + time_to_send = netem_skb_cb(skb)->time_to_send; + if (time_to_send <= psched_get_time()) { rb_erase(p, &q->t_root); sch->q.qlen--; @@ -593,8 +596,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) if (skb) goto deliver; } - qdisc_watchdog_schedule(&q->watchdog, - netem_skb_cb(skb)->time_to_send); + qdisc_watchdog_schedule(&q->watchdog, time_to_send); } if (q->qdisc) { -- GitLab From a1bdc45580fc19e968b32ad27cd7e476a4aa58f6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Jul 2013 00:52:49 +0900 Subject: [PATCH 2251/2900] net: ipv6: add missing lock in ping_v6_sendmsg Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/ping.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 2b52046e1263..10b975577e91 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -174,6 +174,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); + lock_sock(sk); err = ip6_append_data(sk, ping_getfrag, &pfh, len, 0, hlimit, np->tclass, NULL, &fl6, rt, @@ -188,6 +189,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, (struct icmp6hdr *) &pfh.icmph, len); } + release_sock(sk); return err; } -- GitLab From fbfe80c890a1dc521d0b629b870e32fcffff0da5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Jul 2013 00:12:40 +0900 Subject: [PATCH 2252/2900] net: ipv6: fix wrong ping_v6_sendmsg return value ping_v6_sendmsg currently returns 0 on success. It should return the number of bytes written instead. Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/ping.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 10b975577e91..18f19df4189f 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -191,7 +191,10 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } release_sock(sk); - return err; + if (err) + return err; + + return len; } #ifdef CONFIG_PROC_FS -- GitLab From 3630d40067a21d4dfbadc6002bb469ce26ac5d52 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Wed, 3 Jul 2013 20:45:04 +0200 Subject: [PATCH 2253/2900] ipv6: rt6_check_neigh should successfully verify neigh if no NUD information are available After the removal of rt->n we do not create a neighbour entry at route insertion time (rt6_bind_neighbour is gone). As long as no neighbour is created because of "useful traffic" we skip this routing entry because rt6_check_neigh cannot pick up a valid neighbour (neigh == NULL) and thus returns false. This change was introduced by commit 887c95cc1da53f66a5890fdeab13414613010097 ("ipv6: Complete neighbour entry removal from dst_entry.") To quote RFC4191: "If the host has no information about the router's reachability, then the host assumes the router is reachable." and also: "A host MUST NOT probe a router's reachability in the absence of useful traffic that the host would have sent to the router if it were reachable." So, just assume the router is reachable and let's rt6_probe do the rest. We don't need to create a neighbour on route insertion time. If we don't compile with CONFIG_IPV6_ROUTER_PREF (RFC4191 support) a neighbour is only valid if its nud_state is NUD_VALID. I did not find any references that we should probe the router on route insertion time via the other RFCs. So skip this route in that case. v2: a) use IS_ENABLED instead of #ifdefs (thanks to Sergei Shtylyov) Reported-by: Pierre Emeriaud Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/route.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9ff0b78a9c15..bd5fd7054031 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -551,6 +551,8 @@ static inline bool rt6_check_neigh(struct rt6_info *rt) ret = true; #endif read_unlock(&neigh->lock); + } else if (IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) { + ret = true; } rcu_read_unlock_bh(); -- GitLab From 9b9cd8024a2882e896c65222aa421d461354e3f2 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 4 Jul 2013 11:22:57 +0930 Subject: [PATCH 2254/2900] virtio-net: fix the race between channels setting and refill Commit 55257d72bd1c51f25106350f4983ec19f62ed1fa (virtio-net: fill only rx queues which are being used) tries to refill on demand when changing the number of channels by call try_refill_recv() directly, this may race: - the refill work who may do the refill in the same time - the try_refill_recv() called in bh since napi was not disabled Which may led guest complain during setting channels: virtio_net virtio0: input.1:id 0 is not a head! Solve this issue by scheduling a refill work which can guarantee the serialization of refill. Cc: Sasha Levin Cc: Rusty Russell Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: Rusty Russell --- drivers/net/virtio_net.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 655bb25eed2b..6ddd77ece5d5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -900,7 +900,6 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) struct scatterlist sg; struct virtio_net_ctrl_mq s; struct net_device *dev = vi->dev; - int i; if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) return 0; @@ -914,10 +913,8 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) queue_pairs); return -EINVAL; } else { - for (i = vi->curr_queue_pairs; i < queue_pairs; i++) - if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); vi->curr_queue_pairs = queue_pairs; + schedule_delayed_work(&vi->refill, 0); } return 0; -- GitLab From e6dc0418bcb96e3cccb80571f35934ed72e9c99a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 4 Jul 2013 11:22:58 +0930 Subject: [PATCH 2255/2900] lguest: fix example launcher compilation for broken glibc headers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Somehow a naked u16 slipped into the glibc headers on my Ubuntu machine (i386 2.17-0ubuntu5), breaking compile: In file included from lguest.c:46:0: /usr/include/linux/virtio_net.h:188:2: error: unknown type name ‘u16’ We use the kernel-style types anyway, just define them before the includes. Also remove the advice on adding missing headers: that no longer works. Signed-off-by: Rusty Russell --- tools/lguest/Makefile | 1 - tools/lguest/lguest.c | 17 +++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/lguest/Makefile b/tools/lguest/Makefile index 0ac34206f7a7..97bca4871ea3 100644 --- a/tools/lguest/Makefile +++ b/tools/lguest/Makefile @@ -1,5 +1,4 @@ # This creates the demonstration utility "lguest" which runs a Linux guest. -# Missing headers? Add "-I../../../include -I../../../arch/x86/include" CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE all: lguest diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index a64f5cb0c15b..68f67cf3d318 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -42,14 +42,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include "../../include/linux/lguest_launcher.h" /*L:110 * We can ignore the 43 include files we need for this program, but I do want * to draw attention to the use of kernel-style types. @@ -65,6 +57,15 @@ typedef uint16_t u16; typedef uint8_t u8; /*:*/ +#include +#include +#include +#include +#include +#include +#include +#include "../../include/linux/lguest_launcher.h" + #define BRIDGE_PFX "bridge:" #ifndef SIOCBRADDIF #define SIOCBRADDIF 0x89a2 /* add interface to bridge */ -- GitLab From dbf738a1a6f93c634e368e74a1943acb93696b22 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Jun 2013 23:21:20 -0700 Subject: [PATCH 2256/2900] iscsi-target: Allow ->MaxXmitDataSegmentLength assignment for iser discovery This patch changes iscsi_set_connection_parameters() to allow conn_ops->MaxXmitDataSegmentLength assignement to occur during in-band iser send-targets discovery, as this value is required by TEXT response processing code. Reported-by: Or Gerlitz Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_parameters.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index e38222191a33..35fd6439eb01 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -1799,9 +1799,6 @@ void iscsi_set_connection_parameters( * this key is not sent over the wire. */ if (!strcmp(param->name, MAXXMITDATASEGMENTLENGTH)) { - if (param_list->iser == true) - continue; - ops->MaxXmitDataSegmentLength = simple_strtoul(param->value, &tmpptr, 0); pr_debug("MaxXmitDataSegmentLength: %s\n", -- GitLab From 9864ca9d27f75d2716d09dd02b3d62d241194576 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Jun 2013 22:43:11 -0700 Subject: [PATCH 2257/2900] iscsi-target: Move sendtargets parsing into iscsit_process_text_cmd This patch moves ISCSI_OP_TEXT PDU buffer sanity checks to iscsit_process_text_cmd() code, so that it can be shared with iser-target code. It adds IFC_SENDTARGETS_ALL + iscsi_cmd->text_in_ptr in order to save text payload for ISCSI_OP_TEXT_RSP, and updates iscsit_release_cmd() to assigned memory. Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 51 ++++++++++++++---------- drivers/target/iscsi/iscsi_target_core.h | 3 ++ drivers/target/iscsi/iscsi_target_util.c | 1 + 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 1f79a168f1c1..30ca1887516b 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1995,8 +1995,32 @@ int iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, struct iscsi_text *hdr) { + unsigned char *text_in = cmd->text_in_ptr, *text_ptr; int cmdsn_ret; + if (!text_in) { + pr_err("Unable to locate text_in buffer for sendtargets" + " discovery\n"); + goto reject; + } + if (strncmp("SendTargets", text_in, 11) != 0) { + pr_err("Received Text Data that is not" + " SendTargets, cannot continue.\n"); + goto reject; + } + text_ptr = strchr(text_in, '='); + if (!text_ptr) { + pr_err("No \"=\" separator found in Text Data," + " cannot continue.\n"); + goto reject; + } + if (!strncmp("=All", text_ptr, 4)) { + cmd->cmd_flags |= IFC_SENDTARGETS_ALL; + } else { + pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr); + goto reject; + } + spin_lock_bh(&conn->cmd_lock); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); spin_unlock_bh(&conn->cmd_lock); @@ -2013,6 +2037,10 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } return iscsit_execute_cmd(cmd, 0); + +reject: + return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, + 0, 0, (unsigned char *)hdr, cmd); } EXPORT_SYMBOL(iscsit_process_text_cmd); @@ -2031,7 +2059,6 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, rx_size = payload_length; if (payload_length) { - char *text_ptr; u32 checksum = 0, data_crc = 0; u32 padding = 0, pad_bytes = 0; int niov = 0, rx_got; @@ -2043,6 +2070,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, " incoming text parameters\n"); goto reject; } + cmd->text_in_ptr = text_in; memset(iov, 0, 3 * sizeof(struct kvec)); iov[niov].iov_base = text_in; @@ -2101,30 +2129,13 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, text_in[payload_length - 1] = '\0'; pr_debug("Successfully read %d bytes of text" " data.\n", payload_length); - - if (strncmp("SendTargets", text_in, 11) != 0) { - pr_err("Received Text Data that is not" - " SendTargets, cannot continue.\n"); - goto reject; - } - text_ptr = strchr(text_in, '='); - if (!text_ptr) { - pr_err("No \"=\" separator found in Text Data," - " cannot continue.\n"); - goto reject; - } - if (strncmp("=All", text_ptr, 4) != 0) { - pr_err("Unable to locate All value for" - " SendTargets key, cannot continue.\n"); - goto reject; - } - kfree(text_in); } return iscsit_process_text_cmd(conn, cmd, hdr); reject: - kfree(text_in); + kfree(cmd->text_in_ptr); + cmd->text_in_ptr = NULL; return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, 0, 0, buf, cmd); } diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 60ec4b92be03..ad46e73dab4c 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -133,6 +133,7 @@ enum cmd_flags_table { ICF_ATTACHED_TO_RQUEUE = 0x00000040, ICF_OOO_CMDSN = 0x00000080, ICF_REJECT_FAIL_CONN = 0x00000100, + IFC_SENDTARGETS_ALL = 0x00000200, }; /* struct iscsi_cmd->i_state */ @@ -427,6 +428,8 @@ struct iscsi_cmd { u32 tx_size; /* Buffer used for various purposes */ void *buf_ptr; + /* Used by SendTargets=[iqn.,eui.] discovery */ + void *text_in_ptr; /* See include/linux/dma-mapping.h */ enum dma_data_direction data_direction; /* iSCSI PDU Header + CRC */ diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 08a3bacef0c5..fe712d6cc478 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -681,6 +681,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) kfree(cmd->seq_list); kfree(cmd->tmr_req); kfree(cmd->iov_data); + kfree(cmd->text_in_ptr); kmem_cache_free(lio_cmd_cache, cmd); } -- GitLab From 6665889c843c774cd35309cf995ba0d302fa6dba Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Jun 2013 22:45:42 -0700 Subject: [PATCH 2258/2900] iscsi-target: Add IFC_SENDTARGETS_SINGLE support This patch changes ISCSI_OP_TEXT handling of SendTargets=[iqn.,eui.] payloads to return explicit discovery information. It adds checks to iscsit_process_text_cmd() and adds the special single $TARGETNAME discovery case in iscsit_build_sendtargets_response() code. Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 28 ++++++++++++++++++++++++ drivers/target/iscsi/iscsi_target_core.h | 1 + 2 files changed, 29 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 30ca1887516b..f2c3d4abfe70 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -2016,6 +2016,9 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } if (!strncmp("=All", text_ptr, 4)) { cmd->cmd_flags |= IFC_SENDTARGETS_ALL; + } else if (!strncmp("=iqn.", text_ptr, 5) || + !strncmp("=eui.", text_ptr, 5)) { + cmd->cmd_flags |= IFC_SENDTARGETS_SINGLE; } else { pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr); goto reject; @@ -3398,6 +3401,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) struct iscsi_tpg_np *tpg_np; int buffer_len, end_of_buf = 0, len = 0, payload_len = 0; unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */ + unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL; buffer_len = max(conn->conn_ops->MaxRecvDataSegmentLength, SENDTARGETS_BUF_LIMIT); @@ -3408,9 +3412,30 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) " response.\n"); return -ENOMEM; } + /* + * Locate pointer to iqn./eui. string for IFC_SENDTARGETS_SINGLE + * explicit case.. + */ + if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) { + text_ptr = strchr(text_in, '='); + if (!text_ptr) { + pr_err("Unable to locate '=' string in text_in:" + " %s\n", text_in); + return -EINVAL; + } + /* + * Skip over '=' character.. + */ + text_ptr += 1; + } spin_lock(&tiqn_lock); list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) { + if ((cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) && + strcmp(tiqn->tiqn, text_ptr)) { + continue; + } + len = sprintf(buf, "TargetName=%s", tiqn->tiqn); len += 1; @@ -3464,6 +3489,9 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) eob: if (end_of_buf) break; + + if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) + break; } spin_unlock(&tiqn_lock); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index ad46e73dab4c..3436a2cc1d35 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -134,6 +134,7 @@ enum cmd_flags_table { ICF_OOO_CMDSN = 0x00000080, ICF_REJECT_FAIL_CONN = 0x00000100, IFC_SENDTARGETS_ALL = 0x00000200, + IFC_SENDTARGETS_SINGLE = 0x00000400, }; /* struct iscsi_cmd->i_state */ -- GitLab From e4b512e7133f5243f080db8238c5be8434cbcdfd Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Jun 2013 18:37:00 -0700 Subject: [PATCH 2259/2900] target: Add se_portal_group->tpg_auth_group This patch adds an optional /auth/ configfs group to TPG context that can be used by fabrics like iscsi-target for TPG demo-mode authentication. Cc: Dax Kelson Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_fabric_configfs.c | 21 ++++++++++++++++++-- include/target/target_core_base.h | 3 ++- include/target/target_core_configfs.h | 1 + include/target/target_core_fabric_configfs.h | 11 ++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 04c775cb3e65..eb56eb129563 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -965,6 +965,19 @@ TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL); /* End of tfc_tpg_attrib_cit */ +/* Start of tfc_tpg_auth_cit */ + +CONFIGFS_EATTR_OPS(target_fabric_tpg_auth, se_portal_group, tpg_auth_group); + +static struct configfs_item_operations target_fabric_tpg_auth_item_ops = { + .show_attribute = target_fabric_tpg_auth_attr_show, + .store_attribute = target_fabric_tpg_auth_attr_store, +}; + +TF_CIT_SETUP(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL, NULL); + +/* End of tfc_tpg_attrib_cit */ + /* Start of tfc_tpg_param_cit */ CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group); @@ -1030,8 +1043,9 @@ static struct config_group *target_fabric_make_tpg( se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group; se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group; se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group; - se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_param_group; - se_tpg->tpg_group.default_groups[5] = NULL; + se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_auth_group; + se_tpg->tpg_group.default_groups[5] = &se_tpg->tpg_param_group; + se_tpg->tpg_group.default_groups[6] = NULL; config_group_init_type_name(&se_tpg->tpg_group, name, &TF_CIT_TMPL(tf)->tfc_tpg_base_cit); @@ -1043,6 +1057,8 @@ static struct config_group *target_fabric_make_tpg( &TF_CIT_TMPL(tf)->tfc_tpg_nacl_cit); config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib", &TF_CIT_TMPL(tf)->tfc_tpg_attrib_cit); + config_group_init_type_name(&se_tpg->tpg_auth_group, "auth", + &TF_CIT_TMPL(tf)->tfc_tpg_auth_cit); config_group_init_type_name(&se_tpg->tpg_param_group, "param", &TF_CIT_TMPL(tf)->tfc_tpg_param_cit); @@ -1202,6 +1218,7 @@ int target_fabric_setup_cits(struct target_fabric_configfs *tf) target_fabric_setup_tpg_np_cit(tf); target_fabric_setup_tpg_np_base_cit(tf); target_fabric_setup_tpg_attrib_cit(tf); + target_fabric_setup_tpg_auth_cit(tf); target_fabric_setup_tpg_param_cit(tf); target_fabric_setup_tpg_nacl_cit(tf); target_fabric_setup_tpg_nacl_base_cit(tf); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 9fd7a60f47f0..d92ec6765f5d 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -795,11 +795,12 @@ struct se_portal_group { struct target_core_fabric_ops *se_tpg_tfo; struct se_wwn *se_tpg_wwn; struct config_group tpg_group; - struct config_group *tpg_default_groups[6]; + struct config_group *tpg_default_groups[7]; struct config_group tpg_lun_group; struct config_group tpg_np_group; struct config_group tpg_acl_group; struct config_group tpg_attrib_group; + struct config_group tpg_auth_group; struct config_group tpg_param_group; }; diff --git a/include/target/target_core_configfs.h b/include/target/target_core_configfs.h index 612509592ffd..713c5004f4ae 100644 --- a/include/target/target_core_configfs.h +++ b/include/target/target_core_configfs.h @@ -23,6 +23,7 @@ struct target_fabric_configfs_template { struct config_item_type tfc_tpg_np_cit; struct config_item_type tfc_tpg_np_base_cit; struct config_item_type tfc_tpg_attrib_cit; + struct config_item_type tfc_tpg_auth_cit; struct config_item_type tfc_tpg_param_cit; struct config_item_type tfc_tpg_nacl_cit; struct config_item_type tfc_tpg_nacl_base_cit; diff --git a/include/target/target_core_fabric_configfs.h b/include/target/target_core_fabric_configfs.h index a26fb7586a09..b32a14905cfa 100644 --- a/include/target/target_core_fabric_configfs.h +++ b/include/target/target_core_fabric_configfs.h @@ -62,6 +62,17 @@ static struct target_fabric_tpg_attrib_attribute _fabric##_tpg_attrib_##_name = _fabric##_tpg_attrib_show_##_name, \ _fabric##_tpg_attrib_store_##_name); +CONFIGFS_EATTR_STRUCT(target_fabric_tpg_auth, se_portal_group); +#define TF_TPG_AUTH_ATTR(_fabric, _name, _mode) \ +static struct target_fabric_tpg_auth_attribute _fabric##_tpg_auth_##_name = \ + __CONFIGFS_EATTR(_name, _mode, \ + _fabric##_tpg_auth_show_##_name, \ + _fabric##_tpg_auth_store_##_name); + +#define TF_TPG_AUTH_ATTR_RO(_fabric, _name) \ +static struct target_fabric_tpg_auth_attribute _fabric##_tpg_auth_##_name = \ + __CONFIGFS_EATTR_RO(_name, \ + _fabric##_tpg_auth_show_##_name); CONFIGFS_EATTR_STRUCT(target_fabric_tpg_param, se_portal_group); #define TF_TPG_PARAM_ATTR(_fabric, _name, _mode) \ -- GitLab From c3e51442711d20ea1245bb6d260aa05593849e82 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 19 Jun 2013 18:48:51 -0700 Subject: [PATCH 2260/2900] iscsi-target: Add demo-mode TPG authentication context support This patch adds a auth configfs group context following existing explict NodeACL and discovery auth within: /sys/kernel/config/target/iscsi/$TARGETNAME/$TPGT/auth/ This patch allows these attributes to be used for CHAP authentication an TPG is configured in demo-mode (generate_node_acl=1). Note this authentication information takes precedence over NodeACL authentication when struct se_node_acl->dynamic_node_acl is present. Cc: Dax Kelson Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 126 +++++++++++++++++++ drivers/target/iscsi/iscsi_target_core.h | 1 + drivers/target/iscsi/iscsi_target_nego.c | 13 +- 3 files changed, 139 insertions(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 13e9e715ad2e..e251849a6140 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1052,6 +1052,131 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = { /* End items for lio_target_tpg_attrib_cit */ +/* Start items for lio_target_tpg_auth_cit */ + +#define __DEF_TPG_AUTH_STR(prefix, name, flags) \ +static ssize_t __iscsi_##prefix##_show_##name( \ + struct se_portal_group *se_tpg, \ + char *page) \ +{ \ + struct iscsi_portal_group *tpg = container_of(se_tpg, \ + struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ + \ + if (!capable(CAP_SYS_ADMIN)) \ + return -EPERM; \ + \ + return snprintf(page, PAGE_SIZE, "%s\n", auth->name); \ +} \ + \ +static ssize_t __iscsi_##prefix##_store_##name( \ + struct se_portal_group *se_tpg, \ + const char *page, \ + size_t count) \ +{ \ + struct iscsi_portal_group *tpg = container_of(se_tpg, \ + struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ + \ + if (!capable(CAP_SYS_ADMIN)) \ + return -EPERM; \ + \ + snprintf(auth->name, PAGE_SIZE, "%s", page); \ + if (!(strncmp("NULL", auth->name, 4))) \ + auth->naf_flags &= ~flags; \ + else \ + auth->naf_flags |= flags; \ + \ + if ((auth->naf_flags & NAF_USERID_IN_SET) && \ + (auth->naf_flags & NAF_PASSWORD_IN_SET)) \ + auth->authenticate_target = 1; \ + else \ + auth->authenticate_target = 0; \ + \ + return count; \ +} + +#define __DEF_TPG_AUTH_INT(prefix, name) \ +static ssize_t __iscsi_##prefix##_show_##name( \ + struct se_portal_group *se_tpg, \ + char *page) \ +{ \ + struct iscsi_portal_group *tpg = container_of(se_tpg, \ + struct iscsi_portal_group, tpg_se_tpg); \ + struct iscsi_node_auth *auth = &tpg->tpg_demo_auth; \ + \ + if (!capable(CAP_SYS_ADMIN)) \ + return -EPERM; \ + \ + return snprintf(page, PAGE_SIZE, "%d\n", auth->name); \ +} + +#define DEF_TPG_AUTH_STR(name, flags) \ + __DEF_TPG_AUTH_STR(tpg_auth, name, flags) \ +static ssize_t iscsi_tpg_auth_show_##name( \ + struct se_portal_group *se_tpg, \ + char *page) \ +{ \ + return __iscsi_tpg_auth_show_##name(se_tpg, page); \ +} \ + \ +static ssize_t iscsi_tpg_auth_store_##name( \ + struct se_portal_group *se_tpg, \ + const char *page, \ + size_t count) \ +{ \ + return __iscsi_tpg_auth_store_##name(se_tpg, page, count); \ +} + +#define DEF_TPG_AUTH_INT(name) \ + __DEF_TPG_AUTH_INT(tpg_auth, name) \ +static ssize_t iscsi_tpg_auth_show_##name( \ + struct se_portal_group *se_tpg, \ + char *page) \ +{ \ + return __iscsi_tpg_auth_show_##name(se_tpg, page); \ +} + +#define TPG_AUTH_ATTR(_name, _mode) TF_TPG_AUTH_ATTR(iscsi, _name, _mode); +#define TPG_AUTH_ATTR_RO(_name) TF_TPG_AUTH_ATTR_RO(iscsi, _name); + +/* + * * One-way authentication userid + * */ +DEF_TPG_AUTH_STR(userid, NAF_USERID_SET); +TPG_AUTH_ATTR(userid, S_IRUGO | S_IWUSR); +/* + * * One-way authentication password + * */ +DEF_TPG_AUTH_STR(password, NAF_PASSWORD_SET); +TPG_AUTH_ATTR(password, S_IRUGO | S_IWUSR); +/* + * * Enforce mutual authentication + * */ +DEF_TPG_AUTH_INT(authenticate_target); +TPG_AUTH_ATTR_RO(authenticate_target); +/* + * * Mutual authentication userid + * */ +DEF_TPG_AUTH_STR(userid_mutual, NAF_USERID_IN_SET); +TPG_AUTH_ATTR(userid_mutual, S_IRUGO | S_IWUSR); +/* + * * Mutual authentication password + * */ +DEF_TPG_AUTH_STR(password_mutual, NAF_PASSWORD_IN_SET); +TPG_AUTH_ATTR(password_mutual, S_IRUGO | S_IWUSR); + +static struct configfs_attribute *lio_target_tpg_auth_attrs[] = { + &iscsi_tpg_auth_userid.attr, + &iscsi_tpg_auth_password.attr, + &iscsi_tpg_auth_authenticate_target.attr, + &iscsi_tpg_auth_userid_mutual.attr, + &iscsi_tpg_auth_password_mutual.attr, + NULL, +}; + +/* End items for lio_target_tpg_auth_cit */ + /* Start items for lio_target_tpg_param_cit */ #define DEF_TPG_PARAM(name) \ @@ -1865,6 +1990,7 @@ int iscsi_target_register_configfs(void) TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs; TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs; TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs; + TF_CIT_TMPL(fabric)->tfc_tpg_auth_cit.ct_attrs = lio_target_tpg_auth_attrs; TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs; TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs; TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 3436a2cc1d35..391283c85313 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -813,6 +813,7 @@ struct iscsi_portal_group { struct mutex tpg_access_lock; struct mutex np_login_lock; struct iscsi_tpg_attrib tpg_attrib; + struct iscsi_node_auth tpg_demo_auth; /* Pointer to default list of iSCSI parameters for TPG */ struct iscsi_param_list *param_list; struct iscsi_tiqn *tpg_tiqn; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 7ad912060e21..6b5fc27a770d 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -112,6 +112,7 @@ static u32 iscsi_handle_authentication( struct iscsi_session *sess = conn->sess; struct iscsi_node_auth *auth; struct iscsi_node_acl *iscsi_nacl; + struct iscsi_portal_group *iscsi_tpg; struct se_node_acl *se_nacl; if (!sess->sess_ops->SessionType) { @@ -132,7 +133,17 @@ static u32 iscsi_handle_authentication( return -1; } - auth = ISCSI_NODE_AUTH(iscsi_nacl); + if (se_nacl->dynamic_node_acl) { + iscsi_tpg = container_of(se_nacl->se_tpg, + struct iscsi_portal_group, tpg_se_tpg); + + auth = &iscsi_tpg->tpg_demo_auth; + } else { + iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl, + se_node_acl); + + auth = ISCSI_NODE_AUTH(iscsi_nacl); + } } else { /* * For SessionType=Discovery -- GitLab From 8a3918571a4eb3ae10ddd4aaec591b4af80d1172 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 24 Jun 2013 22:18:40 -0700 Subject: [PATCH 2261/2900] target: Make core_scsi3_update_and_write_aptpl return sense_reason_t Fix up sense_reason_t breakage in core_scsi3_update_and_write_aptpl() from recent conversion to use local scope memory allocation. Reported as sparse warnings: (new ones prefixed by >>) by Fengguang: >> drivers/target/target_core_pr.c:2069:57: sparse: incorrect type in >> return expression (different base types) drivers/target/target_core_pr.c:2069:57: expected restricted sense_reason_t drivers/target/target_core_pr.c:2069:57: got int >> drivers/target/target_core_pr.c:2179:21: sparse: incorrect type in >> assignment (different base types) drivers/target/target_core_pr.c:2179:21: expected restricted sense_reason_t [assigned] [usertype] ret drivers/target/target_core_pr.c:2179:21: got int >> drivers/target/target_core_pr.c:2197:13: sparse: incorrect type in >> assignment (different base types) drivers/target/target_core_pr.c:2197:13: expected restricted sense_reason_t [assigned] [usertype] ret drivers/target/target_core_pr.c:2197:13: got int drivers/target/target_core_pr.c:1245:28: sparse: context imbalance in '__core_scsi3_free_registration' - unexpected unlock Reported-by: kbuild test robot Cc: Andy Grover Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 47 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 05c3f426728a..bd78faf67c6b 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1956,41 +1956,44 @@ static int __core_scsi3_write_aptpl_to_file( * Clear the APTPL metadata if APTPL has been disabled, otherwise * write out the updated metadata to struct file for this SCSI device. */ -static int core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) +static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl) { - int ret = 0; + unsigned char *buf; + int rc; if (!aptpl) { char *null_buf = "No Registrations or Reservations\n"; - ret = __core_scsi3_write_aptpl_to_file(dev, null_buf); + rc = __core_scsi3_write_aptpl_to_file(dev, null_buf); dev->t10_pr.pr_aptpl_active = 0; pr_debug("SPC-3 PR: Set APTPL Bit Deactivated\n"); - } else { - int ret; - unsigned char *buf; - buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); - if (!buf) - return -ENOMEM; + if (rc) + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - ret = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); - if (ret < 0) { - kfree(buf); - return ret; - } + return 0; + } - ret = __core_scsi3_write_aptpl_to_file(dev, buf); - if (ret != 0) { - pr_err("SPC-3 PR: Could not update APTPL\n"); - } else { - dev->t10_pr.pr_aptpl_active = 1; - pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); - } + buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); + if (!buf) + return TCM_OUT_OF_RESOURCES; + + rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN); + if (rc < 0) { kfree(buf); + return TCM_OUT_OF_RESOURCES; } - return ret; + rc = __core_scsi3_write_aptpl_to_file(dev, buf); + if (rc != 0) { + pr_err("SPC-3 PR: Could not update APTPL\n"); + kfree(buf); + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + } + dev->t10_pr.pr_aptpl_active = 1; + kfree(buf); + pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); + return 0; } static sense_reason_t -- GitLab From 3e23d025bc19940979c4f0c67a39d64af7c893c6 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 24 Jun 2013 22:26:02 -0700 Subject: [PATCH 2262/2900] iscsi-target: Drop left-over iscsi_conn->bad_hdr All REJECT response setup of the rejected payload is now done using on-demand cmd->buf_ptr allocations. Go ahead and remove dead iscsi_conn->bad_hdr usage rx_opcode path Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 5 ----- drivers/target/iscsi/iscsi_target_core.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f2c3d4abfe70..dc2c0565736d 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -4105,11 +4105,6 @@ int iscsi_target_rx_thread(void *arg) goto transport_err; } - /* - * Set conn->bad_hdr for use with REJECT PDUs. - */ - memcpy(&conn->bad_hdr, &buffer, ISCSI_HDR_LEN); - if (conn->conn_ops->HeaderDigest) { iov.iov_base = &digest; iov.iov_len = ISCSI_CRC_LEN; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 391283c85313..caa0ad9a778b 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -532,8 +532,6 @@ struct iscsi_conn { u32 of_marker; /* Used for calculating OFMarker offset to next PDU */ u32 of_marker_offset; - /* Complete Bad PDU for sending reject */ - unsigned char bad_hdr[ISCSI_HDR_LEN]; #define IPV6_ADDRESS_SPACE 48 unsigned char login_ip[IPV6_ADDRESS_SPACE]; unsigned char local_ip[IPV6_ADDRESS_SPACE]; -- GitLab From 4f45d320ba97ad2f1107a56e8b2af0dd7e764502 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 24 Jun 2013 18:46:57 +0300 Subject: [PATCH 2263/2900] iscsi-target: missing kfree() on error path Fix-up breakage in iscsit_build_sendtargets_response() from v3.11 changes, and free "payload" before returning. Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index dc2c0565736d..19a31f9bb7d5 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3421,6 +3421,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) if (!text_ptr) { pr_err("Unable to locate '=' string in text_in:" " %s\n", text_in); + kfree(payload); return -EINVAL; } /* -- GitLab From 035dc1e0f9008b48630e02bf0eaa7cc547416d1d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 3 Jul 2013 12:56:54 +0200 Subject: [PATCH 2264/2900] drm/i915: reinit status page registers after gpu reset This fixes gpu reset on my gm45 - without this patch the bsd thing is forever stuck since the seqno updates never reach the status page. Tbh I have no idea how this ever worked without rewriting the hws registers after a gpu reset. To satisfy my OCD also give the functions a bit more consistent names: - Use status_page everywhere, also for the physical addressed one. - Use init for the allocation part and setup for the register setup part consistently. Long term I'd really like to share the hw init parts completely between gpu reset, resume and driver load, i.e. to call i915_gem_init_hw instead of the individual pieces we might need. v2: Add the missing paragraph to the commit message about what bug exactly this patch here fixes. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65495 Cc: Chris Wilson Reviewed-by: Chris Wilson Tested-by: lu hua Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 29 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e51ab552046c..18ca76e3e5ef 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -379,6 +379,17 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) return I915_READ(acthd_reg); } +static void ring_setup_phys_status_page(struct intel_ring_buffer *ring) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + u32 addr; + + addr = dev_priv->status_page_dmah->busaddr; + if (INTEL_INFO(ring->dev)->gen >= 4) + addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; + I915_WRITE(HWS_PGA, addr); +} + static int init_ring_common(struct intel_ring_buffer *ring) { struct drm_device *dev = ring->dev; @@ -390,6 +401,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) if (HAS_FORCE_WAKE(dev)) gen6_gt_force_wake_get(dev_priv); + if (I915_NEED_GFX_HWS(dev)) + intel_ring_setup_status_page(ring); + else + ring_setup_phys_status_page(ring); + /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -1223,7 +1239,6 @@ static int init_status_page(struct intel_ring_buffer *ring) ring->status_page.obj = obj; memset(ring->status_page.page_addr, 0, PAGE_SIZE); - intel_ring_setup_status_page(ring); DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", ring->name, ring->status_page.gfx_addr); @@ -1237,10 +1252,9 @@ static int init_status_page(struct intel_ring_buffer *ring) return ret; } -static int init_phys_hws_pga(struct intel_ring_buffer *ring) +static int init_phys_status_page(struct intel_ring_buffer *ring) { struct drm_i915_private *dev_priv = ring->dev->dev_private; - u32 addr; if (!dev_priv->status_page_dmah) { dev_priv->status_page_dmah = @@ -1249,11 +1263,6 @@ static int init_phys_hws_pga(struct intel_ring_buffer *ring) return -ENOMEM; } - addr = dev_priv->status_page_dmah->busaddr; - if (INTEL_INFO(ring->dev)->gen >= 4) - addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; - I915_WRITE(HWS_PGA, addr); - ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; memset(ring->status_page.page_addr, 0, PAGE_SIZE); @@ -1281,7 +1290,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, return ret; } else { BUG_ON(ring->id != RCS); - ret = init_phys_hws_pga(ring); + ret = init_phys_status_page(ring); if (ret) return ret; } @@ -1893,7 +1902,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) } if (!I915_NEED_GFX_HWS(dev)) { - ret = init_phys_hws_pga(ring); + ret = init_phys_status_page(ring); if (ret) return ret; } -- GitLab From 1baa3b4e06f1e03f4fbbbc3734ea3b9a7a1134ec Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 4 Jul 2013 11:48:38 +0530 Subject: [PATCH 2265/2900] regulator: s5m8767: Fix a trivial typo in documentation Changed volatage to voltage. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/s5m8767-regulator.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt index 7364f7114fbd..d1660a90fc06 100644 --- a/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/s5m8767-regulator.txt @@ -1,6 +1,6 @@ * Samsung S5M8767 Voltage and Current Regulator -The Samsung S5M8767 is a multi-function device which includes volatage and +The Samsung S5M8767 is a multi-function device which includes voltage and current regulators, rtc, charger controller and other sub-blocks. It is interfaced to the host controller using a i2c interface. Each sub-block is addressed by the host system using different i2c slave address. This document -- GitLab From 489cceeeb808199f55dbff2adaddd7394fb88de6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 4 Jul 2013 11:48:39 +0530 Subject: [PATCH 2266/2900] regulator: max8997: Fix a trivial typo in documentation Changed volatage to voltage. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/max8997-regulator.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt index 9e5e51d78868..5c186a7a77ba 100644 --- a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt @@ -1,6 +1,6 @@ * Maxim MAX8997 Voltage and Current Regulator -The Maxim MAX8997 is a multi-function device which includes volatage and +The Maxim MAX8997 is a multi-function device which includes voltage and current regulators, rtc, charger controller and other sub-blocks. It is interfaced to the host controller using a i2c interface. Each sub-block is addressed by the host system using different i2c slave address. This document -- GitLab From 6febb5abc597849b3fe918cc69432dc9cf5ab025 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 4 Jul 2013 12:08:50 +0530 Subject: [PATCH 2267/2900] MAINTAINERS: Update git repository The current git repository hasn't been updated since quite a long time. Update it with Mark's git repo which is the currently maintained one. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ad7e322ad17b..199e8078e622 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8895,7 +8895,7 @@ M: Liam Girdwood M: Mark Brown W: http://opensource.wolfsonmicro.com/node/15 W: http://www.slimlogic.co.uk/?p=48 -T: git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/regulator.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git S: Supported F: drivers/regulator/ F: include/linux/regulator/ -- GitLab From 8f0b3b7e222383a21f7d58bd97d5552b3a5dbced Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 4 Jul 2013 12:54:22 +0200 Subject: [PATCH 2268/2900] ALSA: hda - Fix EAPD vmaster hook for AD1884 & co ad1884_fixup_hp_eapd() tries to set the NID for controlling the speaker EAPD from the pin configuration. But the current code can't work expectedly since it sets spec->eapd_nid before calling the generic parser where the autocfg pins are set up. This patch changes the function to set spec->eapd_nid after the generic parser call while it sets vmaster hook unconditionally. The spec->eapd_nid check is moved in the hook function itself instead. Cc: [v3.9+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_analog.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 977b0d878dae..d97f0d61a15b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2112,6 +2112,9 @@ static void ad_vmaster_eapd_hook(void *private_data, int enabled) { struct hda_codec *codec = private_data; struct ad198x_spec *spec = codec->spec; + + if (!spec->eapd_nid) + return; snd_hda_codec_update_cache(codec, spec->eapd_nid, 0, AC_VERB_SET_EAPD_BTLENABLE, enabled ? 0x02 : 0x00); @@ -3601,13 +3604,16 @@ static void ad1884_fixup_hp_eapd(struct hda_codec *codec, { struct ad198x_spec *spec = codec->spec; - if (action == HDA_FIXUP_ACT_PRE_PROBE) { + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; + break; + case HDA_FIXUP_ACT_PROBE: if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) spec->eapd_nid = spec->gen.autocfg.line_out_pins[0]; else spec->eapd_nid = spec->gen.autocfg.speaker_pins[0]; - if (spec->eapd_nid) - spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook; + break; } } -- GitLab From 266c13d767be61a17d8e6f2310b9b7c46278273b Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 2 Jul 2013 16:36:28 +0530 Subject: [PATCH 2269/2900] cpufreq: Fix serialization of frequency transitions Commit 7c30ed ("cpufreq: make sure frequency transitions are serialized") interacts poorly with systems that have a single core freqency for all cores. On such systems we have a single policy for all cores with several CPUs. When we do a frequency transition the governor calls the pre and post change notifiers which causes cpufreq_notify_transition() per CPU. Since the policy is the same for all of them all CPUs after the first and the warnings added are generated by checking a per-policy flag the warnings will be triggered for all cores after the first. Fix this by allowing notifier to be called for n times. Where n is the number of cpus in policy->cpus. Reported-and-tested-by: Mark Brown Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 7 ++++--- include/linux/cpufreq.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 6a015ada5285..0937b8d6c2a4 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -312,11 +312,12 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, switch (state) { case CPUFREQ_PRECHANGE: - if (WARN(policy->transition_ongoing, + if (WARN(policy->transition_ongoing == + cpumask_weight(policy->cpus), "In middle of another frequency transition\n")) return; - policy->transition_ongoing = true; + policy->transition_ongoing++; /* detect if the driver reported a value as "old frequency" * which is not equal to what the cpufreq core thinks is @@ -341,7 +342,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, "No frequency transition in progress\n")) return; - policy->transition_ongoing = false; + policy->transition_ongoing--; adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4d7390bc1727..90d5a15120d5 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -119,7 +119,7 @@ struct cpufreq_policy { struct kobject kobj; struct completion kobj_unregister; - bool transition_ongoing; /* Tracks transition status */ + int transition_ongoing; /* Tracks transition status */ }; #define CPUFREQ_ADJUST (0) -- GitLab From 91bdad0b6237c25a7bf8fd4604d0cc64a2005a23 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Jul 2013 13:22:11 +0200 Subject: [PATCH 2270/2900] ACPI / PM: Fix corner case in acpi_bus_update_power() The role of acpi_bus_update_power() is to update the given ACPI device object's power.state field to reflect the current physical state of the device (as inferred from the configuration of power resources and _PSC, if available). For this purpose it calls acpi_device_set_power() that should update the power resources' reference counters and set power.state as appropriate. However, that doesn't work if the "new" state is D1, D2 or D3hot and the the current value of power.state means D3cold, because in that case acpi_device_set_power() will refuse to transition the device from D3cold to non-D0. To address this problem, make acpi_bus_update_power() call acpi_power_transition() directly to update the power resources' reference counters and only use acpi_device_set_power() to put the device into D0 if the current physical state of it cannot be determined. Signed-off-by: Rafael J. Wysocki Cc: 3.9+ --- drivers/acpi/device_pm.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index e9e8bb24785b..4ab807dc8518 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -324,14 +324,27 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p) if (result) return result; - if (state == ACPI_STATE_UNKNOWN) + if (state == ACPI_STATE_UNKNOWN) { state = ACPI_STATE_D0; - - result = acpi_device_set_power(device, state); - if (!result && state_p) + result = acpi_device_set_power(device, state); + if (result) + return result; + } else { + if (device->power.flags.power_resources) { + /* + * We don't need to really switch the state, bu we need + * to update the power resources' reference counters. + */ + result = acpi_power_transition(device, state); + if (result) + return result; + } + device->power.state = state; + } + if (state_p) *state_p = state; - return result; + return 0; } EXPORT_SYMBOL_GPL(acpi_bus_update_power); -- GitLab From 37bd6ca8ab6c103603e04e320d3debeb4596e481 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Tue, 28 May 2013 11:54:48 +0530 Subject: [PATCH 2271/2900] ARM: OMAP2+: timer: initialize before using oh_name of_property_read_string_index(...,&oh_name) in omap_dm_timer_init_one does not alter the value of 'oh_name' even if the relevant function fails and as 'oh_name' in stack may have a non-zero value, it would be misunderstood by timer code that DT has specified "ti,hwmod" property for timer. 'oh_name' in this scenario would be a junk value, this would result in module not being enabled by hwmod API's for timer, and in turn crash. Signed-off-by: Afzal Mohammed Acked-by: Jon Hunter Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 3bdb0fb02028..5f148e721790 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -220,7 +220,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, int posted) { char name[10]; /* 10 = sizeof("gptXX_Xck0") */ - const char *oh_name; + const char *oh_name = NULL; struct device_node *np; struct omap_hwmod *oh; struct resource irq, mem; -- GitLab From 2ce65fe89153b6091393541de7e211d505436ff7 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Jul 2013 13:25:04 +0200 Subject: [PATCH 2272/2900] ACPI / dock: Actually define acpi_dock_init() as void Commit 94add0f (ACPI / dock: Initialize ACPI dock subsystem upfront) changed the header of acpi_dock_init() in internal.h so that it is supposed to be a void function now, but it forgot to update its actual definition in dock.c according to which it still is supposed to return int. Although that didn't cause any visible breakage or even a compiler warning to be thrown, which is odd enough, fix it. Signed-off-by: Rafael J. Wysocki Cc: 3.10+ --- drivers/acpi/dock.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 14de9f46972e..826560753389 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -1064,10 +1064,10 @@ find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -int __init acpi_dock_init(void) +void __init acpi_dock_init(void) { if (acpi_disabled) - return 0; + return; /* look for dock stations and bays */ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, @@ -1075,11 +1075,10 @@ int __init acpi_dock_init(void) if (!dock_station_count) { pr_info(PREFIX "No dock devices found.\n"); - return 0; + return; } register_acpi_bus_notifier(&dock_acpi_notifier); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); - return 0; } -- GitLab From b67cf7c44c7e6b485f1c255ac3c1fe98cc99b677 Mon Sep 17 00:00:00 2001 From: Haicheng Li Date: Thu, 4 Jul 2013 12:07:11 +0800 Subject: [PATCH 2273/2900] ACPI / scan: remove unused LIST_HEAD(acpi_device_list) The acpi_device_list list is not used, so removed it. [rjw: Changelog] Signed-off-by: Haicheng Li Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index dfe76f17cfc4..10985573aaa7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -35,7 +35,6 @@ bool acpi_force_hot_remove; static const char *dummy_hid = "device"; -static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); static DEFINE_MUTEX(acpi_scan_lock); static LIST_HEAD(acpi_scan_handlers_list); -- GitLab From 85eb98274fd81c44e721c275ced54661ee9d5b05 Mon Sep 17 00:00:00 2001 From: Naresh Bhat Date: Mon, 1 Jul 2013 19:51:00 +0530 Subject: [PATCH 2274/2900] ACPI / fan: Initialize acpi_state variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the following compiler warning go away: CC drivers/acpi/fan.o drivers/acpi/fan.c: In function ‘fan_get_cur_state’: drivers/acpi/fan.c:96:9: warning: ‘acpi_state’ may be used uninitialized in this function [-Wuninitialized] by initializing the local variable acpi_state in fan_get_cur_state(). [rjw: Changelog] Signed-off-by: Naresh Bhat Signed-off-by: Rafael J. Wysocki --- drivers/acpi/fan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 8d1c0105e113..5b02a0aa540c 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -84,7 +84,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long { struct acpi_device *device = cdev->devdata; int result; - int acpi_state; + int acpi_state = ACPI_STATE_D0; if (!device) return -EINVAL; -- GitLab From b46355a920a3dbdce7365d2e39eefd6c7b87c22a Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 26 Jun 2013 09:39:46 -0500 Subject: [PATCH 2275/2900] ARM: OMAP4: sleep: build OMAP4 specific functions only for OMAP4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPU sleep and resume functions for Cortex-A9 based OMAP4 and Cortex-A15 based OMAP5 are different. Hence, even though we reuse most of the remaining file as part of OMAP4/5 consolidation, build OMAP4 specific sleep/resume operations only for OMAP4. SCU is not used OMAP5. This fixes the following build failure with OMAP5 only build: arch/arm/mach-omap2/built-in.o: In function `scu_gp_set': arch/arm/mach-omap2/sleep44xx.S:132: undefined reference to `scu_power_mode' arch/arm/mach-omap2/built-in.o: In function `scu_gp_clear': arch/arm/mach-omap2/sleep44xx.S:229: undefined reference to `scu_power_mode' Reported-by: Pekon Gupta Reported-by: Vincent Stehlé Acked-by: Santosh Shilimkar Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sleep44xx.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S index 88ff83a0942e..9086ce03ae12 100644 --- a/arch/arm/mach-omap2/sleep44xx.S +++ b/arch/arm/mach-omap2/sleep44xx.S @@ -34,6 +34,8 @@ ppa_zero_params: ppa_por_params: .word 1, 0 +#ifdef CONFIG_ARCH_OMAP4 + /* * ============================= * == CPU suspend finisher == @@ -326,7 +328,9 @@ skip_l2en: b cpu_resume @ Jump to generic resume ENDPROC(omap4_cpu_resume) -#endif +#endif /* CONFIG_ARCH_OMAP4 */ + +#endif /* defined(CONFIG_SMP) && defined(CONFIG_PM) */ #ifndef CONFIG_OMAP4_ERRATA_I688 ENTRY(omap_bus_sync) -- GitLab From 2abc75a8c52af5e9cd32223554e6071e07b44559 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Wed, 26 Jun 2013 09:39:47 -0500 Subject: [PATCH 2276/2900] ARM: scu: provide inline dummy functions when SCU is not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On platforms such as Cortex-A15 based OMAP5, SCU is not used, however since much code is shared between Cortex-A9 based OMAP4 (which uses SCU) and OMAP5, It does help to have inline functions returning error values when SCU is not present on the platform. arch/arm/mach-omap2/omap-smp.c which is common between OMAP4 and 5 handles the SCU usage only for OMAP4. This fixes the following build failure with OMAP5 only build: arch/arm/mach-omap2/built-in.o: In function `omap4_smp_init_cpus': arch/arm/mach-omap2/omap-smp.c:185: undefined reference to `scu_get_core_count' arch/arm/mach-omap2/built-in.o: In function `omap4_smp_prepare_cpus': arch/arm/mach-omap2/omap-smp.c:211: undefined reference to `scu_enable' Reported-by: Pekon Gupta Reported-by: Vincent Stehlé Acked-by: Santosh Shilimkar Signed-off-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/include/asm/smp_scu.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h index 18d169373612..0393fbab8dd5 100644 --- a/arch/arm/include/asm/smp_scu.h +++ b/arch/arm/include/asm/smp_scu.h @@ -23,10 +23,21 @@ static inline unsigned long scu_a9_get_base(void) return pa; } +#ifdef CONFIG_HAVE_ARM_SCU unsigned int scu_get_core_count(void __iomem *); int scu_power_mode(void __iomem *, unsigned int); +#else +static inline unsigned int scu_get_core_count(void __iomem *scu_base) +{ + return 0; +} +static inline int scu_power_mode(void __iomem *scu_base, unsigned int mode) +{ + return -EINVAL; +} +#endif -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) && defined(CONFIG_HAVE_ARM_SCU) void scu_enable(void __iomem *scu_base); #else static inline void scu_enable(void __iomem *scu_base) {} -- GitLab From 62618c17e077b22bb12bdf754ca5bf89f2ae4dcd Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 19 Jun 2013 15:52:12 -0400 Subject: [PATCH 2277/2900] ARM: OMAP5: Enable Cortex A15 errata 798181 ARM errata 798181 is applicable for OMAP5 based devices. So enable the same in the build. Errata extract and workaround information is as below. On Cortex-A15 (r0p0..r3p2) the TLBI*IS/DSB operations are not adequately shooting down all use of the old entries. The ARM_ERRATA_798181 option enables the Linux kernel workaround for this erratum which sends an IPI to the CPUs that are running the same ASID as the one being invalidated. Cc: Tony Lindgren Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index c7b32a966f67..e658f7a272e4 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -114,6 +114,7 @@ config SOC_OMAP5 select HAVE_SMP select COMMON_CLK select HAVE_ARM_ARCH_TIMER + select ARM_ERRATA_798181 comment "OMAP Core Type" depends on ARCH_OMAP2 -- GitLab From 9847bd481084249b30308776ecf660b486a6c3d8 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 30 May 2013 13:20:23 +0200 Subject: [PATCH 2278/2900] ARM: OMAP2+: Remove obsolete Makefile line The OMAP runtime PM implementation was removed in v3.0. But one Makefile line, which was used to tweak CFLAGS, was overlooked. Remove it too. Signed-off-by: Paul Bolle Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index ea5a27ff9941..d4f671547c37 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -95,10 +95,6 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o AFLAGS_sleep24xx.o :=-Wa,-march=armv6 AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) -ifeq ($(CONFIG_PM_VERBOSE),y) -CFLAGS_pm_bus.o += -DDEBUG -endif - endif ifeq ($(CONFIG_CPU_IDLE),y) -- GitLab From 1261674a2dded2b5b055f51fb44677a8654d3f06 Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Sat, 1 Jun 2013 11:44:44 +0200 Subject: [PATCH 2279/2900] ARM: OMAP2+: Cocci spatch "ptr_ret.spatch" Cocci spatch "ptr_ret.spatch" Signed-off-by: Thomas Meyer Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/devices.c | 4 ++-- arch/arm/mach-omap2/fb.c | 5 +---- arch/arm/mach-omap2/gpmc.c | 2 +- arch/arm/mach-omap2/pmu.c | 5 +---- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index aef96e45cb20..c3bc58b88fa6 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -66,7 +66,7 @@ static int __init omap3_l3_init(void) WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); - return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; + return PTR_RET(pdev); } omap_postcore_initcall(omap3_l3_init); @@ -100,7 +100,7 @@ static int __init omap4_l3_init(void) WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); - return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; + return PTR_RET(pdev); } omap_postcore_initcall(omap4_l3_init); diff --git a/arch/arm/mach-omap2/fb.c b/arch/arm/mach-omap2/fb.c index 190ae493c6ef..2ca33cc0c484 100644 --- a/arch/arm/mach-omap2/fb.c +++ b/arch/arm/mach-omap2/fb.c @@ -83,10 +83,7 @@ static int __init omap_init_vrfb(void) pdev = platform_device_register_resndata(NULL, "omapvrfb", -1, res, num_res, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - else - return 0; + return PTR_RET(pdev); } omap_arch_initcall(omap_init_vrfb); diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 1c7969e965d7..f3fdd6afa213 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1734,7 +1734,7 @@ static int __init omap_gpmc_init(void) pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0); WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); - return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; + return PTR_RET(pdev); } omap_postcore_initcall(omap_gpmc_init); diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index 9ace8eae7ee8..33c8846b4193 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -54,10 +54,7 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[]) WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n", dev_name); - if (IS_ERR(omap_pmu_dev)) - return PTR_ERR(omap_pmu_dev); - - return 0; + return PTR_RET(omap_pmu_dev); } static int __init omap_init_pmu(void) -- GitLab From ea2409bab7ee7c309e558f257a3b6b7e8233f209 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 1 Jul 2013 23:15:04 +0200 Subject: [PATCH 2280/2900] ARM: OMAP2+: N900: enable N900-specific drivers even if device tree is enabled We still need video & sound drivers with device tree enabled. Signed-off-by: Pavel Machek Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-rx51-video.c | 2 +- sound/soc/omap/rx51.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c index bd74f9f6063b..bdd1e3a179e1 100644 --- a/arch/arm/mach-omap2/board-rx51-video.c +++ b/arch/arm/mach-omap2/board-rx51-video.c @@ -61,7 +61,7 @@ static struct omap_dss_board_info rx51_dss_board_info = { static int __init rx51_video_init(void) { - if (!machine_is_nokia_rx51()) + if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900")) return 0; if (omap_mux_init_gpio(RX51_LCD_RESET_GPIO, OMAP_PIN_OUTPUT)) { diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 249cd230ad8f..611179c3bca4 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -396,7 +396,7 @@ static int __init rx51_soc_init(void) { int err; - if (!machine_is_nokia_rx51()) + if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900")) return -ENODEV; err = gpio_request_one(RX51_TVOUT_SEL_GPIO, -- GitLab From e94eb1ac8ef14ae6a745815d2c184225febfd189 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Wed, 19 Jun 2013 18:24:43 +0200 Subject: [PATCH 2281/2900] ARM: OMAP3: igep0020: Set DSS pins in correct mux mode. Platform code used to depend on bootloadres for correctly setting the mux pin modes. But bootloaders should only set the minimum required mux pins. So, DSS mux pins are not set in U-Boot anymore and video display is broken on IGEPv2 when booting with newer U-Boot versions. Setup the DSS pin muxes to enable display functionality. Signed-off-by: Enric Balletbo i Serra Reviewed-by: Javier Martinez Canillas Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-igep0020.c | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index b54562d1235e..87e65dde8e13 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -553,6 +553,37 @@ static struct usbhs_omap_platform_data igep3_usbhs_bdata __initdata = { #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { + /* Display Sub System */ + OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA9, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA10, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA11, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA12, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA13, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA14, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), + /* TFP410 PanelBus DVI Transmitte (GPIO_170) */ + OMAP3_MUX(HDQ_SIO, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), /* SMSC9221 LAN Controller ETH IRQ (GPIO_176) */ OMAP3_MUX(MCSPI1_CS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), { .reg_offset = OMAP_MUX_TERMINATOR }, -- GitLab From 7f161ce76d356c496af6ef5ee3a896d4bf18e3eb Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 20 Jun 2013 08:01:05 +0800 Subject: [PATCH 2282/2900] ARM: OMAP2+: devices: remove duplicated include from devices.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/devices.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c3bc58b88fa6..3c1279f27d1f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include -- GitLab From 84793c77e13093627f462da616c55f425c2161be Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Fri, 7 Jun 2013 16:46:07 -0400 Subject: [PATCH 2283/2900] ARM: OMAP2+: omap2plus_defconfig: enable TI bandgap driver Enable the bandgap driver for TI SoCs thermal support. Cc: Russell King Cc: Tony Lindgren Cc: Javier Martinez Canillas Cc: AnilKumar Ch Cc: Santosh Shilimkar Cc: Tomi Valkeinen Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 2ac0ffb12f03..b160bb90fb11 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -152,6 +152,13 @@ CONFIG_W1=y CONFIG_POWER_SUPPLY=y CONFIG_SENSORS_LM75=m CONFIG_WATCHDOG=y +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_THERMAL=y CONFIG_OMAP_WATCHDOG=y CONFIG_TWL4030_WATCHDOG=y CONFIG_MFD_TPS65217=y @@ -239,6 +246,10 @@ CONFIG_RTC_DRV_TWL4030=y CONFIG_RTC_DRV_OMAP=y CONFIG_DMADEVICES=y CONFIG_DMA_OMAP=y +CONFIG_TI_SOC_THERMAL=y +CONFIG_TI_THERMAL=y +CONFIG_OMAP4_THERMAL=y +CONFIG_OMAP5_THERMAL=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -- GitLab From 9c18ae3e8f2d76213a244e811b48332f0ebc4e04 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Fri, 7 Jun 2013 16:46:08 -0400 Subject: [PATCH 2284/2900] ARM: OMAP2+: omap2plus_defconfig: enable DRA752 thermal support by default Make DRA752 thermal support enabled on omap2plus_defconfig Cc: Russell King Cc: Tony Lindgren Cc: Javier Martinez Canillas Cc: AnilKumar Ch Cc: Santosh Shilimkar Cc: Tomi Valkeinen Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index b160bb90fb11..61b76b0f7e82 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -250,6 +250,7 @@ CONFIG_TI_SOC_THERMAL=y CONFIG_TI_THERMAL=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y +CONFIG_DRA752_THERMAL=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -- GitLab From fb15bdfbd76dae771069d2a93ebe4bbf84f361d0 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Wed, 26 Jun 2013 22:42:03 -0500 Subject: [PATCH 2285/2900] ARM: OMAP2+: Enable TI_EDMA in omap2plus_defconfig Build EDMA in by default to avoid fewer people stepping on their toes with broken DMA on drivers needing EDMA. Signed-off-by: Joel Fernandes Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 61b76b0f7e82..009fa6944687 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -245,6 +245,7 @@ CONFIG_RTC_DRV_TWL92330=y CONFIG_RTC_DRV_TWL4030=y CONFIG_RTC_DRV_OMAP=y CONFIG_DMADEVICES=y +CONFIG_TI_EDMA=y CONFIG_DMA_OMAP=y CONFIG_TI_SOC_THERMAL=y CONFIG_TI_THERMAL=y -- GitLab From c24a6ae18abde53b048372b066b93b71b1b91154 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 1 Jul 2013 09:13:13 -0400 Subject: [PATCH 2286/2900] ARM: OMAP2+: omap2plus_defconfig: Enable appended DTB support As this config must support boards which cannot support separate device trees, enable support for appended ones. Cc: Tony Lindgren Cc: Russell King Signed-off-by: Tom Rini Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 009fa6944687..a58d57017fed 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -34,6 +34,8 @@ CONFIG_NR_CPUS=2 CONFIG_LEDS=y CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200" CONFIG_KEXEC=y CONFIG_FPE_NWFPE=y -- GitLab From c3eb5b14449a0949e9764d39374a2ea63faae14f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 4 Jul 2013 13:34:32 +0100 Subject: [PATCH 2287/2900] arm64: KVM: Kconfig integration Finally plug KVM/arm64 into the config system, making it possible to enable KVM support on AArch64 CPUs. Signed-off-by: Marc Zyngier Signed-off-by: Paolo Bonzini --- arch/arm64/Kconfig | 2 ++ arch/arm64/kernel/asm-offsets.c | 1 + arch/arm64/kvm/Kconfig | 51 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 arch/arm64/kvm/Kconfig diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 4143d9b0d87a..9737e97f9f38 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -270,6 +270,8 @@ source "drivers/Kconfig" source "fs/Kconfig" +source "arch/arm64/kvm/Kconfig" + source "arch/arm64/Kconfig.debug" source "security/Kconfig" diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 49c162c03b69..666e231d410b 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig new file mode 100644 index 000000000000..21e90820bd23 --- /dev/null +++ b/arch/arm64/kvm/Kconfig @@ -0,0 +1,51 @@ +# +# KVM configuration +# + +source "virt/kvm/Kconfig" + +menuconfig VIRTUALIZATION + bool "Virtualization" + ---help--- + Say Y here to get to see options for using your Linux host to run + other operating systems inside virtual machines (guests). + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and + disabled. + +if VIRTUALIZATION + +config KVM + bool "Kernel-based Virtual Machine (KVM) support" + select MMU_NOTIFIER + select PREEMPT_NOTIFIERS + select ANON_INODES + select KVM_MMIO + select KVM_ARM_HOST + select KVM_ARM_VGIC + select KVM_ARM_TIMER + ---help--- + Support hosting virtualized guest machines. + + If unsure, say N. + +config KVM_ARM_HOST + bool + ---help--- + Provides host support for ARM processors. + +config KVM_ARM_VGIC + bool + depends on KVM_ARM_HOST && OF + select HAVE_KVM_IRQCHIP + ---help--- + Adds support for a hardware assisted, in-kernel GIC emulation. + +config KVM_ARM_TIMER + bool + depends on KVM_ARM_VGIC + ---help--- + Adds support for the Architected Timers in virtual machines. + +endif # VIRTUALIZATION -- GitLab From 03617c188f41eeeb4223c919ee7e66e5a114f2c6 Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Fri, 28 Jun 2013 13:17:18 +0300 Subject: [PATCH 2288/2900] KVM: VMX: mark unusable segment as nonpresent Some userspaces do not preserve unusable property. Since usable segment has to be present according to VMX spec we can use present property to amend userspace bug by making unusable segment always nonpresent. vmx_segment_access_rights() already marks nonpresent segment as unusable. Cc: stable@vger.kernel.org # 3.9+ Reported-by: Stefan Pietsch Tested-by: Stefan Pietsch Signed-off-by: Gleb Natapov Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a7e18551c968..064d0be67ecc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3404,15 +3404,22 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu, var->limit = vmx_read_guest_seg_limit(vmx, seg); var->selector = vmx_read_guest_seg_selector(vmx, seg); ar = vmx_read_guest_seg_ar(vmx, seg); + var->unusable = (ar >> 16) & 1; var->type = ar & 15; var->s = (ar >> 4) & 1; var->dpl = (ar >> 5) & 3; - var->present = (ar >> 7) & 1; + /* + * Some userspaces do not preserve unusable property. Since usable + * segment has to be present according to VMX spec we can use present + * property to amend userspace bug by making unusable segment always + * nonpresent. vmx_segment_access_rights() already marks nonpresent + * segment as unusable. + */ + var->present = !var->unusable; var->avl = (ar >> 12) & 1; var->l = (ar >> 13) & 1; var->db = (ar >> 14) & 1; var->g = (ar >> 15) & 1; - var->unusable = (ar >> 16) & 1; } static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg) -- GitLab From b3ff04668c5a36c290e5b2849b6c86ceb3aec2c3 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 4 Jul 2013 16:24:37 +0530 Subject: [PATCH 2289/2900] ASoC: Samsung: Remove redundant comment There is a typo in the filename (i2c mentioned instead of i2s). However, this is a redundant piece of information. Delete it altogether. Signed-off-by: Sachin Kamat Signed-off-by: Mark Brown --- sound/soc/samsung/s3c-i2s-v2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 20e98d1dded2..e5e81b111001 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -1,6 +1,4 @@ -/* sound/soc/samsung/s3c-i2c-v2.c - * - * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs. +/* ALSA Soc Audio Layer - I2S core for newer Samsung SoCs. * * Copyright (c) 2006 Wolfson Microelectronics PLC. * Graeme Gregory graeme.gregory@wolfsonmicro.com -- GitLab From f2e055e7c9c6084bfbaa68701e52562acf96419e Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 4 Jul 2013 13:11:03 +0200 Subject: [PATCH 2290/2900] regmap: cache: bail in regmap_async_complete() for bus-less maps Commit f8bd822cb ("regmap: cache: Factor out block sync") made regcache_rbtree_sync() call regmap_async_complete(), which in turn does not check for map->bus before dereferencing it. This causes a NULL pointer dereference on bus-less maps. Signed-off-by: Daniel Mack Cc: stable@vger.kernel.org [v3.10 only] Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index a941dcfe7590..d0c81d1f409c 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1717,7 +1717,7 @@ int regmap_async_complete(struct regmap *map) int ret; /* Nothing to do with no async support */ - if (!map->bus->async_write) + if (!map->bus || !map->bus->async_write) return 0; trace_regmap_async_complete_start(map->dev); -- GitLab From 28e5ca73ef9072ed58dbb81cfff6f908be8e3cd4 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Thu, 20 Jun 2013 23:20:49 +0200 Subject: [PATCH 2291/2900] ASoC: imx-sgtl5000: return E_PROBE_DEFER if ssi/codec not found If the ssi or codec drivers are not loaded (for instance, because spi or i2c bus drivers are not loaded), returning -EINVAL will for people to unload and then reload the module to get sound working. Returning E_PROBE_DEFER will mitigate this. Signed-off-by: Arnaud Patard Signed-off-by: Mark Brown --- sound/soc/fsl/imx-sgtl5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c index 7a8bc1220b2e..3f726e4f88db 100644 --- a/sound/soc/fsl/imx-sgtl5000.c +++ b/sound/soc/fsl/imx-sgtl5000.c @@ -113,13 +113,13 @@ static int imx_sgtl5000_probe(struct platform_device *pdev) ssi_pdev = of_find_device_by_node(ssi_np); if (!ssi_pdev) { dev_err(&pdev->dev, "failed to find SSI platform device\n"); - ret = -EINVAL; + ret = -EPROBE_DEFER; goto fail; } codec_dev = of_find_i2c_device_by_node(codec_np); if (!codec_dev) { dev_err(&pdev->dev, "failed to find codec platform device\n"); - return -EINVAL; + return -EPROBE_DEFER; } data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); -- GitLab From 4642aabd21d0491a7d9dcbe789bdf93a596f771c Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 4 Jul 2013 23:14:00 +0800 Subject: [PATCH 2292/2900] ASoC: wm8962: fix NULL pdata pointer There is an error in merge commit 384b834 on conflict resolution which causes the following NULL pdata pointer bug. wm8962 0-001a: customer id 0 revision D Unable to handle kernel NULL pointer dereference at virtual address 00000004 pgd = 80004000 [00000004] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0+ #1 task: bf870000 ti: bf874000 task.ti: bf874000 PC is at wm8962_probe+0x134/0x6c8 LR is at regmap_unlock_mutex+0x10/0x14 pc : [<80452100>] lr : [<80304cf4>] psr: a0000113 sp : bf875c98 ip : 00000000 fp : bf875cd4 r10: 00000000 r9 : bfb1830c r8 : 80779bc4 r7 : 00000000 r6 : 00000001 r5 : bfbac010 r4 : bfb33e00 r3 : 80304ce4 r2 : 00000000 r1 : 00000001 r0 : fffffffb Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c53c7d Table: 1000404a DAC: 00000017 Process swapper/0 (pid: 1, stack limit = 0xbf874238) Stack: (0xbf875c98 to 0xbf876000) ... Fix the error by assigning pdata a correct pointer. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index b1dc7d426438..e2de9ecfd641 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3377,7 +3377,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) { int ret; struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); + struct wm8962_pdata *pdata = &wm8962->pdata; int i, trigger, irq_pol; bool dmicclk, dmicdat; -- GitLab From 95dc8dd14e2e84cc3adabc8310768c13758e7d96 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 4 Jul 2013 10:35:21 -0500 Subject: [PATCH 2293/2900] Limit allocation of crypto mechanisms to dialect which requires Updated patch to try to prevent allocation of cifs, smb2 or smb3 crypto secmech structures unless needed. Currently cifs allocates all crypto mechanisms when the first session is established (4 functions and 4 contexts), rather than only allocating these when needed (smb3 needs two, the rest of the dialects only need one). Acked-by: Jeff Layton Reviewed-by: Shirish Pargaonkar Signed-off-by: Steve French --- fs/cifs/cifsencrypt.c | 195 ++++++++++++++++++---------------------- fs/cifs/cifsproto.h | 1 - fs/cifs/connect.c | 6 -- fs/cifs/smb2transport.c | 90 ++++++++++++++++++- 4 files changed, 174 insertions(+), 118 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 3d8bf941d126..45e57cc38200 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifsencrypt.c * - * Copyright (C) International Business Machines Corp., 2005,2006 + * Copyright (C) International Business Machines Corp., 2005,2013 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -31,6 +31,36 @@ #include #include +static int +cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) +{ + int rc; + unsigned int size; + + if (server->secmech.sdescmd5 != NULL) + return 0; /* already allocated */ + + server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); + if (IS_ERR(server->secmech.md5)) { + cifs_dbg(VFS, "could not allocate crypto md5\n"); + return PTR_ERR(server->secmech.md5); + } + + size = sizeof(struct shash_desc) + + crypto_shash_descsize(server->secmech.md5); + server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); + if (!server->secmech.sdescmd5) { + rc = -ENOMEM; + crypto_free_shash(server->secmech.md5); + server->secmech.md5 = NULL; + return rc; + } + server->secmech.sdescmd5->shash.tfm = server->secmech.md5; + server->secmech.sdescmd5->shash.flags = 0x0; + + return 0; +} + /* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the @@ -50,8 +80,11 @@ static int cifs_calc_signature(struct smb_rqst *rqst, return -EINVAL; if (!server->secmech.sdescmd5) { - cifs_dbg(VFS, "%s: Can't generate signature\n", __func__); - return -1; + rc = cifs_crypto_shash_md5_allocate(server); + if (rc) { + cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); + return -1; + } } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); @@ -556,6 +589,33 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) return rc; } +static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) +{ + unsigned int size; + + /* check if already allocated */ + if (server->secmech.sdeschmacmd5) + return 0; + + server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); + if (IS_ERR(server->secmech.hmacmd5)) { + cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); + return PTR_ERR(server->secmech.hmacmd5); + } + + size = sizeof(struct shash_desc) + + crypto_shash_descsize(server->secmech.hmacmd5); + server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); + if (!server->secmech.sdeschmacmd5) { + crypto_free_shash(server->secmech.hmacmd5); + server->secmech.hmacmd5 = NULL; + return -ENOMEM; + } + server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; + server->secmech.sdeschmacmd5->shash.flags = 0x0; + + return 0; +} int setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) @@ -606,6 +666,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) memcpy(ses->auth_key.response + baselen, tiblob, tilen); + rc = crypto_hmacmd5_alloc(ses->server); + if (rc) { + cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc); + goto setup_ntlmv2_rsp_ret; + } + /* calculate ntlmv2_hash */ rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp); if (rc) { @@ -705,123 +771,32 @@ calc_seckey(struct cifs_ses *ses) void cifs_crypto_shash_release(struct TCP_Server_Info *server) { - if (server->secmech.cmacaes) + if (server->secmech.cmacaes) { crypto_free_shash(server->secmech.cmacaes); + server->secmech.cmacaes = NULL; + } - if (server->secmech.hmacsha256) + if (server->secmech.hmacsha256) { crypto_free_shash(server->secmech.hmacsha256); + server->secmech.hmacsha256 = NULL; + } - if (server->secmech.md5) + if (server->secmech.md5) { crypto_free_shash(server->secmech.md5); + server->secmech.md5 = NULL; + } - if (server->secmech.hmacmd5) + if (server->secmech.hmacmd5) { crypto_free_shash(server->secmech.hmacmd5); + server->secmech.hmacmd5 = NULL; + } kfree(server->secmech.sdesccmacaes); - + server->secmech.sdesccmacaes = NULL; kfree(server->secmech.sdeschmacsha256); - + server->secmech.sdeschmacsha256 = NULL; kfree(server->secmech.sdeschmacmd5); - + server->secmech.sdeschmacmd5 = NULL; kfree(server->secmech.sdescmd5); -} - -int -cifs_crypto_shash_allocate(struct TCP_Server_Info *server) -{ - int rc; - unsigned int size; - - server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); - if (IS_ERR(server->secmech.hmacmd5)) { - cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); - return PTR_ERR(server->secmech.hmacmd5); - } - - server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); - if (IS_ERR(server->secmech.md5)) { - cifs_dbg(VFS, "could not allocate crypto md5\n"); - rc = PTR_ERR(server->secmech.md5); - goto crypto_allocate_md5_fail; - } - - server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); - if (IS_ERR(server->secmech.hmacsha256)) { - cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); - rc = PTR_ERR(server->secmech.hmacsha256); - goto crypto_allocate_hmacsha256_fail; - } - - server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0); - if (IS_ERR(server->secmech.cmacaes)) { - cifs_dbg(VFS, "could not allocate crypto cmac-aes"); - rc = PTR_ERR(server->secmech.cmacaes); - goto crypto_allocate_cmacaes_fail; - } - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.hmacmd5); - server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdeschmacmd5) { - rc = -ENOMEM; - goto crypto_allocate_hmacmd5_sdesc_fail; - } - server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5; - server->secmech.sdeschmacmd5->shash.flags = 0x0; - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.md5); - server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdescmd5) { - rc = -ENOMEM; - goto crypto_allocate_md5_sdesc_fail; - } - server->secmech.sdescmd5->shash.tfm = server->secmech.md5; - server->secmech.sdescmd5->shash.flags = 0x0; - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.hmacsha256); - server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdeschmacsha256) { - rc = -ENOMEM; - goto crypto_allocate_hmacsha256_sdesc_fail; - } - server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; - server->secmech.sdeschmacsha256->shash.flags = 0x0; - - size = sizeof(struct shash_desc) + - crypto_shash_descsize(server->secmech.cmacaes); - server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL); - if (!server->secmech.sdesccmacaes) { - cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__); - rc = -ENOMEM; - goto crypto_allocate_cmacaes_sdesc_fail; - } - server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes; - server->secmech.sdesccmacaes->shash.flags = 0x0; - - return 0; - -crypto_allocate_cmacaes_sdesc_fail: - kfree(server->secmech.sdeschmacsha256); - -crypto_allocate_hmacsha256_sdesc_fail: - kfree(server->secmech.sdescmd5); - -crypto_allocate_md5_sdesc_fail: - kfree(server->secmech.sdeschmacmd5); - -crypto_allocate_hmacmd5_sdesc_fail: - crypto_free_shash(server->secmech.cmacaes); - -crypto_allocate_cmacaes_fail: - crypto_free_shash(server->secmech.hmacsha256); - -crypto_allocate_hmacsha256_fail: - crypto_free_shash(server->secmech.md5); - -crypto_allocate_md5_fail: - crypto_free_shash(server->secmech.hmacmd5); - - return rc; + server->secmech.sdescmd5 = NULL; } diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index c8ff018fae68..f7e584d047e2 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -433,7 +433,6 @@ extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, const struct nls_table *); extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); -extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); extern void cifs_crypto_shash_release(struct TCP_Server_Info *); extern int calc_seckey(struct cifs_ses *); extern void generate_smb3signingkey(struct TCP_Server_Info *); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index afcb8a1a33b7..fa68813396b5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2108,12 +2108,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info) goto out_err; } - rc = cifs_crypto_shash_allocate(tcp_ses); - if (rc) { - cifs_dbg(VFS, "could not setup hash structures rc %d\n", rc); - goto out_err; - } - tcp_ses->ops = volume_info->ops; tcp_ses->vals = volume_info->vals; cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 09b4fbaadeb6..301b191270b9 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -39,6 +39,77 @@ #include "smb2status.h" #include "smb2glob.h" +static int +smb2_crypto_shash_allocate(struct TCP_Server_Info *server) +{ + unsigned int size; + + if (server->secmech.sdeschmacsha256 != NULL) + return 0; /* already allocated */ + + server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); + if (IS_ERR(server->secmech.hmacsha256)) { + cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); + return PTR_ERR(server->secmech.hmacsha256); + } + + size = sizeof(struct shash_desc) + + crypto_shash_descsize(server->secmech.hmacsha256); + server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL); + if (!server->secmech.sdeschmacsha256) { + crypto_free_shash(server->secmech.hmacsha256); + server->secmech.hmacsha256 = NULL; + return -ENOMEM; + } + server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256; + server->secmech.sdeschmacsha256->shash.flags = 0x0; + + return 0; +} + +static int +smb3_crypto_shash_allocate(struct TCP_Server_Info *server) +{ + unsigned int size; + int rc; + + if (server->secmech.sdesccmacaes != NULL) + return 0; /* already allocated */ + + rc = smb2_crypto_shash_allocate(server); + if (rc) + return rc; + + server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0); + if (IS_ERR(server->secmech.cmacaes)) { + cifs_dbg(VFS, "could not allocate crypto cmac-aes"); + kfree(server->secmech.sdeschmacsha256); + server->secmech.sdeschmacsha256 = NULL; + crypto_free_shash(server->secmech.hmacsha256); + server->secmech.hmacsha256 = NULL; + return PTR_ERR(server->secmech.cmacaes); + } + + size = sizeof(struct shash_desc) + + crypto_shash_descsize(server->secmech.cmacaes); + server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL); + if (!server->secmech.sdesccmacaes) { + cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__); + kfree(server->secmech.sdeschmacsha256); + server->secmech.sdeschmacsha256 = NULL; + crypto_free_shash(server->secmech.hmacsha256); + crypto_free_shash(server->secmech.cmacaes); + server->secmech.hmacsha256 = NULL; + server->secmech.cmacaes = NULL; + return -ENOMEM; + } + server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes; + server->secmech.sdesccmacaes->shash.flags = 0x0; + + return 0; +} + + int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { @@ -52,6 +123,12 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); + rc = smb2_crypto_shash_allocate(server); + if (rc) { + cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__); + return rc; + } + rc = crypto_shash_setkey(server->secmech.hmacsha256, server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); if (rc) { @@ -61,7 +138,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash); if (rc) { - cifs_dbg(VFS, "%s: Could not init md5\n", __func__); + cifs_dbg(VFS, "%s: Could not init sha256", __func__); return rc; } @@ -129,6 +206,12 @@ generate_smb3signingkey(struct TCP_Server_Info *server) memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); memset(server->smb3signingkey, 0x0, SMB3_SIGNKEY_SIZE); + rc = smb3_crypto_shash_allocate(server); + if (rc) { + cifs_dbg(VFS, "%s: crypto alloc failed\n", __func__); + goto smb3signkey_ret; + } + rc = crypto_shash_setkey(server->secmech.hmacsha256, server->session_key.response, SMB2_NTLMV2_SESSKEY_SIZE); if (rc) { @@ -210,6 +293,11 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } + /* + * we already allocate sdesccmacaes when we init smb3 signing key, + * so unlike smb2 case we do not have to check here if secmech are + * initialized + */ rc = crypto_shash_init(&server->secmech.sdesccmacaes->shash); if (rc) { cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); -- GitLab From 6658b9f70ebca5fc0795b1d6d733996af1e2caa7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 4 Jul 2013 14:38:48 -0500 Subject: [PATCH 2294/2900] [CIFS] use sensible file nlink values if unprovided Certain servers may not set the NumberOfLinks field in query file/path info responses. In such a case, cifs_inode_needs_reval() assumes that all regular files are hardlinks and triggers revalidation, leading to excessive and unnecessary network traffic. This change hardcodes cf_nlink (and subsequently i_nlink) when not returned by the server, similar to what already occurs in cifs_mkdir(). Cc: Signed-off-by: David Disseldorp Signed-off-by: Steve French --- fs/cifs/inode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 20efd81266c6..449b6cf09b09 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -558,6 +558,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, fattr->cf_mode &= ~(S_IWUGO); fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); + if (fattr->cf_nlink < 1) { + cifs_dbg(1, "replacing bogus file nlink value %u\n", + fattr->cf_nlink); + fattr->cf_nlink = 1; + } } fattr->cf_uid = cifs_sb->mnt_uid; -- GitLab From c9324d1870f3a7d13297ae6b787c567606ab3c89 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Thu, 4 Jul 2013 06:18:07 +0200 Subject: [PATCH 2295/2900] net:stmmac: fix memleak in the open method This patch is to fix a memory leak in the open method, it reviews error conditions freeing the resources previously allocated and not freed in cased of DMA failure. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f2d283d2528f..f2ccb36e8685 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1552,7 +1552,7 @@ static int stmmac_open(struct net_device *dev) if (ret) { pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret); - goto open_error; + goto phy_error; } } @@ -1566,7 +1566,7 @@ static int stmmac_open(struct net_device *dev) ret = stmmac_init_dma_engine(priv); if (ret < 0) { pr_err("%s: DMA initialization failed\n", __func__); - goto open_error; + goto init_error; } /* Copy the MAC addr into the HW */ @@ -1585,7 +1585,7 @@ static int stmmac_open(struct net_device *dev) if (unlikely(ret < 0)) { pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", __func__, dev->irq, ret); - goto open_error; + goto init_error; } /* Request the Wake IRQ in case of another line is used for WoL */ @@ -1595,7 +1595,7 @@ static int stmmac_open(struct net_device *dev) if (unlikely(ret < 0)) { pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n", __func__, priv->wol_irq, ret); - goto open_error_wolirq; + goto wolirq_error; } } @@ -1606,7 +1606,7 @@ static int stmmac_open(struct net_device *dev) if (unlikely(ret < 0)) { pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n", __func__, priv->lpi_irq, ret); - goto open_error_lpiirq; + goto lpiirq_error; } } @@ -1664,17 +1664,17 @@ static int stmmac_open(struct net_device *dev) return 0; -open_error_lpiirq: +lpiirq_error: if (priv->wol_irq != dev->irq) free_irq(priv->wol_irq, dev); - -open_error_wolirq: +wolirq_error: free_irq(dev->irq, dev); -open_error: +init_error: + free_dma_desc_resources(priv); if (priv->phydev) phy_disconnect(priv->phydev); - +phy_error: clk_disable_unprepare(priv->stmmac_clk); return ret; -- GitLab From d741434c3e0ae5592b72a0f4833a42b4be1b2fa1 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 4 Jul 2013 10:35:35 +0100 Subject: [PATCH 2296/2900] dt:net:stmmac: Allocate platform data only if its NULL. In some DT use-cases platform data might be already allocated and passed via AUXDATA. These are the cases where machine level code populates few callbacks in the platform data. This patch adds check and reuses platform_data if its valid, before allocating a new one. Signed-off-by: Srinivas Kandagatla Acked-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 17bc7827e7ca..adfb9a3ce6c5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -92,8 +92,10 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) if (IS_ERR(addr)) return PTR_ERR(addr); + plat_dat = pdev->dev.platform_data; if (pdev->dev.of_node) { - plat_dat = devm_kzalloc(&pdev->dev, + if (!plat_dat) + plat_dat = devm_kzalloc(&pdev->dev, sizeof(struct plat_stmmacenet_data), GFP_KERNEL); if (!plat_dat) { @@ -106,8 +108,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev) pr_err("%s: main dt probe failed", __func__); return ret; } - } else { - plat_dat = pdev->dev.platform_data; } /* Custom initialisation (if needed)*/ -- GitLab From 25c83b5c2e82560406d5265f42cd147f1eb441d0 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 4 Jul 2013 10:35:41 +0100 Subject: [PATCH 2297/2900] dt:net:stmmac: Add support to dwmac version 3.610 and 3.710 This patch adds dt support to dwmac version 3.610 and 3.710 these versions are integrated in STiH415 and STiH416 ARM A9 SOCs. To support these IP version, some of the device tree properties are extended. Signed-off-by: Srinivas Kandagatla Signed-off-by: David S. Miller --- .../devicetree/bindings/net/stmmac.txt | 4 +++ .../ethernet/stmicro/stmmac/stmmac_platform.c | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt index 060bbf098ef3..e1ddfcc46a4e 100644 --- a/Documentation/devicetree/bindings/net/stmmac.txt +++ b/Documentation/devicetree/bindings/net/stmmac.txt @@ -12,6 +12,10 @@ Required properties: property - phy-mode: String, operation mode of the PHY interface. Supported values are: "mii", "rmii", "gmii", "rgmii". +- snps,phy-addr phy address to connect to. +- snps,pbl Programmable Burst Length +- snps,fixed-burst Program the DMA to use the fixed burst mode +- snps,mixed-burst Program the DMA to use the mixed burst mode Optional properties: - mac-address: 6 bytes, mac address diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index adfb9a3ce6c5..03de76c7a177 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -34,12 +34,20 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) { struct device_node *np = pdev->dev.of_node; + struct stmmac_dma_cfg *dma_cfg; if (!np) return -ENODEV; *mac = of_get_mac_address(np); plat->interface = of_get_phy_mode(np); + + plat->bus_id = of_alias_get_id(np, "ethernet"); + if (plat->bus_id < 0) + plat->bus_id = 0; + + of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr); + plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); @@ -56,6 +64,22 @@ static int stmmac_probe_config_dt(struct platform_device *pdev, plat->pmt = 1; } + if (of_device_is_compatible(np, "snps,dwmac-3.610") || + of_device_is_compatible(np, "snps,dwmac-3.710")) { + plat->enh_desc = 1; + plat->bugged_jumbo = 1; + plat->force_sf_dma_mode = 1; + } + + dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL); + if (!dma_cfg) + return -ENOMEM; + + plat->dma_cfg = dma_cfg; + of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); + dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst"); + dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst"); + return 0; } #else @@ -228,7 +252,9 @@ static const struct dev_pm_ops stmmac_pltfr_pm_ops; static const struct of_device_id stmmac_dt_ids[] = { { .compatible = "st,spear600-gmac"}, + { .compatible = "snps,dwmac-3.610"}, { .compatible = "snps,dwmac-3.70a"}, + { .compatible = "snps,dwmac-3.710"}, { .compatible = "snps,dwmac"}, { /* sentinel */ } }; -- GitLab From 0e0764715d8116484d808f5b3985ca043080788e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 4 Jul 2013 10:35:48 +0100 Subject: [PATCH 2298/2900] dt:net:stmmac: Add dt specific phy reset callback support. This patch adds phy reset callback support for stmmac driver via device trees. It adds three new properties to gmac device tree bindings to define the reset signal via gpio. With this patch users can conveniently pass reset gpio number with pre, pulse and post delay in micro secs via DTs. active low: _________ ____________ | | | | |_______________| active high: ________________ | | | | ________| |___________ Signed-off-by: Srinivas Kandagatla Signed-off-by: David S. Miller --- .../devicetree/bindings/net/stmmac.txt | 6 +++ .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 48 ++++++++++++++++++- include/linux/stmmac.h | 4 ++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt index e1ddfcc46a4e..261c563b5f06 100644 --- a/Documentation/devicetree/bindings/net/stmmac.txt +++ b/Documentation/devicetree/bindings/net/stmmac.txt @@ -13,6 +13,12 @@ Required properties: - phy-mode: String, operation mode of the PHY interface. Supported values are: "mii", "rmii", "gmii", "rgmii". - snps,phy-addr phy address to connect to. +- snps,reset-gpio gpio number for phy reset. +- snps,reset-active-low boolean flag to indicate if phy reset is active low. +- snps,reset-delays-us is triplet of delays + The 1st cell is reset pre-delay in micro seconds. + The 2nd cell is reset pulse in micro seconds. + The 3rd cell is reset post-delay in micro seconds. - snps,pbl Programmable Burst Length - snps,fixed-burst Program the DMA to use the fixed burst mode - snps,mixed-burst Program the DMA to use the mixed burst mode diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index cc15039eaa47..fe7bc9903867 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include + #include #include "stmmac.h" @@ -131,10 +134,46 @@ static int stmmac_mdio_reset(struct mii_bus *bus) struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); unsigned int mii_address = priv->hw->mii.addr; + struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data; + +#ifdef CONFIG_OF + if (priv->device->of_node) { + int reset_gpio, active_low; + + if (data->reset_gpio < 0) { + struct device_node *np = priv->device->of_node; + if (!np) + return 0; + + data->reset_gpio = of_get_named_gpio(np, + "snps,reset-gpio", 0); + if (data->reset_gpio < 0) + return 0; + + data->active_low = of_property_read_bool(np, + "snps,reset-active-low"); + of_property_read_u32_array(np, + "snps,reset-delays-us", data->delays, 3); + } + + reset_gpio = data->reset_gpio; + active_low = data->active_low; + + if (!gpio_request(reset_gpio, "mdio-reset")) { + gpio_direction_output(reset_gpio, active_low ? 1 : 0); + udelay(data->delays[0]); + gpio_set_value(reset_gpio, active_low ? 0 : 1); + udelay(data->delays[1]); + gpio_set_value(reset_gpio, active_low ? 1 : 0); + udelay(data->delays[2]); + gpio_free(reset_gpio); + } + } +#endif - if (priv->plat->mdio_bus_data->phy_reset) { + if (data->phy_reset) { pr_debug("stmmac_mdio_reset: calling phy_reset\n"); - priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv); + data->phy_reset(priv->plat->bsp_priv); } /* This is a workaround for problems with the STE101P PHY. @@ -172,6 +211,11 @@ int stmmac_mdio_register(struct net_device *ndev) else irqlist = priv->mii_irq; +#ifdef CONFIG_OF + if (priv->device->of_node) + mdio_bus_data->reset_gpio = -1; +#endif + new_bus->name = "stmmac"; new_bus->read = &stmmac_mdio_read; new_bus->write = &stmmac_mdio_write; diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index c1b3ed3fb787..9e495d31516e 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -80,6 +80,10 @@ struct stmmac_mdio_bus_data { unsigned int phy_mask; int *irqs; int probed_phy_irq; +#ifdef CONFIG_OF + int reset_gpio, active_low; + u32 delays[3]; +#endif }; struct stmmac_dma_cfg { -- GitLab From 86bd68bfd75941d4cf3b874468791c3e73eef23d Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 3 Jul 2013 17:00:34 +0200 Subject: [PATCH 2299/2900] sit: fix tunnel update via netlink The device can stand in another netns, hence we need to do the lookup in netns tunnel->net. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/sit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 85ff37b1ce02..a3437a4cd07e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1426,9 +1426,9 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { - struct ip_tunnel *t; + struct ip_tunnel *t = netdev_priv(dev); struct ip_tunnel_parm p; - struct net *net = dev_net(dev); + struct net *net = t->net; struct sit_net *sitn = net_generic(net, sit_net_id); #ifdef CONFIG_IPV6_SIT_6RD struct ip_tunnel_6rd ip6rd; -- GitLab From f605181abd95a109031a23c67a824eb8e5dcfe67 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 28 Jun 2013 15:34:29 +0200 Subject: [PATCH 2300/2900] cpupower: Make idlestate usage unsigned Use unsigned int as the data type for some variables related to CPU idle states which allows the code to be simplified slightly. [rjw: Changelog] Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/utils/cpuidle-info.c | 18 ++++-------------- tools/power/cpupower/utils/helpers/sysfs.c | 2 +- tools/power/cpupower/utils/helpers/sysfs.h | 2 +- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index 8145af5f93a6..edd5dba3e249 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -22,7 +22,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) { - int idlestates, idlestate; + unsigned int idlestates, idlestate; char *tmp; printf(_ ("Analyzing CPU %d:\n"), cpu); @@ -31,10 +31,8 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) if (idlestates == 0) { printf(_("CPU %u: No idle states\n"), cpu); return; - } else if (idlestates <= 0) { - printf(_("CPU %u: Can't read idle state info\n"), cpu); - return; } + printf(_("Number of idle states: %d\n"), idlestates); printf(_("Available idle states:")); for (idlestate = 0; idlestate < idlestates; idlestate++) { @@ -98,21 +96,13 @@ static void cpuidle_general_output(void) static void proc_cpuidle_cpu_output(unsigned int cpu) { long max_allowed_cstate = 2000000000; - int cstates, cstate; + unsigned int cstate, cstates; cstates = sysfs_get_idlestate_count(cpu); if (cstates == 0) { - /* - * Go on and print same useless info as you'd see with - * cat /proc/acpi/processor/../power - * printf(_("CPU %u: No C-states available\n"), cpu); - * return; - */ - } else if (cstates <= 0) { - printf(_("CPU %u: Can't read C-state info\n"), cpu); + printf(_("CPU %u: No C-states info\n"), cpu); return; } - /* printf("Cstates: %d\n", cstates); */ printf(_("active state: C0\n")); printf(_("max_cstate: C%u\n"), cstates-1); diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 38ab91629463..891f6710d026 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c @@ -238,7 +238,7 @@ char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate) * Negativ in error case * Zero if cpuidle does not export any C-states */ -int sysfs_get_idlestate_count(unsigned int cpu) +unsigned int sysfs_get_idlestate_count(unsigned int cpu) { char file[SYSFS_PATH_MAX]; struct stat statbuf; diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h index 8cb797bbceb0..0401a97a4cab 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.h +++ b/tools/power/cpupower/utils/helpers/sysfs.h @@ -19,7 +19,7 @@ extern char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate); extern char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate); -extern int sysfs_get_idlestate_count(unsigned int cpu); +extern unsigned int sysfs_get_idlestate_count(unsigned int cpu); extern char *sysfs_get_cpuidle_governor(void); extern char *sysfs_get_cpuidle_driver(void); -- GitLab From 0924c369bc5492cf181a066fc2d459aa18ffa5ac Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 28 Jun 2013 15:34:30 +0200 Subject: [PATCH 2301/2900] cpupower: Implement disabling of cstate interface Latest kernel allows to disable C-states via: /sys/devices/system/cpu/cpuX/cpuidle/stateY/disable This patch provides lower level sysfs access functions to make use of this interface. A later patch will implement the higher level stuff. Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/utils/helpers/sysfs.c | 116 ++++++++++++++++++++- tools/power/cpupower/utils/helpers/sysfs.h | 8 ++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 891f6710d026..5cdc600e8152 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c @@ -87,8 +87,35 @@ int sysfs_is_cpu_online(unsigned int cpu) return value; } +/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ + + /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ +/* + * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir + * exists. + * For example the functionality to disable c-states was introduced in later + * kernel versions, this function can be used to explicitly check for this + * feature. + * + * returns 1 if the file exists, 0 otherwise. + */ +unsigned int sysfs_idlestate_file_exists(unsigned int cpu, + unsigned int idlestate, + const char *fname) +{ + char path[SYSFS_PATH_MAX]; + struct stat statbuf; + + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", + cpu, idlestate, fname); + if (stat(path, &statbuf) != 0) + return 0; + return 1; +} + /* * helper function to read file from /sys into given buffer * fname is a relative path under "cpuX/cpuidle/stateX/" dir @@ -121,6 +148,40 @@ unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate, return (unsigned int) numread; } +/* + * helper function to write a new value to a /sys file + * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir + * + * Returns the number of bytes written or 0 on error + */ +static +unsigned int sysfs_idlestate_write_file(unsigned int cpu, + unsigned int idlestate, + const char *fname, + const char *value, size_t len) +{ + char path[SYSFS_PATH_MAX]; + int fd; + ssize_t numwrite; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", + cpu, idlestate, fname); + + fd = open(path, O_WRONLY); + if (fd == -1) + return 0; + + numwrite = write(fd, value, len); + if (numwrite < 1) { + close(fd); + return 0; + } + + close(fd); + + return (unsigned int) numwrite; +} + /* read access to files which contain one numeric value */ enum idlestate_value { @@ -128,6 +189,7 @@ enum idlestate_value { IDLESTATE_POWER, IDLESTATE_LATENCY, IDLESTATE_TIME, + IDLESTATE_DISABLE, MAX_IDLESTATE_VALUE_FILES }; @@ -136,6 +198,7 @@ static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = { [IDLESTATE_POWER] = "power", [IDLESTATE_LATENCY] = "latency", [IDLESTATE_TIME] = "time", + [IDLESTATE_DISABLE] = "disable", }; static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, @@ -205,8 +268,59 @@ static char *sysfs_idlestate_get_one_string(unsigned int cpu, return result; } +/* + * Returns: + * 1 if disabled + * 0 if enabled + * -1 if idlestate is not available + * -2 if disabling is not supported by the kernel + */ +int sysfs_is_idlestate_disabled(unsigned int cpu, + unsigned int idlestate) +{ + if (sysfs_get_idlestate_count(cpu) < idlestate) + return -1; + + if (!sysfs_idlestate_file_exists(cpu, idlestate, + idlestate_value_files[IDLESTATE_DISABLE])) + return -2; + return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_DISABLE); +} + +/* + * Pass 1 as last argument to disable or 0 to enable the state + * Returns: + * 0 on success + * negative values on error, for example: + * -1 if idlestate is not available + * -2 if disabling is not supported by the kernel + * -3 No write access to disable/enable C-states + */ +int sysfs_idlestate_disable(unsigned int cpu, + unsigned int idlestate, + unsigned int disable) +{ + char value[SYSFS_PATH_MAX]; + int bytes_written; + + if (sysfs_get_idlestate_count(cpu) < idlestate) + return -1; + + if (!sysfs_idlestate_file_exists(cpu, idlestate, + idlestate_value_files[IDLESTATE_DISABLE])) + return -2; + + snprintf(value, SYSFS_PATH_MAX, "%u", disable); + + bytes_written = sysfs_idlestate_write_file(cpu, idlestate, "disable", + value, sizeof(disable)); + if (bytes_written) + return 0; + return -3; +} + unsigned long sysfs_get_idlestate_latency(unsigned int cpu, - unsigned int idlestate) + unsigned int idlestate) { return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); } diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h index 0401a97a4cab..d28f11fedbda 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.h +++ b/tools/power/cpupower/utils/helpers/sysfs.h @@ -7,8 +7,16 @@ extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); +extern unsigned int sysfs_idlestate_file_exists(unsigned int cpu, + unsigned int idlestate, + const char *fname); + extern int sysfs_is_cpu_online(unsigned int cpu); +extern int sysfs_is_idlestate_disabled(unsigned int cpu, + unsigned int idlestate); +extern int sysfs_idlestate_disable(unsigned int cpu, unsigned int idlestate, + unsigned int disable); extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, unsigned int idlestate); extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, -- GitLab From c4f3610eba69321b9cf35779cd67e68b5138cc16 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 28 Jun 2013 15:34:31 +0200 Subject: [PATCH 2302/2900] cpupower: Introduce idle-set subcommand and C-state enabling/disabling Example: cpupower idle-set -d 3 will disable C-state 3 on all processors (set commands are active on all CPUs by default), same as: cpupower -c all idle-set -d 3 Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/Makefile | 3 +- tools/power/cpupower/man/cpupower-monitor.1 | 10 +- tools/power/cpupower/utils/builtin.h | 1 + tools/power/cpupower/utils/cpuidle-info.c | 6 +- tools/power/cpupower/utils/cpuidle-set.c | 118 ++++++++++++++++++++ tools/power/cpupower/utils/cpupower.c | 13 ++- 6 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 tools/power/cpupower/utils/cpuidle-set.c diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index d875a74a3bdf..ce17f30f04ba 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -131,7 +131,8 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \ utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \ utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ - utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o + utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \ + utils/cpuidle-set.o UTIL_SRC := $(UTIL_OBJS:.o=.c) diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1 index e01c35d13b6e..914cbb9d9cd0 100644 --- a/tools/power/cpupower/man/cpupower-monitor.1 +++ b/tools/power/cpupower/man/cpupower-monitor.1 @@ -110,13 +110,21 @@ May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP kernel frequency driver periodically cleared aperf/mperf registers in those kernels. -.SS "Nehalem" "SandyBridge" +.SS "Nehalem" "SandyBridge" "HaswellExtended" Intel Core and Package sleep state counters. Threads (hyperthreaded cores) may not be able to enter deeper core states if its sibling is utilized. Deepest package sleep states may in reality show up as machine/platform wide sleep states and can only be entered if all cores are idle. Look up Intel manuals (some are provided in the References section) for further details. +The monitors are named after the CPU family where the sleep state capabilities +got introduced and may not match exactly the CPU name of the platform. +For example an IvyBridge processor has sleep state capabilities which got +introduced in Nehalem and SandyBridge processor families. +Thus on an IvyBridge processor one will get Nehalem and SandyBridge sleep +state monitors. +HaswellExtended extra package sleep state capabilities are available only in a +specific Haswell (family 0x45) and probably also other future processors. .SS "Fam_12h" "Fam_14h" AMD laptop and desktop processor (family 12h and 14h) sleep state counters. diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h index c10496fbe3c6..2284c8ea4e2a 100644 --- a/tools/power/cpupower/utils/builtin.h +++ b/tools/power/cpupower/utils/builtin.h @@ -5,6 +5,7 @@ extern int cmd_set(int argc, const char **argv); extern int cmd_info(int argc, const char **argv); extern int cmd_freq_set(int argc, const char **argv); extern int cmd_freq_info(int argc, const char **argv); +extern int cmd_idle_set(int argc, const char **argv); extern int cmd_idle_info(int argc, const char **argv); extern int cmd_monitor(int argc, const char **argv); diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index edd5dba3e249..75e66de7e7a7 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -48,10 +48,14 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) return; for (idlestate = 0; idlestate < idlestates; idlestate++) { + int disabled = sysfs_is_idlestate_disabled(cpu, idlestate); + /* Disabled interface not supported on older kernels */ + if (disabled < 0) + disabled = 0; tmp = sysfs_get_idlestate_name(cpu, idlestate); if (!tmp) continue; - printf("%s:\n", tmp); + printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : ""); free(tmp); tmp = sysfs_get_idlestate_desc(cpu, idlestate); diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c new file mode 100644 index 000000000000..c78141c5dfac --- /dev/null +++ b/tools/power/cpupower/utils/cpuidle-set.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cpufreq.h" +#include "helpers/helpers.h" +#include "helpers/sysfs.h" + +static struct option info_opts[] = { + { .name = "disable", .has_arg = required_argument, .flag = NULL, .val = 'd'}, + { .name = "enable", .has_arg = required_argument, .flag = NULL, .val = 'e'}, + { }, +}; + + +int cmd_idle_set(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int ret = 0, cont = 1, param = 0, idlestate = 0; + unsigned int cpu = 0; + + do { + ret = getopt_long(argc, argv, "d:e:", info_opts, NULL); + if (ret == -1) + break; + switch (ret) { + case '?': + param = '?'; + cont = 0; + break; + case 'd': + if (param) { + param = -1; + cont = 0; + break; + } + param = ret; + idlestate = atoi(optarg); + break; + case 'e': + if (param) { + param = -1; + cont = 0; + break; + } + param = ret; + idlestate = atoi(optarg); + break; + case -1: + cont = 0; + break; + } + } while (cont); + + switch (param) { + case -1: + printf(_("You can't specify more than one " + "output-specific argument\n")); + exit(EXIT_FAILURE); + case '?': + printf(_("invalid or unknown argument\n")); + exit(EXIT_FAILURE); + } + + /* Default is: set all CPUs */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setall(cpus_chosen); + + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu)) + continue; + + switch (param) { + + case 'd': + ret = sysfs_idlestate_disable(cpu, idlestate, 1); + if (ret == 0) + printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); + else if (ret == -1) + printf(_("Idlestate %u not available on CPU %u\n"), + idlestate, cpu); + else if (ret == -2) + printf(_("Idlestate disabling not supported by kernel\n")); + else + printf(_("Idlestate %u not disabled on CPU %u\n"), + idlestate, cpu); + break; + case 'e': + ret = sysfs_idlestate_disable(cpu, idlestate, 0); + if (ret == 0) + printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); + else if (ret == -1) + printf(_("Idlestate %u not available on CPU %u\n"), + idlestate, cpu); + else if (ret == -2) + printf(_("Idlestate enabling not supported by kernel\n")); + else + printf(_("Idlestate %u not enabled on CPU %u\n"), + idlestate, cpu); + break; + default: + /* Not reachable with proper args checking */ + printf(_("Invalid or unknown argument\n")); + exit(EXIT_FAILURE); + break; + } + } + return EXIT_SUCCESS; +} diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index 52bee591c1c5..7efc570ffbaa 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c @@ -17,12 +17,6 @@ #include "helpers/helpers.h" #include "helpers/bitmask.h" -struct cmd_struct { - const char *cmd; - int (*main)(int, const char **); - int needs_root; -}; - #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) static int cmd_help(int argc, const char **argv); @@ -43,10 +37,17 @@ int be_verbose; static void print_help(void); +struct cmd_struct { + const char *cmd; + int (*main)(int, const char **); + int needs_root; +}; + static struct cmd_struct commands[] = { { "frequency-info", cmd_freq_info, 0 }, { "frequency-set", cmd_freq_set, 1 }, { "idle-info", cmd_idle_info, 0 }, + { "idle-set", cmd_idle_set, 1 }, { "set", cmd_set, 1 }, { "info", cmd_info, 0 }, { "monitor", cmd_monitor, 0 }, -- GitLab From 2aa1ca75c48f1da2c9bdc81ec4403eaf89a410d5 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 28 Jun 2013 15:34:32 +0200 Subject: [PATCH 2303/2900] cpupower: Haswell also supports the C-states introduced with SandyBridge Add Haswell model numbers to snb_register() as it also supports the C-states introduced in SandyBridge processors. [rjw: Changelog] Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/utils/idle_monitor/snb_idle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c index a99b43b97d6d..efc8a69c9aba 100644 --- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c @@ -155,6 +155,10 @@ static struct cpuidle_monitor *snb_register(void) case 0x2D: /* SNB Xeon */ case 0x3A: /* IVB */ case 0x3E: /* IVB Xeon */ + case 0x3C: /* HSW */ + case 0x3F: /* HSW */ + case 0x45: /* HSW */ + case 0x46: /* HSW */ break; default: return NULL; -- GitLab From 7ee767b69b6885dd81bafaf1881c5028033a6177 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 28 Jun 2013 15:34:33 +0200 Subject: [PATCH 2304/2900] cpupower: Add Haswell family 0x45 specific idle monitor to show PC8,9,10 states This specific processor supports 3 new package sleep states. Provide a monitor, so that the user can see their usage. Signed-off-by: Thomas Renninger Signed-off-by: Rafael J. Wysocki --- tools/power/cpupower/Makefile | 1 + .../utils/idle_monitor/hsw_ext_idle.c | 196 ++++++++++++++++++ .../utils/idle_monitor/idle_monitors.def | 1 + 3 files changed, 198 insertions(+) create mode 100644 tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index ce17f30f04ba..cbfec92af327 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -128,6 +128,7 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \ utils/helpers/pci.o utils/helpers/bitmask.o \ utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \ + utils/idle_monitor/hsw_ext_idle.o \ utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \ utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \ utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ diff --git a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c new file mode 100644 index 000000000000..ebeaba6571a3 --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c @@ -0,0 +1,196 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on SandyBridge monitor. Implements the new package C-states + * (PC8, PC9, PC10) coming with a specific Haswell (family 0x45) CPU. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include + +#include "helpers/helpers.h" +#include "idle_monitor/cpupower-monitor.h" + +#define MSR_PKG_C8_RESIDENCY 0x00000630 +#define MSR_PKG_C9_RESIDENCY 0x00000631 +#define MSR_PKG_C10_RESIDENCY 0x00000632 + +#define MSR_TSC 0x10 + +enum intel_hsw_ext_id { PC8 = 0, PC9, PC10, HSW_EXT_CSTATE_COUNT, + TSC = 0xFFFF }; + +static int hsw_ext_get_count_percent(unsigned int self_id, double *percent, + unsigned int cpu); + +static cstate_t hsw_ext_cstates[HSW_EXT_CSTATE_COUNT] = { + { + .name = "PC8", + .desc = N_("Processor Package C8"), + .id = PC8, + .range = RANGE_PACKAGE, + .get_count_percent = hsw_ext_get_count_percent, + }, + { + .name = "PC9", + .desc = N_("Processor Package C9"), + .desc = N_("Processor Package C2"), + .id = PC9, + .range = RANGE_PACKAGE, + .get_count_percent = hsw_ext_get_count_percent, + }, + { + .name = "PC10", + .desc = N_("Processor Package C10"), + .id = PC10, + .range = RANGE_PACKAGE, + .get_count_percent = hsw_ext_get_count_percent, + }, +}; + +static unsigned long long tsc_at_measure_start; +static unsigned long long tsc_at_measure_end; +static unsigned long long *previous_count[HSW_EXT_CSTATE_COUNT]; +static unsigned long long *current_count[HSW_EXT_CSTATE_COUNT]; +/* valid flag for all CPUs. If a MSR read failed it will be zero */ +static int *is_valid; + +static int hsw_ext_get_count(enum intel_hsw_ext_id id, unsigned long long *val, + unsigned int cpu) +{ + int msr; + + switch (id) { + case PC8: + msr = MSR_PKG_C8_RESIDENCY; + break; + case PC9: + msr = MSR_PKG_C9_RESIDENCY; + break; + case PC10: + msr = MSR_PKG_C10_RESIDENCY; + break; + case TSC: + msr = MSR_TSC; + break; + default: + return -1; + }; + if (read_msr(cpu, msr, val)) + return -1; + return 0; +} + +static int hsw_ext_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + *percent = 0.0; + + if (!is_valid[cpu]) + return -1; + + *percent = (100.0 * + (current_count[id][cpu] - previous_count[id][cpu])) / + (tsc_at_measure_end - tsc_at_measure_start); + + dprint("%s: previous: %llu - current: %llu - (%u)\n", + hsw_ext_cstates[id].name, previous_count[id][cpu], + current_count[id][cpu], cpu); + + dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n", + hsw_ext_cstates[id].name, + (unsigned long long) tsc_at_measure_end - tsc_at_measure_start, + current_count[id][cpu] - previous_count[id][cpu], + *percent, cpu); + + return 0; +} + +static int hsw_ext_start(void) +{ + int num, cpu; + unsigned long long val; + + for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + hsw_ext_get_count(num, &val, cpu); + previous_count[num][cpu] = val; + } + } + hsw_ext_get_count(TSC, &tsc_at_measure_start, 0); + return 0; +} + +static int hsw_ext_stop(void) +{ + unsigned long long val; + int num, cpu; + + hsw_ext_get_count(TSC, &tsc_at_measure_end, 0); + + for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + is_valid[cpu] = !hsw_ext_get_count(num, &val, cpu); + current_count[num][cpu] = val; + } + } + return 0; +} + +struct cpuidle_monitor intel_hsw_ext_monitor; + +static struct cpuidle_monitor *hsw_ext_register(void) +{ + int num; + + if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL + || cpupower_cpu_info.family != 6) + return NULL; + + switch (cpupower_cpu_info.model) { + case 0x45: /* HSW */ + break; + default: + return NULL; + } + + is_valid = calloc(cpu_count, sizeof(int)); + for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { + previous_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); + } + intel_hsw_ext_monitor.name_len = strlen(intel_hsw_ext_monitor.name); + return &intel_hsw_ext_monitor; +} + +void hsw_ext_unregister(void) +{ + int num; + free(is_valid); + for (num = 0; num < HSW_EXT_CSTATE_COUNT; num++) { + free(previous_count[num]); + free(current_count[num]); + } +} + +struct cpuidle_monitor intel_hsw_ext_monitor = { + .name = "HaswellExtended", + .hw_states = hsw_ext_cstates, + .hw_states_num = HSW_EXT_CSTATE_COUNT, + .start = hsw_ext_start, + .stop = hsw_ext_stop, + .do_register = hsw_ext_register, + .unregister = hsw_ext_unregister, + .needs_root = 1, + .overflow_s = 922000000 /* 922337203 seconds TSC overflow + at 20GHz */ +}; +#endif /* defined(__i386__) || defined(__x86_64__) */ diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def index e3f8d9b2b18f..0d6ba4dbb9c7 100644 --- a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def +++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def @@ -2,6 +2,7 @@ DEF(amd_fam14h) DEF(intel_nhm) DEF(intel_snb) +DEF(intel_hsw_ext) DEF(mperf) #endif DEF(cpuidle_sysfs) -- GitLab From 100ac5331519866afa9b000b10642b00cb6d03dd Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 3 Jul 2013 09:55:42 +0200 Subject: [PATCH 2305/2900] perf/x86/amd: Do not print an error when the device is not present As Linus said its not an error to not have an AMD IOMMU; esp. when you're not even running on an AMD platform. Reported-by: Linus Torvalds Signed-off-by: Peter Zijlstra Acked-by: Suravee Suthikulpanit Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20130703075542.GF23916@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_amd_iommu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_amd_iommu.c b/arch/x86/kernel/cpu/perf_event_amd_iommu.c index 0db655ef3918..639d1289b1ba 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_iommu.c +++ b/arch/x86/kernel/cpu/perf_event_amd_iommu.c @@ -491,10 +491,8 @@ static struct perf_amd_iommu __perf_iommu = { static __init int amd_iommu_pc_init(void) { /* Make sure the IOMMU PC resource is available */ - if (!amd_iommu_pc_supported()) { - pr_err("perf: amd_iommu PMU not installed. No support!\n"); + if (!amd_iommu_pc_supported()) return -ENODEV; - } _init_perf_amd_iommu(&__perf_iommu, "amd_iommu"); -- GitLab From e5302920da9ef23f9d19d4e9ac85704cc25bee7a Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 5 Jul 2013 00:30:11 +0200 Subject: [PATCH 2306/2900] perf: Fix interrupt handler timing harness This patch fixes a serious bug in: 14c63f17b1fd perf: Drop sample rate when sampling is too slow There was an misunderstanding on the API of the do_div() macro. It returns the remainder of the division and this was not what the function expected leading to disabling the interrupt latency watchdog. This patch also remove a duplicate assignment in perf_sample_event_took(). Signed-off-by: Stephane Eranian Cc: peterz@infradead.org Cc: dave.hansen@linux.intel.com Cc: ak@linux.intel.com Cc: jolsa@redhat.com Link: http://lkml.kernel.org/r/20130704223010.GA30625@quad Signed-off-by: Ingo Molnar --- kernel/events/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 1db3af933704..1833bc5a84a7 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -182,7 +182,7 @@ void update_perf_cpu_limits(void) u64 tmp = perf_sample_period_ns; tmp *= sysctl_perf_cpu_time_max_percent; - tmp = do_div(tmp, 100); + do_div(tmp, 100); atomic_set(&perf_sample_allowed_ns, tmp); } @@ -232,7 +232,7 @@ DEFINE_PER_CPU(u64, running_sample_length); void perf_sample_event_took(u64 sample_len_ns) { u64 avg_local_sample_len; - u64 local_samples_len = __get_cpu_var(running_sample_length); + u64 local_samples_len; if (atomic_read(&perf_sample_allowed_ns) == 0) return; -- GitLab From 734d4e159b283a4ae4d007b7e7a91d84398ccb92 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 4 Jul 2013 23:48:46 +0100 Subject: [PATCH 2307/2900] sfc: Fix memory leak when discarding scattered packets Commit 2768935a4660 ('sfc: reuse pages to avoid DMA mapping/unmapping costs') did not fully take account of DMA scattering which was introduced immediately before. If a received packet is invalid and must be discarded, we only drop a reference to the first buffer's page, but we need to drop a reference for each buffer the packet used. I think this bug was missed partly because efx_recycle_rx_buffers() was not renamed and so no longer does what its name says. It does not change the state of buffers, but only prepares the underlying pages for recycling. Rename it accordingly. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/rx.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 65646cd7af8e..6af9cfda50fb 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -282,9 +282,9 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, } /* Recycle the pages that are used by buffers that have just been received. */ -static void efx_recycle_rx_buffers(struct efx_channel *channel, - struct efx_rx_buffer *rx_buf, - unsigned int n_frags) +static void efx_recycle_rx_pages(struct efx_channel *channel, + struct efx_rx_buffer *rx_buf, + unsigned int n_frags) { struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); @@ -294,6 +294,20 @@ static void efx_recycle_rx_buffers(struct efx_channel *channel, } while (--n_frags); } +static void efx_discard_rx_packet(struct efx_channel *channel, + struct efx_rx_buffer *rx_buf, + unsigned int n_frags) +{ + struct efx_rx_queue *rx_queue = efx_channel_get_rx_queue(channel); + + efx_recycle_rx_pages(channel, rx_buf, n_frags); + + do { + efx_free_rx_buffer(rx_buf); + rx_buf = efx_rx_buf_next(rx_queue, rx_buf); + } while (--n_frags); +} + /** * efx_fast_push_rx_descriptors - push new RX descriptors quickly * @rx_queue: RX descriptor queue @@ -533,8 +547,7 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, */ if (unlikely(rx_buf->flags & EFX_RX_PKT_DISCARD)) { efx_rx_flush_packet(channel); - put_page(rx_buf->page); - efx_recycle_rx_buffers(channel, rx_buf, n_frags); + efx_discard_rx_packet(channel, rx_buf, n_frags); return; } @@ -570,9 +583,9 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, efx_sync_rx_buffer(efx, rx_buf, rx_buf->len); } - /* All fragments have been DMA-synced, so recycle buffers and pages. */ + /* All fragments have been DMA-synced, so recycle pages. */ rx_buf = efx_rx_buffer(rx_queue, index); - efx_recycle_rx_buffers(channel, rx_buf, n_frags); + efx_recycle_rx_pages(channel, rx_buf, n_frags); /* Pipeline receives so that we give time for packet headers to be * prefetched into cache. -- GitLab From e658718e478fb2591f38afd9643eab06698790fe Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Jul 2013 11:33:49 +0800 Subject: [PATCH 2308/2900] irqchip: vt8500: Staticize local symbols This driver is converted to use IRQCHIP_DECLARE and irqchip_init. vt8500_handle_irq() and vt8500_irq_init() are only referenced in this file, so make them static. Signed-off-by: Axel Lin Acked-by: Tony Prisk Cc: Olof Johansson Link: http://lkml.kernel.org/r/1372995229.4038.1.camel@phoenix Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-vt8500.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c index d97059550a2c..1846e7d66681 100644 --- a/drivers/irqchip/irq-vt8500.c +++ b/drivers/irqchip/irq-vt8500.c @@ -178,7 +178,8 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { .xlate = irq_domain_xlate_onecell, }; -asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) +static asmlinkage +void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) { u32 stat, i; int irqnr, virq; @@ -203,7 +204,8 @@ asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) } } -int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) +static int __init vt8500_irq_init(struct device_node *node, + struct device_node *parent) { int irq, i; struct device_node *np = node; -- GitLab From baaecfa7249f1d5553a31f8ad0b9c7ffabcaa339 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Jul 2013 15:41:10 +0800 Subject: [PATCH 2309/2900] irqchip: sun4i: Staticize sun4i_irq_ack() sun4i_irq_ack() is only referenced in this file, so make it static. Signed-off-by: Axel Lin Acked-by: Maxime Ripard Link: http://lkml.kernel.org/r/1373010070.14756.2.camel@phoenix Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-sun4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c index b66d4ae06898..a5438d889245 100644 --- a/drivers/irqchip/irq-sun4i.c +++ b/drivers/irqchip/irq-sun4i.c @@ -38,7 +38,7 @@ static struct irq_domain *sun4i_irq_domain; static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs); -void sun4i_irq_ack(struct irq_data *irqd) +static void sun4i_irq_ack(struct irq_data *irqd) { unsigned int irq = irqd_to_hwirq(irqd); unsigned int irq_off = irq % 32; -- GitLab From 5b8aae489a07ac7d5a2cb897d6ca1fddb0c0043a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Jul 2013 15:39:11 +0800 Subject: [PATCH 2310/2900] irqchip: nvic: Fix wrong num_ct argument for irq_alloc_domain_generic_chips() The third parameter of irq_alloc_domain_generic_chips() is the number of irq_chip_type instances associated with these chips rather than numbanks. Signed-off-by: Axel Lin Cc: Uwe Kleine-Koenig Cc: Catalin Marinas Cc: Arnd Bergmann Cc: Grant Likely Cc: kernel@pengutronix.de Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-nvic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-nvic.c b/drivers/irqchip/irq-nvic.c index 8d0c8b3181c5..70bdf6edb7bb 100644 --- a/drivers/irqchip/irq-nvic.c +++ b/drivers/irqchip/irq-nvic.c @@ -84,7 +84,7 @@ static int __init nvic_of_init(struct device_node *node, return -ENOMEM; } - ret = irq_alloc_domain_generic_chips(nvic_irq_domain, 32, numbanks, + ret = irq_alloc_domain_generic_chips(nvic_irq_domain, 32, 1, "nvic_irq", handle_fasteoi_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); if (ret) { -- GitLab From 002fca5df168922103a2bb52748f9984e6de80b2 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Jul 2013 17:13:12 +0800 Subject: [PATCH 2311/2900] genirq: generic chip: Use DIV_ROUND_UP to calculate numchips The number of interrupts in a domain may be not divisible by the number of interrupts each chip handles. Integer division may truncate the result, thus use DIV_ROUND_UP to count numchips. Seems all users of irq_alloc_domain_generic_chips() in current code do not have this issue. I just found the issue while reading the code. Signed-off-by: Axel Lin Cc: Grant Likely Cc: Tony Lindgren Cc: Arnd Bergmann Link: http://lkml.kernel.org/r/1373015592.18252.2.camel@phoenix Signed-off-by: Thomas Gleixner --- kernel/irq/generic-chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index 1c39eccc1eaf..2f274f30b7e2 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c @@ -278,7 +278,7 @@ int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, if (d->revmap_type != IRQ_DOMAIN_MAP_LINEAR) return -EINVAL; - numchips = d->revmap_data.linear.size / irqs_per_chip; + numchips = DIV_ROUND_UP(d->revmap_data.linear.size, irqs_per_chip); if (!numchips) return -EINVAL; -- GitLab From 4de563ae821b1935b3c467a4606e5738b0b0df87 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 4 Jul 2013 14:38:51 +0200 Subject: [PATCH 2312/2900] irqchip: Add support for MOXA ART SoCs This patch adds an irqchip driver for the main interrupt controller found on MOXA ART SoCs. Signed-off-by: Jonas Jensen Cc: grant.likely@secretlab.ca Cc: thomas.petazzoni@free-electrons.com Cc: arnd@arndb.de Cc: u.kleine-koenig@pengutronix.de Cc: linux@arm.linux.org.uk Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1372941531-6393-1-git-send-email-jonas.jensen@gmail.com Signed-off-by: Thomas Gleixner --- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-moxart.c | 117 +++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 drivers/irqchip/irq-moxart.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 2065ef6a949c..e65c41a7366b 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_MXS) += irq-mxs.o obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o obj-$(CONFIG_METAG) += irq-metag-ext.o obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o +obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o diff --git a/drivers/irqchip/irq-moxart.c b/drivers/irqchip/irq-moxart.c new file mode 100644 index 000000000000..5552fc2bf28a --- /dev/null +++ b/drivers/irqchip/irq-moxart.c @@ -0,0 +1,117 @@ +/* + * MOXA ART SoCs IRQ chip driver. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "irqchip.h" + +#define IRQ_SOURCE_REG 0 +#define IRQ_MASK_REG 0x04 +#define IRQ_CLEAR_REG 0x08 +#define IRQ_MODE_REG 0x0c +#define IRQ_LEVEL_REG 0x10 +#define IRQ_STATUS_REG 0x14 + +#define FIQ_SOURCE_REG 0x20 +#define FIQ_MASK_REG 0x24 +#define FIQ_CLEAR_REG 0x28 +#define FIQ_MODE_REG 0x2c +#define FIQ_LEVEL_REG 0x30 +#define FIQ_STATUS_REG 0x34 + + +struct moxart_irq_data { + void __iomem *base; + struct irq_domain *domain; + unsigned int interrupt_mask; +}; + +static struct moxart_irq_data intc; + +static asmlinkage void __exception_irq_entry handle_irq(struct pt_regs *regs) +{ + u32 irqstat; + int hwirq; + + irqstat = readl(intc.base + IRQ_STATUS_REG); + + while (irqstat) { + hwirq = ffs(irqstat) - 1; + handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs); + irqstat &= ~(1 << hwirq); + } +} + +static int __init moxart_of_intc_init(struct device_node *node, + struct device_node *parent) +{ + unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; + int ret; + struct irq_chip_generic *gc; + + intc.base = of_iomap(node, 0); + if (!intc.base) { + pr_err("%s: unable to map IC registers\n", + node->full_name); + return -EINVAL; + } + + intc.domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops, + intc.base); + if (!intc.domain) { + pr_err("%s: unable to create IRQ domain\n", node->full_name); + return -EINVAL; + } + + ret = irq_alloc_domain_generic_chips(intc.domain, 32, 1, + "MOXARTINTC", handle_edge_irq, + clr, 0, IRQ_GC_INIT_MASK_CACHE); + if (ret) { + pr_err("%s: could not allocate generic chip\n", + node->full_name); + irq_domain_remove(intc.domain); + return -EINVAL; + } + + ret = of_property_read_u32(node, "interrupt-mask", + &intc.interrupt_mask); + if (ret) + pr_err("%s: could not read interrupt-mask DT property\n", + node->full_name); + + gc = irq_get_domain_generic_chip(intc.domain, 0); + + gc->reg_base = intc.base; + gc->chip_types[0].regs.mask = IRQ_MASK_REG; + gc->chip_types[0].regs.ack = IRQ_CLEAR_REG; + gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; + gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; + gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; + + writel(0, intc.base + IRQ_MASK_REG); + writel(0xffffffff, intc.base + IRQ_CLEAR_REG); + + writel(intc.interrupt_mask, intc.base + IRQ_MODE_REG); + writel(intc.interrupt_mask, intc.base + IRQ_LEVEL_REG); + + set_handle_irq(handle_irq); + + return 0; +} +IRQCHIP_DECLARE(moxa_moxart_ic, "moxa,moxart-ic", moxart_of_intc_init); -- GitLab From 016fcab8ff46fca29375d484226ec91932aa4a07 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 4 Jul 2013 20:01:02 -0300 Subject: [PATCH 2313/2900] ASoC: sglt5000: Fix the default value of CHIP_SSS_CTRL According to the sgtl5000 reference manual, the default value of CHIP_SSS_CTRL is 0x10. Reported-by: Oskar Schirmer Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d441559dc92c..d659d3adcfb3 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -38,7 +38,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_CHIP_CLK_CTRL, 0x0008 }, { SGTL5000_CHIP_I2S_CTRL, 0x0010 }, - { SGTL5000_CHIP_SSS_CTRL, 0x0008 }, + { SGTL5000_CHIP_SSS_CTRL, 0x0010 }, { SGTL5000_CHIP_DAC_VOL, 0x3c3c }, { SGTL5000_CHIP_PAD_STRENGTH, 0x015f }, { SGTL5000_CHIP_ANA_HP_CTRL, 0x1818 }, -- GitLab From 5c78dfe87ea04b501ee000a7f03b9432ac9d008c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 4 Jul 2013 20:01:03 -0300 Subject: [PATCH 2314/2900] ASoC: sglt5000: Fix SGTL5000_PLL_FRAC_DIV_MASK SGTL5000_PLL_FRAC_DIV_MASK is used to mask bits 0-10 (11 bits in total) of register CHIP_PLL_CTRL, so fix the mask to accomodate all this bit range. Reported-by: Oskar Schirmer Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/sgtl5000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 4b69229a9818..2f8c88931f69 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -347,7 +347,7 @@ #define SGTL5000_PLL_INT_DIV_MASK 0xf800 #define SGTL5000_PLL_INT_DIV_SHIFT 11 #define SGTL5000_PLL_INT_DIV_WIDTH 5 -#define SGTL5000_PLL_FRAC_DIV_MASK 0x0700 +#define SGTL5000_PLL_FRAC_DIV_MASK 0x07ff #define SGTL5000_PLL_FRAC_DIV_SHIFT 0 #define SGTL5000_PLL_FRAC_DIV_WIDTH 11 -- GitLab From 10a0b6176b9f8b026ce07acd8f755297653c443c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 5 Jul 2013 12:15:56 +0300 Subject: [PATCH 2315/2900] ACPI / power: add missing newline to debug messages There are few places in power.c where debug messages have no newline at the end. Reading such debug messages from dmesg is not fun, so fix this by adding the missing newlines. Signed-off-by: Mika Westerberg Cc: All Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 288bb270f8ed..5c28c894c0fc 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -279,7 +279,7 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource) if (resource->ref_count++) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Power resource [%s] already on", + "Power resource [%s] already on\n", resource->name)); } else { result = __acpi_power_on(resource); @@ -325,7 +325,7 @@ static int acpi_power_off_unlocked(struct acpi_power_resource *resource) if (!resource->ref_count) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Power resource [%s] already off", + "Power resource [%s] already off\n", resource->name)); return 0; } -- GitLab From 82e414fa1dbbc07e7b6d582e4fbcc9b0a5299f7f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 12:36:24 +0100 Subject: [PATCH 2316/2900] ASoC: wm8994: Remove overly noisy debug logging This was committed in error. Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 25580b5a853f..1b89aa9029e8 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3856,8 +3856,6 @@ static void wm8958_mic_work(struct work_struct *work) mic_complete_work.work); struct snd_soc_codec *codec = wm8994->hubs.codec; - dev_crit(codec->dev, "MIC WORK %x\n", wm8994->mic_status); - pm_runtime_get_sync(codec->dev); mutex_lock(&wm8994->accdet_lock); @@ -3867,8 +3865,6 @@ static void wm8958_mic_work(struct work_struct *work) mutex_unlock(&wm8994->accdet_lock); pm_runtime_put(codec->dev); - - dev_crit(codec->dev, "MIC WORK %x DONE\n", wm8994->mic_status); } static irqreturn_t wm8958_mic_irq(int irq, void *data) -- GitLab From 07ecbf244bc5b7537f615647871fa2a71ffab072 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 5 Jul 2013 10:31:43 -0300 Subject: [PATCH 2317/2900] [media] stb0899: restore minimal rate to 5Mbauds According with Manu Abraham, stb0899 seek algorithm is broken for symbol rates bellow to 5Mbauds. So, revert those patches: 55b3318 [media] stb0899: allow minimum symbol rate of 2000000 2eeed77 [media] stb0899: allow minimum symbol rate of 1000000 Requested-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 82391feb6839..3dd5714eadba 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1581,7 +1581,7 @@ static struct dvb_frontend_ops stb0899_ops = { .frequency_max = 2150000, .frequency_stepsize = 0, .frequency_tolerance = 0, - .symbol_rate_min = 2000000, + .symbol_rate_min = 5000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | -- GitLab From c9faff6cbb3d2b37b3aa356ce455848f91685b24 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 13 Jun 2013 11:50:26 +0300 Subject: [PATCH 2318/2900] mmc: sdhci-pci: add support for eMMC hardware reset for BYT eMMC. Add support for eMMC hardware reset for BYT eMMC. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pci.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 611331a39fe5..e082fac6bc96 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -77,6 +77,8 @@ struct sdhci_pci_slot { int rst_n_gpio; int cd_gpio; int cd_irq; + + void (*hw_reset)(struct sdhci_host *host); }; struct sdhci_pci_chip { @@ -307,10 +309,27 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { .probe_slot = pch_hc_probe_slot, }; +static void sdhci_pci_int_hw_reset(struct sdhci_host *host) +{ + u8 reg; + + reg = sdhci_readb(host, SDHCI_POWER_CONTROL); + reg |= 0x10; + sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); + /* For eMMC, minimum is 1us but give it 9us for good measure */ + udelay(9); + reg &= ~0x10; + sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); + /* For eMMC, minimum is 200us but give it 300us for good measure */ + usleep_range(300, 1000); +} + static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) { - slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; + slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | + MMC_CAP_HW_RESET; slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; + slot->hw_reset = sdhci_pci_int_hw_reset; return 0; } @@ -1016,7 +1035,7 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width) return 0; } -static void sdhci_pci_hw_reset(struct sdhci_host *host) +static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host) { struct sdhci_pci_slot *slot = sdhci_priv(host); int rst_n_gpio = slot->rst_n_gpio; @@ -1031,6 +1050,14 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) usleep_range(300, 1000); } +static void sdhci_pci_hw_reset(struct sdhci_host *host) +{ + struct sdhci_pci_slot *slot = sdhci_priv(host); + + if (slot->hw_reset) + slot->hw_reset(host); +} + static const struct sdhci_ops sdhci_pci_ops = { .enable_dma = sdhci_pci_enable_dma, .platform_bus_width = sdhci_pci_bus_width, @@ -1328,6 +1355,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) { gpio_direction_output(slot->rst_n_gpio, 1); slot->host->mmc->caps |= MMC_CAP_HW_RESET; + slot->hw_reset = sdhci_pci_gpio_hw_reset; } else { dev_warn(&pdev->dev, "failed to request rst_n_gpio\n"); slot->rst_n_gpio = -EINVAL; -- GitLab From b04fa064e72c301e075c2d52c146282f8f464083 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 13 Jun 2013 11:50:27 +0300 Subject: [PATCH 2319/2900] mmc: sdhci-acpi: add support for eMMC hardware reset for HID 80860F14 Add support for eMMC hardware reset for HID 80860F14. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-acpi.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 08a85ec33224..cdd4ce0d7c90 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -85,12 +86,37 @@ static int sdhci_acpi_enable_dma(struct sdhci_host *host) return 0; } +static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) +{ + u8 reg; + + reg = sdhci_readb(host, SDHCI_POWER_CONTROL); + reg |= 0x10; + sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); + /* For eMMC, minimum is 1us but give it 9us for good measure */ + udelay(9); + reg &= ~0x10; + sdhci_writeb(host, reg, SDHCI_POWER_CONTROL); + /* For eMMC, minimum is 200us but give it 300us for good measure */ + usleep_range(300, 1000); +} + static const struct sdhci_ops sdhci_acpi_ops_dflt = { .enable_dma = sdhci_acpi_enable_dma, }; +static const struct sdhci_ops sdhci_acpi_ops_int = { + .enable_dma = sdhci_acpi_enable_dma, + .hw_reset = sdhci_acpi_int_hw_reset, +}; + +static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { + .ops = &sdhci_acpi_ops_int, +}; + static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { - .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, + .chip = &sdhci_acpi_chip_int, + .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET, .caps2 = MMC_CAP2_HC_ERASE_SZ, .flags = SDHCI_ACPI_RUNTIME_PM, }; -- GitLab From 04520817d90f1dce863ab7f06531da7579798696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Thu, 13 Jun 2013 10:56:23 +0200 Subject: [PATCH 2320/2900] mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove dw_mci_pltfm_remove gets exported and used by dw_mmc-exynos, so should not be static. Signed-off-by: Heiko Stuebner Acked-by: Jaehoon Chung Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc-pltfm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 2721bd5839cb..19edb0cd0c5e 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -65,7 +65,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, NULL); } -static int dw_mci_pltfm_remove(struct platform_device *pdev) +int dw_mci_pltfm_remove(struct platform_device *pdev) { struct dw_mci *host = platform_get_drvdata(pdev); -- GitLab From b177a530bbe4f7dd01617f542311f87208d21ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Thu, 13 Jun 2013 10:57:01 +0200 Subject: [PATCH 2321/2900] mmc: dw_mmc-pltfm: move probe and remove below dt match table In a subsquent patch probe will need to do some handling of data from the dt match table. So to prevent the need for forward declarations, move probe and remove below the match table. Signed-off-by: Heiko Stuebner Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- drivers/mmc/host/dw_mmc-pltfm.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 19edb0cd0c5e..54e6f061daa4 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -60,20 +60,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev, } EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); -static int dw_mci_pltfm_probe(struct platform_device *pdev) -{ - return dw_mci_pltfm_register(pdev, NULL); -} - -int dw_mci_pltfm_remove(struct platform_device *pdev) -{ - struct dw_mci *host = platform_get_drvdata(pdev); - - dw_mci_remove(host); - return 0; -} -EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); - #ifdef CONFIG_PM_SLEEP /* * TODO: we should probably disable the clock to the card in the suspend path. @@ -105,6 +91,20 @@ static const struct of_device_id dw_mci_pltfm_match[] = { }; MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); +static int dw_mci_pltfm_probe(struct platform_device *pdev) +{ + return dw_mci_pltfm_register(pdev, NULL); +} + +int dw_mci_pltfm_remove(struct platform_device *pdev) +{ + struct dw_mci *host = platform_get_drvdata(pdev); + + dw_mci_remove(host); + return 0; +} +EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); + static struct platform_driver dw_mci_pltfm_driver = { .probe = dw_mci_pltfm_probe, .remove = dw_mci_pltfm_remove, -- GitLab From c73e41c898bb59aaf50098c2c672c7132a88fdbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Thu, 27 Jun 2013 11:55:35 -0400 Subject: [PATCH 2322/2900] mmc: dw_mmc-pltfm: add Rockchip variant Cortex-A9 SoCs from Rockchip use a slightly modified variant of dw_mmc controllers that seems to require the SDMMC_CMD_USE_HOLD_REG bit to always be set. There also seem to be no other modifications (additional register etc) present, so to keep the footprint low, add this small variant to the pltfm driver. Signed-off-by: Heiko Stuebner Acked-by: Seungwon Jeon Signed-off-by: Chris Ball --- .../bindings/mmc/rockchip-dw-mshc.txt | 23 +++++++++++++++++++ drivers/mmc/host/dw_mmc-pltfm.c | 21 ++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt new file mode 100644 index 000000000000..8a3d91d47b6a --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt @@ -0,0 +1,23 @@ +* Rockchip specific extensions to the Synopsis Designware Mobile + Storage Host Controller + +The Synopsis designware mobile storage host controller is used to interface +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents +differences between the core Synopsis dw mshc controller properties described +by synopsis-dw-mshc.txt and the properties used by the Rockchip specific +extensions to the Synopsis Designware Mobile Storage Host Controller. + +Required Properties: + +* compatible: should be + - "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following + +Example: + + rkdwmmc0@12200000 { + compatible = "rockchip,rk2928-dw-mshc"; + reg = <0x12200000 0x1000>; + interrupts = <0 75 0>; + #address-cells = <1>; + #size-cells = <0>; + }; diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 54e6f061daa4..ee525565aa77 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -24,6 +24,15 @@ #include "dw_mmc.h" +static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static const struct dw_mci_drv_data rockchip_drv_data = { + .prepare_command = dw_mci_rockchip_prepare_command, +}; + int dw_mci_pltfm_register(struct platform_device *pdev, const struct dw_mci_drv_data *drv_data) { @@ -87,13 +96,23 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); static const struct of_device_id dw_mci_pltfm_match[] = { { .compatible = "snps,dw-mshc", }, + { .compatible = "rockchip,rk2928-dw-mshc", + .data = &rockchip_drv_data }, {}, }; MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); static int dw_mci_pltfm_probe(struct platform_device *pdev) { - return dw_mci_pltfm_register(pdev, NULL); + const struct dw_mci_drv_data *drv_data = NULL; + const struct of_device_id *match; + + if (pdev->dev.of_node) { + match = of_match_node(dw_mci_pltfm_match, pdev->dev.of_node); + drv_data = match->data; + } + + return dw_mci_pltfm_register(pdev, drv_data); } int dw_mci_pltfm_remove(struct platform_device *pdev) -- GitLab From 599115686d8f62999a871f7d7ee87de3b939b258 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Thu, 13 Jun 2013 16:41:28 +0200 Subject: [PATCH 2323/2900] mmc: sdhci: fix ctrl_2 on super-speed selection This patch fixes the HC ctrl_2 programming where, in case of SDR104 and HS200, we have to write 100b in the the UHS Mode bits. We wrote 101b that is reserved from Arasan Specs. Reported-by: Youssef Triki Signed-off-by: Giuseppe Cavallaro Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9bd6ab203843..3ad3973bdb33 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1543,16 +1543,15 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); /* Select Bus Speed Mode for host */ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; - if (ios->timing == MMC_TIMING_MMC_HS200) - ctrl_2 |= SDHCI_CTRL_HS_SDR200; + if ((ios->timing == MMC_TIMING_MMC_HS200) || + (ios->timing == MMC_TIMING_UHS_SDR104)) + ctrl_2 |= SDHCI_CTRL_UHS_SDR104; else if (ios->timing == MMC_TIMING_UHS_SDR12) ctrl_2 |= SDHCI_CTRL_UHS_SDR12; else if (ios->timing == MMC_TIMING_UHS_SDR25) ctrl_2 |= SDHCI_CTRL_UHS_SDR25; else if (ios->timing == MMC_TIMING_UHS_SDR50) ctrl_2 |= SDHCI_CTRL_UHS_SDR50; - else if (ios->timing == MMC_TIMING_UHS_SDR104) - ctrl_2 |= SDHCI_CTRL_UHS_SDR104; else if (ios->timing == MMC_TIMING_UHS_DDR50) ctrl_2 |= SDHCI_CTRL_UHS_DDR50; sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); -- GitLab From d7a985e08fe84307430090b8604f5652080cc930 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 13 Jun 2013 18:25:55 +0300 Subject: [PATCH 2324/2900] mmc: omap: remove unnecessary #if 0's In commit 3451c067 (mmc: omap: add DMA engine support), some #if 0's were used to comment out parts of the code. This has been in the code for over a year and are not needed anymore (and the commented-out code doesn't even compile). Remove them. Signed-off-by: Luciano Coelho Signed-off-by: Chris Ball --- drivers/mmc/host/omap.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 4b3e0eb77fe0..b94f38ec2a83 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1413,33 +1413,17 @@ static int mmc_omap_probe(struct platform_device *pdev) else sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX; host->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig); -#if 0 - if (!host->dma_tx) { - dev_err(host->dev, "unable to obtain TX DMA engine channel %u\n", - sig); - goto err_dma; - } -#else if (!host->dma_tx) dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n", sig); -#endif if (mmc_omap2()) sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX; else sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX; host->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig); -#if 0 - if (!host->dma_rx) { - dev_err(host->dev, "unable to obtain RX DMA engine channel %u\n", - sig); - goto err_dma; - } -#else if (!host->dma_rx) dev_warn(host->dev, "unable to obtain RX DMA engine channel %u\n", sig); -#endif ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); if (ret) -- GitLab From 7c4f10ac5a940b3994be7f1801a606f8605e7a69 Mon Sep 17 00:00:00 2001 From: Romain Izard Date: Fri, 14 Jun 2013 14:25:44 +0200 Subject: [PATCH 2325/2900] mmc: core: production year for eMMC 4.41 and later The field containing the production date in the CID register only uses 4 bits to encode the year, starting from 1997 in the original standard. In 2013, the production year field contains 0, and the kernel reports a 1997 production date. The eMMC 4.51 specification adds a new interpretation rule. For all devices implementing the 4.41 specification or later, the production year field will be interpreted as a value between 2010 and 2025, with 0 corresponding to 2013. Signed-off-by: Romain Izard Signed-off-by: Chris Ball --- drivers/mmc/core/mmc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index e5ed79eb8e3d..6d02012a1d0b 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -482,6 +482,10 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } if (card->ext_csd.rev >= 5) { + /* Adjust production date as per JEDEC JESD84-B451 */ + if (card->cid.year < 2010) + card->cid.year += 16; + /* check whether the eMMC card supports BKOPS */ if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) { card->ext_csd.bkops = 1; -- GitLab From 66b50a00992dca97b442e016a9b2dba892e2df61 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Thu, 27 Jun 2013 12:00:05 -0400 Subject: [PATCH 2326/2900] mmc: esdhc: Add support for 8-bit bus width and non-removable card This patch adds support of connecting an MMC media using an 8-bit bus width connection to Freescale's P2020 H/W SDHC controller. During the probe function, the generic function mmc_of_parse is called to detect whether the controller is configured with 8-bit bus width. Also, the generic function detects if the non-removable property is set in the device tree. The function esdhc_pltfm_bus_width was added because the bus width configuration is platform specific. Signed-off-by: Oded Gabbay Reviewed-by: Anton Vorontsov Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-esdhc.h | 7 +++++ drivers/mmc/host/sdhci-of-esdhc.c | 44 ++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index 6f16406c37cd..a2a06420e463 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -36,6 +36,13 @@ /* pltfm-specific */ #define ESDHC_HOST_CONTROL_LE 0x20 +/* + * P2020 interpretation of the SDHCI_HOST_CONTROL register + */ +#define ESDHC_CTRL_4BITBUS (0x1 << 1) +#define ESDHC_CTRL_8BITBUS (0x2 << 1) +#define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) + /* OF-specific */ #define ESDHC_DMA_SYSCTL 0x40c #define ESDHC_DMA_SNOOP 0x00000040 diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 2b7369729f91..b2a635e73aee 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -13,6 +13,7 @@ * your option) any later version. */ +#include #include #include #include @@ -230,6 +231,30 @@ static void esdhc_of_platform_init(struct sdhci_host *host) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; } +static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width) +{ + u32 ctrl; + + switch (width) { + case MMC_BUS_WIDTH_8: + ctrl = ESDHC_CTRL_8BITBUS; + break; + + case MMC_BUS_WIDTH_4: + ctrl = ESDHC_CTRL_4BITBUS; + break; + + default: + ctrl = 0; + break; + } + + clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL, + ESDHC_CTRL_BUSWIDTH_MASK, ctrl); + + return 0; +} + static const struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl, .read_w = esdhc_readw, @@ -247,6 +272,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .platform_resume = esdhc_of_resume, #endif .adma_workaround = esdhci_of_adma_workaround, + .platform_bus_width = esdhc_pltfm_bus_width, }; static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { @@ -262,7 +288,23 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { static int sdhci_esdhc_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata, 0); + struct sdhci_host *host; + int ret; + + host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); + if (IS_ERR(host)) + return PTR_ERR(host); + + sdhci_get_of_property(pdev); + + /* call to generic mmc_of_parse to support additional capabilities */ + mmc_of_parse(host->mmc); + + ret = sdhci_add_host(host); + if (ret) + sdhci_pltfm_free(pdev); + + return ret; } static int sdhci_esdhc_remove(struct platform_device *pdev) -- GitLab From dcaff04d36fd7f22973bf4fc108912ce19bcef4f Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Fri, 5 Jul 2013 12:48:35 -0400 Subject: [PATCH 2327/2900] mmc: esdhc: Fix bug when writing to SDHCI_HOST_CONTROL register The P2020 has a non-standard implementation of the SDHCI_HOST_CONTROL register. This patch adds a QUIRK in the SDHCI header to signal that a host controller has a non-standard SDHCI_HOST_CONTROL register. The patch adds a check to the function esdhc_writeb in file sdhci-of-esdhc.c, where it checks if the write is done to the SDHCI_HOST_CONTROL register and th host has the above mentioned QUIRK, then the function simply returns instead of writing to the register. The patch also detects if the processor is P2020 (by looking in dev tree) and if so, adds the QUIRK to the host->quirk2 Signed-off-by: Oded Gabbay Reviewed-by: Anton Vorontsov Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-of-esdhc.c | 17 +++++++++++++++++ include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index b2a635e73aee..15039e2d1c12 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -121,6 +121,13 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) if (reg == SDHCI_HOST_CONTROL) { u32 dma_bits; + /* + * If host control register is not standard, exit + * this function + */ + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) + return; + /* DMA select is 22,23 bits in Protocol Control Register */ dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, @@ -289,6 +296,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { static int sdhci_esdhc_probe(struct platform_device *pdev) { struct sdhci_host *host; + struct device_node *np; int ret; host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); @@ -297,6 +305,15 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + np = pdev->dev.of_node; + if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { + /* + * Freescale messed up with P2020 as it has a non-standard + * host control register + */ + host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; + } + /* call to generic mmc_of_parse to support additional capabilities */ mmc_of_parse(host->mmc); diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index a74518009099..e3c6a74d980a 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -96,6 +96,8 @@ struct sdhci_host { #define SDHCI_QUIRK2_NO_1_8_V (1<<2) #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3) #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1<<4) +/* Controller has a non-standard host control register */ +#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- GitLab From 30d025c0f7234409e8ee1bf22d1729055e640ec6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Jun 2013 12:57:59 +0300 Subject: [PATCH 2328/2900] mmc: sdhci-pci: add another device id Add another PCI device id for an eMMC host controller. Signed-off-by: Adrian Hunter Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci-pci.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index e082fac6bc96..d7d6bc8968d2 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -36,6 +36,7 @@ #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 +#define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 /* * PCI registers @@ -930,6 +931,14 @@ static const struct pci_device_id pci_ids[] = { .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_BYT_EMMC2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, + }, + { .vendor = PCI_VENDOR_ID_O2, .device = PCI_DEVICE_ID_O2_8120, -- GitLab From 203bb5af65d4edaf600d75130438c0c512b05986 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 2 Jul 2013 12:53:01 +0200 Subject: [PATCH 2329/2900] mmc: core: Fixup Oops for SDIO shutdown Commit "mmc: core: Handle card shutdown from mmc_bus" introduced an Oops in the shutdown sequence for SDIO. The drv pointer, does not exist for SDIO since the probing of the SDIO card from the mmc_bus perspective is expected to fail by returning -ENODEV. This patch adds the proper check for the pointer before calling it. Signed-off-by: Ulf Hansson Reported-by: Stephen Warren Reported-by: Tuomas Tynkkynen Tested-by: Tuomas Tynkkynen Acked-by: Jaehoon Chung Signed-off-by: Chris Ball --- drivers/mmc/core/bus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 4c0decfffb53..d4b99bbe0781 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -129,7 +129,8 @@ static void mmc_bus_shutdown(struct device *dev) struct mmc_host *host = card->host; int ret; - drv->shutdown(card); + if (dev->driver && drv->shutdown) + drv->shutdown(card); if (host->bus_ops->shutdown) { ret = host->bus_ops->shutdown(host); -- GitLab From 722e1280c932dd42c474390482429ce12aff9031 Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Thu, 20 Jun 2013 14:26:36 -0700 Subject: [PATCH 2330/2900] mmc: sdhci: add card_event callback to sdhci Add a card_event callback to sdhci so that clients can provide their own card_event to be called when card_detect is triggered. Signed-off-by: Christian Daudt Signed-off-by: Chris Ball --- drivers/mmc/host/sdhci.c | 4 ++++ drivers/mmc/host/sdhci.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3ad3973bdb33..a78bd4f3aecc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2062,6 +2062,10 @@ static void sdhci_card_event(struct mmc_host *mmc) struct sdhci_host *host = mmc_priv(mmc); unsigned long flags; + /* First check if client has provided their own card event */ + if (host->ops->card_event) + host->ops->card_event(host); + spin_lock_irqsave(&host->lock, flags); /* Check host->mrq first in case we are runtime suspended */ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 379e09d9f3c1..b037f188fe44 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -294,6 +294,7 @@ struct sdhci_ops { void (*platform_resume)(struct sdhci_host *host); void (*adma_workaround)(struct sdhci_host *host, u32 intmask); void (*platform_init)(struct sdhci_host *host); + void (*card_event)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS -- GitLab From 01ebea1b411aafc8eab440bf1d2037f01bbed99b Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Thu, 20 Jun 2013 14:26:37 -0700 Subject: [PATCH 2331/2900] mmc: bcm281xx SDHCI driver Add SDHCI driver for the Broadcom 281xx SoCs. Still missing: - power managemement Signed-off-by: Christian Daudt Acked-by: Arnd Bergmann Signed-off-by: Chris Ball --- arch/arm/configs/bcm_defconfig | 7 + drivers/mmc/host/Kconfig | 11 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-bcm-kona.c | 348 ++++++++++++++++++++++++++++++ 4 files changed, 367 insertions(+) create mode 100644 drivers/mmc/host/sdhci-bcm-kona.c diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig index e3bf2d65618e..65edf6d47215 100644 --- a/arch/arm/configs/bcm_defconfig +++ b/arch/arm/configs/bcm_defconfig @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_TEST=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_BCM_KONA=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_TRIGGERS=y diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1be228998c81..8a4c066787d7 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -249,6 +249,17 @@ config MMC_SDHCI_S3C_DMA YMMV. +config MMC_SDHCI_BCM_KONA + tristate "SDHCI support on Broadcom KONA platform" + depends on ARCH_BCM + select MMC_SDHCI_PLTFM + help + This selects the Broadcom Kona Secure Digital Host Controller + Interface(SDHCI) support. + This is used in Broadcom mobile SoCs. + + If you have a controller with this interface, say Y or M here. + config MMC_SDHCI_BCM2835 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" depends on ARCH_BCM2835 diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 67718c1b79ce..d422e2167e19 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o obj-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o +obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += sdhci-bcm2835.o ifeq ($(CONFIG_CB710_DEBUG),y) diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c new file mode 100644 index 000000000000..87175f9817c2 --- /dev/null +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2013 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdhci-pltfm.h" +#include "sdhci.h" + +#define SDHCI_SOFT_RESET 0x01000000 +#define KONA_SDHOST_CORECTRL 0x8000 +#define KONA_SDHOST_CD_PINCTRL 0x00000008 +#define KONA_SDHOST_STOP_HCLK 0x00000004 +#define KONA_SDHOST_RESET 0x00000002 +#define KONA_SDHOST_EN 0x00000001 + +#define KONA_SDHOST_CORESTAT 0x8004 +#define KONA_SDHOST_WP 0x00000002 +#define KONA_SDHOST_CD_SW 0x00000001 + +#define KONA_SDHOST_COREIMR 0x8008 +#define KONA_SDHOST_IP 0x00000001 + +#define KONA_SDHOST_COREISR 0x800C +#define KONA_SDHOST_COREIMSR 0x8010 +#define KONA_SDHOST_COREDBG1 0x8014 +#define KONA_SDHOST_COREGPO_MASK 0x8018 + +#define SD_DETECT_GPIO_DEBOUNCE_128MS 128 + +#define KONA_MMC_AUTOSUSPEND_DELAY (50) + +struct sdhci_bcm_kona_dev { + struct mutex write_lock; /* protect back to back writes */ +}; + + +static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host) +{ + unsigned int val; + unsigned long timeout; + + /* This timeout should be sufficent for core to reset */ + timeout = jiffies + msecs_to_jiffies(100); + + /* reset the host using the top level reset */ + val = sdhci_readl(host, KONA_SDHOST_CORECTRL); + val |= KONA_SDHOST_RESET; + sdhci_writel(host, val, KONA_SDHOST_CORECTRL); + + while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) { + if (time_is_before_jiffies(timeout)) { + pr_err("Error: sd host is stuck in reset!!!\n"); + return -EFAULT; + } + } + + /* bring the host out of reset */ + val = sdhci_readl(host, KONA_SDHOST_CORECTRL); + val &= ~KONA_SDHOST_RESET; + + /* + * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) + * Back-to-Back writes to same register needs delay when SD bus clock + * is very low w.r.t AHB clock, mainly during boot-time and during card + * insert-removal. + */ + usleep_range(1000, 5000); + sdhci_writel(host, val, KONA_SDHOST_CORECTRL); + + return 0; +} + +static void sdhci_bcm_kona_sd_init(struct sdhci_host *host) +{ + unsigned int val; + + /* enable the interrupt from the IP core */ + val = sdhci_readl(host, KONA_SDHOST_COREIMR); + val |= KONA_SDHOST_IP; + sdhci_writel(host, val, KONA_SDHOST_COREIMR); + + /* Enable the AHB clock gating module to the host */ + val = sdhci_readl(host, KONA_SDHOST_CORECTRL); + val |= KONA_SDHOST_EN; + + /* + * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS) + * Back-to-Back writes to same register needs delay when SD bus clock + * is very low w.r.t AHB clock, mainly during boot-time and during card + * insert-removal. + */ + usleep_range(1000, 5000); + sdhci_writel(host, val, KONA_SDHOST_CORECTRL); +} + +/* + * Software emulation of the SD card insertion/removal. Set insert=1 for insert + * and insert=0 for removal. The card detection is done by GPIO. For Broadcom + * IP to function properly the bit 0 of CORESTAT register needs to be set/reset + * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet. + */ +static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert) +{ + struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); + struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); + u32 val; + + /* + * Back-to-Back register write needs a delay of min 10uS. + * Back-to-Back writes to same register needs delay when SD bus clock + * is very low w.r.t AHB clock, mainly during boot-time and during card + * insert-removal. + * We keep 20uS + */ + mutex_lock(&kona_dev->write_lock); + udelay(20); + val = sdhci_readl(host, KONA_SDHOST_CORESTAT); + + if (insert) { + int ret; + + ret = mmc_gpio_get_ro(host->mmc); + if (ret >= 0) + val = (val & ~KONA_SDHOST_WP) | + ((ret) ? KONA_SDHOST_WP : 0); + + val |= KONA_SDHOST_CD_SW; + sdhci_writel(host, val, KONA_SDHOST_CORESTAT); + } else { + val &= ~KONA_SDHOST_CD_SW; + sdhci_writel(host, val, KONA_SDHOST_CORESTAT); + } + mutex_unlock(&kona_dev->write_lock); + + return 0; +} + +/* + * SD card interrupt event callback + */ +void sdhci_bcm_kona_card_event(struct sdhci_host *host) +{ + if (mmc_gpio_get_cd(host->mmc) > 0) { + dev_dbg(mmc_dev(host->mmc), + "card inserted\n"); + sdhci_bcm_kona_sd_card_emulate(host, 1); + } else { + dev_dbg(mmc_dev(host->mmc), + "card removed\n"); + sdhci_bcm_kona_sd_card_emulate(host, 0); + } +} + +/* + * Get the base clock. Use central clock source for now. Not sure if different + * clock speed to each dev is allowed + */ +static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) +{ + struct sdhci_bcm_kona_dev *kona_dev; + struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); + kona_dev = sdhci_pltfm_priv(pltfm_priv); + + return host->mmc->f_max; +} + +static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) +{ + return sdhci_bcm_kona_get_max_clk(host); +} + +static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, + u8 power_mode) +{ + /* + * JEDEC and SD spec specify supplying 74 continuous clocks to + * device after power up. With minimum bus (100KHz) that + * that translates to 740us + */ + if (power_mode != MMC_POWER_OFF) + udelay(740); +} + +static struct sdhci_ops sdhci_bcm_kona_ops = { + .get_max_clock = sdhci_bcm_kona_get_max_clk, + .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, + .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, + .card_event = sdhci_bcm_kona_card_event, +}; + +static struct sdhci_pltfm_data sdhci_pltfm_data_kona = { + .ops = &sdhci_bcm_kona_ops, + .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR | + SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE | + SDHCI_QUIRK_FORCE_BLK_SZ_2048 | + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, +}; + +static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = { + { .compatible = "bcm,kona-sdhci"}, + {} +}; +MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match); + +static int __init sdhci_bcm_kona_probe(struct platform_device *pdev) +{ + struct sdhci_bcm_kona_dev *kona_dev = NULL; + struct sdhci_pltfm_host *pltfm_priv; + struct device *dev = &pdev->dev; + struct sdhci_host *host; + int ret; + + ret = 0; + + host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona, + sizeof(*kona_dev)); + if (IS_ERR(host)) + return PTR_ERR(host); + + dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr); + + pltfm_priv = sdhci_priv(host); + + kona_dev = sdhci_pltfm_priv(pltfm_priv); + mutex_init(&kona_dev->write_lock); + + mmc_of_parse(host->mmc); + + if (!host->mmc->f_max) { + dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n"); + ret = -ENXIO; + goto err_pltfm_free; + } + + dev_dbg(dev, "non-removable=%c\n", + (host->mmc->caps & MMC_CAP_NONREMOVABLE) ? 'Y' : 'N'); + dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n", + (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N', + (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N'); + + if (host->mmc->caps | MMC_CAP_NONREMOVABLE) + host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; + + dev_dbg(dev, "is_8bit=%c\n", + (host->mmc->caps | MMC_CAP_8_BIT_DATA) ? 'Y' : 'N'); + + ret = sdhci_bcm_kona_sd_reset(host); + if (ret) + goto err_pltfm_free; + + sdhci_bcm_kona_sd_init(host); + + ret = sdhci_add_host(host); + if (ret) { + dev_err(dev, "Failed sdhci_add_host\n"); + goto err_reset; + } + + /* if device is eMMC, emulate card insert right here */ + if (host->mmc->caps | MMC_CAP_NONREMOVABLE) { + ret = sdhci_bcm_kona_sd_card_emulate(host, 1); + if (ret) { + dev_err(dev, + "unable to emulate card insertion\n"); + goto err_remove_host; + } + } + /* + * Since the card detection GPIO interrupt is configured to be + * edge sensitive, check the initial GPIO value here, emulate + * only if the card is present + */ + if (mmc_gpio_get_cd(host->mmc) > 0) + sdhci_bcm_kona_sd_card_emulate(host, 1); + + dev_dbg(dev, "initialized properly\n"); + return 0; + +err_remove_host: + sdhci_remove_host(host, 0); + +err_reset: + sdhci_bcm_kona_sd_reset(host); + +err_pltfm_free: + sdhci_pltfm_free(pdev); + + dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret); + return ret; +} + +static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + int dead; + u32 scratch; + + dead = 0; + scratch = readl(host->ioaddr + SDHCI_INT_STATUS); + if (scratch == (u32)-1) + dead = 1; + sdhci_remove_host(host, dead); + + sdhci_free_host(host); + + return 0; +} + +static struct platform_driver sdhci_bcm_kona_driver = { + .driver = { + .name = "sdhci-kona", + .owner = THIS_MODULE, + .pm = SDHCI_PLTFM_PMOPS, + .of_match_table = of_match_ptr(sdhci_bcm_kona_of_match), + }, + .probe = sdhci_bcm_kona_probe, + .remove = __exit_p(sdhci_bcm_kona_remove), +}; +module_platform_driver(sdhci_bcm_kona_driver); + +MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform"); +MODULE_AUTHOR("Broadcom"); +MODULE_LICENSE("GPL v2"); -- GitLab From 896eba3ba41e1a978e9e47cf2837ef8963996bca Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 3 Jun 2013 15:55:41 +0200 Subject: [PATCH 2332/2900] ARM: omap5: omap5 has SCU and TWD These are selected by omap4 but used in common omap4/5 SMP code, so building an omap5-only kernel is actually broken without this patch. Signed-off-by: Arnd Bergmann Cc: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1fdb46216590..1f8127afa744 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -110,6 +110,8 @@ config SOC_OMAP5 select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if LOCAL_TIMERS select HAVE_SMP select COMMON_CLK select HAVE_ARM_ARCH_TIMER -- GitLab From 514a590847ff42dc00ba6c6165736128ad7730a8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 13 Jun 2013 14:13:37 +0200 Subject: [PATCH 2333/2900] ARM: zynq: use DT_MACHINE_START The zynq platform code only supports DT based booting, so we should use DT_MACHINE_START rather than MACHINE_START. Signed-off-by: Arnd Bergmann Cc: Michal Simek --- arch/arm/mach-zynq/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 4130e65a0e3f..5b799c29886e 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -101,7 +101,7 @@ static const char * const zynq_dt_match[] = { NULL }; -MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") +DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform") .smp = smp_ops(zynq_smp_ops), .map_io = zynq_map_io, .init_machine = zynq_init_machine, -- GitLab From 59d92875a6d9f056233fafd6abd41f86eba931ef Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 1 May 2013 00:02:26 +0200 Subject: [PATCH 2334/2900] ARM: OMAP: build mach-omap code only if needed If we build a kernel with CONFIG_ARCH_OMAP2PLUS enabled but all of the individual SoCs disabled, we run into a large number of link errors because if incorrect dependencies: arch/arm/mach-omap2/built-in.o: In function `_add_initiator_dep': arch/arm/mach-omap2/omap_hwmod.c:691: undefined reference to `clkdm_add_sleepdep' arch/arm/mach-omap2/built-in.o: In function `_del_initiator_dep': arch/arm/mach-omap2/omap_hwmod.c:720: undefined reference to `clkdm_del_sleepdep' arch/arm/mach-omap2/built-in.o: In function `_enable': arch/arm/mach-omap2/omap_hwmod.c:2145: undefined reference to `clkdm_in_hwsup' arch/arm/mach-omap2/omap_hwmod.c:2147: undefined reference to `clkdm_hwmod_enable' arch/arm/mach-omap2/omap_hwmod.c:2191: undefined reference to `clkdm_hwmod_disable' arch/arm/mach-omap2/omap_hwmod.c:2146: undefined reference to `clkdm_missing_idle_reporting' arch/arm/mach-omap2/built-in.o: In function `_idle': arch/arm/mach-omap2/omap_hwmod.c:2235: undefined reference to `clkdm_hwmod_disable' arch/arm/mach-omap2/built-in.o: In function `_shutdown': arch/arm/mach-omap2/omap_hwmod.c:2338: undefined reference to `clkdm_hwmod_disable' arch/arm/mach-omap2/built-in.o: In function `omap_hwmod_get_context_loss_count': arch/arm/mach-omap2/omap_hwmod.c:4071: undefined reference to `pwrdm_get_context_loss_count' arch/arm/mach-omap2/built-in.o: In function `omap_pm_clkdms_setup': arch/arm/mach-omap2/pm.c:114: undefined reference to `clkdm_allow_idle' arch/arm/mach-omap2/pm.c:117: undefined reference to `clkdm_sleep' arch/arm/mach-omap2/built-in.o: In function `omap2_common_pm_late_init': arch/arm/mach-omap2/pm.c:294: undefined reference to `omap_voltage_late_init' arch/arm/mach-omap2/built-in.o: In function `omap2_gpio_dev_init': arch/arm/mach-omap2/gpio.c:133: undefined reference to `pwrdm_can_ever_lose_context' We can avoid this if we make CONFIG_ARCH_OMAP2PLUS a silent option that gets enabled any time that one of the SoC versions is enabled. Cc: Tony Lindgren Signed-off-by: Arnd Bergmann --- arch/arm/configs/omap2plus_defconfig | 4 + arch/arm/mach-omap2/Kconfig | 148 +++++++++++++-------------- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index 2ac0ffb12f03..f9b7fccd795d 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -22,6 +22,10 @@ CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set CONFIG_ARCH_MULTI_V6=y CONFIG_ARCH_OMAP2PLUS=y +CONFIG_ARCH_OMAP2=y +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y +CONFIG_SOC_AM33XX=y CONFIG_OMAP_RESET_CLOCKS=y CONFIG_OMAP_MUX_DEBUG=y CONFIG_ARCH_VEXPRESS_CA9X4=y diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1f8127afa744..5c1405157bb6 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -1,62 +1,10 @@ config ARCH_OMAP bool -config ARCH_OMAP2PLUS - bool "TI OMAP2/3/4/5 SoCs with device tree support" if (ARCH_MULTI_V6 || ARCH_MULTI_V7) - select ARCH_HAS_CPUFREQ - select ARCH_HAS_HOLES_MEMORYMODEL - select ARCH_OMAP - select ARCH_REQUIRE_GPIOLIB - select CLKDEV_LOOKUP - select CLKSRC_MMIO - select GENERIC_CLOCKEVENTS - select GENERIC_IRQ_CHIP - select HAVE_CLK - select OMAP_DM_TIMER - select PINCTRL - select PROC_DEVICETREE if PROC_FS - select SOC_BUS - select SPARSE_IRQ - select TI_PRIV_EDMA - select USE_OF - help - Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 - - -if ARCH_OMAP2PLUS - -menu "TI OMAP2/3/4 Specific Features" - -config ARCH_OMAP2PLUS_TYPICAL - bool "Typical OMAP configuration" - default y - select AEABI - select HIGHMEM - select I2C - select I2C_OMAP - select MENELAUS if ARCH_OMAP2 - select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 - select PM_RUNTIME - select REGULATOR - select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4 - select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4 - select VFP - help - Compile a kernel suitable for booting most boards - -config SOC_HAS_OMAP2_SDRC - bool "OMAP2 SDRAM Controller support" - -config SOC_HAS_REALTIME_COUNTER - bool "Real time free running counter" - depends on SOC_OMAP5 - default y - config ARCH_OMAP2 bool "TI OMAP2" - depends on ARCH_OMAP2PLUS depends on ARCH_MULTI_V6 - default y + select ARCH_OMAP2PLUS select CPU_V6 select MULTI_IRQ_HANDLER select SOC_HAS_OMAP2_SDRC @@ -64,9 +12,8 @@ config ARCH_OMAP2 config ARCH_OMAP3 bool "TI OMAP3" - depends on ARCH_OMAP2PLUS depends on ARCH_MULTI_V7 - default y + select ARCH_OMAP2PLUS select ARCH_HAS_OPP select ARM_CPU_SUSPEND if PM select CPU_V7 @@ -80,9 +27,8 @@ config ARCH_OMAP3 config ARCH_OMAP4 bool "TI OMAP4" - default y - depends on ARCH_OMAP2PLUS depends on ARCH_MULTI_V7 + select ARCH_OMAP2PLUS select ARCH_HAS_OPP select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP select ARM_CPU_SUSPEND if PM @@ -107,6 +53,7 @@ config ARCH_OMAP4 config SOC_OMAP5 bool "TI OMAP5" depends on ARCH_MULTI_V7 + select ARCH_OMAP2PLUS select ARM_CPU_SUSPEND if PM select ARM_GIC select CPU_V7 @@ -116,6 +63,76 @@ config SOC_OMAP5 select COMMON_CLK select HAVE_ARM_ARCH_TIMER +config SOC_AM33XX + bool "AM33XX support" + depends on ARCH_MULTI_V7 + select ARCH_OMAP2PLUS + select ARM_CPU_SUSPEND if PM + select CPU_V7 + select MULTI_IRQ_HANDLER + select COMMON_CLK + +config SOC_AM43XX + bool "TI AM43x" + depends on ARCH_MULTI_V7 + select CPU_V7 + select ARCH_OMAP2PLUS + select MULTI_IRQ_HANDLER + select ARM_GIC + select COMMON_CLK + select MACH_OMAP_GENERIC + +config ARCH_OMAP2PLUS + bool + select ARCH_HAS_BANDGAP + select ARCH_HAS_CPUFREQ + select ARCH_HAS_HOLES_MEMORYMODEL + select ARCH_OMAP + select ARCH_REQUIRE_GPIOLIB + select CLKDEV_LOOKUP + select CLKSRC_MMIO + select GENERIC_CLOCKEVENTS + select GENERIC_IRQ_CHIP + select HAVE_CLK + select OMAP_DM_TIMER + select PINCTRL + select PROC_DEVICETREE if PROC_FS + select SOC_BUS + select SPARSE_IRQ + select USE_OF + help + Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 + + +if ARCH_OMAP2PLUS + +menu "TI OMAP2/3/4 Specific Features" + +config ARCH_OMAP2PLUS_TYPICAL + bool "Typical OMAP configuration" + default y + select AEABI + select HIGHMEM + select I2C + select I2C_OMAP + select MENELAUS if ARCH_OMAP2 + select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 + select PM_RUNTIME + select REGULATOR + select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4 + select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4 + select VFP + help + Compile a kernel suitable for booting most boards + +config SOC_HAS_OMAP2_SDRC + bool "OMAP2 SDRAM Controller support" + +config SOC_HAS_REALTIME_COUNTER + bool "Real time free running counter" + depends on SOC_OMAP5 + default y + comment "OMAP Core Type" depends on ARCH_OMAP2 @@ -143,23 +160,6 @@ config SOC_TI81XX depends on ARCH_OMAP3 default y -config SOC_AM33XX - bool "AM33XX support" - depends on ARCH_MULTI_V7 - default y - select ARM_CPU_SUSPEND if PM - select CPU_V7 - select MULTI_IRQ_HANDLER - select COMMON_CLK - -config SOC_AM43XX - bool "TI AM43x" - select CPU_V7 - select MULTI_IRQ_HANDLER - select ARM_GIC - select COMMON_CLK - select MACH_OMAP_GENERIC - config OMAP_PACKAGE_ZAF bool -- GitLab From 5562b80033231bd50bd6809ab2db3b2ce5670dc3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 5 Jul 2013 16:08:44 +0200 Subject: [PATCH 2335/2900] ARM: sti: move DEBUG_STI_UART into alphabetical order This was accidentally added in the wrong place, messing up the ordering of the file. Signed-off-by: Arnd Bergmann --- arch/arm/Kconfig.debug | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 77c1411c9a91..ff4920b1f6c5 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -510,6 +510,16 @@ choice Say Y here if you want the debug print routines to direct their output to the uart1 port on SiRFmarco devices. + config DEBUG_STI_UART + depends on ARCH_STI + bool "Use StiH415/416 ASC for low-level debug" + help + Say Y here if you want kernel low-level debugging support + on StiH415/416 based platforms like B2000, B2020. + It support UART2 and SBC_UART1. + + If unsure, say N. + config DEBUG_U300_UART bool "Kernel low-level debugging messages via U300 UART0" depends on ARCH_U300 @@ -557,16 +567,6 @@ choice This option selects UART0 on VIA/Wondermedia System-on-a-chip devices, including VT8500, WM8505, WM8650 and WM8850. - config DEBUG_STI_UART - depends on ARCH_STI - bool "Use StiH415/416 ASC for low-level debug" - help - Say Y here if you want kernel low-level debugging support - on StiH415/416 based platforms like B2000, B2020. - It support UART2 and SBC_UART1. - - If unsure, say N. - config DEBUG_LL_UART_NONE bool "No low-level debugging UART" depends on !ARCH_MULTIPLATFORM -- GitLab From 069d0a7870f45a3eb0540825d6dc517eda2a525a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 5 Jul 2013 16:20:17 +0200 Subject: [PATCH 2336/2900] ARM: OMAP: omap_common_late_init may be unused Some OMAP SoCs use this function while others do not, and that causes a warning when building multi_v7_defconfig. Marking the function __maybe_unused silences the harmless warning without the need to add complex #ifdef logic. Signed-off-by: Arnd Bergmann Cc: Tony Lindgren --- arch/arm/mach-omap2/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index fe3253a100e7..4a3f06f02859 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -394,7 +394,7 @@ static void __init omap_hwmod_init_postsetup(void) omap_pm_if_early_init(); } -static void __init omap_common_late_init(void) +static void __init __maybe_unused omap_common_late_init(void) { omap_mux_late_init(); omap2_common_pm_late_init(); -- GitLab From 7a6a731bd00ca90d0e250867c3b9c05b5ff0fa49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 21 Nov 2012 09:54:48 +0100 Subject: [PATCH 2337/2900] [SCSI] megaraid_sas: fix memory leak if SGL has zero length entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 98cb7e44 ([SCSI] megaraid_sas: Sanity check user supplied length before passing it to dma_alloc_coherent()) introduced a memory leak. Memory allocated for entries following zero length SGL entries will not be freed. Reference: http://bugs.debian.org/688198 Signed-off-by: Bjørn Mork Cc: Acked-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 6002d363c637..0177295599e0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4958,10 +4958,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, sense, sense_handle); } - for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { - dma_free_coherent(&instance->pdev->dev, - kern_sge32[i].length, - kbuff_arr[i], kern_sge32[i].phys_addr); + for (i = 0; i < ioc->sge_count; i++) { + if (kbuff_arr[i]) + dma_free_coherent(&instance->pdev->dev, + kern_sge32[i].length, + kbuff_arr[i], + kern_sge32[i].phys_addr); } megasas_return_cmd(instance, cmd); -- GitLab From c8a2ba3f50f7445b3d1b822ba1a8168b4234baca Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 27 Jun 2013 15:02:49 +0800 Subject: [PATCH 2338/2900] [SCSI] pm8001: use pdev->pm_cap instead of pci_find_capability(..,PCI_CAP_ID_PM) Pci core has been saved pm cap register offset by pdev->pm_cap in pci_pm_init() in init path. So we can use pdev->pm_cap instead of using pci_find_capability(pdev, PCI_CAP_ID_PM) for better performance and simplified code. Tested-by: Lindar Liu Signed-off-by: Yijing Wang Acked-by: Lindar Liu Signed-off-by: James Bottomley --- drivers/scsi/pm8001/pm8001_init.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e4b9bc7f5410..3861aa1f4520 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -912,14 +912,13 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct pm8001_hba_info *pm8001_ha; - int i , pos; + int i; u32 device_state; pm8001_ha = sha->lldd_ha; flush_workqueue(pm8001_wq); scsi_block_requests(pm8001_ha->shost); - pos = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pos == 0) { - printk(KERN_ERR " PCI PM not supported\n"); + if (!pdev->pm_cap) { + dev_err(&pdev->dev, " PCI PM not supported\n"); return -ENODEV; } PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); -- GitLab From 39f1601c3f840f6e055f7d9726a1a1e9acbefd78 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 5 Jul 2013 16:25:44 +0200 Subject: [PATCH 2339/2900] ARM: ixp4xx: avoid circular header dependency With the new linux/reboot.h header file dependency added, we can no longer build ixp4xx. The easiest way to avoid that is to remove the inclusion of mach/hardware.h from mach/timex.h, which does not need that header anyway. Signed-off-by: Arnd Bergmann Cc: Imre Kaloz Cc: Krzysztof Halasa Cc: Jason Cooper --- arch/arm/mach-ixp4xx/dsmg600-setup.c | 2 ++ arch/arm/mach-ixp4xx/include/mach/timex.h | 2 +- arch/arm/mach-ixp4xx/omixp-setup.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index 5d413f8c5700..63de1b3fd06b 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include diff --git a/arch/arm/mach-ixp4xx/include/mach/timex.h b/arch/arm/mach-ixp4xx/include/mach/timex.h index c9e930f29339..0396d89f947c 100644 --- a/arch/arm/mach-ixp4xx/include/mach/timex.h +++ b/arch/arm/mach-ixp4xx/include/mach/timex.h @@ -3,7 +3,7 @@ * */ -#include +#include /* * We use IXP425 General purpose timer for our timer needs, it runs at diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c index 46a89f5e8269..75ef03dc9964 100644 --- a/arch/arm/mach-ixp4xx/omixp-setup.c +++ b/arch/arm/mach-ixp4xx/omixp-setup.c @@ -27,6 +27,8 @@ #include #include +#include + static struct resource omixp_flash_resources[] = { { .flags = IORESOURCE_MEM, -- GitLab From c1fe55e0b6227093d6faa09ce6932fbcd86aeea2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 17 Jun 2013 09:56:42 +0200 Subject: [PATCH 2340/2900] ARM: exynos: select PM_GENERIC_DOMAINS only when used This fixes building exynos kernels with CONFIG_PM disabled. Signed-off-by: Arnd Bergmann Cc: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 2d503b3684c4..ba70a846d1c6 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -38,7 +38,7 @@ config CPU_EXYNOS4210 depends on ARCH_EXYNOS4 select ARM_CPU_SUSPEND if PM select PINCTRL_EXYNOS - select PM_GENERIC_DOMAINS + select PM_GENERIC_DOMAINS if PM select S5P_PM if PM select S5P_SLEEP if PM select SAMSUNG_DMADEV -- GitLab From 27d7c4ed1f7dfa3fc462e870dc60a4c9c2253f3e Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 5 Jul 2013 21:57:22 -0400 Subject: [PATCH 2341/2900] ext4: silence warning in ext4_writepages() The loop in mpage_map_and_submit_extent() is guaranteed to always run at least once since the caller of mpage_map_and_submit_extent() makes sure map->m_len > 0. So make that explicit using do-while instead of pure while which also silences the compiler warning about uninitialized 'err' variable. Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" Reviewed-by: Lukas Czerner --- fs/ext4/inode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0188e65e1f58..19a1643cbdfa 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2163,7 +2163,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, mpd->io_submit.io_end->offset = ((loff_t)map->m_lblk) << inode->i_blkbits; - while (map->m_len) { + do { err = mpage_map_one_extent(handle, mpd); if (err < 0) { struct super_block *sb = inode->i_sb; @@ -2201,7 +2201,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, err = mpage_map_and_submit_buffers(mpd); if (err < 0) return err; - } + } while (map->m_len); /* Update on-disk size after IO is submitted */ disksize = ((loff_t)mpd->first_page) << PAGE_CACHE_SHIFT; -- GitLab From 960fd856fdc3b08b3638f3f9b6b4bfceb77660c7 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 5 Jul 2013 23:11:16 -0400 Subject: [PATCH 2342/2900] ext4: fix ext4_get_group_number() The function ext4_get_group_number() was introduced as an optimization in commit bd86298e60b8. Unfortunately, this commit incorrectly calculate the group number for file systems with a 1k block size (when s_first_data_block is 1 instead of zero). This could cause the following kernel BUG: [ 568.877799] ------------[ cut here ]------------ [ 568.877833] kernel BUG at fs/ext4/mballoc.c:3728! [ 568.877840] Oops: Exception in kernel mode, sig: 5 [#1] [ 568.877845] SMP NR_CPUS=32 NUMA pSeries [ 568.877852] Modules linked in: binfmt_misc [ 568.877861] CPU: 1 PID: 3516 Comm: fs_mark Not tainted 3.10.0-03216-g7c6809f-dirty #1 [ 568.877867] task: c0000001fb0b8000 ti: c0000001fa954000 task.ti: c0000001fa954000 [ 568.877873] NIP: c0000000002f42a4 LR: c0000000002f4274 CTR: c000000000317ef8 [ 568.877879] REGS: c0000001fa956ed0 TRAP: 0700 Not tainted (3.10.0-03216-g7c6809f-dirty) [ 568.877884] MSR: 8000000000029032 CR: 24000428 XER: 00000000 [ 568.877902] SOFTE: 1 [ 568.877905] CFAR: c0000000002b5464 [ 568.877908] GPR00: 0000000000000001 c0000001fa957150 c000000000c6a408 c0000001fb588000 GPR04: 0000000000003fff c0000001fa9571c0 c0000001fa9571c4 000138098c50625f GPR08: 1301200000000000 0000000000000002 0000000000000001 0000000000000000 GPR12: 0000000024000422 c00000000f33a300 0000000000008000 c0000001fa9577f0 GPR16: c0000001fb7d0100 c000000000c29190 c0000000007f46e8 c000000000a14672 GPR20: 0000000000000001 0000000000000008 ffffffffffffffff 0000000000000000 GPR24: 0000000000000100 c0000001fa957278 c0000001fdb2bc78 c0000001fa957288 GPR28: 0000000000100100 c0000001fa957288 c0000001fb588000 c0000001fdb2bd10 [ 568.877993] NIP [c0000000002f42a4] .ext4_mb_release_group_pa+0xec/0x1c0 [ 568.877999] LR [c0000000002f4274] .ext4_mb_release_group_pa+0xbc/0x1c0 [ 568.878004] Call Trace: [ 568.878008] [c0000001fa957150] [c0000000002f4274] .ext4_mb_release_group_pa+0xbc/0x1c0 (unreliable) [ 568.878017] [c0000001fa957200] [c0000000002fb070] .ext4_mb_discard_lg_preallocations+0x394/0x444 [ 568.878025] [c0000001fa957340] [c0000000002fb45c] .ext4_mb_release_context+0x33c/0x734 [ 568.878032] [c0000001fa957440] [c0000000002fbcf8] .ext4_mb_new_blocks+0x4a4/0x5f4 [ 568.878039] [c0000001fa957510] [c0000000002ef56c] .ext4_ext_map_blocks+0xc28/0x1178 [ 568.878047] [c0000001fa957640] [c0000000002c1a94] .ext4_map_blocks+0x2c8/0x490 [ 568.878054] [c0000001fa957730] [c0000000002c536c] .ext4_writepages+0x738/0xc60 [ 568.878062] [c0000001fa957950] [c000000000168a78] .do_writepages+0x5c/0x80 [ 568.878069] [c0000001fa9579d0] [c00000000015d1c4] .__filemap_fdatawrite_range+0x88/0xb0 [ 568.878078] [c0000001fa957aa0] [c00000000015d23c] .filemap_write_and_wait_range+0x50/0xfc [ 568.878085] [c0000001fa957b30] [c0000000002b8edc] .ext4_sync_file+0x220/0x3c4 [ 568.878092] [c0000001fa957be0] [c0000000001f849c] .vfs_fsync_range+0x64/0x80 [ 568.878098] [c0000001fa957c70] [c0000000001f84f0] .vfs_fsync+0x38/0x4c [ 568.878105] [c0000001fa957d00] [c0000000001f87f4] .do_fsync+0x54/0x90 [ 568.878111] [c0000001fa957db0] [c0000000001f8894] .SyS_fsync+0x28/0x3c [ 568.878120] [c0000001fa957e30] [c000000000009c88] syscall_exit+0x0/0x7c [ 568.878125] Instruction dump: [ 568.878130] 60000000 813d0034 81610070 38000000 7f8b4800 419e001c 813f007c 7d2bfe70 [ 568.878144] 7d604a78 7c005850 54000ffe 7c0007b4 <0b000000> e8a10076 e87f0090 7fa4eb78 [ 568.878160] ---[ end trace 594d911d9654770b ]--- In addition fix the STD_GROUP optimization so that it works for bigalloc file systems as well. Signed-off-by: "Theodore Ts'o" Reported-by: Li Zhong Reviewed-by: Lukas Czerner Cc: stable@vger.kernel.org # 3.10 --- fs/ext4/balloc.c | 4 ++-- fs/ext4/super.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 58339393fa6e..ddd715e42a5c 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb, ext4_group_t group; if (test_opt2(sb, STD_GROUP_SIZE)) - group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + - block) >> + group = (block - + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) >> (EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3); else ext4_get_group_no_and_offset(sb, block, &group, NULL); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 85b3dd60169b..8862d4ddf71f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3624,10 +3624,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb)); sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb)); - /* Do we have standard group size of blocksize * 8 blocks ? */ - if (sbi->s_blocks_per_group == blocksize << 3) - set_opt2(sb, STD_GROUP_SIZE); - for (i = 0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]); sbi->s_def_hash_version = es->s_def_hash_version; @@ -3697,6 +3693,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } + /* Do we have standard group size of clustersize * 8 blocks ? */ + if (sbi->s_blocks_per_group == clustersize << 3) + set_opt2(sb, STD_GROUP_SIZE); + /* * Test whether we have more sectors than will fit in sector_t, * and whether the max offset is addressable by the page cache. -- GitLab From 2a961d0995cdadbfba565b28beada59c5ae7ebae Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 3 Jul 2013 22:25:00 +0100 Subject: [PATCH 2343/2900] iio: mxs-lradc: Remove useless check in read_raw The removed check in the read_raw implementation was always true, therefore remove it. This also fixes a bug, by closely inspecting the code, one can notice the iio_validate_scan_mask_onehot() will always return 1 and therefore the subsequent condition will always succeed, therefore making the mxs_lradc_read_raw() function always return -EINVAL; . Signed-off-by: Marek Vasut Tested-by: Otavio Salvador Acked-by: Hector Palacios Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/mxs-lradc.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index c5edf1cad07a..9f52a2857929 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -234,7 +234,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, { struct mxs_lradc *lradc = iio_priv(iio_dev); int ret; - unsigned long mask; if (m != IIO_CHAN_INFO_RAW) return -EINVAL; @@ -243,12 +242,6 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev, if (chan->channel > LRADC_MAX_TOTAL_CHANS) return -EINVAL; - /* Validate the channel if it doesn't intersect with reserved chans. */ - bitmap_set(&mask, chan->channel, 1); - ret = iio_validate_scan_mask_onehot(iio_dev, &mask); - if (ret) - return -EINVAL; - /* * See if there is no buffered operation in progess. If there is, simply * bail out. This can be improved to support both buffered and raw IO at -- GitLab From bc93aa7640fe97df8d69b50fdce70da1126e12b3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 6 Jul 2013 05:20:00 +0100 Subject: [PATCH 2344/2900] iio: ti_am335x_adc: add missing .driver_module to struct iio_info Add missing .driver_module of struct iio_info. This prevents the module from being removed from underneath its users. Signed-off-by: Wei Yongjun Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 5f9a7e7d3135..985f58873d03 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -134,6 +134,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, static const struct iio_info tiadc_info = { .read_raw = &tiadc_read_raw, + .driver_module = THIS_MODULE, }; static int tiadc_probe(struct platform_device *pdev) -- GitLab From bb3779610254ea5efbf8ec727138e041d801747c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 4 Jul 2013 14:46:00 +0100 Subject: [PATCH 2345/2900] staging:iio:ad7291: add missing .driver_module to struct iio_info Add missing .driver_module of struct iio_info. This prevents the module from being removed from underneath its users. Signed-off-by: Wei Yongjun Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7291.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c index 3fc79e582750..a2e61c2fc8d1 100644 --- a/drivers/staging/iio/adc/ad7291.c +++ b/drivers/staging/iio/adc/ad7291.c @@ -517,6 +517,7 @@ static const struct iio_info ad7291_info = { .read_event_value = &ad7291_read_event_value, .write_event_value = &ad7291_write_event_value, .event_attrs = &ad7291_event_attribute_group, + .driver_module = THIS_MODULE, }; static int ad7291_probe(struct i2c_client *client, -- GitLab From c7e8e8a8f7a70b343ca1e0f90a31e35ab2d16de1 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Fri, 5 Jul 2013 19:36:17 +0800 Subject: [PATCH 2346/2900] bridge: fix some kernel warning in multicast timer Several people reported the warning: "kernel BUG at kernel/timer.c:729!" and the stack trace is: #7 [ffff880214d25c10] mod_timer+501 at ffffffff8106d905 #8 [ffff880214d25c50] br_multicast_del_pg.isra.20+261 at ffffffffa0731d25 [bridge] #9 [ffff880214d25c80] br_multicast_disable_port+88 at ffffffffa0732948 [bridge] #10 [ffff880214d25cb0] br_stp_disable_port+154 at ffffffffa072bcca [bridge] #11 [ffff880214d25ce8] br_device_event+520 at ffffffffa072a4e8 [bridge] #12 [ffff880214d25d18] notifier_call_chain+76 at ffffffff8164aafc #13 [ffff880214d25d50] raw_notifier_call_chain+22 at ffffffff810858f6 #14 [ffff880214d25d60] call_netdevice_notifiers+45 at ffffffff81536aad #15 [ffff880214d25d80] dev_close_many+183 at ffffffff81536d17 #16 [ffff880214d25dc0] rollback_registered_many+168 at ffffffff81537f68 #17 [ffff880214d25de8] rollback_registered+49 at ffffffff81538101 #18 [ffff880214d25e10] unregister_netdevice_queue+72 at ffffffff815390d8 #19 [ffff880214d25e30] __tun_detach+272 at ffffffffa074c2f0 [tun] #20 [ffff880214d25e88] tun_chr_close+45 at ffffffffa074c4bd [tun] #21 [ffff880214d25ea8] __fput+225 at ffffffff8119b1f1 #22 [ffff880214d25ef0] ____fput+14 at ffffffff8119b3fe #23 [ffff880214d25f00] task_work_run+159 at ffffffff8107cf7f #24 [ffff880214d25f30] do_notify_resume+97 at ffffffff810139e1 #25 [ffff880214d25f50] int_signal+18 at ffffffff8164f292 this is due to I forgot to check if mp->timer is armed in br_multicast_del_pg(). This bug is introduced by commit 9f00b2e7cf241fa389733d41b6 (bridge: only expire the mdb entry when query is received). Same for __br_mdb_del(). Tested-by: poma Reported-by: LiYonghua <809674045@qq.com> Reported-by: Robert Hancock Cc: Herbert Xu Cc: Stephen Hemminger Cc: "David S. Miller" Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/bridge/br_mdb.c | 2 +- net/bridge/br_multicast.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 19942e38fd2d..0daae3ec2355 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -447,7 +447,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) call_rcu_bh(&p->rcu, br_multicast_free_pg); err = 0; - if (!mp->ports && !mp->mglist && + if (!mp->ports && !mp->mglist && mp->timer_armed && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); break; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 81befac015e1..69af490cce44 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -270,7 +270,7 @@ static void br_multicast_del_pg(struct net_bridge *br, del_timer(&p->timer); call_rcu_bh(&p->rcu, br_multicast_free_pg); - if (!mp->ports && !mp->mglist && + if (!mp->ports && !mp->mglist && mp->timer_armed && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); -- GitLab From 62f548d0c2d2418e39b8e4b7ec39b5ca2ef4380d Mon Sep 17 00:00:00 2001 From: Ferruh Yigit Date: Thu, 4 Jul 2013 14:02:57 -0700 Subject: [PATCH 2347/2900] Input: cyttsp4 - use 16bit address for I2C/SPI communication In TSG4, register map is 512bytes long and to access all of it, one bit from address byte is used (which bit to use differs for I2C and SPI); Since common code used for TSG3 and TSG4 for I2C, this parameter wrongly used as u8. TSG3 does not access beyond 255 bytes but TSG4 may. Tested-on:TMA3XX DVB && TMA4XX DVB Signed-off-by: Ferruh Yigit Acked-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp4_core.h | 12 ++++---- drivers/input/touchscreen/cyttsp4_spi.c | 20 ++++++------- drivers/input/touchscreen/cyttsp_core.h | 8 ++--- drivers/input/touchscreen/cyttsp_i2c_common.c | 30 ++++++++++++++----- drivers/input/touchscreen/cyttsp_spi.c | 6 ++-- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h index 86a254354136..8e0d4d490b20 100644 --- a/drivers/input/touchscreen/cyttsp4_core.h +++ b/drivers/input/touchscreen/cyttsp4_core.h @@ -369,9 +369,9 @@ struct cyttsp4 { struct cyttsp4_bus_ops { u16 bustype; - int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, + int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); - int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, + int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values); }; @@ -448,13 +448,13 @@ enum cyttsp4_event_id { /* y-axis, 0:origin is on top side of panel, 1: bottom */ #define CY_PCFG_ORIGIN_Y_MASK 0x80 -static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u8 addr, int size, +static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size, void *buf) { return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf); } -static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size, +static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size, const void *buf) { return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf); @@ -463,9 +463,9 @@ static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u8 addr, int size, extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, struct device *dev, u16 irq, size_t xfer_buf_size); extern int cyttsp4_remove(struct cyttsp4 *ts); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr, +int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr, +int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values); extern const struct dev_pm_ops cyttsp4_pm_ops; diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c index f8f891bead34..a71e1141d638 100644 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ b/drivers/input/touchscreen/cyttsp4_spi.c @@ -44,7 +44,7 @@ #define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, - u8 op, u8 reg, u8 *buf, int length) + u8 op, u16 reg, u8 *buf, int length) { struct spi_device *spi = to_spi_device(dev); struct spi_message msg; @@ -63,14 +63,12 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); memset(rd_buf, 0, CY_SPI_CMD_BYTES); - if (reg > 255) - wr_buf[0] = op + CY_SPI_A8_BIT; - else - wr_buf[0] = op; - if (op == CY_SPI_WR_OP) - wr_buf[1] = reg % 256; - if (op == CY_SPI_WR_OP && length > 0) - memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); + wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); + if (op == CY_SPI_WR_OP) { + wr_buf[1] = reg & 0xFF; + if (length > 0) + memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); + } memset(xfer, 0, sizeof(xfer)); spi_message_init(&msg); @@ -130,7 +128,7 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, } static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, void *data) + u16 addr, u8 length, void *data) { int rc; @@ -143,7 +141,7 @@ static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, } static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, const void *data) + u16 addr, u8 length, const void *data) { return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, length); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 0cf564a79fb5..07074110a902 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -112,9 +112,9 @@ struct cyttsp; struct cyttsp_bus_ops { u16 bustype; - int (*write)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, + int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); - int (*read)(struct device *dev, u8 *xfer_buf, u8 addr, u8 length, + int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values); }; @@ -145,9 +145,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); void cyttsp_remove(struct cyttsp *ts); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u8 addr, +int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u8 addr, +int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, void *values); extern const struct dev_pm_ops cyttsp_pm_ops; diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c index 07c553fbcef2..1d7b6f154168 100644 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ b/drivers/input/touchscreen/cyttsp_i2c_common.c @@ -32,18 +32,20 @@ #include int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, void *values) + u16 addr, u8 length, void *values) { struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; struct i2c_msg msgs[] = { { - .addr = client->addr, + .addr = client_addr, .flags = 0, .len = 1, - .buf = &addr, + .buf = &addr_lo, }, { - .addr = client->addr, + .addr = client_addr, .flags = I2C_M_RD, .len = length, .buf = values, @@ -60,17 +62,29 @@ int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data); int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, const void *values) + u16 addr, u8 length, const void *values) { struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = length + 1, + .buf = xfer_buf, + }, + }; int retval; - xfer_buf[0] = addr; + xfer_buf[0] = addr_lo; memcpy(&xfer_buf[1], values, length); - retval = i2c_master_send(client, xfer_buf, length + 1); + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; - return retval < 0 ? retval : 0; + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; } EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 1df625337b84..4728bcb1916c 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -41,7 +41,7 @@ #define CY_SPI_BITS_PER_WORD 8 static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, - u8 op, u8 reg, u8 *buf, int length) + u8 op, u16 reg, u8 *buf, int length) { struct spi_device *spi = to_spi_device(dev); struct spi_message msg; @@ -126,14 +126,14 @@ static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, } static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, void *data) + u16 addr, u8 length, void *data) { return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, length); } static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, - u8 addr, u8 length, const void *data) + u16 addr, u8 length, const void *data) { return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, length); -- GitLab From 9eebed7de660c0b5ab129a9de4f89d20b60de68c Mon Sep 17 00:00:00 2001 From: Matteo Delfino Date: Sat, 6 Jul 2013 21:52:26 -0700 Subject: [PATCH 2348/2900] Input: elantech - fix for newer hardware versions (v7) * Fix version recognition in elantech_set_properties The new hardware reports itself as v7 but the packets' structure is unaltered. * Fix packet type recognition in elantech_packet_check_v4 The bitmask used for v6 is too wide, only the last three bits of the third byte in a packet (packet[3] & 0x03) are actually used to distinguish between packet types. Starting from v7, additional information (to be interpreted) is stored in the remaining bits (packets[3] & 0x1c). In addition, the value stored in (packet[0] & 0x0c) is no longer a constant but contains additional information yet to be deciphered. This change should be backwards compatible with v6 hardware. Additional-author: Giovanni Frigione Signed-off-by: Matteo Delfino Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elantech.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 1e8e42fb03a4..57b2637e153a 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -694,18 +694,18 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) static int elantech_packet_check_v4(struct psmouse *psmouse) { unsigned char *packet = psmouse->packet; + unsigned char packet_type = packet[3] & 0x03; - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x11) + switch (packet_type) { + case 0: + return PACKET_V4_STATUS; + + case 1: return PACKET_V4_HEAD; - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x12) + case 2: return PACKET_V4_MOTION; - - if ((packet[0] & 0x0c) == 0x04 && - (packet[3] & 0x1f) == 0x10) - return PACKET_V4_STATUS; + } return PACKET_UNKNOWN; } @@ -1282,6 +1282,7 @@ static int elantech_set_properties(struct elantech_data *etd) etd->hw_version = 3; break; case 6: + case 7: etd->hw_version = 4; break; default: -- GitLab From 46146e7d4b383d5b34014d072553498c7cd52821 Mon Sep 17 00:00:00 2001 From: Daniel Tang Date: Sat, 6 Jul 2013 21:53:26 -0700 Subject: [PATCH 2349/2900] Input: nspire-keypad - replace magic offset with define Signed-off-by: Daniel Tang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/nspire-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index e0a1339e40e6..20d872d6f603 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -122,7 +122,7 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad) /* Enable interrupts */ keypad->int_mask = 1 << 1; - writel(keypad->int_mask, keypad->reg_base + 0xc); + writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK); /* Disable GPIO interrupts to prevent hanging on touchpad */ /* Possibly used to detect touchpad events */ -- GitLab From 3df8f68aaf7ebe3d136a22262b41b350b0a1858b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 26 Jun 2013 02:31:42 -0700 Subject: [PATCH 2350/2900] iser-target: Fix isert_put_reject payload buffer post This patch adds the missing isert_put_reject() logic to post a outgoing payload buffer to hold the 48 bytes of original PDU header request payload for the rejected cmd. It also fixes ISTATE_SEND_REJECT handling in isert_response_completion() -> isert_do_control_comp() code, and drops incorrect iscsi_cmd_t->reject_comp usage. Cc: Or Gerlitz Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 26 +++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index c48c9481025c..1b38eff7f340 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1243,6 +1243,9 @@ isert_put_cmd(struct isert_cmd *isert_cmd) * associated cmd->se_cmd needs to be released. */ if (cmd->se_cmd.se_tfo != NULL) { + pr_debug("Calling transport_generic_free_cmd from" + " isert_put_cmd for 0x%02x\n", + cmd->iscsi_opcode); transport_generic_free_cmd(&cmd->se_cmd, 0); break; } @@ -1339,8 +1342,8 @@ isert_do_control_comp(struct work_struct *work) atomic_dec(&isert_conn->post_send_buf_count); cmd->i_state = ISTATE_SENT_STATUS; - complete(&cmd->reject_comp); isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); + break; case ISTATE_SEND_LOGOUTRSP: pr_debug("Calling iscsit_logout_post_handler >>>>>>>>>>>>>>\n"); /* @@ -1366,7 +1369,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc, struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || - cmd->i_state == ISTATE_SEND_LOGOUTRSP) { + cmd->i_state == ISTATE_SEND_LOGOUTRSP || + cmd->i_state == ISTATE_SEND_REJECT) { isert_unmap_tx_desc(tx_desc, ib_dev); INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); @@ -1658,11 +1662,25 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) struct isert_cmd, iscsi_cmd); struct isert_conn *isert_conn = (struct isert_conn *)conn->context; struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; + struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; + struct iscsi_reject *hdr = + (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header; isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); - iscsit_build_reject(cmd, conn, (struct iscsi_reject *) - &isert_cmd->tx_desc.iscsi_header); + iscsit_build_reject(cmd, conn, hdr); isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); + + hton24(hdr->dlength, ISCSI_HDR_LEN); + isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev, + (void *)cmd->buf_ptr, ISCSI_HDR_LEN, + DMA_TO_DEVICE); + isert_cmd->sense_buf_len = ISCSI_HDR_LEN; + tx_dsg->addr = isert_cmd->sense_buf_dma; + tx_dsg->length = ISCSI_HDR_LEN; + tx_dsg->lkey = isert_conn->conn_mr->lkey; + isert_cmd->tx_desc.num_sge = 2; + isert_init_send_wr(isert_cmd, send_wr); pr_debug("Posting Reject IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); -- GitLab From ba159914086f06532079fc15141f46ffe7e04a41 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Jul 2013 03:48:24 -0700 Subject: [PATCH 2351/2900] iscsi-target: Fix iscsit_add_reject* usage for iser This patch changes iscsit_add_reject() + iscsit_add_reject_from_cmd() usage to not sleep on iscsi_cmd->reject_comp to address a free-after-use usage bug in v3.10 with iser-target code. It saves ->reject_reason for use within iscsit_build_reject() so the correct value for both transport cases. It also drops the legacy fail_conn parameter usage throughput iscsi-target code and adds two iscsit_add_reject_cmd() and iscsit_reject_cmd helper functions, along with various small cleanups. (v2: Re-enable target_put_sess_cmd() to be called from iscsit_add_reject_from_cmd() for rejects invoked after target_get_sess_cmd() has been called) Cc: Or Gerlitz Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 5 - drivers/target/iscsi/iscsi_target.c | 255 +++++++++-------------- drivers/target/iscsi/iscsi_target.h | 2 +- drivers/target/iscsi/iscsi_target_core.h | 8 +- drivers/target/iscsi/iscsi_target_erl0.c | 7 +- drivers/target/iscsi/iscsi_target_erl1.c | 20 +- drivers/target/iscsi/iscsi_target_util.c | 1 - include/target/iscsi/iscsi_transport.h | 2 - 8 files changed, 120 insertions(+), 180 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 1b38eff7f340..134ff58c6b17 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -939,11 +939,6 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, if (!rc && dump_payload == false && unsol_data) iscsit_set_unsoliticed_dataout(cmd); - if (rc == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); - return 0; } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 19a31f9bb7d5..2a25bd3b065c 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_module(void) } static int iscsit_add_reject( + struct iscsi_conn *conn, u8 reason, - int fail_conn, - unsigned char *buf, - struct iscsi_conn *conn) + unsigned char *buf) { struct iscsi_cmd *cmd; - struct iscsi_reject *hdr; - int ret; cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) return -1; cmd->iscsi_opcode = ISCSI_OP_REJECT; - if (fail_conn) - cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; - - hdr = (struct iscsi_reject *) cmd->pdu; - hdr->reason = reason; + cmd->reject_reason = reason; cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); if (!cmd->buf_ptr) { @@ -662,23 +655,16 @@ static int iscsit_add_reject( cmd->i_state = ISTATE_SEND_REJECT; iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); - ret = wait_for_completion_interruptible(&cmd->reject_comp); - if (ret != 0) - return -1; - - return (!fail_conn) ? 0 : -1; + return -1; } -int iscsit_add_reject_from_cmd( +static int iscsit_add_reject_from_cmd( + struct iscsi_cmd *cmd, u8 reason, - int fail_conn, - int add_to_conn, - unsigned char *buf, - struct iscsi_cmd *cmd) + bool add_to_conn, + unsigned char *buf) { struct iscsi_conn *conn; - struct iscsi_reject *hdr; - int ret; if (!cmd->conn) { pr_err("cmd->conn is NULL for ITT: 0x%08x\n", @@ -688,11 +674,7 @@ int iscsit_add_reject_from_cmd( conn = cmd->conn; cmd->iscsi_opcode = ISCSI_OP_REJECT; - if (fail_conn) - cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; - - hdr = (struct iscsi_reject *) cmd->pdu; - hdr->reason = reason; + cmd->reject_reason = reason; cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); if (!cmd->buf_ptr) { @@ -709,8 +691,6 @@ int iscsit_add_reject_from_cmd( cmd->i_state = ISTATE_SEND_REJECT; iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); - - ret = wait_for_completion_interruptible(&cmd->reject_comp); /* * Perform the kref_put now if se_cmd has already been setup by * scsit_setup_scsi_cmd() @@ -719,12 +699,19 @@ int iscsit_add_reject_from_cmd( pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); } - if (ret != 0) - return -1; + return -1; +} - return (!fail_conn) ? 0 : -1; +static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason, + unsigned char *buf) +{ + return iscsit_add_reject_from_cmd(cmd, reason, true, buf); +} + +int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf) +{ + return iscsit_add_reject_from_cmd(cmd, reason, false, buf); } -EXPORT_SYMBOL(iscsit_add_reject_from_cmd); /* * Map some portion of the allocated scatterlist to an iovec, suitable for @@ -844,8 +831,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" " not set. Bad iSCSI Initiator.\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } if (((hdr->flags & ISCSI_FLAG_CMD_READ) || @@ -865,8 +852,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" " set when Expected Data Transfer Length is 0 for" " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } done: @@ -875,62 +862,62 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" " MUST be set if Expected Data Transfer Length is not 0." " Bad iSCSI Initiator\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } if ((hdr->flags & ISCSI_FLAG_CMD_READ) && (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { pr_err("Bidirectional operations not supported!\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } if (hdr->opcode & ISCSI_OP_IMMEDIATE) { pr_err("Illegally set Immediate Bit in iSCSI Initiator" " Scsi Command PDU.\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } if (payload_length && !conn->sess->sess_ops->ImmediateData) { pr_err("ImmediateData=No but DataSegmentLength=%u," " protocol error.\n", payload_length); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } - if ((be32_to_cpu(hdr->data_length )== payload_length) && + if ((be32_to_cpu(hdr->data_length) == payload_length) && (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) { pr_err("Expected Data Transfer Length and Length of" " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" " bit is not set protocol error\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } if (payload_length > be32_to_cpu(hdr->data_length)) { pr_err("DataSegmentLength: %u is greater than" " EDTL: %u, protocol error.\n", payload_length, hdr->data_length); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { pr_err("DataSegmentLength: %u is greater than" " MaxXmitDataSegmentLength: %u, protocol error.\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } if (payload_length > conn->sess->sess_ops->FirstBurstLength) { pr_err("DataSegmentLength: %u is greater than" " FirstBurstLength: %u, protocol error.\n", payload_length, conn->sess->sess_ops->FirstBurstLength); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : @@ -985,9 +972,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, dr = iscsit_allocate_datain_req(); if (!dr) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); iscsit_attach_datain_req(cmd, dr); } @@ -1015,18 +1001,16 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); if (cmd->sense_reason) { if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } goto attach_cmd; } if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } attach_cmd: @@ -1075,10 +1059,6 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); return 0; - } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); } } @@ -1149,11 +1129,6 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, } else if (cmd->unsolicited_data) iscsit_set_unsoliticed_dataout(cmd); - if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); - } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { /* * Immediate Data failed DataCRC and ERL>=1, @@ -1190,9 +1165,8 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * traditional iSCSI block I/O. */ if (iscsit_allocate_iovecs(cmd) < 0) { - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 0, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } immed_data = cmd->immediate_data; @@ -1282,8 +1256,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, if (!payload_length) { pr_err("DataOUT payload is ZERO, protocol error.\n"); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buf); } /* iSCSI write */ @@ -1300,8 +1274,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, pr_err("DataSegmentLength: %u is greater than" " MaxXmitDataSegmentLength: %u\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buf); } cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, @@ -1324,8 +1298,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, if (cmd->data_direction != DMA_TO_DEVICE) { pr_err("Command ITT: 0x%08x received DataOUT for a" " NON-WRITE command.\n", cmd->init_task_tag); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); } se_cmd = &cmd->se_cmd; iscsit_mod_dataout_timer(cmd); @@ -1334,8 +1307,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, pr_err("DataOut Offset: %u, Length %u greater than" " iSCSI Command EDTL %u, protocol error.\n", hdr->offset, payload_length, cmd->se_cmd.data_length); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf); } if (cmd->unsolicited_data) { @@ -1543,8 +1515,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { pr_err("NOPOUT ITT is reserved, but Immediate Bit is" " not set, protocol error.\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); } if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { @@ -1552,8 +1524,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, " greater than MaxXmitDataSegmentLength: %u, protocol" " error.\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); } pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," @@ -1612,9 +1584,7 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, return 0; if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + return -1; return 0; } @@ -1780,8 +1750,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, pr_err("Task Management Request TASK_REASSIGN not" " issued as immediate command, bad iSCSI Initiator" "implementation\n"); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } if ((function != ISCSI_TM_FUNC_ABORT_TASK) && be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) @@ -1793,9 +1763,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (!cmd->tmr_req) { pr_err("Unable to allocate memory for" " Task Management command!\n"); - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, + buf); } /* @@ -1837,17 +1807,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, default: pr_err("Unknown iSCSI TMR Function:" " 0x%02x\n", function); - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, tcm_function, GFP_KERNEL); if (ret < 0) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req; } @@ -1906,9 +1874,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, break; if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_INVALID, 1, 1, - buf, cmd); + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); break; default: pr_err("Unknown TMR function: 0x%02x, protocol" @@ -1932,9 +1899,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) return 0; else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); + return -1; } iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); @@ -1970,8 +1935,8 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, pr_err("Unable to accept text parameter length: %u" "greater than MaxXmitDataSegmentLength %u.\n", payload_length, conn->conn_ops->MaxXmitDataSegmentLength); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); } pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," @@ -2033,17 +1998,16 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + return -1; + return 0; } return iscsit_execute_cmd(cmd, 0); reject: - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 0, 0, (unsigned char *)hdr, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, + (unsigned char *)hdr); } EXPORT_SYMBOL(iscsit_process_text_cmd); @@ -2139,8 +2103,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, reject: kfree(cmd->text_in_ptr); cmd->text_in_ptr = NULL; - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 0, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); } EXPORT_SYMBOL(iscsit_handle_text_cmd); @@ -2322,13 +2285,10 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, return ret; } else { cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); - if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { + if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) logout_remove = 0; - } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); - } + else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + return -1; } return logout_remove; @@ -2352,8 +2312,8 @@ static int iscsit_handle_snack( if (!conn->sess->sess_ops->ErrorRecoveryLevel) { pr_err("Initiator sent SNACK request while in" " ErrorRecoveryLevel=0.\n"); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buf); } /* * SNACK_DATA and SNACK_R2T are both 0, so check which function to @@ -2377,13 +2337,13 @@ static int iscsit_handle_snack( case ISCSI_FLAG_SNACK_TYPE_RDATA: /* FIXME: Support R-Data SNACK */ pr_err("R-Data SNACK Not Supported.\n"); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buf); default: pr_err("Unknown SNACK type 0x%02x, protocol" " error.\n", hdr->flags & 0x0f); - return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buf, conn); + return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buf); } return 0; @@ -2455,14 +2415,14 @@ static int iscsit_handle_immediate_data( pr_err("Unable to recover from" " Immediate Data digest failure while" " in ERL=0.\n"); - iscsit_add_reject_from_cmd( + iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, - 1, 0, (unsigned char *)hdr, cmd); + (unsigned char *)hdr); return IMMEDIATE_DATA_CANNOT_RECOVER; } else { - iscsit_add_reject_from_cmd( + iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, - 0, 0, (unsigned char *)hdr, cmd); + (unsigned char *)hdr); return IMMEDIATE_DATA_ERL1_CRC_FAILURE; } } else { @@ -3595,6 +3555,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn, struct iscsi_reject *hdr) { hdr->opcode = ISCSI_OP_REJECT; + hdr->reason = cmd->reject_reason; hdr->flags |= ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, ISCSI_HDR_LEN); hdr->ffffffff = cpu_to_be32(0xffffffff); @@ -3868,18 +3829,11 @@ iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) case ISTATE_SEND_STATUS_RECOVERY: case ISTATE_SEND_TEXTRSP: case ISTATE_SEND_TASKMGTRSP: + case ISTATE_SEND_REJECT: spin_lock_bh(&cmd->istate_lock); cmd->i_state = ISTATE_SENT_STATUS; spin_unlock_bh(&cmd->istate_lock); break; - case ISTATE_SEND_REJECT: - if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) { - cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN; - complete(&cmd->reject_comp); - goto err; - } - complete(&cmd->reject_comp); - break; default: pr_err("Unknown Opcode: 0x%02x ITT:" " 0x%08x, i_state: %d on CID: %hu\n", @@ -3984,8 +3938,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) case ISCSI_OP_SCSI_CMD: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); + goto reject; ret = iscsit_handle_scsi_cmd(conn, cmd, buf); break; @@ -3997,32 +3950,28 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); + goto reject; } ret = iscsit_handle_nop_out(conn, cmd, buf); break; case ISCSI_OP_SCSI_TMFUNC: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); + goto reject; ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); break; case ISCSI_OP_TEXT: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); + goto reject; ret = iscsit_handle_text_cmd(conn, cmd, buf); break; case ISCSI_OP_LOGOUT: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); if (!cmd) - return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, buf, conn); + goto reject; ret = iscsit_handle_logout_cmd(conn, cmd, buf); if (ret > 0) @@ -4054,6 +4003,8 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) } return ret; +reject: + return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); } int iscsi_target_rx_thread(void *arg) @@ -4148,8 +4099,8 @@ int iscsi_target_rx_thread(void *arg) (!(opcode & ISCSI_OP_LOGOUT)))) { pr_err("Received illegal iSCSI Opcode: 0x%02x" " while in Discovery Session, rejecting.\n", opcode); - iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, - buffer, conn); + iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, + buffer); goto transport_err; } diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index a0050b2f294e..2c437cb8ca00 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h @@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *, extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *, struct iscsi_portal_group *); extern int iscsit_del_np(struct iscsi_np *); -extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *); +extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *); extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *); extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index caa0ad9a778b..4f77a78edef9 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -132,9 +132,8 @@ enum cmd_flags_table { ICF_CONTIG_MEMORY = 0x00000020, ICF_ATTACHED_TO_RQUEUE = 0x00000040, ICF_OOO_CMDSN = 0x00000080, - ICF_REJECT_FAIL_CONN = 0x00000100, - IFC_SENDTARGETS_ALL = 0x00000200, - IFC_SENDTARGETS_SINGLE = 0x00000400, + IFC_SENDTARGETS_ALL = 0x00000100, + IFC_SENDTARGETS_SINGLE = 0x00000200, }; /* struct iscsi_cmd->i_state */ @@ -368,6 +367,8 @@ struct iscsi_cmd { u8 maxcmdsn_inc; /* Immediate Unsolicited Dataout */ u8 unsolicited_data; + /* Reject reason code */ + u8 reject_reason; /* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */ u16 logout_cid; /* Command flags */ @@ -450,7 +451,6 @@ struct iscsi_cmd { struct list_head datain_list; /* R2T List */ struct list_head cmd_r2t_list; - struct completion reject_comp; /* Timer for DataOUT */ struct timer_list dataout_timer; /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 8e6298cc8839..8f074e0b6099 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -746,13 +746,12 @@ int iscsit_check_post_dataout( if (!conn->sess->sess_ops->ErrorRecoveryLevel) { pr_err("Unable to recover from DataOUT CRC" " failure while ERL=0, closing session.\n"); - iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, - 1, 0, buf, cmd); + iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, + buf); return DATAOUT_CANNOT_RECOVER; } - iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, - 0, 0, buf, cmd); + iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf); return iscsit_dataout_post_crc_failed(cmd, buf); } } diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 40d9dbca987b..d00f1326f0c8 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -162,9 +162,8 @@ static int iscsit_handle_r2t_snack( " protocol error.\n", cmd->init_task_tag, begrun, (begrun + runlength), cmd->acked_data_sn); - return iscsit_add_reject_from_cmd( - ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, + ISCSI_REASON_PROTOCOL_ERROR, buf); } if (runlength) { @@ -173,8 +172,8 @@ static int iscsit_handle_r2t_snack( " with BegRun: 0x%08x, RunLength: 0x%08x, exceeds" " current R2TSN: 0x%08x, protocol error.\n", cmd->init_task_tag, begrun, runlength, cmd->r2t_sn); - return iscsit_add_reject_from_cmd( - ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, + ISCSI_REASON_BOOKMARK_INVALID, buf); } last_r2tsn = (begrun + runlength); } else @@ -433,8 +432,7 @@ static int iscsit_handle_recovery_datain( " protocol error.\n", cmd->init_task_tag, begrun, (begrun + runlength), cmd->acked_data_sn); - return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); } /* @@ -445,14 +443,14 @@ static int iscsit_handle_recovery_datain( pr_err("Initiator requesting BegRun: 0x%08x, RunLength" ": 0x%08x greater than maximum DataSN: 0x%08x.\n", begrun, runlength, (cmd->data_sn - 1)); - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, + buf); } dr = iscsit_allocate_datain_req(); if (!dr) - return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 0, buf, cmd); + return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, + buf); dr->data_sn = dr->begrun = begrun; dr->runlength = runlength; diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index fe712d6cc478..96ce6f2ec428 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) INIT_LIST_HEAD(&cmd->i_conn_node); INIT_LIST_HEAD(&cmd->datain_list); INIT_LIST_HEAD(&cmd->cmd_r2t_list); - init_completion(&cmd->reject_comp); spin_lock_init(&cmd->datain_lock); spin_lock_init(&cmd->dataout_timeout_lock); spin_lock_init(&cmd->istate_lock); diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ce991ba9e887..19a43ad977c2 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -34,8 +34,6 @@ extern void iscsit_put_transport(struct iscsit_transport *); /* * From iscsi_target.c */ -extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, - struct iscsi_cmd *); extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *, unsigned char *); extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); -- GitLab From 561bf15892375597ee59d473a704a3e634c4f311 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Jul 2013 03:58:58 -0700 Subject: [PATCH 2352/2900] iscsi-target: Fix iscsit_sequence_cmd reject handling for iser This patch moves ISCSI_OP_REJECT failures into iscsit_sequence_cmd() in order to avoid external iscsit_reject_cmd() reject usage for all PDU types. It also updates PDU specific handlers for traditional iscsi-target code to not reset the session after posting a ISCSI_OP_REJECT during setup. (v2: Fix CMDSN_LOWER_THAN_EXP for ISCSI_OP_SCSI to call target_put_sess_cmd() after iscsit_sequence_cmd() failure) Cc: Or Gerlitz Cc: Mike Christie Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 2 +- drivers/target/iscsi/iscsi_target.c | 55 +++++++++++++++--------- drivers/target/iscsi/iscsi_target_erl1.c | 6 +-- drivers/target/iscsi/iscsi_target_util.c | 26 ++++++++--- drivers/target/iscsi/iscsi_target_util.h | 3 +- include/target/iscsi/iscsi_transport.h | 3 +- 6 files changed, 62 insertions(+), 33 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 134ff58c6b17..7e219a46e7ca 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -934,7 +934,7 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn, } sequence_cmd: - rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); if (!rc && dump_payload == false && unsol_data) iscsit_set_unsoliticed_dataout(cmd); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 2a25bd3b065c..4319dad7d919 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1052,11 +1052,11 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * be acknowledged. (See below) */ if (!cmd->immediate_data) { - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); - if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { - if (!cmd->sense_reason) - return 0; - + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, + (unsigned char *)hdr, hdr->cmdsn); + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) + return -1; + else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); return 0; } @@ -1083,6 +1083,9 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below. */ if (cmd->sense_reason) { + if (cmd->reject_reason) + return 0; + target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); return 1; } @@ -1091,10 +1094,8 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * the backend memory allocation. */ cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); - if (cmd->sense_reason) { - target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + if (cmd->sense_reason) return 1; - } return 0; } @@ -1104,6 +1105,7 @@ static int iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, bool dump_payload) { + struct iscsi_conn *conn = cmd->conn; int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; /* * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. @@ -1120,12 +1122,22 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, * DataCRC, check against ExpCmdSN/MaxCmdSN if * Immediate Bit is not set. */ - cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn); + cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, + (unsigned char *)hdr, hdr->cmdsn); + if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { + return -1; + } else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { + target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + return 0; + } if (cmd->sense_reason) { - if (iscsit_dump_data_payload(cmd->conn, - cmd->first_burst_len, 1) < 0) - return -1; + int rc; + + rc = iscsit_dump_data_payload(cmd->conn, + cmd->first_burst_len, 1); + target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + return rc; } else if (cmd->unsolicited_data) iscsit_set_unsoliticed_dataout(cmd); @@ -1159,7 +1171,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, rc = iscsit_setup_scsi_cmd(conn, cmd, buf); if (rc < 0) - return rc; + return 0; /* * Allocation iovecs needed for struct socket operations for * traditional iSCSI block I/O. @@ -1494,7 +1506,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) rc = iscsit_check_dataout_hdr(conn, buf, &cmd); if (rc < 0) - return rc; + return 0; else if (!cmd) return 0; @@ -1579,10 +1591,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, return 0; } - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, + (unsigned char *)hdr, hdr->cmdsn); if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) return 0; - if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) return -1; @@ -1623,7 +1635,7 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ret = iscsit_setup_nop_out(conn, cmd, hdr); if (ret < 0) - return ret; + return 0; /* * Handle NOP-OUT payload for traditional iSCSI sockets */ @@ -1893,7 +1905,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, spin_unlock_bh(&conn->cmd_lock); if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { - int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) out_of_order_cmdsn = 1; else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) @@ -1996,7 +2008,8 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, + (unsigned char *)hdr, hdr->cmdsn); if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) return -1; @@ -2022,7 +2035,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, rc = iscsit_setup_text_cmd(conn, cmd, hdr); if (rc < 0) - return rc; + return 0; rx_size = payload_length; if (payload_length) { @@ -2284,7 +2297,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (ret < 0) return ret; } else { - cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); + cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn); if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) logout_remove = 0; else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index d00f1326f0c8..586c268679a4 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -1088,7 +1088,7 @@ int iscsit_handle_ooo_cmdsn( ooo_cmdsn = iscsit_allocate_ooo_cmdsn(); if (!ooo_cmdsn) - return CMDSN_ERROR_CANNOT_RECOVER; + return -ENOMEM; ooo_cmdsn->cmd = cmd; ooo_cmdsn->batch_count = (batch) ? @@ -1099,10 +1099,10 @@ int iscsit_handle_ooo_cmdsn( if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) { kmem_cache_free(lio_ooo_cache, ooo_cmdsn); - return CMDSN_ERROR_CANNOT_RECOVER; + return -ENOMEM; } - return CMDSN_HIGHER_THAN_EXP; + return 0; } static int iscsit_set_dataout_timeout_values( diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 96ce6f2ec428..1df06d5e4e01 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -283,13 +283,12 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm * Commands may be received out of order if MC/S is in use. * Ensure they are executed in CmdSN order. */ -int iscsit_sequence_cmd( - struct iscsi_conn *conn, - struct iscsi_cmd *cmd, - __be32 cmdsn) +int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + unsigned char *buf, __be32 cmdsn) { - int ret; - int cmdsn_ret; + int ret, cmdsn_ret; + bool reject = false; + u8 reason = ISCSI_REASON_BOOKMARK_NO_RESOURCES; mutex_lock(&conn->sess->cmdsn_mutex); @@ -299,9 +298,19 @@ int iscsit_sequence_cmd( ret = iscsit_execute_cmd(cmd, 0); if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list)) iscsit_execute_ooo_cmdsns(conn->sess); + else if (ret < 0) { + reject = true; + ret = CMDSN_ERROR_CANNOT_RECOVER; + } break; case CMDSN_HIGHER_THAN_EXP: ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn)); + if (ret < 0) { + reject = true; + ret = CMDSN_ERROR_CANNOT_RECOVER; + break; + } + ret = CMDSN_HIGHER_THAN_EXP; break; case CMDSN_LOWER_THAN_EXP: cmd->i_state = ISTATE_REMOVE; @@ -309,11 +318,16 @@ int iscsit_sequence_cmd( ret = cmdsn_ret; break; default: + reason = ISCSI_REASON_PROTOCOL_ERROR; + reject = true; ret = cmdsn_ret; break; } mutex_unlock(&conn->sess->cmdsn_mutex); + if (reject) + iscsit_reject_cmd(cmd, reason, buf); + return ret; } EXPORT_SYMBOL(iscsit_sequence_cmd); diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index a4422659d049..e4fc34a02f57 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -13,7 +13,8 @@ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32); extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *); extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); -int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn); +extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + unsigned char * ,__be32 cmdsn); extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *); extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t); extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *, diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index 19a43ad977c2..ce4070d8f156 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -86,4 +86,5 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *); * From iscsi_target_util.c */ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); -extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32); +extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, + unsigned char *, __be32); -- GitLab From 186a9647019587b3784694894c4d136fd00cfd7b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Jul 2013 03:11:48 -0700 Subject: [PATCH 2353/2900] iscsi-target: Fix ISCSI_OP_SCSI_TMFUNC handling for iser This patch adds target_get_sess_cmd reference counting for iscsit_handle_task_mgt_cmd(), and adds a target_put_sess_cmd() for the failure case. It also fixes a bug where ISCSI_OP_SCSI_TMFUNC type commands where leaking iscsi_cmd->i_conn_node and eventually triggering an OOPs during struct isert_conn shutdown. Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 16 ++++++++-------- drivers/target/iscsi/iscsi_target.c | 12 ++++++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 7e219a46e7ca..9efbf13007e4 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1200,14 +1200,12 @@ isert_put_cmd(struct isert_cmd *isert_cmd) { struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; struct isert_conn *isert_conn = isert_cmd->conn; - struct iscsi_conn *conn; + struct iscsi_conn *conn = isert_conn->conn; pr_debug("Entering isert_put_cmd: %p\n", isert_cmd); switch (cmd->iscsi_opcode) { case ISCSI_OP_SCSI_CMD: - conn = isert_conn->conn; - spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) list_del(&cmd->i_conn_node); @@ -1217,16 +1215,18 @@ isert_put_cmd(struct isert_cmd *isert_cmd) iscsit_stop_dataout_timer(cmd); isert_unmap_cmd(isert_cmd, isert_conn); - /* - * Fall-through - */ + transport_generic_free_cmd(&cmd->se_cmd, 0); + break; case ISCSI_OP_SCSI_TMFUNC: + spin_lock_bh(&conn->cmd_lock); + if (!list_empty(&cmd->i_conn_node)) + list_del(&cmd->i_conn_node); + spin_unlock_bh(&conn->cmd_lock); + transport_generic_free_cmd(&cmd->se_cmd, 0); break; case ISCSI_OP_REJECT: case ISCSI_OP_NOOP_OUT: - conn = isert_conn->conn; - spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) list_del(&cmd->i_conn_node); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 4319dad7d919..c30ec1d5756e 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1737,8 +1737,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, struct se_tmr_req *se_tmr; struct iscsi_tmr_req *tmr_req; struct iscsi_tm *hdr; - int out_of_order_cmdsn = 0; - int ret; + int out_of_order_cmdsn = 0, ret; + bool sess_ref = false; u8 function; hdr = (struct iscsi_tm *) buf; @@ -1794,6 +1794,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, conn->sess->se_sess, 0, DMA_NONE, MSG_SIMPLE_TAG, cmd->sense_buffer + 2); + target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true); + sess_ref = true; + switch (function) { case ISCSI_TM_FUNC_ABORT_TASK: tcm_function = TMR_ABORT_TASK; @@ -1931,6 +1934,11 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, * For connection recovery, this is also the default action for * TMR TASK_REASSIGN. */ + if (sess_ref) { + pr_debug("Handle TMR, using sess_ref=true check\n"); + target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); + } + iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); return 0; } -- GitLab From c38e39c378f46f00ce922dd40a91043a9925c28d Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 25 Jun 2013 17:29:46 +0300 Subject: [PATCH 2354/2900] vhost-net: fix use-after-free in vhost_net_flush vhost_net_ubuf_put_and_wait has a confusing name: it will actually also free it's argument. Thus since commit 1280c27f8e29acf4af2da914e80ec27c3dbd5c01 "vhost-net: flush outstanding DMAs on memory change" vhost_net_flush tries to use the argument after passing it to vhost_net_ubuf_put_and_wait, this results in use after free. To fix, don't free the argument in vhost_net_ubuf_put_and_wait, add an new API for callers that want to free ubufs. Acked-by: Asias He Acked-by: Jason Wang Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f80d3dd41d8c..8ca5ac71b845 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -150,6 +150,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) { kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); +} + +static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) +{ + vhost_net_ubuf_put_and_wait(ubufs); kfree(ubufs); } @@ -948,7 +953,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) mutex_unlock(&vq->mutex); if (oldubufs) { - vhost_net_ubuf_put_and_wait(oldubufs); + vhost_net_ubuf_put_wait_and_free(oldubufs); mutex_lock(&vq->mutex); vhost_zerocopy_signal_used(n, vq); mutex_unlock(&vq->mutex); @@ -966,7 +971,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) rcu_assign_pointer(vq->private_data, oldsock); vhost_net_enable_vq(n, vq); if (ubufs) - vhost_net_ubuf_put_and_wait(ubufs); + vhost_net_ubuf_put_wait_and_free(ubufs); err_ubufs: fput(sock->file); err_vq: -- GitLab From 6d5e6aa860a33fdfcd07de658c8108027c06c329 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:23 +0800 Subject: [PATCH 2355/2900] vhost: Simplify dev->vqs[i] access Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 60aa5ad09a2f..4d135b1a861e 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -251,17 +251,16 @@ static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq) /* Helper to allocate iovec buffers for all vqs. */ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev) { + struct vhost_virtqueue *vq; int i; for (i = 0; i < dev->nvqs; ++i) { - dev->vqs[i]->indirect = kmalloc(sizeof *dev->vqs[i]->indirect * - UIO_MAXIOV, GFP_KERNEL); - dev->vqs[i]->log = kmalloc(sizeof *dev->vqs[i]->log * UIO_MAXIOV, - GFP_KERNEL); - dev->vqs[i]->heads = kmalloc(sizeof *dev->vqs[i]->heads * - UIO_MAXIOV, GFP_KERNEL); - if (!dev->vqs[i]->indirect || !dev->vqs[i]->log || - !dev->vqs[i]->heads) + vq = dev->vqs[i]; + vq->indirect = kmalloc(sizeof *vq->indirect * UIO_MAXIOV, + GFP_KERNEL); + vq->log = kmalloc(sizeof *vq->log * UIO_MAXIOV, GFP_KERNEL); + vq->heads = kmalloc(sizeof *vq->heads * UIO_MAXIOV, GFP_KERNEL); + if (!vq->indirect || !vq->log || !vq->heads) goto err_nomem; } return 0; @@ -283,6 +282,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev) long vhost_dev_init(struct vhost_dev *dev, struct vhost_virtqueue **vqs, int nvqs) { + struct vhost_virtqueue *vq; int i; dev->vqs = vqs; @@ -297,15 +297,16 @@ long vhost_dev_init(struct vhost_dev *dev, dev->worker = NULL; for (i = 0; i < dev->nvqs; ++i) { - dev->vqs[i]->log = NULL; - dev->vqs[i]->indirect = NULL; - dev->vqs[i]->heads = NULL; - dev->vqs[i]->dev = dev; - mutex_init(&dev->vqs[i]->mutex); - vhost_vq_reset(dev, dev->vqs[i]); - if (dev->vqs[i]->handle_kick) - vhost_poll_init(&dev->vqs[i]->poll, - dev->vqs[i]->handle_kick, POLLIN, dev); + vq = dev->vqs[i]; + vq->log = NULL; + vq->indirect = NULL; + vq->heads = NULL; + vq->dev = dev; + mutex_init(&vq->mutex); + vhost_vq_reset(dev, vq); + if (vq->handle_kick) + vhost_poll_init(&vq->poll, vq->handle_kick, + POLLIN, dev); } return 0; -- GitLab From deeacef086a0b312da846aac7b7cd046523bf6c6 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:25 +0800 Subject: [PATCH 2356/2900] vhost-scsi: Remove unnecessary forward struct vhost_scsi declaration It was needed when struct tcm_vhost_tpg is in tcm_vhost.h Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 701420297225..d5a91cf84221 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -116,7 +116,6 @@ struct tcm_vhost_nacl { struct se_node_acl se_node_acl; }; -struct vhost_scsi; struct tcm_vhost_tpg { /* Vhost port target portal group tag for TCM */ u16 tport_tpgt; -- GitLab From c7289312fe9b4077b5c15632b232e76144a220c6 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:26 +0800 Subject: [PATCH 2357/2900] vhost-scsi: Rename struct vhost_scsi *s to *vs vs is used everywhere, make the naming more consistent. Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index d5a91cf84221..e5edb651b6d2 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1337,63 +1337,63 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) static int vhost_scsi_open(struct inode *inode, struct file *f) { - struct vhost_scsi *s; + struct vhost_scsi *vs; struct vhost_virtqueue **vqs; int r, i; - s = kzalloc(sizeof(*s), GFP_KERNEL); - if (!s) + vs = kzalloc(sizeof(*vs), GFP_KERNEL); + if (!vs) return -ENOMEM; vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL); if (!vqs) { - kfree(s); + kfree(vs); return -ENOMEM; } - vhost_work_init(&s->vs_completion_work, vhost_scsi_complete_cmd_work); - vhost_work_init(&s->vs_event_work, tcm_vhost_evt_work); + vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work); + vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work); - s->vs_events_nr = 0; - s->vs_events_missed = false; + vs->vs_events_nr = 0; + vs->vs_events_missed = false; - vqs[VHOST_SCSI_VQ_CTL] = &s->vqs[VHOST_SCSI_VQ_CTL].vq; - vqs[VHOST_SCSI_VQ_EVT] = &s->vqs[VHOST_SCSI_VQ_EVT].vq; - s->vqs[VHOST_SCSI_VQ_CTL].vq.handle_kick = vhost_scsi_ctl_handle_kick; - s->vqs[VHOST_SCSI_VQ_EVT].vq.handle_kick = vhost_scsi_evt_handle_kick; + vqs[VHOST_SCSI_VQ_CTL] = &vs->vqs[VHOST_SCSI_VQ_CTL].vq; + vqs[VHOST_SCSI_VQ_EVT] = &vs->vqs[VHOST_SCSI_VQ_EVT].vq; + vs->vqs[VHOST_SCSI_VQ_CTL].vq.handle_kick = vhost_scsi_ctl_handle_kick; + vs->vqs[VHOST_SCSI_VQ_EVT].vq.handle_kick = vhost_scsi_evt_handle_kick; for (i = VHOST_SCSI_VQ_IO; i < VHOST_SCSI_MAX_VQ; i++) { - vqs[i] = &s->vqs[i].vq; - s->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; + vqs[i] = &vs->vqs[i].vq; + vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; } - r = vhost_dev_init(&s->dev, vqs, VHOST_SCSI_MAX_VQ); + r = vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ); - tcm_vhost_init_inflight(s, NULL); + tcm_vhost_init_inflight(vs, NULL); if (r < 0) { kfree(vqs); - kfree(s); + kfree(vs); return r; } - f->private_data = s; + f->private_data = vs; return 0; } static int vhost_scsi_release(struct inode *inode, struct file *f) { - struct vhost_scsi *s = f->private_data; + struct vhost_scsi *vs = f->private_data; struct vhost_scsi_target t; - mutex_lock(&s->dev.mutex); - memcpy(t.vhost_wwpn, s->vs_vhost_wwpn, sizeof(t.vhost_wwpn)); - mutex_unlock(&s->dev.mutex); - vhost_scsi_clear_endpoint(s, &t); - vhost_dev_stop(&s->dev); - vhost_dev_cleanup(&s->dev, false); + mutex_lock(&vs->dev.mutex); + memcpy(t.vhost_wwpn, vs->vs_vhost_wwpn, sizeof(t.vhost_wwpn)); + mutex_unlock(&vs->dev.mutex); + vhost_scsi_clear_endpoint(vs, &t); + vhost_dev_stop(&vs->dev); + vhost_dev_cleanup(&vs->dev, false); /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */ - vhost_scsi_flush(s); - kfree(s->dev.vqs); - kfree(s); + vhost_scsi_flush(vs); + kfree(vs->dev.vqs); + kfree(vs); return 0; } -- GitLab From 683bd967dd32eec4e4c45e4d38e9f807a2fd9479 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:27 +0800 Subject: [PATCH 2358/2900] vhost-scsi: Make func indention more consistent Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 154 ++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 66 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index e5edb651b6d2..acac9cc93edf 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -328,11 +328,12 @@ static u32 tcm_vhost_get_default_depth(struct se_portal_group *se_tpg) return 1; } -static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code, - unsigned char *buf) +static u32 +tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, + struct se_node_acl *se_nacl, + struct t10_pr_registration *pr_reg, + int *format_code, + unsigned char *buf) { struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -358,10 +359,11 @@ static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, format_code, buf); } -static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl, - struct t10_pr_registration *pr_reg, - int *format_code) +static u32 +tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, + struct se_node_acl *se_nacl, + struct t10_pr_registration *pr_reg, + int *format_code) { struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -387,10 +389,11 @@ static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, format_code); } -static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, - const char *buf, - u32 *out_tid_len, - char **port_nexus_ptr) +static char * +tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, + const char *buf, + u32 *out_tid_len, + char **port_nexus_ptr) { struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -416,8 +419,8 @@ static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, port_nexus_ptr); } -static struct se_node_acl *tcm_vhost_alloc_fabric_acl( - struct se_portal_group *se_tpg) +static struct se_node_acl * +tcm_vhost_alloc_fabric_acl(struct se_portal_group *se_tpg) { struct tcm_vhost_nacl *nacl; @@ -430,8 +433,9 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl( return &nacl->se_node_acl; } -static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, - struct se_node_acl *se_nacl) +static void +tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, + struct se_node_acl *se_nacl) { struct tcm_vhost_nacl *nacl = container_of(se_nacl, struct tcm_vhost_nacl, se_node_acl); @@ -526,8 +530,9 @@ static void tcm_vhost_free_evt(struct vhost_scsi *vs, struct tcm_vhost_evt *evt) kfree(evt); } -static struct tcm_vhost_evt *tcm_vhost_allocate_evt(struct vhost_scsi *vs, - u32 event, u32 reason) +static struct tcm_vhost_evt * +tcm_vhost_allocate_evt(struct vhost_scsi *vs, + u32 event, u32 reason) { struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT].vq; struct tcm_vhost_evt *evt; @@ -571,8 +576,8 @@ static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) kfree(tv_cmd); } -static void tcm_vhost_do_evt_work(struct vhost_scsi *vs, - struct tcm_vhost_evt *evt) +static void +tcm_vhost_do_evt_work(struct vhost_scsi *vs, struct tcm_vhost_evt *evt) { struct vhost_virtqueue *vq = &vs->vqs[VHOST_SCSI_VQ_EVT].vq; struct virtio_scsi_event *event = &evt->event; @@ -693,12 +698,12 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) vhost_signal(&vs->dev, &vs->vqs[vq].vq); } -static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( - struct vhost_virtqueue *vq, - struct tcm_vhost_tpg *tv_tpg, - struct virtio_scsi_cmd_req *v_req, - u32 exp_data_len, - int data_direction) +static struct tcm_vhost_cmd * +vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq, + struct tcm_vhost_tpg *tv_tpg, + struct virtio_scsi_cmd_req *v_req, + u32 exp_data_len, + int data_direction) { struct tcm_vhost_cmd *tv_cmd; struct tcm_vhost_nexus *tv_nexus; @@ -729,8 +734,11 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( * * Returns the number of scatterlist entries used or -errno on error. */ -static int vhost_scsi_map_to_sgl(struct scatterlist *sgl, - unsigned int sgl_count, struct iovec *iov, int write) +static int +vhost_scsi_map_to_sgl(struct scatterlist *sgl, + unsigned int sgl_count, + struct iovec *iov, + int write) { unsigned int npages = 0, pages_nr, offset, nbytes; struct scatterlist *sg = sgl; @@ -774,8 +782,11 @@ static int vhost_scsi_map_to_sgl(struct scatterlist *sgl, return ret; } -static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, - struct iovec *iov, unsigned int niov, int write) +static int +vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, + struct iovec *iov, + unsigned int niov, + int write) { int ret; unsigned int i; @@ -855,8 +866,10 @@ static void tcm_vhost_submission_work(struct work_struct *work) } } -static void vhost_scsi_send_bad_target(struct vhost_scsi *vs, - struct vhost_virtqueue *vq, int head, unsigned out) +static void +vhost_scsi_send_bad_target(struct vhost_scsi *vs, + struct vhost_virtqueue *vq, + int head, unsigned out) { struct virtio_scsi_cmd_resp __user *resp; struct virtio_scsi_cmd_resp rsp; @@ -872,8 +885,8 @@ static void vhost_scsi_send_bad_target(struct vhost_scsi *vs, pr_err("Faulted on virtio_scsi_cmd_resp\n"); } -static void vhost_scsi_handle_vq(struct vhost_scsi *vs, - struct vhost_virtqueue *vq) +static void +vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) { struct tcm_vhost_tpg **vs_tpg; struct virtio_scsi_cmd_req v_req; @@ -1054,8 +1067,12 @@ static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) pr_debug("%s: The handling func for control queue.\n", __func__); } -static void tcm_vhost_send_evt(struct vhost_scsi *vs, struct tcm_vhost_tpg *tpg, - struct se_lun *lun, u32 event, u32 reason) +static void +tcm_vhost_send_evt(struct vhost_scsi *vs, + struct tcm_vhost_tpg *tpg, + struct se_lun *lun, + u32 event, + u32 reason) { struct tcm_vhost_evt *evt; @@ -1145,9 +1162,9 @@ static void vhost_scsi_flush(struct vhost_scsi *vs) * The lock nesting rule is: * tcm_vhost_mutex -> vs->dev.mutex -> tpg->tv_tpg_mutex -> vq->mutex */ -static int vhost_scsi_set_endpoint( - struct vhost_scsi *vs, - struct vhost_scsi_target *t) +static int +vhost_scsi_set_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) { struct tcm_vhost_tport *tv_tport; struct tcm_vhost_tpg *tv_tpg; @@ -1235,9 +1252,9 @@ static int vhost_scsi_set_endpoint( return ret; } -static int vhost_scsi_clear_endpoint( - struct vhost_scsi *vs, - struct vhost_scsi_target *t) +static int +vhost_scsi_clear_endpoint(struct vhost_scsi *vs, + struct vhost_scsi_target *t) { struct tcm_vhost_tport *tv_tport; struct tcm_vhost_tpg *tv_tpg; @@ -1397,8 +1414,10 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) return 0; } -static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, - unsigned long arg) +static long +vhost_scsi_ioctl(struct file *f, + unsigned int ioctl, + unsigned long arg) { struct vhost_scsi *vs = f->private_data; struct vhost_scsi_target backend; @@ -1514,8 +1533,9 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport) return "Unknown"; } -static void tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg, - struct se_lun *lun, bool plug) +static void +tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg, + struct se_lun *lun, bool plug) { struct vhost_scsi *vs = tpg->vhost_scsi; @@ -1555,7 +1575,7 @@ static void tcm_vhost_hotunplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun) } static int tcm_vhost_port_link(struct se_portal_group *se_tpg, - struct se_lun *lun) + struct se_lun *lun) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -1574,7 +1594,7 @@ static int tcm_vhost_port_link(struct se_portal_group *se_tpg, } static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, - struct se_lun *lun) + struct se_lun *lun) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -1590,10 +1610,10 @@ static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, mutex_unlock(&tcm_vhost_mutex); } -static struct se_node_acl *tcm_vhost_make_nodeacl( - struct se_portal_group *se_tpg, - struct config_group *group, - const char *name) +static struct se_node_acl * +tcm_vhost_make_nodeacl(struct se_portal_group *se_tpg, + struct config_group *group, + const char *name) { struct se_node_acl *se_nacl, *se_nacl_new; struct tcm_vhost_nacl *nacl; @@ -1635,7 +1655,7 @@ static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) } static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, - const char *name) + const char *name) { struct se_portal_group *se_tpg; struct tcm_vhost_nexus *tv_nexus; @@ -1739,7 +1759,7 @@ static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) } static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, - char *page) + char *page) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -1760,8 +1780,8 @@ static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, } static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, - const char *page, - size_t count) + const char *page, + size_t count) { struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); @@ -1844,9 +1864,10 @@ static struct configfs_attribute *tcm_vhost_tpg_attrs[] = { NULL, }; -static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn, - struct config_group *group, - const char *name) +static struct se_portal_group * +tcm_vhost_make_tpg(struct se_wwn *wwn, + struct config_group *group, + const char *name) { struct tcm_vhost_tport *tport = container_of(wwn, struct tcm_vhost_tport, tport_wwn); @@ -1902,9 +1923,10 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) kfree(tpg); } -static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf, - struct config_group *group, - const char *name) +static struct se_wwn * +tcm_vhost_make_tport(struct target_fabric_configfs *tf, + struct config_group *group, + const char *name) { struct tcm_vhost_tport *tport; char *ptr; @@ -1974,9 +1996,9 @@ static void tcm_vhost_drop_tport(struct se_wwn *wwn) kfree(tport); } -static ssize_t tcm_vhost_wwn_show_attr_version( - struct target_fabric_configfs *tf, - char *page) +static ssize_t +tcm_vhost_wwn_show_attr_version(struct target_fabric_configfs *tf, + char *page) { return sprintf(page, "TCM_VHOST fabric module %s on %s/%s" "on "UTS_RELEASE"\n", TCM_VHOST_VERSION, utsname()->sysname, -- GitLab From 9871831283e79575deb63fa341e9c7f3c1223d10 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:28 +0800 Subject: [PATCH 2359/2900] vhost-scsi: Rename struct tcm_vhost_tpg *tv_tpg to *tpg Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 122 +++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index acac9cc93edf..7fb18595c744 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -700,7 +700,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) static struct tcm_vhost_cmd * vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq, - struct tcm_vhost_tpg *tv_tpg, + struct tcm_vhost_tpg *tpg, struct virtio_scsi_cmd_req *v_req, u32 exp_data_len, int data_direction) @@ -708,7 +708,7 @@ vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq, struct tcm_vhost_cmd *tv_cmd; struct tcm_vhost_nexus *tv_nexus; - tv_nexus = tv_tpg->tpg_nexus; + tv_nexus = tpg->tpg_nexus; if (!tv_nexus) { pr_err("Unable to locate active struct tcm_vhost_nexus\n"); return ERR_PTR(-EIO); @@ -890,7 +890,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) { struct tcm_vhost_tpg **vs_tpg; struct virtio_scsi_cmd_req v_req; - struct tcm_vhost_tpg *tv_tpg; + struct tcm_vhost_tpg *tpg; struct tcm_vhost_cmd *tv_cmd; u32 exp_data_len, data_first, data_num, data_direction; unsigned out, in, i; @@ -976,10 +976,10 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) /* Extract the tpgt */ target = v_req.lun[1]; - tv_tpg = ACCESS_ONCE(vs_tpg[target]); + tpg = ACCESS_ONCE(vs_tpg[target]); /* Target does not exist, fail the request */ - if (unlikely(!tv_tpg)) { + if (unlikely(!tpg)) { vhost_scsi_send_bad_target(vs, vq, head, out); continue; } @@ -988,7 +988,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) for (i = 0; i < data_num; i++) exp_data_len += vq->iov[data_first + i].iov_len; - tv_cmd = vhost_scsi_allocate_cmd(vq, tv_tpg, &v_req, + tv_cmd = vhost_scsi_allocate_cmd(vq, tpg, &v_req, exp_data_len, data_direction); if (IS_ERR(tv_cmd)) { vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n", @@ -1167,7 +1167,7 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, struct vhost_scsi_target *t) { struct tcm_vhost_tport *tv_tport; - struct tcm_vhost_tpg *tv_tpg; + struct tcm_vhost_tpg *tpg; struct tcm_vhost_tpg **vs_tpg; struct vhost_virtqueue *vq; int index, ret, i, len; @@ -1194,32 +1194,32 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs, if (vs->vs_tpg) memcpy(vs_tpg, vs->vs_tpg, len); - list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) { - mutex_lock(&tv_tpg->tv_tpg_mutex); - if (!tv_tpg->tpg_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + list_for_each_entry(tpg, &tcm_vhost_list, tv_tpg_list) { + mutex_lock(&tpg->tv_tpg_mutex); + if (!tpg->tpg_nexus) { + mutex_unlock(&tpg->tv_tpg_mutex); continue; } - if (tv_tpg->tv_tpg_vhost_count != 0) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + if (tpg->tv_tpg_vhost_count != 0) { + mutex_unlock(&tpg->tv_tpg_mutex); continue; } - tv_tport = tv_tpg->tport; + tv_tport = tpg->tport; if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) { - if (vs->vs_tpg && vs->vs_tpg[tv_tpg->tport_tpgt]) { + if (vs->vs_tpg && vs->vs_tpg[tpg->tport_tpgt]) { kfree(vs_tpg); - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); ret = -EEXIST; goto out; } - tv_tpg->tv_tpg_vhost_count++; - tv_tpg->vhost_scsi = vs; - vs_tpg[tv_tpg->tport_tpgt] = tv_tpg; + tpg->tv_tpg_vhost_count++; + tpg->vhost_scsi = vs; + vs_tpg[tpg->tport_tpgt] = tpg; smp_mb__after_atomic_inc(); match = true; } - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); } if (match) { @@ -1257,7 +1257,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, struct vhost_scsi_target *t) { struct tcm_vhost_tport *tv_tport; - struct tcm_vhost_tpg *tv_tpg; + struct tcm_vhost_tpg *tpg; struct vhost_virtqueue *vq; bool match = false; int index, ret, i; @@ -1280,30 +1280,30 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) { target = i; - tv_tpg = vs->vs_tpg[target]; - if (!tv_tpg) + tpg = vs->vs_tpg[target]; + if (!tpg) continue; - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tport = tv_tpg->tport; + mutex_lock(&tpg->tv_tpg_mutex); + tv_tport = tpg->tport; if (!tv_tport) { ret = -ENODEV; goto err_tpg; } if (strcmp(tv_tport->tport_name, t->vhost_wwpn)) { - pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" + pr_warn("tv_tport->tport_name: %s, tpg->tport_tpgt: %hu" " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", - tv_tport->tport_name, tv_tpg->tport_tpgt, + tv_tport->tport_name, tpg->tport_tpgt, t->vhost_wwpn, t->vhost_tpgt); ret = -EINVAL; goto err_tpg; } - tv_tpg->tv_tpg_vhost_count--; - tv_tpg->vhost_scsi = NULL; + tpg->tv_tpg_vhost_count--; + tpg->vhost_scsi = NULL; vs->vs_tpg[target] = NULL; match = true; - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); } if (match) { for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) { @@ -1327,7 +1327,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs, return 0; err_tpg: - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); err_dev: mutex_unlock(&vs->dev.mutex); mutex_unlock(&tcm_vhost_mutex); @@ -1577,16 +1577,16 @@ static void tcm_vhost_hotunplug(struct tcm_vhost_tpg *tpg, struct se_lun *lun) static int tcm_vhost_port_link(struct se_portal_group *se_tpg, struct se_lun *lun) { - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, + struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); mutex_lock(&tcm_vhost_mutex); - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tpg->tv_tpg_port_count++; - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_lock(&tpg->tv_tpg_mutex); + tpg->tv_tpg_port_count++; + mutex_unlock(&tpg->tv_tpg_mutex); - tcm_vhost_hotplug(tv_tpg, lun); + tcm_vhost_hotplug(tpg, lun); mutex_unlock(&tcm_vhost_mutex); @@ -1596,16 +1596,16 @@ static int tcm_vhost_port_link(struct se_portal_group *se_tpg, static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, struct se_lun *lun) { - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, + struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); mutex_lock(&tcm_vhost_mutex); - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_tpg->tv_tpg_port_count--; - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_lock(&tpg->tv_tpg_mutex); + tpg->tv_tpg_port_count--; + mutex_unlock(&tpg->tv_tpg_mutex); - tcm_vhost_hotunplug(tv_tpg, lun); + tcm_vhost_hotunplug(tpg, lun); mutex_unlock(&tcm_vhost_mutex); } @@ -1654,23 +1654,23 @@ static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) kfree(nacl); } -static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, +static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg, const char *name) { struct se_portal_group *se_tpg; struct tcm_vhost_nexus *tv_nexus; - mutex_lock(&tv_tpg->tv_tpg_mutex); - if (tv_tpg->tpg_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); - pr_debug("tv_tpg->tpg_nexus already exists\n"); + mutex_lock(&tpg->tv_tpg_mutex); + if (tpg->tpg_nexus) { + mutex_unlock(&tpg->tv_tpg_mutex); + pr_debug("tpg->tpg_nexus already exists\n"); return -EEXIST; } - se_tpg = &tv_tpg->se_tpg; + se_tpg = &tpg->se_tpg; tv_nexus = kzalloc(sizeof(struct tcm_vhost_nexus), GFP_KERNEL); if (!tv_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); pr_err("Unable to allocate struct tcm_vhost_nexus\n"); return -ENOMEM; } @@ -1679,7 +1679,7 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, */ tv_nexus->tvn_se_sess = transport_init_session(); if (IS_ERR(tv_nexus->tvn_se_sess)) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); kfree(tv_nexus); return -ENOMEM; } @@ -1691,7 +1691,7 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl( se_tpg, (unsigned char *)name); if (!tv_nexus->tvn_se_sess->se_node_acl) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); pr_debug("core_tpg_check_initiator_node_acl() failed" " for %s\n", name); transport_free_session(tv_nexus->tvn_se_sess); @@ -1704,9 +1704,9 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, */ __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, tv_nexus->tvn_se_sess, tv_nexus); - tv_tpg->tpg_nexus = tv_nexus; + tpg->tpg_nexus = tv_nexus; - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); return 0; } @@ -1761,20 +1761,20 @@ static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, char *page) { - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, + struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); struct tcm_vhost_nexus *tv_nexus; ssize_t ret; - mutex_lock(&tv_tpg->tv_tpg_mutex); - tv_nexus = tv_tpg->tpg_nexus; + mutex_lock(&tpg->tv_tpg_mutex); + tv_nexus = tpg->tpg_nexus; if (!tv_nexus) { - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); return -ENODEV; } ret = snprintf(page, PAGE_SIZE, "%s\n", tv_nexus->tvn_se_sess->se_node_acl->initiatorname); - mutex_unlock(&tv_tpg->tv_tpg_mutex); + mutex_unlock(&tpg->tv_tpg_mutex); return ret; } @@ -1783,16 +1783,16 @@ static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, const char *page, size_t count) { - struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, + struct tcm_vhost_tpg *tpg = container_of(se_tpg, struct tcm_vhost_tpg, se_tpg); - struct tcm_vhost_tport *tport_wwn = tv_tpg->tport; + struct tcm_vhost_tport *tport_wwn = tpg->tport; unsigned char i_port[TCM_VHOST_NAMELEN], *ptr, *port_ptr; int ret; /* * Shutdown the active I_T nexus if 'NULL' is passed.. */ if (!strncmp(page, "NULL", 4)) { - ret = tcm_vhost_drop_nexus(tv_tpg); + ret = tcm_vhost_drop_nexus(tpg); return (!ret) ? count : ret; } /* @@ -1850,7 +1850,7 @@ static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, if (i_port[strlen(i_port)-1] == '\n') i_port[strlen(i_port)-1] = '\0'; - ret = tcm_vhost_make_nexus(tv_tpg, port_ptr); + ret = tcm_vhost_make_nexus(tpg, port_ptr); if (ret < 0) return ret; -- GitLab From 3c63f66a0dcdd6cb8bcacf210181f2b3baed19be Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:29 +0800 Subject: [PATCH 2360/2900] vhost-scsi: Rename struct tcm_vhost_cmd *tv_cmd to *cmd This way, we use cmd for struct tcm_vhost_cmd and evt for struct tcm_vhost_cmd. Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 142 +++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 7fb18595c744..03765e17c154 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -494,28 +494,28 @@ static int tcm_vhost_get_cmd_state(struct se_cmd *se_cmd) return 0; } -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) +static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *cmd) { - struct vhost_scsi *vs = tv_cmd->tvc_vhost; + struct vhost_scsi *vs = cmd->tvc_vhost; - llist_add(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); + llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list); vhost_work_queue(&vs->dev, &vs->vs_completion_work); } static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) { - struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, + struct tcm_vhost_cmd *cmd = container_of(se_cmd, struct tcm_vhost_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(tv_cmd); + vhost_scsi_complete_cmd(cmd); return 0; } static int tcm_vhost_queue_status(struct se_cmd *se_cmd) { - struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, + struct tcm_vhost_cmd *cmd = container_of(se_cmd, struct tcm_vhost_cmd, tvc_se_cmd); - vhost_scsi_complete_cmd(tv_cmd); + vhost_scsi_complete_cmd(cmd); return 0; } @@ -556,24 +556,24 @@ tcm_vhost_allocate_evt(struct vhost_scsi *vs, return evt; } -static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) +static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *cmd) { - struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; + struct se_cmd *se_cmd = &cmd->tvc_se_cmd; /* TODO locking against target/backend threads? */ transport_generic_free_cmd(se_cmd, 1); - if (tv_cmd->tvc_sgl_count) { + if (cmd->tvc_sgl_count) { u32 i; - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_sgl[i])); + for (i = 0; i < cmd->tvc_sgl_count; i++) + put_page(sg_page(&cmd->tvc_sgl[i])); - kfree(tv_cmd->tvc_sgl); + kfree(cmd->tvc_sgl); } - tcm_vhost_put_inflight(tv_cmd->inflight); + tcm_vhost_put_inflight(cmd->inflight); - kfree(tv_cmd); + kfree(cmd); } static void @@ -656,7 +656,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) vs_completion_work); DECLARE_BITMAP(signal, VHOST_SCSI_MAX_VQ); struct virtio_scsi_cmd_resp v_rsp; - struct tcm_vhost_cmd *tv_cmd; + struct tcm_vhost_cmd *cmd; struct llist_node *llnode; struct se_cmd *se_cmd; int ret, vq; @@ -664,32 +664,32 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) bitmap_zero(signal, VHOST_SCSI_MAX_VQ); llnode = llist_del_all(&vs->vs_completion_list); while (llnode) { - tv_cmd = llist_entry(llnode, struct tcm_vhost_cmd, + cmd = llist_entry(llnode, struct tcm_vhost_cmd, tvc_completion_list); llnode = llist_next(llnode); - se_cmd = &tv_cmd->tvc_se_cmd; + se_cmd = &cmd->tvc_se_cmd; pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__, - tv_cmd, se_cmd->residual_count, se_cmd->scsi_status); + cmd, se_cmd->residual_count, se_cmd->scsi_status); memset(&v_rsp, 0, sizeof(v_rsp)); v_rsp.resid = se_cmd->residual_count; /* TODO is status_qualifier field needed? */ v_rsp.status = se_cmd->scsi_status; v_rsp.sense_len = se_cmd->scsi_sense_length; - memcpy(v_rsp.sense, tv_cmd->tvc_sense_buf, + memcpy(v_rsp.sense, cmd->tvc_sense_buf, v_rsp.sense_len); - ret = copy_to_user(tv_cmd->tvc_resp, &v_rsp, sizeof(v_rsp)); + ret = copy_to_user(cmd->tvc_resp, &v_rsp, sizeof(v_rsp)); if (likely(ret == 0)) { struct vhost_scsi_virtqueue *q; - vhost_add_used(tv_cmd->tvc_vq, tv_cmd->tvc_vq_desc, 0); - q = container_of(tv_cmd->tvc_vq, struct vhost_scsi_virtqueue, vq); + vhost_add_used(cmd->tvc_vq, cmd->tvc_vq_desc, 0); + q = container_of(cmd->tvc_vq, struct vhost_scsi_virtqueue, vq); vq = q - vs->vqs; __set_bit(vq, signal); } else pr_err("Faulted on virtio_scsi_cmd_resp\n"); - vhost_scsi_free_cmd(tv_cmd); + vhost_scsi_free_cmd(cmd); } vq = -1; @@ -705,7 +705,7 @@ vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq, u32 exp_data_len, int data_direction) { - struct tcm_vhost_cmd *tv_cmd; + struct tcm_vhost_cmd *cmd; struct tcm_vhost_nexus *tv_nexus; tv_nexus = tpg->tpg_nexus; @@ -714,19 +714,19 @@ vhost_scsi_allocate_cmd(struct vhost_virtqueue *vq, return ERR_PTR(-EIO); } - tv_cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC); - if (!tv_cmd) { + cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC); + if (!cmd) { pr_err("Unable to allocate struct tcm_vhost_cmd\n"); return ERR_PTR(-ENOMEM); } - tv_cmd->tvc_tag = v_req->tag; - tv_cmd->tvc_task_attr = v_req->task_attr; - tv_cmd->tvc_exp_data_len = exp_data_len; - tv_cmd->tvc_data_direction = data_direction; - tv_cmd->tvc_nexus = tv_nexus; - tv_cmd->inflight = tcm_vhost_get_inflight(vq); + cmd->tvc_tag = v_req->tag; + cmd->tvc_task_attr = v_req->task_attr; + cmd->tvc_exp_data_len = exp_data_len; + cmd->tvc_data_direction = data_direction; + cmd->tvc_nexus = tv_nexus; + cmd->inflight = tcm_vhost_get_inflight(vq); - return tv_cmd; + return cmd; } /* @@ -783,7 +783,7 @@ vhost_scsi_map_to_sgl(struct scatterlist *sgl, } static int -vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, +vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, struct iovec *iov, unsigned int niov, int write) @@ -802,25 +802,25 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, /* TODO overflow checking */ - sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); + sg = kmalloc(sizeof(cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); if (!sg) return -ENOMEM; pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__, sg, sgl_count, !sg); sg_init_table(sg, sgl_count); - tv_cmd->tvc_sgl = sg; - tv_cmd->tvc_sgl_count = sgl_count; + cmd->tvc_sgl = sg; + cmd->tvc_sgl_count = sgl_count; pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count); for (i = 0; i < niov; i++) { ret = vhost_scsi_map_to_sgl(sg, sgl_count, &iov[i], write); if (ret < 0) { - for (i = 0; i < tv_cmd->tvc_sgl_count; i++) - put_page(sg_page(&tv_cmd->tvc_sgl[i])); - kfree(tv_cmd->tvc_sgl); - tv_cmd->tvc_sgl = NULL; - tv_cmd->tvc_sgl_count = 0; + for (i = 0; i < cmd->tvc_sgl_count; i++) + put_page(sg_page(&cmd->tvc_sgl[i])); + kfree(cmd->tvc_sgl); + cmd->tvc_sgl = NULL; + cmd->tvc_sgl_count = 0; return ret; } @@ -832,15 +832,15 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, static void tcm_vhost_submission_work(struct work_struct *work) { - struct tcm_vhost_cmd *tv_cmd = + struct tcm_vhost_cmd *cmd = container_of(work, struct tcm_vhost_cmd, work); struct tcm_vhost_nexus *tv_nexus; - struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; + struct se_cmd *se_cmd = &cmd->tvc_se_cmd; struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL; int rc, sg_no_bidi = 0; - if (tv_cmd->tvc_sgl_count) { - sg_ptr = tv_cmd->tvc_sgl; + if (cmd->tvc_sgl_count) { + sg_ptr = cmd->tvc_sgl; /* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ #if 0 if (se_cmd->se_cmd_flags & SCF_BIDI) { @@ -851,13 +851,13 @@ static void tcm_vhost_submission_work(struct work_struct *work) } else { sg_ptr = NULL; } - tv_nexus = tv_cmd->tvc_nexus; + tv_nexus = cmd->tvc_nexus; rc = target_submit_cmd_map_sgls(se_cmd, tv_nexus->tvn_se_sess, - tv_cmd->tvc_cdb, &tv_cmd->tvc_sense_buf[0], - tv_cmd->tvc_lun, tv_cmd->tvc_exp_data_len, - tv_cmd->tvc_task_attr, tv_cmd->tvc_data_direction, - 0, sg_ptr, tv_cmd->tvc_sgl_count, + cmd->tvc_cdb, &cmd->tvc_sense_buf[0], + cmd->tvc_lun, cmd->tvc_exp_data_len, + cmd->tvc_task_attr, cmd->tvc_data_direction, + 0, sg_ptr, cmd->tvc_sgl_count, sg_bidi_ptr, sg_no_bidi); if (rc < 0) { transport_send_check_condition_and_sense(se_cmd, @@ -891,7 +891,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) struct tcm_vhost_tpg **vs_tpg; struct virtio_scsi_cmd_req v_req; struct tcm_vhost_tpg *tpg; - struct tcm_vhost_cmd *tv_cmd; + struct tcm_vhost_cmd *cmd; u32 exp_data_len, data_first, data_num, data_direction; unsigned out, in, i; int head, ret; @@ -988,46 +988,46 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) for (i = 0; i < data_num; i++) exp_data_len += vq->iov[data_first + i].iov_len; - tv_cmd = vhost_scsi_allocate_cmd(vq, tpg, &v_req, + cmd = vhost_scsi_allocate_cmd(vq, tpg, &v_req, exp_data_len, data_direction); - if (IS_ERR(tv_cmd)) { + if (IS_ERR(cmd)) { vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n", - PTR_ERR(tv_cmd)); + PTR_ERR(cmd)); goto err_cmd; } pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction" - ": %d\n", tv_cmd, exp_data_len, data_direction); + ": %d\n", cmd, exp_data_len, data_direction); - tv_cmd->tvc_vhost = vs; - tv_cmd->tvc_vq = vq; - tv_cmd->tvc_resp = vq->iov[out].iov_base; + cmd->tvc_vhost = vs; + cmd->tvc_vq = vq; + cmd->tvc_resp = vq->iov[out].iov_base; /* - * Copy in the recieved CDB descriptor into tv_cmd->tvc_cdb + * Copy in the recieved CDB descriptor into cmd->tvc_cdb * that will be used by tcm_vhost_new_cmd_map() and down into * target_setup_cmd_from_cdb() */ - memcpy(tv_cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE); + memcpy(cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE); /* * Check that the recieved CDB size does not exceeded our * hardcoded max for tcm_vhost */ /* TODO what if cdb was too small for varlen cdb header? */ - if (unlikely(scsi_command_size(tv_cmd->tvc_cdb) > + if (unlikely(scsi_command_size(cmd->tvc_cdb) > TCM_VHOST_MAX_CDB_SIZE)) { vq_err(vq, "Received SCSI CDB with command_size: %d that" " exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", - scsi_command_size(tv_cmd->tvc_cdb), + scsi_command_size(cmd->tvc_cdb), TCM_VHOST_MAX_CDB_SIZE); goto err_free; } - tv_cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; + cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", - tv_cmd->tvc_cdb[0], tv_cmd->tvc_lun); + cmd->tvc_cdb[0], cmd->tvc_lun); if (data_direction != DMA_NONE) { - ret = vhost_scsi_map_iov_to_sgl(tv_cmd, + ret = vhost_scsi_map_iov_to_sgl(cmd, &vq->iov[data_first], data_num, data_direction == DMA_TO_DEVICE); if (unlikely(ret)) { @@ -1041,22 +1041,22 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) * complete the virtio-scsi request in TCM callback context via * tcm_vhost_queue_data_in() and tcm_vhost_queue_status() */ - tv_cmd->tvc_vq_desc = head; + cmd->tvc_vq_desc = head; /* * Dispatch tv_cmd descriptor for cmwq execution in process * context provided by tcm_vhost_workqueue. This also ensures * tv_cmd is executed on the same kworker CPU as this vhost * thread to gain positive L2 cache locality effects.. */ - INIT_WORK(&tv_cmd->work, tcm_vhost_submission_work); - queue_work(tcm_vhost_workqueue, &tv_cmd->work); + INIT_WORK(&cmd->work, tcm_vhost_submission_work); + queue_work(tcm_vhost_workqueue, &cmd->work); } mutex_unlock(&vq->mutex); return; err_free: - vhost_scsi_free_cmd(tv_cmd); + vhost_scsi_free_cmd(cmd); err_cmd: vhost_scsi_send_bad_target(vs, vq, head, out); mutex_unlock(&vq->mutex); -- GitLab From 6ac1afbf6132df0fcb0898f3509371305af7de16 Mon Sep 17 00:00:00 2001 From: Asias He Date: Mon, 6 May 2013 16:38:21 +0800 Subject: [PATCH 2361/2900] vhost: Make vhost a separate module Currently, vhost-net and vhost-scsi are sharing the vhost core code. However, vhost-scsi shares the code by including the vhost.c file directly. Making vhost a separate module makes it is easier to share code with other vhost devices. Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/Kconfig | 8 +++++++ drivers/vhost/Makefile | 3 ++- drivers/vhost/scsi.c | 1 - drivers/vhost/test.c | 2 +- drivers/vhost/vhost.c | 51 +++++++++++++++++++++++++++++++++++++++++- drivers/vhost/vhost.h | 2 ++ 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 8b9226da3f54..017a1e8a8f6f 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -1,6 +1,7 @@ config VHOST_NET tristate "Host kernel accelerator for virtio net" depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP) + select VHOST select VHOST_RING ---help--- This kernel module can be loaded in host kernel to accelerate @@ -13,6 +14,7 @@ config VHOST_NET config VHOST_SCSI tristate "VHOST_SCSI TCM fabric driver" depends on TARGET_CORE && EVENTFD && m + select VHOST select VHOST_RING default n ---help--- @@ -24,3 +26,9 @@ config VHOST_RING ---help--- This option is selected by any driver which needs to access the host side of a virtio ring. + +config VHOST + tristate + ---help--- + This option is selected by any driver which needs to access + the core of vhost. diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile index 654e9afb11f5..e0441c34db1c 100644 --- a/drivers/vhost/Makefile +++ b/drivers/vhost/Makefile @@ -1,7 +1,8 @@ obj-$(CONFIG_VHOST_NET) += vhost_net.o -vhost_net-y := vhost.o net.o +vhost_net-y := net.o obj-$(CONFIG_VHOST_SCSI) += vhost_scsi.o vhost_scsi-y := scsi.o obj-$(CONFIG_VHOST_RING) += vringh.o +obj-$(CONFIG_VHOST) += vhost.o diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 03765e17c154..5531ebcc7276 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -49,7 +49,6 @@ #include #include -#include "vhost.c" #include "vhost.h" #define TCM_VHOST_VERSION "v0.1" diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 1ee45bc85f67..9b71a577f7bd 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -18,7 +18,7 @@ #include #include "test.h" -#include "vhost.c" +#include "vhost.h" /* Max number of bytes transferred before requeueing the job. * Using this limit prevents one virtqueue from starving others. */ diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 4d135b1a861e..e58cf0001cee 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "vhost.h" @@ -66,6 +67,7 @@ void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) work->flushing = 0; work->queue_seq = work->done_seq = 0; } +EXPORT_SYMBOL_GPL(vhost_work_init); /* Init poll structure */ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, @@ -79,6 +81,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, vhost_work_init(&poll->work, fn); } +EXPORT_SYMBOL_GPL(vhost_poll_init); /* Start polling a file. We add ourselves to file's wait queue. The caller must * keep a reference to a file until after vhost_poll_stop is called. */ @@ -101,6 +104,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file) return ret; } +EXPORT_SYMBOL_GPL(vhost_poll_start); /* Stop polling a file. After this function returns, it becomes safe to drop the * file reference. You must also flush afterwards. */ @@ -111,6 +115,7 @@ void vhost_poll_stop(struct vhost_poll *poll) poll->wqh = NULL; } } +EXPORT_SYMBOL_GPL(vhost_poll_stop); static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, unsigned seq) @@ -123,7 +128,7 @@ static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, return left <= 0; } -static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) +void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) { unsigned seq; int flushing; @@ -138,6 +143,7 @@ static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) spin_unlock_irq(&dev->work_lock); BUG_ON(flushing < 0); } +EXPORT_SYMBOL_GPL(vhost_work_flush); /* Flush any work that has been scheduled. When calling this, don't hold any * locks that are also used by the callback. */ @@ -145,6 +151,7 @@ void vhost_poll_flush(struct vhost_poll *poll) { vhost_work_flush(poll->dev, &poll->work); } +EXPORT_SYMBOL_GPL(vhost_poll_flush); void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) { @@ -158,11 +165,13 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) } spin_unlock_irqrestore(&dev->work_lock, flags); } +EXPORT_SYMBOL_GPL(vhost_work_queue); void vhost_poll_queue(struct vhost_poll *poll) { vhost_work_queue(poll->dev, &poll->work); } +EXPORT_SYMBOL_GPL(vhost_poll_queue); static void vhost_vq_reset(struct vhost_dev *dev, struct vhost_virtqueue *vq) @@ -311,6 +320,7 @@ long vhost_dev_init(struct vhost_dev *dev, return 0; } +EXPORT_SYMBOL_GPL(vhost_dev_init); /* Caller should have device mutex */ long vhost_dev_check_owner(struct vhost_dev *dev) @@ -318,6 +328,7 @@ long vhost_dev_check_owner(struct vhost_dev *dev) /* Are you the owner? If not, I don't think you mean to do that */ return dev->mm == current->mm ? 0 : -EPERM; } +EXPORT_SYMBOL_GPL(vhost_dev_check_owner); struct vhost_attach_cgroups_struct { struct vhost_work work; @@ -349,6 +360,7 @@ bool vhost_dev_has_owner(struct vhost_dev *dev) { return dev->mm; } +EXPORT_SYMBOL_GPL(vhost_dev_has_owner); /* Caller should have device mutex */ long vhost_dev_set_owner(struct vhost_dev *dev) @@ -392,11 +404,13 @@ long vhost_dev_set_owner(struct vhost_dev *dev) err_mm: return err; } +EXPORT_SYMBOL_GPL(vhost_dev_set_owner); struct vhost_memory *vhost_dev_reset_owner_prepare(void) { return kmalloc(offsetof(struct vhost_memory, regions), GFP_KERNEL); } +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare); /* Caller should have device mutex */ void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_memory *memory) @@ -407,6 +421,7 @@ void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_memory *memory) memory->nregions = 0; RCU_INIT_POINTER(dev->memory, memory); } +EXPORT_SYMBOL_GPL(vhost_dev_reset_owner); void vhost_dev_stop(struct vhost_dev *dev) { @@ -419,6 +434,7 @@ void vhost_dev_stop(struct vhost_dev *dev) } } } +EXPORT_SYMBOL_GPL(vhost_dev_stop); /* Caller should have device mutex if and only if locked is set */ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) @@ -459,6 +475,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) mmput(dev->mm); dev->mm = NULL; } +EXPORT_SYMBOL_GPL(vhost_dev_cleanup); static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) { @@ -544,6 +561,7 @@ int vhost_log_access_ok(struct vhost_dev *dev) lockdep_is_held(&dev->mutex)); return memory_access_ok(dev, mp, 1); } +EXPORT_SYMBOL_GPL(vhost_log_access_ok); /* Verify access for write logging. */ /* Caller should have vq mutex and device mutex */ @@ -569,6 +587,7 @@ int vhost_vq_access_ok(struct vhost_virtqueue *vq) return vq_access_ok(vq->dev, vq->num, vq->desc, vq->avail, vq->used) && vq_log_access_ok(vq->dev, vq, vq->log_base); } +EXPORT_SYMBOL_GPL(vhost_vq_access_ok); static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) { @@ -798,6 +817,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) vhost_poll_flush(&vq->poll); return r; } +EXPORT_SYMBOL_GPL(vhost_vring_ioctl); /* Caller must have device mutex */ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) @@ -878,6 +898,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) done: return r; } +EXPORT_SYMBOL_GPL(vhost_dev_ioctl); static const struct vhost_memory_region *find_region(struct vhost_memory *mem, __u64 addr, __u32 len) @@ -969,6 +990,7 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, BUG(); return 0; } +EXPORT_SYMBOL_GPL(vhost_log_write); static int vhost_update_used_flags(struct vhost_virtqueue *vq) { @@ -1020,6 +1042,7 @@ int vhost_init_used(struct vhost_virtqueue *vq) vq->signalled_used_valid = false; return get_user(vq->last_used_idx, &vq->used->idx); } +EXPORT_SYMBOL_GPL(vhost_init_used); static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, struct iovec iov[], int iov_size) @@ -1296,12 +1319,14 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, BUG_ON(!(vq->used_flags & VRING_USED_F_NO_NOTIFY)); return head; } +EXPORT_SYMBOL_GPL(vhost_get_vq_desc); /* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */ void vhost_discard_vq_desc(struct vhost_virtqueue *vq, int n) { vq->last_avail_idx -= n; } +EXPORT_SYMBOL_GPL(vhost_discard_vq_desc); /* After we've used one of their buffers, we tell them about it. We'll then * want to notify the guest, using eventfd. */ @@ -1350,6 +1375,7 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) vq->signalled_used_valid = false; return 0; } +EXPORT_SYMBOL_GPL(vhost_add_used); static int __vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, @@ -1419,6 +1445,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads, } return r; } +EXPORT_SYMBOL_GPL(vhost_add_used_n); static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) { @@ -1463,6 +1490,7 @@ void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) if (vq->call_ctx && vhost_notify(dev, vq)) eventfd_signal(vq->call_ctx, 1); } +EXPORT_SYMBOL_GPL(vhost_signal); /* And here's the combo meal deal. Supersize me! */ void vhost_add_used_and_signal(struct vhost_dev *dev, @@ -1472,6 +1500,7 @@ void vhost_add_used_and_signal(struct vhost_dev *dev, vhost_add_used(vq, head, len); vhost_signal(dev, vq); } +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal); /* multi-buffer version of vhost_add_used_and_signal */ void vhost_add_used_and_signal_n(struct vhost_dev *dev, @@ -1481,6 +1510,7 @@ void vhost_add_used_and_signal_n(struct vhost_dev *dev, vhost_add_used_n(vq, heads, count); vhost_signal(dev, vq); } +EXPORT_SYMBOL_GPL(vhost_add_used_and_signal_n); /* OK, now we need to know about added descriptors. */ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) @@ -1518,6 +1548,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) return avail_idx != vq->avail_idx; } +EXPORT_SYMBOL_GPL(vhost_enable_notify); /* We don't need to be notified again. */ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) @@ -1534,3 +1565,21 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) &vq->used->flags, r); } } +EXPORT_SYMBOL_GPL(vhost_disable_notify); + +static int __init vhost_init(void) +{ + return 0; +} + +static void __exit vhost_exit(void) +{ +} + +module_init(vhost_init); +module_exit(vhost_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael S. Tsirkin"); +MODULE_DESCRIPTION("Host kernel accelerator for virtio"); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 64adcf99ff33..42298cd23c73 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -46,6 +46,8 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file); void vhost_poll_stop(struct vhost_poll *poll); void vhost_poll_flush(struct vhost_poll *poll); void vhost_poll_queue(struct vhost_poll *poll); +void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work); +long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp); struct vhost_log { u64 addr; -- GitLab From 0a1febf7baafe2de156e0fadd15afb7ebec5d74f Mon Sep 17 00:00:00 2001 From: Asias He Date: Wed, 5 Jun 2013 21:17:38 +0800 Subject: [PATCH 2362/2900] vhost: Make local function static $ make C=1 M=drivers/vhost drivers/vhost/net.c:168:5: warning: symbol 'vhost_net_set_ubuf_info' was not declared. Should it be static? drivers/vhost/net.c:194:6: warning: symbol 'vhost_net_vq_reset' was not declared. Should it be static? drivers/vhost/scsi.c:219:6: warning: symbol 'tcm_vhost_done_inflight' was not declared. Should it be static? Signed-off-by: Asias He Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 4 ++-- drivers/vhost/scsi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 8ca5ac71b845..027be91db139 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -168,7 +168,7 @@ static void vhost_net_clear_ubuf_info(struct vhost_net *n) } } -int vhost_net_set_ubuf_info(struct vhost_net *n) +static int vhost_net_set_ubuf_info(struct vhost_net *n) { bool zcopy; int i; @@ -189,7 +189,7 @@ int vhost_net_set_ubuf_info(struct vhost_net *n) return -ENOMEM; } -void vhost_net_vq_reset(struct vhost_net *n) +static void vhost_net_vq_reset(struct vhost_net *n) { int i; diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 5531ebcc7276..4264840ef7dc 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -216,7 +216,7 @@ static int iov_num_pages(struct iovec *iov) ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT; } -void tcm_vhost_done_inflight(struct kref *kref) +static void tcm_vhost_done_inflight(struct kref *kref) { struct vhost_scsi_inflight *inflight; -- GitLab From 09a34c8404c1d4c5782de319c02e1d742c57875c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 7 Jul 2013 17:12:36 +0300 Subject: [PATCH 2363/2900] vhost/test: update test after vhost cleanups We changed the type of dev.vqs field, update test module accordingly. Signed-off-by: Michael S. Tsirkin --- drivers/vhost/test.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 9b71a577f7bd..a73ea217f24d 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -38,17 +38,19 @@ struct vhost_test { * read-size critical section for our kind of RCU. */ static void handle_vq(struct vhost_test *n) { - struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ]; + struct vhost_virtqueue *vq = &n->vqs[VHOST_TEST_VQ]; unsigned out, in; int head; size_t len, total_len = 0; void *private; - private = rcu_dereference_check(vq->private_data, 1); - if (!private) + mutex_lock(&vq->mutex); + private = vq->private_data; + if (!private) { + mutex_unlock(&vq->mutex); return; + } - mutex_lock(&vq->mutex); vhost_disable_notify(&n->dev, vq); for (;;) { @@ -102,15 +104,23 @@ static int vhost_test_open(struct inode *inode, struct file *f) { struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL); struct vhost_dev *dev; + struct vhost_virtqueue **vqs; int r; if (!n) return -ENOMEM; + vqs = kmalloc(VHOST_TEST_VQ_MAX * sizeof(*vqs), GFP_KERNEL); + if (!vqs) { + kfree(n); + return -ENOMEM; + } dev = &n->dev; + vqs[VHOST_TEST_VQ] = &n->vqs[VHOST_TEST_VQ]; n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick; - r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX); + r = vhost_dev_init(dev, vqs, VHOST_TEST_VQ_MAX); if (r < 0) { + kfree(vqs); kfree(n); return r; } @@ -126,9 +136,8 @@ static void *vhost_test_stop_vq(struct vhost_test *n, void *private; mutex_lock(&vq->mutex); - private = rcu_dereference_protected(vq->private_data, - lockdep_is_held(&vq->mutex)); - rcu_assign_pointer(vq->private_data, NULL); + private = vq->private_data; + vq->private_data = NULL; mutex_unlock(&vq->mutex); return private; } @@ -140,7 +149,7 @@ static void vhost_test_stop(struct vhost_test *n, void **privatep) static void vhost_test_flush_vq(struct vhost_test *n, int index) { - vhost_poll_flush(&n->dev.vqs[index].poll); + vhost_poll_flush(&n->vqs[index].poll); } static void vhost_test_flush(struct vhost_test *n) @@ -268,14 +277,14 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl, return -EFAULT; return vhost_test_run(n, test); case VHOST_GET_FEATURES: - features = VHOST_NET_FEATURES; + features = VHOST_FEATURES; if (copy_to_user(featurep, &features, sizeof features)) return -EFAULT; return 0; case VHOST_SET_FEATURES: if (copy_from_user(&features, featurep, sizeof features)) return -EFAULT; - if (features & ~VHOST_NET_FEATURES) + if (features & ~VHOST_FEATURES) return -EOPNOTSUPP; return vhost_test_set_features(n, features); case VHOST_RESET_OWNER: -- GitLab From 0fa8103be4c20f893486c533e4c6dfbc5ccddeb4 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 4 Jul 2013 08:33:22 +0800 Subject: [PATCH 2364/2900] mm/slab: Fix drain freelist excessively The drain_freelist is called to drain slabs_free lists for cache reap, cache shrink, memory hotplug callback etc. The tofree parameter should be the number of slab to free instead of the number of slab objects to free. This patch fix the callers that pass # of objects. Make sure they pass # of slabs. Acked-by: Christoph Lameter Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slab.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 273a5ac2ade3..c9b4da9a1fe5 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1180,6 +1180,12 @@ static int init_cache_node_node(int node) return 0; } +static inline int slabs_tofree(struct kmem_cache *cachep, + struct kmem_cache_node *n) +{ + return (n->free_objects + cachep->num - 1) / cachep->num; +} + static void __cpuinit cpuup_canceled(long cpu) { struct kmem_cache *cachep; @@ -1241,7 +1247,7 @@ static void __cpuinit cpuup_canceled(long cpu) n = cachep->node[node]; if (!n) continue; - drain_freelist(cachep, n, n->free_objects); + drain_freelist(cachep, n, slabs_tofree(cachep, n)); } } @@ -1408,7 +1414,7 @@ static int __meminit drain_cache_node_node(int node) if (!n) continue; - drain_freelist(cachep, n, n->free_objects); + drain_freelist(cachep, n, slabs_tofree(cachep, n)); if (!list_empty(&n->slabs_full) || !list_empty(&n->slabs_partial)) { @@ -2534,7 +2540,7 @@ static int __cache_shrink(struct kmem_cache *cachep) if (!n) continue; - drain_freelist(cachep, n, n->free_objects); + drain_freelist(cachep, n, slabs_tofree(cachep, n)); ret += !list_empty(&n->slabs_full) || !list_empty(&n->slabs_partial); -- GitLab From e25839f67948ca54fa55a45686d72c266f65f099 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 4 Jul 2013 08:33:23 +0800 Subject: [PATCH 2365/2900] mm/slab: Sharing s_next and s_stop between slab and slub This patch shares s_next and s_stop between slab and slub. Acked-by: Christoph Lameter Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slab.c | 10 ---------- mm/slab.h | 3 +++ mm/slab_common.c | 4 ++-- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index c9b4da9a1fe5..4a907a072669 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4438,16 +4438,6 @@ static int leaks_show(struct seq_file *m, void *p) return 0; } -static void *s_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &slab_caches, pos); -} - -static void s_stop(struct seq_file *m, void *p) -{ - mutex_unlock(&slab_mutex); -} - static const struct seq_operations slabstats_op = { .start = leaks_start, .next = s_next, diff --git a/mm/slab.h b/mm/slab.h index f96b49e4704e..95c88604aab7 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -271,3 +271,6 @@ struct kmem_cache_node { #endif }; + +void *s_next(struct seq_file *m, void *p, loff_t *pos); +void s_stop(struct seq_file *m, void *p); diff --git a/mm/slab_common.c b/mm/slab_common.c index d2517b05d5bc..68518eb67229 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -529,12 +529,12 @@ static void *s_start(struct seq_file *m, loff_t *pos) return seq_list_start(&slab_caches, *pos); } -static void *s_next(struct seq_file *m, void *p, loff_t *pos) +void *s_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } -static void s_stop(struct seq_file *m, void *p) +void s_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } -- GitLab From e9b4db2b8dba6b6c666e54b20ce46f3e597a6d96 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 4 Jul 2013 08:33:24 +0800 Subject: [PATCH 2366/2900] mm/slab: Fix /proc/slabinfo unwriteable for slab Slab have some tunables like limit, batchcount, and sharedfactor can be tuned through function slabinfo_write. Commit (b7454ad3: mm/sl[au]b: Move slabinfo processing to slab_common.c) uncorrectly change /proc/slabinfo unwriteable for slab, this patch fix it by revert to original mode. Acked-by: Christoph Lameter Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slab_common.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mm/slab_common.c b/mm/slab_common.c index 68518eb67229..13ae037c71d4 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -495,6 +495,13 @@ void __init create_kmalloc_caches(unsigned long flags) #ifdef CONFIG_SLABINFO + +#ifdef CONFIG_SLAB +#define SLABINFO_RIGHTS (S_IWUSR | S_IRUSR) +#else +#define SLABINFO_RIGHTS S_IRUSR +#endif + void print_slabinfo_header(struct seq_file *m) { /* @@ -631,7 +638,8 @@ static const struct file_operations proc_slabinfo_operations = { static int __init slab_proc_init(void) { - proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); + proc_create("slabinfo", SLABINFO_RIGHTS, NULL, + &proc_slabinfo_operations); return 0; } module_init(slab_proc_init); -- GitLab From a446336454cf9ce3234a6013d1c3b482358d9459 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 4 Jul 2013 08:33:25 +0800 Subject: [PATCH 2367/2900] mm/slub: Drop unnecessary nr_partials This patch remove unused nr_partials variable. Acked-by: Christoph Lameter Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slub.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 4df2c0c337fb..f788be3a0b12 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5266,7 +5266,6 @@ __initcall(slab_sysfs_init); #ifdef CONFIG_SLABINFO void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) { - unsigned long nr_partials = 0; unsigned long nr_slabs = 0; unsigned long nr_objs = 0; unsigned long nr_free = 0; @@ -5278,7 +5277,6 @@ void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) if (!n) continue; - nr_partials += n->nr_partial; nr_slabs += atomic_long_read(&n->nr_slabs); nr_objs += atomic_long_read(&n->total_objects); nr_free += count_partial(n, count_free); -- GitLab From c17fd13ec0677e61f3692ecb9d4b21f79848fa04 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Thu, 4 Jul 2013 08:33:26 +0800 Subject: [PATCH 2368/2900] mm/slub: Use node_nr_slabs and node_nr_objs in get_slabinfo Use existing interface node_nr_slabs and node_nr_objs to get nr_slabs and nr_objs. Acked-by: Christoph Lameter Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index f788be3a0b12..5ee6c7cd9fc4 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -5277,8 +5277,8 @@ void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) if (!n) continue; - nr_slabs += atomic_long_read(&n->nr_slabs); - nr_objs += atomic_long_read(&n->total_objects); + nr_slabs += node_nr_slabs(n); + nr_objs += node_nr_objs(n); nr_free += count_partial(n, count_free); } -- GitLab From 318df36e57c0ca9f2146660d41ff28e8650af423 Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Wed, 19 Jun 2013 15:33:55 +0900 Subject: [PATCH 2369/2900] slub: do not put a slab to cpu partial list when cpu_partial is 0 In free path, we don't check number of cpu_partial, so one slab can be linked in cpu partial list even if cpu_partial is 0. To prevent this, we should check number of cpu_partial in put_cpu_partial(). Acked-by: Christoph Lameeter Reviewed-by: Wanpeng Li Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg --- mm/slub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/slub.c b/mm/slub.c index 5ee6c7cd9fc4..54cc4d544f3c 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1954,6 +1954,9 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) int pages; int pobjects; + if (!s->cpu_partial) + return; + do { pages = 0; pobjects = 0; -- GitLab From a6d78159f8a717263bea71bef738256dafe6260d Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 20 Dec 2012 14:11:39 -0500 Subject: [PATCH 2370/2900] slob: use DIV_ROUND_UP where possible Acked-by: Christoph Lameter Signed-off-by: Sasha Levin Signed-off-by: Pekka Enberg --- mm/slob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slob.c b/mm/slob.c index a99fdf7a0907..f729c46639fa 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -122,7 +122,7 @@ static inline void clear_slob_page_free(struct page *sp) } #define SLOB_UNIT sizeof(slob_t) -#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT) +#define SLOB_UNITS(size) DIV_ROUND_UP(size, SLOB_UNIT) /* * struct slob_rcu is inserted at the tail of allocated slob blocks, which -- GitLab From 0f8f8094d28eb53368ac09186ea6b3a324cc7d44 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Tue, 2 Jul 2013 12:12:10 -0700 Subject: [PATCH 2371/2900] slab: fix init_lock_keys Some architectures (e.g. powerpc built with CONFIG_PPC_256K_PAGES=y CONFIG_FORCE_MAX_ZONEORDER=11) get PAGE_SHIFT + MAX_ORDER > 26. In 3.10 kernels, CONFIG_LOCKDEP=y with PAGE_SHIFT + MAX_ORDER > 26 makes init_lock_keys() dereference beyond kmalloc_caches[26]. This leads to an unbootable system (kernel panic at initializing SLAB) if one of kmalloc_caches[26...PAGE_SHIFT+MAX_ORDER-1] is not NULL. Fix this by making sure that init_lock_keys() does not dereference beyond kmalloc_caches[26] arrays. Signed-off-by: Christoph Lameter Reported-by: Tetsuo Handa Cc: Pekka Enberg Cc: [3.10.x] Signed-off-by: Andrew Morton Signed-off-by: Pekka Enberg --- mm/slab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slab.c b/mm/slab.c index 4a907a072669..9bf225162fcb 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -565,7 +565,7 @@ static void init_node_lock_keys(int q) if (slab_state < UP) return; - for (i = 1; i < PAGE_SHIFT + MAX_ORDER; i++) { + for (i = 1; i <= KMALLOC_SHIFT_HIGH; i++) { struct kmem_cache_node *n; struct kmem_cache *cache = kmalloc_caches[i]; -- GitLab From e7efa615ccf78394338144ff0187be331240748a Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 25 Jun 2013 18:16:55 +0200 Subject: [PATCH 2372/2900] slab: add kmalloc() to kernel API documentation At the moment, kmalloc() isn't even listed in the kernel API documentation (DocBook/kernel-api.html after running "make htmldocs"). Another issue is that the documentation for kmalloc_node() refers to kcalloc()'s documentation to describe its 'flags' parameter, while kcalloc() refered to kmalloc()'s documentation, which doesn't exist! This patch is a proposed fix for this. It also removes the documentation for kmalloc() in include/linux/slob_def.h which isn't included to generate the documentation anyway. This way, kmalloc() is described in only one place. Acked-by: Christoph Lameter Acked-by: Randy Dunlap Signed-off-by: Michael Opdenacker Signed-off-by: Pekka Enberg --- include/linux/slab.h | 18 ++++++++++++++---- include/linux/slob_def.h | 8 -------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 9690c14eb7fb..6c5cc0ea8713 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -373,9 +373,8 @@ int cache_show(struct kmem_cache *s, struct seq_file *m); void print_slabinfo_header(struct seq_file *m); /** - * kmalloc_array - allocate memory for an array. - * @n: number of elements. - * @size: element size. + * kmalloc - allocate memory + * @size: how many bytes of memory are required. * @flags: the type of memory to allocate. * * The @flags argument may be one of: @@ -422,6 +421,17 @@ void print_slabinfo_header(struct seq_file *m); * There are other flags available as well, but these are not intended * for general use, and so are not documented here. For a full list of * potential flags, always refer to linux/gfp.h. + * + * kmalloc is the normal method of allocating memory + * in the kernel. + */ +static __always_inline void *kmalloc(size_t size, gfp_t flags); + +/** + * kmalloc_array - allocate memory for an array. + * @n: number of elements. + * @size: element size. + * @flags: the type of memory to allocate (see kmalloc). */ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) { @@ -445,7 +455,7 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags) /** * kmalloc_node - allocate memory from a specific node * @size: how many bytes of memory are required. - * @flags: the type of memory to allocate (see kcalloc). + * @flags: the type of memory to allocate (see kmalloc). * @node: node to allocate from. * * kmalloc() for non-local nodes, used to allocate from a specific node diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h index f28e14a12e3f..095a5a4a8516 100644 --- a/include/linux/slob_def.h +++ b/include/linux/slob_def.h @@ -18,14 +18,6 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) return __kmalloc_node(size, flags, node); } -/** - * kmalloc - allocate memory - * @size: how many bytes of memory are required. - * @flags: the type of memory to allocate (see kcalloc). - * - * kmalloc is the normal method of allocating memory - * in the kernel. - */ static __always_inline void *kmalloc(size_t size, gfp_t flags) { return __kmalloc_node(size, flags, NUMA_NO_NODE); -- GitLab From 345c905d13a4ec9f774b6b4bc038fe4aef26cced Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Wed, 19 Jun 2013 14:05:52 +0900 Subject: [PATCH 2373/2900] slub: Make cpu partial slab support configurable CPU partial support can introduce level of indeterminism that is not wanted in certain context (like a realtime kernel). Make it configurable. This patch is based on Christoph Lameter's "slub: Make cpu partial slab support configurable V2". Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg --- init/Kconfig | 11 +++++++++++ mm/slub.c | 27 +++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 7d30240e5bfe..3b34a88cf34e 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1511,6 +1511,17 @@ config SLOB endchoice +config SLUB_CPU_PARTIAL + default y + depends on SLUB + bool "SLUB per cpu partial cache" + help + Per cpu partial caches accellerate objects allocation and freeing + that is local to a processor at the price of more indeterminism + in the latency of the free. On overflow these caches will be cleared + which requires the taking of locks that may cause latency spikes. + Typically one would choose no for a realtime system. + config MMAP_ALLOW_UNINITIALIZED bool "Allow mmapped anonymous memory to be uninitialized" depends on EXPERT && !MMU diff --git a/mm/slub.c b/mm/slub.c index 54cc4d544f3c..ef60536c5d69 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -122,6 +122,15 @@ static inline int kmem_cache_debug(struct kmem_cache *s) #endif } +static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s) +{ +#ifdef CONFIG_SLUB_CPU_PARTIAL + return !kmem_cache_debug(s); +#else + return false; +#endif +} + /* * Issues still to be resolved: * @@ -1572,7 +1581,8 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, put_cpu_partial(s, page, 0); stat(s, CPU_PARTIAL_NODE); } - if (kmem_cache_debug(s) || available > s->cpu_partial / 2) + if (!kmem_cache_has_cpu_partial(s) + || available > s->cpu_partial / 2) break; } @@ -1883,6 +1893,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freel static void unfreeze_partials(struct kmem_cache *s, struct kmem_cache_cpu *c) { +#ifdef CONFIG_SLUB_CPU_PARTIAL struct kmem_cache_node *n = NULL, *n2 = NULL; struct page *page, *discard_page = NULL; @@ -1937,6 +1948,7 @@ static void unfreeze_partials(struct kmem_cache *s, discard_slab(s, page); stat(s, FREE_SLAB); } +#endif } /* @@ -1950,6 +1962,7 @@ static void unfreeze_partials(struct kmem_cache *s, */ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) { +#ifdef CONFIG_SLUB_CPU_PARTIAL struct page *oldpage; int pages; int pobjects; @@ -1989,6 +2002,7 @@ static void put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) page->next = oldpage; } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage); +#endif } static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) @@ -2497,7 +2511,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, new.inuse--; if ((!new.inuse || !prior) && !was_frozen) { - if (!kmem_cache_debug(s) && !prior) + if (kmem_cache_has_cpu_partial(s) && !prior) /* * Slab was on no list before and will be partially empty @@ -2552,8 +2566,9 @@ static void __slab_free(struct kmem_cache *s, struct page *page, * Objects left in the slab. If it was not on the partial list before * then add it. */ - if (kmem_cache_debug(s) && unlikely(!prior)) { - remove_full(s, page); + if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) { + if (kmem_cache_debug(s)) + remove_full(s, page); add_partial(n, page, DEACTIVATE_TO_TAIL); stat(s, FREE_ADD_PARTIAL); } @@ -3061,7 +3076,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) * per node list when we run out of per cpu objects. We only fetch 50% * to keep some capacity around for frees. */ - if (kmem_cache_debug(s)) + if (!kmem_cache_has_cpu_partial(s)) s->cpu_partial = 0; else if (s->size >= PAGE_SIZE) s->cpu_partial = 2; @@ -4456,7 +4471,7 @@ static ssize_t cpu_partial_store(struct kmem_cache *s, const char *buf, err = strict_strtoul(buf, 10, &objects); if (err) return err; - if (objects && kmem_cache_debug(s)) + if (objects && !kmem_cache_has_cpu_partial(s)) return -EINVAL; s->cpu_partial = objects; -- GitLab From c1e854e924f354657ea2ad08fd7b38aac81c59b1 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 17 Jan 2013 12:13:46 -0500 Subject: [PATCH 2374/2900] slob: Check for NULL pointer before calling ctor() While doing some code inspection, I noticed that the slob constructor method can be called with a NULL pointer. If memory is tight and slob fails to allocate with slob_alloc() or slob_new_pages() it still calls the ctor() method with a NULL pointer. Looking at the first ctor() method I found, I noticed that it can not handle a NULL pointer (I'm sure others probably can't either): static void sighand_ctor(void *data) { struct sighand_struct *sighand = data; spin_lock_init(&sighand->siglock); init_waitqueue_head(&sighand->signalfd_wqh); } The solution is to only call the ctor() method if allocation succeeded. Acked-by: Christoph Lameter Signed-off-by: Steven Rostedt Signed-off-by: Pekka Enberg --- mm/slob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slob.c b/mm/slob.c index f729c46639fa..3d73b3b8fb1d 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -554,7 +554,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) flags, node); } - if (c->ctor) + if (b && c->ctor) c->ctor(b); kmemleak_alloc_recursive(b, c->size, 1, c->flags, flags); -- GitLab From b2cb96494d83b894a43ba8b9023eead8ff50684b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Jul 2013 03:05:37 -0700 Subject: [PATCH 2375/2900] iser-target: Fix session reset bug with RDMA_CM_EVENT_DISCONNECTED This patch addresses a bug where RDMA_CM_EVENT_DISCONNECTED may occur before the connection shutdown has been completed by rx/tx threads, that causes isert_free_conn() to wait indefinately on ->conn_wait. This patch allows isert_disconnect_work code to invoke rdma_disconnect when isert_disconnect_work() process context is started by client session reset before isert_free_conn() code has been reached. It also adds isert_conn->conn_mutex protection for ->state within isert_disconnect_work(), isert_cq_comp_err() and isert_free_conn() code, along with isert_check_state() for wait_event usage. (v2: Add explicit iscsit_cause_connection_reinstatement call during isert_disconnect_work() to force conn reset) Cc: stable@vger.kernel.org # 3.10+ Cc: Or Gerlitz Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 70 ++++++++++++++++++++---- drivers/infiniband/ulp/isert/ib_isert.h | 1 + drivers/target/iscsi/iscsi_target_erl0.c | 1 + include/target/iscsi/iscsi_transport.h | 4 ++ 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 9efbf13007e4..d6cc5999d793 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -388,6 +388,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) init_waitqueue_head(&isert_conn->conn_wait_comp_err); kref_init(&isert_conn->conn_kref); kref_get(&isert_conn->conn_kref); + mutex_init(&isert_conn->conn_mutex); cma_id->context = isert_conn; isert_conn->conn_cm_id = cma_id; @@ -540,15 +541,32 @@ isert_disconnect_work(struct work_struct *work) struct isert_conn, conn_logout_work); pr_debug("isert_disconnect_work(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - + mutex_lock(&isert_conn->conn_mutex); isert_conn->state = ISER_CONN_DOWN; if (isert_conn->post_recv_buf_count == 0 && atomic_read(&isert_conn->post_send_buf_count) == 0) { pr_debug("Calling wake_up(&isert_conn->conn_wait);\n"); - wake_up(&isert_conn->conn_wait); + mutex_unlock(&isert_conn->conn_mutex); + goto wake_up; + } + if (!isert_conn->conn_cm_id) { + mutex_unlock(&isert_conn->conn_mutex); + isert_put_conn(isert_conn); + return; + } + if (!isert_conn->logout_posted) { + pr_debug("Calling rdma_disconnect for !logout_posted from" + " isert_disconnect_work\n"); + rdma_disconnect(isert_conn->conn_cm_id); + mutex_unlock(&isert_conn->conn_mutex); + iscsit_cause_connection_reinstatement(isert_conn->conn, 0); + goto wake_up; } + mutex_unlock(&isert_conn->conn_mutex); +wake_up: + wake_up(&isert_conn->conn_wait); isert_put_conn(isert_conn); } @@ -1439,7 +1457,11 @@ isert_cq_comp_err(struct iser_tx_desc *tx_desc, struct isert_conn *isert_conn) pr_debug("isert_cq_comp_err >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); pr_debug("Calling wake_up from isert_cq_comp_err\n"); - isert_conn->state = ISER_CONN_TERMINATING; + mutex_lock(&isert_conn->conn_mutex); + if (isert_conn->state != ISER_CONN_DOWN) + isert_conn->state = ISER_CONN_TERMINATING; + mutex_unlock(&isert_conn->conn_mutex); + wake_up(&isert_conn->conn_wait_comp_err); } } @@ -2209,6 +2231,17 @@ isert_free_np(struct iscsi_np *np) kfree(isert_np); } +static int isert_check_state(struct isert_conn *isert_conn, int state) +{ + int ret; + + mutex_lock(&isert_conn->conn_mutex); + ret = (isert_conn->state == state); + mutex_unlock(&isert_conn->conn_mutex); + + return ret; +} + static void isert_free_conn(struct iscsi_conn *conn) { struct isert_conn *isert_conn = conn->context; @@ -2218,26 +2251,43 @@ static void isert_free_conn(struct iscsi_conn *conn) * Decrement post_send_buf_count for special case when called * from isert_do_control_comp() -> iscsit_logout_post_handler() */ + mutex_lock(&isert_conn->conn_mutex); if (isert_conn->logout_posted) atomic_dec(&isert_conn->post_send_buf_count); - if (isert_conn->conn_cm_id) + if (isert_conn->conn_cm_id && isert_conn->state != ISER_CONN_DOWN) { + pr_debug("Calling rdma_disconnect from isert_free_conn\n"); rdma_disconnect(isert_conn->conn_cm_id); + } /* * Only wait for conn_wait_comp_err if the isert_conn made it * into full feature phase.. */ - if (isert_conn->state > ISER_CONN_INIT) { + if (isert_conn->state == ISER_CONN_UP) { pr_debug("isert_free_conn: Before wait_event comp_err %d\n", isert_conn->state); + mutex_unlock(&isert_conn->conn_mutex); + wait_event(isert_conn->conn_wait_comp_err, - isert_conn->state == ISER_CONN_TERMINATING); - pr_debug("isert_free_conn: After wait_event #1 >>>>>>>>>>>>\n"); + (isert_check_state(isert_conn, ISER_CONN_TERMINATING))); + + wait_event(isert_conn->conn_wait, + (isert_check_state(isert_conn, ISER_CONN_DOWN))); + + isert_put_conn(isert_conn); + return; + } + if (isert_conn->state == ISER_CONN_INIT) { + mutex_unlock(&isert_conn->conn_mutex); + isert_put_conn(isert_conn); + return; } + pr_debug("isert_free_conn: wait_event conn_wait %d\n", + isert_conn->state); + mutex_unlock(&isert_conn->conn_mutex); - pr_debug("isert_free_conn: wait_event conn_wait %d\n", isert_conn->state); - wait_event(isert_conn->conn_wait, isert_conn->state == ISER_CONN_DOWN); - pr_debug("isert_free_conn: After wait_event #2 >>>>>>>>>>>>>>>>>>>>\n"); + wait_event(isert_conn->conn_wait, + (isert_check_state(isert_conn, ISER_CONN_DOWN))); isert_put_conn(isert_conn); } diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index b104f4c2cd38..5795c82a2306 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -102,6 +102,7 @@ struct isert_conn { struct ib_qp *conn_qp; struct isert_device *conn_device; struct work_struct conn_logout_work; + struct mutex conn_mutex; wait_queue_head_t conn_wait; wait_queue_head_t conn_wait_comp_err; struct kref conn_kref; diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 8f074e0b6099..3722f8dffa68 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -908,6 +908,7 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep) wait_for_completion(&conn->conn_wait_comp); complete(&conn->conn_post_wait_comp); } +EXPORT_SYMBOL(iscsit_cause_connection_reinstatement); void iscsit_fall_back_to_erl0(struct iscsi_session *sess) { diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index ce4070d8f156..e5d09d242ba3 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h @@ -72,6 +72,10 @@ extern int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *); * From iscsi_target_device.c */ extern void iscsit_increment_maxcmdsn(struct iscsi_cmd *, struct iscsi_session *); +/* + * From iscsi_target_erl0.c + */ +extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int); /* * From iscsi_target_erl1.c */ -- GitLab From e5c0d6ad557b32f431a70a4efba820430f6ff88b Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 26 Jun 2013 17:36:17 -0700 Subject: [PATCH 2376/2900] target: Add tracepoints for SCSI commands being processed This patch adds tracepoints to the target code for commands being received and being completed, which is quite useful for debugging interactions with initiators. For example, one can do something like the following to watch commands that are completing unsuccessfully: # echo 'scsi_status!=0' > /sys/kernel/debug/tracing/events/target/target_cmd_complete/filter # echo 1 > /sys/kernel/debug/tracing/events/target/target_cmd_complete/enable # cat /sys/kernel/debug/tracing/trace iscsi_trx-0-1902 [003] ...1 990185.810385: target_cmd_complete: iqn.1993-08.org.debian:01:e51ede6aacfd <- LUN 001 status CHECK CONDITION (sense len 18 / 70 00 05 00 00 00 00 0a 00 00 00 00 20 00 00 00 00 00) 0x95 data_length 512 CDB 95 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (TA:SIMPLE C:00) (v2: Drop undefined COMPARE_AND_WRITE) Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 16 +- include/trace/events/target.h | 214 +++++++++++++++++++++++++ 2 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 include/trace/events/target.h diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ae40addd4ce0..7172d005d063 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -52,6 +52,9 @@ #include "target_core_pr.h" #include "target_core_ua.h" +#define CREATE_TRACE_POINTS +#include + static struct workqueue_struct *target_completion_wq; static struct kmem_cache *se_sess_cache; struct kmem_cache *se_ua_cache; @@ -1123,6 +1126,8 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) */ memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb)); + trace_target_sequencer_start(cmd); + /* * Check for an existing UNIT ATTENTION condition */ @@ -1546,7 +1551,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); - ret = cmd->se_tfo->queue_status(cmd); + trace_target_cmd_complete(cmd); + ret = cmd->se_tfo-> queue_status(cmd); if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; goto check_stop; @@ -1766,6 +1772,7 @@ static void transport_complete_qf(struct se_cmd *cmd) transport_complete_task_attr(cmd); if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) { + trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_status(cmd); if (ret) goto out; @@ -1773,6 +1780,7 @@ static void transport_complete_qf(struct se_cmd *cmd) switch (cmd->data_direction) { case DMA_FROM_DEVICE: + trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_data_in(cmd); break; case DMA_TO_DEVICE: @@ -1783,6 +1791,7 @@ static void transport_complete_qf(struct se_cmd *cmd) } /* Fall through for DMA_TO_DEVICE */ case DMA_NONE: + trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_status(cmd); break; default: @@ -1861,6 +1870,7 @@ static void target_complete_ok_work(struct work_struct *work) } spin_unlock(&cmd->se_lun->lun_sep_lock); + trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_data_in(cmd); if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; @@ -1889,6 +1899,7 @@ static void target_complete_ok_work(struct work_struct *work) } /* Fall through for DMA_TO_DEVICE */ case DMA_NONE: + trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_status(cmd); if (ret == -EAGAIN || ret == -ENOMEM) goto queue_full; @@ -2745,6 +2756,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; after_reason: + trace_target_cmd_complete(cmd); return cmd->se_tfo->queue_status(cmd); } EXPORT_SYMBOL(transport_send_check_condition_and_sense); @@ -2761,6 +2773,7 @@ int transport_check_aborted_status(struct se_cmd *cmd, int send_status) cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); cmd->se_cmd_flags |= SCF_SENT_DELAYED_TAS; + trace_target_cmd_complete(cmd); cmd->se_tfo->queue_status(cmd); return 1; @@ -2798,6 +2811,7 @@ void transport_send_task_abort(struct se_cmd *cmd) " ITT: 0x%08x\n", cmd->t_task_cdb[0], cmd->se_tfo->get_task_tag(cmd)); + trace_target_cmd_complete(cmd); cmd->se_tfo->queue_status(cmd); } diff --git a/include/trace/events/target.h b/include/trace/events/target.h new file mode 100644 index 000000000000..aef8fc354025 --- /dev/null +++ b/include/trace/events/target.h @@ -0,0 +1,214 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM target + +#if !defined(_TRACE_TARGET_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_TARGET_H + +#include +#include +#include +#include +#include + +/* cribbed verbatim from */ +#define scsi_opcode_name(opcode) { opcode, #opcode } +#define show_opcode_name(val) \ + __print_symbolic(val, \ + scsi_opcode_name(TEST_UNIT_READY), \ + scsi_opcode_name(REZERO_UNIT), \ + scsi_opcode_name(REQUEST_SENSE), \ + scsi_opcode_name(FORMAT_UNIT), \ + scsi_opcode_name(READ_BLOCK_LIMITS), \ + scsi_opcode_name(REASSIGN_BLOCKS), \ + scsi_opcode_name(INITIALIZE_ELEMENT_STATUS), \ + scsi_opcode_name(READ_6), \ + scsi_opcode_name(WRITE_6), \ + scsi_opcode_name(SEEK_6), \ + scsi_opcode_name(READ_REVERSE), \ + scsi_opcode_name(WRITE_FILEMARKS), \ + scsi_opcode_name(SPACE), \ + scsi_opcode_name(INQUIRY), \ + scsi_opcode_name(RECOVER_BUFFERED_DATA), \ + scsi_opcode_name(MODE_SELECT), \ + scsi_opcode_name(RESERVE), \ + scsi_opcode_name(RELEASE), \ + scsi_opcode_name(COPY), \ + scsi_opcode_name(ERASE), \ + scsi_opcode_name(MODE_SENSE), \ + scsi_opcode_name(START_STOP), \ + scsi_opcode_name(RECEIVE_DIAGNOSTIC), \ + scsi_opcode_name(SEND_DIAGNOSTIC), \ + scsi_opcode_name(ALLOW_MEDIUM_REMOVAL), \ + scsi_opcode_name(SET_WINDOW), \ + scsi_opcode_name(READ_CAPACITY), \ + scsi_opcode_name(READ_10), \ + scsi_opcode_name(WRITE_10), \ + scsi_opcode_name(SEEK_10), \ + scsi_opcode_name(POSITION_TO_ELEMENT), \ + scsi_opcode_name(WRITE_VERIFY), \ + scsi_opcode_name(VERIFY), \ + scsi_opcode_name(SEARCH_HIGH), \ + scsi_opcode_name(SEARCH_EQUAL), \ + scsi_opcode_name(SEARCH_LOW), \ + scsi_opcode_name(SET_LIMITS), \ + scsi_opcode_name(PRE_FETCH), \ + scsi_opcode_name(READ_POSITION), \ + scsi_opcode_name(SYNCHRONIZE_CACHE), \ + scsi_opcode_name(LOCK_UNLOCK_CACHE), \ + scsi_opcode_name(READ_DEFECT_DATA), \ + scsi_opcode_name(MEDIUM_SCAN), \ + scsi_opcode_name(COMPARE), \ + scsi_opcode_name(COPY_VERIFY), \ + scsi_opcode_name(WRITE_BUFFER), \ + scsi_opcode_name(READ_BUFFER), \ + scsi_opcode_name(UPDATE_BLOCK), \ + scsi_opcode_name(READ_LONG), \ + scsi_opcode_name(WRITE_LONG), \ + scsi_opcode_name(CHANGE_DEFINITION), \ + scsi_opcode_name(WRITE_SAME), \ + scsi_opcode_name(UNMAP), \ + scsi_opcode_name(READ_TOC), \ + scsi_opcode_name(LOG_SELECT), \ + scsi_opcode_name(LOG_SENSE), \ + scsi_opcode_name(XDWRITEREAD_10), \ + scsi_opcode_name(MODE_SELECT_10), \ + scsi_opcode_name(RESERVE_10), \ + scsi_opcode_name(RELEASE_10), \ + scsi_opcode_name(MODE_SENSE_10), \ + scsi_opcode_name(PERSISTENT_RESERVE_IN), \ + scsi_opcode_name(PERSISTENT_RESERVE_OUT), \ + scsi_opcode_name(VARIABLE_LENGTH_CMD), \ + scsi_opcode_name(REPORT_LUNS), \ + scsi_opcode_name(MAINTENANCE_IN), \ + scsi_opcode_name(MAINTENANCE_OUT), \ + scsi_opcode_name(MOVE_MEDIUM), \ + scsi_opcode_name(EXCHANGE_MEDIUM), \ + scsi_opcode_name(READ_12), \ + scsi_opcode_name(WRITE_12), \ + scsi_opcode_name(WRITE_VERIFY_12), \ + scsi_opcode_name(SEARCH_HIGH_12), \ + scsi_opcode_name(SEARCH_EQUAL_12), \ + scsi_opcode_name(SEARCH_LOW_12), \ + scsi_opcode_name(READ_ELEMENT_STATUS), \ + scsi_opcode_name(SEND_VOLUME_TAG), \ + scsi_opcode_name(WRITE_LONG_2), \ + scsi_opcode_name(READ_16), \ + scsi_opcode_name(WRITE_16), \ + scsi_opcode_name(VERIFY_16), \ + scsi_opcode_name(WRITE_SAME_16), \ + scsi_opcode_name(SERVICE_ACTION_IN), \ + scsi_opcode_name(SAI_READ_CAPACITY_16), \ + scsi_opcode_name(SAI_GET_LBA_STATUS), \ + scsi_opcode_name(MI_REPORT_TARGET_PGS), \ + scsi_opcode_name(MO_SET_TARGET_PGS), \ + scsi_opcode_name(READ_32), \ + scsi_opcode_name(WRITE_32), \ + scsi_opcode_name(WRITE_SAME_32), \ + scsi_opcode_name(ATA_16), \ + scsi_opcode_name(ATA_12)) + +#define show_task_attribute_name(val) \ + __print_symbolic(val, \ + { MSG_SIMPLE_TAG, "SIMPLE" }, \ + { MSG_HEAD_TAG, "HEAD" }, \ + { MSG_ORDERED_TAG, "ORDERED" }, \ + { MSG_ACA_TAG, "ACA" } ) + +#define show_scsi_status_name(val) \ + __print_symbolic(val, \ + { SAM_STAT_GOOD, "GOOD" }, \ + { SAM_STAT_CHECK_CONDITION, "CHECK CONDITION" }, \ + { SAM_STAT_CONDITION_MET, "CONDITION MET" }, \ + { SAM_STAT_BUSY, "BUSY" }, \ + { SAM_STAT_INTERMEDIATE, "INTERMEDIATE" }, \ + { SAM_STAT_INTERMEDIATE_CONDITION_MET, "INTERMEDIATE CONDITION MET" }, \ + { SAM_STAT_RESERVATION_CONFLICT, "RESERVATION CONFLICT" }, \ + { SAM_STAT_COMMAND_TERMINATED, "COMMAND TERMINATED" }, \ + { SAM_STAT_TASK_SET_FULL, "TASK SET FULL" }, \ + { SAM_STAT_ACA_ACTIVE, "ACA ACTIVE" }, \ + { SAM_STAT_TASK_ABORTED, "TASK ABORTED" } ) + +TRACE_EVENT(target_sequencer_start, + + TP_PROTO(struct se_cmd *cmd), + + TP_ARGS(cmd), + + TP_STRUCT__entry( + __field( unsigned int, unpacked_lun ) + __field( unsigned int, opcode ) + __field( unsigned int, data_length ) + __field( unsigned int, task_attribute ) + __array( unsigned char, cdb, TCM_MAX_COMMAND_SIZE ) + __string( initiator, cmd->se_sess->se_node_acl->initiatorname ) + ), + + TP_fast_assign( + __entry->unpacked_lun = cmd->se_lun->unpacked_lun; + __entry->opcode = cmd->t_task_cdb[0]; + __entry->data_length = cmd->data_length; + __entry->task_attribute = cmd->sam_task_attr; + memcpy(__entry->cdb, cmd->t_task_cdb, TCM_MAX_COMMAND_SIZE); + __assign_str(initiator, cmd->se_sess->se_node_acl->initiatorname); + ), + + TP_printk("%s -> LUN %03u %s data_length %6u CDB %s (TA:%s C:%02x)", + __get_str(initiator), __entry->unpacked_lun, + show_opcode_name(__entry->opcode), + __entry->data_length, __print_hex(__entry->cdb, 16), + show_task_attribute_name(__entry->task_attribute), + scsi_command_size(__entry->cdb) <= 16 ? + __entry->cdb[scsi_command_size(__entry->cdb) - 1] : + __entry->cdb[1] + ) +); + +TRACE_EVENT(target_cmd_complete, + + TP_PROTO(struct se_cmd *cmd), + + TP_ARGS(cmd), + + TP_STRUCT__entry( + __field( unsigned int, unpacked_lun ) + __field( unsigned int, opcode ) + __field( unsigned int, data_length ) + __field( unsigned int, task_attribute ) + __field( unsigned char, scsi_status ) + __field( unsigned char, sense_length ) + __array( unsigned char, cdb, TCM_MAX_COMMAND_SIZE ) + __array( unsigned char, sense_data, 18 ) + __string(initiator, cmd->se_sess->se_node_acl->initiatorname) + ), + + TP_fast_assign( + __entry->unpacked_lun = cmd->se_lun->unpacked_lun; + __entry->opcode = cmd->t_task_cdb[0]; + __entry->data_length = cmd->data_length; + __entry->task_attribute = cmd->sam_task_attr; + __entry->scsi_status = cmd->scsi_status; + __entry->sense_length = cmd->scsi_status == SAM_STAT_CHECK_CONDITION ? + min(18, ((u8 *) cmd->sense_buffer)[SPC_ADD_SENSE_LEN_OFFSET] + 8) : 0; + memcpy(__entry->cdb, cmd->t_task_cdb, TCM_MAX_COMMAND_SIZE); + memcpy(__entry->sense_data, cmd->sense_buffer, __entry->sense_length); + __assign_str(initiator, cmd->se_sess->se_node_acl->initiatorname); + ), + + TP_printk("%s <- LUN %03u status %s (sense len %d%s%s) %s data_length %6u CDB %s (TA:%s C:%02x)", + __get_str(initiator), __entry->unpacked_lun, + show_scsi_status_name(__entry->scsi_status), + __entry->sense_length, __entry->sense_length ? " / " : "", + __print_hex(__entry->sense_data, __entry->sense_length), + show_opcode_name(__entry->opcode), + __entry->data_length, __print_hex(__entry->cdb, 16), + show_task_attribute_name(__entry->task_attribute), + scsi_command_size(__entry->cdb) <= 16 ? + __entry->cdb[scsi_command_size(__entry->cdb) - 1] : + __entry->cdb[1] + ) +); + +#endif /* _TRACE_TARGET_H */ + +/* This part must be outside protection */ +#include -- GitLab From 09ceadc70383a4105c0372f9e83da2c0cb0a8017 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 26 Jun 2013 17:36:18 -0700 Subject: [PATCH 2377/2900] target: Return correct sense data for IO past the end of a device We should use TCM_ADDRESS_OUT_OF_RANGE (-> sense data LOGICAL BLOCK ADDRESS OUT OF RANGE) for IOs past the end of a device instead of INVALID FIELD IN CDB. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index bbc5b0ee2bdc..ee0cb9d96929 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -581,7 +581,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) pr_err("cmd exceeds last lba %llu " "(lba %llu, sectors %u)\n", end_lba, cmd->t_task_lba, sectors); - return TCM_INVALID_CDB_FIELD; + return TCM_ADDRESS_OUT_OF_RANGE; } size = sbc_get_size(cmd, sectors); -- GitLab From 8dc8632aa7bf1de7a56daea56a7011cbfff76678 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 26 Jun 2013 17:36:19 -0700 Subject: [PATCH 2378/2900] target: Add (obsolete) checking for PMI/LBA fields in READ CAPACITY(10) The SBC-2 specification of READ CAPACITY(10) has PMI and LOGICAL BLOCK ADDRESS fields in the CDB; in SBC-3 these fields are simply listed as obsolete. However, SBC-2 also has the language If the PMI bit is set to zero and the LOGICAL BLOCK ADDRESS field is not set to zero, the device server shall terminate the command with CHECK CONDITION status with the sense key set to ILLEGAL REQUEST and the additional sense code set to INVALID FIELD IN CDB. and in fact at least the Windows SCSI compliance test checks this behavior. Since no one following SBC-3 is going to set these fields, we might as well include the check from SBC-2 and pass this test. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_sbc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index ee0cb9d96929..8a462773d0c8 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -38,11 +38,27 @@ static sense_reason_t sbc_emulate_readcapacity(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; + unsigned char *cdb = cmd->t_task_cdb; unsigned long long blocks_long = dev->transport->get_blocks(dev); unsigned char *rbuf; unsigned char buf[8]; u32 blocks; + /* + * SBC-2 says: + * If the PMI bit is set to zero and the LOGICAL BLOCK + * ADDRESS field is not set to zero, the device server shall + * terminate the command with CHECK CONDITION status with + * the sense key set to ILLEGAL REQUEST and the additional + * sense code set to INVALID FIELD IN CDB. + * + * In SBC-3, these fields are obsolete, but some SCSI + * compliance tests actually check this, so we might as well + * follow SBC-2. + */ + if (!(cdb[8] & 1) && !!(cdb[2] | cdb[3] | cdb[4] | cdb[5])) + return TCM_INVALID_CDB_FIELD; + if (blocks_long >= 0x00000000ffffffff) blocks = 0xffffffff; else -- GitLab From c5a2adbfcbc1d364371cd81c4180c7a83b73c5a0 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 1 Jul 2013 15:11:21 -0700 Subject: [PATCH 2379/2900] iser-target: Add vendor_err debug output Add output for ib_wc.vendor_err in isert_cq_[t,r]x_work(), which is useful for debugging future issues. Reported-by: Or Gerlitz Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index d6cc5999d793..66712bd7dc11 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1487,6 +1487,7 @@ isert_cq_tx_work(struct work_struct *work) } else { pr_debug("TX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); pr_debug("TX wc.status: 0x%08x\n", wc.status); + pr_debug("TX wc.vendor_err: 0x%08x\n", wc.vendor_err); atomic_dec(&isert_conn->post_send_buf_count); isert_cq_comp_err(tx_desc, isert_conn); } @@ -1526,9 +1527,11 @@ isert_cq_rx_work(struct work_struct *work) isert_rx_completion(rx_desc, isert_conn, xfer_len); } else { pr_debug("RX wc.status != IB_WC_SUCCESS >>>>>>>>>>>>>>\n"); - if (wc.status != IB_WC_WR_FLUSH_ERR) + if (wc.status != IB_WC_WR_FLUSH_ERR) { pr_debug("RX wc.status: 0x%08x\n", wc.status); - + pr_debug("RX wc.vendor_err: 0x%08x\n", + wc.vendor_err); + } isert_conn->post_recv_buf_count--; isert_cq_comp_err(NULL, isert_conn); } -- GitLab From dbbc5d11074fc017488e6bdaaf9238d53e35ab07 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 3 Jul 2013 19:39:37 -0700 Subject: [PATCH 2380/2900] iser-target: Rename sense_buf_[dma,len] to pdu_[dma,len] Now that these two variables are used for REJECT payloads as well as SCSI response sense payloads, rename them to something that makes more sense. Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 30 ++++++++++++------------- drivers/infiniband/ulp/isert/ib_isert.h | 4 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 66712bd7dc11..fa4251803577 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1286,11 +1286,11 @@ static void isert_completion_put(struct iser_tx_desc *tx_desc, struct isert_cmd *isert_cmd, struct ib_device *ib_dev) { - if (isert_cmd->sense_buf_dma != 0) { - pr_debug("Calling ib_dma_unmap_single for isert_cmd->sense_buf_dma\n"); - ib_dma_unmap_single(ib_dev, isert_cmd->sense_buf_dma, - isert_cmd->sense_buf_len, DMA_TO_DEVICE); - isert_cmd->sense_buf_dma = 0; + if (isert_cmd->pdu_buf_dma != 0) { + pr_debug("Calling ib_dma_unmap_single for isert_cmd->pdu_buf_dma\n"); + ib_dma_unmap_single(ib_dev, isert_cmd->pdu_buf_dma, + isert_cmd->pdu_buf_len, DMA_TO_DEVICE); + isert_cmd->pdu_buf_dma = 0; } isert_unmap_tx_desc(tx_desc, ib_dev); @@ -1588,7 +1588,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) { struct ib_device *ib_dev = isert_conn->conn_cm_id->device; struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; - u32 padding, sense_len; + u32 padding, pdu_len; put_unaligned_be16(cmd->se_cmd.scsi_sense_length, cmd->sense_buffer); @@ -1596,15 +1596,15 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd) padding = -(cmd->se_cmd.scsi_sense_length) & 3; hton24(hdr->dlength, (u32)cmd->se_cmd.scsi_sense_length); - sense_len = cmd->se_cmd.scsi_sense_length + padding; + pdu_len = cmd->se_cmd.scsi_sense_length + padding; - isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev, - (void *)cmd->sense_buffer, sense_len, + isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, + (void *)cmd->sense_buffer, pdu_len, DMA_TO_DEVICE); - isert_cmd->sense_buf_len = sense_len; - tx_dsg->addr = isert_cmd->sense_buf_dma; - tx_dsg->length = sense_len; + isert_cmd->pdu_buf_len = pdu_len; + tx_dsg->addr = isert_cmd->pdu_buf_dma; + tx_dsg->length = pdu_len; tx_dsg->lkey = isert_conn->conn_mr->lkey; isert_cmd->tx_desc.num_sge = 2; } @@ -1692,11 +1692,11 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); hton24(hdr->dlength, ISCSI_HDR_LEN); - isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev, + isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, (void *)cmd->buf_ptr, ISCSI_HDR_LEN, DMA_TO_DEVICE); - isert_cmd->sense_buf_len = ISCSI_HDR_LEN; - tx_dsg->addr = isert_cmd->sense_buf_dma; + isert_cmd->pdu_buf_len = ISCSI_HDR_LEN; + tx_dsg->addr = isert_cmd->pdu_buf_dma; tx_dsg->length = ISCSI_HDR_LEN; tx_dsg->lkey = isert_conn->conn_mr->lkey; isert_cmd->tx_desc.num_sge = 2; diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 5795c82a2306..191117b5b508 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -61,8 +61,8 @@ struct isert_cmd { uint32_t write_stag; uint64_t read_va; uint64_t write_va; - u64 sense_buf_dma; - u32 sense_buf_len; + u64 pdu_buf_dma; + u32 pdu_buf_len; u32 read_va_off; u32 write_va_off; u32 rdma_wr_num; -- GitLab From adb54c29310e8785e4f2eb0dc76e0e2fde943b11 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 14 Jun 2013 16:47:15 -0700 Subject: [PATCH 2381/2900] iser-target: Add support for ISCSI_OP_TEXT opcode + payload handling This patch adds isert_handle_text_cmd() to handle incoming ISCSI_OP_TEXT PDU processing, along with isert_put_text_rsp() for posting ISCSI_OP_TEXT_RSP ib_send_wr response. It copies ISCSI_OP_TEXT payload using unsolicited payload at &iser_rx_desc->data[0] into iscsi_cmd->text_in_ptr for usage with outgoing isert_put_text_rsp() -> iscsit_build_text_rsp() v2 changes: - Let iscsit_build_text_rsp() determine any extra padding Reported-by: Or Gerlitz Cc: Or Gerlitz Cc: Mike Christie Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 89 ++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index fa4251803577..f02bfcc282e5 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1032,6 +1032,33 @@ isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, return iscsit_process_nop_out(conn, cmd, hdr); } +static int +isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, + struct iser_rx_desc *rx_desc, struct iscsi_text *hdr) +{ + struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd; + struct iscsi_conn *conn = isert_conn->conn; + u32 payload_length = ntoh24(hdr->dlength); + int rc; + unsigned char *text_in; + + rc = iscsit_setup_text_cmd(conn, cmd, hdr); + if (rc < 0) + return rc; + + text_in = kzalloc(payload_length, GFP_KERNEL); + if (!text_in) { + pr_err("Unable to allocate text_in of payload_length: %u\n", + payload_length); + return -ENOMEM; + } + cmd->text_in_ptr = text_in; + + memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length); + + return iscsit_process_text_cmd(conn, cmd, hdr); +} + static int isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, uint32_t read_stag, uint64_t read_va, @@ -1091,6 +1118,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, SECONDS_FOR_LOGOUT_COMP * HZ); break; + case ISCSI_OP_TEXT: + cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); + if (!cmd) + break; + + isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd); + ret = isert_handle_text_cmd(isert_conn, isert_cmd, + rx_desc, (struct iscsi_text *)hdr); + break; default: pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode); dump_stack(); @@ -1245,6 +1281,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd) break; case ISCSI_OP_REJECT: case ISCSI_OP_NOOP_OUT: + case ISCSI_OP_TEXT: spin_lock_bh(&conn->cmd_lock); if (!list_empty(&cmd->i_conn_node)) list_del(&cmd->i_conn_node); @@ -1366,6 +1403,11 @@ isert_do_control_comp(struct work_struct *work) isert_conn->logout_posted = true; iscsit_logout_post_handler(cmd, cmd->conn); break; + case ISTATE_SEND_TEXTRSP: + atomic_dec(&isert_conn->post_send_buf_count); + cmd->i_state = ISTATE_SENT_STATUS; + isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev); + break; default: pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state); dump_stack(); @@ -1383,7 +1425,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc, if (cmd->i_state == ISTATE_SEND_TASKMGTRSP || cmd->i_state == ISTATE_SEND_LOGOUTRSP || - cmd->i_state == ISTATE_SEND_REJECT) { + cmd->i_state == ISTATE_SEND_REJECT || + cmd->i_state == ISTATE_SEND_TEXTRSP) { isert_unmap_tx_desc(tx_desc, ib_dev); INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp); @@ -1708,6 +1751,47 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn) return isert_post_response(isert_conn, isert_cmd); } +static int +isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) +{ + struct isert_cmd *isert_cmd = container_of(cmd, + struct isert_cmd, iscsi_cmd); + struct isert_conn *isert_conn = (struct isert_conn *)conn->context; + struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr; + struct iscsi_text_rsp *hdr = + (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header; + u32 txt_rsp_len; + int rc; + + isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc); + rc = iscsit_build_text_rsp(cmd, conn, hdr); + if (rc < 0) + return rc; + + txt_rsp_len = rc; + isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc); + + if (txt_rsp_len) { + struct ib_device *ib_dev = isert_conn->conn_cm_id->device; + struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1]; + void *txt_rsp_buf = cmd->buf_ptr; + + isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev, + txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE); + + isert_cmd->pdu_buf_len = txt_rsp_len; + tx_dsg->addr = isert_cmd->pdu_buf_dma; + tx_dsg->length = txt_rsp_len; + tx_dsg->lkey = isert_conn->conn_mr->lkey; + isert_cmd->tx_desc.num_sge = 2; + } + isert_init_send_wr(isert_cmd, send_wr); + + pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n"); + + return isert_post_response(isert_conn, isert_cmd); +} + static int isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd, struct ib_sge *ib_sge, struct ib_send_wr *send_wr, @@ -2006,6 +2090,9 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state) case ISTATE_SEND_REJECT: ret = isert_put_reject(cmd, conn); break; + case ISTATE_SEND_TEXTRSP: + ret = isert_put_text_rsp(cmd, conn); + break; case ISTATE_SEND_STATUS: /* * Special case for sending non GOOD SCSI status from TX thread -- GitLab From 0fbfc46fb0b2f543a8b539e94c6c293ebc0b05a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Engel?= Date: Wed, 3 Jul 2013 11:35:11 -0400 Subject: [PATCH 2382/2900] iscsi-target: Fix tfc_tpg_nacl_auth_cit configfs length overflow This patch fixes a potential buffer overflow while processing iscsi_node_auth input for configfs attributes within NodeACL tfc_tpg_nacl_auth_cit context. Signed-off-by: Joern Engel Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index e251849a6140..88bc805e998f 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -473,7 +473,7 @@ static ssize_t __iscsi_##prefix##_store_##name( \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ \ - snprintf(auth->name, PAGE_SIZE, "%s", page); \ + snprintf(auth->name, sizeof(auth->name), "%s", page); \ if (!strncmp("NULL", auth->name, 4)) \ auth->naf_flags &= ~flags; \ else \ -- GitLab From 37b32c6faf0e0e40c65c1014df7527ececdd3f9a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sat, 6 Jul 2013 16:48:55 -0700 Subject: [PATCH 2383/2900] iscsi-target: Fix tfc_tpg_auth_cit configfs length overflow This patch fixes another potential buffer overflow while processing iscsi_node_auth input for configfs attributes in v3.11 for-next TPG tfc_tpg_auth_cit context. Reported-by: Joern Engel Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 88bc805e998f..b41d4786fa08 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1081,7 +1081,7 @@ static ssize_t __iscsi_##prefix##_store_##name( \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ \ - snprintf(auth->name, PAGE_SIZE, "%s", page); \ + snprintf(auth->name, sizeof(auth->name), "%s", page); \ if (!(strncmp("NULL", auth->name, 4))) \ auth->naf_flags &= ~flags; \ else \ -- GitLab From ad7babd23726b442b0b5fd92d8bd0611af5e5d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Engel?= Date: Wed, 3 Jul 2013 11:35:11 -0400 Subject: [PATCH 2384/2900] iscsi-target: kstrtou* configfs attribute parameter cleanups This patch includes the conversion of iscsi-target configfs attributes for NetworkPortal, NodeACL, TPG, IQN and Discovery groups to use kstrtou*() instead of simple_strtou*(). It also cleans up new-line usage during iscsi_tpg_param_store_##name to use isspace(). Signed-off-by: Joern Engel Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_configfs.c | 53 ++++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index b41d4786fa08..684d73fcbedf 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -20,6 +20,7 @@ ****************************************************************************/ #include +#include #include #include #include @@ -78,11 +79,12 @@ static ssize_t lio_target_np_store_sctp( struct iscsi_tpg_np *tpg_np = container_of(se_tpg_np, struct iscsi_tpg_np, se_tpg_np); struct iscsi_tpg_np *tpg_np_sctp = NULL; - char *endptr; u32 op; int ret; - op = simple_strtoul(page, &endptr, 0); + ret = kstrtou32(page, 0, &op); + if (ret) + return ret; if ((op != 1) && (op != 0)) { pr_err("Illegal value for tpg_enable: %u\n", op); return -EINVAL; @@ -381,11 +383,12 @@ static ssize_t iscsi_nacl_attrib_store_##name( \ { \ struct iscsi_node_acl *nacl = container_of(se_nacl, struct iscsi_node_acl, \ se_node_acl); \ - char *endptr; \ u32 val; \ int ret; \ \ - val = simple_strtoul(page, &endptr, 0); \ + ret = kstrtou32(page, 0, &val); \ + if (ret) \ + return ret; \ ret = iscsit_na_##name(nacl, val); \ if (ret < 0) \ return ret; \ @@ -788,11 +791,12 @@ static ssize_t lio_target_nacl_store_cmdsn_depth( struct iscsi_portal_group *tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg); struct config_item *acl_ci, *tpg_ci, *wwn_ci; - char *endptr; u32 cmdsn_depth = 0; int ret; - cmdsn_depth = simple_strtoul(page, &endptr, 0); + ret = kstrtou32(page, 0, &cmdsn_depth); + if (ret) + return ret; if (cmdsn_depth > TA_DEFAULT_CMDSN_DEPTH_MAX) { pr_err("Passed cmdsn_depth: %u exceeds" " TA_DEFAULT_CMDSN_DEPTH_MAX: %u\n", cmdsn_depth, @@ -976,14 +980,15 @@ static ssize_t iscsi_tpg_attrib_store_##name( \ { \ struct iscsi_portal_group *tpg = container_of(se_tpg, \ struct iscsi_portal_group, tpg_se_tpg); \ - char *endptr; \ u32 val; \ int ret; \ \ if (iscsit_get_tpg(tpg) < 0) \ return -EINVAL; \ \ - val = simple_strtoul(page, &endptr, 0); \ + ret = kstrtou32(page, 0, &val); \ + if (ret) \ + goto out; \ ret = iscsit_ta_##name(tpg, val); \ if (ret < 0) \ goto out; \ @@ -1211,13 +1216,14 @@ static ssize_t iscsi_tpg_param_store_##name( \ struct iscsi_portal_group *tpg = container_of(se_tpg, \ struct iscsi_portal_group, tpg_se_tpg); \ char *buf; \ - int ret; \ + int ret, len; \ \ buf = kzalloc(PAGE_SIZE, GFP_KERNEL); \ if (!buf) \ return -ENOMEM; \ - snprintf(buf, PAGE_SIZE, "%s=%s", __stringify(name), page); \ - buf[strlen(buf)-1] = '\0'; /* Kill newline */ \ + len = snprintf(buf, PAGE_SIZE, "%s=%s", __stringify(name), page); \ + if (isspace(buf[len-1])) \ + buf[len-1] = '\0'; /* Kill newline */ \ \ if (iscsit_get_tpg(tpg) < 0) { \ kfree(buf); \ @@ -1354,11 +1360,12 @@ static ssize_t lio_target_tpg_store_enable( { struct iscsi_portal_group *tpg = container_of(se_tpg, struct iscsi_portal_group, tpg_se_tpg); - char *endptr; u32 op; - int ret = 0; + int ret; - op = simple_strtoul(page, &endptr, 0); + ret = kstrtou32(page, 0, &op); + if (ret) + return ret; if ((op != 1) && (op != 0)) { pr_err("Illegal value for tpg_enable: %u\n", op); return -EINVAL; @@ -1406,15 +1413,15 @@ static struct se_portal_group *lio_target_tiqn_addtpg( { struct iscsi_portal_group *tpg; struct iscsi_tiqn *tiqn; - char *tpgt_str, *end_ptr; - int ret = 0; - unsigned short int tpgt; + char *tpgt_str; + int ret; + u16 tpgt; tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); /* * Only tpgt_# directory groups can be created below * target/iscsi/iqn.superturodiskarry/ - */ + */ tpgt_str = strstr(name, "tpgt_"); if (!tpgt_str) { pr_err("Unable to locate \"tpgt_#\" directory" @@ -1422,7 +1429,9 @@ static struct se_portal_group *lio_target_tiqn_addtpg( return NULL; } tpgt_str += 5; /* Skip ahead of "tpgt_" */ - tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0); + ret = kstrtou16(tpgt_str, 0, &tpgt); + if (ret) + return NULL; tpg = iscsit_alloc_portal_group(tiqn, tpgt); if (!tpg) @@ -1630,10 +1639,12 @@ static ssize_t iscsi_disc_store_enforce_discovery_auth( { struct iscsi_param *param; struct iscsi_portal_group *discovery_tpg = iscsit_global->discovery_tpg; - char *endptr; u32 op; + int err; - op = simple_strtoul(page, &endptr, 0); + err = kstrtou32(page, 0, &op); + if (err) + return -EINVAL; if ((op != 1) && (op != 0)) { pr_err("Illegal value for enforce_discovery_auth:" " %u\n", op); -- GitLab From 11fee8a751670cf6d60b1912e2e9cb1c7e392842 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Wed, 3 Jul 2013 11:22:16 -0400 Subject: [PATCH 2385/2900] target: remove unused codes from enum tcm_tmrsp_table Three have been checked for but were never set. Remove the dead code. Also renumbers the remaining ones to a) get rid of the holes after the removal and b) avoid a collision between TMR_FUNCTION_COMPLETE==0 and the uninitialized case. If we failed to set a code, we should rather fall into the default case then return success. Signed-off-by: Joern Engel Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 2 -- drivers/target/tcm_fc/tfc_cmd.c | 3 --- include/target/target_core_base.h | 13 +++++-------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index c30ec1d5756e..f73da43cdf9e 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3286,8 +3286,6 @@ static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr) return ISCSI_TMF_RSP_NO_LUN; case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED: return ISCSI_TMF_RSP_NOT_SUPPORTED; - case TMR_FUNCTION_AUTHORIZATION_FAILED: - return ISCSI_TMF_RSP_AUTH_FAILED; case TMR_FUNCTION_REJECTED: default: return ISCSI_TMF_RSP_REJECTED; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index b406f178ff39..7b6bb72fa475 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -413,10 +413,7 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd) code = FCP_TMF_REJECTED; break; case TMR_TASK_DOES_NOT_EXIST: - case TMR_TASK_STILL_ALLEGIANT: - case TMR_TASK_FAILOVER_NOT_SUPPORTED: case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED: - case TMR_FUNCTION_AUTHORIZATION_FAILED: default: code = FCP_TMF_FAILED; break; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index d92ec6765f5d..e34fc904f2e1 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -218,14 +218,11 @@ enum tcm_tmreq_table { /* fabric independent task management response values */ enum tcm_tmrsp_table { - TMR_FUNCTION_COMPLETE = 0, - TMR_TASK_DOES_NOT_EXIST = 1, - TMR_LUN_DOES_NOT_EXIST = 2, - TMR_TASK_STILL_ALLEGIANT = 3, - TMR_TASK_FAILOVER_NOT_SUPPORTED = 4, - TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED = 5, - TMR_FUNCTION_AUTHORIZATION_FAILED = 6, - TMR_FUNCTION_REJECTED = 255, + TMR_FUNCTION_COMPLETE = 1, + TMR_TASK_DOES_NOT_EXIST = 2, + TMR_LUN_DOES_NOT_EXIST = 3, + TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED = 4, + TMR_FUNCTION_REJECTED = 5, }; /* -- GitLab From b79fafac70fc9bbe640b8193ed772eb850efdfe6 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Wed, 3 Jul 2013 11:22:17 -0400 Subject: [PATCH 2386/2900] target: make queue_tm_rsp() return void The return value wasn't checked by any of the callers. Assuming this is correct behaviour, we can simplify some code by not bothering to generate it. nab: Add srpt_queue_data_in() + srpt_queue_tm_rsp() nops around srpt_queue_response() void return Signed-off-by: Joern Engel Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/srpt/ib_srpt.c | 27 ++++++++++++-------- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +-- drivers/target/iscsi/iscsi_target_configfs.c | 3 +-- drivers/target/loopback/tcm_loop.c | 3 +-- drivers/target/sbp/sbp_target.c | 3 +-- drivers/target/tcm_fc/tcm_fc.h | 2 +- drivers/target/tcm_fc/tfc_cmd.c | 5 ++-- drivers/usb/gadget/tcm_usb_gadget.c | 3 +-- drivers/vhost/scsi.c | 4 +-- include/target/target_core_fabric.h | 2 +- 10 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 3f3f0416fbdd..653ac6bfc57a 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -3011,7 +3011,7 @@ static u8 tcm_to_srp_tsk_mgmt_status(const int tcm_mgmt_status) * Callback function called by the TCM core. Must not block since it can be * invoked on the context of the IB completion handler. */ -static int srpt_queue_response(struct se_cmd *cmd) +static void srpt_queue_response(struct se_cmd *cmd) { struct srpt_rdma_ch *ch; struct srpt_send_ioctx *ioctx; @@ -3022,8 +3022,6 @@ static int srpt_queue_response(struct se_cmd *cmd) int resp_len; u8 srp_tm_status; - ret = 0; - ioctx = container_of(cmd, struct srpt_send_ioctx, cmd); ch = ioctx->ch; BUG_ON(!ch); @@ -3049,7 +3047,7 @@ static int srpt_queue_response(struct se_cmd *cmd) || WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) { atomic_inc(&ch->req_lim_delta); srpt_abort_cmd(ioctx); - goto out; + return; } dir = ioctx->cmd.data_direction; @@ -3061,7 +3059,7 @@ static int srpt_queue_response(struct se_cmd *cmd) if (ret) { printk(KERN_ERR "xfer_data failed for tag %llu\n", ioctx->tag); - goto out; + return; } } @@ -3082,9 +3080,17 @@ static int srpt_queue_response(struct se_cmd *cmd) srpt_set_cmd_state(ioctx, SRPT_STATE_DONE); target_put_sess_cmd(ioctx->ch->sess, &ioctx->cmd); } +} -out: - return ret; +static int srpt_queue_data_in(struct se_cmd *cmd) +{ + srpt_queue_response(cmd); + return 0; +} + +static void srpt_queue_tm_rsp(struct se_cmd *cmd) +{ + srpt_queue_response(cmd); } static int srpt_queue_status(struct se_cmd *cmd) @@ -3097,7 +3103,8 @@ static int srpt_queue_status(struct se_cmd *cmd) (SCF_TRANSPORT_TASK_SENSE | SCF_EMULATED_TASK_SENSE)) WARN_ON(cmd->scsi_status != SAM_STAT_CHECK_CONDITION); ioctx->queue_status_only = true; - return srpt_queue_response(cmd); + srpt_queue_response(cmd); + return 0; } static void srpt_refresh_port_work(struct work_struct *work) @@ -3930,9 +3937,9 @@ static struct target_core_fabric_ops srpt_template = { .set_default_node_attributes = srpt_set_default_node_attrs, .get_task_tag = srpt_get_task_tag, .get_cmd_state = srpt_get_tcm_cmd_state, - .queue_data_in = srpt_queue_response, + .queue_data_in = srpt_queue_data_in, .queue_status = srpt_queue_status, - .queue_tm_rsp = srpt_queue_response, + .queue_tm_rsp = srpt_queue_tm_rsp, /* * Setup function pointers for generic logic in * target_core_fabric_configfs.c diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index bb7eb909f0b1..75caa39b807d 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -699,7 +699,7 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) return qlt_xmit_response(cmd, xmit_type, se_cmd->scsi_status); } -static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) +static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) { struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; struct qla_tgt_mgmt_cmd *mcmd = container_of(se_cmd, @@ -731,8 +731,6 @@ static int tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) * CTIO response packet. */ qlt_xmit_tm_rsp(mcmd); - - return 0; } /* Local pointer to allocated TCM configfs fabric module */ diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 684d73fcbedf..7d4e19f39fe6 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -1790,13 +1790,12 @@ static int lio_queue_status(struct se_cmd *se_cmd) return 0; } -static int lio_queue_tm_rsp(struct se_cmd *se_cmd) +static void lio_queue_tm_rsp(struct se_cmd *se_cmd) { struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); cmd->i_state = ISTATE_SEND_TASKMGTRSP; iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state); - return 0; } static char *lio_tpg_get_endpoint_wwn(struct se_portal_group *se_tpg) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 7c908141cc8a..568ad25f25d3 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -786,7 +786,7 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd) return 0; } -static int tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) +static void tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) { struct se_tmr_req *se_tmr = se_cmd->se_tmr_req; struct tcm_loop_tmr *tl_tmr = se_tmr->fabric_tmr_ptr; @@ -796,7 +796,6 @@ static int tcm_loop_queue_tm_rsp(struct se_cmd *se_cmd) */ atomic_set(&tl_tmr->tmr_complete, 1); wake_up(&tl_tmr->tl_tmr_wait); - return 0; } static char *tcm_loop_dump_proto_id(struct tcm_loop_hba *tl_hba) diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c index d3536f57444f..e51b09a04d52 100644 --- a/drivers/target/sbp/sbp_target.c +++ b/drivers/target/sbp/sbp_target.c @@ -1842,9 +1842,8 @@ static int sbp_queue_status(struct se_cmd *se_cmd) return sbp_send_sense(req); } -static int sbp_queue_tm_rsp(struct se_cmd *se_cmd) +static void sbp_queue_tm_rsp(struct se_cmd *se_cmd) { - return 0; } static int sbp_check_stop_free(struct se_cmd *se_cmd) diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index eea69358ced3..0dd54a44abcf 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -161,7 +161,7 @@ int ft_write_pending(struct se_cmd *); int ft_write_pending_status(struct se_cmd *); u32 ft_get_task_tag(struct se_cmd *); int ft_get_cmd_state(struct se_cmd *); -int ft_queue_tm_resp(struct se_cmd *); +void ft_queue_tm_resp(struct se_cmd *); /* * other internal functions. diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 7b6bb72fa475..0e5a1caed176 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -394,14 +394,14 @@ static void ft_send_tm(struct ft_cmd *cmd) /* * Send status from completed task management request. */ -int ft_queue_tm_resp(struct se_cmd *se_cmd) +void ft_queue_tm_resp(struct se_cmd *se_cmd) { struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); struct se_tmr_req *tmr = se_cmd->se_tmr_req; enum fcp_resp_rsp_codes code; if (cmd->aborted) - return 0; + return; switch (tmr->response) { case TMR_FUNCTION_COMPLETE: code = FCP_TMF_CMPL; @@ -421,7 +421,6 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd) pr_debug("tmr fn %d resp %d fcp code %d\n", tmr->function, tmr->response, code); ft_send_resp_code(cmd, code); - return 0; } static void ft_send_work(struct work_struct *work); diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 7cacd6ae818e..0ff33396eef3 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1467,9 +1467,8 @@ static int usbg_get_cmd_state(struct se_cmd *se_cmd) return 0; } -static int usbg_queue_tm_rsp(struct se_cmd *se_cmd) +static void usbg_queue_tm_rsp(struct se_cmd *se_cmd) { - return 0; } static const char *usbg_check_wwn(const char *name) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 1e5e82042f84..b35193807f0b 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -528,9 +528,9 @@ static int tcm_vhost_queue_status(struct se_cmd *se_cmd) return 0; } -static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd) +static void tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd) { - return 0; + return; } static void tcm_vhost_free_evt(struct vhost_scsi *vs, struct tcm_vhost_evt *evt) diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 1dcce9cc99b9..7a16178424f9 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -61,7 +61,7 @@ struct target_core_fabric_ops { int (*get_cmd_state)(struct se_cmd *); int (*queue_data_in)(struct se_cmd *); int (*queue_status)(struct se_cmd *); - int (*queue_tm_rsp)(struct se_cmd *); + void (*queue_tm_rsp)(struct se_cmd *); /* * fabric module calls for target_core_fabric_configfs.c */ -- GitLab From ca40d24eb8fc3c194b4439493ecf6b2d703812b8 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Sun, 7 Jul 2013 17:45:08 -0700 Subject: [PATCH 2387/2900] iser-target: Ignore non TEXT + LOGOUT opcodes for discovery This patch adds a check in isert_rx_opcode() to ignore non TEXT + LOGOUT opcodes when SessionType=Discovery has been negotiated. Cc: Or Gerlitz Signed-off-by: Nicholas Bellinger --- drivers/infiniband/ulp/isert/ib_isert.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index f02bfcc282e5..ecd16541896b 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1066,11 +1066,19 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, { struct iscsi_hdr *hdr = &rx_desc->iscsi_header; struct iscsi_conn *conn = isert_conn->conn; + struct iscsi_session *sess = conn->sess; struct iscsi_cmd *cmd; struct isert_cmd *isert_cmd; int ret = -EINVAL; u8 opcode = (hdr->opcode & ISCSI_OPCODE_MASK); + if (sess->sess_ops->SessionType && + (!(opcode & ISCSI_OP_TEXT) || !(opcode & ISCSI_OP_LOGOUT))) { + pr_err("Got illegal opcode: 0x%02x in SessionType=Discovery," + " ignoring\n", opcode); + return 0; + } + switch (opcode) { case ISCSI_OP_SCSI_CMD: cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); -- GitLab From 0134f16bc91cc15a38c867b81568b791c9b626aa Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 7 Jul 2013 17:25:52 +0300 Subject: [PATCH 2388/2900] IB/core: Add reserved values to enums for low-level driver use Continue the approach taken by commit d2b57063e4a ("IB/core: Reserve bits in enum ib_qp_create_flags for low-level driver use") and add reserved entries to the ib_qp_type and ib_wr_opcode enums. Low-level drivers can then define macros to use these reserved values, giving proper names to the macros for readability. Also add a range of reserved flags to enum ib_send_flags. The mlx5 IB driver uses the new additions. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- include/rdma/ib_verbs.h | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 98cc4b29fc5b..645c3cedce9c 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -610,7 +610,21 @@ enum ib_qp_type { IB_QPT_RAW_PACKET = 8, IB_QPT_XRC_INI = 9, IB_QPT_XRC_TGT, - IB_QPT_MAX + IB_QPT_MAX, + /* Reserve a range for qp types internal to the low level driver. + * These qp types will not be visible at the IB core layer, so the + * IB_QPT_MAX usages should not be affected in the core layer + */ + IB_QPT_RESERVED1 = 0x1000, + IB_QPT_RESERVED2, + IB_QPT_RESERVED3, + IB_QPT_RESERVED4, + IB_QPT_RESERVED5, + IB_QPT_RESERVED6, + IB_QPT_RESERVED7, + IB_QPT_RESERVED8, + IB_QPT_RESERVED9, + IB_QPT_RESERVED10, }; enum ib_qp_create_flags { @@ -766,6 +780,19 @@ enum ib_wr_opcode { IB_WR_MASKED_ATOMIC_CMP_AND_SWP, IB_WR_MASKED_ATOMIC_FETCH_AND_ADD, IB_WR_BIND_MW, + /* reserve values for low level drivers' internal use. + * These values will not be used at all in the ib core layer. + */ + IB_WR_RESERVED1 = 0xf0, + IB_WR_RESERVED2, + IB_WR_RESERVED3, + IB_WR_RESERVED4, + IB_WR_RESERVED5, + IB_WR_RESERVED6, + IB_WR_RESERVED7, + IB_WR_RESERVED8, + IB_WR_RESERVED9, + IB_WR_RESERVED10, }; enum ib_send_flags { @@ -773,7 +800,11 @@ enum ib_send_flags { IB_SEND_SIGNALED = (1<<1), IB_SEND_SOLICITED = (1<<2), IB_SEND_INLINE = (1<<3), - IB_SEND_IP_CSUM = (1<<4) + IB_SEND_IP_CSUM = (1<<4), + + /* reserve bits 26-31 for low level drivers' internal use */ + IB_SEND_RESERVED_START = (1 << 26), + IB_SEND_RESERVED_END = (1 << 31), }; struct ib_sge { -- GitLab From 2f28c8b31dc501027d9aa6acf496c5941736312b Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 29 May 2013 12:15:07 -0700 Subject: [PATCH 2389/2900] net/9p: add privport option to 9p tcp transport If the privport option is specified, the tcp transport binds local address to a reserved port before connecting to the 9p server. In some cases when 9P AUTH cannot be implemented, this is better than nothing. Signed-off-by: Jim Garlick Signed-off-by: Eric Van Hensbergen --- include/net/9p/transport.h | 3 +++ net/9p/trans_fd.c | 40 +++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index adcbb20f6511..9a36d9297114 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -26,6 +26,9 @@ #ifndef NET_9P_TRANSPORT_H #define NET_9P_TRANSPORT_H +#define P9_DEF_MIN_RESVPORT (665U) +#define P9_DEF_MAX_RESVPORT (1023U) + /** * struct p9_trans_module - transport module interface * @list: used to maintain a list of currently available transports diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 02efb25c2957..3ffda1b3799b 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -63,6 +63,7 @@ struct p9_fd_opts { int rfd; int wfd; u16 port; + int privport; }; /** @@ -87,12 +88,15 @@ struct p9_trans_fd { enum { /* Options that take integer arguments */ Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, + /* Options that take no arguments */ + Opt_privport, }; static const match_table_t tokens = { {Opt_port, "port=%u"}, {Opt_rfdno, "rfdno=%u"}, {Opt_wfdno, "wfdno=%u"}, + {Opt_privport, "privport"}, {Opt_err, NULL}, }; @@ -161,6 +165,9 @@ static DEFINE_SPINLOCK(p9_poll_lock); static LIST_HEAD(p9_poll_pending_list); static DECLARE_WORK(p9_poll_work, p9_poll_workfn); +static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT; +static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT; + static void p9_mux_poll_stop(struct p9_conn *m) { unsigned long flags; @@ -741,7 +748,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) if (!*p) continue; token = match_token(p, tokens, args); - if (token != Opt_err) { + if ((token != Opt_err) && (token != Opt_privport)) { r = match_int(&args[0], &option); if (r < 0) { p9_debug(P9_DEBUG_ERROR, @@ -759,6 +766,9 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) case Opt_wfdno: opts->wfd = option; break; + case Opt_privport: + opts->privport = 1; + break; default: continue; } @@ -898,6 +908,24 @@ static inline int valid_ipaddr4(const char *buf) return 0; } +static int p9_bind_privport(struct socket *sock) +{ + struct sockaddr_in cl; + int port, err = -EINVAL; + + memset(&cl, 0, sizeof(cl)); + cl.sin_family = AF_INET; + cl.sin_addr.s_addr = INADDR_ANY; + for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) { + cl.sin_port = htons((ushort)port); + err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl)); + if (err != -EADDRINUSE) + break; + } + return err; +} + + static int p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) { @@ -926,6 +954,16 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) return err; } + if (opts.privport) { + err = p9_bind_privport(csocket); + if (err < 0) { + pr_err("%s (%d): problem binding to privport\n", + __func__, task_pid_nr(current)); + sock_release(csocket); + return err; + } + } + err = csocket->ops->connect(csocket, (struct sockaddr *)&sin_server, sizeof(struct sockaddr_in), 0); -- GitLab From d9a738597faf7cd2edeec82ce8fd81969fed8390 Mon Sep 17 00:00:00 2001 From: Jim Garlick Date: Wed, 29 May 2013 12:09:39 -0700 Subject: [PATCH 2390/2900] fs/9p: xattr: add trusted and security namespaces Allow requests for security.* and trusted.* xattr name spaces to pass through to server. The new files are 99% cut and paste from fs/9p/xattr_user.c with the namespaces changed. It has the intended effect in superficial testing. I do not know much detail about how these namespaces are used, but passing them through to the server, which can decide whether to handle them or not, seems reasonable. I want to support a use case where an ext4 file system is mounted via 9P, then re-exported via samba to windows clients in a cluster. Windows wants to store xattrs such as security.NTACL. This works when ext4 directly backs samba, but not when 9P is inserted. This use case is documented here: http://code.google.com/p/diod/issues/detail?id=95 Signed-off-by: Jim Garlick Signed-off-by: Eric Van Hensbergen --- fs/9p/Kconfig | 13 +++++++ fs/9p/Makefile | 4 ++- fs/9p/xattr.c | 4 +++ fs/9p/xattr.h | 2 ++ fs/9p/xattr_security.c | 80 ++++++++++++++++++++++++++++++++++++++++++ fs/9p/xattr_trusted.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 fs/9p/xattr_security.c create mode 100644 fs/9p/xattr_trusted.c diff --git a/fs/9p/Kconfig b/fs/9p/Kconfig index 55abfd62654a..6489e1fc1afd 100644 --- a/fs/9p/Kconfig +++ b/fs/9p/Kconfig @@ -31,3 +31,16 @@ config 9P_FS_POSIX_ACL If you don't know what Access Control Lists are, say N endif + + +config 9P_FS_SECURITY + bool "9P Security Labels" + depends on 9P_FS + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the 9P filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. diff --git a/fs/9p/Makefile b/fs/9p/Makefile index ab8c12780634..ff7be98f84f2 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile @@ -11,7 +11,9 @@ obj-$(CONFIG_9P_FS) := 9p.o v9fs.o \ fid.o \ xattr.o \ - xattr_user.o + xattr_user.o \ + xattr_trusted.o 9p-$(CONFIG_9P_FSCACHE) += cache.o 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o +9p-$(CONFIG_9P_FS_SECURITY) += xattr_security.o diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index c45e016b190f..3c28cdfb8c47 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c @@ -167,9 +167,13 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) const struct xattr_handler *v9fs_xattr_handlers[] = { &v9fs_xattr_user_handler, + &v9fs_xattr_trusted_handler, #ifdef CONFIG_9P_FS_POSIX_ACL &v9fs_xattr_acl_access_handler, &v9fs_xattr_acl_default_handler, +#endif +#ifdef CONFIG_9P_FS_SECURITY + &v9fs_xattr_security_handler, #endif NULL }; diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h index eec348a3df71..d3e2ea3840be 100644 --- a/fs/9p/xattr.h +++ b/fs/9p/xattr.h @@ -20,6 +20,8 @@ extern const struct xattr_handler *v9fs_xattr_handlers[]; extern struct xattr_handler v9fs_xattr_user_handler; +extern struct xattr_handler v9fs_xattr_trusted_handler; +extern struct xattr_handler v9fs_xattr_security_handler; extern const struct xattr_handler v9fs_xattr_acl_access_handler; extern const struct xattr_handler v9fs_xattr_acl_default_handler; diff --git a/fs/9p/xattr_security.c b/fs/9p/xattr_security.c new file mode 100644 index 000000000000..cb247a142a6e --- /dev/null +++ b/fs/9p/xattr_security.c @@ -0,0 +1,80 @@ +/* + * Copyright IBM Corporation, 2010 + * Author Aneesh Kumar K.V + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + +#include +#include +#include +#include +#include "xattr.h" + +static int v9fs_xattr_security_get(struct dentry *dentry, const char *name, + void *buffer, size_t size, int type) +{ + int retval; + char *full_name; + size_t name_len; + size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; + + if (name == NULL) + return -EINVAL; + + if (strcmp(name, "") == 0) + return -EINVAL; + + name_len = strlen(name); + full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); + if (!full_name) + return -ENOMEM; + memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len); + memcpy(full_name+prefix_len, name, name_len); + full_name[prefix_len + name_len] = '\0'; + + retval = v9fs_xattr_get(dentry, full_name, buffer, size); + kfree(full_name); + return retval; +} + +static int v9fs_xattr_security_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + int retval; + char *full_name; + size_t name_len; + size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; + + if (name == NULL) + return -EINVAL; + + if (strcmp(name, "") == 0) + return -EINVAL; + + name_len = strlen(name); + full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); + if (!full_name) + return -ENOMEM; + memcpy(full_name, XATTR_SECURITY_PREFIX, prefix_len); + memcpy(full_name + prefix_len, name, name_len); + full_name[prefix_len + name_len] = '\0'; + + retval = v9fs_xattr_set(dentry, full_name, value, size, flags); + kfree(full_name); + return retval; +} + +struct xattr_handler v9fs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .get = v9fs_xattr_security_get, + .set = v9fs_xattr_security_set, +}; diff --git a/fs/9p/xattr_trusted.c b/fs/9p/xattr_trusted.c new file mode 100644 index 000000000000..e30d33b8a3fb --- /dev/null +++ b/fs/9p/xattr_trusted.c @@ -0,0 +1,80 @@ +/* + * Copyright IBM Corporation, 2010 + * Author Aneesh Kumar K.V + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + +#include +#include +#include +#include +#include "xattr.h" + +static int v9fs_xattr_trusted_get(struct dentry *dentry, const char *name, + void *buffer, size_t size, int type) +{ + int retval; + char *full_name; + size_t name_len; + size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; + + if (name == NULL) + return -EINVAL; + + if (strcmp(name, "") == 0) + return -EINVAL; + + name_len = strlen(name); + full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); + if (!full_name) + return -ENOMEM; + memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len); + memcpy(full_name+prefix_len, name, name_len); + full_name[prefix_len + name_len] = '\0'; + + retval = v9fs_xattr_get(dentry, full_name, buffer, size); + kfree(full_name); + return retval; +} + +static int v9fs_xattr_trusted_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + int retval; + char *full_name; + size_t name_len; + size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; + + if (name == NULL) + return -EINVAL; + + if (strcmp(name, "") == 0) + return -EINVAL; + + name_len = strlen(name); + full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); + if (!full_name) + return -ENOMEM; + memcpy(full_name, XATTR_TRUSTED_PREFIX, prefix_len); + memcpy(full_name + prefix_len, name, name_len); + full_name[prefix_len + name_len] = '\0'; + + retval = v9fs_xattr_set(dentry, full_name, value, size, flags); + kfree(full_name); + return retval; +} + +struct xattr_handler v9fs_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .get = v9fs_xattr_trusted_get, + .set = v9fs_xattr_trusted_set, +}; -- GitLab From ea071aa1365eaf8a79b33bd8699cb0811dcddf34 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:34 +0200 Subject: [PATCH 2391/2900] 9P: Fix fcall allocation for rdma The current code assumes that when a request in the request array does have a tc, it also has a rc. This is normally true, but not always : when using RDMA, req->rc will temporarily be set to NULL after the request has been sent. That is usually OK though, as when the reply arrives, req->rc will be reassigned to a sane value before the request is recycled. But there is a catch : if the request is flushed, the reply will never arrive, and req->rc will be NULL, but not req->tc. This patch fixes p9_tag_alloc to take this into account. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/client.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 01f1779eba80..5828769d1f3d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -258,27 +258,25 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) req = &c->reqs[row][col]; if (!req->tc) { req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); - if (!req->wq) { - pr_err("Couldn't grow tag array\n"); - return ERR_PTR(-ENOMEM); - } + if (!req->wq) + goto grow_failed; + init_waitqueue_head(req->wq); req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); + if (!req->tc) + goto grow_failed; + + req->tc->capacity = alloc_msize; + req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); + } + if (!req->rc) { req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); - if ((!req->tc) || (!req->rc)) { - pr_err("Couldn't grow tag array\n"); - kfree(req->tc); - kfree(req->rc); - kfree(req->wq); - req->tc = req->rc = NULL; - req->wq = NULL; - return ERR_PTR(-ENOMEM); - } - req->tc->capacity = alloc_msize; + if (!req->rc) + goto grow_failed; + req->rc->capacity = alloc_msize; - req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); } @@ -288,7 +286,16 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) req->tc->tag = tag-1; req->status = REQ_STATUS_ALLOC; - return &c->reqs[row][col]; + return req; + +grow_failed: + pr_err("Couldn't grow tag array\n"); + kfree(req->tc); + kfree(req->rc); + kfree(req->wq); + req->tc = req->rc = NULL; + req->wq = NULL; + return ERR_PTR(-ENOMEM); } /** -- GitLab From 17b6fd9d6dfa0faed3a25a6045f7456821ea140a Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:35 +0200 Subject: [PATCH 2392/2900] 9P/RDMA: rdma_request() needs not allocate req->rc p9_tag_alloc() takes care of that. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 2c69ddd691a1..b1dfdf2078ff 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -427,26 +427,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) err = -ENOMEM; goto err_close; } - - /* - * If the request has a buffer, steal it, otherwise - * allocate a new one. Typically, requests should already - * have receive buffers allocated and just swap them around - */ - if (!req->rc) { - req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize, - GFP_NOFS); - if (req->rc) { - req->rc->sdata = (char *) req->rc + - sizeof(struct p9_fcall); - req->rc->capacity = client->msize; - } - } rpl_context->rc = req->rc; - if (!rpl_context->rc) { - err = -ENOMEM; - goto err_free2; - } /* * Post a receive buffer for this request. We need to ensure -- GitLab From 5387320d4814aa1e40b50529d960a8f2b3340535 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:36 +0200 Subject: [PATCH 2393/2900] 9pnet: refactor struct p9_fcall alloc code Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/client.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 5828769d1f3d..db5bf2480a33 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -204,6 +204,17 @@ static int parse_opts(char *opts, struct p9_client *clnt) return ret; } +struct p9_fcall *p9_fcall_alloc(int alloc_msize) +{ + struct p9_fcall *fc; + fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); + if (!fc) + return NULL; + fc->capacity = alloc_msize; + fc->sdata = (char *) fc + sizeof(struct p9_fcall); + return fc; +} + /** * p9_tag_alloc - lookup/allocate a request by tag * @c: client session to lookup tag within @@ -256,29 +267,19 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) col = tag % P9_ROW_MAXTAG; req = &c->reqs[row][col]; - if (!req->tc) { + if (!req->wq) { req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); if (!req->wq) goto grow_failed; - init_waitqueue_head(req->wq); - req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, - GFP_NOFS); - if (!req->tc) - goto grow_failed; - - req->tc->capacity = alloc_msize; - req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); } - if (!req->rc) { - req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, - GFP_NOFS); - if (!req->rc) - goto grow_failed; - req->rc->capacity = alloc_msize; - req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); - } + if (!req->tc) + req->tc = p9_fcall_alloc(alloc_msize); + if (!req->rc) + req->rc = p9_fcall_alloc(alloc_msize); + if (!req->tc || !req->rc) + goto grow_failed; p9pdu_reset(req->tc); p9pdu_reset(req->rc); -- GitLab From 3fcc62f4e8620fd5f85f957a5e708e69a20adb51 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:37 +0200 Subject: [PATCH 2394/2900] 9P/RDMA: increase P9_RDMA_MAXSIZE to 1MB The current value is too low to get good performance. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index b1dfdf2078ff..b8b66d38f5b0 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -57,9 +57,7 @@ #define P9_RDMA_IRD 0 #define P9_RDMA_ORD 0 #define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ -#define P9_RDMA_MAXSIZE (4*4096) /* Min SGE is 4, so we can - * safely advertise a maxsize - * of 64k */ +#define P9_RDMA_MAXSIZE (1024*1024) /* 1MB */ /** * struct p9_trans_rdma - RDMA transport instance -- GitLab From 47229ff85e5a0b0613df2288d212938aeb9687da Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:38 +0200 Subject: [PATCH 2395/2900] 9P/RDMA: Protect against duplicate replies A well-behaved server would not send twice the reply to a request. But if it ever happens... This additional check prevents the kernel from leaking memory and possibly more nasty consequences in that unlikely event. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index b8b66d38f5b0..274a9c1d3c3d 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -294,6 +294,13 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, if (!req) goto err_out; + /* Check that we have not yet received a reply for this request. + */ + if (unlikely(req->rc)) { + pr_err("Duplicate reply for request %d", tag); + goto err_out; + } + req->rc = c->rc; req->status = REQ_STATUS_RCVD; p9_client_cb(client, req); -- GitLab From fd453d0ed6c1dacef8eff466df473d62d63db1e9 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:39 +0200 Subject: [PATCH 2396/2900] 9P/RDMA: Use a semaphore to protect the RQ The current code keeps track of the number of buffers posted in the RQ, and will prevent it from overflowing. But it does so by simply dropping post requests (And leaking memory in the process). When this happens there will actually be too few buffers posted, and soon the 9P server will complain about 'RNR retry counter exceeded' errors. Instead, use a semaphore, and block until the RQ is ready for another buffer to be posted. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 274a9c1d3c3d..ad8dc331574b 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -73,7 +73,7 @@ * @sq_depth: The depth of the Send Queue * @sq_sem: Semaphore for the SQ * @rq_depth: The depth of the Receive Queue. - * @rq_count: Count of requests in the Receive Queue. + * @rq_sem: Semaphore for the RQ * @addr: The remote peer's address * @req_lock: Protects the active request list * @cm_done: Completion event for connection management tracking @@ -98,7 +98,7 @@ struct p9_trans_rdma { int sq_depth; struct semaphore sq_sem; int rq_depth; - atomic_t rq_count; + struct semaphore rq_sem; struct sockaddr_in addr; spinlock_t req_lock; @@ -341,8 +341,8 @@ static void cq_comp_handler(struct ib_cq *cq, void *cq_context) switch (c->wc_op) { case IB_WC_RECV: - atomic_dec(&rdma->rq_count); handle_recv(client, rdma, c, wc.status, wc.byte_len); + up(&rdma->rq_sem); break; case IB_WC_SEND: @@ -441,12 +441,14 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) * outstanding request, so we must keep a count to avoid * overflowing the RQ. */ - if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) { - err = post_recv(client, rpl_context); - if (err) - goto err_free1; - } else - atomic_dec(&rdma->rq_count); + if (down_interruptible(&rdma->rq_sem)) + goto error; /* FIXME : -EINTR instead */ + + err = post_recv(client, rpl_context); + if (err) { + p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); + goto err_free1; + } /* remove posted receive buffer from request structure */ req->rc = NULL; @@ -537,7 +539,7 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) spin_lock_init(&rdma->req_lock); init_completion(&rdma->cm_done); sema_init(&rdma->sq_sem, rdma->sq_depth); - atomic_set(&rdma->rq_count, 0); + sema_init(&rdma->rq_sem, rdma->rq_depth); return rdma; } -- GitLab From b530e252e291c27fdcb1b73c72ad17f75c8bdba6 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:40 +0200 Subject: [PATCH 2397/2900] 9P/RDMA: Do not free req->rc in error handling in rdma_request() rdma_request() should never be in charge of freeing rc. When an error occurs: * Either the rc buffer has been recv_post()'ed. then kfree()'ing it certainly is a bad idea. * Or is has not, and in that case req->rc still points to it, hence it needs not be freed. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index ad8dc331574b..1bd4c7150114 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -447,7 +447,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) err = post_recv(client, rpl_context); if (err) { p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); - goto err_free1; + goto err_free; } /* remove posted receive buffer from request structure */ @@ -457,7 +457,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) c = kmalloc(sizeof *c, GFP_NOFS); if (!c) { err = -ENOMEM; - goto err_free1; + goto err_free; } c->req = req; @@ -486,13 +486,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) error: kfree(c); - kfree(rpl_context->rc); kfree(rpl_context); p9_debug(P9_DEBUG_ERROR, "EIO\n"); return -EIO; - err_free1: - kfree(rpl_context->rc); - err_free2: + err_free: kfree(rpl_context); err_close: spin_lock_irqsave(&rdma->req_lock, flags); -- GitLab From 2f52d07cb75d96fcbb5b9ab72938590fa9ffb19d Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:41 +0200 Subject: [PATCH 2398/2900] 9P/RDMA: Improve error handling in rdma_request Most importantly: - do not free the recv context (rpl_context) after a successful post_recv() - but do free the send context (c) after a failed send. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/trans_rdma.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 1bd4c7150114..926e72d00e57 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -430,7 +430,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); if (!rpl_context) { err = -ENOMEM; - goto err_close; + goto recv_error; } rpl_context->rc = req->rc; @@ -441,13 +441,15 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) * outstanding request, so we must keep a count to avoid * overflowing the RQ. */ - if (down_interruptible(&rdma->rq_sem)) - goto error; /* FIXME : -EINTR instead */ + if (down_interruptible(&rdma->rq_sem)) { + err = -EINTR; + goto recv_error; + } err = post_recv(client, rpl_context); if (err) { p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); - goto err_free; + goto recv_error; } /* remove posted receive buffer from request structure */ @@ -457,15 +459,17 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) c = kmalloc(sizeof *c, GFP_NOFS); if (!c) { err = -ENOMEM; - goto err_free; + goto send_error; } c->req = req; c->busa = ib_dma_map_single(rdma->cm_id->device, c->req->tc->sdata, c->req->tc->size, DMA_TO_DEVICE); - if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) - goto error; + if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) { + err = -EIO; + goto send_error; + } sge.addr = c->busa; sge.length = c->req->tc->size; @@ -479,19 +483,27 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) wr.sg_list = &sge; wr.num_sge = 1; - if (down_interruptible(&rdma->sq_sem)) - goto error; + if (down_interruptible(&rdma->sq_sem)) { + err = -EINTR; + goto send_error; + } - return ib_post_send(rdma->qp, &wr, &bad_wr); + err = ib_post_send(rdma->qp, &wr, &bad_wr); + if (err) + goto send_error; - error: + /* Success */ + return 0; + + /* Handle errors that happened during or while preparing the send: */ + send_error: kfree(c); + p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); + return err; + + /* Handle errors that happened during or while preparing post_recv(): */ + recv_error: kfree(rpl_context); - p9_debug(P9_DEBUG_ERROR, "EIO\n"); - return -EIO; - err_free: - kfree(rpl_context); - err_close: spin_lock_irqsave(&rdma->req_lock, flags); if (rdma->state < P9_RDMA_CLOSING) { rdma->state = P9_RDMA_CLOSING; -- GitLab From 1cff33069a4a1ac9ed080756113ecd17ad408282 Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:42 +0200 Subject: [PATCH 2399/2900] 9P/RDMA: count posted buffers without a pending request In rdma_request(): If an error occurs between posting the recv and the send, there will be a reply context posted without a pending request. Since there is no way to "un-post" it, we remember it and skip post_recv() for the next request. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- net/9p/client.c | 6 ++++-- net/9p/trans_rdma.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index db5bf2480a33..d18a0b22f62c 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -656,8 +656,10 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) return PTR_ERR(req); - /* if we haven't received a response for oldreq, - remove it from the list. */ + /* + * if we haven't received a response for oldreq, + * remove it from the list. + */ spin_lock(&c->lock); if (oldreq->status == REQ_STATUS_FLSH) list_del(&oldreq->req_list); diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 926e72d00e57..8f68df5d2973 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -74,6 +74,8 @@ * @sq_sem: Semaphore for the SQ * @rq_depth: The depth of the Receive Queue. * @rq_sem: Semaphore for the RQ + * @excess_rc : Amount of posted Receive Contexts without a pending request. + * See rdma_request() * @addr: The remote peer's address * @req_lock: Protects the active request list * @cm_done: Completion event for connection management tracking @@ -99,6 +101,7 @@ struct p9_trans_rdma { struct semaphore sq_sem; int rq_depth; struct semaphore rq_sem; + atomic_t excess_rc; struct sockaddr_in addr; spinlock_t req_lock; @@ -426,6 +429,26 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) struct p9_rdma_context *c = NULL; struct p9_rdma_context *rpl_context = NULL; + /* When an error occurs between posting the recv and the send, + * there will be a receive context posted without a pending request. + * Since there is no way to "un-post" it, we remember it and skip + * post_recv() for the next request. + * So here, + * see if we are this `next request' and need to absorb an excess rc. + * If yes, then drop and free our own, and do not recv_post(). + **/ + if (unlikely(atomic_read(&rdma->excess_rc) > 0)) { + if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) { + /* Got one ! */ + kfree(req->rc); + req->rc = NULL; + goto dont_need_post_recv; + } else { + /* We raced and lost. */ + atomic_inc(&rdma->excess_rc); + } + } + /* Allocate an fcall for the reply */ rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); if (!rpl_context) { @@ -451,10 +474,10 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); goto recv_error; } - /* remove posted receive buffer from request structure */ req->rc = NULL; +dont_need_post_recv: /* Post the request */ c = kmalloc(sizeof *c, GFP_NOFS); if (!c) { @@ -499,6 +522,11 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) send_error: kfree(c); p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); + + /* Ach. + * We did recv_post(), but not send. We have one recv_post in excess. + */ + atomic_inc(&rdma->excess_rc); return err; /* Handle errors that happened during or while preparing post_recv(): */ @@ -549,6 +577,7 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) init_completion(&rdma->cm_done); sema_init(&rdma->sq_sem, rdma->sq_depth); sema_init(&rdma->rq_sem, rdma->rq_depth); + atomic_set(&rdma->excess_rc, 0); return rdma; } -- GitLab From 80b45261a0b263536b043c5ccfc4ba4fc27c2acc Mon Sep 17 00:00:00 2001 From: Simon Derr Date: Fri, 21 Jun 2013 15:32:43 +0200 Subject: [PATCH 2400/2900] 9P: Add cancelled() to the transport functions. RDMA needs to post a buffer for each incoming reply. Hence it needs to keep count of these and needs to be aware of whether a flushed request has received a reply or not. This patch adds the cancelled() callback to the transport modules. It is called when RFLUSH has been received and that the corresponding request will never receive a reply. Signed-off-by: Simon Derr Signed-off-by: Eric Van Hensbergen --- include/net/9p/transport.h | 3 +++ net/9p/client.c | 12 +++++++++--- net/9p/trans_rdma.c | 11 +++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 9a36d9297114..d9fa68f26c41 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -40,6 +40,8 @@ * @close: member function to discard a connection on this transport * @request: member function to issue a request to the transport * @cancel: member function to cancel a request (if it hasn't been sent) + * @cancelled: member function to notify that a cancelled request will not + * not receive a reply * * This is the basic API for a transport module which is registered by the * transport module with the 9P core network module and used by the client @@ -58,6 +60,7 @@ struct p9_trans_module { void (*close) (struct p9_client *); int (*request) (struct p9_client *, struct p9_req_t *req); int (*cancel) (struct p9_client *, struct p9_req_t *req); + int (*cancelled)(struct p9_client *, struct p9_req_t *req); int (*zc_request)(struct p9_client *, struct p9_req_t *, char *, char *, int , int, int, int); }; diff --git a/net/9p/client.c b/net/9p/client.c index d18a0b22f62c..8b93cae2d11d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -658,12 +658,18 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) /* * if we haven't received a response for oldreq, - * remove it from the list. + * remove it from the list, and notify the transport + * layer that the reply will never arrive. */ spin_lock(&c->lock); - if (oldreq->status == REQ_STATUS_FLSH) + if (oldreq->status == REQ_STATUS_FLSH) { list_del(&oldreq->req_list); - spin_unlock(&c->lock); + spin_unlock(&c->lock); + if (c->trans_mod->cancelled) + c->trans_mod->cancelled(c, req); + } else { + spin_unlock(&c->lock); + } p9_free_req(c, req); return 0; diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 8f68df5d2973..928f2bb9bf8d 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -588,6 +588,17 @@ static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) return 1; } +/* A request has been fully flushed without a reply. + * That means we have posted one buffer in excess. + */ +static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req) +{ + struct p9_trans_rdma *rdma = client->trans; + + atomic_inc(&rdma->excess_rc); + return 0; +} + /** * trans_create_rdma - Transport method for creating atransport instance * @client: client instance -- GitLab From f2692ea8d5b535277bc06b315eabd32ef4e7a11c Mon Sep 17 00:00:00 2001 From: Gu Zheng Date: Fri, 28 Jun 2013 12:44:13 -0500 Subject: [PATCH 2401/2900] fs/9p: Remove the unused variable "err" in v9fs_vfs_getattr() Delete the unused variable "err" in v9fs_vfs_getattr() Signed-off-by: Gu Zheng Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index d86edc8d3fd0..25b018efb8ab 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1054,13 +1054,11 @@ static int v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - int err; struct v9fs_session_info *v9ses; struct p9_fid *fid; struct p9_wstat *st; p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); - err = -EPERM; v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { generic_fillattr(dentry->d_inode, stat); -- GitLab From 6f94d5de090947eb41efe9d3841d75ad91fd6dc7 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 4 Jun 2013 12:05:07 -0700 Subject: [PATCH 2402/2900] [SCSI] storvsc: Implement multi-channel support Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 131 +++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 945198910460..1d4d42506ef8 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -328,6 +328,8 @@ static int storvsc_timeout = 180; #define STORVSC_MAX_IO_REQUESTS 128 +static void storvsc_on_channel_callback(void *context); + /* * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In * reality, the path/target is not used (ie always set to 0) so our @@ -364,6 +366,7 @@ struct storvsc_device { bool destroy; bool drain_notify; + bool open_sub_channel; atomic_t num_outstanding_req; struct Scsi_Host *host; @@ -755,12 +758,104 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, return total_copied; } +static void handle_sc_creation(struct vmbus_channel *new_sc) +{ + struct hv_device *device = new_sc->primary_channel->device_obj; + struct storvsc_device *stor_device; + struct vmstorage_channel_properties props; + + stor_device = get_out_stor_device(device); + if (!stor_device) + return; + + if (stor_device->open_sub_channel == false) + return; + + memset(&props, 0, sizeof(struct vmstorage_channel_properties)); + + vmbus_open(new_sc, + storvsc_ringbuffer_size, + storvsc_ringbuffer_size, + (void *)&props, + sizeof(struct vmstorage_channel_properties), + storvsc_on_channel_callback, new_sc); +} + +static void handle_multichannel_storage(struct hv_device *device, int max_chns) +{ + struct storvsc_device *stor_device; + int num_cpus = num_online_cpus(); + int num_sc; + struct storvsc_cmd_request *request; + struct vstor_packet *vstor_packet; + int ret, t; + + num_sc = ((max_chns > num_cpus) ? num_cpus : max_chns); + stor_device = get_out_stor_device(device); + if (!stor_device) + return; + + request = &stor_device->init_request; + vstor_packet = &request->vstor_packet; + + stor_device->open_sub_channel = true; + /* + * Establish a handler for dealing with subchannels. + */ + vmbus_set_sc_create_callback(device->channel, handle_sc_creation); + + /* + * Check to see if sub-channels have already been created. This + * can happen when this driver is re-loaded after unloading. + */ + + if (vmbus_are_subchannels_present(device->channel)) + return; + + stor_device->open_sub_channel = false; + /* + * Request the host to create sub-channels. + */ + memset(request, 0, sizeof(struct storvsc_cmd_request)); + init_completion(&request->wait_event); + vstor_packet->operation = VSTOR_OPERATION_CREATE_SUB_CHANNELS; + vstor_packet->flags = REQUEST_COMPLETION_FLAG; + vstor_packet->sub_channel_count = num_sc; + + ret = vmbus_sendpacket(device->channel, vstor_packet, + (sizeof(struct vstor_packet) - + vmscsi_size_delta), + (unsigned long)request, + VM_PKT_DATA_INBAND, + VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + + if (ret != 0) + return; + + t = wait_for_completion_timeout(&request->wait_event, 10*HZ); + if (t == 0) + return; + + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || + vstor_packet->status != 0) + return; + + /* + * Now that we created the sub-channels, invoke the check; this + * may trigger the callback. + */ + stor_device->open_sub_channel = true; + vmbus_are_subchannels_present(device->channel); +} + static int storvsc_channel_init(struct hv_device *device) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; struct vstor_packet *vstor_packet; int ret, t; + int max_chns; + bool process_sub_channels = false; stor_device = get_out_stor_device(device); if (!stor_device) @@ -855,6 +950,19 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->status != 0) goto cleanup; + /* + * Check to see if multi-channel support is there. + * Hosts that implement protocol version of 5.1 and above + * support multi-channel. + */ + max_chns = vstor_packet->storage_channel_properties.max_channel_cnt; + if ((vmbus_proto_version != VERSION_WIN7) && + (vmbus_proto_version != VERSION_WS2008)) { + if (vstor_packet->storage_channel_properties.flags & + STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) + process_sub_channels = true; + } + memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; @@ -879,6 +987,9 @@ static int storvsc_channel_init(struct hv_device *device) vstor_packet->status != 0) goto cleanup; + if (process_sub_channels) + handle_multichannel_storage(device, max_chns); + cleanup: return ret; @@ -1100,7 +1211,8 @@ static void storvsc_on_receive(struct hv_device *device, static void storvsc_on_channel_callback(void *context) { - struct hv_device *device = (struct hv_device *)context; + struct vmbus_channel *channel = (struct vmbus_channel *)context; + struct hv_device *device; struct storvsc_device *stor_device; u32 bytes_recvd; u64 request_id; @@ -1108,13 +1220,17 @@ static void storvsc_on_channel_callback(void *context) struct storvsc_cmd_request *request; int ret; + if (channel->primary_channel != NULL) + device = channel->primary_channel->device_obj; + else + device = channel->device_obj; stor_device = get_in_stor_device(device); if (!stor_device) return; do { - ret = vmbus_recvpacket(device->channel, packet, + ret = vmbus_recvpacket(channel, packet, ALIGN((sizeof(struct vstor_packet) - vmscsi_size_delta), 8), &bytes_recvd, &request_id); @@ -1155,7 +1271,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) ring_size, (void *)&props, sizeof(struct vmstorage_channel_properties), - storvsc_on_channel_callback, device); + storvsc_on_channel_callback, device->channel); if (ret != 0) return ret; @@ -1207,6 +1323,7 @@ static int storvsc_do_io(struct hv_device *device, { struct storvsc_device *stor_device; struct vstor_packet *vstor_packet; + struct vmbus_channel *outgoing_channel; int ret = 0; vstor_packet = &request->vstor_packet; @@ -1217,6 +1334,11 @@ static int storvsc_do_io(struct hv_device *device, request->device = device; + /* + * Select an an appropriate channel to send the request out. + */ + + outgoing_channel = vmbus_get_outgoing_channel(device->channel); vstor_packet->flags |= REQUEST_COMPLETION_FLAG; @@ -1234,7 +1356,7 @@ static int storvsc_do_io(struct hv_device *device, vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; if (request->data_buffer.len) { - ret = vmbus_sendpacket_multipagebuffer(device->channel, + ret = vmbus_sendpacket_multipagebuffer(outgoing_channel, &request->data_buffer, vstor_packet, (sizeof(struct vstor_packet) - @@ -1643,6 +1765,7 @@ static int storvsc_probe(struct hv_device *device, } stor_device->destroy = false; + stor_device->open_sub_channel = false; init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; stor_device->host = host; -- GitLab From bde6d0f9877e19fc9d309bbd624da422b18cdc3d Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 4 Jun 2013 12:05:08 -0700 Subject: [PATCH 2403/2900] [SCSI] storvsc: Support FC devices Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 1d4d42506ef8..b864e7c3da4b 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1702,6 +1702,7 @@ static struct scsi_host_template scsi_driver = { enum { SCSI_GUID, IDE_GUID, + SFC_GUID, }; static const struct hv_vmbus_device_id id_table[] = { @@ -1713,6 +1714,11 @@ static const struct hv_vmbus_device_id id_table[] = { { HV_IDE_GUID, .driver_data = IDE_GUID }, + /* Fibre Channel GUID */ + { + HV_SYNTHFC_GUID, + .driver_data = SFC_GUID + }, { }, }; -- GitLab From cd63a5ffd24214246b1092365c7d6c2cd5aca29b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 5 Jul 2013 12:13:59 +0200 Subject: [PATCH 2404/2900] ALSA: hda - Keep halting ALC5505 DSP ALC5505 DSP is enabled even though we don't use the features yet at all. This results in the unnecessarily high power consumption, more than 100mV higher. Until we implement the DSP support, better to bypass DSP for saving more power. Reported-by: Mengdong Lin [Patch modified by Mengdong to cal alc5505_dsp_init() with extra acl5505_dsp_halt().] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 14ac9b0e740c..8bd226149868 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -37,6 +37,9 @@ #include "hda_jack.h" #include "hda_generic.h" +/* keep halting ALC5505 DSP, for power saving */ +#define HALT_REALTEK_ALC5505 + /* unsol event tags */ #define ALC_DCVOL_EVENT 0x08 @@ -2659,15 +2662,27 @@ static void alc5505_dsp_init(struct hda_codec *codec) alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */ alc5505_coef_set(codec, 0x880c, 0x00000003); alc5505_coef_set(codec, 0x880c, 0x00000010); + +#ifdef HALT_REALTEK_ALC5505 + alc5505_dsp_halt(codec); +#endif } +#ifdef HALT_REALTEK_ALC5505 +#define alc5505_dsp_suspend(codec) /* NOP */ +#define alc5505_dsp_resume(codec) /* NOP */ +#else +#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec) +#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec) +#endif + #ifdef CONFIG_PM static int alc269_suspend(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; if (spec->has_alc5505_dsp) - alc5505_dsp_halt(codec); + alc5505_dsp_suspend(codec); return alc_suspend(codec); } @@ -2696,7 +2711,7 @@ static int alc269_resume(struct hda_codec *codec) alc_inv_dmic_sync(codec, true); hda_call_check_power_status(codec, 0x01); if (spec->has_alc5505_dsp) - alc5505_dsp_back_from_halt(codec); + alc5505_dsp_resume(codec); return 0; } #endif /* CONFIG_PM */ -- GitLab From 276a2439ce7917b8c3043af7ad6bf17bbcc24030 Mon Sep 17 00:00:00 2001 From: Wanpeng Li Date: Mon, 8 Jul 2013 08:08:28 +0800 Subject: [PATCH 2405/2900] mm/slab: Give s_next and s_stop slab-specific names Give s_next and s_stop slab-specific names instead of exporting "s_next" and "s_stop". Signed-off-by: Wanpeng Li Signed-off-by: Pekka Enberg --- mm/slab.c | 4 ++-- mm/slab.h | 4 ++-- mm/slab_common.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mm/slab.c b/mm/slab.c index 9bf225162fcb..57ab42297d96 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4440,8 +4440,8 @@ static int leaks_show(struct seq_file *m, void *p) static const struct seq_operations slabstats_op = { .start = leaks_start, - .next = s_next, - .stop = s_stop, + .next = slab_next, + .stop = slab_stop, .show = leaks_show, }; diff --git a/mm/slab.h b/mm/slab.h index 95c88604aab7..620ceeddbe1a 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -272,5 +272,5 @@ struct kmem_cache_node { }; -void *s_next(struct seq_file *m, void *p, loff_t *pos); -void s_stop(struct seq_file *m, void *p); +void *slab_next(struct seq_file *m, void *p, loff_t *pos); +void slab_stop(struct seq_file *m, void *p); diff --git a/mm/slab_common.c b/mm/slab_common.c index 13ae037c71d4..eacdffaf71c9 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -536,12 +536,12 @@ static void *s_start(struct seq_file *m, loff_t *pos) return seq_list_start(&slab_caches, *pos); } -void *s_next(struct seq_file *m, void *p, loff_t *pos) +void *slab_next(struct seq_file *m, void *p, loff_t *pos) { return seq_list_next(p, &slab_caches, pos); } -void s_stop(struct seq_file *m, void *p) +void slab_stop(struct seq_file *m, void *p) { mutex_unlock(&slab_mutex); } @@ -618,8 +618,8 @@ static int s_show(struct seq_file *m, void *p) */ static const struct seq_operations slabinfo_op = { .start = s_start, - .next = s_next, - .stop = s_stop, + .next = slab_next, + .stop = slab_stop, .show = s_show, }; -- GitLab From f47a3ca224deff9e768eb49487afa391e28b06b0 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 3 Jun 2013 11:07:26 +0300 Subject: [PATCH 2406/2900] xtensa: tell git to ignore copied zlib source files Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/boot/lib/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 arch/xtensa/boot/lib/.gitignore diff --git a/arch/xtensa/boot/lib/.gitignore b/arch/xtensa/boot/lib/.gitignore new file mode 100644 index 000000000000..1629a6167755 --- /dev/null +++ b/arch/xtensa/boot/lib/.gitignore @@ -0,0 +1,3 @@ +inffast.c +inflate.c +inftrees.c -- GitLab From ed9dfed62c6c057c1c51295d4373ae55c9284a10 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 17 Jun 2013 11:29:42 +0300 Subject: [PATCH 2407/2900] xtensa: timex.h: remove unused symbols Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/timex.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index 3d35e5d0367e..c47989a0e3ad 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h @@ -35,19 +35,12 @@ # error "Bad timer number for Linux configurations!" #endif -#define LINUX_TIMER_MASK (1L << LINUX_TIMER_INT) - -#define CLOCK_TICK_RATE 1193180 /* (everyone is using this value) */ -#define CLOCK_TICK_FACTOR 20 /* Factor of both 10^6 and CLOCK_TICK_RATE */ - #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT extern unsigned long ccount_per_jiffy; extern unsigned long nsec_per_ccount; #define CCOUNT_PER_JIFFY ccount_per_jiffy -#define NSEC_PER_CCOUNT nsec_per_ccount #else #define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ)) -#define NSEC_PER_CCOUNT (1000UL / CONFIG_XTENSA_CPU_CLOCK) #endif -- GitLab From e504c4b6076d9ec1caccaac65803fe3fc29afec8 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 17 Jun 2013 11:29:43 +0300 Subject: [PATCH 2408/2900] xtensa: cleanup ccount frequency tracking Remove unused nsec_per_ccount, and rename ccount_per_jiffy to ccount_preq. Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/timex.h | 5 ++--- arch/xtensa/kernel/platform.c | 2 +- arch/xtensa/kernel/time.c | 7 +++---- arch/xtensa/platforms/xtfpga/setup.c | 3 +-- arch/xtensa/variants/s6000/delay.c | 3 +-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index c47989a0e3ad..69f901713fb6 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h @@ -36,9 +36,8 @@ #endif #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT -extern unsigned long ccount_per_jiffy; -extern unsigned long nsec_per_ccount; -#define CCOUNT_PER_JIFFY ccount_per_jiffy +extern unsigned long ccount_freq; +#define CCOUNT_PER_JIFFY (ccount_freq / HZ) #else #define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ)) #endif diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index da827cbb2f59..1cf008284dd2 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -41,6 +41,6 @@ _F(void, pcibios_init, (void), { }); _F(void, calibrate_ccount, (void), { pr_err("ERROR: Cannot calibrate cpu frequency! Assuming 10MHz.\n"); - ccount_per_jiffy = 10 * (1000000UL/HZ); + ccount_freq = 10 * 1000000UL; }); #endif diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index ffb474104311..a32bc2ea7982 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -28,8 +28,7 @@ #include #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT -unsigned long ccount_per_jiffy; /* per 1/HZ */ -unsigned long nsec_per_ccount; /* nsec per ccount increment */ +unsigned long ccount_freq; /* ccount Hz */ #endif static cycle_t ccount_read(struct clocksource *cs) @@ -57,8 +56,8 @@ void __init time_init(void) #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); platform_calibrate_ccount(); - printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), - (int)(ccount_per_jiffy/(10000/HZ))%100); + printk("%d.%02d MHz\n", (int)ccount_freq/1000000, + (int)(ccount_freq/10000)%100); #endif clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index c7ce62ff73f7..74bb74fa3f87 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c @@ -179,8 +179,7 @@ void __init platform_calibrate_ccount(void) if (!clk_freq) clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; - ccount_per_jiffy = clk_freq / HZ; - nsec_per_ccount = 1000000000UL / clk_freq; + ccount_freq = clk_freq; } #endif diff --git a/arch/xtensa/variants/s6000/delay.c b/arch/xtensa/variants/s6000/delay.c index 54b2b573f166..baefd3a3c2aa 100644 --- a/arch/xtensa/variants/s6000/delay.c +++ b/arch/xtensa/variants/s6000/delay.c @@ -22,6 +22,5 @@ void platform_calibrate_ccount(void) a = b; } while (--i >= 0); b -= a; - nsec_per_ccount = (LOOPS * 10000) / b; - ccount_per_jiffy = b * (100000UL / (LOOPS * HZ)); + ccount_freq = b * (100000UL / LOOPS); } -- GitLab From 8102f47ab5fcffc50f3ff94ca9b9073c12c18cc7 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 17 Jun 2013 11:29:44 +0300 Subject: [PATCH 2409/2900] xtensa: consolidate ccount access routines Use get_ccount everywhere; remove xtensa_get_ccount. Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/delay.h | 13 +++---------- arch/xtensa/variants/s6000/delay.c | 3 +-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/arch/xtensa/include/asm/delay.h b/arch/xtensa/include/asm/delay.h index 61fc5faeb46c..3899610c1dff 100644 --- a/arch/xtensa/include/asm/delay.h +++ b/arch/xtensa/include/asm/delay.h @@ -12,7 +12,7 @@ #ifndef _XTENSA_DELAY_H #define _XTENSA_DELAY_H -#include +#include #include extern unsigned long loops_per_jiffy; @@ -24,24 +24,17 @@ static inline void __delay(unsigned long loops) : "=r" (loops) : "0" (loops)); } -static __inline__ u32 xtensa_get_ccount(void) -{ - u32 ccount; - asm volatile ("rsr %0, ccount\n" : "=r" (ccount)); - return ccount; -} - /* For SMP/NUMA systems, change boot_cpu_data to something like * local_cpu_data->... where local_cpu_data points to the current * cpu. */ static __inline__ void udelay (unsigned long usecs) { - unsigned long start = xtensa_get_ccount(); + unsigned long start = get_ccount(); unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ)); /* Note: all variables are unsigned (can wrap around)! */ - while (((unsigned long)xtensa_get_ccount()) - start < cycles) + while (((unsigned long)get_ccount()) - start < cycles) ; } diff --git a/arch/xtensa/variants/s6000/delay.c b/arch/xtensa/variants/s6000/delay.c index baefd3a3c2aa..39154563ee17 100644 --- a/arch/xtensa/variants/s6000/delay.c +++ b/arch/xtensa/variants/s6000/delay.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -17,7 +16,7 @@ void platform_calibrate_ccount(void) "1: l32i %0, %2, 0 ;" " beq %0, %1, 1b ;" : "=&a"(u) : "a"(t), "a"(tstamp)); - b = xtensa_get_ccount(); + b = get_ccount(); if (i == LOOPS) a = b; } while (--i >= 0); -- GitLab From 925f5532e83bfe236b4f69ba4265c19663cfa9c7 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 18 Jun 2013 08:48:53 +0300 Subject: [PATCH 2410/2900] xtensa: ccount based clockevent implementation Reused some code from a preliminary implementation by Max Fillippov. Cc: Max Filippov Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/Kconfig | 1 + arch/xtensa/kernel/time.c | 110 +++++++++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 0a1b95f81a32..dadcf824a5cb 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -6,6 +6,7 @@ config XTENSA select ARCH_WANT_FRAME_POINTERS select HAVE_IDE select GENERIC_ATOMIC64 + select GENERIC_CLOCKEVENTS select HAVE_GENERIC_HARDIRQS select VIRT_TO_BUS select GENERIC_IRQ_SHOW diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index a32bc2ea7982..ece4f9588625 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -43,16 +44,80 @@ static struct clocksource ccount_clocksource = { .mask = CLOCKSOURCE_MASK(32), }; +static int ccount_timer_set_next_event(unsigned long delta, + struct clock_event_device *dev); +static void ccount_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt); +static struct ccount_timer_t { + struct clock_event_device evt; + int irq_enabled; +} ccount_timer = { + .evt = { + .name = "ccount_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = ccount_timer_set_next_event, + .set_mode = ccount_timer_set_mode, + }, +}; + +static int ccount_timer_set_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + unsigned long flags, next; + int ret = 0; + + local_irq_save(flags); + next = get_ccount() + delta; + set_linux_timer(next); + if (next - get_ccount() > delta) + ret = -ETIME; + local_irq_restore(flags); + + return ret; +} + +static void ccount_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + struct ccount_timer_t *timer = + container_of(evt, struct ccount_timer_t, evt); + + /* + * There is no way to disable the timer interrupt at the device level, + * only at the intenable register itself. Since enable_irq/disable_irq + * calls are nested, we need to make sure that these calls are + * balanced. + */ + switch (mode) { + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + if (timer->irq_enabled) { + disable_irq(evt->irq); + timer->irq_enabled = 0; + } + break; + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_ONESHOT: + if (!timer->irq_enabled) { + enable_irq(evt->irq); + timer->irq_enabled = 1; + } + default: + break; + } +} + static irqreturn_t timer_interrupt(int irq, void *dev_id); static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_TIMER, .name = "timer", + .dev_id = &ccount_timer, }; void __init time_init(void) { - unsigned int irq; #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); platform_calibrate_ccount(); @@ -61,11 +126,14 @@ void __init time_init(void) #endif clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); - /* Initialize the linux timer interrupt. */ - - irq = irq_create_mapping(NULL, LINUX_TIMER_INT); - setup_irq(irq, &timer_irqaction); - set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); + ccount_timer.evt.cpumask = cpumask_of(0); + ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); + if (WARN(!ccount_timer.evt.irq, "error: can't map timer irq")) + return; + clockevents_config_and_register(&ccount_timer.evt, ccount_freq, 0xf, + 0xffffffff); + setup_irq(ccount_timer.evt.irq, &timer_irqaction); + ccount_timer.irq_enabled = 1; } /* @@ -74,36 +142,14 @@ void __init time_init(void) irqreturn_t timer_interrupt (int irq, void *dev_id) { + struct ccount_timer_t *timer = dev_id; + struct clock_event_device *evt = &timer->evt; - unsigned long next; - - next = get_linux_timer(); - -again: - while ((signed long)(get_ccount() - next) > 0) { - - profile_tick(CPU_PROFILING); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - - xtime_update(1); /* Linux handler in kernel/time/timekeeping */ - - /* Note that writing CCOMPARE clears the interrupt. */ - - next += CCOUNT_PER_JIFFY; - set_linux_timer(next); - } + evt->event_handler(evt); /* Allow platform to do something useful (Wdog). */ - platform_heartbeat(); - /* Make sure we didn't miss any tick... */ - - if ((signed long)(get_ccount() - next) > 0) - goto again; - return IRQ_HANDLED; } -- GitLab From e3f432919feb4f26fe837472669e397ba8e8fccb Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 17 Jun 2013 11:29:46 +0300 Subject: [PATCH 2411/2900] xtensa: ccount based sched_clock Signed-off-by: Baruch Siach Signed-off-by: Chris Zankel --- arch/xtensa/Kconfig | 1 + arch/xtensa/kernel/time.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index dadcf824a5cb..8852c0d35834 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -11,6 +11,7 @@ config XTENSA select VIRT_TO_BUS select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES + select GENERIC_SCHED_CLOCK select MODULES_USE_ELF_RELA select GENERIC_PCI_IOMAP select ARCH_WANT_IPC_PARSE_VERSION diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index ece4f9588625..bdbb17312526 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,11 @@ static cycle_t ccount_read(struct clocksource *cs) return (cycle_t)get_ccount(); } +static u32 notrace ccount_sched_clock_read(void) +{ + return get_ccount(); +} + static struct clocksource ccount_clocksource = { .name = "ccount", .rating = 200, @@ -134,6 +140,8 @@ void __init time_init(void) 0xffffffff); setup_irq(ccount_timer.evt.irq, &timer_irqaction); ccount_timer.irq_enabled = 1; + + setup_sched_clock(ccount_sched_clock_read, 32, ccount_freq); } /* -- GitLab From 77b4dcdbfab4c288a3d211f307b5daa0bf45d0f8 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 7 Jun 2013 08:44:34 +0300 Subject: [PATCH 2412/2900] xtensa: tell git to ignore generated .dtb files Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/boot/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/xtensa/boot/.gitignore b/arch/xtensa/boot/.gitignore index 38177c7ebcab..be7655998b26 100644 --- a/arch/xtensa/boot/.gitignore +++ b/arch/xtensa/boot/.gitignore @@ -1,2 +1,3 @@ uImage zImage.redboot +*.dtb -- GitLab From 661b40b0362c16b9969bf018636fb60454f62ee5 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 6 Jun 2013 14:23:37 +0300 Subject: [PATCH 2413/2900] xtensa: bootparams: fix typo Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/include/asm/bootparam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h index 0c25799facab..23392c5630ce 100644 --- a/arch/xtensa/include/asm/bootparam.h +++ b/arch/xtensa/include/asm/bootparam.h @@ -20,7 +20,7 @@ #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ #define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ #define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ -#define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */ +#define BP_TAG_SERIAL_BAUDRATE 0x1004 /* baud rate of current console. */ #define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ #define BP_TAG_FDT 0x1006 /* flat device tree addr */ -- GitLab From c5a771d0678f9613e9f89cf1a5bdcfa5b08b225b Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 9 Jun 2013 04:52:11 +0400 Subject: [PATCH 2414/2900] xtensa: adjust boot parameters address when INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX is selected The virtual address of boot parameters chain is passed to the kernel via a2 register. Adjust it in case it is remapped during MMUv3 -> MMUv2 mapping change, i.e. when it is in the first 128M. Also fix interpretation of initrd and FDT addresses passed in the boot parameters: these are physical addresses. Cc: stable@vger.kernel.org Reported-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/head.S | 9 +++++++++ arch/xtensa/kernel/setup.c | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index ef12c0e6fa25..7d740ebbe198 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -68,6 +68,15 @@ _SetupMMU: #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX initialize_mmu +#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY + rsr a2, excsave1 + movi a3, 0x08000000 + bgeu a2, a3, 1f + movi a3, 0xd0000000 + add a2, a2, a3 + wsr a2, excsave1 +1: +#endif #endif .end no-absolute-literals diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 6dd25ecde3f5..14c6c3a6f04b 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -152,8 +152,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag) { meminfo_t* mi; mi = (meminfo_t*)(tag->data); - initrd_start = (void*)(mi->start); - initrd_end = (void*)(mi->end); + initrd_start = __va(mi->start); + initrd_end = __va(mi->end); return 0; } @@ -164,7 +164,7 @@ __tagtable(BP_TAG_INITRD, parse_tag_initrd); static int __init parse_tag_fdt(const bp_tag_t *tag) { - dtb_start = (void *)(tag->data[0]); + dtb_start = __va(tag->data[0]); return 0; } -- GitLab From a99e07ee5e887750f5136bc6799abe47a56fd2c9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Wed, 15 May 2013 19:34:05 +0400 Subject: [PATCH 2415/2900] xtensa: check TLB sanity on return to userspace - check that user TLB mappings correspond to the current page table; - check that TLB mapping VPN is in the kernel/user address range in accordance with its ASID. Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/Kconfig.debug | 10 ++++ arch/xtensa/kernel/entry.S | 9 ++- arch/xtensa/mm/tlb.c | 113 +++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug index a34010e0e51c..af7da74d535f 100644 --- a/arch/xtensa/Kconfig.debug +++ b/arch/xtensa/Kconfig.debug @@ -2,6 +2,16 @@ menu "Kernel hacking" source "lib/Kconfig.debug" +config DEBUG_TLB_SANITY + bool "Debug TLB sanity" + depends on DEBUG_KERNEL + help + Enable this to turn on TLB sanity check on each entry to userspace. + This check can spot missing TLB invalidation/wrong PTE permissions/ + premature page freeing. + + If unsure, say N. + config LD_NO_RELAX bool "Disable linker relaxation" default n diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index fa94512ff84d..9298742f0fd0 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -458,7 +458,7 @@ common_exception_return: _bbsi.l a4, TIF_NEED_RESCHED, 3f _bbsi.l a4, TIF_NOTIFY_RESUME, 2f - _bbci.l a4, TIF_SIGPENDING, 4f + _bbci.l a4, TIF_SIGPENDING, 5f 2: l32i a4, a1, PT_DEPC bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f @@ -476,6 +476,13 @@ common_exception_return: callx4 a4 j 1b +5: +#ifdef CONFIG_DEBUG_TLB_SANITY + l32i a4, a1, PT_DEPC + bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f + movi a4, check_tlb_sanity + callx4 a4 +#endif 4: /* Restore optional registers. */ load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index 743346150eea..ca9d2366bf12 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c @@ -141,3 +141,116 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) local_irq_restore(flags); } + +#ifdef CONFIG_DEBUG_TLB_SANITY + +static unsigned get_pte_for_vaddr(unsigned vaddr) +{ + struct task_struct *task = get_current(); + struct mm_struct *mm = task->mm; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + if (!mm) + mm = task->active_mm; + pgd = pgd_offset(mm, vaddr); + if (pgd_none_or_clear_bad(pgd)) + return 0; + pmd = pmd_offset(pgd, vaddr); + if (pmd_none_or_clear_bad(pmd)) + return 0; + pte = pte_offset_map(pmd, vaddr); + if (!pte) + return 0; + return pte_val(*pte); +} + +enum { + TLB_SUSPICIOUS = 1, + TLB_INSANE = 2, +}; + +static void tlb_insane(void) +{ + BUG_ON(1); +} + +static void tlb_suspicious(void) +{ + WARN_ON(1); +} + +/* + * Check that TLB entries with kernel ASID (1) have kernel VMA (>= TASK_SIZE), + * and TLB entries with user ASID (>=4) have VMA < TASK_SIZE. + * + * Check that valid TLB entries either have the same PA as the PTE, or PTE is + * marked as non-present. Non-present PTE and the page with non-zero refcount + * and zero mapcount is normal for batched TLB flush operation. Zero refcount + * means that the page was freed prematurely. Non-zero mapcount is unusual, + * but does not necessary means an error, thus marked as suspicious. + */ +static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) +{ + unsigned tlbidx = w | (e << PAGE_SHIFT); + unsigned r0 = dtlb ? + read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx); + unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT); + unsigned pte = get_pte_for_vaddr(vpn); + unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK; + unsigned tlb_asid = r0 & ASID_MASK; + bool kernel = tlb_asid == 1; + int rc = 0; + + if (tlb_asid > 0 && ((vpn < TASK_SIZE) == kernel)) { + pr_err("%cTLB: way: %u, entry: %u, VPN %08x in %s PTE\n", + dtlb ? 'D' : 'I', w, e, vpn, + kernel ? "kernel" : "user"); + rc |= TLB_INSANE; + } + + if (tlb_asid == mm_asid) { + unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) : + read_itlb_translation(tlbidx); + if ((pte ^ r1) & PAGE_MASK) { + pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n", + dtlb ? 'D' : 'I', w, e, r0, r1, pte); + if (pte == 0 || !pte_present(__pte(pte))) { + struct page *p = pfn_to_page(r1 >> PAGE_SHIFT); + pr_err("page refcount: %d, mapcount: %d\n", + page_count(p), + page_mapcount(p)); + if (!page_count(p)) + rc |= TLB_INSANE; + else if (page_mapped(p)) + rc |= TLB_SUSPICIOUS; + } else { + rc |= TLB_INSANE; + } + } + } + return rc; +} + +void check_tlb_sanity(void) +{ + unsigned long flags; + unsigned w, e; + int bug = 0; + + local_irq_save(flags); + for (w = 0; w < DTLB_ARF_WAYS; ++w) + for (e = 0; e < (1 << XCHAL_DTLB_ARF_ENTRIES_LOG2); ++e) + bug |= check_tlb_entry(w, e, true); + for (w = 0; w < ITLB_ARF_WAYS; ++w) + for (e = 0; e < (1 << XCHAL_ITLB_ARF_ENTRIES_LOG2); ++e) + bug |= check_tlb_entry(w, e, false); + if (bug & TLB_INSANE) + tlb_insane(); + if (bug & TLB_SUSPICIOUS) + tlb_suspicious(); + local_irq_restore(flags); +} + +#endif /* CONFIG_DEBUG_TLB_SANITY */ -- GitLab From 220f5354089b27e8eeaa8658806dabc59ce55729 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 22 Feb 2013 00:09:22 +0530 Subject: [PATCH 2416/2900] xtensa: Flat DeviceTree copy not future-safe flat DT copy code calls bootmem allocator with @align = 0. This is probably OK with legacy allocator which xtensa uses right now, but this will panic right away with memblock allocator Signed-off-by: Vineet Gupta Cc: Chris Zankel Cc: Max Filippov Cc: Marc Gauthier Cc: linux-xtensa@linux-xtensa.org Cc: linux-kernel@vger.kernel.org Acked-by: Max Filippov Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 14c6c3a6f04b..42a8bba0b0ea 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -256,7 +256,7 @@ void __init early_init_devtree(void *params) static void __init copy_devtree(void) { void *alloc = early_init_dt_alloc_memory_arch( - be32_to_cpu(initial_boot_params->totalsize), 0); + be32_to_cpu(initial_boot_params->totalsize), 8); if (alloc) { memcpy(alloc, initial_boot_params, be32_to_cpu(initial_boot_params->totalsize)); -- GitLab From 478ba61afccd3a4d7ca662cadff1d35d183fe67d Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Fri, 24 May 2013 07:02:25 +0400 Subject: [PATCH 2417/2900] xtensa: add static function tracer support Signed-off-by: Max Filippov Signed-off-by: Chris Zankel --- arch/xtensa/Kconfig | 1 + arch/xtensa/boot/lib/Makefile | 7 +++++ arch/xtensa/include/asm/ftrace.h | 17 +++++++++-- arch/xtensa/kernel/Makefile | 1 + arch/xtensa/kernel/mcount.S | 50 +++++++++++++++++++++++++++++++ arch/xtensa/kernel/xtensa_ksyms.c | 4 +++ 6 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 arch/xtensa/kernel/mcount.S diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8852c0d35834..7ea6451a3a33 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -19,6 +19,7 @@ config XTENSA select CLONE_BACKWARDS select IRQ_DOMAIN select HAVE_OPROFILE + select HAVE_FUNCTION_TRACER help Xtensa processors are 32-bit RISC machines designed by Tensilica primarily for embedded systems. These processors are both diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index ad8952e8a07f..6868f2ca6af8 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile @@ -7,6 +7,13 @@ zlib := inffast.c inflate.c inftrees.c lib-y += $(zlib:.c=.o) zmem.o ccflags-y := -Ilib/zlib_inflate +ifdef CONFIG_FUNCTION_TRACER +CFLAGS_REMOVE_inflate.o = -pg +CFLAGS_REMOVE_zmem.o = -pg +CFLAGS_REMOVE_inftrees.o = -pg +CFLAGS_REMOVE_inffast.o = -pg +endif + quiet_cmd_copy_zlib = COPY $@ cmd_copy_zlib = cat $< > $@ diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h index 36dc7a684397..73cc3f482304 100644 --- a/arch/xtensa/include/asm/ftrace.h +++ b/arch/xtensa/include/asm/ftrace.h @@ -13,6 +13,7 @@ #include #define HAVE_ARCH_CALLER_ADDR +#ifndef __ASSEMBLY__ #define CALLER_ADDR0 ({ unsigned long a0, a1; \ __asm__ __volatile__ ( \ "mov %0, a0\n" \ @@ -24,10 +25,22 @@ extern unsigned long return_address(unsigned level); #define CALLER_ADDR1 return_address(1) #define CALLER_ADDR2 return_address(2) #define CALLER_ADDR3 return_address(3) -#else +#else /* CONFIG_FRAME_POINTER */ #define CALLER_ADDR1 (0) #define CALLER_ADDR2 (0) #define CALLER_ADDR3 (0) -#endif +#endif /* CONFIG_FRAME_POINTER */ +#endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_FUNCTION_TRACER + +#define MCOUNT_ADDR ((unsigned long)(_mcount)) +#define MCOUNT_INSN_SIZE 3 + +#ifndef __ASSEMBLY__ +extern void _mcount(void); +#define mcount _mcount +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_FUNCTION_TRACER */ #endif /* _XTENSA_FTRACE_H */ diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index 1e7fc87a94bb..f90265ec1ccc 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile @@ -11,6 +11,7 @@ obj-y := align.o coprocessor.o entry.o irq.o pci-dma.o platform.o process.o \ obj-$(CONFIG_KGDB) += xtensa-stub.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o +obj-$(CONFIG_FUNCTION_TRACER) += mcount.o AFLAGS_head.o += -mtext-section-literals diff --git a/arch/xtensa/kernel/mcount.S b/arch/xtensa/kernel/mcount.S new file mode 100644 index 000000000000..0eeda2e4a25e --- /dev/null +++ b/arch/xtensa/kernel/mcount.S @@ -0,0 +1,50 @@ +/* + * arch/xtensa/kernel/mcount.S + * + * Xtensa specific mcount support + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Tensilica Inc. + */ + +#include +#include + +/* + * Entry condition: + * + * a2: a0 of the caller + */ + +ENTRY(_mcount) + + entry a1, 16 + + movi a4, ftrace_trace_function + l32i a4, a4, 0 + movi a3, ftrace_stub + bne a3, a4, 1f + retw + +1: xor a7, a2, a1 + movi a3, 0x3fffffff + and a7, a7, a3 + xor a7, a7, a1 + + xor a6, a0, a1 + and a6, a6, a3 + xor a6, a6, a1 + addi a6, a6, -MCOUNT_INSN_SIZE + callx4 a4 + + retw + +ENDPROC(_mcount) + +ENTRY(ftrace_stub) + entry a1, 16 + retw +ENDPROC(ftrace_stub) diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 42c53c87c204..d8507f812f46 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -124,3 +124,7 @@ extern long common_exception_return; extern long _spill_registers; EXPORT_SYMBOL(common_exception_return); EXPORT_SYMBOL(_spill_registers); + +#ifdef CONFIG_FUNCTION_TRACER +EXPORT_SYMBOL(_mcount); +#endif -- GitLab From 0eb5afb3bae69a18bb4a8dbcbd361c4403fb54cd Mon Sep 17 00:00:00 2001 From: Zhao Hongjiang Date: Mon, 8 Jul 2013 15:22:50 +0800 Subject: [PATCH 2418/2900] xtensa: remove the second argument of __bio_kmap_atomic() kmap_atomic allows only one argument now, just remove the unused 'kmtype'. Signed-off-by: Zhao Hongjiang Acked-by: Geert Uytterhoeven Signed-off-by: Chris Zankel --- arch/xtensa/platforms/iss/simdisk.c | 4 ++-- include/linux/bio.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index c0edb35424ce..8c6e819cd8ed 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c @@ -108,13 +108,13 @@ static int simdisk_xfer_bio(struct simdisk *dev, struct bio *bio) sector_t sector = bio->bi_sector; bio_for_each_segment(bvec, bio, i) { - char *buffer = __bio_kmap_atomic(bio, i, KM_USER0); + char *buffer = __bio_kmap_atomic(bio, i); unsigned len = bvec->bv_len >> SECTOR_SHIFT; simdisk_transfer(dev, sector, len, buffer, bio_data_dir(bio) == WRITE); sector += len; - __bio_kunmap_atomic(bio, KM_USER0); + __bio_kunmap_atomic(bio); } return 0; } diff --git a/include/linux/bio.h b/include/linux/bio.h index ef24466d8f82..ec48bac5b039 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -97,11 +97,11 @@ static inline void *bio_data(struct bio *bio) * permanent PIO fall back, user is probably better off disabling highmem * I/O completely on that queue (see ide-dma for example) */ -#define __bio_kmap_atomic(bio, idx, kmtype) \ +#define __bio_kmap_atomic(bio, idx) \ (kmap_atomic(bio_iovec_idx((bio), (idx))->bv_page) + \ bio_iovec_idx((bio), (idx))->bv_offset) -#define __bio_kunmap_atomic(addr, kmtype) kunmap_atomic(addr) +#define __bio_kunmap_atomic(addr) kunmap_atomic(addr) /* * merge helpers etc -- GitLab From 78c2c2fe59b8c6b7d20e163efde0bfccc679f647 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 8 Jul 2013 14:18:24 +0200 Subject: [PATCH 2419/2900] hwmon: (lm90) Drop redundant safety on cache lifetime time_after (as opposed to time_after_equal) already ensures that the cache lifetime is at least as much as requested. There is no point in manually adding another jiffy to that value, and this can confuse the reader into wrong interpretation. Signed-off-by: Jean Delvare Cc: Imre Deak --- drivers/hwmon/lm90.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 8eeb141c85ac..cdff74282955 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -470,8 +470,8 @@ static struct lm90_data *lm90_update_device(struct device *dev) mutex_lock(&data->update_lock); - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval) + 1; + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval); if (time_after(jiffies, next_update) || !data->valid) { u8 h, l; u8 alarms; -- GitLab From 5b0620df9c38438ee245a97b8102ed74556e5505 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 8 Jul 2013 14:18:24 +0200 Subject: [PATCH 2420/2900] hwmon: (lm63) Drop redundant safety on cache lifetime time_after (as opposed to time_after_equal) already ensures that the cache lifetime is at least as much as requested. There is no point in manually adding another jiffy to that value, and this can confuse the reader into wrong interpretation. Signed-off-by: Jean Delvare Cc: Imre Deak --- drivers/hwmon/lm63.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index f644a2e57599..d0def50ea860 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -247,9 +247,8 @@ static struct lm63_data *lm63_update_device(struct device *dev) mutex_lock(&data->update_lock); - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval) + 1; - + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval); if (time_after(jiffies, next_update) || !data->valid) { if (data->config & 0x04) { /* tachometer enabled */ /* order matters for fan1_input */ -- GitLab From 1b2c14b44adcb7836528640bfdc40bf7499d987d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 8 Jul 2013 10:48:28 -0300 Subject: [PATCH 2421/2900] MAINTAINERS & ABI: Update to point to my new email As mchehab@redhat.com is no longer valid, update it to reflect the new one. Signed-off-by: Mauro Carvalho Chehab --- Documentation/ABI/testing/sysfs-devices-edac | 14 ++++----- MAINTAINERS | 32 ++++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac index 30ee78aaed75..6568e0010e1a 100644 --- a/Documentation/ABI/testing/sysfs-devices-edac +++ b/Documentation/ABI/testing/sysfs-devices-edac @@ -77,7 +77,7 @@ Description: Read/Write attribute file that controls memory scrubbing. What: /sys/devices/system/edac/mc/mc*/max_location Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file displays the information about the last available memory slot in this memory controller. It is used by @@ -85,7 +85,7 @@ Description: This attribute file displays the information about the last What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file will display the size of dimm or rank. For dimm*/size, this is the size, in MB of the DIMM memory @@ -96,14 +96,14 @@ Description: This attribute file will display the size of dimm or rank. What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file will display what type of DRAM device is being utilized on this DIMM (x1, x2, x4, x8, ...). What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file will display what type of Error detection and correction is being utilized. For example: S4ECD4ED would @@ -111,7 +111,7 @@ Description: This attribute file will display what type of Error detection What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This control file allows this DIMM to have a label assigned to it. With this label in the module, when errors occur @@ -126,14 +126,14 @@ Description: This control file allows this DIMM to have a label assigned What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file will display the location (csrow/channel, branch/channel/slot or channel/slot) of the dimm or rank. What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type Date: April 2012 -Contact: Mauro Carvalho Chehab +Contact: Mauro Carvalho Chehab linux-edac@vger.kernel.org Description: This attribute file will display what type of memory is currently on this csrow. Normally, either buffered or diff --git a/MAINTAINERS b/MAINTAINERS index af77eb1d8293..90644d12e9f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1557,7 +1557,7 @@ F: include/net/ax25.h F: net/ax25/ AZ6007 DVB DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -1841,7 +1841,7 @@ F: Documentation/filesystems/btrfs.txt F: fs/btrfs/ BTTV VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -2312,7 +2312,7 @@ F: drivers/media/common/cx2341x* F: include/media/cx2341x* CX88 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -2930,7 +2930,7 @@ S: Maintained F: drivers/edac/e7xxx_edac.c EDAC-GHES -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -2958,21 +2958,21 @@ S: Maintained F: drivers/edac/i5000_edac.c EDAC-I5400 -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5400_edac.c EDAC-I7300 -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i7300_edac.c EDAC-I7CORE -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -3001,7 +3001,7 @@ S: Maintained F: drivers/edac/r82600_edac.c EDAC-SBRIDGE -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -3061,7 +3061,7 @@ S: Maintained F: drivers/net/ethernet/ibm/ehea/ EM28XX VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -5229,7 +5229,7 @@ S: Maintained F: drivers/media/radio/radio-maxiradio* MEDIA INPUT INFRASTRUCTURE (V4L/DVB) -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab P: LinuxTV.org Project L: linux-media@vger.kernel.org W: http://linuxtv.org @@ -6911,7 +6911,7 @@ S: Odd Fixes F: drivers/media/i2c/saa6588* SAA7134 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -7282,7 +7282,7 @@ S: Odd Fixes F: drivers/media/radio/radio-si4713.h SIANO DVB DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -7986,7 +7986,7 @@ S: Maintained F: drivers/media/i2c/tda9840* TEA5761 TUNER DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -7994,7 +7994,7 @@ S: Odd fixes F: drivers/media/tuners/tea5761.* TEA5767 TUNER DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -8232,7 +8232,7 @@ F: include/linux/shmem_fs.h F: mm/shmem.c TM6000 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -9087,7 +9087,7 @@ S: Maintained F: arch/x86/kernel/cpu/mcheck/* XC2028/3028 TUNER DRIVER -M: Mauro Carvalho Chehab +M: Mauro Carvalho Chehab L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git -- GitLab From 65d467e84600754712fb36accd74b036cd775e5e Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Fri, 21 Jun 2013 17:02:36 -0400 Subject: [PATCH 2422/2900] thermal: MAINTAINERS: Add git tree path for SoC specific updates To reduce thermal maintenance load on Rui, SoC specific patches would be applied by me now. Rui Zhang will pull in these changes from time to time (at rc's). Additionally I would be sending him pull request for every merge window and rc's (for fixes). Branch names would be: next and fixes. Cc: Zhang Rui Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Eduardo Valentin --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 311fb4512826..e8fae3a2be25 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8032,6 +8032,7 @@ M: Zhang Rui M: Eduardo Valentin L: linux-pm@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git Q: https://patchwork.kernel.org/project/linux-pm/list/ S: Supported F: drivers/thermal/ -- GitLab From 57d1617137dd61825a3a7cebf61015f58afce510 Mon Sep 17 00:00:00 2001 From: Eduardo Valentin Date: Fri, 7 Jun 2013 11:11:53 -0400 Subject: [PATCH 2423/2900] thermal: ti-soc-thermal: use standard GPIO DT bindings This change updates the ti-soc-thermal driver to use standard GPIO DT bindings to read the GPIO number associated to thermal shutdown IRQ, in case the device features it. Previously, the code was using a specific DT bindings. As now OMAP supports the standard way to model GPIOs, there is no point in having a ti specific binding. Cc: Zhang Rui Cc: Grant Likely Cc: Rob Herring Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: Eduardo Valentin --- .../devicetree/bindings/thermal/ti_soc_thermal.txt | 9 +++++---- drivers/thermal/ti-soc-thermal/ti-bandgap.c | 8 ++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt index 1953b33cad51..0c9222d27fae 100644 --- a/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt +++ b/Documentation/devicetree/bindings/thermal/ti_soc_thermal.txt @@ -17,8 +17,9 @@ Required properties: - interrupts : this entry should indicate which interrupt line the talert signal is routed to; Specific: -- ti,tshut-gpio : this entry should be used to inform which GPIO -line the tshut signal is routed to; +- gpios : this entry should be used to inform which GPIO +line the tshut signal is routed to. The informed GPIO will +be treated as an IRQ; - regs : this entry must also be specified and it is specific to each bandgap version, because the mapping may change from soc to soc, apart of depending on available features. @@ -37,7 +38,7 @@ bandgap { 0x4a002378 0x18>; compatible = "ti,omap4460-bandgap"; interrupts = <0 126 4>; /* talert */ - ti,tshut-gpio = <86>; + gpios = <&gpio3 22 0>; /* tshut */ }; OMAP4470: @@ -47,7 +48,7 @@ bandgap { 0x4a002378 0x18>; compatible = "ti,omap4470-bandgap"; interrupts = <0 126 4>; /* talert */ - ti,tshut-gpio = <86>; + gpios = <&gpio3 22 0>; /* tshut */ }; OMAP5430: diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 7c0b3ebcf83a..9dfd47196e63 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "ti-bandgap.h" @@ -1129,7 +1130,6 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) const struct of_device_id *of_id; struct ti_bandgap *bgp; struct resource *res; - u32 prop; int i; /* just for the sake */ @@ -1173,11 +1173,7 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev) } while (res); if (TI_BANDGAP_HAS(bgp, TSHUT)) { - if (of_property_read_u32(node, "ti,tshut-gpio", &prop) < 0) { - dev_err(&pdev->dev, "missing tshut gpio in device tree\n"); - return ERR_PTR(-EINVAL); - } - bgp->tshut_gpio = prop; + bgp->tshut_gpio = of_get_gpio(node, 0); if (!gpio_is_valid(bgp->tshut_gpio)) { dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n", bgp->tshut_gpio); -- GitLab From e8d39240d635ed9bcaddbec898b1c9f063c5dbb2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 5 Jul 2013 17:40:13 +0200 Subject: [PATCH 2424/2900] thermal: cpu_cooling: fix stub function The function stub for cpufreq_cooling_get_level introduced in 57df81069 "Thermal: exynos: fix cooling state translation" is not syntactically correct C and needs to be fixed to avoid this error: In file included from drivers/thermal/db8500_thermal.c:20:0: include/linux/cpu_cooling.h: In function 'cpufreq_cooling_get_level': include/linux/cpu_cooling.h:57:1: error: parameter name omitted unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int) ^ include/linux/cpu_cooling.h:57:1: error: parameter name omitted Signed-off-by: Arnd Bergmann Acked-by: Eduardo Valentin Cc: Zhang Rui Cc: Amit Daniel kachhap Cc: stable@vger.kernel.org Signed-off-by: Eduardo Valentin --- include/linux/cpu_cooling.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index 282e27028418..a5d52eea8232 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -41,7 +41,7 @@ cpufreq_cooling_register(const struct cpumask *clip_cpus); */ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev); -unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int); +unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq); #else /* !CONFIG_CPU_THERMAL */ static inline struct thermal_cooling_device * cpufreq_cooling_register(const struct cpumask *clip_cpus) @@ -54,7 +54,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) return; } static inline -unsigned long cpufreq_cooling_get_level(unsigned int, unsigned int) +unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq) { return THERMAL_CSTATE_INVALID; } -- GitLab From bb6a4df6db9e69e225bfc5a9d95a1675342e1873 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 4 Jun 2013 12:05:09 -0700 Subject: [PATCH 2425/2900] [SCSI] storvsc: Increase the value of STORVSC_MAX_IO_REQUESTS Increase the value of STORVSC_MAX_IO_REQUESTS to 200 requests. The current ringbuffer size can support this higher value. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: James Bottomley --- drivers/scsi/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index b864e7c3da4b..83ec1aa85964 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -326,7 +326,7 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); */ static int storvsc_timeout = 180; -#define STORVSC_MAX_IO_REQUESTS 128 +#define STORVSC_MAX_IO_REQUESTS 200 static void storvsc_on_channel_callback(void *context); -- GitLab From b253c9d1d858a3f115f791ee4fe2b9399ae7dbbd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 8 Jul 2013 11:44:40 -0400 Subject: [PATCH 2426/2900] hp-wmi: Enable hotkeys on some systems Kyle Evans discovered that he needed to set some bits in an EC register in order to receive hotkey events. Doing so blindly broke some otherwise working HP laptops. It turns out that there's a WMI call that accesses the same register, so let's try calling that instead. Signed-off-by: Matthew Garrett Cc: Kyle Evans --- drivers/platform/x86/hp-wmi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index d111c8687f9b..6e142c3b5e97 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_ALS_QUERY 0x3 #define HPWMI_HARDWARE_QUERY 0x4 #define HPWMI_WIRELESS_QUERY 0x5 +#define HPWMI_BIOS_QUERY 0x9 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b @@ -291,6 +292,19 @@ static int hp_wmi_tablet_state(void) return (state & 0x4) ? 1 : 0; } +static int hp_wmi_enable_hotkeys(void) +{ + int ret; + int query = 0x6e; + + ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query), + 0); + + if (ret) + return -EINVAL; + return 0; +} + static int hp_wmi_set_block(void *data, bool blocked) { enum hp_wmi_radio r = (enum hp_wmi_radio) data; @@ -948,6 +962,8 @@ static int __init hp_wmi_init(void) err = hp_wmi_input_setup(); if (err) return err; + + hp_wmi_enable_hotkeys(); } if (bios_capable) { -- GitLab From 9f2082025902b59193dbdcd63550c1e8bc58e706 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 9 May 2013 10:03:02 +0800 Subject: [PATCH 2427/2900] dell-laptop: fix error return code in dell_init() Fix to return -ENOMEM in the alloc_page() error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Matthew Garrett --- drivers/platform/x86/dell-laptop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 1134119521ac..bb77e18b3dd4 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -551,9 +551,10 @@ static int __init dell_init(void) * is passed to SMI handler. */ bufferpage = alloc_page(GFP_KERNEL | GFP_DMA32); - - if (!bufferpage) + if (!bufferpage) { + ret = -ENOMEM; goto fail_buffer; + } buffer = page_address(bufferpage); if (quirks && quirks->touchpad_led) -- GitLab From e1a98e61c21694c9c690c7f253010cd44e89e7fd Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 14 May 2013 02:44:26 +0100 Subject: [PATCH 2428/2900] amilo-rfkill: Add dependency on SERIO_I8042 I forgot to add this when changing the driver to use the proper i8042 functions. Reported-by: kbuild test robot Signed-off-by: Ben Hutchings Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 85772616efbf..37645b923c52 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -176,6 +176,7 @@ config FUJITSU_TABLET config AMILO_RFKILL tristate "Fujitsu-Siemens Amilo rfkill support" depends on RFKILL + depends on SERIO_I8042 ---help--- This is a driver for enabling wifi on some Fujitsu-Siemens Amilo laptops. -- GitLab From 754d1243915d0fda6874fa0f1a926d85eb09e0b4 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 25 Jun 2013 11:27:16 -0400 Subject: [PATCH 2429/2900] [SCSI] qla2xxx: Clear the MBX_INTR_WAIT flag when the mailbox time-out happens. Signed-off-by: Giridhar Malavali Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index cfa2a20dee97..3cc2105dd902 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -12,7 +12,7 @@ * | Level | Last Value Used | Holes | * ---------------------------------------------------------------------- * | Module Init and Probe | 0x014f | 0x4b,0xba,0xfa | - * | Mailbox commands | 0x1179 | 0x111a-0x111b | + * | Mailbox commands | 0x117a | 0x111a-0x111b | * | | | 0x1155-0x1158 | * | Device Discovery | 0x2095 | 0x2020-0x2022, | * | | | 0x2016 | diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3587ec267fa6..144effd45ddf 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -177,8 +177,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ); - + if (!wait_for_completion_timeout(&ha->mbx_intr_comp, + mcp->tov * HZ)) { + ql_dbg(ql_dbg_mbx, vha, 0x117a, + "cmd=%x Timeout.\n", command); + spin_lock_irqsave(&ha->hardware_lock, flags); + clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + } } else { ql_dbg(ql_dbg_mbx, vha, 0x1011, "Cmd=%x Polling Mode.\n", command); -- GitLab From 8edf3edd8da076008093a8a04d349bbef02ecd88 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 25 Jun 2013 11:27:17 -0400 Subject: [PATCH 2430/2900] [SCSI] qla2xxx: Set the index in outstanding command array to NULL when cmd is aborted when the request timeout. Call the generic BSG free routine to unmap the DMA buffers. Signed-off-by: Giridhar Malavali Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 39719f892488..5ba0cc1f982b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2153,6 +2153,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) (sp->type == SRB_ELS_CMD_HST) || (sp->type == SRB_FXIOCB_BCMD)) && (sp->u.bsg_job == bsg_job)) { + req->outstanding_cmds[cnt] = NULL; spin_unlock_irqrestore(&ha->hardware_lock, flags); if (ha->isp_ops->abort_command(sp)) { ql_log(ql_log_warn, vha, 0x7089, @@ -2180,8 +2181,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) done: spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (bsg_job->request->msgcode == FC_BSG_HST_CT) - kfree(sp->fcport); - qla2x00_rel_sp(vha, sp); + sp->free(vha, sp); return 0; } -- GitLab From 3491255e12c5cd5310d855fe276f7971737a1c10 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Tue, 25 Jun 2013 11:27:18 -0400 Subject: [PATCH 2431/2900] [SCSI] qla2xxx: Move qla2x00_free_device to the correct location. Signed-off-by: Giridhar Malavali Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ad72c1d85111..c2e2e20d2e21 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -104,8 +104,6 @@ MODULE_PARM_DESC(ql2xshiftctondsd, "Set to control shifting of command type processing " "based on total number of SG elements."); -static void qla2x00_free_device(scsi_qla_host_t *); - int ql2xfdmienable=1; module_param(ql2xfdmienable, int, S_IRUGO); MODULE_PARM_DESC(ql2xfdmienable, @@ -237,6 +235,7 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *); static int qla2x00_change_queue_depth(struct scsi_device *, int, int); static int qla2x00_change_queue_type(struct scsi_device *, int); +static void qla2x00_free_device(scsi_qla_host_t *); struct scsi_host_template qla2xxx_driver_template = { .module = THIS_MODULE, -- GitLab From 8fbfe2d21445253411c1ff0f69e3129fc11ba57c Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Tue, 25 Jun 2013 11:27:19 -0400 Subject: [PATCH 2432/2900] [SCSI] qla2xxx: Do not query FC statistics during chip reset. During a chip reset, the mailbox call to get FC statistics from the ISP will not work resulting in needless mailbox accesses and errors printing out: qla2xxx [0000:05:00.0]-00af:11: Performing ISP error recovery - ha=ffff881fad044800. qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****. qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****. qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****. qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****. qla2xxx [0000:05:00.0]-1020:11: **** Failed mbx[0]=4001, mb[1]=4953, mb[2]=5020, mb[3]=b100, cmd=6d ****. To prevent this, check for a chip reset when an application queries for FC stats and return immediately if a chip reset is occurring. Signed-off-by: Chad Dupuis Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index bf60c631abb5..d7a99ae7f39d 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1691,6 +1691,9 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (unlikely(pci_channel_offline(ha->pdev))) goto done; + if (qla2x00_reset_active(vha)) + goto done; + stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); if (stats == NULL) { ql_log(ql_log_warn, vha, 0x707d, @@ -1703,7 +1706,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) if (IS_FWI2_CAPABLE(ha)) { rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma); } else if (atomic_read(&base_vha->loop_state) == LOOP_READY && - !qla2x00_reset_active(vha) && !ha->dpc_active) { + !ha->dpc_active) { /* Must be in a 'READY' state for statistics retrieval. */ rval = qla2x00_get_link_status(base_vha, base_vha->loop_id, stats, stats_dma); -- GitLab From b8eb4136b08f24b159d76b273216d524a26ac8f9 Mon Sep 17 00:00:00 2001 From: Chad Dupuis Date: Tue, 25 Jun 2013 11:27:20 -0400 Subject: [PATCH 2433/2900] [SCSI] qla2xxx: Do not take a second firmware dump when intentionally generating one. When we are intentionally generating a firmware dump by executing the MBC_GEN_SYSTEM_ERROR command, the command actually times out. The normal course of action when a mailbox command times out is to take a firmware dump. However, in this special case we do not want to do this since the MBA_SYSTEM_ERR AEN already generates a firmware dump. Signed-off-by: Chad Dupuis Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 144effd45ddf..7257c3c4f2d0 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -281,9 +281,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) /* * Attempt to capture a firmware dump for further analysis - * of the current firmware state + * of the current firmware state. We do not need to do this + * if we are intentionally generating a dump. */ - ha->isp_ops->fw_dump(vha, 0); + if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) + ha->isp_ops->fw_dump(vha, 0); rval = QLA_FUNCTION_TIMEOUT; } -- GitLab From 1f8deefecdda5a43961dd8062a6cab27e20af5e9 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Tue, 25 Jun 2013 11:27:21 -0400 Subject: [PATCH 2434/2900] [SCSI] qla2xxx: Fix sparse warning from qla_mr.c and qla_iocb.c. Signed-off-by: Giridhar Malavali Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 34 +++--- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_inline.h | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 4 +- drivers/scsi/qla2xxx/qla_mr.c | 167 ++++++++++++++++-------------- drivers/scsi/qla2xxx/qla_mr.h | 98 +++++++++--------- 6 files changed, 157 insertions(+), 150 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index c32efc753229..95ca32a71e75 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -323,7 +323,7 @@ struct srb_iocb { uint32_t lun; uint32_t data; struct completion comp; - uint32_t comp_status; + __le16 comp_status; } tmf; struct { #define SRB_FXDISC_REQ_DMA_VALID BIT_0 @@ -338,21 +338,21 @@ struct srb_iocb { void *rsp_addr; dma_addr_t req_dma_handle; dma_addr_t rsp_dma_handle; - uint32_t adapter_id; - uint32_t adapter_id_hi; - uint32_t req_func_type; - uint32_t req_data; - uint32_t req_data_extra; - uint32_t result; - uint32_t seq_number; - uint32_t fw_flags; + __le32 adapter_id; + __le32 adapter_id_hi; + __le16 req_func_type; + __le32 req_data; + __le32 req_data_extra; + __le32 result; + __le32 seq_number; + __le16 fw_flags; struct completion fxiocb_comp; - uint32_t reserved_0; + __le32 reserved_0; uint8_t reserved_1; } fxiocb; struct { uint32_t cmd_hndl; - uint32_t comp_status; + __le16 comp_status; struct completion comp; } abt; } u; @@ -1196,14 +1196,14 @@ typedef struct { struct init_cb_fx { uint16_t version; uint16_t reserved_1[13]; - uint16_t request_q_outpointer; - uint16_t response_q_inpointer; + __le16 request_q_outpointer; + __le16 response_q_inpointer; uint16_t reserved_2[2]; - uint16_t response_q_length; - uint16_t request_q_length; + __le16 response_q_length; + __le16 request_q_length; uint16_t reserved_3[2]; - uint32_t request_q_address[2]; - uint32_t response_q_address[2]; + __le32 request_q_address[2]; + __le32 response_q_address[2]; uint16_t reserved_4[4]; uint8_t response_q_msivec; uint8_t reserved_5[19]; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 026bfde33e67..2d98232a08eb 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -587,7 +587,7 @@ extern int qlafx00_init_firmware(scsi_qla_host_t *, uint16_t); extern int qlafx00_fw_ready(scsi_qla_host_t *); extern int qlafx00_configure_devices(scsi_qla_host_t *); extern int qlafx00_reset_initialize(scsi_qla_host_t *); -extern int qlafx00_fx_disc(scsi_qla_host_t *, fc_port_t *, uint8_t); +extern int qlafx00_fx_disc(scsi_qla_host_t *, fc_port_t *, uint16_t); extern int qlafx00_process_aen(struct scsi_qla_host *, struct qla_work_evt *); extern int qlafx00_post_aenfx_work(struct scsi_qla_host *, uint32_t, uint32_t *, int); diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 0a5c8951cebb..28c38b4929ce 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -83,7 +83,7 @@ static inline void host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize) { uint32_t *isrc = (uint32_t *) src; - uint32_t *odest = (uint32_t *) dst; + __le32 *odest = (__le32 *) dst; uint32_t iter = bsize >> 2; for (; iter ; iter--) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 15e4080b347c..9de372f00d4a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1863,8 +1863,8 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp) pkt = req->ring_ptr; memset(pkt, 0, REQUEST_ENTRY_SIZE); if (IS_QLAFX00(ha)) { - WRT_REG_BYTE(&pkt->entry_count, req_cnt); - WRT_REG_WORD(&pkt->handle, handle); + WRT_REG_BYTE((void __iomem *)&pkt->entry_count, req_cnt); + WRT_REG_WORD((void __iomem *)&pkt->handle, handle); } else { pkt->entry_count = req_cnt; pkt->handle = handle; diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index a6df55838365..d7993797f46e 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -707,7 +707,7 @@ qlafx00_tmf_iocb_timeout(void *data) srb_t *sp = (srb_t *)data; struct srb_iocb *tmf = &sp->u.iocb_cmd; - tmf->u.tmf.comp_status = CS_TIMEOUT; + tmf->u.tmf.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT); complete(&tmf->u.tmf.comp); } @@ -1418,7 +1418,8 @@ qlafx00_init_response_q_entries(struct rsp_que *rsp) pkt = rsp->ring_ptr; for (cnt = 0; cnt < rsp->length; cnt++) { pkt->signature = RESPONSE_PROCESSED; - WRT_REG_DWORD(&pkt->signature, RESPONSE_PROCESSED); + WRT_REG_DWORD((void __iomem *)&pkt->signature, + RESPONSE_PROCESSED); pkt++; } } @@ -1733,7 +1734,7 @@ qla2x00_fxdisc_sp_done(void *data, void *ptr, int res) } int -qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t fx_type) +qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) { srb_t *sp; struct srb_iocb *fdisc; @@ -1759,13 +1760,13 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t fx_type) fdisc->u.fxiocb.flags = SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID; fdisc->u.fxiocb.rsp_len = QLAFX00_PORT_DATA_INFO; - fdisc->u.fxiocb.req_data = fcport->port_id; + fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->port_id); break; case FXDISC_GET_TGT_NODE_INFO: fdisc->u.fxiocb.flags = SRB_FXDISC_RESP_DMA_VALID | SRB_FXDISC_REQ_DWRD_VALID; fdisc->u.fxiocb.rsp_len = QLAFX00_TGT_NODE_INFO; - fdisc->u.fxiocb.req_data = fcport->tgt_id; + fdisc->u.fxiocb.req_data = cpu_to_le32(fcport->tgt_id); break; case FXDISC_GET_TGT_NODE_LIST: fdisc->u.fxiocb.flags = @@ -1851,7 +1852,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t fx_type) sp->name = "fxdisc"; qla2x00_init_timer(sp, FXDISC_TIMEOUT); fdisc->timeout = qla2x00_fxdisc_iocb_timeout; - fdisc->u.fxiocb.req_func_type = fx_type; + fdisc->u.fxiocb.req_func_type = cpu_to_le16(fx_type); sp->done = qla2x00_fxdisc_sp_done; rval = qla2x00_start_sp(sp); @@ -1904,7 +1905,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t fx_type) (uint8_t *)pinfo, 16); memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE); } - rval = fdisc->u.fxiocb.result; + rval = le32_to_cpu(fdisc->u.fxiocb.result); done_unmap_dma: if (fdisc->u.fxiocb.rsp_addr) @@ -1927,7 +1928,7 @@ qlafx00_abort_iocb_timeout(void *data) srb_t *sp = (srb_t *)data; struct srb_iocb *abt = &sp->u.iocb_cmd; - abt->u.abt.comp_status = CS_TIMEOUT; + abt->u.abt.comp_status = cpu_to_le16((uint16_t)CS_TIMEOUT); complete(&abt->u.abt.comp); } @@ -2169,14 +2170,14 @@ qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, static void qlafx00_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct tsk_mgmt_entry_fx00 *pkt, srb_t *sp, - uint16_t sstatus, uint16_t cpstatus) + __le16 sstatus, __le16 cpstatus) { struct srb_iocb *tmf; tmf = &sp->u.iocb_cmd; - if (cpstatus != CS_COMPLETE || - (sstatus & SS_RESPONSE_INFO_LEN_VALID)) - cpstatus = CS_INCOMPLETE; + if (cpstatus != cpu_to_le16((uint16_t)CS_COMPLETE) || + (sstatus & cpu_to_le16((uint16_t)SS_RESPONSE_INFO_LEN_VALID))) + cpstatus = cpu_to_le16((uint16_t)CS_INCOMPLETE); tmf->u.tmf.comp_status = cpstatus; sp->done(vha, sp, 0); } @@ -2194,7 +2195,7 @@ qlafx00_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, return; abt = &sp->u.iocb_cmd; - abt->u.abt.comp_status = le32_to_cpu(pkt->tgt_id_sts); + abt->u.abt.comp_status = pkt->tgt_id_sts; sp->done(vha, sp, 0); } @@ -2216,12 +2217,12 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, if (sp->type == SRB_FXIOCB_DCMD) { iocb_job = &sp->u.iocb_cmd; - iocb_job->u.fxiocb.seq_number = le32_to_cpu(pkt->seq_no); - iocb_job->u.fxiocb.fw_flags = le32_to_cpu(pkt->fw_iotcl_flags); - iocb_job->u.fxiocb.result = le32_to_cpu(pkt->status); + iocb_job->u.fxiocb.seq_number = pkt->seq_no; + iocb_job->u.fxiocb.fw_flags = pkt->fw_iotcl_flags; + iocb_job->u.fxiocb.result = pkt->status; if (iocb_job->u.fxiocb.flags & SRB_FXDISC_RSP_DWRD_VALID) iocb_job->u.fxiocb.req_data = - le32_to_cpu(pkt->dataword_r); + pkt->dataword_r; } else { bsg_job = sp->u.bsg_job; @@ -2275,10 +2276,10 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) fc_port_t *fcport; struct scsi_cmnd *cp; struct sts_entry_fx00 *sts; - uint16_t comp_status; - uint16_t scsi_status; + __le16 comp_status; + __le16 scsi_status; uint16_t ox_id; - uint8_t lscsi_status; + __le16 lscsi_status; int32_t resid; uint32_t sense_len, par_sense_len, rsp_info_len, resid_len, fw_resid_len; @@ -2292,8 +2293,8 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) sts = (struct sts_entry_fx00 *) pkt; - comp_status = le16_to_cpu(sts->comp_status); - scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK; + comp_status = sts->comp_status; + scsi_status = sts->scsi_status & cpu_to_le16((uint16_t)SS_MASK); hindex = sts->handle; handle = LSW(hindex); @@ -2339,38 +2340,40 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - lscsi_status = scsi_status & STATUS_MASK; + lscsi_status = scsi_status & cpu_to_le16((uint16_t)STATUS_MASK); fcport = sp->fcport; ox_id = 0; sense_len = par_sense_len = rsp_info_len = resid_len = fw_resid_len = 0; - if (scsi_status & SS_SENSE_LEN_VALID) - sense_len = le32_to_cpu(sts->sense_len); - if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) + if (scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID)) + sense_len = sts->sense_len; + if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER + | (uint16_t)SS_RESIDUAL_OVER))) resid_len = le32_to_cpu(sts->residual_len); - if (comp_status == CS_DATA_UNDERRUN) + if (comp_status == cpu_to_le16((uint16_t)CS_DATA_UNDERRUN)) fw_resid_len = le32_to_cpu(sts->residual_len); rsp_info = sense_data = sts->data; par_sense_len = sizeof(sts->data); /* Check for overrun. */ if (comp_status == CS_COMPLETE && - scsi_status & SS_RESIDUAL_OVER) - comp_status = CS_DATA_OVERRUN; + scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_OVER)) + comp_status = cpu_to_le16((uint16_t)CS_DATA_OVERRUN); /* * Based on Host and scsi status generate status code for Linux */ - switch (comp_status) { + switch (le16_to_cpu(comp_status)) { case CS_COMPLETE: case CS_QUEUE_FULL: if (scsi_status == 0) { res = DID_OK << 16; break; } - if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) { + if (scsi_status & cpu_to_le16(((uint16_t)SS_RESIDUAL_UNDER + | (uint16_t)SS_RESIDUAL_OVER))) { resid = resid_len; scsi_set_resid(cp, resid); @@ -2386,19 +2389,20 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) break; } } - res = DID_OK << 16 | lscsi_status; + res = DID_OK << 16 | le16_to_cpu(lscsi_status); - if (lscsi_status == SAM_STAT_TASK_SET_FULL) { + if (lscsi_status == + cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) { ql_dbg(ql_dbg_io, fcport->vha, 0x3051, "QUEUE FULL detected.\n"); break; } logit = 0; - if (lscsi_status != SS_CHECK_CONDITION) + if (lscsi_status != cpu_to_le16((uint16_t)SS_CHECK_CONDITION)) break; memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - if (!(scsi_status & SS_SENSE_LEN_VALID)) + if (!(scsi_status & cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))) break; qlafx00_handle_sense(sp, sense_data, par_sense_len, sense_len, @@ -2412,7 +2416,7 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) else resid = resid_len; scsi_set_resid(cp, resid); - if (scsi_status & SS_RESIDUAL_UNDER) { + if (scsi_status & cpu_to_le16((uint16_t)SS_RESIDUAL_UNDER)) { if ((IS_FWI2_CAPABLE(ha) || IS_QLAFX00(ha)) && fw_resid_len != resid_len) { ql_dbg(ql_dbg_io, fcport->vha, 0x3052, @@ -2420,7 +2424,8 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) "(0x%x of 0x%x bytes).\n", resid, scsi_bufflen(cp)); - res = DID_ERROR << 16 | lscsi_status; + res = DID_ERROR << 16 | + le16_to_cpu(lscsi_status); goto check_scsi_status; } @@ -2436,8 +2441,9 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) res = DID_ERROR << 16; break; } - } else if (lscsi_status != SAM_STAT_TASK_SET_FULL && - lscsi_status != SAM_STAT_BUSY) { + } else if (lscsi_status != + cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL) && + lscsi_status != cpu_to_le16((uint16_t)SAM_STAT_BUSY)) { /* * scsi status of task set and busy are considered * to be task not completed. @@ -2448,7 +2454,7 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) "of 0x%x bytes).\n", resid, scsi_bufflen(cp)); - res = DID_ERROR << 16 | lscsi_status; + res = DID_ERROR << 16 | le16_to_cpu(lscsi_status); goto check_scsi_status; } else { ql_dbg(ql_dbg_io, fcport->vha, 0x3055, @@ -2456,7 +2462,7 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) scsi_status, lscsi_status); } - res = DID_OK << 16 | lscsi_status; + res = DID_OK << 16 | le16_to_cpu(lscsi_status); logit = 0; check_scsi_status: @@ -2465,17 +2471,20 @@ qlafx00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) * Status. */ if (lscsi_status != 0) { - if (lscsi_status == SAM_STAT_TASK_SET_FULL) { + if (lscsi_status == + cpu_to_le16((uint16_t)SAM_STAT_TASK_SET_FULL)) { ql_dbg(ql_dbg_io, fcport->vha, 0x3056, "QUEUE FULL detected.\n"); logit = 1; break; } - if (lscsi_status != SS_CHECK_CONDITION) + if (lscsi_status != + cpu_to_le16((uint16_t)SS_CHECK_CONDITION)) break; memset(cp->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - if (!(scsi_status & SS_SENSE_LEN_VALID)) + if (!(scsi_status & + cpu_to_le16((uint16_t)SS_SENSE_LEN_VALID))) break; qlafx00_handle_sense(sp, sense_data, par_sense_len, @@ -2629,7 +2638,7 @@ qlafx00_multistatus_entry(struct scsi_qla_host *vha, uint32_t handle, hindex, handle_count, i; uint16_t que; struct req_que *req; - uint32_t *handle_ptr; + __le32 *handle_ptr; stsmfx = (struct multi_sts_entry_fx00 *) pkt; @@ -2643,7 +2652,7 @@ qlafx00_multistatus_entry(struct scsi_qla_host *vha, return; } - handle_ptr = (uint32_t *) &stsmfx->handles[0]; + handle_ptr = &stsmfx->handles[0]; for (i = 0; i < handle_count; i++) { hindex = le32_to_cpu(*handle_ptr); @@ -2714,10 +2723,11 @@ qlafx00_process_response_queue(struct scsi_qla_host *vha, if (!vha->flags.online) return; - while (RD_REG_DWORD(&(rsp->ring_ptr->signature)) != + while (RD_REG_DWORD((void __iomem *)&(rsp->ring_ptr->signature)) != RESPONSE_PROCESSED) { lptr = rsp->ring_ptr; - memcpy_fromio(rsp->rsp_pkt, lptr, sizeof(rsp->rsp_pkt)); + memcpy_fromio(rsp->rsp_pkt, (void __iomem *)lptr, + sizeof(rsp->rsp_pkt)); pkt = (struct sts_entry_fx00 *)rsp->rsp_pkt; rsp->ring_index++; @@ -2768,7 +2778,8 @@ qlafx00_process_response_queue(struct scsi_qla_host *vha, break; } next_iter: - WRT_REG_DWORD(&lptr->signature, RESPONSE_PROCESSED); + WRT_REG_DWORD((void __iomem *)&lptr->signature, + RESPONSE_PROCESSED); wmb(); } @@ -2958,8 +2969,7 @@ qlafx00_prep_cont_type1_iocb(struct req_que *req, cont_pkt = (cont_a64_entry_t *)req->ring_ptr; /* Load packet defaults. */ - *((uint32_t *)(&lcont_pkt->entry_type)) = - __constant_cpu_to_le32(CONTINUE_A64_TYPE_FX00); + lcont_pkt->entry_type = CONTINUE_A64_TYPE_FX00; return cont_pkt; } @@ -2969,7 +2979,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt) { uint16_t avail_dsds; - uint32_t *cur_dsd; + __le32 *cur_dsd; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; struct scatterlist *sg; @@ -2986,8 +2996,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, cont_pkt = NULL; /* Update entry type to indicate Command Type 3 IOCB */ - *((uint32_t *)(&lcmd_pkt->entry_type)) = - __constant_cpu_to_le32(FX00_COMMAND_TYPE_7); + lcmd_pkt->entry_type = FX00_COMMAND_TYPE_7; /* No data transfer */ if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { @@ -3006,7 +3015,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, /* One DSD is available in the Command Type 3 IOCB */ avail_dsds = 1; - cur_dsd = (uint32_t *)&lcmd_pkt->dseg_0_address; + cur_dsd = (__le32 *)&lcmd_pkt->dseg_0_address; /* Load data segments */ scsi_for_each_sg(cmd, sg, tot_dsds, i) { @@ -3021,7 +3030,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE); cont_pkt = qlafx00_prep_cont_type1_iocb(req, &lcont_pkt); - cur_dsd = (uint32_t *)lcont_pkt.dseg_0_address; + cur_dsd = (__le32 *)lcont_pkt.dseg_0_address; avail_dsds = 5; cont = 1; } @@ -3224,13 +3233,13 @@ qlafx00_tm_iocb(srb_t *sp, struct tsk_mgmt_entry_fx00 *ptm_iocb) tm_iocb.timeout = cpu_to_le16(qla2x00_get_async_timeout(vha) + 2); tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id); tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags); - if (tm_iocb.control_flags == TCF_LUN_RESET) { + if (tm_iocb.control_flags == cpu_to_le32((uint32_t)TCF_LUN_RESET)) { int_to_scsilun(fxio->u.tmf.lun, &llun); host_to_adap((uint8_t *)&llun, (uint8_t *)&tm_iocb.lun, sizeof(struct scsi_lun)); } - memcpy((void __iomem *)ptm_iocb, &tm_iocb, + memcpy((void *)ptm_iocb, &tm_iocb, sizeof(struct tsk_mgmt_entry_fx00)); wmb(); } @@ -3252,7 +3261,7 @@ qlafx00_abort_iocb(srb_t *sp, struct abort_iocb_entry_fx00 *pabt_iocb) abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id); abt_iocb.req_que_no = cpu_to_le16(req->id); - memcpy((void __iomem *)pabt_iocb, &abt_iocb, + memcpy((void *)pabt_iocb, &abt_iocb, sizeof(struct abort_iocb_entry_fx00)); wmb(); } @@ -3273,13 +3282,12 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) if (sp->type == SRB_FXIOCB_DCMD) { fx_iocb.func_num = - cpu_to_le16(sp->u.iocb_cmd.u.fxiocb.req_func_type); - fx_iocb.adapid = cpu_to_le32(fxio->u.fxiocb.adapter_id); - fx_iocb.adapid_hi = cpu_to_le32(fxio->u.fxiocb.adapter_id_hi); - fx_iocb.reserved_0 = cpu_to_le32(fxio->u.fxiocb.reserved_0); - fx_iocb.reserved_1 = cpu_to_le32(fxio->u.fxiocb.reserved_1); - fx_iocb.dataword_extra = - cpu_to_le32(fxio->u.fxiocb.req_data_extra); + sp->u.iocb_cmd.u.fxiocb.req_func_type; + fx_iocb.adapid = fxio->u.fxiocb.adapter_id; + fx_iocb.adapid_hi = fxio->u.fxiocb.adapter_id_hi; + fx_iocb.reserved_0 = fxio->u.fxiocb.reserved_0; + fx_iocb.reserved_1 = fxio->u.fxiocb.reserved_1; + fx_iocb.dataword_extra = fxio->u.fxiocb.req_data_extra; if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DMA_VALID) { fx_iocb.req_dsdcnt = cpu_to_le16(1); @@ -3306,8 +3314,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) } if (fxio->u.fxiocb.flags & SRB_FXDISC_REQ_DWRD_VALID) { - fx_iocb.dataword = - cpu_to_le32(fxio->u.fxiocb.req_data); + fx_iocb.dataword = fxio->u.fxiocb.req_data; } fx_iocb.flags = fxio->u.fxiocb.flags; } else { @@ -3323,21 +3330,21 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) fx_iocb.reserved_1 = piocb_rqst->reserved_1; fx_iocb.dataword_extra = piocb_rqst->dataword_extra; fx_iocb.dataword = piocb_rqst->dataword; - fx_iocb.req_xfrcnt = cpu_to_le16(piocb_rqst->req_len); - fx_iocb.rsp_xfrcnt = cpu_to_le16(piocb_rqst->rsp_len); + fx_iocb.req_xfrcnt = piocb_rqst->req_len; + fx_iocb.rsp_xfrcnt = piocb_rqst->rsp_len; if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) { int avail_dsds, tot_dsds; cont_a64_entry_t lcont_pkt; cont_a64_entry_t *cont_pkt = NULL; - uint32_t *cur_dsd; + __le32 *cur_dsd; int index = 0, cont = 0; fx_iocb.req_dsdcnt = cpu_to_le16(bsg_job->request_payload.sg_cnt); tot_dsds = - cpu_to_le32(bsg_job->request_payload.sg_cnt); - cur_dsd = (uint32_t *)&fx_iocb.dseg_rq_address[0]; + bsg_job->request_payload.sg_cnt; + cur_dsd = (__le32 *)&fx_iocb.dseg_rq_address[0]; avail_dsds = 1; for_each_sg(bsg_job->request_payload.sg_list, sg, tot_dsds, index) { @@ -3355,7 +3362,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) qlafx00_prep_cont_type1_iocb( sp->fcport->vha->req, &lcont_pkt); - cur_dsd = (uint32_t *) + cur_dsd = (__le32 *) lcont_pkt.dseg_0_address; avail_dsds = 5; cont = 1; @@ -3393,13 +3400,13 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) int avail_dsds, tot_dsds; cont_a64_entry_t lcont_pkt; cont_a64_entry_t *cont_pkt = NULL; - uint32_t *cur_dsd; + __le32 *cur_dsd; int index = 0, cont = 0; fx_iocb.rsp_dsdcnt = cpu_to_le16(bsg_job->reply_payload.sg_cnt); - tot_dsds = cpu_to_le32(bsg_job->reply_payload.sg_cnt); - cur_dsd = (uint32_t *)&fx_iocb.dseg_rsp_address[0]; + tot_dsds = bsg_job->reply_payload.sg_cnt; + cur_dsd = (__le32 *)&fx_iocb.dseg_rsp_address[0]; avail_dsds = 1; for_each_sg(bsg_job->reply_payload.sg_list, sg, @@ -3418,7 +3425,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) qlafx00_prep_cont_type1_iocb( sp->fcport->vha->req, &lcont_pkt); - cur_dsd = (uint32_t *) + cur_dsd = (__le32 *) lcont_pkt.dseg_0_address; avail_dsds = 5; cont = 1; @@ -3453,7 +3460,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) } if (piocb_rqst->flags & SRB_FXDISC_REQ_DWRD_VALID) - fx_iocb.dataword = cpu_to_le32(piocb_rqst->dataword); + fx_iocb.dataword = piocb_rqst->dataword; fx_iocb.flags = piocb_rqst->flags; fx_iocb.entry_count = entry_cnt; } @@ -3462,7 +3469,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb) sp->fcport->vha, 0x3047, (uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00)); - memcpy((void __iomem *)pfxiocb, &fx_iocb, + memcpy((void *)pfxiocb, &fx_iocb, sizeof(struct fxdisc_entry_fx00)); wmb(); } diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h index cc327dc2fd10..1a092af0e2c3 100644 --- a/drivers/scsi/qla2xxx/qla_mr.h +++ b/drivers/scsi/qla2xxx/qla_mr.h @@ -24,10 +24,10 @@ struct cmd_type_7_fx00 { uint32_t handle; /* System handle. */ uint32_t handle_hi; - uint16_t tgt_idx; /* Target Idx. */ + __le16 tgt_idx; /* Target Idx. */ uint16_t timeout; /* Command timeout. */ - uint16_t dseg_count; /* Data segment count. */ + __le16 dseg_count; /* Data segment count. */ uint16_t scsi_rsp_dsd_len; struct scsi_lun lun; /* LUN (LE). */ @@ -41,7 +41,7 @@ struct cmd_type_7_fx00 { uint8_t crn; uint8_t fcp_cdb[MAX_CMDSZ]; /* SCSI command words. */ - uint32_t byte_count; /* Total byte count. */ + __le32 byte_count; /* Total byte count. */ uint32_t dseg_0_address[2]; /* Data segment 0 address. */ uint32_t dseg_0_len; /* Data segment 0 length. */ @@ -81,16 +81,16 @@ struct sts_entry_fx00 { uint32_t handle; /* System handle. */ uint32_t handle_hi; /* System handle. */ - uint16_t comp_status; /* Completion status. */ + __le16 comp_status; /* Completion status. */ uint16_t reserved_0; /* OX_ID used by the firmware. */ - uint32_t residual_len; /* FW calc residual transfer length. */ + __le32 residual_len; /* FW calc residual transfer length. */ uint16_t reserved_1; uint16_t state_flags; /* State flags. */ uint16_t reserved_2; - uint16_t scsi_status; /* SCSI status. */ + __le16 scsi_status; /* SCSI status. */ uint32_t sense_len; /* FCP SENSE length. */ uint8_t data[32]; /* FCP response/sense information. */ @@ -106,7 +106,7 @@ struct multi_sts_entry_fx00 { uint8_t handle_count; uint8_t entry_status; - uint32_t handles[MAX_HANDLE_COUNT]; + __le32 handles[MAX_HANDLE_COUNT]; }; #define TSK_MGMT_IOCB_TYPE_FX00 0x05 @@ -116,21 +116,21 @@ struct tsk_mgmt_entry_fx00 { uint8_t sys_define; uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ + __le32 handle; /* System handle. */ uint32_t handle_hi; /* System handle. */ - uint16_t tgt_id; /* Target Idx. */ + __le16 tgt_id; /* Target Idx. */ uint16_t reserved_1; uint16_t delay; /* Activity delay in seconds. */ - uint16_t timeout; /* Command timeout. */ + __le16 timeout; /* Command timeout. */ struct scsi_lun lun; /* LUN (LE). */ - uint32_t control_flags; /* Control Flags. */ + __le32 control_flags; /* Control Flags. */ uint8_t reserved_2[32]; }; @@ -143,16 +143,16 @@ struct abort_iocb_entry_fx00 { uint8_t sys_define; /* System defined. */ uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ - uint32_t handle_hi; /* System handle. */ + __le32 handle; /* System handle. */ + __le32 handle_hi; /* System handle. */ - uint16_t tgt_id_sts; /* Completion status. */ - uint16_t options; + __le16 tgt_id_sts; /* Completion status. */ + __le16 options; - uint32_t abort_handle; /* System handle. */ - uint32_t abort_handle_hi; /* System handle. */ + __le32 abort_handle; /* System handle. */ + __le32 abort_handle_hi; /* System handle. */ - uint16_t req_que_no; + __le16 req_que_no; uint8_t reserved_1[38]; }; @@ -167,17 +167,17 @@ struct ioctl_iocb_entry_fx00 { uint32_t reserved_0; /* System handle. */ uint16_t comp_func_num; - uint16_t fw_iotcl_flags; + __le16 fw_iotcl_flags; - uint32_t dataword_r; /* Data word returned */ + __le32 dataword_r; /* Data word returned */ uint32_t adapid; /* Adapter ID */ uint32_t adapid_hi; /* Adapter ID high */ uint32_t reserved_1; - uint32_t seq_no; + __le32 seq_no; uint8_t reserved_2[20]; uint32_t residuallen; - uint32_t status; + __le32 status; }; #define STATUS_CONT_TYPE_FX00 0x04 @@ -189,26 +189,26 @@ struct fxdisc_entry_fx00 { uint8_t sys_define; /* System Defined. */ uint8_t entry_status; /* Entry Status. */ - uint32_t handle; /* System handle. */ - uint32_t reserved_0; /* System handle. */ + __le32 handle; /* System handle. */ + __le32 reserved_0; /* System handle. */ - uint16_t func_num; - uint16_t req_xfrcnt; - uint16_t req_dsdcnt; - uint16_t rsp_xfrcnt; - uint16_t rsp_dsdcnt; + __le16 func_num; + __le16 req_xfrcnt; + __le16 req_dsdcnt; + __le16 rsp_xfrcnt; + __le16 rsp_dsdcnt; uint8_t flags; uint8_t reserved_1; - uint32_t dseg_rq_address[2]; /* Data segment 0 address. */ - uint32_t dseg_rq_len; /* Data segment 0 length. */ - uint32_t dseg_rsp_address[2]; /* Data segment 1 address. */ - uint32_t dseg_rsp_len; /* Data segment 1 length. */ + __le32 dseg_rq_address[2]; /* Data segment 0 address. */ + __le32 dseg_rq_len; /* Data segment 0 length. */ + __le32 dseg_rsp_address[2]; /* Data segment 1 address. */ + __le32 dseg_rsp_len; /* Data segment 1 length. */ - uint32_t dataword; - uint32_t adapid; - uint32_t adapid_hi; - uint32_t dataword_extra; + __le32 dataword; + __le32 adapid; + __le32 adapid_hi; + __le32 dataword_extra; }; struct qlafx00_tgt_node_info { @@ -421,43 +421,43 @@ struct config_info_data { WRT_REG_DWORD((ha)->cregbase + off, val) struct qla_mt_iocb_rqst_fx00 { - uint32_t reserved_0; + __le32 reserved_0; - uint16_t func_type; + __le16 func_type; uint8_t flags; uint8_t reserved_1; - uint32_t dataword; + __le32 dataword; - uint32_t adapid; - uint32_t adapid_hi; + __le32 adapid; + __le32 adapid_hi; - uint32_t dataword_extra; + __le32 dataword_extra; - uint32_t req_len; + __le32 req_len; - uint32_t rsp_len; + __le32 rsp_len; }; struct qla_mt_iocb_rsp_fx00 { uint32_t reserved_1; uint16_t func_type; - uint16_t ioctl_flags; + __le16 ioctl_flags; - uint32_t ioctl_data; + __le32 ioctl_data; uint32_t adapid; uint32_t adapid_hi; uint32_t reserved_2; - uint32_t seq_number; + __le32 seq_number; uint8_t reserved_3[20]; int32_t res_count; - uint32_t status; + __le32 status; }; -- GitLab From 090fc2e2cf6a2763f609af6f128a812d5051d935 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:22 -0400 Subject: [PATCH 2435/2900] [SCSI] qla2xxx: Clean up qla24xx_iidma() Remove dead code and simplify a pointer computation. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 9 +-------- drivers/scsi/qla2xxx/qla_dbg.c | 3 ++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 5ba0cc1f982b..9a30b696d758 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1282,14 +1282,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job) return -EINVAL; } - port_param = (struct qla_port_param *)((char *)bsg_job->request + - sizeof(struct fc_bsg_request)); - if (!port_param) { - ql_log(ql_log_warn, vha, 0x7047, - "port_param header not provided.\n"); - return -EINVAL; - } - + port_param = (void *)bsg_job->request + sizeof(struct fc_bsg_request); if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) { ql_log(ql_log_warn, vha, 0x7048, "Invalid destination type.\n"); diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 3cc2105dd902..91a11667a477 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -35,7 +35,8 @@ * | | | 0x70a5,0x70a6, | * | | | 0x70a8,0x70ab, | * | | | 0x70ad-0x70ae, | - * | | | 0x70d1-0x70da | + * | | | 0x70d1-0x70da, | + * | | | 0x7047 | * | Task Management | 0x803c | 0x8025-0x8026 | * | | | 0x800b,0x8039 | * | AER/EEH | 0x9011 | | -- GitLab From a44c72f309224973ffc7c7dfeee6e354c6f3d739 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:23 -0400 Subject: [PATCH 2436/2900] [SCSI] qla2xxx: Clean up qla84xx_mgmt_cmd() Remove dead code, simplify a pointer computation and move the ql84_mgmt assignment to just before its first use. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 10 +--------- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 9a30b696d758..b85f0021db3b 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1084,14 +1084,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) return -EINVAL; } - ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request + - sizeof(struct fc_bsg_request)); - if (!ql84_mgmt) { - ql_log(ql_log_warn, vha, 0x703b, - "MGMT header not provided, exiting.\n"); - return -EINVAL; - } - mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma); if (!mn) { ql_log(ql_log_warn, vha, 0x703c, @@ -1102,7 +1094,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job) memset(mn, 0, sizeof(struct access_chip_84xx)); mn->entry_type = ACCESS_CHIP_IOCB_TYPE; mn->entry_count = 1; - + ql84_mgmt = (void *)bsg_job->request + sizeof(struct fc_bsg_request); switch (ql84_mgmt->mgmt.cmd) { case QLA84_MGMT_READ_MEM: case QLA84_MGMT_GET_INFO: diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 91a11667a477..74a2121783c9 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -36,7 +36,7 @@ * | | | 0x70a8,0x70ab, | * | | | 0x70ad-0x70ae, | * | | | 0x70d1-0x70da, | - * | | | 0x7047 | + * | | | 0x7047,0x703b | * | Task Management | 0x803c | 0x8025-0x8026 | * | | | 0x800b,0x8039 | * | AER/EEH | 0x9011 | | -- GitLab From 6593d5bdbdb26d848ac5afa469cdca7abd3298df Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:24 -0400 Subject: [PATCH 2437/2900] [SCSI] qla2xxx: Remove dead code in qla2x00_configure_hba() At the end of qla2x00_configure_hba() we know that rval == QLA_SUCCESS. Hence remove the dead code. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 1 + drivers/scsi/qla2xxx/qla_init.c | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 74a2121783c9..91dbd8159eb1 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -15,6 +15,7 @@ * | Mailbox commands | 0x117a | 0x111a-0x111b | * | | | 0x1155-0x1158 | * | Device Discovery | 0x2095 | 0x2020-0x2022, | + * | | | 0x2011-0x2012, | * | | | 0x2016 | * | Queue Command and IO tracing | 0x3058 | 0x3006-0x300b | * | | | 0x3027-0x3028 | diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3565dfd8f370..f2216ed2ad8c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2309,14 +2309,6 @@ qla2x00_configure_hba(scsi_qla_host_t *vha) "Topology - %s, Host Loop address 0x%x.\n", connect_type, vha->loop_id); - if (rval) { - ql_log(ql_log_warn, vha, 0x2011, - "%s FAILED\n", __func__); - } else { - ql_dbg(ql_dbg_disc, vha, 0x2012, - "%s success\n", __func__); - } - return(rval); } -- GitLab From c5dcfaac943da1a2981e7488f74b0d4259fbb43f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:25 -0400 Subject: [PATCH 2438/2900] [SCSI] qla2xxx: Remove two superfluous tests. Since ha->model_desc is an array comparing it against NULL is superfluous. Hence remove these tests. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gs.c | 3 +-- drivers/scsi/qla2xxx/qla_os.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index d0ea8b921177..f26442a73d1e 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1370,8 +1370,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Model description. */ eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - if (ha->model_desc) - strncpy(eiter->a.model_desc, ha->model_desc, 80); + strncpy(eiter->a.model_desc, ha->model_desc, 80); alen = strlen(eiter->a.model_desc); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c2e2e20d2e21..6df5223888f8 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2839,8 +2839,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) qla2x00_dfs_setup(base_vha); ql_log(ql_log_info, base_vha, 0x00fb, - "QLogic %s - %s.\n", - ha->model_number, ha->model_desc ? ha->model_desc : ""); + "QLogic %s - %s.\n", ha->model_number, ha->model_desc); ql_log(ql_log_info, base_vha, 0x00fc, "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n", pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info), -- GitLab From 4e541debb8f8746bd61f41cbb129ce9c6987b9d8 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:26 -0400 Subject: [PATCH 2439/2900] [SCSI] qla2xxx: Remove a dead assignment in qla24xx_build_scsi_crc_2_iocbs(). Since the value of cur_seg is not used and since scsi_prot_sglist() has no side effects it is safe to remove the statement "cur_seg = scsi_port_sglist(cmd)". Detected by Coverity. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_iocb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 9de372f00d4a..42ef481db942 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1189,7 +1189,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, uint32_t *cur_dsd, *fcp_dl; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; - struct scatterlist *cur_seg; int sgc; uint32_t total_bytes = 0; uint32_t data_bytes; @@ -1396,7 +1395,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, if (bundling && tot_prot_dsds) { /* Walks dif segments */ - cur_seg = scsi_prot_sglist(cmd); cmd_pkt->control_flags |= __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; -- GitLab From 7f544d00698282655c7abed2262a39f5d9fe9283 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:27 -0400 Subject: [PATCH 2440/2900] [SCSI] qla2xxx: Remove redundant assignments. The value of the pointer called "nxt" is not used after the "nxt = qla24xx_copy_eft(ha, nxt)" statement. Hence keep the function call but remove the assignment. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 91dbd8159eb1..df132fec6d86 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -1470,7 +1470,7 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) nxt = qla2xxx_copy_queues(ha, nxt); - nxt = qla24xx_copy_eft(ha, nxt); + qla24xx_copy_eft(ha, nxt); /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); @@ -1789,7 +1789,7 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) nxt = qla2xxx_copy_queues(ha, nxt); - nxt = qla24xx_copy_eft(ha, nxt); + qla24xx_copy_eft(ha, nxt); /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); @@ -2291,7 +2291,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked) copy_queue: nxt = qla2xxx_copy_queues(ha, nxt); - nxt = qla24xx_copy_eft(ha, nxt); + qla24xx_copy_eft(ha, nxt); /* Chain entries -- started with MQ. */ nxt_chain = qla25xx_copy_fce(ha, nxt_chain, &last_chain); -- GitLab From 6ec6f9094a76aa9e732ede2add6cf32d0c2206e3 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:28 -0400 Subject: [PATCH 2441/2900] [SCSI] qla2xxx: Help Coverity with analyzing ct_sns_pkt initialization. Coverity reports "Overrunning struct type ct_sns_req of 1228 bytes by passing it to a function which accesses it at byte offset 8207" for each qla2x00_prep_ct_req(), qla2x00_prep_ct_fdmi_req() and qla24xx_prep_ct_fm_req() call. Help Coverity to recognize that these calls do not trigger a buffer overflow by making it explicit that these three functions initializes both the request and reply structures. This patch does not change any functionality. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gs.c | 83 ++++++++++++++++------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index f26442a73d1e..0926451980ed 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -99,17 +99,17 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, uint32_t req_size, uint32_t rsp_size) * Returns a pointer to the intitialized @ct_req. */ static inline struct ct_sns_req * -qla2x00_prep_ct_req(struct ct_sns_req *ct_req, uint16_t cmd, uint16_t rsp_size) +qla2x00_prep_ct_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size) { - memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + memset(p, 0, sizeof(struct ct_sns_pkt)); - ct_req->header.revision = 0x01; - ct_req->header.gs_type = 0xFC; - ct_req->header.gs_subtype = 0x02; - ct_req->command = cpu_to_be16(cmd); - ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + p->p.req.header.revision = 0x01; + p->p.req.header.gs_type = 0xFC; + p->p.req.header.gs_subtype = 0x02; + p->p.req.command = cpu_to_be16(cmd); + p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); - return (ct_req); + return &p->p.req; } static int @@ -188,7 +188,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport) GA_NXT_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GA_NXT_CMD, GA_NXT_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -284,8 +284,7 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list) gid_pt_rsp_size); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, - gid_pt_rsp_size); + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GID_PT_CMD, gid_pt_rsp_size); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_type */ @@ -359,7 +358,7 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list) GPN_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GPN_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -421,7 +420,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list) GNN_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GNN_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GNN_ID_CMD, GNN_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -495,7 +494,7 @@ qla2x00_rft_id(scsi_qla_host_t *vha) RFT_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -551,7 +550,7 @@ qla2x00_rff_id(scsi_qla_host_t *vha) RFF_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -606,8 +605,7 @@ qla2x00_rnn_id(scsi_qla_host_t *vha) RNN_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, - RNN_ID_RSP_SIZE); + ct_req = qla2x00_prep_ct_req(ha->ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_id, node_name */ @@ -676,7 +674,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *vha) ms_pkt = ha->isp_ops->prep_ms_iocb(vha, 0, RSNN_NN_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, RSNN_NN_CMD, RSNN_NN_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -1262,18 +1260,18 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size) * Returns a pointer to the intitialized @ct_req. */ static inline struct ct_sns_req * -qla2x00_prep_ct_fdmi_req(struct ct_sns_req *ct_req, uint16_t cmd, +qla2x00_prep_ct_fdmi_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size) { - memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + memset(p, 0, sizeof(struct ct_sns_pkt)); - ct_req->header.revision = 0x01; - ct_req->header.gs_type = 0xFA; - ct_req->header.gs_subtype = 0x10; - ct_req->command = cpu_to_be16(cmd); - ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + p->p.req.header.revision = 0x01; + p->p.req.header.gs_type = 0xFA; + p->p.req.header.gs_subtype = 0x10; + p->p.req.command = cpu_to_be16(cmd); + p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); - return ct_req; + return &p->p.req; } /** @@ -1301,8 +1299,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, - RHBA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare FDMI command arguments -- attribute block, attributes. */ @@ -1490,8 +1487,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *vha) DHBA_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, DHBA_CMD, - DHBA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare FDMI command arguments -- portname. */ @@ -1547,8 +1543,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, - RPA_RSP_SIZE); + ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare FDMI command arguments -- attribute block, attributes. */ @@ -1775,7 +1770,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list) GFPN_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFPN_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFPN_ID_CMD, GFPN_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; @@ -1842,18 +1837,18 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *vha, uint32_t req_size, static inline struct ct_sns_req * -qla24xx_prep_ct_fm_req(struct ct_sns_req *ct_req, uint16_t cmd, +qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd, uint16_t rsp_size) { - memset(ct_req, 0, sizeof(struct ct_sns_pkt)); + memset(p, 0, sizeof(struct ct_sns_pkt)); - ct_req->header.revision = 0x01; - ct_req->header.gs_type = 0xFA; - ct_req->header.gs_subtype = 0x01; - ct_req->command = cpu_to_be16(cmd); - ct_req->max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); + p->p.req.header.revision = 0x01; + p->p.req.header.gs_type = 0xFA; + p->p.req.header.gs_subtype = 0x01; + p->p.req.command = cpu_to_be16(cmd); + p->p.req.max_rsp_size = cpu_to_be16((rsp_size - 16) / 4); - return ct_req; + return &p->p.req; } /** @@ -1889,8 +1884,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list) GPSC_RSP_SIZE); /* Prepare CT request */ - ct_req = qla24xx_prep_ct_fm_req(&ha->ct_sns->p.req, - GPSC_CMD, GPSC_RSP_SIZE); + ct_req = qla24xx_prep_ct_fm_req(ha->ct_sns, GPSC_CMD, + GPSC_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; /* Prepare CT arguments -- port_name */ @@ -2000,7 +1995,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list) GFF_ID_RSP_SIZE); /* Prepare CT request */ - ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GFF_ID_CMD, + ct_req = qla2x00_prep_ct_req(ha->ct_sns, GFF_ID_CMD, GFF_ID_RSP_SIZE); ct_rsp = &ha->ct_sns->p.rsp; -- GitLab From b2ec76c5926438bda26b0e316246ae0e79bc810a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:29 -0400 Subject: [PATCH 2442/2900] [SCSI] qla2xxx: Fix qla2xxx_check_risc_status(). Change the 'rval' variable from QLA_FUNCTION_TIMEOUT into QLA_SUCCESS before starting a loop that is only executed if rval is initialized to QLA_SUCCESS. Coverity reported that loop as "dead code". Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d2a4c75e5b8f..2d8e7b812352 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2485,6 +2485,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha) if (rval == QLA_SUCCESS) goto next_test; + rval = QLA_SUCCESS; WRT_REG_DWORD(®->iobase_window, 0x0003); for (cnt = 100; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 && rval == QLA_SUCCESS; cnt--) { -- GitLab From 6e97c9d5b85caaef9c2da7e410008df7e6d9d38a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:30 -0400 Subject: [PATCH 2443/2900] [SCSI] qla2xxx: Remove an unused variable from qla2x00_remove_one(). Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6df5223888f8..3e21e9fc9d91 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2979,14 +2979,12 @@ qla2x00_remove_one(struct pci_dev *pdev) set_bit(UNLOADING, &base_vha->dpc_flags); mutex_lock(&ha->vport_lock); while (ha->cur_vport_count) { - struct Scsi_Host *scsi_host; - spin_lock_irqsave(&ha->vport_slock, flags); BUG_ON(base_vha->list.next == &ha->vp_list); /* This assumes first entry in ha->vp_list is always base vha */ vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list); - scsi_host = scsi_host_get(vha->host); + scsi_host_get(vha->host); spin_unlock_irqrestore(&ha->vport_slock, flags); mutex_unlock(&ha->vport_lock); -- GitLab From 8c0eb596baa51f2b43949c698c644727ef17805c Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 11:27:31 -0400 Subject: [PATCH 2444/2900] [SCSI] qla2xxx: Fix a memory leak in an error path of qla2x00_process_els() Avoid that the fcport structure gets leaked if bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN, the fcport allocation succeeds and the !vha->flags.online branch is taken. This was detected by Coverity. However, Coverity does not recognize that all qla2x00_process_els() callers specify either FC_BSG_RPT_ELS or FC_BSG_HST_ELS_NOLOGIN in the field bsg_job->request->msgcode and that the value of that field is not modified inside that function. This results in a false positive report about a possible memory leak in an error path for bsg_job->request->msgcode values other than the two mentioned values. Make it easy for Coverity (and for humans) to recognize that there is no fcport leak in the error path by changing the bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN test into bsg_job->request->msgcode != FC_BSG_RPT_ELS. Signed-off-by: Bart Van Assche Signed-off-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_bsg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index b85f0021db3b..417eaad50ae2 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -269,6 +269,12 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) type = "FC_BSG_HST_ELS_NOLOGIN"; } + if (!vha->flags.online) { + ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n"); + rval = -EIO; + goto done; + } + /* pass through is supported only for ISP 4Gb or higher */ if (!IS_FWI2_CAPABLE(ha)) { ql_dbg(ql_dbg_user, vha, 0x7001, @@ -326,12 +332,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) NPH_FABRIC_CONTROLLER : NPH_F_PORT; } - if (!vha->flags.online) { - ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n"); - rval = -EIO; - goto done; - } - req_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); @@ -399,7 +399,7 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) goto done_free_fcport; done_free_fcport: - if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN) + if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) kfree(fcport); done: return rval; -- GitLab From e126ba97dba9edeb6fafa3665b5f8497fc9cdf8c Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Sun, 7 Jul 2013 17:25:49 +0300 Subject: [PATCH 2445/2900] mlx5: Add driver for Mellanox Connect-IB adapters The driver is comprised of two kernel modules: mlx5_ib and mlx5_core. This partitioning resembles what we have for mlx4, except that mlx5_ib is the pci device driver and not mlx5_core. mlx5_core is essentially a library that provides general functionality that is intended to be used by other Mellanox devices that will be introduced in the future. mlx5_ib has a similar role as any hardware device under drivers/infiniband/hw. Signed-off-by: Eli Cohen Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz [ Merge in coccinelle fixes from Fengguang Wu . - Roland ] Signed-off-by: Roland Dreier --- MAINTAINERS | 22 + drivers/infiniband/Kconfig | 1 + drivers/infiniband/Makefile | 1 + drivers/infiniband/hw/mlx5/Kconfig | 10 + drivers/infiniband/hw/mlx5/Makefile | 3 + drivers/infiniband/hw/mlx5/ah.c | 92 + drivers/infiniband/hw/mlx5/cq.c | 843 ++++++ drivers/infiniband/hw/mlx5/doorbell.c | 100 + drivers/infiniband/hw/mlx5/mad.c | 139 + drivers/infiniband/hw/mlx5/main.c | 1504 ++++++++++ drivers/infiniband/hw/mlx5/mem.c | 162 ++ drivers/infiniband/hw/mlx5/mlx5_ib.h | 545 ++++ drivers/infiniband/hw/mlx5/mr.c | 1007 +++++++ drivers/infiniband/hw/mlx5/qp.c | 2524 +++++++++++++++++ drivers/infiniband/hw/mlx5/srq.c | 473 +++ drivers/infiniband/hw/mlx5/user.h | 121 + drivers/net/ethernet/mellanox/Kconfig | 1 + drivers/net/ethernet/mellanox/Makefile | 1 + .../net/ethernet/mellanox/mlx5/core/Kconfig | 18 + .../net/ethernet/mellanox/mlx5/core/Makefile | 5 + .../net/ethernet/mellanox/mlx5/core/alloc.c | 238 ++ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 1515 ++++++++++ drivers/net/ethernet/mellanox/mlx5/core/cq.c | 224 ++ .../net/ethernet/mellanox/mlx5/core/debugfs.c | 587 ++++ drivers/net/ethernet/mellanox/mlx5/core/eq.c | 521 ++++ drivers/net/ethernet/mellanox/mlx5/core/fw.c | 185 ++ .../net/ethernet/mellanox/mlx5/core/health.c | 217 ++ drivers/net/ethernet/mellanox/mlx5/core/mad.c | 78 + .../net/ethernet/mellanox/mlx5/core/main.c | 475 ++++ drivers/net/ethernet/mellanox/mlx5/core/mcg.c | 106 + .../ethernet/mellanox/mlx5/core/mlx5_core.h | 73 + drivers/net/ethernet/mellanox/mlx5/core/mr.c | 136 + .../ethernet/mellanox/mlx5/core/pagealloc.c | 435 +++ drivers/net/ethernet/mellanox/mlx5/core/pd.c | 101 + .../net/ethernet/mellanox/mlx5/core/port.c | 104 + drivers/net/ethernet/mellanox/mlx5/core/qp.c | 301 ++ drivers/net/ethernet/mellanox/mlx5/core/srq.c | 223 ++ drivers/net/ethernet/mellanox/mlx5/core/uar.c | 223 ++ include/linux/mlx5/cmd.h | 51 + include/linux/mlx5/cq.h | 165 ++ include/linux/mlx5/device.h | 893 ++++++ include/linux/mlx5/doorbell.h | 79 + include/linux/mlx5/driver.h | 769 +++++ include/linux/mlx5/qp.h | 467 +++ include/linux/mlx5/srq.h | 41 + 45 files changed, 15779 insertions(+) create mode 100644 drivers/infiniband/hw/mlx5/Kconfig create mode 100644 drivers/infiniband/hw/mlx5/Makefile create mode 100644 drivers/infiniband/hw/mlx5/ah.c create mode 100644 drivers/infiniband/hw/mlx5/cq.c create mode 100644 drivers/infiniband/hw/mlx5/doorbell.c create mode 100644 drivers/infiniband/hw/mlx5/mad.c create mode 100644 drivers/infiniband/hw/mlx5/main.c create mode 100644 drivers/infiniband/hw/mlx5/mem.c create mode 100644 drivers/infiniband/hw/mlx5/mlx5_ib.h create mode 100644 drivers/infiniband/hw/mlx5/mr.c create mode 100644 drivers/infiniband/hw/mlx5/qp.c create mode 100644 drivers/infiniband/hw/mlx5/srq.c create mode 100644 drivers/infiniband/hw/mlx5/user.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/Kconfig create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/Makefile create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/alloc.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/cmd.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/cq.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/debugfs.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/eq.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fw.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/health.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/mad.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/main.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/mcg.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/mr.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/pd.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/port.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/qp.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/srq.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/uar.c create mode 100644 include/linux/mlx5/cmd.h create mode 100644 include/linux/mlx5/cq.h create mode 100644 include/linux/mlx5/device.h create mode 100644 include/linux/mlx5/doorbell.h create mode 100644 include/linux/mlx5/driver.h create mode 100644 include/linux/mlx5/qp.h create mode 100644 include/linux/mlx5/srq.h diff --git a/MAINTAINERS b/MAINTAINERS index 60d6a3393500..b4265364ed27 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5365,6 +5365,28 @@ W: http://linuxtv.org S: Odd Fixes F: drivers/media/radio/radio-miropcm20* +Mellanox MLX5 core VPI driver +M: Eli Cohen +L: netdev@vger.kernel.org +L: linux-rdma@vger.kernel.org +W: http://www.mellanox.com +Q: http://patchwork.ozlabs.org/project/netdev/list/ +Q: http://patchwork.kernel.org/project/linux-rdma/list/ +T: git://openfabrics.org/~eli/connect-ib.git +S: Supported +F: drivers/net/ethernet/mellanox/mlx5/core/ +F: include/linux/mlx5/ + +Mellanox MLX5 IB driver +M: Eli Cohen +L: linux-rdma@vger.kernel.org +W: http://www.mellanox.com +Q: http://patchwork.kernel.org/project/linux-rdma/list/ +T: git://openfabrics.org/~eli/connect-ib.git +S: Supported +F: include/linux/mlx5/ +F: drivers/infiniband/hw/mlx5/ + MODULE SUPPORT M: Rusty Russell S: Maintained diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index c85b56c28099..5ceda710f516 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -50,6 +50,7 @@ source "drivers/infiniband/hw/amso1100/Kconfig" source "drivers/infiniband/hw/cxgb3/Kconfig" source "drivers/infiniband/hw/cxgb4/Kconfig" source "drivers/infiniband/hw/mlx4/Kconfig" +source "drivers/infiniband/hw/mlx5/Kconfig" source "drivers/infiniband/hw/nes/Kconfig" source "drivers/infiniband/hw/ocrdma/Kconfig" diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile index b126fefe0b1c..1fe69888515f 100644 --- a/drivers/infiniband/Makefile +++ b/drivers/infiniband/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_INFINIBAND_AMSO1100) += hw/amso1100/ obj-$(CONFIG_INFINIBAND_CXGB3) += hw/cxgb3/ obj-$(CONFIG_INFINIBAND_CXGB4) += hw/cxgb4/ obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/ +obj-$(CONFIG_MLX5_INFINIBAND) += hw/mlx5/ obj-$(CONFIG_INFINIBAND_NES) += hw/nes/ obj-$(CONFIG_INFINIBAND_OCRDMA) += hw/ocrdma/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ diff --git a/drivers/infiniband/hw/mlx5/Kconfig b/drivers/infiniband/hw/mlx5/Kconfig new file mode 100644 index 000000000000..8e6aebfaf8a4 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/Kconfig @@ -0,0 +1,10 @@ +config MLX5_INFINIBAND + tristate "Mellanox Connect-IB HCA support" + depends on NETDEVICES && ETHERNET && PCI && X86 + select NET_VENDOR_MELLANOX + select MLX5_CORE + ---help--- + This driver provides low-level InfiniBand support for + Mellanox Connect-IB PCI Express host channel adapters (HCAs). + This is required to use InfiniBand protocols such as + IP-over-IB or SRP with these devices. diff --git a/drivers/infiniband/hw/mlx5/Makefile b/drivers/infiniband/hw/mlx5/Makefile new file mode 100644 index 000000000000..4ea0135af484 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_MLX5_INFINIBAND) += mlx5_ib.o + +mlx5_ib-y := main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o diff --git a/drivers/infiniband/hw/mlx5/ah.c b/drivers/infiniband/hw/mlx5/ah.c new file mode 100644 index 000000000000..39ab0caefdf9 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/ah.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "mlx5_ib.h" + +struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr, + struct mlx5_ib_ah *ah) +{ + if (ah_attr->ah_flags & IB_AH_GRH) { + memcpy(ah->av.rgid, &ah_attr->grh.dgid, 16); + ah->av.grh_gid_fl = cpu_to_be32(ah_attr->grh.flow_label | + (1 << 30) | + ah_attr->grh.sgid_index << 20); + ah->av.hop_limit = ah_attr->grh.hop_limit; + ah->av.tclass = ah_attr->grh.traffic_class; + } + + ah->av.rlid = cpu_to_be16(ah_attr->dlid); + ah->av.fl_mlid = ah_attr->src_path_bits & 0x7f; + ah->av.stat_rate_sl = (ah_attr->static_rate << 4) | (ah_attr->sl & 0xf); + + return &ah->ibah; +} + +struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) +{ + struct mlx5_ib_ah *ah; + + ah = kzalloc(sizeof(*ah), GFP_ATOMIC); + if (!ah) + return ERR_PTR(-ENOMEM); + + return create_ib_ah(ah_attr, ah); /* never fails */ +} + +int mlx5_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) +{ + struct mlx5_ib_ah *ah = to_mah(ibah); + u32 tmp; + + memset(ah_attr, 0, sizeof(*ah_attr)); + + tmp = be32_to_cpu(ah->av.grh_gid_fl); + if (tmp & (1 << 30)) { + ah_attr->ah_flags = IB_AH_GRH; + ah_attr->grh.sgid_index = (tmp >> 20) & 0xff; + ah_attr->grh.flow_label = tmp & 0xfffff; + memcpy(&ah_attr->grh.dgid, ah->av.rgid, 16); + ah_attr->grh.hop_limit = ah->av.hop_limit; + ah_attr->grh.traffic_class = ah->av.tclass; + } + ah_attr->dlid = be16_to_cpu(ah->av.rlid); + ah_attr->static_rate = ah->av.stat_rate_sl >> 4; + ah_attr->sl = ah->av.stat_rate_sl & 0xf; + + return 0; +} + +int mlx5_ib_destroy_ah(struct ib_ah *ah) +{ + kfree(to_mah(ah)); + return 0; +} diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c new file mode 100644 index 000000000000..344ab03948a3 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -0,0 +1,843 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "mlx5_ib.h" +#include "user.h" + +static void mlx5_ib_cq_comp(struct mlx5_core_cq *cq) +{ + struct ib_cq *ibcq = &to_mibcq(cq)->ibcq; + + ibcq->comp_handler(ibcq, ibcq->cq_context); +} + +static void mlx5_ib_cq_event(struct mlx5_core_cq *mcq, enum mlx5_event type) +{ + struct mlx5_ib_cq *cq = container_of(mcq, struct mlx5_ib_cq, mcq); + struct mlx5_ib_dev *dev = to_mdev(cq->ibcq.device); + struct ib_cq *ibcq = &cq->ibcq; + struct ib_event event; + + if (type != MLX5_EVENT_TYPE_CQ_ERROR) { + mlx5_ib_warn(dev, "Unexpected event type %d on CQ %06x\n", + type, mcq->cqn); + return; + } + + if (ibcq->event_handler) { + event.device = &dev->ib_dev; + event.event = IB_EVENT_CQ_ERR; + event.element.cq = ibcq; + ibcq->event_handler(&event, ibcq->cq_context); + } +} + +static void *get_cqe_from_buf(struct mlx5_ib_cq_buf *buf, int n, int size) +{ + return mlx5_buf_offset(&buf->buf, n * size); +} + +static void *get_cqe(struct mlx5_ib_cq *cq, int n) +{ + return get_cqe_from_buf(&cq->buf, n, cq->mcq.cqe_sz); +} + +static void *get_sw_cqe(struct mlx5_ib_cq *cq, int n) +{ + void *cqe = get_cqe(cq, n & cq->ibcq.cqe); + struct mlx5_cqe64 *cqe64; + + cqe64 = (cq->mcq.cqe_sz == 64) ? cqe : cqe + 64; + return ((cqe64->op_own & MLX5_CQE_OWNER_MASK) ^ + !!(n & (cq->ibcq.cqe + 1))) ? NULL : cqe; +} + +static void *next_cqe_sw(struct mlx5_ib_cq *cq) +{ + return get_sw_cqe(cq, cq->mcq.cons_index); +} + +static enum ib_wc_opcode get_umr_comp(struct mlx5_ib_wq *wq, int idx) +{ + switch (wq->wr_data[idx]) { + case MLX5_IB_WR_UMR: + return 0; + + case IB_WR_LOCAL_INV: + return IB_WC_LOCAL_INV; + + case IB_WR_FAST_REG_MR: + return IB_WC_FAST_REG_MR; + + default: + pr_warn("unknown completion status\n"); + return 0; + } +} + +static void handle_good_req(struct ib_wc *wc, struct mlx5_cqe64 *cqe, + struct mlx5_ib_wq *wq, int idx) +{ + wc->wc_flags = 0; + switch (be32_to_cpu(cqe->sop_drop_qpn) >> 24) { + case MLX5_OPCODE_RDMA_WRITE_IMM: + wc->wc_flags |= IB_WC_WITH_IMM; + case MLX5_OPCODE_RDMA_WRITE: + wc->opcode = IB_WC_RDMA_WRITE; + break; + case MLX5_OPCODE_SEND_IMM: + wc->wc_flags |= IB_WC_WITH_IMM; + case MLX5_OPCODE_SEND: + case MLX5_OPCODE_SEND_INVAL: + wc->opcode = IB_WC_SEND; + break; + case MLX5_OPCODE_RDMA_READ: + wc->opcode = IB_WC_RDMA_READ; + wc->byte_len = be32_to_cpu(cqe->byte_cnt); + break; + case MLX5_OPCODE_ATOMIC_CS: + wc->opcode = IB_WC_COMP_SWAP; + wc->byte_len = 8; + break; + case MLX5_OPCODE_ATOMIC_FA: + wc->opcode = IB_WC_FETCH_ADD; + wc->byte_len = 8; + break; + case MLX5_OPCODE_ATOMIC_MASKED_CS: + wc->opcode = IB_WC_MASKED_COMP_SWAP; + wc->byte_len = 8; + break; + case MLX5_OPCODE_ATOMIC_MASKED_FA: + wc->opcode = IB_WC_MASKED_FETCH_ADD; + wc->byte_len = 8; + break; + case MLX5_OPCODE_BIND_MW: + wc->opcode = IB_WC_BIND_MW; + break; + case MLX5_OPCODE_UMR: + wc->opcode = get_umr_comp(wq, idx); + break; + } +} + +enum { + MLX5_GRH_IN_BUFFER = 1, + MLX5_GRH_IN_CQE = 2, +}; + +static void handle_responder(struct ib_wc *wc, struct mlx5_cqe64 *cqe, + struct mlx5_ib_qp *qp) +{ + struct mlx5_ib_dev *dev = to_mdev(qp->ibqp.device); + struct mlx5_ib_srq *srq; + struct mlx5_ib_wq *wq; + u16 wqe_ctr; + u8 g; + + if (qp->ibqp.srq || qp->ibqp.xrcd) { + struct mlx5_core_srq *msrq = NULL; + + if (qp->ibqp.xrcd) { + msrq = mlx5_core_get_srq(&dev->mdev, + be32_to_cpu(cqe->srqn)); + srq = to_mibsrq(msrq); + } else { + srq = to_msrq(qp->ibqp.srq); + } + if (srq) { + wqe_ctr = be16_to_cpu(cqe->wqe_counter); + wc->wr_id = srq->wrid[wqe_ctr]; + mlx5_ib_free_srq_wqe(srq, wqe_ctr); + if (msrq && atomic_dec_and_test(&msrq->refcount)) + complete(&msrq->free); + } + } else { + wq = &qp->rq; + wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)]; + ++wq->tail; + } + wc->byte_len = be32_to_cpu(cqe->byte_cnt); + + switch (cqe->op_own >> 4) { + case MLX5_CQE_RESP_WR_IMM: + wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; + wc->wc_flags = IB_WC_WITH_IMM; + wc->ex.imm_data = cqe->imm_inval_pkey; + break; + case MLX5_CQE_RESP_SEND: + wc->opcode = IB_WC_RECV; + wc->wc_flags = 0; + break; + case MLX5_CQE_RESP_SEND_IMM: + wc->opcode = IB_WC_RECV; + wc->wc_flags = IB_WC_WITH_IMM; + wc->ex.imm_data = cqe->imm_inval_pkey; + break; + case MLX5_CQE_RESP_SEND_INV: + wc->opcode = IB_WC_RECV; + wc->wc_flags = IB_WC_WITH_INVALIDATE; + wc->ex.invalidate_rkey = be32_to_cpu(cqe->imm_inval_pkey); + break; + } + wc->slid = be16_to_cpu(cqe->slid); + wc->sl = (be32_to_cpu(cqe->flags_rqpn) >> 24) & 0xf; + wc->src_qp = be32_to_cpu(cqe->flags_rqpn) & 0xffffff; + wc->dlid_path_bits = cqe->ml_path; + g = (be32_to_cpu(cqe->flags_rqpn) >> 28) & 3; + wc->wc_flags |= g ? IB_WC_GRH : 0; + wc->pkey_index = be32_to_cpu(cqe->imm_inval_pkey) & 0xffff; +} + +static void dump_cqe(struct mlx5_ib_dev *dev, struct mlx5_err_cqe *cqe) +{ + __be32 *p = (__be32 *)cqe; + int i; + + mlx5_ib_warn(dev, "dump error cqe\n"); + for (i = 0; i < sizeof(*cqe) / 16; i++, p += 4) + pr_info("%08x %08x %08x %08x\n", be32_to_cpu(p[0]), + be32_to_cpu(p[1]), be32_to_cpu(p[2]), + be32_to_cpu(p[3])); +} + +static void mlx5_handle_error_cqe(struct mlx5_ib_dev *dev, + struct mlx5_err_cqe *cqe, + struct ib_wc *wc) +{ + int dump = 1; + + switch (cqe->syndrome) { + case MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR: + wc->status = IB_WC_LOC_LEN_ERR; + break; + case MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR: + wc->status = IB_WC_LOC_QP_OP_ERR; + break; + case MLX5_CQE_SYNDROME_LOCAL_PROT_ERR: + wc->status = IB_WC_LOC_PROT_ERR; + break; + case MLX5_CQE_SYNDROME_WR_FLUSH_ERR: + dump = 0; + wc->status = IB_WC_WR_FLUSH_ERR; + break; + case MLX5_CQE_SYNDROME_MW_BIND_ERR: + wc->status = IB_WC_MW_BIND_ERR; + break; + case MLX5_CQE_SYNDROME_BAD_RESP_ERR: + wc->status = IB_WC_BAD_RESP_ERR; + break; + case MLX5_CQE_SYNDROME_LOCAL_ACCESS_ERR: + wc->status = IB_WC_LOC_ACCESS_ERR; + break; + case MLX5_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR: + wc->status = IB_WC_REM_INV_REQ_ERR; + break; + case MLX5_CQE_SYNDROME_REMOTE_ACCESS_ERR: + wc->status = IB_WC_REM_ACCESS_ERR; + break; + case MLX5_CQE_SYNDROME_REMOTE_OP_ERR: + wc->status = IB_WC_REM_OP_ERR; + break; + case MLX5_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR: + wc->status = IB_WC_RETRY_EXC_ERR; + dump = 0; + break; + case MLX5_CQE_SYNDROME_RNR_RETRY_EXC_ERR: + wc->status = IB_WC_RNR_RETRY_EXC_ERR; + dump = 0; + break; + case MLX5_CQE_SYNDROME_REMOTE_ABORTED_ERR: + wc->status = IB_WC_REM_ABORT_ERR; + break; + default: + wc->status = IB_WC_GENERAL_ERR; + break; + } + + wc->vendor_err = cqe->vendor_err_synd; + if (dump) + dump_cqe(dev, cqe); +} + +static int is_atomic_response(struct mlx5_ib_qp *qp, uint16_t idx) +{ + /* TBD: waiting decision + */ + return 0; +} + +static void *mlx5_get_atomic_laddr(struct mlx5_ib_qp *qp, uint16_t idx) +{ + struct mlx5_wqe_data_seg *dpseg; + void *addr; + + dpseg = mlx5_get_send_wqe(qp, idx) + sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_atomic_seg); + addr = (void *)(unsigned long)be64_to_cpu(dpseg->addr); + return addr; +} + +static void handle_atomic(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64, + uint16_t idx) +{ + void *addr; + int byte_count; + int i; + + if (!is_atomic_response(qp, idx)) + return; + + byte_count = be32_to_cpu(cqe64->byte_cnt); + addr = mlx5_get_atomic_laddr(qp, idx); + + if (byte_count == 4) { + *(uint32_t *)addr = be32_to_cpu(*((__be32 *)addr)); + } else { + for (i = 0; i < byte_count; i += 8) { + *(uint64_t *)addr = be64_to_cpu(*((__be64 *)addr)); + addr += 8; + } + } + + return; +} + +static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64, + u16 tail, u16 head) +{ + int idx; + + do { + idx = tail & (qp->sq.wqe_cnt - 1); + handle_atomic(qp, cqe64, idx); + if (idx == head) + break; + + tail = qp->sq.w_list[idx].next; + } while (1); + tail = qp->sq.w_list[idx].next; + qp->sq.last_poll = tail; +} + +static int mlx5_poll_one(struct mlx5_ib_cq *cq, + struct mlx5_ib_qp **cur_qp, + struct ib_wc *wc) +{ + struct mlx5_ib_dev *dev = to_mdev(cq->ibcq.device); + struct mlx5_err_cqe *err_cqe; + struct mlx5_cqe64 *cqe64; + struct mlx5_core_qp *mqp; + struct mlx5_ib_wq *wq; + uint8_t opcode; + uint32_t qpn; + u16 wqe_ctr; + void *cqe; + int idx; + + cqe = next_cqe_sw(cq); + if (!cqe) + return -EAGAIN; + + cqe64 = (cq->mcq.cqe_sz == 64) ? cqe : cqe + 64; + + ++cq->mcq.cons_index; + + /* Make sure we read CQ entry contents after we've checked the + * ownership bit. + */ + rmb(); + + /* TBD: resize CQ */ + + qpn = ntohl(cqe64->sop_drop_qpn) & 0xffffff; + if (!*cur_qp || (qpn != (*cur_qp)->ibqp.qp_num)) { + /* We do not have to take the QP table lock here, + * because CQs will be locked while QPs are removed + * from the table. + */ + mqp = __mlx5_qp_lookup(&dev->mdev, qpn); + if (unlikely(!mqp)) { + mlx5_ib_warn(dev, "CQE@CQ %06x for unknown QPN %6x\n", + cq->mcq.cqn, qpn); + return -EINVAL; + } + + *cur_qp = to_mibqp(mqp); + } + + wc->qp = &(*cur_qp)->ibqp; + opcode = cqe64->op_own >> 4; + switch (opcode) { + case MLX5_CQE_REQ: + wq = &(*cur_qp)->sq; + wqe_ctr = be16_to_cpu(cqe64->wqe_counter); + idx = wqe_ctr & (wq->wqe_cnt - 1); + handle_good_req(wc, cqe64, wq, idx); + handle_atomics(*cur_qp, cqe64, wq->last_poll, idx); + wc->wr_id = wq->wrid[idx]; + wq->tail = wq->wqe_head[idx] + 1; + wc->status = IB_WC_SUCCESS; + break; + case MLX5_CQE_RESP_WR_IMM: + case MLX5_CQE_RESP_SEND: + case MLX5_CQE_RESP_SEND_IMM: + case MLX5_CQE_RESP_SEND_INV: + handle_responder(wc, cqe64, *cur_qp); + wc->status = IB_WC_SUCCESS; + break; + case MLX5_CQE_RESIZE_CQ: + break; + case MLX5_CQE_REQ_ERR: + case MLX5_CQE_RESP_ERR: + err_cqe = (struct mlx5_err_cqe *)cqe64; + mlx5_handle_error_cqe(dev, err_cqe, wc); + mlx5_ib_dbg(dev, "%s error cqe on cqn 0x%x:\n", + opcode == MLX5_CQE_REQ_ERR ? + "Requestor" : "Responder", cq->mcq.cqn); + mlx5_ib_dbg(dev, "syndrome 0x%x, vendor syndrome 0x%x\n", + err_cqe->syndrome, err_cqe->vendor_err_synd); + if (opcode == MLX5_CQE_REQ_ERR) { + wq = &(*cur_qp)->sq; + wqe_ctr = be16_to_cpu(cqe64->wqe_counter); + idx = wqe_ctr & (wq->wqe_cnt - 1); + wc->wr_id = wq->wrid[idx]; + wq->tail = wq->wqe_head[idx] + 1; + } else { + struct mlx5_ib_srq *srq; + + if ((*cur_qp)->ibqp.srq) { + srq = to_msrq((*cur_qp)->ibqp.srq); + wqe_ctr = be16_to_cpu(cqe64->wqe_counter); + wc->wr_id = srq->wrid[wqe_ctr]; + mlx5_ib_free_srq_wqe(srq, wqe_ctr); + } else { + wq = &(*cur_qp)->rq; + wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)]; + ++wq->tail; + } + } + break; + } + + return 0; +} + +int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) +{ + struct mlx5_ib_cq *cq = to_mcq(ibcq); + struct mlx5_ib_qp *cur_qp = NULL; + unsigned long flags; + int npolled; + int err = 0; + + spin_lock_irqsave(&cq->lock, flags); + + for (npolled = 0; npolled < num_entries; npolled++) { + err = mlx5_poll_one(cq, &cur_qp, wc + npolled); + if (err) + break; + } + + if (npolled) + mlx5_cq_set_ci(&cq->mcq); + + spin_unlock_irqrestore(&cq->lock, flags); + + if (err == 0 || err == -EAGAIN) + return npolled; + else + return err; +} + +int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags) +{ + mlx5_cq_arm(&to_mcq(ibcq)->mcq, + (flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ? + MLX5_CQ_DB_REQ_NOT_SOL : MLX5_CQ_DB_REQ_NOT, + to_mdev(ibcq->device)->mdev.priv.uuari.uars[0].map, + MLX5_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->mdev.priv.cq_uar_lock)); + + return 0; +} + +static int alloc_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf, + int nent, int cqe_size) +{ + int err; + + err = mlx5_buf_alloc(&dev->mdev, nent * cqe_size, + PAGE_SIZE * 2, &buf->buf); + if (err) + return err; + + buf->cqe_size = cqe_size; + + return 0; +} + +static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf) +{ + mlx5_buf_free(&dev->mdev, &buf->buf); +} + +static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata, + struct ib_ucontext *context, struct mlx5_ib_cq *cq, + int entries, struct mlx5_create_cq_mbox_in **cqb, + int *cqe_size, int *index, int *inlen) +{ + struct mlx5_ib_create_cq ucmd; + int page_shift; + int npages; + int ncont; + int err; + + if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) + return -EFAULT; + + if (ucmd.cqe_size != 64 && ucmd.cqe_size != 128) + return -EINVAL; + + *cqe_size = ucmd.cqe_size; + + cq->buf.umem = ib_umem_get(context, ucmd.buf_addr, + entries * ucmd.cqe_size, + IB_ACCESS_LOCAL_WRITE, 1); + if (IS_ERR(cq->buf.umem)) { + err = PTR_ERR(cq->buf.umem); + return err; + } + + err = mlx5_ib_db_map_user(to_mucontext(context), ucmd.db_addr, + &cq->db); + if (err) + goto err_umem; + + mlx5_ib_cont_pages(cq->buf.umem, ucmd.buf_addr, &npages, &page_shift, + &ncont, NULL); + mlx5_ib_dbg(dev, "addr 0x%llx, size %u, npages %d, page_shift %d, ncont %d\n", + ucmd.buf_addr, entries * ucmd.cqe_size, npages, page_shift, ncont); + + *inlen = sizeof(**cqb) + sizeof(*(*cqb)->pas) * ncont; + *cqb = mlx5_vzalloc(*inlen); + if (!*cqb) { + err = -ENOMEM; + goto err_db; + } + mlx5_ib_populate_pas(dev, cq->buf.umem, page_shift, (*cqb)->pas, 0); + (*cqb)->ctx.log_pg_sz = page_shift - PAGE_SHIFT; + + *index = to_mucontext(context)->uuari.uars[0].index; + + return 0; + +err_db: + mlx5_ib_db_unmap_user(to_mucontext(context), &cq->db); + +err_umem: + ib_umem_release(cq->buf.umem); + return err; +} + +static void destroy_cq_user(struct mlx5_ib_cq *cq, struct ib_ucontext *context) +{ + mlx5_ib_db_unmap_user(to_mucontext(context), &cq->db); + ib_umem_release(cq->buf.umem); +} + +static void init_cq_buf(struct mlx5_ib_cq *cq, int nent) +{ + int i; + void *cqe; + struct mlx5_cqe64 *cqe64; + + for (i = 0; i < nent; i++) { + cqe = get_cqe(cq, i); + cqe64 = (cq->buf.cqe_size == 64) ? cqe : cqe + 64; + cqe64->op_own = 0xf1; + } +} + +static int create_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq, + int entries, int cqe_size, + struct mlx5_create_cq_mbox_in **cqb, + int *index, int *inlen) +{ + int err; + + err = mlx5_db_alloc(&dev->mdev, &cq->db); + if (err) + return err; + + cq->mcq.set_ci_db = cq->db.db; + cq->mcq.arm_db = cq->db.db + 1; + *cq->mcq.set_ci_db = 0; + *cq->mcq.arm_db = 0; + cq->mcq.cqe_sz = cqe_size; + + err = alloc_cq_buf(dev, &cq->buf, entries, cqe_size); + if (err) + goto err_db; + + init_cq_buf(cq, entries); + + *inlen = sizeof(**cqb) + sizeof(*(*cqb)->pas) * cq->buf.buf.npages; + *cqb = mlx5_vzalloc(*inlen); + if (!*cqb) { + err = -ENOMEM; + goto err_buf; + } + mlx5_fill_page_array(&cq->buf.buf, (*cqb)->pas); + + (*cqb)->ctx.log_pg_sz = cq->buf.buf.page_shift - PAGE_SHIFT; + *index = dev->mdev.priv.uuari.uars[0].index; + + return 0; + +err_buf: + free_cq_buf(dev, &cq->buf); + +err_db: + mlx5_db_free(&dev->mdev, &cq->db); + return err; +} + +static void destroy_cq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_cq *cq) +{ + free_cq_buf(dev, &cq->buf); + mlx5_db_free(&dev->mdev, &cq->db); +} + +struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, + int vector, struct ib_ucontext *context, + struct ib_udata *udata) +{ + struct mlx5_create_cq_mbox_in *cqb = NULL; + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct mlx5_ib_cq *cq; + int uninitialized_var(index); + int uninitialized_var(inlen); + int cqe_size; + int irqn; + int eqn; + int err; + + entries = roundup_pow_of_two(entries + 1); + if (entries < 1 || entries > dev->mdev.caps.max_cqes) + return ERR_PTR(-EINVAL); + + cq = kzalloc(sizeof(*cq), GFP_KERNEL); + if (!cq) + return ERR_PTR(-ENOMEM); + + cq->ibcq.cqe = entries - 1; + mutex_init(&cq->resize_mutex); + spin_lock_init(&cq->lock); + cq->resize_buf = NULL; + cq->resize_umem = NULL; + + if (context) { + err = create_cq_user(dev, udata, context, cq, entries, + &cqb, &cqe_size, &index, &inlen); + if (err) + goto err_create; + } else { + /* for now choose 64 bytes till we have a proper interface */ + cqe_size = 64; + err = create_cq_kernel(dev, cq, entries, cqe_size, &cqb, + &index, &inlen); + if (err) + goto err_create; + } + + cq->cqe_size = cqe_size; + cqb->ctx.cqe_sz_flags = cqe_sz_to_mlx_sz(cqe_size) << 5; + cqb->ctx.log_sz_usr_page = cpu_to_be32((ilog2(entries) << 24) | index); + err = mlx5_vector2eqn(dev, vector, &eqn, &irqn); + if (err) + goto err_cqb; + + cqb->ctx.c_eqn = cpu_to_be16(eqn); + cqb->ctx.db_record_addr = cpu_to_be64(cq->db.dma); + + err = mlx5_core_create_cq(&dev->mdev, &cq->mcq, cqb, inlen); + if (err) + goto err_cqb; + + mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn); + cq->mcq.irqn = irqn; + cq->mcq.comp = mlx5_ib_cq_comp; + cq->mcq.event = mlx5_ib_cq_event; + + if (context) + if (ib_copy_to_udata(udata, &cq->mcq.cqn, sizeof(__u32))) { + err = -EFAULT; + goto err_cmd; + } + + + mlx5_vfree(cqb); + return &cq->ibcq; + +err_cmd: + mlx5_core_destroy_cq(&dev->mdev, &cq->mcq); + +err_cqb: + mlx5_vfree(cqb); + if (context) + destroy_cq_user(cq, context); + else + destroy_cq_kernel(dev, cq); + +err_create: + kfree(cq); + + return ERR_PTR(err); +} + + +int mlx5_ib_destroy_cq(struct ib_cq *cq) +{ + struct mlx5_ib_dev *dev = to_mdev(cq->device); + struct mlx5_ib_cq *mcq = to_mcq(cq); + struct ib_ucontext *context = NULL; + + if (cq->uobject) + context = cq->uobject->context; + + mlx5_core_destroy_cq(&dev->mdev, &mcq->mcq); + if (context) + destroy_cq_user(mcq, context); + else + destroy_cq_kernel(dev, mcq); + + kfree(mcq); + + return 0; +} + +static int is_equal_rsn(struct mlx5_cqe64 *cqe64, struct mlx5_ib_srq *srq, + u32 rsn) +{ + u32 lrsn; + + if (srq) + lrsn = be32_to_cpu(cqe64->srqn) & 0xffffff; + else + lrsn = be32_to_cpu(cqe64->sop_drop_qpn) & 0xffffff; + + return rsn == lrsn; +} + +void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 rsn, struct mlx5_ib_srq *srq) +{ + struct mlx5_cqe64 *cqe64, *dest64; + void *cqe, *dest; + u32 prod_index; + int nfreed = 0; + u8 owner_bit; + + if (!cq) + return; + + /* First we need to find the current producer index, so we + * know where to start cleaning from. It doesn't matter if HW + * adds new entries after this loop -- the QP we're worried + * about is already in RESET, so the new entries won't come + * from our QP and therefore don't need to be checked. + */ + for (prod_index = cq->mcq.cons_index; get_sw_cqe(cq, prod_index); prod_index++) + if (prod_index == cq->mcq.cons_index + cq->ibcq.cqe) + break; + + /* Now sweep backwards through the CQ, removing CQ entries + * that match our QP by copying older entries on top of them. + */ + while ((int) --prod_index - (int) cq->mcq.cons_index >= 0) { + cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); + cqe64 = (cq->mcq.cqe_sz == 64) ? cqe : cqe + 64; + if (is_equal_rsn(cqe64, srq, rsn)) { + if (srq) + mlx5_ib_free_srq_wqe(srq, be16_to_cpu(cqe64->wqe_counter)); + ++nfreed; + } else if (nfreed) { + dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe); + dest64 = (cq->mcq.cqe_sz == 64) ? dest : dest + 64; + owner_bit = dest64->op_own & MLX5_CQE_OWNER_MASK; + memcpy(dest, cqe, cq->mcq.cqe_sz); + dest64->op_own = owner_bit | + (dest64->op_own & ~MLX5_CQE_OWNER_MASK); + } + } + + if (nfreed) { + cq->mcq.cons_index += nfreed; + /* Make sure update of buffer contents is done before + * updating consumer index. + */ + wmb(); + mlx5_cq_set_ci(&cq->mcq); + } +} + +void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq) +{ + if (!cq) + return; + + spin_lock_irq(&cq->lock); + __mlx5_ib_cq_clean(cq, qpn, srq); + spin_unlock_irq(&cq->lock); +} + +int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) +{ + return -ENOSYS; +} + +int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) +{ + return -ENOSYS; +} + +int mlx5_ib_get_cqe_size(struct mlx5_ib_dev *dev, struct ib_cq *ibcq) +{ + struct mlx5_ib_cq *cq; + + if (!ibcq) + return 128; + + cq = to_mcq(ibcq); + return cq->cqe_size; +} diff --git a/drivers/infiniband/hw/mlx5/doorbell.c b/drivers/infiniband/hw/mlx5/doorbell.c new file mode 100644 index 000000000000..256a23344f28 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/doorbell.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include "mlx5_ib.h" + +struct mlx5_ib_user_db_page { + struct list_head list; + struct ib_umem *umem; + unsigned long user_virt; + int refcnt; +}; + +int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt, + struct mlx5_db *db) +{ + struct mlx5_ib_user_db_page *page; + struct ib_umem_chunk *chunk; + int err = 0; + + mutex_lock(&context->db_page_mutex); + + list_for_each_entry(page, &context->db_page_list, list) + if (page->user_virt == (virt & PAGE_MASK)) + goto found; + + page = kmalloc(sizeof(*page), GFP_KERNEL); + if (!page) { + err = -ENOMEM; + goto out; + } + + page->user_virt = (virt & PAGE_MASK); + page->refcnt = 0; + page->umem = ib_umem_get(&context->ibucontext, virt & PAGE_MASK, + PAGE_SIZE, 0, 0); + if (IS_ERR(page->umem)) { + err = PTR_ERR(page->umem); + kfree(page); + goto out; + } + + list_add(&page->list, &context->db_page_list); + +found: + chunk = list_entry(page->umem->chunk_list.next, struct ib_umem_chunk, list); + db->dma = sg_dma_address(chunk->page_list) + (virt & ~PAGE_MASK); + db->u.user_page = page; + ++page->refcnt; + +out: + mutex_unlock(&context->db_page_mutex); + + return err; +} + +void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db) +{ + mutex_lock(&context->db_page_mutex); + + if (!--db->u.user_page->refcnt) { + list_del(&db->u.user_page->list); + ib_umem_release(db->u.user_page->umem); + kfree(db->u.user_page); + } + + mutex_unlock(&context->db_page_mutex); +} diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c new file mode 100644 index 000000000000..5c8938be0e08 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/mad.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "mlx5_ib.h" + +enum { + MLX5_IB_VENDOR_CLASS1 = 0x9, + MLX5_IB_VENDOR_CLASS2 = 0xa +}; + +int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, + int port, struct ib_wc *in_wc, struct ib_grh *in_grh, + void *in_mad, void *response_mad) +{ + u8 op_modifier = 0; + + /* Key check traps can't be generated unless we have in_wc to + * tell us where to send the trap. + */ + if (ignore_mkey || !in_wc) + op_modifier |= 0x1; + if (ignore_bkey || !in_wc) + op_modifier |= 0x2; + + return mlx5_core_mad_ifc(&dev->mdev, in_mad, response_mad, op_modifier, port); +} + +int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + struct ib_wc *in_wc, struct ib_grh *in_grh, + struct ib_mad *in_mad, struct ib_mad *out_mad) +{ + u16 slid; + int err; + + slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); + + if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && slid == 0) + return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; + + if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || + in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { + if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && + in_mad->mad_hdr.method != IB_MGMT_METHOD_SET && + in_mad->mad_hdr.method != IB_MGMT_METHOD_TRAP_REPRESS) + return IB_MAD_RESULT_SUCCESS; + + /* Don't process SMInfo queries -- the SMA can't handle them. + */ + if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO) + return IB_MAD_RESULT_SUCCESS; + } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT || + in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS1 || + in_mad->mad_hdr.mgmt_class == MLX5_IB_VENDOR_CLASS2 || + in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_CONG_MGMT) { + if (in_mad->mad_hdr.method != IB_MGMT_METHOD_GET && + in_mad->mad_hdr.method != IB_MGMT_METHOD_SET) + return IB_MAD_RESULT_SUCCESS; + } else { + return IB_MAD_RESULT_SUCCESS; + } + + err = mlx5_MAD_IFC(to_mdev(ibdev), + mad_flags & IB_MAD_IGNORE_MKEY, + mad_flags & IB_MAD_IGNORE_BKEY, + port_num, in_wc, in_grh, in_mad, out_mad); + if (err) + return IB_MAD_RESULT_FAILURE; + + /* set return bit in status of directed route responses */ + if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) + out_mad->mad_hdr.status |= cpu_to_be16(1 << 15); + + if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) + /* no response for trap repress */ + return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED; + + return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY; +} + +int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port) +{ + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + u16 packet_error; + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); + + err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); + + packet_error = be16_to_cpu(out_mad->status); + + dev->mdev.caps.ext_port_cap[port - 1] = (!err && !packet_error) ? + MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO : 0; + +out: + kfree(in_mad); + kfree(out_mad); + return err; +} diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c new file mode 100644 index 000000000000..6b1007f9bc29 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/main.c @@ -0,0 +1,1504 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user.h" +#include "mlx5_ib.h" + +#define DRIVER_NAME "mlx5_ib" +#define DRIVER_VERSION "1.0" +#define DRIVER_RELDATE "June 2013" + +MODULE_AUTHOR("Eli Cohen "); +MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRIVER_VERSION); + +static int prof_sel = 2; +module_param_named(prof_sel, prof_sel, int, 0444); +MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2"); + +static char mlx5_version[] = + DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v" + DRIVER_VERSION " (" DRIVER_RELDATE ")\n"; + +struct mlx5_profile profile[] = { + [0] = { + .mask = 0, + }, + [1] = { + .mask = MLX5_PROF_MASK_QP_SIZE, + .log_max_qp = 12, + }, + [2] = { + .mask = MLX5_PROF_MASK_QP_SIZE | + MLX5_PROF_MASK_MR_CACHE, + .log_max_qp = 17, + .mr_cache[0] = { + .size = 500, + .limit = 250 + }, + .mr_cache[1] = { + .size = 500, + .limit = 250 + }, + .mr_cache[2] = { + .size = 500, + .limit = 250 + }, + .mr_cache[3] = { + .size = 500, + .limit = 250 + }, + .mr_cache[4] = { + .size = 500, + .limit = 250 + }, + .mr_cache[5] = { + .size = 500, + .limit = 250 + }, + .mr_cache[6] = { + .size = 500, + .limit = 250 + }, + .mr_cache[7] = { + .size = 500, + .limit = 250 + }, + .mr_cache[8] = { + .size = 500, + .limit = 250 + }, + .mr_cache[9] = { + .size = 500, + .limit = 250 + }, + .mr_cache[10] = { + .size = 500, + .limit = 250 + }, + .mr_cache[11] = { + .size = 500, + .limit = 250 + }, + .mr_cache[12] = { + .size = 64, + .limit = 32 + }, + .mr_cache[13] = { + .size = 32, + .limit = 16 + }, + .mr_cache[14] = { + .size = 16, + .limit = 8 + }, + .mr_cache[15] = { + .size = 8, + .limit = 4 + }, + }, +}; + +int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn) +{ + struct mlx5_eq_table *table = &dev->mdev.priv.eq_table; + struct mlx5_eq *eq, *n; + int err = -ENOENT; + + spin_lock(&table->lock); + list_for_each_entry_safe(eq, n, &dev->eqs_list, list) { + if (eq->index == vector) { + *eqn = eq->eqn; + *irqn = eq->irqn; + err = 0; + break; + } + } + spin_unlock(&table->lock); + + return err; +} + +static int alloc_comp_eqs(struct mlx5_ib_dev *dev) +{ + struct mlx5_eq_table *table = &dev->mdev.priv.eq_table; + struct mlx5_eq *eq, *n; + int ncomp_vec; + int nent; + int err; + int i; + + INIT_LIST_HEAD(&dev->eqs_list); + ncomp_vec = table->num_comp_vectors; + nent = MLX5_COMP_EQ_SIZE; + for (i = 0; i < ncomp_vec; i++) { + eq = kzalloc(sizeof(*eq), GFP_KERNEL); + if (!eq) { + err = -ENOMEM; + goto clean; + } + + snprintf(eq->name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i); + err = mlx5_create_map_eq(&dev->mdev, eq, + i + MLX5_EQ_VEC_COMP_BASE, nent, 0, + eq->name, + &dev->mdev.priv.uuari.uars[0]); + if (err) { + kfree(eq); + goto clean; + } + mlx5_ib_dbg(dev, "allocated completion EQN %d\n", eq->eqn); + eq->index = i; + spin_lock(&table->lock); + list_add_tail(&eq->list, &dev->eqs_list); + spin_unlock(&table->lock); + } + + dev->num_comp_vectors = ncomp_vec; + return 0; + +clean: + spin_lock(&table->lock); + list_for_each_entry_safe(eq, n, &dev->eqs_list, list) { + list_del(&eq->list); + spin_unlock(&table->lock); + if (mlx5_destroy_unmap_eq(&dev->mdev, eq)) + mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn); + kfree(eq); + spin_lock(&table->lock); + } + spin_unlock(&table->lock); + return err; +} + +static void free_comp_eqs(struct mlx5_ib_dev *dev) +{ + struct mlx5_eq_table *table = &dev->mdev.priv.eq_table; + struct mlx5_eq *eq, *n; + + spin_lock(&table->lock); + list_for_each_entry_safe(eq, n, &dev->eqs_list, list) { + list_del(&eq->list); + spin_unlock(&table->lock); + if (mlx5_destroy_unmap_eq(&dev->mdev, eq)) + mlx5_ib_warn(dev, "failed to destroy EQ 0x%x\n", eq->eqn); + kfree(eq); + spin_lock(&table->lock); + } + spin_unlock(&table->lock); +} + +static int mlx5_ib_query_device(struct ib_device *ibdev, + struct ib_device_attr *props) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + int max_rq_sg; + int max_sq_sg; + u64 flags; + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; + + err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + memset(props, 0, sizeof(*props)); + + props->fw_ver = ((u64)fw_rev_maj(&dev->mdev) << 32) | + (fw_rev_min(&dev->mdev) << 16) | + fw_rev_sub(&dev->mdev); + props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | + IB_DEVICE_PORT_ACTIVE_EVENT | + IB_DEVICE_SYS_IMAGE_GUID | + IB_DEVICE_RC_RNR_NAK_GEN | + IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; + flags = dev->mdev.caps.flags; + if (flags & MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR) + props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; + if (flags & MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR) + props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; + if (flags & MLX5_DEV_CAP_FLAG_APM) + props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; + props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; + if (flags & MLX5_DEV_CAP_FLAG_XRC) + props->device_cap_flags |= IB_DEVICE_XRC; + props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; + + props->vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & + 0xffffff; + props->vendor_part_id = be16_to_cpup((__be16 *)(out_mad->data + 30)); + props->hw_ver = be32_to_cpup((__be32 *)(out_mad->data + 32)); + memcpy(&props->sys_image_guid, out_mad->data + 4, 8); + + props->max_mr_size = ~0ull; + props->page_size_cap = dev->mdev.caps.min_page_sz; + props->max_qp = 1 << dev->mdev.caps.log_max_qp; + props->max_qp_wr = dev->mdev.caps.max_wqes; + max_rq_sg = dev->mdev.caps.max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg); + max_sq_sg = (dev->mdev.caps.max_sq_desc_sz - sizeof(struct mlx5_wqe_ctrl_seg)) / + sizeof(struct mlx5_wqe_data_seg); + props->max_sge = min(max_rq_sg, max_sq_sg); + props->max_cq = 1 << dev->mdev.caps.log_max_cq; + props->max_cqe = dev->mdev.caps.max_cqes - 1; + props->max_mr = 1 << dev->mdev.caps.log_max_mkey; + props->max_pd = 1 << dev->mdev.caps.log_max_pd; + props->max_qp_rd_atom = dev->mdev.caps.max_ra_req_qp; + props->max_qp_init_rd_atom = dev->mdev.caps.max_ra_res_qp; + props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; + props->max_srq = 1 << dev->mdev.caps.log_max_srq; + props->max_srq_wr = dev->mdev.caps.max_srq_wqes - 1; + props->max_srq_sge = max_rq_sg - 1; + props->max_fast_reg_page_list_len = (unsigned int)-1; + props->local_ca_ack_delay = dev->mdev.caps.local_ca_ack_delay; + props->atomic_cap = dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_ATOMIC ? + IB_ATOMIC_HCA : IB_ATOMIC_NONE; + props->masked_atomic_cap = IB_ATOMIC_HCA; + props->max_pkeys = be16_to_cpup((__be16 *)(out_mad->data + 28)); + props->max_mcast_grp = 1 << dev->mdev.caps.log_max_mcg; + props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg; + props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * + props->max_mcast_grp; + props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */ + +out: + kfree(in_mad); + kfree(out_mad); + + return err; +} + +int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, + struct ib_port_attr *props) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int ext_active_speed; + int err = -ENOMEM; + + if (port < 1 || port > dev->mdev.caps.num_ports) { + mlx5_ib_warn(dev, "invalid port number %d\n", port); + return -EINVAL; + } + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + memset(props, 0, sizeof(*props)); + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); + + err = mlx5_MAD_IFC(dev, 1, 1, port, NULL, NULL, in_mad, out_mad); + if (err) { + mlx5_ib_warn(dev, "err %d\n", err); + goto out; + } + + + props->lid = be16_to_cpup((__be16 *)(out_mad->data + 16)); + props->lmc = out_mad->data[34] & 0x7; + props->sm_lid = be16_to_cpup((__be16 *)(out_mad->data + 18)); + props->sm_sl = out_mad->data[36] & 0xf; + props->state = out_mad->data[32] & 0xf; + props->phys_state = out_mad->data[33] >> 4; + props->port_cap_flags = be32_to_cpup((__be32 *)(out_mad->data + 20)); + props->gid_tbl_len = out_mad->data[50]; + props->max_msg_sz = 1 << to_mdev(ibdev)->mdev.caps.log_max_msg; + props->pkey_tbl_len = to_mdev(ibdev)->mdev.caps.port[port - 1].pkey_table_len; + props->bad_pkey_cntr = be16_to_cpup((__be16 *)(out_mad->data + 46)); + props->qkey_viol_cntr = be16_to_cpup((__be16 *)(out_mad->data + 48)); + props->active_width = out_mad->data[31] & 0xf; + props->active_speed = out_mad->data[35] >> 4; + props->max_mtu = out_mad->data[41] & 0xf; + props->active_mtu = out_mad->data[36] >> 4; + props->subnet_timeout = out_mad->data[51] & 0x1f; + props->max_vl_num = out_mad->data[37] >> 4; + props->init_type_reply = out_mad->data[41] >> 4; + + /* Check if extended speeds (EDR/FDR/...) are supported */ + if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) { + ext_active_speed = out_mad->data[62] >> 4; + + switch (ext_active_speed) { + case 1: + props->active_speed = 16; /* FDR */ + break; + case 2: + props->active_speed = 32; /* EDR */ + break; + } + } + + /* If reported active speed is QDR, check if is FDR-10 */ + if (props->active_speed == 4) { + if (dev->mdev.caps.ext_port_cap[port - 1] & + MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) { + init_query_mad(in_mad); + in_mad->attr_id = MLX5_ATTR_EXTENDED_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); + + err = mlx5_MAD_IFC(dev, 1, 1, port, + NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + /* Checking LinkSpeedActive for FDR-10 */ + if (out_mad->data[15] & 0x1) + props->active_speed = 8; + } + } + +out: + kfree(in_mad); + kfree(out_mad); + + return err; +} + +static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index, + union ib_gid *gid) +{ + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; + in_mad->attr_mod = cpu_to_be32(port); + + err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + memcpy(gid->raw, out_mad->data + 8, 8); + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; + in_mad->attr_mod = cpu_to_be32(index / 8); + + err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); + +out: + kfree(in_mad); + kfree(out_mad); + return err; +} + +static int mlx5_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, + u16 *pkey) +{ + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; + in_mad->attr_mod = cpu_to_be32(index / 32); + + err = mlx5_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + *pkey = be16_to_cpu(((__be16 *)out_mad->data)[index % 32]); + +out: + kfree(in_mad); + kfree(out_mad); + return err; +} + +struct mlx5_reg_node_desc { + u8 desc[64]; +}; + +static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask, + struct ib_device_modify *props) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct mlx5_reg_node_desc in; + struct mlx5_reg_node_desc out; + int err; + + if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) + return -EOPNOTSUPP; + + if (!(mask & IB_DEVICE_MODIFY_NODE_DESC)) + return 0; + + /* + * If possible, pass node desc to FW, so it can generate + * a 144 trap. If cmd fails, just ignore. + */ + memcpy(&in, props->node_desc, 64); + err = mlx5_core_access_reg(&dev->mdev, &in, sizeof(in), &out, + sizeof(out), MLX5_REG_NODE_DESC, 0, 1); + if (err) + return err; + + memcpy(ibdev->node_desc, props->node_desc, 64); + + return err; +} + +static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask, + struct ib_port_modify *props) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct ib_port_attr attr; + u32 tmp; + int err; + + mutex_lock(&dev->cap_mask_mutex); + + err = mlx5_ib_query_port(ibdev, port, &attr); + if (err) + goto out; + + tmp = (attr.port_cap_flags | props->set_port_cap_mask) & + ~props->clr_port_cap_mask; + + err = mlx5_set_port_caps(&dev->mdev, port, tmp); + +out: + mutex_unlock(&dev->cap_mask_mutex); + return err; +} + +static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct mlx5_ib_alloc_ucontext_req req; + struct mlx5_ib_alloc_ucontext_resp resp; + struct mlx5_ib_ucontext *context; + struct mlx5_uuar_info *uuari; + struct mlx5_uar *uars; + int num_uars; + int uuarn; + int err; + int i; + + if (!dev->ib_active) + return ERR_PTR(-EAGAIN); + + err = ib_copy_from_udata(&req, udata, sizeof(req)); + if (err) + return ERR_PTR(err); + + if (req.total_num_uuars > MLX5_MAX_UUARS) + return ERR_PTR(-ENOMEM); + + if (req.total_num_uuars == 0) + return ERR_PTR(-EINVAL); + + req.total_num_uuars = ALIGN(req.total_num_uuars, MLX5_BF_REGS_PER_PAGE); + if (req.num_low_latency_uuars > req.total_num_uuars - 1) + return ERR_PTR(-EINVAL); + + num_uars = req.total_num_uuars / MLX5_BF_REGS_PER_PAGE; + resp.qp_tab_size = 1 << dev->mdev.caps.log_max_qp; + resp.bf_reg_size = dev->mdev.caps.bf_reg_size; + resp.cache_line_size = L1_CACHE_BYTES; + resp.max_sq_desc_sz = dev->mdev.caps.max_sq_desc_sz; + resp.max_rq_desc_sz = dev->mdev.caps.max_rq_desc_sz; + resp.max_send_wqebb = dev->mdev.caps.max_wqes; + resp.max_recv_wr = dev->mdev.caps.max_wqes; + resp.max_srq_recv_wr = dev->mdev.caps.max_srq_wqes; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return ERR_PTR(-ENOMEM); + + uuari = &context->uuari; + mutex_init(&uuari->lock); + uars = kcalloc(num_uars, sizeof(*uars), GFP_KERNEL); + if (!uars) { + err = -ENOMEM; + goto out_ctx; + } + + uuari->bitmap = kcalloc(BITS_TO_LONGS(req.total_num_uuars), + sizeof(*uuari->bitmap), + GFP_KERNEL); + if (!uuari->bitmap) { + err = -ENOMEM; + goto out_uar_ctx; + } + /* + * clear all fast path uuars + */ + for (i = 0; i < req.total_num_uuars; i++) { + uuarn = i & 3; + if (uuarn == 2 || uuarn == 3) + set_bit(i, uuari->bitmap); + } + + uuari->count = kcalloc(req.total_num_uuars, sizeof(*uuari->count), GFP_KERNEL); + if (!uuari->count) { + err = -ENOMEM; + goto out_bitmap; + } + + for (i = 0; i < num_uars; i++) { + err = mlx5_cmd_alloc_uar(&dev->mdev, &uars[i].index); + if (err) + goto out_count; + } + + INIT_LIST_HEAD(&context->db_page_list); + mutex_init(&context->db_page_mutex); + + resp.tot_uuars = req.total_num_uuars; + resp.num_ports = dev->mdev.caps.num_ports; + err = ib_copy_to_udata(udata, &resp, sizeof(resp)); + if (err) + goto out_uars; + + uuari->num_low_latency_uuars = req.num_low_latency_uuars; + uuari->uars = uars; + uuari->num_uars = num_uars; + return &context->ibucontext; + +out_uars: + for (i--; i >= 0; i--) + mlx5_cmd_free_uar(&dev->mdev, uars[i].index); +out_count: + kfree(uuari->count); + +out_bitmap: + kfree(uuari->bitmap); + +out_uar_ctx: + kfree(uars); + +out_ctx: + kfree(context); + return ERR_PTR(err); +} + +static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) +{ + struct mlx5_ib_ucontext *context = to_mucontext(ibcontext); + struct mlx5_ib_dev *dev = to_mdev(ibcontext->device); + struct mlx5_uuar_info *uuari = &context->uuari; + int i; + + for (i = 0; i < uuari->num_uars; i++) { + if (mlx5_cmd_free_uar(&dev->mdev, uuari->uars[i].index)) + mlx5_ib_warn(dev, "failed to free UAR 0x%x\n", uuari->uars[i].index); + } + + kfree(uuari->count); + kfree(uuari->bitmap); + kfree(uuari->uars); + kfree(context); + + return 0; +} + +static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev, int index) +{ + return (pci_resource_start(dev->mdev.pdev, 0) >> PAGE_SHIFT) + index; +} + +static int get_command(unsigned long offset) +{ + return (offset >> MLX5_IB_MMAP_CMD_SHIFT) & MLX5_IB_MMAP_CMD_MASK; +} + +static int get_arg(unsigned long offset) +{ + return offset & ((1 << MLX5_IB_MMAP_CMD_SHIFT) - 1); +} + +static int get_index(unsigned long offset) +{ + return get_arg(offset); +} + +static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma) +{ + struct mlx5_ib_ucontext *context = to_mucontext(ibcontext); + struct mlx5_ib_dev *dev = to_mdev(ibcontext->device); + struct mlx5_uuar_info *uuari = &context->uuari; + unsigned long command; + unsigned long idx; + phys_addr_t pfn; + + command = get_command(vma->vm_pgoff); + switch (command) { + case MLX5_IB_MMAP_REGULAR_PAGE: + if (vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; + + idx = get_index(vma->vm_pgoff); + pfn = uar_index2pfn(dev, uuari->uars[idx].index); + mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn 0x%llx\n", idx, + (unsigned long long)pfn); + + if (idx >= uuari->num_uars) + return -EINVAL; + + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + if (io_remap_pfn_range(vma, vma->vm_start, pfn, + PAGE_SIZE, vma->vm_page_prot)) + return -EAGAIN; + + mlx5_ib_dbg(dev, "mapped WC at 0x%lx, PA 0x%llx\n", + vma->vm_start, + (unsigned long long)pfn << PAGE_SHIFT); + break; + + case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES: + return -ENOSYS; + + default: + return -EINVAL; + } + + return 0; +} + +static int alloc_pa_mkey(struct mlx5_ib_dev *dev, u32 *key, u32 pdn) +{ + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_mkey_seg *seg; + struct mlx5_core_mr mr; + int err; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return -ENOMEM; + + seg = &in->seg; + seg->flags = MLX5_PERM_LOCAL_READ | MLX5_ACCESS_MODE_PA; + seg->flags_pd = cpu_to_be32(pdn | MLX5_MKEY_LEN64); + seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + seg->start_addr = 0; + + err = mlx5_core_create_mkey(&dev->mdev, &mr, in, sizeof(*in)); + if (err) { + mlx5_ib_warn(dev, "failed to create mkey, %d\n", err); + goto err_in; + } + + kfree(in); + *key = mr.key; + + return 0; + +err_in: + kfree(in); + + return err; +} + +static void free_pa_mkey(struct mlx5_ib_dev *dev, u32 key) +{ + struct mlx5_core_mr mr; + int err; + + memset(&mr, 0, sizeof(mr)); + mr.key = key; + err = mlx5_core_destroy_mkey(&dev->mdev, &mr); + if (err) + mlx5_ib_warn(dev, "failed to destroy mkey 0x%x\n", key); +} + +static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev, + struct ib_ucontext *context, + struct ib_udata *udata) +{ + struct mlx5_ib_alloc_pd_resp resp; + struct mlx5_ib_pd *pd; + int err; + + pd = kmalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + return ERR_PTR(-ENOMEM); + + err = mlx5_core_alloc_pd(&to_mdev(ibdev)->mdev, &pd->pdn); + if (err) { + kfree(pd); + return ERR_PTR(err); + } + + if (context) { + resp.pdn = pd->pdn; + if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { + mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn); + kfree(pd); + return ERR_PTR(-EFAULT); + } + } else { + err = alloc_pa_mkey(to_mdev(ibdev), &pd->pa_lkey, pd->pdn); + if (err) { + mlx5_core_dealloc_pd(&to_mdev(ibdev)->mdev, pd->pdn); + kfree(pd); + return ERR_PTR(err); + } + } + + return &pd->ibpd; +} + +static int mlx5_ib_dealloc_pd(struct ib_pd *pd) +{ + struct mlx5_ib_dev *mdev = to_mdev(pd->device); + struct mlx5_ib_pd *mpd = to_mpd(pd); + + if (!pd->uobject) + free_pa_mkey(mdev, mpd->pa_lkey); + + mlx5_core_dealloc_pd(&mdev->mdev, mpd->pdn); + kfree(mpd); + + return 0; +} + +static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) +{ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + int err; + + err = mlx5_core_attach_mcg(&dev->mdev, gid, ibqp->qp_num); + if (err) + mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n", + ibqp->qp_num, gid->raw); + + return err; +} + +static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) +{ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + int err; + + err = mlx5_core_detach_mcg(&dev->mdev, gid, ibqp->qp_num); + if (err) + mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n", + ibqp->qp_num, gid->raw); + + return err; +} + +static int init_node_data(struct mlx5_ib_dev *dev) +{ + struct ib_smp *in_mad = NULL; + struct ib_smp *out_mad = NULL; + int err = -ENOMEM; + + in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL); + out_mad = kmalloc(sizeof(*out_mad), GFP_KERNEL); + if (!in_mad || !out_mad) + goto out; + + init_query_mad(in_mad); + in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; + + err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + memcpy(dev->ib_dev.node_desc, out_mad->data, 64); + + in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; + + err = mlx5_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); + if (err) + goto out; + + dev->mdev.rev_id = be32_to_cpup((__be32 *)(out_mad->data + 32)); + memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); + +out: + kfree(in_mad); + kfree(out_mad); + return err; +} + +static ssize_t show_fw_pages(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + + return sprintf(buf, "%d\n", dev->mdev.priv.fw_pages); +} + +static ssize_t show_reg_pages(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + + return sprintf(buf, "%d\n", dev->mdev.priv.reg_pages); +} + +static ssize_t show_hca(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + return sprintf(buf, "MT%d\n", dev->mdev.pdev->device); +} + +static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(&dev->mdev), + fw_rev_min(&dev->mdev), fw_rev_sub(&dev->mdev)); +} + +static ssize_t show_rev(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + return sprintf(buf, "%x\n", dev->mdev.rev_id); +} + +static ssize_t show_board(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct mlx5_ib_dev *dev = + container_of(device, struct mlx5_ib_dev, ib_dev.dev); + return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN, + dev->mdev.board_id); +} + +static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); +static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); +static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); +static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL); +static DEVICE_ATTR(fw_pages, S_IRUGO, show_fw_pages, NULL); +static DEVICE_ATTR(reg_pages, S_IRUGO, show_reg_pages, NULL); + +static struct device_attribute *mlx5_class_attributes[] = { + &dev_attr_hw_rev, + &dev_attr_fw_ver, + &dev_attr_hca_type, + &dev_attr_board_id, + &dev_attr_fw_pages, + &dev_attr_reg_pages, +}; + +static void mlx5_ib_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, + void *data) +{ + struct mlx5_ib_dev *ibdev = container_of(dev, struct mlx5_ib_dev, mdev); + struct ib_event ibev; + u8 port = 0; + + switch (event) { + case MLX5_DEV_EVENT_SYS_ERROR: + ibdev->ib_active = false; + ibev.event = IB_EVENT_DEVICE_FATAL; + break; + + case MLX5_DEV_EVENT_PORT_UP: + ibev.event = IB_EVENT_PORT_ACTIVE; + port = *(u8 *)data; + break; + + case MLX5_DEV_EVENT_PORT_DOWN: + ibev.event = IB_EVENT_PORT_ERR; + port = *(u8 *)data; + break; + + case MLX5_DEV_EVENT_PORT_INITIALIZED: + /* not used by ULPs */ + return; + + case MLX5_DEV_EVENT_LID_CHANGE: + ibev.event = IB_EVENT_LID_CHANGE; + port = *(u8 *)data; + break; + + case MLX5_DEV_EVENT_PKEY_CHANGE: + ibev.event = IB_EVENT_PKEY_CHANGE; + port = *(u8 *)data; + break; + + case MLX5_DEV_EVENT_GUID_CHANGE: + ibev.event = IB_EVENT_GID_CHANGE; + port = *(u8 *)data; + break; + + case MLX5_DEV_EVENT_CLIENT_REREG: + ibev.event = IB_EVENT_CLIENT_REREGISTER; + port = *(u8 *)data; + break; + } + + ibev.device = &ibdev->ib_dev; + ibev.element.port_num = port; + + if (ibdev->ib_active) + ib_dispatch_event(&ibev); +} + +static void get_ext_port_caps(struct mlx5_ib_dev *dev) +{ + int port; + + for (port = 1; port <= dev->mdev.caps.num_ports; port++) + mlx5_query_ext_port_caps(dev, port); +} + +static int get_port_caps(struct mlx5_ib_dev *dev) +{ + struct ib_device_attr *dprops = NULL; + struct ib_port_attr *pprops = NULL; + int err = 0; + int port; + + pprops = kmalloc(sizeof(*pprops), GFP_KERNEL); + if (!pprops) + goto out; + + dprops = kmalloc(sizeof(*dprops), GFP_KERNEL); + if (!dprops) + goto out; + + err = mlx5_ib_query_device(&dev->ib_dev, dprops); + if (err) { + mlx5_ib_warn(dev, "query_device failed %d\n", err); + goto out; + } + + for (port = 1; port <= dev->mdev.caps.num_ports; port++) { + err = mlx5_ib_query_port(&dev->ib_dev, port, pprops); + if (err) { + mlx5_ib_warn(dev, "query_port %d failed %d\n", port, err); + break; + } + dev->mdev.caps.port[port - 1].pkey_table_len = dprops->max_pkeys; + dev->mdev.caps.port[port - 1].gid_table_len = pprops->gid_tbl_len; + mlx5_ib_dbg(dev, "pkey_table_len %d, gid_table_len %d\n", + dprops->max_pkeys, pprops->gid_tbl_len); + } + +out: + kfree(pprops); + kfree(dprops); + + return err; +} + +static void destroy_umrc_res(struct mlx5_ib_dev *dev) +{ + int err; + + err = mlx5_mr_cache_cleanup(dev); + if (err) + mlx5_ib_warn(dev, "mr cache cleanup failed\n"); + + mlx5_ib_destroy_qp(dev->umrc.qp); + ib_destroy_cq(dev->umrc.cq); + ib_dereg_mr(dev->umrc.mr); + ib_dealloc_pd(dev->umrc.pd); +} + +enum { + MAX_UMR_WR = 128, +}; + +static int create_umr_res(struct mlx5_ib_dev *dev) +{ + struct ib_qp_init_attr *init_attr = NULL; + struct ib_qp_attr *attr = NULL; + struct ib_pd *pd; + struct ib_cq *cq; + struct ib_qp *qp; + struct ib_mr *mr; + int ret; + + attr = kzalloc(sizeof(*attr), GFP_KERNEL); + init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL); + if (!attr || !init_attr) { + ret = -ENOMEM; + goto error_0; + } + + pd = ib_alloc_pd(&dev->ib_dev); + if (IS_ERR(pd)) { + mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n"); + ret = PTR_ERR(pd); + goto error_0; + } + + mr = ib_get_dma_mr(pd, IB_ACCESS_LOCAL_WRITE); + if (IS_ERR(mr)) { + mlx5_ib_dbg(dev, "Couldn't create DMA MR for sync UMR QP\n"); + ret = PTR_ERR(mr); + goto error_1; + } + + cq = ib_create_cq(&dev->ib_dev, mlx5_umr_cq_handler, NULL, NULL, 128, + 0); + if (IS_ERR(cq)) { + mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n"); + ret = PTR_ERR(cq); + goto error_2; + } + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); + + init_attr->send_cq = cq; + init_attr->recv_cq = cq; + init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; + init_attr->cap.max_send_wr = MAX_UMR_WR; + init_attr->cap.max_send_sge = 1; + init_attr->qp_type = MLX5_IB_QPT_REG_UMR; + init_attr->port_num = 1; + qp = mlx5_ib_create_qp(pd, init_attr, NULL); + if (IS_ERR(qp)) { + mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n"); + ret = PTR_ERR(qp); + goto error_3; + } + qp->device = &dev->ib_dev; + qp->real_qp = qp; + qp->uobject = NULL; + qp->qp_type = MLX5_IB_QPT_REG_UMR; + + attr->qp_state = IB_QPS_INIT; + attr->port_num = 1; + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX | + IB_QP_PORT, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n"); + goto error_4; + } + + memset(attr, 0, sizeof(*attr)); + attr->qp_state = IB_QPS_RTR; + attr->path_mtu = IB_MTU_256; + + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n"); + goto error_4; + } + + memset(attr, 0, sizeof(*attr)); + attr->qp_state = IB_QPS_RTS; + ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL); + if (ret) { + mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n"); + goto error_4; + } + + dev->umrc.qp = qp; + dev->umrc.cq = cq; + dev->umrc.mr = mr; + dev->umrc.pd = pd; + + sema_init(&dev->umrc.sem, MAX_UMR_WR); + ret = mlx5_mr_cache_init(dev); + if (ret) { + mlx5_ib_warn(dev, "mr cache init failed %d\n", ret); + goto error_4; + } + + kfree(attr); + kfree(init_attr); + + return 0; + +error_4: + mlx5_ib_destroy_qp(qp); + +error_3: + ib_destroy_cq(cq); + +error_2: + ib_dereg_mr(mr); + +error_1: + ib_dealloc_pd(pd); + +error_0: + kfree(attr); + kfree(init_attr); + return ret; +} + +static int create_dev_resources(struct mlx5_ib_resources *devr) +{ + struct ib_srq_init_attr attr; + struct mlx5_ib_dev *dev; + int ret = 0; + + dev = container_of(devr, struct mlx5_ib_dev, devr); + + devr->p0 = mlx5_ib_alloc_pd(&dev->ib_dev, NULL, NULL); + if (IS_ERR(devr->p0)) { + ret = PTR_ERR(devr->p0); + goto error0; + } + devr->p0->device = &dev->ib_dev; + devr->p0->uobject = NULL; + atomic_set(&devr->p0->usecnt, 0); + + devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, 1, 0, NULL, NULL); + if (IS_ERR(devr->c0)) { + ret = PTR_ERR(devr->c0); + goto error1; + } + devr->c0->device = &dev->ib_dev; + devr->c0->uobject = NULL; + devr->c0->comp_handler = NULL; + devr->c0->event_handler = NULL; + devr->c0->cq_context = NULL; + atomic_set(&devr->c0->usecnt, 0); + + devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL); + if (IS_ERR(devr->x0)) { + ret = PTR_ERR(devr->x0); + goto error2; + } + devr->x0->device = &dev->ib_dev; + devr->x0->inode = NULL; + atomic_set(&devr->x0->usecnt, 0); + mutex_init(&devr->x0->tgt_qp_mutex); + INIT_LIST_HEAD(&devr->x0->tgt_qp_list); + + devr->x1 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL); + if (IS_ERR(devr->x1)) { + ret = PTR_ERR(devr->x1); + goto error3; + } + devr->x1->device = &dev->ib_dev; + devr->x1->inode = NULL; + atomic_set(&devr->x1->usecnt, 0); + mutex_init(&devr->x1->tgt_qp_mutex); + INIT_LIST_HEAD(&devr->x1->tgt_qp_list); + + memset(&attr, 0, sizeof(attr)); + attr.attr.max_sge = 1; + attr.attr.max_wr = 1; + attr.srq_type = IB_SRQT_XRC; + attr.ext.xrc.cq = devr->c0; + attr.ext.xrc.xrcd = devr->x0; + + devr->s0 = mlx5_ib_create_srq(devr->p0, &attr, NULL); + if (IS_ERR(devr->s0)) { + ret = PTR_ERR(devr->s0); + goto error4; + } + devr->s0->device = &dev->ib_dev; + devr->s0->pd = devr->p0; + devr->s0->uobject = NULL; + devr->s0->event_handler = NULL; + devr->s0->srq_context = NULL; + devr->s0->srq_type = IB_SRQT_XRC; + devr->s0->ext.xrc.xrcd = devr->x0; + devr->s0->ext.xrc.cq = devr->c0; + atomic_inc(&devr->s0->ext.xrc.xrcd->usecnt); + atomic_inc(&devr->s0->ext.xrc.cq->usecnt); + atomic_inc(&devr->p0->usecnt); + atomic_set(&devr->s0->usecnt, 0); + + return 0; + +error4: + mlx5_ib_dealloc_xrcd(devr->x1); +error3: + mlx5_ib_dealloc_xrcd(devr->x0); +error2: + mlx5_ib_destroy_cq(devr->c0); +error1: + mlx5_ib_dealloc_pd(devr->p0); +error0: + return ret; +} + +static void destroy_dev_resources(struct mlx5_ib_resources *devr) +{ + mlx5_ib_destroy_srq(devr->s0); + mlx5_ib_dealloc_xrcd(devr->x0); + mlx5_ib_dealloc_xrcd(devr->x1); + mlx5_ib_destroy_cq(devr->c0); + mlx5_ib_dealloc_pd(devr->p0); +} + +static int init_one(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct mlx5_core_dev *mdev; + struct mlx5_ib_dev *dev; + int err; + int i; + + printk_once(KERN_INFO "%s", mlx5_version); + + dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev)); + if (!dev) + return -ENOMEM; + + mdev = &dev->mdev; + mdev->event = mlx5_ib_event; + if (prof_sel >= ARRAY_SIZE(profile)) { + pr_warn("selected pofile out of range, selceting default\n"); + prof_sel = 0; + } + mdev->profile = &profile[prof_sel]; + err = mlx5_dev_init(mdev, pdev); + if (err) + goto err_free; + + err = get_port_caps(dev); + if (err) + goto err_cleanup; + + get_ext_port_caps(dev); + + err = alloc_comp_eqs(dev); + if (err) + goto err_cleanup; + + MLX5_INIT_DOORBELL_LOCK(&dev->uar_lock); + + strlcpy(dev->ib_dev.name, "mlx5_%d", IB_DEVICE_NAME_MAX); + dev->ib_dev.owner = THIS_MODULE; + dev->ib_dev.node_type = RDMA_NODE_IB_CA; + dev->ib_dev.local_dma_lkey = mdev->caps.reserved_lkey; + dev->num_ports = mdev->caps.num_ports; + dev->ib_dev.phys_port_cnt = dev->num_ports; + dev->ib_dev.num_comp_vectors = dev->num_comp_vectors; + dev->ib_dev.dma_device = &mdev->pdev->dev; + + dev->ib_dev.uverbs_abi_ver = MLX5_IB_UVERBS_ABI_VERSION; + dev->ib_dev.uverbs_cmd_mask = + (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | + (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | + (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | + (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | + (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | + (1ull << IB_USER_VERBS_CMD_REG_MR) | + (1ull << IB_USER_VERBS_CMD_DEREG_MR) | + (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | + (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | + (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | + (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | + (1ull << IB_USER_VERBS_CMD_CREATE_QP) | + (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | + (1ull << IB_USER_VERBS_CMD_QUERY_QP) | + (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | + (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | + (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | + (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | + (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | + (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | + (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) | + (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) | + (1ull << IB_USER_VERBS_CMD_OPEN_QP); + + dev->ib_dev.query_device = mlx5_ib_query_device; + dev->ib_dev.query_port = mlx5_ib_query_port; + dev->ib_dev.query_gid = mlx5_ib_query_gid; + dev->ib_dev.query_pkey = mlx5_ib_query_pkey; + dev->ib_dev.modify_device = mlx5_ib_modify_device; + dev->ib_dev.modify_port = mlx5_ib_modify_port; + dev->ib_dev.alloc_ucontext = mlx5_ib_alloc_ucontext; + dev->ib_dev.dealloc_ucontext = mlx5_ib_dealloc_ucontext; + dev->ib_dev.mmap = mlx5_ib_mmap; + dev->ib_dev.alloc_pd = mlx5_ib_alloc_pd; + dev->ib_dev.dealloc_pd = mlx5_ib_dealloc_pd; + dev->ib_dev.create_ah = mlx5_ib_create_ah; + dev->ib_dev.query_ah = mlx5_ib_query_ah; + dev->ib_dev.destroy_ah = mlx5_ib_destroy_ah; + dev->ib_dev.create_srq = mlx5_ib_create_srq; + dev->ib_dev.modify_srq = mlx5_ib_modify_srq; + dev->ib_dev.query_srq = mlx5_ib_query_srq; + dev->ib_dev.destroy_srq = mlx5_ib_destroy_srq; + dev->ib_dev.post_srq_recv = mlx5_ib_post_srq_recv; + dev->ib_dev.create_qp = mlx5_ib_create_qp; + dev->ib_dev.modify_qp = mlx5_ib_modify_qp; + dev->ib_dev.query_qp = mlx5_ib_query_qp; + dev->ib_dev.destroy_qp = mlx5_ib_destroy_qp; + dev->ib_dev.post_send = mlx5_ib_post_send; + dev->ib_dev.post_recv = mlx5_ib_post_recv; + dev->ib_dev.create_cq = mlx5_ib_create_cq; + dev->ib_dev.modify_cq = mlx5_ib_modify_cq; + dev->ib_dev.resize_cq = mlx5_ib_resize_cq; + dev->ib_dev.destroy_cq = mlx5_ib_destroy_cq; + dev->ib_dev.poll_cq = mlx5_ib_poll_cq; + dev->ib_dev.req_notify_cq = mlx5_ib_arm_cq; + dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr; + dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr; + dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr; + dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach; + dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach; + dev->ib_dev.process_mad = mlx5_ib_process_mad; + dev->ib_dev.alloc_fast_reg_mr = mlx5_ib_alloc_fast_reg_mr; + dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list; + dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list; + + if (mdev->caps.flags & MLX5_DEV_CAP_FLAG_XRC) { + dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd; + dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd; + dev->ib_dev.uverbs_cmd_mask |= + (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) | + (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD); + } + + err = init_node_data(dev); + if (err) + goto err_eqs; + + mutex_init(&dev->cap_mask_mutex); + spin_lock_init(&dev->mr_lock); + + err = create_dev_resources(&dev->devr); + if (err) + goto err_eqs; + + if (ib_register_device(&dev->ib_dev, NULL)) + goto err_rsrc; + + err = create_umr_res(dev); + if (err) + goto err_dev; + + for (i = 0; i < ARRAY_SIZE(mlx5_class_attributes); i++) { + if (device_create_file(&dev->ib_dev.dev, + mlx5_class_attributes[i])) + goto err_umrc; + } + + dev->ib_active = true; + + return 0; + +err_umrc: + destroy_umrc_res(dev); + +err_dev: + ib_unregister_device(&dev->ib_dev); + +err_rsrc: + destroy_dev_resources(&dev->devr); + +err_eqs: + free_comp_eqs(dev); + +err_cleanup: + mlx5_dev_cleanup(mdev); + +err_free: + ib_dealloc_device((struct ib_device *)dev); + + return err; +} + +static void remove_one(struct pci_dev *pdev) +{ + struct mlx5_ib_dev *dev = mlx5_pci2ibdev(pdev); + + destroy_umrc_res(dev); + ib_unregister_device(&dev->ib_dev); + destroy_dev_resources(&dev->devr); + free_comp_eqs(dev); + mlx5_dev_cleanup(&dev->mdev); + ib_dealloc_device(&dev->ib_dev); +} + +static DEFINE_PCI_DEVICE_TABLE(mlx5_ib_pci_table) = { + { PCI_VDEVICE(MELLANOX, 4113) }, /* MT4113 Connect-IB */ + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, mlx5_ib_pci_table); + +static struct pci_driver mlx5_ib_driver = { + .name = DRIVER_NAME, + .id_table = mlx5_ib_pci_table, + .probe = init_one, + .remove = remove_one +}; + +static int __init mlx5_ib_init(void) +{ + return pci_register_driver(&mlx5_ib_driver); +} + +static void __exit mlx5_ib_cleanup(void) +{ + pci_unregister_driver(&mlx5_ib_driver); +} + +module_init(mlx5_ib_init); +module_exit(mlx5_ib_cleanup); diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c new file mode 100644 index 000000000000..3a5322870b96 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/mem.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "mlx5_ib.h" + +/* @umem: umem object to scan + * @addr: ib virtual address requested by the user + * @count: number of PAGE_SIZE pages covered by umem + * @shift: page shift for the compound pages found in the region + * @ncont: number of compund pages + * @order: log2 of the number of compound pages + */ +void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, + int *ncont, int *order) +{ + struct ib_umem_chunk *chunk; + unsigned long tmp; + unsigned long m; + int i, j, k; + u64 base = 0; + int p = 0; + int skip; + int mask; + u64 len; + u64 pfn; + + addr = addr >> PAGE_SHIFT; + tmp = (unsigned long)addr; + m = find_first_bit(&tmp, sizeof(tmp)); + skip = 1 << m; + mask = skip - 1; + i = 0; + list_for_each_entry(chunk, &umem->chunk_list, list) + for (j = 0; j < chunk->nmap; j++) { + len = sg_dma_len(&chunk->page_list[j]) >> PAGE_SHIFT; + pfn = sg_dma_address(&chunk->page_list[j]) >> PAGE_SHIFT; + for (k = 0; k < len; k++) { + if (!(i & mask)) { + tmp = (unsigned long)pfn; + m = min(m, find_first_bit(&tmp, sizeof(tmp))); + skip = 1 << m; + mask = skip - 1; + base = pfn; + p = 0; + } else { + if (base + p != pfn) { + tmp = (unsigned long)p; + m = find_first_bit(&tmp, sizeof(tmp)); + skip = 1 << m; + mask = skip - 1; + base = pfn; + p = 0; + } + } + p++; + i++; + } + } + + if (i) { + m = min_t(unsigned long, ilog2(roundup_pow_of_two(i)), m); + + if (order) + *order = ilog2(roundup_pow_of_two(i) >> m); + + *ncont = DIV_ROUND_UP(i, (1 << m)); + } else { + m = 0; + + if (order) + *order = 0; + + *ncont = 0; + } + *shift = PAGE_SHIFT + m; + *count = i; +} + +void mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, + int page_shift, __be64 *pas, int umr) +{ + int shift = page_shift - PAGE_SHIFT; + int mask = (1 << shift) - 1; + struct ib_umem_chunk *chunk; + int i, j, k; + u64 cur = 0; + u64 base; + int len; + + i = 0; + list_for_each_entry(chunk, &umem->chunk_list, list) + for (j = 0; j < chunk->nmap; j++) { + len = sg_dma_len(&chunk->page_list[j]) >> PAGE_SHIFT; + base = sg_dma_address(&chunk->page_list[j]); + for (k = 0; k < len; k++) { + if (!(i & mask)) { + cur = base + (k << PAGE_SHIFT); + if (umr) + cur |= 3; + + pas[i >> shift] = cpu_to_be64(cur); + mlx5_ib_dbg(dev, "pas[%d] 0x%llx\n", + i >> shift, be64_to_cpu(pas[i >> shift])); + } else + mlx5_ib_dbg(dev, "=====> 0x%llx\n", + base + (k << PAGE_SHIFT)); + i++; + } + } +} + +int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset) +{ + u64 page_size; + u64 page_mask; + u64 off_size; + u64 off_mask; + u64 buf_off; + + page_size = 1 << page_shift; + page_mask = page_size - 1; + buf_off = addr & page_mask; + off_size = page_size >> 6; + off_mask = off_size - 1; + + if (buf_off & off_mask) + return -EINVAL; + + *offset = buf_off >> ilog2(off_size); + return 0; +} diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h new file mode 100644 index 000000000000..836be9157242 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_IB_H +#define MLX5_IB_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define mlx5_ib_dbg(dev, format, arg...) \ +pr_debug("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ + __LINE__, current->pid, ##arg) + +#define mlx5_ib_err(dev, format, arg...) \ +pr_err("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ + __LINE__, current->pid, ##arg) + +#define mlx5_ib_warn(dev, format, arg...) \ +pr_warn("%s:%s:%d:(pid %d): " format, (dev)->ib_dev.name, __func__, \ + __LINE__, current->pid, ##arg) + +enum { + MLX5_IB_MMAP_CMD_SHIFT = 8, + MLX5_IB_MMAP_CMD_MASK = 0xff, +}; + +enum mlx5_ib_mmap_cmd { + MLX5_IB_MMAP_REGULAR_PAGE = 0, + MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES = 1, /* always last */ +}; + +enum { + MLX5_RES_SCAT_DATA32_CQE = 0x1, + MLX5_RES_SCAT_DATA64_CQE = 0x2, + MLX5_REQ_SCAT_DATA32_CQE = 0x11, + MLX5_REQ_SCAT_DATA64_CQE = 0x22, +}; + +enum mlx5_ib_latency_class { + MLX5_IB_LATENCY_CLASS_LOW, + MLX5_IB_LATENCY_CLASS_MEDIUM, + MLX5_IB_LATENCY_CLASS_HIGH, + MLX5_IB_LATENCY_CLASS_FAST_PATH +}; + +enum mlx5_ib_mad_ifc_flags { + MLX5_MAD_IFC_IGNORE_MKEY = 1, + MLX5_MAD_IFC_IGNORE_BKEY = 2, + MLX5_MAD_IFC_NET_VIEW = 4, +}; + +struct mlx5_ib_ucontext { + struct ib_ucontext ibucontext; + struct list_head db_page_list; + + /* protect doorbell record alloc/free + */ + struct mutex db_page_mutex; + struct mlx5_uuar_info uuari; +}; + +static inline struct mlx5_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext) +{ + return container_of(ibucontext, struct mlx5_ib_ucontext, ibucontext); +} + +struct mlx5_ib_pd { + struct ib_pd ibpd; + u32 pdn; + u32 pa_lkey; +}; + +/* Use macros here so that don't have to duplicate + * enum ib_send_flags and enum ib_qp_type for low-level driver + */ + +#define MLX5_IB_SEND_UMR_UNREG IB_SEND_RESERVED_START +#define MLX5_IB_QPT_REG_UMR IB_QPT_RESERVED1 +#define MLX5_IB_WR_UMR IB_WR_RESERVED1 + +struct wr_list { + u16 opcode; + u16 next; +}; + +struct mlx5_ib_wq { + u64 *wrid; + u32 *wr_data; + struct wr_list *w_list; + unsigned *wqe_head; + u16 unsig_count; + + /* serialize post to the work queue + */ + spinlock_t lock; + int wqe_cnt; + int max_post; + int max_gs; + int offset; + int wqe_shift; + unsigned head; + unsigned tail; + u16 cur_post; + u16 last_poll; + void *qend; +}; + +enum { + MLX5_QP_USER, + MLX5_QP_KERNEL, + MLX5_QP_EMPTY +}; + +struct mlx5_ib_qp { + struct ib_qp ibqp; + struct mlx5_core_qp mqp; + struct mlx5_buf buf; + + struct mlx5_db db; + struct mlx5_ib_wq rq; + + u32 doorbell_qpn; + u8 sq_signal_bits; + u8 fm_cache; + int sq_max_wqes_per_wr; + int sq_spare_wqes; + struct mlx5_ib_wq sq; + + struct ib_umem *umem; + int buf_size; + + /* serialize qp state modifications + */ + struct mutex mutex; + u16 xrcdn; + u32 flags; + u8 port; + u8 alt_port; + u8 atomic_rd_en; + u8 resp_depth; + u8 state; + int mlx_type; + int wq_sig; + int scat_cqe; + int max_inline_data; + struct mlx5_bf *bf; + int has_rq; + + /* only for user space QPs. For kernel + * we have it from the bf object + */ + int uuarn; + + int create_type; + u32 pa_lkey; +}; + +struct mlx5_ib_cq_buf { + struct mlx5_buf buf; + struct ib_umem *umem; + int cqe_size; +}; + +enum mlx5_ib_qp_flags { + MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK = 1 << 0, + MLX5_IB_QP_SIGNATURE_HANDLING = 1 << 1, +}; + +struct mlx5_shared_mr_info { + int mr_id; + struct ib_umem *umem; +}; + +struct mlx5_ib_cq { + struct ib_cq ibcq; + struct mlx5_core_cq mcq; + struct mlx5_ib_cq_buf buf; + struct mlx5_db db; + + /* serialize access to the CQ + */ + spinlock_t lock; + + /* protect resize cq + */ + struct mutex resize_mutex; + struct mlx5_ib_cq_resize *resize_buf; + struct ib_umem *resize_umem; + int cqe_size; +}; + +struct mlx5_ib_srq { + struct ib_srq ibsrq; + struct mlx5_core_srq msrq; + struct mlx5_buf buf; + struct mlx5_db db; + u64 *wrid; + /* protect SRQ hanlding + */ + spinlock_t lock; + int head; + int tail; + u16 wqe_ctr; + struct ib_umem *umem; + /* serialize arming a SRQ + */ + struct mutex mutex; + int wq_sig; +}; + +struct mlx5_ib_xrcd { + struct ib_xrcd ibxrcd; + u32 xrcdn; +}; + +struct mlx5_ib_mr { + struct ib_mr ibmr; + struct mlx5_core_mr mmr; + struct ib_umem *umem; + struct mlx5_shared_mr_info *smr_info; + struct list_head list; + int order; + int umred; + __be64 *pas; + dma_addr_t dma; + int npages; + struct completion done; + enum ib_wc_status status; +}; + +struct mlx5_ib_fast_reg_page_list { + struct ib_fast_reg_page_list ibfrpl; + __be64 *mapped_page_list; + dma_addr_t map; +}; + +struct umr_common { + struct ib_pd *pd; + struct ib_cq *cq; + struct ib_qp *qp; + struct ib_mr *mr; + /* control access to UMR QP + */ + struct semaphore sem; +}; + +enum { + MLX5_FMR_INVALID, + MLX5_FMR_VALID, + MLX5_FMR_BUSY, +}; + +struct mlx5_ib_fmr { + struct ib_fmr ibfmr; + struct mlx5_core_mr mr; + int access_flags; + int state; + /* protect fmr state + */ + spinlock_t lock; + u64 wrid; + struct ib_send_wr wr[2]; + u8 page_shift; + struct ib_fast_reg_page_list page_list; +}; + +struct mlx5_cache_ent { + struct list_head head; + /* sync access to the cahce entry + */ + spinlock_t lock; + + + struct dentry *dir; + char name[4]; + u32 order; + u32 size; + u32 cur; + u32 miss; + u32 limit; + + struct dentry *fsize; + struct dentry *fcur; + struct dentry *fmiss; + struct dentry *flimit; + + struct mlx5_ib_dev *dev; + struct work_struct work; + struct delayed_work dwork; +}; + +struct mlx5_mr_cache { + struct workqueue_struct *wq; + struct mlx5_cache_ent ent[MAX_MR_CACHE_ENTRIES]; + int stopped; + struct dentry *root; + unsigned long last_add; +}; + +struct mlx5_ib_resources { + struct ib_cq *c0; + struct ib_xrcd *x0; + struct ib_xrcd *x1; + struct ib_pd *p0; + struct ib_srq *s0; +}; + +struct mlx5_ib_dev { + struct ib_device ib_dev; + struct mlx5_core_dev mdev; + MLX5_DECLARE_DOORBELL_LOCK(uar_lock); + struct list_head eqs_list; + int num_ports; + int num_comp_vectors; + /* serialize update of capability mask + */ + struct mutex cap_mask_mutex; + bool ib_active; + struct umr_common umrc; + /* sync used page count stats + */ + spinlock_t mr_lock; + struct mlx5_ib_resources devr; + struct mlx5_mr_cache cache; +}; + +static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq) +{ + return container_of(mcq, struct mlx5_ib_cq, mcq); +} + +static inline struct mlx5_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd) +{ + return container_of(ibxrcd, struct mlx5_ib_xrcd, ibxrcd); +} + +static inline struct mlx5_ib_dev *to_mdev(struct ib_device *ibdev) +{ + return container_of(ibdev, struct mlx5_ib_dev, ib_dev); +} + +static inline struct mlx5_ib_fmr *to_mfmr(struct ib_fmr *ibfmr) +{ + return container_of(ibfmr, struct mlx5_ib_fmr, ibfmr); +} + +static inline struct mlx5_ib_cq *to_mcq(struct ib_cq *ibcq) +{ + return container_of(ibcq, struct mlx5_ib_cq, ibcq); +} + +static inline struct mlx5_ib_qp *to_mibqp(struct mlx5_core_qp *mqp) +{ + return container_of(mqp, struct mlx5_ib_qp, mqp); +} + +static inline struct mlx5_ib_pd *to_mpd(struct ib_pd *ibpd) +{ + return container_of(ibpd, struct mlx5_ib_pd, ibpd); +} + +static inline struct mlx5_ib_srq *to_msrq(struct ib_srq *ibsrq) +{ + return container_of(ibsrq, struct mlx5_ib_srq, ibsrq); +} + +static inline struct mlx5_ib_qp *to_mqp(struct ib_qp *ibqp) +{ + return container_of(ibqp, struct mlx5_ib_qp, ibqp); +} + +static inline struct mlx5_ib_srq *to_mibsrq(struct mlx5_core_srq *msrq) +{ + return container_of(msrq, struct mlx5_ib_srq, msrq); +} + +static inline struct mlx5_ib_mr *to_mmr(struct ib_mr *ibmr) +{ + return container_of(ibmr, struct mlx5_ib_mr, ibmr); +} + +static inline struct mlx5_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_page_list *ibfrpl) +{ + return container_of(ibfrpl, struct mlx5_ib_fast_reg_page_list, ibfrpl); +} + +struct mlx5_ib_ah { + struct ib_ah ibah; + struct mlx5_av av; +}; + +static inline struct mlx5_ib_ah *to_mah(struct ib_ah *ibah) +{ + return container_of(ibah, struct mlx5_ib_ah, ibah); +} + +static inline struct mlx5_ib_dev *mlx5_core2ibdev(struct mlx5_core_dev *dev) +{ + return container_of(dev, struct mlx5_ib_dev, mdev); +} + +static inline struct mlx5_ib_dev *mlx5_pci2ibdev(struct pci_dev *pdev) +{ + return mlx5_core2ibdev(pci2mlx5_core_dev(pdev)); +} + +int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt, + struct mlx5_db *db); +void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db); +void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); +void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); +void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index); +int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, + int port, struct ib_wc *in_wc, struct ib_grh *in_grh, + void *in_mad, void *response_mad); +struct ib_ah *create_ib_ah(struct ib_ah_attr *ah_attr, + struct mlx5_ib_ah *ah); +struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); +int mlx5_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr); +int mlx5_ib_destroy_ah(struct ib_ah *ah); +struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, + struct ib_srq_init_attr *init_attr, + struct ib_udata *udata); +int mlx5_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, + enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); +int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr); +int mlx5_ib_destroy_srq(struct ib_srq *srq); +int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, + struct ib_recv_wr **bad_wr); +struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata); +int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, + int attr_mask, struct ib_udata *udata); +int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, + struct ib_qp_init_attr *qp_init_attr); +int mlx5_ib_destroy_qp(struct ib_qp *qp); +int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, + struct ib_send_wr **bad_wr); +int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, + struct ib_recv_wr **bad_wr); +void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n); +struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev, int entries, + int vector, struct ib_ucontext *context, + struct ib_udata *udata); +int mlx5_ib_destroy_cq(struct ib_cq *cq); +int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc); +int mlx5_ib_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags); +int mlx5_ib_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period); +int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata); +struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc); +struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + u64 virt_addr, int access_flags, + struct ib_udata *udata); +int mlx5_ib_dereg_mr(struct ib_mr *ibmr); +struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, + int max_page_list_len); +struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev, + int page_list_len); +void mlx5_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list); +struct ib_fmr *mlx5_ib_fmr_alloc(struct ib_pd *pd, int acc, + struct ib_fmr_attr *fmr_attr); +int mlx5_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, + int npages, u64 iova); +int mlx5_ib_unmap_fmr(struct list_head *fmr_list); +int mlx5_ib_fmr_dealloc(struct ib_fmr *ibfmr); +int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, + struct ib_wc *in_wc, struct ib_grh *in_grh, + struct ib_mad *in_mad, struct ib_mad *out_mad); +struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, + struct ib_ucontext *context, + struct ib_udata *udata); +int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd); +int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn); +int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset); +int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port); +int mlx5_ib_query_port(struct ib_device *ibdev, u8 port, + struct ib_port_attr *props); +int mlx5_ib_init_fmr(struct mlx5_ib_dev *dev); +void mlx5_ib_cleanup_fmr(struct mlx5_ib_dev *dev); +void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift, + int *ncont, int *order); +void mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem, + int page_shift, __be64 *pas, int umr); +void mlx5_ib_copy_pas(u64 *old, u64 *new, int step, int num); +int mlx5_ib_get_cqe_size(struct mlx5_ib_dev *dev, struct ib_cq *ibcq); +int mlx5_mr_cache_init(struct mlx5_ib_dev *dev); +int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev); +int mlx5_mr_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift); +void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context); + +static inline void init_query_mad(struct ib_smp *mad) +{ + mad->base_version = 1; + mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; + mad->class_version = 1; + mad->method = IB_MGMT_METHOD_GET; +} + +static inline u8 convert_access(int acc) +{ + return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) | + (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) | + MLX5_PERM_LOCAL_READ; +} + +#endif /* MLX5_IB_H */ diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c new file mode 100644 index 000000000000..e2daa8f02476 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -0,0 +1,1007 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include +#include +#include +#include +#include +#include "mlx5_ib.h" + +enum { + DEF_CACHE_SIZE = 10, +}; + +static __be64 *mr_align(__be64 *ptr, int align) +{ + unsigned long mask = align - 1; + + return (__be64 *)(((unsigned long)ptr + mask) & ~mask); +} + +static int order2idx(struct mlx5_ib_dev *dev, int order) +{ + struct mlx5_mr_cache *cache = &dev->cache; + + if (order < cache->ent[0].order) + return 0; + else + return order - cache->ent[0].order; +} + +static int add_keys(struct mlx5_ib_dev *dev, int c, int num) +{ + struct device *ddev = dev->ib_dev.dma_device; + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent = &cache->ent[c]; + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_ib_mr *mr; + int npages = 1 << ent->order; + int size = sizeof(u64) * npages; + int err = 0; + int i; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return -ENOMEM; + + for (i = 0; i < num; i++) { + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) { + err = -ENOMEM; + goto out; + } + mr->order = ent->order; + mr->umred = 1; + mr->pas = kmalloc(size + 0x3f, GFP_KERNEL); + if (!mr->pas) { + kfree(mr); + err = -ENOMEM; + goto out; + } + mr->dma = dma_map_single(ddev, mr_align(mr->pas, 0x40), size, + DMA_TO_DEVICE); + if (dma_mapping_error(ddev, mr->dma)) { + kfree(mr->pas); + kfree(mr); + err = -ENOMEM; + goto out; + } + + in->seg.status = 1 << 6; + in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2); + in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + in->seg.flags = MLX5_ACCESS_MODE_MTT | MLX5_PERM_UMR_EN; + in->seg.log2_page_size = 12; + + err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, + sizeof(*in)); + if (err) { + mlx5_ib_warn(dev, "create mkey failed %d\n", err); + dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE); + kfree(mr->pas); + kfree(mr); + goto out; + } + cache->last_add = jiffies; + + spin_lock(&ent->lock); + list_add_tail(&mr->list, &ent->head); + ent->cur++; + ent->size++; + spin_unlock(&ent->lock); + } + +out: + kfree(in); + return err; +} + +static void remove_keys(struct mlx5_ib_dev *dev, int c, int num) +{ + struct device *ddev = dev->ib_dev.dma_device; + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent = &cache->ent[c]; + struct mlx5_ib_mr *mr; + int size; + int err; + int i; + + for (i = 0; i < num; i++) { + spin_lock(&ent->lock); + if (list_empty(&ent->head)) { + spin_unlock(&ent->lock); + return; + } + mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list); + list_del(&mr->list); + ent->cur--; + ent->size--; + spin_unlock(&ent->lock); + err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); + if (err) { + mlx5_ib_warn(dev, "failed destroy mkey\n"); + } else { + size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40); + dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE); + kfree(mr->pas); + kfree(mr); + } + } +} + +static ssize_t size_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_cache_ent *ent = filp->private_data; + struct mlx5_ib_dev *dev = ent->dev; + char lbuf[20]; + u32 var; + int err; + int c; + + if (copy_from_user(lbuf, buf, sizeof(lbuf))) + return -EPERM; + + c = order2idx(dev, ent->order); + lbuf[sizeof(lbuf) - 1] = 0; + + if (sscanf(lbuf, "%u", &var) != 1) + return -EINVAL; + + if (var < ent->limit) + return -EINVAL; + + if (var > ent->size) { + err = add_keys(dev, c, var - ent->size); + if (err) + return err; + } else if (var < ent->size) { + remove_keys(dev, c, ent->size - var); + } + + return count; +} + +static ssize_t size_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_cache_ent *ent = filp->private_data; + char lbuf[20]; + int err; + + if (*pos) + return 0; + + err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->size); + if (err < 0) + return err; + + if (copy_to_user(buf, lbuf, err)) + return -EPERM; + + *pos += err; + + return err; +} + +static const struct file_operations size_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = size_write, + .read = size_read, +}; + +static ssize_t limit_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_cache_ent *ent = filp->private_data; + struct mlx5_ib_dev *dev = ent->dev; + char lbuf[20]; + u32 var; + int err; + int c; + + if (copy_from_user(lbuf, buf, sizeof(lbuf))) + return -EPERM; + + c = order2idx(dev, ent->order); + lbuf[sizeof(lbuf) - 1] = 0; + + if (sscanf(lbuf, "%u", &var) != 1) + return -EINVAL; + + if (var > ent->size) + return -EINVAL; + + ent->limit = var; + + if (ent->cur < ent->limit) { + err = add_keys(dev, c, 2 * ent->limit - ent->cur); + if (err) + return err; + } + + return count; +} + +static ssize_t limit_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_cache_ent *ent = filp->private_data; + char lbuf[20]; + int err; + + if (*pos) + return 0; + + err = snprintf(lbuf, sizeof(lbuf), "%d\n", ent->limit); + if (err < 0) + return err; + + if (copy_to_user(buf, lbuf, err)) + return -EPERM; + + *pos += err; + + return err; +} + +static const struct file_operations limit_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = limit_write, + .read = limit_read, +}; + +static int someone_adding(struct mlx5_mr_cache *cache) +{ + int i; + + for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { + if (cache->ent[i].cur < cache->ent[i].limit) + return 1; + } + + return 0; +} + +static void __cache_work_func(struct mlx5_cache_ent *ent) +{ + struct mlx5_ib_dev *dev = ent->dev; + struct mlx5_mr_cache *cache = &dev->cache; + int i = order2idx(dev, ent->order); + + if (cache->stopped) + return; + + ent = &dev->cache.ent[i]; + if (ent->cur < 2 * ent->limit) { + add_keys(dev, i, 1); + if (ent->cur < 2 * ent->limit) + queue_work(cache->wq, &ent->work); + } else if (ent->cur > 2 * ent->limit) { + if (!someone_adding(cache) && + time_after(jiffies, cache->last_add + 60 * HZ)) { + remove_keys(dev, i, 1); + if (ent->cur > ent->limit) + queue_work(cache->wq, &ent->work); + } else { + queue_delayed_work(cache->wq, &ent->dwork, 60 * HZ); + } + } +} + +static void delayed_cache_work_func(struct work_struct *work) +{ + struct mlx5_cache_ent *ent; + + ent = container_of(work, struct mlx5_cache_ent, dwork.work); + __cache_work_func(ent); +} + +static void cache_work_func(struct work_struct *work) +{ + struct mlx5_cache_ent *ent; + + ent = container_of(work, struct mlx5_cache_ent, work); + __cache_work_func(ent); +} + +static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order) +{ + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_ib_mr *mr = NULL; + struct mlx5_cache_ent *ent; + int c; + int i; + + c = order2idx(dev, order); + if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) { + mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c); + return NULL; + } + + for (i = c; i < MAX_MR_CACHE_ENTRIES; i++) { + ent = &cache->ent[i]; + + mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i); + + spin_lock(&ent->lock); + if (!list_empty(&ent->head)) { + mr = list_first_entry(&ent->head, struct mlx5_ib_mr, + list); + list_del(&mr->list); + ent->cur--; + spin_unlock(&ent->lock); + if (ent->cur < ent->limit) + queue_work(cache->wq, &ent->work); + break; + } + spin_unlock(&ent->lock); + + queue_work(cache->wq, &ent->work); + + if (mr) + break; + } + + if (!mr) + cache->ent[c].miss++; + + return mr; +} + +static void free_cached_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) +{ + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent; + int shrink = 0; + int c; + + c = order2idx(dev, mr->order); + if (c < 0 || c >= MAX_MR_CACHE_ENTRIES) { + mlx5_ib_warn(dev, "order %d, cache index %d\n", mr->order, c); + return; + } + ent = &cache->ent[c]; + spin_lock(&ent->lock); + list_add_tail(&mr->list, &ent->head); + ent->cur++; + if (ent->cur > 2 * ent->limit) + shrink = 1; + spin_unlock(&ent->lock); + + if (shrink) + queue_work(cache->wq, &ent->work); +} + +static void clean_keys(struct mlx5_ib_dev *dev, int c) +{ + struct device *ddev = dev->ib_dev.dma_device; + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent = &cache->ent[c]; + struct mlx5_ib_mr *mr; + int size; + int err; + + while (1) { + spin_lock(&ent->lock); + if (list_empty(&ent->head)) { + spin_unlock(&ent->lock); + return; + } + mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list); + list_del(&mr->list); + ent->cur--; + ent->size--; + spin_unlock(&ent->lock); + err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); + if (err) { + mlx5_ib_warn(dev, "failed destroy mkey\n"); + } else { + size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40); + dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE); + kfree(mr->pas); + kfree(mr); + } + } +} + +static int mlx5_mr_cache_debugfs_init(struct mlx5_ib_dev *dev) +{ + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent; + int i; + + if (!mlx5_debugfs_root) + return 0; + + cache->root = debugfs_create_dir("mr_cache", dev->mdev.priv.dbg_root); + if (!cache->root) + return -ENOMEM; + + for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { + ent = &cache->ent[i]; + sprintf(ent->name, "%d", ent->order); + ent->dir = debugfs_create_dir(ent->name, cache->root); + if (!ent->dir) + return -ENOMEM; + + ent->fsize = debugfs_create_file("size", 0600, ent->dir, ent, + &size_fops); + if (!ent->fsize) + return -ENOMEM; + + ent->flimit = debugfs_create_file("limit", 0600, ent->dir, ent, + &limit_fops); + if (!ent->flimit) + return -ENOMEM; + + ent->fcur = debugfs_create_u32("cur", 0400, ent->dir, + &ent->cur); + if (!ent->fcur) + return -ENOMEM; + + ent->fmiss = debugfs_create_u32("miss", 0600, ent->dir, + &ent->miss); + if (!ent->fmiss) + return -ENOMEM; + } + + return 0; +} + +static void mlx5_mr_cache_debugfs_cleanup(struct mlx5_ib_dev *dev) +{ + if (!mlx5_debugfs_root) + return; + + debugfs_remove_recursive(dev->cache.root); +} + +int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) +{ + struct mlx5_mr_cache *cache = &dev->cache; + struct mlx5_cache_ent *ent; + int limit; + int size; + int err; + int i; + + cache->wq = create_singlethread_workqueue("mkey_cache"); + if (!cache->wq) { + mlx5_ib_warn(dev, "failed to create work queue\n"); + return -ENOMEM; + } + + for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { + INIT_LIST_HEAD(&cache->ent[i].head); + spin_lock_init(&cache->ent[i].lock); + + ent = &cache->ent[i]; + INIT_LIST_HEAD(&ent->head); + spin_lock_init(&ent->lock); + ent->order = i + 2; + ent->dev = dev; + + if (dev->mdev.profile->mask & MLX5_PROF_MASK_MR_CACHE) { + size = dev->mdev.profile->mr_cache[i].size; + limit = dev->mdev.profile->mr_cache[i].limit; + } else { + size = DEF_CACHE_SIZE; + limit = 0; + } + INIT_WORK(&ent->work, cache_work_func); + INIT_DELAYED_WORK(&ent->dwork, delayed_cache_work_func); + ent->limit = limit; + queue_work(cache->wq, &ent->work); + } + + err = mlx5_mr_cache_debugfs_init(dev); + if (err) + mlx5_ib_warn(dev, "cache debugfs failure\n"); + + return 0; +} + +int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev) +{ + int i; + + dev->cache.stopped = 1; + destroy_workqueue(dev->cache.wq); + + mlx5_mr_cache_debugfs_cleanup(dev); + + for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) + clean_keys(dev, i); + + return 0; +} + +struct ib_mr *mlx5_ib_get_dma_mr(struct ib_pd *pd, int acc) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_core_dev *mdev = &dev->mdev; + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_mkey_seg *seg; + struct mlx5_ib_mr *mr; + int err; + + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) + return ERR_PTR(-ENOMEM); + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) { + err = -ENOMEM; + goto err_free; + } + + seg = &in->seg; + seg->flags = convert_access(acc) | MLX5_ACCESS_MODE_PA; + seg->flags_pd = cpu_to_be32(to_mpd(pd)->pdn | MLX5_MKEY_LEN64); + seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + seg->start_addr = 0; + + err = mlx5_core_create_mkey(mdev, &mr->mmr, in, sizeof(*in)); + if (err) + goto err_in; + + kfree(in); + mr->ibmr.lkey = mr->mmr.key; + mr->ibmr.rkey = mr->mmr.key; + mr->umem = NULL; + + return &mr->ibmr; + +err_in: + kfree(in); + +err_free: + kfree(mr); + + return ERR_PTR(err); +} + +static int get_octo_len(u64 addr, u64 len, int page_size) +{ + u64 offset; + int npages; + + offset = addr & (page_size - 1); + npages = ALIGN(len + offset, page_size) >> ilog2(page_size); + return (npages + 1) / 2; +} + +static int use_umr(int order) +{ + return order <= 17; +} + +static void prep_umr_reg_wqe(struct ib_pd *pd, struct ib_send_wr *wr, + struct ib_sge *sg, u64 dma, int n, u32 key, + int page_shift, u64 virt_addr, u64 len, + int access_flags) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct ib_mr *mr = dev->umrc.mr; + + sg->addr = dma; + sg->length = ALIGN(sizeof(u64) * n, 64); + sg->lkey = mr->lkey; + + wr->next = NULL; + wr->send_flags = 0; + wr->sg_list = sg; + if (n) + wr->num_sge = 1; + else + wr->num_sge = 0; + + wr->opcode = MLX5_IB_WR_UMR; + wr->wr.fast_reg.page_list_len = n; + wr->wr.fast_reg.page_shift = page_shift; + wr->wr.fast_reg.rkey = key; + wr->wr.fast_reg.iova_start = virt_addr; + wr->wr.fast_reg.length = len; + wr->wr.fast_reg.access_flags = access_flags; + wr->wr.fast_reg.page_list = (struct ib_fast_reg_page_list *)pd; +} + +static void prep_umr_unreg_wqe(struct mlx5_ib_dev *dev, + struct ib_send_wr *wr, u32 key) +{ + wr->send_flags = MLX5_IB_SEND_UMR_UNREG; + wr->opcode = MLX5_IB_WR_UMR; + wr->wr.fast_reg.rkey = key; +} + +void mlx5_umr_cq_handler(struct ib_cq *cq, void *cq_context) +{ + struct mlx5_ib_mr *mr; + struct ib_wc wc; + int err; + + while (1) { + err = ib_poll_cq(cq, 1, &wc); + if (err < 0) { + pr_warn("poll cq error %d\n", err); + return; + } + if (err == 0) + break; + + mr = (struct mlx5_ib_mr *)(unsigned long)wc.wr_id; + mr->status = wc.status; + complete(&mr->done); + } + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); +} + +static struct mlx5_ib_mr *reg_umr(struct ib_pd *pd, struct ib_umem *umem, + u64 virt_addr, u64 len, int npages, + int page_shift, int order, int access_flags) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct umr_common *umrc = &dev->umrc; + struct ib_send_wr wr, *bad; + struct mlx5_ib_mr *mr; + struct ib_sge sg; + int err; + int i; + + for (i = 0; i < 10; i++) { + mr = alloc_cached_mr(dev, order); + if (mr) + break; + + err = add_keys(dev, order2idx(dev, order), 1); + if (err) { + mlx5_ib_warn(dev, "add_keys failed\n"); + break; + } + } + + if (!mr) + return ERR_PTR(-EAGAIN); + + mlx5_ib_populate_pas(dev, umem, page_shift, mr_align(mr->pas, 0x40), 1); + + memset(&wr, 0, sizeof(wr)); + wr.wr_id = (u64)(unsigned long)mr; + prep_umr_reg_wqe(pd, &wr, &sg, mr->dma, npages, mr->mmr.key, page_shift, virt_addr, len, access_flags); + + /* We serialize polls so one process does not kidnap another's + * completion. This is not a problem since wr is completed in + * around 1 usec + */ + down(&umrc->sem); + init_completion(&mr->done); + err = ib_post_send(umrc->qp, &wr, &bad); + if (err) { + mlx5_ib_warn(dev, "post send failed, err %d\n", err); + up(&umrc->sem); + goto error; + } + wait_for_completion(&mr->done); + up(&umrc->sem); + + if (mr->status != IB_WC_SUCCESS) { + mlx5_ib_warn(dev, "reg umr failed\n"); + err = -EFAULT; + goto error; + } + + return mr; + +error: + free_cached_mr(dev, mr); + return ERR_PTR(err); +} + +static struct mlx5_ib_mr *reg_create(struct ib_pd *pd, u64 virt_addr, + u64 length, struct ib_umem *umem, + int npages, int page_shift, + int access_flags) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_ib_mr *mr; + int inlen; + int err; + + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) + return ERR_PTR(-ENOMEM); + + inlen = sizeof(*in) + sizeof(*in->pas) * ((npages + 1) / 2) * 2; + in = mlx5_vzalloc(inlen); + if (!in) { + err = -ENOMEM; + goto err_1; + } + mlx5_ib_populate_pas(dev, umem, page_shift, in->pas, 0); + + in->seg.flags = convert_access(access_flags) | + MLX5_ACCESS_MODE_MTT; + in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); + in->seg.start_addr = cpu_to_be64(virt_addr); + in->seg.len = cpu_to_be64(length); + in->seg.bsfs_octo_size = 0; + in->seg.xlt_oct_size = cpu_to_be32(get_octo_len(virt_addr, length, 1 << page_shift)); + in->seg.log2_page_size = page_shift; + in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + in->xlat_oct_act_size = cpu_to_be32(get_octo_len(virt_addr, length, 1 << page_shift)); + err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, inlen); + if (err) { + mlx5_ib_warn(dev, "create mkey failed\n"); + goto err_2; + } + mr->umem = umem; + mlx5_vfree(in); + + mlx5_ib_dbg(dev, "mkey = 0x%x\n", mr->mmr.key); + + return mr; + +err_2: + mlx5_vfree(in); + +err_1: + kfree(mr); + + return ERR_PTR(err); +} + +struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + u64 virt_addr, int access_flags, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_ib_mr *mr = NULL; + struct ib_umem *umem; + int page_shift; + int npages; + int ncont; + int order; + int err; + + mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx\n", + start, virt_addr, length); + umem = ib_umem_get(pd->uobject->context, start, length, access_flags, + 0); + if (IS_ERR(umem)) { + mlx5_ib_dbg(dev, "umem get failed\n"); + return (void *)umem; + } + + mlx5_ib_cont_pages(umem, start, &npages, &page_shift, &ncont, &order); + if (!npages) { + mlx5_ib_warn(dev, "avoid zero region\n"); + err = -EINVAL; + goto error; + } + + mlx5_ib_dbg(dev, "npages %d, ncont %d, order %d, page_shift %d\n", + npages, ncont, order, page_shift); + + if (use_umr(order)) { + mr = reg_umr(pd, umem, virt_addr, length, ncont, page_shift, + order, access_flags); + if (PTR_ERR(mr) == -EAGAIN) { + mlx5_ib_dbg(dev, "cache empty for order %d", order); + mr = NULL; + } + } + + if (!mr) + mr = reg_create(pd, virt_addr, length, umem, ncont, page_shift, + access_flags); + + if (IS_ERR(mr)) { + err = PTR_ERR(mr); + goto error; + } + + mlx5_ib_dbg(dev, "mkey 0x%x\n", mr->mmr.key); + + mr->umem = umem; + mr->npages = npages; + spin_lock(&dev->mr_lock); + dev->mdev.priv.reg_pages += npages; + spin_unlock(&dev->mr_lock); + mr->ibmr.lkey = mr->mmr.key; + mr->ibmr.rkey = mr->mmr.key; + + return &mr->ibmr; + +error: + ib_umem_release(umem); + return ERR_PTR(err); +} + +static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) +{ + struct umr_common *umrc = &dev->umrc; + struct ib_send_wr wr, *bad; + int err; + + memset(&wr, 0, sizeof(wr)); + wr.wr_id = (u64)(unsigned long)mr; + prep_umr_unreg_wqe(dev, &wr, mr->mmr.key); + + down(&umrc->sem); + init_completion(&mr->done); + err = ib_post_send(umrc->qp, &wr, &bad); + if (err) { + up(&umrc->sem); + mlx5_ib_dbg(dev, "err %d\n", err); + goto error; + } + wait_for_completion(&mr->done); + up(&umrc->sem); + if (mr->status != IB_WC_SUCCESS) { + mlx5_ib_warn(dev, "unreg umr failed\n"); + err = -EFAULT; + goto error; + } + return 0; + +error: + return err; +} + +int mlx5_ib_dereg_mr(struct ib_mr *ibmr) +{ + struct mlx5_ib_dev *dev = to_mdev(ibmr->device); + struct mlx5_ib_mr *mr = to_mmr(ibmr); + struct ib_umem *umem = mr->umem; + int npages = mr->npages; + int umred = mr->umred; + int err; + + if (!umred) { + err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr); + if (err) { + mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n", + mr->mmr.key, err); + return err; + } + } else { + err = unreg_umr(dev, mr); + if (err) { + mlx5_ib_warn(dev, "failed unregister\n"); + return err; + } + free_cached_mr(dev, mr); + } + + if (umem) { + ib_umem_release(umem); + spin_lock(&dev->mr_lock); + dev->mdev.priv.reg_pages -= npages; + spin_unlock(&dev->mr_lock); + } + + if (!umred) + kfree(mr); + + return 0; +} + +struct ib_mr *mlx5_ib_alloc_fast_reg_mr(struct ib_pd *pd, + int max_page_list_len) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_create_mkey_mbox_in *in; + struct mlx5_ib_mr *mr; + int err; + + mr = kzalloc(sizeof(*mr), GFP_KERNEL); + if (!mr) + return ERR_PTR(-ENOMEM); + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) { + err = -ENOMEM; + goto err_free; + } + + in->seg.status = 1 << 6; /* free */ + in->seg.xlt_oct_size = cpu_to_be32((max_page_list_len + 1) / 2); + in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); + in->seg.flags = MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT; + in->seg.flags_pd = cpu_to_be32(to_mpd(pd)->pdn); + /* + * TBD not needed - issue 197292 */ + in->seg.log2_page_size = PAGE_SHIFT; + + err = mlx5_core_create_mkey(&dev->mdev, &mr->mmr, in, sizeof(*in)); + kfree(in); + if (err) + goto err_free; + + mr->ibmr.lkey = mr->mmr.key; + mr->ibmr.rkey = mr->mmr.key; + mr->umem = NULL; + + return &mr->ibmr; + +err_free: + kfree(mr); + return ERR_PTR(err); +} + +struct ib_fast_reg_page_list *mlx5_ib_alloc_fast_reg_page_list(struct ib_device *ibdev, + int page_list_len) +{ + struct mlx5_ib_fast_reg_page_list *mfrpl; + int size = page_list_len * sizeof(u64); + + mfrpl = kmalloc(sizeof(*mfrpl), GFP_KERNEL); + if (!mfrpl) + return ERR_PTR(-ENOMEM); + + mfrpl->ibfrpl.page_list = kmalloc(size, GFP_KERNEL); + if (!mfrpl->ibfrpl.page_list) + goto err_free; + + mfrpl->mapped_page_list = dma_alloc_coherent(ibdev->dma_device, + size, &mfrpl->map, + GFP_KERNEL); + if (!mfrpl->mapped_page_list) + goto err_free; + + WARN_ON(mfrpl->map & 0x3f); + + return &mfrpl->ibfrpl; + +err_free: + kfree(mfrpl->ibfrpl.page_list); + kfree(mfrpl); + return ERR_PTR(-ENOMEM); +} + +void mlx5_ib_free_fast_reg_page_list(struct ib_fast_reg_page_list *page_list) +{ + struct mlx5_ib_fast_reg_page_list *mfrpl = to_mfrpl(page_list); + struct mlx5_ib_dev *dev = to_mdev(page_list->device); + int size = page_list->max_page_list_len * sizeof(u64); + + dma_free_coherent(&dev->mdev.pdev->dev, size, mfrpl->mapped_page_list, + mfrpl->map); + kfree(mfrpl->ibfrpl.page_list); + kfree(mfrpl); +} diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c new file mode 100644 index 000000000000..16ac54c9819f --- /dev/null +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -0,0 +1,2524 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "mlx5_ib.h" +#include "user.h" + +/* not supported currently */ +static int wq_signature; + +enum { + MLX5_IB_ACK_REQ_FREQ = 8, +}; + +enum { + MLX5_IB_DEFAULT_SCHED_QUEUE = 0x83, + MLX5_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f, + MLX5_IB_LINK_TYPE_IB = 0, + MLX5_IB_LINK_TYPE_ETH = 1 +}; + +enum { + MLX5_IB_SQ_STRIDE = 6, + MLX5_IB_CACHE_LINE_SIZE = 64, +}; + +static const u32 mlx5_ib_opcode[] = { + [IB_WR_SEND] = MLX5_OPCODE_SEND, + [IB_WR_SEND_WITH_IMM] = MLX5_OPCODE_SEND_IMM, + [IB_WR_RDMA_WRITE] = MLX5_OPCODE_RDMA_WRITE, + [IB_WR_RDMA_WRITE_WITH_IMM] = MLX5_OPCODE_RDMA_WRITE_IMM, + [IB_WR_RDMA_READ] = MLX5_OPCODE_RDMA_READ, + [IB_WR_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_CS, + [IB_WR_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_FA, + [IB_WR_SEND_WITH_INV] = MLX5_OPCODE_SEND_INVAL, + [IB_WR_LOCAL_INV] = MLX5_OPCODE_UMR, + [IB_WR_FAST_REG_MR] = MLX5_OPCODE_UMR, + [IB_WR_MASKED_ATOMIC_CMP_AND_SWP] = MLX5_OPCODE_ATOMIC_MASKED_CS, + [IB_WR_MASKED_ATOMIC_FETCH_AND_ADD] = MLX5_OPCODE_ATOMIC_MASKED_FA, + [MLX5_IB_WR_UMR] = MLX5_OPCODE_UMR, +}; + +struct umr_wr { + u64 virt_addr; + struct ib_pd *pd; + unsigned int page_shift; + unsigned int npages; + u32 length; + int access_flags; + u32 mkey; +}; + +static int is_qp0(enum ib_qp_type qp_type) +{ + return qp_type == IB_QPT_SMI; +} + +static int is_qp1(enum ib_qp_type qp_type) +{ + return qp_type == IB_QPT_GSI; +} + +static int is_sqp(enum ib_qp_type qp_type) +{ + return is_qp0(qp_type) || is_qp1(qp_type); +} + +static void *get_wqe(struct mlx5_ib_qp *qp, int offset) +{ + return mlx5_buf_offset(&qp->buf, offset); +} + +static void *get_recv_wqe(struct mlx5_ib_qp *qp, int n) +{ + return get_wqe(qp, qp->rq.offset + (n << qp->rq.wqe_shift)); +} + +void *mlx5_get_send_wqe(struct mlx5_ib_qp *qp, int n) +{ + return get_wqe(qp, qp->sq.offset + (n << MLX5_IB_SQ_STRIDE)); +} + +static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type) +{ + struct ib_qp *ibqp = &to_mibqp(qp)->ibqp; + struct ib_event event; + + if (type == MLX5_EVENT_TYPE_PATH_MIG) + to_mibqp(qp)->port = to_mibqp(qp)->alt_port; + + if (ibqp->event_handler) { + event.device = ibqp->device; + event.element.qp = ibqp; + switch (type) { + case MLX5_EVENT_TYPE_PATH_MIG: + event.event = IB_EVENT_PATH_MIG; + break; + case MLX5_EVENT_TYPE_COMM_EST: + event.event = IB_EVENT_COMM_EST; + break; + case MLX5_EVENT_TYPE_SQ_DRAINED: + event.event = IB_EVENT_SQ_DRAINED; + break; + case MLX5_EVENT_TYPE_SRQ_LAST_WQE: + event.event = IB_EVENT_QP_LAST_WQE_REACHED; + break; + case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: + event.event = IB_EVENT_QP_FATAL; + break; + case MLX5_EVENT_TYPE_PATH_MIG_FAILED: + event.event = IB_EVENT_PATH_MIG_ERR; + break; + case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: + event.event = IB_EVENT_QP_REQ_ERR; + break; + case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: + event.event = IB_EVENT_QP_ACCESS_ERR; + break; + default: + pr_warn("mlx5_ib: Unexpected event type %d on QP %06x\n", type, qp->qpn); + return; + } + + ibqp->event_handler(&event, ibqp->qp_context); + } +} + +static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap, + int has_rq, struct mlx5_ib_qp *qp, struct mlx5_ib_create_qp *ucmd) +{ + int wqe_size; + int wq_size; + + /* Sanity check RQ size before proceeding */ + if (cap->max_recv_wr > dev->mdev.caps.max_wqes) + return -EINVAL; + + if (!has_rq) { + qp->rq.max_gs = 0; + qp->rq.wqe_cnt = 0; + qp->rq.wqe_shift = 0; + } else { + if (ucmd) { + qp->rq.wqe_cnt = ucmd->rq_wqe_count; + qp->rq.wqe_shift = ucmd->rq_wqe_shift; + qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) - qp->wq_sig; + qp->rq.max_post = qp->rq.wqe_cnt; + } else { + wqe_size = qp->wq_sig ? sizeof(struct mlx5_wqe_signature_seg) : 0; + wqe_size += cap->max_recv_sge * sizeof(struct mlx5_wqe_data_seg); + wqe_size = roundup_pow_of_two(wqe_size); + wq_size = roundup_pow_of_two(cap->max_recv_wr) * wqe_size; + wq_size = max_t(int, wq_size, MLX5_SEND_WQE_BB); + qp->rq.wqe_cnt = wq_size / wqe_size; + if (wqe_size > dev->mdev.caps.max_rq_desc_sz) { + mlx5_ib_dbg(dev, "wqe_size %d, max %d\n", + wqe_size, + dev->mdev.caps.max_rq_desc_sz); + return -EINVAL; + } + qp->rq.wqe_shift = ilog2(wqe_size); + qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) - qp->wq_sig; + qp->rq.max_post = qp->rq.wqe_cnt; + } + } + + return 0; +} + +static int sq_overhead(enum ib_qp_type qp_type) +{ + int size; + + switch (qp_type) { + case IB_QPT_XRC_INI: + size = sizeof(struct mlx5_wqe_xrc_seg); + /* fall through */ + case IB_QPT_RC: + size += sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_atomic_seg) + + sizeof(struct mlx5_wqe_raddr_seg); + break; + + case IB_QPT_UC: + size = sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_raddr_seg); + break; + + case IB_QPT_UD: + case IB_QPT_SMI: + case IB_QPT_GSI: + size = sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_datagram_seg); + break; + + case MLX5_IB_QPT_REG_UMR: + size = sizeof(struct mlx5_wqe_ctrl_seg) + + sizeof(struct mlx5_wqe_umr_ctrl_seg) + + sizeof(struct mlx5_mkey_seg); + break; + + default: + return -EINVAL; + } + + return size; +} + +static int calc_send_wqe(struct ib_qp_init_attr *attr) +{ + int inl_size = 0; + int size; + + size = sq_overhead(attr->qp_type); + if (size < 0) + return size; + + if (attr->cap.max_inline_data) { + inl_size = size + sizeof(struct mlx5_wqe_inline_seg) + + attr->cap.max_inline_data; + } + + size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg); + + return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB); +} + +static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr, + struct mlx5_ib_qp *qp) +{ + int wqe_size; + int wq_size; + + if (!attr->cap.max_send_wr) + return 0; + + wqe_size = calc_send_wqe(attr); + mlx5_ib_dbg(dev, "wqe_size %d\n", wqe_size); + if (wqe_size < 0) + return wqe_size; + + if (wqe_size > dev->mdev.caps.max_sq_desc_sz) { + mlx5_ib_dbg(dev, "\n"); + return -EINVAL; + } + + qp->max_inline_data = wqe_size - sq_overhead(attr->qp_type) - + sizeof(struct mlx5_wqe_inline_seg); + attr->cap.max_inline_data = qp->max_inline_data; + + wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size); + qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; + qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB); + qp->sq.max_gs = attr->cap.max_send_sge; + qp->sq.max_post = 1 << ilog2(wq_size / wqe_size); + + return wq_size; +} + +static int set_user_buf_size(struct mlx5_ib_dev *dev, + struct mlx5_ib_qp *qp, + struct mlx5_ib_create_qp *ucmd) +{ + int desc_sz = 1 << qp->sq.wqe_shift; + + if (desc_sz > dev->mdev.caps.max_sq_desc_sz) { + mlx5_ib_warn(dev, "desc_sz %d, max_sq_desc_sz %d\n", + desc_sz, dev->mdev.caps.max_sq_desc_sz); + return -EINVAL; + } + + if (ucmd->sq_wqe_count && ((1 << ilog2(ucmd->sq_wqe_count)) != ucmd->sq_wqe_count)) { + mlx5_ib_warn(dev, "sq_wqe_count %d, sq_wqe_count %d\n", + ucmd->sq_wqe_count, ucmd->sq_wqe_count); + return -EINVAL; + } + + qp->sq.wqe_cnt = ucmd->sq_wqe_count; + + if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) { + mlx5_ib_warn(dev, "wqe_cnt %d, max_wqes %d\n", + qp->sq.wqe_cnt, dev->mdev.caps.max_wqes); + return -EINVAL; + } + + qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) + + (qp->sq.wqe_cnt << 6); + + return 0; +} + +static int qp_has_rq(struct ib_qp_init_attr *attr) +{ + if (attr->qp_type == IB_QPT_XRC_INI || + attr->qp_type == IB_QPT_XRC_TGT || attr->srq || + attr->qp_type == MLX5_IB_QPT_REG_UMR || + !attr->cap.max_recv_wr) + return 0; + + return 1; +} + +static int alloc_high_class_uuar(struct mlx5_uuar_info *uuari) +{ + int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE; + int start_uuar; + int i; + + start_uuar = nuuars - uuari->num_low_latency_uuars; + for (i = start_uuar; i < nuuars; i++) { + if (!test_bit(i, uuari->bitmap)) { + set_bit(i, uuari->bitmap); + uuari->count[i]++; + return i; + } + } + + return -ENOMEM; +} + +static int alloc_med_class_uuar(struct mlx5_uuar_info *uuari) +{ + int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE; + int minidx = 1; + int uuarn; + int end; + int i; + + end = nuuars - uuari->num_low_latency_uuars; + + for (i = 1; i < end; i++) { + uuarn = i & 3; + if (uuarn == 2 || uuarn == 3) + continue; + + if (uuari->count[i] < uuari->count[minidx]) + minidx = i; + } + + uuari->count[minidx]++; + return minidx; +} + +static int alloc_uuar(struct mlx5_uuar_info *uuari, + enum mlx5_ib_latency_class lat) +{ + int uuarn = -EINVAL; + + mutex_lock(&uuari->lock); + switch (lat) { + case MLX5_IB_LATENCY_CLASS_LOW: + uuarn = 0; + uuari->count[uuarn]++; + break; + + case MLX5_IB_LATENCY_CLASS_MEDIUM: + uuarn = alloc_med_class_uuar(uuari); + break; + + case MLX5_IB_LATENCY_CLASS_HIGH: + uuarn = alloc_high_class_uuar(uuari); + break; + + case MLX5_IB_LATENCY_CLASS_FAST_PATH: + uuarn = 2; + break; + } + mutex_unlock(&uuari->lock); + + return uuarn; +} + +static void free_med_class_uuar(struct mlx5_uuar_info *uuari, int uuarn) +{ + clear_bit(uuarn, uuari->bitmap); + --uuari->count[uuarn]; +} + +static void free_high_class_uuar(struct mlx5_uuar_info *uuari, int uuarn) +{ + clear_bit(uuarn, uuari->bitmap); + --uuari->count[uuarn]; +} + +static void free_uuar(struct mlx5_uuar_info *uuari, int uuarn) +{ + int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE; + int high_uuar = nuuars - uuari->num_low_latency_uuars; + + mutex_lock(&uuari->lock); + if (uuarn == 0) { + --uuari->count[uuarn]; + goto out; + } + + if (uuarn < high_uuar) { + free_med_class_uuar(uuari, uuarn); + goto out; + } + + free_high_class_uuar(uuari, uuarn); + +out: + mutex_unlock(&uuari->lock); +} + +static enum mlx5_qp_state to_mlx5_state(enum ib_qp_state state) +{ + switch (state) { + case IB_QPS_RESET: return MLX5_QP_STATE_RST; + case IB_QPS_INIT: return MLX5_QP_STATE_INIT; + case IB_QPS_RTR: return MLX5_QP_STATE_RTR; + case IB_QPS_RTS: return MLX5_QP_STATE_RTS; + case IB_QPS_SQD: return MLX5_QP_STATE_SQD; + case IB_QPS_SQE: return MLX5_QP_STATE_SQER; + case IB_QPS_ERR: return MLX5_QP_STATE_ERR; + default: return -1; + } +} + +static int to_mlx5_st(enum ib_qp_type type) +{ + switch (type) { + case IB_QPT_RC: return MLX5_QP_ST_RC; + case IB_QPT_UC: return MLX5_QP_ST_UC; + case IB_QPT_UD: return MLX5_QP_ST_UD; + case MLX5_IB_QPT_REG_UMR: return MLX5_QP_ST_REG_UMR; + case IB_QPT_XRC_INI: + case IB_QPT_XRC_TGT: return MLX5_QP_ST_XRC; + case IB_QPT_SMI: return MLX5_QP_ST_QP0; + case IB_QPT_GSI: return MLX5_QP_ST_QP1; + case IB_QPT_RAW_IPV6: return MLX5_QP_ST_RAW_IPV6; + case IB_QPT_RAW_ETHERTYPE: return MLX5_QP_ST_RAW_ETHERTYPE; + case IB_QPT_RAW_PACKET: + case IB_QPT_MAX: + default: return -EINVAL; + } +} + +static int uuarn_to_uar_index(struct mlx5_uuar_info *uuari, int uuarn) +{ + return uuari->uars[uuarn / MLX5_BF_REGS_PER_PAGE].index; +} + +static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, + struct mlx5_ib_qp *qp, struct ib_udata *udata, + struct mlx5_create_qp_mbox_in **in, + struct mlx5_ib_create_qp_resp *resp, int *inlen) +{ + struct mlx5_ib_ucontext *context; + struct mlx5_ib_create_qp ucmd; + int page_shift; + int uar_index; + int npages; + u32 offset; + int uuarn; + int ncont; + int err; + + err = ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)); + if (err) { + mlx5_ib_dbg(dev, "copy failed\n"); + return err; + } + + context = to_mucontext(pd->uobject->context); + /* + * TBD: should come from the verbs when we have the API + */ + uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_HIGH); + if (uuarn < 0) { + mlx5_ib_dbg(dev, "failed to allocate low latency UUAR\n"); + mlx5_ib_dbg(dev, "reverting to high latency\n"); + uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_LOW); + if (uuarn < 0) { + mlx5_ib_dbg(dev, "uuar allocation failed\n"); + return uuarn; + } + } + + uar_index = uuarn_to_uar_index(&context->uuari, uuarn); + mlx5_ib_dbg(dev, "uuarn 0x%x, uar_index 0x%x\n", uuarn, uar_index); + + err = set_user_buf_size(dev, qp, &ucmd); + if (err) + goto err_uuar; + + qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, + qp->buf_size, 0, 0); + if (IS_ERR(qp->umem)) { + mlx5_ib_dbg(dev, "umem_get failed\n"); + err = PTR_ERR(qp->umem); + goto err_uuar; + } + + mlx5_ib_cont_pages(qp->umem, ucmd.buf_addr, &npages, &page_shift, + &ncont, NULL); + err = mlx5_ib_get_buf_offset(ucmd.buf_addr, page_shift, &offset); + if (err) { + mlx5_ib_warn(dev, "bad offset\n"); + goto err_umem; + } + mlx5_ib_dbg(dev, "addr 0x%llx, size %d, npages %d, page_shift %d, ncont %d, offset %d\n", + ucmd.buf_addr, qp->buf_size, npages, page_shift, ncont, offset); + + *inlen = sizeof(**in) + sizeof(*(*in)->pas) * ncont; + *in = mlx5_vzalloc(*inlen); + if (!*in) { + err = -ENOMEM; + goto err_umem; + } + mlx5_ib_populate_pas(dev, qp->umem, page_shift, (*in)->pas, 0); + (*in)->ctx.log_pg_sz_remote_qpn = + cpu_to_be32((page_shift - PAGE_SHIFT) << 24); + (*in)->ctx.params2 = cpu_to_be32(offset << 6); + + (*in)->ctx.qp_counter_set_usr_page = cpu_to_be32(uar_index); + resp->uuar_index = uuarn; + qp->uuarn = uuarn; + + err = mlx5_ib_db_map_user(context, ucmd.db_addr, &qp->db); + if (err) { + mlx5_ib_dbg(dev, "map failed\n"); + goto err_free; + } + + err = ib_copy_to_udata(udata, resp, sizeof(*resp)); + if (err) { + mlx5_ib_dbg(dev, "copy failed\n"); + goto err_unmap; + } + qp->create_type = MLX5_QP_USER; + + return 0; + +err_unmap: + mlx5_ib_db_unmap_user(context, &qp->db); + +err_free: + mlx5_vfree(*in); + +err_umem: + ib_umem_release(qp->umem); + +err_uuar: + free_uuar(&context->uuari, uuarn); + return err; +} + +static void destroy_qp_user(struct ib_pd *pd, struct mlx5_ib_qp *qp) +{ + struct mlx5_ib_ucontext *context; + + context = to_mucontext(pd->uobject->context); + mlx5_ib_db_unmap_user(context, &qp->db); + ib_umem_release(qp->umem); + free_uuar(&context->uuari, qp->uuarn); +} + +static int create_kernel_qp(struct mlx5_ib_dev *dev, + struct ib_qp_init_attr *init_attr, + struct mlx5_ib_qp *qp, + struct mlx5_create_qp_mbox_in **in, int *inlen) +{ + enum mlx5_ib_latency_class lc = MLX5_IB_LATENCY_CLASS_LOW; + struct mlx5_uuar_info *uuari; + int uar_index; + int uuarn; + int err; + + uuari = &dev->mdev.priv.uuari; + if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) + qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK; + + if (init_attr->qp_type == MLX5_IB_QPT_REG_UMR) + lc = MLX5_IB_LATENCY_CLASS_FAST_PATH; + + uuarn = alloc_uuar(uuari, lc); + if (uuarn < 0) { + mlx5_ib_dbg(dev, "\n"); + return -ENOMEM; + } + + qp->bf = &uuari->bfs[uuarn]; + uar_index = qp->bf->uar->index; + + err = calc_sq_size(dev, init_attr, qp); + if (err < 0) { + mlx5_ib_dbg(dev, "err %d\n", err); + goto err_uuar; + } + + qp->rq.offset = 0; + qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift; + qp->buf_size = err + (qp->rq.wqe_cnt << qp->rq.wqe_shift); + + err = mlx5_buf_alloc(&dev->mdev, qp->buf_size, PAGE_SIZE * 2, &qp->buf); + if (err) { + mlx5_ib_dbg(dev, "err %d\n", err); + goto err_uuar; + } + + qp->sq.qend = mlx5_get_send_wqe(qp, qp->sq.wqe_cnt); + *inlen = sizeof(**in) + sizeof(*(*in)->pas) * qp->buf.npages; + *in = mlx5_vzalloc(*inlen); + if (!*in) { + err = -ENOMEM; + goto err_buf; + } + (*in)->ctx.qp_counter_set_usr_page = cpu_to_be32(uar_index); + (*in)->ctx.log_pg_sz_remote_qpn = cpu_to_be32((qp->buf.page_shift - PAGE_SHIFT) << 24); + /* Set "fast registration enabled" for all kernel QPs */ + (*in)->ctx.params1 |= cpu_to_be32(1 << 11); + (*in)->ctx.sq_crq_size |= cpu_to_be16(1 << 4); + + mlx5_fill_page_array(&qp->buf, (*in)->pas); + + err = mlx5_db_alloc(&dev->mdev, &qp->db); + if (err) { + mlx5_ib_dbg(dev, "err %d\n", err); + goto err_free; + } + + qp->db.db[0] = 0; + qp->db.db[1] = 0; + + qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wrid), GFP_KERNEL); + qp->sq.wr_data = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wr_data), GFP_KERNEL); + qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(*qp->rq.wrid), GFP_KERNEL); + qp->sq.w_list = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.w_list), GFP_KERNEL); + qp->sq.wqe_head = kmalloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wqe_head), GFP_KERNEL); + + if (!qp->sq.wrid || !qp->sq.wr_data || !qp->rq.wrid || + !qp->sq.w_list || !qp->sq.wqe_head) { + err = -ENOMEM; + goto err_wrid; + } + qp->create_type = MLX5_QP_KERNEL; + + return 0; + +err_wrid: + mlx5_db_free(&dev->mdev, &qp->db); + kfree(qp->sq.wqe_head); + kfree(qp->sq.w_list); + kfree(qp->sq.wrid); + kfree(qp->sq.wr_data); + kfree(qp->rq.wrid); + +err_free: + mlx5_vfree(*in); + +err_buf: + mlx5_buf_free(&dev->mdev, &qp->buf); + +err_uuar: + free_uuar(&dev->mdev.priv.uuari, uuarn); + return err; +} + +static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp) +{ + mlx5_db_free(&dev->mdev, &qp->db); + kfree(qp->sq.wqe_head); + kfree(qp->sq.w_list); + kfree(qp->sq.wrid); + kfree(qp->sq.wr_data); + kfree(qp->rq.wrid); + mlx5_buf_free(&dev->mdev, &qp->buf); + free_uuar(&dev->mdev.priv.uuari, qp->bf->uuarn); +} + +static __be32 get_rx_type(struct mlx5_ib_qp *qp, struct ib_qp_init_attr *attr) +{ + if (attr->srq || (attr->qp_type == IB_QPT_XRC_TGT) || + (attr->qp_type == IB_QPT_XRC_INI)) + return cpu_to_be32(MLX5_SRQ_RQ); + else if (!qp->has_rq) + return cpu_to_be32(MLX5_ZERO_LEN_RQ); + else + return cpu_to_be32(MLX5_NON_ZERO_RQ); +} + +static int is_connected(enum ib_qp_type qp_type) +{ + if (qp_type == IB_QPT_RC || qp_type == IB_QPT_UC) + return 1; + + return 0; +} + +static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata, struct mlx5_ib_qp *qp) +{ + struct mlx5_ib_resources *devr = &dev->devr; + struct mlx5_ib_create_qp_resp resp; + struct mlx5_create_qp_mbox_in *in; + struct mlx5_ib_create_qp ucmd; + int inlen = sizeof(*in); + int err; + + mutex_init(&qp->mutex); + spin_lock_init(&qp->sq.lock); + spin_lock_init(&qp->rq.lock); + + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) + qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; + + if (pd && pd->uobject) { + if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) { + mlx5_ib_dbg(dev, "copy failed\n"); + return -EFAULT; + } + + qp->wq_sig = !!(ucmd.flags & MLX5_QP_FLAG_SIGNATURE); + qp->scat_cqe = !!(ucmd.flags & MLX5_QP_FLAG_SCATTER_CQE); + } else { + qp->wq_sig = !!wq_signature; + } + + qp->has_rq = qp_has_rq(init_attr); + err = set_rq_size(dev, &init_attr->cap, qp->has_rq, + qp, (pd && pd->uobject) ? &ucmd : NULL); + if (err) { + mlx5_ib_dbg(dev, "err %d\n", err); + return err; + } + + if (pd) { + if (pd->uobject) { + mlx5_ib_dbg(dev, "requested sq_wqe_count (%d)\n", ucmd.sq_wqe_count); + if (ucmd.rq_wqe_shift != qp->rq.wqe_shift || + ucmd.rq_wqe_count != qp->rq.wqe_cnt) { + mlx5_ib_dbg(dev, "invalid rq params\n"); + return -EINVAL; + } + if (ucmd.sq_wqe_count > dev->mdev.caps.max_wqes) { + mlx5_ib_dbg(dev, "requested sq_wqe_count (%d) > max allowed (%d)\n", + ucmd.sq_wqe_count, dev->mdev.caps.max_wqes); + return -EINVAL; + } + err = create_user_qp(dev, pd, qp, udata, &in, &resp, &inlen); + if (err) + mlx5_ib_dbg(dev, "err %d\n", err); + } else { + err = create_kernel_qp(dev, init_attr, qp, &in, &inlen); + if (err) + mlx5_ib_dbg(dev, "err %d\n", err); + else + qp->pa_lkey = to_mpd(pd)->pa_lkey; + } + + if (err) + return err; + } else { + in = mlx5_vzalloc(sizeof(*in)); + if (!in) + return -ENOMEM; + + qp->create_type = MLX5_QP_EMPTY; + } + + if (is_sqp(init_attr->qp_type)) + qp->port = init_attr->port_num; + + in->ctx.flags = cpu_to_be32(to_mlx5_st(init_attr->qp_type) << 16 | + MLX5_QP_PM_MIGRATED << 11); + + if (init_attr->qp_type != MLX5_IB_QPT_REG_UMR) + in->ctx.flags_pd = cpu_to_be32(to_mpd(pd ? pd : devr->p0)->pdn); + else + in->ctx.flags_pd = cpu_to_be32(MLX5_QP_LAT_SENSITIVE); + + if (qp->wq_sig) + in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_ENABLE_SIG); + + if (qp->scat_cqe && is_connected(init_attr->qp_type)) { + int rcqe_sz; + int scqe_sz; + + rcqe_sz = mlx5_ib_get_cqe_size(dev, init_attr->recv_cq); + scqe_sz = mlx5_ib_get_cqe_size(dev, init_attr->send_cq); + + if (rcqe_sz == 128) + in->ctx.cs_res = MLX5_RES_SCAT_DATA64_CQE; + else + in->ctx.cs_res = MLX5_RES_SCAT_DATA32_CQE; + + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) { + if (scqe_sz == 128) + in->ctx.cs_req = MLX5_REQ_SCAT_DATA64_CQE; + else + in->ctx.cs_req = MLX5_REQ_SCAT_DATA32_CQE; + } + } + + if (qp->rq.wqe_cnt) { + in->ctx.rq_size_stride = (qp->rq.wqe_shift - 4); + in->ctx.rq_size_stride |= ilog2(qp->rq.wqe_cnt) << 3; + } + + in->ctx.rq_type_srqn = get_rx_type(qp, init_attr); + + if (qp->sq.wqe_cnt) + in->ctx.sq_crq_size |= cpu_to_be16(ilog2(qp->sq.wqe_cnt) << 11); + else + in->ctx.sq_crq_size |= cpu_to_be16(0x8000); + + /* Set default resources */ + switch (init_attr->qp_type) { + case IB_QPT_XRC_TGT: + in->ctx.cqn_recv = cpu_to_be32(to_mcq(devr->c0)->mcq.cqn); + in->ctx.cqn_send = cpu_to_be32(to_mcq(devr->c0)->mcq.cqn); + in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(devr->s0)->msrq.srqn); + in->ctx.xrcd = cpu_to_be32(to_mxrcd(init_attr->xrcd)->xrcdn); + break; + case IB_QPT_XRC_INI: + in->ctx.cqn_recv = cpu_to_be32(to_mcq(devr->c0)->mcq.cqn); + in->ctx.xrcd = cpu_to_be32(to_mxrcd(devr->x1)->xrcdn); + in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(devr->s0)->msrq.srqn); + break; + default: + if (init_attr->srq) { + in->ctx.xrcd = cpu_to_be32(to_mxrcd(devr->x0)->xrcdn); + in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(init_attr->srq)->msrq.srqn); + } else { + in->ctx.xrcd = cpu_to_be32(to_mxrcd(devr->x1)->xrcdn); + in->ctx.rq_type_srqn |= cpu_to_be32(to_msrq(devr->s0)->msrq.srqn); + } + } + + if (init_attr->send_cq) + in->ctx.cqn_send = cpu_to_be32(to_mcq(init_attr->send_cq)->mcq.cqn); + + if (init_attr->recv_cq) + in->ctx.cqn_recv = cpu_to_be32(to_mcq(init_attr->recv_cq)->mcq.cqn); + + in->ctx.db_rec_addr = cpu_to_be64(qp->db.dma); + + err = mlx5_core_create_qp(&dev->mdev, &qp->mqp, in, inlen); + if (err) { + mlx5_ib_dbg(dev, "create qp failed\n"); + goto err_create; + } + + mlx5_vfree(in); + /* Hardware wants QPN written in big-endian order (after + * shifting) for send doorbell. Precompute this value to save + * a little bit when posting sends. + */ + qp->doorbell_qpn = swab32(qp->mqp.qpn << 8); + + qp->mqp.event = mlx5_ib_qp_event; + + return 0; + +err_create: + if (qp->create_type == MLX5_QP_USER) + destroy_qp_user(pd, qp); + else if (qp->create_type == MLX5_QP_KERNEL) + destroy_qp_kernel(dev, qp); + + mlx5_vfree(in); + return err; +} + +static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv_cq) + __acquires(&send_cq->lock) __acquires(&recv_cq->lock) +{ + if (send_cq) { + if (recv_cq) { + if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { + spin_lock_irq(&send_cq->lock); + spin_lock_nested(&recv_cq->lock, + SINGLE_DEPTH_NESTING); + } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) { + spin_lock_irq(&send_cq->lock); + __acquire(&recv_cq->lock); + } else { + spin_lock_irq(&recv_cq->lock); + spin_lock_nested(&send_cq->lock, + SINGLE_DEPTH_NESTING); + } + } else { + spin_lock_irq(&send_cq->lock); + } + } else if (recv_cq) { + spin_lock_irq(&recv_cq->lock); + } +} + +static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv_cq) + __releases(&send_cq->lock) __releases(&recv_cq->lock) +{ + if (send_cq) { + if (recv_cq) { + if (send_cq->mcq.cqn < recv_cq->mcq.cqn) { + spin_unlock(&recv_cq->lock); + spin_unlock_irq(&send_cq->lock); + } else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) { + __release(&recv_cq->lock); + spin_unlock_irq(&send_cq->lock); + } else { + spin_unlock(&send_cq->lock); + spin_unlock_irq(&recv_cq->lock); + } + } else { + spin_unlock_irq(&send_cq->lock); + } + } else if (recv_cq) { + spin_unlock_irq(&recv_cq->lock); + } +} + +static struct mlx5_ib_pd *get_pd(struct mlx5_ib_qp *qp) +{ + return to_mpd(qp->ibqp.pd); +} + +static void get_cqs(struct mlx5_ib_qp *qp, + struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq) +{ + switch (qp->ibqp.qp_type) { + case IB_QPT_XRC_TGT: + *send_cq = NULL; + *recv_cq = NULL; + break; + case MLX5_IB_QPT_REG_UMR: + case IB_QPT_XRC_INI: + *send_cq = to_mcq(qp->ibqp.send_cq); + *recv_cq = NULL; + break; + + case IB_QPT_SMI: + case IB_QPT_GSI: + case IB_QPT_RC: + case IB_QPT_UC: + case IB_QPT_UD: + case IB_QPT_RAW_IPV6: + case IB_QPT_RAW_ETHERTYPE: + *send_cq = to_mcq(qp->ibqp.send_cq); + *recv_cq = to_mcq(qp->ibqp.recv_cq); + break; + + case IB_QPT_RAW_PACKET: + case IB_QPT_MAX: + default: + *send_cq = NULL; + *recv_cq = NULL; + break; + } +} + +static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp) +{ + struct mlx5_ib_cq *send_cq, *recv_cq; + struct mlx5_modify_qp_mbox_in *in; + int err; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return; + if (qp->state != IB_QPS_RESET) + if (mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(qp->state), + MLX5_QP_STATE_RST, in, sizeof(*in), &qp->mqp)) + mlx5_ib_warn(dev, "mlx5_ib: modify QP %06x to RESET failed\n", + qp->mqp.qpn); + + get_cqs(qp, &send_cq, &recv_cq); + + if (qp->create_type == MLX5_QP_KERNEL) { + mlx5_ib_lock_cqs(send_cq, recv_cq); + __mlx5_ib_cq_clean(recv_cq, qp->mqp.qpn, + qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); + if (send_cq != recv_cq) + __mlx5_ib_cq_clean(send_cq, qp->mqp.qpn, NULL); + mlx5_ib_unlock_cqs(send_cq, recv_cq); + } + + err = mlx5_core_destroy_qp(&dev->mdev, &qp->mqp); + if (err) + mlx5_ib_warn(dev, "failed to destroy QP 0x%x\n", qp->mqp.qpn); + kfree(in); + + + if (qp->create_type == MLX5_QP_KERNEL) + destroy_qp_kernel(dev, qp); + else if (qp->create_type == MLX5_QP_USER) + destroy_qp_user(&get_pd(qp)->ibpd, qp); +} + +static const char *ib_qp_type_str(enum ib_qp_type type) +{ + switch (type) { + case IB_QPT_SMI: + return "IB_QPT_SMI"; + case IB_QPT_GSI: + return "IB_QPT_GSI"; + case IB_QPT_RC: + return "IB_QPT_RC"; + case IB_QPT_UC: + return "IB_QPT_UC"; + case IB_QPT_UD: + return "IB_QPT_UD"; + case IB_QPT_RAW_IPV6: + return "IB_QPT_RAW_IPV6"; + case IB_QPT_RAW_ETHERTYPE: + return "IB_QPT_RAW_ETHERTYPE"; + case IB_QPT_XRC_INI: + return "IB_QPT_XRC_INI"; + case IB_QPT_XRC_TGT: + return "IB_QPT_XRC_TGT"; + case IB_QPT_RAW_PACKET: + return "IB_QPT_RAW_PACKET"; + case MLX5_IB_QPT_REG_UMR: + return "MLX5_IB_QPT_REG_UMR"; + case IB_QPT_MAX: + default: + return "Invalid QP type"; + } +} + +struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev; + struct mlx5_ib_qp *qp; + u16 xrcdn = 0; + int err; + + if (pd) { + dev = to_mdev(pd->device); + } else { + /* being cautious here */ + if (init_attr->qp_type != IB_QPT_XRC_TGT && + init_attr->qp_type != MLX5_IB_QPT_REG_UMR) { + pr_warn("%s: no PD for transport %s\n", __func__, + ib_qp_type_str(init_attr->qp_type)); + return ERR_PTR(-EINVAL); + } + dev = to_mdev(to_mxrcd(init_attr->xrcd)->ibxrcd.device); + } + + switch (init_attr->qp_type) { + case IB_QPT_XRC_TGT: + case IB_QPT_XRC_INI: + if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC)) { + mlx5_ib_dbg(dev, "XRC not supported\n"); + return ERR_PTR(-ENOSYS); + } + init_attr->recv_cq = NULL; + if (init_attr->qp_type == IB_QPT_XRC_TGT) { + xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn; + init_attr->send_cq = NULL; + } + + /* fall through */ + case IB_QPT_RC: + case IB_QPT_UC: + case IB_QPT_UD: + case IB_QPT_SMI: + case IB_QPT_GSI: + case MLX5_IB_QPT_REG_UMR: + qp = kzalloc(sizeof(*qp), GFP_KERNEL); + if (!qp) + return ERR_PTR(-ENOMEM); + + err = create_qp_common(dev, pd, init_attr, udata, qp); + if (err) { + mlx5_ib_dbg(dev, "create_qp_common failed\n"); + kfree(qp); + return ERR_PTR(err); + } + + if (is_qp0(init_attr->qp_type)) + qp->ibqp.qp_num = 0; + else if (is_qp1(init_attr->qp_type)) + qp->ibqp.qp_num = 1; + else + qp->ibqp.qp_num = qp->mqp.qpn; + + mlx5_ib_dbg(dev, "ib qpnum 0x%x, mlx qpn 0x%x, rcqn 0x%x, scqn 0x%x\n", + qp->ibqp.qp_num, qp->mqp.qpn, to_mcq(init_attr->recv_cq)->mcq.cqn, + to_mcq(init_attr->send_cq)->mcq.cqn); + + qp->xrcdn = xrcdn; + + break; + + case IB_QPT_RAW_IPV6: + case IB_QPT_RAW_ETHERTYPE: + case IB_QPT_RAW_PACKET: + case IB_QPT_MAX: + default: + mlx5_ib_dbg(dev, "unsupported qp type %d\n", + init_attr->qp_type); + /* Don't support raw QPs */ + return ERR_PTR(-EINVAL); + } + + return &qp->ibqp; +} + +int mlx5_ib_destroy_qp(struct ib_qp *qp) +{ + struct mlx5_ib_dev *dev = to_mdev(qp->device); + struct mlx5_ib_qp *mqp = to_mqp(qp); + + destroy_qp_common(dev, mqp); + + kfree(mqp); + + return 0; +} + +static __be32 to_mlx5_access_flags(struct mlx5_ib_qp *qp, const struct ib_qp_attr *attr, + int attr_mask) +{ + u32 hw_access_flags = 0; + u8 dest_rd_atomic; + u32 access_flags; + + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) + dest_rd_atomic = attr->max_dest_rd_atomic; + else + dest_rd_atomic = qp->resp_depth; + + if (attr_mask & IB_QP_ACCESS_FLAGS) + access_flags = attr->qp_access_flags; + else + access_flags = qp->atomic_rd_en; + + if (!dest_rd_atomic) + access_flags &= IB_ACCESS_REMOTE_WRITE; + + if (access_flags & IB_ACCESS_REMOTE_READ) + hw_access_flags |= MLX5_QP_BIT_RRE; + if (access_flags & IB_ACCESS_REMOTE_ATOMIC) + hw_access_flags |= (MLX5_QP_BIT_RAE | MLX5_ATOMIC_MODE_CX); + if (access_flags & IB_ACCESS_REMOTE_WRITE) + hw_access_flags |= MLX5_QP_BIT_RWE; + + return cpu_to_be32(hw_access_flags); +} + +enum { + MLX5_PATH_FLAG_FL = 1 << 0, + MLX5_PATH_FLAG_FREE_AR = 1 << 1, + MLX5_PATH_FLAG_COUNTER = 1 << 2, +}; + +static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate) +{ + if (rate == IB_RATE_PORT_CURRENT) { + return 0; + } else if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_300_GBPS) { + return -EINVAL; + } else { + while (rate != IB_RATE_2_5_GBPS && + !(1 << (rate + MLX5_STAT_RATE_OFFSET) & + dev->mdev.caps.stat_rate_support)) + --rate; + } + + return rate + MLX5_STAT_RATE_OFFSET; +} + +static int mlx5_set_path(struct mlx5_ib_dev *dev, const struct ib_ah_attr *ah, + struct mlx5_qp_path *path, u8 port, int attr_mask, + u32 path_flags, const struct ib_qp_attr *attr) +{ + int err; + + path->fl = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0; + path->free_ar = (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x80 : 0; + + if (attr_mask & IB_QP_PKEY_INDEX) + path->pkey_index = attr->pkey_index; + + path->grh_mlid = ah->src_path_bits & 0x7f; + path->rlid = cpu_to_be16(ah->dlid); + + if (ah->ah_flags & IB_AH_GRH) { + path->grh_mlid |= 1 << 7; + path->mgid_index = ah->grh.sgid_index; + path->hop_limit = ah->grh.hop_limit; + path->tclass_flowlabel = + cpu_to_be32((ah->grh.traffic_class << 20) | + (ah->grh.flow_label)); + memcpy(path->rgid, ah->grh.dgid.raw, 16); + } + + err = ib_rate_to_mlx5(dev, ah->static_rate); + if (err < 0) + return err; + path->static_rate = err; + path->port = port; + + if (ah->ah_flags & IB_AH_GRH) { + if (ah->grh.sgid_index >= dev->mdev.caps.port[port - 1].gid_table_len) { + pr_err(KERN_ERR "sgid_index (%u) too large. max is %d\n", + ah->grh.sgid_index, dev->mdev.caps.port[port - 1].gid_table_len); + return -EINVAL; + } + + path->grh_mlid |= 1 << 7; + path->mgid_index = ah->grh.sgid_index; + path->hop_limit = ah->grh.hop_limit; + path->tclass_flowlabel = + cpu_to_be32((ah->grh.traffic_class << 20) | + (ah->grh.flow_label)); + memcpy(path->rgid, ah->grh.dgid.raw, 16); + } + + if (attr_mask & IB_QP_TIMEOUT) + path->ackto_lt = attr->timeout << 3; + + path->sl = ah->sl & 0xf; + + return 0; +} + +static enum mlx5_qp_optpar opt_mask[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE][MLX5_QP_ST_MAX] = { + [MLX5_QP_STATE_INIT] = { + [MLX5_QP_STATE_INIT] = { + [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_PRI_PORT, + [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_PRI_PORT, + [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_Q_KEY | + MLX5_QP_OPTPAR_PRI_PORT, + }, + [MLX5_QP_STATE_RTR] = { + [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | + MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PKEY_INDEX, + [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PKEY_INDEX, + [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_Q_KEY, + [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_PKEY_INDEX | + MLX5_QP_OPTPAR_Q_KEY, + }, + }, + [MLX5_QP_STATE_RTR] = { + [MLX5_QP_STATE_RTS] = { + [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | + MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PM_STATE | + MLX5_QP_OPTPAR_RNR_TIMEOUT, + [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PM_STATE, + [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY, + }, + }, + [MLX5_QP_STATE_RTS] = { + [MLX5_QP_STATE_RTS] = { + [MLX5_QP_ST_RC] = MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE | + MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_RNR_TIMEOUT | + MLX5_QP_OPTPAR_PM_STATE, + [MLX5_QP_ST_UC] = MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_PM_STATE, + [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY | + MLX5_QP_OPTPAR_SRQN | + MLX5_QP_OPTPAR_CQN_RCV, + }, + }, + [MLX5_QP_STATE_SQER] = { + [MLX5_QP_STATE_RTS] = { + [MLX5_QP_ST_UD] = MLX5_QP_OPTPAR_Q_KEY, + [MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_Q_KEY, + }, + }, +}; + +static int ib_nr_to_mlx5_nr(int ib_mask) +{ + switch (ib_mask) { + case IB_QP_STATE: + return 0; + case IB_QP_CUR_STATE: + return 0; + case IB_QP_EN_SQD_ASYNC_NOTIFY: + return 0; + case IB_QP_ACCESS_FLAGS: + return MLX5_QP_OPTPAR_RWE | MLX5_QP_OPTPAR_RRE | + MLX5_QP_OPTPAR_RAE; + case IB_QP_PKEY_INDEX: + return MLX5_QP_OPTPAR_PKEY_INDEX; + case IB_QP_PORT: + return MLX5_QP_OPTPAR_PRI_PORT; + case IB_QP_QKEY: + return MLX5_QP_OPTPAR_Q_KEY; + case IB_QP_AV: + return MLX5_QP_OPTPAR_PRIMARY_ADDR_PATH | + MLX5_QP_OPTPAR_PRI_PORT; + case IB_QP_PATH_MTU: + return 0; + case IB_QP_TIMEOUT: + return MLX5_QP_OPTPAR_ACK_TIMEOUT; + case IB_QP_RETRY_CNT: + return MLX5_QP_OPTPAR_RETRY_COUNT; + case IB_QP_RNR_RETRY: + return MLX5_QP_OPTPAR_RNR_RETRY; + case IB_QP_RQ_PSN: + return 0; + case IB_QP_MAX_QP_RD_ATOMIC: + return MLX5_QP_OPTPAR_SRA_MAX; + case IB_QP_ALT_PATH: + return MLX5_QP_OPTPAR_ALT_ADDR_PATH; + case IB_QP_MIN_RNR_TIMER: + return MLX5_QP_OPTPAR_RNR_TIMEOUT; + case IB_QP_SQ_PSN: + return 0; + case IB_QP_MAX_DEST_RD_ATOMIC: + return MLX5_QP_OPTPAR_RRA_MAX | MLX5_QP_OPTPAR_RWE | + MLX5_QP_OPTPAR_RRE | MLX5_QP_OPTPAR_RAE; + case IB_QP_PATH_MIG_STATE: + return MLX5_QP_OPTPAR_PM_STATE; + case IB_QP_CAP: + return 0; + case IB_QP_DEST_QPN: + return 0; + } + return 0; +} + +static int ib_mask_to_mlx5_opt(int ib_mask) +{ + int result = 0; + int i; + + for (i = 0; i < 8 * sizeof(int); i++) { + if ((1 << i) & ib_mask) + result |= ib_nr_to_mlx5_nr(1 << i); + } + + return result; +} + +static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, + const struct ib_qp_attr *attr, int attr_mask, + enum ib_qp_state cur_state, enum ib_qp_state new_state) +{ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + struct mlx5_ib_qp *qp = to_mqp(ibqp); + struct mlx5_ib_cq *send_cq, *recv_cq; + struct mlx5_qp_context *context; + struct mlx5_modify_qp_mbox_in *in; + struct mlx5_ib_pd *pd; + enum mlx5_qp_state mlx5_cur, mlx5_new; + enum mlx5_qp_optpar optpar; + int sqd_event; + int mlx5_st; + int err; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return -ENOMEM; + + context = &in->ctx; + err = to_mlx5_st(ibqp->qp_type); + if (err < 0) + goto out; + + context->flags = cpu_to_be32(err << 16); + + if (!(attr_mask & IB_QP_PATH_MIG_STATE)) { + context->flags |= cpu_to_be32(MLX5_QP_PM_MIGRATED << 11); + } else { + switch (attr->path_mig_state) { + case IB_MIG_MIGRATED: + context->flags |= cpu_to_be32(MLX5_QP_PM_MIGRATED << 11); + break; + case IB_MIG_REARM: + context->flags |= cpu_to_be32(MLX5_QP_PM_REARM << 11); + break; + case IB_MIG_ARMED: + context->flags |= cpu_to_be32(MLX5_QP_PM_ARMED << 11); + break; + } + } + + if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) { + context->mtu_msgmax = (IB_MTU_256 << 5) | 8; + } else if (ibqp->qp_type == IB_QPT_UD || + ibqp->qp_type == MLX5_IB_QPT_REG_UMR) { + context->mtu_msgmax = (IB_MTU_4096 << 5) | 12; + } else if (attr_mask & IB_QP_PATH_MTU) { + if (attr->path_mtu < IB_MTU_256 || + attr->path_mtu > IB_MTU_4096) { + mlx5_ib_warn(dev, "invalid mtu %d\n", attr->path_mtu); + err = -EINVAL; + goto out; + } + context->mtu_msgmax = (attr->path_mtu << 5) | dev->mdev.caps.log_max_msg; + } + + if (attr_mask & IB_QP_DEST_QPN) + context->log_pg_sz_remote_qpn = cpu_to_be32(attr->dest_qp_num); + + if (attr_mask & IB_QP_PKEY_INDEX) + context->pri_path.pkey_index = attr->pkey_index; + + /* todo implement counter_index functionality */ + + if (is_sqp(ibqp->qp_type)) + context->pri_path.port = qp->port; + + if (attr_mask & IB_QP_PORT) + context->pri_path.port = attr->port_num; + + if (attr_mask & IB_QP_AV) { + err = mlx5_set_path(dev, &attr->ah_attr, &context->pri_path, + attr_mask & IB_QP_PORT ? attr->port_num : qp->port, + attr_mask, 0, attr); + if (err) + goto out; + } + + if (attr_mask & IB_QP_TIMEOUT) + context->pri_path.ackto_lt |= attr->timeout << 3; + + if (attr_mask & IB_QP_ALT_PATH) { + err = mlx5_set_path(dev, &attr->alt_ah_attr, &context->alt_path, + attr->alt_port_num, attr_mask, 0, attr); + if (err) + goto out; + } + + pd = get_pd(qp); + get_cqs(qp, &send_cq, &recv_cq); + + context->flags_pd = cpu_to_be32(pd ? pd->pdn : to_mpd(dev->devr.p0)->pdn); + context->cqn_send = send_cq ? cpu_to_be32(send_cq->mcq.cqn) : 0; + context->cqn_recv = recv_cq ? cpu_to_be32(recv_cq->mcq.cqn) : 0; + context->params1 = cpu_to_be32(MLX5_IB_ACK_REQ_FREQ << 28); + + if (attr_mask & IB_QP_RNR_RETRY) + context->params1 |= cpu_to_be32(attr->rnr_retry << 13); + + if (attr_mask & IB_QP_RETRY_CNT) + context->params1 |= cpu_to_be32(attr->retry_cnt << 16); + + if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { + if (attr->max_rd_atomic) + context->params1 |= + cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21); + } + + if (attr_mask & IB_QP_SQ_PSN) + context->next_send_psn = cpu_to_be32(attr->sq_psn); + + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { + if (attr->max_dest_rd_atomic) + context->params2 |= + cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21); + } + + if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) + context->params2 |= to_mlx5_access_flags(qp, attr, attr_mask); + + if (attr_mask & IB_QP_MIN_RNR_TIMER) + context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24); + + if (attr_mask & IB_QP_RQ_PSN) + context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn); + + if (attr_mask & IB_QP_QKEY) + context->qkey = cpu_to_be32(attr->qkey); + + if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) + context->db_rec_addr = cpu_to_be64(qp->db.dma); + + if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD && + attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify) + sqd_event = 1; + else + sqd_event = 0; + + if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) + context->sq_crq_size |= cpu_to_be16(1 << 4); + + + mlx5_cur = to_mlx5_state(cur_state); + mlx5_new = to_mlx5_state(new_state); + mlx5_st = to_mlx5_st(ibqp->qp_type); + if (mlx5_cur < 0 || mlx5_new < 0 || mlx5_st < 0) + goto out; + + optpar = ib_mask_to_mlx5_opt(attr_mask); + optpar &= opt_mask[mlx5_cur][mlx5_new][mlx5_st]; + in->optparam = cpu_to_be32(optpar); + err = mlx5_core_qp_modify(&dev->mdev, to_mlx5_state(cur_state), + to_mlx5_state(new_state), in, sqd_event, + &qp->mqp); + if (err) + goto out; + + qp->state = new_state; + + if (attr_mask & IB_QP_ACCESS_FLAGS) + qp->atomic_rd_en = attr->qp_access_flags; + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) + qp->resp_depth = attr->max_dest_rd_atomic; + if (attr_mask & IB_QP_PORT) + qp->port = attr->port_num; + if (attr_mask & IB_QP_ALT_PATH) + qp->alt_port = attr->alt_port_num; + + /* + * If we moved a kernel QP to RESET, clean up all old CQ + * entries and reinitialize the QP. + */ + if (new_state == IB_QPS_RESET && !ibqp->uobject) { + mlx5_ib_cq_clean(recv_cq, qp->mqp.qpn, + ibqp->srq ? to_msrq(ibqp->srq) : NULL); + if (send_cq != recv_cq) + mlx5_ib_cq_clean(send_cq, qp->mqp.qpn, NULL); + + qp->rq.head = 0; + qp->rq.tail = 0; + qp->sq.head = 0; + qp->sq.tail = 0; + qp->sq.cur_post = 0; + qp->sq.last_poll = 0; + qp->db.db[MLX5_RCV_DBR] = 0; + qp->db.db[MLX5_SND_DBR] = 0; + } + +out: + kfree(in); + return err; +} + +int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, + int attr_mask, struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + struct mlx5_ib_qp *qp = to_mqp(ibqp); + enum ib_qp_state cur_state, new_state; + int err = -EINVAL; + int port; + + mutex_lock(&qp->mutex); + + cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; + new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state; + + if (ibqp->qp_type != MLX5_IB_QPT_REG_UMR && + !ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask)) + goto out; + + if ((attr_mask & IB_QP_PORT) && + (attr->port_num == 0 || attr->port_num > dev->mdev.caps.num_ports)) + goto out; + + if (attr_mask & IB_QP_PKEY_INDEX) { + port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port; + if (attr->pkey_index >= dev->mdev.caps.port[port - 1].pkey_table_len) + goto out; + } + + if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && + attr->max_rd_atomic > dev->mdev.caps.max_ra_res_qp) + goto out; + + if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && + attr->max_dest_rd_atomic > dev->mdev.caps.max_ra_req_qp) + goto out; + + if (cur_state == new_state && cur_state == IB_QPS_RESET) { + err = 0; + goto out; + } + + err = __mlx5_ib_modify_qp(ibqp, attr, attr_mask, cur_state, new_state); + +out: + mutex_unlock(&qp->mutex); + return err; +} + +static int mlx5_wq_overflow(struct mlx5_ib_wq *wq, int nreq, struct ib_cq *ib_cq) +{ + struct mlx5_ib_cq *cq; + unsigned cur; + + cur = wq->head - wq->tail; + if (likely(cur + nreq < wq->max_post)) + return 0; + + cq = to_mcq(ib_cq); + spin_lock(&cq->lock); + cur = wq->head - wq->tail; + spin_unlock(&cq->lock); + + return cur + nreq >= wq->max_post; +} + +static __always_inline void set_raddr_seg(struct mlx5_wqe_raddr_seg *rseg, + u64 remote_addr, u32 rkey) +{ + rseg->raddr = cpu_to_be64(remote_addr); + rseg->rkey = cpu_to_be32(rkey); + rseg->reserved = 0; +} + +static void set_atomic_seg(struct mlx5_wqe_atomic_seg *aseg, struct ib_send_wr *wr) +{ + if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) { + aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap); + aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add); + } else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) { + aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add); + aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add_mask); + } else { + aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add); + aseg->compare = 0; + } +} + +static void set_masked_atomic_seg(struct mlx5_wqe_masked_atomic_seg *aseg, + struct ib_send_wr *wr) +{ + aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap); + aseg->swap_add_mask = cpu_to_be64(wr->wr.atomic.swap_mask); + aseg->compare = cpu_to_be64(wr->wr.atomic.compare_add); + aseg->compare_mask = cpu_to_be64(wr->wr.atomic.compare_add_mask); +} + +static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg, + struct ib_send_wr *wr) +{ + memcpy(&dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof(struct mlx5_av)); + dseg->av.dqp_dct = cpu_to_be32(wr->wr.ud.remote_qpn | MLX5_EXTENDED_UD_AV); + dseg->av.key.qkey.qkey = cpu_to_be32(wr->wr.ud.remote_qkey); +} + +static void set_data_ptr_seg(struct mlx5_wqe_data_seg *dseg, struct ib_sge *sg) +{ + dseg->byte_count = cpu_to_be32(sg->length); + dseg->lkey = cpu_to_be32(sg->lkey); + dseg->addr = cpu_to_be64(sg->addr); +} + +static __be16 get_klm_octo(int npages) +{ + return cpu_to_be16(ALIGN(npages, 8) / 2); +} + +static __be64 frwr_mkey_mask(void) +{ + u64 result; + + result = MLX5_MKEY_MASK_LEN | + MLX5_MKEY_MASK_PAGE_SIZE | + MLX5_MKEY_MASK_START_ADDR | + MLX5_MKEY_MASK_EN_RINVAL | + MLX5_MKEY_MASK_KEY | + MLX5_MKEY_MASK_LR | + MLX5_MKEY_MASK_LW | + MLX5_MKEY_MASK_RR | + MLX5_MKEY_MASK_RW | + MLX5_MKEY_MASK_A | + MLX5_MKEY_MASK_SMALL_FENCE | + MLX5_MKEY_MASK_FREE; + + return cpu_to_be64(result); +} + +static void set_frwr_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, + struct ib_send_wr *wr, int li) +{ + memset(umr, 0, sizeof(*umr)); + + if (li) { + umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE); + umr->flags = 1 << 7; + return; + } + + umr->flags = (1 << 5); /* fail if not free */ + umr->klm_octowords = get_klm_octo(wr->wr.fast_reg.page_list_len); + umr->mkey_mask = frwr_mkey_mask(); +} + +static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr, + struct ib_send_wr *wr) +{ + struct umr_wr *umrwr = (struct umr_wr *)&wr->wr.fast_reg; + u64 mask; + + memset(umr, 0, sizeof(*umr)); + + if (!(wr->send_flags & MLX5_IB_SEND_UMR_UNREG)) { + umr->flags = 1 << 5; /* fail if not free */ + umr->klm_octowords = get_klm_octo(umrwr->npages); + mask = MLX5_MKEY_MASK_LEN | + MLX5_MKEY_MASK_PAGE_SIZE | + MLX5_MKEY_MASK_START_ADDR | + MLX5_MKEY_MASK_PD | + MLX5_MKEY_MASK_LR | + MLX5_MKEY_MASK_LW | + MLX5_MKEY_MASK_RR | + MLX5_MKEY_MASK_RW | + MLX5_MKEY_MASK_A | + MLX5_MKEY_MASK_FREE; + umr->mkey_mask = cpu_to_be64(mask); + } else { + umr->flags = 2 << 5; /* fail if free */ + mask = MLX5_MKEY_MASK_FREE; + umr->mkey_mask = cpu_to_be64(mask); + } + + if (!wr->num_sge) + umr->flags |= (1 << 7); /* inline */ +} + +static u8 get_umr_flags(int acc) +{ + return (acc & IB_ACCESS_REMOTE_ATOMIC ? MLX5_PERM_ATOMIC : 0) | + (acc & IB_ACCESS_REMOTE_WRITE ? MLX5_PERM_REMOTE_WRITE : 0) | + (acc & IB_ACCESS_REMOTE_READ ? MLX5_PERM_REMOTE_READ : 0) | + (acc & IB_ACCESS_LOCAL_WRITE ? MLX5_PERM_LOCAL_WRITE : 0) | + MLX5_PERM_LOCAL_READ | MLX5_PERM_UMR_EN | MLX5_ACCESS_MODE_MTT; +} + +static void set_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr, + int li, int *writ) +{ + memset(seg, 0, sizeof(*seg)); + if (li) { + seg->status = 1 << 6; + return; + } + + seg->flags = get_umr_flags(wr->wr.fast_reg.access_flags); + *writ = seg->flags & (MLX5_PERM_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE); + seg->qpn_mkey7_0 = cpu_to_be32((wr->wr.fast_reg.rkey & 0xff) | 0xffffff00); + seg->flags_pd = cpu_to_be32(MLX5_MKEY_REMOTE_INVAL); + seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start); + seg->len = cpu_to_be64(wr->wr.fast_reg.length); + seg->xlt_oct_size = cpu_to_be32((wr->wr.fast_reg.page_list_len + 1) / 2); + seg->log2_page_size = wr->wr.fast_reg.page_shift; +} + +static void set_reg_mkey_segment(struct mlx5_mkey_seg *seg, struct ib_send_wr *wr) +{ + memset(seg, 0, sizeof(*seg)); + if (wr->send_flags & MLX5_IB_SEND_UMR_UNREG) { + seg->status = 1 << 6; + return; + } + + seg->flags = convert_access(wr->wr.fast_reg.access_flags); + seg->flags_pd = cpu_to_be32(to_mpd((struct ib_pd *)wr->wr.fast_reg.page_list)->pdn); + seg->start_addr = cpu_to_be64(wr->wr.fast_reg.iova_start); + seg->len = cpu_to_be64(wr->wr.fast_reg.length); + seg->log2_page_size = wr->wr.fast_reg.page_shift; + seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8); +} + +static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg, + struct ib_send_wr *wr, + struct mlx5_core_dev *mdev, + struct mlx5_ib_pd *pd, + int writ) +{ + struct mlx5_ib_fast_reg_page_list *mfrpl = to_mfrpl(wr->wr.fast_reg.page_list); + u64 *page_list = wr->wr.fast_reg.page_list->page_list; + u64 perm = MLX5_EN_RD | (writ ? MLX5_EN_WR : 0); + int i; + + for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) + mfrpl->mapped_page_list[i] = cpu_to_be64(page_list[i] | perm); + dseg->addr = cpu_to_be64(mfrpl->map); + dseg->byte_count = cpu_to_be32(ALIGN(sizeof(u64) * wr->wr.fast_reg.page_list_len, 64)); + dseg->lkey = cpu_to_be32(pd->pa_lkey); +} + +static __be32 send_ieth(struct ib_send_wr *wr) +{ + switch (wr->opcode) { + case IB_WR_SEND_WITH_IMM: + case IB_WR_RDMA_WRITE_WITH_IMM: + return wr->ex.imm_data; + + case IB_WR_SEND_WITH_INV: + return cpu_to_be32(wr->ex.invalidate_rkey); + + default: + return 0; + } +} + +static u8 calc_sig(void *wqe, int size) +{ + u8 *p = wqe; + u8 res = 0; + int i; + + for (i = 0; i < size; i++) + res ^= p[i]; + + return ~res; +} + +static u8 wq_sig(void *wqe) +{ + return calc_sig(wqe, (*((u8 *)wqe + 8) & 0x3f) << 4); +} + +static int set_data_inl_seg(struct mlx5_ib_qp *qp, struct ib_send_wr *wr, + void *wqe, int *sz) +{ + struct mlx5_wqe_inline_seg *seg; + void *qend = qp->sq.qend; + void *addr; + int inl = 0; + int copy; + int len; + int i; + + seg = wqe; + wqe += sizeof(*seg); + for (i = 0; i < wr->num_sge; i++) { + addr = (void *)(unsigned long)(wr->sg_list[i].addr); + len = wr->sg_list[i].length; + inl += len; + + if (unlikely(inl > qp->max_inline_data)) + return -ENOMEM; + + if (unlikely(wqe + len > qend)) { + copy = qend - wqe; + memcpy(wqe, addr, copy); + addr += copy; + len -= copy; + wqe = mlx5_get_send_wqe(qp, 0); + } + memcpy(wqe, addr, len); + wqe += len; + } + + seg->byte_count = cpu_to_be32(inl | MLX5_INLINE_SEG); + + *sz = ALIGN(inl + sizeof(seg->byte_count), 16) / 16; + + return 0; +} + +static int set_frwr_li_wr(void **seg, struct ib_send_wr *wr, int *size, + struct mlx5_core_dev *mdev, struct mlx5_ib_pd *pd, struct mlx5_ib_qp *qp) +{ + int writ = 0; + int li; + + li = wr->opcode == IB_WR_LOCAL_INV ? 1 : 0; + if (unlikely(wr->send_flags & IB_SEND_INLINE)) + return -EINVAL; + + set_frwr_umr_segment(*seg, wr, li); + *seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); + *size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; + if (unlikely((*seg == qp->sq.qend))) + *seg = mlx5_get_send_wqe(qp, 0); + set_mkey_segment(*seg, wr, li, &writ); + *seg += sizeof(struct mlx5_mkey_seg); + *size += sizeof(struct mlx5_mkey_seg) / 16; + if (unlikely((*seg == qp->sq.qend))) + *seg = mlx5_get_send_wqe(qp, 0); + if (!li) { + set_frwr_pages(*seg, wr, mdev, pd, writ); + *seg += sizeof(struct mlx5_wqe_data_seg); + *size += (sizeof(struct mlx5_wqe_data_seg) / 16); + } + return 0; +} + +static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16) +{ + __be32 *p = NULL; + int tidx = idx; + int i, j; + + pr_debug("dump wqe at %p\n", mlx5_get_send_wqe(qp, tidx)); + for (i = 0, j = 0; i < size_16 * 4; i += 4, j += 4) { + if ((i & 0xf) == 0) { + void *buf = mlx5_get_send_wqe(qp, tidx); + tidx = (tidx + 1) & (qp->sq.wqe_cnt - 1); + p = buf; + j = 0; + } + pr_debug("%08x %08x %08x %08x\n", be32_to_cpu(p[j]), + be32_to_cpu(p[j + 1]), be32_to_cpu(p[j + 2]), + be32_to_cpu(p[j + 3])); + } +} + +static void mlx5_bf_copy(u64 __iomem *dst, u64 *src, + unsigned bytecnt, struct mlx5_ib_qp *qp) +{ + while (bytecnt > 0) { + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + __iowrite64_copy(dst++, src++, 8); + bytecnt -= 64; + if (unlikely(src == qp->sq.qend)) + src = mlx5_get_send_wqe(qp, 0); + } +} + +static u8 get_fence(u8 fence, struct ib_send_wr *wr) +{ + if (unlikely(wr->opcode == IB_WR_LOCAL_INV && + wr->send_flags & IB_SEND_FENCE)) + return MLX5_FENCE_MODE_STRONG_ORDERING; + + if (unlikely(fence)) { + if (wr->send_flags & IB_SEND_FENCE) + return MLX5_FENCE_MODE_SMALL_AND_FENCE; + else + return fence; + + } else { + return 0; + } +} + +int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, + struct ib_send_wr **bad_wr) +{ + struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + struct mlx5_core_dev *mdev = &dev->mdev; + struct mlx5_ib_qp *qp = to_mqp(ibqp); + struct mlx5_wqe_data_seg *dpseg; + struct mlx5_wqe_xrc_seg *xrc; + struct mlx5_bf *bf = qp->bf; + int uninitialized_var(size); + void *qend = qp->sq.qend; + unsigned long flags; + u32 mlx5_opcode; + unsigned idx; + int err = 0; + int inl = 0; + int num_sge; + void *seg; + int nreq; + int i; + u8 next_fence = 0; + u8 opmod = 0; + u8 fence; + + spin_lock_irqsave(&qp->sq.lock, flags); + + for (nreq = 0; wr; nreq++, wr = wr->next) { + if (unlikely(wr->opcode >= sizeof(mlx5_ib_opcode) / sizeof(mlx5_ib_opcode[0]))) { + mlx5_ib_warn(dev, "\n"); + err = -EINVAL; + *bad_wr = wr; + goto out; + } + + if (unlikely(mlx5_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq))) { + mlx5_ib_warn(dev, "\n"); + err = -ENOMEM; + *bad_wr = wr; + goto out; + } + + fence = qp->fm_cache; + num_sge = wr->num_sge; + if (unlikely(num_sge > qp->sq.max_gs)) { + mlx5_ib_warn(dev, "\n"); + err = -ENOMEM; + *bad_wr = wr; + goto out; + } + + idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1); + seg = mlx5_get_send_wqe(qp, idx); + ctrl = seg; + *(uint32_t *)(seg + 8) = 0; + ctrl->imm = send_ieth(wr); + ctrl->fm_ce_se = qp->sq_signal_bits | + (wr->send_flags & IB_SEND_SIGNALED ? + MLX5_WQE_CTRL_CQ_UPDATE : 0) | + (wr->send_flags & IB_SEND_SOLICITED ? + MLX5_WQE_CTRL_SOLICITED : 0); + + seg += sizeof(*ctrl); + size = sizeof(*ctrl) / 16; + + switch (ibqp->qp_type) { + case IB_QPT_XRC_INI: + xrc = seg; + xrc->xrc_srqn = htonl(wr->xrc_remote_srq_num); + seg += sizeof(*xrc); + size += sizeof(*xrc) / 16; + /* fall through */ + case IB_QPT_RC: + switch (wr->opcode) { + case IB_WR_RDMA_READ: + case IB_WR_RDMA_WRITE: + case IB_WR_RDMA_WRITE_WITH_IMM: + set_raddr_seg(seg, wr->wr.rdma.remote_addr, + wr->wr.rdma.rkey); + seg += sizeof(struct mlx5_wqe_raddr_seg); + size += sizeof(struct mlx5_wqe_raddr_seg) / 16; + break; + + case IB_WR_ATOMIC_CMP_AND_SWP: + case IB_WR_ATOMIC_FETCH_AND_ADD: + set_raddr_seg(seg, wr->wr.atomic.remote_addr, + wr->wr.atomic.rkey); + seg += sizeof(struct mlx5_wqe_raddr_seg); + + set_atomic_seg(seg, wr); + seg += sizeof(struct mlx5_wqe_atomic_seg); + + size += (sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_atomic_seg)) / 16; + break; + + case IB_WR_MASKED_ATOMIC_CMP_AND_SWP: + set_raddr_seg(seg, wr->wr.atomic.remote_addr, + wr->wr.atomic.rkey); + seg += sizeof(struct mlx5_wqe_raddr_seg); + + set_masked_atomic_seg(seg, wr); + seg += sizeof(struct mlx5_wqe_masked_atomic_seg); + + size += (sizeof(struct mlx5_wqe_raddr_seg) + + sizeof(struct mlx5_wqe_masked_atomic_seg)) / 16; + break; + + case IB_WR_LOCAL_INV: + next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; + qp->sq.wr_data[idx] = IB_WR_LOCAL_INV; + ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey); + err = set_frwr_li_wr(&seg, wr, &size, mdev, to_mpd(ibqp->pd), qp); + if (err) { + mlx5_ib_warn(dev, "\n"); + *bad_wr = wr; + goto out; + } + num_sge = 0; + break; + + case IB_WR_FAST_REG_MR: + next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; + qp->sq.wr_data[idx] = IB_WR_FAST_REG_MR; + ctrl->imm = cpu_to_be32(wr->wr.fast_reg.rkey); + err = set_frwr_li_wr(&seg, wr, &size, mdev, to_mpd(ibqp->pd), qp); + if (err) { + mlx5_ib_warn(dev, "\n"); + *bad_wr = wr; + goto out; + } + num_sge = 0; + break; + + default: + break; + } + break; + + case IB_QPT_UC: + switch (wr->opcode) { + case IB_WR_RDMA_WRITE: + case IB_WR_RDMA_WRITE_WITH_IMM: + set_raddr_seg(seg, wr->wr.rdma.remote_addr, + wr->wr.rdma.rkey); + seg += sizeof(struct mlx5_wqe_raddr_seg); + size += sizeof(struct mlx5_wqe_raddr_seg) / 16; + break; + + default: + break; + } + break; + + case IB_QPT_UD: + case IB_QPT_SMI: + case IB_QPT_GSI: + set_datagram_seg(seg, wr); + seg += sizeof(struct mlx5_wqe_datagram_seg); + size += sizeof(struct mlx5_wqe_datagram_seg) / 16; + if (unlikely((seg == qend))) + seg = mlx5_get_send_wqe(qp, 0); + break; + + case MLX5_IB_QPT_REG_UMR: + if (wr->opcode != MLX5_IB_WR_UMR) { + err = -EINVAL; + mlx5_ib_warn(dev, "bad opcode\n"); + goto out; + } + qp->sq.wr_data[idx] = MLX5_IB_WR_UMR; + ctrl->imm = cpu_to_be32(wr->wr.fast_reg.rkey); + set_reg_umr_segment(seg, wr); + seg += sizeof(struct mlx5_wqe_umr_ctrl_seg); + size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16; + if (unlikely((seg == qend))) + seg = mlx5_get_send_wqe(qp, 0); + set_reg_mkey_segment(seg, wr); + seg += sizeof(struct mlx5_mkey_seg); + size += sizeof(struct mlx5_mkey_seg) / 16; + if (unlikely((seg == qend))) + seg = mlx5_get_send_wqe(qp, 0); + break; + + default: + break; + } + + if (wr->send_flags & IB_SEND_INLINE && num_sge) { + int uninitialized_var(sz); + + err = set_data_inl_seg(qp, wr, seg, &sz); + if (unlikely(err)) { + mlx5_ib_warn(dev, "\n"); + *bad_wr = wr; + goto out; + } + inl = 1; + size += sz; + } else { + dpseg = seg; + for (i = 0; i < num_sge; i++) { + if (unlikely(dpseg == qend)) { + seg = mlx5_get_send_wqe(qp, 0); + dpseg = seg; + } + if (likely(wr->sg_list[i].length)) { + set_data_ptr_seg(dpseg, wr->sg_list + i); + size += sizeof(struct mlx5_wqe_data_seg) / 16; + dpseg++; + } + } + } + + mlx5_opcode = mlx5_ib_opcode[wr->opcode]; + ctrl->opmod_idx_opcode = cpu_to_be32(((u32)(qp->sq.cur_post) << 8) | + mlx5_opcode | + ((u32)opmod << 24)); + ctrl->qpn_ds = cpu_to_be32(size | (qp->mqp.qpn << 8)); + ctrl->fm_ce_se |= get_fence(fence, wr); + qp->fm_cache = next_fence; + if (unlikely(qp->wq_sig)) + ctrl->signature = wq_sig(ctrl); + + qp->sq.wrid[idx] = wr->wr_id; + qp->sq.w_list[idx].opcode = mlx5_opcode; + qp->sq.wqe_head[idx] = qp->sq.head + nreq; + qp->sq.cur_post += DIV_ROUND_UP(size * 16, MLX5_SEND_WQE_BB); + qp->sq.w_list[idx].next = qp->sq.cur_post; + + if (0) + dump_wqe(qp, idx, size); + } + +out: + if (likely(nreq)) { + qp->sq.head += nreq; + + /* Make sure that descriptors are written before + * updating doorbell record and ringing the doorbell + */ + wmb(); + + qp->db.db[MLX5_SND_DBR] = cpu_to_be32(qp->sq.cur_post); + + if (bf->need_lock) + spin_lock(&bf->lock); + + /* TBD enable WC */ + if (0 && nreq == 1 && bf->uuarn && inl && size > 1 && size <= bf->buf_size / 16) { + mlx5_bf_copy(bf->reg + bf->offset, (u64 *)ctrl, ALIGN(size * 16, 64), qp); + /* wc_wmb(); */ + } else { + mlx5_write64((__be32 *)ctrl, bf->regreg + bf->offset, + MLX5_GET_DOORBELL_LOCK(&bf->lock32)); + /* Make sure doorbells don't leak out of SQ spinlock + * and reach the HCA out of order. + */ + mmiowb(); + } + bf->offset ^= bf->buf_size; + if (bf->need_lock) + spin_unlock(&bf->lock); + } + + spin_unlock_irqrestore(&qp->sq.lock, flags); + + return err; +} + +static void set_sig_seg(struct mlx5_rwqe_sig *sig, int size) +{ + sig->signature = calc_sig(sig, size); +} + +int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, + struct ib_recv_wr **bad_wr) +{ + struct mlx5_ib_qp *qp = to_mqp(ibqp); + struct mlx5_wqe_data_seg *scat; + struct mlx5_rwqe_sig *sig; + unsigned long flags; + int err = 0; + int nreq; + int ind; + int i; + + spin_lock_irqsave(&qp->rq.lock, flags); + + ind = qp->rq.head & (qp->rq.wqe_cnt - 1); + + for (nreq = 0; wr; nreq++, wr = wr->next) { + if (mlx5_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { + err = -ENOMEM; + *bad_wr = wr; + goto out; + } + + if (unlikely(wr->num_sge > qp->rq.max_gs)) { + err = -EINVAL; + *bad_wr = wr; + goto out; + } + + scat = get_recv_wqe(qp, ind); + if (qp->wq_sig) + scat++; + + for (i = 0; i < wr->num_sge; i++) + set_data_ptr_seg(scat + i, wr->sg_list + i); + + if (i < qp->rq.max_gs) { + scat[i].byte_count = 0; + scat[i].lkey = cpu_to_be32(MLX5_INVALID_LKEY); + scat[i].addr = 0; + } + + if (qp->wq_sig) { + sig = (struct mlx5_rwqe_sig *)scat; + set_sig_seg(sig, (qp->rq.max_gs + 1) << 2); + } + + qp->rq.wrid[ind] = wr->wr_id; + + ind = (ind + 1) & (qp->rq.wqe_cnt - 1); + } + +out: + if (likely(nreq)) { + qp->rq.head += nreq; + + /* Make sure that descriptors are written before + * doorbell record. + */ + wmb(); + + *qp->db.db = cpu_to_be32(qp->rq.head & 0xffff); + } + + spin_unlock_irqrestore(&qp->rq.lock, flags); + + return err; +} + +static inline enum ib_qp_state to_ib_qp_state(enum mlx5_qp_state mlx5_state) +{ + switch (mlx5_state) { + case MLX5_QP_STATE_RST: return IB_QPS_RESET; + case MLX5_QP_STATE_INIT: return IB_QPS_INIT; + case MLX5_QP_STATE_RTR: return IB_QPS_RTR; + case MLX5_QP_STATE_RTS: return IB_QPS_RTS; + case MLX5_QP_STATE_SQ_DRAINING: + case MLX5_QP_STATE_SQD: return IB_QPS_SQD; + case MLX5_QP_STATE_SQER: return IB_QPS_SQE; + case MLX5_QP_STATE_ERR: return IB_QPS_ERR; + default: return -1; + } +} + +static inline enum ib_mig_state to_ib_mig_state(int mlx5_mig_state) +{ + switch (mlx5_mig_state) { + case MLX5_QP_PM_ARMED: return IB_MIG_ARMED; + case MLX5_QP_PM_REARM: return IB_MIG_REARM; + case MLX5_QP_PM_MIGRATED: return IB_MIG_MIGRATED; + default: return -1; + } +} + +static int to_ib_qp_access_flags(int mlx5_flags) +{ + int ib_flags = 0; + + if (mlx5_flags & MLX5_QP_BIT_RRE) + ib_flags |= IB_ACCESS_REMOTE_READ; + if (mlx5_flags & MLX5_QP_BIT_RWE) + ib_flags |= IB_ACCESS_REMOTE_WRITE; + if (mlx5_flags & MLX5_QP_BIT_RAE) + ib_flags |= IB_ACCESS_REMOTE_ATOMIC; + + return ib_flags; +} + +static void to_ib_ah_attr(struct mlx5_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr, + struct mlx5_qp_path *path) +{ + struct mlx5_core_dev *dev = &ibdev->mdev; + + memset(ib_ah_attr, 0, sizeof(*ib_ah_attr)); + ib_ah_attr->port_num = path->port; + + if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports) + return; + + ib_ah_attr->sl = path->sl & 0xf; + + ib_ah_attr->dlid = be16_to_cpu(path->rlid); + ib_ah_attr->src_path_bits = path->grh_mlid & 0x7f; + ib_ah_attr->static_rate = path->static_rate ? path->static_rate - 5 : 0; + ib_ah_attr->ah_flags = (path->grh_mlid & (1 << 7)) ? IB_AH_GRH : 0; + if (ib_ah_attr->ah_flags) { + ib_ah_attr->grh.sgid_index = path->mgid_index; + ib_ah_attr->grh.hop_limit = path->hop_limit; + ib_ah_attr->grh.traffic_class = + (be32_to_cpu(path->tclass_flowlabel) >> 20) & 0xff; + ib_ah_attr->grh.flow_label = + be32_to_cpu(path->tclass_flowlabel) & 0xfffff; + memcpy(ib_ah_attr->grh.dgid.raw, + path->rgid, sizeof(ib_ah_attr->grh.dgid.raw)); + } +} + +int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, + struct ib_qp_init_attr *qp_init_attr) +{ + struct mlx5_ib_dev *dev = to_mdev(ibqp->device); + struct mlx5_ib_qp *qp = to_mqp(ibqp); + struct mlx5_query_qp_mbox_out *outb; + struct mlx5_qp_context *context; + int mlx5_state; + int err = 0; + + mutex_lock(&qp->mutex); + outb = kzalloc(sizeof(*outb), GFP_KERNEL); + if (!outb) { + err = -ENOMEM; + goto out; + } + context = &outb->ctx; + err = mlx5_core_qp_query(&dev->mdev, &qp->mqp, outb, sizeof(*outb)); + if (err) + goto out_free; + + mlx5_state = be32_to_cpu(context->flags) >> 28; + + qp->state = to_ib_qp_state(mlx5_state); + qp_attr->qp_state = qp->state; + qp_attr->path_mtu = context->mtu_msgmax >> 5; + qp_attr->path_mig_state = + to_ib_mig_state((be32_to_cpu(context->flags) >> 11) & 0x3); + qp_attr->qkey = be32_to_cpu(context->qkey); + qp_attr->rq_psn = be32_to_cpu(context->rnr_nextrecvpsn) & 0xffffff; + qp_attr->sq_psn = be32_to_cpu(context->next_send_psn) & 0xffffff; + qp_attr->dest_qp_num = be32_to_cpu(context->log_pg_sz_remote_qpn) & 0xffffff; + qp_attr->qp_access_flags = + to_ib_qp_access_flags(be32_to_cpu(context->params2)); + + if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) { + to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path); + to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path); + qp_attr->alt_pkey_index = context->alt_path.pkey_index & 0x7f; + qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; + } + + qp_attr->pkey_index = context->pri_path.pkey_index & 0x7f; + qp_attr->port_num = context->pri_path.port; + + /* qp_attr->en_sqd_async_notify is only applicable in modify qp */ + qp_attr->sq_draining = mlx5_state == MLX5_QP_STATE_SQ_DRAINING; + + qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context->params1) >> 21) & 0x7); + + qp_attr->max_dest_rd_atomic = + 1 << ((be32_to_cpu(context->params2) >> 21) & 0x7); + qp_attr->min_rnr_timer = + (be32_to_cpu(context->rnr_nextrecvpsn) >> 24) & 0x1f; + qp_attr->timeout = context->pri_path.ackto_lt >> 3; + qp_attr->retry_cnt = (be32_to_cpu(context->params1) >> 16) & 0x7; + qp_attr->rnr_retry = (be32_to_cpu(context->params1) >> 13) & 0x7; + qp_attr->alt_timeout = context->alt_path.ackto_lt >> 3; + qp_attr->cur_qp_state = qp_attr->qp_state; + qp_attr->cap.max_recv_wr = qp->rq.wqe_cnt; + qp_attr->cap.max_recv_sge = qp->rq.max_gs; + + if (!ibqp->uobject) { + qp_attr->cap.max_send_wr = qp->sq.wqe_cnt; + qp_attr->cap.max_send_sge = qp->sq.max_gs; + } else { + qp_attr->cap.max_send_wr = 0; + qp_attr->cap.max_send_sge = 0; + } + + /* We don't support inline sends for kernel QPs (yet), and we + * don't know what userspace's value should be. + */ + qp_attr->cap.max_inline_data = 0; + + qp_init_attr->cap = qp_attr->cap; + + qp_init_attr->create_flags = 0; + if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK) + qp_init_attr->create_flags |= IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK; + + qp_init_attr->sq_sig_type = qp->sq_signal_bits & MLX5_WQE_CTRL_CQ_UPDATE ? + IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; + +out_free: + kfree(outb); + +out: + mutex_unlock(&qp->mutex); + return err; +} + +struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev, + struct ib_ucontext *context, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(ibdev); + struct mlx5_ib_xrcd *xrcd; + int err; + + if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_XRC)) + return ERR_PTR(-ENOSYS); + + xrcd = kmalloc(sizeof(*xrcd), GFP_KERNEL); + if (!xrcd) + return ERR_PTR(-ENOMEM); + + err = mlx5_core_xrcd_alloc(&dev->mdev, &xrcd->xrcdn); + if (err) { + kfree(xrcd); + return ERR_PTR(-ENOMEM); + } + + return &xrcd->ibxrcd; +} + +int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd) +{ + struct mlx5_ib_dev *dev = to_mdev(xrcd->device); + u32 xrcdn = to_mxrcd(xrcd)->xrcdn; + int err; + + err = mlx5_core_xrcd_dealloc(&dev->mdev, xrcdn); + if (err) { + mlx5_ib_warn(dev, "failed to dealloc xrcdn 0x%x\n", xrcdn); + return err; + } + + kfree(xrcd); + + return 0; +} diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c new file mode 100644 index 000000000000..84d297afd6a9 --- /dev/null +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "mlx5_ib.h" +#include "user.h" + +/* not supported currently */ +static int srq_signature; + +static void *get_wqe(struct mlx5_ib_srq *srq, int n) +{ + return mlx5_buf_offset(&srq->buf, n << srq->msrq.wqe_shift); +} + +static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type) +{ + struct ib_event event; + struct ib_srq *ibsrq = &to_mibsrq(srq)->ibsrq; + + if (ibsrq->event_handler) { + event.device = ibsrq->device; + event.element.srq = ibsrq; + switch (type) { + case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: + event.event = IB_EVENT_SRQ_LIMIT_REACHED; + break; + case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: + event.event = IB_EVENT_SRQ_ERR; + break; + default: + pr_warn("mlx5_ib: Unexpected event type %d on SRQ %06x\n", + type, srq->srqn); + return; + } + + ibsrq->event_handler(&event, ibsrq->srq_context); + } +} + +static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, + struct mlx5_create_srq_mbox_in **in, + struct ib_udata *udata, int buf_size, int *inlen) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_ib_create_srq ucmd; + int err; + int npages; + int page_shift; + int ncont; + u32 offset; + + if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) { + mlx5_ib_dbg(dev, "failed copy udata\n"); + return -EFAULT; + } + srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); + + srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, buf_size, + 0, 0); + if (IS_ERR(srq->umem)) { + mlx5_ib_dbg(dev, "failed umem get, size %d\n", buf_size); + err = PTR_ERR(srq->umem); + return err; + } + + mlx5_ib_cont_pages(srq->umem, ucmd.buf_addr, &npages, + &page_shift, &ncont, NULL); + err = mlx5_ib_get_buf_offset(ucmd.buf_addr, page_shift, + &offset); + if (err) { + mlx5_ib_warn(dev, "bad offset\n"); + goto err_umem; + } + + *inlen = sizeof(**in) + sizeof(*(*in)->pas) * ncont; + *in = mlx5_vzalloc(*inlen); + if (!(*in)) { + err = -ENOMEM; + goto err_umem; + } + + mlx5_ib_populate_pas(dev, srq->umem, page_shift, (*in)->pas, 0); + + err = mlx5_ib_db_map_user(to_mucontext(pd->uobject->context), + ucmd.db_addr, &srq->db); + if (err) { + mlx5_ib_dbg(dev, "map doorbell failed\n"); + goto err_in; + } + + (*in)->ctx.log_pg_sz = page_shift - PAGE_SHIFT; + (*in)->ctx.pgoff_cqn = cpu_to_be32(offset << 26); + + return 0; + +err_in: + mlx5_vfree(*in); + +err_umem: + ib_umem_release(srq->umem); + + return err; +} + +static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq, + struct mlx5_create_srq_mbox_in **in, int buf_size, + int *inlen) +{ + int err; + int i; + struct mlx5_wqe_srq_next_seg *next; + int page_shift; + int npages; + + err = mlx5_db_alloc(&dev->mdev, &srq->db); + if (err) { + mlx5_ib_warn(dev, "alloc dbell rec failed\n"); + return err; + } + + *srq->db.db = 0; + + if (mlx5_buf_alloc(&dev->mdev, buf_size, PAGE_SIZE * 2, &srq->buf)) { + mlx5_ib_dbg(dev, "buf alloc failed\n"); + err = -ENOMEM; + goto err_db; + } + page_shift = srq->buf.page_shift; + + srq->head = 0; + srq->tail = srq->msrq.max - 1; + srq->wqe_ctr = 0; + + for (i = 0; i < srq->msrq.max; i++) { + next = get_wqe(srq, i); + next->next_wqe_index = + cpu_to_be16((i + 1) & (srq->msrq.max - 1)); + } + + npages = DIV_ROUND_UP(srq->buf.npages, 1 << (page_shift - PAGE_SHIFT)); + mlx5_ib_dbg(dev, "buf_size %d, page_shift %d, npages %d, calc npages %d\n", + buf_size, page_shift, srq->buf.npages, npages); + *inlen = sizeof(**in) + sizeof(*(*in)->pas) * npages; + *in = mlx5_vzalloc(*inlen); + if (!*in) { + err = -ENOMEM; + goto err_buf; + } + mlx5_fill_page_array(&srq->buf, (*in)->pas); + + srq->wrid = kmalloc(srq->msrq.max * sizeof(u64), GFP_KERNEL); + if (!srq->wrid) { + mlx5_ib_dbg(dev, "kmalloc failed %lu\n", + (unsigned long)(srq->msrq.max * sizeof(u64))); + err = -ENOMEM; + goto err_in; + } + srq->wq_sig = !!srq_signature; + + (*in)->ctx.log_pg_sz = page_shift - PAGE_SHIFT; + + return 0; + +err_in: + mlx5_vfree(*in); + +err_buf: + mlx5_buf_free(&dev->mdev, &srq->buf); + +err_db: + mlx5_db_free(&dev->mdev, &srq->db); + return err; +} + +static void destroy_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq) +{ + mlx5_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db); + ib_umem_release(srq->umem); +} + + +static void destroy_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq) +{ + kfree(srq->wrid); + mlx5_buf_free(&dev->mdev, &srq->buf); + mlx5_db_free(&dev->mdev, &srq->db); +} + +struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, + struct ib_srq_init_attr *init_attr, + struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(pd->device); + struct mlx5_ib_srq *srq; + int desc_size; + int buf_size; + int err; + struct mlx5_create_srq_mbox_in *uninitialized_var(in); + int uninitialized_var(inlen); + int is_xrc; + u32 flgs, xrcdn; + + /* Sanity check SRQ size before proceeding */ + if (init_attr->attr.max_wr >= dev->mdev.caps.max_srq_wqes) { + mlx5_ib_dbg(dev, "max_wr %d, cap %d\n", + init_attr->attr.max_wr, + dev->mdev.caps.max_srq_wqes); + return ERR_PTR(-EINVAL); + } + + srq = kmalloc(sizeof(*srq), GFP_KERNEL); + if (!srq) + return ERR_PTR(-ENOMEM); + + mutex_init(&srq->mutex); + spin_lock_init(&srq->lock); + srq->msrq.max = roundup_pow_of_two(init_attr->attr.max_wr + 1); + srq->msrq.max_gs = init_attr->attr.max_sge; + + desc_size = sizeof(struct mlx5_wqe_srq_next_seg) + + srq->msrq.max_gs * sizeof(struct mlx5_wqe_data_seg); + desc_size = roundup_pow_of_two(desc_size); + desc_size = max_t(int, 32, desc_size); + srq->msrq.max_avail_gather = (desc_size - sizeof(struct mlx5_wqe_srq_next_seg)) / + sizeof(struct mlx5_wqe_data_seg); + srq->msrq.wqe_shift = ilog2(desc_size); + buf_size = srq->msrq.max * desc_size; + mlx5_ib_dbg(dev, "desc_size 0x%x, req wr 0x%x, srq size 0x%x, max_gs 0x%x, max_avail_gather 0x%x\n", + desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs, + srq->msrq.max_avail_gather); + + if (pd->uobject) + err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen); + else + err = create_srq_kernel(dev, srq, &in, buf_size, &inlen); + + if (err) { + mlx5_ib_warn(dev, "create srq %s failed, err %d\n", + pd->uobject ? "user" : "kernel", err); + goto err_srq; + } + + is_xrc = (init_attr->srq_type == IB_SRQT_XRC); + in->ctx.state_log_sz = ilog2(srq->msrq.max); + flgs = ((srq->msrq.wqe_shift - 4) | (is_xrc << 5) | (srq->wq_sig << 7)) << 24; + xrcdn = 0; + if (is_xrc) { + xrcdn = to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn; + in->ctx.pgoff_cqn |= cpu_to_be32(to_mcq(init_attr->ext.xrc.cq)->mcq.cqn); + } else if (init_attr->srq_type == IB_SRQT_BASIC) { + xrcdn = to_mxrcd(dev->devr.x0)->xrcdn; + in->ctx.pgoff_cqn |= cpu_to_be32(to_mcq(dev->devr.c0)->mcq.cqn); + } + + in->ctx.flags_xrcd = cpu_to_be32((flgs & 0xFF000000) | (xrcdn & 0xFFFFFF)); + + in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn); + in->ctx.db_record = cpu_to_be64(srq->db.dma); + err = mlx5_core_create_srq(&dev->mdev, &srq->msrq, in, inlen); + mlx5_vfree(in); + if (err) { + mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err); + goto err_srq; + } + + mlx5_ib_dbg(dev, "create SRQ with srqn 0x%x\n", srq->msrq.srqn); + + srq->msrq.event = mlx5_ib_srq_event; + srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn; + + if (pd->uobject) + if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof(__u32))) { + mlx5_ib_dbg(dev, "copy to user failed\n"); + err = -EFAULT; + goto err_core; + } + + init_attr->attr.max_wr = srq->msrq.max - 1; + + return &srq->ibsrq; + +err_core: + mlx5_core_destroy_srq(&dev->mdev, &srq->msrq); + if (pd->uobject) + destroy_srq_user(pd, srq); + else + destroy_srq_kernel(dev, srq); + +err_srq: + kfree(srq); + + return ERR_PTR(err); +} + +int mlx5_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, + enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) +{ + struct mlx5_ib_dev *dev = to_mdev(ibsrq->device); + struct mlx5_ib_srq *srq = to_msrq(ibsrq); + int ret; + + /* We don't support resizing SRQs yet */ + if (attr_mask & IB_SRQ_MAX_WR) + return -EINVAL; + + if (attr_mask & IB_SRQ_LIMIT) { + if (attr->srq_limit >= srq->msrq.max) + return -EINVAL; + + mutex_lock(&srq->mutex); + ret = mlx5_core_arm_srq(&dev->mdev, &srq->msrq, attr->srq_limit, 1); + mutex_unlock(&srq->mutex); + + if (ret) + return ret; + } + + return 0; +} + +int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr) +{ + struct mlx5_ib_dev *dev = to_mdev(ibsrq->device); + struct mlx5_ib_srq *srq = to_msrq(ibsrq); + int ret; + struct mlx5_query_srq_mbox_out *out; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return -ENOMEM; + + ret = mlx5_core_query_srq(&dev->mdev, &srq->msrq, out); + if (ret) + goto out_box; + + srq_attr->srq_limit = be16_to_cpu(out->ctx.lwm); + srq_attr->max_wr = srq->msrq.max - 1; + srq_attr->max_sge = srq->msrq.max_gs; + +out_box: + kfree(out); + return ret; +} + +int mlx5_ib_destroy_srq(struct ib_srq *srq) +{ + struct mlx5_ib_dev *dev = to_mdev(srq->device); + struct mlx5_ib_srq *msrq = to_msrq(srq); + + mlx5_core_destroy_srq(&dev->mdev, &msrq->msrq); + + if (srq->uobject) { + mlx5_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db); + ib_umem_release(msrq->umem); + } else { + kfree(msrq->wrid); + mlx5_buf_free(&dev->mdev, &msrq->buf); + mlx5_db_free(&dev->mdev, &msrq->db); + } + + kfree(srq); + return 0; +} + +void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index) +{ + struct mlx5_wqe_srq_next_seg *next; + + /* always called with interrupts disabled. */ + spin_lock(&srq->lock); + + next = get_wqe(srq, srq->tail); + next->next_wqe_index = cpu_to_be16(wqe_index); + srq->tail = wqe_index; + + spin_unlock(&srq->lock); +} + +int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, + struct ib_recv_wr **bad_wr) +{ + struct mlx5_ib_srq *srq = to_msrq(ibsrq); + struct mlx5_wqe_srq_next_seg *next; + struct mlx5_wqe_data_seg *scat; + unsigned long flags; + int err = 0; + int nreq; + int i; + + spin_lock_irqsave(&srq->lock, flags); + + for (nreq = 0; wr; nreq++, wr = wr->next) { + if (unlikely(wr->num_sge > srq->msrq.max_gs)) { + err = -EINVAL; + *bad_wr = wr; + break; + } + + if (unlikely(srq->head == srq->tail)) { + err = -ENOMEM; + *bad_wr = wr; + break; + } + + srq->wrid[srq->head] = wr->wr_id; + + next = get_wqe(srq, srq->head); + srq->head = be16_to_cpu(next->next_wqe_index); + scat = (struct mlx5_wqe_data_seg *)(next + 1); + + for (i = 0; i < wr->num_sge; i++) { + scat[i].byte_count = cpu_to_be32(wr->sg_list[i].length); + scat[i].lkey = cpu_to_be32(wr->sg_list[i].lkey); + scat[i].addr = cpu_to_be64(wr->sg_list[i].addr); + } + + if (i < srq->msrq.max_avail_gather) { + scat[i].byte_count = 0; + scat[i].lkey = cpu_to_be32(MLX5_INVALID_LKEY); + scat[i].addr = 0; + } + } + + if (likely(nreq)) { + srq->wqe_ctr += nreq; + + /* Make sure that descriptors are written before + * doorbell record. + */ + wmb(); + + *srq->db.db = cpu_to_be32(srq->wqe_ctr); + } + + spin_unlock_irqrestore(&srq->lock, flags); + + return err; +} diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h new file mode 100644 index 000000000000..a886de3e593c --- /dev/null +++ b/drivers/infiniband/hw/mlx5/user.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_IB_USER_H +#define MLX5_IB_USER_H + +#include + +enum { + MLX5_QP_FLAG_SIGNATURE = 1 << 0, + MLX5_QP_FLAG_SCATTER_CQE = 1 << 1, +}; + +enum { + MLX5_SRQ_FLAG_SIGNATURE = 1 << 0, +}; + + +/* Increment this value if any changes that break userspace ABI + * compatibility are made. + */ +#define MLX5_IB_UVERBS_ABI_VERSION 1 + +/* Make sure that all structs defined in this file remain laid out so + * that they pack the same way on 32-bit and 64-bit architectures (to + * avoid incompatibility between 32-bit userspace and 64-bit kernels). + * In particular do not use pointer types -- pass pointers in __u64 + * instead. + */ + +struct mlx5_ib_alloc_ucontext_req { + __u32 total_num_uuars; + __u32 num_low_latency_uuars; +}; + +struct mlx5_ib_alloc_ucontext_resp { + __u32 qp_tab_size; + __u32 bf_reg_size; + __u32 tot_uuars; + __u32 cache_line_size; + __u16 max_sq_desc_sz; + __u16 max_rq_desc_sz; + __u32 max_send_wqebb; + __u32 max_recv_wr; + __u32 max_srq_recv_wr; + __u16 num_ports; + __u16 reserved; +}; + +struct mlx5_ib_alloc_pd_resp { + __u32 pdn; +}; + +struct mlx5_ib_create_cq { + __u64 buf_addr; + __u64 db_addr; + __u32 cqe_size; +}; + +struct mlx5_ib_create_cq_resp { + __u32 cqn; + __u32 reserved; +}; + +struct mlx5_ib_resize_cq { + __u64 buf_addr; +}; + +struct mlx5_ib_create_srq { + __u64 buf_addr; + __u64 db_addr; + __u32 flags; +}; + +struct mlx5_ib_create_srq_resp { + __u32 srqn; + __u32 reserved; +}; + +struct mlx5_ib_create_qp { + __u64 buf_addr; + __u64 db_addr; + __u32 sq_wqe_count; + __u32 rq_wqe_count; + __u32 rq_wqe_shift; + __u32 flags; +}; + +struct mlx5_ib_create_qp_resp { + __u32 uuar_index; +}; +#endif /* MLX5_IB_USER_H */ diff --git a/drivers/net/ethernet/mellanox/Kconfig b/drivers/net/ethernet/mellanox/Kconfig index bcdbc14aeff0..8cf7563a8d92 100644 --- a/drivers/net/ethernet/mellanox/Kconfig +++ b/drivers/net/ethernet/mellanox/Kconfig @@ -19,5 +19,6 @@ config NET_VENDOR_MELLANOX if NET_VENDOR_MELLANOX source "drivers/net/ethernet/mellanox/mlx4/Kconfig" +source "drivers/net/ethernet/mellanox/mlx5/core/Kconfig" endif # NET_VENDOR_MELLANOX diff --git a/drivers/net/ethernet/mellanox/Makefile b/drivers/net/ethernet/mellanox/Makefile index 37afb9683372..38fe32ef5e5f 100644 --- a/drivers/net/ethernet/mellanox/Makefile +++ b/drivers/net/ethernet/mellanox/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_MLX4_CORE) += mlx4/ +obj-$(CONFIG_MLX5_CORE) += mlx5/core/ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig new file mode 100644 index 000000000000..21962828925a --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -0,0 +1,18 @@ +# +# Mellanox driver configuration +# + +config MLX5_CORE + tristate + depends on PCI && X86 + default n + +config MLX5_DEBUG + bool "Verbose debugging output" if (MLX5_CORE && EXPERT) + depends on MLX5_CORE + default y + ---help--- + This option causes debugging code to be compiled into the + mlx5_core driver. The output can be turned on via the + debug_mask module parameter (which can also be set after + the driver is loaded through sysfs). diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile new file mode 100644 index 000000000000..105780bb980b --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_MLX5_CORE) += mlx5_core.o + +mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ + health.o mcg.o cq.o srq.o alloc.o qp.o port.o mr.o pd.o \ + mad.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c new file mode 100644 index 000000000000..b215742b842f --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mlx5_core.h" + +/* Handling for queue buffers -- we allocate a bunch of memory and + * register it in a memory region at HCA virtual address 0. If the + * requested size is > max_direct, we split the allocation into + * multiple pages, so we don't require too much contiguous memory. + */ + +int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, int max_direct, + struct mlx5_buf *buf) +{ + dma_addr_t t; + + buf->size = size; + if (size <= max_direct) { + buf->nbufs = 1; + buf->npages = 1; + buf->page_shift = get_order(size) + PAGE_SHIFT; + buf->direct.buf = dma_zalloc_coherent(&dev->pdev->dev, + size, &t, GFP_KERNEL); + if (!buf->direct.buf) + return -ENOMEM; + + buf->direct.map = t; + + while (t & ((1 << buf->page_shift) - 1)) { + --buf->page_shift; + buf->npages *= 2; + } + } else { + int i; + + buf->direct.buf = NULL; + buf->nbufs = (size + PAGE_SIZE - 1) / PAGE_SIZE; + buf->npages = buf->nbufs; + buf->page_shift = PAGE_SHIFT; + buf->page_list = kcalloc(buf->nbufs, sizeof(*buf->page_list), + GFP_KERNEL); + if (!buf->page_list) + return -ENOMEM; + + for (i = 0; i < buf->nbufs; i++) { + buf->page_list[i].buf = + dma_zalloc_coherent(&dev->pdev->dev, PAGE_SIZE, + &t, GFP_KERNEL); + if (!buf->page_list[i].buf) + goto err_free; + + buf->page_list[i].map = t; + } + + if (BITS_PER_LONG == 64) { + struct page **pages; + pages = kmalloc(sizeof(*pages) * buf->nbufs, GFP_KERNEL); + if (!pages) + goto err_free; + for (i = 0; i < buf->nbufs; i++) + pages[i] = virt_to_page(buf->page_list[i].buf); + buf->direct.buf = vmap(pages, buf->nbufs, VM_MAP, PAGE_KERNEL); + kfree(pages); + if (!buf->direct.buf) + goto err_free; + } + } + + return 0; + +err_free: + mlx5_buf_free(dev, buf); + + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(mlx5_buf_alloc); + +void mlx5_buf_free(struct mlx5_core_dev *dev, struct mlx5_buf *buf) +{ + int i; + + if (buf->nbufs == 1) + dma_free_coherent(&dev->pdev->dev, buf->size, buf->direct.buf, + buf->direct.map); + else { + if (BITS_PER_LONG == 64 && buf->direct.buf) + vunmap(buf->direct.buf); + + for (i = 0; i < buf->nbufs; i++) + if (buf->page_list[i].buf) + dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, + buf->page_list[i].buf, + buf->page_list[i].map); + kfree(buf->page_list); + } +} +EXPORT_SYMBOL_GPL(mlx5_buf_free); + +static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct device *dma_device) +{ + struct mlx5_db_pgdir *pgdir; + + pgdir = kzalloc(sizeof(*pgdir), GFP_KERNEL); + if (!pgdir) + return NULL; + + bitmap_fill(pgdir->bitmap, MLX5_DB_PER_PAGE); + pgdir->db_page = dma_alloc_coherent(dma_device, PAGE_SIZE, + &pgdir->db_dma, GFP_KERNEL); + if (!pgdir->db_page) { + kfree(pgdir); + return NULL; + } + + return pgdir; +} + +static int mlx5_alloc_db_from_pgdir(struct mlx5_db_pgdir *pgdir, + struct mlx5_db *db) +{ + int offset; + int i; + + i = find_first_bit(pgdir->bitmap, MLX5_DB_PER_PAGE); + if (i >= MLX5_DB_PER_PAGE) + return -ENOMEM; + + __clear_bit(i, pgdir->bitmap); + + db->u.pgdir = pgdir; + db->index = i; + offset = db->index * L1_CACHE_BYTES; + db->db = pgdir->db_page + offset / sizeof(*pgdir->db_page); + db->dma = pgdir->db_dma + offset; + + return 0; +} + +int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db) +{ + struct mlx5_db_pgdir *pgdir; + int ret = 0; + + mutex_lock(&dev->priv.pgdir_mutex); + + list_for_each_entry(pgdir, &dev->priv.pgdir_list, list) + if (!mlx5_alloc_db_from_pgdir(pgdir, db)) + goto out; + + pgdir = mlx5_alloc_db_pgdir(&(dev->pdev->dev)); + if (!pgdir) { + ret = -ENOMEM; + goto out; + } + + list_add(&pgdir->list, &dev->priv.pgdir_list); + + /* This should never fail -- we just allocated an empty page: */ + WARN_ON(mlx5_alloc_db_from_pgdir(pgdir, db)); + +out: + mutex_unlock(&dev->priv.pgdir_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(mlx5_db_alloc); + +void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db) +{ + mutex_lock(&dev->priv.pgdir_mutex); + + __set_bit(db->index, db->u.pgdir->bitmap); + + if (bitmap_full(db->u.pgdir->bitmap, MLX5_DB_PER_PAGE)) { + dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, + db->u.pgdir->db_page, db->u.pgdir->db_dma); + list_del(&db->u.pgdir->list); + kfree(db->u.pgdir); + } + + mutex_unlock(&dev->priv.pgdir_mutex); +} +EXPORT_SYMBOL_GPL(mlx5_db_free); + + +void mlx5_fill_page_array(struct mlx5_buf *buf, __be64 *pas) +{ + u64 addr; + int i; + + for (i = 0; i < buf->npages; i++) { + if (buf->nbufs == 1) + addr = buf->direct.map + (i << buf->page_shift); + else + addr = buf->page_list[i].map; + + pas[i] = cpu_to_be64(addr); + } +} +EXPORT_SYMBOL_GPL(mlx5_fill_page_array); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c new file mode 100644 index 000000000000..c1c0eef89694 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -0,0 +1,1515 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mlx5_core.h" + +enum { + CMD_IF_REV = 3, +}; + +enum { + CMD_MODE_POLLING, + CMD_MODE_EVENTS +}; + +enum { + NUM_LONG_LISTS = 2, + NUM_MED_LISTS = 64, + LONG_LIST_SIZE = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 + + MLX5_CMD_DATA_BLOCK_SIZE, + MED_LIST_SIZE = 16 + MLX5_CMD_DATA_BLOCK_SIZE, +}; + +enum { + MLX5_CMD_DELIVERY_STAT_OK = 0x0, + MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR = 0x1, + MLX5_CMD_DELIVERY_STAT_TOK_ERR = 0x2, + MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR = 0x3, + MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR = 0x4, + MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR = 0x5, + MLX5_CMD_DELIVERY_STAT_FW_ERR = 0x6, + MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR = 0x7, + MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR = 0x8, + MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR = 0x9, + MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR = 0x10, +}; + +enum { + MLX5_CMD_STAT_OK = 0x0, + MLX5_CMD_STAT_INT_ERR = 0x1, + MLX5_CMD_STAT_BAD_OP_ERR = 0x2, + MLX5_CMD_STAT_BAD_PARAM_ERR = 0x3, + MLX5_CMD_STAT_BAD_SYS_STATE_ERR = 0x4, + MLX5_CMD_STAT_BAD_RES_ERR = 0x5, + MLX5_CMD_STAT_RES_BUSY = 0x6, + MLX5_CMD_STAT_LIM_ERR = 0x8, + MLX5_CMD_STAT_BAD_RES_STATE_ERR = 0x9, + MLX5_CMD_STAT_IX_ERR = 0xa, + MLX5_CMD_STAT_NO_RES_ERR = 0xf, + MLX5_CMD_STAT_BAD_INP_LEN_ERR = 0x50, + MLX5_CMD_STAT_BAD_OUTP_LEN_ERR = 0x51, + MLX5_CMD_STAT_BAD_QP_STATE_ERR = 0x10, + MLX5_CMD_STAT_BAD_PKT_ERR = 0x30, + MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR = 0x40, +}; + +static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd, + struct mlx5_cmd_msg *in, + struct mlx5_cmd_msg *out, + mlx5_cmd_cbk_t cbk, + void *context, int page_queue) +{ + gfp_t alloc_flags = cbk ? GFP_ATOMIC : GFP_KERNEL; + struct mlx5_cmd_work_ent *ent; + + ent = kzalloc(sizeof(*ent), alloc_flags); + if (!ent) + return ERR_PTR(-ENOMEM); + + ent->in = in; + ent->out = out; + ent->callback = cbk; + ent->context = context; + ent->cmd = cmd; + ent->page_queue = page_queue; + + return ent; +} + +static u8 alloc_token(struct mlx5_cmd *cmd) +{ + u8 token; + + spin_lock(&cmd->token_lock); + token = cmd->token++ % 255 + 1; + spin_unlock(&cmd->token_lock); + + return token; +} + +static int alloc_ent(struct mlx5_cmd *cmd) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&cmd->alloc_lock, flags); + ret = find_first_bit(&cmd->bitmask, cmd->max_reg_cmds); + if (ret < cmd->max_reg_cmds) + clear_bit(ret, &cmd->bitmask); + spin_unlock_irqrestore(&cmd->alloc_lock, flags); + + return ret < cmd->max_reg_cmds ? ret : -ENOMEM; +} + +static void free_ent(struct mlx5_cmd *cmd, int idx) +{ + unsigned long flags; + + spin_lock_irqsave(&cmd->alloc_lock, flags); + set_bit(idx, &cmd->bitmask); + spin_unlock_irqrestore(&cmd->alloc_lock, flags); +} + +static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx) +{ + return cmd->cmd_buf + (idx << cmd->log_stride); +} + +static u8 xor8_buf(void *buf, int len) +{ + u8 *ptr = buf; + u8 sum = 0; + int i; + + for (i = 0; i < len; i++) + sum ^= ptr[i]; + + return sum; +} + +static int verify_block_sig(struct mlx5_cmd_prot_block *block) +{ + if (xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 1) != 0xff) + return -EINVAL; + + if (xor8_buf(block, sizeof(*block)) != 0xff) + return -EINVAL; + + return 0; +} + +static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token) +{ + block->token = token; + block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 2); + block->sig = ~xor8_buf(block, sizeof(*block) - 1); +} + +static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token) +{ + struct mlx5_cmd_mailbox *next = msg->next; + + while (next) { + calc_block_sig(next->buf, token); + next = next->next; + } +} + +static void set_signature(struct mlx5_cmd_work_ent *ent) +{ + ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay)); + calc_chain_sig(ent->in, ent->token); + calc_chain_sig(ent->out, ent->token); +} + +static void poll_timeout(struct mlx5_cmd_work_ent *ent) +{ + unsigned long poll_end = jiffies + msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC + 1000); + u8 own; + + do { + own = ent->lay->status_own; + if (!(own & CMD_OWNER_HW)) { + ent->ret = 0; + return; + } + usleep_range(5000, 10000); + } while (time_before(jiffies, poll_end)); + + ent->ret = -ETIMEDOUT; +} + +static void free_cmd(struct mlx5_cmd_work_ent *ent) +{ + kfree(ent); +} + + +static int verify_signature(struct mlx5_cmd_work_ent *ent) +{ + struct mlx5_cmd_mailbox *next = ent->out->next; + int err; + u8 sig; + + sig = xor8_buf(ent->lay, sizeof(*ent->lay)); + if (sig != 0xff) + return -EINVAL; + + while (next) { + err = verify_block_sig(next->buf); + if (err) + return err; + + next = next->next; + } + + return 0; +} + +static void dump_buf(void *buf, int size, int data_only, int offset) +{ + __be32 *p = buf; + int i; + + for (i = 0; i < size; i += 16) { + pr_debug("%03x: %08x %08x %08x %08x\n", offset, be32_to_cpu(p[0]), + be32_to_cpu(p[1]), be32_to_cpu(p[2]), + be32_to_cpu(p[3])); + p += 4; + offset += 16; + } + if (!data_only) + pr_debug("\n"); +} + +const char *mlx5_command_str(int command) +{ + switch (command) { + case MLX5_CMD_OP_QUERY_HCA_CAP: + return "QUERY_HCA_CAP"; + + case MLX5_CMD_OP_SET_HCA_CAP: + return "SET_HCA_CAP"; + + case MLX5_CMD_OP_QUERY_ADAPTER: + return "QUERY_ADAPTER"; + + case MLX5_CMD_OP_INIT_HCA: + return "INIT_HCA"; + + case MLX5_CMD_OP_TEARDOWN_HCA: + return "TEARDOWN_HCA"; + + case MLX5_CMD_OP_QUERY_PAGES: + return "QUERY_PAGES"; + + case MLX5_CMD_OP_MANAGE_PAGES: + return "MANAGE_PAGES"; + + case MLX5_CMD_OP_CREATE_MKEY: + return "CREATE_MKEY"; + + case MLX5_CMD_OP_QUERY_MKEY: + return "QUERY_MKEY"; + + case MLX5_CMD_OP_DESTROY_MKEY: + return "DESTROY_MKEY"; + + case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS: + return "QUERY_SPECIAL_CONTEXTS"; + + case MLX5_CMD_OP_CREATE_EQ: + return "CREATE_EQ"; + + case MLX5_CMD_OP_DESTROY_EQ: + return "DESTROY_EQ"; + + case MLX5_CMD_OP_QUERY_EQ: + return "QUERY_EQ"; + + case MLX5_CMD_OP_CREATE_CQ: + return "CREATE_CQ"; + + case MLX5_CMD_OP_DESTROY_CQ: + return "DESTROY_CQ"; + + case MLX5_CMD_OP_QUERY_CQ: + return "QUERY_CQ"; + + case MLX5_CMD_OP_MODIFY_CQ: + return "MODIFY_CQ"; + + case MLX5_CMD_OP_CREATE_QP: + return "CREATE_QP"; + + case MLX5_CMD_OP_DESTROY_QP: + return "DESTROY_QP"; + + case MLX5_CMD_OP_RST2INIT_QP: + return "RST2INIT_QP"; + + case MLX5_CMD_OP_INIT2RTR_QP: + return "INIT2RTR_QP"; + + case MLX5_CMD_OP_RTR2RTS_QP: + return "RTR2RTS_QP"; + + case MLX5_CMD_OP_RTS2RTS_QP: + return "RTS2RTS_QP"; + + case MLX5_CMD_OP_SQERR2RTS_QP: + return "SQERR2RTS_QP"; + + case MLX5_CMD_OP_2ERR_QP: + return "2ERR_QP"; + + case MLX5_CMD_OP_RTS2SQD_QP: + return "RTS2SQD_QP"; + + case MLX5_CMD_OP_SQD2RTS_QP: + return "SQD2RTS_QP"; + + case MLX5_CMD_OP_2RST_QP: + return "2RST_QP"; + + case MLX5_CMD_OP_QUERY_QP: + return "QUERY_QP"; + + case MLX5_CMD_OP_CONF_SQP: + return "CONF_SQP"; + + case MLX5_CMD_OP_MAD_IFC: + return "MAD_IFC"; + + case MLX5_CMD_OP_INIT2INIT_QP: + return "INIT2INIT_QP"; + + case MLX5_CMD_OP_SUSPEND_QP: + return "SUSPEND_QP"; + + case MLX5_CMD_OP_UNSUSPEND_QP: + return "UNSUSPEND_QP"; + + case MLX5_CMD_OP_SQD2SQD_QP: + return "SQD2SQD_QP"; + + case MLX5_CMD_OP_ALLOC_QP_COUNTER_SET: + return "ALLOC_QP_COUNTER_SET"; + + case MLX5_CMD_OP_DEALLOC_QP_COUNTER_SET: + return "DEALLOC_QP_COUNTER_SET"; + + case MLX5_CMD_OP_QUERY_QP_COUNTER_SET: + return "QUERY_QP_COUNTER_SET"; + + case MLX5_CMD_OP_CREATE_PSV: + return "CREATE_PSV"; + + case MLX5_CMD_OP_DESTROY_PSV: + return "DESTROY_PSV"; + + case MLX5_CMD_OP_QUERY_PSV: + return "QUERY_PSV"; + + case MLX5_CMD_OP_QUERY_SIG_RULE_TABLE: + return "QUERY_SIG_RULE_TABLE"; + + case MLX5_CMD_OP_QUERY_BLOCK_SIZE_TABLE: + return "QUERY_BLOCK_SIZE_TABLE"; + + case MLX5_CMD_OP_CREATE_SRQ: + return "CREATE_SRQ"; + + case MLX5_CMD_OP_DESTROY_SRQ: + return "DESTROY_SRQ"; + + case MLX5_CMD_OP_QUERY_SRQ: + return "QUERY_SRQ"; + + case MLX5_CMD_OP_ARM_RQ: + return "ARM_RQ"; + + case MLX5_CMD_OP_RESIZE_SRQ: + return "RESIZE_SRQ"; + + case MLX5_CMD_OP_ALLOC_PD: + return "ALLOC_PD"; + + case MLX5_CMD_OP_DEALLOC_PD: + return "DEALLOC_PD"; + + case MLX5_CMD_OP_ALLOC_UAR: + return "ALLOC_UAR"; + + case MLX5_CMD_OP_DEALLOC_UAR: + return "DEALLOC_UAR"; + + case MLX5_CMD_OP_ATTACH_TO_MCG: + return "ATTACH_TO_MCG"; + + case MLX5_CMD_OP_DETACH_FROM_MCG: + return "DETACH_FROM_MCG"; + + case MLX5_CMD_OP_ALLOC_XRCD: + return "ALLOC_XRCD"; + + case MLX5_CMD_OP_DEALLOC_XRCD: + return "DEALLOC_XRCD"; + + case MLX5_CMD_OP_ACCESS_REG: + return "MLX5_CMD_OP_ACCESS_REG"; + + default: return "unknown command opcode"; + } +} + +static void dump_command(struct mlx5_core_dev *dev, + struct mlx5_cmd_work_ent *ent, int input) +{ + u16 op = be16_to_cpu(((struct mlx5_inbox_hdr *)(ent->lay->in))->opcode); + struct mlx5_cmd_msg *msg = input ? ent->in : ent->out; + struct mlx5_cmd_mailbox *next = msg->next; + int data_only; + int offset = 0; + int dump_len; + + data_only = !!(mlx5_core_debug_mask & (1 << MLX5_CMD_DATA)); + + if (data_only) + mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_DATA, + "dump command data %s(0x%x) %s\n", + mlx5_command_str(op), op, + input ? "INPUT" : "OUTPUT"); + else + mlx5_core_dbg(dev, "dump command %s(0x%x) %s\n", + mlx5_command_str(op), op, + input ? "INPUT" : "OUTPUT"); + + if (data_only) { + if (input) { + dump_buf(ent->lay->in, sizeof(ent->lay->in), 1, offset); + offset += sizeof(ent->lay->in); + } else { + dump_buf(ent->lay->out, sizeof(ent->lay->out), 1, offset); + offset += sizeof(ent->lay->out); + } + } else { + dump_buf(ent->lay, sizeof(*ent->lay), 0, offset); + offset += sizeof(*ent->lay); + } + + while (next && offset < msg->len) { + if (data_only) { + dump_len = min_t(int, MLX5_CMD_DATA_BLOCK_SIZE, msg->len - offset); + dump_buf(next->buf, dump_len, 1, offset); + offset += MLX5_CMD_DATA_BLOCK_SIZE; + } else { + mlx5_core_dbg(dev, "command block:\n"); + dump_buf(next->buf, sizeof(struct mlx5_cmd_prot_block), 0, offset); + offset += sizeof(struct mlx5_cmd_prot_block); + } + next = next->next; + } + + if (data_only) + pr_debug("\n"); +} + +static void cmd_work_handler(struct work_struct *work) +{ + struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); + struct mlx5_cmd *cmd = ent->cmd; + struct mlx5_core_dev *dev = container_of(cmd, struct mlx5_core_dev, cmd); + struct mlx5_cmd_layout *lay; + struct semaphore *sem; + + sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + down(sem); + if (!ent->page_queue) { + ent->idx = alloc_ent(cmd); + if (ent->idx < 0) { + mlx5_core_err(dev, "failed to allocate command entry\n"); + up(sem); + return; + } + } else { + ent->idx = cmd->max_reg_cmds; + } + + ent->token = alloc_token(cmd); + cmd->ent_arr[ent->idx] = ent; + lay = get_inst(cmd, ent->idx); + ent->lay = lay; + memset(lay, 0, sizeof(*lay)); + memcpy(lay->in, ent->in->first.data, sizeof(lay->in)); + if (ent->in->next) + lay->in_ptr = cpu_to_be64(ent->in->next->dma); + lay->inlen = cpu_to_be32(ent->in->len); + if (ent->out->next) + lay->out_ptr = cpu_to_be64(ent->out->next->dma); + lay->outlen = cpu_to_be32(ent->out->len); + lay->type = MLX5_PCI_CMD_XPORT; + lay->token = ent->token; + lay->status_own = CMD_OWNER_HW; + if (!cmd->checksum_disabled) + set_signature(ent); + dump_command(dev, ent, 1); + ktime_get_ts(&ent->ts1); + + /* ring doorbell after the descriptor is valid */ + wmb(); + iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell); + mlx5_core_dbg(dev, "write 0x%x to command doorbell\n", 1 << ent->idx); + mmiowb(); + if (cmd->mode == CMD_MODE_POLLING) { + poll_timeout(ent); + /* make sure we read the descriptor after ownership is SW */ + rmb(); + mlx5_cmd_comp_handler(dev, 1UL << ent->idx); + } +} + +static const char *deliv_status_to_str(u8 status) +{ + switch (status) { + case MLX5_CMD_DELIVERY_STAT_OK: + return "no errors"; + case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR: + return "signature error"; + case MLX5_CMD_DELIVERY_STAT_TOK_ERR: + return "token error"; + case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR: + return "bad block number"; + case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR: + return "output pointer not aligned to block size"; + case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR: + return "input pointer not aligned to block size"; + case MLX5_CMD_DELIVERY_STAT_FW_ERR: + return "firmware internal error"; + case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR: + return "command input length error"; + case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR: + return "command ouput length error"; + case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR: + return "reserved fields not cleared"; + case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR: + return "bad command descriptor type"; + default: + return "unknown status code"; + } +} + +static u16 msg_to_opcode(struct mlx5_cmd_msg *in) +{ + struct mlx5_inbox_hdr *hdr = (struct mlx5_inbox_hdr *)(in->first.data); + + return be16_to_cpu(hdr->opcode); +} + +static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) +{ + unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC); + struct mlx5_cmd *cmd = &dev->cmd; + int err; + + if (cmd->mode == CMD_MODE_POLLING) { + wait_for_completion(&ent->done); + err = ent->ret; + } else { + if (!wait_for_completion_timeout(&ent->done, timeout)) + err = -ETIMEDOUT; + else + err = 0; + } + if (err == -ETIMEDOUT) { + mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n", + mlx5_command_str(msg_to_opcode(ent->in)), + msg_to_opcode(ent->in)); + } + mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n", err, + deliv_status_to_str(ent->status), ent->status); + + return err; +} + +/* Notes: + * 1. Callback functions may not sleep + * 2. page queue commands do not support asynchrous completion + */ +static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, + struct mlx5_cmd_msg *out, mlx5_cmd_cbk_t callback, + void *context, int page_queue, u8 *status) +{ + struct mlx5_cmd *cmd = &dev->cmd; + struct mlx5_cmd_work_ent *ent; + ktime_t t1, t2, delta; + struct mlx5_cmd_stats *stats; + int err = 0; + s64 ds; + u16 op; + + if (callback && page_queue) + return -EINVAL; + + ent = alloc_cmd(cmd, in, out, callback, context, page_queue); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + if (!callback) + init_completion(&ent->done); + + INIT_WORK(&ent->work, cmd_work_handler); + if (page_queue) { + cmd_work_handler(&ent->work); + } else if (!queue_work(cmd->wq, &ent->work)) { + mlx5_core_warn(dev, "failed to queue work\n"); + err = -ENOMEM; + goto out_free; + } + + if (!callback) { + err = wait_func(dev, ent); + if (err == -ETIMEDOUT) + goto out; + + t1 = timespec_to_ktime(ent->ts1); + t2 = timespec_to_ktime(ent->ts2); + delta = ktime_sub(t2, t1); + ds = ktime_to_ns(delta); + op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode); + if (op < ARRAY_SIZE(cmd->stats)) { + stats = &cmd->stats[op]; + spin_lock(&stats->lock); + stats->sum += ds; + ++stats->n; + spin_unlock(&stats->lock); + } + mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME, + "fw exec time for %s is %lld nsec\n", + mlx5_command_str(op), ds); + *status = ent->status; + free_cmd(ent); + } + + return err; + +out_free: + free_cmd(ent); +out: + return err; +} + +static ssize_t dbg_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + char lbuf[3]; + int err; + + if (!dbg->in_msg || !dbg->out_msg) + return -ENOMEM; + + if (copy_from_user(lbuf, buf, sizeof(lbuf))) + return -EPERM; + + lbuf[sizeof(lbuf) - 1] = 0; + + if (strcmp(lbuf, "go")) + return -EINVAL; + + err = mlx5_cmd_exec(dev, dbg->in_msg, dbg->inlen, dbg->out_msg, dbg->outlen); + + return err ? err : count; +} + + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = dbg_write, +}; + +static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size) +{ + struct mlx5_cmd_prot_block *block; + struct mlx5_cmd_mailbox *next; + int copy; + + if (!to || !from) + return -ENOMEM; + + copy = min_t(int, size, sizeof(to->first.data)); + memcpy(to->first.data, from, copy); + size -= copy; + from += copy; + + next = to->next; + while (size) { + if (!next) { + /* this is a BUG */ + return -ENOMEM; + } + + copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE); + block = next->buf; + memcpy(block->data, from, copy); + from += copy; + size -= copy; + next = next->next; + } + + return 0; +} + +static int mlx5_copy_from_msg(void *to, struct mlx5_cmd_msg *from, int size) +{ + struct mlx5_cmd_prot_block *block; + struct mlx5_cmd_mailbox *next; + int copy; + + if (!to || !from) + return -ENOMEM; + + copy = min_t(int, size, sizeof(from->first.data)); + memcpy(to, from->first.data, copy); + size -= copy; + to += copy; + + next = from->next; + while (size) { + if (!next) { + /* this is a BUG */ + return -ENOMEM; + } + + copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE); + block = next->buf; + if (xor8_buf(block, sizeof(*block)) != 0xff) + return -EINVAL; + + memcpy(to, block->data, copy); + to += copy; + size -= copy; + next = next->next; + } + + return 0; +} + +static struct mlx5_cmd_mailbox *alloc_cmd_box(struct mlx5_core_dev *dev, + gfp_t flags) +{ + struct mlx5_cmd_mailbox *mailbox; + + mailbox = kmalloc(sizeof(*mailbox), flags); + if (!mailbox) + return ERR_PTR(-ENOMEM); + + mailbox->buf = pci_pool_alloc(dev->cmd.pool, flags, + &mailbox->dma); + if (!mailbox->buf) { + mlx5_core_dbg(dev, "failed allocation\n"); + kfree(mailbox); + return ERR_PTR(-ENOMEM); + } + memset(mailbox->buf, 0, sizeof(struct mlx5_cmd_prot_block)); + mailbox->next = NULL; + + return mailbox; +} + +static void free_cmd_box(struct mlx5_core_dev *dev, + struct mlx5_cmd_mailbox *mailbox) +{ + pci_pool_free(dev->cmd.pool, mailbox->buf, mailbox->dma); + kfree(mailbox); +} + +static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, + gfp_t flags, int size) +{ + struct mlx5_cmd_mailbox *tmp, *head = NULL; + struct mlx5_cmd_prot_block *block; + struct mlx5_cmd_msg *msg; + int blen; + int err; + int n; + int i; + + msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return ERR_PTR(-ENOMEM); + + blen = size - min_t(int, sizeof(msg->first.data), size); + n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1) / MLX5_CMD_DATA_BLOCK_SIZE; + + for (i = 0; i < n; i++) { + tmp = alloc_cmd_box(dev, flags); + if (IS_ERR(tmp)) { + mlx5_core_warn(dev, "failed allocating block\n"); + err = PTR_ERR(tmp); + goto err_alloc; + } + + block = tmp->buf; + tmp->next = head; + block->next = cpu_to_be64(tmp->next ? tmp->next->dma : 0); + block->block_num = cpu_to_be32(n - i - 1); + head = tmp; + } + msg->next = head; + msg->len = size; + return msg; + +err_alloc: + while (head) { + tmp = head->next; + free_cmd_box(dev, head); + head = tmp; + } + kfree(msg); + + return ERR_PTR(err); +} + +static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, + struct mlx5_cmd_msg *msg) +{ + struct mlx5_cmd_mailbox *head = msg->next; + struct mlx5_cmd_mailbox *next; + + while (head) { + next = head->next; + free_cmd_box(dev, head); + head = next; + } + kfree(msg); +} + +static ssize_t data_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + void *ptr; + int err; + + if (*pos != 0) + return -EINVAL; + + kfree(dbg->in_msg); + dbg->in_msg = NULL; + dbg->inlen = 0; + + ptr = kzalloc(count, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + if (copy_from_user(ptr, buf, count)) { + err = -EPERM; + goto out; + } + dbg->in_msg = ptr; + dbg->inlen = count; + + *pos = count; + + return count; + +out: + kfree(ptr); + return err; +} + +static ssize_t data_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + int copy; + + if (*pos) + return 0; + + if (!dbg->out_msg) + return -ENOMEM; + + copy = min_t(int, count, dbg->outlen); + if (copy_to_user(buf, dbg->out_msg, copy)) + return -EPERM; + + *pos += copy; + + return copy; +} + +static const struct file_operations dfops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = data_write, + .read = data_read, +}; + +static ssize_t outlen_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + char outlen[8]; + int err; + + if (*pos) + return 0; + + err = snprintf(outlen, sizeof(outlen), "%d", dbg->outlen); + if (err < 0) + return err; + + if (copy_to_user(buf, &outlen, err)) + return -EPERM; + + *pos += err; + + return err; +} + +static ssize_t outlen_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + char outlen_str[8]; + int outlen; + void *ptr; + int err; + + if (*pos != 0 || count > 6) + return -EINVAL; + + kfree(dbg->out_msg); + dbg->out_msg = NULL; + dbg->outlen = 0; + + if (copy_from_user(outlen_str, buf, count)) + return -EPERM; + + outlen_str[7] = 0; + + err = sscanf(outlen_str, "%d", &outlen); + if (err < 0) + return err; + + ptr = kzalloc(outlen, GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + dbg->out_msg = ptr; + dbg->outlen = outlen; + + *pos = count; + + return count; +} + +static const struct file_operations olfops = { + .owner = THIS_MODULE, + .open = simple_open, + .write = outlen_write, + .read = outlen_read, +}; + +static void set_wqname(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + + snprintf(cmd->wq_name, sizeof(cmd->wq_name), "mlx5_cmd_%s", + dev_name(&dev->pdev->dev)); +} + +static void clean_debug_files(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + + if (!mlx5_debugfs_root) + return; + + mlx5_cmdif_debugfs_cleanup(dev); + debugfs_remove_recursive(dbg->dbg_root); +} + +static int create_debugfs_files(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; + int err = -ENOMEM; + + if (!mlx5_debugfs_root) + return 0; + + dbg->dbg_root = debugfs_create_dir("cmd", dev->priv.dbg_root); + if (!dbg->dbg_root) + return err; + + dbg->dbg_in = debugfs_create_file("in", 0400, dbg->dbg_root, + dev, &dfops); + if (!dbg->dbg_in) + goto err_dbg; + + dbg->dbg_out = debugfs_create_file("out", 0200, dbg->dbg_root, + dev, &dfops); + if (!dbg->dbg_out) + goto err_dbg; + + dbg->dbg_outlen = debugfs_create_file("out_len", 0600, dbg->dbg_root, + dev, &olfops); + if (!dbg->dbg_outlen) + goto err_dbg; + + dbg->dbg_status = debugfs_create_u8("status", 0600, dbg->dbg_root, + &dbg->status); + if (!dbg->dbg_status) + goto err_dbg; + + dbg->dbg_run = debugfs_create_file("run", 0200, dbg->dbg_root, dev, &fops); + if (!dbg->dbg_run) + goto err_dbg; + + mlx5_cmdif_debugfs_init(dev); + + return 0; + +err_dbg: + clean_debug_files(dev); + return err; +} + +void mlx5_cmd_use_events(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + int i; + + for (i = 0; i < cmd->max_reg_cmds; i++) + down(&cmd->sem); + + down(&cmd->pages_sem); + + flush_workqueue(cmd->wq); + + cmd->mode = CMD_MODE_EVENTS; + + up(&cmd->pages_sem); + for (i = 0; i < cmd->max_reg_cmds; i++) + up(&cmd->sem); +} + +void mlx5_cmd_use_polling(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + int i; + + for (i = 0; i < cmd->max_reg_cmds; i++) + down(&cmd->sem); + + down(&cmd->pages_sem); + + flush_workqueue(cmd->wq); + cmd->mode = CMD_MODE_POLLING; + + up(&cmd->pages_sem); + for (i = 0; i < cmd->max_reg_cmds; i++) + up(&cmd->sem); +} + +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) +{ + struct mlx5_cmd *cmd = &dev->cmd; + struct mlx5_cmd_work_ent *ent; + mlx5_cmd_cbk_t callback; + void *context; + int err; + int i; + + for (i = 0; i < (1 << cmd->log_sz); i++) { + if (test_bit(i, &vector)) { + ent = cmd->ent_arr[i]; + ktime_get_ts(&ent->ts2); + memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out)); + dump_command(dev, ent, 0); + if (!ent->ret) { + if (!cmd->checksum_disabled) + ent->ret = verify_signature(ent); + else + ent->ret = 0; + ent->status = ent->lay->status_own >> 1; + mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n", + ent->ret, deliv_status_to_str(ent->status), ent->status); + } + free_ent(cmd, ent->idx); + if (ent->callback) { + callback = ent->callback; + context = ent->context; + err = ent->ret; + free_cmd(ent); + callback(err, context); + } else { + complete(&ent->done); + } + if (ent->page_queue) + up(&cmd->pages_sem); + else + up(&cmd->sem); + } + } +} +EXPORT_SYMBOL(mlx5_cmd_comp_handler); + +static int status_to_err(u8 status) +{ + return status ? -1 : 0; /* TBD more meaningful codes */ +} + +static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size) +{ + struct mlx5_cmd_msg *msg = ERR_PTR(-ENOMEM); + struct mlx5_cmd *cmd = &dev->cmd; + struct cache_ent *ent = NULL; + + if (in_size > MED_LIST_SIZE && in_size <= LONG_LIST_SIZE) + ent = &cmd->cache.large; + else if (in_size > 16 && in_size <= MED_LIST_SIZE) + ent = &cmd->cache.med; + + if (ent) { + spin_lock(&ent->lock); + if (!list_empty(&ent->head)) { + msg = list_entry(ent->head.next, typeof(*msg), list); + /* For cached lists, we must explicitly state what is + * the real size + */ + msg->len = in_size; + list_del(&msg->list); + } + spin_unlock(&ent->lock); + } + + if (IS_ERR(msg)) + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, in_size); + + return msg; +} + +static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg) +{ + if (msg->cache) { + spin_lock(&msg->cache->lock); + list_add_tail(&msg->list, &msg->cache->head); + spin_unlock(&msg->cache->lock); + } else { + mlx5_free_cmd_msg(dev, msg); + } +} + +static int is_manage_pages(struct mlx5_inbox_hdr *in) +{ + return be16_to_cpu(in->opcode) == MLX5_CMD_OP_MANAGE_PAGES; +} + +int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, + int out_size) +{ + struct mlx5_cmd_msg *inb; + struct mlx5_cmd_msg *outb; + int pages_queue; + int err; + u8 status = 0; + + pages_queue = is_manage_pages(in); + + inb = alloc_msg(dev, in_size); + if (IS_ERR(inb)) { + err = PTR_ERR(inb); + return err; + } + + err = mlx5_copy_to_msg(inb, in, in_size); + if (err) { + mlx5_core_warn(dev, "err %d\n", err); + goto out_in; + } + + outb = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, out_size); + if (IS_ERR(outb)) { + err = PTR_ERR(outb); + goto out_in; + } + + err = mlx5_cmd_invoke(dev, inb, outb, NULL, NULL, pages_queue, &status); + if (err) + goto out_out; + + mlx5_core_dbg(dev, "err %d, status %d\n", err, status); + if (status) { + err = status_to_err(status); + goto out_out; + } + + err = mlx5_copy_from_msg(out, outb, out_size); + +out_out: + mlx5_free_cmd_msg(dev, outb); + +out_in: + free_msg(dev, inb); + return err; +} +EXPORT_SYMBOL(mlx5_cmd_exec); + +static void destroy_msg_cache(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + struct mlx5_cmd_msg *msg; + struct mlx5_cmd_msg *n; + + list_for_each_entry_safe(msg, n, &cmd->cache.large.head, list) { + list_del(&msg->list); + mlx5_free_cmd_msg(dev, msg); + } + + list_for_each_entry_safe(msg, n, &cmd->cache.med.head, list) { + list_del(&msg->list); + mlx5_free_cmd_msg(dev, msg); + } +} + +static int create_msg_cache(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + struct mlx5_cmd_msg *msg; + int err; + int i; + + spin_lock_init(&cmd->cache.large.lock); + INIT_LIST_HEAD(&cmd->cache.large.head); + spin_lock_init(&cmd->cache.med.lock); + INIT_LIST_HEAD(&cmd->cache.med.head); + + for (i = 0; i < NUM_LONG_LISTS; i++) { + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE); + if (IS_ERR(msg)) { + err = PTR_ERR(msg); + goto ex_err; + } + msg->cache = &cmd->cache.large; + list_add_tail(&msg->list, &cmd->cache.large.head); + } + + for (i = 0; i < NUM_MED_LISTS; i++) { + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE); + if (IS_ERR(msg)) { + err = PTR_ERR(msg); + goto ex_err; + } + msg->cache = &cmd->cache.med; + list_add_tail(&msg->list, &cmd->cache.med.head); + } + + return 0; + +ex_err: + destroy_msg_cache(dev); + return err; +} + +int mlx5_cmd_init(struct mlx5_core_dev *dev) +{ + int size = sizeof(struct mlx5_cmd_prot_block); + int align = roundup_pow_of_two(size); + struct mlx5_cmd *cmd = &dev->cmd; + u32 cmd_h, cmd_l; + u16 cmd_if_rev; + int err; + int i; + + cmd_if_rev = cmdif_rev(dev); + if (cmd_if_rev != CMD_IF_REV) { + dev_err(&dev->pdev->dev, + "Driver cmdif rev(%d) differs from firmware's(%d)\n", + CMD_IF_REV, cmd_if_rev); + return -EINVAL; + } + + cmd->pool = pci_pool_create("mlx5_cmd", dev->pdev, size, align, 0); + if (!cmd->pool) + return -ENOMEM; + + cmd->cmd_buf = (void *)__get_free_pages(GFP_ATOMIC, 0); + if (!cmd->cmd_buf) { + err = -ENOMEM; + goto err_free_pool; + } + cmd->dma = dma_map_single(&dev->pdev->dev, cmd->cmd_buf, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(&dev->pdev->dev, cmd->dma)) { + err = -ENOMEM; + goto err_free; + } + + cmd_l = ioread32be(&dev->iseg->cmdq_addr_l_sz) & 0xff; + cmd->log_sz = cmd_l >> 4 & 0xf; + cmd->log_stride = cmd_l & 0xf; + if (1 << cmd->log_sz > MLX5_MAX_COMMANDS) { + dev_err(&dev->pdev->dev, "firmware reports too many outstanding commands %d\n", + 1 << cmd->log_sz); + err = -EINVAL; + goto err_map; + } + + if (cmd->log_sz + cmd->log_stride > PAGE_SHIFT) { + dev_err(&dev->pdev->dev, "command queue size overflow\n"); + err = -EINVAL; + goto err_map; + } + + cmd->max_reg_cmds = (1 << cmd->log_sz) - 1; + cmd->bitmask = (1 << cmd->max_reg_cmds) - 1; + + cmd->cmdif_rev = ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; + if (cmd->cmdif_rev > CMD_IF_REV) { + dev_err(&dev->pdev->dev, "driver does not support command interface version. driver %d, firmware %d\n", + CMD_IF_REV, cmd->cmdif_rev); + err = -ENOTSUPP; + goto err_map; + } + + spin_lock_init(&cmd->alloc_lock); + spin_lock_init(&cmd->token_lock); + for (i = 0; i < ARRAY_SIZE(cmd->stats); i++) + spin_lock_init(&cmd->stats[i].lock); + + sema_init(&cmd->sem, cmd->max_reg_cmds); + sema_init(&cmd->pages_sem, 1); + + cmd_h = (u32)((u64)(cmd->dma) >> 32); + cmd_l = (u32)(cmd->dma); + if (cmd_l & 0xfff) { + dev_err(&dev->pdev->dev, "invalid command queue address\n"); + err = -ENOMEM; + goto err_map; + } + + iowrite32be(cmd_h, &dev->iseg->cmdq_addr_h); + iowrite32be(cmd_l, &dev->iseg->cmdq_addr_l_sz); + + /* Make sure firmware sees the complete address before we proceed */ + wmb(); + + mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma)); + + cmd->mode = CMD_MODE_POLLING; + + err = create_msg_cache(dev); + if (err) { + dev_err(&dev->pdev->dev, "failed to create command cache\n"); + goto err_map; + } + + set_wqname(dev); + cmd->wq = create_singlethread_workqueue(cmd->wq_name); + if (!cmd->wq) { + dev_err(&dev->pdev->dev, "failed to create command workqueue\n"); + err = -ENOMEM; + goto err_cache; + } + + err = create_debugfs_files(dev); + if (err) { + err = -ENOMEM; + goto err_wq; + } + + return 0; + +err_wq: + destroy_workqueue(cmd->wq); + +err_cache: + destroy_msg_cache(dev); + +err_map: + dma_unmap_single(&dev->pdev->dev, cmd->dma, PAGE_SIZE, + DMA_BIDIRECTIONAL); +err_free: + free_pages((unsigned long)cmd->cmd_buf, 0); + +err_free_pool: + pci_pool_destroy(cmd->pool); + + return err; +} +EXPORT_SYMBOL(mlx5_cmd_init); + +void mlx5_cmd_cleanup(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd *cmd = &dev->cmd; + + clean_debug_files(dev); + destroy_workqueue(cmd->wq); + destroy_msg_cache(dev); + dma_unmap_single(&dev->pdev->dev, cmd->dma, PAGE_SIZE, + DMA_BIDIRECTIONAL); + free_pages((unsigned long)cmd->cmd_buf, 0); + pci_pool_destroy(cmd->pool); +} +EXPORT_SYMBOL(mlx5_cmd_cleanup); + +static const char *cmd_status_str(u8 status) +{ + switch (status) { + case MLX5_CMD_STAT_OK: + return "OK"; + case MLX5_CMD_STAT_INT_ERR: + return "internal error"; + case MLX5_CMD_STAT_BAD_OP_ERR: + return "bad operation"; + case MLX5_CMD_STAT_BAD_PARAM_ERR: + return "bad parameter"; + case MLX5_CMD_STAT_BAD_SYS_STATE_ERR: + return "bad system state"; + case MLX5_CMD_STAT_BAD_RES_ERR: + return "bad resource"; + case MLX5_CMD_STAT_RES_BUSY: + return "resource busy"; + case MLX5_CMD_STAT_LIM_ERR: + return "limits exceeded"; + case MLX5_CMD_STAT_BAD_RES_STATE_ERR: + return "bad resource state"; + case MLX5_CMD_STAT_IX_ERR: + return "bad index"; + case MLX5_CMD_STAT_NO_RES_ERR: + return "no resources"; + case MLX5_CMD_STAT_BAD_INP_LEN_ERR: + return "bad input length"; + case MLX5_CMD_STAT_BAD_OUTP_LEN_ERR: + return "bad output length"; + case MLX5_CMD_STAT_BAD_QP_STATE_ERR: + return "bad QP state"; + case MLX5_CMD_STAT_BAD_PKT_ERR: + return "bad packet (discarded)"; + case MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR: + return "bad size too many outstanding CQEs"; + default: + return "unknown status"; + } +} + +int mlx5_cmd_status_to_err(struct mlx5_outbox_hdr *hdr) +{ + if (!hdr->status) + return 0; + + pr_warn("command failed, status %s(0x%x), syndrome 0x%x\n", + cmd_status_str(hdr->status), hdr->status, + be32_to_cpu(hdr->syndrome)); + + switch (hdr->status) { + case MLX5_CMD_STAT_OK: return 0; + case MLX5_CMD_STAT_INT_ERR: return -EIO; + case MLX5_CMD_STAT_BAD_OP_ERR: return -EINVAL; + case MLX5_CMD_STAT_BAD_PARAM_ERR: return -EINVAL; + case MLX5_CMD_STAT_BAD_SYS_STATE_ERR: return -EIO; + case MLX5_CMD_STAT_BAD_RES_ERR: return -EINVAL; + case MLX5_CMD_STAT_RES_BUSY: return -EBUSY; + case MLX5_CMD_STAT_LIM_ERR: return -EINVAL; + case MLX5_CMD_STAT_BAD_RES_STATE_ERR: return -EINVAL; + case MLX5_CMD_STAT_IX_ERR: return -EINVAL; + case MLX5_CMD_STAT_NO_RES_ERR: return -EAGAIN; + case MLX5_CMD_STAT_BAD_INP_LEN_ERR: return -EIO; + case MLX5_CMD_STAT_BAD_OUTP_LEN_ERR: return -EIO; + case MLX5_CMD_STAT_BAD_QP_STATE_ERR: return -EINVAL; + case MLX5_CMD_STAT_BAD_PKT_ERR: return -EINVAL; + case MLX5_CMD_STAT_BAD_SIZE_OUTS_CQES_ERR: return -EINVAL; + default: return -EIO; + } +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c new file mode 100644 index 000000000000..c2d660be6f76 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn) +{ + struct mlx5_core_cq *cq; + struct mlx5_cq_table *table = &dev->priv.cq_table; + + spin_lock(&table->lock); + cq = radix_tree_lookup(&table->tree, cqn); + if (likely(cq)) + atomic_inc(&cq->refcount); + spin_unlock(&table->lock); + + if (!cq) { + mlx5_core_warn(dev, "Completion event for bogus CQ 0x%x\n", cqn); + return; + } + + ++cq->arm_sn; + + cq->comp(cq); + + if (atomic_dec_and_test(&cq->refcount)) + complete(&cq->free); +} + +void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type) +{ + struct mlx5_cq_table *table = &dev->priv.cq_table; + struct mlx5_core_cq *cq; + + spin_lock(&table->lock); + + cq = radix_tree_lookup(&table->tree, cqn); + if (cq) + atomic_inc(&cq->refcount); + + spin_unlock(&table->lock); + + if (!cq) { + mlx5_core_warn(dev, "Async event for bogus CQ 0x%x\n", cqn); + return; + } + + cq->event(cq, event_type); + + if (atomic_dec_and_test(&cq->refcount)) + complete(&cq->free); +} + + +int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + struct mlx5_create_cq_mbox_in *in, int inlen) +{ + int err; + struct mlx5_cq_table *table = &dev->priv.cq_table; + struct mlx5_create_cq_mbox_out out; + struct mlx5_destroy_cq_mbox_in din; + struct mlx5_destroy_cq_mbox_out dout; + + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_CQ); + memset(&out, 0, sizeof(out)); + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + cq->cqn = be32_to_cpu(out.cqn) & 0xffffff; + cq->cons_index = 0; + cq->arm_sn = 0; + atomic_set(&cq->refcount, 1); + init_completion(&cq->free); + + spin_lock_irq(&table->lock); + err = radix_tree_insert(&table->tree, cq->cqn, cq); + spin_unlock_irq(&table->lock); + if (err) + goto err_cmd; + + cq->pid = current->pid; + err = mlx5_debug_cq_add(dev, cq); + if (err) + mlx5_core_dbg(dev, "failed adding CP 0x%x to debug file system\n", + cq->cqn); + + return 0; + +err_cmd: + memset(&din, 0, sizeof(din)); + memset(&dout, 0, sizeof(dout)); + din.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_CQ); + mlx5_cmd_exec(dev, &din, sizeof(din), &dout, sizeof(dout)); + return err; +} +EXPORT_SYMBOL(mlx5_core_create_cq); + +int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) +{ + struct mlx5_cq_table *table = &dev->priv.cq_table; + struct mlx5_destroy_cq_mbox_in in; + struct mlx5_destroy_cq_mbox_out out; + struct mlx5_core_cq *tmp; + int err; + + spin_lock_irq(&table->lock); + tmp = radix_tree_delete(&table->tree, cq->cqn); + spin_unlock_irq(&table->lock); + if (!tmp) { + mlx5_core_warn(dev, "cq 0x%x not found in tree\n", cq->cqn); + return -EINVAL; + } + if (tmp != cq) { + mlx5_core_warn(dev, "corruption on srqn 0x%x\n", cq->cqn); + return -EINVAL; + } + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_CQ); + in.cqn = cpu_to_be32(cq->cqn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + synchronize_irq(cq->irqn); + + mlx5_debug_cq_remove(dev, cq); + if (atomic_dec_and_test(&cq->refcount)) + complete(&cq->free); + wait_for_completion(&cq->free); + + return 0; +} +EXPORT_SYMBOL(mlx5_core_destroy_cq); + +int mlx5_core_query_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + struct mlx5_query_cq_mbox_out *out) +{ + struct mlx5_query_cq_mbox_in in; + int err; + + memset(&in, 0, sizeof(in)); + memset(out, 0, sizeof(*out)); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_CQ); + in.cqn = cpu_to_be32(cq->cqn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, sizeof(*out)); + if (err) + return err; + + if (out->hdr.status) + return mlx5_cmd_status_to_err(&out->hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_query_cq); + + +int mlx5_core_modify_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + int type, struct mlx5_cq_modify_params *params) +{ + return -ENOSYS; +} + +int mlx5_init_cq_table(struct mlx5_core_dev *dev) +{ + struct mlx5_cq_table *table = &dev->priv.cq_table; + int err; + + spin_lock_init(&table->lock); + INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); + err = mlx5_cq_debugfs_init(dev); + + return err; +} + +void mlx5_cleanup_cq_table(struct mlx5_core_dev *dev) +{ + mlx5_cq_debugfs_cleanup(dev); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c new file mode 100644 index 000000000000..5e9cf2b9aaf7 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +enum { + QP_PID, + QP_STATE, + QP_XPORT, + QP_MTU, + QP_N_RECV, + QP_RECV_SZ, + QP_N_SEND, + QP_LOG_PG_SZ, + QP_RQPN, +}; + +static char *qp_fields[] = { + [QP_PID] = "pid", + [QP_STATE] = "state", + [QP_XPORT] = "transport", + [QP_MTU] = "mtu", + [QP_N_RECV] = "num_recv", + [QP_RECV_SZ] = "rcv_wqe_sz", + [QP_N_SEND] = "num_send", + [QP_LOG_PG_SZ] = "log2_page_sz", + [QP_RQPN] = "remote_qpn", +}; + +enum { + EQ_NUM_EQES, + EQ_INTR, + EQ_LOG_PG_SZ, +}; + +static char *eq_fields[] = { + [EQ_NUM_EQES] = "num_eqes", + [EQ_INTR] = "intr", + [EQ_LOG_PG_SZ] = "log_page_size", +}; + +enum { + CQ_PID, + CQ_NUM_CQES, + CQ_LOG_PG_SZ, +}; + +static char *cq_fields[] = { + [CQ_PID] = "pid", + [CQ_NUM_CQES] = "num_cqes", + [CQ_LOG_PG_SZ] = "log_page_size", +}; + +struct dentry *mlx5_debugfs_root; +EXPORT_SYMBOL(mlx5_debugfs_root); + +void mlx5_register_debugfs(void) +{ + mlx5_debugfs_root = debugfs_create_dir("mlx5", NULL); + if (IS_ERR_OR_NULL(mlx5_debugfs_root)) + mlx5_debugfs_root = NULL; +} + +void mlx5_unregister_debugfs(void) +{ + debugfs_remove(mlx5_debugfs_root); +} + +int mlx5_qp_debugfs_init(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return 0; + + atomic_set(&dev->num_qps, 0); + + dev->priv.qp_debugfs = debugfs_create_dir("QPs", dev->priv.dbg_root); + if (!dev->priv.qp_debugfs) + return -ENOMEM; + + return 0; +} + +void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return; + + debugfs_remove_recursive(dev->priv.qp_debugfs); +} + +int mlx5_eq_debugfs_init(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return 0; + + dev->priv.eq_debugfs = debugfs_create_dir("EQs", dev->priv.dbg_root); + if (!dev->priv.eq_debugfs) + return -ENOMEM; + + return 0; +} + +void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return; + + debugfs_remove_recursive(dev->priv.eq_debugfs); +} + +static ssize_t average_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_cmd_stats *stats; + u64 field = 0; + int ret; + int err; + char tbuf[22]; + + if (*pos) + return 0; + + stats = filp->private_data; + spin_lock(&stats->lock); + if (stats->n) + field = stats->sum / stats->n; + spin_unlock(&stats->lock); + ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field); + if (ret > 0) { + err = copy_to_user(buf, tbuf, ret); + if (err) + return err; + } + + *pos += ret; + return ret; +} + + +static ssize_t average_write(struct file *filp, const char __user *buf, + size_t count, loff_t *pos) +{ + struct mlx5_cmd_stats *stats; + + stats = filp->private_data; + spin_lock(&stats->lock); + stats->sum = 0; + stats->n = 0; + spin_unlock(&stats->lock); + + *pos += count; + + return count; +} + +static const struct file_operations stats_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = average_read, + .write = average_write, +}; + +int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_stats *stats; + struct dentry **cmd; + const char *namep; + int err; + int i; + + if (!mlx5_debugfs_root) + return 0; + + cmd = &dev->priv.cmdif_debugfs; + *cmd = debugfs_create_dir("commands", dev->priv.dbg_root); + if (!*cmd) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(dev->cmd.stats); i++) { + stats = &dev->cmd.stats[i]; + namep = mlx5_command_str(i); + if (strcmp(namep, "unknown command opcode")) { + stats->root = debugfs_create_dir(namep, *cmd); + if (!stats->root) { + mlx5_core_warn(dev, "failed adding command %d\n", + i); + err = -ENOMEM; + goto out; + } + + stats->avg = debugfs_create_file("average", 0400, + stats->root, stats, + &stats_fops); + if (!stats->avg) { + mlx5_core_warn(dev, "failed creating debugfs file\n"); + err = -ENOMEM; + goto out; + } + + stats->count = debugfs_create_u64("n", 0400, + stats->root, + &stats->n); + if (!stats->count) { + mlx5_core_warn(dev, "failed creating debugfs file\n"); + err = -ENOMEM; + goto out; + } + } + } + + return 0; +out: + debugfs_remove_recursive(dev->priv.cmdif_debugfs); + return err; +} + +void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return; + + debugfs_remove_recursive(dev->priv.cmdif_debugfs); +} + +int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return 0; + + dev->priv.cq_debugfs = debugfs_create_dir("CQs", dev->priv.dbg_root); + if (!dev->priv.cq_debugfs) + return -ENOMEM; + + return 0; +} + +void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev) +{ + if (!mlx5_debugfs_root) + return; + + debugfs_remove_recursive(dev->priv.cq_debugfs); +} + +static u64 qp_read_field(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp, + int index) +{ + struct mlx5_query_qp_mbox_out *out; + struct mlx5_qp_context *ctx; + u64 param = 0; + int err; + int no_sq; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return param; + + err = mlx5_core_qp_query(dev, qp, out, sizeof(*out)); + if (err) { + mlx5_core_warn(dev, "failed to query qp\n"); + goto out; + } + + ctx = &out->ctx; + switch (index) { + case QP_PID: + param = qp->pid; + break; + case QP_STATE: + param = be32_to_cpu(ctx->flags) >> 28; + break; + case QP_XPORT: + param = (be32_to_cpu(ctx->flags) >> 16) & 0xff; + break; + case QP_MTU: + param = ctx->mtu_msgmax >> 5; + break; + case QP_N_RECV: + param = 1 << ((ctx->rq_size_stride >> 3) & 0xf); + break; + case QP_RECV_SZ: + param = 1 << ((ctx->rq_size_stride & 7) + 4); + break; + case QP_N_SEND: + no_sq = be16_to_cpu(ctx->sq_crq_size) >> 15; + if (!no_sq) + param = 1 << (be16_to_cpu(ctx->sq_crq_size) >> 11); + else + param = 0; + break; + case QP_LOG_PG_SZ: + param = ((cpu_to_be32(ctx->log_pg_sz_remote_qpn) >> 24) & 0x1f); + param += 12; + break; + case QP_RQPN: + param = cpu_to_be32(ctx->log_pg_sz_remote_qpn) & 0xffffff; + break; + } + +out: + kfree(out); + return param; +} + +static u64 eq_read_field(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + int index) +{ + struct mlx5_query_eq_mbox_out *out; + struct mlx5_eq_context *ctx; + u64 param = 0; + int err; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return param; + + ctx = &out->ctx; + + err = mlx5_core_eq_query(dev, eq, out, sizeof(*out)); + if (err) { + mlx5_core_warn(dev, "failed to query eq\n"); + goto out; + } + + switch (index) { + case EQ_NUM_EQES: + param = 1 << ((be32_to_cpu(ctx->log_sz_usr_page) >> 24) & 0x1f); + break; + case EQ_INTR: + param = ctx->intr; + break; + case EQ_LOG_PG_SZ: + param = (ctx->log_page_size & 0x1f) + 12; + break; + } + +out: + kfree(out); + return param; +} + +static u64 cq_read_field(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + int index) +{ + struct mlx5_query_cq_mbox_out *out; + struct mlx5_cq_context *ctx; + u64 param = 0; + int err; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return param; + + ctx = &out->ctx; + + err = mlx5_core_query_cq(dev, cq, out); + if (err) { + mlx5_core_warn(dev, "failed to query cq\n"); + goto out; + } + + switch (index) { + case CQ_PID: + param = cq->pid; + break; + case CQ_NUM_CQES: + param = 1 << ((be32_to_cpu(ctx->log_sz_usr_page) >> 24) & 0x1f); + break; + case CQ_LOG_PG_SZ: + param = (ctx->log_pg_sz & 0x1f) + 12; + break; + } + +out: + kfree(out); + return param; +} + +static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count, + loff_t *pos) +{ + struct mlx5_field_desc *desc; + struct mlx5_rsc_debug *d; + char tbuf[18]; + u64 field; + int ret; + int err; + + if (*pos) + return 0; + + desc = filp->private_data; + d = (void *)(desc - desc->i) - sizeof(*d); + switch (d->type) { + case MLX5_DBG_RSC_QP: + field = qp_read_field(d->dev, d->object, desc->i); + break; + + case MLX5_DBG_RSC_EQ: + field = eq_read_field(d->dev, d->object, desc->i); + break; + + case MLX5_DBG_RSC_CQ: + field = cq_read_field(d->dev, d->object, desc->i); + break; + + default: + mlx5_core_warn(d->dev, "invalid resource type %d\n", d->type); + return -EINVAL; + } + + ret = snprintf(tbuf, sizeof(tbuf), "0x%llx\n", field); + if (ret > 0) { + err = copy_to_user(buf, tbuf, ret); + if (err) + return err; + } + + *pos += ret; + return ret; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = dbg_read, +}; + +static int add_res_tree(struct mlx5_core_dev *dev, enum dbg_rsc_type type, + struct dentry *root, struct mlx5_rsc_debug **dbg, + int rsn, char **field, int nfile, void *data) +{ + struct mlx5_rsc_debug *d; + char resn[32]; + int err; + int i; + + d = kzalloc(sizeof(*d) + nfile * sizeof(d->fields[0]), GFP_KERNEL); + if (!d) + return -ENOMEM; + + d->dev = dev; + d->object = data; + d->type = type; + sprintf(resn, "0x%x", rsn); + d->root = debugfs_create_dir(resn, root); + if (!d->root) { + err = -ENOMEM; + goto out_free; + } + + for (i = 0; i < nfile; i++) { + d->fields[i].i = i; + d->fields[i].dent = debugfs_create_file(field[i], 0400, + d->root, &d->fields[i], + &fops); + if (!d->fields[i].dent) { + err = -ENOMEM; + goto out_rem; + } + } + *dbg = d; + + return 0; +out_rem: + debugfs_remove_recursive(d->root); + +out_free: + kfree(d); + return err; +} + +static void rem_res_tree(struct mlx5_rsc_debug *d) +{ + debugfs_remove_recursive(d->root); + kfree(d); +} + +int mlx5_debug_qp_add(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) +{ + int err; + + if (!mlx5_debugfs_root) + return 0; + + err = add_res_tree(dev, MLX5_DBG_RSC_QP, dev->priv.qp_debugfs, + &qp->dbg, qp->qpn, qp_fields, + ARRAY_SIZE(qp_fields), qp); + if (err) + qp->dbg = NULL; + + return err; +} + +void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) +{ + if (!mlx5_debugfs_root) + return; + + if (qp->dbg) + rem_res_tree(qp->dbg); +} + + +int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq) +{ + int err; + + if (!mlx5_debugfs_root) + return 0; + + err = add_res_tree(dev, MLX5_DBG_RSC_EQ, dev->priv.eq_debugfs, + &eq->dbg, eq->eqn, eq_fields, + ARRAY_SIZE(eq_fields), eq); + if (err) + eq->dbg = NULL; + + return err; +} + +void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq) +{ + if (!mlx5_debugfs_root) + return; + + if (eq->dbg) + rem_res_tree(eq->dbg); +} + +int mlx5_debug_cq_add(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) +{ + int err; + + if (!mlx5_debugfs_root) + return 0; + + err = add_res_tree(dev, MLX5_DBG_RSC_CQ, dev->priv.cq_debugfs, + &cq->dbg, cq->cqn, cq_fields, + ARRAY_SIZE(cq_fields), cq); + if (err) + cq->dbg = NULL; + + return err; +} + +void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) +{ + if (!mlx5_debugfs_root) + return; + + if (cq->dbg) + rem_res_tree(cq->dbg); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c new file mode 100644 index 000000000000..c02cbcfd0fb8 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "mlx5_core.h" + +enum { + MLX5_EQE_SIZE = sizeof(struct mlx5_eqe), + MLX5_EQE_OWNER_INIT_VAL = 0x1, +}; + +enum { + MLX5_EQ_STATE_ARMED = 0x9, + MLX5_EQ_STATE_FIRED = 0xa, + MLX5_EQ_STATE_ALWAYS_ARMED = 0xb, +}; + +enum { + MLX5_NUM_SPARE_EQE = 0x80, + MLX5_NUM_ASYNC_EQE = 0x100, + MLX5_NUM_CMD_EQE = 32, +}; + +enum { + MLX5_EQ_DOORBEL_OFFSET = 0x40, +}; + +#define MLX5_ASYNC_EVENT_MASK ((1ull << MLX5_EVENT_TYPE_PATH_MIG) | \ + (1ull << MLX5_EVENT_TYPE_COMM_EST) | \ + (1ull << MLX5_EVENT_TYPE_SQ_DRAINED) | \ + (1ull << MLX5_EVENT_TYPE_CQ_ERROR) | \ + (1ull << MLX5_EVENT_TYPE_WQ_CATAS_ERROR) | \ + (1ull << MLX5_EVENT_TYPE_PATH_MIG_FAILED) | \ + (1ull << MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \ + (1ull << MLX5_EVENT_TYPE_WQ_ACCESS_ERROR) | \ + (1ull << MLX5_EVENT_TYPE_PORT_CHANGE) | \ + (1ull << MLX5_EVENT_TYPE_SRQ_CATAS_ERROR) | \ + (1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \ + (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT)) + +struct map_eq_in { + u64 mask; + u32 reserved; + u32 unmap_eqn; +}; + +struct cre_des_eq { + u8 reserved[15]; + u8 eqn; +}; + +static int mlx5_cmd_destroy_eq(struct mlx5_core_dev *dev, u8 eqn) +{ + struct mlx5_destroy_eq_mbox_in in; + struct mlx5_destroy_eq_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_EQ); + in.eqn = eqn; + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (!err) + goto ex; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + +ex: + return err; +} + +static struct mlx5_eqe *get_eqe(struct mlx5_eq *eq, u32 entry) +{ + return mlx5_buf_offset(&eq->buf, entry * MLX5_EQE_SIZE); +} + +static struct mlx5_eqe *next_eqe_sw(struct mlx5_eq *eq) +{ + struct mlx5_eqe *eqe = get_eqe(eq, eq->cons_index & (eq->nent - 1)); + + return ((eqe->owner & 1) ^ !!(eq->cons_index & eq->nent)) ? NULL : eqe; +} + +static const char *eqe_type_str(u8 type) +{ + switch (type) { + case MLX5_EVENT_TYPE_COMP: + return "MLX5_EVENT_TYPE_COMP"; + case MLX5_EVENT_TYPE_PATH_MIG: + return "MLX5_EVENT_TYPE_PATH_MIG"; + case MLX5_EVENT_TYPE_COMM_EST: + return "MLX5_EVENT_TYPE_COMM_EST"; + case MLX5_EVENT_TYPE_SQ_DRAINED: + return "MLX5_EVENT_TYPE_SQ_DRAINED"; + case MLX5_EVENT_TYPE_SRQ_LAST_WQE: + return "MLX5_EVENT_TYPE_SRQ_LAST_WQE"; + case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: + return "MLX5_EVENT_TYPE_SRQ_RQ_LIMIT"; + case MLX5_EVENT_TYPE_CQ_ERROR: + return "MLX5_EVENT_TYPE_CQ_ERROR"; + case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: + return "MLX5_EVENT_TYPE_WQ_CATAS_ERROR"; + case MLX5_EVENT_TYPE_PATH_MIG_FAILED: + return "MLX5_EVENT_TYPE_PATH_MIG_FAILED"; + case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: + return "MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR"; + case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: + return "MLX5_EVENT_TYPE_WQ_ACCESS_ERROR"; + case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: + return "MLX5_EVENT_TYPE_SRQ_CATAS_ERROR"; + case MLX5_EVENT_TYPE_INTERNAL_ERROR: + return "MLX5_EVENT_TYPE_INTERNAL_ERROR"; + case MLX5_EVENT_TYPE_PORT_CHANGE: + return "MLX5_EVENT_TYPE_PORT_CHANGE"; + case MLX5_EVENT_TYPE_GPIO_EVENT: + return "MLX5_EVENT_TYPE_GPIO_EVENT"; + case MLX5_EVENT_TYPE_REMOTE_CONFIG: + return "MLX5_EVENT_TYPE_REMOTE_CONFIG"; + case MLX5_EVENT_TYPE_DB_BF_CONGESTION: + return "MLX5_EVENT_TYPE_DB_BF_CONGESTION"; + case MLX5_EVENT_TYPE_STALL_EVENT: + return "MLX5_EVENT_TYPE_STALL_EVENT"; + case MLX5_EVENT_TYPE_CMD: + return "MLX5_EVENT_TYPE_CMD"; + case MLX5_EVENT_TYPE_PAGE_REQUEST: + return "MLX5_EVENT_TYPE_PAGE_REQUEST"; + default: + return "Unrecognized event"; + } +} + +static enum mlx5_dev_event port_subtype_event(u8 subtype) +{ + switch (subtype) { + case MLX5_PORT_CHANGE_SUBTYPE_DOWN: + return MLX5_DEV_EVENT_PORT_DOWN; + case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: + return MLX5_DEV_EVENT_PORT_UP; + case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED: + return MLX5_DEV_EVENT_PORT_INITIALIZED; + case MLX5_PORT_CHANGE_SUBTYPE_LID: + return MLX5_DEV_EVENT_LID_CHANGE; + case MLX5_PORT_CHANGE_SUBTYPE_PKEY: + return MLX5_DEV_EVENT_PKEY_CHANGE; + case MLX5_PORT_CHANGE_SUBTYPE_GUID: + return MLX5_DEV_EVENT_GUID_CHANGE; + case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG: + return MLX5_DEV_EVENT_CLIENT_REREG; + } + return -1; +} + +static void eq_update_ci(struct mlx5_eq *eq, int arm) +{ + __be32 __iomem *addr = eq->doorbell + (arm ? 0 : 2); + u32 val = (eq->cons_index & 0xffffff) | (eq->eqn << 24); + __raw_writel((__force u32) cpu_to_be32(val), addr); + /* We still want ordering, just not swabbing, so add a barrier */ + mb(); +} + +static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq) +{ + struct mlx5_eqe *eqe; + int eqes_found = 0; + int set_ci = 0; + u32 cqn; + u32 srqn; + u8 port; + + while ((eqe = next_eqe_sw(eq))) { + /* + * Make sure we read EQ entry contents after we've + * checked the ownership bit. + */ + rmb(); + + mlx5_core_dbg(eq->dev, "eqn %d, eqe type %s\n", eq->eqn, eqe_type_str(eqe->type)); + switch (eqe->type) { + case MLX5_EVENT_TYPE_COMP: + cqn = be32_to_cpu(eqe->data.comp.cqn) & 0xffffff; + mlx5_cq_completion(dev, cqn); + break; + + case MLX5_EVENT_TYPE_PATH_MIG: + case MLX5_EVENT_TYPE_COMM_EST: + case MLX5_EVENT_TYPE_SQ_DRAINED: + case MLX5_EVENT_TYPE_SRQ_LAST_WQE: + case MLX5_EVENT_TYPE_WQ_CATAS_ERROR: + case MLX5_EVENT_TYPE_PATH_MIG_FAILED: + case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR: + case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR: + mlx5_core_dbg(dev, "event %s(%d) arrived\n", + eqe_type_str(eqe->type), eqe->type); + mlx5_qp_event(dev, be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff, + eqe->type); + break; + + case MLX5_EVENT_TYPE_SRQ_RQ_LIMIT: + case MLX5_EVENT_TYPE_SRQ_CATAS_ERROR: + srqn = be32_to_cpu(eqe->data.qp_srq.qp_srq_n) & 0xffffff; + mlx5_core_dbg(dev, "SRQ event %s(%d): srqn 0x%x\n", + eqe_type_str(eqe->type), eqe->type, srqn); + mlx5_srq_event(dev, srqn, eqe->type); + break; + + case MLX5_EVENT_TYPE_CMD: + mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector)); + break; + + case MLX5_EVENT_TYPE_PORT_CHANGE: + port = (eqe->data.port.port >> 4) & 0xf; + switch (eqe->sub_type) { + case MLX5_PORT_CHANGE_SUBTYPE_DOWN: + case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: + case MLX5_PORT_CHANGE_SUBTYPE_LID: + case MLX5_PORT_CHANGE_SUBTYPE_PKEY: + case MLX5_PORT_CHANGE_SUBTYPE_GUID: + case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG: + case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED: + dev->event(dev, port_subtype_event(eqe->sub_type), &port); + break; + default: + mlx5_core_warn(dev, "Port event with unrecognized subtype: port %d, sub_type %d\n", + port, eqe->sub_type); + } + break; + case MLX5_EVENT_TYPE_CQ_ERROR: + cqn = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff; + mlx5_core_warn(dev, "CQ error on CQN 0x%x, syndrom 0x%x\n", + cqn, eqe->data.cq_err.syndrome); + mlx5_cq_event(dev, cqn, eqe->type); + break; + + case MLX5_EVENT_TYPE_PAGE_REQUEST: + { + u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id); + s16 npages = be16_to_cpu(eqe->data.req_pages.num_pages); + + mlx5_core_dbg(dev, "page request for func 0x%x, napges %d\n", func_id, npages); + mlx5_core_req_pages_handler(dev, func_id, npages); + } + break; + + + default: + mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n", eqe->type, eq->eqn); + break; + } + + ++eq->cons_index; + eqes_found = 1; + ++set_ci; + + /* The HCA will think the queue has overflowed if we + * don't tell it we've been processing events. We + * create our EQs with MLX5_NUM_SPARE_EQE extra + * entries, so we must update our consumer index at + * least that often. + */ + if (unlikely(set_ci >= MLX5_NUM_SPARE_EQE)) { + eq_update_ci(eq, 0); + set_ci = 0; + } + } + + eq_update_ci(eq, 1); + + return eqes_found; +} + +static irqreturn_t mlx5_msix_handler(int irq, void *eq_ptr) +{ + struct mlx5_eq *eq = eq_ptr; + struct mlx5_core_dev *dev = eq->dev; + + mlx5_eq_int(dev, eq); + + /* MSI-X vectors always belong to us */ + return IRQ_HANDLED; +} + +static void init_eq_buf(struct mlx5_eq *eq) +{ + struct mlx5_eqe *eqe; + int i; + + for (i = 0; i < eq->nent; i++) { + eqe = get_eqe(eq, i); + eqe->owner = MLX5_EQE_OWNER_INIT_VAL; + } +} + +int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, + int nent, u64 mask, const char *name, struct mlx5_uar *uar) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + struct mlx5_create_eq_mbox_in *in; + struct mlx5_create_eq_mbox_out out; + int err; + int inlen; + + eq->nent = roundup_pow_of_two(nent + MLX5_NUM_SPARE_EQE); + err = mlx5_buf_alloc(dev, eq->nent * MLX5_EQE_SIZE, 2 * PAGE_SIZE, + &eq->buf); + if (err) + return err; + + init_eq_buf(eq); + + inlen = sizeof(*in) + sizeof(in->pas[0]) * eq->buf.npages; + in = mlx5_vzalloc(inlen); + if (!in) { + err = -ENOMEM; + goto err_buf; + } + memset(&out, 0, sizeof(out)); + + mlx5_fill_page_array(&eq->buf, in->pas); + + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_EQ); + in->ctx.log_sz_usr_page = cpu_to_be32(ilog2(eq->nent) << 24 | uar->index); + in->ctx.intr = vecidx; + in->ctx.log_page_size = PAGE_SHIFT - 12; + in->events_mask = cpu_to_be64(mask); + + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + if (err) + goto err_in; + + if (out.hdr.status) { + err = mlx5_cmd_status_to_err(&out.hdr); + goto err_in; + } + + eq->eqn = out.eq_number; + err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0, + name, eq); + if (err) + goto err_eq; + + eq->irqn = vecidx; + eq->dev = dev; + eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET; + + err = mlx5_debug_eq_add(dev, eq); + if (err) + goto err_irq; + + /* EQs are created in ARMED state + */ + eq_update_ci(eq, 1); + + mlx5_vfree(in); + return 0; + +err_irq: + free_irq(table->msix_arr[vecidx].vector, eq); + +err_eq: + mlx5_cmd_destroy_eq(dev, eq->eqn); + +err_in: + mlx5_vfree(in); + +err_buf: + mlx5_buf_free(dev, &eq->buf); + return err; +} +EXPORT_SYMBOL_GPL(mlx5_create_map_eq); + +int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + int err; + + mlx5_debug_eq_remove(dev, eq); + free_irq(table->msix_arr[eq->irqn].vector, eq); + err = mlx5_cmd_destroy_eq(dev, eq->eqn); + if (err) + mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", + eq->eqn); + mlx5_buf_free(dev, &eq->buf); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_destroy_unmap_eq); + +int mlx5_eq_init(struct mlx5_core_dev *dev) +{ + int err; + + spin_lock_init(&dev->priv.eq_table.lock); + + err = mlx5_eq_debugfs_init(dev); + + return err; +} + + +void mlx5_eq_cleanup(struct mlx5_core_dev *dev) +{ + mlx5_eq_debugfs_cleanup(dev); +} + +int mlx5_start_eqs(struct mlx5_core_dev *dev) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + int err; + + err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD, + MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD, + "mlx5_cmd_eq", &dev->priv.uuari.uars[0]); + if (err) { + mlx5_core_warn(dev, "failed to create cmd EQ %d\n", err); + return err; + } + + mlx5_cmd_use_events(dev); + + err = mlx5_create_map_eq(dev, &table->async_eq, MLX5_EQ_VEC_ASYNC, + MLX5_NUM_ASYNC_EQE, MLX5_ASYNC_EVENT_MASK, + "mlx5_async_eq", &dev->priv.uuari.uars[0]); + if (err) { + mlx5_core_warn(dev, "failed to create async EQ %d\n", err); + goto err1; + } + + err = mlx5_create_map_eq(dev, &table->pages_eq, + MLX5_EQ_VEC_PAGES, + dev->caps.max_vf + 1, + 1 << MLX5_EVENT_TYPE_PAGE_REQUEST, "mlx5_pages_eq", + &dev->priv.uuari.uars[0]); + if (err) { + mlx5_core_warn(dev, "failed to create pages EQ %d\n", err); + goto err2; + } + + return err; + +err2: + mlx5_destroy_unmap_eq(dev, &table->async_eq); + +err1: + mlx5_cmd_use_polling(dev); + mlx5_destroy_unmap_eq(dev, &table->cmd_eq); + return err; +} + +int mlx5_stop_eqs(struct mlx5_core_dev *dev) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + int err; + + err = mlx5_destroy_unmap_eq(dev, &table->pages_eq); + if (err) + return err; + + mlx5_destroy_unmap_eq(dev, &table->async_eq); + mlx5_cmd_use_polling(dev); + + err = mlx5_destroy_unmap_eq(dev, &table->cmd_eq); + if (err) + mlx5_cmd_use_events(dev); + + return err; +} + +int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + struct mlx5_query_eq_mbox_out *out, int outlen) +{ + struct mlx5_query_eq_mbox_in in; + int err; + + memset(&in, 0, sizeof(in)); + memset(out, 0, outlen); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_EQ); + in.eqn = eq->eqn; + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); + if (err) + return err; + + if (out->hdr.status) + err = mlx5_cmd_status_to_err(&out->hdr); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_eq_query); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c new file mode 100644 index 000000000000..72a5222447f5 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "mlx5_core.h" + +int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_query_adapter_mbox_out *out; + struct mlx5_cmd_query_adapter_mbox_in in; + int err; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return -ENOMEM; + + memset(&in, 0, sizeof(in)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_ADAPTER); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, sizeof(*out)); + if (err) + goto out_out; + + if (out->hdr.status) { + err = mlx5_cmd_status_to_err(&out->hdr); + goto out_out; + } + + memcpy(dev->board_id, out->vsd_psid, sizeof(out->vsd_psid)); + +out_out: + kfree(out); + + return err; +} + +int mlx5_cmd_query_hca_cap(struct mlx5_core_dev *dev, + struct mlx5_caps *caps) +{ + struct mlx5_cmd_query_hca_cap_mbox_out *out; + struct mlx5_cmd_query_hca_cap_mbox_in in; + struct mlx5_query_special_ctxs_mbox_out ctx_out; + struct mlx5_query_special_ctxs_mbox_in ctx_in; + int err; + u16 t16; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) + return -ENOMEM; + + memset(&in, 0, sizeof(in)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_HCA_CAP); + in.hdr.opmod = cpu_to_be16(0x1); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, sizeof(*out)); + if (err) + goto out_out; + + if (out->hdr.status) { + err = mlx5_cmd_status_to_err(&out->hdr); + goto out_out; + } + + + caps->log_max_eq = out->hca_cap.log_max_eq & 0xf; + caps->max_cqes = 1 << out->hca_cap.log_max_cq_sz; + caps->max_wqes = 1 << out->hca_cap.log_max_qp_sz; + caps->max_sq_desc_sz = be16_to_cpu(out->hca_cap.max_desc_sz_sq); + caps->max_rq_desc_sz = be16_to_cpu(out->hca_cap.max_desc_sz_rq); + caps->flags = be64_to_cpu(out->hca_cap.flags); + caps->stat_rate_support = be16_to_cpu(out->hca_cap.stat_rate_support); + caps->log_max_msg = out->hca_cap.log_max_msg & 0x1f; + caps->num_ports = out->hca_cap.num_ports & 0xf; + caps->log_max_cq = out->hca_cap.log_max_cq & 0x1f; + if (caps->num_ports > MLX5_MAX_PORTS) { + mlx5_core_err(dev, "device has %d ports while the driver supports max %d ports\n", + caps->num_ports, MLX5_MAX_PORTS); + err = -EINVAL; + goto out_out; + } + caps->log_max_qp = out->hca_cap.log_max_qp & 0x1f; + caps->log_max_mkey = out->hca_cap.log_max_mkey & 0x3f; + caps->log_max_pd = out->hca_cap.log_max_pd & 0x1f; + caps->log_max_srq = out->hca_cap.log_max_srqs & 0x1f; + caps->local_ca_ack_delay = out->hca_cap.local_ca_ack_delay & 0x1f; + caps->log_max_mcg = out->hca_cap.log_max_mcg; + caps->max_qp_mcg = be16_to_cpu(out->hca_cap.max_qp_mcg); + caps->max_ra_res_qp = 1 << (out->hca_cap.log_max_ra_res_qp & 0x3f); + caps->max_ra_req_qp = 1 << (out->hca_cap.log_max_ra_req_qp & 0x3f); + caps->max_srq_wqes = 1 << out->hca_cap.log_max_srq_sz; + t16 = be16_to_cpu(out->hca_cap.bf_log_bf_reg_size); + if (t16 & 0x8000) { + caps->bf_reg_size = 1 << (t16 & 0x1f); + caps->bf_regs_per_page = MLX5_BF_REGS_PER_PAGE; + } else { + caps->bf_reg_size = 0; + caps->bf_regs_per_page = 0; + } + caps->min_page_sz = ~(u32)((1 << out->hca_cap.log_pg_sz) - 1); + + memset(&ctx_in, 0, sizeof(ctx_in)); + memset(&ctx_out, 0, sizeof(ctx_out)); + ctx_in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS); + err = mlx5_cmd_exec(dev, &ctx_in, sizeof(ctx_in), + &ctx_out, sizeof(ctx_out)); + if (err) + goto out_out; + + if (ctx_out.hdr.status) + err = mlx5_cmd_status_to_err(&ctx_out.hdr); + + caps->reserved_lkey = be32_to_cpu(ctx_out.reserved_lkey); + +out_out: + kfree(out); + + return err; +} + +int mlx5_cmd_init_hca(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_init_hca_mbox_in in; + struct mlx5_cmd_init_hca_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_INIT_HCA); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + + return err; +} + +int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_teardown_hca_mbox_in in; + struct mlx5_cmd_teardown_hca_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_TEARDOWN_HCA); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + + return err; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c new file mode 100644 index 000000000000..ea4b9bca6d4a --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +enum { + MLX5_HEALTH_POLL_INTERVAL = 2 * HZ, + MAX_MISSES = 3, +}; + +enum { + MLX5_HEALTH_SYNDR_FW_ERR = 0x1, + MLX5_HEALTH_SYNDR_IRISC_ERR = 0x7, + MLX5_HEALTH_SYNDR_CRC_ERR = 0x9, + MLX5_HEALTH_SYNDR_FETCH_PCI_ERR = 0xa, + MLX5_HEALTH_SYNDR_HW_FTL_ERR = 0xb, + MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR = 0xc, + MLX5_HEALTH_SYNDR_EQ_ERR = 0xd, + MLX5_HEALTH_SYNDR_FFSER_ERR = 0xf, +}; + +static DEFINE_SPINLOCK(health_lock); + +static LIST_HEAD(health_list); +static struct work_struct health_work; + +static health_handler_t reg_handler; +int mlx5_register_health_report_handler(health_handler_t handler) +{ + spin_lock_irq(&health_lock); + if (reg_handler) { + spin_unlock_irq(&health_lock); + return -EEXIST; + } + reg_handler = handler; + spin_unlock_irq(&health_lock); + + return 0; +} +EXPORT_SYMBOL(mlx5_register_health_report_handler); + +void mlx5_unregister_health_report_handler(void) +{ + spin_lock_irq(&health_lock); + reg_handler = NULL; + spin_unlock_irq(&health_lock); +} +EXPORT_SYMBOL(mlx5_unregister_health_report_handler); + +static void health_care(struct work_struct *work) +{ + struct mlx5_core_health *health, *n; + struct mlx5_core_dev *dev; + struct mlx5_priv *priv; + LIST_HEAD(tlist); + + spin_lock_irq(&health_lock); + list_splice_init(&health_list, &tlist); + + spin_unlock_irq(&health_lock); + + list_for_each_entry_safe(health, n, &tlist, list) { + priv = container_of(health, struct mlx5_priv, health); + dev = container_of(priv, struct mlx5_core_dev, priv); + mlx5_core_warn(dev, "handling bad device here\n"); + spin_lock_irq(&health_lock); + if (reg_handler) + reg_handler(dev->pdev, health->health, + sizeof(health->health)); + + list_del_init(&health->list); + spin_unlock_irq(&health_lock); + } +} + +static const char *hsynd_str(u8 synd) +{ + switch (synd) { + case MLX5_HEALTH_SYNDR_FW_ERR: + return "firmware internal error"; + case MLX5_HEALTH_SYNDR_IRISC_ERR: + return "irisc not responding"; + case MLX5_HEALTH_SYNDR_CRC_ERR: + return "firmware CRC error"; + case MLX5_HEALTH_SYNDR_FETCH_PCI_ERR: + return "ICM fetch PCI error"; + case MLX5_HEALTH_SYNDR_HW_FTL_ERR: + return "HW fatal error\n"; + case MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR: + return "async EQ buffer overrun"; + case MLX5_HEALTH_SYNDR_EQ_ERR: + return "EQ error"; + case MLX5_HEALTH_SYNDR_FFSER_ERR: + return "FFSER error"; + default: + return "unrecognized error"; + } +} + +static void print_health_info(struct mlx5_core_dev *dev) +{ + struct mlx5_core_health *health = &dev->priv.health; + struct health_buffer __iomem *h = health->health; + int i; + + for (i = 0; i < ARRAY_SIZE(h->assert_var); i++) + pr_info("assert_var[%d] 0x%08x\n", i, be32_to_cpu(h->assert_var[i])); + + pr_info("assert_exit_ptr 0x%08x\n", be32_to_cpu(h->assert_exit_ptr)); + pr_info("assert_callra 0x%08x\n", be32_to_cpu(h->assert_callra)); + pr_info("fw_ver 0x%08x\n", be32_to_cpu(h->fw_ver)); + pr_info("hw_id 0x%08x\n", be32_to_cpu(h->hw_id)); + pr_info("irisc_index %d\n", h->irisc_index); + pr_info("synd 0x%x: %s\n", h->synd, hsynd_str(h->synd)); + pr_info("ext_sync 0x%04x\n", be16_to_cpu(h->ext_sync)); +} + +static void poll_health(unsigned long data) +{ + struct mlx5_core_dev *dev = (struct mlx5_core_dev *)data; + struct mlx5_core_health *health = &dev->priv.health; + unsigned long next; + u32 count; + + count = ioread32be(health->health_counter); + if (count == health->prev) + ++health->miss_counter; + else + health->miss_counter = 0; + + health->prev = count; + if (health->miss_counter == MAX_MISSES) { + mlx5_core_err(dev, "device's health compromised\n"); + print_health_info(dev); + spin_lock_irq(&health_lock); + list_add_tail(&health->list, &health_list); + spin_unlock_irq(&health_lock); + + queue_work(mlx5_core_wq, &health_work); + } else { + get_random_bytes(&next, sizeof(next)); + next %= HZ; + next += jiffies + MLX5_HEALTH_POLL_INTERVAL; + mod_timer(&health->timer, next); + } +} + +void mlx5_start_health_poll(struct mlx5_core_dev *dev) +{ + struct mlx5_core_health *health = &dev->priv.health; + + INIT_LIST_HEAD(&health->list); + init_timer(&health->timer); + health->health = &dev->iseg->health; + health->health_counter = &dev->iseg->health_counter; + + health->timer.data = (unsigned long)dev; + health->timer.function = poll_health; + health->timer.expires = round_jiffies(jiffies + MLX5_HEALTH_POLL_INTERVAL); + add_timer(&health->timer); +} + +void mlx5_stop_health_poll(struct mlx5_core_dev *dev) +{ + struct mlx5_core_health *health = &dev->priv.health; + + del_timer_sync(&health->timer); + + spin_lock_irq(&health_lock); + if (!list_empty(&health->list)) + list_del_init(&health->list); + spin_unlock_irq(&health_lock); +} + +void mlx5_health_cleanup(void) +{ +} + +void __init mlx5_health_init(void) +{ + INIT_WORK(&health_work, health_care); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mad.c b/drivers/net/ethernet/mellanox/mlx5/core/mad.c new file mode 100644 index 000000000000..18d6fd5dd90b --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/mad.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "mlx5_core.h" + +int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb, + u16 opmod, int port) +{ + struct mlx5_mad_ifc_mbox_in *in = NULL; + struct mlx5_mad_ifc_mbox_out *out = NULL; + int err; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return -ENOMEM; + + out = kzalloc(sizeof(*out), GFP_KERNEL); + if (!out) { + err = -ENOMEM; + goto out; + } + + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MAD_IFC); + in->hdr.opmod = cpu_to_be16(opmod); + in->port = port; + + memcpy(in->data, inb, sizeof(in->data)); + + err = mlx5_cmd_exec(dev, in, sizeof(*in), out, sizeof(*out)); + if (err) + goto out; + + if (out->hdr.status) { + err = mlx5_cmd_status_to_err(&out->hdr); + goto out; + } + + memcpy(outb, out->data, sizeof(out->data)); + +out: + kfree(out); + kfree(in); + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_mad_ifc); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c new file mode 100644 index 000000000000..f21cc397d1bc --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +#define DRIVER_NAME "mlx5_core" +#define DRIVER_VERSION "1.0" +#define DRIVER_RELDATE "June 2013" + +MODULE_AUTHOR("Eli Cohen "); +MODULE_DESCRIPTION("Mellanox ConnectX-IB HCA core library"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRIVER_VERSION); + +int mlx5_core_debug_mask; +module_param_named(debug_mask, mlx5_core_debug_mask, int, 0644); +MODULE_PARM_DESC(debug_mask, "debug mask: 1 = dump cmd data, 2 = dump cmd exec time, 3 = both. Default=0"); + +struct workqueue_struct *mlx5_core_wq; + +static int set_dma_caps(struct pci_dev *pdev) +{ + int err; + + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (err) { + dev_warn(&pdev->dev, "Warning: couldn't set 64-bit PCI DMA mask.\n"); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, "Can't set PCI DMA mask, aborting.\n"); + return err; + } + } + + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + if (err) { + dev_warn(&pdev->dev, + "Warning: couldn't set 64-bit consistent PCI DMA mask.\n"); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, + "Can't set consistent PCI DMA mask, aborting.\n"); + return err; + } + } + + dma_set_max_seg_size(&pdev->dev, 2u * 1024 * 1024 * 1024); + return err; +} + +static int request_bar(struct pci_dev *pdev) +{ + int err = 0; + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + dev_err(&pdev->dev, "Missing registers BAR, aborting.\n"); + return -ENODEV; + } + + err = pci_request_regions(pdev, DRIVER_NAME); + if (err) + dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n"); + + return err; +} + +static void release_bar(struct pci_dev *pdev) +{ + pci_release_regions(pdev); +} + +static int mlx5_enable_msix(struct mlx5_core_dev *dev) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + int num_eqs = 1 << dev->caps.log_max_eq; + int nvec; + int err; + int i; + + nvec = dev->caps.num_ports * num_online_cpus() + MLX5_EQ_VEC_COMP_BASE; + nvec = min_t(int, nvec, num_eqs); + if (nvec <= MLX5_EQ_VEC_COMP_BASE) + return -ENOMEM; + + table->msix_arr = kzalloc(nvec * sizeof(*table->msix_arr), GFP_KERNEL); + if (!table->msix_arr) + return -ENOMEM; + + for (i = 0; i < nvec; i++) + table->msix_arr[i].entry = i; + +retry: + table->num_comp_vectors = nvec - MLX5_EQ_VEC_COMP_BASE; + err = pci_enable_msix(dev->pdev, table->msix_arr, nvec); + if (err <= 0) { + return err; + } else if (err > 2) { + nvec = err; + goto retry; + } + + mlx5_core_dbg(dev, "received %d MSI vectors out of %d requested\n", err, nvec); + + return 0; +} + +static void mlx5_disable_msix(struct mlx5_core_dev *dev) +{ + struct mlx5_eq_table *table = &dev->priv.eq_table; + + pci_disable_msix(dev->pdev); + kfree(table->msix_arr); +} + +struct mlx5_reg_host_endianess { + u8 he; + u8 rsvd[15]; +}; + +static int handle_hca_cap(struct mlx5_core_dev *dev) +{ + struct mlx5_cmd_query_hca_cap_mbox_out *query_out = NULL; + struct mlx5_cmd_set_hca_cap_mbox_in *set_ctx = NULL; + struct mlx5_cmd_query_hca_cap_mbox_in query_ctx; + struct mlx5_cmd_set_hca_cap_mbox_out set_out; + struct mlx5_profile *prof = dev->profile; + u64 flags; + int csum = 1; + int err; + + memset(&query_ctx, 0, sizeof(query_ctx)); + query_out = kzalloc(sizeof(*query_out), GFP_KERNEL); + if (!query_out) + return -ENOMEM; + + set_ctx = kzalloc(sizeof(*set_ctx), GFP_KERNEL); + if (!set_ctx) { + err = -ENOMEM; + goto query_ex; + } + + query_ctx.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_HCA_CAP); + query_ctx.hdr.opmod = cpu_to_be16(0x1); + err = mlx5_cmd_exec(dev, &query_ctx, sizeof(query_ctx), + query_out, sizeof(*query_out)); + if (err) + goto query_ex; + + err = mlx5_cmd_status_to_err(&query_out->hdr); + if (err) { + mlx5_core_warn(dev, "query hca cap failed, %d\n", err); + goto query_ex; + } + + memcpy(&set_ctx->hca_cap, &query_out->hca_cap, + sizeof(set_ctx->hca_cap)); + + if (prof->mask & MLX5_PROF_MASK_CMDIF_CSUM) { + csum = !!prof->cmdif_csum; + flags = be64_to_cpu(set_ctx->hca_cap.flags); + if (csum) + flags |= MLX5_DEV_CAP_FLAG_CMDIF_CSUM; + else + flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM; + + set_ctx->hca_cap.flags = cpu_to_be64(flags); + } + + if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE) + set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp; + + memset(&set_out, 0, sizeof(set_out)); + set_ctx->hca_cap.uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12); + set_ctx->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_SET_HCA_CAP); + err = mlx5_cmd_exec(dev, set_ctx, sizeof(*set_ctx), + &set_out, sizeof(set_out)); + if (err) { + mlx5_core_warn(dev, "set hca cap failed, %d\n", err); + goto query_ex; + } + + err = mlx5_cmd_status_to_err(&set_out.hdr); + if (err) + goto query_ex; + + if (!csum) + dev->cmd.checksum_disabled = 1; + +query_ex: + kfree(query_out); + kfree(set_ctx); + + return err; +} + +static int set_hca_ctrl(struct mlx5_core_dev *dev) +{ + struct mlx5_reg_host_endianess he_in; + struct mlx5_reg_host_endianess he_out; + int err; + + memset(&he_in, 0, sizeof(he_in)); + he_in.he = MLX5_SET_HOST_ENDIANNESS; + err = mlx5_core_access_reg(dev, &he_in, sizeof(he_in), + &he_out, sizeof(he_out), + MLX5_REG_HOST_ENDIANNESS, 0, 1); + return err; +} + +int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) +{ + struct mlx5_priv *priv = &dev->priv; + int err; + + dev->pdev = pdev; + pci_set_drvdata(dev->pdev, dev); + strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN); + priv->name[MLX5_MAX_NAME_LEN - 1] = 0; + + mutex_init(&priv->pgdir_mutex); + INIT_LIST_HEAD(&priv->pgdir_list); + spin_lock_init(&priv->mkey_lock); + + priv->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), mlx5_debugfs_root); + if (!priv->dbg_root) + return -ENOMEM; + + err = pci_enable_device(pdev); + if (err) { + dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n"); + goto err_dbg; + } + + err = request_bar(pdev); + if (err) { + dev_err(&pdev->dev, "error requesting BARs, aborting.\n"); + goto err_disable; + } + + pci_set_master(pdev); + + err = set_dma_caps(pdev); + if (err) { + dev_err(&pdev->dev, "Failed setting DMA capabilities mask, aborting\n"); + goto err_clr_master; + } + + dev->iseg_base = pci_resource_start(dev->pdev, 0); + dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg)); + if (!dev->iseg) { + err = -ENOMEM; + dev_err(&pdev->dev, "Failed mapping initialization segment, aborting\n"); + goto err_clr_master; + } + dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev), + fw_rev_min(dev), fw_rev_sub(dev)); + + err = mlx5_cmd_init(dev); + if (err) { + dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); + goto err_unmap; + } + + mlx5_pagealloc_init(dev); + err = set_hca_ctrl(dev); + if (err) { + dev_err(&pdev->dev, "set_hca_ctrl failed\n"); + goto err_pagealloc_cleanup; + } + + err = handle_hca_cap(dev); + if (err) { + dev_err(&pdev->dev, "handle_hca_cap failed\n"); + goto err_pagealloc_cleanup; + } + + err = mlx5_satisfy_startup_pages(dev); + if (err) { + dev_err(&pdev->dev, "failed to allocate startup pages\n"); + goto err_pagealloc_cleanup; + } + + err = mlx5_pagealloc_start(dev); + if (err) { + dev_err(&pdev->dev, "mlx5_pagealloc_start failed\n"); + goto err_reclaim_pages; + } + + err = mlx5_cmd_init_hca(dev); + if (err) { + dev_err(&pdev->dev, "init hca failed\n"); + goto err_pagealloc_stop; + } + + mlx5_start_health_poll(dev); + + err = mlx5_cmd_query_hca_cap(dev, &dev->caps); + if (err) { + dev_err(&pdev->dev, "query hca failed\n"); + goto err_stop_poll; + } + + err = mlx5_cmd_query_adapter(dev); + if (err) { + dev_err(&pdev->dev, "query adapter failed\n"); + goto err_stop_poll; + } + + err = mlx5_enable_msix(dev); + if (err) { + dev_err(&pdev->dev, "enable msix failed\n"); + goto err_stop_poll; + } + + err = mlx5_eq_init(dev); + if (err) { + dev_err(&pdev->dev, "failed to initialize eq\n"); + goto disable_msix; + } + + err = mlx5_alloc_uuars(dev, &priv->uuari); + if (err) { + dev_err(&pdev->dev, "Failed allocating uar, aborting\n"); + goto err_eq_cleanup; + } + + err = mlx5_start_eqs(dev); + if (err) { + dev_err(&pdev->dev, "Failed to start pages and async EQs\n"); + goto err_free_uar; + } + + MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock); + + mlx5_init_cq_table(dev); + mlx5_init_qp_table(dev); + mlx5_init_srq_table(dev); + + return 0; + +err_free_uar: + mlx5_free_uuars(dev, &priv->uuari); + +err_eq_cleanup: + mlx5_eq_cleanup(dev); + +disable_msix: + mlx5_disable_msix(dev); + +err_stop_poll: + mlx5_stop_health_poll(dev); + mlx5_cmd_teardown_hca(dev); + +err_pagealloc_stop: + mlx5_pagealloc_stop(dev); + +err_reclaim_pages: + mlx5_reclaim_startup_pages(dev); + +err_pagealloc_cleanup: + mlx5_pagealloc_cleanup(dev); + mlx5_cmd_cleanup(dev); + +err_unmap: + iounmap(dev->iseg); + +err_clr_master: + pci_clear_master(dev->pdev); + release_bar(dev->pdev); + +err_disable: + pci_disable_device(dev->pdev); + +err_dbg: + debugfs_remove(priv->dbg_root); + return err; +} +EXPORT_SYMBOL(mlx5_dev_init); + +void mlx5_dev_cleanup(struct mlx5_core_dev *dev) +{ + struct mlx5_priv *priv = &dev->priv; + + mlx5_cleanup_srq_table(dev); + mlx5_cleanup_qp_table(dev); + mlx5_cleanup_cq_table(dev); + mlx5_stop_eqs(dev); + mlx5_free_uuars(dev, &priv->uuari); + mlx5_eq_cleanup(dev); + mlx5_disable_msix(dev); + mlx5_stop_health_poll(dev); + mlx5_cmd_teardown_hca(dev); + mlx5_pagealloc_stop(dev); + mlx5_reclaim_startup_pages(dev); + mlx5_pagealloc_cleanup(dev); + mlx5_cmd_cleanup(dev); + iounmap(dev->iseg); + pci_clear_master(dev->pdev); + release_bar(dev->pdev); + pci_disable_device(dev->pdev); + debugfs_remove(priv->dbg_root); +} +EXPORT_SYMBOL(mlx5_dev_cleanup); + +static int __init init(void) +{ + int err; + + mlx5_register_debugfs(); + mlx5_core_wq = create_singlethread_workqueue("mlx5_core_wq"); + if (!mlx5_core_wq) { + err = -ENOMEM; + goto err_debug; + } + mlx5_health_init(); + + return 0; + + mlx5_health_cleanup(); +err_debug: + mlx5_unregister_debugfs(); + return err; +} + +static void __exit cleanup(void) +{ + mlx5_health_cleanup(); + destroy_workqueue(mlx5_core_wq); + mlx5_unregister_debugfs(); +} + +module_init(init); +module_exit(cleanup); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mcg.c b/drivers/net/ethernet/mellanox/mlx5/core/mcg.c new file mode 100644 index 000000000000..44837640bd7c --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/mcg.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +struct mlx5_attach_mcg_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + __be32 rsvd; + u8 gid[16]; +}; + +struct mlx5_attach_mcg_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvf[8]; +}; + +struct mlx5_detach_mcg_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + __be32 rsvd; + u8 gid[16]; +}; + +struct mlx5_detach_mcg_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvf[8]; +}; + +int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn) +{ + struct mlx5_attach_mcg_mbox_in in; + struct mlx5_attach_mcg_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ATTACH_TO_MCG); + memcpy(in.gid, mgid, sizeof(*mgid)); + in.qpn = cpu_to_be32(qpn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_attach_mcg); + +int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn) +{ + struct mlx5_detach_mcg_mbox_in in; + struct mlx5_detach_mcg_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DETACH_FROM_MCG); + memcpy(in.gid, mgid, sizeof(*mgid)); + in.qpn = cpu_to_be32(qpn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_detach_mcg); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h new file mode 100644 index 000000000000..68b74e1ae1b0 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __MLX5_CORE_H__ +#define __MLX5_CORE_H__ + +#include +#include +#include + +extern int mlx5_core_debug_mask; + +#define mlx5_core_dbg(dev, format, arg...) \ +pr_debug("%s:%s:%d:(pid %d): " format, (dev)->priv.name, __func__, __LINE__, \ + current->pid, ##arg) + +#define mlx5_core_dbg_mask(dev, mask, format, arg...) \ +do { \ + if ((mask) & mlx5_core_debug_mask) \ + pr_debug("%s:%s:%d:(pid %d): " format, (dev)->priv.name, \ + __func__, __LINE__, current->pid, ##arg); \ +} while (0) + +#define mlx5_core_err(dev, format, arg...) \ +pr_err("%s:%s:%d:(pid %d): " format, (dev)->priv.name, __func__, __LINE__, \ + current->pid, ##arg) + +#define mlx5_core_warn(dev, format, arg...) \ +pr_warn("%s:%s:%d:(pid %d): " format, (dev)->priv.name, __func__, __LINE__, \ + current->pid, ##arg) + +enum { + MLX5_CMD_DATA, /* print command payload only */ + MLX5_CMD_TIME, /* print command execution time */ +}; + + +int mlx5_cmd_query_hca_cap(struct mlx5_core_dev *dev, + struct mlx5_caps *caps); +int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev); +int mlx5_cmd_init_hca(struct mlx5_core_dev *dev); +int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev); + +#endif /* __MLX5_CORE_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c new file mode 100644 index 000000000000..5b44e2e46daf --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "mlx5_core.h" + +int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + struct mlx5_create_mkey_mbox_in *in, int inlen) +{ + struct mlx5_create_mkey_mbox_out out; + int err; + u8 key; + + memset(&out, 0, sizeof(out)); + spin_lock(&dev->priv.mkey_lock); + key = dev->priv.mkey_key++; + spin_unlock(&dev->priv.mkey_lock); + in->seg.qpn_mkey7_0 |= cpu_to_be32(key); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_MKEY); + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + if (err) { + mlx5_core_dbg(dev, "cmd exec faile %d\n", err); + return err; + } + + if (out.hdr.status) { + mlx5_core_dbg(dev, "status %d\n", out.hdr.status); + return mlx5_cmd_status_to_err(&out.hdr); + } + + mr->key = mlx5_idx_to_mkey(be32_to_cpu(out.mkey) & 0xffffff) | key; + mlx5_core_dbg(dev, "out 0x%x, key 0x%x, mkey 0x%x\n", be32_to_cpu(out.mkey), key, mr->key); + + return err; +} +EXPORT_SYMBOL(mlx5_core_create_mkey); + +int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr) +{ + struct mlx5_destroy_mkey_mbox_in in; + struct mlx5_destroy_mkey_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_MKEY); + in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key)); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_destroy_mkey); + +int mlx5_core_query_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + struct mlx5_query_mkey_mbox_out *out, int outlen) +{ + struct mlx5_destroy_mkey_mbox_in in; + int err; + + memset(&in, 0, sizeof(in)); + memset(out, 0, outlen); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_MKEY); + in.mkey = cpu_to_be32(mlx5_mkey_to_idx(mr->key)); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); + if (err) + return err; + + if (out->hdr.status) + return mlx5_cmd_status_to_err(&out->hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_query_mkey); + +int mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + u32 *mkey) +{ + struct mlx5_query_special_ctxs_mbox_in in; + struct mlx5_query_special_ctxs_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + *mkey = be32_to_cpu(out.dump_fill_mkey); + + return err; +} +EXPORT_SYMBOL(mlx5_core_dump_fill_mkey); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c new file mode 100644 index 000000000000..f0bf46339b28 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +enum { + MLX5_PAGES_CANT_GIVE = 0, + MLX5_PAGES_GIVE = 1, + MLX5_PAGES_TAKE = 2 +}; + +struct mlx5_pages_req { + struct mlx5_core_dev *dev; + u32 func_id; + s16 npages; + struct work_struct work; +}; + +struct fw_page { + struct rb_node rb_node; + u64 addr; + struct page *page; + u16 func_id; +}; + +struct mlx5_query_pages_inbox { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_query_pages_outbox { + struct mlx5_outbox_hdr hdr; + u8 reserved[2]; + __be16 func_id; + __be16 init_pages; + __be16 num_pages; +}; + +struct mlx5_manage_pages_inbox { + struct mlx5_inbox_hdr hdr; + __be16 rsvd0; + __be16 func_id; + __be16 rsvd1; + __be16 num_entries; + u8 rsvd2[16]; + __be64 pas[0]; +}; + +struct mlx5_manage_pages_outbox { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[2]; + __be16 num_entries; + u8 rsvd1[20]; + __be64 pas[0]; +}; + +static int insert_page(struct mlx5_core_dev *dev, u64 addr, struct page *page, u16 func_id) +{ + struct rb_root *root = &dev->priv.page_root; + struct rb_node **new = &root->rb_node; + struct rb_node *parent = NULL; + struct fw_page *nfp; + struct fw_page *tfp; + + while (*new) { + parent = *new; + tfp = rb_entry(parent, struct fw_page, rb_node); + if (tfp->addr < addr) + new = &parent->rb_left; + else if (tfp->addr > addr) + new = &parent->rb_right; + else + return -EEXIST; + } + + nfp = kmalloc(sizeof(*nfp), GFP_KERNEL); + if (!nfp) + return -ENOMEM; + + nfp->addr = addr; + nfp->page = page; + nfp->func_id = func_id; + + rb_link_node(&nfp->rb_node, parent, new); + rb_insert_color(&nfp->rb_node, root); + + return 0; +} + +static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr) +{ + struct rb_root *root = &dev->priv.page_root; + struct rb_node *tmp = root->rb_node; + struct page *result = NULL; + struct fw_page *tfp; + + while (tmp) { + tfp = rb_entry(tmp, struct fw_page, rb_node); + if (tfp->addr < addr) { + tmp = tmp->rb_left; + } else if (tfp->addr > addr) { + tmp = tmp->rb_right; + } else { + rb_erase(&tfp->rb_node, root); + result = tfp->page; + kfree(tfp); + break; + } + } + + return result; +} + +static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, + s16 *pages, s16 *init_pages) +{ + struct mlx5_query_pages_inbox in; + struct mlx5_query_pages_outbox out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_PAGES); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + if (pages) + *pages = be16_to_cpu(out.num_pages); + if (init_pages) + *init_pages = be16_to_cpu(out.init_pages); + *func_id = be16_to_cpu(out.func_id); + + return err; +} + +static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, + int notify_fail) +{ + struct mlx5_manage_pages_inbox *in; + struct mlx5_manage_pages_outbox out; + struct page *page; + int inlen; + u64 addr; + int err; + int i; + + inlen = sizeof(*in) + npages * sizeof(in->pas[0]); + in = mlx5_vzalloc(inlen); + if (!in) { + mlx5_core_warn(dev, "vzalloc failed %d\n", inlen); + return -ENOMEM; + } + memset(&out, 0, sizeof(out)); + + for (i = 0; i < npages; i++) { + page = alloc_page(GFP_HIGHUSER); + if (!page) { + err = -ENOMEM; + mlx5_core_warn(dev, "failed to allocate page\n"); + goto out_alloc; + } + addr = dma_map_page(&dev->pdev->dev, page, 0, + PAGE_SIZE, DMA_BIDIRECTIONAL); + if (dma_mapping_error(&dev->pdev->dev, addr)) { + mlx5_core_warn(dev, "failed dma mapping page\n"); + __free_page(page); + err = -ENOMEM; + goto out_alloc; + } + err = insert_page(dev, addr, page, func_id); + if (err) { + mlx5_core_err(dev, "failed to track allocated page\n"); + dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + __free_page(page); + err = -ENOMEM; + goto out_alloc; + } + in->pas[i] = cpu_to_be64(addr); + } + + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); + in->hdr.opmod = cpu_to_be16(MLX5_PAGES_GIVE); + in->func_id = cpu_to_be16(func_id); + in->num_entries = cpu_to_be16(npages); + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + mlx5_core_dbg(dev, "err %d\n", err); + if (err) { + mlx5_core_warn(dev, "func_id 0x%x, npages %d, err %d\n", func_id, npages, err); + goto out_alloc; + } + dev->priv.fw_pages += npages; + + if (out.hdr.status) { + err = mlx5_cmd_status_to_err(&out.hdr); + if (err) { + mlx5_core_warn(dev, "func_id 0x%x, npages %d, status %d\n", func_id, npages, out.hdr.status); + goto out_alloc; + } + } + + mlx5_core_dbg(dev, "err %d\n", err); + + goto out_free; + +out_alloc: + if (notify_fail) { + memset(in, 0, inlen); + memset(&out, 0, sizeof(out)); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); + in->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE); + if (mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out))) + mlx5_core_warn(dev, "\n"); + } + for (i--; i >= 0; i--) { + addr = be64_to_cpu(in->pas[i]); + page = remove_page(dev, addr); + if (!page) { + mlx5_core_err(dev, "BUG: can't remove page at addr 0x%llx\n", + addr); + continue; + } + dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + __free_page(page); + } + +out_free: + mlx5_vfree(in); + return err; +} + +static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, + int *nclaimed) +{ + struct mlx5_manage_pages_inbox in; + struct mlx5_manage_pages_outbox *out; + struct page *page; + int num_claimed; + int outlen; + u64 addr; + int err; + int i; + + memset(&in, 0, sizeof(in)); + outlen = sizeof(*out) + npages * sizeof(out->pas[0]); + out = mlx5_vzalloc(outlen); + if (!out) + return -ENOMEM; + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); + in.hdr.opmod = cpu_to_be16(MLX5_PAGES_TAKE); + in.func_id = cpu_to_be16(func_id); + in.num_entries = cpu_to_be16(npages); + mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); + if (err) { + mlx5_core_err(dev, "failed recliaming pages\n"); + goto out_free; + } + dev->priv.fw_pages -= npages; + + if (out->hdr.status) { + err = mlx5_cmd_status_to_err(&out->hdr); + goto out_free; + } + + num_claimed = be16_to_cpu(out->num_entries); + if (nclaimed) + *nclaimed = num_claimed; + + for (i = 0; i < num_claimed; i++) { + addr = be64_to_cpu(out->pas[i]); + page = remove_page(dev, addr); + if (!page) { + mlx5_core_warn(dev, "FW reported unknown DMA address 0x%llx\n", addr); + } else { + dma_unmap_page(&dev->pdev->dev, addr, PAGE_SIZE, DMA_BIDIRECTIONAL); + __free_page(page); + } + } + +out_free: + mlx5_vfree(out); + return err; +} + +static void pages_work_handler(struct work_struct *work) +{ + struct mlx5_pages_req *req = container_of(work, struct mlx5_pages_req, work); + struct mlx5_core_dev *dev = req->dev; + int err = 0; + + if (req->npages < 0) + err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL); + else if (req->npages > 0) + err = give_pages(dev, req->func_id, req->npages, 1); + + if (err) + mlx5_core_warn(dev, "%s fail %d\n", req->npages < 0 ? + "reclaim" : "give", err); + + kfree(req); +} + +void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, + s16 npages) +{ + struct mlx5_pages_req *req; + + req = kzalloc(sizeof(*req), GFP_ATOMIC); + if (!req) { + mlx5_core_warn(dev, "failed to allocate pages request\n"); + return; + } + + req->dev = dev; + req->func_id = func_id; + req->npages = npages; + INIT_WORK(&req->work, pages_work_handler); + queue_work(dev->priv.pg_wq, &req->work); +} + +int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev) +{ + s16 uninitialized_var(init_pages); + u16 uninitialized_var(func_id); + int err; + + err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages); + if (err) + return err; + + mlx5_core_dbg(dev, "requested %d init pages for func_id 0x%x\n", init_pages, func_id); + + return give_pages(dev, func_id, init_pages, 0); +} + +static int optimal_reclaimed_pages(void) +{ + struct mlx5_cmd_prot_block *block; + struct mlx5_cmd_layout *lay; + int ret; + + ret = (sizeof(lay->in) + sizeof(block->data) - + sizeof(struct mlx5_manage_pages_outbox)) / 8; + + return ret; +} + +int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) +{ + unsigned long end = jiffies + msecs_to_jiffies(5000); + struct fw_page *fwp; + struct rb_node *p; + int err; + + do { + p = rb_first(&dev->priv.page_root); + if (p) { + fwp = rb_entry(p, struct fw_page, rb_node); + err = reclaim_pages(dev, fwp->func_id, optimal_reclaimed_pages(), NULL); + if (err) { + mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", err); + return err; + } + } + if (time_after(jiffies, end)) { + mlx5_core_warn(dev, "FW did not return all pages. giving up...\n"); + break; + } + } while (p); + + return 0; +} + +void mlx5_pagealloc_init(struct mlx5_core_dev *dev) +{ + dev->priv.page_root = RB_ROOT; +} + +void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev) +{ + /* nothing */ +} + +int mlx5_pagealloc_start(struct mlx5_core_dev *dev) +{ + dev->priv.pg_wq = create_singlethread_workqueue("mlx5_page_allocator"); + if (!dev->priv.pg_wq) + return -ENOMEM; + + return 0; +} + +void mlx5_pagealloc_stop(struct mlx5_core_dev *dev) +{ + destroy_workqueue(dev->priv.pg_wq); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pd.c b/drivers/net/ethernet/mellanox/mlx5/core/pd.c new file mode 100644 index 000000000000..790da5c4ca4f --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/pd.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "mlx5_core.h" + +struct mlx5_alloc_pd_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_alloc_pd_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 pdn; + u8 rsvd[4]; +}; + +struct mlx5_dealloc_pd_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 pdn; + u8 rsvd[4]; +}; + +struct mlx5_dealloc_pd_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +int mlx5_core_alloc_pd(struct mlx5_core_dev *dev, u32 *pdn) +{ + struct mlx5_alloc_pd_mbox_in in; + struct mlx5_alloc_pd_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ALLOC_PD); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + *pdn = be32_to_cpu(out.pdn) & 0xffffff; + return err; +} +EXPORT_SYMBOL(mlx5_core_alloc_pd); + +int mlx5_core_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn) +{ + struct mlx5_dealloc_pd_mbox_in in; + struct mlx5_dealloc_pd_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DEALLOC_PD); + in.pdn = cpu_to_be32(pdn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_dealloc_pd); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c new file mode 100644 index 000000000000..f6afe7b5a675 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "mlx5_core.h" + +int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, + int size_in, void *data_out, int size_out, + u16 reg_num, int arg, int write) +{ + struct mlx5_access_reg_mbox_in *in = NULL; + struct mlx5_access_reg_mbox_out *out = NULL; + int err = -ENOMEM; + + in = mlx5_vzalloc(sizeof(*in) + size_in); + if (!in) + return -ENOMEM; + + out = mlx5_vzalloc(sizeof(*out) + size_out); + if (!out) + goto ex1; + + memcpy(in->data, data_in, size_in); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ACCESS_REG); + in->hdr.opmod = cpu_to_be16(!write); + in->arg = cpu_to_be32(arg); + in->register_id = cpu_to_be16(reg_num); + err = mlx5_cmd_exec(dev, in, sizeof(*in) + size_in, out, + sizeof(out) + size_out); + if (err) + goto ex2; + + if (out->hdr.status) + err = mlx5_cmd_status_to_err(&out->hdr); + + if (!err) + memcpy(data_out, out->data, size_out); + +ex2: + mlx5_vfree(out); +ex1: + mlx5_vfree(in); + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_access_reg); + + +struct mlx5_reg_pcap { + u8 rsvd0; + u8 port_num; + u8 rsvd1[2]; + __be32 caps_127_96; + __be32 caps_95_64; + __be32 caps_63_32; + __be32 caps_31_0; +}; + +int mlx5_set_port_caps(struct mlx5_core_dev *dev, int port_num, u32 caps) +{ + struct mlx5_reg_pcap in; + struct mlx5_reg_pcap out; + int err; + + memset(&in, 0, sizeof(in)); + in.caps_127_96 = cpu_to_be32(caps); + in.port_num = port_num; + + err = mlx5_core_access_reg(dev, &in, sizeof(in), &out, + sizeof(out), MLX5_REG_PCAP, 0, 1); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_set_port_caps); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c new file mode 100644 index 000000000000..54faf8bfcaf4 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include +#include +#include +#include +#include + +#include "mlx5_core.h" + +void mlx5_qp_event(struct mlx5_core_dev *dev, u32 qpn, int event_type) +{ + struct mlx5_qp_table *table = &dev->priv.qp_table; + struct mlx5_core_qp *qp; + + spin_lock(&table->lock); + + qp = radix_tree_lookup(&table->tree, qpn); + if (qp) + atomic_inc(&qp->refcount); + + spin_unlock(&table->lock); + + if (!qp) { + mlx5_core_warn(dev, "Async event for bogus QP 0x%x\n", qpn); + return; + } + + qp->event(qp, event_type); + + if (atomic_dec_and_test(&qp->refcount)) + complete(&qp->free); +} + +int mlx5_core_create_qp(struct mlx5_core_dev *dev, + struct mlx5_core_qp *qp, + struct mlx5_create_qp_mbox_in *in, + int inlen) +{ + struct mlx5_qp_table *table = &dev->priv.qp_table; + struct mlx5_create_qp_mbox_out out; + struct mlx5_destroy_qp_mbox_in din; + struct mlx5_destroy_qp_mbox_out dout; + int err; + + memset(&dout, 0, sizeof(dout)); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_QP); + + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + if (err) { + mlx5_core_warn(dev, "ret %d", err); + return err; + } + + if (out.hdr.status) { + pr_warn("current num of QPs 0x%x\n", atomic_read(&dev->num_qps)); + return mlx5_cmd_status_to_err(&out.hdr); + } + + qp->qpn = be32_to_cpu(out.qpn) & 0xffffff; + mlx5_core_dbg(dev, "qpn = 0x%x\n", qp->qpn); + + spin_lock_irq(&table->lock); + err = radix_tree_insert(&table->tree, qp->qpn, qp); + spin_unlock_irq(&table->lock); + if (err) { + mlx5_core_warn(dev, "err %d", err); + goto err_cmd; + } + + err = mlx5_debug_qp_add(dev, qp); + if (err) + mlx5_core_dbg(dev, "failed adding QP 0x%x to debug file system\n", + qp->qpn); + + qp->pid = current->pid; + atomic_set(&qp->refcount, 1); + atomic_inc(&dev->num_qps); + init_completion(&qp->free); + + return 0; + +err_cmd: + memset(&din, 0, sizeof(din)); + memset(&dout, 0, sizeof(dout)); + din.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP); + din.qpn = cpu_to_be32(qp->qpn); + mlx5_cmd_exec(dev, &din, sizeof(din), &out, sizeof(dout)); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_create_qp); + +int mlx5_core_destroy_qp(struct mlx5_core_dev *dev, + struct mlx5_core_qp *qp) +{ + struct mlx5_destroy_qp_mbox_in in; + struct mlx5_destroy_qp_mbox_out out; + struct mlx5_qp_table *table = &dev->priv.qp_table; + unsigned long flags; + int err; + + mlx5_debug_qp_remove(dev, qp); + + spin_lock_irqsave(&table->lock, flags); + radix_tree_delete(&table->tree, qp->qpn); + spin_unlock_irqrestore(&table->lock, flags); + + if (atomic_dec_and_test(&qp->refcount)) + complete(&qp->free); + wait_for_completion(&qp->free); + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_QP); + in.qpn = cpu_to_be32(qp->qpn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + atomic_dec(&dev->num_qps); + return 0; +} +EXPORT_SYMBOL_GPL(mlx5_core_destroy_qp); + +int mlx5_core_qp_modify(struct mlx5_core_dev *dev, enum mlx5_qp_state cur_state, + enum mlx5_qp_state new_state, + struct mlx5_modify_qp_mbox_in *in, int sqd_event, + struct mlx5_core_qp *qp) +{ + static const u16 optab[MLX5_QP_NUM_STATE][MLX5_QP_NUM_STATE] = { + [MLX5_QP_STATE_RST] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_RST2INIT_QP, + }, + [MLX5_QP_STATE_INIT] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_INIT] = MLX5_CMD_OP_INIT2INIT_QP, + [MLX5_QP_STATE_RTR] = MLX5_CMD_OP_INIT2RTR_QP, + }, + [MLX5_QP_STATE_RTR] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTR2RTS_QP, + }, + [MLX5_QP_STATE_RTS] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_RTS2RTS_QP, + [MLX5_QP_STATE_SQD] = MLX5_CMD_OP_RTS2SQD_QP, + }, + [MLX5_QP_STATE_SQD] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_SQD2RTS_QP, + [MLX5_QP_STATE_SQD] = MLX5_CMD_OP_SQD2SQD_QP, + }, + [MLX5_QP_STATE_SQER] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + [MLX5_QP_STATE_RTS] = MLX5_CMD_OP_SQERR2RTS_QP, + }, + [MLX5_QP_STATE_ERR] = { + [MLX5_QP_STATE_RST] = MLX5_CMD_OP_2RST_QP, + [MLX5_QP_STATE_ERR] = MLX5_CMD_OP_2ERR_QP, + } + }; + + struct mlx5_modify_qp_mbox_out out; + int err = 0; + u16 op; + + if (cur_state >= MLX5_QP_NUM_STATE || new_state >= MLX5_QP_NUM_STATE || + !optab[cur_state][new_state]) + return -EINVAL; + + memset(&out, 0, sizeof(out)); + op = optab[cur_state][new_state]; + in->hdr.opcode = cpu_to_be16(op); + in->qpn = cpu_to_be32(qp->qpn); + err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out)); + if (err) + return err; + + return mlx5_cmd_status_to_err(&out.hdr); +} +EXPORT_SYMBOL_GPL(mlx5_core_qp_modify); + +void mlx5_init_qp_table(struct mlx5_core_dev *dev) +{ + struct mlx5_qp_table *table = &dev->priv.qp_table; + + spin_lock_init(&table->lock); + INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); + mlx5_qp_debugfs_init(dev); +} + +void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev) +{ + mlx5_qp_debugfs_cleanup(dev); +} + +int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp, + struct mlx5_query_qp_mbox_out *out, int outlen) +{ + struct mlx5_query_qp_mbox_in in; + int err; + + memset(&in, 0, sizeof(in)); + memset(out, 0, outlen); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_QP); + in.qpn = cpu_to_be32(qp->qpn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, outlen); + if (err) + return err; + + if (out->hdr.status) + return mlx5_cmd_status_to_err(&out->hdr); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_qp_query); + +int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn) +{ + struct mlx5_alloc_xrcd_mbox_in in; + struct mlx5_alloc_xrcd_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ALLOC_XRCD); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + else + *xrcdn = be32_to_cpu(out.xrcdn); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_xrcd_alloc); + +int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn) +{ + struct mlx5_dealloc_xrcd_mbox_in in; + struct mlx5_dealloc_xrcd_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DEALLOC_XRCD); + in.xrcdn = cpu_to_be32(xrcdn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL_GPL(mlx5_core_xrcd_dealloc); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/srq.c b/drivers/net/ethernet/mellanox/mlx5/core/srq.c new file mode 100644 index 000000000000..38bce93f8314 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/srq.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include "mlx5_core.h" + +void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type) +{ + struct mlx5_srq_table *table = &dev->priv.srq_table; + struct mlx5_core_srq *srq; + + spin_lock(&table->lock); + + srq = radix_tree_lookup(&table->tree, srqn); + if (srq) + atomic_inc(&srq->refcount); + + spin_unlock(&table->lock); + + if (!srq) { + mlx5_core_warn(dev, "Async event for bogus SRQ 0x%08x\n", srqn); + return; + } + + srq->event(srq, event_type); + + if (atomic_dec_and_test(&srq->refcount)) + complete(&srq->free); +} + +struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn) +{ + struct mlx5_srq_table *table = &dev->priv.srq_table; + struct mlx5_core_srq *srq; + + spin_lock(&table->lock); + + srq = radix_tree_lookup(&table->tree, srqn); + if (srq) + atomic_inc(&srq->refcount); + + spin_unlock(&table->lock); + + return srq; +} +EXPORT_SYMBOL(mlx5_core_get_srq); + +int mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + struct mlx5_create_srq_mbox_in *in, int inlen) +{ + struct mlx5_create_srq_mbox_out out; + struct mlx5_srq_table *table = &dev->priv.srq_table; + struct mlx5_destroy_srq_mbox_in din; + struct mlx5_destroy_srq_mbox_out dout; + int err; + + memset(&out, 0, sizeof(out)); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_SRQ); + err = mlx5_cmd_exec(dev, in, inlen, &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + srq->srqn = be32_to_cpu(out.srqn) & 0xffffff; + + atomic_set(&srq->refcount, 1); + init_completion(&srq->free); + + spin_lock_irq(&table->lock); + err = radix_tree_insert(&table->tree, srq->srqn, srq); + spin_unlock_irq(&table->lock); + if (err) { + mlx5_core_warn(dev, "err %d, srqn 0x%x\n", err, srq->srqn); + goto err_cmd; + } + + return 0; + +err_cmd: + memset(&din, 0, sizeof(din)); + memset(&dout, 0, sizeof(dout)); + din.srqn = cpu_to_be32(srq->srqn); + din.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ); + mlx5_cmd_exec(dev, &din, sizeof(din), &dout, sizeof(dout)); + return err; +} +EXPORT_SYMBOL(mlx5_core_create_srq); + +int mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq) +{ + struct mlx5_destroy_srq_mbox_in in; + struct mlx5_destroy_srq_mbox_out out; + struct mlx5_srq_table *table = &dev->priv.srq_table; + struct mlx5_core_srq *tmp; + int err; + + spin_lock_irq(&table->lock); + tmp = radix_tree_delete(&table->tree, srq->srqn); + spin_unlock_irq(&table->lock); + if (!tmp) { + mlx5_core_warn(dev, "srq 0x%x not found in tree\n", srq->srqn); + return -EINVAL; + } + if (tmp != srq) { + mlx5_core_warn(dev, "corruption on srqn 0x%x\n", srq->srqn); + return -EINVAL; + } + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ); + in.srqn = cpu_to_be32(srq->srqn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + if (atomic_dec_and_test(&srq->refcount)) + complete(&srq->free); + wait_for_completion(&srq->free); + + return 0; +} +EXPORT_SYMBOL(mlx5_core_destroy_srq); + +int mlx5_core_query_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + struct mlx5_query_srq_mbox_out *out) +{ + struct mlx5_query_srq_mbox_in in; + int err; + + memset(&in, 0, sizeof(in)); + memset(out, 0, sizeof(*out)); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SRQ); + in.srqn = cpu_to_be32(srq->srqn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), out, sizeof(*out)); + if (err) + return err; + + if (out->hdr.status) + return mlx5_cmd_status_to_err(&out->hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_query_srq); + +int mlx5_core_arm_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + u16 lwm, int is_srq) +{ + struct mlx5_arm_srq_mbox_in in; + struct mlx5_arm_srq_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ARM_RQ); + in.hdr.opmod = cpu_to_be16(!!is_srq); + in.srqn = cpu_to_be32(srq->srqn); + in.lwm = cpu_to_be16(lwm); + + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + return err; + + if (out.hdr.status) + return mlx5_cmd_status_to_err(&out.hdr); + + return err; +} +EXPORT_SYMBOL(mlx5_core_arm_srq); + +void mlx5_init_srq_table(struct mlx5_core_dev *dev) +{ + struct mlx5_srq_table *table = &dev->priv.srq_table; + + spin_lock_init(&table->lock); + INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); +} + +void mlx5_cleanup_srq_table(struct mlx5_core_dev *dev) +{ + /* nothing */ +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/uar.c b/drivers/net/ethernet/mellanox/mlx5/core/uar.c new file mode 100644 index 000000000000..71d4a3937200 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/uar.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include "mlx5_core.h" + +enum { + NUM_DRIVER_UARS = 4, + NUM_LOW_LAT_UUARS = 4, +}; + + +struct mlx5_alloc_uar_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_alloc_uar_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 uarn; + u8 rsvd[4]; +}; + +struct mlx5_free_uar_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 uarn; + u8 rsvd[4]; +}; + +struct mlx5_free_uar_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +int mlx5_cmd_alloc_uar(struct mlx5_core_dev *dev, u32 *uarn) +{ + struct mlx5_alloc_uar_mbox_in in; + struct mlx5_alloc_uar_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + memset(&out, 0, sizeof(out)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ALLOC_UAR); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + goto ex; + + if (out.hdr.status) { + err = mlx5_cmd_status_to_err(&out.hdr); + goto ex; + } + + *uarn = be32_to_cpu(out.uarn) & 0xffffff; + +ex: + return err; +} +EXPORT_SYMBOL(mlx5_cmd_alloc_uar); + +int mlx5_cmd_free_uar(struct mlx5_core_dev *dev, u32 uarn) +{ + struct mlx5_free_uar_mbox_in in; + struct mlx5_free_uar_mbox_out out; + int err; + + memset(&in, 0, sizeof(in)); + in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DEALLOC_UAR); + in.uarn = cpu_to_be32(uarn); + err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); + if (err) + goto ex; + + if (out.hdr.status) + err = mlx5_cmd_status_to_err(&out.hdr); + +ex: + return err; +} +EXPORT_SYMBOL(mlx5_cmd_free_uar); + +static int need_uuar_lock(int uuarn) +{ + int tot_uuars = NUM_DRIVER_UARS * MLX5_BF_REGS_PER_PAGE; + + if (uuarn == 0 || tot_uuars - NUM_LOW_LAT_UUARS) + return 0; + + return 1; +} + +int mlx5_alloc_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari) +{ + int tot_uuars = NUM_DRIVER_UARS * MLX5_BF_REGS_PER_PAGE; + struct mlx5_bf *bf; + phys_addr_t addr; + int err; + int i; + + uuari->num_uars = NUM_DRIVER_UARS; + uuari->num_low_latency_uuars = NUM_LOW_LAT_UUARS; + + mutex_init(&uuari->lock); + uuari->uars = kcalloc(uuari->num_uars, sizeof(*uuari->uars), GFP_KERNEL); + if (!uuari->uars) + return -ENOMEM; + + uuari->bfs = kcalloc(tot_uuars, sizeof(*uuari->bfs), GFP_KERNEL); + if (!uuari->bfs) { + err = -ENOMEM; + goto out_uars; + } + + uuari->bitmap = kcalloc(BITS_TO_LONGS(tot_uuars), sizeof(*uuari->bitmap), + GFP_KERNEL); + if (!uuari->bitmap) { + err = -ENOMEM; + goto out_bfs; + } + + uuari->count = kcalloc(tot_uuars, sizeof(*uuari->count), GFP_KERNEL); + if (!uuari->count) { + err = -ENOMEM; + goto out_bitmap; + } + + for (i = 0; i < uuari->num_uars; i++) { + err = mlx5_cmd_alloc_uar(dev, &uuari->uars[i].index); + if (err) + goto out_count; + + addr = dev->iseg_base + ((phys_addr_t)(uuari->uars[i].index) << PAGE_SHIFT); + uuari->uars[i].map = ioremap(addr, PAGE_SIZE); + if (!uuari->uars[i].map) { + mlx5_cmd_free_uar(dev, uuari->uars[i].index); + goto out_count; + } + mlx5_core_dbg(dev, "allocated uar index 0x%x, mmaped at %p\n", + uuari->uars[i].index, uuari->uars[i].map); + } + + for (i = 0; i < tot_uuars; i++) { + bf = &uuari->bfs[i]; + + bf->buf_size = dev->caps.bf_reg_size / 2; + bf->uar = &uuari->uars[i / MLX5_BF_REGS_PER_PAGE]; + bf->regreg = uuari->uars[i / MLX5_BF_REGS_PER_PAGE].map; + bf->reg = NULL; /* Add WC support */ + bf->offset = (i % MLX5_BF_REGS_PER_PAGE) * dev->caps.bf_reg_size + + MLX5_BF_OFFSET; + bf->need_lock = need_uuar_lock(i); + spin_lock_init(&bf->lock); + spin_lock_init(&bf->lock32); + bf->uuarn = i; + } + + return 0; + +out_count: + for (i--; i >= 0; i--) { + iounmap(uuari->uars[i].map); + mlx5_cmd_free_uar(dev, uuari->uars[i].index); + } + kfree(uuari->count); + +out_bitmap: + kfree(uuari->bitmap); + +out_bfs: + kfree(uuari->bfs); + +out_uars: + kfree(uuari->uars); + return err; +} + +int mlx5_free_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari) +{ + int i = uuari->num_uars; + + for (i--; i >= 0; i--) { + iounmap(uuari->uars[i].map); + mlx5_cmd_free_uar(dev, uuari->uars[i].index); + } + + kfree(uuari->count); + kfree(uuari->bitmap); + kfree(uuari->bfs); + kfree(uuari->uars); + + return 0; +} diff --git a/include/linux/mlx5/cmd.h b/include/linux/mlx5/cmd.h new file mode 100644 index 000000000000..2826a4b6071e --- /dev/null +++ b/include/linux/mlx5/cmd.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_CMD_H +#define MLX5_CMD_H + +#include + +struct manage_pages_layout { + u64 ptr; + u32 reserved; + u16 num_entries; + u16 func_id; +}; + + +struct mlx5_cmd_alloc_uar_imm_out { + u32 rsvd[3]; + u32 uarn; +}; + +#endif /* MLX5_CMD_H */ diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h new file mode 100644 index 000000000000..3db67f73d96d --- /dev/null +++ b/include/linux/mlx5/cq.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_CORE_CQ_H +#define MLX5_CORE_CQ_H + +#include +#include + + +struct mlx5_core_cq { + u32 cqn; + int cqe_sz; + __be32 *set_ci_db; + __be32 *arm_db; + atomic_t refcount; + struct completion free; + unsigned vector; + int irqn; + void (*comp) (struct mlx5_core_cq *); + void (*event) (struct mlx5_core_cq *, enum mlx5_event); + struct mlx5_uar *uar; + u32 cons_index; + unsigned arm_sn; + struct mlx5_rsc_debug *dbg; + int pid; +}; + + +enum { + MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR = 0x01, + MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR = 0x02, + MLX5_CQE_SYNDROME_LOCAL_PROT_ERR = 0x04, + MLX5_CQE_SYNDROME_WR_FLUSH_ERR = 0x05, + MLX5_CQE_SYNDROME_MW_BIND_ERR = 0x06, + MLX5_CQE_SYNDROME_BAD_RESP_ERR = 0x10, + MLX5_CQE_SYNDROME_LOCAL_ACCESS_ERR = 0x11, + MLX5_CQE_SYNDROME_REMOTE_INVAL_REQ_ERR = 0x12, + MLX5_CQE_SYNDROME_REMOTE_ACCESS_ERR = 0x13, + MLX5_CQE_SYNDROME_REMOTE_OP_ERR = 0x14, + MLX5_CQE_SYNDROME_TRANSPORT_RETRY_EXC_ERR = 0x15, + MLX5_CQE_SYNDROME_RNR_RETRY_EXC_ERR = 0x16, + MLX5_CQE_SYNDROME_REMOTE_ABORTED_ERR = 0x22, +}; + +enum { + MLX5_CQE_OWNER_MASK = 1, + MLX5_CQE_REQ = 0, + MLX5_CQE_RESP_WR_IMM = 1, + MLX5_CQE_RESP_SEND = 2, + MLX5_CQE_RESP_SEND_IMM = 3, + MLX5_CQE_RESP_SEND_INV = 4, + MLX5_CQE_RESIZE_CQ = 0xff, /* TBD */ + MLX5_CQE_REQ_ERR = 13, + MLX5_CQE_RESP_ERR = 14, +}; + +enum { + MLX5_CQ_MODIFY_RESEIZE = 0, + MLX5_CQ_MODIFY_MODER = 1, + MLX5_CQ_MODIFY_MAPPING = 2, +}; + +struct mlx5_cq_modify_params { + int type; + union { + struct { + u32 page_offset; + u8 log_cq_size; + } resize; + + struct { + } moder; + + struct { + } mapping; + } params; +}; + +enum { + CQE_SIZE_64 = 0, + CQE_SIZE_128 = 1, +}; + +static inline int cqe_sz_to_mlx_sz(u8 size) +{ + return size == 64 ? CQE_SIZE_64 : CQE_SIZE_128; +} + +static inline void mlx5_cq_set_ci(struct mlx5_core_cq *cq) +{ + *cq->set_ci_db = cpu_to_be32(cq->cons_index & 0xffffff); +} + +enum { + MLX5_CQ_DB_REQ_NOT_SOL = 1 << 24, + MLX5_CQ_DB_REQ_NOT = 0 << 24 +}; + +static inline void mlx5_cq_arm(struct mlx5_core_cq *cq, u32 cmd, + void __iomem *uar_page, + spinlock_t *doorbell_lock) +{ + __be32 doorbell[2]; + u32 sn; + u32 ci; + + sn = cq->arm_sn & 3; + ci = cq->cons_index & 0xffffff; + + *cq->arm_db = cpu_to_be32(sn << 28 | cmd | ci); + + /* Make sure that the doorbell record in host memory is + * written before ringing the doorbell via PCI MMIO. + */ + wmb(); + + doorbell[0] = cpu_to_be32(sn << 28 | cmd | ci); + doorbell[1] = cpu_to_be32(cq->cqn); + + mlx5_write64(doorbell, uar_page + MLX5_CQ_DOORBELL, doorbell_lock); +} + +int mlx5_init_cq_table(struct mlx5_core_dev *dev); +void mlx5_cleanup_cq_table(struct mlx5_core_dev *dev); +int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + struct mlx5_create_cq_mbox_in *in, int inlen); +int mlx5_core_destroy_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); +int mlx5_core_query_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + struct mlx5_query_cq_mbox_out *out); +int mlx5_core_modify_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, + int type, struct mlx5_cq_modify_params *params); +int mlx5_debug_cq_add(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); +void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq); + +#endif /* MLX5_CORE_CQ_H */ diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h new file mode 100644 index 000000000000..51390915e538 --- /dev/null +++ b/include/linux/mlx5/device.h @@ -0,0 +1,893 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_DEVICE_H +#define MLX5_DEVICE_H + +#include +#include + +#if defined(__LITTLE_ENDIAN) +#define MLX5_SET_HOST_ENDIANNESS 0 +#elif defined(__BIG_ENDIAN) +#define MLX5_SET_HOST_ENDIANNESS 0x80 +#else +#error Host endianness not defined +#endif + +enum { + MLX5_MAX_COMMANDS = 32, + MLX5_CMD_DATA_BLOCK_SIZE = 512, + MLX5_PCI_CMD_XPORT = 7, +}; + +enum { + MLX5_EXTENDED_UD_AV = 0x80000000, +}; + +enum { + MLX5_CQ_STATE_ARMED = 9, + MLX5_CQ_STATE_ALWAYS_ARMED = 0xb, + MLX5_CQ_STATE_FIRED = 0xa, +}; + +enum { + MLX5_STAT_RATE_OFFSET = 5, +}; + +enum { + MLX5_INLINE_SEG = 0x80000000, +}; + +enum { + MLX5_PERM_LOCAL_READ = 1 << 2, + MLX5_PERM_LOCAL_WRITE = 1 << 3, + MLX5_PERM_REMOTE_READ = 1 << 4, + MLX5_PERM_REMOTE_WRITE = 1 << 5, + MLX5_PERM_ATOMIC = 1 << 6, + MLX5_PERM_UMR_EN = 1 << 7, +}; + +enum { + MLX5_PCIE_CTRL_SMALL_FENCE = 1 << 0, + MLX5_PCIE_CTRL_RELAXED_ORDERING = 1 << 2, + MLX5_PCIE_CTRL_NO_SNOOP = 1 << 3, + MLX5_PCIE_CTRL_TLP_PROCE_EN = 1 << 6, + MLX5_PCIE_CTRL_TPH_MASK = 3 << 4, +}; + +enum { + MLX5_ACCESS_MODE_PA = 0, + MLX5_ACCESS_MODE_MTT = 1, + MLX5_ACCESS_MODE_KLM = 2 +}; + +enum { + MLX5_MKEY_REMOTE_INVAL = 1 << 24, + MLX5_MKEY_FLAG_SYNC_UMR = 1 << 29, + MLX5_MKEY_BSF_EN = 1 << 30, + MLX5_MKEY_LEN64 = 1 << 31, +}; + +enum { + MLX5_EN_RD = (u64)1, + MLX5_EN_WR = (u64)2 +}; + +enum { + MLX5_BF_REGS_PER_PAGE = 4, + MLX5_MAX_UAR_PAGES = 1 << 8, + MLX5_MAX_UUARS = MLX5_MAX_UAR_PAGES * MLX5_BF_REGS_PER_PAGE, +}; + +enum { + MLX5_MKEY_MASK_LEN = 1ull << 0, + MLX5_MKEY_MASK_PAGE_SIZE = 1ull << 1, + MLX5_MKEY_MASK_START_ADDR = 1ull << 6, + MLX5_MKEY_MASK_PD = 1ull << 7, + MLX5_MKEY_MASK_EN_RINVAL = 1ull << 8, + MLX5_MKEY_MASK_BSF_EN = 1ull << 12, + MLX5_MKEY_MASK_KEY = 1ull << 13, + MLX5_MKEY_MASK_QPN = 1ull << 14, + MLX5_MKEY_MASK_LR = 1ull << 17, + MLX5_MKEY_MASK_LW = 1ull << 18, + MLX5_MKEY_MASK_RR = 1ull << 19, + MLX5_MKEY_MASK_RW = 1ull << 20, + MLX5_MKEY_MASK_A = 1ull << 21, + MLX5_MKEY_MASK_SMALL_FENCE = 1ull << 23, + MLX5_MKEY_MASK_FREE = 1ull << 29, +}; + +enum mlx5_event { + MLX5_EVENT_TYPE_COMP = 0x0, + + MLX5_EVENT_TYPE_PATH_MIG = 0x01, + MLX5_EVENT_TYPE_COMM_EST = 0x02, + MLX5_EVENT_TYPE_SQ_DRAINED = 0x03, + MLX5_EVENT_TYPE_SRQ_LAST_WQE = 0x13, + MLX5_EVENT_TYPE_SRQ_RQ_LIMIT = 0x14, + + MLX5_EVENT_TYPE_CQ_ERROR = 0x04, + MLX5_EVENT_TYPE_WQ_CATAS_ERROR = 0x05, + MLX5_EVENT_TYPE_PATH_MIG_FAILED = 0x07, + MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR = 0x10, + MLX5_EVENT_TYPE_WQ_ACCESS_ERROR = 0x11, + MLX5_EVENT_TYPE_SRQ_CATAS_ERROR = 0x12, + + MLX5_EVENT_TYPE_INTERNAL_ERROR = 0x08, + MLX5_EVENT_TYPE_PORT_CHANGE = 0x09, + MLX5_EVENT_TYPE_GPIO_EVENT = 0x15, + MLX5_EVENT_TYPE_REMOTE_CONFIG = 0x19, + + MLX5_EVENT_TYPE_DB_BF_CONGESTION = 0x1a, + MLX5_EVENT_TYPE_STALL_EVENT = 0x1b, + + MLX5_EVENT_TYPE_CMD = 0x0a, + MLX5_EVENT_TYPE_PAGE_REQUEST = 0xb, +}; + +enum { + MLX5_PORT_CHANGE_SUBTYPE_DOWN = 1, + MLX5_PORT_CHANGE_SUBTYPE_ACTIVE = 4, + MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED = 5, + MLX5_PORT_CHANGE_SUBTYPE_LID = 6, + MLX5_PORT_CHANGE_SUBTYPE_PKEY = 7, + MLX5_PORT_CHANGE_SUBTYPE_GUID = 8, + MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG = 9, +}; + +enum { + MLX5_DEV_CAP_FLAG_RC = 1LL << 0, + MLX5_DEV_CAP_FLAG_UC = 1LL << 1, + MLX5_DEV_CAP_FLAG_UD = 1LL << 2, + MLX5_DEV_CAP_FLAG_XRC = 1LL << 3, + MLX5_DEV_CAP_FLAG_SRQ = 1LL << 6, + MLX5_DEV_CAP_FLAG_BAD_PKEY_CNTR = 1LL << 8, + MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1LL << 9, + MLX5_DEV_CAP_FLAG_APM = 1LL << 17, + MLX5_DEV_CAP_FLAG_ATOMIC = 1LL << 18, + MLX5_DEV_CAP_FLAG_ON_DMND_PG = 1LL << 24, + MLX5_DEV_CAP_FLAG_RESIZE_SRQ = 1LL << 32, + MLX5_DEV_CAP_FLAG_REMOTE_FENCE = 1LL << 38, + MLX5_DEV_CAP_FLAG_TLP_HINTS = 1LL << 39, + MLX5_DEV_CAP_FLAG_SIG_HAND_OVER = 1LL << 40, + MLX5_DEV_CAP_FLAG_DCT = 1LL << 41, + MLX5_DEV_CAP_FLAG_CMDIF_CSUM = 1LL << 46, +}; + +enum { + MLX5_OPCODE_NOP = 0x00, + MLX5_OPCODE_SEND_INVAL = 0x01, + MLX5_OPCODE_RDMA_WRITE = 0x08, + MLX5_OPCODE_RDMA_WRITE_IMM = 0x09, + MLX5_OPCODE_SEND = 0x0a, + MLX5_OPCODE_SEND_IMM = 0x0b, + MLX5_OPCODE_RDMA_READ = 0x10, + MLX5_OPCODE_ATOMIC_CS = 0x11, + MLX5_OPCODE_ATOMIC_FA = 0x12, + MLX5_OPCODE_ATOMIC_MASKED_CS = 0x14, + MLX5_OPCODE_ATOMIC_MASKED_FA = 0x15, + MLX5_OPCODE_BIND_MW = 0x18, + MLX5_OPCODE_CONFIG_CMD = 0x1f, + + MLX5_RECV_OPCODE_RDMA_WRITE_IMM = 0x00, + MLX5_RECV_OPCODE_SEND = 0x01, + MLX5_RECV_OPCODE_SEND_IMM = 0x02, + MLX5_RECV_OPCODE_SEND_INVAL = 0x03, + + MLX5_CQE_OPCODE_ERROR = 0x1e, + MLX5_CQE_OPCODE_RESIZE = 0x16, + + MLX5_OPCODE_SET_PSV = 0x20, + MLX5_OPCODE_GET_PSV = 0x21, + MLX5_OPCODE_CHECK_PSV = 0x22, + MLX5_OPCODE_RGET_PSV = 0x26, + MLX5_OPCODE_RCHECK_PSV = 0x27, + + MLX5_OPCODE_UMR = 0x25, + +}; + +enum { + MLX5_SET_PORT_RESET_QKEY = 0, + MLX5_SET_PORT_GUID0 = 16, + MLX5_SET_PORT_NODE_GUID = 17, + MLX5_SET_PORT_SYS_GUID = 18, + MLX5_SET_PORT_GID_TABLE = 19, + MLX5_SET_PORT_PKEY_TABLE = 20, +}; + +enum { + MLX5_MAX_PAGE_SHIFT = 31 +}; + +struct mlx5_inbox_hdr { + __be16 opcode; + u8 rsvd[4]; + __be16 opmod; +}; + +struct mlx5_outbox_hdr { + u8 status; + u8 rsvd[3]; + __be32 syndrome; +}; + +struct mlx5_cmd_query_adapter_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_cmd_query_adapter_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[24]; + u8 intapin; + u8 rsvd1[13]; + __be16 vsd_vendor_id; + u8 vsd[208]; + u8 vsd_psid[16]; +}; + +struct mlx5_hca_cap { + u8 rsvd1[16]; + u8 log_max_srq_sz; + u8 log_max_qp_sz; + u8 rsvd2; + u8 log_max_qp; + u8 log_max_strq_sz; + u8 log_max_srqs; + u8 rsvd4[2]; + u8 rsvd5; + u8 log_max_cq_sz; + u8 rsvd6; + u8 log_max_cq; + u8 log_max_eq_sz; + u8 log_max_mkey; + u8 rsvd7; + u8 log_max_eq; + u8 max_indirection; + u8 log_max_mrw_sz; + u8 log_max_bsf_list_sz; + u8 log_max_klm_list_sz; + u8 rsvd_8_0; + u8 log_max_ra_req_dc; + u8 rsvd_8_1; + u8 log_max_ra_res_dc; + u8 rsvd9; + u8 log_max_ra_req_qp; + u8 rsvd10; + u8 log_max_ra_res_qp; + u8 rsvd11[4]; + __be16 max_qp_count; + __be16 rsvd12; + u8 rsvd13; + u8 local_ca_ack_delay; + u8 rsvd14; + u8 num_ports; + u8 log_max_msg; + u8 rsvd15[3]; + __be16 stat_rate_support; + u8 rsvd16[2]; + __be64 flags; + u8 rsvd17; + u8 uar_sz; + u8 rsvd18; + u8 log_pg_sz; + __be16 bf_log_bf_reg_size; + u8 rsvd19[4]; + __be16 max_desc_sz_sq; + u8 rsvd20[2]; + __be16 max_desc_sz_rq; + u8 rsvd21[2]; + __be16 max_desc_sz_sq_dc; + u8 rsvd22[4]; + __be16 max_qp_mcg; + u8 rsvd23; + u8 log_max_mcg; + u8 rsvd24; + u8 log_max_pd; + u8 rsvd25; + u8 log_max_xrcd; + u8 rsvd26[40]; + __be32 uar_page_sz; + u8 rsvd27[28]; + u8 log_msx_atomic_size_qp; + u8 rsvd28[2]; + u8 log_msx_atomic_size_dc; + u8 rsvd29[76]; +}; + + +struct mlx5_cmd_query_hca_cap_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + + +struct mlx5_cmd_query_hca_cap_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; + struct mlx5_hca_cap hca_cap; +}; + + +struct mlx5_cmd_set_hca_cap_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; + struct mlx5_hca_cap hca_cap; +}; + + +struct mlx5_cmd_set_hca_cap_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; +}; + + +struct mlx5_cmd_init_hca_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[2]; + __be16 profile; + u8 rsvd1[4]; +}; + +struct mlx5_cmd_init_hca_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_cmd_teardown_hca_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[2]; + __be16 profile; + u8 rsvd1[4]; +}; + +struct mlx5_cmd_teardown_hca_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_cmd_layout { + u8 type; + u8 rsvd0[3]; + __be32 inlen; + __be64 in_ptr; + __be32 in[4]; + __be32 out[4]; + __be64 out_ptr; + __be32 outlen; + u8 token; + u8 sig; + u8 rsvd1; + u8 status_own; +}; + + +struct health_buffer { + __be32 assert_var[5]; + __be32 rsvd0[3]; + __be32 assert_exit_ptr; + __be32 assert_callra; + __be32 rsvd1[2]; + __be32 fw_ver; + __be32 hw_id; + __be32 rsvd2; + u8 irisc_index; + u8 synd; + __be16 ext_sync; +}; + +struct mlx5_init_seg { + __be32 fw_rev; + __be32 cmdif_rev_fw_sub; + __be32 rsvd0[2]; + __be32 cmdq_addr_h; + __be32 cmdq_addr_l_sz; + __be32 cmd_dbell; + __be32 rsvd1[121]; + struct health_buffer health; + __be32 rsvd2[884]; + __be32 health_counter; + __be32 rsvd3[1023]; + __be64 ieee1588_clk; + __be32 ieee1588_clk_type; + __be32 clr_intx; +}; + +struct mlx5_eqe_comp { + __be32 reserved[6]; + __be32 cqn; +}; + +struct mlx5_eqe_qp_srq { + __be32 reserved[6]; + __be32 qp_srq_n; +}; + +struct mlx5_eqe_cq_err { + __be32 cqn; + u8 reserved1[7]; + u8 syndrome; +}; + +struct mlx5_eqe_dropped_packet { +}; + +struct mlx5_eqe_port_state { + u8 reserved0[8]; + u8 port; +}; + +struct mlx5_eqe_gpio { + __be32 reserved0[2]; + __be64 gpio_event; +}; + +struct mlx5_eqe_congestion { + u8 type; + u8 rsvd0; + u8 congestion_level; +}; + +struct mlx5_eqe_stall_vl { + u8 rsvd0[3]; + u8 port_vl; +}; + +struct mlx5_eqe_cmd { + __be32 vector; + __be32 rsvd[6]; +}; + +struct mlx5_eqe_page_req { + u8 rsvd0[2]; + __be16 func_id; + u8 rsvd1[2]; + __be16 num_pages; + __be32 rsvd2[5]; +}; + +union ev_data { + __be32 raw[7]; + struct mlx5_eqe_cmd cmd; + struct mlx5_eqe_comp comp; + struct mlx5_eqe_qp_srq qp_srq; + struct mlx5_eqe_cq_err cq_err; + struct mlx5_eqe_dropped_packet dp; + struct mlx5_eqe_port_state port; + struct mlx5_eqe_gpio gpio; + struct mlx5_eqe_congestion cong; + struct mlx5_eqe_stall_vl stall_vl; + struct mlx5_eqe_page_req req_pages; +} __packed; + +struct mlx5_eqe { + u8 rsvd0; + u8 type; + u8 rsvd1; + u8 sub_type; + __be32 rsvd2[7]; + union ev_data data; + __be16 rsvd3; + u8 signature; + u8 owner; +} __packed; + +struct mlx5_cmd_prot_block { + u8 data[MLX5_CMD_DATA_BLOCK_SIZE]; + u8 rsvd0[48]; + __be64 next; + __be32 block_num; + u8 rsvd1; + u8 token; + u8 ctrl_sig; + u8 sig; +}; + +struct mlx5_err_cqe { + u8 rsvd0[32]; + __be32 srqn; + u8 rsvd1[18]; + u8 vendor_err_synd; + u8 syndrome; + __be32 s_wqe_opcode_qpn; + __be16 wqe_counter; + u8 signature; + u8 op_own; +}; + +struct mlx5_cqe64 { + u8 rsvd0[17]; + u8 ml_path; + u8 rsvd20[4]; + __be16 slid; + __be32 flags_rqpn; + u8 rsvd28[4]; + __be32 srqn; + __be32 imm_inval_pkey; + u8 rsvd40[4]; + __be32 byte_cnt; + __be64 timestamp; + __be32 sop_drop_qpn; + __be16 wqe_counter; + u8 signature; + u8 op_own; +}; + +struct mlx5_wqe_srq_next_seg { + u8 rsvd0[2]; + __be16 next_wqe_index; + u8 signature; + u8 rsvd1[11]; +}; + +union mlx5_ext_cqe { + struct ib_grh grh; + u8 inl[64]; +}; + +struct mlx5_cqe128 { + union mlx5_ext_cqe inl_grh; + struct mlx5_cqe64 cqe64; +}; + +struct mlx5_srq_ctx { + u8 state_log_sz; + u8 rsvd0[3]; + __be32 flags_xrcd; + __be32 pgoff_cqn; + u8 rsvd1[4]; + u8 log_pg_sz; + u8 rsvd2[7]; + __be32 pd; + __be16 lwm; + __be16 wqe_cnt; + u8 rsvd3[8]; + __be64 db_record; +}; + +struct mlx5_create_srq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 input_srqn; + u8 rsvd0[4]; + struct mlx5_srq_ctx ctx; + u8 rsvd1[208]; + __be64 pas[0]; +}; + +struct mlx5_create_srq_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 srqn; + u8 rsvd[4]; +}; + +struct mlx5_destroy_srq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 srqn; + u8 rsvd[4]; +}; + +struct mlx5_destroy_srq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_query_srq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 srqn; + u8 rsvd0[4]; +}; + +struct mlx5_query_srq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; + struct mlx5_srq_ctx ctx; + u8 rsvd1[32]; + __be64 pas[0]; +}; + +struct mlx5_arm_srq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 srqn; + __be16 rsvd; + __be16 lwm; +}; + +struct mlx5_arm_srq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_cq_context { + u8 status; + u8 cqe_sz_flags; + u8 st; + u8 rsvd3; + u8 rsvd4[6]; + __be16 page_offset; + __be32 log_sz_usr_page; + __be16 cq_period; + __be16 cq_max_count; + __be16 rsvd20; + __be16 c_eqn; + u8 log_pg_sz; + u8 rsvd25[7]; + __be32 last_notified_index; + __be32 solicit_producer_index; + __be32 consumer_counter; + __be32 producer_counter; + u8 rsvd48[8]; + __be64 db_record_addr; +}; + +struct mlx5_create_cq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 input_cqn; + u8 rsvdx[4]; + struct mlx5_cq_context ctx; + u8 rsvd6[192]; + __be64 pas[0]; +}; + +struct mlx5_create_cq_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 cqn; + u8 rsvd0[4]; +}; + +struct mlx5_destroy_cq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 cqn; + u8 rsvd0[4]; +}; + +struct mlx5_destroy_cq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; +}; + +struct mlx5_query_cq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 cqn; + u8 rsvd0[4]; +}; + +struct mlx5_query_cq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; + struct mlx5_cq_context ctx; + u8 rsvd6[16]; + __be64 pas[0]; +}; + +struct mlx5_eq_context { + u8 status; + u8 ec_oi; + u8 st; + u8 rsvd2[7]; + __be16 page_pffset; + __be32 log_sz_usr_page; + u8 rsvd3[7]; + u8 intr; + u8 log_page_size; + u8 rsvd4[15]; + __be32 consumer_counter; + __be32 produser_counter; + u8 rsvd5[16]; +}; + +struct mlx5_create_eq_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[3]; + u8 input_eqn; + u8 rsvd1[4]; + struct mlx5_eq_context ctx; + u8 rsvd2[8]; + __be64 events_mask; + u8 rsvd3[176]; + __be64 pas[0]; +}; + +struct mlx5_create_eq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[3]; + u8 eq_number; + u8 rsvd1[4]; +}; + +struct mlx5_destroy_eq_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[3]; + u8 eqn; + u8 rsvd1[4]; +}; + +struct mlx5_destroy_eq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_map_eq_mbox_in { + struct mlx5_inbox_hdr hdr; + __be64 mask; + u8 mu; + u8 rsvd0[2]; + u8 eqn; + u8 rsvd1[24]; +}; + +struct mlx5_map_eq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_query_eq_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[3]; + u8 eqn; + u8 rsvd1[4]; +}; + +struct mlx5_query_eq_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; + struct mlx5_eq_context ctx; +}; + +struct mlx5_mkey_seg { + /* This is a two bit field occupying bits 31-30. + * bit 31 is always 0, + * bit 30 is zero for regular MRs and 1 (e.g free) for UMRs that do not have tanslation + */ + u8 status; + u8 pcie_control; + u8 flags; + u8 version; + __be32 qpn_mkey7_0; + u8 rsvd1[4]; + __be32 flags_pd; + __be64 start_addr; + __be64 len; + __be32 bsfs_octo_size; + u8 rsvd2[16]; + __be32 xlt_oct_size; + u8 rsvd3[3]; + u8 log2_page_size; + u8 rsvd4[4]; +}; + +struct mlx5_query_special_ctxs_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_query_special_ctxs_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 dump_fill_mkey; + __be32 reserved_lkey; +}; + +struct mlx5_create_mkey_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 input_mkey_index; + u8 rsvd0[4]; + struct mlx5_mkey_seg seg; + u8 rsvd1[16]; + __be32 xlat_oct_act_size; + __be32 bsf_coto_act_size; + u8 rsvd2[168]; + __be64 pas[0]; +}; + +struct mlx5_create_mkey_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 mkey; + u8 rsvd[4]; +}; + +struct mlx5_destroy_mkey_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 mkey; + u8 rsvd[4]; +}; + +struct mlx5_destroy_mkey_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_query_mkey_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 mkey; +}; + +struct mlx5_query_mkey_mbox_out { + struct mlx5_outbox_hdr hdr; + __be64 pas[0]; +}; + +struct mlx5_modify_mkey_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 mkey; + __be64 pas[0]; +}; + +struct mlx5_modify_mkey_mbox_out { + struct mlx5_outbox_hdr hdr; +}; + +struct mlx5_dump_mkey_mbox_in { + struct mlx5_inbox_hdr hdr; +}; + +struct mlx5_dump_mkey_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 mkey; +}; + +struct mlx5_mad_ifc_mbox_in { + struct mlx5_inbox_hdr hdr; + __be16 remote_lid; + u8 rsvd0; + u8 port; + u8 rsvd1[4]; + u8 data[256]; +}; + +struct mlx5_mad_ifc_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; + u8 data[256]; +}; + +struct mlx5_access_reg_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd0[2]; + __be16 register_id; + __be32 arg; + __be32 data[0]; +}; + +struct mlx5_access_reg_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; + __be32 data[0]; +}; + +#define MLX5_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90) + +enum { + MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO = 1 << 0 +}; + +#endif /* MLX5_DEVICE_H */ diff --git a/include/linux/mlx5/doorbell.h b/include/linux/mlx5/doorbell.h new file mode 100644 index 000000000000..163a818411e7 --- /dev/null +++ b/include/linux/mlx5/doorbell.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_DOORBELL_H +#define MLX5_DOORBELL_H + +#define MLX5_BF_OFFSET 0x800 +#define MLX5_CQ_DOORBELL 0x20 + +#if BITS_PER_LONG == 64 +/* Assume that we can just write a 64-bit doorbell atomically. s390 + * actually doesn't have writeq() but S/390 systems don't even have + * PCI so we won't worry about it. + */ + +#define MLX5_DECLARE_DOORBELL_LOCK(name) +#define MLX5_INIT_DOORBELL_LOCK(ptr) do { } while (0) +#define MLX5_GET_DOORBELL_LOCK(ptr) (NULL) + +static inline void mlx5_write64(__be32 val[2], void __iomem *dest, + spinlock_t *doorbell_lock) +{ + __raw_writeq(*(u64 *)val, dest); +} + +#else + +/* Just fall back to a spinlock to protect the doorbell if + * BITS_PER_LONG is 32 -- there's no portable way to do atomic 64-bit + * MMIO writes. + */ + +#define MLX5_DECLARE_DOORBELL_LOCK(name) spinlock_t name; +#define MLX5_INIT_DOORBELL_LOCK(ptr) spin_lock_init(ptr) +#define MLX5_GET_DOORBELL_LOCK(ptr) (ptr) + +static inline void mlx5_write64(__be32 val[2], void __iomem *dest, + spinlock_t *doorbell_lock) +{ + unsigned long flags; + + spin_lock_irqsave(doorbell_lock, flags); + __raw_writel((__force u32) val[0], dest); + __raw_writel((__force u32) val[1], dest + 4); + spin_unlock_irqrestore(doorbell_lock, flags); +} + +#endif + +#endif /* MLX5_DOORBELL_H */ diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h new file mode 100644 index 000000000000..e47f1e4c9b03 --- /dev/null +++ b/include/linux/mlx5/driver.h @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_DRIVER_H +#define MLX5_DRIVER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + MLX5_BOARD_ID_LEN = 64, + MLX5_MAX_NAME_LEN = 16, +}; + +enum { + /* one minute for the sake of bringup. Generally, commands must always + * complete and we may need to increase this timeout value + */ + MLX5_CMD_TIMEOUT_MSEC = 7200 * 1000, + MLX5_CMD_WQ_MAX_NAME = 32, +}; + +enum { + CMD_OWNER_SW = 0x0, + CMD_OWNER_HW = 0x1, + CMD_STATUS_SUCCESS = 0, +}; + +enum mlx5_sqp_t { + MLX5_SQP_SMI = 0, + MLX5_SQP_GSI = 1, + MLX5_SQP_IEEE_1588 = 2, + MLX5_SQP_SNIFFER = 3, + MLX5_SQP_SYNC_UMR = 4, +}; + +enum { + MLX5_MAX_PORTS = 2, +}; + +enum { + MLX5_EQ_VEC_PAGES = 0, + MLX5_EQ_VEC_CMD = 1, + MLX5_EQ_VEC_ASYNC = 2, + MLX5_EQ_VEC_COMP_BASE, +}; + +enum { + MLX5_MAX_EQ_NAME = 20 +}; + +enum { + MLX5_ATOMIC_MODE_IB_COMP = 1 << 16, + MLX5_ATOMIC_MODE_CX = 2 << 16, + MLX5_ATOMIC_MODE_8B = 3 << 16, + MLX5_ATOMIC_MODE_16B = 4 << 16, + MLX5_ATOMIC_MODE_32B = 5 << 16, + MLX5_ATOMIC_MODE_64B = 6 << 16, + MLX5_ATOMIC_MODE_128B = 7 << 16, + MLX5_ATOMIC_MODE_256B = 8 << 16, +}; + +enum { + MLX5_CMD_OP_QUERY_HCA_CAP = 0x100, + MLX5_CMD_OP_QUERY_ADAPTER = 0x101, + MLX5_CMD_OP_INIT_HCA = 0x102, + MLX5_CMD_OP_TEARDOWN_HCA = 0x103, + MLX5_CMD_OP_QUERY_PAGES = 0x107, + MLX5_CMD_OP_MANAGE_PAGES = 0x108, + MLX5_CMD_OP_SET_HCA_CAP = 0x109, + + MLX5_CMD_OP_CREATE_MKEY = 0x200, + MLX5_CMD_OP_QUERY_MKEY = 0x201, + MLX5_CMD_OP_DESTROY_MKEY = 0x202, + MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS = 0x203, + + MLX5_CMD_OP_CREATE_EQ = 0x301, + MLX5_CMD_OP_DESTROY_EQ = 0x302, + MLX5_CMD_OP_QUERY_EQ = 0x303, + + MLX5_CMD_OP_CREATE_CQ = 0x400, + MLX5_CMD_OP_DESTROY_CQ = 0x401, + MLX5_CMD_OP_QUERY_CQ = 0x402, + MLX5_CMD_OP_MODIFY_CQ = 0x403, + + MLX5_CMD_OP_CREATE_QP = 0x500, + MLX5_CMD_OP_DESTROY_QP = 0x501, + MLX5_CMD_OP_RST2INIT_QP = 0x502, + MLX5_CMD_OP_INIT2RTR_QP = 0x503, + MLX5_CMD_OP_RTR2RTS_QP = 0x504, + MLX5_CMD_OP_RTS2RTS_QP = 0x505, + MLX5_CMD_OP_SQERR2RTS_QP = 0x506, + MLX5_CMD_OP_2ERR_QP = 0x507, + MLX5_CMD_OP_RTS2SQD_QP = 0x508, + MLX5_CMD_OP_SQD2RTS_QP = 0x509, + MLX5_CMD_OP_2RST_QP = 0x50a, + MLX5_CMD_OP_QUERY_QP = 0x50b, + MLX5_CMD_OP_CONF_SQP = 0x50c, + MLX5_CMD_OP_MAD_IFC = 0x50d, + MLX5_CMD_OP_INIT2INIT_QP = 0x50e, + MLX5_CMD_OP_SUSPEND_QP = 0x50f, + MLX5_CMD_OP_UNSUSPEND_QP = 0x510, + MLX5_CMD_OP_SQD2SQD_QP = 0x511, + MLX5_CMD_OP_ALLOC_QP_COUNTER_SET = 0x512, + MLX5_CMD_OP_DEALLOC_QP_COUNTER_SET = 0x513, + MLX5_CMD_OP_QUERY_QP_COUNTER_SET = 0x514, + + MLX5_CMD_OP_CREATE_PSV = 0x600, + MLX5_CMD_OP_DESTROY_PSV = 0x601, + MLX5_CMD_OP_QUERY_PSV = 0x602, + MLX5_CMD_OP_QUERY_SIG_RULE_TABLE = 0x603, + MLX5_CMD_OP_QUERY_BLOCK_SIZE_TABLE = 0x604, + + MLX5_CMD_OP_CREATE_SRQ = 0x700, + MLX5_CMD_OP_DESTROY_SRQ = 0x701, + MLX5_CMD_OP_QUERY_SRQ = 0x702, + MLX5_CMD_OP_ARM_RQ = 0x703, + MLX5_CMD_OP_RESIZE_SRQ = 0x704, + + MLX5_CMD_OP_ALLOC_PD = 0x800, + MLX5_CMD_OP_DEALLOC_PD = 0x801, + MLX5_CMD_OP_ALLOC_UAR = 0x802, + MLX5_CMD_OP_DEALLOC_UAR = 0x803, + + MLX5_CMD_OP_ATTACH_TO_MCG = 0x806, + MLX5_CMD_OP_DETACH_FROM_MCG = 0x807, + + + MLX5_CMD_OP_ALLOC_XRCD = 0x80e, + MLX5_CMD_OP_DEALLOC_XRCD = 0x80f, + + MLX5_CMD_OP_ACCESS_REG = 0x805, + MLX5_CMD_OP_MAX = 0x810, +}; + +enum { + MLX5_REG_PCAP = 0x5001, + MLX5_REG_PMTU = 0x5003, + MLX5_REG_PTYS = 0x5004, + MLX5_REG_PAOS = 0x5006, + MLX5_REG_PMAOS = 0x5012, + MLX5_REG_PUDE = 0x5009, + MLX5_REG_PMPE = 0x5010, + MLX5_REG_PELC = 0x500e, + MLX5_REG_PMLP = 0, /* TBD */ + MLX5_REG_NODE_DESC = 0x6001, + MLX5_REG_HOST_ENDIANNESS = 0x7004, +}; + +enum dbg_rsc_type { + MLX5_DBG_RSC_QP, + MLX5_DBG_RSC_EQ, + MLX5_DBG_RSC_CQ, +}; + +struct mlx5_field_desc { + struct dentry *dent; + int i; +}; + +struct mlx5_rsc_debug { + struct mlx5_core_dev *dev; + void *object; + enum dbg_rsc_type type; + struct dentry *root; + struct mlx5_field_desc fields[0]; +}; + +enum mlx5_dev_event { + MLX5_DEV_EVENT_SYS_ERROR, + MLX5_DEV_EVENT_PORT_UP, + MLX5_DEV_EVENT_PORT_DOWN, + MLX5_DEV_EVENT_PORT_INITIALIZED, + MLX5_DEV_EVENT_LID_CHANGE, + MLX5_DEV_EVENT_PKEY_CHANGE, + MLX5_DEV_EVENT_GUID_CHANGE, + MLX5_DEV_EVENT_CLIENT_REREG, +}; + +struct mlx5_uuar_info { + struct mlx5_uar *uars; + int num_uars; + int num_low_latency_uuars; + unsigned long *bitmap; + unsigned int *count; + struct mlx5_bf *bfs; + + /* + * protect uuar allocation data structs + */ + struct mutex lock; +}; + +struct mlx5_bf { + void __iomem *reg; + void __iomem *regreg; + int buf_size; + struct mlx5_uar *uar; + unsigned long offset; + int need_lock; + /* protect blue flame buffer selection when needed + */ + spinlock_t lock; + + /* serialize 64 bit writes when done as two 32 bit accesses + */ + spinlock_t lock32; + int uuarn; +}; + +struct mlx5_cmd_first { + __be32 data[4]; +}; + +struct mlx5_cmd_msg { + struct list_head list; + struct cache_ent *cache; + u32 len; + struct mlx5_cmd_first first; + struct mlx5_cmd_mailbox *next; +}; + +struct mlx5_cmd_debug { + struct dentry *dbg_root; + struct dentry *dbg_in; + struct dentry *dbg_out; + struct dentry *dbg_outlen; + struct dentry *dbg_status; + struct dentry *dbg_run; + void *in_msg; + void *out_msg; + u8 status; + u16 inlen; + u16 outlen; +}; + +struct cache_ent { + /* protect block chain allocations + */ + spinlock_t lock; + struct list_head head; +}; + +struct cmd_msg_cache { + struct cache_ent large; + struct cache_ent med; + +}; + +struct mlx5_cmd_stats { + u64 sum; + u64 n; + struct dentry *root; + struct dentry *avg; + struct dentry *count; + /* protect command average calculations */ + spinlock_t lock; +}; + +struct mlx5_cmd { + void *cmd_buf; + dma_addr_t dma; + u16 cmdif_rev; + u8 log_sz; + u8 log_stride; + int max_reg_cmds; + int events; + u32 __iomem *vector; + + /* protect command queue allocations + */ + spinlock_t alloc_lock; + + /* protect token allocations + */ + spinlock_t token_lock; + u8 token; + unsigned long bitmask; + char wq_name[MLX5_CMD_WQ_MAX_NAME]; + struct workqueue_struct *wq; + struct semaphore sem; + struct semaphore pages_sem; + int mode; + struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS]; + struct pci_pool *pool; + struct mlx5_cmd_debug dbg; + struct cmd_msg_cache cache; + int checksum_disabled; + struct mlx5_cmd_stats stats[MLX5_CMD_OP_MAX]; +}; + +struct mlx5_port_caps { + int gid_table_len; + int pkey_table_len; +}; + +struct mlx5_caps { + u8 log_max_eq; + u8 log_max_cq; + u8 log_max_qp; + u8 log_max_mkey; + u8 log_max_pd; + u8 log_max_srq; + u32 max_cqes; + int max_wqes; + int max_sq_desc_sz; + int max_rq_desc_sz; + u64 flags; + u16 stat_rate_support; + int log_max_msg; + int num_ports; + int max_ra_res_qp; + int max_ra_req_qp; + int max_srq_wqes; + int bf_reg_size; + int bf_regs_per_page; + struct mlx5_port_caps port[MLX5_MAX_PORTS]; + u8 ext_port_cap[MLX5_MAX_PORTS]; + int max_vf; + u32 reserved_lkey; + u8 local_ca_ack_delay; + u8 log_max_mcg; + u16 max_qp_mcg; + int min_page_sz; +}; + +struct mlx5_cmd_mailbox { + void *buf; + dma_addr_t dma; + struct mlx5_cmd_mailbox *next; +}; + +struct mlx5_buf_list { + void *buf; + dma_addr_t map; +}; + +struct mlx5_buf { + struct mlx5_buf_list direct; + struct mlx5_buf_list *page_list; + int nbufs; + int npages; + int page_shift; + int size; +}; + +struct mlx5_eq { + struct mlx5_core_dev *dev; + __be32 __iomem *doorbell; + u32 cons_index; + struct mlx5_buf buf; + int size; + u8 irqn; + u8 eqn; + int nent; + u64 mask; + char name[MLX5_MAX_EQ_NAME]; + struct list_head list; + int index; + struct mlx5_rsc_debug *dbg; +}; + + +struct mlx5_core_mr { + u64 iova; + u64 size; + u32 key; + u32 pd; + u32 access; +}; + +struct mlx5_core_srq { + u32 srqn; + int max; + int max_gs; + int max_avail_gather; + int wqe_shift; + void (*event) (struct mlx5_core_srq *, enum mlx5_event); + + atomic_t refcount; + struct completion free; +}; + +struct mlx5_eq_table { + void __iomem *update_ci; + void __iomem *update_arm_ci; + struct list_head *comp_eq_head; + struct mlx5_eq pages_eq; + struct mlx5_eq async_eq; + struct mlx5_eq cmd_eq; + struct msix_entry *msix_arr; + int num_comp_vectors; + /* protect EQs list + */ + spinlock_t lock; +}; + +struct mlx5_uar { + u32 index; + struct list_head bf_list; + unsigned free_bf_bmap; + void __iomem *wc_map; + void __iomem *map; +}; + + +struct mlx5_core_health { + struct health_buffer __iomem *health; + __be32 __iomem *health_counter; + struct timer_list timer; + struct list_head list; + u32 prev; + int miss_counter; +}; + +struct mlx5_cq_table { + /* protect radix tree + */ + spinlock_t lock; + struct radix_tree_root tree; +}; + +struct mlx5_qp_table { + /* protect radix tree + */ + spinlock_t lock; + struct radix_tree_root tree; +}; + +struct mlx5_srq_table { + /* protect radix tree + */ + spinlock_t lock; + struct radix_tree_root tree; +}; + +struct mlx5_priv { + char name[MLX5_MAX_NAME_LEN]; + struct mlx5_eq_table eq_table; + struct mlx5_uuar_info uuari; + MLX5_DECLARE_DOORBELL_LOCK(cq_uar_lock); + + /* pages stuff */ + struct workqueue_struct *pg_wq; + struct rb_root page_root; + int fw_pages; + int reg_pages; + + struct mlx5_core_health health; + + struct mlx5_srq_table srq_table; + + /* start: qp staff */ + struct mlx5_qp_table qp_table; + struct dentry *qp_debugfs; + struct dentry *eq_debugfs; + struct dentry *cq_debugfs; + struct dentry *cmdif_debugfs; + /* end: qp staff */ + + /* start: cq staff */ + struct mlx5_cq_table cq_table; + /* end: cq staff */ + + /* start: alloc staff */ + struct mutex pgdir_mutex; + struct list_head pgdir_list; + /* end: alloc staff */ + struct dentry *dbg_root; + + /* protect mkey key part */ + spinlock_t mkey_lock; + u8 mkey_key; +}; + +struct mlx5_core_dev { + struct pci_dev *pdev; + u8 rev_id; + char board_id[MLX5_BOARD_ID_LEN]; + struct mlx5_cmd cmd; + struct mlx5_caps caps; + phys_addr_t iseg_base; + struct mlx5_init_seg __iomem *iseg; + void (*event) (struct mlx5_core_dev *dev, + enum mlx5_dev_event event, + void *data); + struct mlx5_priv priv; + struct mlx5_profile *profile; + atomic_t num_qps; +}; + +struct mlx5_db { + __be32 *db; + union { + struct mlx5_db_pgdir *pgdir; + struct mlx5_ib_user_db_page *user_page; + } u; + dma_addr_t dma; + int index; +}; + +enum { + MLX5_DB_PER_PAGE = PAGE_SIZE / L1_CACHE_BYTES, +}; + +enum { + MLX5_COMP_EQ_SIZE = 1024, +}; + +struct mlx5_db_pgdir { + struct list_head list; + DECLARE_BITMAP(bitmap, MLX5_DB_PER_PAGE); + __be32 *db_page; + dma_addr_t db_dma; +}; + +typedef void (*mlx5_cmd_cbk_t)(int status, void *context); + +struct mlx5_cmd_work_ent { + struct mlx5_cmd_msg *in; + struct mlx5_cmd_msg *out; + mlx5_cmd_cbk_t callback; + void *context; + int idx; + struct completion done; + struct mlx5_cmd *cmd; + struct work_struct work; + struct mlx5_cmd_layout *lay; + int ret; + int page_queue; + u8 status; + u8 token; + struct timespec ts1; + struct timespec ts2; +}; + +struct mlx5_pas { + u64 pa; + u8 log_sz; +}; + +static inline void *mlx5_buf_offset(struct mlx5_buf *buf, int offset) +{ + if (likely(BITS_PER_LONG == 64 || buf->nbufs == 1)) + return buf->direct.buf + offset; + else + return buf->page_list[offset >> PAGE_SHIFT].buf + + (offset & (PAGE_SIZE - 1)); +} + +extern struct workqueue_struct *mlx5_core_wq; + +#define STRUCT_FIELD(header, field) \ + .struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field), \ + .struct_size_bytes = sizeof((struct ib_unpacked_ ## header *)0)->field + +struct ib_field { + size_t struct_offset_bytes; + size_t struct_size_bytes; + int offset_bits; + int size_bits; +}; + +static inline struct mlx5_core_dev *pci2mlx5_core_dev(struct pci_dev *pdev) +{ + return pci_get_drvdata(pdev); +} + +extern struct dentry *mlx5_debugfs_root; + +static inline u16 fw_rev_maj(struct mlx5_core_dev *dev) +{ + return ioread32be(&dev->iseg->fw_rev) & 0xffff; +} + +static inline u16 fw_rev_min(struct mlx5_core_dev *dev) +{ + return ioread32be(&dev->iseg->fw_rev) >> 16; +} + +static inline u16 fw_rev_sub(struct mlx5_core_dev *dev) +{ + return ioread32be(&dev->iseg->cmdif_rev_fw_sub) & 0xffff; +} + +static inline u16 cmdif_rev(struct mlx5_core_dev *dev) +{ + return ioread32be(&dev->iseg->cmdif_rev_fw_sub) >> 16; +} + +static inline void *mlx5_vzalloc(unsigned long size) +{ + void *rtn; + + rtn = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!rtn) + rtn = vzalloc(size); + return rtn; +} + +static inline void mlx5_vfree(const void *addr) +{ + if (addr && is_vmalloc_addr(addr)) + vfree(addr); + else + kfree(addr); +} + +int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev); +void mlx5_dev_cleanup(struct mlx5_core_dev *dev); +int mlx5_cmd_init(struct mlx5_core_dev *dev); +void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); +void mlx5_cmd_use_events(struct mlx5_core_dev *dev); +void mlx5_cmd_use_polling(struct mlx5_core_dev *dev); +int mlx5_cmd_status_to_err(struct mlx5_outbox_hdr *hdr); +int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, + int out_size); +int mlx5_cmd_alloc_uar(struct mlx5_core_dev *dev, u32 *uarn); +int mlx5_cmd_free_uar(struct mlx5_core_dev *dev, u32 uarn); +int mlx5_alloc_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari); +int mlx5_free_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari); +void mlx5_health_cleanup(void); +void __init mlx5_health_init(void); +void mlx5_start_health_poll(struct mlx5_core_dev *dev); +void mlx5_stop_health_poll(struct mlx5_core_dev *dev); +int mlx5_buf_alloc(struct mlx5_core_dev *dev, int size, int max_direct, + struct mlx5_buf *buf); +void mlx5_buf_free(struct mlx5_core_dev *dev, struct mlx5_buf *buf); +struct mlx5_cmd_mailbox *mlx5_alloc_cmd_mailbox_chain(struct mlx5_core_dev *dev, + gfp_t flags, int npages); +void mlx5_free_cmd_mailbox_chain(struct mlx5_core_dev *dev, + struct mlx5_cmd_mailbox *head); +int mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + struct mlx5_create_srq_mbox_in *in, int inlen); +int mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq); +int mlx5_core_query_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + struct mlx5_query_srq_mbox_out *out); +int mlx5_core_arm_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, + u16 lwm, int is_srq); +int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + struct mlx5_create_mkey_mbox_in *in, int inlen); +int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr); +int mlx5_core_query_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + struct mlx5_query_mkey_mbox_out *out, int outlen); +int mlx5_core_dump_fill_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mr *mr, + u32 *mkey); +int mlx5_core_alloc_pd(struct mlx5_core_dev *dev, u32 *pdn); +int mlx5_core_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn); +int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, void *inb, void *outb, + u16 opmod, int port); +void mlx5_pagealloc_init(struct mlx5_core_dev *dev); +void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev); +int mlx5_pagealloc_start(struct mlx5_core_dev *dev); +void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); +void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, + s16 npages); +int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev); +int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); +void mlx5_register_debugfs(void); +void mlx5_unregister_debugfs(void); +int mlx5_eq_init(struct mlx5_core_dev *dev); +void mlx5_eq_cleanup(struct mlx5_core_dev *dev); +void mlx5_fill_page_array(struct mlx5_buf *buf, __be64 *pas); +void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn); +void mlx5_qp_event(struct mlx5_core_dev *dev, u32 qpn, int event_type); +void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type); +struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn); +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector); +void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type); +int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, + int nent, u64 mask, const char *name, struct mlx5_uar *uar); +int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq); +int mlx5_start_eqs(struct mlx5_core_dev *dev); +int mlx5_stop_eqs(struct mlx5_core_dev *dev); +int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); +int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); + +int mlx5_qp_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev); +int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, + int size_in, void *data_out, int size_out, + u16 reg_num, int arg, int write); +int mlx5_set_port_caps(struct mlx5_core_dev *dev, int port_num, u32 caps); + +int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq); +void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq); +int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq, + struct mlx5_query_eq_mbox_out *out, int outlen); +int mlx5_eq_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev); +int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev); +int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db); +void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); + +typedef void (*health_handler_t)(struct pci_dev *pdev, void *buf, int size); +int mlx5_register_health_report_handler(health_handler_t handler); +void mlx5_unregister_health_report_handler(void); +const char *mlx5_command_str(int command); +int mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev); +void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev); + +static inline u32 mlx5_mkey_to_idx(u32 mkey) +{ + return mkey >> 8; +} + +static inline u32 mlx5_idx_to_mkey(u32 mkey_idx) +{ + return mkey_idx << 8; +} + +enum { + MLX5_PROF_MASK_QP_SIZE = (u64)1 << 0, + MLX5_PROF_MASK_CMDIF_CSUM = (u64)1 << 1, + MLX5_PROF_MASK_MR_CACHE = (u64)1 << 2, +}; + +enum { + MAX_MR_CACHE_ENTRIES = 16, +}; + +struct mlx5_profile { + u64 mask; + u32 log_max_qp; + int cmdif_csum; + struct { + int size; + int limit; + } mr_cache[MAX_MR_CACHE_ENTRIES]; +}; + +#endif /* MLX5_DRIVER_H */ diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h new file mode 100644 index 000000000000..d9e3eacb3a7f --- /dev/null +++ b/include/linux/mlx5/qp.h @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_QP_H +#define MLX5_QP_H + +#include +#include + +#define MLX5_INVALID_LKEY 0x100 + +enum mlx5_qp_optpar { + MLX5_QP_OPTPAR_ALT_ADDR_PATH = 1 << 0, + MLX5_QP_OPTPAR_RRE = 1 << 1, + MLX5_QP_OPTPAR_RAE = 1 << 2, + MLX5_QP_OPTPAR_RWE = 1 << 3, + MLX5_QP_OPTPAR_PKEY_INDEX = 1 << 4, + MLX5_QP_OPTPAR_Q_KEY = 1 << 5, + MLX5_QP_OPTPAR_RNR_TIMEOUT = 1 << 6, + MLX5_QP_OPTPAR_PRIMARY_ADDR_PATH = 1 << 7, + MLX5_QP_OPTPAR_SRA_MAX = 1 << 8, + MLX5_QP_OPTPAR_RRA_MAX = 1 << 9, + MLX5_QP_OPTPAR_PM_STATE = 1 << 10, + MLX5_QP_OPTPAR_RETRY_COUNT = 1 << 12, + MLX5_QP_OPTPAR_RNR_RETRY = 1 << 13, + MLX5_QP_OPTPAR_ACK_TIMEOUT = 1 << 14, + MLX5_QP_OPTPAR_PRI_PORT = 1 << 16, + MLX5_QP_OPTPAR_SRQN = 1 << 18, + MLX5_QP_OPTPAR_CQN_RCV = 1 << 19, + MLX5_QP_OPTPAR_DC_HS = 1 << 20, + MLX5_QP_OPTPAR_DC_KEY = 1 << 21, +}; + +enum mlx5_qp_state { + MLX5_QP_STATE_RST = 0, + MLX5_QP_STATE_INIT = 1, + MLX5_QP_STATE_RTR = 2, + MLX5_QP_STATE_RTS = 3, + MLX5_QP_STATE_SQER = 4, + MLX5_QP_STATE_SQD = 5, + MLX5_QP_STATE_ERR = 6, + MLX5_QP_STATE_SQ_DRAINING = 7, + MLX5_QP_STATE_SUSPENDED = 9, + MLX5_QP_NUM_STATE +}; + +enum { + MLX5_QP_ST_RC = 0x0, + MLX5_QP_ST_UC = 0x1, + MLX5_QP_ST_UD = 0x2, + MLX5_QP_ST_XRC = 0x3, + MLX5_QP_ST_MLX = 0x4, + MLX5_QP_ST_DCI = 0x5, + MLX5_QP_ST_DCT = 0x6, + MLX5_QP_ST_QP0 = 0x7, + MLX5_QP_ST_QP1 = 0x8, + MLX5_QP_ST_RAW_ETHERTYPE = 0x9, + MLX5_QP_ST_RAW_IPV6 = 0xa, + MLX5_QP_ST_SNIFFER = 0xb, + MLX5_QP_ST_SYNC_UMR = 0xe, + MLX5_QP_ST_PTP_1588 = 0xd, + MLX5_QP_ST_REG_UMR = 0xc, + MLX5_QP_ST_MAX +}; + +enum { + MLX5_QP_PM_MIGRATED = 0x3, + MLX5_QP_PM_ARMED = 0x0, + MLX5_QP_PM_REARM = 0x1 +}; + +enum { + MLX5_NON_ZERO_RQ = 0 << 24, + MLX5_SRQ_RQ = 1 << 24, + MLX5_CRQ_RQ = 2 << 24, + MLX5_ZERO_LEN_RQ = 3 << 24 +}; + +enum { + /* params1 */ + MLX5_QP_BIT_SRE = 1 << 15, + MLX5_QP_BIT_SWE = 1 << 14, + MLX5_QP_BIT_SAE = 1 << 13, + /* params2 */ + MLX5_QP_BIT_RRE = 1 << 15, + MLX5_QP_BIT_RWE = 1 << 14, + MLX5_QP_BIT_RAE = 1 << 13, + MLX5_QP_BIT_RIC = 1 << 4, +}; + +enum { + MLX5_WQE_CTRL_CQ_UPDATE = 2 << 2, + MLX5_WQE_CTRL_SOLICITED = 1 << 1, +}; + +enum { + MLX5_SEND_WQE_BB = 64, +}; + +enum { + MLX5_WQE_FMR_PERM_LOCAL_READ = 1 << 27, + MLX5_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28, + MLX5_WQE_FMR_PERM_REMOTE_READ = 1 << 29, + MLX5_WQE_FMR_PERM_REMOTE_WRITE = 1 << 30, + MLX5_WQE_FMR_PERM_ATOMIC = 1 << 31 +}; + +enum { + MLX5_FENCE_MODE_NONE = 0 << 5, + MLX5_FENCE_MODE_INITIATOR_SMALL = 1 << 5, + MLX5_FENCE_MODE_STRONG_ORDERING = 3 << 5, + MLX5_FENCE_MODE_SMALL_AND_FENCE = 4 << 5, +}; + +enum { + MLX5_QP_LAT_SENSITIVE = 1 << 28, + MLX5_QP_ENABLE_SIG = 1 << 31, +}; + +enum { + MLX5_RCV_DBR = 0, + MLX5_SND_DBR = 1, +}; + +struct mlx5_wqe_fmr_seg { + __be32 flags; + __be32 mem_key; + __be64 buf_list; + __be64 start_addr; + __be64 reg_len; + __be32 offset; + __be32 page_size; + u32 reserved[2]; +}; + +struct mlx5_wqe_ctrl_seg { + __be32 opmod_idx_opcode; + __be32 qpn_ds; + u8 signature; + u8 rsvd[2]; + u8 fm_ce_se; + __be32 imm; +}; + +struct mlx5_wqe_xrc_seg { + __be32 xrc_srqn; + u8 rsvd[12]; +}; + +struct mlx5_wqe_masked_atomic_seg { + __be64 swap_add; + __be64 compare; + __be64 swap_add_mask; + __be64 compare_mask; +}; + +struct mlx5_av { + union { + struct { + __be32 qkey; + __be32 reserved; + } qkey; + __be64 dc_key; + } key; + __be32 dqp_dct; + u8 stat_rate_sl; + u8 fl_mlid; + __be16 rlid; + u8 reserved0[10]; + u8 tclass; + u8 hop_limit; + __be32 grh_gid_fl; + u8 rgid[16]; +}; + +struct mlx5_wqe_datagram_seg { + struct mlx5_av av; +}; + +struct mlx5_wqe_raddr_seg { + __be64 raddr; + __be32 rkey; + u32 reserved; +}; + +struct mlx5_wqe_atomic_seg { + __be64 swap_add; + __be64 compare; +}; + +struct mlx5_wqe_data_seg { + __be32 byte_count; + __be32 lkey; + __be64 addr; +}; + +struct mlx5_wqe_umr_ctrl_seg { + u8 flags; + u8 rsvd0[3]; + __be16 klm_octowords; + __be16 bsf_octowords; + __be64 mkey_mask; + u8 rsvd1[32]; +}; + +struct mlx5_seg_set_psv { + __be32 psv_num; + __be16 syndrome; + __be16 status; + __be32 transient_sig; + __be32 ref_tag; +}; + +struct mlx5_seg_get_psv { + u8 rsvd[19]; + u8 num_psv; + __be32 l_key; + __be64 va; + __be32 psv_index[4]; +}; + +struct mlx5_seg_check_psv { + u8 rsvd0[2]; + __be16 err_coalescing_op; + u8 rsvd1[2]; + __be16 xport_err_op; + u8 rsvd2[2]; + __be16 xport_err_mask; + u8 rsvd3[7]; + u8 num_psv; + __be32 l_key; + __be64 va; + __be32 psv_index[4]; +}; + +struct mlx5_rwqe_sig { + u8 rsvd0[4]; + u8 signature; + u8 rsvd1[11]; +}; + +struct mlx5_wqe_signature_seg { + u8 rsvd0[4]; + u8 signature; + u8 rsvd1[11]; +}; + +struct mlx5_wqe_inline_seg { + __be32 byte_count; +}; + +struct mlx5_core_qp { + void (*event) (struct mlx5_core_qp *, int); + int qpn; + atomic_t refcount; + struct completion free; + struct mlx5_rsc_debug *dbg; + int pid; +}; + +struct mlx5_qp_path { + u8 fl; + u8 rsvd3; + u8 free_ar; + u8 pkey_index; + u8 rsvd0; + u8 grh_mlid; + __be16 rlid; + u8 ackto_lt; + u8 mgid_index; + u8 static_rate; + u8 hop_limit; + __be32 tclass_flowlabel; + u8 rgid[16]; + u8 rsvd1[4]; + u8 sl; + u8 port; + u8 rsvd2[6]; +}; + +struct mlx5_qp_context { + __be32 flags; + __be32 flags_pd; + u8 mtu_msgmax; + u8 rq_size_stride; + __be16 sq_crq_size; + __be32 qp_counter_set_usr_page; + __be32 wire_qpn; + __be32 log_pg_sz_remote_qpn; + struct mlx5_qp_path pri_path; + struct mlx5_qp_path alt_path; + __be32 params1; + u8 reserved2[4]; + __be32 next_send_psn; + __be32 cqn_send; + u8 reserved3[8]; + __be32 last_acked_psn; + __be32 ssn; + __be32 params2; + __be32 rnr_nextrecvpsn; + __be32 xrcd; + __be32 cqn_recv; + __be64 db_rec_addr; + __be32 qkey; + __be32 rq_type_srqn; + __be32 rmsn; + __be16 hw_sq_wqe_counter; + __be16 sw_sq_wqe_counter; + __be16 hw_rcyclic_byte_counter; + __be16 hw_rq_counter; + __be16 sw_rcyclic_byte_counter; + __be16 sw_rq_counter; + u8 rsvd0[5]; + u8 cgs; + u8 cs_req; + u8 cs_res; + __be64 dc_access_key; + u8 rsvd1[24]; +}; + +struct mlx5_create_qp_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 input_qpn; + u8 rsvd0[4]; + __be32 opt_param_mask; + u8 rsvd1[4]; + struct mlx5_qp_context ctx; + u8 rsvd3[16]; + __be64 pas[0]; +}; + +struct mlx5_create_qp_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 qpn; + u8 rsvd0[4]; +}; + +struct mlx5_destroy_qp_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + u8 rsvd0[4]; +}; + +struct mlx5_destroy_qp_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; +}; + +struct mlx5_modify_qp_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + u8 rsvd1[4]; + __be32 optparam; + u8 rsvd0[4]; + struct mlx5_qp_context ctx; +}; + +struct mlx5_modify_qp_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd0[8]; +}; + +struct mlx5_query_qp_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + u8 rsvd[4]; +}; + +struct mlx5_query_qp_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd1[8]; + __be32 optparam; + u8 rsvd0[4]; + struct mlx5_qp_context ctx; + u8 rsvd2[16]; + __be64 pas[0]; +}; + +struct mlx5_conf_sqp_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 qpn; + u8 rsvd[3]; + u8 type; +}; + +struct mlx5_conf_sqp_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_alloc_xrcd_mbox_in { + struct mlx5_inbox_hdr hdr; + u8 rsvd[8]; +}; + +struct mlx5_alloc_xrcd_mbox_out { + struct mlx5_outbox_hdr hdr; + __be32 xrcdn; + u8 rsvd[4]; +}; + +struct mlx5_dealloc_xrcd_mbox_in { + struct mlx5_inbox_hdr hdr; + __be32 xrcdn; + u8 rsvd[4]; +}; + +struct mlx5_dealloc_xrcd_mbox_out { + struct mlx5_outbox_hdr hdr; + u8 rsvd[8]; +}; + +static inline struct mlx5_core_qp *__mlx5_qp_lookup(struct mlx5_core_dev *dev, u32 qpn) +{ + return radix_tree_lookup(&dev->priv.qp_table.tree, qpn); +} + +int mlx5_core_create_qp(struct mlx5_core_dev *dev, + struct mlx5_core_qp *qp, + struct mlx5_create_qp_mbox_in *in, + int inlen); +int mlx5_core_qp_modify(struct mlx5_core_dev *dev, enum mlx5_qp_state cur_state, + enum mlx5_qp_state new_state, + struct mlx5_modify_qp_mbox_in *in, int sqd_event, + struct mlx5_core_qp *qp); +int mlx5_core_destroy_qp(struct mlx5_core_dev *dev, + struct mlx5_core_qp *qp); +int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp, + struct mlx5_query_qp_mbox_out *out, int outlen); + +int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn); +int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn); +void mlx5_init_qp_table(struct mlx5_core_dev *dev); +void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev); +int mlx5_debug_qp_add(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp); +void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp); + +#endif /* MLX5_QP_H */ diff --git a/include/linux/mlx5/srq.h b/include/linux/mlx5/srq.h new file mode 100644 index 000000000000..e1a363a33663 --- /dev/null +++ b/include/linux/mlx5/srq.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef MLX5_SRQ_H +#define MLX5_SRQ_H + +#include + +void mlx5_init_srq_table(struct mlx5_core_dev *dev); +void mlx5_cleanup_srq_table(struct mlx5_core_dev *dev); + +#endif /* MLX5_SRQ_H */ -- GitLab From 63884c90ffa3f73a81b81f169c51c34d2b9cf75e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 1 Jul 2013 14:15:17 -0700 Subject: [PATCH 2446/2900] mlx5: Fix parameter type of health_handler_t This deals with the sparse warning: drivers/net/ethernet/mellanox/mlx5/core/health.c:94:54: warning: incorrect type in argument 2 (different address spaces) drivers/net/ethernet/mellanox/mlx5/core/health.c:94:54: expected void *buf drivers/net/ethernet/mellanox/mlx5/core/health.c:94:54: got struct health_buffer [noderef] *health Signed-off-by: Roland Dreier --- include/linux/mlx5/driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index e47f1e4c9b03..f22e4419839b 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -729,7 +729,7 @@ void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev); int mlx5_db_alloc(struct mlx5_core_dev *dev, struct mlx5_db *db); void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db); -typedef void (*health_handler_t)(struct pci_dev *pdev, void *buf, int size); +typedef void (*health_handler_t)(struct pci_dev *pdev, struct health_buffer __iomem *buf, int size); int mlx5_register_health_report_handler(health_handler_t handler); void mlx5_unregister_health_report_handler(void); const char *mlx5_command_str(int command); -- GitLab From ad32b95f8281ac5a292da83ff27616aceee4b770 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 8 Jul 2013 00:13:35 -0700 Subject: [PATCH 2447/2900] IB/mlx5: Make profile[] static in main.c Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx5/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 6b1007f9bc29..8000fff4d444 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -62,7 +62,7 @@ static char mlx5_version[] = DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v" DRIVER_VERSION " (" DRIVER_RELDATE ")\n"; -struct mlx5_profile profile[] = { +static struct mlx5_profile profile[] = { [0] = { .mask = 0, }, -- GitLab From 44840098478f6bf8c6e8d010241dcd4990fefe07 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Thu, 20 Jun 2013 11:15:39 -0700 Subject: [PATCH 2448/2900] [IA64] sim: Add casts to avoid assignment warnings Pointers in the efi_runtime_services_t structure now have type "void *" (formerly they were "unsigned long"). So we now see a bunch of warnings like this: arch/ia64/hp/sim/boot/fw-emu.c:293: warning: assignment makes pointer from integer without a cast Add (void *) casts to the 10 affected lines to make the build quiet again. Signed-off-by: Tony Luck --- arch/ia64/hp/sim/boot/fw-emu.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c index 271f412bda1a..87bf9ad8cf0f 100644 --- a/arch/ia64/hp/sim/boot/fw-emu.c +++ b/arch/ia64/hp/sim/boot/fw-emu.c @@ -290,16 +290,16 @@ sys_fw_init (const char *args, int arglen) efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); - efi_runtime->get_time = __pa(&fw_efi_get_time); - efi_runtime->set_time = __pa(&efi_unimplemented); - efi_runtime->get_wakeup_time = __pa(&efi_unimplemented); - efi_runtime->set_wakeup_time = __pa(&efi_unimplemented); - efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented); - efi_runtime->get_variable = __pa(&efi_unimplemented); - efi_runtime->get_next_variable = __pa(&efi_unimplemented); - efi_runtime->set_variable = __pa(&efi_unimplemented); - efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented); - efi_runtime->reset_system = __pa(&efi_reset_system); + efi_runtime->get_time = (void *)__pa(&fw_efi_get_time); + efi_runtime->set_time = (void *)__pa(&efi_unimplemented); + efi_runtime->get_wakeup_time = (void *)__pa(&efi_unimplemented); + efi_runtime->set_wakeup_time = (void *)__pa(&efi_unimplemented); + efi_runtime->set_virtual_address_map = (void *)__pa(&efi_unimplemented); + efi_runtime->get_variable = (void *)__pa(&efi_unimplemented); + efi_runtime->get_next_variable = (void *)__pa(&efi_unimplemented); + efi_runtime->set_variable = (void *)__pa(&efi_unimplemented); + efi_runtime->get_next_high_mono_count = (void *)__pa(&efi_unimplemented); + efi_runtime->reset_system = (void *)__pa(&efi_reset_system); efi_tables->guid = SAL_SYSTEM_TABLE_GUID; efi_tables->table = __pa(sal_systab); -- GitLab From 582c016e68dc5dfea4d3582512157f165a428149 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 8 Jul 2013 10:52:28 -0700 Subject: [PATCH 2449/2900] mlx5_core: Fixes for sparse warnings - use be32_to_cpu() instead of cpu_to_be32() where appropriate. - use proper accessors for pointers marked __iomem. Signed-off-by: Roland Dreier --- .../net/ethernet/mellanox/mlx5/core/debugfs.c | 4 +-- .../net/ethernet/mellanox/mlx5/core/health.c | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 5e9cf2b9aaf7..a550a8ef94a1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -323,11 +323,11 @@ static u64 qp_read_field(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp, param = 0; break; case QP_LOG_PG_SZ: - param = ((cpu_to_be32(ctx->log_pg_sz_remote_qpn) >> 24) & 0x1f); + param = (be32_to_cpu(ctx->log_pg_sz_remote_qpn) >> 24) & 0x1f; param += 12; break; case QP_RQPN: - param = cpu_to_be32(ctx->log_pg_sz_remote_qpn) & 0xffffff; + param = be32_to_cpu(ctx->log_pg_sz_remote_qpn) & 0xffffff; break; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index ea4b9bca6d4a..748f10a155c4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -132,6 +132,16 @@ static const char *hsynd_str(u8 synd) } } +static u16 read_be16(__be16 __iomem *p) +{ + return swab16(readl((__force u16 __iomem *) p)); +} + +static u32 read_be32(__be32 __iomem *p) +{ + return swab32(readl((__force u32 __iomem *) p)); +} + static void print_health_info(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; @@ -139,15 +149,15 @@ static void print_health_info(struct mlx5_core_dev *dev) int i; for (i = 0; i < ARRAY_SIZE(h->assert_var); i++) - pr_info("assert_var[%d] 0x%08x\n", i, be32_to_cpu(h->assert_var[i])); - - pr_info("assert_exit_ptr 0x%08x\n", be32_to_cpu(h->assert_exit_ptr)); - pr_info("assert_callra 0x%08x\n", be32_to_cpu(h->assert_callra)); - pr_info("fw_ver 0x%08x\n", be32_to_cpu(h->fw_ver)); - pr_info("hw_id 0x%08x\n", be32_to_cpu(h->hw_id)); - pr_info("irisc_index %d\n", h->irisc_index); - pr_info("synd 0x%x: %s\n", h->synd, hsynd_str(h->synd)); - pr_info("ext_sync 0x%04x\n", be16_to_cpu(h->ext_sync)); + pr_info("assert_var[%d] 0x%08x\n", i, read_be32(h->assert_var + i)); + + pr_info("assert_exit_ptr 0x%08x\n", read_be32(&h->assert_exit_ptr)); + pr_info("assert_callra 0x%08x\n", read_be32(&h->assert_callra)); + pr_info("fw_ver 0x%08x\n", read_be32(&h->fw_ver)); + pr_info("hw_id 0x%08x\n", read_be32(&h->hw_id)); + pr_info("irisc_index %d\n", readb(&h->irisc_index)); + pr_info("synd 0x%x: %s\n", readb(&h->synd), hsynd_str(readb(&h->synd))); + pr_info("ext_sync 0x%04x\n", read_be16(&h->ext_sync)); } static void poll_health(unsigned long data) -- GitLab From da183c7af8444cb2c1beedaa498a9359f19ff665 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 8 Jul 2013 11:15:45 -0700 Subject: [PATCH 2450/2900] IB/uverbs: Use get_unused_fd_flags(O_CLOEXEC) instead of get_unused_fd() The macro get_unused_fd() is used to allocate a file descriptor with default flags. Those default flags (0) can be "unsafe": O_CLOEXEC must be used by default to not leak file descriptor across exec(). Replace calls to get_unused_fd() in uverbs with calls to get_unused_fd_flags(O_CLOEXEC). Inheriting uverbs fds across exec() cannot be used to do anything useful. Based on a patch/suggestion from Yann Droneaud . Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a7d00f6b3bc1..b3c07b0c9f26 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -334,7 +334,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, resp.num_comp_vectors = file->device->num_comp_vectors; - ret = get_unused_fd(); + ret = get_unused_fd_flags(O_CLOEXEC); if (ret < 0) goto err_free; resp.async_fd = ret; @@ -1184,7 +1184,7 @@ ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - ret = get_unused_fd(); + ret = get_unused_fd_flags(O_CLOEXEC); if (ret < 0) return ret; resp.fd = ret; -- GitLab From 5125bc22e7871b46e71312d6cc4455e9eea1619d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 3 May 2013 15:49:53 +0200 Subject: [PATCH 2451/2900] tools: Get only verbose output with V=1 Fix having verbose build with V=0, e.g: make V=0 -C tools/ perf Signed-off-by: Robert Richter Link: http://lkml.kernel.org/r/20130503134953.GU8356@rric.localhost Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/Makefile | 2 +- tools/perf/config/utilities.mak | 2 +- tools/scripts/Makefile.include | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile index eb30044a922a..f75175757892 100644 --- a/tools/perf/Documentation/Makefile +++ b/tools/perf/Documentation/Makefile @@ -150,7 +150,7 @@ NO_SUBDIR = : endif ifneq ($(findstring $(MAKEFLAGS),s),s) -ifndef V +ifneq ($(V),1) QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; QUIET_XMLTO = @echo ' ' XMLTO $@; QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak index 8ef3bd30a549..faffb52fcf80 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/perf/config/utilities.mak @@ -181,7 +181,7 @@ _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) # try-cc # Usage: option = $(call try-cc, source-to-build, cc-options, msg) -ifndef V +ifneq ($(V),1) TRY_CC_OUTPUT= > /dev/null 2>&1 endif TRY_CC_MSG=echo " CHK $(3)" 1>&2; diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index f03e681f8891..0d0506d55c71 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -59,7 +59,7 @@ QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir QUIET_SUBDIR1 = ifneq ($(findstring $(MAKEFLAGS),s),s) -ifndef V +ifneq ($(V),1) QUIET_CC = @echo ' ' CC $@; QUIET_AR = @echo ' ' AR $@; QUIET_LINK = @echo ' ' LINK $@; -- GitLab From 761a0f395d5d8b7aafe563ecefbc8cf71a214a91 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 6 May 2013 20:40:14 +0200 Subject: [PATCH 2452/2900] perf tools: Fix output directory of Documentation/ The OUTPUT directory is wrongly determind leading to: make[3]: *** No rule to make target `.../.build/perf/PERF-VERSION-FILE'. Stop. Fixing this by using the generic approach in script/Makefile.include. Signed-off-by: Robert Richter Link: http://lkml.kernel.org/r/1367865614-30876-1-git-send-email-rric@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/Makefile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile index f75175757892..5a37a7c84e69 100644 --- a/tools/perf/Documentation/Makefile +++ b/tools/perf/Documentation/Makefile @@ -1,12 +1,6 @@ +include ../../scripts/Makefile.include include ../config/utilities.mak -OUTPUT := ./ -ifeq ("$(origin O)", "command line") - ifneq ($(O),) - OUTPUT := $(O)/ - endif -endif - MAN1_TXT= \ $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ $(wildcard perf-*.txt)) \ @@ -277,7 +271,7 @@ $(MAN_HTML): $(OUTPUT)%.html : %.txt $(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml $(QUIET_XMLTO)$(RM) $@ && \ - $(XMLTO) -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< + $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< $(OUTPUT)%.xml : %.txt $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ -- GitLab From 107de3724eff5a6fa6474a4d2aa5460b63749ebf Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 11 Jun 2013 17:22:38 +0200 Subject: [PATCH 2453/2900] perf tools: Fix build errors with O and DESTDIR make vars set Fixing build errors with O and DESTDIR make vars set: $ make prefix=/usr/local O=$builddir DESTDIR=$destdir -C tools/ perf ... make[1]: Entering directory `.../.source/perf/tools/perf' CC .../.build/perf/perf/util/parse-events.o util/parse-events.c:14:32: fatal error: parse-events-bison.h: No such file or directory compilation terminated. make[1]: *** [.../.build/perf/perf/util/parse-events.o] Error 1 ... and: LINK /.../.build/perf/perf/perf gcc: error: /.../.build/perf/perf//.../.source/perf/tools/lib/lk/liblk.a: No such file or directory Signed-off-by: Robert Richter Signed-off-by: Robert Richter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Robert Richter Link: http://lkml.kernel.org/r/1370964158-4135-1-git-send-email-rric@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 5 ++--- tools/perf/config/Makefile | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 203cb0eecff2..641fccddb249 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -121,17 +121,16 @@ SCRIPT_SH += perf-archive.sh grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) -LK_PATH=$(LK_DIR) - ifneq ($(OUTPUT),) TE_PATH=$(OUTPUT) ifneq ($(subdir),) - LK_PATH=$(OUTPUT)$(LK_DIR) + LK_PATH=$(objtree)/lib/lk/ else LK_PATH=$(OUTPUT) endif else TE_PATH=$(TRACE_EVENT_DIR) + LK_PATH=$(LK_DIR) endif LIBTRACEEVENT = $(TE_PATH)libtraceevent.a diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f139dcd2796e..f4468954d3dc 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -39,7 +39,7 @@ src-perf := $(srctree)/tools/perf endif ifeq ($(obj-perf),) -obj-perf := $(objtree) +obj-perf := $(OUTPUT) endif ifneq ($(obj-perf),) -- GitLab From 13966721a11f4a2ba8038191e48083b5f31822bb Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Thu, 6 Jun 2013 14:35:03 +0300 Subject: [PATCH 2454/2900] perf bench: Fix memory allocation fail check in mem{set,cpy} workloads Addresses of allocated memory areas saved to '*src' and '*dst', so we need to check them for NULL, not 'src' and 'dst'. Signed-off-by: Kirill A. Shutemov Acked-by: Hitoshi Mitake Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370518503-4230-1-git-send-email-kirill.shutemov@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/mem-memcpy.c | 4 ++-- tools/perf/bench/mem-memset.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 93c83e3cb4a7..25fd3f1966f1 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -111,11 +111,11 @@ static double timeval2double(struct timeval *ts) static void alloc_mem(void **dst, void **src, size_t length) { *dst = zalloc(length); - if (!dst) + if (!*dst) die("memory allocation failed - maybe length is too large?\n"); *src = zalloc(length); - if (!src) + if (!*src) die("memory allocation failed - maybe length is too large?\n"); } diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index c6e4bc523492..4a2f12081964 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c @@ -111,7 +111,7 @@ static double timeval2double(struct timeval *ts) static void alloc_mem(void **dst, size_t length) { *dst = zalloc(length); - if (!dst) + if (!*dst) die("memory allocation failed - maybe length is too large?\n"); } -- GitLab From 756bbc84e30b57ca1010b550ea30594fd0b0494f Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Wed, 19 Jun 2013 10:02:30 +0900 Subject: [PATCH 2455/2900] perf tools: Include termios.h explicitly Building perf for android fails because it can't find the definition of struct winsize. This definition is in termios.h, so I add this header to util.h to solve the problem. It is missed by commit '2c803e52' which moves get_term_dimensions() from builtin-top.c to util.c, but missed to move termios.h header. Signed-off-by: Joonsoo Kim Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1371603750-15053-3-git-send-email-iamjoonsoo.kim@lge.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 7a484c97e500..2732fad03908 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -72,6 +72,7 @@ #include "types.h" #include #include +#include extern const char *graph_line; extern const char *graph_dotted_line; @@ -274,6 +275,5 @@ void dump_stack(void); extern unsigned int page_size; -struct winsize; void get_term_dimensions(struct winsize *ws); #endif /* GIT_COMPAT_UTIL_H */ -- GitLab From 079787f209416416383c74ea5d5044be2d586f5e Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Wed, 19 Jun 2013 10:02:29 +0900 Subject: [PATCH 2456/2900] tools lib lk: Fix for cross build Currently, lib lk doesn't use CROSS_COMPILE environment variable, so cross build always fails. This is a quick fix for this problem. Signed-off-by: Joonsoo Kim Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1371603750-15053-2-git-send-email-iamjoonsoo.kim@lge.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/lk/Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/lib/lk/Makefile b/tools/lib/lk/Makefile index 2c5a19733357..f0ecc0a13300 100644 --- a/tools/lib/lk/Makefile +++ b/tools/lib/lk/Makefile @@ -3,6 +3,21 @@ include ../../scripts/Makefile.include CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar +# Makefiles suck: This macro sets a default value of $(2) for the +# variable named by $(1), unless the variable has been set by +# environment or command line. This is necessary for CC and AR +# because make sets default values, so the simpler ?= approach +# won't work as expected. +define allow-override + $(if $(or $(findstring environment,$(origin $(1))),\ + $(findstring command line,$(origin $(1)))),,\ + $(eval $(1) = $(2))) +endef + +# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. +$(call allow-override,CC,$(CROSS_COMPILE)gcc) +$(call allow-override,AR,$(CROSS_COMPILE)ar) + # guard against environment variables LIB_H= LIB_OBJS= -- GitLab From d07f0b120642f442d81a61f68a9325fb7717004f Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Tue, 4 Jun 2013 17:44:26 +0200 Subject: [PATCH 2457/2900] perf stat: Avoid sending SIGTERM to random processes This patch fixes a problem with perf stat whereby on termination it may send a SIGTERM signal to random processes on systems with high PID recycling. I got some actual bug reports on this. There is race between the SIGCHLD and sig_atexit() handlers. This patch addresses this problem by clearing child_pid in the SIGCHLD handler. Signed-off-by: Stephane Eranian Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20130604154426.GA2928@quad Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7e910bab1097..95768afaae3e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -87,7 +87,7 @@ static int run_count = 1; static bool no_inherit = false; static bool scale = true; static enum aggr_mode aggr_mode = AGGR_GLOBAL; -static pid_t child_pid = -1; +static volatile pid_t child_pid = -1; static bool null_run = false; static int detailed_run = 0; static bool big_num = true; @@ -1148,13 +1148,34 @@ static void skip_signal(int signo) done = 1; signr = signo; + /* + * render child_pid harmless + * won't send SIGTERM to a random + * process in case of race condition + * and fast PID recycling + */ + child_pid = -1; } static void sig_atexit(void) { + sigset_t set, oset; + + /* + * avoid race condition with SIGCHLD handler + * in skip_signal() which is modifying child_pid + * goal is to avoid send SIGTERM to a random + * process + */ + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + sigprocmask(SIG_BLOCK, &set, &oset); + if (child_pid != -1) kill(child_pid, SIGTERM); + sigprocmask(SIG_SETMASK, &oset, NULL); + if (signr == -1) return; -- GitLab From 563aecb2e63a16f86c7daabfdcfee23f3e7c5955 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 5 Jun 2013 13:35:06 +0200 Subject: [PATCH 2458/2900] perf record: Remove -A/--append option It's no longer working and needed. Quite straightforward discussion/vote was in here: http://marc.info/?t=137028288300004&r=1&w=2 Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-8fgdva12hl8w3xzzpsvvg7nx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-record.txt | 4 +- tools/perf/builtin-record.c | 82 +++--------------------- tools/perf/util/header.c | 13 +--- 3 files changed, 11 insertions(+), 88 deletions(-) diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index d4da111ef53d..7e3258066bc9 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -65,12 +65,10 @@ OPTIONS -r:: --realtime=:: Collect data with this RT SCHED_FIFO priority. + -D:: --no-delay:: Collect data without buffering. --A:: ---append:: - Append to the output file to do incremental profiling. -f:: --force:: diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index fff985cf3852..2990570b5c6d 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -61,11 +61,6 @@ static void __handle_on_exit_funcs(void) } #endif -enum write_mode_t { - WRITE_FORCE, - WRITE_APPEND -}; - struct perf_record { struct perf_tool tool; struct perf_record_opts opts; @@ -77,12 +72,9 @@ struct perf_record { int output; unsigned int page_size; int realtime_prio; - enum write_mode_t write_mode; bool no_buildid; bool no_buildid_cache; bool force; - bool file_new; - bool append_file; long samples; off_t post_processing_offset; }; @@ -200,25 +192,6 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) signal(signr, SIG_DFL); } -static bool perf_evlist__equal(struct perf_evlist *evlist, - struct perf_evlist *other) -{ - struct perf_evsel *pos, *pair; - - if (evlist->nr_entries != other->nr_entries) - return false; - - pair = perf_evlist__first(other); - - list_for_each_entry(pos, &evlist->entries, node) { - if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0)) - return false; - pair = perf_evsel__next(pair); - } - - return true; -} - static int perf_record__open(struct perf_record *rec) { char msg[512]; @@ -273,16 +246,7 @@ static int perf_record__open(struct perf_record *rec) goto out; } - if (rec->file_new) - session->evlist = evlist; - else { - if (!perf_evlist__equal(session->evlist, evlist)) { - fprintf(stderr, "incompatible append\n"); - rc = -1; - goto out; - } - } - + session->evlist = evlist; perf_session__set_id_hdr_size(session); out: return rc; @@ -415,23 +379,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (!strcmp(output_name, "-")) opts->pipe_output = true; else if (!stat(output_name, &st) && st.st_size) { - if (rec->write_mode == WRITE_FORCE) { - char oldname[PATH_MAX]; - snprintf(oldname, sizeof(oldname), "%s.old", - output_name); - unlink(oldname); - rename(output_name, oldname); - } - } else if (rec->write_mode == WRITE_APPEND) { - rec->write_mode = WRITE_FORCE; + char oldname[PATH_MAX]; + snprintf(oldname, sizeof(oldname), "%s.old", + output_name); + unlink(oldname); + rename(output_name, oldname); } } - flags = O_CREAT|O_RDWR; - if (rec->write_mode == WRITE_APPEND) - rec->file_new = 0; - else - flags |= O_TRUNC; + flags = O_CREAT|O_RDWR|O_TRUNC; if (opts->pipe_output) output = STDOUT_FILENO; @@ -445,7 +401,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) rec->output = output; session = perf_session__new(output_name, O_WRONLY, - rec->write_mode == WRITE_FORCE, false, NULL); + true, false, NULL); if (session == NULL) { pr_err("Not enough memory for reading perf file header\n"); return -1; @@ -465,12 +421,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) if (!rec->opts.branch_stack) perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); - if (!rec->file_new) { - err = perf_session__read_header(session, output); - if (err < 0) - goto out_delete_session; - } - if (forks) { err = perf_evlist__prepare_workload(evsel_list, &opts->target, argv, opts->pipe_output, @@ -498,7 +448,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) err = perf_header__write_pipe(output); if (err < 0) goto out_delete_session; - } else if (rec->file_new) { + } else { err = perf_session__write_header(session, evsel_list, output, false); if (err < 0) @@ -869,8 +819,6 @@ static struct perf_record record = { .uses_mmap = true, }, }, - .write_mode = WRITE_FORCE, - .file_new = true, }; #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " @@ -906,8 +854,6 @@ const struct option record_options[] = { "collect raw sample records from all opened counters"), OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide, "system-wide collection from all CPUs"), - OPT_BOOLEAN('A', "append", &record.append_file, - "append to the output file to do incremental profiling"), OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", "list of cpus to monitor"), OPT_BOOLEAN('f', "force", &record.force, @@ -977,16 +923,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) if (!argc && perf_target__none(&rec->opts.target)) usage_with_options(record_usage, record_options); - if (rec->force && rec->append_file) { - ui__error("Can't overwrite and append at the same time." - " You need to choose between -f and -A"); - usage_with_options(record_usage, record_options); - } else if (rec->append_file) { - rec->write_mode = WRITE_APPEND; - } else { - rec->write_mode = WRITE_FORCE; - } - if (nr_cgroups && !rec->opts.target.system_wide) { ui__error("cgroup monitoring only available in" " system-wide mode\n"); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 738d3b8d9745..93dd31573fb5 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2303,29 +2303,18 @@ int perf_session__write_header(struct perf_session *session, struct perf_file_header f_header; struct perf_file_attr f_attr; struct perf_header *header = &session->header; - struct perf_evsel *evsel, *pair = NULL; + struct perf_evsel *evsel; int err; lseek(fd, sizeof(f_header), SEEK_SET); - if (session->evlist != evlist) - pair = perf_evlist__first(session->evlist); - list_for_each_entry(evsel, &evlist->entries, node) { evsel->id_offset = lseek(fd, 0, SEEK_CUR); err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); if (err < 0) { -out_err_write: pr_debug("failed to write perf header\n"); return err; } - if (session->evlist != evlist) { - err = do_write(fd, pair->id, pair->ids * sizeof(u64)); - if (err < 0) - goto out_err_write; - evsel->ids += pair->ids; - pair = perf_evsel__next(pair); - } } header->attr_offset = lseek(fd, 0, SEEK_CUR); -- GitLab From 4a4d371a4dfbd3b84a7eab8d535d4c7c3647b09e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 5 Jun 2013 13:37:21 +0200 Subject: [PATCH 2459/2900] perf record: Remove -f/--force option It no longer have any affect on the processing and is marked as obsolete anyway. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-tvwyspiqr4getzfib2lw06ty@git.kernel.org Link: http://lkml.kernel.org/r/1372307120-737-1-git-send-email-namhyung@kernel.org [ combined patch removing the -f usage in various sub-commands, such as 'perf sched', etc, by Namhyung Kim ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/examples.txt | 4 ++-- tools/perf/Documentation/perf-record.txt | 4 ---- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-lock.c | 2 +- tools/perf/builtin-record.c | 3 --- tools/perf/builtin-sched.c | 1 - tools/perf/builtin-timechart.c | 4 ++-- 7 files changed, 6 insertions(+), 14 deletions(-) diff --git a/tools/perf/Documentation/examples.txt b/tools/perf/Documentation/examples.txt index 77f952762426..a4e392156488 100644 --- a/tools/perf/Documentation/examples.txt +++ b/tools/perf/Documentation/examples.txt @@ -66,7 +66,7 @@ Furthermore, these tracepoints can be used to sample the workload as well. For example the page allocations done by a 'git gc' can be captured the following way: - titan:~/git> perf record -f -e kmem:mm_page_alloc -c 1 ./git gc + titan:~/git> perf record -e kmem:mm_page_alloc -c 1 ./git gc Counting objects: 1148, done. Delta compression using up to 2 threads. Compressing objects: 100% (450/450), done. @@ -120,7 +120,7 @@ Furthermore, call-graph sampling can be done too, of page allocations - to see precisely what kind of page allocations there are: - titan:~/git> perf record -f -g -e kmem:mm_page_alloc -c 1 ./git gc + titan:~/git> perf record -g -e kmem:mm_page_alloc -c 1 ./git gc Counting objects: 1148, done. Delta compression using up to 2 threads. Compressing objects: 100% (450/450), done. diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 7e3258066bc9..e297b74471b8 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -70,10 +70,6 @@ OPTIONS --no-delay:: Collect data without buffering. --f:: ---force:: - Overwrite existing data file. (deprecated) - -c:: --count=:: Event period to sample. diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 46878daca5cc..0259502638b4 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -708,7 +708,7 @@ static int parse_line_opt(const struct option *opt __maybe_unused, static int __cmd_record(int argc, const char **argv) { const char * const record_args[] = { - "record", "-a", "-R", "-f", "-c", "1", + "record", "-a", "-R", "-c", "1", "-e", "kmem:kmalloc", "-e", "kmem:kmalloc_node", "-e", "kmem:kfree", diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 425830069749..76543a4a7a30 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -878,7 +878,7 @@ static int __cmd_report(void) static int __cmd_record(int argc, const char **argv) { const char *record_args[] = { - "record", "-R", "-f", "-m", "1024", "-c", "1", + "record", "-R", "-m", "1024", "-c", "1", }; unsigned int rec_argc, i, j; const char **rec_argv; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2990570b5c6d..ecca62e27b28 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -74,7 +74,6 @@ struct perf_record { int realtime_prio; bool no_buildid; bool no_buildid_cache; - bool force; long samples; off_t post_processing_offset; }; @@ -856,8 +855,6 @@ const struct option record_options[] = { "system-wide collection from all CPUs"), OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", "list of cpus to monitor"), - OPT_BOOLEAN('f', "force", &record.force, - "overwrite existing data file (deprecated)"), OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), OPT_STRING('o', "output", &record.output_name, "file", "output file name"), diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 2da2a6ca22bf..fed9ae432c16 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1632,7 +1632,6 @@ static int __cmd_record(int argc, const char **argv) "record", "-a", "-R", - "-f", "-m", "1024", "-c", "1", "-e", "sched:sched_switch", diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index ab4cf232b852..4536a92b18f3 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -1005,7 +1005,7 @@ static int __cmd_record(int argc, const char **argv) { #ifdef SUPPORT_OLD_POWER_EVENTS const char * const record_old_args[] = { - "record", "-a", "-R", "-f", "-c", "1", + "record", "-a", "-R", "-c", "1", "-e", "power:power_start", "-e", "power:power_end", "-e", "power:power_frequency", @@ -1014,7 +1014,7 @@ static int __cmd_record(int argc, const char **argv) }; #endif const char * const record_new_args[] = { - "record", "-a", "-R", "-f", "-c", "1", + "record", "-a", "-R", "-c", "1", "-e", "power:cpu_frequency", "-e", "power:cpu_idle", "-e", "sched:sched_wakeup", -- GitLab From bcf3145fbeb1bd91ad2ca67b1946077530f7bfb1 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 26 Jun 2013 16:14:15 +0900 Subject: [PATCH 2460/2900] perf evlist: Enhance perf_evlist__start_workload() When perf tries to start a workload, it relies on a pipe which the workload was blocked for reading. After closing the pipe on the parent, the workload (child) can start the actual work via exec(). However, if another process was forked after creating a workload, this mechanism cannot work since the other process (child) also inherits the pipe, so that closing the pipe in parent cannot unblock the workload. Fix it by using explicit write call can then closing it. For similar reason, the pipe fd on parent should be marked as CLOEXEC so that it can be closed after another child exec'ed. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1372230862-15861-13-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 99b43dd18c57..8065ce8fa9a5 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -821,6 +821,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, goto out_close_pipes; } + fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC); evlist->workload.cork_fd = go_pipe[1]; close(child_ready_pipe[0]); return 0; @@ -837,10 +838,17 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, int perf_evlist__start_workload(struct perf_evlist *evlist) { if (evlist->workload.cork_fd > 0) { + char bf; + int ret; /* * Remove the cork, let it rip! */ - return close(evlist->workload.cork_fd); + ret = write(evlist->workload.cork_fd, &bf, 1); + if (ret < 0) + perror("enable to write to pipe"); + + close(evlist->workload.cork_fd); + return ret; } return 0; -- GitLab From 0276c22a3f22b7f6696fa07b0a77635726b2c0fd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 10 Jun 2013 08:21:21 +0200 Subject: [PATCH 2461/2900] perf tools: Fix -x/--exclude-other option for report command Currently we have symbol_conf.exclude_other being set as true every time so the -x/--exclude-other has nothing to do. Also we have no way to see the data with symbol_conf.exclude_other being false which is useful sometimes. Fixing it by making symbol_conf.exclude_other false by default. 1) Example without -x option: $ perf report -i perf.data.delete -p perf_session__delete -s parent + 99.91% [other] + 0.08% perf_session__delete + 0.00% perf_session__delete_dead_threads + 0.00% perf_session__delete_threads 2) Example with -x option: $ ./perf report -i perf.data.delete -p perf_session__delete -s parent -x + 96.22% perf_session__delete + 1.89% perf_session__delete_dead_threads + 1.89% perf_session__delete_threads In Example 1) we get the sorted out data together with the rest "[other]". This could help us estimate how much time we spent in the sorted data. In Example 2) the total is just the sorted data. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-sg8fvu0fyqohf9ur9l38lhkw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 1 - tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-top.c | 2 -- tools/perf/util/symbol.c | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index da8f8eb383a0..0aac5f3e594d 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -607,7 +607,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) input_new = "perf.data.guest"; } - symbol_conf.exclude_other = false; if (symbol__init() < 0) return -1; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ca98d34cd58b..3662047cc6b1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -939,8 +939,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) */ if (!strstr(sort_order, "parent")) sort_parent.elide = 1; - } else - symbol_conf.exclude_other = false; + } if (argc) { /* diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f036af9b6f09..e06c4f869330 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1130,8 +1130,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) if (top.evlist == NULL) return -ENOMEM; - symbol_conf.exclude_other = false; - argc = parse_options(argc, argv, options, top_usage, 0); if (argc) usage_with_options(top_usage, options); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 8cf3b5426a9a..d5528e1cc03a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -32,7 +32,6 @@ int vmlinux_path__nr_entries; char **vmlinux_path; struct symbol_conf symbol_conf = { - .exclude_other = true, .use_modules = true, .try_vmlinux_path = true, .annotate_src = true, -- GitLab From 7e40c92019cef784fffbdfc51c6e731e7ee6ba10 Mon Sep 17 00:00:00 2001 From: Runzhen Wang Date: Fri, 28 Jun 2013 16:14:56 +0800 Subject: [PATCH 2462/2900] perf tools: fix a typo of a Power7 event name In the Power7 PMU guide: https://www.power.org/documentation/commonly-used-metrics-for-performance-analysis/ PM_BRU_MPRED is referred to as PM_BR_MPRED. It fixed the typo by changing the name of the event in kernel and documentation accordingly. This patch changes the ABI, there are some reasons I think it's ok: - It is relatively new interface, specific to the Power7 platform. - No tools that we know of actually use this interface at this point (none are listed near the interface). - Users of this interface (eg oprofile users migrating to perf) would be more used to the "PM_BR_MPRED" rather than "PM_BRU_MPRED". - These are in the ABI/testing at this point rather than ABI/stable, so hoping we have some wiggle room. Signed-off-by: Runzhen Wang Acked-by: Michael Ellerman Cc: icycoder@gmail.com Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman Cc: Paul Mackerras Cc: Runzhen Wang Cc: Sukadev Bhattiprolu Cc: Xiao Guangrong Link: http://lkml.kernel.org/r/1372407297-6996-2-git-send-email-runzhen@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- .../testing/sysfs-bus-event_source-devices-events | 2 +- arch/powerpc/perf/power7-pmu.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events index 8b25ffb42562..3c1cc24361bd 100644 --- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events +++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events @@ -29,7 +29,7 @@ Description: Generic performance monitoring events What: /sys/devices/cpu/events/PM_1PLUS_PPC_CMPL /sys/devices/cpu/events/PM_BRU_FIN - /sys/devices/cpu/events/PM_BRU_MPRED + /sys/devices/cpu/events/PM_BR_MPRED /sys/devices/cpu/events/PM_CMPLU_STALL /sys/devices/cpu/events/PM_CMPLU_STALL_BRU /sys/devices/cpu/events/PM_CMPLU_STALL_DCACHE_MISS diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 13c3f0e547a2..d1821b8bbc4c 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c @@ -60,7 +60,7 @@ #define PME_PM_LD_REF_L1 0xc880 #define PME_PM_LD_MISS_L1 0x400f0 #define PME_PM_BRU_FIN 0x10068 -#define PME_PM_BRU_MPRED 0x400f6 +#define PME_PM_BR_MPRED 0x400f6 #define PME_PM_CMPLU_STALL_FXU 0x20014 #define PME_PM_CMPLU_STALL_DIV 0x40014 @@ -349,7 +349,7 @@ static int power7_generic_events[] = { [PERF_COUNT_HW_CACHE_REFERENCES] = PME_PM_LD_REF_L1, [PERF_COUNT_HW_CACHE_MISSES] = PME_PM_LD_MISS_L1, [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PME_PM_BRU_FIN, - [PERF_COUNT_HW_BRANCH_MISSES] = PME_PM_BRU_MPRED, + [PERF_COUNT_HW_BRANCH_MISSES] = PME_PM_BR_MPRED, }; #define C(x) PERF_COUNT_HW_CACHE_##x @@ -405,7 +405,7 @@ GENERIC_EVENT_ATTR(instructions, INST_CMPL); GENERIC_EVENT_ATTR(cache-references, LD_REF_L1); GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1); GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN); -GENERIC_EVENT_ATTR(branch-misses, BRU_MPRED); +GENERIC_EVENT_ATTR(branch-misses, BR_MPRED); POWER_EVENT_ATTR(CYC, CYC); POWER_EVENT_ATTR(GCT_NOSLOT_CYC, GCT_NOSLOT_CYC); @@ -414,7 +414,7 @@ POWER_EVENT_ATTR(INST_CMPL, INST_CMPL); POWER_EVENT_ATTR(LD_REF_L1, LD_REF_L1); POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1); POWER_EVENT_ATTR(BRU_FIN, BRU_FIN) -POWER_EVENT_ATTR(BRU_MPRED, BRU_MPRED); +POWER_EVENT_ATTR(BR_MPRED, BR_MPRED); POWER_EVENT_ATTR(CMPLU_STALL_FXU, CMPLU_STALL_FXU); POWER_EVENT_ATTR(CMPLU_STALL_DIV, CMPLU_STALL_DIV); @@ -449,7 +449,7 @@ static struct attribute *power7_events_attr[] = { GENERIC_EVENT_PTR(LD_REF_L1), GENERIC_EVENT_PTR(LD_MISS_L1), GENERIC_EVENT_PTR(BRU_FIN), - GENERIC_EVENT_PTR(BRU_MPRED), + GENERIC_EVENT_PTR(BR_MPRED), POWER_EVENT_PTR(CYC), POWER_EVENT_PTR(GCT_NOSLOT_CYC), @@ -458,7 +458,7 @@ static struct attribute *power7_events_attr[] = { POWER_EVENT_PTR(LD_REF_L1), POWER_EVENT_PTR(LD_MISS_L1), POWER_EVENT_PTR(BRU_FIN), - POWER_EVENT_PTR(BRU_MPRED), + POWER_EVENT_PTR(BR_MPRED), POWER_EVENT_PTR(CMPLU_STALL_FXU), POWER_EVENT_PTR(CMPLU_STALL_DIV), -- GitLab From 7cab84e8975cfb8a59ce3e79ce75e5eedd384484 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Jul 2013 13:27:20 -0600 Subject: [PATCH 2463/2900] perf evsel: Fix count parameter to read call in event_format__new per realloc above the length of the buffer is alloc_size, not BUFSIZ. Adjust length per size as done for buf start. Addresses some valgrind complaints: ==1870== Syscall param read(buf) points to unaddressable byte(s) ==1870== at 0x4E3F610: __read_nocancel (in /lib64/libpthread-2.14.90.so) ==1870== by 0x44AEE1: event_format__new (unistd.h:45) ==1870== by 0x44B025: perf_evsel__newtp (evsel.c:158) ==1870== by 0x451919: add_tracepoint_event (parse-events.c:395) ==1870== by 0x479815: parse_events_parse (parse-events.y:292) ==1870== by 0x45463A: parse_events_option (parse-events.c:861) ==1870== by 0x44FEE4: get_value (parse-options.c:113) ==1870== by 0x450767: parse_options_step (parse-options.c:192) ==1870== by 0x450C40: parse_options (parse-options.c:422) ==1870== by 0x42735F: cmd_record (builtin-record.c:918) ==1870== by 0x419D72: run_builtin (perf.c:319) ==1870== by 0x4195F2: main (perf.c:376) ==1870== Address 0xcffebf0 is 0 bytes after a block of size 8,192 alloc'd ==1870== at 0x4C2A62F: malloc (vg_replace_malloc.c:270) ==1870== by 0x4C2A7A3: realloc (vg_replace_malloc.c:662) ==1870== by 0x44AF07: event_format__new (evsel.c:121) ==1870== by 0x44B025: perf_evsel__newtp (evsel.c:158) ==1870== by 0x451919: add_tracepoint_event (parse-events.c:395) ==1870== by 0x479815: parse_events_parse (parse-events.y:292) ==1870== by 0x45463A: parse_events_option (parse-events.c:861) ==1870== by 0x44FEE4: get_value (parse-options.c:113) ==1870== by 0x450767: parse_options_step (parse-options.c:192) ==1870== by 0x450C40: parse_options (parse-options.c:422) ==1870== by 0x42735F: cmd_record (builtin-record.c:918) ==1870== by 0x419D72: run_builtin (perf.c:319) Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372793245-4136-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 63b6f8c8edf2..df99ebe852ae 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -124,7 +124,7 @@ struct event_format *event_format__new(const char *sys, const char *name) bf = nbf; } - n = read(fd, bf + size, BUFSIZ); + n = read(fd, bf + size, alloc_size - size); if (n < 0) goto out_free_bf; size += n; -- GitLab From b2c34fde048f3c85ef0716a8cdabbe46ac67d1e6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:23 +0300 Subject: [PATCH 2464/2900] perf tools: Fix parse_events_terms() segfault on error path On the error path, 'data.terms' may not have been initialised. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-5-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6c8bb0fb189b..d8dcb8dbb1e2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -860,7 +860,8 @@ int parse_events_terms(struct list_head *terms, const char *str) return 0; } - parse_events__free_terms(data.terms); + if (data.terms) + parse_events__free_terms(data.terms); return ret; } -- GitLab From 4be8be6b430611def94bcd583b7b302d197a9520 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:24 +0300 Subject: [PATCH 2465/2900] perf tools: Fix new_term() missing free on error path On the error path, newly allocated 'term' must be freed. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-6-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d8dcb8dbb1e2..995fc25db8c6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1184,6 +1184,7 @@ static int new_term(struct parse_events_term **_term, int type_val, term->val.str = str; break; default: + free(term); return -EINVAL; } -- GitLab From 7e0d6fc90fc6f9faea63a2b67233ae767903573c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:29 +0300 Subject: [PATCH 2466/2900] perf tools: Update symbol_conf.nr_events when processing attribute events Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-11-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 93dd31573fb5..a4dafbee2511 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2956,6 +2956,8 @@ int perf_event__process_attr(union perf_event *event, perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]); } + symbol_conf.nr_events = evlist->nr_entries; + return 0; } -- GitLab From 54bd269205c188967d565f1f5552b13d08ca1be0 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:34 +0300 Subject: [PATCH 2467/2900] perf evsel: Fix missing increment in sample parsing The final sample format bit used to be PERF_SAMPLE_STACK_USER which neglected to do a final increment of the array pointer. The result is that the following parsing might start at the wrong place. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-16-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index df99ebe852ae..c9c7494506a1 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1170,7 +1170,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, } else { data->user_stack.data = (char *)array; array += size / sizeof(*array); - data->user_stack.size = *array; + data->user_stack.size = *array++; } } -- GitLab From f9ceffb605be7b3b3b2a6e6d14dd0d7a97eae580 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Thu, 9 May 2013 10:42:48 -0400 Subject: [PATCH 2468/2900] perf symbols: Fix vdso list searching When "perf record" was used on a large machine with a lot of CPUs, the perf post-processing time (the time after the workload was done until the perf command itself exited) could take a lot of minutes and even hours depending on how large the resulting perf.data file was. While running AIM7 1500-user high_systime workload on a 80-core x86-64 system with a 3.9 kernel (with only the -s -a options used), the workload itself took about 2 minutes to run and the perf.data file had a size of 1108.746 MB. However, the post-processing step took more than 10 minutes. With a gprof-profiled perf binary, the time spent by perf was as follows: % cumulative self self total time seconds seconds calls s/call s/call name 96.90 822.10 822.10 192156 0.00 0.00 dsos__find 0.81 828.96 6.86 172089958 0.00 0.00 rb_next 0.41 832.44 3.48 48539289 0.00 0.00 rb_erase So 97% (822 seconds) of the time was spent in a single dsos_find() function. After analyzing the call-graph data below: ----------------------------------------------- 0.00 822.12 192156/192156 map__new [6] [7] 96.9 0.00 822.12 192156 vdso__dso_findnew [7] 822.10 0.00 192156/192156 dsos__find [8] 0.01 0.00 192156/192156 dsos__add [62] 0.01 0.00 192156/192366 dso__new [61] 0.00 0.00 1/45282525 memdup [31] 0.00 0.00 192156/192230 dso__set_long_name [91] ----------------------------------------------- 822.10 0.00 192156/192156 vdso__dso_findnew [7] [8] 96.9 822.10 0.00 192156 dsos__find [8] ----------------------------------------------- It was found that the vdso__dso_findnew() function failed to locate VDSO__MAP_NAME ("[vdso]") in the dso list and have to insert a new entry at the end for 192156 times. This problem is due to the fact that there are 2 types of name in the dso entry - short name and long name. The initial dso__new() adds "[vdso]" to both the short and long names. After that, vdso__dso_findnew() modifies the long name to something like /tmp/perf-vdso.so-NoXkDj. The dsos__find() function only compares the long name. As a result, the same vdso entry is duplicated many time in the dso list. This bug increases memory consumption as well as slows the symbol processing time to a crawl. To resolve this problem, the dsos__find() function interface was modified to enable searching either the long name or the short name. The vdso__dso_findnew() will now search only the short name while the other call sites search for the long name as before. With this change, the cpu time of perf was reduced from 848.38s to 15.77s and dsos__find() only accounted for 0.06% of the total time. 0.06 15.73 0.01 192151 0.00 0.00 dsos__find Signed-off-by: Waiman Long Acked-by: Ingo Molnar Cc: "Chandramouleeswaran, Aswin" Cc: "Norton, Scott J" Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1368110568-64714-1-git-send-email-Waiman.Long@hp.com [ replaced TRUE/FALSE with stdbool.h equivalents, fixing builds where those macros are not present (NO_LIBPYTHON=1 NO_LIBPERL=1), fix from Jiri Olsa ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 10 ++++++++-- tools/perf/util/dso.h | 3 ++- tools/perf/util/vdso.c | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 6f7d5a9d6b05..c4374f07603c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -513,10 +513,16 @@ void dsos__add(struct list_head *head, struct dso *dso) list_add_tail(&dso->node, head); } -struct dso *dsos__find(struct list_head *head, const char *name) +struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short) { struct dso *pos; + if (cmp_short) { + list_for_each_entry(pos, head, node) + if (strcmp(pos->short_name, name) == 0) + return pos; + return NULL; + } list_for_each_entry(pos, head, node) if (strcmp(pos->long_name, name) == 0) return pos; @@ -525,7 +531,7 @@ struct dso *dsos__find(struct list_head *head, const char *name) struct dso *__dsos__findnew(struct list_head *head, const char *name) { - struct dso *dso = dsos__find(head, name); + struct dso *dso = dsos__find(head, name, false); if (!dso) { dso = dso__new(name); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 450199ab51b5..d51aaf272c68 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -133,7 +133,8 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, const char *short_name, int dso_type); void dsos__add(struct list_head *head, struct dso *dso); -struct dso *dsos__find(struct list_head *head, const char *name); +struct dso *dsos__find(struct list_head *head, const char *name, + bool cmp_short); struct dso *__dsos__findnew(struct list_head *head, const char *name); bool __dsos__read_build_ids(struct list_head *head, bool with_hits); diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index e60951fcdb12..39159822d58f 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -91,7 +91,7 @@ void vdso__exit(void) struct dso *vdso__dso_findnew(struct list_head *head) { - struct dso *dso = dsos__find(head, VDSO__MAP_NAME); + struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true); if (!dso) { char *file; -- GitLab From 582ec0829b3dd74d8c0f58403a3f9df8cbaa9c7d Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Fri, 5 Jul 2013 19:06:45 +0200 Subject: [PATCH 2469/2900] perf stat: Fix per-socket output bug for uncore events This patch fixes a problem reported by Andi Kleen on perf stat when measuring uncore events: # perf stat --per-socket -e uncore_pcu/event=0x0/ -I1000 -a sleep 2 It would not report counts for the second socket. That was due to a cpu mapping bug in print_aggr(). This patch also fixes the socket numbering bug for events. Reported-by: Andi Kleen Signed-off-by: Stephane Eranian Tested-by: Andi Kleen Cc: Andi Kleen Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: zheng.z.yan@intel.com Link: http://lkml.kernel.org/r/20130705170645.GA32519@quad Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 95768afaae3e..352fbd7ff4a1 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -924,7 +924,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) static void print_aggr(char *prefix) { struct perf_evsel *counter; - int cpu, s, s2, id, nr; + int cpu, cpu2, s, s2, id, nr; u64 ena, run, val; if (!(aggr_map || aggr_get_id)) @@ -936,7 +936,8 @@ static void print_aggr(char *prefix) val = ena = run = 0; nr = 0; for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { - s2 = aggr_get_id(evsel_list->cpus, cpu); + cpu2 = perf_evsel__cpus(counter)->map[cpu]; + s2 = aggr_get_id(evsel_list->cpus, cpu2); if (s2 != id) continue; val += counter->counts->cpu[cpu].val; @@ -948,7 +949,7 @@ static void print_aggr(char *prefix) fprintf(output, "%s", prefix); if (run == 0 || ena == 0) { - aggr_printout(counter, cpu, nr); + aggr_printout(counter, id, nr); fprintf(output, "%*s%s%*s", csv_output ? 0 : 18, -- GitLab From a4147f0f91386540316e468f3a3674a498dada5f Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 8 May 2013 11:43:34 +0200 Subject: [PATCH 2470/2900] perf tools: Fix perf version generation The tag of the perf version is wrongly determined, always the latest tag is taken regardless of the HEAD commit: $ perf --version perf version 3.9.rc8.gd7f5d3 $ git describe d7f5d3 v3.9-rc7-154-gd7f5d33 $ head -n 4 Makefile VERSION = 3 PATCHLEVEL = 9 SUBLEVEL = 0 EXTRAVERSION = -rc7 In other cases no tag might be found. This patch fixes this. This new implementation handles also the case if there are no tags at all found in the git repo but there is a commit id. Signed-off-by: Robert Richter Link: http://lkml.kernel.org/r/1368006214-12912-1-git-send-email-rric@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/PERF-VERSION-GEN | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 055fef34b6f6..15a77b7c0e36 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -13,13 +13,22 @@ LF=' # First check if there is a .git to get the version from git describe # otherwise try to get the version from the kernel Makefile # -if test -d ../../.git -o -f ../../.git && - VN=$(git tag 2>/dev/null | tail -1 | grep -E "v[0-9].[0-9]*") +CID= +TAG= +if test -d ../../.git -o -f ../../.git then - VN=$(echo $VN"-g"$(git log -1 --abbrev=4 --pretty=format:"%h" HEAD)) - VN=$(echo "$VN" | sed -e 's/-/./g'); -else - VN=$(MAKEFLAGS= make -sC ../.. kernelversion) + TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null ) + CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID" +fi +if test -z "$TAG" +then + TAG=$(MAKEFLAGS= make -sC ../.. kernelversion) +fi +VN="$TAG$CID" +if test -n "$CID" +then + # format version string, strip trailing zero of sublevel: + VN=$(echo "$VN" | sed -e 's/-/./g;s/\([0-9]*[.][0-9]*\)[.]0/\1/') fi VN=$(expr "$VN" : v*'\(.*\)') -- GitLab From 0979292bfa301cb87d936b69af428090d2feea1b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 8 Jul 2013 13:44:45 -0400 Subject: [PATCH 2471/2900] svcrpc: fix failures to handle -1 uid's As of f025adf191924e3a75ce80e130afcd2485b53bb8 "sunrpc: Properly decode kuids and kgids in RPC_AUTH_UNIX credentials" any rpc containing a -1 (0xffff) uid or gid would fail with a badcred error. Commit afe3c3fd5392b2f0066930abc5dbd3f4b14a0f13 "svcrpc: fix failures to handle -1 uid's and gid's" fixed part of the problem, but overlooked the gid upcall--the kernel can request supplementary gid's for the -1 uid, but mountd's attempt write a response will get -EINVAL. Symptoms were nfsd failing to reply to the first attempt to use a newly negotiated krb5 context. Reported-by: Sven Geggus Tested-by: Sven Geggus Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- net/sunrpc/svcauth_unix.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index a98853dfccdc..621ca7b4a155 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -493,8 +493,6 @@ static int unix_gid_parse(struct cache_detail *cd, if (rv) return -EINVAL; uid = make_kuid(&init_user_ns, id); - if (!uid_valid(uid)) - return -EINVAL; ug.uid = uid; expiry = get_expiry(&mesg); -- GitLab From f0f51f5cdd107971282ae18f00a6fa03d69407a0 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 18 Jun 2013 14:26:02 -0400 Subject: [PATCH 2472/2900] nfsd4: allow destroy_session over destroyed session RFC 5661 allows a client to destroy a session using a compound associated with the destroyed session, as long as the DESTROY_SESSION op is the last op of the compound. We attempt to allow this, but testing against a Solaris client (which does destroy sessions in this way) showed that we were failing the DESTROY_SESSION with NFS4ERR_DELAY, because we assumed the reference count on the session (held by us) represented another rpc in progress over this session. Fix this by noting that in this case the expected reference count is 1, not 0. Also, note as long as the session holds a reference to the compound we're destroying, we can't free it here--instead, delay the free till the final put in nfs4svc_encode_compoundres. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 23 ++++++++++++++--------- fs/nfsd/nfs4xdr.c | 6 +++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d44a4bf71cef..25ae6cedb73a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -97,19 +97,20 @@ nfs4_lock_state(void) static void free_session(struct nfsd4_session *); -void nfsd4_put_session(struct nfsd4_session *ses) +static bool is_session_dead(struct nfsd4_session *ses) { - atomic_dec(&ses->se_ref); + return ses->se_flags & NFS4_SESSION_DEAD; } -static bool is_session_dead(struct nfsd4_session *ses) +void nfsd4_put_session(struct nfsd4_session *ses) { - return ses->se_flags & NFS4_SESSION_DEAD; + if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses)) + free_session(ses); } -static __be32 mark_session_dead_locked(struct nfsd4_session *ses) +static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me) { - if (atomic_read(&ses->se_ref)) + if (atomic_read(&ses->se_ref) > ref_held_by_me) return nfserr_jukebox; ses->se_flags |= NFS4_SESSION_DEAD; return nfs_ok; @@ -2074,6 +2075,7 @@ nfsd4_destroy_session(struct svc_rqst *r, { struct nfsd4_session *ses; __be32 status; + int ref_held_by_me = 0; struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id); nfs4_lock_state(); @@ -2081,6 +2083,7 @@ nfsd4_destroy_session(struct svc_rqst *r, if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) { if (!nfsd4_last_compound_op(r)) goto out; + ref_held_by_me++; } dump_sessionid(__func__, &sessionid->sessionid); spin_lock(&nn->client_lock); @@ -2091,17 +2094,19 @@ nfsd4_destroy_session(struct svc_rqst *r, status = nfserr_wrong_cred; if (!mach_creds_match(ses->se_client, r)) goto out_client_lock; - status = mark_session_dead_locked(ses); + nfsd4_get_session_locked(ses); + status = mark_session_dead_locked(ses, 1 + ref_held_by_me); if (status) - goto out_client_lock; + goto out_put_session; unhash_session(ses); spin_unlock(&nn->client_lock); nfsd4_probe_callback_sync(ses->se_client); spin_lock(&nn->client_lock); - free_session(ses); status = nfs_ok; +out_put_session: + nfsd4_put_session(ses); out_client_lock: spin_unlock(&nn->client_lock); out: diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index c102d2509a2a..0c0f3ea90de5 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3760,13 +3760,17 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; BUG_ON(iov->iov_len > PAGE_SIZE); if (nfsd4_has_session(cs)) { + struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); + struct nfs4_client *clp = cs->session->se_client; if (cs->status != nfserr_replay_cache) { nfsd4_store_cache_entry(resp); cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; } /* Renew the clientid on success and on replay */ - put_client_renew(cs->session->se_client); + spin_lock(&nn->client_lock); nfsd4_put_session(cs->session); + spin_unlock(&nn->client_lock); + put_client_renew(clp); } return 1; } -- GitLab From d109148111cdfcdae94f797dc142468bd0ff7557 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 8 Jul 2013 18:00:56 -0400 Subject: [PATCH 2473/2900] nfsd4: support minorversion 1 by default We now have minimal minorversion 1 support; turn it on by default. This can still be turned off with "echo -4.1 >/proc/fs/nfsd/versions". Signed-off-by: J. Bruce Fields --- fs/nfsd/nfssvc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 262df5ccbf59..6b9f48ca4c25 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -116,7 +116,7 @@ struct svc_program nfsd_program = { }; -u32 nfsd_supported_minorversion; +u32 nfsd_supported_minorversion = 1; int nfsd_vers(int vers, enum vers_op change) { -- GitLab From 62525a00b87cc967bce9779d63fcc84fb9199130 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 8 Jul 2013 10:33:37 +0930 Subject: [PATCH 2474/2900] virtio: VIRTIO_F_ANY_LAYOUT feature Also known as the "no really, I read the spec" bit. Signed-off-by: Rusty Russell --- include/uapi/linux/virtio_config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h index b7cda390fd00..3ce768c6910d 100644 --- a/include/uapi/linux/virtio_config.h +++ b/include/uapi/linux/virtio_config.h @@ -51,4 +51,7 @@ * suppressed them? */ #define VIRTIO_F_NOTIFY_ON_EMPTY 24 +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 + #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */ -- GitLab From c5610a5d7188b90fe0f927d2513bf684fb0bc427 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 8 Jul 2013 11:31:06 +0930 Subject: [PATCH 2475/2900] virtio: include asm/barrier explicitly virtio_ring.h uses mb() and friends, make it pull in asm/barrier.h itself, not rely on other headers to do it. Signed-off-by: Michael S. Tsirkin Signed-off-by: Rusty Russell --- include/linux/virtio_ring.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index ca3ad41c2c82..b300787af8e0 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h @@ -1,6 +1,7 @@ #ifndef _LINUX_VIRTIO_RING_H #define _LINUX_VIRTIO_RING_H +#include #include #include -- GitLab From 80390df8b263f1f6b7acb1df35a758736e3ec961 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 8 Jul 2013 11:31:10 +0930 Subject: [PATCH 2476/2900] tools/virtio: move module license stub to module.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes build for the vringh test: [linux]$ make -C tools/virtio/ make: Entering directory `/home/mst/scm/linux/tools/virtio' cc -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -c -o vringh.o ../../drivers/vhost/vringh.c ../../drivers/vhost/vringh.c:1010:16: error: expected declaration specifiers or ‘...’ before string constant Signed-off-by: Michael S. Tsirkin Signed-off-by: Rusty Russell --- tools/virtio/linux/module.h | 5 +++++ tools/virtio/linux/virtio.h | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h index 3039a7e972b6..28ce95a05997 100644 --- a/tools/virtio/linux/module.h +++ b/tools/virtio/linux/module.h @@ -1 +1,6 @@ #include + +#define MODULE_LICENSE(__MODULE_LICENSE_value) \ + static __attribute__((unused)) const char *__MODULE_LICENSE_name = \ + __MODULE_LICENSE_value + diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h index cd801838156f..844783040703 100644 --- a/tools/virtio/linux/virtio.h +++ b/tools/virtio/linux/virtio.h @@ -45,9 +45,6 @@ struct virtqueue { void *priv; }; -#define MODULE_LICENSE(__MODULE_LICENSE_value) \ - const char *__MODULE_LICENSE_name = __MODULE_LICENSE_value - /* Interfaces exported by virtio_ring. */ int virtqueue_add_sgs(struct virtqueue *vq, struct scatterlist *sgs[], -- GitLab From c893c8d763d8a8a757028a48ace7d1bb2dd8373f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 8 Jul 2013 11:31:13 +0930 Subject: [PATCH 2477/2900] MAINTAINERS: add tools/virtio/ under virtio This should help make sure patches go to the correct list. Signed-off-by: Michael S. Tsirkin Signed-off-by: Rusty Russell --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3a7b07f513da..0680f447d740 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8758,6 +8758,7 @@ M: "Michael S. Tsirkin" L: virtualization@lists.linux-foundation.org S: Maintained F: drivers/virtio/ +F: tools/virtio/ F: drivers/net/virtio_net.c F: drivers/block/virtio_blk.c F: include/linux/virtio_*.h -- GitLab From cbf55001b2ddb814329735641be5d29b08c82b08 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Mon, 8 Jul 2013 16:20:34 +0300 Subject: [PATCH 2478/2900] net: rename low latency sockets functions to busy poll Rename functions in include/net/ll_poll.h to busy wait. Clarify documentation about expected power use increase. Rename POLL_LL to POLL_BUSY_LOOP. Add need_resched() testing to poll/select busy loops. Note, that in select and poll can_busy_poll is dynamic and is updated continuously to reflect the existence of supported sockets with valid queue information. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 12 ++++--- fs/select.c | 60 ++++++++++++++++++++------------- include/net/ll_poll.h | 46 +++++++++++++------------ include/uapi/asm-generic/poll.h | 2 +- net/core/datagram.c | 3 +- net/ipv4/tcp.c | 6 ++-- net/socket.c | 12 +++---- 7 files changed, 80 insertions(+), 61 deletions(-) diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index e658bbfb641f..7323b88e26be 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -53,22 +53,24 @@ Default: 64 low_latency_read ---------------- Low latency busy poll timeout for socket reads. (needs CONFIG_NET_LL_RX_POLL) -Approximate time in us to spin waiting for packets on the device queue. +Approximate time in us to busy loop waiting for packets on the device queue. This sets the default value of the SO_LL socket option. -Can be set or overridden per socket by setting socket option SO_LL. -Recommended value is 50. May increase power usage. +Can be set or overridden per socket by setting socket option SO_LL, which is +the preferred method of enabling. +If you need to enable the feature globally via sysctl, a value of 50 is recommended. +Will increase power usage. Default: 0 (off) low_latency_poll ---------------- Low latency busy poll timeout for poll and select. (needs CONFIG_NET_LL_RX_POLL) -Approximate time in us to spin waiting for packets on the device queue. +Approximate time in us to busy loop waiting for events. Recommended value depends on the number of sockets you poll on. For several sockets 50, for several hundreds 100. For more than that you probably want to use epoll. Note that only sockets with SO_LL set will be busy polled, so you want to either selectively set SO_LL on those sockets or set sysctl.net.low_latency_read globally. -May increase power usage. +Will increase power usage. Default: 0 (off) rmem_default diff --git a/fs/select.c b/fs/select.c index f28a58592725..25cac5faf6d6 100644 --- a/fs/select.c +++ b/fs/select.c @@ -402,9 +402,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) poll_table *wait; int retval, i, timed_out = 0; unsigned long slack = 0; - unsigned int ll_flag = ll_get_flag(); - u64 ll_start = ll_start_time(ll_flag); - u64 ll_time = ll_run_time(); + unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; + u64 busy_start = busy_loop_start_time(busy_flag); + u64 busy_end = busy_loop_end_time(); rcu_read_lock(); retval = max_select_fd(n, fds); @@ -427,7 +427,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) retval = 0; for (;;) { unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; - bool can_ll = false; + bool can_busy_loop = false; inp = fds->in; outp = fds->out; exp = fds->ex; rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; @@ -456,7 +456,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) mask = DEFAULT_POLLMASK; if (f_op && f_op->poll) { wait_key_set(wait, in, out, - bit, ll_flag); + bit, busy_flag); mask = (*f_op->poll)(f.file, wait); } fdput(f); @@ -475,11 +475,18 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) retval++; wait->_qproc = NULL; } - if (mask & POLL_LL) - can_ll = true; /* got something, stop busy polling */ - if (retval) - ll_flag = 0; + if (retval) { + can_busy_loop = false; + busy_flag = 0; + + /* + * only remember a returned + * POLL_BUSY_LOOP if we asked for it + */ + } else if (busy_flag & mask) + can_busy_loop = true; + } } if (res_in) @@ -498,8 +505,9 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) break; } - /* only if on, have sockets with POLL_LL and not out of time */ - if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time)) + /* only if found POLL_BUSY_LOOP sockets && not out of time */ + if (!need_resched() && can_busy_loop && + busy_loop_range(busy_start, busy_end)) continue; /* @@ -734,7 +742,8 @@ struct poll_list { * if pwait->_qproc is non-NULL. */ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait, - bool *can_ll, unsigned int ll_flag) + bool *can_busy_poll, + unsigned int busy_flag) { unsigned int mask; int fd; @@ -748,10 +757,10 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait, mask = DEFAULT_POLLMASK; if (f.file->f_op && f.file->f_op->poll) { pwait->_key = pollfd->events|POLLERR|POLLHUP; - pwait->_key |= ll_flag; + pwait->_key |= busy_flag; mask = f.file->f_op->poll(f.file, pwait); - if (mask & POLL_LL) - *can_ll = true; + if (mask & busy_flag) + *can_busy_poll = true; } /* Mask out unneeded events. */ mask &= pollfd->events | POLLERR | POLLHUP; @@ -770,9 +779,10 @@ static int do_poll(unsigned int nfds, struct poll_list *list, ktime_t expire, *to = NULL; int timed_out = 0, count = 0; unsigned long slack = 0; - unsigned int ll_flag = ll_get_flag(); - u64 ll_start = ll_start_time(ll_flag); - u64 ll_time = ll_run_time(); + unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; + u64 busy_start = busy_loop_start_time(busy_flag); + u64 busy_end = busy_loop_end_time(); + /* Optimise the no-wait case */ if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { @@ -785,7 +795,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, for (;;) { struct poll_list *walk; - bool can_ll = false; + bool can_busy_loop = false; for (walk = list; walk != NULL; walk = walk->next) { struct pollfd * pfd, * pfd_end; @@ -800,10 +810,13 @@ static int do_poll(unsigned int nfds, struct poll_list *list, * this. They'll get immediately deregistered * when we break out and return. */ - if (do_pollfd(pfd, pt, &can_ll, ll_flag)) { + if (do_pollfd(pfd, pt, &can_busy_loop, + busy_flag)) { count++; pt->_qproc = NULL; - ll_flag = 0; + /* found something, stop busy polling */ + busy_flag = 0; + can_busy_loop = false; } } } @@ -820,8 +833,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list, if (count || timed_out) break; - /* only if on, have sockets with POLL_LL and not out of time */ - if (ll_flag && can_ll && can_poll_ll(ll_start, ll_time)) + /* only if found POLL_BUSY_LOOP sockets && not out of time */ + if (!need_resched() && can_busy_loop && + busy_loop_range(busy_start, busy_end)) continue; /* diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index 0d620ba19bc5..f14dd88dafc8 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -37,9 +37,9 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; #define LL_FLUSH_FAILED -1 #define LL_FLUSH_BUSY -2 -static inline unsigned int ll_get_flag(void) +static inline bool net_busy_loop_on(void) { - return sysctl_net_ll_poll ? POLL_LL : 0; + return sysctl_net_ll_poll; } /* a wrapper to make debug_smp_processor_id() happy @@ -47,7 +47,7 @@ static inline unsigned int ll_get_flag(void) * we only care that the average is bounded */ #ifdef CONFIG_DEBUG_PREEMPT -static inline u64 ll_sched_clock(void) +static inline u64 busy_loop_sched_clock(void) { u64 rc; @@ -58,7 +58,7 @@ static inline u64 ll_sched_clock(void) return rc; } #else /* CONFIG_DEBUG_PREEMPT */ -static inline u64 ll_sched_clock(void) +static inline u64 busy_loop_sched_clock(void) { return sched_clock(); } @@ -67,7 +67,7 @@ static inline u64 ll_sched_clock(void) /* we don't mind a ~2.5% imprecision so <<10 instead of *1000 * sk->sk_ll_usec is a u_int so this can't overflow */ -static inline u64 ll_sk_run_time(struct sock *sk) +static inline u64 sk_busy_loop_end_time(struct sock *sk) { return (u64)ACCESS_ONCE(sk->sk_ll_usec) << 10; } @@ -75,27 +75,29 @@ static inline u64 ll_sk_run_time(struct sock *sk) /* in poll/select we use the global sysctl_net_ll_poll value * only call sched_clock() if enabled */ -static inline u64 ll_run_time(void) +static inline u64 busy_loop_end_time(void) { return (u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10; } -/* if flag is not set we don't need to know the time */ -static inline u64 ll_start_time(unsigned int flag) +/* if flag is not set we don't need to know the time + * so we want to avoid a potentially expensive sched_clock() + */ +static inline u64 busy_loop_start_time(unsigned int flag) { - return flag ? ll_sched_clock() : 0; + return flag ? busy_loop_sched_clock() : 0; } -static inline bool sk_valid_ll(struct sock *sk) +static inline bool sk_can_busy_loop(struct sock *sk) { return sk->sk_ll_usec && sk->sk_napi_id && !need_resched() && !signal_pending(current); } /* careful! time_in_range64 will evaluate now twice */ -static inline bool can_poll_ll(u64 start_time, u64 run_time) +static inline bool busy_loop_range(u64 start_time, u64 run_time) { - u64 now = ll_sched_clock(); + u64 now = busy_loop_sched_clock(); return time_in_range64(now, start_time, start_time + run_time); } @@ -103,10 +105,10 @@ static inline bool can_poll_ll(u64 start_time, u64 run_time) /* when used in sock_poll() nonblock is known at compile time to be true * so the loop and end_time will be optimized out */ -static inline bool sk_poll_ll(struct sock *sk, int nonblock) +static inline bool sk_busy_loop(struct sock *sk, int nonblock) { - u64 start_time = ll_start_time(!nonblock); - u64 run_time = ll_sk_run_time(sk); + u64 start_time = busy_loop_start_time(!nonblock); + u64 end_time = sk_busy_loop_end_time(sk); const struct net_device_ops *ops; struct napi_struct *napi; int rc = false; @@ -137,7 +139,7 @@ static inline bool sk_poll_ll(struct sock *sk, int nonblock) LINUX_MIB_LOWLATENCYRXPACKETS, rc); } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && - can_poll_ll(start_time, run_time)); + busy_loop_range(start_time, end_time)); rc = !skb_queue_empty(&sk->sk_receive_queue); out: @@ -158,27 +160,27 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) } #else /* CONFIG_NET_LL_RX_POLL */ -static inline unsigned long ll_get_flag(void) +static inline unsigned long net_busy_loop_on(void) { return 0; } -static inline u64 ll_start_time(unsigned int flag) +static inline u64 busy_loop_start_time(unsigned int flag) { return 0; } -static inline u64 ll_run_time(void) +static inline u64 busy_loop_end_time(void) { return 0; } -static inline bool sk_valid_ll(struct sock *sk) +static inline bool sk_can_busy_loop(struct sock *sk) { return false; } -static inline bool sk_poll_ll(struct sock *sk, int nonblock) +static inline bool sk_busy_poll(struct sock *sk, int nonblock) { return false; } @@ -191,7 +193,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) { } -static inline bool can_poll_ll(u64 start_time, u64 run_time) +static inline bool busy_loop_range(u64 start_time, u64 run_time) { return false; } diff --git a/include/uapi/asm-generic/poll.h b/include/uapi/asm-generic/poll.h index 4aee586979ca..a9694982689f 100644 --- a/include/uapi/asm-generic/poll.h +++ b/include/uapi/asm-generic/poll.h @@ -30,7 +30,7 @@ #define POLLFREE 0x4000 /* currently only for epoll */ -#define POLL_LL 0x8000 +#define POLL_BUSY_LOOP 0x8000 struct pollfd { int fd; diff --git a/net/core/datagram.c b/net/core/datagram.c index 9cbaba98ce4c..6e9ab31e457e 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -208,7 +208,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags, } spin_unlock_irqrestore(&queue->lock, cpu_flags); - if (sk_valid_ll(sk) && sk_poll_ll(sk, flags & MSG_DONTWAIT)) + if (sk_can_busy_loop(sk) && + sk_busy_loop(sk, flags & MSG_DONTWAIT)) continue; /* User doesn't want to wait */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 46ed9afd1f5e..15cbfa94bd8e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1554,9 +1554,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct sk_buff *skb; u32 urg_hole = 0; - if (sk_valid_ll(sk) && skb_queue_empty(&sk->sk_receive_queue) - && (sk->sk_state == TCP_ESTABLISHED)) - sk_poll_ll(sk, nonblock); + if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) && + (sk->sk_state == TCP_ESTABLISHED)) + sk_busy_loop(sk, nonblock); lock_sock(sk); diff --git a/net/socket.c b/net/socket.c index 4da14cbd49b6..45afa648364a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1148,7 +1148,7 @@ EXPORT_SYMBOL(sock_create_lite); /* No kernel lock held - perfect */ static unsigned int sock_poll(struct file *file, poll_table *wait) { - unsigned int ll_flag = 0; + unsigned int busy_flag = 0; struct socket *sock; /* @@ -1156,16 +1156,16 @@ static unsigned int sock_poll(struct file *file, poll_table *wait) */ sock = file->private_data; - if (sk_valid_ll(sock->sk)) { + if (sk_can_busy_loop(sock->sk)) { /* this socket can poll_ll so tell the system call */ - ll_flag = POLL_LL; + busy_flag = POLL_BUSY_LOOP; /* once, only if requested by syscall */ - if (wait && (wait->_key & POLL_LL)) - sk_poll_ll(sock->sk, 1); + if (wait && (wait->_key & POLL_BUSY_LOOP)) + sk_busy_loop(sock->sk, 1); } - return ll_flag | sock->ops->poll(file, sock, wait); + return busy_flag | sock->ops->poll(file, sock, wait); } static int sock_mmap(struct file *file, struct vm_area_struct *vma) -- GitLab From 48e3b9855d6e1b408ec4a808f243e858a78f4482 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:50:34 +0530 Subject: [PATCH 2479/2900] [SCSI] mpt3sas: 2013 source code copyright The Copyright String in all mpt3sas files are changed to 2012-2013. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/Kconfig | 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_config.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_ctl.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_debug.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_transport.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig index 81471bf415d8..d53e1b02e893 100644 --- a/drivers/scsi/mpt3sas/Kconfig +++ b/drivers/scsi/mpt3sas/Kconfig @@ -2,7 +2,7 @@ # Kernel configuration file for the MPT3SAS # # This code is based on drivers/scsi/mpt3sas/Kconfig -# Copyright (C) 2012 LSI Corporation +# Copyright (C) 2012-2013 LSI Corporation # (mailto:DL-MPTFusionLinux@lsi.com) # This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 18360032a520..673a1b53a23f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -3,7 +3,7 @@ * for access to MPT (Message Passing Technology) firmware. * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 994656cbfac9..36106470530b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -3,7 +3,7 @@ * for access to MPT (Message Passing Technology) firmware. * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 4db0c7a18bd8..936ec0391990 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -2,7 +2,7 @@ * This module provides common API for accessing firmware configuration pages * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 0b402b6f2d26..9b89de14a0a3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -3,7 +3,7 @@ * controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h index bd89f4f00550..53b0c480d98f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h @@ -3,7 +3,7 @@ * controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_debug.h b/drivers/scsi/mpt3sas/mpt3sas_debug.h index 35405e7044f8..545b22d2cbdf 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_debug.h +++ b/drivers/scsi/mpt3sas/mpt3sas_debug.h @@ -2,7 +2,7 @@ * Logging Support for MPT (Message Passing Technology) based controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_debug.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index dcbf7c880cb2..73d3b81a0d06 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2,7 +2,7 @@ * Scsi Host Layer for MPT (Message Passing Technology) based controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 87ca2b7287c3..dcadd56860ff 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -2,7 +2,7 @@ * SAS Transport Layer for MPT (Message Passing Technology) based controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c index 6f8d6213040b..f6533ab20364 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c +++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c @@ -3,7 +3,7 @@ * (Message Passing Technology) based controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h index a10c30907394..bb693923bef1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h +++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h @@ -4,7 +4,7 @@ * controllers * * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012 LSI Corporation + * Copyright (C) 2012-2013 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * * This program is free software; you can redistribute it and/or -- GitLab From b453ff84de6caf3ad3a988da8444c13b71e3f507 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:51:19 +0530 Subject: [PATCH 2480/2900] [SCSI] mpt3sas: Updated the Hardware timing requirements Hardware timing requirements is updated in order to comply with firmware requirement. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_base.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 673a1b53a23f..5dc280c75325 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4090,11 +4090,15 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, &ioc->chip->HostDiagnostic); - /* don't access any registers for 50 milliseconds */ - msleep(50); + /*This delay allows the chip PCIe hardware time to finish reset tasks*/ + if (sleep_flag == CAN_SLEEP) + msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); + else + mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); - /* 300 second max wait */ - for (count = 0; count < 3000000 ; count++) { + /* Approximately 300 second max wait */ + for (count = 0; count < (300000000 / + MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) { host_diagnostic = readl(&ioc->chip->HostDiagnostic); @@ -4103,11 +4107,13 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) break; - /* wait 1 msec */ + /* Wait to pass the second read delay window */ if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); + msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC + / 1000); else - mdelay(1); + mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC + / 1000); } if (host_diagnostic & MPI2_DIAG_HCB_MODE) { -- GitLab From b65cfedf4560af65305bd7b3b9f26c02c6fb3660 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:52:03 +0530 Subject: [PATCH 2481/2900] [SCSI] mpt3sas: fix for kernel panic when driver loads with HBA conected to non LUN 0 configured expander With some enclosures when LUN 0 is not created but LUN 1 or LUN X is created then SCSI scan procedure calls target_alloc, slave_alloc call back functions for LUN 0 and slave_destory() for same LUN 0. In these kind of cases within slave_destroy, pointer to scsi_target in _sas_device structure is set to NULL, following which when slave_alloc for LUN 1 is called then starget would not be set properly for this LUN. So, scsi_target pointer pointing to NULL value would lead to a crash later in the discovery procedure. To solve this issue set the sas_device's scsi_target pointer to scsi_device's scsi_target if it is NULL earlier in slave_alloc callback function. Signed-off-by: Sreekanth Reddy Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 73d3b81a0d06..9ebc9dce3046 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -1273,6 +1273,7 @@ _scsih_slave_alloc(struct scsi_device *sdev) struct MPT3SAS_DEVICE *sas_device_priv_data; struct scsi_target *starget; struct _raid_device *raid_device; + struct _sas_device *sas_device; unsigned long flags; sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); @@ -1301,6 +1302,19 @@ _scsih_slave_alloc(struct scsi_device *sdev) spin_unlock_irqrestore(&ioc->raid_device_lock, flags); } + if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, + sas_target_priv_data->sas_address); + if (sas_device && (sas_device->starget == NULL)) { + sdev_printk(KERN_INFO, sdev, + "%s : sas_device->starget set to starget @ %d\n", + __func__, __LINE__); + sas_device->starget = starget; + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + } + return 0; } -- GitLab From 259c9b1712242fb3c841d49020a4f179f0c1920c Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 28 May 2013 13:25:44 +0800 Subject: [PATCH 2482/2900] kgdb: blackfin: include irq_regs.h in kgdb.c The function definition of get_irq_regs() is moved to asm header irq_regs.h. Signed-off-by: Sonic Zhang --- arch/blackfin/kernel/kgdb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index b882ce22c347..fa53faeeb0e9 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c @@ -9,6 +9,7 @@ #include /* for linux pt_regs struct */ #include #include +#include void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { -- GitLab From 5e50175bdceefac46427c2cc6ae340a2ac045de5 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 3 Jul 2013 16:48:19 +0800 Subject: [PATCH 2483/2900] bf609: rename bfin6xx_spi to bfin_spi3 Signed-off-by: Scott Jiang Signed-off-by: Steven Miao --- .../include/asm/{bfin6xx_spi.h => bfin_spi3.h} | 4 ++-- arch/blackfin/mach-bf609/boards/ezkit.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) rename arch/blackfin/include/asm/{bfin6xx_spi.h => bfin_spi3.h} (99%) diff --git a/arch/blackfin/include/asm/bfin6xx_spi.h b/arch/blackfin/include/asm/bfin_spi3.h similarity index 99% rename from arch/blackfin/include/asm/bfin6xx_spi.h rename to arch/blackfin/include/asm/bfin_spi3.h index 89370b653dcd..0957e65a54be 100644 --- a/arch/blackfin/include/asm/bfin6xx_spi.h +++ b/arch/blackfin/include/asm/bfin_spi3.h @@ -240,7 +240,7 @@ struct bfin_spi_regs { #define MAX_CTRL_CS 8 /* cs in spi controller */ /* device.platform_data for SSP controller devices */ -struct bfin6xx_spi_master { +struct bfin_spi3_master { u16 num_chipselect; u16 pin_req[7]; }; @@ -248,7 +248,7 @@ struct bfin6xx_spi_master { /* spi_board_info.controller_data for SPI slave devices, * copied to spi_device.platform_data ... mostly for dma tuning */ -struct bfin6xx_spi_chip { +struct bfin_spi3_chip { u32 control; u16 cs_chg_udelay; /* Some devices require 16-bit delays */ u32 tx_dummy_val; /* tx value for rx only transfer */ diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index 97d701639585..6939ac3a805e 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -745,13 +745,13 @@ static struct flash_platform_data bfin_spi_flash_data = { .type = "w25q32", }; -static struct bfin6xx_spi_chip spi_flash_chip_info = { +static struct bfin_spi3_chip spi_flash_chip_info = { .enable_dma = true, /* use dma transfer with this chip*/ }; #endif #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) -static struct bfin6xx_spi_chip spidev_chip_info = { +static struct bfin_spi3_chip spidev_chip_info = { .enable_dma = true, }; #endif @@ -1296,7 +1296,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { }, #endif }; -#if defined(CONFIG_SPI_BFIN6XX) || defined(CONFIG_SPI_BFIN6XX_MODULE) +#if IS_ENABLED(CONFIG_SPI_BFIN_V3) /* SPI (0) */ static struct resource bfin_spi0_resource[] = { { @@ -1337,13 +1337,13 @@ static struct resource bfin_spi1_resource[] = { }; /* SPI controller data */ -static struct bfin6xx_spi_master bf60x_spi_master_info0 = { +static struct bfin_spi3_master bf60x_spi_master_info0 = { .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS, .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0}, }; static struct platform_device bf60x_spi_master0 = { - .name = "bfin-spi", + .name = "bfin-spi3", .id = 0, /* Bus number */ .num_resources = ARRAY_SIZE(bfin_spi0_resource), .resource = bfin_spi0_resource, @@ -1352,13 +1352,13 @@ static struct platform_device bf60x_spi_master0 = { }, }; -static struct bfin6xx_spi_master bf60x_spi_master_info1 = { +static struct bfin_spi3_master bf60x_spi_master_info1 = { .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS, .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0}, }; static struct platform_device bf60x_spi_master1 = { - .name = "bfin-spi", + .name = "bfin-spi3", .id = 1, /* Bus number */ .num_resources = ARRAY_SIZE(bfin_spi1_resource), .resource = bfin_spi1_resource, @@ -1534,7 +1534,7 @@ static struct platform_device *ezkit_devices[] __initdata = { &bfin_sdh_device, #endif -#if defined(CONFIG_SPI_BFIN6XX) || defined(CONFIG_SPI_BFIN6XX_MODULE) +#if IS_ENABLED(CONFIG_SPI_BFIN_V3) &bf60x_spi_master0, &bf60x_spi_master1, #endif -- GitLab From 14be49ac965ebd3f8561d57e01ddb22f93f9b454 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:53:02 +0530 Subject: [PATCH 2484/2900] [SCSI] mpt3sas: Infinite loops can occur if MPI2_IOCSTATUS_CONFIG_INVALID_PAGE is not returned Infinite loop can occur if IOCStatus is not equal to MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value in the while loops in functions _scsih_search_responding_sas_devices, _scsih_search_responding_raid_devices and _scsih_search_responding_expanders So, Instead of checking for MPI2_IOCSTATUS_CONFIG_INVALID_PAGE value, in this patch code is modified to check for IOCStatus not equals to MPI2_IOCSTATUS_SUCCESS to break the while loop. Signed-off-by: Sreekanth Reddy Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 9ebc9dce3046..632eba75971c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -6406,7 +6406,7 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) break; handle = le16_to_cpu(sas_device_pg0.DevHandle); device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); @@ -6508,7 +6508,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) break; handle = le16_to_cpu(volume_pg1.DevHandle); @@ -6532,7 +6532,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) phys_disk_num))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) break; phys_disk_num = pd_pg0.PhysDiskNum; handle = le16_to_cpu(pd_pg0.DevHandle); @@ -6611,7 +6611,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) break; handle = le16_to_cpu(expander_pg0.DevHandle); @@ -6756,8 +6756,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \ "ioc_status(0x%04x), loginfo(0x%08x)\n", @@ -6801,8 +6799,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) phys_disk_num))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\ "ioc_status(0x%04x), loginfo(0x%08x)\n", @@ -6868,8 +6864,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \ "ioc_status(0x%04x), loginfo(0x%08x)\n", @@ -6928,8 +6922,6 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) handle))) { ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\ " ioc_status(0x%04x), loginfo(0x%08x)\n", -- GitLab From 67c0b1b5580181bb4c7d8e1c43b3f9c5b98fbb0b Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Fri, 7 Jun 2013 16:45:12 +0800 Subject: [PATCH 2485/2900] bf609: add cpu revision 0.1 Signed-off-by: Sonic Zhang --- arch/blackfin/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a117652b5fea..32226e56b0e9 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -282,7 +282,7 @@ config BF_REV_0_0 config BF_REV_0_1 bool "0.1" - depends on (BF51x || BF52x || (BF54x && !BF54xM)) + depends on (BF51x || BF52x || (BF54x && !BF54xM) || BF60x) config BF_REV_0_2 bool "0.2" -- GitLab From b700a3f304cfc8589f3a5b6012bdd3689b778033 Mon Sep 17 00:00:00 2001 From: Steven Miao Date: Thu, 4 Jul 2013 15:56:19 +0800 Subject: [PATCH 2486/2900] bf609: stmmac: fix build after stmmac_mdio_bus_data changed Signed-off-by: Steven Miao --- arch/blackfin/mach-bf609/boards/ezkit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index 6939ac3a805e..a5dca18f4e5d 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c @@ -108,7 +108,6 @@ static struct platform_device bfin_rotary_device = { static unsigned short pins[] = P_RMII0; static struct stmmac_mdio_bus_data phy_private_data = { - .bus_id = 0, .phy_mask = 1, }; -- GitLab From 150382a53d11256e5666c86525c8bf8d23684532 Mon Sep 17 00:00:00 2001 From: Steven Miao Date: Tue, 9 Jul 2013 15:39:53 +0800 Subject: [PATCH 2487/2900] smp: refine bf561 smpboot code release boot lock earlier to let coreb do setup and calibrate set coreb online later after initialization ready add BFIN_IPI_NONE IPI type drop unnecesarry smp_mb() and using atomic type Signed-off-by: Steven Miao --- arch/blackfin/mach-bf561/smp.c | 7 +++---- arch/blackfin/mach-common/smp.c | 18 ++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index ab1c617b9cfc..c77a23bc9de3 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -69,7 +69,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu) SSYNC(); /* We are done with local CPU inits, unblock the boot CPU. */ - set_cpu_online(cpu, true); spin_lock(&boot_lock); spin_unlock(&boot_lock); } @@ -91,7 +90,9 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle SSYNC(); } - timeout = jiffies + 1 * HZ; + timeout = jiffies + HZ; + /* release the lock and let coreb run */ + spin_unlock(&boot_lock); while (time_before(jiffies, timeout)) { if (cpu_online(cpu)) break; @@ -100,8 +101,6 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle } if (cpu_online(cpu)) { - /* release the lock and let coreb run */ - spin_unlock(&boot_lock); return 0; } else panic("CPU%u: processor failed to boot\n", cpu); diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 1bc2ce6f3c94..961d8392e5e3 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -49,6 +49,7 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS]; struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; enum ipi_message_type { + BFIN_IPI_NONE, BFIN_IPI_TIMER, BFIN_IPI_RESCHEDULE, BFIN_IPI_CALL_FUNC, @@ -72,8 +73,8 @@ static DEFINE_SPINLOCK(stop_lock); /* Simple FIFO buffer, overflow leads to panic */ struct ipi_data { - unsigned long count; - unsigned long bits; + atomic_t count; + atomic_t bits; }; static DEFINE_PER_CPU(struct ipi_data, bfin_ipi); @@ -146,7 +147,6 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) platform_clear_ipi(cpu, IRQ_SUPPLE_1); bfin_ipi_data = &__get_cpu_var(bfin_ipi); - smp_mb(); while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { msg = 0; do { @@ -170,9 +170,8 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) ipi_cpu_stop(cpu); break; } + atomic_dec(&bfin_ipi_data->count); } while (msg < BITS_PER_LONG); - - smp_mb(); } return IRQ_HANDLED; } @@ -195,12 +194,10 @@ void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg) unsigned long flags; local_irq_save(flags); - smp_mb(); for_each_cpu(cpu, cpumask) { bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - smp_mb(); - set_bit(msg, &bfin_ipi_data->bits); - bfin_ipi_data->count++; + atomic_set_mask((1 << msg), &bfin_ipi_data->bits); + atomic_inc(&bfin_ipi_data->count); platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1); } @@ -319,7 +316,6 @@ void __cpuinit secondary_start_kernel(void) setup_secondary(cpu); platform_secondary_init(cpu); - /* setup local core timer */ bfin_local_timer_setup(); @@ -335,6 +331,8 @@ void __cpuinit secondary_start_kernel(void) */ calibrate_delay(); + /* We are done with local CPU inits, unblock the boot CPU. */ + set_cpu_online(cpu, true); cpu_startup_entry(CPUHP_ONLINE); } -- GitLab From 17263e754d87fac1be2825b43d984f594a68845e Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:54:07 +0530 Subject: [PATCH 2488/2900] [SCSI] mpt3sas: MPI2.5 Rev F v2.5.1.1 specification Change set in MPI v2.5 Rev F(v2.5.1.1) specification and 2.00.29 header files 1. Added a bit to the IOCExceptions field of the IOCFacts Reply to indicate that the IOC detected a partial memory failure. 2. Added ElapsedSeconds field to RAID Volume Indicator Structure. Added Elapsed Seconds Valid flag to Flags field of this structure. 3. Added ElapsedSeconds field to Integrated RAID Operations Status Event Data. 4. Added two new AbortType values for TargetModeAbort Request, one to abort all I/Os from a single initiator, and the other to abort only Command IUs. 5. Added a new chapter covering DMA Flags and Multicast Modes. 6. In the IOCSettings field of BIOS Page 1, modified the Adapter Support bits description to specify X86 BIOS. 7. Marked bit 0 of the ControlFlags field of SAS IO Unit Page 1 as obsolete. This was the Clear SATA Affiliation flag. 8. Added additional requirements for certain IOCs that support more than eight MSI-x vectors. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpi/mpi2.h | 12 +++++++++--- drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | 15 +++++++++++++-- drivers/scsi/mpt3sas/mpi/mpi2_init.h | 2 +- drivers/scsi/mpt3sas/mpi/mpi2_ioc.h | 10 +++++++--- drivers/scsi/mpt3sas/mpi/mpi2_raid.h | 10 +++++++--- drivers/scsi/mpt3sas/mpi/mpi2_sas.h | 2 +- drivers/scsi/mpt3sas/mpi/mpi2_tool.h | 10 ++++++---- drivers/scsi/mpt3sas/mpi/mpi2_type.h | 2 +- 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h index 03317ffea62c..20da8f907c00 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2.h @@ -8,7 +8,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.26 + * mpi2.h Version: 02.00.29 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -82,6 +82,10 @@ * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT. * Added Hard Reset delay timings. * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT. + * 07-26-12 02.00.27 Bumped MPI2_HEADER_VERSION_UNIT. + * 11-27-12 02.00.28 Bumped MPI2_HEADER_VERSION_UNIT. + * 12-20-12 02.00.29 Bumped MPI2_HEADER_VERSION_UNIT. + * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET. * -------------------------------------------------------------------------- */ @@ -115,7 +119,7 @@ #define MPI2_VERSION_02_05 (0x0205) /*Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x1A) +#define MPI2_HEADER_VERSION_UNIT (0x1D) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) @@ -274,6 +278,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS { #define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF) #define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000) #define MPI2_RPHI_MSIX_INDEX_SHIFT (24) +#define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C) /*MPI v2.5 only*/ + /* *Defines for the HCBSize and address diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index d8b2c3eedb57..889aa7067899 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2011 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_cnfg.h * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.22 + * mpi2_cnfg.h Version: 02.00.24 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -155,6 +155,11 @@ * Added UEFIVersion field to BIOS Page 1 and defined new * BiosOptions bits. * Incorporating additions for MPI v2.5. + * 11-27-12 02.00.23 Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER. + * Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID. + * 12-20-12 02.00.24 Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as + * obsolete for MPI v2.5 and later. + * Added some defines for 12G SAS speeds. * -------------------------------------------------------------------------- */ @@ -714,6 +719,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 { #define MPI2_MANUFACTURING7_PAGEVERSION (0x01) /*defines for the Flags field */ +#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002) #define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) @@ -1310,6 +1316,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 { #define MPI2_BIOSPAGE1_PAGEVERSION (0x05) /*values for BIOS Page 1 BiosOptions field */ +#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) +#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) + #define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) #define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) #define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) @@ -1884,6 +1893,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 { #define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) #define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) #define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) +#define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0) #define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) #define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) #define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) @@ -1897,6 +1907,7 @@ typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 { #define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) #define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) #define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) +#define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0) #define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) #define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) #define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h index a079e5242474..f7928bf66478 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_init.h diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h index 0de425d8fd70..e2bb82143720 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.21 + * mpi2_ioc.h Version: 02.00.22 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -124,6 +124,9 @@ * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. * 11-18-11 02.00.20 Incorporating additions for MPI v2.5. * 03-29-12 02.00.21 Added a product specific range to event values. + * 07-26-12 02.00.22 Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE. + * Added ElapsedSeconds field to + * MPI2_EVENT_DATA_IR_OPERATION_STATUS. * -------------------------------------------------------------------------- */ @@ -283,6 +286,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY { #define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) /*IOCExceptions */ +#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200) #define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) @@ -634,7 +638,7 @@ typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS { U8 RAIDOperation; /*0x04 */ U8 PercentComplete; /*0x05 */ U16 Reserved2; /*0x06 */ - U32 Resereved3; /*0x08 */ + U32 ElapsedSeconds; /*0x08 */ } MPI2_EVENT_DATA_IR_OPERATION_STATUS, *PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, Mpi2EventDataIrOperationStatus_t, diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h index d1d9866cf300..71765236afef 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_raid.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_raid.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_raid.h * Title: MPI Integrated RAID messages and structures * Creation Date: April 26, 2007 * - * mpi2_raid.h Version: 02.00.08 + * mpi2_raid.h Version: 02.00.09 * * Version History * --------------- @@ -28,6 +28,8 @@ * Added product-specific range to RAID Action values. * 11-18-11 02.00.07 Incorporating additions for MPI v2.5. * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN. + * 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR. + * Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define. * -------------------------------------------------------------------------- */ @@ -269,10 +271,12 @@ typedef struct _MPI2_RAID_VOL_INDICATOR { U64 TotalBlocks; /*0x00 */ U64 BlocksRemaining; /*0x08 */ U32 Flags; /*0x10 */ + U32 ElapsedSeconds; /* 0x14 */ } MPI2_RAID_VOL_INDICATOR, *PTR_MPI2_RAID_VOL_INDICATOR, Mpi2RaidVolIndicator_t, *pMpi2RaidVolIndicator_t; /*defines for RAID Volume Indicator Flags field */ +#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000) #define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) #define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) #define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) @@ -312,7 +316,7 @@ typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT { /*RAID Action Reply ActionData union */ typedef union _MPI2_RAID_ACTION_REPLY_DATA { - U32 Word[5]; + U32 Word[6]; MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; U16 VolDevHandle; U8 VolumeState; diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h index b4e7084aba31..cba046f6a4b4 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_sas.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_sas.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_sas.h diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h index 71453d11c1c1..34e9a7ba76b0 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h @@ -1,12 +1,12 @@ /* - * Copyright (c) 2000-2012 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_tool.h * Title: MPI diagnostic tool structures and definitions * Creation Date: March 26, 2007 * - * mpi2_tool.h Version: 02.00.09 + * mpi2_tool.h Version: 02.00.10 * * Version History * --------------- @@ -30,6 +30,8 @@ * 11-18-11 02.00.08 Incorporating additions for MPI v2.5. * 07-10-12 02.00.09 Add MPI v2.5 Toolbox Diagnostic CLI Tool Request * message. + * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that + * it uses MPI Chain SGE as well as MPI Simple SGE. * -------------------------------------------------------------------------- */ @@ -279,7 +281,7 @@ typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { U16 Reserved6; /*0x0E */ U32 DataLength; /*0x10 */ U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x70 */ + MPI2_MPI_SGE_IO_UNION SGL; /*0x70 */ } MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, *PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, Mpi2ToolboxDiagnosticCliRequest_t, @@ -302,7 +304,7 @@ typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { U32 Reserved5; /*0x0C */ U32 DataLength; /*0x10 */ U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI25_SGE_IO_UNION SGL; /*0x70 */ + MPI25_SGE_IO_UNION SGL; /* 0x70 */ } MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, *PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, Mpi25ToolboxDiagnosticCliRequest_t, diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_type.h b/drivers/scsi/mpt3sas/mpi/mpi2_type.h index 516f959573f5..ba1fed50966e 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_type.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2013 LSI Corporation. * * * Name: mpi2_type.h -- GitLab From f5edbe77d93b99f169d752d91bf31df0432ca990 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:54:51 +0530 Subject: [PATCH 2489/2900] [SCSI] mpt3sas: when async scanning is enabled then while scanning, devices are removed but their transport layer entries are not removed When Async scanning mode is enabled and device scanning is in progress, devices should not be removed. But in actuality, devices are removed but their transport layer entries are not removed. This causes error to add the same device to the transport layer after host reset or diagnostic reset. So, in this patch, modified the code in such a way that device is not removed when Async scanning mode is enabled and device scanning is in progress. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 632eba75971c..8cbe8fd21fc4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -675,11 +675,12 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, * devices while scanning is turned on due to an oops in * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start() */ - if (!ioc->is_driver_loading) + if (!ioc->is_driver_loading) { mpt3sas_transport_port_remove(ioc, sas_device->sas_address, sas_device->sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); + _scsih_sas_device_remove(ioc, sas_device); + } } } @@ -7531,10 +7532,12 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) sas_address_parent)) { _scsih_sas_device_remove(ioc, sas_device); } else if (!sas_device->starget) { - if (!ioc->is_driver_loading) - mpt3sas_transport_port_remove(ioc, sas_address, + if (!ioc->is_driver_loading) { + mpt3sas_transport_port_remove(ioc, + sas_address, sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); + _scsih_sas_device_remove(ioc, sas_device); + } } } } @@ -7590,13 +7593,14 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) * oops in scsi_sysfs_add_sdev()->add_device()-> * sysfs_addrm_start() */ - if (!ioc->is_driver_loading) + if (!ioc->is_driver_loading) { mpt3sas_transport_port_remove(ioc, sas_device->sas_address, sas_device->sas_address_parent); - list_del(&sas_device->list); - kfree(sas_device); - continue; + list_del(&sas_device->list); + kfree(sas_device); + continue; + } } spin_lock_irqsave(&ioc->sas_device_lock, flags); -- GitLab From e9ce9c86c28c5d44dc408ffe5069597cbbe4663a Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Sat, 29 Jun 2013 03:55:45 +0530 Subject: [PATCH 2490/2900] [SCSI] mpt3sas: Bump driver version to v02.100.00.00 Bump driver version to v02.100.00.00. Signed-off-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 36106470530b..0ebf5d913c80 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -70,10 +70,10 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "LSI Corporation " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "01.100.01.00" -#define MPT3SAS_MAJOR_VERSION 1 +#define MPT3SAS_DRIVER_VERSION "02.100.00.00" +#define MPT3SAS_MAJOR_VERSION 2 #define MPT3SAS_MINOR_VERSION 100 -#define MPT3SAS_BUILD_VERSION 1 +#define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 /* -- GitLab From 518d9df87105a078984c90c75cf6e7f67e3c928c Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:14 +0900 Subject: [PATCH 2491/2900] [SCSI] scsi_debug: fix invalid address passed to kunmap_atomic() In the function prot_verify_write(), the kmap address 'daddr' is incremented in the loop for each data page. Finally 'daddr' reaches the next page boundary in the end of the loop, and the invalid address is passed to kunmap_atomic(). Fix the issue by not incrementing 'daddr' in the loop and offsetting it by the loop counter on demand. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 0a537a0515ca..d51bddde5b1f 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1899,7 +1899,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, daddr = kmap_atomic(sg_page(dsgl)) + dsgl->offset; /* For each sector-sized chunk in data page */ - for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) { + for (j = 0; j < dsgl->length; j += scsi_debug_sector_size) { /* If we're at the end of the current * protection page advance to the next one @@ -1917,11 +1917,11 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, switch (scsi_debug_guard) { case 1: - csum = ip_compute_csum(daddr, + csum = ip_compute_csum(daddr + j, scsi_debug_sector_size); break; case 0: - csum = cpu_to_be16(crc_t10dif(daddr, + csum = cpu_to_be16(crc_t10dif(daddr + j, scsi_debug_sector_size)); break; default: @@ -1938,7 +1938,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, be16_to_cpu(sdt->guard_tag), be16_to_cpu(csum)); ret = 0x01; - dump_sector(daddr, scsi_debug_sector_size); + dump_sector(daddr + j, scsi_debug_sector_size); goto out; } @@ -1949,7 +1949,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, "%s: REF check failed on sector %lu\n", __func__, (unsigned long)sector); ret = 0x03; - dump_sector(daddr, scsi_debug_sector_size); + dump_sector(daddr + j, scsi_debug_sector_size); goto out; } @@ -1959,7 +1959,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, "%s: REF check failed on sector %lu\n", __func__, (unsigned long)sector); ret = 0x03; - dump_sector(daddr, scsi_debug_sector_size); + dump_sector(daddr + j, scsi_debug_sector_size); goto out; } @@ -1977,7 +1977,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, start_sec++; ei_lba++; - daddr += scsi_debug_sector_size; ppage_offset += sizeof(struct sd_dif_tuple); } -- GitLab From fc3fc352b6e7a6452596f8a13cedeaa6bcfe9689 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:15 +0900 Subject: [PATCH 2492/2900] [SCSI] scsi_debug: fix incorrectly nested kmap_atomic() In the function prot_verify_write(), kmap_atomic()/kunmap_atomic() for data page and kmap_atomic()/kunmap_atomic() for protection information page are not nested each other. It worked perfectly before commit 3e4d3af501cccdc8a8cca41bdbe57d54ad7e7e73 ("mm: stack based kmap_atomic()"). Because the kmap_atomic slot KM_IRQ0 was used for data page and the slot KM_IRQ1 was used for protection page. But KM_types are gone and kmap_atomic() is using stack based implementation. So two different kmap_atomic() usages must be strictly nested now. This change ensures kmap_atomic() usage is strictly nested. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d51bddde5b1f..bcf73e44d2fb 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1891,12 +1891,12 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, BUG_ON(scsi_sg_count(SCpnt) == 0); BUG_ON(scsi_prot_sg_count(SCpnt) == 0); - paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; ppage_offset = 0; /* For each data page */ scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) { daddr = kmap_atomic(sg_page(dsgl)) + dsgl->offset; + paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; /* For each sector-sized chunk in data page */ for (j = 0; j < dsgl->length; j += scsi_debug_sector_size) { @@ -1980,19 +1980,18 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, ppage_offset += sizeof(struct sd_dif_tuple); } + kunmap_atomic(paddr); kunmap_atomic(daddr); } - kunmap_atomic(paddr); - dix_writes++; return 0; out: dif_errors++; - kunmap_atomic(daddr); kunmap_atomic(paddr); + kunmap_atomic(daddr); return ret; } -- GitLab From 7cb69d0397233546d82191e524235fdb9d1d91aa Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:16 +0900 Subject: [PATCH 2493/2900] [SCSI] scsi_debug: fix NULL pointer dereference with parameters dif=0 dix=1 The protection info dif_storep is allocated only when parameter dif is not zero. But it will be accessed when reading or writing to the storage installed with parameter dix is not zero. So kernel crashes if scsi_debug module is loaded with parameters dix=1 and dif=0. This fixes it by making dif_storep available if parameter dix is not zero instead of checking if parameter dif is not zero. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index bcf73e44d2fb..e83e661b0257 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -3372,7 +3372,7 @@ static int __init scsi_debug_init(void) if (scsi_debug_num_parts > 0) sdebug_build_parts(fake_storep, sz); - if (scsi_debug_dif) { + if (scsi_debug_dix) { int dif_size; dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); -- GitLab From e9926b4376544d5a2dc4d310d4d0006c634b1a93 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:17 +0900 Subject: [PATCH 2494/2900] [SCSI] scsi_debug: invalidate protection info for unmapped region When UNMAP command is issued with the data integrity support enabled, the protection info for the unmapped region is remain unchanged. So READ command for the region later on causes data integrity failure. This fixes it by invalidating protection info for the unmapped region by filling with 0xff pattern. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index e83e661b0257..83efec2919b1 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2064,6 +2064,11 @@ static void unmap_region(sector_t lba, unsigned int len) scsi_debug_sector_size * scsi_debug_unmap_granularity); } + if (dif_storep) { + memset(dif_storep + lba, 0xff, + sizeof(*dif_storep) * + scsi_debug_unmap_granularity); + } } lba = map_index_to_lba(index + 1); } -- GitLab From e18d8bea33077d259cc826c6d3fa76d36af61876 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:18 +0900 Subject: [PATCH 2495/2900] [SCSI] scsi_debug: simplify offset calculation for dif_storep dif_storep is declared as pointer to unsigned char type. But it is actually used to store vmalloced array of struct sd_dif_tuple. This changes the type of dif_storep to the pointer to struct sd_dif_tuple. It simplifies offset calculation for dif_storep and enables to remove hardcoded size of struct sd_dif_tuple. Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 83efec2919b1..fc8b3aa083d4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -258,7 +258,7 @@ struct sdebug_queued_cmd { static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; static unsigned char * fake_storep; /* ramdisk storage */ -static unsigned char *dif_storep; /* protection info */ +static struct sd_dif_tuple *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ static unsigned long map_size; @@ -277,11 +277,6 @@ static char sdebug_proc_name[] = "scsi_debug"; static struct bus_type pseudo_lld_bus; -static inline sector_t dif_offset(sector_t sector) -{ - return sector << 3; -} - static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, .bus = &pseudo_lld_bus, @@ -1727,7 +1722,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, start_sec = do_div(tmp_sec, sdebug_store_sectors); - sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec)); + sdt = dif_storep + start_sec; for (i = 0 ; i < sectors ; i++) { u16 csum; @@ -1782,16 +1777,17 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, ei_lba++; } - resid = sectors * 8; /* Bytes of protection data to copy into sgl */ + /* Bytes of protection data to copy into sgl */ + resid = sectors * sizeof(*dif_storep); sector = start_sec; scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) { int len = min(psgl->length, resid); paddr = kmap_atomic(sg_page(psgl)) + psgl->offset; - memcpy(paddr, dif_storep + dif_offset(sector), len); + memcpy(paddr, dif_storep + sector, len); - sector += len >> 3; + sector += len / sizeof(*dif_storep); if (sector >= sdebug_store_sectors) { /* Force wrap */ tmp_sec = sector; @@ -1968,7 +1964,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, * correctness we need to verify each sector * before writing it to "stable" storage */ - memcpy(dif_storep + dif_offset(sector), sdt, 8); + memcpy(dif_storep + sector, sdt, sizeof(*sdt)); sector++; -- GitLab From 9d8812df35be58a5da0c44182c1e4ba2507cc6a7 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 9 Jul 2013 01:31:23 -0700 Subject: [PATCH 2496/2900] ARM: omap2: add select of TI_PRIV_EDMA "ARM: OMAP: build mach-omap code only if needed" moved around the ARCH_OMAP2PLUS stanza, but accidentally dropped the seleciton of TI_PRIV_EDMA in the process. Add it back. Cc: Arnd Bergmann Cc: Tony Lindgren Signed-off-by: Olof Johansson --- arch/arm/mach-omap2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 5c1405157bb6..58152b15ecaa 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -99,6 +99,7 @@ config ARCH_OMAP2PLUS select PROC_DEVICETREE if PROC_FS select SOC_BUS select SPARSE_IRQ + select TI_PRIV_EDMA select USE_OF help Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 -- GitLab From 8c69d7af12265e5be9326110b695e010b47505bd Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 5 Jul 2013 22:59:42 +0100 Subject: [PATCH 2497/2900] ARM: 7780/1: add missing linker section markup to head-common.S Macro __INIT is used to place various code in head-common.S into the init section. This should be matched by a closing __FINIT. Also, add an explicit ".text" to ensure subsequent code is placed into the correct section; __FINIT is simply a closing marker to match __INIT and doesn't guarantee to revert to .text. This historically caused no problem, because macro __CPUINIT was used at the exact location where __FINIT was missing, which then placed following code into the cpuinit section. However, with commit 22f0a2736 "init.h: remove __cpuinit sections from the kernel" applied, __CPUINIT becomes a no-op, thus leaving all this code in the init section, rather than the regular text section. This caused issues such as secondary CPU boot failures or crashes. Signed-off-by: Stephen Warren Acked-by: Paul Gortmaker Signed-off-by: Russell King --- arch/arm/kernel/head-common.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 5b391a689b47..76ab5ca50610 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -133,6 +133,9 @@ ENTRY(lookup_processor_type) ldmfd sp!, {r4 - r6, r9, pc} ENDPROC(lookup_processor_type) + __FINIT + .text + /* * Read processor ID register (CP#15, CR0), and look up in the linker-built * supported processor list. Note that we can't use the absolute addresses -- GitLab From ee4de5d99aeac44f4507b7538b2b3faedc5205b9 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Sat, 6 Jul 2013 00:25:51 +0100 Subject: [PATCH 2498/2900] ARM: 7781/1: mmu: Add debug_ll_io_init() mappings to early mappings Failure to add the mapping created in debug_ll_io_init() can lead to the BUG_ON() triggering in lib/ioremap.c:27 if the static virtual address decided for the debug_ll mapping overlaps with another mapping that is created later. This happens because the generic ioremap code has no idea there is a mapping there and it tries to place a mapping in the same location and blows up when it sees that there is a pte already present. kernel BUG at lib/ioremap.c:27! Internal error: Oops - BUG: 0 [#1] PREEMPT SMP ARM Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-rc2-00042-g2af0c67-dirty #316 task: ef088000 ti: ef082000 task.ti: ef082000 PC is at ioremap_page_range+0x16c/0x198 LR is at ioremap_page_range+0xf0/0x198 pc : [] lr : [] psr: 20000113 sp : ef083e78 ip : af140000 fp : ef083ebc r10: ef7fc100 r9 : ef7fc104 r8 : 000af174 r7 : 00000647 r6 : beffffff r5 : f004c000 r4 : f0040000 r3 : af173417 r2 : 16440653 r1 : af173e07 r0 : ef7fc8fc Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5787d Table: 8020406a DAC: 00000015 Process swapper/0 (pid: 1, stack limit = 0xef082238) Stack: (0xef083e78 to 0xef084000) 3e60: 00040000 ef083eec 3e80: bf134000 f004bfff c0207c00 f004c000 c02fc120 f000c000 c15e7800 00040000 3ea0: ef083eec 00000647 c098ba9c c0953544 ef083edc ef083ec0 c021b82c c04cb714 3ec0: c09cdc50 00000040 ef0f1e00 ef1003c0 ef083f14 ef083ee0 c09535bc c021b7bc 3ee0: c0953544 c04d0c6c c094e2cc c1600be4 c07440c4 c09a6888 00000002 c0a15f00 3f00: ef082000 00000000 ef083f54 ef083f18 c0208728 c0953550 00000002 c1600bfc 3f20: c08e3fac c0839918 ef083f54 c1600b80 c09a6888 c0a15f00 0000008b c094e2cc 3f40: c098ba9c c098bab8 ef083f94 ef083f58 c094ea0c c020865c 00000002 00000002 3f60: c094e2cc 00000000 c025b674 00000000 c06ff860 00000000 00000000 00000000 3f80: 00000000 00000000 ef083fac ef083f98 c06ff878 c094e910 00000000 00000000 3fa0: 00000000 ef083fb0 c020efe8 c06ff86c 00000000 00000000 00000000 00000000 3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 c0595108 [] (ioremap_page_range+0x16c/0x198) from [] (__alloc_remap_buffer.isra.18+0x7c/0xc4) [] (__alloc_remap_buffer.isra.18+0x7c/0xc4) from [] (atomic_pool_init+0x78/0x128) [] (atomic_pool_init+0x78/0x128) from [] (do_one_initcall+0xd8/0x198) [] (do_one_initcall+0xd8/0x198) from [] (kernel_init_freeable+0x108/0x1d0) [] (kernel_init_freeable+0x108/0x1d0) from [] (kernel_init+0x18/0xf4) [] (kernel_init+0x18/0xf4) from [] (ret_from_fork+0x14/0x20) Code: e50b0040 ebf54b2f e51b0040 eaffffee (e7f001f2) Fix it by telling generic layers about the static mapping via iotable_init(). This also has the nice side effect of letting you see the mapping in procfs' vmallocinfo file. Cc: Rob Herring Cc: Stephen Warren Signed-off-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4d409e6a552d..f6ad0182df40 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -949,7 +949,7 @@ void __init debug_ll_io_init(void) map.virtual &= PAGE_MASK; map.length = PAGE_SIZE; map.type = MT_DEVICE; - create_mapping(&map); + iotable_init(&map, 1); } #endif -- GitLab From 319e0b4f02f73983c03a2ca38595fc6367929edf Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 Jul 2013 09:52:55 +0100 Subject: [PATCH 2499/2900] ARM: mm: fix boot on SA1110 Assabet Commit 83db0384 (mm/ARM: use common help functions to free reserved pages) broke booting on the Assabet by trying to convert a PFN to a virtual address using the __va() macro. This macro takes the physical address, not a PFN. Fix this. Cc: # 3.10 Signed-off-by: Russell King --- arch/arm/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9a5cdc01fcdf..0ecc43fd6229 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -600,7 +600,7 @@ void __init mem_init(void) #ifdef CONFIG_SA1111 /* now that our DMA memory is actually so designated, we can free it */ - free_reserved_area(__va(PHYS_PFN_OFFSET), swapper_pg_dir, 0, NULL); + free_reserved_area(__va(PHYS_OFFSET), swapper_pg_dir, 0, NULL); #endif free_highpages(); -- GitLab From d903bca9bc542bd6d60019f9f761be15ad79c956 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Mon, 8 Jul 2013 12:21:47 +0100 Subject: [PATCH 2500/2900] metag: checksum.h: fix carry in csum_tcpudp_nofold In csum_tcpudp_nofold, add 1 if the carry bit is set after adding the destination IP address (32 bits) to the checksum (16 bits). The lack of carry handling for this particular addition meant that a destination address of *.*.255.255 (e.g. certain broadcasts) sometimes resulted in an incorrect checksum. This bug has been present in the Meta port since the code was written in the 2.4 days. Reported-by: Marcin Nowakowski Signed-off-by: James Hogan --- arch/metag/include/asm/checksum.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/metag/include/asm/checksum.h b/arch/metag/include/asm/checksum.h index 999bf761a732..08dd1cc65799 100644 --- a/arch/metag/include/asm/checksum.h +++ b/arch/metag/include/asm/checksum.h @@ -64,7 +64,8 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __wsum sum) { unsigned long len_proto = (proto + len) << 8; - asm ("ADD %0, %0, %1\n" + asm ("ADDS %0, %0, %1\n" + "ADDCS %0, %0, #1\n" "ADDS %0, %0, %2\n" "ADDCS %0, %0, #1\n" "ADDS %0, %0, %3\n" -- GitLab From beb40ea42bd65511bc275a7d58d3753835906be5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 29 Jun 2013 17:59:19 +0900 Subject: [PATCH 2501/2900] [SCSI] scsi_debug: reduce duplication between prot_verify_read and prot_verify_write In order to reduce code duplication between prot_verify_read() and prot_verify_write(), this moves common code into the new functions. [jejb: fix unitialised variable warning] Signed-off-by: Akinobu Mita Acked-by: Douglas Gilbert Acked-by: "Martin K. Petersen" Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 137 +++++++++++++++----------------------- 1 file changed, 52 insertions(+), 85 deletions(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index fc8b3aa083d4..3f096a6681ac 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1710,6 +1710,50 @@ static int do_device_access(struct scsi_cmnd *scmd, return ret; } +static u16 dif_compute_csum(const void *buf, int len) +{ + u16 csum; + + switch (scsi_debug_guard) { + case 1: + csum = ip_compute_csum(buf, len); + break; + case 0: + csum = cpu_to_be16(crc_t10dif(buf, len)); + break; + } + return csum; +} + +static int dif_verify(struct sd_dif_tuple *sdt, const void *data, + sector_t sector, u32 ei_lba) +{ + u16 csum = dif_compute_csum(data, scsi_debug_sector_size); + + if (sdt->guard_tag != csum) { + pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", + __func__, + (unsigned long)sector, + be16_to_cpu(sdt->guard_tag), + be16_to_cpu(csum)); + return 0x01; + } + if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && + be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { + pr_err("%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + return 0x03; + } + if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && + be32_to_cpu(sdt->ref_tag) != ei_lba) { + pr_err("%s: REF check failed on sector %lu\n", + __func__, (unsigned long)sector); + dif_errors++; + return 0x03; + } + return 0; +} + static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, unsigned int sectors, u32 ei_lba) { @@ -1725,53 +1769,19 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, sdt = dif_storep + start_sec; for (i = 0 ; i < sectors ; i++) { - u16 csum; + int ret; if (sdt[i].app_tag == 0xffff) continue; sector = start_sec + i; - switch (scsi_debug_guard) { - case 1: - csum = ip_compute_csum(fake_storep + - sector * scsi_debug_sector_size, - scsi_debug_sector_size); - break; - case 0: - csum = crc_t10dif(fake_storep + - sector * scsi_debug_sector_size, - scsi_debug_sector_size); - csum = cpu_to_be16(csum); - break; - default: - BUG(); - } - - if (sdt[i].guard_tag != csum) { - printk(KERN_ERR "%s: GUARD check failed on sector %lu" \ - " rcvd 0x%04x, data 0x%04x\n", __func__, - (unsigned long)sector, - be16_to_cpu(sdt[i].guard_tag), - be16_to_cpu(csum)); - dif_errors++; - return 0x01; - } - - if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && - be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { - printk(KERN_ERR "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - dif_errors++; - return 0x03; - } - - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && - be32_to_cpu(sdt[i].ref_tag) != ei_lba) { - printk(KERN_ERR "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); + ret = dif_verify(&sdt[i], + fake_storep + sector * scsi_debug_sector_size, + sector, ei_lba); + if (ret) { dif_errors++; - return 0x03; + return ret; } ei_lba++; @@ -1880,7 +1890,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, sector_t tmp_sec = start_sec; sector_t sector; int ppage_offset; - unsigned short csum; sector = do_div(tmp_sec, sdebug_store_sectors); @@ -1911,50 +1920,8 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, sdt = paddr + ppage_offset; - switch (scsi_debug_guard) { - case 1: - csum = ip_compute_csum(daddr + j, - scsi_debug_sector_size); - break; - case 0: - csum = cpu_to_be16(crc_t10dif(daddr + j, - scsi_debug_sector_size)); - break; - default: - BUG(); - ret = 0; - goto out; - } - - if (sdt->guard_tag != csum) { - printk(KERN_ERR - "%s: GUARD check failed on sector %lu " \ - "rcvd 0x%04x, calculated 0x%04x\n", - __func__, (unsigned long)sector, - be16_to_cpu(sdt->guard_tag), - be16_to_cpu(csum)); - ret = 0x01; - dump_sector(daddr + j, scsi_debug_sector_size); - goto out; - } - - if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && - be32_to_cpu(sdt->ref_tag) - != (start_sec & 0xffffffff)) { - printk(KERN_ERR - "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - ret = 0x03; - dump_sector(daddr + j, scsi_debug_sector_size); - goto out; - } - - if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && - be32_to_cpu(sdt->ref_tag) != ei_lba) { - printk(KERN_ERR - "%s: REF check failed on sector %lu\n", - __func__, (unsigned long)sector); - ret = 0x03; + ret = dif_verify(sdt, daddr + j, start_sec, ei_lba); + if (ret) { dump_sector(daddr + j, scsi_debug_sector_size); goto out; } -- GitLab From fec3c1b4575431e2020c5c6502d18b281925ca45 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Jun 2013 00:21:04 +0300 Subject: [PATCH 2502/2900] [SCSI] megaraid_sas: fix a bug for 64 bit arches On 64 bit then -1UL and -1U are not equal, so these conditions don't work as intended and it breaks error handling. Signed-off-by: Dan Carpenter Acked-by: Sumit Saxena Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_fp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index 8056eacba758..4f401f753f8e 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -585,7 +585,7 @@ u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe, case 1: /* start with logical arm */ arm = get_arm_from_strip(instance, ld, stripe, map); - if (arm != -1UL) + if (arm != -1U) arm *= 2; break; } @@ -637,7 +637,7 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld, if (raid->level == 6) { logArm = get_arm_from_strip(instance, ld, stripRow, map); - if (logArm == -1UL) + if (logArm == -1U) return FALSE; rowMod = mega_mod64(row, SPAN_ROW_SIZE(map, ld, span)); armQ = SPAN_ROW_SIZE(map, ld, span) - 1 - rowMod; -- GitLab From e2eb7244bc9e4fd130fc8a961224968e22ba48ee Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 2 Jul 2013 15:05:26 +0200 Subject: [PATCH 2503/2900] [SCSI] Fix race between starved list and device removal scsi_run_queue() examines all SCSI devices that are present on the starved list. Since scsi_run_queue() unlocks the SCSI host lock a SCSI device can get removed after it has been removed from the starved list and before its queue is run. Protect against that race condition by holding a reference on the queue while running it. Reported-by: Chanho Min Reviewed-by: Bart Van Assche Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 86d522004a20..df8bd5ab3c0b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -434,6 +434,8 @@ static void scsi_run_queue(struct request_queue *q) list_splice_init(&shost->starved_list, &starved_list); while (!list_empty(&starved_list)) { + struct request_queue *slq; + /* * As long as shost is accepting commands and we have * starved queues, call blk_run_queue. scsi_request_fn @@ -456,11 +458,25 @@ static void scsi_run_queue(struct request_queue *q) continue; } - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); - __blk_run_queue(sdev->request_queue); - spin_unlock(sdev->request_queue->queue_lock); - spin_lock(shost->host_lock); + /* + * Once we drop the host lock, a racing scsi_remove_device() + * call may remove the sdev from the starved list and destroy + * it and the queue. Mitigate by taking a reference to the + * queue and never touching the sdev again after we drop the + * host lock. Note: if __scsi_remove_device() invokes + * blk_cleanup_queue() before the queue is run from this + * function then blk_run_queue() will return immediately since + * blk_cleanup_queue() marks the queue with QUEUE_FLAG_DYING. + */ + slq = sdev->request_queue; + if (!blk_get_queue(slq)) + continue; + spin_unlock_irqrestore(shost->host_lock, flags); + + blk_run_queue(slq); + blk_put_queue(slq); + + spin_lock_irqsave(shost->host_lock, flags); } /* put any unprocessed entries back */ list_splice(&starved_list, &shost->starved_list); -- GitLab From 0516c08d10835a8f9169051504cbc9929b3a7f3e Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 2 Jul 2013 15:06:33 +0200 Subject: [PATCH 2504/2900] [SCSI] enable destruction of blocked devices which fail LUN scanning If something goes wrong during LUN scanning, e.g. a transport layer failure occurs, then __scsi_remove_device() can get invoked by the LUN scanning code for a SCSI device in state SDEV_CREATED_BLOCK and before the SCSI device has been added to sysfs (is_visible == 0). Make sure that even in this case the transition into state SDEV_DEL occurs. This avoids that __scsi_remove_device() can get invoked a second time by scsi_forget_host() if this last function is invoked from another thread than the thread that performs LUN scanning. Signed-off-by: Bart Van Assche Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index df8bd5ab3c0b..124392f3091e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2193,6 +2193,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) case SDEV_OFFLINE: case SDEV_TRANSPORT_OFFLINE: case SDEV_CANCEL: + case SDEV_CREATED_BLOCK: break; default: goto illegal; -- GitLab From bf51d5e2cda5d36d98e4b46ac7fca9461e512c41 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 3 Jul 2013 17:12:13 -0300 Subject: [PATCH 2505/2900] drm/i915: switch disable_power_well default value to 1 Now that the audio driver is using our power well API, everything should be working correctly, so let's give it a try. Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 062cbda1bf4a..f4af1ca0fb62 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -123,10 +123,10 @@ module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 060 MODULE_PARM_DESC(preliminary_hw_support, "Enable preliminary hardware support. (default: false)"); -int i915_disable_power_well __read_mostly = 0; +int i915_disable_power_well __read_mostly = 1; module_param_named(disable_power_well, i915_disable_power_well, int, 0600); MODULE_PARM_DESC(disable_power_well, - "Disable the power well when possible (default: false)"); + "Disable the power well when possible (default: true)"); int i915_enable_ips __read_mostly = 1; module_param_named(enable_ips, i915_enable_ips, int, 0600); -- GitLab From 067556084a0e412013af6b0250a3143ae5afde6d Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Fri, 5 Jul 2013 18:53:29 +0800 Subject: [PATCH 2506/2900] drm/i915: Correct obj->mm_list link to dev_priv->dev_priv->mm.inactive_list obj->mm_list link to dev_priv->mm.inactive_list/active_list obj->global_list link to dev_priv->mm.unbound_list/bound_list This regression has been introduced in commit 93927ca52a55c23e0a6a305e7e9082e8411ac9fa Author: Daniel Vetter Date: Thu Jan 10 18:03:00 2013 +0100 drm/i915: Revert shrinker changes from "Track unbound pages" Cc: stable@vger.kernel.org Signed-off-by: Xiong Zhang [danvet: Add regression notice.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 769f75262feb..7f368d79f7d2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4623,7 +4623,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) if (obj->pages_pin_count == 0) cnt += obj->base.size >> PAGE_SHIFT; - list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list) + list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) if (obj->pin_count == 0 && obj->pages_pin_count == 0) cnt += obj->base.size >> PAGE_SHIFT; -- GitLab From aaf8a5167291b65e9116cb8736d862965b57c13a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 5 Jul 2013 23:39:50 +0200 Subject: [PATCH 2507/2900] drm/i915: fix up ring cleanup for the i830/i845 CS tlb w/a It's not a good idea to also run the pipe_control cleanup. This regression has been introduced whith the original cs tlb w/a in commit b45305fce5bb1abec263fcff9d81ebecd6306ede Author: Daniel Vetter Date: Mon Dec 17 16:21:27 2012 +0100 drm/i915: Implement workaround for broken CS tlb on i830/845 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64610 Cc: Chris Wilson Cc: stable@vger.kernel.org Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 18ca76e3e5ef..664118d8c1d6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -534,9 +534,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring) struct pipe_control *pc = ring->private; struct drm_i915_gem_object *obj; - if (!ring->private) - return; - obj = pc->obj; kunmap(sg_page(obj->pages->sgl)); @@ -544,7 +541,6 @@ cleanup_pipe_control(struct intel_ring_buffer *ring) drm_gem_object_unreference(&obj->base); kfree(pc); - ring->private = NULL; } static int init_render_ring(struct intel_ring_buffer *ring) @@ -617,7 +613,10 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring) if (HAS_BROKEN_CS_TLB(dev)) drm_gem_object_unreference(to_gem_object(ring->private)); - cleanup_pipe_control(ring); + if (INTEL_INFO(dev)->gen >= 5) + cleanup_pipe_control(ring); + + ring->private = NULL; } static void -- GitLab From d4eead50eb206b875f54f66cc0f6ec7d54122c28 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 9 Jul 2013 17:05:26 +0300 Subject: [PATCH 2508/2900] drm/i915: fix lane bandwidth capping for DP 1.2 sinks DP 1.2 compatible displays may report a 5.4Gbps maximum bandwidth which the driver will treat as an invalid value and use 1.62Gbps instead. Fix this by capping to 2.7Gbps for sinks reporting a 5.4Gbps max bw. Also add a warning for reserved values. v2: - allow only bw values explicitly listed in the DP standard (Daniel, Chris) Signed-off-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b73971234013..26e162bb3a51 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -75,7 +75,12 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) case DP_LINK_BW_1_62: case DP_LINK_BW_2_7: break; + case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */ + max_link_bw = DP_LINK_BW_2_7; + break; default: + WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n", + max_link_bw); max_link_bw = DP_LINK_BW_1_62; break; } -- GitLab From e0335f67a281cb8eb11868e614ee9390fbbe9b1d Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 18 May 2013 04:01:36 +0000 Subject: [PATCH 2509/2900] libfc: Reject PLOGI from nodes with incompatible role Reject a PLOGI from a node with an incompatible role, that is, initiator-to-initiator or target-to-target. Signed-off-by: Mark Rustad Reviewed-by: Yi Zou Tested-by: Jack Morgan Signed-off-by: Robert Love --- drivers/scsi/libfc/fc_rport.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6bbb9447b75d..c710d908fda6 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -926,6 +926,20 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } +static bool +fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata) +{ + if (rdata->ids.roles == FC_PORT_ROLE_UNKNOWN) + return true; + if ((rdata->ids.roles & FC_PORT_ROLE_FCP_TARGET) && + (lport->service_params & FCP_SPPF_INIT_FCN)) + return true; + if ((rdata->ids.roles & FC_PORT_ROLE_FCP_INITIATOR) && + (lport->service_params & FCP_SPPF_TARG_FCN)) + return true; + return false; +} + /** * fc_rport_enter_plogi() - Send Port Login (PLOGI) request * @rdata: The remote port to send a PLOGI to @@ -938,6 +952,12 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; + if (!fc_rport_compatible_roles(lport, rdata)) { + FC_RPORT_DBG(rdata, "PLOGI suppressed for incompatible role\n"); + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + return; + } + FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n", fc_rport_state(rdata)); @@ -1646,6 +1666,13 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, rjt_data.explan = ELS_EXPL_NONE; goto reject; } + if (!fc_rport_compatible_roles(lport, rdata)) { + FC_RPORT_DBG(rdata, "Received PLOGI for incompatible role\n"); + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_LOGIC; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; + } /* * Get session payload size from incoming PLOGI. -- GitLab From f07d46bbc9ba9a08b338dec7bb858977d4d822fb Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Sat, 18 May 2013 05:12:28 +0000 Subject: [PATCH 2510/2900] fcoe: Fix smatch warning in fcoe_fdmi_info function This patch fixes a smatch warning as below: smatch warnings: drivers/scsi/fcoe/fcoe.c:782 fcoe_fdmi_info() warn: 'fdmi' puts 896 bytes on stack Reported-by: Fengguang Wu Signed-off-by: Neerav Parikh Tested-by: Jack Morgan Signed-off-by: Robert Love --- drivers/scsi/fcoe/fcoe.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 32ae6c67ea3a..3336e5754930 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -774,7 +774,6 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev) struct fcoe_port *port; struct net_device *realdev; int rc; - struct netdev_fcoe_hbainfo fdmi; port = lport_priv(lport); fcoe = port->priv; @@ -788,9 +787,13 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev) return; if (realdev->netdev_ops->ndo_fcoe_get_hbainfo) { - memset(&fdmi, 0, sizeof(fdmi)); + struct netdev_fcoe_hbainfo *fdmi; + fdmi = kzalloc(sizeof(*fdmi), GFP_KERNEL); + if (!fdmi) + return; + rc = realdev->netdev_ops->ndo_fcoe_get_hbainfo(realdev, - &fdmi); + fdmi); if (rc) { printk(KERN_INFO "fcoe: Failed to retrieve FDMI " "information from netdev.\n"); @@ -800,38 +803,39 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev) snprintf(fc_host_serial_number(lport->host), FC_SERIAL_NUMBER_SIZE, "%s", - fdmi.serial_number); + fdmi->serial_number); snprintf(fc_host_manufacturer(lport->host), FC_SERIAL_NUMBER_SIZE, "%s", - fdmi.manufacturer); + fdmi->manufacturer); snprintf(fc_host_model(lport->host), FC_SYMBOLIC_NAME_SIZE, "%s", - fdmi.model); + fdmi->model); snprintf(fc_host_model_description(lport->host), FC_SYMBOLIC_NAME_SIZE, "%s", - fdmi.model_description); + fdmi->model_description); snprintf(fc_host_hardware_version(lport->host), FC_VERSION_STRING_SIZE, "%s", - fdmi.hardware_version); + fdmi->hardware_version); snprintf(fc_host_driver_version(lport->host), FC_VERSION_STRING_SIZE, "%s", - fdmi.driver_version); + fdmi->driver_version); snprintf(fc_host_optionrom_version(lport->host), FC_VERSION_STRING_SIZE, "%s", - fdmi.optionrom_version); + fdmi->optionrom_version); snprintf(fc_host_firmware_version(lport->host), FC_VERSION_STRING_SIZE, "%s", - fdmi.firmware_version); + fdmi->firmware_version); /* Enable FDMI lport states */ lport->fdmi_enabled = 1; + kfree(fdmi); } else { lport->fdmi_enabled = 0; printk(KERN_INFO "fcoe: No FDMI support.\n"); -- GitLab From 418a8cfe69c3b6bd4598e9870b9f412e2c247214 Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Sat, 18 May 2013 06:28:17 +0000 Subject: [PATCH 2511/2900] fcoe: fix the link error status block sparse warnings Both fcoe_fc_els_lesb and fc_els_lesb are in __be32 already, and both are exactly the same size in bytes, with somewhat different member names to reflect the fact the former is for Ethernet media the latter is for Fiber Channel, so, remove conversion and use __be32 directly. This fixes the warning from sparse check. Signed-off-by: Yi Zou Reported-by: Fengguang Wu Tested-by: Jack Morgan Signed-off-by: Robert Love --- drivers/scsi/fcoe/fcoe_transport.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index f3a5a53e8631..bedd42211727 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -180,24 +180,10 @@ void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev) { struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); struct net_device *netdev = fcoe_get_netdev(fip->lp); - struct fcoe_fc_els_lesb *fcoe_lesb; - struct fc_els_lesb fc_lesb; - - __fcoe_get_lesb(fip->lp, &fc_lesb, netdev); - fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb); - - ctlr_dev->lesb.lesb_link_fail = - ntohl(fcoe_lesb->lesb_link_fail); - ctlr_dev->lesb.lesb_vlink_fail = - ntohl(fcoe_lesb->lesb_vlink_fail); - ctlr_dev->lesb.lesb_miss_fka = - ntohl(fcoe_lesb->lesb_miss_fka); - ctlr_dev->lesb.lesb_symb_err = - ntohl(fcoe_lesb->lesb_symb_err); - ctlr_dev->lesb.lesb_err_block = - ntohl(fcoe_lesb->lesb_err_block); - ctlr_dev->lesb.lesb_fcs_error = - ntohl(fcoe_lesb->lesb_fcs_error); + struct fc_els_lesb *fc_lesb; + + fc_lesb = (struct fc_els_lesb *)(&ctlr_dev->lesb); + __fcoe_get_lesb(fip->lp, fc_lesb, netdev); } EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb); -- GitLab From 4a80f083dd70a200763e77d3eeee48bdf753c7df Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 11 Jun 2013 07:28:03 +0000 Subject: [PATCH 2512/2900] libfc: Remove extra space in fc_exch_timer_cancel definition Simply remove an extra space that violates coding style. Signed-off-by: Robert Love Tested-by: Jack Morgan Acked-by: Neil Horman --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8b928c67e4b9..e98ea6af84e0 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -337,7 +337,7 @@ static void fc_exch_release(struct fc_exch *ep) * fc_exch_timer_cancel() - cancel exch timer * @ep: The exchange whose timer to be canceled */ -static inline void fc_exch_timer_cancel(struct fc_exch *ep) +static inline void fc_exch_timer_cancel(struct fc_exch *ep) { if (cancel_delayed_work(&ep->timeout_work)) { FC_EXCH_DBG(ep, "Exchange timer canceled\n"); -- GitLab From 3a2926054acf876313afaaddac00a8ad255f6d68 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 11 Jun 2013 07:28:09 +0000 Subject: [PATCH 2513/2900] libfc: Differentiate echange timer cancellation debug statements There are two debug statements with the same output string regarding echange timer cancellation. This patch simply changes the output of one string so that they can be differentiated. Signed-off-by: Robert Love Tested-by: Jack Morgan Acked-by: Neil Horman --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index e98ea6af84e0..587992952b3c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1567,7 +1567,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) fc_exch_rctl_name(fh->fh_r_ctl)); if (cancel_delayed_work_sync(&ep->timeout_work)) { - FC_EXCH_DBG(ep, "Exchange timer canceled\n"); + FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n"); fc_exch_release(ep); /* release from pending timer hold */ } -- GitLab From a2ceb1fbaa875172345f611a3d37c3662f7e5082 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 11 Jun 2013 07:28:19 +0000 Subject: [PATCH 2514/2900] libfcoe: Fix meaningless log statement ctlr_dev was initialized to NULL, and never re-assigned. This caused the log statement to always report failure. This patch removes the unused variable and fixes the log statement to always report 'success', as that is what should be logged if the code reaches this point. Signed-off-by: Robert Love Tested-by: Jack Morgan Acked-by: Neil Horman --- drivers/scsi/fcoe/fcoe_transport.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c index bedd42211727..f1ae5edb2de1 100644 --- a/drivers/scsi/fcoe/fcoe_transport.c +++ b/drivers/scsi/fcoe/fcoe_transport.c @@ -707,7 +707,6 @@ ssize_t fcoe_ctlr_create_store(struct bus_type *bus, { struct net_device *netdev = NULL; struct fcoe_transport *ft = NULL; - struct fcoe_ctlr_device *ctlr_dev = NULL; int rc = 0; int err; @@ -754,9 +753,8 @@ ssize_t fcoe_ctlr_create_store(struct bus_type *bus, goto out_putdev; } - LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n", - ft->name, (ctlr_dev) ? "succeeded" : "failed", - netdev->name); + LIBFCOE_TRANSPORT_DBG("transport %s succeeded to create fcoe on %s.\n", + ft->name, netdev->name); out_putdev: dev_put(netdev); -- GitLab From d17efa001aacaa774581972230b1a9db1e618ded Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 18 May 2013 04:10:07 +0000 Subject: [PATCH 2515/2900] fcoe: Stop fc_rport_priv structure leak When repeatedly doing rmmod and modprobe on the ixgbe driver while FCoE is active in a VN2VN configuration, memory leaks would be discovered by kmemleak with the following backtrace: unreferenced object 0xffff88003d076000 (size 1024): comm "kworker/0:3", pid 2998, jiffies 4295436448 (age 1015.332s) hex dump (first 32 bytes): 48 8a fe 6f 00 88 ff ff 00 00 00 00 00 00 00 00 H..o............ 01 00 00 00 02 00 00 00 7b ac 87 21 1b 00 00 10 ........{..!.... backtrace: [] kmemleak_alloc+0x5b/0xc0 [] __kmalloc+0xd8/0x1b0 [] fc_rport_create+0x48/0x1f0 [libfc] [] fcoe_ctlr_vn_add.isra.10+0x56/0x1a0 [libfcoe] [] fcoe_ctlr_vn_recv+0x8b0/0xab0 [libfcoe] [] fcoe_ctlr_recv_work+0x4c6/0xf60 [libfcoe] [] process_one_work+0x1e4/0x4d0 [] worker_thread+0x10f/0x380 [] kthread+0xea/0xf0 [] ret_from_fork+0x7c/0xb0 [] 0xffffffffffffffff This patch stops the leak of the fc_rport_priv structure. Signed-off-by: Mark Rustad Tested-by: Jack Morgan Signed-off-by: Robert Love --- drivers/scsi/fcoe/fcoe_ctlr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 795843dde8ec..203415e02518 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -2090,7 +2090,11 @@ static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = { */ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) { + struct fc_rport_priv *rdata; + mutex_lock(&lport->disc.disc_mutex); + list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) + lport->tt.rport_logoff(rdata); lport->disc.disc_callback = NULL; mutex_unlock(&lport->disc.disc_mutex); } -- GitLab From 7a5ed75a782a1f2de7fc773981ecd88bfa7595b1 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 25 Jun 2013 17:49:40 +0000 Subject: [PATCH 2516/2900] fcoe: Reduce number of sparse warnings Declare local variables and functions 'static'. This patch does not change any functionality. Signed-off-by: Bart Van Assche Signed-off-by: Robert Love --- drivers/scsi/fcoe/fcoe_sysfs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index 8c05ae017f5b..c9382d6eee78 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c @@ -507,7 +507,7 @@ static const struct attribute_group *fcoe_fcf_attr_groups[] = { NULL, }; -struct bus_type fcoe_bus_type; +static struct bus_type fcoe_bus_type; static int fcoe_bus_match(struct device *dev, struct device_driver *drv) @@ -541,25 +541,25 @@ static void fcoe_fcf_device_release(struct device *dev) kfree(fcf); } -struct device_type fcoe_ctlr_device_type = { +static struct device_type fcoe_ctlr_device_type = { .name = "fcoe_ctlr", .groups = fcoe_ctlr_attr_groups, .release = fcoe_ctlr_device_release, }; -struct device_type fcoe_fcf_device_type = { +static struct device_type fcoe_fcf_device_type = { .name = "fcoe_fcf", .groups = fcoe_fcf_attr_groups, .release = fcoe_fcf_device_release, }; -struct bus_attribute fcoe_bus_attr_group[] = { +static struct bus_attribute fcoe_bus_attr_group[] = { __ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store), __ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store), __ATTR_NULL }; -struct bus_type fcoe_bus_type = { +static struct bus_type fcoe_bus_type = { .name = "fcoe", .match = &fcoe_bus_match, .bus_attrs = fcoe_bus_attr_group, @@ -569,7 +569,7 @@ struct bus_type fcoe_bus_type = { * fcoe_ctlr_device_flush_work() - Flush a FIP ctlr's workqueue * @ctlr: Pointer to the FIP ctlr whose workqueue is to be flushed */ -void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) +static void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) { if (!fcoe_ctlr_work_q(ctlr)) { printk(KERN_ERR @@ -590,8 +590,8 @@ void fcoe_ctlr_device_flush_work(struct fcoe_ctlr_device *ctlr) * Return value: * 1 on success / 0 already queued / < 0 for error */ -int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, - struct work_struct *work) +static int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, + struct work_struct *work) { if (unlikely(!fcoe_ctlr_work_q(ctlr))) { printk(KERN_ERR @@ -609,7 +609,7 @@ int fcoe_ctlr_device_queue_work(struct fcoe_ctlr_device *ctlr, * fcoe_ctlr_device_flush_devloss() - Flush a FIP ctlr's devloss workqueue * @ctlr: Pointer to FIP ctlr whose workqueue is to be flushed */ -void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) +static void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) { if (!fcoe_ctlr_devloss_work_q(ctlr)) { printk(KERN_ERR @@ -631,9 +631,9 @@ void fcoe_ctlr_device_flush_devloss(struct fcoe_ctlr_device *ctlr) * Return value: * 1 on success / 0 already queued / < 0 for error */ -int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr, - struct delayed_work *work, - unsigned long delay) +static int fcoe_ctlr_device_queue_devloss_work(struct fcoe_ctlr_device *ctlr, + struct delayed_work *work, + unsigned long delay) { if (unlikely(!fcoe_ctlr_devloss_work_q(ctlr))) { printk(KERN_ERR -- GitLab From a69c7c077228b0bef38ccb1d385c099e132fe54b Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 28 Mar 2012 12:21:11 -0500 Subject: [PATCH 2517/2900] xfs: use XFS_BMAP_BMDR_SPACE vs. XFS_BROOT_SIZE_ADJ XFS_BROOT_SIZE_ADJ is an undocumented macro which accounts for the difference in size between the on-disk and in-core btree root. It's much clearer to just use the newly-added XFS_BMAP_BMDR_SPACE macro which gives us the on-disk size directly. In one case, we must test that the if_broot exists before applying the macro, however. Signed-off-by: Eric Sandeen Reviewed-by: Dave Chinner Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dinode.h | 3 --- fs/xfs/xfs_inode.c | 14 +++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index f7a0e95d197a..07d735a80a0f 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -132,9 +132,6 @@ typedef enum xfs_dinode_fmt { #define XFS_LITINO(mp, version) \ ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version))) -#define XFS_BROOT_SIZE_ADJ(ip) \ - (XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t)) - /* * Inode data & attribute fork sizes, per inode. */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 9ecfe1e559fc..b78481f99d9d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2156,8 +2156,8 @@ xfs_iroot_realloc( np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, (int)new_size); ifp->if_broot_bytes = (int)new_size; - ASSERT(ifp->if_broot_bytes <= - XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + XFS_IFORK_SIZE(ip, whichfork)); memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t)); return; } @@ -2210,8 +2210,9 @@ xfs_iroot_realloc( kmem_free(ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = (int)new_size; - ASSERT(ifp->if_broot_bytes <= - XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip)); + if (ifp->if_broot) + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + XFS_IFORK_SIZE(ip, whichfork)); return; } @@ -2522,9 +2523,8 @@ xfs_iflush_fork( if ((iip->ili_fields & brootflag[whichfork]) && (ifp->if_broot_bytes > 0)) { ASSERT(ifp->if_broot != NULL); - ASSERT(ifp->if_broot_bytes <= - (XFS_IFORK_SIZE(ip, whichfork) + - XFS_BROOT_SIZE_ADJ(ip))); + ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <= + XFS_IFORK_SIZE(ip, whichfork)); xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, (xfs_bmdr_block_t *)cp, XFS_DFORK_SIZE(dip, mp, whichfork)); -- GitLab From 76b1e9b9813e412bde7446525f6c299803713545 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Tue, 9 Jul 2013 13:09:21 +0300 Subject: [PATCH 2518/2900] net/fs: change busy poll time accounting Suggested by Linus: Changed time accounting for busy-poll: - Make it microsecond based. - Use unsigned longs. - Revert back to use time_after instead of time_in_range. Reorder poll/select busy loop conditions: - Clear busy_flag after one time we can't busy-poll. - Only init busy_end if we actually are going to busy-poll. Added one more missing need_resched() test. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- fs/select.c | 31 +++++++++++++++--------- include/net/ll_poll.h | 55 ++++++++++++++----------------------------- 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/fs/select.c b/fs/select.c index 25cac5faf6d6..50a804b6839f 100644 --- a/fs/select.c +++ b/fs/select.c @@ -403,8 +403,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) int retval, i, timed_out = 0; unsigned long slack = 0; unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; - u64 busy_start = busy_loop_start_time(busy_flag); - u64 busy_end = busy_loop_end_time(); + unsigned long busy_end = 0; rcu_read_lock(); retval = max_select_fd(n, fds); @@ -506,9 +505,15 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) } /* only if found POLL_BUSY_LOOP sockets && not out of time */ - if (!need_resched() && can_busy_loop && - busy_loop_range(busy_start, busy_end)) - continue; + if (can_busy_loop && !need_resched()) { + if (!busy_end) { + busy_end = busy_loop_end_time(); + continue; + } + if (!busy_loop_timeout(busy_end)) + continue; + } + busy_flag = 0; /* * If this is the first loop and we have a timeout @@ -780,9 +785,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list, int timed_out = 0, count = 0; unsigned long slack = 0; unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0; - u64 busy_start = busy_loop_start_time(busy_flag); - u64 busy_end = busy_loop_end_time(); - + unsigned long busy_end = 0; /* Optimise the no-wait case */ if (end_time && !end_time->tv_sec && !end_time->tv_nsec) { @@ -834,9 +837,15 @@ static int do_poll(unsigned int nfds, struct poll_list *list, break; /* only if found POLL_BUSY_LOOP sockets && not out of time */ - if (!need_resched() && can_busy_loop && - busy_loop_range(busy_start, busy_end)) - continue; + if (can_busy_loop && !need_resched()) { + if (!busy_end) { + busy_end = busy_loop_end_time(); + continue; + } + if (!busy_loop_timeout(busy_end)) + continue; + } + busy_flag = 0; /* * If this is the first loop and we have a timeout diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h index f14dd88dafc8..76f034087743 100644 --- a/include/net/ll_poll.h +++ b/include/net/ll_poll.h @@ -47,7 +47,7 @@ static inline bool net_busy_loop_on(void) * we only care that the average is bounded */ #ifdef CONFIG_DEBUG_PREEMPT -static inline u64 busy_loop_sched_clock(void) +static inline u64 busy_loop_us_clock(void) { u64 rc; @@ -55,37 +55,24 @@ static inline u64 busy_loop_sched_clock(void) rc = sched_clock(); preempt_enable_no_resched_notrace(); - return rc; + return rc >> 10; } #else /* CONFIG_DEBUG_PREEMPT */ -static inline u64 busy_loop_sched_clock(void) +static inline u64 busy_loop_us_clock(void) { - return sched_clock(); + return sched_clock() >> 10; } #endif /* CONFIG_DEBUG_PREEMPT */ -/* we don't mind a ~2.5% imprecision so <<10 instead of *1000 - * sk->sk_ll_usec is a u_int so this can't overflow - */ -static inline u64 sk_busy_loop_end_time(struct sock *sk) +static inline unsigned long sk_busy_loop_end_time(struct sock *sk) { - return (u64)ACCESS_ONCE(sk->sk_ll_usec) << 10; + return busy_loop_us_clock() + ACCESS_ONCE(sk->sk_ll_usec); } -/* in poll/select we use the global sysctl_net_ll_poll value - * only call sched_clock() if enabled - */ -static inline u64 busy_loop_end_time(void) -{ - return (u64)ACCESS_ONCE(sysctl_net_ll_poll) << 10; -} - -/* if flag is not set we don't need to know the time - * so we want to avoid a potentially expensive sched_clock() - */ -static inline u64 busy_loop_start_time(unsigned int flag) +/* in poll/select we use the global sysctl_net_ll_poll value */ +static inline unsigned long busy_loop_end_time(void) { - return flag ? busy_loop_sched_clock() : 0; + return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_ll_poll); } static inline bool sk_can_busy_loop(struct sock *sk) @@ -94,12 +81,12 @@ static inline bool sk_can_busy_loop(struct sock *sk) !need_resched() && !signal_pending(current); } -/* careful! time_in_range64 will evaluate now twice */ -static inline bool busy_loop_range(u64 start_time, u64 run_time) + +static inline bool busy_loop_timeout(unsigned long end_time) { - u64 now = busy_loop_sched_clock(); + unsigned long now = busy_loop_us_clock(); - return time_in_range64(now, start_time, start_time + run_time); + return time_after(now, end_time); } /* when used in sock_poll() nonblock is known at compile time to be true @@ -107,8 +94,7 @@ static inline bool busy_loop_range(u64 start_time, u64 run_time) */ static inline bool sk_busy_loop(struct sock *sk, int nonblock) { - u64 start_time = busy_loop_start_time(!nonblock); - u64 end_time = sk_busy_loop_end_time(sk); + unsigned long end_time = !nonblock ? sk_busy_loop_end_time(sk) : 0; const struct net_device_ops *ops; struct napi_struct *napi; int rc = false; @@ -139,7 +125,7 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock) LINUX_MIB_LOWLATENCYRXPACKETS, rc); } while (!nonblock && skb_queue_empty(&sk->sk_receive_queue) && - busy_loop_range(start_time, end_time)); + !need_resched() && !busy_loop_timeout(end_time)); rc = !skb_queue_empty(&sk->sk_receive_queue); out: @@ -165,12 +151,7 @@ static inline unsigned long net_busy_loop_on(void) return 0; } -static inline u64 busy_loop_start_time(unsigned int flag) -{ - return 0; -} - -static inline u64 busy_loop_end_time(void) +static inline unsigned long busy_loop_end_time(void) { return 0; } @@ -193,9 +174,9 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) { } -static inline bool busy_loop_range(u64 start_time, u64 run_time) +static inline bool busy_loop_timeout(unsigned long end_time) { - return false; + return true; } #endif /* CONFIG_NET_LL_RX_POLL */ -- GitLab From b78ba72cda78314c11ac8f47617240bc8d0e89da Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Jul 2013 10:22:31 +0200 Subject: [PATCH 2519/2900] Documentation: Fix references to defunct linux-net@vger.kernel.org linux-net@vger.kernel.org was replaced by netdev@oss.sgi.com was replaced by netdev@vger.kernel.org. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- Documentation/networking/arcnet.txt | 7 ++++--- Documentation/networking/vortex.txt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/networking/arcnet.txt b/Documentation/networking/arcnet.txt index 9ff579502151..aff97f47c05c 100644 --- a/Documentation/networking/arcnet.txt +++ b/Documentation/networking/arcnet.txt @@ -70,9 +70,10 @@ list, mail to linux-arcnet@tichy.ch.uj.edu.pl. There are archives of the mailing list at: http://epistolary.org/mailman/listinfo.cgi/arcnet -The people on linux-net@vger.kernel.org have also been known to be very -helpful, especially when we're talking about ALPHA Linux kernels that may or -may not work right in the first place. +The people on linux-net@vger.kernel.org (now defunct, replaced by +netdev@vger.kernel.org) have also been known to be very helpful, especially +when we're talking about ALPHA Linux kernels that may or may not work right +in the first place. Other Drivers and Info diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt index b4038ffb3bc5..9a8041dcbb53 100644 --- a/Documentation/networking/vortex.txt +++ b/Documentation/networking/vortex.txt @@ -359,7 +359,7 @@ steps you should take: - OK, it's a driver problem. You need to generate a report. Typically this is an email to the - maintainer and/or linux-net@vger.kernel.org. The maintainer's + maintainer and/or netdev@vger.kernel.org. The maintainer's email address will be in the driver source or in the MAINTAINERS file. - The contents of your report will vary a lot depending upon the -- GitLab From 01276ed2424eb78c95461545410923d5da154d31 Mon Sep 17 00:00:00 2001 From: Jongsung Kim Date: Tue, 9 Jul 2013 17:36:00 +0900 Subject: [PATCH 2520/2900] net/cadence/macb: fix bug/typo in extracting gem_irq_read_clear bit Signed-off-by: Jongsung Kim Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index f7e21f278e05..e866608d7d91 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1292,7 +1292,7 @@ static void macb_configure_dma(struct macb *bp) static void macb_configure_caps(struct macb *bp) { if (macb_is_gem(bp)) { - if (GEM_BF(IRQCOR, gem_readl(bp, DCFG1)) == 0) + if (GEM_BFEXT(IRQCOR, gem_readl(bp, DCFG1)) == 0) bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE; } } -- GitLab From cc229884d3f77ec3b1240e467e0236c3e0647c0c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 9 Jul 2013 13:19:18 +0300 Subject: [PATCH 2521/2900] virtio: support unlocked queue poll This adds a way to check ring empty state after enable_cb outside any locks. Will be used by virtio_net. Note: there's room for more optimization: caller is likely to have a memory barrier already, which means we might be able to get rid of a barrier here. Deferring this optimization until we do some benchmarking. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/virtio/virtio_ring.c | 56 ++++++++++++++++++++++++++++-------- include/linux/virtio.h | 4 +++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 5217baf5528c..37d58f84dc50 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -607,19 +607,21 @@ void virtqueue_disable_cb(struct virtqueue *_vq) EXPORT_SYMBOL_GPL(virtqueue_disable_cb); /** - * virtqueue_enable_cb - restart callbacks after disable_cb. + * virtqueue_enable_cb_prepare - restart callbacks after disable_cb * @vq: the struct virtqueue we're talking about. * - * This re-enables callbacks; it returns "false" if there are pending - * buffers in the queue, to detect a possible race between the driver - * checking for more work, and enabling callbacks. + * This re-enables callbacks; it returns current queue state + * in an opaque unsigned value. This value should be later tested by + * virtqueue_poll, to detect a possible race between the driver checking for + * more work, and enabling callbacks. * * Caller must ensure we don't call this with other virtqueue * operations at the same time (except where noted). */ -bool virtqueue_enable_cb(struct virtqueue *_vq) +unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); + u16 last_used_idx; START_USE(vq); @@ -629,15 +631,45 @@ bool virtqueue_enable_cb(struct virtqueue *_vq) * either clear the flags bit or point the event index at the next * entry. Always do both to keep code simple. */ vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - vring_used_event(&vq->vring) = vq->last_used_idx; + vring_used_event(&vq->vring) = last_used_idx = vq->last_used_idx; + END_USE(vq); + return last_used_idx; +} +EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare); + +/** + * virtqueue_poll - query pending used buffers + * @vq: the struct virtqueue we're talking about. + * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare). + * + * Returns "true" if there are pending used buffers in the queue. + * + * This does not need to be serialized. + */ +bool virtqueue_poll(struct virtqueue *_vq, unsigned last_used_idx) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + virtio_mb(vq->weak_barriers); - if (unlikely(more_used(vq))) { - END_USE(vq); - return false; - } + return (u16)last_used_idx != vq->vring.used->idx; +} +EXPORT_SYMBOL_GPL(virtqueue_poll); - END_USE(vq); - return true; +/** + * virtqueue_enable_cb - restart callbacks after disable_cb. + * @vq: the struct virtqueue we're talking about. + * + * This re-enables callbacks; it returns "false" if there are pending + * buffers in the queue, to detect a possible race between the driver + * checking for more work, and enabling callbacks. + * + * Caller must ensure we don't call this with other virtqueue + * operations at the same time (except where noted). + */ +bool virtqueue_enable_cb(struct virtqueue *_vq) +{ + unsigned last_used_idx = virtqueue_enable_cb_prepare(_vq); + return !virtqueue_poll(_vq, last_used_idx); } EXPORT_SYMBOL_GPL(virtqueue_enable_cb); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 9ff8645b7e0b..72398eea6e86 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -70,6 +70,10 @@ void virtqueue_disable_cb(struct virtqueue *vq); bool virtqueue_enable_cb(struct virtqueue *vq); +unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq); + +bool virtqueue_poll(struct virtqueue *vq, unsigned); + bool virtqueue_enable_cb_delayed(struct virtqueue *vq); void *virtqueue_detach_unused_buf(struct virtqueue *vq); -- GitLab From cbdadbbf0c790f79350a8f36029208944c5487d0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 9 Jul 2013 08:13:04 +0300 Subject: [PATCH 2522/2900] virtio_net: fix race in RX VQ processing virtio net called virtqueue_enable_cq on RX path after napi_complete, so with NAPI_STATE_SCHED clear - outside the implicit napi lock. This violates the requirement to synchronize virtqueue_enable_cq wrt virtqueue_add_buf. In particular, used event can move backwards, causing us to lose interrupts. In a debug build, this can trigger panic within START_USE. Jason Wang reports that he can trigger the races artificially, by adding udelay() in virtqueue_enable_cb() after virtio_mb(). However, we must call napi_complete to clear NAPI_STATE_SCHED before polling the virtqueue for used buffers, otherwise napi_schedule_prep in a callback will fail, causing us to lose RX events. To fix, call virtqueue_enable_cb_prepare with NAPI_STATE_SCHED set (under napi lock), later call virtqueue_poll with NAPI_STATE_SCHED clear (outside the lock). Reported-by: Jason Wang Tested-by: Jason Wang Acked-by: Jason Wang Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c9e00387d999..42d670a468f8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -602,7 +602,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget) container_of(napi, struct receive_queue, napi); struct virtnet_info *vi = rq->vq->vdev->priv; void *buf; - unsigned int len, received = 0; + unsigned int r, len, received = 0; again: while (received < budget && @@ -619,8 +619,9 @@ static int virtnet_poll(struct napi_struct *napi, int budget) /* Out of packets? */ if (received < budget) { + r = virtqueue_enable_cb_prepare(rq->vq); napi_complete(napi); - if (unlikely(!virtqueue_enable_cb(rq->vq)) && + if (unlikely(virtqueue_poll(rq->vq, r)) && napi_schedule_prep(napi)) { virtqueue_disable_cb(rq->vq); __napi_schedule(napi); -- GitLab From 8c2f414ad1b3aa3af05791cd7312eb8ff9d80e0d Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 9 Jul 2013 16:17:04 +0200 Subject: [PATCH 2523/2900] net: sctp: confirm route during forward progress This fix has been proposed originally by Vlad Yasevich. He says: When SCTP makes forward progress (receives a SACK that acks new chunks, renegs, or answeres 0-window probes) or when HB-ACK arrives, mark the route as confirmed so we don't unnecessarily send NUD probes. Having a simple SCTP client/server that exchange data chunks every 1sec, without this patch ARP requests are sent periodically every 40-60sec. With this fix applied, an ARP request is only done once right at the "session" beginning. Also, when clearing the related ARP cache entry manually during the session, a new request is correctly done. I have only "backported" this to net-next and tested that it works, so full credit goes to Vlad. Signed-off-by: Vlad Yasevich Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/sctp/outqueue.c | 9 +++++++++ net/sctp/sm_sideeffect.c | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index cb80a8e060b7..ef9e2bbc0f2f 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1334,6 +1334,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, __u8 restart_timer = 0; int bytes_acked = 0; int migrate_bytes = 0; + bool forward_progress = false; sack_ctsn = ntohl(sack->cum_tsn_ack); @@ -1400,6 +1401,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, bytes_acked += sctp_data_size(tchunk); if (!tchunk->transport) migrate_bytes += sctp_data_size(tchunk); + forward_progress = true; } if (TSN_lte(tsn, sack_ctsn)) { @@ -1413,6 +1415,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, * current RTO. */ restart_timer = 1; + forward_progress = true; if (!tchunk->tsn_gap_acked) { /* @@ -1503,6 +1506,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, */ transport->error_count = 0; transport->asoc->overall_error_count = 0; + forward_progress = true; /* * While in SHUTDOWN PENDING, we may have started @@ -1576,6 +1580,11 @@ static void sctp_check_transmitted(struct sctp_outq *q, jiffies + transport->rto)) sctp_transport_hold(transport); } + + if (forward_progress) { + if (transport->dst) + dst_confirm(transport->dst); + } } list_splice(&tlist, transmitted_queue); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index cf6f84518222..9da68852ee94 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -730,6 +730,12 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, SCTP_HEARTBEAT_SUCCESS); + /* HB-ACK was received for a the proper HB. Consider this + * forward progress. + */ + if (t->dst) + dst_confirm(t->dst); + /* The receiver of the HEARTBEAT ACK should also perform an * RTT measurement for that destination transport address * using the time value carried in the HEARTBEAT ACK chunk. -- GitLab From 785bf6f7904352242d187ff6087d523a4ce1b3ac Mon Sep 17 00:00:00 2001 From: Jonas Gorski Date: Mon, 8 Jul 2013 00:44:55 +0200 Subject: [PATCH 2524/2900] net: mv643xx_eth: do not use port number as platform device id The port number is only local to the ethernet block, not global, so there can be two ethernet blocks both using the same port, like kirkwood with both using port 0. Fix this by using the array index offset for the allocated platform devices as the id. Signed-off-by: Jonas Gorski Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 6495bea56ec8..c35db735958f 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2483,6 +2483,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, struct resource res; const char *mac_addr; int ret; + int dev_num = 0; memset(&ppd, 0, sizeof(ppd)); ppd.shared = pdev; @@ -2503,6 +2504,14 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, return -EINVAL; } + while (dev_num < 3 && port_platdev[dev_num]) + dev_num++; + + if (dev_num == 3) { + dev_err(&pdev->dev, "too many ports registered\n"); + return -EINVAL; + } + mac_addr = of_get_mac_address(pnp); if (mac_addr) memcpy(ppd.mac_addr, mac_addr, 6); @@ -2521,7 +2530,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, of_property_read_u32(pnp, "duplex", &ppd.duplex); } - ppdev = platform_device_alloc(MV643XX_ETH_NAME, ppd.port_number); + ppdev = platform_device_alloc(MV643XX_ETH_NAME, dev_num); if (!ppdev) return -ENOMEM; ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); @@ -2538,7 +2547,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev, if (ret) goto port_err; - port_platdev[ppd.port_number] = ppdev; + port_platdev[dev_num] = ppdev; return 0; -- GitLab From dd7633ecd553a5e304d349aa6f8eb8a0417098c5 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 7 Jul 2013 14:26:53 +0300 Subject: [PATCH 2525/2900] vhost-net: fix use-after-free in vhost_net_flush vhost_net_ubuf_put_and_wait has a confusing name: it will actually also free it's argument. Thus since commit 1280c27f8e29acf4af2da914e80ec27c3dbd5c01 "vhost-net: flush outstanding DMAs on memory change" vhost_net_flush tries to use the argument after passing it to vhost_net_ubuf_put_and_wait, this results in use after free. To fix, don't free the argument in vhost_net_ubuf_put_and_wait, add an new API for callers that want to free ubufs. Acked-by: Asias He Acked-by: Jason Wang Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/vhost/net.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f80d3dd41d8c..8ca5ac71b845 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -150,6 +150,11 @@ static void vhost_net_ubuf_put_and_wait(struct vhost_net_ubuf_ref *ubufs) { kref_put(&ubufs->kref, vhost_net_zerocopy_done_signal); wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); +} + +static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) +{ + vhost_net_ubuf_put_and_wait(ubufs); kfree(ubufs); } @@ -948,7 +953,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) mutex_unlock(&vq->mutex); if (oldubufs) { - vhost_net_ubuf_put_and_wait(oldubufs); + vhost_net_ubuf_put_wait_and_free(oldubufs); mutex_lock(&vq->mutex); vhost_zerocopy_signal_used(n, vq); mutex_unlock(&vq->mutex); @@ -966,7 +971,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) rcu_assign_pointer(vq->private_data, oldsock); vhost_net_enable_vq(n, vq); if (ubufs) - vhost_net_ubuf_put_and_wait(ubufs); + vhost_net_ubuf_put_wait_and_free(ubufs); err_ubufs: fput(sock->file); err_vq: -- GitLab From e057590b05bc120732967a04d63c15f2f82cdd2b Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 8 Jul 2013 11:22:51 +0400 Subject: [PATCH 2526/2900] drivers/net: enic: release rtnl_lock on error-path enic_change_mtu_work() must call rtnl_unlock() on all exiting paths. Signed-off-by: Konstantin Khlebnikov Cc: Christian Benvenuti Cc: Roopa Prabhu Cc: Neel Patel Cc: Nishank Trivedi Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 635f55992d7e..992ec2ee64d9 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1761,6 +1761,7 @@ static void enic_change_mtu_work(struct work_struct *work) enic_synchronize_irqs(enic); err = vnic_rq_disable(&enic->rq[0]); if (err) { + rtnl_unlock(); netdev_err(netdev, "Unable to disable RQ.\n"); return; } @@ -1773,6 +1774,7 @@ static void enic_change_mtu_work(struct work_struct *work) vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); /* Need at least one buffer on ring to get going */ if (vnic_rq_desc_used(&enic->rq[0]) == 0) { + rtnl_unlock(); netdev_err(netdev, "Unable to alloc receive buffers.\n"); return; } -- GitLab From 56e0ef527b184b3de2d7f88c6190812b2b2ac6bf Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 8 Jul 2013 11:23:04 +0400 Subject: [PATCH 2527/2900] drivers/net: caif: fix wrong rtnl_is_locked() usage rtnl_is_locked() doesn't check who holds this lock, it just tells that it's locked right now. if caif::ldisc_close really can be called under rtrnl_lock then it should release net device in other context because there is no way to grab rtnl_lock without deadlock. This patch adds work which releases these devices. Also this patch fixes calling dev_close/unregister_netdevice without rtnl_lock from caif_ser_exit(). Signed-off-by: Konstantin Khlebnikov Cc: Dmitry Tarnyagin Signed-off-by: David S. Miller --- drivers/net/caif/caif_serial.c | 61 ++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 77be3cb0b5fe..34dea95d58db 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -35,8 +35,9 @@ MODULE_ALIAS_LDISC(N_CAIF); #define OFF 0 #define CAIF_MAX_MTU 4096 -/*This list is protected by the rtnl lock. */ +static DEFINE_SPINLOCK(ser_lock); static LIST_HEAD(ser_list); +static LIST_HEAD(ser_release_list); static bool ser_loop; module_param(ser_loop, bool, S_IRUGO); @@ -308,6 +309,28 @@ static void ldisc_tx_wakeup(struct tty_struct *tty) } +static void ser_release(struct work_struct *work) +{ + struct list_head list; + struct ser_device *ser, *tmp; + + spin_lock(&ser_lock); + list_replace_init(&ser_release_list, &list); + spin_unlock(&ser_lock); + + if (!list_empty(&list)) { + rtnl_lock(); + list_for_each_entry_safe(ser, tmp, &list, node) { + dev_close(ser->dev); + unregister_netdevice(ser->dev); + debugfs_deinit(ser); + } + rtnl_unlock(); + } +} + +static DECLARE_WORK(ser_release_work, ser_release); + static int ldisc_open(struct tty_struct *tty) { struct ser_device *ser; @@ -321,6 +344,9 @@ static int ldisc_open(struct tty_struct *tty) if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_TTY_CONFIG)) return -EPERM; + /* release devices to avoid name collision */ + ser_release(NULL); + sprintf(name, "cf%s", tty->name); dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); if (!dev) @@ -341,7 +367,9 @@ static int ldisc_open(struct tty_struct *tty) return -ENODEV; } + spin_lock(&ser_lock); list_add(&ser->node, &ser_list); + spin_unlock(&ser_lock); rtnl_unlock(); netif_stop_queue(dev); update_tty_status(ser); @@ -351,19 +379,13 @@ static int ldisc_open(struct tty_struct *tty) static void ldisc_close(struct tty_struct *tty) { struct ser_device *ser = tty->disc_data; - /* Remove may be called inside or outside of rtnl_lock */ - int islocked = rtnl_is_locked(); - if (!islocked) - rtnl_lock(); - /* device is freed automagically by net-sysfs */ - dev_close(ser->dev); - unregister_netdevice(ser->dev); - list_del(&ser->node); - debugfs_deinit(ser); tty_kref_put(ser->tty); - if (!islocked) - rtnl_unlock(); + + spin_lock(&ser_lock); + list_move(&ser->node, &ser_release_list); + spin_unlock(&ser_lock); + schedule_work(&ser_release_work); } /* The line discipline structure. */ @@ -438,16 +460,11 @@ static int __init caif_ser_init(void) static void __exit caif_ser_exit(void) { - struct ser_device *ser = NULL; - struct list_head *node; - struct list_head *_tmp; - - list_for_each_safe(node, _tmp, &ser_list) { - ser = list_entry(node, struct ser_device, node); - dev_close(ser->dev); - unregister_netdevice(ser->dev); - list_del(node); - } + spin_lock(&ser_lock); + list_splice(&ser_list, &ser_release_list); + spin_unlock(&ser_lock); + ser_release(NULL); + cancel_work_sync(&ser_release_work); tty_unregister_ldisc(N_CAIF); debugfs_remove_recursive(debugfsdir); } -- GitLab From dac76f1be5beaea4af9afe85fb475c73de0b8731 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 18 Jun 2013 23:21:25 +0200 Subject: [PATCH 2528/2900] parisc: fix LMMIO mismatch between PAT length and MASK register The LMMIO length reported by PAT and the length given by the LBA MASK register are not consistent. This leads e.g. to a not-working ATI FireGL card with the radeon DRM driver since the memory can't be mapped. Fix this by correctly adjusting the resource sizes. Signed-off-by: Helge Deller Cc: # 3.10 --- drivers/parisc/lba_pci.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 1f05913ae677..19f6f70c67d3 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -613,6 +613,54 @@ truncate_pat_collision(struct resource *root, struct resource *new) return 0; /* truncation successful */ } +/* + * extend_lmmio_len: extend lmmio range to maximum length + * + * This is needed at least on C8000 systems to get the ATI FireGL card + * working. On other systems we will currently not extend the lmmio space. + */ +static unsigned long +extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len) +{ + struct resource *tmp; + + pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n", + end - start, lba_len); + + lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */ + + pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end); + + if (boot_cpu_data.cpu_type < mako) { + pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n"); + return end; + } + + end += lba_len; + if (end < start) /* fix overflow */ + end = -1ULL; + + pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end); + + /* first overlap */ + for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { + pr_debug("LBA: testing %pR\n", tmp); + if (tmp->start == start) + continue; /* ignore ourself */ + if (tmp->end < start) + continue; + if (tmp->start > end) + continue; + if (end >= tmp->start) + end = tmp->start - 1; + } + + pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end); + + /* return new end */ + return end; +} + #else #define truncate_pat_collision(r,n) (0) #endif @@ -994,6 +1042,14 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) case PAT_LMMIO: /* used to fix up pre-initialized MEM BARs */ if (!lba_dev->hba.lmmio_space.flags) { + unsigned long lba_len; + + lba_len = ~READ_REG32(lba_dev->hba.base_addr + + LBA_LMMIO_MASK); + if ((p->end - p->start) != lba_len) + p->end = extend_lmmio_len(p->start, + p->end, lba_len); + sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", (int)lba_dev->hba.bus_num.start); -- GitLab From 30a9f0b251285ba29f09a7134eee07a4c3aca639 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 21 Jun 2013 23:32:44 +0200 Subject: [PATCH 2529/2900] parisc: more capabilities info in /proc/cpuinfo Signed-off-by: Helge Deller Cc: # 3.10 --- arch/parisc/kernel/processor.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index c8fb61ed32f4..8a96c8ab9fe6 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -371,10 +371,23 @@ show_cpuinfo (struct seq_file *m, void *v) seq_printf(m, "capabilities\t:"); if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32) - seq_printf(m, " os32"); + seq_puts(m, " os32"); if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64) - seq_printf(m, " os64"); - seq_printf(m, "\n"); + seq_puts(m, " os64"); + if (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC) + seq_puts(m, " iopdir_fdc"); + switch (boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) { + case PDC_MODEL_NVA_SUPPORTED: + seq_puts(m, " nva_supported"); + break; + case PDC_MODEL_NVA_SLOW: + seq_puts(m, " nva_slow"); + break; + case PDC_MODEL_NVA_UNSUPPORTED: + seq_puts(m, " needs_equivalent_aliasing"); + break; + } + seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities); seq_printf(m, "model\t\t: %s\n" "model name\t: %s\n", -- GitLab From a83f58bcb24003b9de2364de7c829a263423ead7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 29 Jun 2013 13:24:16 +0200 Subject: [PATCH 2530/2900] parisc: document the shadow registers Signed-off-by: Helge Deller Cc: # 3.10 --- Documentation/parisc/registers | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/parisc/registers b/Documentation/parisc/registers index dd3caddd1ad9..10c7d1730f5d 100644 --- a/Documentation/parisc/registers +++ b/Documentation/parisc/registers @@ -77,6 +77,14 @@ PSW default E value 0 Shadow Registers used by interruption handler code TOC enable bit 1 +========================================================================= + +The PA-RISC architecture defines 7 registers as "shadow registers". +Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce +the state save and restore time by eliminating the need for general register +(GR) saves and restores in interruption handlers. +Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25. + ========================================================================= Register usage notes, originally from John Marvin, with some additional notes from Randolph Chung. -- GitLab From 594174d810a29982929cbb454dafee4a1498e4fb Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 29 Jun 2013 13:31:24 +0200 Subject: [PATCH 2531/2900] parisc: switch to gzip-compressed vmlinuz kernel The latest PA-RISC Boot Loader (palo) allows loading of gzip compressed vmlinuz kernels. So let's now switch to build a vmlinuz file when we build a palo boot image. PALO version 1.9 (or higher) is required for this which is available at git://git.kernel.org/pub/scm/linux/kernel/git/deller/palo.git Signed-off-by: Helge Deller Cc: # 3.10 --- arch/parisc/Makefile | 15 +++++++++++---- arch/parisc/defpalo.conf | 8 ++++---- arch/parisc/install.sh | 6 +++--- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 96ec3982be8d..e02f665f804a 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -17,6 +17,8 @@ # Mike Shaver, Helge Deller and Martin K. Petersen # +KBUILD_IMAGE := vmlinuz + KBUILD_DEFCONFIG := default_defconfig NM = sh $(srctree)/arch/parisc/nm @@ -92,7 +94,7 @@ PALOCONF := $(shell if [ -f $(src)/palo.conf ]; then echo $(src)/palo.conf; \ else echo $(obj)/palo.conf; \ fi) -palo: vmlinux +palo: vmlinuz @if test ! -x "$(PALO)"; then \ echo 'ERROR: Please install palo first (apt-get install palo)';\ echo 'or build it from source and install it somewhere in your $$PATH';\ @@ -107,10 +109,14 @@ palo: vmlinux fi $(PALO) -f $(PALOCONF) -# Shorthands for known targets not supported by parisc, use vmlinux as default -Image zImage bzImage: vmlinux +# Shorthands for known targets not supported by parisc, use vmlinux/vmlinuz as default +Image: vmlinux +zImage bzImage: vmlinuz + +vmlinuz: vmlinux + @gzip -cf -9 $< > $@ -install: vmlinux +install: vmlinuz sh $(src)/arch/parisc/install.sh \ $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" @@ -119,6 +125,7 @@ MRPROPER_FILES += palo.conf define archhelp @echo '* vmlinux - Uncompressed kernel image (./vmlinux)' + @echo ' vmlinuz - Compressed kernel image (./vmlinuz)' @echo ' palo - Bootable image (./lifimage)' @echo ' install - Install kernel using' @echo ' (your) ~/bin/$(INSTALLKERNEL) or' diff --git a/arch/parisc/defpalo.conf b/arch/parisc/defpalo.conf index 4e1ae25b08d1..208ff3b41487 100644 --- a/arch/parisc/defpalo.conf +++ b/arch/parisc/defpalo.conf @@ -4,7 +4,7 @@ # Most people using 'make palo' want a bootable file, usable for # network or tape booting for example. --init-tape=lifimage ---recoverykernel=vmlinux +--recoverykernel=vmlinuz ########## Pick your ROOT here! ########## # You need at least one 'root='! @@ -12,10 +12,10 @@ # If you want a root ramdisk, use the next 2 lines # (Edit the ramdisk image name!!!!) --ramdisk=ram-disk-image-file ---commandline=0/vmlinux HOME=/ root=/dev/ram initrd=0/ramdisk +--commandline=0/vmlinuz HOME=/ root=/dev/ram initrd=0/ramdisk panic_timeout=60 panic=-1 # If you want NFS root, use the following command line (Edit the HOSTNAME!!!) -#--commandline=0/vmlinux HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp +#--commandline=0/vmlinuz HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp # If you have root on a disk partition, use this (Edit the partition name!!!) -#--commandline=0/vmlinux HOME=/ root=/dev/sda1 +#--commandline=0/vmlinuz HOME=/ root=/dev/sda1 diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh index e593fc8d58bc..4da682b466d0 100644 --- a/arch/parisc/install.sh +++ b/arch/parisc/install.sh @@ -26,13 +26,13 @@ if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi # Default install -if [ -f $4/vmlinux ]; then - mv $4/vmlinux $4/vmlinux.old +if [ -f $4/vmlinuz ]; then + mv $4/vmlinuz $4/vmlinuz.old fi if [ -f $4/System.map ]; then mv $4/System.map $4/System.old fi -cat $2 > $4/vmlinux +cat $2 > $4/vmlinuz cp $3 $4/System.map -- GitLab From 92b59929825d67db575043a76651865d16873b36 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 29 Jun 2013 22:08:03 +0200 Subject: [PATCH 2532/2900] parisc: optimize mtsp(0,sr) inline assembly If the value which should be moved into a space register is zero, we can optimize the inline assembly to become "mtsp %r0,%srX". Signed-off-by: Helge Deller Cc: # 3.10 --- arch/parisc/include/asm/special_insns.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h index d306b75bc77f..e1509308899f 100644 --- a/arch/parisc/include/asm/special_insns.h +++ b/arch/parisc/include/asm/special_insns.h @@ -32,9 +32,12 @@ static inline void set_eiem(unsigned long val) cr; \ }) -#define mtsp(gr, cr) \ - __asm__ __volatile__("mtsp %0,%1" \ +#define mtsp(val, cr) \ + { if (__builtin_constant_p(val) && ((val) == 0)) \ + __asm__ __volatile__("mtsp %%r0,%0" : : "i" (cr) : "memory"); \ + else \ + __asm__ __volatile__("mtsp %0,%1" \ : /* no outputs */ \ - : "r" (gr), "i" (cr) : "memory") + : "r" (val), "i" (cr) : "memory"); } #endif /* __PARISC_SPECIAL_INSNS_H */ -- GitLab From e8d8fc219f9a0e63e7fb927881e6f4db8e7d34df Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sat, 29 Jun 2013 16:42:12 -0400 Subject: [PATCH 2533/2900] parisc: Ensure volatile space register %sr1 is not clobbered I still see the occasional random segv on rp3440. Looking at one of these (a code 15), it appeared the problem must be with the cache handling of anonymous pages. Reviewing this, I noticed that the space register %sr1 might be being clobbered when we flush an anonymous page. Register %sr1 is used for TLB purges in a couple of places. These purges are needed on PA8800 and PA8900 processors to ensure cache consistency of flushed cache lines. The solution here is simply to move the %sr1 load into the TLB lock region needed to ensure that one purge executes at a time on SMP systems. This was already the case for one use. After a few days of operation, I haven't had a random segv on my rp3440. Signed-off-by: John David Anglin Cc: # 3.10 Signed-off-by: Helge Deller --- arch/parisc/include/asm/tlbflush.h | 5 +++-- arch/parisc/kernel/cache.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 5273da991e06..9d086a599fa0 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h @@ -63,13 +63,14 @@ static inline void flush_tlb_mm(struct mm_struct *mm) static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { - unsigned long flags; + unsigned long flags, sid; /* For one page, it's not worth testing the split_tlb variable */ mb(); - mtsp(vma->vm_mm->context,1); + sid = vma->vm_mm->context; purge_tlb_start(flags); + mtsp(sid, 1); pdtlb(addr); pitlb(addr); purge_tlb_end(flags); diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 65fb4cbc3a0f..2e65aa54bd10 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -440,8 +440,8 @@ void __flush_tlb_range(unsigned long sid, unsigned long start, else { unsigned long flags; - mtsp(sid, 1); purge_tlb_start(flags); + mtsp(sid, 1); if (split_tlb) { while (npages--) { pdtlb(start); -- GitLab From 5b879d78bc0818aa710f5d4d9abbfc2aca075cc3 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 4 Jul 2013 22:34:11 +0200 Subject: [PATCH 2534/2900] parisc: Fix gcc miscompilation in pa_memcpy() When running the LTP testsuite one may hit this kernel BUG() with the write06 testcase: kernel BUG at mm/filemap.c:2023! CPU: 1 PID: 8614 Comm: writev01 Not tainted 3.10.0-rc7-64bit-c3000+ #6 IASQ: 0000000000000000 0000000000000000 IAOQ: 00000000401e6e84 00000000401e6e88 IIR: 03ffe01f ISR: 0000000010340000 IOR: 000001fbe0380820 CPU: 1 CR30: 00000000bef80000 CR31: ffffffffffffffff ORIG_R28: 00000000bdc192c0 IAOQ[0]: iov_iter_advance+0x3c/0xc0 IAOQ[1]: iov_iter_advance+0x40/0xc0 RP(r2): generic_file_buffered_write+0x204/0x3f0 Backtrace: [<00000000401e764c>] generic_file_buffered_write+0x204/0x3f0 [<00000000401eab24>] __generic_file_aio_write+0x244/0x448 [<00000000401eadc0>] generic_file_aio_write+0x98/0x150 [<000000004024f460>] do_sync_readv_writev+0xc0/0x130 [<000000004025037c>] compat_do_readv_writev+0x12c/0x340 [<00000000402505f8>] compat_writev+0x68/0xa0 [<0000000040251d88>] compat_SyS_writev+0x98/0xf8 Reason for this crash is a gcc miscompilation in the fault handlers of pa_memcpy() which return the fault address instead of the copied bytes. Since this seems to be a generic problem with gcc-4.7.x (and below), it's better to simplify the fault handlers in pa_memcpy to avoid this problem. Here is a simple reproducer for the problem: int main(int argc, char **argv) { int fd, nbytes; struct iovec wr_iovec[] = { { "TEST STRING ",32}, { (char*)0x40005000,32} }; // random memory. fd = open(DATA_FILE, O_RDWR | O_CREAT, 0666); nbytes = writev(fd, wr_iovec, 2); printf("return value = %d, errno %d (%s)\n", nbytes, errno, strerror(errno)); return 0; } In addition, John David Anglin wrote: There is no gcc PR as pa_memcpy is not legitimate C code. There is an implicit assumption that certain variables will contain correct values when an exception occurs and the code randomly jumps to one of the exception blocks. There is no guarantee of this. If a PR was filed, it would likely be marked as invalid. Signed-off-by: Helge Deller Signed-off-by: John David Anglin Cc: # 3.8+ Signed-off-by: Helge Deller --- arch/parisc/lib/memcpy.c | 79 +++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index a49cc812df8a..ac4370b1ca40 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -2,6 +2,7 @@ * Optimized memory copy routines. * * Copyright (C) 2004 Randolph Chung + * Copyright (C) 2013 Helge Deller * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -153,17 +154,21 @@ static inline void prefetch_dst(const void *addr) #define prefetch_dst(addr) do { } while(0) #endif +#define PA_MEMCPY_OK 0 +#define PA_MEMCPY_LOAD_ERROR 1 +#define PA_MEMCPY_STORE_ERROR 2 + /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words * per loop. This code is derived from glibc. */ -static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len) +static inline unsigned long copy_dstaligned(unsigned long dst, + unsigned long src, unsigned long len) { /* gcc complains that a2 and a3 may be uninitialized, but actually * they cannot be. Initialize a2/a3 to shut gcc up. */ register unsigned int a0, a1, a2 = 0, a3 = 0; int sh_1, sh_2; - struct exception_data *d; /* prefetch_src((const void *)src); */ @@ -197,7 +202,7 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src goto do2; case 0: if (len == 0) - return 0; + return PA_MEMCPY_OK; /* a3 = ((unsigned int *) src)[0]; a0 = ((unsigned int *) src)[1]; */ ldw(s_space, 0, src, a3, cda_ldw_exc); @@ -256,42 +261,35 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src preserve_branch(handle_load_error); preserve_branch(handle_store_error); - return 0; + return PA_MEMCPY_OK; handle_load_error: __asm__ __volatile__ ("cda_ldw_exc:\n"); - d = &__get_cpu_var(exception_data); - DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n", - o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src); - return o_len * 4 - d->fault_addr + o_src; + return PA_MEMCPY_LOAD_ERROR; handle_store_error: __asm__ __volatile__ ("cda_stw_exc:\n"); - d = &__get_cpu_var(exception_data); - DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n", - o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst); - return o_len * 4 - d->fault_addr + o_dst; + return PA_MEMCPY_STORE_ERROR; } -/* Returns 0 for success, otherwise, returns number of bytes not transferred. */ -static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) +/* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR. + * In case of an access fault the faulty address can be read from the per_cpu + * exception data struct. */ +static unsigned long pa_memcpy_internal(void *dstp, const void *srcp, + unsigned long len) { register unsigned long src, dst, t1, t2, t3; register unsigned char *pcs, *pcd; register unsigned int *pws, *pwd; register double *pds, *pdd; - unsigned long ret = 0; - unsigned long o_dst, o_src, o_len; - struct exception_data *d; + unsigned long ret; src = (unsigned long)srcp; dst = (unsigned long)dstp; pcs = (unsigned char *)srcp; pcd = (unsigned char *)dstp; - o_dst = dst; o_src = src; o_len = len; - /* prefetch_src((const void *)srcp); */ if (len < THRESHOLD) @@ -401,7 +399,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) len--; } - return 0; + return PA_MEMCPY_OK; unaligned_copy: /* possibly we are aligned on a word, but not on a double... */ @@ -438,8 +436,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) src = (unsigned long)pcs; } - ret = copy_dstaligned(dst, src, len / sizeof(unsigned int), - o_dst, o_src, o_len); + ret = copy_dstaligned(dst, src, len / sizeof(unsigned int)); if (ret) return ret; @@ -454,17 +451,41 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) handle_load_error: __asm__ __volatile__ ("pmc_load_exc:\n"); - d = &__get_cpu_var(exception_data); - DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n", - o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src); - return o_len - d->fault_addr + o_src; + return PA_MEMCPY_LOAD_ERROR; handle_store_error: __asm__ __volatile__ ("pmc_store_exc:\n"); + return PA_MEMCPY_STORE_ERROR; +} + + +/* Returns 0 for success, otherwise, returns number of bytes not transferred. */ +static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) +{ + unsigned long ret, fault_addr, reference; + struct exception_data *d; + + ret = pa_memcpy_internal(dstp, srcp, len); + if (likely(ret == PA_MEMCPY_OK)) + return 0; + + /* if a load or store fault occured we can get the faulty addr */ d = &__get_cpu_var(exception_data); - DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n", - o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst); - return o_len - d->fault_addr + o_dst; + fault_addr = d->fault_addr; + + /* error in load or store? */ + if (ret == PA_MEMCPY_LOAD_ERROR) + reference = (unsigned long) srcp; + else + reference = (unsigned long) dstp; + + DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n", + ret, len, fault_addr, reference); + + if (fault_addr >= reference) + return len - (fault_addr - reference); + else + return len; } #ifdef __KERNEL__ -- GitLab From a363a9da65d253fa7354ce5fd630f4f94df934cc Mon Sep 17 00:00:00 2001 From: Michael Witten Date: Wed, 17 Apr 2013 02:23:16 +0000 Subject: [PATCH 2535/2900] perf tools: Revert regression in configuration of Python support Among other things, the following: commit 31160d7feab786c991780d7f0ce2755a469e0e5e Date: Tue Jan 8 16:22:36 2013 -0500 perf tools: Fix GNU make v3.80 compatibility issue attempts to aid the user by tapping into an existing error message, as described in the commit message: ... Also fix an issue where _get_attempt was called with only one argument. This prevented the error message from printing the name of the variable that can be used to fix the problem. or more precisely: -$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) +$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1))) However, The "missing" argument was in fact missing on purpose; it's absence is a signal that the error message should be skipped, because the failure would be due to the default value, not any user-supplied value. This can be seen in how `_ge_attempt' uses `gea_err' (in the config/utilities.mak file): _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) _gea_warn = $(warning The path '$(1)' is not executable.) _gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) That is, because the argument is no longer missing, the value `$(1)' (associated with `_gea_err') always evaluates to true, thus always triggering the error condition that is meant to be reserved for only the case when a user explicitly supplies an invalid value. Concretely, the result is a regression in the Makefile's configuration of python support; rather than gracefully disable support when the relevant executables cannot be found according to default values, the build process halts in error as though the user explicitly supplied the values. This new commit simply reverts the offending one-line change. Reported-by: Pekka Enberg Link: http://lkml.kernel.org/r/CAOJsxLHv17Ys3M7P5q25imkUxQW6LE_vABxh1N3Tt7Mv6Ho4iw@mail.gmail.com Signed-off-by: Michael Witten --- tools/perf/config/utilities.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak index faffb52fcf80..94d2d4f9c35d 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/perf/config/utilities.mak @@ -173,7 +173,7 @@ _ge-abspath = $(if $(is-executable),$(1)) # Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default) # define get-executable-or-default -$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2),$(1))) +$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) endef _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) _gea_warn = $(warning The path '$(1)' is not executable.) -- GitLab From 9cee4c5b7b706157554cb06ca949997240da725a Mon Sep 17 00:00:00 2001 From: Jie Liu Date: Mon, 1 Jul 2013 21:51:32 +0800 Subject: [PATCH 2536/2900] xfs: clean up unused codes at xfs_bulkstat() There are some unused codes at xfs_bulkstat(): - Variable bp is defined to point to the on-disk inode cluster buffer, but it proved to be of no practical help. - We process the chunks of good inodes which were fetched by iterating btree records from an AG. When processing inodes from each chunk, the code recomputing agbno if run into the first inode of a cluster, however, the agbno is not being used thereafter. This patch tries to clean up those things. Signed-off-by: Jie Liu Reviewed-by: Dave Chinner Signed-off-by: Ben Myers --- fs/xfs/xfs_itable.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index bc92c5306a17..b93e14b86754 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -221,7 +221,6 @@ xfs_bulkstat( char __user *ubufp; /* pointer into user's buffer */ int ubelem; /* spaces used in user's buffer */ int ubused; /* bytes used by formatter */ - xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ /* * Get the last inode value, see if there's nothing to do. @@ -263,7 +262,6 @@ xfs_bulkstat( rval = 0; while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) { cond_resched(); - bp = NULL; error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); if (error) { /* @@ -436,27 +434,7 @@ xfs_bulkstat( irbp->ir_freecount < XFS_INODES_PER_CHUNK; chunkidx++, clustidx++, agino++) { ASSERT(chunkidx < XFS_INODES_PER_CHUNK); - /* - * Recompute agbno if this is the - * first inode of the cluster. - * - * Careful with clustidx. There can be - * multiple clusters per chunk, a single - * cluster per chunk or a cluster that has - * inodes represented from several different - * chunks (if blocksize is large). - * - * Because of this, the starting clustidx is - * initialized to zero in this loop but must - * later be reset after reading in the cluster - * buffer. - */ - if ((chunkidx & (nicluster - 1)) == 0) { - agbno = XFS_AGINO_TO_AGBNO(mp, - irbp->ir_startino) + - ((chunkidx & nimask) >> - mp->m_sb.sb_inopblog); - } + ino = XFS_AGINO_TO_INO(mp, agno, agino); /* * Skip if this inode is free. @@ -502,10 +480,6 @@ xfs_bulkstat( cond_resched(); } - - if (bp) - xfs_buf_relse(bp); - /* * Set up for the next loop iteration. */ -- GitLab From 862a62937e76a91da218c1ee4dceb7b0700fed67 Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Tue, 2 Jul 2013 18:39:34 +0200 Subject: [PATCH 2537/2900] xfs: use get_unused_fd_flags(0) instead of get_unused_fd() Macro get_unused_fd() is used to allocate a file descriptor with default flags. Those default flags (0) can be "unsafe": O_CLOEXEC must be used by default to not leak file descriptor across exec(). Instead of macro get_unused_fd(), functions anon_inode_getfd() or get_unused_fd_flags() should be used with flags given by userspace. If not possible, flags should be set to O_CLOEXEC to provide userspace with a default safe behavor. In a further patch, get_unused_fd() will be removed so that new code start using anon_inode_getfd() or get_unused_fd_flags() with correct flags. This patch replaces calls to get_unused_fd() with equivalent call to get_unused_fd_flags(0) to preserve current behavor for existing code. The hard coded flag value (0) should be reviewed on a per-subsystem basis, and, if possible, set to O_CLOEXEC. Signed-off-by: Yann Droneaud Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 5e999680094a..dc5b65983e5f 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -248,7 +248,7 @@ xfs_open_by_handle( goto out_dput; } - fd = get_unused_fd(); + fd = get_unused_fd_flags(0); if (fd < 0) { error = fd; goto out_dput; -- GitLab From fd832478422834be03029ffab6df96f4df35f3e6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 9 Jul 2013 18:34:01 +0100 Subject: [PATCH 2538/2900] ARM: 7782/1: Kconfig: Let ARM_ERRATA_364296 not depend on CONFIG_SMP imx_v6_v7_defconfig handles both multi-core and single-core SoCs, and it has CONFIG_SMP=y selected by default. With such config we cannot select ARM_ERRATA_364296, as it depends on !SMP. Let ARM_ERRATA_364296 be undependent on CONFIG_SMP, so that we can select this erratum for the ARM1136 SoCs, even if CONFIG_SMP=y is enabled. Reviewed-by: Dave Martin Signed-off-by: Fabio Estevam Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 136f263ed47b..6271d7eb8b29 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1300,7 +1300,7 @@ config ARM_ERRATA_754327 config ARM_ERRATA_364296 bool "ARM errata: Possible cache data corruption with hit-under-miss enabled" - depends on CPU_V6 && !SMP + depends on CPU_V6 help This options enables the workaround for the 364296 ARM1136 r0p2 erratum (possible cache data corruption with -- GitLab From 8f6817a0a57cf15935f8f076d0ade34da01cf26d Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sun, 7 Jul 2013 21:24:00 +0100 Subject: [PATCH 2539/2900] iio staging: fix lis3l02dq, read error handling Signed-off-by: Peter Meerwald Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/lis3l02dq_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 1bfe5d81792b..8ed75a94f465 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -257,6 +257,8 @@ static int lis3l02dq_read_raw(struct iio_dev *indio_dev, ret = lis3l02dq_read_reg_s16(indio_dev, reg, val); } mutex_unlock(&indio_dev->mlock); + if (ret < 0) + goto error_ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; -- GitLab From cbbe6f82b489e7ceba4ad7c833bd3a76cd0084cb Mon Sep 17 00:00:00 2001 From: Jason Liu Date: Mon, 1 Jul 2013 09:53:30 +0100 Subject: [PATCH 2540/2900] ARM: 7778/1: smp_twd: twd_update_frequency need be run on all online CPUs When the local timer freq changed, the twd_update_frequency function should be run all the CPUs include itself, otherwise, the twd freq will not get updated and the local timer will not run correcttly. smp_call_function will run functions on all other CPUs, but not include himself, this is not correct,use on_each_cpu instead to fix this issue. Cc: Linus Walleij Cc: Rob Herring Cc: Shawn Guo Cc: Arnd Bergmann Cc: stable@vger.kernel.org Acked-by: Linus Walleij Acked-by: Shawn Guo Signed-off-by: Jason Liu Signed-off-by: Russell King --- arch/arm/kernel/smp_twd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 90525d9d290b..f6fd1d4398c6 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -120,7 +120,7 @@ static int twd_rate_change(struct notifier_block *nb, * changing cpu. */ if (flags == POST_RATE_CHANGE) - smp_call_function(twd_update_frequency, + on_each_cpu(twd_update_frequency, (void *)&cnd->new_rate, 1); return NOTIFY_OK; -- GitLab From cda57a1ef6f0da7e24f392ffdf00538ec0480310 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Thu, 4 Jul 2013 06:35:23 -0400 Subject: [PATCH 2541/2900] nfs: set verifier on existing dentries in nfs_prime_dcache nfs_prime_dcache currently only sets the verifier when it doesn't initially a matching dentry in the dcache. Set the verifier in the case where we do find a dentry in the dcache. This ensures that we don't have to look up the dentry again if we want to use it after a readdir. Cc: Scott Mayhew Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 0fac2cb1ea18..bd7e1cc53b90 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -450,6 +450,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) dentry = d_lookup(parent, &filename); if (dentry != NULL) { if (nfs_same_file(dentry, entry)) { + nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); status = nfs_refresh_inode(dentry->d_inode, entry->fattr); if (!status) nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); -- GitLab From 76fa66657900071016f2bae61de28f059f3f2abf Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 2 Jul 2013 13:00:52 -0400 Subject: [PATCH 2542/2900] rpc_pipe: set dentry operations at d_alloc time Currently the way these get set is a little convoluted. If the dentry is allocated via lookup from userland, then it gets set by simple_lookup. If it gets allocated when the kernel is populating the directory, then it gets set via __rpc_lookup_create_exclusive, which has to check whether they might already be set. Between both of these, this ensures that all dentries have their d_op pointer set. Instead of doing that, just have them set at d_alloc time by pointing sb->s_d_op at them. With that change, we no longer want the lookup op to set them, so we must move to using our own lookup routine. Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust --- net/sunrpc/rpc_pipe.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 4679df5a6d50..c5f6812ca06a 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -480,6 +480,23 @@ static const struct dentry_operations rpc_dentry_operations = { .d_delete = rpc_delete_dentry, }; +/* + * Lookup the data. This is trivial - if the dentry didn't already + * exist, we know it is negative. + */ +static struct dentry * +rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) +{ + if (dentry->d_name.len > NAME_MAX) + return ERR_PTR(-ENAMETOOLONG); + d_add(dentry, NULL); + return NULL; +} + +const struct inode_operations rpc_dir_inode_operations = { + .lookup = rpc_lookup, +}; + static struct inode * rpc_get_inode(struct super_block *sb, umode_t mode) { @@ -492,7 +509,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode) switch (mode & S_IFMT) { case S_IFDIR: inode->i_fop = &simple_dir_operations; - inode->i_op = &simple_dir_inode_operations; + inode->i_op = &rpc_dir_inode_operations; inc_nlink(inode); default: break; @@ -666,11 +683,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, if (!dentry) return ERR_PTR(-ENOMEM); } - if (dentry->d_inode == NULL) { - if (!dentry->d_op) - d_set_d_op(dentry, &rpc_dentry_operations); + if (dentry->d_inode == NULL) return dentry; - } dput(dentry); return ERR_PTR(-EEXIST); } @@ -1117,6 +1131,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RPCAUTH_GSSMAGIC; sb->s_op = &s_ops; + sb->s_d_op = &rpc_dentry_operations; sb->s_time_gran = 1; inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); -- GitLab From 43f291cd0754f8f10c2cd701e014936f708dab59 Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Fri, 5 Jul 2013 17:49:30 -0400 Subject: [PATCH 2543/2900] NFS: Make nfs_attribute_cache_expired() non-static NFS: Make nfs_attribute_cache_expired() non-static so we can call it from nfs_readdir(). Signed-off-by: Scott Mayhew Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 2 +- include/linux/nfs_fs.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index c93639e6cf68..af6e806044d7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -936,7 +936,7 @@ int nfs_attribute_timeout(struct inode *inode) return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo); } -static int nfs_attribute_cache_expired(struct inode *inode) +int nfs_attribute_cache_expired(struct inode *inode) { if (nfs_have_delegated_attributes(inode)) return 0; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 0b176297aaf6..7125cef74164 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -348,6 +348,7 @@ extern int nfs_permission(struct inode *, int); extern int nfs_open(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *); extern int nfs_attribute_timeout(struct inode *inode); +extern int nfs_attribute_cache_expired(struct inode *inode); extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); -- GitLab From 07b5ce8ef2d87f1914054804720d6facbaa3f4ce Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Fri, 5 Jul 2013 17:49:31 -0400 Subject: [PATCH 2544/2900] NFS: Make nfs_readdir revalidate less often Make nfs_readdir revalidate only when we're at the beginning of the directory or if the cached attributes have expired. Signed-off-by: Scott Mayhew Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index bd7e1cc53b90..e474ca2b2bfe 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -818,7 +818,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) nfs_readdir_descriptor_t my_desc, *desc = &my_desc; struct nfs_open_dir_context *dir_ctx = file->private_data; - int res; + int res = 0; dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", dentry->d_parent->d_name.name, dentry->d_name.name, @@ -840,7 +840,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; nfs_block_sillyrename(dentry); - res = nfs_revalidate_mapping(inode, file->f_mapping); + if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) + res = nfs_revalidate_mapping(inode, file->f_mapping); if (res < 0) goto out; -- GitLab From 3e5b7d8b491c3710b7e007eab0a643f923932e3d Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 10 Jul 2013 07:03:59 +1000 Subject: [PATCH 2545/2900] xfs: update mount options documentation Because it's horribly out of date. And mark various deprecated options as deprecated and give them a removal date. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- Documentation/filesystems/xfs.txt | 317 ++++++++++++++++++++---------- 1 file changed, 209 insertions(+), 108 deletions(-) diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt index 83577f0232a0..12525b17d9ed 100644 --- a/Documentation/filesystems/xfs.txt +++ b/Documentation/filesystems/xfs.txt @@ -18,6 +18,8 @@ Mount Options ============= When mounting an XFS filesystem, the following options are accepted. +For boolean mount options, the names with the (*) suffix is the +default behaviour. allocsize=size Sets the buffered I/O end-of-file preallocation size when @@ -25,97 +27,128 @@ When mounting an XFS filesystem, the following options are accepted. Valid values for this option are page size (typically 4KiB) through to 1GiB, inclusive, in power-of-2 increments. - attr2/noattr2 - The options enable/disable (default is disabled for backward - compatibility on-disk) an "opportunistic" improvement to be - made in the way inline extended attributes are stored on-disk. - When the new form is used for the first time (by setting or - removing extended attributes) the on-disk superblock feature - bit field will be updated to reflect this format being in use. + The default behaviour is for dynamic end-of-file + preallocation size, which uses a set of heuristics to + optimise the preallocation size based on the current + allocation patterns within the file and the access patterns + to the file. Specifying a fixed allocsize value turns off + the dynamic behaviour. + + attr2 + noattr2 + The options enable/disable an "opportunistic" improvement to + be made in the way inline extended attributes are stored + on-disk. When the new form is used for the first time when + attr2 is selected (either when setting or removing extended + attributes) the on-disk superblock feature bit field will be + updated to reflect this format being in use. + + The default behaviour is determined by the on-disk feature + bit indicating that attr2 behaviour is active. If either + mount option it set, then that becomes the new default used + by the filesystem. CRC enabled filesystems always use the attr2 format, and so will reject the noattr2 mount option if it is set. - barrier - Enables the use of block layer write barriers for writes into - the journal and unwritten extent conversion. This allows for - drive level write caching to be enabled, for devices that - support write barriers. + barrier (*) + nobarrier + Enables/disables the use of block layer write barriers for + writes into the journal and for data integrity operations. + This allows for drive level write caching to be enabled, for + devices that support write barriers. discard - Issue command to let the block device reclaim space freed by the - filesystem. This is useful for SSD devices, thinly provisioned - LUNs and virtual machine images, but may have a performance - impact. - - dmapi - Enable the DMAPI (Data Management API) event callouts. - Use with the "mtpt" option. - - grpid/bsdgroups and nogrpid/sysvgroups - These options define what group ID a newly created file gets. - When grpid is set, it takes the group ID of the directory in - which it is created; otherwise (the default) it takes the fsgid - of the current process, unless the directory has the setgid bit - set, in which case it takes the gid from the parent directory, - and also gets the setgid bit set if it is a directory itself. - - ihashsize=value - In memory inode hashes have been removed, so this option has - no function as of August 2007. Option is deprecated. - - ikeep/noikeep - When ikeep is specified, XFS does not delete empty inode clusters - and keeps them around on disk. ikeep is the traditional XFS - behaviour. When noikeep is specified, empty inode clusters - are returned to the free space pool. The default is noikeep for - non-DMAPI mounts, while ikeep is the default when DMAPI is in use. - - inode64 - Indicates that XFS is allowed to create inodes at any location - in the filesystem, including those which will result in inode - numbers occupying more than 32 bits of significance. This is - the default allocation option. Applications which do not handle - inode numbers bigger than 32 bits, should use inode32 option. + nodiscard (*) + Enable/disable the issuing of commands to let the block + device reclaim space freed by the filesystem. This is + useful for SSD devices, thinly provisioned LUNs and virtual + machine images, but may have a performance impact. + + Note: It is currently recommended that you use the fstrim + application to discard unused blocks rather than the discard + mount option because the performance impact of this option + is quite severe. + + grpid/bsdgroups + nogrpid/sysvgroups (*) + These options define what group ID a newly created file + gets. When grpid is set, it takes the group ID of the + directory in which it is created; otherwise it takes the + fsgid of the current process, unless the directory has the + setgid bit set, in which case it takes the gid from the + parent directory, and also gets the setgid bit set if it is + a directory itself. + + filestreams + Make the data allocator use the filestreams allocation mode + across the entire filesystem rather than just on directories + configured to use it. + + ikeep + noikeep (*) + When ikeep is specified, XFS does not delete empty inode + clusters and keeps them around on disk. When noikeep is + specified, empty inode clusters are returned to the free + space pool. inode32 - Indicates that XFS is limited to create inodes at locations which - will not result in inode numbers with more than 32 bits of - significance. This is provided for backwards compatibility, since - 64 bits inode numbers might cause problems for some applications - that cannot handle large inode numbers. - - largeio/nolargeio + inode64 (*) + When inode32 is specified, it indicates that XFS limits + inode creation to locations which will not result in inode + numbers with more than 32 bits of significance. + + When inode64 is specified, it indicates that XFS is allowed + to create inodes at any location in the filesystem, + including those which will result in inode numbers occupying + more than 32 bits of significance. + + inode32 is provided for backwards compatibility with older + systems and applications, since 64 bits inode numbers might + cause problems for some applications that cannot handle + large inode numbers. If applications are in use which do + not handle inode numbers bigger than 32 bits, the inode32 + option should be specified. + + + largeio + nolargeio (*) If "nolargeio" is specified, the optimal I/O reported in - st_blksize by stat(2) will be as small as possible to allow user - applications to avoid inefficient read/modify/write I/O. - If "largeio" specified, a filesystem that has a "swidth" specified - will return the "swidth" value (in bytes) in st_blksize. If the - filesystem does not have a "swidth" specified but does specify - an "allocsize" then "allocsize" (in bytes) will be returned - instead. - If neither of these two options are specified, then filesystem - will behave as if "nolargeio" was specified. + st_blksize by stat(2) will be as small as possible to allow + user applications to avoid inefficient read/modify/write + I/O. This is typically the page size of the machine, as + this is the granularity of the page cache. + + If "largeio" specified, a filesystem that was created with a + "swidth" specified will return the "swidth" value (in bytes) + in st_blksize. If the filesystem does not have a "swidth" + specified but does specify an "allocsize" then "allocsize" + (in bytes) will be returned instead. Otherwise the behaviour + is the same as if "nolargeio" was specified. logbufs=value - Set the number of in-memory log buffers. Valid numbers range - from 2-8 inclusive. - The default value is 8 buffers for filesystems with a - blocksize of 64KiB, 4 buffers for filesystems with a blocksize - of 32KiB, 3 buffers for filesystems with a blocksize of 16KiB - and 2 buffers for all other configurations. Increasing the - number of buffers may increase performance on some workloads - at the cost of the memory used for the additional log buffers - and their associated control structures. + Set the number of in-memory log buffers. Valid numbers + range from 2-8 inclusive. + + The default value is 8 buffers. + + If the memory cost of 8 log buffers is too high on small + systems, then it may be reduced at some cost to performance + on metadata intensive workloads. The logbsize option below + controls the size of each buffer and so is also relevent to + this case. logbsize=value - Set the size of each in-memory log buffer. - Size may be specified in bytes, or in kilobytes with a "k" suffix. - Valid sizes for version 1 and version 2 logs are 16384 (16k) and - 32768 (32k). Valid sizes for version 2 logs also include - 65536 (64k), 131072 (128k) and 262144 (256k). - The default value for machines with more than 32MiB of memory - is 32768, machines with less memory use 16384 by default. + Set the size of each in-memory log buffer. The size may be + specified in bytes, or in kilobytes with a "k" suffix. + Valid sizes for version 1 and version 2 logs are 16384 (16k) + and 32768 (32k). Valid sizes for version 2 logs also + include 65536 (64k), 131072 (128k) and 262144 (256k). The + logbsize must be an integer multiple of the log + stripe unit configured at mkfs time. + + The default value for for version 1 logs is 32768, while the + default value for version 2 logs is MAX(32768, log_sunit). logdev=device and rtdev=device Use an external log (metadata journal) and/or real-time device. @@ -124,16 +157,11 @@ When mounting an XFS filesystem, the following options are accepted. optional, and the log section can be separate from the data section or contained within it. - mtpt=mountpoint - Use with the "dmapi" option. The value specified here will be - included in the DMAPI mount event, and should be the path of - the actual mountpoint that is used. - noalign - Data allocations will not be aligned at stripe unit boundaries. - - noatime - Access timestamps are not updated when a file is read. + Data allocations will not be aligned at stripe unit + boundaries. This is only relevant to filesystems created + with non-zero data alignment parameters (sunit, swidth) by + mkfs. norecovery The filesystem will be mounted without running log recovery. @@ -144,8 +172,14 @@ When mounting an XFS filesystem, the following options are accepted. the mount will fail. nouuid - Don't check for double mounted file systems using the file system uuid. - This is useful to mount LVM snapshot volumes. + Don't check for double mounted file systems using the file + system uuid. This is useful to mount LVM snapshot volumes, + and often used in combination with "norecovery" for mounting + read-only snapshots. + + noquota + Forcibly turns off all quota accounting and enforcement + within the filesystem. uquota/usrquota/uqnoenforce/quota User disk quota accounting enabled, and limits (optionally) @@ -160,24 +194,64 @@ When mounting an XFS filesystem, the following options are accepted. enforced. Refer to xfs_quota(8) for further details. sunit=value and swidth=value - Used to specify the stripe unit and width for a RAID device or - a stripe volume. "value" must be specified in 512-byte block - units. - If this option is not specified and the filesystem was made on - a stripe volume or the stripe width or unit were specified for - the RAID device at mkfs time, then the mount system call will - restore the value from the superblock. For filesystems that - are made directly on RAID devices, these options can be used - to override the information in the superblock if the underlying - disk layout changes after the filesystem has been created. - The "swidth" option is required if the "sunit" option has been - specified, and must be a multiple of the "sunit" value. + Used to specify the stripe unit and width for a RAID device + or a stripe volume. "value" must be specified in 512-byte + block units. These options are only relevant to filesystems + that were created with non-zero data alignment parameters. + + The sunit and swidth parameters specified must be compatible + with the existing filesystem alignment characteristics. In + general, that means the only valid changes to sunit are + increasing it by a power-of-2 multiple. Valid swidth values + are any integer multiple of a valid sunit value. + + Typically the only time these mount options are necessary if + after an underlying RAID device has had it's geometry + modified, such as adding a new disk to a RAID5 lun and + reshaping it. swalloc Data allocations will be rounded up to stripe width boundaries when the current end of file is being extended and the file size is larger than the stripe width size. + wsync + When specified, all filesystem namespace operations are + executed synchronously. This ensures that when the namespace + operation (create, unlink, etc) completes, the change to the + namespace is on stable storage. This is useful in HA setups + where failover must not result in clients seeing + inconsistent namespace presentation during or after a + failover event. + + +Deprecated Mount Options +======================== + + delaylog/nodelaylog + Delayed logging is the only logging method that XFS supports + now, so these mount options are now ignored. + + Due for removal in 3.12. + + ihashsize=value + In memory inode hashes have been removed, so this option has + no function as of August 2007. Option is deprecated. + + Due for removal in 3.12. + + irixsgid + This behaviour is now controlled by a sysctl, so the mount + option is ignored. + + Due for removal in 3.12. + + osyncisdsync + osyncisosync + O_SYNC and O_DSYNC are fully supported, so there is no need + for these options any more. + + Due for removal in 3.12. sysctls ======= @@ -189,15 +263,20 @@ The following sysctls are available for the XFS filesystem: in /proc/fs/xfs/stat. It then immediately resets to "0". fs.xfs.xfssyncd_centisecs (Min: 100 Default: 3000 Max: 720000) - The interval at which the xfssyncd thread flushes metadata - out to disk. This thread will flush log activity out, and - do some processing on unlinked inodes. + The interval at which the filesystem flushes metadata + out to disk and runs internal cache cleanup routines. - fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) - The interval at which xfsbufd scans the dirty metadata buffers list. + fs.xfs.filestream_centisecs (Min: 1 Default: 3000 Max: 360000) + The interval at which the filesystem ages filestreams cache + references and returns timed-out AGs back to the free stream + pool. - fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) - The age at which xfsbufd flushes dirty metadata buffers to disk. + fs.xfs.speculative_prealloc_lifetime + (Units: seconds Min: 1 Default: 300 Max: 86400) + The interval at which the background scanning for inodes + with unused speculative preallocation runs. The scan + removes unused preallocation from clean inodes and releases + the unused space back to the free pool. fs.xfs.error_level (Min: 0 Default: 3 Max: 11) A volume knob for error reporting when internal errors occur. @@ -254,9 +333,31 @@ The following sysctls are available for the XFS filesystem: by the xfs_io(8) chattr command on a directory to be inherited by files in that directory. + fs.xfs.inherit_nodefrag (Min: 0 Default: 1 Max: 1) + Setting this to "1" will cause the "nodefrag" flag set + by the xfs_io(8) chattr command on a directory to be + inherited by files in that directory. + fs.xfs.rotorstep (Min: 1 Default: 1 Max: 256) In "inode32" allocation mode, this option determines how many files the allocator attempts to allocate in the same allocation group before moving to the next allocation group. The intent is to control the rate at which the allocator moves between allocation groups when allocating extents for new files. + +Deprecated Sysctls +================== + + fs.xfs.xfsbufd_centisecs (Min: 50 Default: 100 Max: 3000) + Dirty metadata is now tracked by the log subsystem and + flushing is driven by log space and idling demands. The + xfsbufd no longer exists, so this syctl does nothing. + + Due for removal in 3.14. + + fs.xfs.age_buffer_centisecs (Min: 100 Default: 1500 Max: 720000) + Dirty metadata is now tracked by the log subsystem and + flushing is driven by log space and idling demands. The + xfsbufd no longer exists, so this syctl does nothing. + + Due for removal in 3.14. -- GitLab From f3508bcddf8fae6ebd21000d708cf09e7e77a963 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 10 Jul 2013 07:04:00 +1000 Subject: [PATCH 2546/2900] xfs: remove local fork format handling from xfs_bmapi_write() The conversion from local format to extent format requires interpretation of the data in the fork being converted, so it cannot be done in a generic way. It is up to the caller to convert the fork format to extent format before calling into xfs_bmapi_write() so format conversion can be done correctly. The code in xfs_bmapi_write() to convert the format is used implicitly by the attribute and directory code, but they specifically zero the fork size so that the conversion does not do any allocation or manipulation. Move this conversion into the shortform to leaf functions for the dir/attr code so the conversions are explicitly controlled by all callers. Now we can remove the conversion code in xfs_bmapi_write. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_attr_leaf.c | 2 + fs/xfs/xfs_bmap.c | 199 +++++++++++++++++----------------------- fs/xfs/xfs_bmap.h | 1 + fs/xfs/xfs_dir2_block.c | 20 ++-- 4 files changed, 98 insertions(+), 124 deletions(-) diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 31d3cd129269..b800fbcafc7f 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -690,6 +690,8 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) sf = (xfs_attr_shortform_t *)tmpbuffer; xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); + xfs_bmap_local_to_extents_empty(dp, XFS_ATTR_FORK); + bp = NULL; error = xfs_da_grow_inode(args, &blkno); if (error) { diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 89042848f9ec..05c698ccb238 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -1161,6 +1161,24 @@ xfs_bmap_extents_to_btree( * since the file data needs to get logged so things will stay consistent. * (The bmap-level manipulations are ok, though). */ +void +xfs_bmap_local_to_extents_empty( + struct xfs_inode *ip, + int whichfork) +{ + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + + ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); + ASSERT(ifp->if_bytes == 0); + ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); + + xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); + ifp->if_flags &= ~XFS_IFINLINE; + ifp->if_flags |= XFS_IFEXTENTS; + XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); +} + + STATIC int /* error */ xfs_bmap_local_to_extents( xfs_trans_t *tp, /* transaction pointer */ @@ -1174,9 +1192,12 @@ xfs_bmap_local_to_extents( struct xfs_inode *ip, struct xfs_ifork *ifp)) { - int error; /* error return value */ + int error = 0; int flags; /* logging flags returned */ xfs_ifork_t *ifp; /* inode fork pointer */ + xfs_alloc_arg_t args; /* allocation arguments */ + xfs_buf_t *bp; /* buffer for extent block */ + xfs_bmbt_rec_host_t *ep; /* extent record pointer */ /* * We don't want to deal with the case of keeping inode data inline yet. @@ -1185,68 +1206,65 @@ xfs_bmap_local_to_extents( ASSERT(!(S_ISREG(ip->i_d.di_mode) && whichfork == XFS_DATA_FORK)); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); + + if (!ifp->if_bytes) { + xfs_bmap_local_to_extents_empty(ip, whichfork); + flags = XFS_ILOG_CORE; + goto done; + } + flags = 0; error = 0; - if (ifp->if_bytes) { - xfs_alloc_arg_t args; /* allocation arguments */ - xfs_buf_t *bp; /* buffer for extent block */ - xfs_bmbt_rec_host_t *ep;/* extent record pointer */ - - ASSERT((ifp->if_flags & - (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); - memset(&args, 0, sizeof(args)); - args.tp = tp; - args.mp = ip->i_mount; - args.firstblock = *firstblock; - /* - * Allocate a block. We know we need only one, since the - * file currently fits in an inode. - */ - if (*firstblock == NULLFSBLOCK) { - args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); - args.type = XFS_ALLOCTYPE_START_BNO; - } else { - args.fsbno = *firstblock; - args.type = XFS_ALLOCTYPE_NEAR_BNO; - } - args.total = total; - args.minlen = args.maxlen = args.prod = 1; - error = xfs_alloc_vextent(&args); - if (error) - goto done; - - /* Can't fail, the space was reserved. */ - ASSERT(args.fsbno != NULLFSBLOCK); - ASSERT(args.len == 1); - *firstblock = args.fsbno; - bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0); - - /* initialise the block and copy the data */ - init_fn(tp, bp, ip, ifp); - - /* account for the change in fork size and log everything */ - xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); - xfs_bmap_forkoff_reset(args.mp, ip, whichfork); - xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); - xfs_iext_add(ifp, 0, 1); - ep = xfs_iext_get_ext(ifp, 0); - xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); - trace_xfs_bmap_post_update(ip, 0, - whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0, - _THIS_IP_); - XFS_IFORK_NEXT_SET(ip, whichfork, 1); - ip->i_d.di_nblocks = 1; - xfs_trans_mod_dquot_byino(tp, ip, - XFS_TRANS_DQ_BCOUNT, 1L); - flags |= xfs_ilog_fext(whichfork); + ASSERT((ifp->if_flags & (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == + XFS_IFINLINE); + memset(&args, 0, sizeof(args)); + args.tp = tp; + args.mp = ip->i_mount; + args.firstblock = *firstblock; + /* + * Allocate a block. We know we need only one, since the + * file currently fits in an inode. + */ + if (*firstblock == NULLFSBLOCK) { + args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); + args.type = XFS_ALLOCTYPE_START_BNO; } else { - ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); - xfs_bmap_forkoff_reset(ip->i_mount, ip, whichfork); + args.fsbno = *firstblock; + args.type = XFS_ALLOCTYPE_NEAR_BNO; } - ifp->if_flags &= ~XFS_IFINLINE; - ifp->if_flags |= XFS_IFEXTENTS; - XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); + args.total = total; + args.minlen = args.maxlen = args.prod = 1; + error = xfs_alloc_vextent(&args); + if (error) + goto done; + + /* Can't fail, the space was reserved. */ + ASSERT(args.fsbno != NULLFSBLOCK); + ASSERT(args.len == 1); + *firstblock = args.fsbno; + bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0); + + /* initialise the block and copy the data */ + init_fn(tp, bp, ip, ifp); + + /* account for the change in fork size and log everything */ + xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1); + xfs_idata_realloc(ip, -ifp->if_bytes, whichfork); + xfs_bmap_local_to_extents_empty(ip, whichfork); flags |= XFS_ILOG_CORE; + + xfs_iext_add(ifp, 0, 1); + ep = xfs_iext_get_ext(ifp, 0); + xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM); + trace_xfs_bmap_post_update(ip, 0, + whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0, + _THIS_IP_); + XFS_IFORK_NEXT_SET(ip, whichfork, 1); + ip->i_d.di_nblocks = 1; + xfs_trans_mod_dquot_byino(tp, ip, + XFS_TRANS_DQ_BCOUNT, 1L); + flags |= xfs_ilog_fext(whichfork); + done: *logflagsp = flags; return error; @@ -1322,25 +1340,6 @@ xfs_bmap_add_attrfork_extents( return error; } -/* - * Block initialisation function for local to extent format conversion. - * - * This shouldn't actually be called by anyone, so make sure debug kernels cause - * a noticable failure. - */ -STATIC void -xfs_bmap_local_to_extents_init_fn( - struct xfs_trans *tp, - struct xfs_buf *bp, - struct xfs_inode *ip, - struct xfs_ifork *ifp) -{ - ASSERT(0); - bp->b_ops = &xfs_bmbt_buf_ops; - memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes); - xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF); -} - /* * Called from xfs_bmap_add_attrfork to handle local format files. Each * different data fork content type needs a different callout to do the @@ -1381,9 +1380,9 @@ xfs_bmap_add_attrfork_local( flags, XFS_DATA_FORK, xfs_symlink_local_to_remote); - return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, - XFS_DATA_FORK, - xfs_bmap_local_to_extents_init_fn); + /* should only be called for types that support local format data */ + ASSERT(0); + return EFSCORRUPTED; } /* @@ -4907,20 +4906,19 @@ xfs_bmapi_write( orig_mval = mval; orig_nmap = *nmap; #endif + whichfork = (flags & XFS_BMAPI_ATTRFORK) ? + XFS_ATTR_FORK : XFS_DATA_FORK; ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); ASSERT(!(flags & XFS_BMAPI_IGSTATE)); ASSERT(tp != NULL); ASSERT(len > 0); - - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); @@ -4933,37 +4931,6 @@ xfs_bmapi_write( XFS_STATS_INC(xs_blk_mapw); - if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { - /* - * XXX (dgc): This assumes we are only called for inodes that - * contain content neutral data in local format. Anything that - * contains caller-specific data in local format that needs - * transformation to move to a block format needs to do the - * conversion to extent format itself. - * - * Directory data forks and attribute forks handle this - * themselves, but with the addition of metadata verifiers every - * data fork in local format now contains caller specific data - * and as such conversion through this function is likely to be - * broken. - * - * The only likely user of this branch is for remote symlinks, - * but we cannot overwrite the data fork contents of the symlink - * (EEXIST occurs higher up the stack) and so it will never go - * from local format to extent format here. Hence I don't think - * this branch is ever executed intentionally and we should - * consider removing it and asserting that xfs_bmapi_write() - * cannot be called directly on local format forks. i.e. callers - * are completely responsible for local to extent format - * conversion, not xfs_bmapi_write(). - */ - error = xfs_bmap_local_to_extents(tp, ip, firstblock, total, - &bma.logflags, whichfork, - xfs_bmap_local_to_extents_init_fn); - if (error) - goto error0; - } - if (*firstblock == NULLFSBLOCK) { if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 5f469c3516eb..1cf1292d29b7 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -172,6 +172,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, #endif int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); +void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, struct xfs_bmap_free *flist, struct xfs_mount *mp); void xfs_bmap_cancel(struct xfs_bmap_free *flist); diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index e59f5fc816fe..53b9aa26d567 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -29,6 +29,7 @@ #include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_inode_item.h" +#include "xfs_bmap.h" #include "xfs_buf_item.h" #include "xfs_dir2.h" #include "xfs_dir2_format.h" @@ -1167,13 +1168,15 @@ xfs_dir2_sf_to_block( __be16 *tagp; /* end of data entry */ xfs_trans_t *tp; /* transaction pointer */ struct xfs_name name; + struct xfs_ifork *ifp; trace_xfs_dir2_sf_to_block(args); dp = args->dp; tp = args->trans; mp = dp->i_mount; - ASSERT(dp->i_df.if_flags & XFS_IFINLINE); + ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK); + ASSERT(ifp->if_flags & XFS_IFINLINE); /* * Bomb out if the shortform directory is way too short. */ @@ -1182,22 +1185,23 @@ xfs_dir2_sf_to_block( return XFS_ERROR(EIO); } - oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; + oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data; - ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); - ASSERT(dp->i_df.if_u1.if_data != NULL); + ASSERT(ifp->if_bytes == dp->i_d.di_size); + ASSERT(ifp->if_u1.if_data != NULL); ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count)); + ASSERT(dp->i_d.di_nextents == 0); /* * Copy the directory into a temporary buffer. * Then pitch the incore inode data so we can make extents. */ - sfp = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP); - memcpy(sfp, oldsfp, dp->i_df.if_bytes); + sfp = kmem_alloc(ifp->if_bytes, KM_SLEEP); + memcpy(sfp, oldsfp, ifp->if_bytes); - xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK); + xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK); + xfs_bmap_local_to_extents_empty(dp, XFS_DATA_FORK); dp->i_d.di_size = 0; - xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); /* * Add block 0 to the inode. -- GitLab From b0a9dab78aee2a479d7c226e6939d553967e4024 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 10 Jul 2013 07:04:01 +1000 Subject: [PATCH 2547/2900] xfs: dquot log reservations are too small During review of the separate project quota inode patches, it became obvious that the dquot log reservation calculation underestimated the number dquots that can be modified in a transaction. This has it's roots way back in the Irix quota implementation. That is, when quotas were first implemented in XFS, it only supported user and project quotas as Irix did not have group quotas. Hence the worst case operation involving dquot modification was calculated to involve 2 user dquots and 1 project dquot or 1 user dequot and 2 project dquots. i.e. 3 dquots. This was determined back in 1996, and has remained unchanged ever since. However, back in 2001, the Linux XFS port dropped all support for project quota and implmented group quotas over the top. This was effectively done with a search-and-replace of project with group, and as such the log reservation was not changed. However, with the advent of group quotas, chmod and rename now could modify more than 3 dquots in a single transaction - both could modify 4 dquots. Hence this log reservation has been wrong for a long time. In 2005, project quota support was reintroduced into Linux, but it was implemented to be mutually exclusive to group quotas and so this didn't add any new changes to the dquot log reservation. Hence when project quotas were in use (rather than group quotas) the log reservation was again valid, just like in the Irix days. Now, with the addition of the separate project quota inode, group and project quotas are no longer mutually exclusive, and hence operations can now modify three dquots per inode where previously it was only two. The worst case here is the rename transaction, which can allocate/free space on two different directory inodes, and if they have different uid/gid/prid configurations and are world writeable, then rename can actually modify 6 different dquots now. Further, the dquot log reservation doesn't take into account the space used by the dquot log format structure that precedes the dquot that is logged, and hence further underestimates the worst case log space required by dquots during a transaction. This has been missing since the first commit in 1996. Hence the worst case log reservation needs to be increased from 3 to 6, and it needs to take into account a log format header for each of those dquots. Signed-off-by: Dave Chinner Reviewed-by: Mark Tinguely Signed-off-by: Ben Myers --- fs/xfs/xfs_quota.h | 25 +++++++++++++++++++++---- fs/xfs/xfs_trans_dquot.c | 9 ++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index c3483bab9cde..40d508be9a00 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -108,11 +108,28 @@ typedef struct xfs_dqblk { { XFS_DQ_FREEING, "FREEING" } /* - * In the worst case, when both user and group quotas are on, - * we can have a max of three dquots changing in a single transaction. + * We have the possibility of all three quota types being active at once, and + * hence free space modification requires modification of all three current + * dquots in a single transaction. For this case we need to have a reservation + * of at least 3 dquots. + * + * However, a chmod operation can change both UID and GID in a single + * transaction, resulting in requiring {old, new} x {uid, gid} dquots to be + * modified. Hence for this case we need to reserve space for at least 4 dquots. + * + * And in the worst case, there's a rename operation that can be modifying up to + * 4 inodes with dquots attached to them. In reality, the only inodes that can + * have their dquots modified are the source and destination directory inodes + * due to directory name creation and removal. That can require space allocation + * and/or freeing on both directory inodes, and hence all three dquots on each + * inode can be modified. And if the directories are world writeable, all the + * dquots can be unique and so 6 dquots can be modified.... + * + * And, of course, we also need to take into account the dquot log format item + * used to describe each dquot. */ -#define XFS_DQUOT_LOGRES(mp) (sizeof(xfs_disk_dquot_t) * 3) - +#define XFS_DQUOT_LOGRES(mp) \ + ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6) /* * These are the structures used to lay out dquots and quotaoff diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index 3ba64d540168..db041a5e1f6d 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -291,11 +291,10 @@ xfs_trans_mod_dquot( /* - * Given an array of dqtrx structures, lock all the dquots associated - * and join them to the transaction, provided they have been modified. - * We know that the highest number of dquots (of one type - usr OR grp), - * involved in a transaction is 2 and that both usr and grp combined - 3. - * So, we don't attempt to make this very generic. + * Given an array of dqtrx structures, lock all the dquots associated and join + * them to the transaction, provided they have been modified. We know that the + * highest number of dquots of one type - usr, grp OR prj - involved in a + * transaction is 2 so we don't need to make this very generic. */ STATIC void xfs_trans_dqlockedjoin( -- GitLab From 655ee63cf3714ac0a7ebee4a7dd00fdc54b006fc Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 2 Jul 2013 00:17:34 -0400 Subject: [PATCH 2548/2900] [SCSI] scsi constants: command, sense key + additional sense strings It has been several years since the SCSI constants.c file has been updated. The attached is against lk 3.10 and brings the command strings, sense keys and additional sense code strings into sync with spc4r36g.pdf. Certain SCSI command names that previously only took the opcode (i.e. byte 0 of the cdb) into account, have been split into several command names using the associated service action field to differentiate. For example, persistent reservations that previously had 2 commands (i.e. "in" and "out") have been expanded to 12 commands (e.g. "Persistent reserve in, read reservation"). Sync SCSI command names, sense key strings and additional sense code strings with SPC-4 draft revision 36g [jejb: whitespace fix] Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 235 +++++++++++++++++++++++++++++++-------- 1 file changed, 187 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 76e4c039f0d5..d35a5d6c8d7c 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1,10 +1,10 @@ -/* +/* * ASCII values for a number of symbolic constants, printing functions, * etc. * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422) * Additions for SCSI 3+ (SPC-3 T10/1416-D Rev 07 3 May 2002) * by D. Gilbert and aeb (20020609) - * Update to SPC-4 T10/1713-D Rev 20, 22 May 2009, D. Gilbert 20090624 + * Updated to SPC-4 T10/1713-D Rev 36g, D. Gilbert 20130701 */ #include @@ -21,12 +21,13 @@ /* Commands with service actions that change the command name */ -#define MAINTENANCE_IN 0xa3 -#define MAINTENANCE_OUT 0xa4 #define SERVICE_ACTION_IN_12 0xab #define SERVICE_ACTION_OUT_12 0xa9 +#define SERVICE_ACTION_BIDIRECTIONAL 0x9d #define SERVICE_ACTION_IN_16 0x9e #define SERVICE_ACTION_OUT_16 0x9f +#define THIRD_PARTY_COPY_OUT 0x83 +#define THIRD_PARTY_COPY_IN 0x84 @@ -36,11 +37,11 @@ static const char * cdb_byte0_names[] = { /* 04-07 */ "Format Unit/Medium", "Read Block Limits", NULL, "Reassign Blocks", /* 08-0d */ "Read(6)", NULL, "Write(6)", "Seek(6)", NULL, NULL, -/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry", +/* 0e-12 */ NULL, "Read Reverse", "Write Filemarks", "Space", "Inquiry", /* 13-16 */ "Verify(6)", "Recover Buffered Data", "Mode Select(6)", "Reserve(6)", /* 17-1a */ "Release(6)", "Copy", "Erase", "Mode Sense(6)", -/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic", +/* 1b-1d */ "Start/Stop Unit", "Receive Diagnostic", "Send Diagnostic", /* 1e-1f */ "Prevent/Allow Medium Removal", NULL, /* 20-22 */ NULL, NULL, NULL, /* 23-28 */ "Read Format Capacities", "Set Window", @@ -48,16 +49,16 @@ static const char * cdb_byte0_names[] = { /* 29-2d */ "Read Generation", "Write(10)", "Seek(10)", "Erase(10)", "Read updated block", /* 2e-31 */ "Write Verify(10)", "Verify(10)", "Search High", "Search Equal", -/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position", +/* 32-34 */ "Search Low", "Set Limits", "Prefetch/Read Position", /* 35-37 */ "Synchronize Cache(10)", "Lock/Unlock Cache(10)", - "Read Defect Data(10)", -/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", - "Read Buffer", + "Read Defect Data(10)", +/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", + "Read Buffer", /* 3d-3f */ "Update Block", "Read Long(10)", "Write Long(10)", /* 40-41 */ "Change Definition", "Write Same(10)", /* 42-48 */ "Unmap/Read sub-channel", "Read TOC/PMA/ATIP", "Read density support", "Play audio(10)", "Get configuration", - "Play audio msf", "Play audio track/index", + "Play audio msf", "Sanitize/Play audio track/index", /* 49-4f */ "Play track relative(10)", "Get event status notification", "Pause/resume", "Log Select", "Log Sense", "Stop play/scan", NULL, @@ -72,17 +73,17 @@ static const char * cdb_byte0_names[] = { /* 70-77 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 78-7f */ NULL, NULL, NULL, NULL, NULL, NULL, "Extended CDB", "Variable length", -/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", "Extended copy", - "Receive copy results", +/* 80-84 */ "Xdwrite(16)", "Rebuild(16)", "Regenerate(16)", + "Third party copy out", "Third party copy in", /* 85-89 */ "ATA command pass through(16)", "Access control in", - "Access control out", "Read(16)", "Memory Export Out(16)", + "Access control out", "Read(16)", "Compare and Write", /* 8a-8f */ "Write(16)", "ORWrite", "Read attributes", "Write attributes", "Write and verify(16)", "Verify(16)", /* 90-94 */ "Pre-fetch(16)", "Synchronize cache(16)", "Lock/unlock cache(16)", "Write same(16)", NULL, /* 95-99 */ NULL, NULL, NULL, NULL, NULL, -/* 9a-9f */ NULL, NULL, NULL, NULL, "Service action in(16)", - "Service action out(16)", +/* 9a-9f */ NULL, NULL, NULL, "Service action bidirectional", + "Service action in(16)", "Service action out(16)", /* a0-a5 */ "Report luns", "ATA command pass through(12)/Blank", "Security protocol in", "Maintenance in", "Maintenance out", "Move medium/play audio(12)", @@ -122,6 +123,7 @@ static const struct value_name_pair maint_out_arr[] = { {0x6, "Set identifying information"}, {0xa, "Set target port groups"}, {0xb, "Change aliases"}, + {0xc, "Remove I_T nexus"}, {0xe, "Set priority"}, {0xf, "Set timestamp"}, {0x10, "Management protocol out"}, @@ -138,10 +140,16 @@ static const struct value_name_pair serv_out12_arr[] = { }; #define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr) +static const struct value_name_pair serv_bidi_arr[] = { + {-1, "dummy entry"}, +}; +#define SERV_BIDI_SZ ARRAY_SIZE(serv_bidi_arr) + static const struct value_name_pair serv_in16_arr[] = { {0x10, "Read capacity(16)"}, {0x11, "Read long(16)"}, {0x12, "Get LBA status"}, + {0x13, "Report referrals"}, }; #define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr) @@ -151,6 +159,51 @@ static const struct value_name_pair serv_out16_arr[] = { }; #define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr) +static const struct value_name_pair pr_in_arr[] = { + {0x0, "Persistent reserve in, read keys"}, + {0x1, "Persistent reserve in, read reservation"}, + {0x2, "Persistent reserve in, report capabilities"}, + {0x3, "Persistent reserve in, read full status"}, +}; +#define PR_IN_SZ ARRAY_SIZE(pr_in_arr) + +static const struct value_name_pair pr_out_arr[] = { + {0x0, "Persistent reserve out, register"}, + {0x1, "Persistent reserve out, reserve"}, + {0x2, "Persistent reserve out, release"}, + {0x3, "Persistent reserve out, clear"}, + {0x4, "Persistent reserve out, preempt"}, + {0x5, "Persistent reserve out, preempt and abort"}, + {0x6, "Persistent reserve out, register and ignore existing key"}, + {0x7, "Persistent reserve out, register and move"}, +}; +#define PR_OUT_SZ ARRAY_SIZE(pr_out_arr) + +/* SPC-4 rev 34 renamed the Extended Copy opcode to Third Party Copy Out. + LID1 (List Identifier length: 1 byte) is the Extended Copy found in SPC-2 + and SPC-3 */ +static const struct value_name_pair tpc_out_arr[] = { + {0x0, "Extended copy(LID1)"}, + {0x1, "Extended copy(LID4)"}, + {0x10, "Populate token"}, + {0x11, "Write using token"}, + {0x1c, "Copy operation abort"}, +}; +#define TPC_OUT_SZ ARRAY_SIZE(tpc_out_arr) + +static const struct value_name_pair tpc_in_arr[] = { + {0x0, "Receive copy status(LID1)"}, + {0x1, "Receive copy data(LID1)"}, + {0x3, "Receive copy operating parameters"}, + {0x4, "Receive copy failure details(LID1)"}, + {0x5, "Receive copy status(LID4)"}, + {0x6, "Receive copy data(LID4)"}, + {0x7, "Receive ROD token information"}, + {0x8, "Report all ROD tokens"}, +}; +#define TPC_IN_SZ ARRAY_SIZE(tpc_in_arr) + + static const struct value_name_pair variable_length_arr[] = { {0x1, "Rebuild(32)"}, {0x2, "Regenerate(32)"}, @@ -207,6 +260,7 @@ static const char * get_sa_name(const struct value_name_pair * arr, static void print_opcode_name(unsigned char * cdbp, int cdb_len) { int sa, len, cdb0; + int fin_name = 0; const char * name; cdb0 = cdbp[0]; @@ -219,7 +273,8 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) break; } sa = (cdbp[8] << 8) + cdbp[9]; - name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ, sa); + name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ, + sa); if (name) printk("%s", name); else @@ -232,50 +287,57 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) case MAINTENANCE_IN: sa = cdbp[1] & 0x1f; name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; break; case MAINTENANCE_OUT: sa = cdbp[1] & 0x1f; name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; + break; + case PERSISTENT_RESERVE_IN: + sa = cdbp[1] & 0x1f; + name = get_sa_name(pr_in_arr, PR_IN_SZ, sa); + fin_name = 1; + break; + case PERSISTENT_RESERVE_OUT: + sa = cdbp[1] & 0x1f; + name = get_sa_name(pr_out_arr, PR_OUT_SZ, sa); + fin_name = 1; break; case SERVICE_ACTION_IN_12: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; break; case SERVICE_ACTION_OUT_12: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; + break; + case SERVICE_ACTION_BIDIRECTIONAL: + sa = cdbp[1] & 0x1f; + name = get_sa_name(serv_bidi_arr, SERV_BIDI_SZ, sa); + fin_name = 1; break; case SERVICE_ACTION_IN_16: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; break; case SERVICE_ACTION_OUT_16: sa = cdbp[1] & 0x1f; name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa); - if (name) - printk("%s", name); - else - printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + fin_name = 1; + break; + case THIRD_PARTY_COPY_IN: + sa = cdbp[1] & 0x1f; + name = get_sa_name(tpc_in_arr, TPC_IN_SZ, sa); + fin_name = 1; + break; + case THIRD_PARTY_COPY_OUT: + sa = cdbp[1] & 0x1f; + name = get_sa_name(tpc_out_arr, TPC_OUT_SZ, sa); + fin_name = 1; break; default: if (cdb0 < 0xc0) { @@ -288,6 +350,12 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) printk("cdb[0]=0x%x (vendor)", cdb0); break; } + if (fin_name) { + if (name) + printk("%s", name); + else + printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); + } } #else /* ifndef CONFIG_SCSI_CONSTANTS */ @@ -312,10 +380,15 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) break; case MAINTENANCE_IN: case MAINTENANCE_OUT: + case PERSISTENT_RESERVE_IN: + case PERSISTENT_RESERVE_OUT: case SERVICE_ACTION_IN_12: case SERVICE_ACTION_OUT_12: + case SERVICE_ACTION_BIDIRECTIONAL: case SERVICE_ACTION_IN_16: case SERVICE_ACTION_OUT_16: + case THIRD_PARTY_COPY_IN: + case THIRD_PARTY_COPY_OUT: sa = cdbp[1] & 0x1f; printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa); break; @@ -327,7 +400,7 @@ static void print_opcode_name(unsigned char * cdbp, int cdb_len) break; } } -#endif +#endif void __scsi_print_command(unsigned char *cdb) { @@ -336,7 +409,7 @@ void __scsi_print_command(unsigned char *cdb) print_opcode_name(cdb, 0); len = scsi_command_size(cdb); /* print out all bytes in cdb */ - for (k = 0; k < len; ++k) + for (k = 0; k < len; ++k) printk(" %02x", cdb[k]); printk("\n"); } @@ -404,8 +477,9 @@ struct error_info { /* * The canonical list of T10 Additional Sense Codes is available at: - * http://www.t10.org/lists/asc-num.txt + * http://www.t10.org/lists/asc-num.txt [most recent: 20130605] */ + static const struct error_info additional[] = { {0x0000, "No additional sense information"}, @@ -430,6 +504,8 @@ static const struct error_info additional[] = {0x001C, "Verify operation in progress"}, {0x001D, "ATA pass through information available"}, {0x001E, "Conflicting SA creation request"}, + {0x001F, "Logical unit transitioning to another power condition"}, + {0x0020, "Extended copy information available"}, {0x0100, "No index/sector signal"}, @@ -460,6 +536,17 @@ static const struct error_info additional[] = {0x0412, "Logical unit not ready, offline"}, {0x0413, "Logical unit not ready, SA creation in progress"}, {0x0414, "Logical unit not ready, space allocation in progress"}, + {0x0415, "Logical unit not ready, robotics disabled"}, + {0x0416, "Logical unit not ready, configuration required"}, + {0x0417, "Logical unit not ready, calibration required"}, + {0x0418, "Logical unit not ready, a door is open"}, + {0x0419, "Logical unit not ready, operating in sequential mode"}, + {0x041A, "Logical unit not ready, start stop unit command in " + "progress"}, + {0x041B, "Logical unit not ready, sanitize in progress"}, + {0x041C, "Logical unit not ready, additional power use not yet " + "granted"}, + {0x041D, "Logical unit not ready, configuration in progress"}, {0x0500, "Logical unit does not respond to selection"}, @@ -490,6 +577,7 @@ static const struct error_info additional[] = {0x0B06, "Warning - non-volatile cache now volatile"}, {0x0B07, "Warning - degraded power to non-volatile cache"}, {0x0B08, "Warning - power loss expected"}, + {0x0B09, "Warning - device statistics notification active"}, {0x0C00, "Write error"}, {0x0C01, "Write error - recovered with auto reallocation"}, @@ -505,6 +593,7 @@ static const struct error_info additional[] = {0x0C0B, "Auxiliary memory write error"}, {0x0C0C, "Write error - unexpected unsolicited data"}, {0x0C0D, "Write error - not enough unsolicited data"}, + {0x0C0E, "Multiple write errors"}, {0x0C0F, "Defects in error window"}, {0x0D00, "Error detected by third party temporary initiator"}, @@ -523,6 +612,8 @@ static const struct error_info additional[] = {0x1001, "Logical block guard check failed"}, {0x1002, "Logical block application tag check failed"}, {0x1003, "Logical block reference tag check failed"}, + {0x1004, "Logical block protection error on recover buffered data"}, + {0x1005, "Logical block protection method error"}, {0x1100, "Unrecovered read error"}, {0x1101, "Read retries exhausted"}, @@ -545,6 +636,7 @@ static const struct error_info additional[] = {0x1112, "Auxiliary memory read error"}, {0x1113, "Read error - failed retransmission request"}, {0x1114, "Read error - lba marked bad by application client"}, + {0x1115, "Write after sanitize required"}, {0x1200, "Address mark not found for id field"}, @@ -622,6 +714,7 @@ static const struct error_info additional[] = {0x2009, "Access denied - invalid LU identifier"}, {0x200A, "Access denied - invalid proxy token"}, {0x200B, "Access denied - ACL LUN conflict"}, + {0x200C, "Illegal command when not in append-only mode"}, {0x2100, "Logical block address out of range"}, {0x2101, "Invalid element address"}, @@ -630,6 +723,19 @@ static const struct error_info additional[] = {0x2200, "Illegal function (use 20 00, 24 00, or 26 00)"}, + {0x2300, "Invalid token operation, cause not reportable"}, + {0x2301, "Invalid token operation, unsupported token type"}, + {0x2302, "Invalid token operation, remote token usage not supported"}, + {0x2303, "Invalid token operation, remote rod token creation not " + "supported"}, + {0x2304, "Invalid token operation, token unknown"}, + {0x2305, "Invalid token operation, token corrupt"}, + {0x2306, "Invalid token operation, token revoked"}, + {0x2307, "Invalid token operation, token expired"}, + {0x2308, "Invalid token operation, token cancelled"}, + {0x2309, "Invalid token operation, token deleted"}, + {0x230A, "Invalid token operation, invalid token length"}, + {0x2400, "Invalid field in cdb"}, {0x2401, "CDB decryption error"}, {0x2402, "Obsolete"}, @@ -705,6 +811,7 @@ static const struct error_info additional[] = "event"}, {0x2A13, "Data encryption key instance counter has changed"}, {0x2A14, "SA creation capabilities data has changed"}, + {0x2A15, "Medium removal prevention preempted"}, {0x2B00, "Copy cannot execute since host cannot disconnect"}, @@ -720,6 +827,7 @@ static const struct error_info additional[] = {0x2C09, "Previous reservation conflict status"}, {0x2C0A, "Partition or collection contains user objects"}, {0x2C0B, "Not reserved"}, + {0x2C0C, "Orwrite generation does not match"}, {0x2D00, "Overwrite error on update in place"}, @@ -728,6 +836,7 @@ static const struct error_info additional[] = {0x2F00, "Commands cleared by another initiator"}, {0x2F01, "Commands cleared by power loss notification"}, {0x2F02, "Commands cleared by device server"}, + {0x2F03, "Some commands cleared by queuing layer event"}, {0x3000, "Incompatible medium installed"}, {0x3001, "Cannot read medium - unknown format"}, @@ -745,10 +854,12 @@ static const struct error_info additional[] = {0x3010, "Medium not formatted"}, {0x3011, "Incompatible volume type"}, {0x3012, "Incompatible volume qualifier"}, + {0x3013, "Cleaning volume expired"}, {0x3100, "Medium format corrupted"}, {0x3101, "Format command failed"}, {0x3102, "Zoned formatting failed due to spare linking"}, + {0x3103, "Sanitize command failed"}, {0x3200, "No defect spare location available"}, {0x3201, "Defect list update failure"}, @@ -809,6 +920,8 @@ static const struct error_info additional[] = {0x3B19, "Element enabled"}, {0x3B1A, "Data transfer device removed"}, {0x3B1B, "Data transfer device inserted"}, + {0x3B1C, "Too many logical objects on partition to support " + "operation"}, {0x3D00, "Invalid bits in identify message"}, @@ -839,6 +952,7 @@ static const struct error_info additional[] = {0x3F12, "iSCSI IP address added"}, {0x3F13, "iSCSI IP address removed"}, {0x3F14, "iSCSI IP address changed"}, + {0x3F15, "Inspect referrals sense descriptors"}, /* * {0x40NN, "Ram failure"}, * {0x40NN, "Diagnostic failure on component nn"}, @@ -848,6 +962,7 @@ static const struct error_info additional[] = {0x4300, "Message error"}, {0x4400, "Internal target failure"}, + {0x4401, "Persistent reservation information lost"}, {0x4471, "ATA device failed set features"}, {0x4500, "Select or reselect failure"}, @@ -876,6 +991,21 @@ static const struct error_info additional[] = {0x4B04, "Nak received"}, {0x4B05, "Data offset error"}, {0x4B06, "Initiator response timeout"}, + {0x4B07, "Connection lost"}, + {0x4B08, "Data-in buffer overflow - data buffer size"}, + {0x4B09, "Data-in buffer overflow - data buffer descriptor area"}, + {0x4B0A, "Data-in buffer error"}, + {0x4B0B, "Data-out buffer overflow - data buffer size"}, + {0x4B0C, "Data-out buffer overflow - data buffer descriptor area"}, + {0x4B0D, "Data-out buffer error"}, + {0x4B0E, "PCIe fabric error"}, + {0x4B0F, "PCIe completion timeout"}, + {0x4B10, "PCIe completer abort"}, + {0x4B11, "PCIe poisoned tlp received"}, + {0x4B12, "PCIe eCRC check failed"}, + {0x4B13, "PCIe unsupported request"}, + {0x4B14, "PCIe acs violation"}, + {0x4B15, "PCIe tlp prefix blocked"}, {0x4C00, "Logical unit failed self-configuration"}, /* @@ -897,6 +1027,10 @@ static const struct error_info additional[] = {0x5302, "Medium removal prevented"}, {0x5303, "Medium removal prevented by data transfer element"}, {0x5304, "Medium thread or unthread failure"}, + {0x5305, "Volume identifier invalid"}, + {0x5306, "Volume identifier missing"}, + {0x5307, "Duplicate volume identifier"}, + {0x5308, "Element status unknown"}, {0x5400, "Scsi to host system interface failure"}, @@ -911,6 +1045,9 @@ static const struct error_info additional[] = {0x5508, "Maximum number of supplemental decryption keys exceeded"}, {0x5509, "Medium auxiliary memory not accessible"}, {0x550A, "Data currently unavailable"}, + {0x550B, "Insufficient power for operation"}, + {0x550C, "Insufficient resources to create rod"}, + {0x550D, "Insufficient resources to create rod token"}, {0x5700, "Unable to recover table-of-contents"}, @@ -1069,6 +1206,7 @@ static const struct error_info additional[] = {0x670B, "ATA device feature not enabled"}, {0x6800, "Logical unit not configured"}, + {0x6801, "Subsidiary logical unit not configured"}, {0x6900, "Data loss on logical unit"}, {0x6901, "Multiple logical unit failures"}, @@ -1185,10 +1323,13 @@ static const char * const snstext[] = { "Vendor Specific(9)", "Copy Aborted", /* A: COPY or COMPARE was aborted */ "Aborted Command", /* B: The target aborted the command */ - "Equal", /* C: A SEARCH DATA command found data equal */ + "Equal", /* C: A SEARCH DATA command found data equal, + reserved in SPC-4 rev 36 */ "Volume Overflow", /* D: Medium full with still data to be written */ "Miscompare", /* E: Source data and data on the medium do not agree */ + "Completed", /* F: command completed sense data reported, + may occur for successful command */ }; #endif @@ -1306,7 +1447,7 @@ scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { int k, num, res; - + res = scsi_normalize_sense(sense_buffer, sense_len, sshdr); if (0 == res) { /* this may be SCSI-1 sense data */ @@ -1459,5 +1600,3 @@ void scsi_print_result(struct scsi_cmnd *cmd) scsi_show_result(cmd->result); } EXPORT_SYMBOL(scsi_print_result); - - -- GitLab From c7559663e42f4294ffe31fe159da6b6a66b35d61 Mon Sep 17 00:00:00 2001 From: Scott Mayhew Date: Fri, 5 Jul 2013 17:33:19 -0400 Subject: [PATCH 2549/2900] NFS: Allow nfs_updatepage to extend a write under additional circumstances Currently nfs_updatepage allows a write to be extended to cover a full page only if we don't have a byte range lock lock on the file... but if we have a write delegation on the file or if we have the whole file locked for writing then we should be allowed to extend the write as well. Signed-off-by: Scott Mayhew [Trond: fix up call to nfs_have_delegation()] Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index a2c7c28049d5..f1bdb7254776 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -888,6 +888,28 @@ static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) return PageUptodate(page) != 0; } +/* If we know the page is up to date, and we're not using byte range locks (or + * if we have the whole file locked for writing), it may be more efficient to + * extend the write to cover the entire page in order to avoid fragmentation + * inefficiencies. + * + * If the file is opened for synchronous writes or if we have a write delegation + * from the server then we can just skip the rest of the checks. + */ +static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) +{ + if (file->f_flags & O_DSYNC) + return 0; + if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) + return 1; + if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL || + (inode->i_flock->fl_start == 0 && + inode->i_flock->fl_end == OFFSET_MAX && + inode->i_flock->fl_type != F_RDLCK))) + return 1; + return 0; +} + /* * Update and possibly write a cached page of an NFS file. * @@ -908,14 +930,7 @@ int nfs_updatepage(struct file *file, struct page *page, file->f_path.dentry->d_name.name, count, (long long)(page_file_offset(page) + offset)); - /* If we're not using byte range locks, and we know the page - * is up to date, it may be more efficient to extend the write - * to cover the entire page in order to avoid fragmentation - * inefficiencies. - */ - if (nfs_write_pageuptodate(page, inode) && - inode->i_flock == NULL && - !(file->f_flags & O_DSYNC)) { + if (nfs_can_extend_write(file, page, inode)) { count = max(count + offset, nfs_page_length(page)); offset = 0; } -- GitLab From 4f8568cb5290295c384d5c1328c52790e33a8a0d Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Wed, 10 Jul 2013 09:17:14 +0800 Subject: [PATCH 2550/2900] rpc_pipe: rpc_dir_inode_operations can be static Hi Jeff, FYI, there are new sparse warnings show up in tree: git://git.linux-nfs.org/projects/trondmy/linux-nfs.git nfs-for-next head: 296afe1f58d55fd56ed85daaafafcfee39f59ece commit: 76fa66657900071016f2bae61de28f059f3f2abf [2/5] rpc_pipe: set dentry operations at d_alloc time >> net/sunrpc/rpc_pipe.c:496:31: sparse: symbol 'rpc_dir_inode_operations' was not declared. Should it be static? Please consider folding the attached diff :-) Signed-off-by: Fengguang Wu Signed-off-by: Trond Myklebust --- net/sunrpc/rpc_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index c5f6812ca06a..61239a2cb786 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -493,7 +493,7 @@ rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) return NULL; } -const struct inode_operations rpc_dir_inode_operations = { +static const struct inode_operations rpc_dir_inode_operations = { .lookup = rpc_lookup, }; -- GitLab From 40c2702a02b755e0183b702778331b351f3be20c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 8 Jul 2013 09:50:24 +0200 Subject: [PATCH 2551/2900] microblaze: Move __NR_syscalls from uapi The reason is that other applications like strace think that every __NR_xx is syscall. Also __NR_syscalls is not used by user applications/libs. Signed-off-by: Michal Simek --- arch/microblaze/include/asm/unistd.h | 3 +++ arch/microblaze/include/uapi/asm/unistd.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6dece2d002dc..b14232b6878f 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -38,4 +38,7 @@ #define __ARCH_WANT_SYS_FORK #endif /* __ASSEMBLY__ */ + +#define __NR_syscalls 381 + #endif /* _ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h index 5f7fe7582f3a..20043b67d158 100644 --- a/arch/microblaze/include/uapi/asm/unistd.h +++ b/arch/microblaze/include/uapi/asm/unistd.h @@ -397,6 +397,4 @@ #define __NR_kcmp 379 #define __NR_finit_module 380 -#define __NR_syscalls 381 - #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */ -- GitLab From 4937a269cb063915d50e47c68493679b7fe0ffb7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 7 Feb 2013 17:28:20 +0100 Subject: [PATCH 2552/2900] xilinx systemace: Fix sparse warnings Fix sysace sparse warnings. Signed-off-by: Michal Simek --- drivers/block/xsysace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 3fd130fdfbc1..1393b8871a28 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -407,7 +407,7 @@ static void ace_dump_regs(struct ace_device *ace) ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT)); } -void ace_fix_driveid(u16 *id) +static void ace_fix_driveid(u16 *id) { #if defined(__BIG_ENDIAN) int i; @@ -463,7 +463,7 @@ static inline void ace_fsm_yieldirq(struct ace_device *ace) } /* Get the next read/write request; ending requests that we don't handle */ -struct request *ace_get_next_request(struct request_queue * q) +static struct request *ace_get_next_request(struct request_queue *q) { struct request *req; -- GitLab From c11e5f35ab490bd30591563816fbc83526521777 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Jul 2013 16:00:31 -0700 Subject: [PATCH 2553/2900] Partially revert "drm/i915: unconditionally use mt forcewake on hsw/ivb" This patch partially reverts commit 36ec8f877481449bdfa072e6adf2060869e2b970 for IvyBridge CPUs. The original commit results in repeated 'Timed out waiting for forcewake old ack to clear' messages on a Supermicro C7H61 board (BIOS version 2.00 and 2.00b) with i7-3770K CPU. It ultimately results in a hangup if the system is highly loaded. Reverting the commit for IvyBridge CPUs fixes the issue. Issue a warning if the CPU is IvyBridge and mt forcewake is disabled, since this condition can result in secondary issues. v2: Only revert patch for Ivybridge CPUs Issue info message if mt forcewake is disabled on Ivybridge Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60541 Cc: Jesse Barnes Cc: Daniel Vetter Cc: Mika Kuoppala Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66139 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ccbdd83f5220..d10e6735771f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5500,9 +5500,38 @@ void intel_gt_init(struct drm_device *dev) if (IS_VALLEYVIEW(dev)) { dev_priv->gt.force_wake_get = vlv_force_wake_get; dev_priv->gt.force_wake_put = vlv_force_wake_put; - } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { + } else if (IS_HASWELL(dev)) { dev_priv->gt.force_wake_get = __gen6_gt_force_wake_mt_get; dev_priv->gt.force_wake_put = __gen6_gt_force_wake_mt_put; + } else if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + + /* IVB configs may use multi-threaded forcewake */ + + /* A small trick here - if the bios hasn't configured + * MT forcewake, and if the device is in RC6, then + * force_wake_mt_get will not wake the device and the + * ECOBUS read will return zero. Which will be + * (correctly) interpreted by the test below as MT + * forcewake being disabled. + */ + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ_NOTRACE(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + dev_priv->gt.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->gt.force_wake_put = + __gen6_gt_force_wake_mt_put; + } else { + DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n"); + DRM_INFO("when using vblank-synced partial screen updates.\n"); + dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; + } } else if (IS_GEN6(dev)) { dev_priv->gt.force_wake_get = __gen6_gt_force_wake_get; dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; -- GitLab From cc18ec3c8f5dd735c1bff5da30fd33860c08a293 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 15 Jun 2013 07:55:59 -0400 Subject: [PATCH 2554/2900] Use ecryptfs_dentry_to_lower_path in a couple of places There are two places in ecryptfs that benefit from using ecryptfs_dentry_to_lower_path() instead of separate calls to ecryptfs_dentry_to_lower() and ecryptfs_dentry_to_lower_mnt(). Both sites use fewer instructions and less stack (determined by examining objdump output). Signed-off-by: Matthew Wilcox Signed-off-by: Tyler Hicks --- fs/ecryptfs/file.c | 7 +++---- fs/ecryptfs/main.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index a7abbea2c096..0943f6f20b1c 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -49,7 +49,7 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, unsigned long nr_segs, loff_t pos) { ssize_t rc; - struct path lower; + struct path *path; struct file *file = iocb->ki_filp; rc = generic_file_aio_read(iocb, iov, nr_segs, pos); @@ -60,9 +60,8 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb, if (-EIOCBQUEUED == rc) rc = wait_on_sync_kiocb(iocb); if (rc >= 0) { - lower.dentry = ecryptfs_dentry_to_lower(file->f_path.dentry); - lower.mnt = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry); - touch_atime(&lower); + path = ecryptfs_dentry_to_lower_path(file->f_path.dentry); + touch_atime(path); } return rc; } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index e924cf45aad9..eb1c5979ecaf 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -120,16 +120,15 @@ static int ecryptfs_init_lower_file(struct dentry *dentry, struct file **lower_file) { const struct cred *cred = current_cred(); - struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); + struct path *path = ecryptfs_dentry_to_lower_path(dentry); int rc; - rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt, + rc = ecryptfs_privileged_open(lower_file, path->dentry, path->mnt, cred); if (rc) { printk(KERN_ERR "Error opening lower file " "for lower_dentry [0x%p] and lower_mnt [0x%p]; " - "rc = [%d]\n", lower_dentry, lower_mnt, rc); + "rc = [%d]\n", path->dentry, path->mnt, rc); (*lower_file) = NULL; } return rc; -- GitLab From 02978ff57a5bdfbf703d2bc5a4d933a53ede3144 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 9 Jul 2013 09:22:39 +0100 Subject: [PATCH 2555/2900] drm/i915: Fix write-read race with multiple rings Daniel noticed a problem where is we wrote to an object with ring A in the middle of a very long running batch, then executed a quick batch on ring B before a batch that reads from the same object, its obj->ring would now point to ring B, but its last_write_seqno would be still relative to ring A. This would allow for the user to read from the object before the GPU had completed the write, as set_domain would only check that ring B had passed the last_write_seqno. To fix this simply (and inelegantly), we bump the last_write_seqno when switching rings so that the last_write_seqno is always relative to the current obj->ring. This fixes igt/tests/gem_write_read_ring_switch. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: stable@vger.kernel.org [danvet: Add note about the newly created igt which exercises this bug.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7f368d79f7d2..8fd8e82ebda4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1880,6 +1880,10 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, u32 seqno = intel_ring_get_seqno(ring); BUG_ON(ring == NULL); + if (obj->ring != ring && obj->last_write_seqno) { + /* Keep the seqno relative to the current ring */ + obj->last_write_seqno = seqno; + } obj->ring = ring; /* Add a reference if we're newly entering the active list. */ -- GitLab From e07619539017ac31004a038d1d886e2ed4d0e61a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 10 Jul 2013 09:25:28 +0200 Subject: [PATCH 2556/2900] spi/xilinx: Revert master->setup function removal master->setup() must be initialized to be able to successfully run spi_bitbang_start() and satisfy if/else logic there. "spi: convert drivers to use bits_per_word_mask" (sha1: 24778be20f87d5aadb19624fc768b3159fa43efc) Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index fb56fcfdf65e..09a942852593 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -233,6 +233,21 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, return 0; } +static int xilinx_spi_setup(struct spi_device *spi) +{ + /* always return 0, we can not check the number of bits. + * There are cases when SPI setup is called before any driver is + * there, in that case the SPI core defaults to 8 bits, which we + * do not support in some cases. But if we return an error, the + * SPI device would not be registered and no driver can get hold of it + * When the driver is there, it will call SPI setup again with the + * correct number of bits per transfer. + * If a driver setups with the wrong bit number, it will fail when + * it tries to do a transfer + */ + return 0; +} + static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi) { u8 sr; @@ -360,6 +375,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; + xspi->bitbang.master->setup = xilinx_spi_setup; init_completion(&xspi->done); if (!request_mem_region(mem->start, resource_size(mem), -- GitLab From d18b9619034230b6f945e215276425636ca401fe Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 10 Jul 2013 13:36:23 +0100 Subject: [PATCH 2557/2900] drm/i915: Fix incoherence with fence updates on Sandybridge+ This hopefully fixes the root cause behind the workaround added in commit 25ff1195f8a0b3724541ae7bbe331b4296de9c06 Author: Chris Wilson Date: Thu Apr 4 21:31:03 2013 +0100 drm/i915: Workaround incoherence between fences and LLC across multiple CPUs Thanks to further investigation by Jon Bloomfield, he realised that the 64-bit register might be broken up by the hardware into two 32-bit writes (a problem we have encountered elsewhere). This non-atomicity would then cause an issue where a second thread would see an intermediate register state (new high dword, old low dword), and this register would randomly be used in preference to its own thread register. This would cause the second thread to read from and write into a fairly random tiled location. Breaking the operation into 3 explicit 32-bit updates (first disable the fence, poke the upper bits, then poke the lower bits and enable) ensures that, given proper serialisation between the 32-bit register write and the memory transfer, that the fence value is always consistent. Armed with this knowledge, we can explain how the previous workaround work. The key to the corruption is that a second thread sees an erroneous fence register that conflicts and overrides its own. By serialising the fence update across all CPUs, we have a small window where no GTT access is occurring and so hide the potential corruption. This also leads to the conclusion that the earlier workaround was incomplete. v2: Be overly paranoid about the order in which fence updates become visible to the GPU to make really sure that we turn the fence off before doing the update, and then only switch the fence on afterwards. Signed-off-by: Jon Bloomfield Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Carsten Emde Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8fd8e82ebda4..a34e8e2ba98a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2668,7 +2668,6 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, drm_i915_private_t *dev_priv = dev->dev_private; int fence_reg; int fence_pitch_shift; - uint64_t val; if (INTEL_INFO(dev)->gen >= 6) { fence_reg = FENCE_REG_SANDYBRIDGE_0; @@ -2678,8 +2677,23 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, fence_pitch_shift = I965_FENCE_PITCH_SHIFT; } + fence_reg += reg * 8; + + /* To w/a incoherency with non-atomic 64-bit register updates, + * we split the 64-bit update into two 32-bit writes. In order + * for a partial fence not to be evaluated between writes, we + * precede the update with write to turn off the fence register, + * and only enable the fence as the last step. + * + * For extra levels of paranoia, we make sure each step lands + * before applying the next step. + */ + I915_WRITE(fence_reg, 0); + POSTING_READ(fence_reg); + if (obj) { u32 size = obj->gtt_space->size; + uint64_t val; val = (uint64_t)((obj->gtt_offset + size - 4096) & 0xfffff000) << 32; @@ -2688,12 +2702,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, if (obj->tiling_mode == I915_TILING_Y) val |= 1 << I965_FENCE_TILING_Y_SHIFT; val |= I965_FENCE_REG_VALID; - } else - val = 0; - fence_reg += reg * 8; - I915_WRITE64(fence_reg, val); - POSTING_READ(fence_reg); + I915_WRITE(fence_reg + 4, val >> 32); + POSTING_READ(fence_reg + 4); + + I915_WRITE(fence_reg + 0, val); + POSTING_READ(fence_reg); + } else { + I915_WRITE(fence_reg + 4, 0); + POSTING_READ(fence_reg + 4); + } } static void i915_write_fence_reg(struct drm_device *dev, int reg, -- GitLab From 46a0b638f35b45fc13d3dc0deb6a7e17988170b2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 10 Jul 2013 13:36:24 +0100 Subject: [PATCH 2558/2900] Revert "drm/i915: Workaround incoherence between fences and LLC across multiple CPUs" This reverts commit 25ff119 and the follow on for Valleyview commit 2dc8aae. commit 25ff1195f8a0b3724541ae7bbe331b4296de9c06 Author: Chris Wilson Date: Thu Apr 4 21:31:03 2013 +0100 drm/i915: Workaround incoherence between fences and LLC across multiple CPUs commit 2dc8aae06d53458dd3624dc0accd4f81100ee631 Author: Chris Wilson Date: Wed May 22 17:08:06 2013 +0100 drm/i915: Workaround incoherence with fence updates on Valleyview Jon Bloomfield came up with a plausible explanation and cheap fix (drm/i915: Fix incoherence with fence updates on Sandybridge+) for the race condition, so lets run with it. This is a candidate for stable as the old workaround incurs a significant cost (calling wbinvd on all CPUs before performing the register write) for some workloads as noted by Carsten Emde. Link: http://lists.freedesktop.org/archives/intel-gfx/2013-June/028819.html References: https://www.osadl.org/?id=1543#c7602 References: https://bugs.freedesktop.org/show_bug.cgi?id=63825 Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Jon Bloomfield Cc: Carsten Emde Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 47 +++------------------------------ 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a34e8e2ba98a..06d66e09da17 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2829,56 +2829,17 @@ static inline int fence_number(struct drm_i915_private *dev_priv, return fence - dev_priv->fence_regs; } -struct write_fence { - struct drm_device *dev; - struct drm_i915_gem_object *obj; - int fence; -}; - -static void i915_gem_write_fence__ipi(void *data) -{ - struct write_fence *args = data; - - /* Required for SNB+ with LLC */ - wbinvd(); - - /* Required for VLV */ - i915_gem_write_fence(args->dev, args->fence, args->obj); -} - static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, struct drm_i915_fence_reg *fence, bool enable) { struct drm_i915_private *dev_priv = obj->base.dev->dev_private; - struct write_fence args = { - .dev = obj->base.dev, - .fence = fence_number(dev_priv, fence), - .obj = enable ? obj : NULL, - }; - - /* In order to fully serialize access to the fenced region and - * the update to the fence register we need to take extreme - * measures on SNB+. In theory, the write to the fence register - * flushes all memory transactions before, and coupled with the - * mb() placed around the register write we serialise all memory - * operations with respect to the changes in the tiler. Yet, on - * SNB+ we need to take a step further and emit an explicit wbinvd() - * on each processor in order to manually flush all memory - * transactions before updating the fence register. - * - * However, Valleyview complicates matter. There the wbinvd is - * insufficient and unlike SNB/IVB requires the serialising - * register write. (Note that that register write by itself is - * conversely not sufficient for SNB+.) To compromise, we do both. - */ - if (INTEL_INFO(args.dev)->gen >= 6) - on_each_cpu(i915_gem_write_fence__ipi, &args, 1); - else - i915_gem_write_fence(args.dev, args.fence, args.obj); + int reg = fence_number(dev_priv, fence); + + i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL); if (enable) { - obj->fence_reg = args.fence; + obj->fence_reg = reg; fence->obj = obj; list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); } else { -- GitLab From 42c49d7f249c2487f36d3314753d5d8ebcee8249 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Fri, 21 Jun 2013 14:45:53 -0300 Subject: [PATCH 2559/2900] xfs: fix sgid inheritance for subdirectories inheriting default acls [V3] XFS removes sgid bits of subdirectories under a directory containing a default acl. When a default acl is set, it implies xfs to call xfs_setattr_nonsize() in its code path. Such function is shared among mkdir and chmod system calls, and does some checks unneeded by mkdir (calling inode_change_ok()). Such checks remove sgid bit from the inode after it has been granted. With this patch, we extend the meaning of XFS_ATTR_NOACL flag to avoid these checks when acls are being inherited (thanks hch). Also, xfs_setattr_mode, doesn't need to re-check for group id and capabilities permissions, this only implies in another try to remove sgid bit from the directories. Such check is already done either on inode_change_ok() or xfs_setattr_nonsize(). Changelog: V2: Extends the meaning of XFS_ATTR_NOACL instead of wrap the tests into another function V3: Remove S_ISDIR check in xfs_setattr_nonsize() from the patch Signed-off-by: Carlos Maiolino Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_iops.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c69bbc493cb0..8865261e5417 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -467,9 +467,6 @@ xfs_setattr_mode( ASSERT(tp); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - mode &= ~S_ISGID; - ip->i_d.di_mode &= S_IFMT; ip->i_d.di_mode |= mode & ~S_IFMT; @@ -495,15 +492,18 @@ xfs_setattr_nonsize( trace_xfs_setattr(ip); - if (mp->m_flags & XFS_MOUNT_RDONLY) - return XFS_ERROR(EROFS); + /* If acls are being inherited, we already have this checked */ + if (!(flags & XFS_ATTR_NOACL)) { + if (mp->m_flags & XFS_MOUNT_RDONLY) + return XFS_ERROR(EROFS); - if (XFS_FORCED_SHUTDOWN(mp)) - return XFS_ERROR(EIO); + if (XFS_FORCED_SHUTDOWN(mp)) + return XFS_ERROR(EIO); - error = -inode_change_ok(inode, iattr); - if (error) - return XFS_ERROR(error); + error = -inode_change_ok(inode, iattr); + if (error) + return XFS_ERROR(error); + } ASSERT((mask & ATTR_SIZE) == 0); -- GitLab From 42d4ab832d843b5a512b373c86e70caa43a041c8 Mon Sep 17 00:00:00 2001 From: Eldad Zack Date: Tue, 9 Jul 2013 20:36:15 +0200 Subject: [PATCH 2560/2900] ALSA: usb-audio: fix regression for fixed stream quirk Commit 8f898e92aea2c24c7f379ee265d178f69ebb9c07 removed the redundant reads of bInterfaceProtocol from the descriptors, but introduced a regression to devices with quirks of type QUIRK_AUDIO_FIXED_ENDPOINT, since fp->protocol is not set in setup process. As a consequence, audio streams would not get initialized, as the following logs show: [ 48.923043] setting usb interface 3:1 [ 48.923056] Creating new capture data endpoint #81 [ 48.923484] 4:3:1: cannot set freq 48000 to ep 0x81 This patch sets fp->protocol in create_fixed_stream_quirk() and resolves the regression. Signed-off-by: Eldad Zack Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 5b01330b8452..1bc45e71f1fe 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -129,6 +129,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, { struct audioformat *fp; struct usb_host_interface *alts; + struct usb_interface_descriptor *altsd; int stream, err; unsigned *rate_table = NULL; @@ -166,6 +167,9 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, return -EINVAL; } alts = &iface->altsetting[fp->altset_idx]; + altsd = get_iface_desc(alts); + fp->protocol = altsd->bInterfaceProtocol; + if (fp->datainterval == 0) fp->datainterval = snd_usb_parse_datainterval(chip, alts); if (fp->maxpacksize == 0) -- GitLab From d14c496588733ec1b586ec068932c1db228dd770 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 9 May 2013 00:17:44 -0400 Subject: [PATCH 2561/2900] perf tools: Fix -ldw/-lelf link test when static linking Since libelf sometimes uses libpthread, we have to list that after -lelf when someone tries to build statically. Else things go boom: Makefile:479: *** No libelf.h/libelf found, please install \ libelf-dev/elfutils-libelf-devel. Stop. Similarly, the -ldw test fails as it often uses -lz: Makefile:462: No libdw.h found or old libdw.h found or elfutils is older \ than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev And if we add debugging to try-cc, we see: + echo '#include int main(void) { Dwarf *dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }' + i686-pc-linux-gnu-gcc -x c - -O2 -pipe -march=atom -mtune=atom -mfpmath=sse -g \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE \ -ldw -lelf -static -lpthread -lrt -lelf -lm -o .24368 /usr/lib/libdw.a(dwarf_begin_elf.o):function check_section.isra.1: error: undefined reference to 'inflateInit_' /usr/lib/libdw.a(dwarf_begin_elf.o):function check_section.isra.1: error: undefined reference to 'inflate' /usr/lib/libdw.a(dwarf_begin_elf.o):function check_section.isra.1: error: undefined reference to 'inflateReset' /usr/lib/libdw.a(dwarf_begin_elf.o):function check_section.isra.1: error: undefined reference to 'inflateEnd' + echo '#include int main(void) { Elf *elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }' + i686-pc-linux-gnu-gcc -x c - -O2 -pipe -march=atom -mtune=atom -mfpmath=sse -g \ -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE \ -static -lpthread -lrt -lelf -lm -o .19216 /usr/lib/libelf.a(elf_begin.o):function file_read_elf: error: undefined reference to 'pthread_rwlock_init' /usr/lib/libelf.a(elf_begin.o):function __libelf_read_mmaped_file: error: undefined reference to 'pthread_rwlock_init' /usr/lib/libelf.a(elf_begin.o):function __libelf_read_mmaped_file: error: undefined reference to 'pthread_rwlock_init' /usr/lib/libelf.a(elf_begin.o):function read_file: error: undefined reference to 'pthread_rwlock_init' /usr/lib/libelf.a(elf_begin.o):function lock_dup_elf.8072: error: undefined reference to 'pthread_rwlock_unlock' /usr/lib/libelf.a(elf_begin.o):function lock_dup_elf.8072: error: undefined reference to 'pthread_rwlock_wrlock' /usr/lib/libelf.a(elf_begin.o):function elf_begin: error: undefined reference to 'pthread_rwlock_rdlock' /usr/lib/libelf.a(elf_begin.o):function elf_begin: error: undefined reference to 'pthread_rwlock_unlock' Signed-off-by: Mike Frysinger Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1368073064-18276-1-git-send-email-vapier@gentoo.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/lk/Makefile | 2 +- tools/perf/config/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/lib/lk/Makefile b/tools/lib/lk/Makefile index f0ecc0a13300..280dd8205430 100644 --- a/tools/lib/lk/Makefile +++ b/tools/lib/lk/Makefile @@ -29,7 +29,7 @@ LIB_OBJS += $(OUTPUT)debugfs.o LIBFILE = liblk.a CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC -EXTLIBS = -lpthread -lrt -lelf -lm +EXTLIBS = -lelf -lpthread -lrt -lm ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ALL_LDFLAGS = $(LDFLAGS) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index f4468954d3dc..b5d9238cb181 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -85,7 +85,7 @@ CFLAGS += -Wall CFLAGS += -Wextra CFLAGS += -std=gnu99 -EXTLIBS = -lpthread -lrt -lelf -lm +EXTLIBS = -lelf -lpthread -lrt -lm ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) CFLAGS += -fstack-protector-all @@ -165,7 +165,7 @@ else LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib endif - FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) + FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); NO_DWARF := 1 -- GitLab From 750ade7e82709c2835cb221a7b6a9ef0a6a9c0ac Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Tue, 9 Jul 2013 15:30:30 +0530 Subject: [PATCH 2562/2900] perf script: Fix broken include in Context.xs 765532c8 (perf script: Finish the rename from trace to script, 2010-12-23) made a mistake during find-and-replace replacing "../../../util/trace-event.h" with "../../../util/script-event.h", a non-existent file. Fix this include. Signed-off-by: Ramkumar Ramachandra Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1373364033-7918-3-git-send-email-artagnon@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/perl/Perf-Trace-Util/Context.xs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs index c1e2ed1ed34e..8c7ea42444d1 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs +++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs @@ -23,7 +23,7 @@ #include "perl.h" #include "XSUB.h" #include "../../../perf.h" -#include "../../../util/script-event.h" +#include "../../../util/trace-event.h" MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context PROTOTYPES: ENABLE -- GitLab From fd55439638a27e34d87b91d618c0ba6b42302940 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Tue, 9 Jul 2013 19:44:56 +0400 Subject: [PATCH 2563/2900] CIFS: Fix lease context buffer parsing to prevent missing RqLs context if it's not the first one. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2pdu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2b312e4eeaa6..19fafeb767fa 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -853,23 +853,24 @@ parse_lease_state(struct smb2_create_rsp *rsp) char *data_offset; struct create_lease *lc; bool found = false; + unsigned int next = 0; + char *name; - data_offset = (char *)rsp; - data_offset += 4 + le32_to_cpu(rsp->CreateContextsOffset); + data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); lc = (struct create_lease *)data_offset; do { - char *name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc; + lc = (struct create_lease *)((char *)lc + next); + name = le16_to_cpu(lc->ccontext.NameOffset) + (char *)lc; if (le16_to_cpu(lc->ccontext.NameLength) != 4 || strncmp(name, "RqLs", 4)) { - lc = (struct create_lease *)((char *)lc - + le32_to_cpu(lc->ccontext.Next)); + next = le32_to_cpu(lc->ccontext.Next); continue; } if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) return SMB2_OPLOCK_LEVEL_NOCHANGE; found = true; break; - } while (le32_to_cpu(lc->ccontext.Next) != 0); + } while (next != 0); if (!found) return 0; -- GitLab From ca81983fe5e095ee90c0f7b6013e7c446af17088 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 5 Jul 2013 12:21:26 +0400 Subject: [PATCH 2564/2900] CIFS: Respect create_options in smb2_open_file and eliminated unused file_attribute parms of SMB2_open. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2file.c | 2 +- fs/cifs/smb2inode.c | 25 ++++++++++++------------- fs/cifs/smb2ops.c | 6 +++--- fs/cifs/smb2pdu.c | 10 +++++++--- fs/cifs/smb2proto.h | 4 ++-- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 5da1b55a2258..46a4299b7ae8 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -88,7 +88,7 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid, &fid->volatile_fid, desired_access, disposition, - 0, 0, smb2_oplock, smb2_data); + create_options, smb2_oplock, smb2_data); if (rc) goto out; diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index fff6dfba6204..f50eefd9e005 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -41,8 +41,7 @@ static int smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, __u32 desired_access, __u32 create_disposition, - __u32 file_attributes, __u32 create_options, - void *data, int command) + __u32 create_options, void *data, int command) { int rc, tmprc = 0; u64 persistent_fid, volatile_fid; @@ -54,8 +53,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, return -ENOMEM; rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - desired_access, create_disposition, file_attributes, - create_options, &oplock, NULL); + desired_access, create_disposition, create_options, + &oplock, NULL); if (rc) { kfree(utf16_path); return rc; @@ -129,8 +128,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, return -ENOMEM; rc = smb2_open_op_close(xid, tcon, cifs_sb, full_path, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, - smb2_data, SMB2_OP_QUERY_INFO); + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, smb2_data, + SMB2_OP_QUERY_INFO); if (rc) goto out; @@ -145,7 +144,7 @@ smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb) { return smb2_open_op_close(xid, tcon, cifs_sb, name, - FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR); } @@ -164,7 +163,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; data.Attributes = cpu_to_le32(dosattrs); tmprc = smb2_open_op_close(xid, tcon, cifs_sb, name, - FILE_WRITE_ATTRIBUTES, FILE_CREATE, 0, + FILE_WRITE_ATTRIBUTES, FILE_CREATE, CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO); if (tmprc == 0) cifs_i->cifsAttrs = dosattrs; @@ -175,7 +174,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb) { return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, - 0, CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, + CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE, NULL, SMB2_OP_DELETE); } @@ -184,7 +183,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb) { return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN, - 0, CREATE_DELETE_ON_CLOSE, NULL, + CREATE_DELETE_ON_CLOSE, NULL, SMB2_OP_DELETE); } @@ -203,7 +202,7 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon, } rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access, - FILE_OPEN, 0, 0, smb2_to_name, command); + FILE_OPEN, 0, smb2_to_name, command); smb2_rename_path: kfree(smb2_to_name); return rc; @@ -234,7 +233,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, { __le64 eof = cpu_to_le64(size); return smb2_open_op_close(xid, tcon, cifs_sb, full_path, - FILE_WRITE_DATA, FILE_OPEN, 0, 0, &eof, + FILE_WRITE_DATA, FILE_OPEN, 0, &eof, SMB2_OP_SET_EOF); } @@ -250,7 +249,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path, if (IS_ERR(tlink)) return PTR_ERR(tlink); rc = smb2_open_op_close(xid, tlink_tcon(tlink), cifs_sb, full_path, - FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, 0, buf, + FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf, SMB2_OP_SET_INFO); cifs_put_tlink(tlink); return rc; diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 6d15cab95b99..92bdc7ec5c99 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -222,7 +222,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, return -ENOMEM; rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, &oplock, NULL); if (rc) { kfree(utf16_path); return rc; @@ -450,7 +450,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, return -ENOMEM; rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, 0, + FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, &oplock, NULL); kfree(utf16_path); if (rc) { @@ -533,7 +533,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, u8 oplock = SMB2_OPLOCK_LEVEL_NONE; rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, 0, &oplock, NULL); + FILE_READ_ATTRIBUTES, FILE_OPEN, 0, &oplock, NULL); if (rc) return rc; buf->f_type = SMB2_MAGIC_NUMBER; diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 19fafeb767fa..4c046a5b81af 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -881,8 +881,8 @@ parse_lease_state(struct smb2_create_rsp *rsp) int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, - __u32 create_disposition, __u32 file_attributes, __u32 create_options, - __u8 *oplock, struct smb2_file_all_info *buf) + __u32 create_disposition, __u32 create_options, __u8 *oplock, + struct smb2_file_all_info *buf) { struct smb2_create_req *req; struct smb2_create_rsp *rsp; @@ -895,6 +895,7 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, int copy_size; int rc = 0; int num_iovecs = 2; + __u32 file_attributes = 0; cifs_dbg(FYI, "create/open\n"); @@ -907,13 +908,16 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, if (rc) return rc; + if (create_options & CREATE_OPTION_READONLY) + file_attributes |= ATTR_READONLY; + req->ImpersonationLevel = IL_IMPERSONATION; req->DesiredAccess = cpu_to_le32(desired_access); /* File attributes ignored on open (used in create though) */ req->FileAttributes = cpu_to_le32(file_attributes); req->ShareAccess = FILE_SHARE_ALL_LE; req->CreateDisposition = cpu_to_le32(create_disposition); - req->CreateOptions = cpu_to_le32(create_options); + req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 8 /* pad */ - 4 /* do not count rfc1001 len field */); diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index d4e1eb807457..d71a3e2a772d 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -109,8 +109,8 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, __u32 create_disposition, - __u32 file_attributes, __u32 create_options, - __u8 *oplock, struct smb2_file_all_info *buf); + __u32 create_options, __u8 *oplock, + struct smb2_file_all_info *buf); extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, bool is_fsctl, char *in_data, u32 indatalen, -- GitLab From 59aa371841ddb3a1a434497c6590542a785fa37c Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 4 Jul 2013 19:41:24 +0400 Subject: [PATCH 2565/2900] CIFS: Simplify SMB2_open code path by passing a filename to a separate iovec regardless of its length. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2pdu.c | 59 +++++++++++++++++++---------------------------- fs/cifs/smb2pdu.h | 2 +- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 4c046a5b81af..9a35dcda9099 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -894,7 +894,7 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, __le16 *copy_path = NULL; int copy_size; int rc = 0; - int num_iovecs = 2; + unsigned int num_iovecs = 2; __u32 file_attributes = 0; cifs_dbg(FYI, "create/open\n"); @@ -919,47 +919,36 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, req->CreateDisposition = cpu_to_le32(create_disposition); req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; - req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - - 8 /* pad */ - 4 /* do not count rfc1001 len field */); + /* do not count rfc1001 len field */ + req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4); iov[0].iov_base = (char *)req; /* 4 for rfc1002 length field */ iov[0].iov_len = get_rfc1002_length(req) + 4; /* MUST set path len (NameLength) to 0 opening root of share */ - if (uni_path_len >= 4) { - req->NameLength = cpu_to_le16(uni_path_len - 2); - /* -1 since last byte is buf[0] which is sent below (path) */ - iov[0].iov_len--; - if (uni_path_len % 8 != 0) { - copy_size = uni_path_len / 8 * 8; - if (copy_size < uni_path_len) - copy_size += 8; - - copy_path = kzalloc(copy_size, GFP_KERNEL); - if (!copy_path) - return -ENOMEM; - memcpy((char *)copy_path, (const char *)path, - uni_path_len); - uni_path_len = copy_size; - path = copy_path; - } - - iov[1].iov_len = uni_path_len; - iov[1].iov_base = path; - /* - * -1 since last byte is buf[0] which was counted in - * smb2_buf_len. - */ - inc_rfc1001_len(req, uni_path_len - 1); - } else { - iov[0].iov_len += 7; - req->hdr.smb2_buf_length = cpu_to_be32(be32_to_cpu( - req->hdr.smb2_buf_length) + 8 - 1); - num_iovecs = 1; - req->NameLength = 0; + req->NameLength = cpu_to_le16(uni_path_len - 2); + /* -1 since last byte is buf[0] which is sent below (path) */ + iov[0].iov_len--; + if (uni_path_len % 8 != 0) { + copy_size = uni_path_len / 8 * 8; + if (copy_size < uni_path_len) + copy_size += 8; + + copy_path = kzalloc(copy_size, GFP_KERNEL); + if (!copy_path) + return -ENOMEM; + memcpy((char *)copy_path, (const char *)path, + uni_path_len); + uni_path_len = copy_size; + path = copy_path; } + iov[1].iov_len = uni_path_len; + iov[1].iov_base = path; + /* -1 since last byte is buf[0] which was counted in smb2_buf_len */ + inc_rfc1001_len(req, uni_path_len - 1); + if (!server->oplocks) *oplock = SMB2_OPLOCK_LEVEL_NONE; @@ -976,7 +965,7 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, iov[num_iovecs].iov_len = sizeof(struct create_lease); req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; req->CreateContextsOffset = cpu_to_le32( - sizeof(struct smb2_create_req) - 4 - 8 + + sizeof(struct smb2_create_req) - 4 + iov[num_iovecs-1].iov_len); req->CreateContextsLength = cpu_to_le32( sizeof(struct create_lease)); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index f31043b26bd3..8b1025f6f0da 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -428,7 +428,7 @@ struct smb2_create_req { __le16 NameLength; __le32 CreateContextsOffset; __le32 CreateContextsLength; - __u8 Buffer[8]; + __u8 Buffer[0]; } __packed; struct smb2_create_rsp { -- GitLab From d22cbfecbd9047465d9067a6eedc43434c888593 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 4 Jul 2013 19:10:00 +0400 Subject: [PATCH 2566/2900] CIFS: Simplify SMB2 create context handling to make it easier to add other create context further. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2pdu.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 9a35dcda9099..e65ccdb528cf 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -878,6 +878,29 @@ parse_lease_state(struct smb2_create_rsp *rsp) return smb2_map_lease_to_oplock(lc->lcontext.LeaseState); } +static int +add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock) +{ + struct smb2_create_req *req = iov[0].iov_base; + unsigned int num = *num_iovec; + + iov[num].iov_base = create_lease_buf(oplock+1, *oplock); + if (iov[num].iov_base == NULL) + return -ENOMEM; + iov[num].iov_len = sizeof(struct create_lease); + req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; + if (!req->CreateContextsOffset) + req->CreateContextsOffset = cpu_to_le32( + sizeof(struct smb2_create_req) - 4 + + iov[num - 1].iov_len); + req->CreateContextsLength = cpu_to_le32( + le32_to_cpu(req->CreateContextsLength) + + sizeof(struct create_lease)); + inc_rfc1001_len(&req->hdr, sizeof(struct create_lease)); + *num_iovec = num + 1; + return 0; +} + int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, @@ -956,21 +979,12 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, *oplock == SMB2_OPLOCK_LEVEL_NONE) req->RequestedOplockLevel = *oplock; else { - iov[num_iovecs].iov_base = create_lease_buf(oplock+1, *oplock); - if (iov[num_iovecs].iov_base == NULL) { + rc = add_lease_context(iov, &num_iovecs, oplock); + if (rc) { cifs_small_buf_release(req); kfree(copy_path); - return -ENOMEM; + return rc; } - iov[num_iovecs].iov_len = sizeof(struct create_lease); - req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_LEASE; - req->CreateContextsOffset = cpu_to_le32( - sizeof(struct smb2_create_req) - 4 + - iov[num_iovecs-1].iov_len); - req->CreateContextsLength = cpu_to_le32( - sizeof(struct create_lease)); - inc_rfc1001_len(&req->hdr, sizeof(struct create_lease)); - num_iovecs++; } rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); -- GitLab From 63eb3def3267a5744863801e8221898b0ba9d41d Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 4 Jul 2013 18:41:09 +0400 Subject: [PATCH 2567/2900] CIFS: Request durable open for SMB2 opens by passing durable context together with a handle caching lease or batch oplock. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2file.c | 2 +- fs/cifs/smb2pdu.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- fs/cifs/smb2pdu.h | 6 +++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 46a4299b7ae8..150a9b1bc7fa 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -81,7 +81,7 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, } desired_access |= FILE_READ_ATTRIBUTES; - *smb2_oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE; + *smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index e65ccdb528cf..140a613073fb 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -847,6 +847,28 @@ create_lease_buf(u8 *lease_key, u8 oplock) return buf; } +static struct create_durable * +create_durable_buf(void) +{ + struct create_durable *buf; + + buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); + if (!buf) + return NULL; + + buf->ccontext.DataOffset = cpu_to_le16(offsetof + (struct create_durable, Reserved)); + buf->ccontext.DataLength = cpu_to_le32(16); + buf->ccontext.NameOffset = cpu_to_le16(offsetof + (struct create_durable, Name)); + buf->ccontext.NameLength = cpu_to_le16(4); + buf->Name[0] = 'D'; + buf->Name[1] = 'H'; + buf->Name[2] = 'n'; + buf->Name[3] = 'Q'; + return buf; +} + static __u8 parse_lease_state(struct smb2_create_rsp *rsp) { @@ -901,6 +923,28 @@ add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock) return 0; } +static int +add_durable_context(struct kvec *iov, unsigned int *num_iovec) +{ + struct smb2_create_req *req = iov[0].iov_base; + unsigned int num = *num_iovec; + + iov[num].iov_base = create_durable_buf(); + if (iov[num].iov_base == NULL) + return -ENOMEM; + iov[num].iov_len = sizeof(struct create_durable); + if (!req->CreateContextsOffset) + req->CreateContextsOffset = + cpu_to_le32(sizeof(struct smb2_create_req) - 4 + + iov[1].iov_len); + req->CreateContextsLength = + cpu_to_le32(le32_to_cpu(req->CreateContextsLength) + + sizeof(struct create_durable)); + inc_rfc1001_len(&req->hdr, sizeof(struct create_durable)); + *num_iovec = num + 1; + return 0; +} + int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, @@ -911,7 +955,7 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, struct smb2_create_rsp *rsp; struct TCP_Server_Info *server; struct cifs_ses *ses = tcon->ses; - struct kvec iov[3]; + struct kvec iov[4]; int resp_buftype; int uni_path_len; __le16 *copy_path = NULL; @@ -987,6 +1031,22 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, } } + if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) { + /* need to set Next field of lease context if we request it */ + if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) { + struct create_context *ccontext = + (struct create_context *)iov[num_iovecs-1].iov_base; + ccontext->Next = sizeof(struct create_lease); + } + rc = add_durable_context(iov, &num_iovecs); + if (rc) { + cifs_small_buf_release(req); + kfree(copy_path); + kfree(iov[num_iovecs-1].iov_base); + return rc; + } + } + rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); rsp = (struct smb2_create_rsp *)iov[0].iov_base; diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 8b1025f6f0da..3e30f0ad5749 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -485,6 +485,12 @@ struct create_lease { struct lease_context lcontext; } __packed; +struct create_durable { + struct create_context ccontext; + __u8 Name[8]; + __u8 Reserved[16]; +} __packed; + /* this goes in the ioctl buffer when doing a copychunk request */ struct copychunk_ioctl { char SourceKey[24]; -- GitLab From 226730b4d8adae393dc07092655cdd29d2a2ff07 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Fri, 5 Jul 2013 12:00:30 +0400 Subject: [PATCH 2568/2900] CIFS: Introduce cifs_open_parms struct and pass it to the open() call. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/cifsglob.h | 16 +++++++++++++--- fs/cifs/dir.c | 13 ++++++++++--- fs/cifs/file.c | 26 ++++++++++++++++++++------ fs/cifs/smb1ops.c | 29 ++++++++++++++++------------- fs/cifs/smb2file.c | 22 +++++++++++----------- fs/cifs/smb2proto.h | 8 +++----- 6 files changed, 73 insertions(+), 41 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index e66b08882548..982fdf92c791 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -194,6 +194,7 @@ struct cifs_writedata; struct cifs_io_parms; struct cifs_search_info; struct cifsInodeInfo; +struct cifs_open_parms; struct smb_version_operations { int (*send_cancel)(struct TCP_Server_Info *, void *, @@ -307,9 +308,8 @@ struct smb_version_operations { const char *, const char *, struct cifs_sb_info *); /* open a file for non-posix mounts */ - int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, - int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, - struct cifs_sb_info *); + int (*open)(const unsigned int, struct cifs_open_parms *, + __u32 *, FILE_ALL_INFO *); /* set fid protocol-specific info */ void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32); /* close a file */ @@ -912,6 +912,16 @@ struct cifs_search_info { bool smallBuf:1; /* so we know which buf_release function to call */ }; +struct cifs_open_parms { + struct cifs_tcon *tcon; + struct cifs_sb_info *cifs_sb; + int disposition; + int desired_access; + int create_options; + const char *path; + struct cifs_fid *fid; +}; + struct cifs_fid { __u16 netfid; #ifdef CONFIG_CIFS_SMB2 diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 5175aebf6737..c27c242ac5ba 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -204,6 +204,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, struct inode *newinode = NULL; int disposition; struct TCP_Server_Info *server = tcon->ses->server; + struct cifs_open_parms oparms; *oplock = 0; if (tcon->ses->server->oplocks) @@ -319,9 +320,15 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = server->ops->open(xid, tcon, full_path, disposition, - desired_access, create_options, fid, oplock, - buf, cifs_sb); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; + oparms.create_options = create_options; + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = fid; + + rc = server->ops->open(xid, &oparms, oplock, buf); if (rc) { cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc); goto out; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 91d8629e69a2..f36f9a7893da 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -183,6 +183,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, int create_options = CREATE_NOT_DIR; FILE_ALL_INFO *buf; struct TCP_Server_Info *server = tcon->ses->server; + struct cifs_open_parms oparms; if (!server->ops->open) return -ENOSYS; @@ -224,9 +225,15 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, if (backup_cred(cifs_sb)) create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = server->ops->open(xid, tcon, full_path, disposition, - desired_access, create_options, fid, oplock, buf, - cifs_sb); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; + oparms.create_options = create_options; + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = fid; + + rc = server->ops->open(xid, &oparms, oplock, buf); if (rc) goto out; @@ -588,6 +595,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) int disposition = FILE_OPEN; int create_options = CREATE_NOT_DIR; struct cifs_fid fid; + struct cifs_open_parms oparms; xid = get_xid(); mutex_lock(&cfile->fh_mutex); @@ -656,6 +664,14 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) if (server->ops->get_lease_key) server->ops->get_lease_key(inode, &fid); + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; + oparms.create_options = create_options; + oparms.disposition = disposition; + oparms.path = full_path; + oparms.fid = &fid; + /* * Can not refresh inode by passing in file_info buf to be returned by * CIFSSMBOpen and then calling get_inode_info with returned buf since @@ -663,9 +679,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) * version of file size can be stale. If we knew for sure that inode was * not dirty locally we could do this. */ - rc = server->ops->open(xid, tcon, full_path, disposition, - desired_access, create_options, &fid, &oplock, - NULL, cifs_sb); + rc = server->ops->open(xid, &oparms, &oplock, NULL); if (rc) { mutex_unlock(&cfile->fh_mutex); cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index e813f04511d8..6457690731a2 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -674,20 +674,23 @@ cifs_mkdir_setinfo(struct inode *inode, const char *full_path, } static int -cifs_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, - int disposition, int desired_access, int create_options, - struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf, - struct cifs_sb_info *cifs_sb) -{ - if (!(tcon->ses->capabilities & CAP_NT_SMBS)) - return SMBLegacyOpen(xid, tcon, path, disposition, - desired_access, create_options, - &fid->netfid, oplock, buf, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags +cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + __u32 *oplock, FILE_ALL_INFO *buf) +{ + if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS)) + return SMBLegacyOpen(xid, oparms->tcon, oparms->path, + oparms->disposition, + oparms->desired_access, + oparms->create_options, + &oparms->fid->netfid, oplock, buf, + oparms->cifs_sb->local_nls, + oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - return CIFSSMBOpen(xid, tcon, path, disposition, desired_access, - create_options, &fid->netfid, oplock, buf, - cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + return CIFSSMBOpen(xid, oparms->tcon, oparms->path, + oparms->disposition, oparms->desired_access, + oparms->create_options, &oparms->fid->netfid, oplock, + buf, oparms->cifs_sb->local_nls, + oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 150a9b1bc7fa..5bab192f64e8 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -57,17 +57,16 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) } int -smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, - int disposition, int desired_access, int create_options, - struct cifs_fid *fid, __u32 *oplock, FILE_ALL_INFO *buf, - struct cifs_sb_info *cifs_sb) +smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, + __u32 *oplock, FILE_ALL_INFO *buf) { int rc; __le16 *smb2_path; struct smb2_file_all_info *smb2_data = NULL; __u8 smb2_oplock[17]; + struct cifs_fid *fid = oparms->fid; - smb2_path = cifs_convert_path_to_utf16(path, cifs_sb); + smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb); if (smb2_path == NULL) { rc = -ENOMEM; goto out; @@ -80,21 +79,22 @@ smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, const char *path, goto out; } - desired_access |= FILE_READ_ATTRIBUTES; + oparms->desired_access |= FILE_READ_ATTRIBUTES; *smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH; - if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) + if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE); - rc = SMB2_open(xid, tcon, smb2_path, &fid->persistent_fid, - &fid->volatile_fid, desired_access, disposition, - create_options, smb2_oplock, smb2_data); + rc = SMB2_open(xid, oparms->tcon, smb2_path, &fid->persistent_fid, + &fid->volatile_fid, oparms->desired_access, + oparms->disposition, oparms->create_options, smb2_oplock, + smb2_data); if (rc) goto out; if (buf) { /* open response does not have IndexNumber field - get it */ - rc = SMB2_get_srv_num(xid, tcon, fid->persistent_fid, + rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, fid->volatile_fid, &smb2_data->IndexNumber); if (rc) { diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index d71a3e2a772d..206efde13f71 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -84,11 +84,9 @@ extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon, const char *from_name, const char *to_name, struct cifs_sb_info *cifs_sb); -extern int smb2_open_file(const unsigned int xid, struct cifs_tcon *tcon, - const char *full_path, int disposition, - int desired_access, int create_options, - struct cifs_fid *fid, __u32 *oplock, - FILE_ALL_INFO *buf, struct cifs_sb_info *cifs_sb); +extern int smb2_open_file(const unsigned int xid, + struct cifs_open_parms *oparms, + __u32 *oplock, FILE_ALL_INFO *buf); extern void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); extern int smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, const unsigned int xid); -- GitLab From 064f6047a123d61dd52bb44605c999cd8ef727d9 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Tue, 9 Jul 2013 18:20:30 +0400 Subject: [PATCH 2569/2900] CIFS: Make SMB2_open use cifs_open_parms struct to prepare it for further durable handle reconnect processing. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/smb2file.c | 5 +---- fs/cifs/smb2inode.c | 35 ++++++++++++++++++------------- fs/cifs/smb2ops.c | 51 +++++++++++++++++++++++++++++---------------- fs/cifs/smb2pdu.c | 19 ++++++++--------- fs/cifs/smb2proto.h | 6 ++---- 5 files changed, 66 insertions(+), 50 deletions(-) diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 5bab192f64e8..398992962cc6 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -85,10 +85,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE); - rc = SMB2_open(xid, oparms->tcon, smb2_path, &fid->persistent_fid, - &fid->volatile_fid, oparms->desired_access, - oparms->disposition, oparms->create_options, smb2_oplock, - smb2_data); + rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data); if (rc) goto out; diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index f50eefd9e005..9841df771f08 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -44,17 +44,22 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, __u32 create_options, void *data, int command) { int rc, tmprc = 0; - u64 persistent_fid, volatile_fid; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct cifs_open_parms oparms; + struct cifs_fid fid; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - desired_access, create_disposition, create_options, - &oplock, NULL); + oparms.tcon = tcon; + oparms.desired_access = desired_access; + oparms.disposition = create_disposition; + oparms.create_options = create_options; + oparms.fid = &fid; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); if (rc) { kfree(utf16_path); return rc; @@ -64,8 +69,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, case SMB2_OP_DELETE: break; case SMB2_OP_QUERY_INFO: - tmprc = SMB2_query_info(xid, tcon, persistent_fid, - volatile_fid, + tmprc = SMB2_query_info(xid, tcon, fid.persistent_fid, + fid.volatile_fid, (struct smb2_file_all_info *)data); break; case SMB2_OP_MKDIR: @@ -75,19 +80,21 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, */ break; case SMB2_OP_RENAME: - tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid, - (__le16 *)data); + tmprc = SMB2_rename(xid, tcon, fid.persistent_fid, + fid.volatile_fid, (__le16 *)data); break; case SMB2_OP_HARDLINK: - tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid, - volatile_fid, (__le16 *)data); + tmprc = SMB2_set_hardlink(xid, tcon, fid.persistent_fid, + fid.volatile_fid, (__le16 *)data); break; case SMB2_OP_SET_EOF: - tmprc = SMB2_set_eof(xid, tcon, persistent_fid, volatile_fid, - current->tgid, (__le64 *)data); + tmprc = SMB2_set_eof(xid, tcon, fid.persistent_fid, + fid.volatile_fid, current->tgid, + (__le64 *)data); break; case SMB2_OP_SET_INFO: - tmprc = SMB2_set_info(xid, tcon, persistent_fid, volatile_fid, + tmprc = SMB2_set_info(xid, tcon, fid.persistent_fid, + fid.volatile_fid, (FILE_BASIC_INFO *)data); break; default: @@ -95,7 +102,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, break; } - rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); + rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); if (tmprc) rc = tmprc; kfree(utf16_path); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 92bdc7ec5c99..1bc7d7e64cf5 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -213,22 +213,28 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path) { int rc; - __u64 persistent_fid, volatile_fid; __le16 *utf16_path; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct cifs_open_parms oparms; + struct cifs_fid fid; utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); if (!utf16_path) return -ENOMEM; - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, &oplock, NULL); + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; + oparms.create_options = 0; + oparms.fid = &fid; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); if (rc) { kfree(utf16_path); return rc; } - rc = SMB2_close(xid, tcon, persistent_fid, volatile_fid); + rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); kfree(utf16_path); return rc; } @@ -443,15 +449,19 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, __le16 *utf16_path; int rc; __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; - __u64 persistent_fid, volatile_fid; + struct cifs_open_parms oparms; utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); if (!utf16_path) return -ENOMEM; - rc = SMB2_open(xid, tcon, utf16_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES | FILE_READ_DATA, FILE_OPEN, 0, - &oplock, NULL); + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA; + oparms.disposition = FILE_OPEN; + oparms.create_options = 0; + oparms.fid = fid; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); kfree(utf16_path); if (rc) { cifs_dbg(VFS, "open dir failed\n"); @@ -460,14 +470,12 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, srch_inf->entries_in_buffer = 0; srch_inf->index_of_last_entry = 0; - fid->persistent_fid = persistent_fid; - fid->volatile_fid = volatile_fid; - rc = SMB2_query_directory(xid, tcon, persistent_fid, volatile_fid, 0, - srch_inf); + rc = SMB2_query_directory(xid, tcon, fid->persistent_fid, + fid->volatile_fid, 0, srch_inf); if (rc) { cifs_dbg(VFS, "query directory failed\n"); - SMB2_close(xid, tcon, persistent_fid, volatile_fid); + SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid); } return rc; } @@ -528,17 +536,24 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, struct kstatfs *buf) { int rc; - u64 persistent_fid, volatile_fid; __le16 srch_path = 0; /* Null - open root of share */ u8 oplock = SMB2_OPLOCK_LEVEL_NONE; + struct cifs_open_parms oparms; + struct cifs_fid fid; + + oparms.tcon = tcon; + oparms.desired_access = FILE_READ_ATTRIBUTES; + oparms.disposition = FILE_OPEN; + oparms.create_options = 0; + oparms.fid = &fid; - rc = SMB2_open(xid, tcon, &srch_path, &persistent_fid, &volatile_fid, - FILE_READ_ATTRIBUTES, FILE_OPEN, 0, &oplock, NULL); + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL); if (rc) return rc; buf->f_type = SMB2_MAGIC_NUMBER; - rc = SMB2_QFS_info(xid, tcon, persistent_fid, volatile_fid, buf); - SMB2_close(xid, tcon, persistent_fid, volatile_fid); + rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid, + buf); + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); return rc; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 140a613073fb..9d7341d696fc 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -946,14 +946,13 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec) } int -SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, - u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, - __u32 create_disposition, __u32 create_options, __u8 *oplock, - struct smb2_file_all_info *buf) +SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, + __u8 *oplock, struct smb2_file_all_info *buf) { struct smb2_create_req *req; struct smb2_create_rsp *rsp; struct TCP_Server_Info *server; + struct cifs_tcon *tcon = oparms->tcon; struct cifs_ses *ses = tcon->ses; struct kvec iov[4]; int resp_buftype; @@ -975,16 +974,16 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, if (rc) return rc; - if (create_options & CREATE_OPTION_READONLY) + if (oparms->create_options & CREATE_OPTION_READONLY) file_attributes |= ATTR_READONLY; req->ImpersonationLevel = IL_IMPERSONATION; - req->DesiredAccess = cpu_to_le32(desired_access); + req->DesiredAccess = cpu_to_le32(oparms->desired_access); /* File attributes ignored on open (used in create though) */ req->FileAttributes = cpu_to_le32(file_attributes); req->ShareAccess = FILE_SHARE_ALL_LE; - req->CreateDisposition = cpu_to_le32(create_disposition); - req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); + req->CreateDisposition = cpu_to_le32(oparms->disposition); + req->CreateOptions = cpu_to_le32(oparms->create_options & CREATE_OPTIONS_MASK); uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; /* do not count rfc1001 len field */ req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) - 4); @@ -1055,8 +1054,8 @@ SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, goto creat_exit; } - *persistent_fid = rsp->PersistentFileId; - *volatile_fid = rsp->VolatileFileId; + oparms->fid->persistent_fid = rsp->PersistentFileId; + oparms->fid->volatile_fid = rsp->VolatileFileId; if (buf) { memcpy(buf, &rsp->CreationTime, 32); diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 206efde13f71..1a5ecbed40ed 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -104,10 +104,8 @@ extern int SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, struct cifs_tcon *tcon, const struct nls_table *); extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon); -extern int SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, - __le16 *path, u64 *persistent_fid, u64 *volatile_fid, - __u32 desired_access, __u32 create_disposition, - __u32 create_options, __u8 *oplock, +extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, + __le16 *path, __u8 *oplock, struct smb2_file_all_info *buf); extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid, u32 opcode, -- GitLab From 9cbc0b7339b0542a1d13922d2745a2636ce44853 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Tue, 9 Jul 2013 18:40:58 +0400 Subject: [PATCH 2570/2900] CIFS: Reconnect durable handles for SMB2 On reconnects, we need to reopen file and then obtain all byte-range locks held by the client. SMB2 protocol provides feature to make this process atomic by reconnecting to the same file handle with all it's byte-range locks. This patch adds this capability for SMB2 shares. Signed-off-by: Pavel Shilovsky Signed-off-by: Steven French --- fs/cifs/cifsglob.h | 1 + fs/cifs/dir.c | 1 + fs/cifs/file.c | 15 +++++++++------ fs/cifs/smb2file.c | 3 ++- fs/cifs/smb2inode.c | 1 + fs/cifs/smb2ops.c | 3 +++ fs/cifs/smb2pdu.c | 38 ++++++++++++++++++++++++++++++++++---- fs/cifs/smb2pdu.h | 8 +++++++- 8 files changed, 58 insertions(+), 12 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 982fdf92c791..1fdc37041057 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -920,6 +920,7 @@ struct cifs_open_parms { int create_options; const char *path; struct cifs_fid *fid; + bool reconnect:1; }; struct cifs_fid { diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index c27c242ac5ba..d62ce0d48141 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -327,6 +327,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid, oparms.disposition = disposition; oparms.path = full_path; oparms.fid = fid; + oparms.reconnect = false; rc = server->ops->open(xid, &oparms, oplock, buf); if (rc) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index f36f9a7893da..ba7eed2ee662 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -232,6 +232,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, oparms.disposition = disposition; oparms.path = full_path; oparms.fid = fid; + oparms.reconnect = false; rc = server->ops->open(xid, &oparms, oplock, buf); @@ -594,7 +595,6 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) int desired_access; int disposition = FILE_OPEN; int create_options = CREATE_NOT_DIR; - struct cifs_fid fid; struct cifs_open_parms oparms; xid = get_xid(); @@ -645,7 +645,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) rc = cifs_posix_open(full_path, NULL, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, - oflags, &oplock, &fid.netfid, xid); + oflags, &oplock, &cfile->fid.netfid, xid); if (rc == 0) { cifs_dbg(FYI, "posix reopen succeeded\n"); goto reopen_success; @@ -662,7 +662,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) create_options |= CREATE_OPEN_BACKUP_INTENT; if (server->ops->get_lease_key) - server->ops->get_lease_key(inode, &fid); + server->ops->get_lease_key(inode, &cfile->fid); oparms.tcon = tcon; oparms.cifs_sb = cifs_sb; @@ -670,7 +670,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) oparms.create_options = create_options; oparms.disposition = disposition; oparms.path = full_path; - oparms.fid = &fid; + oparms.fid = &cfile->fid; + oparms.reconnect = true; /* * Can not refresh inode by passing in file_info buf to be returned by @@ -710,8 +711,9 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) * to the server to get the new inode info. */ - server->ops->set_fid(cfile, &fid, oplock); - cifs_relock_file(cfile); + server->ops->set_fid(cfile, &cfile->fid, oplock); + if (oparms.reconnect) + cifs_relock_file(cfile); reopen_error_exit: kfree(full_path); @@ -1508,6 +1510,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, if (!rc) goto out; + /* * Windows 7 server can delay breaking lease from read to None * if we set a byte-range lock on a file - break it explicitly diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 398992962cc6..04a81a4142c3 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -40,7 +40,8 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) oplock &= 0xFF; if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) return; - if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { + if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE || + oplock == SMB2_OPLOCK_LEVEL_BATCH) { cinode->clientCanCacheAll = true; cinode->clientCanCacheRead = true; cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n", diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 9841df771f08..c6ec1633309a 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -58,6 +58,7 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon, oparms.disposition = create_disposition; oparms.create_options = create_options; oparms.fid = &fid; + oparms.reconnect = false; rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); if (rc) { diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 1bc7d7e64cf5..f259e6cc8357 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -227,6 +227,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, oparms.disposition = FILE_OPEN; oparms.create_options = 0; oparms.fid = &fid; + oparms.reconnect = false; rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); if (rc) { @@ -460,6 +461,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, oparms.disposition = FILE_OPEN; oparms.create_options = 0; oparms.fid = fid; + oparms.reconnect = false; rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL); kfree(utf16_path); @@ -546,6 +548,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, oparms.disposition = FILE_OPEN; oparms.create_options = 0; oparms.fid = &fid; + oparms.reconnect = false; rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL); if (rc) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 9d7341d696fc..c7ad06fc9d63 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -857,7 +857,7 @@ create_durable_buf(void) return NULL; buf->ccontext.DataOffset = cpu_to_le16(offsetof - (struct create_durable, Reserved)); + (struct create_durable, Data)); buf->ccontext.DataLength = cpu_to_le32(16); buf->ccontext.NameOffset = cpu_to_le16(offsetof (struct create_durable, Name)); @@ -869,6 +869,30 @@ create_durable_buf(void) return buf; } +static struct create_durable * +create_reconnect_durable_buf(struct cifs_fid *fid) +{ + struct create_durable *buf; + + buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); + if (!buf) + return NULL; + + buf->ccontext.DataOffset = cpu_to_le16(offsetof + (struct create_durable, Data)); + buf->ccontext.DataLength = cpu_to_le32(16); + buf->ccontext.NameOffset = cpu_to_le16(offsetof + (struct create_durable, Name)); + buf->ccontext.NameLength = cpu_to_le16(4); + buf->Data.Fid.PersistentFileId = fid->persistent_fid; + buf->Data.Fid.VolatileFileId = fid->volatile_fid; + buf->Name[0] = 'D'; + buf->Name[1] = 'H'; + buf->Name[2] = 'n'; + buf->Name[3] = 'C'; + return buf; +} + static __u8 parse_lease_state(struct smb2_create_rsp *rsp) { @@ -924,12 +948,18 @@ add_lease_context(struct kvec *iov, unsigned int *num_iovec, __u8 *oplock) } static int -add_durable_context(struct kvec *iov, unsigned int *num_iovec) +add_durable_context(struct kvec *iov, unsigned int *num_iovec, + struct cifs_open_parms *oparms) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; - iov[num].iov_base = create_durable_buf(); + if (oparms->reconnect) { + iov[num].iov_base = create_reconnect_durable_buf(oparms->fid); + /* indicate that we don't need to relock the file */ + oparms->reconnect = false; + } else + iov[num].iov_base = create_durable_buf(); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = sizeof(struct create_durable); @@ -1037,7 +1067,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, (struct create_context *)iov[num_iovecs-1].iov_base; ccontext->Next = sizeof(struct create_lease); } - rc = add_durable_context(iov, &num_iovecs); + rc = add_durable_context(iov, &num_iovecs, oparms); if (rc) { cifs_small_buf_release(req); kfree(copy_path); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 3e30f0ad5749..36b0d37ea69b 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -488,7 +488,13 @@ struct create_lease { struct create_durable { struct create_context ccontext; __u8 Name[8]; - __u8 Reserved[16]; + union { + __u8 Reserved[16]; + struct { + __u64 PersistentFileId; + __u64 VolatileFileId; + } Fid; + } Data; } __packed; /* this goes in the ioctl buffer when doing a copychunk request */ -- GitLab From 1c46943f84f7532a9503810d44b0772581c0325c Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 10 Jul 2013 12:50:57 -0500 Subject: [PATCH 2571/2900] [CIFS] Fix minor endian error in durable handle patch series Fix endian warning: CHECK fs/cifs/smb2pdu.c fs/cifs/smb2pdu.c:1068:40: warning: incorrect type in assignment (different base types) fs/cifs/smb2pdu.c:1068:40: expected restricted __le32 [usertype] Next fs/cifs/smb2pdu.c:1068:40: got unsigned long Signed-off-by: Steve French --- fs/cifs/smb2pdu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index c7ad06fc9d63..abc9c2809b51 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1065,7 +1065,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) { struct create_context *ccontext = (struct create_context *)iov[num_iovecs-1].iov_base; - ccontext->Next = sizeof(struct create_lease); + ccontext->Next = + cpu_to_le32(sizeof(struct create_lease)); } rc = add_durable_context(iov, &num_iovecs, oparms); if (rc) { -- GitLab From 99bfdd878693f440e723a7b33ccedd0b9dc1ca16 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 27 May 2013 10:28:46 +0800 Subject: [PATCH 2572/2900] drivers/ide/delkin_cb: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: David S. Miller --- drivers/ide/delkin_cb.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c index 7e27d3295e55..300daabaa575 100644 --- a/drivers/ide/delkin_cb.c +++ b/drivers/ide/delkin_cb.c @@ -173,18 +173,7 @@ static struct pci_driver delkin_cb_pci_driver = { .resume = delkin_cb_resume, }; -static int __init delkin_cb_init(void) -{ - return pci_register_driver(&delkin_cb_pci_driver); -} - -static void __exit delkin_cb_exit(void) -{ - pci_unregister_driver(&delkin_cb_pci_driver); -} - -module_init(delkin_cb_init); -module_exit(delkin_cb_exit); +module_pci_driver(delkin_cb_pci_driver); MODULE_AUTHOR("Mark Lord"); MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE"); -- GitLab From 1581208b2f0643eebfa7a3fbe5bad831c0bb7f0e Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 20 Jun 2013 10:30:37 -0500 Subject: [PATCH 2573/2900] ide: Fix IDE PIO size calculation IDE PIO calculates the size wrong when passing the parameter "ide-core.nodma=0.0" to the kernel. Signed-off-by: Leonid Yegoshin Acked-by: Steven J. Hill Signed-off-by: Steven J. Hill Signed-off-by: David S. Miller --- drivers/ide/ide-taskfile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 729428edeba2..dabb88b1cbec 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -239,9 +239,6 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs); int page_is_high; - if (nr_bytes > PAGE_SIZE) - nr_bytes = PAGE_SIZE; - page = sg_page(cursg); offset = cursg->offset + cmd->cursg_ofs; @@ -249,6 +246,8 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, page = nth_page(page, (offset >> PAGE_SHIFT)); offset %= PAGE_SIZE; + nr_bytes = min_t(unsigned, nr_bytes, (PAGE_SIZE - offset)); + page_is_high = PageHighMem(page); if (page_is_high) local_irq_save(flags); -- GitLab From 4c241b364b5899e46924bfd4f9599c45f8e4a146 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 20 May 2013 10:30:07 +0800 Subject: [PATCH 2574/2900] x86: msi-laptop: fix memleak 1. fix two visible mistakes: * when load_scm_model_init faild, we should call platform_device_del(msipf_device) * msipf_attribute_group should be remove in err case 2. change some tags, give them real meaning. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/msi-laptop.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 6b2293875672..62f8030b9e77 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -1098,29 +1098,29 @@ static int __init msi_init(void) ret = platform_device_add(msipf_device); if (ret) - goto fail_platform_device1; + goto fail_device_add; if (quirks->load_scm_model && (load_scm_model_init(msipf_device) < 0)) { ret = -EINVAL; - goto fail_platform_device1; + goto fail_scm_model_init; } ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); if (ret) - goto fail_platform_device2; + goto fail_create_group; if (!quirks->old_ec_model) { if (threeg_exists) ret = device_create_file(&msipf_device->dev, &dev_attr_threeg); if (ret) - goto fail_platform_device2; + goto fail_create_attr; } else { ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_old_attribute_group); if (ret) - goto fail_platform_device2; + goto fail_create_attr; /* Disable automatic brightness control by default because * this module was probably loaded to do brightness control in @@ -1134,26 +1134,22 @@ static int __init msi_init(void) return 0; -fail_platform_device2: - +fail_create_attr: + sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); +fail_create_group: if (quirks->load_scm_model) { i8042_remove_filter(msi_laptop_i8042_filter); cancel_delayed_work_sync(&msi_rfkill_dwork); cancel_work_sync(&msi_rfkill_work); rfkill_cleanup(); } +fail_scm_model_init: platform_device_del(msipf_device); - -fail_platform_device1: - +fail_device_add: platform_device_put(msipf_device); - fail_platform_driver: - platform_driver_unregister(&msipf_driver); - fail_backlight: - backlight_device_unregister(msibl_device); return ret; -- GitLab From 38bdd729ca39e1924a31970e41b13b6ce6ec1755 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 20 May 2013 10:30:24 +0800 Subject: [PATCH 2575/2900] x86: asus-laptop: fix invalid point access asus->name is null or point to const string,so it is not suitable to kfree it. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-laptop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 0eea09c1c134..8e268da6fdbd 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1935,7 +1935,6 @@ static int asus_acpi_add(struct acpi_device *device) fail_backlight: asus_platform_exit(asus); fail_platform: - kfree(asus->name); kfree(asus); return result; -- GitLab From 0ed60654a24c730dcb555da8439e5639253b6eca Mon Sep 17 00:00:00 2001 From: vic Date: Wed, 22 May 2013 21:32:10 +0300 Subject: [PATCH 2576/2900] asus-wmi: append newline to messages Append newline to messages. Signed-off-by: Viktar Vauchkevich Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c11b2426dac1..0e58d748d7f6 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1045,7 +1045,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev, else if (value == 3) value = 255; else if (value != 0) { - pr_err("Unknown fan speed %#x", value); + pr_err("Unknown fan speed %#x\n", value); value = -1; } @@ -1557,11 +1557,11 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) /* INIT enable hotkeys on some models */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv)) - pr_info("Initialization: %#x", rv); + pr_info("Initialization: %#x\n", rv); /* We don't know yet what to do with this version... */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) { - pr_info("BIOS WMI version: %d.%d", rv >> 16, rv & 0xFF); + pr_info("BIOS WMI version: %d.%d\n", rv >> 16, rv & 0xFF); asus->spec = rv; } @@ -1572,7 +1572,7 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) * The significance of others is yet to be found. */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) { - pr_info("SFUN value: %#x", rv); + pr_info("SFUN value: %#x\n", rv); asus->sfun = rv; } @@ -1712,7 +1712,7 @@ static int asus_wmi_debugfs_init(struct asus_wmi *asus) asus->debug.root = debugfs_create_dir(asus->driver->name, NULL); if (!asus->debug.root) { - pr_err("failed to create debugfs directory"); + pr_err("failed to create debugfs directory\n"); goto error_debugfs; } @@ -1985,17 +1985,17 @@ EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver); static int __init asus_wmi_init(void) { if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) { - pr_info("Asus Management GUID not found"); + pr_info("Asus Management GUID not found\n"); return -ENODEV; } - pr_info("ASUS WMI generic driver loaded"); + pr_info("ASUS WMI generic driver loaded\n"); return 0; } static void __exit asus_wmi_exit(void) { - pr_info("ASUS WMI generic driver unloaded"); + pr_info("ASUS WMI generic driver unloaded\n"); } module_init(asus_wmi_init); -- GitLab From 3aabf444f70f5855d8a0a06285fdd55e76a740d5 Mon Sep 17 00:00:00 2001 From: Viktar Vauchkevich Date: Thu, 23 May 2013 07:17:11 +0300 Subject: [PATCH 2577/2900] asus-nb-wmi: ignore ALS notification key code Ignore Ambient Light Sensor notification key code 0xC6 found in ASUS UX31a. When the illuminance changes dmesg shows: [10814.939979] asus_wmi: Unknown key c6 pressed Signed-off-by: Viktar Vauchkevich Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 8fcb41e18b9c..7340566c5865 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -256,6 +256,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0xB5, { KEY_CALC } }, { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, + { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ { KE_END, 0}, }; -- GitLab From b5f4f9ef0125845cd03dc9de5dbe1344e60474d0 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Mon, 27 May 2013 10:31:33 +0800 Subject: [PATCH 2578/2900] drivers/platform/x86/intel_ips: Convert to module_pci_driver use module_pci_driver instead of init/exit, make code clean. Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_ips.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 5051aa970e0a..18dcb58ba965 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1731,18 +1731,7 @@ static struct pci_driver ips_pci_driver = { .shutdown = ips_shutdown, }; -static int __init ips_init(void) -{ - return pci_register_driver(&ips_pci_driver); -} -module_init(ips_init); - -static void ips_exit(void) -{ - pci_unregister_driver(&ips_pci_driver); - return; -} -module_exit(ips_exit); +module_pci_driver(ips_pci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jesse Barnes "); -- GitLab From e8f56c80aedacfb1552509c0e4ed265266328bc4 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Thu, 30 May 2013 10:31:50 +0800 Subject: [PATCH 2579/2900] asus-wmi: control wlan-led only if wapf == 4 Controlling the wlan led seems to have some side effects to the machines with wapf value is not equal to 4. It will make the keyboard backlight out of order. So, the patch will enable the wlan led function only if the wapf == 4. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=46791 Reported-by: Mirto Silvio Busico Tested-by: Karol Herbst Tested-by: drunkenbatman Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-wmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 0e58d748d7f6..19c313b056c3 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -558,7 +558,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus)) { + if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -886,7 +886,8 @@ static int asus_new_rfkill(struct asus_wmi *asus, if (!*rfkill) return -EINVAL; - if (dev_id == ASUS_WMI_DEVID_WLAN) + if ((dev_id == ASUS_WMI_DEVID_WLAN) && + (asus->driver->quirks->wapf == 4)) rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); rfkill_init_sw_state(*rfkill, !result); -- GitLab From 8667ca9518bbe0eff2222e69d611f4c8549fcbde Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Thu, 13 Jun 2013 16:46:25 +0800 Subject: [PATCH 2580/2900] hp-wmi: add supports for POST code error HP laptops include a POST code error query 0x2A that reports which point BIOS fails to boot at. The error code is kept in CMOS until it is cleared. Signed-off-by: Alex Hung Signed-off-by: Matthew Garrett --- drivers/platform/x86/hp-wmi.c | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 6e142c3b5e97..97bb05edcb5a 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -56,6 +56,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); #define HPWMI_BIOS_QUERY 0x9 #define HPWMI_HOTKEY_QUERY 0xc #define HPWMI_WIRELESS2_QUERY 0x1b +#define HPWMI_POSTCODEERROR_QUERY 0x2a enum hp_wmi_radio { HPWMI_WIFI = 0, @@ -400,6 +401,16 @@ static int hp_wmi_rfkill2_refresh(void) return 0; } +static int hp_wmi_post_code_state(void) +{ + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 0, &state, + sizeof(state), sizeof(state)); + if (ret) + return -EINVAL; + return state; +} + static ssize_t show_display(struct device *dev, struct device_attribute *attr, char *buf) { @@ -445,6 +456,16 @@ static ssize_t show_tablet(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", value); } +static ssize_t show_postcode(struct device *dev, struct device_attribute *attr, + char *buf) +{ + /* Get the POST error code of previous boot failure. */ + int value = hp_wmi_post_code_state(); + if (value < 0) + return -EINVAL; + return sprintf(buf, "0x%x\n", value); +} + static ssize_t set_als(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -457,11 +478,33 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t set_postcode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + u32 tmp; + long unsigned int tmp2; + + ret = kstrtoul(buf, 10, &tmp2); + if (ret || tmp2 != 1) + return -EINVAL; + + /* Clear the POST error code. It is kept until until cleared. */ + tmp = (u32) tmp2; + ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, 1, &tmp, + sizeof(tmp), sizeof(tmp)); + if (ret) + return -EINVAL; + + return count; +} + static DEVICE_ATTR(display, S_IRUGO, show_display, NULL); static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); +static DEVICE_ATTR(postcode, S_IRUGO | S_IWUSR, show_postcode, set_postcode); static void hp_wmi_notify(u32 value, void *context) { @@ -642,6 +685,7 @@ static void cleanup_sysfs(struct platform_device *device) device_remove_file(&device->dev, &dev_attr_als); device_remove_file(&device->dev, &dev_attr_dock); device_remove_file(&device->dev, &dev_attr_tablet); + device_remove_file(&device->dev, &dev_attr_postcode); } static int hp_wmi_rfkill_setup(struct platform_device *device) @@ -857,6 +901,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) if (err) goto add_sysfs_error; err = device_create_file(&device->dev, &dev_attr_tablet); + if (err) + goto add_sysfs_error; + err = device_create_file(&device->dev, &dev_attr_postcode); if (err) goto add_sysfs_error; return 0; -- GitLab From 34a956db3774e8cba3f6b52aa9c1d67cf9a496fe Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 2 Jul 2013 18:41:03 -0400 Subject: [PATCH 2581/2900] Add support driver for Intel Rapid Start Technology Intel Rapid Start Technology is a firmware-based suspend-to-disk implementation. Once placed in S3, the device will wake once either a timeout elapses or the battery reaches a critical level. It will then resume to the firmware and copy the contents of RAM to a specialised partition, and then power off the machine. If the user turns the machine back on the firmware will copy the contents of the partition back to RAM and then resume from S3 as normal. This driver provides an interface for configuring the wakeup events and timeout. It still requires firmware support and an appropriate suspend partition. Signed-off-by: Matthew Garrett Signed-off-by: Matthew Garrett --- .../testing/sysfs-driver-intel-rapid-start | 21 ++ drivers/platform/x86/Kconfig | 12 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-rst.c | 209 ++++++++++++++++++ 4 files changed, 243 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-intel-rapid-start create mode 100644 drivers/platform/x86/intel-rst.c diff --git a/Documentation/ABI/testing/sysfs-driver-intel-rapid-start b/Documentation/ABI/testing/sysfs-driver-intel-rapid-start new file mode 100644 index 000000000000..5a7d2e217d40 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-intel-rapid-start @@ -0,0 +1,21 @@ +What: /sys/bus/acpi/intel-rapid-start/wakeup_events +Date: July 2, 2013 +KernelVersion: 3.11 +Contact: Matthew Garrett +Description: An integer representing a set of wakeup events as follows: + 1: Wake to enter hibernation when the wakeup timer expires + 2: Wake to enter hibernation when the battery reaches a + critical level + + These values are ORed together. For example, a value of 3 + indicates that the system will wake to enter hibernation when + either the wakeup timer expires or the battery reaches a + critical level. + +What: /sys/bus/acpi/intel-rapid-start/wakeup_time +Date: July 2, 2013 +KernelVersion: 3.11 +Contact: Matthew Garrett +Description: An integer representing the length of time the system will + remain asleep before waking up to enter hibernation. + This value is in minutes. diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 37645b923c52..36057f481162 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -782,6 +782,18 @@ config APPLE_GMUX graphics as well as the backlight. Currently only backlight control is supported by the driver. +config INTEL_RST + tristate "Intel Rapid Start Technology Driver" + depends on ACPI + ---help--- + This driver provides support for modifying paramaters on systems + equipped with Intel's Rapid Start Technology. When put in an ACPI + sleep state, these devices will wake after either a configured + timeout or when the system battery reaches a critical state, + automatically copying memory contents to disk. On resume, the + firmware will copy the memory contents back to RAM and resume the OS + as usual. + config PVPANIC tristate "pvpanic device support" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index ef0ec746f78c..5c669ce8d243 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -51,5 +51,6 @@ obj-$(CONFIG_INTEL_OAKTRAIL) += intel_oaktrail.o obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o +obj-$(CONFIG_INTEL_RST) += intel-rst.o obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c new file mode 100644 index 000000000000..9385afd9b558 --- /dev/null +++ b/drivers/platform/x86/intel-rst.c @@ -0,0 +1,209 @@ +/* + * Copyright 2013 Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +static ssize_t irst_show_wakeup_events(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + acpi_status status; + + acpi = to_acpi_device(dev); + + status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + return sprintf(buf, "%lld\n", result->integer.value); +} + +static ssize_t irst_store_wakeup_events(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + unsigned long value; + int error; + + acpi = to_acpi_device(dev); + + error = kstrtoul(buf, 0, &value); + + if (error) + return error; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = value; + + input.count = 1; + input.pointer = ¶m; + + status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL); + + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + return count; +} + +static struct device_attribute irst_wakeup_attr = { + .attr = { .name = "wakeup_events", .mode = 0600 }, + .show = irst_show_wakeup_events, + .store = irst_store_wakeup_events +}; + +static ssize_t irst_show_wakeup_time(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct acpi_device *acpi; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + acpi_status status; + + acpi = to_acpi_device(dev); + + status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + return sprintf(buf, "%lld\n", result->integer.value); +} + +static ssize_t irst_store_wakeup_time(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct acpi_object_list input; + union acpi_object param; + acpi_status status; + unsigned long value; + int error; + + acpi = to_acpi_device(dev); + + error = kstrtoul(buf, 0, &value); + + if (error) + return error; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = value; + + input.count = 1; + input.pointer = ¶m; + + status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL); + + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + return count; +} + +static struct device_attribute irst_timeout_attr = { + .attr = { .name = "wakeup_time", .mode = 0600 }, + .show = irst_show_wakeup_time, + .store = irst_store_wakeup_time +}; + +static int irst_add(struct acpi_device *acpi) +{ + int error = 0; + + error = device_create_file(&acpi->dev, &irst_timeout_attr); + if (error) + goto out; + + error = device_create_file(&acpi->dev, &irst_wakeup_attr); + if (error) + goto out_timeout; + + return 0; + +out_timeout: + device_remove_file(&acpi->dev, &irst_timeout_attr); +out: + return error; +} + +static int irst_remove(struct acpi_device *acpi) +{ + device_remove_file(&acpi->dev, &irst_wakeup_attr); + device_remove_file(&acpi->dev, &irst_timeout_attr); + + return 0; +} + +static const struct acpi_device_id irst_ids[] = { + {"INT3392", 0}, + {"", 0} +}; + +static struct acpi_driver irst_driver = { + .owner = THIS_MODULE, + .name = "intel_rapid_start", + .class = "intel_rapid_start", + .ids = irst_ids, + .ops = { + .add = irst_add, + .remove = irst_remove, + }, +}; + +static int irst_init(void) +{ + return acpi_bus_register_driver(&irst_driver); +} + +static void irst_exit(void) +{ + acpi_bus_unregister_driver(&irst_driver); +} + +module_init(irst_init); +module_exit(irst_exit); + +MODULE_DEVICE_TABLE(acpi, irst_ids); -- GitLab From 5c7f80f75512557dd0728ada77e8e8a8c7c8458b Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 3 Jul 2013 00:50:13 -0400 Subject: [PATCH 2582/2900] Add trivial driver to disable Intel Smart Connect Intel Smart Connect is an Intel-specific ACPI interface for configuring devices to wake up at regular intervals so they can pull down mail or other internet updates, and then go to sleep again. If a user enables this in Windows and then reboots into Linux, the device may wake up if it's put to sleep. Since there's no Linux userland support for any of this, the machine will then remain awake until something else puts it back to sleep. I haven't figured out all that much about how this works (there's a bunch of different ACPI calls available on the device), but this seems to be enough to turn it off. We can add more features to this driver if anyone ever cares about figuring out what the rest of the calls do or writing some Linux userspace to implement the rest of it. Signed-off-by: Matthew Garrett Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 14 ++++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-smartconnect.c | 90 +++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/platform/x86/intel-smartconnect.c diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 36057f481162..a3d76c59a394 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -794,6 +794,20 @@ config INTEL_RST firmware will copy the memory contents back to RAM and resume the OS as usual. +config INTEL_SMARTCONNECT + tristate "Intel Smart Connect disabling driver" + depends on ACPI + ---help--- + Intel Smart Connect is a technology intended to permit devices to + update state by resuming for a short period of time at regular + intervals. If a user enables this functionality under Windows and + then reboots into Linux, the system may remain configured to resume + on suspend. In the absence of any userspace to support it, the system + will then remain awake until something triggers another suspend. + + This driver checks to determine whether the device has Intel Smart + Connect enabled, and if so disables it. + config PVPANIC tristate "pvpanic device support" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index 5c669ce8d243..5dbe19324351 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -52,5 +52,6 @@ obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_INTEL_RST) += intel-rst.o +obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c new file mode 100644 index 000000000000..f74e93d096bc --- /dev/null +++ b/drivers/platform/x86/intel-smartconnect.c @@ -0,0 +1,90 @@ +/* + * Copyright 2013 Matthew Garrett + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include + +MODULE_LICENSE("GPL"); + +static int smartconnect_acpi_init(struct acpi_device *acpi) +{ + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *result; + union acpi_object param; + acpi_status status; + + status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output); + if (!ACPI_SUCCESS(status)) + return -EINVAL; + + result = output.pointer; + + if (result->type != ACPI_TYPE_INTEGER) { + kfree(result); + return -EINVAL; + } + + if (result->integer.value & 0x1) { + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0; + + input.count = 1; + input.pointer = ¶m; + + dev_info(&acpi->dev, "Disabling Intel Smart Connect\n"); + status = acpi_evaluate_object(acpi->handle, "SAOS", &input, + NULL); + } + + kfree(result); + + return 0; +} + +static const struct acpi_device_id smartconnect_ids[] = { + {"INT33A0", 0}, + {"", 0} +}; + +static struct acpi_driver smartconnect_driver = { + .owner = THIS_MODULE, + .name = "intel_smart_connect", + .class = "intel_smart_connect", + .ids = smartconnect_ids, + .ops = { + .add = smartconnect_acpi_init, + }, +}; + +static int smartconnect_init(void) +{ + return acpi_bus_register_driver(&smartconnect_driver); +} + +static void smartconnect_exit(void) +{ + acpi_bus_unregister_driver(&smartconnect_driver); +} + +module_init(smartconnect_init); +module_exit(smartconnect_exit); + +MODULE_DEVICE_TABLE(acpi, smartconnect_ids); -- GitLab From 144a19ac94526c4609fa8b8264e6f9c3d48f7a55 Mon Sep 17 00:00:00 2001 From: AceLan Kao Date: Wed, 3 Jul 2013 14:35:15 +0800 Subject: [PATCH 2583/2900] asus-nb-wmi: set wapf=4 for ASUSTeK COMPUTER INC. 1015E/U Need to set wapf to 4 for ASUSTeK COMPUTER INC. 1015E/U, so that user can toggle wifi function through function key correctly. Signed-off-by: AceLan Kao Signed-off-by: Matthew Garrett --- drivers/platform/x86/asus-nb-wmi.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 7340566c5865..563f59efa669 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -180,6 +180,24 @@ static struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_x401u, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. 1015E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. 1015U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), + }, + .driver_data = &quirk_asus_x401u, + }, {}, }; -- GitLab From 283672e425b24fe4046535973460e8732f4bd485 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 3 Jul 2013 08:14:16 -0500 Subject: [PATCH 2584/2900] toshiba_acpi: Add dependency on SERIO_I8042 Configuring this option as a module with ACPI_TOSHIBA built-in results in the following errors: drivers/built-in.o: In function `toshiba_acpi_remove': >> toshiba_acpi.c:(.text+0x314bb0): undefined reference to `i8042_remove_filter' drivers/built-in.o: In function `toshiba_acpi_add': >> toshiba_acpi.c:(.devinit.text+0xb822): undefined reference to `i8042_install_filter' >> toshiba_acpi.c:(.devinit.text+0xb98b): undefined reference to `i8042_remove_filter' Add a dependency to prevent ACPI_TOSHIBA from being built-in when SERIO_I8042=m. Reported-by: kbuild test robot Cc: Azael Avalos Signed-off-by: Seth Forshee Signed-off-by: Matthew Garrett --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index a3d76c59a394..36a9e6023395 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -592,6 +592,7 @@ config ACPI_TOSHIBA depends on BACKLIGHT_CLASS_DEVICE depends on INPUT depends on RFKILL || RFKILL = n + depends on SERIO_I8042 || SERIO_I8042 = n select INPUT_POLLDEV select INPUT_SPARSEKMAP ---help--- -- GitLab From fef8ce166b2d5cdba8bbf85fa48c4cb8d75ffec4 Mon Sep 17 00:00:00 2001 From: Libo Chen Date: Tue, 9 Jul 2013 20:34:28 +0800 Subject: [PATCH 2585/2900] x86 platform drivers: fix gpio leak when request_irq fails, we should release gpiochip v2: fix warning: ignoring return value of 'gpiochip_remove Signed-off-by: Libo Chen Signed-off-by: Matthew Garrett --- drivers/platform/x86/intel_pmic_gpio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel_pmic_gpio.c b/drivers/platform/x86/intel_pmic_gpio.c index 6f4b7289a059..2805988485f6 100644 --- a/drivers/platform/x86/intel_pmic_gpio.c +++ b/drivers/platform/x86/intel_pmic_gpio.c @@ -288,7 +288,7 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) retval = request_irq(pg->irq, pmic_irq_handler, 0, "pmic", pg); if (retval) { pr_warn("Interrupt request failed\n"); - goto err; + goto fail_request_irq; } for (i = 0; i < 8; i++) { @@ -299,6 +299,10 @@ static int platform_pmic_gpio_probe(struct platform_device *pdev) irq_set_chip_data(i + pg->irq_base, pg); } return 0; + +fail_request_irq: + if (gpiochip_remove(&pg->chip)) + pr_err("gpiochip_remove failed\n"); err: iounmap(pg->gpiointr); err2: -- GitLab From eeee245268c951262b861bc1be4e9dc812352499 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 10 Jul 2013 15:33:01 -0400 Subject: [PATCH 2586/2900] SUNRPC: Fix a deadlock in rpc_client_register() Commit 384816051ca9125cd54750e59c780c2a2655fa4f (SUNRPC: fix races on PipeFS MOUNT notifications) introduces a regression when we call rpc_setup_pipedir() with RPCSEC_GSS as the auth flavour. By calling rpcauth_create() while holding the sn->pipefs_sb_lock, we end up deadlocking in gss_pipes_dentries_create_net(). Fix is to register the client and release the mutex before calling rpcauth_create(). Reported-by: Weston Andros Adamson Tested-by: Weston Andros Adamson Cc: Stanislav Kinsbursky Cc: # : 3848160: SUNRPC: fix races on PipeFS MOUNT Cc: # : e73f4cc: SUNRPC: split client creation Signed-off-by: Trond Myklebust --- net/sunrpc/clnt.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f0339ae9bf37..aa401560777b 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -290,7 +290,7 @@ static int rpc_client_register(const struct rpc_create_args *args, struct rpc_auth *auth; struct net *net = rpc_net_ns(clnt); struct super_block *pipefs_sb; - int err = 0; + int err; pipefs_sb = rpc_get_sb_net(net); if (pipefs_sb) { @@ -299,6 +299,10 @@ static int rpc_client_register(const struct rpc_create_args *args, goto out; } + rpc_register_client(clnt); + if (pipefs_sb) + rpc_put_sb_net(net); + auth = rpcauth_create(args->authflavor, clnt); if (IS_ERR(auth)) { dprintk("RPC: Couldn't create auth handle (flavor %u)\n", @@ -306,16 +310,14 @@ static int rpc_client_register(const struct rpc_create_args *args, err = PTR_ERR(auth); goto err_auth; } - - rpc_register_client(clnt); + return 0; +err_auth: + pipefs_sb = rpc_get_sb_net(net); + __rpc_clnt_remove_pipedir(clnt); out: if (pipefs_sb) rpc_put_sb_net(net); return err; - -err_auth: - __rpc_clnt_remove_pipedir(clnt); - goto out; } static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) -- GitLab From f118e9abddfae94d7ef88858159d7556e1c2f7f6 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 22 Jun 2013 13:26:09 +0800 Subject: [PATCH 2587/2900] arch: sparc: kernel: check the memory length before use strcpy(). For the related next strcpy(), the destination length is less than 512, but the source maximize length may be 'OPROMMAXPARAM' (4096) which is more than 512. One work flow may: openprom_sunos_ioctl() -> if (cmd == OPROMSETOPT) getstrings() -> will alloc buffer with size 'OPROMMAXPARAM'. opromsetopt() -> devide the buffer into 'var' and 'value' of_set_property() -> pass prom_setprop() -> pass ldom_set_var() And do not mind the additional 4 alignment buffer increasing, since 'sizeof(pkt) - sizeof(pkt.header)' is 4 alignment at least. Signed-off-by: Chen Gang Signed-off-by: David S. Miller --- arch/sparc/kernel/ds.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 5ef48dab5636..11d460f6f9cc 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -783,6 +783,16 @@ void ldom_set_var(const char *var, const char *value) char *base, *p; int msg_len, loops; + if (strlen(var) + strlen(value) + 2 > + sizeof(pkt) - sizeof(pkt.header)) { + printk(KERN_ERR PFX + "contents length: %zu, which more than max: %lu," + "so could not set (%s) variable to (%s).\n", + strlen(var) + strlen(value) + 2, + sizeof(pkt) - sizeof(pkt.header), var, value); + return; + } + memset(&pkt, 0, sizeof(pkt)); pkt.header.data.tag.type = DS_DATA; pkt.header.data.handle = cp->handle; -- GitLab From e8e2bfd1033aadfee334419b7d11eeba1bc9cbed Mon Sep 17 00:00:00 2001 From: Andreas Larsson Date: Mon, 1 Jul 2013 16:16:07 +0200 Subject: [PATCH 2588/2900] sparc32, leon: Require separate snoop tags set to regard snooping to be enabled Even if data snooping is enabled, without separate snoop tags snooping will not work when the MMU is enabled. Signed-off-by: Andreas Larsson Signed-off-by: David S. Miller --- arch/sparc/include/asm/leon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index b836e9297f2a..c2f6ff6d7a35 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -108,7 +108,7 @@ static inline int sparc_leon3_snooping_enabled(void) { u32 cctrl; __asm__ __volatile__("lda [%%g0] 2, %0\n\t" : "=r"(cctrl)); - return (cctrl >> 23) & 1; + return ((cctrl >> 23) & 1) && ((cctrl >> 17) & 1); }; static inline void sparc_leon3_disable_cache(void) -- GitLab From aabb9875d02559ab9b928cd6f259a5cc4c21a589 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 1 Jul 2013 16:49:22 -0500 Subject: [PATCH 2589/2900] sunvnet: vnet_port_remove must call unregister_netdev The missing call to unregister_netdev() leaves the interface active after the driver is unloaded by rmmod. Signed-off-by: Dave Kleikamp Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunvnet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 1df0ff3839e8..3df56840a3b9 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -1239,6 +1239,8 @@ static int vnet_port_remove(struct vio_dev *vdev) dev_set_drvdata(&vdev->dev, NULL); kfree(port); + + unregister_netdev(vp->dev); } return 0; } -- GitLab From 961246b4ed8da3bcf4ee1eb9147f341013553e3c Mon Sep 17 00:00:00 2001 From: Olivier DANET Date: Wed, 10 Jul 2013 13:56:10 -0700 Subject: [PATCH 2590/2900] [PATCH] sparc32: vm_area_struct access for old Sun SPARCs. Commit e4c6bfd2d79d063017ab19a18915f0bc759f32d9 ("mm: rearrange vm_area_struct for fewer cache misses") changed the layout of the vm_area_struct structure, it broke several SPARC32 assembly routines which used numerical constants for accessing the vm_mm field. This patch defines the VMA_VM_MM constant to replace the immediate values. Signed-off-by: Olivier DANET Signed-off-by: David S. Miller --- arch/sparc/kernel/asm-offsets.c | 2 ++ arch/sparc/mm/hypersparc.S | 8 ++++---- arch/sparc/mm/swift.S | 8 ++++---- arch/sparc/mm/tsunami.S | 6 +++--- arch/sparc/mm/viking.S | 10 +++++----- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c index 961b87f99e69..f76389a32342 100644 --- a/arch/sparc/kernel/asm-offsets.c +++ b/arch/sparc/kernel/asm-offsets.c @@ -49,6 +49,8 @@ int foo(void) DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread)); BLANK(); DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context)); + BLANK(); + DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); /* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */ return 0; diff --git a/arch/sparc/mm/hypersparc.S b/arch/sparc/mm/hypersparc.S index 44aad32eeb4e..969f96450f69 100644 --- a/arch/sparc/mm/hypersparc.S +++ b/arch/sparc/mm/hypersparc.S @@ -74,7 +74,7 @@ hypersparc_flush_cache_mm_out: /* The things we do for performance... */ hypersparc_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 #ifndef CONFIG_SMP ld [%o0 + AOFF_mm_context], %g1 cmp %g1, -1 @@ -163,7 +163,7 @@ hypersparc_flush_cache_range_out: */ /* Verified, my ass... */ hypersparc_flush_cache_page: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %g2 #ifndef CONFIG_SMP cmp %g2, -1 @@ -284,7 +284,7 @@ hypersparc_flush_tlb_mm_out: sta %g5, [%g1] ASI_M_MMUREGS hypersparc_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -307,7 +307,7 @@ hypersparc_flush_tlb_range_out: sta %g5, [%g1] ASI_M_MMUREGS hypersparc_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S index c801c3953a00..5d2b88d39424 100644 --- a/arch/sparc/mm/swift.S +++ b/arch/sparc/mm/swift.S @@ -105,7 +105,7 @@ swift_flush_cache_mm_out: .globl swift_flush_cache_range swift_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 sub %o2, %o1, %o2 sethi %hi(4096), %o3 cmp %o2, %o3 @@ -116,7 +116,7 @@ swift_flush_cache_range: .globl swift_flush_cache_page swift_flush_cache_page: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 70: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -219,7 +219,7 @@ swift_flush_sig_insns: .globl swift_flush_tlb_range .globl swift_flush_tlb_all swift_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 swift_flush_tlb_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -233,7 +233,7 @@ swift_flush_tlb_all_out: .globl swift_flush_tlb_page swift_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S index 4e55e8f76648..bf10a345fa8b 100644 --- a/arch/sparc/mm/tsunami.S +++ b/arch/sparc/mm/tsunami.S @@ -24,7 +24,7 @@ /* Sliiick... */ tsunami_flush_cache_page: tsunami_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 tsunami_flush_cache_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -46,7 +46,7 @@ tsunami_flush_sig_insns: /* More slick stuff... */ tsunami_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 tsunami_flush_tlb_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -65,7 +65,7 @@ tsunami_flush_tlb_out: /* This one can be done in a fine grained manner... */ tsunami_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S index bf8ee0613ae7..852257fcc82b 100644 --- a/arch/sparc/mm/viking.S +++ b/arch/sparc/mm/viking.S @@ -108,7 +108,7 @@ viking_mxcc_flush_page: viking_flush_cache_page: viking_flush_cache_range: #ifndef CONFIG_SMP - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 #endif viking_flush_cache_mm: #ifndef CONFIG_SMP @@ -148,7 +148,7 @@ viking_flush_tlb_mm: #endif viking_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -173,7 +173,7 @@ viking_flush_tlb_range: #endif viking_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -239,7 +239,7 @@ sun4dsmp_flush_tlb_range: tst %g5 bne 3f mov SRMMU_CTX_REG, %g1 - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4 @@ -265,7 +265,7 @@ sun4dsmp_flush_tlb_page: tst %g5 bne 2f mov SRMMU_CTX_REG, %g1 - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 and %o1, PAGE_MASK, %o1 -- GitLab From 496fd15bee6f2fd673ab992e5211c5f3c5bd6779 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 10 Jul 2013 14:21:46 -0700 Subject: [PATCH 2591/2900] drm: avoid warning in drm_load_edid_firmware() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use "const char *" instead of "char *" in order to avoid this warning: drivers/gpu/drm/drm_edid_load.c: In function ‘drm_load_edid_firmware’: drivers/gpu/drm/drm_edid_load.c:245:25: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default] Signed-off-by: Linus Torvalds --- drivers/gpu/drm/drm_edid_load.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index a4f5ce14dc1c..271b42bbfb72 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -133,8 +133,8 @@ static u8 generic_edid[GENERIC_EDIDS][128] = { }, }; -static u8 *edid_load(struct drm_connector *connector, char *name, - char *connector_name) +static u8 *edid_load(struct drm_connector *connector, const char *name, + const char *connector_name) { const struct firmware *fw; struct platform_device *pdev; @@ -242,7 +242,7 @@ static u8 *edid_load(struct drm_connector *connector, char *name, int drm_load_edid_firmware(struct drm_connector *connector) { - char *connector_name = drm_get_connector_name(connector); + const char *connector_name = drm_get_connector_name(connector); char *edidname = edid_firmware, *last, *colon; int ret; struct edid *edid; -- GitLab From 6c182cd88d179cbbd06f4f8a8a19b6977940753f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 10 Jul 2013 23:41:15 +0100 Subject: [PATCH 2592/2900] dm mpath: fix ioctl deadlock when no paths When multipath needs to retry an ioctl the reference to the current live table needs to be dropped. Otherwise a deadlock occurs when all paths are down: - dm_blk_ioctl takes a reference to the current table and spins in multipath_ioctl(). - A new table is being loaded, but upon resume the process hangs in dm_table_destroy() waiting for references to drop to zero. With this patch the reference to the old table is dropped prior to retry, thereby avoiding the deadlock. Signed-off-by: Hannes Reinecke Cc: Mike Snitzer Cc: stable@vger.kernel.org Signed-off-by: Alasdair G Kergon --- drivers/md/dm-mpath.c | 8 ++------ drivers/md/dm.c | 9 ++++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index bdf26f5bd326..5adede17ddf6 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1561,7 +1561,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long flags; int r; -again: bdev = NULL; mode = 0; r = 0; @@ -1579,7 +1578,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, } if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) - r = -EAGAIN; + r = -ENOTCONN; else if (!bdev) r = -EIO; @@ -1591,11 +1590,8 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) r = scsi_verify_blk_ioctl(NULL, cmd); - if (r == -EAGAIN && !fatal_signal_pending(current)) { + if (r == -ENOTCONN && !fatal_signal_pending(current)) queue_work(kmultipathd, &m->process_queued_ios); - msleep(10); - goto again; - } return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d5370a94b2c1..33f20103d8d5 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -386,10 +386,12 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct mapped_device *md = bdev->bd_disk->private_data; - struct dm_table *map = dm_get_live_table(md); + struct dm_table *map; struct dm_target *tgt; int r = -ENOTTY; +retry: + map = dm_get_live_table(md); if (!map || !dm_table_get_size(map)) goto out; @@ -410,6 +412,11 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, out: dm_table_put(map); + if (r == -ENOTCONN) { + msleep(10); + goto retry; + } + return r; } -- GitLab From 1c0e883e86ece31880fac2f84b260545d66a39e0 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:15 +0100 Subject: [PATCH 2593/2900] dm ioctl: set noio flag to avoid __vmalloc deadlock Set noio flag while calling __vmalloc() because it doesn't fully respect gfp flags to avoid a possible deadlock (see commit 502624bdad3dba45dfaacaf36b7d83e39e74b2d2). This should be backported to stable kernels 3.8 and newer. The kernel 3.8 doesn't have memalloc_noio_save(), so we should set and restore process flag PF_MEMALLOC instead. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index aa04f0224642..81a79b739e97 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1644,7 +1644,10 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern } if (!dmi) { + unsigned noio_flag; + noio_flag = memalloc_noio_save(); dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL); + memalloc_noio_restore(noio_flag); if (dmi) *param_flags |= DM_PARAMS_VMALLOC; } -- GitLab From b1bf2de07271932326af847a3c6a01fdfd29d4be Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:16 +0100 Subject: [PATCH 2594/2900] dm verity: fix inability to use a few specific devices sizes Fix a boundary condition that caused failure for certain device sizes. The problem is reported at http://code.google.com/p/cryptsetup/issues/detail?id=160 For certain device sizes the number of hashes at a specific level was calculated incorrectly. It happens for example for a device with data and metadata block size 4096 that has 16385 blocks and algorithm sha256. The user can test if he is affected by this bug by running the "veritysetup verify" command and also by activating the dm-verity kernel driver and reading the whole block device. If it passes without an error, then the user is not affected. The condition for the bug is: Split the total number of data blocks (data_block_bits) into bit strings, each string has hash_per_block_bits bits. hash_per_block_bits is rounddown(log2(metadata_block_size/hash_digest_size)). Equivalently, you can say that you convert data_blocks_bits to 2^hash_per_block_bits base. If there some zero bit string below the most significant bit string and at least one bit below this zero bit string is set, then the bug happens. The same bug exists in the userspace veritysetup tool, so you must use fixed veritysetup too if you want to use devices that are affected by this boundary condition. Signed-off-by: Mikulas Patocka Cc: stable@vger.kernel.org # 3.4+ Cc: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-verity.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index b948fd864d45..0d2e812d424b 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -831,9 +831,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) for (i = v->levels - 1; i >= 0; i--) { sector_t s; v->hash_level_block[i] = hash_position; - s = verity_position_at_level(v, v->data_blocks, i); - s = (s >> v->hash_per_block_bits) + - !!(s & ((1 << v->hash_per_block_bits) - 1)); + s = (v->data_blocks + ((sector_t)1 << ((i + 1) * v->hash_per_block_bits)) - 1) + >> ((i + 1) * v->hash_per_block_bits); if (hash_position + s < hash_position) { ti->error = "Hash device offset overflow"; r = -E2BIG; -- GitLab From 220cd058d9b66b940105e0a32324f06d557deba7 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:16 +0100 Subject: [PATCH 2595/2900] dm: use __GFP_HIGHMEM in __vmalloc Use __GFP_HIGHMEM in __vmalloc. Pages allocated with __vmalloc can be allocated in high memory that is not directly mapped to kernel space, so use __GFP_HIGHMEM just like vmalloc does. This patch reduces memory pressure slightly because pages can be allocated in the high zone. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-bufio.c | 2 +- drivers/md/dm-ioctl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 0387e05cdb98..9588b864d311 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -349,7 +349,7 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask, if (gfp_mask & __GFP_NORETRY) noio_flag = memalloc_noio_save(); - ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL); + ptr = __vmalloc(c->block_size, gfp_mask | __GFP_HIGHMEM, PAGE_KERNEL); if (gfp_mask & __GFP_NORETRY) memalloc_noio_restore(noio_flag); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 81a79b739e97..12f04868e899 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1646,7 +1646,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern if (!dmi) { unsigned noio_flag; noio_flag = memalloc_noio_save(); - dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH, PAGE_KERNEL); + dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_REPEAT | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL); memalloc_noio_restore(noio_flag); if (dmi) *param_flags |= DM_PARAMS_VMALLOC; -- GitLab From 5d8be84397618a2c04ec2b74d5d5a3d852a2ee5a Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:17 +0100 Subject: [PATCH 2596/2900] dm verity: remove pointless comparison Remove num < 0 test in verity_ctr because num is unsigned. (Found by Coverity.) Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-verity.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 0d2e812d424b..9804da16a476 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -695,8 +695,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) goto bad; } - if (sscanf(argv[0], "%d%c", &num, &dummy) != 1 || - num < 0 || num > 1) { + if (sscanf(argv[0], "%u%c", &num, &dummy) != 1 || + num > 1) { ti->error = "Invalid version"; r = -EINVAL; goto bad; -- GitLab From 75e3a0f55bf097dab76c662358bcb7c88928f49d Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Wed, 10 Jul 2013 23:41:17 +0100 Subject: [PATCH 2597/2900] dm flakey: correct ctr alloc failure mesg Remove the reference to the "linear" target from the error message issued when allocation fails in the flakey target. Cc: Robin Dong Signed-off-by: Alasdair G Kergon --- drivers/md/dm-flakey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index 7fcf21cb4ff8..c80a0ec5f126 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -176,7 +176,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv) fc = kzalloc(sizeof(*fc), GFP_KERNEL); if (!fc) { - ti->error = "Cannot allocate linear context"; + ti->error = "Cannot allocate context"; return -ENOMEM; } fc->start_time = jiffies; -- GitLab From 553d8fe029a561d5921fba495206e64eefea42cb Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:17 +0100 Subject: [PATCH 2598/2900] dm verity: use __ffs and __fls This patch changes ffs() to __ffs() and fls() to __fls() which don't add one to the result. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-verity.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 9804da16a476..4b7941db3aff 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -451,7 +451,7 @@ static void verity_prefetch_io(struct work_struct *work) goto no_prefetch_cluster; if (unlikely(cluster & (cluster - 1))) - cluster = 1 << (fls(cluster) - 1); + cluster = 1 << __fls(cluster); hash_block_start &= ~(sector_t)(cluster - 1); hash_block_end |= cluster - 1; @@ -723,7 +723,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) r = -EINVAL; goto bad; } - v->data_dev_block_bits = ffs(num) - 1; + v->data_dev_block_bits = __ffs(num); if (sscanf(argv[4], "%u%c", &num, &dummy) != 1 || !num || (num & (num - 1)) || @@ -733,7 +733,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) r = -EINVAL; goto bad; } - v->hash_dev_block_bits = ffs(num) - 1; + v->hash_dev_block_bits = __ffs(num); if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 || (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) @@ -812,7 +812,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) } v->hash_per_block_bits = - fls((1 << v->hash_dev_block_bits) / v->digest_size) - 1; + __fls((1 << v->hash_dev_block_bits) / v->digest_size); v->levels = 0; if (v->data_blocks) -- GitLab From 43aeaa29573924df76f44eda2bbd94ca36e407b5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:17 +0100 Subject: [PATCH 2599/2900] dm cache: fix arm link errors with inline Use __always_inline to avoid a link failure with gcc 4.6 on ARM. gcc 4.7 is OK. It creates a function block_div.part.8, it references __udivdi3 and __umoddi3 and it is never called. The references to __udivdi3 and __umoddi3 cause a link failure. Reported-by: Rob Herring Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-cache-target.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index df44b60e66f2..0df3ec085ebb 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -425,6 +425,10 @@ static bool block_size_is_power_of_two(struct cache *cache) return cache->sectors_per_block_shift >= 0; } +/* gcc on ARM generates spurious references to __udivdi3 and __umoddi3 */ +#if defined(CONFIG_ARM) && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 +__always_inline +#endif static dm_block_t block_div(dm_block_t b, uint32_t n) { do_div(b, n); -- GitLab From 2480945cd44b50ba8b1646544eec2db21f064f12 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:18 +0100 Subject: [PATCH 2600/2900] dm bufio: submit writes outside lock This patch changes dm-bufio so that it submits write I/Os outside of the lock. If the number of submitted buffers is greater than the number of requests on the target queue, submit_bio blocks. We want to block outside of the lock to improve latency of other threads that may need the lock. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-bufio.c | 73 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 9588b864d311..5227e079a6e3 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -145,6 +145,7 @@ struct dm_buffer { unsigned long state; unsigned long last_accessed; struct dm_bufio_client *c; + struct list_head write_list; struct bio bio; struct bio_vec bio_vec[DM_BUFIO_INLINE_VECS]; }; @@ -630,7 +631,8 @@ static int do_io_schedule(void *word) * - Submit our write and don't wait on it. We set B_WRITING indicating * that there is a write in progress. */ -static void __write_dirty_buffer(struct dm_buffer *b) +static void __write_dirty_buffer(struct dm_buffer *b, + struct list_head *write_list) { if (!test_bit(B_DIRTY, &b->state)) return; @@ -639,7 +641,24 @@ static void __write_dirty_buffer(struct dm_buffer *b) wait_on_bit_lock(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE); - submit_io(b, WRITE, b->block, write_endio); + if (!write_list) + submit_io(b, WRITE, b->block, write_endio); + else + list_add_tail(&b->write_list, write_list); +} + +static void __flush_write_list(struct list_head *write_list) +{ + struct blk_plug plug; + blk_start_plug(&plug); + while (!list_empty(write_list)) { + struct dm_buffer *b = + list_entry(write_list->next, struct dm_buffer, write_list); + list_del(&b->write_list); + submit_io(b, WRITE, b->block, write_endio); + dm_bufio_cond_resched(); + } + blk_finish_plug(&plug); } /* @@ -655,7 +674,7 @@ static void __make_buffer_clean(struct dm_buffer *b) return; wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE); - __write_dirty_buffer(b); + __write_dirty_buffer(b, NULL); wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE); } @@ -802,7 +821,8 @@ static void __free_buffer_wake(struct dm_buffer *b) wake_up(&c->free_buffer_wait); } -static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait) +static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait, + struct list_head *write_list) { struct dm_buffer *b, *tmp; @@ -818,7 +838,7 @@ static void __write_dirty_buffers_async(struct dm_bufio_client *c, int no_wait) if (no_wait && test_bit(B_WRITING, &b->state)) return; - __write_dirty_buffer(b); + __write_dirty_buffer(b, write_list); dm_bufio_cond_resched(); } } @@ -853,7 +873,8 @@ static void __get_memory_limit(struct dm_bufio_client *c, * If we are over threshold_buffers, start freeing buffers. * If we're over "limit_buffers", block until we get under the limit. */ -static void __check_watermark(struct dm_bufio_client *c) +static void __check_watermark(struct dm_bufio_client *c, + struct list_head *write_list) { unsigned long threshold_buffers, limit_buffers; @@ -872,7 +893,7 @@ static void __check_watermark(struct dm_bufio_client *c) } if (c->n_buffers[LIST_DIRTY] > threshold_buffers) - __write_dirty_buffers_async(c, 1); + __write_dirty_buffers_async(c, 1, write_list); } /* @@ -897,7 +918,8 @@ static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block) *--------------------------------------------------------------*/ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block, - enum new_flag nf, int *need_submit) + enum new_flag nf, int *need_submit, + struct list_head *write_list) { struct dm_buffer *b, *new_b = NULL; @@ -924,7 +946,7 @@ static struct dm_buffer *__bufio_new(struct dm_bufio_client *c, sector_t block, goto found_buffer; } - __check_watermark(c); + __check_watermark(c, write_list); b = new_b; b->hold_count = 1; @@ -992,10 +1014,14 @@ static void *new_read(struct dm_bufio_client *c, sector_t block, int need_submit; struct dm_buffer *b; + LIST_HEAD(write_list); + dm_bufio_lock(c); - b = __bufio_new(c, block, nf, &need_submit); + b = __bufio_new(c, block, nf, &need_submit, &write_list); dm_bufio_unlock(c); + __flush_write_list(&write_list); + if (!b) return b; @@ -1047,6 +1073,8 @@ void dm_bufio_prefetch(struct dm_bufio_client *c, { struct blk_plug plug; + LIST_HEAD(write_list); + BUG_ON(dm_bufio_in_request()); blk_start_plug(&plug); @@ -1055,7 +1083,15 @@ void dm_bufio_prefetch(struct dm_bufio_client *c, for (; n_blocks--; block++) { int need_submit; struct dm_buffer *b; - b = __bufio_new(c, block, NF_PREFETCH, &need_submit); + b = __bufio_new(c, block, NF_PREFETCH, &need_submit, + &write_list); + if (unlikely(!list_empty(&write_list))) { + dm_bufio_unlock(c); + blk_finish_plug(&plug); + __flush_write_list(&write_list); + blk_start_plug(&plug); + dm_bufio_lock(c); + } if (unlikely(b != NULL)) { dm_bufio_unlock(c); @@ -1069,7 +1105,6 @@ void dm_bufio_prefetch(struct dm_bufio_client *c, goto flush_plug; dm_bufio_lock(c); } - } dm_bufio_unlock(c); @@ -1126,11 +1161,14 @@ EXPORT_SYMBOL_GPL(dm_bufio_mark_buffer_dirty); void dm_bufio_write_dirty_buffers_async(struct dm_bufio_client *c) { + LIST_HEAD(write_list); + BUG_ON(dm_bufio_in_request()); dm_bufio_lock(c); - __write_dirty_buffers_async(c, 0); + __write_dirty_buffers_async(c, 0, &write_list); dm_bufio_unlock(c); + __flush_write_list(&write_list); } EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers_async); @@ -1147,8 +1185,13 @@ int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c) unsigned long buffers_processed = 0; struct dm_buffer *b, *tmp; + LIST_HEAD(write_list); + + dm_bufio_lock(c); + __write_dirty_buffers_async(c, 0, &write_list); + dm_bufio_unlock(c); + __flush_write_list(&write_list); dm_bufio_lock(c); - __write_dirty_buffers_async(c, 0); again: list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_DIRTY], lru_list) { @@ -1274,7 +1317,7 @@ void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block) BUG_ON(!b->hold_count); BUG_ON(test_bit(B_READING, &b->state)); - __write_dirty_buffer(b); + __write_dirty_buffer(b, NULL); if (b->hold_count == 1) { wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE); -- GitLab From 83d5e5b0af907d46d241a86d9e44003b3f0accbd Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:18 +0100 Subject: [PATCH 2601/2900] dm: optimize use SRCU and RCU This patch removes "io_lock" and "map_lock" in struct mapped_device and "holders" in struct dm_table and replaces these mechanisms with sleepable-rcu. Previously, the code would call "dm_get_live_table" and "dm_table_put" to get and release table. Now, the code is changed to call "dm_get_live_table" and "dm_put_live_table". dm_get_live_table locks sleepable-rcu and dm_put_live_table unlocks it. dm_get_live_table_fast/dm_put_live_table_fast can be used instead of dm_get_live_table/dm_put_live_table. These *_fast functions use non-sleepable RCU, so the caller must not block between them. If the code changes active or inactive dm table, it must call dm_sync_table before destroying the old table. Signed-off-by: Mikulas Patocka Signed-off-by: Jun'ichi Nomura Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 122 +++++++++++++++++--------- drivers/md/dm-table.c | 35 -------- drivers/md/dm.c | 160 ++++++++++++++++++++-------------- include/linux/device-mapper.h | 6 +- include/uapi/linux/dm-ioctl.h | 4 +- 5 files changed, 180 insertions(+), 147 deletions(-) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 12f04868e899..f1b758675ec7 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -36,6 +36,14 @@ struct hash_cell { struct dm_table *new_map; }; +/* + * A dummy definition to make RCU happy. + * struct dm_table should never be dereferenced in this file. + */ +struct dm_table { + int undefined__; +}; + struct vers_iter { size_t param_size; struct dm_target_versions *vers, *old_vers; @@ -242,9 +250,10 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi return -EBUSY; } -static void __hash_remove(struct hash_cell *hc) +static struct dm_table *__hash_remove(struct hash_cell *hc) { struct dm_table *table; + int srcu_idx; /* remove from the dev hash */ list_del(&hc->uuid_list); @@ -253,16 +262,18 @@ static void __hash_remove(struct hash_cell *hc) dm_set_mdptr(hc->md, NULL); mutex_unlock(&dm_hash_cells_mutex); - table = dm_get_live_table(hc->md); - if (table) { + table = dm_get_live_table(hc->md, &srcu_idx); + if (table) dm_table_event(table); - dm_table_put(table); - } + dm_put_live_table(hc->md, srcu_idx); + table = NULL; if (hc->new_map) - dm_table_destroy(hc->new_map); + table = hc->new_map; dm_put(hc->md); free_cell(hc); + + return table; } static void dm_hash_remove_all(int keep_open_devices) @@ -270,6 +281,7 @@ static void dm_hash_remove_all(int keep_open_devices) int i, dev_skipped; struct hash_cell *hc; struct mapped_device *md; + struct dm_table *t; retry: dev_skipped = 0; @@ -287,10 +299,14 @@ static void dm_hash_remove_all(int keep_open_devices) continue; } - __hash_remove(hc); + t = __hash_remove(hc); up_write(&_hash_lock); + if (t) { + dm_sync_table(md); + dm_table_destroy(t); + } dm_put(md); if (likely(keep_open_devices)) dm_destroy(md); @@ -356,6 +372,7 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param, struct dm_table *table; struct mapped_device *md; unsigned change_uuid = (param->flags & DM_UUID_FLAG) ? 1 : 0; + int srcu_idx; /* * duplicate new. @@ -418,11 +435,10 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param, /* * Wake up any dm event waiters. */ - table = dm_get_live_table(hc->md); - if (table) { + table = dm_get_live_table(hc->md, &srcu_idx); + if (table) dm_table_event(table); - dm_table_put(table); - } + dm_put_live_table(hc->md, srcu_idx); if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, param->event_nr)) param->flags |= DM_UEVENT_GENERATED_FLAG; @@ -620,11 +636,14 @@ static int check_name(const char *name) * _hash_lock without first calling dm_table_put, because dm_table_destroy * waits for this dm_table_put and could be called under this lock. */ -static struct dm_table *dm_get_inactive_table(struct mapped_device *md) +static struct dm_table *dm_get_inactive_table(struct mapped_device *md, int *srcu_idx) { struct hash_cell *hc; struct dm_table *table = NULL; + /* increment rcu count, we don't care about the table pointer */ + dm_get_live_table(md, srcu_idx); + down_read(&_hash_lock); hc = dm_get_mdptr(md); if (!hc || hc->md != md) { @@ -633,8 +652,6 @@ static struct dm_table *dm_get_inactive_table(struct mapped_device *md) } table = hc->new_map; - if (table) - dm_table_get(table); out: up_read(&_hash_lock); @@ -643,10 +660,11 @@ static struct dm_table *dm_get_inactive_table(struct mapped_device *md) } static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md, - struct dm_ioctl *param) + struct dm_ioctl *param, + int *srcu_idx) { return (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) ? - dm_get_inactive_table(md) : dm_get_live_table(md); + dm_get_inactive_table(md, srcu_idx) : dm_get_live_table(md, srcu_idx); } /* @@ -657,6 +675,7 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param) { struct gendisk *disk = dm_disk(md); struct dm_table *table; + int srcu_idx; param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | DM_ACTIVE_PRESENT_FLAG); @@ -676,26 +695,27 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param) param->event_nr = dm_get_event_nr(md); param->target_count = 0; - table = dm_get_live_table(md); + table = dm_get_live_table(md, &srcu_idx); if (table) { if (!(param->flags & DM_QUERY_INACTIVE_TABLE_FLAG)) { if (get_disk_ro(disk)) param->flags |= DM_READONLY_FLAG; param->target_count = dm_table_get_num_targets(table); } - dm_table_put(table); param->flags |= DM_ACTIVE_PRESENT_FLAG; } + dm_put_live_table(md, srcu_idx); if (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) { - table = dm_get_inactive_table(md); + int srcu_idx; + table = dm_get_inactive_table(md, &srcu_idx); if (table) { if (!(dm_table_get_mode(table) & FMODE_WRITE)) param->flags |= DM_READONLY_FLAG; param->target_count = dm_table_get_num_targets(table); - dm_table_put(table); } + dm_put_live_table(md, srcu_idx); } } @@ -796,6 +816,7 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) struct hash_cell *hc; struct mapped_device *md; int r; + struct dm_table *t; down_write(&_hash_lock); hc = __find_device_hash_cell(param); @@ -819,9 +840,14 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size) return r; } - __hash_remove(hc); + t = __hash_remove(hc); up_write(&_hash_lock); + if (t) { + dm_sync_table(md); + dm_table_destroy(t); + } + if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr)) param->flags |= DM_UEVENT_GENERATED_FLAG; @@ -986,6 +1012,7 @@ static int do_resume(struct dm_ioctl *param) old_map = dm_swap_table(md, new_map); if (IS_ERR(old_map)) { + dm_sync_table(md); dm_table_destroy(new_map); dm_put(md); return PTR_ERR(old_map); @@ -1003,6 +1030,10 @@ static int do_resume(struct dm_ioctl *param) param->flags |= DM_UEVENT_GENERATED_FLAG; } + /* + * Since dm_swap_table synchronizes RCU, nobody should be in + * read-side critical section already. + */ if (old_map) dm_table_destroy(old_map); @@ -1125,6 +1156,7 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) int r = 0; struct mapped_device *md; struct dm_table *table; + int srcu_idx; md = find_device(param); if (!md) @@ -1145,11 +1177,10 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) */ __dev_status(md, param); - table = dm_get_live_or_inactive_table(md, param); - if (table) { + table = dm_get_live_or_inactive_table(md, param, &srcu_idx); + if (table) retrieve_status(table, param, param_size); - dm_table_put(table); - } + dm_put_live_table(md, srcu_idx); out: dm_put(md); @@ -1221,7 +1252,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) { int r; struct hash_cell *hc; - struct dm_table *t; + struct dm_table *t, *old_map = NULL; struct mapped_device *md; struct target_type *immutable_target_type; @@ -1277,14 +1308,14 @@ static int table_load(struct dm_ioctl *param, size_t param_size) hc = dm_get_mdptr(md); if (!hc || hc->md != md) { DMWARN("device has been removed from the dev hash table."); - dm_table_destroy(t); up_write(&_hash_lock); + dm_table_destroy(t); r = -ENXIO; goto out; } if (hc->new_map) - dm_table_destroy(hc->new_map); + old_map = hc->new_map; hc->new_map = t; up_write(&_hash_lock); @@ -1292,6 +1323,11 @@ static int table_load(struct dm_ioctl *param, size_t param_size) __dev_status(md, param); out: + if (old_map) { + dm_sync_table(md); + dm_table_destroy(old_map); + } + dm_put(md); return r; @@ -1301,6 +1337,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) { struct hash_cell *hc; struct mapped_device *md; + struct dm_table *old_map = NULL; down_write(&_hash_lock); @@ -1312,7 +1349,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) } if (hc->new_map) { - dm_table_destroy(hc->new_map); + old_map = hc->new_map; hc->new_map = NULL; } @@ -1321,6 +1358,10 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) __dev_status(hc->md, param); md = hc->md; up_write(&_hash_lock); + if (old_map) { + dm_sync_table(md); + dm_table_destroy(old_map); + } dm_put(md); return 0; @@ -1370,6 +1411,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) { struct mapped_device *md; struct dm_table *table; + int srcu_idx; md = find_device(param); if (!md) @@ -1377,11 +1419,10 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) __dev_status(md, param); - table = dm_get_live_or_inactive_table(md, param); - if (table) { + table = dm_get_live_or_inactive_table(md, param, &srcu_idx); + if (table) retrieve_deps(table, param, param_size); - dm_table_put(table); - } + dm_put_live_table(md, srcu_idx); dm_put(md); @@ -1396,6 +1437,7 @@ static int table_status(struct dm_ioctl *param, size_t param_size) { struct mapped_device *md; struct dm_table *table; + int srcu_idx; md = find_device(param); if (!md) @@ -1403,11 +1445,10 @@ static int table_status(struct dm_ioctl *param, size_t param_size) __dev_status(md, param); - table = dm_get_live_or_inactive_table(md, param); - if (table) { + table = dm_get_live_or_inactive_table(md, param, &srcu_idx); + if (table) retrieve_status(table, param, param_size); - dm_table_put(table); - } + dm_put_live_table(md, srcu_idx); dm_put(md); @@ -1443,6 +1484,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size) struct dm_target_msg *tmsg = (void *) param + param->data_start; size_t maxlen; char *result = get_result_buffer(param, param_size, &maxlen); + int srcu_idx; md = find_device(param); if (!md) @@ -1470,9 +1512,9 @@ static int target_message(struct dm_ioctl *param, size_t param_size) if (r <= 1) goto out_argv; - table = dm_get_live_table(md); + table = dm_get_live_table(md, &srcu_idx); if (!table) - goto out_argv; + goto out_table; if (dm_deleting_md(md)) { r = -ENXIO; @@ -1491,7 +1533,7 @@ static int target_message(struct dm_ioctl *param, size_t param_size) } out_table: - dm_table_put(table); + dm_put_live_table(md, srcu_idx); out_argv: kfree(argv); out: diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 1ff252ab7d46..f221812b7dbc 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -26,22 +26,8 @@ #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) -/* - * The table has always exactly one reference from either mapped_device->map - * or hash_cell->new_map. This reference is not counted in table->holders. - * A pair of dm_create_table/dm_destroy_table functions is used for table - * creation/destruction. - * - * Temporary references from the other code increase table->holders. A pair - * of dm_table_get/dm_table_put functions is used to manipulate it. - * - * When the table is about to be destroyed, we wait for table->holders to - * drop to zero. - */ - struct dm_table { struct mapped_device *md; - atomic_t holders; unsigned type; /* btree table */ @@ -208,7 +194,6 @@ int dm_table_create(struct dm_table **result, fmode_t mode, INIT_LIST_HEAD(&t->devices); INIT_LIST_HEAD(&t->target_callbacks); - atomic_set(&t->holders, 0); if (!num_targets) num_targets = KEYS_PER_NODE; @@ -246,10 +231,6 @@ void dm_table_destroy(struct dm_table *t) if (!t) return; - while (atomic_read(&t->holders)) - msleep(1); - smp_mb(); - /* free the indexes */ if (t->depth >= 2) vfree(t->index[t->depth - 2]); @@ -274,22 +255,6 @@ void dm_table_destroy(struct dm_table *t) kfree(t); } -void dm_table_get(struct dm_table *t) -{ - atomic_inc(&t->holders); -} -EXPORT_SYMBOL(dm_table_get); - -void dm_table_put(struct dm_table *t) -{ - if (!t) - return; - - smp_mb__before_atomic_dec(); - atomic_dec(&t->holders); -} -EXPORT_SYMBOL(dm_table_put); - /* * Checks to see if we need to extend highs or targets. */ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 33f20103d8d5..ecff83f5b53a 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -116,13 +116,20 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo); #define DMF_NOFLUSH_SUSPENDING 5 #define DMF_MERGE_IS_OPTIONAL 6 +/* + * A dummy definition to make RCU happy. + * struct dm_table should never be dereferenced in this file. + */ +struct dm_table { + int undefined__; +}; + /* * Work processed by per-device workqueue. */ struct mapped_device { - struct rw_semaphore io_lock; + struct srcu_struct io_barrier; struct mutex suspend_lock; - rwlock_t map_lock; atomic_t holders; atomic_t open_count; @@ -156,6 +163,8 @@ struct mapped_device { /* * The current mapping. + * Use dm_get_live_table{_fast} or take suspend_lock for + * dereference. */ struct dm_table *map; @@ -386,12 +395,14 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct mapped_device *md = bdev->bd_disk->private_data; + int srcu_idx; struct dm_table *map; struct dm_target *tgt; int r = -ENOTTY; retry: - map = dm_get_live_table(md); + map = dm_get_live_table(md, &srcu_idx); + if (!map || !dm_table_get_size(map)) goto out; @@ -410,7 +421,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, r = tgt->type->ioctl(tgt, cmd, arg); out: - dm_table_put(map); + dm_put_live_table(md, srcu_idx); if (r == -ENOTCONN) { msleep(10); @@ -509,20 +520,39 @@ static void queue_io(struct mapped_device *md, struct bio *bio) /* * Everyone (including functions in this file), should use this * function to access the md->map field, and make sure they call - * dm_table_put() when finished. + * dm_put_live_table() when finished. */ -struct dm_table *dm_get_live_table(struct mapped_device *md) +struct dm_table *dm_get_live_table(struct mapped_device *md, int *srcu_idx) __acquires(md->io_barrier) { - struct dm_table *t; - unsigned long flags; + *srcu_idx = srcu_read_lock(&md->io_barrier); + + return srcu_dereference(md->map, &md->io_barrier); +} - read_lock_irqsave(&md->map_lock, flags); - t = md->map; - if (t) - dm_table_get(t); - read_unlock_irqrestore(&md->map_lock, flags); +void dm_put_live_table(struct mapped_device *md, int srcu_idx) __releases(md->io_barrier) +{ + srcu_read_unlock(&md->io_barrier, srcu_idx); +} + +void dm_sync_table(struct mapped_device *md) +{ + synchronize_srcu(&md->io_barrier); + synchronize_rcu_expedited(); +} + +/* + * A fast alternative to dm_get_live_table/dm_put_live_table. + * The caller must not block between these two functions. + */ +static struct dm_table *dm_get_live_table_fast(struct mapped_device *md) __acquires(RCU) +{ + rcu_read_lock(); + return rcu_dereference(md->map); +} - return t; +static void dm_put_live_table_fast(struct mapped_device *md) __releases(RCU) +{ + rcu_read_unlock(); } /* @@ -1356,17 +1386,18 @@ static int __split_and_process_non_flush(struct clone_info *ci) /* * Entry point to split a bio into clones and submit them to the targets. */ -static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) +static void __split_and_process_bio(struct mapped_device *md, + struct dm_table *map, struct bio *bio) { struct clone_info ci; int error = 0; - ci.map = dm_get_live_table(md); - if (unlikely(!ci.map)) { + if (unlikely(!map)) { bio_io_error(bio); return; } + ci.map = map; ci.md = md; ci.io = alloc_io(md); ci.io->error = 0; @@ -1393,7 +1424,6 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio) /* drop the extra reference count */ dec_pending(ci.io, error); - dm_table_put(ci.map); } /*----------------------------------------------------------------- * CRUD END @@ -1404,7 +1434,7 @@ static int dm_merge_bvec(struct request_queue *q, struct bio_vec *biovec) { struct mapped_device *md = q->queuedata; - struct dm_table *map = dm_get_live_table(md); + struct dm_table *map = dm_get_live_table_fast(md); struct dm_target *ti; sector_t max_sectors; int max_size = 0; @@ -1414,7 +1444,7 @@ static int dm_merge_bvec(struct request_queue *q, ti = dm_table_find_target(map, bvm->bi_sector); if (!dm_target_is_valid(ti)) - goto out_table; + goto out; /* * Find maximum amount of I/O that won't need splitting @@ -1443,10 +1473,8 @@ static int dm_merge_bvec(struct request_queue *q, max_size = 0; -out_table: - dm_table_put(map); - out: + dm_put_live_table_fast(md); /* * Always allow an entire first page */ @@ -1465,8 +1493,10 @@ static void _dm_request(struct request_queue *q, struct bio *bio) int rw = bio_data_dir(bio); struct mapped_device *md = q->queuedata; int cpu; + int srcu_idx; + struct dm_table *map; - down_read(&md->io_lock); + map = dm_get_live_table(md, &srcu_idx); cpu = part_stat_lock(); part_stat_inc(cpu, &dm_disk(md)->part0, ios[rw]); @@ -1475,7 +1505,7 @@ static void _dm_request(struct request_queue *q, struct bio *bio) /* if we're suspended, we have to queue this io for later */ if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) { - up_read(&md->io_lock); + dm_put_live_table(md, srcu_idx); if (bio_rw(bio) != READA) queue_io(md, bio); @@ -1484,8 +1514,8 @@ static void _dm_request(struct request_queue *q, struct bio *bio) return; } - __split_and_process_bio(md, bio); - up_read(&md->io_lock); + __split_and_process_bio(md, map, bio); + dm_put_live_table(md, srcu_idx); return; } @@ -1671,7 +1701,8 @@ static struct request *dm_start_request(struct mapped_device *md, struct request static void dm_request_fn(struct request_queue *q) { struct mapped_device *md = q->queuedata; - struct dm_table *map = dm_get_live_table(md); + int srcu_idx; + struct dm_table *map = dm_get_live_table(md, &srcu_idx); struct dm_target *ti; struct request *rq, *clone; sector_t pos; @@ -1726,7 +1757,7 @@ static void dm_request_fn(struct request_queue *q) delay_and_out: blk_delay_queue(q, HZ / 10); out: - dm_table_put(map); + dm_put_live_table(md, srcu_idx); } int dm_underlying_device_busy(struct request_queue *q) @@ -1739,14 +1770,14 @@ static int dm_lld_busy(struct request_queue *q) { int r; struct mapped_device *md = q->queuedata; - struct dm_table *map = dm_get_live_table(md); + struct dm_table *map = dm_get_live_table_fast(md); if (!map || test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) r = 1; else r = dm_table_any_busy_target(map); - dm_table_put(map); + dm_put_live_table_fast(md); return r; } @@ -1758,7 +1789,7 @@ static int dm_any_congested(void *congested_data, int bdi_bits) struct dm_table *map; if (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) { - map = dm_get_live_table(md); + map = dm_get_live_table_fast(md); if (map) { /* * Request-based dm cares about only own queue for @@ -1769,9 +1800,8 @@ static int dm_any_congested(void *congested_data, int bdi_bits) bdi_bits; else r = dm_table_any_congested(map, bdi_bits); - - dm_table_put(map); } + dm_put_live_table_fast(md); } return r; @@ -1876,12 +1906,14 @@ static struct mapped_device *alloc_dev(int minor) if (r < 0) goto bad_minor; + r = init_srcu_struct(&md->io_barrier); + if (r < 0) + goto bad_io_barrier; + md->type = DM_TYPE_NONE; - init_rwsem(&md->io_lock); mutex_init(&md->suspend_lock); mutex_init(&md->type_lock); spin_lock_init(&md->deferred_lock); - rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); atomic_set(&md->event_nr, 0); @@ -1944,6 +1976,8 @@ static struct mapped_device *alloc_dev(int minor) bad_disk: blk_cleanup_queue(md->queue); bad_queue: + cleanup_srcu_struct(&md->io_barrier); +bad_io_barrier: free_minor(minor); bad_minor: module_put(THIS_MODULE); @@ -1967,6 +2001,7 @@ static void free_dev(struct mapped_device *md) bioset_free(md->bs); blk_integrity_unregister(md->disk); del_gendisk(md->disk); + cleanup_srcu_struct(&md->io_barrier); free_minor(minor); spin_lock(&_minor_lock); @@ -2109,7 +2144,6 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, struct dm_table *old_map; struct request_queue *q = md->queue; sector_t size; - unsigned long flags; int merge_is_optional; size = dm_table_get_size(t); @@ -2138,9 +2172,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, merge_is_optional = dm_table_merge_is_optional(t); - write_lock_irqsave(&md->map_lock, flags); old_map = md->map; - md->map = t; + rcu_assign_pointer(md->map, t); md->immutable_target_type = dm_table_get_immutable_target_type(t); dm_table_set_restrictions(t, q, limits); @@ -2148,7 +2181,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); else clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); - write_unlock_irqrestore(&md->map_lock, flags); + dm_sync_table(md); return old_map; } @@ -2159,15 +2192,13 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t, static struct dm_table *__unbind(struct mapped_device *md) { struct dm_table *map = md->map; - unsigned long flags; if (!map) return NULL; dm_table_event_callback(map, NULL, NULL); - write_lock_irqsave(&md->map_lock, flags); - md->map = NULL; - write_unlock_irqrestore(&md->map_lock, flags); + rcu_assign_pointer(md->map, NULL); + dm_sync_table(md); return map; } @@ -2319,11 +2350,12 @@ EXPORT_SYMBOL_GPL(dm_device_name); static void __dm_destroy(struct mapped_device *md, bool wait) { struct dm_table *map; + int srcu_idx; might_sleep(); spin_lock(&_minor_lock); - map = dm_get_live_table(md); + map = dm_get_live_table(md, &srcu_idx); idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md)))); set_bit(DMF_FREEING, &md->flags); spin_unlock(&_minor_lock); @@ -2333,6 +2365,9 @@ static void __dm_destroy(struct mapped_device *md, bool wait) dm_table_postsuspend_targets(map); } + /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ + dm_put_live_table(md, srcu_idx); + /* * Rare, but there may be I/O requests still going to complete, * for example. Wait for all references to disappear. @@ -2347,7 +2382,6 @@ static void __dm_destroy(struct mapped_device *md, bool wait) dm_device_name(md), atomic_read(&md->holders)); dm_sysfs_exit(md); - dm_table_put(map); dm_table_destroy(__unbind(md)); free_dev(md); } @@ -2404,8 +2438,10 @@ static void dm_wq_work(struct work_struct *work) struct mapped_device *md = container_of(work, struct mapped_device, work); struct bio *c; + int srcu_idx; + struct dm_table *map; - down_read(&md->io_lock); + map = dm_get_live_table(md, &srcu_idx); while (!test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags)) { spin_lock_irq(&md->deferred_lock); @@ -2415,17 +2451,13 @@ static void dm_wq_work(struct work_struct *work) if (!c) break; - up_read(&md->io_lock); - if (dm_request_based(md)) generic_make_request(c); else - __split_and_process_bio(md, c); - - down_read(&md->io_lock); + __split_and_process_bio(md, map, c); } - up_read(&md->io_lock); + dm_put_live_table(md, srcu_idx); } static void dm_queue_flush(struct mapped_device *md) @@ -2457,10 +2489,10 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) * reappear. */ if (dm_table_has_no_data_devices(table)) { - live_map = dm_get_live_table(md); + live_map = dm_get_live_table_fast(md); if (live_map) limits = md->queue->limits; - dm_table_put(live_map); + dm_put_live_table_fast(md); } if (!live_map) { @@ -2540,7 +2572,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) goto out_unlock; } - map = dm_get_live_table(md); + map = md->map; /* * DMF_NOFLUSH_SUSPENDING must be set before presuspend. @@ -2561,7 +2593,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) if (!noflush && do_lockfs) { r = lock_fs(md); if (r) - goto out; + goto out_unlock; } /* @@ -2576,9 +2608,8 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) * (dm_wq_work), we set BMF_BLOCK_IO_FOR_SUSPEND and call * flush_workqueue(md->wq). */ - down_write(&md->io_lock); set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags); - up_write(&md->io_lock); + synchronize_srcu(&md->io_barrier); /* * Stop md->queue before flushing md->wq in case request-based @@ -2596,10 +2627,9 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) */ r = dm_wait_for_completion(md, TASK_INTERRUPTIBLE); - down_write(&md->io_lock); if (noflush) clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); - up_write(&md->io_lock); + synchronize_srcu(&md->io_barrier); /* were we interrupted ? */ if (r < 0) { @@ -2609,7 +2639,7 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) start_queue(md->queue); unlock_fs(md); - goto out; /* pushback list is already flushed, so skip flush */ + goto out_unlock; /* pushback list is already flushed, so skip flush */ } /* @@ -2622,9 +2652,6 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) dm_table_postsuspend_targets(map); -out: - dm_table_put(map); - out_unlock: mutex_unlock(&md->suspend_lock); return r; @@ -2639,7 +2666,7 @@ int dm_resume(struct mapped_device *md) if (!dm_suspended_md(md)) goto out; - map = dm_get_live_table(md); + map = md->map; if (!map || !dm_table_get_size(map)) goto out; @@ -2663,7 +2690,6 @@ int dm_resume(struct mapped_device *md) r = 0; out: - dm_table_put(map); mutex_unlock(&md->suspend_lock); return r; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 3cd32478f2fd..e151d4c9298d 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -446,9 +446,9 @@ int __must_check dm_set_target_max_io_len(struct dm_target *ti, sector_t len); /* * Table reference counting. */ -struct dm_table *dm_get_live_table(struct mapped_device *md); -void dm_table_get(struct dm_table *t); -void dm_table_put(struct dm_table *t); +struct dm_table *dm_get_live_table(struct mapped_device *md, int *srcu_idx); +void dm_put_live_table(struct mapped_device *md, int srcu_idx); +void dm_sync_table(struct mapped_device *md); /* * Queries diff --git a/include/uapi/linux/dm-ioctl.h b/include/uapi/linux/dm-ioctl.h index 7e75b6fd8d45..afd0cbd52edb 100644 --- a/include/uapi/linux/dm-ioctl.h +++ b/include/uapi/linux/dm-ioctl.h @@ -267,9 +267,9 @@ enum { #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 24 +#define DM_VERSION_MINOR 25 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2013-01-15)" +#define DM_VERSION_EXTRA "-ioctl (2013-06-26)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ -- GitLab From 2a7faeb176fb0478bc6a0cb380c658b32179ead0 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 10 Jul 2013 23:41:18 +0100 Subject: [PATCH 2602/2900] dm: optimize reorder structure This reorder actually improves performance by 20% (from 39.1s to 32.8s) on x86-64 quad core Opteron. I have no explanation for this, possibly it makes some other entries are better cache-aligned. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index ecff83f5b53a..9e39d2b64bf8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -133,6 +133,13 @@ struct mapped_device { atomic_t holders; atomic_t open_count; + /* + * The current mapping. + * Use dm_get_live_table{_fast} or take suspend_lock for + * dereference. + */ + struct dm_table *map; + unsigned long flags; struct request_queue *queue; @@ -161,13 +168,6 @@ struct mapped_device { */ struct workqueue_struct *wq; - /* - * The current mapping. - * Use dm_get_live_table{_fast} or take suspend_lock for - * dereference. - */ - struct dm_table *map; - /* * io objects are allocated from here. */ -- GitLab From 8504eed3ac96457addfef7efc6aab2251073e8dc Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Wed, 10 Jul 2013 23:41:19 +0100 Subject: [PATCH 2603/2900] dm: update maintainers Add Mike Snitzer as an additional device-mapper maintainer. Recognise uapi dm-*.h include files as device-mapper files. Signed-off-by: Alasdair G Kergon Cc: Yann Droneaud Cc: Mike Snitzer --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ad7e322ad17b..d307aec373b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2527,6 +2527,7 @@ S: Maintained DEVICE-MAPPER (LVM) M: Alasdair Kergon +M: Mike Snitzer M: dm-devel@redhat.com L: dm-devel@redhat.com W: http://sources.redhat.com/dm @@ -2538,6 +2539,7 @@ F: drivers/md/dm* F: drivers/md/persistent-data/ F: include/linux/device-mapper.h F: include/linux/dm-*.h +F: include/uapi/linux/dm-*.h DIOLAN U2C-12 I2C DRIVER M: Guenter Roeck -- GitLab From 9d0eb0ab432aaa9160cf2675aee73b3900b9bc18 Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Wed, 10 Jul 2013 23:41:19 +0100 Subject: [PATCH 2604/2900] dm: add switch target dm-switch is a new target that maps IO to underlying block devices efficiently when there is a large number of fixed-sized address regions but there is no simple pattern to allow for a compact mapping representation such as dm-stripe. Though we have developed this target for a specific storage device, Dell EqualLogic, we have made an effort to keep it as general purpose as possible in the hope that others may benefit. Originally developed by Jim Ramsay. Simplified by Mikulas Patocka. Signed-off-by: Jim Ramsay Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- Documentation/device-mapper/switch.txt | 126 ++++++ drivers/md/Kconfig | 14 + drivers/md/Makefile | 1 + drivers/md/dm-switch.c | 538 +++++++++++++++++++++++++ 4 files changed, 679 insertions(+) create mode 100644 Documentation/device-mapper/switch.txt create mode 100644 drivers/md/dm-switch.c diff --git a/Documentation/device-mapper/switch.txt b/Documentation/device-mapper/switch.txt new file mode 100644 index 000000000000..2fa749387be8 --- /dev/null +++ b/Documentation/device-mapper/switch.txt @@ -0,0 +1,126 @@ +dm-switch +========= + +The device-mapper switch target creates a device that supports an +arbitrary mapping of fixed-size regions of I/O across a fixed set of +paths. The path used for any specific region can be switched +dynamically by sending the target a message. + +It maps I/O to underlying block devices efficiently when there is a large +number of fixed-sized address regions but there is no simple pattern +that would allow for a compact representation of the mapping such as +dm-stripe. + +Background +---------- + +Dell EqualLogic and some other iSCSI storage arrays use a distributed +frameless architecture. In this architecture, the storage group +consists of a number of distinct storage arrays ("members") each having +independent controllers, disk storage and network adapters. When a LUN +is created it is spread across multiple members. The details of the +spreading are hidden from initiators connected to this storage system. +The storage group exposes a single target discovery portal, no matter +how many members are being used. When iSCSI sessions are created, each +session is connected to an eth port on a single member. Data to a LUN +can be sent on any iSCSI session, and if the blocks being accessed are +stored on another member the I/O will be forwarded as required. This +forwarding is invisible to the initiator. The storage layout is also +dynamic, and the blocks stored on disk may be moved from member to +member as needed to balance the load. + +This architecture simplifies the management and configuration of both +the storage group and initiators. In a multipathing configuration, it +is possible to set up multiple iSCSI sessions to use multiple network +interfaces on both the host and target to take advantage of the +increased network bandwidth. An initiator could use a simple round +robin algorithm to send I/O across all paths and let the storage array +members forward it as necessary, but there is a performance advantage to +sending data directly to the correct member. + +A device-mapper table already lets you map different regions of a +device onto different targets. However in this architecture the LUN is +spread with an address region size on the order of 10s of MBs, which +means the resulting table could have more than a million entries and +consume far too much memory. + +Using this device-mapper switch target we can now build a two-layer +device hierarchy: + + Upper Tier – Determine which array member the I/O should be sent to. + Lower Tier – Load balance amongst paths to a particular member. + +The lower tier consists of a single dm multipath device for each member. +Each of these multipath devices contains the set of paths directly to +the array member in one priority group, and leverages existing path +selectors to load balance amongst these paths. We also build a +non-preferred priority group containing paths to other array members for +failover reasons. + +The upper tier consists of a single dm-switch device. This device uses +a bitmap to look up the location of the I/O and choose the appropriate +lower tier device to route the I/O. By using a bitmap we are able to +use 4 bits for each address range in a 16 member group (which is very +large for us). This is a much denser representation than the dm table +b-tree can achieve. + +Construction Parameters +======================= + + [...] + [ ]+ + + + The number of paths across which to distribute the I/O. + + + The number of 512-byte sectors in a region. Each region can be redirected + to any of the available paths. + + + The number of optional arguments. Currently, no optional arguments + are supported and so this must be zero. + + + The block device that represents a specific path to the device. + + + The offset of the start of data on the specific (in units + of 512-byte sectors). This number is added to the sector number when + forwarding the request to the specific path. Typically it is zero. + +Messages +======== + +set_region_mappings : []: []:... + +Modify the region table by specifying which regions are redirected to +which paths. + + + The region number (region size was specified in constructor parameters). + If index is omitted, the next region (previous index + 1) is used. + Expressed in hexadecimal (WITHOUT any prefix like 0x). + + + The path number in the range 0 ... ( - 1). + Expressed in hexadecimal (WITHOUT any prefix like 0x). + +Status +====== + +No status line is reported. + +Example +======= + +Assume that you have volumes vg1/switch0 vg1/switch1 vg1/switch2 with +the same size. + +Create a switch device with 64kB region size: + dmsetup create switch --table "0 `blockdev --getsize /dev/vg1/switch0` + switch 3 128 0 /dev/vg1/switch0 0 /dev/vg1/switch1 0 /dev/vg1/switch2 0" + +Set mappings for the first 7 entries to point to devices switch0, switch1, +switch2, switch0, switch1, switch2, switch1: + dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1 diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 3bfc8f1da9fe..30b426ed744b 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -412,4 +412,18 @@ config DM_VERITY If unsure, say N. +config DM_SWITCH + tristate "Switch target support (EXPERIMENTAL)" + depends on BLK_DEV_DM + ---help--- + This device-mapper target creates a device that supports an arbitrary + mapping of fixed-size regions of I/O across a fixed set of paths. + The path used for any specific region can be switched dynamically + by sending the target a message. + + To compile this code as a module, choose M here: the module will + be called dm-switch. + + If unsure, say N. + endif # MD diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 1439fd4ad9b1..5ef78efc27f2 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o obj-$(CONFIG_DM_MULTIPATH_QL) += dm-queue-length.o obj-$(CONFIG_DM_MULTIPATH_ST) += dm-service-time.o +obj-$(CONFIG_DM_SWITCH) += dm-switch.o obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_PERSISTENT_DATA) += persistent-data/ obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c new file mode 100644 index 000000000000..ff9ac4be4721 --- /dev/null +++ b/drivers/md/dm-switch.c @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2010-2012 by Dell Inc. All rights reserved. + * Copyright (C) 2011-2013 Red Hat, Inc. + * + * This file is released under the GPL. + * + * dm-switch is a device-mapper target that maps IO to underlying block + * devices efficiently when there are a large number of fixed-sized + * address regions but there is no simple pattern to allow for a compact + * mapping representation such as dm-stripe. + */ + +#include + +#include +#include +#include + +#define DM_MSG_PREFIX "switch" + +/* + * One region_table_slot_t holds region table + * entries each of which is in size. + */ +typedef unsigned long region_table_slot_t; + +/* + * A device with the offset to its start sector. + */ +struct switch_path { + struct dm_dev *dmdev; + sector_t start; +}; + +/* + * Context block for a dm switch device. + */ +struct switch_ctx { + struct dm_target *ti; + + unsigned nr_paths; /* Number of paths in path_list. */ + + unsigned region_size; /* Region size in 512-byte sectors */ + unsigned long nr_regions; /* Number of regions making up the device */ + signed char region_size_bits; /* log2 of region_size or -1 */ + + unsigned char region_table_entry_bits; /* Number of bits in one region table entry */ + unsigned char region_entries_per_slot; /* Number of entries in one region table slot */ + signed char region_entries_per_slot_bits; /* log2 of region_entries_per_slot or -1 */ + + region_table_slot_t *region_table; /* Region table */ + + /* + * Array of dm devices to switch between. + */ + struct switch_path path_list[0]; +}; + +static struct switch_ctx *alloc_switch_ctx(struct dm_target *ti, unsigned nr_paths, + unsigned region_size) +{ + struct switch_ctx *sctx; + + sctx = kzalloc(sizeof(struct switch_ctx) + nr_paths * sizeof(struct switch_path), + GFP_KERNEL); + if (!sctx) + return NULL; + + sctx->ti = ti; + sctx->region_size = region_size; + + ti->private = sctx; + + return sctx; +} + +static int alloc_region_table(struct dm_target *ti, unsigned nr_paths) +{ + struct switch_ctx *sctx = ti->private; + sector_t nr_regions = ti->len; + sector_t nr_slots; + + if (!(sctx->region_size & (sctx->region_size - 1))) + sctx->region_size_bits = __ffs(sctx->region_size); + else + sctx->region_size_bits = -1; + + sctx->region_table_entry_bits = 1; + while (sctx->region_table_entry_bits < sizeof(region_table_slot_t) * 8 && + (region_table_slot_t)1 << sctx->region_table_entry_bits < nr_paths) + sctx->region_table_entry_bits++; + + sctx->region_entries_per_slot = (sizeof(region_table_slot_t) * 8) / sctx->region_table_entry_bits; + if (!(sctx->region_entries_per_slot & (sctx->region_entries_per_slot - 1))) + sctx->region_entries_per_slot_bits = __ffs(sctx->region_entries_per_slot); + else + sctx->region_entries_per_slot_bits = -1; + + if (sector_div(nr_regions, sctx->region_size)) + nr_regions++; + + sctx->nr_regions = nr_regions; + if (sctx->nr_regions != nr_regions || sctx->nr_regions >= ULONG_MAX) { + ti->error = "Region table too large"; + return -EINVAL; + } + + nr_slots = nr_regions; + if (sector_div(nr_slots, sctx->region_entries_per_slot)) + nr_slots++; + + if (nr_slots > ULONG_MAX / sizeof(region_table_slot_t)) { + ti->error = "Region table too large"; + return -EINVAL; + } + + sctx->region_table = vmalloc(nr_slots * sizeof(region_table_slot_t)); + if (!sctx->region_table) { + ti->error = "Cannot allocate region table"; + return -ENOMEM; + } + + return 0; +} + +static void switch_get_position(struct switch_ctx *sctx, unsigned long region_nr, + unsigned long *region_index, unsigned *bit) +{ + if (sctx->region_entries_per_slot_bits >= 0) { + *region_index = region_nr >> sctx->region_entries_per_slot_bits; + *bit = region_nr & (sctx->region_entries_per_slot - 1); + } else { + *region_index = region_nr / sctx->region_entries_per_slot; + *bit = region_nr % sctx->region_entries_per_slot; + } + + *bit *= sctx->region_table_entry_bits; +} + +/* + * Find which path to use at given offset. + */ +static unsigned switch_get_path_nr(struct switch_ctx *sctx, sector_t offset) +{ + unsigned long region_index; + unsigned bit, path_nr; + sector_t p; + + p = offset; + if (sctx->region_size_bits >= 0) + p >>= sctx->region_size_bits; + else + sector_div(p, sctx->region_size); + + switch_get_position(sctx, p, ®ion_index, &bit); + path_nr = (ACCESS_ONCE(sctx->region_table[region_index]) >> bit) & + ((1 << sctx->region_table_entry_bits) - 1); + + /* This can only happen if the processor uses non-atomic stores. */ + if (unlikely(path_nr >= sctx->nr_paths)) + path_nr = 0; + + return path_nr; +} + +static void switch_region_table_write(struct switch_ctx *sctx, unsigned long region_nr, + unsigned value) +{ + unsigned long region_index; + unsigned bit; + region_table_slot_t pte; + + switch_get_position(sctx, region_nr, ®ion_index, &bit); + + pte = sctx->region_table[region_index]; + pte &= ~((((region_table_slot_t)1 << sctx->region_table_entry_bits) - 1) << bit); + pte |= (region_table_slot_t)value << bit; + sctx->region_table[region_index] = pte; +} + +/* + * Fill the region table with an initial round robin pattern. + */ +static void initialise_region_table(struct switch_ctx *sctx) +{ + unsigned path_nr = 0; + unsigned long region_nr; + + for (region_nr = 0; region_nr < sctx->nr_regions; region_nr++) { + switch_region_table_write(sctx, region_nr, path_nr); + if (++path_nr >= sctx->nr_paths) + path_nr = 0; + } +} + +static int parse_path(struct dm_arg_set *as, struct dm_target *ti) +{ + struct switch_ctx *sctx = ti->private; + unsigned long long start; + int r; + + r = dm_get_device(ti, dm_shift_arg(as), dm_table_get_mode(ti->table), + &sctx->path_list[sctx->nr_paths].dmdev); + if (r) { + ti->error = "Device lookup failed"; + return r; + } + + if (kstrtoull(dm_shift_arg(as), 10, &start) || start != (sector_t)start) { + ti->error = "Invalid device starting offset"; + dm_put_device(ti, sctx->path_list[sctx->nr_paths].dmdev); + return -EINVAL; + } + + sctx->path_list[sctx->nr_paths].start = start; + + sctx->nr_paths++; + + return 0; +} + +/* + * Destructor: Don't free the dm_target, just the ti->private data (if any). + */ +static void switch_dtr(struct dm_target *ti) +{ + struct switch_ctx *sctx = ti->private; + + while (sctx->nr_paths--) + dm_put_device(ti, sctx->path_list[sctx->nr_paths].dmdev); + + vfree(sctx->region_table); + kfree(sctx); +} + +/* + * Constructor arguments: + * [...] + * [ ]+ + * + * Optional args are to allow for future extension: currently this + * parameter must be 0. + */ +static int switch_ctr(struct dm_target *ti, unsigned argc, char **argv) +{ + static struct dm_arg _args[] = { + {1, (KMALLOC_MAX_SIZE - sizeof(struct switch_ctx)) / sizeof(struct switch_path), "Invalid number of paths"}, + {1, UINT_MAX, "Invalid region size"}, + {0, 0, "Invalid number of optional args"}, + }; + + struct switch_ctx *sctx; + struct dm_arg_set as; + unsigned nr_paths, region_size, nr_optional_args; + int r; + + as.argc = argc; + as.argv = argv; + + r = dm_read_arg(_args, &as, &nr_paths, &ti->error); + if (r) + return -EINVAL; + + r = dm_read_arg(_args + 1, &as, ®ion_size, &ti->error); + if (r) + return r; + + r = dm_read_arg_group(_args + 2, &as, &nr_optional_args, &ti->error); + if (r) + return r; + /* parse optional arguments here, if we add any */ + + if (as.argc != nr_paths * 2) { + ti->error = "Incorrect number of path arguments"; + return -EINVAL; + } + + sctx = alloc_switch_ctx(ti, nr_paths, region_size); + if (!sctx) { + ti->error = "Cannot allocate redirection context"; + return -ENOMEM; + } + + r = dm_set_target_max_io_len(ti, region_size); + if (r) + goto error; + + while (as.argc) { + r = parse_path(&as, ti); + if (r) + goto error; + } + + r = alloc_region_table(ti, nr_paths); + if (r) + goto error; + + initialise_region_table(sctx); + + /* For UNMAP, sending the request down any path is sufficient */ + ti->num_discard_bios = 1; + + return 0; + +error: + switch_dtr(ti); + + return r; +} + +static int switch_map(struct dm_target *ti, struct bio *bio) +{ + struct switch_ctx *sctx = ti->private; + sector_t offset = dm_target_offset(ti, bio->bi_sector); + unsigned path_nr = switch_get_path_nr(sctx, offset); + + bio->bi_bdev = sctx->path_list[path_nr].dmdev->bdev; + bio->bi_sector = sctx->path_list[path_nr].start + offset; + + return DM_MAPIO_REMAPPED; +} + +/* + * We need to parse hex numbers in the message as quickly as possible. + * + * This table-based hex parser improves performance. + * It improves a time to load 1000000 entries compared to the condition-based + * parser. + * table-based parser condition-based parser + * PA-RISC 0.29s 0.31s + * Opteron 0.0495s 0.0498s + */ +static const unsigned char hex_table[256] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, +255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 +}; + +static __always_inline unsigned long parse_hex(const char **string) +{ + unsigned char d; + unsigned long r = 0; + + while ((d = hex_table[(unsigned char)**string]) < 16) { + r = (r << 4) | d; + (*string)++; + } + + return r; +} + +static int process_set_region_mappings(struct switch_ctx *sctx, + unsigned argc, char **argv) +{ + unsigned i; + unsigned long region_index = 0; + + for (i = 1; i < argc; i++) { + unsigned long path_nr; + const char *string = argv[i]; + + if (*string == ':') + region_index++; + else { + region_index = parse_hex(&string); + if (unlikely(*string != ':')) { + DMWARN("invalid set_region_mappings argument: '%s'", argv[i]); + return -EINVAL; + } + } + + string++; + if (unlikely(!*string)) { + DMWARN("invalid set_region_mappings argument: '%s'", argv[i]); + return -EINVAL; + } + + path_nr = parse_hex(&string); + if (unlikely(*string)) { + DMWARN("invalid set_region_mappings argument: '%s'", argv[i]); + return -EINVAL; + } + if (unlikely(region_index >= sctx->nr_regions)) { + DMWARN("invalid set_region_mappings region number: %lu >= %lu", region_index, sctx->nr_regions); + return -EINVAL; + } + if (unlikely(path_nr >= sctx->nr_paths)) { + DMWARN("invalid set_region_mappings device: %lu >= %u", path_nr, sctx->nr_paths); + return -EINVAL; + } + + switch_region_table_write(sctx, region_index, path_nr); + } + + return 0; +} + +/* + * Messages are processed one-at-a-time. + * + * Only set_region_mappings is supported. + */ +static int switch_message(struct dm_target *ti, unsigned argc, char **argv) +{ + static DEFINE_MUTEX(message_mutex); + + struct switch_ctx *sctx = ti->private; + int r = -EINVAL; + + mutex_lock(&message_mutex); + + if (!strcasecmp(argv[0], "set_region_mappings")) + r = process_set_region_mappings(sctx, argc, argv); + else + DMWARN("Unrecognised message received."); + + mutex_unlock(&message_mutex); + + return r; +} + +static void switch_status(struct dm_target *ti, status_type_t type, + unsigned status_flags, char *result, unsigned maxlen) +{ + struct switch_ctx *sctx = ti->private; + unsigned sz = 0; + int path_nr; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + DMEMIT("%u %u 0", sctx->nr_paths, sctx->region_size); + for (path_nr = 0; path_nr < sctx->nr_paths; path_nr++) + DMEMIT(" %s %llu", sctx->path_list[path_nr].dmdev->name, + (unsigned long long)sctx->path_list[path_nr].start); + break; + } +} + +/* + * Switch ioctl: + * + * Passthrough all ioctls to the path for sector 0 + */ +static int switch_ioctl(struct dm_target *ti, unsigned cmd, + unsigned long arg) +{ + struct switch_ctx *sctx = ti->private; + struct block_device *bdev; + fmode_t mode; + unsigned path_nr; + int r = 0; + + path_nr = switch_get_path_nr(sctx, 0); + + bdev = sctx->path_list[path_nr].dmdev->bdev; + mode = sctx->path_list[path_nr].dmdev->mode; + + /* + * Only pass ioctls through if the device sizes match exactly. + */ + if (ti->len + sctx->path_list[path_nr].start != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) + r = scsi_verify_blk_ioctl(NULL, cmd); + + return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); +} + +static int switch_iterate_devices(struct dm_target *ti, + iterate_devices_callout_fn fn, void *data) +{ + struct switch_ctx *sctx = ti->private; + int path_nr; + int r; + + for (path_nr = 0; path_nr < sctx->nr_paths; path_nr++) { + r = fn(ti, sctx->path_list[path_nr].dmdev, + sctx->path_list[path_nr].start, ti->len, data); + if (r) + return r; + } + + return 0; +} + +static struct target_type switch_target = { + .name = "switch", + .version = {1, 0, 0}, + .module = THIS_MODULE, + .ctr = switch_ctr, + .dtr = switch_dtr, + .map = switch_map, + .message = switch_message, + .status = switch_status, + .ioctl = switch_ioctl, + .iterate_devices = switch_iterate_devices, +}; + +static int __init dm_switch_init(void) +{ + int r; + + r = dm_register_target(&switch_target); + if (r < 0) + DMERR("dm_register_target() failed %d", r); + + return r; +} + +static void __exit dm_switch_exit(void) +{ + dm_unregister_target(&switch_target); +} + +module_init(dm_switch_init); +module_exit(dm_switch_exit); + +MODULE_DESCRIPTION(DM_NAME " dynamic path switching target"); +MODULE_AUTHOR("Kevin D. O'Kelley "); +MODULE_AUTHOR("Narendran Ganapathy "); +MODULE_AUTHOR("Jim Ramsay "); +MODULE_AUTHOR("Mikulas Patocka "); +MODULE_LICENSE("GPL"); -- GitLab From 076bb0c82a44fbe46fe2c8527a5b5b64b69f679d Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Wed, 10 Jul 2013 17:13:17 +0300 Subject: [PATCH 2605/2900] net: rename include/net/ll_poll.h to include/net/busy_poll.h Rename the file and correct all the places where it is included. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 +- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +- fs/select.c | 2 +- include/net/{ll_poll.h => busy_poll.h} | 0 net/core/datagram.c | 2 +- net/core/sock.c | 2 +- net/core/sysctl_net_core.c | 2 +- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udp.c | 2 +- net/socket.c | 2 +- 15 files changed, 14 insertions(+), 14 deletions(-) rename include/net/{ll_poll.h => busy_poll.h} (100%) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ec3aa1d451e8..05b6b4e8b073 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include "bnx2x_cmn.h" #include "bnx2x_init.h" diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index fb098b46c6a6..7be725cdfea8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -52,7 +52,7 @@ #include #endif -#include +#include #ifdef CONFIG_NET_LL_RX_POLL #define LL_EXTENDED_STATS diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index caf204770569..0fb2438dc2c7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 76997b93fdfe..90746d37ac9b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -31,7 +31,7 @@ * */ -#include +#include #include #include #include diff --git a/fs/select.c b/fs/select.c index f9f49c40cfd4..35d4adc749d9 100644 --- a/fs/select.c +++ b/fs/select.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include diff --git a/include/net/ll_poll.h b/include/net/busy_poll.h similarity index 100% rename from include/net/ll_poll.h rename to include/net/busy_poll.h diff --git a/net/core/datagram.c b/net/core/datagram.c index 6e9ab31e457e..8ab48cd89559 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include /* * Is a socket 'connection oriented' ? diff --git a/net/core/sock.c b/net/core/sock.c index ab06b719f5b1..9bfe83f4d670 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -139,7 +139,7 @@ #include #endif -#include +#include static DEFINE_MUTEX(proto_list_mutex); static LIST_HEAD(proto_list); diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index afc677eadd93..1a298cb3daee 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include static int one = 1; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 15cbfa94bd8e..5423223e93c2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -279,7 +279,7 @@ #include #include -#include +#include int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 35675e46aff8..3a261b41a00c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -75,7 +75,7 @@ #include #include #include -#include +#include #include #include diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6b270e53c207..bcc0ff2c16da 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -109,7 +109,7 @@ #include #include #include -#include +#include #include "udp_impl.h" struct udp_table udp_table __read_mostly; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5cffa5c3e6b8..345bd92d4ddb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b6f31437a1f8..40e72034da07 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include diff --git a/net/socket.c b/net/socket.c index 45afa648364a..6a3e9a3f50ad 100644 --- a/net/socket.c +++ b/net/socket.c @@ -104,7 +104,7 @@ #include #include #include -#include +#include #ifdef CONFIG_NET_LL_RX_POLL unsigned int sysctl_net_ll_read __read_mostly; -- GitLab From 8b80cda536ea9bceec0364e897868a30ee13b992 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Wed, 10 Jul 2013 17:13:26 +0300 Subject: [PATCH 2606/2900] net: rename ll methods to busy-poll Rename ndo_ll_poll to ndo_busy_poll. Rename sk_mark_ll to sk_mark_napi_id. Rename skb_mark_ll to skb_mark_napi_id. Correct all useres of these functions. Update comments and defines in include/net/busy_poll.h Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- .../net/ethernet/mellanox/mlx4/en_netdev.c | 2 +- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 2 +- include/linux/netdevice.h | 2 +- include/net/busy_poll.h | 22 ++++++++++--------- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udp.c | 2 +- 11 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 05b6b4e8b073..3353efe79194 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -990,7 +990,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), le16_to_cpu(cqe_fp->vlan_tag)); - skb_mark_ll(skb, &fp->napi); + skb_mark_napi_id(skb, &fp->napi); if (bnx2x_fp_ll_polling(fp)) netif_receive_skb(skb); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 15a528bda87c..e5da07858a2f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12027,7 +12027,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { #endif #ifdef CONFIG_NET_LL_RX_POLL - .ndo_ll_poll = bnx2x_low_latency_recv, + .ndo_busy_poll = bnx2x_low_latency_recv, #endif }; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 047ebaaf0141..bad8f14b1941 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1978,7 +1978,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, } #endif /* IXGBE_FCOE */ - skb_mark_ll(skb, &q_vector->napi); + skb_mark_napi_id(skb, &q_vector->napi); ixgbe_rx_skb(q_vector, skb); /* update budget accounting */ @@ -7228,7 +7228,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_poll_controller = ixgbe_netpoll, #endif #ifdef CONFIG_NET_LL_RX_POLL - .ndo_ll_poll = ixgbe_low_latency_recv, + .ndo_busy_poll = ixgbe_low_latency_recv, #endif #ifdef IXGBE_FCOE .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 0fb2438dc2c7..5eac871399d8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2141,7 +2141,7 @@ static const struct net_device_ops mlx4_netdev_ops = { .ndo_rx_flow_steer = mlx4_en_filter_rfs, #endif #ifdef CONFIG_NET_LL_RX_POLL - .ndo_ll_poll = mlx4_en_low_latency_recv, + .ndo_busy_poll = mlx4_en_low_latency_recv, #endif }; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 90746d37ac9b..dec455c8f627 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -767,7 +767,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud timestamp); } - skb_mark_ll(skb, &cq->napi); + skb_mark_napi_id(skb, &cq->napi); /* Push it up the stack */ netif_receive_skb(skb); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index bb82871b8494..0741a1e919a5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -974,7 +974,7 @@ struct net_device_ops { void (*ndo_netpoll_cleanup)(struct net_device *dev); #endif #ifdef CONFIG_NET_LL_RX_POLL - int (*ndo_ll_poll)(struct napi_struct *dev); + int (*ndo_busy_poll)(struct napi_struct *dev); #endif int (*ndo_set_vf_mac)(struct net_device *dev, int queue, u8 *mac); diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 76f034087743..4ff71908fd42 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h @@ -1,5 +1,5 @@ /* - * Low Latency Sockets + * net busy poll support * Copyright(c) 2013 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it @@ -21,8 +21,8 @@ * e1000-devel Mailing List */ -#ifndef _LINUX_NET_LL_POLL_H -#define _LINUX_NET_LL_POLL_H +#ifndef _LINUX_NET_BUSY_POLL_H +#define _LINUX_NET_BUSY_POLL_H #include #include @@ -110,11 +110,11 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock) goto out; ops = napi->dev->netdev_ops; - if (!ops->ndo_ll_poll) + if (!ops->ndo_busy_poll) goto out; do { - rc = ops->ndo_ll_poll(napi); + rc = ops->ndo_busy_poll(napi); if (rc == LL_FLUSH_FAILED) break; /* permanent failure */ @@ -134,13 +134,14 @@ static inline bool sk_busy_loop(struct sock *sk, int nonblock) } /* used in the NIC receive handler to mark the skb */ -static inline void skb_mark_ll(struct sk_buff *skb, struct napi_struct *napi) +static inline void skb_mark_napi_id(struct sk_buff *skb, + struct napi_struct *napi) { skb->napi_id = napi->napi_id; } /* used in the protocol hanlder to propagate the napi_id to the socket */ -static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) +static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb) { sk->sk_napi_id = skb->napi_id; } @@ -166,11 +167,12 @@ static inline bool sk_busy_poll(struct sock *sk, int nonblock) return false; } -static inline void skb_mark_ll(struct sk_buff *skb, struct napi_struct *napi) +static inline void skb_mark_napi_id(struct sk_buff *skb, + struct napi_struct *napi) { } -static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb) +static inline void sk_mark_napi_id(struct sock *sk, struct sk_buff *skb) { } @@ -180,4 +182,4 @@ static inline bool busy_loop_timeout(unsigned long end_time) } #endif /* CONFIG_NET_LL_RX_POLL */ -#endif /* _LINUX_NET_LL_POLL_H */ +#endif /* _LINUX_NET_BUSY_POLL_H */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3a261b41a00c..b299da5ff499 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1994,7 +1994,7 @@ int tcp_v4_rcv(struct sk_buff *skb) if (sk_filter(sk, skb)) goto discard_and_relse; - sk_mark_ll(sk, skb); + sk_mark_napi_id(sk, skb); skb->dev = NULL; bh_lock_sock_nested(sk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index bcc0ff2c16da..a0d7151ffbd9 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1713,7 +1713,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (sk != NULL) { int ret; - sk_mark_ll(sk, skb); + sk_mark_napi_id(sk, skb); ret = udp_queue_rcv_skb(sk, skb); sock_put(sk); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 345bd92d4ddb..6e1649d58533 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1499,7 +1499,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (sk_filter(sk, skb)) goto discard_and_relse; - sk_mark_ll(sk, skb); + sk_mark_napi_id(sk, skb); skb->dev = NULL; bh_lock_sock_nested(sk); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 40e72034da07..f4058150262b 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -844,7 +844,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (sk != NULL) { int ret; - sk_mark_ll(sk, skb); + sk_mark_napi_id(sk, skb); ret = udpv6_queue_rcv_skb(sk, skb); sock_put(sk); -- GitLab From 64b0dc517ea1b35d02565a779e6cb77ae9045685 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Wed, 10 Jul 2013 17:13:36 +0300 Subject: [PATCH 2607/2900] net: rename busy poll socket op and globals Rename LL_SO to BUSY_POLL_SO Rename sysctl_net_ll_{read,poll} to sysctl_busy_{read,poll} Fix up users of these variables. Fix documentation for sysctl. a patch for the socket.7 man page will follow separately, because of limitations of my mail setup. Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller --- Documentation/sysctl/net.txt | 17 +++++++++-------- arch/alpha/include/uapi/asm/socket.h | 2 +- arch/avr32/include/uapi/asm/socket.h | 2 +- arch/cris/include/uapi/asm/socket.h | 2 +- arch/frv/include/uapi/asm/socket.h | 2 +- arch/h8300/include/uapi/asm/socket.h | 2 +- arch/ia64/include/uapi/asm/socket.h | 2 +- arch/m32r/include/uapi/asm/socket.h | 2 +- arch/mips/include/uapi/asm/socket.h | 2 +- arch/mn10300/include/uapi/asm/socket.h | 2 +- arch/parisc/include/uapi/asm/socket.h | 2 +- arch/powerpc/include/uapi/asm/socket.h | 2 +- arch/s390/include/uapi/asm/socket.h | 2 +- arch/sparc/include/uapi/asm/socket.h | 2 +- arch/xtensa/include/uapi/asm/socket.h | 2 +- include/net/busy_poll.h | 8 ++++---- include/uapi/asm-generic/socket.h | 2 +- net/core/sock.c | 6 +++--- net/core/sysctl_net_core.c | 8 ++++---- net/socket.c | 4 ++-- 20 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index d69e14c9002c..1c15043aaee4 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -50,26 +50,27 @@ The maximum number of packets that kernel can handle on a NAPI interrupt, it's a Per-CPU variable. Default: 64 -low_latency_read +busy_read ---------------- Low latency busy poll timeout for socket reads. (needs CONFIG_NET_LL_RX_POLL) Approximate time in us to busy loop waiting for packets on the device queue. -This sets the default value of the SO_LL socket option. -Can be set or overridden per socket by setting socket option SO_LL, which is -the preferred method of enabling. -If you need to enable the feature globally via sysctl, a value of 50 is recommended. +This sets the default value of the SO_BUSY_POLL socket option. +Can be set or overridden per socket by setting socket option SO_BUSY_POLL, +which is the preferred method of enabling. If you need to enable the feature +globally via sysctl, a value of 50 is recommended. Will increase power usage. Default: 0 (off) -low_latency_poll +busy_poll ---------------- Low latency busy poll timeout for poll and select. (needs CONFIG_NET_LL_RX_POLL) Approximate time in us to busy loop waiting for events. Recommended value depends on the number of sockets you poll on. For several sockets 50, for several hundreds 100. For more than that you probably want to use epoll. -Note that only sockets with SO_LL set will be busy polled, so you want to either -selectively set SO_LL on those sockets or set sysctl.net.low_latency_read globally. +Note that only sockets with SO_BUSY_POLL set will be busy polled, +so you want to either selectively set SO_BUSY_POLL on those sockets or set +sysctl.net.busy_read globally. Will increase power usage. Default: 0 (off) diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 4885825e498d..467de010ea7e 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -81,6 +81,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h index 79b61798ebf8..11c4259c62fb 100644 --- a/arch/avr32/include/uapi/asm/socket.h +++ b/arch/avr32/include/uapi/asm/socket.h @@ -74,6 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* __ASM_AVR32_SOCKET_H */ diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h index 47b1ec55092d..eb723e51554e 100644 --- a/arch/cris/include/uapi/asm/socket.h +++ b/arch/cris/include/uapi/asm/socket.h @@ -76,7 +76,7 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_SOCKET_H */ diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h index dbc08520f22c..f0cb1c341163 100644 --- a/arch/frv/include/uapi/asm/socket.h +++ b/arch/frv/include/uapi/asm/socket.h @@ -74,7 +74,7 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_SOCKET_H */ diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h index a38d38a6520b..9490758c5e2b 100644 --- a/arch/h8300/include/uapi/asm/socket.h +++ b/arch/h8300/include/uapi/asm/socket.h @@ -74,6 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_SOCKET_H */ diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h index d3358b760681..556d0701a155 100644 --- a/arch/ia64/include/uapi/asm/socket.h +++ b/arch/ia64/include/uapi/asm/socket.h @@ -83,6 +83,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_IA64_SOCKET_H */ diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h index 44aaf4639a4a..24be7c8da86a 100644 --- a/arch/m32r/include/uapi/asm/socket.h +++ b/arch/m32r/include/uapi/asm/socket.h @@ -74,6 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_M32R_SOCKET_H */ diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 6a07992ba6c6..61c01f054d1b 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -92,6 +92,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _UAPI_ASM_SOCKET_H */ diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h index db80fd3e398b..e2a2b203eb00 100644 --- a/arch/mn10300/include/uapi/asm/socket.h +++ b/arch/mn10300/include/uapi/asm/socket.h @@ -74,6 +74,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_SOCKET_H */ diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f866fff9a004..71700e636a8e 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -73,7 +73,7 @@ #define SO_SELECT_ERR_QUEUE 0x4026 -#define SO_LL 0x4027 +#define SO_BUSY_POLL 0x4027 /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index 405fb09bda94..a6d74467c9ed 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h @@ -81,6 +81,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index 0c5105fbaaf3..92494494692e 100644 --- a/arch/s390/include/uapi/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h @@ -80,6 +80,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _ASM_SOCKET_H */ diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index b46c3fa0b265..4e1d66c3ce71 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -70,7 +70,7 @@ #define SO_SELECT_ERR_QUEUE 0x0029 -#define SO_LL 0x0030 +#define SO_BUSY_POLL 0x0030 /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index b21ace4fc9ba..c114483010c1 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h @@ -85,6 +85,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* _XTENSA_SOCKET_H */ diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h index 4ff71908fd42..a14339c2985f 100644 --- a/include/net/busy_poll.h +++ b/include/net/busy_poll.h @@ -30,8 +30,8 @@ #ifdef CONFIG_NET_LL_RX_POLL struct napi_struct; -extern unsigned int sysctl_net_ll_read __read_mostly; -extern unsigned int sysctl_net_ll_poll __read_mostly; +extern unsigned int sysctl_net_busy_read __read_mostly; +extern unsigned int sysctl_net_busy_poll __read_mostly; /* return values from ndo_ll_poll */ #define LL_FLUSH_FAILED -1 @@ -39,7 +39,7 @@ extern unsigned int sysctl_net_ll_poll __read_mostly; static inline bool net_busy_loop_on(void) { - return sysctl_net_ll_poll; + return sysctl_net_busy_poll; } /* a wrapper to make debug_smp_processor_id() happy @@ -72,7 +72,7 @@ static inline unsigned long sk_busy_loop_end_time(struct sock *sk) /* in poll/select we use the global sysctl_net_ll_poll value */ static inline unsigned long busy_loop_end_time(void) { - return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_ll_poll); + return busy_loop_us_clock() + ACCESS_ONCE(sysctl_net_busy_poll); } static inline bool sk_can_busy_loop(struct sock *sk) diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h index ca3a20d772ac..f04b69b6abf2 100644 --- a/include/uapi/asm-generic/socket.h +++ b/include/uapi/asm-generic/socket.h @@ -76,6 +76,6 @@ #define SO_SELECT_ERR_QUEUE 45 -#define SO_LL 46 +#define SO_BUSY_POLL 46 #endif /* __ASM_GENERIC_SOCKET_H */ diff --git a/net/core/sock.c b/net/core/sock.c index 9bfe83f4d670..548d716c5f62 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -901,7 +901,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; #ifdef CONFIG_NET_LL_RX_POLL - case SO_LL: + case SO_BUSY_POLL: /* allow unprivileged users to decrease the value */ if ((val > sk->sk_ll_usec) && !capable(CAP_NET_ADMIN)) ret = -EPERM; @@ -1171,7 +1171,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, break; #ifdef CONFIG_NET_LL_RX_POLL - case SO_LL: + case SO_BUSY_POLL: v.val = sk->sk_ll_usec; break; #endif @@ -2294,7 +2294,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) #ifdef CONFIG_NET_LL_RX_POLL sk->sk_napi_id = 0; - sk->sk_ll_usec = sysctl_net_ll_read; + sk->sk_ll_usec = sysctl_net_busy_read; #endif /* diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 1a298cb3daee..660968616637 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -300,15 +300,15 @@ static struct ctl_table net_core_table[] = { #endif /* CONFIG_NET_FLOW_LIMIT */ #ifdef CONFIG_NET_LL_RX_POLL { - .procname = "low_latency_poll", - .data = &sysctl_net_ll_poll, + .procname = "busy_poll", + .data = &sysctl_net_busy_poll, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec }, { - .procname = "low_latency_read", - .data = &sysctl_net_ll_read, + .procname = "busy_read", + .data = &sysctl_net_busy_read, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = proc_dointvec diff --git a/net/socket.c b/net/socket.c index 6a3e9a3f50ad..829b460acb87 100644 --- a/net/socket.c +++ b/net/socket.c @@ -107,8 +107,8 @@ #include #ifdef CONFIG_NET_LL_RX_POLL -unsigned int sysctl_net_ll_read __read_mostly; -unsigned int sysctl_net_ll_poll __read_mostly; +unsigned int sysctl_net_busy_read __read_mostly; +unsigned int sysctl_net_busy_poll __read_mostly; #endif static int sock_no_open(struct inode *irrelevant, struct file *dontcare); -- GitLab From 45dd95c443c2d81d8d41e55afeafd4c61042fa76 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 8 Jul 2013 17:09:01 +0800 Subject: [PATCH 2608/2900] r8169: add a new chip for RTL8411 Add a new chip for RTL8411 series. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 67 ++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 393f961a013c..4106a743ca74 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -46,6 +46,7 @@ #define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" #define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw" #define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" +#define FIRMWARE_8411_2 "rtl_nic/rtl8411-2.fw" #define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw" #define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw" #define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw" @@ -144,6 +145,7 @@ enum mac_version { RTL_GIGA_MAC_VER_41, RTL_GIGA_MAC_VER_42, RTL_GIGA_MAC_VER_43, + RTL_GIGA_MAC_VER_44, RTL_GIGA_MAC_NONE = 0xff, }; @@ -276,6 +278,9 @@ static const struct { [RTL_GIGA_MAC_VER_43] = _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_2, JUMBO_1K, true), + [RTL_GIGA_MAC_VER_44] = + _R("RTL8411", RTL_TD_1, FIRMWARE_8411_2, + JUMBO_9K, false), }; #undef _R @@ -394,6 +399,7 @@ enum rtl8168_8101_registers { #define CSIAR_FUNC_CARD 0x00000000 #define CSIAR_FUNC_SDIO 0x00010000 #define CSIAR_FUNC_NIC 0x00020000 +#define CSIAR_FUNC_NIC2 0x00010000 PMCH = 0x6f, EPHYAR = 0x80, #define EPHYAR_FLAG 0x80000000 @@ -826,6 +832,7 @@ MODULE_FIRMWARE(FIRMWARE_8168F_1); MODULE_FIRMWARE(FIRMWARE_8168F_2); MODULE_FIRMWARE(FIRMWARE_8402_1); MODULE_FIRMWARE(FIRMWARE_8411_1); +MODULE_FIRMWARE(FIRMWARE_8411_2); MODULE_FIRMWARE(FIRMWARE_8106E_1); MODULE_FIRMWARE(FIRMWARE_8106E_2); MODULE_FIRMWARE(FIRMWARE_8168G_2); @@ -2051,6 +2058,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, int mac_version; } mac_info[] = { /* 8168G family. */ + { 0x7cf00000, 0x5c800000, RTL_GIGA_MAC_VER_44 }, { 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 }, { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 }, { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 }, @@ -3651,6 +3659,7 @@ static void rtl_hw_phy_config(struct net_device *dev) break; case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: rtl8168g_2_hw_phy_config(tp); break; @@ -3863,6 +3872,7 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: ops->write = r8168g_mdio_write; ops->read = r8168g_mdio_read; break; @@ -3916,6 +3926,7 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: RTL_W32(RxConfig, RTL_R32(RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); break; @@ -4178,6 +4189,7 @@ static void rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_40: case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: + case RTL_GIGA_MAC_VER_44: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; @@ -4224,6 +4236,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF); break; default: @@ -4384,6 +4397,7 @@ static void rtl_init_jumbo_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: default: ops->disable = NULL; ops->enable = NULL; @@ -4493,6 +4507,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) tp->mac_version == RTL_GIGA_MAC_VER_41 || tp->mac_version == RTL_GIGA_MAC_VER_42 || tp->mac_version == RTL_GIGA_MAC_VER_43 || + tp->mac_version == RTL_GIGA_MAC_VER_44 || tp->mac_version == RTL_GIGA_MAC_VER_38) { RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); @@ -4782,6 +4797,29 @@ static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) RTL_R32(CSIDR) : ~0; } +static void r8411_csi_write(struct rtl8169_private *tp, int addr, int value) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W32(CSIDR, value); + RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | + CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | + CSIAR_FUNC_NIC2); + + rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); +} + +static u32 r8411_csi_read(struct rtl8169_private *tp, int addr) +{ + void __iomem *ioaddr = tp->mmio_addr; + + RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC2 | + CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); + + return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? + RTL_R32(CSIDR) : ~0; +} + static void rtl_init_csi_ops(struct rtl8169_private *tp) { struct csi_ops *ops = &tp->csi_ops; @@ -4811,6 +4849,11 @@ static void rtl_init_csi_ops(struct rtl8169_private *tp) ops->read = r8402_csi_read; break; + case RTL_GIGA_MAC_VER_44: + ops->write = r8411_csi_write; + ops->read = r8411_csi_read; + break; + default: ops->write = r8169_csi_write; ops->read = r8169_csi_read; @@ -5255,6 +5298,25 @@ static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8168g_2, ARRAY_SIZE(e_info_8168g_2)); } +static void rtl_hw_start_8411_2(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + static const struct ephy_info e_info_8411_2[] = { + { 0x00, 0x0000, 0x0008 }, + { 0x0c, 0x3df0, 0x0200 }, + { 0x0f, 0xffff, 0x5200 }, + { 0x19, 0x0020, 0x0000 }, + { 0x1e, 0x0000, 0x2000 } + }; + + rtl_hw_start_8168g_1(tp); + + /* disable aspm and clock request before access ephy */ + RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); + RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); + rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2)); +} + static void rtl_hw_start_8168(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); @@ -5361,6 +5423,10 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168g_2(tp); break; + case RTL_GIGA_MAC_VER_44: + rtl_hw_start_8411_2(tp); + break; + default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); @@ -6877,6 +6943,7 @@ static void rtl_hw_initialize(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_41: case RTL_GIGA_MAC_VER_42: case RTL_GIGA_MAC_VER_43: + case RTL_GIGA_MAC_VER_44: rtl_hw_init_8168g(tp); break; -- GitLab From 4e2e2770b1529edc5849c86b29a6febe27e2f083 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 10 Jul 2013 16:04:55 -0700 Subject: [PATCH 2609/2900] zbud: add to mm/ zbud is an special purpose allocator for storing compressed pages. It is designed to store up to two compressed pages per physical page. While this design limits storage density, it has simple and deterministic reclaim properties that make it preferable to a higher density approach when reclaim will be used. zbud works by storing compressed pages, or "zpages", together in pairs in a single memory page called a "zbud page". The first buddy is "left justifed" at the beginning of the zbud page, and the last buddy is "right justified" at the end of the zbud page. The benefit is that if either buddy is freed, the freed buddy space, coalesced with whatever slack space that existed between the buddies, results in the largest possible free region within the zbud page. zbud also provides an attractive lower bound on density. The ratio of zpages to zbud pages can not be less than 1. This ensures that zbud can never "do harm" by using more pages to store zpages than the uncompressed zpages would have used on their own. This implementation is a rewrite of the zbud allocator internally used by zcache in the driver/staging tree. The rewrite was necessary to remove some of the zcache specific elements that were ingrained throughout and provide a generic allocation interface that can later be used by zsmalloc and others. This patch adds zbud to mm/ for later use by zswap. Signed-off-by: Seth Jennings Acked-by: Rik van Riel Cc: Greg Kroah-Hartman Cc: Nitin Gupta Cc: Minchan Kim Cc: Konrad Rzeszutek Wilk Cc: Dan Magenheimer Cc: Robert Jennings Cc: Jenifer Hopper Cc: Mel Gorman Cc: Johannes Weiner Cc: Larry Woodman Cc: Benjamin Herrenschmidt Cc: Dave Hansen Cc: Joe Perches Cc: Joonsoo Kim Cc: Cody P Schafer Cc: Hugh Dickens Cc: Paul Mackerras Cc: Bob Liu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/zbud.h | 22 ++ mm/Kconfig | 10 + mm/Makefile | 1 + mm/zbud.c | 527 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 560 insertions(+) create mode 100644 include/linux/zbud.h create mode 100644 mm/zbud.c diff --git a/include/linux/zbud.h b/include/linux/zbud.h new file mode 100644 index 000000000000..2571a5cfa5fc --- /dev/null +++ b/include/linux/zbud.h @@ -0,0 +1,22 @@ +#ifndef _ZBUD_H_ +#define _ZBUD_H_ + +#include + +struct zbud_pool; + +struct zbud_ops { + int (*evict)(struct zbud_pool *pool, unsigned long handle); +}; + +struct zbud_pool *zbud_create_pool(gfp_t gfp, struct zbud_ops *ops); +void zbud_destroy_pool(struct zbud_pool *pool); +int zbud_alloc(struct zbud_pool *pool, int size, gfp_t gfp, + unsigned long *handle); +void zbud_free(struct zbud_pool *pool, unsigned long handle); +int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries); +void *zbud_map(struct zbud_pool *pool, unsigned long handle); +void zbud_unmap(struct zbud_pool *pool, unsigned long handle); +u64 zbud_get_pool_size(struct zbud_pool *pool); + +#endif /* _ZBUD_H_ */ diff --git a/mm/Kconfig b/mm/Kconfig index 7e28ecfa8aa4..45503ed5f3aa 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -478,6 +478,16 @@ config FRONTSWAP If unsure, say Y to enable frontswap. +config ZBUD + tristate + default n + help + A special purpose allocator for storing compressed pages. + It is designed to store up to two compressed pages per physical + page. While this design limits storage density, it has simple and + deterministic reclaim properties that make it preferable to a higher + density approach when reclaim will be used. + config MEM_SOFT_DIRTY bool "Track memory changes" depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY diff --git a/mm/Makefile b/mm/Makefile index 72c5acb9345f..95f0197ce3d3 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o obj-$(CONFIG_CLEANCACHE) += cleancache.o obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o +obj-$(CONFIG_ZBUD) += zbud.o diff --git a/mm/zbud.c b/mm/zbud.c new file mode 100644 index 000000000000..9bb4710e3589 --- /dev/null +++ b/mm/zbud.c @@ -0,0 +1,527 @@ +/* + * zbud.c + * + * Copyright (C) 2013, Seth Jennings, IBM + * + * Concepts based on zcache internal zbud allocator by Dan Magenheimer. + * + * zbud is an special purpose allocator for storing compressed pages. Contrary + * to what its name may suggest, zbud is not a buddy allocator, but rather an + * allocator that "buddies" two compressed pages together in a single memory + * page. + * + * While this design limits storage density, it has simple and deterministic + * reclaim properties that make it preferable to a higher density approach when + * reclaim will be used. + * + * zbud works by storing compressed pages, or "zpages", together in pairs in a + * single memory page called a "zbud page". The first buddy is "left + * justifed" at the beginning of the zbud page, and the last buddy is "right + * justified" at the end of the zbud page. The benefit is that if either + * buddy is freed, the freed buddy space, coalesced with whatever slack space + * that existed between the buddies, results in the largest possible free region + * within the zbud page. + * + * zbud also provides an attractive lower bound on density. The ratio of zpages + * to zbud pages can not be less than 1. This ensures that zbud can never "do + * harm" by using more pages to store zpages than the uncompressed zpages would + * have used on their own. + * + * zbud pages are divided into "chunks". The size of the chunks is fixed at + * compile time and determined by NCHUNKS_ORDER below. Dividing zbud pages + * into chunks allows organizing unbuddied zbud pages into a manageable number + * of unbuddied lists according to the number of free chunks available in the + * zbud page. + * + * The zbud API differs from that of conventional allocators in that the + * allocation function, zbud_alloc(), returns an opaque handle to the user, + * not a dereferenceable pointer. The user must map the handle using + * zbud_map() in order to get a usable pointer by which to access the + * allocation data and unmap the handle with zbud_unmap() when operations + * on the allocation data are complete. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +/***************** + * Structures +*****************/ +/* + * NCHUNKS_ORDER determines the internal allocation granularity, effectively + * adjusting internal fragmentation. It also determines the number of + * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the + * allocation granularity will be in chunks of size PAGE_SIZE/64, and there + * will be 64 freelists per pool. + */ +#define NCHUNKS_ORDER 6 + +#define CHUNK_SHIFT (PAGE_SHIFT - NCHUNKS_ORDER) +#define CHUNK_SIZE (1 << CHUNK_SHIFT) +#define NCHUNKS (PAGE_SIZE >> CHUNK_SHIFT) +#define ZHDR_SIZE_ALIGNED CHUNK_SIZE + +/** + * struct zbud_pool - stores metadata for each zbud pool + * @lock: protects all pool fields and first|last_chunk fields of any + * zbud page in the pool + * @unbuddied: array of lists tracking zbud pages that only contain one buddy; + * the lists each zbud page is added to depends on the size of + * its free region. + * @buddied: list tracking the zbud pages that contain two buddies; + * these zbud pages are full + * @lru: list tracking the zbud pages in LRU order by most recently + * added buddy. + * @pages_nr: number of zbud pages in the pool. + * @ops: pointer to a structure of user defined operations specified at + * pool creation time. + * + * This structure is allocated at pool creation time and maintains metadata + * pertaining to a particular zbud pool. + */ +struct zbud_pool { + spinlock_t lock; + struct list_head unbuddied[NCHUNKS]; + struct list_head buddied; + struct list_head lru; + u64 pages_nr; + struct zbud_ops *ops; +}; + +/* + * struct zbud_header - zbud page metadata occupying the first chunk of each + * zbud page. + * @buddy: links the zbud page into the unbuddied/buddied lists in the pool + * @lru: links the zbud page into the lru list in the pool + * @first_chunks: the size of the first buddy in chunks, 0 if free + * @last_chunks: the size of the last buddy in chunks, 0 if free + */ +struct zbud_header { + struct list_head buddy; + struct list_head lru; + unsigned int first_chunks; + unsigned int last_chunks; + bool under_reclaim; +}; + +/***************** + * Helpers +*****************/ +/* Just to make the code easier to read */ +enum buddy { + FIRST, + LAST +}; + +/* Converts an allocation size in bytes to size in zbud chunks */ +static int size_to_chunks(int size) +{ + return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; +} + +#define for_each_unbuddied_list(_iter, _begin) \ + for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) + +/* Initializes the zbud header of a newly allocated zbud page */ +static struct zbud_header *init_zbud_page(struct page *page) +{ + struct zbud_header *zhdr = page_address(page); + zhdr->first_chunks = 0; + zhdr->last_chunks = 0; + INIT_LIST_HEAD(&zhdr->buddy); + INIT_LIST_HEAD(&zhdr->lru); + zhdr->under_reclaim = 0; + return zhdr; +} + +/* Resets the struct page fields and frees the page */ +static void free_zbud_page(struct zbud_header *zhdr) +{ + __free_page(virt_to_page(zhdr)); +} + +/* + * Encodes the handle of a particular buddy within a zbud page + * Pool lock should be held as this function accesses first|last_chunks + */ +static unsigned long encode_handle(struct zbud_header *zhdr, enum buddy bud) +{ + unsigned long handle; + + /* + * For now, the encoded handle is actually just the pointer to the data + * but this might not always be the case. A little information hiding. + * Add CHUNK_SIZE to the handle if it is the first allocation to jump + * over the zbud header in the first chunk. + */ + handle = (unsigned long)zhdr; + if (bud == FIRST) + /* skip over zbud header */ + handle += ZHDR_SIZE_ALIGNED; + else /* bud == LAST */ + handle += PAGE_SIZE - (zhdr->last_chunks << CHUNK_SHIFT); + return handle; +} + +/* Returns the zbud page where a given handle is stored */ +static struct zbud_header *handle_to_zbud_header(unsigned long handle) +{ + return (struct zbud_header *)(handle & PAGE_MASK); +} + +/* Returns the number of free chunks in a zbud page */ +static int num_free_chunks(struct zbud_header *zhdr) +{ + /* + * Rather than branch for different situations, just use the fact that + * free buddies have a length of zero to simplify everything. -1 at the + * end for the zbud header. + */ + return NCHUNKS - zhdr->first_chunks - zhdr->last_chunks - 1; +} + +/***************** + * API Functions +*****************/ +/** + * zbud_create_pool() - create a new zbud pool + * @gfp: gfp flags when allocating the zbud pool structure + * @ops: user-defined operations for the zbud pool + * + * Return: pointer to the new zbud pool or NULL if the metadata allocation + * failed. + */ +struct zbud_pool *zbud_create_pool(gfp_t gfp, struct zbud_ops *ops) +{ + struct zbud_pool *pool; + int i; + + pool = kmalloc(sizeof(struct zbud_pool), gfp); + if (!pool) + return NULL; + spin_lock_init(&pool->lock); + for_each_unbuddied_list(i, 0) + INIT_LIST_HEAD(&pool->unbuddied[i]); + INIT_LIST_HEAD(&pool->buddied); + INIT_LIST_HEAD(&pool->lru); + pool->pages_nr = 0; + pool->ops = ops; + return pool; +} + +/** + * zbud_destroy_pool() - destroys an existing zbud pool + * @pool: the zbud pool to be destroyed + * + * The pool should be emptied before this function is called. + */ +void zbud_destroy_pool(struct zbud_pool *pool) +{ + kfree(pool); +} + +/** + * zbud_alloc() - allocates a region of a given size + * @pool: zbud pool from which to allocate + * @size: size in bytes of the desired allocation + * @gfp: gfp flags used if the pool needs to grow + * @handle: handle of the new allocation + * + * This function will attempt to find a free region in the pool large enough to + * satisfy the allocation request. A search of the unbuddied lists is + * performed first. If no suitable free region is found, then a new page is + * allocated and added to the pool to satisfy the request. + * + * gfp should not set __GFP_HIGHMEM as highmem pages cannot be used + * as zbud pool pages. + * + * Return: 0 if success and handle is set, otherwise -EINVAL is the size or + * gfp arguments are invalid or -ENOMEM if the pool was unable to allocate + * a new page. + */ +int zbud_alloc(struct zbud_pool *pool, int size, gfp_t gfp, + unsigned long *handle) +{ + int chunks, i, freechunks; + struct zbud_header *zhdr = NULL; + enum buddy bud; + struct page *page; + + if (size <= 0 || gfp & __GFP_HIGHMEM) + return -EINVAL; + if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED) + return -ENOSPC; + chunks = size_to_chunks(size); + spin_lock(&pool->lock); + + /* First, try to find an unbuddied zbud page. */ + zhdr = NULL; + for_each_unbuddied_list(i, chunks) { + if (!list_empty(&pool->unbuddied[i])) { + zhdr = list_first_entry(&pool->unbuddied[i], + struct zbud_header, buddy); + list_del(&zhdr->buddy); + if (zhdr->first_chunks == 0) + bud = FIRST; + else + bud = LAST; + goto found; + } + } + + /* Couldn't find unbuddied zbud page, create new one */ + spin_unlock(&pool->lock); + page = alloc_page(gfp); + if (!page) + return -ENOMEM; + spin_lock(&pool->lock); + pool->pages_nr++; + zhdr = init_zbud_page(page); + bud = FIRST; + +found: + if (bud == FIRST) + zhdr->first_chunks = chunks; + else + zhdr->last_chunks = chunks; + + if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0) { + /* Add to unbuddied list */ + freechunks = num_free_chunks(zhdr); + list_add(&zhdr->buddy, &pool->unbuddied[freechunks]); + } else { + /* Add to buddied list */ + list_add(&zhdr->buddy, &pool->buddied); + } + + /* Add/move zbud page to beginning of LRU */ + if (!list_empty(&zhdr->lru)) + list_del(&zhdr->lru); + list_add(&zhdr->lru, &pool->lru); + + *handle = encode_handle(zhdr, bud); + spin_unlock(&pool->lock); + + return 0; +} + +/** + * zbud_free() - frees the allocation associated with the given handle + * @pool: pool in which the allocation resided + * @handle: handle associated with the allocation returned by zbud_alloc() + * + * In the case that the zbud page in which the allocation resides is under + * reclaim, as indicated by the PG_reclaim flag being set, this function + * only sets the first|last_chunks to 0. The page is actually freed + * once both buddies are evicted (see zbud_reclaim_page() below). + */ +void zbud_free(struct zbud_pool *pool, unsigned long handle) +{ + struct zbud_header *zhdr; + int freechunks; + + spin_lock(&pool->lock); + zhdr = handle_to_zbud_header(handle); + + /* If first buddy, handle will be page aligned */ + if ((handle - ZHDR_SIZE_ALIGNED) & ~PAGE_MASK) + zhdr->last_chunks = 0; + else + zhdr->first_chunks = 0; + + if (zhdr->under_reclaim) { + /* zbud page is under reclaim, reclaim will free */ + spin_unlock(&pool->lock); + return; + } + + /* Remove from existing buddy list */ + list_del(&zhdr->buddy); + + if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) { + /* zbud page is empty, free */ + list_del(&zhdr->lru); + free_zbud_page(zhdr); + pool->pages_nr--; + } else { + /* Add to unbuddied list */ + freechunks = num_free_chunks(zhdr); + list_add(&zhdr->buddy, &pool->unbuddied[freechunks]); + } + + spin_unlock(&pool->lock); +} + +#define list_tail_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * zbud_reclaim_page() - evicts allocations from a pool page and frees it + * @pool: pool from which a page will attempt to be evicted + * @retires: number of pages on the LRU list for which eviction will + * be attempted before failing + * + * zbud reclaim is different from normal system reclaim in that the reclaim is + * done from the bottom, up. This is because only the bottom layer, zbud, has + * information on how the allocations are organized within each zbud page. This + * has the potential to create interesting locking situations between zbud and + * the user, however. + * + * To avoid these, this is how zbud_reclaim_page() should be called: + + * The user detects a page should be reclaimed and calls zbud_reclaim_page(). + * zbud_reclaim_page() will remove a zbud page from the pool LRU list and call + * the user-defined eviction handler with the pool and handle as arguments. + * + * If the handle can not be evicted, the eviction handler should return + * non-zero. zbud_reclaim_page() will add the zbud page back to the + * appropriate list and try the next zbud page on the LRU up to + * a user defined number of retries. + * + * If the handle is successfully evicted, the eviction handler should + * return 0 _and_ should have called zbud_free() on the handle. zbud_free() + * contains logic to delay freeing the page if the page is under reclaim, + * as indicated by the setting of the PG_reclaim flag on the underlying page. + * + * If all buddies in the zbud page are successfully evicted, then the + * zbud page can be freed. + * + * Returns: 0 if page is successfully freed, otherwise -EINVAL if there are + * no pages to evict or an eviction handler is not registered, -EAGAIN if + * the retry limit was hit. + */ +int zbud_reclaim_page(struct zbud_pool *pool, unsigned int retries) +{ + int i, ret, freechunks; + struct zbud_header *zhdr; + unsigned long first_handle = 0, last_handle = 0; + + spin_lock(&pool->lock); + if (!pool->ops || !pool->ops->evict || list_empty(&pool->lru) || + retries == 0) { + spin_unlock(&pool->lock); + return -EINVAL; + } + for (i = 0; i < retries; i++) { + zhdr = list_tail_entry(&pool->lru, struct zbud_header, lru); + list_del(&zhdr->lru); + list_del(&zhdr->buddy); + /* Protect zbud page against free */ + zhdr->under_reclaim = true; + /* + * We need encode the handles before unlocking, since we can + * race with free that will set (first|last)_chunks to 0 + */ + first_handle = 0; + last_handle = 0; + if (zhdr->first_chunks) + first_handle = encode_handle(zhdr, FIRST); + if (zhdr->last_chunks) + last_handle = encode_handle(zhdr, LAST); + spin_unlock(&pool->lock); + + /* Issue the eviction callback(s) */ + if (first_handle) { + ret = pool->ops->evict(pool, first_handle); + if (ret) + goto next; + } + if (last_handle) { + ret = pool->ops->evict(pool, last_handle); + if (ret) + goto next; + } +next: + spin_lock(&pool->lock); + zhdr->under_reclaim = false; + if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) { + /* + * Both buddies are now free, free the zbud page and + * return success. + */ + free_zbud_page(zhdr); + pool->pages_nr--; + spin_unlock(&pool->lock); + return 0; + } else if (zhdr->first_chunks == 0 || + zhdr->last_chunks == 0) { + /* add to unbuddied list */ + freechunks = num_free_chunks(zhdr); + list_add(&zhdr->buddy, &pool->unbuddied[freechunks]); + } else { + /* add to buddied list */ + list_add(&zhdr->buddy, &pool->buddied); + } + + /* add to beginning of LRU */ + list_add(&zhdr->lru, &pool->lru); + } + spin_unlock(&pool->lock); + return -EAGAIN; +} + +/** + * zbud_map() - maps the allocation associated with the given handle + * @pool: pool in which the allocation resides + * @handle: handle associated with the allocation to be mapped + * + * While trivial for zbud, the mapping functions for others allocators + * implementing this allocation API could have more complex information encoded + * in the handle and could create temporary mappings to make the data + * accessible to the user. + * + * Returns: a pointer to the mapped allocation + */ +void *zbud_map(struct zbud_pool *pool, unsigned long handle) +{ + return (void *)(handle); +} + +/** + * zbud_unmap() - maps the allocation associated with the given handle + * @pool: pool in which the allocation resides + * @handle: handle associated with the allocation to be unmapped + */ +void zbud_unmap(struct zbud_pool *pool, unsigned long handle) +{ +} + +/** + * zbud_get_pool_size() - gets the zbud pool size in pages + * @pool: pool whose size is being queried + * + * Returns: size in pages of the given pool. The pool lock need not be + * taken to access pages_nr. + */ +u64 zbud_get_pool_size(struct zbud_pool *pool) +{ + return pool->pages_nr; +} + +static int __init init_zbud(void) +{ + /* Make sure the zbud header will fit in one chunk */ + BUILD_BUG_ON(sizeof(struct zbud_header) > ZHDR_SIZE_ALIGNED); + pr_info("loaded\n"); + return 0; +} + +static void __exit exit_zbud(void) +{ + pr_info("unloaded\n"); +} + +module_init(init_zbud); +module_exit(exit_zbud); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Seth Jennings "); +MODULE_DESCRIPTION("Buddy Allocator for Compressed Pages"); -- GitLab From 2b2811178e85553405b86e3fe78357b9b95889ce Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 10 Jul 2013 16:05:03 -0700 Subject: [PATCH 2610/2900] zswap: add to mm/ zswap is a thin backend for frontswap that takes pages that are in the process of being swapped out and attempts to compress them and store them in a RAM-based memory pool. This can result in a significant I/O reduction on the swap device and, in the case where decompressing from RAM is faster than reading from the swap device, can also improve workload performance. It also has support for evicting swap pages that are currently compressed in zswap to the swap device on an LRU(ish) basis. This functionality makes zswap a true cache in that, once the cache is full, the oldest pages can be moved out of zswap to the swap device so newer pages can be compressed and stored in zswap. This patch adds the zswap driver to mm/ Signed-off-by: Seth Jennings Acked-by: Rik van Riel Cc: Greg Kroah-Hartman Cc: Nitin Gupta Cc: Minchan Kim Cc: Konrad Rzeszutek Wilk Cc: Dan Magenheimer Cc: Robert Jennings Cc: Jenifer Hopper Cc: Mel Gorman Cc: Johannes Weiner Cc: Larry Woodman Cc: Benjamin Herrenschmidt Cc: Dave Hansen Cc: Joe Perches Cc: Joonsoo Kim Cc: Cody P Schafer Cc: Hugh Dickens Cc: Paul Mackerras Cc: Fengguang Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/Kconfig | 20 ++ mm/Makefile | 1 + mm/zswap.c | 943 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 964 insertions(+) create mode 100644 mm/zswap.c diff --git a/mm/Kconfig b/mm/Kconfig index 45503ed5f3aa..8028dcc6615c 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -488,6 +488,26 @@ config ZBUD deterministic reclaim properties that make it preferable to a higher density approach when reclaim will be used. +config ZSWAP + bool "Compressed cache for swap pages (EXPERIMENTAL)" + depends on FRONTSWAP && CRYPTO=y + select CRYPTO_LZO + select ZBUD + default n + help + A lightweight compressed cache for swap pages. It takes + pages that are in the process of being swapped out and attempts to + compress them into a dynamically allocated RAM-based memory pool. + This can result in a significant I/O reduction on swap device and, + in the case where decompressing from RAM is faster that swap device + reads, can also improve workload performance. + + This is marked experimental because it is a new feature (as of + v3.11) that interacts heavily with memory reclaim. While these + interactions don't cause any known issues on simple memory setups, + they have not be fully explored on the large set of potential + configurations and workloads that exist. + config MEM_SOFT_DIRTY bool "Track memory changes" depends on CHECKPOINT_RESTORE && HAVE_ARCH_SOFT_DIRTY diff --git a/mm/Makefile b/mm/Makefile index 95f0197ce3d3..f00803386a67 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o obj-$(CONFIG_BOUNCE) += bounce.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o obj-$(CONFIG_FRONTSWAP) += frontswap.o +obj-$(CONFIG_ZSWAP) += zswap.o obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o diff --git a/mm/zswap.c b/mm/zswap.c new file mode 100644 index 000000000000..deda2b671e12 --- /dev/null +++ b/mm/zswap.c @@ -0,0 +1,943 @@ +/* + * zswap.c - zswap driver file + * + * zswap is a backend for frontswap that takes pages that are in the process + * of being swapped out and attempts to compress and store them in a + * RAM-based memory pool. This can result in a significant I/O reduction on + * the swap device and, in the case where decompressing from RAM is faster + * than reading from the swap device, can also improve workload performance. + * + * Copyright (C) 2012 Seth Jennings + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/********************************* +* statistics +**********************************/ +/* Number of memory pages used by the compressed pool */ +static u64 zswap_pool_pages; +/* The number of compressed pages currently stored in zswap */ +static atomic_t zswap_stored_pages = ATOMIC_INIT(0); + +/* + * The statistics below are not protected from concurrent access for + * performance reasons so they may not be a 100% accurate. However, + * they do provide useful information on roughly how many times a + * certain event is occurring. +*/ + +/* Pool limit was hit (see zswap_max_pool_percent) */ +static u64 zswap_pool_limit_hit; +/* Pages written back when pool limit was reached */ +static u64 zswap_written_back_pages; +/* Store failed due to a reclaim failure after pool limit was reached */ +static u64 zswap_reject_reclaim_fail; +/* Compressed page was too big for the allocator to (optimally) store */ +static u64 zswap_reject_compress_poor; +/* Store failed because underlying allocator could not get memory */ +static u64 zswap_reject_alloc_fail; +/* Store failed because the entry metadata could not be allocated (rare) */ +static u64 zswap_reject_kmemcache_fail; +/* Duplicate store was encountered (rare) */ +static u64 zswap_duplicate_entry; + +/********************************* +* tunables +**********************************/ +/* Enable/disable zswap (disabled by default, fixed at boot for now) */ +static bool zswap_enabled __read_mostly; +module_param_named(enabled, zswap_enabled, bool, 0); + +/* Compressor to be used by zswap (fixed at boot for now) */ +#define ZSWAP_COMPRESSOR_DEFAULT "lzo" +static char *zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT; +module_param_named(compressor, zswap_compressor, charp, 0); + +/* The maximum percentage of memory that the compressed pool can occupy */ +static unsigned int zswap_max_pool_percent = 20; +module_param_named(max_pool_percent, + zswap_max_pool_percent, uint, 0644); + +/********************************* +* compression functions +**********************************/ +/* per-cpu compression transforms */ +static struct crypto_comp * __percpu *zswap_comp_pcpu_tfms; + +enum comp_op { + ZSWAP_COMPOP_COMPRESS, + ZSWAP_COMPOP_DECOMPRESS +}; + +static int zswap_comp_op(enum comp_op op, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + struct crypto_comp *tfm; + int ret; + + tfm = *per_cpu_ptr(zswap_comp_pcpu_tfms, get_cpu()); + switch (op) { + case ZSWAP_COMPOP_COMPRESS: + ret = crypto_comp_compress(tfm, src, slen, dst, dlen); + break; + case ZSWAP_COMPOP_DECOMPRESS: + ret = crypto_comp_decompress(tfm, src, slen, dst, dlen); + break; + default: + ret = -EINVAL; + } + + put_cpu(); + return ret; +} + +static int __init zswap_comp_init(void) +{ + if (!crypto_has_comp(zswap_compressor, 0, 0)) { + pr_info("%s compressor not available\n", zswap_compressor); + /* fall back to default compressor */ + zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT; + if (!crypto_has_comp(zswap_compressor, 0, 0)) + /* can't even load the default compressor */ + return -ENODEV; + } + pr_info("using %s compressor\n", zswap_compressor); + + /* alloc percpu transforms */ + zswap_comp_pcpu_tfms = alloc_percpu(struct crypto_comp *); + if (!zswap_comp_pcpu_tfms) + return -ENOMEM; + return 0; +} + +static void zswap_comp_exit(void) +{ + /* free percpu transforms */ + if (zswap_comp_pcpu_tfms) + free_percpu(zswap_comp_pcpu_tfms); +} + +/********************************* +* data structures +**********************************/ +/* + * struct zswap_entry + * + * This structure contains the metadata for tracking a single compressed + * page within zswap. + * + * rbnode - links the entry into red-black tree for the appropriate swap type + * refcount - the number of outstanding reference to the entry. This is needed + * to protect against premature freeing of the entry by code + * concurent calls to load, invalidate, and writeback. The lock + * for the zswap_tree structure that contains the entry must + * be held while changing the refcount. Since the lock must + * be held, there is no reason to also make refcount atomic. + * offset - the swap offset for the entry. Index into the red-black tree. + * handle - zsmalloc allocation handle that stores the compressed page data + * length - the length in bytes of the compressed page data. Needed during + * decompression + */ +struct zswap_entry { + struct rb_node rbnode; + pgoff_t offset; + int refcount; + unsigned int length; + unsigned long handle; +}; + +struct zswap_header { + swp_entry_t swpentry; +}; + +/* + * The tree lock in the zswap_tree struct protects a few things: + * - the rbtree + * - the refcount field of each entry in the tree + */ +struct zswap_tree { + struct rb_root rbroot; + spinlock_t lock; + struct zbud_pool *pool; +}; + +static struct zswap_tree *zswap_trees[MAX_SWAPFILES]; + +/********************************* +* zswap entry functions +**********************************/ +static struct kmem_cache *zswap_entry_cache; + +static int zswap_entry_cache_create(void) +{ + zswap_entry_cache = KMEM_CACHE(zswap_entry, 0); + return (zswap_entry_cache == NULL); +} + +static void zswap_entry_cache_destory(void) +{ + kmem_cache_destroy(zswap_entry_cache); +} + +static struct zswap_entry *zswap_entry_cache_alloc(gfp_t gfp) +{ + struct zswap_entry *entry; + entry = kmem_cache_alloc(zswap_entry_cache, gfp); + if (!entry) + return NULL; + entry->refcount = 1; + return entry; +} + +static void zswap_entry_cache_free(struct zswap_entry *entry) +{ + kmem_cache_free(zswap_entry_cache, entry); +} + +/* caller must hold the tree lock */ +static void zswap_entry_get(struct zswap_entry *entry) +{ + entry->refcount++; +} + +/* caller must hold the tree lock */ +static int zswap_entry_put(struct zswap_entry *entry) +{ + entry->refcount--; + return entry->refcount; +} + +/********************************* +* rbtree functions +**********************************/ +static struct zswap_entry *zswap_rb_search(struct rb_root *root, pgoff_t offset) +{ + struct rb_node *node = root->rb_node; + struct zswap_entry *entry; + + while (node) { + entry = rb_entry(node, struct zswap_entry, rbnode); + if (entry->offset > offset) + node = node->rb_left; + else if (entry->offset < offset) + node = node->rb_right; + else + return entry; + } + return NULL; +} + +/* + * In the case that a entry with the same offset is found, a pointer to + * the existing entry is stored in dupentry and the function returns -EEXIST + */ +static int zswap_rb_insert(struct rb_root *root, struct zswap_entry *entry, + struct zswap_entry **dupentry) +{ + struct rb_node **link = &root->rb_node, *parent = NULL; + struct zswap_entry *myentry; + + while (*link) { + parent = *link; + myentry = rb_entry(parent, struct zswap_entry, rbnode); + if (myentry->offset > entry->offset) + link = &(*link)->rb_left; + else if (myentry->offset < entry->offset) + link = &(*link)->rb_right; + else { + *dupentry = myentry; + return -EEXIST; + } + } + rb_link_node(&entry->rbnode, parent, link); + rb_insert_color(&entry->rbnode, root); + return 0; +} + +/********************************* +* per-cpu code +**********************************/ +static DEFINE_PER_CPU(u8 *, zswap_dstmem); + +static int __zswap_cpu_notifier(unsigned long action, unsigned long cpu) +{ + struct crypto_comp *tfm; + u8 *dst; + + switch (action) { + case CPU_UP_PREPARE: + tfm = crypto_alloc_comp(zswap_compressor, 0, 0); + if (IS_ERR(tfm)) { + pr_err("can't allocate compressor transform\n"); + return NOTIFY_BAD; + } + *per_cpu_ptr(zswap_comp_pcpu_tfms, cpu) = tfm; + dst = kmalloc(PAGE_SIZE * 2, GFP_KERNEL); + if (!dst) { + pr_err("can't allocate compressor buffer\n"); + crypto_free_comp(tfm); + *per_cpu_ptr(zswap_comp_pcpu_tfms, cpu) = NULL; + return NOTIFY_BAD; + } + per_cpu(zswap_dstmem, cpu) = dst; + break; + case CPU_DEAD: + case CPU_UP_CANCELED: + tfm = *per_cpu_ptr(zswap_comp_pcpu_tfms, cpu); + if (tfm) { + crypto_free_comp(tfm); + *per_cpu_ptr(zswap_comp_pcpu_tfms, cpu) = NULL; + } + dst = per_cpu(zswap_dstmem, cpu); + kfree(dst); + per_cpu(zswap_dstmem, cpu) = NULL; + break; + default: + break; + } + return NOTIFY_OK; +} + +static int zswap_cpu_notifier(struct notifier_block *nb, + unsigned long action, void *pcpu) +{ + unsigned long cpu = (unsigned long)pcpu; + return __zswap_cpu_notifier(action, cpu); +} + +static struct notifier_block zswap_cpu_notifier_block = { + .notifier_call = zswap_cpu_notifier +}; + +static int zswap_cpu_init(void) +{ + unsigned long cpu; + + get_online_cpus(); + for_each_online_cpu(cpu) + if (__zswap_cpu_notifier(CPU_UP_PREPARE, cpu) != NOTIFY_OK) + goto cleanup; + register_cpu_notifier(&zswap_cpu_notifier_block); + put_online_cpus(); + return 0; + +cleanup: + for_each_online_cpu(cpu) + __zswap_cpu_notifier(CPU_UP_CANCELED, cpu); + put_online_cpus(); + return -ENOMEM; +} + +/********************************* +* helpers +**********************************/ +static bool zswap_is_full(void) +{ + return (totalram_pages * zswap_max_pool_percent / 100 < + zswap_pool_pages); +} + +/* + * Carries out the common pattern of freeing and entry's zsmalloc allocation, + * freeing the entry itself, and decrementing the number of stored pages. + */ +static void zswap_free_entry(struct zswap_tree *tree, struct zswap_entry *entry) +{ + zbud_free(tree->pool, entry->handle); + zswap_entry_cache_free(entry); + atomic_dec(&zswap_stored_pages); + zswap_pool_pages = zbud_get_pool_size(tree->pool); +} + +/********************************* +* writeback code +**********************************/ +/* return enum for zswap_get_swap_cache_page */ +enum zswap_get_swap_ret { + ZSWAP_SWAPCACHE_NEW, + ZSWAP_SWAPCACHE_EXIST, + ZSWAP_SWAPCACHE_NOMEM +}; + +/* + * zswap_get_swap_cache_page + * + * This is an adaption of read_swap_cache_async() + * + * This function tries to find a page with the given swap entry + * in the swapper_space address space (the swap cache). If the page + * is found, it is returned in retpage. Otherwise, a page is allocated, + * added to the swap cache, and returned in retpage. + * + * If success, the swap cache page is returned in retpage + * Returns 0 if page was already in the swap cache, page is not locked + * Returns 1 if the new page needs to be populated, page is locked + * Returns <0 on error + */ +static int zswap_get_swap_cache_page(swp_entry_t entry, + struct page **retpage) +{ + struct page *found_page, *new_page = NULL; + struct address_space *swapper_space = &swapper_spaces[swp_type(entry)]; + int err; + + *retpage = NULL; + do { + /* + * First check the swap cache. Since this is normally + * called after lookup_swap_cache() failed, re-calling + * that would confuse statistics. + */ + found_page = find_get_page(swapper_space, entry.val); + if (found_page) + break; + + /* + * Get a new page to read into from swap. + */ + if (!new_page) { + new_page = alloc_page(GFP_KERNEL); + if (!new_page) + break; /* Out of memory */ + } + + /* + * call radix_tree_preload() while we can wait. + */ + err = radix_tree_preload(GFP_KERNEL); + if (err) + break; + + /* + * Swap entry may have been freed since our caller observed it. + */ + err = swapcache_prepare(entry); + if (err == -EEXIST) { /* seems racy */ + radix_tree_preload_end(); + continue; + } + if (err) { /* swp entry is obsolete ? */ + radix_tree_preload_end(); + break; + } + + /* May fail (-ENOMEM) if radix-tree node allocation failed. */ + __set_page_locked(new_page); + SetPageSwapBacked(new_page); + err = __add_to_swap_cache(new_page, entry); + if (likely(!err)) { + radix_tree_preload_end(); + lru_cache_add_anon(new_page); + *retpage = new_page; + return ZSWAP_SWAPCACHE_NEW; + } + radix_tree_preload_end(); + ClearPageSwapBacked(new_page); + __clear_page_locked(new_page); + /* + * add_to_swap_cache() doesn't return -EEXIST, so we can safely + * clear SWAP_HAS_CACHE flag. + */ + swapcache_free(entry, NULL); + } while (err != -ENOMEM); + + if (new_page) + page_cache_release(new_page); + if (!found_page) + return ZSWAP_SWAPCACHE_NOMEM; + *retpage = found_page; + return ZSWAP_SWAPCACHE_EXIST; +} + +/* + * Attempts to free an entry by adding a page to the swap cache, + * decompressing the entry data into the page, and issuing a + * bio write to write the page back to the swap device. + * + * This can be thought of as a "resumed writeback" of the page + * to the swap device. We are basically resuming the same swap + * writeback path that was intercepted with the frontswap_store() + * in the first place. After the page has been decompressed into + * the swap cache, the compressed version stored by zswap can be + * freed. + */ +static int zswap_writeback_entry(struct zbud_pool *pool, unsigned long handle) +{ + struct zswap_header *zhdr; + swp_entry_t swpentry; + struct zswap_tree *tree; + pgoff_t offset; + struct zswap_entry *entry; + struct page *page; + u8 *src, *dst; + unsigned int dlen; + int ret, refcount; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_NONE, + }; + + /* extract swpentry from data */ + zhdr = zbud_map(pool, handle); + swpentry = zhdr->swpentry; /* here */ + zbud_unmap(pool, handle); + tree = zswap_trees[swp_type(swpentry)]; + offset = swp_offset(swpentry); + BUG_ON(pool != tree->pool); + + /* find and ref zswap entry */ + spin_lock(&tree->lock); + entry = zswap_rb_search(&tree->rbroot, offset); + if (!entry) { + /* entry was invalidated */ + spin_unlock(&tree->lock); + return 0; + } + zswap_entry_get(entry); + spin_unlock(&tree->lock); + BUG_ON(offset != entry->offset); + + /* try to allocate swap cache page */ + switch (zswap_get_swap_cache_page(swpentry, &page)) { + case ZSWAP_SWAPCACHE_NOMEM: /* no memory */ + ret = -ENOMEM; + goto fail; + + case ZSWAP_SWAPCACHE_EXIST: /* page is unlocked */ + /* page is already in the swap cache, ignore for now */ + page_cache_release(page); + ret = -EEXIST; + goto fail; + + case ZSWAP_SWAPCACHE_NEW: /* page is locked */ + /* decompress */ + dlen = PAGE_SIZE; + src = (u8 *)zbud_map(tree->pool, entry->handle) + + sizeof(struct zswap_header); + dst = kmap_atomic(page); + ret = zswap_comp_op(ZSWAP_COMPOP_DECOMPRESS, src, + entry->length, dst, &dlen); + kunmap_atomic(dst); + zbud_unmap(tree->pool, entry->handle); + BUG_ON(ret); + BUG_ON(dlen != PAGE_SIZE); + + /* page is up to date */ + SetPageUptodate(page); + } + + /* start writeback */ + __swap_writepage(page, &wbc, end_swap_bio_write); + page_cache_release(page); + zswap_written_back_pages++; + + spin_lock(&tree->lock); + + /* drop local reference */ + zswap_entry_put(entry); + /* drop the initial reference from entry creation */ + refcount = zswap_entry_put(entry); + + /* + * There are three possible values for refcount here: + * (1) refcount is 1, load is in progress, unlink from rbtree, + * load will free + * (2) refcount is 0, (normal case) entry is valid, + * remove from rbtree and free entry + * (3) refcount is -1, invalidate happened during writeback, + * free entry + */ + if (refcount >= 0) { + /* no invalidate yet, remove from rbtree */ + rb_erase(&entry->rbnode, &tree->rbroot); + } + spin_unlock(&tree->lock); + if (refcount <= 0) { + /* free the entry */ + zswap_free_entry(tree, entry); + return 0; + } + return -EAGAIN; + +fail: + spin_lock(&tree->lock); + zswap_entry_put(entry); + spin_unlock(&tree->lock); + return ret; +} + +/********************************* +* frontswap hooks +**********************************/ +/* attempts to compress and store an single page */ +static int zswap_frontswap_store(unsigned type, pgoff_t offset, + struct page *page) +{ + struct zswap_tree *tree = zswap_trees[type]; + struct zswap_entry *entry, *dupentry; + int ret; + unsigned int dlen = PAGE_SIZE, len; + unsigned long handle; + char *buf; + u8 *src, *dst; + struct zswap_header *zhdr; + + if (!tree) { + ret = -ENODEV; + goto reject; + } + + /* reclaim space if needed */ + if (zswap_is_full()) { + zswap_pool_limit_hit++; + if (zbud_reclaim_page(tree->pool, 8)) { + zswap_reject_reclaim_fail++; + ret = -ENOMEM; + goto reject; + } + } + + /* allocate entry */ + entry = zswap_entry_cache_alloc(GFP_KERNEL); + if (!entry) { + zswap_reject_kmemcache_fail++; + ret = -ENOMEM; + goto reject; + } + + /* compress */ + dst = get_cpu_var(zswap_dstmem); + src = kmap_atomic(page); + ret = zswap_comp_op(ZSWAP_COMPOP_COMPRESS, src, PAGE_SIZE, dst, &dlen); + kunmap_atomic(src); + if (ret) { + ret = -EINVAL; + goto freepage; + } + + /* store */ + len = dlen + sizeof(struct zswap_header); + ret = zbud_alloc(tree->pool, len, __GFP_NORETRY | __GFP_NOWARN, + &handle); + if (ret == -ENOSPC) { + zswap_reject_compress_poor++; + goto freepage; + } + if (ret) { + zswap_reject_alloc_fail++; + goto freepage; + } + zhdr = zbud_map(tree->pool, handle); + zhdr->swpentry = swp_entry(type, offset); + buf = (u8 *)(zhdr + 1); + memcpy(buf, dst, dlen); + zbud_unmap(tree->pool, handle); + put_cpu_var(zswap_dstmem); + + /* populate entry */ + entry->offset = offset; + entry->handle = handle; + entry->length = dlen; + + /* map */ + spin_lock(&tree->lock); + do { + ret = zswap_rb_insert(&tree->rbroot, entry, &dupentry); + if (ret == -EEXIST) { + zswap_duplicate_entry++; + /* remove from rbtree */ + rb_erase(&dupentry->rbnode, &tree->rbroot); + if (!zswap_entry_put(dupentry)) { + /* free */ + zswap_free_entry(tree, dupentry); + } + } + } while (ret == -EEXIST); + spin_unlock(&tree->lock); + + /* update stats */ + atomic_inc(&zswap_stored_pages); + zswap_pool_pages = zbud_get_pool_size(tree->pool); + + return 0; + +freepage: + put_cpu_var(zswap_dstmem); + zswap_entry_cache_free(entry); +reject: + return ret; +} + +/* + * returns 0 if the page was successfully decompressed + * return -1 on entry not found or error +*/ +static int zswap_frontswap_load(unsigned type, pgoff_t offset, + struct page *page) +{ + struct zswap_tree *tree = zswap_trees[type]; + struct zswap_entry *entry; + u8 *src, *dst; + unsigned int dlen; + int refcount, ret; + + /* find */ + spin_lock(&tree->lock); + entry = zswap_rb_search(&tree->rbroot, offset); + if (!entry) { + /* entry was written back */ + spin_unlock(&tree->lock); + return -1; + } + zswap_entry_get(entry); + spin_unlock(&tree->lock); + + /* decompress */ + dlen = PAGE_SIZE; + src = (u8 *)zbud_map(tree->pool, entry->handle) + + sizeof(struct zswap_header); + dst = kmap_atomic(page); + ret = zswap_comp_op(ZSWAP_COMPOP_DECOMPRESS, src, entry->length, + dst, &dlen); + kunmap_atomic(dst); + zbud_unmap(tree->pool, entry->handle); + BUG_ON(ret); + + spin_lock(&tree->lock); + refcount = zswap_entry_put(entry); + if (likely(refcount)) { + spin_unlock(&tree->lock); + return 0; + } + spin_unlock(&tree->lock); + + /* + * We don't have to unlink from the rbtree because + * zswap_writeback_entry() or zswap_frontswap_invalidate page() + * has already done this for us if we are the last reference. + */ + /* free */ + + zswap_free_entry(tree, entry); + + return 0; +} + +/* frees an entry in zswap */ +static void zswap_frontswap_invalidate_page(unsigned type, pgoff_t offset) +{ + struct zswap_tree *tree = zswap_trees[type]; + struct zswap_entry *entry; + int refcount; + + /* find */ + spin_lock(&tree->lock); + entry = zswap_rb_search(&tree->rbroot, offset); + if (!entry) { + /* entry was written back */ + spin_unlock(&tree->lock); + return; + } + + /* remove from rbtree */ + rb_erase(&entry->rbnode, &tree->rbroot); + + /* drop the initial reference from entry creation */ + refcount = zswap_entry_put(entry); + + spin_unlock(&tree->lock); + + if (refcount) { + /* writeback in progress, writeback will free */ + return; + } + + /* free */ + zswap_free_entry(tree, entry); +} + +/* frees all zswap entries for the given swap type */ +static void zswap_frontswap_invalidate_area(unsigned type) +{ + struct zswap_tree *tree = zswap_trees[type]; + struct rb_node *node; + struct zswap_entry *entry; + + if (!tree) + return; + + /* walk the tree and free everything */ + spin_lock(&tree->lock); + /* + * TODO: Even though this code should not be executed because + * the try_to_unuse() in swapoff should have emptied the tree, + * it is very wasteful to rebalance the tree after every + * removal when we are freeing the whole tree. + * + * If post-order traversal code is ever added to the rbtree + * implementation, it should be used here. + */ + while ((node = rb_first(&tree->rbroot))) { + entry = rb_entry(node, struct zswap_entry, rbnode); + rb_erase(&entry->rbnode, &tree->rbroot); + zbud_free(tree->pool, entry->handle); + zswap_entry_cache_free(entry); + atomic_dec(&zswap_stored_pages); + } + tree->rbroot = RB_ROOT; + spin_unlock(&tree->lock); +} + +static struct zbud_ops zswap_zbud_ops = { + .evict = zswap_writeback_entry +}; + +static void zswap_frontswap_init(unsigned type) +{ + struct zswap_tree *tree; + + tree = kzalloc(sizeof(struct zswap_tree), GFP_KERNEL); + if (!tree) + goto err; + tree->pool = zbud_create_pool(GFP_KERNEL, &zswap_zbud_ops); + if (!tree->pool) + goto freetree; + tree->rbroot = RB_ROOT; + spin_lock_init(&tree->lock); + zswap_trees[type] = tree; + return; + +freetree: + kfree(tree); +err: + pr_err("alloc failed, zswap disabled for swap type %d\n", type); +} + +static struct frontswap_ops zswap_frontswap_ops = { + .store = zswap_frontswap_store, + .load = zswap_frontswap_load, + .invalidate_page = zswap_frontswap_invalidate_page, + .invalidate_area = zswap_frontswap_invalidate_area, + .init = zswap_frontswap_init +}; + +/********************************* +* debugfs functions +**********************************/ +#ifdef CONFIG_DEBUG_FS +#include + +static struct dentry *zswap_debugfs_root; + +static int __init zswap_debugfs_init(void) +{ + if (!debugfs_initialized()) + return -ENODEV; + + zswap_debugfs_root = debugfs_create_dir("zswap", NULL); + if (!zswap_debugfs_root) + return -ENOMEM; + + debugfs_create_u64("pool_limit_hit", S_IRUGO, + zswap_debugfs_root, &zswap_pool_limit_hit); + debugfs_create_u64("reject_reclaim_fail", S_IRUGO, + zswap_debugfs_root, &zswap_reject_reclaim_fail); + debugfs_create_u64("reject_alloc_fail", S_IRUGO, + zswap_debugfs_root, &zswap_reject_alloc_fail); + debugfs_create_u64("reject_kmemcache_fail", S_IRUGO, + zswap_debugfs_root, &zswap_reject_kmemcache_fail); + debugfs_create_u64("reject_compress_poor", S_IRUGO, + zswap_debugfs_root, &zswap_reject_compress_poor); + debugfs_create_u64("written_back_pages", S_IRUGO, + zswap_debugfs_root, &zswap_written_back_pages); + debugfs_create_u64("duplicate_entry", S_IRUGO, + zswap_debugfs_root, &zswap_duplicate_entry); + debugfs_create_u64("pool_pages", S_IRUGO, + zswap_debugfs_root, &zswap_pool_pages); + debugfs_create_atomic_t("stored_pages", S_IRUGO, + zswap_debugfs_root, &zswap_stored_pages); + + return 0; +} + +static void __exit zswap_debugfs_exit(void) +{ + debugfs_remove_recursive(zswap_debugfs_root); +} +#else +static int __init zswap_debugfs_init(void) +{ + return 0; +} + +static void __exit zswap_debugfs_exit(void) { } +#endif + +/********************************* +* module init and exit +**********************************/ +static int __init init_zswap(void) +{ + if (!zswap_enabled) + return 0; + + pr_info("loading zswap\n"); + if (zswap_entry_cache_create()) { + pr_err("entry cache creation failed\n"); + goto error; + } + if (zswap_comp_init()) { + pr_err("compressor initialization failed\n"); + goto compfail; + } + if (zswap_cpu_init()) { + pr_err("per-cpu initialization failed\n"); + goto pcpufail; + } + frontswap_register_ops(&zswap_frontswap_ops); + if (zswap_debugfs_init()) + pr_warn("debugfs initialization failed\n"); + return 0; +pcpufail: + zswap_comp_exit(); +compfail: + zswap_entry_cache_destory(); +error: + return -ENOMEM; +} +/* must be late so crypto has time to come up */ +late_initcall(init_zswap); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Seth Jennings "); +MODULE_DESCRIPTION("Compressed cache for swap pages"); -- GitLab From 61b0d76017a50c263c303fa263b295b04e0c68f6 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Wed, 10 Jul 2013 16:05:05 -0700 Subject: [PATCH 2611/2900] zswap: add documentation Add the documentation file for the zswap functionality Signed-off-by: Seth Jennings Acked-by: Rik van Riel Cc: Greg Kroah-Hartman Cc: Nitin Gupta Cc: Minchan Kim Cc: Konrad Rzeszutek Wilk Cc: Dan Magenheimer Cc: Robert Jennings Cc: Jenifer Hopper Cc: Mel Gorman Cc: Johannes Weiner Cc: Larry Woodman Cc: Benjamin Herrenschmidt Cc: Dave Hansen Cc: Joe Perches Cc: Joonsoo Kim Cc: Cody P Schafer Cc: Hugh Dickens Cc: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/zswap.txt | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Documentation/vm/zswap.txt diff --git a/Documentation/vm/zswap.txt b/Documentation/vm/zswap.txt new file mode 100644 index 000000000000..7e492d8aaeaf --- /dev/null +++ b/Documentation/vm/zswap.txt @@ -0,0 +1,68 @@ +Overview: + +Zswap is a lightweight compressed cache for swap pages. It takes pages that are +in the process of being swapped out and attempts to compress them into a +dynamically allocated RAM-based memory pool. zswap basically trades CPU cycles +for potentially reduced swap I/O.  This trade-off can also result in a +significant performance improvement if reads from the compressed cache are +faster than reads from a swap device. + +NOTE: Zswap is a new feature as of v3.11 and interacts heavily with memory +reclaim. This interaction has not be fully explored on the large set of +potential configurations and workloads that exist. For this reason, zswap +is a work in progress and should be considered experimental. + +Some potential benefits: +* Desktop/laptop users with limited RAM capacities can mitigate the +    performance impact of swapping. +* Overcommitted guests that share a common I/O resource can +    dramatically reduce their swap I/O pressure, avoiding heavy handed I/O + throttling by the hypervisor. This allows more work to get done with less + impact to the guest workload and guests sharing the I/O subsystem +* Users with SSDs as swap devices can extend the life of the device by +    drastically reducing life-shortening writes. + +Zswap evicts pages from compressed cache on an LRU basis to the backing swap +device when the compressed pool reaches it size limit. This requirement had +been identified in prior community discussions. + +To enabled zswap, the "enabled" attribute must be set to 1 at boot time. e.g. +zswap.enabled=1 + +Design: + +Zswap receives pages for compression through the Frontswap API and is able to +evict pages from its own compressed pool on an LRU basis and write them back to +the backing swap device in the case that the compressed pool is full. + +Zswap makes use of zbud for the managing the compressed memory pool. Each +allocation in zbud is not directly accessible by address. Rather, a handle is +return by the allocation routine and that handle must be mapped before being +accessed. The compressed memory pool grows on demand and shrinks as compressed +pages are freed. The pool is not preallocated. + +When a swap page is passed from frontswap to zswap, zswap maintains a mapping +of the swap entry, a combination of the swap type and swap offset, to the zbud +handle that references that compressed swap page. This mapping is achieved +with a red-black tree per swap type. The swap offset is the search key for the +tree nodes. + +During a page fault on a PTE that is a swap entry, frontswap calls the zswap +load function to decompress the page into the page allocated by the page fault +handler. + +Once there are no PTEs referencing a swap page stored in zswap (i.e. the count +in the swap_map goes to 0) the swap code calls the zswap invalidate function, +via frontswap, to free the compressed entry. + +Zswap seeks to be simple in its policies. Sysfs attributes allow for one user +controlled policies: +* max_pool_percent - The maximum percentage of memory that the compressed + pool can occupy. + +Zswap allows the compressor to be selected at kernel boot time by setting the +“compressor” attribute. The default compressor is lzo. e.g. +zswap.compressor=deflate + +A debugfs interface is provided for various statistic about pool size, number +of pages stored, and various counters for the reasons pages are rejected. -- GitLab From 98d1e64f95b177d0f14efbdf695a1b28e1428035 Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Wed, 10 Jul 2013 16:05:12 -0700 Subject: [PATCH 2612/2900] mm: remove free_area_cache Since all architectures have been converted to use vm_unmapped_area(), there is no remaining use for the free_area_cache. Signed-off-by: Michel Lespinasse Acked-by: Rik van Riel Cc: "James E.J. Bottomley" Cc: "Luck, Tony" Cc: Benjamin Herrenschmidt Cc: David Howells Cc: Helge Deller Cc: Ivan Kokshaysky Cc: Matt Turner Cc: Paul Mackerras Cc: Richard Henderson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mm/mmap.c | 2 -- arch/arm64/mm/mmap.c | 2 -- arch/mips/mm/mmap.c | 2 -- arch/powerpc/mm/mmap.c | 2 -- arch/s390/mm/mmap.c | 4 ---- arch/sparc/kernel/sys_sparc_64.c | 2 -- arch/tile/mm/mmap.c | 2 -- arch/x86/ia32/ia32_aout.c | 2 -- arch/x86/mm/mmap.c | 2 -- fs/binfmt_aout.c | 2 -- fs/binfmt_elf.c | 2 -- include/linux/mm_types.h | 3 --- include/linux/sched.h | 2 -- kernel/fork.c | 4 ---- mm/mmap.c | 28 ---------------------------- mm/nommu.c | 4 ---- mm/util.c | 1 - 17 files changed, 66 deletions(-) diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index 10062ceadd1c..0c6356255fe3 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -181,11 +181,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(random_factor); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index 7c7be7855638..8ed6cb1a900f 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -90,11 +90,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } EXPORT_SYMBOL_GPL(arch_pick_mmap_layout); diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c index 7e5fe2790d8a..f1baadd56e82 100644 --- a/arch/mips/mm/mmap.c +++ b/arch/mips/mm/mmap.c @@ -158,11 +158,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(random_factor); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index 67a42ed0d2fc..cb8bdbe4972f 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c @@ -92,10 +92,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 06bafec00278..40023290ee5b 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -91,11 +91,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } @@ -176,11 +174,9 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = s390_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = s390_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 2daaaa6eda23..51561b8b15ba 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -290,7 +290,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) sysctl_legacy_va_layout) { mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { /* We know it's 32-bit */ unsigned long task_size = STACK_TOP32; @@ -302,7 +301,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/tile/mm/mmap.c b/arch/tile/mm/mmap.c index f96f4cec602a..d67d91ebf63e 100644 --- a/arch/tile/mm/mmap.c +++ b/arch/tile/mm/mmap.c @@ -66,10 +66,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (!is_32bit || rlimit(RLIMIT_STACK) == RLIM_INFINITY) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(mm); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 52ff81cce008..bae3aba95b15 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -308,8 +308,6 @@ static int load_aout_binary(struct linux_binprm *bprm) (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); - current->mm->free_area_cache = TASK_UNMAPPED_BASE; - current->mm->cached_hole_size = 0; retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); if (retval < 0) { diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c index 845df6835f9f..62c29a5bfe26 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -115,10 +115,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm) if (mmap_is_legacy()) { mm->mmap_base = mmap_legacy_base(); mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; } } diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index bce87694f7b0..89dec7f789a4 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -255,8 +255,6 @@ static int load_aout_binary(struct linux_binprm * bprm) (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); - current->mm->free_area_cache = current->mm->mmap_base; - current->mm->cached_hole_size = 0; retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); if (retval < 0) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index f8a0b0efda44..100edcc5e312 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -738,8 +738,6 @@ static int load_elf_binary(struct linux_binprm *bprm) /* Do this so that we can load the interpreter, if need be. We will change some of these later */ - current->mm->free_area_cache = current->mm->mmap_base; - current->mm->cached_hole_size = 0; retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack); if (retval < 0) { diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index ace9a5f01c64..fb425aa16c01 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -330,12 +330,9 @@ struct mm_struct { unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); - void (*unmap_area) (struct mm_struct *mm, unsigned long addr); #endif unsigned long mmap_base; /* base of mmap area */ unsigned long task_size; /* size of task vm space */ - unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ - unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ unsigned long highest_vm_end; /* highest vma end address */ pgd_t * pgd; atomic_t mm_users; /* How many users with user space? */ diff --git a/include/linux/sched.h b/include/linux/sched.h index f99d57e0ae47..50d04b92ceda 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -322,8 +322,6 @@ extern unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); -extern void arch_unmap_area(struct mm_struct *, unsigned long); -extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long); #else static inline void arch_pick_mmap_layout(struct mm_struct *mm) {} #endif diff --git a/kernel/fork.c b/kernel/fork.c index 6e6a1c11b3e5..66635c80a813 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -365,8 +365,6 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) mm->locked_vm = 0; mm->mmap = NULL; mm->mmap_cache = NULL; - mm->free_area_cache = oldmm->mmap_base; - mm->cached_hole_size = ~0UL; mm->map_count = 0; cpumask_clear(mm_cpumask(mm)); mm->mm_rb = RB_ROOT; @@ -540,8 +538,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p) mm->nr_ptes = 0; memset(&mm->rss_stat, 0, sizeof(mm->rss_stat)); spin_lock_init(&mm->page_table_lock); - mm->free_area_cache = TASK_UNMAPPED_BASE; - mm->cached_hole_size = ~0UL; mm_init_aio(mm); mm_init_owner(mm, p); diff --git a/mm/mmap.c b/mm/mmap.c index f81311173b4d..fbad7b091090 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1878,15 +1878,6 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, } #endif -void arch_unmap_area(struct mm_struct *mm, unsigned long addr) -{ - /* - * Is this a new hole at the lowest possible address? - */ - if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) - mm->free_area_cache = addr; -} - /* * This mmap-allocator allocates new areas top-down from below the * stack's low limit (the base): @@ -1943,19 +1934,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, } #endif -void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) -{ - /* - * Is this a new hole at the highest possible address? - */ - if (addr > mm->free_area_cache) - mm->free_area_cache = addr; - - /* dont allow allocations above current base */ - if (mm->free_area_cache > mm->mmap_base) - mm->free_area_cache = mm->mmap_base; -} - unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -2376,7 +2354,6 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, { struct vm_area_struct **insertion_point; struct vm_area_struct *tail_vma = NULL; - unsigned long addr; insertion_point = (prev ? &prev->vm_next : &mm->mmap); vma->vm_prev = NULL; @@ -2393,11 +2370,6 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, } else mm->highest_vm_end = prev ? prev->vm_end : 0; tail_vma->vm_next = NULL; - if (mm->unmap_area == arch_unmap_area) - addr = prev ? prev->vm_end : mm->mmap_base; - else - addr = vma ? vma->vm_start : mm->mmap_base; - mm->unmap_area(mm, addr); mm->mmap_cache = NULL; /* Kill the cache. */ } diff --git a/mm/nommu.c b/mm/nommu.c index e44e6e0a125c..ecd1f158548e 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1871,10 +1871,6 @@ unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr, return -ENOMEM; } -void arch_unmap_area(struct mm_struct *mm, unsigned long addr) -{ -} - void unmap_mapping_range(struct address_space *mapping, loff_t const holebegin, loff_t const holelen, int even_cows) diff --git a/mm/util.c b/mm/util.c index ab1424dbe2e6..7441c41d00f6 100644 --- a/mm/util.c +++ b/mm/util.c @@ -295,7 +295,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm) { mm->mmap_base = TASK_UNMAPPED_BASE; mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; } #endif -- GitLab From 822dbba33458cd6ad0e715f3f4a57ebc99d54d1b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 10 Jul 2013 21:31:04 -0400 Subject: [PATCH 2613/2900] ext4: fix warning in ext4_evict_inode() The following race can lead to ext4_evict_inode() seeing i_ioend_count > 0 and thus triggering a sanity check warning: CPU1 CPU2 ext4_end_bio() ext4_evict_inode() ext4_finish_bio() end_page_writeback(); truncate_inode_pages() evict page WARN_ON(i_ioend_count > 0); ext4_put_io_end_defer() ext4_release_io_end() dec i_ioend_count This is possible use-after-free bug since we decrement i_ioend_count in possibly released inode. Since i_ioend_count is used only for sanity checks one possible solution would be to just remove it but for now I'd like to keep those sanity checks to help debugging the new ext4 writeback code. This patch changes ext4_end_bio() to call ext4_put_io_end_defer() before ext4_finish_bio() in the shortcut case when unwritten extent conversion isn't needed. In that case we don't need the io_end so we are safe to drop it early. Reported-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Jan Kara Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 48786cdb5e6c..d63cc5e9d3b5 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -308,6 +308,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) return io_end; } +/* BIO completion function for page writeback */ static void ext4_end_bio(struct bio *bio, int error) { ext4_io_end_t *io_end = bio->bi_private; @@ -318,18 +319,6 @@ static void ext4_end_bio(struct bio *bio, int error) if (test_bit(BIO_UPTODATE, &bio->bi_flags)) error = 0; - if (io_end->flag & EXT4_IO_END_UNWRITTEN) { - /* - * Link bio into list hanging from io_end. We have to do it - * atomically as bio completions can be racing against each - * other. - */ - bio->bi_private = xchg(&io_end->bio, bio); - } else { - ext4_finish_bio(bio); - bio_put(bio); - } - if (error) { struct inode *inode = io_end->inode; @@ -341,7 +330,24 @@ static void ext4_end_bio(struct bio *bio, int error) (unsigned long long) bi_sector >> (inode->i_blkbits - 9)); } - ext4_put_io_end_defer(io_end); + + if (io_end->flag & EXT4_IO_END_UNWRITTEN) { + /* + * Link bio into list hanging from io_end. We have to do it + * atomically as bio completions can be racing against each + * other. + */ + bio->bi_private = xchg(&io_end->bio, bio); + ext4_put_io_end_defer(io_end); + } else { + /* + * Drop io_end reference early. Inode can get freed once + * we finish the bio. + */ + ext4_put_io_end_defer(io_end); + ext4_finish_bio(bio); + bio_put(bio); + } } void ext4_io_submit(struct ext4_io_submit *io) -- GitLab From 440d57bc5ff55ec1efb3efc9cbe9420b4bbdfefa Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Wed, 10 Jul 2013 12:04:02 +0800 Subject: [PATCH 2614/2900] ifb: fix rcu_sched self-detected stalls According to the commit 16b0dc29c1af9df341428f4c49ada4f626258082 (dummy: fix rcu_sched self-detected stalls) Eric Dumazet fix the problem in dummy, but the ifb will occur the same problem like the dummy modules. Trying to "modprobe ifb numifbs=30000" triggers : INFO: rcu_sched self-detected stall on CPU After this splat, RTNL is locked and reboot is needed. We must call cond_resched() to avoid this, even holding RTNL. Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/ifb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index dc9f6a45515d..a11f7a45cb5f 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -292,8 +292,10 @@ static int __init ifb_init_module(void) rtnl_lock(); err = __rtnl_link_register(&ifb_link_ops); - for (i = 0; i < numifbs && !err; i++) + for (i = 0; i < numifbs && !err; i++) { err = ifb_init_one(i); + cond_resched(); + } if (err) __rtnl_link_unregister(&ifb_link_ops); rtnl_unlock(); -- GitLab From 3dd5c3308e8b671e8e8882ba972f51cefbe9fd0d Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 10 Jul 2013 13:43:27 +0800 Subject: [PATCH 2615/2900] tuntap: correctly linearize skb when zerocopy is used Userspace may produce vectors greater than MAX_SKB_FRAGS. When we try to linearize parts of the skb to let the rest of iov to be fit in the frags, we need count copylen into linear when calling tun_alloc_skb() instead of partly counting it into data_len. Since this breaks zerocopy_sg_from_iovec() since its inner counter assumes nr_frags should be zero at beginning. This cause nr_frags to be increased wrongly without setting the correct frags. This bug were introduced from 0690899b4d4501b3505be069b9a687e68ccbe15b (tun: experimental zero copy tx support) Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7eab5fcd064f..5cdcf92eb310 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1042,7 +1042,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, { struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; struct sk_buff *skb; - size_t len = total_len, align = NET_SKB_PAD; + size_t len = total_len, align = NET_SKB_PAD, linear; struct virtio_net_hdr gso = { 0 }; int offset = 0; int copylen; @@ -1106,10 +1106,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, copylen = gso.hdr_len; if (!copylen) copylen = GOODCOPY_LEN; - } else + linear = copylen; + } else { copylen = len; + linear = gso.hdr_len; + } - skb = tun_alloc_skb(tfile, align, copylen, gso.hdr_len, noblock); + skb = tun_alloc_skb(tfile, align, copylen, linear, noblock); if (IS_ERR(skb)) { if (PTR_ERR(skb) != -EAGAIN) tun->dev->stats.rx_dropped++; -- GitLab From 61d46bf979d5cd7c164709a80ad5676a35494aae Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 10 Jul 2013 13:43:28 +0800 Subject: [PATCH 2616/2900] macvtap: correctly linearize skb when zerocopy is used Userspace may produce vectors greater than MAX_SKB_FRAGS. When we try to linearize parts of the skb to let the rest of iov to be fit in the frags, we need count copylen into linear when calling macvtap_alloc_skb() instead of partly counting it into data_len. Since this breaks zerocopy_sg_from_iovec() since its inner counter assumes nr_frags should be zero at beginning. This cause nr_frags to be increased wrongly without setting the correct frags. This bug were introduced from b92946e2919134ebe2a4083e4302236295ea2a73 (macvtap: zerocopy: validate vectors before building skb). Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index f2c4a3b218fc..876c72246ae9 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -712,6 +712,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, int vnet_hdr_len = 0; int copylen = 0; bool zerocopy = false; + size_t linear; if (q->flags & IFF_VNET_HDR) { vnet_hdr_len = q->vnet_hdr_sz; @@ -766,11 +767,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, copylen = vnet_hdr.hdr_len; if (!copylen) copylen = GOODCOPY_LEN; - } else + linear = copylen; + } else { copylen = len; + linear = vnet_hdr.hdr_len; + } skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, - vnet_hdr.hdr_len, noblock, &err); + linear, noblock, &err); if (!skb) goto err; -- GitLab From 6d128e1e72bf082542e85f72e6b7ddd704193588 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 10 Jul 2013 19:02:51 -0700 Subject: [PATCH 2617/2900] Revert "Makefile: Fix install error with make -j option" This reverts commit d2aae8477cd00325bb7c7c7e95be488088900c48. It is completely and utterly broken. Module install should not build any files, and adding broken dependencies to "help" it build files is complete and utter sh*t. The kernel should not be built by root, and "make install" and "make module_install" (that for obvious reasons need to be run as root) absolutely must not build any files. They should only ever copy the already-built files over. So having dependencies for the install targets is wrong, wrong, wrong. If you try to install a kernel without building it first, you *should* get errors. The build system shouldn't try to help root build the files. Signed-off-by: Linus Torvalds --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e631e6c05f8e..4e3575c7ec35 100644 --- a/Makefile +++ b/Makefile @@ -981,7 +981,7 @@ _modinst_: # boot a modules.dep even before / is mounted read-write. However the # boot script depmod is the master version. PHONY += _modinst_post -_modinst_post: include/config/kernel.release _modinst_ +_modinst_post: _modinst_ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst $(call cmd,depmod) -- GitLab From 1eb4f758286884e7566627164bca4c4a16952a83 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Wed, 10 Jul 2013 23:00:57 +0200 Subject: [PATCH 2618/2900] ipv6: in case of link failure remove route directly instead of letting it expire We could end up expiring a route which is part of an ecmp route set. Doing so would invalidate the rt->rt6i_nsiblings calculations and could provoke the following panic: [ 80.144667] ------------[ cut here ]------------ [ 80.145172] kernel BUG at net/ipv6/ip6_fib.c:733! [ 80.145172] invalid opcode: 0000 [#1] SMP [ 80.145172] Modules linked in: 8021q nf_conntrack_netbios_ns nf_conntrack_broadcast ipt_MASQUERADE ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables +snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc snd_timer virtio_balloon snd soundcore i2c_piix4 i2c_core virtio_net virtio_blk [ 80.145172] CPU: 1 PID: 786 Comm: ping6 Not tainted 3.10.0+ #118 [ 80.145172] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 80.145172] task: ffff880117fa0000 ti: ffff880118770000 task.ti: ffff880118770000 [ 80.145172] RIP: 0010:[] [] fib6_add+0x75d/0x830 [ 80.145172] RSP: 0018:ffff880118771798 EFLAGS: 00010202 [ 80.145172] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88011350e480 [ 80.145172] RDX: ffff88011350e238 RSI: 0000000000000004 RDI: ffff88011350f738 [ 80.145172] RBP: ffff880118771848 R08: ffff880117903280 R09: 0000000000000001 [ 80.145172] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88011350f680 [ 80.145172] R13: ffff880117903280 R14: ffff880118771890 R15: ffff88011350ef90 [ 80.145172] FS: 00007f02b5127740(0000) GS:ffff88011fd00000(0000) knlGS:0000000000000000 [ 80.145172] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 80.145172] CR2: 00007f981322a000 CR3: 00000001181b1000 CR4: 00000000000006e0 [ 80.145172] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 80.145172] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 80.145172] Stack: [ 80.145172] 0000000000000001 ffff880100000000 ffff880100000000 ffff880117903280 [ 80.145172] 0000000000000000 ffff880119a4cf00 0000000000000400 00000000000007fa [ 80.145172] 0000000000000000 0000000000000000 0000000000000000 ffff88011350f680 [ 80.145172] Call Trace: [ 80.145172] [] ? rt6_bind_peer+0x4b/0x90 [ 80.145172] [] __ip6_ins_rt+0x45/0x70 [ 80.145172] [] ip6_ins_rt+0x35/0x40 [ 80.145172] [] ip6_pol_route.isra.44+0x3a4/0x4b0 [ 80.145172] [] ip6_pol_route_output+0x2a/0x30 [ 80.145172] [] fib6_rule_action+0xd7/0x210 [ 80.145172] [] ? ip6_pol_route_input+0x30/0x30 [ 80.145172] [] fib_rules_lookup+0xc6/0x140 [ 80.145172] [] fib6_rule_lookup+0x44/0x80 [ 80.145172] [] ? ip6_pol_route_input+0x30/0x30 [ 80.145172] [] ip6_route_output+0x73/0xb0 [ 80.145172] [] ip6_dst_lookup_tail+0x2c3/0x2e0 [ 80.145172] [] ? list_del+0x11/0x40 [ 80.145172] [] ? remove_wait_queue+0x3c/0x50 [ 80.145172] [] ip6_dst_lookup_flow+0x3d/0xa0 [ 80.145172] [] rawv6_sendmsg+0x267/0xc20 [ 80.145172] [] inet_sendmsg+0x63/0xb0 [ 80.145172] [] ? selinux_socket_sendmsg+0x23/0x30 [ 80.145172] [] sock_sendmsg+0xa6/0xd0 [ 80.145172] [] SYSC_sendto+0x128/0x180 [ 80.145172] [] ? update_curr+0xec/0x170 [ 80.145172] [] ? kvm_clock_get_cycles+0x9/0x10 [ 80.145172] [] ? __getnstimeofday+0x3e/0xd0 [ 80.145172] [] SyS_sendto+0xe/0x10 [ 80.145172] [] system_call_fastpath+0x16/0x1b [ 80.145172] Code: fe ff ff 41 f6 45 2a 06 0f 85 ca fe ff ff 49 8b 7e 08 4c 89 ee e8 94 ef ff ff e9 b9 fe ff ff 48 8b 82 28 05 00 00 e9 01 ff ff ff <0f> 0b 49 8b 54 24 30 0d 00 00 40 00 89 83 14 01 00 00 48 89 53 [ 80.145172] RIP [] fib6_add+0x75d/0x830 [ 80.145172] RSP [ 80.387413] ---[ end trace 02f20b7a8b81ed95 ]--- [ 80.390154] Kernel panic - not syncing: Fatal exception in interrupt Cc: Nicolas Dichtel Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/route.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bd5fd7054031..5b127e09c224 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1080,10 +1080,13 @@ static void ip6_link_failure(struct sk_buff *skb) rt = (struct rt6_info *) skb_dst(skb); if (rt) { - if (rt->rt6i_flags & RTF_CACHE) - rt6_update_expires(rt, 0); - else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) + if (rt->rt6i_flags & RTF_CACHE) { + dst_hold(&rt->dst); + if (ip6_del_rt(rt)) + dst_free(&rt->dst); + } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { rt->rt6i_node->fn_sernum = -1; + } } } -- GitLab From b41e6a51d57e231d2ed237f17f002cc536c0987c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 10 Jul 2013 23:03:34 +0200 Subject: [PATCH 2619/2900] sh_eth: SH_ETH should depend on HAS_DMA If NO_DMA=y: drivers/built-in.o: In function `sh_eth_free_dma_buffer': drivers/net/ethernet/renesas/sh_eth.c:1103: undefined reference to `dma_free_coherent' drivers/net/ethernet/renesas/sh_eth.c:1110: undefined reference to `dma_free_coherent' drivers/built-in.o: In function `sh_eth_ring_init': drivers/net/ethernet/renesas/sh_eth.c:1065: undefined reference to `dma_alloc_coherent' drivers/net/ethernet/renesas/sh_eth.c:1086: undefined reference to `dma_free_coherent' drivers/built-in.o: In function `sh_eth_ring_format': drivers/net/ethernet/renesas/sh_eth.c:988: undefined reference to `dma_map_single' drivers/built-in.o: In function `sh_eth_txfree': drivers/net/ethernet/renesas/sh_eth.c:1220: undefined reference to `dma_unmap_single' drivers/built-in.o: In function `sh_eth_rx': drivers/net/ethernet/renesas/sh_eth.c:1323: undefined reference to `dma_map_single' drivers/built-in.o: In function `sh_eth_start_xmit': drivers/net/ethernet/renesas/sh_eth.c:1954: undefined reference to `dma_map_single' Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 544514e66187..19a8a045e077 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -4,6 +4,7 @@ config SH_ETH tristate "Renesas SuperH Ethernet support" + depends on HAS_DMA select CRC32 select MII select MDIO_BITBANG -- GitLab From d320c079efd46db1be0640d00bd6723d9e738f9f Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 11 Jul 2013 07:30:33 +0100 Subject: [PATCH 2620/2900] efivars: check for EFI_RUNTIME_SERVICES The efivars code requires EFI runtime services to function, so check that they are enabled. This fixes a crash when booting with the "noefi" kernel parameter, and also when mixing kernel and firmware "bitness", e.g. 32-bit kernel with 64-bit firmware. Tested-by: Dave Young Signed-off-by: Matt Fleming --- drivers/firmware/efi/efivars.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 8bd1bb6dbe47..8a7432a4b413 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -583,6 +583,9 @@ int efivars_sysfs_init(void) struct kobject *parent_kobj = efivars_kobject(); int error = 0; + if (!efi_enabled(EFI_RUNTIME_SERVICES)) + return -ENODEV; + /* No efivars has been registered yet */ if (!parent_kobj) return 0; -- GitLab From 8216a67eb5e92224b4509b7f55ec4891c9021fdb Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 11 Jul 2013 10:32:32 +0100 Subject: [PATCH 2621/2900] Revert "UEFI: Don't pass boot services regions to SetVirtualAddressMap()" This reverts commit 1acba98f810a14b1255e34bc620594f83de37e36. The firmware on both Dave's Thinkpad and Maarten's Macbook Pro appear to rely on the old behaviour, and their machines fail to boot with the above commit. Reported-by: Dave Young Reported-by: Maarten Lankhorst Cc: Seth Forshee Cc: Matthew Garrett Signed-off-by: Matt Fleming --- arch/x86/platform/efi/efi.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index c8d5577044bb..90f6ed127096 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -931,13 +931,6 @@ void __init efi_enter_virtual_mode(void) va = efi_ioremap(md->phys_addr, size, md->type, md->attribute); - if (!(md->attribute & EFI_MEMORY_RUNTIME)) { - if (!va) - pr_err("ioremap of 0x%llX failed!\n", - (unsigned long long)md->phys_addr); - continue; - } - md->virt_addr = (u64) (unsigned long) va; if (!va) { -- GitLab From 103ccee4ef1595468cf79c93068d253c7f2d85a8 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Wed, 10 Jul 2013 10:38:18 -0600 Subject: [PATCH 2622/2900] spi: revert master->setup function removal for altera and nuc900 Commit 24778be "spi: convert drivers to use bits_per_word_mask" removed what appeared to be redundant code from many drivers. However, it appears that in the spi-bitbang case, these functions are required by the spi-bitbang core, even if they don't do anything. Restore them. For 3.12, the spi-bitbang core should be adjusted not to require these callbacks to exist if they don't need to do anything. This is the equivalent of Michal Simek's patch "spi/xilinx: Revert master->setup function removal", applied to other affected drivers. Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- drivers/spi/spi-altera.c | 12 ++++++++++++ drivers/spi/spi-nuc900.c | 13 +++++++++++++ 2 files changed, 25 insertions(+) diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c index 8a6bb37910da..81b9adb6e766 100644 --- a/drivers/spi/spi-altera.c +++ b/drivers/spi/spi-altera.c @@ -103,6 +103,16 @@ static void altera_spi_chipsel(struct spi_device *spi, int value) } } +static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) +{ + return 0; +} + +static int altera_spi_setup(struct spi_device *spi) +{ + return 0; +} + static inline unsigned int hw_txbyte(struct altera_spi *hw, int count) { if (hw->tx) { @@ -221,6 +231,7 @@ static int altera_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = 16; master->mode_bits = SPI_CS_HIGH; + master->setup = altera_spi_setup; hw = spi_master_get_devdata(master); platform_set_drvdata(pdev, hw); @@ -229,6 +240,7 @@ static int altera_spi_probe(struct platform_device *pdev) hw->bitbang.master = spi_master_get(master); if (!hw->bitbang.master) return err; + hw->bitbang.setup_transfer = altera_spi_setupxfer; hw->bitbang.chipselect = altera_spi_chipsel; hw->bitbang.txrx_bufs = altera_spi_txrx; diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c index 2ad3d74ac021..150d85453c27 100644 --- a/drivers/spi/spi-nuc900.c +++ b/drivers/spi/spi-nuc900.c @@ -174,6 +174,17 @@ static void nuc900_spi_gobusy(struct nuc900_spi *hw) spin_unlock_irqrestore(&hw->lock, flags); } +static int nuc900_spi_setupxfer(struct spi_device *spi, + struct spi_transfer *t) +{ + return 0; +} + +static int nuc900_spi_setup(struct spi_device *spi) +{ + return 0; +} + static inline unsigned int hw_txbyte(struct nuc900_spi *hw, int count) { return hw->tx ? hw->tx[count] : 0; @@ -366,8 +377,10 @@ static int nuc900_spi_probe(struct platform_device *pdev) master->num_chipselect = hw->pdata->num_cs; master->bus_num = hw->pdata->bus_num; hw->bitbang.master = hw->master; + hw->bitbang.setup_transfer = nuc900_spi_setupxfer; hw->bitbang.chipselect = nuc900_spi_chipsel; hw->bitbang.txrx_bufs = nuc900_spi_txrx; + hw->bitbang.master->setup = nuc900_spi_setup; hw->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (hw->res == NULL) { -- GitLab From 770100108be7dbe614361dbcc450096b4cdfc98b Mon Sep 17 00:00:00 2001 From: Padmavathi Venna Date: Thu, 11 Jul 2013 12:38:25 +0530 Subject: [PATCH 2623/2900] ASoC: Samsung: Set RFS and BFS in slave mode As per the User Manual, the RFS and BFS should be set in slave mode for correct operation. Signed-off-by: Padmavathi Venna Signed-off-by: Andrew Bresticker Reviewed-by: Simon Glass Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 7a1734697434..959c702235c8 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -742,13 +742,13 @@ static int config_setup(struct i2s_dai *i2s) return -EAGAIN; } - /* Don't bother RFS, BFS & PSR in Slave mode */ - if (is_slave(i2s)) - return 0; - set_bfs(i2s, bfs); set_rfs(i2s, rfs); + /* Don't bother with PSR in Slave mode */ + if (is_slave(i2s)) + return 0; + if (!(i2s->quirks & QUIRK_NO_MUXPSR)) { psr = i2s->rclk_srcrate / i2s->frmclk / rfs; writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR); -- GitLab From 92f8ff73f18672b03ec8b92197cdddf2b5de7ea0 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Thu, 11 Jul 2013 00:00:40 -0500 Subject: [PATCH 2624/2900] xfs: Add pquota fields where gquota is used. Add project quota changes to all the places where group quota field is used: * add separate project quota members into various structures * split project quota and group quotas so that instead of overriding the group quota members incore, the new project quota members are used instead * get rid of usage of the OQUOTA flag incore, in favor of separate group and project quota flags. * add a project dquot argument to various functions. Not using the pquotino field from superblock yet. Signed-off-by: Chandra Seetharaman Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_dquot.c | 15 ++- fs/xfs/xfs_dquot.h | 7 +- fs/xfs/xfs_icache.c | 1 + fs/xfs/xfs_inode.h | 1 + fs/xfs/xfs_ioctl.c | 14 +-- fs/xfs/xfs_iops.c | 4 +- fs/xfs/xfs_qm.c | 243 ++++++++++++++++++++++++++++----------- fs/xfs/xfs_qm.h | 20 ++-- fs/xfs/xfs_qm_bhv.c | 10 +- fs/xfs/xfs_qm_syscalls.c | 19 ++- fs/xfs/xfs_quota.h | 32 +++--- fs/xfs/xfs_symlink.c | 10 +- fs/xfs/xfs_trans_dquot.c | 26 ++++- fs/xfs/xfs_vnodeops.c | 13 ++- 14 files changed, 291 insertions(+), 124 deletions(-) diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index f01012de06d0..0adf27ecf3f1 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -936,6 +936,7 @@ xfs_qm_dqput_final( { struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; struct xfs_dquot *gdqp; + struct xfs_dquot *pdqp; trace_xfs_dqput_free(dqp); @@ -949,21 +950,29 @@ xfs_qm_dqput_final( /* * If we just added a udquot to the freelist, then we want to release - * the gdquot reference that it (probably) has. Otherwise it'll keep - * the gdquot from getting reclaimed. + * the gdquot/pdquot reference that it (probably) has. Otherwise it'll + * keep the gdquot/pdquot from getting reclaimed. */ gdqp = dqp->q_gdquot; if (gdqp) { xfs_dqlock(gdqp); dqp->q_gdquot = NULL; } + + pdqp = dqp->q_pdquot; + if (pdqp) { + xfs_dqlock(pdqp); + dqp->q_pdquot = NULL; + } xfs_dqunlock(dqp); /* - * If we had a group quota hint, release it now. + * If we had a group/project quota hint, release it now. */ if (gdqp) xfs_qm_dqput(gdqp); + if (pdqp) + xfs_qm_dqput(pdqp); } /* diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h index b596626249b8..55abbca2883d 100644 --- a/fs/xfs/xfs_dquot.h +++ b/fs/xfs/xfs_dquot.h @@ -53,6 +53,7 @@ typedef struct xfs_dquot { xfs_fileoff_t q_fileoffset; /* offset in quotas file */ struct xfs_dquot*q_gdquot; /* group dquot, hint only */ + struct xfs_dquot*q_pdquot; /* project dquot, hint only */ xfs_disk_dquot_t q_core; /* actual usage & quotas */ xfs_dq_logitem_t q_logitem; /* dquot log item */ xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ @@ -118,8 +119,9 @@ static inline int xfs_this_quota_on(struct xfs_mount *mp, int type) case XFS_DQ_USER: return XFS_IS_UQUOTA_ON(mp); case XFS_DQ_GROUP: + return XFS_IS_GQUOTA_ON(mp); case XFS_DQ_PROJ: - return XFS_IS_OQUOTA_ON(mp); + return XFS_IS_PQUOTA_ON(mp); default: return 0; } @@ -131,8 +133,9 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type) case XFS_DQ_USER: return ip->i_udquot; case XFS_DQ_GROUP: - case XFS_DQ_PROJ: return ip->i_gdquot; + case XFS_DQ_PROJ: + return ip->i_pdquot; default: return NULL; } diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 9560dc1f15a9..3f90e1ceb8d6 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -337,6 +337,7 @@ xfs_iget_cache_miss( iflags |= XFS_IDONTCACHE; ip->i_udquot = NULL; ip->i_gdquot = NULL; + ip->i_pdquot = NULL; xfs_iflags_set(ip, iflags); /* insert the new inode */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 91129794aaec..b55fd347ab5b 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -250,6 +250,7 @@ typedef struct xfs_inode { struct xfs_mount *i_mount; /* fs mount struct ptr */ struct xfs_dquot *i_udquot; /* user dquot */ struct xfs_dquot *i_gdquot; /* group dquot */ + struct xfs_dquot *i_pdquot; /* project dquot */ /* Inode location stuff */ xfs_ino_t i_ino; /* inode number (agno/agino)*/ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index dc5b65983e5f..6e2bca5d44d6 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -928,7 +928,7 @@ xfs_ioctl_setattr( struct xfs_trans *tp; unsigned int lock_flags = 0; struct xfs_dquot *udqp = NULL; - struct xfs_dquot *gdqp = NULL; + struct xfs_dquot *pdqp = NULL; struct xfs_dquot *olddquot = NULL; int code; @@ -957,7 +957,7 @@ xfs_ioctl_setattr( if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, ip->i_d.di_gid, fa->fsx_projid, - XFS_QMOPT_PQUOTA, &udqp, &gdqp); + XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp); if (code) return code; } @@ -994,8 +994,8 @@ xfs_ioctl_setattr( XFS_IS_PQUOTA_ON(mp) && xfs_get_projid(ip) != fa->fsx_projid) { ASSERT(tp); - code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, - capable(CAP_FOWNER) ? + code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, + pdqp, capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0); if (code) /* out of quota */ goto error_return; @@ -1113,7 +1113,7 @@ xfs_ioctl_setattr( if (xfs_get_projid(ip) != fa->fsx_projid) { if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) { olddquot = xfs_qm_vop_chown(tp, ip, - &ip->i_gdquot, gdqp); + &ip->i_pdquot, pdqp); } xfs_set_projid(ip, fa->fsx_projid); @@ -1160,13 +1160,13 @@ xfs_ioctl_setattr( */ xfs_qm_dqrele(olddquot); xfs_qm_dqrele(udqp); - xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); return code; error_return: xfs_qm_dqrele(udqp); - xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); xfs_trans_cancel(tp, 0); if (lock_flags) xfs_iunlock(ip, lock_flags); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 8865261e5417..96dda62d497b 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -539,7 +539,7 @@ xfs_setattr_nonsize( ASSERT(udqp == NULL); ASSERT(gdqp == NULL); error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip), - qflags, &udqp, &gdqp); + qflags, &udqp, &gdqp, NULL); if (error) return error; } @@ -575,7 +575,7 @@ xfs_setattr_nonsize( (XFS_IS_GQUOTA_ON(mp) && igid != gid))) { ASSERT(tp); error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, - capable(CAP_FOWNER) ? + NULL, capable(CAP_FOWNER) ? XFS_QMOPT_FORCE_RES : 0); if (error) /* out of quota */ goto out_trans_cancel; diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 7a3e007b49f4..d320794d03ce 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -137,6 +137,7 @@ xfs_qm_dqpurge( struct xfs_mount *mp = dqp->q_mount; struct xfs_quotainfo *qi = mp->m_quotainfo; struct xfs_dquot *gdqp = NULL; + struct xfs_dquot *pdqp = NULL; xfs_dqlock(dqp); if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { @@ -145,8 +146,7 @@ xfs_qm_dqpurge( } /* - * If this quota has a group hint attached, prepare for releasing it - * now. + * If this quota has a hint attached, prepare for releasing it now. */ gdqp = dqp->q_gdquot; if (gdqp) { @@ -154,6 +154,12 @@ xfs_qm_dqpurge( dqp->q_gdquot = NULL; } + pdqp = dqp->q_pdquot; + if (pdqp) { + xfs_dqlock(pdqp); + dqp->q_pdquot = NULL; + } + dqp->dq_flags |= XFS_DQ_FREEING; xfs_dqflock(dqp); @@ -208,6 +214,8 @@ xfs_qm_dqpurge( if (gdqp) xfs_qm_dqput(gdqp); + if (pdqp) + xfs_qm_dqput(pdqp); return 0; } @@ -364,6 +372,10 @@ xfs_qm_unmount_quotas( IRELE(mp->m_quotainfo->qi_gquotaip); mp->m_quotainfo->qi_gquotaip = NULL; } + if (mp->m_quotainfo->qi_pquotaip) { + IRELE(mp->m_quotainfo->qi_pquotaip); + mp->m_quotainfo->qi_pquotaip = NULL; + } } } @@ -410,7 +422,10 @@ xfs_qm_dqattach_one( * be reclaimed as long as we have a ref from inode and we * hold the ilock. */ - dqp = udqhint->q_gdquot; + if (type == XFS_DQ_GROUP) + dqp = udqhint->q_gdquot; + else + dqp = udqhint->q_pdquot; if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { ASSERT(*IO_idqpp == NULL); @@ -453,28 +468,42 @@ xfs_qm_dqattach_one( /* - * Given a udquot and gdquot, attach a ptr to the group dquot in the - * udquot as a hint for future lookups. + * Given a udquot and group/project type, attach the group/project + * dquot pointer to the udquot as a hint for future lookups. */ STATIC void -xfs_qm_dqattach_grouphint( - xfs_dquot_t *udq, - xfs_dquot_t *gdq) +xfs_qm_dqattach_hint( + struct xfs_inode *ip, + int type) { - xfs_dquot_t *tmp; + struct xfs_dquot **dqhintp; + struct xfs_dquot *dqp; + struct xfs_dquot *udq = ip->i_udquot; + + ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); xfs_dqlock(udq); - tmp = udq->q_gdquot; - if (tmp) { - if (tmp == gdq) + if (type == XFS_DQ_GROUP) { + dqp = ip->i_gdquot; + dqhintp = &udq->q_gdquot; + } else { + dqp = ip->i_pdquot; + dqhintp = &udq->q_pdquot; + } + + if (*dqhintp) { + struct xfs_dquot *tmp; + + if (*dqhintp == dqp) goto done; - udq->q_gdquot = NULL; + tmp = *dqhintp; + *dqhintp = NULL; xfs_qm_dqrele(tmp); } - udq->q_gdquot = xfs_qm_dqhold(gdq); + *dqhintp = xfs_qm_dqhold(dqp); done: xfs_dqunlock(udq); } @@ -527,12 +556,8 @@ xfs_qm_dqattach_locked( } ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - if (XFS_IS_OQUOTA_ON(mp)) { - error = XFS_IS_GQUOTA_ON(mp) ? - xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, - flags & XFS_QMOPT_DQALLOC, - ip->i_udquot, &ip->i_gdquot) : - xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, + if (XFS_IS_GQUOTA_ON(mp)) { + error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, flags & XFS_QMOPT_DQALLOC, ip->i_udquot, &ip->i_gdquot); /* @@ -544,14 +569,28 @@ xfs_qm_dqattach_locked( nquotas++; } + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + if (XFS_IS_PQUOTA_ON(mp)) { + error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ, + flags & XFS_QMOPT_DQALLOC, + ip->i_udquot, &ip->i_pdquot); + /* + * Don't worry about the udquot that we may have + * attached above. It'll get detached, if not already. + */ + if (error) + goto done; + nquotas++; + } + /* - * Attach this group quota to the user quota as a hint. + * Attach this group/project quota to the user quota as a hint. * This WON'T, in general, result in a thrash. */ - if (nquotas == 2) { + if (nquotas > 1 && ip->i_udquot) { ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - ASSERT(ip->i_udquot); - ASSERT(ip->i_gdquot); + ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp)); + ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp)); /* * We do not have i_udquot locked at this point, but this check @@ -560,7 +599,10 @@ xfs_qm_dqattach_locked( * succeed in general. */ if (ip->i_udquot->q_gdquot != ip->i_gdquot) - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP); + + if (ip->i_udquot->q_pdquot != ip->i_pdquot) + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ); } done: @@ -568,8 +610,10 @@ xfs_qm_dqattach_locked( if (!error) { if (XFS_IS_UQUOTA_ON(mp)) ASSERT(ip->i_udquot); - if (XFS_IS_OQUOTA_ON(mp)) + if (XFS_IS_GQUOTA_ON(mp)) ASSERT(ip->i_gdquot); + if (XFS_IS_PQUOTA_ON(mp)) + ASSERT(ip->i_pdquot); } ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); #endif @@ -602,7 +646,7 @@ void xfs_qm_dqdetach( xfs_inode_t *ip) { - if (!(ip->i_udquot || ip->i_gdquot)) + if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot)) return; trace_xfs_dquot_dqdetach(ip); @@ -616,6 +660,10 @@ xfs_qm_dqdetach( xfs_qm_dqrele(ip->i_gdquot); ip->i_gdquot = NULL; } + if (ip->i_pdquot) { + xfs_qm_dqrele(ip->i_pdquot); + ip->i_pdquot = NULL; + } } int @@ -660,6 +708,7 @@ xfs_qm_init_quotainfo( INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); + INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS); mutex_init(&qinf->qi_tree_lock); INIT_LIST_HEAD(&qinf->qi_lru_list); @@ -761,6 +810,10 @@ xfs_qm_destroy_quotainfo( IRELE(qi->qi_gquotaip); qi->qi_gquotaip = NULL; } + if (qi->qi_pquotaip) { + IRELE(qi->qi_pquotaip); + qi->qi_pquotaip = NULL; + } mutex_destroy(&qi->qi_quotaofflock); kmem_free(qi); mp->m_quotainfo = NULL; @@ -1269,13 +1322,14 @@ xfs_qm_quotacheck( LIST_HEAD (buffer_list); struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; + struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip; count = INT_MAX; structsz = 1; lastino = 0; flags = 0; - ASSERT(uip || gip); + ASSERT(uip || gip || pip); ASSERT(XFS_IS_QUOTA_RUNNING(mp)); xfs_notice(mp, "Quotacheck needed: Please wait."); @@ -1294,13 +1348,19 @@ xfs_qm_quotacheck( } if (gip) { - error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ? - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA, + error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA, &buffer_list); if (error) goto error_return; - flags |= XFS_IS_GQUOTA_ON(mp) ? - XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD; + flags |= XFS_GQUOTA_CHKD; + } + + if (pip) { + error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA, + &buffer_list); + if (error) + goto error_return; + flags |= XFS_PQUOTA_CHKD; } do { @@ -1397,6 +1457,7 @@ xfs_qm_init_quotainos( { struct xfs_inode *uip = NULL; struct xfs_inode *gip = NULL; + struct xfs_inode *pip = NULL; int error; __int64_t sbflags = 0; uint flags = 0; @@ -1415,7 +1476,7 @@ xfs_qm_init_quotainos( if (error) return XFS_ERROR(error); } - if (XFS_IS_OQUOTA_ON(mp) && + if (XFS_IS_GQUOTA_ON(mp) && mp->m_sb.sb_gquotino != NULLFSINO) { ASSERT(mp->m_sb.sb_gquotino > 0); error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, @@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos( if (error) goto error_rele; } + /* XXX: Use gquotino for now */ + if (XFS_IS_PQUOTA_ON(mp) && + mp->m_sb.sb_gquotino != NULLFSINO) { + ASSERT(mp->m_sb.sb_gquotino > 0); + error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, + 0, 0, &pip); + if (error) + goto error_rele; + } } else { flags |= XFS_QMOPT_SBVERSION; sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | @@ -1430,7 +1500,7 @@ xfs_qm_init_quotainos( } /* - * Create the two inodes, if they don't exist already. The changes + * Create the three inodes, if they don't exist already. The changes * made above will get added to a transaction and logged in one of * the qino_alloc calls below. If the device is readonly, * temporarily switch to read-write to do this. @@ -1444,17 +1514,27 @@ xfs_qm_init_quotainos( flags &= ~XFS_QMOPT_SBVERSION; } - if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) { - flags |= (XFS_IS_GQUOTA_ON(mp) ? - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA); + if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { error = xfs_qm_qino_alloc(mp, &gip, - sbflags | XFS_SB_GQUOTINO, flags); + sbflags | XFS_SB_GQUOTINO, + flags | XFS_QMOPT_GQUOTA); + if (error) + goto error_rele; + + flags &= ~XFS_QMOPT_SBVERSION; + } + if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) { + /* XXX: Use XFS_SB_GQUOTINO for now */ + error = xfs_qm_qino_alloc(mp, &pip, + sbflags | XFS_SB_GQUOTINO, + flags | XFS_QMOPT_PQUOTA); if (error) goto error_rele; } mp->m_quotainfo->qi_uquotaip = uip; mp->m_quotainfo->qi_gquotaip = gip; + mp->m_quotainfo->qi_pquotaip = pip; return 0; @@ -1463,6 +1543,8 @@ xfs_qm_init_quotainos( IRELE(uip); if (gip) IRELE(gip); + if (pip) + IRELE(pip); return XFS_ERROR(error); } @@ -1657,11 +1739,13 @@ xfs_qm_vop_dqalloc( prid_t prid, uint flags, struct xfs_dquot **O_udqpp, - struct xfs_dquot **O_gdqpp) + struct xfs_dquot **O_gdqpp, + struct xfs_dquot **O_pdqpp) { struct xfs_mount *mp = ip->i_mount; struct xfs_dquot *uq = NULL; struct xfs_dquot *gq = NULL; + struct xfs_dquot *pq = NULL; int error; uint lockflags; @@ -1741,24 +1825,25 @@ xfs_qm_vop_dqalloc( ASSERT(ip->i_gdquot); gq = xfs_qm_dqhold(ip->i_gdquot); } - } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { + } + if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { if (xfs_get_projid(ip) != prid) { xfs_iunlock(ip, lockflags); error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, XFS_DQ_PROJ, XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN, - &gq); + &pq); if (error) { ASSERT(error != ENOENT); goto error_rele; } - xfs_dqunlock(gq); + xfs_dqunlock(pq); lockflags = XFS_ILOCK_SHARED; xfs_ilock(ip, lockflags); } else { - ASSERT(ip->i_gdquot); - gq = xfs_qm_dqhold(ip->i_gdquot); + ASSERT(ip->i_pdquot); + pq = xfs_qm_dqhold(ip->i_pdquot); } } if (uq) @@ -1773,9 +1858,15 @@ xfs_qm_vop_dqalloc( *O_gdqpp = gq; else if (gq) xfs_qm_dqrele(gq); + if (O_pdqpp) + *O_pdqpp = pq; + else if (pq) + xfs_qm_dqrele(pq); return 0; error_rele: + if (gq) + xfs_qm_dqrele(gq); if (uq) xfs_qm_dqrele(uq); return error; @@ -1830,14 +1921,17 @@ xfs_qm_vop_chown_reserve( struct xfs_inode *ip, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, uint flags) { struct xfs_mount *mp = ip->i_mount; uint delblks, blkflags, prjflags = 0; struct xfs_dquot *udq_unres = NULL; struct xfs_dquot *gdq_unres = NULL; + struct xfs_dquot *pdq_unres = NULL; struct xfs_dquot *udq_delblks = NULL; struct xfs_dquot *gdq_delblks = NULL; + struct xfs_dquot *pdq_delblks = NULL; int error; @@ -1861,24 +1955,28 @@ xfs_qm_vop_chown_reserve( udq_unres = ip->i_udquot; } } - if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { - if (XFS_IS_PQUOTA_ON(ip->i_mount) && - xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) - prjflags = XFS_QMOPT_ENOSPC; - - if (prjflags || - (XFS_IS_GQUOTA_ON(ip->i_mount) && - ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { - gdq_delblks = gdqp; - if (delblks) { - ASSERT(ip->i_gdquot); - gdq_unres = ip->i_gdquot; - } + if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && + ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) { + gdq_delblks = gdqp; + if (delblks) { + ASSERT(ip->i_gdquot); + gdq_unres = ip->i_gdquot; + } + } + + if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp && + xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) { + prjflags = XFS_QMOPT_ENOSPC; + pdq_delblks = pdqp; + if (delblks) { + ASSERT(ip->i_pdquot); + pdq_unres = ip->i_pdquot; } } error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, - udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1, + udq_delblks, gdq_delblks, pdq_delblks, + ip->i_d.di_nblocks, 1, flags | blkflags | prjflags); if (error) return error; @@ -1893,16 +1991,17 @@ xfs_qm_vop_chown_reserve( /* * Do the reservations first. Unreservation can't fail. */ - ASSERT(udq_delblks || gdq_delblks); - ASSERT(udq_unres || gdq_unres); + ASSERT(udq_delblks || gdq_delblks || pdq_delblks); + ASSERT(udq_unres || gdq_unres || pdq_unres); error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, - udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0, + udq_delblks, gdq_delblks, pdq_delblks, + (xfs_qcnt_t)delblks, 0, flags | blkflags | prjflags); if (error) return error; xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, - udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0, - blkflags); + udq_unres, gdq_unres, pdq_unres, + -((xfs_qcnt_t)delblks), 0, blkflags); } return (0); @@ -1941,7 +2040,8 @@ xfs_qm_vop_create_dqattach( struct xfs_trans *tp, struct xfs_inode *ip, struct xfs_dquot *udqp, - struct xfs_dquot *gdqp) + struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp) { struct xfs_mount *mp = tp->t_mountp; @@ -1961,13 +2061,18 @@ xfs_qm_vop_create_dqattach( } if (gdqp) { ASSERT(ip->i_gdquot == NULL); - ASSERT(XFS_IS_OQUOTA_ON(mp)); - ASSERT((XFS_IS_GQUOTA_ON(mp) ? - ip->i_d.di_gid : xfs_get_projid(ip)) == - be32_to_cpu(gdqp->q_core.d_id)); - + ASSERT(XFS_IS_GQUOTA_ON(mp)); + ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id)); ip->i_gdquot = xfs_qm_dqhold(gdqp); xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); } + if (pdqp) { + ASSERT(ip->i_pdquot == NULL); + ASSERT(XFS_IS_PQUOTA_ON(mp)); + ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id)); + + ip->i_pdquot = xfs_qm_dqhold(pdqp); + xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1); + } } diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index bdb4f8b95207..579d6a02a5b6 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h @@ -44,9 +44,11 @@ extern struct kmem_zone *xfs_qm_dqtrxzone; typedef struct xfs_quotainfo { struct radix_tree_root qi_uquota_tree; struct radix_tree_root qi_gquota_tree; + struct radix_tree_root qi_pquota_tree; struct mutex qi_tree_lock; - xfs_inode_t *qi_uquotaip; /* user quota inode */ - xfs_inode_t *qi_gquotaip; /* group quota inode */ + struct xfs_inode *qi_uquotaip; /* user quota inode */ + struct xfs_inode *qi_gquotaip; /* group quota inode */ + struct xfs_inode *qi_pquotaip; /* project quota inode */ struct list_head qi_lru_list; struct mutex qi_lru_lock; int qi_lru_count; @@ -78,8 +80,9 @@ xfs_dquot_tree( case XFS_DQ_USER: return &qi->qi_uquota_tree; case XFS_DQ_GROUP: - case XFS_DQ_PROJ: return &qi->qi_gquota_tree; + case XFS_DQ_PROJ: + return &qi->qi_pquota_tree; default: ASSERT(0); } @@ -93,8 +96,9 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp) case XFS_DQ_USER: return dqp->q_mount->m_quotainfo->qi_uquotaip; case XFS_DQ_GROUP: - case XFS_DQ_PROJ: return dqp->q_mount->m_quotainfo->qi_gquotaip; + case XFS_DQ_PROJ: + return dqp->q_mount->m_quotainfo->qi_pquotaip; default: ASSERT(0); } @@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *, struct xfs_dquot *, uint, long); extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, - struct xfs_dquot *, long, long, uint); + struct xfs_dquot *, struct xfs_dquot *, + long, long, uint); extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *); extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *); /* - * We keep the usr and grp dquots separately so that locking will be easier - * to do at commit time. All transactions that we know of at this point + * We keep the usr, grp, and prj dquots separately so that locking will be + * easier to do at commit time. All transactions that we know of at this point * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value. */ enum { XFS_QM_TRANS_USR = 0, XFS_QM_TRANS_GRP, + XFS_QM_TRANS_PRJ, XFS_QM_TRANS_DQTYPES }; #define XFS_QM_TRANS_MAXDQS 2 diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c index 2d02eac1c9a8..437a52d91f6d 100644 --- a/fs/xfs/xfs_qm_bhv.c +++ b/fs/xfs/xfs_qm_bhv.c @@ -112,16 +112,16 @@ xfs_qm_newmount( if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || - (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) || - (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) || (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || - (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) && + (!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) || + (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) || + (!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) && xfs_dev_is_read_only(mp, "changing quota state")) { xfs_warn(mp, "please mount with%s%s%s%s.", (!quotaondisk ? "out quota" : ""), (uquotaondisk ? " usrquota" : ""), - (pquotaondisk ? " prjquota" : ""), - (gquotaondisk ? " grpquota" : "")); + (gquotaondisk ? " grpquota" : ""), + (pquotaondisk ? " prjquota" : "")); return XFS_ERROR(EPERM); } diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index a08801ae24e2..b9363838b42b 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -119,7 +119,8 @@ xfs_qm_scall_quotaoff( dqtype |= XFS_QMOPT_GQUOTA; flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); inactivate_flags |= XFS_GQUOTA_ACTIVE; - } else if (flags & XFS_PQUOTA_ACCT) { + } + if (flags & XFS_PQUOTA_ACCT) { dqtype |= XFS_QMOPT_PQUOTA; flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD); inactivate_flags |= XFS_PQUOTA_ACTIVE; @@ -214,10 +215,14 @@ xfs_qm_scall_quotaoff( IRELE(q->qi_uquotaip); q->qi_uquotaip = NULL; } - if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) { + if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) { IRELE(q->qi_gquotaip); q->qi_gquotaip = NULL; } + if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) { + IRELE(q->qi_pquotaip); + q->qi_pquotaip = NULL; + } out_unlock: mutex_unlock(&q->qi_quotaofflock); @@ -859,9 +864,11 @@ xfs_dqrele_inode( { /* skip quota inodes */ if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || - ip == ip->i_mount->m_quotainfo->qi_gquotaip) { + ip == ip->i_mount->m_quotainfo->qi_gquotaip || + ip == ip->i_mount->m_quotainfo->qi_pquotaip) { ASSERT(ip->i_udquot == NULL); ASSERT(ip->i_gdquot == NULL); + ASSERT(ip->i_pdquot == NULL); return 0; } @@ -870,10 +877,14 @@ xfs_dqrele_inode( xfs_qm_dqrele(ip->i_udquot); ip->i_udquot = NULL; } - if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { + if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) { xfs_qm_dqrele(ip->i_gdquot); ip->i_gdquot = NULL; } + if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) { + xfs_qm_dqrele(ip->i_pdquot); + ip->i_pdquot = NULL; + } xfs_iunlock(ip, XFS_ILOCK_EXCL); return 0; } diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 40d508be9a00..09777c41d5b7 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -288,10 +288,10 @@ typedef struct xfs_qoff_logformat { * we didn't have the inode locked, the appropriate dquot(s) will be * attached atomically. */ -#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ - (ip)->i_udquot == NULL) || \ - (XFS_IS_OQUOTA_ON(mp) && \ - (ip)->i_gdquot == NULL)) +#define XFS_NOT_DQATTACHED(mp, ip) \ + ((XFS_IS_UQUOTA_ON(mp) && (ip)->i_udquot == NULL) || \ + (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \ + (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL)) #define XFS_QM_NEED_QUOTACHECK(mp) \ ((XFS_IS_UQUOTA_ON(mp) && \ @@ -346,17 +346,18 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *, struct xfs_inode *, long, long, uint); extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, struct xfs_mount *, struct xfs_dquot *, - struct xfs_dquot *, long, long, uint); + struct xfs_dquot *, struct xfs_dquot *, long, long, uint); extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint, - struct xfs_dquot **, struct xfs_dquot **); + struct xfs_dquot **, struct xfs_dquot **, struct xfs_dquot **); extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *, - struct xfs_dquot *, struct xfs_dquot *); + struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *); extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *, - struct xfs_dquot *, struct xfs_dquot *, uint); + struct xfs_dquot *, struct xfs_dquot *, + struct xfs_dquot *, uint); extern int xfs_qm_dqattach(struct xfs_inode *, uint); extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint); extern void xfs_qm_dqdetach(struct xfs_inode *); @@ -370,10 +371,12 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *); #else static inline int xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid, - uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp) + uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp, + struct xfs_dquot **pdqp) { *udqp = NULL; *gdqp = NULL; + *pdqp = NULL; return 0; } #define xfs_trans_dup_dqinfo(tp, tp2) @@ -388,14 +391,15 @@ static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, } static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, struct xfs_mount *mp, struct xfs_dquot *udqp, - struct xfs_dquot *gdqp, long nblks, long nions, uint flags) + struct xfs_dquot *gdqp, struct xfs_dquot *pdqp, + long nblks, long nions, uint flags) { return 0; } -#define xfs_qm_vop_create_dqattach(tp, ip, u, g) +#define xfs_qm_vop_create_dqattach(tp, ip, u, g, p) #define xfs_qm_vop_rename_dqattach(it) (0) #define xfs_qm_vop_chown(tp, ip, old, new) (NULL) -#define xfs_qm_vop_chown_reserve(tp, ip, u, g, fl) (0) +#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0) #define xfs_qm_dqattach(ip, fl) (0) #define xfs_qm_dqattach_locked(ip, fl) (0) #define xfs_qm_dqdetach(ip) @@ -409,8 +413,8 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, #define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \ xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags) -#define xfs_trans_reserve_quota(tp, mp, ud, gd, nb, ni, f) \ - xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ +#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \ + xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \ f | XFS_QMOPT_RES_REGBLKS) extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index e830fb56e27f..f4895b662fcb 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -360,6 +360,7 @@ xfs_symlink( prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; + struct xfs_dquot *pdqp = NULL; uint resblks; *ipp = NULL; @@ -386,7 +387,7 @@ xfs_symlink( * Make sure that we have allocated dquot(s) on disk. */ error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp); if (error) goto std_return; @@ -427,7 +428,8 @@ xfs_symlink( /* * Reserve disk quota : blocks and inode. */ - error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); + error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, + pdqp, resblks, 1, 0); if (error) goto error_return; @@ -465,7 +467,7 @@ xfs_symlink( /* * Also attach the dquot(s) to it, if applicable. */ - xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); + xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); if (resblks) resblks -= XFS_IALLOC_SPACE_RES(mp); @@ -563,6 +565,7 @@ xfs_symlink( error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); *ipp = ip; return 0; @@ -576,6 +579,7 @@ xfs_symlink( xfs_trans_cancel(tp, cancel_flags); xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index db041a5e1f6d..61407a847b86 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -163,8 +163,10 @@ xfs_trans_mod_dquot_byino( if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); - if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot) + if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); + if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot) + (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta); } STATIC struct xfs_dqtrx * @@ -177,8 +179,12 @@ xfs_trans_get_dqtrx( if (XFS_QM_ISUDQ(dqp)) qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR]; - else + else if (XFS_QM_ISGDQ(dqp)) qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP]; + else if (XFS_QM_ISPDQ(dqp)) + qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ]; + else + return NULL; for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { if (qa[i].qt_dquot == NULL || @@ -727,8 +733,8 @@ xfs_trans_dqresv( /* * Given dquot(s), make disk block and/or inode reservations against them. - * The fact that this does the reservation against both the usr and - * grp/prj quotas is important, because this follows a both-or-nothing + * The fact that this does the reservation against user, group and + * project quotas is important, because this follows a all-or-nothing * approach. * * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. @@ -743,6 +749,7 @@ xfs_trans_reserve_quota_bydquots( struct xfs_mount *mp, struct xfs_dquot *udqp, struct xfs_dquot *gdqp, + struct xfs_dquot *pdqp, long nblks, long ninos, uint flags) @@ -770,11 +777,21 @@ xfs_trans_reserve_quota_bydquots( goto unwind_usr; } + if (pdqp) { + error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags); + if (error) + goto unwind_grp; + } + /* * Didn't change anything critical, so, no need to log */ return 0; +unwind_grp: + flags |= XFS_QMOPT_FORCE_RES; + if (gdqp) + xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags); unwind_usr: flags |= XFS_QMOPT_FORCE_RES; if (udqp) @@ -816,6 +833,7 @@ xfs_trans_reserve_quota_nblks( */ return xfs_trans_reserve_quota_bydquots(tp, mp, ip->i_udquot, ip->i_gdquot, + ip->i_pdquot, nblks, ninos, flags); } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 42c0ef288aeb..dc730ac272be 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -489,6 +489,7 @@ xfs_create( prid_t prid; struct xfs_dquot *udqp = NULL; struct xfs_dquot *gdqp = NULL; + struct xfs_dquot *pdqp = NULL; uint resblks; uint log_res; uint log_count; @@ -507,7 +508,8 @@ xfs_create( * Make sure that we have allocated dquot(s) on disk. */ error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, - XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); + XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, + &udqp, &gdqp, &pdqp); if (error) return error; @@ -559,7 +561,8 @@ xfs_create( /* * Reserve disk quota and the inode. */ - error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); + error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, + pdqp, resblks, 1, 0); if (error) goto out_trans_cancel; @@ -623,7 +626,7 @@ xfs_create( * These ids of the inode couldn't have changed since the new * inode has been locked ever since it was created. */ - xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); + xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) @@ -635,6 +638,7 @@ xfs_create( xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); *ipp = ip; return 0; @@ -656,6 +660,7 @@ xfs_create( xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); + xfs_qm_dqrele(pdqp); if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); @@ -1568,7 +1573,7 @@ xfs_free_file_space( } xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota(tp, mp, - ip->i_udquot, ip->i_gdquot, + ip->i_udquot, ip->i_gdquot, ip->i_pdquot, resblks, 0, XFS_QMOPT_RES_REGBLKS); if (error) goto error1; -- GitLab From f6becf0b2ffef0bed813d7f910b5d276c5dc45e1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 11 Jul 2013 14:35:43 +0200 Subject: [PATCH 2625/2900] ASoC: omap-pcm: Request the DMA channel differently when DT is involved When booting with DT the platform_get_resource_byname() is not available to get the DMA resource. In this case the DAI drivers will set the filter_data to the name of the DMA and omap-pcm can use this to request the DMA channel. Signed-off-by: Peter Ujfalusi Reviewed-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/omap-pcm.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index c28e042f2208..a11405de86e8 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -113,14 +113,25 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_dmaengine_dai_dma_data *dma_data; + int ret; snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - return snd_dmaengine_pcm_open_request_chan(substream, - omap_dma_filter_fn, - dma_data->filter_data); + /* DT boot: filter_data is the DMA name */ + if (rtd->cpu_dai->dev->of_node) { + struct dma_chan *chan; + + chan = dma_request_slave_channel(rtd->cpu_dai->dev, + dma_data->filter_data); + ret = snd_dmaengine_pcm_open(substream, chan); + } else { + ret = snd_dmaengine_pcm_open_request_chan(substream, + omap_dma_filter_fn, + dma_data->filter_data); + } + return ret; } static int omap_pcm_mmap(struct snd_pcm_substream *substream, -- GitLab From a8035f073cb508a0c1223db2662510575627b41d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 11 Jul 2013 14:35:44 +0200 Subject: [PATCH 2626/2900] ASoC: omap-mcpdm: Do not use platform_get_resource_byname() for DMA The DMA resource no longer available via this API when booting with DT. McPDM is only available on OMAP4/5 and both can boot with DT only. Set the dma_data.filter_data to the DMA name which will be used by omap-pcm to request the DMA channel. Signed-off-by: Peter Ujfalusi Reviewed-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/omap-mcpdm.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index eb05c7ed6d05..a49dc52f8abc 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -66,7 +66,6 @@ struct omap_mcpdm { bool restart; struct snd_dmaengine_dai_dma_data dma_data[2]; - unsigned int dma_req[2]; }; /* @@ -477,19 +476,8 @@ static int asoc_mcpdm_probe(struct platform_device *pdev) mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); - if (!res) - return -ENODEV; - - mcpdm->dma_req[0] = res->start; - mcpdm->dma_data[0].filter_data = &mcpdm->dma_req[0]; - - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); - if (!res) - return -ENODEV; - - mcpdm->dma_req[1] = res->start; - mcpdm->dma_data[1].filter_data = &mcpdm->dma_req[1]; + mcpdm->dma_data[0].filter_data = "dn_link"; + mcpdm->dma_data[1].filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (res == NULL) -- GitLab From 2ebef44789223389708505e33c67d44e9f999d4a Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 11 Jul 2013 14:35:45 +0200 Subject: [PATCH 2627/2900] ASoC: omap-dmic: Do not use platform_get_resource_byname() for DMA The DMA resource no longer available via this API when booting with DT. DMIC is only available on OMAP4/5 and both can boot with DT only. Set the dma_data.filter_data to the DMA name which will be used by omap-pcm to request the DMA channel. Signed-off-by: Peter Ujfalusi Reviewed-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/omap-dmic.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 2ad0370146fd..4db1f8e6e172 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -57,7 +57,6 @@ struct omap_dmic { struct mutex mutex; struct snd_dmaengine_dai_dma_data dma_data; - unsigned int dma_req; }; static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) @@ -478,15 +477,7 @@ static int asoc_dmic_probe(struct platform_device *pdev) } dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG; - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dmic->dev, "invalid dma resource\n"); - ret = -ENODEV; - goto err_put_clk; - } - - dmic->dma_req = res->start; - dmic->dma_data.filter_data = &dmic->dma_req; + dmic->dma_data.filter_data = "up_link"; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (!res) { -- GitLab From 9ab1fac4829b3da0ba4d3f44d95d3e8ad13e6629 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Thu, 11 Jul 2013 14:35:46 +0200 Subject: [PATCH 2628/2900] ASoC: omap-mcbsp: Use different method for DMA request when booted with DT The DMA resource no longer available via this API when booting with DT. When the board is booted with DT do not use platform_get_resource_byname(), instead set the dma_data.filter_data to the name of the DMA channel and omap-pcm can use this name to request the DMA channel. Signed-off-by: Peter Ujfalusi Reviewed-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/omap/mcbsp.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index eb68c7db1cf3..361e4c03646e 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -1012,28 +1012,33 @@ int omap_mcbsp_init(struct platform_device *pdev) } } - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); - if (!res) { - dev_err(&pdev->dev, "invalid rx DMA channel\n"); - return -ENODEV; - } - /* RX DMA request number, and port address configuration */ - mcbsp->dma_req[1] = res->start; - mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; - mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); - mcbsp->dma_data[1].maxburst = 4; + if (!pdev->dev.of_node) { + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); + if (!res) { + dev_err(&pdev->dev, "invalid tx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[0] = res->start; + mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; - res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); - if (!res) { - dev_err(&pdev->dev, "invalid tx DMA channel\n"); - return -ENODEV; + res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); + if (!res) { + dev_err(&pdev->dev, "invalid rx DMA channel\n"); + return -ENODEV; + } + mcbsp->dma_req[1] = res->start; + mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1]; + } else { + mcbsp->dma_data[0].filter_data = "tx"; + mcbsp->dma_data[1].filter_data = "rx"; } - /* TX DMA request number, and port address configuration */ - mcbsp->dma_req[0] = res->start; - mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0]; + mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp, 0); mcbsp->dma_data[0].maxburst = 4; + mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp, 1); + mcbsp->dma_data[1].maxburst = 4; + mcbsp->fclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(mcbsp->fclk)) { ret = PTR_ERR(mcbsp->fclk); -- GitLab From 110ecd69a9feea82a152bbf9b12aba57e6396883 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 11 Jul 2013 13:16:54 -0400 Subject: [PATCH 2629/2900] 9p: fix off by one causing access violations and memory corruption p9_release_pages() would attempt to dereference one value past the end of pages[]. This would cause the following crashes: [ 6293.171817] BUG: unable to handle kernel paging request at ffff8807c96f3000 [ 6293.174146] IP: [] p9_release_pages+0x3b/0x60 [ 6293.176447] PGD 79c5067 PUD 82c1e3067 PMD 82c197067 PTE 80000007c96f3060 [ 6293.180060] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 6293.180060] Modules linked in: [ 6293.180060] CPU: 62 PID: 174043 Comm: modprobe Tainted: G W 3.10.0-next-20130710-sasha #3954 [ 6293.180060] task: ffff8807b803b000 ti: ffff880787dde000 task.ti: ffff880787dde000 [ 6293.180060] RIP: 0010:[] [] p9_release_pages+0x3b/0x60 [ 6293.214316] RSP: 0000:ffff880787ddfc28 EFLAGS: 00010202 [ 6293.214316] RAX: 0000000000000001 RBX: ffff8807c96f2ff8 RCX: 0000000000000000 [ 6293.222017] RDX: ffff8807b803b000 RSI: 0000000000000001 RDI: ffffea001c7e3d40 [ 6293.222017] RBP: ffff880787ddfc48 R08: 0000000000000000 R09: 0000000000000000 [ 6293.222017] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000001 [ 6293.222017] R13: 0000000000000001 R14: ffff8807cc50c070 R15: ffff8807cc50c070 [ 6293.222017] FS: 00007f572641d700(0000) GS:ffff8807f3600000(0000) knlGS:0000000000000000 [ 6293.256784] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 6293.256784] CR2: ffff8807c96f3000 CR3: 00000007c8e81000 CR4: 00000000000006e0 [ 6293.256784] Stack: [ 6293.256784] ffff880787ddfcc8 ffff880787ddfcc8 0000000000000000 ffff880787ddfcc8 [ 6293.256784] ffff880787ddfd48 ffffffff84128be8 ffff880700000002 0000000000000001 [ 6293.256784] ffff8807b803b000 ffff880787ddfce0 0000100000000000 0000000000000000 [ 6293.256784] Call Trace: [ 6293.256784] [] p9_virtio_zc_request+0x598/0x630 [ 6293.256784] [] ? wake_up_bit+0x40/0x40 [ 6293.256784] [] p9_client_zc_rpc+0x111/0x3a0 [ 6293.256784] [] ? sched_clock_cpu+0x108/0x120 [ 6293.256784] [] p9_client_read+0xe1/0x2c0 [ 6293.256784] [] v9fs_file_read+0x90/0xc0 [ 6293.256784] [] vfs_read+0xc3/0x130 [ 6293.256784] [] ? trace_hardirqs_on+0xd/0x10 [ 6293.256784] [] SyS_read+0x62/0xa0 [ 6293.256784] [] tracesys+0xdd/0xe2 [ 6293.256784] Code: 66 90 48 89 fb 41 89 f5 48 8b 3f 48 85 ff 74 29 85 f6 74 25 45 31 e4 66 0f 1f 84 00 00 00 00 00 e8 eb 14 12 fd 41 ff c4 49 63 c4 <48> 8b 3c c3 48 85 ff 74 05 45 39 e5 75 e7 48 83 c4 08 5b 41 5c [ 6293.256784] RIP [] p9_release_pages+0x3b/0x60 [ 6293.256784] RSP [ 6293.256784] CR2: ffff8807c96f3000 [ 6293.256784] ---[ end trace 50822ee72cd360fc ]--- Signed-off-by: Sasha Levin Signed-off-by: David S. Miller --- net/9p/trans_common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index de8df957867d..2ee3879161b1 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c @@ -24,11 +24,11 @@ */ void p9_release_pages(struct page **pages, int nr_pages) { - int i = 0; - while (pages[i] && nr_pages--) { - put_page(pages[i]); - i++; - } + int i; + + for (i = 0; i < nr_pages; i++) + if (pages[i]) + put_page(pages[i]); } EXPORT_SYMBOL(p9_release_pages); -- GitLab From f89e57c4f5d7efdbe73b6214c73058aa335870e4 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 11 Jul 2013 11:38:06 -0700 Subject: [PATCH 2630/2900] vxlan: Fix kernel crash on rmmod. vxlan exit module unregisters vxlan net and then it unregisters rtnl ops which triggers vxlan_dellink() from __rtnl_kill_links(). vxlan_dellink() deletes vxlan-dev from vxlan_list which has list-head in vxlan-net-struct but that is already gone due to net-unregister. That is how we are getting following crash. Following commit fixes the crash by fixing module exit path. BUG: unable to handle kernel paging request at ffff8804102c8000 IP: [] __list_del_entry+0x29/0xd0 PGD 2972067 PUD 83e019067 PMD 83df97067 PTE 80000004102c8060 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC Modules linked in: --- CPU: 19 PID: 6712 Comm: rmmod Tainted: GF 3.10.0+ #95 Hardware name: Dell Inc. PowerEdge R620/0KCKR5, BIOS 1.4.8 10/25/2012 task: ffff88080c47c580 ti: ffff88080ac50000 task.ti: ffff88080ac50000 RIP: 0010:[] [] __list_del_entry+0x29/0xd0 RSP: 0018:ffff88080ac51e08 EFLAGS: 00010206 RAX: ffff8804102c8000 RBX: ffff88040f0d4b10 RCX: dead000000200200 RDX: ffff8804102c8000 RSI: ffff88080ac51e58 RDI: ffff88040f0d4b10 RBP: ffff88080ac51e08 R08: 0000000000000001 R09: 2222222222222222 R10: 2222222222222222 R11: 2222222222222222 R12: ffff88080ac51e58 R13: ffffffffa07b8840 R14: ffffffff81ae48c0 R15: ffff88080ac51e58 FS: 00007f9ef105c700(0000) GS:ffff88082a800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff8804102c8000 CR3: 00000008227e5000 CR4: 00000000000407e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffff88080ac51e28 ffffffff812cc6a1 2222222222222222 ffff88040f0d4000 ffff88080ac51e48 ffffffffa07b3311 ffff88040f0d4000 ffffffff81ae49c8 ffff88080ac51e98 ffffffff81492fc2 ffff88080ac51e58 ffff88080ac51e58 Call Trace: [] list_del+0x11/0x40 [] vxlan_dellink+0x51/0x70 [vxlan] [] __rtnl_link_unregister+0xa2/0xb0 [] rtnl_link_unregister+0x1e/0x30 [] vxlan_cleanup_module+0x1c/0x2f [vxlan] [] SyS_delete_module+0x1d1/0x2c0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x16/0x1b Code: eb 9f 55 48 8b 17 48 b9 00 01 10 00 00 00 ad de 48 8b 47 08 48 89 e5 48 39 ca 74 29 48 b9 00 02 20 00 00 00 ad de 48 39 c8 74 7a <4c> 8b 00 4c 39 c7 75 53 4c 8b 42 08 4c 39 c7 75 2b 48 89 42 08 RIP [] __list_del_entry+0x29/0xd0 RSP CR2: ffff8804102c8000 Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 227b54a1f88a..0ba1e7edbb1b 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1916,9 +1916,9 @@ late_initcall(vxlan_init_module); static void __exit vxlan_cleanup_module(void) { - unregister_pernet_device(&vxlan_net_ops); rtnl_link_unregister(&vxlan_link_ops); destroy_workqueue(vxlan_wq); + unregister_pernet_device(&vxlan_net_ops); rcu_barrier(); } module_exit(vxlan_cleanup_module); -- GitLab From a8798a5c77c9981e88caef1373a3310bf8aed219 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 11 Jul 2013 15:53:21 +0200 Subject: [PATCH 2631/2900] alx: fix lockdep annotation Move spin_lock_init to be called before the spinlocks are used, preventing a lockdep splat. Signed-off-by: Maarten Lankhorst Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/alx/main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 0e0b242a9dd4..027398ebbba6 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1245,6 +1245,8 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SET_NETDEV_DEV(netdev, &pdev->dev); alx = netdev_priv(netdev); + spin_lock_init(&alx->hw.mdio_lock); + spin_lock_init(&alx->irq_lock); alx->dev = netdev; alx->hw.pdev = pdev; alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP | @@ -1327,9 +1329,6 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&alx->link_check_wk, alx_link_check); INIT_WORK(&alx->reset_wk, alx_reset); - spin_lock_init(&alx->hw.mdio_lock); - spin_lock_init(&alx->irq_lock); - netif_carrier_off(netdev); err = register_netdev(netdev); -- GitLab From 1b4fc0e249d61916b8a525b0e7b3c028232457c9 Mon Sep 17 00:00:00 2001 From: Dmitry Kravkov Date: Thu, 11 Jul 2013 15:48:21 +0300 Subject: [PATCH 2632/2900] bnx2x: fix tunneling CSUM calculation Since commit c957d09ffda417f6c8e3d1f10e2b05228607d6d7 "bnx2x: Remove sparse and coccinelle warnings" driver provided wrong partial csum for HW in tunneing scenarios. Reported-by: Eric Dumazet CC: Alexander Duyck CC: Pravin Shelar CC: Cong Wang Signed-off-by: Dmitry Kravkov Tested-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 3353efe79194..ee350bde1818 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3543,9 +3543,9 @@ static void bnx2x_update_pbds_gso_enc(struct sk_buff *skb, /* outer IP header info */ if (xmit_type & XMIT_CSUM_V4) { struct iphdr *iph = ip_hdr(skb); - u16 csum = (__force u16)(~iph->check) - - (__force u16)iph->tot_len - - (__force u16)iph->frag_off; + u32 csum = (__force u32)(~iph->check) - + (__force u32)iph->tot_len - + (__force u32)iph->frag_off; pbd2->fw_ip_csum_wo_len_flags_frag = bswab16(csum_fold((__force __wsum)csum)); -- GitLab From afc154e978de1eb11c555bc8bcec1552f75ebc43 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Thu, 11 Jul 2013 12:43:42 +0200 Subject: [PATCH 2633/2900] ipv6: fix route selection if kernel is not compiled with CONFIG_IPV6_ROUTER_PREF This is a follow-up patch to 3630d40067a21d4dfbadc6002bb469ce26ac5d52 ("ipv6: rt6_check_neigh should successfully verify neigh if no NUD information are available"). Since the removal of rt->n in rt6_info we can end up with a dst == NULL in rt6_check_neigh. In case the kernel is not compiled with CONFIG_IPV6_ROUTER_PREF we should also select a route with unkown NUD state but we must not avoid doing round robin selection on routes with the same target. So introduce and pass down a boolean ``do_rr'' to indicate when we should update rt->rr_ptr. As soon as no route is valid we do backtracking and do a lookup on a higher level in the fib trie. v2: a) Improved rt6_check_neigh logic (no need to create neighbour there) and documented return values. v3: a) Introduce enum rt6_nud_state to get rid of the magic numbers (thanks to David Miller). b) Update and shorten commit message a bit to actualy reflect the source. Reported-by: Pierre Emeriaud Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/route.c | 63 ++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5b127e09c224..a8c891aa2464 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -65,6 +65,12 @@ #include #endif +enum rt6_nud_state { + RT6_NUD_FAIL_HARD = -2, + RT6_NUD_FAIL_SOFT = -1, + RT6_NUD_SUCCEED = 1 +}; + static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, const struct in6_addr *dest); static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); @@ -531,28 +537,29 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif) return 0; } -static inline bool rt6_check_neigh(struct rt6_info *rt) +static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt) { struct neighbour *neigh; - bool ret = false; + enum rt6_nud_state ret = RT6_NUD_FAIL_HARD; if (rt->rt6i_flags & RTF_NONEXTHOP || !(rt->rt6i_flags & RTF_GATEWAY)) - return true; + return RT6_NUD_SUCCEED; rcu_read_lock_bh(); neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); if (neigh) { read_lock(&neigh->lock); if (neigh->nud_state & NUD_VALID) - ret = true; + ret = RT6_NUD_SUCCEED; #ifdef CONFIG_IPV6_ROUTER_PREF else if (!(neigh->nud_state & NUD_FAILED)) - ret = true; + ret = RT6_NUD_SUCCEED; #endif read_unlock(&neigh->lock); - } else if (IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) { - ret = true; + } else { + ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ? + RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT; } rcu_read_unlock_bh(); @@ -566,43 +573,52 @@ static int rt6_score_route(struct rt6_info *rt, int oif, m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_LOOKUP_F_IFACE)) - return -1; + return RT6_NUD_FAIL_HARD; #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; #endif - if (!rt6_check_neigh(rt) && (strict & RT6_LOOKUP_F_REACHABLE)) - return -1; + if (strict & RT6_LOOKUP_F_REACHABLE) { + int n = rt6_check_neigh(rt); + if (n < 0) + return n; + } return m; } static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, - int *mpri, struct rt6_info *match) + int *mpri, struct rt6_info *match, + bool *do_rr) { int m; + bool match_do_rr = false; if (rt6_check_expired(rt)) goto out; m = rt6_score_route(rt, oif, strict); - if (m < 0) + if (m == RT6_NUD_FAIL_SOFT && !IS_ENABLED(CONFIG_IPV6_ROUTER_PREF)) { + match_do_rr = true; + m = 0; /* lowest valid score */ + } else if (m < 0) { goto out; + } + + if (strict & RT6_LOOKUP_F_REACHABLE) + rt6_probe(rt); if (m > *mpri) { - if (strict & RT6_LOOKUP_F_REACHABLE) - rt6_probe(match); + *do_rr = match_do_rr; *mpri = m; match = rt; - } else if (strict & RT6_LOOKUP_F_REACHABLE) { - rt6_probe(rt); } - out: return match; } static struct rt6_info *find_rr_leaf(struct fib6_node *fn, struct rt6_info *rr_head, - u32 metric, int oif, int strict) + u32 metric, int oif, int strict, + bool *do_rr) { struct rt6_info *rt, *match; int mpri = -1; @@ -610,10 +626,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn, match = NULL; for (rt = rr_head; rt && rt->rt6i_metric == metric; rt = rt->dst.rt6_next) - match = find_match(rt, oif, strict, &mpri, match); + match = find_match(rt, oif, strict, &mpri, match, do_rr); for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric; rt = rt->dst.rt6_next) - match = find_match(rt, oif, strict, &mpri, match); + match = find_match(rt, oif, strict, &mpri, match, do_rr); return match; } @@ -622,15 +638,16 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) { struct rt6_info *match, *rt0; struct net *net; + bool do_rr = false; rt0 = fn->rr_ptr; if (!rt0) fn->rr_ptr = rt0 = fn->leaf; - match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict); + match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict, + &do_rr); - if (!match && - (strict & RT6_LOOKUP_F_REACHABLE)) { + if (do_rr) { struct rt6_info *next = rt0->dst.rt6_next; /* no entries matched; do round-robin */ -- GitLab From a7960784e9ddd526e4fb791bc23e4fe6f039c28e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 13:59:48 +0900 Subject: [PATCH 2634/2900] watchdog: at32ap700x_wdt: use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at32ap700x_wdt.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index 7a715e3e6828..c4cb5526112a 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -321,13 +321,14 @@ static int __init at32_wdt_probe(struct platform_device *pdev) return -ENXIO; } - wdt = kzalloc(sizeof(struct wdt_at32ap700x), GFP_KERNEL); + wdt = devm_kzalloc(&pdev->dev, sizeof(struct wdt_at32ap700x), + GFP_KERNEL); if (!wdt) { dev_dbg(&pdev->dev, "no memory for wdt structure\n"); return -ENOMEM; } - wdt->regs = ioremap(regs->start, resource_size(regs)); + wdt->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!wdt->regs) { ret = -ENOMEM; dev_dbg(&pdev->dev, "could not map I/O memory\n"); @@ -342,7 +343,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) dev_info(&pdev->dev, "CPU must be reset with external " "reset or POR due to silicon errata.\n"); ret = -EIO; - goto err_iounmap; + goto err_free; } else { wdt->users = 0; } @@ -375,10 +376,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) err_register: platform_set_drvdata(pdev, NULL); -err_iounmap: - iounmap(wdt->regs); err_free: - kfree(wdt); wdt = NULL; return ret; } @@ -391,8 +389,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev) at32_wdt_stop(); misc_deregister(&wdt->miscdev); - iounmap(wdt->regs); - kfree(wdt); wdt = NULL; platform_set_drvdata(pdev, NULL); } -- GitLab From 321e31231d781aa91e94e8e3974db1edb428b6a4 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 4 May 2013 01:41:14 +0530 Subject: [PATCH 2635/2900] watchdog: at32ap700x: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Acked-by: Hans-Christian Egtvedt Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at32ap700x_wdt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index c4cb5526112a..b178e717ef09 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -365,7 +365,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) ret = misc_register(&wdt->miscdev); if (ret) { dev_dbg(&pdev->dev, "failed to register wdt miscdev\n"); - goto err_register; + goto err_free; } dev_info(&pdev->dev, @@ -374,8 +374,6 @@ static int __init at32_wdt_probe(struct platform_device *pdev) return 0; -err_register: - platform_set_drvdata(pdev, NULL); err_free: wdt = NULL; return ret; @@ -390,7 +388,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev) misc_deregister(&wdt->miscdev); wdt = NULL; - platform_set_drvdata(pdev, NULL); } return 0; } -- GitLab From 626d65aa5255fdd98e62f74cf43d3166e9832fb2 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 14:00:33 +0900 Subject: [PATCH 2636/2900] watchdog: bcm63xx_wdt: use devm_ioremap_nocache() Use devm_ioremap_nocache() to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Acked-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bcm63xx_wdt.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index b2b80d4ac818..a14a58d9d110 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -249,7 +250,8 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) return -ENODEV; } - bcm63xx_wdt_device.regs = ioremap_nocache(r->start, resource_size(r)); + bcm63xx_wdt_device.regs = devm_ioremap_nocache(&pdev->dev, r->start, + resource_size(r)); if (!bcm63xx_wdt_device.regs) { dev_err(&pdev->dev, "failed to remap I/O resources\n"); return -ENXIO; @@ -258,7 +260,7 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, NULL); if (ret < 0) { dev_err(&pdev->dev, "failed to register wdt timer isr\n"); - goto unmap; + return ret; } if (bcm63xx_wdt_settimeout(wdt_time)) { @@ -281,8 +283,6 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) unregister_timer: bcm63xx_timer_unregister(TIMER_WDT_ID); -unmap: - iounmap(bcm63xx_wdt_device.regs); return ret; } @@ -293,7 +293,6 @@ static int bcm63xx_wdt_remove(struct platform_device *pdev) misc_deregister(&bcm63xx_wdt_miscdev); bcm63xx_timer_unregister(TIMER_WDT_ID); - iounmap(bcm63xx_wdt_device.regs); return 0; } -- GitLab From ce9a1bf8e6c65d2ab6786e759952a3548347ad6f Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 11 Jul 2013 13:57:34 +0200 Subject: [PATCH 2637/2900] drivers: net: phy: at803x: Add missing mdio device id at803x supports Atheros 8030, 8031 and 8035 PHYs. 8031 was missing from the mdio device id table. Signed-off-by: Helmut Schaa Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 1f7091b3c27c..ac22283aaf23 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -217,6 +217,7 @@ module_exit(atheros_exit); static struct mdio_device_id __maybe_unused atheros_tbl[] = { { 0x004dd076, 0xffffffef }, + { 0x004dd074, 0xffffffef }, { 0x004dd072, 0xffffffef }, { } }; -- GitLab From ac1bb694c05302a0552c5a34ba701f246004bc03 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 14:00:49 +0900 Subject: [PATCH 2638/2900] watchdog: mv64x60_wdt: use devm_ioremap() Use devm_ioremap() to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mv64x60_wdt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index c7fb878ca493..e4cf98019265 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -276,7 +276,7 @@ static int mv64x60_wdt_probe(struct platform_device *dev) if (!r) return -ENODEV; - mv64x60_wdt_regs = ioremap(r->start, resource_size(r)); + mv64x60_wdt_regs = devm_ioremap(&dev->dev, r->start, resource_size(r)); if (mv64x60_wdt_regs == NULL) return -ENOMEM; @@ -293,8 +293,6 @@ static int mv64x60_wdt_remove(struct platform_device *dev) mv64x60_wdt_handler_disable(); - iounmap(mv64x60_wdt_regs); - return 0; } -- GitLab From 3666eb028827c3a9df942cbc0a16388898c5a686 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 14:01:25 +0900 Subject: [PATCH 2639/2900] watchdog: nuc900_wdt: use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/nuc900_wdt.c | 50 ++++++++--------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c index 04c45a102992..e2b6d2cf5c9d 100644 --- a/drivers/watchdog/nuc900_wdt.c +++ b/drivers/watchdog/nuc900_wdt.c @@ -61,7 +61,6 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); struct nuc900_wdt { - struct resource *res; struct clk *wdt_clock; struct platform_device *pdev; void __iomem *wdt_base; @@ -244,9 +243,11 @@ static struct miscdevice nuc900wdt_miscdev = { static int nuc900wdt_probe(struct platform_device *pdev) { + struct resource *res; int ret = 0; - nuc900_wdt = kzalloc(sizeof(struct nuc900_wdt), GFP_KERNEL); + nuc900_wdt = devm_kzalloc(&pdev->dev, sizeof(*nuc900_wdt), + GFP_KERNEL); if (!nuc900_wdt) return -ENOMEM; @@ -254,33 +255,20 @@ static int nuc900wdt_probe(struct platform_device *pdev) spin_lock_init(&nuc900_wdt->wdt_lock); - nuc900_wdt->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (nuc900_wdt->res == NULL) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { dev_err(&pdev->dev, "no memory resource specified\n"); - ret = -ENOENT; - goto err_get; + return -ENOENT; } - if (!request_mem_region(nuc900_wdt->res->start, - resource_size(nuc900_wdt->res), pdev->name)) { - dev_err(&pdev->dev, "failed to get memory region\n"); - ret = -ENOENT; - goto err_get; - } - - nuc900_wdt->wdt_base = ioremap(nuc900_wdt->res->start, - resource_size(nuc900_wdt->res)); - if (nuc900_wdt->wdt_base == NULL) { - dev_err(&pdev->dev, "failed to ioremap() region\n"); - ret = -EINVAL; - goto err_req; - } + nuc900_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(nuc900_wdt->wdt_base)) + return PTR_ERR(nuc900_wdt->wdt_base); - nuc900_wdt->wdt_clock = clk_get(&pdev->dev, NULL); + nuc900_wdt->wdt_clock = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(nuc900_wdt->wdt_clock)) { dev_err(&pdev->dev, "failed to find watchdog clock source\n"); - ret = PTR_ERR(nuc900_wdt->wdt_clock); - goto err_map; + return PTR_ERR(nuc900_wdt->wdt_clock); } clk_enable(nuc900_wdt->wdt_clock); @@ -298,14 +286,6 @@ static int nuc900wdt_probe(struct platform_device *pdev) err_clk: clk_disable(nuc900_wdt->wdt_clock); - clk_put(nuc900_wdt->wdt_clock); -err_map: - iounmap(nuc900_wdt->wdt_base); -err_req: - release_mem_region(nuc900_wdt->res->start, - resource_size(nuc900_wdt->res)); -err_get: - kfree(nuc900_wdt); return ret; } @@ -314,14 +294,6 @@ static int nuc900wdt_remove(struct platform_device *pdev) misc_deregister(&nuc900wdt_miscdev); clk_disable(nuc900_wdt->wdt_clock); - clk_put(nuc900_wdt->wdt_clock); - - iounmap(nuc900_wdt->wdt_base); - - release_mem_region(nuc900_wdt->res->start, - resource_size(nuc900_wdt->res)); - - kfree(nuc900_wdt); return 0; } -- GitLab From 52ccc5aca4c9cf35974c1ea3b53fc43044b29361 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 14:01:41 +0900 Subject: [PATCH 2640/2900] watchdog: rc32434_wdt: use devm_ioremap_nocache() functions Use devm_ioremap_nocache() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rc32434_wdt.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index f78bc008cbb7..9cf6bc7a234f 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -32,6 +32,7 @@ #include /* For platform_driver framework */ #include /* For spin_lock/spin_unlock/... */ #include /* For copy_to_user/put_user/... */ +#include /* For devm_ioremap_nocache */ #include /* For the Watchdog registers */ @@ -271,7 +272,7 @@ static int rc32434_wdt_probe(struct platform_device *pdev) return -ENODEV; } - wdt_reg = ioremap_nocache(r->start, resource_size(r)); + wdt_reg = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r)); if (!wdt_reg) { pr_err("failed to remap I/O resources\n"); return -ENXIO; @@ -293,23 +294,18 @@ static int rc32434_wdt_probe(struct platform_device *pdev) ret = misc_register(&rc32434_wdt_miscdev); if (ret < 0) { pr_err("failed to register watchdog device\n"); - goto unmap; + return ret; } pr_info("Watchdog Timer version " VERSION ", timer margin: %d sec\n", timeout); return 0; - -unmap: - iounmap(wdt_reg); - return ret; } static int rc32434_wdt_remove(struct platform_device *pdev) { misc_deregister(&rc32434_wdt_miscdev); - iounmap(wdt_reg); return 0; } -- GitLab From a508e2e634f9ea462c3beb56e12aa50ba9e8b0a9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Apr 2013 14:01:59 +0900 Subject: [PATCH 2641/2900] watchdog: riowd: use devm_kzalloc() Use devm_kzalloc() to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/riowd.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 0040451aec1d..13363adc364f 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -183,7 +183,7 @@ static int riowd_probe(struct platform_device *op) goto out; err = -ENOMEM; - p = kzalloc(sizeof(*p), GFP_KERNEL); + p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL); if (!p) goto out; @@ -192,7 +192,7 @@ static int riowd_probe(struct platform_device *op) p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME); if (!p->regs) { pr_err("Cannot map registers\n"); - goto out_free; + goto out; } /* Make miscdev useable right away */ riowd_device = p; @@ -213,9 +213,6 @@ static int riowd_probe(struct platform_device *op) riowd_device = NULL; of_iounmap(&op->resource[0], p->regs, 2); -out_free: - kfree(p); - out: return err; } @@ -226,7 +223,6 @@ static int riowd_remove(struct platform_device *op) misc_deregister(&riowd_miscdev); of_iounmap(&op->resource[0], p->regs, 2); - kfree(p); return 0; } -- GitLab From b94828ffb2261a9803948ccd74f2b75105b1bf87 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:44:38 +0900 Subject: [PATCH 2642/2900] watchdog: riowd: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/riowd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c index 13363adc364f..3dd8ed28adc8 100644 --- a/drivers/watchdog/riowd.c +++ b/drivers/watchdog/riowd.c @@ -206,7 +206,7 @@ static int riowd_probe(struct platform_device *op) pr_info("Hardware watchdog [%i minutes], regs at %p\n", riowd_timeout, p->regs); - dev_set_drvdata(&op->dev, p); + platform_set_drvdata(op, p); return 0; out_iounmap: @@ -219,7 +219,7 @@ static int riowd_probe(struct platform_device *op) static int riowd_remove(struct platform_device *op) { - struct riowd *p = dev_get_drvdata(&op->dev); + struct riowd *p = platform_get_drvdata(op); misc_deregister(&riowd_miscdev); of_iounmap(&op->resource[0], p->regs, 2); -- GitLab From 9d8a7f16f47fca776b60ab63901dc8481ceb6e1f Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 2 May 2013 14:52:16 +0900 Subject: [PATCH 2643/2900] watchdog: ts72xx_wdt: use devm_*() functions Use devm_*() functions to make cleanup paths simpler. Signed-off-by: Jingoo Han Acked-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ts72xx_wdt.c | 67 ++++++----------------------------- 1 file changed, 10 insertions(+), 57 deletions(-) diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index b8a92459f10f..4da59b4d73f0 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -396,7 +396,7 @@ static int ts72xx_wdt_probe(struct platform_device *pdev) struct resource *r1, *r2; int error = 0; - wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL); + wdt = devm_kzalloc(&pdev->dev, sizeof(struct ts72xx_wdt), GFP_KERNEL); if (!wdt) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; @@ -405,44 +405,22 @@ static int ts72xx_wdt_probe(struct platform_device *pdev) r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r1) { dev_err(&pdev->dev, "failed to get memory resource\n"); - error = -ENODEV; - goto fail; + return -ENODEV; } - r1 = request_mem_region(r1->start, resource_size(r1), pdev->name); - if (!r1) { - dev_err(&pdev->dev, "cannot request memory region\n"); - error = -EBUSY; - goto fail; - } - - wdt->control_reg = ioremap(r1->start, resource_size(r1)); - if (!wdt->control_reg) { - dev_err(&pdev->dev, "failed to map memory\n"); - error = -ENODEV; - goto fail_free_control; - } + wdt->control_reg = devm_ioremap_resource(&pdev->dev, r1); + if (IS_ERR(wdt->control_reg)) + return PTR_ERR(wdt->control_reg); r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!r2) { dev_err(&pdev->dev, "failed to get memory resource\n"); - error = -ENODEV; - goto fail_unmap_control; - } - - r2 = request_mem_region(r2->start, resource_size(r2), pdev->name); - if (!r2) { - dev_err(&pdev->dev, "cannot request memory region\n"); - error = -EBUSY; - goto fail_unmap_control; + return -ENODEV; } - wdt->feed_reg = ioremap(r2->start, resource_size(r2)); - if (!wdt->feed_reg) { - dev_err(&pdev->dev, "failed to map memory\n"); - error = -ENODEV; - goto fail_free_feed; - } + wdt->feed_reg = devm_ioremap_resource(&pdev->dev, r2); + if (IS_ERR(wdt->feed_reg)) + return PTR_ERR(wdt->feed_reg); platform_set_drvdata(pdev, wdt); ts72xx_wdt_pdev = pdev; @@ -455,45 +433,20 @@ static int ts72xx_wdt_probe(struct platform_device *pdev) error = misc_register(&ts72xx_wdt_miscdev); if (error) { dev_err(&pdev->dev, "failed to register miscdev\n"); - goto fail_unmap_feed; + return error; } dev_info(&pdev->dev, "TS-72xx Watchdog driver\n"); return 0; - -fail_unmap_feed: - platform_set_drvdata(pdev, NULL); - iounmap(wdt->feed_reg); -fail_free_feed: - release_mem_region(r2->start, resource_size(r2)); -fail_unmap_control: - iounmap(wdt->control_reg); -fail_free_control: - release_mem_region(r1->start, resource_size(r1)); -fail: - kfree(wdt); - return error; } static int ts72xx_wdt_remove(struct platform_device *pdev) { - struct ts72xx_wdt *wdt = platform_get_drvdata(pdev); - struct resource *res; int error; error = misc_deregister(&ts72xx_wdt_miscdev); - platform_set_drvdata(pdev, NULL); - - iounmap(wdt->feed_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - release_mem_region(res->start, resource_size(res)); - - iounmap(wdt->control_reg); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - kfree(wdt); return error; } -- GitLab From cf3cc8c252cbd8d50ed61ef5e176bc577f38cf71 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:15:26 +0900 Subject: [PATCH 2644/2900] watchdog: dw_wdt: use devm_clk_get() Use devm_clk_get() to make cleanup paths more simple. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 203766989382..2e70fd07ea40 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -305,13 +305,13 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) if (IS_ERR(dw_wdt.regs)) return PTR_ERR(dw_wdt.regs); - dw_wdt.clk = clk_get(&pdev->dev, NULL); + dw_wdt.clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dw_wdt.clk)) return PTR_ERR(dw_wdt.clk); ret = clk_enable(dw_wdt.clk); if (ret) - goto out_put_clk; + return ret; spin_lock_init(&dw_wdt.lock); @@ -327,8 +327,6 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) out_disable_clk: clk_disable(dw_wdt.clk); -out_put_clk: - clk_put(dw_wdt.clk); return ret; } @@ -338,7 +336,6 @@ static int dw_wdt_drv_remove(struct platform_device *pdev) misc_deregister(&dw_wdt_miscdev); clk_disable(dw_wdt.clk); - clk_put(dw_wdt.clk); return 0; } -- GitLab From 2c8a01894a12665d8059fad8f0a293c98a264121 Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Thu, 11 Jul 2013 19:04:02 +0800 Subject: [PATCH 2645/2900] dummy: fix oops when loading the dummy failed We rename the dummy in modprobe.conf like this: install dummy0 /sbin/modprobe -o dummy0 --ignore-install dummy install dummy1 /sbin/modprobe -o dummy1 --ignore-install dummy We got oops when we run the command: modprobe dummy0 modprobe dummy1 ------------[ cut here ]------------ [ 3302.187584] BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 [ 3302.195411] IP: [] __rtnl_link_unregister+0x9a/0xd0 [ 3302.201844] PGD 85c94a067 PUD 8517bd067 PMD 0 [ 3302.206305] Oops: 0002 [#1] SMP [ 3302.299737] task: ffff88105ccea300 ti: ffff880eba4a0000 task.ti: ffff880eba4a0000 [ 3302.307186] RIP: 0010:[] [] __rtnl_link_unregister+0x9a/0xd0 [ 3302.316044] RSP: 0018:ffff880eba4a1dd8 EFLAGS: 00010246 [ 3302.321332] RAX: 0000000000000000 RBX: ffffffff81a9d738 RCX: 0000000000000002 [ 3302.328436] RDX: 0000000000000000 RSI: ffffffffa04d602c RDI: ffff880eba4a1dd8 [ 3302.335541] RBP: ffff880eba4a1e18 R08: dead000000200200 R09: dead000000100100 [ 3302.342644] R10: 0000000000000080 R11: 0000000000000003 R12: ffffffff81a9d788 [ 3302.349748] R13: ffffffffa04d7020 R14: ffffffff81a9d670 R15: ffff880eba4a1dd8 [ 3302.364910] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 3302.370630] CR2: 0000000000000008 CR3: 000000085e15e000 CR4: 00000000000427e0 [ 3302.377734] DR0: 0000000000000003 DR1: 00000000000000b0 DR2: 0000000000000001 [ 3302.384838] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 3302.391940] Stack: [ 3302.393944] ffff880eba4a1dd8 ffff880eba4a1dd8 ffff880eba4a1e18 ffffffffa04d70c0 [ 3302.401350] 00000000ffffffef ffffffffa01a8000 0000000000000000 ffffffff816111c8 [ 3302.408758] ffff880eba4a1e48 ffffffffa01a80be ffff880eba4a1e48 ffffffffa04d70c0 [ 3302.416164] Call Trace: [ 3302.418605] [] ? 0xffffffffa01a7fff [ 3302.423727] [] dummy_init_module+0xbe/0x1000 [dummy0] [ 3302.430405] [] ? 0xffffffffa01a7fff [ 3302.435535] [] do_one_initcall+0x152/0x1b0 [ 3302.441263] [] do_init_module+0x7b/0x200 [ 3302.446824] [] load_module+0x4e2/0x530 [ 3302.452215] [] ? ddebug_dyndbg_boot_param_cb+0x60/0x60 [ 3302.458979] [] SyS_init_module+0xd1/0x130 [ 3302.464627] [] system_call_fastpath+0x16/0x1b [ 3302.490090] RIP [] __rtnl_link_unregister+0x9a/0xd0 [ 3302.496607] RSP [ 3302.500084] CR2: 0000000000000008 [ 3302.503466] ---[ end trace 8342d49cd49f78ed ]--- The reason is that when loading dummy, if __rtnl_link_register() return failed, the init_module should return and avoid take the wrong path. Signed-off-by: Tan Xiaojun Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/dummy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 42aa54af6842..b710c6b2d659 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -185,6 +185,8 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); + if (err < 0) + goto out; for (i = 0; i < numdummies && !err; i++) { err = dummy_init_one(); @@ -192,6 +194,8 @@ static int __init dummy_init_module(void) } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); + +out: rtnl_unlock(); return err; -- GitLab From f2966cd5691058b8674a20766525bedeaea9cbcf Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Thu, 11 Jul 2013 19:04:06 +0800 Subject: [PATCH 2646/2900] ifb: fix oops when loading the ifb failed If __rtnl_link_register() return faild when loading the ifb, it will take the wrong path and get oops, so fix it just like dummy. Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- drivers/net/ifb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index a11f7a45cb5f..a3bed28197d2 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -291,6 +291,8 @@ static int __init ifb_init_module(void) rtnl_lock(); err = __rtnl_link_register(&ifb_link_ops); + if (err < 0) + goto out; for (i = 0; i < numifbs && !err; i++) { err = ifb_init_one(i); @@ -298,6 +300,8 @@ static int __init ifb_init_module(void) } if (err) __rtnl_link_unregister(&ifb_link_ops); + +out: rtnl_unlock(); return err; -- GitLab From 0b9302619963e46931c64693fd24d467c39bbb4c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 14 May 2013 12:11:03 +0530 Subject: [PATCH 2647/2900] watchdog: dw_wdt: Staticize local symbol 'dw_wdt_write' is used only in this file. Make it static. Signed-off-by: Sachin Kamat Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 2e70fd07ea40..e621098bf663 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -154,8 +154,8 @@ static int dw_wdt_open(struct inode *inode, struct file *filp) return nonseekable_open(inode, filp); } -ssize_t dw_wdt_write(struct file *filp, const char __user *buf, size_t len, - loff_t *offset) +static ssize_t dw_wdt_write(struct file *filp, const char __user *buf, + size_t len, loff_t *offset) { if (!len) return 0; -- GitLab From bdf495742716211259dba644e0950129db6f2641 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:15:53 +0900 Subject: [PATCH 2648/2900] watchdog: imx2_wdt: use devm_clk_get() Use devm_clk_get() to make cleanup paths more simple. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx2_wdt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 62946c2cb4f8..693ac3f4de5a 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -261,7 +261,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (IS_ERR(imx2_wdt.base)) return PTR_ERR(imx2_wdt.base); - imx2_wdt.clk = clk_get(&pdev->dev, NULL); + imx2_wdt.clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(imx2_wdt.clk)) { dev_err(&pdev->dev, "can't get Watchdog clock\n"); return PTR_ERR(imx2_wdt.clk); @@ -286,7 +286,6 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) fail: imx2_wdt_miscdev.parent = NULL; - clk_put(imx2_wdt.clk); return ret; } @@ -299,8 +298,7 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev) dev_crit(imx2_wdt_miscdev.parent, "Device removed: Expect reboot!\n"); - } else - clk_put(imx2_wdt.clk); + } imx2_wdt_miscdev.parent = NULL; return 0; -- GitLab From 259181feb003e3244d4ba15256735ca259be217a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:16:14 +0900 Subject: [PATCH 2649/2900] watchdog: pnx4008_wdt: use devm_clk_get() Use devm_clk_get() to make cleanup paths more simple. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pnx4008_wdt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index a3684a30eb69..b30bd430f591 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -159,13 +159,13 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt_base)) return PTR_ERR(wdt_base); - wdt_clk = clk_get(&pdev->dev, NULL); + wdt_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(wdt_clk)) return PTR_ERR(wdt_clk); ret = clk_enable(wdt_clk); if (ret) - goto out; + return ret; pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? WDIOF_CARDRESET : 0; @@ -186,8 +186,6 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) disable_clk: clk_disable(wdt_clk); -out: - clk_put(wdt_clk); return ret; } @@ -196,7 +194,6 @@ static int pnx4008_wdt_remove(struct platform_device *pdev) watchdog_unregister_device(&pnx4008_wdd); clk_disable(wdt_clk); - clk_put(wdt_clk); return 0; } -- GitLab From 2f7b9b4883f4d67821bbd80f8fdfb8630d24cc60 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:16:33 +0900 Subject: [PATCH 2650/2900] watchdog: shwdt: use devm_clk_get() Use devm_clk_get() to make cleanup paths more simple. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/shwdt.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 6185af2b3310..ea2154bfe5ab 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -241,7 +241,7 @@ static int sh_wdt_probe(struct platform_device *pdev) wdt->dev = &pdev->dev; - wdt->clk = clk_get(&pdev->dev, NULL); + wdt->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(wdt->clk)) { /* * Clock framework support is optional, continue on @@ -251,10 +251,8 @@ static int sh_wdt_probe(struct platform_device *pdev) } wdt->base = devm_ioremap_resource(wdt->dev, res); - if (IS_ERR(wdt->base)) { - rc = PTR_ERR(wdt->base); - goto err; - } + if (IS_ERR(wdt->base)) + return PTR_ERR(wdt->base); watchdog_set_nowayout(&sh_wdt_dev, nowayout); watchdog_set_drvdata(&sh_wdt_dev, wdt); @@ -277,7 +275,7 @@ static int sh_wdt_probe(struct platform_device *pdev) rc = watchdog_register_device(&sh_wdt_dev); if (unlikely(rc)) { dev_err(&pdev->dev, "Can't register watchdog (err=%d)\n", rc); - goto err; + return rc; } init_timer(&wdt->timer); @@ -292,11 +290,6 @@ static int sh_wdt_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); return 0; - -err: - clk_put(wdt->clk); - - return rc; } static int sh_wdt_remove(struct platform_device *pdev) @@ -308,7 +301,6 @@ static int sh_wdt_remove(struct platform_device *pdev) watchdog_unregister_device(&sh_wdt_dev); pm_runtime_disable(&pdev->dev); - clk_put(wdt->clk); return 0; } -- GitLab From 3b8ccd447375acebed9af0a3798e1ab4e58bedf4 Mon Sep 17 00:00:00 2001 From: Camelia Groza Date: Thu, 11 Jul 2013 09:55:51 +0300 Subject: [PATCH 2651/2900] inet: fix spacing in assignment Found using checkpatch.pl Signed-off-by: Camelia Groza Signed-off-by: David S. Miller --- net/ipv4/inet_hashtables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 6af375afeeef..7bd8983dbfcf 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -467,7 +467,7 @@ void inet_unhash(struct sock *sk) lock = inet_ehash_lockp(hashinfo, sk->sk_hash); spin_lock_bh(lock); - done =__sk_nulls_del_node_init_rcu(sk); + done = __sk_nulls_del_node_init_rcu(sk); if (done) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); spin_unlock_bh(lock); -- GitLab From 4d2327ca9d44dbf5b4ead443f380ad58baa8c201 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 4 May 2013 01:41:16 +0530 Subject: [PATCH 2652/2900] watchdog: shwdt: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Paul Mundt Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/shwdt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index ea2154bfe5ab..5bca79457768 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -296,8 +296,6 @@ static int sh_wdt_remove(struct platform_device *pdev) { struct sh_wdt *wdt = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - watchdog_unregister_device(&sh_wdt_dev); pm_runtime_disable(&pdev->dev); -- GitLab From 07bf971a38427e2659603468e5947c39754edb13 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:16:49 +0900 Subject: [PATCH 2653/2900] watchdog: sp805_wdt: use devm_clk_get() Use devm_clk_get() to make cleanup paths more simple. Signed-off-by: Jingoo Han Acked-by: Viresh Kumar Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 8872642505c0..58df98aec122 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -231,7 +231,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) goto err; } - wdt->clk = clk_get(&adev->dev, NULL); + wdt->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(wdt->clk)) { dev_warn(&adev->dev, "Clock not found\n"); ret = PTR_ERR(wdt->clk); @@ -251,15 +251,13 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) if (ret) { dev_err(&adev->dev, "watchdog_register_device() failed: %d\n", ret); - goto err_register; + goto err; } amba_set_drvdata(adev, wdt); dev_info(&adev->dev, "registration successful\n"); return 0; -err_register: - clk_put(wdt->clk); err: dev_err(&adev->dev, "Probe Failed!!!\n"); return ret; @@ -272,7 +270,6 @@ static int sp805_wdt_remove(struct amba_device *adev) watchdog_unregister_device(&wdt->wdd); amba_set_drvdata(adev, NULL); watchdog_set_drvdata(&wdt->wdd, NULL); - clk_put(wdt->clk); return 0; } -- GitLab From d3a33a9500f262a40fcf3a9b9b9c3e03890b14dd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:30:43 +0900 Subject: [PATCH 2654/2900] watchdog: mtx1-wdt: use devm_gpio_request_one() Use devm_gpio_request_one() to make cleanup paths simpler. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 14dab6ff87aa..b4341110ad4f 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -209,7 +209,7 @@ static int mtx1_wdt_probe(struct platform_device *pdev) int ret; mtx1_wdt_device.gpio = pdev->resource[0].start; - ret = gpio_request_one(mtx1_wdt_device.gpio, + ret = devm_gpio_request_one(&pdev->dev, mtx1_wdt_device.gpio, GPIOF_OUT_INIT_HIGH, "mtx1-wdt"); if (ret < 0) { dev_err(&pdev->dev, "failed to request gpio"); @@ -241,7 +241,6 @@ static int mtx1_wdt_remove(struct platform_device *pdev) wait_for_completion(&mtx1_wdt_device.stop); } - gpio_free(mtx1_wdt_device.gpio); misc_deregister(&mtx1_wdt_misc); return 0; } -- GitLab From 7a5da030c6ecdd6229f079902a17e641c7f2fbd6 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 29 Apr 2013 18:31:20 +0900 Subject: [PATCH 2655/2900] watchdog: wm831x_wdt: use devm_gpio_request_one() Use devm_gpio_request_one() to make cleanup paths simpler. Also, GPIOF_DIR_OUT | GPIOF_INIT_LOW is replaced with GPIOF_OUT_INIT_LOW. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm831x_wdt.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 9dcb6d082277..3348ddd618c7 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -247,9 +247,10 @@ static int wm831x_wdt_probe(struct platform_device *pdev) reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT; if (pdata->update_gpio) { - ret = gpio_request_one(pdata->update_gpio, - GPIOF_DIR_OUT | GPIOF_INIT_LOW, - "Watchdog update"); + ret = devm_gpio_request_one(&pdev->dev, + pdata->update_gpio, + GPIOF_OUT_INIT_LOW, + "Watchdog update"); if (ret < 0) { dev_err(wm831x->dev, "Failed to request update GPIO: %d\n", @@ -270,7 +271,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) } else { dev_err(wm831x->dev, "Failed to unlock security key: %d\n", ret); - goto err_gpio; + goto err; } } @@ -278,16 +279,13 @@ static int wm831x_wdt_probe(struct platform_device *pdev) if (ret != 0) { dev_err(wm831x->dev, "watchdog_register_device() failed: %d\n", ret); - goto err_gpio; + goto err; } dev_set_drvdata(&pdev->dev, driver_data); return 0; -err_gpio: - if (driver_data->update_gpio) - gpio_free(driver_data->update_gpio); err: return ret; } @@ -298,9 +296,6 @@ static int wm831x_wdt_remove(struct platform_device *pdev) watchdog_unregister_device(&driver_data->wdt); - if (driver_data->update_gpio) - gpio_free(driver_data->update_gpio); - return 0; } -- GitLab From 1ae995dca9da3a5671aa471e1c355e47437a1056 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:44:53 +0900 Subject: [PATCH 2656/2900] watchdog: wm831x: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wm831x_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c index 3348ddd618c7..d4e47eda4182 100644 --- a/drivers/watchdog/wm831x_wdt.c +++ b/drivers/watchdog/wm831x_wdt.c @@ -282,7 +282,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) goto err; } - dev_set_drvdata(&pdev->dev, driver_data); + platform_set_drvdata(pdev, driver_data); return 0; @@ -292,7 +292,7 @@ static int wm831x_wdt_probe(struct platform_device *pdev) static int wm831x_wdt_remove(struct platform_device *pdev) { - struct wm831x_wdt_drvdata *driver_data = dev_get_drvdata(&pdev->dev); + struct wm831x_wdt_drvdata *driver_data = platform_get_drvdata(pdev); watchdog_unregister_device(&driver_data->wdt); -- GitLab From 3828924af2e24a615b302fe1da69527d58474cdc Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 14 Mar 2013 10:30:21 +0900 Subject: [PATCH 2657/2900] watchdog: s3c2410_wdt: use dev_err()/dev_info() instead of pr_err()/pr_info() dev_err()/dev_info() are more preferred than pr_err()/pr_info(). Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 3a9f6961db2d..c3beb3adc6f7 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -358,7 +358,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) ret = s3c2410wdt_cpufreq_register(); if (ret < 0) { - pr_err("failed to register cpufreq\n"); + dev_err(dev, "failed to register cpufreq\n"); goto err_clk; } @@ -473,7 +473,7 @@ static int s3c2410wdt_resume(struct platform_device *dev) writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ writel(wtcon_save, wdt_base + S3C2410_WTCON); - pr_info("watchdog %sabled\n", + dev_info(&dev->dev, "watchdog %sabled\n", (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); return 0; -- GitLab From 0183984c61fdd298dde717ff1c5c2f6ce2ef3f73 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 14 Mar 2013 10:31:21 +0900 Subject: [PATCH 2658/2900] watchdog: s3c2410_wdt: convert s3c2410wdt to dev_pm_ops Instead of using legacy suspend/resume methods, using newer dev_pm_ops structure allows better control over power management. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index c3beb3adc6f7..6a22cf5d35bd 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -448,12 +448,12 @@ static void s3c2410wdt_shutdown(struct platform_device *dev) s3c2410wdt_stop(&s3c2410_wdd); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static unsigned long wtcon_save; static unsigned long wtdat_save; -static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state) +static int s3c2410wdt_suspend(struct device *dev) { /* Save watchdog state, and turn it off. */ wtcon_save = readl(wdt_base + S3C2410_WTCON); @@ -465,7 +465,7 @@ static int s3c2410wdt_suspend(struct platform_device *dev, pm_message_t state) return 0; } -static int s3c2410wdt_resume(struct platform_device *dev) +static int s3c2410wdt_resume(struct device *dev) { /* Restore watchdog state. */ @@ -473,16 +473,15 @@ static int s3c2410wdt_resume(struct platform_device *dev) writel(wtdat_save, wdt_base + S3C2410_WTCNT); /* Reset count */ writel(wtcon_save, wdt_base + S3C2410_WTCON); - dev_info(&dev->dev, "watchdog %sabled\n", + dev_info(dev, "watchdog %sabled\n", (wtcon_save & S3C2410_WTCON_ENABLE) ? "en" : "dis"); return 0; } +#endif -#else -#define s3c2410wdt_suspend NULL -#define s3c2410wdt_resume NULL -#endif /* CONFIG_PM */ +static SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops, s3c2410wdt_suspend, + s3c2410wdt_resume); #ifdef CONFIG_OF static const struct of_device_id s3c2410_wdt_match[] = { @@ -496,11 +495,10 @@ static struct platform_driver s3c2410wdt_driver = { .probe = s3c2410wdt_probe, .remove = s3c2410wdt_remove, .shutdown = s3c2410wdt_shutdown, - .suspend = s3c2410wdt_suspend, - .resume = s3c2410wdt_resume, .driver = { .owner = THIS_MODULE, .name = "s3c2410-wdt", + .pm = &s3c2410wdt_pm_ops, .of_match_table = of_match_ptr(s3c2410_wdt_match), }, }; -- GitLab From 26556b6e0bf044622a5d3dcade0ac6657b23c2a7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:43:43 +0900 Subject: [PATCH 2659/2900] watchdog: cpwd: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cpwd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c index 70387582843f..213225edd059 100644 --- a/drivers/watchdog/cpwd.c +++ b/drivers/watchdog/cpwd.c @@ -621,7 +621,7 @@ static int cpwd_probe(struct platform_device *op) WD_BADMODEL); } - dev_set_drvdata(&op->dev, p); + platform_set_drvdata(op, p); cpwd_device = p; err = 0; @@ -642,7 +642,7 @@ static int cpwd_probe(struct platform_device *op) static int cpwd_remove(struct platform_device *op) { - struct cpwd *p = dev_get_drvdata(&op->dev); + struct cpwd *p = platform_get_drvdata(op); int i; for (i = 0; i < WD_NUMDEVS; i++) { -- GitLab From 552a96415ff297475c20a05d384398ef1c729794 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:44:09 +0900 Subject: [PATCH 2660/2900] watchdog: da9052: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/da9052_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c index 367445009c64..f09c54e9686f 100644 --- a/drivers/watchdog/da9052_wdt.c +++ b/drivers/watchdog/da9052_wdt.c @@ -215,14 +215,14 @@ static int da9052_wdt_probe(struct platform_device *pdev) goto err; } - dev_set_drvdata(&pdev->dev, driver_data); + platform_set_drvdata(pdev, driver_data); err: return ret; } static int da9052_wdt_remove(struct platform_device *pdev) { - struct da9052_wdt_data *driver_data = dev_get_drvdata(&pdev->dev); + struct da9052_wdt_data *driver_data = platform_get_drvdata(pdev); watchdog_unregister_device(&driver_data->wdt); kref_put(&driver_data->kref, da9052_wdt_release_resources); -- GitLab From 76692c944cd8e85d833dc30d7346463e18b6d30e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 23 May 2013 19:44:23 +0900 Subject: [PATCH 2661/2900] watchdog: da9055: use platform_{get,set}_drvdata() Use the wrapper functions for getting and setting the driver data using platform_device instead of using dev_{get,set}_drvdata() with &pdev->dev, so we can directly pass a struct platform_device. Signed-off-by: Jingoo Han Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/da9055_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c index f5ad10546fc9..575f37a965a4 100644 --- a/drivers/watchdog/da9055_wdt.c +++ b/drivers/watchdog/da9055_wdt.c @@ -174,7 +174,7 @@ static int da9055_wdt_probe(struct platform_device *pdev) goto err; } - dev_set_drvdata(&pdev->dev, driver_data); + platform_set_drvdata(pdev, driver_data); ret = watchdog_register_device(&driver_data->wdt); if (ret != 0) @@ -187,7 +187,7 @@ static int da9055_wdt_probe(struct platform_device *pdev) static int da9055_wdt_remove(struct platform_device *pdev) { - struct da9055_wdt_data *driver_data = dev_get_drvdata(&pdev->dev); + struct da9055_wdt_data *driver_data = platform_get_drvdata(pdev); watchdog_unregister_device(&driver_data->wdt); kref_put(&driver_data->kref, da9055_wdt_release_resources); -- GitLab From 6697dbd27b6507c11815725ab31473ba74c49f06 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 4 May 2013 01:41:15 +0530 Subject: [PATCH 2662/2900] watchdog: mpcore: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mpcore_wdt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 233cfadcb21f..4f5ac408c7a3 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -379,8 +379,6 @@ static int mpcore_wdt_probe(struct platform_device *pdev) static int mpcore_wdt_remove(struct platform_device *pdev) { - platform_set_drvdata(pdev, NULL); - misc_deregister(&mpcore_wdt_miscdev); mpcore_wdt_pdev = NULL; -- GitLab From 6638f4e5e5114fcb0c9dcec05cb3e33454f4a9ac Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Sat, 4 May 2013 01:41:18 +0530 Subject: [PATCH 2663/2900] watchdog: twl4030: Remove redundant platform_set_drvdata() Commit 0998d06310 (device-core: Ensure drvdata = NULL when no driver is bound) removes the need to set driver data field to NULL. Signed-off-by: Sachin Kamat Cc: Timo Kokkonen Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/twl4030_wdt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c index 0f03106f7516..2d4535dc2676 100644 --- a/drivers/watchdog/twl4030_wdt.c +++ b/drivers/watchdog/twl4030_wdt.c @@ -90,10 +90,8 @@ static int twl4030_wdt_probe(struct platform_device *pdev) twl4030_wdt_stop(wdt); ret = watchdog_register_device(wdt); - if (ret) { - platform_set_drvdata(pdev, NULL); + if (ret) return ret; - } return 0; } @@ -103,7 +101,6 @@ static int twl4030_wdt_remove(struct platform_device *pdev) struct watchdog_device *wdt = platform_get_drvdata(pdev); watchdog_unregister_device(wdt); - platform_set_drvdata(pdev, NULL); return 0; } -- GitLab From 5f314970b25a6960dd056b0038ffc7b88dc2973e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 12 May 2013 20:04:03 +0200 Subject: [PATCH 2664/2900] watchdog: jz4740: Pass device to clk_get In preparation to switching the jz4740 clk driver to the common clk framework make sure to pass the device to clk_get(). Signed-off-by: Lars-Peter Clausen Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/jz4740_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 1cb25f69a96d..d1afdf684c18 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -177,7 +177,7 @@ static int jz4740_wdt_probe(struct platform_device *pdev) goto err_out; } - drvdata->rtc_clk = clk_get(NULL, "rtc"); + drvdata->rtc_clk = clk_get(&pdev->dev, "rtc"); if (IS_ERR(drvdata->rtc_clk)) { dev_err(&pdev->dev, "cannot find RTC clock\n"); ret = PTR_ERR(drvdata->rtc_clk); -- GitLab From fcf95670fd29359a382e0755e573b36076d6283e Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 8 Apr 2013 17:06:32 +0200 Subject: [PATCH 2665/2900] watchdog: core: don't try to stop device if not running A watchdog device may be stopped from userspace using WDIOC_SETOPTIONS ioctl and flag WDIOS_DISABLECARD. If the device is closed after this operation, watchdog_release() is called and status bits checked for stopping it. Besides, if the device has not been unregistered a critical message "watchdog did not stop!" is printed, although the ioctl may have successfully stopped it already. Without the patch a user application sample code like this will successfully stop the watchdog, but the kernel will output the message "watchdog did not stop!": wd_fd = open("/dev/watchdog", O_RDWR); flags = WDIOS_DISABLECARD; ioctl(wd_fd, WDIOC_SETOPTIONS, &flags); close(wd_fd); Signed-off-by: Hector Palacios Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/watchdog_dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index faf4e189fe42..6aaefbad303e 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -469,8 +469,10 @@ static int watchdog_release(struct inode *inode, struct file *file) * or if WDIOF_MAGICCLOSE is not set. If nowayout was set then * watchdog_stop will fail. */ - if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) || - !(wdd->info->options & WDIOF_MAGICCLOSE)) + if (!test_bit(WDOG_ACTIVE, &wdd->status)) + err = 0; + else if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) || + !(wdd->info->options & WDIOF_MAGICCLOSE)) err = watchdog_stop(wdd); /* If the watchdog was not stopped, send a keepalive ping */ -- GitLab From cdbaa0bb26d8116d00be24e6b49043777b382f3a Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 10 Jul 2013 17:05:06 -0700 Subject: [PATCH 2666/2900] gso: Update tunnel segmentation to support Tx checksum offload This change makes it so that the GRE and VXLAN tunnels can make use of Tx checksum offload support provided by some drivers via the hw_enc_features. Without this fix enabling GSO means sacrificing Tx checksum offload and this actually leads to a performance regression as shown below: Utilization Send Throughput local GSO 10^6bits/s % S state 6276.51 8.39 enabled 7123.52 8.42 disabled To resolve this it was necessary to address two items. First netif_skb_features needed to be updated so that it would correctly handle the Trans Ether Bridging protocol without impacting the need to check for Q-in-Q tagging. To do this it was necessary to update harmonize_features so that it used skb_network_protocol instead of just using the outer protocol. Second it was necessary to update the GRE and UDP tunnel segmentation offloads so that they would reset the encapsulation bit and inner header offsets after the offload was complete. As a result of this change I have seen the following results on a interface with Tx checksum enabled for encapsulated frames: Utilization Send Throughput local GSO 10^6bits/s % S state 7123.52 8.42 disabled 8321.75 5.43 enabled v2: Instead of replacing refrence to skb->protocol with skb_network_protocol just replace the protocol reference in harmonize_features to allow for double VLAN tag checks. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/dev.c | 14 ++++++-------- net/ipv4/gre_offload.c | 3 +++ net/ipv4/udp.c | 4 +++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 560dafd83adf..a3d8d44cb7f4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2481,10 +2481,10 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) } static netdev_features_t harmonize_features(struct sk_buff *skb, - __be16 protocol, netdev_features_t features) + netdev_features_t features) { if (skb->ip_summed != CHECKSUM_NONE && - !can_checksum_protocol(features, protocol)) { + !can_checksum_protocol(features, skb_network_protocol(skb))) { features &= ~NETIF_F_ALL_CSUM; } else if (illegal_highdma(skb->dev, skb)) { features &= ~NETIF_F_SG; @@ -2505,20 +2505,18 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; } else if (!vlan_tx_tag_present(skb)) { - return harmonize_features(skb, protocol, features); + return harmonize_features(skb, features); } features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); - if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD)) { - return harmonize_features(skb, protocol, features); - } else { + if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; - return harmonize_features(skb, protocol, features); - } + + return harmonize_features(skb, features); } EXPORT_SYMBOL(netif_skb_features); diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 775d5b532ece..55e6bfb3a289 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -100,6 +100,9 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, } __skb_push(skb, tnl_hlen - ghl); + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + skb_reset_mac_header(skb); skb_set_network_header(skb, mac_len); skb->mac_len = mac_len; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index a0d7151ffbd9..766e6bab9113 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2323,6 +2323,9 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, struct udphdr *uh; int udp_offset = outer_hlen - tnl_hlen; + skb_reset_inner_headers(skb); + skb->encapsulation = 1; + skb->mac_len = mac_len; skb_push(skb, outer_hlen); @@ -2345,7 +2348,6 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, uh->check = CSUM_MANGLED_0; } - skb->ip_summed = CHECKSUM_NONE; skb->protocol = protocol; } while ((skb = skb->next)); out: -- GitLab From 48388069bd6736065ed5143cb42d22a16b1744a5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 28 May 2013 12:25:49 +0300 Subject: [PATCH 2667/2900] watchdog: wdrtas: don't use custom version of print_hex_dump Kernel has nice helpers to dump buffers. Signed-off-by: Andy Shevchenko Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdrtas.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 0a77655cda60..3045debd5411 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -161,31 +161,6 @@ static void wdrtas_timer_stop(void) wdrtas_set_interval(0); } -/** - * wdrtas_log_scanned_event - logs an event we received during keepalive - * - * wdrtas_log_scanned_event prints a message to the log buffer dumping - * the results of the last event-scan call - */ -static void wdrtas_log_scanned_event(void) -{ - int i; - - for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16) - pr_info("dumping event (line %i/%i), data = " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16), - wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], - wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], - wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], - wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], - wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], - wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], - wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], - wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]); -} - /** * wdrtas_timer_keepalive - resets watchdog timer to keep system alive * @@ -205,7 +180,9 @@ static void wdrtas_timer_keepalive(void) if (result < 0) pr_err("event-scan failed: %li\n", result); if (result == 0) - wdrtas_log_scanned_event(); + print_hex_dump(KERN_INFO, "dumping event, data: ", + DUMP_PREFIX_OFFSET, 16, 1, + wdrtas_logbuffer, WDRTAS_LOGBUFFER_LEN, false); } while (result == 0); } -- GitLab From 9419c07ccebf6080159b4440dab9b3e484c96d7a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 31 May 2013 07:56:33 +0200 Subject: [PATCH 2668/2900] watchdog: xilinx: Fix driver header - Remove reference for IP version - Fix header coding style - Remove notes which are visible from the code - Fix driver license according to header Signed-off-by: Michal Simek Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 2761ddb08501..d4a35ab89e01 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -1,23 +1,13 @@ /* -* of_xilinx_wdt.c 1.01 A Watchdog Device Driver for Xilinx xps_timebase_wdt -* -* (C) Copyright 2011 (Alejandro Cabrera ) -* -* ----------------------- -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version -* 2 of the License, or (at your option) any later version. -* -* ----------------------- -* 30-May-2011 Alejandro Cabrera -* - If "xlnx,wdt-enable-once" wasn't found on device tree the -* module will use CONFIG_WATCHDOG_NOWAYOUT -* - If the device tree parameters ("clock-frequency" and -* "xlnx,wdt-interval") wasn't found the driver won't -* know the wdt reset interval -*/ + * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt + * + * (C) Copyright 2011 (Alejandro Cabrera ) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -413,5 +403,5 @@ module_platform_driver(xwdt_driver); MODULE_AUTHOR("Alejandro Cabrera "); MODULE_DESCRIPTION("Xilinx Watchdog driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From 8fce9b367d672332d2d101175b10737ee5c18b59 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 31 May 2013 07:56:34 +0200 Subject: [PATCH 2669/2900] watchdog: xilinx: Setup the origin compatible string Watchdog 1.01.a is also compatible with 1.00.a. Add the origin version to compatible list. Signed-off-by: Michal Simek Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index d4a35ab89e01..4dd281f2c33f 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -384,6 +384,7 @@ static int xwdt_remove(struct platform_device *dev) /* Match table for of_platform binding */ static struct of_device_id xwdt_of_match[] = { + { .compatible = "xlnx,xps-timebase-wdt-1.00.a", }, { .compatible = "xlnx,xps-timebase-wdt-1.01.a", }, {}, }; -- GitLab From 6e63a3a294fdf91eaaac1061a9c7a5f53d16ac25 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Jun 2013 20:38:58 +0530 Subject: [PATCH 2670/2900] watchdog: delete mpcore_wdt driver Interrupt request doesn't use the right API: The TWD watchdog uses a per-cpu interrupt (usually interrupt #30), and the GIC configuration should flag it as such. With this setup, request_irq() should fail, and the right API is request_percpu_irq(), together with enable_percpu_irq()/disable_percpu_irq(). Nothing ensures the userspace ioctl() will end-up kicking the watchdog on the right CPU. There are no users of this driver since a long time and it makes more sense to get rid of it as nobody is looking to fix it. In case somebody wakes up after this has been removed and needs it, please revert this driver and pick these updates (These were never pushed to mainline): http://comments.gmane.org/gmane.linux.ports.arm.kernel/245998 Signed-off-by: Viresh Kumar Acked-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../watchdog/watchdog-parameters.txt | 8 - arch/arm/configs/spear13xx_defconfig | 1 - drivers/watchdog/Kconfig | 9 - drivers/watchdog/Makefile | 1 - drivers/watchdog/mpcore_wdt.c | 454 ------------------ 5 files changed, 473 deletions(-) delete mode 100644 drivers/watchdog/mpcore_wdt.c diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt index 04fddbacdbde..f9492fed4104 100644 --- a/Documentation/watchdog/watchdog-parameters.txt +++ b/Documentation/watchdog/watchdog-parameters.txt @@ -194,14 +194,6 @@ reset: Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) ------------------------------------------------- -mpcore_wdt: -mpcore_margin: MPcore timer margin in seconds. - (0 < mpcore_margin < 65536, default=60) -nowayout: Watchdog cannot be stopped once started - (default=kernel config parameter) -mpcore_noboot: MPcore watchdog action, set to 1 to ignore reboots, - 0 to reboot (default=0 -------------------------------------------------- mv64x60_wdt: nowayout: Watchdog cannot be stopped once started (default=kernel config parameter) diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig index 1fdb82694ca2..82eaa552ed14 100644 --- a/arch/arm/configs/spear13xx_defconfig +++ b/arch/arm/configs/spear13xx_defconfig @@ -61,7 +61,6 @@ CONFIG_GPIO_SYSFS=y CONFIG_GPIO_PL061=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y -CONFIG_MPCORE_WATCHDOG=y # CONFIG_HID_SUPPORT is not set CONFIG_USB=y # CONFIG_USB_DEVICE_CLASS is not set diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 7460d349df59..6042e9ed542c 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -221,15 +221,6 @@ config DW_WATCHDOG To compile this driver as a module, choose M here: the module will be called dw_wdt. -config MPCORE_WATCHDOG - tristate "MPcore watchdog" - depends on HAVE_ARM_TWD - help - Watchdog timer embedded into the MPcore system. - - To compile this driver as a module, choose M here: the - module will be called mpcore_wdt. - config EP93XX_WATCHDOG tristate "EP93xx Watchdog" depends on ARCH_EP93XX diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index ec268995b261..291828b356c5 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o -obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c deleted file mode 100644 index 4f5ac408c7a3..000000000000 --- a/drivers/watchdog/mpcore_wdt.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Watchdog driver for the mpcore watchdog timer - * - * (c) Copyright 2004 ARM Limited - * - * Based on the SoftDog driver: - * (c) Copyright 1996 Alan Cox , - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 1995 Alan Cox - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct mpcore_wdt { - unsigned long timer_alive; - struct device *dev; - void __iomem *base; - int irq; - unsigned int perturb; - char expect_close; -}; - -static struct platform_device *mpcore_wdt_pdev; -static DEFINE_SPINLOCK(wdt_lock); - -#define TIMER_MARGIN 60 -static int mpcore_margin = TIMER_MARGIN; -module_param(mpcore_margin, int, 0); -MODULE_PARM_DESC(mpcore_margin, - "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default=" - __MODULE_STRING(TIMER_MARGIN) ")"); - -static bool nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -#define ONLY_TESTING 0 -static int mpcore_noboot = ONLY_TESTING; -module_param(mpcore_noboot, int, 0); -MODULE_PARM_DESC(mpcore_noboot, "MPcore watchdog action, " - "set to 1 to ignore reboots, 0 to reboot (default=" - __MODULE_STRING(ONLY_TESTING) ")"); - -/* - * This is the interrupt handler. Note that we only use this - * in testing mode, so don't actually do a reboot here. - */ -static irqreturn_t mpcore_wdt_fire(int irq, void *arg) -{ - struct mpcore_wdt *wdt = arg; - - /* Check it really was our interrupt */ - if (readl(wdt->base + TWD_WDOG_INTSTAT)) { - dev_crit(wdt->dev, "Triggered - Reboot ignored\n"); - /* Clear the interrupt on the watchdog */ - writel(1, wdt->base + TWD_WDOG_INTSTAT); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -/* - * mpcore_wdt_keepalive - reload the timer - * - * Note that the spec says a DIFFERENT value must be written to the reload - * register each time. The "perturb" variable deals with this by adding 1 - * to the count every other time the function is called. - */ -static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) -{ - unsigned long count; - - spin_lock(&wdt_lock); - /* Assume prescale is set to 256 */ - count = __raw_readl(wdt->base + TWD_WDOG_COUNTER); - count = (0xFFFFFFFFU - count) * (HZ / 5); - count = (count / 256) * mpcore_margin; - - /* Reload the counter */ - writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); - wdt->perturb = wdt->perturb ? 0 : 1; - spin_unlock(&wdt_lock); -} - -static void mpcore_wdt_stop(struct mpcore_wdt *wdt) -{ - spin_lock(&wdt_lock); - writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); - writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); - writel(0x0, wdt->base + TWD_WDOG_CONTROL); - spin_unlock(&wdt_lock); -} - -static void mpcore_wdt_start(struct mpcore_wdt *wdt) -{ - dev_info(wdt->dev, "enabling watchdog\n"); - - /* This loads the count register but does NOT start the count yet */ - mpcore_wdt_keepalive(wdt); - - if (mpcore_noboot) { - /* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */ - writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL); - } else { - /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ - writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); - } -} - -static int mpcore_wdt_set_heartbeat(int t) -{ - if (t < 0x0001 || t > 0xFFFF) - return -EINVAL; - - mpcore_margin = t; - return 0; -} - -/* - * /dev/watchdog handling - */ -static int mpcore_wdt_open(struct inode *inode, struct file *file) -{ - struct mpcore_wdt *wdt = platform_get_drvdata(mpcore_wdt_pdev); - - if (test_and_set_bit(0, &wdt->timer_alive)) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - file->private_data = wdt; - - /* - * Activate timer - */ - mpcore_wdt_start(wdt); - - return nonseekable_open(inode, file); -} - -static int mpcore_wdt_release(struct inode *inode, struct file *file) -{ - struct mpcore_wdt *wdt = file->private_data; - - /* - * Shut off the timer. - * Lock it in if it's a module and we set nowayout - */ - if (wdt->expect_close == 42) - mpcore_wdt_stop(wdt); - else { - dev_crit(wdt->dev, - "unexpected close, not stopping watchdog!\n"); - mpcore_wdt_keepalive(wdt); - } - clear_bit(0, &wdt->timer_alive); - wdt->expect_close = 0; - return 0; -} - -static ssize_t mpcore_wdt_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - struct mpcore_wdt *wdt = file->private_data; - - /* - * Refresh the timer. - */ - if (len) { - if (!nowayout) { - size_t i; - - /* In case it was set long ago */ - wdt->expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - wdt->expect_close = 42; - } - } - mpcore_wdt_keepalive(wdt); - } - return len; -} - -static const struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .identity = "MPcore Watchdog", -}; - -static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct mpcore_wdt *wdt = file->private_data; - int ret; - union { - struct watchdog_info ident; - int i; - } uarg; - - if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg)) - return -ENOTTY; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd)); - if (ret) - return -EFAULT; - } - - switch (cmd) { - case WDIOC_GETSUPPORT: - uarg.ident = ident; - ret = 0; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - uarg.i = 0; - ret = 0; - break; - - case WDIOC_SETOPTIONS: - ret = -EINVAL; - if (uarg.i & WDIOS_DISABLECARD) { - mpcore_wdt_stop(wdt); - ret = 0; - } - if (uarg.i & WDIOS_ENABLECARD) { - mpcore_wdt_start(wdt); - ret = 0; - } - break; - - case WDIOC_KEEPALIVE: - mpcore_wdt_keepalive(wdt); - ret = 0; - break; - - case WDIOC_SETTIMEOUT: - ret = mpcore_wdt_set_heartbeat(uarg.i); - if (ret) - break; - - mpcore_wdt_keepalive(wdt); - /* Fall */ - case WDIOC_GETTIMEOUT: - uarg.i = mpcore_margin; - ret = 0; - break; - - default: - return -ENOTTY; - } - - if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) { - ret = copy_to_user((void __user *)arg, &uarg, _IOC_SIZE(cmd)); - if (ret) - ret = -EFAULT; - } - return ret; -} - -/* - * System shutdown handler. Turn off the watchdog if we're - * restarting or halting the system. - */ -static void mpcore_wdt_shutdown(struct platform_device *pdev) -{ - struct mpcore_wdt *wdt = platform_get_drvdata(pdev); - - if (system_state == SYSTEM_RESTART || system_state == SYSTEM_HALT) - mpcore_wdt_stop(wdt); -} - -/* - * Kernel Interfaces - */ -static const struct file_operations mpcore_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mpcore_wdt_write, - .unlocked_ioctl = mpcore_wdt_ioctl, - .open = mpcore_wdt_open, - .release = mpcore_wdt_release, -}; - -static struct miscdevice mpcore_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mpcore_wdt_fops, -}; - -static int mpcore_wdt_probe(struct platform_device *pdev) -{ - struct mpcore_wdt *wdt; - struct resource *res; - int ret; - - /* We only accept one device, and it must have an id of -1 */ - if (pdev->id != -1) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - wdt = devm_kzalloc(&pdev->dev, sizeof(struct mpcore_wdt), GFP_KERNEL); - if (!wdt) - return -ENOMEM; - - wdt->dev = &pdev->dev; - wdt->irq = platform_get_irq(pdev, 0); - if (wdt->irq >= 0) { - ret = devm_request_irq(wdt->dev, wdt->irq, mpcore_wdt_fire, 0, - "mpcore_wdt", wdt); - if (ret) { - dev_err(wdt->dev, - "cannot register IRQ%d for watchdog\n", - wdt->irq); - return ret; - } - } - - wdt->base = devm_ioremap(wdt->dev, res->start, resource_size(res)); - if (!wdt->base) - return -ENOMEM; - - mpcore_wdt_miscdev.parent = &pdev->dev; - ret = misc_register(&mpcore_wdt_miscdev); - if (ret) { - dev_err(wdt->dev, - "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - return ret; - } - - mpcore_wdt_stop(wdt); - platform_set_drvdata(pdev, wdt); - mpcore_wdt_pdev = pdev; - - return 0; -} - -static int mpcore_wdt_remove(struct platform_device *pdev) -{ - misc_deregister(&mpcore_wdt_miscdev); - - mpcore_wdt_pdev = NULL; - - return 0; -} - -#ifdef CONFIG_PM -static int mpcore_wdt_suspend(struct platform_device *pdev, pm_message_t msg) -{ - struct mpcore_wdt *wdt = platform_get_drvdata(pdev); - mpcore_wdt_stop(wdt); /* Turn the WDT off */ - return 0; -} - -static int mpcore_wdt_resume(struct platform_device *pdev) -{ - struct mpcore_wdt *wdt = platform_get_drvdata(pdev); - /* re-activate timer */ - if (test_bit(0, &wdt->timer_alive)) - mpcore_wdt_start(wdt); - return 0; -} -#else -#define mpcore_wdt_suspend NULL -#define mpcore_wdt_resume NULL -#endif - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:mpcore_wdt"); - -static struct platform_driver mpcore_wdt_driver = { - .probe = mpcore_wdt_probe, - .remove = mpcore_wdt_remove, - .suspend = mpcore_wdt_suspend, - .resume = mpcore_wdt_resume, - .shutdown = mpcore_wdt_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = "mpcore_wdt", - }, -}; - -static int __init mpcore_wdt_init(void) -{ - /* - * Check that the margin value is within it's range; - * if not reset to the default - */ - if (mpcore_wdt_set_heartbeat(mpcore_margin)) { - mpcore_wdt_set_heartbeat(TIMER_MARGIN); - pr_info("mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n", - TIMER_MARGIN); - } - - pr_info("MPcore Watchdog Timer: 0.1. mpcore_noboot=%d mpcore_margin=%d sec (nowayout= %d)\n", - mpcore_noboot, mpcore_margin, nowayout); - - return platform_driver_register(&mpcore_wdt_driver); -} - -static void __exit mpcore_wdt_exit(void) -{ - platform_driver_unregister(&mpcore_wdt_driver); -} - -module_init(mpcore_wdt_init); -module_exit(mpcore_wdt_exit); - -MODULE_AUTHOR("ARM Limited"); -MODULE_DESCRIPTION("MPcore Watchdog Device Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From 87f1369d6e2e820c77cf9eac542eed4dcf036f64 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Wed, 10 Jul 2013 15:46:08 +0200 Subject: [PATCH 2671/2900] pkt_sched: sch_qfq: improve efficiency of make_eligible In make_eligible, a mask is used to decide which groups must become eligible: the i-th group becomes eligible only if the i-th bit of the mask (from the right) is set. The mask is computed by left-shifting a 1 by a given number of places, and decrementing the result. The shift is performed on a ULL to avoid problems in case the number of places to shift is higher than 31. On a 32-bit machine, this is more costly than working on an UL. This patch replaces such a costly operation with two cheaper branches. The trick is based on the following fact: in case of a shift of at least 32 places, the resulting mask has at least the 32 less significant bits set, whereas the total number of groups is lower than 32. As a consequence, in this case it is enough to just set the 32 less significant bits of the mask with a cheaper ~0UL. In the other case, the shift can be safely performed on a UL. Reported-by: David S. Miller Reported-by: David Laight Signed-off-by: Paolo Valente Signed-off-by: David S. Miller --- net/sched/sch_qfq.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 7c195d972bf0..8d86a8b5522a 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -821,7 +821,14 @@ static void qfq_make_eligible(struct qfq_sched *q) unsigned long old_vslot = q->oldV >> q->min_slot_shift; if (vslot != old_vslot) { - unsigned long mask = (1ULL << fls(vslot ^ old_vslot)) - 1; + unsigned long mask; + int last_flip_pos = fls(vslot ^ old_vslot); + + if (last_flip_pos > 31) /* higher than the number of groups */ + mask = ~0UL; /* make all groups eligible */ + else + mask = (1UL << last_flip_pos) - 1; + qfq_move_groups(q, mask, IR, ER); qfq_move_groups(q, mask, IB, EB); } -- GitLab From 88d4f419a43b474a4524f41f55c36bee13416bdd Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Wed, 10 Jul 2013 15:46:09 +0200 Subject: [PATCH 2672/2900] pkt_sched: sch_qfq: remove forward declaration of qfq_update_agg_ts This patch removes the forward declaration of qfq_update_agg_ts, by moving the definition of the function above its first call. This patch also removes a useless forward declaration of qfq_schedule_agg. Reported-by: David S. Miller Signed-off-by: Paolo Valente Signed-off-by: David S. Miller --- net/sched/sch_qfq.c | 118 +++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 63 deletions(-) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 8d86a8b5522a..a7ab323849b6 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -1010,9 +1010,61 @@ static inline void charge_actual_service(struct qfq_aggregate *agg) agg->F = agg->S + (u64)service_received * agg->inv_w; } -static inline void qfq_update_agg_ts(struct qfq_sched *q, - struct qfq_aggregate *agg, - enum update_reason reason); +/* Assign a reasonable start time for a new aggregate in group i. + * Admissible values for \hat(F) are multiples of \sigma_i + * no greater than V+\sigma_i . Larger values mean that + * we had a wraparound so we consider the timestamp to be stale. + * + * If F is not stale and F >= V then we set S = F. + * Otherwise we should assign S = V, but this may violate + * the ordering in EB (see [2]). So, if we have groups in ER, + * set S to the F_j of the first group j which would be blocking us. + * We are guaranteed not to move S backward because + * otherwise our group i would still be blocked. + */ +static void qfq_update_start(struct qfq_sched *q, struct qfq_aggregate *agg) +{ + unsigned long mask; + u64 limit, roundedF; + int slot_shift = agg->grp->slot_shift; + + roundedF = qfq_round_down(agg->F, slot_shift); + limit = qfq_round_down(q->V, slot_shift) + (1ULL << slot_shift); + + if (!qfq_gt(agg->F, q->V) || qfq_gt(roundedF, limit)) { + /* timestamp was stale */ + mask = mask_from(q->bitmaps[ER], agg->grp->index); + if (mask) { + struct qfq_group *next = qfq_ffs(q, mask); + if (qfq_gt(roundedF, next->F)) { + if (qfq_gt(limit, next->F)) + agg->S = next->F; + else /* preserve timestamp correctness */ + agg->S = limit; + return; + } + } + agg->S = q->V; + } else /* timestamp is not stale */ + agg->S = agg->F; +} + +/* Update the timestamps of agg before scheduling/rescheduling it for + * service. In particular, assign to agg->F its maximum possible + * value, i.e., the virtual finish time with which the aggregate + * should be labeled if it used all its budget once in service. + */ +static inline void +qfq_update_agg_ts(struct qfq_sched *q, + struct qfq_aggregate *agg, enum update_reason reason) +{ + if (reason != requeue) + qfq_update_start(q, agg); + else /* just charge agg for the service received */ + agg->S = agg->F; + + agg->F = agg->S + (u64)agg->budgetmax * agg->inv_w; +} static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg); @@ -1135,66 +1187,6 @@ static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q) return agg; } -/* - * Assign a reasonable start time for a new aggregate in group i. - * Admissible values for \hat(F) are multiples of \sigma_i - * no greater than V+\sigma_i . Larger values mean that - * we had a wraparound so we consider the timestamp to be stale. - * - * If F is not stale and F >= V then we set S = F. - * Otherwise we should assign S = V, but this may violate - * the ordering in EB (see [2]). So, if we have groups in ER, - * set S to the F_j of the first group j which would be blocking us. - * We are guaranteed not to move S backward because - * otherwise our group i would still be blocked. - */ -static void qfq_update_start(struct qfq_sched *q, struct qfq_aggregate *agg) -{ - unsigned long mask; - u64 limit, roundedF; - int slot_shift = agg->grp->slot_shift; - - roundedF = qfq_round_down(agg->F, slot_shift); - limit = qfq_round_down(q->V, slot_shift) + (1ULL << slot_shift); - - if (!qfq_gt(agg->F, q->V) || qfq_gt(roundedF, limit)) { - /* timestamp was stale */ - mask = mask_from(q->bitmaps[ER], agg->grp->index); - if (mask) { - struct qfq_group *next = qfq_ffs(q, mask); - if (qfq_gt(roundedF, next->F)) { - if (qfq_gt(limit, next->F)) - agg->S = next->F; - else /* preserve timestamp correctness */ - agg->S = limit; - return; - } - } - agg->S = q->V; - } else /* timestamp is not stale */ - agg->S = agg->F; -} - -/* - * Update the timestamps of agg before scheduling/rescheduling it for - * service. In particular, assign to agg->F its maximum possible - * value, i.e., the virtual finish time with which the aggregate - * should be labeled if it used all its budget once in service. - */ -static inline void -qfq_update_agg_ts(struct qfq_sched *q, - struct qfq_aggregate *agg, enum update_reason reason) -{ - if (reason != requeue) - qfq_update_start(q, agg); - else /* just charge agg for the service received */ - agg->S = agg->F; - - agg->F = agg->S + (u64)agg->budgetmax * agg->inv_w; -} - -static void qfq_schedule_agg(struct qfq_sched *, struct qfq_aggregate *); - static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) { struct qfq_sched *q = qdisc_priv(sch); -- GitLab From 938d0a840d0f97b627111fd038a735f3924fd987 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 18 Jun 2013 19:44:48 +0200 Subject: [PATCH 2673/2900] watchdog: Add Broadcom BCM2835 watchdog timer driver This adds a driver for watchdog timer hardware present on Broadcom BCM2835 SoC, used in Raspberry Pi and Roku 2 devices. Signed-off-by: Lubomir Rintel Tested-by: Stephen Warren Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck Cc: linux-rpi-kernel@lists.infradead.org Cc: linux-watchdog@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org --- .../watchdog/brcm,bcm2835-pm-wdog.txt | 5 + drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/bcm2835_wdt.c | 189 ++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 drivers/watchdog/bcm2835_wdt.c diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt index d209366b4a69..f801d71de1cd 100644 --- a/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt +++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm2835-pm-wdog.txt @@ -5,9 +5,14 @@ Required properties: - compatible : should be "brcm,bcm2835-pm-wdt" - reg : Specifies base physical address and size of the registers. +Optional properties: + +- timeout-sec : Contains the watchdog timeout in seconds + Example: watchdog { compatible = "brcm,bcm2835-pm-wdt"; reg = <0x7e100000 0x28>; + timeout-sec = <10>; }; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 6042e9ed542c..f17ffdb75bb0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1100,6 +1100,17 @@ config BCM63XX_WDT To compile this driver as a loadable module, choose M here. The module will be called bcm63xx_wdt. +config BCM2835_WDT + tristate "Broadcom BCM2835 hardware watchdog" + depends on ARCH_BCM2835 + select WATCHDOG_CORE + help + Watchdog driver for the built in watchdog hardware in Broadcom + BCM2835 SoC. + + To compile this driver as a loadable module, choose M here. + The module will be called bcm2835_wdt. + config LANTIQ_WDT tristate "Lantiq SoC watchdog" depends on LANTIQ diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 291828b356c5..c443f6247fa6 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o +obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c new file mode 100644 index 000000000000..61566fc47f84 --- /dev/null +++ b/drivers/watchdog/bcm2835_wdt.c @@ -0,0 +1,189 @@ +/* + * Watchdog driver for Broadcom BCM2835 + * + * "bcm2708_wdog" driver written by Luke Diamand that was obtained from + * branch "rpi-3.6.y" of git://github.com/raspberrypi/linux.git was used + * as a hardware reference for the Broadcom BCM2835 watchdog timer. + * + * Copyright (C) 2013 Lubomir Rintel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PM_RSTC 0x1c +#define PM_WDOG 0x24 + +#define PM_PASSWORD 0x5a000000 + +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 + +#define SECS_TO_WDOG_TICKS(x) ((x) << 16) +#define WDOG_TICKS_TO_SECS(x) ((x) >> 16) + +struct bcm2835_wdt { + void __iomem *base; + spinlock_t lock; +}; + +static unsigned int heartbeat; +static bool nowayout = WATCHDOG_NOWAYOUT; + +static int bcm2835_wdt_start(struct watchdog_device *wdog) +{ + struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); + uint32_t cur; + unsigned long flags; + + spin_lock_irqsave(&wdt->lock, flags); + + writel_relaxed(PM_PASSWORD | (SECS_TO_WDOG_TICKS(wdog->timeout) & + PM_WDOG_TIME_SET), wdt->base + PM_WDOG); + cur = readl_relaxed(wdt->base + PM_RSTC); + writel_relaxed(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | + PM_RSTC_WRCFG_FULL_RESET, wdt->base + PM_RSTC); + + spin_unlock_irqrestore(&wdt->lock, flags); + + return 0; +} + +static int bcm2835_wdt_stop(struct watchdog_device *wdog) +{ + struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); + + writel_relaxed(PM_PASSWORD | PM_RSTC_RESET, wdt->base + PM_RSTC); + dev_info(wdog->dev, "Watchdog timer stopped"); + return 0; +} + +static int bcm2835_wdt_set_timeout(struct watchdog_device *wdog, unsigned int t) +{ + wdog->timeout = t; + return 0; +} + +static unsigned int bcm2835_wdt_get_timeleft(struct watchdog_device *wdog) +{ + struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); + + uint32_t ret = readl_relaxed(wdt->base + PM_WDOG); + return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET); +} + +static struct watchdog_ops bcm2835_wdt_ops = { + .owner = THIS_MODULE, + .start = bcm2835_wdt_start, + .stop = bcm2835_wdt_stop, + .set_timeout = bcm2835_wdt_set_timeout, + .get_timeleft = bcm2835_wdt_get_timeleft, +}; + +static struct watchdog_info bcm2835_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | + WDIOF_KEEPALIVEPING, + .identity = "Broadcom BCM2835 Watchdog timer", +}; + +static struct watchdog_device bcm2835_wdt_wdd = { + .info = &bcm2835_wdt_info, + .ops = &bcm2835_wdt_ops, + .min_timeout = 1, + .max_timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), + .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), +}; + +static int bcm2835_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct bcm2835_wdt *wdt; + int err; + + wdt = devm_kzalloc(dev, sizeof(struct bcm2835_wdt), GFP_KERNEL); + if (!wdt) { + dev_err(dev, "Failed to allocate memory for watchdog device"); + return -ENOMEM; + } + platform_set_drvdata(pdev, wdt); + + spin_lock_init(&wdt->lock); + + wdt->base = of_iomap(np, 0); + if (!wdt->base) { + dev_err(dev, "Failed to remap watchdog regs"); + return -ENODEV; + } + + watchdog_set_drvdata(&bcm2835_wdt_wdd, wdt); + watchdog_init_timeout(&bcm2835_wdt_wdd, heartbeat, dev); + watchdog_set_nowayout(&bcm2835_wdt_wdd, nowayout); + err = watchdog_register_device(&bcm2835_wdt_wdd); + if (err) { + dev_err(dev, "Failed to register watchdog device"); + iounmap(wdt->base); + return err; + } + + dev_info(dev, "Broadcom BCM2835 watchdog timer"); + return 0; +} + +static int bcm2835_wdt_remove(struct platform_device *pdev) +{ + struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); + + watchdog_unregister_device(&bcm2835_wdt_wdd); + iounmap(wdt->base); + + return 0; +} + +static void bcm2835_wdt_shutdown(struct platform_device *pdev) +{ + bcm2835_wdt_stop(&bcm2835_wdt_wdd); +} + +static const struct of_device_id bcm2835_wdt_of_match[] = { + { .compatible = "brcm,bcm2835-pm-wdt", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm2835_wdt_of_match); + +static struct platform_driver bcm2835_wdt_driver = { + .probe = bcm2835_wdt_probe, + .remove = bcm2835_wdt_remove, + .shutdown = bcm2835_wdt_shutdown, + .driver = { + .name = "bcm2835-wdt", + .owner = THIS_MODULE, + .of_match_table = bcm2835_wdt_of_match, + }, +}; +module_platform_driver(bcm2835_wdt_driver); + +module_param(heartbeat, uint, 0); +MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); + +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +MODULE_AUTHOR("Lubomir Rintel "); +MODULE_DESCRIPTION("Driver for Broadcom BCM2835 watchdog timer"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- GitLab From fa142ff5b3f67fab01f3d02a501b041b4266afdd Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jun 2013 17:19:32 +0100 Subject: [PATCH 2674/2900] Watchdog: allow orion_wdt to be built for Dove The watchdog infrastructure in Dove is no different from that in Orion5x or Kirkwood, so let's enable it for Dove. The only things missing are a few register settings in Dove's bridge-regs.h. Rather than duplicating the same register bit masks for the RSTOUTn_MASK and BRIDGE_CAUSE registers, move the definitions into the watchdog driver itself. Signed-off-by: Russell King Acked-by: Jason Cooper Tested-by: Andrew Lunn Signed-off-by: Wim Van Sebroeck --- arch/arm/mach-dove/include/mach/bridge-regs.h | 1 + arch/arm/mach-kirkwood/include/mach/bridge-regs.h | 2 -- arch/arm/mach-orion5x/include/mach/bridge-regs.h | 3 --- drivers/watchdog/Kconfig | 2 +- drivers/watchdog/orion_wdt.c | 3 +++ 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h index 99f259e8cf33..5362df3df89f 100644 --- a/arch/arm/mach-dove/include/mach/bridge-regs.h +++ b/arch/arm/mach-dove/include/mach/bridge-regs.h @@ -26,6 +26,7 @@ #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) #define SOFT_RESET 0x00000001 +#define BRIDGE_CAUSE (BRIDGE_VIRT_BASE + 0x0110) #define BRIDGE_INT_TIMER1_CLR (~0x0004) #define IRQ_VIRT_BASE (BRIDGE_VIRT_BASE + 0x0200) diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h index d4cbe5e81bb4..91242c944d7a 100644 --- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h +++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h @@ -21,14 +21,12 @@ #define CPU_RESET 0x00000002 #define RSTOUTn_MASK (BRIDGE_VIRT_BASE + 0x0108) -#define WDT_RESET_OUT_EN 0x00000002 #define SOFT_RESET_OUT_EN 0x00000004 #define SYSTEM_SOFT_RESET (BRIDGE_VIRT_BASE + 0x010c) #define SOFT_RESET 0x00000001 #define BRIDGE_CAUSE (BRIDGE_VIRT_BASE + 0x0110) -#define WDT_INT_REQ 0x0008 #define BRIDGE_INT_TIMER1_CLR (~0x0004) diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h index 461fd69a10ae..f727d03f1688 100644 --- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h +++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h @@ -18,7 +18,6 @@ #define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) #define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) -#define WDT_RESET_OUT_EN 0x0002 #define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) @@ -26,8 +25,6 @@ #define POWER_MNG_CTRL_REG (ORION5X_BRIDGE_VIRT_BASE + 0x11C) -#define WDT_INT_REQ 0x0008 - #define BRIDGE_INT_TIMER1_CLR (~0x0004) #define MAIN_IRQ_CAUSE (ORION5X_BRIDGE_VIRT_BASE + 0x200) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index f17ffdb75bb0..b69e4821d668 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -282,7 +282,7 @@ config DAVINCI_WATCHDOG config ORION_WATCHDOG tristate "Orion watchdog" - depends on ARCH_ORION5X || ARCH_KIRKWOOD + depends on ARCH_ORION5X || ARCH_KIRKWOOD || ARCH_DOVE select WATCHDOG_CORE help Say Y here if to include support for the watchdog timer diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index da577980d390..4074244c7183 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -38,6 +38,9 @@ #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 +#define WDT_RESET_OUT_EN BIT(1) +#define WDT_INT_REQ BIT(3) + static bool nowayout = WATCHDOG_NOWAYOUT; static int heartbeat = -1; /* module parameter (seconds) */ static unsigned int wdt_max_duration; /* (seconds) */ -- GitLab From 6910ceb5cababfefffc4ddc58a085a71c0ab9f22 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 Jun 2013 17:20:32 +0100 Subject: [PATCH 2675/2900] Watchdog: fix clearing of the watchdog interrupt The bits in BRIDGE_CAUSE are documented as RW0C - read, write 0 to clear. If we read the register, mask off the watchdog bit, and write it back, we're actually clearing every interrupt which wasn't pending at the time we read the register - and that is racy. Fix this to only write ~WATCHDOG_BIT to the register, which means we write as zero only the watchdog bit. Signed-off-by: Russell King Acked-by: Jason Cooper Tested-by: Andrew Lunn Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/orion_wdt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 4074244c7183..4ea5fcccac02 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -70,9 +70,7 @@ static int orion_wdt_start(struct watchdog_device *wdt_dev) writel(wdt_tclk * wdt_dev->timeout, wdt_reg + WDT_VAL); /* Clear watchdog timer interrupt */ - reg = readl(BRIDGE_CAUSE); - reg &= ~WDT_INT_REQ; - writel(reg, BRIDGE_CAUSE); + writel(~WDT_INT_REQ, BRIDGE_CAUSE); /* Enable watchdog timer */ reg = readl(wdt_reg + TIMER_CTRL); -- GitLab From 26c57ef1ea35f2e7b73db5fad3c81c388d6d056a Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Tue, 18 Jun 2013 17:19:45 +0200 Subject: [PATCH 2676/2900] watchdog: New watchdog driver for MEN A21 watchdogs This patch adds the driver for the watchdog devices found on MEN Mikro Elektronik A21 VMEbus CPU Carrier Boards. It has DT-support and uses the watchdog framework. Signed-off-by: Johannes Thumshirn Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/gpio/men-a021-wdt.txt | 25 ++ MAINTAINERS | 6 + drivers/watchdog/Kconfig | 12 + drivers/watchdog/Makefile | 1 + drivers/watchdog/mena21_wdt.c | 270 ++++++++++++++++++ 5 files changed, 314 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/men-a021-wdt.txt create mode 100644 drivers/watchdog/mena21_wdt.c diff --git a/Documentation/devicetree/bindings/gpio/men-a021-wdt.txt b/Documentation/devicetree/bindings/gpio/men-a021-wdt.txt new file mode 100644 index 000000000000..370dee3226d9 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/men-a021-wdt.txt @@ -0,0 +1,25 @@ +Bindings for MEN A21 Watchdog device connected to GPIO lines + +Required properties: +- compatible: "men,a021-wdt" +- gpios: Specifies the pins that control the Watchdog, order: + 1: Watchdog enable + 2: Watchdog fast-mode + 3: Watchdog trigger + 4: Watchdog reset cause bit 0 + 5: Watchdog reset cause bit 1 + 6: Watchdog reset cause bit 2 + +Optional properties: +- None + +Example: + watchdog { + compatible ="men,a021-wdt"; + gpios = <&gpio3 9 1 /* WD_EN */ + &gpio3 10 1 /* WD_FAST */ + &gpio3 11 1 /* WD_TRIG */ + &gpio3 6 1 /* RST_CAUSE[0] */ + &gpio3 7 1 /* RST_CAUSE[1] */ + &gpio3 8 1>; /* RST_CAUSE[2] */ + }; diff --git a/MAINTAINERS b/MAINTAINERS index cbd4f66bc677..c66b165ab5a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5394,6 +5394,12 @@ F: drivers/mtd/ F: include/linux/mtd/ F: include/uapi/mtd/ +MEN A21 WATCHDOG DRIVER +M: Johannes Thumshirn +L: linux-watchdog@vger.kernel.org +S: Supported +F: drivers/watchdog/mena21_wdt.c + METAG ARCHITECTURE M: James Hogan S: Supported diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b69e4821d668..8519bc696a6f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1185,6 +1185,18 @@ config BOOKE_WDT_DEFAULT_TIMEOUT The value can be overridden by the wdt_period command-line parameter. +config MEN_A21_WDT + tristate "MEN A21 VME CPU Carrier Board Watchdog Timer" + select WATCHDOG_CORE + depends on GPIOLIB + help + Watchdog driver for MEN A21 VMEbus CPU Carrier Boards. + + The driver can also be built as a module. If so, the module will be + called mena21_wdt. + + If unsure select N here. + # PPC64 Architecture config WATCHDOG_RTAS diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index c443f6247fa6..2f26a0b47ddc 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -144,6 +144,7 @@ obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_PIKA_WDT) += pika_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o +obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt.o # PPC64 Architecture obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c new file mode 100644 index 000000000000..96dbba980579 --- /dev/null +++ b/drivers/watchdog/mena21_wdt.c @@ -0,0 +1,270 @@ +/* + * Watchdog driver for the A21 VME CPU Boards + * + * Copyright (C) 2013 MEN Mikro Elektronik Nuernberg GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_GPIOS 6 + +enum a21_wdt_gpios { + GPIO_WD_ENAB, + GPIO_WD_FAST, + GPIO_WD_TRIG, + GPIO_WD_RST0, + GPIO_WD_RST1, + GPIO_WD_RST2, +}; + +struct a21_wdt_drv { + struct watchdog_device wdt; + struct mutex lock; + unsigned gpios[NUM_GPIOS]; +}; + +static bool nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static unsigned int a21_wdt_get_bootstatus(struct a21_wdt_drv *drv) +{ + int reset = 0; + + reset |= gpio_get_value(drv->gpios[GPIO_WD_RST0]) ? (1 << 0) : 0; + reset |= gpio_get_value(drv->gpios[GPIO_WD_RST1]) ? (1 << 1) : 0; + reset |= gpio_get_value(drv->gpios[GPIO_WD_RST2]) ? (1 << 2) : 0; + + return reset; +} + +static int a21_wdt_start(struct watchdog_device *wdt) +{ + struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt); + + mutex_lock(&drv->lock); + + gpio_set_value(drv->gpios[GPIO_WD_ENAB], 1); + + mutex_unlock(&drv->lock); + + return 0; +} + +static int a21_wdt_stop(struct watchdog_device *wdt) +{ + struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt); + + mutex_lock(&drv->lock); + + gpio_set_value(drv->gpios[GPIO_WD_ENAB], 0); + + mutex_unlock(&drv->lock); + + return 0; +} + +static int a21_wdt_ping(struct watchdog_device *wdt) +{ + struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt); + + mutex_lock(&drv->lock); + + gpio_set_value(drv->gpios[GPIO_WD_TRIG], 0); + ndelay(10); + gpio_set_value(drv->gpios[GPIO_WD_TRIG], 1); + + mutex_unlock(&drv->lock); + + return 0; +} + +static int a21_wdt_set_timeout(struct watchdog_device *wdt, + unsigned int timeout) +{ + struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt); + + if (timeout != 1 && timeout != 30) { + dev_err(wdt->dev, "Only 1 and 30 allowed as timeout\n"); + return -EINVAL; + } + + if (timeout == 30 && wdt->timeout == 1) { + dev_err(wdt->dev, + "Transition from fast to slow mode not allowed\n"); + return -EINVAL; + } + + mutex_lock(&drv->lock); + + if (timeout == 1) + gpio_set_value(drv->gpios[GPIO_WD_FAST], 1); + else + gpio_set_value(drv->gpios[GPIO_WD_FAST], 0); + + wdt->timeout = timeout; + + mutex_unlock(&drv->lock); + + return 0; +} + +static const struct watchdog_info a21_wdt_info = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, + .identity = "MEN A21 Watchdog", +}; + +static const struct watchdog_ops a21_wdt_ops = { + .owner = THIS_MODULE, + .start = a21_wdt_start, + .stop = a21_wdt_stop, + .ping = a21_wdt_ping, + .set_timeout = a21_wdt_set_timeout, +}; + +static struct watchdog_device a21_wdt = { + .info = &a21_wdt_info, + .ops = &a21_wdt_ops, + .min_timeout = 1, + .max_timeout = 30, +}; + +static int a21_wdt_probe(struct platform_device *pdev) +{ + struct device_node *node; + struct a21_wdt_drv *drv; + unsigned int reset = 0; + int num_gpios; + int ret; + int i; + + drv = devm_kzalloc(&pdev->dev, sizeof(struct a21_wdt_drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + /* Fill GPIO pin array */ + node = pdev->dev.of_node; + + num_gpios = of_gpio_count(node); + if (num_gpios != NUM_GPIOS) { + dev_err(&pdev->dev, "gpios DT property wrong, got %d want %d", + num_gpios, NUM_GPIOS); + return -ENODEV; + } + + for (i = 0; i < num_gpios; i++) { + int val; + + val = of_get_gpio(node, i); + if (val < 0) + return val; + + drv->gpios[i] = val; + } + + /* Request the used GPIOs */ + for (i = 0; i < num_gpios; i++) { + ret = devm_gpio_request(&pdev->dev, drv->gpios[i], + "MEN A21 Watchdog"); + if (ret) + return ret; + + if (i < GPIO_WD_RST0) + ret = gpio_direction_output(drv->gpios[i], + gpio_get_value(drv->gpios[i])); + else /* GPIO_WD_RST[0..2] are inputs */ + ret = gpio_direction_input(drv->gpios[i]); + if (ret) + return ret; + } + + mutex_init(&drv->lock); + watchdog_init_timeout(&a21_wdt, 30, &pdev->dev); + watchdog_set_nowayout(&a21_wdt, nowayout); + watchdog_set_drvdata(&a21_wdt, drv); + + reset = a21_wdt_get_bootstatus(drv); + if (reset == 2) + a21_wdt.bootstatus |= WDIOF_EXTERN1; + else if (reset == 4) + a21_wdt.bootstatus |= WDIOF_CARDRESET; + else if (reset == 5) + a21_wdt.bootstatus |= WDIOF_POWERUNDER; + else if (reset == 7) + a21_wdt.bootstatus |= WDIOF_EXTERN2; + + ret = watchdog_register_device(&a21_wdt); + if (ret) { + dev_err(&pdev->dev, "Cannot register watchdog device\n"); + goto err_register_wd; + } + + dev_set_drvdata(&pdev->dev, drv); + + dev_info(&pdev->dev, "MEN A21 watchdog timer driver enabled\n"); + + return 0; + +err_register_wd: + mutex_destroy(&drv->lock); + + return ret; +} + +static int a21_wdt_remove(struct platform_device *pdev) +{ + struct a21_wdt_drv *drv = dev_get_drvdata(&pdev->dev); + + dev_warn(&pdev->dev, + "Unregistering A21 watchdog driver, board may reboot\n"); + + watchdog_unregister_device(&drv->wdt); + + mutex_destroy(&drv->lock); + + return 0; +} + +static void a21_wdt_shutdown(struct platform_device *pdev) +{ + struct a21_wdt_drv *drv = dev_get_drvdata(&pdev->dev); + + gpio_set_value(drv->gpios[GPIO_WD_ENAB], 0); +} + +static const struct of_device_id a21_wdt_ids[] = { + { .compatible = "men,a021-wdt" }, + { }, +}; + +static struct platform_driver a21_wdt_driver = { + .probe = a21_wdt_probe, + .remove = a21_wdt_remove, + .shutdown = a21_wdt_shutdown, + .driver = { + .name = "a21-watchdog", + .of_match_table = a21_wdt_ids, + }, +}; + +module_platform_driver(a21_wdt_driver); + +MODULE_AUTHOR("MEN Mikro Elektronik"); +MODULE_DESCRIPTION("MEN A21 Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:a21-watchdog"); -- GitLab From 086f3ec187a18e29f8f36ebd4ae9eb8d48d9fd03 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Tue, 26 Mar 2013 07:26:49 +0000 Subject: [PATCH 2677/2900] watchdog: softdog: remove replaceable ping operation In watchdog_ping(), 'start' is called automatically when 'ping' function call is not configured. Softdog driver has same handling in both cases - start and ping, so 'ping' OPS can be removed. Signed-off-by: Milo(Woogyom) Kim Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/softdog.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index fe83beb8f1b7..b68b1e519d53 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -152,7 +152,6 @@ static struct watchdog_ops softdog_ops = { .owner = THIS_MODULE, .start = softdog_ping, .stop = softdog_stop, - .ping = softdog_ping, .set_timeout = softdog_set_timeout, }; -- GitLab From cce78da76601b64305c050f602767bf58cebcf5d Mon Sep 17 00:00:00 2001 From: "Mingarelli, Thomas" Date: Tue, 9 Jul 2013 23:04:55 +0000 Subject: [PATCH 2678/2900] watchdog: hpwdt: Add check for UEFI bits This patch is being created to use the UEFI bits in the type 219 SMBIOS record in order to decide whether or not to execute BIOS code. This is a better solution than to depend on the iCRU bit since not all future servers will use iCRU. Signed-off-by: Thomas Mingarelli Signed-off-by: Wim Van Sebroeck ---- drivers/watchdog/hpwdt.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) --- drivers/watchdog/hpwdt.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 11796b9b864e..de7e4f497222 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -39,7 +39,7 @@ #endif /* CONFIG_HPWDT_NMI_DECODING */ #include -#define HPWDT_VERSION "1.3.1" +#define HPWDT_VERSION "1.3.2" #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) #define HPWDT_MAX_TIMER TICKS_TO_SECS(65535) @@ -148,6 +148,7 @@ struct cmn_registers { static unsigned int hpwdt_nmi_decoding; static unsigned int allow_kdump = 1; static unsigned int is_icru; +static unsigned int is_uefi; static DEFINE_SPINLOCK(rom_lock); static void *cru_rom_addr; static struct cmn_registers cmn_regs; @@ -484,7 +485,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) goto out; spin_lock_irqsave(&rom_lock, rom_pl); - if (!die_nmi_called && !is_icru) + if (!die_nmi_called && !is_icru && !is_uefi) asminline_call(&cmn_regs, cru_rom_addr); die_nmi_called = 1; spin_unlock_irqrestore(&rom_lock, rom_pl); @@ -492,7 +493,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) if (allow_kdump) hpwdt_stop(); - if (!is_icru) { + if (!is_icru && !is_uefi) { if (cmn_regs.u1.ral == 0) { panic("An NMI occurred, " "but unable to determine source.\n"); @@ -679,6 +680,8 @@ static void dmi_find_icru(const struct dmi_header *dm, void *dummy) smbios_proliant_ptr = (struct smbios_proliant_info *) dm; if (smbios_proliant_ptr->misc_features & 0x01) is_icru = 1; + if (smbios_proliant_ptr->misc_features & 0x408) + is_uefi = 1; } } @@ -697,7 +700,7 @@ static int hpwdt_init_nmi_decoding(struct pci_dev *dev) * the old cru detect code. */ dmi_walk(dmi_find_icru, NULL); - if (!is_icru) { + if (!is_icru && !is_uefi) { /* * We need to map the ROM to get the CRU service. -- GitLab From 1c327d962fc420aea046c16215a552710bde8231 Mon Sep 17 00:00:00 2001 From: David Jeffery Date: Wed, 10 Jul 2013 13:19:50 -0400 Subject: [PATCH 2679/2900] lockd: protect nlm_blocked access in nlmsvc_retry_blocked In nlmsvc_retry_blocked, the check that the list is non-empty and acquiring the pointer of the first entry is unprotected by any lock. This allows a rare race condition when there is only one entry on the list. A function such as nlmsvc_grant_callback() can be called, which will temporarily remove the entry from the list. Between the list_empty() and list_entry(),the list may become empty, causing an invalid pointer to be used as an nlm_block, leading to a possible crash. This patch adds the nlm_block_lock around these calls to prevent concurrent use of the nlm_blocked list. This was a regression introduced by f904be9cc77f361d37d71468b13ff3d1a1823dea "lockd: Mostly remove BKL from the server". Cc: Bryan Schumaker Cc: stable@vger.kernel.org Signed-off-by: David Jeffery Signed-off-by: J. Bruce Fields --- fs/lockd/svclock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e703318c41df..8ebd3f551e0c 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -939,6 +939,7 @@ nlmsvc_retry_blocked(void) unsigned long timeout = MAX_SCHEDULE_TIMEOUT; struct nlm_block *block; + spin_lock(&nlm_blocked_lock); while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { block = list_entry(nlm_blocked.next, struct nlm_block, b_list); @@ -948,6 +949,7 @@ nlmsvc_retry_blocked(void) timeout = block->b_when - jiffies; break; } + spin_unlock(&nlm_blocked_lock); dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", block, block->b_when); @@ -957,7 +959,9 @@ nlmsvc_retry_blocked(void) retry_deferred_block(block); } else nlmsvc_grant_blocked(block); + spin_lock(&nlm_blocked_lock); } + spin_unlock(&nlm_blocked_lock); return timeout; } -- GitLab From c31ad439e8d111bf911c9cc80619cebde411a44d Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Wed, 10 Jul 2013 18:00:36 -0500 Subject: [PATCH 2680/2900] xfs: Fix the logic check for all quotas being turned off During the review of seperate pquota inode patches, David noticed that the test to detect all quotas being turned off was incorrect, and hence the block was not freeing all the quota information. The check made sense in Irix, but in Linux, quota is turned off one at a time, which makes the test invalid for Linux. This problem existed since XFS was ported to Linux. David suggested to fix the problem by detecting when all quotas are turned off by checking m_qflags. Signed-off-by: Chandra Seetharaman Reviewed-by: Ben Myers Signed-off-by: Ben Myers --- fs/xfs/xfs_qm_syscalls.c | 5 ++--- fs/xfs/xfs_quota.h | 8 -------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index b9363838b42b..e4f8b2d6f38b 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c @@ -199,10 +199,9 @@ xfs_qm_scall_quotaoff( } /* - * If quotas is completely disabled, close shop. + * If all quotas are completely turned off, close shop. */ - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) || - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) { + if (mp->m_qflags == 0) { mutex_unlock(&q->qi_quotaofflock); xfs_qm_destroy_quotainfo(mp); return (0); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 09777c41d5b7..b14f42c714b6 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -301,14 +301,6 @@ typedef struct xfs_qoff_logformat { (XFS_IS_PQUOTA_ON(mp) && \ (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0)) -#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ - XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ - XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD) - -#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ - XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\ - XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD) - #define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD|\ -- GitLab From ad065dd01662ae22138899e6b1c8eeb3a529964f Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 11 Jul 2013 18:54:37 -0400 Subject: [PATCH 2681/2900] ext4: don't show usrquota/grpquota twice in /proc/mounts We now print mount options in a generic fashion in ext4_show_options(), so we shouldn't be explicitly printing the {usr,grp}quota options in ext4_show_quota_options(). Without this patch, /proc/mounts can look like this: /dev/vdb /vdb ext4 rw,relatime,quota,usrquota,data=ordered,usrquota 0 0 ^^^^^^^^ ^^^^^^^^ Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/super.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8862d4ddf71f..bca26f34edf4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1702,12 +1702,6 @@ static inline void ext4_show_quota_options(struct seq_file *seq, if (sbi->s_qf_names[GRPQUOTA]) seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]); - - if (test_opt(sb, USRQUOTA)) - seq_puts(seq, ",usrquota"); - - if (test_opt(sb, GRPQUOTA)) - seq_puts(seq, ",grpquota"); #endif } -- GitLab From b33fcf1c9d359374ef6e8e7ec1e0b6f7a8717e16 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 11 Jul 2013 10:58:30 +0400 Subject: [PATCH 2682/2900] CIFS: Reopen the file if reconnect durable handle failed This is a follow-on patch for 8/8 patch from the durable handles series. It fixes the problem when durable file handle timeout expired on the server and reopen returns -ENOENT for such files. Signed-off-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/file.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ba7eed2ee662..1dc9dea2ae70 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -681,6 +681,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) * not dirty locally we could do this. */ rc = server->ops->open(xid, &oparms, &oplock, NULL); + if (rc == -ENOENT && oparms.reconnect == false) { + /* durable handle timeout is expired - open the file again */ + rc = server->ops->open(xid, &oparms, &oplock, NULL); + /* indicate that we need to relock the file */ + oparms.reconnect = true; + } + if (rc) { mutex_unlock(&cfile->fh_mutex); cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); @@ -1510,7 +1517,6 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, if (!rc) goto out; - /* * Windows 7 server can delay breaking lease from read to None * if we set a byte-range lock on a file - break it explicitly -- GitLab From 689c3db4d57a73bee6c5ad7797fce7b54d32a87c Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 11 Jul 2013 11:17:45 +0400 Subject: [PATCH 2683/2900] CIFS: Fix a deadlock when a file is reopened If we request reading or writing on a file that needs to be reopened, it causes the deadlock: we are already holding rw semaphore for reading and then we try to acquire it for writing in cifs_relock_file. Fix this by acquiring the semaphore for reading in cifs_relock_file due to we don't make any changes in locks and don't need a write access. CC: Signed-off-by: Pavel Shilovsky Acked-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/file.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1dc9dea2ae70..1e57f36ea1b2 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -561,11 +561,10 @@ cifs_relock_file(struct cifsFileInfo *cfile) struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); int rc = 0; - /* we are going to update can_cache_brlcks here - need a write access */ - down_write(&cinode->lock_sem); + down_read(&cinode->lock_sem); if (cinode->can_cache_brlcks) { - /* can cache locks - no need to push them */ - up_write(&cinode->lock_sem); + /* can cache locks - no need to relock */ + up_read(&cinode->lock_sem); return rc; } @@ -576,7 +575,7 @@ cifs_relock_file(struct cifsFileInfo *cfile) else rc = tcon->ses->server->ops->push_mand_locks(cfile); - up_write(&cinode->lock_sem); + up_read(&cinode->lock_sem); return rc; } -- GitLab From 8c91e162e058bb91b7766f26f4d5823a21941026 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 11 Jul 2013 13:12:22 -0700 Subject: [PATCH 2684/2900] gre: Fix MTU sizing check for gretap tunnels This change fixes an MTU sizing issue seen with gretap tunnels when non-gso packets are sent from the interface. In my case I was able to reproduce the issue by simply sending a ping of 1421 bytes with the gretap interface created on a device with a standard 1500 mtu. This fix is based on the fact that the tunnel mtu is already adjusted by dev->hard_header_len so it would make sense that any packets being compared against that mtu should also be adjusted by hard_header_len and the tunnel header instead of just the tunnel header. Signed-off-by: Alexander Duyck Reported-by: Cong Wang Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 945734b2f209..ca1cb2d5f6e2 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -476,7 +476,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, struct rtable *rt, __be16 df) { struct ip_tunnel *tunnel = netdev_priv(dev); - int pkt_size = skb->len - tunnel->hlen; + int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; int mtu; if (df) -- GitLab From 7ad031ee468e4ed9196215394d7e18a78a66a7da Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Wed, 10 Jul 2013 14:00:22 -0400 Subject: [PATCH 2685/2900] qlcnic: Adding Maintainers. Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 37f9a71c744f..6a904d30d6a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6651,10 +6651,12 @@ F: Documentation/networking/LICENSE.qla3xxx F: drivers/net/ethernet/qlogic/qla3xxx.* QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER +M: Himanshu Madhani M: Rajesh Borundia M: Shahed Shaikh M: Jitendra Kalsaria M: Sony Chacko +M: Sucheta Chakraborty M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported -- GitLab From 80d5e8a235624cd3c0e24be7c070fd6f445e590d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 10 Jul 2013 17:36:35 +0200 Subject: [PATCH 2686/2900] IB/srp: Let srp_abort() return FAST_IO_FAIL if TL offline If the transport layer is offline it is more appropriate to let srp_abort() return FAST_IO_FAIL instead of SUCCESS. Reported-by: Sebastian Riemer Acked-by: David Dillow Signed-off-by: Bart Van Assche Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9d8b46eafdb2..f93baf8254c4 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1753,8 +1753,7 @@ static int srp_abort(struct scsi_cmnd *scmnd) if (!req || !srp_claim_req(target, req, scmnd)) return FAILED; if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK) == 0 || - target->transport_offline) + SRP_TSK_ABORT_TASK) == 0) ret = SUCCESS; else if (target->transport_offline) ret = FAST_IO_FAIL; -- GitLab From 288dde9f23b6726c1e8147bf635721372bf77b16 Mon Sep 17 00:00:00 2001 From: Moshe Lazer Date: Wed, 10 Jul 2013 14:31:03 +0300 Subject: [PATCH 2687/2900] mlx5_core: Adjust hca_cap.uar_page_sz to conform to Connect-IB spec Sparse reported an endianness bug in the assignment to hca_cap.uar_page_sz. Fix the declaration of this field to be __be16 (which is what is in the firmware spec), renaming the field to log_uar_pg_size to conform to the spec, which fixes the endianness bug reported by sparse. Reported-by: Fengguang Wu Signed-off-by: Moshe Lazer Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- include/linux/mlx5/device.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index f21cc397d1bc..12242de2b0e3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -212,7 +212,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev) set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp; memset(&set_out, 0, sizeof(set_out)); - set_ctx->hca_cap.uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12); + set_ctx->hca_cap.log_uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12); set_ctx->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_SET_HCA_CAP); err = mlx5_cmd_exec(dev, set_ctx, sizeof(*set_ctx), &set_out, sizeof(set_out)); diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 51390915e538..8de8d8f22384 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -317,8 +317,8 @@ struct mlx5_hca_cap { u8 log_max_pd; u8 rsvd25; u8 log_max_xrcd; - u8 rsvd26[40]; - __be32 uar_page_sz; + u8 rsvd26[42]; + __be16 log_uar_page_sz; u8 rsvd27[28]; u8 log_msx_atomic_size_qp; u8 rsvd28[2]; -- GitLab From 308c813b19cb676df7e5e70b5f014fa56e918677 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 3 Jul 2013 13:50:28 -0400 Subject: [PATCH 2688/2900] IB/qib: Fix module-level leak The vzalloc()'ed field physshadow is leaked on module unload. This patch adds vfree after the sibling page shadow is freed. Reported-by: Dean Luick Reviewed-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index fdae42973056..36e048e0e1d9 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1350,7 +1350,7 @@ static void cleanup_device_data(struct qib_devdata *dd) if (dd->pageshadow) { struct page **tmpp = dd->pageshadow; dma_addr_t *tmpd = dd->physshadow; - int i, cnt = 0; + int i; for (ctxt = 0; ctxt < dd->cfgctxts; ctxt++) { int ctxt_tidbase = ctxt * dd->rcvtidcnt; @@ -1363,13 +1363,13 @@ static void cleanup_device_data(struct qib_devdata *dd) PAGE_SIZE, PCI_DMA_FROMDEVICE); qib_release_user_pages(&tmpp[i], 1); tmpp[i] = NULL; - cnt++; } } - tmpp = dd->pageshadow; dd->pageshadow = NULL; vfree(tmpp); + dd->physshadow = NULL; + vfree(tmpd); } /* -- GitLab From 0b3ddf380ca7aa6a009cc3e1944933fff8113b6a Mon Sep 17 00:00:00 2001 From: Dean Luick Date: Thu, 11 Jul 2013 15:32:14 -0400 Subject: [PATCH 2689/2900] IB/qib: Log all SDMA errors unconditionally This patch adds code to log SDMA errors for supportability purposes. Signed-off-by: Dean Luick Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib.h | 2 +- drivers/infiniband/hw/qib/qib_iba7322.c | 114 ++++++++++++++++++++++++ drivers/infiniband/hw/qib/qib_sdma.c | 56 ++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 5453e2b36567..4a9af795b88f 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1348,7 +1348,7 @@ static inline int __qib_sdma_running(struct qib_pportdata *ppd) return ppd->sdma_state.current_state == qib_sdma_state_s99_running; } int qib_sdma_running(struct qib_pportdata *); - +void dump_sdma_state(struct qib_pportdata *ppd); void __qib_sdma_process_event(struct qib_pportdata *, enum qib_sdma_events); void qib_sdma_process_event(struct qib_pportdata *, enum qib_sdma_events); diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index f7c4b44b1f93..21e8b09d4bf8 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -83,6 +83,7 @@ static void ibsd_wr_allchans(struct qib_pportdata *, int, unsigned, unsigned); static void serdes_7322_los_enable(struct qib_pportdata *, int); static int serdes_7322_init_old(struct qib_pportdata *); static int serdes_7322_init_new(struct qib_pportdata *); +static void dump_sdma_7322_state(struct qib_pportdata *); #define BMASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb)) @@ -652,6 +653,7 @@ struct qib_chippport_specific { u8 ibmalfusesnap; struct qib_qsfp_data qsfp_data; char epmsgbuf[192]; /* for port error interrupt msg buffer */ + char sdmamsgbuf[192]; /* for per-port sdma error messages */ }; static struct { @@ -1601,6 +1603,15 @@ static void sdma_7322_p_errors(struct qib_pportdata *ppd, u64 errs) spin_lock_irqsave(&ppd->sdma_lock, flags); + if (errs != QIB_E_P_SDMAHALT) { + /* SDMA errors have QIB_E_P_SDMAHALT and another bit set */ + qib_dev_porterr(dd, ppd->port, + "SDMA %s 0x%016llx %s\n", + qib_sdma_state_names[ppd->sdma_state.current_state], + errs, ppd->cpspec->sdmamsgbuf); + dump_sdma_7322_state(ppd); + } + switch (ppd->sdma_state.current_state) { case qib_sdma_state_s00_hw_down: break; @@ -2156,6 +2167,29 @@ static void qib_7322_handle_hwerrors(struct qib_devdata *dd, char *msg, qib_dev_err(dd, "%s hardware error\n", msg); + if (hwerrs & + (SYM_MASK(HwErrMask, SDmaMemReadErrMask_0) | + SYM_MASK(HwErrMask, SDmaMemReadErrMask_1))) { + int pidx = 0; + int err; + unsigned long flags; + struct qib_pportdata *ppd = dd->pport; + for (; pidx < dd->num_pports; ++pidx, ppd++) { + err = 0; + if (pidx == 0 && (hwerrs & + SYM_MASK(HwErrMask, SDmaMemReadErrMask_0))) + err++; + if (pidx == 1 && (hwerrs & + SYM_MASK(HwErrMask, SDmaMemReadErrMask_1))) + err++; + if (err) { + spin_lock_irqsave(&ppd->sdma_lock, flags); + dump_sdma_7322_state(ppd); + spin_unlock_irqrestore(&ppd->sdma_lock, flags); + } + } + } + if (isfatal && !dd->diag_client) { qib_dev_err(dd, "Fatal Hardware Error, no longer usable, SN %.16s\n", @@ -6753,6 +6787,86 @@ static void qib_sdma_set_7322_desc_cnt(struct qib_pportdata *ppd, unsigned cnt) qib_write_kreg_port(ppd, krp_senddmadesccnt, cnt); } +/* + * sdma_lock should be acquired before calling this routine + */ +static void dump_sdma_7322_state(struct qib_pportdata *ppd) +{ + u64 reg, reg1, reg2; + + reg = qib_read_kreg_port(ppd, krp_senddmastatus); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmastatus: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_sendctrl); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA sendctrl: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmabase); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmabase: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmabufmask0); + reg1 = qib_read_kreg_port(ppd, krp_senddmabufmask1); + reg2 = qib_read_kreg_port(ppd, krp_senddmabufmask2); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmabufmask 0:%llx 1:%llx 2:%llx\n", + reg, reg1, reg2); + + /* get bufuse bits, clear them, and print them again if non-zero */ + reg = qib_read_kreg_port(ppd, krp_senddmabuf_use0); + qib_write_kreg_port(ppd, krp_senddmabuf_use0, reg); + reg1 = qib_read_kreg_port(ppd, krp_senddmabuf_use1); + qib_write_kreg_port(ppd, krp_senddmabuf_use0, reg1); + reg2 = qib_read_kreg_port(ppd, krp_senddmabuf_use2); + qib_write_kreg_port(ppd, krp_senddmabuf_use0, reg2); + /* 0 and 1 should always be zero, so print as short form */ + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA current senddmabuf_use 0:%llx 1:%llx 2:%llx\n", + reg, reg1, reg2); + reg = qib_read_kreg_port(ppd, krp_senddmabuf_use0); + reg1 = qib_read_kreg_port(ppd, krp_senddmabuf_use1); + reg2 = qib_read_kreg_port(ppd, krp_senddmabuf_use2); + /* 0 and 1 should always be zero, so print as short form */ + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA cleared senddmabuf_use 0:%llx 1:%llx 2:%llx\n", + reg, reg1, reg2); + + reg = qib_read_kreg_port(ppd, krp_senddmatail); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmatail: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmahead); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmahead: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmaheadaddr); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmaheadaddr: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmalengen); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmalengen: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmadesccnt); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmadesccnt: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmaidlecnt); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmaidlecnt: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmaprioritythld); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmapriorityhld: 0x%016llx\n", reg); + + reg = qib_read_kreg_port(ppd, krp_senddmareloadcnt); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA senddmareloadcnt: 0x%016llx\n", reg); + + dump_sdma_state(ppd); +} + static struct sdma_set_state_action sdma_7322_action_table[] = { [qib_sdma_state_s00_hw_down] = { .go_s99_running_tofalse = 1, diff --git a/drivers/infiniband/hw/qib/qib_sdma.c b/drivers/infiniband/hw/qib/qib_sdma.c index 3fc514431212..32162d355370 100644 --- a/drivers/infiniband/hw/qib/qib_sdma.c +++ b/drivers/infiniband/hw/qib/qib_sdma.c @@ -708,6 +708,62 @@ int qib_sdma_verbs_send(struct qib_pportdata *ppd, return ret; } +/* + * sdma_lock should be acquired before calling this routine + */ +void dump_sdma_state(struct qib_pportdata *ppd) +{ + struct qib_sdma_desc *descq; + struct qib_sdma_txreq *txp, *txpnext; + __le64 *descqp; + u64 desc[2]; + dma_addr_t addr; + u16 gen, dwlen, dwoffset; + u16 head, tail, cnt; + + head = ppd->sdma_descq_head; + tail = ppd->sdma_descq_tail; + cnt = qib_sdma_descq_freecnt(ppd); + descq = ppd->sdma_descq; + + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA ppd->sdma_descq_head: %u\n", head); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA ppd->sdma_descq_tail: %u\n", tail); + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA sdma_descq_freecnt: %u\n", cnt); + + /* print info for each entry in the descriptor queue */ + while (head != tail) { + char flags[6] = { 'x', 'x', 'x', 'x', 'x', 0 }; + + descqp = &descq[head].qw[0]; + desc[0] = le64_to_cpu(descqp[0]); + desc[1] = le64_to_cpu(descqp[1]); + flags[0] = (desc[0] & 1<<15) ? 'I' : '-'; + flags[1] = (desc[0] & 1<<14) ? 'L' : 'S'; + flags[2] = (desc[0] & 1<<13) ? 'H' : '-'; + flags[3] = (desc[0] & 1<<12) ? 'F' : '-'; + flags[4] = (desc[0] & 1<<11) ? 'L' : '-'; + addr = (desc[1] << 32) | ((desc[0] >> 32) & 0xfffffffcULL); + gen = (desc[0] >> 30) & 3ULL; + dwlen = (desc[0] >> 14) & (0x7ffULL << 2); + dwoffset = (desc[0] & 0x7ffULL) << 2; + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA sdmadesc[%u]: flags:%s addr:0x%016llx gen:%u len:%u bytes offset:%u bytes\n", + head, flags, addr, gen, dwlen, dwoffset); + if (++head == ppd->sdma_descq_cnt) + head = 0; + } + + /* print dma descriptor indices from the TX requests */ + list_for_each_entry_safe(txp, txpnext, &ppd->sdma_activelist, + list) + qib_dev_porterr(ppd->dd, ppd->port, + "SDMA txp->start_idx: %u txp->next_descq_idx: %u\n", + txp->start_idx, txp->next_descq_idx); +} + void qib_sdma_process_event(struct qib_pportdata *ppd, enum qib_sdma_events event) { -- GitLab From 5e631a03af7eaa55b9ef7fa7611144c2c698c6c6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Jul 2013 13:58:59 +0300 Subject: [PATCH 2690/2900] mlx5: Return -EFAULT instead of -EPERM For copy_to/from_user() failure, the correct error code is -EFAULT not -EPERM. Signed-off-by: Dan Carpenter Acked-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx5/mr.c | 8 ++++---- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 10 +++++----- drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 12 ++++-------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index e2daa8f02476..bd41df95b6f0 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -171,7 +171,7 @@ static ssize_t size_write(struct file *filp, const char __user *buf, int c; if (copy_from_user(lbuf, buf, sizeof(lbuf))) - return -EPERM; + return -EFAULT; c = order2idx(dev, ent->order); lbuf[sizeof(lbuf) - 1] = 0; @@ -208,7 +208,7 @@ static ssize_t size_read(struct file *filp, char __user *buf, size_t count, return err; if (copy_to_user(buf, lbuf, err)) - return -EPERM; + return -EFAULT; *pos += err; @@ -233,7 +233,7 @@ static ssize_t limit_write(struct file *filp, const char __user *buf, int c; if (copy_from_user(lbuf, buf, sizeof(lbuf))) - return -EPERM; + return -EFAULT; c = order2idx(dev, ent->order); lbuf[sizeof(lbuf) - 1] = 0; @@ -270,7 +270,7 @@ static ssize_t limit_read(struct file *filp, char __user *buf, size_t count, return err; if (copy_to_user(buf, lbuf, err)) - return -EPERM; + return -EFAULT; *pos += err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index c1c0eef89694..205753a04cfc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -693,7 +693,7 @@ static ssize_t dbg_write(struct file *filp, const char __user *buf, return -ENOMEM; if (copy_from_user(lbuf, buf, sizeof(lbuf))) - return -EPERM; + return -EFAULT; lbuf[sizeof(lbuf) - 1] = 0; @@ -889,7 +889,7 @@ static ssize_t data_write(struct file *filp, const char __user *buf, return -ENOMEM; if (copy_from_user(ptr, buf, count)) { - err = -EPERM; + err = -EFAULT; goto out; } dbg->in_msg = ptr; @@ -919,7 +919,7 @@ static ssize_t data_read(struct file *filp, char __user *buf, size_t count, copy = min_t(int, count, dbg->outlen); if (copy_to_user(buf, dbg->out_msg, copy)) - return -EPERM; + return -EFAULT; *pos += copy; @@ -949,7 +949,7 @@ static ssize_t outlen_read(struct file *filp, char __user *buf, size_t count, return err; if (copy_to_user(buf, &outlen, err)) - return -EPERM; + return -EFAULT; *pos += err; @@ -974,7 +974,7 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, dbg->outlen = 0; if (copy_from_user(outlen_str, buf, count)) - return -EPERM; + return -EFAULT; outlen_str[7] = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index a550a8ef94a1..4273c06e2e96 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -148,7 +148,6 @@ static ssize_t average_read(struct file *filp, char __user *buf, size_t count, struct mlx5_cmd_stats *stats; u64 field = 0; int ret; - int err; char tbuf[22]; if (*pos) @@ -161,9 +160,8 @@ static ssize_t average_read(struct file *filp, char __user *buf, size_t count, spin_unlock(&stats->lock); ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field); if (ret > 0) { - err = copy_to_user(buf, tbuf, ret); - if (err) - return err; + if (copy_to_user(buf, tbuf, ret)) + return -EFAULT; } *pos += ret; @@ -418,7 +416,6 @@ static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count, char tbuf[18]; u64 field; int ret; - int err; if (*pos) return 0; @@ -445,9 +442,8 @@ static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count, ret = snprintf(tbuf, sizeof(tbuf), "0x%llx\n", field); if (ret > 0) { - err = copy_to_user(buf, tbuf, ret); - if (err) - return err; + if (copy_to_user(buf, tbuf, ret)) + return -EFAULT; } *pos += ret; -- GitLab From d77e41e12744e53ca7f98f920350998b5f00c93a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2013 17:30:34 +0300 Subject: [PATCH 2691/2900] net/tipc: use %*phC to dump small buffers in hex form Instead of passing each byte by stack let's use nice specifier for that. Signed-off-by: Andy Shevchenko Signed-off-by: David S. Miller --- net/tipc/ib_media.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c index ad2e1ec4117e..9934a32bfa87 100644 --- a/net/tipc/ib_media.c +++ b/net/tipc/ib_media.c @@ -292,13 +292,7 @@ static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) if (str_size < 60) /* 60 = 19 * strlen("xx:") + strlen("xx\0") */ return 1; - sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" - "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - a->value[0], a->value[1], a->value[2], a->value[3], - a->value[4], a->value[5], a->value[6], a->value[7], - a->value[8], a->value[9], a->value[10], a->value[11], - a->value[12], a->value[13], a->value[14], a->value[15], - a->value[16], a->value[17], a->value[18], a->value[19]); + sprintf(str_buf, "%20phC", a->value); return 0; } -- GitLab From c073f666ff5c38477849c5109f2c430df1a60e82 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Mon, 8 Jul 2013 10:41:21 +0800 Subject: [PATCH 2692/2900] net/usb: add relative mii functions for r815x Base on cdc_ether, add the mii functions for RTL8152 and RTL8153. The RTL8152 and RTL8153 support ECM mode which use the driver of cdc_ether. Add the mii functions. Then, the basic PHY access is possible. Signed-off-by: Hayes Wang Signed-off-by: David S. Miller --- drivers/net/usb/Makefile | 2 +- drivers/net/usb/cdc_ether.c | 9 +- drivers/net/usb/r815x.c | 231 ++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 drivers/net/usb/r815x.c diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 9ab5c9d4b45a..e8171784529d 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o asix-y := asix_devices.o asix_common.o ax88172a.o obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o -obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o +obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 4393f1483126..03ad4dc293aa 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -646,13 +646,18 @@ static const struct usb_device_id products [] = { }, /* Realtek RTL8152 Based USB 2.0 Ethernet Adapters */ -#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE) { USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = 0, }, -#endif + +/* Realtek RTL8153 Based USB 3.0 Ethernet Adapters */ +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, /* * WHITELIST!!! diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c new file mode 100644 index 000000000000..65167377ff09 --- /dev/null +++ b/drivers/net/usb/r815x.c @@ -0,0 +1,231 @@ +#include +#include +#include +#include +#include +#include + +#define RTL815x_REQT_READ 0xc0 +#define RTL815x_REQT_WRITE 0x40 +#define RTL815x_REQ_GET_REGS 0x05 +#define RTL815x_REQ_SET_REGS 0x05 + +#define MCU_TYPE_PLA 0x0100 +#define OCP_BASE 0xe86c +#define BASE_MII 0xa400 + +#define BYTE_EN_DWORD 0xff +#define BYTE_EN_WORD 0x33 +#define BYTE_EN_BYTE 0x11 + +#define R815x_PHY_ID 32 +#define REALTEK_VENDOR_ID 0x0bda + + +static int pla_read_word(struct usb_device *udev, u16 index) +{ + int data, ret; + u8 shift = index & 2; + + index &= ~3; + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, + index, MCU_TYPE_PLA, &data, sizeof(data), 500); + if (ret < 0) + return ret; + + data = __le32_to_cpu(data); + data >>= (shift * 8); + data &= 0xffff; + + return data; +} + +static int pla_write_word(struct usb_device *udev, u16 index, u32 data) +{ + u32 tmp, mask = 0xffff; + u16 byen = BYTE_EN_WORD; + u8 shift = index & 2; + int ret; + + data &= mask; + + if (shift) { + byen <<= shift; + mask <<= (shift * 8); + data <<= (shift * 8); + index &= ~3; + } + + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, + index, MCU_TYPE_PLA, &tmp, sizeof(tmp), 500); + if (ret < 0) + return ret; + + tmp = __le32_to_cpu(tmp) & ~mask; + tmp |= data; + tmp = __cpu_to_le32(tmp); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, + index, MCU_TYPE_PLA | byen, &tmp, + sizeof(tmp), 500); + + return ret; +} + +static int ocp_reg_read(struct usbnet *dev, u16 addr) +{ + u16 ocp_base, ocp_index; + int ret; + + ocp_base = addr & 0xf000; + ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); + if (ret < 0) + goto out; + + ocp_index = (addr & 0x0fff) | 0xb000; + ret = pla_read_word(dev->udev, ocp_index); + +out: + return ret; +} + +static int ocp_reg_write(struct usbnet *dev, u16 addr, u16 data) +{ + u16 ocp_base, ocp_index; + int ret; + + ocp_base = addr & 0xf000; + ret = pla_write_word(dev->udev, OCP_BASE, ocp_base); + if (ret < 0) + goto out1; + + ocp_index = (addr & 0x0fff) | 0xb000; + ret = pla_write_word(dev->udev, ocp_index, data); + +out1: + return ret; +} + +static int r815x_mdio_read(struct net_device *netdev, int phy_id, int reg) +{ + struct usbnet *dev = netdev_priv(netdev); + + if (phy_id != R815x_PHY_ID) + return -EINVAL; + + return ocp_reg_read(dev, BASE_MII + reg * 2); +} + +static +void r815x_mdio_write(struct net_device *netdev, int phy_id, int reg, int val) +{ + struct usbnet *dev = netdev_priv(netdev); + + if (phy_id != R815x_PHY_ID) + return; + + ocp_reg_write(dev, BASE_MII + reg * 2, val); +} + +static int r8153_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status; + + status = usbnet_cdc_bind(dev, intf); + if (status < 0) + return status; + + dev->mii.dev = dev->net; + dev->mii.mdio_read = r815x_mdio_read; + dev->mii.mdio_write = r815x_mdio_write; + dev->mii.phy_id_mask = 0x3f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = R815x_PHY_ID; + dev->mii.supports_gmii = 1; + + return 0; +} + +static int r8152_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status; + + status = usbnet_cdc_bind(dev, intf); + if (status < 0) + return status; + + dev->mii.dev = dev->net; + dev->mii.mdio_read = r815x_mdio_read; + dev->mii.mdio_write = r815x_mdio_write; + dev->mii.phy_id_mask = 0x3f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = R815x_PHY_ID; + dev->mii.supports_gmii = 0; + + return 0; +} + +static const struct driver_info r8152_info = { + .description = "RTL8152 ECM Device", + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, + .bind = r8152_bind, + .unbind = usbnet_cdc_unbind, + .status = usbnet_cdc_status, + .manage_power = usbnet_manage_power, +}; + +static const struct driver_info r8153_info = { + .description = "RTL8153 ECM Device", + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, + .bind = r8153_bind, + .unbind = usbnet_cdc_unbind, + .status = usbnet_cdc_status, + .manage_power = usbnet_manage_power, +}; + +static const struct usb_device_id products[] = { +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8152, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +#if defined(CONFIG_USB_RTL8152) || defined(CONFIG_USB_RTL8152_MODULE) + .driver_info = 0, +#else + .driver_info = (unsigned long) &r8152_info, +#endif +}, + +{ + USB_DEVICE_AND_INTERFACE_INFO(REALTEK_VENDOR_ID, 0x8153, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), +#if defined(CONFIG_USB_RTL8153) || defined(CONFIG_USB_RTL8153_MODULE) + .driver_info = 0, +#else + .driver_info = (unsigned long) &r8153_info, +#endif +}, + + { }, /* END */ +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver r815x_driver = { + .name = "r815x", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, + .reset_resume = usbnet_resume, + .supports_autosuspend = 1, + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(r815x_driver); + +MODULE_AUTHOR("Hayes Wang"); +MODULE_DESCRIPTION("Realtek USB ECM device"); +MODULE_LICENSE("GPL"); -- GitLab From d25903f894849fa799141e774c4ad34199e3e6a1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:42 +0100 Subject: [PATCH 2693/2900] drivers/net/can/c_can: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang Acked-by: Marc Kleine-Budde Signed-off-by: David S. Miller --- drivers/net/can/c_can/c_can_platform.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index b918c7329426..c6f838d922a5 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -114,7 +113,6 @@ static int c_can_plat_probe(struct platform_device *pdev) struct c_can_priv *priv; const struct of_device_id *match; const struct platform_device_id *id; - struct pinctrl *pinctrl; struct resource *mem, *res; int irq; struct clk *clk; @@ -131,11 +129,6 @@ static int c_can_plat_probe(struct platform_device *pdev) id = platform_get_device_id(pdev); } - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, - "failed to configure pins from driver\n"); - /* get the appropriate clk */ clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { -- GitLab From 54842ec2b0644b3e04c6fcfb52bc94dfcf918a43 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:43 +0100 Subject: [PATCH 2694/2900] drivers/net/ethernet/cadence: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/at91_ether.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 3f1957158a3b..bb5d63fb2e6d 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -29,7 +29,6 @@ #include #include #include -#include #include "macb.h" @@ -309,7 +308,6 @@ static int __init at91ether_probe(struct platform_device *pdev) struct resource *regs; struct net_device *dev; struct phy_device *phydev; - struct pinctrl *pinctrl; struct macb *lp; int res; u32 reg; @@ -319,15 +317,6 @@ static int __init at91ether_probe(struct platform_device *pdev) if (!regs) return -ENOENT; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - res = PTR_ERR(pinctrl); - if (res == -EPROBE_DEFER) - return res; - - dev_warn(&pdev->dev, "No pinctrl provided\n"); - } - dev = alloc_etherdev(sizeof(struct macb)); if (!dev) return -ENOMEM; -- GitLab From fdb70270015466076846a0525f195f59849c1966 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:44 +0100 Subject: [PATCH 2695/2900] drivers/net/ieee802154: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/net/ieee802154/mrf24j40.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index ede3ce4912f9..42e6deee6db5 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -627,7 +626,6 @@ static int mrf24j40_probe(struct spi_device *spi) int ret = -ENOMEM; u8 val; struct mrf24j40 *devrec; - struct pinctrl *pinctrl; printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq); @@ -638,11 +636,6 @@ static int mrf24j40_probe(struct spi_device *spi) if (!devrec->buf) goto err_buf; - pinctrl = devm_pinctrl_get_select_default(&spi->dev); - if (IS_ERR(pinctrl)) - dev_warn(&spi->dev, - "pinctrl pins are not configured from the driver"); - spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */ if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) spi->max_speed_hz = MAX_SPI_SPEED_HZ; -- GitLab From e8974c3930ae9692bb4f77380961421e9a2f76ab Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Thu, 11 Jul 2013 22:42:42 -0400 Subject: [PATCH 2696/2900] ext4: rate limit printk in buffer_io_error() If there are a lot of outstanding buffered IOs when a device is taken offline (due to hardware errors etc), ext4_end_bio prints out a message for each failed logical block. While this is desirable, we see thousands of such lines being printed out before the serial console gets overwhelmed, causing ext4_end_bio() wait for the printk to complete. This in itself isn't a disaster, except for the detail that this function is being called with the queue lock held. This causes any other function in the block layer to spin on its spin_lock_irqsave while the serial console is draining. If NMI watchdog is enabled on this machine then it eventually comes along and shoots the machine in the head. The end result is that losing any one disk causes the machine to go down. This patch rate limits the printk to bandaid around the problem. Tested: xfstests Change-Id: I8ab5690dcf4f3a67e78be147d45e489fdf4a88d8 Signed-off-by: Anatol Pomozov Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index d63cc5e9d3b5..6625d210fb45 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "ext4_jbd2.h" #include "xattr.h" @@ -55,7 +56,7 @@ void ext4_exit_pageio(void) static void buffer_io_error(struct buffer_head *bh) { char b[BDEVNAME_SIZE]; - printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", + printk_ratelimited(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); } -- GitLab From 5f17482a3244c07646279d16c0e5b8c0b2b76d0e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 11 Jul 2013 20:09:43 -0700 Subject: [PATCH 2697/2900] ASoC: wm8978: enable symmetric rates wm8978 needs .symmetric_rates = 1. The playback/capture will be strange without this patch when it used asymmetric rate in same time Tested-by: Yusuke Goda Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 029f31c8e703..d8fc531c0e59 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -921,6 +921,7 @@ static struct snd_soc_dai_driver wm8978_dai = { .formats = WM8978_FORMATS, }, .ops = &wm8978_dai_ops, + .symmetric_rates = 1, }; static int wm8978_suspend(struct snd_soc_codec *codec) -- GitLab From 734df5ab549ca44f40de0f07af1c8803856dfb18 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jul 2013 17:44:10 +0200 Subject: [PATCH 2698/2900] perf: Clone child context from parent context pmu Currently when the child context for inherited events is created, it's based on the pmu object of the first event of the parent context. This is wrong for the following scenario: - HW context having HW and SW event - HW event got removed (closed) - SW event stays in HW context as the only event and its pmu is used to clone the child context The issue starts when the cpu context object is touched based on the pmu context object (__get_cpu_context). In this case the HW context will work with SW cpu context ending up with following WARN below. Fixing this by using parent context pmu object to clone from child context. Addresses the following warning reported by Vince Weaver: [ 2716.472065] ------------[ cut here ]------------ [ 2716.476035] WARNING: at kernel/events/core.c:2122 task_ctx_sched_out+0x3c/0x) [ 2716.476035] Modules linked in: nfsd auth_rpcgss oid_registry nfs_acl nfs locn [ 2716.476035] CPU: 0 PID: 3164 Comm: perf_fuzzer Not tainted 3.10.0-rc4 #2 [ 2716.476035] Hardware name: AOpen DE7000/nMCP7ALPx-DE R1.06 Oct.19.2012, BI2 [ 2716.476035] 0000000000000000 ffffffff8102e215 0000000000000000 ffff88011fc18 [ 2716.476035] ffff8801175557f0 0000000000000000 ffff880119fda88c ffffffff810ad [ 2716.476035] ffff880119fda880 ffffffff810af02a 0000000000000009 ffff880117550 [ 2716.476035] Call Trace: [ 2716.476035] [] ? warn_slowpath_common+0x5b/0x70 [ 2716.476035] [] ? task_ctx_sched_out+0x3c/0x5f [ 2716.476035] [] ? perf_event_exit_task+0xbf/0x194 [ 2716.476035] [] ? do_exit+0x3e7/0x90c [ 2716.476035] [] ? __do_fault+0x359/0x394 [ 2716.476035] [] ? do_group_exit+0x66/0x98 [ 2716.476035] [] ? get_signal_to_deliver+0x479/0x4ad [ 2716.476035] [] ? __perf_event_task_sched_out+0x230/0x2d1 [ 2716.476035] [] ? do_signal+0x3c/0x432 [ 2716.476035] [] ? ctx_sched_in+0x43/0x141 [ 2716.476035] [] ? perf_event_context_sched_in+0x7a/0x90 [ 2716.476035] [] ? __perf_event_task_sched_in+0x31/0x118 [ 2716.476035] [] ? mmdrop+0xd/0x1c [ 2716.476035] [] ? finish_task_switch+0x7d/0xa6 [ 2716.476035] [] ? do_notify_resume+0x20/0x5d [ 2716.476035] [] ? retint_signal+0x3d/0x78 [ 2716.476035] ---[ end trace 827178d8a5966c3d ]--- Reported-by: Vince Weaver Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1373384651-6109-1-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 1833bc5a84a7..1d1f030e2f1e 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7465,7 +7465,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent, * child. */ - child_ctx = alloc_perf_context(event->pmu, child); + child_ctx = alloc_perf_context(parent_ctx->pmu, child); if (!child_ctx) return -ENOMEM; -- GitLab From 06f417968beac6e6b614e17b37d347aa6a6b1d30 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jul 2013 17:44:11 +0200 Subject: [PATCH 2699/2900] perf: Remove WARN_ON_ONCE() check in __perf_event_enable() for valid scenario The '!ctx->is_active' check has a valid scenario, so there's no need for the warning. The reason is that there's a time window between the 'ctx->is_active' check in the perf_event_enable() function and the __perf_event_enable() function having: - IRQs on - ctx->lock unlocked where the task could be killed and 'ctx' deactivated by perf_event_exit_task(), ending up with the warning below. So remove the WARN_ON_ONCE() check and add comments to explain it all. This addresses the following warning reported by Vince Weaver: [ 324.983534] ------------[ cut here ]------------ [ 324.984420] WARNING: at kernel/events/core.c:1953 __perf_event_enable+0x187/0x190() [ 324.984420] Modules linked in: [ 324.984420] CPU: 19 PID: 2715 Comm: nmi_bug_snb Not tainted 3.10.0+ #246 [ 324.984420] Hardware name: Supermicro X8DTN/X8DTN, BIOS 4.6.3 01/08/2010 [ 324.984420] 0000000000000009 ffff88043fce3ec8 ffffffff8160ea0b ffff88043fce3f00 [ 324.984420] ffffffff81080ff0 ffff8802314fdc00 ffff880231a8f800 ffff88043fcf7860 [ 324.984420] 0000000000000286 ffff880231a8f800 ffff88043fce3f10 ffffffff8108103a [ 324.984420] Call Trace: [ 324.984420] [] dump_stack+0x19/0x1b [ 324.984420] [] warn_slowpath_common+0x70/0xa0 [ 324.984420] [] warn_slowpath_null+0x1a/0x20 [ 324.984420] [] __perf_event_enable+0x187/0x190 [ 324.984420] [] remote_function+0x40/0x50 [ 324.984420] [] generic_smp_call_function_single_interrupt+0xbe/0x130 [ 324.984420] [] smp_call_function_single_interrupt+0x27/0x40 [ 324.984420] [] call_function_single_interrupt+0x6f/0x80 [ 324.984420] [] ? _raw_spin_unlock_irqrestore+0x41/0x70 [ 324.984420] [] perf_event_exit_task+0x14d/0x210 [ 324.984420] [] ? switch_task_namespaces+0x24/0x60 [ 324.984420] [] do_exit+0x2b6/0xa40 [ 324.984420] [] ? _raw_spin_unlock_irq+0x2c/0x30 [ 324.984420] [] do_group_exit+0x49/0xc0 [ 324.984420] [] get_signal_to_deliver+0x254/0x620 [ 324.984420] [] do_signal+0x57/0x5a0 [ 324.984420] [] ? __do_page_fault+0x2a4/0x4e0 [ 324.984420] [] ? retint_restore_args+0xe/0xe [ 324.984420] [] ? retint_signal+0x11/0x84 [ 324.984420] [] do_notify_resume+0x65/0x80 [ 324.984420] [] retint_signal+0x46/0x84 [ 324.984420] ---[ end trace 442ec2f04db3771a ]--- Reported-by: Vince Weaver Signed-off-by: Jiri Olsa Suggested-by: Peter Zijlstra Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1373384651-6109-2-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 1d1f030e2f1e..ef5e7cc686e3 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1950,7 +1950,16 @@ static int __perf_event_enable(void *info) struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); int err; - if (WARN_ON_ONCE(!ctx->is_active)) + /* + * There's a time window between 'ctx->is_active' check + * in perf_event_enable function and this place having: + * - IRQs on + * - ctx->lock unlocked + * + * where the task could be killed and 'ctx' deactivated + * by perf_event_exit_task. + */ + if (!ctx->is_active) return -EINVAL; raw_spin_lock(&ctx->lock); -- GitLab From 058ebd0eba3aff16b144eabf4510ed9510e1416e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 12 Jul 2013 11:08:33 +0200 Subject: [PATCH 2700/2900] perf: Fix perf_lock_task_context() vs RCU Jiri managed to trigger this warning: [] ====================================================== [] [ INFO: possible circular locking dependency detected ] [] 3.10.0+ #228 Tainted: G W [] ------------------------------------------------------- [] p/6613 is trying to acquire lock: [] (rcu_node_0){..-...}, at: [] rcu_read_unlock_special+0xa7/0x250 [] [] but task is already holding lock: [] (&ctx->lock){-.-...}, at: [] perf_lock_task_context+0xd9/0x2c0 [] [] which lock already depends on the new lock. [] [] the existing dependency chain (in reverse order) is: [] [] -> #4 (&ctx->lock){-.-...}: [] -> #3 (&rq->lock){-.-.-.}: [] -> #2 (&p->pi_lock){-.-.-.}: [] -> #1 (&rnp->nocb_gp_wq[1]){......}: [] -> #0 (rcu_node_0){..-...}: Paul was quick to explain that due to preemptible RCU we cannot call rcu_read_unlock() while holding scheduler (or nested) locks when part of the read side critical section was preemptible. Therefore solve it by making the entire RCU read side non-preemptible. Also pull out the retry from under the non-preempt to play nice with RT. Reported-by: Jiri Olsa Helped-out-by: Paul E. McKenney Cc: Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- kernel/events/core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index ef5e7cc686e3..eba8fb5834ae 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -947,8 +947,18 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) { struct perf_event_context *ctx; - rcu_read_lock(); retry: + /* + * One of the few rules of preemptible RCU is that one cannot do + * rcu_read_unlock() while holding a scheduler (or nested) lock when + * part of the read side critical section was preemptible -- see + * rcu_read_unlock_special(). + * + * Since ctx->lock nests under rq->lock we must ensure the entire read + * side critical section is non-preemptible. + */ + preempt_disable(); + rcu_read_lock(); ctx = rcu_dereference(task->perf_event_ctxp[ctxn]); if (ctx) { /* @@ -964,6 +974,8 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) raw_spin_lock_irqsave(&ctx->lock, *flags); if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) { raw_spin_unlock_irqrestore(&ctx->lock, *flags); + rcu_read_unlock(); + preempt_enable(); goto retry; } @@ -973,6 +985,7 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) } } rcu_read_unlock(); + preempt_enable(); return ctx; } -- GitLab From ff5599816711d2e67da2d7561fd36ac48debd433 Mon Sep 17 00:00:00 2001 From: Xiong Zhou Date: Tue, 9 Jul 2013 11:06:27 +0800 Subject: [PATCH 2701/2900] x86/platform/ce4100: Add header file for reboot type Add header file for reboot type to fix this build failure: error: 'reboot_type' undeclared (first use in this function) error: 'BOOT_KBD' undeclared (first use in this function) Signed-off-by: Xiong Zhou Cc: rui.zhang@intel.com Cc: alan@linux.intel.com Cc: ffainelli@freebox.fr Cc: mbizon@freebox.fr Cc: matthew.garrett@nebula.com Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1307091053280.28371@M2420 Signed-off-by: Ingo Molnar --- arch/x86/platform/ce4100/ce4100.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index f8ab4945892e..9962015a3d55 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include -- GitLab From a272dcca1802a7e265a56e60b0d0a6715b0a8ac2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 11 Jul 2013 07:00:59 -0700 Subject: [PATCH 2702/2900] tick: broadcast: Check broadcast mode on CPU hotplug On ARM systems the dummy clockevent is registered with the cpu hotplug notifier chain before any other per-cpu clockevent. This has the side-effect of causing the dummy clockevent to be registered first in every hotplug sequence. Because the dummy is first, we'll try to turn the broadcast source on but the code in tick_device_uses_broadcast() assumes the broadcast source is in periodic mode and calls tick_broadcast_start_periodic() unconditionally. On boot this isn't a problem because we typically haven't switched into oneshot mode yet (if at all). During hotplug, if the broadcast source isn't in periodic mode we'll replace the broadcast oneshot handler with the broadcast periodic handler and start emulating oneshot mode when we shouldn't. Due to the way the broadcast oneshot handler programs the next_event it's possible for it to contain KTIME_MAX and cause us to hang the system when the periodic handler tries to program the next tick. Fix this by using the appropriate function to start the broadcast source. Reported-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Stephen Boyd Cc: Mark Rutland Cc: Marc Zyngier Cc: ARM kernel mailing list Cc: John Stultz Cc: Joseph Lo Link: http://lkml.kernel.org/r/20130711140059.GA27430@codeaurora.org Signed-off-by: Thomas Gleixner --- kernel/time/tick-broadcast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 6d3f91631de6..218bcb565fed 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -157,7 +157,10 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) dev->event_handler = tick_handle_periodic; tick_device_setup_broadcast_func(dev); cpumask_set_cpu(cpu, tick_broadcast_mask); - tick_broadcast_start_periodic(bc); + if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) + tick_broadcast_start_periodic(bc); + else + tick_broadcast_setup_oneshot(bc); ret = 1; } else { /* -- GitLab From 971ee28cbd1ccd87b3164facd9359a534c1d2892 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 28 Jun 2013 11:18:53 +0200 Subject: [PATCH 2703/2900] sched: Fix HRTICK David reported that the HRTICK sched feature was borken; which was enough motivation for me to finally fix it ;-) We should not allow hrtimer code to do softirq wakeups while holding scheduler locks. The hrtimer code only needs this when we accidentally try to program an expired time. We don't much care about those anyway since we have the regular tick to fall back to. Reported-by: David Ahern Tested-by: David Ahern Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20130628091853.GE29209@dyad.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9b1f2e533b95..0d8eb4525e76 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -370,13 +370,6 @@ static struct rq *this_rq_lock(void) #ifdef CONFIG_SCHED_HRTICK /* * Use HR-timers to deliver accurate preemption points. - * - * Its all a bit involved since we cannot program an hrt while holding the - * rq->lock. So what we do is store a state in in rq->hrtick_* and ask for a - * reschedule event. - * - * When we get rescheduled we reprogram the hrtick_timer outside of the - * rq->lock. */ static void hrtick_clear(struct rq *rq) @@ -404,6 +397,15 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer) } #ifdef CONFIG_SMP + +static int __hrtick_restart(struct rq *rq) +{ + struct hrtimer *timer = &rq->hrtick_timer; + ktime_t time = hrtimer_get_softexpires(timer); + + return __hrtimer_start_range_ns(timer, time, 0, HRTIMER_MODE_ABS_PINNED, 0); +} + /* * called from hardirq (IPI) context */ @@ -412,7 +414,7 @@ static void __hrtick_start(void *arg) struct rq *rq = arg; raw_spin_lock(&rq->lock); - hrtimer_restart(&rq->hrtick_timer); + __hrtick_restart(rq); rq->hrtick_csd_pending = 0; raw_spin_unlock(&rq->lock); } @@ -430,7 +432,7 @@ void hrtick_start(struct rq *rq, u64 delay) hrtimer_set_expires(timer, time); if (rq == this_rq()) { - hrtimer_restart(timer); + __hrtick_restart(rq); } else if (!rq->hrtick_csd_pending) { __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 0); rq->hrtick_csd_pending = 1; -- GitLab From baf64b85445546a38b44052d71782dfe7531e350 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Mon, 8 Jul 2013 14:44:04 -0700 Subject: [PATCH 2704/2900] perf/x86: Fix incorrect use of do_div() in NMI warning I completely botched understanding the calling conventions of do_div(). I assumed that do_div() returned the result instead of realizing that it modifies its argument and returns a remainder. The side-effect from this would be bogus numbers for the "msecs" value in the warning messages: INFO: NMI handler (perf_event_nmi_handler) took too long to run: 0.114 msecs Note, there was a second fix posted by Stephane Eranian for a separate patch which I also botched: http://lkml.kernel.org/r/20130704223010.GA30625@quad Signed-off-by: Dave Hansen Cc: Dave Hansen Link: http://lkml.kernel.org/r/20130708214404.B0B6EA66@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/nmi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 0920212e6159..ba77ebc2c353 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -111,7 +111,7 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2 */ list_for_each_entry_rcu(a, &desc->head, list) { u64 before, delta, whole_msecs; - int decimal_msecs, thishandled; + int remainder_ns, decimal_msecs, thishandled; before = local_clock(); thishandled = a->handler(type, regs); @@ -123,8 +123,9 @@ static int __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2 continue; nmi_longest_ns = delta; - whole_msecs = do_div(delta, (1000 * 1000)); - decimal_msecs = do_div(delta, 1000) % 1000; + whole_msecs = delta; + remainder_ns = do_div(whole_msecs, (1000 * 1000)); + decimal_msecs = remainder_ns / 1000; printk_ratelimited(KERN_INFO "INFO: NMI handler (%ps) took too long to run: " "%lld.%03d msecs\n", a->handler, whole_msecs, -- GitLab From 1157d73d07b6143cbe49145ef917d52abbe531f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Stehl=C3=A9?= Date: Wed, 3 Jul 2013 10:12:58 +0200 Subject: [PATCH 2705/2900] arm: multi_v7_defconfig: add i.MX options and NFS root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add i.MX serial console support. This gives us the boot messages on UART on e.g. the i.MX6Q sabre sd platform. - Add the necessary config options, to allow booting with NFS root on an i.MX6 sabre sd. - Add Freescale LPUART serial console support. This gives us the boot messages on UART on e.g. the Vybrid VF610 Tower board. Signed-off-by: Vincent Stehlé Cc: Russell King [olof: squashed three commits down to one] Signed-off-by: Olof Johansson --- arch/arm/configs/multi_v7_defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 6d8d3c456b5f..80aacc6d3b48 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -47,6 +47,8 @@ CONFIG_ARM_APPENDED_DTB=y CONFIG_NET=y CONFIG_UNIX=y CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_BLK_DEV_SD=y @@ -75,6 +77,10 @@ CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y CONFIG_I2C_SIRF=y CONFIG_I2C_TEGRA=y @@ -147,6 +153,10 @@ CONFIG_PWM=y CONFIG_PWM_VT8500=y CONFIG_EXT4_FS=y CONFIG_TMPFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y CONFIG_PRINTK_TIME=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y -- GitLab From 35f7a14fc1180164d6358a5885031fc187ef1bfa Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 8 Jul 2013 19:51:44 -0400 Subject: [PATCH 2706/2900] nfsd4: fix minorversion support interface You can turn on or off support for minorversions using e.g. echo "-4.2" >/proc/fs/nfsd/versions However, the current implementation is a little wonky. For example, the above will turn off 4.2 support, but it will also turn *on* 4.1 support. This didn't matter as long as we only had 2 minorversions, which was true till very recently. And do a little cleanup here. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfsd.h | 1 - fs/nfsd/nfssvc.c | 13 +++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a7cee864e7b2..0d4c410e4589 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1293,7 +1293,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, * According to RFC3010, this takes precedence over all other errors. */ status = nfserr_minor_vers_mismatch; - if (args->minorversion > nfsd_supported_minorversion) + if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) goto out; status = nfs41_check_op_ordering(args); diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 2bbd94e51efc..30f34ab02137 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -53,7 +53,6 @@ struct readdir_cd { extern struct svc_program nfsd_program; extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; -extern u32 nfsd_supported_minorversion; extern struct mutex nfsd_mutex; extern spinlock_t nfsd_drc_lock; extern unsigned long nfsd_drc_max_mem; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 6b9f48ca4c25..760c85a6f534 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -116,7 +116,10 @@ struct svc_program nfsd_program = { }; -u32 nfsd_supported_minorversion = 1; +static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = { + [0] = 1, + [1] = 1, +}; int nfsd_vers(int vers, enum vers_op change) { @@ -151,15 +154,13 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change) return -1; switch(change) { case NFSD_SET: - nfsd_supported_minorversion = minorversion; + nfsd_supported_minorversions[minorversion] = true; break; case NFSD_CLEAR: - if (minorversion == 0) - return -1; - nfsd_supported_minorversion = minorversion - 1; + nfsd_supported_minorversions[minorversion] = false; break; case NFSD_TEST: - return minorversion <= nfsd_supported_minorversion; + return nfsd_supported_minorversions[minorversion]; case NFSD_AVAIL: return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; } -- GitLab From 92338dc2fb33c8526256a458a520af73d9ab2d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CCosmin?= Date: Fri, 12 Jul 2013 09:33:33 +0300 Subject: [PATCH 2707/2900] net: strict_strtoul is obsolete, use kstrtoul instead patch found using checkpatch.pl Signed-off-by: Cosmin Stanescu Signed-off-by: David S. Miller --- net/dns_resolver/dns_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 0a69d0757795..f347a2ca7d7e 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -118,7 +118,7 @@ dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) if (opt_vlen <= 0) goto bad_option_value; - ret = strict_strtoul(eq, 10, &derrno); + ret = kstrtoul(eq, 10, &derrno); if (ret < 0) goto bad_option_value; -- GitLab From 40dadff26539d1695d2a37b44f66c53158439ae9 Mon Sep 17 00:00:00 2001 From: Sunghan Suh Date: Fri, 12 Jul 2013 16:17:23 +0900 Subject: [PATCH 2708/2900] net: access page->private by using page_private Signed-off-by: Sunghan Suh Signed-off-by: David S. Miller --- net/core/skbuff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 724bb7cb173f..20e02d2605ec 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -824,7 +824,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) page = alloc_page(gfp_mask); if (!page) { while (head) { - struct page *next = (struct page *)head->private; + struct page *next = (struct page *)page_private(head); put_page(head); head = next; } @@ -834,7 +834,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) memcpy(page_address(page), vaddr + f->page_offset, skb_frag_size(f)); kunmap_atomic(vaddr); - page->private = (unsigned long)head; + set_page_private(page, (unsigned long)head); head = page; } @@ -848,7 +848,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) for (i = num_frags - 1; i >= 0; i--) { __skb_fill_page_desc(skb, i, head, 0, skb_shinfo(skb)->frags[i].size); - head = (struct page *)head->private; + head = (struct page *)page_private(head); } skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; -- GitLab From 3ff25e3c4531aff5b1a96e2ea6e1a2d355263019 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Fri, 12 Jul 2013 16:26:15 +0800 Subject: [PATCH 2709/2900] usb/net/r8152: fix integer overflow in expression config: make ARCH=avr32 allyesconfig drivers/net/usb/r8152.c: In function 'rtl8152_start_xmit': drivers/net/usb/r8152.c:956: warning: integer overflow in expression 955 memset(tx_desc, 0, sizeof(*tx_desc)); > 956 tx_desc->opts1 = cpu_to_le32((len & TX_LEN_MASK) | TX_FS | TX_LS); 957 tp->tx_skb = skb; Signed-off-by: Hayes Wang Spotted-by: kbuild test robot Signed-off-by: David S. Miller --- drivers/net/usb/r8152.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index d02bac82fc57..ee13f9eb740c 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -934,7 +934,8 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, struct r8152 *tp = netdev_priv(netdev); struct net_device_stats *stats = rtl8152_get_stats(netdev); struct tx_desc *tx_desc; - int len, res; + unsigned int len; + int res; netif_stop_queue(netdev); len = skb->len; -- GitLab From e76385240ee5c812267319c9084e5a0d62bfbf90 Mon Sep 17 00:00:00 2001 From: hayeswang Date: Fri, 12 Jul 2013 16:26:16 +0800 Subject: [PATCH 2710/2900] usb/net/r815x: fix cast to restricted __le32 >> drivers/net/usb/r815x.c:38:16: sparse: cast to restricted __le32 >> drivers/net/usb/r815x.c:67:15: sparse: cast to restricted __le32 >> drivers/net/usb/r815x.c:69:13: sparse: incorrect type in assignment (different base types) drivers/net/usb/r815x.c:69:13: expected unsigned int [unsigned] [addressable] [assigned] [usertype] tmp drivers/net/usb/r815x.c:69:13: got restricted __le32 [usertype] Signed-off-by: Hayes Wang Spotted-by: kbuild test robot Signed-off-by: David S. Miller --- drivers/net/usb/r815x.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/r815x.c b/drivers/net/usb/r815x.c index 65167377ff09..852392269718 100644 --- a/drivers/net/usb/r815x.c +++ b/drivers/net/usb/r815x.c @@ -26,16 +26,18 @@ static int pla_read_word(struct usb_device *udev, u16 index) { int data, ret; u8 shift = index & 2; + __le32 ocp_data; index &= ~3; ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, - index, MCU_TYPE_PLA, &data, sizeof(data), 500); + index, MCU_TYPE_PLA, &ocp_data, sizeof(ocp_data), + 500); if (ret < 0) return ret; - data = __le32_to_cpu(data); + data = __le32_to_cpu(ocp_data); data >>= (shift * 8); data &= 0xffff; @@ -44,7 +46,8 @@ static int pla_read_word(struct usb_device *udev, u16 index) static int pla_write_word(struct usb_device *udev, u16 index, u32 data) { - u32 tmp, mask = 0xffff; + __le32 ocp_data; + u32 mask = 0xffff; u16 byen = BYTE_EN_WORD; u8 shift = index & 2; int ret; @@ -60,18 +63,18 @@ static int pla_write_word(struct usb_device *udev, u16 index, u32 data) ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), RTL815x_REQ_GET_REGS, RTL815x_REQT_READ, - index, MCU_TYPE_PLA, &tmp, sizeof(tmp), 500); + index, MCU_TYPE_PLA, &ocp_data, sizeof(ocp_data), + 500); if (ret < 0) return ret; - tmp = __le32_to_cpu(tmp) & ~mask; - tmp |= data; - tmp = __cpu_to_le32(tmp); + data |= __le32_to_cpu(ocp_data) & ~mask; + ocp_data = __cpu_to_le32(data); ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), RTL815x_REQ_SET_REGS, RTL815x_REQT_WRITE, - index, MCU_TYPE_PLA | byen, &tmp, - sizeof(tmp), 500); + index, MCU_TYPE_PLA | byen, &ocp_data, + sizeof(ocp_data), 500); return ret; } -- GitLab From 24ab6bec80861d0c55263047e8bf97e460a32e7b Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Fri, 12 Jul 2013 11:33:04 -0700 Subject: [PATCH 2711/2900] tcp: account all retransmit failures Change snmp RETRANSFAILS stat to include timeout retransmit failures in addition to other loss recoveries. Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_output.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3d609490f118..92fde8d1aa82 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2407,6 +2407,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) * see tcp_input.c tcp_sacktag_write_queue(). */ TCP_SKB_CB(skb)->ack_seq = tp->snd_nxt; + } else { + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); } return err; } @@ -2528,10 +2530,9 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS)) continue; - if (tcp_retransmit_skb(sk, skb)) { - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); + if (tcp_retransmit_skb(sk, skb)) return; - } + NET_INC_STATS_BH(sock_net(sk), mib_idx); if (tcp_in_cwnd_reduction(sk)) -- GitLab From 352900b583b2852152a1e05ea0e8b579292e731e Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 12 Jul 2013 10:58:48 -0400 Subject: [PATCH 2712/2900] atl1e: fix dma mapping warnings Recently had this backtrace reported: WARNING: at lib/dma-debug.c:937 check_unmap+0x47d/0x930() Hardware name: System Product Name ATL1E 0000:02:00.0: DMA-API: device driver failed to check map error[device address=0x00000000cbfd1000] [size=90 bytes] [mapped as single] Modules linked in: xt_conntrack nf_conntrack ebtable_filter ebtables ip6table_filter ip6_tables snd_hda_codec_hdmi snd_hda_codec_realtek iTCO_wdt iTCO_vendor_support snd_hda_intel acpi_cpufreq mperf coretemp btrfs zlib_deflate snd_hda_codec snd_hwdep microcode raid6_pq libcrc32c snd_seq usblp serio_raw xor snd_seq_device joydev snd_pcm snd_page_alloc snd_timer snd lpc_ich i2c_i801 soundcore mfd_core atl1e asus_atk0110 ata_generic pata_acpi radeon i2c_algo_bit drm_kms_helper ttm drm i2c_core pata_marvell uinput Pid: 314, comm: systemd-journal Not tainted 3.9.0-0.rc6.git2.3.fc19.x86_64 #1 Call Trace: [] warn_slowpath_common+0x66/0x80 [] warn_slowpath_fmt+0x4c/0x50 [] check_unmap+0x47d/0x930 [] ? sched_clock_cpu+0xa8/0x100 [] debug_dma_unmap_page+0x5f/0x70 [] ? unmap_single+0x20/0x30 [] atl1e_intr+0x3a1/0x5b0 [atl1e] [] ? trace_hardirqs_off+0xd/0x10 [] handle_irq_event_percpu+0x56/0x390 [] handle_irq_event+0x3d/0x60 [] handle_fasteoi_irq+0x5a/0x100 [] handle_irq+0xbf/0x150 [] ? file_sb_list_del+0x3f/0x50 [] ? irq_enter+0x50/0xa0 [] do_IRQ+0x4d/0xc0 [] ? file_sb_list_del+0x3f/0x50 [] common_interrupt+0x72/0x72 [] ? lock_release+0xc2/0x310 [] lg_local_unlock_cpu+0x24/0x50 [] file_sb_list_del+0x3f/0x50 [] fput+0x2d/0xc0 [] filp_close+0x61/0x90 [] __close_fd+0x8d/0x150 [] sys_close+0x20/0x50 [] system_call_fastpath+0x16/0x1b The usual straighforward failure to check for dma_mapping_error after a map operation is completed. This patch should fix it, the reporter wandered off after filing this bz: https://bugzilla.redhat.com/show_bug.cgi?id=954170 and I don't have hardware to test, but the fix is pretty straightforward, so I figured I'd post it for review. Signed-off-by: Neil Horman CC: Jay Cliburn CC: Chris Snook CC: "David S. Miller" Signed-off-by: David S. Miller --- .../net/ethernet/atheros/atl1e/atl1e_main.c | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 895f5377ad1b..6d1a62a84c9d 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1665,8 +1665,8 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, return 0; } -static void atl1e_tx_map(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) +static int atl1e_tx_map(struct atl1e_adapter *adapter, + struct sk_buff *skb, struct atl1e_tpd_desc *tpd) { struct atl1e_tpd_desc *use_tpd = NULL; struct atl1e_tx_buffer *tx_buffer = NULL; @@ -1677,6 +1677,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, u16 nr_frags; u16 f; int segment; + int ring_start = adapter->tx_ring.next_to_use; nr_frags = skb_shinfo(skb)->nr_frags; segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; @@ -1689,6 +1690,9 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->length = map_len; tx_buffer->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) + return -ENOSPC; + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); @@ -1715,6 +1719,13 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->dma = pci_map_single(adapter->pdev, skb->data + mapped_len, map_len, PCI_DMA_TODEVICE); + + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* Reset the tx rings next pointer */ + adapter->tx_ring.next_to_use = ring_start; + return -ENOSPC; + } + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); @@ -1750,6 +1761,13 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, (i * MAX_TX_BUF_LEN), tx_buffer->length, DMA_TO_DEVICE); + + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* Reset the ring next to use pointer */ + adapter->tx_ring.next_to_use = ring_start; + return -ENOSPC; + } + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | @@ -1767,6 +1785,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, /* The last buffer info contain the skb address, so it will be free after unmap */ tx_buffer->skb = skb; + return 0; } static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count, @@ -1834,10 +1853,13 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } - atl1e_tx_map(adapter, skb, tpd); + if (atl1e_tx_map(adapter, skb, tpd)) + goto out; + atl1e_tx_queue(adapter, tpd_req, tpd); netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ +out: spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } -- GitLab From 9b4fe5fb0bdd8f31f24cbfe77e38ec8155c250c5 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 12 Jul 2013 13:35:33 -0400 Subject: [PATCH 2713/2900] via-rhine: fix dma mapping errors this bug: https://bugzilla.redhat.com/show_bug.cgi?id=951695 Reported a dma debug backtrace: WARNING: at lib/dma-debug.c:937 check_unmap+0x47d/0x930() Hardware name: To Be Filled By O.E.M. via-rhine 0000:00:12.0: DMA-API: device driver failed to check map error[device address=0x0000000075a837b2] [size=90 bytes] [mapped as single] Modules linked in: ip6_tables gspca_spca561 gspca_main videodev media snd_hda_codec_realtek snd_hda_intel i2c_viapro snd_hda_codec snd_hwdep snd_seq ppdev mperf via_rhine coretemp snd_pcm mii microcode snd_page_alloc snd_timer snd_mpu401 snd_mpu401_uart snd_rawmidi snd_seq_device snd soundcore parport_pc parport shpchp ata_generic pata_acpi radeon i2c_algo_bit drm_kms_helper ttm drm pata_via sata_via i2c_core uinput Pid: 295, comm: systemd-journal Not tainted 3.9.0-0.rc6.git2.1.fc20.x86_64 #1 Call Trace: [] warn_slowpath_common+0x70/0xa0 [] warn_slowpath_fmt+0x4c/0x50 [] check_unmap+0x47d/0x930 [] ? local_clock+0x5f/0x70 [] debug_dma_unmap_page+0x5f/0x70 [] ? rhine_ack_events.isra.14+0x3c/0x50 [via_rhine] [] rhine_napipoll+0x1d8/0xd80 [via_rhine] [] ? net_rx_action+0xa1/0x380 [] net_rx_action+0x172/0x380 [] __do_softirq+0xff/0x400 [] irq_exit+0xb5/0xc0 [] do_IRQ+0x56/0xc0 [] common_interrupt+0x72/0x72 [] ? __slab_alloc+0x4c2/0x526 [] ? mmap_region+0x2b0/0x5a0 [] ? __lock_is_held+0x57/0x80 [] ? mmap_region+0x2b0/0x5a0 [] kmem_cache_alloc+0x2df/0x360 [] mmap_region+0x2b0/0x5a0 [] do_mmap_pgoff+0x316/0x3d0 [] vm_mmap_pgoff+0x90/0xc0 [] sys_mmap_pgoff+0x4c/0x190 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] sys_mmap+0x22/0x30 [] system_call_fastpath+0x16/0x1b Usual problem with the usual fix, add the appropriate calls to dma_mapping_error where appropriate Untested, as I don't have hardware, but its pretty straightforward Signed-off-by: Neil Horman CC: David S. Miller CC: Roger Luethi Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-rhine.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index ca98acabf1b4..b75eb9e0e867 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1171,7 +1171,11 @@ static void alloc_rbufs(struct net_device *dev) rp->rx_skbuff_dma[i] = pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, PCI_DMA_FROMDEVICE); - + if (dma_mapping_error(&rp->pdev->dev, rp->rx_skbuff_dma[i])) { + rp->rx_skbuff_dma[i] = 0; + dev_kfree_skb(skb); + break; + } rp->rx_ring[i].addr = cpu_to_le32(rp->rx_skbuff_dma[i]); rp->rx_ring[i].rx_status = cpu_to_le32(DescOwn); } @@ -1687,6 +1691,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, rp->tx_skbuff_dma[entry] = pci_map_single(rp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&rp->pdev->dev, rp->tx_skbuff_dma[entry])) { + dev_kfree_skb(skb); + rp->tx_skbuff_dma[entry] = 0; + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_skbuff_dma[entry]); } @@ -1961,6 +1971,11 @@ static int rhine_rx(struct net_device *dev, int limit) pci_map_single(rp->pdev, skb->data, rp->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&rp->pdev->dev, rp->rx_skbuff_dma[entry])) { + dev_kfree_skb(skb); + rp->rx_skbuff_dma[entry] = 0; + break; + } rp->rx_ring[entry].addr = cpu_to_le32(rp->rx_skbuff_dma[entry]); } rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); -- GitLab From 307f2fb95e9b96b3577916e73d92e104f8f26494 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Fri, 12 Jul 2013 23:46:33 +0200 Subject: [PATCH 2714/2900] ipv6: only static routes qualify for equal cost multipathing Static routes in this case are non-expiring routes which did not get configured by autoconf or by icmpv6 redirects. To make sure we actually get an ecmp route while searching for the first one in this fib6_node's leafs, also make sure it matches the ecmp route assumptions. v2: a) Removed RTF_EXPIRE check in dst.from chain. The check of RTF_ADDRCONF already ensures that this route, even if added again without RTF_EXPIRES (in case of a RA announcement with infinite timeout), does not cause the rt6i_nsiblings logic to go wrong if a later RA updates the expiration time later. v3: a) Allow RTF_EXPIRES routes to enter the ecmp route set. We have to do so, because an pmtu event could update the RTF_EXPIRES flag and we would not count this route, if another route joins this set. We now filter only for RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC, which are flags that don't get changed after rt6_info construction. Cc: Nicolas Dichtel Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 192dd1a0e188..5fc9c7a68d8d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -632,6 +632,12 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, return ln; } +static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) +{ + return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) == + RTF_GATEWAY; +} + /* * Insert routing information in a node. */ @@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, int add = (!info->nlh || (info->nlh->nlmsg_flags & NLM_F_CREATE)); int found = 0; + bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); ins = &fn->leaf; @@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, * To avoid long list, we only had siblings if the * route have a gateway. */ - if (rt->rt6i_flags & RTF_GATEWAY && - !(rt->rt6i_flags & RTF_EXPIRES) && - !(iter->rt6i_flags & RTF_EXPIRES)) + if (rt_can_ecmp && + rt6_qualify_for_ecmp(iter)) rt->rt6i_nsiblings++; } @@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, /* Find the first route that have the same metric */ sibling = fn->leaf; while (sibling) { - if (sibling->rt6i_metric == rt->rt6i_metric) { + if (sibling->rt6i_metric == rt->rt6i_metric && + rt6_qualify_for_ecmp(sibling)) { list_add_tail(&rt->rt6i_siblings, &sibling->rt6i_siblings); break; -- GitLab From bdafe42aaf72859166f784f0fad3e6b4a815fa6d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 13 Jul 2013 00:40:31 -0400 Subject: [PATCH 2715/2900] ext4: fix spelling errors and a comment in extent_status tree Replace "assertation" with "assertion" in lots and lots of debugging messages. Correct the comment stating when ext4_es_insert_extent() is used. It was no doubt tree at one point, but it is no longer true... Signed-off-by: "Theodore Ts'o" Cc: Zheng Liu --- fs/ext4/extents_status.c | 22 ++++++++++------------ fs/ext4/inode.c | 8 ++++---- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index ee018d5f397e..4b8df7fbb10a 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -439,7 +439,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, */ if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) { if (in_range(es->es_lblk, ee_block, ee_len)) { - pr_warn("ES insert assertation failed for " + pr_warn("ES insert assertion failed for " "inode: %lu we can find an extent " "at block [%d/%d/%llu/%c], but we " "want to add an delayed/hole extent " @@ -458,7 +458,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, */ if (es->es_lblk < ee_block || ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) { - pr_warn("ES insert assertation failed for inode: %lu " + pr_warn("ES insert assertion failed for inode: %lu " "ex_status [%d/%d/%llu/%c] != " "es_status [%d/%d/%llu/%c]\n", inode->i_ino, ee_block, ee_len, ee_start, @@ -468,7 +468,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, } if (ee_status ^ es_status) { - pr_warn("ES insert assertation failed for inode: %lu " + pr_warn("ES insert assertion failed for inode: %lu " "ex_status [%d/%d/%llu/%c] != " "es_status [%d/%d/%llu/%c]\n", inode->i_ino, ee_block, ee_len, ee_start, @@ -481,7 +481,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode, * that we don't want to add an written/unwritten extent. */ if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) { - pr_warn("ES insert assertation failed for inode: %lu " + pr_warn("ES insert assertion failed for inode: %lu " "can't find an extent at block %d but we want " "to add an written/unwritten extent " "[%d/%d/%llu/%llx]\n", inode->i_ino, @@ -519,7 +519,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, * We want to add a delayed/hole extent but this * block has been allocated. */ - pr_warn("ES insert assertation failed for inode: %lu " + pr_warn("ES insert assertion failed for inode: %lu " "We can find blocks but we want to add a " "delayed/hole extent [%d/%d/%llu/%llx]\n", inode->i_ino, es->es_lblk, es->es_len, @@ -527,13 +527,13 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, return; } else if (ext4_es_is_written(es)) { if (retval != es->es_len) { - pr_warn("ES insert assertation failed for " + pr_warn("ES insert assertion failed for " "inode: %lu retval %d != es_len %d\n", inode->i_ino, retval, es->es_len); return; } if (map.m_pblk != ext4_es_pblock(es)) { - pr_warn("ES insert assertation failed for " + pr_warn("ES insert assertion failed for " "inode: %lu m_pblk %llu != " "es_pblk %llu\n", inode->i_ino, map.m_pblk, @@ -549,7 +549,7 @@ static void ext4_es_insert_extent_ind_check(struct inode *inode, } } else if (retval == 0) { if (ext4_es_is_written(es)) { - pr_warn("ES insert assertation failed for inode: %lu " + pr_warn("ES insert assertion failed for inode: %lu " "We can't find the block but we want to add " "an written extent [%d/%d/%llu/%llx]\n", inode->i_ino, es->es_lblk, es->es_len, @@ -632,10 +632,8 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes) } /* - * ext4_es_insert_extent() adds a space to a extent status tree. - * - * ext4_es_insert_extent is called by ext4_da_write_begin and - * ext4_es_remove_extent. + * ext4_es_insert_extent() adds information to an inode's extent + * status tree. * * Return 0 on success, error code on failure. */ diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 19a1643cbdfa..98b9bff92a8a 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -465,7 +465,7 @@ static void ext4_map_blocks_es_recheck(handle_t *handle, if (es_map->m_lblk != map->m_lblk || es_map->m_flags != map->m_flags || es_map->m_pblk != map->m_pblk) { - printk("ES cache assertation failed for inode: %lu " + printk("ES cache assertion failed for inode: %lu " "es_cached ex [%d/%d/%llu/%x] != " "found ex [%d/%d/%llu/%x] retval %d flags %x\n", inode->i_ino, es_map->m_lblk, es_map->m_len, @@ -558,7 +558,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, #ifdef ES_AGGRESSIVE_TEST if (retval != map->m_len) { - printk("ES len assertation failed for inode: %lu " + printk("ES len assertion failed for inode: %lu " "retval %d != map->m_len %d " "in %s (lookup)\n", inode->i_ino, retval, map->m_len, __func__); @@ -659,7 +659,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, #ifdef ES_AGGRESSIVE_TEST if (retval != map->m_len) { - printk("ES len assertation failed for inode: %lu " + printk("ES len assertion failed for inode: %lu " "retval %d != map->m_len %d " "in %s (allocation)\n", inode->i_ino, retval, map->m_len, __func__); @@ -1642,7 +1642,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, #ifdef ES_AGGRESSIVE_TEST if (retval != map->m_len) { - printk("ES len assertation failed for inode: %lu " + printk("ES len assertion failed for inode: %lu " "retval %d != map->m_len %d " "in %s (lookup)\n", inode->i_ino, retval, map->m_len, __func__); -- GitLab From e7676a704ee0a1ef71a6b23760b5a8f6896cb1a1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 13 Jul 2013 00:40:35 -0400 Subject: [PATCH 2716/2900] ext4: don't allow ext4_free_blocks() to fail due to ENOMEM The filesystem should not be marked inconsistent if ext4_free_blocks() is not able to allocate memory. Unfortunately some callers (most notably ext4_truncate) don't have a way to reflect an error back up to the VFS. And even if we did, most userspace applications won't deal with most system calls returning ENOMEM anyway. Reported-by: Nagachandra P Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/mballoc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index a9ff5e5137ca..4bbbf13bd743 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4740,11 +4740,16 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * blocks being freed are metadata. these blocks shouldn't * be used until this transaction is committed */ + retry: new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); if (!new_entry) { - ext4_mb_unload_buddy(&e4b); - err = -ENOMEM; - goto error_return; + /* + * We use a retry loop because + * ext4_free_blocks() is not allowed to fail. + */ + cond_resched(); + congestion_wait(BLK_RW_ASYNC, HZ/50); + goto retry; } new_entry->efd_start_cluster = bit; new_entry->efd_group = block_group; -- GitLab From d4e1c7ef46e9b02dbf691da0c84d653f88670213 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 12 Jul 2013 20:00:20 -0700 Subject: [PATCH 2717/2900] arm: multi_v7_defconfig: Tweaks for omap and sunxi OMAP recently changed how the platforms are configured, so OMAP2/3/4 SoC support is no longer enabled by default. Add them back. Enable new ethernet driver for sunxi. The i.MX console options moved due to resorting, no functional change. Signed-off-by: Olof Johansson --- arch/arm/configs/multi_v7_defconfig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 80aacc6d3b48..fe0bdc361d2c 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -15,8 +15,10 @@ CONFIG_SOC_IMX53=y CONFIG_SOC_IMX6Q=y CONFIG_SOC_IMX6SL=y CONFIG_SOC_VF610=y -CONFIG_ARCH_OMAP2PLUS=y +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP4=y CONFIG_SOC_OMAP5=y +CONFIG_SOC_AM33XX=y CONFIG_SOC_AM43XX=y CONFIG_ARCH_ROCKCHIP=y CONFIG_ARCH_SOCFPGA=y @@ -57,9 +59,11 @@ CONFIG_SATA_AHCI_PLATFORM=y CONFIG_SATA_HIGHBANK=y CONFIG_SATA_MV=y CONFIG_NETDEVICES=y +CONFIG_SUN4I_EMAC=y CONFIG_NET_CALXEDA_XGMAC=y CONFIG_SMSC911X=y CONFIG_STMMAC_ETH=y +CONFIG_MDIO_SUN4I=y CONFIG_KEYBOARD_SPEAR=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y @@ -70,6 +74,8 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_SIRFSOC=y CONFIG_SERIAL_SIRFSOC_CONSOLE=y CONFIG_SERIAL_TEGRA=y +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y CONFIG_SERIAL_VT8500=y CONFIG_SERIAL_VT8500_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y @@ -77,8 +83,6 @@ CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_SERIAL_XILINX_PS_UART=y CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y CONFIG_SERIAL_FSL_LPUART=y CONFIG_SERIAL_FSL_LPUART_CONSOLE=y CONFIG_I2C_DESIGNWARE_PLATFORM=y -- GitLab From bb458c644a59dbba3a1fe59b27106c5e68e1c4bd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 13 Jul 2013 13:26:37 +0400 Subject: [PATCH 2718/2900] Safer ABI for O_TMPFILE [suggested by Rasmus Villemoes] make O_DIRECTORY | O_RDWR part of O_TMPFILE; that will fail on old kernels in a lot more cases than what I came up with. And make sure O_CREAT doesn't get there... Signed-off-by: Al Viro --- arch/alpha/include/uapi/asm/fcntl.h | 2 +- arch/parisc/include/uapi/asm/fcntl.h | 2 +- arch/sparc/include/uapi/asm/fcntl.h | 2 +- fs/namei.c | 2 +- fs/open.c | 4 ++-- include/uapi/asm-generic/fcntl.h | 8 ++++++-- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h index dfdadb0b4bef..09f49a6b87d1 100644 --- a/arch/alpha/include/uapi/asm/fcntl.h +++ b/arch/alpha/include/uapi/asm/fcntl.h @@ -32,7 +32,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 040000000 -#define O_TMPFILE 0100000000 +#define __O_TMPFILE 0100000000 #define F_GETLK 7 #define F_SETLK 8 diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index cc61c475f277..34a46cbc76ed 100644 --- a/arch/parisc/include/uapi/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h @@ -20,7 +20,7 @@ #define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ #define O_PATH 020000000 -#define O_TMPFILE 040000000 +#define __O_TMPFILE 040000000 #define F_GETLK64 8 #define F_SETLK64 9 diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h index d73e5e008b0d..7e8ace5bf760 100644 --- a/arch/sparc/include/uapi/asm/fcntl.h +++ b/arch/sparc/include/uapi/asm/fcntl.h @@ -35,7 +35,7 @@ #define O_SYNC (__O_SYNC|O_DSYNC) #define O_PATH 0x1000000 -#define O_TMPFILE 0x2000000 +#define __O_TMPFILE 0x2000000 #define F_GETOWN 5 /* for sockets. */ #define F_SETOWN 6 /* for sockets. */ diff --git a/fs/namei.c b/fs/namei.c index b2beee7a733f..8b61d103a8a7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2977,7 +2977,7 @@ static struct file *path_openat(int dfd, struct filename *pathname, file->f_flags = op->open_flag; - if (unlikely(file->f_flags & O_TMPFILE)) { + if (unlikely(file->f_flags & __O_TMPFILE)) { error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened); goto out; } diff --git a/fs/open.c b/fs/open.c index fca72c4d3f17..9156cb050d08 100644 --- a/fs/open.c +++ b/fs/open.c @@ -840,8 +840,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o if (flags & __O_SYNC) flags |= O_DSYNC; - if (flags & O_TMPFILE) { - if (!(flags & O_CREAT)) + if (flags & __O_TMPFILE) { + if ((flags & O_TMPFILE_MASK) != O_TMPFILE) return -EINVAL; acc_mode = MAY_OPEN | ACC_MODE(flags); } else if (flags & O_PATH) { diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index 06632beaa6d5..05ac354e124d 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -84,10 +84,14 @@ #define O_PATH 010000000 #endif -#ifndef O_TMPFILE -#define O_TMPFILE 020000000 +#ifndef __O_TMPFILE +#define __O_TMPFILE 020000000 #endif +/* a horrid kludge trying to make sure that this will fail on old kernels */ +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY | O_RDWR) +#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT | O_ACCMODE) + #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK #endif -- GitLab From 64372501e2af9b11e2ffd1ff79345dc4b1abe539 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 8 Jul 2013 14:24:15 -0700 Subject: [PATCH 2719/2900] fs/file_table.c:fput(): add comment A missed update to "fput: task_work_add() can fail if the caller has passed exit_task_work()". Cc: "Eric W. Biederman" Cc: Al Viro Cc: Andrey Vagin Cc: David Howells Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- fs/file_table.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/file_table.c b/fs/file_table.c index 08e719b884ca..b9a77ad08b4d 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -313,6 +313,12 @@ void fput(struct file *file) init_task_work(&file->f_u.fu_rcuhead, ____fput); if (!task_work_add(task, &file->f_u.fu_rcuhead, true)) return; + /* + * After this task has run exit_task_work(), + * task_work_add() will fail. free_ipc_ns()-> + * shm_destroy() can do this. Fall through to delayed + * fput to avoid leaking *file. + */ } spin_lock_irqsave(&delayed_fput_lock, flags); list_add(&file->f_u.fu_list, &delayed_fput_list); -- GitLab From 4f5e65a1cc90bbb15b9f6cdc362922af1bcc155a Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 8 Jul 2013 14:24:16 -0700 Subject: [PATCH 2720/2900] fput: turn "list_head delayed_fput_list" into llist_head fput() and delayed_fput() can use llist and avoid the locking. This is unlikely path, it is not that this change can improve the performance, but this way the code looks simpler. Signed-off-by: Oleg Nesterov Suggested-by: Andrew Morton Cc: Al Viro Cc: Andrey Vagin Cc: "Eric W. Biederman" Cc: David Howells Cc: Huang Ying Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- fs/file_table.c | 25 ++++++++++--------------- include/linux/fs.h | 2 ++ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/fs/file_table.c b/fs/file_table.c index b9a77ad08b4d..b44e4c559786 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -265,18 +265,15 @@ static void __fput(struct file *file) mntput(mnt); } -static DEFINE_SPINLOCK(delayed_fput_lock); -static LIST_HEAD(delayed_fput_list); +static LLIST_HEAD(delayed_fput_list); static void delayed_fput(struct work_struct *unused) { - LIST_HEAD(head); - spin_lock_irq(&delayed_fput_lock); - list_splice_init(&delayed_fput_list, &head); - spin_unlock_irq(&delayed_fput_lock); - while (!list_empty(&head)) { - struct file *f = list_first_entry(&head, struct file, f_u.fu_list); - list_del_init(&f->f_u.fu_list); - __fput(f); + struct llist_node *node = llist_del_all(&delayed_fput_list); + struct llist_node *next; + + for (; node; node = next) { + next = llist_next(node); + __fput(llist_entry(node, struct file, f_u.fu_llist)); } } @@ -306,7 +303,6 @@ void fput(struct file *file) { if (atomic_long_dec_and_test(&file->f_count)) { struct task_struct *task = current; - unsigned long flags; file_sb_list_del(file); if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { @@ -320,10 +316,9 @@ void fput(struct file *file) * fput to avoid leaking *file. */ } - spin_lock_irqsave(&delayed_fput_lock, flags); - list_add(&file->f_u.fu_list, &delayed_fput_list); - schedule_work(&delayed_fput_work); - spin_unlock_irqrestore(&delayed_fput_lock, flags); + + if (llist_add(&file->f_u.fu_llist, &delayed_fput_list)) + schedule_work(&delayed_fput_work); } } diff --git a/include/linux/fs.h b/include/linux/fs.h index 834c9e5113d9..d40e8e78bbd1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -768,6 +769,7 @@ struct file { */ union { struct list_head fu_list; + struct llist_node fu_llist; struct rcu_head fu_rcuhead; } f_u; struct path f_path; -- GitLab From fb4214db50b00558cc6e274c88b3f7325068e942 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 8 Jul 2013 14:24:18 -0700 Subject: [PATCH 2721/2900] llist: fix/simplify llist_add() and llist_add_batch() 1. This is mostly theoretical, but llist_add*() need ACCESS_ONCE(). Otherwise it is not guaranteed that the first cmpxchg() uses the same value for old_entry and new_last->next. 2. These helpers cache the result of cmpxchg() and read the initial value of head->first before the main loop. I do not think this makes sense. In the likely case cmpxchg() succeeds, otherwise it doesn't hurt to reload head->first. I think it would be better to simplify the code and simply read ->first before cmpxchg(). Signed-off-by: Oleg Nesterov Cc: Al Viro Cc: Andrey Vagin Cc: "Eric W. Biederman" Cc: David Howells Cc: Huang Ying Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- include/linux/llist.h | 19 +++++++------------ lib/llist.c | 15 +++++---------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/include/linux/llist.h b/include/linux/llist.h index a5199f6d0e82..3e2b969d68f6 100644 --- a/include/linux/llist.h +++ b/include/linux/llist.h @@ -151,18 +151,13 @@ static inline struct llist_node *llist_next(struct llist_node *node) */ static inline bool llist_add(struct llist_node *new, struct llist_head *head) { - struct llist_node *entry, *old_entry; - - entry = head->first; - for (;;) { - old_entry = entry; - new->next = entry; - entry = cmpxchg(&head->first, old_entry, new); - if (entry == old_entry) - break; - } - - return old_entry == NULL; + struct llist_node *first; + + do { + new->next = first = ACCESS_ONCE(head->first); + } while (cmpxchg(&head->first, first, new) != first); + + return !first; } /** diff --git a/lib/llist.c b/lib/llist.c index 4a15115e90f8..4a70d120138c 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -39,18 +39,13 @@ bool llist_add_batch(struct llist_node *new_first, struct llist_node *new_last, struct llist_head *head) { - struct llist_node *entry, *old_entry; + struct llist_node *first; - entry = head->first; - for (;;) { - old_entry = entry; - new_last->next = entry; - entry = cmpxchg(&head->first, old_entry, new_first); - if (entry == old_entry) - break; - } + do { + new_last->next = first = ACCESS_ONCE(head->first); + } while (cmpxchg(&head->first, first, new_first) != first); - return old_entry == NULL; + return !first; } EXPORT_SYMBOL_GPL(llist_add_batch); -- GitLab From e9a17bd73a29e5323c37ec5ffe50fc0e825d3d03 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 8 Jul 2013 14:24:19 -0700 Subject: [PATCH 2722/2900] llist: llist_add() can use llist_add_batch() llist_add(new, head) can simply use llist_add_batch(new, new, head), no need to duplicate the code. This obviously uninlines llist_add() and to me this is a win. But we can make llist_add_batch() inline if this is desirable, in this case gcc can notice that new_first == new_last if the caller is llist_add(). Signed-off-by: Oleg Nesterov Cc: Al Viro Cc: Andrey Vagin Cc: "Eric W. Biederman" Cc: David Howells Cc: Huang Ying Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- include/linux/llist.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/linux/llist.h b/include/linux/llist.h index 3e2b969d68f6..cdaa7f023899 100644 --- a/include/linux/llist.h +++ b/include/linux/llist.h @@ -142,6 +142,9 @@ static inline struct llist_node *llist_next(struct llist_node *node) return node->next; } +extern bool llist_add_batch(struct llist_node *new_first, + struct llist_node *new_last, + struct llist_head *head); /** * llist_add - add a new entry * @new: new entry to be added @@ -151,13 +154,7 @@ static inline struct llist_node *llist_next(struct llist_node *node) */ static inline bool llist_add(struct llist_node *new, struct llist_head *head) { - struct llist_node *first; - - do { - new->next = first = ACCESS_ONCE(head->first); - } while (cmpxchg(&head->first, first, new) != first); - - return !first; + return llist_add_batch(new, new, head); } /** @@ -173,9 +170,6 @@ static inline struct llist_node *llist_del_all(struct llist_head *head) return xchg(&head->first, NULL); } -extern bool llist_add_batch(struct llist_node *new_first, - struct llist_node *new_last, - struct llist_head *head); extern struct llist_node *llist_del_first(struct llist_head *head); #endif /* LLIST_H */ -- GitLab From a95e691f9c4a6e24fdeab6d7feae6d5411fe8a69 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 16:43:54 +0400 Subject: [PATCH 2723/2900] rpc_create_*_dir: don't bother with qstr just pass the name Signed-off-by: Al Viro --- include/linux/sunrpc/rpc_pipe_fs.h | 4 ++-- net/sunrpc/cache.c | 18 +++++------------- net/sunrpc/clnt.c | 20 ++++++++------------ net/sunrpc/rpc_pipe.c | 14 ++++++++------ 4 files changed, 23 insertions(+), 33 deletions(-) diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index a7b422b33eda..aa5b582cc471 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h @@ -73,12 +73,12 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *, extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *); struct rpc_clnt; -extern struct dentry *rpc_create_client_dir(struct dentry *, struct qstr *, struct rpc_clnt *); +extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); extern int rpc_remove_client_dir(struct dentry *); struct cache_detail; extern struct dentry *rpc_create_cache_dir(struct dentry *, - struct qstr *, + const char *, umode_t umode, struct cache_detail *); extern void rpc_remove_cache_dir(struct dentry *); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 80fe5c86efd1..b40f9567e628 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1812,19 +1812,11 @@ int sunrpc_cache_register_pipefs(struct dentry *parent, const char *name, umode_t umode, struct cache_detail *cd) { - struct qstr q; - struct dentry *dir; - int ret = 0; - - q.name = name; - q.len = strlen(name); - q.hash = full_name_hash(q.name, q.len); - dir = rpc_create_cache_dir(parent, &q, umode, cd); - if (!IS_ERR(dir)) - cd->u.pipefs.dir = dir; - else - ret = PTR_ERR(dir); - return ret; + struct dentry *dir = rpc_create_cache_dir(parent, name, umode, cd); + if (IS_ERR(dir)) + return PTR_ERR(dir); + cd->u.pipefs.dir = dir; + return 0; } EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5a750b9c3640..26456274b24e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -128,9 +128,7 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, { static uint32_t clntid; char name[15]; - struct qstr q = { .name = name }; struct dentry *dir, *dentry; - int error; dir = rpc_d_lookup_sb(sb, dir_name); if (dir == NULL) { @@ -138,19 +136,17 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, return dir; } for (;;) { - q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); + snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); name[sizeof(name) - 1] = '\0'; - q.hash = full_name_hash(q.name, q.len); - dentry = rpc_create_client_dir(dir, &q, clnt); + dentry = rpc_create_client_dir(dir, name, clnt); if (!IS_ERR(dentry)) break; - error = PTR_ERR(dentry); - if (error != -EEXIST) { - printk(KERN_INFO "RPC: Couldn't create pipefs entry" - " %s/%s, error %d\n", - dir_name, name, error); - break; - } + if (dentry == ERR_PTR(-EEXIST)) + continue; + printk(KERN_INFO "RPC: Couldn't create pipefs entry" + " %s/%s, error %ld\n", + dir_name, name, PTR_ERR(dentry)); + break; } dput(dir); return dentry; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e7ce4b3eb0bd..63364cb5d11a 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -770,15 +770,17 @@ static int rpc_populate(struct dentry *parent, } static struct dentry *rpc_mkdir_populate(struct dentry *parent, - struct qstr *name, umode_t mode, void *private, + const char *name, umode_t mode, void *private, int (*populate)(struct dentry *, void *), void *args_populate) { struct dentry *dentry; + struct qstr q = QSTR_INIT(name, strlen(name)); struct inode *dir = parent->d_inode; int error; + q.hash = full_name_hash(q.name, q.len); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); - dentry = __rpc_lookup_create_exclusive(parent, name); + dentry = __rpc_lookup_create_exclusive(parent, &q); if (IS_ERR(dentry)) goto out; error = __rpc_mkdir(dir, dentry, mode, NULL, private); @@ -925,8 +927,8 @@ static void rpc_clntdir_depopulate(struct dentry *dentry) /** * rpc_create_client_dir - Create a new rpc_client directory in rpc_pipefs - * @dentry: dentry from the rpc_pipefs root to the new directory - * @name: &struct qstr for the name + * @dentry: the parent of new directory + * @name: the name of new directory * @rpc_client: rpc client to associate with this directory * * This creates a directory at the given @path associated with @@ -935,7 +937,7 @@ static void rpc_clntdir_depopulate(struct dentry *dentry) * later be created using rpc_mkpipe(). */ struct dentry *rpc_create_client_dir(struct dentry *dentry, - struct qstr *name, + const char *name, struct rpc_clnt *rpc_client) { return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, @@ -981,7 +983,7 @@ static void rpc_cachedir_depopulate(struct dentry *dentry) rpc_depopulate(dentry, cache_pipefs_files, 0, 3); } -struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name, +struct dentry *rpc_create_cache_dir(struct dentry *parent, const char *name, umode_t umode, struct cache_detail *cd) { return rpc_mkdir_populate(parent, name, umode, NULL, -- GitLab From d3db90b0a448bfdf77ab3d887c9579fead656cc5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:09:57 +0400 Subject: [PATCH 2724/2900] __rpc_lookup_create_exclusive: pass string instead of qstr ... and use d_hash_and_lookup() instead of open-coding it, for fsck sake... Signed-off-by: Al Viro --- net/sunrpc/rpc_pipe.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 63364cb5d11a..27e54d265705 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -656,13 +656,12 @@ static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) } static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, - struct qstr *name) + const char *name) { - struct dentry *dentry; - - dentry = d_lookup(parent, name); + struct qstr q = QSTR_INIT(name, strlen(name)); + struct dentry *dentry = d_hash_and_lookup(parent, &q); if (!dentry) { - dentry = d_alloc(parent, name); + dentry = d_alloc(parent, &q); if (!dentry) return ERR_PTR(-ENOMEM); } @@ -689,8 +688,7 @@ static void __rpc_depopulate(struct dentry *parent, for (i = start; i < eof; i++) { name.name = files[i].name; name.len = strlen(files[i].name); - name.hash = full_name_hash(name.name, name.len); - dentry = d_lookup(parent, &name); + dentry = d_hash_and_lookup(parent, &name); if (dentry == NULL) continue; @@ -732,12 +730,7 @@ static int rpc_populate(struct dentry *parent, mutex_lock(&dir->i_mutex); for (i = start; i < eof; i++) { - struct qstr q; - - q.name = files[i].name; - q.len = strlen(files[i].name); - q.hash = full_name_hash(q.name, q.len); - dentry = __rpc_lookup_create_exclusive(parent, &q); + dentry = __rpc_lookup_create_exclusive(parent, files[i].name); err = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_bad; @@ -774,13 +767,11 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent, int (*populate)(struct dentry *, void *), void *args_populate) { struct dentry *dentry; - struct qstr q = QSTR_INIT(name, strlen(name)); struct inode *dir = parent->d_inode; int error; - q.hash = full_name_hash(q.name, q.len); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); - dentry = __rpc_lookup_create_exclusive(parent, &q); + dentry = __rpc_lookup_create_exclusive(parent, name); if (IS_ERR(dentry)) goto out; error = __rpc_mkdir(dir, dentry, mode, NULL, private); @@ -843,7 +834,6 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, struct dentry *dentry; struct inode *dir = parent->d_inode; umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR; - struct qstr q; int err; if (pipe->ops->upcall == NULL) @@ -851,12 +841,8 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, if (pipe->ops->downcall == NULL) umode &= ~S_IWUGO; - q.name = name; - q.len = strlen(name); - q.hash = full_name_hash(q.name, q.len), - mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); - dentry = __rpc_lookup_create_exclusive(parent, &q); + dentry = __rpc_lookup_create_exclusive(parent, name); if (IS_ERR(dentry)) goto out; err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops, @@ -1063,9 +1049,7 @@ struct dentry *rpc_d_lookup_sb(const struct super_block *sb, const unsigned char *dir_name) { struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name)); - - dir.hash = full_name_hash(dir.name, dir.len); - return d_lookup(sb->s_root, &dir); + return d_hash_and_lookup(sb->s_root, &dir); } EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); -- GitLab From ec193cf5af0a8dc35c3975ca0aca8e7b7f3e3464 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:16:52 +0400 Subject: [PATCH 2725/2900] configfs: don't open-code d_alloc_name() Signed-off-by: Al Viro --- fs/configfs/dir.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 64e5323cbbb0..437b0d535b33 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -660,19 +660,15 @@ static int create_default_group(struct config_group *parent_group, struct config_group *group) { int ret; - struct qstr name; struct configfs_dirent *sd; /* We trust the caller holds a reference to parent */ struct dentry *child, *parent = parent_group->cg_item.ci_dentry; if (!group->cg_item.ci_name) group->cg_item.ci_name = group->cg_item.ci_namebuf; - name.name = group->cg_item.ci_name; - name.len = strlen(name.name); - name.hash = full_name_hash(name.name, name.len); ret = -ENOMEM; - child = d_alloc(parent, &name); + child = d_alloc_name(parent, group->cg_item.ci_name); if (child) { d_add(child, NULL); @@ -1650,7 +1646,6 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) { int err; struct config_group *group = &subsys->su_group; - struct qstr name; struct dentry *dentry; struct dentry *root; struct configfs_dirent *sd; @@ -1667,12 +1662,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT); - name.name = group->cg_item.ci_name; - name.len = strlen(name.name); - name.hash = full_name_hash(name.name, name.len); - err = -ENOMEM; - dentry = d_alloc(root, &name); + dentry = d_alloc_name(root, group->cg_item.ci_name); if (dentry) { d_add(dentry, NULL); -- GitLab From 74931da7a6d341c137f1564a47f36fda68ad21e6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:43:25 +0400 Subject: [PATCH 2726/2900] make simple_lookup() usable for filesystems that set ->s_d_op Signed-off-by: Al Viro --- fs/libfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/libfs.c b/fs/libfs.c index c3a0837fb861..3a3a9b53bf5a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -61,7 +61,8 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned if (dentry->d_name.len > NAME_MAX) return ERR_PTR(-ENAMETOOLONG); - d_set_d_op(dentry, &simple_dentry_operations); + if (!dentry->d_sb->s_d_op) + d_set_d_op(dentry, &simple_dentry_operations); d_add(dentry, NULL); return NULL; } -- GitLab From 6e8cd2cb46e3c772871c86de2ffb718f911f9b59 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:48:35 +0400 Subject: [PATCH 2727/2900] efivarfs: we can use simple_lookup() now Signed-off-by: Al Viro --- fs/efivarfs/inode.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 7e787fb90293..07ab49745e31 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c @@ -155,20 +155,8 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) return 0; }; -/* - * Handle negative dentry. - */ -static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - if (dentry->d_name.len > NAME_MAX) - return ERR_PTR(-ENAMETOOLONG); - d_add(dentry, NULL); - return NULL; -} - const struct inode_operations efivarfs_dir_inode_operations = { - .lookup = efivarfs_lookup, + .lookup = simple_lookup, .unlink = efivarfs_unlink, .create = efivarfs_create, }; -- GitLab From 786e1448d9c5d2a469bcc9d2aecacd418ee1aca0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:50:23 +0400 Subject: [PATCH 2728/2900] cgroup: we can use simple_lookup() now Signed-off-by: Al Viro --- kernel/cgroup.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e5583d10a325..0e0b20b8c5db 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -802,7 +802,6 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, */ static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); -static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int); static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files, unsigned long subsys_mask); @@ -2642,7 +2641,7 @@ static const struct inode_operations cgroup_file_inode_operations = { }; static const struct inode_operations cgroup_dir_inode_operations = { - .lookup = cgroup_lookup, + .lookup = simple_lookup, .mkdir = cgroup_mkdir, .rmdir = cgroup_rmdir, .rename = cgroup_rename, @@ -2652,14 +2651,6 @@ static const struct inode_operations cgroup_dir_inode_operations = { .removexattr = cgroup_removexattr, }; -static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) -{ - if (dentry->d_name.len > NAME_MAX) - return ERR_PTR(-ENAMETOOLONG); - d_add(dentry, NULL); - return NULL; -} - /* * Check if a file is a control file */ -- GitLab From dae3794fd603b92dcbac2859fe0bc7fe129a5188 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Jul 2013 17:55:39 +0400 Subject: [PATCH 2729/2900] sunrpc: now we can just set ->s_d_op Signed-off-by: Al Viro --- net/sunrpc/rpc_pipe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 27e54d265705..260fe72656a1 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -665,10 +665,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, if (!dentry) return ERR_PTR(-ENOMEM); } - if (dentry->d_inode == NULL) { - d_set_d_op(dentry, &rpc_dentry_operations); + if (dentry->d_inode == NULL) return dentry; - } dput(dentry); return ERR_PTR(-EEXIST); } @@ -1102,6 +1100,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RPCAUTH_GSSMAGIC; sb->s_op = &s_ops; + sb->s_d_op = &rpc_dentry_operations; sb->s_time_gran = 1; inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); -- GitLab From c2b4cacfe9816c1fe378c785ce8a678cf0635ec6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Jul 2013 18:16:56 -0400 Subject: [PATCH 2730/2900] drm/radeon/hdmi: make sure we have an afmt block assigned Prevents a segfault if an afmt block is not assigned to the encoder such as in the LVDS or eDP case. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66714 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 6 ++++++ drivers/gpu/drm/radeon/r600_hdmi.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index b9c6f7675e59..b0d3fb341417 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -177,6 +177,9 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode uint32_t offset; ssize_t err; + if (!dig || !dig->afmt) + return; + /* Silent, r600_hdmi_enable will raise WARN for us */ if (!dig->afmt->enabled) return; @@ -280,6 +283,9 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + if (!dig || !dig->afmt) + return; + /* Silent, r600_hdmi_enable will raise WARN for us */ if (enable && dig->afmt->enabled) return; diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index e73b2a73494a..f48240bb8c56 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -266,6 +266,9 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod uint32_t offset; ssize_t err; + if (!dig || !dig->afmt) + return; + /* Silent, r600_hdmi_enable will raise WARN for us */ if (!dig->afmt->enabled) return; @@ -448,6 +451,9 @@ void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; u32 hdmi = HDMI0_ERROR_ACK; + if (!dig || !dig->afmt) + return; + /* Silent, r600_hdmi_enable will raise WARN for us */ if (enable && dig->afmt->enabled) return; -- GitLab From 9847b36af413f32528fc929a0b11d32c2872a05c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 11 Jul 2013 15:00:14 -0400 Subject: [PATCH 2731/2900] drm/radeon/dpm: disable gfx PG on PALM Gfx PG doesn't seem to work properly when UVD is initialized on certain PALM boards. Disable gfx PG for now until we sort out a proper fix. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/sumo_dpm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index 11b6b9924f1b..ca381028bd7b 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1732,7 +1732,13 @@ int sumo_dpm_init(struct radeon_device *rdev) pi->enable_sclk_ds = true; pi->enable_dynamic_m3_arbiter = false; pi->enable_dynamic_patch_ps = true; - pi->enable_gfx_power_gating = true; + /* Some PALM chips don't seem to properly ungate gfx when UVD is in use; + * for now just disable gfx PG. + */ + if (rdev->family == CHIP_PALM) + pi->enable_gfx_power_gating = false; + else + pi->enable_gfx_power_gating = true; pi->enable_gfx_clock_gating = true; pi->enable_mg_clock_gating = true; pi->enable_auto_thermal_throttling = true; -- GitLab From aeea40cbf9388fc829e66fa049f64d97fd72e118 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 11 Jul 2013 14:20:11 -0400 Subject: [PATCH 2732/2900] drm/radeon: Disable dma rings for bo moves on r6xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They still seem to cause instability on some r6xx parts. As a follow up, we can switch to using CP DMA for bo moves on r6xx as a lighter weight alternative to using the 3D engine. A version of this patch should also go to stable kernels. Tested-by: J.N. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 097077499cc6..ea5c52b1f445 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1026,8 +1026,8 @@ static struct radeon_asic r600_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_dma, - .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &r600_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { .set_reg = r600_set_surface_reg, @@ -1119,8 +1119,8 @@ static struct radeon_asic rv6xx_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_dma, - .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &r600_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { .set_reg = r600_set_surface_reg, @@ -1229,8 +1229,8 @@ static struct radeon_asic rs780_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_dma, - .copy_ring_index = R600_RING_TYPE_DMA_INDEX, + .copy = &r600_copy_blit, + .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { .set_reg = r600_set_surface_reg, -- GitLab From 072b5acc7edec1530acc0497b48616bf8dd93313 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 11 Jul 2013 14:48:05 -0400 Subject: [PATCH 2733/2900] drm/radeon: implement bo copy callback using CP DMA (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lighter weight than using the 3D engine. v2: fix ring count Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600.c | 81 ++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/r600d.h | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 3 ++ 3 files changed, 85 insertions(+) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 2d3655f7f41e..f7d494f264a5 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3144,6 +3144,87 @@ int r600_copy_blit(struct radeon_device *rdev, return 0; } +/** + * r600_copy_cpdma - copy pages using the CP DMA engine + * + * @rdev: radeon_device pointer + * @src_offset: src GPU address + * @dst_offset: dst GPU address + * @num_gpu_pages: number of GPU pages to xfer + * @fence: radeon fence object + * + * Copy GPU paging using the CP DMA engine (r6xx+). + * Used by the radeon ttm implementation to move pages if + * registered as the asic copy callback. + */ +int r600_copy_cpdma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, + struct radeon_fence **fence) +{ + struct radeon_semaphore *sem = NULL; + int ring_index = rdev->asic->copy.blit_ring_index; + struct radeon_ring *ring = &rdev->ring[ring_index]; + u32 size_in_bytes, cur_size_in_bytes, tmp; + int i, num_loops; + int r = 0; + + r = radeon_semaphore_create(rdev, &sem); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + return r; + } + + size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); + num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff); + r = radeon_ring_lock(rdev, ring, num_loops * 6 + 21); + if (r) { + DRM_ERROR("radeon: moving bo (%d).\n", r); + radeon_semaphore_free(rdev, &sem, NULL); + return r; + } + + if (radeon_fence_need_sync(*fence, ring->idx)) { + radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring, + ring->idx); + radeon_fence_note_sync(*fence, ring->idx); + } else { + radeon_semaphore_free(rdev, &sem, NULL); + } + + for (i = 0; i < num_loops; i++) { + cur_size_in_bytes = size_in_bytes; + if (cur_size_in_bytes > 0x1fffff) + cur_size_in_bytes = 0x1fffff; + size_in_bytes -= cur_size_in_bytes; + tmp = upper_32_bits(src_offset) & 0xff; + if (size_in_bytes == 0) + tmp |= PACKET3_CP_DMA_CP_SYNC; + radeon_ring_write(ring, PACKET3(PACKET3_CP_DMA, 4)); + radeon_ring_write(ring, src_offset & 0xffffffff); + radeon_ring_write(ring, tmp); + radeon_ring_write(ring, dst_offset & 0xffffffff); + radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); + radeon_ring_write(ring, cur_size_in_bytes); + src_offset += cur_size_in_bytes; + dst_offset += cur_size_in_bytes; + } + radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); + radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); + radeon_ring_write(ring, WAIT_CP_DMA_IDLE_bit); + + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } + + radeon_ring_unlock_commit(rdev, ring); + radeon_semaphore_free(rdev, &sem, *fence); + + return r; +} + /** * r600_copy_dma - copy pages using the DMA engine * diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index f1b3084d8f51..8e3fe815edab 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -602,6 +602,7 @@ #define L2_BUSY (1 << 0) #define WAIT_UNTIL 0x8040 +#define WAIT_CP_DMA_IDLE_bit (1 << 8) #define WAIT_2D_IDLE_bit (1 << 14) #define WAIT_3D_IDLE_bit (1 << 15) #define WAIT_2D_IDLECLEAN_bit (1 << 16) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 45d0693cddd5..b04b5789f4a8 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -340,6 +340,9 @@ int r600_uvd_ring_test(struct radeon_device *rdev, struct radeon_ring *ring); int r600_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, struct radeon_fence **fence); +int r600_copy_cpdma(struct radeon_device *rdev, + uint64_t src_offset, uint64_t dst_offset, + unsigned num_gpu_pages, struct radeon_fence **fence); int r600_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, struct radeon_fence **fence); -- GitLab From bfea6a6803396c6b2240bff59c0dc80420a840f3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 11 Jul 2013 14:53:34 -0400 Subject: [PATCH 2734/2900] drm/radeon: use CP DMA on r6xx for bo moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lighter weight than using the 3D engine. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index ea5c52b1f445..fea997e247ba 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1026,7 +1026,7 @@ static struct radeon_asic r600_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_blit, + .copy = &r600_copy_cpdma, .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { @@ -1119,7 +1119,7 @@ static struct radeon_asic rv6xx_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_blit, + .copy = &r600_copy_cpdma, .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { @@ -1229,7 +1229,7 @@ static struct radeon_asic rs780_asic = { .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &r600_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, - .copy = &r600_copy_blit, + .copy = &r600_copy_cpdma, .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX, }, .surface = { -- GitLab From 1b6e5fd5f4fc152064f4f71cea0bcfeb49e29b8b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 10 Jul 2013 12:26:56 +0200 Subject: [PATCH 2735/2900] drm/radeon: add missing ttm_eu_backoff_reservation to radeon_bo_list_validate Op 10-07-13 12:03, Markus Trippelsdorf schreef: > On 2013.07.10 at 11:56 +0200, Maarten Lankhorst wrote: >> Op 10-07-13 11:46, Markus Trippelsdorf schreef: >>> On 2013.07.10 at 11:29 +0200, Maarten Lankhorst wrote: >>>> Op 10-07-13 11:22, Markus Trippelsdorf schreef: >>>>> By simply copy/pasting a big document under LibreOffice my system hangs >>>>> itself up. Only a hard reset gets it working again. >>>>> see also: https://bugs.freedesktop.org/show_bug.cgi?id=66551 >>>>> >>>>> I've bisected the issue to: >>>>> >>>>> commit ecff665f5e3f1c6909353e00b9420e45ae23d995 >>>>> Author: Maarten Lankhorst >>>>> Date: Thu Jun 27 13:48:17 2013 +0200 >>>>> >>>>> drm/ttm: make ttm reservation calls behave like reservation calls >>>>> >>>>> This commit converts the source of the val_seq counter to >>>>> the ww_mutex api. The reservation objects are converted later, >>>>> because there is still a lockdep splat in nouveau that has to >>>>> resolved first. >>>>> >>>>> Signed-off-by: Maarten Lankhorst >>>>> Reviewed-by: Jerome Glisse >>>>> Signed-off-by: Dave Airlie >>>> Hey, >>>> >>>> Can you try current head with CONFIG_PROVE_LOCKING set and post the >>>> lockdep splat from dmesg, if any? If there is any locking issue >>>> lockdep should warn about it. Lockdep will turn itself off after the >>>> first splat, so if the lockdep splat happens before running the >>>> affected parts those will have to be fixed first. >>> There was an unrelated EDAC lockdep splat, so I simply disabled it. >>> >>> This is what I get: >>> >>> Jul 10 11:40:44 x4 kernel: ================================================ >>> Jul 10 11:40:44 x4 kernel: [ BUG: lock held when returning to user space! ] >>> Jul 10 11:40:44 x4 kernel: 3.10.0-08587-g496322b #35 Not tainted >>> Jul 10 11:40:44 x4 kernel: ------------------------------------------------ >>> Jul 10 11:40:44 x4 kernel: X/211 is leaving the kernel with locks still held! >>> Jul 10 11:40:44 x4 kernel: 2 locks held by X/211: >>> Jul 10 11:40:44 x4 kernel: #0: (reservation_ww_class_acquire){+.+.+.}, at: [] radeon_bo_list_validate+0x20/0xd0 >>> Jul 10 11:40:44 x4 kernel: #1: (reservation_ww_class_mutex){+.+.+.}, at: [] ttm_eu_reserve_buffers+0x126/0x4b0 >>> Jul 10 11:40:52 x4 kernel: SysRq : Emergency Sync >>> Jul 10 11:40:53 x4 kernel: Emergency Sync complete >>> >> Thanks, exactly what I thought. I missed a backoff somewhere.. >> >> Does the below patch fix it? > Yes. Thank you for your quick reply. 8<------ If radeon_cs_parser_relocs fails ttm_eu_backoff_reservation doesn't get called. This left open a bug where ttm_eu_reserve_buffers succeeded but the bo's were not unlocked afterwards: Jul 10 11:40:44 x4 kernel: ================================================ Jul 10 11:40:44 x4 kernel: [ BUG: lock held when returning to user space! ] Jul 10 11:40:44 x4 kernel: 3.10.0-08587-g496322b #35 Not tainted Jul 10 11:40:44 x4 kernel: ------------------------------------------------ Jul 10 11:40:44 x4 kernel: X/211 is leaving the kernel with locks still held! Jul 10 11:40:44 x4 kernel: 2 locks held by X/211: Jul 10 11:40:44 x4 kernel: #0: (reservation_ww_class_acquire){+.+.+.}, at: [] radeon_bo_list_validate+0x20/0xd0 Jul 10 11:40:44 x4 kernel: #1: (reservation_ww_class_mutex){+.+.+.}, at: [] ttm_eu_reserve_buffers+0x126/0x4b0 Jul 10 11:40:52 x4 kernel: SysRq : Emergency Sync Jul 10 11:40:53 x4 kernel: Emergency Sync complete This is a regression caused by commit ecff665f5e. "drm/ttm: make ttm reservation calls behave like reservation calls" Reported-by: Markus Trippelsdorf Tested-by: Markus Trippelsdorf Signed-off-by: Maarten Lankhorst Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 0219d263e2df..2020bf4a3830 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -377,6 +377,7 @@ int radeon_bo_list_validate(struct ww_acquire_ctx *ticket, domain = lobj->alt_domain; goto retry; } + ttm_eu_backoff_reservation(ticket, head); return r; } } -- GitLab From 0a168933976eb483da91161316bbbbcb74d00486 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 11 Jul 2013 15:53:01 -0400 Subject: [PATCH 2736/2900] drm/radeon: use radeon device for request firmware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid creating temporary platform device that will lead to issue when several radeon gpu are in same computer. Instead directly use the radeon device for requesting firmware. Reviewed-by: Christian König Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 25 +++++++------------------ drivers/gpu/drm/radeon/ni.c | 21 +++++---------------- drivers/gpu/drm/radeon/r100.c | 11 +---------- drivers/gpu/drm/radeon/r600.c | 19 ++++--------------- drivers/gpu/drm/radeon/radeon_uvd.c | 13 +------------ drivers/gpu/drm/radeon/si.c | 23 ++++++----------------- 6 files changed, 24 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index ed1d91025928..27891d87c1d3 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -22,7 +22,6 @@ * Authors: Alex Deucher */ #include -#include #include #include #include "drmP.h" @@ -742,7 +741,6 @@ static int ci_mc_load_microcode(struct radeon_device *rdev) */ static int cik_init_microcode(struct radeon_device *rdev) { - struct platform_device *pdev; const char *chip_name; size_t pfp_req_size, me_req_size, ce_req_size, mec_req_size, rlc_req_size, mc_req_size, @@ -752,13 +750,6 @@ static int cik_init_microcode(struct radeon_device *rdev) DRM_DEBUG("\n"); - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } - switch (rdev->family) { case CHIP_BONAIRE: chip_name = "BONAIRE"; @@ -794,7 +785,7 @@ static int cik_init_microcode(struct radeon_device *rdev) DRM_INFO("Loading %s Microcode\n", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); - err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->pfp_fw->size != pfp_req_size) { @@ -806,7 +797,7 @@ static int cik_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); - err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->me_fw->size != me_req_size) { @@ -817,7 +808,7 @@ static int cik_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name); - err = request_firmware(&rdev->ce_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->ce_fw->size != ce_req_size) { @@ -828,7 +819,7 @@ static int cik_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_mec.bin", chip_name); - err = request_firmware(&rdev->mec_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->mec_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->mec_fw->size != mec_req_size) { @@ -839,7 +830,7 @@ static int cik_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name); - err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->rlc_fw->size != rlc_req_size) { @@ -850,7 +841,7 @@ static int cik_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_sdma.bin", chip_name); - err = request_firmware(&rdev->sdma_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->sdma_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->sdma_fw->size != sdma_req_size) { @@ -863,7 +854,7 @@ static int cik_init_microcode(struct radeon_device *rdev) /* No MC ucode on APUs */ if (!(rdev->flags & RADEON_IS_IGP)) { snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); - err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->mc_fw->size != mc_req_size) { @@ -875,8 +866,6 @@ static int cik_init_microcode(struct radeon_device *rdev) } out: - platform_device_unregister(pdev); - if (err) { if (err != -EINVAL) printk(KERN_ERR diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index f30127cb30ef..465b17e1fa4e 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -22,7 +22,6 @@ * Authors: Alex Deucher */ #include -#include #include #include #include @@ -684,7 +683,6 @@ int ni_mc_load_microcode(struct radeon_device *rdev) int ni_init_microcode(struct radeon_device *rdev) { - struct platform_device *pdev; const char *chip_name; const char *rlc_chip_name; size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size; @@ -694,13 +692,6 @@ int ni_init_microcode(struct radeon_device *rdev) DRM_DEBUG("\n"); - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } - switch (rdev->family) { case CHIP_BARTS: chip_name = "BARTS"; @@ -753,7 +744,7 @@ int ni_init_microcode(struct radeon_device *rdev) DRM_INFO("Loading %s Microcode\n", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); - err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->pfp_fw->size != pfp_req_size) { @@ -765,7 +756,7 @@ int ni_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); - err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->me_fw->size != me_req_size) { @@ -776,7 +767,7 @@ int ni_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); - err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->rlc_fw->size != rlc_req_size) { @@ -789,7 +780,7 @@ int ni_init_microcode(struct radeon_device *rdev) /* no MC ucode on TN */ if (!(rdev->flags & RADEON_IS_IGP)) { snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); - err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->mc_fw->size != mc_req_size) { @@ -802,7 +793,7 @@ int ni_init_microcode(struct radeon_device *rdev) if ((rdev->family >= CHIP_BARTS) && (rdev->family <= CHIP_CAYMAN)) { snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); - err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->smc_fw->size != smc_req_size) { @@ -814,8 +805,6 @@ int ni_init_microcode(struct radeon_device *rdev) } out: - platform_device_unregister(pdev); - if (err) { if (err != -EINVAL) printk(KERN_ERR diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c9affefd79f6..75349cdaa84b 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -39,7 +39,6 @@ #include "atom.h" #include -#include #include #include "r100_reg_safe.h" @@ -989,18 +988,11 @@ void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) /* Load the microcode for the CP */ static int r100_cp_init_microcode(struct radeon_device *rdev) { - struct platform_device *pdev; const char *fw_name = NULL; int err; DRM_DEBUG_KMS("\n"); - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || (rdev->family == CHIP_RS200)) { @@ -1042,8 +1034,7 @@ static int r100_cp_init_microcode(struct radeon_device *rdev) fw_name = FIRMWARE_R520; } - err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); - platform_device_unregister(pdev); + err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); if (err) { printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", fw_name); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f7d494f264a5..4982cd8ce8b7 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -2144,7 +2143,6 @@ void r600_cp_stop(struct radeon_device *rdev) int r600_init_microcode(struct radeon_device *rdev) { - struct platform_device *pdev; const char *chip_name; const char *rlc_chip_name; const char *smc_chip_name = "RV770"; @@ -2154,13 +2152,6 @@ int r600_init_microcode(struct radeon_device *rdev) DRM_DEBUG("\n"); - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } - switch (rdev->family) { case CHIP_R600: chip_name = "R600"; @@ -2272,7 +2263,7 @@ int r600_init_microcode(struct radeon_device *rdev) DRM_INFO("Loading %s Microcode\n", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); - err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->pfp_fw->size != pfp_req_size) { @@ -2284,7 +2275,7 @@ int r600_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); - err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->me_fw->size != me_req_size) { @@ -2295,7 +2286,7 @@ int r600_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); - err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->rlc_fw->size != rlc_req_size) { @@ -2307,7 +2298,7 @@ int r600_init_microcode(struct radeon_device *rdev) if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) { snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); - err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->smc_fw->size != smc_req_size) { @@ -2319,8 +2310,6 @@ int r600_init_microcode(struct radeon_device *rdev) } out: - platform_device_unregister(pdev); - if (err) { if (err != -EINVAL) printk(KERN_ERR diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 41efcec28cd8..34444f62803f 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -56,20 +56,12 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work); int radeon_uvd_init(struct radeon_device *rdev) { - struct platform_device *pdev; unsigned long bo_size; const char *fw_name; int i, r; INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); - pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0); - r = IS_ERR(pdev); - if (r) { - dev_err(rdev->dev, "radeon_uvd: Failed to register firmware\n"); - return -EINVAL; - } - switch (rdev->family) { case CHIP_RV710: case CHIP_RV730: @@ -112,16 +104,13 @@ int radeon_uvd_init(struct radeon_device *rdev) return -EINVAL; } - r = request_firmware(&rdev->uvd_fw, fw_name, &pdev->dev); + r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev); if (r) { dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", fw_name); - platform_device_unregister(pdev); return r; } - platform_device_unregister(pdev); - bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 234906709067..f305768c3dfa 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -22,7 +22,6 @@ * Authors: Alex Deucher */ #include -#include #include #include #include @@ -1541,7 +1540,6 @@ static int si_mc_load_microcode(struct radeon_device *rdev) static int si_init_microcode(struct radeon_device *rdev) { - struct platform_device *pdev; const char *chip_name; const char *rlc_chip_name; size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; @@ -1551,13 +1549,6 @@ static int si_init_microcode(struct radeon_device *rdev) DRM_DEBUG("\n"); - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } - switch (rdev->family) { case CHIP_TAHITI: chip_name = "TAHITI"; @@ -1615,7 +1606,7 @@ static int si_init_microcode(struct radeon_device *rdev) DRM_INFO("Loading %s Microcode\n", chip_name); snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); - err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->pfp_fw->size != pfp_req_size) { @@ -1627,7 +1618,7 @@ static int si_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); - err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->me_fw->size != me_req_size) { @@ -1638,7 +1629,7 @@ static int si_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name); - err = request_firmware(&rdev->ce_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->ce_fw->size != ce_req_size) { @@ -1649,7 +1640,7 @@ static int si_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); - err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->rlc_fw->size != rlc_req_size) { @@ -1660,7 +1651,7 @@ static int si_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); - err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->mc_fw->size != mc_req_size) { @@ -1671,7 +1662,7 @@ static int si_init_microcode(struct radeon_device *rdev) } snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); - err = request_firmware(&rdev->smc_fw, fw_name, &pdev->dev); + err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); if (err) goto out; if (rdev->smc_fw->size != smc_req_size) { @@ -1682,8 +1673,6 @@ static int si_init_microcode(struct radeon_device *rdev) } out: - platform_device_unregister(pdev); - if (err) { if (err != -EINVAL) printk(KERN_ERR -- GitLab From 54e2e49ce28ff7ac67b93e7e9e44702552b04a69 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Jun 2013 18:26:25 -0400 Subject: [PATCH 2737/2900] drm/radeon: add fault decode function for cayman/TN (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helpful for debugging GPUVM errors as we can see what hw block and page generated the fault in the log. v2: simplify fault decoding Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/evergreen.c | 10 +- drivers/gpu/drm/radeon/ni.c | 161 +++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/nid.h | 16 +++ 3 files changed, 185 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e49059dc9b8f..526e428cb4d0 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -139,6 +139,8 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev); void evergreen_program_aspm(struct radeon_device *rdev); extern void cayman_cp_int_cntl_setup(struct radeon_device *rdev, int ring, u32 cp_int_cntl); +extern void cayman_vm_decode_fault(struct radeon_device *rdev, + u32 status, u32 addr); static const u32 evergreen_golden_registers[] = { @@ -4586,6 +4588,7 @@ int evergreen_irq_process(struct radeon_device *rdev) bool queue_hotplug = false; bool queue_hdmi = false; bool queue_thermal = false; + u32 status, addr; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; @@ -4872,11 +4875,14 @@ int evergreen_irq_process(struct radeon_device *rdev) break; case 146: case 147: + addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); + status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS); dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + addr); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + status); + cayman_vm_decode_fault(rdev, status, addr); /* reset addr and status */ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); break; diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 465b17e1fa4e..56bd4f3be4fe 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2450,6 +2450,167 @@ void cayman_vm_fini(struct radeon_device *rdev) { } +/** + * cayman_vm_decode_fault - print human readable fault info + * + * @rdev: radeon_device pointer + * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value + * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value + * + * Print human readable fault information (cayman/TN). + */ +void cayman_vm_decode_fault(struct radeon_device *rdev, + u32 status, u32 addr) +{ + u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT; + u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT; + u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT; + char *block; + + switch (mc_id) { + case 32: + case 16: + case 96: + case 80: + case 160: + case 144: + case 224: + case 208: + block = "CB"; + break; + case 33: + case 17: + case 97: + case 81: + case 161: + case 145: + case 225: + case 209: + block = "CB_FMASK"; + break; + case 34: + case 18: + case 98: + case 82: + case 162: + case 146: + case 226: + case 210: + block = "CB_CMASK"; + break; + case 35: + case 19: + case 99: + case 83: + case 163: + case 147: + case 227: + case 211: + block = "CB_IMMED"; + break; + case 36: + case 20: + case 100: + case 84: + case 164: + case 148: + case 228: + case 212: + block = "DB"; + break; + case 37: + case 21: + case 101: + case 85: + case 165: + case 149: + case 229: + case 213: + block = "DB_HTILE"; + break; + case 38: + case 22: + case 102: + case 86: + case 166: + case 150: + case 230: + case 214: + block = "SX"; + break; + case 39: + case 23: + case 103: + case 87: + case 167: + case 151: + case 231: + case 215: + block = "DB_STEN"; + break; + case 40: + case 24: + case 104: + case 88: + case 232: + case 216: + case 168: + case 152: + block = "TC_TFETCH"; + break; + case 41: + case 25: + case 105: + case 89: + case 233: + case 217: + case 169: + case 153: + block = "TC_VFETCH"; + break; + case 42: + case 26: + case 106: + case 90: + case 234: + case 218: + case 170: + case 154: + block = "VC"; + break; + case 112: + block = "CP"; + break; + case 113: + case 114: + block = "SH"; + break; + case 115: + block = "VGT"; + break; + case 178: + block = "IH"; + break; + case 51: + block = "RLC"; + break; + case 55: + block = "DMA"; + break; + case 56: + block = "HDP"; + break; + default: + block = "unknown"; + break; + } + + printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n", + protections, vmid, addr, + (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read", + block, mc_id); +} + #define R600_ENTRY_VALID (1 << 0) #define R600_PTE_SYSTEM (1 << 1) #define R600_PTE_SNOOPED (1 << 2) diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index fe24a93542ec..22421bc80c0d 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -133,6 +133,22 @@ #define VM_CONTEXT1_CNTL2 0x1434 #define VM_INVALIDATE_REQUEST 0x1478 #define VM_INVALIDATE_RESPONSE 0x147c +#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC +#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC +#define PROTECTIONS_MASK (0xf << 0) +#define PROTECTIONS_SHIFT 0 + /* bit 0: range + * bit 2: pde0 + * bit 3: valid + * bit 4: read + * bit 5: write + */ +#define MEMORY_CLIENT_ID_MASK (0xff << 12) +#define MEMORY_CLIENT_ID_SHIFT 12 +#define MEMORY_CLIENT_RW_MASK (1 << 24) +#define MEMORY_CLIENT_RW_SHIFT 24 +#define FAULT_VMID_MASK (0x7 << 25) +#define FAULT_VMID_SHIFT 25 #define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 #define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c #define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C -- GitLab From fbf6dc7ac7291841f53367d461a01a8e8bad0369 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Jun 2013 18:47:58 -0400 Subject: [PATCH 2738/2900] drm/radeon: add fault decode function for SI (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helpful for debugging GPUVM errors as we can see what hw block and page generated the fault in the log. v2: simplify fault decoding Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/si.c | 272 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/sid.h | 14 ++ 2 files changed, 284 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f305768c3dfa..d3f05076f385 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4389,6 +4389,270 @@ void si_vm_fini(struct radeon_device *rdev) { } +/** + * si_vm_decode_fault - print human readable fault info + * + * @rdev: radeon_device pointer + * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value + * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value + * + * Print human readable fault information (SI). + */ +static void si_vm_decode_fault(struct radeon_device *rdev, + u32 status, u32 addr) +{ + u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT; + u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT; + u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT; + char *block; + + if (rdev->family == CHIP_TAHITI) { + switch (mc_id) { + case 160: + case 144: + case 96: + case 80: + case 224: + case 208: + case 32: + case 16: + block = "CB"; + break; + case 161: + case 145: + case 97: + case 81: + case 225: + case 209: + case 33: + case 17: + block = "CB_FMASK"; + break; + case 162: + case 146: + case 98: + case 82: + case 226: + case 210: + case 34: + case 18: + block = "CB_CMASK"; + break; + case 163: + case 147: + case 99: + case 83: + case 227: + case 211: + case 35: + case 19: + block = "CB_IMMED"; + break; + case 164: + case 148: + case 100: + case 84: + case 228: + case 212: + case 36: + case 20: + block = "DB"; + break; + case 165: + case 149: + case 101: + case 85: + case 229: + case 213: + case 37: + case 21: + block = "DB_HTILE"; + break; + case 167: + case 151: + case 103: + case 87: + case 231: + case 215: + case 39: + case 23: + block = "DB_STEN"; + break; + case 72: + case 68: + case 64: + case 8: + case 4: + case 0: + case 136: + case 132: + case 128: + case 200: + case 196: + case 192: + block = "TC"; + break; + case 112: + case 48: + block = "CP"; + break; + case 49: + case 177: + case 50: + case 178: + block = "SH"; + break; + case 53: + case 190: + block = "VGT"; + break; + case 117: + block = "IH"; + break; + case 51: + case 115: + block = "RLC"; + break; + case 119: + case 183: + block = "DMA0"; + break; + case 61: + block = "DMA1"; + break; + case 248: + case 120: + block = "HDP"; + break; + default: + block = "unknown"; + break; + } + } else { + switch (mc_id) { + case 32: + case 16: + case 96: + case 80: + case 160: + case 144: + case 224: + case 208: + block = "CB"; + break; + case 33: + case 17: + case 97: + case 81: + case 161: + case 145: + case 225: + case 209: + block = "CB_FMASK"; + break; + case 34: + case 18: + case 98: + case 82: + case 162: + case 146: + case 226: + case 210: + block = "CB_CMASK"; + break; + case 35: + case 19: + case 99: + case 83: + case 163: + case 147: + case 227: + case 211: + block = "CB_IMMED"; + break; + case 36: + case 20: + case 100: + case 84: + case 164: + case 148: + case 228: + case 212: + block = "DB"; + break; + case 37: + case 21: + case 101: + case 85: + case 165: + case 149: + case 229: + case 213: + block = "DB_HTILE"; + break; + case 39: + case 23: + case 103: + case 87: + case 167: + case 151: + case 231: + case 215: + block = "DB_STEN"; + break; + case 72: + case 68: + case 8: + case 4: + case 136: + case 132: + case 200: + case 196: + block = "TC"; + break; + case 112: + case 48: + block = "CP"; + break; + case 49: + case 177: + case 50: + case 178: + block = "SH"; + break; + case 53: + block = "VGT"; + break; + case 117: + block = "IH"; + break; + case 51: + case 115: + block = "RLC"; + break; + case 119: + case 183: + block = "DMA0"; + break; + case 61: + block = "DMA1"; + break; + case 248: + case 120: + block = "HDP"; + break; + default: + block = "unknown"; + break; + } + } + + printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n", + protections, vmid, addr, + (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read", + block, mc_id); +} + /** * si_vm_set_page - update the page tables using the CP * @@ -5755,6 +6019,7 @@ int si_irq_process(struct radeon_device *rdev) u32 ring_index; bool queue_hotplug = false; bool queue_thermal = false; + u32 status, addr; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; @@ -5990,11 +6255,14 @@ int si_irq_process(struct radeon_device *rdev) break; case 146: case 147: + addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); + status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS); dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + addr); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + status); + si_vm_decode_fault(rdev, status, addr); /* reset addr and status */ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); break; diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 12a20eb77d0c..2c8da27a929f 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -367,6 +367,20 @@ #define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC #define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC +#define PROTECTIONS_MASK (0xf << 0) +#define PROTECTIONS_SHIFT 0 + /* bit 0: range + * bit 1: pde0 + * bit 2: valid + * bit 3: read + * bit 4: write + */ +#define MEMORY_CLIENT_ID_MASK (0xff << 12) +#define MEMORY_CLIENT_ID_SHIFT 12 +#define MEMORY_CLIENT_RW_MASK (1 << 24) +#define MEMORY_CLIENT_RW_SHIFT 24 +#define FAULT_VMID_MASK (0xf << 25) +#define FAULT_VMID_SHIFT 25 #define VM_INVALIDATE_REQUEST 0x1478 #define VM_INVALIDATE_RESPONSE 0x147c -- GitLab From 3ec7d11b9a8f280cd68e53d4a7877624cc002e43 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Jun 2013 10:42:22 -0400 Subject: [PATCH 2739/2900] drm/radeon: add fault decode function for CIK Helpful for debugging GPUVM errors as we can see what hw block and page generated the fault in the log. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 32 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/cikd.h | 16 ++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 27891d87c1d3..68b4fc599e03 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -4441,6 +4441,29 @@ void cik_vm_fini(struct radeon_device *rdev) { } +/** + * cik_vm_decode_fault - print human readable fault info + * + * @rdev: radeon_device pointer + * @status: VM_CONTEXT1_PROTECTION_FAULT_STATUS register value + * @addr: VM_CONTEXT1_PROTECTION_FAULT_ADDR register value + * + * Print human readable fault information (CIK). + */ +static void cik_vm_decode_fault(struct radeon_device *rdev, + u32 status, u32 addr, u32 mc_client) +{ + u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT; + u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT; + u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT; + char *block = (char *)&mc_client; + + printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n", + protections, vmid, addr, + (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read", + block, mc_id); +} + /** * cik_vm_flush - cik vm flush using the CP * @@ -5496,6 +5519,7 @@ int cik_irq_process(struct radeon_device *rdev) u32 ring_index; bool queue_hotplug = false; bool queue_reset = false; + u32 addr, status, mc_client; if (!rdev->ih.enabled || rdev->shutdown) return IRQ_NONE; @@ -5731,11 +5755,15 @@ int cik_irq_process(struct radeon_device *rdev) break; case 146: case 147: + addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR); + status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS); + mc_client = RREG32(VM_CONTEXT1_PROTECTION_FAULT_MCCLIENT); dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); + addr); dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", - RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + status); + cik_vm_decode_fault(rdev, status, addr, mc_client); /* reset addr and status */ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); break; diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 63514b95889a..7e9275eaef80 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -136,6 +136,22 @@ #define VM_INVALIDATE_RESPONSE 0x147c #define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC +#define PROTECTIONS_MASK (0xf << 0) +#define PROTECTIONS_SHIFT 0 + /* bit 0: range + * bit 1: pde0 + * bit 2: valid + * bit 3: read + * bit 4: write + */ +#define MEMORY_CLIENT_ID_MASK (0xff << 12) +#define MEMORY_CLIENT_ID_SHIFT 12 +#define MEMORY_CLIENT_RW_MASK (1 << 24) +#define MEMORY_CLIENT_RW_SHIFT 24 +#define FAULT_VMID_MASK (0xf << 25) +#define FAULT_VMID_SHIFT 25 + +#define VM_CONTEXT1_PROTECTION_FAULT_MCCLIENT 0x14E4 #define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC -- GitLab From c9a6ca4abd5f1978ef15b3ece3474f4372ae5fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 12 Jul 2013 10:05:47 +0200 Subject: [PATCH 2740/2900] drm/radeon: fix UVD fence emit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently doesn't matter cause we allocate the fence in the lower 265MB anyway. Reported-by: Frank Huang Signed-off-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/r600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4982cd8ce8b7..393880a09412 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3008,7 +3008,7 @@ void r600_uvd_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[fence->ring]; - uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; + uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; radeon_ring_write(ring, PACKET0(UVD_CONTEXT_ID, 0)); radeon_ring_write(ring, fence->seq); -- GitLab From 9cc2e0e9f13315559c85c9f99f141e420967c955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 12 Jul 2013 10:18:09 -0400 Subject: [PATCH 2741/2900] drm/radeon: never unpin UVD bo v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changing the UVD BOs offset on suspend/resume doesn't work because the VCPU internally keeps pointers to it. Just keep it always pinned and save the content manually. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66425 v2: fix compiler warning v3: fix CIK support Note: a version of this patch needs to go to stable. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_fence.c | 2 +- drivers/gpu/drm/radeon/radeon_uvd.c | 100 +++++++++++++------------- drivers/gpu/drm/radeon/rv770.c | 2 +- 5 files changed, 53 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 68b4fc599e03..6dacec4e2090 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -6978,7 +6978,7 @@ int cik_uvd_resume(struct radeon_device *rdev) /* programm the VCPU memory controller bits 0-27 */ addr = rdev->uvd.gpu_addr >> 3; - size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; + size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3; WREG32(UVD_VCPU_CACHE_OFFSET0, addr); WREG32(UVD_VCPU_CACHE_SIZE0, size); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9b7025d02cd0..7b7d23ae3f27 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1460,6 +1460,8 @@ struct radeon_uvd { struct radeon_bo *vcpu_bo; void *cpu_addr; uint64_t gpu_addr; + void *saved_bo; + unsigned fw_size; atomic_t handles[RADEON_MAX_UVD_HANDLES]; struct drm_file *filp[RADEON_MAX_UVD_HANDLES]; struct delayed_work idle_work; @@ -2054,7 +2056,6 @@ struct radeon_device { const struct firmware *rlc_fw; /* r6/700 RLC firmware */ const struct firmware *mc_fw; /* NI MC firmware */ const struct firmware *ce_fw; /* SI CE firmware */ - const struct firmware *uvd_fw; /* UVD firmware */ const struct firmware *mec_fw; /* CIK MEC firmware */ const struct firmware *sdma_fw; /* CIK SDMA firmware */ const struct firmware *smc_fw; /* SMC firmware */ diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index ddb8f8e04eb5..7ddb0efe2408 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) } else { /* put fence directly behind firmware */ - index = ALIGN(rdev->uvd_fw->size, 8); + index = ALIGN(rdev->uvd.fw_size, 8); rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index; rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index; } diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 34444f62803f..414fd145d20e 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -56,6 +56,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work); int radeon_uvd_init(struct radeon_device *rdev) { + const struct firmware *fw; unsigned long bo_size; const char *fw_name; int i, r; @@ -104,14 +105,14 @@ int radeon_uvd_init(struct radeon_device *rdev) return -EINVAL; } - r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev); + r = request_firmware(&fw, fw_name, rdev->dev); if (r) { dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n", fw_name); return r; } - bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) + + bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) + RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE; r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo); @@ -120,16 +121,35 @@ int radeon_uvd_init(struct radeon_device *rdev) return r; } - r = radeon_uvd_resume(rdev); - if (r) + r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); + if (r) { + radeon_bo_unref(&rdev->uvd.vcpu_bo); + dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r); return r; + } - memset(rdev->uvd.cpu_addr, 0, bo_size); - memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size); + r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, + &rdev->uvd.gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->uvd.vcpu_bo); + radeon_bo_unref(&rdev->uvd.vcpu_bo); + dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r); + return r; + } - r = radeon_uvd_suspend(rdev); - if (r) + r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); + if (r) { + dev_err(rdev->dev, "(%d) UVD map failed\n", r); return r; + } + + radeon_bo_unreserve(rdev->uvd.vcpu_bo); + + rdev->uvd.fw_size = fw->size; + memset(rdev->uvd.cpu_addr, 0, bo_size); + memcpy(rdev->uvd.cpu_addr, fw->data, fw->size); + + release_firmware(fw); for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { atomic_set(&rdev->uvd.handles[i], 0); @@ -140,72 +160,48 @@ int radeon_uvd_init(struct radeon_device *rdev) } void radeon_uvd_fini(struct radeon_device *rdev) -{ - radeon_uvd_suspend(rdev); - radeon_bo_unref(&rdev->uvd.vcpu_bo); -} - -int radeon_uvd_suspend(struct radeon_device *rdev) { int r; if (rdev->uvd.vcpu_bo == NULL) - return 0; + return; r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); if (!r) { radeon_bo_kunmap(rdev->uvd.vcpu_bo); radeon_bo_unpin(rdev->uvd.vcpu_bo); - rdev->uvd.cpu_addr = NULL; - if (!radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_CPU, NULL)) { - radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); - } radeon_bo_unreserve(rdev->uvd.vcpu_bo); - - if (rdev->uvd.cpu_addr) { - radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); - } else { - rdev->fence_drv[R600_RING_TYPE_UVD_INDEX].cpu_addr = NULL; - } } - return r; + + radeon_bo_unref(&rdev->uvd.vcpu_bo); } -int radeon_uvd_resume(struct radeon_device *rdev) +int radeon_uvd_suspend(struct radeon_device *rdev) { - int r; + unsigned size; if (rdev->uvd.vcpu_bo == NULL) - return -EINVAL; + return 0; - r = radeon_bo_reserve(rdev->uvd.vcpu_bo, false); - if (r) { - radeon_bo_unref(&rdev->uvd.vcpu_bo); - dev_err(rdev->dev, "(%d) failed to reserve UVD bo\n", r); - return r; - } + size = radeon_bo_size(rdev->uvd.vcpu_bo); + rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL); + memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size); - /* Have been pin in cpu unmap unpin */ - radeon_bo_kunmap(rdev->uvd.vcpu_bo); - radeon_bo_unpin(rdev->uvd.vcpu_bo); + return 0; +} - r = radeon_bo_pin(rdev->uvd.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, - &rdev->uvd.gpu_addr); - if (r) { - radeon_bo_unreserve(rdev->uvd.vcpu_bo); - radeon_bo_unref(&rdev->uvd.vcpu_bo); - dev_err(rdev->dev, "(%d) UVD bo pin failed\n", r); - return r; - } +int radeon_uvd_resume(struct radeon_device *rdev) +{ + if (rdev->uvd.vcpu_bo == NULL) + return -EINVAL; - r = radeon_bo_kmap(rdev->uvd.vcpu_bo, &rdev->uvd.cpu_addr); - if (r) { - dev_err(rdev->dev, "(%d) UVD map failed\n", r); - return r; + if (rdev->uvd.saved_bo != NULL) { + unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo); + memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size); + kfree(rdev->uvd.saved_bo); + rdev->uvd.saved_bo = NULL; } - radeon_bo_unreserve(rdev->uvd.vcpu_bo); - return 0; } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 4a62ad2e5399..30ea14e8854c 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev) /* programm the VCPU memory controller bits 0-27 */ addr = rdev->uvd.gpu_addr >> 3; - size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; + size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3; WREG32(UVD_VCPU_CACHE_OFFSET0, addr); WREG32(UVD_VCPU_CACHE_SIZE0, size); -- GitLab From 6c4f978b357bc779c703fda1f200e9179623d3e9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 12 Jul 2013 15:46:09 -0400 Subject: [PATCH 2742/2900] drm/radeon: allow selection of alignment in the sub-allocator There are cases where we need more than 4k alignment. No functional change with this commit. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_gart.c | 1 + drivers/gpu/drm/radeon/radeon_object.h | 2 +- drivers/gpu/drm/radeon/radeon_ring.c | 1 + drivers/gpu/drm/radeon/radeon_sa.c | 7 ++++--- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 7b7d23ae3f27..82e8e36064e3 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -455,6 +455,7 @@ struct radeon_sa_manager { uint64_t gpu_addr; void *cpu_ptr; uint32_t domain; + uint32_t align; }; struct radeon_sa_bo; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 43ec4a401f07..5ce190b8bd1f 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -467,6 +467,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev) size *= 2; r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, RADEON_GPU_PAGE_ALIGN(size), + RADEON_GPU_PAGE_SIZE, RADEON_GEM_DOMAIN_VRAM); if (r) { dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 91519a5622b4..49c82c480013 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -174,7 +174,7 @@ static inline void * radeon_sa_bo_cpu_addr(struct radeon_sa_bo *sa_bo) extern int radeon_sa_bo_manager_init(struct radeon_device *rdev, struct radeon_sa_manager *sa_manager, - unsigned size, u32 domain); + unsigned size, u32 align, u32 domain); extern void radeon_sa_bo_manager_fini(struct radeon_device *rdev, struct radeon_sa_manager *sa_manager); extern int radeon_sa_bo_manager_start(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 5f1c51a776ed..fb5ea6208970 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -224,6 +224,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) } r = radeon_sa_bo_manager_init(rdev, &rdev->ring_tmp_bo, RADEON_IB_POOL_SIZE*64*1024, + RADEON_GPU_PAGE_SIZE, RADEON_GEM_DOMAIN_GTT); if (r) { return r; diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c index 0abe5a9431bb..f0bac68254b7 100644 --- a/drivers/gpu/drm/radeon/radeon_sa.c +++ b/drivers/gpu/drm/radeon/radeon_sa.c @@ -49,7 +49,7 @@ static void radeon_sa_bo_try_free(struct radeon_sa_manager *sa_manager); int radeon_sa_bo_manager_init(struct radeon_device *rdev, struct radeon_sa_manager *sa_manager, - unsigned size, u32 domain) + unsigned size, u32 align, u32 domain) { int i, r; @@ -57,13 +57,14 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, sa_manager->bo = NULL; sa_manager->size = size; sa_manager->domain = domain; + sa_manager->align = align; sa_manager->hole = &sa_manager->olist; INIT_LIST_HEAD(&sa_manager->olist); for (i = 0; i < RADEON_NUM_RINGS; ++i) { INIT_LIST_HEAD(&sa_manager->flist[i]); } - r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, + r = radeon_bo_create(rdev, size, align, true, domain, NULL, &sa_manager->bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); @@ -317,7 +318,7 @@ int radeon_sa_bo_new(struct radeon_device *rdev, unsigned tries[RADEON_NUM_RINGS]; int i, r; - BUG_ON(align > RADEON_GPU_PAGE_SIZE); + BUG_ON(align > sa_manager->align); BUG_ON(size > sa_manager->size); *sa_bo = kmalloc(sizeof(struct radeon_sa_bo), GFP_KERNEL); -- GitLab From c25f195e828f847735c7626b5693ddc3b853d245 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 17 Jan 2013 13:10:58 -0500 Subject: [PATCH 2743/2900] slub: Check for page NULL before doing the node_match check In the -rt kernel (mrg), we hit the following dump: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] kmem_cache_alloc_node+0x51/0x180 PGD a2d39067 PUD b1641067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: sunrpc cpufreq_ondemand ipv6 tg3 joydev sg serio_raw pcspkr k8temp amd64_edac_mod edac_core i2c_piix4 e100 mii shpchp ext4 mbcache jbd2 sd_mod crc_t10dif sr_mod cdrom sata_svw ata_generic pata_acpi pata_serverworks radeon ttm drm_kms_helper drm hwmon i2c_algo_bit i2c_core dm_mirror dm_region_hash dm_log dm_mod CPU 3 Pid: 20878, comm: hackbench Not tainted 3.6.11-rt25.14.el6rt.x86_64 #1 empty empty/Tyan Transport GT24-B3992 RIP: 0010:[] [] kmem_cache_alloc_node+0x51/0x180 RSP: 0018:ffff8800a9b17d70 EFLAGS: 00010213 RAX: 0000000000000000 RBX: 0000000001200011 RCX: ffff8800a06d8000 RDX: 0000000004d92a03 RSI: 00000000000000d0 RDI: ffff88013b805500 RBP: ffff8800a9b17dc0 R08: ffff88023fd14d10 R09: ffffffff81041cbd R10: 00007f4e3f06e9d0 R11: 0000000000000246 R12: ffff88013b805500 R13: ffff8801ff46af40 R14: 0000000000000001 R15: 0000000000000000 FS: 00007f4e3f06e700(0000) GS:ffff88023fd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 00000000a2d3a000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process hackbench (pid: 20878, threadinfo ffff8800a9b16000, task ffff8800a06d8000) Stack: ffff8800a9b17da0 ffffffff81202e08 ffff8800a9b17de0 000000d001200011 0000000001200011 0000000001200011 0000000000000000 0000000000000000 00007f4e3f06e9d0 0000000000000000 ffff8800a9b17e60 ffffffff81041cbd Call Trace: [] ? current_has_perm+0x68/0x80 [] copy_process+0xdd/0x15b0 [] ? rt_up_read+0x25/0x30 [] do_fork+0x5a/0x360 [] ? migrate_enable+0xeb/0x220 [] sys_clone+0x28/0x30 [] stub_clone+0x13/0x20 [] ? system_call_fastpath+0x16/0x1b Code: 89 fc 89 75 cc 41 89 d6 4d 8b 04 24 65 4c 03 04 25 48 ae 00 00 49 8b 50 08 4d 8b 28 49 8b 40 10 4d 85 ed 74 12 41 83 fe ff 74 27 <48> 8b 00 48 c1 e8 3a 41 39 c6 74 1b 8b 75 cc 4c 89 c9 44 89 f2 RIP [] kmem_cache_alloc_node+0x51/0x180 RSP CR2: 0000000000000000 ---[ end trace 0000000000000002 ]--- Now, this uses SLUB pretty much unmodified, but as it is the -rt kernel with CONFIG_PREEMPT_RT set, spinlocks are mutexes, although they do disable migration. But the SLUB code is relatively lockless, and the spin_locks there are raw_spin_locks (not converted to mutexes), thus I believe this bug can happen in mainline without -rt features. The -rt patch is just good at triggering mainline bugs ;-) Anyway, looking at where this crashed, it seems that the page variable can be NULL when passed to the node_match() function (which does not check if it is NULL). When this happens we get the above panic. As page is only used in slab_alloc() to check if the node matches, if it's NULL I'm assuming that we can say it doesn't and call the __slab_alloc() code. Is this a correct assumption? Acked-by: Christoph Lameter Signed-off-by: Steven Rostedt Signed-off-by: Pekka Enberg Signed-off-by: Linus Torvalds --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index ef60536c5d69..33f71330e713 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2374,7 +2374,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, object = c->freelist; page = c->page; - if (unlikely(!object || !node_match(page, node))) + if (unlikely(!object || !page || !node_match(page, node))) object = __slab_alloc(s, gfpflags, node, addr, c); else { -- GitLab From ad81f0545ef01ea651886dddac4bef6cec930092 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Jul 2013 15:18:27 -0700 Subject: [PATCH 2744/2900] Linux 3.11-rc1 --- Makefile | 6 +- drivers/video/logo/logo_linux_clut224.ppm | 2481 ++++++++------------- 2 files changed, 883 insertions(+), 1604 deletions(-) diff --git a/Makefile b/Makefile index 4e3575c7ec35..9262ba8da4f9 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 3 -PATCHLEVEL = 10 +PATCHLEVEL = 11 SUBLEVEL = 0 -EXTRAVERSION = -NAME = Unicycling Gorilla +EXTRAVERSION = -rc1 +NAME = Linux for Workgroups # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43b82fe..285d552089f2 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,883 @@ P3 -# Standard 224-color Linux logo 80 80 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 1 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 14 14 14 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 11 15 17 33 49 54 59 85 92 73 97 106 +83 116 129 105 131 142 115 114 122 74 88 93 20 29 31 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 10 10 10 10 10 10 +10 10 10 6 6 6 6 6 6 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 3 3 17 23 26 50 67 72 73 97 106 59 85 92 73 97 106 +105 131 142 124 127 131 105 131 142 105 131 142 53 75 83 6 8 8 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 6 6 6 10 10 10 14 14 14 22 22 22 26 26 26 30 30 30 34 34 34 +30 30 30 30 30 30 26 26 26 18 18 18 14 14 14 10 10 10 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 +0 0 0 1 1 1 26 35 39 59 85 92 59 85 92 59 85 92 29 43 47 53 75 83 +108 122 132 132 98 104 108 122 132 105 131 142 101 101 101 43 45 48 6 8 8 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 14 14 14 26 26 26 42 42 42 54 54 54 66 66 66 78 78 78 78 78 78 +78 78 78 74 74 74 66 66 66 54 54 54 42 42 42 26 26 26 18 18 18 10 10 10 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 +11 15 17 27 40 45 59 85 92 59 85 92 27 40 45 31 45 49 73 97 106 93 121 133 +108 122 132 108 122 132 105 131 142 108 122 132 105 131 142 73 97 106 26 35 39 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +22 22 22 42 42 42 66 66 66 86 86 86 66 66 66 38 38 38 38 38 38 22 22 22 +26 26 26 34 34 34 54 54 54 66 66 66 86 86 86 70 70 70 46 46 46 26 26 26 +14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 7 12 13 21 31 35 42 59 64 +53 75 83 53 75 83 50 67 72 42 59 64 32 40 45 42 59 64 73 97 106 116 116 116 +132 98 104 116 116 116 108 122 132 117 104 110 105 131 142 83 116 129 50 67 72 7 12 13 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 +50 50 50 82 82 82 58 58 58 6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 54 54 54 86 86 86 66 66 66 +38 38 38 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 1 1 1 6 8 8 15 22 25 26 35 39 36 54 60 53 75 83 59 85 92 +59 85 92 48 63 69 15 22 25 12 17 20 52 67 79 94 94 94 132 98 104 132 98 104 +117 104 110 108 122 132 108 122 132 115 114 122 105 131 142 77 105 114 59 85 92 36 54 60 +7 12 13 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 50 50 50 +78 78 78 34 34 34 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 +78 78 78 46 46 46 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 15 22 25 29 43 47 36 54 60 42 59 64 42 59 64 48 63 69 21 31 35 +6 8 8 29 43 47 36 50 56 43 45 48 79 78 84 132 98 104 165 78 79 132 98 104 +108 122 132 117 104 110 117 104 110 108 122 132 77 105 114 73 97 106 95 131 149 78 102 129 +36 50 56 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 42 42 42 82 82 82 +26 26 26 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 14 14 14 46 46 46 34 34 34 6 6 6 2 2 6 +42 42 42 78 78 78 42 42 42 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +27 40 45 53 75 83 48 63 69 24 31 37 6 8 12 0 0 0 18 25 28 26 35 39 +12 17 20 26 35 39 65 78 84 112 81 86 152 81 83 137 83 86 132 98 104 117 104 110 +117 104 110 132 98 104 132 98 104 115 114 122 73 97 106 53 75 83 95 131 149 93 124 152 +68 78 128 15 22 25 0 0 0 0 0 0 10 10 10 30 30 30 66 66 66 58 58 58 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 26 26 26 86 86 86 101 101 101 46 46 46 10 10 10 +2 2 6 58 58 58 70 70 70 34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +36 50 56 21 30 33 4 7 7 0 0 0 1 1 1 17 12 12 69 31 31 68 59 64 +57 59 63 21 31 35 32 40 45 86 73 69 152 81 83 152 81 83 117 104 110 132 98 104 +152 81 83 132 98 104 108 122 132 77 105 114 77 105 114 93 121 133 95 131 149 93 124 152 +95 131 149 53 75 83 11 15 17 0 0 0 14 14 14 42 42 42 86 86 86 10 10 10 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 30 30 30 94 94 94 94 94 94 58 58 58 26 26 26 +2 2 6 6 6 6 78 78 78 54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +17 23 26 2 3 3 0 0 0 17 12 12 69 31 31 123 55 55 123 55 55 152 81 83 +86 73 69 17 23 26 7 12 13 45 54 57 101 101 101 137 83 86 132 98 104 132 98 104 +137 83 86 117 104 110 77 105 114 42 59 64 50 67 72 78 102 129 91 117 157 91 117 157 +95 131 149 83 116 129 40 48 73 6 6 6 22 22 22 62 62 62 62 62 62 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 26 26 26 54 54 54 38 38 38 18 18 18 10 10 10 +2 2 6 2 2 6 34 34 34 82 82 82 38 38 38 14 14 14 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +1 1 1 1 2 2 2 3 3 28 12 12 123 55 55 174 79 79 174 79 79 174 79 79 +152 81 83 68 59 64 26 35 39 27 40 45 79 78 84 137 83 86 165 78 79 137 83 86 +94 94 94 48 63 69 36 50 56 50 67 72 73 97 106 93 121 133 93 124 152 93 124 152 +95 131 149 91 118 149 78 102 129 27 40 45 30 30 30 78 78 78 30 30 30 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 10 10 10 10 10 10 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 78 78 78 50 50 50 18 18 18 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +4 5 3 24 53 24 19 31 15 8 7 3 90 61 47 165 78 79 174 79 79 174 79 79 +174 79 79 137 83 86 60 52 57 7 12 13 17 23 26 70 70 70 132 98 104 112 81 86 +79 78 84 31 45 49 15 22 25 53 75 83 91 118 149 86 106 160 91 117 157 93 124 152 +91 117 157 93 124 152 95 131 149 53 75 83 50 50 50 86 86 86 14 14 14 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 54 54 54 66 66 66 26 26 26 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +19 31 15 34 76 34 34 76 34 19 31 15 28 12 12 123 55 55 174 79 79 174 79 79 +174 79 79 165 78 79 112 81 86 32 40 45 15 22 25 38 53 58 65 78 84 29 31 32 +21 30 33 42 59 64 60 80 103 78 102 129 87 112 149 84 96 162 91 117 157 93 124 152 +91 117 157 93 124 152 93 121 133 59 85 92 57 68 71 82 85 86 2 2 6 2 2 6 +2 2 6 6 6 6 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 6 6 6 14 14 14 10 10 10 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 18 18 18 82 82 82 34 34 34 10 10 10 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +34 76 34 40 89 40 40 89 40 34 76 34 8 15 6 48 26 18 123 55 55 174 79 79 +174 79 79 174 79 79 137 83 86 68 59 64 32 40 45 21 30 33 31 45 49 21 31 35 +12 17 20 48 63 69 78 102 129 81 88 166 84 96 162 91 117 157 93 124 152 91 117 157 +93 124 152 95 131 149 83 116 129 59 85 92 57 68 71 86 86 86 2 2 6 2 2 6 +6 6 6 6 6 6 22 22 22 34 34 34 6 6 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 18 18 18 34 34 34 10 10 10 50 50 50 22 22 22 2 2 6 +2 2 6 2 2 6 2 2 6 10 10 10 86 86 86 42 42 42 14 14 14 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +40 89 40 40 89 40 40 89 40 40 89 40 24 53 24 6 6 6 69 31 31 123 55 55 +123 55 55 90 61 47 69 31 31 36 32 33 21 31 35 7 12 13 18 25 28 48 63 69 +60 80 103 68 78 128 84 101 153 84 96 162 84 96 162 91 117 157 91 117 157 84 96 162 +91 117 157 73 97 106 48 63 69 50 67 72 57 59 63 86 86 86 2 2 6 2 2 6 +38 38 38 116 116 116 94 94 94 22 22 22 22 22 22 2 2 6 2 2 6 2 2 6 +14 14 14 86 86 86 124 131 137 170 170 170 151 151 151 38 38 38 26 26 26 6 6 6 +2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 46 46 46 14 14 14 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +34 76 34 40 89 40 40 89 40 40 89 40 34 76 34 19 31 15 17 12 12 48 26 18 +48 26 18 8 7 3 10 10 22 23 29 47 51 61 92 42 59 64 21 30 33 34 45 54 +68 78 128 81 88 166 81 82 173 86 106 160 86 106 160 84 96 162 86 106 160 87 112 149 +91 118 149 77 105 114 52 67 79 32 40 45 50 50 50 86 86 86 2 2 6 14 14 14 +124 131 137 198 198 198 195 195 195 116 116 116 10 10 10 2 2 6 2 2 6 6 6 6 +101 98 89 187 187 187 210 210 210 218 218 218 214 214 214 124 131 137 14 14 14 6 6 6 +2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 50 50 50 18 18 18 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +19 31 15 34 76 34 40 89 40 40 89 40 40 89 40 24 53 24 8 7 3 0 0 0 +6 8 12 28 32 52 51 61 92 54 54 122 74 77 160 68 78 128 26 35 39 6 8 8 +34 45 54 68 78 128 84 96 162 86 106 160 86 106 160 81 88 166 84 96 162 87 112 149 +73 97 106 36 50 56 33 49 54 18 18 18 46 46 46 86 86 86 2 2 6 54 54 54 +218 218 218 195 195 195 226 226 226 246 246 246 58 58 58 2 2 6 2 2 6 30 30 30 +210 210 210 253 253 253 170 170 170 124 127 131 221 221 221 234 234 234 74 74 74 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 22 22 22 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +4 5 3 24 53 24 40 89 40 40 89 40 34 76 34 12 22 15 4 5 3 4 5 3 +13 17 26 54 54 122 78 78 174 78 78 174 78 78 174 74 77 160 51 61 92 21 31 35 +26 35 39 53 75 83 84 101 153 81 82 173 81 88 166 84 101 153 60 80 103 60 80 103 +53 75 83 38 53 58 42 59 64 22 22 22 46 46 46 82 82 82 2 2 6 106 106 106 +170 170 170 26 26 26 86 86 86 226 226 226 124 127 131 10 10 10 14 14 14 46 46 46 +231 231 231 190 190 190 6 6 6 70 70 70 90 90 90 238 238 238 151 151 151 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 22 22 22 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +1 2 2 8 15 6 24 53 24 34 76 34 19 31 15 8 15 6 63 55 20 63 55 20 +18 18 18 40 48 73 74 77 160 78 78 174 78 78 174 81 82 173 74 77 160 52 67 79 +17 23 26 21 31 35 60 80 103 81 88 166 74 77 160 78 102 129 36 54 60 12 17 20 +42 59 64 48 63 69 21 31 35 18 18 18 42 42 42 86 86 86 6 6 6 116 116 116 +106 106 106 6 6 6 70 70 70 151 151 151 124 127 131 18 18 18 38 38 38 54 54 54 +221 221 221 106 106 106 2 2 6 14 14 14 46 46 46 190 190 190 198 198 198 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 22 22 22 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +11 15 17 0 0 0 12 22 15 19 31 15 8 15 6 63 55 20 149 139 69 149 139 69 +63 55 20 10 10 22 54 54 122 78 78 174 78 78 174 78 78 174 81 82 173 68 78 128 +24 31 37 6 6 6 36 50 56 60 80 103 51 61 92 42 59 64 36 50 56 31 45 49 +29 43 47 27 40 45 6 8 8 14 14 14 42 42 42 94 94 94 14 14 14 101 101 101 +124 127 131 2 2 6 18 18 18 116 116 116 106 107 48 121 92 8 121 92 8 98 70 6 +170 170 170 106 106 106 2 2 6 2 2 6 2 2 6 195 195 195 195 195 195 6 6 6 +2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 22 22 22 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +26 35 39 3 5 6 1 1 1 2 3 3 35 31 12 133 118 54 175 176 80 175 176 80 +133 118 54 35 31 12 23 29 47 54 54 122 78 78 174 78 78 174 74 77 160 68 78 128 +51 61 92 31 45 49 26 35 39 36 50 56 29 43 47 7 12 13 21 30 33 42 59 64 +18 25 28 7 12 13 1 1 1 10 10 10 38 38 38 90 90 90 14 14 14 58 58 58 +210 210 210 26 26 26 62 42 6 154 114 10 226 170 11 237 188 10 220 174 15 184 138 11 +220 174 15 174 140 55 35 31 12 2 2 6 70 70 70 246 246 246 124 131 137 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 66 66 66 26 26 26 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +27 40 45 17 23 26 2 3 3 1 1 1 56 77 35 165 152 80 175 176 80 175 176 80 +175 176 80 106 107 48 22 22 22 28 32 52 54 54 122 54 54 122 51 61 92 28 32 52 +20 27 34 31 45 49 11 15 17 7 12 13 36 50 56 31 45 49 29 43 47 36 50 56 +6 8 8 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 14 14 14 10 10 10 +195 195 195 198 179 130 192 133 9 220 174 15 239 182 13 237 188 10 232 195 16 239 207 25 +237 201 50 241 208 19 232 195 16 184 138 11 198 179 130 208 206 196 42 42 42 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 74 74 74 30 30 30 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +15 22 25 26 35 39 15 22 25 0 0 0 35 31 12 133 118 54 175 176 80 175 176 80 +175 176 80 165 152 80 56 77 35 6 8 12 23 29 47 13 17 26 2 2 6 0 0 0 +1 2 2 26 35 39 26 35 39 26 35 39 42 59 64 42 59 64 20 29 31 6 8 8 +0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 86 86 86 14 14 14 2 2 6 +121 92 8 192 133 9 219 162 10 239 182 13 237 188 10 232 195 16 241 208 19 237 201 50 +237 201 50 239 207 25 241 208 19 241 208 19 241 208 19 230 187 11 121 92 8 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 82 82 82 34 34 34 10 10 10 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +1 2 2 15 22 25 31 45 49 6 8 12 4 5 3 63 55 20 149 139 69 175 176 80 +175 176 80 175 176 80 106 107 48 20 16 6 1 1 1 0 0 0 2 3 3 11 15 17 +21 30 33 36 50 56 36 50 56 24 31 37 15 22 25 6 8 8 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 82 82 82 30 30 30 62 42 6 +180 123 7 206 145 10 230 174 11 239 182 13 237 188 10 238 202 15 241 208 19 237 201 50 +239 207 25 241 208 19 241 208 19 241 208 19 230 187 11 220 174 15 184 138 11 6 6 6 +2 2 6 2 2 6 2 2 6 2 2 6 26 26 26 94 94 94 42 42 42 14 14 14 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 1 2 2 29 43 47 26 35 39 3 5 6 8 7 3 106 107 48 165 152 80 +175 176 80 149 139 69 63 55 20 4 5 3 2 3 3 12 17 20 26 35 39 26 35 39 +17 23 26 7 12 13 6 8 8 3 5 6 1 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 50 50 50 104 69 6 +192 133 9 216 158 10 236 178 12 237 188 10 232 195 16 241 208 19 237 201 50 237 201 50 +241 208 19 241 208 19 241 208 19 204 160 10 200 144 11 216 158 10 156 118 10 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 90 90 90 54 54 54 18 18 18 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 12 17 20 27 40 45 18 25 28 1 1 1 35 31 12 106 107 48 +149 139 69 56 77 35 8 7 3 1 2 2 12 17 20 26 35 39 21 31 35 11 15 17 +3 5 6 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 46 46 46 22 22 22 +137 92 6 204 160 10 239 182 13 237 188 10 238 202 15 241 208 19 241 208 19 241 208 19 +241 208 19 204 160 10 184 138 11 210 150 10 216 158 10 210 150 10 98 70 6 2 2 6 +6 6 6 54 54 54 14 14 14 2 2 6 2 2 6 62 62 62 74 74 74 30 30 30 +10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 1 1 1 15 22 25 33 49 54 12 17 20 2 3 3 35 31 12 +56 77 35 20 16 6 1 1 1 18 25 28 21 31 35 11 15 17 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 78 78 78 50 50 50 6 6 6 +88 55 22 139 102 15 190 146 13 230 187 11 239 207 25 232 195 16 220 174 15 190 146 13 +171 120 8 192 133 9 210 150 10 213 154 11 185 146 40 165 152 80 101 98 89 2 2 6 +2 2 6 78 78 78 116 116 116 58 58 58 2 2 6 22 22 22 90 90 90 46 46 46 +18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 1 1 1 27 40 45 29 43 47 3 5 6 2 3 3 +8 7 3 1 1 1 17 23 26 31 45 49 15 22 25 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 50 50 50 6 6 6 +124 127 131 168 158 138 156 107 11 171 120 8 204 160 10 184 138 11 197 138 11 200 144 11 +206 145 10 206 145 10 197 138 11 198 179 130 195 195 195 198 198 198 170 170 170 14 14 14 +2 2 6 22 22 22 116 116 116 116 116 116 22 22 22 2 2 6 74 74 74 70 70 70 +30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 11 15 17 31 45 49 26 35 39 3 5 6 +0 0 0 7 12 13 27 40 45 18 25 28 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 6 6 6 18 18 18 50 50 50 101 101 101 26 26 26 10 10 10 +124 131 137 190 190 190 168 158 138 156 107 11 197 138 11 200 144 11 197 138 11 192 133 9 +180 123 7 185 146 40 198 179 130 187 187 187 202 202 202 221 221 221 214 214 214 66 66 66 +2 2 6 2 2 6 50 50 50 62 62 62 6 6 6 2 2 6 10 10 10 90 90 90 +50 50 50 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 15 22 25 36 54 60 18 25 28 +0 0 0 21 30 33 27 40 45 2 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 10 10 34 34 34 74 74 74 74 74 74 2 2 6 6 6 6 +151 151 151 198 198 198 190 190 190 168 158 138 148 132 55 156 107 11 156 107 11 169 125 40 +168 158 138 187 187 187 190 190 190 210 210 210 246 246 246 253 253 253 253 253 253 180 180 180 +6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 +74 74 74 34 34 34 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 27 40 45 35 52 58 +18 25 28 35 52 58 17 23 26 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 10 10 22 22 22 54 54 54 94 94 94 18 18 18 2 2 6 46 46 46 +234 234 234 221 221 221 190 190 190 190 190 190 190 190 190 187 187 187 187 187 187 190 190 190 +190 190 190 195 195 195 214 214 214 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 14 14 14 +86 86 86 54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 12 13 33 49 54 +52 72 81 36 54 60 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 18 18 18 46 46 46 90 90 90 46 46 46 18 18 18 6 6 6 180 180 180 +253 253 253 246 246 246 202 202 202 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 +202 202 202 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +202 202 202 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +42 42 42 86 86 86 42 42 42 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 17 20 +36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +14 14 14 38 38 38 74 74 74 66 66 66 2 2 6 6 6 6 90 90 90 250 250 250 +253 253 253 253 253 253 238 238 238 198 198 198 190 190 190 190 190 190 195 195 195 221 221 221 +246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 78 78 78 70 70 70 34 34 34 14 14 14 6 6 6 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 +34 34 34 66 66 66 78 78 78 6 6 6 2 2 6 18 18 18 218 218 218 253 253 253 +253 253 253 253 253 253 253 253 253 246 246 246 226 226 226 231 231 231 246 246 246 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 180 180 180 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 18 18 18 90 90 90 62 62 62 30 30 30 10 10 10 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 +58 58 58 90 90 90 18 18 18 2 2 6 2 2 6 106 106 106 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 231 231 231 18 18 18 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 18 18 18 94 94 94 54 54 54 26 26 26 10 10 10 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 50 50 50 +90 90 90 26 26 26 2 2 6 2 2 6 14 14 14 195 195 195 250 250 250 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +250 250 250 242 242 242 54 54 54 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 38 38 38 86 86 86 50 50 50 22 22 22 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 38 38 38 82 82 82 +34 34 34 2 2 6 2 2 6 2 2 6 42 42 42 195 195 195 246 246 246 253 253 253 +253 253 253 253 253 253 253 253 253 250 250 250 242 242 242 242 242 242 250 250 250 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 246 246 246 238 238 238 +226 226 226 231 231 231 101 101 101 6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 82 82 82 42 42 42 14 14 14 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 62 62 62 66 66 66 +2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 170 170 170 202 202 202 234 234 234 +246 246 246 250 250 250 250 250 250 238 238 238 226 226 226 231 231 231 238 238 238 250 250 250 +250 250 250 250 250 250 246 246 246 231 231 231 214 214 214 202 202 202 202 202 202 202 202 202 +198 198 198 202 202 202 180 180 180 18 18 18 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 66 66 66 30 30 30 +10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 12 17 20 36 54 60 29 43 47 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 82 82 82 18 18 18 +2 2 6 2 2 6 2 2 6 10 10 10 94 94 94 180 180 180 218 218 218 242 242 242 +250 250 250 253 253 253 253 253 253 250 250 250 234 234 234 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 246 246 246 238 238 238 226 226 226 210 210 210 202 202 202 +195 195 195 195 195 195 210 210 210 151 151 151 6 6 6 14 14 14 50 50 50 14 14 14 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 86 86 86 46 46 46 +18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 21 30 33 35 52 58 6 8 12 0 0 0 +0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 54 54 54 70 70 70 2 2 6 +2 2 6 10 10 10 2 2 6 22 22 22 170 170 170 231 231 231 250 250 250 253 253 253 +253 253 253 253 253 253 253 253 253 250 250 250 242 242 242 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 246 246 246 +231 231 231 202 202 202 198 198 198 226 226 226 94 94 94 2 2 6 6 6 6 38 38 38 +30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 62 62 66 66 66 +26 26 26 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 8 8 33 49 54 29 43 47 6 8 12 +0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 74 74 74 50 50 50 2 2 6 +26 26 26 26 26 26 2 2 6 106 106 106 238 238 238 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 246 246 246 218 218 218 202 202 202 210 210 210 14 14 14 2 2 6 2 2 6 +30 30 30 22 22 22 2 2 6 2 2 6 2 2 6 2 2 6 18 18 18 86 86 86 +42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 17 20 33 49 54 17 23 26 +0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 90 90 90 22 22 22 2 2 6 +42 42 42 2 2 6 18 18 18 218 218 218 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 250 250 250 221 221 221 218 218 218 101 101 101 2 2 6 14 14 14 +18 18 18 38 38 38 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 78 78 78 +58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 22 25 36 54 60 +0 0 0 0 0 0 0 0 0 18 18 18 54 54 54 82 82 82 2 2 6 26 26 26 +22 22 22 2 2 6 124 127 131 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 250 250 250 238 238 238 198 198 198 6 6 6 38 38 38 +58 58 58 26 26 26 38 38 38 2 2 6 2 2 6 2 2 6 2 2 6 46 46 46 +78 78 78 30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 21 30 33 +36 54 60 0 0 0 0 0 0 30 30 30 74 74 74 58 58 58 2 2 6 42 42 42 +2 2 6 22 22 22 231 231 231 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 246 246 246 46 46 46 38 38 38 +42 42 42 14 14 14 38 38 38 14 14 14 2 2 6 2 2 6 2 2 6 6 6 6 +86 86 86 46 46 46 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +36 54 60 0 0 0 0 0 0 42 42 42 90 90 90 18 18 18 18 18 18 26 26 26 +2 2 6 116 116 116 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 250 250 250 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 94 94 94 6 6 6 +2 2 6 2 2 6 10 10 10 34 34 34 2 2 6 2 2 6 2 2 6 2 2 6 +74 74 74 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 36 54 60 26 26 26 66 66 66 82 82 82 2 2 6 38 38 38 6 6 6 +14 14 14 210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 246 246 246 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 151 151 151 2 2 6 +2 2 6 2 2 6 2 2 6 46 46 46 2 2 6 2 2 6 2 2 6 2 2 6 +42 42 42 74 74 74 30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 36 54 60 21 30 33 90 90 90 26 26 26 6 6 6 42 42 42 2 2 6 +74 74 74 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 242 242 242 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 180 180 180 2 2 6 +2 2 6 2 2 6 2 2 6 46 46 46 2 2 6 2 2 6 2 2 6 2 2 6 +10 10 10 86 86 86 38 38 38 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 10 10 26 26 26 36 54 60 82 82 82 2 2 6 22 22 22 18 18 18 2 2 6 +151 151 151 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 202 202 202 2 2 6 +2 2 6 2 2 6 2 2 6 38 38 38 2 2 6 2 2 6 2 2 6 2 2 6 +6 6 6 86 86 86 46 46 46 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +18 18 18 46 46 46 86 86 86 36 54 60 2 2 6 34 34 34 10 10 10 6 6 6 +210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 221 221 6 6 6 +2 2 6 2 2 6 6 6 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 82 82 82 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +26 26 26 66 66 66 62 62 62 2 2 6 2 2 6 38 38 38 10 10 10 26 26 26 +238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 231 231 231 6 6 6 +2 2 6 2 2 6 10 10 10 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 66 66 66 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +38 38 38 78 78 78 6 6 6 2 2 6 2 2 6 46 46 46 14 14 14 42 42 42 +246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 234 234 234 10 10 10 +2 2 6 2 2 6 22 22 22 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 66 66 66 62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 +50 50 50 74 74 74 2 2 6 2 2 6 14 14 14 70 70 70 34 34 34 62 62 62 +250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 234 234 234 14 14 14 +2 2 6 2 2 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 66 66 66 62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 +54 54 54 62 62 62 2 2 6 2 2 6 2 2 6 30 30 30 46 46 46 70 70 70 +250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 226 226 226 10 10 10 +2 2 6 6 6 6 30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 66 66 66 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 +58 58 58 62 62 62 2 2 6 2 2 6 2 2 6 2 2 6 30 30 30 78 78 78 +250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 202 202 202 2 2 6 +22 22 22 34 34 34 20 16 6 22 22 22 26 26 26 18 18 18 6 6 6 2 2 6 +2 2 6 82 82 82 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 26 26 26 +62 62 62 106 106 106 63 55 20 184 138 11 204 160 10 121 92 8 6 6 6 62 62 62 +238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 151 151 151 18 18 18 +14 14 14 2 2 6 2 2 6 2 2 6 6 6 6 18 18 18 66 66 66 38 38 38 +6 6 6 94 94 94 50 50 50 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 6 6 10 10 10 10 10 10 18 18 18 38 38 38 +78 78 78 138 132 106 216 158 10 242 186 14 246 190 14 246 190 14 156 118 10 10 10 10 +90 90 90 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 246 230 190 214 187 87 214 187 87 185 146 40 35 31 12 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 46 46 46 +26 26 26 106 106 106 54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 6 6 6 14 14 14 22 22 22 30 30 30 38 38 38 50 50 50 70 70 70 +106 106 106 185 146 40 226 170 11 242 186 14 246 190 14 246 190 14 246 190 14 154 114 10 +6 6 6 74 74 74 226 226 226 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 231 231 231 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 237 201 50 241 196 14 241 208 19 232 195 16 35 31 12 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 30 30 30 26 26 26 +204 160 10 165 152 80 66 66 66 26 26 26 6 6 6 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 18 18 18 38 38 38 58 58 58 78 78 78 86 86 86 101 101 101 124 127 131 +174 140 55 210 150 10 234 174 13 246 186 14 246 190 14 246 190 14 246 190 14 237 188 10 +98 70 6 2 2 6 46 46 46 198 198 198 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 234 234 234 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 214 187 87 242 186 14 241 196 14 204 160 10 20 16 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 121 92 8 +238 202 15 232 195 16 82 82 82 34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +14 14 14 38 38 38 70 70 70 148 132 55 185 146 40 200 144 11 197 138 11 197 138 11 +213 154 11 226 170 11 242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +220 174 15 35 31 12 2 2 6 22 22 22 151 151 151 250 250 250 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 250 250 250 242 242 242 214 187 87 239 182 13 237 188 10 213 154 11 35 31 12 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 62 42 6 220 174 15 +237 188 10 237 188 10 113 101 86 42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +22 22 22 54 54 54 148 132 55 213 154 11 226 170 11 230 174 11 226 170 11 226 170 11 +236 178 12 242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +241 196 14 184 138 11 10 10 10 2 2 6 6 6 6 116 116 116 242 242 242 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 231 231 231 198 198 198 213 164 39 236 178 12 236 178 12 210 150 10 137 92 6 +20 16 6 2 2 6 2 2 6 2 2 6 6 6 6 62 42 6 200 144 11 236 178 12 +239 182 13 239 182 13 124 112 88 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +30 30 30 70 70 70 169 125 40 226 170 11 239 182 13 242 186 14 242 186 14 246 186 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 232 195 16 98 70 6 2 2 6 2 2 6 2 2 6 66 66 66 221 221 221 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 202 202 202 198 198 198 213 164 39 230 174 11 230 174 11 216 158 10 192 133 9 +163 110 8 120 80 7 98 70 6 120 80 7 167 114 7 197 138 11 226 170 11 239 182 13 +242 186 14 242 186 14 165 152 80 78 78 78 34 34 34 14 14 14 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +30 30 30 78 78 78 185 146 40 226 170 11 239 182 13 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 241 196 14 204 160 10 20 16 6 2 2 6 2 2 6 2 2 6 38 38 38 +218 218 218 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +250 250 250 202 202 202 198 198 198 213 164 39 226 170 11 236 178 12 224 166 10 210 150 10 +200 144 11 197 138 11 192 133 9 197 138 11 210 150 10 226 170 11 242 186 14 246 190 14 +246 190 14 246 186 14 220 174 15 124 112 88 62 62 62 30 30 30 14 14 14 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +30 30 30 78 78 78 174 140 55 224 166 10 239 182 13 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 241 196 14 139 102 15 2 2 6 2 2 6 2 2 6 2 2 6 +78 78 78 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +250 250 250 214 214 214 198 198 198 185 146 40 219 162 10 236 178 12 234 174 13 224 166 10 +216 158 10 213 154 11 213 154 11 216 158 10 226 170 11 239 182 13 246 190 14 246 190 14 +246 190 14 246 190 14 242 186 14 213 164 39 101 101 101 58 58 58 30 30 30 14 14 14 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +30 30 30 74 74 74 174 140 55 216 158 10 236 178 12 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 241 196 14 230 187 11 62 42 6 2 2 6 2 2 6 2 2 6 +22 22 22 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 226 226 226 187 187 187 169 125 40 216 158 10 236 178 12 239 182 13 236 178 12 +230 174 11 226 170 11 226 170 11 230 174 11 236 178 12 242 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 186 14 239 182 13 213 164 39 106 106 106 66 66 66 34 34 34 +14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +26 26 26 70 70 70 149 139 69 213 154 11 236 178 12 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 241 196 14 190 146 13 20 16 6 2 2 6 2 2 6 +46 46 46 246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 221 221 221 86 86 86 156 107 11 216 158 10 236 178 12 242 186 14 246 186 14 +242 186 14 239 182 13 239 182 13 242 186 14 242 186 14 246 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 220 174 15 149 139 69 66 66 66 +30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +26 26 26 70 70 70 149 139 69 210 150 10 236 178 12 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 121 92 8 34 34 34 106 106 106 +221 221 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +242 242 242 82 82 82 20 16 6 163 110 8 216 158 10 236 178 12 242 186 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 149 139 69 +46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 +30 30 30 78 78 78 149 139 69 210 150 10 236 178 12 246 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 241 196 14 220 174 15 198 179 130 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 218 218 218 +58 58 58 2 2 6 20 16 6 167 114 7 216 158 10 236 178 12 246 186 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 242 186 14 185 146 40 +54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 +38 38 38 86 86 86 169 125 40 213 154 11 236 178 12 246 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 190 146 13 214 214 214 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 250 250 250 170 170 170 26 26 26 +2 2 6 2 2 6 35 31 12 163 110 8 219 162 10 239 182 13 246 186 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 236 178 12 224 166 10 149 139 69 +46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 +50 50 50 113 101 86 192 133 9 224 166 10 242 186 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 230 187 11 204 160 10 133 118 54 +226 226 226 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +253 253 253 253 253 253 253 253 253 253 253 253 198 198 198 66 66 66 2 2 6 2 2 6 +2 2 6 2 2 6 62 42 6 156 107 11 219 162 10 239 182 13 246 186 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 242 186 14 234 174 13 213 154 11 148 132 55 66 66 66 +30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 +58 58 58 148 132 55 206 145 10 234 174 13 242 186 14 246 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 236 178 12 204 160 10 163 110 8 +62 42 6 124 131 137 218 218 218 250 250 250 253 253 253 253 253 253 253 253 253 250 250 250 +242 242 242 210 210 210 151 151 151 66 66 66 6 6 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 62 42 6 163 110 8 216 158 10 236 178 12 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 239 182 13 230 174 11 216 158 10 185 146 40 124 112 88 70 70 70 38 38 38 +18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 +62 62 62 169 125 40 206 145 10 224 166 10 236 178 12 239 182 13 242 186 14 242 186 14 +246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 236 178 12 216 158 10 171 120 8 +85 57 6 2 2 6 6 6 6 30 30 30 54 54 54 62 62 62 50 50 50 38 38 38 +14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 6 6 6 85 57 6 167 114 7 213 154 11 236 178 12 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 239 182 13 239 182 13 +230 174 11 210 150 10 174 140 55 124 112 88 82 82 82 54 54 54 34 34 34 18 18 18 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 +50 50 50 169 125 40 192 133 9 200 144 11 216 158 10 219 162 10 224 166 10 226 170 11 +230 174 11 236 178 12 239 182 13 239 182 13 242 186 14 246 186 14 246 190 14 246 190 14 +246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 230 174 11 210 150 10 163 110 8 +104 69 6 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 6 6 6 85 57 6 167 114 7 206 145 10 230 174 11 242 186 14 246 190 14 +246 190 14 246 190 14 246 186 14 242 186 14 239 182 13 230 174 11 224 166 10 213 154 11 +169 125 40 124 112 88 86 86 86 58 58 58 38 38 38 22 22 22 10 10 10 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 +34 34 34 70 70 70 133 118 54 169 125 40 167 114 7 180 123 7 192 133 9 197 138 11 +200 144 11 206 145 10 213 154 11 219 162 10 224 166 10 230 174 11 239 182 13 242 186 14 +246 186 14 246 186 14 246 186 14 246 186 14 239 182 13 216 158 10 184 138 11 152 99 6 +104 69 6 20 16 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 +2 2 6 6 6 6 85 57 6 152 99 6 192 133 9 219 162 10 236 178 12 239 182 13 +246 186 14 242 186 14 239 182 13 236 178 12 224 166 10 206 145 10 192 133 9 148 132 55 +94 94 94 62 62 62 42 42 42 22 22 22 14 14 14 6 6 6 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +18 18 18 34 34 34 58 58 58 78 78 78 101 98 89 124 112 88 133 118 54 156 107 11 +163 110 8 167 114 7 171 120 8 180 123 7 184 138 11 197 138 11 210 150 10 219 162 10 +226 170 11 236 178 12 236 178 12 234 174 13 219 162 10 197 138 11 163 110 8 134 84 6 +85 57 6 10 10 10 2 2 6 2 2 6 18 18 18 38 38 38 38 38 38 38 38 38 +38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 26 26 26 2 2 6 +2 2 6 6 6 6 62 42 6 137 92 6 171 120 8 200 144 11 219 162 10 230 174 11 +234 174 13 230 174 11 219 162 10 210 150 10 192 133 9 163 110 8 124 112 88 82 82 82 +50 50 50 30 30 30 14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 14 14 14 22 22 22 34 34 34 42 42 42 58 58 58 74 74 74 86 86 86 +101 98 89 113 101 86 133 118 54 121 92 8 137 92 6 152 99 6 163 110 8 180 123 7 +184 138 11 197 138 11 206 145 10 200 144 11 180 123 7 156 107 11 134 84 6 104 69 6 +62 42 6 54 54 54 106 106 106 101 98 89 86 86 86 82 82 82 78 78 78 78 78 78 +78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 82 82 82 86 86 86 94 94 94 +106 106 106 101 101 101 90 61 47 120 80 7 156 107 11 180 123 7 192 133 9 200 144 11 +206 145 10 200 144 11 192 133 9 171 120 8 139 102 15 113 101 86 70 70 70 42 42 42 +22 22 22 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 6 6 6 10 10 10 14 14 14 22 22 22 30 30 30 38 38 38 +50 50 50 62 62 62 74 74 74 90 90 90 101 98 89 113 101 86 121 92 8 120 80 7 +137 92 6 152 99 6 152 99 6 152 99 6 134 84 6 120 80 7 98 70 6 88 55 22 +101 98 89 82 82 82 58 58 58 46 46 46 38 38 38 34 34 34 34 34 34 34 34 34 +34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 38 38 38 42 42 42 +54 54 54 82 82 82 94 86 71 85 57 6 134 84 6 156 107 11 167 114 7 171 120 8 +171 120 8 167 114 7 152 99 6 121 92 8 101 98 89 62 62 62 34 34 34 18 18 18 +6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 10 10 10 +18 18 18 22 22 22 30 30 30 42 42 42 50 50 50 66 66 66 86 86 86 101 98 89 +94 86 71 98 70 6 104 69 6 104 69 6 104 69 6 85 57 6 88 55 22 90 90 90 +62 62 62 38 38 38 22 22 22 14 14 14 10 10 10 10 10 10 10 10 10 10 10 10 +10 10 10 10 10 10 6 6 6 10 10 10 10 10 10 10 10 10 10 10 10 14 14 14 +22 22 22 42 42 42 70 70 70 94 86 71 85 57 6 104 69 6 120 80 7 137 92 6 +134 84 6 120 80 7 94 86 71 86 86 86 58 58 58 30 30 30 14 14 14 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 6 6 6 10 10 10 14 14 14 18 18 18 26 26 26 38 38 38 54 54 54 +70 70 70 86 86 86 94 86 71 94 86 71 94 86 71 86 86 86 74 74 74 50 50 50 +30 30 30 14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +6 6 6 18 18 18 34 34 34 58 58 58 82 82 82 94 86 71 94 86 71 94 86 71 +94 86 71 94 86 71 74 74 74 50 50 50 26 26 26 14 14 14 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 14 14 14 18 18 18 +30 30 30 38 38 38 46 46 46 54 54 54 50 50 50 42 42 42 30 30 30 18 18 18 +10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 6 6 6 14 14 14 26 26 26 38 38 38 50 50 50 58 58 58 58 58 58 +54 54 54 42 42 42 30 30 30 18 18 18 10 10 10 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 +6 6 6 10 10 10 14 14 14 18 18 18 18 18 18 14 14 14 10 10 10 6 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 18 18 18 22 22 22 22 22 22 +18 18 18 14 14 14 10 10 10 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + -- GitLab From 0b905d83c4db7ae98718c44d79c717836a2ecaa7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 11 Jul 2013 10:21:00 +0530 Subject: [PATCH 2745/2900] hwmon: (abx500) Staticize abx500_temp_attributes abx500_temp_attributes is used only in this file. Make it static. Signed-off-by: Sachin Kamat Signed-off-by: Guenter Roeck --- drivers/hwmon/abx500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/abx500.c b/drivers/hwmon/abx500.c index eee1134274c8..769fe20ec938 100644 --- a/drivers/hwmon/abx500.c +++ b/drivers/hwmon/abx500.c @@ -315,7 +315,7 @@ static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IWUSR | S_IRUGO, static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_min_alarm, NULL, 3); static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_max_alarm, NULL, 3); -struct attribute *abx500_temp_attributes[] = { +static struct attribute *abx500_temp_attributes[] = { &sensor_dev_attr_name.dev_attr.attr, &sensor_dev_attr_temp1_label.dev_attr.attr, -- GitLab From 3a391a39593b48341f0908511590a6c0e55cc069 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 12 Jul 2013 13:45:59 +0200 Subject: [PATCH 2746/2900] ACPI / scan: Do not try to attach scan handlers to devices having them In acpi_bus_device_attach(), if there is an ACPI device object for the given handle and that device object has a scan handler attached to it already, there's nothing more to do for that handle. Moreover, if acpi_scan_attach_handler() is called then, it may execute the .attach() callback of the ACPI scan handler already attached to the device object and that may lead to interesting breakage. For this reason, make acpi_bus_device_attach() return success immediately when the handle's device object has a scan handler attached to it. Reported-by: Toshi Kani Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani Cc: 3.10+ --- drivers/acpi/scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 10985573aaa7..080d75962c57 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1981,6 +1981,9 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, if (acpi_bus_get_device(handle, &device)) return AE_CTRL_DEPTH; + if (device->handler) + return AE_OK; + ret = acpi_scan_attach_handler(device); if (ret) return ret > 0 ? AE_OK : AE_CTRL_DEPTH; -- GitLab From 8832f7e43fa7f0f19bd54e13766a825dd1ed4d6f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 8 Jul 2013 02:01:53 +0200 Subject: [PATCH 2747/2900] ACPI / scan: Always call acpi_bus_scan() for bus check notifications An ACPI_NOTIFY_BUS_CHECK notification means that we should scan the entire namespace starting from the given handle even if the device represented by that handle is present (other devices below it may just have appeared). For this reason, modify acpi_scan_bus_device_check() to always run acpi_bus_scan() if the notification being handled is of type ACPI_NOTIFY_BUS_CHECK. Signed-off-by: Rafael J. Wysocki Acked-by: Toshi Kani Cc: 3.10+ --- drivers/acpi/scan.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 080d75962c57..8a46c924effd 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -352,10 +352,12 @@ static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) mutex_lock(&acpi_scan_lock); lock_device_hotplug(); - acpi_bus_get_device(handle, &device); - if (device) { - dev_warn(&device->dev, "Attempt to re-insert\n"); - goto out; + if (ost_source != ACPI_NOTIFY_BUS_CHECK) { + acpi_bus_get_device(handle, &device); + if (device) { + dev_warn(&device->dev, "Attempt to re-insert\n"); + goto out; + } } acpi_evaluate_hotplug_ost(handle, ost_source, ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); -- GitLab From d19f503e22316a84c39bc19445e0e4fdd49b3532 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Wed, 10 Jul 2013 10:47:13 -0600 Subject: [PATCH 2748/2900] ACPI / memhotplug: Fix a stale pointer in error path device->driver_data needs to be cleared when releasing its data, mem_device, in an error path of acpi_memory_device_add(). The function evaluates the _CRS of memory device objects, and fails when it gets an unexpected resource or cannot allocate memory. A kernel crash or data corruption may occur when the kernel accesses the stale pointer. Signed-off-by: Toshi Kani Reviewed-by: Yasuaki Ishimatsu Cc: 2.6.32+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_memhotplug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index c711d1144044..999adb5499c7 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -323,6 +323,7 @@ static int acpi_memory_device_add(struct acpi_device *device, /* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); if (result) { + device->driver_data = NULL; kfree(mem_device); return result; } -- GitLab From aae760ed21cd690fe8a6db9f3a177ad55d7e12ab Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Fri, 12 Jul 2013 03:45:37 +0530 Subject: [PATCH 2749/2900] cpufreq: Revert commit a66b2e to fix suspend/resume regression commit a66b2e (cpufreq: Preserve sysfs files across suspend/resume) has unfortunately caused several things in the cpufreq subsystem to break subtly after a suspend/resume cycle. The intention of that patch was to retain the file permissions of the cpufreq related sysfs files across suspend/resume. To achieve that, the commit completely removed the calls to cpufreq_add_dev() and __cpufreq_remove_dev() during suspend/resume transitions. But the problem is that those functions do 2 kinds of things: 1. Low-level initialization/tear-down that are critical to the correct functioning of cpufreq-core. 2. Kobject and sysfs related initialization/teardown. Ideally we should have reorganized the code to cleanly separate these two responsibilities, and skipped only the sysfs related parts during suspend/resume. Since we skipped the entire callbacks instead (which also included some CPU and cpufreq-specific critical components), cpufreq subsystem started behaving erratically after suspend/resume. So revert the commit to fix the regression. We'll revisit and address the original goal of that commit separately, since it involves quite a bit of careful code reorganization and appears to be non-trivial. (While reverting the commit, note that another commit f51e1eb (cpufreq: Fix cpufreq regression after suspend/resume) already reverted part of the original set of changes. So revert only the remaining ones). Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Tested-by: Paul Bolle Cc: 3.10+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 4 +++- drivers/cpufreq/cpufreq_stats.c | 6 ++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0937b8d6c2a4..7dcfa6854833 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1942,13 +1942,15 @@ static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, if (dev) { switch (action) { case CPU_ONLINE: + case CPU_ONLINE_FROZEN: cpufreq_add_dev(dev, NULL); break; case CPU_DOWN_PREPARE: - case CPU_UP_CANCELED_FROZEN: + case CPU_DOWN_PREPARE_FROZEN: __cpufreq_remove_dev(dev, NULL); break; case CPU_DOWN_FAILED: + case CPU_DOWN_FAILED_FROZEN: cpufreq_add_dev(dev, NULL); break; } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index cd9e81713a71..12225d19ffcb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -353,13 +353,11 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, cpufreq_update_policy(cpu); break; case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); break; case CPU_DEAD: - cpufreq_stats_free_table(cpu); - break; - case CPU_UP_CANCELED_FROZEN: - cpufreq_stats_free_sysfs(cpu); + case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); break; } -- GitLab From e5248a111bf4048a9f3fab1a9c94c4630a10592a Mon Sep 17 00:00:00 2001 From: Liu ShuoX Date: Thu, 11 Jul 2013 16:03:45 +0800 Subject: [PATCH 2750/2900] PM / Sleep: avoid 'autosleep' in shutdown progress Prevent automatic system suspend from happening during system shutdown by making try_to_suspend() check system_state and return immediately if it is not SYSTEM_RUNNING. This prevents the following breakage from happening (scenario from Zhang Yanmin): Kernel starts shutdown and calls all device driver's shutdown callback. When a driver's shutdown is called, the last wakelock is released and suspend-to-ram starts. However, as some driver's shut down callbacks already shut down devices and disabled runtime pm, the suspend-to-ram calls driver's suspend callback without noticing that device is already off and causes crash. [rjw: Changelog] Signed-off-by: Liu ShuoX Cc: 3.5+ Signed-off-by: Rafael J. Wysocki --- kernel/power/autosleep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/power/autosleep.c b/kernel/power/autosleep.c index c6422ffeda9a..9012ecf7b814 100644 --- a/kernel/power/autosleep.c +++ b/kernel/power/autosleep.c @@ -32,7 +32,8 @@ static void try_to_suspend(struct work_struct *work) mutex_lock(&autosleep_lock); - if (!pm_save_wakeup_count(initial_count)) { + if (!pm_save_wakeup_count(initial_count) || + system_state != SYSTEM_RUNNING) { mutex_unlock(&autosleep_lock); goto out; } -- GitLab From 1258ca805f613025ec079d959d4a78acfb1f79d3 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 11 Jul 2013 13:55:58 +0900 Subject: [PATCH 2751/2900] PM / Sleep: Fix comment typo in pm_wakeup.h Fix a comment typo (sorce -> source) in pm_wakeup.h. [rjw: Changelog] Signed-off-by: Chanwoo Choi Signed-off-by: Rafael J. Wysocki --- include/linux/pm_wakeup.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 569781faa504..a0f70808d7f4 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -36,8 +36,8 @@ * @last_time: Monotonic clock when the wakeup source's was touched last time. * @prevent_sleep_time: Total time this source has been preventing autosleep. * @event_count: Number of signaled wakeup events. - * @active_count: Number of times the wakeup sorce was activated. - * @relax_count: Number of times the wakeup sorce was deactivated. + * @active_count: Number of times the wakeup source was activated. + * @relax_count: Number of times the wakeup source was deactivated. * @expire_count: Number of times the wakeup source's timeout has expired. * @wakeup_count: Number of times the wakeup source might abort suspend. * @active: Status of the wakeup source. -- GitLab From 4a6c41083df3bf4ad828c45e5f8ee1a224d537c6 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 14 Jul 2013 20:29:56 +0200 Subject: [PATCH 2752/2900] cpufreq: s3c24xx: rename CONFIG_CPU_FREQ_S3C24XX_DEBUGFS The Kconfig symbol CPU_FREQ_S3C24XX_DEBUGFS was renamed to ARM_S3C24XX_CPUFREQ_DEBUGFS in commit f023f8dd59 ("cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq"). But that commit missed one instance of its macro CONFIG_CPU_FREQ_S3C24XX_DEBUGFS. Rename it too. Signed-off-by: Paul Bolle Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/s3c24xx-cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 3513e7477160..87781eb20d6d 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -49,7 +49,7 @@ static struct clk *clk_hclk; static struct clk *clk_pclk; static struct clk *clk_arm; -#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS +#ifdef CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void) { return &cpu_cur; @@ -59,7 +59,7 @@ struct s3c_iotimings *s3c_cpufreq_getiotimings(void) { return &s3c24xx_iotiming; } -#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */ +#endif /* CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS */ static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg) { -- GitLab From ab39c77c3246f8462663fb1b07fa193f3e31e255 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 17 Jun 2013 15:43:14 -0400 Subject: [PATCH 2753/2900] alpha: delete __cpuinit usage from all users The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the alpha uses of the __cpuinit macros. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Matt Turner Signed-off-by: Paul Gortmaker --- arch/alpha/kernel/smp.c | 10 +++++----- arch/alpha/kernel/traps.c | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 7b60834fb4b2..53b18a620e1c 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -116,7 +116,7 @@ wait_boot_cpu_to_stop(int cpuid) /* * Where secondaries begin a life of C. */ -void __cpuinit +void smp_callin(void) { int cpuid = hard_smp_processor_id(); @@ -194,7 +194,7 @@ wait_for_txrdy (unsigned long cpumask) * Send a message to a secondary's console. "START" is one such * interesting message. ;-) */ -static void __cpuinit +static void send_secondary_console_msg(char *str, int cpuid) { struct percpu_struct *cpu; @@ -285,7 +285,7 @@ recv_secondary_console_msg(void) /* * Convince the console to have a secondary cpu begin execution. */ -static int __cpuinit +static int secondary_cpu_start(int cpuid, struct task_struct *idle) { struct percpu_struct *cpu; @@ -356,7 +356,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) /* * Bring one cpu online. */ -static int __cpuinit +static int smp_boot_one_cpu(int cpuid, struct task_struct *idle) { unsigned long timeout; @@ -472,7 +472,7 @@ smp_prepare_boot_cpu(void) { } -int __cpuinit +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { smp_boot_one_cpu(cpu, tidle); diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index affccb959a9e..be1fba334bd0 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -32,7 +32,7 @@ static int opDEC_fix; -static void __cpuinit +static void opDEC_check(void) { __asm__ __volatile__ ( @@ -1059,7 +1059,7 @@ do_entUnaUser(void __user * va, unsigned long opcode, return; } -void __cpuinit +void trap_init(void) { /* Tell PAL-code what global pointer we want in the kernel. */ -- GitLab From 60ffef065dd40b91f6f76af6c7510ddf23102f54 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 17 Jun 2013 15:43:14 -0400 Subject: [PATCH 2754/2900] parisc: delete __cpuinit usage from all users The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the parisc uses of the __cpuinit macros. [1] https://lkml.org/lkml/2013/5/20/589 Acked-by: James Bottomley Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Signed-off-by: Paul Gortmaker --- arch/parisc/kernel/firmware.c | 14 ++++++++------ arch/parisc/kernel/hardware.c | 2 +- arch/parisc/kernel/processor.c | 6 +++--- arch/parisc/kernel/smp.c | 8 ++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f65fa480c905..22395901d47b 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -150,7 +150,7 @@ static void convert_to_wide(unsigned long *addr) } #ifdef CONFIG_64BIT -void __cpuinit set_firmware_width_unlocked(void) +void set_firmware_width_unlocked(void) { int ret; @@ -167,7 +167,7 @@ void __cpuinit set_firmware_width_unlocked(void) * This function must be called before any pdc_* function that uses the * convert_to_wide function. */ -void __cpuinit set_firmware_width(void) +void set_firmware_width(void) { unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); @@ -175,11 +175,13 @@ void __cpuinit set_firmware_width(void) spin_unlock_irqrestore(&pdc_lock, flags); } #else -void __cpuinit set_firmware_width_unlocked(void) { +void set_firmware_width_unlocked(void) +{ return; } -void __cpuinit set_firmware_width(void) { +void set_firmware_width(void) +{ return; } #endif /*CONFIG_64BIT*/ @@ -301,7 +303,7 @@ int pdc_chassis_warn(unsigned long *warn) return retval; } -int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) +int pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; @@ -322,7 +324,7 @@ int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) * This PDC call returns the presence and status of all the coprocessors * attached to the processor. */ -int __cpuinit pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) +int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; unsigned long flags; diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index 872275659d98..06cb3992907e 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -1367,7 +1367,7 @@ const char *parisc_hardware_description(struct parisc_device_id *id) /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ -enum cpu_type __cpuinit +enum cpu_type parisc_get_cpu_type(unsigned long hversion) { struct hp_cpu_type_mask *ptr; diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 8a96c8ab9fe6..b68d977ce30f 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -73,7 +73,7 @@ extern int update_cr16_clocksource(void); /* from time.c */ * * FIXME: doesn't do much yet... */ -static void __cpuinit +static void init_percpu_prof(unsigned long cpunum) { struct cpuinfo_parisc *p; @@ -92,7 +92,7 @@ init_percpu_prof(unsigned long cpunum) * (return 1). If so, initialize the chip and tell other partners in crime * they have work to do. */ -static int __cpuinit processor_probe(struct parisc_device *dev) +static int processor_probe(struct parisc_device *dev) { unsigned long txn_addr; unsigned long cpuid; @@ -299,7 +299,7 @@ void __init collect_boot_cpu_data(void) * * o Enable CPU profiling hooks. */ -int __cpuinit init_per_cpu(int cpunum) +int init_per_cpu(int cpunum) { int ret; struct pdc_coproc_cfg coproc_cfg; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index e3614fb343e5..8a252f2d6c08 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -62,9 +62,9 @@ static int smp_debug_lvl = 0; volatile struct task_struct *smp_init_current_idle_task; /* track which CPU is booting */ -static volatile int cpu_now_booting __cpuinitdata; +static volatile int cpu_now_booting; -static int parisc_max_cpus __cpuinitdata = 1; +static int parisc_max_cpus = 1; static DEFINE_PER_CPU(spinlock_t, ipi_lock); @@ -328,7 +328,7 @@ void __init smp_callin(void) /* * Bring one cpu online. */ -int __cpuinit smp_boot_one_cpu(int cpuid, struct task_struct *idle) +int smp_boot_one_cpu(int cpuid, struct task_struct *idle) { const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); long timeout; @@ -424,7 +424,7 @@ void smp_cpus_done(unsigned int cpu_max) } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { if (cpu != 0 && cpu < parisc_max_cpus) smp_boot_one_cpu(cpu, tidle); -- GitLab From 078a55fc824c1633b3a507e4ad48b4637c1dfc18 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 13:38:59 +0000 Subject: [PATCH 2755/2900] MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code commit 3747069b25e419f6b51395f48127e9812abc3596 upstream. The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) and are flagged as __cpuinit -- so if we remove the __cpuinit from the arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit related content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. Here, we remove all the MIPS __cpuinit from C code and __CPUINIT from asm files. MIPS is interesting in this respect, because there are also uasm users hiding behind their own renamed versions of the __cpuinit macros. [1] https://lkml.org/lkml/2013/5/20/589 [ralf@linux-mips.org: Folded in Paul's followup fix.] Signed-off-by: Paul Gortmaker Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5494/ Patchwork: https://patchwork.linux-mips.org/patch/5495/ Patchwork: https://patchwork.linux-mips.org/patch/5509/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/setup.c | 2 +- arch/mips/cavium-octeon/octeon-irq.c | 12 +-- arch/mips/cavium-octeon/smp.c | 6 +- arch/mips/include/asm/uasm.h | 37 +++---- arch/mips/kernel/bmips_vec.S | 4 - arch/mips/kernel/cevt-bcm1480.c | 2 +- arch/mips/kernel/cevt-gic.c | 2 +- arch/mips/kernel/cevt-r4k.c | 2 +- arch/mips/kernel/cevt-sb1250.c | 2 +- arch/mips/kernel/cevt-smtc.c | 2 +- arch/mips/kernel/cpu-bugs64.c | 2 +- arch/mips/kernel/cpu-probe.c | 14 +-- arch/mips/kernel/head.S | 4 - arch/mips/kernel/smp-bmips.c | 6 +- arch/mips/kernel/smp-mt.c | 6 +- arch/mips/kernel/smp-up.c | 6 +- arch/mips/kernel/smp.c | 6 +- arch/mips/kernel/smtc.c | 2 +- arch/mips/kernel/spram.c | 14 +-- arch/mips/kernel/sync-r4k.c | 12 +-- arch/mips/kernel/traps.c | 12 +-- arch/mips/kernel/watch.c | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/lib/uncached.c | 2 +- arch/mips/mm/c-octeon.c | 6 +- arch/mips/mm/c-r3k.c | 8 +- arch/mips/mm/c-r4k.c | 34 +++--- arch/mips/mm/c-tx39.c | 2 +- arch/mips/mm/cache.c | 2 +- arch/mips/mm/cex-sb1.S | 4 - arch/mips/mm/page.c | 40 +++---- arch/mips/mm/sc-ip22.c | 2 +- arch/mips/mm/sc-mips.c | 2 +- arch/mips/mm/sc-r5k.c | 2 +- arch/mips/mm/sc-rm7k.c | 12 +-- arch/mips/mm/tlb-r3k.c | 2 +- arch/mips/mm/tlb-r4k.c | 4 +- arch/mips/mm/tlb-r8k.c | 4 +- arch/mips/mm/tlbex.c | 144 ++++++++++++-------------- arch/mips/mm/uasm-micromips.c | 10 +- arch/mips/mm/uasm-mips.c | 10 +- arch/mips/mm/uasm.c | 106 +++++++++---------- arch/mips/mti-malta/malta-smtc.c | 6 +- arch/mips/mti-malta/malta-time.c | 2 +- arch/mips/mti-sead3/sead3-time.c | 2 +- arch/mips/netlogic/common/smp.c | 4 +- arch/mips/netlogic/common/smpboot.S | 4 - arch/mips/netlogic/common/time.c | 2 +- arch/mips/netlogic/xlr/wakeup.c | 2 +- arch/mips/pci/pci-ip27.c | 2 +- arch/mips/pmcs-msp71xx/msp_smtc.c | 7 +- arch/mips/pmcs-msp71xx/msp_time.c | 2 +- arch/mips/pnx833x/common/interrupts.c | 2 +- arch/mips/powertv/time.c | 2 +- arch/mips/ralink/irq.c | 2 +- arch/mips/sgi-ip27/ip27-init.c | 4 +- arch/mips/sgi-ip27/ip27-smp.c | 6 +- arch/mips/sgi-ip27/ip27-timer.c | 6 +- arch/mips/sgi-ip27/ip27-xtalk.c | 6 +- arch/mips/sibyte/bcm1480/smp.c | 8 +- arch/mips/sibyte/sb1250/smp.c | 8 +- 61 files changed, 294 insertions(+), 338 deletions(-) diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 8be4e856b8b8..80f4ecd42b0d 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -182,7 +182,7 @@ const char *get_system_type(void) return ath79_sys_type; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 7181def6037a..9d36774bded1 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1095,7 +1095,7 @@ static void octeon_irq_ip3_ciu(void) static bool octeon_irq_use_ip4; -static void __cpuinit octeon_irq_local_enable_ip4(void *arg) +static void octeon_irq_local_enable_ip4(void *arg) { set_c0_status(STATUSF_IP4); } @@ -1110,21 +1110,21 @@ static void (*octeon_irq_ip2)(void); static void (*octeon_irq_ip3)(void); static void (*octeon_irq_ip4)(void); -void __cpuinitdata (*octeon_irq_setup_secondary)(void); +void (*octeon_irq_setup_secondary)(void); -void __cpuinit octeon_irq_set_ip4_handler(octeon_irq_ip4_handler_t h) +void octeon_irq_set_ip4_handler(octeon_irq_ip4_handler_t h) { octeon_irq_ip4 = h; octeon_irq_use_ip4 = true; on_each_cpu(octeon_irq_local_enable_ip4, NULL, 1); } -static void __cpuinit octeon_irq_percpu_enable(void) +static void octeon_irq_percpu_enable(void) { irq_cpu_online(); } -static void __cpuinit octeon_irq_init_ciu_percpu(void) +static void octeon_irq_init_ciu_percpu(void) { int coreid = cvmx_get_core_num(); @@ -1167,7 +1167,7 @@ static void octeon_irq_init_ciu2_percpu(void) cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid)); } -static void __cpuinit octeon_irq_setup_secondary_ciu(void) +static void octeon_irq_setup_secondary_ciu(void) { octeon_irq_init_ciu_percpu(); octeon_irq_percpu_enable(); diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 295137dfdc37..138cc80c5928 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -173,7 +173,7 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle) * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -static void __cpuinit octeon_init_secondary(void) +static void octeon_init_secondary(void) { unsigned int sr; @@ -375,7 +375,7 @@ static int octeon_update_boot_vector(unsigned int cpu) return 0; } -static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, +static int octeon_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -394,7 +394,7 @@ static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static int __cpuinit register_cavium_notifier(void) +static int register_cavium_notifier(void) { hotcpu_notifier(octeon_cpu_callback, 0); return 0; diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 370d967725c2..c33a9564fb41 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -13,12 +13,8 @@ #ifdef CONFIG_EXPORT_UASM #include -#define __uasminit -#define __uasminitdata #define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym) #else -#define __uasminit __cpuinit -#define __uasminitdata __cpuinitdata #define UASM_EXPORT_SYMBOL(sym) #endif @@ -54,43 +50,36 @@ #endif #define Ip_u1u2u3(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u3u1u2(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u1u2s3(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2s3u1(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c) +void ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c) #define Ip_u2u1s3(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c) #define Ip_u2u1msbu3(op) \ -void __uasminit \ -ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ unsigned int d) #define Ip_u1u2(op) \ -void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) #define Ip_u1s2(op) \ -void __uasminit ISAOPC(op)(u32 **buf, unsigned int a, signed int b) +void ISAOPC(op)(u32 **buf, unsigned int a, signed int b) -#define Ip_u1(op) void __uasminit ISAOPC(op)(u32 **buf, unsigned int a) +#define Ip_u1(op) void ISAOPC(op)(u32 **buf, unsigned int a) -#define Ip_0(op) void __uasminit ISAOPC(op)(u32 **buf) +#define Ip_0(op) void ISAOPC(op)(u32 **buf) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); @@ -163,7 +152,7 @@ struct uasm_label { int lab; }; -void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, +void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid); #ifdef CONFIG_64BIT int ISAFUNC(uasm_in_compat_space_p)(long addr); @@ -174,7 +163,7 @@ void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr); void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr); #define UASM_L_LA(lb) \ -static inline void __uasminit ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \ +static inline void ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \ { \ ISAFUNC(uasm_build_label)(lab, addr, label##lb); \ } diff --git a/arch/mips/kernel/bmips_vec.S b/arch/mips/kernel/bmips_vec.S index 64c4fd62cf08..f739aedcb509 100644 --- a/arch/mips/kernel/bmips_vec.S +++ b/arch/mips/kernel/bmips_vec.S @@ -28,8 +28,6 @@ .set mips0 .endm - __CPUINIT - /*********************************************************************** * Alternate CPU1 startup vector for BMIPS4350 * @@ -216,8 +214,6 @@ END(bmips_smp_int_vec) * Certain CPUs support extending kseg0 to 1024MB. ***********************************************************************/ - __CPUINIT - LEAF(bmips_enable_xks01) #if defined(CONFIG_XKS01) diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 15f618b40cf6..7976457184b1 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -109,7 +109,7 @@ static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); static DEFINE_PER_CPU(char [18], sibyte_hpt_name); -void __cpuinit sb1480_clockevent_init(void) +void sb1480_clockevent_init(void) { unsigned int cpu = smp_processor_id(); unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu; diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c index 730eaf92c018..594cbbf16d62 100644 --- a/arch/mips/kernel/cevt-gic.c +++ b/arch/mips/kernel/cevt-gic.c @@ -59,7 +59,7 @@ void gic_event_handler(struct clock_event_device *dev) { } -int __cpuinit gic_clockevent_init(void) +int gic_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 02033eaf8825..50d3f5a8d6bb 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -171,7 +171,7 @@ int c0_compare_int_usable(void) } #ifndef CONFIG_MIPS_MT_SMTC -int __cpuinit r4k_clockevent_init(void) +int r4k_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 200f2778bf36..5ea6d6b1de15 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -107,7 +107,7 @@ static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); static DEFINE_PER_CPU(char [18], sibyte_hpt_name); -void __cpuinit sb1250_clockevent_init(void) +void sb1250_clockevent_init(void) { unsigned int cpu = smp_processor_id(); unsigned int irq = K_INT_TIMER_0 + cpu; diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c index 9de5ed7ef1a3..b6cf0a60d896 100644 --- a/arch/mips/kernel/cevt-smtc.c +++ b/arch/mips/kernel/cevt-smtc.c @@ -248,7 +248,7 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id) } -int __cpuinit smtc_clockevent_init(void) +int smtc_clockevent_init(void) { uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index 0c61df281ce6..2d80b5f1aeae 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -168,7 +168,7 @@ static inline void check_mult_sh(void) panic(bug64hit, !R4000_WAR ? r4kwar : nowar); } -static volatile int daddi_ov __cpuinitdata; +static volatile int daddi_ov; asmlinkage void __init do_daddi_ov(struct pt_regs *regs) { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index c7b1b3c5a761..4c6167a17875 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -27,7 +27,7 @@ #include #include -static int __cpuinitdata mips_fpu_disabled; +static int mips_fpu_disabled; static int __init fpu_disable(char *s) { @@ -39,7 +39,7 @@ static int __init fpu_disable(char *s) __setup("nofpu", fpu_disable); -int __cpuinitdata mips_dsp_disabled; +int mips_dsp_disabled; static int __init dsp_disable(char *s) { @@ -134,7 +134,7 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) #endif } -static void __cpuinit set_isa(struct cpuinfo_mips *c, unsigned int isa) +static void set_isa(struct cpuinfo_mips *c, unsigned int isa) { switch (isa) { case MIPS_CPU_ISA_M64R2: @@ -159,7 +159,7 @@ static void __cpuinit set_isa(struct cpuinfo_mips *c, unsigned int isa) } } -static char unknown_isa[] __cpuinitdata = KERN_ERR \ +static char unknown_isa[] = KERN_ERR \ "Unsupported ISA type, c0.config0: %d."; static inline unsigned int decode_config0(struct cpuinfo_mips *c) @@ -290,7 +290,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) return config4 & MIPS_CONF_M; } -static void __cpuinit decode_configs(struct cpuinfo_mips *c) +static void decode_configs(struct cpuinfo_mips *c) { int ok; @@ -962,7 +962,7 @@ EXPORT_SYMBOL(__ua_limit); const char *__cpu_name[NR_CPUS]; const char *__elf_platform; -__cpuinit void cpu_probe(void) +void cpu_probe(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); @@ -1047,7 +1047,7 @@ __cpuinit void cpu_probe(void) #endif } -__cpuinit void cpu_report(void) +void cpu_report(void) { struct cpuinfo_mips *c = ¤t_cpu_data; diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 099912324423..7b6a5b3e3acf 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -158,8 +158,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point j start_kernel END(kernel_entry) - __CPUINIT - #ifdef CONFIG_SMP /* * SMP slave cpus entry point. Board specific code for bootstrap calls this @@ -188,5 +186,3 @@ NESTED(smp_bootstrap, 16, sp) j start_secondary END(smp_bootstrap) #endif /* CONFIG_SMP */ - - __FINIT diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index aea6c0885838..76f31353e718 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -398,7 +398,7 @@ struct plat_smp_ops bmips_smp_ops = { * UP BMIPS systems as well. ***********************************************************************/ -static void __cpuinit bmips_wr_vec(unsigned long dst, char *start, char *end) +static void bmips_wr_vec(unsigned long dst, char *start, char *end) { memcpy((void *)dst, start, end - start); dma_cache_wback((unsigned long)start, end - start); @@ -406,7 +406,7 @@ static void __cpuinit bmips_wr_vec(unsigned long dst, char *start, char *end) instruction_hazard(); } -static inline void __cpuinit bmips_nmi_handler_setup(void) +static inline void bmips_nmi_handler_setup(void) { bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec, &bmips_reset_nmi_vec_end); @@ -414,7 +414,7 @@ static inline void __cpuinit bmips_nmi_handler_setup(void) &bmips_smp_int_vec_end); } -void __cpuinit bmips_ebase_setup(void) +void bmips_ebase_setup(void) { unsigned long new_ebase = ebase; void __iomem __maybe_unused *cbr; diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 3e5164c11cac..57a3f7a2b370 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -149,7 +149,7 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) vsmp_send_ipi_single(i, action); } -static void __cpuinit vsmp_init_secondary(void) +static void vsmp_init_secondary(void) { #ifdef CONFIG_IRQ_GIC /* This is Malta specific: IPI,performance and timer interrupts */ @@ -162,7 +162,7 @@ static void __cpuinit vsmp_init_secondary(void) STATUSF_IP6 | STATUSF_IP7); } -static void __cpuinit vsmp_smp_finish(void) +static void vsmp_smp_finish(void) { /* CDFIXME: remove this? */ write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); @@ -188,7 +188,7 @@ static void vsmp_cpus_done(void) * (unsigned long)idle->thread_info the gp * assumes a 1:1 mapping of TC => VPE */ -static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle) +static void vsmp_boot_secondary(int cpu, struct task_struct *idle) { struct thread_info *gp = task_thread_info(idle); dvpe(); diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c index 00500fea2750..7fde3e4d978f 100644 --- a/arch/mips/kernel/smp-up.c +++ b/arch/mips/kernel/smp-up.c @@ -28,11 +28,11 @@ static inline void up_send_ipi_mask(const struct cpumask *mask, * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -static void __cpuinit up_init_secondary(void) +static void up_init_secondary(void) { } -static void __cpuinit up_smp_finish(void) +static void up_smp_finish(void) { } @@ -44,7 +44,7 @@ static void up_cpus_done(void) /* * Firmware CPU startup hook */ -static void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle) +static void up_boot_secondary(int cpu, struct task_struct *idle) { } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 6e7862ab46cc..5c208ed8f856 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -86,7 +86,7 @@ static inline void set_cpu_sibling_map(int cpu) struct plat_smp_ops *mp_ops; EXPORT_SYMBOL(mp_ops); -__cpuinit void register_smp_ops(struct plat_smp_ops *ops) +void register_smp_ops(struct plat_smp_ops *ops) { if (mp_ops) printk(KERN_WARNING "Overriding previously set SMP ops\n"); @@ -98,7 +98,7 @@ __cpuinit void register_smp_ops(struct plat_smp_ops *ops) * First C code run on the secondary CPUs after being started up by * the master. */ -asmlinkage __cpuinit void start_secondary(void) +asmlinkage void start_secondary(void) { unsigned int cpu; @@ -197,7 +197,7 @@ void smp_prepare_boot_cpu(void) cpu_set(0, cpu_callin_map); } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { mp_ops->boot_secondary(cpu, tidle); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 75a4fd709841..dfc1b911be04 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -645,7 +645,7 @@ void smtc_prepare_cpus(int cpus) * (unsigned long)idle->thread_info the gp * */ -void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) +void smtc_boot_secondary(int cpu, struct task_struct *idle) { extern u32 kernelsp[NR_CPUS]; unsigned long flags; diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c index 6af08d896e20..93f86817f20a 100644 --- a/arch/mips/kernel/spram.c +++ b/arch/mips/kernel/spram.c @@ -37,7 +37,7 @@ /* * Different semantics to the set_c0_* function built by __BUILD_SET_C0 */ -static __cpuinit unsigned int bis_c0_errctl(unsigned int set) +static unsigned int bis_c0_errctl(unsigned int set) { unsigned int res; res = read_c0_errctl(); @@ -45,7 +45,7 @@ static __cpuinit unsigned int bis_c0_errctl(unsigned int set) return res; } -static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data) +static void ispram_store_tag(unsigned int offset, unsigned int data) { unsigned int errctl; @@ -64,7 +64,7 @@ static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data) } -static __cpuinit unsigned int ispram_load_tag(unsigned int offset) +static unsigned int ispram_load_tag(unsigned int offset) { unsigned int data; unsigned int errctl; @@ -82,7 +82,7 @@ static __cpuinit unsigned int ispram_load_tag(unsigned int offset) return data; } -static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data) +static void dspram_store_tag(unsigned int offset, unsigned int data) { unsigned int errctl; @@ -98,7 +98,7 @@ static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data) } -static __cpuinit unsigned int dspram_load_tag(unsigned int offset) +static unsigned int dspram_load_tag(unsigned int offset) { unsigned int data; unsigned int errctl; @@ -115,7 +115,7 @@ static __cpuinit unsigned int dspram_load_tag(unsigned int offset) return data; } -static __cpuinit void probe_spram(char *type, +static void probe_spram(char *type, unsigned int base, unsigned int (*read)(unsigned int), void (*write)(unsigned int, unsigned int)) @@ -196,7 +196,7 @@ static __cpuinit void probe_spram(char *type, offset += 2 * SPRAM_TAG_STRIDE; } } -void __cpuinit spram_config(void) +void spram_config(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config0; diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 1ff43d5ac2c4..84536bf4a154 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -20,15 +20,15 @@ #include #include -static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); +static atomic_t count_start_flag = ATOMIC_INIT(0); +static atomic_t count_count_start = ATOMIC_INIT(0); +static atomic_t count_count_stop = ATOMIC_INIT(0); +static atomic_t count_reference = ATOMIC_INIT(0); #define COUNTON 100 #define NR_LOOPS 5 -void __cpuinit synchronise_count_master(int cpu) +void synchronise_count_master(int cpu) { int i; unsigned long flags; @@ -106,7 +106,7 @@ void __cpuinit synchronise_count_master(int cpu) printk("done.\n"); } -void __cpuinit synchronise_count_slave(int cpu) +void synchronise_count_slave(int cpu) { int i; unsigned int initcount; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0903d70b2cfe..c89568f88bfd 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -90,7 +90,7 @@ void (*board_nmi_handler_setup)(void); void (*board_ejtag_handler_setup)(void); void (*board_bind_eic_interrupt)(int irq, int regset); void (*board_ebase_setup)(void); -void __cpuinitdata(*board_cache_error_setup)(void); +void(*board_cache_error_setup)(void); static void show_raw_backtrace(unsigned long reg29) { @@ -1682,7 +1682,7 @@ int cp0_compare_irq_shift; int cp0_perfcount_irq; EXPORT_SYMBOL_GPL(cp0_perfcount_irq); -static int __cpuinitdata noulri; +static int noulri; static int __init ulri_disable(char *s) { @@ -1693,7 +1693,7 @@ static int __init ulri_disable(char *s) } __setup("noulri", ulri_disable); -void __cpuinit per_cpu_trap_init(bool is_boot_cpu) +void per_cpu_trap_init(bool is_boot_cpu) { unsigned int cpu = smp_processor_id(); unsigned int status_set = ST0_CU0; @@ -1810,7 +1810,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu) } /* Install CPU exception handler */ -void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size) +void set_handler(unsigned long offset, void *addr, unsigned long size) { #ifdef CONFIG_CPU_MICROMIPS memcpy((void *)(ebase + offset), ((unsigned char *)addr - 1), size); @@ -1820,7 +1820,7 @@ void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size) local_flush_icache_range(ebase + offset, ebase + offset + size); } -static char panic_null_cerr[] __cpuinitdata = +static char panic_null_cerr[] = "Trying to set NULL cache error exception handler"; /* @@ -1828,7 +1828,7 @@ static char panic_null_cerr[] __cpuinitdata = * This is suitable only for the cache error exception which is the only * exception handler that is being run uncached. */ -void __cpuinit set_uncached_handler(unsigned long offset, void *addr, +void set_uncached_handler(unsigned long offset, void *addr, unsigned long size) { unsigned long uncached_ebase = CKSEG1ADDR(ebase); diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index cbdc4de85bb4..2a03abb5bd2c 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -100,7 +100,7 @@ void mips_clear_watch_registers(void) } } -__cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) +void mips_probe_watch_registers(struct cpuinfo_mips *c) { unsigned int t; diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 51194875f158..eb3e18659630 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -461,7 +461,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) return 0; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return MIPS_CPU_TIMER_IRQ; } diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c index 65e3dfc4e585..d8522f8e842a 100644 --- a/arch/mips/lib/uncached.c +++ b/arch/mips/lib/uncached.c @@ -36,7 +36,7 @@ * values, so we can avoid sharing the same stack area between a cached * and the uncached mode. */ -unsigned long __cpuinit run_uncached(void *func) +unsigned long run_uncached(void *func) { register long sp __asm__("$sp"); register long ret __asm__("$2"); diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 8557fb552863..a0bcdbb81d41 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -180,7 +180,7 @@ static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size) * Probe Octeon's caches * */ -static void __cpuinit probe_octeon(void) +static void probe_octeon(void) { unsigned long icache_size; unsigned long dcache_size; @@ -251,7 +251,7 @@ static void __cpuinit probe_octeon(void) } } -static void __cpuinit octeon_cache_error_setup(void) +static void octeon_cache_error_setup(void) { extern char except_vec2_octeon; set_handler(0x100, &except_vec2_octeon, 0x80); @@ -261,7 +261,7 @@ static void __cpuinit octeon_cache_error_setup(void) * Setup the Octeon cache flush routines * */ -void __cpuinit octeon_cache_init(void) +void octeon_cache_init(void) { probe_octeon(); diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 704dc735a59d..2fcde0c8ea02 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -26,7 +26,7 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags) +unsigned long r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; volatile unsigned long *p; @@ -61,7 +61,7 @@ unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags) return size * sizeof(*p); } -unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags) +unsigned long r3k_cache_lsize(unsigned long ca_flags) { unsigned long flags, status, lsize, i; volatile unsigned long *p; @@ -90,7 +90,7 @@ unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags) return lsize * sizeof(*p); } -static void __cpuinit r3k_probe_cache(void) +static void r3k_probe_cache(void) { dcache_size = r3k_cache_size(ST0_ISC); if (dcache_size) @@ -312,7 +312,7 @@ static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) r3k_flush_dcache_range(start, start + size); } -void __cpuinit r3k_cache_init(void) +void r3k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 21813beec7a5..f749f687ee87 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -107,7 +107,7 @@ static inline void r4k_blast_dcache_page_dc64(unsigned long addr) blast_dcache64_page(addr); } -static void __cpuinit r4k_blast_dcache_page_setup(void) +static void r4k_blast_dcache_page_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -123,7 +123,7 @@ static void __cpuinit r4k_blast_dcache_page_setup(void) static void (* r4k_blast_dcache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) +static void r4k_blast_dcache_page_indexed_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -140,7 +140,7 @@ static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) void (* r4k_blast_dcache)(void); EXPORT_SYMBOL(r4k_blast_dcache); -static void __cpuinit r4k_blast_dcache_setup(void) +static void r4k_blast_dcache_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -227,7 +227,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page) static void (* r4k_blast_icache_page)(unsigned long addr); -static void __cpuinit r4k_blast_icache_page_setup(void) +static void r4k_blast_icache_page_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -244,7 +244,7 @@ static void __cpuinit r4k_blast_icache_page_setup(void) static void (* r4k_blast_icache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_icache_page_indexed_setup(void) +static void r4k_blast_icache_page_indexed_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -269,7 +269,7 @@ static void __cpuinit r4k_blast_icache_page_indexed_setup(void) void (* r4k_blast_icache)(void); EXPORT_SYMBOL(r4k_blast_icache); -static void __cpuinit r4k_blast_icache_setup(void) +static void r4k_blast_icache_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -290,7 +290,7 @@ static void __cpuinit r4k_blast_icache_setup(void) static void (* r4k_blast_scache_page)(unsigned long addr); -static void __cpuinit r4k_blast_scache_page_setup(void) +static void r4k_blast_scache_page_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -308,7 +308,7 @@ static void __cpuinit r4k_blast_scache_page_setup(void) static void (* r4k_blast_scache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_scache_page_indexed_setup(void) +static void r4k_blast_scache_page_indexed_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -326,7 +326,7 @@ static void __cpuinit r4k_blast_scache_page_indexed_setup(void) static void (* r4k_blast_scache)(void); -static void __cpuinit r4k_blast_scache_setup(void) +static void r4k_blast_scache_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -797,11 +797,11 @@ static inline void alias_74k_erratum(struct cpuinfo_mips *c) } } -static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", +static char *way_string[] = { NULL, "direct mapped", "2-way", "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" }; -static void __cpuinit probe_pcache(void) +static void probe_pcache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1119,7 +1119,7 @@ static void __cpuinit probe_pcache(void) * executes in KSEG1 space or else you will crash and burn badly. You have * been warned. */ -static int __cpuinit probe_scache(void) +static int probe_scache(void) { unsigned long flags, addr, begin, end, pow2; unsigned int config = read_c0_config(); @@ -1196,7 +1196,7 @@ extern int r5k_sc_init(void); extern int rm7k_sc_init(void); extern int mips_sc_init(void); -static void __cpuinit setup_scache(void) +static void setup_scache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1329,7 +1329,7 @@ static void nxp_pr4450_fixup_config(void) NXP_BARRIER(); } -static int __cpuinitdata cca = -1; +static int cca = -1; static int __init cca_setup(char *str) { @@ -1340,7 +1340,7 @@ static int __init cca_setup(char *str) early_param("cca", cca_setup); -static void __cpuinit coherency_setup(void) +static void coherency_setup(void) { if (cca < 0 || cca > 7) cca = read_c0_config() & CONF_CM_CMASK; @@ -1380,7 +1380,7 @@ static void __cpuinit coherency_setup(void) } } -static void __cpuinit r4k_cache_error_setup(void) +static void r4k_cache_error_setup(void) { extern char __weak except_vec2_generic; extern char __weak except_vec2_sb1; @@ -1398,7 +1398,7 @@ static void __cpuinit r4k_cache_error_setup(void) } } -void __cpuinit r4k_cache_init(void) +void r4k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index ba9da270289f..8d909dbbf37f 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -344,7 +344,7 @@ static __init void tx39_probe_cache(void) } } -void __cpuinit tx39_cache_init(void) +void tx39_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 5aeb3eb0b72f..15f813c303b4 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -182,7 +182,7 @@ static inline void setup_protection_map(void) } } -void __cpuinit cpu_cache_init(void) +void cpu_cache_init(void) { if (cpu_has_3k_cache) { extern void __weak r3k_cache_init(void); diff --git a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S index fe1d887e8d70..191cf6e0c725 100644 --- a/arch/mips/mm/cex-sb1.S +++ b/arch/mips/mm/cex-sb1.S @@ -49,8 +49,6 @@ * (0x170-0x17f) are used to preserve k0, k1, and ra. */ - __CPUINIT - LEAF(except_vec2_sb1) /* * If this error is recoverable, we need to exit the handler @@ -142,8 +140,6 @@ unrecoverable: END(except_vec2_sb1) - __FINIT - LEAF(handle_vec2_sb1) mfc0 k0,CP0_CONFIG li k1,~CONF_CM_CMASK diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index 2c0bd580b9da..218c2109a55d 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -66,29 +66,29 @@ UASM_L_LA(_copy_pref_both) UASM_L_LA(_copy_pref_store) /* We need one branch and therefore one relocation per target label. */ -static struct uasm_label __cpuinitdata labels[5]; -static struct uasm_reloc __cpuinitdata relocs[5]; +static struct uasm_label labels[5]; +static struct uasm_reloc relocs[5]; #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010) #define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020) -static int pref_bias_clear_store __cpuinitdata; -static int pref_bias_copy_load __cpuinitdata; -static int pref_bias_copy_store __cpuinitdata; +static int pref_bias_clear_store; +static int pref_bias_copy_load; +static int pref_bias_copy_store; -static u32 pref_src_mode __cpuinitdata; -static u32 pref_dst_mode __cpuinitdata; +static u32 pref_src_mode; +static u32 pref_dst_mode; -static int clear_word_size __cpuinitdata; -static int copy_word_size __cpuinitdata; +static int clear_word_size; +static int copy_word_size; -static int half_clear_loop_size __cpuinitdata; -static int half_copy_loop_size __cpuinitdata; +static int half_clear_loop_size; +static int half_copy_loop_size; -static int cache_line_size __cpuinitdata; +static int cache_line_size; #define cache_line_mask() (cache_line_size - 1) -static inline void __cpuinit +static inline void pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off) { if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) { @@ -108,7 +108,7 @@ pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off) } } -static void __cpuinit set_prefetch_parameters(void) +static void set_prefetch_parameters(void) { if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) clear_word_size = 8; @@ -199,7 +199,7 @@ static void __cpuinit set_prefetch_parameters(void) 4 * copy_word_size)); } -static void __cpuinit build_clear_store(u32 **buf, int off) +static void build_clear_store(u32 **buf, int off) { if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) { uasm_i_sd(buf, ZERO, off, A0); @@ -208,7 +208,7 @@ static void __cpuinit build_clear_store(u32 **buf, int off) } } -static inline void __cpuinit build_clear_pref(u32 **buf, int off) +static inline void build_clear_pref(u32 **buf, int off) { if (off & cache_line_mask()) return; @@ -240,7 +240,7 @@ extern u32 __clear_page_end; extern u32 __copy_page_start; extern u32 __copy_page_end; -void __cpuinit build_clear_page(void) +void build_clear_page(void) { int off; u32 *buf = &__clear_page_start; @@ -333,7 +333,7 @@ void __cpuinit build_clear_page(void) pr_debug("\t.set pop\n"); } -static void __cpuinit build_copy_load(u32 **buf, int reg, int off) +static void build_copy_load(u32 **buf, int reg, int off) { if (cpu_has_64bit_gp_regs) { uasm_i_ld(buf, reg, off, A1); @@ -342,7 +342,7 @@ static void __cpuinit build_copy_load(u32 **buf, int reg, int off) } } -static void __cpuinit build_copy_store(u32 **buf, int reg, int off) +static void build_copy_store(u32 **buf, int reg, int off) { if (cpu_has_64bit_gp_regs) { uasm_i_sd(buf, reg, off, A0); @@ -387,7 +387,7 @@ static inline void build_copy_store_pref(u32 **buf, int off) } } -void __cpuinit build_copy_page(void) +void build_copy_page(void) { int off; u32 *buf = &__copy_page_start; diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c index c6aaed934d53..dc7c5a5214a9 100644 --- a/arch/mips/mm/sc-ip22.c +++ b/arch/mips/mm/sc-ip22.c @@ -167,7 +167,7 @@ static struct bcache_ops indy_sc_ops = { .bc_inv = indy_sc_wback_invalidate }; -void __cpuinit indy_sc_init(void) +void indy_sc_init(void) { if (indy_sc_probe()) { indy_sc_enable(); diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index df96da7e939b..5d01392e3518 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -132,7 +132,7 @@ static inline int __init mips_sc_probe(void) return 1; } -int __cpuinit mips_sc_init(void) +int mips_sc_init(void) { int found = mips_sc_probe(); if (found) { diff --git a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c index 8bc67720e145..0216ed6eaa2a 100644 --- a/arch/mips/mm/sc-r5k.c +++ b/arch/mips/mm/sc-r5k.c @@ -98,7 +98,7 @@ static struct bcache_ops r5k_sc_ops = { .bc_inv = r5k_dma_cache_inv_sc }; -void __cpuinit r5k_sc_init(void) +void r5k_sc_init(void) { if (r5k_sc_probe()) { r5k_sc_enable(); diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 274af3be1442..aaffbba33706 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -104,7 +104,7 @@ static void blast_rm7k_tcache(void) /* * This function is executed in uncached address space. */ -static __cpuinit void __rm7k_tc_enable(void) +static void __rm7k_tc_enable(void) { int i; @@ -117,7 +117,7 @@ static __cpuinit void __rm7k_tc_enable(void) cache_op(Index_Store_Tag_T, CKSEG0ADDR(i)); } -static __cpuinit void rm7k_tc_enable(void) +static void rm7k_tc_enable(void) { if (read_c0_config() & RM7K_CONF_TE) return; @@ -130,7 +130,7 @@ static __cpuinit void rm7k_tc_enable(void) /* * This function is executed in uncached address space. */ -static __cpuinit void __rm7k_sc_enable(void) +static void __rm7k_sc_enable(void) { int i; @@ -143,7 +143,7 @@ static __cpuinit void __rm7k_sc_enable(void) cache_op(Index_Store_Tag_SD, CKSEG0ADDR(i)); } -static __cpuinit void rm7k_sc_enable(void) +static void rm7k_sc_enable(void) { if (read_c0_config() & RM7K_CONF_SE) return; @@ -184,7 +184,7 @@ static struct bcache_ops rm7k_sc_ops = { * This is a probing function like the one found in c-r4k.c, we look for the * wrap around point with different addresses. */ -static __cpuinit void __probe_tcache(void) +static void __probe_tcache(void) { unsigned long flags, addr, begin, end, pow2; @@ -226,7 +226,7 @@ static __cpuinit void __probe_tcache(void) local_irq_restore(flags); } -void __cpuinit rm7k_sc_init(void) +void rm7k_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index a63d1ed0827f..9aca10994cd2 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -276,7 +276,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, } } -void __cpuinit tlb_init(void) +void tlb_init(void) { local_flush_tlb_all(); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index c643de4c473a..00b26a67a06d 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -389,7 +389,7 @@ int __init has_transparent_hugepage(void) #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ -static int __cpuinitdata ntlb; +static int ntlb; static int __init set_ntlb(char *str) { get_option(&str, &ntlb); @@ -398,7 +398,7 @@ static int __init set_ntlb(char *str) __setup("ntlb=", set_ntlb); -void __cpuinit tlb_init(void) +void tlb_init(void) { /* * You should never change this register: diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 91c2499f806a..6a99733a4440 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -213,14 +213,14 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) local_irq_restore(flags); } -static void __cpuinit probe_tlb(unsigned long config) +static void probe_tlb(unsigned long config) { struct cpuinfo_mips *c = ¤t_cpu_data; c->tlbsize = 3 * 128; /* 3 sets each 128 entries */ } -void __cpuinit tlb_init(void) +void tlb_init(void) { unsigned int config = read_c0_config(); unsigned long status; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 9ab0f907a52c..34fce2b2095b 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -136,7 +136,7 @@ static int scratchpad_offset(int i) * why; it's not an issue caused by the core RTL. * */ -static int __cpuinit m4kc_tlbp_war(void) +static int m4kc_tlbp_war(void) { return (current_cpu_data.processor_id & 0xffff00) == (PRID_COMP_MIPS | PRID_IMP_4KC); @@ -181,11 +181,9 @@ UASM_L_LA(_large_segbits_fault) UASM_L_LA(_tlb_huge_update) #endif -static int __cpuinitdata hazard_instance; +static int hazard_instance; -static void __cpuinit uasm_bgezl_hazard(u32 **p, - struct uasm_reloc **r, - int instance) +static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance) { switch (instance) { case 0 ... 7: @@ -196,9 +194,7 @@ static void __cpuinit uasm_bgezl_hazard(u32 **p, } } -static void __cpuinit uasm_bgezl_label(struct uasm_label **l, - u32 **p, - int instance) +static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance) { switch (instance) { case 0 ... 7: @@ -295,15 +291,15 @@ static inline void dump_handler(const char *symbol, const u32 *handler, int coun * We deliberately chose a buffer size of 128, so we won't scribble * over anything important on overflow before we panic. */ -static u32 tlb_handler[128] __cpuinitdata; +static u32 tlb_handler[128]; /* simply assume worst case size for labels and relocs */ -static struct uasm_label labels[128] __cpuinitdata; -static struct uasm_reloc relocs[128] __cpuinitdata; +static struct uasm_label labels[128]; +static struct uasm_reloc relocs[128]; -static int check_for_high_segbits __cpuinitdata; +static int check_for_high_segbits; -static unsigned int kscratch_used_mask __cpuinitdata; +static unsigned int kscratch_used_mask; static inline int __maybe_unused c0_kscratch(void) { @@ -316,7 +312,7 @@ static inline int __maybe_unused c0_kscratch(void) } } -static int __cpuinit allocate_kscratch(void) +static int allocate_kscratch(void) { int r; unsigned int a = cpu_data[0].kscratch_mask & ~kscratch_used_mask; @@ -333,11 +329,11 @@ static int __cpuinit allocate_kscratch(void) return r; } -static int scratch_reg __cpuinitdata; -static int pgd_reg __cpuinitdata; +static int scratch_reg; +static int pgd_reg; enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch}; -static struct work_registers __cpuinit build_get_work_registers(u32 **p) +static struct work_registers build_get_work_registers(u32 **p) { struct work_registers r; @@ -393,7 +389,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) return r; } -static void __cpuinit build_restore_work_registers(u32 **p) +static void build_restore_work_registers(u32 **p) { if (scratch_reg >= 0) { UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); @@ -418,7 +414,7 @@ extern unsigned long pgd_current[]; /* * The R3000 TLB handler is simple. */ -static void __cpuinit build_r3000_tlb_refill_handler(void) +static void build_r3000_tlb_refill_handler(void) { long pgdc = (long)pgd_current; u32 *p; @@ -463,7 +459,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void) * other one.To keep things simple, we first assume linear space, * then we relocate it to the final handler layout as needed. */ -static u32 final_handler[64] __cpuinitdata; +static u32 final_handler[64]; /* * Hazards @@ -487,7 +483,7 @@ static u32 final_handler[64] __cpuinitdata; * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ -static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) +static void __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { /* Found by experiment: R4600 v2.0/R4700 needs this, too. */ @@ -511,9 +507,9 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) */ enum tlb_write_entry { tlb_random, tlb_indexed }; -static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, - struct uasm_reloc **r, - enum tlb_write_entry wmode) +static void build_tlb_write_entry(u32 **p, struct uasm_label **l, + struct uasm_reloc **r, + enum tlb_write_entry wmode) { void(*tlbw)(u32 **) = NULL; @@ -647,8 +643,8 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, } } -static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p, - unsigned int reg) +static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, + unsigned int reg) { if (cpu_has_rixi) { UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL)); @@ -663,11 +659,9 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p, #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT -static __cpuinit void build_restore_pagemask(u32 **p, - struct uasm_reloc **r, - unsigned int tmp, - enum label_id lid, - int restore_scratch) +static void build_restore_pagemask(u32 **p, struct uasm_reloc **r, + unsigned int tmp, enum label_id lid, + int restore_scratch) { if (restore_scratch) { /* Reset default page size */ @@ -706,12 +700,11 @@ static __cpuinit void build_restore_pagemask(u32 **p, } } -static __cpuinit void build_huge_tlb_write_entry(u32 **p, - struct uasm_label **l, - struct uasm_reloc **r, - unsigned int tmp, - enum tlb_write_entry wmode, - int restore_scratch) +static void build_huge_tlb_write_entry(u32 **p, struct uasm_label **l, + struct uasm_reloc **r, + unsigned int tmp, + enum tlb_write_entry wmode, + int restore_scratch) { /* Set huge page tlb entry size */ uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16); @@ -726,9 +719,9 @@ static __cpuinit void build_huge_tlb_write_entry(u32 **p, /* * Check if Huge PTE is present, if so then jump to LABEL. */ -static void __cpuinit +static void build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp, - unsigned int pmd, int lid) + unsigned int pmd, int lid) { UASM_i_LW(p, tmp, 0, pmd); if (use_bbit_insns()) { @@ -739,9 +732,8 @@ build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp, } } -static __cpuinit void build_huge_update_entries(u32 **p, - unsigned int pte, - unsigned int tmp) +static void build_huge_update_entries(u32 **p, unsigned int pte, + unsigned int tmp) { int small_sequence; @@ -771,11 +763,10 @@ static __cpuinit void build_huge_update_entries(u32 **p, UASM_i_MTC0(p, pte, C0_ENTRYLO1); /* load it */ } -static __cpuinit void build_huge_handler_tail(u32 **p, - struct uasm_reloc **r, - struct uasm_label **l, - unsigned int pte, - unsigned int ptr) +static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, + struct uasm_label **l, + unsigned int pte, + unsigned int ptr) { #ifdef CONFIG_SMP UASM_i_SC(p, pte, 0, ptr); @@ -794,7 +785,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pmd entry. */ -static void __cpuinit +static void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) { @@ -886,7 +877,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * BVADDR is the faulting address, PTR is scratch. * PTR will hold the pgd for vmalloc. */ -static void __cpuinit +static void build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int bvaddr, unsigned int ptr, enum vmalloc64_mode mode) @@ -956,7 +947,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pgd entry. */ -static void __cpuinit __maybe_unused +static void __maybe_unused build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) { long pgdc = (long)pgd_current; @@ -991,7 +982,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) #endif /* !CONFIG_64BIT */ -static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) +static void build_adjust_context(u32 **p, unsigned int ctx) { unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); @@ -1017,7 +1008,7 @@ static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) uasm_i_andi(p, ctx, ctx, mask); } -static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) +static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) { /* * Bug workaround for the Nevada. It seems as if under certain @@ -1042,8 +1033,7 @@ static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */ } -static void __cpuinit build_update_entries(u32 **p, unsigned int tmp, - unsigned int ptep) +static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { /* * 64bit address support (36bit on a 32bit CPU) in a 32bit @@ -1104,7 +1094,7 @@ struct mips_huge_tlb_info { int restore_scratch; }; -static struct mips_huge_tlb_info __cpuinit +static struct mips_huge_tlb_info build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr, int c0_scratch_reg) @@ -1282,7 +1272,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, */ #define MIPS64_REFILL_INSNS 32 -static void __cpuinit build_r4000_tlb_refill_handler(void) +static void build_r4000_tlb_refill_handler(void) { u32 *p = tlb_handler; struct uasm_label *l = labels; @@ -1462,7 +1452,7 @@ extern u32 handle_tlbm[], handle_tlbm_end[]; #ifdef CONFIG_MIPS_PGD_C0_CONTEXT extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[]; -static void __cpuinit build_r4000_setup_pgd(void) +static void build_r4000_setup_pgd(void) { const int a0 = 4; const int a1 = 5; @@ -1513,7 +1503,7 @@ static void __cpuinit build_r4000_setup_pgd(void) } #endif -static void __cpuinit +static void iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) { #ifdef CONFIG_SMP @@ -1533,7 +1523,7 @@ iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) #endif } -static void __cpuinit +static void iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, unsigned int mode) { @@ -1593,7 +1583,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, * the page table where this PTE is located, PTE will be re-loaded * with it's original value. */ -static void __cpuinit +static void build_pte_present(u32 **p, struct uasm_reloc **r, int pte, int ptr, int scratch, enum label_id lid) { @@ -1621,7 +1611,7 @@ build_pte_present(u32 **p, struct uasm_reloc **r, } /* Make PTE valid, store result in PTR. */ -static void __cpuinit +static void build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -1634,7 +1624,7 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be written to, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __cpuinit +static void build_pte_writable(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, int scratch, enum label_id lid) @@ -1654,7 +1644,7 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, /* Make PTE writable, update software status bits as well, then store * at PTR. */ -static void __cpuinit +static void build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -1668,7 +1658,7 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be modified, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __cpuinit +static void build_pte_modifiable(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, int scratch, enum label_id lid) @@ -1697,7 +1687,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r, * This places the pte into ENTRYLO0 and writes it with tlbwi. * Then it returns. */ -static void __cpuinit +static void build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) { uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */ @@ -1713,7 +1703,7 @@ build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) * may have the probe fail bit set as a result of a trap on a * kseg2 access, i.e. without refill. Then it returns. */ -static void __cpuinit +static void build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int tmp) @@ -1731,7 +1721,7 @@ build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, uasm_i_rfe(p); /* branch delay */ } -static void __cpuinit +static void build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, unsigned int ptr) { @@ -1751,7 +1741,7 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, uasm_i_tlbp(p); /* load delay */ } -static void __cpuinit build_r3000_tlb_load_handler(void) +static void build_r3000_tlb_load_handler(void) { u32 *p = handle_tlbl; const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; @@ -1782,7 +1772,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void) dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size); } -static void __cpuinit build_r3000_tlb_store_handler(void) +static void build_r3000_tlb_store_handler(void) { u32 *p = handle_tlbs; const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; @@ -1813,7 +1803,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void) dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size); } -static void __cpuinit build_r3000_tlb_modify_handler(void) +static void build_r3000_tlb_modify_handler(void) { u32 *p = handle_tlbm; const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; @@ -1848,7 +1838,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) /* * R4000 style TLB load/store/modify handlers. */ -static struct work_registers __cpuinit +static struct work_registers build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, struct uasm_reloc **r) { @@ -1884,7 +1874,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, return wr; } -static void __cpuinit +static void build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) @@ -1902,7 +1892,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, #endif } -static void __cpuinit build_r4000_tlb_load_handler(void) +static void build_r4000_tlb_load_handler(void) { u32 *p = handle_tlbl; const int handle_tlbl_size = handle_tlbl_end - handle_tlbl; @@ -2085,7 +2075,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void) dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size); } -static void __cpuinit build_r4000_tlb_store_handler(void) +static void build_r4000_tlb_store_handler(void) { u32 *p = handle_tlbs; const int handle_tlbs_size = handle_tlbs_end - handle_tlbs; @@ -2140,7 +2130,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void) dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size); } -static void __cpuinit build_r4000_tlb_modify_handler(void) +static void build_r4000_tlb_modify_handler(void) { u32 *p = handle_tlbm; const int handle_tlbm_size = handle_tlbm_end - handle_tlbm; @@ -2196,7 +2186,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size); } -static void __cpuinit flush_tlb_handlers(void) +static void flush_tlb_handlers(void) { local_flush_icache_range((unsigned long)handle_tlbl, (unsigned long)handle_tlbl_end); @@ -2210,7 +2200,7 @@ static void __cpuinit flush_tlb_handlers(void) #endif } -void __cpuinit build_tlb_refill_handler(void) +void build_tlb_refill_handler(void) { /* * The refill handler is generated per-CPU, multi-node systems diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 162ee6d62788..060000fa653c 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -49,7 +49,7 @@ #include "uasm.c" -static struct insn insn_table_MM[] __uasminitdata = { +static struct insn insn_table_MM[] = { { insn_addu, M(mm_pool32a_op, 0, 0, 0, 0, mm_addu32_op), RT | RS | RD }, { insn_addiu, M(mm_addiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_and, M(mm_pool32a_op, 0, 0, 0, 0, mm_and_op), RT | RS | RD }, @@ -118,7 +118,7 @@ static struct insn insn_table_MM[] __uasminitdata = { #undef M -static inline __uasminit u32 build_bimm(s32 arg) +static inline u32 build_bimm(s32 arg) { WARN(arg > 0xffff || arg < -0x10000, KERN_WARNING "Micro-assembler field overflow\n"); @@ -128,7 +128,7 @@ static inline __uasminit u32 build_bimm(s32 arg) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 1) & 0x7fff); } -static inline __uasminit u32 build_jimm(u32 arg) +static inline u32 build_jimm(u32 arg) { WARN(arg & ~((JIMM_MASK << 2) | 1), @@ -141,7 +141,7 @@ static inline __uasminit u32 build_jimm(u32 arg) * The order of opcode arguments is implicitly left to right, * starting with RS and ending with FUNC or IMM. */ -static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) +static void build_insn(u32 **buf, enum opcode opc, ...) { struct insn *ip = NULL; unsigned int i; @@ -199,7 +199,7 @@ static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) (*buf)++; } -static inline void __uasminit +static inline void __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { long laddr = (long)lab->addr; diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 5fcdd8fe3e83..0c724589854e 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -49,7 +49,7 @@ #include "uasm.c" -static struct insn insn_table[] __uasminitdata = { +static struct insn insn_table[] = { { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, @@ -119,7 +119,7 @@ static struct insn insn_table[] __uasminitdata = { #undef M -static inline __uasminit u32 build_bimm(s32 arg) +static inline u32 build_bimm(s32 arg) { WARN(arg > 0x1ffff || arg < -0x20000, KERN_WARNING "Micro-assembler field overflow\n"); @@ -129,7 +129,7 @@ static inline __uasminit u32 build_bimm(s32 arg) return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); } -static inline __uasminit u32 build_jimm(u32 arg) +static inline u32 build_jimm(u32 arg) { WARN(arg & ~(JIMM_MASK << 2), KERN_WARNING "Micro-assembler field overflow\n"); @@ -141,7 +141,7 @@ static inline __uasminit u32 build_jimm(u32 arg) * The order of opcode arguments is implicitly left to right, * starting with RS and ending with FUNC or IMM. */ -static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) +static void build_insn(u32 **buf, enum opcode opc, ...) { struct insn *ip = NULL; unsigned int i; @@ -187,7 +187,7 @@ static void __uasminit build_insn(u32 **buf, enum opcode opc, ...) (*buf)++; } -static inline void __uasminit +static inline void __resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab) { long laddr = (long)lab->addr; diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 7eb5e4355d25..b9d14b6c7f58 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -63,35 +63,35 @@ struct insn { enum fields fields; }; -static inline __uasminit u32 build_rs(u32 arg) +static inline u32 build_rs(u32 arg) { WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return (arg & RS_MASK) << RS_SH; } -static inline __uasminit u32 build_rt(u32 arg) +static inline u32 build_rt(u32 arg) { WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return (arg & RT_MASK) << RT_SH; } -static inline __uasminit u32 build_rd(u32 arg) +static inline u32 build_rd(u32 arg) { WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return (arg & RD_MASK) << RD_SH; } -static inline __uasminit u32 build_re(u32 arg) +static inline u32 build_re(u32 arg) { WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return (arg & RE_MASK) << RE_SH; } -static inline __uasminit u32 build_simm(s32 arg) +static inline u32 build_simm(s32 arg) { WARN(arg > 0x7fff || arg < -0x8000, KERN_WARNING "Micro-assembler field overflow\n"); @@ -99,14 +99,14 @@ static inline __uasminit u32 build_simm(s32 arg) return arg & 0xffff; } -static inline __uasminit u32 build_uimm(u32 arg) +static inline u32 build_uimm(u32 arg) { WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return arg & IMM_MASK; } -static inline __uasminit u32 build_scimm(u32 arg) +static inline u32 build_scimm(u32 arg) { WARN(arg & ~SCIMM_MASK, KERN_WARNING "Micro-assembler field overflow\n"); @@ -114,21 +114,21 @@ static inline __uasminit u32 build_scimm(u32 arg) return (arg & SCIMM_MASK) << SCIMM_SH; } -static inline __uasminit u32 build_func(u32 arg) +static inline u32 build_func(u32 arg) { WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return arg & FUNC_MASK; } -static inline __uasminit u32 build_set(u32 arg) +static inline u32 build_set(u32 arg) { WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n"); return arg & SET_MASK; } -static void __uasminit build_insn(u32 **buf, enum opcode opc, ...); +static void build_insn(u32 **buf, enum opcode opc, ...); #define I_u1u2u3(op) \ Ip_u1u2u3(op) \ @@ -286,7 +286,7 @@ I_u3u1u2(_ldx) #ifdef CONFIG_CPU_CAVIUM_OCTEON #include -void __uasminit ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, +void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b, unsigned int c) { if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5) @@ -304,7 +304,7 @@ I_u2s3u1(_pref) #endif /* Handle labels. */ -void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid) +void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid) { (*lab)->addr = addr; (*lab)->lab = lid; @@ -312,7 +312,7 @@ void __uasminit ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, in } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label)); -int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr) +int ISAFUNC(uasm_in_compat_space_p)(long addr) { /* Is this address in 32bit compat space? */ #ifdef CONFIG_64BIT @@ -323,7 +323,7 @@ int __uasminit ISAFUNC(uasm_in_compat_space_p)(long addr) } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p)); -static int __uasminit uasm_rel_highest(long val) +static int uasm_rel_highest(long val) { #ifdef CONFIG_64BIT return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; @@ -332,7 +332,7 @@ static int __uasminit uasm_rel_highest(long val) #endif } -static int __uasminit uasm_rel_higher(long val) +static int uasm_rel_higher(long val) { #ifdef CONFIG_64BIT return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; @@ -341,19 +341,19 @@ static int __uasminit uasm_rel_higher(long val) #endif } -int __uasminit ISAFUNC(uasm_rel_hi)(long val) +int ISAFUNC(uasm_rel_hi)(long val) { return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi)); -int __uasminit ISAFUNC(uasm_rel_lo)(long val) +int ISAFUNC(uasm_rel_lo)(long val) { return ((val & 0xffff) ^ 0x8000) - 0x8000; } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo)); -void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) +void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) { if (!ISAFUNC(uasm_in_compat_space_p)(addr)) { ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr)); @@ -371,7 +371,7 @@ void __uasminit ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr) } UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly)); -void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) +void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) { ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr); if (ISAFUNC(uasm_rel_lo(addr))) { @@ -386,8 +386,7 @@ void __uasminit ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr) UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA)); /* Handle relocations. */ -void __uasminit -ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) +void ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) { (*rel)->addr = addr; (*rel)->type = R_MIPS_PC16; @@ -396,11 +395,11 @@ ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid) } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16)); -static inline void __uasminit -__resolve_relocs(struct uasm_reloc *rel, struct uasm_label *lab); +static inline void __resolve_relocs(struct uasm_reloc *rel, + struct uasm_label *lab); -void __uasminit -ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab) +void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, + struct uasm_label *lab) { struct uasm_label *l; @@ -411,8 +410,8 @@ ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel, struct uasm_label *lab) } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs)); -void __uasminit -ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off) +void ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, + long off) { for (; rel->lab != UASM_LABEL_INVALID; rel++) if (rel->addr >= first && rel->addr < end) @@ -420,8 +419,8 @@ ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end, long off } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs)); -void __uasminit -ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off) +void ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, + long off) { for (; lab->lab != UASM_LABEL_INVALID; lab++) if (lab->addr >= first && lab->addr < end) @@ -429,9 +428,8 @@ ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end, long off } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels)); -void __uasminit -ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 *first, - u32 *end, u32 *target) +void ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, + u32 *first, u32 *end, u32 *target) { long off = (long)(target - first); @@ -442,7 +440,7 @@ ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab, u32 * } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler)); -int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) +int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) { for (; rel->lab != UASM_LABEL_INVALID; rel++) { if (rel->addr == addr @@ -456,83 +454,79 @@ int __uasminit ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr) UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay)); /* Convenience functions for labeled branches. */ -void __uasminit -ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bltz)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz)); -void __uasminit -ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) +void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_b)(p, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); -void __uasminit -ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_beqz)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz)); -void __uasminit -ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_beqzl)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl)); -void __uasminit -ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1, - unsigned int reg2, int lid) +void ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1, + unsigned int reg2, int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne)); -void __uasminit -ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bnez)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez)); -void __uasminit -ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bgezl)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl)); -void __uasminit -ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) +void ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg, + int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bgez)(p, reg, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez)); -void __uasminit -ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg, - unsigned int bit, int lid) +void ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0); } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0)); -void __uasminit -ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg, - unsigned int bit, int lid) +void ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid) { uasm_r_mips_pc16(r, *p, lid); ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0); diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c index becbf47506a5..c4849904f013 100644 --- a/arch/mips/mti-malta/malta-smtc.c +++ b/arch/mips/mti-malta/malta-smtc.c @@ -32,7 +32,7 @@ static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action) /* * Post-config but pre-boot cleanup entry point */ -static void __cpuinit msmtc_init_secondary(void) +static void msmtc_init_secondary(void) { int myvpe; @@ -53,7 +53,7 @@ static void __cpuinit msmtc_init_secondary(void) /* * Platform "CPU" startup hook */ -static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) +static void msmtc_boot_secondary(int cpu, struct task_struct *idle) { smtc_boot_secondary(cpu, idle); } @@ -61,7 +61,7 @@ static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) /* * SMP initialization finalization entry point */ -static void __cpuinit msmtc_smp_finish(void) +static void msmtc_smp_finish(void) { smtc_smp_finish(); } diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 0ad305f75802..53aad4a35375 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -150,7 +150,7 @@ static void __init plat_perf_setup(void) } } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c index 96b42eb9b5e2..a43ea3cc0a3b 100644 --- a/arch/mips/mti-sead3/sead3-time.c +++ b/arch/mips/mti-sead3/sead3-time.c @@ -91,7 +91,7 @@ static void __init plat_perf_setup(void) } } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { if (cpu_has_vint) set_vi_handler(cp0_compare_irq, mips_timer_dispatch); diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 885d293b61da..4e35d9c453e2 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -116,7 +116,7 @@ void nlm_early_init_secondary(int cpu) /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit nlm_init_secondary(void) +static void nlm_init_secondary(void) { int hwtid; @@ -252,7 +252,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask) return 0; } -int __cpuinit nlm_wakeup_secondary_cpus(void) +int nlm_wakeup_secondary_cpus(void) { u32 *reset_data; int threadmode; diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 528c46c5a170..aa6cff0a229b 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -70,7 +70,6 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ nop /* not reached */ - __CPUINIT NESTED(nlm_boot_secondary_cpus, 16, sp) /* Initialize CP0 Status */ move t1, zero @@ -94,7 +93,6 @@ NESTED(nlm_boot_secondary_cpus, 16, sp) jr t0 nop END(nlm_boot_secondary_cpus) - __FINIT /* * In case of RMIboot bootloader which is used on XLR boards, the CPUs @@ -102,7 +100,6 @@ END(nlm_boot_secondary_cpus) * This will get them out of the bootloader code and into linux. Needed * because the bootloader area will be taken and initialized by linux. */ - __CPUINIT NESTED(nlm_rmiboot_preboot, 16, sp) mfc0 t0, $15, 1 /* read ebase */ andi t0, 0x1f /* t0 has the processor_id() */ @@ -140,4 +137,3 @@ NESTED(nlm_rmiboot_preboot, 16, sp) b 1b nop END(nlm_rmiboot_preboot) - __FINIT diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index 5c56555380bb..045a396c57ce 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -54,7 +54,7 @@ #error "Unknown CPU" #endif -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return IRQ_TIMER; } diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c index c06e4c9f0478..9fb81fa6272a 100644 --- a/arch/mips/netlogic/xlr/wakeup.c +++ b/arch/mips/netlogic/xlr/wakeup.c @@ -49,7 +49,7 @@ #include #include -int __cpuinit xlr_wakeup_secondary_cpus(void) +int xlr_wakeup_secondary_cpus(void) { struct nlm_soc_info *nodep; unsigned int i, j, boot_cpu; diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 7b2ac81e1f59..162b4cb29dba 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -42,7 +42,7 @@ int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; extern struct pci_ops bridge_pci_ops; -int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) +int bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; diff --git a/arch/mips/pmcs-msp71xx/msp_smtc.c b/arch/mips/pmcs-msp71xx/msp_smtc.c index c8dcc1c01e18..6b5607fce279 100644 --- a/arch/mips/pmcs-msp71xx/msp_smtc.c +++ b/arch/mips/pmcs-msp71xx/msp_smtc.c @@ -33,7 +33,7 @@ static void msp_smtc_send_ipi_mask(const struct cpumask *mask, /* * Post-config but pre-boot cleanup entry point */ -static void __cpuinit msp_smtc_init_secondary(void) +static void msp_smtc_init_secondary(void) { int myvpe; @@ -48,8 +48,7 @@ static void __cpuinit msp_smtc_init_secondary(void) /* * Platform "CPU" startup hook */ -static void __cpuinit msp_smtc_boot_secondary(int cpu, - struct task_struct *idle) +static void msp_smtc_boot_secondary(int cpu, struct task_struct *idle) { smtc_boot_secondary(cpu, idle); } @@ -57,7 +56,7 @@ static void __cpuinit msp_smtc_boot_secondary(int cpu, /* * SMP initialization finalization entry point */ -static void __cpuinit msp_smtc_smp_finish(void) +static void msp_smtc_smp_finish(void) { smtc_smp_finish(); } diff --git a/arch/mips/pmcs-msp71xx/msp_time.c b/arch/mips/pmcs-msp71xx/msp_time.c index 8f12ecc55ace..fea917be0ff1 100644 --- a/arch/mips/pmcs-msp71xx/msp_time.c +++ b/arch/mips/pmcs-msp71xx/msp_time.c @@ -88,7 +88,7 @@ void __init plat_time_init(void) mips_hpt_frequency = cpu_rate/2; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { /* MIPS_MT modes may want timer for second VPE */ if ((get_current_vpe()) && !tim_installed) { diff --git a/arch/mips/pnx833x/common/interrupts.c b/arch/mips/pnx833x/common/interrupts.c index a4a90596c0ad..e460865873c1 100644 --- a/arch/mips/pnx833x/common/interrupts.c +++ b/arch/mips/pnx833x/common/interrupts.c @@ -281,7 +281,7 @@ void __init arch_init_irq(void) write_c0_status(read_c0_status() | IE_IRQ2); } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { if (cpu_has_vint) set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); diff --git a/arch/mips/powertv/time.c b/arch/mips/powertv/time.c index 9fd7b67f2af7..f38b0d45eca9 100644 --- a/arch/mips/powertv/time.c +++ b/arch/mips/powertv/time.c @@ -25,7 +25,7 @@ #include "powertv-clock.h" -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return irq_mips_timer; } diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index 320b1f1043ff..781b3d14a489 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -73,7 +73,7 @@ static struct irq_chip ralink_intc_irq_chip = { .irq_mask_ack = ralink_intc_irq_mask, }; -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index d41b1c6fb032..ee736bd103f8 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -54,7 +54,7 @@ extern void pcibr_setup(cnodeid_t); extern void xtalk_probe_node(cnodeid_t nid); -static void __cpuinit per_hub_init(cnodeid_t cnode) +static void per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); @@ -110,7 +110,7 @@ static void __cpuinit per_hub_init(cnodeid_t cnode) } } -void __cpuinit per_cpu_init(void) +void per_cpu_init(void) { int cpu = smp_processor_id(); int slice = LOCAL_HUB_L(PI_CPU_NUM); diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index f94638141b20..f4ea8aa79ba2 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -173,12 +173,12 @@ static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action) ip27_send_ipi_single(i, action); } -static void __cpuinit ip27_init_secondary(void) +static void ip27_init_secondary(void) { per_cpu_init(); } -static void __cpuinit ip27_smp_finish(void) +static void ip27_smp_finish(void) { extern void hub_rt_clock_event_init(void); @@ -195,7 +195,7 @@ static void __init ip27_cpus_done(void) * set sp to the kernel stack of the newly created idle process, gp to the proc * struct so that current_thread_info() will work. */ -static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle) +static void ip27_boot_secondary(int cpu, struct task_struct *idle) { unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 2e21b761cb9c..1d97eaba0c5f 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -106,7 +106,7 @@ struct irqaction hub_rt_irqaction = { #define NSEC_PER_CYCLE 800 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) -void __cpuinit hub_rt_clock_event_init(void) +void hub_rt_clock_event_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); @@ -173,7 +173,7 @@ void __init plat_time_init(void) hub_rt_clock_event_init(); } -void __cpuinit cpu_time_init(void) +void cpu_time_init(void) { lboard_t *board; klcpu_t *cpu; @@ -194,7 +194,7 @@ void __cpuinit cpu_time_init(void) set_c0_status(SRB_TIMOCLK); } -void __cpuinit hub_rtc_init(cnodeid_t cnode) +void hub_rtc_init(cnodeid_t cnode) { /* diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index a4df7d0f6f12..d59b820f528d 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -23,7 +23,7 @@ extern int bridge_probe(nasid_t nasid, int widget, int masterwid); -static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) +static int probe_one_port(nasid_t nasid, int widget, int masterwid) { widgetreg_t widget_id; xwidget_part_num_t partnum; @@ -47,7 +47,7 @@ static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) return 0; } -static int __cpuinit xbow_probe(nasid_t nasid) +static int xbow_probe(nasid_t nasid) { lboard_t *brd; klxbow_t *xbow_p; @@ -100,7 +100,7 @@ static int __cpuinit xbow_probe(nasid_t nasid) return 0; } -void __cpuinit xtalk_probe_node(cnodeid_t nid) +void xtalk_probe_node(cnodeid_t nid) { volatile u64 hubreg; nasid_t nasid; diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index de88e22694a0..54e2c4de15c1 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -60,7 +60,7 @@ static void *mailbox_0_regs[] = { /* * SMP init and finish on secondary CPUs */ -void __cpuinit bcm1480_smp_init(void) +void bcm1480_smp_init(void) { unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | STATUSF_IP1 | STATUSF_IP0; @@ -95,7 +95,7 @@ static void bcm1480_send_ipi_mask(const struct cpumask *mask, /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit bcm1480_init_secondary(void) +static void bcm1480_init_secondary(void) { extern void bcm1480_smp_init(void); @@ -106,7 +106,7 @@ static void __cpuinit bcm1480_init_secondary(void) * Do any tidying up before marking online and running the idle * loop */ -static void __cpuinit bcm1480_smp_finish(void) +static void bcm1480_smp_finish(void) { extern void sb1480_clockevent_init(void); @@ -125,7 +125,7 @@ static void bcm1480_cpus_done(void) * Setup the PC, SP, and GP of a secondary processor and start it * running! */ -static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle) +static void bcm1480_boot_secondary(int cpu, struct task_struct *idle) { int retval; diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 285cfef4ebc0..d7b942db0ea5 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -48,7 +48,7 @@ static void *mailbox_regs[] = { /* * SMP init and finish on secondary CPUs */ -void __cpuinit sb1250_smp_init(void) +void sb1250_smp_init(void) { unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | STATUSF_IP1 | STATUSF_IP0; @@ -83,7 +83,7 @@ static inline void sb1250_send_ipi_mask(const struct cpumask *mask, /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit sb1250_init_secondary(void) +static void sb1250_init_secondary(void) { extern void sb1250_smp_init(void); @@ -94,7 +94,7 @@ static void __cpuinit sb1250_init_secondary(void) * Do any tidying up before marking online and running the idle * loop */ -static void __cpuinit sb1250_smp_finish(void) +static void sb1250_smp_finish(void) { extern void sb1250_clockevent_init(void); @@ -113,7 +113,7 @@ static void sb1250_cpus_done(void) * Setup the PC, SP, and GP of a secondary processor and start it * running! */ -static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) +static void sb1250_boot_secondary(int cpu, struct task_struct *idle) { int retval; -- GitLab From 8bd26e3a7e49af2697449bbcb7187a39dc85d672 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 17 Jun 2013 15:43:14 -0400 Subject: [PATCH 2756/2900] arm: delete __cpuinit/__CPUINIT usage from all ARM users The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) and are flagged as __cpuinit -- so if we remove the __cpuinit from the arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit related content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the ARM uses of the __cpuinit macros from C code, and all __CPUINIT from assembly code. It also had two ".previous" section statements that were paired off against __CPUINIT (aka .section ".cpuinit.text") that also get removed here. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Russell King Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker --- arch/arm/common/mcpm_platsmp.c | 4 ++-- arch/arm/include/asm/arch_timer.h | 2 +- arch/arm/kernel/head-common.S | 1 - arch/arm/kernel/head-nommu.S | 1 - arch/arm/kernel/head.S | 1 - arch/arm/kernel/hw_breakpoint.c | 4 ++-- arch/arm/kernel/perf_event_cpu.c | 6 +++--- arch/arm/kernel/psci_smp.c | 3 +-- arch/arm/kernel/smp.c | 18 +++++++++--------- arch/arm/kernel/smp_twd.c | 6 +++--- arch/arm/lib/delay.c | 2 +- arch/arm/mach-exynos/headsmp.S | 2 -- arch/arm/mach-exynos/platsmp.c | 4 ++-- arch/arm/mach-highbank/platsmp.c | 2 +- arch/arm/mach-imx/platsmp.c | 2 +- arch/arm/mach-keystone/platsmp.c | 2 +- arch/arm/mach-msm/headsmp.S | 2 -- arch/arm/mach-msm/platsmp.c | 6 +++--- arch/arm/mach-msm/timer.c | 4 ++-- arch/arm/mach-mvebu/coherency.c | 2 +- arch/arm/mach-mvebu/headsmp.S | 2 -- arch/arm/mach-mvebu/platsmp.c | 5 ++--- arch/arm/mach-omap2/omap-headsmp.S | 2 -- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 2 +- arch/arm/mach-omap2/omap-smp.c | 4 ++-- arch/arm/mach-omap2/omap-wakeupgen.c | 4 ++-- arch/arm/mach-prima2/headsmp.S | 2 -- arch/arm/mach-prima2/platsmp.c | 4 ++-- arch/arm/mach-shmobile/headsmp-scu.S | 1 - arch/arm/mach-shmobile/headsmp.S | 2 -- arch/arm/mach-shmobile/smp-emev2.c | 2 +- arch/arm/mach-shmobile/smp-r8a7779.c | 2 +- arch/arm/mach-shmobile/smp-sh73a0.c | 2 +- arch/arm/mach-socfpga/headsmp.S | 1 - arch/arm/mach-socfpga/platsmp.c | 2 +- arch/arm/mach-spear/generic.h | 2 +- arch/arm/mach-spear/platsmp.c | 4 ++-- arch/arm/mach-sti/platsmp.c | 6 +++--- arch/arm/mach-tegra/platsmp.c | 4 ++-- arch/arm/mach-tegra/pm.c | 2 +- arch/arm/mach-ux500/platsmp.c | 4 ++-- arch/arm/mach-zynq/common.h | 2 +- arch/arm/mach-zynq/headsmp.S | 2 -- arch/arm/mach-zynq/platsmp.c | 6 +++--- arch/arm/mm/proc-arm1020.S | 2 -- arch/arm/mm/proc-arm1020e.S | 2 -- arch/arm/mm/proc-arm1022.S | 2 -- arch/arm/mm/proc-arm1026.S | 3 --- arch/arm/mm/proc-arm720.S | 2 -- arch/arm/mm/proc-arm740.S | 2 -- arch/arm/mm/proc-arm7tdmi.S | 2 -- arch/arm/mm/proc-arm920.S | 2 -- arch/arm/mm/proc-arm922.S | 2 -- arch/arm/mm/proc-arm925.S | 2 -- arch/arm/mm/proc-arm926.S | 2 -- arch/arm/mm/proc-arm940.S | 2 -- arch/arm/mm/proc-arm946.S | 2 -- arch/arm/mm/proc-arm9tdmi.S | 2 -- arch/arm/mm/proc-fa526.S | 2 -- arch/arm/mm/proc-feroceon.S | 2 -- arch/arm/mm/proc-mohawk.S | 2 -- arch/arm/mm/proc-sa110.S | 2 -- arch/arm/mm/proc-sa1100.S | 2 -- arch/arm/mm/proc-v6.S | 2 -- arch/arm/mm/proc-v7-2level.S | 4 ---- arch/arm/mm/proc-v7-3level.S | 4 ---- arch/arm/mm/proc-v7.S | 2 -- arch/arm/mm/proc-xsc3.S | 2 -- arch/arm/mm/proc-xscale.S | 2 -- arch/arm/plat-versatile/platsmp.c | 6 +++--- 70 files changed, 64 insertions(+), 140 deletions(-) diff --git a/arch/arm/common/mcpm_platsmp.c b/arch/arm/common/mcpm_platsmp.c index 510e5b13aa2e..1bc34c7567fd 100644 --- a/arch/arm/common/mcpm_platsmp.c +++ b/arch/arm/common/mcpm_platsmp.c @@ -19,7 +19,7 @@ #include #include -static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned int mpidr, pcpu, pcluster, ret; extern void secondary_startup(void); @@ -40,7 +40,7 @@ static int __cpuinit mcpm_boot_secondary(unsigned int cpu, struct task_struct *i return 0; } -static void __cpuinit mcpm_secondary_init(unsigned int cpu) +static void mcpm_secondary_init(unsigned int cpu) { mcpm_cpu_powered_up(); } diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index accefe099182..e406d575c94f 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -89,7 +89,7 @@ static inline u64 arch_counter_get_cntvct(void) return cval; } -static inline void __cpuinit arch_counter_set_user_access(void) +static inline void arch_counter_set_user_access(void) { u32 cntkctl; diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 76ab5ca50610..47cd974e57ea 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -149,7 +149,6 @@ ENDPROC(lookup_processor_type) * r5 = proc_info pointer in physical address space * r9 = cpuid (preserved) */ - __CPUINIT __lookup_processor_type: adr r3, __lookup_processor_type_data ldmia r3, {r4 - r6} diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 75f14cc3e073..b361de143756 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -87,7 +87,6 @@ ENTRY(stext) ENDPROC(stext) #ifdef CONFIG_SMP - __CPUINIT ENTRY(secondary_startup) /* * Common entry point for secondary CPUs. diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 45e8935cae4e..9cf6063020ae 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -343,7 +343,6 @@ __turn_mmu_on_loc: .long __turn_mmu_on_end #if defined(CONFIG_SMP) - __CPUINIT ENTRY(secondary_startup) /* * Common entry point for secondary CPUs. diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 1fd749ee4a1b..7b95de601357 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -1020,7 +1020,7 @@ static void reset_ctrl_regs(void *unused) cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); } -static int __cpuinit dbg_reset_notify(struct notifier_block *self, +static int dbg_reset_notify(struct notifier_block *self, unsigned long action, void *cpu) { if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) @@ -1029,7 +1029,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata dbg_reset_nb = { +static struct notifier_block dbg_reset_nb = { .notifier_call = dbg_reset_notify, }; diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c index 1f2740e3dbc0..aebe0e99c153 100644 --- a/arch/arm/kernel/perf_event_cpu.c +++ b/arch/arm/kernel/perf_event_cpu.c @@ -157,8 +157,8 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu) * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading * junk values out of them. */ -static int __cpuinit cpu_pmu_notify(struct notifier_block *b, - unsigned long action, void *hcpu) +static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, + void *hcpu) { if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) return NOTIFY_DONE; @@ -171,7 +171,7 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = { +static struct notifier_block cpu_pmu_hotplug_notifier = { .notifier_call = cpu_pmu_notify, }; diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 219f1d73572a..70ded3fb42d9 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c @@ -46,8 +46,7 @@ extern void secondary_startup(void); -static int __cpuinit psci_boot_secondary(unsigned int cpu, - struct task_struct *idle) +static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle) { if (psci_ops.cpu_on) return psci_ops.cpu_on(cpu_logical_map(cpu), diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index c5fb5469054b..c2b4f8f0be9a 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -58,7 +58,7 @@ struct secondary_data secondary_data; * control for which core is the next to come out of the secondary * boot "holding pen" */ -volatile int __cpuinitdata pen_release = -1; +volatile int pen_release = -1; enum ipi_msg_type { IPI_WAKEUP, @@ -86,7 +86,7 @@ static unsigned long get_arch_pgd(pgd_t *pgd) return pgdir >> ARCH_PGD_SHIFT; } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -138,7 +138,7 @@ void __init smp_init_cpus(void) smp_ops.smp_init_cpus(); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { if (smp_ops.smp_boot_secondary) return smp_ops.smp_boot_secondary(cpu, idle); @@ -170,7 +170,7 @@ static int platform_cpu_disable(unsigned int cpu) /* * __cpu_disable runs on the processor to be shutdown. */ -int __cpuinit __cpu_disable(void) +int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); int ret; @@ -216,7 +216,7 @@ static DECLARE_COMPLETION(cpu_died); * called on the thread which is asking for a CPU to be shutdown - * waits until shutdown has completed, or it is timed out. */ -void __cpuinit __cpu_die(unsigned int cpu) +void __cpu_die(unsigned int cpu) { if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { pr_err("CPU%u: cpu didn't die\n", cpu); @@ -306,7 +306,7 @@ void __ref cpu_die(void) * Called by both boot and secondaries to move global data into * per-processor storage. */ -static void __cpuinit smp_store_cpu_info(unsigned int cpuid) +static void smp_store_cpu_info(unsigned int cpuid) { struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); @@ -322,7 +322,7 @@ static void percpu_timer_setup(void); * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void __cpuinit secondary_start_kernel(void) +asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu; @@ -521,7 +521,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode, { } -static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) +static void broadcast_timer_setup(struct clock_event_device *evt) { evt->name = "dummy_timer"; evt->features = CLOCK_EVT_FEAT_ONESHOT | @@ -550,7 +550,7 @@ int local_timer_register(struct local_timer_ops *ops) } #endif -static void __cpuinit percpu_timer_setup(void) +static void percpu_timer_setup(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index f6fd1d4398c6..25956204ef23 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -187,7 +187,7 @@ core_initcall(twd_cpufreq_init); #endif -static void __cpuinit twd_calibrate_rate(void) +static void twd_calibrate_rate(void) { unsigned long count; u64 waitjiffies; @@ -265,7 +265,7 @@ static void twd_get_clock(struct device_node *np) /* * Setup the local clock events for a CPU. */ -static int __cpuinit twd_timer_setup(struct clock_event_device *clk) +static int twd_timer_setup(struct clock_event_device *clk) { struct clock_event_device **this_cpu_clk; int cpu = smp_processor_id(); @@ -308,7 +308,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) return 0; } -static struct local_timer_ops twd_lt_ops __cpuinitdata = { +static struct local_timer_ops twd_lt_ops = { .setup = twd_timer_setup, .stop = twd_timer_stop, }; diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 64dbfa57204a..5306de350133 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -86,7 +86,7 @@ void __init register_current_timer_delay(const struct delay_timer *timer) } } -unsigned long __cpuinit calibrate_delay_is_known(void) +unsigned long calibrate_delay_is_known(void) { delay_calibrated = true; return lpj_fine; diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S index 5364d4bfa8bc..cdd9d91e9933 100644 --- a/arch/arm/mach-exynos/headsmp.S +++ b/arch/arm/mach-exynos/headsmp.S @@ -13,8 +13,6 @@ #include #include - __CPUINIT - /* * exynos4 specific entry point for secondary CPUs. This provides * a "holding pen" into which all secondary cores are held until we're diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index deba1308ff16..58b43e6f9262 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -75,7 +75,7 @@ static void __iomem *scu_base_addr(void) static DEFINE_SPINLOCK(boot_lock); -static void __cpuinit exynos_secondary_init(unsigned int cpu) +static void exynos_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -90,7 +90,7 @@ static void __cpuinit exynos_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; unsigned long phys_cpu = cpu_logical_map(cpu); diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c index a984573e0d02..32d75cf55cbc 100644 --- a/arch/arm/mach-highbank/platsmp.c +++ b/arch/arm/mach-highbank/platsmp.c @@ -24,7 +24,7 @@ extern void secondary_startup(void); -static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int highbank_boot_secondary(unsigned int cpu, struct task_struct *idle) { highbank_set_cpu_jump(cpu, secondary_startup); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index c6e1ab544882..1f24c1fdfea4 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -53,7 +53,7 @@ void imx_scu_standby_enable(void) writel_relaxed(val, scu_base); } -static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int imx_boot_secondary(unsigned int cpu, struct task_struct *idle) { imx_set_cpu_jump(cpu, v7_secondary_startup); imx_enable_cpu(cpu, true); diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c index 1d4181e1daf2..14378e3fef16 100644 --- a/arch/arm/mach-keystone/platsmp.c +++ b/arch/arm/mach-keystone/platsmp.c @@ -21,7 +21,7 @@ #include "keystone.h" -static int __cpuinit keystone_smp_boot_secondary(unsigned int cpu, +static int keystone_smp_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long start = virt_to_phys(&secondary_startup); diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S index bcd5af223dea..6c62c3f82fe6 100644 --- a/arch/arm/mach-msm/headsmp.S +++ b/arch/arm/mach-msm/headsmp.S @@ -11,8 +11,6 @@ #include #include - __CPUINIT - /* * MSM specific entry point for secondary CPUs. This provides * a "holding pen" into which all secondary cores are held until we're diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 00cdb0a5dac8..3f06edcdd0ce 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -38,7 +38,7 @@ static inline int get_core_count(void) return ((read_cpuid_id() >> 4) & 3) + 1; } -static void __cpuinit msm_secondary_init(unsigned int cpu) +static void msm_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -54,7 +54,7 @@ static void __cpuinit msm_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static __cpuinit void prepare_cold_cpu(unsigned int cpu) +static void prepare_cold_cpu(unsigned int cpu) { int ret; ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup), @@ -73,7 +73,7 @@ static __cpuinit void prepare_cold_cpu(unsigned int cpu) "address\n"); } -static int __cpuinit msm_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int msm_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; static int cold_boot_done; diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index b6418fd5fe0d..8697cfc0d0b6 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -139,7 +139,7 @@ static struct clocksource msm_clocksource = { }; #ifdef CONFIG_LOCAL_TIMERS -static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) +static int msm_local_timer_setup(struct clock_event_device *evt) { /* Use existing clock_event for cpu 0 */ if (!smp_processor_id()) @@ -164,7 +164,7 @@ static void msm_local_timer_stop(struct clock_event_device *evt) disable_percpu_irq(evt->irq); } -static struct local_timer_ops msm_local_timer_ops __cpuinitdata = { +static struct local_timer_ops msm_local_timer_ops = { .setup = msm_local_timer_setup, .stop = msm_local_timer_stop, }; diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c index be117591f7f2..4c24303ec481 100644 --- a/arch/arm/mach-mvebu/coherency.c +++ b/arch/arm/mach-mvebu/coherency.c @@ -28,7 +28,7 @@ #include #include "armada-370-xp.h" -unsigned long __cpuinitdata coherency_phys_base; +unsigned long coherency_phys_base; static void __iomem *coherency_base; static void __iomem *coherency_cpu_base; diff --git a/arch/arm/mach-mvebu/headsmp.S b/arch/arm/mach-mvebu/headsmp.S index 7147300c8af2..8a1b0c96e9ec 100644 --- a/arch/arm/mach-mvebu/headsmp.S +++ b/arch/arm/mach-mvebu/headsmp.S @@ -21,8 +21,6 @@ #include #include - __CPUINIT - /* * Armada XP specific entry point for secondary CPUs. * We add the CPU to the coherency fabric and then jump to secondary diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 93f2f3ab45f1..ce81d3031405 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -71,13 +71,12 @@ void __init set_secondary_cpus_clock(void) } } -static void __cpuinit armada_xp_secondary_init(unsigned int cpu) +static void armada_xp_secondary_init(unsigned int cpu) { armada_xp_mpic_smp_cpu_init(); } -static int __cpuinit armada_xp_boot_secondary(unsigned int cpu, - struct task_struct *idle) +static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle) { pr_info("Booting CPU %d\n", cpu); diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index 4ea308114165..75e92952c18e 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -20,8 +20,6 @@ #include "omap44xx.h" - __CPUINIT - /* Physical address needed since MMU not enabled yet on secondary core */ #define AUX_CORE_BOOT0_PA 0x48281800 diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index f993a4188701..f991016e2a6a 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -291,7 +291,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) * @cpu : CPU ID * @power_state: CPU low power state. */ -int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) +int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu); unsigned int cpu_state = 0; diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 98a11463a843..8708b2a9da45 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -51,7 +51,7 @@ void __iomem *omap4_get_scu_base(void) return scu_base; } -static void __cpuinit omap4_secondary_init(unsigned int cpu) +static void omap4_secondary_init(unsigned int cpu) { /* * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device. @@ -72,7 +72,7 @@ static void __cpuinit omap4_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index f8bb3b9b6a76..813c61558a5f 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -323,8 +323,8 @@ static void irq_save_secure_context(void) #endif #ifdef CONFIG_HOTPLUG_CPU -static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int irq_cpu_hotplug_notify(struct notifier_block *self, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)hcpu; diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S index 5b8a408d8921..d86fe33c5f53 100644 --- a/arch/arm/mach-prima2/headsmp.S +++ b/arch/arm/mach-prima2/headsmp.S @@ -9,8 +9,6 @@ #include #include - __CPUINIT - /* * SIRFSOC specific entry point for secondary CPUs. This provides * a "holding pen" into which all secondary cores are held until we're diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c index 1c3de7bed841..3dbcb1ab6e37 100644 --- a/arch/arm/mach-prima2/platsmp.c +++ b/arch/arm/mach-prima2/platsmp.c @@ -44,7 +44,7 @@ void __init sirfsoc_map_scu(void) scu_base = (void __iomem *)SIRFSOC_VA(base); } -static void __cpuinit sirfsoc_secondary_init(unsigned int cpu) +static void sirfsoc_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -65,7 +65,7 @@ static struct of_device_id rsc_ids[] = { {}, }; -static int __cpuinit sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; struct device_node *np; diff --git a/arch/arm/mach-shmobile/headsmp-scu.S b/arch/arm/mach-shmobile/headsmp-scu.S index 6f9865467258..bfd920083a3b 100644 --- a/arch/arm/mach-shmobile/headsmp-scu.S +++ b/arch/arm/mach-shmobile/headsmp-scu.S @@ -23,7 +23,6 @@ #include #include - __CPUINIT /* * Boot code for secondary CPUs. * diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index 559d1ce5f57e..a9d212498987 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -14,8 +14,6 @@ #include #include - __CPUINIT - ENTRY(shmobile_invalidate_start) bl v7_invalidate_l1 b secondary_startup diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c index 80991b35f4ac..22a05a869d25 100644 --- a/arch/arm/mach-shmobile/smp-emev2.c +++ b/arch/arm/mach-shmobile/smp-emev2.c @@ -30,7 +30,7 @@ #define EMEV2_SCU_BASE 0x1e000000 -static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) { arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu))); return 0; diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 526cfaae81c1..9bdf810f2a87 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -81,7 +81,7 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu) return ret ? ret : 1; } -static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) { struct r8a7779_pm_ch *ch = NULL; int ret = -EIO; diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index d613113a04bd..d5fc3ed4e315 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -48,7 +48,7 @@ void __init sh73a0_register_twd(void) } #endif -static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) { cpu = cpu_logical_map(cpu); diff --git a/arch/arm/mach-socfpga/headsmp.S b/arch/arm/mach-socfpga/headsmp.S index 9004bfb1756e..95c115d8b5ee 100644 --- a/arch/arm/mach-socfpga/headsmp.S +++ b/arch/arm/mach-socfpga/headsmp.S @@ -10,7 +10,6 @@ #include #include - __CPUINIT .arch armv7-a ENTRY(secondary_trampoline) diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c index b51ce8c7929d..5356a72bc8ce 100644 --- a/arch/arm/mach-socfpga/platsmp.c +++ b/arch/arm/mach-socfpga/platsmp.c @@ -29,7 +29,7 @@ #include "core.h" -static int __cpuinit socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle) { int trampoline_size = &secondary_trampoline_end - &secondary_trampoline; diff --git a/arch/arm/mach-spear/generic.h b/arch/arm/mach-spear/generic.h index 904f2c907b46..a99d90a4d09c 100644 --- a/arch/arm/mach-spear/generic.h +++ b/arch/arm/mach-spear/generic.h @@ -37,7 +37,7 @@ void __init spear13xx_l2x0_init(void); void spear_restart(enum reboot_mode, const char *); void spear13xx_secondary_startup(void); -void __cpuinit spear13xx_cpu_die(unsigned int cpu); +void spear13xx_cpu_die(unsigned int cpu); extern struct smp_operations spear13xx_smp_ops; diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c index 9c4c722c954e..5c4a19887b2b 100644 --- a/arch/arm/mach-spear/platsmp.c +++ b/arch/arm/mach-spear/platsmp.c @@ -24,7 +24,7 @@ static DEFINE_SPINLOCK(boot_lock); static void __iomem *scu_base = IOMEM(VA_SCU_BASE); -static void __cpuinit spear13xx_secondary_init(unsigned int cpu) +static void spear13xx_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -40,7 +40,7 @@ static void __cpuinit spear13xx_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/mach-sti/platsmp.c b/arch/arm/mach-sti/platsmp.c index 977a863468fc..dce50d983a8e 100644 --- a/arch/arm/mach-sti/platsmp.c +++ b/arch/arm/mach-sti/platsmp.c @@ -27,7 +27,7 @@ #include "smp.h" -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); @@ -37,7 +37,7 @@ static void __cpuinit write_pen_release(int val) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit sti_secondary_init(unsigned int cpu) +void sti_secondary_init(unsigned int cpu) { trace_hardirqs_off(); @@ -54,7 +54,7 @@ void __cpuinit sti_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit sti_boot_secondary(unsigned int cpu, struct task_struct *idle) +int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 24db4ac428ae..97b33a2a2d75 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -35,7 +35,7 @@ static cpumask_t tegra_cpu_init_mask; -static void __cpuinit tegra_secondary_init(unsigned int cpu) +static void tegra_secondary_init(unsigned int cpu) { cpumask_set_cpu(cpu, &tegra_cpu_init_mask); } @@ -167,7 +167,7 @@ static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle) return ret; } -static int __cpuinit tegra_boot_secondary(unsigned int cpu, +static int tegra_boot_secondary(unsigned int cpu, struct task_struct *idle) { if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20) diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 94e69bee3da5..261fec140c06 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -191,7 +191,7 @@ static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = { [TEGRA_SUSPEND_LP0] = "LP0", }; -static int __cpuinit tegra_suspend_enter(suspend_state_t state) +static int tegra_suspend_enter(suspend_state_t state) { enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode(); diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 14d90469392f..1f296e796a4f 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -54,7 +54,7 @@ static void __iomem *scu_base_addr(void) static DEFINE_SPINLOCK(boot_lock); -static void __cpuinit ux500_secondary_init(unsigned int cpu) +static void ux500_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -69,7 +69,7 @@ static void __cpuinit ux500_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit ux500_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index fbbd0e21c404..3040d219570f 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -27,7 +27,7 @@ extern void secondary_startup(void); extern char zynq_secondary_trampoline; extern char zynq_secondary_trampoline_jump; extern char zynq_secondary_trampoline_end; -extern int __cpuinit zynq_cpun_start(u32 address, int cpu); +extern int zynq_cpun_start(u32 address, int cpu); extern struct smp_operations zynq_smp_ops __initdata; #endif diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S index d183cd234a9b..d4cd5f34fe5c 100644 --- a/arch/arm/mach-zynq/headsmp.S +++ b/arch/arm/mach-zynq/headsmp.S @@ -9,8 +9,6 @@ #include #include - __CPUINIT - ENTRY(zynq_secondary_trampoline) ldr r0, [pc] bx r0 diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c index 023f225493f2..689fbbc3d9c8 100644 --- a/arch/arm/mach-zynq/platsmp.c +++ b/arch/arm/mach-zynq/platsmp.c @@ -30,11 +30,11 @@ /* * Store number of cores in the system * Because of scu_get_core_count() must be in __init section and can't - * be called from zynq_cpun_start() because it is in __cpuinit section. + * be called from zynq_cpun_start() because it is not in __init section. */ static int ncores; -int __cpuinit zynq_cpun_start(u32 address, int cpu) +int zynq_cpun_start(u32 address, int cpu) { u32 trampoline_code_size = &zynq_secondary_trampoline_end - &zynq_secondary_trampoline; @@ -92,7 +92,7 @@ int __cpuinit zynq_cpun_start(u32 address, int cpu) } EXPORT_SYMBOL(zynq_cpun_start); -static int __cpuinit zynq_boot_secondary(unsigned int cpu, +static int zynq_boot_secondary(unsigned int cpu, struct task_struct *idle) { return zynq_cpun_start(virt_to_phys(secondary_startup), cpu); diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 2bb61e703d6c..d1a2d05971e0 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -443,8 +443,6 @@ ENTRY(cpu_arm1020_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - __CPUINIT - .type __arm1020_setup, #function __arm1020_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 8f96aa40f510..9d89405c3d03 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -425,8 +425,6 @@ ENTRY(cpu_arm1020e_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - __CPUINIT - .type __arm1020e_setup, #function __arm1020e_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 8ebe4a469a22..6f01a0ae3b30 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -407,8 +407,6 @@ ENTRY(cpu_arm1022_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - __CPUINIT - .type __arm1022_setup, #function __arm1022_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 093fc7e520c3..4799a24b43e6 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -396,9 +396,6 @@ ENTRY(cpu_arm1026_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - - __CPUINIT - .type __arm1026_setup, #function __arm1026_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index 0ac908c7ade1..d42c37f9f5bc 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -116,8 +116,6 @@ ENTRY(cpu_arm720_reset) ENDPROC(cpu_arm720_reset) .popsection - __CPUINIT - .type __arm710_setup, #function __arm710_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S index fde2d2a794cf..9b0ae90cbf17 100644 --- a/arch/arm/mm/proc-arm740.S +++ b/arch/arm/mm/proc-arm740.S @@ -60,8 +60,6 @@ ENTRY(cpu_arm740_reset) ENDPROC(cpu_arm740_reset) .popsection - __CPUINIT - .type __arm740_setup, #function __arm740_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index 6ddea3e464bd..f6cc3f63ce39 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -51,8 +51,6 @@ ENTRY(cpu_arm7tdmi_reset) ENDPROC(cpu_arm7tdmi_reset) .popsection - __CPUINIT - .type __arm7tdmi_setup, #function __arm7tdmi_setup: mov pc, lr diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 2556cf1c2da1..549557df6d57 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -410,8 +410,6 @@ ENTRY(cpu_arm920_do_resume) ENDPROC(cpu_arm920_do_resume) #endif - __CPUINIT - .type __arm920_setup, #function __arm920_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 4464c49d7449..2a758b06c6f6 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -388,8 +388,6 @@ ENTRY(cpu_arm922_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - __CPUINIT - .type __arm922_setup, #function __arm922_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 281eb9b9c1d6..97448c3acf38 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -438,8 +438,6 @@ ENTRY(cpu_arm925_set_pte_ext) #endif /* CONFIG_MMU */ mov pc, lr - __CPUINIT - .type __arm925_setup, #function __arm925_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 344c8a548cc0..0f098f407c9f 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -425,8 +425,6 @@ ENTRY(cpu_arm926_do_resume) ENDPROC(cpu_arm926_do_resume) #endif - __CPUINIT - .type __arm926_setup, #function __arm926_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 8da189d4a402..1c39a704ff6e 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -273,8 +273,6 @@ ENDPROC(arm940_dma_unmap_area) @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm940 - __CPUINIT - .type __arm940_setup, #function __arm940_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index f666cf34075a..0289cd905e73 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -326,8 +326,6 @@ ENTRY(cpu_arm946_dcache_clean_area) mcr p15, 0, r0, c7, c10, 4 @ drain WB mov pc, lr - __CPUINIT - .type __arm946_setup, #function __arm946_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index 8881391dfb9e..f51197ba754a 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -51,8 +51,6 @@ ENTRY(cpu_arm9tdmi_reset) ENDPROC(cpu_arm9tdmi_reset) .popsection - __CPUINIT - .type __arm9tdmi_setup, #function __arm9tdmi_setup: mov pc, lr diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S index aaeb6c127c7a..2dfc0f1d3bfd 100644 --- a/arch/arm/mm/proc-fa526.S +++ b/arch/arm/mm/proc-fa526.S @@ -135,8 +135,6 @@ ENTRY(cpu_fa526_set_pte_ext) #endif mov pc, lr - __CPUINIT - .type __fa526_setup, #function __fa526_setup: /* On return of this routine, r0 must carry correct flags for CFG register */ diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index 4106b09e0c29..d5146b98c8d1 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -514,8 +514,6 @@ ENTRY(cpu_feroceon_set_pte_ext) #endif mov pc, lr - __CPUINIT - .type __feroceon_setup, #function __feroceon_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index 0b60dd3d742a..40acba595731 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S @@ -383,8 +383,6 @@ ENTRY(cpu_mohawk_do_resume) ENDPROC(cpu_mohawk_do_resume) #endif - __CPUINIT - .type __mohawk_setup, #function __mohawk_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 775d70fba937..c45319c8f1d9 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -159,8 +159,6 @@ ENTRY(cpu_sa110_set_pte_ext) #endif mov pc, lr - __CPUINIT - .type __sa110_setup, #function __sa110_setup: mov r10, #0 diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index d92dfd081429..09d241ae2dbe 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -198,8 +198,6 @@ ENTRY(cpu_sa1100_do_resume) ENDPROC(cpu_sa1100_do_resume) #endif - __CPUINIT - .type __sa1100_setup, #function __sa1100_setup: mov r0, #0 diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 2d1ef87328a1..1128064fddcb 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -180,8 +180,6 @@ ENDPROC(cpu_v6_do_resume) .align - __CPUINIT - /* * __v6_setup * diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S index 9704097c450e..f64afb9f1bd5 100644 --- a/arch/arm/mm/proc-v7-2level.S +++ b/arch/arm/mm/proc-v7-2level.S @@ -160,8 +160,6 @@ ENDPROC(cpu_v7_set_pte_ext) mcr p15, 0, \ttbr1, c2, c0, 1 @ load TTB1 .endm - __CPUINIT - /* AT * TFR EV X F I D LR S * .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM @@ -172,5 +170,3 @@ ENDPROC(cpu_v7_set_pte_ext) .type v7_crval, #object v7_crval: crval clear=0x2120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c - - .previous diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S index 5ffe1956c6d9..c36ac69488c8 100644 --- a/arch/arm/mm/proc-v7-3level.S +++ b/arch/arm/mm/proc-v7-3level.S @@ -140,8 +140,6 @@ ENDPROC(cpu_v7_set_pte_ext) mcrr p15, 0, \ttbr0, \zero, c2 @ load TTBR0 .endm - __CPUINIT - /* * AT * TFR EV X F IHD LR S @@ -153,5 +151,3 @@ ENDPROC(cpu_v7_set_pte_ext) .type v7_crval, #object v7_crval: crval clear=0x0120c302, mmuset=0x30c23c7d, ucset=0x00c01c7c - - .previous diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 7ef3ad05df39..5c6d5a3050ea 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -167,8 +167,6 @@ ENDPROC(cpu_pj4b_do_idle) #endif - __CPUINIT - /* * __v7_setup * diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index e8efd83b6f25..dc1645890042 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -446,8 +446,6 @@ ENTRY(cpu_xsc3_do_resume) ENDPROC(cpu_xsc3_do_resume) #endif - __CPUINIT - .type __xsc3_setup, #function __xsc3_setup: mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index e766f889bfd6..d19b1cfcad91 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -558,8 +558,6 @@ ENTRY(cpu_xscale_do_resume) ENDPROC(cpu_xscale_do_resume) #endif - __CPUINIT - .type __xscale_setup, #function __xscale_setup: mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 1e1b2d769748..39895d892c3b 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -23,7 +23,7 @@ * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); @@ -33,7 +33,7 @@ static void __cpuinit write_pen_release(int val) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit versatile_secondary_init(unsigned int cpu) +void versatile_secondary_init(unsigned int cpu) { /* * let the primary processor know we're out of the @@ -48,7 +48,7 @@ void __cpuinit versatile_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) +int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; -- GitLab From 2066aadd53c563445039d6490b685783816270ec Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 17 Jun 2013 15:43:14 -0400 Subject: [PATCH 2757/2900] sparc: delete __cpuinit/__CPUINIT usage from all users The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/sparc uses of the __cpuinit macros from C files and removes __CPUINIT from assembly files. Note that even though arch/sparc/kernel/trampoline_64.S has instances of ".previous" in it, they are all paired off against explicit ".section" directives, and not implicitly paired with __CPUINIT (unlike mips and arm were). [1] https://lkml.org/lkml/2013/5/20/589 Cc: "David S. Miller" Cc: sparclinux@vger.kernel.org Signed-off-by: Paul Gortmaker --- arch/sparc/kernel/ds.c | 11 ++++------ arch/sparc/kernel/entry.h | 2 +- arch/sparc/kernel/hvtramp.S | 1 - arch/sparc/kernel/irq_64.c | 5 +++-- arch/sparc/kernel/leon_smp.c | 10 ++++----- arch/sparc/kernel/mdesc.c | 34 +++++++++++++++---------------- arch/sparc/kernel/smp_32.c | 20 +++++++++--------- arch/sparc/kernel/smp_64.c | 9 ++++---- arch/sparc/kernel/sun4d_smp.c | 6 +++--- arch/sparc/kernel/sun4m_smp.c | 6 +++--- arch/sparc/kernel/sysfs.c | 4 ++-- arch/sparc/kernel/trampoline_32.S | 3 --- arch/sparc/kernel/trampoline_64.S | 2 -- arch/sparc/mm/init_64.c | 2 +- arch/sparc/mm/srmmu.c | 12 +++++------ 15 files changed, 60 insertions(+), 67 deletions(-) diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 11d460f6f9cc..62d6b153ffa2 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -528,10 +528,8 @@ static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus, } } -static int __cpuinit dr_cpu_configure(struct ds_info *dp, - struct ds_cap_state *cp, - u64 req_num, - cpumask_t *mask) +static int dr_cpu_configure(struct ds_info *dp, struct ds_cap_state *cp, + u64 req_num, cpumask_t *mask) { struct ds_data *resp; int resp_len, ncpus, cpu; @@ -627,9 +625,8 @@ static int dr_cpu_unconfigure(struct ds_info *dp, return 0; } -static void __cpuinit dr_cpu_data(struct ds_info *dp, - struct ds_cap_state *cp, - void *buf, int len) +static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, + int len) { struct ds_data *data = buf; struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index cc3c5cb47cda..9c179fbfb219 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -250,7 +250,7 @@ extern struct ino_bucket *ivector_table; extern unsigned long ivector_table_pa; extern void init_irqwork_curcpu(void); -extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); +extern void sun4v_register_mondo_queues(int this_cpu); #endif /* CONFIG_SPARC32 */ #endif /* _ENTRY_H */ diff --git a/arch/sparc/kernel/hvtramp.S b/arch/sparc/kernel/hvtramp.S index 605c960b2fa6..4eb1a5a1d544 100644 --- a/arch/sparc/kernel/hvtramp.S +++ b/arch/sparc/kernel/hvtramp.S @@ -16,7 +16,6 @@ #include #include - __CPUINIT .align 8 .globl hv_cpu_startup, hv_cpu_startup_end diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 9bcbbe2c4e7e..d4840cec2c55 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -835,7 +835,8 @@ void notrace init_irqwork_curcpu(void) * Therefore you cannot make any OBP calls, not even prom_printf, * from these two routines. */ -static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) +static void notrace register_one_mondo(unsigned long paddr, unsigned long type, + unsigned long qmask) { unsigned long num_entries = (qmask + 1) / 64; unsigned long status; @@ -848,7 +849,7 @@ static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned l } } -void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) +void notrace sun4v_register_mondo_queues(int this_cpu) { struct trap_per_cpu *tb = &trap_block[this_cpu]; diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index d7aa524b7283..6edf955f987c 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -54,7 +54,7 @@ extern ctxd_t *srmmu_ctx_table_phys; static int smp_processors_ready; extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern cpumask_t smp_commenced_mask; -void __cpuinit leon_configure_cache_smp(void); +void leon_configure_cache_smp(void); static void leon_ipi_init(void); /* IRQ number of LEON IPIs */ @@ -69,12 +69,12 @@ static inline unsigned long do_swap(volatile unsigned long *ptr, return val; } -void __cpuinit leon_cpu_pre_starting(void *arg) +void leon_cpu_pre_starting(void *arg) { leon_configure_cache_smp(); } -void __cpuinit leon_cpu_pre_online(void *arg) +void leon_cpu_pre_online(void *arg) { int cpuid = hard_smp_processor_id(); @@ -106,7 +106,7 @@ void __cpuinit leon_cpu_pre_online(void *arg) extern struct linux_prom_registers smp_penguin_ctable; -void __cpuinit leon_configure_cache_smp(void) +void leon_configure_cache_smp(void) { unsigned long cfg = sparc_leon3_get_dcachecfg(); int me = smp_processor_id(); @@ -186,7 +186,7 @@ void __init leon_boot_cpus(void) } -int __cpuinit leon_boot_one_cpu(int i, struct task_struct *idle) +int leon_boot_one_cpu(int i, struct task_struct *idle) { int timeout; diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 831c001604e8..b90bf23e3aab 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -571,9 +571,7 @@ static void __init report_platform_properties(void) mdesc_release(hp); } -static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c, - struct mdesc_handle *hp, - u64 mp) +static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp) { const u64 *level = mdesc_get_property(hp, mp, "level", NULL); const u64 *size = mdesc_get_property(hp, mp, "size", NULL); @@ -616,7 +614,7 @@ static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c, } } -static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) +static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) { u64 a; @@ -649,7 +647,7 @@ static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id } } -static void __cpuinit set_core_ids(struct mdesc_handle *hp) +static void set_core_ids(struct mdesc_handle *hp) { int idx; u64 mp; @@ -674,7 +672,7 @@ static void __cpuinit set_core_ids(struct mdesc_handle *hp) } } -static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) +static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) { u64 a; @@ -693,7 +691,7 @@ static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id } } -static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name) +static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name) { int idx; u64 mp; @@ -714,14 +712,14 @@ static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_u } } -static void __cpuinit set_proc_ids(struct mdesc_handle *hp) +static void set_proc_ids(struct mdesc_handle *hp) { __set_proc_ids(hp, "exec_unit"); __set_proc_ids(hp, "exec-unit"); } -static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask, - unsigned long def, unsigned long max) +static void get_one_mondo_bits(const u64 *p, unsigned int *mask, + unsigned long def, unsigned long max) { u64 val; @@ -742,8 +740,8 @@ static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask, *mask = ((1U << def) * 64U) - 1U; } -static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp, - struct trap_per_cpu *tb) +static void get_mondo_data(struct mdesc_handle *hp, u64 mp, + struct trap_per_cpu *tb) { static int printed; const u64 *val; @@ -769,7 +767,7 @@ static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp, } } -static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask) +static void *mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask) { struct mdesc_handle *hp = mdesc_grab(); void *ret = NULL; @@ -799,7 +797,8 @@ static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handl return ret; } -static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) +static void *record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, + void *arg) { ncpus_probed++; #ifdef CONFIG_SMP @@ -808,7 +807,7 @@ static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpui return NULL; } -void __cpuinit mdesc_populate_present_mask(cpumask_t *mask) +void mdesc_populate_present_mask(cpumask_t *mask) { if (tlb_type != hypervisor) return; @@ -841,7 +840,8 @@ void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask) mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask); } -static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) +static void *fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, + void *arg) { const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL); struct trap_per_cpu *tb; @@ -890,7 +890,7 @@ static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpu return NULL; } -void __cpuinit mdesc_fill_in_cpu_data(cpumask_t *mask) +void mdesc_fill_in_cpu_data(cpumask_t *mask) { struct mdesc_handle *hp; diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index e3f2b81c23f1..a102bfba6ea8 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -39,7 +39,7 @@ #include "kernel.h" #include "irq.h" -volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; +volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; cpumask_t smp_commenced_mask = CPU_MASK_NONE; @@ -53,7 +53,7 @@ const struct sparc32_ipi_ops *sparc32_ipi_ops; * instruction which is much better... */ -void __cpuinit smp_store_cpu_info(int id) +void smp_store_cpu_info(int id) { int cpu_node; int mid; @@ -120,7 +120,7 @@ void cpu_panic(void) panic("SMP bolixed\n"); } -struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; +struct linux_prom_registers smp_penguin_ctable = { 0 }; void smp_send_reschedule(int cpu) { @@ -259,10 +259,10 @@ void __init smp_prepare_boot_cpu(void) set_cpu_possible(cpuid, true); } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - extern int __cpuinit smp4m_boot_one_cpu(int, struct task_struct *); - extern int __cpuinit smp4d_boot_one_cpu(int, struct task_struct *); + extern int smp4m_boot_one_cpu(int, struct task_struct *); + extern int smp4d_boot_one_cpu(int, struct task_struct *); int ret=0; switch(sparc_cpu_model) { @@ -297,7 +297,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) return ret; } -void __cpuinit arch_cpu_pre_starting(void *arg) +void arch_cpu_pre_starting(void *arg) { local_ops->cache_all(); local_ops->tlb_all(); @@ -317,7 +317,7 @@ void __cpuinit arch_cpu_pre_starting(void *arg) } } -void __cpuinit arch_cpu_pre_online(void *arg) +void arch_cpu_pre_online(void *arg) { unsigned int cpuid = hard_smp_processor_id(); @@ -344,7 +344,7 @@ void __cpuinit arch_cpu_pre_online(void *arg) } } -void __cpuinit sparc_start_secondary(void *arg) +void sparc_start_secondary(void *arg) { unsigned int cpu; @@ -375,7 +375,7 @@ void __cpuinit sparc_start_secondary(void *arg) BUG(); } -void __cpuinit smp_callin(void) +void smp_callin(void) { sparc_start_secondary(NULL); } diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 77539eda928c..e142545244f2 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -87,7 +87,7 @@ extern void setup_sparc64_timer(void); static volatile unsigned long callin_flag = 0; -void __cpuinit smp_callin(void) +void smp_callin(void) { int cpuid = hard_smp_processor_id(); @@ -281,7 +281,8 @@ static unsigned long kimage_addr_to_ra(void *p) return kern_base + (val - KERNBASE); } -static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp) +static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, + void **descrp) { extern unsigned long sparc64_ttable_tl0; extern unsigned long kern_locked_tte_data; @@ -342,7 +343,7 @@ extern unsigned long sparc64_cpu_startup; */ static struct thread_info *cpu_new_thread = NULL; -static int __cpuinit smp_boot_one_cpu(unsigned int cpu, struct task_struct *idle) +static int smp_boot_one_cpu(unsigned int cpu, struct task_struct *idle) { unsigned long entry = (unsigned long)(&sparc64_cpu_startup); @@ -1266,7 +1267,7 @@ void smp_fill_in_sib_core_maps(void) } } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { int ret = smp_boot_one_cpu(cpu, tidle); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index c9eb82f23d92..d5c319553fd0 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -50,7 +50,7 @@ static inline void show_leds(int cpuid) "i" (ASI_M_CTL)); } -void __cpuinit sun4d_cpu_pre_starting(void *arg) +void sun4d_cpu_pre_starting(void *arg) { int cpuid = hard_smp_processor_id(); @@ -62,7 +62,7 @@ void __cpuinit sun4d_cpu_pre_starting(void *arg) cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); } -void __cpuinit sun4d_cpu_pre_online(void *arg) +void sun4d_cpu_pre_online(void *arg) { unsigned long flags; int cpuid; @@ -118,7 +118,7 @@ void __init smp4d_boot_cpus(void) local_ops->cache_all(); } -int __cpuinit smp4d_boot_one_cpu(int i, struct task_struct *idle) +int smp4d_boot_one_cpu(int i, struct task_struct *idle) { unsigned long *entry = &sun4d_cpu_startup; int timeout; diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 8a65f158153d..d3408e72d20c 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -34,11 +34,11 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) return val; } -void __cpuinit sun4m_cpu_pre_starting(void *arg) +void sun4m_cpu_pre_starting(void *arg) { } -void __cpuinit sun4m_cpu_pre_online(void *arg) +void sun4m_cpu_pre_online(void *arg) { int cpuid = hard_smp_processor_id(); @@ -75,7 +75,7 @@ void __init smp4m_boot_cpus(void) local_ops->cache_all(); } -int __cpuinit smp4m_boot_one_cpu(int i, struct task_struct *idle) +int smp4m_boot_one_cpu(int i, struct task_struct *idle) { unsigned long *entry = &sun4m_cpu_startup; int timeout; diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index 654e8aad3bbe..c21c673e5f7c 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -246,7 +246,7 @@ static void unregister_cpu_online(unsigned int cpu) } #endif -static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, +static int sysfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; @@ -266,7 +266,7 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata sysfs_cpu_nb = { +static struct notifier_block sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S index 6cdb08cdabf0..76dcbd3c988a 100644 --- a/arch/sparc/kernel/trampoline_32.S +++ b/arch/sparc/kernel/trampoline_32.S @@ -18,7 +18,6 @@ .globl sun4m_cpu_startup .globl sun4d_cpu_startup - __CPUINIT .align 4 /* When we start up a cpu for the first time it enters this routine. @@ -94,7 +93,6 @@ smp_panic: /* CPUID in bootbus can be found at PA 0xff0140000 */ #define SUN4D_BOOTBUS_CPUID 0xf0140000 - __CPUINIT .align 4 sun4d_cpu_startup: @@ -146,7 +144,6 @@ sun4d_cpu_startup: b,a smp_panic - __CPUINIT .align 4 .global leon_smp_cpu_startup, smp_penguin_ctable diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S index 2e973a26fbda..e0b1e13a0736 100644 --- a/arch/sparc/kernel/trampoline_64.S +++ b/arch/sparc/kernel/trampoline_64.S @@ -32,13 +32,11 @@ itlb_load: dtlb_load: .asciz "SUNW,dtlb-load" - /* XXX __cpuinit this thing XXX */ #define TRAMP_STACK_SIZE 1024 .align 16 tramp_stack: .skip TRAMP_STACK_SIZE - __CPUINIT .align 8 .globl sparc64_cpu_startup, sparc64_cpu_startup_end sparc64_cpu_startup: diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index a9c42a7ffb6a..ed82edad1a39 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1694,7 +1694,7 @@ static void __init sun4v_ktsb_init(void) #endif } -void __cpuinit sun4v_ktsb_register(void) +void sun4v_ktsb_register(void) { unsigned long pa, ret; diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index 036c2797dece..5d721df48a72 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -858,7 +858,7 @@ static void __init map_kernel(void) } } -void (*poke_srmmu)(void) __cpuinitdata = NULL; +void (*poke_srmmu)(void) = NULL; extern unsigned long bootmem_init(unsigned long *pages_avail); @@ -1055,7 +1055,7 @@ static void __init init_vac_layout(void) (int)vac_cache_size, (int)vac_line_size); } -static void __cpuinit poke_hypersparc(void) +static void poke_hypersparc(void) { volatile unsigned long clear; unsigned long mreg = srmmu_get_mmureg(); @@ -1107,7 +1107,7 @@ static void __init init_hypersparc(void) hypersparc_setup_blockops(); } -static void __cpuinit poke_swift(void) +static void poke_swift(void) { unsigned long mreg; @@ -1287,7 +1287,7 @@ static void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long } -static void __cpuinit poke_turbosparc(void) +static void poke_turbosparc(void) { unsigned long mreg = srmmu_get_mmureg(); unsigned long ccreg; @@ -1350,7 +1350,7 @@ static void __init init_turbosparc(void) poke_srmmu = poke_turbosparc; } -static void __cpuinit poke_tsunami(void) +static void poke_tsunami(void) { unsigned long mreg = srmmu_get_mmureg(); @@ -1391,7 +1391,7 @@ static void __init init_tsunami(void) tsunami_setup_blockops(); } -static void __cpuinit poke_viking(void) +static void poke_viking(void) { unsigned long mreg = srmmu_get_mmureg(); static int smp_catch; -- GitLab From b8c6453aaf142620c2e1a4c2da24bbb10cb424bf Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 10:18:31 -0400 Subject: [PATCH 2758/2900] arm64: delete __cpuinit usage from all users The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/arm64 uses of the __cpuinit macros from all C files. Currently arm64 does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Catalin Marinas Cc: Will Deacon Acked-by: Catalin Marinas Signed-off-by: Paul Gortmaker --- arch/arm64/include/asm/arch_timer.h | 2 +- arch/arm64/kernel/debug-monitors.c | 6 +++--- arch/arm64/kernel/hw_breakpoint.c | 4 ++-- arch/arm64/kernel/smp.c | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index d56ed11ba9a3..98abd476992d 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -97,7 +97,7 @@ static inline u32 arch_timer_get_cntfrq(void) return val; } -static inline void __cpuinit arch_counter_set_user_access(void) +static inline void arch_counter_set_user_access(void) { u32 cntkctl; diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 08018e3df580..cbfacf7fb438 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -141,7 +141,7 @@ static void clear_os_lock(void *unused) isb(); } -static int __cpuinit os_lock_notify(struct notifier_block *self, +static int os_lock_notify(struct notifier_block *self, unsigned long action, void *data) { int cpu = (unsigned long)data; @@ -150,11 +150,11 @@ static int __cpuinit os_lock_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata os_lock_nb = { +static struct notifier_block os_lock_nb = { .notifier_call = os_lock_notify, }; -static int __cpuinit debug_monitors_init(void) +static int debug_monitors_init(void) { /* Clear the OS lock. */ smp_call_function(clear_os_lock, NULL, 1); diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 5ab825c59db9..329218ca9ffb 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -821,7 +821,7 @@ static void reset_ctrl_regs(void *unused) } } -static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self, +static int hw_breakpoint_reset_notify(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -831,7 +831,7 @@ static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hw_breakpoint_reset_nb = { +static struct notifier_block hw_breakpoint_reset_nb = { .notifier_call = hw_breakpoint_reset_notify, }; diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5d54e3717bf8..4a053b3d1728 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -71,7 +71,7 @@ static DEFINE_RAW_SPINLOCK(boot_lock); * in coherency or not. This is necessary for the hotplug code to work * reliably. */ -static void __cpuinit write_pen_release(u64 val) +static void write_pen_release(u64 val) { void *start = (void *)&secondary_holding_pen_release; unsigned long size = sizeof(secondary_holding_pen_release); @@ -84,7 +84,7 @@ static void __cpuinit write_pen_release(u64 val) * Boot a secondary CPU, and assign it the specified idle task. * This also gives us the initial stack to use for this CPU. */ -static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +static int boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; @@ -122,7 +122,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) static DECLARE_COMPLETION(cpu_running); -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -162,7 +162,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void __cpuinit secondary_start_kernel(void) +asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); -- GitLab From 13dff62d80e93f1cc65b4ad2dddedd12de720272 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 16:56:21 -0400 Subject: [PATCH 2759/2900] blackfin: delete __cpuinit usage from all blackfin files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/blackfin uses of the __cpuinit macros from all C files. Currently blackfin does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Mike Frysinger Cc: Bob Liu Cc: Sonic Zhang Cc: uclinux-dist-devel@blackfin.uclinux.org Acked-by: Mike Frysinger Signed-off-by: Paul Gortmaker --- arch/blackfin/kernel/perf_event.c | 2 +- arch/blackfin/kernel/setup.c | 4 ++-- arch/blackfin/mach-bf561/smp.c | 6 +++--- arch/blackfin/mach-common/cache-c.c | 4 ++-- arch/blackfin/mach-common/ints-priority.c | 2 +- arch/blackfin/mach-common/smp.c | 12 ++++++------ 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c index e47d19ae3e06..974e55496db3 100644 --- a/arch/blackfin/kernel/perf_event.c +++ b/arch/blackfin/kernel/perf_event.c @@ -468,7 +468,7 @@ static void bfin_pmu_setup(int cpu) memset(cpuhw, 0, sizeof(struct cpu_hw_events)); } -static int __cpuinit +static int bfin_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 107b306b06f1..19ad0637e8ff 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -99,7 +99,7 @@ void __init generate_cplb_tables(void) } #endif -void __cpuinit bfin_setup_caches(unsigned int cpu) +void bfin_setup_caches(unsigned int cpu) { #ifdef CONFIG_BFIN_ICACHE bfin_icache_init(icplb_tbl[cpu]); @@ -165,7 +165,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) #endif } -void __cpuinit bfin_setup_cpudata(unsigned int cpu) +void bfin_setup_cpudata(unsigned int cpu) { struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index c77a23bc9de3..11789beca75a 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -48,7 +48,7 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */ return -EINVAL; } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* Clone setup for peripheral interrupt sources from CoreA. */ bfin_write_SICB_IMASK0(bfin_read_SIC_IMASK0()); @@ -73,7 +73,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle) +int platform_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; @@ -154,7 +154,7 @@ void platform_clear_ipi(unsigned int cpu, int irq) * Setup core B's local core timer. * In SMP, core timer is used for clock event device. */ -void __cpuinit bfin_local_timer_setup(void) +void bfin_local_timer_setup(void) { #if defined(CONFIG_TICKSOURCE_CORETMR) struct irq_data *data = irq_get_irq_data(IRQ_CORETMR); diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c index a60a24f5035d..0e1e451fd7d8 100644 --- a/arch/blackfin/mach-common/cache-c.c +++ b/arch/blackfin/mach-common/cache-c.c @@ -52,7 +52,7 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, } #ifdef CONFIG_BFIN_ICACHE -void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) +void bfin_icache_init(struct cplb_entry *icplb_tbl) { bfin_cache_init(icplb_tbl, ICPLB_ADDR0, ICPLB_DATA0, IMEM_CONTROL, (IMC | ENICPLB)); @@ -60,7 +60,7 @@ void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) #endif #ifdef CONFIG_BFIN_DCACHE -void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) +void bfin_dcache_init(struct cplb_entry *dcplb_tbl) { /* * Anomaly notes: diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 6c0c6816a51a..d143fd8d2bc5 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1281,7 +1281,7 @@ static struct irq_chip bfin_gpio_irqchip = { .irq_set_wake = bfin_gpio_set_wake, }; -void __cpuinit init_exception_vectors(void) +void init_exception_vectors(void) { /* cannot program in software: * evt0 - emulation (jtag) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 961d8392e5e3..e546db2f4bc8 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -46,7 +46,7 @@ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); unsigned long blackfin_iflush_l1_entry[NR_CPUS]; #endif -struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; +struct blackfin_initial_pda initial_pda_coreb; enum ipi_message_type { BFIN_IPI_NONE, @@ -246,7 +246,7 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -259,7 +259,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) return ret; } -static void __cpuinit setup_secondary(unsigned int cpu) +static void setup_secondary(unsigned int cpu) { unsigned long ilat; @@ -277,7 +277,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; } -void __cpuinit secondary_start_kernel(void) +void secondary_start_kernel(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; @@ -402,7 +402,7 @@ EXPORT_SYMBOL(resync_core_dcache); #endif #ifdef CONFIG_HOTPLUG_CPU -int __cpuexit __cpu_disable(void) +int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -415,7 +415,7 @@ int __cpuexit __cpu_disable(void) static DECLARE_COMPLETION(cpu_killed); -int __cpuexit __cpu_die(unsigned int cpu) +int __cpu_die(unsigned int cpu) { return wait_for_completion_timeout(&cpu_killed, 5000); } -- GitLab From e2741f17584f9f5a6e9034b1357ac2152c800087 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:04:52 -0400 Subject: [PATCH 2760/2900] s390: delete __cpuinit usage from all s390 files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/s390 uses of the __cpuinit macros from all C files. Currently s390 does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Paul Gortmaker --- arch/s390/kernel/cache.c | 15 +++++++-------- arch/s390/kernel/perf_cpum_cf.c | 4 ++-- arch/s390/kernel/processor.c | 2 +- arch/s390/kernel/smp.c | 17 ++++++++--------- arch/s390/kernel/sysinfo.c | 2 +- arch/s390/kernel/vtime.c | 6 +++--- arch/s390/mm/fault.c | 4 ++-- 7 files changed, 24 insertions(+), 26 deletions(-) diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c index 64b24650e4f8..dd62071624be 100644 --- a/arch/s390/kernel/cache.c +++ b/arch/s390/kernel/cache.c @@ -173,7 +173,7 @@ static void __init cache_build_info(void) } } -static struct cache_dir *__cpuinit cache_create_cache_dir(int cpu) +static struct cache_dir *cache_create_cache_dir(int cpu) { struct cache_dir *cache_dir; struct kobject *kobj = NULL; @@ -289,9 +289,8 @@ static struct kobj_type cache_index_type = { .default_attrs = cache_index_default_attrs, }; -static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir, - struct cache *cache, int index, - int cpu) +static int cache_create_index_dir(struct cache_dir *cache_dir, + struct cache *cache, int index, int cpu) { struct cache_index_dir *index_dir; int rc; @@ -313,7 +312,7 @@ static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir, return rc; } -static int __cpuinit cache_add_cpu(int cpu) +static int cache_add_cpu(int cpu) { struct cache_dir *cache_dir; struct cache *cache; @@ -335,7 +334,7 @@ static int __cpuinit cache_add_cpu(int cpu) return 0; } -static void __cpuinit cache_remove_cpu(int cpu) +static void cache_remove_cpu(int cpu) { struct cache_index_dir *index, *next; struct cache_dir *cache_dir; @@ -354,8 +353,8 @@ static void __cpuinit cache_remove_cpu(int cpu) cache_dir_cpu[cpu] = NULL; } -static int __cpuinit cache_hotplug(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int cache_hotplug(struct notifier_block *nfb, unsigned long action, + void *hcpu) { int cpu = (long)hcpu; int rc = 0; diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 390d9ae57bb2..fb99c2057b85 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -639,8 +639,8 @@ static struct pmu cpumf_pmu = { .cancel_txn = cpumf_pmu_cancel_txn, }; -static int __cpuinit cpumf_pmu_notifier(struct notifier_block *self, - unsigned long action, void *hcpu) +static int cpumf_pmu_notifier(struct notifier_block *self, unsigned long action, + void *hcpu) { unsigned int cpu = (long) hcpu; int flags; diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 753c41d0ffd3..24612029f450 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -21,7 +21,7 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id); /* * cpu_init - initializes state that is per-CPU. */ -void __cpuinit cpu_init(void) +void cpu_init(void) { struct s390_idle_data *idle = &__get_cpu_var(s390_idle); struct cpuid *id = &__get_cpu_var(cpu_id); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 15a016c10563..d386c4e9d2e5 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -165,7 +165,7 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) pcpu_sigp_retry(pcpu, order, 0); } -static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) +static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) { struct _lowcore *lc; @@ -616,10 +616,9 @@ static struct sclp_cpu_info *smp_get_cpu_info(void) return info; } -static int __cpuinit smp_add_present_cpu(int cpu); +static int smp_add_present_cpu(int cpu); -static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info, - int sysfs_add) +static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) { struct pcpu *pcpu; cpumask_t avail; @@ -685,7 +684,7 @@ static void __init smp_detect_cpus(void) /* * Activate a secondary processor. */ -static void __cpuinit smp_start_secondary(void *cpuvoid) +static void smp_start_secondary(void *cpuvoid) { S390_lowcore.last_update_clock = get_tod_clock(); S390_lowcore.restart_stack = (unsigned long) restart_stack; @@ -708,7 +707,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid) } /* Upping and downing of CPUs */ -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { struct pcpu *pcpu; int rc; @@ -964,8 +963,8 @@ static struct attribute_group cpu_online_attr_group = { .attrs = cpu_online_attrs, }; -static int __cpuinit smp_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int smp_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; struct cpu *c = &pcpu_devices[cpu].cpu; @@ -983,7 +982,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, return notifier_from_errno(err); } -static int __cpuinit smp_add_present_cpu(int cpu) +static int smp_add_present_cpu(int cpu) { struct cpu *c = &pcpu_devices[cpu].cpu; struct device *s = &c->dev; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 62f89d98e880..811f542b8ed4 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -418,7 +418,7 @@ void s390_adjust_jiffies(void) /* * calibrate the delay loop */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { s390_adjust_jiffies(); /* Print the good old Bogomips line .. */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 3fb09359eda6..9b9c1b78ec67 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -371,14 +371,14 @@ EXPORT_SYMBOL(del_virt_timer); /* * Start the virtual CPU timer on the current CPU. */ -void __cpuinit init_cpu_vtimer(void) +void init_cpu_vtimer(void) { /* set initial cpu timer */ set_vtimer(VTIMER_MAX_SLICE); } -static int __cpuinit s390_nohz_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int s390_nohz_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { struct s390_idle_data *idle; long cpu = (long) hcpu; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 047c3e4c59a2..f00aefb66a4e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -639,8 +639,8 @@ static void pfault_interrupt(struct ext_code ext_code, put_task_struct(tsk); } -static int __cpuinit pfault_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int pfault_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { struct thread_struct *thread, *next; struct task_struct *tsk; -- GitLab From 4603f53a1dc3c76dfba841d123db9fa6204934f5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:10:12 -0400 Subject: [PATCH 2761/2900] sh: delete __cpuinit usage from all sh files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/sh uses of the __cpuinit macros from all C files. Currently sh does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Paul Mundt Cc: linux-sh@vger.kernel.org Signed-off-by: Paul Gortmaker --- arch/sh/kernel/cpu/init.c | 18 +++++++++--------- arch/sh/kernel/cpu/sh2/probe.c | 2 +- arch/sh/kernel/cpu/sh2a/probe.c | 2 +- arch/sh/kernel/cpu/sh3/probe.c | 2 +- arch/sh/kernel/cpu/sh4/probe.c | 2 +- arch/sh/kernel/cpu/sh4a/smp-shx3.c | 6 +++--- arch/sh/kernel/cpu/sh5/probe.c | 2 +- arch/sh/kernel/perf_event.c | 4 ++-- arch/sh/kernel/process.c | 2 +- arch/sh/kernel/setup.c | 2 +- arch/sh/kernel/smp.c | 8 ++++---- arch/sh/kernel/traps_32.c | 2 +- arch/sh/kernel/traps_64.c | 2 +- arch/sh/mm/tlb-sh5.c | 2 +- 14 files changed, 28 insertions(+), 28 deletions(-) diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 61a07dafcd46..ecf83cd158dc 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -43,9 +43,9 @@ * peripherals (nofpu, nodsp, and so forth). */ #define onchip_setup(x) \ -static int x##_disabled __cpuinitdata = !cpu_has_##x; \ +static int x##_disabled = !cpu_has_##x; \ \ -static int __cpuinit x##_setup(char *opts) \ +static int x##_setup(char *opts) \ { \ x##_disabled = 1; \ return 1; \ @@ -59,7 +59,7 @@ onchip_setup(dsp); #define CPUOPM 0xff2f0000 #define CPUOPM_RABD (1 << 5) -static void __cpuinit speculative_execution_init(void) +static void speculative_execution_init(void) { /* Clear RABD */ __raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM); @@ -78,7 +78,7 @@ static void __cpuinit speculative_execution_init(void) #define EXPMASK_BRDSSLP (1 << 1) #define EXPMASK_MMCAW (1 << 4) -static void __cpuinit expmask_init(void) +static void expmask_init(void) { unsigned long expmask = __raw_readl(EXPMASK); @@ -217,7 +217,7 @@ static void detect_cache_shape(void) l2_cache_shape = -1; /* No S-cache */ } -static void __cpuinit fpu_init(void) +static void fpu_init(void) { /* Disable the FPU */ if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) { @@ -230,7 +230,7 @@ static void __cpuinit fpu_init(void) } #ifdef CONFIG_SH_DSP -static void __cpuinit release_dsp(void) +static void release_dsp(void) { unsigned long sr; @@ -244,7 +244,7 @@ static void __cpuinit release_dsp(void) ); } -static void __cpuinit dsp_init(void) +static void dsp_init(void) { unsigned long sr; @@ -276,7 +276,7 @@ static void __cpuinit dsp_init(void) release_dsp(); } #else -static inline void __cpuinit dsp_init(void) { } +static inline void dsp_init(void) { } #endif /* CONFIG_SH_DSP */ /** @@ -295,7 +295,7 @@ static inline void __cpuinit dsp_init(void) { } * Each processor family is still responsible for doing its own probing * and cache configuration in cpu_probe(). */ -asmlinkage void __cpuinit cpu_init(void) +asmlinkage void cpu_init(void) { current_thread_info()->cpu = hard_smp_processor_id(); diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index bab8e75958ae..6c687ae812ef 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -13,7 +13,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { #if defined(CONFIG_CPU_SUBTYPE_SH7619) boot_cpu_data.type = CPU_SH7619; diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 5170b6aa4129..3f87971082f1 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -13,7 +13,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { boot_cpu_data.family = CPU_FAMILY_SH2A; diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c index bf23c322e164..426e1e1dcedc 100644 --- a/arch/sh/kernel/cpu/sh3/probe.c +++ b/arch/sh/kernel/cpu/sh3/probe.c @@ -16,7 +16,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long addr0, addr1, data0, data1, data2, data3; diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 0fbbd50bc8ad..a521bcf50695 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -15,7 +15,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long pvr, prr, cvr; unsigned long size; diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 03f2b55757cf..4a298808789c 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -124,7 +124,7 @@ static void shx3_update_boot_vector(unsigned int cpu) __raw_writel(STBCR_RESET, STBCR_REG(cpu)); } -static int __cpuinit +static int shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)hcpu; @@ -143,11 +143,11 @@ shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata shx3_cpu_notifier = { +static struct notifier_block shx3_cpu_notifier = { .notifier_call = shx3_cpu_callback, }; -static int __cpuinit register_shx3_cpu_notifier(void) +static int register_shx3_cpu_notifier(void) { register_hotcpu_notifier(&shx3_cpu_notifier); return 0; diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 9e882409e4e9..eca427c2f2f3 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -17,7 +17,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long long cir; diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c index 068b8a2759b5..b9cefebda55c 100644 --- a/arch/sh/kernel/perf_event.c +++ b/arch/sh/kernel/perf_event.c @@ -367,7 +367,7 @@ static void sh_pmu_setup(int cpu) memset(cpuhw, 0, sizeof(struct cpu_hw_events)); } -static int __cpuinit +static int sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; @@ -384,7 +384,7 @@ sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) return NOTIFY_OK; } -int __cpuinit register_sh_pmu(struct sh_pmu *_pmu) +int register_sh_pmu(struct sh_pmu *_pmu) { if (sh_pmu) return -EBUSY; diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 055d91b70305..53bc6c4c84ec 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -65,7 +65,7 @@ void arch_task_cache_init(void) # define HAVE_SOFTFP 0 #endif -void __cpuinit init_thread_xstate(void) +void init_thread_xstate(void) { if (boot_cpu_data.flags & CPU_HAS_FPU) xstate_size = sizeof(struct sh_fpu_hard_struct); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index ebe7a7d97215..1cf90e947dbf 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -172,7 +172,7 @@ void __init check_for_initrd(void) #endif } -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { struct clk *clk = clk_get(NULL, "cpu_clk"); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 45696451f0ea..86a7936a980b 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -37,7 +37,7 @@ struct plat_smp_ops *mp_ops = NULL; /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -void __cpuinit register_smp_ops(struct plat_smp_ops *ops) +void register_smp_ops(struct plat_smp_ops *ops) { if (mp_ops) printk(KERN_WARNING "Overriding previously set SMP ops\n"); @@ -45,7 +45,7 @@ void __cpuinit register_smp_ops(struct plat_smp_ops *ops) mp_ops = ops; } -static inline void __cpuinit smp_store_cpu_info(unsigned int cpu) +static inline void smp_store_cpu_info(unsigned int cpu) { struct sh_cpuinfo *c = cpu_data + cpu; @@ -174,7 +174,7 @@ void native_play_dead(void) } #endif -asmlinkage void __cpuinit start_secondary(void) +asmlinkage void start_secondary(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; @@ -215,7 +215,7 @@ extern struct { void *thread_info; } stack_start; -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tsk) +int __cpu_up(unsigned int cpu, struct task_struct *tsk) { unsigned long timeout; diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 5f513a64dedf..68e99f09171d 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -741,7 +741,7 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, die_if_kernel("exception", regs, ex); } -void __cpuinit per_cpu_trap_init(void) +void per_cpu_trap_init(void) { extern void *vbr_base; diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index f87d20da1791..112ea11c030d 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -810,7 +810,7 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); } -void __cpuinit per_cpu_trap_init(void) +void per_cpu_trap_init(void) { /* Nothing to do for now, VBR initialization later. */ } diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c index ff1c40a31cbc..e4bb2a8e0a69 100644 --- a/arch/sh/mm/tlb-sh5.c +++ b/arch/sh/mm/tlb-sh5.c @@ -17,7 +17,7 @@ /** * sh64_tlb_init - Perform initial setup for the DTLB and ITLB. */ -int __cpuinit sh64_tlb_init(void) +int sh64_tlb_init(void) { /* Assign some sane DTLB defaults */ cpu_data->dtlb.entries = 64; -- GitLab From 18f894c145e8515c26da09dd95e06d6b1158775c Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:28:07 -0400 Subject: [PATCH 2762/2900] tile: delete __cpuinit usage from all tile files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/tile uses of the __cpuinit macros from all C files. Currently tile does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Chris Metcalf Signed-off-by: Paul Gortmaker --- arch/tile/kernel/irq.c | 2 +- arch/tile/kernel/messaging.c | 2 +- arch/tile/kernel/setup.c | 12 ++++++------ arch/tile/kernel/smpboot.c | 8 ++++---- arch/tile/kernel/time.c | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index 02e628065012..3ccf2cd7182e 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c @@ -220,7 +220,7 @@ void __init init_IRQ(void) ipi_init(); } -void __cpuinit setup_irq_regs(void) +void setup_irq_regs(void) { /* Enable interrupt delivery. */ unmask_irqs(~0UL); diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c index 0858ee6b520f..00331af9525d 100644 --- a/arch/tile/kernel/messaging.c +++ b/arch/tile/kernel/messaging.c @@ -25,7 +25,7 @@ /* All messages are stored here */ static DEFINE_PER_CPU(HV_MsgState, msg_state); -void __cpuinit init_messaging(void) +void init_messaging(void) { /* Allocate storage for messages in kernel space */ HV_MsgState *state = &__get_cpu_var(msg_state); diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 68b542677f6a..eceb8344280f 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -58,8 +58,8 @@ struct pglist_data node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); /* Information on the NUMA nodes that we compute early */ -unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; -unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; +unsigned long node_start_pfn[MAX_NUMNODES]; +unsigned long node_end_pfn[MAX_NUMNODES]; unsigned long __initdata node_memmap_pfn[MAX_NUMNODES]; unsigned long __initdata node_percpu_pfn[MAX_NUMNODES]; unsigned long __initdata node_free_pfn[MAX_NUMNODES]; @@ -84,7 +84,7 @@ unsigned long __initdata boot_pc = (unsigned long)start_kernel; #ifdef CONFIG_HIGHMEM /* Page frame index of end of lowmem on each controller. */ -unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES]; +unsigned long node_lowmem_end_pfn[MAX_NUMNODES]; /* Number of pages that can be mapped into lowmem. */ static unsigned long __initdata mappable_physpages; @@ -290,7 +290,7 @@ static void *__init setup_pa_va_mapping(void) * This is up to 4 mappings for lowmem, one mapping per memory * controller, plus one for our text segment. */ -static void __cpuinit store_permanent_mappings(void) +static void store_permanent_mappings(void) { int i; @@ -935,7 +935,7 @@ subsys_initcall(topology_init); * So the values we set up here in the hypervisor may be overridden on * the boot cpu as arguments are parsed. */ -static __cpuinit void init_super_pages(void) +static void init_super_pages(void) { #ifdef CONFIG_HUGETLB_SUPER_PAGES int i; @@ -950,7 +950,7 @@ static __cpuinit void init_super_pages(void) * * Called from setup_arch() on the boot cpu, or online_secondary(). */ -void __cpuinit setup_cpu(int boot) +void setup_cpu(int boot) { /* The boot cpu sets up its permanent mappings much earlier. */ if (!boot) diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index 44bab29bf2f3..a535655b7089 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c @@ -133,14 +133,14 @@ static __init int reset_init_affinity(void) } late_initcall(reset_init_affinity); -static struct cpumask cpu_started __cpuinitdata; +static struct cpumask cpu_started; /* * Activate a secondary processor. Very minimal; don't add anything * to this path without knowing what you're doing, since SMP booting * is pretty fragile. */ -static void __cpuinit start_secondary(void) +static void start_secondary(void) { int cpuid = smp_processor_id(); @@ -183,7 +183,7 @@ static void __cpuinit start_secondary(void) /* * Bring a secondary processor online. */ -void __cpuinit online_secondary(void) +void online_secondary(void) { /* * low-memory mappings have been cleared, flush them from @@ -210,7 +210,7 @@ void __cpuinit online_secondary(void) cpu_startup_entry(CPUHP_ONLINE); } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { /* Wait 5s total for all CPUs for them to come online */ static int timeout; diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 5ac397ec6986..7c353d8c2da9 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -159,7 +159,7 @@ static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { .set_mode = tile_timer_set_mode, }; -void __cpuinit setup_tile_timer(void) +void setup_tile_timer(void) { struct clock_event_device *evt = &__get_cpu_var(tile_timer); -- GitLab From 54be16e7b2c96793bee4bf472409e9d31bc77c78 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:40:47 -0400 Subject: [PATCH 2763/2900] metag: delete __cpuinit usage from all metag files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/metag uses of the __cpuinit macros from all C files. Currently metag does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: James Hogan Acked-by: James Hogan Signed-off-by: Paul Gortmaker --- arch/metag/kernel/perf/perf_event.c | 6 +++--- arch/metag/kernel/smp.c | 22 ++++++++++------------ arch/metag/kernel/traps.c | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c index 5b18888ee364..5cc4d4dcf3cf 100644 --- a/arch/metag/kernel/perf/perf_event.c +++ b/arch/metag/kernel/perf/perf_event.c @@ -813,8 +813,8 @@ static struct metag_pmu _metag_pmu = { }; /* PMU CPU hotplug notifier */ -static int __cpuinit metag_pmu_cpu_notify(struct notifier_block *b, - unsigned long action, void *hcpu) +static int metag_pmu_cpu_notify(struct notifier_block *b, unsigned long action, + void *hcpu) { unsigned int cpu = (unsigned int)hcpu; struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); @@ -828,7 +828,7 @@ static int __cpuinit metag_pmu_cpu_notify(struct notifier_block *b, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata metag_pmu_notifier = { +static struct notifier_block metag_pmu_notifier = { .notifier_call = metag_pmu_cpu_notify, }; diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index e413875cf6d2..7c0113142981 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c @@ -68,7 +68,7 @@ static DECLARE_COMPLETION(cpu_running); /* * "thread" is assumed to be a valid Meta hardware thread ID. */ -int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle) +int boot_secondary(unsigned int thread, struct task_struct *idle) { u32 val; @@ -118,11 +118,9 @@ int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle) * If the cache partition has changed, prints a message to the log describing * those changes. */ -static __cpuinit void describe_cachepart_change(unsigned int thread, - const char *label, - unsigned int sz, - unsigned int old, - unsigned int new) +static void describe_cachepart_change(unsigned int thread, const char *label, + unsigned int sz, unsigned int old, + unsigned int new) { unsigned int lor1, land1, gor1, gand1; unsigned int lor2, land2, gor2, gand2; @@ -170,7 +168,7 @@ static __cpuinit void describe_cachepart_change(unsigned int thread, * Ensures that coherency is enabled and that the threads share the same cache * partitions. */ -static __cpuinit void setup_smp_cache(unsigned int thread) +static void setup_smp_cache(unsigned int thread) { unsigned int this_thread, lflags; unsigned int dcsz, dcpart_this, dcpart_old, dcpart_new; @@ -215,7 +213,7 @@ static __cpuinit void setup_smp_cache(unsigned int thread) icpart_old, icpart_new); } -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { unsigned int thread = cpu_2_hwthread_id[cpu]; int ret; @@ -268,7 +266,7 @@ static DECLARE_COMPLETION(cpu_killed); /* * __cpu_disable runs on the processor to be shutdown. */ -int __cpuexit __cpu_disable(void) +int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -299,7 +297,7 @@ int __cpuexit __cpu_disable(void) * called on the thread which is asking for a CPU to be shutdown - * waits until shutdown has completed, or it is timed out. */ -void __cpuexit __cpu_die(unsigned int cpu) +void __cpu_die(unsigned int cpu) { if (!wait_for_completion_timeout(&cpu_killed, msecs_to_jiffies(1))) pr_err("CPU%u: unable to kill\n", cpu); @@ -311,7 +309,7 @@ void __cpuexit __cpu_die(unsigned int cpu) * Note that we do not return from this function. If this cpu is * brought online again it will need to run secondary_startup(). */ -void __cpuexit cpu_die(void) +void cpu_die(void) { local_irq_disable(); idle_task_exit(); @@ -326,7 +324,7 @@ void __cpuexit cpu_die(void) * Called by both boot and secondaries to move global data into * per-processor storage. */ -void __cpuinit smp_store_cpu_info(unsigned int cpuid) +void smp_store_cpu_info(unsigned int cpuid) { struct cpuinfo_metag *cpu_info = &per_cpu(cpu_data, cpuid); diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c index c00ade0228ef..25f9d1c2ffec 100644 --- a/arch/metag/kernel/traps.c +++ b/arch/metag/kernel/traps.c @@ -812,7 +812,7 @@ static void set_trigger_mask(unsigned int mask) } #endif -void __cpuinit per_cpu_trap_init(unsigned long cpu) +void per_cpu_trap_init(unsigned long cpu) { TBIRES int_context; unsigned int thread = cpu_2_hwthread_id[cpu]; -- GitLab From 2de6c0bd689bdb5d6d8e4d20c5032a7f397487a8 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:48 -0400 Subject: [PATCH 2764/2900] cris: delete __cpuinit usage from all cris files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/cris uses of the __cpuinit macros from all C files. Currently cris does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Mikael Starvik Cc: Jesper Nilsson Cc: linux-cris-kernel@axis.com Acked-by: Jesper Nilsson Signed-off-by: Paul Gortmaker --- arch/cris/arch-v32/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index cdd12028de0c..fe8e6039db2a 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -197,7 +197,7 @@ int setup_profiling_timer(unsigned int multiplier) */ unsigned long cache_decay_ticks = 1; -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { smp_boot_one_cpu(cpu, tidle); return cpu_online(cpu) ? 0 : -ENOSYS; -- GitLab From ec460ae52ef51eb329e08deda6beb97b1cc37d99 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:48 -0400 Subject: [PATCH 2765/2900] frv: delete __cpuinit usage from all frv files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/frv uses of the __cpuinit macros from all C files. Currently frv does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: David Howells Signed-off-by: Paul Gortmaker --- arch/frv/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index ae3a6706419b..9f3a7a62d787 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -709,7 +709,7 @@ static void __init reserve_dma_coherent(void) /* * calibrate the delay loop */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ); -- GitLab From 7ddc839977cf4aa2c643a2f0405aa79daa72dc07 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:48 -0400 Subject: [PATCH 2766/2900] hexagon: delete __cpuinit usage from all hexagon files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/hexagon uses of the __cpuinit macros from all C files. Currently hexagon does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Richard Kuo Acked-by: Richard Kuo Cc: linux-hexagon@vger.kernel.org Signed-off-by: Paul Gortmaker --- arch/hexagon/kernel/setup.c | 2 +- arch/hexagon/kernel/smp.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c index bfe13311d70d..29d1f1b00016 100644 --- a/arch/hexagon/kernel/setup.c +++ b/arch/hexagon/kernel/setup.c @@ -41,7 +41,7 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; int on_simulator; -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = thread_freq_mhz * 1000000 / HZ; } diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 0e364ca43198..9faaa940452b 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -146,7 +146,7 @@ void __init smp_prepare_boot_cpu(void) * to point to current thread info */ -void __cpuinit start_secondary(void) +void start_secondary(void) { unsigned int cpu; unsigned long thread_ptr; @@ -194,7 +194,7 @@ void __cpuinit start_secondary(void) * maintains control until "cpu_online(cpu)" is set. */ -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { struct thread_info *thread = (struct thread_info *)idle->stack; void *stack_start; -- GitLab From d1407fde791285d1ffd4c7af6b666987d1213f6a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:49 -0400 Subject: [PATCH 2767/2900] m32r: delete __cpuinit usage from all m32r files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/m32r uses of the __cpuinit macros from all C files. Currently m32r does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Hirokazu Takata Cc: linux-m32r@ml.linux-m32r.org Cc: linux-m32r-ja@ml.linux-m32r.org Signed-off-by: Paul Gortmaker --- arch/m32r/kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index 0ac558adc605..bb21f4f63170 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -343,7 +343,7 @@ static void __init do_boot_cpu(int phys_id) } } -int __cpuinit __cpu_up(unsigned int cpu_id, struct task_struct *tidle) +int __cpu_up(unsigned int cpu_id, struct task_struct *tidle) { int timeout; -- GitLab From 8e8550ef01676829f4d4b175a1ce4fee30f7a778 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:49 -0400 Subject: [PATCH 2768/2900] openrisc: delete __cpuinit usage from all openrisc files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/openrisc uses of the __cpuinit macros from all C files. Currently openrisc does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Jonas Bonn Cc: linux@lists.openrisc.net Signed-off-by: Paul Gortmaker --- arch/openrisc/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c index f4d5bedc3b4f..d7359ffbcbdd 100644 --- a/arch/openrisc/kernel/setup.c +++ b/arch/openrisc/kernel/setup.c @@ -267,7 +267,7 @@ void __init detect_unit_config(unsigned long upr, unsigned long mask, * */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { const int *val; struct device_node *cpu = NULL; -- GitLab From 6cb4c159b0b8825ea8ea8ae4d6e72c9970af3993 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 17:54:49 -0400 Subject: [PATCH 2769/2900] xtensa: delete __cpuinit usage from all xtensa files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/xtensa uses of the __cpuinit macros from all C files. Currently xtensa does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Chris Zankel Cc: Max Filippov Cc: linux-xtensa@linux-xtensa.org Signed-off-by: Paul Gortmaker --- arch/xtensa/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index bdbb17312526..24bb0c1776ba 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -162,7 +162,7 @@ irqreturn_t timer_interrupt (int irq, void *dev_id) } #ifndef CONFIG_GENERIC_CALIBRATE_DELAY -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = CCOUNT_PER_JIFFY; printk("Calibrating delay loop (skipped)... " -- GitLab From 70e2a7bf23a0c412b908ba260e790a4f51c9f2b0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 18:09:02 -0400 Subject: [PATCH 2770/2900] score: delete __cpuinit usage from all score files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/score uses of the __cpuinit macros from all C files. Currently score does not have any __CPUINIT used in assembly files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Chen Liqin Cc: Lennox Wu Signed-off-by: Paul Gortmaker --- arch/score/mm/tlb-score.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/score/mm/tlb-score.c b/arch/score/mm/tlb-score.c index 6fdb100244c8..004073717de0 100644 --- a/arch/score/mm/tlb-score.c +++ b/arch/score/mm/tlb-score.c @@ -240,7 +240,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) local_irq_restore(flags); } -void __cpuinit tlb_init(void) +void tlb_init(void) { tlblock_set(0); local_flush_tlb_all(); -- GitLab From 148f9bb87745ed45f7a11b2cbd3bc0f017d5d257 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 18 Jun 2013 18:23:59 -0400 Subject: [PATCH 2771/2900] x86: delete __cpuinit usage from all x86 files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. Note that some harmless section mismatch warnings may result, since notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c) are flagged as __cpuinit -- so if we remove the __cpuinit from arch specific callers, we will also get section mismatch warnings. As an intermediate step, we intend to turn the linux/init.h cpuinit content into no-ops as early as possible, since that will get rid of these warnings. In any case, they are temporary and harmless. This removes all the arch/x86 uses of the __cpuinit macros from all C files. x86 only had the one __CPUINIT used in assembly files, and it wasn't paired off with a .previous or a __FINIT, so we can delete it directly w/o any corresponding additional change there. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x86@kernel.org Acked-by: Ingo Molnar Acked-by: Thomas Gleixner Acked-by: H. Peter Anvin Signed-off-by: Paul Gortmaker --- arch/x86/include/asm/cpu.h | 2 +- arch/x86/include/asm/microcode.h | 4 +- arch/x86/include/asm/microcode_amd.h | 4 +- arch/x86/include/asm/microcode_intel.h | 4 +- arch/x86/include/asm/mmconfig.h | 4 +- arch/x86/include/asm/mpspec.h | 2 +- arch/x86/include/asm/numa.h | 6 +- arch/x86/include/asm/processor.h | 2 +- arch/x86/include/asm/prom.h | 2 +- arch/x86/include/asm/smp.h | 2 +- arch/x86/kernel/acpi/boot.c | 6 +- arch/x86/kernel/apic/apic.c | 30 ++++----- arch/x86/kernel/apic/apic_numachip.c | 2 +- arch/x86/kernel/apic/es7000_32.c | 2 +- arch/x86/kernel/apic/numaq_32.c | 2 +- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- arch/x86/kernel/apic/x2apic_uv_x.c | 14 ++-- arch/x86/kernel/cpu/amd.c | 33 +++++----- arch/x86/kernel/cpu/centaur.c | 26 ++++---- arch/x86/kernel/cpu/common.c | 64 +++++++++---------- arch/x86/kernel/cpu/cyrix.c | 40 ++++++------ arch/x86/kernel/cpu/hypervisor.c | 2 +- arch/x86/kernel/cpu/intel.c | 30 ++++----- arch/x86/kernel/cpu/intel_cacheinfo.c | 55 ++++++++-------- arch/x86/kernel/cpu/mcheck/mce.c | 23 ++++--- arch/x86/kernel/cpu/mcheck/mce_amd.c | 14 ++-- arch/x86/kernel/cpu/mcheck/therm_throt.c | 9 ++- arch/x86/kernel/cpu/perf_event.c | 2 +- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 2 +- arch/x86/kernel/cpu/perf_event_amd_uncore.c | 31 +++++---- arch/x86/kernel/cpu/perf_event_intel_uncore.c | 20 +++--- arch/x86/kernel/cpu/rdrand.c | 2 +- arch/x86/kernel/cpu/scattered.c | 4 +- arch/x86/kernel/cpu/topology.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 6 +- arch/x86/kernel/cpu/umc.c | 2 +- arch/x86/kernel/cpu/vmware.c | 2 +- arch/x86/kernel/cpuid.c | 7 +- arch/x86/kernel/devicetree.c | 2 +- arch/x86/kernel/head_32.S | 1 - arch/x86/kernel/i387.c | 10 +-- arch/x86/kernel/irq_32.c | 2 +- arch/x86/kernel/kvm.c | 10 +-- arch/x86/kernel/kvmclock.c | 2 +- arch/x86/kernel/microcode_amd_early.c | 8 +-- arch/x86/kernel/microcode_core.c | 2 +- arch/x86/kernel/microcode_core_early.c | 6 +- arch/x86/kernel/microcode_intel_early.c | 26 ++++---- arch/x86/kernel/mmconf-fam10h_64.c | 12 ++-- arch/x86/kernel/msr.c | 6 +- arch/x86/kernel/process.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 28 ++++---- arch/x86/kernel/tboot.c | 6 +- arch/x86/kernel/tsc.c | 4 +- arch/x86/kernel/tsc_sync.c | 18 +++--- arch/x86/kernel/vsyscall_64.c | 6 +- arch/x86/kernel/x86_init.c | 4 +- arch/x86/kernel/xsave.c | 4 +- arch/x86/mm/mmio-mod.c | 4 +- arch/x86/mm/numa.c | 12 ++-- arch/x86/mm/numa_emulation.c | 12 ++-- arch/x86/mm/setup_nx.c | 4 +- arch/x86/pci/amd_bus.c | 8 +-- arch/x86/platform/ce4100/ce4100.c | 2 +- arch/x86/platform/mrst/mrst.c | 4 +- arch/x86/xen/enlighten.c | 6 +- arch/x86/xen/setup.c | 6 +- arch/x86/xen/smp.c | 12 ++-- arch/x86/xen/spinlock.c | 2 +- arch/x86/xen/xen-ops.h | 2 +- 71 files changed, 345 insertions(+), 356 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 5f9a1243190e..d2b12988d2ed 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -28,7 +28,7 @@ struct x86_cpu { #ifdef CONFIG_HOTPLUG_CPU extern int arch_register_cpu(int num); extern void arch_unregister_cpu(int); -extern void __cpuinit start_cpu0(void); +extern void start_cpu0(void); #ifdef CONFIG_DEBUG_HOTPLUG_CPU0 extern int _debug_hotplug_cpu(int cpu, int action); #endif diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index 6bc3985ee473..f98bd6625318 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h @@ -60,11 +60,11 @@ static inline void __exit exit_amd_microcode(void) {} #ifdef CONFIG_MICROCODE_EARLY #define MAX_UCODE_COUNT 128 extern void __init load_ucode_bsp(void); -extern void __cpuinit load_ucode_ap(void); +extern void load_ucode_ap(void); extern int __init save_microcode_in_initrd(void); #else static inline void __init load_ucode_bsp(void) {} -static inline void __cpuinit load_ucode_ap(void) {} +static inline void load_ucode_ap(void) {} static inline int __init save_microcode_in_initrd(void) { return 0; diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index c6b043f40271..50e5c58ced23 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h @@ -67,11 +67,11 @@ extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size) extern u8 amd_bsp_mpb[MPB_MAX_SIZE]; #endif extern void __init load_ucode_amd_bsp(void); -extern void __cpuinit load_ucode_amd_ap(void); +extern void load_ucode_amd_ap(void); extern int __init save_microcode_in_initrd_amd(void); #else static inline void __init load_ucode_amd_bsp(void) {} -static inline void __cpuinit load_ucode_amd_ap(void) {} +static inline void load_ucode_amd_ap(void) {} static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } #endif diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h index 87a085333cbf..9067166409bf 100644 --- a/arch/x86/include/asm/microcode_intel.h +++ b/arch/x86/include/asm/microcode_intel.h @@ -65,12 +65,12 @@ update_match_revision(struct microcode_header_intel *mc_header, int rev); #ifdef CONFIG_MICROCODE_INTEL_EARLY extern void __init load_ucode_intel_bsp(void); -extern void __cpuinit load_ucode_intel_ap(void); +extern void load_ucode_intel_ap(void); extern void show_ucode_info_early(void); extern int __init save_microcode_in_initrd_intel(void); #else static inline __init void load_ucode_intel_bsp(void) {} -static inline __cpuinit void load_ucode_intel_ap(void) {} +static inline void load_ucode_intel_ap(void) {} static inline void show_ucode_info_early(void) {} static inline int __init save_microcode_in_initrd_intel(void) { return -EINVAL; } #endif diff --git a/arch/x86/include/asm/mmconfig.h b/arch/x86/include/asm/mmconfig.h index 9b119da1d105..04a3fed22cfe 100644 --- a/arch/x86/include/asm/mmconfig.h +++ b/arch/x86/include/asm/mmconfig.h @@ -2,8 +2,8 @@ #define _ASM_X86_MMCONFIG_H #ifdef CONFIG_PCI_MMCONFIG -extern void __cpuinit fam10h_check_enable_mmcfg(void); -extern void __cpuinit check_enable_amd_mmconf_dmi(void); +extern void fam10h_check_enable_mmcfg(void); +extern void check_enable_amd_mmconf_dmi(void); #else static inline void fam10h_check_enable_mmcfg(void) { } static inline void check_enable_amd_mmconf_dmi(void) { } diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 3e2f42a4b872..626cf70082d7 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { } #define default_get_smp_config x86_init_uint_noop #endif -void __cpuinit generic_processor_info(int apicid, int version); +void generic_processor_info(int apicid, int version); #ifdef CONFIG_ACPI extern void mp_register_ioapic(int id, u32 address, u32 gsi_base); extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h index 1b99ee5c9f00..4064acae625d 100644 --- a/arch/x86/include/asm/numa.h +++ b/arch/x86/include/asm/numa.h @@ -39,7 +39,7 @@ static inline void set_apicid_to_node(int apicid, s16 node) __apicid_to_node[apicid] = node; } -extern int __cpuinit numa_cpu_node(int cpu); +extern int numa_cpu_node(int cpu); #else /* CONFIG_NUMA */ static inline void set_apicid_to_node(int apicid, s16 node) @@ -60,8 +60,8 @@ static inline int numa_cpu_node(int cpu) extern void numa_set_node(int cpu, int node); extern void numa_clear_node(int cpu); extern void __init init_cpu_to_node(void); -extern void __cpuinit numa_add_cpu(int cpu); -extern void __cpuinit numa_remove_cpu(int cpu); +extern void numa_add_cpu(int cpu); +extern void numa_remove_cpu(int cpu); #else /* CONFIG_NUMA */ static inline void numa_set_node(int cpu, int node) { } static inline void numa_clear_node(int cpu) { } diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 29937c4f6ff8..24cf5aefb704 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -164,7 +164,7 @@ extern const struct seq_operations cpuinfo_op; #define cache_line_size() (boot_cpu_data.x86_cache_alignment) extern void cpu_detect(struct cpuinfo_x86 *c); -extern void __cpuinit fpu_detect(struct cpuinfo_x86 *c); +extern void fpu_detect(struct cpuinfo_x86 *c); extern void early_cpu_init(void); extern void identify_boot_cpu(void); diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 60bef663609a..bade6ac3b14f 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -27,7 +27,7 @@ extern int of_ioapic; extern u64 initial_dtb; extern void add_dtb(u64 data); extern void x86_add_irq_domains(void); -void __cpuinit x86_of_pci_init(void); +void x86_of_pci_init(void); void x86_dtb_init(void); #else static inline void add_dtb(u64 data) { } diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index b073aaea747c..4137890e88e3 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -179,7 +179,7 @@ static inline int wbinvd_on_all_cpus(void) } #endif /* CONFIG_SMP */ -extern unsigned disabled_cpus __cpuinitdata; +extern unsigned disabled_cpus; #ifdef CONFIG_X86_32_SMP /* diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index d81a972dd506..2627a81253ee 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -195,7 +195,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) return 0; } -static void __cpuinit acpi_register_lapic(int id, u8 enabled) +static void acpi_register_lapic(int id, u8 enabled) { unsigned int ver = 0; @@ -607,7 +607,7 @@ void __init acpi_set_irq_model_ioapic(void) #ifdef CONFIG_ACPI_HOTPLUG_CPU #include -static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) +static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA int nid; @@ -620,7 +620,7 @@ static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) #endif } -static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 99663b59123a..eca89c53a7f5 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -58,7 +58,7 @@ unsigned int num_processors; -unsigned disabled_cpus __cpuinitdata; +unsigned disabled_cpus; /* Processor that is doing the boot up */ unsigned int boot_cpu_physical_apicid = -1U; @@ -544,7 +544,7 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events); * Setup the local APIC timer for this CPU. Copy the initialized values * of the boot CPU and register the clock event in the framework. */ -static void __cpuinit setup_APIC_timer(void) +static void setup_APIC_timer(void) { struct clock_event_device *levt = &__get_cpu_var(lapic_events); @@ -866,7 +866,7 @@ void __init setup_boot_APIC_clock(void) setup_APIC_timer(); } -void __cpuinit setup_secondary_APIC_clock(void) +void setup_secondary_APIC_clock(void) { setup_APIC_timer(); } @@ -1229,7 +1229,7 @@ void __init init_bsp_APIC(void) apic_write(APIC_LVT1, value); } -static void __cpuinit lapic_setup_esr(void) +static void lapic_setup_esr(void) { unsigned int oldvalue, value, maxlvt; @@ -1276,7 +1276,7 @@ static void __cpuinit lapic_setup_esr(void) * Used to setup local APIC while initializing BSP or bringin up APs. * Always called with preemption disabled. */ -void __cpuinit setup_local_APIC(void) +void setup_local_APIC(void) { int cpu = smp_processor_id(); unsigned int value, queued; @@ -1471,7 +1471,7 @@ void __cpuinit setup_local_APIC(void) #endif } -void __cpuinit end_local_APIC_setup(void) +void end_local_APIC_setup(void) { lapic_setup_esr(); @@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT1, value); } -void __cpuinit generic_processor_info(int apicid, int version) +void generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, @@ -2377,7 +2377,7 @@ static struct syscore_ops lapic_syscore_ops = { .suspend = lapic_suspend, }; -static void __cpuinit apic_pm_activate(void) +static void apic_pm_activate(void) { apic_pm_state.active = 1; } @@ -2402,7 +2402,7 @@ static void apic_pm_activate(void) { } #ifdef CONFIG_X86_64 -static int __cpuinit apic_cluster_num(void) +static int apic_cluster_num(void) { int i, clusters, zeros; unsigned id; @@ -2447,10 +2447,10 @@ static int __cpuinit apic_cluster_num(void) return clusters; } -static int __cpuinitdata multi_checked; -static int __cpuinitdata multi; +static int multi_checked; +static int multi; -static int __cpuinit set_multi(const struct dmi_system_id *d) +static int set_multi(const struct dmi_system_id *d) { if (multi) return 0; @@ -2459,7 +2459,7 @@ static int __cpuinit set_multi(const struct dmi_system_id *d) return 0; } -static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { +static const struct dmi_system_id multi_dmi_table[] = { { .callback = set_multi, .ident = "IBM System Summit2", @@ -2471,7 +2471,7 @@ static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { {} }; -static void __cpuinit dmi_check_multi(void) +static void dmi_check_multi(void) { if (multi_checked) return; @@ -2488,7 +2488,7 @@ static void __cpuinit dmi_check_multi(void) * multi-chassis. * Use DMI to check them */ -__cpuinit int apic_is_clustered_box(void) +int apic_is_clustered_box(void) { dmi_check_multi(); if (multi) diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 9a9110918ca7..3e67f9e3d7ef 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -74,7 +74,7 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb) return initial_apic_id >> index_msb; } -static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) +static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) { union numachip_csr_g3_ext_irq_gen int_gen; diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 0874799a98c6..c55224731b2d 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -130,7 +130,7 @@ int es7000_plat; */ -static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) +static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) { unsigned long vect = 0, psaival = 0; diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index d661ee95cabf..1e42e8f305ee 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -105,7 +105,7 @@ static void __init smp_dump_qct(void) } } -void __cpuinit numaq_tsc_disable(void) +void numaq_tsc_disable(void) { if (!found_numaq) return; diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index c88baa4ff0e5..140e29db478d 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -148,7 +148,7 @@ static void init_x2apic_ldr(void) /* * At CPU state changes, update the x2apic cluster sibling info. */ -static int __cpuinit +static int update_clusterinfo(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int this_cpu = (unsigned long)hcpu; diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 63092afb142e..1191ac1c9d25 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(uv_possible_blades); unsigned long sn_rtc_cycles_per_second; EXPORT_SYMBOL(sn_rtc_cycles_per_second); -static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) +static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) { #ifdef CONFIG_SMP unsigned long val; @@ -416,7 +416,7 @@ static struct apic __refdata apic_x2apic_uv_x = { .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle, }; -static __cpuinit void set_x2apic_extra_bits(int pnode) +static void set_x2apic_extra_bits(int pnode) { __this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift); } @@ -735,7 +735,7 @@ static void uv_heartbeat(unsigned long ignored) mod_timer_pinned(timer, jiffies + SCIR_CPU_HB_INTERVAL); } -static void __cpuinit uv_heartbeat_enable(int cpu) +static void uv_heartbeat_enable(int cpu) { while (!uv_cpu_hub_info(cpu)->scir.enabled) { struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer; @@ -752,7 +752,7 @@ static void __cpuinit uv_heartbeat_enable(int cpu) } #ifdef CONFIG_HOTPLUG_CPU -static void __cpuinit uv_heartbeat_disable(int cpu) +static void uv_heartbeat_disable(int cpu) { if (uv_cpu_hub_info(cpu)->scir.enabled) { uv_cpu_hub_info(cpu)->scir.enabled = 0; @@ -764,8 +764,8 @@ static void __cpuinit uv_heartbeat_disable(int cpu) /* * cpu hotplug notifier */ -static __cpuinit int uv_scir_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int uv_scir_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { long cpu = (long)hcpu; @@ -835,7 +835,7 @@ int uv_set_vga_state(struct pci_dev *pdev, bool decode, * Called on each cpu to initialize the per_cpu UV data area. * FIXME: hotplug not supported yet */ -void __cpuinit uv_cpu_init(void) +void uv_cpu_init(void) { /* CPU 0 initilization will be done via uv_system_init. */ if (!uv_blade_info) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index c587a8757227..f654ecefea5b 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -69,7 +69,7 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val) extern void vide(void); __asm__(".align 4\nvide: ret"); -static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) +static void init_amd_k5(struct cpuinfo_x86 *c) { /* * General Systems BIOSen alias the cpu frequency registers @@ -87,7 +87,7 @@ static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) } -static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) +static void init_amd_k6(struct cpuinfo_x86 *c) { u32 l, h; int mbytes = get_num_physpages() >> (20-PAGE_SHIFT); @@ -179,7 +179,7 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) } } -static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) +static void amd_k7_smp_check(struct cpuinfo_x86 *c) { /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index) @@ -222,7 +222,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) add_taint(TAINT_UNSAFE_SMP, LOCKDEP_NOW_UNRELIABLE); } -static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) +static void init_amd_k7(struct cpuinfo_x86 *c) { u32 l, h; @@ -267,7 +267,7 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) * To workaround broken NUMA config. Read the comment in * srat_detect_node(). */ -static int __cpuinit nearby_node(int apicid) +static int nearby_node(int apicid) { int i, node; @@ -292,7 +292,7 @@ static int __cpuinit nearby_node(int apicid) * (2) AMD processors supporting compute units */ #ifdef CONFIG_X86_HT -static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c) +static void amd_get_topology(struct cpuinfo_x86 *c) { u32 nodes, cores_per_cu = 1; u8 node_id; @@ -342,7 +342,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c) * On a AMD dual core setup the lower bits of the APIC id distingush the cores. * Assumes number of cores is a power of two. */ -static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) +static void amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT unsigned bits; @@ -369,7 +369,7 @@ u16 amd_get_nb_id(int cpu) } EXPORT_SYMBOL_GPL(amd_get_nb_id); -static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +static void srat_detect_node(struct cpuinfo_x86 *c) { #ifdef CONFIG_NUMA int cpu = smp_processor_id(); @@ -421,7 +421,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) #endif } -static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) +static void early_init_amd_mc(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT unsigned bits, ecx; @@ -447,7 +447,7 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) #endif } -static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) +static void bsp_init_amd(struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { @@ -475,7 +475,7 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) } } -static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) +static void early_init_amd(struct cpuinfo_x86 *c) { early_init_amd_mc(c); @@ -514,7 +514,7 @@ static const int amd_erratum_383[]; static const int amd_erratum_400[]; static bool cpu_has_amd_erratum(const int *erratum); -static void __cpuinit init_amd(struct cpuinfo_x86 *c) +static void init_amd(struct cpuinfo_x86 *c) { u32 dummy; unsigned long long value; @@ -740,8 +740,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_32 -static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, - unsigned int size) +static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* AMD errata T13 (order #21922) */ if ((c->x86 == 6)) { @@ -757,7 +756,7 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, } #endif -static void __cpuinit cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) +static void cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) { tlb_flushall_shift = 5; @@ -765,7 +764,7 @@ static void __cpuinit cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c) tlb_flushall_shift = 4; } -static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c) +static void cpu_detect_tlb_amd(struct cpuinfo_x86 *c) { u32 ebx, eax, ecx, edx; u16 mask = 0xfff; @@ -820,7 +819,7 @@ static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c) cpu_set_tlb_flushall_shift(c); } -static const struct cpu_dev __cpuinitconst amd_cpu_dev = { +static const struct cpu_dev amd_cpu_dev = { .c_vendor = "AMD", .c_ident = { "AuthenticAMD" }, #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 159103c0b1f4..fbf6c3bc2400 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -11,7 +11,7 @@ #ifdef CONFIG_X86_OOSTORE -static u32 __cpuinit power2(u32 x) +static u32 power2(u32 x) { u32 s = 1; @@ -25,7 +25,7 @@ static u32 __cpuinit power2(u32 x) /* * Set up an actual MCR */ -static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key) +static void centaur_mcr_insert(int reg, u32 base, u32 size, int key) { u32 lo, hi; @@ -42,7 +42,7 @@ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key) * * Shortcut: We know you can't put 4Gig of RAM on a winchip */ -static u32 __cpuinit ramtop(void) +static u32 ramtop(void) { u32 clip = 0xFFFFFFFFUL; u32 top = 0; @@ -91,7 +91,7 @@ static u32 __cpuinit ramtop(void) /* * Compute a set of MCR's to give maximum coverage */ -static int __cpuinit centaur_mcr_compute(int nr, int key) +static int centaur_mcr_compute(int nr, int key) { u32 mem = ramtop(); u32 root = power2(mem); @@ -157,7 +157,7 @@ static int __cpuinit centaur_mcr_compute(int nr, int key) return ct; } -static void __cpuinit centaur_create_optimal_mcr(void) +static void centaur_create_optimal_mcr(void) { int used; int i; @@ -181,7 +181,7 @@ static void __cpuinit centaur_create_optimal_mcr(void) wrmsr(MSR_IDT_MCR0+i, 0, 0); } -static void __cpuinit winchip2_create_optimal_mcr(void) +static void winchip2_create_optimal_mcr(void) { u32 lo, hi; int used; @@ -217,7 +217,7 @@ static void __cpuinit winchip2_create_optimal_mcr(void) /* * Handle the MCR key on the Winchip 2. */ -static void __cpuinit winchip2_unprotect_mcr(void) +static void winchip2_unprotect_mcr(void) { u32 lo, hi; u32 key; @@ -229,7 +229,7 @@ static void __cpuinit winchip2_unprotect_mcr(void) wrmsr(MSR_IDT_MCR_CTRL, lo, hi); } -static void __cpuinit winchip2_protect_mcr(void) +static void winchip2_protect_mcr(void) { u32 lo, hi; @@ -247,7 +247,7 @@ static void __cpuinit winchip2_protect_mcr(void) #define RNG_ENABLED (1 << 3) #define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */ -static void __cpuinit init_c3(struct cpuinfo_x86 *c) +static void init_c3(struct cpuinfo_x86 *c) { u32 lo, hi; @@ -318,7 +318,7 @@ enum { EAMD3D = 1<<20, }; -static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) +static void early_init_centaur(struct cpuinfo_x86 *c) { switch (c->x86) { #ifdef CONFIG_X86_32 @@ -337,7 +337,7 @@ static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) #endif } -static void __cpuinit init_centaur(struct cpuinfo_x86 *c) +static void init_centaur(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 char *name; @@ -468,7 +468,7 @@ static void __cpuinit init_centaur(struct cpuinfo_x86 *c) #endif } -static unsigned int __cpuinit +static unsigned int centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) { #ifdef CONFIG_X86_32 @@ -488,7 +488,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) return size; } -static const struct cpu_dev __cpuinitconst centaur_cpu_dev = { +static const struct cpu_dev centaur_cpu_dev = { .c_vendor = "Centaur", .c_ident = { "CentaurHauls" }, .c_early_init = early_init_centaur, diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 548bd039784e..25eb2747b063 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -63,7 +63,7 @@ void __init setup_cpu_local_masks(void) alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); } -static void __cpuinit default_init(struct cpuinfo_x86 *c) +static void default_init(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_64 cpu_detect_cache_sizes(c); @@ -80,13 +80,13 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c) #endif } -static const struct cpu_dev __cpuinitconst default_cpu = { +static const struct cpu_dev default_cpu = { .c_init = default_init, .c_vendor = "Unknown", .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu; +static const struct cpu_dev *this_cpu = &default_cpu; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64 @@ -160,8 +160,8 @@ static int __init x86_xsaveopt_setup(char *s) __setup("noxsaveopt", x86_xsaveopt_setup); #ifdef CONFIG_X86_32 -static int cachesize_override __cpuinitdata = -1; -static int disable_x86_serial_nr __cpuinitdata = 1; +static int cachesize_override = -1; +static int disable_x86_serial_nr = 1; static int __init cachesize_setup(char *str) { @@ -215,12 +215,12 @@ static inline int flag_is_changeable_p(u32 flag) } /* Probe for the CPUID instruction */ -int __cpuinit have_cpuid_p(void) +int have_cpuid_p(void) { return flag_is_changeable_p(X86_EFLAGS_ID); } -static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) { unsigned long lo, hi; @@ -298,7 +298,7 @@ struct cpuid_dependent_feature { u32 level; }; -static const struct cpuid_dependent_feature __cpuinitconst +static const struct cpuid_dependent_feature cpuid_dependent_features[] = { { X86_FEATURE_MWAIT, 0x00000005 }, { X86_FEATURE_DCA, 0x00000009 }, @@ -306,7 +306,7 @@ cpuid_dependent_features[] = { { 0, 0 } }; -static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) +static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) { const struct cpuid_dependent_feature *df; @@ -344,7 +344,7 @@ static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) */ /* Look up CPU names by table lookup. */ -static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c) +static const char *table_lookup_model(struct cpuinfo_x86 *c) { const struct cpu_model_info *info; @@ -364,8 +364,8 @@ static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c) return NULL; /* Not found */ } -__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata; -__u32 cpu_caps_set[NCAPINTS] __cpuinitdata; +__u32 cpu_caps_cleared[NCAPINTS]; +__u32 cpu_caps_set[NCAPINTS]; void load_percpu_segment(int cpu) { @@ -394,9 +394,9 @@ void switch_to_new_gdt(int cpu) load_percpu_segment(cpu); } -static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {}; +static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; -static void __cpuinit get_model_name(struct cpuinfo_x86 *c) +static void get_model_name(struct cpuinfo_x86 *c) { unsigned int *v; char *p, *q; @@ -425,7 +425,7 @@ static void __cpuinit get_model_name(struct cpuinfo_x86 *c) } } -void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c) +void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) { unsigned int n, dummy, ebx, ecx, edx, l2size; @@ -479,7 +479,7 @@ u16 __read_mostly tlb_lld_4m[NR_INFO]; */ s8 __read_mostly tlb_flushall_shift = -1; -void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) +void cpu_detect_tlb(struct cpuinfo_x86 *c) { if (this_cpu->c_detect_tlb) this_cpu->c_detect_tlb(c); @@ -493,7 +493,7 @@ void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c) tlb_flushall_shift); } -void __cpuinit detect_ht(struct cpuinfo_x86 *c) +void detect_ht(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT u32 eax, ebx, ecx, edx; @@ -544,7 +544,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) #endif } -static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) +static void get_cpu_vendor(struct cpuinfo_x86 *c) { char *v = c->x86_vendor_id; int i; @@ -571,7 +571,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) this_cpu = &default_cpu; } -void __cpuinit cpu_detect(struct cpuinfo_x86 *c) +void cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ cpuid(0x00000000, (unsigned int *)&c->cpuid_level, @@ -601,7 +601,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) } } -void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) +void get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; u32 ebx; @@ -652,7 +652,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) init_scattered_cpuid_features(c); } -static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c) +static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 int i; @@ -769,7 +769,7 @@ void __init early_cpu_init(void) * unless we can find a reliable way to detect all the broken cases. * Enable it explicitly on 64-bit for non-constant inputs of cpu_has(). */ -static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +static void detect_nopl(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 clear_cpu_cap(c, X86_FEATURE_NOPL); @@ -778,7 +778,7 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) #endif } -static void __cpuinit generic_identify(struct cpuinfo_x86 *c) +static void generic_identify(struct cpuinfo_x86 *c) { c->extended_cpuid_level = 0; @@ -815,7 +815,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) /* * This does the hard work of actually picking apart the CPU stuff... */ -static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) +static void identify_cpu(struct cpuinfo_x86 *c) { int i; @@ -960,7 +960,7 @@ void __init identify_boot_cpu(void) cpu_detect_tlb(&boot_cpu_data); } -void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) +void identify_secondary_cpu(struct cpuinfo_x86 *c) { BUG_ON(c == &boot_cpu_data); identify_cpu(c); @@ -975,14 +975,14 @@ struct msr_range { unsigned max; }; -static const struct msr_range msr_range_array[] __cpuinitconst = { +static const struct msr_range msr_range_array[] = { { 0x00000000, 0x00000418}, { 0xc0000000, 0xc000040b}, { 0xc0010000, 0xc0010142}, { 0xc0011000, 0xc001103b}, }; -static void __cpuinit __print_cpu_msr(void) +static void __print_cpu_msr(void) { unsigned index_min, index_max; unsigned index; @@ -1001,7 +1001,7 @@ static void __cpuinit __print_cpu_msr(void) } } -static int show_msr __cpuinitdata; +static int show_msr; static __init int setup_show_msr(char *arg) { @@ -1022,7 +1022,7 @@ static __init int setup_noclflush(char *arg) } __setup("noclflush", setup_noclflush); -void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) +void print_cpu_info(struct cpuinfo_x86 *c) { const char *vendor = NULL; @@ -1051,7 +1051,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) print_cpu_msr(c); } -void __cpuinit print_cpu_msr(struct cpuinfo_x86 *c) +void print_cpu_msr(struct cpuinfo_x86 *c) { if (c->cpu_index < show_msr) __print_cpu_msr(); @@ -1216,7 +1216,7 @@ static void dbg_restore_debug_regs(void) */ #ifdef CONFIG_X86_64 -void __cpuinit cpu_init(void) +void cpu_init(void) { struct orig_ist *oist; struct task_struct *me; @@ -1315,7 +1315,7 @@ void __cpuinit cpu_init(void) #else -void __cpuinit cpu_init(void) +void cpu_init(void) { int cpu = smp_processor_id(); struct task_struct *curr = current; diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 7582f475b163..d0969c75ab54 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -15,7 +15,7 @@ /* * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU */ -static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned char ccr2, ccr3; @@ -44,7 +44,7 @@ static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) } } -static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned long flags; @@ -59,25 +59,25 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) * Actually since bugs.h doesn't even reference this perhaps someone should * fix the documentation ??? */ -static unsigned char Cx86_dir0_msb __cpuinitdata = 0; +static unsigned char Cx86_dir0_msb = 0; -static const char __cpuinitconst Cx86_model[][9] = { +static const char Cx86_model[][9] = { "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ", "M II ", "Unknown" }; -static const char __cpuinitconst Cx486_name[][5] = { +static const char Cx486_name[][5] = { "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx", "SRx2", "DRx2" }; -static const char __cpuinitconst Cx486S_name[][4] = { +static const char Cx486S_name[][4] = { "S", "S2", "Se", "S2e" }; -static const char __cpuinitconst Cx486D_name[][4] = { +static const char Cx486D_name[][4] = { "DX", "DX2", "?", "?", "?", "DX4" }; -static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock"; -static const char __cpuinitconst cyrix_model_mult1[] = "12??43"; -static const char __cpuinitconst cyrix_model_mult2[] = "12233445"; +static char Cx86_cb[] = "?.5x Core/Bus Clock"; +static const char cyrix_model_mult1[] = "12??43"; +static const char cyrix_model_mult2[] = "12233445"; /* * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old @@ -87,7 +87,7 @@ static const char __cpuinitconst cyrix_model_mult2[] = "12233445"; * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP */ -static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c) +static void check_cx686_slop(struct cpuinfo_x86 *c) { unsigned long flags; @@ -112,7 +112,7 @@ static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c) } -static void __cpuinit set_cx86_reorder(void) +static void set_cx86_reorder(void) { u8 ccr3; @@ -127,7 +127,7 @@ static void __cpuinit set_cx86_reorder(void) setCx86(CX86_CCR3, ccr3); } -static void __cpuinit set_cx86_memwb(void) +static void set_cx86_memwb(void) { printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); @@ -143,7 +143,7 @@ static void __cpuinit set_cx86_memwb(void) * Configure later MediaGX and/or Geode processor. */ -static void __cpuinit geode_configure(void) +static void geode_configure(void) { unsigned long flags; u8 ccr3; @@ -166,7 +166,7 @@ static void __cpuinit geode_configure(void) local_irq_restore(flags); } -static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) +static void early_init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir1 = 0; @@ -185,7 +185,7 @@ static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) } } -static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) +static void init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; char *buf = c->x86_model_id; @@ -356,7 +356,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* * Handle National Semiconductor branded processors */ -static void __cpuinit init_nsc(struct cpuinfo_x86 *c) +static void init_nsc(struct cpuinfo_x86 *c) { /* * There may be GX1 processors in the wild that are branded @@ -405,7 +405,7 @@ static inline int test_cyrix_52div(void) return (unsigned char) (test >> 8) == 0x02; } -static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) +static void cyrix_identify(struct cpuinfo_x86 *c) { /* Detect Cyrix with disabled CPUID */ if (c->x86 == 4 && test_cyrix_52div()) { @@ -441,7 +441,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) } } -static const struct cpu_dev __cpuinitconst cyrix_cpu_dev = { +static const struct cpu_dev cyrix_cpu_dev = { .c_vendor = "Cyrix", .c_ident = { "CyrixInstead" }, .c_early_init = early_init_cyrix, @@ -452,7 +452,7 @@ static const struct cpu_dev __cpuinitconst cyrix_cpu_dev = { cpu_dev_register(cyrix_cpu_dev); -static const struct cpu_dev __cpuinitconst nsc_cpu_dev = { +static const struct cpu_dev nsc_cpu_dev = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, .c_init = init_nsc, diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 1e7e84a02eba..87279212d318 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -60,7 +60,7 @@ detect_hypervisor_vendor(void) } } -void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) +void init_hypervisor(struct cpuinfo_x86 *c) { if (x86_hyper && x86_hyper->set_cpu_features) x86_hyper->set_cpu_features(c); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 9b0c441c03f5..ec7299566f79 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -26,7 +26,7 @@ #include #endif -static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) +static void early_init_intel(struct cpuinfo_x86 *c) { u64 misc_enable; @@ -163,7 +163,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) * This is called before we do cpu ident work */ -int __cpuinit ppro_with_ram_bug(void) +int ppro_with_ram_bug(void) { /* Uses data from early_cpu_detect now */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && @@ -176,7 +176,7 @@ int __cpuinit ppro_with_ram_bug(void) return 0; } -static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) +static void intel_smp_check(struct cpuinfo_x86 *c) { /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index) @@ -196,7 +196,7 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) } } -static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) +static void intel_workarounds(struct cpuinfo_x86 *c) { unsigned long lo, hi; @@ -275,12 +275,12 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) intel_smp_check(c); } #else -static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) +static void intel_workarounds(struct cpuinfo_x86 *c) { } #endif -static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +static void srat_detect_node(struct cpuinfo_x86 *c) { #ifdef CONFIG_NUMA unsigned node; @@ -300,7 +300,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) /* * find out the number of processor cores on the die */ -static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) +static int intel_num_cpu_cores(struct cpuinfo_x86 *c) { unsigned int eax, ebx, ecx, edx; @@ -315,7 +315,7 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) return 1; } -static void __cpuinit detect_vmx_virtcap(struct cpuinfo_x86 *c) +static void detect_vmx_virtcap(struct cpuinfo_x86 *c) { /* Intel VMX MSR indicated features */ #define X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW 0x00200000 @@ -353,7 +353,7 @@ static void __cpuinit detect_vmx_virtcap(struct cpuinfo_x86 *c) } } -static void __cpuinit init_intel(struct cpuinfo_x86 *c) +static void init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; @@ -472,7 +472,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_32 -static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) +static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* * Intel PIII Tualatin. This comes in two flavours. @@ -506,7 +506,7 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned i #define STLB_4K 0x41 -static const struct _tlb_table intel_tlb_table[] __cpuinitconst = { +static const struct _tlb_table intel_tlb_table[] = { { 0x01, TLB_INST_4K, 32, " TLB_INST 4 KByte pages, 4-way set associative" }, { 0x02, TLB_INST_4M, 2, " TLB_INST 4 MByte pages, full associative" }, { 0x03, TLB_DATA_4K, 64, " TLB_DATA 4 KByte pages, 4-way set associative" }, @@ -536,7 +536,7 @@ static const struct _tlb_table intel_tlb_table[] __cpuinitconst = { { 0x00, 0, 0 } }; -static void __cpuinit intel_tlb_lookup(const unsigned char desc) +static void intel_tlb_lookup(const unsigned char desc) { unsigned char k; if (desc == 0) @@ -605,7 +605,7 @@ static void __cpuinit intel_tlb_lookup(const unsigned char desc) } } -static void __cpuinit intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c) +static void intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c) { switch ((c->x86 << 8) + c->x86_model) { case 0x60f: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ @@ -634,7 +634,7 @@ static void __cpuinit intel_tlb_flushall_shift_set(struct cpuinfo_x86 *c) } } -static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) +static void intel_detect_tlb(struct cpuinfo_x86 *c) { int i, j, n; unsigned int regs[4]; @@ -661,7 +661,7 @@ static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c) intel_tlb_flushall_shift_set(c); } -static const struct cpu_dev __cpuinitconst intel_cpu_dev = { +static const struct cpu_dev intel_cpu_dev = { .c_vendor = "Intel", .c_ident = { "GenuineIntel" }, #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 8dc72dda66fe..1414c90feaba 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -37,7 +37,7 @@ struct _cache_table { /* All the cache descriptor types we care about (no TLB or trace cache entries) */ -static const struct _cache_table __cpuinitconst cache_table[] = +static const struct _cache_table cache_table[] = { { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ @@ -203,7 +203,7 @@ union l3_cache { unsigned val; }; -static const unsigned short __cpuinitconst assocs[] = { +static const unsigned short assocs[] = { [1] = 1, [2] = 2, [4] = 4, @@ -217,10 +217,10 @@ static const unsigned short __cpuinitconst assocs[] = { [0xf] = 0xffff /* fully associative - no way to show this currently */ }; -static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 }; -static const unsigned char __cpuinitconst types[] = { 1, 2, 3, 3 }; +static const unsigned char levels[] = { 1, 1, 2, 3 }; +static const unsigned char types[] = { 1, 2, 3, 3 }; -static void __cpuinit +static void amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx) @@ -302,7 +302,7 @@ struct _cache_attr { /* * L3 cache descriptors */ -static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) +static void amd_calc_l3_indices(struct amd_northbridge *nb) { struct amd_l3_cache *l3 = &nb->l3_cache; unsigned int sc0, sc1, sc2, sc3; @@ -325,7 +325,7 @@ static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; } -static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index) +static void amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index) { int node; @@ -528,8 +528,7 @@ static struct _cache_attr subcaches = #endif /* CONFIG_AMD_NB && CONFIG_SYSFS */ static int -__cpuinit cpuid4_cache_lookup_regs(int index, - struct _cpuid4_info_regs *this_leaf) +cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf) { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; @@ -560,7 +559,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, return 0; } -static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c) +static int find_num_cache_leaves(struct cpuinfo_x86 *c) { unsigned int eax, ebx, ecx, edx, op; union _cpuid4_leaf_eax cache_eax; @@ -580,7 +579,7 @@ static int __cpuinit find_num_cache_leaves(struct cpuinfo_x86 *c) return i; } -void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c) +void init_amd_cacheinfo(struct cpuinfo_x86 *c) { if (cpu_has_topoext) { @@ -593,7 +592,7 @@ void __cpuinit init_amd_cacheinfo(struct cpuinfo_x86 *c) } } -unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) +unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c) { /* Cache sizes */ unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; @@ -744,7 +743,7 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info); #ifdef CONFIG_SMP -static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) +static int cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf; int i, sibling; @@ -793,7 +792,7 @@ static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) return 1; } -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) +static void cache_shared_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf, *sibling_leaf; unsigned long num_threads_sharing; @@ -828,7 +827,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) } } } -static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) +static void cache_remove_shared_cpu_map(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf, *sibling_leaf; int sibling; @@ -841,16 +840,16 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) } } #else -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) +static void cache_shared_cpu_map_setup(unsigned int cpu, int index) { } -static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) +static void cache_remove_shared_cpu_map(unsigned int cpu, int index) { } #endif -static void __cpuinit free_cache_attributes(unsigned int cpu) +static void free_cache_attributes(unsigned int cpu) { int i; @@ -861,7 +860,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) per_cpu(ici_cpuid4_info, cpu) = NULL; } -static void __cpuinit get_cpu_leaves(void *_retval) +static void get_cpu_leaves(void *_retval) { int j, *retval = _retval, cpu = smp_processor_id(); @@ -881,7 +880,7 @@ static void __cpuinit get_cpu_leaves(void *_retval) } } -static int __cpuinit detect_cache_attributes(unsigned int cpu) +static int detect_cache_attributes(unsigned int cpu) { int retval; @@ -1015,7 +1014,7 @@ static struct attribute *default_attrs[] = { }; #ifdef CONFIG_AMD_NB -static struct attribute ** __cpuinit amd_l3_attrs(void) +static struct attribute **amd_l3_attrs(void) { static struct attribute **attrs; int n; @@ -1091,7 +1090,7 @@ static struct kobj_type ktype_percpu_entry = { .sysfs_ops = &sysfs_ops, }; -static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu) +static void cpuid4_cache_sysfs_exit(unsigned int cpu) { kfree(per_cpu(ici_cache_kobject, cpu)); kfree(per_cpu(ici_index_kobject, cpu)); @@ -1100,7 +1099,7 @@ static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu) free_cache_attributes(cpu); } -static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) +static int cpuid4_cache_sysfs_init(unsigned int cpu) { int err; @@ -1132,7 +1131,7 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) static DECLARE_BITMAP(cache_dev_map, NR_CPUS); /* Add/Remove cache interface for CPU device */ -static int __cpuinit cache_add_dev(struct device *dev) +static int cache_add_dev(struct device *dev) { unsigned int cpu = dev->id; unsigned long i, j; @@ -1183,7 +1182,7 @@ static int __cpuinit cache_add_dev(struct device *dev) return 0; } -static void __cpuinit cache_remove_dev(struct device *dev) +static void cache_remove_dev(struct device *dev) { unsigned int cpu = dev->id; unsigned long i; @@ -1200,8 +1199,8 @@ static void __cpuinit cache_remove_dev(struct device *dev) cpuid4_cache_sysfs_exit(cpu); } -static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int cacheinfo_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; struct device *dev; @@ -1220,7 +1219,7 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier = { +static struct notifier_block cacheinfo_cpu_notifier = { .notifier_call = cacheinfo_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index bf49cdbb010f..87a65c939bcd 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1363,7 +1363,7 @@ int mce_notify_irq(void) } EXPORT_SYMBOL_GPL(mce_notify_irq); -static int __cpuinit __mcheck_cpu_mce_banks_init(void) +static int __mcheck_cpu_mce_banks_init(void) { int i; u8 num_banks = mca_cfg.banks; @@ -1384,7 +1384,7 @@ static int __cpuinit __mcheck_cpu_mce_banks_init(void) /* * Initialize Machine Checks for a CPU. */ -static int __cpuinit __mcheck_cpu_cap_init(void) +static int __mcheck_cpu_cap_init(void) { unsigned b; u64 cap; @@ -1483,7 +1483,7 @@ static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs) } /* Add per CPU specific workarounds here */ -static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) +static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) { struct mca_config *cfg = &mca_cfg; @@ -1593,7 +1593,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) return 0; } -static int __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c) +static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c) { if (c->x86 != 5) return 0; @@ -1664,7 +1664,7 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) = * Called for each booted CPU to set up machine checks. * Must be called with preempt off: */ -void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c) +void mcheck_cpu_init(struct cpuinfo_x86 *c) { if (mca_cfg.disabled) return; @@ -2082,7 +2082,6 @@ static struct bus_type mce_subsys = { DEFINE_PER_CPU(struct device *, mce_device); -__cpuinitdata void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); static inline struct mce_bank *attr_to_bank(struct device_attribute *attr) @@ -2228,7 +2227,7 @@ static void mce_device_release(struct device *dev) } /* Per cpu device init. All of the cpus still share the same ctrl bank: */ -static __cpuinit int mce_device_create(unsigned int cpu) +static int mce_device_create(unsigned int cpu) { struct device *dev; int err; @@ -2274,7 +2273,7 @@ static __cpuinit int mce_device_create(unsigned int cpu) return err; } -static __cpuinit void mce_device_remove(unsigned int cpu) +static void mce_device_remove(unsigned int cpu) { struct device *dev = per_cpu(mce_device, cpu); int i; @@ -2294,7 +2293,7 @@ static __cpuinit void mce_device_remove(unsigned int cpu) } /* Make sure there are no machine checks on offlined CPUs. */ -static void __cpuinit mce_disable_cpu(void *h) +static void mce_disable_cpu(void *h) { unsigned long action = *(unsigned long *)h; int i; @@ -2312,7 +2311,7 @@ static void __cpuinit mce_disable_cpu(void *h) } } -static void __cpuinit mce_reenable_cpu(void *h) +static void mce_reenable_cpu(void *h) { unsigned long action = *(unsigned long *)h; int i; @@ -2331,7 +2330,7 @@ static void __cpuinit mce_reenable_cpu(void *h) } /* Get notified when a cpu comes on/off. Be hotplug friendly. */ -static int __cpuinit +static int mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -2367,7 +2366,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block mce_cpu_notifier __cpuinitdata = { +static struct notifier_block mce_cpu_notifier = { .notifier_call = mce_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 9cb52767999a..603df4f74640 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -458,10 +458,8 @@ static struct kobj_type threshold_ktype = { .default_attrs = default_attrs, }; -static __cpuinit int allocate_threshold_blocks(unsigned int cpu, - unsigned int bank, - unsigned int block, - u32 address) +static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, + unsigned int block, u32 address) { struct threshold_block *b = NULL; u32 low, high; @@ -543,7 +541,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, return err; } -static __cpuinit int __threshold_add_blocks(struct threshold_bank *b) +static int __threshold_add_blocks(struct threshold_bank *b) { struct list_head *head = &b->blocks->miscj; struct threshold_block *pos = NULL; @@ -567,7 +565,7 @@ static __cpuinit int __threshold_add_blocks(struct threshold_bank *b) return err; } -static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) +static int threshold_create_bank(unsigned int cpu, unsigned int bank) { struct device *dev = per_cpu(mce_device, cpu); struct amd_northbridge *nb = NULL; @@ -632,7 +630,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) } /* create dir/files for all valid threshold banks */ -static __cpuinit int threshold_create_device(unsigned int cpu) +static int threshold_create_device(unsigned int cpu) { unsigned int bank; struct threshold_bank **bp; @@ -736,7 +734,7 @@ static void threshold_remove_device(unsigned int cpu) } /* get notified when a cpu comes on/off */ -static void __cpuinit +static void amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu) { switch (action) { diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 41e8e00a6637..3eec7de76efb 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -240,8 +240,7 @@ __setup("int_pln_enable", int_pln_enable_setup); #ifdef CONFIG_SYSFS /* Add/Remove thermal_throttle interface for CPU device: */ -static __cpuinit int thermal_throttle_add_dev(struct device *dev, - unsigned int cpu) +static int thermal_throttle_add_dev(struct device *dev, unsigned int cpu) { int err; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -267,7 +266,7 @@ static __cpuinit int thermal_throttle_add_dev(struct device *dev, return err; } -static __cpuinit void thermal_throttle_remove_dev(struct device *dev) +static void thermal_throttle_remove_dev(struct device *dev) { sysfs_remove_group(&dev->kobj, &thermal_attr_group); } @@ -276,7 +275,7 @@ static __cpuinit void thermal_throttle_remove_dev(struct device *dev) static DEFINE_MUTEX(therm_cpu_lock); /* Get notified when a cpu comes on/off. Be hotplug friendly. */ -static __cpuinit int +static int thermal_throttle_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) @@ -307,7 +306,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block thermal_throttle_cpu_notifier __cpuinitdata = +static struct notifier_block thermal_throttle_cpu_notifier = { .notifier_call = thermal_throttle_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 9e581c5cf6d0..a7c7305030cc 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1295,7 +1295,7 @@ perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) struct event_constraint emptyconstraint; struct event_constraint unconstrained; -static int __cpuinit +static int x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 5f0581e713c2..e09f0bfb7b8f 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -851,7 +851,7 @@ static void clear_APIC_ibs(void *dummy) setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); } -static int __cpuinit +static int perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c index c0c661adf03e..754291adec33 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_amd_uncore.c @@ -288,13 +288,13 @@ static struct pmu amd_l2_pmu = { .read = amd_uncore_read, }; -static struct amd_uncore * __cpuinit amd_uncore_alloc(unsigned int cpu) +static struct amd_uncore *amd_uncore_alloc(unsigned int cpu) { return kzalloc_node(sizeof(struct amd_uncore), GFP_KERNEL, cpu_to_node(cpu)); } -static void __cpuinit amd_uncore_cpu_up_prepare(unsigned int cpu) +static void amd_uncore_cpu_up_prepare(unsigned int cpu) { struct amd_uncore *uncore; @@ -322,8 +322,8 @@ static void __cpuinit amd_uncore_cpu_up_prepare(unsigned int cpu) } static struct amd_uncore * -__cpuinit amd_uncore_find_online_sibling(struct amd_uncore *this, - struct amd_uncore * __percpu *uncores) +amd_uncore_find_online_sibling(struct amd_uncore *this, + struct amd_uncore * __percpu *uncores) { unsigned int cpu; struct amd_uncore *that; @@ -348,7 +348,7 @@ __cpuinit amd_uncore_find_online_sibling(struct amd_uncore *this, return this; } -static void __cpuinit amd_uncore_cpu_starting(unsigned int cpu) +static void amd_uncore_cpu_starting(unsigned int cpu) { unsigned int eax, ebx, ecx, edx; struct amd_uncore *uncore; @@ -376,8 +376,8 @@ static void __cpuinit amd_uncore_cpu_starting(unsigned int cpu) } } -static void __cpuinit uncore_online(unsigned int cpu, - struct amd_uncore * __percpu *uncores) +static void uncore_online(unsigned int cpu, + struct amd_uncore * __percpu *uncores) { struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu); @@ -388,7 +388,7 @@ static void __cpuinit uncore_online(unsigned int cpu, cpumask_set_cpu(cpu, uncore->active_mask); } -static void __cpuinit amd_uncore_cpu_online(unsigned int cpu) +static void amd_uncore_cpu_online(unsigned int cpu) { if (amd_uncore_nb) uncore_online(cpu, amd_uncore_nb); @@ -397,8 +397,8 @@ static void __cpuinit amd_uncore_cpu_online(unsigned int cpu) uncore_online(cpu, amd_uncore_l2); } -static void __cpuinit uncore_down_prepare(unsigned int cpu, - struct amd_uncore * __percpu *uncores) +static void uncore_down_prepare(unsigned int cpu, + struct amd_uncore * __percpu *uncores) { unsigned int i; struct amd_uncore *this = *per_cpu_ptr(uncores, cpu); @@ -423,7 +423,7 @@ static void __cpuinit uncore_down_prepare(unsigned int cpu, } } -static void __cpuinit amd_uncore_cpu_down_prepare(unsigned int cpu) +static void amd_uncore_cpu_down_prepare(unsigned int cpu) { if (amd_uncore_nb) uncore_down_prepare(cpu, amd_uncore_nb); @@ -432,8 +432,7 @@ static void __cpuinit amd_uncore_cpu_down_prepare(unsigned int cpu) uncore_down_prepare(cpu, amd_uncore_l2); } -static void __cpuinit uncore_dead(unsigned int cpu, - struct amd_uncore * __percpu *uncores) +static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores) { struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu); @@ -445,7 +444,7 @@ static void __cpuinit uncore_dead(unsigned int cpu, *per_cpu_ptr(amd_uncore_nb, cpu) = NULL; } -static void __cpuinit amd_uncore_cpu_dead(unsigned int cpu) +static void amd_uncore_cpu_dead(unsigned int cpu) { if (amd_uncore_nb) uncore_dead(cpu, amd_uncore_nb); @@ -454,7 +453,7 @@ static void __cpuinit amd_uncore_cpu_dead(unsigned int cpu) uncore_dead(cpu, amd_uncore_l2); } -static int __cpuinit +static int amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -489,7 +488,7 @@ amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action, return NOTIFY_OK; } -static struct notifier_block amd_uncore_cpu_notifier_block __cpuinitdata = { +static struct notifier_block amd_uncore_cpu_notifier_block = { .notifier_call = amd_uncore_cpu_notifier, .priority = CPU_PRI_PERF + 1, }; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 9dd99751ccf9..cad791dbde95 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -3297,7 +3297,7 @@ static void __init uncore_pci_exit(void) /* CPU hot plug/unplug are serialized by cpu_add_remove_lock mutex */ static LIST_HEAD(boxes_to_free); -static void __cpuinit uncore_kfree_boxes(void) +static void uncore_kfree_boxes(void) { struct intel_uncore_box *box; @@ -3309,7 +3309,7 @@ static void __cpuinit uncore_kfree_boxes(void) } } -static void __cpuinit uncore_cpu_dying(int cpu) +static void uncore_cpu_dying(int cpu) { struct intel_uncore_type *type; struct intel_uncore_pmu *pmu; @@ -3328,7 +3328,7 @@ static void __cpuinit uncore_cpu_dying(int cpu) } } -static int __cpuinit uncore_cpu_starting(int cpu) +static int uncore_cpu_starting(int cpu) { struct intel_uncore_type *type; struct intel_uncore_pmu *pmu; @@ -3371,7 +3371,7 @@ static int __cpuinit uncore_cpu_starting(int cpu) return 0; } -static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id) +static int uncore_cpu_prepare(int cpu, int phys_id) { struct intel_uncore_type *type; struct intel_uncore_pmu *pmu; @@ -3397,7 +3397,7 @@ static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id) return 0; } -static void __cpuinit +static void uncore_change_context(struct intel_uncore_type **uncores, int old_cpu, int new_cpu) { struct intel_uncore_type *type; @@ -3435,7 +3435,7 @@ uncore_change_context(struct intel_uncore_type **uncores, int old_cpu, int new_c } } -static void __cpuinit uncore_event_exit_cpu(int cpu) +static void uncore_event_exit_cpu(int cpu) { int i, phys_id, target; @@ -3463,7 +3463,7 @@ static void __cpuinit uncore_event_exit_cpu(int cpu) uncore_change_context(pci_uncores, cpu, target); } -static void __cpuinit uncore_event_init_cpu(int cpu) +static void uncore_event_init_cpu(int cpu) { int i, phys_id; @@ -3479,8 +3479,8 @@ static void __cpuinit uncore_event_init_cpu(int cpu) uncore_change_context(pci_uncores, -1, cpu); } -static int - __cpuinit uncore_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) +static int uncore_cpu_notifier(struct notifier_block *self, + unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; @@ -3520,7 +3520,7 @@ static int return NOTIFY_OK; } -static struct notifier_block uncore_cpu_nb __cpuinitdata = { +static struct notifier_block uncore_cpu_nb = { .notifier_call = uncore_cpu_notifier, /* * to migrate uncore events, our notifier should be executed diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index feca286c2bb4..88db010845cb 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c @@ -52,7 +52,7 @@ static inline int rdrand_long(unsigned long *v) */ #define RESEED_LOOP ((512*128)/sizeof(unsigned long)) -void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c) +void x86_init_rdrand(struct cpuinfo_x86 *c) { #ifdef CONFIG_ARCH_RANDOM unsigned long tmp; diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index d92b5dad15dd..f2cc63e9cf08 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -24,13 +24,13 @@ enum cpuid_regs { CR_EBX }; -void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) +void init_scattered_cpuid_features(struct cpuinfo_x86 *c) { u32 max_level; u32 regs[4]; const struct cpuid_bit *cb; - static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { + static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index 4397e987a1cf..4c60eaf0571c 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -26,7 +26,7 @@ * exists, use it for populating initial_apicid and cpu topology * detection. */ -void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) +void detect_extended_topology(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP unsigned int eax, ebx, ecx, edx, sub_index; diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 28000743bbb0..aa0430d69b90 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -5,7 +5,7 @@ #include #include "cpu.h" -static void __cpuinit early_init_transmeta(struct cpuinfo_x86 *c) +static void early_init_transmeta(struct cpuinfo_x86 *c) { u32 xlvl; @@ -17,7 +17,7 @@ static void __cpuinit early_init_transmeta(struct cpuinfo_x86 *c) } } -static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) +static void init_transmeta(struct cpuinfo_x86 *c) { unsigned int cap_mask, uk, max, dummy; unsigned int cms_rev1, cms_rev2; @@ -98,7 +98,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) #endif } -static const struct cpu_dev __cpuinitconst transmeta_cpu_dev = { +static const struct cpu_dev transmeta_cpu_dev = { .c_vendor = "Transmeta", .c_ident = { "GenuineTMx86", "TransmetaCPU" }, .c_early_init = early_init_transmeta, diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index fd2c37bf7acb..202759a14121 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c @@ -8,7 +8,7 @@ * so no special init takes place. */ -static const struct cpu_dev __cpuinitconst umc_cpu_dev = { +static const struct cpu_dev umc_cpu_dev = { .c_vendor = "UMC", .c_ident = { "UMC UMC UMC" }, .c_models = { diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 03a36321ec54..7076878404ec 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -122,7 +122,7 @@ static bool __init vmware_platform(void) * so that the kernel could just trust the hypervisor with providing a * reliable virtual TSC that is suitable for timekeeping. */ -static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c) +static void vmware_set_cpu_features(struct cpuinfo_x86 *c) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 1e4dbcfe6d31..7d9481c743f8 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -137,7 +137,7 @@ static const struct file_operations cpuid_fops = { .open = cpuid_open, }; -static __cpuinit int cpuid_device_create(int cpu) +static int cpuid_device_create(int cpu) { struct device *dev; @@ -151,9 +151,8 @@ static void cpuid_device_destroy(int cpu) device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); } -static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb, - unsigned long action, - void *hcpu) +static int cpuid_class_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; int err = 0; diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 4934890e4db2..69eb2fa25494 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -133,7 +133,7 @@ static void x86_of_pci_irq_disable(struct pci_dev *dev) { } -void __cpuinit x86_of_pci_init(void) +void x86_of_pci_init(void) { pcibios_enable_irq = x86_of_pci_irq_enable; pcibios_disable_irq = x86_of_pci_irq_disable; diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index e65ddc62e113..5dd87a89f011 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -292,7 +292,6 @@ ENDPROC(start_cpu0) * If cpu hotplug is not supported then this code can go in init section * which will be freed later */ -__CPUINIT ENTRY(startup_32_smp) cld movl $(__BOOT_DS),%eax diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index b627746f6b1a..202d24f0f7e7 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -108,9 +108,9 @@ EXPORT_SYMBOL(unlazy_fpu); unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; unsigned int xstate_size; EXPORT_SYMBOL_GPL(xstate_size); -static struct i387_fxsave_struct fx_scratch __cpuinitdata; +static struct i387_fxsave_struct fx_scratch; -static void __cpuinit mxcsr_feature_mask_init(void) +static void mxcsr_feature_mask_init(void) { unsigned long mask = 0; @@ -124,7 +124,7 @@ static void __cpuinit mxcsr_feature_mask_init(void) mxcsr_feature_mask &= mask; } -static void __cpuinit init_thread_xstate(void) +static void init_thread_xstate(void) { /* * Note that xstate_size might be overwriten later during @@ -153,7 +153,7 @@ static void __cpuinit init_thread_xstate(void) * into all processes. */ -void __cpuinit fpu_init(void) +void fpu_init(void) { unsigned long cr0; unsigned long cr4_mask = 0; @@ -608,7 +608,7 @@ static int __init no_387(char *s) __setup("no387", no_387); -void __cpuinit fpu_detect(struct cpuinfo_x86 *c) +void fpu_detect(struct cpuinfo_x86 *c) { unsigned long cr0; u16 fsw, fcw; diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 344faf8d0d62..4186755f1d7c 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -119,7 +119,7 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) /* * allocate per-cpu stacks for hardirq and for softirq processing */ -void __cpuinit irq_ctx_init(int cpu) +void irq_ctx_init(int cpu) { union irq_ctx *irqctx; diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index cd6d9a5a42f6..a96d32cc55b8 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -320,7 +320,7 @@ static void kvm_guest_apic_eoi_write(u32 reg, u32 val) apic_write(APIC_EOI, APIC_EOI_ACK); } -void __cpuinit kvm_guest_cpu_init(void) +void kvm_guest_cpu_init(void) { if (!kvm_para_available()) return; @@ -421,7 +421,7 @@ static void __init kvm_smp_prepare_boot_cpu(void) native_smp_prepare_boot_cpu(); } -static void __cpuinit kvm_guest_cpu_online(void *dummy) +static void kvm_guest_cpu_online(void *dummy) { kvm_guest_cpu_init(); } @@ -435,8 +435,8 @@ static void kvm_guest_cpu_offline(void *dummy) apf_task_wake_all(); } -static int __cpuinit kvm_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int kvm_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { int cpu = (unsigned long)hcpu; switch (action) { @@ -455,7 +455,7 @@ static int __cpuinit kvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata kvm_cpu_notifier = { +static struct notifier_block kvm_cpu_notifier = { .notifier_call = kvm_cpu_notify, }; #endif diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 1f354f4b602b..1570e0741344 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -182,7 +182,7 @@ static void kvm_restore_sched_clock_state(void) } #ifdef CONFIG_X86_LOCAL_APIC -static void __cpuinit kvm_setup_secondary_clock(void) +static void kvm_setup_secondary_clock(void) { /* * Now that the first cpu already had this clocksource initialized, diff --git a/arch/x86/kernel/microcode_amd_early.c b/arch/x86/kernel/microcode_amd_early.c index 1ac6e9aee766..1d14ffee5749 100644 --- a/arch/x86/kernel/microcode_amd_early.c +++ b/arch/x86/kernel/microcode_amd_early.c @@ -82,7 +82,7 @@ static struct cpio_data __init find_ucode_in_initrd(void) * load_microcode_amd() to save equivalent cpu table and microcode patches in * kernel heap memory. */ -static void __cpuinit apply_ucode_in_initrd(void *ucode, size_t size) +static void apply_ucode_in_initrd(void *ucode, size_t size) { struct equiv_cpu_entry *eq; u32 *header; @@ -206,7 +206,7 @@ u8 amd_bsp_mpb[MPB_MAX_SIZE]; * save_microcode_in_initrd_amd() BSP's patch is copied to amd_bsp_mpb, which * is used upon resume from suspend. */ -void __cpuinit load_ucode_amd_ap(void) +void load_ucode_amd_ap(void) { struct microcode_amd *mc; unsigned long *initrd; @@ -238,7 +238,7 @@ static void __init collect_cpu_sig_on_bsp(void *arg) uci->cpu_sig.sig = cpuid_eax(0x00000001); } #else -static void __cpuinit collect_cpu_info_amd_early(struct cpuinfo_x86 *c, +static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c, struct ucode_cpu_info *uci) { u32 rev, eax; @@ -252,7 +252,7 @@ static void __cpuinit collect_cpu_info_amd_early(struct cpuinfo_x86 *c, c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); } -void __cpuinit load_ucode_amd_ap(void) +void load_ucode_amd_ap(void) { unsigned int cpu = smp_processor_id(); diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 22db92bbdf1a..15c987698b0f 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -468,7 +468,7 @@ static struct syscore_ops mc_syscore_ops = { .resume = mc_bp_resume, }; -static __cpuinit int +static int mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c index 86119f63db0c..be7f8514f577 100644 --- a/arch/x86/kernel/microcode_core_early.c +++ b/arch/x86/kernel/microcode_core_early.c @@ -41,7 +41,7 @@ * * x86_vendor() gets vendor information directly through cpuid. */ -static int __cpuinit x86_vendor(void) +static int x86_vendor(void) { u32 eax = 0x00000000; u32 ebx, ecx = 0, edx; @@ -57,7 +57,7 @@ static int __cpuinit x86_vendor(void) return X86_VENDOR_UNKNOWN; } -static int __cpuinit x86_family(void) +static int x86_family(void) { u32 eax = 0x00000001; u32 ebx, ecx = 0, edx; @@ -96,7 +96,7 @@ void __init load_ucode_bsp(void) } } -void __cpuinit load_ucode_ap(void) +void load_ucode_ap(void) { int vendor, x86; diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c index dabef95506f3..1575deb2e636 100644 --- a/arch/x86/kernel/microcode_intel_early.c +++ b/arch/x86/kernel/microcode_intel_early.c @@ -34,7 +34,7 @@ struct mc_saved_data { struct microcode_intel **mc_saved; } mc_saved_data; -static enum ucode_state __cpuinit +static enum ucode_state generic_load_microcode_early(struct microcode_intel **mc_saved_p, unsigned int mc_saved_count, struct ucode_cpu_info *uci) @@ -69,7 +69,7 @@ generic_load_microcode_early(struct microcode_intel **mc_saved_p, return state; } -static void __cpuinit +static void microcode_pointer(struct microcode_intel **mc_saved, unsigned long *mc_saved_in_initrd, unsigned long initrd_start, int mc_saved_count) @@ -82,7 +82,7 @@ microcode_pointer(struct microcode_intel **mc_saved, } #ifdef CONFIG_X86_32 -static void __cpuinit +static void microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mc_saved_data) { @@ -101,7 +101,7 @@ microcode_phys(struct microcode_intel **mc_saved_tmp, } #endif -static enum ucode_state __cpuinit +static enum ucode_state load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *mc_saved_in_initrd, unsigned long initrd_start, @@ -375,7 +375,7 @@ do { \ #define native_wrmsr(msr, low, high) \ native_write_msr(msr, low, high); -static int __cpuinit collect_cpu_info_early(struct ucode_cpu_info *uci) +static int collect_cpu_info_early(struct ucode_cpu_info *uci) { unsigned int val[2]; u8 x86, x86_model; @@ -584,7 +584,7 @@ scan_microcode(unsigned long start, unsigned long end, /* * Print ucode update info. */ -static void __cpuinit +static void print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) { int cpu = smp_processor_id(); @@ -605,7 +605,7 @@ static int current_mc_date; /* * Print early updated ucode info after printk works. This is delayed info dump. */ -void __cpuinit show_ucode_info_early(void) +void show_ucode_info_early(void) { struct ucode_cpu_info uci; @@ -621,7 +621,7 @@ void __cpuinit show_ucode_info_early(void) * mc_saved_data.mc_saved and delay printing microcode info in * show_ucode_info_early() until printk() works. */ -static void __cpuinit print_ucode(struct ucode_cpu_info *uci) +static void print_ucode(struct ucode_cpu_info *uci) { struct microcode_intel *mc_intel; int *delay_ucode_info_p; @@ -643,12 +643,12 @@ static void __cpuinit print_ucode(struct ucode_cpu_info *uci) * Flush global tlb. We only do this in x86_64 where paging has been enabled * already and PGE should be enabled as well. */ -static inline void __cpuinit flush_tlb_early(void) +static inline void flush_tlb_early(void) { __native_flush_tlb_global_irq_disabled(); } -static inline void __cpuinit print_ucode(struct ucode_cpu_info *uci) +static inline void print_ucode(struct ucode_cpu_info *uci) { struct microcode_intel *mc_intel; @@ -660,8 +660,8 @@ static inline void __cpuinit print_ucode(struct ucode_cpu_info *uci) } #endif -static int __cpuinit apply_microcode_early(struct mc_saved_data *mc_saved_data, - struct ucode_cpu_info *uci) +static int apply_microcode_early(struct mc_saved_data *mc_saved_data, + struct ucode_cpu_info *uci) { struct microcode_intel *mc_intel; unsigned int val[2]; @@ -763,7 +763,7 @@ load_ucode_intel_bsp(void) #endif } -void __cpuinit load_ucode_intel_ap(void) +void load_ucode_intel_ap(void) { struct mc_saved_data *mc_saved_data_p; struct ucode_cpu_info uci; diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index ac861b8348e2..f4c886d9165c 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -24,14 +24,14 @@ struct pci_hostbridge_probe { u32 device; }; -static u64 __cpuinitdata fam10h_pci_mmconf_base; +static u64 fam10h_pci_mmconf_base; -static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = { +static struct pci_hostbridge_probe pci_probes[] = { { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 }, { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, }; -static int __cpuinit cmp_range(const void *x1, const void *x2) +static int cmp_range(const void *x1, const void *x2) { const struct range *r1 = x1; const struct range *r2 = x2; @@ -49,7 +49,7 @@ static int __cpuinit cmp_range(const void *x1, const void *x2) /* need to avoid (0xfd<<32), (0xfe<<32), and (0xff<<32), ht used space */ #define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32) #define BASE_VALID(b) ((b) + MMCONF_SIZE <= (0xfdULL<<32) || (b) >= (1ULL<<40)) -static void __cpuinit get_fam10h_pci_mmconf_base(void) +static void get_fam10h_pci_mmconf_base(void) { int i; unsigned bus; @@ -166,7 +166,7 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void) fam10h_pci_mmconf_base = base; } -void __cpuinit fam10h_check_enable_mmcfg(void) +void fam10h_check_enable_mmcfg(void) { u64 val; u32 address; @@ -230,7 +230,7 @@ static const struct dmi_system_id __initconst mmconf_dmi_table[] = { {} }; -/* Called from a __cpuinit function, but only on the BSP. */ +/* Called from a non __init function, but only on the BSP. */ void __ref check_enable_amd_mmconf_dmi(void) { dmi_check_system(mmconf_dmi_table); diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index ce130493b802..88458faea2f8 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -200,7 +200,7 @@ static const struct file_operations msr_fops = { .compat_ioctl = msr_ioctl, }; -static int __cpuinit msr_device_create(int cpu) +static int msr_device_create(int cpu) { struct device *dev; @@ -214,8 +214,8 @@ static void msr_device_destroy(int cpu) device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); } -static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int msr_class_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; int err = 0; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 81a5f5e8f142..83369e5a1d27 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -398,7 +398,7 @@ static void amd_e400_idle(void) default_idle(); } -void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) +void select_idle_routine(const struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP if (boot_option_idle_override == IDLE_POLL && smp_num_siblings > 1) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index e68709da8251..f8ec57815c05 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -170,7 +170,7 @@ static struct resource bss_resource = { #ifdef CONFIG_X86_32 /* cpu data as detected by the assembly code in head.S */ -struct cpuinfo_x86 new_cpu_data __cpuinitdata = { +struct cpuinfo_x86 new_cpu_data = { .wp_works_ok = -1, }; /* common cpu data for all cpus */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index bfd348e99369..aecc98a93d1b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -130,7 +130,7 @@ atomic_t init_deasserted; * Report back to the Boot Processor during boot time or to the caller processor * during CPU online. */ -static void __cpuinit smp_callin(void) +static void smp_callin(void) { int cpuid, phys_id; unsigned long timeout; @@ -237,7 +237,7 @@ static int enable_start_cpu0; /* * Activate a secondary processor. */ -notrace static void __cpuinit start_secondary(void *unused) +static void notrace start_secondary(void *unused) { /* * Don't put *anything* before cpu_init(), SMP booting is too @@ -300,7 +300,7 @@ void __init smp_store_boot_cpu_info(void) * The bootstrap kernel entry code has set these up. Save them for * a given CPU */ -void __cpuinit smp_store_cpu_info(int id) +void smp_store_cpu_info(int id) { struct cpuinfo_x86 *c = &cpu_data(id); @@ -313,7 +313,7 @@ void __cpuinit smp_store_cpu_info(int id) identify_secondary_cpu(c); } -static bool __cpuinit +static bool topology_sane(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o, const char *name) { int cpu1 = c->cpu_index, cpu2 = o->cpu_index; @@ -330,7 +330,7 @@ do { \ cpumask_set_cpu((c2), cpu_##_m##_mask(c1)); \ } while (0) -static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) +static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { if (cpu_has_topoext) { int cpu1 = c->cpu_index, cpu2 = o->cpu_index; @@ -348,7 +348,7 @@ static bool __cpuinit match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) return false; } -static bool __cpuinit match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) +static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { int cpu1 = c->cpu_index, cpu2 = o->cpu_index; @@ -359,7 +359,7 @@ static bool __cpuinit match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) return false; } -static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) +static bool match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) { if (c->phys_proc_id == o->phys_proc_id) { if (cpu_has(c, X86_FEATURE_AMD_DCM)) @@ -370,7 +370,7 @@ static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) return false; } -void __cpuinit set_cpu_sibling_map(int cpu) +void set_cpu_sibling_map(int cpu) { bool has_smt = smp_num_siblings > 1; bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1; @@ -499,7 +499,7 @@ void __inquire_remote_apic(int apicid) * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this * won't ... remember to clear down the APIC, etc later. */ -int __cpuinit +int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip) { unsigned long send_status, accept_status = 0; @@ -533,7 +533,7 @@ wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip) return (send_status | accept_status); } -static int __cpuinit +static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) { unsigned long send_status, accept_status = 0; @@ -649,7 +649,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) } /* reduce the number of lines printed when booting a large cpu count system */ -static void __cpuinit announce_cpu(int cpu, int apicid) +static void announce_cpu(int cpu, int apicid) { static int current_node = -1; int node = early_cpu_to_node(cpu); @@ -691,7 +691,7 @@ static int wakeup_cpu0_nmi(unsigned int cmd, struct pt_regs *regs) * We'll change this code in the future to wake up hard offlined CPU0 if * real platform and request are available. */ -static int __cpuinit +static int wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid, int *cpu0_nmi_registered) { @@ -731,7 +731,7 @@ wakeup_cpu_via_init_nmi(int cpu, unsigned long start_ip, int apicid, * Returns zero if CPU booted OK, else error code from * ->wakeup_secondary_cpu. */ -static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) +static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) { volatile u32 *trampoline_status = (volatile u32 *) __va(real_mode_header->trampoline_status); @@ -872,7 +872,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle) return boot_error; } -int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle) +int native_cpu_up(unsigned int cpu, struct task_struct *tidle) { int apicid = apic->cpu_present_to_apicid(cpu); unsigned long flags; diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 3ff42d2f046d..addf7b58f4e8 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -320,8 +320,8 @@ static int tboot_wait_for_aps(int num_aps) return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps); } -static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int tboot_cpu_callback(struct notifier_block *nfb, unsigned long action, + void *hcpu) { switch (action) { case CPU_DYING: @@ -334,7 +334,7 @@ static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block tboot_cpu_notifier __cpuinitdata = +static struct notifier_block tboot_cpu_notifier = { .notifier_call = tboot_cpu_callback, }; diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 098b3cfda72e..6ff49247edf8 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -824,7 +824,7 @@ static void __init check_system_tsc_reliable(void) * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs. */ -__cpuinit int unsynchronized_tsc(void) +int unsynchronized_tsc(void) { if (!cpu_has_tsc || tsc_unstable) return 1; @@ -1020,7 +1020,7 @@ void __init tsc_init(void) * been calibrated. This assumes that CONSTANT_TSC applies to all * cpus in the socket - this should be a safe assumption. */ -unsigned long __cpuinit calibrate_delay_is_known(void) +unsigned long calibrate_delay_is_known(void) { int i, cpu = smp_processor_id(); diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index fc25e60a5884..adfdf56a3714 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -25,24 +25,24 @@ * Entry/exit counters that make sure that both CPUs * run the measurement code at once: */ -static __cpuinitdata atomic_t start_count; -static __cpuinitdata atomic_t stop_count; +static atomic_t start_count; +static atomic_t stop_count; /* * We use a raw spinlock in this exceptional case, because * we want to have the fastest, inlined, non-debug version * of a critical section, to be able to prove TSC time-warps: */ -static __cpuinitdata arch_spinlock_t sync_lock = __ARCH_SPIN_LOCK_UNLOCKED; +static arch_spinlock_t sync_lock = __ARCH_SPIN_LOCK_UNLOCKED; -static __cpuinitdata cycles_t last_tsc; -static __cpuinitdata cycles_t max_warp; -static __cpuinitdata int nr_warps; +static cycles_t last_tsc; +static cycles_t max_warp; +static int nr_warps; /* * TSC-warp measurement loop running on both CPUs: */ -static __cpuinit void check_tsc_warp(unsigned int timeout) +static void check_tsc_warp(unsigned int timeout) { cycles_t start, now, prev, end; int i; @@ -121,7 +121,7 @@ static inline unsigned int loop_timeout(int cpu) * Source CPU calls into this - it waits for the freshly booted * target CPU to arrive and then starts the measurement: */ -void __cpuinit check_tsc_sync_source(int cpu) +void check_tsc_sync_source(int cpu) { int cpus = 2; @@ -187,7 +187,7 @@ void __cpuinit check_tsc_sync_source(int cpu) /* * Freshly booted CPUs call into this: */ -void __cpuinit check_tsc_sync_target(void) +void check_tsc_sync_target(void) { int cpus = 2; diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 9a907a67be8f..1f96f9347ed9 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -331,7 +331,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) * Assume __initcall executes before all user space. Hopefully kmod * doesn't violate that. We'll find out if it does. */ -static void __cpuinit vsyscall_set_cpu(int cpu) +static void vsyscall_set_cpu(int cpu) { unsigned long d; unsigned long node = 0; @@ -353,13 +353,13 @@ static void __cpuinit vsyscall_set_cpu(int cpu) write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S); } -static void __cpuinit cpu_vsyscall_init(void *arg) +static void cpu_vsyscall_init(void *arg) { /* preemption should be already off */ vsyscall_set_cpu(raw_smp_processor_id()); } -static int __cpuinit +static int cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { long cpu = (long)arg; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 45a14dbbddaf..5f24c71accaa 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -25,7 +25,7 @@ #include #include -void __cpuinit x86_init_noop(void) { } +void x86_init_noop(void) { } void __init x86_init_uint_noop(unsigned int unused) { } int __init iommu_init_noop(void) { return 0; } void iommu_shutdown_noop(void) { } @@ -85,7 +85,7 @@ struct x86_init_ops x86_init __initdata = { }, }; -struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { +struct x86_cpuinit_ops x86_cpuinit = { .early_percpu_clock_init = x86_init_noop, .setup_percpu_clockev = setup_secondary_APIC_clock, }; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index d6c28acdf99c..422fd8223470 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -573,7 +573,7 @@ static void __init xstate_enable_boot_cpu(void) * This is somewhat obfuscated due to the lack of powerful enough * overrides for the section checks. */ -void __cpuinit xsave_init(void) +void xsave_init(void) { static __refdata void (*next_func)(void) = xstate_enable_boot_cpu; void (*this_func)(void); @@ -594,7 +594,7 @@ static inline void __init eager_fpu_init_bp(void) setup_init_fpu_buf(); } -void __cpuinit eager_fpu_init(void) +void eager_fpu_init(void) { static __refdata void (*boot_func)(void) = eager_fpu_init_bp; diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index dc0b727742f4..0057a7accfb1 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c @@ -410,9 +410,7 @@ static void enter_uniprocessor(void) pr_warning("multiple CPUs still online, may miss events.\n"); } -/* __ref because leave_uniprocessor calls cpu_up which is __cpuinit, - but this whole function is ifdefed CONFIG_HOTPLUG_CPU */ -static void __ref leave_uniprocessor(void) +static void leave_uniprocessor(void) { int cpu; int err; diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index a71c4e207679..8bf93bae1f13 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -60,7 +60,7 @@ s16 __apicid_to_node[MAX_LOCAL_APIC] = { [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE }; -int __cpuinit numa_cpu_node(int cpu) +int numa_cpu_node(int cpu) { int apicid = early_per_cpu(x86_cpu_to_apicid, cpu); @@ -691,12 +691,12 @@ void __init init_cpu_to_node(void) #ifndef CONFIG_DEBUG_PER_CPU_MAPS # ifndef CONFIG_NUMA_EMU -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } @@ -763,17 +763,17 @@ void debug_cpumask_set_cpu(int cpu, int node, bool enable) } # ifndef CONFIG_NUMA_EMU -static void __cpuinit numa_set_cpumask(int cpu, bool enable) +static void numa_set_cpumask(int cpu, bool enable) { debug_cpumask_set_cpu(cpu, early_cpu_to_node(cpu), enable); } -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { numa_set_cpumask(cpu, true); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { numa_set_cpumask(cpu, false); } diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c index dbbbb47260cc..a8f90ce3dedf 100644 --- a/arch/x86/mm/numa_emulation.c +++ b/arch/x86/mm/numa_emulation.c @@ -10,7 +10,7 @@ #include "numa_internal.h" -static int emu_nid_to_phys[MAX_NUMNODES] __cpuinitdata; +static int emu_nid_to_phys[MAX_NUMNODES]; static char *emu_cmdline __initdata; void __init numa_emu_cmdline(char *str) @@ -444,7 +444,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) } #ifndef CONFIG_DEBUG_PER_CPU_MAPS -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { int physnid, nid; @@ -462,7 +462,7 @@ void __cpuinit numa_add_cpu(int cpu) cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { int i; @@ -470,7 +470,7 @@ void __cpuinit numa_remove_cpu(int cpu) cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); } #else /* !CONFIG_DEBUG_PER_CPU_MAPS */ -static void __cpuinit numa_set_cpumask(int cpu, bool enable) +static void numa_set_cpumask(int cpu, bool enable) { int nid, physnid; @@ -490,12 +490,12 @@ static void __cpuinit numa_set_cpumask(int cpu, bool enable) } } -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { numa_set_cpumask(cpu, true); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { numa_set_cpumask(cpu, false); } diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 410531d3c292..90555bf60aa4 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -5,7 +5,7 @@ #include #include -static int disable_nx __cpuinitdata; +static int disable_nx; /* * noexec = on|off @@ -29,7 +29,7 @@ static int __init noexec_setup(char *str) } early_param("noexec", noexec_setup); -void __cpuinit x86_configure_nx(void) +void x86_configure_nx(void) { if (cpu_has_nx && !disable_nx) __supported_pte_mask |= _PAGE_NX; diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index e9e6ed5cdf94..a48be98e9ded 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -312,7 +312,7 @@ static int __init early_fill_mp_bus_info(void) #define ENABLE_CF8_EXT_CFG (1ULL << 46) -static void __cpuinit enable_pci_io_ecs(void *unused) +static void enable_pci_io_ecs(void *unused) { u64 reg; rdmsrl(MSR_AMD64_NB_CFG, reg); @@ -322,8 +322,8 @@ static void __cpuinit enable_pci_io_ecs(void *unused) } } -static int __cpuinit amd_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int amd_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { int cpu = (long)hcpu; switch (action) { @@ -337,7 +337,7 @@ static int __cpuinit amd_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata amd_cpu_notifier = { +static struct notifier_block amd_cpu_notifier = { .notifier_call = amd_cpu_notify, }; diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index f8ab4945892e..baec704231b3 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -134,7 +134,7 @@ static void __init sdv_arch_setup(void) } #ifdef CONFIG_X86_IO_APIC -static void __cpuinit sdv_pci_init(void) +static void sdv_pci_init(void) { x86_of_pci_init(); /* We can't set this earlier, because we need to calibrate the timer */ diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index a0a0a4389bbd..47fe66fe61f1 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -65,7 +65,7 @@ * lapic (always-on,ARAT) ------ 150 */ -__cpuinitdata enum mrst_timer_options mrst_timer_options; +enum mrst_timer_options mrst_timer_options; static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; @@ -248,7 +248,7 @@ static void __init mrst_time_init(void) apbt_time_init(); } -static void __cpuinit mrst_arch_setup(void) +static void mrst_arch_setup(void) { if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 2fa02bc50034..193097ef3d7d 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1681,8 +1681,8 @@ static void __init init_hvm_pv_info(void) xen_domain_type = XEN_HVM_DOMAIN; } -static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { int cpu = (long)hcpu; switch (action) { @@ -1700,7 +1700,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block xen_hvm_cpu_notifier __cpuinitdata = { +static struct notifier_block xen_hvm_cpu_notifier = { .notifier_call = xen_hvm_cpu_notify, }; diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 94eac5c85cdc..056d11faef21 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -475,7 +475,7 @@ static void __init fiddle_vdso(void) #endif } -static int __cpuinit register_callback(unsigned type, const void *func) +static int register_callback(unsigned type, const void *func) { struct callback_register callback = { .type = type, @@ -486,7 +486,7 @@ static int __cpuinit register_callback(unsigned type, const void *func) return HYPERVISOR_callback_op(CALLBACKOP_register, &callback); } -void __cpuinit xen_enable_sysenter(void) +void xen_enable_sysenter(void) { int ret; unsigned sysenter_feature; @@ -505,7 +505,7 @@ void __cpuinit xen_enable_sysenter(void) setup_clear_cpu_cap(sysenter_feature); } -void __cpuinit xen_enable_syscall(void) +void xen_enable_syscall(void) { #ifdef CONFIG_X86_64 int ret; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index c1367b29c3b1..ca92754eb846 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -65,7 +65,7 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void __cpuinit cpu_bringup(void) +static void cpu_bringup(void) { int cpu; @@ -97,7 +97,7 @@ static void __cpuinit cpu_bringup(void) wmb(); /* make sure everything is out */ } -static void __cpuinit cpu_bringup_and_idle(void) +static void cpu_bringup_and_idle(void) { cpu_bringup(); cpu_startup_entry(CPUHP_ONLINE); @@ -326,7 +326,7 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) set_cpu_present(cpu, true); } -static int __cpuinit +static int cpu_initialize_context(unsigned int cpu, struct task_struct *idle) { struct vcpu_guest_context *ctxt; @@ -397,7 +397,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) return 0; } -static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle) +static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) { int rc; @@ -470,7 +470,7 @@ static void xen_cpu_die(unsigned int cpu) xen_teardown_timer(cpu); } -static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ +static void xen_play_dead(void) /* used only with HOTPLUG_CPU */ { play_dead_common(); HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); @@ -691,7 +691,7 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) xen_init_lock_cpu(0); } -static int __cpuinit xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) +static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) { int rc; rc = native_cpu_up(cpu, tidle); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index a40f8508e760..cf3caee356b3 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -361,7 +361,7 @@ static irqreturn_t dummy_handler(int irq, void *dev_id) return IRQ_HANDLED; } -void __cpuinit xen_init_lock_cpu(int cpu) +void xen_init_lock_cpu(int cpu) { int irq; char *name; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index a95b41744ad0..86782c5d7e2a 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -73,7 +73,7 @@ static inline void xen_hvm_smp_init(void) {} #ifdef CONFIG_PARAVIRT_SPINLOCKS void __init xen_init_spinlocks(void); -void __cpuinit xen_init_lock_cpu(int cpu); +void xen_init_lock_cpu(int cpu); void xen_uninit_lock_cpu(int cpu); #else static inline void xen_init_spinlocks(void) -- GitLab From 8c37bb3ac95b8ff953bd3c8bc8dd0a393d5ae989 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 11:32:08 -0400 Subject: [PATCH 2772/2900] clocksource+irqchip: delete __cpuinit usage from all related files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/clocksource and drivers/irqchip uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: John Stultz Cc: Thomas Gleixner Acked-by: Thomas Gleixner Signed-off-by: Paul Gortmaker --- drivers/clocksource/arm_arch_timer.c | 8 ++++---- drivers/clocksource/arm_global_timer.c | 8 ++++---- drivers/clocksource/dummy_timer.c | 6 +++--- drivers/clocksource/exynos_mct.c | 4 ++-- drivers/clocksource/metag_generic.c | 6 +++--- drivers/clocksource/time-armada-370-xp.c | 4 ++-- drivers/clocksource/timer-marco.c | 4 ++-- drivers/irqchip/irq-gic.c | 8 ++++---- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 053d846ab5b1..ffadd836e0b5 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -123,7 +123,7 @@ static int arch_timer_set_next_event_phys(unsigned long evt, return 0; } -static int __cpuinit arch_timer_setup(struct clock_event_device *clk) +static int arch_timer_setup(struct clock_event_device *clk) { clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->name = "arch_sys_timer"; @@ -221,7 +221,7 @@ struct timecounter *arch_timer_get_timecounter(void) return &timecounter; } -static void __cpuinit arch_timer_stop(struct clock_event_device *clk) +static void arch_timer_stop(struct clock_event_device *clk) { pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", clk->irq, smp_processor_id()); @@ -237,7 +237,7 @@ static void __cpuinit arch_timer_stop(struct clock_event_device *clk) clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); } -static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, +static int arch_timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -256,7 +256,7 @@ static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block arch_timer_cpu_nb __cpuinitdata = { +static struct notifier_block arch_timer_cpu_nb = { .notifier_call = arch_timer_cpu_notify, }; diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index db8afc7427a6..b66c1f36066c 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -164,7 +164,7 @@ static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __cpuinit gt_clockevents_init(struct clock_event_device *clk) +static int gt_clockevents_init(struct clock_event_device *clk) { int cpu = smp_processor_id(); @@ -221,8 +221,8 @@ static void __init gt_clocksource_init(void) clocksource_register_hz(>_clocksource, gt_clk_rate); } -static int __cpuinit gt_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int gt_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { case CPU_STARTING: @@ -235,7 +235,7 @@ static int __cpuinit gt_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block gt_cpu_nb __cpuinitdata = { +static struct notifier_block gt_cpu_nb = { .notifier_call = gt_cpu_notify, }; diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c index 1f55f9620338..b3eb582d6a6f 100644 --- a/drivers/clocksource/dummy_timer.c +++ b/drivers/clocksource/dummy_timer.c @@ -25,7 +25,7 @@ static void dummy_timer_set_mode(enum clock_event_mode mode, */ } -static void __cpuinit dummy_timer_setup(void) +static void dummy_timer_setup(void) { int cpu = smp_processor_id(); struct clock_event_device *evt = __this_cpu_ptr(&dummy_timer_evt); @@ -41,7 +41,7 @@ static void __cpuinit dummy_timer_setup(void) clockevents_register_device(evt); } -static int __cpuinit dummy_timer_cpu_notify(struct notifier_block *self, +static int dummy_timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING) @@ -50,7 +50,7 @@ static int __cpuinit dummy_timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block dummy_timer_cpu_nb __cpuinitdata = { +static struct notifier_block dummy_timer_cpu_nb = { .notifier_call = dummy_timer_cpu_notify, }; diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index a70480409ea5..b2bbc415f120 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -400,7 +400,7 @@ static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) +static int exynos4_local_timer_setup(struct clock_event_device *evt) { struct mct_clock_event_device *mevt; unsigned int cpu = smp_processor_id(); @@ -448,7 +448,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt) disable_percpu_irq(mct_irqs[MCT_L0_IRQ]); } -static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { +static struct local_timer_ops exynos4_mct_tick_ops = { .setup = exynos4_local_timer_setup, .stop = exynos4_local_timer_stop, }; diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index 6722f0e2fe40..9e4db41abe3c 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c @@ -109,7 +109,7 @@ unsigned long long sched_clock(void) return ticks << HARDWARE_TO_NS_SHIFT; } -static void __cpuinit arch_timer_setup(unsigned int cpu) +static void arch_timer_setup(unsigned int cpu) { unsigned int txdivtime; struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); @@ -154,7 +154,7 @@ static void __cpuinit arch_timer_setup(unsigned int cpu) } } -static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, +static int arch_timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; @@ -169,7 +169,7 @@ static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata arch_timer_cpu_nb = { +static struct notifier_block arch_timer_cpu_nb = { .notifier_call = arch_timer_cpu_notify, }; diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index efdca3263afe..1b04b7e1d39b 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -167,7 +167,7 @@ static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id) /* * Setup the local clock events for a CPU. */ -static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt) +static int armada_370_xp_timer_setup(struct clock_event_device *evt) { u32 u; int cpu = smp_processor_id(); @@ -205,7 +205,7 @@ static void armada_370_xp_timer_stop(struct clock_event_device *evt) disable_percpu_irq(evt->irq); } -static struct local_timer_ops armada_370_xp_local_timer_ops __cpuinitdata = { +static struct local_timer_ops armada_370_xp_local_timer_ops = { .setup = armada_370_xp_timer_setup, .stop = armada_370_xp_timer_stop, }; diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index e5dc9129ca26..62876baa3ab9 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c @@ -184,7 +184,7 @@ static struct irqaction sirfsoc_timer1_irq = { .handler = sirfsoc_timer_interrupt, }; -static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce) +static int sirfsoc_local_timer_setup(struct clock_event_device *ce) { /* Use existing clock_event for cpu 0 */ if (!smp_processor_id()) @@ -216,7 +216,7 @@ static void sirfsoc_local_timer_stop(struct clock_event_device *ce) remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq); } -static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = { +static struct local_timer_ops sirfsoc_local_timer_ops = { .setup = sirfsoc_local_timer_setup, .stop = sirfsoc_local_timer_stop, }; diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 19ceaa60e0f4..ee7c50312066 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -414,7 +414,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(1, base + GIC_DIST_CTRL); } -static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) +static void gic_cpu_init(struct gic_chip_data *gic) { void __iomem *dist_base = gic_data_dist_base(gic); void __iomem *base = gic_data_cpu_base(gic); @@ -702,8 +702,8 @@ static int gic_irq_domain_xlate(struct irq_domain *d, } #ifdef CONFIG_SMP -static int __cpuinit gic_secondary_init(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int gic_secondary_init(struct notifier_block *nfb, unsigned long action, + void *hcpu) { if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) gic_cpu_init(&gic_data[0]); @@ -714,7 +714,7 @@ static int __cpuinit gic_secondary_init(struct notifier_block *nfb, * Notifier for enabling the GIC CPU interface. Set an arbitrarily high * priority because the GIC needs to be up before the ARM generic timers. */ -static struct notifier_block __cpuinitdata gic_cpu_notifier = { +static struct notifier_block gic_cpu_notifier = { .notifier_call = gic_secondary_init, .priority = 100, }; -- GitLab From 2760984f6578d5a462155bb4727766d0c8b68387 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 13:54:04 -0400 Subject: [PATCH 2773/2900] cpufreq: delete __cpuinit usage from all cpufreq files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/cpufreq uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 [v2: leave 2nd lines of args misaligned as requested by Viresh] Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Cc: cpufreq@vger.kernel.org Cc: linux-pm@vger.kernel.org Acked-by: Dirk Brandewie Acked-by: Viresh Kumar Signed-off-by: Paul Gortmaker --- drivers/cpufreq/cpufreq.c | 2 +- drivers/cpufreq/cpufreq_stats.c | 2 +- drivers/cpufreq/dbx500-cpufreq.c | 2 +- drivers/cpufreq/intel_pstate.c | 4 ++-- drivers/cpufreq/longhaul.c | 6 +++--- drivers/cpufreq/longhaul.h | 26 +++++++++++++------------- drivers/cpufreq/longrun.c | 6 +++--- drivers/cpufreq/omap-cpufreq.c | 2 +- drivers/cpufreq/powernow-k7.c | 8 ++++---- drivers/cpufreq/powernow-k8.c | 6 +++--- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0937b8d6c2a4..b7bda8d9f081 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1932,7 +1932,7 @@ int cpufreq_update_policy(unsigned int cpu) } EXPORT_SYMBOL(cpufreq_update_policy); -static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, +static int cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index cd9e81713a71..c1ec11c513c1 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -341,7 +341,7 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb, return 0; } -static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, +static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c index 1fdb02b9f1ec..26321cdc1946 100644 --- a/drivers/cpufreq/dbx500-cpufreq.c +++ b/drivers/cpufreq/dbx500-cpufreq.c @@ -82,7 +82,7 @@ static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu) return freq_table[i].frequency; } -static int __cpuinit dbx500_cpufreq_init(struct cpufreq_policy *policy) +static int dbx500_cpufreq_init(struct cpufreq_policy *policy) { int res; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 07f2840ad805..b012d7600e1a 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -617,7 +617,7 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy) return 0; } -static int __cpuinit intel_pstate_cpu_exit(struct cpufreq_policy *policy) +static int intel_pstate_cpu_exit(struct cpufreq_policy *policy) { int cpu = policy->cpu; @@ -627,7 +627,7 @@ static int __cpuinit intel_pstate_cpu_exit(struct cpufreq_policy *policy) return 0; } -static int __cpuinit intel_pstate_cpu_init(struct cpufreq_policy *policy) +static int intel_pstate_cpu_init(struct cpufreq_policy *policy) { int rc, min_pstate, max_pstate; struct cpudata *cpu; diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index b6a0a7a406b0..8c49261df57d 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -422,7 +422,7 @@ static int guess_fsb(int mult) } -static int __cpuinit longhaul_get_ranges(void) +static int longhaul_get_ranges(void) { unsigned int i, j, k = 0; unsigned int ratio; @@ -526,7 +526,7 @@ static int __cpuinit longhaul_get_ranges(void) } -static void __cpuinit longhaul_setup_voltagescaling(void) +static void longhaul_setup_voltagescaling(void) { union msr_longhaul longhaul; struct mV_pos minvid, maxvid, vid; @@ -780,7 +780,7 @@ static int longhaul_setup_southbridge(void) return 0; } -static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy) +static int longhaul_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = &cpu_data(0); char *cpuname = NULL; diff --git a/drivers/cpufreq/longhaul.h b/drivers/cpufreq/longhaul.h index e2dc436099d1..1928b923a57b 100644 --- a/drivers/cpufreq/longhaul.h +++ b/drivers/cpufreq/longhaul.h @@ -56,7 +56,7 @@ union msr_longhaul { /* * VIA C3 Samuel 1 & Samuel 2 (stepping 0) */ -static const int __cpuinitconst samuel1_mults[16] = { +static const int samuel1_mults[16] = { -1, /* 0000 -> RESERVED */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -75,7 +75,7 @@ static const int __cpuinitconst samuel1_mults[16] = { -1, /* 1111 -> RESERVED */ }; -static const int __cpuinitconst samuel1_eblcr[16] = { +static const int samuel1_eblcr[16] = { 50, /* 0000 -> RESERVED */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -97,7 +97,7 @@ static const int __cpuinitconst samuel1_eblcr[16] = { /* * VIA C3 Samuel2 Stepping 1->15 */ -static const int __cpuinitconst samuel2_eblcr[16] = { +static const int samuel2_eblcr[16] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -119,7 +119,7 @@ static const int __cpuinitconst samuel2_eblcr[16] = { /* * VIA C3 Ezra */ -static const int __cpuinitconst ezra_mults[16] = { +static const int ezra_mults[16] = { 100, /* 0000 -> 10.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -138,7 +138,7 @@ static const int __cpuinitconst ezra_mults[16] = { 120, /* 1111 -> 12.0x */ }; -static const int __cpuinitconst ezra_eblcr[16] = { +static const int ezra_eblcr[16] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -160,7 +160,7 @@ static const int __cpuinitconst ezra_eblcr[16] = { /* * VIA C3 (Ezra-T) [C5M]. */ -static const int __cpuinitconst ezrat_mults[32] = { +static const int ezrat_mults[32] = { 100, /* 0000 -> 10.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -196,7 +196,7 @@ static const int __cpuinitconst ezrat_mults[32] = { -1, /* 1111 -> RESERVED (12.0x) */ }; -static const int __cpuinitconst ezrat_eblcr[32] = { +static const int ezrat_eblcr[32] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -235,7 +235,7 @@ static const int __cpuinitconst ezrat_eblcr[32] = { /* * VIA C3 Nehemiah */ -static const int __cpuinitconst nehemiah_mults[32] = { +static const int nehemiah_mults[32] = { 100, /* 0000 -> 10.0x */ -1, /* 0001 -> 16.0x */ 40, /* 0010 -> 4.0x */ @@ -270,7 +270,7 @@ static const int __cpuinitconst nehemiah_mults[32] = { -1, /* 1111 -> 12.0x */ }; -static const int __cpuinitconst nehemiah_eblcr[32] = { +static const int nehemiah_eblcr[32] = { 50, /* 0000 -> 5.0x */ 160, /* 0001 -> 16.0x */ 40, /* 0010 -> 4.0x */ @@ -315,7 +315,7 @@ struct mV_pos { unsigned short pos; }; -static const struct mV_pos __cpuinitconst vrm85_mV[32] = { +static const struct mV_pos vrm85_mV[32] = { {1250, 8}, {1200, 6}, {1150, 4}, {1100, 2}, {1050, 0}, {1800, 30}, {1750, 28}, {1700, 26}, {1650, 24}, {1600, 22}, {1550, 20}, {1500, 18}, @@ -326,14 +326,14 @@ static const struct mV_pos __cpuinitconst vrm85_mV[32] = { {1475, 17}, {1425, 15}, {1375, 13}, {1325, 11} }; -static const unsigned char __cpuinitconst mV_vrm85[32] = { +static const unsigned char mV_vrm85[32] = { 0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11, 0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d, 0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19, 0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15 }; -static const struct mV_pos __cpuinitconst mobilevrm_mV[32] = { +static const struct mV_pos mobilevrm_mV[32] = { {1750, 31}, {1700, 30}, {1650, 29}, {1600, 28}, {1550, 27}, {1500, 26}, {1450, 25}, {1400, 24}, {1350, 23}, {1300, 22}, {1250, 21}, {1200, 20}, @@ -344,7 +344,7 @@ static const struct mV_pos __cpuinitconst mobilevrm_mV[32] = { {675, 3}, {650, 2}, {625, 1}, {600, 0} }; -static const unsigned char __cpuinitconst mV_mobilevrm[32] = { +static const unsigned char mV_mobilevrm[32] = { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 8bc9f5fbbaeb..0fe041d1f77f 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c @@ -33,7 +33,7 @@ static unsigned int longrun_low_freq, longrun_high_freq; * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS * and MSR_TMTA_LONGRUN_CTRL */ -static void __cpuinit longrun_get_policy(struct cpufreq_policy *policy) +static void longrun_get_policy(struct cpufreq_policy *policy) { u32 msr_lo, msr_hi; @@ -163,7 +163,7 @@ static unsigned int longrun_get(unsigned int cpu) * TMTA rules: * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq) */ -static int __cpuinit longrun_determine_freqs(unsigned int *low_freq, +static int longrun_determine_freqs(unsigned int *low_freq, unsigned int *high_freq) { u32 msr_lo, msr_hi; @@ -256,7 +256,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq, } -static int __cpuinit longrun_cpu_init(struct cpufreq_policy *policy) +static int longrun_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 29468a522ee9..f31fcfcad514 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -165,7 +165,7 @@ static inline void freq_table_free(void) opp_free_cpufreq_table(mpu_dev, &freq_table); } -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) +static int omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index b9f80b713fda..955870877935 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -563,7 +563,7 @@ static int powernow_verify(struct cpufreq_policy *policy) * We will then get the same kind of behaviour already tested under * the "well-known" other OS. */ -static int __cpuinit fixup_sgtc(void) +static int fixup_sgtc(void) { unsigned int sgtc; unsigned int m; @@ -597,7 +597,7 @@ static unsigned int powernow_get(unsigned int cpu) } -static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d) +static int acer_cpufreq_pst(const struct dmi_system_id *d) { printk(KERN_WARNING PFX "%s laptop with broken PST tables in BIOS detected.\n", @@ -615,7 +615,7 @@ static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d) * A BIOS update is all that can save them. * Mention this, and disable cpufreq. */ -static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = { +static struct dmi_system_id powernow_dmi_table[] = { { .callback = acer_cpufreq_pst, .ident = "Acer Aspire", @@ -627,7 +627,7 @@ static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = { { } }; -static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy) +static int powernow_cpu_init(struct cpufreq_policy *policy) { union msr_fidvidstatus fidvidstatus; int result; diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 78f018f2a5de..c39d189217cb 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1069,7 +1069,7 @@ struct init_on_cpu { int rc; }; -static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu) +static void powernowk8_cpu_init_on_cpu(void *_init_on_cpu) { struct init_on_cpu *init_on_cpu = _init_on_cpu; @@ -1096,7 +1096,7 @@ static const char missing_pss_msg[] = FW_BUG PFX "If that doesn't help, try upgrading your BIOS.\n"; /* per CPU init entry point to the driver */ -static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) +static int powernowk8_cpu_init(struct cpufreq_policy *pol) { struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; @@ -1263,7 +1263,7 @@ static void __request_acpi_cpufreq(void) } /* driver entry point for init */ -static int __cpuinit powernowk8_init(void) +static int powernowk8_init(void) { unsigned int i, supported_cpus = 0; int ret; -- GitLab From d23e2ae1aae52bb80bd90525179375817db99809 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 14:02:20 -0400 Subject: [PATCH 2774/2900] hwmon: delete __cpuinit usage from all hwmon files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/hwmon uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Fenghua Yu Cc: lm-sensors@lm-sensors.org Acked-by: Guenter Roeck Signed-off-by: Paul Gortmaker --- drivers/hwmon/coretemp.c | 39 +++++++++++++++++-------------------- drivers/hwmon/via-cputemp.c | 8 ++++---- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index ade35cf3f488..2e5e2dc47eaf 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -195,7 +195,7 @@ struct tjmax { int tjmax; }; -static const struct tjmax __cpuinitconst tjmax_table[] = { +static const struct tjmax tjmax_table[] = { { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 Sodaville */ @@ -211,7 +211,7 @@ struct tjmax_model { #define ANY 0xff -static const struct tjmax_model __cpuinitconst tjmax_model_table[] = { +static const struct tjmax_model tjmax_model_table[] = { { 0x1c, 10, 100000 }, /* D4xx, K4xx, N4xx, D5xx, K5xx, N5xx */ { 0x1c, ANY, 90000 }, /* Z5xx, N2xx, possibly others * Note: Also matches 230 and 330, @@ -226,8 +226,7 @@ static const struct tjmax_model __cpuinitconst tjmax_model_table[] = { { 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */ }; -static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, - struct device *dev) +static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) { /* The 100C is default for both mobile and non mobile CPUs */ @@ -317,8 +316,7 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, return tjmax; } -static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id, - struct device *dev) +static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) { int err; u32 eax, edx; @@ -367,8 +365,8 @@ static int create_name_attr(struct platform_data *pdata, return device_create_file(dev, &pdata->name_attr); } -static int __cpuinit create_core_attrs(struct temp_data *tdata, - struct device *dev, int attr_no) +static int create_core_attrs(struct temp_data *tdata, struct device *dev, + int attr_no) { int err, i; static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, @@ -401,7 +399,7 @@ static int __cpuinit create_core_attrs(struct temp_data *tdata, } -static int __cpuinit chk_ucode_version(unsigned int cpu) +static int chk_ucode_version(unsigned int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -417,7 +415,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu) return 0; } -static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) +static struct platform_device *coretemp_get_pdev(unsigned int cpu) { u16 phys_proc_id = TO_PHYS_ID(cpu); struct pdev_entry *p; @@ -434,8 +432,7 @@ static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) return NULL; } -static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, - int pkg_flag) +static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) { struct temp_data *tdata; @@ -453,8 +450,8 @@ static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, return tdata; } -static int __cpuinit create_core_data(struct platform_device *pdev, - unsigned int cpu, int pkg_flag) +static int create_core_data(struct platform_device *pdev, unsigned int cpu, + int pkg_flag) { struct temp_data *tdata; struct platform_data *pdata = platform_get_drvdata(pdev); @@ -524,7 +521,7 @@ static int __cpuinit create_core_data(struct platform_device *pdev, return err; } -static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag) +static void coretemp_add_core(unsigned int cpu, int pkg_flag) { struct platform_device *pdev = coretemp_get_pdev(cpu); int err; @@ -607,7 +604,7 @@ static struct platform_driver coretemp_driver = { .remove = coretemp_remove, }; -static int __cpuinit coretemp_device_add(unsigned int cpu) +static int coretemp_device_add(unsigned int cpu) { int err; struct platform_device *pdev; @@ -651,7 +648,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) return err; } -static void __cpuinit coretemp_device_remove(unsigned int cpu) +static void coretemp_device_remove(unsigned int cpu) { struct pdev_entry *p, *n; u16 phys_proc_id = TO_PHYS_ID(cpu); @@ -667,7 +664,7 @@ static void __cpuinit coretemp_device_remove(unsigned int cpu) mutex_unlock(&pdev_list_mutex); } -static bool __cpuinit is_any_core_online(struct platform_data *pdata) +static bool is_any_core_online(struct platform_data *pdata) { int i; @@ -681,7 +678,7 @@ static bool __cpuinit is_any_core_online(struct platform_data *pdata) return false; } -static void __cpuinit get_core_online(unsigned int cpu) +static void get_core_online(unsigned int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct platform_device *pdev = coretemp_get_pdev(cpu); @@ -723,7 +720,7 @@ static void __cpuinit get_core_online(unsigned int cpu) coretemp_add_core(cpu, 0); } -static void __cpuinit put_core_offline(unsigned int cpu) +static void put_core_offline(unsigned int cpu) { int i, indx; struct platform_data *pdata; @@ -771,7 +768,7 @@ static void __cpuinit put_core_offline(unsigned int cpu) coretemp_device_remove(cpu); } -static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, +static int coretemp_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long) hcpu; diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 76f157b568ed..38944e94f65f 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -221,7 +221,7 @@ struct pdev_entry { static LIST_HEAD(pdev_list); static DEFINE_MUTEX(pdev_list_mutex); -static int __cpuinit via_cputemp_device_add(unsigned int cpu) +static int via_cputemp_device_add(unsigned int cpu) { int err; struct platform_device *pdev; @@ -262,7 +262,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu) return err; } -static void __cpuinit via_cputemp_device_remove(unsigned int cpu) +static void via_cputemp_device_remove(unsigned int cpu) { struct pdev_entry *p; @@ -279,8 +279,8 @@ static void __cpuinit via_cputemp_device_remove(unsigned int cpu) mutex_unlock(&pdev_list_mutex); } -static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int via_cputemp_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long) hcpu; -- GitLab From fe7bf106ebc22730797ba9b51308b166d68b77f9 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 14:30:58 -0400 Subject: [PATCH 2775/2900] acpi: delete __cpuinit usage from all acpi files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/acpi uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Len Brown Cc: "Rafael J. Wysocki" Cc: linux-acpi@vger.kernel.org Signed-off-by: Paul Gortmaker --- drivers/acpi/acpi_processor.c | 2 +- drivers/acpi/processor_core.c | 8 ++++---- drivers/acpi/processor_driver.c | 8 ++++---- drivers/acpi/processor_idle.c | 6 ++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index e9b01e35ac37..fd6c51cc3acb 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -340,7 +340,7 @@ static int acpi_processor_get_info(struct acpi_device *device) */ static DEFINE_PER_CPU(void *, processor_device_array); -static int __cpuinit acpi_processor_add(struct acpi_device *device, +static int acpi_processor_add(struct acpi_device *device, const struct acpi_device_id *id) { struct acpi_processor *pr; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 164d49569aeb..a5e9f4a5b281 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -253,7 +253,7 @@ static bool __init processor_physically_present(acpi_handle handle) return true; } -static void __cpuinit acpi_set_pdc_bits(u32 *buf) +static void acpi_set_pdc_bits(u32 *buf) { buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -265,7 +265,7 @@ static void __cpuinit acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; @@ -308,7 +308,7 @@ static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int __cpuinit +static int acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; @@ -336,7 +336,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void __cpuinit acpi_processor_set_pdc(acpi_handle handle) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 823be116619e..870eaf5fa547 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -118,9 +118,9 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) return; } -static __cpuinit int __acpi_processor_start(struct acpi_device *device); +static int __acpi_processor_start(struct acpi_device *device); -static int __cpuinit acpi_cpu_soft_notify(struct notifier_block *nfb, +static int acpi_cpu_soft_notify(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -162,7 +162,7 @@ static struct notifier_block __refdata acpi_cpu_notifier = .notifier_call = acpi_cpu_soft_notify, }; -static __cpuinit int __acpi_processor_start(struct acpi_device *device) +static int __acpi_processor_start(struct acpi_device *device) { struct acpi_processor *pr = acpi_driver_data(device); acpi_status status; @@ -226,7 +226,7 @@ static __cpuinit int __acpi_processor_start(struct acpi_device *device) return result; } -static int __cpuinit acpi_processor_start(struct device *dev) +static int acpi_processor_start(struct device *dev) { struct acpi_device *device; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0461ccc92c54..f98dd00b51a9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -96,9 +96,7 @@ static int set_max_cstate(const struct dmi_system_id *id) return 0; } -/* Actually this shouldn't be __cpuinitdata, would be better to fix the - callers to only run once -AK */ -static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { +static struct dmi_system_id processor_power_dmi_table[] = { { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, @@ -1165,7 +1163,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) static int acpi_processor_registered; -int __cpuinit acpi_processor_power_init(struct acpi_processor *pr) +int acpi_processor_power_init(struct acpi_processor *pr) { acpi_status status = 0; int retval; -- GitLab From 013dbb325be702d777118d5e4ffefff3dad2b153 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 14:32:33 -0400 Subject: [PATCH 2776/2900] net: delete __cpuinit usage from all net files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the net/* uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: "David S. Miller" Cc: netdev@vger.kernel.org Signed-off-by: Paul Gortmaker --- net/core/flow.c | 4 ++-- net/iucv/iucv.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/flow.c b/net/core/flow.c index 7102f166482d..dfa602ceb8cd 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -403,7 +403,7 @@ void flow_cache_flush_deferred(void) schedule_work(&flow_cache_flush_work); } -static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) +static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) { struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); size_t sz = sizeof(struct hlist_head) * flow_cache_hash_size(fc); @@ -421,7 +421,7 @@ static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) return 0; } -static int __cpuinit flow_cache_cpu(struct notifier_block *nfb, +static int flow_cache_cpu(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 4fe76ff214c2..cd5b8ec9be04 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -621,7 +621,7 @@ static void iucv_disable(void) put_online_cpus(); } -static int __cpuinit iucv_cpu_notify(struct notifier_block *self, +static int iucv_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { cpumask_t cpumask; -- GitLab From 49fb4c6290c70c418a5c25eee996d6b55ea132d6 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 14:52:21 -0400 Subject: [PATCH 2777/2900] rcu: delete __cpuinit usage from all rcu files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/rcu uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Dipankar Sarma Reviewed-by: Josh Triplett Signed-off-by: Paul Gortmaker --- kernel/rcutorture.c | 6 +++--- kernel/rcutree.c | 6 +++--- kernel/rcutree.h | 4 ++-- kernel/rcutree_plugin.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index b1fa5510388d..f4871e52c546 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -1476,7 +1476,7 @@ rcu_torture_shutdown(void *arg) * Execute random CPU-hotplug operations at the interval specified * by the onoff_interval. */ -static int __cpuinit +static int rcu_torture_onoff(void *arg) { int cpu; @@ -1558,7 +1558,7 @@ rcu_torture_onoff(void *arg) return 0; } -static int __cpuinit +static int rcu_torture_onoff_init(void) { int ret; @@ -1601,7 +1601,7 @@ static void rcu_torture_onoff_cleanup(void) * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then * induces a CPU stall for the time specified by stall_cpu. */ -static int __cpuinit rcu_torture_stall(void *args) +static int rcu_torture_stall(void *args) { unsigned long stop_at; diff --git a/kernel/rcutree.c b/kernel/rcutree.c index e08abb9461ac..068de3a93606 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -2910,7 +2910,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp) * can accept some slop in the rsp->completed access due to the fact * that this CPU cannot possibly have any RCU callbacks in flight yet. */ -static void __cpuinit +static void rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) { unsigned long flags; @@ -2962,7 +2962,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) mutex_unlock(&rsp->onoff_mutex); } -static void __cpuinit rcu_prepare_cpu(int cpu) +static void rcu_prepare_cpu(int cpu) { struct rcu_state *rsp; @@ -2974,7 +2974,7 @@ static void __cpuinit rcu_prepare_cpu(int cpu) /* * Handle CPU online/offline notification events. */ -static int __cpuinit rcu_cpu_notify(struct notifier_block *self, +static int rcu_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 4a39d364493c..b3832581043c 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -521,10 +521,10 @@ static void invoke_rcu_callbacks_kthread(void); static bool rcu_is_callbacks_kthread(void); #ifdef CONFIG_RCU_BOOST static void rcu_preempt_do_callbacks(void); -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, +static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp); #endif /* #ifdef CONFIG_RCU_BOOST */ -static void __cpuinit rcu_prepare_kthreads(int cpu); +static void rcu_prepare_kthreads(int cpu); static void rcu_cleanup_after_idle(int cpu); static void rcu_prepare_for_idle(int cpu); static void rcu_idle_count_callbacks_posted(void); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 63098a59216e..769e12e3151b 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1352,7 +1352,7 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) * already exist. We only create this kthread for preemptible RCU. * Returns zero if all is well, a negated errno otherwise. */ -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, +static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp) { int rnp_index = rnp - &rsp->node[0]; @@ -1507,7 +1507,7 @@ static int __init rcu_spawn_kthreads(void) } early_initcall(rcu_spawn_kthreads); -static void __cpuinit rcu_prepare_kthreads(int cpu) +static void rcu_prepare_kthreads(int cpu) { struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); struct rcu_node *rnp = rdp->mynode; @@ -1549,7 +1549,7 @@ static int __init rcu_scheduler_really_started(void) } early_initcall(rcu_scheduler_really_started); -static void __cpuinit rcu_prepare_kthreads(int cpu) +static void rcu_prepare_kthreads(int cpu) { } -- GitLab From 0db0628d90125193280eabb501c94feaf48fa9ab Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 14:53:51 -0400 Subject: [PATCH 2778/2900] kernel: delete __cpuinit usage from all core kernel files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the uses of the __cpuinit macros from C files in the core kernel directories (kernel, init, lib, mm, and include) that don't really have a specific maintainer. [1] https://lkml.org/lkml/2013/5/20/589 Signed-off-by: Paul Gortmaker --- Documentation/cpu-hotplug.txt | 6 +++--- include/linux/cpu.h | 2 +- include/linux/perf_event.h | 2 +- init/calibrate.c | 13 ++++++++----- kernel/cpu.c | 6 +++--- kernel/events/core.c | 4 ++-- kernel/fork.c | 2 +- kernel/hrtimer.c | 6 +++--- kernel/printk.c | 2 +- kernel/profile.c | 2 +- kernel/relay.c | 2 +- kernel/sched/core.c | 12 ++++++------ kernel/sched/fair.c | 2 +- kernel/smp.c | 2 +- kernel/smpboot.c | 2 +- kernel/softirq.c | 8 ++++---- kernel/time/tick-sched.c | 2 +- kernel/timer.c | 10 +++++----- kernel/workqueue.c | 4 ++-- lib/Kconfig.debug | 2 +- lib/earlycpio.c | 2 +- lib/percpu_counter.c | 2 +- mm/memcontrol.c | 2 +- mm/page-writeback.c | 4 ++-- mm/slab.c | 10 +++++----- mm/slub.c | 4 ++-- mm/vmstat.c | 6 +++--- 27 files changed, 62 insertions(+), 59 deletions(-) diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index edd4b4df3932..786dc82f98ce 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt @@ -267,8 +267,8 @@ Q: If i have some kernel code that needs to be aware of CPU arrival and A: This is what you would need in your kernel code to receive notifications. #include - static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) + static int foobar_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -285,7 +285,7 @@ A: This is what you would need in your kernel code to receive notifications. return NOTIFY_OK; } - static struct notifier_block __cpuinitdata foobar_cpu_notifer = + static struct notifier_block foobar_cpu_notifer = { .notifier_call = foobar_cpu_callback, }; diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 944f283f01c4..ab0eade73039 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -114,7 +114,7 @@ enum { /* Need to know about CPUs going up/down? */ #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) #define cpu_notifier(fn, pri) { \ - static struct notifier_block fn##_nb __cpuinitdata = \ + static struct notifier_block fn##_nb = \ { .notifier_call = fn, .priority = pri }; \ register_cpu_notifier(&fn##_nb); \ } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 8873f82c7baa..c43f6eabad5b 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -826,7 +826,7 @@ static inline void perf_restore_debug_store(void) { } */ #define perf_cpu_notifier(fn) \ do { \ - static struct notifier_block fn##_nb __cpuinitdata = \ + static struct notifier_block fn##_nb = \ { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ unsigned long cpu = smp_processor_id(); \ unsigned long flags; \ diff --git a/init/calibrate.c b/init/calibrate.c index fda0a7b0f06c..520702db9acc 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -31,7 +31,7 @@ __setup("lpj=", lpj_setup); #define DELAY_CALIBRATION_TICKS ((HZ < 100) ? 1 : (HZ/100)) #define MAX_DIRECT_CALIBRATION_RETRIES 5 -static unsigned long __cpuinit calibrate_delay_direct(void) +static unsigned long calibrate_delay_direct(void) { unsigned long pre_start, start, post_start; unsigned long pre_end, end, post_end; @@ -166,7 +166,10 @@ static unsigned long __cpuinit calibrate_delay_direct(void) return 0; } #else -static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} +static unsigned long calibrate_delay_direct(void) +{ + return 0; +} #endif /* @@ -180,7 +183,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} */ #define LPS_PREC 8 -static unsigned long __cpuinit calibrate_delay_converge(void) +static unsigned long calibrate_delay_converge(void) { /* First stage - slowly accelerate to find initial bounds */ unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit; @@ -254,12 +257,12 @@ static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 }; * Architectures should override this function if a faster calibration * method is available. */ -unsigned long __attribute__((weak)) __cpuinit calibrate_delay_is_known(void) +unsigned long __attribute__((weak)) calibrate_delay_is_known(void) { return 0; } -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { unsigned long lpj; static bool printed; diff --git a/kernel/cpu.c b/kernel/cpu.c index 198a38883e64..b2b227b82123 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -366,7 +366,7 @@ EXPORT_SYMBOL(cpu_down); #endif /*CONFIG_HOTPLUG_CPU*/ /* Requires cpu_add_remove_lock to be held */ -static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) +static int _cpu_up(unsigned int cpu, int tasks_frozen) { int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; @@ -419,7 +419,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) return ret; } -int __cpuinit cpu_up(unsigned int cpu) +int cpu_up(unsigned int cpu) { int err = 0; @@ -618,7 +618,7 @@ core_initcall(cpu_hotplug_pm_sync_init); * It must be called by the arch code on the new cpu, before the new cpu * enables interrupts and before the "boot" cpu returns from __cpu_up(). */ -void __cpuinit notify_cpu_starting(unsigned int cpu) +void notify_cpu_starting(unsigned int cpu) { unsigned long val = CPU_STARTING; diff --git a/kernel/events/core.c b/kernel/events/core.c index eba8fb5834ae..f3e9dce39bc9 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7630,7 +7630,7 @@ static void __init perf_event_init_all_cpus(void) } } -static void __cpuinit perf_event_init_cpu(int cpu) +static void perf_event_init_cpu(int cpu) { struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); @@ -7719,7 +7719,7 @@ static struct notifier_block perf_reboot_notifier = { .priority = INT_MIN, }; -static int __cpuinit +static int perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/kernel/fork.c b/kernel/fork.c index 66635c80a813..403d2bb8a968 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1546,7 +1546,7 @@ static inline void init_idle_pids(struct pid_link *links) } } -struct task_struct * __cpuinit fork_idle(int cpu) +struct task_struct *fork_idle(int cpu) { struct task_struct *task; task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index f0f4fe29cd21..383319bae3f7 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -1659,7 +1659,7 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, /* * Functions related to boot-time initialization: */ -static void __cpuinit init_hrtimers_cpu(int cpu) +static void init_hrtimers_cpu(int cpu) { struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); int i; @@ -1740,7 +1740,7 @@ static void migrate_hrtimers(int scpu) #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, +static int hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int scpu = (long)hcpu; @@ -1773,7 +1773,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hrtimers_nb = { +static struct notifier_block hrtimers_nb = { .notifier_call = hrtimer_cpu_notify, }; diff --git a/kernel/printk.c b/kernel/printk.c index d37d45c90ae6..69b0890ed7e5 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1921,7 +1921,7 @@ void resume_console(void) * called when a new CPU comes online (or fails to come up), and ensures * that any such output gets printed. */ -static int __cpuinit console_cpu_notify(struct notifier_block *self, +static int console_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action) { diff --git a/kernel/profile.c b/kernel/profile.c index 0bf400737660..6631e1ef55ab 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -331,7 +331,7 @@ static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) put_cpu(); } -static int __cpuinit profile_cpu_callback(struct notifier_block *info, +static int profile_cpu_callback(struct notifier_block *info, unsigned long action, void *__cpu) { int node, cpu = (unsigned long)__cpu; diff --git a/kernel/relay.c b/kernel/relay.c index b91488ba2e5a..5001c9887db1 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -516,7 +516,7 @@ static void setup_callbacks(struct rchan *chan, * * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) */ -static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb, +static int relay_hotcpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0d8eb4525e76..b7c32cb7bfeb 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4133,7 +4133,7 @@ void show_state_filter(unsigned long state_filter) debug_show_all_locks(); } -void __cpuinit init_idle_bootup_task(struct task_struct *idle) +void init_idle_bootup_task(struct task_struct *idle) { idle->sched_class = &idle_sched_class; } @@ -4146,7 +4146,7 @@ void __cpuinit init_idle_bootup_task(struct task_struct *idle) * NOTE: this function does not set the idle thread's NEED_RESCHED * flag, to make booting more robust. */ -void __cpuinit init_idle(struct task_struct *idle, int cpu) +void init_idle(struct task_struct *idle, int cpu) { struct rq *rq = cpu_rq(cpu); unsigned long flags; @@ -4630,7 +4630,7 @@ static void set_rq_offline(struct rq *rq) * migration_call - callback that gets triggered when a CPU is added. * Here we can start up the necessary migration thread for the new CPU. */ -static int __cpuinit +static int migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { int cpu = (long)hcpu; @@ -4684,12 +4684,12 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) * happens before everything else. This has to be lower priority than * the notifier in the perf_event subsystem, though. */ -static struct notifier_block __cpuinitdata migration_notifier = { +static struct notifier_block migration_notifier = { .notifier_call = migration_call, .priority = CPU_PRI_MIGRATION, }; -static int __cpuinit sched_cpu_active(struct notifier_block *nfb, +static int sched_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { @@ -4702,7 +4702,7 @@ static int __cpuinit sched_cpu_active(struct notifier_block *nfb, } } -static int __cpuinit sched_cpu_inactive(struct notifier_block *nfb, +static int sched_cpu_inactive(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f77f9c527449..bb456f44b7b1 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5506,7 +5506,7 @@ void nohz_balance_enter_idle(int cpu) set_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); } -static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, +static int sched_ilb_notifier(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/kernel/smp.c b/kernel/smp.c index 4dba0f7b72ad..fe9f773d7114 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -73,7 +73,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hotplug_cfd_notifier = { +static struct notifier_block hotplug_cfd_notifier = { .notifier_call = hotplug_cfd, }; diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 02fc5c933673..eb89e1807408 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -24,7 +24,7 @@ */ static DEFINE_PER_CPU(struct task_struct *, idle_threads); -struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) +struct task_struct *idle_thread_get(unsigned int cpu) { struct task_struct *tsk = per_cpu(idle_threads, cpu); diff --git a/kernel/softirq.c b/kernel/softirq.c index ca25e6e704a2..be3d3514c325 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -699,7 +699,7 @@ void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq) } EXPORT_SYMBOL(send_remote_softirq); -static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self, +static int remote_softirq_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -728,7 +728,7 @@ static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = { +static struct notifier_block remote_softirq_cpu_notifier = { .notifier_call = remote_softirq_cpu_notify, }; @@ -830,7 +830,7 @@ static void takeover_tasklets(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit cpu_callback(struct notifier_block *nfb, +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -845,7 +845,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 69601726a745..e80183f4a6c4 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -298,7 +298,7 @@ static int __init tick_nohz_full_setup(char *str) } __setup("nohz_full=", tick_nohz_full_setup); -static int __cpuinit tick_nohz_cpu_down_callback(struct notifier_block *nfb, +static int tick_nohz_cpu_down_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/kernel/timer.c b/kernel/timer.c index 15bc1b41021d..4296d13db3d1 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1505,11 +1505,11 @@ signed long __sched schedule_timeout_uninterruptible(signed long timeout) } EXPORT_SYMBOL(schedule_timeout_uninterruptible); -static int __cpuinit init_timers_cpu(int cpu) +static int init_timers_cpu(int cpu) { int j; struct tvec_base *base; - static char __cpuinitdata tvec_base_done[NR_CPUS]; + static char tvec_base_done[NR_CPUS]; if (!tvec_base_done[cpu]) { static char boot_done; @@ -1577,7 +1577,7 @@ static void migrate_timer_list(struct tvec_base *new_base, struct list_head *hea } } -static void __cpuinit migrate_timers(int cpu) +static void migrate_timers(int cpu) { struct tvec_base *old_base; struct tvec_base *new_base; @@ -1610,7 +1610,7 @@ static void __cpuinit migrate_timers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit timer_cpu_notify(struct notifier_block *self, +static int timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1635,7 +1635,7 @@ static int __cpuinit timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata timers_nb = { +static struct notifier_block timers_nb = { .notifier_call = timer_cpu_notify, }; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f02c4a4a0c3c..0b72e816b8d0 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4644,7 +4644,7 @@ static void restore_unbound_workers_cpumask(struct worker_pool *pool, int cpu) * Workqueues should be brought up before normal priority CPU notifiers. * This will be registered high priority CPU notifier. */ -static int __cpuinit workqueue_cpu_up_callback(struct notifier_block *nfb, +static int workqueue_cpu_up_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -4697,7 +4697,7 @@ static int __cpuinit workqueue_cpu_up_callback(struct notifier_block *nfb, * Workqueues should be brought down after normal priority CPU notifiers. * This will be registered as low priority CPU notifier. */ -static int __cpuinit workqueue_cpu_down_callback(struct notifier_block *nfb, +static int workqueue_cpu_down_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 98ac17ed6222..1501aa553221 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -238,7 +238,7 @@ config DEBUG_SECTION_MISMATCH any use of code/data previously in these sections would most likely result in an oops. In the code, functions and variables are annotated with - __init, __cpuinit, etc. (see the full list in include/linux/init.h), + __init,, etc. (see the full list in include/linux/init.h), which results in the code/data being placed in specific sections. The section mismatch analysis is always performed after a full kernel build, and enabling this option causes the following diff --git a/lib/earlycpio.c b/lib/earlycpio.c index 8078ef49cb79..7aa7ce250c94 100644 --- a/lib/earlycpio.c +++ b/lib/earlycpio.c @@ -63,7 +63,7 @@ enum cpio_fields { * the match returned an empty filename string. */ -struct cpio_data __cpuinit find_cpio_data(const char *path, void *data, +struct cpio_data find_cpio_data(const char *path, void *data, size_t len, long *offset) { const size_t cpio_header_len = 8*C_NFIELDS - 2; diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index 1fc23a3277e1..93c5d5ecff4e 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -158,7 +158,7 @@ static void compute_batch_value(void) percpu_counter_batch = max(32, nr*2); } -static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, +static int percpu_counter_hotcpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { #ifdef CONFIG_HOTPLUG_CPU diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d12ca6f3c293..00a7a664b9c1 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2522,7 +2522,7 @@ static void mem_cgroup_drain_pcp_counter(struct mem_cgroup *memcg, int cpu) spin_unlock(&memcg->pcp_counter_lock); } -static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb, +static int memcg_cpu_hotplug_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 4514ad7415c3..3f0c895c71fe 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1619,7 +1619,7 @@ void writeback_set_ratelimit(void) ratelimit_pages = 16; } -static int __cpuinit +static int ratelimit_handler(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -1634,7 +1634,7 @@ ratelimit_handler(struct notifier_block *self, unsigned long action, } } -static struct notifier_block __cpuinitdata ratelimit_nb = { +static struct notifier_block ratelimit_nb = { .notifier_call = ratelimit_handler, .next = NULL, }; diff --git a/mm/slab.c b/mm/slab.c index 35cb0c861508..2580db062df9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -787,7 +787,7 @@ static void next_reap_node(void) * the CPUs getting into lockstep and contending for the global cache chain * lock. */ -static void __cpuinit start_cpu_timer(int cpu) +static void start_cpu_timer(int cpu) { struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu); @@ -1186,7 +1186,7 @@ static inline int slabs_tofree(struct kmem_cache *cachep, return (n->free_objects + cachep->num - 1) / cachep->num; } -static void __cpuinit cpuup_canceled(long cpu) +static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; struct kmem_cache_node *n = NULL; @@ -1251,7 +1251,7 @@ static void __cpuinit cpuup_canceled(long cpu) } } -static int __cpuinit cpuup_prepare(long cpu) +static int cpuup_prepare(long cpu) { struct kmem_cache *cachep; struct kmem_cache_node *n = NULL; @@ -1334,7 +1334,7 @@ static int __cpuinit cpuup_prepare(long cpu) return -ENOMEM; } -static int __cpuinit cpuup_callback(struct notifier_block *nfb, +static int cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1390,7 +1390,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block __cpuinitdata cpucache_notifier = { +static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 }; diff --git a/mm/slub.c b/mm/slub.c index 3b482c863002..2b02d666bf63 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3773,7 +3773,7 @@ int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) * Use the cpu notifier to insure that the cpu slabs are flushed when * necessary. */ -static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, +static int slab_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -3799,7 +3799,7 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata slab_notifier = { +static struct notifier_block slab_notifier = { .notifier_call = slab_cpuup_callback }; diff --git a/mm/vmstat.c b/mm/vmstat.c index f42745e65780..20c2ef4458fa 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1182,7 +1182,7 @@ static void vmstat_update(struct work_struct *w) round_jiffies_relative(sysctl_stat_interval)); } -static void __cpuinit start_cpu_timer(int cpu) +static void start_cpu_timer(int cpu) { struct delayed_work *work = &per_cpu(vmstat_work, cpu); @@ -1194,7 +1194,7 @@ static void __cpuinit start_cpu_timer(int cpu) * Use the cpu notifier to insure that the thresholds are recalculated * when necessary. */ -static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, +static int vmstat_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1226,7 +1226,7 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata vmstat_notifier = +static struct notifier_block vmstat_notifier = { &vmstat_cpuup_callback, NULL, 0 }; #endif -- GitLab From a83048ebd449a441fdbd3fa854e6b1a71552cc99 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 15:22:41 -0400 Subject: [PATCH 2779/2900] drivers: delete __cpuinit usage from all remaining drivers files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the remaining one-off uses of the __cpuinit macros from all C files in the drivers/* directory. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Greg Kroah-Hartman Acked-by: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker --- drivers/base/cpu.c | 2 +- drivers/base/topology.c | 10 +++++----- drivers/oprofile/timer_int.c | 4 ++-- drivers/xen/xen-acpi-cpuhotplug.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index a16d20e389f0..4c358bc44c72 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -278,7 +278,7 @@ static void cpu_device_release(struct device *dev) * * Initialize and register the CPU device. */ -int __cpuinit register_cpu(struct cpu *cpu, int num) +int register_cpu(struct cpu *cpu, int num) { int error; diff --git a/drivers/base/topology.c b/drivers/base/topology.c index ae989c57cd5e..2f5919ed91ab 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -143,22 +143,22 @@ static struct attribute_group topology_attr_group = { }; /* Add/Remove cpu_topology interface for CPU device */ -static int __cpuinit topology_add_dev(unsigned int cpu) +static int topology_add_dev(unsigned int cpu) { struct device *dev = get_cpu_device(cpu); return sysfs_create_group(&dev->kobj, &topology_attr_group); } -static void __cpuinit topology_remove_dev(unsigned int cpu) +static void topology_remove_dev(unsigned int cpu) { struct device *dev = get_cpu_device(cpu); sysfs_remove_group(&dev->kobj, &topology_attr_group); } -static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static int topology_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; int rc = 0; @@ -178,7 +178,7 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(rc); } -static int __cpuinit topology_sysfs_init(void) +static int topology_sysfs_init(void) { int cpu; int rc; diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 93404f72dfa8..61be1d9c16c8 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -74,8 +74,8 @@ static void oprofile_hrtimer_stop(void) put_online_cpus(); } -static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int oprofile_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) { long cpu = (long) hcpu; diff --git a/drivers/xen/xen-acpi-cpuhotplug.c b/drivers/xen/xen-acpi-cpuhotplug.c index 0caf4863be8c..8dae6c13063a 100644 --- a/drivers/xen/xen-acpi-cpuhotplug.c +++ b/drivers/xen/xen-acpi-cpuhotplug.c @@ -91,7 +91,7 @@ static int xen_acpi_processor_enable(struct acpi_device *device) return 0; } -static int __cpuinit xen_acpi_processor_add(struct acpi_device *device) +static int xen_acpi_processor_add(struct acpi_device *device) { int ret; struct acpi_processor *pr; -- GitLab From 0b776b062843b63cb4c9acdfc092b2581be3c2f6 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 19 Jun 2013 15:26:23 -0400 Subject: [PATCH 2780/2900] block: delete __cpuinit usage from all block files The __cpuinit type of throwaway sections might have made sense some time ago when RAM was more constrained, but now the savings do not offset the cost and complications. For example, the fix in commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time") is a good example of the nasty type of bugs that can be created with improper use of the various __init prefixes. After a discussion on LKML[1] it was decided that cpuinit should go the way of devinit and be phased out. Once all the users are gone, we can then finally remove the macros themselves from linux/init.h. This removes all the drivers/block uses of the __cpuinit macros from all C files. [1] https://lkml.org/lkml/2013/5/20/589 Cc: Jens Axboe Signed-off-by: Paul Gortmaker --- block/blk-iopoll.c | 6 +++--- block/blk-softirq.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c index 58916afbbda5..4b8d9b541112 100644 --- a/block/blk-iopoll.c +++ b/block/blk-iopoll.c @@ -189,8 +189,8 @@ void blk_iopoll_init(struct blk_iopoll *iop, int weight, blk_iopoll_fn *poll_fn) } EXPORT_SYMBOL(blk_iopoll_init); -static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int blk_iopoll_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) { /* * If a CPU goes away, splice its entries to the current CPU @@ -209,7 +209,7 @@ static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_iopoll_cpu_notifier = { +static struct notifier_block blk_iopoll_cpu_notifier = { .notifier_call = blk_iopoll_cpu_notify, }; diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 467c8de88642..ec9e60636f43 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -78,8 +78,8 @@ static int raise_blk_irq(int cpu, struct request *rq) } #endif -static int __cpuinit blk_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int blk_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { /* * If a CPU goes away, splice its entries to the current CPU @@ -98,7 +98,7 @@ static int __cpuinit blk_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_cpu_notifier = { +static struct notifier_block blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; -- GitLab From 8acd5e9b1217e58a57124d9e225afa12efeae20d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 15 Jul 2013 00:09:19 -0400 Subject: [PATCH 2781/2900] ext4: fix error handling in ext4_ext_truncate() Previously ext4_ext_truncate() was ignoring potential error returns from ext4_es_remove_extent() and ext4_ext_remove_space(). This can lead to the on-diks extent tree and the extent status tree cache getting out of sync, which is particuarlly bad, and can lead to file system corruption and potential data loss. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/extents.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 7097b0f680e6..f57cc0e7f1bc 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4405,9 +4405,20 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode) last_block = (inode->i_size + sb->s_blocksize - 1) >> EXT4_BLOCK_SIZE_BITS(sb); +retry: err = ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block); + if (err == ENOMEM) { + cond_resched(); + congestion_wait(BLK_RW_ASYNC, HZ/50); + goto retry; + } + if (err) { + ext4_std_error(inode->i_sb, err); + return; + } err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); + ext4_std_error(inode->i_sb, err); } static void ext4_falloc_update_inode(struct inode *inode, -- GitLab From c8e15130e1636f68d5165aa2605b8e9cba0f644c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 15 Jul 2013 00:09:37 -0400 Subject: [PATCH 2782/2900] ext4: simplify calculation of blocks to free on error In ext4_ext_map_blocks(), if we have successfully allocated the data blocks, but then run into trouble inserting the extent into the extent tree, most likely due to an ENOSPC condition, determine the arguments to ext4_free_blocks() in a simpler way which is easier to prove to be correct. Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f57cc0e7f1bc..593091537e76 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4261,8 +4261,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), - ext4_ext_get_actual_len(&newex), fb_flags); + ext4_free_blocks(handle, inode, NULL, newblock, + EXT4_C2B(sbi, allocated_clusters), fb_flags); goto out2; } -- GitLab From e15f742ce816076497549b955fbec3254820db85 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 15 Jul 2013 00:12:14 -0400 Subject: [PATCH 2783/2900] ext4: make the extent_status code more robust against ENOMEM failures Some callers of ext4_es_remove_extent() and ext4_es_insert_extent() may not be completely robust against ENOMEM failures (or the consequences of reflecting ENOMEM back up to userspace may lead to xfstest or user application failure). To mitigate against this, when trying to insert an entry in the extent status tree, try to shrink the inode's extent status tree before returning ENOMEM. If there are entries which don't record information about extents under delayed allocations, freeing one of them is preferable to returning ENOMEM. Signed-off-by: "Theodore Ts'o" Reviewed-by: Zheng Liu --- fs/ext4/extents_status.c | 51 ++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 4b8df7fbb10a..91cb110da1b4 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -148,6 +148,8 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t end); static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, int nr_to_scan); +static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, + struct ext4_inode_info *locked_ei); int __init ext4_init_es(void) { @@ -665,7 +667,13 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk, err = __es_remove_extent(inode, lblk, end); if (err != 0) goto error; +retry: err = __es_insert_extent(inode, &newes); + if (err == -ENOMEM && __ext4_es_shrink(EXT4_SB(inode->i_sb), 1, + EXT4_I(inode))) + goto retry; + if (err == -ENOMEM && !ext4_es_is_delayed(&newes)) + err = 0; error: write_unlock(&EXT4_I(inode)->i_es_lock); @@ -744,8 +752,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, struct extent_status orig_es; ext4_lblk_t len1, len2; ext4_fsblk_t block; - int err = 0; + int err; +retry: + err = 0; es = __es_tree_search(&tree->root, lblk); if (!es) goto out; @@ -780,6 +790,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, if (err) { es->es_lblk = orig_es.es_lblk; es->es_len = orig_es.es_len; + if ((err == -ENOMEM) && + __ext4_es_shrink(EXT4_SB(inode->i_sb), 1, + EXT4_I(inode))) + goto retry; goto out; } } else { @@ -889,22 +903,14 @@ static int ext4_inode_touch_time_cmp(void *priv, struct list_head *a, return -1; } -static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) +static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, + struct ext4_inode_info *locked_ei) { - struct ext4_sb_info *sbi = container_of(shrink, - struct ext4_sb_info, s_es_shrinker); struct ext4_inode_info *ei; struct list_head *cur, *tmp; LIST_HEAD(skiped); - int nr_to_scan = sc->nr_to_scan; int ret, nr_shrunk = 0; - ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); - trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); - - if (!nr_to_scan) - return ret; - spin_lock(&sbi->s_es_lru_lock); /* @@ -933,7 +939,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) continue; } - if (ei->i_es_lru_nr == 0) + if (ei->i_es_lru_nr == 0 || ei == locked_ei) continue; write_lock(&ei->i_es_lock); @@ -952,6 +958,27 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) list_splice_tail(&skiped, &sbi->s_es_lru); spin_unlock(&sbi->s_es_lru_lock); + if (locked_ei && nr_shrunk == 0) + nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan); + + return nr_shrunk; +} + +static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) +{ + struct ext4_sb_info *sbi = container_of(shrink, + struct ext4_sb_info, s_es_shrinker); + int nr_to_scan = sc->nr_to_scan; + int ret, nr_shrunk; + + ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); + trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); + + if (!nr_to_scan) + return ret; + + nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL); + ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret); return ret; -- GitLab From 8331b9e332a6e72d5285b05f56a7b66b692cb67a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 15 Jul 2013 11:58:55 +0200 Subject: [PATCH 2784/2900] sound: oss/vwsnd: Add missing inclusion of linux/delay.h Reported-by: Fengguang Wu Signed-off-by: Takashi Iwai --- sound/oss/vwsnd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 7e814a5c3677..d8db9023bc55 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -149,6 +149,7 @@ #include #include #include +#include #include -- GitLab From 4b8846062faac4e5c3f08e2e06bbb33c949aa51f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 15 Jul 2013 12:00:24 +0200 Subject: [PATCH 2785/2900] sound: oss/vwsnd: Always define vwsnd_mutex While the conversion of BKL to mutex in commit 645ef9ef, the mutex definition was put in a wrong place inside #ifdef WSND_DEBUG, which leads to the build error. Just move it outside the ifdef. Reported-by: Fengguang Wu Signed-off-by: Takashi Iwai --- sound/oss/vwsnd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index d8db9023bc55..4bbcc0fcd4eb 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -155,12 +155,13 @@ #include "sound_config.h" +static DEFINE_MUTEX(vwsnd_mutex); + /*****************************************************************************/ /* debug stuff */ #ifdef VWSND_DEBUG -static DEFINE_MUTEX(vwsnd_mutex); static int shut_up = 1; /* -- GitLab From 1c01103cb90197900beb534911de558d7a43d0b3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 12 Jul 2013 15:56:02 -0400 Subject: [PATCH 2786/2900] drm/radeon: align VM PTBs (Page Table Blocks) to 32K MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers requirements of all current asics. Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 5 +++++ drivers/gpu/drm/radeon/radeon_gart.c | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 82e8e36064e3..001081757895 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -784,6 +784,11 @@ struct radeon_mec { /* number of entries in page table */ #define RADEON_VM_PTE_COUNT (1 << RADEON_VM_BLOCK_SIZE) +/* PTBs (Page Table Blocks) need to be aligned to 32K */ +#define RADEON_VM_PTB_ALIGN_SIZE 32768 +#define RADEON_VM_PTB_ALIGN_MASK (RADEON_VM_PTB_ALIGN_SIZE - 1) +#define RADEON_VM_PTB_ALIGN(a) (((a) + RADEON_VM_PTB_ALIGN_MASK) & ~RADEON_VM_PTB_ALIGN_MASK) + struct radeon_vm { struct list_head list; struct list_head va; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 5ce190b8bd1f..d9d31a383276 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -466,8 +466,8 @@ int radeon_vm_manager_init(struct radeon_device *rdev) size += rdev->vm_manager.max_pfn * 8; size *= 2; r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, - RADEON_GPU_PAGE_ALIGN(size), - RADEON_GPU_PAGE_SIZE, + RADEON_VM_PTB_ALIGN(size), + RADEON_VM_PTB_ALIGN_SIZE, RADEON_GEM_DOMAIN_VRAM); if (r) { dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", @@ -621,10 +621,10 @@ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) } retry: - pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); + pd_size = RADEON_VM_PTB_ALIGN(radeon_vm_directory_size(rdev)); r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->page_directory, pd_size, - RADEON_GPU_PAGE_SIZE, false); + RADEON_VM_PTB_ALIGN_SIZE, false); if (r == -ENOMEM) { r = radeon_vm_evict(rdev, vm); if (r) @@ -953,8 +953,8 @@ static int radeon_vm_update_pdes(struct radeon_device *rdev, retry: r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->page_tables[pt_idx], - RADEON_VM_PTE_COUNT * 8, - RADEON_GPU_PAGE_SIZE, false); + RADEON_VM_PTB_ALIGN(RADEON_VM_PTE_COUNT * 8), + RADEON_VM_PTB_ALIGN_SIZE, false); if (r == -ENOMEM) { r = radeon_vm_evict(rdev, vm); -- GitLab From 13f69c2c9ce151773b30e0d7df2f1b66cc696f67 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 12 Jul 2013 18:40:40 -0400 Subject: [PATCH 2787/2900] drm/radeon/dpm/sumo: handle boost states properly when forcing a perf level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to properly enable/disable boost states when forcing a performance level. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/sumo_dpm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index ca381028bd7b..c0a850319908 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1851,6 +1851,8 @@ int sumo_dpm_force_performance_level(struct radeon_device *rdev, return 0; if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { + if (pi->enable_boost) + sumo_enable_boost(rdev, rps, false); sumo_power_level_enable(rdev, ps->num_levels - 1, true); sumo_set_forced_level(rdev, ps->num_levels - 1); sumo_set_forced_mode_enabled(rdev); @@ -1861,6 +1863,8 @@ int sumo_dpm_force_performance_level(struct radeon_device *rdev, sumo_set_forced_mode_enabled(rdev); sumo_set_forced_mode(rdev, false); } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { + if (pi->enable_boost) + sumo_enable_boost(rdev, rps, false); sumo_power_level_enable(rdev, 0, true); sumo_set_forced_level(rdev, 0); sumo_set_forced_mode_enabled(rdev); @@ -1874,6 +1878,8 @@ int sumo_dpm_force_performance_level(struct radeon_device *rdev, for (i = 0; i < ps->num_levels; i++) { sumo_power_level_enable(rdev, i, true); } + if (pi->enable_boost) + sumo_enable_boost(rdev, rps, true); } rdev->pm.dpm.forced_level = level; -- GitLab From a01c34f72e7cd2624570818f579b5ab464f93de2 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Sun, 14 Jul 2013 14:03:27 +0300 Subject: [PATCH 2788/2900] radeon kms: do not flush uninitialized hotplug work Fix a warning from lockdep caused by calling flush_work() for uninitialized hotplug work. Initialize hotplug_work, audio_work and reset_work upon successful radeon_irq_kms_init() completion and thus perform hotplug flush_work only when rdev->irq.installed is true. [ 4.790019] [drm] Loading CEDAR Microcode [ 4.790943] r600_cp: Failed to load firmware "radeon/CEDAR_smc.bin" [ 4.791152] [drm:evergreen_startup] *ERROR* Failed to load firmware! [ 4.791330] radeon 0000:01:00.0: disabling GPU acceleration [ 4.792633] INFO: trying to register non-static key. [ 4.792792] the code is fine but needs lockdep annotation. [ 4.792953] turning off the locking correctness validator. [ 4.793114] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 3.11.0-rc0-dbg-10676-gfe56456-dirty #1816 [ 4.793314] Hardware name: Acer Aspire 5741G /Aspire 5741G , BIOS V1.20 02/08/2011 [ 4.793507] ffffffff821fd810 ffff8801530b9a18 ffffffff8160434e 0000000000000002 [ 4.794155] ffff8801530b9ad8 ffffffff810b8404 ffff8801530b0798 ffff8801530b0000 [ 4.794789] ffff8801530b9b00 0000000000000046 00000000000004c0 ffffffff00000000 [ 4.795418] Call Trace: [ 4.795573] [] dump_stack+0x4e/0x82 [ 4.795731] [] __lock_acquire+0x1a64/0x1d30 [ 4.795893] [] ? dev_vprintk_emit+0x50/0x60 [ 4.796034] [] lock_acquire+0xa4/0x200 [ 4.796216] [] ? flush_work+0x5/0x280 [ 4.796375] [] flush_work+0x3d/0x280 [ 4.796520] [] ? flush_work+0x5/0x280 [ 4.796682] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 4.796862] [] ? delay_tsc+0x95/0xf0 [ 4.797024] [] radeon_irq_kms_fini+0x2b/0x70 [ 4.797186] [] evergreen_init+0x2a9/0x2e0 [ 4.797347] [] radeon_device_init+0x5ef/0x700 [ 4.797511] [] ? pci_find_capability+0x47/0x50 [ 4.797672] [] radeon_driver_load_kms+0x8d/0x150 [ 4.797843] [] drm_get_pci_dev+0x166/0x280 [ 4.798007] [] ? kfree+0xf5/0x2e0 [ 4.798168] [] ? radeon_pci_probe+0x98/0xd0 [ 4.798329] [] radeon_pci_probe+0xaa/0xd0 [ 4.798489] [] pci_device_probe+0x84/0xe0 [ 4.798644] [] driver_probe_device+0x76/0x240 [ 4.798805] [] __driver_attach+0x93/0xa0 [ 4.798948] [] ? __device_attach+0x40/0x40 [ 4.799126] [] bus_for_each_dev+0x6b/0xb0 [ 4.799272] [] driver_attach+0x1e/0x20 [ 4.799434] [] bus_add_driver+0x1f0/0x280 [ 4.799596] [] driver_register+0x74/0x150 [ 4.799758] [] __pci_register_driver+0x5d/0x60 [ 4.799936] [] ? ttm_init+0x67/0x67 [ 4.800081] [] drm_pci_init+0x115/0x130 [ 4.800243] [] ? ttm_init+0x67/0x67 [ 4.800405] [] radeon_init+0x9c/0xba [ 4.800586] [] do_one_initcall+0xfa/0x150 [ 4.800746] [] ? parse_args+0x120/0x330 [ 4.800909] [] kernel_init_freeable+0x111/0x191 [ 4.801052] [] ? do_early_param+0x88/0x88 [ 4.801233] [] ? rest_init+0x140/0x140 [ 4.801393] [] kernel_init+0xe/0x180 [ 4.801556] [] ret_from_fork+0x7c/0xb0 [ 4.801718] [] ? rest_init+0x140/0x140 Signed-off-by: Sergey Senozhatsky Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_irq_kms.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index bcdefd1dcd43..081886b0642d 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -260,10 +260,6 @@ int radeon_irq_kms_init(struct radeon_device *rdev) { int r = 0; - INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); - INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); - INIT_WORK(&rdev->reset_work, radeon_irq_reset_work_func); - spin_lock_init(&rdev->irq.lock); r = drm_vblank_init(rdev->ddev, rdev->num_crtc); if (r) { @@ -285,6 +281,11 @@ int radeon_irq_kms_init(struct radeon_device *rdev) rdev->irq.installed = false; return r; } + + INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); + INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); + INIT_WORK(&rdev->reset_work, radeon_irq_reset_work_func); + DRM_INFO("radeon: irq initialized.\n"); return 0; } @@ -304,8 +305,8 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) rdev->irq.installed = false; if (rdev->msi_enabled) pci_disable_msi(rdev->pdev); + flush_work(&rdev->hotplug_work); } - flush_work(&rdev->hotplug_work); } /** -- GitLab From 1540c5d3cbf7670eb68a0d02611ec73e5604a91a Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sun, 14 Jul 2013 22:57:50 -0400 Subject: [PATCH 2789/2900] SUNRPC: Fix another issue with rpc_client_register() Fix the error pathway if rpcauth_create() fails. Signed-off-by: Trond Myklebust --- net/sunrpc/clnt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 9963584605c0..74f6a704e374 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -309,6 +309,7 @@ static int rpc_client_register(const struct rpc_create_args *args, return 0; err_auth: pipefs_sb = rpc_get_sb_net(net); + rpc_unregister_client(clnt); __rpc_clnt_remove_pipedir(clnt); out: if (pipefs_sb) -- GitLab From b2781e1021525649c0b33fffd005ef219da33926 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Jul 2013 09:39:03 +0300 Subject: [PATCH 2790/2900] svcrdma: underflow issue in decode_write_list() My static checker marks everything from ntohl() as untrusted and it complains we could have an underflow problem doing: return (u32 *)&ary->wc_array[nchunks]; Also on 32 bit systems the upper bound check could overflow. Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_marshal.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c index 8d2edddf48cf..65b146297f5a 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c +++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c @@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, */ static u32 *decode_write_list(u32 *va, u32 *vaend) { + unsigned long start, end; int nchunks; struct rpcrdma_write_array *ary = @@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) return NULL; } nchunks = ntohl(ary->wc_nchunks); - if (((unsigned long)&ary->wc_array[0] + - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > - (unsigned long)vaend) { + + start = (unsigned long)&ary->wc_array[0]; + end = (unsigned long)vaend; + if (nchunks < 0 || + nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || + (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", ary, nchunks, vaend); return NULL; @@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) static u32 *decode_reply_array(u32 *va, u32 *vaend) { + unsigned long start, end; int nchunks; struct rpcrdma_write_array *ary = (struct rpcrdma_write_array *)va; @@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) return NULL; } nchunks = ntohl(ary->wc_nchunks); - if (((unsigned long)&ary->wc_array[0] + - (sizeof(struct rpcrdma_write_chunk) * nchunks)) > - (unsigned long)vaend) { + + start = (unsigned long)&ary->wc_array[0]; + end = (unsigned long)vaend; + if (nchunks < 0 || + nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || + (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", ary, nchunks, vaend); return NULL; -- GitLab From 60478295d6876619f8f47f6d1a5c25eaade69ee3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:55:57 +0200 Subject: [PATCH 2791/2900] ALSA: asihpi: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- sound/pci/asihpi/asihpi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 185d54a5cb1a..dc632cdc3870 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -769,7 +769,10 @@ static void snd_card_asihpi_timer_function(unsigned long data) s->number); ds->drained_count++; if (ds->drained_count > 20) { + unsigned long flags; + snd_pcm_stream_lock_irqsave(s, flags); snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(s, flags); continue; } } else { -- GitLab From cc7282b8d5abbd48c81d1465925d464d9e3eaa8f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:56:56 +0200 Subject: [PATCH 2792/2900] ALSA: atiixp: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- sound/pci/atiixp.c | 2 ++ sound/pci/atiixp_modem.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index fe4c61bdb8ba..f6dec3ea371f 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -689,7 +689,9 @@ static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma) if (! dma->substream || ! dma->running) return; snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type); + snd_pcm_stream_lock(dma->substream); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(dma->substream); } /* diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index cf29b9a1d65d..289563ecb6dd 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -638,7 +638,9 @@ static void snd_atiixp_xrun_dma(struct atiixp_modem *chip, if (! dma->substream || ! dma->running) return; snd_printdd("atiixp-modem: XRUN detected (DMA %d)\n", dma->ops->type); + snd_pcm_stream_lock(dma->substream); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(dma->substream); } /* -- GitLab From 5b9ab3f7324a1b94a5a5a76d44cf92dfeb3b5e80 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:57:55 +0200 Subject: [PATCH 2793/2900] ALSA: 6fire: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- sound/usb/6fire/pcm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index c5b9cac37dc4..2aa4e13063a8 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -639,17 +639,25 @@ int usb6fire_pcm_init(struct sfire_chip *chip) void usb6fire_pcm_abort(struct sfire_chip *chip) { struct pcm_runtime *rt = chip->pcm; + unsigned long flags; int i; if (rt) { rt->panic = true; - if (rt->playback.instance) + if (rt->playback.instance) { + snd_pcm_stream_lock_irqsave(rt->playback.instance, flags); snd_pcm_stop(rt->playback.instance, SNDRV_PCM_STATE_XRUN); - if (rt->capture.instance) + snd_pcm_stream_unlock_irqrestore(rt->playback.instance, flags); + } + + if (rt->capture.instance) { + snd_pcm_stream_lock_irqsave(rt->capture.instance, flags); snd_pcm_stop(rt->capture.instance, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(rt->capture.instance, flags); + } for (i = 0; i < PCM_N_URBS; i++) { usb_poison_urb(&rt->in_urbs[i].instance); -- GitLab From 76828c882630ced08b5ddce22cc0095b05de9bc5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 15 Jul 2013 12:27:47 -0400 Subject: [PATCH 2794/2900] ext4: yield during large unlinks During large unlink operations on files with extents, we can use a lot of CPU time. This adds a cond_resched() call when starting to examine the next level of a multi-level extent tree. Multi-level extent trees are rare in the first place, and this should rarely be executed. Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 593091537e76..cfdc51e30257 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2835,6 +2835,9 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, err = -EIO; break; } + /* Yield here to deal with large extent trees. + * Should be a no-op if we did IO above. */ + cond_resched(); if (WARN_ON(i + 1 > depth)) { err = -EIO; break; -- GitLab From 9538aa46c2427d6782aa10036c4da4c541605e0e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:58:25 +0200 Subject: [PATCH 2795/2900] ALSA: ua101: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Acked-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/usb/misc/ua101.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 8b5d2c564e04..509315937f25 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -613,14 +613,24 @@ static int start_usb_playback(struct ua101 *ua) static void abort_alsa_capture(struct ua101 *ua) { - if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) + unsigned long flags; + + if (test_bit(ALSA_CAPTURE_RUNNING, &ua->states)) { + snd_pcm_stream_lock_irqsave(ua->capture.substream, flags); snd_pcm_stop(ua->capture.substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(ua->capture.substream, flags); + } } static void abort_alsa_playback(struct ua101 *ua) { - if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) + unsigned long flags; + + if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) { + snd_pcm_stream_lock_irqsave(ua->playback.substream, flags); snd_pcm_stop(ua->playback.substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(ua->playback.substream, flags); + } } static int set_stream_hw(struct ua101 *ua, struct snd_pcm_substream *substream, -- GitLab From 5be1efb4c2ed79c3d7c0cbcbecae768377666e84 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:58:47 +0200 Subject: [PATCH 2796/2900] ALSA: usx2y: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usbusx2yaudio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 4967fe9c938d..63fb5219f0f8 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -273,7 +273,11 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) struct snd_usX2Y_substream *subs = usX2Y->subs[s]; if (subs) { if (atomic_read(&subs->state) >= state_PRERUNNING) { + unsigned long flags; + + snd_pcm_stream_lock_irqsave(subs->pcm_substream, flags); snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock_irqrestore(subs->pcm_substream, flags); } for (u = 0; u < NRURBS; u++) { struct urb *urb = subs->urb[u]; -- GitLab From 46f6c1aaf790be9ea3c8ddfc8f235a5f677d08e2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 17:59:33 +0200 Subject: [PATCH 2797/2900] ALSA: pxa2xx: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/arm/pxa2xx-pcm-lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c index 76e0d5695075..823359ed95e1 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/arm/pxa2xx-pcm-lib.c @@ -166,7 +166,9 @@ void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) } else { printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", rtd->params->name, dma_ch, dcsr); + snd_pcm_stream_lock(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(substream); } } EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); -- GitLab From 571185717f8d7f2a088a7ac38d94a9ad5fd9da5c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 18:00:01 +0200 Subject: [PATCH 2798/2900] ASoC: atmel: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/soc/atmel/atmel-pcm-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/atmel/atmel-pcm-dma.c b/sound/soc/atmel/atmel-pcm-dma.c index 1d38fd0bc4e2..d12826526798 100644 --- a/sound/soc/atmel/atmel-pcm-dma.c +++ b/sound/soc/atmel/atmel-pcm-dma.c @@ -81,7 +81,9 @@ static void atmel_pcm_dma_irq(u32 ssc_sr, /* stop RX and capture: will be enabled again at restart */ ssc_writex(prtd->ssc->regs, SSC_CR, prtd->mask->ssc_disable); + snd_pcm_stream_lock(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(substream); /* now drain RHR and read status to remove xrun condition */ ssc_readx(prtd->ssc->regs, SSC_RHR); -- GitLab From 61be2b9a18ec70f3cbe3deef7a5f77869c71b5ae Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 18:00:25 +0200 Subject: [PATCH 2799/2900] ASoC: s6000: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/soc/s6000/s6000-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 1358c7de2521..d0740a762963 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -128,7 +128,9 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) substream->runtime && snd_pcm_running(substream)) { dev_dbg(pcm->dev, "xrun\n"); + snd_pcm_stream_lock(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(substream); ret = IRQ_HANDLED; } -- GitLab From e6355ad7b1c6f70e2f48ae159f5658b441ccff95 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 18:00:59 +0200 Subject: [PATCH 2800/2900] [media] saa7134: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- drivers/media/pci/saa7134/saa7134-alsa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index 10460fd3ce39..dbcdfbf8aed0 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -172,7 +172,9 @@ static void saa7134_irq_alsa_done(struct saa7134_dev *dev, dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count, dev->dmasound.bufsize, dev->dmasound.blocks); spin_unlock(&dev->slock); + snd_pcm_stream_lock(dev->dmasound.substream); snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN); + snd_pcm_stream_unlock(dev->dmasound.substream); return; } -- GitLab From 86f0b5b86d142b9323432fef078a6cf0fb5dda74 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 11 Jul 2013 18:02:38 +0200 Subject: [PATCH 2801/2900] staging: line6: Fix unlocked snd_pcm_stop() call snd_pcm_stop() must be called in the PCM substream lock context. Cc: Signed-off-by: Takashi Iwai --- drivers/staging/line6/pcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c index 4795f1284906..0dd08ef51398 100644 --- a/drivers/staging/line6/pcm.c +++ b/drivers/staging/line6/pcm.c @@ -392,8 +392,11 @@ static int snd_line6_pcm_free(struct snd_device *device) */ static void pcm_disconnect_substream(struct snd_pcm_substream *substream) { - if (substream->runtime && snd_pcm_running(substream)) + if (substream->runtime && snd_pcm_running(substream)) { + snd_pcm_stream_lock_irq(substream); snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); + snd_pcm_stream_unlock_irq(substream); + } } /* -- GitLab From 5ff560fd48d5b3d82fa0c3aff625c9da1a301911 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 12 Jul 2013 16:48:12 -0700 Subject: [PATCH 2802/2900] x86, suspend: Handle CPUs which fail to #GP on RDMSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are CPUs which have errata causing RDMSR of a nonexistent MSR to not fault. We would then try to WRMSR to restore the value of that MSR, causing a crash. Specifically, some Pentium M variants would have this problem trying to save and restore the non-existent EFER, causing a crash on resume. Work around this by making sure we can write back the result at suspend time. Huge thanks to Christian Sünkenberg for finding the offending erratum that finally deciphered the mystery. Reported-and-tested-by: Johan Heinrich Debugged-by: Christian Sünkenberg Acked-by: Rafael J. Wysocki Link: http://lkml.kernel.org/r/51DDC972.3010005@student.kit.edu Cc: # v3.7+ --- arch/x86/kernel/acpi/sleep.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 2a34aaf3c8f1..33120100ff5e 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -48,9 +48,20 @@ int x86_acpi_suspend_lowlevel(void) #ifndef CONFIG_64BIT native_store_gdt((struct desc_ptr *)&header->pmode_gdt); + /* + * We have to check that we can write back the value, and not + * just read it. At least on 90 nm Pentium M (Family 6, Model + * 13), reading an invalid MSR is not guaranteed to trap, see + * Erratum X4 in "Intel Pentium M Processor on 90 nm Process + * with 2-MB L2 Cache and Intel® Processor A100 and A110 on 90 + * nm process with 512-KB L2 Cache Specification Update". + */ if (!rdmsr_safe(MSR_EFER, &header->pmode_efer_low, - &header->pmode_efer_high)) + &header->pmode_efer_high) && + !wrmsr_safe(MSR_EFER, + header->pmode_efer_low, + header->pmode_efer_high)) header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER); #endif /* !CONFIG_64BIT */ @@ -61,7 +72,10 @@ int x86_acpi_suspend_lowlevel(void) } if (!rdmsr_safe(MSR_IA32_MISC_ENABLE, &header->pmode_misc_en_low, - &header->pmode_misc_en_high)) + &header->pmode_misc_en_high) && + !wrmsr_safe(MSR_IA32_MISC_ENABLE, + header->pmode_misc_en_low, + header->pmode_misc_en_high)) header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE); header->realmode_flags = acpi_realmode_flags; -- GitLab From d1ce3d5496f2a7c90dd00a9133572f931d2acdcc Mon Sep 17 00:00:00 2001 From: Sylvain 'ythier' Hitier Date: Fri, 12 Jul 2013 18:25:54 +0200 Subject: [PATCH 2803/2900] uvesafb: Really allow mtrr being 0, as documented and warn()ed Fixup for commit "uvesafb: Clean up MTRR code" (63e28a7a5ffce59b645ca9cbcc01e1e8be56bd75) Signed-off-by: Sylvain "ythier" Hitier Acked-by: Andy Lutomirski Also-spotted-by: Torsten Kaiser Signed-off-by: Dave Airlie --- drivers/video/uvesafb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index b963ea12d175..7aec6f39fdd5 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -1891,7 +1891,7 @@ static int uvesafb_setup(char *options) } } - if (mtrr != 3 && mtrr != 1) + if (mtrr != 3 && mtrr != 0) pr_warn("uvesafb: mtrr should be set to 0 or 3; %d is unsupported", mtrr); return 0; -- GitLab From d52392b1a80458c0510810789c7db4a39b88022a Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Fri, 12 Jul 2013 11:01:37 -0700 Subject: [PATCH 2804/2900] ALSA: hda - Add new GPU codec ID to snd-hda Vendor ID 0x10de0060 is used by a yet-to-be-named GPU chip. Reviewed-by: Andy Ritger Signed-off-by: Aaron Plattner Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 540bdef2f904..030ca8652a1c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2622,6 +2622,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = { { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, +{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_generic_hdmi }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, @@ -2674,6 +2675,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0042"); MODULE_ALIAS("snd-hda-codec-id:10de0043"); MODULE_ALIAS("snd-hda-codec-id:10de0044"); MODULE_ALIAS("snd-hda-codec-id:10de0051"); +MODULE_ALIAS("snd-hda-codec-id:10de0060"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); MODULE_ALIAS("snd-hda-codec-id:11069f80"); -- GitLab From 67dbf54a3b03881c7b683801fa49ca1f2c4c3bcf Mon Sep 17 00:00:00 2001 From: Jacek Anaszewski Date: Tue, 2 Jul 2013 11:13:00 +0100 Subject: [PATCH 2805/2900] iio: lps331ap: Fix wrong in_pressure_scale output value This patch fixes improper in_pressure_scale output that is returned by the lps331ap barometer sensor driver. According to the documentation the pressure after applying the scale has to be expressed in kilopascal units. With erroneous implementation the scale value larger by two orders of magnitude is returned - 2441410 instead of 24414. Signed-off-by: Jacek Anaszewski Signed-off-by: Kyungmin Park Acked-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/st_pressure_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index 9c343b40665e..3ffbc56917b4 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -28,7 +28,9 @@ #include #include "st_pressure.h" -#define ST_PRESS_MBAR_TO_KPASCAL(x) (x * 10) +#define ST_PRESS_LSB_PER_MBAR 4096UL +#define ST_PRESS_KPASCAL_NANO_SCALE (100000000UL / \ + ST_PRESS_LSB_PER_MBAR) #define ST_PRESS_NUMBER_DATA_CHANNELS 1 /* DEFAULT VALUE FOR SENSORS */ @@ -51,8 +53,8 @@ #define ST_PRESS_1_FS_ADDR 0x23 #define ST_PRESS_1_FS_MASK 0x30 #define ST_PRESS_1_FS_AVL_1260_VAL 0x00 -#define ST_PRESS_1_FS_AVL_1260_GAIN ST_PRESS_MBAR_TO_KPASCAL(244141) #define ST_PRESS_1_FS_AVL_TEMP_GAIN 2083000 +#define ST_PRESS_1_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE #define ST_PRESS_1_BDU_ADDR 0x20 #define ST_PRESS_1_BDU_MASK 0x04 #define ST_PRESS_1_DRDY_IRQ_ADDR 0x22 -- GitLab From 64597f9dae1850e0360ae2e9b5485d4b5d1fdf4c Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 2 Jul 2013 22:58:26 +0200 Subject: [PATCH 2806/2900] s390/ptrace: PTRACE_TE_ABORT_RAND The patch implements a s390 specific ptrace request PTRACE_TE_ABORT_RAND to modify the randomness of spontaneous aborts of memory transactions of the transaction execution facility. The data argument of the ptrace request is used to specify the levels of randomness, 0 for normal operation, 1 to abort every transaction at a random instruction, and 2 to abort a random transaction at a random instruction. The default is 0 for normal operation. Acked-by: Heiko Carstens Signed-off-by: Michael Mueller Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/processor.h | 10 +++++- arch/s390/include/asm/switch_to.h | 4 +-- arch/s390/include/uapi/asm/ptrace.h | 1 + arch/s390/kernel/ptrace.c | 50 ++++++++++++++++++++++------- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 6b499870662f..b0e6435b2f02 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -91,7 +91,15 @@ struct thread_struct { #endif }; -#define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */ +/* Flag to disable transactions. */ +#define PER_FLAG_NO_TE 1UL +/* Flag to enable random transaction aborts. */ +#define PER_FLAG_TE_ABORT_RAND 2UL +/* Flag to specify random transaction abort mode: + * - abort each transaction at a random instruction before TEND if set. + * - abort random transactions at a random instruction if cleared. + */ +#define PER_FLAG_TE_ABORT_RAND_TEND 4UL typedef struct thread_struct thread_struct; diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h index f3a9e0f92704..80b6f11263c4 100644 --- a/arch/s390/include/asm/switch_to.h +++ b/arch/s390/include/asm/switch_to.h @@ -10,7 +10,7 @@ #include extern struct task_struct *__switch_to(void *, void *); -extern void update_per_regs(struct task_struct *task); +extern void update_cr_regs(struct task_struct *task); static inline void save_fp_regs(s390_fp_regs *fpregs) { @@ -86,7 +86,7 @@ static inline void restore_access_regs(unsigned int *acrs) restore_fp_regs(&next->thread.fp_regs); \ restore_access_regs(&next->thread.acrs[0]); \ restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ - update_per_regs(next); \ + update_cr_regs(next); \ } \ prev = __switch_to(prev,next); \ } while (0) diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h index 3aa9f1ec5b29..7a84619e315e 100644 --- a/arch/s390/include/uapi/asm/ptrace.h +++ b/arch/s390/include/uapi/asm/ptrace.h @@ -400,6 +400,7 @@ typedef struct #define PTRACE_POKE_SYSTEM_CALL 0x5008 #define PTRACE_ENABLE_TE 0x5009 #define PTRACE_DISABLE_TE 0x5010 +#define PTRACE_TE_ABORT_RAND 0x5011 /* * PT_PROT definition is loosely based on hppa bsd definition in diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index a314c57f4e94..e9fadb04e3c6 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -47,7 +47,7 @@ enum s390_regset { REGSET_GENERAL_EXTENDED, }; -void update_per_regs(struct task_struct *task) +void update_cr_regs(struct task_struct *task) { struct pt_regs *regs = task_pt_regs(task); struct thread_struct *thread = &task->thread; @@ -56,17 +56,25 @@ void update_per_regs(struct task_struct *task) #ifdef CONFIG_64BIT /* Take care of the enable/disable of transactional execution. */ if (MACHINE_HAS_TE) { - unsigned long cr0, cr0_new; + unsigned long cr[3], cr_new[3]; - __ctl_store(cr0, 0, 0); - /* set or clear transaction execution bits 8 and 9. */ + __ctl_store(cr, 0, 2); + cr_new[1] = cr[1]; + /* Set or clear transaction execution TXC/PIFO bits 8 and 9. */ if (task->thread.per_flags & PER_FLAG_NO_TE) - cr0_new = cr0 & ~(3UL << 54); + cr_new[0] = cr[0] & ~(3UL << 54); else - cr0_new = cr0 | (3UL << 54); - /* Only load control register 0 if necessary. */ - if (cr0 != cr0_new) - __ctl_load(cr0_new, 0, 0); + cr_new[0] = cr[0] | (3UL << 54); + /* Set or clear transaction execution TDC bits 62 and 63. */ + cr_new[2] = cr[2] & ~3UL; + if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) { + if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND) + cr_new[2] |= 1UL; + else + cr_new[2] |= 2UL; + } + if (memcmp(&cr_new, &cr, sizeof(cr))) + __ctl_load(cr_new, 0, 2); } #endif /* Copy user specified PER registers */ @@ -100,14 +108,14 @@ void user_enable_single_step(struct task_struct *task) { set_tsk_thread_flag(task, TIF_SINGLE_STEP); if (task == current) - update_per_regs(task); + update_cr_regs(task); } void user_disable_single_step(struct task_struct *task) { clear_tsk_thread_flag(task, TIF_SINGLE_STEP); if (task == current) - update_per_regs(task); + update_cr_regs(task); } /* @@ -447,6 +455,26 @@ long arch_ptrace(struct task_struct *child, long request, if (!MACHINE_HAS_TE) return -EIO; child->thread.per_flags |= PER_FLAG_NO_TE; + child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND; + return 0; + case PTRACE_TE_ABORT_RAND: + if (!MACHINE_HAS_TE || (child->thread.per_flags & PER_FLAG_NO_TE)) + return -EIO; + switch (data) { + case 0UL: + child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND; + break; + case 1UL: + child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND; + child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND_TEND; + break; + case 2UL: + child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND; + child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND_TEND; + break; + default: + return -EINVAL; + } return 0; default: /* Removing high order bit from addr (only for 31 bit). */ -- GitLab From dae7fd42961e9ae9386f527b6d0e14f6e3da2317 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Fri, 5 Jul 2013 09:22:11 +0200 Subject: [PATCH 2807/2900] s390/qdio: remove unused variable Fix a "set but not used" warning found via make W=1. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index fb1c1e0483ed..8ed52aa49122 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1497,7 +1497,7 @@ static inline int buf_in_between(int bufnr, int start, int count) static int handle_inbound(struct qdio_q *q, unsigned int callflags, int bufnr, int count) { - int used, diff; + int diff; qperf_inc(q, inbound_call); @@ -1530,7 +1530,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, set: count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); - used = atomic_add_return(count, &q->nr_buf_used) - count; + atomic_add(count, &q->nr_buf_used); if (need_siga_in(q)) return qdio_siga_input(q); -- GitLab From 63b999685cb372e24eb73f255cd73547026370fd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 16 Jul 2013 10:28:47 -0400 Subject: [PATCH 2808/2900] ext4: call ext4_es_lru_add() after handling cache miss If there are no items in the extent status tree, ext4_es_lru_add() is a no-op. So it is not sufficient to call ext4_es_lru_add() before we try to lookup an entry in the extent status tree. We also need to call it at the end of ext4_ext_map_blocks(), after items have been added to the extent status tree. This could lead to inodes with that have extent status trees but which are not in the LRU list, which means they won't get considered for eviction by the es_shrinker. Signed-off-by: "Theodore Ts'o" Cc: Zheng Liu Cc: stable@vger.kernel.org --- fs/ext4/extents.c | 5 +++-- fs/ext4/inode.c | 7 ++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index cfdc51e30257..a61873808f76 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4385,8 +4385,9 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, } out3: - trace_ext4_ext_map_blocks_exit(inode, flags, map, err ? err : allocated); - + trace_ext4_ext_map_blocks_exit(inode, flags, map, + err ? err : allocated); + ext4_es_lru_add(inode); return err ? err : allocated; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 98b9bff92a8a..ba33c67d6e48 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -514,10 +514,9 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, "logical block %lu\n", inode->i_ino, flags, map->m_len, (unsigned long) map->m_lblk); - ext4_es_lru_add(inode); - /* Lookup extent status tree firstly */ if (ext4_es_lookup_extent(inode, map->m_lblk, &es)) { + ext4_es_lru_add(inode); if (ext4_es_is_written(&es) || ext4_es_is_unwritten(&es)) { map->m_pblk = ext4_es_pblock(&es) + map->m_lblk - es.es_lblk; @@ -1529,11 +1528,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, "logical block %lu\n", inode->i_ino, map->m_len, (unsigned long) map->m_lblk); - ext4_es_lru_add(inode); - /* Lookup extent status tree firstly */ if (ext4_es_lookup_extent(inode, iblock, &es)) { - + ext4_es_lru_add(inode); if (ext4_es_is_hole(&es)) { retval = 0; down_read((&EXT4_I(inode)->i_data_sem)); -- GitLab From 16fc5bc4c76b9ac335c2b39943f29c5d047a822d Mon Sep 17 00:00:00 2001 From: Steven Miao Date: Tue, 16 Jul 2013 13:25:21 +0800 Subject: [PATCH 2809/2900] smp: blackfin: fix check error, using atomic_ops to handle atomic_t type Signed-off-by: Geert Uytterhoeven Signed-off-by: Steven Miao Signed-off-by: Linus Torvalds --- arch/blackfin/mach-common/smp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 961d8392e5e3..b5f9ed7d4856 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -147,7 +147,7 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) platform_clear_ipi(cpu, IRQ_SUPPLE_1); bfin_ipi_data = &__get_cpu_var(bfin_ipi); - while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) { + while ((pending = atomic_xchg(&bfin_ipi_data->bits, 0)) != 0) { msg = 0; do { msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1); @@ -182,8 +182,8 @@ static void bfin_ipi_init(void) struct ipi_data *bfin_ipi_data; for_each_possible_cpu(cpu) { bfin_ipi_data = &per_cpu(bfin_ipi, cpu); - bfin_ipi_data->bits = 0; - bfin_ipi_data->count = 0; + atomic_set(&bfin_ipi_data->bits, 0); + atomic_set(&bfin_ipi_data->count, 0); } } -- GitLab From b9b3259746d77f4fcb786e2a43c25bcc40773755 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:51 -0700 Subject: [PATCH 2810/2900] sysfs.h: add __ATTR_RW() macro A number of parts of the kernel created their own version of this, might as well have the sysfs core provide it instead. Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 2 ++ kernel/events/core.c | 2 -- mm/backing-dev.c | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index e2cee22f578a..9cd20c8404e5 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -79,6 +79,8 @@ struct attribute_group { .show = _name##_show, \ } +#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) + #define __ATTR_NULL { .attr = { .name = NULL } } #ifdef CONFIG_DEBUG_LOCK_ALLOC diff --git a/kernel/events/core.c b/kernel/events/core.c index eba8fb5834ae..dd9878029d1f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6234,8 +6234,6 @@ perf_event_mux_interval_ms_store(struct device *dev, return count; } -#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) - static struct device_attribute pmu_dev_attrs[] = { __ATTR_RO(type), __ATTR_RW(perf_event_mux_interval_ms), diff --git a/mm/backing-dev.c b/mm/backing-dev.c index d014ee5fcbbd..e04454cdb33f 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -232,8 +232,6 @@ static ssize_t stable_pages_required_show(struct device *dev, bdi_cap_stable_pages_required(bdi) ? 1 : 0); } -#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) - static struct device_attribute bdi_dev_attrs[] = { __ATTR_RW(read_ahead_kb), __ATTR_RW(min_ratio), -- GitLab From f2f37f58b1b933b06d6d84e80a31a1b500fb0db2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:52 -0700 Subject: [PATCH 2811/2900] sysfs.h: add ATTRIBUTE_GROUPS() macro To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups. Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 9cd20c8404e5..f62ff01e5f59 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -94,6 +94,15 @@ struct attribute_group { #define __ATTR_IGNORE_LOCKDEP __ATTR #endif +#define ATTRIBUTE_GROUPS(name) \ +static const struct attribute_group name##_group = { \ + .attrs = name##_attrs, \ +}; \ +static const struct attribute_group *name##_groups[] = { \ + &name##_group, \ + NULL, \ +} + #define attr_name(_attr) (_attr).attr.name struct file; -- GitLab From e4b63603c2a1e2c4db3de11b0f2b17360a7695bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:53 -0700 Subject: [PATCH 2812/2900] sysfs.h: add BIN_ATTR macro This makes it easier to create static binary attributes, which is needed in a number of drivers, instead of "open coding" them. Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index f62ff01e5f59..d50a96b9bb6d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -132,6 +132,15 @@ struct bin_attribute { */ #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr) +/* macro to create static binary attributes easier */ +#define BIN_ATTR(_name, _mode, _read, _write, _size) \ +struct bin_attribute bin_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .read = _read, \ + .write = _write, \ + .size = _size, \ +} + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); -- GitLab From ced321bf9151535f85779b0004c93529f860b2a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:54 -0700 Subject: [PATCH 2813/2900] driver core: device.h: add RW and RO attribute macros Make it easier to create attributes without having to always audit the mode settings. Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index bcf8c0d4cd98..f207a8f49f80 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -47,7 +47,11 @@ struct bus_attribute { }; #define BUS_ATTR(_name, _mode, _show, _store) \ -struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) + struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store) +#define BUS_ATTR_RW(_name) \ + struct bus_attribute bus_attr_##_name = __ATTR_RW(_name) +#define BUS_ATTR_RO(_name) \ + struct bus_attribute bus_attr_##_name = __ATTR_RO(_name) extern int __must_check bus_create_file(struct bus_type *, struct bus_attribute *); @@ -261,9 +265,12 @@ struct driver_attribute { size_t count); }; -#define DRIVER_ATTR(_name, _mode, _show, _store) \ -struct driver_attribute driver_attr_##_name = \ - __ATTR(_name, _mode, _show, _store) +#define DRIVER_ATTR(_name, _mode, _show, _store) \ + struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store) +#define DRIVER_ATTR_RW(_name) \ + struct driver_attribute driver_attr_##_name = __ATTR_RW(_name) +#define DRIVER_ATTR_RO(_name) \ + struct driver_attribute driver_attr_##_name = __ATTR_RO(_name) extern int __must_check driver_create_file(struct device_driver *driver, const struct driver_attribute *attr); @@ -414,8 +421,12 @@ struct class_attribute { const struct class_attribute *attr); }; -#define CLASS_ATTR(_name, _mode, _show, _store) \ -struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store) +#define CLASS_ATTR(_name, _mode, _show, _store) \ + struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store) +#define CLASS_ATTR_RW(_name) \ + struct class_attribute class_attr_##_name = __ATTR_RW(_name) +#define CLASS_ATTR_RO(_name) \ + struct class_attribute class_attr_##_name = __ATTR_RO(_name) extern int __must_check class_create_file(struct class *class, const struct class_attribute *attr); @@ -423,7 +434,6 @@ extern void class_remove_file(struct class *class, const struct class_attribute *attr); /* Simple class attribute that is just a static string */ - struct class_attribute_string { struct class_attribute attr; char *str; @@ -512,6 +522,10 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, #define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) +#define DEVICE_ATTR_RW(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RW(_name) +#define DEVICE_ATTR_RO(_name) \ + struct device_attribute dev_attr_##_name = __ATTR_RO(_name) #define DEVICE_ULONG_ATTR(_name, _mode, _var) \ struct dev_ext_attribute dev_attr_##_name = \ { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) } -- GitLab From 6ab9cea16075ea707022753395f340b67f64304c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:55 -0700 Subject: [PATCH 2814/2900] sysfs: add support for binary attributes in groups groups should be able to support binary attributes, just like it supports "normal" attributes. This lets us only handle one type of structure, groups, throughout the driver core and subsystems, making binary attributes a "full fledged" part of the driver model, and not something just "tacked on". Reported-by: Oliver Schinagl Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/group.c | 66 ++++++++++++++++++++++++++++++------------- include/linux/sysfs.h | 4 +-- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index aec3d5c98c94..e5719c6095c3 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -20,38 +20,64 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, const struct attribute_group *grp) { struct attribute *const* attr; - int i; + struct bin_attribute *const* bin_attr; - for (i = 0, attr = grp->attrs; *attr; i++, attr++) - sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); + if (grp->attrs) + for (attr = grp->attrs; *attr; attr++) + sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); + if (grp->bin_attrs) + for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) + sysfs_remove_bin_file(kobj, *bin_attr); } static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, const struct attribute_group *grp, int update) { struct attribute *const* attr; + struct bin_attribute *const* bin_attr; int error = 0, i; - for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { - umode_t mode = 0; + if (grp->attrs) { + for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { + umode_t mode = 0; + + /* + * In update mode, we're changing the permissions or + * visibility. Do this by first removing then + * re-adding (if required) the file. + */ + if (update) + sysfs_hash_and_remove(dir_sd, NULL, + (*attr)->name); + if (grp->is_visible) { + mode = grp->is_visible(kobj, *attr, i); + if (!mode) + continue; + } + error = sysfs_add_file_mode(dir_sd, *attr, + SYSFS_KOBJ_ATTR, + (*attr)->mode | mode); + if (unlikely(error)) + break; + } + if (error) { + remove_files(dir_sd, kobj, grp); + goto exit; + } + } - /* in update mode, we're changing the permissions or - * visibility. Do this by first removing then - * re-adding (if required) the file */ - if (update) - sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); - if (grp->is_visible) { - mode = grp->is_visible(kobj, *attr, i); - if (!mode) - continue; + if (grp->bin_attrs) { + for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { + if (update) + sysfs_remove_bin_file(kobj, *bin_attr); + error = sysfs_create_bin_file(kobj, *bin_attr); + if (error) + break; } - error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR, - (*attr)->mode | mode); - if (unlikely(error)) - break; + if (error) + remove_files(dir_sd, kobj, grp); } - if (error) - remove_files(dir_sd, kobj, grp); +exit: return error; } diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d50a96b9bb6d..2c3b6a30697d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -21,6 +21,7 @@ struct kobject; struct module; +struct bin_attribute; enum kobj_ns_type; struct attribute { @@ -59,10 +60,9 @@ struct attribute_group { umode_t (*is_visible)(struct kobject *, struct attribute *, int); struct attribute **attrs; + struct bin_attribute **bin_attrs; }; - - /** * Use these macros to make defining attributes easier. See include/linux/device.h * for examples.. -- GitLab From 388a8c353d671d4ea2f638be84cfcbb912afdcf2 Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Sun, 14 Jul 2013 16:05:56 -0700 Subject: [PATCH 2815/2900] sysfs: prevent warning when only using binary attributes When only using bin_attrs instead of attrs the kernel prints a warning and refuses to create the sysfs entry. This fixes that. Signed-off-by: Oliver Schinagl Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/group.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index e5719c6095c3..09a1a25cd145 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -93,8 +93,8 @@ static int internal_create_group(struct kobject *kobj, int update, /* Updates may happen before the object has been instantiated */ if (unlikely(update && !kobj->sd)) return -EINVAL; - if (!grp->attrs) { - WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n", + if (!grp->attrs && !grp->bin_attrs) { + WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n", kobj->name, grp->name ? "" : grp->name); return -EINVAL; } -- GitLab From 39ef311204941ddd01ea2950d6220c8ccc710d15 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 14 Jul 2013 16:05:57 -0700 Subject: [PATCH 2816/2900] driver core: Introduce device_create_groups device_create_groups lets callers create devices as well as associated sysfs attributes with a single call. This avoids race conditions seen if sysfs attributes on new devices are created later. [fixed up comment block placement and add checks for printk buffer formats - gregkh] Signed-off-by: Guenter Roeck Cc: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 111 ++++++++++++++++++++++++++++++----------- include/linux/device.h | 5 ++ 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index dc3ea237f086..a8aae1823f73 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev) kfree(dev); } -/** - * device_create_vargs - creates a device and registers it with sysfs - * @class: pointer to the struct class that this device should be registered to - * @parent: pointer to the parent struct device of this new device, if any - * @devt: the dev_t for the char device to be added - * @drvdata: the data to be added to the device for callbacks - * @fmt: string for the device's name - * @args: va_list for the device's name - * - * This function can be used by char device classes. A struct device - * will be created in sysfs, registered to the specified class. - * - * A "dev" file will be created, showing the dev_t for the device, if - * the dev_t is not 0,0. - * If a pointer to a parent struct device is passed in, the newly created - * struct device will be a child of that device in sysfs. - * The pointer to the struct device will be returned from the call. - * Any further sysfs files that might be required can be created using this - * pointer. - * - * Returns &struct device pointer on success, or ERR_PTR() on error. - * - * Note: the struct class passed to this function must have previously - * been created with a call to class_create(). - */ -struct device *device_create_vargs(struct class *class, struct device *parent, - dev_t devt, void *drvdata, const char *fmt, - va_list args) +static struct device * +device_create_groups_vargs(struct class *class, struct device *parent, + dev_t devt, void *drvdata, + const struct attribute_group **groups, + const char *fmt, va_list args) { struct device *dev = NULL; int retval = -ENODEV; @@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, dev->devt = devt; dev->class = class; dev->parent = parent; + dev->groups = groups; dev->release = device_create_release; dev_set_drvdata(dev, drvdata); @@ -1728,6 +1706,39 @@ struct device *device_create_vargs(struct class *class, struct device *parent, put_device(dev); return ERR_PTR(retval); } + +/** + * device_create_vargs - creates a device and registers it with sysfs + * @class: pointer to the struct class that this device should be registered to + * @parent: pointer to the parent struct device of this new device, if any + * @devt: the dev_t for the char device to be added + * @drvdata: the data to be added to the device for callbacks + * @fmt: string for the device's name + * @args: va_list for the device's name + * + * This function can be used by char device classes. A struct device + * will be created in sysfs, registered to the specified class. + * + * A "dev" file will be created, showing the dev_t for the device, if + * the dev_t is not 0,0. + * If a pointer to a parent struct device is passed in, the newly created + * struct device will be a child of that device in sysfs. + * The pointer to the struct device will be returned from the call. + * Any further sysfs files that might be required can be created using this + * pointer. + * + * Returns &struct device pointer on success, or ERR_PTR() on error. + * + * Note: the struct class passed to this function must have previously + * been created with a call to class_create(). + */ +struct device *device_create_vargs(struct class *class, struct device *parent, + dev_t devt, void *drvdata, const char *fmt, + va_list args) +{ + return device_create_groups_vargs(class, parent, devt, drvdata, NULL, + fmt, args); +} EXPORT_SYMBOL_GPL(device_create_vargs); /** @@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent, } EXPORT_SYMBOL_GPL(device_create); +/** + * device_create_with_groups - creates a device and registers it with sysfs + * @class: pointer to the struct class that this device should be registered to + * @parent: pointer to the parent struct device of this new device, if any + * @devt: the dev_t for the char device to be added + * @drvdata: the data to be added to the device for callbacks + * @groups: NULL-terminated list of attribute groups to be created + * @fmt: string for the device's name + * + * This function can be used by char device classes. A struct device + * will be created in sysfs, registered to the specified class. + * Additional attributes specified in the groups parameter will also + * be created automatically. + * + * A "dev" file will be created, showing the dev_t for the device, if + * the dev_t is not 0,0. + * If a pointer to a parent struct device is passed in, the newly created + * struct device will be a child of that device in sysfs. + * The pointer to the struct device will be returned from the call. + * Any further sysfs files that might be required can be created using this + * pointer. + * + * Returns &struct device pointer on success, or ERR_PTR() on error. + * + * Note: the struct class passed to this function must have previously + * been created with a call to class_create(). + */ +struct device *device_create_with_groups(struct class *class, + struct device *parent, dev_t devt, + void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...) +{ + va_list vargs; + struct device *dev; + + va_start(vargs, fmt); + dev = device_create_groups_vargs(class, parent, devt, drvdata, groups, + fmt, vargs); + va_end(vargs); + return dev; +} +EXPORT_SYMBOL_GPL(device_create_with_groups); + static int __match_devt(struct device *dev, const void *data) { const dev_t *devt = data; diff --git a/include/linux/device.h b/include/linux/device.h index f207a8f49f80..bd5931e89f74 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -938,6 +938,11 @@ extern __printf(5, 6) struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...); +extern __printf(6, 7) +struct device *device_create_with_groups(struct class *cls, + struct device *parent, dev_t devt, void *drvdata, + const struct attribute_group **groups, + const char *fmt, ...); extern void device_destroy(struct class *cls, dev_t devt); /* -- GitLab From d05a6f96c76062b5f25858ac02cf677602076f7e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Jul 2013 16:05:58 -0700 Subject: [PATCH 2817/2900] driver core: add default groups to struct class We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them. The dev_attrs list will go away after all in-kernel users are converted to use dev_groups. Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 9 ++++++++- include/linux/device.h | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index a8aae1823f73..8856d74545d9 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -528,9 +528,12 @@ static int device_add_attrs(struct device *dev) int error; if (class) { - error = device_add_attributes(dev, class->dev_attrs); + error = device_add_groups(dev, class->dev_groups); if (error) return error; + error = device_add_attributes(dev, class->dev_attrs); + if (error) + goto err_remove_class_groups; error = device_add_bin_attributes(dev, class->dev_bin_attrs); if (error) goto err_remove_class_attrs; @@ -563,6 +566,9 @@ static int device_add_attrs(struct device *dev) err_remove_class_attrs: if (class) device_remove_attributes(dev, class->dev_attrs); + err_remove_class_groups: + if (class) + device_remove_groups(dev, class->dev_groups); return error; } @@ -581,6 +587,7 @@ static void device_remove_attrs(struct device *dev) if (class) { device_remove_attributes(dev, class->dev_attrs); device_remove_bin_attributes(dev, class->dev_bin_attrs); + device_remove_groups(dev, class->dev_groups); } } diff --git a/include/linux/device.h b/include/linux/device.h index bd5931e89f74..22b546a58591 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -320,6 +320,7 @@ int subsys_virtual_register(struct bus_type *subsys, * @name: Name of the class. * @owner: The module owner. * @class_attrs: Default attributes of this class. + * @dev_groups: Default attributes of the devices that belong to the class. * @dev_attrs: Default attributes of the devices belong to the class. * @dev_bin_attrs: Default binary attributes of the devices belong to the class. * @dev_kobj: The kobject that represents this class and links it into the hierarchy. @@ -349,7 +350,8 @@ struct class { struct module *owner; struct class_attribute *class_attrs; - struct device_attribute *dev_attrs; + struct device_attribute *dev_attrs; /* use dev_groups instead */ + const struct attribute_group **dev_groups; struct bin_attribute *dev_bin_attrs; struct kobject *dev_kobj; -- GitLab From 3493f69f4c4e8703961919a9a56c2d2e6a25b46f Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Sun, 14 Jul 2013 16:05:59 -0700 Subject: [PATCH 2818/2900] sysfs: add more helper macro's for (bin_)attribute(_groups) With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them. Signed-off-by: Oliver Schinagl Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 51 ++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 2c3b6a30697d..d907a7328025 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -17,6 +17,7 @@ #include #include #include +#include #include struct kobject; @@ -94,15 +95,18 @@ struct attribute_group { #define __ATTR_IGNORE_LOCKDEP __ATTR #endif -#define ATTRIBUTE_GROUPS(name) \ -static const struct attribute_group name##_group = { \ - .attrs = name##_attrs, \ -}; \ -static const struct attribute_group *name##_groups[] = { \ - &name##_group, \ +#define __ATTRIBUTE_GROUPS(_name) \ +static const struct attribute_group *_name##_groups[] = { \ + &_name##_group, \ NULL, \ } +#define ATTRIBUTE_GROUPS(_name) \ +static const struct attribute_group _name##_group = { \ + .attrs = _name##_attrs, \ +}; \ +__ATTRIBUTE_GROUPS(_name) + #define attr_name(_attr) (_attr).attr.name struct file; @@ -132,15 +136,36 @@ struct bin_attribute { */ #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr) -/* macro to create static binary attributes easier */ -#define BIN_ATTR(_name, _mode, _read, _write, _size) \ -struct bin_attribute bin_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .read = _read, \ - .write = _write, \ - .size = _size, \ +/* macros to create static binary attributes easier */ +#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \ + .attr = { .name = __stringify(_name), .mode = _mode }, \ + .read = _read, \ + .write = _write, \ + .size = _size, \ +} + +#define __BIN_ATTR_RO(_name, _size) { \ + .attr = { .name = __stringify(_name), .mode = S_IRUGO }, \ + .read = _name##_read, \ + .size = _size, \ } +#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name, \ + (S_IWUSR | S_IRUGO), _name##_read, \ + _name##_write) + +#define __BIN_ATTR_NULL __ATTR_NULL + +#define BIN_ATTR(_name, _mode, _read, _write, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read, \ + _write, _size) + +#define BIN_ATTR_RO(_name, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size) + +#define BIN_ATTR_RW(_name, _size) \ +struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size) + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); -- GitLab From aa01aa3ca205ea04f44423a58bae38aec886fb96 Mon Sep 17 00:00:00 2001 From: Oliver Schinagl Date: Sun, 14 Jul 2013 16:06:00 -0700 Subject: [PATCH 2819/2900] sysfs: use file mode defines from stat.h With the last patches stat.h was included to the header, and thus those permission defines should be used. Signed-off-by: Oliver Schinagl Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d907a7328025..9e8a9b555ad6 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -69,18 +69,19 @@ struct attribute_group { * for examples.. */ -#define __ATTR(_name,_mode,_show,_store) { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ +#define __ATTR(_name,_mode,_show,_store) { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ } -#define __ATTR_RO(_name) { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = _name##_show, \ +#define __ATTR_RO(_name) { \ + .attr = { .name = __stringify(_name), .mode = S_IRUGO }, \ + .show = _name##_show, \ } -#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) +#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ + _name##_show, _name##_store) #define __ATTR_NULL { .attr = { .name = NULL } } -- GitLab From 584ec4355355ffac43571b02a314d43eb2f7fcbf Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 16 Jul 2013 10:49:41 -0400 Subject: [PATCH 2820/2900] atl1e: unmap partially mapped skb on dma error and free skb Ben Hutchings pointed out that my recent update to atl1e in commit 352900b583b2852152a1e05ea0e8b579292e731e ("atl1e: fix dma mapping warnings") was missing a bit of code. Specifically it reset the hardware tx ring to its origional state when we hit a dma error, but didn't unmap any exiting mappings from the operation. This patch fixes that up. It also remembers to free the skb in the event that an error occurs, so we don't leak. Untested, as I don't have hardware. I think its pretty straightforward, but please review closely. Signed-off-by: Neil Horman CC: Ben Hutchings CC: Jay Cliburn CC: Chris Snook CC: "David S. Miller" Signed-off-by: David S. Miller --- .../net/ethernet/atheros/atl1e/atl1e_main.c | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 6d1a62a84c9d..1966444590f6 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1678,6 +1678,7 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter, u16 f; int segment; int ring_start = adapter->tx_ring.next_to_use; + int ring_end; nr_frags = skb_shinfo(skb)->nr_frags; segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; @@ -1721,6 +1722,15 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter, map_len, PCI_DMA_TODEVICE); if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* We need to unwind the mappings we've done */ + ring_end = adapter->tx_ring.next_to_use; + adapter->tx_ring.next_to_use = ring_start; + while (adapter->tx_ring.next_to_use != ring_end) { + tpd = atl1e_get_tpd(adapter); + tx_buffer = atl1e_get_tx_buffer(adapter, tpd); + pci_unmap_single(adapter->pdev, tx_buffer->dma, + tx_buffer->length, PCI_DMA_TODEVICE); + } /* Reset the tx rings next pointer */ adapter->tx_ring.next_to_use = ring_start; return -ENOSPC; @@ -1763,6 +1773,16 @@ static int atl1e_tx_map(struct atl1e_adapter *adapter, DMA_TO_DEVICE); if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* We need to unwind the mappings we've done */ + ring_end = adapter->tx_ring.next_to_use; + adapter->tx_ring.next_to_use = ring_start; + while (adapter->tx_ring.next_to_use != ring_end) { + tpd = atl1e_get_tpd(adapter); + tx_buffer = atl1e_get_tx_buffer(adapter, tpd); + dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); + } + /* Reset the ring next to use pointer */ adapter->tx_ring.next_to_use = ring_start; return -ENOSPC; @@ -1853,8 +1873,10 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } - if (atl1e_tx_map(adapter, skb, tpd)) + if (atl1e_tx_map(adapter, skb, tpd)) { + dev_kfree_skb_any(skb); goto out; + } atl1e_tx_queue(adapter, tpd_req, tpd); -- GitLab From f2f79cca13e36972978ffd1fb6483c8a1141b510 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Sat, 13 Jul 2013 11:26:51 +0300 Subject: [PATCH 2821/2900] ndisc: bool initializations should use true and false Signed-off-by: Daniel Baluta Signed-off-by: David S. Miller --- net/ipv6/ndisc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index b3b5730b48c5..24c03396e008 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -479,7 +479,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, if (ifp) { src_addr = solicited_addr; if (ifp->flags & IFA_F_OPTIMISTIC) - override = 0; + override = false; inc_opt |= ifp->idev->cnf.force_tllao; in6_ifa_put(ifp); } else { @@ -557,7 +557,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, } if (ipv6_addr_any(saddr)) - inc_opt = 0; + inc_opt = false; if (inc_opt) optlen += ndisc_opt_addr_space(dev); @@ -790,7 +790,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) (is_router = pndisc_is_router(&msg->target, dev)) >= 0)) { if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && skb->pkt_type != PACKET_HOST && - inc != 0 && + inc && idev->nd_parms->proxy_delay != 0) { /* * for anycast or proxy, -- GitLab From 8a73125c36809527236e1d8d367a09a3f0e9f9e1 Mon Sep 17 00:00:00 2001 From: Dragos Foianu Date: Sat, 13 Jul 2013 14:43:00 +0100 Subject: [PATCH 2822/2900] ethtool: fixed trailing statements in ethtool Applied fixes suggested by checkpatch.pl. Signed-off-by: Dragos Foianu Signed-off-by: David S. Miller --- net/core/ethtool.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index ab5fa6336c84..78e9d9223e40 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -279,11 +279,16 @@ static u32 __ethtool_get_flags(struct net_device *dev) { u32 flags = 0; - if (dev->features & NETIF_F_LRO) flags |= ETH_FLAG_LRO; - if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) flags |= ETH_FLAG_RXVLAN; - if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) flags |= ETH_FLAG_TXVLAN; - if (dev->features & NETIF_F_NTUPLE) flags |= ETH_FLAG_NTUPLE; - if (dev->features & NETIF_F_RXHASH) flags |= ETH_FLAG_RXHASH; + if (dev->features & NETIF_F_LRO) + flags |= ETH_FLAG_LRO; + if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) + flags |= ETH_FLAG_RXVLAN; + if (dev->features & NETIF_F_HW_VLAN_CTAG_TX) + flags |= ETH_FLAG_TXVLAN; + if (dev->features & NETIF_F_NTUPLE) + flags |= ETH_FLAG_NTUPLE; + if (dev->features & NETIF_F_RXHASH) + flags |= ETH_FLAG_RXHASH; return flags; } @@ -295,11 +300,16 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) if (data & ~ETH_ALL_FLAGS) return -EINVAL; - if (data & ETH_FLAG_LRO) features |= NETIF_F_LRO; - if (data & ETH_FLAG_RXVLAN) features |= NETIF_F_HW_VLAN_CTAG_RX; - if (data & ETH_FLAG_TXVLAN) features |= NETIF_F_HW_VLAN_CTAG_TX; - if (data & ETH_FLAG_NTUPLE) features |= NETIF_F_NTUPLE; - if (data & ETH_FLAG_RXHASH) features |= NETIF_F_RXHASH; + if (data & ETH_FLAG_LRO) + features |= NETIF_F_LRO; + if (data & ETH_FLAG_RXVLAN) + features |= NETIF_F_HW_VLAN_CTAG_RX; + if (data & ETH_FLAG_TXVLAN) + features |= NETIF_F_HW_VLAN_CTAG_TX; + if (data & ETH_FLAG_NTUPLE) + features |= NETIF_F_NTUPLE; + if (data & ETH_FLAG_RXHASH) + features |= NETIF_F_RXHASH; /* allow changing only bits set in hw_features */ changed = (features ^ dev->features) & ETH_ALL_FEATURES; -- GitLab From b6a82dd233cabcc1517c0744d7a8f0b61f559caf Mon Sep 17 00:00:00 2001 From: Dragos Foianu Date: Sat, 13 Jul 2013 15:03:55 +0100 Subject: [PATCH 2823/2900] net/irda: fixed style issues in irlan_eth Applied fixes suggested by checkpatch.pl Signed-off-by: Dragos Foianu Signed-off-by: David S. Miller --- net/irda/irlan/irlan_eth.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index d14152e866d9..ffcec225b5d9 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -44,12 +44,12 @@ static int irlan_eth_open(struct net_device *dev); static int irlan_eth_close(struct net_device *dev); static netdev_tx_t irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev); -static void irlan_eth_set_multicast_list( struct net_device *dev); +static void irlan_eth_set_multicast_list(struct net_device *dev); static const struct net_device_ops irlan_eth_netdev_ops = { - .ndo_open = irlan_eth_open, - .ndo_stop = irlan_eth_close, - .ndo_start_xmit = irlan_eth_xmit, + .ndo_open = irlan_eth_open, + .ndo_stop = irlan_eth_close, + .ndo_start_xmit = irlan_eth_xmit, .ndo_set_rx_mode = irlan_eth_set_multicast_list, .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, @@ -110,7 +110,7 @@ static int irlan_eth_open(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); - IRDA_DEBUG(2, "%s()\n", __func__ ); + IRDA_DEBUG(2, "%s()\n", __func__); /* Ready to play! */ netif_stop_queue(dev); /* Wait until data link is ready */ @@ -137,7 +137,7 @@ static int irlan_eth_close(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); - IRDA_DEBUG(2, "%s()\n", __func__ ); + IRDA_DEBUG(2, "%s()\n", __func__); /* Stop device */ netif_stop_queue(dev); @@ -310,35 +310,32 @@ static void irlan_eth_set_multicast_list(struct net_device *dev) { struct irlan_cb *self = netdev_priv(dev); - IRDA_DEBUG(2, "%s()\n", __func__ ); + IRDA_DEBUG(2, "%s()\n", __func__); /* Check if data channel has been connected yet */ if (self->client.state != IRLAN_DATA) { - IRDA_DEBUG(1, "%s(), delaying!\n", __func__ ); + IRDA_DEBUG(1, "%s(), delaying!\n", __func__); return; } if (dev->flags & IFF_PROMISC) { /* Enable promiscuous mode */ IRDA_WARNING("Promiscuous mode not implemented by IrLAN!\n"); - } - else if ((dev->flags & IFF_ALLMULTI) || + } else if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > HW_MAX_ADDRS) { /* Disable promiscuous mode, use normal mode. */ - IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); + IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__); /* hardware_set_filter(NULL); */ irlan_set_multicast_filter(self, TRUE); - } - else if (!netdev_mc_empty(dev)) { - IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); + } else if (!netdev_mc_empty(dev)) { + IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__); /* Walk the address list, and load the filter */ /* hardware_set_filter(dev->mc_list); */ irlan_set_multicast_filter(self, TRUE); - } - else { - IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __func__ ); + } else { + IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __func__); irlan_set_multicast_filter(self, FALSE); } -- GitLab From 31bd29776b8575b8cf7c25bbf7496a460278dc83 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Mon, 15 Jul 2013 13:26:27 +0200 Subject: [PATCH 2824/2900] bgmac: add dependency to phylib bgmac is using functions from phylib, add the dependency. Signed-off-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 1d680baf43d6..52c96036dcc4 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -131,6 +131,7 @@ config BNX2X_SRIOV config BGMAC tristate "BCMA bus GBit core support" depends on BCMA_HOST_SOC && HAS_DMA + select PHYLIB ---help--- This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. They can be found on BCM47xx SoCs and provide gigabit ethernet. -- GitLab From 9a0f06fee1f453370e87b6568dc1d39d676f53fc Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Mon, 15 Jul 2013 08:56:45 -0600 Subject: [PATCH 2825/2900] mlx5 core: Fix __udivdi3 when compiling for 32 bit arches Cc: Eli Cohen Signed-off-by: Tim Gardner Acked-by: Randy Dunlap Reported-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index 4273c06e2e96..9c7194b26ee2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -156,7 +156,7 @@ static ssize_t average_read(struct file *filp, char __user *buf, size_t count, stats = filp->private_data; spin_lock(&stats->lock); if (stats->n) - field = stats->sum / stats->n; + field = div64_u64(stats->sum, stats->n); spin_unlock(&stats->lock); ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field); if (ret > 0) { -- GitLab From 3715534adf899bfc842868865f13a001b8aa4692 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 14 Jul 2013 14:02:19 +0200 Subject: [PATCH 2826/2900] cpufreq: s3c24xx: fix "depends on ARM_S3C24XX" in Kconfig Kconfig symbol S3C24XX_PLL depends on ARM_S3C24XX. But that symbol doesn't exist. Commit f023f8dd59bf ("cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq"), which added this issue, makes it clear that ARM_S3C24XX_CPUFREQ was intended here. Signed-off-by: Paul Bolle Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-s3c24xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index 6d9252e081ce..7791ac76f945 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -208,7 +208,7 @@ config S3C24XX_GPIO_EXTRA128 config S3C24XX_PLL bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)" - depends on ARM_S3C24XX + depends on ARM_S3C24XX_CPUFREQ help Compile in support for changing the PLL frequency from the S3C24XX series CPUfreq driver. The PLL takes time to settle -- GitLab From 21d1196a35f5686c4323e42a62fdb4b23b0ab4a3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 15 Jul 2013 20:03:19 -0700 Subject: [PATCH 2827/2900] ipv4: set transport header earlier commit 45f00f99d6e ("ipv4: tcp: clean up tcp_v4_early_demux()") added a performance regression for non GRO traffic, basically disabling IP early demux. IPv6 stack resets transport header in ip6_rcv() before calling IP early demux in ip6_rcv_finish(), while IPv4 does this only in ip_local_deliver_finish(), _after_ IP early demux. GRO traffic happened to enable IP early demux because transport header is also set in inet_gro_receive() Instead of reverting the faulty commit, we can make IPv4/IPv6 behave the same : transport_header should be set in ip_rcv() instead of ip_local_deliver_finish() ip_local_deliver_finish() can also use skb_network_header_len() which is faster than ip_hdrlen() Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/ip_input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 3da817b89e9b..15e3e683adec 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -190,10 +190,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb) { struct net *net = dev_net(skb->dev); - __skb_pull(skb, ip_hdrlen(skb)); - - /* Point into the IP datagram, just past the header. */ - skb_reset_transport_header(skb); + __skb_pull(skb, skb_network_header_len(skb)); rcu_read_lock(); { @@ -437,6 +434,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, goto drop; } + skb->transport_header = skb->network_header + iph->ihl*4; + /* Remove any debris in the socket control block */ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); -- GitLab From 82a19eb8c02ab98bfe0bf6fa4915de370acb2858 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 16 Jul 2013 13:36:33 +0800 Subject: [PATCH 2828/2900] macvtap: fix the missing ret value of TUNSETQUEUE Commit 441ac0fcaadc76ad09771812382345001dd2b813 (macvtap: Convert to using rtnl lock) forget to return what macvtap_ioctl_set_queue() returns to its caller. This may break multiqueue API by always falling through to TUNGETFEATURES. Cc: Vlad Yasevich Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 876c72246ae9..0e5492ec753a 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -1107,6 +1107,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, rtnl_lock(); ret = macvtap_ioctl_set_queue(file, u); rtnl_unlock(); + return ret; case TUNGETFEATURES: if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR | -- GitLab From 0fbe0d47b1ee2015c288abd4e7b32224f8bfa212 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 16 Jul 2013 13:36:34 +0800 Subject: [PATCH 2829/2900] macvtap: do not assume 802.1Q when send vlan packets The hard-coded 8021.q proto will break 802.1ad traffic. So switch to use vlan->proto. Cc: Basil Gor Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 0e5492ec753a..a7c5654a2e5c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -873,7 +873,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, __be16 h_vlan_proto; __be16 h_vlan_TCI; } veth; - veth.h_vlan_proto = htons(ETH_P_8021Q); + veth.h_vlan_proto = skb->vlan_proto; veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); -- GitLab From 52fe29e4bb614367c108b717c6d7fe5953eb7af3 Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Tue, 16 Jul 2013 12:44:02 +0530 Subject: [PATCH 2830/2900] be2net: Fix to avoid hardware workaround when not needed Hardware workaround requesting hardware to skip vlan insertion is necessary only when umc or qnq is enabled. Enabling this workaround in other scenarios could cause controller to stall. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 2df48bb0f1ca..181edb522450 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -782,16 +782,22 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, if (vlan_tx_tag_present(skb)) vlan_tag = be_get_tx_vlan_tag(adapter, skb); - else if (qnq_async_evt_rcvd(adapter) && adapter->pvid) - vlan_tag = adapter->pvid; + + if (qnq_async_evt_rcvd(adapter) && adapter->pvid) { + if (!vlan_tag) + vlan_tag = adapter->pvid; + /* f/w workaround to set skip_hw_vlan = 1, informs the F/W to + * skip VLAN insertion + */ + if (skip_hw_vlan) + *skip_hw_vlan = true; + } if (vlan_tag) { skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); if (unlikely(!skb)) return skb; skb->vlan_tci = 0; - if (skip_hw_vlan) - *skip_hw_vlan = true; } /* Insert the outer VLAN, if any */ -- GitLab From e8d05276f236ee6435e78411f62be9714e0b9377 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 16 Jul 2013 22:46:48 +0200 Subject: [PATCH 2831/2900] cpufreq: Revert commit 2f7021a8 to fix CPU hotplug regression commit 2f7021a8 "cpufreq: protect 'policy->cpus' from offlining during __gov_queue_work()" caused a regression in CPU hotplug, because it lead to a deadlock between cpufreq governor worker thread and the CPU hotplug writer task. Lockdep splat corresponding to this deadlock is shown below: [ 60.277396] ====================================================== [ 60.277400] [ INFO: possible circular locking dependency detected ] [ 60.277407] 3.10.0-rc7-dbg-01385-g241fd04-dirty #1744 Not tainted [ 60.277411] ------------------------------------------------------- [ 60.277417] bash/2225 is trying to acquire lock: [ 60.277422] ((&(&j_cdbs->work)->work)){+.+...}, at: [] flush_work+0x5/0x280 [ 60.277444] but task is already holding lock: [ 60.277449] (cpu_hotplug.lock){+.+.+.}, at: [] cpu_hotplug_begin+0x2b/0x60 [ 60.277465] which lock already depends on the new lock. [ 60.277472] the existing dependency chain (in reverse order) is: [ 60.277477] -> #2 (cpu_hotplug.lock){+.+.+.}: [ 60.277490] [] lock_acquire+0xa4/0x200 [ 60.277503] [] mutex_lock_nested+0x67/0x410 [ 60.277514] [] get_online_cpus+0x3c/0x60 [ 60.277522] [] gov_queue_work+0x2a/0xb0 [ 60.277532] [] cs_dbs_timer+0xc1/0xe0 [ 60.277543] [] process_one_work+0x1cd/0x6a0 [ 60.277552] [] worker_thread+0x121/0x3a0 [ 60.277560] [] kthread+0xdb/0xe0 [ 60.277569] [] ret_from_fork+0x7c/0xb0 [ 60.277580] -> #1 (&j_cdbs->timer_mutex){+.+...}: [ 60.277592] [] lock_acquire+0xa4/0x200 [ 60.277600] [] mutex_lock_nested+0x67/0x410 [ 60.277608] [] cs_dbs_timer+0x8d/0xe0 [ 60.277616] [] process_one_work+0x1cd/0x6a0 [ 60.277624] [] worker_thread+0x121/0x3a0 [ 60.277633] [] kthread+0xdb/0xe0 [ 60.277640] [] ret_from_fork+0x7c/0xb0 [ 60.277649] -> #0 ((&(&j_cdbs->work)->work)){+.+...}: [ 60.277661] [] __lock_acquire+0x1766/0x1d30 [ 60.277669] [] lock_acquire+0xa4/0x200 [ 60.277677] [] flush_work+0x3d/0x280 [ 60.277685] [] __cancel_work_timer+0x8a/0x120 [ 60.277693] [] cancel_delayed_work_sync+0x13/0x20 [ 60.277701] [] cpufreq_governor_dbs+0x529/0x6f0 [ 60.277709] [] cs_cpufreq_governor_dbs+0x17/0x20 [ 60.277719] [] __cpufreq_governor+0x48/0x100 [ 60.277728] [] __cpufreq_remove_dev.isra.14+0x80/0x3c0 [ 60.277737] [] cpufreq_cpu_callback+0x38/0x4c [ 60.277747] [] notifier_call_chain+0x5d/0x110 [ 60.277759] [] __raw_notifier_call_chain+0xe/0x10 [ 60.277768] [] _cpu_down+0x88/0x330 [ 60.277779] [] cpu_down+0x36/0x50 [ 60.277788] [] store_online+0x98/0xd0 [ 60.277796] [] dev_attr_store+0x18/0x30 [ 60.277806] [] sysfs_write_file+0xdb/0x150 [ 60.277818] [] vfs_write+0xbd/0x1f0 [ 60.277826] [] SyS_write+0x4c/0xa0 [ 60.277834] [] tracesys+0xd0/0xd5 [ 60.277842] other info that might help us debug this: [ 60.277848] Chain exists of: (&(&j_cdbs->work)->work) --> &j_cdbs->timer_mutex --> cpu_hotplug.lock [ 60.277864] Possible unsafe locking scenario: [ 60.277869] CPU0 CPU1 [ 60.277873] ---- ---- [ 60.277877] lock(cpu_hotplug.lock); [ 60.277885] lock(&j_cdbs->timer_mutex); [ 60.277892] lock(cpu_hotplug.lock); [ 60.277900] lock((&(&j_cdbs->work)->work)); [ 60.277907] *** DEADLOCK *** [ 60.277915] 6 locks held by bash/2225: [ 60.277919] #0: (sb_writers#6){.+.+.+}, at: [] vfs_write+0x1c3/0x1f0 [ 60.277937] #1: (&buffer->mutex){+.+.+.}, at: [] sysfs_write_file+0x3c/0x150 [ 60.277954] #2: (s_active#61){.+.+.+}, at: [] sysfs_write_file+0xc3/0x150 [ 60.277972] #3: (x86_cpu_hotplug_driver_mutex){+.+...}, at: [] cpu_hotplug_driver_lock+0x17/0x20 [ 60.277990] #4: (cpu_add_remove_lock){+.+.+.}, at: [] cpu_down+0x22/0x50 [ 60.278007] #5: (cpu_hotplug.lock){+.+.+.}, at: [] cpu_hotplug_begin+0x2b/0x60 [ 60.278023] stack backtrace: [ 60.278031] CPU: 3 PID: 2225 Comm: bash Not tainted 3.10.0-rc7-dbg-01385-g241fd04-dirty #1744 [ 60.278037] Hardware name: Acer Aspire 5741G /Aspire 5741G , BIOS V1.20 02/08/2011 [ 60.278042] ffffffff8204e110 ffff88014df6b9f8 ffffffff815b3d90 ffff88014df6ba38 [ 60.278055] ffffffff815b0a8d ffff880150ed3f60 ffff880150ed4770 3871c4002c8980b2 [ 60.278068] ffff880150ed4748 ffff880150ed4770 ffff880150ed3f60 ffff88014df6bb00 [ 60.278081] Call Trace: [ 60.278091] [] dump_stack+0x19/0x1b [ 60.278101] [] print_circular_bug+0x2b6/0x2c5 [ 60.278111] [] __lock_acquire+0x1766/0x1d30 [ 60.278123] [] ? __kernel_text_address+0x58/0x80 [ 60.278134] [] lock_acquire+0xa4/0x200 [ 60.278142] [] ? flush_work+0x5/0x280 [ 60.278151] [] flush_work+0x3d/0x280 [ 60.278159] [] ? flush_work+0x5/0x280 [ 60.278169] [] ? mark_held_locks+0x94/0x140 [ 60.278178] [] ? __cancel_work_timer+0x77/0x120 [ 60.278188] [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [ 60.278196] [] __cancel_work_timer+0x8a/0x120 [ 60.278206] [] cancel_delayed_work_sync+0x13/0x20 [ 60.278214] [] cpufreq_governor_dbs+0x529/0x6f0 [ 60.278225] [] cs_cpufreq_governor_dbs+0x17/0x20 [ 60.278234] [] __cpufreq_governor+0x48/0x100 [ 60.278244] [] __cpufreq_remove_dev.isra.14+0x80/0x3c0 [ 60.278255] [] cpufreq_cpu_callback+0x38/0x4c [ 60.278265] [] notifier_call_chain+0x5d/0x110 [ 60.278275] [] __raw_notifier_call_chain+0xe/0x10 [ 60.278284] [] _cpu_down+0x88/0x330 [ 60.278292] [] ? cpu_hotplug_driver_lock+0x17/0x20 [ 60.278302] [] cpu_down+0x36/0x50 [ 60.278311] [] store_online+0x98/0xd0 [ 60.278320] [] dev_attr_store+0x18/0x30 [ 60.278329] [] sysfs_write_file+0xdb/0x150 [ 60.278337] [] vfs_write+0xbd/0x1f0 [ 60.278347] [] ? fget_light+0x320/0x4b0 [ 60.278355] [] SyS_write+0x4c/0xa0 [ 60.278364] [] tracesys+0xd0/0xd5 [ 60.280582] smpboot: CPU 1 is now offline The intention of that commit was to avoid warnings during CPU hotplug, which indicated that offline CPUs were getting IPIs from the cpufreq governor's work items. But the real root-cause of that problem was commit a66b2e5 (cpufreq: Preserve sysfs files across suspend/resume) because it totally skipped all the cpufreq callbacks during CPU hotplug in the suspend/resume path, and hence it never actually shut down the cpufreq governor's worker threads during CPU offline in the suspend/resume path. Reflecting back, the reason why we never suspected that commit as the root-cause earlier, was that the original issue was reported with just the halt command and nobody had brought in suspend/resume to the equation. The reason for _that_ in turn, as it turns out, is that earlier halt/shutdown was being done by disabling non-boot CPUs while tasks were frozen, just like suspend/resume.... but commit cf7df378a (reboot: migrate shutdown/reboot to boot cpu) which came somewhere along that very same time changed that logic: shutdown/halt no longer takes CPUs offline. Thus, the test-cases for reproducing the bug were vastly different and thus we went totally off the trail. Overall, it was one hell of a confusion with so many commits affecting each other and also affecting the symptoms of the problems in subtle ways. Finally, now since the original problematic commit (a66b2e5) has been completely reverted, revert this intermediate fix too (2f7021a8), to fix the CPU hotplug deadlock. Phew! Reported-by: Sergey Senozhatsky Reported-by: Bartlomiej Zolnierkiewicz Signed-off-by: Srivatsa S. Bhat Tested-by: Peter Wu Cc: 3.10+ Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 464587697561..7b839a8db2a7 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "cpufreq_governor.h" @@ -137,10 +136,8 @@ void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy, if (!all_cpus) { __gov_queue_work(smp_processor_id(), dbs_data, delay); } else { - get_online_cpus(); for_each_cpu(i, policy->cpus) __gov_queue_work(i, dbs_data, delay); - put_online_cpus(); } } EXPORT_SYMBOL_GPL(gov_queue_work); -- GitLab From 4df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 16 Jul 2013 11:34:41 -0700 Subject: [PATCH 2832/2900] x86: Make sure IDT is page aligned Since the IDT is referenced from a fixmap, make sure it is page aligned. Merge with 32-bit one, since it was already aligned to deal with F00F bug. Since bss is cleared before IDT setup, it can live there. This also moves the other *_idt_table variables into common locations. This avoids the risk of the IDT ever being moved in the bss and having the mapping be offset, resulting in calling incorrect handlers. In the current upstream kernel this is not a manifested bug, but heavily patched kernels (such as those using the PaX patch series) did encounter this bug. The tables other than idt_table technically do not need to be page aligned, at least not at the current time, but using a common declaration avoids mistakes. On 64 bits the table is exactly one page long, anyway. Signed-off-by: Kees Cook Link: http://lkml.kernel.org/r/20130716183441.GA14232@www.outflux.net Reported-by: PaX Team Signed-off-by: H. Peter Anvin --- arch/x86/kernel/head_64.S | 15 --------------- arch/x86/kernel/tracepoint.c | 6 ++---- arch/x86/kernel/traps.c | 12 ++++++------ 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 5e4d8a8a5c40..e1aabdb314c8 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -512,21 +512,6 @@ ENTRY(phys_base) #include "../../x86/xen/xen-head.S" - .section .bss, "aw", @nobits - .align L1_CACHE_BYTES -ENTRY(idt_table) - .skip IDT_ENTRIES * 16 - - .align L1_CACHE_BYTES -ENTRY(debug_idt_table) - .skip IDT_ENTRIES * 16 - -#ifdef CONFIG_TRACING - .align L1_CACHE_BYTES -ENTRY(trace_idt_table) - .skip IDT_ENTRIES * 16 -#endif - __PAGE_ALIGNED_BSS NEXT_PAGE(empty_zero_page) .skip PAGE_SIZE diff --git a/arch/x86/kernel/tracepoint.c b/arch/x86/kernel/tracepoint.c index 4e584a8d6edd..1c113db9ed57 100644 --- a/arch/x86/kernel/tracepoint.c +++ b/arch/x86/kernel/tracepoint.c @@ -12,10 +12,8 @@ atomic_t trace_idt_ctr = ATOMIC_INIT(0); struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) trace_idt_table }; -#ifndef CONFIG_X86_64 -gate_desc trace_idt_table[NR_VECTORS] __page_aligned_data - = { { { { 0, 0 } } }, }; -#endif +/* No need to be aligned, but done to keep all IDTs defined the same way. */ +gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss; static int trace_irq_vector_refcount; static DEFINE_MUTEX(irq_vector_mutex); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b0865e88d3cc..1b23a1c92746 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -63,19 +63,19 @@ #include #include #include + +/* No need to be aligned, but done to keep all IDTs defined the same way. */ +gate_desc debug_idt_table[NR_VECTORS] __page_aligned_bss; #else #include #include asmlinkage int system_call(void); - -/* - * The IDT has to be page-aligned to simplify the Pentium - * F0 0F bug workaround. - */ -gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, }; #endif +/* Must be page-aligned because the real IDT is used in a fixmap. */ +gate_desc idt_table[NR_VECTORS] __page_aligned_bss; + DECLARE_BITMAP(used_vectors, NR_VECTORS); EXPORT_SYMBOL_GPL(used_vectors); -- GitLab From ae8e9c5a1a7889315229a741fd48a5dd0bc2964c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Jul 2013 17:09:15 -0700 Subject: [PATCH 2833/2900] net: Fix sysfs_format_mac() code duplication. It's just a duplicate implementation of "%*phC". Thanks to Joe Perches for showing that we had exactly this support in the lib/vsprintf.c code already. Signed-off-by: David S. Miller --- net/ethernet/eth.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 5359560926bc..be1f64d35358 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -401,27 +401,8 @@ struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, } EXPORT_SYMBOL(alloc_etherdev_mqs); -static size_t _format_mac_addr(char *buf, int buflen, - const unsigned char *addr, int len) -{ - int i; - char *cp = buf; - - for (i = 0; i < len; i++) { - cp += scnprintf(cp, buflen - (cp - buf), "%02x", addr[i]); - if (i == len - 1) - break; - cp += scnprintf(cp, buflen - (cp - buf), ":"); - } - return cp - buf; -} - ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len) { - size_t l; - - l = _format_mac_addr(buf, PAGE_SIZE, addr, len); - l += scnprintf(buf + l, PAGE_SIZE - l, "\n"); - return (ssize_t)l; + return scnprintf(buf, PAGE_SIZE, "%*phC\n", len, addr); } EXPORT_SYMBOL(sysfs_format_mac); -- GitLab From c0d15cc7ee8c0d1970197d9eb1727503bcdd2471 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 16 Jul 2013 22:44:08 -0400 Subject: [PATCH 2834/2900] linked-list: Remove __list_for_each __list_for_each used to be the non prefetch() aware list walking primitive. When we removed the prefetch macros from the list routines, it became redundant. Given it does exactly the same thing as list_for_each now, we might as well remove it and call list_for_each directly. All users of __list_for_each have been converted to list_for_each calls in the current merge window. Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- include/linux/list.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/include/linux/list.h b/include/linux/list.h index b83e5657365a..f4d8a2f12a33 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -380,17 +380,6 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - * - * This variant doesn't differ from list_for_each() any more. - * We don't do prefetching in either case. - */ -#define __list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - /** * list_for_each_prev - iterate over a list backwards * @pos: the &struct list_head to use as a loop cursor. -- GitLab From ade7615de0643a9da628688e661e08148cd7c463 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Jul 2013 22:37:09 -0700 Subject: [PATCH 2835/2900] staging: csr: remove driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver is not being updated as the specifications are not able to be gotten from CSR or anyone else. Without those, getting this driver into proper mergable shape is going to be impossible. So remove the driver from the tree. If the specifications ever become available, this patch can be reverted and the driver fixed up properly. Reported-by: Lidza Louina Cc: Veli-Pekka Peltola Cc: Mikko Virkkilä Cc: Lauri Hintsala Cc: Riku Mettälä Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/csr/Kconfig | 9 - drivers/staging/csr/LICENSE.txt | 39 - drivers/staging/csr/Makefile | 73 - drivers/staging/csr/bh.c | 404 - drivers/staging/csr/csr_framework_ext.c | 40 - drivers/staging/csr/csr_framework_ext.h | 35 - drivers/staging/csr/csr_framework_ext_types.h | 30 - drivers/staging/csr/csr_log.h | 223 - drivers/staging/csr/csr_log_configure.h | 39 - drivers/staging/csr/csr_log_text.h | 124 - drivers/staging/csr/csr_macro.h | 39 - drivers/staging/csr/csr_msg_transport.h | 17 - drivers/staging/csr/csr_msgconv.c | 291 - drivers/staging/csr/csr_msgconv.h | 78 - drivers/staging/csr/csr_prim_defs.h | 55 - drivers/staging/csr/csr_result.h | 17 - drivers/staging/csr/csr_sched.h | 85 - drivers/staging/csr/csr_sdio.h | 723 -- .../csr/csr_serialize_primitive_types.c | 100 - drivers/staging/csr/csr_time.c | 33 - drivers/staging/csr/csr_time.h | 76 - drivers/staging/csr/csr_util.c | 15 - drivers/staging/csr/csr_wifi_common.h | 101 - drivers/staging/csr/csr_wifi_fsm.h | 240 - drivers/staging/csr/csr_wifi_fsm_event.h | 42 - drivers/staging/csr/csr_wifi_fsm_types.h | 430 -- drivers/staging/csr/csr_wifi_hip_card.h | 114 - drivers/staging/csr/csr_wifi_hip_card_sdio.c | 4001 ---------- drivers/staging/csr/csr_wifi_hip_card_sdio.h | 694 -- .../staging/csr/csr_wifi_hip_card_sdio_intr.c | 2595 ------- .../staging/csr/csr_wifi_hip_card_sdio_mem.c | 1713 ----- drivers/staging/csr/csr_wifi_hip_chiphelper.c | 793 -- drivers/staging/csr/csr_wifi_hip_chiphelper.h | 407 -- .../csr/csr_wifi_hip_chiphelper_private.h | 200 - .../staging/csr/csr_wifi_hip_conversions.h | 73 - drivers/staging/csr/csr_wifi_hip_download.c | 819 --- drivers/staging/csr/csr_wifi_hip_dump.c | 837 --- drivers/staging/csr/csr_wifi_hip_packing.c | 4804 ------------ drivers/staging/csr/csr_wifi_hip_send.c | 415 -- drivers/staging/csr/csr_wifi_hip_signals.c | 1313 ---- drivers/staging/csr/csr_wifi_hip_signals.h | 128 - drivers/staging/csr/csr_wifi_hip_sigs.h | 1417 ---- .../staging/csr/csr_wifi_hip_ta_sampling.c | 541 -- .../staging/csr/csr_wifi_hip_ta_sampling.h | 66 - drivers/staging/csr/csr_wifi_hip_udi.c | 173 - drivers/staging/csr/csr_wifi_hip_unifi.h | 871 --- .../csr/csr_wifi_hip_unifi_signal_names.c | 41 - drivers/staging/csr/csr_wifi_hip_unifi_udi.h | 52 - drivers/staging/csr/csr_wifi_hip_unifihw.h | 59 - .../staging/csr/csr_wifi_hip_unifiversion.h | 30 - drivers/staging/csr/csr_wifi_hip_xbv.c | 1076 --- drivers/staging/csr/csr_wifi_hip_xbv.h | 119 - drivers/staging/csr/csr_wifi_hostio_prim.h | 18 - drivers/staging/csr/csr_wifi_lib.h | 103 - drivers/staging/csr/csr_wifi_msgconv.h | 49 - .../csr/csr_wifi_nme_ap_converter_init.c | 90 - .../csr/csr_wifi_nme_ap_converter_init.h | 41 - ...csr_wifi_nme_ap_free_downstream_contents.c | 84 - .../csr_wifi_nme_ap_free_upstream_contents.c | 39 - drivers/staging/csr/csr_wifi_nme_ap_lib.h | 495 -- drivers/staging/csr/csr_wifi_nme_ap_prim.h | 494 -- drivers/staging/csr/csr_wifi_nme_ap_sef.c | 30 - drivers/staging/csr/csr_wifi_nme_ap_sef.h | 21 - .../staging/csr/csr_wifi_nme_ap_serialize.c | 909 --- .../staging/csr/csr_wifi_nme_ap_serialize.h | 94 - .../staging/csr/csr_wifi_nme_converter_init.h | 38 - drivers/staging/csr/csr_wifi_nme_lib.h | 991 --- drivers/staging/csr/csr_wifi_nme_prim.h | 1657 ----- drivers/staging/csr/csr_wifi_nme_serialize.h | 166 - drivers/staging/csr/csr_wifi_nme_task.h | 27 - drivers/staging/csr/csr_wifi_private_common.h | 81 - drivers/staging/csr/csr_wifi_result.h | 27 - .../csr/csr_wifi_router_converter_init.c | 82 - .../csr/csr_wifi_router_converter_init.h | 34 - .../csr/csr_wifi_router_ctrl_converter_init.c | 134 - .../csr/csr_wifi_router_ctrl_converter_init.h | 34 - ...ifi_router_ctrl_free_downstream_contents.c | 108 - ..._wifi_router_ctrl_free_upstream_contents.c | 87 - .../staging/csr/csr_wifi_router_ctrl_lib.h | 2082 ------ .../staging/csr/csr_wifi_router_ctrl_prim.h | 2113 ------ .../staging/csr/csr_wifi_router_ctrl_sef.c | 46 - .../staging/csr/csr_wifi_router_ctrl_sef.h | 51 - .../csr/csr_wifi_router_ctrl_serialize.c | 2591 ------- .../csr/csr_wifi_router_ctrl_serialize.h | 333 - ...csr_wifi_router_free_downstream_contents.c | 53 - .../csr_wifi_router_free_upstream_contents.c | 47 - drivers/staging/csr/csr_wifi_router_lib.h | 417 -- drivers/staging/csr/csr_wifi_router_prim.h | 421 -- drivers/staging/csr/csr_wifi_router_sef.c | 19 - drivers/staging/csr/csr_wifi_router_sef.h | 25 - .../staging/csr/csr_wifi_router_serialize.c | 418 -- .../staging/csr/csr_wifi_router_serialize.h | 67 - drivers/staging/csr/csr_wifi_router_task.h | 25 - .../staging/csr/csr_wifi_router_transport.c | 199 - .../csr/csr_wifi_serialize_primitive_types.c | 256 - drivers/staging/csr/csr_wifi_sme_ap_lib.h | 774 -- drivers/staging/csr/csr_wifi_sme_ap_prim.h | 1030 --- .../staging/csr/csr_wifi_sme_converter_init.c | 201 - .../staging/csr/csr_wifi_sme_converter_init.h | 34 - .../csr_wifi_sme_free_downstream_contents.c | 187 - .../csr/csr_wifi_sme_free_upstream_contents.c | 275 - drivers/staging/csr/csr_wifi_sme_lib.h | 4303 ----------- drivers/staging/csr/csr_wifi_sme_prim.h | 6510 ----------------- drivers/staging/csr/csr_wifi_sme_sef.c | 85 - drivers/staging/csr/csr_wifi_sme_sef.h | 142 - drivers/staging/csr/csr_wifi_sme_serialize.c | 5809 --------------- drivers/staging/csr/csr_wifi_sme_serialize.h | 666 -- drivers/staging/csr/csr_wifi_sme_task.h | 25 - drivers/staging/csr/csr_wifi_vif_utils.h | 27 - drivers/staging/csr/data_tx.c | 54 - drivers/staging/csr/drv.c | 2193 ------ drivers/staging/csr/firmware.c | 396 - drivers/staging/csr/inet.c | 104 - drivers/staging/csr/init_hw.c | 108 - drivers/staging/csr/io.c | 1098 --- drivers/staging/csr/mlme.c | 433 -- drivers/staging/csr/monitor.c | 384 - drivers/staging/csr/netdev.c | 3307 --------- drivers/staging/csr/os.c | 477 -- drivers/staging/csr/putest.c | 685 -- drivers/staging/csr/sdio_events.c | 134 - drivers/staging/csr/sdio_mmc.c | 1288 ---- drivers/staging/csr/sdio_stubs.c | 82 - drivers/staging/csr/sme_blocking.c | 1466 ---- drivers/staging/csr/sme_mgt.c | 1012 --- drivers/staging/csr/sme_native.c | 566 -- drivers/staging/csr/sme_sys.c | 3260 --------- drivers/staging/csr/sme_userspace.c | 315 - drivers/staging/csr/sme_userspace.h | 38 - drivers/staging/csr/sme_wext.c | 3327 --------- drivers/staging/csr/ul_int.c | 528 -- drivers/staging/csr/unifi_clients.h | 129 - drivers/staging/csr/unifi_config.h | 34 - drivers/staging/csr/unifi_dbg.c | 110 - drivers/staging/csr/unifi_event.c | 692 -- drivers/staging/csr/unifi_native.h | 257 - drivers/staging/csr/unifi_os.h | 122 - drivers/staging/csr/unifi_pdu_processing.c | 3729 ---------- drivers/staging/csr/unifi_priv.h | 1136 --- drivers/staging/csr/unifi_sme.c | 1225 ---- drivers/staging/csr/unifi_sme.h | 245 - drivers/staging/csr/unifi_wext.h | 108 - drivers/staging/csr/unifiio.h | 398 - drivers/staging/csr/wext_events.c | 283 - 146 files changed, 91599 deletions(-) delete mode 100644 drivers/staging/csr/Kconfig delete mode 100644 drivers/staging/csr/LICENSE.txt delete mode 100644 drivers/staging/csr/Makefile delete mode 100644 drivers/staging/csr/bh.c delete mode 100644 drivers/staging/csr/csr_framework_ext.c delete mode 100644 drivers/staging/csr/csr_framework_ext.h delete mode 100644 drivers/staging/csr/csr_framework_ext_types.h delete mode 100644 drivers/staging/csr/csr_log.h delete mode 100644 drivers/staging/csr/csr_log_configure.h delete mode 100644 drivers/staging/csr/csr_log_text.h delete mode 100644 drivers/staging/csr/csr_macro.h delete mode 100644 drivers/staging/csr/csr_msg_transport.h delete mode 100644 drivers/staging/csr/csr_msgconv.c delete mode 100644 drivers/staging/csr/csr_msgconv.h delete mode 100644 drivers/staging/csr/csr_prim_defs.h delete mode 100644 drivers/staging/csr/csr_result.h delete mode 100644 drivers/staging/csr/csr_sched.h delete mode 100644 drivers/staging/csr/csr_sdio.h delete mode 100644 drivers/staging/csr/csr_serialize_primitive_types.c delete mode 100644 drivers/staging/csr/csr_time.c delete mode 100644 drivers/staging/csr/csr_time.h delete mode 100644 drivers/staging/csr/csr_util.c delete mode 100644 drivers/staging/csr/csr_wifi_common.h delete mode 100644 drivers/staging/csr/csr_wifi_fsm.h delete mode 100644 drivers/staging/csr/csr_wifi_fsm_event.h delete mode 100644 drivers/staging/csr/csr_wifi_fsm_types.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_card.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_chiphelper_private.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_conversions.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_download.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_dump.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_packing.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_send.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_signals.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_signals.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_sigs.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_ta_sampling.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_ta_sampling.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_udi.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_unifi.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_unifi_udi.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_unifihw.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_unifiversion.h delete mode 100644 drivers/staging/csr/csr_wifi_hip_xbv.c delete mode 100644 drivers/staging/csr/csr_wifi_hip_xbv.h delete mode 100644 drivers/staging/csr/csr_wifi_hostio_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_msgconv.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_converter_init.c delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_converter_init.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_free_downstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_free_upstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_sef.c delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_sef.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_serialize.c delete mode 100644 drivers/staging/csr/csr_wifi_nme_ap_serialize.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_converter_init.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_serialize.h delete mode 100644 drivers/staging/csr/csr_wifi_nme_task.h delete mode 100644 drivers/staging/csr/csr_wifi_private_common.h delete mode 100644 drivers/staging/csr/csr_wifi_result.h delete mode 100644 drivers/staging/csr/csr_wifi_router_converter_init.c delete mode 100644 drivers/staging/csr/csr_wifi_router_converter_init.h delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_sef.c delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_sef.h delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_serialize.c delete mode 100644 drivers/staging/csr/csr_wifi_router_ctrl_serialize.h delete mode 100644 drivers/staging/csr/csr_wifi_router_free_downstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_router_free_upstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_router_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_router_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_router_sef.c delete mode 100644 drivers/staging/csr/csr_wifi_router_sef.h delete mode 100644 drivers/staging/csr/csr_wifi_router_serialize.c delete mode 100644 drivers/staging/csr/csr_wifi_router_serialize.h delete mode 100644 drivers/staging/csr/csr_wifi_router_task.h delete mode 100644 drivers/staging/csr/csr_wifi_router_transport.c delete mode 100644 drivers/staging/csr/csr_wifi_serialize_primitive_types.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_ap_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_ap_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_converter_init.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_converter_init.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_lib.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_prim.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_sef.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_sef.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_serialize.c delete mode 100644 drivers/staging/csr/csr_wifi_sme_serialize.h delete mode 100644 drivers/staging/csr/csr_wifi_sme_task.h delete mode 100644 drivers/staging/csr/csr_wifi_vif_utils.h delete mode 100644 drivers/staging/csr/data_tx.c delete mode 100644 drivers/staging/csr/drv.c delete mode 100644 drivers/staging/csr/firmware.c delete mode 100644 drivers/staging/csr/inet.c delete mode 100644 drivers/staging/csr/init_hw.c delete mode 100644 drivers/staging/csr/io.c delete mode 100644 drivers/staging/csr/mlme.c delete mode 100644 drivers/staging/csr/monitor.c delete mode 100644 drivers/staging/csr/netdev.c delete mode 100644 drivers/staging/csr/os.c delete mode 100644 drivers/staging/csr/putest.c delete mode 100644 drivers/staging/csr/sdio_events.c delete mode 100644 drivers/staging/csr/sdio_mmc.c delete mode 100644 drivers/staging/csr/sdio_stubs.c delete mode 100644 drivers/staging/csr/sme_blocking.c delete mode 100644 drivers/staging/csr/sme_mgt.c delete mode 100644 drivers/staging/csr/sme_native.c delete mode 100644 drivers/staging/csr/sme_sys.c delete mode 100644 drivers/staging/csr/sme_userspace.c delete mode 100644 drivers/staging/csr/sme_userspace.h delete mode 100644 drivers/staging/csr/sme_wext.c delete mode 100644 drivers/staging/csr/ul_int.c delete mode 100644 drivers/staging/csr/unifi_clients.h delete mode 100644 drivers/staging/csr/unifi_config.h delete mode 100644 drivers/staging/csr/unifi_dbg.c delete mode 100644 drivers/staging/csr/unifi_event.c delete mode 100644 drivers/staging/csr/unifi_native.h delete mode 100644 drivers/staging/csr/unifi_os.h delete mode 100644 drivers/staging/csr/unifi_pdu_processing.c delete mode 100644 drivers/staging/csr/unifi_priv.h delete mode 100644 drivers/staging/csr/unifi_sme.c delete mode 100644 drivers/staging/csr/unifi_sme.h delete mode 100644 drivers/staging/csr/unifi_wext.h delete mode 100644 drivers/staging/csr/unifiio.h delete mode 100644 drivers/staging/csr/wext_events.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3227ebeae3f1..57d8b3444600 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -118,8 +118,6 @@ source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/gdm72xx/Kconfig" -source "drivers/staging/csr/Kconfig" - source "drivers/staging/silicom/Kconfig" source "drivers/staging/ced1401/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 4d79ebe2de06..429321f15105 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ -obj-$(CONFIG_CSR_WIFI) += csr/ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ obj-$(CONFIG_CED1401) += ced1401/ obj-$(CONFIG_DRM_IMX) += imx-drm/ diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig deleted file mode 100644 index ad2a1096e920..000000000000 --- a/drivers/staging/csr/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -config CSR_WIFI - tristate "CSR wireless driver" - depends on MMC && CFG80211_WEXT && INET - select WIRELESS_EXT - select WEXT_PRIV - help - Driver for the CSR wireless SDIO device. - - If unsure, select N. diff --git a/drivers/staging/csr/LICENSE.txt b/drivers/staging/csr/LICENSE.txt deleted file mode 100644 index 364853e5fedc..000000000000 --- a/drivers/staging/csr/LICENSE.txt +++ /dev/null @@ -1,39 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -Except as contained in this notice, the names of above-listed -copyright holders and the names of any contributors shall not be used -in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR -CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Alternatively, this software may be distributed under the terms of the -GNU General Public License ("GPL") version 2 as published -by the Free Software Foundation. - -As a special exception, if other files instantiate templates or use -macros or inline functions from this file, or you compile this file -and link it with other works to produce a work based on this file, -this file does not by itself cause the resulting work to be covered by -the GNU General Public License. However the source code for this file -must still be made available in accordance with section (3) of the GNU -General Public License. - -This exception does not invalidate any other reasons why a work based -on this file might be covered by the GNU General Public License. diff --git a/drivers/staging/csr/Makefile b/drivers/staging/csr/Makefile deleted file mode 100644 index dbd135a8b177..000000000000 --- a/drivers/staging/csr/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -ccflags-y := -DCSR_SME_USERSPACE -DCSR_SUPPORT_SME -DREMOTE_SYS_SAP -DCSR_WIFI_SECURITY_WAPI_ENABLE -DENABLE_SHUTDOWN -DUNIFI_DEBUG -ccflags-y += -DSDIO_EXPORTS_STRUCT_DEVICE -DCSR_WIFI_SUPPORT_MMC_DRIVER -DCSR_WIFI_SINGLE_FUNCTION -DCSR_WIFI_SPLIT_PATCH -ccflags-y += -DCSR_SUPPORT_WEXT -DREMOTE_SYS_SAP -DREMOTE_MGT_SAP -DCSR_WIFI_SECURITY_WAPI_ENABLE -DCSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND -DENABLE_SHUTDOWN -DCSR_WIFI_NME_ENABLE -DCSR_WIFI_AP_ENABLE -DCSR_SUPPORT_WEXT_AP -DCSR_WIFI_REQUEUE_PACKET_TO_HAL - -obj-$(CONFIG_CSR_WIFI) += csr_wifi.o -obj-$(CONFIG_CSR_WIFI) += csr_helper.o - -csr_wifi-y := bh.o \ - data_tx.o \ - drv.o \ - firmware.o \ - inet.o \ - init_hw.o \ - io.o \ - monitor.o \ - netdev.o \ - os.o \ - putest.o \ - sdio_events.o \ - sdio_mmc.o \ - sdio_stubs.o \ - sme_blocking.o \ - ul_int.o \ - unifi_dbg.o \ - unifi_event.o \ - unifi_pdu_processing.o \ - unifi_sme.o \ - csr_wifi_hip_card_sdio.o \ - csr_wifi_hip_card_sdio_intr.o \ - csr_wifi_hip_card_sdio_mem.o \ - csr_wifi_hip_chiphelper.o \ - csr_wifi_hip_download.o \ - csr_wifi_hip_dump.o \ - csr_wifi_hip_packing.o \ - csr_wifi_hip_send.o \ - csr_wifi_hip_signals.o \ - csr_wifi_hip_ta_sampling.o \ - csr_wifi_hip_udi.o \ - csr_wifi_hip_unifi_signal_names.o \ - csr_wifi_hip_xbv.o \ - csr_wifi_nme_ap_converter_init.o \ - csr_wifi_nme_ap_free_downstream_contents.o \ - csr_wifi_nme_ap_free_upstream_contents.o \ - csr_wifi_nme_ap_serialize.o \ - csr_wifi_nme_ap_sef.o \ - csr_wifi_router_ctrl_sef.o \ - csr_wifi_router_sef.o \ - csr_wifi_router_transport.o \ - csr_wifi_sme_sef.o \ - csr_wifi_sme_converter_init.o \ - csr_wifi_sme_free_downstream_contents.o \ - csr_wifi_sme_free_upstream_contents.o \ - csr_wifi_sme_serialize.o \ - csr_wifi_router_ctrl_converter_init.o \ - csr_wifi_router_ctrl_free_downstream_contents.o \ - csr_wifi_router_ctrl_free_upstream_contents.o \ - csr_wifi_router_ctrl_serialize.o \ - csr_wifi_router_converter_init.o \ - csr_wifi_router_free_downstream_contents.o \ - csr_wifi_router_free_upstream_contents.o \ - csr_wifi_router_serialize.o \ - sme_mgt.o \ - sme_sys.o \ - sme_userspace.o \ - sme_wext.o \ - wext_events.o - -csr_helper-y := csr_time.o \ - csr_util.o \ - csr_framework_ext.o \ - csr_wifi_serialize_primitive_types.o \ - csr_serialize_primitive_types.o \ - csr_msgconv.o diff --git a/drivers/staging/csr/bh.c b/drivers/staging/csr/bh.c deleted file mode 100644 index d795852ccb1c..000000000000 --- a/drivers/staging/csr/bh.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: bh.c - * - * PURPOSE: - * Provides an implementation for the driver bottom-half. - * It is part of the porting exercise in Linux. - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include "csr_wifi_hip_unifi.h" -#include "unifi_priv.h" -#include - -/* - * --------------------------------------------------------------------------- - * uf_start_thread - * - * Helper function to start a new thread. - * - * Arguments: - * priv Pointer to OS driver structure for the device. - * thread Pointer to the thread object - * func The thread function - * - * Returns: - * 0 on success or else a Linux error code. - * --------------------------------------------------------------------------- - */ -int uf_start_thread(unifi_priv_t *priv, - struct uf_thread *thread, int (*func)(void *)) -{ - if (thread->thread_task != NULL) { - unifi_error(priv, "%s thread already started\n", thread->name); - return 0; - } - - /* Start the kernel thread that handles all h/w accesses. */ - thread->thread_task = kthread_run(func, priv, "%s", thread->name); - if (IS_ERR(thread->thread_task)) - return PTR_ERR(thread->thread_task); - - /* Module parameter overides the thread priority */ - if (bh_priority != -1) { - if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) { - struct sched_param param; - priv->bh_thread.prio = bh_priority; - unifi_trace(priv, UDBG1, - "%s thread (RT) priority = %d\n", - thread->name, bh_priority); - param.sched_priority = bh_priority; - sched_setscheduler(thread->thread_task, - SCHED_FIFO, ¶m); - } else if (bh_priority > MAX_RT_PRIO && - bh_priority <= MAX_PRIO) { - priv->bh_thread.prio = bh_priority; - unifi_trace(priv, UDBG1, "%s thread priority = %d\n", - thread->name, - PRIO_TO_NICE(bh_priority)); - set_user_nice(thread->thread_task, - PRIO_TO_NICE(bh_priority)); - } else { - priv->bh_thread.prio = DEFAULT_PRIO; - unifi_warning(priv, - "%s thread unsupported (%d) priority\n", - thread->name, bh_priority); - } - } else - priv->bh_thread.prio = DEFAULT_PRIO; - unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name); - - return 0; -} /* uf_start_thread() */ - - -/* - * --------------------------------------------------------------------------- - * uf_stop_thread - * - * Helper function to stop a thread. - * - * Arguments: - * priv Pointer to OS driver structure for the device. - * thread Pointer to the thread object - * - * Returns: - * - * --------------------------------------------------------------------------- - */ -void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread) -{ - if (!thread->thread_task) { - unifi_notice(priv, "%s thread is already stopped\n", - thread->name); - return; - } - - unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name); - - kthread_stop(thread->thread_task); - thread->thread_task = NULL; - -} /* uf_stop_thread() */ - - - -/* - * --------------------------------------------------------------------------- - * uf_wait_for_thread_to_stop - * - * Helper function to wait until a thread is stopped. - * - * Arguments: - * priv Pointer to OS driver structure for the device. - * - * Returns: - * - * --------------------------------------------------------------------------- - */ -void -uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread) -{ - /* - * kthread_stop() cannot handle the thread exiting while - * kthread_should_stop() is false, so sleep until kthread_stop() - * wakes us up - */ - unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", - thread->name); - set_current_state(TASK_INTERRUPTIBLE); - if (!kthread_should_stop()) { - unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name); - schedule(); - } - - thread->thread_task = NULL; - unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name); -} /* uf_wait_for_thread_to_stop() */ - - -/* - * --------------------------------------------------------------------------- - * handle_bh_error - * - * This function reports an error returned from the HIP core bottom-half. - * Normally, implemented during the porting exercise, passing the error - * to the SME using unifi_sys_wifi_off_ind(). - * The SME will try to reset the device and go through - * the initialisation of the UniFi. - * - * Arguments: - * priv Pointer to OS driver structure for the device. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -handle_bh_error(unifi_priv_t *priv) -{ - netInterface_priv_t *interfacePriv; - u8 conf_param = CONFIG_IND_ERROR; - u8 interfaceTag; - - - /* Block unifi_run_bh() until the error has been handled. */ - priv->bh_thread.block_thread = 1; - - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; - - /* Stop the network traffic */ - for (interfaceTag = 0; - interfaceTag < CSR_WIFI_NUM_INTERFACES; interfaceTag++) { - interfacePriv = priv->interfacePriv[interfaceTag]; - if (interfacePriv->netdev_registered) - netif_carrier_off(priv->netdev[interfaceTag]); - } - -#ifdef CSR_NATIVE_LINUX - /* Force any client waiting on an mlme_wait_for_reply() to abort. */ - uf_abort_mlme(priv); - - /* Cancel any pending workqueue tasks */ - flush_workqueue(priv->unifi_workqueue); - -#endif /* CSR_NATIVE_LINUX */ - - unifi_error(priv, - "handle_bh_error: fatal error is reported to the SME.\n"); - /* Notify the clients (SME or unifi_manager) for the error. */ - ul_log_config_ind(priv, &conf_param, sizeof(u8)); - -} /* handle_bh_error() */ - - - -/* - * --------------------------------------------------------------------------- - * bh_thread_function - * - * All hardware access happens in this thread. - * This means there is no need for locks on the hardware and we don't need - * to worry about reentrancy with the SDIO library. - * Provides and example implementation on how to call unifi_bh(), which - * is part of the HIP core API. - * - * It processes the events generated by unifi_run_bh() to serialise calls - * to unifi_bh(). It also demonstrates how the timeout parameter passed in - * and returned from unifi_bh() needs to be handled. - * - * Arguments: - * arg Pointer to OS driver structure for the device. - * - * Returns: - * None. - * - * Notes: - * When the bottom half of the driver needs to process signals, events, - * or simply the host status (i.e sleep mode), it invokes unifi_run_bh(). - * Since we need all SDIO transaction to be in a single thread, the - * unifi_run_bh() will wake up this thread to process it. - * - * --------------------------------------------------------------------------- - */ -static int bh_thread_function(void *arg) -{ - unifi_priv_t *priv = (unifi_priv_t *)arg; - CsrResult csrResult; - long ret; - u32 timeout, t; - struct uf_thread *this_thread; - - unifi_trace(priv, UDBG2, "bh_thread_function starting\n"); - - this_thread = &priv->bh_thread; - - t = timeout = 0; - while (!kthread_should_stop()) { - /* - * wait until an error occurs, - * or we need to process something. - */ - unifi_trace(priv, UDBG3, "bh_thread goes to sleep.\n"); - - if (timeout > 0) { - /* Convert t in ms to jiffies */ - t = msecs_to_jiffies(timeout); - ret = wait_event_interruptible_timeout( - this_thread->wakeup_q, - (this_thread->wakeup_flag && !this_thread->block_thread) || - kthread_should_stop(), - t); - timeout = (ret > 0) ? jiffies_to_msecs(ret) : 0; - } else { - ret = wait_event_interruptible(this_thread->wakeup_q, - (this_thread->wakeup_flag && !this_thread->block_thread) || - kthread_should_stop()); - } - - if (kthread_should_stop()) { - unifi_trace(priv, UDBG2, - "bh_thread: signalled to exit\n"); - break; - } - - if (ret < 0) { - unifi_notice(priv, - "bh_thread: wait_event returned %d, thread will exit\n", - ret); - uf_wait_for_thread_to_stop(priv, this_thread); - break; - } - - this_thread->wakeup_flag = 0; - - unifi_trace(priv, UDBG3, "bh_thread calls unifi_bh().\n"); - - CsrSdioClaim(priv->sdio); - csrResult = unifi_bh(priv->card, &timeout); - if (csrResult != CSR_RESULT_SUCCESS) { - if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) { - CsrSdioRelease(priv->sdio); - uf_wait_for_thread_to_stop(priv, this_thread); - break; - } - /* Errors must be delivered to the error task */ - handle_bh_error(priv); - } - CsrSdioRelease(priv->sdio); - } - - /* - * I would normally try to call csr_sdio_remove_irq() here to make sure - * that we do not get any interrupts while this thread is not running. - * However, the MMC/SDIO driver tries to kill its' interrupt thread. - * The kernel threads implementation does not allow to kill threads - * from a signalled to stop thread. - * So, instead call csr_sdio_linux_remove_irq() always after calling - * uf_stop_thread() to kill this thread. - */ - - unifi_trace(priv, UDBG2, "bh_thread exiting....\n"); - return 0; -} /* bh_thread_function() */ - - -/* - * --------------------------------------------------------------------------- - * uf_init_bh - * - * Helper function to start the bottom half of the driver. - * All we need to do here is start the I/O bh thread. - * - * Arguments: - * priv Pointer to OS driver structure for the device. - * - * Returns: - * 0 on success or else a Linux error code. - * --------------------------------------------------------------------------- - */ -int -uf_init_bh(unifi_priv_t *priv) -{ - int r; - - /* Enable mlme interface. */ - priv->io_aborted = 0; - - - /* Start the BH thread */ - r = uf_start_thread(priv, &priv->bh_thread, bh_thread_function); - if (r) { - unifi_error(priv, - "uf_init_bh: failed to start the BH thread.\n"); - return r; - } - - /* Allow interrupts */ - r = csr_sdio_linux_install_irq(priv->sdio); - if (r) { - unifi_error(priv, - "uf_init_bh: failed to install the IRQ.\n"); - - uf_stop_thread(priv, &priv->bh_thread); - } - - return r; -} /* uf_init_bh() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_run_bh - * - * Part of the HIP core lib API, implemented in the porting exercise. - * The bottom half of the driver calls this function when - * it wants to process anything that requires access to unifi. - * We need to call unifi_bh() which in this implementation is done - * by waking up the I/O thread. - * - * Arguments: - * ospriv Pointer to OS driver structure for the device. - * - * Returns: - * 0 on success or else a Linux error code. - * - * Notes: - * --------------------------------------------------------------------------- - */ -CsrResult unifi_run_bh(void *ospriv) -{ - unifi_priv_t *priv = ospriv; - - /* - * If an error has occurred, we discard silently all messages from the bh - * until the error has been processed and the unifi has been - * reinitialised. - */ - if (priv->bh_thread.block_thread == 1) { - unifi_trace(priv, UDBG3, "unifi_run_bh: discard message.\n"); - /* - * Do not try to acknowledge a pending interrupt here. - * This function is called by unifi_send_signal() - * which in turn can be running in an atomic or 'disabled irq' - * level if a signal is sent from a workqueue task - * (i.e multicass addresses set). We can not hold the SDIO lock - * because it might sleep. - */ - return CSR_RESULT_FAILURE; - } - - priv->bh_thread.wakeup_flag = 1; - /* wake up I/O thread */ - wake_up_interruptible(&priv->bh_thread.wakeup_q); - - return CSR_RESULT_SUCCESS; -} /* unifi_run_bh() */ - diff --git a/drivers/staging/csr/csr_framework_ext.c b/drivers/staging/csr/csr_framework_ext.c deleted file mode 100644 index 98122bce1427..000000000000 --- a/drivers/staging/csr/csr_framework_ext.c +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include "csr_framework_ext.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrThreadSleep - * - * DESCRIPTION - * Sleep for a given period. - * - * RETURNS - * void - * - *----------------------------------------------------------------------------*/ -void CsrThreadSleep(u16 sleepTimeInMs) -{ - unsigned long t; - - /* Convert t in ms to jiffies and round up */ - t = ((sleepTimeInMs * HZ) + 999) / 1000; - schedule_timeout_uninterruptible(t); -} -EXPORT_SYMBOL_GPL(CsrThreadSleep); diff --git a/drivers/staging/csr/csr_framework_ext.h b/drivers/staging/csr/csr_framework_ext.h deleted file mode 100644 index 6d26ac6173b0..000000000000 --- a/drivers/staging/csr/csr_framework_ext.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CSR_FRAMEWORK_EXT_H__ -#define CSR_FRAMEWORK_EXT_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_result.h" -#include "csr_framework_ext_types.h" - -/* Result codes */ -#define CSR_FE_RESULT_NO_MORE_EVENTS ((CsrResult) 0x0001) -#define CSR_FE_RESULT_INVALID_POINTER ((CsrResult) 0x0002) -#define CSR_FE_RESULT_INVALID_HANDLE ((CsrResult) 0x0003) -#define CSR_FE_RESULT_NO_MORE_MUTEXES ((CsrResult) 0x0004) -#define CSR_FE_RESULT_TIMEOUT ((CsrResult) 0x0005) -#define CSR_FE_RESULT_NO_MORE_THREADS ((CsrResult) 0x0006) - -/* Thread priorities */ -#define CSR_THREAD_PRIORITY_HIGHEST ((u16) 0) -#define CSR_THREAD_PRIORITY_HIGH ((u16) 1) -#define CSR_THREAD_PRIORITY_NORMAL ((u16) 2) -#define CSR_THREAD_PRIORITY_LOW ((u16) 3) -#define CSR_THREAD_PRIORITY_LOWEST ((u16) 4) - -#define CSR_EVENT_WAIT_INFINITE ((u16) 0xFFFF) - -void CsrThreadSleep(u16 sleepTimeInMs); - -#endif diff --git a/drivers/staging/csr/csr_framework_ext_types.h b/drivers/staging/csr/csr_framework_ext_types.h deleted file mode 100644 index 575598cf69b2..000000000000 --- a/drivers/staging/csr/csr_framework_ext_types.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef CSR_FRAMEWORK_EXT_TYPES_H__ -#define CSR_FRAMEWORK_EXT_TYPES_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifdef __KERNEL__ -#include -#include -#else -#include -#endif - -#ifdef __KERNEL__ - -typedef struct semaphore CsrMutexHandle; - -#else /* __KERNEL __ */ - -typedef pthread_mutex_t CsrMutexHandle; - -#endif /* __KERNEL__ */ - -#endif diff --git a/drivers/staging/csr/csr_log.h b/drivers/staging/csr/csr_log.h deleted file mode 100644 index 982941043ddc..000000000000 --- a/drivers/staging/csr/csr_log.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef CSR_LOG_H__ -#define CSR_LOG_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_sched.h" -#include "csr_prim_defs.h" -#include "csr_msgconv.h" - -/* - * Log filtering - */ - -/*----------------------------------------------------*/ -/* Filtering on environment specific log levels */ -/*----------------------------------------------------*/ -typedef u32 CsrLogLevelEnvironment; -#define CSR_LOG_LEVEL_ENVIRONMENT_OFF ((CsrLogLevelEnvironment) 0x00000000) /* No environment data/events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_ACL ((CsrLogLevelEnvironment) 0x00000001) /* BlueCore Channel Interface HCI Acl data are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_HCI ((CsrLogLevelEnvironment) 0x00000002) /* BlueCore Channel Interface HCI Cmd/Evt data are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_SCO ((CsrLogLevelEnvironment) 0x00000004) /* BlueCore Channel Interface HCI Sco data are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BCI_VENDOR ((CsrLogLevelEnvironment) 0x00000008) /* BlueCore Channel Interface HCI Vendor specific data are logged (This includes BCCMD, HQ, VM etc) */ -#define CSR_LOG_LEVEL_ENVIRONMENT_TRANSPORTS ((CsrLogLevelEnvironment) 0x00000010) /* Transport protocol data is logged (This includes transport protocols like BCSP, H4 etc.) */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_REG ((CsrLogLevelEnvironment) 0x00000020) /* Background Interrupt registration events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_UNREG ((CsrLogLevelEnvironment) 0x00000040) /* Background Interrupt unregistration events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_SET ((CsrLogLevelEnvironment) 0x00000080) /* Background Interrupt set events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_START ((CsrLogLevelEnvironment) 0x00000100) /* Background Interrupt start events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_BGINT_DONE ((CsrLogLevelEnvironment) 0x00000200) /* Background Interrupt done events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_PROTO ((CsrLogLevelEnvironment) 0x00000400) /* Transport protocol events are logged */ -#define CSR_LOG_LEVEL_ENVIRONMENT_PROTO_LOC ((CsrLogLevelEnvironment) 0x00000800) /* The Location where the transport protocol event occurred are logged NB: This is a supplement to CSR_LOG_LEVEL_ENVIRONMENT_PROTO, it has no effect without it */ -/* The bit masks between here are reserved for future usage */ -#define CSR_LOG_LEVEL_ENVIRONMENT_ALL ((CsrLogLevelEnvironment) 0xFFFFFFFF) /* All possible environment data/events are logged WARNING: By using this define the application also accepts future possible environment data/events in the logs */ - -/*----------------------------------------------------*/ -/* Filtering on task specific log levels */ -/*----------------------------------------------------*/ -typedef u32 CsrLogLevelTask; -#define CSR_LOG_LEVEL_TASK_OFF ((CsrLogLevelTask) 0x00000000) /* No events are logged for this task */ -#define CSR_LOG_LEVEL_TASK_TEXT ((CsrLogLevelTask) 0x00000001) /* Text strings printed by a task are logged NB: This bit does not affect the CSR_LOG_TEXT_LEVEL interface. This has to be configured separately */ -#define CSR_LOG_LEVEL_TASK_TEXT_LOC ((CsrLogLevelTask) 0x00000002) /* The locaction where the text string call occurred are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TEXT, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_STATE ((CsrLogLevelTask) 0x00000004) /* FSM state transitions in a task are logged */ -#define CSR_LOG_LEVEL_TASK_STATE_NAME ((CsrLogLevelTask) 0x00000008) /* The name of each state in a FSM state transition are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_STATE, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_STATE_LOC ((CsrLogLevelTask) 0x00000010) /* The location where the FSM state transition occurred are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_STATE, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_TASK_SWITCH ((CsrLogLevelTask) 0x00000020) /* Activation and deactiation of a task are logged */ -#define CSR_LOG_LEVEL_TASK_MESSAGE_PUT ((CsrLogLevelTask) 0x00000080) /* Message put operations are logged */ -#define CSR_LOG_LEVEL_TASK_MESSAGE_PUT_LOC ((CsrLogLevelTask) 0x00000100) /* The location where a message was sent are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_MESSAGE_PUT, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_MESSAGE_GET ((CsrLogLevelTask) 0x00000200) /* Message get operations are logged */ -#define CSR_LOG_LEVEL_TASK_MESSAGE_QUEUE_PUSH ((CsrLogLevelTask) 0x00000400) /* Message push operations are logged */ -#define CSR_LOG_LEVEL_TASK_MESSAGE_QUEUE_POP ((CsrLogLevelTask) 0x00000800) /* Message pop operations are logged */ -#define CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE ((CsrLogLevelTask) 0x00001000) /* Only the type of primitives in messages are logged. By default the entire primitive is serialized and logged */ -#define CSR_LOG_LEVEL_TASK_PRIM_APPLY_LIMIT ((CsrLogLevelTask) 0x00002000) /* An upper limit (defined by CSR_LOG_PRIM_SIZE_UPPER_LIMIT) is applied to how much of a primitive in a message are logged. NB: This limit is only applied if CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE is _not_ defined */ -#define CSR_LOG_LEVEL_TASK_TIMER_IN ((CsrLogLevelTask) 0x00004000) /* TimedEventIn events are logged */ -#define CSR_LOG_LEVEL_TASK_TIMER_IN_LOC ((CsrLogLevelTask) 0x00008000) /* The location where a timer was started are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TIMER_IN, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_TIMER_CANCEL ((CsrLogLevelTask) 0x00010000) /* TimedEventCancel events are logged */ -#define CSR_LOG_LEVEL_TASK_TIMER_CANCEL_LOC ((CsrLogLevelTask) 0x00020000) /* The location where a timer was cancelled are logged. NB: This is a supplement to CSR_LOG_LEVEL_TASK_TIMER_CANCEL, it has no effect without it */ -#define CSR_LOG_LEVEL_TASK_TIMER_FIRE ((CsrLogLevelTask) 0x00040000) /* TimedEventFire events are logged */ -#define CSR_LOG_LEVEL_TASK_TIMER_DONE ((CsrLogLevelTask) 0x00080000) /* TimedEventDone events are logged */ -/* The bit masks between here are reserved for future usage */ -#define CSR_LOG_LEVEL_TASK_ALL ((CsrLogLevelTask) 0xFFFFFFFF & ~(CSR_LOG_LEVEL_TASK_PRIM_ONLY_TYPE | CSR_LOG_LEVEL_TASK_PRIM_APPLY_LIMIT)) /* All info possible to log for a task are logged. WARNING: By using this define the application also accepts future possible task data/events in the logs */ - -u8 CsrLogEnvironmentIsFiltered(CsrLogLevelEnvironment level); -CsrLogLevelTask CsrLogTaskFilterGet(CsrSchedQid taskId); -u8 CsrLogTaskIsFiltered(CsrSchedQid taskId, CsrLogLevelTask level); - -/* - * Logging stuff - */ -#define CSR_LOG_STRINGIFY_REAL(a) (#a) -#define CSR_LOG_STRINGIFY(a) CSR_LOG_STRINGIFY_REAL(a) - -typedef struct { - u16 primitiveType; - const char *primitiveName; - CsrMsgConvMsgEntry *messageConv; /* Private - do not use */ -} CsrLogPrimitiveInformation; - -typedef struct { - const char *techVer; - u32 primitiveInfoCount; - CsrLogPrimitiveInformation *primitiveInfo; -} CsrLogTechInformation; - -/*---------------------------------*/ -/* Tech logging */ -/*---------------------------------*/ -typedef u8 bitmask8_t; -typedef u16 bitmask16_t; -typedef u32 bitmask32_t; - -#ifdef CSR_LOG_ENABLE -#ifdef CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER -/* DEPRECATED - replaced by csr_log_text.h */ -#define CSR_LOG_TEXT(text) \ - do { \ - if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) { \ - CsrLogTaskText(text, __LINE__, __FILE__); \ - } \ - } while (0) -#else -/* DEPRECATED - replaced by csr_log_text.h */ -#define CSR_LOG_TEXT(text) \ - do { \ - if (!CsrLogTaskIsFiltered(CsrSchedTaskQueueGet(), CSR_LOG_LEVEL_TASK_TEXT)) { \ - CsrLogTaskText(text, 0, NULL); \ - } \ - } while (0) -#endif -#else -#define CSR_LOG_TEXT(text) -#endif - -/* DEPRECATED - replaced by csr_log_text.h */ -void CsrLogTaskText(const char *text, - u32 line, - const char *file); - -#define CSR_LOG_STATE_TRANSITION_MASK_FSM_NAME (0x001) -#define CSR_LOG_STATE_TRANSITION_MASK_NEXT_STATE (0x002) -#define CSR_LOG_STATE_TRANSITION_MASK_NEXT_STATE_STR (0x004) -#define CSR_LOG_STATE_TRANSITION_MASK_PREV_STATE (0x008) -#define CSR_LOG_STATE_TRANSITION_MASK_PREV_STATE_STR (0x010) -#define CSR_LOG_STATE_TRANSITION_MASK_EVENT (0x020) -#define CSR_LOG_STATE_TRANSITION_MASK_EVENT_STR (0x040) - -/* DEPRECATED - replaced by csr_log_text.h */ -void CsrLogStateTransition(bitmask16_t mask, - u32 identifier, - const char *fsm_name, - u32 prev_state, - const char *prev_state_str, - u32 in_event, - const char *in_event_str, - u32 next_state, - const char *next_state_str, - u32 line, - const char *file); - -/*---------------------------------*/ -/* BSP logging */ -/*---------------------------------*/ -void CsrLogSchedInit(u8 thread_id); -void CsrLogSchedDeinit(u8 thread_id); - -void CsrLogSchedStart(u8 thread_id); -void CsrLogSchedStop(u8 thread_id); - -void CsrLogInitTask(u8 thread_id, CsrSchedQid tskid, const char *tskName); -void CsrLogDeinitTask(u16 task_id); - -void CsrLogActivate(CsrSchedQid tskid); -void CsrLogDeactivate(CsrSchedQid tskid); - -#define SYNERGY_SERIALIZER_TYPE_DUMP (0x000) -#define SYNERGY_SERIALIZER_TYPE_SER (0x001) - -void CsrLogMessagePut(u32 line, - const char *file, - CsrSchedQid src_task_id, - CsrSchedQid dst_taskid, - CsrSchedMsgId msg_id, - u16 prim_type, - const void *msg); - -void CsrLogMessageGet(CsrSchedQid src_task_id, - CsrSchedQid dst_taskid, - u8 get_res, - CsrSchedMsgId msg_id, - u16 prim_type, - const void *msg); - -void CsrLogTimedEventIn(u32 line, - const char *file, - CsrSchedQid task_id, - CsrSchedTid tid, - u32 requested_delay, - u16 fniarg, - const void *fnvarg); - -void CsrLogTimedEventFire(CsrSchedQid task_id, - CsrSchedTid tid); - -void CsrLogTimedEventDone(CsrSchedQid task_id, - CsrSchedTid tid); - -void CsrLogTimedEventCancel(u32 line, - const char *file, - CsrSchedQid task_id, - CsrSchedTid tid, - u8 cancel_res); - -void CsrLogBgintRegister(u8 thread_id, - CsrSchedBgint irq, - const char *callback, - const void *ptr); -void CsrLogBgintUnregister(CsrSchedBgint irq); -void CsrLogBgintSet(CsrSchedBgint irq); -void CsrLogBgintServiceStart(CsrSchedBgint irq); -void CsrLogBgintServiceDone(CsrSchedBgint irq); - -void CsrLogExceptionStateEvent(u16 prim_type, - CsrPrim msg_type, - u16 state, - u32 line, - const char *file); -void CsrLogExceptionGeneral(u16 prim_type, - u16 state, - const char *text, - u32 line, - const char *file); -void CsrLogExceptionWarning(u16 prim_type, - u16 state, - const char *text, - u32 line, - const char *file); - -#endif diff --git a/drivers/staging/csr/csr_log_configure.h b/drivers/staging/csr/csr_log_configure.h deleted file mode 100644 index 283647cf9702..000000000000 --- a/drivers/staging/csr/csr_log_configure.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef CSR_LOG_CONFIGURE_H__ -#define CSR_LOG_CONFIGURE_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ - -#include "csr_log.h" - -/*--------------------------------------------*/ -/* Filtering on log text warning levels */ -/*--------------------------------------------*/ -typedef u32 CsrLogLevelText; -#define CSR_LOG_LEVEL_TEXT_OFF ((CsrLogLevelText) 0x0000) - -#define CSR_LOG_LEVEL_TEXT_CRITICAL ((CsrLogLevelText) 0x0001) -#define CSR_LOG_LEVEL_TEXT_ERROR ((CsrLogLevelText) 0x0002) -#define CSR_LOG_LEVEL_TEXT_WARNING ((CsrLogLevelText) 0x0004) -#define CSR_LOG_LEVEL_TEXT_INFO ((CsrLogLevelText) 0x0008) -#define CSR_LOG_LEVEL_TEXT_DEBUG ((CsrLogLevelText) 0x0010) - -#define CSR_LOG_LEVEL_TEXT_ALL ((CsrLogLevelText) 0xFFFF) - -/* The log text interface is used by both scheduler tasks and components outside the scheduler context. - * Therefore a CsrLogTextTaskId is introduced. It is effectively considered as two u16's. The lower - * 16 bits corresponds one2one with the scheduler queueId's (CsrSchedQid) and as such these bits can not be used - * by components outside scheduler tasks. The upper 16 bits are allocated for use of components outside the - * scheduler like drivers etc. Components in this range is defined independently by each technology. To avoid - * clashes the technologies are only allowed to assign values within the same restrictive range as allies to - * primitive identifiers. eg. for the framework components outside the scheduler is only allowed to assign - * taskId's in the range 0x0600xxxx to 0x06FFxxxx. And so on for other technologies. */ -typedef u32 CsrLogTextTaskId; - -#endif diff --git a/drivers/staging/csr/csr_log_text.h b/drivers/staging/csr/csr_log_text.h deleted file mode 100644 index cfcf64aa6225..000000000000 --- a/drivers/staging/csr/csr_log_text.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef CSR_LOG_TEXT_H__ -#define CSR_LOG_TEXT_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_log_configure.h" - -typedef struct CsrLogSubOrigin -{ - u16 subOriginNumber; /* Id of the given SubOrigin */ - const char *subOriginName; /* Prefix Text for this SubOrigin */ -} CsrLogSubOrigin; - -/* Register a task which is going to use the CSR_LOG_TEXT_XXX interface */ -#ifdef CSR_LOG_ENABLE -void CsrLogTextRegister(CsrLogTextTaskId taskId, const char *taskName, u16 subOriginsLength, const CsrLogSubOrigin *subOrigins); -#else -#define CsrLogTextRegister(taskId, taskName, subOriginsLength, subOrigins) -#endif - -/* CRITICAL: Conditions that are threatening to the integrity/stability of the - system as a whole. */ -#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_CRITICAL_DISABLE) -void CsrLogTextCritical(CsrLogTextTaskId taskId, u16 subOrigin, const char *formatString, ...); -void CsrLogTextBufferCritical(CsrLogTextTaskId taskId, u16 subOrigin, size_t bufferLength, const void *buffer, const char *formatString, ...); -#define CSR_LOG_TEXT_CRITICAL(taskId_subOrigin_formatString_varargs) CsrLogTextCritical taskId_subOrigin_formatString_varargs -#define CSR_LOG_TEXT_CONDITIONAL_CRITICAL(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_CRITICAL(logtextargs);}} -#define CSR_LOG_TEXT_BUFFER_CRITICAL(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferCritical taskId_subOrigin_length_buffer_formatString_varargs -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_CRITICAL(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_CRITICAL(logtextbufferargs);}} -#else -#define CSR_LOG_TEXT_CRITICAL(taskId_subOrigin_formatString_varargs) -#define CSR_LOG_TEXT_CONDITIONAL_CRITICAL(condition, logtextargs) -#define CSR_LOG_TEXT_BUFFER_CRITICAL(taskId_subOrigin_length_buffer_formatString_varargs) -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_CRITICAL(condition, logtextbufferargs) -#endif - -/* ERROR: Malfunction of a component rendering it unable to operate correctly, - causing lack of functionality but not loss of system integrity/stability. */ -#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_ERROR_DISABLE) -void CsrLogTextError(CsrLogTextTaskId taskId, u16 subOrigin, const char *formatString, ...); -void CsrLogTextBufferError(CsrLogTextTaskId taskId, u16 subOrigin, size_t bufferLength, const void *buffer, const char *formatString, ...); -#define CSR_LOG_TEXT_ERROR(taskId_subOrigin_formatString_varargs) CsrLogTextError taskId_subOrigin_formatString_varargs -#define CSR_LOG_TEXT_CONDITIONAL_ERROR(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_ERROR(logtextargs);}} -#define CSR_LOG_TEXT_BUFFER_ERROR(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferError taskId_subOrigin_length_buffer_formatString_varargs -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_ERROR(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_ERROR(logtextbufferargs);}} -#else -#define CSR_LOG_TEXT_ERROR(taskId_subOrigin_formatString_varargs) -#define CSR_LOG_TEXT_CONDITIONAL_ERROR(condition, logtextargs) -#define CSR_LOG_TEXT_BUFFER_ERROR(taskId_subOrigin_length_buffer_formatString_varargs) -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_ERROR(condition, logtextbufferargs) -#endif - -/* WARNING: Conditions that are unexpected and indicative of possible problems - or violations of specifications, where the result of such deviations does not - lead to malfunction of the component. */ -#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_WARNING_DISABLE) -void CsrLogTextWarning(CsrLogTextTaskId taskId, u16 subOrigin, const char *formatString, ...); -void CsrLogTextBufferWarning(CsrLogTextTaskId taskId, u16 subOrigin, size_t bufferLength, const void *buffer, const char *formatString, ...); -#define CSR_LOG_TEXT_WARNING(taskId_subOrigin_formatString_varargs) CsrLogTextWarning taskId_subOrigin_formatString_varargs -#define CSR_LOG_TEXT_CONDITIONAL_WARNING(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_WARNING(logtextargs);}} -#define CSR_LOG_TEXT_BUFFER_WARNING(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferWarning taskId_subOrigin_length_buffer_formatString_varargs -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_WARNING(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_WARNING(logtextbufferargs);}} -#else -#define CSR_LOG_TEXT_WARNING(taskId_subOrigin_formatString_varargs) -#define CSR_LOG_TEXT_CONDITIONAL_WARNING(condition, logtextargs) -#define CSR_LOG_TEXT_BUFFER_WARNING(taskId_subOrigin_length_buffer_formatString_varargs) -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_WARNING(condition, logtextbufferargs) -#endif - -/* INFO: Important events that may aid in determining the conditions under which - the more severe conditions are encountered. */ -#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_INFO_DISABLE) -void CsrLogTextInfo(CsrLogTextTaskId taskId, u16 subOrigin, const char *formatString, ...); -void CsrLogTextBufferInfo(CsrLogTextTaskId taskId, u16 subOrigin, size_t bufferLength, const void *buffer, const char *formatString, ...); -#define CSR_LOG_TEXT_INFO(taskId_subOrigin_formatString_varargs) CsrLogTextInfo taskId_subOrigin_formatString_varargs -#define CSR_LOG_TEXT_CONDITIONAL_INFO(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_INFO(logtextargs);}} -#define CSR_LOG_TEXT_BUFFER_INFO(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferInfo taskId_subOrigin_length_buffer_formatString_varargs -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_INFO(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_INFO(logtextbufferargs);}} -#else -#define CSR_LOG_TEXT_INFO(taskId_subOrigin_formatString_varargs) -#define CSR_LOG_TEXT_CONDITIONAL_INFO(condition, logtextargs) -#define CSR_LOG_TEXT_BUFFER_INFO(taskId_subOrigin_length_buffer_formatString_varargs) -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_INFO(condition, logtextbufferargs) -#endif - -/* DEBUG: Similar to INFO, but dedicated to events that occur more frequently. */ -#if defined(CSR_LOG_ENABLE) && !defined(CSR_LOG_LEVEL_TEXT_DEBUG_DISABLE) -void CsrLogTextDebug(CsrLogTextTaskId taskId, u16 subOrigin, const char *formatString, ...); -void CsrLogTextBufferDebug(CsrLogTextTaskId taskId, u16 subOrigin, size_t bufferLength, const void *buffer, const char *formatString, ...); -#define CSR_LOG_TEXT_DEBUG(taskId_subOrigin_formatString_varargs) CsrLogTextDebug taskId_subOrigin_formatString_varargs -#define CSR_LOG_TEXT_CONDITIONAL_DEBUG(condition, logtextargs) {if (condition) {CSR_LOG_TEXT_DEBUG(logtextargs);}} -#define CSR_LOG_TEXT_BUFFER_DEBUG(taskId_subOrigin_length_buffer_formatString_varargs) CsrLogTextBufferDebug taskId_subOrigin_length_buffer_formatString_varargs -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_DEBUG(condition, logtextbufferargs) {if (condition) {CSR_LOG_TEXT_BUFFER_DEBUG(logtextbufferargs);}} -#else -#define CSR_LOG_TEXT_DEBUG(taskId_subOrigin_formatString_varargs) -#define CSR_LOG_TEXT_CONDITIONAL_DEBUG(condition, logtextargs) -#define CSR_LOG_TEXT_BUFFER_DEBUG(taskId_subOrigin_length_buffer_formatString_varargs) -#define CSR_LOG_TEXT_BUFFER_CONDITIONAL_DEBUG(condition, logtextbufferargs) -#endif - -/* CSR_LOG_TEXT_ASSERT (CRITICAL) */ -#ifdef CSR_LOG_ENABLE -#define CSR_LOG_TEXT_ASSERT(origin, suborigin, condition) \ - {if (!(condition)) {CSR_LOG_TEXT_CRITICAL((origin, suborigin, "Assertion \"%s\" failed at %s:%u", #condition, __FILE__, __LINE__));}} -#else -#define CSR_LOG_TEXT_ASSERT(origin, suborigin, condition) -#endif - -/* CSR_LOG_TEXT_UNHANDLED_PRIM (CRITICAL) */ -#ifdef CSR_LOG_ENABLE -#define CSR_LOG_TEXT_UNHANDLED_PRIMITIVE(origin, suborigin, primClass, primType) \ - CSR_LOG_TEXT_CRITICAL((origin, suborigin, "Unhandled primitive 0x%04X:0x%04X at %s:%u", primClass, primType, __FILE__, __LINE__)) -#else -#define CSR_LOG_TEXT_UNHANDLED_PRIMITIVE(origin, suborigin, primClass, primType) -#endif - -#endif diff --git a/drivers/staging/csr/csr_macro.h b/drivers/staging/csr/csr_macro.h deleted file mode 100644 index c47f1d91b6fa..000000000000 --- a/drivers/staging/csr/csr_macro.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef CSR_MACRO_H__ -#define CSR_MACRO_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include - -#define FALSE (0) -#define TRUE (1) - -/*------------------------------------------------------------------*/ -/* Endian conversion */ -/*------------------------------------------------------------------*/ -#define CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr) (((u16) ((u8 *) (ptr))[0]) | ((u16) ((u8 *) (ptr))[1]) << 8) -#define CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr) (((u32) ((u8 *) (ptr))[0]) | ((u32) ((u8 *) (ptr))[1]) << 8 | \ - ((u32) ((u8 *) (ptr))[2]) << 16 | ((u32) ((u8 *) (ptr))[3]) << 24) -#define CSR_COPY_UINT16_TO_LITTLE_ENDIAN(uint, ptr) ((u8 *) (ptr))[0] = ((u8) ((uint) & 0x00FF)); \ - ((u8 *) (ptr))[1] = ((u8) ((uint) >> 8)) -#define CSR_COPY_UINT32_TO_LITTLE_ENDIAN(uint, ptr) ((u8 *) (ptr))[0] = ((u8) ((uint) & 0x000000FF)); \ - ((u8 *) (ptr))[1] = ((u8) (((uint) >> 8) & 0x000000FF)); \ - ((u8 *) (ptr))[2] = ((u8) (((uint) >> 16) & 0x000000FF)); \ - ((u8 *) (ptr))[3] = ((u8) (((uint) >> 24) & 0x000000FF)) - -/*------------------------------------------------------------------*/ -/* Misc */ -/*------------------------------------------------------------------*/ -/* Use this macro on unused local variables that cannot be removed (such as - unused function parameters). This will quell warnings from certain compilers - and static code analysis tools like Lint and Valgrind. */ -#define CSR_UNUSED(x) ((void) (x)) - -#endif diff --git a/drivers/staging/csr/csr_msg_transport.h b/drivers/staging/csr/csr_msg_transport.h deleted file mode 100644 index 8d88e7836567..000000000000 --- a/drivers/staging/csr/csr_msg_transport.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef CSR_MSG_TRANSPORT_H__ -#define CSR_MSG_TRANSPORT_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CsrMsgTransport -#define CsrMsgTransport CsrSchedMessagePut -#endif - -#endif /* CSR_MSG_TRANSPORT */ diff --git a/drivers/staging/csr/csr_msgconv.c b/drivers/staging/csr/csr_msgconv.c deleted file mode 100644 index db5e845e60f5..000000000000 --- a/drivers/staging/csr/csr_msgconv.c +++ /dev/null @@ -1,291 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include -#include -#include "csr_sched.h" -#include "csr_msgconv.h" -#include "csr_macro.h" - -static CsrMsgConvEntry *converter; - -CsrMsgConvPrimEntry *CsrMsgConvFind(u16 primType) -{ - CsrMsgConvPrimEntry *ptr = NULL; - - if (converter) - { - ptr = converter->profile_converters; - while (ptr) - { - if (ptr->primType == primType) - { - break; - } - else - { - ptr = ptr->next; - } - } - } - - return ptr; -} - -static const CsrMsgConvMsgEntry *find_msg_converter(CsrMsgConvPrimEntry *ptr, u16 msgType) -{ - const CsrMsgConvMsgEntry *cv = ptr->conv; - if (ptr->lookupFunc) - { - return (const CsrMsgConvMsgEntry *) ptr->lookupFunc((CsrMsgConvMsgEntry *) cv, msgType); - } - - while (cv) - { - if (cv->serFunc == NULL) - { - /* We've reached the end of the chain */ - cv = NULL; - break; - } - - if (cv->msgType == msgType) - { - break; - } - else - { - cv++; - } - } - - return cv; -} - -static void *deserialize_data(u16 primType, - size_t length, - u8 *data) -{ - CsrMsgConvPrimEntry *ptr; - u8 *ret; - - ptr = CsrMsgConvFind(primType); - - if (ptr) - { - const CsrMsgConvMsgEntry *cv; - u16 msgId = 0; - size_t offset = 0; - CsrUint16Des(&msgId, data, &offset); - - cv = find_msg_converter(ptr, msgId); - if (cv) - { - ret = cv->deserFunc(data, length); - } - else - { - ret = NULL; - } - } - else - { - ret = NULL; - } - - return ret; -} - -static size_t sizeof_message(u16 primType, void *msg) -{ - CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); - size_t ret; - - if (ptr) - { - const CsrMsgConvMsgEntry *cv; - u16 msgId = *(u16 *) msg; - - cv = find_msg_converter(ptr, msgId); - if (cv) - { - ret = cv->sizeofFunc(msg); - } - else - { - ret = 0; - } - } - else - { - ret = 0; - } - - return ret; -} - -static u8 free_message(u16 primType, u8 *data) -{ - CsrMsgConvPrimEntry *ptr; - u8 ret; - - ptr = CsrMsgConvFind(primType); - - if (ptr) - { - const CsrMsgConvMsgEntry *cv; - u16 msgId = *(u16 *) data; - - cv = find_msg_converter(ptr, msgId); - if (cv) - { - cv->freeFunc(data); - ret = TRUE; - } - else - { - ret = FALSE; - } - } - else - { - ret = FALSE; - } - - return ret; -} - -static u8 *serialize_message(u16 primType, - void *msg, - size_t *length, - u8 *buffer) -{ - CsrMsgConvPrimEntry *ptr; - u8 *ret; - - ptr = CsrMsgConvFind(primType); - - *length = 0; - - if (ptr) - { - const CsrMsgConvMsgEntry *cv; - - cv = find_msg_converter(ptr, *(u16 *) msg); - if (cv) - { - ret = cv->serFunc(buffer, length, msg); - } - else - { - ret = NULL; - } - } - else - { - ret = NULL; - } - - return ret; -} - -size_t CsrMsgConvSizeof(u16 primType, void *msg) -{ - return sizeof_message(primType, msg); -} - -u8 *CsrMsgConvSerialize(u8 *buffer, size_t maxBufferOffset, size_t *offset, u16 primType, void *msg) -{ - if (converter) - { - size_t serializedLength; - u8 *bufSerialized; - u8 *bufOffset = &buffer[*offset]; - bufSerialized = converter->serialize_message(primType, msg, &serializedLength, bufOffset); - *offset += serializedLength; - return bufSerialized; - } - else - { - return NULL; - } -} - -/* Insert profile converter at head of converter list. */ -void CsrMsgConvInsert(u16 primType, const CsrMsgConvMsgEntry *ce) -{ - CsrMsgConvPrimEntry *pc; - pc = CsrMsgConvFind(primType); - - if (pc) - { - /* Already registered. Do nothing */ - } - else - { - pc = kmalloc(sizeof(*pc), GFP_KERNEL); - pc->primType = primType; - pc->conv = ce; - pc->lookupFunc = NULL; - pc->next = converter->profile_converters; - converter->profile_converters = pc; - } -} -EXPORT_SYMBOL_GPL(CsrMsgConvInsert); - -CsrMsgConvMsgEntry *CsrMsgConvFindEntry(u16 primType, u16 msgType) -{ - CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); - if (ptr) - { - return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType); - } - return NULL; -} -EXPORT_SYMBOL_GPL(CsrMsgConvFindEntry); - -CsrMsgConvMsgEntry *CsrMsgConvFindEntryByMsg(u16 primType, const void *msg) -{ - CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); - if (ptr && msg) - { - u16 msgType = *((u16 *) msg); - return (CsrMsgConvMsgEntry *) find_msg_converter(ptr, msgType); - } - return NULL; -} - -void CsrMsgConvCustomLookupRegister(u16 primType, CsrMsgCustomLookupFunc *lookupFunc) -{ - CsrMsgConvPrimEntry *ptr = CsrMsgConvFind(primType); - if (ptr) - { - ptr->lookupFunc = lookupFunc; - } -} -EXPORT_SYMBOL_GPL(CsrMsgConvCustomLookupRegister); - -CsrMsgConvEntry *CsrMsgConvInit(void) -{ - if (!converter) - { - converter = kmalloc(sizeof(CsrMsgConvEntry), GFP_KERNEL); - - converter->profile_converters = NULL; - converter->free_message = free_message; - converter->sizeof_message = sizeof_message; - converter->serialize_message = serialize_message; - converter->deserialize_data = deserialize_data; - } - - return converter; -} -EXPORT_SYMBOL_GPL(CsrMsgConvInit); diff --git a/drivers/staging/csr/csr_msgconv.h b/drivers/staging/csr/csr_msgconv.h deleted file mode 100644 index 7e4dd388ae37..000000000000 --- a/drivers/staging/csr/csr_msgconv.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef CSR_MSGCONV_H__ -#define CSR_MSGCONV_H__ - -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" - -typedef size_t (CsrMsgSizeofFunc)(void *msg); -typedef u8 *(CsrMsgSerializeFunc)(u8 *buffer, size_t *length, void *msg); -typedef void (CsrMsgFreeFunc)(void *msg); -typedef void *(CsrMsgDeserializeFunc)(u8 *buffer, size_t length); - -/* Converter entry for one message type */ -typedef struct CsrMsgConvMsgEntry -{ - u16 msgType; - CsrMsgSizeofFunc *sizeofFunc; - CsrMsgSerializeFunc *serFunc; - CsrMsgDeserializeFunc *deserFunc; - CsrMsgFreeFunc *freeFunc; -} CsrMsgConvMsgEntry; - -/* Optional lookup function */ -typedef CsrMsgConvMsgEntry *(CsrMsgCustomLookupFunc)(CsrMsgConvMsgEntry *ce, u16 msgType); - -/* All converter entries for one specific primitive */ -typedef struct CsrMsgConvPrimEntry -{ - u16 primType; - const CsrMsgConvMsgEntry *conv; - CsrMsgCustomLookupFunc *lookupFunc; - struct CsrMsgConvPrimEntry *next; -} CsrMsgConvPrimEntry; - -typedef struct -{ - CsrMsgConvPrimEntry *profile_converters; - void *(*deserialize_data)(u16 primType, size_t length, u8 * data); - u8 (*free_message)(u16 primType, u8 *data); - size_t (*sizeof_message)(u16 primType, void *msg); - u8 *(*serialize_message)(u16 primType, void *msg, - size_t * length, - u8 * buffer); -} CsrMsgConvEntry; - -size_t CsrMsgConvSizeof(u16 primType, void *msg); -u8 *CsrMsgConvSerialize(u8 *buffer, size_t maxBufferOffset, size_t *offset, u16 primType, void *msg); -void CsrMsgConvCustomLookupRegister(u16 primType, CsrMsgCustomLookupFunc *lookupFunc); -void CsrMsgConvInsert(u16 primType, const CsrMsgConvMsgEntry *ce); -CsrMsgConvPrimEntry *CsrMsgConvFind(u16 primType); -CsrMsgConvMsgEntry *CsrMsgConvFindEntry(u16 primType, u16 msgType); -CsrMsgConvMsgEntry *CsrMsgConvFindEntryByMsg(u16 primType, const void *msg); -CsrMsgConvEntry *CsrMsgConvInit(void); - -/* Prototypes for primitive type serializers */ -void CsrUint8Ser(u8 *buffer, size_t *offset, u8 value); -void CsrUint16Ser(u8 *buffer, size_t *offset, u16 value); -void CsrUint32Ser(u8 *buffer, size_t *offset, u32 value); -void CsrMemCpySer(u8 *buffer, size_t *offset, const void *value, size_t length); -void CsrCharStringSer(u8 *buffer, size_t *offset, const char *value); - -void CsrUint8Des(u8 *value, u8 *buffer, size_t *offset); -void CsrUint16Des(u16 *value, u8 *buffer, size_t *offset); -void CsrUint32Des(u32 *value, u8 *buffer, size_t *offset); -void CsrMemCpyDes(void *value, u8 *buffer, size_t *offset, size_t length); -void CsrCharStringDes(char **value, u8 *buffer, size_t *offset); - -#endif diff --git a/drivers/staging/csr/csr_prim_defs.h b/drivers/staging/csr/csr_prim_defs.h deleted file mode 100644 index 81a1eaac30d9..000000000000 --- a/drivers/staging/csr/csr_prim_defs.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CSR_PRIM_DEFS_H__ -#define CSR_PRIM_DEFS_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/************************************************************************************ - * Segmentation of primitives in upstream and downstream segment - ************************************************************************************/ -typedef u16 CsrPrim; -#define CSR_PRIM_UPSTREAM ((CsrPrim) (0x8000)) - -/************************************************************************************ - * Primitive definitions for Synergy framework - ************************************************************************************/ -#define CSR_SYNERGY_EVENT_CLASS_BASE ((u16) (0x0600)) - -#define CSR_HCI_PRIM ((u16) (0x0000 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_BCCMD_PRIM ((u16) (0x0001 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_HQ_PRIM ((u16) (0x0002 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_VM_PRIM ((u16) (0x0003 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_TM_BLUECORE_PRIM ((u16) (0x0004 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_FP_PRIM ((u16) (0x0005 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_IP_SOCKET_PRIM ((u16) (0x0006 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_IP_ETHER_PRIM ((u16) (0x0007 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_IP_IFCONFIG_PRIM ((u16) (0x0008 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_IP_INTERNAL_PRIM ((u16) (0x0009 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_FSAL_PRIM ((u16) (0x000A | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_DATA_STORE_PRIM ((u16) (0x000B | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_AM_PRIM ((u16) (0x000C | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_TLS_PRIM ((u16) (0x000D | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_DHCP_SERVER_PRIM ((u16) (0x000E | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_TFTP_PRIM ((u16) (0x000F | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_DSPM_PRIM ((u16) (0x0010 | CSR_SYNERGY_EVENT_CLASS_BASE)) -#define CSR_TLS_INTERNAL_PRIM ((u16) (0x0011 | CSR_SYNERGY_EVENT_CLASS_BASE)) - -#define NUMBER_OF_CSR_FW_EVENTS (CSR_DSPM_PRIM - CSR_SYNERGY_EVENT_CLASS_BASE + 1) - -#define CSR_SYNERGY_EVENT_CLASS_MISC_BASE ((u16) (0x06A0)) - -#define CSR_UI_PRIM ((u16) (0x0000 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) -#define CSR_APP_PRIM ((u16) (0x0001 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) -#define CSR_SDIO_PROBE_PRIM ((u16) (0x0002 | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) - -#define NUMBER_OF_CSR_FW_MISC_EVENTS (CSR_SDIO_PROBE_PRIM - CSR_SYNERGY_EVENT_CLASS_MISC_BASE + 1) - -#define CSR_ENV_PRIM ((u16) (0x00FF | CSR_SYNERGY_EVENT_CLASS_MISC_BASE)) - -#endif /* CSR_PRIM_DEFS_H__ */ diff --git a/drivers/staging/csr/csr_result.h b/drivers/staging/csr/csr_result.h deleted file mode 100644 index cbb607d943c7..000000000000 --- a/drivers/staging/csr/csr_result.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef CSR_RESULT_H__ -#define CSR_RESULT_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -typedef u16 CsrResult; -#define CSR_RESULT_SUCCESS ((CsrResult) 0x0000) -#define CSR_RESULT_FAILURE ((CsrResult) 0xFFFF) - -#endif diff --git a/drivers/staging/csr/csr_sched.h b/drivers/staging/csr/csr_sched.h deleted file mode 100644 index c7d672c59f5b..000000000000 --- a/drivers/staging/csr/csr_sched.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef CSR_SCHED_H__ -#define CSR_SCHED_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ -#include -#include "csr_time.h" - -/* An identifier issued by the scheduler. */ -typedef u32 CsrSchedIdentifier; - -/* A task identifier */ -typedef u16 CsrSchedTaskId; - -/* A queue identifier */ -typedef u16 CsrSchedQid; - -/* A message identifier */ -typedef CsrSchedIdentifier CsrSchedMsgId; - -/* A timer event identifier */ -typedef CsrSchedIdentifier CsrSchedTid; -#define CSR_SCHED_TID_INVALID ((CsrSchedTid) 0) - -/* Time constants. */ -#define CSR_SCHED_TIME_MAX (0xFFFFFFFF) -#define CSR_SCHED_MILLISECOND (1000) -#define CSR_SCHED_SECOND (1000 * CSR_SCHED_MILLISECOND) -#define CSR_SCHED_MINUTE (60 * CSR_SCHED_SECOND) - -/* Queue and primitive that identifies the environment */ -#define CSR_SCHED_TASK_ID 0xFFFF -#define CSR_SCHED_PRIM (CSR_SCHED_TASK_ID) -#define CSR_SCHED_EXCLUDED_MODULE_QUEUE 0xFFFF - -/* - * Background interrupt definitions - */ -typedef u16 CsrSchedBgint; -#define CSR_SCHED_BGINT_INVALID ((CsrSchedBgint) 0xFFFF) - -/*----------------------------------------------------------------------------* - * NAME - * CsrSchedMessagePut - * - * DESCRIPTION - * Sends a message consisting of the integer "mi" and the void * pointer - * "mv" to the message queue "q". - * - * "mi" and "mv" are neither inspected nor changed by the scheduler - the - * task that owns "q" is expected to make sense of the values. "mv" may - * be null. - * - * NOTE - * If "mv" is not null then it will typically be a chunk of kmalloc()ed - * memory, though there is no need for it to be so. Tasks should normally - * obey the convention that when a message built with kmalloc()ed memory - * is given to CsrSchedMessagePut() then ownership of the memory is ceded to the - * scheduler - and eventually to the recipient task. I.e., the receiver of - * the message will be expected to kfree() the message storage. - * - * RETURNS - * void. - * - *----------------------------------------------------------------------------*/ -#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) -void CsrSchedMessagePutStringLog(CsrSchedQid q, - u16 mi, - void *mv, - u32 line, - const char *file); -#define CsrSchedMessagePut(q, mi, mv) CsrSchedMessagePutStringLog((q), (mi), (mv), __LINE__, __FILE__) -#else -void CsrSchedMessagePut(CsrSchedQid q, - u16 mi, - void *mv); -#endif - -#endif diff --git a/drivers/staging/csr/csr_sdio.h b/drivers/staging/csr/csr_sdio.h deleted file mode 100644 index 0971d135abf6..000000000000 --- a/drivers/staging/csr/csr_sdio.h +++ /dev/null @@ -1,723 +0,0 @@ -#ifndef CSR_SDIO_H__ -#define CSR_SDIO_H__ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_result.h" - -/* Result Codes */ -#define CSR_SDIO_RESULT_INVALID_VALUE ((CsrResult) 1) /* Invalid argument value */ -#define CSR_SDIO_RESULT_NO_DEVICE ((CsrResult) 2) /* The specified device is no longer present */ -#define CSR_SDIO_RESULT_CRC_ERROR ((CsrResult) 3) /* The transmitted/received data or command response contained a CRC error */ -#define CSR_SDIO_RESULT_TIMEOUT ((CsrResult) 4) /* No command response or data received from device, or function enable/disable did not succeed within timeout period */ -#define CSR_SDIO_RESULT_NOT_RESET ((CsrResult) 5) /* The device was not reset */ - -/* Features (for use in features member of CsrSdioFunction) */ -#define CSR_SDIO_FEATURE_BYTE_MODE 0x00000001 /* Transfer sizes do not have to be a multiple of block size */ -#define CSR_SDIO_FEATURE_DMA_CAPABLE_MEM_REQUIRED 0x00000002 /* Bulk operations require DMA friendly memory */ - -/* CsrSdioFunctionId wildcards (for use in CsrSdioFunctionId members) */ -#define CSR_SDIO_ANY_MANF_ID 0xFFFF -#define CSR_SDIO_ANY_CARD_ID 0xFFFF -#define CSR_SDIO_ANY_SDIO_FUNCTION 0xFF -#define CSR_SDIO_ANY_SDIO_INTERFACE 0xFF - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionId - * - * DESCRIPTION - * This structure describes one or more functions of a device, based on - * four qualitative measures. The CsrSdioFunctionId wildcard defines can be - * used for making the CsrSdioFunctionId match more than one function. - * - * MEMBERS - * manfId - Vendor ID (or CSR_SDIO_ANY_MANF_ID). - * cardId - Device ID (or CSR_SDIO_ANY_CARD_ID). - * sdioFunction - SDIO Function number (or CSR_SDIO_ANY_SDIO_FUNCTION). - * sdioInterface - SDIO Standard Interface Code (or CSR_SDIO_ANY_SDIO_INTERFACE) - * - *----------------------------------------------------------------------------*/ -typedef struct -{ - u16 manfId; /* Vendor ID to match or CSR_SDIO_ANY_MANF_ID */ - u16 cardId; /* Device ID to match or CSR_SDIO_ANY_CARD_ID */ - u8 sdioFunction; /* SDIO Function number to match or CSR_SDIO_ANY_SDIO_FUNCTION */ - u8 sdioInterface; /* SDIO Standard Interface Code to match or CSR_SDIO_ANY_SDIO_INTERFACE */ -} CsrSdioFunctionId; - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunction - * - * DESCRIPTION - * This structure represents a single function on a device. - * - * MEMBERS - * sdioId - A CsrSdioFunctionId describing this particular function. The - * subfield shall not contain any CsrSdioFunctionId wildcards. The - * subfields shall describe the specific single function - * represented by this structure. - * blockSize - Actual configured block size, or 0 if unconfigured. - * features - Bit mask with any of CSR_SDIO_FEATURE_* set. - * device - Handle of device containing the function. If two functions have - * the same device handle, they reside on the same device. - * driverData - For use by the Function Driver. The SDIO Driver shall not - * attempt to dereference the pointer. - * priv - For use by the SDIO Driver. The Function Driver shall not attempt - * to dereference the pointer. - * - * - *----------------------------------------------------------------------------*/ -typedef struct -{ - CsrSdioFunctionId sdioId; - u16 blockSize; /* Actual configured block size, or 0 if unconfigured */ - u32 features; /* Bit mask with any of CSR_SDIO_FEATURE_* set */ - void *device; /* Handle of device containing the function */ - void *driverData; /* For use by the Function Driver */ - void *priv; /* For use by the SDIO Driver */ -} CsrSdioFunction; - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioInsertedCallback, CsrSdioRemovedCallback - * - * DESCRIPTION - * CsrSdioInsertedCallback is called when a function becomes available to - * a registered Function Driver that supports the function. - * CsrSdioRemovedCallback is called when a function is no longer available - * to a Function Driver, either because the device has been removed, or the - * Function Driver has been unregistered. - * - * NOTE: These functions are implemented by the Function Driver, and are - * passed as function pointers in the CsrSdioFunctionDriver struct. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - *----------------------------------------------------------------------------*/ -typedef void (*CsrSdioInsertedCallback)(CsrSdioFunction *function); -typedef void (*CsrSdioRemovedCallback)(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioInterruptDsrCallback, CsrSdioInterruptCallback - * - * DESCRIPTION - * CsrSdioInterruptCallback is called when an interrupt occurs on the - * the device associated with the specified function. - * - * NOTE: These functions are implemented by the Function Driver, and are - * passed as function pointers in the CsrSdioFunctionDriver struct. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - * RETURNS (only CsrSdioInterruptCallback) - * A pointer to a CsrSdioInterruptDsrCallback function. - * - *----------------------------------------------------------------------------*/ -typedef void (*CsrSdioInterruptDsrCallback)(CsrSdioFunction *function); -typedef CsrSdioInterruptDsrCallback (*CsrSdioInterruptCallback)(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioSuspendCallback, CsrSdioResumeCallback - * - * DESCRIPTION - * CsrSdioSuspendCallback is called when the system is preparing to go - * into a suspended state. CsrSdioResumeCallback is called when the system - * has entered an active state again. - * - * NOTE: These functions are implemented by the Function Driver, and are - * passed as function pointers in the CsrSdioFunctionDriver struct. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - *----------------------------------------------------------------------------*/ -typedef void (*CsrSdioSuspendCallback)(CsrSdioFunction *function); -typedef void (*CsrSdioResumeCallback)(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioAsyncCallback, CsrSdioAsyncDsrCallback - * - * DESCRIPTION - * CsrSdioAsyncCallback is called when an asynchronous operation completes. - * - * NOTE: These functions are implemented by the Function Driver, and are - * passed as function pointers in the function calls that initiate - * the operation. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * result - The result of the operation that completed. See the description - * of the initiating function for possible result values. - * - * RETURNS (only CsrSdioAsyncCallback) - * A pointer to a CsrSdioAsyncDsrCallback function. - * - *----------------------------------------------------------------------------*/ -typedef void (*CsrSdioAsyncDsrCallback)(CsrSdioFunction *function, CsrResult result); -typedef CsrSdioAsyncDsrCallback (*CsrSdioAsyncCallback)(CsrSdioFunction *function, CsrResult result); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionDriver - * - * DESCRIPTION - * Structure representing a Function Driver. - * - * MEMBERS - * inserted - Callback, see description of CsrSdioInsertedCallback. - * removed - Callback, see description of CsrSdioRemovedCallback. - * intr - Callback, see description of CsrSdioInterruptCallback. - * suspend - Callback, see description of CsrSdioSuspendCallback. - * resume - Callback, see description of CsrSdioResumeCallback. - * ids - Array of CsrSdioFunctionId describing one or more functions that - * are supported by the Function Driver. - * idsCount - Length of the ids array. - * priv - For use by the SDIO Driver. The Function Driver may initialise - * it to NULL, but shall otherwise not access the pointer or attempt - * to dereference it. - * - *----------------------------------------------------------------------------*/ -typedef struct -{ - CsrSdioInsertedCallback inserted; - CsrSdioRemovedCallback removed; - CsrSdioInterruptCallback intr; - CsrSdioSuspendCallback suspend; - CsrSdioResumeCallback resume; - CsrSdioFunctionId *ids; - u8 idsCount; - void *priv; /* For use by the SDIO Driver */ -} CsrSdioFunctionDriver; - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionDriverRegister - * - * DESCRIPTION - * Register a Function Driver. - * - * PARAMETERS - * functionDriver - Pointer to struct describing the Function Driver. - * - * RETURNS - * CSR_RESULT_SUCCESS - The Function Driver was successfully - * registered. - * CSR_RESULT_FAILURE - Unable to register the function driver, - * because of an unspecified/unknown error. The - * Function Driver has not been registered. - * CSR_SDIO_RESULT_INVALID_VALUE - The specified Function Driver pointer - * does not point at a valid Function - * Driver structure, or some of the members - * contain invalid entries. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *functionDriver); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionDriverUnregister - * - * DESCRIPTION - * Unregister a previously registered Function Driver. - * - * PARAMETERS - * functionDriver - pointer to struct describing the Function Driver. - * - *----------------------------------------------------------------------------*/ -void CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *functionDriver); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionEnable, CsrSdioFunctionDisable - * - * DESCRIPTION - * Enable/disable the specified function by setting/clearing the - * corresponding bit in the I/O Enable register in function 0, and then - * periodically reading the related bit in the I/O Ready register until it - * is set/clear, limited by an implementation defined timeout. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - * RETURNS - * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. The state of the - * related bit in the I/O Enable register is - * undefined. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device, or the related - * bit in the I/O ready register was not - * set/cleared within the timeout period. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioFunctionEnable(CsrSdioFunction *function); -CsrResult CsrSdioFunctionDisable(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioInterruptEnable, CsrSdioInterruptDisable - * - * DESCRIPTION - * Enable/disable the interrupt for the specified function by - * setting/clearing the corresponding bit in the INT Enable register in - * function 0. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - * RETURNS - * CSR_RESULT_SUCCESS - The specified function was enabled/disabled. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. The state of the - * related bit in the INT Enable register is - * unchanged. - * CSR_SDIO_RESULT_INVALID_VALUE - The specified function cannot be - * enabled/disabled, because it either - * does not exist or it is not possible to - * individually enable/disable functions. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioInterruptEnable(CsrSdioFunction *function); -CsrResult CsrSdioInterruptDisable(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioInterruptAcknowledge - * - * DESCRIPTION - * Acknowledge that a signalled interrupt has been handled. Shall only - * be called once, and exactly once for each signalled interrupt to the - * corresponding function. - * - * PARAMETERS - * function - Pointer to struct representing the function to which the - * event was signalled. - * - *----------------------------------------------------------------------------*/ -void CsrSdioInterruptAcknowledge(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioInsertedAcknowledge, CsrSdioRemovedAcknowledge - * - * DESCRIPTION - * Acknowledge that a signalled inserted/removed event has been handled. - * Shall only be called once, and exactly once for each signalled event to - * the corresponding function. - * - * PARAMETERS - * function - Pointer to struct representing the function to which the - * inserted was signalled. - * result (CsrSdioInsertedAcknowledge only) - * CSR_RESULT_SUCCESS - The Function Driver has accepted the - * function, and the function is attached to - * the Function Driver until the - * CsrSdioRemovedCallback is called and - * acknowledged. - * CSR_RESULT_FAILURE - Unable to accept the function. The - * function is not attached to the Function - * Driver, and it may be passed to another - * Function Driver which supports the - * function. - * - *----------------------------------------------------------------------------*/ -void CsrSdioInsertedAcknowledge(CsrSdioFunction *function, CsrResult result); -void CsrSdioRemovedAcknowledge(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioSuspendAcknowledge, CsrSdioResumeAcknowledge - * - * DESCRIPTION - * Acknowledge that a signalled suspend event has been handled. Shall only - * be called once, and exactly once for each signalled event to the - * corresponding function. - * - * PARAMETERS - * function - Pointer to struct representing the function to which the - * event was signalled. - * result - * CSR_RESULT_SUCCESS - Successfully suspended/resumed. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * - *----------------------------------------------------------------------------*/ -void CsrSdioSuspendAcknowledge(CsrSdioFunction *function, CsrResult result); -void CsrSdioResumeAcknowledge(CsrSdioFunction *function, CsrResult result); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioBlockSizeSet - * - * DESCRIPTION - * Set the block size to use for the function. The actual configured block - * size shall be the minimum of: - * 1) Maximum block size supported by the function. - * 2) Maximum block size supported by the host controller. - * 3) The block size specified by the blockSize argument. - * - * When this function returns, the actual configured block size is - * available in the blockSize member of the function struct. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * blockSize - Block size to use for the function. Valid range is 1 to - * 2048. - * - * RETURNS - * CSR_RESULT_SUCCESS - The block size register on the chip - * was updated. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. The configured block - * size is undefined. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER - * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. - * If the ERROR bit is set (but not FUNCTION_NUMBER), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * NOTE: Setting the block size requires two individual operations. The - * implementation shall ignore the OUT_OF_RANGE bit of the SDIO R5 - * response for the first operation, as the partially configured - * block size may be out of range, even if the final block size - * (after the second operation) is in the valid range. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioBlockSizeSet(CsrSdioFunction *function, u16 blockSize); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioMaxBusClockFrequencySet - * - * DESCRIPTION - * Set the maximum clock frequency to use for the device associated with - * the specified function. The actual configured clock frequency for the - * device shall be the minimum of: - * 1) Maximum clock frequency supported by the device. - * 2) Maximum clock frequency supported by the host controller. - * 3) Maximum clock frequency specified for any function on the same - * device. - * - * If the clock frequency exceeds 25MHz, it is the responsibility of the - * SDIO driver to enable high speed mode on the device, using the standard - * defined procedure, before increasing the frequency beyond the limit. - * - * Note that the clock frequency configured affects all functions on the - * same device. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * maxFrequency - The maximum clock frequency for the function in Hertz. - * - * RETURNS - * CSR_RESULT_SUCCESS - The maximum clock frequency was successfully - * set for the function. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * - * NOTE: If the SDIO R5 response is available, and the FUNCTION_NUMBER - * bits is set, CSR_SDIO_RESULT_INVALID_VALUE shall be returned. - * If the ERROR bit is set (but not FUNCTION_NUMBER), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, u32 maxFrequency); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioRead8, CsrSdioWrite8, CsrSdioRead8Async, CsrSdioWrite8Async - * - * DESCRIPTION - * Read/write an 8bit value from/to the specified register address. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * address - Register address within the function. - * data - The data to read/write. - * callback - The function to call on operation completion. - * - * RETURNS - * CSR_RESULT_SUCCESS - The data was successfully read/written. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. No data read/written. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * NOTE: The CsrSdioRead8Async and CsrSdioWrite8Async functions return - * immediately, and the supplied callback function is called when the - * operation is complete. The result value is given as an argument to - * the callback function. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioRead8(CsrSdioFunction *function, u32 address, u8 *data); -CsrResult CsrSdioWrite8(CsrSdioFunction *function, u32 address, u8 data); -void CsrSdioRead8Async(CsrSdioFunction *function, u32 address, u8 *data, CsrSdioAsyncCallback callback); -void CsrSdioWrite8Async(CsrSdioFunction *function, u32 address, u8 data, CsrSdioAsyncCallback callback); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioRead16, CsrSdioWrite16, CsrSdioRead16Async, CsrSdioWrite16Async - * - * DESCRIPTION - * Read/write a 16bit value from/to the specified register address. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * address - Register address within the function. - * data - The data to read/write. - * callback - The function to call on operation completion. - * - * RETURNS - * CSR_RESULT_SUCCESS - The data was successfully read/written. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. Data may have been - * partially read/written. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * NOTE: The CsrSdioRead16Async and CsrSdioWrite16Async functions return - * immediately, and the supplied callback function is called when the - * operation is complete. The result value is given as an argument to - * the callback function. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioRead16(CsrSdioFunction *function, u32 address, u16 *data); -CsrResult CsrSdioWrite16(CsrSdioFunction *function, u32 address, u16 data); -void CsrSdioRead16Async(CsrSdioFunction *function, u32 address, u16 *data, CsrSdioAsyncCallback callback); -void CsrSdioWrite16Async(CsrSdioFunction *function, u32 address, u16 data, CsrSdioAsyncCallback callback); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioF0Read8, CsrSdioF0Write8, CsrSdioF0Read8Async, - * CsrSdioF0Write8Async - * - * DESCRIPTION - * Read/write an 8bit value from/to the specified register address in - * function 0. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * address - Register address within the function. - * data - The data to read/write. - * callback - The function to call on operation completion. - * - * RETURNS - * CSR_RESULT_SUCCESS - The data was successfully read/written. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. No data read/written. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return - * immediately, and the supplied callback function is called when the - * operation is complete. The result value is given as an argument to - * the callback function. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioF0Read8(CsrSdioFunction *function, u32 address, u8 *data); -CsrResult CsrSdioF0Write8(CsrSdioFunction *function, u32 address, u8 data); -void CsrSdioF0Read8Async(CsrSdioFunction *function, u32 address, u8 *data, CsrSdioAsyncCallback callback); -void CsrSdioF0Write8Async(CsrSdioFunction *function, u32 address, u8 data, CsrSdioAsyncCallback callback); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioRead, CsrSdioWrite, CsrSdioReadAsync, CsrSdioWriteAsync - * - * DESCRIPTION - * Read/write a specified number of bytes from/to the specified register - * address. - * - * PARAMETERS - * function - Pointer to struct representing the function. - * address - Register address within the function. - * data - The data to read/write. - * length - Number of byte to read/write. - * callback - The function to call on operation completion. - * - * RETURNS - * CSR_RESULT_SUCCESS - The data was successfully read/written. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_INVALID_VALUE - One or more arguments were invalid. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred. Data may have been - * partially read/written. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device. - * - * NOTE: If the SDIO R5 response is available, and either of the - * FUNCTION_NUMBER or OUT_OF_RANGE bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE shall be returned. If the ERROR bit - * is set (but none of FUNCTION_NUMBER or OUT_OF_RANGE), - * CSR_RESULT_FAILURE shall be returned. The ILLEGAL_COMMAND and - * COM_CRC_ERROR bits shall be ignored. - * - * If the CSPI response is available, and any of the - * FUNCTION_DISABLED or CLOCK_DISABLED bits are set, - * CSR_SDIO_RESULT_INVALID_VALUE will be returned. - * - * NOTE: The CsrSdioF0Read8Async and CsrSdioF0Write8Async functions return - * immediately, and the supplied callback function is called when the - * operation is complete. The result value is given as an argument to - * the callback function. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioRead(CsrSdioFunction *function, u32 address, void *data, u32 length); -CsrResult CsrSdioWrite(CsrSdioFunction *function, u32 address, const void *data, u32 length); -void CsrSdioReadAsync(CsrSdioFunction *function, u32 address, void *data, u32 length, CsrSdioAsyncCallback callback); -void CsrSdioWriteAsync(CsrSdioFunction *function, u32 address, const void *data, u32 length, CsrSdioAsyncCallback callback); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioPowerOn, CsrSdioPowerOff - * - * DESCRIPTION - * Power on/off the device. - * - * PARAMETERS - * function - Pointer to struct representing the function that resides on - * the device to power on/off. - * - * RETURNS (only CsrSdioPowerOn) - * CSR_RESULT_SUCCESS - Power was successfully reapplied and the device - * has been reinitialised. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred during reinitialisation. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device during - * reinitialisation. - * CSR_SDIO_RESULT_NOT_RESET - The power was not removed by the - * CsrSdioPowerOff call. The state of the - * device is unchanged. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioPowerOn(CsrSdioFunction *function); -void CsrSdioPowerOff(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioHardReset - * - * DESCRIPTION - * Perform a hardware reset of the device. - * - * PARAMETERS - * function - Pointer to struct representing the function that resides on - * the device to hard reset. - * - * RETURNS - * CSR_RESULT_SUCCESS - Reset was successfully performed and the device - * has been reinitialised. - * CSR_RESULT_FAILURE - Unspecified/unknown error. - * CSR_SDIO_RESULT_NO_DEVICE - The device does not exist anymore. - * CSR_SDIO_RESULT_CRC_ERROR - A CRC error occurred during reinitialisation. - * CSR_SDIO_RESULT_TIMEOUT - No response from the device during - * reinitialisation. - * CSR_SDIO_RESULT_NOT_RESET - The reset was not applied because it is not - * supported. The state of the device is - * unchanged. - * - *----------------------------------------------------------------------------*/ -CsrResult CsrSdioHardReset(CsrSdioFunction *function); - -/*----------------------------------------------------------------------------* - * NAME - * CsrSdioFunctionActive, CsrSdioFunctionIdle - * - * DESCRIPTION - * - * PARAMETERS - * function - Pointer to struct representing the function. - * - *----------------------------------------------------------------------------*/ -void CsrSdioFunctionActive(CsrSdioFunction *function); -void CsrSdioFunctionIdle(CsrSdioFunction *function); - -#endif diff --git a/drivers/staging/csr/csr_serialize_primitive_types.c b/drivers/staging/csr/csr_serialize_primitive_types.c deleted file mode 100644 index 9713b9afef64..000000000000 --- a/drivers/staging/csr/csr_serialize_primitive_types.c +++ /dev/null @@ -1,100 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include -#include "csr_prim_defs.h" -#include "csr_msgconv.h" -#include "csr_macro.h" - -void CsrUint8Des(u8 *value, u8 *buffer, size_t *offset) -{ - *value = buffer[*offset]; - *offset += sizeof(*value); -} -EXPORT_SYMBOL_GPL(CsrUint8Des); - -void CsrUint16Des(u16 *value, u8 *buffer, size_t *offset) -{ - *value = (buffer[*offset + 0] << 0) | - (buffer[*offset + 1] << 8); - *offset += sizeof(*value); -} -EXPORT_SYMBOL_GPL(CsrUint16Des); - -void CsrUint32Des(u32 *value, u8 *buffer, size_t *offset) -{ - *value = (buffer[*offset + 0] << 0) | - (buffer[*offset + 1] << 8) | - (buffer[*offset + 2] << 16) | - (buffer[*offset + 3] << 24); - *offset += sizeof(*value); -} -EXPORT_SYMBOL_GPL(CsrUint32Des); - -void CsrMemCpyDes(void *value, u8 *buffer, size_t *offset, size_t length) -{ - memcpy(value, &buffer[*offset], length); - *offset += length; -} -EXPORT_SYMBOL_GPL(CsrMemCpyDes); - -void CsrCharStringDes(char **value, u8 *buffer, size_t *offset) -{ - *value = kstrdup((char *) &buffer[*offset], GFP_KERNEL); - *offset += strlen(*value) + 1; -} -EXPORT_SYMBOL_GPL(CsrCharStringDes); - -void CsrUint8Ser(u8 *buffer, size_t *offset, u8 value) -{ - buffer[*offset] = value; - *offset += sizeof(value); -} -EXPORT_SYMBOL_GPL(CsrUint8Ser); - -void CsrUint16Ser(u8 *buffer, size_t *offset, u16 value) -{ - buffer[*offset + 0] = (u8) ((value >> 0) & 0xFF); - buffer[*offset + 1] = (u8) ((value >> 8) & 0xFF); - *offset += sizeof(value); -} -EXPORT_SYMBOL_GPL(CsrUint16Ser); - -void CsrUint32Ser(u8 *buffer, size_t *offset, u32 value) -{ - buffer[*offset + 0] = (u8) ((value >> 0) & 0xFF); - buffer[*offset + 1] = (u8) ((value >> 8) & 0xFF); - buffer[*offset + 2] = (u8) ((value >> 16) & 0xFF); - buffer[*offset + 3] = (u8) ((value >> 24) & 0xFF); - *offset += sizeof(value); -} -EXPORT_SYMBOL_GPL(CsrUint32Ser); - -void CsrMemCpySer(u8 *buffer, size_t *offset, const void *value, size_t length) -{ - memcpy(&buffer[*offset], value, length); - *offset += length; -} -EXPORT_SYMBOL_GPL(CsrMemCpySer); - -void CsrCharStringSer(u8 *buffer, size_t *offset, const char *value) -{ - if (value) - { - strcpy(((char *) &buffer[*offset]), value); - *offset += strlen(value) + 1; - } - else - { - CsrUint8Ser(buffer, offset, 0); - } -} -EXPORT_SYMBOL_GPL(CsrCharStringSer); diff --git a/drivers/staging/csr/csr_time.c b/drivers/staging/csr/csr_time.c deleted file mode 100644 index 01179e46f47d..000000000000 --- a/drivers/staging/csr/csr_time.c +++ /dev/null @@ -1,33 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include -#include - -#include "csr_time.h" - -u32 CsrTimeGet(u32 *high) -{ - struct timespec ts; - u64 time; - u32 low; - - ts = current_kernel_time(); - time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; - - if (high != NULL) - *high = (u32) ((time >> 32) & 0xFFFFFFFF); - - low = (u32) (time & 0xFFFFFFFF); - - return low; -} -EXPORT_SYMBOL_GPL(CsrTimeGet); diff --git a/drivers/staging/csr/csr_time.h b/drivers/staging/csr/csr_time.h deleted file mode 100644 index fc29e8e5e478..000000000000 --- a/drivers/staging/csr/csr_time.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef CSR_TIME_H__ -#define CSR_TIME_H__ -/***************************************************************************** - -(c) Cambridge Silicon Radio Limited 2010 -All rights reserved and confidential information of CSR - -Refer to LICENSE.txt included with this source for details -on the license terms. - -*****************************************************************************/ - -#include - -/******************************************************************************* - -NAME - CsrTimeGet - -DESCRIPTION - Returns the current system time in a low and a high part. The low part - is expressed in microseconds. The high part is incremented when the low - part wraps to provide an extended range. - - The caller may provide a NULL pointer as the high parameter. - In this case the function just returns the low part and ignores the - high parameter. - - Although the time is expressed in microseconds the actual resolution is - platform dependent and can be less. It is recommended that the - resolution is at least 10 milliseconds. - -PARAMETERS - high - Pointer to variable that will receive the high part of the - current system time. Passing NULL is valid. - -RETURNS - Low part of current system time in microseconds. - -*******************************************************************************/ -u32 CsrTimeGet(u32 *high); - - -/*------------------------------------------------------------------*/ -/* CsrTime Macros */ -/*------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------* - * NAME - * CsrTimeAdd - * - * DESCRIPTION - * Add two time values. Adding the numbers can overflow the range of a - * CsrTime, so the user must be cautious. - * - * RETURNS - * CsrTime - the sum of "t1" and "t2". - * - *----------------------------------------------------------------------------*/ -#define CsrTimeAdd(t1, t2) ((t1) + (t2)) - -/*----------------------------------------------------------------------------* - * NAME - * CsrTimeSub - * - * DESCRIPTION - * Subtract two time values. Subtracting the numbers can provoke an - * underflow, so the user must be cautious. - * - * RETURNS - * CsrTime - "t1" - "t2". - * - *----------------------------------------------------------------------------*/ -#define CsrTimeSub(t1, t2) ((s32) (t1) - (s32) (t2)) - -#endif diff --git a/drivers/staging/csr/csr_util.c b/drivers/staging/csr/csr_util.c deleted file mode 100644 index c3aa9d509e5c..000000000000 --- a/drivers/staging/csr/csr_util.c +++ /dev/null @@ -1,15 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include - -MODULE_DESCRIPTION("CSR Operating System Kernel Abstraction"); -MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/staging/csr/csr_wifi_common.h b/drivers/staging/csr/csr_wifi_common.h deleted file mode 100644 index efc43a525a3d..000000000000 --- a/drivers/staging/csr/csr_wifi_common.h +++ /dev/null @@ -1,101 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_COMMON_H__ -#define CSR_WIFI_COMMON_H__ - -#include -#include "csr_result.h" - -/* MAC address */ -typedef struct -{ - u8 a[6]; -} CsrWifiMacAddress; - -/* IPv4 address */ -typedef struct -{ - u8 a[4]; -} CsrWifiIp4Address; - -/* IPv6 address */ -typedef struct -{ - u8 a[16]; -} CsrWifiIp6Address; - -typedef struct -{ - u8 ssid[32]; - u8 length; -} CsrWifiSsid; - -/******************************************************************************* - - DESCRIPTION - Result values used on the Wifi Interfaces - - VALUES - CSR_RESULT_SUCCESS - - The request/procedure succeeded - CSR_RESULT_FAILURE - - The request/procedure did not succeed because of an error - CSR_WIFI_RESULT_NOT_FOUND - - The request did not succeed because some resource was not - found. - CSR_WIFI_RESULT_TIMED_OUT - - The request/procedure did not succeed because of a time out - CSR_WIFI_RESULT_CANCELLED - - The request was canceled due to another conflicting - request that was issued before this one was completed - CSR_WIFI_RESULT_INVALID_PARAMETER - - The request/procedure did not succeed because it had an - invalid parameter - CSR_WIFI_RESULT_NO_ROOM - - The request did not succeed due to a lack of resources, - e.g. out of memory problem. - CSR_WIFI_RESULT_UNSUPPORTED - - The request/procedure did not succeed because the feature - is not supported yet - CSR_WIFI_RESULT_UNAVAILABLE - - The request cannot be processed at this time - CSR_WIFI_RESULT_WIFI_OFF - - The requested action is not available because Wi-Fi is - currently off - CSR_WIFI_RESULT_SECURITY_ERROR - - The request/procedure did not succeed because of a security - error - CSR_WIFI_RESULT_MIB_SET_FAILURE - - MIB Set Failure: either the MIB OID to be written to does - not exist or the MIB Value is invalid. - CSR_WIFI_RESULT_INVALID_INTERFACE_TAG - - The supplied Interface Tag is not valid. - CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT - - The new NOA configuration conflicts with the existing NOA configuration - hence not accepted" -*******************************************************************************/ -#define CSR_WIFI_RESULT_NOT_FOUND ((CsrResult) 0x0001) -#define CSR_WIFI_RESULT_TIMED_OUT ((CsrResult) 0x0002) -#define CSR_WIFI_RESULT_CANCELLED ((CsrResult) 0x0003) -#define CSR_WIFI_RESULT_INVALID_PARAMETER ((CsrResult) 0x0004) -#define CSR_WIFI_RESULT_NO_ROOM ((CsrResult) 0x0005) -#define CSR_WIFI_RESULT_UNSUPPORTED ((CsrResult) 0x0006) -#define CSR_WIFI_RESULT_UNAVAILABLE ((CsrResult) 0x0007) -#define CSR_WIFI_RESULT_WIFI_OFF ((CsrResult) 0x0008) -#define CSR_WIFI_RESULT_SECURITY_ERROR ((CsrResult) 0x0009) -#define CSR_WIFI_RESULT_MIB_SET_FAILURE ((CsrResult) 0x000A) -#define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG ((CsrResult) 0x000B) -#define CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT ((CsrResult) 0x000C) - -#define CSR_WIFI_VERSION "5.1.0.0" - -#endif - diff --git a/drivers/staging/csr/csr_wifi_fsm.h b/drivers/staging/csr/csr_wifi_fsm.h deleted file mode 100644 index fc5c5aa6a3c4..000000000000 --- a/drivers/staging/csr/csr_wifi_fsm.h +++ /dev/null @@ -1,240 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_FSM_H -#define CSR_WIFI_FSM_H - -#include "csr_prim_defs.h" -#include "csr_log_text.h" -#include "csr_wifi_fsm_event.h" - -/* including this file for CsrWifiInterfaceMode*/ -#include "csr_wifi_common.h" - -#define CSR_WIFI_FSM_ENV (0xFFFF) - -/** - * @brief - * Toplevel FSM context data - * - * @par Description - * Holds ALL FSM static and dynamic data for a FSM - */ -typedef struct CsrWifiFsmContext CsrWifiFsmContext; - -/** - * @brief - * FSM External Wakeup CallbackFunction Pointer - * - * @par Description - * Defines the external wakeup function for the FSM - * to call when an external event is injected into the systen - * - * @param[in] context : External context - * - * @return - * void - */ -typedef void (*CsrWifiFsmExternalWakupCallbackPtr)(void *context); - -/** - * @brief - * Initialises a top level FSM context - * - * @par Description - * Initialises the FSM Context to an initial state and allocates - * space for "maxProcesses" number of instances - * - * @param[in] osaContext : OSA context - * @param[in] applicationContext : Internal fsm application context - * @param[in] externalContext : External context - * @param[in] maxProcesses : Max processes to allocate room for - * - * @return - * CsrWifiFsmContext* fsm context - */ -extern CsrWifiFsmContext* CsrWifiFsmInit(void *applicationContext, void *externalContext, u16 maxProcesses, CsrLogTextTaskId loggingTaskId); - -/** - * @brief - * Resets the FSM's back to first conditions - * - * @par Description - * This function is used to free any dynamic resources allocated for the - * given context by CsrWifiFsmInit(). - * The FSM's reset function is called to cleanup any fsm specific memory - * The reset function does NOT need to free the fsm data pointer as - * CsrWifiFsmShutdown() will do it. - * the FSM's init function is call again to reinitialise the FSM context. - * CsrWifiFsmReset() should NEVER be called when CsrWifiFsmExecute() is running. - * - * @param[in] context : FSM context - * - * @return - * void - */ -extern void CsrWifiFsmReset(CsrWifiFsmContext *context); - -/** - * @brief - * Frees resources allocated by CsrWifiFsmInit - * - * @par Description - * This function is used to free any dynamic resources allocated for the - * given context by CsrWifiFsmInit(), prior to complete termination of - * the program. - * The FSM's reset function is called to cleanup any fsm specific memory. - * The reset function does NOT need to free the fsm data pointer as - * CsrWifiFsmShutdown() will do it. - * CsrWifiFsmShutdown() should NEVER be called when CsrWifiFsmExecute() is running. - * - * @param[in] context : FSM context - * - * @return - * void - */ -extern void CsrWifiFsmShutdown(CsrWifiFsmContext *context); - -/** - * @brief - * Executes the fsm context - * - * @par Description - * Executes the FSM context and runs until ALL events in the context are processed. - * When no more events are left to process then CsrWifiFsmExecute() returns to a time - * specifying when to next call the CsrWifiFsmExecute() - * Scheduling, threading, blocking and external event notification are outside - * the scope of the FSM and CsrWifiFsmExecute(). - * - * @param[in] context : FSM context - * - * @return - * u32 Time in ms until next timeout or 0xFFFFFFFF for no timer set - */ -extern u32 CsrWifiFsmExecute(CsrWifiFsmContext *context); - -/** - * @brief - * Adds an event to the FSM context's external event queue for processing - * - * @par Description - * Adds an event to the contexts external queue - * This is thread safe and adds an event to the fsm's external event queue. - * - * @param[in] context : FSM context - * @param[in] event : event to add to the event queue - * @param[in] source : source of the event (this can be a synergy task queue or an fsm instance id) - * @param[in] destination : destination of the event (This can be a fsm instance id or CSR_WIFI_FSM_ENV) - * @param[in] id : event id - * - * @return - * void - */ -extern void CsrWifiFsmSendEventExternal(CsrWifiFsmContext *context, CsrWifiFsmEvent *event, u16 source, u16 destination, CsrPrim primtype, u16 id); - -/** - * @brief - * Adds an Alien event to the FSM context's external event queue for processing - * - * @par Description - * Adds an event to the contexts external queue - * This is thread safe and adds an event to the fsm's external event queue. - * - * @param[in] context : FSM context - * @param[in] event : event to add to the event queue - * @param[in] source : source of the event (this can be a synergy task queue or an fsm instance id) - * @param[in] destination : destination of the event (This can be a fsm instance id or CSR_WIFI_FSM_ENV) - * @param[in] id : event id - */ -#define CsrWifiFsmSendAlienEventExternal(_context, _alienEvent, _source, _destination, _primtype, _id) \ - { \ - CsrWifiFsmAlienEvent *_evt = kmalloc(sizeof(CsrWifiFsmAlienEvent), GFP_KERNEL); \ - _evt->alienEvent = _alienEvent; \ - CsrWifiFsmSendEventExternal(_context, (CsrWifiFsmEvent *)_evt, _source, _destination, _primtype, _id); \ - } - - -/** - * @brief - * Current time of day in ms - * - * @param[in] context : FSM context - * - * @return - * u32 32 bit ms tick - */ -extern u32 CsrWifiFsmGetTimeOfDayMs(CsrWifiFsmContext *context); - -/** - * @brief - * Gets the time until the next FSM timer expiry - * - * @par Description - * Returns the next timeout time or 0 if no timers are set. - * - * @param[in] context : FSM context - * - * @return - * u32 Time in ms until next timeout or 0xFFFFFFFF for no timer set - */ -extern u32 CsrWifiFsmGetNextTimeout(CsrWifiFsmContext *context); - -/** - * @brief - * Fast forwards the fsm timers by ms Milliseconds - * - * @param[in] context : FSM context - * @param[in] ms : Milliseconds to fast forward by - * - * @return - * void - */ -extern void CsrWifiFsmFastForward(CsrWifiFsmContext *context, u16 ms); - -/** - * @brief - * shift the current time of day by ms amount - * - * @par Description - * useful to speed up tests where time needs to pass - * - * @param[in] context : FSM context - * @param[in] ms : ms to adjust time by - * - * @return - * void - */ -extern void CsrWifiFsmTestAdvanceTime(CsrWifiFsmContext *context, u32 ms); - -/** - * @brief - * Check if the fsm has events to process - * - * @param[in] context : FSM context - * - * @return - * u8 returns TRUE if there are events for the FSM to process - */ -extern u8 CsrWifiFsmHasEvents(CsrWifiFsmContext *context); - -/** - * @brief - * function that installs the contexts wakeup function - * - * @param[in] context : FSM context - * @param[in] callback : Callback function pointer - * - * @return - * void - */ -extern void CsrWifiFsmInstallWakeupCallback(CsrWifiFsmContext *context, CsrWifiFsmExternalWakupCallbackPtr callback); - -#endif /* CSR_WIFI_FSM_H */ - diff --git a/drivers/staging/csr/csr_wifi_fsm_event.h b/drivers/staging/csr/csr_wifi_fsm_event.h deleted file mode 100644 index 0690ca955ef5..000000000000 --- a/drivers/staging/csr/csr_wifi_fsm_event.h +++ /dev/null @@ -1,42 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_FSM_EVENT_H -#define CSR_WIFI_FSM_EVENT_H - -#include "csr_prim_defs.h" -#include "csr_sched.h" - -/** - * @brief - * FSM event header. - * - * @par Description - * All events MUST have this struct as the FIRST member. - * The next member is used internally for linked lists - */ -typedef struct CsrWifiFsmEvent -{ - CsrPrim type; - u16 primtype; - CsrSchedQid destination; - CsrSchedQid source; - - /* Private pointer to allow an optimal Event list */ - /* NOTE: Ignore this pointer. - * Do not waste code initializing OR freeing it. - * The pointer is used internally in the CsrWifiFsm code - * to avoid a second malloc when queuing events. - */ - struct CsrWifiFsmEvent *next; -} CsrWifiFsmEvent; - -#endif /* CSR_WIFI_FSM_EVENT_H */ - diff --git a/drivers/staging/csr/csr_wifi_fsm_types.h b/drivers/staging/csr/csr_wifi_fsm_types.h deleted file mode 100644 index d21c60a81fcf..000000000000 --- a/drivers/staging/csr/csr_wifi_fsm_types.h +++ /dev/null @@ -1,430 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_FSM_TYPES_H -#define CSR_WIFI_FSM_TYPES_H - -#include -#include "csr_macro.h" -#include "csr_sched.h" - -#ifdef CSR_WIFI_FSM_MUTEX_ENABLE -#include "csr_framework_ext.h" -#endif - -#include "csr_wifi_fsm.h" - -#define CSR_WIFI_FSM_MAX_TRANSITION_HISTORY 10 - -/** - * @brief - * FSM event list header. - * - * @par Description - * Singly linked list of events. - */ -typedef struct CsrWifiFsmEventList -{ - CsrWifiFsmEvent *first; - CsrWifiFsmEvent *last; -} CsrWifiFsmEventList; - - -/** - * @brief - * FSM timer id. - * - * @par Description - * Composite Id made up of the type, dest and a unique id so - * CsrWifiFsmRemoveTimer knows where to look when removing the timer - */ -typedef struct CsrWifiFsmTimerId -{ - CsrPrim type; - u16 primtype; - CsrSchedQid destination; - u16 uniqueid; -} CsrWifiFsmTimerId; - -/** - * @brief - * FSM timer header. - * - * @par Description - * All timer MUST have this struct as the FIRST member. - * The first members of the structure MUST remain compatable - * with the CsrWifiFsmEvent so that timers are just specialised events - */ -typedef struct CsrWifiFsmTimer -{ - CsrPrim type; - u16 primtype; - CsrSchedQid destination; - CsrSchedQid source; - - /* Private pointer to allow an optimal Event list */ - struct CsrWifiFsmTimer *next; - - CsrWifiFsmTimerId timerid; - u32 timeoutTimeMs; -} CsrWifiFsmTimer; - - -/** - * @brief - * Fsm Alien Event - * - * @par Description - * Allows the wrapping of alien events that do not use CsrWifiFsmEvent - * as the first member of the Event struct - */ -typedef struct -{ - CsrWifiFsmEvent event; - void *alienEvent; -} CsrWifiFsmAlienEvent; - - -/** - * @brief - * FSM timer list header. - * - * @par Description - * Singly linked list of timers. - */ -typedef struct CsrWifiFsmTimerList -{ - CsrWifiFsmTimer *first; - CsrWifiFsmTimer *last; - u16 nexttimerid; -} CsrWifiFsmTimerList; - -/** - * @brief - * Process Entry Function Pointer - * - * @par Description - * Defines the entry function for a processes. - * Called at process initialisation. - * - * @param[in] context : FSM context - * - * @return - * void - */ -typedef void (*CsrWifiFsmProcEntryFnPtr)(CsrWifiFsmContext *context); - -/** - * @brief - * Process Transition Function Pointer - * - * @par Description - * Defines a transition function for a processes. - * Called when an event causes a transition on a process - * - * @param[in] CsrWifiFsmContext* : FSM context - * @param[in] void* : FSM data (can be NULL) - * @param[in] const CsrWifiFsmEvent* : event to process - * - * @return - * void - */ -typedef void (*CsrWifiFsmTransitionFnPtr)(CsrWifiFsmContext *context, void *fsmData, const CsrWifiFsmEvent *event); - -/** - * @brief - * Process reset/shutdown Function Pointer - * - * @par Description - * Defines the reset/shutdown function for a processes. - * Called to reset or shutdown an fsm. - * - * @param[in] context : FSM context - * - * @return - * void - */ -typedef void (*CsrWifiFsmProcResetFnPtr)(CsrWifiFsmContext *context); - -/** - * @brief - * FSM Default Destination CallbackFunction Pointer - * - * @par Description - * Defines the default destination function for the FSM - * to call when an event does not have a valid destination. - * This - * - * @param[in] context : External context - * - * @return - * u16 a valid destination OR CSR_WIFI_FSM_ENV - */ -typedef u16 (*CsrWifiFsmDestLookupCallbackPtr)(void *context, const CsrWifiFsmEvent *event); - - -#ifdef CSR_WIFI_FSM_DUMP_ENABLE -/** - * @brief - * Trace Dump Function Pointer - * - * @par Description - * Called when we want to trace the FSM - * - * @param[in] context : FSM context - * @param[in] id : fsm id - * - * @return - * void - */ -typedef void (*CsrWifiFsmDumpFnPtr)(CsrWifiFsmContext *context, void *fsmData); -#endif - -/** - * @brief - * Event ID to transition function entry - * - * @par Description - * Event ID to Transition Entry in a state table. - */ -typedef struct -{ - u32 eventid; - CsrWifiFsmTransitionFnPtr transition; -#ifdef CSR_LOG_ENABLE - const char *transitionName; -#endif -} CsrWifiFsmEventEntry; - -/** - * @brief - * Single State's Transition Table - * - * @par Description - * Stores Data for a single State's event to - * transition functions mapping - */ -typedef struct -{ - const u8 numEntries; - const u8 saveAll; - const CsrWifiFsmEventEntry *eventEntryArray; /* array of transition function pointers for state */ -#ifdef CSR_LOG_ENABLE - u16 stateNumber; - const char *stateName; -#endif -} CsrWifiFsmTableEntry; - -/** - * @brief - * Process State Transtion table - * - * @par Description - * Stores Data for a processes State to transition table - */ -typedef struct -{ - u16 numStates; /* number of states */ - const CsrWifiFsmTableEntry *aStateEventMatrix; /* state event matrix */ -} CsrWifiFsmTransitionFunctionTable; - -/** - * @brief - * Const Process definition - * - * @par Description - * Constant process specification. - * This is ALL the non dynamic data that defines - * a process. - */ -typedef struct -{ - const char *processName; - const u32 processId; - const CsrWifiFsmTransitionFunctionTable transitionTable; - const CsrWifiFsmTableEntry unhandledTransitions; - const CsrWifiFsmTableEntry ignoreFunctions; - const CsrWifiFsmProcEntryFnPtr entryFn; - const CsrWifiFsmProcResetFnPtr resetFn; -#ifdef CSR_WIFI_FSM_DUMP_ENABLE - const CsrWifiFsmDumpFnPtr dumpFn; /* Called to dump fsm specific trace if not NULL */ -#endif -} CsrWifiFsmProcessStateMachine; - -#ifdef CSR_WIFI_FSM_DUMP_ENABLE -/** - * @brief - * Storage for state transition info - */ -typedef struct -{ - u16 transitionNumber; - CsrWifiFsmEvent event; - u16 fromState; - u16 toState; - CsrWifiFsmTransitionFnPtr transitionFn; - u16 transitionCount; /* number consecutive of times this transition was seen */ -#ifdef CSR_LOG_ENABLE - const char *transitionName; -#endif -} CsrWifiFsmTransitionRecord; - -/** - * @brief - * Storage for the last state X transitions - */ -typedef struct -{ - u16 numTransitions; - CsrWifiFsmTransitionRecord records[CSR_WIFI_FSM_MAX_TRANSITION_HISTORY]; -} CsrWifiFsmTransitionRecords; -#endif - -/** - * @brief - * Dynamic Process data - * - * @par Description - * Dynamic process data that is used to keep track of the - * state and data for a process instance - */ -typedef struct -{ - const CsrWifiFsmProcessStateMachine *fsmInfo; /* state machine info that is constant regardless of context */ - u16 instanceId; /* Runtime process id */ - u16 state; /* Current state */ - void *params; /* Instance user data */ - CsrWifiFsmEventList savedEventQueue; /* The saved event queue */ - struct CsrWifiFsmInstanceEntry *subFsm; /* Sub Fsm instance data */ - struct CsrWifiFsmInstanceEntry *subFsmCaller; /* The Fsm instance that created the SubFsm and should be used for callbacks*/ -#ifdef CSR_WIFI_FSM_DUMP_ENABLE - CsrWifiFsmTransitionRecords transitionRecords; /* Last X transitions in the FSM */ -#endif -} CsrWifiFsmInstanceEntry; - -/** - * @brief - * OnCreate Callback Function Pointer - * - * @par Description - * Called when an fsm is created. - * - * @param[in] extContext : External context - * @param[in] instance : FSM instance - * - * @return - * void - */ -typedef void (*CsrWifiFsmOnCreateFnPtr)(void *extContext, const CsrWifiFsmInstanceEntry *instance); - -/** - * @brief - * OnTransition Callback Function Pointer - * - * @par Description - * Called when an event is processed by a fsm - * - * @param[in] extContext : External context - * @param[in] eventEntryArray : Entry data - * @param[in] event : Event - * - * @return - * void - */ -typedef void (*CsrWifiFsmOnTransitionFnPtr)(void *extContext, const CsrWifiFsmEventEntry *eventEntryArray, const CsrWifiFsmEvent *event); - -/** - * @brief - * OnStateChange Callback Function Pointer - * - * @par Description - * Called when CsrWifiFsmNextState is called - * - * @param[in] extContext : External context - * - * @return - * void - */ -typedef void (*CsrWifiFsmOnStateChangeFnPtr)(void *extContext, u16 nextstate); - -/** - * @brief - * OnIgnore,OnError or OnInvalid Callback Function Pointer - * - * @par Description - * Called when an event is processed by a fsm - * - * @param[in] extContext : External context - * @param[in] event : Event - * - * @return - * void - */ -typedef void (*CsrWifiFsmOnEventFnPtr)(void *extContext, const CsrWifiFsmEvent *event); - -/** - * @brief - * Toplevel FSM context data - * - * @par Description - * Holds ALL FSM static and dynamic data for a FSM - */ -struct CsrWifiFsmContext -{ - CsrWifiFsmEventList eventQueue; /* The internal event queue */ - CsrWifiFsmEventList externalEventQueue; /* The external event queue */ -#ifdef CSR_WIFI_FSM_MUTEX_ENABLE - CsrMutexHandle externalEventQueueLock; /* The external event queue mutex */ -#endif - u32 timeOffset; /* Amount to adjust the TimeOfDayMs by */ - CsrWifiFsmTimerList timerQueue; /* The internal timer queue */ - u8 useTempSaveList; /* Should the temp save list be used */ - CsrWifiFsmEventList tempSaveList; /* The temp save event queue */ - CsrWifiFsmEvent *eventForwardedOrSaved; /* The event that was forwarded or Saved */ - u16 maxProcesses; /* Size of instanceArray */ - u16 numProcesses; /* Current number allocated in instanceArray */ - CsrWifiFsmInstanceEntry *instanceArray; /* Array of processes for this component */ - CsrWifiFsmInstanceEntry *ownerInstance; /* The Process that owns currentInstance (SubFsm support) */ - CsrWifiFsmInstanceEntry *currentInstance; /* Current Process that is executing */ - CsrWifiFsmExternalWakupCallbackPtr externalEventFn; /* External event Callback */ - CsrWifiFsmOnEventFnPtr appIgnoreCallback; /* Application Ignore event Callback */ - CsrWifiFsmDestLookupCallbackPtr appEvtDstCallback; /* Application Lookup event Destination Function*/ - - void *applicationContext; /* Internal fsm application context */ - void *externalContext; /* External context (set by the user of the fsm)*/ - CsrLogTextTaskId loggingTaskId; /* Task Id to use in any logging output */ - -#ifndef CSR_WIFI_FSM_SCHEDULER_DISABLED - CsrSchedTid schedTimerId; /* Scheduler TimerId for use in Scheduler Tasks */ - u32 schedTimerNexttimeoutMs; /* Next timeout time for the current timer */ -#endif - -#ifdef CSR_WIFI_FSM_MUTEX_ENABLE -#ifdef CSR_WIFI_FSM_TRANSITION_LOCK - CsrMutexHandle transitionLock; /* Lock when calling transition functions */ -#endif -#endif - -#ifdef CSR_LOG_ENABLE - CsrWifiFsmOnCreateFnPtr onCreate; /* Debug Transition Callback */ - CsrWifiFsmOnTransitionFnPtr onTransition; /* Debug Transition Callback */ - CsrWifiFsmOnTransitionFnPtr onUnhandedCallback; /* Unhanded event Callback */ - CsrWifiFsmOnStateChangeFnPtr onStateChange; /* Debug State Change Callback */ - CsrWifiFsmOnEventFnPtr onIgnoreCallback; /* Ignore event Callback */ - CsrWifiFsmOnEventFnPtr onSaveCallback; /* Save event Callback */ - CsrWifiFsmOnEventFnPtr onErrorCallback; /* Error event Callback */ - CsrWifiFsmOnEventFnPtr onInvalidCallback; /* Invalid event Callback */ -#endif -#ifdef CSR_WIFI_FSM_DUMP_ENABLE - u16 masterTransitionNumber; /* Increments on every transition */ -#endif -}; - -#endif /* CSR_WIFI_FSM_TYPES_H */ diff --git a/drivers/staging/csr/csr_wifi_hip_card.h b/drivers/staging/csr/csr_wifi_hip_card.h deleted file mode 100644 index bd47f606e0de..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_card.h +++ /dev/null @@ -1,114 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - ****************************************************************************** - * FILE : csr_wifi_hip_card.h - * - * PURPOSE : Defines abstract interface for hardware specific functions. - * Note, this is a different file from one of the same name in the - * Windows driver. - * - ***************************************************************************** - */ -#ifndef __CARD_H__ -#define __CARD_H__ - -#include "csr_wifi_hip_card_sdio.h" -#include "csr_wifi_hip_signals.h" -#include "csr_wifi_hip_unifi_udi.h" - - -/***************************************************************************** - * CardEnableInt - - */ -CsrResult CardEnableInt(card_t *card); - -/***************************************************************************** - * CardGenInt - - */ -CsrResult CardGenInt(card_t *card); - -/***************************************************************************** - * CardPendingInt - - */ -CsrResult CardPendingInt(card_t *card, u8 *pintr); - -/***************************************************************************** - * CardDisableInt - - */ -CsrResult CardDisableInt(card_t *card); - -/***************************************************************************** - * CardClearInt - - */ -CsrResult CardClearInt(card_t *card); - -/***************************************************************************** - * CardDisable - - */ -void CardDisable(card_t *card); - -/***************************************************************************** - * CardIntEnabled - - */ -CsrResult CardIntEnabled(card_t *card, u8 *enabled); - -/***************************************************************************** - * CardGetDataSlotSize - */ -u16 CardGetDataSlotSize(card_t *card); - -/***************************************************************************** - * CardWriteBulkData - - */ -CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQueue queue); - - -/***************************************************************************** - * CardClearFromHostDataSlot - - */ -void CardClearFromHostDataSlot(card_t *card, const s16 aSlotNum); - -#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL -/***************************************************************************** - * CardClearFromHostDataSlotWithoutFreeingBulkData - Clear the data stot - * without freeing the bulk data - */ - -void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const s16 aSlotNum); -#endif - -/***************************************************************************** - * CardGetFreeFromHostDataSlots - - */ -u16 CardGetFreeFromHostDataSlots(card_t *card); - -u16 CardAreAllFromHostDataSlotsEmpty(card_t *card); - -CsrResult card_start_processor(card_t *card, enum unifi_dbg_processors_select which); - -CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr); - -CsrResult unifi_dl_firmware(card_t *card, void *arg); -CsrResult unifi_dl_patch(card_t *card, void *arg, u32 boot_ctrl); -CsrResult unifi_do_loader_op(card_t *card, u32 op_addr, u8 opcode); -void* unifi_dl_fw_read_start(card_t *card, s8 is_fw); - -CsrResult unifi_coredump_handle_request(card_t *card); - -CsrResult ConvertCsrSdioToCsrHipResult(card_t *card, CsrResult csrResult); -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -void unifi_debug_log_to_buf(const char *fmt, ...); -void unifi_debug_string_to_buf(const char *str); -void unifi_debug_hex_to_buf(const char *buff, u16 length); -#endif - -#endif /* __CARD_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c deleted file mode 100644 index d5425325894c..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c +++ /dev/null @@ -1,4001 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_card_sdio.c - * - * PURPOSE: Implementation of the Card API for SDIO. - * - * NOTES: - * CardInit() is called from the SDIO probe callback when a card is - * inserted. This performs the basic SDIO initialisation, enabling i/o - * etc. - * - * --------------------------------------------------------------------------- - */ -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "csr_wifi_hip_unifiversion.h" -#include "csr_wifi_hip_card.h" -#include "csr_wifi_hip_card_sdio.h" -#include "csr_wifi_hip_chiphelper.h" - - -/* Time to wait between attempts to read MAILBOX0 */ -#define MAILBOX1_TIMEOUT 10 /* in millisecs */ -#define MAILBOX1_ATTEMPTS 200 /* 2 seconds */ - -#define MAILBOX2_TIMEOUT 5 /* in millisecs */ -#define MAILBOX2_ATTEMPTS 10 /* 50ms */ - -#define RESET_SETTLE_DELAY 25 /* in millisecs */ - -static CsrResult card_init_slots(card_t *card); -static CsrResult card_hw_init(card_t *card); -static CsrResult firmware_present_in_flash(card_t *card); -static void bootstrap_chip_hw(card_t *card); -static CsrResult unifi_reset_hardware(card_t *card); -static CsrResult unifi_hip_init(card_t *card); -static CsrResult card_access_panic(card_t *card); -static CsrResult unifi_read_chip_version(card_t *card); - -/* - * --------------------------------------------------------------------------- - * unifi_alloc_card - * - * Allocate and initialise the card context structure. - * - * Arguments: - * sdio Pointer to SDIO context pointer to pass to low - * level i/o functions. - * ospriv Pointer to O/S private struct to pass when calling - * callbacks to the higher level system. - * - * Returns: - * Pointer to card struct, which represents the driver context or - * NULL if the allocation failed. - * --------------------------------------------------------------------------- - */ -card_t* unifi_alloc_card(CsrSdioFunction *sdio, void *ospriv) -{ - card_t *card; - u32 i; - - - card = kzalloc(sizeof(card_t), GFP_KERNEL); - if (card == NULL) - { - return NULL; - } - - card->sdio_if = sdio; - card->ospriv = ospriv; - - card->unifi_interrupt_seq = 1; - - /* Make these invalid. */ - card->proc_select = (u32)(-1); - card->dmem_page = (u32)(-1); - card->pmem_page = (u32)(-1); - - card->bh_reason_host = 0; - card->bh_reason_unifi = 0; - - for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++) - { - card->tx_q_paused_flag[i] = 0; - } - card->memory_resources_allocated = 0; - - card->low_power_mode = UNIFI_LOW_POWER_DISABLED; - card->periodic_wake_mode = UNIFI_PERIODIC_WAKE_HOST_DISABLED; - - card->host_state = UNIFI_HOST_STATE_AWAKE; - card->intmode = CSR_WIFI_INTMODE_DEFAULT; - - /* - * Memory resources for buffers are allocated when the chip is initialised - * because we need configuration information from the firmware. - */ - - /* - * Initialise wait queues and lists - */ - card->fh_command_queue.q_body = card->fh_command_q_body; - card->fh_command_queue.q_length = UNIFI_SOFT_COMMAND_Q_LENGTH; - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->fh_traffic_queue[i].q_body = card->fh_traffic_q_body[i]; - card->fh_traffic_queue[i].q_length = UNIFI_SOFT_TRAFFIC_Q_LENGTH; - } - - - /* Initialise mini-coredump pointers in case no coredump buffers - * are requested by the OS layer. - */ - card->request_coredump_on_reset = 0; - card->dump_next_write = NULL; - card->dump_cur_read = NULL; - card->dump_buf = NULL; - -#ifdef UNIFI_DEBUG - /* Determine offset of LSB in pointer for later alignment sanity check. - * Synergy integer types have specific widths, which cause compiler - * warnings when casting pointer types, e.g. on 64-bit systems. - */ - { - u32 val = 0x01234567; - - if (*((u8 *)&val) == 0x01) - { - card->lsb = sizeof(void *) - 1; /* BE */ - } - else - { - card->lsb = 0; /* LE */ - } - } -#endif - return card; -} /* unifi_alloc_card() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_init_card - * - * Reset the hardware and perform HIP initialization - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CsrResult code - * CSR_RESULT_SUCCESS if successful - * --------------------------------------------------------------------------- - */ -CsrResult unifi_init_card(card_t *card, s32 led_mask) -{ - CsrResult r; - - - if (card == NULL) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - r = unifi_init(card); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - r = unifi_hip_init(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to start host protocol.\n"); - return r; - } - - return CSR_RESULT_SUCCESS; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_init - * - * Init the hardware. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CsrResult code - * CSR_RESULT_SUCCESS if successful - * --------------------------------------------------------------------------- - */ -CsrResult unifi_init(card_t *card) -{ - CsrResult r; - CsrResult csrResult; - - if (card == NULL) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* - * Disable the SDIO interrupts while initialising UniFi. - * Re-enable them when f/w is running. - */ - csrResult = CsrSdioInterruptDisable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - - /* - * UniFi's PLL may start with a slow clock (~ 1 MHz) so initially - * set the SDIO bus clock to a similar value or SDIO accesses may - * fail. - */ - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - return r; - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; - - /* - * Reset UniFi. Note, this only resets the WLAN function part of the chip, - * the SDIO interface is not reset. - */ - unifi_trace(card->ospriv, UDBG1, "Resetting UniFi\n"); - r = unifi_reset_hardware(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to reset UniFi\n"); - return r; - } - - /* Reset the power save mode, to be active until the MLME-reset is complete */ - r = unifi_configure_low_power_mode(card, - UNIFI_LOW_POWER_DISABLED, UNIFI_PERIODIC_WAKE_HOST_DISABLED); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to set power save mode\n"); - return r; - } - - /* - * Set initial value of page registers. - * The page registers will be maintained by unifi_read...() and - * unifi_write...(). - */ - card->proc_select = (u32)(-1); - card->dmem_page = (u32)(-1); - card->pmem_page = (u32)(-1); - r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW3_PAGE(card->helper) * 2, 0); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n"); - return r; - } - r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, 0); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write PROG_MEM2_PAGE\n"); - return r; - } - - /* - * If the driver has reset UniFi due to previous SDIO failure, this may - * have been due to a chip watchdog reset. In this case, the driver may - * have requested a mini-coredump which needs to be captured now the - * SDIO interface is alive. - */ - (void)unifi_coredump_handle_request(card); - - /* - * Probe to see if the UniFi has ROM/flash to boot from. CSR6xxx should do. - */ - r = firmware_present_in_flash(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r == CSR_WIFI_HIP_RESULT_NOT_FOUND) - { - unifi_error(card->ospriv, "No firmware found\n"); - } - else if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Probe for Flash failed\n"); - } - - return r; -} /* unifi_init() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_download - * - * Load the firmware. - * - * Arguments: - * card Pointer to card struct - * led_mask Loader LED mask - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CsrResult error code on failure. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_download(card_t *card, s32 led_mask) -{ - CsrResult r; - void *dlpriv; - - if (card == NULL) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* Set the loader led mask */ - card->loader_led_mask = led_mask; - - /* Get the firmware file information */ - unifi_trace(card->ospriv, UDBG1, "downloading firmware...\n"); - - dlpriv = unifi_dl_fw_read_start(card, UNIFI_FW_STA); - if (dlpriv == NULL) - { - return CSR_WIFI_HIP_RESULT_NOT_FOUND; - } - - /* Download the firmware. */ - r = unifi_dl_firmware(card, dlpriv); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to download firmware\n"); - return r; - } - - /* Free the firmware file information. */ - unifi_fw_read_stop(card->ospriv, dlpriv); - - return CSR_RESULT_SUCCESS; -} /* unifi_download() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_hip_init - * - * This function performs the f/w initialisation sequence as described - * in the Unifi Host Interface Protocol Specification. - * It allocates memory for host-side slot data and signal queues. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS on success or else a CSR error code - * - * Notes: - * The firmware must have been downloaded. - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_hip_init(card_t *card) -{ - CsrResult r; - CsrResult csrResult; - - r = card_hw_init(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to establish communication with UniFi\n"); - return r; - } -#ifdef CSR_PRE_ALLOC_NET_DATA - /* if there is any preallocated netdata left from the prev session free it now */ - prealloc_netdata_free(card); -#endif - /* - * Allocate memory for host-side slot data and signal queues. - * We need the config info read from the firmware to know how much - * memory to allocate. - */ - r = card_init_slots(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Init slots failed: %d\n", r); - return r; - } - - unifi_trace(card->ospriv, UDBG2, "Sending first UniFi interrupt\n"); - - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - /* Enable the SDIO interrupts now that the f/w is running. */ - csrResult = CsrSdioInterruptEnable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - - /* Signal the UniFi to start handling messages */ - r = CardGenInt(card); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_hip_init() */ - - -/* - * --------------------------------------------------------------------------- - * _build_sdio_config_data - * - * Unpack the SDIO configuration information from a buffer read from - * UniFi into a host structure. - * The data is byte-swapped for a big-endian host if necessary by the - * UNPACK... macros. - * - * Arguments: - * card Pointer to card struct - * cfg_data Destination structure to unpack into. - * cfg_data_buf Source buffer to read from. This should be the raw - * data read from UniFi. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void _build_sdio_config_data(sdio_config_data_t *cfg_data, - const u8 *cfg_data_buf) -{ - s16 offset = 0; - - cfg_data->version = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->sdio_ctrl_offset = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->fromhost_sigbuf_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->tohost_sigbuf_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->num_fromhost_sig_frags = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->num_tohost_sig_frags = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->num_fromhost_data_slots = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->num_tohost_data_slots = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->data_slot_size = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->initialised = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->overlay_size = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT32; - - cfg_data->data_slot_round = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->sig_frag_size = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); - offset += SIZEOF_UINT16; - - cfg_data->tohost_signal_padding = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cfg_data_buf + offset); -} /* _build_sdio_config_data() */ - - -/* - * - Function ---------------------------------------------------------------- - * card_hw_init() - * - * Perform the initialisation procedure described in the UniFi Host - * Interface Protocol document (section 3.3.8) and read the run-time - * configuration information from the UniFi. This is stuff like number - * of bulk data slots etc. - * - * The card enumeration and SD initialisation has already been done by - * the SDIO library, see card_sdio_init(). - * - * The initialisation is done when firmware is ready, i.e. this may need - * to be called after a f/w download operation. - * - * The initialisation procedure goes like this: - * - Wait for UniFi to start-up by polling SHARED_MAILBOX1 - * - Find the symbol table and look up SLT_SDIO_SLOT_CONFIG - * - Read the config structure - * - Check the "SDIO initialised" flag, if not zero do a h/w reset and - * start again - * - Decide the number of bulk data slots to allocate, allocate them and - * set "SDIO initialised" flag (and generate an interrupt) to say so. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCEESS on success, - * a CSR error code on failure - * - * Notes: - * All data in the f/w is stored in a little endian format, without any - * padding bytes. Every read from this memory has to be transformed in - * host (cpu specific) format, before it is stored in driver's parameters - * or/and structures. Athough unifi_card_read16() and unifi_read32() do perform - * the conversion internally, unifi_readn() does not. - * --------------------------------------------------------------------------- - */ -static CsrResult card_hw_init(card_t *card) -{ - u32 slut_address; - u16 initialised; - u16 finger_print; - symbol_t slut; - sdio_config_data_t *cfg_data; - u8 cfg_data_buf[SDIO_CONFIG_DATA_SIZE]; - CsrResult r; - void *dlpriv; - s16 major, minor; - s16 search_4slut_again; - CsrResult csrResult; - - /* - * The device revision from the TPLMID_MANF and TPLMID_CARD fields - * of the CIS are available as - * card->sdio_if->pDevice->ManfID - * card->sdio_if->pDevice->AppID - */ - - /* - * Run in a loop so we can patch. - */ - do - { - /* Reset these each time around the loop. */ - search_4slut_again = 0; - cfg_data = NULL; - - r = card_wait_for_firmware_to_start(card, &slut_address); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Firmware hasn't started\n"); - return r; - } - unifi_trace(card->ospriv, UDBG4, "SLUT addr 0x%lX\n", slut_address); - - /* - * Firmware has started, but doesn't know full clock configuration yet - * as some of the information may be in the MIB. Therefore we set an - * initial SDIO clock speed, faster than UNIFI_SDIO_CLOCK_SAFE_HZ, for - * the patch download and subsequent firmware initialisation, and - * full speed UNIFI_SDIO_CLOCK_MAX_HZ will be set once the f/w tells us - * that it is ready. - */ - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - return r; - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; - - /* - * Check the SLUT fingerprint. - * The slut_address is a generic pointer so we must use unifi_card_read16(). - */ - unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n"); - finger_print = 0; - r = unifi_card_read16(card, slut_address, &finger_print); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read SLUT finger print\n"); - return r; - } - - if (finger_print != SLUT_FINGERPRINT) - { - unifi_error(card->ospriv, "Failed to find Symbol lookup table fingerprint\n"); - return CSR_RESULT_FAILURE; - } - - /* Symbol table starts imedately after the fingerprint */ - slut_address += 2; - - /* Search the table until either the end marker is found, or the - * loading of patch firmware invalidates the current table. - */ - while (!search_4slut_again) - { - u16 s; - u32 l; - - r = unifi_card_read16(card, slut_address, &s); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - slut_address += 2; - - if (s == CSR_SLT_END) - { - unifi_trace(card->ospriv, UDBG3, " found CSR_SLT_END\n"); - break; - } - - r = unifi_read32(card, slut_address, &l); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - slut_address += 4; - - slut.id = s; - slut.obj = l; - - unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", slut.id, slut.obj); - switch (slut.id) - { - case CSR_SLT_SDIO_SLOT_CONFIG: - cfg_data = &card->config_data; - /* - * unifi_card_readn reads n bytes from the card, where data is stored - * in a little endian format, without any padding bytes. So, we - * can not just pass the cfg_data pointer or use the - * sizeof(sdio_config_data_t) since the structure in the host can - * be big endian formatted or have padding bytes for alignment. - * We use a char buffer to read the data from the card. - */ - r = unifi_card_readn(card, slut.obj, cfg_data_buf, SDIO_CONFIG_DATA_SIZE); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read config data\n"); - return r; - } - /* .. and then we copy the data to the host structure */ - _build_sdio_config_data(cfg_data, cfg_data_buf); - - /* Make sure the from host data slots are what we expect - we reserve 2 for commands and there should be at least - 1 left for each access category */ - if ((cfg_data->num_fromhost_data_slots < UNIFI_RESERVED_COMMAND_SLOTS) - || (cfg_data->num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS) / UNIFI_NO_OF_TX_QS == 0) - { - unifi_error(card->ospriv, "From host data slots %d\n", cfg_data->num_fromhost_data_slots); - unifi_error(card->ospriv, "need to be (queues * x + 2) (UNIFI_RESERVED_COMMAND_SLOTS for commands)\n"); - return CSR_RESULT_FAILURE; - } - - /* Configure SDIO to-block-size padding */ - if (card->sdio_io_block_pad) - { - /* - * Firmware limits the maximum padding size via data_slot_round. - * Therefore when padding to whole block sizes, the block size - * must be configured correctly by adjusting CSR_WIFI_HIP_SDIO_BLOCK_SIZE. - */ - if (cfg_data->data_slot_round < card->sdio_io_block_size) - { - unifi_error(card->ospriv, - "Configuration error: Block size of %d exceeds f/w data_slot_round of %d\n", - card->sdio_io_block_size, cfg_data->data_slot_round); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* - * To force the To-Host signals to be rounded up to the SDIO block - * size, we need to write the To-Host Signal Padding Fragments - * field of the SDIO configuration in UniFi. - */ - if ((card->sdio_io_block_size % cfg_data->sig_frag_size) != 0) - { - unifi_error(card->ospriv, "Configuration error: Can not pad to-host signals.\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - cfg_data->tohost_signal_padding = (u16) (card->sdio_io_block_size / cfg_data->sig_frag_size); - unifi_info(card->ospriv, "SDIO block size %d requires %d padding chunks\n", - card->sdio_io_block_size, cfg_data->tohost_signal_padding); - r = unifi_card_write16(card, slut.obj + SDIO_TO_HOST_SIG_PADDING_OFFSET, cfg_data->tohost_signal_padding); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write To-Host Signal Padding Fragments\n"); - return r; - } - } - - /* Reconstruct the Generic Pointer address of the - * SDIO Control Data Struct. - */ - card->sdio_ctrl_addr = cfg_data->sdio_ctrl_offset | (UNIFI_SH_DMEM << 24); - card->init_flag_addr = slut.obj + SDIO_INIT_FLAG_OFFSET; - break; - - case CSR_SLT_BUILD_ID_NUMBER: - { - u32 n; - r = unifi_read32(card, slut.obj, &n); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read build id\n"); - return r; - } - card->build_id = n; - } - break; - - case CSR_SLT_BUILD_ID_STRING: - r = unifi_readnz(card, slut.obj, card->build_id_string, - sizeof(card->build_id_string)); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read build string\n"); - return r; - } - break; - - case CSR_SLT_PERSISTENT_STORE_DB: - break; - - case CSR_SLT_BOOT_LOADER_CONTROL: - - /* This command copies most of the station firmware - * image from ROM into program RAM. It also clears - * out the zerod data and sets up the initialised - * data. */ - r = unifi_do_loader_op(card, slut.obj + 6, UNIFI_BOOT_LOADER_LOAD_STA); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write loader load image command\n"); - return r; - } - - dlpriv = unifi_dl_fw_read_start(card, UNIFI_FW_STA); - - /* dlpriv might be NULL, we still need to do the do_loader_op step. */ - if (dlpriv != NULL) - { - /* Download the firmware. */ - r = unifi_dl_patch(card, dlpriv, slut.obj); - - /* Free the firmware file information. */ - unifi_fw_read_stop(card->ospriv, dlpriv); - - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to patch firmware\n"); - return r; - } - } - - /* This command starts the firmware image that we want (the - * station by default) with any patches required applied. */ - r = unifi_do_loader_op(card, slut.obj + 6, UNIFI_BOOT_LOADER_RESTART); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write loader restart command\n"); - return r; - } - - /* The now running patch f/w defines a new SLUT data structure - - * the current one is no longer valid. We must drop out of the - * processing loop and enumerate the new SLUT (which may appear - * at a different offset). - */ - search_4slut_again = 1; - break; - - case CSR_SLT_PANIC_DATA_PHY: - card->panic_data_phy_addr = slut.obj; - break; - - case CSR_SLT_PANIC_DATA_MAC: - card->panic_data_mac_addr = slut.obj; - break; - - default: - /* do nothing */ - break; - } - } /* while */ - } while (search_4slut_again); - - /* Did we find the Config Data ? */ - if (cfg_data == NULL) - { - unifi_error(card->ospriv, "Failed to find SDIO_SLOT_CONFIG Symbol\n"); - return CSR_RESULT_FAILURE; - } - - /* - * Has ths card already been initialised? - * If so, return an error so we do a h/w reset and start again. - */ - r = unifi_card_read16(card, card->init_flag_addr, &initialised); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read init flag at %08lx\n", - card->init_flag_addr); - return r; - } - if (initialised != 0) - { - return CSR_RESULT_FAILURE; - } - - - /* - * Now check the UniFi firmware version - */ - major = (cfg_data->version >> 8) & 0xFF; - minor = cfg_data->version & 0xFF; - unifi_info(card->ospriv, "UniFi f/w protocol version %d.%d (driver %d.%d)\n", - major, minor, - UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); - - unifi_info(card->ospriv, "Firmware build %u: %s\n", - card->build_id, card->build_id_string); - - if (major != UNIFI_HIP_MAJOR_VERSION) - { - unifi_error(card->ospriv, "UniFi f/w protocol major version (%d) is different from driver (v%d.%d)\n", - major, UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); -#ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK - return CSR_RESULT_FAILURE; -#endif - } - if (minor < UNIFI_HIP_MINOR_VERSION) - { - unifi_error(card->ospriv, "UniFi f/w protocol version (v%d.%d) is older than minimum required by driver (v%d.%d).\n", - major, minor, - UNIFI_HIP_MAJOR_VERSION, UNIFI_HIP_MINOR_VERSION); -#ifndef CSR_WIFI_DISABLE_HIP_VERSION_CHECK - return CSR_RESULT_FAILURE; -#endif - } - - /* Read panic codes from a previous firmware panic. If the firmware has - * not panicked since power was applied (e.g. power-off hard reset) - * the stored panic codes will not be updated. - */ - unifi_read_panic(card); - - return CSR_RESULT_SUCCESS; -} /* card_hw_init() */ - - -/* - * --------------------------------------------------------------------------- - * card_wait_for_unifi_to_reset - * - * Waits for a reset to complete by polling the WLAN function enable - * bit (which is cleared on reset). - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure. - * --------------------------------------------------------------------------- - */ -static CsrResult card_wait_for_unifi_to_reset(card_t *card) -{ - s16 i; - CsrResult r; - u8 io_enable; - CsrResult csrResult; - - r = CSR_RESULT_SUCCESS; - for (i = 0; i < MAILBOX2_ATTEMPTS; i++) - { - unifi_trace(card->ospriv, UDBG1, "waiting for reset to complete, attempt %d\n", i); - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - /* It's quite likely that this read will timeout for the - * first few tries - especially if we have reset via - * DBG_RESET. - */ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("m0@%02X=", SDIO_IO_READY); -#endif - csrResult = CsrSdioF0Read8(card->sdio_if, SDIO_IO_READY, &io_enable); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf("error=%X\n", csrResult); - } - else - { - unifi_debug_log_to_buf("%X\n", io_enable); - } -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - r = CSR_RESULT_SUCCESS; - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - } - } - else - { - r = sdio_read_f0(card, SDIO_IO_ENABLE, &io_enable); - } - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r == CSR_RESULT_SUCCESS) - { - u16 mbox2; - s16 enabled = io_enable & (1 << card->function); - - if (!enabled) - { - unifi_trace(card->ospriv, UDBG1, - "Reset complete (function %d is disabled) in ~ %u msecs\n", - card->function, i * MAILBOX2_TIMEOUT); - - /* Enable WLAN function and verify MAILBOX2 is zero'd */ - csrResult = CsrSdioFunctionEnable(card->sdio_if); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - unifi_error(card->ospriv, "CsrSdioFunctionEnable failed %d\n", r); - break; - } - } - - r = unifi_read_direct16(card, ChipHelper_SDIO_HIP_HANDSHAKE(card->helper) * 2, &mbox2); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "read HIP_HANDSHAKE failed %d\n", r); - break; - } - if (mbox2 != 0) - { - unifi_error(card->ospriv, "MAILBOX2 non-zero after reset (mbox2 = %04x)\n", mbox2); - r = CSR_RESULT_FAILURE; - } - break; - } - else - { - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - /* We ignore read failures for the first few reads, - * they are probably benign. */ - if (i > MAILBOX2_ATTEMPTS / 4) - { - unifi_trace(card->ospriv, UDBG1, "Failed to read CCCR IO Ready register while polling for reset\n"); - } - } - else - { - unifi_trace(card->ospriv, UDBG1, "Failed to read CCCR IO Enable register while polling for reset\n"); - } - } - CsrThreadSleep(MAILBOX2_TIMEOUT); - } - - if (r == CSR_RESULT_SUCCESS && i == MAILBOX2_ATTEMPTS) - { - unifi_trace(card->ospriv, UDBG1, "Timeout waiting for UniFi to complete reset\n"); - r = CSR_RESULT_FAILURE; - } - - return r; -} /* card_wait_for_unifi_to_reset() */ - - -/* - * --------------------------------------------------------------------------- - * card_wait_for_unifi_to_disable - * - * Waits for the function to become disabled by polling the - * IO_READY bit. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure. - * - * Notes: This function can only be used with - * card->chip_id > SDIO_CARD_ID_UNIFI_2 - * --------------------------------------------------------------------------- - */ -static CsrResult card_wait_for_unifi_to_disable(card_t *card) -{ - s16 i; - CsrResult r; - u8 io_enable; - CsrResult csrResult; - - if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) - { - unifi_error(card->ospriv, - "Function reset method not supported for chip_id=%d\n", - card->chip_id); - return CSR_RESULT_FAILURE; - } - - r = CSR_RESULT_SUCCESS; - for (i = 0; i < MAILBOX2_ATTEMPTS; i++) - { - unifi_trace(card->ospriv, UDBG1, "waiting for disable to complete, attempt %d\n", i); - - /* - * It's quite likely that this read will timeout for the - * first few tries - especially if we have reset via - * DBG_RESET. - */ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("r0@%02X=", SDIO_IO_READY); -#endif - csrResult = CsrSdioF0Read8(card->sdio_if, SDIO_IO_READY, &io_enable); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf("error=%X\n", csrResult); - } - else - { - unifi_debug_log_to_buf("%X\n", io_enable); - } -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - if (csrResult == CSR_RESULT_SUCCESS) - { - s16 enabled = io_enable & (1 << card->function); - r = CSR_RESULT_SUCCESS; - if (!enabled) - { - unifi_trace(card->ospriv, UDBG1, - "Disable complete (function %d is disabled) in ~ %u msecs\n", - card->function, i * MAILBOX2_TIMEOUT); - - break; - } - } - else - { - /* - * We ignore read failures for the first few reads, - * they are probably benign. - */ - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - if (i > (MAILBOX2_ATTEMPTS / 4)) - { - unifi_trace(card->ospriv, UDBG1, - "Failed to read CCCR IO Ready register while polling for disable\n"); - } - } - CsrThreadSleep(MAILBOX2_TIMEOUT); - } - - if ((r == CSR_RESULT_SUCCESS) && (i == MAILBOX2_ATTEMPTS)) - { - unifi_trace(card->ospriv, UDBG1, "Timeout waiting for UniFi to complete disable\n"); - r = CSR_RESULT_FAILURE; - } - - return r; -} /* card_wait_for_unifi_to_reset() */ - - -/* - * --------------------------------------------------------------------------- - * card_wait_for_firmware_to_start - * - * Polls the MAILBOX1 register for a non-zero value. - * Then reads MAILBOX0 and forms the two values into a 32-bit address - * which is returned to the caller. - * - * Arguments: - * card Pointer to card struct - * paddr Pointer to receive the UniFi address formed - * by concatenating MAILBOX1 and MAILBOX0. - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure. - * --------------------------------------------------------------------------- - */ -CsrResult card_wait_for_firmware_to_start(card_t *card, u32 *paddr) -{ - s32 i; - u16 mbox0, mbox1; - CsrResult r; - - /* - * Wait for UniFi to initialise its data structures by polling - * the SHARED_MAILBOX1 register. - * Experience shows this is typically 120ms. - */ - CsrThreadSleep(MAILBOX1_TIMEOUT); - - mbox1 = 0; - unifi_trace(card->ospriv, UDBG1, "waiting for MAILBOX1 to be non-zero...\n"); - for (i = 0; i < MAILBOX1_ATTEMPTS; i++) - { - r = unifi_read_direct16(card, ChipHelper_MAILBOX1(card->helper) * 2, &mbox1); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - /* These reads can fail if UniFi isn't up yet, so try again */ - unifi_warning(card->ospriv, "Failed to read UniFi Mailbox1 register\n"); - } - - if ((r == CSR_RESULT_SUCCESS) && (mbox1 != 0)) - { - unifi_trace(card->ospriv, UDBG1, "MAILBOX1 ready (0x%04X) in %u millisecs\n", - mbox1, i * MAILBOX1_TIMEOUT); - - /* Read the MAILBOX1 again in case we caught the value as it - * changed. */ - r = unifi_read_direct16(card, ChipHelper_MAILBOX1(card->helper) * 2, &mbox1); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read UniFi Mailbox1 register for second time\n"); - return r; - } - unifi_trace(card->ospriv, UDBG1, "MAILBOX1 value=0x%04X\n", mbox1); - - break; - } - - CsrThreadSleep(MAILBOX1_TIMEOUT); - if ((i % 100) == 99) - { - unifi_trace(card->ospriv, UDBG2, "MAILBOX1 not ready (0x%X), still trying...\n", mbox1); - } - } - - if ((r == CSR_RESULT_SUCCESS) && (mbox1 == 0)) - { - unifi_trace(card->ospriv, UDBG1, "Timeout waiting for firmware to start, Mailbox1 still 0 after %d ms\n", - MAILBOX1_ATTEMPTS * MAILBOX1_TIMEOUT); - return CSR_RESULT_FAILURE; - } - - - /* - * Complete the reset handshake by setting MAILBOX2 to 0xFFFF - */ - r = unifi_write_direct16(card, ChipHelper_SDIO_HIP_HANDSHAKE(card->helper) * 2, 0xFFFF); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write f/w startup handshake to MAILBOX2\n"); - return r; - } - - - /* - * Read the Symbol Look Up Table (SLUT) offset. - * Top 16 bits are in mbox1, read the lower 16 bits from mbox0. - */ - mbox0 = 0; - r = unifi_read_direct16(card, ChipHelper_MAILBOX0(card->helper) * 2, &mbox0); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read UniFi Mailbox0 register\n"); - return r; - } - - *paddr = (((u32)mbox1 << 16) | mbox0); - - return CSR_RESULT_SUCCESS; -} /* card_wait_for_firmware_to_start() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_capture_panic - * - * Attempt to capture panic codes from the firmware. This may involve - * warm reset of the chip to regain access following a watchdog reset. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS if panic codes were captured, or none available - * CSR_RESULT_FAILURE if the driver could not access function 1 - * --------------------------------------------------------------------------- - */ -CsrResult unifi_capture_panic(card_t *card) -{ - - /* The firmware must have previously initialised to read the panic addresses - * from the SLUT - */ - if (!card->panic_data_phy_addr || !card->panic_data_mac_addr) - { - return CSR_RESULT_SUCCESS; - } - - /* Ensure we can access function 1 following a panic/watchdog reset */ - if (card_access_panic(card) == CSR_RESULT_SUCCESS) - { - /* Read the panic codes */ - unifi_read_panic(card); - } - else - { - unifi_info(card->ospriv, "Unable to read panic codes"); - } - - return CSR_RESULT_SUCCESS; -} - - -/* - * --------------------------------------------------------------------------- - * card_access_panic - * Attempt to read the WLAN SDIO function in order to read panic codes - * and perform various reset steps to regain access if the read fails. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS if panic codes can be read - * CSR error code if panic codes can not be read - * --------------------------------------------------------------------------- - */ -static CsrResult card_access_panic(card_t *card) -{ - u16 data_u16 = 0; - s32 i; - CsrResult r, sr; - - /* A chip version of zero means that the version never got successfully read - * during reset. In this case give up because it will not be possible to - * verify the chip version. - */ - if (!card->chip_version) - { - unifi_info(card->ospriv, "Unknown chip version\n"); - return CSR_RESULT_FAILURE; - } - - /* Ensure chip is awake or access to function 1 will fail */ - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_set_host_state() failed %d\n", r); - return CSR_RESULT_FAILURE; /* Card is probably unpowered */ - } - CsrThreadSleep(20); - - for (i = 0; i < 3; i++) - { - sr = CsrSdioRead16(card->sdio_if, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION * 2, &data_u16); - if (sr != CSR_RESULT_SUCCESS || data_u16 != card->chip_version) - { - unifi_info(card->ospriv, "Failed to read valid chip version sr=%d (0x%04x want 0x%04x) try %d\n", - sr, data_u16, card->chip_version, i); - - /* Set clock speed low */ - sr = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); - if (sr != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "CsrSdioMaxBusClockFrequencySet() failed1 %d\n", sr); - r = ConvertCsrSdioToCsrHipResult(card, sr); - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; - - /* First try re-enabling function in case a f/w watchdog reset disabled it */ - if (i == 0) - { - unifi_info(card->ospriv, "Try function enable\n"); - sr = CsrSdioFunctionEnable(card->sdio_if); - if (sr != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, sr); - unifi_error(card->ospriv, "CsrSdioFunctionEnable failed %d (HIP %d)\n", sr, r); - } - continue; - } - - /* Second try, set awake */ - unifi_info(card->ospriv, "Try set awake\n"); - - /* Ensure chip is awake */ - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_set_host_state() failed2 %d\n", r); - } - - /* Set clock speed low in case setting the host state raised it, which - * would only happen if host state was previously TORPID - */ - sr = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_SAFE_HZ); - if (sr != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "CsrSdioMaxBusClockFrequencySet() failed2 %d\n", sr); - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; - - if (i == 1) - { - continue; - } - - /* Perform a s/w reset to preserve as much as the card state as possible, - * (mainly the preserve RAM). The context will be lost for coredump - but as we - * were unable to access the WLAN function for panic, the coredump would have - * also failed without a reset. - */ - unifi_info(card->ospriv, "Try s/w reset\n"); - - r = unifi_card_hard_reset(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_card_hard_reset() failed %d\n", r); - } - } - else - { - if (i > 0) - { - unifi_info(card->ospriv, "Read chip version 0x%x after %d retries\n", data_u16, i); - } - break; - } - } - - r = ConvertCsrSdioToCsrHipResult(card, sr); - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_read_panic - * Reads, saves and prints panic codes stored by the firmware in UniFi's - * preserve RAM by the last panic that occurred since chip was powered. - * Nothing is saved if the panic codes are read as zero. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * --------------------------------------------------------------------------- - */ -void unifi_read_panic(card_t *card) -{ - CsrResult r; - u16 p_code, p_arg; - - /* The firmware must have previously initialised to read the panic addresses - * from the SLUT - */ - if (!card->panic_data_phy_addr || !card->panic_data_mac_addr) - { - return; - } - - /* Get the panic data from PHY */ - r = unifi_card_read16(card, card->panic_data_phy_addr, &p_code); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_phy_addr, r); - p_code = 0; - } - if (p_code) - { - r = unifi_card_read16(card, card->panic_data_phy_addr + 2, &p_arg); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_phy_addr + 2, r); - } - unifi_error(card->ospriv, "Last UniFi PHY PANIC %04x arg %04x\n", p_code, p_arg); - card->last_phy_panic_code = p_code; - card->last_phy_panic_arg = p_arg; - } - - /* Get the panic data from MAC */ - r = unifi_card_read16(card, card->panic_data_mac_addr, &p_code); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_mac_addr, r); - p_code = 0; - } - if (p_code) - { - r = unifi_card_read16(card, card->panic_data_mac_addr + 2, &p_arg); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "capture_panic: unifi_read16 %08x failed %d\n", card->panic_data_mac_addr + 2, r); - } - unifi_error(card->ospriv, "Last UniFi MAC PANIC %04x arg %04x\n", p_code, p_arg); - card->last_mac_panic_code = p_code; - card->last_mac_panic_arg = p_arg; - } - -} - - -/* - * --------------------------------------------------------------------------- - * card_allocate_memory_resources - * - * Allocates memory for the from-host, to-host bulk data slots, - * soft queue buffers and bulk data buffers. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure. - * --------------------------------------------------------------------------- - */ -static CsrResult card_allocate_memory_resources(card_t *card) -{ - s16 n, i, k, r; - sdio_config_data_t *cfg_data; - - /* Reset any state carried forward from a previous life */ - card->fh_command_queue.q_rd_ptr = 0; - card->fh_command_queue.q_wr_ptr = 0; - (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, - "fh_cmd_q"); - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->fh_traffic_queue[i].q_rd_ptr = 0; - card->fh_traffic_queue[i].q_wr_ptr = 0; - (void)scnprintf(card->fh_traffic_queue[i].name, - UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); - } -#ifndef CSR_WIFI_HIP_TA_DISABLE - unifi_ta_sampling_init(card); -#endif - /* Convenience short-cut */ - cfg_data = &card->config_data; - - /* - * Allocate memory for the from-host and to-host signal buffers. - */ - card->fh_buffer.buf = kmalloc(UNIFI_FH_BUF_SIZE, GFP_KERNEL); - if (card->fh_buffer.buf == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - card->fh_buffer.bufsize = UNIFI_FH_BUF_SIZE; - card->fh_buffer.ptr = card->fh_buffer.buf; - card->fh_buffer.count = 0; - - card->th_buffer.buf = kmalloc(UNIFI_FH_BUF_SIZE, GFP_KERNEL); - if (card->th_buffer.buf == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - card->th_buffer.bufsize = UNIFI_FH_BUF_SIZE; - card->th_buffer.ptr = card->th_buffer.buf; - card->th_buffer.count = 0; - - - /* - * Allocate memory for the from-host and to-host bulk data slots. - * This is done as separate kmallocs because lots of smaller - * allocations are more likely to succeed than one huge one. - */ - - /* Allocate memory for the array of pointers */ - n = cfg_data->num_fromhost_data_slots; - - unifi_trace(card->ospriv, UDBG3, "Alloc from-host resources, %d slots.\n", n); - card->from_host_data = kmalloc(n * sizeof(slot_desc_t), GFP_KERNEL); - if (card->from_host_data == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for F-H bulk data array\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* Initialise from-host bulk data slots */ - for (i = 0; i < n; i++) - { - UNIFI_INIT_BULK_DATA(&card->from_host_data[i].bd); - } - - /* Allocate memory for the array used for slot host tag mapping */ - card->fh_slot_host_tag_record = kmalloc(n * sizeof(u32), GFP_KERNEL); - - if (card->fh_slot_host_tag_record == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for F-H slot host tag mapping array\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* Initialise host tag entries for from-host bulk data slots */ - for (i = 0; i < n; i++) - { - card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; - } - - - /* Allocate memory for the array of pointers */ - n = cfg_data->num_tohost_data_slots; - - unifi_trace(card->ospriv, UDBG3, "Alloc to-host resources, %d slots.\n", n); - card->to_host_data = kmalloc(n * sizeof(bulk_data_desc_t), GFP_KERNEL); - if (card->to_host_data == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for T-H bulk data array\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* Initialise to-host bulk data slots */ - for (i = 0; i < n; i++) - { - UNIFI_INIT_BULK_DATA(&card->to_host_data[i]); - } - - /* - * Initialise buffers for soft Q - */ - for (i = 0; i < UNIFI_SOFT_COMMAND_Q_LENGTH; i++) - { - for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) - { - UNIFI_INIT_BULK_DATA(&card->fh_command_q_body[i].bulkdata[r]); - } - } - - for (k = 0; k < UNIFI_NO_OF_TX_QS; k++) - { - for (i = 0; i < UNIFI_SOFT_TRAFFIC_Q_LENGTH; i++) - { - for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) - { - UNIFI_INIT_BULK_DATA(&card->fh_traffic_q_body[k][i].bulkdata[r]); - } - } - } - - card->memory_resources_allocated = 1; - - return CSR_RESULT_SUCCESS; -} /* card_allocate_memory_resources() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_free_bulk_data - * - * Free the data associated to a bulk data structure. - * - * Arguments: - * card Pointer to card struct - * bulk_data_slot Pointer to bulk data structure - * - * Returns: - * None. - * - * --------------------------------------------------------------------------- - */ -static void unifi_free_bulk_data(card_t *card, bulk_data_desc_t *bulk_data_slot) -{ - if (bulk_data_slot->data_length != 0) - { - unifi_net_data_free(card->ospriv, bulk_data_slot); - } -} /* unifi_free_bulk_data() */ - - -/* - * --------------------------------------------------------------------------- - * card_free_memory_resources - * - * Frees memory allocated for the from-host, to-host bulk data slots, - * soft queue buffers and bulk data buffers. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void card_free_memory_resources(card_t *card) -{ - - unifi_trace(card->ospriv, UDBG1, "Freeing card memory resources.\n"); - - /* Clear our internal queues */ - unifi_cancel_pending_signals(card); - - - kfree(card->to_host_data); - card->to_host_data = NULL; - - kfree(card->from_host_data); - card->from_host_data = NULL; - - /* free the memory for slot host tag mapping array */ - kfree(card->fh_slot_host_tag_record); - card->fh_slot_host_tag_record = NULL; - - kfree(card->fh_buffer.buf); - card->fh_buffer.ptr = card->fh_buffer.buf = NULL; - card->fh_buffer.bufsize = 0; - card->fh_buffer.count = 0; - - kfree(card->th_buffer.buf); - card->th_buffer.ptr = card->th_buffer.buf = NULL; - card->th_buffer.bufsize = 0; - card->th_buffer.count = 0; - - - card->memory_resources_allocated = 0; - -} /* card_free_memory_resources() */ - - -static void card_init_soft_queues(card_t *card) -{ - s16 i; - - unifi_trace(card->ospriv, UDBG1, "Initialising internal signal queues.\n"); - /* Reset any state carried forward from a previous life */ - card->fh_command_queue.q_rd_ptr = 0; - card->fh_command_queue.q_wr_ptr = 0; - (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH, - "fh_cmd_q"); - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->fh_traffic_queue[i].q_rd_ptr = 0; - card->fh_traffic_queue[i].q_wr_ptr = 0; - (void)scnprintf(card->fh_traffic_queue[i].name, - UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i); - } -#ifndef CSR_WIFI_HIP_TA_DISABLE - unifi_ta_sampling_init(card); -#endif -} - - -/* - * --------------------------------------------------------------------------- - * unifi_cancel_pending_signals - * - * Free the signals and associated bulk data, pending in the core. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void unifi_cancel_pending_signals(card_t *card) -{ - s16 i, n, r; - - unifi_trace(card->ospriv, UDBG1, "Canceling pending signals.\n"); - - if (card->to_host_data) - { - /* - * Free any bulk data buffers allocated for the t-h slots - * This will clear all buffers that did not make it to - * unifi_receive_event() before cancel was request. - */ - n = card->config_data.num_tohost_data_slots; - unifi_trace(card->ospriv, UDBG3, "Freeing to-host resources, %d slots.\n", n); - for (i = 0; i < n; i++) - { - unifi_free_bulk_data(card, &card->to_host_data[i]); - } - } - - /* - * If any of the from-host bulk data has reached the card->from_host_data - * but not UniFi, we need to free the buffers here. - */ - if (card->from_host_data) - { - /* Free any bulk data buffers allocated for the f-h slots */ - n = card->config_data.num_fromhost_data_slots; - unifi_trace(card->ospriv, UDBG3, "Freeing from-host resources, %d slots.\n", n); - for (i = 0; i < n; i++) - { - unifi_free_bulk_data(card, &card->from_host_data[i].bd); - } - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->dynamic_slot_data.from_host_used_slots[i] = 0; - card->dynamic_slot_data.from_host_max_slots[i] = 0; - card->dynamic_slot_data.from_host_reserved_slots[i] = 0; - } - } - - /* - * Free any bulk data buffers allocated in the soft queues. - * This covers the case where a bulk data pointer has reached the soft queue - * but not the card->from_host_data. - */ - unifi_trace(card->ospriv, UDBG3, "Freeing cmd q resources.\n"); - for (i = 0; i < UNIFI_SOFT_COMMAND_Q_LENGTH; i++) - { - for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) - { - unifi_free_bulk_data(card, &card->fh_command_q_body[i].bulkdata[r]); - } - } - - unifi_trace(card->ospriv, UDBG3, "Freeing traffic q resources.\n"); - for (n = 0; n < UNIFI_NO_OF_TX_QS; n++) - { - for (i = 0; i < UNIFI_SOFT_TRAFFIC_Q_LENGTH; i++) - { - for (r = 0; r < UNIFI_MAX_DATA_REFERENCES; r++) - { - unifi_free_bulk_data(card, &card->fh_traffic_q_body[n][i].bulkdata[r]); - } - } - } - - card_init_soft_queues(card); - -} /* unifi_cancel_pending_signals() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_free_card - * - * Free the memory allocated for the card structure and buffers. - * - * Notes: - * The porting layer is responsible for freeing any mini-coredump buffers - * allocated when it called unifi_coredump_init(), by calling - * unifi_coredump_free() before calling this function. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void unifi_free_card(card_t *card) -{ -#ifdef CSR_PRE_ALLOC_NET_DATA - prealloc_netdata_free(card); -#endif - /* Free any memory allocated. */ - card_free_memory_resources(card); - - /* Warn if caller didn't free coredump buffers */ - if (card->dump_buf) - { - unifi_error(card->ospriv, "Caller should call unifi_coredump_free()\n"); - unifi_coredump_free(card); /* free anyway to prevent memory leak */ - } - - kfree(card); - -} /* unifi_free_card() */ - - -/* - * --------------------------------------------------------------------------- - * card_init_slots - * - * Allocate memory for host-side slot data and signal queues. - * - * Arguments: - * card Pointer to card object - * - * Returns: - * CSR error code. - * --------------------------------------------------------------------------- - */ -static CsrResult card_init_slots(card_t *card) -{ - CsrResult r; - u8 i; - - /* Allocate the buffers we need, only once. */ - if (card->memory_resources_allocated == 1) - { - card_free_memory_resources(card); - } - else - { - /* Initialise our internal command and traffic queues */ - card_init_soft_queues(card); - } - - r = card_allocate_memory_resources(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to allocate card memory resources.\n"); - card_free_memory_resources(card); - return r; - } - - if (card->sdio_ctrl_addr == 0) - { - unifi_error(card->ospriv, "Failed to find config struct!\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* - * Set initial counts. - */ - - card->from_host_data_head = 0; - - /* Get initial signal counts from UniFi, in case it has not been reset. */ - { - u16 s; - - /* Get the from-host-signals-written count */ - r = unifi_card_read16(card, card->sdio_ctrl_addr + 0, &s); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read from-host sig written count\n"); - return r; - } - card->from_host_signals_w = (s16)s; - - /* Get the to-host-signals-written count */ - r = unifi_card_read16(card, card->sdio_ctrl_addr + 6, &s); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read to-host sig read count\n"); - return r; - } - card->to_host_signals_r = (s16)s; - } - - /* Set Initialised flag. */ - r = unifi_card_write16(card, card->init_flag_addr, 0x0001); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write initialised flag\n"); - return r; - } - - /* Dynamic queue reservation */ - memset(&card->dynamic_slot_data, 0, sizeof(card_dynamic_slot_t)); - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->dynamic_slot_data.from_host_max_slots[i] = card->config_data.num_fromhost_data_slots - - UNIFI_RESERVED_COMMAND_SLOTS; - card->dynamic_slot_data.queue_stable[i] = FALSE; - } - - card->dynamic_slot_data.packets_interval = UNIFI_PACKETS_INTERVAL; - - return CSR_RESULT_SUCCESS; -} /* card_init_slots() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_set_udi_hook - * - * Registers the udi hook that reports the sent signals to the core. - * - * Arguments: - * card Pointer to the card context struct - * udi_fn Pointer to the callback function. - * - * Returns: - * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the card pointer is invalid, - * CSR_RESULT_SUCCESS on success. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_set_udi_hook(card_t *card, udi_func_t udi_fn) -{ - if (card == NULL) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - if (card->udi_hook == NULL) - { - card->udi_hook = udi_fn; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_set_udi_hook() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_remove_udi_hook - * - * Removes the udi hook that reports the sent signals from the core. - * - * Arguments: - * card Pointer to the card context struct - * udi_fn Pointer to the callback function. - * - * Returns: - * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the card pointer is invalid, - * CSR_RESULT_SUCCESS on success. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_remove_udi_hook(card_t *card, udi_func_t udi_fn) -{ - if (card == NULL) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - if (card->udi_hook == udi_fn) - { - card->udi_hook = NULL; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_remove_udi_hook() */ - - -static void CardReassignDynamicReservation(card_t *card) -{ - u8 i; - - unifi_trace(card->ospriv, UDBG5, "Packets Txed %d %d %d %d\n", - card->dynamic_slot_data.packets_txed[0], - card->dynamic_slot_data.packets_txed[1], - card->dynamic_slot_data.packets_txed[2], - card->dynamic_slot_data.packets_txed[3]); - - /* Clear reservation and recalculate max slots */ - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - card->dynamic_slot_data.queue_stable[i] = FALSE; - card->dynamic_slot_data.from_host_reserved_slots[i] = 0; - card->dynamic_slot_data.from_host_max_slots[i] = card->config_data.num_fromhost_data_slots - - UNIFI_RESERVED_COMMAND_SLOTS; - card->dynamic_slot_data.packets_txed[i] = 0; - - unifi_trace(card->ospriv, UDBG5, "CardReassignDynamicReservation: queue %d reserved %d Max %d\n", i, - card->dynamic_slot_data.from_host_reserved_slots[i], - card->dynamic_slot_data.from_host_max_slots[i]); - } - - card->dynamic_slot_data.total_packets_txed = 0; -} - - -/* Algorithm to dynamically reserve slots. The logic is based mainly on the outstanding queue - * length. Slots are reserved for particular queues during an interval and cleared after the interval. - * Each queue has three associated variables.. a) used slots - the number of slots currently occupied - * by the queue b) reserved slots - number of slots reserved specifically for the queue c) max slots - total - * slots that this queue can actually use (may be higher than reserved slots and is dependent on reserved slots - * for other queues). - * This function is called when there are no slots available for a queue. It checks to see if there are enough - * unreserved slots sufficient for this request. If available these slots are reserved for the queue. - * If there are not enough unreserved slots, a fair share for each queue is calculated based on the total slots - * and the number of active queues (any queue with existing reservation is considered active). Queues needing - * less than their fair share are allowed to have the previously reserved slots. The remaining slots are - * distributed evenly among queues that need more than the fair share - * - * A better scheme would take current bandwidth per AC into consideration when reserving slots. An - * implementation scheme could consider the relative time/service period for slots in an AC. If the firmware - * services other ACs faster than a particular AC (packets wait in the slots longer) then it is fair to reserve - * less slots for the AC - */ -static void CardCheckDynamicReservation(card_t *card, unifi_TrafficQueue queue) -{ - u16 q_len, active_queues = 0, excess_queue_slots, div_extra_slots, - queue_fair_share, reserved_slots = 0, q, excess_need_queues = 0, unmovable_slots = 0; - s32 i; - q_t *sigq; - u16 num_data_slots = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; - - /* Calculate the pending queue length */ - sigq = &card->fh_traffic_queue[queue]; - q_len = CSR_WIFI_HIP_Q_SLOTS_USED(sigq); - - if (q_len <= card->dynamic_slot_data.from_host_reserved_slots[queue]) - { - unifi_trace(card->ospriv, UDBG5, "queue %d q_len %d already has that many reserved slots, exiting\n", queue, q_len); - return; - } - - /* Upper limit */ - if (q_len > num_data_slots) - { - q_len = num_data_slots; - } - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - if (i != (s32)queue) - { - reserved_slots += card->dynamic_slot_data.from_host_reserved_slots[i]; - } - if ((i == (s32)queue) || (card->dynamic_slot_data.from_host_reserved_slots[i] > 0)) - { - active_queues++; - } - } - - unifi_trace(card->ospriv, UDBG5, "CardCheckDynamicReservation: queue %d q_len %d\n", queue, q_len); - unifi_trace(card->ospriv, UDBG5, "Active queues %d reserved slots on other queues %d\n", - active_queues, reserved_slots); - - if (reserved_slots + q_len <= num_data_slots) - { - card->dynamic_slot_data.from_host_reserved_slots[queue] = q_len; - if (q_len == num_data_slots) - { - /* This is the common case when just 1 stream is going */ - card->dynamic_slot_data.queue_stable[queue] = TRUE; - } - } - else - { - queue_fair_share = num_data_slots / active_queues; - unifi_trace(card->ospriv, UDBG5, "queue fair share %d\n", queue_fair_share); - - /* Evenly distribute slots among active queues */ - /* Find out the queues that need excess of fair share. Also find slots allocated - * to queues less than their fair share, these slots cannot be reallocated (unmovable slots) */ - - card->dynamic_slot_data.from_host_reserved_slots[queue] = q_len; - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - if (card->dynamic_slot_data.from_host_reserved_slots[i] > queue_fair_share) - { - excess_need_queues++; - } - else - { - unmovable_slots += card->dynamic_slot_data.from_host_reserved_slots[i]; - } - } - - unifi_trace(card->ospriv, UDBG5, "Excess need queues %d\n", excess_need_queues); - - /* Now find the slots per excess demand queue */ - excess_queue_slots = (num_data_slots - unmovable_slots) / excess_need_queues; - div_extra_slots = (num_data_slots - unmovable_slots) - excess_queue_slots * excess_need_queues; - for (i = UNIFI_NO_OF_TX_QS - 1; i >= 0; i--) - { - if (card->dynamic_slot_data.from_host_reserved_slots[i] > excess_queue_slots) - { - card->dynamic_slot_data.from_host_reserved_slots[i] = excess_queue_slots; - if (div_extra_slots > 0) - { - card->dynamic_slot_data.from_host_reserved_slots[i]++; - div_extra_slots--; - } - /* No more slots will be allocated to this queue during the current interval */ - card->dynamic_slot_data.queue_stable[i] = TRUE; - unifi_trace(card->ospriv, UDBG5, "queue stable %d\n", i); - } - } - } - - /* Redistribute max slots */ - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - reserved_slots = 0; - for (q = 0; q < UNIFI_NO_OF_TX_QS; q++) - { - if (i != q) - { - reserved_slots += card->dynamic_slot_data.from_host_reserved_slots[q]; - } - } - - card->dynamic_slot_data.from_host_max_slots[i] = num_data_slots - reserved_slots; - unifi_trace(card->ospriv, UDBG5, "queue %d reserved %d Max %d\n", i, - card->dynamic_slot_data.from_host_reserved_slots[i], - card->dynamic_slot_data.from_host_max_slots[i]); - } - -} - - -/* - * --------------------------------------------------------------------------- - * CardClearFromHostDataSlot - * - * Clear a the given data slot, making it available again. - * - * Arguments: - * card Pointer to Card object - * slot Index of the signal slot to clear. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void CardClearFromHostDataSlot(card_t *card, const s16 slot) -{ - u8 queue = card->from_host_data[slot].queue; - const void *os_data_ptr = card->from_host_data[slot].bd.os_data_ptr; - - if (card->from_host_data[slot].bd.data_length == 0) - { - unifi_warning(card->ospriv, - "Surprise: request to clear an already free FH data slot: %d\n", - slot); - return; - } - - if (os_data_ptr == NULL) - { - unifi_warning(card->ospriv, - "Clearing FH data slot %d: has null payload, len=%d\n", - slot, card->from_host_data[slot].bd.data_length); - } - - /* Free card->from_host_data[slot].bd.os_net_ptr here. */ - /* Mark slot as free by setting length to 0. */ - unifi_free_bulk_data(card, &card->from_host_data[slot].bd); - if (queue < UNIFI_NO_OF_TX_QS) - { - if (card->dynamic_slot_data.from_host_used_slots[queue] == 0) - { - unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n", - queue, - card->dynamic_slot_data.from_host_used_slots[queue]); - } - else - { - card->dynamic_slot_data.from_host_used_slots[queue]--; - } - card->dynamic_slot_data.packets_txed[queue]++; - card->dynamic_slot_data.total_packets_txed++; - if (card->dynamic_slot_data.total_packets_txed >= card->dynamic_slot_data.packets_interval) - { - CardReassignDynamicReservation(card); - } - } - - unifi_trace(card->ospriv, UDBG4, "CardClearFromHostDataSlot: slot %d recycled %p\n", slot, os_data_ptr); - -} /* CardClearFromHostDataSlot() */ - - -#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL -/* - * --------------------------------------------------------------------------- - * CardClearFromHostDataSlotWithoutFreeingBulkData - * - * Clear the given data slot with out freeing the bulk data. - * - * Arguments: - * card Pointer to Card object - * slot Index of the signal slot to clear. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const s16 slot) -{ - u8 queue = card->from_host_data[slot].queue; - - /* Initialise the from_host data slot so it can be re-used, - * Set length field in from_host_data array to 0. - */ - UNIFI_INIT_BULK_DATA(&card->from_host_data[slot].bd); - - queue = card->from_host_data[slot].queue; - - if (queue < UNIFI_NO_OF_TX_QS) - { - if (card->dynamic_slot_data.from_host_used_slots[queue] == 0) - { - unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n", - queue, - card->dynamic_slot_data.from_host_used_slots[queue]); - } - else - { - card->dynamic_slot_data.from_host_used_slots[queue]--; - } - card->dynamic_slot_data.packets_txed[queue]++; - card->dynamic_slot_data.total_packets_txed++; - if (card->dynamic_slot_data.total_packets_txed >= - card->dynamic_slot_data.packets_interval) - { - CardReassignDynamicReservation(card); - } - } -} /* CardClearFromHostDataSlotWithoutFreeingBulkData() */ - - -#endif - -u16 CardGetDataSlotSize(card_t *card) -{ - return card->config_data.data_slot_size; -} /* CardGetDataSlotSize() */ - - -/* - * --------------------------------------------------------------------------- - * CardGetFreeFromHostDataSlots - * - * Retrieve the number of from-host bulk data slots available. - * - * Arguments: - * card Pointer to the card context struct - * - * Returns: - * Number of free from-host bulk data slots. - * --------------------------------------------------------------------------- - */ -u16 CardGetFreeFromHostDataSlots(card_t *card) -{ - u16 i, n = 0; - - /* First two slots reserved for MLME */ - for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) - { - if (card->from_host_data[i].bd.data_length == 0) - { - /* Free slot */ - n++; - } - } - - return n; -} /* CardGetFreeFromHostDataSlots() */ - - -/* - * --------------------------------------------------------------------------- - * CardAreAllFromHostDataSlotsEmpty - * - * Returns the state of from-host bulk data slots. - * - * Arguments: - * card Pointer to the card context struct - * - * Returns: - * 1 The from-host bulk data slots are all empty (available). - * 0 Some or all the from-host bulk data slots are in use. - * --------------------------------------------------------------------------- - */ -u16 CardAreAllFromHostDataSlotsEmpty(card_t *card) -{ - u16 i; - - for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) - { - if (card->from_host_data[i].bd.data_length != 0) - { - return 0; - } - } - - return 1; -} /* CardGetFreeFromHostDataSlots() */ - - -static CsrResult unifi_identify_hw(card_t *card) -{ - - card->chip_id = card->sdio_if->sdioId.cardId; - card->function = card->sdio_if->sdioId.sdioFunction; - card->sdio_io_block_size = card->sdio_if->blockSize; - - /* If SDIO controller doesn't support byte mode CMD53, pad transfers to block sizes */ - card->sdio_io_block_pad = (card->sdio_if->features & CSR_SDIO_FEATURE_BYTE_MODE)?FALSE : TRUE; - - /* - * Setup the chip helper so that we can access the registers (and - * also tell what sub-type of HIP we should use). - */ - card->helper = ChipHelper_GetVersionSdio((u8)card->chip_id); - if (!card->helper) - { - unifi_error(card->ospriv, "Null ChipHelper\n"); - } - - unifi_info(card->ospriv, "Chip ID 0x%02X Function %u Block Size %u Name %s(%s)\n", - card->chip_id, card->function, card->sdio_io_block_size, - ChipHelper_MarketingName(card->helper), - ChipHelper_FriendlyName(card->helper)); - - return CSR_RESULT_SUCCESS; -} /* unifi_identify_hw() */ - - -static CsrResult unifi_prepare_hw(card_t *card) -{ - CsrResult r; - CsrResult csrResult; - enum unifi_host_state old_state = card->host_state; - - r = unifi_identify_hw(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to identify hw\n"); - return r; - } - - unifi_trace(card->ospriv, UDBG1, - "%s mode SDIO\n", card->sdio_io_block_pad?"Block" : "Byte"); - /* - * Chip must be a awake or blocks that are asleep may not get - * reset. We can only do this after we have read the chip_id. - */ - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - - if (old_state == UNIFI_HOST_STATE_TORPID) - { - /* Ensure the initial clock rate is set; if a reset occurred when the chip was - * TORPID, unifi_set_host_state() may have raised it to MAX. - */ - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - return r; - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; - } - - /* - * The WLAN function must be enabled to access MAILBOX2 and DEBUG_RST - * registers. - */ - csrResult = CsrSdioFunctionEnable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - /* Can't enable WLAN function. Try resetting the SDIO block. */ - unifi_error(card->ospriv, "Failed to re-enable function %d.\n", card->function); - return r; - } - - /* - * Poke some registers to make sure the PLL has started, - * otherwise memory accesses are likely to fail. - */ - bootstrap_chip_hw(card); - - /* Try to read the chip version from register. */ - r = unifi_read_chip_version(card); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_prepare_hw() */ - - -static CsrResult unifi_read_chip_version(card_t *card) -{ - u32 gbl_chip_version; - CsrResult r; - u16 ver; - - gbl_chip_version = ChipHelper_GBL_CHIP_VERSION(card->helper); - - /* Try to read the chip version from register. */ - if (gbl_chip_version != 0) - { - r = unifi_read_direct16(card, gbl_chip_version * 2, &ver); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read GBL_CHIP_VERSION\n"); - return r; - } - card->chip_version = ver; - } - else - { - unifi_info(card->ospriv, "Unknown Chip ID, cannot locate GBL_CHIP_VERSION\n"); - r = CSR_RESULT_FAILURE; - } - - unifi_info(card->ospriv, "Chip Version 0x%04X\n", card->chip_version); - - return r; -} /* unifi_read_chip_version() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_reset_hardware - * - * Execute the UniFi reset sequence. - * - * Note: This may fail if the chip is going TORPID so retry at - * least once. - * - * Arguments: - * card - pointer to card context structure - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error otherwise. - * - * Notes: - * Some platforms (e.g. Windows Vista) do not allow access to registers - * that are necessary for a software soft reset. - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_reset_hardware(card_t *card) -{ - CsrResult r; - u16 new_block_size = UNIFI_IO_BLOCK_SIZE; - CsrResult csrResult; - - /* Errors returned by unifi_prepare_hw() are not critical at this point */ - r = unifi_prepare_hw(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - - /* First try SDIO controller reset, which may power cycle the UniFi, assert - * its reset line, or not be implemented depending on the platform. - */ - unifi_info(card->ospriv, "Calling CsrSdioHardReset\n"); - csrResult = CsrSdioHardReset(card->sdio_if); - if (csrResult == CSR_RESULT_SUCCESS) - { - unifi_info(card->ospriv, "CsrSdioHardReset succeeded on resetting UniFi\n"); - r = unifi_prepare_hw(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_prepare_hw failed after hard reset\n"); - return r; - } - } - else if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - else - { - /* Falling back to software hard reset methods */ - unifi_info(card->ospriv, "Falling back to software hard reset\n"); - r = unifi_card_hard_reset(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "software hard reset failed\n"); - return r; - } - - /* If we fell back to unifi_card_hard_reset() methods, chip version may - * not have been read. (Note in the unlikely event that it is zero, - * it will be harmlessly read again) - */ - if (card->chip_version == 0) - { - r = unifi_read_chip_version(card); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - } - } - -#ifdef CSR_WIFI_HIP_SDIO_BLOCK_SIZE - new_block_size = CSR_WIFI_HIP_SDIO_BLOCK_SIZE; -#endif - - /* After hard reset, we need to restore the SDIO block size */ - csrResult = CsrSdioBlockSizeSet(card->sdio_if, new_block_size); - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - - /* Warn if a different block size was achieved by the transport */ - if (card->sdio_if->blockSize != new_block_size) - { - unifi_info(card->ospriv, - "Actually got block size %d\n", card->sdio_if->blockSize); - } - - /* sdio_io_block_size always needs be updated from the achieved block size, - * as it is used by the OS layer to allocate memory in unifi_net_malloc(). - * Controllers which don't support block mode (e.g. CSPI) will report a - * block size of zero. - */ - if (card->sdio_if->blockSize == 0) - { - unifi_info(card->ospriv, "Block size 0, block mode not available\n"); - - /* Set sdio_io_block_size to 1 so that unifi_net_data_malloc() has a - * sensible rounding value. Elsewhere padding will already be - * disabled because the controller supports byte mode. - */ - card->sdio_io_block_size = 1; - - /* Controller features must declare support for byte mode */ - if (!(card->sdio_if->features & CSR_SDIO_FEATURE_BYTE_MODE)) - { - unifi_error(card->ospriv, "Requires byte mode\n"); - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - } - else - { - /* Padding will be enabled if CSR_SDIO_FEATURE_BYTE_MODE isn't set */ - card->sdio_io_block_size = card->sdio_if->blockSize; - } - - - return r; -} /* unifi_reset_hardware() */ - - -/* - * --------------------------------------------------------------------------- - * card_reset_method_io_enable - * - * Issue a hard reset to the hw writing the IO_ENABLE. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * 0 on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred or if a response - * was not seen in the expected time - * --------------------------------------------------------------------------- - */ -static CsrResult card_reset_method_io_enable(card_t *card) -{ - CsrResult r; - CsrResult csrResult; - - /* - * This resets only function 1, so should be used in - * preference to the method below (CSR_FUNC_EN) - */ - unifi_trace(card->ospriv, UDBG1, "Hard reset (IO_ENABLE)\n"); - - csrResult = CsrSdioFunctionDisable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - unifi_warning(card->ospriv, "SDIO error writing IO_ENABLE: %d\n", r); - } - else - { - /* Delay here to let the reset take affect. */ - CsrThreadSleep(RESET_SETTLE_DELAY); - - r = card_wait_for_unifi_to_disable(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - - if (r == CSR_RESULT_SUCCESS) - { - r = card_wait_for_unifi_to_reset(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - } - } - - if (r != CSR_RESULT_SUCCESS) - { - unifi_trace(card->ospriv, UDBG1, "Hard reset (CSR_FUNC_EN)\n"); - - r = sdio_write_f0(card, SDIO_CSR_FUNC_EN, 0); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_warning(card->ospriv, "SDIO error writing SDIO_CSR_FUNC_EN: %d\n", r); - return r; - } - else - { - /* Delay here to let the reset take affect. */ - CsrThreadSleep(RESET_SETTLE_DELAY); - - r = card_wait_for_unifi_to_reset(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - } - } - - if (r != CSR_RESULT_SUCCESS) - { - unifi_warning(card->ospriv, "card_reset_method_io_enable failed to reset UniFi\n"); - } - - return r; -} /* card_reset_method_io_enable() */ - - -/* - * --------------------------------------------------------------------------- - * card_reset_method_dbg_reset - * - * Issue a hard reset to the hw writing the DBG_RESET. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred or if a response - * was not seen in the expected time - * --------------------------------------------------------------------------- - */ -static CsrResult card_reset_method_dbg_reset(card_t *card) -{ - CsrResult r; - - /* - * Prepare UniFi for h/w reset - */ - if (card->host_state == UNIFI_HOST_STATE_TORPID) - { - r = unifi_set_host_state(card, UNIFI_HOST_STATE_DROWSY); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to set UNIFI_HOST_STATE_DROWSY\n"); - return r; - } - CsrThreadSleep(5); - } - - r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Can't stop processors\n"); - return r; - } - - unifi_trace(card->ospriv, UDBG1, "Hard reset (DBG_RESET)\n"); - - /* - * This register write may fail. The debug reset resets - * parts of the Function 0 sections of the chip, and - * therefore the response cannot be sent back to the host. - */ - r = unifi_write_direct_8_or_16(card, ChipHelper_DBG_RESET(card->helper) * 2, 1); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_warning(card->ospriv, "SDIO error writing DBG_RESET: %d\n", r); - return r; - } - - /* Delay here to let the reset take affect. */ - CsrThreadSleep(RESET_SETTLE_DELAY); - - r = card_wait_for_unifi_to_reset(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_warning(card->ospriv, "card_reset_method_dbg_reset failed to reset UniFi\n"); - } - - return r; -} /* card_reset_method_dbg_reset() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_hard_reset - * - * Issue reset to hardware, by writing to registers on the card. - * Power to the card is preserved. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred or if a response - * was not seen in the expected time - * --------------------------------------------------------------------------- - */ -CsrResult unifi_card_hard_reset(card_t *card) -{ - CsrResult r; - const struct chip_helper_reset_values *init_data; - u32 chunks; - - /* Clear cache of page registers */ - card->proc_select = (u32)(-1); - card->dmem_page = (u32)(-1); - card->pmem_page = (u32)(-1); - - /* - * We need to have a valid card->helper before we use software hard reset. - * If unifi_identify_hw() fails to get the card ID, it probably means - * that there is no way to talk to the h/w. - */ - r = unifi_identify_hw(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_card_hard_reset failed to identify h/w\n"); - return r; - } - - /* Search for some reset code. */ - chunks = ChipHelper_HostResetSequence(card->helper, &init_data); - if (chunks != 0) - { - unifi_error(card->ospriv, - "Hard reset (Code download) is unsupported\n"); - - return CSR_RESULT_FAILURE; - } - - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - /* The HIP spec considers this a bus-specific reset. - * This resets only function 1, so should be used in - * preference to the method below (CSR_FUNC_EN) - * If this method fails, it means that the f/w is probably - * not running. In this case, try the DBG_RESET method. - */ - r = card_reset_method_io_enable(card); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r == CSR_RESULT_SUCCESS) - { - return r; - } - } - - /* Software hard reset */ - r = card_reset_method_dbg_reset(card); - - return r; -} /* unifi_card_hard_reset() */ - - -/* - * --------------------------------------------------------------------------- - * - * CardGenInt - * - * Prod the card. - * This function causes an internal interrupt to be raised in the - * UniFi chip. It is used to signal the firmware that some action has - * been completed. - * The UniFi Host Interface asks that the value used increments for - * debugging purposes. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred or if a response - * was not seen in the expected time - * --------------------------------------------------------------------------- - */ -CsrResult CardGenInt(card_t *card) -{ - CsrResult r; - - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - r = sdio_write_f0(card, SDIO_CSR_FROM_HOST_SCRATCH0, - (u8)card->unifi_interrupt_seq); - } - else - { - r = unifi_write_direct_8_or_16(card, - ChipHelper_SHARED_IO_INTERRUPT(card->helper) * 2, - (u8)card->unifi_interrupt_seq); - } - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error writing UNIFI_SHARED_IO_INTERRUPT: %d\n", r); - return r; - } - - card->unifi_interrupt_seq++; - - return CSR_RESULT_SUCCESS; -} /* CardGenInt() */ - - -/* - * --------------------------------------------------------------------------- - * CardEnableInt - * - * Enable the outgoing SDIO interrupt from UniFi to the host. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred, - * --------------------------------------------------------------------------- - */ -CsrResult CardEnableInt(card_t *card) -{ - CsrResult r; - u8 int_enable; - - r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); - return r; - } - - int_enable |= (1 << card->function) | UNIFI_SD_INT_ENABLE_IENM; - - r = sdio_write_f0(card, SDIO_INT_ENABLE, int_enable); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error writing SDIO_INT_ENABLE\n"); - return r; - } - - return CSR_RESULT_SUCCESS; -} /* CardEnableInt() */ - - -/* - * --------------------------------------------------------------------------- - * CardDisableInt - * - * Disable the outgoing SDIO interrupt from UniFi to the host. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred, - * --------------------------------------------------------------------------- - */ -CsrResult CardDisableInt(card_t *card) -{ - CsrResult r; - u8 int_enable; - - r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); - return r; - } - - int_enable &= ~(1 << card->function); - - r = sdio_write_f0(card, SDIO_INT_ENABLE, int_enable); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error writing SDIO_INT_ENABLE\n"); - return r; - } - - return CSR_RESULT_SUCCESS; -} /* CardDisableInt() */ - - -/* - * --------------------------------------------------------------------------- - * CardPendingInt - * - * Determine whether UniFi is currently asserting the SDIO interrupt - * request. - * - * Arguments: - * card Pointer to Card object - * pintr Pointer to location to write interrupt status, - * TRUE if interrupt pending, - * FALSE if no interrupt pending. - * Returns: - * CSR_RESULT_SUCCESS interrupt status read successfully - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred, - * --------------------------------------------------------------------------- - */ -CsrResult CardPendingInt(card_t *card, u8 *pintr) -{ - CsrResult r; - u8 pending; - - *pintr = FALSE; - - r = sdio_read_f0(card, SDIO_INT_PENDING, &pending); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error reading SDIO_INT_PENDING\n"); - return r; - } - - *pintr = (pending & (1 << card->function))?TRUE : FALSE; - - return CSR_RESULT_SUCCESS; -} /* CardPendingInt() */ - - -/* - * --------------------------------------------------------------------------- - * CardClearInt - * - * Clear the UniFi SDIO interrupt request. - * - * Arguments: - * card Pointer to Card object - * - * Returns: - * CSR_RESULT_SUCCESS if pending interrupt was cleared, or no pending interrupt. - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred, - * --------------------------------------------------------------------------- - */ -CsrResult CardClearInt(card_t *card) -{ - CsrResult r; - u8 intr; - - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - /* CardPendingInt() sets intr, if there is a pending interrupt */ - r = CardPendingInt(card, &intr); - if (intr == FALSE) - { - return r; - } - - r = sdio_write_f0(card, SDIO_CSR_HOST_INT_CLEAR, 1); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error writing SDIO_CSR_HOST_INT_CLEAR\n"); - } - } - else - { - r = unifi_write_direct_8_or_16(card, - ChipHelper_SDIO_HOST_INT(card->helper) * 2, - 0); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error writing UNIFI_SDIO_HOST_INT\n"); - } - } - - return r; -} /* CardClearInt() */ - - -/* - * --------------------------------------------------------------------------- - * CardIntEnabled - * - * Determine whether UniFi is currently asserting the SDIO interrupt - * request. - * - * Arguments: - * card Pointer to Card object - * enabled Pointer to location to write interrupt enable status, - * TRUE if interrupts enabled, - * FALSE if interupts disabled. - * - * Returns: - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred, - * --------------------------------------------------------------------------- - */ -CsrResult CardIntEnabled(card_t *card, u8 *enabled) -{ - CsrResult r; - u8 int_enable; - - r = sdio_read_f0(card, SDIO_INT_ENABLE, &int_enable); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "SDIO error reading SDIO_INT_ENABLE\n"); - return r; - } - - *enabled = (int_enable & (1 << card->function))?TRUE : FALSE; - - return CSR_RESULT_SUCCESS; -} /* CardIntEnabled() */ - - -/* - * --------------------------------------------------------------------------- - * CardWriteBulkData - * Allocate slot in the pending bulkdata arrays and assign it to a signal's - * bulkdata reference. The slot is then ready for UniFi's bulkdata commands - * to transfer the data to/from the host. - * - * Arguments: - * card Pointer to Card object - * csptr Pending signal pointer, including bulkdata ref - * queue Traffic queue that this signal is using - * - * Returns: - * CSR_RESULT_SUCCESS if a free slot was assigned - * CSR_RESULT_FAILURE if no slot was available - * --------------------------------------------------------------------------- - */ -CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQueue queue) -{ - u16 i, slots[UNIFI_MAX_DATA_REFERENCES], j = 0; - u8 *packed_sigptr, num_slots_required = 0; - bulk_data_desc_t *bulkdata = csptr->bulkdata; - s16 h, nslots; - - /* Count the number of slots required */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - if (bulkdata[i].data_length != 0) - { - num_slots_required++; - } - } - - /* Get the slot numbers */ - if (num_slots_required != 0) - { - /* Last 2 slots for MLME */ - if (queue == UNIFI_TRAFFIC_Q_MLME) - { - h = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; - for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) - { - if (card->from_host_data[h].bd.data_length == 0) - { - /* Free data slot, claim it */ - slots[j++] = h; - if (j == num_slots_required) - { - break; - } - } - - if (++h >= card->config_data.num_fromhost_data_slots) - { - h = 0; - } - } - } - else - { - if (card->dynamic_slot_data.from_host_used_slots[queue] - < card->dynamic_slot_data.from_host_max_slots[queue]) - { - /* Data commands get a free slot only after a few checks */ - nslots = card->config_data.num_fromhost_data_slots - UNIFI_RESERVED_COMMAND_SLOTS; - - h = card->from_host_data_head; - - for (i = 0; i < nslots; i++) - { - if (card->from_host_data[h].bd.data_length == 0) - { - /* Free data slot, claim it */ - slots[j++] = h; - if (j == num_slots_required) - { - break; - } - } - - if (++h >= nslots) - { - h = 0; - } - } - card->from_host_data_head = h; - } - } - - /* Required number of slots are not available, bail out */ - if (j != num_slots_required) - { - unifi_trace(card->ospriv, UDBG5, "CardWriteBulkData: didn't find free slot/s\n"); - - /* If we haven't already reached the stable state we can ask for reservation */ - if ((queue != UNIFI_TRAFFIC_Q_MLME) && (card->dynamic_slot_data.queue_stable[queue] == FALSE)) - { - CardCheckDynamicReservation(card, queue); - } - - for (i = 0; i < card->config_data.num_fromhost_data_slots; i++) - { - unifi_trace(card->ospriv, UDBG5, "fh data slot %d: %d\n", i, card->from_host_data[i].bd.data_length); - } - return CSR_RESULT_FAILURE; - } - } - - packed_sigptr = csptr->sigbuf; - - /* Fill in the slots with data */ - j = 0; - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - if (bulkdata[i].data_length == 0) - { - /* Zero-out the DATAREF in the signal */ - SET_PACKED_DATAREF_SLOT(packed_sigptr, i, 0); - SET_PACKED_DATAREF_LEN(packed_sigptr, i, 0); - } - else - { - /* - * Fill in the slot number in the SIGNAL structure but - * preserve the offset already in there - */ - SET_PACKED_DATAREF_SLOT(packed_sigptr, i, slots[j] | (((u16)packed_sigptr[SIZEOF_SIGNAL_HEADER + (i * SIZEOF_DATAREF) + 1]) << 8)); - SET_PACKED_DATAREF_LEN(packed_sigptr, i, bulkdata[i].data_length); - - /* Do not copy the data, just store the information to them */ - card->from_host_data[slots[j]].bd.os_data_ptr = bulkdata[i].os_data_ptr; - card->from_host_data[slots[j]].bd.os_net_buf_ptr = bulkdata[i].os_net_buf_ptr; - card->from_host_data[slots[j]].bd.data_length = bulkdata[i].data_length; - card->from_host_data[slots[j]].bd.net_buf_length = bulkdata[i].net_buf_length; - card->from_host_data[slots[j]].queue = queue; - - unifi_trace(card->ospriv, UDBG4, "CardWriteBulkData sig=0x%x, fh slot %d = %p\n", - GET_SIGNAL_ID(packed_sigptr), i, bulkdata[i].os_data_ptr); - - /* Sanity-check that the bulk data desc being assigned to the slot - * actually has a payload. - */ - if (!bulkdata[i].os_data_ptr) - { - unifi_error(card->ospriv, "Assign null os_data_ptr (len=%d) fh slot %d, i=%d, q=%d, sig=0x%x", - bulkdata[i].data_length, slots[j], i, queue, GET_SIGNAL_ID(packed_sigptr)); - } - - j++; - if (queue < UNIFI_NO_OF_TX_QS) - { - card->dynamic_slot_data.from_host_used_slots[queue]++; - } - } - } - - return CSR_RESULT_SUCCESS; -} /* CardWriteBulkData() */ - - -/* - * --------------------------------------------------------------------------- - * card_find_data_slot - * - * Dereference references to bulk data slots into pointers to real data. - * - * Arguments: - * card Pointer to the card struct. - * slot Slot number from a signal structure - * - * Returns: - * Pointer to entry in bulk_data_slot array. - * --------------------------------------------------------------------------- - */ -bulk_data_desc_t* card_find_data_slot(card_t *card, s16 slot) -{ - s16 sn; - bulk_data_desc_t *bd; - - sn = slot & 0x7FFF; - - /* ?? check sanity of slot number ?? */ - - if (slot & SLOT_DIR_TO_HOST) - { - bd = &card->to_host_data[sn]; - } - else - { - bd = &card->from_host_data[sn].bd; - } - - return bd; -} /* card_find_data_slot() */ - - -/* - * --------------------------------------------------------------------------- - * firmware_present_in_flash - * - * Probe for external Flash that looks like it might contain firmware. - * - * If Flash is not present, reads always return 0x0008. - * If Flash is present, but empty, reads return 0xFFFF. - * Anything else is considered to be firmware. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS firmware is present in ROM or flash - * CSR_WIFI_HIP_RESULT_NOT_FOUND firmware is not present in ROM or flash - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred - * --------------------------------------------------------------------------- - */ -static CsrResult firmware_present_in_flash(card_t *card) -{ - CsrResult r; - u16 m1, m5; - - if (ChipHelper_HasRom(card->helper)) - { - return CSR_RESULT_SUCCESS; - } - if (!ChipHelper_HasFlash(card->helper)) - { - return CSR_WIFI_HIP_RESULT_NOT_FOUND; - } - - /* - * Examine the Flash locations that are the power-on default reset - * vectors of the XAP processors. - * These are words 1 and 5 in Flash. - */ - r = unifi_card_read16(card, UNIFI_MAKE_GP(EXT_FLASH, 2), &m1); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - r = unifi_card_read16(card, UNIFI_MAKE_GP(EXT_FLASH, 10), &m5); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - /* Check for uninitialised/missing flash */ - if ((m1 == 0x0008) || (m1 == 0xFFFF) || - (m1 == 0x0004) || (m5 == 0x0004) || - (m5 == 0x0008) || (m5 == 0xFFFF)) - { - return CSR_WIFI_HIP_RESULT_NOT_FOUND; - } - - return CSR_RESULT_SUCCESS; -} /* firmware_present_in_flash() */ - - -/* - * --------------------------------------------------------------------------- - * bootstrap_chip_hw - * - * Perform chip specific magic to "Get It Working" TM. This will - * increase speed of PLLs in analogue and maybe enable some - * on-chip regulators. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void bootstrap_chip_hw(card_t *card) -{ - const struct chip_helper_init_values *vals; - u32 i, len; - void *sdio = card->sdio_if; - CsrResult csrResult; - - len = ChipHelper_ClockStartupSequence(card->helper, &vals); - if (len != 0) - { - for (i = 0; i < len; i++) - { - csrResult = CsrSdioWrite16(sdio, vals[i].addr * 2, vals[i].value); - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_warning(card->ospriv, "Failed to write bootstrap value %d\n", i); - /* Might not be fatal */ - } - - CsrThreadSleep(1); - } - } -} /* bootstrap_chip_hw() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_stop_processor - * - * Stop the UniFi XAP processors. - * - * Arguments: - * card Pointer to card struct - * which One of UNIFI_PROC_MAC, UNIFI_PROC_PHY, UNIFI_PROC_BOTH - * - * Returns: - * CSR_RESULT_SUCCESS if successful, or CSR error code - * --------------------------------------------------------------------------- - */ -CsrResult unifi_card_stop_processor(card_t *card, enum unifi_dbg_processors_select which) -{ - CsrResult r = CSR_RESULT_SUCCESS; - u8 status; - s16 retry = 100; - - while (retry--) - { - /* Select both XAPs */ - r = unifi_set_proc_select(card, which); - if (r != CSR_RESULT_SUCCESS) - { - break; - } - - /* Stop processors */ - r = unifi_write_direct16(card, ChipHelper_DBG_EMU_CMD(card->helper) * 2, 2); - if (r != CSR_RESULT_SUCCESS) - { - break; - } - - /* Read status */ - r = unifi_read_direct_8_or_16(card, - ChipHelper_DBG_HOST_STOP_STATUS(card->helper) * 2, - &status); - if (r != CSR_RESULT_SUCCESS) - { - break; - } - - if ((status & 1) == 1) - { - /* Success! */ - return CSR_RESULT_SUCCESS; - } - - /* Processors didn't stop, try again */ - } - - if (r != CSR_RESULT_SUCCESS) - { - /* An SDIO error occurred */ - unifi_error(card->ospriv, "Failed to stop processors: SDIO error\n"); - } - else - { - /* If we reach here, we didn't the status in time. */ - unifi_error(card->ospriv, "Failed to stop processors: timeout waiting for stopped status\n"); - r = CSR_RESULT_FAILURE; - } - - return r; -} /* unifi_card_stop_processor() */ - - -/* - * --------------------------------------------------------------------------- - * card_start_processor - * - * Start the UniFi XAP processors. - * - * Arguments: - * card Pointer to card struct - * which One of UNIFI_PROC_MAC, UNIFI_PROC_PHY, UNIFI_PROC_BOTH - * - * Returns: - * CSR_RESULT_SUCCESS or CSR error code - * --------------------------------------------------------------------------- - */ -CsrResult card_start_processor(card_t *card, enum unifi_dbg_processors_select which) -{ - CsrResult r; - - /* Select both XAPs */ - r = unifi_set_proc_select(card, which); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "unifi_set_proc_select failed: %d.\n", r); - return r; - } - - - r = unifi_write_direct_8_or_16(card, - ChipHelper_DBG_EMU_CMD(card->helper) * 2, 8); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - r = unifi_write_direct_8_or_16(card, - ChipHelper_DBG_EMU_CMD(card->helper) * 2, 0); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - return CSR_RESULT_SUCCESS; -} /* card_start_processor() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_set_interrupt_mode - * - * Configure the interrupt processing mode used by the HIP - * - * Arguments: - * card Pointer to card struct - * mode Interrupt mode to apply - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -void unifi_set_interrupt_mode(card_t *card, u32 mode) -{ - if (mode == CSR_WIFI_INTMODE_RUN_BH_ONCE) - { - unifi_info(card->ospriv, "Scheduled interrupt mode"); - } - card->intmode = mode; -} /* unifi_set_interrupt_mode() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_start_processors - * - * Start all UniFi XAP processors. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on error - * --------------------------------------------------------------------------- - */ -CsrResult unifi_start_processors(card_t *card) -{ - return card_start_processor(card, UNIFI_PROC_BOTH); -} /* unifi_start_processors() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_request_max_sdio_clock - * - * Requests that the maximum SDIO clock rate is set at the next suitable - * opportunity (e.g. when the BH next runs, so as not to interfere with - * any current operation). - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -void unifi_request_max_sdio_clock(card_t *card) -{ - card->request_max_clock = 1; -} /* unifi_request_max_sdio_clock() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_set_host_state - * - * Set the host deep-sleep state. - * - * If transitioning to TORPID, the SDIO driver will be notified - * that the SD bus will be unused (idle) and conversely, when - * transitioning from TORPID that the bus will be used (active). - * - * Arguments: - * card Pointer to card struct - * state New deep-sleep state. - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CSR_WIFI_HIP_RESULT_NO_DEVICE if the card was ejected - * CSR_RESULT_FAILURE if an SDIO error occurred - * - * Notes: - * We need to reduce the SDIO clock speed before trying to wake up the - * chip. Actually, in the implementation below we reduce the clock speed - * not just before we try to wake up the chip, but when we put the chip to - * deep sleep. This means that if the f/w wakes up on its' own, we waste - * a reduce/increace cycle. However, trying to eliminate this overhead is - * proved difficult, as the current state machine in the HIP lib does at - * least a CMD52 to disable the interrupts before we configure the host - * state. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_set_host_state(card_t *card, enum unifi_host_state state) -{ - CsrResult r = CSR_RESULT_SUCCESS; - CsrResult csrResult; - static const char *const states[] = { - "AWAKE", "DROWSY", "TORPID" - }; - static const u8 state_csr_host_wakeup[] = { - 1, 3, 0 - }; - static const u8 state_io_abort[] = { - 0, 2, 3 - }; - - unifi_trace(card->ospriv, UDBG4, "State %s to %s\n", - states[card->host_state], states[state]); - - if (card->host_state == UNIFI_HOST_STATE_TORPID) - { - CsrSdioFunctionActive(card->sdio_if); - } - - /* Write the new state to UniFi. */ - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - r = sdio_write_f0(card, SDIO_CSR_HOST_WAKEUP, - (u8)((card->function << 4) | state_csr_host_wakeup[state])); - } - else - { - r = sdio_write_f0(card, SDIO_IO_ABORT, state_io_abort[state]); - } - - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write UniFi deep sleep state\n"); - } - else - { - /* - * If the chip was in state TORPID then we can now increase - * the maximum bus clock speed. - */ - if (card->host_state == UNIFI_HOST_STATE_TORPID) - { - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, - UNIFI_SDIO_CLOCK_MAX_HZ); - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - /* Non-fatal error */ - if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - unifi_warning(card->ospriv, - "Failed to increase the SDIO clock speed\n"); - } - else - { - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_MAX_HZ; - } - } - - /* - * Cache the current state in the card structure to avoid - * unnecessary SDIO reads. - */ - card->host_state = state; - - if (state == UNIFI_HOST_STATE_TORPID) - { - /* - * If the chip is now in state TORPID then we must now decrease - * the maximum bus clock speed. - */ - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, - UNIFI_SDIO_CLOCK_SAFE_HZ); - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - unifi_warning(card->ospriv, - "Failed to decrease the SDIO clock speed\n"); - } - else - { - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_SAFE_HZ; - } - CsrSdioFunctionIdle(card->sdio_if); - } - } - - return r; -} /* unifi_set_host_state() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_info - * - * Update the card information data structure - * - * Arguments: - * card Pointer to card struct - * card_info Pointer to info structure to update - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -void unifi_card_info(card_t *card, card_info_t *card_info) -{ - card_info->chip_id = card->chip_id; - card_info->chip_version = card->chip_version; - card_info->fw_build = card->build_id; - card_info->fw_hip_version = card->config_data.version; - card_info->sdio_block_size = card->sdio_io_block_size; -} /* unifi_card_info() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_check_io_status - * - * Check UniFi for spontaneous reset and pending interrupt. - * - * Arguments: - * card Pointer to card struct - * status Pointer to location to write chip status: - * 0 if UniFi is running, and no interrupt pending - * 1 if UniFi has spontaneously reset - * 2 if there is a pending interrupt - * Returns: - * CSR_RESULT_SUCCESS if OK, or CSR error - * --------------------------------------------------------------------------- - */ -CsrResult unifi_check_io_status(card_t *card, s32 *status) -{ - u8 io_en; - CsrResult r; - u8 pending; - - *status = 0; - - r = sdio_read_f0(card, SDIO_IO_ENABLE, &io_en); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read SDIO_IO_ENABLE to check for spontaneous reset\n"); - return r; - } - - if ((io_en & (1 << card->function)) == 0) - { - s32 fw_count; - *status = 1; - unifi_error(card->ospriv, "UniFi has spontaneously reset.\n"); - - /* - * These reads are very likely to fail. We want to know if the function is really - * disabled or the SDIO driver just returns rubbish. - */ - fw_count = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); - if (fw_count < 0) - { - unifi_error(card->ospriv, "Failed to read to-host sig written count\n"); - } - else - { - unifi_error(card->ospriv, "thsw: %u (driver thinks is %u)\n", - fw_count, card->to_host_signals_w); - } - fw_count = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); - if (fw_count < 0) - { - unifi_error(card->ospriv, "Failed to read from-host sig read count\n"); - } - else - { - unifi_error(card->ospriv, "fhsr: %u (driver thinks is %u)\n", - fw_count, card->from_host_signals_r); - } - - return r; - } - - unifi_info(card->ospriv, "UniFi function %d is enabled.\n", card->function); - - /* See if we missed an SDIO interrupt */ - r = CardPendingInt(card, &pending); - if (pending) - { - unifi_error(card->ospriv, "There is an unhandled pending interrupt.\n"); - *status = 2; - return r; - } - - return r; -} /* unifi_check_io_status() */ - - -void unifi_get_hip_qos_info(card_t *card, unifi_HipQosInfo *hipqosinfo) -{ - s32 count_fhr; - s16 t; - u32 occupied_fh; - - q_t *sigq; - u16 nslots, i; - - memset(hipqosinfo, 0, sizeof(unifi_HipQosInfo)); - - nslots = card->config_data.num_fromhost_data_slots; - - for (i = 0; i < nslots; i++) - { - if (card->from_host_data[i].bd.data_length == 0) - { - hipqosinfo->free_fh_bulkdata_slots++; - } - } - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - { - sigq = &card->fh_traffic_queue[i]; - t = sigq->q_wr_ptr - sigq->q_rd_ptr; - if (t < 0) - { - t += sigq->q_length; - } - hipqosinfo->free_fh_sig_queue_slots[i] = (sigq->q_length - t) - 1; - } - - count_fhr = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); - if (count_fhr < 0) - { - unifi_error(card->ospriv, "Failed to read from-host sig read count - %d\n", count_fhr); - hipqosinfo->free_fh_fw_slots = 0xfa; - return; - } - - occupied_fh = (card->from_host_signals_w - count_fhr) % 128; - - hipqosinfo->free_fh_fw_slots = (u16)(card->config_data.num_fromhost_sig_frags - occupied_fh); -} - - - -CsrResult ConvertCsrSdioToCsrHipResult(card_t *card, CsrResult csrResult) -{ - CsrResult r = CSR_RESULT_FAILURE; - - switch (csrResult) - { - case CSR_RESULT_SUCCESS: - r = CSR_RESULT_SUCCESS; - break; - /* Timeout errors */ - case CSR_SDIO_RESULT_TIMEOUT: - /* Integrity errors */ - case CSR_SDIO_RESULT_CRC_ERROR: - r = CSR_RESULT_FAILURE; - break; - case CSR_SDIO_RESULT_NO_DEVICE: - r = CSR_WIFI_HIP_RESULT_NO_DEVICE; - break; - case CSR_SDIO_RESULT_INVALID_VALUE: - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - break; - case CSR_RESULT_FAILURE: - r = CSR_RESULT_FAILURE; - break; - default: - unifi_warning(card->ospriv, "Unrecognised csrResult error code: %d\n", csrResult); - break; - } - - return r; -} /* ConvertCsrSdioToCsrHipResult() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.h b/drivers/staging/csr/csr_wifi_hip_card_sdio.h deleted file mode 100644 index a9b9ec427320..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio.h +++ /dev/null @@ -1,694 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * - * FILE: csr_wifi_hip_card_sdio.h - * - * PURPOSE: - * Internal header for Card API for SDIO. - * --------------------------------------------------------------------------- - */ -#ifndef __CARD_SDIO_H__ -#define __CARD_SDIO_H__ - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifi_udi.h" -#include "csr_wifi_hip_unifihw.h" -#include "csr_wifi_hip_unifiversion.h" -#ifndef CSR_WIFI_HIP_TA_DISABLE -#include "csr_wifi_hip_ta_sampling.h" -#endif -#include "csr_wifi_hip_xbv.h" -#include "csr_wifi_hip_chiphelper.h" - - -/* - * - * Configuration items. - * Which of these should go in a platform unifi_config.h file? - * - */ - -/* - * When the traffic queues contain more signals than there is space for on - * UniFi, a limiting algorithm comes into play. - * If a traffic queue has enough slots free to buffer more traffic from the - * network stack, then the following check is applied. The number of free - * slots is RESUME_XMIT_THRESHOLD. - */ -#define RESUME_XMIT_THRESHOLD 4 - - -/* - * When reading signals from UniFi, the host processes pending all signals - * and then acknowledges them together in a single write to update the - * to-host-chunks-read location. - * When there is more than one bulk data transfer (e.g. one received data - * packet and a request for the payload data of a transmitted packet), the - * update can be delayed significantly. This ties up resources on chip. - * - * To remedy this problem, to-host-chunks-read is updated after processing - * a signal if TO_HOST_FLUSH_THRESHOLD bytes of bulk data have been - * transferred since the last update. - */ -#define TO_HOST_FLUSH_THRESHOLD (500 * 5) - - -/* SDIO Card Common Control Registers */ -#define SDIO_CCCR_SDIO_REVISION (0x00) -#define SDIO_SD_SPEC_REVISION (0x01) -#define SDIO_IO_ENABLE (0x02) -#define SDIO_IO_READY (0x03) -#define SDIO_INT_ENABLE (0x04) -#define SDIO_INT_PENDING (0x05) -#define SDIO_IO_ABORT (0x06) -#define SDIO_BUS_IFACE_CONTROL (0x07) -#define SDIO_CARD_CAPABILOTY (0x08) -#define SDIO_COMMON_CIS_POINTER (0x09) -#define SDIO_BUS_SUSPEND (0x0C) -#define SDIO_FUNCTION_SELECT (0x0D) -#define SDIO_EXEC_FLAGS (0x0E) -#define SDIO_READY_FLAGS (0x0F) -#define SDIO_FN0_BLOCK_SIZE (0x10) -#define SDIO_POWER_CONTROL (0x12) -#define SDIO_VENDOR_START (0xF0) - -#define SDIO_CSR_HOST_WAKEUP (0xf0) -#define SDIO_CSR_HOST_INT_CLEAR (0xf1) -#define SDIO_CSR_FROM_HOST_SCRATCH0 (0xf2) -#define SDIO_CSR_FROM_HOST_SCRATCH1 (0xf3) -#define SDIO_CSR_TO_HOST_SCRATCH0 (0xf4) -#define SDIO_CSR_TO_HOST_SCRATCH1 (0xf5) -#define SDIO_CSR_FUNC_EN (0xf6) -#define SDIO_CSR_CSPI_MODE (0xf7) -#define SDIO_CSR_CSPI_STATUS (0xf8) -#define SDIO_CSR_CSPI_PADDING (0xf9) - - -#define UNIFI_SD_INT_ENABLE_IENM 0x0001 /* Master INT Enable */ - -#ifdef CSR_PRE_ALLOC_NET_DATA -#define BULK_DATA_PRE_ALLOC_NUM 16 -#endif - -/* - * Structure to hold configuration information read from UniFi. - */ -typedef struct -{ - /* - * The version of the SDIO signal queues and bulk data pools - * configuration structure. The MSB is the major version number, used to - * indicate incompatible changes. The LSB gives the minor revision number, - * used to indicate changes that maintain backwards compatibility. - */ - u16 version; - - /* - * offset from the start of the shared data memory to the SD IO - * control structure. - */ - u16 sdio_ctrl_offset; - - /* Buffer handle of the from-host signal queue */ - u16 fromhost_sigbuf_handle; - - /* Buffer handle of the to-host signal queue */ - u16 tohost_sigbuf_handle; - - /* - * Maximum number of signal primitive or bulk data command fragments that may be - * pending in the to-hw signal queue. - */ - u16 num_fromhost_sig_frags; - - /* - * Number of signal primitive or bulk data command fragments that must be pending - * in the to-host signal queue before the host will generate an interrupt - * to indicate that it has read a signal. This will usually be the total - * capacity of the to-host signal buffer less the size of the largest signal - * primitive divided by the signal primitive fragment size, but may be set - * to 1 to request interrupts every time that the host read a signal. - * Note that the hw may place more signals in the to-host signal queue - * than indicated by this field. - */ - u16 num_tohost_sig_frags; - - /* - * Number of to-hw bulk data slots. Slots are numbered from 0 (zero) to - * one less than the value in this field - */ - u16 num_fromhost_data_slots; - - /* - * Number of frm-hw bulk data slots. Slots are numbered from 0 (zero) to - * one less than the value in this field - */ - u16 num_tohost_data_slots; - - /* - * Size of the bulk data slots (2 octets) - * The size of the bulk data slots in octets. This will usually be - * the size of the largest MSDU. The value should always be even. - */ - u16 data_slot_size; - - /* - * Indicates that the host has finished the initialisation sequence. - * Initialised to 0x0000 by the firmware, and set to 0x0001 by us. - */ - u16 initialised; - - /* Added by protocol version 0x0001 */ - u32 overlay_size; - - /* Added by protocol version 0x0300 */ - u16 data_slot_round; - u16 sig_frag_size; - - /* Added by protocol version 0x0500 */ - u16 tohost_signal_padding; -} sdio_config_data_t; - -/* - * These values may change with versions of the Host Interface Protocol. - */ -/* - * Size of config info block pointed to by the CSR_SLT_SDIO_SLOT_CONFIG - * entry in the f/w symbol table - */ -#define SDIO_CONFIG_DATA_SIZE 30 - -/* Offset of the INIT flag in the config info block. */ -#define SDIO_INIT_FLAG_OFFSET 0x12 -#define SDIO_TO_HOST_SIG_PADDING_OFFSET 0x1C - - -/* Structure for a bulk data transfer command */ -typedef struct -{ - u16 cmd_and_len; /* bits 12-15 cmd, bits 0-11 len */ - u16 data_slot; /* slot number, perhaps OR'd with SLOT_DIR_TO_HOST */ - u16 offset; - u16 buffer_handle; -} bulk_data_cmd_t; - - -/* Bulk Data signal command values */ -#define SDIO_CMD_SIGNAL 0x00 -#define SDIO_CMD_TO_HOST_TRANSFER 0x01 -#define SDIO_CMD_TO_HOST_TRANSFER_ACK 0x02 /*deprecated*/ -#define SDIO_CMD_FROM_HOST_TRANSFER 0x03 -#define SDIO_CMD_FROM_HOST_TRANSFER_ACK 0x04 /*deprecated*/ -#define SDIO_CMD_CLEAR_SLOT 0x05 -#define SDIO_CMD_OVERLAY_TRANSFER 0x06 -#define SDIO_CMD_OVERLAY_TRANSFER_ACK 0x07 /*deprecated*/ -#define SDIO_CMD_FROM_HOST_AND_CLEAR 0x08 -#define SDIO_CMD_PADDING 0x0f - -#define SLOT_DIR_TO_HOST 0x8000 - - -/* Initialise bulkdata slot - * params: - * bulk_data_desc_t *bulk_data_slot - */ -#define UNIFI_INIT_BULK_DATA(bulk_data_slot) \ - { \ - (bulk_data_slot)->os_data_ptr = NULL; \ - (bulk_data_slot)->data_length = 0; \ - (bulk_data_slot)->os_net_buf_ptr = NULL; \ - (bulk_data_slot)->net_buf_length = 0; \ - } - -/* - * Structure to contain a SIGNAL datagram. - * This is used to build signal queues between the main driver and the - * i/o thread. - * The fields are: - * sigbuf Contains the HIP signal is wire-format (i.e. packed, - * little-endian) - * bulkdata Contains a copy of any associated bulk data - * signal_length The size of the signal in the sigbuf - */ -typedef struct card_signal -{ - u8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; - - /* Length of the SIGNAL inside sigbuf */ - u16 signal_length; - - bulk_data_desc_t bulkdata[UNIFI_MAX_DATA_REFERENCES]; -} card_signal_t; - - -/* - * Control structure for a generic ring buffer. - */ -#define UNIFI_QUEUE_NAME_MAX_LENGTH 16 -typedef struct -{ - card_signal_t *q_body; - - /* Num elements in queue (capacity is one less than this!) */ - u16 q_length; - - u16 q_wr_ptr; - u16 q_rd_ptr; - - char name[UNIFI_QUEUE_NAME_MAX_LENGTH]; -} q_t; - - -#define UNIFI_RESERVED_COMMAND_SLOTS 2 - -/* Considering approx 500 us per packet giving 0.5 secs */ -#define UNIFI_PACKETS_INTERVAL 1000 - -/* - * Dynamic slot reservation for QoS - */ -typedef struct -{ - u16 from_host_used_slots[UNIFI_NO_OF_TX_QS]; - u16 from_host_max_slots[UNIFI_NO_OF_TX_QS]; - u16 from_host_reserved_slots[UNIFI_NO_OF_TX_QS]; - - /* Parameters to determine if a queue was active. - If number of packets sent is greater than the threshold - for the queue, the queue is considered active and no - re reservation is done, it is important not to keep this - value too low */ - /* Packets sent during this interval */ - u16 packets_txed[UNIFI_NO_OF_TX_QS]; - u16 total_packets_txed; - - /* Number of packets to see if slots need to be reassigned */ - u16 packets_interval; - - /* Once a queue reaches a stable state, avoid processing */ - u8 queue_stable[UNIFI_NO_OF_TX_QS]; -} card_dynamic_slot_t; - - -/* These are type-safe and don't write incorrect values to the - * structure. */ - -/* Return queue slots used count - * params: - * const q_t *q - * returns: - * u16 - */ -#define CSR_WIFI_HIP_Q_SLOTS_USED(q) \ - (((q)->q_wr_ptr - (q)->q_rd_ptr < 0)? \ - ((q)->q_wr_ptr - (q)->q_rd_ptr + (q)->q_length) : ((q)->q_wr_ptr - (q)->q_rd_ptr)) - -/* Return queue slots free count - * params: - * const q_t *q - * returns: - * u16 - */ -#define CSR_WIFI_HIP_Q_SLOTS_FREE(q) \ - ((q)->q_length - CSR_WIFI_HIP_Q_SLOTS_USED((q)) - 1) - -/* Return slot signal data pointer - * params: - * const q_t *q - * u16 slot - * returns: - * card_signal_t * - */ -#define CSR_WIFI_HIP_Q_SLOT_DATA(q, slot) \ - ((q)->q_body + slot) - -/* Return queue next read slot - * params: - * const q_t *q - * returns: - * u16 slot offset - */ -#define CSR_WIFI_HIP_Q_NEXT_R_SLOT(q) \ - ((q)->q_rd_ptr) - -/* Return queue next write slot - * params: - * const q_t *q - * returns: - * u16 slot offset - */ -#define CSR_WIFI_HIP_Q_NEXT_W_SLOT(q) \ - ((q)->q_wr_ptr) - -/* Return updated queue pointer wrapped around its length - * params: - * const q_t *q - * u16 x amount to add to queue pointer - * returns: - * u16 wrapped queue pointer - */ -#define CSR_WIFI_HIP_Q_WRAP(q, x) \ - ((((x) >= (q)->q_length)?((x) % (q)->q_length) : (x))) - -/* Advance queue read pointer - * params: - * const q_t *q - */ -#define CSR_WIFI_HIP_Q_INC_R(q) \ - ((q)->q_rd_ptr = CSR_WIFI_HIP_Q_WRAP((q), (q)->q_rd_ptr + 1)) - -/* Advance queue write pointer - * params: - * const q_t *q - */ -#define CSR_WIFI_HIP_Q_INC_W(q) \ - ((q)->q_wr_ptr = CSR_WIFI_HIP_Q_WRAP((q), (q)->q_wr_ptr + 1)) - -enum unifi_host_state -{ - UNIFI_HOST_STATE_AWAKE = 0, - UNIFI_HOST_STATE_DROWSY = 1, - UNIFI_HOST_STATE_TORPID = 2 -}; - -typedef struct -{ - bulk_data_desc_t bd; - unifi_TrafficQueue queue; /* Used for dynamic slot reservation */ -} slot_desc_t; - -/* - * Structure describing a UniFi SDIO card. - */ -struct card -{ - /* - * Back pointer for the higher level OS code. This is passed as - * an argument to callbacks (e.g. for received data and indications). - */ - void *ospriv; - - /* - * mapping of HIP slot to MA-PACKET.req host tag, the - * array is indexed by slot numbers and each index stores - * information of the last host tag it was used for - */ - u32 *fh_slot_host_tag_record; - - - /* Info read from Symbol Table during probe */ - u32 build_id; - char build_id_string[128]; - - /* Retrieve from SDIO driver. */ - u16 chip_id; - - /* Read from GBL_CHIP_VERSION. */ - u16 chip_version; - - /* From the SDIO driver (probably 1) */ - u8 function; - - /* This is sused to get the register addresses and things. */ - ChipDescript *helper; - - /* - * Bit mask of PIOs for the loader to waggle during download. - * We assume these are connected to LEDs. The main firmware gets - * the mask from a MIB entry. - */ - s32 loader_led_mask; - - /* - * Support for flow control. When the from-host queue of signals - * is full, we ask the host upper layer to stop sending packets. When - * the queue drains we tell it that it can send packets again. - * We use this flag to remember the current state. - */ -#define card_is_tx_q_paused(card, q) (card->tx_q_paused_flag[q]) -#define card_tx_q_unpause(card, q) (card->tx_q_paused_flag[q] = 0) -#define card_tx_q_pause(card, q) (card->tx_q_paused_flag[q] = 1) - - u16 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX + 1 + UNIFI_NO_OF_TX_QS]; /* defensive more than big enough */ - - /* UDI callback for logging UniFi interactions */ - udi_func_t udi_hook; - - u8 bh_reason_host; - u8 bh_reason_unifi; - - /* SDIO clock speed request from OS layer */ - u8 request_max_clock; - - /* Last SDIO clock frequency set */ - u32 sdio_clock_speed; - - /* - * Current host state (copy of value in IOABORT register and - * spinlock to protect it. - */ - enum unifi_host_state host_state; - - enum unifi_low_power_mode low_power_mode; - enum unifi_periodic_wake_mode periodic_wake_mode; - - /* - * Ring buffer of signal structs for a queue of data packets from - * the host. - * The queue is empty when fh_data_q_num_rd == fh_data_q_num_wr. - * To add a packet to the queue, copy it to index given by - * (fh_data_q_num_wr%UNIFI_SOFT_Q_LENGTH) and advance fh_data_q_num_wr. - * To take a packet from the queue, copy data from index given by - * (fh_data_q_num_rd%UNIFI_SOFT_Q_LENGTH) and advance fh_data_q_num_rd. - * fh_data_q_num_rd and fh_data_q_num_rd are both modulo 256. - */ - card_signal_t fh_command_q_body[UNIFI_SOFT_COMMAND_Q_LENGTH]; - q_t fh_command_queue; - - card_signal_t fh_traffic_q_body[UNIFI_NO_OF_TX_QS][UNIFI_SOFT_TRAFFIC_Q_LENGTH]; - q_t fh_traffic_queue[UNIFI_NO_OF_TX_QS]; - - /* - * Signal counts from UniFi SDIO Control Data Structure. - * These are cached and synchronised with the UniFi before and after - * a batch of operations. - * - * These are the modulo-256 count of signals written to or read from UniFi - * The value is incremented for every signal. - */ - s32 from_host_signals_w; - s32 from_host_signals_r; - s32 to_host_signals_r; - s32 to_host_signals_w; - - - /* Should specify buffer size as a number of signals */ - /* - * Enough for 10 th and 10 fh data slots: - * 1 * 10 * 8 = 80 - * 2 * 10 * 8 = 160 - */ -#define UNIFI_FH_BUF_SIZE 1024 - struct sigbuf - { - u8 *buf; /* buffer area */ - u8 *ptr; /* current pos */ - u16 count; /* signal count */ - u16 bufsize; - } fh_buffer; - struct sigbuf th_buffer; - - - /* - * Field to use for the incrementing value to write to the UniFi - * SHARED_IO_INTERRUPT register. - * Flag to say we need to generate an interrupt at end of processing. - */ - u32 unifi_interrupt_seq; - u8 generate_interrupt; - - - /* Pointers to the bulk data slots */ - slot_desc_t *from_host_data; - bulk_data_desc_t *to_host_data; - - - /* - * Index of the next (hopefully) free data slot. - * This is an optimisation that starts searching at a more likely point - * than the beginning. - */ - s16 from_host_data_head; - - /* Dynamic slot allocation for queues */ - card_dynamic_slot_t dynamic_slot_data; - - /* - * SDIO specific fields - */ - - /* Interface pointer for the SDIO library */ - CsrSdioFunction *sdio_if; - - /* Copy of config_data struct from the card */ - sdio_config_data_t config_data; - - /* SDIO address of the Initialised flag and Control Data struct */ - u32 init_flag_addr; - u32 sdio_ctrl_addr; - - /* The last value written to the Shared Data Memory Page register */ - u32 proc_select; - u32 dmem_page; - u32 pmem_page; - - /* SDIO traffic counters limited to 32 bits for Synergy compatibility */ - u32 sdio_bytes_read; - u32 sdio_bytes_written; - - u8 memory_resources_allocated; - - /* UniFi SDIO I/O Block size. */ - u16 sdio_io_block_size; - - /* Pad transfer sizes to SDIO block boundaries */ - u8 sdio_io_block_pad; - - /* Read from the XBV */ - struct FWOV fwov; - -#ifndef CSR_WIFI_HIP_TA_DISABLE - /* TA sampling */ - ta_data_t ta_sampling; -#endif - - /* Auto-coredump */ - s16 request_coredump_on_reset; /* request coredump on next reset */ - struct coredump_buf *dump_buf; /* root node */ - struct coredump_buf *dump_next_write; /* node to fill at next dump */ - struct coredump_buf *dump_cur_read; /* valid node to read, or NULL */ - -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - struct cmd_profile - { - u32 cmd52_count; - u32 cmd53_count; - u32 tx_count; - u32 tx_cfm_count; - u32 rx_count; - u32 bh_count; - u32 process_count; - u32 protocol_count; - - u32 cmd52_f0_r_count; - u32 cmd52_f0_w_count; - u32 cmd52_r8or16_count; - u32 cmd52_w8or16_count; - u32 cmd52_r16_count; - u32 cmd52_w16_count; - u32 cmd52_r32_count; - - u32 sdio_cmd_signal; - u32 sdio_cmd_clear_slot; - u32 sdio_cmd_to_host; - u32 sdio_cmd_from_host; - u32 sdio_cmd_from_host_and_clear; - } hip_prof; - struct cmd_profile cmd_prof; -#endif - - /* Interrupt processing mode flags */ - u32 intmode; - -#ifdef UNIFI_DEBUG - u8 lsb; -#endif - - /* Historic firmware panic codes */ - u32 panic_data_phy_addr; - u32 panic_data_mac_addr; - u16 last_phy_panic_code; - u16 last_phy_panic_arg; - u16 last_mac_panic_code; - u16 last_mac_panic_arg; -#ifdef CSR_PRE_ALLOC_NET_DATA - bulk_data_desc_t bulk_data_desc_list[BULK_DATA_PRE_ALLOC_NUM]; - u16 prealloc_netdata_r; - u16 prealloc_netdata_w; -#endif -}; /* struct card */ - - -/* Reset types */ -enum unifi_reset_type -{ - UNIFI_COLD_RESET = 1, - UNIFI_WARM_RESET = 2 -}; - -/* - * unifi_set_host_state() implements signalling for waking UniFi from - * deep sleep. The host indicates to UniFi that it is in one of three states: - * Torpid - host has nothing to send, UniFi can go to sleep. - * Drowsy - host has data to send to UniFi. UniFi will respond with an - * SDIO interrupt. When hosts responds it moves to Awake. - * Awake - host has data to transfer, UniFi must stay awake. - * When host has finished, it moves to Torpid. - */ -CsrResult unifi_set_host_state(card_t *card, enum unifi_host_state state); - - -CsrResult unifi_set_proc_select(card_t *card, enum unifi_dbg_processors_select select); -s32 card_read_signal_counts(card_t *card); -bulk_data_desc_t* card_find_data_slot(card_t *card, s16 slot); - - -CsrResult unifi_read32(card_t *card, u32 unifi_addr, u32 *pdata); -CsrResult unifi_readnz(card_t *card, u32 unifi_addr, - void *pdata, u16 len); -s32 unifi_read_shared_count(card_t *card, u32 addr); - -CsrResult unifi_writen(card_t *card, u32 unifi_addr, void *pdata, u16 len); - -CsrResult unifi_bulk_rw(card_t *card, u32 handle, - void *pdata, u32 len, s16 direction); -CsrResult unifi_bulk_rw_noretry(card_t *card, u32 handle, - void *pdata, u32 len, s16 direction); -#define UNIFI_SDIO_READ 0 -#define UNIFI_SDIO_WRITE 1 - -CsrResult unifi_read_8_or_16(card_t *card, u32 unifi_addr, u8 *pdata); -CsrResult unifi_write_8_or_16(card_t *card, u32 unifi_addr, u8 data); -CsrResult unifi_read_direct_8_or_16(card_t *card, u32 addr, u8 *pdata); -CsrResult unifi_write_direct_8_or_16(card_t *card, u32 addr, u8 data); - -CsrResult unifi_read_direct16(card_t *card, u32 addr, u16 *pdata); -CsrResult unifi_read_direct32(card_t *card, u32 addr, u32 *pdata); -CsrResult unifi_read_directn(card_t *card, u32 addr, void *pdata, u16 len); - -CsrResult unifi_write_direct16(card_t *card, u32 addr, u16 data); -CsrResult unifi_write_directn(card_t *card, u32 addr, void *pdata, u16 len); - -CsrResult sdio_read_f0(card_t *card, u32 addr, u8 *pdata); -CsrResult sdio_write_f0(card_t *card, u32 addr, u8 data); - -void unifi_read_panic(card_t *card); -#ifdef CSR_PRE_ALLOC_NET_DATA -void prealloc_netdata_free(card_t *card); -CsrResult prealloc_netdata_alloc(card_t *card); -#endif -/* For diagnostic use */ -void dump(void *mem, u16 len); -void dump16(void *mem, u16 len); - -#endif /* __CARD_SDIO_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c deleted file mode 100644 index cfe186e07071..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c +++ /dev/null @@ -1,2595 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_card_sdio_intr.c - * - * PURPOSE: - * Interrupt processing for the UniFi SDIO driver. - * - * We may need another signal queue of responses to UniFi to hold - * bulk data commands generated by read_to_host_signals(). - * - * --------------------------------------------------------------------------- - */ -#undef CSR_WIFI_HIP_NOISY - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "csr_wifi_hip_card.h" -#include "csr_wifi_hip_xbv.h" - - -/* - * If the SDIO link is idle for this time (in milliseconds), - * signal UniFi to go into Deep Sleep. - * Valid return value of unifi_bh(). - */ -#define UNIFI_DEFAULT_HOST_IDLE_TIMEOUT 5 -/* - * If the UniFi has not woken up for this time (in milliseconds), - * signal the bottom half to take action. - * Valid return value of unifi_bh(). - */ -#define UNIFI_DEFAULT_WAKE_TIMEOUT 1000 - - -static CsrResult process_bh(card_t *card); -static CsrResult handle_host_protocol(card_t *card, u8 *processed_something); - -static CsrResult flush_fh_buffer(card_t *card); - -static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space); - -static CsrResult read_to_host_signals(card_t *card, s32 *processed); -static CsrResult process_to_host_signals(card_t *card, s32 *processed); - -static CsrResult process_bulk_data_command(card_t *card, - const u8 *cmdptr, - s16 cmd, u16 len); -static CsrResult process_clear_slot_command(card_t *card, - const u8 *cmdptr); -static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed); -static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed); -static void restart_packet_flow(card_t *card); -static CsrResult process_clock_request(card_t *card); - -#ifdef CSR_WIFI_HIP_NOISY -s16 dump_fh_buf = 0; -#endif /* CSR_WIFI_HIP_NOISY */ - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - -/* - * The unifi_debug_output buffer can be used to debug the HIP behaviour offline - * i.e. without using the tracing functions that change the timing. - * - * Call unifi_debug_log_to_buf() with printf arguments to store a string into - * unifi_debug_output. When unifi_debug_buf_dump() is called, the contents of the - * buffer are dumped with dump_str() which has to be implemented in the - * OS layer, during the porting exercise. The offset printed, holds the - * offset where the last character is (always a zero). - * - */ - -#define UNIFI_DEBUG_GBUFFER_SIZE 8192 -static char unifi_debug_output[UNIFI_DEBUG_GBUFFER_SIZE]; -static char *unifi_dbgbuf_ptr = unifi_debug_output; -static char *unifi_dbgbuf_start = unifi_debug_output; - -static void append_char(char c) -{ - /* write char and advance pointer */ - *unifi_dbgbuf_ptr++ = c; - /* wrap pointer at end of buffer */ - if ((unifi_dbgbuf_ptr - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE) - { - unifi_dbgbuf_ptr = unifi_debug_output; - } -} /* append_char() */ - - -void unifi_debug_string_to_buf(const char *str) -{ - const char *p = str; - while (*p) - { - append_char(*p); - p++; - } - /* Update start-of-buffer pointer */ - unifi_dbgbuf_start = unifi_dbgbuf_ptr + 1; - if ((unifi_dbgbuf_start - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE) - { - unifi_dbgbuf_start = unifi_debug_output; - } -} - - -void unifi_debug_log_to_buf(const char *fmt, ...) -{ -#define DEBUG_BUFFER_SIZE 80 - static char s[DEBUG_BUFFER_SIZE]; - va_list args; - - va_start(args, fmt); - vsnprintf(s, DEBUG_BUFFER_SIZE, fmt, args); - va_end(args); - - unifi_debug_string_to_buf(s); -} /* unifi_debug_log_to_buf() */ - - -/* Convert signed 32 bit (or less) integer to string */ -static void CsrUInt16ToHex(u16 number, char *str) -{ - u16 index; - u16 currentValue; - - for (index = 0; index < 4; index++) - { - currentValue = (u16) (number & 0x000F); - number >>= 4; - str[3 - index] = (char) (currentValue > 9 ? currentValue + 55 : currentValue + '0'); - } - str[4] = '\0'; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_debug_hex_to_buf - * - * puts the contents of the passed buffer into the debug buffer as a hex string - * - * Arguments: - * buff buffer to print as hex - * length number of chars to print - * - * Returns: - * None. - * - * --------------------------------------------------------------------------- - */ -void unifi_debug_hex_to_buf(const char *buff, u16 length) -{ - char s[5]; - u16 i; - - for (i = 0; i < length; i = i + 2) - { - CsrUInt16ToHex(*((u16 *)(buff + i)), s); - unifi_debug_string_to_buf(s); - } -} - - -void unifi_debug_buf_dump(void) -{ - s32 offset = unifi_dbgbuf_ptr - unifi_debug_output; - - unifi_error(NULL, "HIP debug buffer offset=%d\n", offset); - dump_str(unifi_debug_output + offset, UNIFI_DEBUG_GBUFFER_SIZE - offset); - dump_str(unifi_debug_output, offset); -} /* unifi_debug_buf_dump() */ - - -#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ - -#ifdef CSR_PRE_ALLOC_NET_DATA -#define NETDATA_PRE_ALLOC_BUF_SIZE 8000 - -void prealloc_netdata_free(card_t *card) -{ - unifi_warning(card->ospriv, "prealloc_netdata_free: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); - - while (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length != 0) - { - unifi_warning(card->ospriv, "prealloc_netdata_free: r=%d\n", card->prealloc_netdata_r); - - unifi_net_data_free(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_r]); - card->prealloc_netdata_r++; - card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM; - } - card->prealloc_netdata_r = card->prealloc_netdata_w = 0; - - unifi_warning(card->ospriv, "prealloc_netdata_free: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); -} - - -CsrResult prealloc_netdata_alloc(card_t *card) -{ - CsrResult r; - - unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); - - while (card->bulk_data_desc_list[card->prealloc_netdata_w].data_length == 0) - { - r = unifi_net_data_malloc(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_w], NETDATA_PRE_ALLOC_BUF_SIZE); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "prealloc_netdata_alloc: Failed to allocate t-h bulk data\n"); - return CSR_RESULT_FAILURE; - } - card->prealloc_netdata_w++; - card->prealloc_netdata_w %= BULK_DATA_PRE_ALLOC_NUM; - } - unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); - - return CSR_RESULT_SUCCESS; -} - - -static CsrResult prealloc_netdata_get(card_t *card, bulk_data_desc_t *bulk_data_slot, u32 size) -{ - CsrResult r; - - unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); - - if (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0) - { - unifi_error(card->ospriv, "prealloc_netdata_get: data_length = 0\n"); - } - - if ((size > NETDATA_PRE_ALLOC_BUF_SIZE) || (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0)) - { - unifi_warning(card->ospriv, "prealloc_netdata_get: Calling net_data_malloc\n"); - - r = unifi_net_data_malloc(card->ospriv, bulk_data_slot, size); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "prealloc_netdata_get: Failed to allocate t-h bulk data\n"); - return CSR_RESULT_FAILURE; - } - return CSR_RESULT_SUCCESS; - } - - *bulk_data_slot = card->bulk_data_desc_list[card->prealloc_netdata_r]; - card->bulk_data_desc_list[card->prealloc_netdata_r].os_data_ptr = NULL; - card->bulk_data_desc_list[card->prealloc_netdata_r].os_net_buf_ptr = NULL; - card->bulk_data_desc_list[card->prealloc_netdata_r].net_buf_length = 0; - card->bulk_data_desc_list[card->prealloc_netdata_r].data_length = 0; - - card->prealloc_netdata_r++; - card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM; - - unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r); - - return CSR_RESULT_SUCCESS; -} - - -#endif - -/* - * --------------------------------------------------------------------------- - * unifi_sdio_interrupt_handler - * - * This function should be called by the OS-dependent code to handle - * an SDIO interrupt from the UniFi. - * - * Arguments: - * card Pointer to card context structure. - * - * Returns: - * None. - * - * Notes: This function may be called in DRS context. In this case, - * tracing with the unifi_trace(), etc, is not allowed. - * --------------------------------------------------------------------------- - */ -void unifi_sdio_interrupt_handler(card_t *card) -{ - /* - * Set the flag to say reason for waking was SDIO interrupt. - * Then ask the OS layer to run the unifi_bh to give attention to the UniFi. - */ - card->bh_reason_unifi = 1; - (void)unifi_run_bh(card->ospriv); -} /* sdio_interrupt_handler() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_configure_low_power_mode - * - * This function should be called by the OS-dependent when - * the deep sleep signaling needs to be enabled or disabled. - * - * Arguments: - * card Pointer to card context structure. - * low_power_mode Disable/Enable the deep sleep signaling - * periodic_wake_mode UniFi wakes host periodically. - * - * Returns: - * CSR_RESULT_SUCCESS on success or a CSR error code. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_configure_low_power_mode(card_t *card, - enum unifi_low_power_mode low_power_mode, - enum unifi_periodic_wake_mode periodic_wake_mode) -{ - card->low_power_mode = low_power_mode; - card->periodic_wake_mode = periodic_wake_mode; - - unifi_trace(card->ospriv, UDBG1, - "unifi_configure_low_power_mode: new mode = %s, wake_host = %s\n", - (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled", - (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE"); - - (void)unifi_run_bh(card->ospriv); - return CSR_RESULT_SUCCESS; -} /* unifi_configure_low_power_mode() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_force_low_power_mode - * - * This function should be called by the OS-dependent when - * UniFi needs to be set to the low power mode (e.g. on suspend) - * - * Arguments: - * card Pointer to card context structure. - * - * Returns: - * CSR_RESULT_SUCCESS on success or a CSR error code. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_force_low_power_mode(card_t *card) -{ - if (card->low_power_mode == UNIFI_LOW_POWER_DISABLED) - { - unifi_error(card->ospriv, "Attempt to set mode to TORPID when lower power mode is disabled\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - return unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); -} /* unifi_force_low_power_mode() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_bh - * - * This function should be called by the OS-dependent code when - * host and/or UniFi has requested an exchange of messages. - * - * Arguments: - * card Pointer to card context structure. - * - * Returns: - * CSR_RESULT_SUCCESS on success or a CSR error code. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_bh(card_t *card, u32 *remaining) -{ - CsrResult r; - CsrResult csrResult; - u8 pending; - s32 iostate, j; - const enum unifi_low_power_mode low_power_mode = card->low_power_mode; - u16 data_slots_used = 0; - - - /* Process request to raise the maximum SDIO clock */ - r = process_clock_request(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Error setting maximum SDIO clock\n"); - goto exit; - } - - /* - * Why was the BH thread woken? - * If it was an SDIO interrupt, UniFi is awake and we need to process it. - * If it was a host process queueing data, then we need to awaken UniFi. - * - * Priority of flags is top down. - * - * ----------------------------------------------------------+ - * \state| AWAKE | DROWSY | TORPID | - * flag\ | | | | - * ---------+--------------+----------------+----------------| - * | do the host | go to AWAKE and| go to AWAKE and| - * unifi | protocol | do the host | do the host | - * | | protocol | protocol | - * ---------+--------------+----------------+----------------| - * | do the host | | | - * host | protocol | do nothing | go to DROWSY | - * | | | | - * ---------+--------------+----------------+----------------| - * | | | should not | - * timeout | go to TORPID | error, unifi | occur | - * | | didn't wake up | do nothing | - * ----------------------------------------------------------+ - * - * Note that if we end up in the AWAKE state we always do the host protocol. - */ - - do - { - /* - * When the host state is set to DROWSY, then we can not disable the - * interrupts as UniFi can generate an interrupt even when the INT_ENABLE - * register has the interrupts disabled. This interrupt will be lost. - */ - if (card->host_state == UNIFI_HOST_STATE_DROWSY || card->host_state == UNIFI_HOST_STATE_TORPID) - { - u8 reason_unifi; - - /* - * An interrupt may occur while or after we cache the reason. - * This interrupt will cause the unifi_bh() to be scheduled again. - * Any interrupt that has happened before the register is read - * and is considered spurious has to acknowledged. - */ - reason_unifi = card->bh_reason_unifi; - - /* - * If an interrupt is received, check if it was a real one, - * set the host state to AWAKE and run the BH. - */ - r = CardPendingInt(card, &pending); - if (r != CSR_RESULT_SUCCESS) - { - goto exit; - } - - if (pending) - { - unifi_trace(card->ospriv, UDBG5, - "UNIFI_HOST_STATE_%s: Set state to AWAKE.\n", - (card->host_state == UNIFI_HOST_STATE_TORPID)?"TORPID" : "DROWSY"); - - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r == CSR_RESULT_SUCCESS) - { - (*remaining) = 0; - break; - } - } - else if (reason_unifi) - { - CsrSdioInterruptAcknowledge(card->sdio_if); - } - - /* - * If an chip is in TORPID, and the host wants to wake it up, - * set the host state to DROWSY and wait for the wake-up interrupt. - */ - if ((card->host_state == UNIFI_HOST_STATE_TORPID) && card->bh_reason_host) - { - r = unifi_set_host_state(card, UNIFI_HOST_STATE_DROWSY); - if (r == CSR_RESULT_SUCCESS) - { - /* - * set the timeout value to UNIFI_DEFAULT_WAKE_TIMEOUT - * to capture a wake error. - */ - card->bh_reason_host = 0; - (*remaining) = UNIFI_DEFAULT_WAKE_TIMEOUT; - return CSR_RESULT_SUCCESS; - } - - goto exit; - } - - /* - * If the chip is in DROWSY, and the timeout expires, - * we need to reset the chip. This should never occur. - * (If it does, check that the calling thread set "remaining" - * according to the time remaining when unifi_bh() was called). - */ - if ((card->host_state == UNIFI_HOST_STATE_DROWSY) && ((*remaining) == 0)) - { - unifi_error(card->ospriv, "UniFi did not wake up on time...\n"); - - /* - * Check if Function1 has gone away or - * if we missed an SDIO interrupt. - */ - r = unifi_check_io_status(card, &iostate); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - goto exit; - } - /* Need to reset and reboot */ - return CSR_RESULT_FAILURE; - } - } - else - { - if (card->bh_reason_unifi || card->bh_reason_host) - { - break; - } - - if (((*remaining) == 0) && (low_power_mode == UNIFI_LOW_POWER_ENABLED)) - { - r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); - if (r == CSR_RESULT_SUCCESS) - { - (*remaining) = 0; - return CSR_RESULT_SUCCESS; - } - - goto exit; - } - } - - /* No need to run the host protocol */ - return CSR_RESULT_SUCCESS; - } while (0); - - - /* Disable the SDIO interrupts while doing SDIO ops */ - csrResult = CsrSdioInterruptDisable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - r = CSR_WIFI_HIP_RESULT_NO_DEVICE; - goto exit; - } - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - unifi_error(card->ospriv, "Failed to disable SDIO interrupts. unifi_bh queues error.\n"); - goto exit; - } - - /* Now that the interrupts are disabled, ack the interrupt */ - CsrSdioInterruptAcknowledge(card->sdio_if); - - /* Run the HIP */ - r = process_bh(card); - if (r != CSR_RESULT_SUCCESS) - { - goto exit; - } - - /* - * If host is now idle, schedule a timer for the delay before we - * let UniFi go into deep sleep. - * If the timer goes off, we will move to TORPID state. - * If UniFi raises an interrupt in the meantime, we will cancel - * the timer and start a new one when we become idle. - */ - for (j = 0; j < UNIFI_NO_OF_TX_QS; j++) - { - data_slots_used += CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[j]); - } - - if ((low_power_mode == UNIFI_LOW_POWER_ENABLED) && (data_slots_used == 0)) - { -#ifndef CSR_WIFI_HIP_TA_DISABLE - if (card->ta_sampling.traffic_type != CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC) - { -#endif - /* return the UNIFI_DEFAULT_HOST_IDLE_TIMEOUT, so we can go to sleep. */ - unifi_trace(card->ospriv, UDBG5, - "Traffic is not periodic, set timer for TORPID.\n"); - (*remaining) = UNIFI_DEFAULT_HOST_IDLE_TIMEOUT; -#ifndef CSR_WIFI_HIP_TA_DISABLE - } - else - { - unifi_trace(card->ospriv, UDBG5, - "Traffic is periodic, set unifi to TORPID immediately.\n"); - if (CardAreAllFromHostDataSlotsEmpty(card) == 1) - { - r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID); - if (r != CSR_RESULT_SUCCESS) - { - goto exit; - } - } - } -#endif - } - - csrResult = CsrSdioInterruptEnable(card->sdio_if); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - r = CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - unifi_error(card->ospriv, "Failed to enable SDIO interrupt\n"); - } - -exit: - - unifi_trace(card->ospriv, UDBG4, "New state=%d\n", card->host_state); - - if (r != CSR_RESULT_SUCCESS) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_buf_dump(); -#endif - /* If an interrupt has been raised, ack it here */ - if (card->bh_reason_unifi) - { - CsrSdioInterruptAcknowledge(card->sdio_if); - } - - unifi_error(card->ospriv, - "unifi_bh: state=%d %c, clock=%dkHz, interrupt=%d host=%d, power_save=%s\n", - card->host_state, - (card->host_state == UNIFI_HOST_STATE_AWAKE)?'A' : (card->host_state == UNIFI_HOST_STATE_DROWSY)?'D' : 'T', - card->sdio_clock_speed / 1000, - card->bh_reason_unifi, card->bh_reason_host, - (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled"); - - /* Try to capture firmware panic codes */ - (void)unifi_capture_panic(card); - - /* Ask for a mini-coredump when the driver has reset UniFi */ - (void)unifi_coredump_request_at_next_reset(card, 1); - } - - return r; -} /* unifi_bh() */ - - -/* - * --------------------------------------------------------------------------- - * process_clock_request - * - * Handle request from the OS layer to increase the SDIO clock speed. - * The fast clock is limited until the firmware has indicated that it has - * completed initialisation to the OS layer. - * - * Arguments: - * card Pointer to card context structure. - * - * Returns: - * CSR_RESULT_SUCCESS on success or CSR error code. - * --------------------------------------------------------------------------- - */ -static CsrResult process_clock_request(card_t *card) -{ - CsrResult r = CSR_RESULT_SUCCESS; - CsrResult csrResult; - - if (!card->request_max_clock) - { - return CSR_RESULT_SUCCESS; /* No pending request */ - } - - /* - * The SDIO clock speed request from the OS layer is only acted upon if - * the UniFi is awake. If it was in any other state, the clock speed will - * transition through SAFE to MAX while the host wakes it up, and the - * final speed reached will be UNIFI_SDIO_CLOCK_MAX_HZ. - * This assumes that the SME never requests low power mode while the f/w - * initialisation takes place. - */ - if (card->host_state == UNIFI_HOST_STATE_AWAKE) - { - unifi_trace(card->ospriv, UDBG1, "Set SDIO max clock\n"); - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_MAX_HZ); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - } - else - { - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_MAX_HZ; /* log the new freq */ - } - } - else - { - unifi_trace(card->ospriv, UDBG1, "Will set SDIO max clock after wakeup\n"); - } - - /* Cancel the request now that it has been acted upon, or is about to be - * by the wakeup mechanism - */ - card->request_max_clock = 0; - - return r; -} - - -/* - * --------------------------------------------------------------------------- - * process_bh - * - * Exchange messages with UniFi - * - * Arguments: - * card Pointer to card context structure. - * - * Returns: - * CSR_RESULT_SUCCESS on success or CSR error code. - * --------------------------------------------------------------------------- - */ -static CsrResult process_bh(card_t *card) -{ - CsrResult r; - u8 more; - more = FALSE; - - /* Process the reasons (interrupt, signals) */ - do - { - /* - * Run in a while loop, to save clearing the interrupts - * every time around the outside loop. - */ - do - { - /* If configured to run the HIP just once, skip first loop */ - if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) - { - break; - } - - r = handle_host_protocol(card, &more); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n", - card->cmd_prof.cmd52_count, - card->cmd_prof.cmd53_count, - card->cmd_prof.tx_count, - card->cmd_prof.tx_cfm_count, - card->cmd_prof.rx_count, - card->cmd_prof.sdio_cmd_signal, - card->cmd_prof.sdio_cmd_to_host, - card->cmd_prof.sdio_cmd_from_host_and_clear - ); - - card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0; - card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0; - - card->cmd_prof.cmd52_f0_r_count = 0; - card->cmd_prof.cmd52_f0_w_count = 0; - card->cmd_prof.cmd52_r8or16_count = 0; - card->cmd_prof.cmd52_w8or16_count = 0; - card->cmd_prof.cmd52_r16_count = 0; - card->cmd_prof.cmd52_w16_count = 0; - card->cmd_prof.cmd52_r32_count = 0; - - card->cmd_prof.sdio_cmd_signal = 0; - card->cmd_prof.sdio_cmd_clear_slot = 0; - card->cmd_prof.sdio_cmd_to_host = 0; - card->cmd_prof.sdio_cmd_from_host = 0; - card->cmd_prof.sdio_cmd_from_host_and_clear = 0; -#endif - - - } while (more || card->bh_reason_unifi || card->bh_reason_host); - - /* Acknowledge the h/w interrupt */ - r = CardClearInt(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to acknowledge interrupt.\n"); - return r; - } - - /* - * UniFi may have tried to generate an interrupt during the - * CardClearInt() was running. So, we need to run the host - * protocol again, to check if there are any pending requests. - */ - r = handle_host_protocol(card, &more); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n", - card->cmd_prof.cmd52_count, - card->cmd_prof.cmd53_count, - card->cmd_prof.tx_count, - card->cmd_prof.tx_cfm_count, - card->cmd_prof.rx_count, - card->cmd_prof.sdio_cmd_signal, - card->cmd_prof.sdio_cmd_to_host, - card->cmd_prof.sdio_cmd_from_host_and_clear - ); - - card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0; - card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0; - - card->cmd_prof.cmd52_f0_r_count = 0; - card->cmd_prof.cmd52_f0_w_count = 0; - card->cmd_prof.cmd52_r8or16_count = 0; - card->cmd_prof.cmd52_w8or16_count = 0; - card->cmd_prof.cmd52_r16_count = 0; - card->cmd_prof.cmd52_w16_count = 0; - card->cmd_prof.cmd52_r32_count = 0; - - card->cmd_prof.sdio_cmd_signal = 0; - card->cmd_prof.sdio_cmd_clear_slot = 0; - card->cmd_prof.sdio_cmd_to_host = 0; - card->cmd_prof.sdio_cmd_from_host = 0; - card->cmd_prof.sdio_cmd_from_host_and_clear = 0; -#endif - /* If configured to run the HIP just once, work is now done */ - if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) - { - break; - } - - } while (more || card->bh_reason_unifi || card->bh_reason_host); - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - if ((card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) == 0) - { - unifi_debug_log_to_buf("proc=%d\n", - card->cmd_prof.process_count); - } -#endif - - return CSR_RESULT_SUCCESS; -} /* process_bh() */ - - -/* - * --------------------------------------------------------------------------- - * handle_host_protocol - * - * This function implements the Host Interface Protocol (HIP) as - * described in the Host Interface Protocol Specification. - * - * Arguments: - * card Pointer to card context structure. - * processed_something Pointer to location to update processing status: - * TRUE when data was transferred - * FALSE when no data was transferred (queues empty) - * - * Returns: - * CSR_RESULT_SUCCESS on success or CSR error code. - * --------------------------------------------------------------------------- - */ -static CsrResult handle_host_protocol(card_t *card, u8 *processed_something) -{ - CsrResult r; - s32 done; - - *processed_something = FALSE; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, " ======================== \n"); -#endif /* CSR_WIFI_HIP_NOISY */ - -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.process_count++; -#endif - - card->bh_reason_unifi = card->bh_reason_host = 0; - card->generate_interrupt = 0; - - - /* - * (Re)fill the T-H signal buffer - */ - r = read_to_host_signals(card, &done); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Error occurred reading to-host signals\n"); - return r; - } - if (done > 0) - { - *processed_something = TRUE; - } - - /* - * Process any to-host signals. - * Perform any requested CMD53 transfers here, but just queue any - * bulk data command responses. - */ - r = process_to_host_signals(card, &done); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Error occurred processing to-host signals\n"); - return r; - } - - /* Now send any signals in the F-H queues */ - /* Give precedence to the command queue */ - r = process_fh_cmd_queue(card, &done); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Error occurred processing from-host signals\n"); - return r; - } - if (done > 0) - { - *processed_something = TRUE; - } - - r = process_fh_traffic_queue(card, &done); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Error occurred processing from-host data signals\n"); - return r; - } - if (done > 0) - { - *processed_something = TRUE; - } - - /* Flush out the batch of signals to the UniFi. */ - r = flush_fh_buffer(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to copy from-host signals to UniFi\n"); - return r; - } - - - /* - * Send the host interrupt to say the queues have been modified. - */ - if (card->generate_interrupt) - { - r = CardGenInt(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to notify UniFi that queues have been modified.\n"); - return r; - } - } - -#ifdef CSR_WIFI_RX_PATH_SPLIT -#ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ - unifi_rx_queue_flush(card->ospriv); -#endif -#endif - - /* See if we can re-enable transmission now */ - restart_packet_flow(card); - -#ifdef CSR_PRE_ALLOC_NET_DATA - r = prealloc_netdata_alloc(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "prealloc_netdata failed\n"); - return r; - } -#endif - - /* - * Don't put the thread sleep if we just interacted with the chip, - * there might be more to do if we look again. - */ - return r; -} /* handle_host_protocol() */ - - -/* - * Rounds the given signal length in bytes to a whole number - * of sig_frag_size. - */ -#define GET_CHUNKS_FOR(SIG_FRAG_SIZE, LENGTH) (((LENGTH) + ((SIG_FRAG_SIZE)-1)) / (SIG_FRAG_SIZE)) - - -/* - * --------------------------------------------------------------------------- - * read_to_host_signals - * - * Read everything pending in the UniFi TH signal buffer. - * Only do it if the local buffer is empty. - * - * Arguments: - * card Pointer to card context struct - * processed Number of signals read: - * 0 if there were no signals pending, - * 1 if we read at least one signal - * Returns: - * CSR error code if an error occurred. - * --------------------------------------------------------------------------- - */ -static CsrResult read_to_host_signals(card_t *card, s32 *processed) -{ - s32 count_thw, count_thr; - s32 unread_chunks, unread_bytes; - CsrResult r; - - *processed = 0; - - /* Read any pending signals or bulk data commands */ - count_thw = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); - if (count_thw < 0) - { - unifi_error(card->ospriv, "Failed to read to-host sig written count\n"); - return CSR_RESULT_FAILURE; - } - card->to_host_signals_w = count_thw; /* diag */ - - count_thr = card->to_host_signals_r; - - if (count_thw == count_thr) - { - return CSR_RESULT_SUCCESS; - } - - unread_chunks = - (((count_thw - count_thr) + 128) % 128) - card->th_buffer.count; - - if (unread_chunks == 0) - { - return CSR_RESULT_SUCCESS; - } - - unread_bytes = card->config_data.sig_frag_size * unread_chunks; - - - r = unifi_bulk_rw(card, - card->config_data.tohost_sigbuf_handle, - card->th_buffer.ptr, - unread_bytes, - UNIFI_SDIO_READ); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read ToHost signal\n"); - return r; - } - - card->th_buffer.ptr += unread_bytes; - card->th_buffer.count += (u16)unread_chunks; - - *processed = 1; - - return CSR_RESULT_SUCCESS; -} /* read_to_host_signals() */ - - -/* - * --------------------------------------------------------------------------- - * update_to_host_signals_r - * - * Advance the shared-memory count of chunks read from the to-host - * signal buffer. - * Raise a UniFi internal interrupt to tell the firmware that the - * count has changed. - * - * Arguments: - * card Pointer to card context struct - * pending Number of chunks remaining - * - * Returns: - * CSR_RESULT_SUCCESS on success or CSR error code - * --------------------------------------------------------------------------- - */ -static CsrResult update_to_host_signals_r(card_t *card, s16 pending) -{ - CsrResult r; - - card->to_host_signals_r = - (card->to_host_signals_r + (card->th_buffer.count - pending)) % 128; - card->th_buffer.count = pending; - - /* Update the count of signals read */ - r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 6, - (u8)card->to_host_signals_r); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to update to-host signals read\n"); - return r; - } - - r = CardGenInt(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to notify UniFi that we processed to-host signals.\n"); - return r; - } - - card->generate_interrupt = 0; - - return CSR_RESULT_SUCCESS; -} /* update_to_host_signals_r() */ - - -/* - * --------------------------------------------------------------------------- - * read_unpack_cmd - * - * Converts a wire-formatted command to the host bulk_data_cmd_t structure. - * - * Arguments: - * ptr Pointer to the command - * bulk_data_cmd Pointer to the host structure - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void read_unpack_cmd(const u8 *ptr, bulk_data_cmd_t *bulk_data_cmd) -{ - s16 index = 0; - bulk_data_cmd->cmd_and_len = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - bulk_data_cmd->data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - bulk_data_cmd->offset = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - bulk_data_cmd->buffer_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; -} /* read_unpack_cmd */ - - -/* - * --------------------------------------------------------------------------- - * process_to_host_signals - * - * Read and dispatch signals from the UniFi - * - * Arguments: - * card Pointer to card context struct - * processed Pointer to location to write processing result: - * 0 if there were no signals pending, - * 1 if we read at least one signal - * - * Returns: - * CSR error code if there was an error - * - * Notes: - * Since bulk data transfers can take a long time, if we wait until - * all are done before we acknowledge the signals, the UniFi runs out - * of buffer space. Therefore we keep a count of the bytes transferred - * in bulk data commands, and update the to-host-signals-read count - * if we've done a large transfer. - * - * All data in the f/w is stored in a little endian format, without any - * padding bytes. Every read from the memory has to be transformed in - * host (cpu specific) format, before we can process it. Therefore we - * use read_unpack_cmd() and read_unpack_signal() to convert the raw data - * contained in the card->th_buffer.buf to host structures. - * Important: UDI clients use wire-formatted structures, so we need to - * indicate all data, as we have read it from the device. - * --------------------------------------------------------------------------- - */ -static CsrResult process_to_host_signals(card_t *card, s32 *processed) -{ - s16 pending; - s16 remaining; - u8 *bufptr; - bulk_data_param_t data_ptrs; - s16 cmd; - u16 sig_len; - s16 i; - u16 chunks_in_buf; - u16 bytes_transferred = 0; - CsrResult r = CSR_RESULT_SUCCESS; - - *processed = 0; - - pending = card->th_buffer.count; - - /* Are there new to-host signals? */ - unifi_trace(card->ospriv, UDBG4, "handling %d to-host chunks\n", pending); - - if (!pending) - { - return CSR_RESULT_SUCCESS; - } - - /* - * This is a pointer to the raw data we have read from the f/w. - * Can be a signal or a command. Note that we need to convert - * it to a host structure before we process it. - */ - bufptr = card->th_buffer.buf; - - while (pending > 0) - { - s16 f_flush_count = 0; - - /* - * Command and length are common to signal and bulk data msgs. - * If command == 0 (i.e. a signal), len is number of bytes - * *following* the 2-byte header. - */ - cmd = bufptr[1] >> 4; - sig_len = bufptr[0] + ((bufptr[1] & 0x0F) << 8); - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Received UniFi msg cmd=%d, len=%d\n", - cmd, sig_len); -#endif /* CSR_WIFI_HIP_NOISY */ - - if ((sig_len == 0) && - ((cmd != SDIO_CMD_CLEAR_SLOT) && (cmd != SDIO_CMD_PADDING))) - { - unifi_error(card->ospriv, "incomplete signal or command: has size zero\n"); - return CSR_RESULT_FAILURE; - } - /* - * Make sure the buffer contains a complete message. - * Signals may occupy multiple chunks, bulk-data commands occupy - * one chunk. - */ - if (cmd == SDIO_CMD_SIGNAL) - { - chunks_in_buf = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(sig_len + 2)); - } - else - { - chunks_in_buf = 1; - } - - if (chunks_in_buf > (u16)pending) - { - unifi_error(card->ospriv, "incomplete signal (0x%x?): need %d chunks, got %d\n", - GET_SIGNAL_ID(bufptr + 2), - chunks_in_buf, pending); - unifi_error(card->ospriv, " thsw=%d, thsr=%d\n", - card->to_host_signals_w, - card->to_host_signals_r); - return CSR_RESULT_FAILURE; - } - - - switch (cmd) - { - case SDIO_CMD_SIGNAL: - /* This is a signal. Read the rest of it and then handle it. */ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.sdio_cmd_signal++; -#endif - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - /* Retrieve dataRefs[i].DataLength */ - u16 data_len = GET_PACKED_DATAREF_LEN(bufptr + 2, i); - - /* - * The bulk data length in the signal can not be greater than - * the maximun length allowed by the SDIO config structure. - */ - if (data_len > card->config_data.data_slot_size) - { - unifi_error(card->ospriv, - "Bulk Data length (%d) exceeds Maximum Bulk Data length (%d)\n", - data_len, card->config_data.data_slot_size); - return CSR_RESULT_FAILURE; - } - - /* - * Len here might not be the same as the length in the - * bulk data slot. The slot length will always be even, - * but len could be odd. - */ - if (data_len != 0) - { - /* Retrieve dataRefs[i].SlotNumber */ - s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i); - - if (slot >= card->config_data.num_tohost_data_slots) - { - unifi_error(card->ospriv, "!!!bad slot number in to-host signal: %d, sig 0x%X\n", - slot, cmd); - return CSR_RESULT_FAILURE; - } - - data_ptrs.d[i].os_data_ptr = card->to_host_data[slot].os_data_ptr; - data_ptrs.d[i].os_net_buf_ptr = card->to_host_data[slot].os_net_buf_ptr; - data_ptrs.d[i].net_buf_length = card->to_host_data[slot].net_buf_length; - data_ptrs.d[i].data_length = data_len; - } - else - { - UNIFI_INIT_BULK_DATA(&data_ptrs.d[i]); - } - } - - /* - * Log the signal to the UDI, before call unifi_receive_event() as - * it can modify the bulk data. - */ - if (card->udi_hook) - { - (*card->udi_hook)(card->ospriv, bufptr + 2, sig_len, - &data_ptrs, UDI_LOG_TO_HOST); - } - -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID) - { - card->cmd_prof.tx_cfm_count++; - } - else if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_INDICATION_ID) - { - if (data_ptrs.d[0].os_data_ptr) - { - if ((*data_ptrs.d[0].os_data_ptr) & 0x08) - { - card->cmd_prof.rx_count++; - } - } - } -#endif - /* - * Check if the signal is MA-PACKET.cfm and if so check the status. - * If the status is failure, search through the slot records to find - * if any slots are occupied for this host tag. This can happen if - * f/w has not downloaded the bulkdata and before that itself it has - * signalled the confirm with failure. If it finds a slot with that - * host tag then, it clears the corresponding slot - */ - - if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID) - { - /* Get host tag and transmission status */ - u32 host_tag = GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(bufptr + 2); - u16 status = GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(bufptr + 2); - - unifi_trace(card->ospriv, UDBG4, "process_to_host_signals signal ID=%x host Tag=%x status=%x\n", - GET_SIGNAL_ID(bufptr + 2), host_tag, status); - - /* If transmission status is failure then search through the slot records - * and if for any slot records the clear slot is not done then do it now - */ - - if (status && (card->fh_slot_host_tag_record)) - { - u16 num_fh_slots = card->config_data.num_fromhost_data_slots; - - /* search through the list of slot records and match with host tag - * If a slot is not yet cleared then clear the slot from here - */ - for (i = 0; i < num_fh_slots; i++) - { - if (card->fh_slot_host_tag_record[i] == host_tag) - { -#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL - /* Invoke the HAL module function to requeue it back to HAL Queues */ - r = unifi_reque_ma_packet_request(card->ospriv, host_tag, status, &card->from_host_data[i].bd); - card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; - if (CSR_RESULT_SUCCESS != r) - { - unifi_trace(card->ospriv, UDBG5, "process_to_host_signals: Failed to requeue Packet(hTag:%x) back to HAL \n", host_tag); - CardClearFromHostDataSlot(card, i); - } - else - { - CardClearFromHostDataSlotWithoutFreeingBulkData(card, i); - } - -#else - unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag); - card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG; - - /* Set length field in from_host_data array to 0 */ - CardClearFromHostDataSlot(card, i); -#endif - break; - } - } - } - } - - /* Pass event to OS layer */ - unifi_receive_event(card->ospriv, bufptr + 2, sig_len, &data_ptrs); - - /* Initialise the to_host data, so it can be re-used. */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - /* The slot is only valid if the length is non-zero. */ - if (GET_PACKED_DATAREF_LEN(bufptr + 2, i) != 0) - { - s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i); - if (slot < card->config_data.num_tohost_data_slots) - { - UNIFI_INIT_BULK_DATA(&card->to_host_data[slot]); - } - } - } - -#ifndef CSR_WIFI_DEFER_TH_FLUSH - /* - * If we have previously transferred a lot of data, ack - * the signals read so far, so f/w can reclaim the buffer - * memory sooner. - */ - if (bytes_transferred >= TO_HOST_FLUSH_THRESHOLD) - { - f_flush_count = 1; - } -#endif - break; - - - case SDIO_CMD_CLEAR_SLOT: -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.sdio_cmd_clear_slot++; -#endif - /* This is a clear slot command. */ - if (sig_len != 0) - { - unifi_error(card->ospriv, "process_to_host_signals: clear slot, bad data len: 0x%X at offset %d\n", - sig_len, bufptr - card->th_buffer.buf); - return CSR_RESULT_FAILURE; - } - - r = process_clear_slot_command(card, bufptr); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to process clear slot\n"); - return r; - } - break; - - case SDIO_CMD_TO_HOST_TRANSFER: - case SDIO_CMD_FROM_HOST_TRANSFER: - case SDIO_CMD_FROM_HOST_AND_CLEAR: - case SDIO_CMD_OVERLAY_TRANSFER: - /* This is a bulk data command. */ - if (sig_len & 1) - { - unifi_error(card->ospriv, "process_to_host_signals: bulk data, bad data len: 0x%X at offset %d\n", - sig_len, bufptr - card->th_buffer.buf); - return CSR_RESULT_FAILURE; - } - - r = process_bulk_data_command(card, bufptr, cmd, sig_len); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to process bulk cmd\n"); - return r; - } - /* Count the bytes transferred */ - bytes_transferred += sig_len; - - if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.sdio_cmd_from_host_and_clear++; -#endif -#ifndef CSR_WIFI_DEFER_TH_FLUSH - f_flush_count = 1; -#endif - } -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - else if (cmd == SDIO_CMD_FROM_HOST_TRANSFER) - { - card->cmd_prof.sdio_cmd_from_host++; - } - else if (cmd == SDIO_CMD_TO_HOST_TRANSFER) - { - card->cmd_prof.sdio_cmd_to_host++; - } -#endif - break; - - case SDIO_CMD_PADDING: - break; - - default: - unifi_error(card->ospriv, "Unrecognised to-host command: %d\n", cmd); - break; - } - - bufptr += chunks_in_buf * card->config_data.sig_frag_size; - pending -= chunks_in_buf; - - /* - * Write out the host signal count when a significant - * number of bytes of bulk data have been transferred or - * when we have performed a CopyFromHostAndClear. - */ - if (f_flush_count) - { - r = update_to_host_signals_r(card, pending); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - bytes_transferred = 0; - } - } - - if (pending) - { - unifi_warning(card->ospriv, "proc_th_sigs: %d unprocessed\n", pending); - } - - /* If we processed any signals, write the updated count to UniFi */ - if (card->th_buffer.count != pending) - { - r = update_to_host_signals_r(card, pending); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - } - - /* - * Reset the buffer pointer, copying down any un-processed signals. - * This can happen if we enable the optimisation in read_to_host_signals() - * that limits the length to whole blocks. - */ - remaining = card->th_buffer.ptr - bufptr; - if (remaining < 0) - { - unifi_error(card->ospriv, "Processing TH signals overran the buffer\n"); - return CSR_RESULT_FAILURE; - } - if (remaining > 0) - { - /* Use a safe copy because source and destination may overlap */ - u8 *d = card->th_buffer.buf; - u8 *s = bufptr; - s32 n = remaining; - while (n--) - { - *d++ = *s++; - } - } - card->th_buffer.ptr = card->th_buffer.buf + remaining; - - - /* If we reach here then we processed something */ - *processed = 1; - return CSR_RESULT_SUCCESS; -} /* process_to_host_signals() */ - - -/* - * --------------------------------------------------------------------------- - * process_clear_slot_command - * - * Process a clear slot command fom the UniFi. - * - * Arguments: - * card Pointer to card context struct - * bdcmd Pointer to bulk-data command msg from UniFi - * - * Returns: - * 0 on success, CSR error code on error - * --------------------------------------------------------------------------- - */ -static CsrResult process_clear_slot_command(card_t *card, const u8 *cmdptr) -{ - u16 data_slot; - s16 slot; - - data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cmdptr + SIZEOF_UINT16); - - unifi_trace(card->ospriv, UDBG4, "Processing clear slot cmd, slot=0x%X\n", - data_slot); - - slot = data_slot & 0x7FFF; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "CMD clear data slot 0x%04x\n", data_slot); -#endif /* CSR_WIFI_HIP_NOISY */ - - if (data_slot & SLOT_DIR_TO_HOST) - { - if (slot >= card->config_data.num_tohost_data_slots) - { - unifi_error(card->ospriv, - "Invalid to-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n", - slot); - return CSR_RESULT_FAILURE; - } - /* clear to-host data slot */ - unifi_warning(card->ospriv, "Unexpected clear to-host data slot cmd: 0x%04x\n", - data_slot); - } - else - { - if (slot >= card->config_data.num_fromhost_data_slots) - { - unifi_error(card->ospriv, - "Invalid from-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n", - slot); - return CSR_RESULT_FAILURE; - } - - /* - * The driver is the owner to clear all slots now - * Ref - comment in process_fh_traffic_queue - * so it will just ignore the clear slot command from firmware - * and return success - */ - return CSR_RESULT_SUCCESS; - - /* Set length field in from_host_data array to 0 */ - /* CardClearFromHostDataSlot(card, slot); */ - } - - return CSR_RESULT_SUCCESS; -} /* process_clear_slot_command() */ - - -/* - * --------------------------------------------------------------------------- - * process_bulk_data_command - * - * Process a bulk data request from the UniFi. - * - * Arguments: - * card Pointer to card context struct - * bdcmd Pointer to bulk-data command msg from UniFi - * cmd, len Decoded values of command and length from the msg header - * Cmd will only be one of: - * SDIO_CMD_TO_HOST_TRANSFER - * SDIO_CMD_FROM_HOST_TRANSFER - * SDIO_CMD_FROM_HOST_AND_CLEAR - * SDIO_CMD_OVERLAY_TRANSFER - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on error - * --------------------------------------------------------------------------- - */ -static CsrResult process_bulk_data_command(card_t *card, const u8 *cmdptr, - s16 cmd, u16 len) -{ - bulk_data_desc_t *bdslot; -#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND - u8 *host_bulk_data_slot; -#endif - bulk_data_cmd_t bdcmd; - s16 offset; - s16 slot; - s16 dir; - CsrResult r; - - read_unpack_cmd(cmdptr, &bdcmd); - - unifi_trace(card->ospriv, UDBG4, "Processing bulk data cmd %d %s, len=%d, slot=0x%X\n", - cmd, lookup_bulkcmd_name(cmd), len, bdcmd.data_slot); - - /* - * Round up the transfer length if required. - * This is useful to force all transfers to be a multiple of the SDIO block - * size, so the SDIO driver won't try to use a byte-mode CMD53. These are - * broken on some hardware platforms. - */ - if (card->sdio_io_block_pad) - { - len = (len + card->sdio_io_block_size - 1) & ~(card->sdio_io_block_size - 1); - unifi_trace(card->ospriv, UDBG4, "Rounded bulk data length up to %d\n", len); - } - - slot = bdcmd.data_slot & 0x7FFF; - - if (cmd == SDIO_CMD_OVERLAY_TRANSFER) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; /* Not used on CSR6xxx */ - } - else - { - if (bdcmd.data_slot & SLOT_DIR_TO_HOST) - { - /* Request is for to-host bulk data */ - - /* Check sanity of slot number */ - if (slot >= card->config_data.num_tohost_data_slots) - { - unifi_error(card->ospriv, - "Invalid to-host data slot in SDIO bulk xfr req: %d\n", - slot); - return CSR_RESULT_FAILURE; - } - - /* Allocate memory for card->to_host_data[slot] bulk data here. */ -#ifdef CSR_PRE_ALLOC_NET_DATA - r = prealloc_netdata_get(card, &card->to_host_data[slot], len); -#else - r = unifi_net_data_malloc(card->ospriv, &card->to_host_data[slot], len); -#endif - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to allocate t-h bulk data\n"); - return CSR_RESULT_FAILURE; - } - - bdslot = &card->to_host_data[slot]; - - /* Make sure that the buffer is 4-bytes aligned */ - r = unifi_net_dma_align(card->ospriv, bdslot); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to align t-h bulk data buffer for DMA\n"); - return CSR_RESULT_FAILURE; - } - } - else - { - /* Request is for from-host bulk data */ - - if (slot >= card->config_data.num_fromhost_data_slots) - { - unifi_error(card->ospriv, - "Invalid from-host data slot in SDIO bulk xfr req: %d\n", - slot); - return CSR_RESULT_FAILURE; - } - bdslot = &card->from_host_data[slot].bd; - } - offset = bdcmd.offset; - } - /* Do the transfer */ - dir = (cmd == SDIO_CMD_TO_HOST_TRANSFER)? - UNIFI_SDIO_READ : UNIFI_SDIO_WRITE; - - unifi_trace(card->ospriv, UDBG4, - "Bulk %c %s len=%d, handle %d - slot=%d %p+(%d)\n", - (dir == UNIFI_SDIO_READ)?'R' : 'W', - lookup_bulkcmd_name(cmd), - len, - bdcmd.buffer_handle, - slot, bdslot->os_data_ptr, offset); -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Bulk %s len=%d, handle %d - slot=%d %p+(%d)\n", - lookup_bulkcmd_name(cmd), - len, - bdcmd.buffer_handle, - slot, bdslot->os_data_ptr, offset); -#endif /* CSR_WIFI_HIP_NOISY */ - - - if (bdslot->os_data_ptr == NULL) - { - unifi_error(card->ospriv, "Null os_data_ptr - Bulk %s handle %d - slot=%d o=(%d)\n", - lookup_bulkcmd_name(cmd), - bdcmd.buffer_handle, - slot, - offset); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - -#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND - /* if os_data_ptr is not 4-byte aligned, then allocate a new buffer and copy data - to new buffer to ensure the address passed to unifi_bulk_rw is 4-byte aligned */ - - if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3)) - { - host_bulk_data_slot = kmalloc(len, GFP_KERNEL); - - if (!host_bulk_data_slot) - { - unifi_error(card->ospriv, " failed to allocate request_data before unifi_bulk_rw\n"); - return -1; - } - - memcpy((void *)host_bulk_data_slot, - (void *)(bdslot->os_data_ptr + offset), len); - - r = unifi_bulk_rw(card, - bdcmd.buffer_handle, - (void *)host_bulk_data_slot, - len, - dir); - } - else -#endif - { - r = unifi_bulk_rw(card, - bdcmd.buffer_handle, - (void *)(bdslot->os_data_ptr + offset), - len, - dir); - } - - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, - "Failed: %s hlen=%d, slen=%d, handle %d - slot=%d %p+0x%X\n", - lookup_bulkcmd_name(cmd), - len, /* Header length */ - bdslot->data_length, /* Length stored in slot */ - bdcmd.buffer_handle, - slot, bdslot->os_data_ptr, offset); - return r; - } - - bdslot->data_length = len; - - if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR) - { - if (slot >= card->config_data.num_fromhost_data_slots) - { - unifi_error(card->ospriv, - "Invalid from-host data slot in SDIO_CMD_FROM_HOST_AND_CLEAR: %d\n", - slot); - return CSR_RESULT_FAILURE; - } - -#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND - /* moving this check before we clear host data slot */ - if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3)) - { - kfree(host_bulk_data_slot); - } -#endif - - if (card->fh_slot_host_tag_record) - { - unifi_trace(card->ospriv, UDBG5, "CopyFromHostAndClearSlot Reset entry for slot=%d\n", slot); - - /* reset the host tag entry for the corresponding slot */ - card->fh_slot_host_tag_record[slot] = CSR_WIFI_HIP_RESERVED_HOST_TAG; - } - - - /* Set length field in from_host_data array to 0 */ - CardClearFromHostDataSlot(card, slot); - } - - return CSR_RESULT_SUCCESS; -} /* process_bulk_data_command() */ - - -/* - * --------------------------------------------------------------------------- - * check_fh_sig_slots - * - * Check whether there are free signal slots available on UniFi. - * This takes into account the signals already batched since the - * from_host_signal counts were last read. - * If the from_host_signal counts indicate not enough space, we read - * the latest count from UniFi to see if some more have been freed. - * - * Arguments: - * None. - * - * Returns: - * CSR_RESULT_SUCCESS, otherwise CSR error code on error. - * --------------------------------------------------------------------------- - */ -static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space_fh) -{ - u32 count_fhw; - u32 occupied_fh, slots_fh; - s32 count_fhr; - - count_fhw = card->from_host_signals_w; - count_fhr = card->from_host_signals_r; - slots_fh = card->config_data.num_fromhost_sig_frags; - - /* Only read the space in from-host queue if necessary */ - occupied_fh = (count_fhw - count_fhr) % 128; - - if (slots_fh < occupied_fh) - { - *space_fh = 0; - } - else - { - *space_fh = slots_fh - occupied_fh; - } - - if ((occupied_fh != 0) && (*space_fh < needed)) - { - count_fhr = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2); - if (count_fhr < 0) - { - unifi_error(card->ospriv, "Failed to read from-host sig read count\n"); - return CSR_RESULT_FAILURE; - } - card->from_host_signals_r = count_fhr; /* diag */ - - occupied_fh = (count_fhw - count_fhr) % 128; - *space_fh = slots_fh - occupied_fh; - } - - return CSR_RESULT_SUCCESS; -} /* check_fh_sig_slots() */ - - -/* -* If we are padding the From-Host signals to the SDIO block size, -* we need to round up the needed_chunks to the SDIO block size. -*/ -#define ROUND_UP_NEEDED_CHUNKS(_card, _needed_chunks) \ - { \ - u16 _chunks_per_block; \ - u16 _chunks_in_last_block; \ - \ - if (_card->sdio_io_block_pad) \ - { \ - _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \ - _chunks_in_last_block = _needed_chunks % _chunks_per_block; \ - if (_chunks_in_last_block != 0) \ - { \ - _needed_chunks = _needed_chunks + (_chunks_per_block - _chunks_in_last_block); \ - } \ - } \ - } - - -#define ROUND_UP_SPACE_CHUNKS(_card, _space_chunks) \ - { \ - u16 _chunks_per_block; \ - \ - if (_card->sdio_io_block_pad) \ - { \ - _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \ - _space_chunks = ((_space_chunks / _chunks_per_block) * _chunks_per_block); \ - } \ - } - - - - - -/* - * --------------------------------------------------------------------------- - * process_fh_cmd_queue - * - * Take one signal off the from-host queue and copy it to the UniFi. - * Does nothing if the UniFi has no slots free. - * - * Arguments: - * card Pointer to card context struct - * processed Location to write: - * 0 if there is nothing on the queue to process - * 1 if a signal was successfully processed - * - * Returns: - * CSR error code if an error occurred. - * - * Notes: - * The from-host queue contains signal requests from the network driver - * and any UDI clients interspersed. UDI clients' requests have been stored - * in the from-host queue using the wire-format structures, as they arrive. - * All other requests are stored in the from-host queue using the host - * (cpu specific) structures. We use the is_packed member of the card_signal_t - * structure that describes the queue to make the distinction. - * --------------------------------------------------------------------------- - */ -static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed) -{ - q_t *sigq = &card->fh_command_queue; - - CsrResult r; - u16 pending_sigs; - u16 pending_chunks; - u16 needed_chunks; - s32 space_chunks; - u16 q_index; - - *processed = 0; - - /* Get the number of pending signals. */ - pending_sigs = CSR_WIFI_HIP_Q_SLOTS_USED(sigq); - unifi_trace(card->ospriv, UDBG5, "proc_fh: %d pending\n", pending_sigs); - if (pending_sigs == 0) - { - /* Nothing to do */ - return CSR_RESULT_SUCCESS; - } - - /* Work out how many chunks we have waiting to send */ - for (pending_chunks = 0, q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq); - q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq); - q_index = CSR_WIFI_HIP_Q_WRAP(sigq, q_index + 1)) - { - card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index); - - /* - * Note that GET_CHUNKS_FOR() needs the size of the packed - * (wire-formatted) structure - */ - pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2)); - } - - /* - * Check whether UniFi has space for all the buffered bulk-data - * commands and signals as well. - */ - needed_chunks = pending_chunks + card->fh_buffer.count; - - /* Round up to the block size if necessary */ - ROUND_UP_NEEDED_CHUNKS(card, needed_chunks); - - r = check_fh_sig_slots(card, needed_chunks, &space_chunks); - if (r != CSR_RESULT_SUCCESS) - { - /* Error */ - unifi_error(card->ospriv, "Failed to read fh sig count\n"); - return r; - } - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "proc_fh: %d chunks free, need %d\n", - space_chunks, needed_chunks); -#endif /* CSR_WIFI_HIP_NOISY */ - - - /* - * Coalesce as many from-host signals as possible - * into a single block and write using a single CMD53 - */ - if (needed_chunks > (u16)space_chunks) - { - /* Round up to the block size if necessary */ - ROUND_UP_SPACE_CHUNKS(card, space_chunks); - - /* - * If the f/w has less free chunks than those already pending - * return immediately. - */ - if ((u16)space_chunks <= card->fh_buffer.count) - { - /* - * No room in UniFi for any signals after the buffered bulk - * data commands have been sent. - */ - unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n", - card->fh_buffer.count, space_chunks); - card->generate_interrupt = 1; - return CSR_RESULT_SUCCESS; - } - pending_chunks = (u16)(space_chunks - card->fh_buffer.count); - } - - while (pending_sigs-- && pending_chunks > 0) - { - card_signal_t *csptr; - s16 i; - u16 sig_chunks, total_length, free_chunks_in_fh_buffer; - bulk_data_param_t bulkdata; - u8 *packed_sigptr; - u16 signal_length = 0; - - /* Retrieve the entry at the head of the queue */ - q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq); - - /* Get a pointer to the containing card_signal_t struct */ - csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index); - - /* Get the new length of the packed signal */ - signal_length = csptr->signal_length; - - if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE)) - { - unifi_error(card->ospriv, "process_fh_queue: Bad len: %d\n", signal_length); - return CSR_RESULT_FAILURE; - } - - /* Need space for 2-byte SDIO protocol header + signal */ - sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2)); - - free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size, - (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr)); - if (free_chunks_in_fh_buffer < sig_chunks) - { - /* No more room */ - unifi_notice(card->ospriv, "proc_fh_cmd_q: no room in fh buffer for 0x%.4X, deferring\n", - (u16)(GET_SIGNAL_ID(csptr->sigbuf))); - break; - } - - packed_sigptr = csptr->sigbuf; - - /* Claim and set up a from-host data slot */ - if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, UNIFI_TRAFFIC_Q_MLME)) - { - unifi_notice(card->ospriv, "proc_fh_cmd_q: no fh data slots for 0x%.4X, deferring\n", - (u16)(GET_SIGNAL_ID(csptr->sigbuf))); - break; - } - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - if (csptr->bulkdata[i].data_length == 0) - { - UNIFI_INIT_BULK_DATA(&bulkdata.d[i]); - } - else - { - bulkdata.d[i].os_data_ptr = csptr->bulkdata[i].os_data_ptr; - bulkdata.d[i].data_length = csptr->bulkdata[i].data_length; - } - - /* Pass the free responsibility to the lower layer. */ - UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]); - } - - unifi_trace(card->ospriv, UDBG2, "Sending signal 0x%.4X\n", - GET_SIGNAL_ID(packed_sigptr)); -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Sending signal 0x%.4X\n", - GET_SIGNAL_ID(packed_sigptr)); -#endif /* CSR_WIFI_HIP_NOISY */ - - - /* Append packed signal to F-H buffer */ - total_length = sig_chunks * card->config_data.sig_frag_size; - - card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff); - card->fh_buffer.ptr[1] = - (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4)); - - memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length); - memset(card->fh_buffer.ptr + 2 + signal_length, 0, - total_length - (2 + signal_length)); - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n", - signal_length + 2); - dump(card->fh_buffer.ptr, signal_length + 2); - unifi_trace(card->ospriv, UDBG1, " \n"); -#endif /* CSR_WIFI_HIP_NOISY */ - - card->fh_buffer.ptr += total_length; - card->fh_buffer.count += sig_chunks; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n", - signal_length, - card->fh_buffer.ptr - card->fh_buffer.buf, - card->fh_buffer.count); -#endif /* CSR_WIFI_HIP_NOISY */ - - (*processed)++; - pending_chunks -= sig_chunks; - - /* Log the signal to the UDI. */ - /* UDI will get the packed structure */ - /* Can not log the unpacked signal, unless we reconstruct it! */ - if (card->udi_hook) - { - (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length, - &bulkdata, UDI_LOG_FROM_HOST); - } - - /* Remove entry from q */ - csptr->signal_length = 0; - CSR_WIFI_HIP_Q_INC_R(sigq); - } - - return CSR_RESULT_SUCCESS; -} /* process_fh_cmd_queue() */ - - -/* - * --------------------------------------------------------------------------- - * process_fh_traffic_queue - * - * Take signals off the from-host queue and copy them to the UniFi. - * Does nothing if the UniFi has no slots free. - * - * Arguments: - * card Pointer to card context struct - * sigq Pointer to the traffic queue - * processed Pointer to location to write: - * 0 if there is nothing on the queue to process - * 1 if a signal was successfully processed - * - * Returns: - * CSR error code if an error occurred. - * - * Notes: - * The from-host queue contains signal requests from the network driver - * and any UDI clients interspersed. - * --------------------------------------------------------------------------- - */ -static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed) -{ - q_t *sigq = card->fh_traffic_queue; - - CsrResult r; - s16 n = 0; - s32 q_no; - u16 pending_sigs = 0; - u16 pending_chunks = 0; - u16 needed_chunks; - s32 space_chunks; - u16 q_index; - u32 host_tag = 0; - u16 slot_num = 0; - - *processed = 0; - - /* calculate how many signals are in queues and how many chunks are needed. */ - for (n = UNIFI_NO_OF_TX_QS - 1; n >= 0; n--) - { - /* Get the number of pending signals. */ - pending_sigs += CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[n]); - unifi_trace(card->ospriv, UDBG5, "proc_fh%d: %d pending\n", n, pending_sigs); - - /* Work out how many chunks we have waiting to send */ - for (q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[n]); - q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(&sigq[n]); - q_index = CSR_WIFI_HIP_Q_WRAP(&sigq[n], q_index + 1)) - { - card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[n], q_index); - - /* - * Note that GET_CHUNKS_FOR() needs the size of the packed - * (wire-formatted) structure - */ - pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2)); - } - } - - /* If there are no pending signals, just return */ - if (pending_sigs == 0) - { - /* Nothing to do */ - return CSR_RESULT_SUCCESS; - } - - /* - * Check whether UniFi has space for all the buffered bulk-data - * commands and signals as well. - */ - needed_chunks = pending_chunks + card->fh_buffer.count; - - /* Round up to the block size if necessary */ - ROUND_UP_NEEDED_CHUNKS(card, needed_chunks); - - r = check_fh_sig_slots(card, needed_chunks, &space_chunks); - if (r != CSR_RESULT_SUCCESS) - { - /* Error */ - unifi_error(card->ospriv, "Failed to read fh sig count\n"); - return r; - } - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, - "process_fh_traffic_queue: %d chunks free, need %d\n", - space_chunks, needed_chunks); - read_fhsr(card); /* debugging only */ -#endif /* CSR_WIFI_HIP_NOISY */ - - /* Coalesce as many from-host signals as possible - into a single block and write using a single CMD53 */ - if (needed_chunks > (u16)space_chunks) - { - /* Round up to the block size if necessary */ - ROUND_UP_SPACE_CHUNKS(card, space_chunks); - - if ((u16)space_chunks <= card->fh_buffer.count) - { - /* - * No room in UniFi for any signals after the buffered bulk - * data commands have been sent. - */ - unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n", - card->fh_buffer.count, space_chunks); - card->generate_interrupt = 1; - return 0; - } - - pending_chunks = (u16)space_chunks - card->fh_buffer.count; - } - - q_no = UNIFI_NO_OF_TX_QS - 1; - - /* - * pending_sigs will be exhausted if there are is no restriction to the pending - * signals per queue. pending_chunks may be exhausted if there is a restriction. - * q_no check will be exhausted if there is a restriction and our round-robin - * algorith fails to fill all chunks. - */ - do - { - card_signal_t *csptr; - u16 sig_chunks, total_length, free_chunks_in_fh_buffer; - bulk_data_param_t bulkdata; - u8 *packed_sigptr; - u16 signal_length = 0; - - /* if this queue is empty go to next one. */ - if (CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[q_no]) == 0) - { - q_no--; - continue; - } - - /* Retrieve the entry at the head of the queue */ - q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[q_no]); - - /* Get a pointer to the containing card_signal_t struct */ - csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[q_no], q_index); - - /* Get the new length of the packed signal */ - signal_length = csptr->signal_length; - - if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE)) - { - unifi_error(card->ospriv, "process_fh_traffic_queue: Bad len: %d\n", signal_length); - return CSR_RESULT_FAILURE; - } - - /* Need space for 2-byte SDIO protocol header + signal */ - sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2)); - free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size, - (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr)); - if (free_chunks_in_fh_buffer < sig_chunks) - { - /* No more room */ - unifi_notice(card->ospriv, "process_fh_traffic_queue: no more chunks.\n"); - break; - } - - packed_sigptr = csptr->sigbuf; - /* Claim and set up a from-host data slot */ - if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, (unifi_TrafficQueue)q_no)) - { - q_no--; - continue; - } - - /* Sanity check: MA-PACKET.req must have a valid bulk data */ - if ((csptr->bulkdata[0].data_length == 0) || (csptr->bulkdata[0].os_data_ptr == NULL)) - { - unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n", - csptr->bulkdata[0].data_length, csptr->bulkdata[0].os_data_ptr); - dump(packed_sigptr, signal_length); - return CSR_RESULT_FAILURE; - } - - bulkdata.d[0].os_data_ptr = csptr->bulkdata[0].os_data_ptr; - bulkdata.d[0].data_length = csptr->bulkdata[0].data_length; - bulkdata.d[0].os_net_buf_ptr = csptr->bulkdata[0].os_net_buf_ptr; - bulkdata.d[0].net_buf_length = csptr->bulkdata[0].net_buf_length; - - /* The driver owns clearing of HIP slots for following scenario - * - driver has requested a MA-PACKET.req signal - * - The f/w after receiving the signal decides it can't send it out due to various reasons - * - So the f/w without downloading the bulk data decides to just send a confirmation with fail - * - and then sends a clear slot signal to HIP - * - * But in some cases the clear slot signal never comes and the slot remains --NOT-- freed for ever - * - * To handle this, HIP will keep the record of host tag for each occupied slot - * and then based on status of that Host tag and slot the driver will decide if the slot is - * cleared by f/w signal or the slot has to be freed by driver - */ - - if (card->fh_slot_host_tag_record) - { - /* Update the f-h slot record for the corresponding host tag */ - host_tag = GET_PACKED_MA_PACKET_REQUEST_HOST_TAG(packed_sigptr); - slot_num = GET_PACKED_DATAREF_SLOT(packed_sigptr, 0) & 0x00FF; - - unifi_trace(card->ospriv, UDBG5, - "process_fh_traffic_queue signal ID =%x fh slot=%x Host tag =%x\n", - GET_SIGNAL_ID(packed_sigptr), slot_num, host_tag); - card->fh_slot_host_tag_record[slot_num] = host_tag; - } - UNIFI_INIT_BULK_DATA(&bulkdata.d[1]); - UNIFI_INIT_BULK_DATA(&csptr->bulkdata[0]); - UNIFI_INIT_BULK_DATA(&csptr->bulkdata[1]); - -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - if (bulkdata.d[0].os_data_ptr) - { - if ((*bulkdata.d[0].os_data_ptr) & 0x08) - { - card->cmd_prof.tx_count++; - } - } -#endif - unifi_trace(card->ospriv, UDBG3, "Sending signal 0x%.4X\n", - GET_SIGNAL_ID(packed_sigptr)); -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Sending signal 0x%.4X\n", - GET_SIGNAL_ID(packed_sigptr)); -#endif /* CSR_WIFI_HIP_NOISY */ - - /* Append packed signal to F-H buffer */ - total_length = sig_chunks * card->config_data.sig_frag_size; - - card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff); - card->fh_buffer.ptr[1] = - (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4)); - - memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length); - memset(card->fh_buffer.ptr + 2 + signal_length, 0, - total_length - (2 + signal_length)); - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n", - signal_length + 2); - dump(card->fh_buffer.ptr, signal_length + 2); - unifi_trace(card->ospriv, UDBG1, " \n"); -#endif /* CSR_WIFI_HIP_NOISY */ - - card->fh_buffer.ptr += total_length; - card->fh_buffer.count += sig_chunks; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n", - signal_length, - card->fh_buffer.ptr - card->fh_buffer.buf, - card->fh_buffer.count); -#endif /* CSR_WIFI_HIP_NOISY */ - - (*processed)++; - pending_sigs--; - pending_chunks -= sig_chunks; - - /* Log the signal to the UDI. */ - /* UDI will get the packed structure */ - /* Can not log the unpacked signal, unless we reconstruct it! */ - if (card->udi_hook) - { - (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length, - &bulkdata, UDI_LOG_FROM_HOST); - } - - /* Remove entry from q */ - csptr->signal_length = 0; - /* Note that the traffic queue has only one valid bulk data buffer. */ - csptr->bulkdata[0].data_length = 0; - - CSR_WIFI_HIP_Q_INC_R(&sigq[q_no]); - } while ((pending_sigs > 0) && (pending_chunks > 0) && (q_no >= 0)); - - return CSR_RESULT_SUCCESS; -} /* process_fh_traffic_queue() */ - - -/* - * --------------------------------------------------------------------------- - * flush_fh_buffer - * - * Write out the cache from-hosts signals to the UniFi. - * - * Arguments: - * card Pointer to card context struct - * - * Returns: - * CSR error code if an SDIO error occurred. - * --------------------------------------------------------------------------- - */ -static CsrResult flush_fh_buffer(card_t *card) -{ - CsrResult r; - u16 len; - u16 sig_units; - u16 data_round; - u16 chunks_in_last_block; - u16 padding_chunks; - u16 i; - - len = card->fh_buffer.ptr - card->fh_buffer.buf; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "fh_buffer is at %p, ptr= %p\n", - card->fh_buffer.buf, card->fh_buffer.ptr); -#endif /* CSR_WIFI_HIP_NOISY */ - - if (len == 0) - { - return CSR_RESULT_SUCCESS; - } - -#ifdef CSR_WIFI_HIP_NOISY - if (dump_fh_buf) - { - dump(card->fh_buffer.buf, len); - dump_fh_buf = 0; - } -#endif /* CSR_WIFI_HIP_NOISY */ - - if (card->sdio_io_block_pad) - { - /* Both of these are powers of 2 */ - sig_units = card->config_data.sig_frag_size; - data_round = card->sdio_io_block_size; - - if (data_round > sig_units) - { - chunks_in_last_block = (len % data_round) / sig_units; - - if (chunks_in_last_block != 0) - { - padding_chunks = (data_round / sig_units) - chunks_in_last_block; - - memset(card->fh_buffer.ptr, 0, padding_chunks * sig_units); - for (i = 0; i < padding_chunks; i++) - { - card->fh_buffer.ptr[1] = SDIO_CMD_PADDING << 4; - card->fh_buffer.ptr += sig_units; - } - - card->fh_buffer.count += padding_chunks; - len += padding_chunks * sig_units; - } - } - } - - r = unifi_bulk_rw(card, - card->config_data.fromhost_sigbuf_handle, - card->fh_buffer.buf, - len, UNIFI_SDIO_WRITE); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write fh signals: %u bytes, error %d\n", len, r); - return r; - } - - /* Update from-host-signals-written signal count */ - card->from_host_signals_w = - (card->from_host_signals_w + card->fh_buffer.count) % 128u; - r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 0, - (u8)card->from_host_signals_w); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write fh signal count %u with error %d\n", - card->from_host_signals_w, r); - return r; - } - card->generate_interrupt = 1; - - /* Reset the fh buffer pointer */ - card->fh_buffer.ptr = card->fh_buffer.buf; - card->fh_buffer.count = 0; - -#ifdef CSR_WIFI_HIP_NOISY - unifi_error(card->ospriv, "END flush: fh len %d, count %d\n", - card->fh_buffer.ptr - card->fh_buffer.buf, - card->fh_buffer.count); -#endif /* CSR_WIFI_HIP_NOISY */ - - return CSR_RESULT_SUCCESS; -} /* flush_fh_buffer() */ - - -/* - * --------------------------------------------------------------------------- - * restart_packet_flow - * - * This function is called before the bottom-half thread sleeps. - * It checks whether both data and signal resources are available and - * then calls the OS-layer function to re-enable packet transmission. - * - * Arguments: - * card Pointer to card context struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void restart_packet_flow(card_t *card) -{ - u8 q; - - /* - * We only look at the fh_traffic_queue, because that is where packets from - * the network stack are placed. - */ - for (q = 0; q <= UNIFI_TRAFFIC_Q_VO; q++) - { - if (card_is_tx_q_paused(card, q) && - CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[q]) >= RESUME_XMIT_THRESHOLD) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("U"); -#endif - card_tx_q_unpause(card, q); - unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue)q); - } - } -} /* restart_packet_flow() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c b/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c deleted file mode 100644 index 17867f60df16..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c +++ /dev/null @@ -1,1713 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_card_sdio_mem.c - * - * PURPOSE: Implementation of the Card API for SDIO. - * - * --------------------------------------------------------------------------- - */ -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_card.h" - -#define SDIO_RETRIES 3 -#define CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH 16 - - -#define retryable_sdio_error(_csrResult) (((_csrResult) == CSR_SDIO_RESULT_CRC_ERROR) || ((_csrResult) == CSR_SDIO_RESULT_TIMEOUT)) - - -/* - * --------------------------------------------------------------------------- - * retrying_read8 - * retrying_write8 - * - * These functions provide the first level of retry for SDIO operations. - * If an SDIO command fails for reason of a response timeout or CRC - * error, it is retried immediately. If three attempts fail we report a - * failure. - * If the command failed for any other reason, the failure is reported - * immediately. - * - * Arguments: - * card Pointer to card structure. - * funcnum The SDIO function to access. - * Function 0 is the Card Configuration Register space, - * function 1/2 is the UniFi register space. - * addr Address to access - * pdata Pointer in which to return the value read. - * data Value to write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -static CsrResult retrying_read8(card_t *card, s16 funcnum, u32 addr, u8 *pdata) -{ - CsrSdioFunction *sdio = card->sdio_if; - CsrResult r = CSR_RESULT_SUCCESS; - s16 retries; - CsrResult csrResult = CSR_RESULT_SUCCESS; - - retries = 0; - while (retries++ < SDIO_RETRIES) - { - if (funcnum == 0) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("r0@%02X", addr); -#endif - csrResult = CsrSdioF0Read8(sdio, addr, pdata); - } - else - { -#ifdef CSR_WIFI_TRANSPORT_CSPI - unifi_error(card->ospriv, - "retrying_read_f0_8: F1 8-bit reads are not allowed.\n"); - return CSR_RESULT_FAILURE; -#else -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("r@%02X", addr); -#endif - csrResult = CsrSdioRead8(sdio, addr, pdata); -#endif - } -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf("error=%X\n", csrResult); - } - else - { - unifi_debug_log_to_buf("=%X\n", *pdata); - } -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - /* - * Try again for retryable (CRC or TIMEOUT) errors, - * break on success or fatal error - */ - if (!retryable_sdio_error(csrResult)) - { -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.cmd52_count++; -#endif - break; - } - unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); - } - - if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) - { - unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); - } - - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", - addr, retries - 1); - /* Report any SDIO error as a general i/o error */ - r = CSR_RESULT_FAILURE; - } - - return r; -} /* retrying_read8() */ - - -static CsrResult retrying_write8(card_t *card, s16 funcnum, u32 addr, u8 data) -{ - CsrSdioFunction *sdio = card->sdio_if; - CsrResult r = CSR_RESULT_SUCCESS; - s16 retries; - CsrResult csrResult = CSR_RESULT_SUCCESS; - - retries = 0; - while (retries++ < SDIO_RETRIES) - { - if (funcnum == 0) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("w0@%02X=%X", addr, data); -#endif - csrResult = CsrSdioF0Write8(sdio, addr, data); - } - else - { -#ifdef CSR_WIFI_TRANSPORT_CSPI - unifi_error(card->ospriv, - "retrying_write_f0_8: F1 8-bit writes are not allowed.\n"); - return CSR_RESULT_FAILURE; -#else -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("w@%02X=%X", addr, data); -#endif - csrResult = CsrSdioWrite8(sdio, addr, data); -#endif - } -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf(",error=%X", csrResult); - } - unifi_debug_string_to_buf("\n"); -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - /* - * Try again for retryable (CRC or TIMEOUT) errors, - * break on success or fatal error - */ - if (!retryable_sdio_error(csrResult)) - { -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.cmd52_count++; -#endif - break; - } - unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", - data, funcnum, addr); - } - - if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) - { - unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); - } - - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", - addr, retries - 1); - /* Report any SDIO error as a general i/o error */ - r = CSR_RESULT_FAILURE; - } - - return r; -} /* retrying_write8() */ - - -static CsrResult retrying_read16(card_t *card, s16 funcnum, - u32 addr, u16 *pdata) -{ - CsrSdioFunction *sdio = card->sdio_if; - CsrResult r = CSR_RESULT_SUCCESS; - s16 retries; - CsrResult csrResult = CSR_RESULT_SUCCESS; - - retries = 0; - while (retries++ < SDIO_RETRIES) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("r@%02X", addr); -#endif - csrResult = CsrSdioRead16(sdio, addr, pdata); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf("error=%X\n", csrResult); - } - else - { - unifi_debug_log_to_buf("=%X\n", *pdata); - } -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - - /* - * Try again for retryable (CRC or TIMEOUT) errors, - * break on success or fatal error - */ - if (!retryable_sdio_error(csrResult)) - { -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.cmd52_count++; -#endif - break; - } - unifi_trace(card->ospriv, UDBG2, "retryable SDIO error reading F%d 0x%lX\n", funcnum, addr); - } - - if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) - { - unifi_warning(card->ospriv, "Read succeeded after %d attempts\n", retries); - } - - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read from UniFi (addr 0x%lX) after %d tries\n", - addr, retries - 1); - /* Report any SDIO error as a general i/o error */ - r = CSR_RESULT_FAILURE; - } - - return r; -} /* retrying_read16() */ - - -static CsrResult retrying_write16(card_t *card, s16 funcnum, - u32 addr, u16 data) -{ - CsrSdioFunction *sdio = card->sdio_if; - CsrResult r = CSR_RESULT_SUCCESS; - s16 retries; - CsrResult csrResult = CSR_RESULT_SUCCESS; - - retries = 0; - while (retries++ < SDIO_RETRIES) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("w@%02X=%X", addr, data); -#endif - csrResult = CsrSdioWrite16(sdio, addr, data); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf(",error=%X", csrResult); - } - unifi_debug_string_to_buf("\n"); -#endif - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } - - /* - * Try again for retryable (CRC or TIMEOUT) errors, - * break on success or fatal error - */ - if (!retryable_sdio_error(csrResult)) - { -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.cmd52_count++; -#endif - break; - } - unifi_trace(card->ospriv, UDBG2, "retryable SDIO error writing %02X to F%d 0x%lX\n", - data, funcnum, addr); - } - - if ((csrResult == CSR_RESULT_SUCCESS) && (retries > 1)) - { - unifi_warning(card->ospriv, "Write succeeded after %d attempts\n", retries); - } - - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write to UniFi (addr 0x%lX) after %d tries\n", - addr, retries - 1); - /* Report any SDIO error as a general i/o error */ - r = CSR_RESULT_FAILURE; - } - - return r; -} /* retrying_write16() */ - - -/* - * --------------------------------------------------------------------------- - * sdio_read_f0 - * - * Reads a byte value from the CCCR (func 0) area of UniFi. - * - * Arguments: - * card Pointer to card structure. - * addr Address to read from - * pdata Pointer in which to store the read value. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -CsrResult sdio_read_f0(card_t *card, u32 addr, u8 *pdata) -{ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_f0_r_count++; -#endif - return retrying_read8(card, 0, addr, pdata); -} /* sdio_read_f0() */ - - -/* - * --------------------------------------------------------------------------- - * sdio_write_f0 - * - * Writes a byte value to the CCCR (func 0) area of UniFi. - * - * Arguments: - * card Pointer to card structure. - * addr Address to read from - * data Data value to write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -CsrResult sdio_write_f0(card_t *card, u32 addr, u8 data) -{ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_f0_w_count++; -#endif - return retrying_write8(card, 0, addr, data); -} /* sdio_write_f0() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read_direct_8_or_16 - * - * Read a 8-bit value from the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Address to read from - * pdata Pointer in which to return data. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read_direct_8_or_16(card_t *card, u32 addr, u8 *pdata) -{ -#ifdef CSR_WIFI_TRANSPORT_CSPI - u16 w; - CsrResult r; - - r = retrying_read16(card, card->function, addr, &w); - *pdata = (u8)(w & 0xFF); - return r; -#else - return retrying_read8(card, card->function, addr, pdata); -#endif -} /* unifi_read_direct_8_or_16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_write_direct_8_or_16 - * - * Write a byte value to the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Address to write to - * data Value to write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error - * - * Notes: - * If 8-bit write is used, the even address *must* be written second. - * This is because writes to odd bytes are cached and not committed - * to memory until the preceding even address is written. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_write_direct_8_or_16(card_t *card, u32 addr, u8 data) -{ - if (addr & 1) - { - unifi_warning(card->ospriv, - "Warning: Byte write to an odd address (0x%lX) is dangerous\n", - addr); - } - -#ifdef CSR_WIFI_TRANSPORT_CSPI - return retrying_write16(card, card->function, addr, (u16)data); -#else - return retrying_write8(card, card->function, addr, data); -#endif -} /* unifi_write_direct_8_or_16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read_direct16 - * - * Read a 16-bit value from the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Address to read from - * pdata Pointer in which to return data. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * The even address *must* be read first. This is because reads from - * odd bytes are cached and read from memory when the preceding - * even address is read. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read_direct16(card_t *card, u32 addr, u16 *pdata) -{ - return retrying_read16(card, card->function, addr, pdata); -} /* unifi_read_direct16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_write_direct16 - * - * Write a 16-bit value to the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Address to write to - * data Value to write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * The even address *must* be written second. This is because writes to - * odd bytes are cached and not committed to memory until the preceding - * even address is written. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_write_direct16(card_t *card, u32 addr, u16 data) -{ - return retrying_write16(card, card->function, addr, data); -} /* unifi_write_direct16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read_direct32 - * - * Read a 32-bit value from the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Address to read from - * pdata Pointer in which to return data. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read_direct32(card_t *card, u32 addr, u32 *pdata) -{ - CsrResult r; - u16 w0, w1; - - r = retrying_read16(card, card->function, addr, &w0); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - r = retrying_read16(card, card->function, addr + 2, &w1); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - *pdata = ((u32)w1 << 16) | (u32)w0; - - return CSR_RESULT_SUCCESS; -} /* unifi_read_direct32() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read_directn_match - * - * Read multiple 8-bit values from the UniFi SDIO interface, - * stopping when either we have read 'len' bytes or we have read - * a octet equal to 'match'. If 'match' is not a valid octet - * then this function is the same as 'unifi_read_directn'. - * - * Arguments: - * card Pointer to card structure. - * addr Start address to read from. - * pdata Pointer to which to write data. - * len Maximum umber of bytes to read - * match The value to stop reading at. - * num Pointer to buffer to write number of bytes read - * - * Returns: - * number of octets read on success, negative error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * The even address *must* be read first. This is because reads from - * odd bytes are cached and read from memory when the preceding - * even address is read. - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_read_directn_match(card_t *card, u32 addr, void *pdata, u16 len, s8 m, u32 *num) -{ - CsrResult r; - u32 i; - u8 *cptr; - u16 w; - - *num = 0; - - cptr = (u8 *)pdata; - for (i = 0; i < len; i += 2) - { - r = retrying_read16(card, card->function, addr, &w); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - *cptr++ = ((u8)w & 0xFF); - if ((m >= 0) && (((s8)w & 0xFF) == m)) - { - break; - } - - if (i + 1 == len) - { - /* The len is odd. Ignore the last high byte */ - break; - } - - *cptr++ = ((u8)(w >> 8) & 0xFF); - if ((m >= 0) && (((s8)(w >> 8) & 0xFF) == m)) - { - break; - } - - addr += 2; - } - - *num = (s32)(cptr - (u8 *)pdata); - return CSR_RESULT_SUCCESS; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_read_directn - * - * Read multiple 8-bit values from the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Start address to read from. - * pdata Pointer to which to write data. - * len Number of bytes to read - * - * Returns: - * 0 on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * The even address *must* be read first. This is because reads from - * odd bytes are cached and read from memory when the preceding - * even address is read. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read_directn(card_t *card, u32 addr, void *pdata, u16 len) -{ - u32 num; - - return unifi_read_directn_match(card, addr, pdata, len, -1, &num); -} /* unifi_read_directn() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_write_directn - * - * Write multiple 8-bit values to the UniFi SDIO interface. - * - * Arguments: - * card Pointer to card structure. - * addr Start address to write to. - * pdata Source data pointer. - * len Number of bytes to write, must be even. - * - * Returns: - * 0 on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * The UniFi has a peculiar 16-bit bus architecture. Writes are only - * committed to memory when an even address is accessed. Writes to - * odd addresses are cached and only committed if the next write is - * to the preceding address. - * This means we must write data as pairs of bytes in reverse order. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_write_directn(card_t *card, u32 addr, void *pdata, u16 len) -{ - CsrResult r; - u8 *cptr; - s16 signed_len; - - cptr = (u8 *)pdata; - signed_len = (s16)len; - while (signed_len > 0) - { - /* This is UniFi-1 specific code. CSPI not supported so 8-bit write allowed */ - r = retrying_write16(card, card->function, addr, *cptr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - cptr += 2; - addr += 2; - signed_len -= 2; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_write_directn() */ - - -/* - * --------------------------------------------------------------------------- - * set_dmem_page - * set_pmem_page - * - * Set up the page register for the shared data memory window or program - * memory window. - * - * Arguments: - * card Pointer to card structure. - * dmem_addr UniFi shared-data-memory address to access. - * pmem_addr UniFi program memory address to access. This includes - * External FLASH memory at 0x000000 - * Processor program memory at 0x200000 - * External SRAM at memory 0x400000 - * paddr Location to write an SDIO address (24-bit) for - * use in a unifi_read_direct or unifi_write_direct call. - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -static CsrResult set_dmem_page(card_t *card, u32 dmem_addr, u32 *paddr) -{ - u16 page, addr; - u32 len; - CsrResult r; - - *paddr = 0; - - if (!ChipHelper_DecodeWindow(card->helper, - CHIP_HELPER_WINDOW_3, - CHIP_HELPER_WT_SHARED, - dmem_addr / 2, - &page, &addr, &len)) - { - unifi_error(card->ospriv, "Failed to decode SHARED_DMEM_PAGE %08lx\n", dmem_addr); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - if (page != card->dmem_page) - { - unifi_trace(card->ospriv, UDBG6, "setting dmem page=0x%X, addr=0x%lX\n", page, addr); - - /* change page register */ - r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW3_PAGE(card->helper) * 2, page); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write SHARED_DMEM_PAGE\n"); - return r; - } - - card->dmem_page = page; - } - - *paddr = ((s32)addr * 2) + (dmem_addr & 1); - - return CSR_RESULT_SUCCESS; -} /* set_dmem_page() */ - - -static CsrResult set_pmem_page(card_t *card, u32 pmem_addr, - enum chip_helper_window_type mem_type, u32 *paddr) -{ - u16 page, addr; - u32 len; - CsrResult r; - - *paddr = 0; - - if (!ChipHelper_DecodeWindow(card->helper, - CHIP_HELPER_WINDOW_2, - mem_type, - pmem_addr / 2, - &page, &addr, &len)) - { - unifi_error(card->ospriv, "Failed to decode PROG MEM PAGE %08lx %d\n", pmem_addr, mem_type); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - if (page != card->pmem_page) - { - unifi_trace(card->ospriv, UDBG6, "setting pmem page=0x%X, addr=0x%lX\n", page, addr); - - /* change page register */ - r = unifi_write_direct16(card, ChipHelper_HOST_WINDOW2_PAGE(card->helper) * 2, page); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write PROG MEM PAGE\n"); - return r; - } - - card->pmem_page = page; - } - - *paddr = ((s32)addr * 2) + (pmem_addr & 1); - - return CSR_RESULT_SUCCESS; -} /* set_pmem_page() */ - - -/* - * --------------------------------------------------------------------------- - * set_page - * - * Sets up the appropriate page register to access the given address. - * Returns the sdio address at which the unifi address can be accessed. - * - * Arguments: - * card Pointer to card structure. - * generic_addr UniFi internal address to access, in Generic Pointer - * format, i.e. top byte is space indicator. - * paddr Location to write page address - * SDIO address (24-bit) for use in a unifi_read_direct or - * unifi_write_direct call - * - * Returns: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE the address is invalid - * --------------------------------------------------------------------------- - */ -static CsrResult set_page(card_t *card, u32 generic_addr, u32 *paddr) -{ - s32 space; - u32 addr; - CsrResult r = CSR_RESULT_SUCCESS; - - if (!paddr) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - *paddr = 0; - space = UNIFI_GP_SPACE(generic_addr); - addr = UNIFI_GP_OFFSET(generic_addr); - switch (space) - { - case UNIFI_SH_DMEM: - /* Shared Data Memory is accessed via the Shared Data Memory window */ - r = set_dmem_page(card, addr, paddr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - break; - - case UNIFI_EXT_FLASH: - if (!ChipHelper_HasFlash(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - /* External FLASH is accessed via the Program Memory window */ - r = set_pmem_page(card, addr, CHIP_HELPER_WT_FLASH, paddr); - break; - - case UNIFI_EXT_SRAM: - if (!ChipHelper_HasExtSram(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08l (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - /* External SRAM is accessed via the Program Memory window */ - r = set_pmem_page(card, addr, CHIP_HELPER_WT_EXT_SRAM, paddr); - break; - - case UNIFI_REGISTERS: - /* Registers are accessed directly */ - *paddr = addr; - break; - - case UNIFI_PHY_DMEM: - r = unifi_set_proc_select(card, UNIFI_PROC_PHY); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; - break; - - case UNIFI_MAC_DMEM: - r = unifi_set_proc_select(card, UNIFI_PROC_MAC); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; - break; - - case UNIFI_BT_DMEM: - if (!ChipHelper_HasBt(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - r = unifi_set_proc_select(card, UNIFI_PROC_BT); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - *paddr = ChipHelper_DATA_MEMORY_RAM_OFFSET(card->helper) * 2 + addr; - break; - - case UNIFI_PHY_PMEM: - r = unifi_set_proc_select(card, UNIFI_PROC_PHY); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); - break; - - case UNIFI_MAC_PMEM: - r = unifi_set_proc_select(card, UNIFI_PROC_MAC); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); - break; - - case UNIFI_BT_PMEM: - if (!ChipHelper_HasBt(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - r = unifi_set_proc_select(card, UNIFI_PROC_BT); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_CODE_RAM, paddr); - break; - - case UNIFI_PHY_ROM: - if (!ChipHelper_HasRom(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - r = unifi_set_proc_select(card, UNIFI_PROC_PHY); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); - break; - - case UNIFI_MAC_ROM: - if (!ChipHelper_HasRom(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - r = unifi_set_proc_select(card, UNIFI_PROC_MAC); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); - break; - - case UNIFI_BT_ROM: - if (!ChipHelper_HasRom(card->helper) || !ChipHelper_HasBt(card->helper)) - { - unifi_error(card->ospriv, "Bad address space for chip in generic pointer 0x%08lX (helper=0x%x)\n", - generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - r = unifi_set_proc_select(card, UNIFI_PROC_BT); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - r = set_pmem_page(card, addr, CHIP_HELPER_WT_ROM, paddr); - break; - - default: - unifi_error(card->ospriv, "Bad address space %d in generic pointer 0x%08lX (helper=0x%x)\n", - space, generic_addr, card->helper); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - return r; -} /* set_page() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_set_proc_select - * - * - * Arguments: - * card Pointer to card structure. - * select Which XAP core to select - * - * Returns: - * 0 on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * --------------------------------------------------------------------------- - */ -CsrResult unifi_set_proc_select(card_t *card, enum unifi_dbg_processors_select select) -{ - CsrResult r; - - /* Verify the the select value is allowed. */ - switch (select) - { - case UNIFI_PROC_MAC: - case UNIFI_PROC_PHY: - case UNIFI_PROC_BOTH: - break; - - - default: - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - if (card->proc_select != (u32)select) - { - r = unifi_write_direct16(card, - ChipHelper_DBG_HOST_PROC_SELECT(card->helper) * 2, - (u8)select); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write to Proc Select register\n"); - return r; - } - - card->proc_select = (u32)select; - } - - return CSR_RESULT_SUCCESS; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_read_8_or_16 - * - * Performs a byte read of the given address in shared data memory. - * Set up the shared data memory page register as required. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to a byte variable for the value read. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read_8_or_16(card_t *card, u32 unifi_addr, u8 *pdata) -{ - u32 sdio_addr; - CsrResult r; -#ifdef CSR_WIFI_TRANSPORT_CSPI - u16 w; -#endif - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_r8or16_count++; -#endif -#ifdef CSR_WIFI_TRANSPORT_CSPI - r = retrying_read16(card, card->function, sdio_addr, &w); - *pdata = (u8)(w & 0xFF); - return r; -#else - return retrying_read8(card, card->function, sdio_addr, pdata); -#endif -} /* unifi_read_8_or_16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_write_8_or_16 - * - * Performs a byte write of the given address in shared data memory. - * Set up the shared data memory page register as required. - * - * Arguments: - * card Pointer to card context struct. - * unifi_addr UniFi shared-data-memory address to access. - * data Value to write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * - * Notes: - * Beware using unifi_write8() because byte writes are not safe on UniFi. - * Writes to odd bytes are cached, writes to even bytes perform a 16-bit - * write with the previously cached odd byte. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_write_8_or_16(card_t *card, u32 unifi_addr, u8 data) -{ - u32 sdio_addr; - CsrResult r; -#ifdef CSR_WIFI_TRANSPORT_CSPI - u16 w; -#endif - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - if (sdio_addr & 1) - { - unifi_warning(card->ospriv, - "Warning: Byte write to an odd address (0x%lX) is dangerous\n", - sdio_addr); - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_w8or16_count++; -#endif -#ifdef CSR_WIFI_TRANSPORT_CSPI - w = data; - return retrying_write16(card, card->function, sdio_addr, w); -#else - return retrying_write8(card, card->function, sdio_addr, data); -#endif -} /* unifi_write_8_or_16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_read16 - * - * Performs a 16-bit read of the given address in shared data memory. - * Set up the shared data memory page register as required. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to a 16-bit int variable for the value read. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * --------------------------------------------------------------------------- - */ -CsrResult unifi_card_read16(card_t *card, u32 unifi_addr, u16 *pdata) -{ - u32 sdio_addr; - CsrResult r; - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_r16_count++; -#endif - return unifi_read_direct16(card, sdio_addr, pdata); -} /* unifi_card_read16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_write16 - * - * Performs a 16-bit write of the given address in shared data memory. - * Set up the shared data memory page register as required. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to a byte variable for the value write. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * --------------------------------------------------------------------------- - */ -CsrResult unifi_card_write16(card_t *card, u32 unifi_addr, u16 data) -{ - u32 sdio_addr; - CsrResult r; - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_w16_count++; -#endif - return unifi_write_direct16(card, sdio_addr, data); -} /* unifi_card_write16() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read32 - * - * Performs a 32-bit read of the given address in shared data memory. - * Set up the shared data memory page register as required. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to a int variable for the value read. - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * --------------------------------------------------------------------------- - */ -CsrResult unifi_read32(card_t *card, u32 unifi_addr, u32 *pdata) -{ - u32 sdio_addr; - CsrResult r; - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - card->cmd_prof.cmd52_r32_count++; -#endif - return unifi_read_direct32(card, sdio_addr, pdata); -} /* unifi_read32() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_card_readn - * unifi_readnz - * - * Read multiple 8-bit values from the UniFi SDIO interface. - * This function interprets the address as a GenericPointer as - * defined in the UniFi Host Interface Protocol Specification. - * The readnz version of this function will stop when it reads a - * zero octet. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to which to write data. - * len Number of bytes to read - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE a bad generic pointer was specified - * --------------------------------------------------------------------------- - */ -CsrResult unifi_readn_match(card_t *card, u32 unifi_addr, void *pdata, u16 len, s8 match) -{ - u32 sdio_addr; - CsrResult r; - u32 num; - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - r = unifi_read_directn_match(card, sdio_addr, pdata, len, match, &num); - return r; -} /* unifi_readn_match() */ - - -CsrResult unifi_card_readn(card_t *card, u32 unifi_addr, void *pdata, u16 len) -{ - return unifi_readn_match(card, unifi_addr, pdata, len, -1); -} /* unifi_card_readn() */ - - -CsrResult unifi_readnz(card_t *card, u32 unifi_addr, void *pdata, u16 len) -{ - return unifi_readn_match(card, unifi_addr, pdata, len, 0); -} /* unifi_readnz() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_read_shared_count - * - * Read signal count locations, checking for an SDIO error. The - * signal count locations only contain a valid number if the - * highest bit isn't set. - * - * Arguments: - * card Pointer to card context structure. - * addr Shared-memory address to read. - * - * Returns: - * Value read from memory (0-127) or -1 on error - * --------------------------------------------------------------------------- - */ -s32 unifi_read_shared_count(card_t *card, u32 addr) -{ - u8 b; - /* I've increased this count, because I have seen cases where - * there were three reads in a row with the top bit set. I'm not - * sure why this might have happened, but I can't see a problem - * with increasing this limit. It's better to take a while to - * recover than to fail. */ -#define SHARED_READ_RETRY_LIMIT 10 - s32 i; - - /* - * Get the to-host-signals-written count. - * The top-bit will be set if the firmware was in the process of - * changing the value, in which case we read again. - */ - /* Limit the number of repeats so we don't freeze */ - for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) - { - CsrResult r; - r = unifi_read_8_or_16(card, addr, &b); - if (r != CSR_RESULT_SUCCESS) - { - return -1; - } - if (!(b & 0x80)) - { - /* There is a chance that the MSB may have contained invalid data - * (overflow) at the time it was read. Therefore mask off the MSB. - * This avoids a race between driver read and firmware write of the - * word, the value we need is in the lower 8 bits anway. - */ - return (s32)(b & 0xff); - } - } - - return -1; /* this function has changed in WMM mods */ -} /* unifi_read_shared_count() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_writen - * - * Write multiple 8-bit values to the UniFi SDIO interface using CMD52 - * This function interprets the address as a GenericPointer as - * defined in the UniFi Host Interface Protocol Specification. - * - * Arguments: - * card Pointer to card structure. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to which to write data. - * len Number of bytes to write - * - * Returns: - * 0 on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * CSR_WIFI_HIP_RESULT_INVALID_VALUE an odd length or length too big. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_writen(card_t *card, u32 unifi_addr, void *pdata, u16 len) -{ - u32 sdio_addr; - CsrResult r; - - r = set_page(card, unifi_addr, &sdio_addr); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - return unifi_write_directn(card, sdio_addr, pdata, len); -} /* unifi_writen() */ - - -static CsrResult csr_sdio_block_rw(card_t *card, s16 funcnum, - u32 addr, u8 *pdata, - u16 count, s16 dir_is_write) -{ - CsrResult csrResult; - - if (dir_is_write == UNIFI_SDIO_READ) - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("r@%02X#%X=", addr, count); -#endif -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("R"); -#endif - csrResult = CsrSdioRead(card->sdio_if, addr, pdata, count); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("<"); -#endif - } - else - { -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - unifi_debug_log_to_buf("w@%02X#%X=", addr, count); - unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); -#endif -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("W"); -#endif - csrResult = CsrSdioWrite(card->sdio_if, addr, pdata, count); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf(">"); -#endif - } -#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE - card->cmd_prof.cmd53_count++; -#endif -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE) - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_debug_log_to_buf("error=%X", csrResult); - } - else if (dir_is_write == UNIFI_SDIO_READ) - { - unifi_debug_hex_to_buf(pdata, count > CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH?CSR_WIFI_HIP_SDIO_TRACE_DATA_LENGTH : count); - } - unifi_debug_string_to_buf("\n"); -#endif - return csrResult; /* CSR SDIO (not HIP) error code */ -} - - -/* - * --------------------------------------------------------------------------- - * unifi_bulk_rw - * - * Transfer bulk data to or from the UniFi SDIO interface. - * This function is used to read or write signals and bulk data. - * - * Arguments: - * card Pointer to card structure. - * handle Value to put in the Register Address field of the CMD53 req. - * data Pointer to data to write. - * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE - * - * Returns: - * CSR_RESULT_SUCCESS on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * This function uses SDIO CMD53, which is the block transfer mode. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_bulk_rw(card_t *card, u32 handle, void *pdata, - u32 len, s16 direction) -{ -#define CMD53_RETRIES 3 - /* - * Ideally instead of sleeping, we want to busy wait. - * Currently there is no framework API to do this. When it becomes available, - * we can use it to busy wait using usecs - */ -#define REWIND_RETRIES 15 /* when REWIND_DELAY==1msec, or 250 when REWIND_DELAY==50usecs */ -#define REWIND_POLLING_RETRIES 5 -#define REWIND_DELAY 1 /* msec or 50usecs */ - CsrResult csrResult; /* SDIO error code */ - CsrResult r = CSR_RESULT_SUCCESS; /* HIP error code */ - s16 retries = CMD53_RETRIES; - s16 stat_retries; - u8 stat; - s16 dump_read; -#ifdef UNIFI_DEBUG - u8 *pdata_lsb = ((u8 *)&pdata) + card->lsb; -#endif -#ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS - static s16 fake_error; -#endif - - dump_read = 0; -#ifdef UNIFI_DEBUG - if (*pdata_lsb & 1) - { - unifi_notice(card->ospriv, "CD53 request on a unaligned buffer (addr: 0x%X) dir %s-Host\n", - pdata, (direction == UNIFI_SDIO_READ)?"To" : "From"); - if (direction == UNIFI_SDIO_WRITE) - { - dump(pdata, (u16)len); - } - else - { - dump_read = 1; - } - } -#endif - - /* Defensive checks */ - if (!pdata) - { - unifi_error(card->ospriv, "Null pdata for unifi_bulk_rw() len: %d\n", len); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - if ((len & 1) || (len > 0xffff)) - { - unifi_error(card->ospriv, "Impossible CMD53 length requested: %d\n", len); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - while (1) - { - csrResult = csr_sdio_block_rw(card, card->function, handle, - (u8 *)pdata, (u16)len, - direction); - if (csrResult == CSR_SDIO_RESULT_NO_DEVICE) - { - return CSR_WIFI_HIP_RESULT_NO_DEVICE; - } -#ifdef CSR_WIFI_MAKE_FAKE_CMD53_ERRORS - if (++fake_error > 100) - { - fake_error = 90; - unifi_warning(card->ospriv, "Faking a CMD53 error,\n"); - if (csrResult == CSR_RESULT_SUCCESS) - { - csrResult = CSR_RESULT_FAILURE; - } - } -#endif - if (csrResult == CSR_RESULT_SUCCESS) - { - if (dump_read) - { - dump(pdata, (u16)len); - } - break; - } - - /* - * At this point the SDIO driver should have written the I/O Abort - * register to notify UniFi that the command has failed. - * UniFi-1 and UniFi-2 (not UF6xxx) use the same register to store the - * Deep Sleep State. This means we have to restore the Deep Sleep - * State (AWAKE in any case since we can not perform a CD53 in any other - * state) by rewriting the I/O Abort register to its previous value. - */ - if (card->chip_id <= SDIO_CARD_ID_UNIFI_2) - { - (void)unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - } - - /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted - * then stop retrying - */ - if (!retryable_sdio_error(csrResult)) - { - unifi_error(card->ospriv, "Fatal error in a CMD53 transfer\n"); - break; - } - - /* - * These happen from time to time, try again - */ - if (--retries == 0) - { - break; - } - - unifi_trace(card->ospriv, UDBG4, - "Error in a CMD53 transfer, retrying (h:%d,l:%u)...\n", - (s16)handle & 0xff, len); - - /* The transfer failed, rewind and try again */ - r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 8, - (u8)(handle & 0xff)); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - /* - * If we can't even do CMD52 (register read/write) then - * stop here. - */ - unifi_error(card->ospriv, "Failed to write REWIND cmd\n"); - return r; - } - - /* Signal the UniFi to look for the rewind request. */ - r = CardGenInt(card); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - /* Wait for UniFi to acknowledge the rewind */ - stat_retries = REWIND_RETRIES; - while (1) - { - r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 8, &stat); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read REWIND status\n"); - return CSR_RESULT_FAILURE; - } - - if (stat == 0) - { - break; - } - if (--stat_retries == 0) - { - unifi_error(card->ospriv, "Timeout waiting for REWIND ready\n"); - return CSR_RESULT_FAILURE; - } - - /* Poll for the ack a few times */ - if (stat_retries < REWIND_RETRIES - REWIND_POLLING_RETRIES) - { - CsrThreadSleep(REWIND_DELAY); - } - } - } - - /* The call to csr_sdio_block_rw() still failed after retrying */ - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Block %s failed after %d retries\n", - (direction == UNIFI_SDIO_READ)?"read" : "write", - CMD53_RETRIES - retries); - /* Report any SDIO error as a general i/o error */ - return CSR_RESULT_FAILURE; - } - - /* Collect some stats */ - if (direction == UNIFI_SDIO_READ) - { - card->sdio_bytes_read += len; - } - else - { - card->sdio_bytes_written += len; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_bulk_rw() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_bulk_rw_noretry - * - * Transfer bulk data to or from the UniFi SDIO interface. - * This function is used to read or write signals and bulk data. - * - * Arguments: - * card Pointer to card structure. - * handle Value to put in the Register Address field of - * the CMD53 req. - * data Pointer to data to write. - * direction One of UNIFI_SDIO_READ or UNIFI_SDIO_WRITE - * - * Returns: - * 0 on success, non-zero error code on error: - * CSR_WIFI_HIP_RESULT_NO_DEVICE card was ejected - * CSR_RESULT_FAILURE an SDIO error occurred - * - * Notes: - * This function uses SDIO CMD53, which is the block transfer mode. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_bulk_rw_noretry(card_t *card, u32 handle, void *pdata, - u32 len, s16 direction) -{ - CsrResult csrResult; - - csrResult = csr_sdio_block_rw(card, card->function, handle, - (u8 *)pdata, (u16)len, direction); - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Block %s failed\n", - (direction == UNIFI_SDIO_READ)?"read" : "write"); - return csrResult; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_bulk_rw_noretry() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.c b/drivers/staging/csr/csr_wifi_hip_chiphelper.c deleted file mode 100644 index 5cf5b8a5a1e1..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_chiphelper.c +++ /dev/null @@ -1,793 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_macro.h" -#include "csr_wifi_hip_chiphelper_private.h" - -#ifndef nelem -#define nelem(a) (sizeof(a) / sizeof(a[0])) -#endif - -#define counted(foo) { nelem(foo), foo } -#define null_counted() { 0, NULL } - -/* The init values are a set of register writes that we must - perform when we first connect to the chip to get it working. - They swicth on the correct clocks and possibly set the host - interface as a wkaeup source. They should not be used if - proper HIP opperation is required, but are useful before we - do a code download. */ -static const struct chip_helper_init_values init_vals_v1[] = { - { 0xFDBB, 0xFFFF }, - { 0xFDB6, 0x03FF }, - { 0xFDB1, 0x01E3 }, - { 0xFDB3, 0x0FFF }, - { 0xFEE3, 0x08F0 }, - { 0xFEE7, 0x3C3F }, - { 0xFEE6, 0x0050 }, - { 0xFDBA, 0x0000 } -}; - -static const struct chip_helper_init_values init_vals_v2[] = { - { 0xFDB6, 0x0FFF }, - { 0xF023, 0x3F3F }, - { 0xFDB1, 0x01E3 }, - { 0xFDB3, 0x0FFF }, - { 0xF003, 0x08F0 }, - { 0xF007, 0x3C3F }, - { 0xF006, 0x0050 } -}; - - -static const struct chip_helper_init_values init_vals_v22_v23[] = { - { 0xF81C, 0x00FF }, - /*{ 0x????, 0x???? }, */ - { 0xF80C, 0x1FFF }, - { 0xFA25, 0x001F }, - { 0xF804, 0x00FF }, - { 0xF802, 0x0FFF }, - /*{ 0x????, 0x???? }, - { 0x????, 0x???? }, - { 0x????, 0x???? }*/ -}; - -static const u16 reset_program_a_v1_or_v2[] = { - 0x0000 -}; -static const u16 reset_program_b_v1_or_v2[] = { - 0x0010, 0xFE00, 0xA021, 0xFF00, 0x8111, 0x0009, 0x0CA4, 0x0114, - 0x0280, 0x04F8, 0xFE00, 0x6F25, 0x06E0, 0x0010, 0xFC00, 0x0121, - 0xFC00, 0x0225, 0xFE00, 0x7125, 0xFE00, 0x6D11, 0x03F0, 0xFE00, - 0x6E25, 0x0008, 0x00E0 -}; - -static const struct chip_helper_reset_values reset_program_v1_or_v2[] = -{ - { - MAKE_GP(REGISTERS, 0x000C), - nelem(reset_program_a_v1_or_v2), - reset_program_a_v1_or_v2 - }, - { - MAKE_GP(MAC_PMEM, 0x000000), - nelem(reset_program_b_v1_or_v2), - reset_program_b_v1_or_v2 - } -}; - -static const struct chip_map_address_t unifi_map_address_v1_v2[] = -{ - { 0xFE9F, 0xFE7B }, /* PM1_BANK_SELECT */ - { 0xFE9E, 0xFE78 }, /* PM2_BANK_SELECT */ - { 0xFE9D, 0xFE7E }, /* SHARED_DMEM_PAGE */ - { 0xFE91, 0xFE90 }, /* PROC_SELECT */ - { 0xFE8D, 0xFE8C }, /* STOP_STATUS */ -}; - -static const struct chip_map_address_t unifi_map_address_v22_v23[] = -{ - { 0xF8F9, 0xF8AC }, /* GW1_CONFIG */ - { 0xF8FA, 0xF8AD }, /* GW2_CONFIG */ - { 0xF8FB, 0xF8AE }, /* GW3_CONFIG */ - { 0xF830, 0xF81E }, /* PROC_SELECT */ - { 0xF831, 0xF81F }, /* STOP_STATUS */ - { 0xF8FC, 0xF8AF }, /* IO_LOG_ADDRESS */ -}; - -static const struct chip_device_regs_t unifi_device_regs_null = -{ - 0xFE81, /* GBL_CHIP_VERSION */ - 0x0000, /* GBL_MISC_ENABLES */ - 0x0000, /* DBG_EMU_CMD */ - { - 0x0000, /* HOST.DBG_PROC_SELECT */ - 0x0000, /* HOST.DBG_STOP_STATUS */ - 0x0000, /* HOST.WINDOW1_PAGE */ - 0x0000, /* HOST.WINDOW2_PAGE */ - 0x0000, /* HOST.WINDOW3_PAGE */ - 0x0000 /* HOST.IO_LOG_ADDR */ - }, - { - 0x0000, /* SPI.DBG_PROC_SELECT */ - 0x0000, /* SPI.DBG_STOP_STATUS */ - 0x0000, /* SPI.WINDOW1_PAGE */ - 0x0000, /* SPI.WINDOW2_PAGE */ - 0x0000, /* SPI.WINDOW3_PAGE */ - 0x0000 /* SPI.IO_LOG_ADDR */ - }, - 0x0000, /* DBG_RESET */ - 0x0000, /* > DBG_RESET_VALUE */ - 0x0000, /* DBG_RESET_WARN */ - 0x0000, /* DBG_RESET_WARN_VALUE */ - 0x0000, /* DBG_RESET_RESULT */ - 0xFFE9, /* XAP_PCH */ - 0xFFEA, /* XAP_PCL */ - 0x0000, /* PROC_PC_SNOOP */ - 0x0000, /* WATCHDOG_DISABLE */ - 0x0000, /* MAILBOX0 */ - 0x0000, /* MAILBOX1 */ - 0x0000, /* MAILBOX2 */ - 0x0000, /* MAILBOX3 */ - 0x0000, /* SDIO_HOST_INT */ - 0x0000, /* SHARED_IO_INTERRUPT */ - 0x0000, /* SDIO HIP HANDSHAKE */ - 0x0000 /* COEX_STATUS */ -}; - -/* UF105x */ -static const struct chip_device_regs_t unifi_device_regs_v1 = -{ - 0xFE81, /* GBL_CHIP_VERSION */ - 0xFE87, /* GBL_MISC_ENABLES */ - 0xFE9C, /* DBG_EMU_CMD */ - { - 0xFE90, /* HOST.DBG_PROC_SELECT */ - 0xFE8C, /* HOST.DBG_STOP_STATUS */ - 0xFE7B, /* HOST.WINDOW1_PAGE */ - 0xFE78, /* HOST.WINDOW2_PAGE */ - 0xFE7E, /* HOST.WINDOW3_PAGE */ - 0x0000 /* HOST.IO_LOG_ADDR */ - }, - { - 0xFE91, /* SPI.DBG_PROC_SELECT */ - 0xFE8D, /* SPI.DBG_STOP_STATUS */ - 0xFE9F, /* SPI.WINDOW1_PAGE */ - 0xFE9E, /* SPI.WINDOW2_PAGE */ - 0xFE9D, /* SPI.WINDOW3_PAGE */ - 0x0000 /* SPI.IO_LOG_ADDR */ - }, - 0xFE92, /* DBG_RESET */ - 0x0001, /* > DBG_RESET_VALUE */ - 0xFDA0, /* DBG_RESET_WARN (HOST_SELECT) */ - 0x0000, /* DBG_RESET_WARN_VALUE */ - 0xFE92, /* DBG_RESET_RESULT */ - 0xFFE9, /* XAP_PCH */ - 0xFFEA, /* XAP_PCL */ - 0x0051, /* PROC_PC_SNOOP */ - 0xFE70, /* WATCHDOG_DISABLE */ - 0xFE6B, /* MAILBOX0 */ - 0xFE6A, /* MAILBOX1 */ - 0xFE69, /* MAILBOX2 */ - 0xFE68, /* MAILBOX3 */ - 0xFE67, /* SDIO_HOST_INT */ - 0xFE65, /* SHARED_IO_INTERRUPT */ - 0xFDE9, /* SDIO HIP HANDSHAKE */ - 0x0000 /* COEX_STATUS */ -}; - -/* UF2... */ -static const struct chip_device_regs_t unifi_device_regs_v2 = -{ - 0xFE81, /* GBL_CHIP_VERSION */ - 0xFE87, /* GBL_MISC_ENABLES */ - 0xFE9C, /* DBG_EMU_CMD */ - { - 0xFE90, /* HOST.DBG_PROC_SELECT */ - 0xFE8C, /* HOST.DBG_STOP_STATUS */ - 0xFE7B, /* HOST.WINDOW1_PAGE */ - 0xFE78, /* HOST.WINDOW2_PAGE */ - 0xFE7E, /* HOST.WINDOW3_PAGE */ - 0x0000 /* HOST.IO_LOG_ADDR */ - }, - { - 0xFE91, /* SPI.DBG_PROC_SELECT */ - 0xFE8D, /* SPI.DBG_STOP_STATUS */ - 0xFE9F, /* SPI.WINDOW1_PAGE */ - 0xFE9E, /* SPI.WINDOW2_PAGE */ - 0xFE9D, /* SPI.WINDOW3_PAGE */ - 0x0000 /* SPI.IO_LOG_ADDR */ - }, - 0xFE92, /* DBG_RESET */ - 0x0000, /* > DBG_RESET_VALUE */ - 0xFDE9, /* DBG_RESET_WARN (TEST_FLASH_DATA - SHARED_MAILBOX2B) */ - 0xFFFF, /* DBG_RESET_WARN_VALUE */ - 0xFDE9, /* DBG_RESET_RESULT (TEST_FLASH_DATA) */ - 0xFFE9, /* XAP_PCH */ - 0xFFEA, /* XAP_PCL */ - 0x0051, /* PROC_PC_SNOOP */ - 0xFE70, /* WATCHDOG_DISABLE */ - 0xFE6B, /* MAILBOX0 */ - 0xFE6A, /* MAILBOX1 */ - 0xFE69, /* MAILBOX2 */ - 0xFE68, /* MAILBOX3 */ - 0xFE67, /* SDIO_HOST_INT */ - 0xFE65, /* SHARED_IO_INTERRUPT */ - 0xFE69, /* SDIO HIP HANDSHAKE */ - 0x0000 /* COEX_STATUS */ -}; - -/* UF60xx */ -static const struct chip_device_regs_t unifi_device_regs_v22_v23 = -{ - 0xFE81, /* GBL_CHIP_VERSION */ - 0xF84F, /* GBL_MISC_ENABLES */ - 0xF81D, /* DBG_EMU_CMD */ - { - 0xF81E, /* HOST.DBG_PROC_SELECT */ - 0xF81F, /* HOST.DBG_STOP_STATUS */ - 0xF8AC, /* HOST.WINDOW1_PAGE */ - 0xF8AD, /* HOST.WINDOW2_PAGE */ - 0xF8AE, /* HOST.WINDOW3_PAGE */ - 0xF8AF /* HOST.IO_LOG_ADDR */ - }, - { - 0xF830, /* SPI.DBG_PROC_SELECT */ - 0xF831, /* SPI.DBG_STOP_STATUS */ - 0xF8F9, /* SPI.WINDOW1_PAGE */ - 0xF8FA, /* SPI.WINDOW2_PAGE */ - 0xF8FB, /* SPI.WINDOW3_PAGE */ - 0xF8FC /* SPI.IO_LOG_ADDR */ - }, - 0xF82F, /* DBG_RESET */ - 0x0001, /* > DBG_RESET_VALUE */ - 0x0000, /* DBG_RESET_WARN */ - 0x0000, /* DBG_RESET_WARN_VALUE */ - 0xF82F, /* DBG_RESET_RESULT */ - 0xFFE9, /* XAP_PCH */ - 0xFFEA, /* XAP_PCL */ - 0x001B, /* PROC_PC_SNOOP */ - 0x0055, /* WATCHDOG_DISABLE */ - 0xF84B, /* MAILBOX0 */ - 0xF84C, /* MAILBOX1 */ - 0xF84D, /* MAILBOX2 */ - 0xF84E, /* MAILBOX3 */ - 0xF92F, /* SDIO_HOST_INT */ - 0xF92B, /* SDIO_FROMHOST_SCRTACH0 / SHARED_IO_INTERRUPT */ - 0xF84D, /* SDIO HIP HANDSHAKE (MAILBOX2) */ - 0xF9FB /* COEX_STATUS */ -}; - -/* Program memory window on UF105x. */ -static const struct window_shift_info_t prog_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] = -{ - { TRUE, 11, 0x0200 }, /* CODE RAM */ - { TRUE, 11, 0x0000 }, /* FLASH */ - { TRUE, 11, 0x0400 }, /* External SRAM */ - { FALSE, 0, 0 }, /* ROM */ - { FALSE, 0, 0 } /* SHARED */ -}; - -/* Shared memory window on UF105x. */ -static const struct window_shift_info_t shared_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] = -{ - { FALSE, 0, 0 }, /* CODE RAM */ - { FALSE, 0, 0 }, /* FLASH */ - { FALSE, 0, 0 }, /* External SRAM */ - { FALSE, 0, 0 }, /* ROM */ - { TRUE, 11, 0x0000 } /* SHARED */ -}; - -/* One of the Generic Windows on UF60xx and later. */ -static const struct window_shift_info_t generic_window_array_unifi_v22_v23[CHIP_HELPER_WT_COUNT] = -{ - { TRUE, 11, 0x3800 }, /* CODE RAM */ - { FALSE, 0, 0 }, /* FLASH */ - { FALSE, 0, 0 }, /* External SRAM */ - { TRUE, 11, 0x2000 }, /* ROM */ - { TRUE, 11, 0x0000 } /* SHARED */ -}; - -/* The three windows on UF105x. */ -static const struct window_info_t prog1_window_unifi_v1_v2 = { 0x0000, 0x2000, 0x0080, prog_window_array_unifi_v1_v2 }; -static const struct window_info_t prog2_window_unifi_v1_v2 = { 0x2000, 0x2000, 0x0000, prog_window_array_unifi_v1_v2 }; -static const struct window_info_t shared_window_unifi_v1_v2 = { 0x4000, 0x2000, 0x0000, shared_window_array_unifi_v1_v2 }; - -/* The three windows on UF60xx and later. */ -static const struct window_info_t generic1_window_unifi_v22_v23 = { 0x0000, 0x2000, 0x0080, generic_window_array_unifi_v22_v23 }; -static const struct window_info_t generic2_window_unifi_v22_v23 = { 0x2000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 }; -static const struct window_info_t generic3_window_unifi_v22_v23 = { 0x4000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 }; - -static const struct chip_device_desc_t chip_device_desc_null = -{ - { FALSE, 0x0000, 0x0000, 0x00 }, - "", - "", - null_counted(), /* init */ - null_counted(), /* reset_prog */ - &unifi_device_regs_null, /* regs */ - { - FALSE, /* has_flash */ - FALSE, /* has_ext_sram */ - FALSE, /* has_rom */ - FALSE, /* has_bt */ - FALSE, /* has_wlan */ - }, - null_counted(), - /* prog_offset */ - { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000 - }, - /* data_offset */ - { - 0x0000 /* ram */ - }, - /* windows */ - { - NULL, - NULL, - NULL - } -}; - -static const struct chip_device_desc_t unifi_device_desc_v1 = -{ - { FALSE, 0xf0ff, 0x1001, 0x01 }, /* UF105x R01 */ - "UF105x", - "UniFi-1", - counted(init_vals_v1), /* init */ - counted(reset_program_v1_or_v2), /* reset_prog */ - &unifi_device_regs_v1, /* regs */ - { - TRUE, /* has_flash */ - TRUE, /* has_ext_sram */ - FALSE, /* has_rom */ - FALSE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v1_v2), /* map */ - /* prog_offset */ - { - 0x00100000, /* ram */ - 0x00000000, /* rom (invalid) */ - 0x00000000, /* flash */ - 0x00200000, /* ext_ram */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &prog1_window_unifi_v1_v2, - &prog2_window_unifi_v1_v2, - &shared_window_unifi_v1_v2 - } -}; - -static const struct chip_device_desc_t unifi_device_desc_v2 = -{ - { FALSE, 0xf0ff, 0x2001, 0x02 }, /* UF2... R02 */ - "UF2...", - "UniFi-2", - counted(init_vals_v2), /* init */ - counted(reset_program_v1_or_v2), /* reset_prog */ - &unifi_device_regs_v2, /* regs */ - { - TRUE, /* has_flash */ - TRUE, /* has_ext_sram */ - FALSE, /* has_rom */ - FALSE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v1_v2), /* map */ - /* prog_offset */ - { - 0x00100000, /* ram */ - 0x00000000, /* rom (invalid) */ - 0x00000000, /* flash */ - 0x00200000, /* ext_ram */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &prog1_window_unifi_v1_v2, - &prog2_window_unifi_v1_v2, - &shared_window_unifi_v1_v2 - } -}; - -static const struct chip_device_desc_t unifi_device_desc_v3 = -{ - { FALSE, 0xf0ff, 0x3001, 0x02 }, /* UF2... R03 */ - "UF2...", - "UniFi-3", - counted(init_vals_v2), /* init */ - counted(reset_program_v1_or_v2), /* reset_prog */ - &unifi_device_regs_v2, /* regs */ - { - TRUE, /* has_flash */ - TRUE, /* has_ext_sram */ - FALSE, /* has_rom */ - FALSE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v1_v2), /* map */ - /* prog_offset */ - { - 0x00100000, /* ram */ - 0x00000000, /* rom (invalid) */ - 0x00000000, /* flash */ - 0x00200000, /* ext_ram */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &prog1_window_unifi_v1_v2, - &prog2_window_unifi_v1_v2, - &shared_window_unifi_v1_v2 - } -}; - -static const struct chip_device_desc_t unifi_device_desc_v22 = -{ - { FALSE, 0x00ff, 0x0022, 0x07 }, /* UF60xx */ - "UF60xx", - "UniFi-4", - counted(init_vals_v22_v23), /* init */ - null_counted(), /* reset_prog */ - &unifi_device_regs_v22_v23, /* regs */ - { - FALSE, /* has_flash */ - FALSE, /* has_ext_sram */ - TRUE, /* has_rom */ - FALSE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v22_v23), /* map */ - /* prog_offset */ - { - 0x00C00000, /* ram */ - 0x00000000, /* rom */ - 0x00000000, /* flash (invalid) */ - 0x00000000, /* ext_ram (invalid) */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &generic1_window_unifi_v22_v23, - &generic2_window_unifi_v22_v23, - &generic3_window_unifi_v22_v23 - } -}; - -static const struct chip_device_desc_t unifi_device_desc_v23 = -{ - { FALSE, 0x00ff, 0x0023, 0x08 }, /* UF.... */ - "UF....", - "UF.... (5)", - counted(init_vals_v22_v23), /* init */ - null_counted(), /* reset_prog */ - &unifi_device_regs_v22_v23, /* regs */ - { - FALSE, /* has_flash */ - FALSE, /* has_ext_sram */ - TRUE, /* has_rom */ - TRUE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v22_v23), - /* prog_offset */ - { - 0x00C00000, /* ram */ - 0x00000000, /* rom */ - 0x00000000, /* flash (invalid) */ - 0x00000000, /* ext_sram (invalid) */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &generic1_window_unifi_v22_v23, - &generic2_window_unifi_v22_v23, - &generic3_window_unifi_v22_v23 - } -}; - -static const struct chip_device_desc_t hyd_wlan_subsys_desc_v1 = -{ - { FALSE, 0x00ff, 0x0044, 0x00 }, /* UF.... */ - "HYD...", - "HYD... ", - counted(init_vals_v22_v23), /* init */ - null_counted(), /* reset_prog */ - &unifi_device_regs_v22_v23, /* regs */ - { - FALSE, /* has_flash */ - FALSE, /* has_ext_sram */ - TRUE, /* has_rom */ - FALSE, /* has_bt */ - TRUE, /* has_wlan */ - }, - counted(unifi_map_address_v22_v23), - /* prog_offset */ - { - 0x00C00000, /* ram */ - 0x00000000, /* rom */ - 0x00000000, /* flash (invalid) */ - 0x00000000, /* ext_sram (invalid) */ - }, - /* data_offset */ - { - 0x8000 /* ram */ - }, - /* windows */ - { - &generic1_window_unifi_v22_v23, - &generic2_window_unifi_v22_v23, - &generic3_window_unifi_v22_v23 - } -}; - - -/* This is the list of all chips that we know about. I'm - assuming that the order here will be important - we - might have multiple entries witrh the same SDIO id for - instance. The first one in this list will be the one - that is returned if a search is done on only that id. - The client will then have to call GetVersionXXX again - but with more detailed info. - - I don't know if we need to signal this up to the client - in some way? - - (We get the SDIO id before we know anything else about - the chip. We might not be able to read any of the other - registers at first, but we still need to know about the - chip). */ -static const struct chip_device_desc_t *chip_ver_to_desc[] = -{ - &unifi_device_desc_v1, /* UF105x R01 */ - &unifi_device_desc_v2, /* UF2... R02 */ - &unifi_device_desc_v3, /* UF2... R03 */ - &unifi_device_desc_v22, /* UF60xx */ - &unifi_device_desc_v23, /* UF.... */ - &hyd_wlan_subsys_desc_v1 -}; - -ChipDescript* ChipHelper_GetVersionSdio(u8 sdio_ver) -{ - u32 i; - - for (i = 0; i < nelem(chip_ver_to_desc); i++) - { - if (chip_ver_to_desc[i]->chip_version.sdio == sdio_ver) - { - return chip_ver_to_desc[i]; - } - } - - return &chip_device_desc_null; -} - - -ChipDescript* ChipHelper_GetVersionAny(u16 from_FF9A, u16 from_FE81) -{ - u32 i; - - if ((from_FF9A & 0xFF00) != 0) - { - for (i = 0; i < nelem(chip_ver_to_desc); i++) - { - if (chip_ver_to_desc[i]->chip_version.pre_bc7 && - ((from_FF9A & chip_ver_to_desc[i]->chip_version.mask) == - chip_ver_to_desc[i]->chip_version.result)) - { - return chip_ver_to_desc[i]; - } - } - } - else - { - for (i = 0; i < nelem(chip_ver_to_desc); i++) - { - if (!chip_ver_to_desc[i]->chip_version.pre_bc7 && - ((from_FE81 & chip_ver_to_desc[i]->chip_version.mask) == - chip_ver_to_desc[i]->chip_version.result)) - { - return chip_ver_to_desc[i]; - } - } - } - - return &chip_device_desc_null; -} - - -ChipDescript* ChipHelper_GetVersionUniFi(u16 ver) -{ - return ChipHelper_GetVersionAny(0x0000, ver); -} - - -ChipDescript *ChipHelper_Null(void) -{ - return &chip_device_desc_null; -} - - -ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age bc_age, u16 version) -{ - if (bc_age == chip_helper_bluecore_pre_bc7) - { - return ChipHelper_GetVersionAny(version, 0x0000); - } - else - { - return ChipHelper_GetVersionAny(0x0000, version); - } -} - - -/* Expand the DEF0 functions into simple code to return the - correct thing. The DEF1 functions expand to nothing in - this X macro expansion. */ -#define CHIP_HELPER_DEF0_C_DEF(ret_type, name, info) \ - ret_type ChipHelper_ ## name(ChipDescript * chip_help) \ - { \ - return chip_help->info; \ - } -#define CHIP_HELPER_DEF1_C_DEF(ret_type, name, type1, name1) - -CHIP_HELPER_LIST(C_DEF) - -/* - * Map register addresses between HOST and SPI access. - */ -u16 ChipHelper_MapAddress_SPI2HOST(ChipDescript *chip_help, u16 addr) -{ - u32 i; - for (i = 0; i < chip_help->map.len; i++) - { - if (chip_help->map.vals[i].spi == addr) - { - return chip_help->map.vals[i].host; - } - } - return addr; -} - - -u16 ChipHelper_MapAddress_HOST2SPI(ChipDescript *chip_help, u16 addr) -{ - u32 i; - for (i = 0; i < chip_help->map.len; i++) - { - if (chip_help->map.vals[i].host == addr) - { - return chip_help->map.vals[i].spi; - } - } - return addr; -} - - -/* The address returned by this function is the start of the - window in the address space, that is where we can start - accessing data from. If a section of the window at the - start is unusable because something else is cluttering up - the address map then that is taken into account and this - function returns that address justt past that. */ -u16 ChipHelper_WINDOW_ADDRESS(ChipDescript *chip_help, - enum chip_helper_window_index window) -{ - if (window < CHIP_HELPER_WINDOW_COUNT && - chip_help->windows[window] != NULL) - { - return chip_help->windows[window]->address + chip_help->windows[window]->blocked; - } - return 0; -} - - -/* This returns the size of the window minus any blocked section */ -u16 ChipHelper_WINDOW_SIZE(ChipDescript *chip_help, - enum chip_helper_window_index window) -{ - if (window < CHIP_HELPER_WINDOW_COUNT && - chip_help->windows[window] != NULL) - { - return chip_help->windows[window]->size - chip_help->windows[window]->blocked; - } - return 0; -} - - -/* Get the register writes we should do to make sure that - the chip is running with most clocks on. */ -u32 ChipHelper_ClockStartupSequence(ChipDescript *chip_help, - const struct chip_helper_init_values **val) -{ - *val = chip_help->init.vals; - return chip_help->init.len; -} - - -/* Get the set of values tat we should write to the chip to perform a reset. */ -u32 ChipHelper_HostResetSequence(ChipDescript *chip_help, - const struct chip_helper_reset_values **val) -{ - *val = chip_help->reset_prog.vals; - return chip_help->reset_prog.len; -} - - -/* Decode a windowed access to the chip. */ -s32 ChipHelper_DecodeWindow(ChipDescript *chip_help, - enum chip_helper_window_index window, - enum chip_helper_window_type type, - u32 offset, - u16 *page, u16 *addr, u32 *len) -{ - const struct window_info_t *win; - const struct window_shift_info_t *mode; - u16 of, pg; - - if (window >= CHIP_HELPER_WINDOW_COUNT) - { - return FALSE; - } - if ((win = chip_help->windows[window]) == NULL) - { - return FALSE; - } - if (type >= CHIP_HELPER_WT_COUNT) - { - return FALSE; - } - if ((mode = &win->mode[type]) == NULL) - { - return FALSE; - } - if (!mode->allowed) - { - return FALSE; - } - - pg = (u16)(offset >> mode->page_shift) + mode->page_offset; - of = (u16)(offset & ((1 << mode->page_shift) - 1)); - /* If 'blocked' is zero this does nothing, else decrease - the page register and increase the offset until we aren't - in the blocked region of the window. */ - while (of < win->blocked) - { - of += 1 << mode->page_shift; - pg--; - } - *page = pg; - *addr = win->address + of; - *len = win->size - of; - return TRUE; -} - - diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper.h b/drivers/staging/csr/csr_wifi_hip_chiphelper.h deleted file mode 100644 index 09b3aefcbced..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_chiphelper.h +++ /dev/null @@ -1,407 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_HIP_CHIPHELPER_H__ -#define CSR_WIFI_HIP_CHIPHELPER_H__ - - -#include - -/* The age of the BlueCore chip. This is probably not useful, if - you know the age then you can probably work out the version directly. */ -enum chip_helper_bluecore_age -{ - chip_helper_bluecore_pre_bc7, - chip_helper_bluecore_bc7_or_later -}; - -/* We support up to three windowed regions at the moment. - Don't reorder these - they're used to index into an array. */ -enum chip_helper_window_index -{ - CHIP_HELPER_WINDOW_1 = 0, - CHIP_HELPER_WINDOW_2 = 1, - CHIP_HELPER_WINDOW_3 = 2, - CHIP_HELPER_WINDOW_COUNT = 3 -}; - -/* These are the things that we can access through a window. - Don't reorder these - they're used to index into an array. */ -enum chip_helper_window_type -{ - CHIP_HELPER_WT_CODE_RAM = 0, - CHIP_HELPER_WT_FLASH = 1, - CHIP_HELPER_WT_EXT_SRAM = 2, - CHIP_HELPER_WT_ROM = 3, - CHIP_HELPER_WT_SHARED = 4, - CHIP_HELPER_WT_COUNT = 5 -}; - -/* Commands to stop and start the XAP */ -enum chip_helper_dbg_emu_cmd_enum -{ - CHIP_HELPER_DBG_EMU_CMD_XAP_STEP_MASK = 0x0001, - CHIP_HELPER_DBG_EMU_CMD_XAP_RUN_B_MASK = 0x0002, - CHIP_HELPER_DBG_EMU_CMD_XAP_BRK_MASK = 0x0004, - CHIP_HELPER_DBG_EMU_CMD_XAP_WAKEUP_MASK = 0x0008 -}; - -/* Bitmasks for Stop and sleep status: DBG_SPI_STOP_STATUS & DBG_HOST_STOP_STATUS */ -enum chip_helper_dbg_stop_status_enum -{ - CHIP_HELPER_DBG_STOP_STATUS_NONE_MASK = 0x0000, - CHIP_HELPER_DBG_STOP_STATUS_P0_MASK = 0x0001, - CHIP_HELPER_DBG_STOP_STATUS_P1_MASK = 0x0002, - CHIP_HELPER_DBG_STOP_STATUS_P2_MASK = 0x0004, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P0_MASK = 0x0008, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P1_MASK = 0x0010, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P2_MASK = 0x0020, - /* Legacy names/alias */ - CHIP_HELPER_DBG_STOP_STATUS_MAC_MASK = 0x0001, - CHIP_HELPER_DBG_STOP_STATUS_PHY_MASK = 0x0002, - CHIP_HELPER_DBG_STOP_STATUS_BT_MASK = 0x0004, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_MAC_MASK = 0x0008, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_PHY_MASK = 0x0010, - CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_BT_MASK = 0x0020 -}; - -/* Codes to disable the watchdog */ -enum chip_helper_watchdog_disable_enum -{ - CHIP_HELPER_WATCHDOG_DISABLE_CODE1 = 0x6734, - CHIP_HELPER_WATCHDOG_DISABLE_CODE2 = 0xD6BF, - CHIP_HELPER_WATCHDOG_DISABLE_CODE3 = 0xC31E -}; - -/* Other bits have changed between versions */ -enum chip_helper_gbl_misc_enum -{ - CHIP_HELPER_GBL_MISC_SPI_STOP_OUT_EN_MASK = 0x0001, - CHIP_HELPER_GBL_MISC_MMU_INIT_DONE_MASK = 0x0004 -}; - -/* Coex status register, contains interrupt status and reset pullup status. - * CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK can be used to check - * for WAPI on R03 chips and later. */ -enum chip_helper_coex_status_mask_enum -{ - CHIP_HELPER_COEX_STATUS_RST_PULLS_LSB_MASK = 0x0001, - CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK = 0x0008, - CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_LSB_MASK = 0x0010, - CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_MSB_MASK = 0x0080, - CHIP_HELPER_COEX_STATUS_INT_UART_MASK = 0x0100, - CHIP_HELPER_COEX_STATUS_INT_BT_LEG_MASK = 0x0200 -}; - -/* How to select the different CPUs */ -enum chip_helper_dbg_proc_sel_enum -{ - CHIP_HELPER_DBG_PROC_SEL_MAC = 0, - CHIP_HELPER_DBG_PROC_SEL_PHY = 1, - CHIP_HELPER_DBG_PROC_SEL_BT = 2, - CHIP_HELPER_DBG_PROC_SEL_NONE = 2, - CHIP_HELPER_DBG_PROC_SEL_BOTH = 3 -}; - -/* These are the only registers that we have to know the - address of before we know the chip version. */ -enum chip_helper_fixed_registers -{ - /* This is the address of GBL_CHIP_VERISON on BC7, - UF105x, UF60xx and - anything later than that. */ - CHIP_HELPER_UNIFI_GBL_CHIP_VERSION = 0xFE81, - - CHIP_HELPER_OLD_BLUECORE_GBL_CHIP_VERSION = 0xFF9A - - /* This isn't used at the moment (but might be needed - to distinguish the BlueCore sub version?) */ - /* CHIP_HELPER_OLD_BLUECORE_ANA_VERSION_ID = 0xFF7D */ -}; - -/* Address-value pairs for defining initialisation values */ -struct chip_helper_init_values -{ - u16 addr; - u16 value; -}; - -/* A block of data that should be written to the device */ -struct chip_helper_reset_values -{ - u32 gp_address; - u32 len; - const u16 *data; -}; - -/* - * This is the C API. - */ - -/* opaque type */ -typedef const struct chip_device_desc_t ChipDescript; - -/* Return a NULL descriptor */ -ChipDescript* ChipHelper_Null(void); - -/* This should get the correct version for any CSR chip. - The two parameters are what is read from addresses - 0xFF9A and 0xFE81 (OLD_BLUECORE_GBL_CHIP_VERSION and - UNIFI_GBL_CHIP_VERSION). These should give a unique identity - for most (all?) chips. - - FF9A is the old GBL_CHIP_VERSION register. If the high - eight bits are zero then the chip is a new (BC7 +) one - and FE81 is the _new_ GBL_CHIP_VERSION register. */ -ChipDescript* ChipHelper_GetVersionAny(u16 from_FF9A, u16 from_FE81); - -/* The chip is a UniFi, but we don't know which type - The parameter is the value of UNIFI_GBL_CHIP_VERSION (0xFE81) */ -ChipDescript* ChipHelper_GetVersionUniFi(u16 version); - -/* This gets the version from the SDIO device id. This only - gives quite a coarse grained version, so we should update once - we hav access to the function N registers. */ -ChipDescript* ChipHelper_GetVersionSdio(u8 sdio_version); - -/* The chip is some sort of BlueCore. If "age" is "pre_bc7" then - "version" is what was read from FF9A. If "age" is bc7_or_later - then "version" is read from FE81. If we don't know if we're pre - or post BC7 then we should use "GetVersionAny". */ -ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age age, - u16 version); - -/* The main functions of this class are built with an X macro. This - means we can generate the C and C++ versions from the same source - without the two diverging. - - The DEF0 functions are simple and take no parameters. The first - parameter to the macro is the return type. The second parameter - is the function name and the third parameter is where to get the - info from (this is hidden from the user). - - The DEF1 functions take one parameter. This time the third macro - parameter is the type of this parameter, and the fourth macro - parameter is the name of the parameter. The bodies of these - functions are hand written. */ -#define CHIP_HELPER_LIST(m) \ - CHIP_HELPER_DEF0(m, (const char *, FriendlyName, friendly_name)) \ - CHIP_HELPER_DEF0(m, (const char *, MarketingName, marketing_name)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_EMU_CMD, regs->dbg_emu_cmd)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_HOST_PROC_SELECT, regs->host.dbg_proc_select)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_HOST_STOP_STATUS, regs->host.dbg_stop_status)) \ - CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW1_PAGE, regs->host.window1_page)) \ - CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW2_PAGE, regs->host.window2_page)) \ - CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW3_PAGE, regs->host.window3_page)) \ - CHIP_HELPER_DEF0(m, (u16, HOST_IO_LOG_ADDR, regs->host.io_log_addr)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_SPI_PROC_SELECT, regs->spi.dbg_proc_select)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_SPI_STOP_STATUS, regs->spi.dbg_stop_status)) \ - CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW1_PAGE, regs->spi.window1_page)) \ - CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW2_PAGE, regs->spi.window2_page)) \ - CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW3_PAGE, regs->spi.window3_page)) \ - CHIP_HELPER_DEF0(m, (u16, SPI_IO_LOG_ADDR, regs->spi.io_log_addr)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_RESET, regs->dbg_reset)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_RESET_VALUE, regs->dbg_reset_value)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_RESET_WARN, regs->dbg_reset_warn)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_RESET_WARN_VALUE, regs->dbg_reset_warn_value)) \ - CHIP_HELPER_DEF0(m, (u16, DBG_RESET_RESULT, regs->dbg_reset_result)) \ - CHIP_HELPER_DEF0(m, (u16, WATCHDOG_DISABLE, regs->watchdog_disable)) \ - CHIP_HELPER_DEF0(m, (u16, PROC_PC_SNOOP, regs->proc_pc_snoop)) \ - CHIP_HELPER_DEF0(m, (u16, GBL_CHIP_VERSION, regs->gbl_chip_version)) \ - CHIP_HELPER_DEF0(m, (u16, GBL_MISC_ENABLES, regs->gbl_misc_enables)) \ - CHIP_HELPER_DEF0(m, (u16, XAP_PCH, regs->xap_pch)) \ - CHIP_HELPER_DEF0(m, (u16, XAP_PCL, regs->xap_pcl)) \ - CHIP_HELPER_DEF0(m, (u16, MAILBOX0, regs->mailbox0)) \ - CHIP_HELPER_DEF0(m, (u16, MAILBOX1, regs->mailbox1)) \ - CHIP_HELPER_DEF0(m, (u16, MAILBOX2, regs->mailbox2)) \ - CHIP_HELPER_DEF0(m, (u16, MAILBOX3, regs->mailbox3)) \ - CHIP_HELPER_DEF0(m, (u16, SDIO_HIP_HANDSHAKE, regs->sdio_hip_handshake)) \ - CHIP_HELPER_DEF0(m, (u16, SDIO_HOST_INT, regs->sdio_host_int)) \ - CHIP_HELPER_DEF0(m, (u16, COEX_STATUS, regs->coex_status)) \ - CHIP_HELPER_DEF0(m, (u16, SHARED_IO_INTERRUPT, regs->shared_io_interrupt)) \ - CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_RAM_OFFSET, prog_offset.ram)) \ - CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_ROM_OFFSET, prog_offset.rom)) \ - CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_FLASH_OFFSET, prog_offset.flash)) \ - CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_EXT_SRAM_OFFSET, prog_offset.ext_sram)) \ - CHIP_HELPER_DEF0(m, (u16, DATA_MEMORY_RAM_OFFSET, data_offset.ram)) \ - CHIP_HELPER_DEF0(m, (s32, HasFlash, bools.has_flash)) \ - CHIP_HELPER_DEF0(m, (s32, HasExtSram, bools.has_ext_sram)) \ - CHIP_HELPER_DEF0(m, (s32, HasRom, bools.has_rom)) \ - CHIP_HELPER_DEF0(m, (s32, HasBt, bools.has_bt)) \ - CHIP_HELPER_DEF0(m, (s32, HasWLan, bools.has_wlan)) \ - CHIP_HELPER_DEF1(m, (u16, WINDOW_ADDRESS, enum chip_helper_window_index, window)) \ - CHIP_HELPER_DEF1(m, (u16, WINDOW_SIZE, enum chip_helper_window_index, window)) \ - CHIP_HELPER_DEF1(m, (u16, MapAddress_SPI2HOST, u16, addr)) \ - CHIP_HELPER_DEF1(m, (u16, MapAddress_HOST2SPI, u16, addr)) \ - CHIP_HELPER_DEF1(m, (u32, ClockStartupSequence, const struct chip_helper_init_values **, val)) \ - CHIP_HELPER_DEF1(m, (u32, HostResetSequence, const struct chip_helper_reset_values **, val)) - -/* Some magic to help the expansion */ -#define CHIP_HELPER_DEF0(a, b) \ - CHIP_HELPER_DEF0_ ## a b -#define CHIP_HELPER_DEF1(a, b) \ - CHIP_HELPER_DEF1_ ## a b - -/* Macros so that when we expand the list we get "C" function prototypes. */ -#define CHIP_HELPER_DEF0_C_DEC(ret_type, name, info) \ - ret_type ChipHelper_ ## name(ChipDescript * chip_help); -#define CHIP_HELPER_DEF1_C_DEC(ret_type, name, type1, name1) \ - ret_type ChipHelper_ ## name(ChipDescript * chip_help, type1 name1); - -CHIP_HELPER_LIST(C_DEC) - -/* FriendlyName - MarketingName - - These two functions return human readable strings that describe - the chip. FriendlyName returns something that a software engineer - at CSR might understand. MarketingName returns something more like - an external name for a CSR chip. -*/ -/* DBG_EMU_CMD - WATCHDOG_DISABLE - PROC_PC_SNOOP - GBL_CHIP_VERSION - XAP_PCH - XAP_PCL - - These registers are used to control the XAPs. -*/ -/* DBG_HOST_PROC_SELECT DBG_HOST_STOP_STATUS - HOST_WINDOW1_PAGE HOST_WINDOW2_PAGE HOST_WINDOW3_PAGE - HOST_IO_LOG_ADDR - DBG_SPI_PROC_SELECT DBG_SPI_STOP_STATUS - SPI_WINDOW1_PAGE SPI_WINDOW2_PAGE SPI_WINDOW3_PAGE - SPI_IO_LOG_ADDR - - These register are used to control the XAPs and the memory - windows, normally while debugging the code on chip. There - are two versons of these registers, one for access via SPI - and another for access via the host interface. -*/ -/* DBG_RESET - DBG_RESET_VALUE - DBG_RESET_WARN - DBG_RESET_WARN_VALUE - DBG_RESET_RESULT - - These registers are used to reset the XAP. This can be - quite complex for some chips. If DBG_RESET_WARN is non - zero the DBG_RESET_WARN_VALUE should be written to address - DBG_RESET_WARN before the reset is perfeormed. DBG_RESET_VALUE - should then be written to DBG_RESET to make the reset happen. - The DBG_RESET_RESULT register should contain 0 if the reset - was successful. -*/ -/* GBL_MISC_ENABLES - - This register controls some special chip features. It - should be used with care is it changes quite a lot between - chip versions. -*/ -/* MAILBOX0 - MAILBOX1 - MAILBOX2 - MAILBOX3 - - The mailbox registers are for communication between the host - and the firmware. There use is described in part by the host - interface protcol specifcation. -*/ -/* SDIO_HIP_HANDSHAKE - - This is one of the more important SDIO HIP registers. On some - chips it has the same value as one of the mailbox registers - and on other chips it is different. -*/ -/* SDIO_HOST_INT - SHARED_IO_INTERRUPT - - These registers are used by some versions of the host interface - protocol specification. Their names should probably be changed - to hide the registers and to expose the functions more. -*/ -/* COEX_STATUS - - Coex status register, contains interrupt status and reset - pullup status. The latter is used to detect WAPI. -*/ -/* PROGRAM_MEMORY_RAM_OFFSET - PROGRAM_MEMORY_ROM_OFFSET - PROGRAM_MEMORY_FLASH_OFFSET - PROGRAM_MEMORY_EXT_SRAM_OFFSET - DATA_MEMORY_RAM_OFFSET - - These are constants that describe the offset of the different - memory types in the two different address spaces. -*/ -/* HasFlash HasExtSram HasRom - HasBt HasWLan - - These are a set of bools describing the chip. -*/ -/* WINDOW_ADDRESS WINDOW_SIZE - - These two functions return the size and address of the windows. - The address is the address of the lowest value in the address - map that is part of the window and the size is the number of - visible words. - - Some of the windows have their lowest portion covered by - registers. For these windows address is the first address - after the registers and size is the siave excluding the part - covered by registers. -*/ -/* MapAddress_SPI2HOST - MapAddress_HOST2SPI - - The debugging interface is duplicated on UniFi and later chips - so that there are two versions - one over the SPI interaface and - the other over the SDIO interface. These functions map the - registers between these two interfaces. -*/ -/* ClockStartupSequence - - This function returns the list of register value pairs that - should be forced into UniFi to enable SPI communication. This - set of registers is not needed if the firmware is running, but - will be needed if the device is being booted from cold. These - register writes enable the clocks and setup the PLL to a basic - working state. SPI access might be unreliable until these writes - have occurred (And they may take mulitple goes). -*/ -/* HostResetSequence - - This returns a number of chunks of data and generic pointers. - All of the XAPs should be stopped. The data should be written - to the generic pointers. The instruction pointer for the MAC - should then be set to the start of program memory and then the - MAC should be "go"d. This will reset the chip in a reliable - and orderly manner without resetting the SDIO interface. It - is therefore not needed if the chip is being accessed by the - SPI interface (the DBG_RESET_ mechanism can be used instead). -*/ - -/* The Decode Window function is more complex. For the window - 'window' it tries to return the address and page register - value needed to see offset 'offset' of memory type 'type'. - - It return 1 on success and 0 on failure. 'page' is what - should be written to the page register. 'addr' is the - address in the XAPs 16 address map to read from. 'len' - is the length that we can read without having to change - the page registers. */ -s32 ChipHelper_DecodeWindow(ChipDescript *chip_help, - enum chip_helper_window_index window, - enum chip_helper_window_type type, - u32 offset, - u16 *page, u16 *addr, u32 *len); - -#endif diff --git a/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h b/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h deleted file mode 100644 index e5e579912550..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_chiphelper_private.h +++ /dev/null @@ -1,200 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ -#define CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ - - -#include "csr_wifi_hip_chiphelper.h" - -/* This GP stuff should be somewhere else? */ - -/* Memory spaces encoded in top byte of Generic Pointer type */ -#define UNIFI_SH_DMEM 0x01 /* Shared Data Memory */ -#define UNIFI_EXT_FLASH 0x02 /* External FLASH */ -#define UNIFI_EXT_SRAM 0x03 /* External SRAM */ -#define UNIFI_REGISTERS 0x04 /* Registers */ -#define UNIFI_PHY_DMEM 0x10 /* PHY Data Memory */ -#define UNIFI_PHY_PMEM 0x11 /* PHY Program Memory */ -#define UNIFI_PHY_ROM 0x12 /* PHY ROM */ -#define UNIFI_MAC_DMEM 0x20 /* MAC Data Memory */ -#define UNIFI_MAC_PMEM 0x21 /* MAC Program Memory */ -#define UNIFI_MAC_ROM 0x22 /* MAC ROM */ -#define UNIFI_BT_DMEM 0x30 /* BT Data Memory */ -#define UNIFI_BT_PMEM 0x31 /* BT Program Memory */ -#define UNIFI_BT_ROM 0x32 /* BT ROM */ - -#define MAKE_GP(R, O) (((UNIFI_ ## R) << 24) | (O)) -#define GP_OFFSET(GP) ((GP) & 0xFFFFFF) -#define GP_SPACE(GP) (((GP) >> 24) & 0xFF) - - -/* Address value pairs */ -struct val_array_t -{ - u32 len; - const struct chip_helper_init_values *vals; -}; - -/* Just a (counted) u16 array */ -struct data_array_t -{ - u32 len; - const u16 *vals; -}; - -struct reset_prog_t -{ - u32 len; - const struct chip_helper_reset_values *vals; -}; - -/* The addresses of registers that are equivalent but on - different host transports. */ -struct chip_map_address_t -{ - u16 spi, host; -}; - -struct map_array_t -{ - u32 len; - const struct chip_map_address_t *vals; -}; - -struct chip_device_regs_per_transport_t -{ - u16 dbg_proc_select; - u16 dbg_stop_status; - u16 window1_page; /* PROG_PMEM1 or GW1 */ - u16 window2_page; /* PROG_PMEM2 or GW2 */ - u16 window3_page; /* SHARED or GW3 */ - u16 io_log_addr; -}; - -struct chip_device_regs_t -{ - u16 gbl_chip_version; - u16 gbl_misc_enables; - u16 dbg_emu_cmd; - struct chip_device_regs_per_transport_t host; - struct chip_device_regs_per_transport_t spi; - u16 dbg_reset; - u16 dbg_reset_value; - u16 dbg_reset_warn; - u16 dbg_reset_warn_value; - u16 dbg_reset_result; - u16 xap_pch; - u16 xap_pcl; - u16 proc_pc_snoop; - u16 watchdog_disable; - u16 mailbox0; - u16 mailbox1; - u16 mailbox2; - u16 mailbox3; - u16 sdio_host_int; - u16 shared_io_interrupt; - u16 sdio_hip_handshake; - u16 coex_status; /* Allows WAPI detection */ -}; - -/* If allowed is false then this window does not provide this - type of access. - This describes how addresses should be shifted to make the - "page" address. The address is shifted left by 'page_shift' - and then has 'page_offset' added. This value should then be - written to the page register. */ -struct window_shift_info_t -{ - s32 allowed; - u32 page_shift; - u16 page_offset; -}; - -/* Each window has an address and size. These are obvious. It then - has a description for each type of memory that might be accessed - through it. There might also be a start to the offset of the window. - This means that that number of addresses at the start of the window - are unusable. */ -struct window_info_t -{ - u16 address; - u16 size; - u16 blocked; - const struct window_shift_info_t *mode; -}; - -/* If GBL_CHIP_VERSION and'ed with 'mask' and is equal to 'result' - then this is the correct set of info. If pre_bc7 is true then the - address of GBL_CHIP_VERSION is FF9A, else its FE81. */ -struct chip_version_t -{ - s32 pre_bc7; - u16 mask; - u16 result; - u8 sdio; -}; - -struct chip_device_desc_t -{ - struct chip_version_t chip_version; - - /* This is a text string that a human might find useful (BC02, UF105x) */ - const char *friendly_name; - /* This is what we show to customers */ - const char *marketing_name; - - /* Initialisation values to write following a reset */ - struct val_array_t init; - - /* Binary sequence for hard reset */ - struct reset_prog_t reset_prog; - - /* The register map */ - const struct chip_device_regs_t *regs; - - /* Some misc. info on the chip */ - struct - { - u32 has_flash : 1; - u32 has_ext_sram : 1; - u32 has_rom : 1; - u32 has_bt : 1; - u32 has_wlan : 1; - } bools; - - /* This table is used to remap register addresses depending on what - host interface is used. On the BC7 and later chips there are - multiple sets of memory window registers, on for each host - interafce (SDIO / SPI). The correct one is needed. */ - struct map_array_t map; - - /* The offsets into the program address space of the different types of memory. - The RAM offset is probably the most useful. */ - struct - { - u32 ram; - u32 rom; - u32 flash; - u32 ext_sram; - } prog_offset; - - /* The offsets into the data address space of interesting things. */ - struct - { - u16 ram; - /* maybe add shared / page tables? */ - } data_offset; - - /* Information on the different windows */ - const struct window_info_t *windows[CHIP_HELPER_WINDOW_COUNT]; -}; - -#endif /* CSR_WIFI_HIP_CHIPHELPER_PRIVATE_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_conversions.h b/drivers/staging/csr/csr_wifi_hip_conversions.h deleted file mode 100644 index bf7a52e82995..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_conversions.h +++ /dev/null @@ -1,73 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * - * FILE: csr_wifi_hip_conversions.h - * - * PURPOSE: - * This header file provides the macros for converting to and from - * wire format. - * These macros *MUST* work for little-endian AND big-endian hosts. - * - * --------------------------------------------------------------------------- - */ -#ifndef __CSR_WIFI_HIP_CONVERSIONS_H__ -#define __CSR_WIFI_HIP_CONVERSIONS_H__ - -#define SIZEOF_UINT16 2 -#define SIZEOF_UINT32 4 -#define SIZEOF_UINT64 8 - -#define SIZEOF_SIGNAL_HEADER 6 -#define SIZEOF_DATAREF 4 - - -/* - * Macro to retrieve the signal ID from a wire-format signal. - */ -#define GET_SIGNAL_ID(_buf) CSR_GET_UINT16_FROM_LITTLE_ENDIAN((_buf)) - -/* - * Macros to retrieve and set the DATAREF fields in a packed (i.e. wire-format) - * HIP signal. - */ -#define GET_PACKED_DATAREF_SLOT(_buf, _ref) \ - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 0)) - -#define GET_PACKED_DATAREF_LEN(_buf, _ref) \ - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 2)) - -#define SET_PACKED_DATAREF_SLOT(_buf, _ref, _slot) \ - CSR_COPY_UINT16_TO_LITTLE_ENDIAN((_slot), ((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 0)) - -#define SET_PACKED_DATAREF_LEN(_buf, _ref, _len) \ - CSR_COPY_UINT16_TO_LITTLE_ENDIAN((_len), ((_buf) + SIZEOF_SIGNAL_HEADER + ((_ref) * SIZEOF_DATAREF) + 2)) - -#define GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(_buf) \ - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 8)) - -#define GET_PACKED_MA_PACKET_REQUEST_HOST_TAG(_buf) \ - CSR_GET_UINT32_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 4)) - -#define GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(_buf) \ - CSR_GET_UINT32_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 8)) - -#define GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(_buf) \ - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(((_buf) + SIZEOF_SIGNAL_HEADER + UNIFI_MAX_DATA_REFERENCES * SIZEOF_DATAREF + 2)) - - -s32 get_packed_struct_size(const u8 *buf); -CsrResult read_unpack_signal(const u8 *ptr, CSR_SIGNAL *sig); -CsrResult write_pack(const CSR_SIGNAL *sig, u8 *ptr, u16 *sig_len); - -#endif /* __CSR_WIFI_HIP_CONVERSIONS_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_hip_download.c b/drivers/staging/csr/csr_wifi_hip_download.c deleted file mode 100644 index 2f44a383d2cf..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_download.c +++ /dev/null @@ -1,819 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_download.c - * - * PURPOSE: - * Routines for downloading firmware to UniFi. - * - * --------------------------------------------------------------------------- - */ -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifiversion.h" -#include "csr_wifi_hip_card.h" -#include "csr_wifi_hip_xbv.h" - -#undef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH - -static CsrResult do_patch_download(card_t *card, void *dlpriv, - xbv1_t *pfwinfo, u32 boot_ctrl_addr); - -static CsrResult do_patch_convert_download(card_t *card, - void *dlpriv, xbv1_t *pfwinfo); - -/* - * --------------------------------------------------------------------------- - * _find_in_slut - * - * Find the offset of the appropriate object in the SLUT of a card - * - * Arguments: - * card Pointer to card struct - * psym Pointer to symbol object. - * id set up by caller - * obj will be set up by this function - * pslut Pointer to SLUT address, if 0xffffffff then it must be - * read from the chip. - * Returns: - * CSR_RESULT_SUCCESS on success - * Non-zero on error, - * CSR_WIFI_HIP_RESULT_NOT_FOUND if not found - * --------------------------------------------------------------------------- - */ -static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut) -{ - u32 slut_address; - u16 finger_print; - CsrResult r; - CsrResult csrResult; - - /* Get SLUT address */ - if (*pslut == 0xffffffff) - { - r = card_wait_for_firmware_to_start(card, &slut_address); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Firmware hasn't started\n"); - return r; - } - *pslut = slut_address; - - /* - * Firmware has started so set the SDIO bus clock to the initial speed, - * faster than UNIFI_SDIO_CLOCK_SAFE_HZ, to speed up the f/w download. - */ - csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ); - if (csrResult != CSR_RESULT_SUCCESS) - { - r = ConvertCsrSdioToCsrHipResult(card, csrResult); - return r; - } - card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ; - } - else - { - slut_address = *pslut; /* Use previously discovered address */ - } - unifi_trace(card->ospriv, UDBG4, "SLUT addr: 0x%lX\n", slut_address); - - /* - * Check the SLUT fingerprint. - * The slut_address is a generic pointer so we must use unifi_card_read16(). - */ - unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n"); - finger_print = 0; - r = unifi_card_read16(card, slut_address, &finger_print); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read SLUT finger print\n"); - return r; - } - - if (finger_print != SLUT_FINGERPRINT) - { - unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n"); - return CSR_RESULT_FAILURE; - } - - /* Symbol table starts imedately after the fingerprint */ - slut_address += 2; - - while (1) - { - u16 id; - u32 obj; - - r = unifi_card_read16(card, slut_address, &id); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - slut_address += 2; - - if (id == CSR_SLT_END) - { - /* End of table reached: not found */ - r = CSR_WIFI_HIP_RESULT_RANGE; - break; - } - - r = unifi_read32(card, slut_address, &obj); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - slut_address += 4; - - unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", id, obj); - - r = CSR_WIFI_HIP_RESULT_NOT_FOUND; - /* Found search term? */ - if (id == psym->id) - { - unifi_trace(card->ospriv, UDBG1, " matched SLUT id %02d.%08lx\n", id, obj); - psym->obj = obj; - r = CSR_RESULT_SUCCESS; - break; - } - } - - return r; -} - - -/* - * --------------------------------------------------------------------------- - * do_patch_convert_download - * - * Download the given firmware image to the UniFi, converting from FWDL - * to PTDL XBV format. - * - * Arguments: - * card Pointer to card struct - * dlpriv Pointer to source firmware image - * fwinfo Pointer to source firmware info struct - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on error - * - * Notes: - * --------------------------------------------------------------------------- - */ -static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo) -{ - CsrResult r; - u32 slut_base = 0xffffffff; - void *pfw; - u32 psize; - symbol_t sym; - - /* Reset the chip to guarantee that the ROM loader is running */ - r = unifi_init(card); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, - "do_patch_convert_download: failed to re-init UniFi\n"); - return r; - } - - /* If no unifi_helper is running, the firmware version must be read */ - if (card->build_id == 0) - { - u32 ver = 0; - sym.id = CSR_SLT_BUILD_ID_NUMBER; - sym.obj = 0; /* To be updated by _find_in_slut() */ - - unifi_trace(card->ospriv, UDBG1, "Need f/w version\n"); - - /* Find chip build id entry in SLUT */ - r = _find_in_slut(card, &sym, &slut_base); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to find CSR_SLT_BUILD_ID_NUMBER\n"); - return CSR_RESULT_FAILURE; - } - - /* Read running f/w version */ - r = unifi_read32(card, sym.obj, &ver); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read f/w id\n"); - return CSR_RESULT_FAILURE; - } - card->build_id = ver; - } - - /* Convert the ptest firmware to a patch against the running firmware */ - pfw = xbv_to_patch(card, unifi_fw_read, dlpriv, pfwinfo, &psize); - if (!pfw) - { - unifi_error(card->ospriv, "Failed to convert f/w to patch"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - else - { - void *desc; - sym.id = CSR_SLT_BOOT_LOADER_CONTROL; - sym.obj = 0; /* To be updated by _find_in_slut() */ - - /* Find boot loader control entry in SLUT */ - r = _find_in_slut(card, &sym, &slut_base); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n"); - kfree(pfw); - return CSR_RESULT_FAILURE; - } - - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to wake UniFi\n"); - } - - /* Get a dlpriv for the patch buffer so that unifi_fw_read() can - * access it. - */ - desc = unifi_fw_open_buffer(card->ospriv, pfw, psize); - if (!desc) - { - kfree(pfw); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* Download the patch */ - unifi_info(card->ospriv, "Downloading converted f/w as patch\n"); - r = unifi_dl_patch(card, desc, sym.obj); - kfree(pfw); - unifi_fw_close_buffer(card->ospriv, desc); - - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Converted patch download failed\n"); - return r; - } - else - { - unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n"); - } - - /* This command starts the firmware */ - r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write loader restart cmd\n"); - } - - return r; - } -} - - -/* - * --------------------------------------------------------------------------- - * unifi_dl_firmware - * - * Download the given firmware image to the UniFi. - * - * Arguments: - * card Pointer to card struct - * dlpriv A context pointer from the calling function to be - * passed when calling unifi_fw_read(). - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed - * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file - * CSR_RESULT_FAILURE SDIO error - * - * Notes: - * Stops and resets the chip, does the download and runs the new - * firmware. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_dl_firmware(card_t *card, void *dlpriv) -{ - xbv1_t *fwinfo; - CsrResult r; - - fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL); - if (fwinfo == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for firmware\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* - * Scan the firmware file to find the TLVs we are interested in. - * These are: - * - check we support the file format version in VERF - * - SLTP Symbol Lookup Table Pointer - * - FWDL firmware download segments - * - FWOV firmware overlay segment - * - VMEQ Register probe tests to verify matching h/w - */ - r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo); - if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware) - { - unifi_error(card->ospriv, "File type is %s, expected firmware.\n", - fwinfo->mode == xbv_patch?"patch" : "unknown"); - kfree(fwinfo); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* UF6xxx doesn't accept firmware, only patches. Therefore we convert - * the file to patch format with version numbers matching the current - * running firmware, and then download via the patch mechanism. - * The sole purpose of this is to support production test firmware across - * different ROM releases, the test firmware being provided in non-patch - * format. - */ - if (card->chip_id > SDIO_CARD_ID_UNIFI_2) - { - unifi_info(card->ospriv, "Must convert f/w to patch format\n"); - r = do_patch_convert_download(card, dlpriv, fwinfo); - } - else - { - /* Older UniFi chips allowed firmware to be directly loaded onto the - * chip, which is no longer supported. - */ - unifi_error(card->ospriv, "Only patch downloading supported\n"); - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - kfree(fwinfo); - return r; -} /* unifi_dl_firmware() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_dl_patch - * - * Load the given patch set into UniFi. - * - * Arguments: - * card Pointer to card struct - * dlpriv The os specific handle to the firmware file. - * boot_ctrl The address of the boot loader control structure. - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed - * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file - * CSR_RESULT_FAILURE SDIO error - * - * Notes: - * This ends up telling UniFi to restart. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl) -{ - xbv1_t *fwinfo; - CsrResult r; - - unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl); - - fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL); - if (fwinfo == NULL) - { - unifi_error(card->ospriv, "Failed to allocate memory for patches\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - /* - * Scan the firmware file to find the TLVs we are interested in. - * These are: - * - check we support the file format version in VERF - * - FWID The build ID of the ROM that we can patch - * - PTDL patch download segments - */ - r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo); - if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch) - { - kfree(fwinfo); - unifi_error(card->ospriv, "Failed to read in patch file\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* - * We have to check the build id read from the SLUT against that - * for the patch file. They have to match exactly. - * "card->build_id" == XBV1.PTCH.FWID - */ - if (card->build_id != fwinfo->build_id) - { - unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n", - card->build_id, fwinfo->build_id); - kfree(fwinfo); -#ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; -#else - fwinfo = NULL; - dlpriv = NULL; - return CSR_RESULT_SUCCESS; -#endif - } - - r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to patch image\n"); - } - - kfree(fwinfo); - - return r; -} /* unifi_dl_patch() */ - - -void* unifi_dl_fw_read_start(card_t *card, s8 is_fw) -{ - card_info_t card_info; - - unifi_card_info(card, &card_info); - unifi_trace(card->ospriv, UDBG5, - "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n", - card_info.chip_id, card_info.chip_version, - card_info.fw_build, card_info.fw_hip_version, - card_info.sdio_block_size); - - return unifi_fw_read_start(card->ospriv, is_fw, &card_info); -} - - -/* - * --------------------------------------------------------------------------- - * safe_read_shared_location - * - * Read a shared memory location repeatedly until we get two readings - * the same. - * - * Arguments: - * card Pointer to card context struct. - * unifi_addr UniFi shared-data-memory address to access. - * pdata Pointer to a byte variable for the value read. - * - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure - * --------------------------------------------------------------------------- - */ -static CsrResult safe_read_shared_location(card_t *card, u32 address, u8 *pdata) -{ - CsrResult r; - u16 limit = 1000; - u8 b, b2; - - *pdata = 0; - - r = unifi_read_8_or_16(card, address, &b); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - while (limit--) - { - r = unifi_read_8_or_16(card, address, &b2); - if (r != CSR_RESULT_SUCCESS) - { - return r; - } - - /* When we have a stable value, return it */ - if (b == b2) - { - *pdata = b; - return CSR_RESULT_SUCCESS; - } - - b = b2; - } - - return CSR_RESULT_FAILURE; -} /* safe_read_shared_location() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_do_loader_op - * - * Send a loader / boot_loader command to the UniFi and wait for - * it to complete. - * - * Arguments: - * card Pointer to card context struct. - * op_addr The address of the loader operation control word. - * opcode The operation to perform. - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CSR_RESULT_FAILURE SDIO error or SDIO/XAP timeout - * --------------------------------------------------------------------------- - */ - -/* - * Ideally instead of sleeping, we want to busy wait. - * Currently there is no framework API to do this. When it becomes available, - * we can use it to busy wait using usecs - */ -#define OPERATION_TIMEOUT_LOOPS (100) /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */ -#define OPERATION_TIMEOUT_DELAY 1 /* msec, or 200usecs */ - -CsrResult unifi_do_loader_op(card_t *card, u32 op_addr, u8 opcode) -{ - CsrResult r; - s16 op_retries; - - unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr); - - /* Set the Operation command byte to the opcode */ - r = unifi_write_8_or_16(card, op_addr, opcode); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to write loader copy command\n"); - return r; - } - - /* Wait for Operation command byte to be Idle */ - /* Typically takes ~100us */ - op_retries = 0; - r = CSR_RESULT_SUCCESS; - while (1) - { - u8 op; - - /* - * Read the memory location until two successive reads give - * the same value. - * Then handle it. - */ - r = safe_read_shared_location(card, op_addr, &op); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to read loader status\n"); - break; - } - - if (op == UNIFI_LOADER_IDLE) - { - /* Success */ - break; - } - - if (op != opcode) - { - unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op); - r = CSR_RESULT_FAILURE; - break; - } - - /* Allow 500us timeout */ - if (++op_retries >= OPERATION_TIMEOUT_LOOPS) - { - unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n"); - /* Stop XAPs to aid post-mortem */ - r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to stop UniFi processors\n"); - } - else - { - r = CSR_RESULT_FAILURE; - } - break; - } - CsrThreadSleep(OPERATION_TIMEOUT_DELAY); - } /* Loop exits with r != CSR_RESULT_SUCCESS on error */ - - return r; -} /* unifi_do_loader_op() */ - - -/* - * --------------------------------------------------------------------------- - * send_ptdl_to_unifi - * - * Copy a patch block from userland to the UniFi. - * This function reads data, 2K at a time, from userland and writes - * it to the UniFi. - * - * Arguments: - * card A pointer to the card structure - * dlpriv The os specific handle for the firmware file - * ptdl A pointer ot the PTDL block - * handle The buffer handle to use for the xfer - * op_addr The address of the loader operation control word - * - * Returns: - * Number of bytes sent (Positive) or negative value indicating - * error code: - * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed - * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file - * CSR_RESULT_FAILURE SDIO error - * --------------------------------------------------------------------------- - */ -static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv, - const struct PTDL *ptdl, u32 handle, - u32 op_addr) -{ - u32 offset; - u8 *buf; - s32 data_len; - u32 write_len; - CsrResult r; - const u16 buf_size = 2 * 1024; - - offset = ptdl->dl_offset; - data_len = ptdl->dl_size; - - if (data_len > buf_size) - { - unifi_error(card->ospriv, "PTDL block is too large (%u)\n", - ptdl->dl_size); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - buf = kmalloc(buf_size, GFP_KERNEL); - if (buf == NULL) - { - unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n"); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; - } - - r = CSR_RESULT_SUCCESS; - - if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len) - { - unifi_error(card->ospriv, "Failed to read from file\n"); - } - else - { - /* We can always round these if the host wants to */ - if (card->sdio_io_block_pad) - { - write_len = (data_len + (card->sdio_io_block_size - 1)) & - ~(card->sdio_io_block_size - 1); - - /* Zero out the rest of the buffer (This isn't needed, but it - * makes debugging things later much easier). */ - memset(buf + data_len, 0, write_len - data_len); - } - else - { - write_len = data_len; - } - - r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n", - data_len, handle); - } - else - { - /* - * Can change the order of things to overlap read from file - * with copy to unifi - */ - r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH); - } - } - - kfree(buf); - - if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n", - ptdl->dl_size); - } - - return r; -} /* send_ptdl_to_unifi() */ - - -/* - * --------------------------------------------------------------------------- - * do_patch_download - * - * This function downloads a set of patches to UniFi and then - * causes it to restart. - * - * Arguments: - * card Pointer to card struct. - * dlpriv A context pointer from the calling function to be - * used when reading the XBV file. This can be NULL - * in which case not patches are applied. - * pfwinfo Pointer to a fwinfo struct describing the f/w - * XBV file. - * boot_ctrl_addr The address of the boot loader control structure. - * - * Returns: - * 0 on success, or an error code - * CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number - * --------------------------------------------------------------------------- - */ -static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, u32 boot_ctrl_addr) -{ - CsrResult r; - s32 i; - u16 loader_version; - u16 handle; - u32 total_bytes; - - /* - * Read info from the SDIO Loader Control Data Structure - */ - /* Check the loader version */ - r = unifi_card_read16(card, boot_ctrl_addr, &loader_version); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Patch download: Failed to read loader version\n"); - return r; - } - unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version); - switch (loader_version) - { - case 0x0000: - break; - - default: - unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n", - loader_version); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* Retrieve the handle to use with CMD53 */ - r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n"); - return r; - } - - /* Set the mask of LEDs to flash */ - if (card->loader_led_mask) - { - r = unifi_card_write16(card, boot_ctrl_addr + 2, - (u16)card->loader_led_mask); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n"); - return r; - } - } - - total_bytes = 0; - - /* Copy download data to UniFi memory */ - for (i = 0; i < pfwinfo->num_ptdl; i++) - { - unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n", - i, - pfwinfo->ptdl[i].dl_size, - pfwinfo->ptdl[i].dl_offset); - - r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i], - handle, boot_ctrl_addr + 6); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - return r; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Patch failed after %u bytes\n", - total_bytes); - return r; - } - total_bytes += pfwinfo->ptdl[i].dl_size; - } - - return CSR_RESULT_SUCCESS; -} /* do_patch_download() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_dump.c b/drivers/staging/csr/csr_wifi_hip_dump.c deleted file mode 100644 index 7b7eec49d028..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_dump.c +++ /dev/null @@ -1,837 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_dump.c - * - * PURPOSE: - * Routines for retrieving and buffering core status from the UniFi - * - * --------------------------------------------------------------------------- - */ -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifiversion.h" -#include "csr_wifi_hip_card.h" - -/* Locations to capture in dump (XAP words) */ -#define HIP_CDUMP_FIRST_CPUREG (0xFFE0) /* First CPU register */ -#define HIP_CDUMP_FIRST_LO (0) /* Start of low address range */ -#define HIP_CDUMP_FIRST_HI_MAC (0x3C00) /* Start of MAC high area */ -#define HIP_CDUMP_FIRST_HI_PHY (0x1C00) /* Start of PHY high area */ -#define HIP_CDUMP_FIRST_SH (0) /* Start of shared memory area */ - -#define HIP_CDUMP_NCPUREGS (10) /* No. of 16-bit XAP registers */ -#define HIP_CDUMP_NWORDS_LO (0x0100) /* Low area size in 16-bit words */ -#define HIP_CDUMP_NWORDS_HI (0x0400) /* High area size in 16-bit words */ -#define HIP_CDUMP_NWORDS_SH (0x0500) /* Shared memory area size, 16-bit words */ - -#define HIP_CDUMP_NUM_ZONES 7 /* Number of UniFi memory areas to capture */ - -/* Mini-coredump state */ -typedef struct coredump_buf -{ - u16 count; /* serial number of dump */ - u32 timestamp; /* host's system time at capture */ - s16 requestor; /* request: 0=auto dump, 1=manual */ - u16 chip_ver; - u32 fw_ver; - u16 *zone[HIP_CDUMP_NUM_ZONES]; - - struct coredump_buf *next; /* circular list */ - struct coredump_buf *prev; /* circular list */ -} coredump_buffer; - -/* Structure used to describe a zone of chip memory captured by mini-coredump */ -struct coredump_zone -{ - unifi_coredump_space_t space; /* XAP memory space this zone covers */ - enum unifi_dbg_processors_select cpu; /* XAP CPU core selector */ - u32 gp; /* Generic Pointer to memory zone on XAP */ - u16 offset; /* 16-bit XAP word offset of zone in memory space */ - u16 length; /* Length of zone in XAP words */ -}; - -static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_buf); -static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_buf); -static CsrResult unifi_coredump_read_zone(card_t *card, u16 *zone, - const struct coredump_zone *def); -static s32 get_value_from_coredump(const coredump_buffer *dump, - const unifi_coredump_space_t space, const u16 offset); - -/* Table of chip memory zones we capture on mini-coredump */ -static const struct coredump_zone zonedef_table[HIP_CDUMP_NUM_ZONES] = { - { UNIFI_COREDUMP_MAC_REG, UNIFI_PROC_MAC, UNIFI_MAKE_GP(REGISTERS, HIP_CDUMP_FIRST_CPUREG * 2), HIP_CDUMP_FIRST_CPUREG, HIP_CDUMP_NCPUREGS }, - { UNIFI_COREDUMP_PHY_REG, UNIFI_PROC_PHY, UNIFI_MAKE_GP(REGISTERS, HIP_CDUMP_FIRST_CPUREG * 2), HIP_CDUMP_FIRST_CPUREG, HIP_CDUMP_NCPUREGS }, - { UNIFI_COREDUMP_SH_DMEM, UNIFI_PROC_INVALID, UNIFI_MAKE_GP(SH_DMEM, HIP_CDUMP_FIRST_SH * 2), HIP_CDUMP_FIRST_SH, HIP_CDUMP_NWORDS_SH }, - { UNIFI_COREDUMP_MAC_DMEM, UNIFI_PROC_MAC, UNIFI_MAKE_GP(MAC_DMEM, HIP_CDUMP_FIRST_LO * 2), HIP_CDUMP_FIRST_LO, HIP_CDUMP_NWORDS_LO }, - { UNIFI_COREDUMP_MAC_DMEM, UNIFI_PROC_MAC, UNIFI_MAKE_GP(MAC_DMEM, HIP_CDUMP_FIRST_HI_MAC * 2), HIP_CDUMP_FIRST_HI_MAC, HIP_CDUMP_NWORDS_HI }, - { UNIFI_COREDUMP_PHY_DMEM, UNIFI_PROC_PHY, UNIFI_MAKE_GP(PHY_DMEM, HIP_CDUMP_FIRST_LO * 2), HIP_CDUMP_FIRST_LO, HIP_CDUMP_NWORDS_LO }, - { UNIFI_COREDUMP_PHY_DMEM, UNIFI_PROC_PHY, UNIFI_MAKE_GP(PHY_DMEM, HIP_CDUMP_FIRST_HI_PHY * 2), HIP_CDUMP_FIRST_HI_PHY, HIP_CDUMP_NWORDS_HI }, -}; - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_request_at_next_reset - * - * Request that a mini-coredump is performed when the driver has - * completed resetting the UniFi device. - * - * Arguments: - * card Pointer to card struct - * enable If non-zero, sets the request. - * If zero, cancels any pending request. - * - * Returns: - * CSR_RESULT_SUCCESS or CSR HIP error code - * - * Notes: - * This function is typically called once the driver has detected that - * the UniFi device has become unresponsive due to crash, or internal - * watchdog reset. The driver must reset it to regain communication and, - * immediately after that, the mini-coredump can be captured. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_coredump_request_at_next_reset(card_t *card, s8 enable) -{ - CsrResult r; - - if (enable) - { - unifi_trace(card->ospriv, UDBG2, "Mini-coredump requested after reset\n"); - } - - if (card == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - else - { - card->request_coredump_on_reset = enable?1 : 0; - r = CSR_RESULT_SUCCESS; - } - - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_handle_request - * - * Performs a coredump now, if one was requested, and clears the request. - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * CSR_RESULT_SUCCESS or CSR HIP error code - * - * Notes: - * --------------------------------------------------------------------------- - */ -CsrResult unifi_coredump_handle_request(card_t *card) -{ - CsrResult r = CSR_RESULT_SUCCESS; - - if (card == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - else - { - if (card->request_coredump_on_reset == 1) - { - card->request_coredump_on_reset = 0; - r = unifi_coredump_capture(card, NULL); - } - } - - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_capture - * - * Capture the current status of the UniFi device. - * Various registers are buffered for future offline inspection. - * - * Arguments: - * card Pointer to card struct - * req Pointer to request struct, or NULL: - * A coredump requested manually by the user app - * will have a request struct pointer, an automatic - * coredump will have a NULL pointer. - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_RESULT_FAILURE SDIO error - * CSR_WIFI_HIP_RESULT_INVALID_VALUE Initialisation not complete - * - * Notes: - * The result is a filled entry in the circular buffer of core dumps, - * values from which can be extracted to userland via an ioctl. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req) -{ - CsrResult r = CSR_RESULT_SUCCESS; - static u16 dump_seq_no = 1; - u32 time_of_capture; - - if (card->dump_next_write == NULL) - { - r = CSR_RESULT_SUCCESS; - goto done; - } - - /* Reject forced capture before initialisation has happened */ - if (card->helper == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - goto done; - } - - - /* - * Force a mini-coredump capture right now - */ - time_of_capture = CsrTimeGet(NULL); - unifi_info(card->ospriv, "Mini-coredump capture at t=%u\n", time_of_capture); - - /* Wake up the processors so we can talk to them */ - r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to wake UniFi\n"); - goto done; - } - CsrThreadSleep(20); - - /* Stop both XAPs */ - unifi_trace(card->ospriv, UDBG4, "Stopping XAPs for coredump capture\n"); - r = unifi_card_stop_processor(card, UNIFI_PROC_BOTH); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to stop UniFi XAPs\n"); - goto done; - } - - /* Dump core into the next available slot in the circular list */ - r = unifi_coredump_from_sdio(card, card->dump_next_write); - if (r == CSR_RESULT_SUCCESS) - { - /* Record whether the dump was manual or automatic */ - card->dump_next_write->requestor = (req?1 : 0); - card->dump_next_write->timestamp = time_of_capture; - /* Advance to the next buffer */ - card->dump_next_write->count = dump_seq_no++; - card->dump_cur_read = card->dump_next_write; - card->dump_next_write = card->dump_next_write->next; - - /* Sequence no. of zero indicates slot not in use, so handle wrap */ - if (dump_seq_no == 0) - { - dump_seq_no = 1; - } - - unifi_trace(card->ospriv, UDBG3, - "Coredump (%p), SeqNo=%d, cur_read=%p, next_write=%p\n", - req, - card->dump_cur_read->count, - card->dump_cur_read, card->dump_next_write); - } - - /* Start both XAPs */ - unifi_trace(card->ospriv, UDBG4, "Restart XAPs after coredump\n"); - r = card_start_processor(card, UNIFI_PROC_BOTH); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Failed to start UniFi XAPs\n"); - goto done; - } - -done: - return r; -} /* unifi_coredump_capture() */ - - -/* - * --------------------------------------------------------------------------- - * get_value_from_coredump - * - * - * - * Arguments: - * dump Pointer to buffered coredump data - * offset_in_space XAP memory space to retrieve from the buffer (there - * may be more than one zone covering the same memory - * space, but starting from different offsets). - * offset Offset within the XAP memory space to be retrieved - * - * Returns: - * >=0 Register value on success - * <0 Register out of range of any captured zones - * - * Notes: - * --------------------------------------------------------------------------- - */ -static s32 get_value_from_coredump(const coredump_buffer *coreDump, - const unifi_coredump_space_t space, - const u16 offset_in_space) -{ - s32 r = -1; - u16 offset_in_zone; - u32 zone_end_offset; - s32 i; - const struct coredump_zone *def = &zonedef_table[0]; - - /* Search zone def table for a match with the requested memory space */ - for (i = 0; i < HIP_CDUMP_NUM_ZONES; i++, def++) - { - if (space == def->space) - { - zone_end_offset = def->offset + def->length; - - /* Is the space offset contained in this zone? */ - if (offset_in_space < zone_end_offset && - offset_in_space >= def->offset) - { - /* Calculate the offset of data within the zone buffer */ - offset_in_zone = offset_in_space - def->offset; - r = (s32) * (coreDump->zone[i] + offset_in_zone); - - unifi_trace(NULL, UDBG6, - "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n", - space, offset_in_space, r, - i, def->offset, zone_end_offset - 1); - break; - } - } - } - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_get_value - * - * Retrieve the value of a register buffered from a previous core dump, - * so that it may be reported back to application code. - * - * Arguments: - * card Pointer to card struct - * req_reg Pointer to request parameter partially filled. This - * function puts in the values retrieved from the dump. - * - * Returns: - * CSR_RESULT_SUCCESS on success, or: - * CSR_WIFI_HIP_RESULT_INVALID_VALUE Null parameter error - * CSR_WIFI_HIP_RESULT_RANGE Register out of range - * CSR_WIFI_HIP_RESULT_NOT_FOUND Dump index not (yet) captured - * - * Notes: - * --------------------------------------------------------------------------- - */ -CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req) -{ - CsrResult r; - s32 i = 0; - coredump_buffer *find_dump = NULL; - - if (req == NULL || card == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - goto done; - } - req->value = -1; - if (card->dump_buf == NULL) - { - unifi_trace(card->ospriv, UDBG2, "No coredump buffers\n"); - r = CSR_WIFI_HIP_RESULT_NOT_FOUND; /* Coredumping disabled */ - goto done; - } - if (card->dump_cur_read == NULL) - { - unifi_trace(card->ospriv, UDBG4, "No coredumps captured\n"); - r = CSR_WIFI_HIP_RESULT_NOT_FOUND; /* No coredump yet captured */ - goto done; - } - - /* Find the requested dump buffer */ - switch (req->index) - { - case 0: /* Newest */ - find_dump = card->dump_cur_read; - break; - case -1: /* Oldest: The next used slot forward */ - for (find_dump = card->dump_cur_read->next; - (find_dump->count == 0) && (find_dump != card->dump_cur_read); - find_dump = card->dump_cur_read->next) - { - } - break; - default: /* Number of steps back from current read position */ - for (i = 0, find_dump = card->dump_cur_read; - i < req->index; - i++, find_dump = find_dump->prev) - { - /* Walk the list for the index'th entry, but - * stop when about to wrap. */ - unifi_trace(card->ospriv, UDBG6, - "%d: %d, @%p, p=%p, n=%p, cr=%p, h=%p\n", - i, find_dump->count, find_dump, find_dump->prev, - find_dump->next, card->dump_cur_read, card->dump_buf); - if (find_dump->prev == card->dump_cur_read) - { - /* Wrapped but still not found, index out of range */ - if (i != req->index) - { - unifi_trace(card->ospriv, UDBG6, - "Dump index %d not found %d\n", req->index, i); - r = CSR_WIFI_HIP_RESULT_NOT_FOUND; - goto done; - } - break; - } - } - break; - } - - /* Check if the slot is actually filled with a core dump */ - if (find_dump->count == 0) - { - unifi_trace(card->ospriv, UDBG4, "Not captured %d\n", req->index); - r = CSR_WIFI_HIP_RESULT_NOT_FOUND; - goto done; - } - - unifi_trace(card->ospriv, UDBG6, "Req index %d, found seq %d at step %d\n", - req->index, find_dump->count, i); - - /* Find the appropriate entry in the buffer */ - req->value = get_value_from_coredump(find_dump, req->space, (u16)req->offset); - if (req->value < 0) - { - r = CSR_WIFI_HIP_RESULT_RANGE; /* Un-captured register */ - unifi_trace(card->ospriv, UDBG4, - "Can't read space %d, reg 0x%x from coredump buffer %d\n", - req->space, req->offset, req->index); - } - else - { - r = CSR_RESULT_SUCCESS; - } - - /* Update the private request structure with the found values */ - req->chip_ver = find_dump->chip_ver; - req->fw_ver = find_dump->fw_ver; - req->timestamp = find_dump->timestamp; - req->requestor = find_dump->requestor; - req->serial = find_dump->count; - -done: - return r; -} /* unifi_coredump_get_value() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_read_zone - * - * Captures a UniFi memory zone into a buffer on the host - * - * Arguments: - * card Pointer to card struct - * zonebuf Pointer to on-host buffer to dump the memory zone into - * def Pointer to description of the memory zone to read from UniFi. - * - * Returns: - * CSR_RESULT_SUCCESS on success, or: - * CSR_RESULT_FAILURE SDIO error - * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error - * - * Notes: - * It is assumed that the caller has already stopped the XAPs - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_coredump_read_zone(card_t *card, u16 *zonebuf, const struct coredump_zone *def) -{ - CsrResult r; - - if (zonebuf == NULL || def == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - goto done; - } - - /* Select XAP CPU if necessary */ - if (def->cpu != UNIFI_PROC_INVALID) - { - if (def->cpu != UNIFI_PROC_MAC && def->cpu != UNIFI_PROC_PHY) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - goto done; - } - r = unifi_set_proc_select(card, def->cpu); - if (r != CSR_RESULT_SUCCESS) - { - goto done; - } - } - - unifi_trace(card->ospriv, UDBG4, - "Dump sp %d, offs 0x%04x, 0x%04x words @GP=%08x CPU %d\n", - def->space, def->offset, def->length, def->gp, def->cpu); - - /* Read on-chip RAM (byte-wise) */ - r = unifi_card_readn(card, def->gp, zonebuf, (u16)(def->length * 2)); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - goto done; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Can't read UniFi shared data area\n"); - goto done; - } - -done: - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_read_zones - * - * Walks through the table of on-chip memory zones defined in zonedef_table, - * and reads each of them from the UniFi chip - * - * Arguments: - * card Pointer to card struct - * dump_buf Buffer into which register values will be dumped - * - * Returns: - * CSR_RESULT_SUCCESS on success, or: - * CSR_RESULT_FAILURE SDIO error - * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error - * - * Notes: - * It is assumed that the caller has already stopped the XAPs - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_coredump_read_zones(card_t *card, coredump_buffer *dump_buf) -{ - CsrResult r = CSR_RESULT_SUCCESS; - s32 i; - - /* Walk the table of coredump zone definitions and read them from the chip */ - for (i = 0; - (i < HIP_CDUMP_NUM_ZONES) && (r == 0); - i++) - { - r = unifi_coredump_read_zone(card, dump_buf->zone[i], &zonedef_table[i]); - } - - return r; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_from_sdio - * - * Capture the status of the UniFi processors, over SDIO - * - * Arguments: - * card Pointer to card struct - * reg_buffer Buffer into which register values will be dumped - * - * Returns: - * CSR_RESULT_SUCCESS on success, or: - * CSR_RESULT_FAILURE SDIO error - * CSR_WIFI_HIP_RESULT_INVALID_VALUE Parameter error - * - * Notes: - * --------------------------------------------------------------------------- - */ -static CsrResult unifi_coredump_from_sdio(card_t *card, coredump_buffer *dump_buf) -{ - u16 val; - CsrResult r; - u32 sdio_addr; - - if (dump_buf == NULL) - { - r = CSR_WIFI_HIP_RESULT_INVALID_VALUE; - goto done; - } - - - /* Chip and firmware version */ - unifi_trace(card->ospriv, UDBG4, "Get chip version\n"); - sdio_addr = 2 * ChipHelper_GBL_CHIP_VERSION(card->helper); - if (sdio_addr != 0) - { - r = unifi_read_direct16(card, sdio_addr, &val); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - goto done; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Can't read GBL_CHIP_VERSION\n"); - goto done; - } - } - dump_buf->chip_ver = val; - dump_buf->fw_ver = card->build_id; - - unifi_trace(card->ospriv, UDBG4, "chip_ver 0x%04x, fw_ver %u\n", - dump_buf->chip_ver, dump_buf->fw_ver); - - /* Capture the memory zones required from UniFi */ - r = unifi_coredump_read_zones(card, dump_buf); - if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE) - { - goto done; - } - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "Can't read UniFi memory areas\n"); - goto done; - } - -done: - return r; -} /* unifi_coredump_from_sdio() */ - - -#ifndef UNIFI_DISABLE_COREDUMP -/* - * --------------------------------------------------------------------------- - * new_coredump_node - * - * Allocates a coredump linked-list node, and links it to the previous. - * - * Arguments: - * ospriv OS context - * prevnode Previous node to link into - * - * Returns: - * Pointer to valid coredump_buffer on success - * NULL on memory allocation failure - * - * Notes: - * Allocates "all or nothing" - * --------------------------------------------------------------------------- - */ -static -coredump_buffer* new_coredump_node(void *ospriv, coredump_buffer *prevnode) -{ - coredump_buffer *newnode = NULL; - u16 *newzone = NULL; - s32 i; - u32 zone_size; - - /* Allocate node header */ - newnode = kzalloc(sizeof(coredump_buffer), GFP_KERNEL); - if (newnode == NULL) - { - return NULL; - } - - /* Allocate chip memory zone capture buffers */ - for (i = 0; i < HIP_CDUMP_NUM_ZONES; i++) - { - zone_size = sizeof(u16) * zonedef_table[i].length; - newzone = kzalloc(zone_size, GFP_KERNEL); - newnode->zone[i] = newzone; - if (newzone == NULL) - { - unifi_error(ospriv, "Out of memory on coredump zone %d (%d words)\n", - i, zonedef_table[i].length); - break; - } - } - - /* Clean up if any zone alloc failed */ - if (newzone == NULL) - { - for (i = 0; newnode->zone[i] != NULL; i++) - { - kfree(newnode->zone[i]); - newnode->zone[i] = NULL; - } - } - - /* Link to previous node */ - newnode->prev = prevnode; - if (prevnode) - { - prevnode->next = newnode; - } - newnode->next = NULL; - - return newnode; -} - - -#endif /* UNIFI_DISABLE_COREDUMP */ - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_init - * - * Allocates buffers for the automatic SDIO core dump - * - * Arguments: - * card Pointer to card struct - * num_dump_buffers Number of buffers to reserve for coredumps - * - * Returns: - * CSR_RESULT_SUCCESS on success, or: - * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed - * - * Notes: - * Allocates space in advance, to be used for the last n coredump buffers - * the intention being that the size is sufficient for at least one dump, - * probably several. - * It's probably advisable to have at least 2 coredump buffers to allow - * one to be enquired with the unifi_coredump tool, while leaving another - * free for capturing. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_coredump_init(card_t *card, u16 num_dump_buffers) -{ -#ifndef UNIFI_DISABLE_COREDUMP - void *ospriv = card->ospriv; - coredump_buffer *prev = NULL; - coredump_buffer *newnode = NULL; - u32 i = 0; -#endif - - card->request_coredump_on_reset = 0; - card->dump_next_write = NULL; - card->dump_cur_read = NULL; - card->dump_buf = NULL; - -#ifndef UNIFI_DISABLE_COREDUMP - unifi_trace(ospriv, UDBG1, - "Allocate buffers for %d core dumps\n", num_dump_buffers); - if (num_dump_buffers == 0) - { - goto done; - } - - /* Root node */ - card->dump_buf = new_coredump_node(ospriv, NULL); - if (card->dump_buf == NULL) - { - goto fail; - } - prev = card->dump_buf; - newnode = card->dump_buf; - - /* Add each subsequent node at tail */ - for (i = 1; i < num_dump_buffers; i++) - { - newnode = new_coredump_node(ospriv, prev); - if (newnode == NULL) - { - goto fail; - } - prev = newnode; - } - - /* Link the first and last nodes to make the list circular */ - card->dump_buf->prev = newnode; - newnode->next = card->dump_buf; - - /* Set initial r/w access pointers */ - card->dump_next_write = card->dump_buf; - card->dump_cur_read = NULL; - - unifi_trace(ospriv, UDBG2, "Core dump configured (%d dumps max)\n", i); - -done: -#endif - return CSR_RESULT_SUCCESS; - -#ifndef UNIFI_DISABLE_COREDUMP -fail: - /* Unwind what we allocated so far */ - unifi_error(ospriv, "Out of memory allocating core dump node %d\n", i); - unifi_coredump_free(card); - return CSR_WIFI_HIP_RESULT_NO_MEMORY; -#endif -} /* unifi_coreump_init() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_coredump_free - * - * Free all memory dynamically allocated for core dump - * - * Arguments: - * card Pointer to card struct - * - * Returns: - * None - * - * Notes: - * --------------------------------------------------------------------------- - */ -void unifi_coredump_free(card_t *card) -{ - void *ospriv = card->ospriv; - coredump_buffer *node, *del_node; - s16 i = 0; - s16 j; - - unifi_trace(ospriv, UDBG2, "Core dump de-configured\n"); - - if (card->dump_buf == NULL) - { - return; - } - - node = card->dump_buf; - do - { - /* Free payload zones */ - for (j = 0; j < HIP_CDUMP_NUM_ZONES; j++) - { - kfree(node->zone[j]); - node->zone[j] = NULL; - } - - /* Detach */ - del_node = node; - node = node->next; - - /* Free header */ - kfree(del_node); - i++; - } while ((node != NULL) && (node != card->dump_buf)); - - unifi_trace(ospriv, UDBG3, "Freed %d coredump buffers\n", i); - - card->dump_buf = NULL; - card->dump_next_write = NULL; - card->dump_cur_read = NULL; -} /* unifi_coredump_free() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_packing.c b/drivers/staging/csr/csr_wifi_hip_packing.c deleted file mode 100644 index 0768aefc6d1f..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_packing.c +++ /dev/null @@ -1,4804 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_wifi_hip_signals.h" -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" - - -/* - * --------------------------------------------------------------------------- - * get_packed_struct_size - * - * Examine a buffer containing a UniFi signal in wire-format. - * The first two bytes contain the signal ID, decode the signal ID and - * return the size, in bytes, of the signal, not including any bulk - * data. - * - * WARNING: This function is auto-generated, DO NOT EDIT! - * - * Arguments: - * buf Pointer to buffer to decode. - * - * Returns: - * 0 if the signal ID is not recognised (i.e. zero length), - * otherwise the number of bytes occupied by the signal in the buffer. - * This is useful for stepping past the signal to the object in the buffer. - * --------------------------------------------------------------------------- - */ -s32 get_packed_struct_size(const u8 *buf) -{ - s32 size = 0; - u16 sig_id; - - sig_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(buf); - - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - switch (sig_id) - { -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_WORD16_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; - case CSR_DEBUG_GENERIC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT64; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; - case CSR_MLME_SET_TIM_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif - case CSR_DEBUG_GENERIC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_MLME_SET_TIM_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_GENERIC_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT32; - size += SIZEOF_UINT32; - size += 48 / 8; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 32 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_ERROR_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - size += SIZEOF_UINT32; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += 48 / 8; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - size += SIZEOF_UINT16; - break; -#endif - default: - size = 0; - } - return size; -} /* get_packed_struct_size() */ - - -/* - * --------------------------------------------------------------------------- - * read_unpack_signal - * - * Unpack a wire-format signal into a host-native structure. - * This function handles any necessary conversions for endianness and - * places no restrictions on packing or alignment for the structure - * definition. - * - * WARNING: This function is auto-generated, DO NOT EDIT! - * - * Arguments: - * ptr Signal buffer to unpack. - * sig Pointer to destination structure to populate. - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the ID of signal was not recognised. - * --------------------------------------------------------------------------- - */ -CsrResult read_unpack_signal(const u8 *ptr, CSR_SIGNAL *sig) -{ - s32 index = 0; - - sig->SignalPrimitiveHeader.SignalId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - - sig->SignalPrimitiveHeader.ReceiverProcessId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - - sig->SignalPrimitiveHeader.SenderProcessId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - - switch (sig->SignalPrimitiveHeader.SignalId) - { -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - sig->u.MlmeSetkeysConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - sig->u.MlmeConfigQueueConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - sig->u.MlmeAddBlackoutConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - sig->u.MlmeDelBlackoutRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutRequest.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - sig->u.MlmeSmStartConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - sig->u.MlmeStopAggregationConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeStopAggregationConfirm.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeStopAggregationConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - sig->u.MlmeDelTspecRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_WORD16_INDICATION_ID: - sig->u.DebugWord16Indication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[8] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[9] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[10] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[11] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[12] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[13] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[14] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugWord16Indication.DebugWords[15] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_DEBUG_GENERIC_CONFIRM_ID: - sig->u.DebugGenericConfirm.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericConfirm.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_INDICATION_ID: - sig->u.MaPacketIndication.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MaPacketIndication.LocalTime.x, &ptr[index], 64 / 8); - index += 64 / 8; - sig->u.MaPacketIndication.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.ReceptionStatus = (CSR_RECEPTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Rssi = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.Snr = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketIndication.ReceivedRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MLME_SET_TIM_REQUEST_ID: - sig->u.MlmeSetTimRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.AssociationId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimRequest.TimValue = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - sig->u.MlmeConnectedIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectedIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectedIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectedIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectedIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectedIndication.ConnectionStatus = (CSR_CONNECTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeConnectedIndication.PeerMacAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - sig->u.MlmeDelRxTriggerRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerRequest.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - sig->u.MlmeTriggeredGetIndication.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeTriggeredGetIndication.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - sig->u.MlmeScanRequest.ChannelList.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.ChannelList.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.ScanType = (CSR_SCAN_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.ProbeDelay = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeScanRequest.MinChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanRequest.MaxChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - sig->u.MlmeDeletekeysConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - sig->u.MlmeGetNextRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - sig->u.MlmeSetChannelConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - sig->u.MlmeStartAggregationRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeStartAggregationRequest.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeStartAggregationRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.StartingSequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.BufferSize = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationRequest.BlockAckTimeout = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - sig->u.MlmeHlSyncRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeHlSyncRequest.GroupAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif - case CSR_DEBUG_GENERIC_REQUEST_ID: - sig->u.DebugGenericRequest.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericRequest.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - sig->u.MlmeLeaveConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetRequest.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - sig->u.MlmeAddMulticastAddressRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressRequest.NumberOfMulticastGroupAddresses = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - sig->u.MlmeResetRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeResetRequest.StaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeResetRequest.SetDefaultMib = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - sig->u.MlmeScanCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanCancelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetConfirm.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - sig->u.MlmeSetPacketFilterRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.PacketFilterMode = (CSR_PACKET_FILTER_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetPacketFilterRequest.ArpFilterAddress = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelRxTriggerConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - sig->u.MlmeConnectStatusRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.ConnectionStatus = (CSR_CONNECTION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeConnectStatusRequest.StaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeConnectStatusRequest.AssociationId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusRequest.AssociationCapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - sig->u.MlmeLeaveRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeLeaveRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - sig->u.MlmeConfigQueueRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.QueueIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Aifs = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Cwmin = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.Cwmax = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConfigQueueRequest.TxopLimit = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - sig->u.MlmeDelTspecConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTspecConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MLME_SET_TIM_CONFIRM_ID: - sig->u.MlmeSetTimConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetTimConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - sig->u.MlmeMeasureIndication.MeasurementReportSet.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureIndication.MeasurementReportSet.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureIndication.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - sig->u.MlmeDelBlackoutConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelBlackoutConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelTriggeredGetConfirm.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_GENERIC_INDICATION_ID: - sig->u.DebugGenericIndication.DebugVariable.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugVariable.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugGenericIndication.DebugWords[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - sig->u.MaPacketCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketCancelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketCancelRequest.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_REQUEST_ID: - sig->u.MaPacketRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.TransmitRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketRequest.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MaPacketRequest.Priority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MaPacketRequest.Ra.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MaPacketRequest.TransmissionControl = (CSR_TRANSMISSION_CONTROL) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - sig->u.MlmeModifyBssParameterRequest.Data.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.Data.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.BeaconPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.DtimPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeModifyBssParameterRequest.CapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeModifyBssParameterRequest.Bssid.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeModifyBssParameterRequest.RtsThreshold = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - sig->u.MlmeAddRxTriggerRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerRequest.Priority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - sig->u.MaVifAvailabilityIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityIndication.Multicast = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - sig->u.MlmeHlSyncCancelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeHlSyncCancelRequest.GroupAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - sig->u.MlmeBlackoutEndedIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlackoutEndedIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlackoutEndedIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlackoutEndedIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlackoutEndedIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlackoutEndedIndication.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanDoneIndication.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - sig->u.MlmeGetKeySequenceRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetKeySequenceRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeGetKeySequenceRequest.Address.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - sig->u.MlmeSetChannelRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeSetChannelRequest.Address.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeSetChannelRequest.AvailabilityDuration = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetChannelRequest.AvailabilityInterval = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - sig->u.MlmeMeasureConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureConfirm.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - sig->u.MlmeAddTriggeredGetRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTriggeredGetRequest.TriggeredId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAutonomousScanLossIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeAutonomousScanLossIndication.Bssid.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - sig->u.MaVifAvailabilityResponse.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityResponse.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityResponse.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityResponse.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityResponse.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaVifAvailabilityResponse.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - sig->u.MlmeAddTemplateRequest.Data1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.Data1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.Data2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.Data2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.FrameType = (CSR_FRAME_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateRequest.MinTransmitRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - sig->u.MlmePowermgtConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - sig->u.MlmeAddPeriodicConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - sig->u.MlmeGetConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - sig->u.MlmeGetNextConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetNextConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - sig->u.MlmeStopAggregationRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeStopAggregationRequest.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeStopAggregationRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopAggregationRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.TriggerId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddRxTriggerConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - sig->u.MlmeAddBlackoutRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.BlackoutId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.BlackoutType = (CSR_BLACKOUT_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.BlackoutSource = (CSR_BLACKOUT_SOURCE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddBlackoutRequest.BlackoutStartReference = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddBlackoutRequest.BlackoutPeriod = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddBlackoutRequest.BlackoutDuration = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - memcpy(sig->u.MlmeAddBlackoutRequest.PeerStaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeAddBlackoutRequest.BlackoutCount = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - sig->u.MlmeDeletekeysRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDeletekeysRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeDeletekeysRequest.Address.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - sig->u.MlmeResetConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeResetConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - sig->u.MlmeHlSyncConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeHlSyncConfirm.GroupAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeHlSyncConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - sig->u.MlmeAddAutonomousScanRequest.ChannelList.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.ChannelList.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.InformationElements.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.InformationElements.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.ChannelStartingFactor = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.ScanType = (CSR_SCAN_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.ProbeDelay = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddAutonomousScanRequest.MinChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddAutonomousScanRequest.MaxChannelTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - sig->u.MlmeSetRequest.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetRequest.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - sig->u.MlmeSmStartRequest.Beacon.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.Beacon.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.BssParameters.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.BssParameters.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.Ifindex = (CSR_IFINTERFACE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.Channel = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeSmStartRequest.InterfaceAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - memcpy(sig->u.MlmeSmStartRequest.Bssid.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeSmStartRequest.BeaconPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.DtimPeriod = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSmStartRequest.CapabilityInformation = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - sig->u.MlmeConnectStatusConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeConnectStatusConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelAutonomousScanConfirm.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - sig->u.MlmeDelPeriodicRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicRequest.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - sig->u.MlmeSetkeysRequest.Key.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.Key.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.Length = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.KeyId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.KeyType = (CSR_KEY_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeSetkeysRequest.Address.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeSetkeysRequest.SequenceNumber[0] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[1] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[2] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[3] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[4] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[5] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[6] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetkeysRequest.SequenceNumber[7] = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(&sig->u.MlmeSetkeysRequest.CipherSuiteSelector, &ptr[index], 32 / 8); - index += 32 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.AutonomousScanId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePauseAutonomousScanRequest.Pause = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - sig->u.MlmeGetRequest.MibAttribute.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetRequest.MibAttribute.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeGetRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - sig->u.MlmePowermgtRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.PowerManagementMode = (CSR_POWER_MANAGEMENT_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.ReceiveDtims = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.ListenInterval = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmePowermgtRequest.TrafficWindow = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_ERROR_INDICATION_ID: - sig->u.MaPacketErrorIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketErrorIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketErrorIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketErrorIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketErrorIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MaPacketErrorIndication.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MaPacketErrorIndication.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketErrorIndication.SequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - sig->u.MlmeAddPeriodicRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.MaximumLatency = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddPeriodicRequest.PeriodicSchedulingMode = (CSR_PERIODIC_SCHEDULING_MODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.WakeHost = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddPeriodicRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - sig->u.MlmeAddTspecRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.PsScheme = (CSR_PS_SCHEME) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.MediumTime = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecRequest.ServiceStartTime = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddTspecRequest.ServiceInterval = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - sig->u.MlmeAddTspecRequest.MinimumDataRate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddMulticastAddressConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - sig->u.MlmeAddTspecConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTspecConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeHlSyncCancelConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - sig->u.MlmeScanConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeScanConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - sig->u.DebugStringIndication.DebugMessage.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugStringIndication.DebugMessage.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugStringIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.DebugStringIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - sig->u.MlmeAddTemplateConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.FrameType = (CSR_FRAME_TYPE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeAddTemplateConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - sig->u.MlmeBlockackErrorIndication.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlockackErrorIndication.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlockackErrorIndication.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlockackErrorIndication.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlockackErrorIndication.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeBlockackErrorIndication.ResultCode = (CSR_REASON_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeBlockackErrorIndication.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - sig->u.MlmeSetConfirm.MibAttributeValue.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetConfirm.MibAttributeValue.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetConfirm.Status = (CSR_MIB_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeSetConfirm.ErrorIndex = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - sig->u.MlmeMeasureRequest.MeasurementRequestSet.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureRequest.MeasurementRequestSet.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeMeasureRequest.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - sig->u.MlmeStartAggregationConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - memcpy(sig->u.MlmeStartAggregationConfirm.PeerQstaAddress.x, &ptr[index], 48 / 8); - index += 48 / 8; - sig->u.MlmeStartAggregationConfirm.UserPriority = (CSR_PRIORITY) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.Direction = (CSR_DIRECTION) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStartAggregationConfirm.SequenceNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - sig->u.MlmeStopMeasureConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureConfirm.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_CONFIRM_ID: - sig->u.MaPacketConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.TransmissionStatus = (CSR_TRANSMISSION_STATUS) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.RetryCount = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.Rate = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MaPacketConfirm.HostTag = CSR_GET_UINT32_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - sig->u.MlmeDelPeriodicConfirm.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.VirtualInterfaceIdentifier = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.PeriodicId = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeDelPeriodicConfirm.ResultCode = (CSR_RESULT_CODE) CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - sig->u.MlmeStopMeasureRequest.Dummydataref1.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureRequest.Dummydataref1.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureRequest.Dummydataref2.SlotNumber = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureRequest.Dummydataref2.DataLength = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - sig->u.MlmeStopMeasureRequest.DialogToken = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index); - index += SIZEOF_UINT16; - break; -#endif - - default: - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - return CSR_RESULT_SUCCESS; -} /* read_unpack_signal() */ - - -/* - * --------------------------------------------------------------------------- - * write_pack - * - * Convert a signal structure, in host-native format, to the - * little-endian wire format specified in the UniFi Host Interface - * Protocol Specification. - * - * WARNING: This function is auto-generated, DO NOT EDIT! - * - * Arguments: - * sig Pointer to signal structure to pack. - * ptr Destination buffer to pack into. - * sig_len Returns the length of the packed signal, i.e. the - * number of bytes written to ptr. - * - * Returns: - * CSR_RESULT_SUCCESS on success, - * CSR_WIFI_HIP_RESULT_INVALID_VALUE if the ID of signal was not recognised. - * --------------------------------------------------------------------------- - */ -CsrResult write_pack(const CSR_SIGNAL *sig, u8 *ptr, u16 *sig_len) -{ - s16 index = 0; - - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.SignalId, ptr + index); - index += SIZEOF_UINT16; - - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.ReceiverProcessId, ptr + index); - index += SIZEOF_UINT16; - - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->SignalPrimitiveHeader.SenderProcessId, ptr + index); - index += SIZEOF_UINT16; - - switch (sig->SignalPrimitiveHeader.SignalId) - { -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanConfirm.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.BlackoutId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutRequest.BlackoutId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceConfirm.SequenceNumber[7], ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeStopAggregationConfirm.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.Direction, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecRequest.Direction, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_WORD16_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[7], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[8], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[9], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[10], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[11], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[12], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[13], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[14], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugWord16Indication.DebugWords[15], ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_DEBUG_GENERIC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugVariable.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugVariable.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericConfirm.DebugWords[7], ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Data.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Data.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MaPacketIndication.LocalTime.x, 64 / 8); - index += 64 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Ifindex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Channel, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.ReceptionStatus, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Rssi, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.Snr, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketIndication.ReceivedRate, ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MLME_SET_TIM_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.AssociationId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimRequest.TimValue, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectedIndication.ConnectionStatus, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeConnectedIndication.PeerMacAddress.x, 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerRequest.TriggerId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.MibAttributeValue.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.MibAttributeValue.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.Status, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.ErrorIndex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeTriggeredGetIndication.TriggeredId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ChannelList.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ChannelList.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.InformationElements.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.InformationElements.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.Ifindex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ScanType, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.ProbeDelay, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.MinChannelTime, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanRequest.MaxChannelTime, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.MibAttribute.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.MibAttribute.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeStartAggregationRequest.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.Direction, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.StartingSequenceNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.BufferSize, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationRequest.BlockAckTimeout, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeHlSyncRequest.GroupAddress.x, 48 / 8); - index += 48 / 8; - break; -#endif - case CSR_DEBUG_GENERIC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugVariable.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugVariable.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericRequest.DebugWords[7], ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetRequest.TriggeredId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Data.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Data.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressRequest.NumberOfMulticastGroupAddresses, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeResetRequest.StaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetRequest.SetDefaultMib, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanCancelRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetConfirm.TriggeredId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.InformationElements.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.InformationElements.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.PacketFilterMode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeSetPacketFilterRequest.ArpFilterAddress, ptr + index); - index += SIZEOF_UINT32; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.TriggerId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelRxTriggerConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.InformationElements.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.InformationElements.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.ConnectionStatus, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeConnectStatusRequest.StaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.AssociationId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusRequest.AssociationCapabilityInformation, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeLeaveRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.QueueIndex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Aifs, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Cwmin, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.Cwmax, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConfigQueueRequest.TxopLimit, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTspecConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MLME_SET_TIM_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetTimConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.MeasurementReportSet.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.MeasurementReportSet.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureIndication.DialogToken, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.BlackoutId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelBlackoutConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelTriggeredGetConfirm.TriggeredId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_GENERIC_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugVariable.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugVariable.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugGenericIndication.DebugWords[7], ptr + index); - index += SIZEOF_UINT16; - break; - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketCancelRequest.HostTag, ptr + index); - index += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanConfirm.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Data.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Data.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.TransmitRate, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.HostTag, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.Priority, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MaPacketRequest.Ra.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketRequest.TransmissionControl, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Data.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Data.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.BeaconPeriod, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.DtimPeriod, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.CapabilityInformation, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeModifyBssParameterRequest.Bssid.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeModifyBssParameterRequest.RtsThreshold, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.InformationElements.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.InformationElements.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.TriggerId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerRequest.Priority, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityIndication.Multicast, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeHlSyncCancelRequest.GroupAddress.x, 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanRequest.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlackoutEndedIndication.BlackoutId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanDoneIndication.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.KeyId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetKeySequenceRequest.KeyType, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeGetKeySequenceRequest.Address.x, 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Ifindex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.Channel, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeSetChannelRequest.Address.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.AvailabilityDuration, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetChannelRequest.AvailabilityInterval, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureConfirm.DialogToken, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.MibAttribute.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.MibAttribute.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTriggeredGetRequest.TriggeredId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAutonomousScanLossIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeAutonomousScanLossIndication.Bssid.x, 48 / 8); - index += 48 / 8; - break; -#endif - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaVifAvailabilityResponse.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.Data2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.FrameType, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateRequest.MinTransmitRate, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.PeriodicId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.MibAttributeValue.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.MibAttributeValue.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.Status, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetConfirm.ErrorIndex, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.MibAttributeValue.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.MibAttributeValue.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.Status, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetNextConfirm.ErrorIndex, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeStopAggregationRequest.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopAggregationRequest.Direction, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.TriggerId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddRxTriggerConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutType, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutSource, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutStartReference, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutPeriod, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutDuration, ptr + index); - index += SIZEOF_UINT32; - memcpy(ptr + index, sig->u.MlmeAddBlackoutRequest.PeerStaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddBlackoutRequest.BlackoutCount, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.KeyId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDeletekeysRequest.KeyType, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeDeletekeysRequest.Address.x, 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeResetConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeHlSyncConfirm.GroupAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelList.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelList.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.InformationElements.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.InformationElements.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.Ifindex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ChannelStartingFactor, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ScanType, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.ProbeDelay, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.MinChannelTime, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddAutonomousScanRequest.MaxChannelTime, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.MibAttributeValue.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.MibAttributeValue.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Beacon.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Beacon.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BssParameters.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BssParameters.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Ifindex, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.Channel, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeSmStartRequest.InterfaceAddress.x, 48 / 8); - index += 48 / 8; - memcpy(ptr + index, sig->u.MlmeSmStartRequest.Bssid.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.BeaconPeriod, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.DtimPeriod, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSmStartRequest.CapabilityInformation, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeConnectStatusConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelAutonomousScanConfirm.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicRequest.PeriodicId, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Key.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Key.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.Length, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.KeyId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.KeyType, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeSetkeysRequest.Address.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[0], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[1], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[2], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[3], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[4], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[5], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[6], ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetkeysRequest.SequenceNumber[7], ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, &sig->u.MlmeSetkeysRequest.CipherSuiteSelector, 32 / 8); - index += 32 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.AutonomousScanId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePauseAutonomousScanRequest.Pause, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.MibAttribute.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.MibAttribute.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeGetRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.PowerManagementMode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.ReceiveDtims, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.ListenInterval, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmePowermgtRequest.TrafficWindow, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_ERROR_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MaPacketErrorIndication.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketErrorIndication.SequenceNumber, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.PeriodicId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.MaximumLatency, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.PeriodicSchedulingMode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.WakeHost, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddPeriodicRequest.UserPriority, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.Direction, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.PsScheme, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.MediumTime, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.ServiceStartTime, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.ServiceInterval, ptr + index); - index += SIZEOF_UINT32; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecRequest.MinimumDataRate, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddMulticastAddressConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTspecConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeHlSyncCancelConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeScanConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.DebugMessage.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.DebugMessage.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.DebugStringIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.FrameType, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeAddTemplateConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeBlockackErrorIndication.ResultCode, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeBlockackErrorIndication.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.MibAttributeValue.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.MibAttributeValue.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.Status, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeSetConfirm.ErrorIndex, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.MeasurementRequestSet.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.MeasurementRequestSet.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeMeasureRequest.DialogToken, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - memcpy(ptr + index, sig->u.MlmeStartAggregationConfirm.PeerQstaAddress.x, 48 / 8); - index += 48 / 8; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.UserPriority, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.Direction, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStartAggregationConfirm.SequenceNumber, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureConfirm.DialogToken, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - case CSR_MA_PACKET_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.TransmissionStatus, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.RetryCount, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.Rate, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT32_TO_LITTLE_ENDIAN(sig->u.MaPacketConfirm.HostTag, ptr + index); - index += SIZEOF_UINT32; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.VirtualInterfaceIdentifier, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.PeriodicId, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeDelPeriodicConfirm.ResultCode, ptr + index); - index += SIZEOF_UINT16; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref1.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref1.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref2.SlotNumber, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.Dummydataref2.DataLength, ptr + index); - index += SIZEOF_UINT16; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(sig->u.MlmeStopMeasureRequest.DialogToken, ptr + index); - index += SIZEOF_UINT16; - break; -#endif - - default: - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - *sig_len = index; - - return CSR_RESULT_SUCCESS; -} /* write_pack() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_send.c b/drivers/staging/csr/csr_wifi_hip_send.c deleted file mode 100644 index 76429e5e77cf..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_send.c +++ /dev/null @@ -1,415 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * *************************************************************************** - * - * FILE: csr_wifi_hip_send.c - * - * PURPOSE: - * Code for adding a signal request to the from-host queue. - * When the driver bottom-half is run, it will take requests from the - * queue and pass them to the UniFi. - * - * *************************************************************************** - */ -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "csr_wifi_hip_sigs.h" -#include "csr_wifi_hip_card.h" - -unifi_TrafficQueue unifi_frame_priority_to_queue(CSR_PRIORITY priority) -{ - switch (priority) - { - case CSR_QOS_UP0: - case CSR_QOS_UP3: - return UNIFI_TRAFFIC_Q_BE; - case CSR_QOS_UP1: - case CSR_QOS_UP2: - return UNIFI_TRAFFIC_Q_BK; - case CSR_QOS_UP4: - case CSR_QOS_UP5: - return UNIFI_TRAFFIC_Q_VI; - case CSR_QOS_UP6: - case CSR_QOS_UP7: - case CSR_MANAGEMENT: - return UNIFI_TRAFFIC_Q_VO; - default: - return UNIFI_TRAFFIC_Q_BE; - } -} - - -CSR_PRIORITY unifi_get_default_downgrade_priority(unifi_TrafficQueue queue) -{ - switch (queue) - { - case UNIFI_TRAFFIC_Q_BE: - return CSR_QOS_UP0; - case UNIFI_TRAFFIC_Q_BK: - return CSR_QOS_UP1; - case UNIFI_TRAFFIC_Q_VI: - return CSR_QOS_UP5; - case UNIFI_TRAFFIC_Q_VO: - return CSR_QOS_UP6; - default: - return CSR_QOS_UP0; - } -} - - -/* - * --------------------------------------------------------------------------- - * send_signal - * - * This function queues a signal for sending to UniFi. It first checks - * that there is space on the fh_signal_queue for another entry, then - * claims any bulk data slots required and copies data into them. Then - * increments the fh_signal_queue write count. - * - * The fh_signal_queue is later processed by the driver bottom half - * (in unifi_bh()). - * - * This function call unifi_pause_xmit() to pause the flow of data plane - * packets when: - * - the fh_signal_queue ring buffer is full - * - there are less than UNIFI_MAX_DATA_REFERENCES (2) bulk data - * slots available. - * - * Arguments: - * card Pointer to card context structure - * sigptr Pointer to the signal to write to UniFi. - * siglen Number of bytes pointer to by sigptr. - * bulkdata Array of pointers to an associated bulk data. - * sigq To which from-host queue to add the signal. - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or - * no free signal queue entry - * - * Notes: - * Calls unifi_pause_xmit() when the last slots are used. - * --------------------------------------------------------------------------- - */ -static CsrResult send_signal(card_t *card, const u8 *sigptr, u32 siglen, - const bulk_data_param_t *bulkdata, - q_t *sigq, u32 priority_q, u32 run_bh) -{ - u16 i, data_slot_size; - card_signal_t *csptr; - s16 qe; - CsrResult r; - s16 debug_print = 0; - - data_slot_size = CardGetDataSlotSize(card); - - /* Check that the fh_data_queue has a free slot */ - if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sigq)) - { - unifi_trace(card->ospriv, UDBG3, "send_signal: %s full\n", sigq->name); - - return CSR_WIFI_HIP_RESULT_NO_SPACE; - } - - /* - * Now add the signal to the From Host signal queue - */ - /* Get next slot on queue */ - qe = CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq); - csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, qe); - - /* Make up the card_signal struct */ - csptr->signal_length = (u16)siglen; - memcpy((void *)csptr->sigbuf, (void *)sigptr, siglen); - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) - { - if ((bulkdata != NULL) && (bulkdata->d[i].data_length != 0)) - { - u32 datalen = bulkdata->d[i].data_length; - - /* Make sure data will fit in a bulk data slot */ - if (bulkdata->d[i].os_data_ptr == NULL) - { - unifi_error(card->ospriv, "send_signal - NULL bulkdata[%d]\n", i); - debug_print++; - csptr->bulkdata[i].data_length = 0; - } - else - { - if (datalen > data_slot_size) - { - unifi_error(card->ospriv, - "send_signal - Invalid data length %u (@%p), " - "truncating\n", - datalen, bulkdata->d[i].os_data_ptr); - datalen = data_slot_size; - debug_print++; - } - /* Store the bulk data info in the soft queue. */ - csptr->bulkdata[i].os_data_ptr = (u8 *)bulkdata->d[i].os_data_ptr; - csptr->bulkdata[i].os_net_buf_ptr = (u8 *)bulkdata->d[i].os_net_buf_ptr; - csptr->bulkdata[i].net_buf_length = bulkdata->d[i].net_buf_length; - csptr->bulkdata[i].data_length = datalen; - } - } - else - { - UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]); - } - } - - if (debug_print) - { - const u8 *sig = sigptr; - - unifi_error(card->ospriv, "Signal(%d): %*ph\n", siglen, - 16, sig); - unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n", - bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL, - bulkdata != NULL?bulkdata->d[0].data_length : 0, - bulkdata != NULL?bulkdata->d[1].os_data_ptr : NULL, - bulkdata != NULL?bulkdata->d[1].data_length : 0); - } - - /* Advance the written count to say there is a new entry */ - CSR_WIFI_HIP_Q_INC_W(sigq); - - /* - * Set the flag to say reason for waking was a host request. - * Then ask the OS layer to run the unifi_bh. - */ - if (run_bh == 1) - { - card->bh_reason_host = 1; - r = unifi_run_bh(card->ospriv); - if (r != CSR_RESULT_SUCCESS) - { - unifi_error(card->ospriv, "failed to run bh.\n"); - card->bh_reason_host = 0; - - /* - * The bulk data buffer will be freed by the caller. - * We need to invalidate the description of the bulk data in our - * soft queue, to prevent the core freeing the bulk data again later. - */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) - { - if (csptr->bulkdata[i].data_length != 0) - { - csptr->bulkdata[i].os_data_ptr = csptr->bulkdata[i].os_net_buf_ptr = NULL; - csptr->bulkdata[i].net_buf_length = csptr->bulkdata[i].data_length = 0; - } - } - return r; - } - } - else - { - unifi_error(card->ospriv, "run_bh=%d, bh not called.\n", run_bh); - } - - /* - * Have we used up all the fh signal list entries? - */ - if (CSR_WIFI_HIP_Q_SLOTS_FREE(sigq) == 0) - { - /* We have filled the queue, so stop the upper layer. The command queue - * is an exception, as suspending due to that being full could delay - * resume/retry until new commands or data are received. - */ - if (sigq != &card->fh_command_queue) - { - /* - * Must call unifi_pause_xmit() *before* setting the paused flag. - * (the unifi_pause_xmit call should not be after setting the flag because of the possibility of being interrupted - * by the bh thread between our setting the flag and the call to unifi_pause_xmit() - * If bh thread then cleared the flag, we would end up paused, but without the flag set) - * Instead, setting it afterwards means that if this thread is interrupted by the bh thread - * the pause flag is still guaranteed to end up set - * However the potential deadlock now is that if bh thread emptied the queue and cleared the flag before this thread's - * call to unifi_pause_xmit(), then bh thread may not run again because it will be waiting for - * a packet to appear in the queue but nothing ever will because xmit is paused. - * So we will end up with the queue paused, and the flag set to say it is paused, but bh never runs to unpause it. - * (Note even this bad situation would not persist long in practice, because something else (eg rx, or tx in different queue) - * is likely to wake bh thread quite soon) - * But to avoid this deadlock completely, after setting the flag we check that there is something left in the queue. - * If there is, we know that bh thread has not emptied the queue yet. - * Since bh thread checks to unpause the queue *after* taking packets from the queue, we know that it is still going to make at - * least one more check to see whether it needs to unpause the queue. So all is well. - * If there are no packets in the queue, then the deadlock described above might happen. To make sure it does not, we - * unpause the queue here. A possible side effect is that unifi_restart_xmit() may (rarely) be called for second time - * unnecessarily, which is harmless - */ - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("P"); -#endif - unifi_pause_xmit(card->ospriv, (unifi_TrafficQueue)priority_q); - card_tx_q_pause(card, priority_q); - if (CSR_WIFI_HIP_Q_SLOTS_USED(sigq) == 0) - { - card_tx_q_unpause(card, priority_q); - unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue) priority_q); - } - } - else - { - unifi_warning(card->ospriv, - "send_signal: fh_cmd_q full, not pausing (run_bh=%d)\n", - run_bh); - } - } - - return CSR_RESULT_SUCCESS; -} /* send_signal() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_send_signal - * - * Invokes send_signal() to queue a signal in the command or traffic queue - * If sigptr pointer is NULL, it pokes the bh to check if UniFi is responsive. - * - * Arguments: - * card Pointer to card context struct - * sigptr Pointer to signal from card. - * siglen Size of the signal - * bulkdata Pointer to the bulk data of the signal - * - * Returns: - * CSR_RESULT_SUCCESS on success - * CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or no free signal queue entry - * - * Notes: - * unifi_send_signal() is used to queue signals, created by the driver, - * to the device. Signals are constructed using the UniFi packed structures. - * --------------------------------------------------------------------------- - */ -CsrResult unifi_send_signal(card_t *card, const u8 *sigptr, u32 siglen, - const bulk_data_param_t *bulkdata) -{ - q_t *sig_soft_q; - u16 signal_id; - CsrResult r; - u32 run_bh; - u32 priority_q; - - /* A NULL signal pointer is a request to check if UniFi is responsive */ - if (sigptr == NULL) - { - card->bh_reason_host = 1; - return unifi_run_bh(card->ospriv); - } - - priority_q = 0; - run_bh = 1; - signal_id = GET_SIGNAL_ID(sigptr); - /* - * If the signal is a CSR_MA_PACKET_REQUEST , - * we send it using the traffic soft queue. Else we use the command soft queue. - */ - if (signal_id == CSR_MA_PACKET_REQUEST_ID) - { - u16 frame_priority; - - if (card->periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_ENABLED) - { - run_bh = 0; - } - -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE) - unifi_debug_log_to_buf("D"); -#endif - /* Sanity check: MA-PACKET.req must have a valid bulk data */ - if ((bulkdata->d[0].data_length == 0) || (bulkdata->d[0].os_data_ptr == NULL)) - { - unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n", - bulkdata->d[0].data_length, bulkdata->d[0].os_data_ptr); - dump((void *)sigptr, siglen); - return CSR_RESULT_FAILURE; - } - - /* Map the frame priority to a traffic queue index. */ - frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr); - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority); - - sig_soft_q = &card->fh_traffic_queue[priority_q]; - } - else - { - sig_soft_q = &card->fh_command_queue; - } - - r = send_signal(card, sigptr, siglen, bulkdata, sig_soft_q, priority_q, run_bh); - /* On error, the caller must free or requeue bulkdata buffers */ - - return r; -} /* unifi_send_signal() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_send_resources_available - * - * Examines whether there is available space to queue - * a signal in the command or traffic queue - * - * Arguments: - * card Pointer to card context struct - * sigptr Pointer to signal. - * - * Returns: - * CSR_RESULT_SUCCESS if resources available - * CSR_WIFI_HIP_RESULT_NO_SPACE if there was no free signal queue entry - * - * Notes: - * --------------------------------------------------------------------------- - */ -CsrResult unifi_send_resources_available(card_t *card, const u8 *sigptr) -{ - q_t *sig_soft_q; - u16 signal_id = GET_SIGNAL_ID(sigptr); - - /* - * If the signal is a CSR_MA_PACKET_REQUEST , - * we send it using the traffic soft queue. Else we use the command soft queue. - */ - if (signal_id == CSR_MA_PACKET_REQUEST_ID) - { - u16 frame_priority; - u32 priority_q; - - /* Map the frame priority to a traffic queue index. */ - frame_priority = GET_PACKED_MA_PACKET_REQUEST_FRAME_PRIORITY(sigptr); - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY)frame_priority); - - sig_soft_q = &card->fh_traffic_queue[priority_q]; - } - else - { - sig_soft_q = &card->fh_command_queue; - } - - /* Check that the fh_data_queue has a free slot */ - if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sig_soft_q)) - { - unifi_notice(card->ospriv, "unifi_send_resources_available: %s full\n", - sig_soft_q->name); - return CSR_WIFI_HIP_RESULT_NO_SPACE; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_send_resources_available() */ - - diff --git a/drivers/staging/csr/csr_wifi_hip_signals.c b/drivers/staging/csr/csr_wifi_hip_signals.c deleted file mode 100644 index 3c821320df00..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_signals.c +++ /dev/null @@ -1,1313 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - - -/* Generated by hip_dd_l_c_gen.pl */ - -#include "csr_wifi_hip_signals.h" - -#include "csr_wifi_hip_unifi.h" - -s32 SigGetSize(const CSR_SIGNAL *aSignal) -{ - switch (aSignal->SignalPrimitiveHeader.SignalId) - { - case CSR_MA_PACKET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_REQUEST); - case CSR_MA_PACKET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_CONFIRM); - case CSR_MA_PACKET_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_INDICATION); - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_CANCEL_REQUEST); - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_VIF_AVAILABILITY_RESPONSE); - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_VIF_AVAILABILITY_INDICATION); - case CSR_MA_PACKET_ERROR_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MA_PACKET_ERROR_INDICATION); -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_RESET_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_RESET_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_NEXT_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_NEXT_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_POWERMGT_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_POWERMGT_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MEASURE_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SETKEYS_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SETKEYS_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DELETEKEYS_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DELETEKEYS_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECTED_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SCAN_CANCEL_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CANCEL_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_HL_SYNC_CANCEL_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_PERIODIC_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_PERIODIC_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_PERIODIC_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_PERIODIC_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_PACKET_FILTER_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_PACKET_FILTER_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_MEASURE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_MEASURE_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TRIGGERED_GET_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TRIGGERED_GET_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TRIGGERED_GET_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TRIGGERED_GET_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_TRIGGERED_GET_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_BLACKOUT_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_BLACKOUT_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_BLACKOUT_ENDED_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_BLACKOUT_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_BLACKOUT_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_RX_TRIGGER_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_RX_TRIGGER_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_RX_TRIGGER_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_RX_TRIGGER_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECT_STATUS_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONNECT_STATUS_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TEMPLATE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TEMPLATE_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONFIG_QUEUE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_CONFIG_QUEUE_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TSPEC_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_TSPEC_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TSPEC_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_DEL_TSPEC_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_START_AGGREGATION_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_START_AGGREGATION_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_BLOCKACK_ERROR_INDICATION); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_AGGREGATION_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_STOP_AGGREGATION_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SM_START_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SM_START_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_LEAVE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_LEAVE_CONFIRM); -#endif - case CSR_MLME_SET_TIM_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_TIM_REQUEST); - case CSR_MLME_SET_TIM_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_TIM_CONFIRM); -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_KEY_SEQUENCE_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_GET_KEY_SEQUENCE_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CHANNEL_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_SET_CHANNEL_CONFIRM); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST); -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM); -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_STRING_INDICATION); - case CSR_DEBUG_WORD16_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_WORD16_INDICATION); - case CSR_DEBUG_GENERIC_REQUEST_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_REQUEST); - case CSR_DEBUG_GENERIC_CONFIRM_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_CONFIRM); - case CSR_DEBUG_GENERIC_INDICATION_ID: - return offsetof(struct CSR_SIGNAL_PRIMITIVE, u) + sizeof(CSR_DEBUG_GENERIC_INDICATION); - default: - return 0; - } -} - - -s32 SigGetDataRefs(CSR_SIGNAL *aSignal, CSR_DATAREF **aDataRef) -{ - s32 numRefs = 0; - - switch (aSignal->SignalPrimitiveHeader.SignalId) - { - case CSR_MA_PACKET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MaPacketRequest.Data; - aDataRef[numRefs++] = &aSignal->u.MaPacketRequest.Dummydataref2; - break; - case CSR_MA_PACKET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MaPacketConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MaPacketConfirm.Dummydataref2; - break; - case CSR_MA_PACKET_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MaPacketIndication.Data; - aDataRef[numRefs++] = &aSignal->u.MaPacketIndication.Dummydataref2; - break; - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MaPacketCancelRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MaPacketCancelRequest.Dummydataref2; - break; - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityResponse.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityResponse.Dummydataref2; - break; - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MaVifAvailabilityIndication.Dummydataref2; - break; - case CSR_MA_PACKET_ERROR_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MaPacketErrorIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MaPacketErrorIndication.Dummydataref2; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeResetRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeResetRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeResetConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeResetConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetRequest.MibAttribute; - aDataRef[numRefs++] = &aSignal->u.MlmeGetRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetConfirm.MibAttributeValue; - aDataRef[numRefs++] = &aSignal->u.MlmeGetConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetRequest.MibAttributeValue; - aDataRef[numRefs++] = &aSignal->u.MlmeSetRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetConfirm.MibAttributeValue; - aDataRef[numRefs++] = &aSignal->u.MlmeSetConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetNextRequest.MibAttribute; - aDataRef[numRefs++] = &aSignal->u.MlmeGetNextRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetNextConfirm.MibAttributeValue; - aDataRef[numRefs++] = &aSignal->u.MlmeGetNextConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmePowermgtRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmePowermgtRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmePowermgtConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmePowermgtConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeScanRequest.ChannelList; - aDataRef[numRefs++] = &aSignal->u.MlmeScanRequest.InformationElements; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeScanConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeScanConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureRequest.MeasurementRequestSet; - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureIndication.MeasurementReportSet; - aDataRef[numRefs++] = &aSignal->u.MlmeMeasureIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysRequest.Key; - aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetkeysConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDeletekeysConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanLossIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanLossIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeConnectedIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeConnectedIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeScanCancelRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeScanCancelRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeHlSyncCancelConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddPeriodicConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelPeriodicConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanRequest.ChannelList; - aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanRequest.InformationElements; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddAutonomousScanConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelAutonomousScanConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterRequest.InformationElements; - aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetPacketFilterConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStopMeasureConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmePauseAutonomousScanConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanDoneIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAutonomousScanDoneIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetRequest.MibAttribute; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTriggeredGetConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelTriggeredGetConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeTriggeredGetIndication.MibAttributeValue; - aDataRef[numRefs++] = &aSignal->u.MlmeTriggeredGetIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddBlackoutConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeBlackoutEndedIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeBlackoutEndedIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelBlackoutConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerRequest.InformationElements; - aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddRxTriggerConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelRxTriggerConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusRequest.InformationElements; - aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeConnectStatusConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterRequest.Data; - aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeModifyBssParameterConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateRequest.Data1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateRequest.Data2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTemplateConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeConfigQueueConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddTspecConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeDelTspecConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStartAggregationConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeBlockackErrorIndication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeBlockackErrorIndication.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeStopAggregationConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSmStartRequest.Beacon; - aDataRef[numRefs++] = &aSignal->u.MlmeSmStartRequest.BssParameters; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSmStartConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSmStartConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeLeaveRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeLeaveRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeLeaveConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeLeaveConfirm.Dummydataref2; - break; -#endif - case CSR_MLME_SET_TIM_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetTimRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetTimRequest.Dummydataref2; - break; - case CSR_MLME_SET_TIM_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetTimConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetTimConfirm.Dummydataref2; - break; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeGetKeySequenceConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelRequest.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeSetChannelConfirm.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressRequest.Data; - aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressRequest.Dummydataref2; - break; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressConfirm.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.MlmeAddMulticastAddressConfirm.Dummydataref2; - break; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.DebugStringIndication.DebugMessage; - aDataRef[numRefs++] = &aSignal->u.DebugStringIndication.Dummydataref2; - break; - case CSR_DEBUG_WORD16_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.DebugWord16Indication.Dummydataref1; - aDataRef[numRefs++] = &aSignal->u.DebugWord16Indication.Dummydataref2; - break; - case CSR_DEBUG_GENERIC_REQUEST_ID: - aDataRef[numRefs++] = &aSignal->u.DebugGenericRequest.DebugVariable; - aDataRef[numRefs++] = &aSignal->u.DebugGenericRequest.Dummydataref2; - break; - case CSR_DEBUG_GENERIC_CONFIRM_ID: - aDataRef[numRefs++] = &aSignal->u.DebugGenericConfirm.DebugVariable; - aDataRef[numRefs++] = &aSignal->u.DebugGenericConfirm.Dummydataref2; - break; - case CSR_DEBUG_GENERIC_INDICATION_ID: - aDataRef[numRefs++] = &aSignal->u.DebugGenericIndication.DebugVariable; - aDataRef[numRefs++] = &aSignal->u.DebugGenericIndication.Dummydataref2; - break; - default: - return 0; - } - return numRefs; -} - - -u32 SigGetFilterPos(u16 aSigID) -{ - switch (aSigID) - { - case CSR_MA_PACKET_REQUEST_ID: - return 0x00000001; - case CSR_MA_PACKET_CONFIRM_ID: - return 0x00000002; - case CSR_MA_PACKET_INDICATION_ID: - return 0x00000004; - case CSR_MA_PACKET_CANCEL_REQUEST_ID: - return 0x00000008; - case CSR_MA_VIF_AVAILABILITY_RESPONSE_ID: - return 0x00000010; - case CSR_MA_VIF_AVAILABILITY_INDICATION_ID: - return 0x00000020; - case CSR_MA_PACKET_ERROR_INDICATION_ID: - return 0x00000040; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_REQUEST_ID: - return 0x00000080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_RESET_CONFIRM_ID: - return 0x00000100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_REQUEST_ID: - return 0x00000200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_CONFIRM_ID: - return 0x00000400; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_REQUEST_ID: - return 0x00000800; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CONFIRM_ID: - return 0x00001000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_REQUEST_ID: - return 0x00002000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_NEXT_CONFIRM_ID: - return 0x00004000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_REQUEST_ID: - return 0x00008000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_POWERMGT_CONFIRM_ID: - return 0x00010001; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_REQUEST_ID: - return 0x00010002; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CONFIRM_ID: - return 0x00010004; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_REQUEST_ID: - return 0x00010008; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CONFIRM_ID: - return 0x00010010; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_REQUEST_ID: - return 0x00010020; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_CONFIRM_ID: - return 0x00010040; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MEASURE_INDICATION_ID: - return 0x00010080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_REQUEST_ID: - return 0x00010100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SETKEYS_CONFIRM_ID: - return 0x00010200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_REQUEST_ID: - return 0x00010400; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - return 0x00010800; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID: - return 0x00011000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECTED_INDICATION_ID: - return 0x00012000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SCAN_CANCEL_REQUEST_ID: - return 0x00014000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID: - return 0x00018000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - return 0x00020001; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_REQUEST_ID: - return 0x00020002; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - return 0x00020004; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_REQUEST_ID: - return 0x00020008; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - return 0x00020010; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID: - return 0x00020020; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - return 0x00020040; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID: - return 0x00020080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - return 0x00020100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_REQUEST_ID: - return 0x00020200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - return 0x00020400; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_REQUEST_ID: - return 0x00020800; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - return 0x00021000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID: - return 0x00022000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - return 0x00024000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID: - return 0x00028000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID: - return 0x00030001; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - return 0x00030002; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID: - return 0x00030004; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - return 0x00030008; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_TRIGGERED_GET_INDICATION_ID: - return 0x00030010; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_REQUEST_ID: - return 0x00030020; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - return 0x00030040; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLACKOUT_ENDED_INDICATION_ID: - return 0x00030080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_REQUEST_ID: - return 0x00030100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - return 0x00030200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID: - return 0x00030400; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - return 0x00030800; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID: - return 0x00031000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - return 0x00032000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_REQUEST_ID: - return 0x00034000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - return 0x00038000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID: - return 0x00040001; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - return 0x00040002; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_REQUEST_ID: - return 0x00040004; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - return 0x00040008; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_REQUEST_ID: - return 0x00040010; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - return 0x00040020; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_REQUEST_ID: - return 0x00040040; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - return 0x00040080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_REQUEST_ID: - return 0x00040100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - return 0x00040200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_REQUEST_ID: - return 0x00040400; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - return 0x00040800; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_BLOCKACK_ERROR_INDICATION_ID: - return 0x00041000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_REQUEST_ID: - return 0x00042000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - return 0x00044000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_REQUEST_ID: - return 0x00048000; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SM_START_CONFIRM_ID: - return 0x00050001; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_REQUEST_ID: - return 0x00050002; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_LEAVE_CONFIRM_ID: - return 0x00050004; -#endif - case CSR_MLME_SET_TIM_REQUEST_ID: - return 0x00050008; - case CSR_MLME_SET_TIM_CONFIRM_ID: - return 0x00050010; -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID: - return 0x00050020; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - return 0x00050040; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_REQUEST_ID: - return 0x00050080; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - return 0x00050100; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID: - return 0x00050200; -#endif -#ifdef CSR_WIFI_HIP_FULL_SIGNAL_SET - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - return 0x00050400; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - return 0x00050800; - case CSR_DEBUG_WORD16_INDICATION_ID: - return 0x00051000; - case CSR_DEBUG_GENERIC_REQUEST_ID: - return 0x00052000; - case CSR_DEBUG_GENERIC_CONFIRM_ID: - return 0x00054000; - case CSR_DEBUG_GENERIC_INDICATION_ID: - return 0x00058000; - default: - break; - } - return 0xffffffff; -} - - diff --git a/drivers/staging/csr/csr_wifi_hip_signals.h b/drivers/staging/csr/csr_wifi_hip_signals.h deleted file mode 100644 index ca4d0774195c..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_signals.h +++ /dev/null @@ -1,128 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - ***************************************************************************** - * - * FILE: csr_wifi_hip_signals.h - * - * PURPOSE: - * Header file wrapping the auto-generated code in csr_wifi_hip_sigs.h - * and csr_wifi_hip_signals.c - - * csr_wifi_hip_sigs.h provides structures defining UniFi signals and - * csr_wifi_hip_signals.c provides SigGetSize() and SigGetDataRefs(). - * - ***************************************************************************** - */ -#ifndef __CSR_WIFI_HIP_SIGNALS_H__ -#define __CSR_WIFI_HIP_SIGNALS_H__ - -#include -#include "csr_wifi_hip_sigs.h" - - -/****************************************************************************/ -/* INFORMATION ELEMENTS */ -/****************************************************************************/ - -/* Information Element ID's - shouldn't be in here, but nowhere better yet */ -#define IE_SSID_ID 0 -#define IE_SUPPORTED_RATES_ID 1 -#define IE_FH_PARAM_SET_ID 2 -#define IE_DS_PARAM_SET_ID 3 -#define IE_CF_PARAM_SET_ID 4 -#define IE_TIM_ID 5 -#define IE_IBSS_PARAM_SET_ID 6 -#define IE_COUNTRY_ID 7 -#define IE_HOPPING_PATTERN_PARAMS_ID 8 -#define IE_HOPPING_PATTERN_TABLE_ID 9 -#define IE_REQUEST_ID 10 -#define IE_QBSS_LOAD_ID 11 -#define IE_EDCA_PARAM_SET_ID 12 -#define IE_TRAFFIC_SPEC_ID 13 -#define IE_TRAFFIC_CLASS_ID 14 -#define IE_SCHEDULE_ID 15 -#define IE_CHALLENGE_TEXT_ID 16 -#define IE_POWER_CONSTRAINT_ID 32 -#define IE_POWER_CAPABILITY_ID 33 -#define IE_TPC_REQUEST_ID 34 -#define IE_TPC_REPORT_ID 35 -#define IE_SUPPORTED_CHANNELS_ID 36 -#define IE_CHANNEL_SWITCH_ANNOUNCE_ID 37 -#define IE_MEASUREMENT_REQUEST_ID 38 -#define IE_MEASUREMENT_REPORT_ID 39 -#define IE_QUIET_ID 40 -#define IE_IBSS_DFS_ID 41 -#define IE_ERP_INFO_ID 42 -#define IE_TS_DELAY_ID 43 -#define IE_TCLAS_PROCESSING_ID 44 -#define IE_QOS_CAPABILITY_ID 46 -#define IE_RSN_ID 48 -#define IE_EXTENDED_SUPPORTED_RATES_ID 50 -#define IE_AP_CHANNEL_REPORT_ID 52 -#define IE_RCPI_ID 53 -#define IE_WPA_ID 221 - - -/* The maximum number of data references in a signal structure */ -#define UNIFI_MAX_DATA_REFERENCES 2 - -/* The space to allow for a wire-format signal structure */ -#define UNIFI_PACKED_SIGBUF_SIZE 64 - - -/******************************************************************************/ -/* SIGNAL PARAMETER VALUES */ -/******************************************************************************/ - -/* ifIndex */ -#define UNIFI_IF_2G4 1 -#define UNIFI_IF_5G 2 - -/* SendProcessId */ -#define HOST_PROC_ID 0xc000 - -#define SIG_CAP_ESS 0x0001 -#define SIG_CAP_IBSS 0x0002 -#define SIG_CAP_CF_POLLABLE 0x0004 -#define SIG_CAP_CF_POLL_REQUEST 0x0008 -#define SIG_CAP_PRIVACY 0x0010 -#define SIG_CAP_SHORT_PREAMBLE 0x0020 -#define SIG_CAP_DSSSOFDM 0x2000 - -/******************************************************************************/ -/* FUNCTION DECLARATIONS */ -/******************************************************************************/ - -/****************************************************************************** - * SigGetNumDataRefs - Retrieve pointers to data-refs from a signal. - * - * PARAMETERS: - * aSignal - Pointer to signal to retrieve the data refs of. - * aDataRef - Address of a pointer to the structure that the data refs - * pointers will be stored. - * - * RETURNS: - * The number of data-refs in the signal. - */ -s32 SigGetDataRefs(CSR_SIGNAL *aSignal, CSR_DATAREF **aDataRef); - -/****************************************************************************** - * SigGetSize - Retrieve the size (in bytes) of a given signal. - * - * PARAMETERS: - * aSignal - Pointer to signal to retrieve size of. - * - * RETURNS: - * The size (in bytes) of the given signal. - */ -s32 SigGetSize(const CSR_SIGNAL *aSignal); - -#endif /* __CSR_WIFI_HIP_SIGNALS_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_sigs.h b/drivers/staging/csr/csr_wifi_hip_sigs.h deleted file mode 100644 index 6112cc3e87fa..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_sigs.h +++ /dev/null @@ -1,1417 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - - -/* Generated by hip_dd_l_h_gen.pl */ - -#ifndef CSR_WIFI_HIP_SIGS_H -#define CSR_WIFI_HIP_SIGS_H - -typedef s16 csr_place_holding_type; - -typedef u16 CSR_ASSOCIATION_ID; - -typedef u16 CSR_AUTONOMOUS_SCAN_ID; - -typedef u16 CSR_BEACON_PERIODS; - -typedef u16 CSR_BLACKOUT_ID; - -typedef enum CSR_BLACKOUT_SOURCE -{ - CSR_DOT11_LOCAL = 0x0000, - CSR_DOT11_REMOTE = 0x0001, - CSR_OTHER_RADIO = 0x0002, - CSR_NOT_LINKED = 0x0004 -} CSR_BLACKOUT_SOURCE; - -typedef enum CSR_BLACKOUT_TYPE -{ - CSR_LOCAL_DEVICE_ONLY = 0x0001, - CSR_SPECIFIED_PEER = 0x0002, - CSR_CURRENT_CHANNEL = 0x0004, - CSR_P2P = 0x0008 -} CSR_BLACKOUT_TYPE; - -typedef enum CSR_BOOT_LOADER_OPERATION -{ - CSR_BOOT_LOADER_IDLE = 0x00, - CSR_BOOT_LOADER_RESTART = 0x01, - CSR_BOOT_LOADER_PATCH = 0x02, - CSR_BOOT_LOADER_IMAGE_0 = 0x10, - CSR_BOOT_LOADER_IMAGE_1 = 0x11, - CSR_BOOT_LOADER_IMAGE_2 = 0x12, - CSR_BOOT_LOADER_IMAGE_3 = 0x13 -} CSR_BOOT_LOADER_OPERATION; - -typedef u16 CSR_CAPABILITY_INFORMATION; - -typedef u16 CSR_CHANNEL_STARTING_FACTOR; - -typedef u32 CSR_CIPHER_SUITE_SELECTOR; - -typedef u32 CSR_CLIENT_TAG; - -typedef enum CSR_CONNECTION_STATUS -{ - CSR_DISCONNECTED = 0x0000, - CSR_CONNECTED_AWAKE = 0x0001 -} CSR_CONNECTION_STATUS; - -typedef s16 CSR_DECIBELS; - -typedef enum CSR_DIRECTION -{ - CSR_TRANSMIT = 0x0000, - CSR_RECEIVE = 0x0001, - CSR_BIDIRECTIONAL = 0x0003 -} CSR_DIRECTION; - -typedef enum CSR_FRAME_TYPE -{ - CSR_RESERVED = 0x0000, - CSR_BEACON = 0x0001, - CSR_PROBE_RESPONSE = 0x0002, - CSR_BEACON_AND_PROBE_RESPONSE = 0x0003, - CSR_PROBE_REQUEST = 0x0004 -} CSR_FRAME_TYPE; - -typedef u32 CSR_IPV4_ADDRESS; - -typedef enum CSR_IFINTERFACE -{ - CSR_INDEX_2G4 = 0x0001, - CSR_INDEX_5G = 0x0002 -} CSR_IFINTERFACE; - -typedef enum CSR_KEY_TYPE -{ - CSR_GROUP = 0x0000, - CSR_PAIRWISE = 0x0001, - CSR_PEER_KEY = 0x0002, - CSR_IGTK = 0x0003 -} CSR_KEY_TYPE; - -typedef enum CSR_LOADER_OPERATION -{ - CSR_LOADER_IDLE = 0x0000, - CSR_LOADER_COPY = 0x0001 -} CSR_LOADER_OPERATION; - -typedef struct CSR_MAC_ADDRESS -{ - u8 x[6]; -} CSR_MACADDRESS; - -typedef enum CSR_MIB_STATUS -{ - CSR_MIB_SUCCESSFUL = 0x0000, - CSR_MIB_INVALID_PARAMETERS = 0x0001, - CSR_MIB_WRITE_ONLY = 0x0002, - CSR_MIB_READ_ONLY = 0x0003 -} CSR_MIB_STATUS; - -typedef enum CSR_MEMORY_SPACE -{ - CSR_NONE = 0x00, - CSR_SHARED_DATA_MEMORY = 0x01, - CSR_EXTERNAL_FLASH_MEMORY = 0x02, - CSR_EXTERNAL_SRAM = 0x03, - CSR_REGISTERS = 0x04, - CSR_PHY_PROCESSOR_DATA_MEMORY = 0x10, - CSR_PHY_PROCESSOR_PROGRAM_MEMORY = 0x11, - CSR_PHY_PROCESSOR_ROM = 0x12, - CSR_MAC_PROCESSOR_DATA_MEMORY = 0x20, - CSR_MAC_PROCESSOR_PROGRAM_MEMORY = 0x21, - CSR_MAC_PROCESSOR_ROM = 0x22, - CSR_BT_PROCESSOR_DATA_MEMORY = 0x30, - CSR_BT_PROCESSOR_PROGRAM_MEMORY = 0x31, - CSR_BT_PROCESSOR_ROM = 0x32 -} CSR_MEMORY_SPACE; - -typedef u16 CSR_MICROSECONDS16; - -typedef u32 CSR_MICROSECONDS32; - -typedef u16 CSR_NATURAL16; - -typedef enum CSR_PS_SCHEME -{ - CSR_LEGACY_PS = 0x0001, - CSR_U_APSD = 0x0002, - CSR_S_APSD = 0x0004 -} CSR_PS_SCHEME; - -typedef enum CSR_PACKET_FILTER_MODE -{ - CSR_PFM_OPT_OUT = 0x0000, - CSR_PFM_OPT_IN = 0x0003 -} CSR_PACKET_FILTER_MODE; - -typedef u16 CSR_PERIODIC_ID; - -typedef enum CSR_PERIODIC_SCHEDULING_MODE -{ - CSR_PSM_PERIODIC_SCHEDULE_PS_POLL = 0x0001, - CSR_PSM_PERIODIC_SCHEDULE_PM_BIT = 0x0002, - CSR_PSM_PERIODIC_SCHEDULE_UAPSD = 0x0004, - CSR_PSM_PERIODIC_SCHEDULE_SAPSD = 0x0008 -} CSR_PERIODIC_SCHEDULING_MODE; - -typedef enum CSR_POWER_MANAGEMENT_MODE -{ - CSR_PMM_ACTIVE_MODE = 0x0000, - CSR_PMM_POWER_SAVE = 0x0001, - CSR_PMM_FAST_POWER_SAVE = 0x0002 -} CSR_POWER_MANAGEMENT_MODE; - -typedef enum CSR_PRIORITY -{ - CSR_QOS_UP0 = 0x0000, - CSR_QOS_UP1 = 0x0001, - CSR_QOS_UP2 = 0x0002, - CSR_QOS_UP3 = 0x0003, - CSR_QOS_UP4 = 0x0004, - CSR_QOS_UP5 = 0x0005, - CSR_QOS_UP6 = 0x0006, - CSR_QOS_UP7 = 0x0007, - CSR_CONTENTION = 0x8000, - CSR_MANAGEMENT = 0x8010 -} CSR_PRIORITY; - -typedef enum CSR_REASON_CODE -{ - CSR_UNSPECIFIED_REASON = 0x0001, - CSR_INVALID_INFORMATION_ELEMENT = 0x000d, - CSR_QOS_UNSPECIFIED_REASON = 0x0020, - CSR_QOS_EXCESSIVE_NOT_ACK = 0x0022, - CSR_QOS_TXOP_LIMIT_EXCEEDED = 0x0023, - CSR_QSTA_LEAVING = 0x0024, - CSR_UNKNOWN_BA = 0x0026, - CSR_UNKNOWN_TS = 0x0026, - CSR_TIMEOUT = 0x0027 -} CSR_REASON_CODE; - -typedef enum CSR_RECEPTION_STATUS -{ - CSR_RX_SUCCESS = 0x0000, - CSR_RX_FAILURE_UNSPECIFIED = 0x0001, - CSR_MICHAEL_MIC_ERROR = 0x0002, - CSR_DECRYPTION_ERROR = 0x0003, - CSR_NO_TEMPORAL_KEY_AVAILABLE = 0x0004, - CSR_UNSUPPORTED_MODULATION = 0x0011, - CSR_BAD_FCS = 0x0012, - CSR_BAD_SIGNAL = 0x0013 -} CSR_RECEPTION_STATUS; - -typedef enum CSR_RESULT_CODE -{ - CSR_RC_SUCCESS = 0x0000, - CSR_RC_UNSPECIFIED_FAILURE = 0x0001, - CSR_RC_REFUSED = 0x0003, - CSR_RC_INVALID_PARAMETERS = 0x0026, - CSR_RC_REJECTED_INVALID_IE = 0x0028, - CSR_RC_REJECTED_INVALID_GROUP_CIPHER = 0x0029, - CSR_RC_REJECTED_INVALID_PAIRWISE_CIPHER = 0x002a, - CSR_RC_TIMEOUT = 0x8000, - CSR_RC_TOO_MANY_SIMULTANEOUS_REQUESTS = 0x8001, - CSR_RC_BSS_ALREADY_STARTED_OR_JOINED = 0x8002, - CSR_RC_NOT_SUPPORTED = 0x8003, - CSR_RC_TRANSMISSION_FAILURE = 0x8004, - CSR_RC_RESET_REQUIRED_BEFORE_START = 0x8006, - CSR_RC_INSUFFICIENT_RESOURCE = 0x8007, - CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES = 0x8008, - CSR_RC_INVALID_UNICAST_CIPHER = 0xf02f, - CSR_RC_INVALID_MULTICAST_CIPHER = 0xf030 -} CSR_RESULT_CODE; - -typedef enum CSR_SCAN_TYPE -{ - CSR_SC_ACTIVE_SCAN = 0x0000, - CSR_SC_PASSIVE_SCAN = 0x0001 -} CSR_SCAN_TYPE; - -typedef enum CSR_SIGNAL_ID -{ - CSR_MA_PACKET_REQUEST_ID = 0x0110, - CSR_MA_PACKET_CONFIRM_ID = 0x0111, - CSR_MA_PACKET_INDICATION_ID = 0x0113, - CSR_MA_PACKET_CANCEL_REQUEST_ID = 0x0114, - CSR_MA_VIF_AVAILABILITY_RESPONSE_ID = 0x0116, - CSR_MA_VIF_AVAILABILITY_INDICATION_ID = 0x0117, - CSR_MA_PACKET_ERROR_INDICATION_ID = 0x011b, - CSR_MLME_RESET_REQUEST_ID = 0x0200, - CSR_MLME_RESET_CONFIRM_ID = 0x0201, - CSR_MLME_GET_REQUEST_ID = 0x0204, - CSR_MLME_GET_CONFIRM_ID = 0x0205, - CSR_MLME_SET_REQUEST_ID = 0x0208, - CSR_MLME_SET_CONFIRM_ID = 0x0209, - CSR_MLME_GET_NEXT_REQUEST_ID = 0x020c, - CSR_MLME_GET_NEXT_CONFIRM_ID = 0x020d, - CSR_MLME_POWERMGT_REQUEST_ID = 0x0210, - CSR_MLME_POWERMGT_CONFIRM_ID = 0x0211, - CSR_MLME_SCAN_REQUEST_ID = 0x0214, - CSR_MLME_SCAN_CONFIRM_ID = 0x0215, - CSR_MLME_HL_SYNC_REQUEST_ID = 0x0244, - CSR_MLME_HL_SYNC_CONFIRM_ID = 0x0245, - CSR_MLME_MEASURE_REQUEST_ID = 0x0258, - CSR_MLME_MEASURE_CONFIRM_ID = 0x0259, - CSR_MLME_MEASURE_INDICATION_ID = 0x025b, - CSR_MLME_SETKEYS_REQUEST_ID = 0x0268, - CSR_MLME_SETKEYS_CONFIRM_ID = 0x0269, - CSR_MLME_DELETEKEYS_REQUEST_ID = 0x026c, - CSR_MLME_DELETEKEYS_CONFIRM_ID = 0x026d, - CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION_ID = 0x0287, - CSR_MLME_CONNECTED_INDICATION_ID = 0x028b, - CSR_MLME_SCAN_CANCEL_REQUEST_ID = 0x028c, - CSR_MLME_HL_SYNC_CANCEL_REQUEST_ID = 0x0298, - CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID = 0x0299, - CSR_MLME_ADD_PERIODIC_REQUEST_ID = 0x02a0, - CSR_MLME_ADD_PERIODIC_CONFIRM_ID = 0x02a1, - CSR_MLME_DEL_PERIODIC_REQUEST_ID = 0x02a4, - CSR_MLME_DEL_PERIODIC_CONFIRM_ID = 0x02a5, - CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST_ID = 0x02a8, - CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02a9, - CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST_ID = 0x02ac, - CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02ad, - CSR_MLME_SET_PACKET_FILTER_REQUEST_ID = 0x02b8, - CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID = 0x02b9, - CSR_MLME_STOP_MEASURE_REQUEST_ID = 0x02bc, - CSR_MLME_STOP_MEASURE_CONFIRM_ID = 0x02bd, - CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST_ID = 0x02cc, - CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID = 0x02cd, - CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION_ID = 0x02db, - CSR_MLME_ADD_TRIGGERED_GET_REQUEST_ID = 0x02dc, - CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID = 0x02dd, - CSR_MLME_DEL_TRIGGERED_GET_REQUEST_ID = 0x02e0, - CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID = 0x02e1, - CSR_MLME_TRIGGERED_GET_INDICATION_ID = 0x02e7, - CSR_MLME_ADD_BLACKOUT_REQUEST_ID = 0x02f8, - CSR_MLME_ADD_BLACKOUT_CONFIRM_ID = 0x02f9, - CSR_MLME_BLACKOUT_ENDED_INDICATION_ID = 0x02fb, - CSR_MLME_DEL_BLACKOUT_REQUEST_ID = 0x02fc, - CSR_MLME_DEL_BLACKOUT_CONFIRM_ID = 0x02fd, - CSR_MLME_ADD_RX_TRIGGER_REQUEST_ID = 0x0304, - CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID = 0x0305, - CSR_MLME_DEL_RX_TRIGGER_REQUEST_ID = 0x0308, - CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID = 0x0309, - CSR_MLME_CONNECT_STATUS_REQUEST_ID = 0x0310, - CSR_MLME_CONNECT_STATUS_CONFIRM_ID = 0x0311, - CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST_ID = 0x0314, - CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID = 0x0315, - CSR_MLME_ADD_TEMPLATE_REQUEST_ID = 0x0318, - CSR_MLME_ADD_TEMPLATE_CONFIRM_ID = 0x0319, - CSR_MLME_CONFIG_QUEUE_REQUEST_ID = 0x031c, - CSR_MLME_CONFIG_QUEUE_CONFIRM_ID = 0x031d, - CSR_MLME_ADD_TSPEC_REQUEST_ID = 0x0320, - CSR_MLME_ADD_TSPEC_CONFIRM_ID = 0x0321, - CSR_MLME_DEL_TSPEC_REQUEST_ID = 0x0324, - CSR_MLME_DEL_TSPEC_CONFIRM_ID = 0x0325, - CSR_MLME_START_AGGREGATION_REQUEST_ID = 0x0328, - CSR_MLME_START_AGGREGATION_CONFIRM_ID = 0x0329, - CSR_MLME_BLOCKACK_ERROR_INDICATION_ID = 0x032b, - CSR_MLME_STOP_AGGREGATION_REQUEST_ID = 0x032c, - CSR_MLME_STOP_AGGREGATION_CONFIRM_ID = 0x032d, - CSR_MLME_SM_START_REQUEST_ID = 0x0334, - CSR_MLME_SM_START_CONFIRM_ID = 0x0335, - CSR_MLME_LEAVE_REQUEST_ID = 0x0338, - CSR_MLME_LEAVE_CONFIRM_ID = 0x0339, - CSR_MLME_SET_TIM_REQUEST_ID = 0x033c, - CSR_MLME_SET_TIM_CONFIRM_ID = 0x033d, - CSR_MLME_GET_KEY_SEQUENCE_REQUEST_ID = 0x0340, - CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID = 0x0341, - CSR_MLME_SET_CHANNEL_REQUEST_ID = 0x034c, - CSR_MLME_SET_CHANNEL_CONFIRM_ID = 0x034d, - CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST_ID = 0x040c, - CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID = 0x040d, - CSR_DEBUG_STRING_INDICATION_ID = 0x0803, - CSR_DEBUG_WORD16_INDICATION_ID = 0x0807, - CSR_DEBUG_GENERIC_REQUEST_ID = 0x0808, - CSR_DEBUG_GENERIC_CONFIRM_ID = 0x0809, - CSR_DEBUG_GENERIC_INDICATION_ID = 0x080b -} CSR_SIGNAL_ID; - -typedef u16 CSR_SIMPLE_POINTER; - -typedef u16 CSR_STARTING_SEQUENCE_NUMBER; - -typedef enum CSR_SYMBOL_ID -{ - CSR_SLT_END = 0x0000, - CSR_SLT_PCI_SLOT_CONFIG = 0x0001, - CSR_SLT_SDIO_SLOT_CONFIG = 0x0002, - CSR_SLT_BUILD_ID_NUMBER = 0x0003, - CSR_SLT_BUILD_ID_STRING = 0x0004, - CSR_SLT_PERSISTENT_STORE_DB = 0x0005, - CSR_SLT_RESET_VECTOR_PHY = 0x0006, - CSR_SLT_RESET_VECTOR_MAC = 0x0007, - CSR_SLT_SDIO_LOADER_CONTROL = 0x0008, - CSR_SLT_TEST_CMD = 0x0009, - CSR_SLT_TEST_ALIVE_COUNTER = 0x000a, - CSR_SLT_TEST_PARAMETERS = 0x000b, - CSR_SLT_TEST_RESULTS = 0x000c, - CSR_SLT_TEST_VERSION = 0x000d, - CSR_SLT_MIB_PSID_RANGES = 0x000e, - CSR_SLT_KIP_TABLE = 0x000f, - CSR_SLT_PANIC_DATA_PHY = 0x0010, - CSR_SLT_PANIC_DATA_MAC = 0x0011, - CSR_SLT_BOOT_LOADER_CONTROL = 0x0012, - CSR_SLT_SOFT_MAC = 0x0013 -} CSR_SYMBOL_ID; - -typedef struct CSR_TSF_TIME -{ - u8 x[8]; -} CSR_TSF_TIME; - -typedef u16 CSR_TIME_UNITS; - -typedef enum CSR_TRANSMISSION_CONTROL -{ - CSR_TRIGGERED = 0x0001, - CSR_END_OF_SERVICE = 0x0002, - CSR_NO_CONFIRM_REQUIRED = 0x0004, - CSR_ALLOW_BA = 0x0008 -} CSR_TRANSMISSION_CONTROL; - -typedef enum CSR_TRANSMISSION_STATUS -{ - CSR_TX_SUCCESSFUL = 0x0000, - CSR_TX_RETRY_LIMIT = 0x0001, - CSR_TX_LIFETIME = 0x0002, - CSR_TX_NO_BSS = 0x0003, - CSR_TX_EXCESSIVE_DATA_LENGTH = 0x0004, - CSR_TX_UNSUPPORTED_PRIORITY = 0x0006, - CSR_TX_UNAVAILABLE_PRIORITY = 0x0007, - CSR_TX_UNAVAILABLE_KEY_MAPPING = 0x000a, - CSR_TX_EDCA_TIMEOUT = 0x000b, - CSR_TX_BLOCK_ACK_TIMEOUT = 0x000c, - CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED = 0x000d, - CSR_TX_REJECTED_PEER_STATION_SLEEPING = 0x000e, - CSR_TX_REJECTED_DTIM_ENDED = 0x000f, - CSR_TX_REJECTED_DTIM_STARTED = 0x0010 -} CSR_TRANSMISSION_STATUS; - -typedef u16 CSR_TRIGGER_ID; - -typedef u16 CSR_TRIGGERED_ID; - -typedef enum CSR_HIP_VERSIONS -{ - CSR_HIP_ENG_VERSION = 0x0001, - CSR_HIP_VERSION = 0x0900 -} CSR_HIP_VERSIONS; - -typedef u16 CSR_BUFFER_HANDLE; - -typedef u16 CSR_CHANNEL_NUMBER; - -typedef struct CSR_DATA_REFERENCE -{ - u16 SlotNumber; - u16 DataLength; -} CSR_DATAREF; - -typedef u16 CSR_DIALOG_TOKEN; - -typedef struct CSR_GENERIC_POINTER -{ - u32 MemoryOffset; - CSR_MEMORY_SPACE MemorySpace; -} CSR_GENERIC_POINTER; - -typedef struct CSR_MLME_CONFIG_QUEUE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_CONFIG_QUEUE_CONFIRM; - -typedef struct CSR_MLME_CONFIG_QUEUE_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_NATURAL16 QueueIndex; - CSR_NATURAL16 Aifs; - CSR_NATURAL16 Cwmin; - CSR_NATURAL16 Cwmax; - CSR_NATURAL16 TxopLimit; -} CSR_MLME_CONFIG_QUEUE_REQUEST; - -typedef struct CSR_MLME_GET_CONFIRM -{ - CSR_DATAREF MibAttributeValue; - CSR_DATAREF Dummydataref2; - CSR_MIB_STATUS Status; - CSR_NATURAL16 ErrorIndex; -} CSR_MLME_GET_CONFIRM; - -typedef struct CSR_MLME_GET_REQUEST -{ - CSR_DATAREF MibAttribute; - CSR_DATAREF Dummydataref2; -} CSR_MLME_GET_REQUEST; - -typedef struct CSR_MLME_GET_NEXT_CONFIRM -{ - CSR_DATAREF MibAttributeValue; - CSR_DATAREF Dummydataref2; - CSR_MIB_STATUS Status; - CSR_NATURAL16 ErrorIndex; -} CSR_MLME_GET_NEXT_CONFIRM; - -typedef struct CSR_MLME_GET_NEXT_REQUEST -{ - CSR_DATAREF MibAttribute; - CSR_DATAREF Dummydataref2; -} CSR_MLME_GET_NEXT_REQUEST; - -typedef struct CSR_MLME_HL_SYNC_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_MACADDRESS GroupAddress; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_HL_SYNC_CONFIRM; - -typedef struct CSR_MLME_HL_SYNC_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_MACADDRESS GroupAddress; -} CSR_MLME_HL_SYNC_REQUEST; - -typedef struct CSR_MLME_HL_SYNC_CANCEL_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_HL_SYNC_CANCEL_CONFIRM; - -typedef struct CSR_MLME_HL_SYNC_CANCEL_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_MACADDRESS GroupAddress; -} CSR_MLME_HL_SYNC_CANCEL_REQUEST; - -typedef struct CSR_MLME_MEASURE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_RESULT_CODE ResultCode; - CSR_DIALOG_TOKEN DialogToken; -} CSR_MLME_MEASURE_CONFIRM; - -typedef struct CSR_MLME_MEASURE_INDICATION -{ - CSR_DATAREF MeasurementReportSet; - CSR_DATAREF Dummydataref2; - CSR_DIALOG_TOKEN DialogToken; -} CSR_MLME_MEASURE_INDICATION; - -typedef struct CSR_MLME_MEASURE_REQUEST -{ - CSR_DATAREF MeasurementRequestSet; - CSR_DATAREF Dummydataref2; - CSR_DIALOG_TOKEN DialogToken; -} CSR_MLME_MEASURE_REQUEST; - -typedef struct CSR_MLME_RESET_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_RESET_CONFIRM; - -typedef struct CSR_MLME_RESET_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_MACADDRESS StaAddress; - s16 SetDefaultMib; -} CSR_MLME_RESET_REQUEST; - -typedef struct CSR_MLME_SET_CONFIRM -{ - CSR_DATAREF MibAttributeValue; - CSR_DATAREF Dummydataref2; - CSR_MIB_STATUS Status; - CSR_NATURAL16 ErrorIndex; -} CSR_MLME_SET_CONFIRM; - -typedef struct CSR_MLME_SET_REQUEST -{ - CSR_DATAREF MibAttributeValue; - CSR_DATAREF Dummydataref2; -} CSR_MLME_SET_REQUEST; - -typedef struct CSR_MLME_STOP_MEASURE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_RESULT_CODE ResultCode; - CSR_DIALOG_TOKEN DialogToken; -} CSR_MLME_STOP_MEASURE_CONFIRM; - -typedef struct CSR_MLME_STOP_MEASURE_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_DIALOG_TOKEN DialogToken; -} CSR_MLME_STOP_MEASURE_REQUEST; - -typedef u16 CSR_PROCESS_ID; - -typedef u16 CSR_RATE; - -typedef u16 CSR_SEQUENCE_NUMBER; - -typedef struct CSR_SIGNAL_PRIMITIVE_HEADER -{ - s16 SignalId; - CSR_PROCESS_ID ReceiverProcessId; - CSR_PROCESS_ID SenderProcessId; -} CSR_SIGNAL_PRIMITIVE_HEADER; - -typedef u16 CSR_TRAFFIC_WINDOW; - -typedef u16 CSR_VIF_IDENTIFIER; - -typedef struct CSR_DEBUG_GENERIC_CONFIRM -{ - CSR_DATAREF DebugVariable; - CSR_DATAREF Dummydataref2; - CSR_NATURAL16 DebugWords[8]; -} CSR_DEBUG_GENERIC_CONFIRM; - -typedef struct CSR_DEBUG_GENERIC_INDICATION -{ - CSR_DATAREF DebugVariable; - CSR_DATAREF Dummydataref2; - CSR_NATURAL16 DebugWords[8]; -} CSR_DEBUG_GENERIC_INDICATION; - -typedef struct CSR_DEBUG_GENERIC_REQUEST -{ - CSR_DATAREF DebugVariable; - CSR_DATAREF Dummydataref2; - CSR_NATURAL16 DebugWords[8]; -} CSR_DEBUG_GENERIC_REQUEST; - -typedef struct CSR_DEBUG_STRING_INDICATION -{ - CSR_DATAREF DebugMessage; - CSR_DATAREF Dummydataref2; -} CSR_DEBUG_STRING_INDICATION; - -typedef struct CSR_DEBUG_WORD16_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_NATURAL16 DebugWords[16]; -} CSR_DEBUG_WORD16_INDICATION; - -typedef struct CSR_MA_PACKET_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRANSMISSION_STATUS TransmissionStatus; - CSR_NATURAL16 RetryCount; - CSR_RATE Rate; - CSR_CLIENT_TAG HostTag; -} CSR_MA_PACKET_CONFIRM; - -typedef struct CSR_MA_PACKET_INDICATION -{ - CSR_DATAREF Data; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TSF_TIME LocalTime; - CSR_IFINTERFACE Ifindex; - CSR_CHANNEL_NUMBER Channel; - CSR_RECEPTION_STATUS ReceptionStatus; - CSR_DECIBELS Rssi; - CSR_DECIBELS Snr; - CSR_RATE ReceivedRate; -} CSR_MA_PACKET_INDICATION; - -typedef struct CSR_MA_PACKET_REQUEST -{ - CSR_DATAREF Data; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RATE TransmitRate; - CSR_CLIENT_TAG HostTag; - CSR_PRIORITY Priority; - CSR_MACADDRESS Ra; - CSR_TRANSMISSION_CONTROL TransmissionControl; -} CSR_MA_PACKET_REQUEST; - -typedef struct CSR_MA_PACKET_CANCEL_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_CLIENT_TAG HostTag; -} CSR_MA_PACKET_CANCEL_REQUEST; - -typedef struct CSR_MA_PACKET_ERROR_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS PeerQstaAddress; - CSR_PRIORITY UserPriority; - CSR_SEQUENCE_NUMBER SequenceNumber; -} CSR_MA_PACKET_ERROR_INDICATION; - -typedef struct CSR_MA_VIF_AVAILABILITY_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - s16 Multicast; -} CSR_MA_VIF_AVAILABILITY_INDICATION; - -typedef struct CSR_MA_VIF_AVAILABILITY_RESPONSE -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MA_VIF_AVAILABILITY_RESPONSE; - -typedef struct CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; -} CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM; - -typedef struct CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST -{ - CSR_DATAREF ChannelList; - CSR_DATAREF InformationElements; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; - CSR_IFINTERFACE Ifindex; - CSR_CHANNEL_STARTING_FACTOR ChannelStartingFactor; - CSR_SCAN_TYPE ScanType; - CSR_MICROSECONDS32 ProbeDelay; - CSR_TIME_UNITS MinChannelTime; - CSR_TIME_UNITS MaxChannelTime; -} CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST; - -typedef struct CSR_MLME_ADD_BLACKOUT_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_BLACKOUT_ID BlackoutId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_BLACKOUT_CONFIRM; - -typedef struct CSR_MLME_ADD_BLACKOUT_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_BLACKOUT_ID BlackoutId; - CSR_BLACKOUT_TYPE BlackoutType; - CSR_BLACKOUT_SOURCE BlackoutSource; - CSR_MICROSECONDS32 BlackoutStartReference; - CSR_MICROSECONDS32 BlackoutPeriod; - CSR_MICROSECONDS32 BlackoutDuration; - CSR_MACADDRESS PeerStaAddress; - CSR_NATURAL16 BlackoutCount; -} CSR_MLME_ADD_BLACKOUT_REQUEST; - -typedef struct CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM; - -typedef struct CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST -{ - CSR_DATAREF Data; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_NATURAL16 NumberOfMulticastGroupAddresses; -} CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST; - -typedef struct CSR_MLME_ADD_PERIODIC_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PERIODIC_ID PeriodicId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_PERIODIC_CONFIRM; - -typedef struct CSR_MLME_ADD_PERIODIC_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PERIODIC_ID PeriodicId; - CSR_MICROSECONDS32 MaximumLatency; - CSR_PERIODIC_SCHEDULING_MODE PeriodicSchedulingMode; - s16 WakeHost; - CSR_PRIORITY UserPriority; -} CSR_MLME_ADD_PERIODIC_REQUEST; - -typedef struct CSR_MLME_ADD_RX_TRIGGER_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGER_ID TriggerId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_RX_TRIGGER_CONFIRM; - -typedef struct CSR_MLME_ADD_RX_TRIGGER_REQUEST -{ - CSR_DATAREF InformationElements; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGER_ID TriggerId; - CSR_PRIORITY Priority; -} CSR_MLME_ADD_RX_TRIGGER_REQUEST; - -typedef struct CSR_MLME_ADD_TEMPLATE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_FRAME_TYPE FrameType; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_TEMPLATE_CONFIRM; - -typedef struct CSR_MLME_ADD_TEMPLATE_REQUEST -{ - CSR_DATAREF Data1; - CSR_DATAREF Data2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_FRAME_TYPE FrameType; - CSR_RATE MinTransmitRate; -} CSR_MLME_ADD_TEMPLATE_REQUEST; - -typedef struct CSR_MLME_ADD_TRIGGERED_GET_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_TRIGGERED_ID TriggeredId; -} CSR_MLME_ADD_TRIGGERED_GET_CONFIRM; - -typedef struct CSR_MLME_ADD_TRIGGERED_GET_REQUEST -{ - CSR_DATAREF MibAttribute; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGERED_ID TriggeredId; -} CSR_MLME_ADD_TRIGGERED_GET_REQUEST; - -typedef struct CSR_MLME_ADD_TSPEC_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PRIORITY UserPriority; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_ADD_TSPEC_CONFIRM; - -typedef struct CSR_MLME_ADD_TSPEC_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; - CSR_PS_SCHEME PsScheme; - CSR_NATURAL16 MediumTime; - CSR_MICROSECONDS32 ServiceStartTime; - CSR_MICROSECONDS32 ServiceInterval; - CSR_RATE MinimumDataRate; -} CSR_MLME_ADD_TSPEC_REQUEST; - -typedef struct CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; -} CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION; - -typedef struct CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS Bssid; -} CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION; - -typedef struct CSR_MLME_BLACKOUT_ENDED_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_BLACKOUT_ID BlackoutId; -} CSR_MLME_BLACKOUT_ENDED_INDICATION; - -typedef struct CSR_MLME_BLOCKACK_ERROR_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_REASON_CODE ResultCode; - CSR_MACADDRESS PeerQstaAddress; -} CSR_MLME_BLOCKACK_ERROR_INDICATION; - -typedef struct CSR_MLME_CONNECTED_INDICATION -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_CONNECTION_STATUS ConnectionStatus; - CSR_MACADDRESS PeerMacAddress; -} CSR_MLME_CONNECTED_INDICATION; - -typedef struct CSR_MLME_CONNECT_STATUS_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_CONNECT_STATUS_CONFIRM; - -typedef struct CSR_MLME_CONNECT_STATUS_REQUEST -{ - CSR_DATAREF InformationElements; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_CONNECTION_STATUS ConnectionStatus; - CSR_MACADDRESS StaAddress; - CSR_ASSOCIATION_ID AssociationId; - CSR_CAPABILITY_INFORMATION AssociationCapabilityInformation; -} CSR_MLME_CONNECT_STATUS_REQUEST; - -typedef struct CSR_MLME_DELETEKEYS_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_DELETEKEYS_CONFIRM; - -typedef struct CSR_MLME_DELETEKEYS_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_NATURAL16 KeyId; - CSR_KEY_TYPE KeyType; - CSR_MACADDRESS Address; -} CSR_MLME_DELETEKEYS_REQUEST; - -typedef struct CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; -} CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM; - -typedef struct CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; -} CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST; - -typedef struct CSR_MLME_DEL_BLACKOUT_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_BLACKOUT_ID BlackoutId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_DEL_BLACKOUT_CONFIRM; - -typedef struct CSR_MLME_DEL_BLACKOUT_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_BLACKOUT_ID BlackoutId; -} CSR_MLME_DEL_BLACKOUT_REQUEST; - -typedef struct CSR_MLME_DEL_PERIODIC_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PERIODIC_ID PeriodicId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_DEL_PERIODIC_CONFIRM; - -typedef struct CSR_MLME_DEL_PERIODIC_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PERIODIC_ID PeriodicId; -} CSR_MLME_DEL_PERIODIC_REQUEST; - -typedef struct CSR_MLME_DEL_RX_TRIGGER_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGER_ID TriggerId; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_DEL_RX_TRIGGER_CONFIRM; - -typedef struct CSR_MLME_DEL_RX_TRIGGER_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGER_ID TriggerId; -} CSR_MLME_DEL_RX_TRIGGER_REQUEST; - -typedef struct CSR_MLME_DEL_TRIGGERED_GET_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_TRIGGERED_ID TriggeredId; -} CSR_MLME_DEL_TRIGGERED_GET_CONFIRM; - -typedef struct CSR_MLME_DEL_TRIGGERED_GET_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TRIGGERED_ID TriggeredId; -} CSR_MLME_DEL_TRIGGERED_GET_REQUEST; - -typedef struct CSR_MLME_DEL_TSPEC_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PRIORITY UserPriority; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_DEL_TSPEC_CONFIRM; - -typedef struct CSR_MLME_DEL_TSPEC_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; -} CSR_MLME_DEL_TSPEC_REQUEST; - -typedef struct CSR_MLME_GET_KEY_SEQUENCE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_NATURAL16 SequenceNumber[8]; -} CSR_MLME_GET_KEY_SEQUENCE_CONFIRM; - -typedef struct CSR_MLME_GET_KEY_SEQUENCE_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_NATURAL16 KeyId; - CSR_KEY_TYPE KeyType; - CSR_MACADDRESS Address; -} CSR_MLME_GET_KEY_SEQUENCE_REQUEST; - -typedef struct CSR_MLME_LEAVE_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_LEAVE_CONFIRM; - -typedef struct CSR_MLME_LEAVE_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; -} CSR_MLME_LEAVE_REQUEST; - -typedef struct CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM; - -typedef struct CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST -{ - CSR_DATAREF Data; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_TIME_UNITS BeaconPeriod; - CSR_BEACON_PERIODS DtimPeriod; - CSR_CAPABILITY_INFORMATION CapabilityInformation; - CSR_MACADDRESS Bssid; - CSR_NATURAL16 RtsThreshold; -} CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST; - -typedef struct CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; -} CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM; - -typedef struct CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_AUTONOMOUS_SCAN_ID AutonomousScanId; - s16 Pause; -} CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST; - -typedef struct CSR_MLME_POWERMGT_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_POWERMGT_CONFIRM; - -typedef struct CSR_MLME_POWERMGT_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_POWER_MANAGEMENT_MODE PowerManagementMode; - s16 ReceiveDtims; - CSR_BEACON_PERIODS ListenInterval; - CSR_TRAFFIC_WINDOW TrafficWindow; -} CSR_MLME_POWERMGT_REQUEST; - -typedef struct CSR_MLME_SCAN_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SCAN_CONFIRM; - -typedef struct CSR_MLME_SCAN_REQUEST -{ - CSR_DATAREF ChannelList; - CSR_DATAREF InformationElements; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_IFINTERFACE Ifindex; - CSR_SCAN_TYPE ScanType; - CSR_MICROSECONDS32 ProbeDelay; - CSR_TIME_UNITS MinChannelTime; - CSR_TIME_UNITS MaxChannelTime; -} CSR_MLME_SCAN_REQUEST; - -typedef struct CSR_MLME_SCAN_CANCEL_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; -} CSR_MLME_SCAN_CANCEL_REQUEST; - -typedef struct CSR_MLME_SETKEYS_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SETKEYS_CONFIRM; - -typedef struct CSR_MLME_SETKEYS_REQUEST -{ - CSR_DATAREF Key; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_NATURAL16 Length; - CSR_NATURAL16 KeyId; - CSR_KEY_TYPE KeyType; - CSR_MACADDRESS Address; - CSR_NATURAL16 SequenceNumber[8]; - CSR_CIPHER_SUITE_SELECTOR CipherSuiteSelector; -} CSR_MLME_SETKEYS_REQUEST; - -typedef struct CSR_MLME_SET_CHANNEL_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SET_CHANNEL_CONFIRM; - -typedef struct CSR_MLME_SET_CHANNEL_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_IFINTERFACE Ifindex; - CSR_CHANNEL_NUMBER Channel; - CSR_MACADDRESS Address; - CSR_TIME_UNITS AvailabilityDuration; - CSR_TIME_UNITS AvailabilityInterval; -} CSR_MLME_SET_CHANNEL_REQUEST; - -typedef struct CSR_MLME_SET_PACKET_FILTER_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SET_PACKET_FILTER_CONFIRM; - -typedef struct CSR_MLME_SET_PACKET_FILTER_REQUEST -{ - CSR_DATAREF InformationElements; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_PACKET_FILTER_MODE PacketFilterMode; - CSR_IPV4_ADDRESS ArpFilterAddress; -} CSR_MLME_SET_PACKET_FILTER_REQUEST; - -typedef struct CSR_MLME_SET_TIM_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SET_TIM_CONFIRM; - -typedef struct CSR_MLME_SET_TIM_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_ASSOCIATION_ID AssociationId; - s16 TimValue; -} CSR_MLME_SET_TIM_REQUEST; - -typedef struct CSR_MLME_SM_START_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_SM_START_CONFIRM; - -typedef struct CSR_MLME_SM_START_REQUEST -{ - CSR_DATAREF Beacon; - CSR_DATAREF BssParameters; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_IFINTERFACE Ifindex; - CSR_CHANNEL_NUMBER Channel; - CSR_MACADDRESS InterfaceAddress; - CSR_MACADDRESS Bssid; - CSR_TIME_UNITS BeaconPeriod; - CSR_BEACON_PERIODS DtimPeriod; - CSR_CAPABILITY_INFORMATION CapabilityInformation; -} CSR_MLME_SM_START_REQUEST; - -typedef struct CSR_MLME_START_AGGREGATION_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS PeerQstaAddress; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; - CSR_RESULT_CODE ResultCode; - CSR_SEQUENCE_NUMBER SequenceNumber; -} CSR_MLME_START_AGGREGATION_CONFIRM; - -typedef struct CSR_MLME_START_AGGREGATION_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS PeerQstaAddress; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; - CSR_STARTING_SEQUENCE_NUMBER StartingSequenceNumber; - CSR_NATURAL16 BufferSize; - CSR_TIME_UNITS BlockAckTimeout; -} CSR_MLME_START_AGGREGATION_REQUEST; - -typedef struct CSR_MLME_STOP_AGGREGATION_CONFIRM -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS PeerQstaAddress; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; - CSR_RESULT_CODE ResultCode; -} CSR_MLME_STOP_AGGREGATION_CONFIRM; - -typedef struct CSR_MLME_STOP_AGGREGATION_REQUEST -{ - CSR_DATAREF Dummydataref1; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MACADDRESS PeerQstaAddress; - CSR_PRIORITY UserPriority; - CSR_DIRECTION Direction; -} CSR_MLME_STOP_AGGREGATION_REQUEST; - -typedef struct CSR_MLME_TRIGGERED_GET_INDICATION -{ - CSR_DATAREF MibAttributeValue; - CSR_DATAREF Dummydataref2; - CSR_VIF_IDENTIFIER VirtualInterfaceIdentifier; - CSR_MIB_STATUS Status; - CSR_NATURAL16 ErrorIndex; - CSR_TRIGGERED_ID TriggeredId; -} CSR_MLME_TRIGGERED_GET_INDICATION; - -typedef struct CSR_SIGNAL_PRIMITIVE -{ - CSR_SIGNAL_PRIMITIVE_HEADER SignalPrimitiveHeader; - union - { - CSR_MA_PACKET_REQUEST MaPacketRequest; - CSR_MA_PACKET_CONFIRM MaPacketConfirm; - CSR_MA_PACKET_INDICATION MaPacketIndication; - CSR_MA_PACKET_CANCEL_REQUEST MaPacketCancelRequest; - CSR_MA_VIF_AVAILABILITY_RESPONSE MaVifAvailabilityResponse; - CSR_MA_VIF_AVAILABILITY_INDICATION MaVifAvailabilityIndication; - CSR_MA_PACKET_ERROR_INDICATION MaPacketErrorIndication; - CSR_MLME_RESET_REQUEST MlmeResetRequest; - CSR_MLME_RESET_CONFIRM MlmeResetConfirm; - CSR_MLME_GET_REQUEST MlmeGetRequest; - CSR_MLME_GET_CONFIRM MlmeGetConfirm; - CSR_MLME_SET_REQUEST MlmeSetRequest; - CSR_MLME_SET_CONFIRM MlmeSetConfirm; - CSR_MLME_GET_NEXT_REQUEST MlmeGetNextRequest; - CSR_MLME_GET_NEXT_CONFIRM MlmeGetNextConfirm; - CSR_MLME_POWERMGT_REQUEST MlmePowermgtRequest; - CSR_MLME_POWERMGT_CONFIRM MlmePowermgtConfirm; - CSR_MLME_SCAN_REQUEST MlmeScanRequest; - CSR_MLME_SCAN_CONFIRM MlmeScanConfirm; - CSR_MLME_HL_SYNC_REQUEST MlmeHlSyncRequest; - CSR_MLME_HL_SYNC_CONFIRM MlmeHlSyncConfirm; - CSR_MLME_MEASURE_REQUEST MlmeMeasureRequest; - CSR_MLME_MEASURE_CONFIRM MlmeMeasureConfirm; - CSR_MLME_MEASURE_INDICATION MlmeMeasureIndication; - CSR_MLME_SETKEYS_REQUEST MlmeSetkeysRequest; - CSR_MLME_SETKEYS_CONFIRM MlmeSetkeysConfirm; - CSR_MLME_DELETEKEYS_REQUEST MlmeDeletekeysRequest; - CSR_MLME_DELETEKEYS_CONFIRM MlmeDeletekeysConfirm; - CSR_MLME_AUTONOMOUS_SCAN_LOSS_INDICATION MlmeAutonomousScanLossIndication; - CSR_MLME_CONNECTED_INDICATION MlmeConnectedIndication; - CSR_MLME_SCAN_CANCEL_REQUEST MlmeScanCancelRequest; - CSR_MLME_HL_SYNC_CANCEL_REQUEST MlmeHlSyncCancelRequest; - CSR_MLME_HL_SYNC_CANCEL_CONFIRM MlmeHlSyncCancelConfirm; - CSR_MLME_ADD_PERIODIC_REQUEST MlmeAddPeriodicRequest; - CSR_MLME_ADD_PERIODIC_CONFIRM MlmeAddPeriodicConfirm; - CSR_MLME_DEL_PERIODIC_REQUEST MlmeDelPeriodicRequest; - CSR_MLME_DEL_PERIODIC_CONFIRM MlmeDelPeriodicConfirm; - CSR_MLME_ADD_AUTONOMOUS_SCAN_REQUEST MlmeAddAutonomousScanRequest; - CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM MlmeAddAutonomousScanConfirm; - CSR_MLME_DEL_AUTONOMOUS_SCAN_REQUEST MlmeDelAutonomousScanRequest; - CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM MlmeDelAutonomousScanConfirm; - CSR_MLME_SET_PACKET_FILTER_REQUEST MlmeSetPacketFilterRequest; - CSR_MLME_SET_PACKET_FILTER_CONFIRM MlmeSetPacketFilterConfirm; - CSR_MLME_STOP_MEASURE_REQUEST MlmeStopMeasureRequest; - CSR_MLME_STOP_MEASURE_CONFIRM MlmeStopMeasureConfirm; - CSR_MLME_PAUSE_AUTONOMOUS_SCAN_REQUEST MlmePauseAutonomousScanRequest; - CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM MlmePauseAutonomousScanConfirm; - CSR_MLME_AUTONOMOUS_SCAN_DONE_INDICATION MlmeAutonomousScanDoneIndication; - CSR_MLME_ADD_TRIGGERED_GET_REQUEST MlmeAddTriggeredGetRequest; - CSR_MLME_ADD_TRIGGERED_GET_CONFIRM MlmeAddTriggeredGetConfirm; - CSR_MLME_DEL_TRIGGERED_GET_REQUEST MlmeDelTriggeredGetRequest; - CSR_MLME_DEL_TRIGGERED_GET_CONFIRM MlmeDelTriggeredGetConfirm; - CSR_MLME_TRIGGERED_GET_INDICATION MlmeTriggeredGetIndication; - CSR_MLME_ADD_BLACKOUT_REQUEST MlmeAddBlackoutRequest; - CSR_MLME_ADD_BLACKOUT_CONFIRM MlmeAddBlackoutConfirm; - CSR_MLME_BLACKOUT_ENDED_INDICATION MlmeBlackoutEndedIndication; - CSR_MLME_DEL_BLACKOUT_REQUEST MlmeDelBlackoutRequest; - CSR_MLME_DEL_BLACKOUT_CONFIRM MlmeDelBlackoutConfirm; - CSR_MLME_ADD_RX_TRIGGER_REQUEST MlmeAddRxTriggerRequest; - CSR_MLME_ADD_RX_TRIGGER_CONFIRM MlmeAddRxTriggerConfirm; - CSR_MLME_DEL_RX_TRIGGER_REQUEST MlmeDelRxTriggerRequest; - CSR_MLME_DEL_RX_TRIGGER_CONFIRM MlmeDelRxTriggerConfirm; - CSR_MLME_CONNECT_STATUS_REQUEST MlmeConnectStatusRequest; - CSR_MLME_CONNECT_STATUS_CONFIRM MlmeConnectStatusConfirm; - CSR_MLME_MODIFY_BSS_PARAMETER_REQUEST MlmeModifyBssParameterRequest; - CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM MlmeModifyBssParameterConfirm; - CSR_MLME_ADD_TEMPLATE_REQUEST MlmeAddTemplateRequest; - CSR_MLME_ADD_TEMPLATE_CONFIRM MlmeAddTemplateConfirm; - CSR_MLME_CONFIG_QUEUE_REQUEST MlmeConfigQueueRequest; - CSR_MLME_CONFIG_QUEUE_CONFIRM MlmeConfigQueueConfirm; - CSR_MLME_ADD_TSPEC_REQUEST MlmeAddTspecRequest; - CSR_MLME_ADD_TSPEC_CONFIRM MlmeAddTspecConfirm; - CSR_MLME_DEL_TSPEC_REQUEST MlmeDelTspecRequest; - CSR_MLME_DEL_TSPEC_CONFIRM MlmeDelTspecConfirm; - CSR_MLME_START_AGGREGATION_REQUEST MlmeStartAggregationRequest; - CSR_MLME_START_AGGREGATION_CONFIRM MlmeStartAggregationConfirm; - CSR_MLME_BLOCKACK_ERROR_INDICATION MlmeBlockackErrorIndication; - CSR_MLME_STOP_AGGREGATION_REQUEST MlmeStopAggregationRequest; - CSR_MLME_STOP_AGGREGATION_CONFIRM MlmeStopAggregationConfirm; - CSR_MLME_SM_START_REQUEST MlmeSmStartRequest; - CSR_MLME_SM_START_CONFIRM MlmeSmStartConfirm; - CSR_MLME_LEAVE_REQUEST MlmeLeaveRequest; - CSR_MLME_LEAVE_CONFIRM MlmeLeaveConfirm; - CSR_MLME_SET_TIM_REQUEST MlmeSetTimRequest; - CSR_MLME_SET_TIM_CONFIRM MlmeSetTimConfirm; - CSR_MLME_GET_KEY_SEQUENCE_REQUEST MlmeGetKeySequenceRequest; - CSR_MLME_GET_KEY_SEQUENCE_CONFIRM MlmeGetKeySequenceConfirm; - CSR_MLME_SET_CHANNEL_REQUEST MlmeSetChannelRequest; - CSR_MLME_SET_CHANNEL_CONFIRM MlmeSetChannelConfirm; - CSR_MLME_ADD_MULTICAST_ADDRESS_REQUEST MlmeAddMulticastAddressRequest; - CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM MlmeAddMulticastAddressConfirm; - CSR_DEBUG_STRING_INDICATION DebugStringIndication; - CSR_DEBUG_WORD16_INDICATION DebugWord16Indication; - CSR_DEBUG_GENERIC_REQUEST DebugGenericRequest; - CSR_DEBUG_GENERIC_CONFIRM DebugGenericConfirm; - CSR_DEBUG_GENERIC_INDICATION DebugGenericIndication; - } u; -} CSR_SIGNAL; - -#define SIG_FILTER_SIZE 6 - -u32 SigGetFilterPos(u16 aSigID); - -#endif diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.c b/drivers/staging/csr/csr_wifi_hip_ta_sampling.c deleted file mode 100644 index f1df36aa87e7..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_ta_sampling.c +++ /dev/null @@ -1,541 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_ta_sampling.c - * - * PURPOSE: - * The traffic analysis sampling module. - * This gathers data which is sent to the SME and used to analyse - * the traffic behaviour. - * - * Provides: - * unifi_ta_sampling_init - Initialise the internal state - * unifi_ta_sample - Sampling function, call this for every data packet - * - * Calls these external functions which must be provided: - * unifi_ta_indicate_sampling - Pass sample data to the SME. - * unifi_ta_indicate_protocol - Report certain data packet types to the SME. - * --------------------------------------------------------------------------- - */ - -#include "csr_wifi_hip_card_sdio.h" - -/* Maximum number of Tx frames we store each CYCLE_1, for detecting period */ -#define TA_MAX_INTERVALS_IN_C1 100 - -/* Number of intervals in CYCLE_1 (one second), for detecting periodic */ -/* Must match size of unifi_TrafficStats.intervals - 1 */ -#define TA_INTERVALS_NUM 10 - -/* Step (in msecs) between intervals, for detecting periodic */ -/* We are only interested in periods up to 100ms, i.e. between beacons */ -/* This is correct for TA_INTERVALS_NUM=10 */ -#define TA_INTERVALS_STEP 10 - - -enum ta_frame_identity -{ - TA_FRAME_UNKNOWN, - TA_FRAME_ETHERNET_UNINTERESTING, - TA_FRAME_ETHERNET_INTERESTING -}; - - -#define TA_ETHERNET_TYPE_OFFSET 6 -#define TA_LLC_HEADER_SIZE 8 -#define TA_IP_TYPE_OFFSET 17 -#define TA_UDP_SOURCE_PORT_OFFSET 28 -#define TA_UDP_DEST_PORT_OFFSET (TA_UDP_SOURCE_PORT_OFFSET + 2) -#define TA_BOOTP_CLIENT_MAC_ADDR_OFFSET 64 -#define TA_DHCP_MESSAGE_TYPE_OFFSET 278 -#define TA_DHCP_MESSAGE_TYPE_ACK 0x05 -#define TA_PROTO_TYPE_IP 0x0800 -#define TA_PROTO_TYPE_EAP 0x888E -#define TA_PROTO_TYPE_WAI 0x8864 -#define TA_PROTO_TYPE_ARP 0x0806 -#define TA_IP_TYPE_TCP 0x06 -#define TA_IP_TYPE_UDP 0x11 -#define TA_UDP_PORT_BOOTPC 0x0044 -#define TA_UDP_PORT_BOOTPS 0x0043 -#define TA_EAPOL_TYPE_OFFSET 9 -#define TA_EAPOL_TYPE_START 0x01 - -#define snap_802_2 0xAAAA0300 -#define oui_rfc1042 0x00000000 -#define oui_8021h 0x0000f800 -static const u8 aironet_snap[5] = { 0x00, 0x40, 0x96, 0x00, 0x00 }; - - -/* - * --------------------------------------------------------------------------- - * ta_detect_protocol - * - * Internal only. - * Detects a specific protocol in a frame and indicates a TA event. - * - * Arguments: - * ta The pointer to the TA module. - * direction The direction of the frame (tx or rx). - * data Pointer to the structure that contains the data. - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrlProtocolDirection direction, - const bulk_data_desc_t *data, - const u8 *saddr, - const u8 *sta_macaddr) -{ - ta_data_t *tad = &card->ta_sampling; - u16 proto; - u16 source_port, dest_port; - CsrWifiMacAddress srcAddress; - u32 snap_hdr, oui_hdr; - - if (data->data_length < TA_LLC_HEADER_SIZE) - { - return TA_FRAME_UNKNOWN; - } - - snap_hdr = (((u32)data->os_data_ptr[0]) << 24) | - (((u32)data->os_data_ptr[1]) << 16) | - (((u32)data->os_data_ptr[2]) << 8); - if (snap_hdr != snap_802_2) - { - return TA_FRAME_UNKNOWN; - } - - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) - { - /* - * Here we would use the custom filter to detect interesting frames. - */ - } - - oui_hdr = (((u32)data->os_data_ptr[3]) << 24) | - (((u32)data->os_data_ptr[4]) << 16) | - (((u32)data->os_data_ptr[5]) << 8); - if ((oui_hdr == oui_rfc1042) || (oui_hdr == oui_8021h)) - { - proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) + - data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1]; - - /* The only interesting IP frames are the DHCP */ - if (proto == TA_PROTO_TYPE_IP) - { - if (data->data_length > TA_IP_TYPE_OFFSET) - { - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) - { - ta_l4stats_t *ta_l4stats = &tad->ta_l4stats; - u8 l4proto = data->os_data_ptr[TA_IP_TYPE_OFFSET]; - - if (l4proto == TA_IP_TYPE_TCP) - { - if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) - { - ta_l4stats->txTcpBytesCount += data->data_length; - } - else - { - ta_l4stats->rxTcpBytesCount += data->data_length; - } - } - else if (l4proto == TA_IP_TYPE_UDP) - { - if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) - { - ta_l4stats->txUdpBytesCount += data->data_length; - } - else - { - ta_l4stats->rxUdpBytesCount += data->data_length; - } - } - } - - /* detect DHCP frames */ - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP) - { - /* DHCP frames are UDP frames with BOOTP ports */ - if (data->os_data_ptr[TA_IP_TYPE_OFFSET] == TA_IP_TYPE_UDP) - { - if (data->data_length > TA_UDP_DEST_PORT_OFFSET) - { - source_port = (data->os_data_ptr[TA_UDP_SOURCE_PORT_OFFSET] * 256) + - data->os_data_ptr[TA_UDP_SOURCE_PORT_OFFSET + 1]; - dest_port = (data->os_data_ptr[TA_UDP_DEST_PORT_OFFSET] * 256) + - data->os_data_ptr[TA_UDP_DEST_PORT_OFFSET + 1]; - - if (((source_port == TA_UDP_PORT_BOOTPC) && (dest_port == TA_UDP_PORT_BOOTPS)) || - ((source_port == TA_UDP_PORT_BOOTPS) && (dest_port == TA_UDP_PORT_BOOTPC))) - { - /* The DHCP should have at least a message type (request, ack, nack, etc) */ - if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6) - { - UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); - - if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) - { - unifi_ta_indicate_protocol(card->ospriv, - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP, - direction, - &srcAddress); - return TA_FRAME_ETHERNET_UNINTERESTING; - } - - /* DHCPACK is a special indication */ - if (UNIFI_MAC_ADDRESS_CMP(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr) == TRUE) - { - if (data->os_data_ptr[TA_DHCP_MESSAGE_TYPE_OFFSET] == TA_DHCP_MESSAGE_TYPE_ACK) - { - unifi_ta_indicate_protocol(card->ospriv, - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK, - direction, - &srcAddress); - } - else - { - unifi_ta_indicate_protocol(card->ospriv, - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP, - direction, - &srcAddress); - } - } - } - } - } - } - } - } - - return TA_FRAME_ETHERNET_INTERESTING; - } - - /* detect protocol type EAPOL or WAI (treated as equivalent here) */ - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL) - { - if (TA_PROTO_TYPE_EAP == proto || TA_PROTO_TYPE_WAI == proto) - { - if ((TA_PROTO_TYPE_WAI == proto) || (direction != CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) || - (data->os_data_ptr[TA_EAPOL_TYPE_OFFSET] == TA_EAPOL_TYPE_START)) - { - UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); - unifi_ta_indicate_protocol(card->ospriv, - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL, - direction, &srcAddress); - } - return TA_FRAME_ETHERNET_UNINTERESTING; - } - } - - /* detect protocol type 0x0806 (ARP) */ - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP) - { - if (proto == TA_PROTO_TYPE_ARP) - { - UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); - unifi_ta_indicate_protocol(card->ospriv, - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP, - direction, &srcAddress); - return TA_FRAME_ETHERNET_UNINTERESTING; - } - } - - return TA_FRAME_ETHERNET_INTERESTING; - } - else if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET) - { - /* detect Aironet frames */ - if (!memcmp(data->os_data_ptr + 3, aironet_snap, 5)) - { - UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr); - unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET, - direction, &srcAddress); - } - } - - return TA_FRAME_ETHERNET_UNINTERESTING; -} /* ta_detect_protocol() */ - - -static void tas_reset_data(ta_data_t *tad) -{ - s16 i; - - for (i = 0; i < (TA_INTERVALS_NUM + 1); i++) - { - tad->stats.intervals[i] = 0; - } - - tad->stats.rxFramesNum = 0; - tad->stats.txFramesNum = 0; - tad->stats.rxBytesCount = 0; - tad->stats.txBytesCount = 0; - tad->stats.rxMeanRate = 0; - - tad->rx_sum_rate = 0; - - tad->ta_l4stats.rxTcpBytesCount = 0; - tad->ta_l4stats.txTcpBytesCount = 0; - tad->ta_l4stats.rxUdpBytesCount = 0; - tad->ta_l4stats.txUdpBytesCount = 0; -} /* tas_reset_data() */ - - -/* - * --------------------------------------------------------------------------- - * API. - * unifi_ta_sampling_init - * - * (Re)Initialise the Traffic Analysis sampling module. - * Resets the counters and timestamps. - * - * Arguments: - * tad Pointer to a ta_data_t structure containing the - * context for this device instance. - * drv_priv An opaque pointer that the TA sampling module will - * pass in call-outs. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void unifi_ta_sampling_init(card_t *card) -{ - (void)unifi_ta_configure(card, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET, NULL); - - card->ta_sampling.packet_filter = CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE; - card->ta_sampling.traffic_type = CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL; -} /* unifi_ta_sampling_init() */ - - -/* - * --------------------------------------------------------------------------- - * API. - * unifi_ta_sample - * - * Sample a data frame for the TA module. - * This function stores all the useful information it can extract from - * the frame and detects any specific protocols. - * - * Arguments: - * tad The pointer to the TA sampling context struct. - * direction The direction of the frame (rx, tx) - * data Pointer to the frame data - * saddr Source MAC address of frame. - * timestamp Time (in msecs) that the frame was received. - * rate Reported data rate for the rx frame (0 for tx frames) - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -void unifi_ta_sample(card_t *card, - CsrWifiRouterCtrlProtocolDirection direction, - const bulk_data_desc_t *data, - const u8 *saddr, - const u8 *sta_macaddr, - u32 timestamp, - u16 rate) -{ - ta_data_t *tad = &card->ta_sampling; - enum ta_frame_identity identity; - u32 time_delta; - - - - /* Step1: Check for specific frames */ - if (tad->packet_filter != CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE) - { - identity = ta_detect_protocol(card, direction, data, saddr, sta_macaddr); - } - else - { - identity = TA_FRAME_ETHERNET_INTERESTING; - } - - - /* Step2: Update the information in the current record */ - if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX) - { - /* Update the Rx packet count and the throughput count */ - tad->stats.rxFramesNum++; - tad->stats.rxBytesCount += data->data_length; - - /* Accumulate packet Rx rates for later averaging */ - tad->rx_sum_rate += rate; - } - else - { - if (identity == TA_FRAME_ETHERNET_INTERESTING) - { - /* - * Store the period between the last and the current frame. - * There is not point storing more than TA_MAX_INTERVALS_IN_C1 periods, - * the traffic will be bursty or continuous. - */ - if (tad->stats.txFramesNum < TA_MAX_INTERVALS_IN_C1) - { - u32 interval; - u32 index_in_intervals; - - interval = timestamp - tad->tx_last_ts; - tad->tx_last_ts = timestamp; - index_in_intervals = (interval + TA_INTERVALS_STEP / 2 - 1) / TA_INTERVALS_STEP; - - /* If the interval is interesting, update the t1_intervals count */ - if (index_in_intervals <= TA_INTERVALS_NUM) - { - unifi_trace(card->ospriv, UDBG5, - "unifi_ta_sample: TX interval=%d index=%d\n", - interval, index_in_intervals); - tad->stats.intervals[index_in_intervals]++; - } - } - } - - /* Update the Tx packet count... */ - tad->stats.txFramesNum++; - /* ... and the number of bytes for throughput. */ - tad->stats.txBytesCount += data->data_length; - } - - /* - * If more than one second has elapsed since the last report, send - * another one. - */ - /* Unsigned subtraction handles wrap-around from 0xFFFFFFFF to 0 */ - time_delta = timestamp - tad->last_indication_time; - if (time_delta >= 1000) - { - /* - * rxFramesNum can be flashed in tas_reset_data() by another thread. - * Use a temp to avoid division by zero. - */ - u32 temp_rxFramesNum; - temp_rxFramesNum = tad->stats.rxFramesNum; - - /* Calculate this interval's mean frame Rx rate from the sum */ - if (temp_rxFramesNum) - { - tad->stats.rxMeanRate = tad->rx_sum_rate / temp_rxFramesNum; - } - unifi_trace(card->ospriv, UDBG5, - "unifi_ta_sample: RX fr=%lu, r=%u, sum=%lu, av=%lu\n", - tad->stats.rxFramesNum, rate, - tad->rx_sum_rate, tad->stats.rxMeanRate); - - /* - * Send the information collected in the stats struct - * to the SME and reset the counters. - */ - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) - { - u32 rxTcpThroughput = tad->ta_l4stats.rxTcpBytesCount / time_delta; - u32 txTcpThroughput = tad->ta_l4stats.txTcpBytesCount / time_delta; - u32 rxUdpThroughput = tad->ta_l4stats.rxUdpBytesCount / time_delta; - u32 txUdpThroughput = tad->ta_l4stats.txUdpBytesCount / time_delta; - - unifi_ta_indicate_l4stats(card->ospriv, - rxTcpThroughput, - txTcpThroughput, - rxUdpThroughput, - txUdpThroughput - ); - } - unifi_ta_indicate_sampling(card->ospriv, &tad->stats); - tas_reset_data(tad); - tad->last_indication_time = timestamp; - } -} /* unifi_ta_sample() */ - - -/* - * --------------------------------------------------------------------------- - * External API. - * unifi_ta_configure - * - * Configures the TA module parameters. - * - * Arguments: - * ta The pointer to the TA module. - * config_type The type of the configuration request - * config Pointer to the configuration parameters. - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code otherwise - * --------------------------------------------------------------------------- - */ -CsrResult unifi_ta_configure(card_t *card, - CsrWifiRouterCtrlTrafficConfigType config_type, - const CsrWifiRouterCtrlTrafficConfig *config) -{ - ta_data_t *tad = &card->ta_sampling; - - /* Reinitialise our data when we are reset */ - if (config_type == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET) - { - /* Reset the stats to zero */ - tas_reset_data(tad); - - /* Reset the timer variables */ - tad->tx_last_ts = 0; - tad->last_indication_time = 0; - - return CSR_RESULT_SUCCESS; - } - - if (config_type == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER) - { - tad->packet_filter = config->packetFilter; - - if (tad->packet_filter & CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM) - { - tad->custom_filter = config->customFilter; - } - - return CSR_RESULT_SUCCESS; - } - - return CSR_RESULT_SUCCESS; -} /* unifi_ta_configure() */ - - -/* - * --------------------------------------------------------------------------- - * External API. - * unifi_ta_classification - * - * Configures the current TA classification. - * - * Arguments: - * ta The pointer to the TA module. - * traffic_type The classification type - * period The traffic period if the type is periodic - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -void unifi_ta_classification(card_t *card, - CsrWifiRouterCtrlTrafficType traffic_type, - u16 period) -{ - unifi_trace(card->ospriv, UDBG3, - "Changed current ta classification to: %d\n", traffic_type); - - card->ta_sampling.traffic_type = traffic_type; -} - - diff --git a/drivers/staging/csr/csr_wifi_hip_ta_sampling.h b/drivers/staging/csr/csr_wifi_hip_ta_sampling.h deleted file mode 100644 index aa684c654d06..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_ta_sampling.h +++ /dev/null @@ -1,66 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_ta_sampling.h - * - * PURPOSE: - * This file contains Traffic Analysis definitions common to the - * sampling and analysis modules. - * - * --------------------------------------------------------------------------- - */ -#ifndef __TA_SAMPLING_H__ -#define __TA_SAMPLING_H__ - -#include "csr_wifi_hip_unifi.h" - -typedef struct ta_l4stats -{ - u32 rxTcpBytesCount; - u32 txTcpBytesCount; - u32 rxUdpBytesCount; - u32 txUdpBytesCount; -} ta_l4stats_t; - -/* - * Context structure to preserve state between calls. - */ - -typedef struct ta_data -{ - /* Current packet filter configuration */ - u16 packet_filter; - - /* Current packet custom filter configuration */ - CsrWifiRouterCtrlTrafficFilter custom_filter; - - /* The timestamp of the last tx packet processed. */ - u32 tx_last_ts; - - /* The timestamp of the last packet processed. */ - u32 last_indication_time; - - /* Statistics */ - CsrWifiRouterCtrlTrafficStats stats; - - /* Current traffic classification */ - CsrWifiRouterCtrlTrafficType traffic_type; - - /* Sum of packet rx rates for this interval used to calculate mean */ - u32 rx_sum_rate; - ta_l4stats_t ta_l4stats; -} ta_data_t; - - -void unifi_ta_sampling_init(card_t *card); - -#endif /* __TA_SAMPLING_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_udi.c b/drivers/staging/csr/csr_wifi_hip_udi.c deleted file mode 100644 index a6b006b0e983..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_udi.c +++ /dev/null @@ -1,173 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_card_udi.c - * - * PURPOSE: - * Maintain a list of callbacks to log UniFi exchanges to one or more - * debug/monitoring client applications. - * - * NOTES: - * Just call the UDI driver log fn directly for now. - * When done properly, each open() on the UDI device will install - * a log function. We will call all log fns whenever a signal is written - * to or read form the UniFi. - * - * --------------------------------------------------------------------------- - */ -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_card.h" - - -static void unifi_print_unsafe_sdio_status(card_t *card, struct seq_file *m) -{ -#ifdef CSR_UNSAFE_SDIO_ACCESS - s32 iostate; - CsrResult r; - static const char *const states[] = { - "AWAKE", "DROWSY", "TORPID" - }; -#define SHARED_READ_RETRY_LIMIT 10 - u8 b; - - seq_printf(m, "Host State: %s\n", states[card->host_state]); - - r = unifi_check_io_status(card, &iostate); - if (iostate == 1) { - seq_puts(m, remaining, "I/O Check: F1 disabled\n"); - } else { - if (iostate == 1) { - seq_puts(m, "I/O Check: pending interrupt\n"); - - seq_printf(m, "BH reason interrupt = %d\n", card->bh_reason_unifi); - seq_printf(m, "BH reason host = %d\n", card->bh_reason_host); - - for (i = 0; i < SHARED_READ_RETRY_LIMIT; i++) { - r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b); - if (r == CSR_RESULT_SUCCESS && !(b & 0x80)) { - seq_printf(m, "fhsr: %u (driver thinks is %u)\n", - b, card->from_host_signals_r); - break; - } - } - - iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4); - seq_printf(m, "thsw: %u (driver thinks is %u)\n", - iostate, card->to_host_signals_w); - } -#endif -} - -/* - * --------------------------------------------------------------------------- - * unifi_print_status - * - * Print status info to given character buffer. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -s32 unifi_print_status(card_t *card, struct seq_file *m) -{ - sdio_config_data_t *cfg; - u16 i, n; - - i = n = 0; - seq_printf(m, "Chip ID %u\n", card->chip_id); - seq_printf(m, "Chip Version %04X\n", card->chip_version); - seq_printf(m, "HIP v%u.%u\n", - (card->config_data.version >> 8) & 0xFF, - card->config_data.version & 0xFF); - seq_printf(m, "Build %u: %s\n", card->build_id, card->build_id_string); - - cfg = &card->config_data; - - seq_printf(m, "sdio ctrl offset %u\n", cfg->sdio_ctrl_offset); - seq_printf(m, "fromhost sigbuf handle %u\n", cfg->fromhost_sigbuf_handle); - seq_printf(m, "tohost_sigbuf_handle %u\n", cfg->tohost_sigbuf_handle); - seq_printf(m, "num_fromhost_sig_frags %u\n", cfg->num_fromhost_sig_frags); - seq_printf(m, "num_tohost_sig_frags %u\n", cfg->num_tohost_sig_frags); - seq_printf(m, "num_fromhost_data_slots %u\n", cfg->num_fromhost_data_slots); - seq_printf(m, "num_tohost_data_slots %u\n", cfg->num_tohost_data_slots); - seq_printf(m, "data_slot_size %u\n", cfg->data_slot_size); - - /* Added by protocol version 0x0001 */ - seq_printf(m, "overlay_size %u\n", cfg->overlay_size); - - /* Added by protocol version 0x0300 */ - seq_printf(m, "data_slot_round %u\n", cfg->data_slot_round); - seq_printf(m, "sig_frag_size %u\n", cfg->sig_frag_size); - - /* Added by protocol version 0x0300 */ - seq_printf(m, "tohost_sig_pad %u\n", cfg->tohost_signal_padding); - - seq_puts(m, "\nInternal state:\n"); - - seq_printf(m, "Last PHY PANIC: %04x:%04x\n", - card->last_phy_panic_code, card->last_phy_panic_arg); - seq_printf(m, "Last MAC PANIC: %04x:%04x\n", - card->last_mac_panic_code, card->last_mac_panic_arg); - - seq_printf(m, "fhsr: %hu\n", (u16)card->from_host_signals_r); - seq_printf(m, "fhsw: %hu\n", (u16)card->from_host_signals_w); - seq_printf(m, "thsr: %hu\n", (u16)card->to_host_signals_r); - seq_printf(m, "thsw: %hu\n", (u16)card->to_host_signals_w); - seq_printf(m, "fh buffer contains: %d signals, %td bytes\n", - card->fh_buffer.count, - card->fh_buffer.ptr - card->fh_buffer.buf); - - seq_puts(m, "paused: "); - for (i = 0; i < ARRAY_SIZE(card->tx_q_paused_flag); i++) - seq_printf(m, card->tx_q_paused_flag[i] ? "1" : "0"); - seq_putc(m, '\n'); - - seq_printf(m, "fh command q: %u waiting, %u free of %u:\n", - CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue), - CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue), - UNIFI_SOFT_COMMAND_Q_LENGTH); - - for (i = 0; i < UNIFI_NO_OF_TX_QS; i++) - seq_printf(m, "fh traffic q[%u]: %u waiting, %u free of %u:\n", - i, - CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]), - CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[i]), - UNIFI_SOFT_TRAFFIC_Q_LENGTH); - - seq_printf(m, "fh data slots free: %u\n", - card->from_host_data ? CardGetFreeFromHostDataSlots(card) : 0); - - seq_puts(m, "From host data slots:"); - n = card->config_data.num_fromhost_data_slots; - for (i = 0; i < n && card->from_host_data; i++) - seq_printf(m, " %hu", (u16)card->from_host_data[i].bd.data_length); - seq_putc(m, '\n'); - - seq_puts(m, "To host data slots:"); - n = card->config_data.num_tohost_data_slots; - for (i = 0; i < n && card->to_host_data; i++) - seq_printf(m, " %hu", (u16)card->to_host_data[i].data_length); - seq_putc(m, '\n'); - - unifi_print_unsafe_sdio_status(card, m); - - seq_puts(m, "\nStats:\n"); - seq_printf(m, "Total SDIO bytes: R=%u W=%u\n", - card->sdio_bytes_read, card->sdio_bytes_written); - - seq_printf(m, "Interrupts generated on card: %u\n", card->unifi_interrupt_seq); - return 0; -} diff --git a/drivers/staging/csr/csr_wifi_hip_unifi.h b/drivers/staging/csr/csr_wifi_hip_unifi.h deleted file mode 100644 index 1160a0e25c7d..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_unifi.h +++ /dev/null @@ -1,871 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * - * FILE : csr_wifi_hip_unifi.h - * - * PURPOSE : Public API for the UniFi HIP core library. - * - * --------------------------------------------------------------------------- - */ -#ifndef __CSR_WIFI_HIP_UNIFI_H__ -#define __CSR_WIFI_HIP_UNIFI_H__ 1 - -#ifndef CSR_WIFI_HIP_TA_DISABLE -#include "csr_wifi_router_ctrl_prim.h" -#include "csr_wifi_router_prim.h" -#else -#include "csr_time.h" -#endif - -/* SDIO chip ID numbers */ - -/* Manufacturer id */ -#define SDIO_MANF_ID_CSR 0x032a - -/* Device id */ -#define SDIO_CARD_ID_UNIFI_1 0x0001 -#define SDIO_CARD_ID_UNIFI_2 0x0002 -#define SDIO_CARD_ID_UNIFI_3 0x0007 -#define SDIO_CARD_ID_UNIFI_4 0x0008 - -/* Function number for WLAN */ -#define SDIO_WLAN_FUNC_ID_UNIFI_1 0x0001 -#define SDIO_WLAN_FUNC_ID_UNIFI_2 0x0001 -#define SDIO_WLAN_FUNC_ID_UNIFI_3 0x0001 -#define SDIO_WLAN_FUNC_ID_UNIFI_4 0x0002 - -/* Maximum SDIO bus clock supported. */ -#define UNIFI_SDIO_CLOCK_MAX_HZ 50000000 /* Hz */ - -/* - * Initialisation SDIO bus clock. - * - * The initialisation clock speed should be used from when the chip has been - * reset until the first MLME-reset has been received (i.e. during firmware - * initialisation), unless UNIFI_SDIO_CLOCK_SAFE_HZ applies. - */ -#define UNIFI_SDIO_CLOCK_INIT_HZ 12500000 /* Hz */ - -/* - * Safe SDIO bus clock. - * - * The safe speed should be used when the chip is in deep sleep or - * it's state is unknown (just after reset / power on). - */ -#define UNIFI_SDIO_CLOCK_SAFE_HZ 1000000 /* Hz */ - -/* I/O default block size to use for UniFi. */ -#define UNIFI_IO_BLOCK_SIZE 64 - -#define UNIFI_WOL_OFF 0 -#define UNIFI_WOL_SDIO 1 -#define UNIFI_WOL_PIO 2 - -/* The number of Tx traffic queues */ -#define UNIFI_NO_OF_TX_QS 4 - -#define CSR_WIFI_HIP_RESERVED_HOST_TAG 0xFFFFFFFF - -/* - * The number of slots in the from-host queues. - * - * UNIFI_SOFT_TRAFFIC_Q_LENGTH is the number of slots in the traffic queues - * and there will be UNIFI_NO_OF_TX_QS of them. - * Traffic queues are used for data packets. - * - * UNIFI_SOFT_COMMAND_Q_LENGTH is the number of slots in the command queue. - * The command queue is used for MLME management requests. - * - * Queues are ring buffers and so must always have 1 unused slot. - */ -#define UNIFI_SOFT_TRAFFIC_Q_LENGTH (20 + 1) -#define UNIFI_SOFT_COMMAND_Q_LENGTH (16 + 1) - -#include "csr_framework_ext.h" /* from the synergy porting folder */ -#include "csr_sdio.h" /* from the synergy porting folder */ -#include "csr_macro.h" /* from the synergy porting folder */ -#include "csr_wifi_result.h" - -/* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */ -#define UNIFI_MAC_ADDRESS_COPY(dst, src) \ - do { (dst)[0] = (src)[0]; (dst)[1] = (src)[1]; \ - (dst)[2] = (src)[2]; (dst)[3] = (src)[3]; \ - (dst)[4] = (src)[4]; (dst)[5] = (src)[5]; \ - } while (0) - -#define UNIFI_MAC_ADDRESS_CMP(addr1, addr2) \ - (((addr1)[0] == (addr2)[0]) && ((addr1)[1] == (addr2)[1]) && \ - ((addr1)[2] == (addr2)[2]) && ((addr1)[3] == (addr2)[3]) && \ - ((addr1)[4] == (addr2)[4]) && ((addr1)[5] == (addr2)[5])) - -/* Traffic queue ordered according to priority - * EAPOL/Uncontrolled port Queue should be the last - */ -typedef enum -{ - UNIFI_TRAFFIC_Q_BK = 0, - UNIFI_TRAFFIC_Q_BE, - UNIFI_TRAFFIC_Q_VI, - UNIFI_TRAFFIC_Q_VO, - UNIFI_TRAFFIC_Q_EAPOL, /* Non existent in HIP */ - UNIFI_TRAFFIC_Q_MAX, /* Non existent */ - UNIFI_TRAFFIC_Q_MLME /* Non existent */ -} unifi_TrafficQueue; - -/* - * Structure describing a bulk data slot. - * This structure is shared between the HIP core library and the OS - * layer. See the definition of unifi_net_data_malloc() for more details. - * - * The data_length field is used to indicate empty/occupied state. - * Needs to be defined before #include "unifi_os.h". - */ -typedef struct _bulk_data_desc -{ - const u8 *os_data_ptr; - u32 data_length; - const void *os_net_buf_ptr; - u32 net_buf_length; -} bulk_data_desc_t; - -/* Structure of an entry in the Symbol Look Up Table (SLUT). */ -typedef struct _symbol -{ - u16 id; - u32 obj; -} symbol_t; - -/* - * Header files need to be included from the current directory, - * the SME library, the synergy framework and the OS layer. - * A thin OS layer needs to be implemented in the porting exercise. - * - * Note that unifi_os.h should be included only in unifi.h - */ - -#include "unifi_os.h" - -/* - * Contains the HIP core definitions selected in the porting exercise, such as - * UNIFI_PAD_BULK_DATA_TO_BLOCK_SIZE and UNIFI_PAD_SIGNALS_TO_BLOCK_SIZE. - * Implemented in the OS layer, as part of the porting exersice. - */ -#include "unifi_config.h" - -#include "csr_wifi_hip_signals.h" /* from this dir */ - -/* - * The card structure is an opaque pointer that is used to pass context - * to the upper-edge API functions. - */ -typedef struct card card_t; - - -/* - * This structure describes all of the bulk data that 'might' be - * associated with a signal. - */ -typedef struct _bulk_data_param -{ - bulk_data_desc_t d[UNIFI_MAX_DATA_REFERENCES]; -} bulk_data_param_t; - - -/* - * This structure describes the chip and HIP core lib - * information that exposed to the OS layer. - */ -typedef struct _card_info -{ - u16 chip_id; - u16 chip_version; - u32 fw_build; - u16 fw_hip_version; - u32 sdio_block_size; -} card_info_t; - - -/* - * Mini-coredump definitions - */ -/* Definition of XAP memory ranges used by the mini-coredump system. - * Note that, these values are NOT the same as UNIFI_REGISTERS, etc - * in unifihw.h which don't allow selection of register areas for each XAP. - */ -typedef enum unifi_coredump_space -{ - UNIFI_COREDUMP_MAC_REG, - UNIFI_COREDUMP_PHY_REG, - UNIFI_COREDUMP_SH_DMEM, - UNIFI_COREDUMP_MAC_DMEM, - UNIFI_COREDUMP_PHY_DMEM, - UNIFI_COREDUMP_TRIGGER_MAGIC = 0xFEED -} unifi_coredump_space_t; - -/* Structure used to request a register value from a mini-coredump buffer */ -typedef struct unifi_coredump_req -{ - /* From user */ - s32 index; /* 0=newest, -1=oldest */ - unifi_coredump_space_t space; /* memory space */ - u32 offset; /* register offset in space */ - /* From driver */ - u32 drv_build; /* Driver build id */ - u32 chip_ver; /* Chip version */ - u32 fw_ver; /* Firmware version */ - s32 requestor; /* Requestor: 0=auto dump, 1=manual */ - u32 timestamp; /* time of capture by driver */ - u32 serial; /* capture serial number */ - s32 value; /* register value */ -} unifi_coredump_req_t; /* mini-coredumped reg value request */ - - -/** - * @defgroup upperedge Upper edge API - * - * The following functions are implemented in the HIP core lib. - */ - -/** - * - * Initialise the HIP core lib. - * Note that the OS layer must initialise the SDIO glue layer and obtain - * an SDIO function context, prior to this call. - * - * @param sdiopriv the SDIO function context. - * - * @param ospriv the OS layer context. - * - * @return \p card_t the HIP core lib API context. - * - * @ingroup upperedge - */ -card_t* unifi_alloc_card(CsrSdioFunction *sdiopriv, void *ospriv); - - -/** - * - * Initialise the UniFi chip. - * - * @param card the HIP core lib API context. - * - * @param led_mask the led mask to apply to UniFi. - * - * @return \b 0 if UniFi is initialized. - * - * @return \b -CSR_EIO if an I/O error occurred while initializing UniFi - * - * @return \b -CSR_ENODEV if the card is no longer present. - * - * @ingroup upperedge - */ -CsrResult unifi_init_card(card_t *card, s32 led_mask); - -/** - * - * De-Initialise the HIP core lib. - * - * @param card the HIP core lib API context. - * - * @ingroup upperedge - */ -void unifi_free_card(card_t *card); - -/** - * - * Cancel all the signals pending in the HIP core lib. - * Normally used during a system suspend when the power is retained on UniFi. - * - * @param card the HIP core lib API context. - * - * @ingroup upperedge - */ -void unifi_cancel_pending_signals(card_t *card); - -/** - * - * Send a signal to UniFi. - * Normally it is called from unifi_sys_hip_req() and the OS layer - * Tx data plane. - * - * Note that the bulkdata buffers ownership is passed to the HIP core lib. - * These buffers must be allocated using unifi_net_data_malloc(). - * - * @param card the HIP core lib API context. - * - * @param sigptr pointer to the signal. - * - * @param siglen size of the signal. - * - * @param bulkdata pointer to the bulk data associated with the signal. - * - * @return \b 0 signal is sent. - * - * @return \b -CSR_EIO if an error occurred while sending the signal - * - * @return \b -CSR_ENODEV if the card is no longer present. - * - * @ingroup upperedge - */ -CsrResult unifi_send_signal(card_t *card, const u8 *sigptr, - u32 siglen, - const bulk_data_param_t *bulkdata); - -/** - * - * Check if the HIP core lib has resources to send a signal. - * Normally there no need to use this function. - * - * @param card the HIP core lib API context. - * - * @param sigptr pointer to the signal. - * - * @return \b 0 if there are resources for the signal. - * - * @return \b -CSR_ENOSPC if there are not enough resources - * - * @ingroup upperedge - */ -CsrResult unifi_send_resources_available(card_t *card, const u8 *sigptr); - -/** - * - * Read the UniFi chip and the HIP core lib information. - * - * @param card the HIP core lib API context. - * - * @param card_info pointer to save the information. - * - * @ingroup upperedge - */ -void unifi_card_info(card_t *card, card_info_t *card_info); - -/** - * - * Print the UniFi I/O and Interrupt status. - * Normally it is used for debug purposes only. - * - * @param card the HIP core lib API context. - - * @param status buffer for the chip status - * - * @return \b 0 if the check was performed. - * - * @return \b -CSR_EIO if an error occurred while checking the status. - * - * @return \b -CSR_ENODEV if the card is no longer present. - * - * @ingroup upperedge - */ -CsrResult unifi_check_io_status(card_t *card, s32 *status); - - -/** - * - * Run the HIP core lib Botton-Half. - * Whenever the HIP core lib want this function to be called - * by the OS layer, it calls unifi_run_bh(). - * - * @param card the HIP core lib API context. - * - * @param remaining pointer to return the time (in msecs) that this function - * should be re-scheduled. A return value of 0 means that no re-scheduling - * is required. If unifi_bh() is called before the timeout expires, - * the caller must pass in the remaining time. - * - * @return \b 0 if no error occurred. - * - * @return \b -CSR_ENODEV if the card is no longer present. - * - * @return \b -CSR_E* if an error occurred while running the bottom half. - * - * @ingroup upperedge - */ -CsrResult unifi_bh(card_t *card, u32 *remaining); - - -/** - * UniFi Low Power Mode (Deep Sleep Signaling) - * - * unifi_low_power_mode defines the UniFi Deep Sleep Signaling status. - * Use with unifi_configure_low_power_mode() to enable/disable - * the Deep Sleep Signaling. - */ -enum unifi_low_power_mode -{ - UNIFI_LOW_POWER_DISABLED, - UNIFI_LOW_POWER_ENABLED -}; - -/** - * Periodic Wake Host Mode - * - * unifi_periodic_wake_mode defines the Periodic Wake Host Mode. - * It can only be set to UNIFI_PERIODIC_WAKE_HOST_ENABLED if - * low_power_mode == UNIFI_LOW_POWER_ENABLED. - */ -enum unifi_periodic_wake_mode -{ - UNIFI_PERIODIC_WAKE_HOST_DISABLED, - UNIFI_PERIODIC_WAKE_HOST_ENABLED -}; - -/** - * - * Run the HIP core lib Botton-Half. - * Whenever the HIP core lib want this function to be called - * by the OS layer, it calls unifi_run_bh(). - * - * Typically, the SME is responsible for configuring these parameters, - * so unifi_sys_configure_power_mode_req() is usually implemented - * as a direct call to unifi_configure_low_power_mode(). - * - * Note: When polling mode is used instead of interrupts, - * low_power_mode must never be set to UNIFI_LOW_POWER_ENABLED. - * - * @param card the HIP core lib API context. - * - * @param low_power_mode the Low Power Mode. - * - * @param periodic_wake_mode the Periodic Wake Mode. - * - * @return \b 0 if no error occurred. - * - * @return \b -CSR_E* if the request failed. - * - * @ingroup upperedge - */ -CsrResult unifi_configure_low_power_mode(card_t *card, - enum unifi_low_power_mode low_power_mode, - enum unifi_periodic_wake_mode periodic_wake_mode); - -/** - * - * Forces the UniFi chip to enter a Deep Sleep state. - * This is normally called by the OS layer when the platform suspends. - * - * Note that if the UniFi Low Power Mode is disabled this call fails. - * - * @param card the HIP core lib API context. - * - * @return \b 0 if no error occurred. - * - * @return \b -CSR_ENODEV if the card is no longer present. - * - * @return \b -CSR_E* if the request failed. - * - * @ingroup upperedge - */ -CsrResult unifi_force_low_power_mode(card_t *card); - -#ifndef CSR_WIFI_HIP_TA_DISABLE -/** - * Configure the Traffic Analysis sampling - * - * Enable or disable statistics gathering. - * Enable or disable particular packet detection. - * - * @param card the HIP core context - * @param config_type the item to configure - * @param config pointer to struct containing config info - * - * @return \b 0 if configuration was successful - * - * @return \b -CSR_EINVAL if a parameter had an invalid value - * - * @ingroup upperedge - */ -CsrResult unifi_ta_configure(card_t *card, - CsrWifiRouterCtrlTrafficConfigType config_type, - const CsrWifiRouterCtrlTrafficConfig *config); - -/** - * Pass a packet for Traffic Analysis sampling - * - * @param card the HIP core context - * @param direction the direction (Rx or Tx) of the frame. - * @param data pointer to bulkdata struct containing the packet - * @param saddr the source address of the packet - * @param sta_macaddr the MAC address of the UniFi chip - * @param timestamp the current time in msecs - * - * @ingroup upperedge - */ -void unifi_ta_sample(card_t *card, - CsrWifiRouterCtrlProtocolDirection direction, - const bulk_data_desc_t *data, - const u8 *saddr, - const u8 *sta_macaddr, - u32 timestamp, - u16 rate); - -/** - * Notify the HIP core lib for a detected Traffic Classification. - * Typically, the SME is responsible for configuring these parameters, - * so unifi_sys_traffic_classification_req() is usually implemented - * as a direct call to unifi_ta_classification(). - * - * @param card the HIP core context. - * @param traffic_type the detected traffic type. - * @param period The detected period of the traffic. - * - * @ingroup upperedge - */ -void unifi_ta_classification(card_t *card, - CsrWifiRouterCtrlTrafficType traffic_type, - u16 period); - -#endif -/** - * Use software to hard reset the chip. - * This is a subset of the unifi_init_card() functionality and should - * only be used only to reset a paniced chip before a coredump is taken. - * - * @param card the HIP core context. - * - * @ingroup upperedge - */ -CsrResult unifi_card_hard_reset(card_t *card); - - -CsrResult unifi_card_readn(card_t *card, u32 unifi_addr, void *pdata, u16 len); -CsrResult unifi_card_read16(card_t *card, u32 unifi_addr, u16 *pdata); -CsrResult unifi_card_write16(card_t *card, u32 unifi_addr, u16 data); - - -enum unifi_dbg_processors_select -{ - UNIFI_PROC_MAC, - UNIFI_PROC_PHY, - UNIFI_PROC_BT, - UNIFI_PROC_BOTH, - UNIFI_PROC_INVALID -}; - -CsrResult unifi_card_stop_processor(card_t *card, enum unifi_dbg_processors_select which); - -/** - * Call-outs from the HIP core lib to the OS layer. - * The following functions need to be implemented during the porting exercise. - */ - -/** - * Selects appropriate queue according to priority - * Helps maintain uniformity in queue selection between the HIP - * and the OS layers. - * - * @param priority priority of the packet - * - * @return \b Traffic queue to which a packet of this priority belongs - * - * @ingroup upperedge - */ -unifi_TrafficQueue -unifi_frame_priority_to_queue(CSR_PRIORITY priority); - -/** - * Returns the priority corresponding to a particular Queue when that is used - * when downgrading a packet to a lower AC. - * Helps maintain uniformity in queue - priority mapping between the HIP - * and the OS layers. - * - * @param queue - * - * @return \b Highest priority corresponding to this queue - * - * @ingroup upperedge - */ -CSR_PRIORITY unifi_get_default_downgrade_priority(unifi_TrafficQueue queue); - -/** - * - * Flow control callbacks. - * unifi_pause_xmit() is called when the HIP core lib does not have any - * resources to store data packets. The OS layer needs to pause - * the Tx data plane until unifi_restart_xmit() is called. - * - * @param ospriv the OS layer context. - * - * @ingroup upperedge - */ -void unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue); -void unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue); - -/** - * - * Request to run the Bottom-Half. - * The HIP core lib calls this function to request that unifi_bh() - * needs to be run by the OS layer. It can be called anytime, i.e. - * when the unifi_bh() is running. - * Since unifi_bh() is not re-entrant, usually unifi_run_bh() sets - * an event to a thread that schedules a call to unifi_bh(). - * - * @param ospriv the OS layer context. - * - * @ingroup upperedge - */ -CsrResult unifi_run_bh(void *ospriv); - -/** - * - * Delivers a signal received from UniFi to the OS layer. - * Normally, the data signals should be delivered to the data plane - * and all the rest to the SME (unifi_sys_hip_ind()). - * - * Note that the OS layer is responsible for freeing the bulkdata - * buffers, using unifi_net_data_free(). - * - * @param ospriv the OS layer context. - * - * @param sigptr pointer to the signal. - * - * @param siglen size of the signal. - * - * @param bulkdata pointer to the bulk data associated with the signal. - * - * @ingroup upperedge - */ -void unifi_receive_event(void *ospriv, - u8 *sigdata, u32 siglen, - const bulk_data_param_t *bulkdata); - -#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL -/** - * - * Used to reque the failed ma packet request back to hal queues - * - * @param ospriv the OS layer context. - * - * @param host_tag host tag for the packet to requeue. - * - * @param bulkDataDesc pointer to the bulk data. - * - * @ingroup upperedge - */ -CsrResult unifi_reque_ma_packet_request(void *ospriv, u32 host_tag, - u16 status, - bulk_data_desc_t *bulkDataDesc); - -#endif -typedef struct -{ - u16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS]; - u16 free_fh_bulkdata_slots; - u16 free_fh_fw_slots; -} unifi_HipQosInfo; - -void unifi_get_hip_qos_info(card_t *card, unifi_HipQosInfo *hipqosinfo); - - -/** - * Functions that read a portion of a firmware file. - * - * Note: If the UniFi chip runs the f/w from ROM, the HIP core may never - * call these functions. Also, the HIP core may call these functions even if - * a f/w file is not available. In this case, it is safe to fail the request. - */ -#define UNIFI_FW_STA 1 /* Identify STA firmware file */ - -/** - * - * Ask the OS layer to initialise a read from a f/w file. - * - * @param ospriv the OS layer context. - * - * @param is_fw if 0 the request if for the loader file, if 1 the request - * is for a f/w file. - * - * @param info a card_info_t structure containing versions information. - * Note that some members of the structure may not be initialised. - * - * @return \p NULL if the file is not available, or a pointer which contains - * OS specific information for the file (typically the contents of the file) - * that the HIP core uses when calling unifi_fw_read() and unifi_fw_read_stop() - * - * @ingroup upperedge - */ -void* unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info); - -/** - * - * Ask the OS layer to return a portion from a f/w file. - * - * @param ospriv the OS layer context. - * - * @param arg the OS pointer returned by unifi_fw_read_start(). - * - * @param offset the offset in the f/w file to read the read from. - * - * @param buf the buffer to store the returned data. - * - * @param len the size in bytes of the requested read. - * - * @ingroup upperedge - */ -s32 unifi_fw_read(void *ospriv, void *arg, u32 offset, void *buf, u32 len); - -/** - * - * Ask the OS layer to finish reading from a f/w file. - * - * @param ospriv the OS layer context. - * - * @param dlpriv the OS pointer returned by unifi_fw_read_start(). - * - * @ingroup upperedge - */ -void unifi_fw_read_stop(void *ospriv, void *dlpriv); - -/** - * - * Ask OS layer for a handle to a dynamically allocated firmware buffer - * (primarily intended for production test images which may need conversion) - * - * @param ospriv the OS layer context. - * - * @param fwbuf pointer to dynamically allocated buffer - * - * @param len length of provided buffer in bytes - * - * @ingroup upperedge - */ -void* unifi_fw_open_buffer(void *ospriv, void *fwbuf, u32 len); - -/** - * - * Release a handle to a dynamically allocated firmware buffer - * (primarily intended for production test images which may need conversion) - * - * @param ospriv the OS layer context. - * - * @param fwbuf pointer to dynamically allocated buffer - * - * @ingroup upperedge - */ -void unifi_fw_close_buffer(void *ospriv, void *fwbuf); - -#ifndef CSR_WIFI_HIP_TA_DISABLE -/* - * Driver must provide these. - * - * A simple implementation will just call - * unifi_sys_traffic_protocol_ind() or unifi_sys_traffic_classification_ind() - * respectively. See sme_csr_userspace/sme_userspace.c. - */ -/** - * - * Indicates a detected packet of type packet_type. - * Typically, this information is processed by the SME so - * unifi_ta_indicate_protocol() needs to schedule a call to - * unifi_sys_traffic_protocol_ind(). - * - * @param ospriv the OS layer context. - * - * @param packet_type the detected packet type. - * - * @param direction the direction of the packet (Rx, Tx). - * - * @param src_addr the source address of the packet. - * - * @ingroup upperedge - */ -void unifi_ta_indicate_protocol(void *ospriv, - CsrWifiRouterCtrlTrafficPacketType packet_type, - CsrWifiRouterCtrlProtocolDirection direction, - const CsrWifiMacAddress *src_addr); - -/** - * - * Indicates statistics for the sample data over a period. - * Typically, this information is processed by the SME so - * unifi_ta_indicate_sampling() needs to schedule a call to - * unifi_sys_traffic_sample_ind(). - * - * @param ospriv the OS layer context. - * - * @param stats the pointer to the structure that contains the statistics. - * - * @ingroup upperedge - */ -void unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats); -void unifi_ta_indicate_l4stats(void *ospriv, - u32 rxTcpThroughput, - u32 txTcpThroughput, - u32 rxUdpThroughput, - u32 txUdpThroughput); -#endif - -void unifi_rx_queue_flush(void *ospriv); - -/** - * Call-out from the SDIO glue layer. - * - * The glue layer needs to call unifi_sdio_interrupt_handler() every time - * an interrupts occurs. - * - * @param card the HIP core context. - * - * @ingroup bottomedge - */ -void unifi_sdio_interrupt_handler(card_t *card); - - -/* HELPER FUNCTIONS */ - -/* - * unifi_init() and unifi_download() implement a subset of unifi_init_card functionality - * that excludes HIP initialization. - */ -CsrResult unifi_init(card_t *card); -CsrResult unifi_download(card_t *card, s32 led_mask); - -/* - * unifi_start_processors() ensures both on-chip processors are running - */ -CsrResult unifi_start_processors(card_t *card); - -CsrResult unifi_capture_panic(card_t *card); - -/* - * Configure HIP interrupt processing mode - */ -#define CSR_WIFI_INTMODE_DEFAULT 0 -#define CSR_WIFI_INTMODE_RUN_BH_ONCE 1 /* Run BH once per interrupt */ - -void unifi_set_interrupt_mode(card_t *card, u32 mode); - -/* - * unifi_request_max_clock() requests that max SDIO clock speed is set at the - * next suitable opportunity. - */ -void unifi_request_max_sdio_clock(card_t *card); - - -/* Functions to lookup bulk data command names. */ -const char* lookup_bulkcmd_name(u16 id); - -/* Function to log HIP's global debug buffer */ -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -void unifi_debug_buf_dump(void); -void unifi_debug_log_to_buf(const char *fmt, ...); -void unifi_debug_hex_to_buf(const char *buff, u16 length); -#endif - -/* Mini-coredump utility functions */ -CsrResult unifi_coredump_get_value(card_t *card, struct unifi_coredump_req *req); -CsrResult unifi_coredump_capture(card_t *card, struct unifi_coredump_req *req); -CsrResult unifi_coredump_request_at_next_reset(card_t *card, s8 enable); -CsrResult unifi_coredump_init(card_t *card, u16 num_dump_buffers); -void unifi_coredump_free(card_t *card); - -#endif /* __CSR_WIFI_HIP_UNIFI_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c b/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c deleted file mode 100644 index 9a3528599f3c..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_unifi_signal_names.c +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include "csr_wifi_hip_unifi.h" - -struct sig_name { - s16 id; - const char *name; -}; - -static const struct sig_name Unifi_bulkcmd_names[] = { - { 0, "SignalCmd" }, - { 1, "CopyToHost" }, - { 2, "CopyToHostAck" }, - { 3, "CopyFromHost" }, - { 4, "CopyFromHostAck" }, - { 5, "ClearSlot" }, - { 6, "CopyOverlay" }, - { 7, "CopyOverlayAck" }, - { 8, "CopyFromHostAndClearSlot" }, - { 15, "Padding" } -}; - -const char *lookup_bulkcmd_name(u16 id) -{ - if (id < 9) - return Unifi_bulkcmd_names[id].name; - if (id == 15) - return "Padding"; - - return "UNKNOWN"; -} - - diff --git a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h b/drivers/staging/csr/csr_wifi_hip_unifi_udi.h deleted file mode 100644 index 4126e85bfe9b..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_unifi_udi.h +++ /dev/null @@ -1,52 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_unifi_udi.h - * - * PURPOSE: - * Declarations and definitions for the UniFi Debug Interface. - * - * --------------------------------------------------------------------------- - */ -#ifndef __CSR_WIFI_HIP_UNIFI_UDI_H__ -#define __CSR_WIFI_HIP_UNIFI_UDI_H__ - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_signals.h" - - -/* - * Support for tracing the wire protocol. - */ -enum udi_log_direction -{ - UDI_LOG_FROM_HOST = 0x0000, - UDI_LOG_TO_HOST = 0x0001 -}; - -typedef void (*udi_func_t)(void *ospriv, u8 *sigdata, - u32 signal_len, - const bulk_data_param_t *bulkdata, - enum udi_log_direction dir); - -CsrResult unifi_set_udi_hook(card_t *card, udi_func_t udi_fn); -CsrResult unifi_remove_udi_hook(card_t *card, udi_func_t udi_fn); - - -/* - * Function to print current status info to a string. - * This is used in the linux /proc interface and might be useful - * in other systems. - */ -s32 unifi_print_status(card_t *card, struct seq_file *m); - -#endif /* __CSR_WIFI_HIP_UNIFI_UDI_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifihw.h b/drivers/staging/csr/csr_wifi_hip_unifihw.h deleted file mode 100644 index 3f9fcbd55b55..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_unifihw.h +++ /dev/null @@ -1,59 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * - * File: csr_wifi_hip_unifihw.h - * - * Definitions of various chip registers, addresses, values etc. - * - * --------------------------------------------------------------------------- - */ -#ifndef __UNIFIHW_H__ -#define __UNIFIHW_H__ 1 - -/* Symbol Look Up Table fingerprint. IDs are in sigs.h */ -#define SLUT_FINGERPRINT 0xD397 - - -/* Values of LoaderOperation */ -#define UNIFI_LOADER_IDLE 0x00 -#define UNIFI_LOADER_COPY 0x01 -#define UNIFI_LOADER_ERROR_MASK 0xF0 - -/* Values of BootLoaderOperation */ -#define UNIFI_BOOT_LOADER_IDLE 0x00 -#define UNIFI_BOOT_LOADER_RESTART 0x01 -#define UNIFI_BOOT_LOADER_PATCH 0x02 -#define UNIFI_BOOT_LOADER_LOAD_STA 0x10 -#define UNIFI_BOOT_LOADER_LOAD_PTEST 0x11 - - -/* Memory spaces encoded in top byte of Generic Pointer type */ -#define UNIFI_SH_DMEM 0x01 /* Shared Data Memory */ -#define UNIFI_EXT_FLASH 0x02 /* External FLASH */ -#define UNIFI_EXT_SRAM 0x03 /* External SRAM */ -#define UNIFI_REGISTERS 0x04 /* Registers */ -#define UNIFI_PHY_DMEM 0x10 /* PHY Data Memory */ -#define UNIFI_PHY_PMEM 0x11 /* PHY Program Memory */ -#define UNIFI_PHY_ROM 0x12 /* PHY ROM */ -#define UNIFI_MAC_DMEM 0x20 /* MAC Data Memory */ -#define UNIFI_MAC_PMEM 0x21 /* MAC Program Memory */ -#define UNIFI_MAC_ROM 0x22 /* MAC ROM */ -#define UNIFI_BT_DMEM 0x30 /* BT Data Memory */ -#define UNIFI_BT_PMEM 0x31 /* BT Program Memory */ -#define UNIFI_BT_ROM 0x32 /* BT ROM */ - -#define UNIFI_MAKE_GP(R, O) (((UNIFI_ ## R) << 24) | (O)) -#define UNIFI_GP_OFFSET(GP) ((GP) & 0xFFFFFF) -#define UNIFI_GP_SPACE(GP) (((GP) >> 24) & 0xFF) - -#endif /* __UNIFIHW_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_unifiversion.h b/drivers/staging/csr/csr_wifi_hip_unifiversion.h deleted file mode 100644 index d1c66783f32c..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_unifiversion.h +++ /dev/null @@ -1,30 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: unifiversion.h - * - * PURPOSE: - * Version information for the portable UniFi driver. - * - * --------------------------------------------------------------------------- - */ - -#ifndef __UNIFIVERSION_H__ -#define __UNIFIVERSION_H__ - -/* - * The minimum version of Host Interface Protocol required by the driver. - */ -#define UNIFI_HIP_MAJOR_VERSION 9 -#define UNIFI_HIP_MINOR_VERSION 1 - -#endif /* __UNIFIVERSION_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.c b/drivers/staging/csr/csr_wifi_hip_xbv.c deleted file mode 100644 index 050a15fbadf9..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_xbv.c +++ /dev/null @@ -1,1076 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_xbv.c - * - * PURPOSE: - * Routines for downloading firmware to UniFi. - * - * UniFi firmware files use a nested TLV (Tag-Length-Value) format. - * - * --------------------------------------------------------------------------- - */ -#include - -#ifdef CSR_WIFI_XBV_TEST -/* Standalone test harness */ -#include "unifi_xbv.h" -#include "csr_wifi_hip_unifihw.h" -#else -/* Normal driver build */ -#include "csr_wifi_hip_unifiversion.h" -#include "csr_wifi_hip_card.h" -#define DBG_TAG(t) -#endif - -#include "csr_wifi_hip_xbv.h" - -#define STREAM_CHECKSUM 0x6d34 /* Sum of uint16s in each patch stream */ - -/* XBV sizes used in patch conversion - */ -#define PTDL_MAX_SIZE 2048 /* Max bytes allowed per PTDL */ -#define PTDL_HDR_SIZE (4 + 2 + 6 + 2) /* sizeof(fw_id, sec_len, patch_cmd, csum) */ - -/* Struct to represent a buffer for reading firmware file */ - -typedef struct -{ - void *dlpriv; - s32 ioffset; - fwreadfn_t iread; -} ct_t; - -/* Struct to represent a TLV field */ -typedef struct -{ - char t_name[4]; - u32 t_len; -} tag_t; - - -#define TAG_EQ(i, v) (((i)[0] == (v)[0]) && \ - ((i)[1] == (v)[1]) && \ - ((i)[2] == (v)[2]) && \ - ((i)[3] == (v)[3])) - -/* We create a small stack on the stack that contains an enum - * indicating the containing list segments, and the offset at which - * those lists end. This enables a lot more error checking. */ -typedef enum -{ - xbv_xbv1, - /*xbv_info,*/ - xbv_fw, - xbv_vers, - xbv_vand, - xbv_ptch, - xbv_other -} xbv_container; - -#define XBV_STACK_SIZE 6 -#define XBV_MAX_OFFS 0x7fffffff - -typedef struct -{ - struct - { - xbv_container container; - s32 ioffset_end; - } s[XBV_STACK_SIZE]; - u32 ptr; -} xbv_stack_t; - -static s32 read_tag(card_t *card, ct_t *ct, tag_t *tag); -static s32 read_bytes(card_t *card, ct_t *ct, void *buf, u32 len); -static s32 read_uint(card_t *card, ct_t *ct, u32 *u, u32 len); -static s32 xbv_check(xbv1_t *fwinfo, const xbv_stack_t *stack, - xbv_mode new_mode, xbv_container old_cont); -static s32 xbv_push(xbv1_t *fwinfo, xbv_stack_t *stack, - xbv_mode new_mode, xbv_container old_cont, - xbv_container new_cont, u32 ioff); - -static u32 write_uint16(void *buf, const u32 offset, - const u16 val); -static u32 write_uint32(void *buf, const u32 offset, - const u32 val); -static u32 write_bytes(void *buf, const u32 offset, - const u8 *data, const u32 len); -static u32 write_tag(void *buf, const u32 offset, - const char *tag_str); -static u32 write_chunk(void *buf, const u32 offset, - const char *tag_str, - const u32 payload_len); -static u16 calc_checksum(void *buf, const u32 offset, - const u32 bytes_len); -static u32 calc_patch_size(const xbv1_t *fwinfo); - -static u32 write_xbv_header(void *buf, const u32 offset, - const u32 file_payload_length); -static u32 write_ptch_header(void *buf, const u32 offset, - const u32 fw_id); -static u32 write_patchcmd(void *buf, const u32 offset, - const u32 dst_genaddr, const u16 len); -static u32 write_reset_ptdl(void *buf, const u32 offset, - const xbv1_t *fwinfo, u32 fw_id); -static u32 write_fwdl_to_ptdl(void *buf, const u32 offset, - fwreadfn_t readfn, const struct FWDL *fwdl, - const void *fw_buf, const u32 fw_id, - void *rdbuf); - -/* - * --------------------------------------------------------------------------- - * parse_xbv1 - * - * Scan the firmware file to find the TLVs we are interested in. - * Actions performed: - * - check we support the file format version in VERF - * Store these TLVs if we have a firmware image: - * - SLTP Symbol Lookup Table Pointer - * - FWDL firmware download segments - * - FWOL firmware overlay segment - * - VMEQ Register probe tests to verify matching h/w - * Store these TLVs if we have a patch file: - * - FWID the firmware build ID that this file patches - * - PTDL The actual patches - * - * The structure pointed to by fwinfo is cleared and - * 'fwinfo->mode' is set to 'unknown'. The 'fwinfo->mode' - * variable is set to 'firmware' or 'patch' once we know which - * sort of XBV file we have. - * - * Arguments: - * readfn Pointer to function to call to read from the file. - * dlpriv Opaque pointer arg to pass to readfn. - * fwinfo Pointer to fwinfo struct to fill in. - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR error code on failure - * --------------------------------------------------------------------------- - */ -CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo) -{ - ct_t ct; - tag_t tag; - xbv_stack_t stack; - - ct.dlpriv = dlpriv; - ct.ioffset = 0; - ct.iread = readfn; - - memset(fwinfo, 0, sizeof(xbv1_t)); - fwinfo->mode = xbv_unknown; - - /* File must start with XBV1 triplet */ - if (read_tag(card, &ct, &tag) <= 0) - { - unifi_error(NULL, "File is not UniFi firmware\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - DBG_TAG(tag.t_name); - - if (!TAG_EQ(tag.t_name, "XBV1")) - { - unifi_error(NULL, "File is not UniFi firmware (%s)\n", tag.t_name); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - stack.ptr = 0; - stack.s[stack.ptr].container = xbv_xbv1; - stack.s[stack.ptr].ioffset_end = XBV_MAX_OFFS; - - /* Now scan the file */ - while (1) - { - s32 n; - - n = read_tag(card, &ct, &tag); - if (n < 0) - { - unifi_error(NULL, "No tag\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - if (n == 0) - { - /* End of file */ - break; - } - - DBG_TAG(tag.t_name); - - /* File format version */ - if (TAG_EQ(tag.t_name, "VERF")) - { - u32 version; - - if (xbv_check(fwinfo, &stack, xbv_unknown, xbv_xbv1) || - (tag.t_len != 2) || - read_uint(card, &ct, &version, 2)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - if (version != 0) - { - unifi_error(NULL, "Unsupported firmware file version: %d.%d\n", - version >> 8, version & 0xFF); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - } - else if (TAG_EQ(tag.t_name, "LIST")) - { - char name[4]; - u32 list_end; - - list_end = ct.ioffset + tag.t_len; - - if (read_bytes(card, &ct, name, 4)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - DBG_TAG(name); - if (TAG_EQ(name, "FW ")) - { - if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_xbv1, xbv_fw, list_end)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - } - else if (TAG_EQ(name, "VERS")) - { - if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_fw, xbv_vers, list_end) || - (fwinfo->vers.num_vand != 0)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - } - else if (TAG_EQ(name, "VAND")) - { - struct VAND *vand; - - if (xbv_push(fwinfo, &stack, xbv_firmware, xbv_vers, xbv_vand, list_end) || - (fwinfo->vers.num_vand >= MAX_VAND)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* Get a new VAND */ - vand = fwinfo->vand + fwinfo->vers.num_vand++; - - /* Fill it in */ - vand->first = fwinfo->num_vmeq; - vand->count = 0; - } - else if (TAG_EQ(name, "PTCH")) - { - if (xbv_push(fwinfo, &stack, xbv_patch, xbv_xbv1, xbv_ptch, list_end)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - } - else - { - /* Skip over any other lists. We dont bother to push - * the new list type now as we would only pop it at - * the end of the outer loop. */ - ct.ioffset += tag.t_len - 4; - } - } - else if (TAG_EQ(tag.t_name, "SLTP")) - { - u32 addr; - - if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || - (tag.t_len != 4) || - (fwinfo->slut_addr != 0) || - read_uint(card, &ct, &addr, 4)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - fwinfo->slut_addr = addr; - } - else if (TAG_EQ(tag.t_name, "FWDL")) - { - u32 addr; - struct FWDL *fwdl; - - if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || - (fwinfo->num_fwdl >= MAX_FWDL) || - (read_uint(card, &ct, &addr, 4))) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - fwdl = fwinfo->fwdl + fwinfo->num_fwdl++; - - fwdl->dl_size = tag.t_len - 4; - fwdl->dl_addr = addr; - fwdl->dl_offset = ct.ioffset; - - ct.ioffset += tag.t_len - 4; - } - else if (TAG_EQ(tag.t_name, "FWOV")) - { - if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_fw) || - (fwinfo->fwov.dl_size != 0) || - (fwinfo->fwov.dl_offset != 0)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - fwinfo->fwov.dl_size = tag.t_len; - fwinfo->fwov.dl_offset = ct.ioffset; - - ct.ioffset += tag.t_len; - } - else if (TAG_EQ(tag.t_name, "VMEQ")) - { - u32 temp[3]; - struct VAND *vand; - struct VMEQ *vmeq; - - if (xbv_check(fwinfo, &stack, xbv_firmware, xbv_vand) || - (fwinfo->num_vmeq >= MAX_VMEQ) || - (fwinfo->vers.num_vand == 0) || - (tag.t_len != 8) || - read_uint(card, &ct, &temp[0], 4) || - read_uint(card, &ct, &temp[1], 2) || - read_uint(card, &ct, &temp[2], 2)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* Get the last VAND */ - vand = fwinfo->vand + (fwinfo->vers.num_vand - 1); - - /* Get a new VMEQ */ - vmeq = fwinfo->vmeq + fwinfo->num_vmeq++; - - /* Note that this VAND contains another VMEQ */ - vand->count++; - - /* Fill in the VMEQ */ - vmeq->addr = temp[0]; - vmeq->mask = (u16)temp[1]; - vmeq->value = (u16)temp[2]; - } - else if (TAG_EQ(tag.t_name, "FWID")) - { - u32 build_id; - - if (xbv_check(fwinfo, &stack, xbv_patch, xbv_ptch) || - (tag.t_len != 4) || - (fwinfo->build_id != 0) || - read_uint(card, &ct, &build_id, 4)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - fwinfo->build_id = build_id; - } - else if (TAG_EQ(tag.t_name, "PTDL")) - { - struct PTDL *ptdl; - - if (xbv_check(fwinfo, &stack, xbv_patch, xbv_ptch) || - (fwinfo->num_ptdl >= MAX_PTDL)) - { - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - /* Allocate a new PTDL */ - ptdl = fwinfo->ptdl + fwinfo->num_ptdl++; - - ptdl->dl_size = tag.t_len; - ptdl->dl_offset = ct.ioffset; - - ct.ioffset += tag.t_len; - } - else - { - /* - * If we get here it is a tag we are not interested in, - * just skip over it. - */ - ct.ioffset += tag.t_len; - } - - /* Check to see if we are at the end of the currently stacked - * segment. We could finish more than one list at a time. */ - while (ct.ioffset >= stack.s[stack.ptr].ioffset_end) - { - if (ct.ioffset > stack.s[stack.ptr].ioffset_end) - { - unifi_error(NULL, - "XBV file has overrun stack'd segment %d (%d > %d)\n", - stack.ptr, ct.ioffset, stack.s[stack.ptr].ioffset_end); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - if (stack.ptr <= 0) - { - unifi_error(NULL, "XBV file has underrun stack pointer\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - stack.ptr--; - } - } - - if (stack.ptr != 0) - { - unifi_error(NULL, "Last list of XBV is not complete.\n"); - return CSR_WIFI_HIP_RESULT_INVALID_VALUE; - } - - return CSR_RESULT_SUCCESS; -} /* xbv1_parse() */ - - -/* Check the the XBV file is of a consistant sort (either firmware or - * patch) and that we are in the correct containing list type. */ -static s32 xbv_check(xbv1_t *fwinfo, const xbv_stack_t *stack, - xbv_mode new_mode, xbv_container old_cont) -{ - /* If the new file mode is unknown the current packet could be in - * either (any) type of XBV file, and we cant make a decission at - * this time. */ - if (new_mode != xbv_unknown) - { - if (fwinfo->mode == xbv_unknown) - { - fwinfo->mode = new_mode; - } - else if (fwinfo->mode != new_mode) - { - return -1; - } - } - /* If the current stack top doesn't match what we expect then the - * file is corrupt. */ - if (stack->s[stack->ptr].container != old_cont) - { - return -1; - } - return 0; -} - - -/* Make checks as above and then enter a new list */ -static s32 xbv_push(xbv1_t *fwinfo, xbv_stack_t *stack, - xbv_mode new_mode, xbv_container old_cont, - xbv_container new_cont, u32 new_ioff) -{ - if (xbv_check(fwinfo, stack, new_mode, old_cont)) - { - return -1; - } - - /* Check that our stack won't overflow. */ - if (stack->ptr >= (XBV_STACK_SIZE - 1)) - { - return -1; - } - - /* Add the new list element to the top of the stack. */ - stack->ptr++; - stack->s[stack->ptr].container = new_cont; - stack->s[stack->ptr].ioffset_end = new_ioff; - - return 0; -} - - -static u32 xbv2uint(u8 *ptr, s32 len) -{ - u32 u = 0; - s16 i; - - for (i = 0; i < len; i++) - { - u32 b; - b = ptr[i]; - u += b << (i * 8); - } - return u; -} - - -static s32 read_tag(card_t *card, ct_t *ct, tag_t *tag) -{ - u8 buf[8]; - s32 n; - - n = (*ct->iread)(card->ospriv, ct->dlpriv, ct->ioffset, buf, 8); - if (n <= 0) - { - return n; - } - - /* read the tag and length */ - if (n != 8) - { - return -1; - } - - /* get section tag */ - memcpy(tag->t_name, buf, 4); - - /* get section length */ - tag->t_len = xbv2uint(buf + 4, 4); - - ct->ioffset += 8; - - return 8; -} /* read_tag() */ - - -static s32 read_bytes(card_t *card, ct_t *ct, void *buf, u32 len) -{ - /* read the tag value */ - if ((*ct->iread)(card->ospriv, ct->dlpriv, ct->ioffset, buf, len) != (s32)len) - { - return -1; - } - - ct->ioffset += len; - - return 0; -} /* read_bytes() */ - - -static s32 read_uint(card_t *card, ct_t *ct, u32 *u, u32 len) -{ - u8 buf[4]; - - /* Integer cannot be more than 4 bytes */ - if (len > 4) - { - return -1; - } - - if (read_bytes(card, ct, buf, len)) - { - return -1; - } - - *u = xbv2uint(buf, len); - - return 0; -} /* read_uint() */ - - -static u32 write_uint16(void *buf, const u32 offset, const u16 val) -{ - u8 *dst = (u8 *)buf + offset; - *dst++ = (u8)(val & 0xff); /* LSB first */ - *dst = (u8)(val >> 8); - return sizeof(u16); -} - - -static u32 write_uint32(void *buf, const u32 offset, const u32 val) -{ - (void)write_uint16(buf, offset + 0, (u16)(val & 0xffff)); - (void)write_uint16(buf, offset + 2, (u16)(val >> 16)); - return sizeof(u32); -} - - -static u32 write_bytes(void *buf, const u32 offset, const u8 *data, const u32 len) -{ - u32 i; - u8 *dst = (u8 *)buf + offset; - - for (i = 0; i < len; i++) - { - *dst++ = *((u8 *)data + i); - } - return len; -} - - -static u32 write_tag(void *buf, const u32 offset, const char *tag_str) -{ - u8 *dst = (u8 *)buf + offset; - memcpy(dst, tag_str, 4); - return 4; -} - - -static u32 write_chunk(void *buf, const u32 offset, const char *tag_str, const u32 payload_len) -{ - u32 written = 0; - written += write_tag(buf, offset, tag_str); - written += write_uint32(buf, written + offset, (u32)payload_len); - - return written; -} - - -static u16 calc_checksum(void *buf, const u32 offset, const u32 bytes_len) -{ - u32 i; - u8 *src = (u8 *)buf + offset; - u16 sum = 0; - u16 val; - - for (i = 0; i < bytes_len / 2; i++) - { - /* Contents copied to file is LE, host might not be */ - val = (u16) * src++; /* LSB */ - val += (u16)(*src++) << 8; /* MSB */ - sum += val; - } - - /* Total of uint16s in the stream plus the stored check value - * should equal STREAM_CHECKSUM when decoded. - */ - return (STREAM_CHECKSUM - sum); -} - - -#define PTDL_RESET_DATA_SIZE 20 /* Size of reset vectors PTDL */ - -static u32 calc_patch_size(const xbv1_t *fwinfo) -{ - s16 i; - u32 size = 0; - - /* - * Work out how big an equivalent patch format file must be for this image. - * This only needs to be approximate, so long as it's large enough. - */ - if (fwinfo->mode != xbv_firmware) - { - return 0; - } - - /* Payload (which will get put into a series of PTDLs) */ - for (i = 0; i < fwinfo->num_fwdl; i++) - { - size += fwinfo->fwdl[i].dl_size; - } - - /* Another PTDL at the end containing reset vectors */ - size += PTDL_RESET_DATA_SIZE; - - /* PTDL headers. Add one for remainder, one for reset vectors */ - size += ((fwinfo->num_fwdl / PTDL_MAX_SIZE) + 2) * PTDL_HDR_SIZE; - - /* Another 1K sufficient to cover miscellaneous headers */ - size += 1024; - - return size; -} - - -static u32 write_xbv_header(void *buf, const u32 offset, const u32 file_payload_length) -{ - u32 written = 0; - - /* The length value given to the XBV chunk is the length of all subsequent - * contents of the file, excluding the 8 byte size of the XBV1 header itself - * (The added 6 bytes thus accounts for the size of the VERF) - */ - written += write_chunk(buf, offset + written, (char *)"XBV1", file_payload_length + 6); - - written += write_chunk(buf, offset + written, (char *)"VERF", 2); - written += write_uint16(buf, offset + written, 0); /* File version */ - - return written; -} - - -static u32 write_ptch_header(void *buf, const u32 offset, const u32 fw_id) -{ - u32 written = 0; - - /* LIST is written with a zero length, to be updated later */ - written += write_chunk(buf, offset + written, (char *)"LIST", 0); - written += write_tag(buf, offset + written, (char *)"PTCH"); /* List type */ - - written += write_chunk(buf, offset + written, (char *)"FWID", 4); - written += write_uint32(buf, offset + written, fw_id); - - - return written; -} - - -#define UF_REGION_PHY 1 -#define UF_REGION_MAC 2 -#define UF_MEMPUT_MAC 0x0000 -#define UF_MEMPUT_PHY 0x1000 - -static u32 write_patchcmd(void *buf, const u32 offset, const u32 dst_genaddr, const u16 len) -{ - u32 written = 0; - u32 region = (dst_genaddr >> 28); - u16 cmd_and_len = UF_MEMPUT_MAC; - - if (region == UF_REGION_PHY) - { - cmd_and_len = UF_MEMPUT_PHY; - } - else if (region != UF_REGION_MAC) - { - return 0; /* invalid */ - } - - /* Write the command and data length */ - cmd_and_len |= len; - written += write_uint16(buf, offset + written, cmd_and_len); - - /* Write the destination generic address */ - written += write_uint16(buf, offset + written, (u16)(dst_genaddr >> 16)); - written += write_uint16(buf, offset + written, (u16)(dst_genaddr & 0xffff)); - - /* The data payload should be appended to the command */ - return written; -} - - -static u32 write_fwdl_to_ptdl(void *buf, const u32 offset, fwreadfn_t readfn, - const struct FWDL *fwdl, const void *dlpriv, - const u32 fw_id, void *fw_buf) -{ - u32 written = 0; - s16 chunks = 0; - u32 left = fwdl->dl_size; /* Bytes left in this fwdl */ - u32 dl_addr = fwdl->dl_addr; /* Target address of fwdl image on XAP */ - u32 dl_offs = fwdl->dl_offset; /* Offset of fwdl image data in source */ - u16 csum; - u32 csum_start_offs; /* first offset to include in checksum */ - u32 sec_data_len; /* section data byte count */ - u32 sec_len; /* section data + header byte count */ - - /* FWDL maps to one or more PTDLs, as max size for a PTDL is 1K words */ - while (left) - { - /* Calculate amount to be transferred */ - sec_data_len = min_t(u32, left, PTDL_MAX_SIZE - PTDL_HDR_SIZE); - sec_len = sec_data_len + PTDL_HDR_SIZE; - - /* Write PTDL header + entire PTDL size */ - written += write_chunk(buf, offset + written, (char *)"PTDL", sec_len); - /* bug digest implies 4 bytes of padding here, but that seems wrong */ - - /* Checksum starts here */ - csum_start_offs = offset + written; - - /* Patch-chunk header: fw_id. Note that this is in XAP word order */ - written += write_uint16(buf, offset + written, (u16)(fw_id >> 16)); - written += write_uint16(buf, offset + written, (u16)(fw_id & 0xffff)); - - /* Patch-chunk header: section length in uint16s */ - written += write_uint16(buf, offset + written, (u16)(sec_len / 2)); - - - /* Write the appropriate patch command for the data's destination ptr */ - written += write_patchcmd(buf, offset + written, dl_addr, (u16)(sec_data_len / 2)); - - /* Write the data itself (limited to the max chunk length) */ - if (readfn(NULL, (void *)dlpriv, dl_offs, fw_buf, sec_data_len) < 0) - { - return 0; - } - - written += write_bytes(buf, - offset + written, - fw_buf, - sec_data_len); - - /* u16 checksum calculated over data written */ - csum = calc_checksum(buf, csum_start_offs, written - (csum_start_offs - offset)); - written += write_uint16(buf, offset + written, csum); - - left -= sec_data_len; - dl_addr += sec_data_len; - dl_offs += sec_data_len; - chunks++; - } - - return written; -} - - -#define SEC_CMD_LEN ((4 + 2) * 2) /* sizeof(cmd, vector) per XAP */ -#define PTDL_VEC_HDR_SIZE (4 + 2 + 2) /* sizeof(fw_id, sec_len, csum) */ -#define UF_MAC_START_VEC 0x00c00000 /* Start address of image on MAC */ -#define UF_PHY_START_VEC 0x00c00000 /* Start address of image on PHY */ -#define UF_MAC_START_CMD 0x6000 /* MAC "Set start address" command */ -#define UF_PHY_START_CMD 0x7000 /* PHY "Set start address" command */ - -static u32 write_reset_ptdl(void *buf, const u32 offset, const xbv1_t *fwinfo, u32 fw_id) -{ - u32 written = 0; - u16 csum; - u32 csum_start_offs; /* first offset to include in checksum */ - u32 sec_len; /* section data + header byte count */ - - sec_len = SEC_CMD_LEN + PTDL_VEC_HDR_SIZE; /* Total section byte length */ - - /* Write PTDL header + entire PTDL size */ - written += write_chunk(buf, offset + written, (char *)"PTDL", sec_len); - - /* Checksum starts here */ - csum_start_offs = offset + written; - - /* Patch-chunk header: fw_id. Note that this is in XAP word order */ - written += write_uint16(buf, offset + written, (u16)(fw_id >> 16)); - written += write_uint16(buf, offset + written, (u16)(fw_id & 0xffff)); - - /* Patch-chunk header: section length in uint16s */ - written += write_uint16(buf, offset + written, (u16)(sec_len / 2)); - - /* - * Restart addresses to be executed on subsequent loader restart command. - */ - - /* Setup the MAC start address, note word ordering */ - written += write_uint16(buf, offset + written, UF_MAC_START_CMD); - written += write_uint16(buf, offset + written, (UF_MAC_START_VEC >> 16)); - written += write_uint16(buf, offset + written, (UF_MAC_START_VEC & 0xffff)); - - /* Setup the PHY start address, note word ordering */ - written += write_uint16(buf, offset + written, UF_PHY_START_CMD); - written += write_uint16(buf, offset + written, (UF_PHY_START_VEC >> 16)); - written += write_uint16(buf, offset + written, (UF_PHY_START_VEC & 0xffff)); - - /* u16 checksum calculated over data written */ - csum = calc_checksum(buf, csum_start_offs, written - (csum_start_offs - offset)); - written += write_uint16(buf, offset + written, csum); - - return written; -} - - -/* - * --------------------------------------------------------------------------- - * read_slut - * - * desc - * - * Arguments: - * readfn Pointer to function to call to read from the file. - * dlpriv Opaque pointer arg to pass to readfn. - * addr Offset into firmware image of SLUT. - * fwinfo Pointer to fwinfo struct to fill in. - * - * Returns: - * Number of SLUT entries in the f/w, or -1 if the image was corrupt. - * --------------------------------------------------------------------------- - */ -s32 xbv1_read_slut(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo, - symbol_t *slut, u32 slut_len) -{ - s16 i; - s32 offset; - u32 magic; - u32 count = 0; - ct_t ct; - - if (fwinfo->mode != xbv_firmware) - { - return -1; - } - - /* Find the d/l segment containing the SLUT */ - /* This relies on the SLUT being entirely contained in one segment */ - offset = -1; - for (i = 0; i < fwinfo->num_fwdl; i++) - { - if ((fwinfo->slut_addr >= fwinfo->fwdl[i].dl_addr) && - (fwinfo->slut_addr < (fwinfo->fwdl[i].dl_addr + fwinfo->fwdl[i].dl_size))) - { - offset = fwinfo->fwdl[i].dl_offset + - (fwinfo->slut_addr - fwinfo->fwdl[i].dl_addr); - } - } - if (offset < 0) - { - return -1; - } - - ct.dlpriv = dlpriv; - ct.ioffset = offset; - ct.iread = readfn; - - if (read_uint(card, &ct, &magic, 2)) - { - return -1; - } - if (magic != SLUT_FINGERPRINT) - { - return -1; - } - - while (count < slut_len) - { - u32 id, obj; - - /* Read Symbol Id */ - if (read_uint(card, &ct, &id, 2)) - { - return -1; - } - - /* Check for end of table marker */ - if (id == CSR_SLT_END) - { - break; - } - - /* Read Symbol Value */ - if (read_uint(card, &ct, &obj, 4)) - { - return -1; - } - - slut[count].id = (u16)id; - slut[count].obj = obj; - count++; - } - - return count; -} /* read_slut() */ - - -/* - * --------------------------------------------------------------------------- - * xbv_to_patch - * - * Convert (the relevant parts of) a firmware xbv file into a patch xbv - * - * Arguments: - * card - * fw_buf - pointer to xbv firmware image - * fwinfo - structure describing the firmware image - * size - pointer to location into which size of f/w is written. - * - * Returns: - * Pointer to firmware image, or NULL on error. Caller must free this - * buffer via kfree() once it's finished with. - * - * Notes: - * The input fw_buf should have been checked via xbv1_parse prior to - * calling this function, so the input image is assumed valid. - * --------------------------------------------------------------------------- - */ -#define PTCH_LIST_SIZE 16 /* sizeof PTCH+FWID chunk in LIST header */ - -void* xbv_to_patch(card_t *card, fwreadfn_t readfn, - const void *fw_buf, const xbv1_t *fwinfo, u32 *size) -{ - void *patch_buf = NULL; - u32 patch_buf_size; - u32 payload_offs = 0; /* Start of XBV payload */ - s16 i; - u32 patch_offs = 0; - u32 list_len_offs = 0; /* Offset of PTDL LIST length parameter */ - u32 ptdl_start_offs = 0; /* Offset of first PTDL chunk */ - u32 fw_id; - void *rdbuf; - - if (!fw_buf || !fwinfo || !card) - { - return NULL; - } - - if (fwinfo->mode != xbv_firmware) - { - unifi_error(NULL, "Not a firmware file\n"); - return NULL; - } - - /* Pre-allocate read buffer for chunk conversion */ - rdbuf = kmalloc(PTDL_MAX_SIZE, GFP_KERNEL); - if (!rdbuf) - { - unifi_error(card, "Couldn't alloc conversion buffer\n"); - return NULL; - } - - /* Loader requires patch file's build ID to match the running firmware's */ - fw_id = card->build_id; - - /* Firmware XBV1 contains VERF, optional INFO, SLUT(s), FWDL(s) */ - /* Other chunks should get skipped. */ - /* VERF should be sanity-checked against chip version */ - - /* Patch XBV1 contains VERF, optional INFO, PTCH */ - /* PTCH contains FWID, optional INFO, PTDL(s), PTDL(start_vec) */ - /* Each FWDL is split into PTDLs (each is 1024 XAP words max) */ - /* Each PTDL contains running ROM f/w version, and checksum */ - /* MAC/PHY reset addresses (known) are added into a final PTDL */ - - /* The input image has already been parsed, and loaded into fwinfo, so we - * can use that to build the output image - */ - patch_buf_size = calc_patch_size(fwinfo); - - patch_buf = kmalloc(patch_buf_size, GFP_KERNEL); - if (!patch_buf) - { - kfree(rdbuf); - unifi_error(NULL, "Can't malloc buffer for patch conversion\n"); - return NULL; - } - - memset(patch_buf, 0xdd, patch_buf_size); - - /* Write XBV + VERF headers */ - patch_offs += write_xbv_header(patch_buf, patch_offs, 0); - payload_offs = patch_offs; - - /* Write patch (LIST) header */ - list_len_offs = patch_offs + 4; /* Save LIST.length offset for later update */ - patch_offs += write_ptch_header(patch_buf, patch_offs, fw_id); - - /* Save start offset of the PTDL chunks */ - ptdl_start_offs = patch_offs; - - /* Write LIST of firmware PTDL blocks */ - for (i = 0; i < fwinfo->num_fwdl; i++) - { - patch_offs += write_fwdl_to_ptdl(patch_buf, - patch_offs, - readfn, - &fwinfo->fwdl[i], - fw_buf, - fw_id, - rdbuf); - } - - /* Write restart-vector PTDL last */ - patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id); - - /* Now the length is known, update the LIST.length */ - (void)write_uint32(patch_buf, list_len_offs, - (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE); - - /* Re write XBV headers just to fill in the correct file size */ - (void)write_xbv_header(patch_buf, 0, (patch_offs - payload_offs)); - - unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n", - patch_offs, fw_id); - if (size) - { - *size = patch_offs; - } - kfree(rdbuf); - - return patch_buf; -} - - diff --git a/drivers/staging/csr/csr_wifi_hip_xbv.h b/drivers/staging/csr/csr_wifi_hip_xbv.h deleted file mode 100644 index 3c507235323d..000000000000 --- a/drivers/staging/csr/csr_wifi_hip_xbv.h +++ /dev/null @@ -1,119 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* - * --------------------------------------------------------------------------- - * FILE: csr_wifi_hip_xbv.h - * - * PURPOSE: - * Definitions and declarations for code to read XBV files - the UniFi - * firmware download file format. - * - * --------------------------------------------------------------------------- - */ -#ifndef __XBV_H__ -#define __XBV_H__ - -#ifndef CSR_WIFI_XBV_TEST -/* Driver includes */ -#include "csr_wifi_hip_unifi.h" -#endif - - -struct VMEQ -{ - u32 addr; - u16 mask; - u16 value; -}; - -struct VAND -{ - u32 first; - u32 count; -}; - -struct VERS -{ - u32 num_vand; -}; - -struct FWDL -{ - u32 dl_addr; - u32 dl_size; - u32 dl_offset; -}; - -struct FWOV -{ - u32 dl_size; - u32 dl_offset; -}; - -struct PTDL -{ - u32 dl_size; - u32 dl_offset; -}; - -#define MAX_VMEQ 64 -#define MAX_VAND 64 -#define MAX_FWDL 256 -#define MAX_PTDL 256 - -/* An XBV1 file can either contain firmware or patches (at the - * moment). The 'mode' member of the xbv1_t structure tells us which - * one is the case. */ -typedef enum -{ - xbv_unknown, - xbv_firmware, - xbv_patch -} xbv_mode; - -typedef struct -{ - xbv_mode mode; - - /* Parts of a Firmware XBV1 */ - - struct VMEQ vmeq[MAX_VMEQ]; - u32 num_vmeq; - struct VAND vand[MAX_VAND]; - struct VERS vers; - - u32 slut_addr; - - /* F/W download image, possibly more than one part */ - struct FWDL fwdl[MAX_FWDL]; - s16 num_fwdl; - - /* F/W overlay image, add r not used */ - struct FWOV fwov; - - /* Parts of a Patch XBV1 */ - - u32 build_id; - - struct PTDL ptdl[MAX_PTDL]; - s16 num_ptdl; -} xbv1_t; - - -typedef s32 (*fwreadfn_t)(void *ospriv, void *dlpriv, u32 offset, void *buf, u32 len); - -CsrResult xbv1_parse(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo); -s32 xbv1_read_slut(card_t *card, fwreadfn_t readfn, void *dlpriv, xbv1_t *fwinfo, - symbol_t *slut, u32 slut_len); -void* xbv_to_patch(card_t *card, fwreadfn_t readfn, const void *fw_buf, const xbv1_t *fwinfo, - u32 *size); - -#endif /* __XBV_H__ */ diff --git a/drivers/staging/csr/csr_wifi_hostio_prim.h b/drivers/staging/csr/csr_wifi_hostio_prim.h deleted file mode 100644 index cfb3e272e359..000000000000 --- a/drivers/staging/csr/csr_wifi_hostio_prim.h +++ /dev/null @@ -1,18 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - - -#ifndef CSR_WIFI_HOSTIO_H -#define CSR_WIFI_HOSTIO_H - -#define CSR_WIFI_HOSTIO_PRIM 0x0453 - -#endif /* CSR_WIFI_HOSTIO_H */ - diff --git a/drivers/staging/csr/csr_wifi_lib.h b/drivers/staging/csr/csr_wifi_lib.h deleted file mode 100644 index 5fde0efb5dca..000000000000 --- a/drivers/staging/csr/csr_wifi_lib.h +++ /dev/null @@ -1,103 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ -#ifndef CSR_WIFI_LIB_H__ -#define CSR_WIFI_LIB_H__ - -#include "csr_wifi_fsm_event.h" - -/*----------------------------------------------------------------------------* - * CsrWifiFsmEventInit - * - * DESCRIPTION - * Macro to initialise the members of a CsrWifiFsmEvent. - *----------------------------------------------------------------------------*/ -#define CsrWifiFsmEventInit(evt, p_primtype, p_msgtype, p_dst, p_src) \ - (evt)->primtype = p_primtype; \ - (evt)->type = p_msgtype; \ - (evt)->destination = p_dst; \ - (evt)->source = p_src - - -/*----------------------------------------------------------------------------* - * CsrWifiEvent_struct - * - * DESCRIPTION - * Generic message creator. - * Allocates and fills in a message with the signature CsrWifiEvent - * - *----------------------------------------------------------------------------*/ -CsrWifiFsmEvent* CsrWifiEvent_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src); - -typedef struct -{ - CsrWifiFsmEvent common; - u8 value; -} CsrWifiEventCsrUint8; - -/*----------------------------------------------------------------------------* - * CsrWifiEventCsrUint8_struct - * - * DESCRIPTION - * Generic message creator. - * Allocates and fills in a message with the signature CsrWifiEventCsrUint8 - * - *----------------------------------------------------------------------------*/ -CsrWifiEventCsrUint8* CsrWifiEventCsrUint8_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src, u8 value); - -typedef struct -{ - CsrWifiFsmEvent common; - u16 value; -} CsrWifiEventCsrUint16; - -/*----------------------------------------------------------------------------* - * CsrWifiEventCsrUint16_struct - * - * DESCRIPTION - * Generic message creator. - * Allocates and fills in a message with the signature CsrWifiEventCsrUint16 - * - *----------------------------------------------------------------------------*/ -CsrWifiEventCsrUint16* CsrWifiEventCsrUint16_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src, u16 value); - -typedef struct -{ - CsrWifiFsmEvent common; - u32 value; -} CsrWifiEventCsrUint32; - -/*----------------------------------------------------------------------------* - * CsrWifiEventCsrUint32_struct - * - * DESCRIPTION - * Generic message creator. - * Allocates and fills in a message with the signature CsrWifiEventCsrUint32 - * - *----------------------------------------------------------------------------*/ -CsrWifiEventCsrUint32* CsrWifiEventCsrUint32_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src, u32 value); - -typedef struct -{ - CsrWifiFsmEvent common; - u16 value16; - u8 value8; -} CsrWifiEventCsrUint16CsrUint8; - -/*----------------------------------------------------------------------------* - * CsrWifiEventCsrUint16CsrUint8_struct - * - * DESCRIPTION - * Generic message creator. - * Allocates and fills in a message with the signature CsrWifiEventCsrUint16CsrUint8 - * - *----------------------------------------------------------------------------*/ -CsrWifiEventCsrUint16CsrUint8* CsrWifiEventCsrUint16CsrUint8_struct(u16 primtype, u16 msgtype, CsrSchedQid dst, CsrSchedQid src, u16 value16, u8 value8); - -#endif /* CSR_WIFI_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_msgconv.h b/drivers/staging/csr/csr_wifi_msgconv.h deleted file mode 100644 index f8b402947a09..000000000000 --- a/drivers/staging/csr/csr_wifi_msgconv.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_MSGCONV_H__ -#define CSR_WIFI_MSGCONV_H__ - -#include "csr_prim_defs.h" -#include "csr_sched.h" - -void CsrUint16SerBigEndian(u8 *ptr, size_t *len, u16 v); -void CsrUint24SerBigEndian(u8 *ptr, size_t *len, u32 v); -void CsrUint32SerBigEndian(u8 *ptr, size_t *len, u32 v); - -void CsrUint16DesBigEndian(u16 *v, u8 *buffer, size_t *offset); -void CsrUint24DesBigEndian(u32 *v, u8 *buffer, size_t *offset); -void CsrUint32DesBigEndian(u32 *v, u8 *buffer, size_t *offset); - -void CsrUint24Ser(u8 *ptr, size_t *len, u32 v); -void CsrUint24Des(u32 *v, u8 *buffer, size_t *offset); - - -size_t CsrWifiEventSizeof(void *msg); -u8* CsrWifiEventSer(u8 *ptr, size_t *len, void *msg); -void* CsrWifiEventDes(u8 *buffer, size_t length); - -size_t CsrWifiEventCsrUint8Sizeof(void *msg); -u8* CsrWifiEventCsrUint8Ser(u8 *ptr, size_t *len, void *msg); -void* CsrWifiEventCsrUint8Des(u8 *buffer, size_t length); - -size_t CsrWifiEventCsrUint16Sizeof(void *msg); -u8* CsrWifiEventCsrUint16Ser(u8 *ptr, size_t *len, void *msg); -void* CsrWifiEventCsrUint16Des(u8 *buffer, size_t length); - -size_t CsrWifiEventCsrUint32Sizeof(void *msg); -u8* CsrWifiEventCsrUint32Ser(u8 *ptr, size_t *len, void *msg); -void* CsrWifiEventCsrUint32Des(u8 *buffer, size_t length); - -size_t CsrWifiEventCsrUint16CsrUint8Sizeof(void *msg); -u8* CsrWifiEventCsrUint16CsrUint8Ser(u8 *ptr, size_t *len, void *msg); -void* CsrWifiEventCsrUint16CsrUint8Des(u8 *buffer, size_t length); - -#endif /* CSR_WIFI_MSGCONV_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.c b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.c deleted file mode 100644 index 0689d6f1cab1..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.c +++ /dev/null @@ -1,90 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_msgconv.h" -#include "csr_macro.h" - -#ifdef CSR_WIFI_NME_ENABLE -#ifdef CSR_WIFI_AP_ENABLE - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" -#endif - -#ifndef EXCLUDE_CSR_WIFI_NME_AP_MODULE -#include "csr_wifi_nme_ap_serialize.h" -#include "csr_wifi_nme_ap_prim.h" - -static CsrMsgConvMsgEntry csrwifinmeap_conv_lut[] = { - { CSR_WIFI_NME_AP_CONFIG_SET_REQ, CsrWifiNmeApConfigSetReqSizeof, CsrWifiNmeApConfigSetReqSer, CsrWifiNmeApConfigSetReqDes, CsrWifiNmeApConfigSetReqSerFree }, - { CSR_WIFI_NME_AP_WPS_REGISTER_REQ, CsrWifiNmeApWpsRegisterReqSizeof, CsrWifiNmeApWpsRegisterReqSer, CsrWifiNmeApWpsRegisterReqDes, CsrWifiNmeApWpsRegisterReqSerFree }, - { CSR_WIFI_NME_AP_START_REQ, CsrWifiNmeApStartReqSizeof, CsrWifiNmeApStartReqSer, CsrWifiNmeApStartReqDes, CsrWifiNmeApStartReqSerFree }, - { CSR_WIFI_NME_AP_STOP_REQ, CsrWifiNmeApStopReqSizeof, CsrWifiNmeApStopReqSer, CsrWifiNmeApStopReqDes, CsrWifiNmeApStopReqSerFree }, - { CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_REQ, CsrWifiNmeApWmmParamUpdateReqSizeof, CsrWifiNmeApWmmParamUpdateReqSer, CsrWifiNmeApWmmParamUpdateReqDes, CsrWifiNmeApWmmParamUpdateReqSerFree }, - { CSR_WIFI_NME_AP_STA_REMOVE_REQ, CsrWifiNmeApStaRemoveReqSizeof, CsrWifiNmeApStaRemoveReqSer, CsrWifiNmeApStaRemoveReqDes, CsrWifiNmeApStaRemoveReqSerFree }, - { CSR_WIFI_NME_AP_CONFIG_SET_CFM, CsrWifiNmeApConfigSetCfmSizeof, CsrWifiNmeApConfigSetCfmSer, CsrWifiNmeApConfigSetCfmDes, CsrWifiNmeApConfigSetCfmSerFree }, - { CSR_WIFI_NME_AP_WPS_REGISTER_CFM, CsrWifiNmeApWpsRegisterCfmSizeof, CsrWifiNmeApWpsRegisterCfmSer, CsrWifiNmeApWpsRegisterCfmDes, CsrWifiNmeApWpsRegisterCfmSerFree }, - { CSR_WIFI_NME_AP_START_CFM, CsrWifiNmeApStartCfmSizeof, CsrWifiNmeApStartCfmSer, CsrWifiNmeApStartCfmDes, CsrWifiNmeApStartCfmSerFree }, - { CSR_WIFI_NME_AP_STOP_CFM, CsrWifiNmeApStopCfmSizeof, CsrWifiNmeApStopCfmSer, CsrWifiNmeApStopCfmDes, CsrWifiNmeApStopCfmSerFree }, - { CSR_WIFI_NME_AP_STOP_IND, CsrWifiNmeApStopIndSizeof, CsrWifiNmeApStopIndSer, CsrWifiNmeApStopIndDes, CsrWifiNmeApStopIndSerFree }, - { CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_CFM, CsrWifiNmeApWmmParamUpdateCfmSizeof, CsrWifiNmeApWmmParamUpdateCfmSer, CsrWifiNmeApWmmParamUpdateCfmDes, CsrWifiNmeApWmmParamUpdateCfmSerFree }, - { CSR_WIFI_NME_AP_STATION_IND, CsrWifiNmeApStationIndSizeof, CsrWifiNmeApStationIndSer, CsrWifiNmeApStationIndDes, CsrWifiNmeApStationIndSerFree }, - - { 0, NULL, NULL, NULL, NULL }, -}; - -CsrMsgConvMsgEntry* CsrWifiNmeApConverterLookup(CsrMsgConvMsgEntry *ce, u16 msgType) -{ - if (msgType & CSR_PRIM_UPSTREAM) - { - u16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT; - if (idx < (CSR_WIFI_NME_AP_PRIM_UPSTREAM_COUNT + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT) && - csrwifinmeap_conv_lut[idx].msgType == msgType) - { - return &csrwifinmeap_conv_lut[idx]; - } - } - else - { - if (msgType < CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT && - csrwifinmeap_conv_lut[msgType].msgType == msgType) - { - return &csrwifinmeap_conv_lut[msgType]; - } - } - return NULL; -} - - -void CsrWifiNmeApConverterInit(void) -{ - CsrMsgConvInsert(CSR_WIFI_NME_AP_PRIM, csrwifinmeap_conv_lut); - CsrMsgConvCustomLookupRegister(CSR_WIFI_NME_AP_PRIM, CsrWifiNmeApConverterLookup); -} - - -#ifdef CSR_LOG_ENABLE -static const CsrLogPrimitiveInformation csrwifinmeap_conv_info = { - CSR_WIFI_NME_AP_PRIM, - (char *)"CSR_WIFI_NME_AP_PRIM", - csrwifinmeap_conv_lut -}; -const CsrLogPrimitiveInformation* CsrWifiNmeApTechInfoGet(void) -{ - return &csrwifinmeap_conv_info; -} - - -#endif /* CSR_LOG_ENABLE */ -#endif /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */ -#endif /* CSR_WIFI_NME_ENABLE */ -#endif /* CSR_WIFI_AP_ENABLE */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h b/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h deleted file mode 100644 index b89d7c7f8e21..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_converter_init.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_AP_CONVERTER_INIT_H__ -#define CSR_WIFI_NME_AP_CONVERTER_INIT_H__ - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_converter_init.h -#endif -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_converter_init.h -#endif - -#ifndef EXCLUDE_CSR_WIFI_NME_AP_MODULE - -#include "csr_msgconv.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" - -extern const CsrLogPrimitiveInformation* CsrWifiNmeApTechInfoGet(void); -#endif /* CSR_LOG_ENABLE */ - -extern void CsrWifiNmeApConverterInit(void); - -#else /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */ - -#define CsrWifiNmeApConverterInit() - -#endif /* EXCLUDE_CSR_WIFI_NME_AP_MODULE */ - -#endif /* CSR_WIFI_NME_AP_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_nme_ap_free_downstream_contents.c deleted file mode 100644 index ab9358873ec3..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_free_downstream_contents.c +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_nme_ap_prim.h" -#include "csr_wifi_nme_ap_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiNmeApFreeDownstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_NME_AP_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiNmeApFreeDownstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_NME_AP_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiNmeApPrim *) message)) - { - case CSR_WIFI_NME_AP_CONFIG_SET_REQ: - { - CsrWifiNmeApConfigSetReq *p = (CsrWifiNmeApConfigSetReq *)message; - kfree(p->apMacConfig.macAddressList); - p->apMacConfig.macAddressList = NULL; - break; - } - case CSR_WIFI_NME_AP_START_REQ: - { - CsrWifiNmeApStartReq *p = (CsrWifiNmeApStartReq *)message; - switch (p->apCredentials.authType) - { - case CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL: - switch (p->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase) - { - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE: - kfree(p->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase); - p->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase = NULL; - break; - default: - break; - } - break; - default: - break; - } - { - u16 i3; - for (i3 = 0; i3 < p->p2pGoParam.operatingChanList.channelEntryListCount; i3++) - { - kfree(p->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel); - p->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel = NULL; - } - } - kfree(p->p2pGoParam.operatingChanList.channelEntryList); - p->p2pGoParam.operatingChanList.channelEntryList = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_nme_ap_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_nme_ap_free_upstream_contents.c deleted file mode 100644 index 2786a6bbff97..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_free_upstream_contents.c +++ /dev/null @@ -1,39 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_wifi_nme_ap_prim.h" -#include "csr_wifi_nme_ap_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiNmeApFreeUpstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_NME_AP_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiNmeApFreeUpstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_NME_AP_PRIM) - { - return; - } - if (NULL == message) - { - return; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_nme_ap_lib.h b/drivers/staging/csr/csr_wifi_nme_ap_lib.h deleted file mode 100644 index 6d8df8366817..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_lib.h +++ /dev/null @@ -1,495 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_AP_LIB_H__ -#define CSR_WIFI_NME_AP_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_nme_ap_prim.h" -#include "csr_wifi_nme_task.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_lib.h -#endif -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_lib.h -#endif - -/*----------------------------------------------------------------------------* - * CsrWifiNmeApFreeUpstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_NME_AP upstream message. Does not - * free the message itself, and can only be used for upstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_NME_AP upstream message - *----------------------------------------------------------------------------*/ -void CsrWifiNmeApFreeUpstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * CsrWifiNmeApFreeDownstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_NME_AP downstream message. Does not - * free the message itself, and can only be used for downstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_NME_AP downstream message - *----------------------------------------------------------------------------*/ -void CsrWifiNmeApFreeDownstreamMessageContents(u16 eventClass, void *message); - -/******************************************************************************* - - NAME - CsrWifiNmeApConfigSetReqSend - - DESCRIPTION - This primitive passes AP configuration info for NME. This can be sent at - any time but will be acted upon when the AP is started again. This - information is common to both P2P GO and AP - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - apConfig - AP configuration for the NME. - apMacConfig - MAC configuration to be acted on when - CSR_WIFI_NME_AP_START.request is sent. - -*******************************************************************************/ -#define CsrWifiNmeApConfigSetReqCreate(msg__, dst__, src__, apConfig__, apMacConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_CONFIG_SET_REQ, dst__, src__); \ - msg__->apConfig = (apConfig__); \ - msg__->apMacConfig = (apMacConfig__); - -#define CsrWifiNmeApConfigSetReqSendTo(dst__, src__, apConfig__, apMacConfig__) \ - { \ - CsrWifiNmeApConfigSetReq *msg__; \ - CsrWifiNmeApConfigSetReqCreate(msg__, dst__, src__, apConfig__, apMacConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApConfigSetReqSend(src__, apConfig__, apMacConfig__) \ - CsrWifiNmeApConfigSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, apConfig__, apMacConfig__) - -/******************************************************************************* - - NAME - CsrWifiNmeApConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiNmeApConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeApConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeApConfigSetCfm *msg__; \ - CsrWifiNmeApConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApConfigSetCfmSend(dst__, status__) \ - CsrWifiNmeApConfigSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStaRemoveReqSend - - DESCRIPTION - This primitive disconnects a connected station. If keepBlocking is set to - TRUE, the station with the specified MAC address is not allowed to - connect. If the requested station is not already connected,it may be - blocked based on keepBlocking parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - staMacAddress - Mac Address of the station to be disconnected or blocked - keepBlocking - If TRUE, the station is blocked. If FALSE and the station is - connected, disconnect the station. If FALSE and the station - is not connected, no action is taken. - -*******************************************************************************/ -#define CsrWifiNmeApStaRemoveReqCreate(msg__, dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStaRemoveReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STA_REMOVE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->staMacAddress = (staMacAddress__); \ - msg__->keepBlocking = (keepBlocking__); - -#define CsrWifiNmeApStaRemoveReqSendTo(dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__) \ - { \ - CsrWifiNmeApStaRemoveReq *msg__; \ - CsrWifiNmeApStaRemoveReqCreate(msg__, dst__, src__, interfaceTag__, staMacAddress__, keepBlocking__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStaRemoveReqSend(src__, interfaceTag__, staMacAddress__, keepBlocking__) \ - CsrWifiNmeApStaRemoveReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, staMacAddress__, keepBlocking__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStartReqSend - - DESCRIPTION - This primitive requests NME to started the AP operation. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface identifier; unique identifier of an interface - apType - AP Type specifies the Legacy AP or P2P GO operation - cloakSsid - Indicates whether the SSID should be cloaked (hidden and - not broadcast in beacon) or not - ssid - Service Set Identifier - ifIndex - Radio interface - channel - Channel number of the channel to use - apCredentials - Security credential configuration. - maxConnections - Maximum number of stations/P2P clients allowed - p2pGoParam - P2P specific GO parameters. - wpsEnabled - Indicates whether WPS should be enabled or not - -*******************************************************************************/ -#define CsrWifiNmeApStartReqCreate(msg__, dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStartReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_START_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->apType = (apType__); \ - msg__->cloakSsid = (cloakSsid__); \ - msg__->ssid = (ssid__); \ - msg__->ifIndex = (ifIndex__); \ - msg__->channel = (channel__); \ - msg__->apCredentials = (apCredentials__); \ - msg__->maxConnections = (maxConnections__); \ - msg__->p2pGoParam = (p2pGoParam__); \ - msg__->wpsEnabled = (wpsEnabled__); - -#define CsrWifiNmeApStartReqSendTo(dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ - { \ - CsrWifiNmeApStartReq *msg__; \ - CsrWifiNmeApStartReqCreate(msg__, dst__, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStartReqSend(src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) \ - CsrWifiNmeApStartReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, apCredentials__, maxConnections__, p2pGoParam__, wpsEnabled__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStartCfmSend - - DESCRIPTION - This primitive reports the result of CSR_WIFI_NME_AP_START.request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - ssid - Service Set Identifier - -*******************************************************************************/ -#define CsrWifiNmeApStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ssid__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStartCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_START_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->ssid = (ssid__); - -#define CsrWifiNmeApStartCfmSendTo(dst__, src__, interfaceTag__, status__, ssid__) \ - { \ - CsrWifiNmeApStartCfm *msg__; \ - CsrWifiNmeApStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ssid__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStartCfmSend(dst__, interfaceTag__, status__, ssid__) \ - CsrWifiNmeApStartCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, ssid__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStationIndSend - - DESCRIPTION - This primitive indicates that a station has joined or a previously joined - station has left the BSS/group - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - mediaStatus - Indicates whether the station is connected or - disconnected - peerMacAddress - MAC address of the station - peerDeviceAddress - P2P Device Address - -*******************************************************************************/ -#define CsrWifiNmeApStationIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStationInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STATION_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->mediaStatus = (mediaStatus__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->peerDeviceAddress = (peerDeviceAddress__); - -#define CsrWifiNmeApStationIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ - { \ - CsrWifiNmeApStationInd *msg__; \ - CsrWifiNmeApStationIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStationIndSend(dst__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) \ - CsrWifiNmeApStationIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStopReqSend - - DESCRIPTION - This primitive requests NME to stop the AP operation. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiNmeApStopReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStopReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiNmeApStopReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiNmeApStopReq *msg__; \ - CsrWifiNmeApStopReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStopReqSend(src__, interfaceTag__) \ - CsrWifiNmeApStopReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStopIndSend - - DESCRIPTION - Indicates that AP operation had stopped because of some unrecoverable - error after AP operation was started successfully. NME sends this signal - after failing to restart the AP operation internally following an error - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - apType - Reports AP Type (P2PGO or AP) - status - Error Status - -*******************************************************************************/ -#define CsrWifiNmeApStopIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStopInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->apType = (apType__); \ - msg__->status = (status__); - -#define CsrWifiNmeApStopIndSendTo(dst__, src__, interfaceTag__, apType__, status__) \ - { \ - CsrWifiNmeApStopInd *msg__; \ - CsrWifiNmeApStopIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStopIndSend(dst__, interfaceTag__, apType__, status__) \ - CsrWifiNmeApStopIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, apType__, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeApStopCfmSend - - DESCRIPTION - This primitive confirms that the AP operation is stopped. NME shall send - this primitive in response to the request even if AP operation has - already been stopped - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiNmeApStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApStopCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_STOP_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiNmeApStopCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiNmeApStopCfm *msg__; \ - CsrWifiNmeApStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApStopCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiNmeApStopCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeApWmmParamUpdateReqSend - - DESCRIPTION - Application uses this primitive to update the WMM parameters - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - wmmApParams - WMM Access point parameters per access category. The array - index corresponds to the ACI - wmmApBcParams - WMM station parameters per access category to be advertised - in the beacons and probe response The array index - corresponds to the ACI - -*******************************************************************************/ -#define CsrWifiNmeApWmmParamUpdateReqCreate(msg__, dst__, src__, wmmApParams__, wmmApBcParams__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApWmmParamUpdateReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_REQ, dst__, src__); \ - memcpy(msg__->wmmApParams, (wmmApParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); \ - memcpy(msg__->wmmApBcParams, (wmmApBcParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); - -#define CsrWifiNmeApWmmParamUpdateReqSendTo(dst__, src__, wmmApParams__, wmmApBcParams__) \ - { \ - CsrWifiNmeApWmmParamUpdateReq *msg__; \ - CsrWifiNmeApWmmParamUpdateReqCreate(msg__, dst__, src__, wmmApParams__, wmmApBcParams__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApWmmParamUpdateReqSend(src__, wmmApParams__, wmmApBcParams__) \ - CsrWifiNmeApWmmParamUpdateReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, wmmApParams__, wmmApBcParams__) - -/******************************************************************************* - - NAME - CsrWifiNmeApWmmParamUpdateCfmSend - - DESCRIPTION - A confirm for for the WMM parameters update - - PARAMETERS - queue - Destination Task Queue - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiNmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApWmmParamUpdateCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeApWmmParamUpdateCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeApWmmParamUpdateCfm *msg__; \ - CsrWifiNmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApWmmParamUpdateCfmSend(dst__, status__) \ - CsrWifiNmeApWmmParamUpdateCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeApWpsRegisterReqSend - - DESCRIPTION - This primitive allows the NME to accept the WPS registration from an - enrollee. Such registration procedure can be cancelled by sending - CSR_WIFI_NME_WPS_CANCEL.request. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an - interface - selectedDevicePasswordId - Selected password type - selectedConfigMethod - Selected WPS configuration method type - pin - PIN value. - Relevant if selected device password ID is PIN.4 - digit pin is passed by sending the pin digits in - pin[0]..pin[3] and rest of the contents filled - with '-'. - -*******************************************************************************/ -#define CsrWifiNmeApWpsRegisterReqCreate(msg__, dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApWpsRegisterReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WPS_REGISTER_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->selectedDevicePasswordId = (selectedDevicePasswordId__); \ - msg__->selectedConfigMethod = (selectedConfigMethod__); \ - memcpy(msg__->pin, (pin__), sizeof(u8) * 8); - -#define CsrWifiNmeApWpsRegisterReqSendTo(dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ - { \ - CsrWifiNmeApWpsRegisterReq *msg__; \ - CsrWifiNmeApWpsRegisterReqCreate(msg__, dst__, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApWpsRegisterReqSend(src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) \ - CsrWifiNmeApWpsRegisterReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, selectedDevicePasswordId__, selectedConfigMethod__, pin__) - -/******************************************************************************* - - NAME - CsrWifiNmeApWpsRegisterCfmSend - - DESCRIPTION - This primitive reports the result of WPS procedure. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiNmeApWpsRegisterCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeApWpsRegisterCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_AP_PRIM, CSR_WIFI_NME_AP_WPS_REGISTER_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiNmeApWpsRegisterCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiNmeApWpsRegisterCfm *msg__; \ - CsrWifiNmeApWpsRegisterCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_AP_PRIM, msg__); \ - } - -#define CsrWifiNmeApWpsRegisterCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiNmeApWpsRegisterCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) - -#endif /* CSR_WIFI_NME_AP_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_prim.h b/drivers/staging/csr/csr_wifi_nme_ap_prim.h deleted file mode 100644 index b32bdbc7e22f..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_prim.h +++ /dev/null @@ -1,494 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_AP_PRIM_H__ -#define CSR_WIFI_NME_AP_PRIM_H__ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" -#include "csr_wifi_sme_ap_prim.h" -#include "csr_wifi_nme_prim.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_prim.h -#endif -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_prim.h -#endif - -#define CSR_WIFI_NME_AP_PRIM (0x0426) - -typedef CsrPrim CsrWifiNmeApPrim; - - -/******************************************************************************* - - NAME - CsrWifiNmeApPersCredentialType - - DESCRIPTION - NME Credential Types - - VALUES - CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK - - Use PSK as credential. - CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE - - Use the specified passphrase as credential - -*******************************************************************************/ -typedef u8 CsrWifiNmeApPersCredentialType; -#define CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK ((CsrWifiNmeApPersCredentialType) 0x00) -#define CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE ((CsrWifiNmeApPersCredentialType) 0x01) - - -/******************************************************************************* - - NAME - CsrWifiNmeApConfig - - DESCRIPTION - Structure holding AP config data. - - MEMBERS - apGroupkeyTimeout - Access point group key timeout. - apStrictGtkRekey - Access point strict GTK rekey flag. If set TRUE, the AP - shall rekey GTK every time a connected STA leaves BSS. - apGmkTimeout - Access point GMK timeout - apResponseTimeout - Response timeout - apRetransLimit - Max allowed retransmissions - -*******************************************************************************/ -typedef struct -{ - u16 apGroupkeyTimeout; - u8 apStrictGtkRekey; - u16 apGmkTimeout; - u16 apResponseTimeout; - u8 apRetransLimit; -} CsrWifiNmeApConfig; - -/******************************************************************************* - - NAME - CsrWifiNmeApAuthPers - - DESCRIPTION - - MEMBERS - authSupport - Credential type value (as defined in the - enumeration type). - rsnCapabilities - RSN capabilities mask - wapiCapabilities - WAPI capabilities mask - pskOrPassphrase - Credential type value (as defined in the - enumeration type). - authPers_credentials - Union containing credentials which depends - on credentialType parameter. - authPers_credentialspsk - - authPers_credentialspassphrase - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApAuthSupportMask authSupport; - CsrWifiSmeApRsnCapabilitiesMask rsnCapabilities; - CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities; - CsrWifiNmeApPersCredentialType pskOrPassphrase; - union { - CsrWifiNmePsk psk; - CsrWifiNmePassphrase passphrase; - } authPers_credentials; -} CsrWifiNmeApAuthPers; - -/******************************************************************************* - - NAME - CsrWifiNmeApCredentials - - DESCRIPTION - Structure containing the Credentials data. - - MEMBERS - authType - Authentication type - nmeAuthType - Authentication parameters - nmeAuthTypeopenSystemEmpty - - nmeAuthTypeauthwep - - nmeAuthTypeauthTypePersonal - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApAuthType authType; - union { - CsrWifiSmeEmpty openSystemEmpty; - CsrWifiSmeWepAuth authwep; - CsrWifiNmeApAuthPers authTypePersonal; - } nmeAuthType; -} CsrWifiNmeApCredentials; - - -/* Downstream */ -#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_NME_AP_CONFIG_SET_REQ ((CsrWifiNmeApPrim) (0x0000 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_WPS_REGISTER_REQ ((CsrWifiNmeApPrim) (0x0001 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_START_REQ ((CsrWifiNmeApPrim) (0x0002 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_STOP_REQ ((CsrWifiNmeApPrim) (0x0003 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_REQ ((CsrWifiNmeApPrim) (0x0004 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_STA_REMOVE_REQ ((CsrWifiNmeApPrim) (0x0005 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0005 + CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_NME_AP_CONFIG_SET_CFM ((CsrWifiNmeApPrim)(0x0000 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_WPS_REGISTER_CFM ((CsrWifiNmeApPrim)(0x0001 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_START_CFM ((CsrWifiNmeApPrim)(0x0002 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_STOP_CFM ((CsrWifiNmeApPrim)(0x0003 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_STOP_IND ((CsrWifiNmeApPrim)(0x0004 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_WMM_PARAM_UPDATE_CFM ((CsrWifiNmeApPrim)(0x0005 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_AP_STATION_IND ((CsrWifiNmeApPrim)(0x0006 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_HIGHEST (0x0006 + CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_NME_AP_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_NME_AP_PRIM_UPSTREAM_COUNT (CSR_WIFI_NME_AP_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_NME_AP_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiNmeApConfigSetReq - - DESCRIPTION - This primitive passes AP configuration info for NME. This can be sent at - any time but will be acted upon when the AP is started again. This - information is common to both P2P GO and AP - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - apConfig - AP configuration for the NME. - apMacConfig - MAC configuration to be acted on when - CSR_WIFI_NME_AP_START.request is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiNmeApConfig apConfig; - CsrWifiSmeApMacConfig apMacConfig; -} CsrWifiNmeApConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApWpsRegisterReq - - DESCRIPTION - This primitive allows the NME to accept the WPS registration from an - enrollee. Such registration procedure can be cancelled by sending - CSR_WIFI_NME_WPS_CANCEL.request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an - interface - selectedDevicePasswordId - Selected password type - selectedConfigMethod - Selected WPS configuration method type - pin - PIN value. - Relevant if selected device password ID is PIN.4 - digit pin is passed by sending the pin digits in - pin[0]..pin[3] and rest of the contents filled - with '-'. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeWpsDpid selectedDevicePasswordId; - CsrWifiSmeWpsConfigType selectedConfigMethod; - u8 pin[8]; -} CsrWifiNmeApWpsRegisterReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApStartReq - - DESCRIPTION - This primitive requests NME to started the AP operation. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface identifier; unique identifier of an interface - apType - AP Type specifies the Legacy AP or P2P GO operation - cloakSsid - Indicates whether the SSID should be cloaked (hidden and - not broadcast in beacon) or not - ssid - Service Set Identifier - ifIndex - Radio interface - channel - Channel number of the channel to use - apCredentials - Security credential configuration. - maxConnections - Maximum number of stations/P2P clients allowed - p2pGoParam - P2P specific GO parameters. - wpsEnabled - Indicates whether WPS should be enabled or not - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeApType apType; - u8 cloakSsid; - CsrWifiSsid ssid; - CsrWifiSmeRadioIF ifIndex; - u8 channel; - CsrWifiNmeApCredentials apCredentials; - u8 maxConnections; - CsrWifiSmeApP2pGoConfig p2pGoParam; - u8 wpsEnabled; -} CsrWifiNmeApStartReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApStopReq - - DESCRIPTION - This primitive requests NME to stop the AP operation. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiNmeApStopReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApWmmParamUpdateReq - - DESCRIPTION - Application uses this primitive to update the WMM parameters - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - wmmApParams - WMM Access point parameters per access category. The array - index corresponds to the ACI - wmmApBcParams - WMM station parameters per access category to be advertised - in the beacons and probe response The array index - corresponds to the ACI - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeWmmAcParams wmmApParams[4]; - CsrWifiSmeWmmAcParams wmmApBcParams[4]; -} CsrWifiNmeApWmmParamUpdateReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApStaRemoveReq - - DESCRIPTION - This primitive disconnects a connected station. If keepBlocking is set to - TRUE, the station with the specified MAC address is not allowed to - connect. If the requested station is not already connected,it may be - blocked based on keepBlocking parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - staMacAddress - Mac Address of the station to be disconnected or blocked - keepBlocking - If TRUE, the station is blocked. If FALSE and the station is - connected, disconnect the station. If FALSE and the station - is not connected, no action is taken. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiMacAddress staMacAddress; - u8 keepBlocking; -} CsrWifiNmeApStaRemoveReq; - -/******************************************************************************* - - NAME - CsrWifiNmeApConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeApConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeApWpsRegisterCfm - - DESCRIPTION - This primitive reports the result of WPS procedure. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiNmeApWpsRegisterCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeApStartCfm - - DESCRIPTION - This primitive reports the result of CSR_WIFI_NME_AP_START.request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - ssid - Service Set Identifier - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSsid ssid; -} CsrWifiNmeApStartCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeApStopCfm - - DESCRIPTION - This primitive confirms that the AP operation is stopped. NME shall send - this primitive in response to the request even if AP operation has - already been stopped - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface identifier; unique identifier of an interface - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiNmeApStopCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeApStopInd - - DESCRIPTION - Indicates that AP operation had stopped because of some unrecoverable - error after AP operation was started successfully. NME sends this signal - after failing to restart the AP operation internally following an error - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - apType - Reports AP Type (P2PGO or AP) - status - Error Status - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeApType apType; - CsrResult status; -} CsrWifiNmeApStopInd; - -/******************************************************************************* - - NAME - CsrWifiNmeApWmmParamUpdateCfm - - DESCRIPTION - A confirm for for the WMM parameters update - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeApWmmParamUpdateCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeApStationInd - - DESCRIPTION - This primitive indicates that a station has joined or a previously joined - station has left the BSS/group - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - mediaStatus - Indicates whether the station is connected or - disconnected - peerMacAddress - MAC address of the station - peerDeviceAddress - P2P Device Address - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeMediaStatus mediaStatus; - CsrWifiMacAddress peerMacAddress; - CsrWifiMacAddress peerDeviceAddress; -} CsrWifiNmeApStationInd; - -#endif /* CSR_WIFI_NME_AP_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_nme_ap_sef.c b/drivers/staging/csr/csr_wifi_nme_ap_sef.c deleted file mode 100644 index bfebb1529779..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_sef.c +++ /dev/null @@ -1,30 +0,0 @@ -/***************************************************************************** - - FILE: csr_wifi_nme_sef.c - - (c) Cambridge Silicon Radio Limited 2010 - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#include "csr_wifi_nme_ap_sef.h" -#include "unifi_priv.h" - -void CsrWifiNmeApUpstreamStateHandlers(void* drvpriv, CsrWifiFsmEvent* msg) -{ - switch(msg->type) { - case CSR_WIFI_NME_AP_START_CFM: - CsrWifiNmeApStartCfmHandler(drvpriv, msg); - break; - case CSR_WIFI_NME_AP_STOP_CFM: - CsrWifiNmeApStopCfmHandler(drvpriv, msg); - break; - case CSR_WIFI_NME_AP_CONFIG_SET_CFM: - CsrWifiNmeApConfigSetCfmHandler(drvpriv, msg); - break; - default: - unifi_error(drvpriv, "CsrWifiNmeApUpstreamStateHandlers: unhandled NME_AP message type 0x%.4X\n", msg->type); - break; - } -} diff --git a/drivers/staging/csr/csr_wifi_nme_ap_sef.h b/drivers/staging/csr/csr_wifi_nme_ap_sef.h deleted file mode 100644 index 3daaa0944dba..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_sef.h +++ /dev/null @@ -1,21 +0,0 @@ -/***************************************************************************** - FILE: csr_wifi_nme_sef.h - (c) Cambridge Silicon Radio Limited 2010 - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ -#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ -#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ - -#include "csr_wifi_nme_prim.h" - -void CsrWifiNmeApUpstreamStateHandlers(void* drvpriv, CsrWifiFsmEvent* msg); - - -extern void CsrWifiNmeApConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); -extern void CsrWifiNmeApStartCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); -extern void CsrWifiNmeApStopCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg); - -#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_NME_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_serialize.c b/drivers/staging/csr/csr_wifi_nme_ap_serialize.c deleted file mode 100644 index 1a901a70d195..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_serialize.c +++ /dev/null @@ -1,909 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include -#include "csr_msgconv.h" - -#ifdef CSR_WIFI_NME_ENABLE -#ifdef CSR_WIFI_AP_ENABLE - -#include "csr_wifi_nme_ap_prim.h" -#include "csr_wifi_nme_ap_serialize.h" - -void CsrWifiNmeApPfree(void *ptr) -{ - kfree(ptr); -} - - -size_t CsrWifiNmeApConfigSetReqSizeof(void *msg) -{ - CsrWifiNmeApConfigSetReq *primitive = (CsrWifiNmeApConfigSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 104) */ - bufferSize += 2; /* u16 primitive->apConfig.apGroupkeyTimeout */ - bufferSize += 1; /* u8 primitive->apConfig.apStrictGtkRekey */ - bufferSize += 2; /* u16 primitive->apConfig.apGmkTimeout */ - bufferSize += 2; /* u16 primitive->apConfig.apResponseTimeout */ - bufferSize += 1; /* u8 primitive->apConfig.apRetransLimit */ - bufferSize += 1; /* CsrWifiSmeApPhySupportMask primitive->apMacConfig.phySupportedBitmap */ - bufferSize += 2; /* u16 primitive->apMacConfig.beaconInterval */ - bufferSize += 1; /* u8 primitive->apMacConfig.dtimPeriod */ - bufferSize += 2; /* u16 primitive->apMacConfig.maxListenInterval */ - bufferSize += 1; /* u8 primitive->apMacConfig.supportedRatesCount */ - bufferSize += 20; /* u8 primitive->apMacConfig.supportedRates[20] */ - bufferSize += 1; /* CsrWifiSmePreambleType primitive->apMacConfig.preamble */ - bufferSize += 1; /* u8 primitive->apMacConfig.shortSlotTimeEnabled */ - bufferSize += 1; /* CsrWifiSmeCtsProtectionType primitive->apMacConfig.ctsProtectionType */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmEnabled */ - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApParams[i2].cwMin */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApParams[i2].cwMax */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApParams[i2].aifs */ - bufferSize += 2; /* u16 primitive->apMacConfig.wmmApParams[i2].txopLimit */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApParams[i2].admissionControlMandatory */ - } - } - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApBcParams[i2].cwMin */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApBcParams[i2].cwMax */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApBcParams[i2].aifs */ - bufferSize += 2; /* u16 primitive->apMacConfig.wmmApBcParams[i2].txopLimit */ - bufferSize += 1; /* u8 primitive->apMacConfig.wmmApBcParams[i2].admissionControlMandatory */ - } - } - bufferSize += 1; /* CsrWifiSmeApAccessType primitive->apMacConfig.accessType */ - bufferSize += 1; /* u8 primitive->apMacConfig.macAddressListCount */ - { - u16 i2; - for (i2 = 0; i2 < primitive->apMacConfig.macAddressListCount; i2++) - { - bufferSize += 6; /* u8 primitive->apMacConfig.macAddressList[i2].a[6] */ - } - } - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.greenfieldSupported */ - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.shortGi20MHz */ - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.rxStbc */ - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.rifsModeAllowed */ - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.htProtection */ - bufferSize += 1; /* u8 primitive->apMacConfig.apHtParams.dualCtsProtection */ - return bufferSize; -} - - -u8* CsrWifiNmeApConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApConfigSetReq *primitive = (CsrWifiNmeApConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->apConfig.apGroupkeyTimeout); - CsrUint8Ser(ptr, len, (u8) primitive->apConfig.apStrictGtkRekey); - CsrUint16Ser(ptr, len, (u16) primitive->apConfig.apGmkTimeout); - CsrUint16Ser(ptr, len, (u16) primitive->apConfig.apResponseTimeout); - CsrUint8Ser(ptr, len, (u8) primitive->apConfig.apRetransLimit); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.phySupportedBitmap); - CsrUint16Ser(ptr, len, (u16) primitive->apMacConfig.beaconInterval); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.dtimPeriod); - CsrUint16Ser(ptr, len, (u16) primitive->apMacConfig.maxListenInterval); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.supportedRatesCount); - CsrMemCpySer(ptr, len, (const void *) primitive->apMacConfig.supportedRates, ((u16) (20))); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.preamble); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.shortSlotTimeEnabled); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.ctsProtectionType); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmEnabled); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApParams[i2].cwMin); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApParams[i2].cwMax); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApParams[i2].aifs); - CsrUint16Ser(ptr, len, (u16) primitive->apMacConfig.wmmApParams[i2].txopLimit); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApParams[i2].admissionControlMandatory); - } - } - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApBcParams[i2].cwMin); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApBcParams[i2].cwMax); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApBcParams[i2].aifs); - CsrUint16Ser(ptr, len, (u16) primitive->apMacConfig.wmmApBcParams[i2].txopLimit); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.wmmApBcParams[i2].admissionControlMandatory); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.accessType); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.macAddressListCount); - { - u16 i2; - for (i2 = 0; i2 < primitive->apMacConfig.macAddressListCount; i2++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->apMacConfig.macAddressList[i2].a, ((u16) (6))); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.greenfieldSupported); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.shortGi20MHz); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.rxStbc); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.rifsModeAllowed); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.htProtection); - CsrUint8Ser(ptr, len, (u8) primitive->apMacConfig.apHtParams.dualCtsProtection); - return(ptr); -} - - -void* CsrWifiNmeApConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApConfigSetReq *primitive = kmalloc(sizeof(CsrWifiNmeApConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apConfig.apGroupkeyTimeout, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apConfig.apStrictGtkRekey, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apConfig.apGmkTimeout, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apConfig.apResponseTimeout, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apConfig.apRetransLimit, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.phySupportedBitmap, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apMacConfig.beaconInterval, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.dtimPeriod, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apMacConfig.maxListenInterval, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.supportedRatesCount, buffer, &offset); - CsrMemCpyDes(primitive->apMacConfig.supportedRates, buffer, &offset, ((u16) (20))); - CsrUint8Des((u8 *) &primitive->apMacConfig.preamble, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.shortSlotTimeEnabled, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.ctsProtectionType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmEnabled, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApParams[i2].cwMin, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApParams[i2].cwMax, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApParams[i2].aifs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apMacConfig.wmmApParams[i2].txopLimit, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApParams[i2].admissionControlMandatory, buffer, &offset); - } - } - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApBcParams[i2].cwMin, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApBcParams[i2].cwMax, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApBcParams[i2].aifs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apMacConfig.wmmApBcParams[i2].txopLimit, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.wmmApBcParams[i2].admissionControlMandatory, buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->apMacConfig.accessType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.macAddressListCount, buffer, &offset); - primitive->apMacConfig.macAddressList = NULL; - if (primitive->apMacConfig.macAddressListCount) - { - primitive->apMacConfig.macAddressList = kmalloc(sizeof(CsrWifiMacAddress) * primitive->apMacConfig.macAddressListCount, GFP_KERNEL); - } - { - u16 i2; - for (i2 = 0; i2 < primitive->apMacConfig.macAddressListCount; i2++) - { - CsrMemCpyDes(primitive->apMacConfig.macAddressList[i2].a, buffer, &offset, ((u16) (6))); - } - } - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.greenfieldSupported, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.shortGi20MHz, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.rxStbc, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.rifsModeAllowed, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.htProtection, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apMacConfig.apHtParams.dualCtsProtection, buffer, &offset); - - return primitive; -} - - -void CsrWifiNmeApConfigSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiNmeApConfigSetReq *primitive = (CsrWifiNmeApConfigSetReq *) voidPrimitivePointer; - kfree(primitive->apMacConfig.macAddressList); - kfree(primitive); -} - - -size_t CsrWifiNmeApWpsRegisterReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiSmeWpsDpid primitive->selectedDevicePasswordId */ - bufferSize += 2; /* CsrWifiSmeWpsConfigType primitive->selectedConfigMethod */ - bufferSize += 8; /* u8 primitive->pin[8] */ - return bufferSize; -} - - -u8* CsrWifiNmeApWpsRegisterReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApWpsRegisterReq *primitive = (CsrWifiNmeApWpsRegisterReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->selectedDevicePasswordId); - CsrUint16Ser(ptr, len, (u16) primitive->selectedConfigMethod); - CsrMemCpySer(ptr, len, (const void *) primitive->pin, ((u16) (8))); - return(ptr); -} - - -void* CsrWifiNmeApWpsRegisterReqDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApWpsRegisterReq *primitive = kmalloc(sizeof(CsrWifiNmeApWpsRegisterReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->selectedDevicePasswordId, buffer, &offset); - CsrUint16Des((u16 *) &primitive->selectedConfigMethod, buffer, &offset); - CsrMemCpyDes(primitive->pin, buffer, &offset, ((u16) (8))); - - return primitive; -} - - -size_t CsrWifiNmeApStartReqSizeof(void *msg) -{ - CsrWifiNmeApStartReq *primitive = (CsrWifiNmeApStartReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 112) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeApType primitive->apType */ - bufferSize += 1; /* u8 primitive->cloakSsid */ - bufferSize += 32; /* u8 primitive->ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->ssid.length */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->ifIndex */ - bufferSize += 1; /* u8 primitive->channel */ - bufferSize += 1; /* CsrWifiSmeApAuthType primitive->apCredentials.authType */ - switch (primitive->apCredentials.authType) - { - case CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM: - bufferSize += 1; /* u8 primitive->apCredentials.nmeAuthType.openSystemEmpty.empty */ - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_WEP: - bufferSize += 1; /* CsrWifiSmeWepCredentialType primitive->apCredentials.nmeAuthType.authwep.wepKeyType */ - switch (primitive->apCredentials.nmeAuthType.authwep.wepKeyType) - { - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128: - bufferSize += 1; /* CsrWifiSmeWepAuthMode primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.wepAuthType */ - bufferSize += 1; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.selectedWepKey */ - bufferSize += 13; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key1[13] */ - bufferSize += 13; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key2[13] */ - bufferSize += 13; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key3[13] */ - bufferSize += 13; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key4[13] */ - break; - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64: - bufferSize += 1; /* CsrWifiSmeWepAuthMode primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.wepAuthType */ - bufferSize += 1; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.selectedWepKey */ - bufferSize += 5; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key1[5] */ - bufferSize += 5; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key2[5] */ - bufferSize += 5; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key3[5] */ - bufferSize += 5; /* u8 primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key4[5] */ - break; - default: - break; - } - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL: - bufferSize += 1; /* CsrWifiSmeApAuthSupportMask primitive->apCredentials.nmeAuthType.authTypePersonal.authSupport */ - bufferSize += 2; /* CsrWifiSmeApRsnCapabilitiesMask primitive->apCredentials.nmeAuthType.authTypePersonal.rsnCapabilities */ - bufferSize += 2; /* CsrWifiSmeApWapiCapabilitiesMask primitive->apCredentials.nmeAuthType.authTypePersonal.wapiCapabilities */ - bufferSize += 1; /* CsrWifiNmeApPersCredentialType primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase */ - switch (primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase) - { - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK: - bufferSize += 2; /* u16 primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.encryptionMode */ - bufferSize += 32; /* u8 primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.psk[32] */ - break; - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE: - bufferSize += 2; /* u16 primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.encryptionMode */ - bufferSize += (primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase ? strlen(primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase) : 0) + 1; /* char* primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase (0 byte len + 1 for NULL Term) */ - break; - default: - break; - } - break; - default: - break; - } - bufferSize += 1; /* u8 primitive->maxConnections */ - bufferSize += 1; /* CsrWifiSmeP2pGroupCapabilityMask primitive->p2pGoParam.groupCapability */ - bufferSize += 3; /* u8 primitive->p2pGoParam.operatingChanList.country[3] */ - bufferSize += 1; /* u8 primitive->p2pGoParam.operatingChanList.channelEntryListCount */ - { - u16 i3; - for (i3 = 0; i3 < primitive->p2pGoParam.operatingChanList.channelEntryListCount; i3++) - { - bufferSize += 1; /* u8 primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingClass */ - bufferSize += 1; /* u8 primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount */ - bufferSize += primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount; /* u8 primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel */ - } - } - bufferSize += 1; /* u8 primitive->p2pGoParam.opPsEnabled */ - bufferSize += 1; /* u8 primitive->p2pGoParam.ctWindow */ - bufferSize += 1; /* CsrWifiSmeP2pNoaConfigMethod primitive->p2pGoParam.noaConfigMethod */ - bufferSize += 1; /* u8 primitive->p2pGoParam.allowNoaWithNonP2pDevices */ - bufferSize += 1; /* u8 primitive->wpsEnabled */ - return bufferSize; -} - - -u8* CsrWifiNmeApStartReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStartReq *primitive = (CsrWifiNmeApStartReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->apType); - CsrUint8Ser(ptr, len, (u8) primitive->cloakSsid); - CsrMemCpySer(ptr, len, (const void *) primitive->ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->ssid.length); - CsrUint8Ser(ptr, len, (u8) primitive->ifIndex); - CsrUint8Ser(ptr, len, (u8) primitive->channel); - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.authType); - switch (primitive->apCredentials.authType) - { - case CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM: - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.openSystemEmpty.empty); - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_WEP: - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authwep.wepKeyType); - switch (primitive->apCredentials.nmeAuthType.authwep.wepKeyType) - { - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128: - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.wepAuthType); - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.selectedWepKey); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key1, ((u16) (13))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key2, ((u16) (13))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key3, ((u16) (13))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key4, ((u16) (13))); - break; - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64: - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.wepAuthType); - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.selectedWepKey); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key1, ((u16) (5))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key2, ((u16) (5))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key3, ((u16) (5))); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key4, ((u16) (5))); - break; - default: - break; - } - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL: - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authTypePersonal.authSupport); - CsrUint16Ser(ptr, len, (u16) primitive->apCredentials.nmeAuthType.authTypePersonal.rsnCapabilities); - CsrUint16Ser(ptr, len, (u16) primitive->apCredentials.nmeAuthType.authTypePersonal.wapiCapabilities); - CsrUint8Ser(ptr, len, (u8) primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase); - switch (primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase) - { - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK: - CsrUint16Ser(ptr, len, (u16) primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.encryptionMode); - CsrMemCpySer(ptr, len, (const void *) primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.psk, ((u16) (32))); - break; - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE: - CsrUint16Ser(ptr, len, (u16) primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.encryptionMode); - CsrCharStringSer(ptr, len, primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase); - break; - default: - break; - } - break; - default: - break; - } - CsrUint8Ser(ptr, len, (u8) primitive->maxConnections); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.groupCapability); - CsrMemCpySer(ptr, len, (const void *) primitive->p2pGoParam.operatingChanList.country, ((u16) (3))); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.operatingChanList.channelEntryListCount); - { - u16 i3; - for (i3 = 0; i3 < primitive->p2pGoParam.operatingChanList.channelEntryListCount; i3++) - { - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingClass); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount); - if (primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount) - { - CsrMemCpySer(ptr, len, (const void *) primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel, ((u16) (primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount))); - } - } - } - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.opPsEnabled); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.ctWindow); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.noaConfigMethod); - CsrUint8Ser(ptr, len, (u8) primitive->p2pGoParam.allowNoaWithNonP2pDevices); - CsrUint8Ser(ptr, len, (u8) primitive->wpsEnabled); - return(ptr); -} - - -void* CsrWifiNmeApStartReqDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStartReq *primitive = kmalloc(sizeof(CsrWifiNmeApStartReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->cloakSsid, buffer, &offset); - CsrMemCpyDes(primitive->ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->ssid.length, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ifIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->channel, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apCredentials.authType, buffer, &offset); - switch (primitive->apCredentials.authType) - { - case CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM: - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.openSystemEmpty.empty, buffer, &offset); - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_WEP: - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authwep.wepKeyType, buffer, &offset); - switch (primitive->apCredentials.nmeAuthType.authwep.wepKeyType) - { - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128: - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.wepAuthType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.selectedWepKey, buffer, &offset); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key1, buffer, &offset, ((u16) (13))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key2, buffer, &offset, ((u16) (13))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key3, buffer, &offset, ((u16) (13))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep128Key.key4, buffer, &offset, ((u16) (13))); - break; - case CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64: - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.wepAuthType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.selectedWepKey, buffer, &offset); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key1, buffer, &offset, ((u16) (5))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key2, buffer, &offset, ((u16) (5))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key3, buffer, &offset, ((u16) (5))); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authwep.wepCredentials.wep64Key.key4, buffer, &offset, ((u16) (5))); - break; - default: - break; - } - break; - case CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL: - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.authSupport, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.rsnCapabilities, buffer, &offset); - CsrUint16Des((u16 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.wapiCapabilities, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase, buffer, &offset); - switch (primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase) - { - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK: - CsrUint16Des((u16 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.encryptionMode, buffer, &offset); - CsrMemCpyDes(primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.psk.psk, buffer, &offset, ((u16) (32))); - break; - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE: - CsrUint16Des((u16 *) &primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.encryptionMode, buffer, &offset); - CsrCharStringDes(&primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase, buffer, &offset); - break; - default: - break; - } - break; - default: - break; - } - CsrUint8Des((u8 *) &primitive->maxConnections, buffer, &offset); - CsrUint8Des((u8 *) &primitive->p2pGoParam.groupCapability, buffer, &offset); - CsrMemCpyDes(primitive->p2pGoParam.operatingChanList.country, buffer, &offset, ((u16) (3))); - CsrUint8Des((u8 *) &primitive->p2pGoParam.operatingChanList.channelEntryListCount, buffer, &offset); - primitive->p2pGoParam.operatingChanList.channelEntryList = NULL; - if (primitive->p2pGoParam.operatingChanList.channelEntryListCount) - { - primitive->p2pGoParam.operatingChanList.channelEntryList = kmalloc(sizeof(CsrWifiSmeApP2pOperatingChanEntry) * primitive->p2pGoParam.operatingChanList.channelEntryListCount, GFP_KERNEL); - } - { - u16 i3; - for (i3 = 0; i3 < primitive->p2pGoParam.operatingChanList.channelEntryListCount; i3++) - { - CsrUint8Des((u8 *) &primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingClass, buffer, &offset); - CsrUint8Des((u8 *) &primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount, buffer, &offset); - if (primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount) - { - primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel = kmalloc(primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount, GFP_KERNEL); - CsrMemCpyDes(primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel, buffer, &offset, ((u16) (primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannelCount))); - } - else - { - primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel = NULL; - } - } - } - CsrUint8Des((u8 *) &primitive->p2pGoParam.opPsEnabled, buffer, &offset); - CsrUint8Des((u8 *) &primitive->p2pGoParam.ctWindow, buffer, &offset); - CsrUint8Des((u8 *) &primitive->p2pGoParam.noaConfigMethod, buffer, &offset); - CsrUint8Des((u8 *) &primitive->p2pGoParam.allowNoaWithNonP2pDevices, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wpsEnabled, buffer, &offset); - - return primitive; -} - - -void CsrWifiNmeApStartReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiNmeApStartReq *primitive = (CsrWifiNmeApStartReq *) voidPrimitivePointer; - switch (primitive->apCredentials.authType) - { - case CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL: - switch (primitive->apCredentials.nmeAuthType.authTypePersonal.pskOrPassphrase) - { - case CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PASSPHRASE: - kfree(primitive->apCredentials.nmeAuthType.authTypePersonal.authPers_credentials.passphrase.passphrase); - break; - default: - break; - } - break; - default: - break; - } - { - u16 i3; - for (i3 = 0; i3 < primitive->p2pGoParam.operatingChanList.channelEntryListCount; i3++) - { - kfree(primitive->p2pGoParam.operatingChanList.channelEntryList[i3].operatingChannel); - } - } - kfree(primitive->p2pGoParam.operatingChanList.channelEntryList); - kfree(primitive); -} - - -size_t CsrWifiNmeApWmmParamUpdateReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 51) */ - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - bufferSize += 1; /* u8 primitive->wmmApParams[i1].cwMin */ - bufferSize += 1; /* u8 primitive->wmmApParams[i1].cwMax */ - bufferSize += 1; /* u8 primitive->wmmApParams[i1].aifs */ - bufferSize += 2; /* u16 primitive->wmmApParams[i1].txopLimit */ - bufferSize += 1; /* u8 primitive->wmmApParams[i1].admissionControlMandatory */ - } - } - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - bufferSize += 1; /* u8 primitive->wmmApBcParams[i1].cwMin */ - bufferSize += 1; /* u8 primitive->wmmApBcParams[i1].cwMax */ - bufferSize += 1; /* u8 primitive->wmmApBcParams[i1].aifs */ - bufferSize += 2; /* u16 primitive->wmmApBcParams[i1].txopLimit */ - bufferSize += 1; /* u8 primitive->wmmApBcParams[i1].admissionControlMandatory */ - } - } - return bufferSize; -} - - -u8* CsrWifiNmeApWmmParamUpdateReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApWmmParamUpdateReq *primitive = (CsrWifiNmeApWmmParamUpdateReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - CsrUint8Ser(ptr, len, (u8) primitive->wmmApParams[i1].cwMin); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApParams[i1].cwMax); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApParams[i1].aifs); - CsrUint16Ser(ptr, len, (u16) primitive->wmmApParams[i1].txopLimit); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApParams[i1].admissionControlMandatory); - } - } - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - CsrUint8Ser(ptr, len, (u8) primitive->wmmApBcParams[i1].cwMin); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApBcParams[i1].cwMax); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApBcParams[i1].aifs); - CsrUint16Ser(ptr, len, (u16) primitive->wmmApBcParams[i1].txopLimit); - CsrUint8Ser(ptr, len, (u8) primitive->wmmApBcParams[i1].admissionControlMandatory); - } - } - return(ptr); -} - - -void* CsrWifiNmeApWmmParamUpdateReqDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApWmmParamUpdateReq *primitive = kmalloc(sizeof(CsrWifiNmeApWmmParamUpdateReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - CsrUint8Des((u8 *) &primitive->wmmApParams[i1].cwMin, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApParams[i1].cwMax, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApParams[i1].aifs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->wmmApParams[i1].txopLimit, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApParams[i1].admissionControlMandatory, buffer, &offset); - } - } - { - u16 i1; - for (i1 = 0; i1 < 4; i1++) - { - CsrUint8Des((u8 *) &primitive->wmmApBcParams[i1].cwMin, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApBcParams[i1].cwMax, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApBcParams[i1].aifs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->wmmApBcParams[i1].txopLimit, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wmmApBcParams[i1].admissionControlMandatory, buffer, &offset); - } - } - - return primitive; -} - - -size_t CsrWifiNmeApStaRemoveReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->staMacAddress.a[6] */ - bufferSize += 1; /* u8 primitive->keepBlocking */ - return bufferSize; -} - - -u8* CsrWifiNmeApStaRemoveReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStaRemoveReq *primitive = (CsrWifiNmeApStaRemoveReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->staMacAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->keepBlocking); - return(ptr); -} - - -void* CsrWifiNmeApStaRemoveReqDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStaRemoveReq *primitive = kmalloc(sizeof(CsrWifiNmeApStaRemoveReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->staMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->keepBlocking, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiNmeApWpsRegisterCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiNmeApWpsRegisterCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApWpsRegisterCfm *primitive = (CsrWifiNmeApWpsRegisterCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiNmeApWpsRegisterCfmDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApWpsRegisterCfm *primitive = kmalloc(sizeof(CsrWifiNmeApWpsRegisterCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiNmeApStartCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 40) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 32; /* u8 primitive->ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->ssid.length */ - return bufferSize; -} - - -u8* CsrWifiNmeApStartCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStartCfm *primitive = (CsrWifiNmeApStartCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->ssid.length); - return(ptr); -} - - -void* CsrWifiNmeApStartCfmDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStartCfm *primitive = kmalloc(sizeof(CsrWifiNmeApStartCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->ssid.length, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiNmeApStopCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiNmeApStopCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStopCfm *primitive = (CsrWifiNmeApStopCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiNmeApStopCfmDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStopCfm *primitive = kmalloc(sizeof(CsrWifiNmeApStopCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiNmeApStopIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeApType primitive->apType */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiNmeApStopIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStopInd *primitive = (CsrWifiNmeApStopInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->apType); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiNmeApStopIndDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStopInd *primitive = kmalloc(sizeof(CsrWifiNmeApStopInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->apType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiNmeApStationIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 18) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeMediaStatus primitive->mediaStatus */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 6; /* u8 primitive->peerDeviceAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiNmeApStationIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiNmeApStationInd *primitive = (CsrWifiNmeApStationInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->mediaStatus); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->peerDeviceAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiNmeApStationIndDes(u8 *buffer, size_t length) -{ - CsrWifiNmeApStationInd *primitive = kmalloc(sizeof(CsrWifiNmeApStationInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mediaStatus, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->peerDeviceAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -#endif /* CSR_WIFI_NME_ENABLE */ -#endif /* CSR_WIFI_AP_ENABLE */ diff --git a/drivers/staging/csr/csr_wifi_nme_ap_serialize.h b/drivers/staging/csr/csr_wifi_nme_ap_serialize.h deleted file mode 100644 index c04585e72460..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_ap_serialize.h +++ /dev/null @@ -1,94 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_AP_SERIALIZE_H__ -#define CSR_WIFI_NME_AP_SERIALIZE_H__ - -#include "csr_wifi_msgconv.h" - -#include "csr_wifi_nme_ap_prim.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_serialize.h -#endif -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_nme_ap_serialize.h -#endif - -extern void CsrWifiNmeApPfree(void *ptr); - -extern u8* CsrWifiNmeApConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApConfigSetReqSizeof(void *msg); -extern void CsrWifiNmeApConfigSetReqSerFree(void *msg); - -extern u8* CsrWifiNmeApWpsRegisterReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApWpsRegisterReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApWpsRegisterReqSizeof(void *msg); -#define CsrWifiNmeApWpsRegisterReqSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStartReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStartReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStartReqSizeof(void *msg); -extern void CsrWifiNmeApStartReqSerFree(void *msg); - -#define CsrWifiNmeApStopReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeApStopReqDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeApStopReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeApStopReqSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApWmmParamUpdateReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApWmmParamUpdateReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApWmmParamUpdateReqSizeof(void *msg); -#define CsrWifiNmeApWmmParamUpdateReqSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStaRemoveReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStaRemoveReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStaRemoveReqSizeof(void *msg); -#define CsrWifiNmeApStaRemoveReqSerFree CsrWifiNmeApPfree - -#define CsrWifiNmeApConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeApConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeApConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeApConfigSetCfmSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApWpsRegisterCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApWpsRegisterCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApWpsRegisterCfmSizeof(void *msg); -#define CsrWifiNmeApWpsRegisterCfmSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStartCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStartCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStartCfmSizeof(void *msg); -#define CsrWifiNmeApStartCfmSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStopCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStopCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStopCfmSizeof(void *msg); -#define CsrWifiNmeApStopCfmSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStopIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStopIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStopIndSizeof(void *msg); -#define CsrWifiNmeApStopIndSerFree CsrWifiNmeApPfree - -#define CsrWifiNmeApWmmParamUpdateCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeApWmmParamUpdateCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeApWmmParamUpdateCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeApWmmParamUpdateCfmSerFree CsrWifiNmeApPfree - -extern u8* CsrWifiNmeApStationIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeApStationIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeApStationIndSizeof(void *msg); -#define CsrWifiNmeApStationIndSerFree CsrWifiNmeApPfree - -#endif /* CSR_WIFI_NME_AP_SERIALIZE_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_converter_init.h b/drivers/staging/csr/csr_wifi_nme_converter_init.h deleted file mode 100644 index 85e6f5f57130..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_converter_init.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_CONVERTER_INIT_H__ -#define CSR_WIFI_NME_CONVERTER_INIT_H__ - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_converter_init.h -#endif - -#ifndef EXCLUDE_CSR_WIFI_NME_MODULE - -#include "csr_msgconv.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" - -extern const CsrLogPrimitiveInformation* CsrWifiNmeTechInfoGet(void); -#endif /* CSR_LOG_ENABLE */ - -extern void CsrWifiNmeConverterInit(void); - -#else /* EXCLUDE_CSR_WIFI_NME_MODULE */ - -#define CsrWifiNmeConverterInit() - -#endif /* EXCLUDE_CSR_WIFI_NME_MODULE */ - -#endif /* CSR_WIFI_NME_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_lib.h b/drivers/staging/csr/csr_wifi_nme_lib.h deleted file mode 100644 index 5a1f132009bf..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_lib.h +++ /dev/null @@ -1,991 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_LIB_H__ -#define CSR_WIFI_NME_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_nme_prim.h" -#include "csr_wifi_nme_task.h" - - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_lib.h -#endif - -/******************************************************************************* - - NAME - CsrWifiNmeConnectionStatusGetReqSend - - DESCRIPTION - Requests the current connection status of the NME. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiNmeConnectionStatusGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeConnectionStatusGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_CONNECTION_STATUS_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiNmeConnectionStatusGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiNmeConnectionStatusGetReq *msg__; \ - CsrWifiNmeConnectionStatusGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeConnectionStatusGetReqSend(src__, interfaceTag__) \ - CsrWifiNmeConnectionStatusGetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiNmeConnectionStatusGetCfmSend - - DESCRIPTION - Reports the connection status of the NME. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - connectionStatus - NME current connection status - -*******************************************************************************/ -#define CsrWifiNmeConnectionStatusGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStatus__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeConnectionStatusGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_CONNECTION_STATUS_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectionStatus = (connectionStatus__); - -#define CsrWifiNmeConnectionStatusGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionStatus__) \ - { \ - CsrWifiNmeConnectionStatusGetCfm *msg__; \ - CsrWifiNmeConnectionStatusGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStatus__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeConnectionStatusGetCfmSend(dst__, interfaceTag__, status__, connectionStatus__) \ - CsrWifiNmeConnectionStatusGetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, connectionStatus__) - -/******************************************************************************* - - NAME - CsrWifiNmeEventMaskSetReqSend - - DESCRIPTION - The wireless manager application may register with the NME to receive - notification of interesting events. Indications will be sent only if the - wireless manager explicitly registers to be notified of that event. - indMask is a bit mask of values defined in CsrWifiNmeIndicationsMask. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - indMask - Set mask with values from CsrWifiNmeIndications - -*******************************************************************************/ -#define CsrWifiNmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeEventMaskSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_EVENT_MASK_SET_REQ, dst__, src__); \ - msg__->indMask = (indMask__); - -#define CsrWifiNmeEventMaskSetReqSendTo(dst__, src__, indMask__) \ - { \ - CsrWifiNmeEventMaskSetReq *msg__; \ - CsrWifiNmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeEventMaskSetReqSend(src__, indMask__) \ - CsrWifiNmeEventMaskSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, indMask__) - -/******************************************************************************* - - NAME - CsrWifiNmeEventMaskSetCfmSend - - DESCRIPTION - The NME calls the primitive to report the result of the request - primitive. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiNmeEventMaskSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeEventMaskSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_EVENT_MASK_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeEventMaskSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeEventMaskSetCfm *msg__; \ - CsrWifiNmeEventMaskSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeEventMaskSetCfmSend(dst__, status__) \ - CsrWifiNmeEventMaskSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileConnectReqSend - - DESCRIPTION - Requests the NME to attempt to connect to the specified profile. - Overrides any current connection attempt. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - profileIdentity - Identity (BSSID, SSID) of profile to be connected to. - It must match an existing profile in the NME. - -*******************************************************************************/ -#define CsrWifiNmeProfileConnectReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentity__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileConnectReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_CONNECT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->profileIdentity = (profileIdentity__); - -#define CsrWifiNmeProfileConnectReqSendTo(dst__, src__, interfaceTag__, profileIdentity__) \ - { \ - CsrWifiNmeProfileConnectReq *msg__; \ - CsrWifiNmeProfileConnectReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentity__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileConnectReqSend(src__, interfaceTag__, profileIdentity__) \ - CsrWifiNmeProfileConnectReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, profileIdentity__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileConnectCfmSend - - DESCRIPTION - Reports the status of the NME PROFILE CONNECT REQ. If unsuccessful the - connectAttempt parameters contain details of the APs that the NME - attempted to connect to before reporting the failure of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an - interface - status - Indicates the success or otherwise of the requested - operation. - connectAttemptsCount - This parameter is relevant only if - status!=CSR_WIFI_NME_STATUS_SUCCESS. - Number of connection attempt elements provided with - this primitive - connectAttempts - This parameter is relevant only if - status!=CSR_WIFI_NME_STATUS_SUCCESS. - Points to the list of connection attempt elements - provided with this primitive - Each element of the list provides information about - an AP on which the connection attempt was made and - the error that occurred during the attempt. - -*******************************************************************************/ -#define CsrWifiNmeProfileConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileConnectCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_CONNECT_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectAttemptsCount = (connectAttemptsCount__); \ - msg__->connectAttempts = (connectAttempts__); - -#define CsrWifiNmeProfileConnectCfmSendTo(dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ - { \ - CsrWifiNmeProfileConnectCfm *msg__; \ - CsrWifiNmeProfileConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileConnectCfmSend(dst__, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) \ - CsrWifiNmeProfileConnectCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, connectAttemptsCount__, connectAttempts__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteAllReqSend - - DESCRIPTION - Deletes all profiles present in the NME, but does NOT modify the - preferred profile list. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiNmeProfileDeleteAllReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileDeleteAllReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ, dst__, src__); - -#define CsrWifiNmeProfileDeleteAllReqSendTo(dst__, src__) \ - { \ - CsrWifiNmeProfileDeleteAllReq *msg__; \ - CsrWifiNmeProfileDeleteAllReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileDeleteAllReqSend(src__) \ - CsrWifiNmeProfileDeleteAllReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteAllCfmSend - - DESCRIPTION - Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ. - Returns always CSR_WIFI_NME_STATUS_SUCCESS. - - PARAMETERS - queue - Destination Task Queue - status - Indicates the success or otherwise of the requested operation, but - in this case it always set to success. - -*******************************************************************************/ -#define CsrWifiNmeProfileDeleteAllCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileDeleteAllCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_ALL_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeProfileDeleteAllCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeProfileDeleteAllCfm *msg__; \ - CsrWifiNmeProfileDeleteAllCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileDeleteAllCfmSend(dst__, status__) \ - CsrWifiNmeProfileDeleteAllCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteReqSend - - DESCRIPTION - Will delete the profile with a matching identity, but does NOT modify the - preferred profile list. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - profileIdentity - Identity (BSSID, SSID) of profile to be deleted. - -*******************************************************************************/ -#define CsrWifiNmeProfileDeleteReqCreate(msg__, dst__, src__, profileIdentity__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileDeleteReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_REQ, dst__, src__); \ - msg__->profileIdentity = (profileIdentity__); - -#define CsrWifiNmeProfileDeleteReqSendTo(dst__, src__, profileIdentity__) \ - { \ - CsrWifiNmeProfileDeleteReq *msg__; \ - CsrWifiNmeProfileDeleteReqCreate(msg__, dst__, src__, profileIdentity__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileDeleteReqSend(src__, profileIdentity__) \ - CsrWifiNmeProfileDeleteReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, profileIdentity__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteCfmSend - - DESCRIPTION - Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_REQ. - Returns CSR_WIFI_NME_STATUS_NOT_FOUND if there is no matching profile. - - PARAMETERS - queue - Destination Task Queue - status - Indicates the success or otherwise of the requested operation. - -*******************************************************************************/ -#define CsrWifiNmeProfileDeleteCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileDeleteCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DELETE_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeProfileDeleteCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeProfileDeleteCfm *msg__; \ - CsrWifiNmeProfileDeleteCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileDeleteCfmSend(dst__, status__) \ - CsrWifiNmeProfileDeleteCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDisconnectIndSend - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that informs that application that the current profile - connection has disconnected. The indication will contain information - about APs that it attempted to maintain the connection via i.e. in the - case of failed roaming. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an - interface - connectAttemptsCount - Number of connection attempt elements provided with - this primitive - connectAttempts - Points to the list of connection attempt elements - provided with this primitive - Each element of the list provides information about - an AP on which the connection attempt was made and - the error occurred during the attempt. - -*******************************************************************************/ -#define CsrWifiNmeProfileDisconnectIndCreate(msg__, dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileDisconnectInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_DISCONNECT_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->connectAttemptsCount = (connectAttemptsCount__); \ - msg__->connectAttempts = (connectAttempts__); - -#define CsrWifiNmeProfileDisconnectIndSendTo(dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ - { \ - CsrWifiNmeProfileDisconnectInd *msg__; \ - CsrWifiNmeProfileDisconnectIndCreate(msg__, dst__, src__, interfaceTag__, connectAttemptsCount__, connectAttempts__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileDisconnectIndSend(dst__, interfaceTag__, connectAttemptsCount__, connectAttempts__) \ - CsrWifiNmeProfileDisconnectIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, connectAttemptsCount__, connectAttempts__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileOrderSetReqSend - - DESCRIPTION - Defines the preferred order that profiles present in the NME should be - used during the NME auto-connect behaviour. - If profileIdentitysCount == 0, it removes any existing preferred profile - list already present in the NME, effectively disabling the auto-connect - behaviour. - NOTE: Profile identities that do not match any profile stored in the NME - are ignored during the auto-connect procedure. - NOTE: during auto-connect the NME will only attempt to join an existing - adhoc network and it will never attempt to host an adhoc network; for - hosting and adhoc network, use CSR_WIFI_NME_PROFILE_CONNECT_REQ - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an - interface - profileIdentitysCount - The number of profiles identities in the list. - profileIdentitys - Points to the list of profile identities. - -*******************************************************************************/ -#define CsrWifiNmeProfileOrderSetReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileOrderSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_ORDER_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->profileIdentitysCount = (profileIdentitysCount__); \ - msg__->profileIdentitys = (profileIdentitys__); - -#define CsrWifiNmeProfileOrderSetReqSendTo(dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ - { \ - CsrWifiNmeProfileOrderSetReq *msg__; \ - CsrWifiNmeProfileOrderSetReqCreate(msg__, dst__, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileOrderSetReqSend(src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) \ - CsrWifiNmeProfileOrderSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, profileIdentitysCount__, profileIdentitys__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileOrderSetCfmSend - - DESCRIPTION - Confirmation to UNIFI_NME_PROFILE_ORDER_SET.request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - -*******************************************************************************/ -#define CsrWifiNmeProfileOrderSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileOrderSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_ORDER_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiNmeProfileOrderSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiNmeProfileOrderSetCfm *msg__; \ - CsrWifiNmeProfileOrderSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileOrderSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiNmeProfileOrderSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileSetReqSend - - DESCRIPTION - Creates or updates an existing profile in the NME that matches the unique - identity of the profile. Each profile is identified by the combination of - BSSID and SSID. The profile contains all the required credentials for - attempting to connect to the network. Creating or updating a profile via - the NME PROFILE SET REQ does NOT add the profile to the preferred profile - list within the NME used for the NME auto-connect behaviour. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - profile - Specifies the identity and credentials of the network. - -*******************************************************************************/ -#define CsrWifiNmeProfileSetReqCreate(msg__, dst__, src__, profile__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_SET_REQ, dst__, src__); \ - msg__->profile = (profile__); - -#define CsrWifiNmeProfileSetReqSendTo(dst__, src__, profile__) \ - { \ - CsrWifiNmeProfileSetReq *msg__; \ - CsrWifiNmeProfileSetReqCreate(msg__, dst__, src__, profile__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileSetReqSend(src__, profile__) \ - CsrWifiNmeProfileSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, profile__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileSetCfmSend - - DESCRIPTION - Reports the status of the NME PROFILE SET REQ; the request will only fail - if the details specified in the profile contains an invalid combination - of parameters for example specifying the profile as cloaked but not - specifying the SSID. The NME doesn't limit the number of profiles that - may be created. The NME assumes that the entity configuring it is aware - of the appropriate limits. - - PARAMETERS - queue - Destination Task Queue - status - Indicates the success or otherwise of the requested operation. - -*******************************************************************************/ -#define CsrWifiNmeProfileSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeProfileSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeProfileSetCfm *msg__; \ - CsrWifiNmeProfileSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileSetCfmSend(dst__, status__) \ - CsrWifiNmeProfileSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileUpdateIndSend - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that informs that application that the contained profile has - changed. - For example, either the credentials EAP-FAST PAC file or the session data - within the profile has changed. - It is up to the application whether it stores this updated profile or - not. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - profile - The identity and credentials of the network. - -*******************************************************************************/ -#define CsrWifiNmeProfileUpdateIndCreate(msg__, dst__, src__, interfaceTag__, profile__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeProfileUpdateInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_PROFILE_UPDATE_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->profile = (profile__); - -#define CsrWifiNmeProfileUpdateIndSendTo(dst__, src__, interfaceTag__, profile__) \ - { \ - CsrWifiNmeProfileUpdateInd *msg__; \ - CsrWifiNmeProfileUpdateIndCreate(msg__, dst__, src__, interfaceTag__, profile__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeProfileUpdateIndSend(dst__, interfaceTag__, profile__) \ - CsrWifiNmeProfileUpdateIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, profile__) - -/******************************************************************************* - - NAME - CsrWifiNmeSimGsmAuthIndSend - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the UICC Manager to perform a GSM - authentication on behalf of the NME. This indication is generated when - the NME is attempting to connect to a profile configured for EAP-SIM. An - application MUST register to receive this indication for the NME to - support the EAP-SIM credential types. Otherwise the NME has no route to - obtain the information from the UICC. EAP-SIM authentication requires 2 - or 3 GSM authentication rounds and therefore 2 or 3 RANDS (GSM Random - Challenges) are included. - - PARAMETERS - queue - Destination Task Queue - randsLength - GSM RAND is 16 bytes long hence valid values are 32 (2 RANDS) - or 48 (3 RANDs). - rands - 2 or 3 RANDs values. - -*******************************************************************************/ -#define CsrWifiNmeSimGsmAuthIndCreate(msg__, dst__, src__, randsLength__, rands__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimGsmAuthInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_GSM_AUTH_IND, dst__, src__); \ - msg__->randsLength = (randsLength__); \ - msg__->rands = (rands__); - -#define CsrWifiNmeSimGsmAuthIndSendTo(dst__, src__, randsLength__, rands__) \ - { \ - CsrWifiNmeSimGsmAuthInd *msg__; \ - CsrWifiNmeSimGsmAuthIndCreate(msg__, dst__, src__, randsLength__, rands__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimGsmAuthIndSend(dst__, randsLength__, rands__) \ - CsrWifiNmeSimGsmAuthIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, randsLength__, rands__) - -/******************************************************************************* - - NAME - CsrWifiNmeSimGsmAuthResSend - - DESCRIPTION - Response from the application that received the NME SIM GSM AUTH IND. For - each GSM authentication round a GSM Ciphering key (Kc) and a signed - response (SRES) are produced. Since 2 or 3 GSM authentication rounds are - used the 2 or 3 Kc's obtained respectively are combined into one buffer - and similarly the 2 or 3 SRES's obtained are combined into another - buffer. The order of Kc values (SRES values respectively) in their buffer - is the same as that of their corresponding RAND values in the incoming - indication. - - PARAMETERS - status - Indicates the outcome of the requested operation: - STATUS_SUCCESS or STATUS_ERROR - kcsLength - Length in Bytes of Kc buffer. Legal values are: 16 or 24. - kcs - Kc buffer holding 2 or 3 Kc values. - sresLength - Length in Bytes of SRES buffer. Legal values are: 8 or 12. - sres - SRES buffer holding 2 or 3 SRES values. - -*******************************************************************************/ -#define CsrWifiNmeSimGsmAuthResCreate(msg__, dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimGsmAuthRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_GSM_AUTH_RES, dst__, src__); \ - msg__->status = (status__); \ - msg__->kcsLength = (kcsLength__); \ - msg__->kcs = (kcs__); \ - msg__->sresLength = (sresLength__); \ - msg__->sres = (sres__); - -#define CsrWifiNmeSimGsmAuthResSendTo(dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ - { \ - CsrWifiNmeSimGsmAuthRes *msg__; \ - CsrWifiNmeSimGsmAuthResCreate(msg__, dst__, src__, status__, kcsLength__, kcs__, sresLength__, sres__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimGsmAuthResSend(src__, status__, kcsLength__, kcs__, sresLength__, sres__) \ - CsrWifiNmeSimGsmAuthResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, kcsLength__, kcs__, sresLength__, sres__) - -/******************************************************************************* - - NAME - CsrWifiNmeSimImsiGetIndSend - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the IMSI and UICC type from the UICC Manager. - This indication is generated when the NME is attempting to connect to a - profile configured for EAP-SIM/AKA. An application MUST register to - receive this indication for the NME to support the EAP-SIM/AKA credential - types. Otherwise the NME has no route to obtain the information from the - UICC. - - PARAMETERS - queue - Destination Task Queue - -*******************************************************************************/ -#define CsrWifiNmeSimImsiGetIndCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimImsiGetInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_IMSI_GET_IND, dst__, src__); - -#define CsrWifiNmeSimImsiGetIndSendTo(dst__, src__) \ - { \ - CsrWifiNmeSimImsiGetInd *msg__; \ - CsrWifiNmeSimImsiGetIndCreate(msg__, dst__, src__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimImsiGetIndSend(dst__) \ - CsrWifiNmeSimImsiGetIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE) - -/******************************************************************************* - - NAME - CsrWifiNmeSimImsiGetResSend - - DESCRIPTION - Response from the application that received the NME SIM IMSI GET IND. - - PARAMETERS - status - Indicates the outcome of the requested operation: STATUS_SUCCESS - or STATUS_ERROR. - imsi - The value of the IMSI obtained from the UICC. - cardType - The UICC type (GSM only (SIM), UMTS only (USIM), Both). - -*******************************************************************************/ -#define CsrWifiNmeSimImsiGetResCreate(msg__, dst__, src__, status__, imsi__, cardType__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimImsiGetRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_IMSI_GET_RES, dst__, src__); \ - msg__->status = (status__); \ - msg__->imsi = (imsi__); \ - msg__->cardType = (cardType__); - -#define CsrWifiNmeSimImsiGetResSendTo(dst__, src__, status__, imsi__, cardType__) \ - { \ - CsrWifiNmeSimImsiGetRes *msg__; \ - CsrWifiNmeSimImsiGetResCreate(msg__, dst__, src__, status__, imsi__, cardType__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimImsiGetResSend(src__, status__, imsi__, cardType__) \ - CsrWifiNmeSimImsiGetResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, imsi__, cardType__) - -/******************************************************************************* - - NAME - CsrWifiNmeSimUmtsAuthIndSend - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the UICC Manager to perform a UMTS - authentication on behalf of the NME. This indication is generated when - the NME is attempting to connect to a profile configured for EAP-AKA. An - application MUST register to receive this indication for the NME to - support the EAP-AKA credential types. Otherwise the NME has no route to - obtain the information from the USIM. EAP-AKA requires one UMTS - authentication round and therefore only one RAND and one AUTN values are - included. - - PARAMETERS - queue - Destination Task Queue - rand - UMTS RAND value. - autn - UMTS AUTN value. - -*******************************************************************************/ -#define CsrWifiNmeSimUmtsAuthIndCreate(msg__, dst__, src__, rand__, autn__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimUmtsAuthInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_UMTS_AUTH_IND, dst__, src__); \ - memcpy(msg__->rand, (rand__), sizeof(u8) * 16); \ - memcpy(msg__->autn, (autn__), sizeof(u8) * 16); - -#define CsrWifiNmeSimUmtsAuthIndSendTo(dst__, src__, rand__, autn__) \ - { \ - CsrWifiNmeSimUmtsAuthInd *msg__; \ - CsrWifiNmeSimUmtsAuthIndCreate(msg__, dst__, src__, rand__, autn__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimUmtsAuthIndSend(dst__, rand__, autn__) \ - CsrWifiNmeSimUmtsAuthIndSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, rand__, autn__) - -/******************************************************************************* - - NAME - CsrWifiNmeSimUmtsAuthResSend - - DESCRIPTION - Response from the application that received the NME SIM UMTS AUTH IND. - The values of umtsCipherKey, umtsIntegrityKey, resParameterLength and - resParameter are only meanigful when result = UMTS_AUTH_RESULT_SUCCESS. - The value of auts is only meaningful when - result=UMTS_AUTH_RESULT_SYNC_FAIL. - - PARAMETERS - status - Indicates the outcome of the requested operation: - STATUS_SUCCESS or STATUS_ERROR. - result - The result of UMTS authentication as performed by the - UICC which could be: Success, Authentication Reject or - Synchronisation Failure. For all these 3 outcomes the - value of status is success. - umtsCipherKey - The UMTS Cipher Key as calculated and returned by the - UICC. - umtsIntegrityKey - The UMTS Integrity Key as calculated and returned by - the UICC. - resParameterLength - The length (in bytes) of the RES parameter (min=4; max - = 16). - resParameter - The RES parameter as calculated and returned by the - UICC. - auts - The AUTS parameter as calculated and returned by the - UICC. - -*******************************************************************************/ -#define CsrWifiNmeSimUmtsAuthResCreate(msg__, dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeSimUmtsAuthRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_SIM_UMTS_AUTH_RES, dst__, src__); \ - msg__->status = (status__); \ - msg__->result = (result__); \ - memcpy(msg__->umtsCipherKey, (umtsCipherKey__), sizeof(u8) * 16); \ - memcpy(msg__->umtsIntegrityKey, (umtsIntegrityKey__), sizeof(u8) * 16); \ - msg__->resParameterLength = (resParameterLength__); \ - msg__->resParameter = (resParameter__); \ - memcpy(msg__->auts, (auts__), sizeof(u8) * 14); - -#define CsrWifiNmeSimUmtsAuthResSendTo(dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ - { \ - CsrWifiNmeSimUmtsAuthRes *msg__; \ - CsrWifiNmeSimUmtsAuthResCreate(msg__, dst__, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeSimUmtsAuthResSend(src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) \ - CsrWifiNmeSimUmtsAuthResSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, status__, result__, umtsCipherKey__, umtsIntegrityKey__, resParameterLength__, resParameter__, auts__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCancelReqSend - - DESCRIPTION - Requests the NME to cancel any WPS procedure that it is currently - performing. This includes WPS registrar activities started because of - CSR_WIFI_NME_AP_REGISTER.request - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiNmeWpsCancelReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsCancelReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CANCEL_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiNmeWpsCancelReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiNmeWpsCancelReq *msg__; \ - CsrWifiNmeWpsCancelReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsCancelReqSend(src__, interfaceTag__) \ - CsrWifiNmeWpsCancelReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCancelCfmSend - - DESCRIPTION - Reports the status of the NME WPS REQ, the request is always SUCCESSFUL. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Only returns CSR_WIFI_NME_STATUS_SUCCESS - -*******************************************************************************/ -#define CsrWifiNmeWpsCancelCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsCancelCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CANCEL_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiNmeWpsCancelCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiNmeWpsCancelCfm *msg__; \ - CsrWifiNmeWpsCancelCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsCancelCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiNmeWpsCancelCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCfmSend - - DESCRIPTION - Reports the status of the NME WPS REQ. - If CSR_WIFI_NME_STATUS_SUCCESS, the profile parameter contains the - identity and credentials of the AP. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - profile - This parameter is relevant only if - status==CSR_WIFI_NME_STATUS_SUCCESS. - The identity and credentials of the network. - -*******************************************************************************/ -#define CsrWifiNmeWpsCfmCreate(msg__, dst__, src__, interfaceTag__, status__, profile__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->profile = (profile__); - -#define CsrWifiNmeWpsCfmSendTo(dst__, src__, interfaceTag__, status__, profile__) \ - { \ - CsrWifiNmeWpsCfm *msg__; \ - CsrWifiNmeWpsCfmCreate(msg__, dst__, src__, interfaceTag__, status__, profile__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsCfmSend(dst__, interfaceTag__, status__, profile__) \ - CsrWifiNmeWpsCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, interfaceTag__, status__, profile__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsConfigSetReqSend - - DESCRIPTION - This primitive passes the WPS information for the device to NME. This may - be accepted only if no interface is active. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - wpsConfig - WPS config. - -*******************************************************************************/ -#define CsrWifiNmeWpsConfigSetReqCreate(msg__, dst__, src__, wpsConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CONFIG_SET_REQ, dst__, src__); \ - msg__->wpsConfig = (wpsConfig__); - -#define CsrWifiNmeWpsConfigSetReqSendTo(dst__, src__, wpsConfig__) \ - { \ - CsrWifiNmeWpsConfigSetReq *msg__; \ - CsrWifiNmeWpsConfigSetReqCreate(msg__, dst__, src__, wpsConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsConfigSetReqSend(src__, wpsConfig__) \ - CsrWifiNmeWpsConfigSetReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, wpsConfig__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsConfigSetCfmSend - - DESCRIPTION - Confirm. - - PARAMETERS - queue - Destination Task Queue - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiNmeWpsConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiNmeWpsConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiNmeWpsConfigSetCfm *msg__; \ - CsrWifiNmeWpsConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsConfigSetCfmSend(dst__, status__) \ - CsrWifiNmeWpsConfigSetCfmSendTo(dst__, CSR_WIFI_NME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiNmeWpsReqSend - - DESCRIPTION - Requests the NME to look for WPS enabled APs and attempt to perform WPS - to determine the appropriate security credentials to connect to the AP. - If the PIN == '00000000' then 'push button mode' is indicated, otherwise - the PIN has to match that of the AP. 4 digit pin is passed by sending the - pin digits in pin[0]..pin[3] and rest of the contents filled with '-'. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - pin - PIN value. - ssid - Service Set identifier - bssid - ID of Basic Service Set for which a WPS connection attempt is - being made. - -*******************************************************************************/ -#define CsrWifiNmeWpsReqCreate(msg__, dst__, src__, interfaceTag__, pin__, ssid__, bssid__) \ - msg__ = kmalloc(sizeof(CsrWifiNmeWpsReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_NME_PRIM, CSR_WIFI_NME_WPS_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - memcpy(msg__->pin, (pin__), sizeof(u8) * 8); \ - msg__->ssid = (ssid__); \ - msg__->bssid = (bssid__); - -#define CsrWifiNmeWpsReqSendTo(dst__, src__, interfaceTag__, pin__, ssid__, bssid__) \ - { \ - CsrWifiNmeWpsReq *msg__; \ - CsrWifiNmeWpsReqCreate(msg__, dst__, src__, interfaceTag__, pin__, ssid__, bssid__); \ - CsrMsgTransport(dst__, CSR_WIFI_NME_PRIM, msg__); \ - } - -#define CsrWifiNmeWpsReqSend(src__, interfaceTag__, pin__, ssid__, bssid__) \ - CsrWifiNmeWpsReqSendTo(CSR_WIFI_NME_IFACEQUEUE, src__, interfaceTag__, pin__, ssid__, bssid__) - -#endif /* CSR_WIFI_NME_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_nme_prim.h b/drivers/staging/csr/csr_wifi_nme_prim.h deleted file mode 100644 index 9a7927a117ea..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_prim.h +++ /dev/null @@ -1,1657 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_PRIM_H__ -#define CSR_WIFI_NME_PRIM_H__ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" -#include "csr_wifi_sme_prim.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_prim.h -#endif - -#define CSR_WIFI_NME_PRIM (0x0424) - -typedef CsrPrim CsrWifiNmePrim; - -typedef void (*CsrWifiNmeFrameFreeFunction)(void *frame); - -/******************************************************************************* - - NAME - CsrWifiNmeAuthMode - - DESCRIPTION - WiFi Authentication Mode - - VALUES - CSR_WIFI_NME_AUTH_MODE_80211_OPEN - - Connects to an open system network (i.e. no authentication, - no encryption) or to a WEP enabled network. - CSR_WIFI_NME_AUTH_MODE_80211_SHARED - - Connect to a WEP enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_WPA - - Connects to a WPA Enterprise enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_WPAPSK - - Connects to a WPA with Pre-Shared Key enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_WPA2 - - Connects to a WPA2 Enterprise enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_WPA2PSK - - Connects to a WPA2 with Pre-Shared Key enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_CCKM - - Connects to a CCKM enabled network. - CSR_WIFI_NME_AUTH_MODE_WAPI_WAI - - Connects to a WAPI Enterprise enabled network. - CSR_WIFI_NME_AUTH_MODE_WAPI_WAIPSK - - Connects to a WAPI with Pre-Shared Key enabled network. - CSR_WIFI_NME_AUTH_MODE_8021X_OTHER1X - - For future use. - -*******************************************************************************/ -typedef u16 CsrWifiNmeAuthMode; -#define CSR_WIFI_NME_AUTH_MODE_80211_OPEN ((CsrWifiNmeAuthMode) 0x0001) -#define CSR_WIFI_NME_AUTH_MODE_80211_SHARED ((CsrWifiNmeAuthMode) 0x0002) -#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA ((CsrWifiNmeAuthMode) 0x0004) -#define CSR_WIFI_NME_AUTH_MODE_8021X_WPAPSK ((CsrWifiNmeAuthMode) 0x0008) -#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA2 ((CsrWifiNmeAuthMode) 0x0010) -#define CSR_WIFI_NME_AUTH_MODE_8021X_WPA2PSK ((CsrWifiNmeAuthMode) 0x0020) -#define CSR_WIFI_NME_AUTH_MODE_8021X_CCKM ((CsrWifiNmeAuthMode) 0x0040) -#define CSR_WIFI_NME_AUTH_MODE_WAPI_WAI ((CsrWifiNmeAuthMode) 0x0080) -#define CSR_WIFI_NME_AUTH_MODE_WAPI_WAIPSK ((CsrWifiNmeAuthMode) 0x0100) -#define CSR_WIFI_NME_AUTH_MODE_8021X_OTHER1X ((CsrWifiNmeAuthMode) 0x0200) - -/******************************************************************************* - - NAME - CsrWifiNmeBssType - - DESCRIPTION - Type of BSS - - VALUES - CSR_WIFI_NME_BSS_TYPE_INFRASTRUCTURE - - Infrastructure BSS type where access to the network is via - one or several Access Points. - CSR_WIFI_NME_BSS_TYPE_ADHOC - - Adhoc or Independent BSS Type where one Station acts as a - host and future stations can join the adhoc network without - needing an access point. - CSR_WIFI_NME_BSS_TYPE_RESERVED - - To be in sync with SME.This is not used. - CSR_WIFI_NME_BSS_TYPE_P2P - - P2P mode of operation. - -*******************************************************************************/ -typedef u8 CsrWifiNmeBssType; -#define CSR_WIFI_NME_BSS_TYPE_INFRASTRUCTURE ((CsrWifiNmeBssType) 0x00) -#define CSR_WIFI_NME_BSS_TYPE_ADHOC ((CsrWifiNmeBssType) 0x01) -#define CSR_WIFI_NME_BSS_TYPE_RESERVED ((CsrWifiNmeBssType) 0x02) -#define CSR_WIFI_NME_BSS_TYPE_P2P ((CsrWifiNmeBssType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiNmeCcxOptionsMask - - DESCRIPTION - Enumeration type defining possible mask values for setting CCX options. - - VALUES - CSR_WIFI_NME_CCX_OPTION_NONE - No CCX option is set. - CSR_WIFI_NME_CCX_OPTION_CCKM - CCX option cckm is set. - -*******************************************************************************/ -typedef u8 CsrWifiNmeCcxOptionsMask; -#define CSR_WIFI_NME_CCX_OPTION_NONE ((CsrWifiNmeCcxOptionsMask) 0x00) -#define CSR_WIFI_NME_CCX_OPTION_CCKM ((CsrWifiNmeCcxOptionsMask) 0x01) - -/******************************************************************************* - - NAME - CsrWifiNmeConfigAction - - DESCRIPTION - - VALUES - CSR_WIFI_PIN_ENTRY_PUSH_BUTTON - - CSR_WIFI_PIN_ENTRY_DISPLAY_PIN - - CSR_WIFI_PIN_ENTRY_ENTER_PIN - - -*******************************************************************************/ -typedef u8 CsrWifiNmeConfigAction; -#define CSR_WIFI_PIN_ENTRY_PUSH_BUTTON ((CsrWifiNmeConfigAction) 0x00) -#define CSR_WIFI_PIN_ENTRY_DISPLAY_PIN ((CsrWifiNmeConfigAction) 0x01) -#define CSR_WIFI_PIN_ENTRY_ENTER_PIN ((CsrWifiNmeConfigAction) 0x02) - -/******************************************************************************* - - NAME - CsrWifiNmeConnectionStatus - - DESCRIPTION - Indicate the NME Connection Status when connecting or when disconnecting - - VALUES - CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTED - - NME is disconnected. - CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTING - - NME is in the process of connecting. - CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_AUTHENTICATING - - NME is in the authentication stage of a connection attempt. - CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTED - - NME is connected. - CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTING - - NME is in the process of disconnecting. - -*******************************************************************************/ -typedef u8 CsrWifiNmeConnectionStatus; -#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTED ((CsrWifiNmeConnectionStatus) 0x00) -#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTING ((CsrWifiNmeConnectionStatus) 0x01) -#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_AUTHENTICATING ((CsrWifiNmeConnectionStatus) 0x02) -#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_CONNECTED ((CsrWifiNmeConnectionStatus) 0x03) -#define CSR_WIFI_NME_CONNECTION_STATUS_CONNECTION_STATUS_DISCONNECTING ((CsrWifiNmeConnectionStatus) 0x04) - -/******************************************************************************* - - NAME - CsrWifiNmeCredentialType - - DESCRIPTION - NME Credential Types - - VALUES - CSR_WIFI_NME_CREDENTIAL_TYPE_OPEN_SYSTEM - - Credential Type Open System. - CSR_WIFI_NME_CREDENTIAL_TYPE_WEP64 - - Credential Type WEP-64 - CSR_WIFI_NME_CREDENTIAL_TYPE_WEP128 - - Credential Type WEP-128 - CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PSK - - Credential Type WPA Pre-Shared Key - CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PASSPHRASE - - Credential Type WPA pass phrase - CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PSK - - Credential Type WPA2 Pre-Shared Key. - CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PASSPHRASE - - Credential Type WPA2 pass phrase - CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PSK - - Credential Type WAPI Pre-Shared Key. - CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PASSPHRASE - - Credential Type WAPI pass phrase - CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI - - Credential Type WAPI certificates - CSR_WIFI_NME_CREDENTIAL_TYPE_8021X - - Credential Type 802.1X: the associated type supports - FAST/LEAP/TLS/TTLS/PEAP/etc. - -*******************************************************************************/ -typedef u16 CsrWifiNmeCredentialType; -#define CSR_WIFI_NME_CREDENTIAL_TYPE_OPEN_SYSTEM ((CsrWifiNmeCredentialType) 0x0000) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WEP64 ((CsrWifiNmeCredentialType) 0x0001) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WEP128 ((CsrWifiNmeCredentialType) 0x0002) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PSK ((CsrWifiNmeCredentialType) 0x0003) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0004) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PSK ((CsrWifiNmeCredentialType) 0x0005) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WPA2_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0006) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PSK ((CsrWifiNmeCredentialType) 0x0007) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI_PASSPHRASE ((CsrWifiNmeCredentialType) 0x0008) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_WAPI ((CsrWifiNmeCredentialType) 0x0009) -#define CSR_WIFI_NME_CREDENTIAL_TYPE_8021X ((CsrWifiNmeCredentialType) 0x000A) - -/******************************************************************************* - - NAME - CsrWifiNmeEapMethod - - DESCRIPTION - Outer EAP method with possibly inner method. - - VALUES - CSR_WIFI_NME_EAP_METHOD_TLS - - EAP-TLS Method. - CSR_WIFI_NME_EAP_METHOD_TTLS_MSCHAPV2 - - EAP-TTLS Method with MSCHAPV2. - CSR_WIFI_NME_EAP_METHOD_PEAP_GTC - - EAP-PEAP Method with GTC. - CSR_WIFI_NME_EAP_METHOD_PEAP_MSCHAPV2 - - EAP-PEAP Method with MSCHAPV2. - CSR_WIFI_NME_EAP_METHOD_SIM - - EAP-SIM Method. - CSR_WIFI_NME_EAP_METHOD_AKA - - EAP-AKA Method. - CSR_WIFI_NME_EAP_METHOD_FAST_GTC - - EAP-FAST Method with GTC. - CSR_WIFI_NME_EAP_METHOD_FAST_MSCHAPV2 - - EAP-FAST Method with MSCHAPV2. - CSR_WIFI_NME_EAP_METHOD_LEAP - - EAP-LEAP Method. - -*******************************************************************************/ -typedef u16 CsrWifiNmeEapMethod; -#define CSR_WIFI_NME_EAP_METHOD_TLS ((CsrWifiNmeEapMethod) 0x0001) -#define CSR_WIFI_NME_EAP_METHOD_TTLS_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0002) -#define CSR_WIFI_NME_EAP_METHOD_PEAP_GTC ((CsrWifiNmeEapMethod) 0x0004) -#define CSR_WIFI_NME_EAP_METHOD_PEAP_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0008) -#define CSR_WIFI_NME_EAP_METHOD_SIM ((CsrWifiNmeEapMethod) 0x0010) -#define CSR_WIFI_NME_EAP_METHOD_AKA ((CsrWifiNmeEapMethod) 0x0020) -#define CSR_WIFI_NME_EAP_METHOD_FAST_GTC ((CsrWifiNmeEapMethod) 0x0040) -#define CSR_WIFI_NME_EAP_METHOD_FAST_MSCHAPV2 ((CsrWifiNmeEapMethod) 0x0080) -#define CSR_WIFI_NME_EAP_METHOD_LEAP ((CsrWifiNmeEapMethod) 0x0100) - -/******************************************************************************* - - NAME - CsrWifiNmeEncryption - - DESCRIPTION - WiFi Encryption method - - VALUES - CSR_WIFI_NME_ENCRYPTION_CIPHER_NONE - - No encryprion set. - CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 - - 40 bytes WEP key for peer to peer communication. - CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 - - 104 bytes WEP key for peer to peer communication. - CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_TKIP - - TKIP key for peer to peer communication. - CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP - - CCMP key for peer to peer communication. - CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 - - SMS4 key for peer to peer communication. - CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP40 - - 40 bytes WEP key for broadcast messages. - CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP104 - - 104 bytes WEP key for broadcast messages. - CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_TKIP - - TKIP key for broadcast messages. - CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP - - CCMP key for broadcast messages - CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_SMS4 - - SMS4 key for broadcast messages. - -*******************************************************************************/ -typedef u16 CsrWifiNmeEncryption; -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_NONE ((CsrWifiNmeEncryption) 0x0000) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 ((CsrWifiNmeEncryption) 0x0001) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 ((CsrWifiNmeEncryption) 0x0002) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_TKIP ((CsrWifiNmeEncryption) 0x0004) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP ((CsrWifiNmeEncryption) 0x0008) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 ((CsrWifiNmeEncryption) 0x0010) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP40 ((CsrWifiNmeEncryption) 0x0020) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_WEP104 ((CsrWifiNmeEncryption) 0x0040) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_TKIP ((CsrWifiNmeEncryption) 0x0080) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP ((CsrWifiNmeEncryption) 0x0100) -#define CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_SMS4 ((CsrWifiNmeEncryption) 0x0200) - -/******************************************************************************* - - NAME - CsrWifiNmeIndications - - DESCRIPTION - NME indications - - VALUES - CSR_WIFI_NME_INDICATIONS_IND_AP_STATION - - NME AP Station Indication. - CSR_WIFI_NME_INDICATIONS_IND_AP_STOP - - NME AP Stop Indication. - CSR_WIFI_NME_INDICATIONS_IND_SIM_UMTS_AUTH - - NME UMTS Authentication Indication. - CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_START - - NME P2P Group Start Indication. - CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_STATUS - - NME P2P Group Status Indication. - CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_ROLE - - NME P2P Group Role Indication. - CSR_WIFI_NME_INDICATIONS_IND_PROFILE_DISCONNECT - - NME Profile Disconnect Indication. - CSR_WIFI_NME_INDICATIONS_IND_PROFILE_UPDATE - - NME Profile Update Indication. - CSR_WIFI_NME_INDICATIONS_IND_SIM_IMSI_GET - - NME GET IMSI Indication. - CSR_WIFI_NME_INDICATIONS_IND_SIM_GSM_AUTH - - NME GSM Authentication Indication. - CSR_WIFI_NME_INDICATIONS_ALL - - Used to register for all available indications - -*******************************************************************************/ -typedef u32 CsrWifiNmeIndications; -#define CSR_WIFI_NME_INDICATIONS_IND_AP_STATION ((CsrWifiNmeIndications) 0x00100000) -#define CSR_WIFI_NME_INDICATIONS_IND_AP_STOP ((CsrWifiNmeIndications) 0x00200000) -#define CSR_WIFI_NME_INDICATIONS_IND_SIM_UMTS_AUTH ((CsrWifiNmeIndications) 0x01000000) -#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_START ((CsrWifiNmeIndications) 0x02000000) -#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_STATUS ((CsrWifiNmeIndications) 0x04000000) -#define CSR_WIFI_NME_INDICATIONS_IND_P2P_GROUP_ROLE ((CsrWifiNmeIndications) 0x08000000) -#define CSR_WIFI_NME_INDICATIONS_IND_PROFILE_DISCONNECT ((CsrWifiNmeIndications) 0x10000000) -#define CSR_WIFI_NME_INDICATIONS_IND_PROFILE_UPDATE ((CsrWifiNmeIndications) 0x20000000) -#define CSR_WIFI_NME_INDICATIONS_IND_SIM_IMSI_GET ((CsrWifiNmeIndications) 0x40000000) -#define CSR_WIFI_NME_INDICATIONS_IND_SIM_GSM_AUTH ((CsrWifiNmeIndications) 0x80000000) -#define CSR_WIFI_NME_INDICATIONS_ALL ((CsrWifiNmeIndications) 0xFFFFFFFF) - -/******************************************************************************* - - NAME - CsrWifiNmeSecError - - DESCRIPTION - NME Security Errors - place holder for the security library abort reason - - VALUES - CSR_WIFI_NME_SEC_ERROR_SEC_ERROR_UNKNOWN - - Unknown Security Error. - -*******************************************************************************/ -typedef u8 CsrWifiNmeSecError; -#define CSR_WIFI_NME_SEC_ERROR_SEC_ERROR_UNKNOWN ((CsrWifiNmeSecError) 0x00) - -/******************************************************************************* - - NAME - CsrWifiNmeSimCardType - - DESCRIPTION - (U)SIM Card (or UICC) types - - VALUES - CSR_WIFI_NME_SIM_CARD_TYPE_2G - 2G SIM card, capable of performing GSM - authentication only. - CSR_WIFI_NME_SIM_CARD_TYPE_3G - UICC supporting USIM application, capable - of performing UMTS authentication only. - CSR_WIFI_NME_SIM_CARD_TYPE_2G3G - UICC supporting both USIM and SIM - applications, capable of performing both - UMTS and GSM authentications. - -*******************************************************************************/ -typedef u8 CsrWifiNmeSimCardType; -#define CSR_WIFI_NME_SIM_CARD_TYPE_2G ((CsrWifiNmeSimCardType) 0x01) -#define CSR_WIFI_NME_SIM_CARD_TYPE_3G ((CsrWifiNmeSimCardType) 0x02) -#define CSR_WIFI_NME_SIM_CARD_TYPE_2G3G ((CsrWifiNmeSimCardType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiNmeUmtsAuthResult - - DESCRIPTION - Only relevant for UMTS Authentication. It indicates if the UICC has - successfully authenticated the network or otherwise. - - VALUES - CSR_WIFI_NME_UMTS_AUTH_RESULT_SUCCESS - - Successful outcome from USIM indicating that the card has - successfully authenticated the network. - CSR_WIFI_NME_UMTS_AUTH_RESULT_SYNC_FAIL - - Unsuccessful outcome from USIM indicating that the card is - requesting the network to synchronise and re-try again. If - no further request is received an NME timer will expire and - the authentication is aborted. - CSR_WIFI_NME_UMTS_AUTH_RESULT_REJECT - - Unsuccessful outcome from USIM indicating that the card has - rejected the network and that the authentication is - aborted. - -*******************************************************************************/ -typedef u8 CsrWifiNmeUmtsAuthResult; -#define CSR_WIFI_NME_UMTS_AUTH_RESULT_SUCCESS ((CsrWifiNmeUmtsAuthResult) 0x00) -#define CSR_WIFI_NME_UMTS_AUTH_RESULT_SYNC_FAIL ((CsrWifiNmeUmtsAuthResult) 0x01) -#define CSR_WIFI_NME_UMTS_AUTH_RESULT_REJECT ((CsrWifiNmeUmtsAuthResult) 0x02) - -/******************************************************************************* - - NAME - CsrWifiNmeWmmQosInfo - - DESCRIPTION - Defines bits for the QoS Info octect as defined in the WMM specification. - The values of this type are used across the NME/SME/Router API's and they - must be kept consistent with the corresponding types in the .xml of the - other interfaces - - VALUES - CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_ALL - - WMM AP may deliver all buffered frames. - CSR_WIFI_NME_WMM_QOS_INFO_AC_VO - - To enable the triggering and delivery of QoS Voice. - CSR_WIFI_NME_WMM_QOS_INFO_AC_VI - - To enable the triggering and delivery of QoS Video. - CSR_WIFI_NME_WMM_QOS_INFO_AC_BK - - To enable the triggering and delivery of QoS Background. - CSR_WIFI_NME_WMM_QOS_INFO_AC_BE - - To enable the triggering and delivery of QoS Best Effort. - CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_TWO - - WMM AP may deliver a maximum of 2 buffered frames per - Unscheduled Service Period (USP). - CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_FOUR - - WMM AP may deliver a maximum of 4 buffered frames per USP. - CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_SIX - - WMM AP may deliver a maximum of 6 buffered frames per USP. - -*******************************************************************************/ -typedef u8 CsrWifiNmeWmmQosInfo; -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_ALL ((CsrWifiNmeWmmQosInfo) 0x00) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_VO ((CsrWifiNmeWmmQosInfo) 0x01) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_VI ((CsrWifiNmeWmmQosInfo) 0x02) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_BK ((CsrWifiNmeWmmQosInfo) 0x04) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_BE ((CsrWifiNmeWmmQosInfo) 0x08) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_TWO ((CsrWifiNmeWmmQosInfo) 0x20) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_FOUR ((CsrWifiNmeWmmQosInfo) 0x40) -#define CSR_WIFI_NME_WMM_QOS_INFO_AC_MAX_SP_SIX ((CsrWifiNmeWmmQosInfo) 0x60) - - -/******************************************************************************* - - NAME - CsrWifiNmeEapMethodMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiNmeEapMethod. - -*******************************************************************************/ -typedef u16 CsrWifiNmeEapMethodMask; -/******************************************************************************* - - NAME - CsrWifiNmeEncryptionMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiNmeEncryption - -*******************************************************************************/ -typedef u16 CsrWifiNmeEncryptionMask; -/******************************************************************************* - - NAME - CsrWifiNmeIndicationsMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiNmeIndications - -*******************************************************************************/ -typedef u32 CsrWifiNmeIndicationsMask; -/******************************************************************************* - - NAME - CsrWifiNmeNmeIndicationsMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiNmeNmeIndications. - Used to overlap the unused portion of the unifi_IndicationsMask For NME - specific indications - -*******************************************************************************/ -typedef u32 CsrWifiNmeNmeIndicationsMask; -/******************************************************************************* - - NAME - CsrWifiNmeWmmQosInfoMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiNmeWmmQosInfo - -*******************************************************************************/ -typedef u8 CsrWifiNmeWmmQosInfoMask; - - -/******************************************************************************* - - NAME - CsrWifiNmeEmpty - - DESCRIPTION - Empty Structure to indicate that no credentials are available. - - MEMBERS - empty - Only element of the empty structure (always set to 0). - -*******************************************************************************/ -typedef struct -{ - u8 empty; -} CsrWifiNmeEmpty; - -/******************************************************************************* - - NAME - CsrWifiNmePassphrase - - DESCRIPTION - Structure holding the ASCII Pass Phrase data. - - MEMBERS - encryptionMode - Encryption type as defined in CsrWifiSmeEncryption. - passphrase - Pass phrase ASCII value. - -*******************************************************************************/ -typedef struct -{ - u16 encryptionMode; - char *passphrase; -} CsrWifiNmePassphrase; - -/******************************************************************************* - - NAME - CsrWifiNmePsk - - DESCRIPTION - Structure holding the Pre-Shared Key data. - - MEMBERS - encryptionMode - Encryption type as defined in CsrWifiSmeEncryption. - psk - Pre-Shared Key value. - -*******************************************************************************/ -typedef struct -{ - u16 encryptionMode; - u8 psk[32]; -} CsrWifiNmePsk; - -/******************************************************************************* - - NAME - CsrWifiNmeWapiCredentials - - DESCRIPTION - Structure holding WAPI credentials data. - - MEMBERS - certificateLength - Length in bytes of the following client certificate. - certificate - The actual client certificate data (if present). - DER/PEM format supported. - privateKeyLength - Length in bytes of the following private key. - privateKey - The actual private key. DER/PEM format. - caCertificateLength - Length in bytes of the following certificate authority - certificate. - caCertificate - The actual certificate authority certificate data. If - not supplied the received certificate authority - certificate is assumed to be validate, if present the - received certificate is validated against it. DER/PEM - format supported. - -*******************************************************************************/ -typedef struct -{ - u32 certificateLength; - u8 *certificate; - u16 privateKeyLength; - u8 *privateKey; - u32 caCertificateLength; - u8 *caCertificate; -} CsrWifiNmeWapiCredentials; - -/******************************************************************************* - - NAME - CsrWifiNmeConnectAttempt - - DESCRIPTION - Structure holding Connection attempt data. - - MEMBERS - bssid - Id of Basic Service Set connections attempt have been made - to. - status - Status returned to indicate the success or otherwise of the - connection attempt. - securityError - Security error status indicating the nature of the failure - to connect. - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress bssid; - CsrResult status; - CsrWifiNmeSecError securityError; -} CsrWifiNmeConnectAttempt; - -/******************************************************************************* - - NAME - CsrWifiNmeEapCredentials - - DESCRIPTION - Supports the use of multiple EAP methods via a single structure. The - methods required are indicated by the value set in the eapMethodMask - - MEMBERS - eapMethodMask - - Bit mask of supported EAP methods - Currently only supports the setting of one bit. - Required for all the EAP methods. - authMode - - Bit mask representing the authentication types that may be - supported by a suitable AP. An AP must support at least one - of the authentication types specified to be considered for - connection. Required for all EAP methods. - encryptionMode - - Bit mask representing the encryption types that may be - supported by a suitable AP. An AP must support a suitable - mix of the pairwise and group encryption types requested to - be considered for connection. Required for all EAP methods. - userName - - User name. Required for all EAP methods except: SIM or AKA. - userPassword - - User Password. Required for all EAP methods except: TLS, - SIM or AKA. - authServerUserIdentity - - Authentication server user Identity. Required for all EAP - methods except: TLS, SIM, AKA or FAST. - clientCertificateLength - - Length in bytes of the following client certificate (if - present). Only required for TLS. - clientCertificate - - The actual client certificate data (if present). Only - required for TLS. DER/PEM format supported. - certificateAuthorityCertificateLength - - Length in bytes of the following certificate authority - certificate (if present). Optional for TLS, TTLS, PEAP. - certificateAuthorityCertificate - - The actual certificate authority certificate data (if - present). If not supplied the received certificate - authority certificate is assumed to be valid, if present - the received certificate is validated against it. Optional - for TLS, TTLS, PEAP. DER/PEM format supported. - privateKeyLength - - Length in bytes of the following private key (if present). - Only required for TLS. - privateKey - - The actual private key (if present). Only required for TLS. - DER/PEM format, maybe password protected. - privateKeyPassword - - Optional password to protect the private key. - sessionLength - - Length in bytes of the following session field Supported - for all EAP methods except: SIM or AKA. - session - - Session information to support faster re-authentication. - Supported for all EAP methods except: SIM or AKA. - allowPacProvisioning - - If TRUE: PAC provisioning is allowed 'over-the_air'; - If FALSE: a PAC must be supplied. - Only required for FAST. - pacLength - - Length the following PAC field. If allowPacProvisioning is - FALSE then the PAC MUST be supplied (i.e. non-zero). Only - required for FAST. - pac - - The actual PAC data. If allowPacProvisioning is FALSE then - the PAC MUST be supplied. Only required for FAST. - pacPassword - - Optional password to protect the PAC. Only required for - FAST. - -*******************************************************************************/ -typedef struct -{ - CsrWifiNmeEapMethodMask eapMethodMask; - CsrWifiSmeAuthModeMask authMode; - CsrWifiNmeEncryptionMask encryptionMode; - char *userName; - char *userPassword; - char *authServerUserIdentity; - u32 clientCertificateLength; - u8 *clientCertificate; - u32 certificateAuthorityCertificateLength; - u8 *certificateAuthorityCertificate; - u16 privateKeyLength; - u8 *privateKey; - char *privateKeyPassword; - u32 sessionLength; - u8 *session; - u8 allowPacProvisioning; - u32 pacLength; - u8 *pac; - char *pacPassword; -} CsrWifiNmeEapCredentials; - -/******************************************************************************* - - NAME - CsrWifiNmePeerConfig - - DESCRIPTION - Structure holding Peer Config data. - - MEMBERS - p2pDeviceId - - groupCapabilityMask - - groupOwnerIntent - - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress p2pDeviceId; - CsrWifiSmeP2pGroupCapabilityMask groupCapabilityMask; - u8 groupOwnerIntent; -} CsrWifiNmePeerConfig; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileIdentity - - DESCRIPTION - The identity of a profile is defined as the unique combination the BSSID - and SSID. - - MEMBERS - bssid - ID of Basic Service Set for or the P2pDevice address of the GO for - which a connection attempt was made. - ssid - Service Set Id. - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress bssid; - CsrWifiSsid ssid; -} CsrWifiNmeProfileIdentity; - -/******************************************************************************* - - NAME - CsrWifiNmeWep128Keys - - DESCRIPTION - Structure holding WEP Authentication Type and WEP keys that can be used - when using WEP128. - - MEMBERS - wepAuthType - Mask to select the WEP authentication type (Open or Shared) - selectedWepKey - Index to one of the four keys below indicating the - currently used WEP key. - key1 - Value for key number 1. - key2 - Value for key number 2. - key3 - Value for key number 3. - key4 - Value for key number 4. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeAuthModeMask wepAuthType; - u8 selectedWepKey; - u8 key1[13]; - u8 key2[13]; - u8 key3[13]; - u8 key4[13]; -} CsrWifiNmeWep128Keys; - -/******************************************************************************* - - NAME - CsrWifiNmeWep64Keys - - DESCRIPTION - Structure for holding WEP Authentication Type and WEP keys that can be - used when using WEP64. - - MEMBERS - wepAuthType - Mask to select the WEP authentication type (Open or Shared) - selectedWepKey - Index to one of the four keys below indicating the - currently used WEP key. - key1 - Value for key number 1. - key2 - Value for key number 2. - key3 - Value for key number 3. - key4 - Value for key number 4. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeAuthModeMask wepAuthType; - u8 selectedWepKey; - u8 key1[5]; - u8 key2[5]; - u8 key3[5]; - u8 key4[5]; -} CsrWifiNmeWep64Keys; - -/******************************************************************************* - - NAME - CsrWifiNmeCredentials - - DESCRIPTION - Structure containing the Credentials data. - - MEMBERS - credentialType - Credential type value (as defined in the - enumeration type). - credential - Union containing credentials which depends on - credentialType parameter. - credentialeap - - credentialwapiPassphrase - - credentialwpa2Passphrase - - credentialwpa2Psk - - credentialwapiPsk - - credentialwpaPassphrase - - credentialwapi - - credentialwep128Key - - credentialwpaPsk - - credentialopenSystem - - credentialwep64Key - - -*******************************************************************************/ -typedef struct -{ - CsrWifiNmeCredentialType credentialType; - union { - CsrWifiNmeEapCredentials eap; - CsrWifiNmePassphrase wapiPassphrase; - CsrWifiNmePassphrase wpa2Passphrase; - CsrWifiNmePsk wpa2Psk; - CsrWifiNmePsk wapiPsk; - CsrWifiNmePassphrase wpaPassphrase; - CsrWifiNmeWapiCredentials wapi; - CsrWifiNmeWep128Keys wep128Key; - CsrWifiNmePsk wpaPsk; - CsrWifiNmeEmpty openSystem; - CsrWifiNmeWep64Keys wep64Key; - } credential; -} CsrWifiNmeCredentials; - -/******************************************************************************* - - NAME - CsrWifiNmeProfile - - DESCRIPTION - Structure containing the Profile data. - - MEMBERS - profileIdentity - Profile Identity. - wmmQosInfoMask - Mask for WMM QoS information. - bssType - Type of BSS (Infrastructure or Adhoc). - channelNo - Channel Number. - ccxOptionsMask - Options mask for Cisco Compatible Extentions. - cloakedSsid - Flag to decide whether the SSID is cloaked (not - transmitted) or not. - credentials - Credentials data. - -*******************************************************************************/ -typedef struct -{ - CsrWifiNmeProfileIdentity profileIdentity; - CsrWifiNmeWmmQosInfoMask wmmQosInfoMask; - CsrWifiNmeBssType bssType; - u8 channelNo; - u8 ccxOptionsMask; - u8 cloakedSsid; - CsrWifiNmeCredentials credentials; -} CsrWifiNmeProfile; - - -/* Downstream */ -#define CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_NME_PROFILE_SET_REQ ((CsrWifiNmePrim) (0x0000 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_DELETE_REQ ((CsrWifiNmePrim) (0x0001 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ ((CsrWifiNmePrim) (0x0002 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_ORDER_SET_REQ ((CsrWifiNmePrim) (0x0003 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_CONNECT_REQ ((CsrWifiNmePrim) (0x0004 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_REQ ((CsrWifiNmePrim) (0x0005 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_CANCEL_REQ ((CsrWifiNmePrim) (0x0006 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_CONNECTION_STATUS_GET_REQ ((CsrWifiNmePrim) (0x0007 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_IMSI_GET_RES ((CsrWifiNmePrim) (0x0008 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_GSM_AUTH_RES ((CsrWifiNmePrim) (0x0009 + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_UMTS_AUTH_RES ((CsrWifiNmePrim) (0x000A + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_CONFIG_SET_REQ ((CsrWifiNmePrim) (0x000B + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_NME_EVENT_MASK_SET_REQ ((CsrWifiNmePrim) (0x000C + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_NME_PRIM_DOWNSTREAM_HIGHEST (0x000C + CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_NME_PROFILE_SET_CFM ((CsrWifiNmePrim)(0x0000 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_DELETE_CFM ((CsrWifiNmePrim)(0x0001 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_DELETE_ALL_CFM ((CsrWifiNmePrim)(0x0002 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_ORDER_SET_CFM ((CsrWifiNmePrim)(0x0003 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_CONNECT_CFM ((CsrWifiNmePrim)(0x0004 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_CFM ((CsrWifiNmePrim)(0x0005 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_CANCEL_CFM ((CsrWifiNmePrim)(0x0006 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_CONNECTION_STATUS_GET_CFM ((CsrWifiNmePrim)(0x0007 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_UPDATE_IND ((CsrWifiNmePrim)(0x0008 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_PROFILE_DISCONNECT_IND ((CsrWifiNmePrim)(0x0009 + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_IMSI_GET_IND ((CsrWifiNmePrim)(0x000A + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_GSM_AUTH_IND ((CsrWifiNmePrim)(0x000B + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_SIM_UMTS_AUTH_IND ((CsrWifiNmePrim)(0x000C + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_WPS_CONFIG_SET_CFM ((CsrWifiNmePrim)(0x000D + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_NME_EVENT_MASK_SET_CFM ((CsrWifiNmePrim)(0x000E + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_NME_PRIM_UPSTREAM_HIGHEST (0x000E + CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_NME_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_NME_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_NME_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_NME_PRIM_UPSTREAM_COUNT (CSR_WIFI_NME_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_NME_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiNmeProfileSetReq - - DESCRIPTION - Creates or updates an existing profile in the NME that matches the unique - identity of the profile. Each profile is identified by the combination of - BSSID and SSID. The profile contains all the required credentials for - attempting to connect to the network. Creating or updating a profile via - the NME PROFILE SET REQ does NOT add the profile to the preferred profile - list within the NME used for the NME auto-connect behaviour. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - profile - Specifies the identity and credentials of the network. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiNmeProfile profile; -} CsrWifiNmeProfileSetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteReq - - DESCRIPTION - Will delete the profile with a matching identity, but does NOT modify the - preferred profile list. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - profileIdentity - Identity (BSSID, SSID) of profile to be deleted. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiNmeProfileIdentity profileIdentity; -} CsrWifiNmeProfileDeleteReq; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteAllReq - - DESCRIPTION - Deletes all profiles present in the NME, but does NOT modify the - preferred profile list. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiNmeProfileDeleteAllReq; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileOrderSetReq - - DESCRIPTION - Defines the preferred order that profiles present in the NME should be - used during the NME auto-connect behaviour. - If profileIdentitysCount == 0, it removes any existing preferred profile - list already present in the NME, effectively disabling the auto-connect - behaviour. - NOTE: Profile identities that do not match any profile stored in the NME - are ignored during the auto-connect procedure. - NOTE: during auto-connect the NME will only attempt to join an existing - adhoc network and it will never attempt to host an adhoc network; for - hosting and adhoc network, use CSR_WIFI_NME_PROFILE_CONNECT_REQ - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an - interface - profileIdentitysCount - The number of profiles identities in the list. - profileIdentitys - Points to the list of profile identities. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 profileIdentitysCount; - CsrWifiNmeProfileIdentity *profileIdentitys; -} CsrWifiNmeProfileOrderSetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileConnectReq - - DESCRIPTION - Requests the NME to attempt to connect to the specified profile. - Overrides any current connection attempt. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - profileIdentity - Identity (BSSID, SSID) of profile to be connected to. - It must match an existing profile in the NME. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiNmeProfileIdentity profileIdentity; -} CsrWifiNmeProfileConnectReq; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsReq - - DESCRIPTION - Requests the NME to look for WPS enabled APs and attempt to perform WPS - to determine the appropriate security credentials to connect to the AP. - If the PIN == '00000000' then 'push button mode' is indicated, otherwise - the PIN has to match that of the AP. 4 digit pin is passed by sending the - pin digits in pin[0]..pin[3] and rest of the contents filled with '-'. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - pin - PIN value. - ssid - Service Set identifier - bssid - ID of Basic Service Set for which a WPS connection attempt is - being made. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 pin[8]; - CsrWifiSsid ssid; - CsrWifiMacAddress bssid; -} CsrWifiNmeWpsReq; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCancelReq - - DESCRIPTION - Requests the NME to cancel any WPS procedure that it is currently - performing. This includes WPS registrar activities started because of - CSR_WIFI_NME_AP_REGISTER.request - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiNmeWpsCancelReq; - -/******************************************************************************* - - NAME - CsrWifiNmeConnectionStatusGetReq - - DESCRIPTION - Requests the current connection status of the NME. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiNmeConnectionStatusGetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeSimImsiGetRes - - DESCRIPTION - Response from the application that received the NME SIM IMSI GET IND. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the outcome of the requested operation: STATUS_SUCCESS - or STATUS_ERROR. - imsi - The value of the IMSI obtained from the UICC. - cardType - The UICC type (GSM only (SIM), UMTS only (USIM), Both). - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - char *imsi; - CsrWifiNmeSimCardType cardType; -} CsrWifiNmeSimImsiGetRes; - -/******************************************************************************* - - NAME - CsrWifiNmeSimGsmAuthRes - - DESCRIPTION - Response from the application that received the NME SIM GSM AUTH IND. For - each GSM authentication round a GSM Ciphering key (Kc) and a signed - response (SRES) are produced. Since 2 or 3 GSM authentication rounds are - used the 2 or 3 Kc's obtained respectively are combined into one buffer - and similarly the 2 or 3 SRES's obtained are combined into another - buffer. The order of Kc values (SRES values respectively) in their buffer - is the same as that of their corresponding RAND values in the incoming - indication. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the outcome of the requested operation: - STATUS_SUCCESS or STATUS_ERROR - kcsLength - Length in Bytes of Kc buffer. Legal values are: 16 or 24. - kcs - Kc buffer holding 2 or 3 Kc values. - sresLength - Length in Bytes of SRES buffer. Legal values are: 8 or 12. - sres - SRES buffer holding 2 or 3 SRES values. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u8 kcsLength; - u8 *kcs; - u8 sresLength; - u8 *sres; -} CsrWifiNmeSimGsmAuthRes; - -/******************************************************************************* - - NAME - CsrWifiNmeSimUmtsAuthRes - - DESCRIPTION - Response from the application that received the NME SIM UMTS AUTH IND. - The values of umtsCipherKey, umtsIntegrityKey, resParameterLength and - resParameter are only meanigful when result = UMTS_AUTH_RESULT_SUCCESS. - The value of auts is only meaningful when - result=UMTS_AUTH_RESULT_SYNC_FAIL. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the outcome of the requested operation: - STATUS_SUCCESS or STATUS_ERROR. - result - The result of UMTS authentication as performed by the - UICC which could be: Success, Authentication Reject or - Synchronisation Failure. For all these 3 outcomes the - value of status is success. - umtsCipherKey - The UMTS Cipher Key as calculated and returned by the - UICC. - umtsIntegrityKey - The UMTS Integrity Key as calculated and returned by - the UICC. - resParameterLength - The length (in bytes) of the RES parameter (min=4; max - = 16). - resParameter - The RES parameter as calculated and returned by the - UICC. - auts - The AUTS parameter as calculated and returned by the - UICC. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiNmeUmtsAuthResult result; - u8 umtsCipherKey[16]; - u8 umtsIntegrityKey[16]; - u8 resParameterLength; - u8 *resParameter; - u8 auts[14]; -} CsrWifiNmeSimUmtsAuthRes; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsConfigSetReq - - DESCRIPTION - This primitive passes the WPS information for the device to NME. This may - be accepted only if no interface is active. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - wpsConfig - WPS config. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeWpsConfig wpsConfig; -} CsrWifiNmeWpsConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeEventMaskSetReq - - DESCRIPTION - The wireless manager application may register with the NME to receive - notification of interesting events. Indications will be sent only if the - wireless manager explicitly registers to be notified of that event. - indMask is a bit mask of values defined in CsrWifiNmeIndicationsMask. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - indMask - Set mask with values from CsrWifiNmeIndications - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiNmeIndicationsMask indMask; -} CsrWifiNmeEventMaskSetReq; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileSetCfm - - DESCRIPTION - Reports the status of the NME PROFILE SET REQ; the request will only fail - if the details specified in the profile contains an invalid combination - of parameters for example specifying the profile as cloaked but not - specifying the SSID. The NME doesn't limit the number of profiles that - may be created. The NME assumes that the entity configuring it is aware - of the appropriate limits. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the success or otherwise of the requested operation. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeProfileSetCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteCfm - - DESCRIPTION - Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_REQ. - Returns CSR_WIFI_NME_STATUS_NOT_FOUND if there is no matching profile. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the success or otherwise of the requested operation. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeProfileDeleteCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDeleteAllCfm - - DESCRIPTION - Reports the status of the CSR_WIFI_NME_PROFILE_DELETE_ALL_REQ. - Returns always CSR_WIFI_NME_STATUS_SUCCESS. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Indicates the success or otherwise of the requested operation, but - in this case it always set to success. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeProfileDeleteAllCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileOrderSetCfm - - DESCRIPTION - Confirmation to UNIFI_NME_PROFILE_ORDER_SET.request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiNmeProfileOrderSetCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileConnectCfm - - DESCRIPTION - Reports the status of the NME PROFILE CONNECT REQ. If unsuccessful the - connectAttempt parameters contain details of the APs that the NME - attempted to connect to before reporting the failure of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an - interface - status - Indicates the success or otherwise of the requested - operation. - connectAttemptsCount - This parameter is relevant only if - status!=CSR_WIFI_NME_STATUS_SUCCESS. - Number of connection attempt elements provided with - this primitive - connectAttempts - This parameter is relevant only if - status!=CSR_WIFI_NME_STATUS_SUCCESS. - Points to the list of connection attempt elements - provided with this primitive - Each element of the list provides information about - an AP on which the connection attempt was made and - the error that occurred during the attempt. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - u8 connectAttemptsCount; - CsrWifiNmeConnectAttempt *connectAttempts; -} CsrWifiNmeProfileConnectCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCfm - - DESCRIPTION - Reports the status of the NME WPS REQ. - If CSR_WIFI_NME_STATUS_SUCCESS, the profile parameter contains the - identity and credentials of the AP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - profile - This parameter is relevant only if - status==CSR_WIFI_NME_STATUS_SUCCESS. - The identity and credentials of the network. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiNmeProfile profile; -} CsrWifiNmeWpsCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsCancelCfm - - DESCRIPTION - Reports the status of the NME WPS REQ, the request is always SUCCESSFUL. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Only returns CSR_WIFI_NME_STATUS_SUCCESS - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiNmeWpsCancelCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeConnectionStatusGetCfm - - DESCRIPTION - Reports the connection status of the NME. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Indicates the success or otherwise of the requested - operation. - connectionStatus - NME current connection status - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiNmeConnectionStatus connectionStatus; -} CsrWifiNmeConnectionStatusGetCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileUpdateInd - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that informs that application that the contained profile has - changed. - For example, either the credentials EAP-FAST PAC file or the session data - within the profile has changed. - It is up to the application whether it stores this updated profile or - not. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - profile - The identity and credentials of the network. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiNmeProfile profile; -} CsrWifiNmeProfileUpdateInd; - -/******************************************************************************* - - NAME - CsrWifiNmeProfileDisconnectInd - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that informs that application that the current profile - connection has disconnected. The indication will contain information - about APs that it attempted to maintain the connection via i.e. in the - case of failed roaming. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an - interface - connectAttemptsCount - Number of connection attempt elements provided with - this primitive - connectAttempts - Points to the list of connection attempt elements - provided with this primitive - Each element of the list provides information about - an AP on which the connection attempt was made and - the error occurred during the attempt. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 connectAttemptsCount; - CsrWifiNmeConnectAttempt *connectAttempts; -} CsrWifiNmeProfileDisconnectInd; - -/******************************************************************************* - - NAME - CsrWifiNmeSimImsiGetInd - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the IMSI and UICC type from the UICC Manager. - This indication is generated when the NME is attempting to connect to a - profile configured for EAP-SIM/AKA. An application MUST register to - receive this indication for the NME to support the EAP-SIM/AKA credential - types. Otherwise the NME has no route to obtain the information from the - UICC. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiNmeSimImsiGetInd; - -/******************************************************************************* - - NAME - CsrWifiNmeSimGsmAuthInd - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the UICC Manager to perform a GSM - authentication on behalf of the NME. This indication is generated when - the NME is attempting to connect to a profile configured for EAP-SIM. An - application MUST register to receive this indication for the NME to - support the EAP-SIM credential types. Otherwise the NME has no route to - obtain the information from the UICC. EAP-SIM authentication requires 2 - or 3 GSM authentication rounds and therefore 2 or 3 RANDS (GSM Random - Challenges) are included. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - randsLength - GSM RAND is 16 bytes long hence valid values are 32 (2 RANDS) - or 48 (3 RANDs). - rands - 2 or 3 RANDs values. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u8 randsLength; - u8 *rands; -} CsrWifiNmeSimGsmAuthInd; - -/******************************************************************************* - - NAME - CsrWifiNmeSimUmtsAuthInd - - DESCRIPTION - Indication generated from the NME (if an application subscribes to - receive it) that requests the UICC Manager to perform a UMTS - authentication on behalf of the NME. This indication is generated when - the NME is attempting to connect to a profile configured for EAP-AKA. An - application MUST register to receive this indication for the NME to - support the EAP-AKA credential types. Otherwise the NME has no route to - obtain the information from the USIM. EAP-AKA requires one UMTS - authentication round and therefore only one RAND and one AUTN values are - included. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - rand - UMTS RAND value. - autn - UMTS AUTN value. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u8 rand[16]; - u8 autn[16]; -} CsrWifiNmeSimUmtsAuthInd; - -/******************************************************************************* - - NAME - CsrWifiNmeWpsConfigSetCfm - - DESCRIPTION - Confirm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeWpsConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiNmeEventMaskSetCfm - - DESCRIPTION - The NME calls the primitive to report the result of the request - primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiNmeEventMaskSetCfm; - -#endif /* CSR_WIFI_NME_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_nme_serialize.h b/drivers/staging/csr/csr_wifi_nme_serialize.h deleted file mode 100644 index ebac484419cf..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_serialize.h +++ /dev/null @@ -1,166 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_SERIALIZE_H__ -#define CSR_WIFI_NME_SERIALIZE_H__ - -#include "csr_wifi_msgconv.h" -#include "csr_wifi_nme_prim.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_serialize.h -#endif - -extern void CsrWifiNmePfree(void *ptr); - -extern u8* CsrWifiNmeProfileSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileSetReqSizeof(void *msg); -extern void CsrWifiNmeProfileSetReqSerFree(void *msg); - -extern u8* CsrWifiNmeProfileDeleteReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileDeleteReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileDeleteReqSizeof(void *msg); -#define CsrWifiNmeProfileDeleteReqSerFree CsrWifiNmePfree - -#define CsrWifiNmeProfileDeleteAllReqSer CsrWifiEventSer -#define CsrWifiNmeProfileDeleteAllReqDes CsrWifiEventDes -#define CsrWifiNmeProfileDeleteAllReqSizeof CsrWifiEventSizeof -#define CsrWifiNmeProfileDeleteAllReqSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeProfileOrderSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileOrderSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileOrderSetReqSizeof(void *msg); -extern void CsrWifiNmeProfileOrderSetReqSerFree(void *msg); - -extern u8* CsrWifiNmeProfileConnectReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileConnectReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileConnectReqSizeof(void *msg); -#define CsrWifiNmeProfileConnectReqSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeWpsReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeWpsReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeWpsReqSizeof(void *msg); -#define CsrWifiNmeWpsReqSerFree CsrWifiNmePfree - -#define CsrWifiNmeWpsCancelReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeWpsCancelReqDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeWpsCancelReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeWpsCancelReqSerFree CsrWifiNmePfree - -#define CsrWifiNmeConnectionStatusGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeConnectionStatusGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeConnectionStatusGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeConnectionStatusGetReqSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeSimImsiGetResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeSimImsiGetResDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeSimImsiGetResSizeof(void *msg); -extern void CsrWifiNmeSimImsiGetResSerFree(void *msg); - -extern u8* CsrWifiNmeSimGsmAuthResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeSimGsmAuthResDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeSimGsmAuthResSizeof(void *msg); -extern void CsrWifiNmeSimGsmAuthResSerFree(void *msg); - -extern u8* CsrWifiNmeSimUmtsAuthResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeSimUmtsAuthResDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeSimUmtsAuthResSizeof(void *msg); -extern void CsrWifiNmeSimUmtsAuthResSerFree(void *msg); - -extern u8* CsrWifiNmeWpsConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeWpsConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeWpsConfigSetReqSizeof(void *msg); -extern void CsrWifiNmeWpsConfigSetReqSerFree(void *msg); - -#define CsrWifiNmeEventMaskSetReqSer CsrWifiEventCsrUint32Ser -#define CsrWifiNmeEventMaskSetReqDes CsrWifiEventCsrUint32Des -#define CsrWifiNmeEventMaskSetReqSizeof CsrWifiEventCsrUint32Sizeof -#define CsrWifiNmeEventMaskSetReqSerFree CsrWifiNmePfree - -#define CsrWifiNmeProfileSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeProfileSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeProfileSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeProfileSetCfmSerFree CsrWifiNmePfree - -#define CsrWifiNmeProfileDeleteCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeProfileDeleteCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeProfileDeleteCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeProfileDeleteCfmSerFree CsrWifiNmePfree - -#define CsrWifiNmeProfileDeleteAllCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeProfileDeleteAllCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeProfileDeleteAllCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeProfileDeleteAllCfmSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeProfileOrderSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileOrderSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileOrderSetCfmSizeof(void *msg); -#define CsrWifiNmeProfileOrderSetCfmSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeProfileConnectCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileConnectCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileConnectCfmSizeof(void *msg); -extern void CsrWifiNmeProfileConnectCfmSerFree(void *msg); - -extern u8* CsrWifiNmeWpsCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeWpsCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeWpsCfmSizeof(void *msg); -extern void CsrWifiNmeWpsCfmSerFree(void *msg); - -extern u8* CsrWifiNmeWpsCancelCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeWpsCancelCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeWpsCancelCfmSizeof(void *msg); -#define CsrWifiNmeWpsCancelCfmSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeConnectionStatusGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeConnectionStatusGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeConnectionStatusGetCfmSizeof(void *msg); -#define CsrWifiNmeConnectionStatusGetCfmSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeProfileUpdateIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileUpdateIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileUpdateIndSizeof(void *msg); -extern void CsrWifiNmeProfileUpdateIndSerFree(void *msg); - -extern u8* CsrWifiNmeProfileDisconnectIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeProfileDisconnectIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeProfileDisconnectIndSizeof(void *msg); -extern void CsrWifiNmeProfileDisconnectIndSerFree(void *msg); - -#define CsrWifiNmeSimImsiGetIndSer CsrWifiEventSer -#define CsrWifiNmeSimImsiGetIndDes CsrWifiEventDes -#define CsrWifiNmeSimImsiGetIndSizeof CsrWifiEventSizeof -#define CsrWifiNmeSimImsiGetIndSerFree CsrWifiNmePfree - -extern u8* CsrWifiNmeSimGsmAuthIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeSimGsmAuthIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeSimGsmAuthIndSizeof(void *msg); -extern void CsrWifiNmeSimGsmAuthIndSerFree(void *msg); - -extern u8* CsrWifiNmeSimUmtsAuthIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiNmeSimUmtsAuthIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiNmeSimUmtsAuthIndSizeof(void *msg); -#define CsrWifiNmeSimUmtsAuthIndSerFree CsrWifiNmePfree - -#define CsrWifiNmeWpsConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeWpsConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeWpsConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeWpsConfigSetCfmSerFree CsrWifiNmePfree - -#define CsrWifiNmeEventMaskSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiNmeEventMaskSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiNmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiNmeEventMaskSetCfmSerFree CsrWifiNmePfree - -#endif /* CSR_WIFI_NME_SERIALIZE_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_nme_task.h b/drivers/staging/csr/csr_wifi_nme_task.h deleted file mode 100644 index 84e973a59bb2..000000000000 --- a/drivers/staging/csr/csr_wifi_nme_task.h +++ /dev/null @@ -1,27 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_NME_TASK_H__ -#define CSR_WIFI_NME_TASK_H__ - -#include -#include "csr_sched.h" - -#ifndef CSR_WIFI_NME_ENABLE -#error CSR_WIFI_NME_ENABLE MUST be defined inorder to use csr_wifi_nme_task.h -#endif - -#define CSR_WIFI_NME_LOG_ID 0x1203FFFF -extern CsrSchedQid CSR_WIFI_NME_IFACEQUEUE; - -#endif /* CSR_WIFI_NME_TASK_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_private_common.h b/drivers/staging/csr/csr_wifi_private_common.h deleted file mode 100644 index ee3bd51b934a..000000000000 --- a/drivers/staging/csr/csr_wifi_private_common.h +++ /dev/null @@ -1,81 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_PRIVATE_COMMON_H__ -#define CSR_WIFI_PRIVATE_COMMON_H__ - -/** - * @brief maximum number of STAs allowed to be connected - * - * @par Description - * min & max Beacon Interval - */ -#define CSR_WIFI_AP_MAX_ASSOC_STA 8 - -/** Number of only b rates */ -#define CSR_WIFI_SME_AP_MAX_ONLY_B_RATES 4 - - -/** Number of mandatory b rates */ -#define CSR_WIFI_SME_AP_MAX_MANDATORY_B_RATES 2 - - -/** Number of mandatory bg rates */ -#define CSR_WIFI_SME_AP_MAX_MANDATORY_BG_RATES 4 - - -/** Number of bg rates */ -#define CSR_WIFI_SME_AP_MAX_BG_RATES 12 - - -/** Number of no b only g rates */ -#define CSR_WIFI_SME_AP_MAX_NO_B_ONLY_G_RATES 8 - - -/** Number of mandatory g rates */ -#define CSR_WIFI_SME_AP_MAX_MANDATORY_G_RATES 7 - - -/* Number of g mandatory rates */ -#define CSR_WIFI_SME_AP_G_MANDATORY_RATES_NUM 7 - - -/* Number of b mandatory rates */ -#define CSR_WIFI_SME_AP_B_MANDATORY_RATES_NUM 2 - - -/* Number of b/g mandatory rates */ -#define CSR_WIFI_SME_AP_BG_MANDATORY_RATES_NUM 4 - - -/* The maximum allowed length of SSID */ -#define CSR_WIFI_SME_AP_SSID_MAX_LENGTH 32 - -/* Refer 8.4.2.27 RSN element - we support TKIP, WPA2, WAPI and PSK only, no pmkid, group cipher suite */ -#define CSR_WIFI_SME_RSN_PACKED_SIZE (1 + 1 + 2 + 4 + 2 + 4 * 2 + 2 + 4 * 1 + 2 + 24) - -/* Refer 7.3.2.9 (ISO/IEC 8802-11:2006) WAPI element - we support WAPI PSK only, no bkid, group cipher suite */ -#define CSR_WIFI_SME_WAPI_PACKED_SIZE (1 + 1 + 2 + 2 + 4 * 1 + 2 + 4 * 1 + 4 + 2 + 24) - - -/* Common structure for NME and SME to maintain Interface mode*/ -typedef u8 CsrWifiInterfaceMode; -#define CSR_WIFI_MODE_NONE ((CsrWifiInterfaceMode) 0xFF) -#define CSR_WIFI_MODE_STA ((CsrWifiInterfaceMode) 0x00) -#define CSR_WIFI_MODE_AP ((CsrWifiInterfaceMode) 0x01) -#define CSR_WIFI_MODE_P2P_DEVICE ((CsrWifiInterfaceMode) 0x02) -#define CSR_WIFI_MODE_P2P_CLI ((CsrWifiInterfaceMode) 0x03) -#define CSR_WIFI_MODE_P2P_GO ((CsrWifiInterfaceMode) 0x04) -#define CSR_WIFI_MODE_AMP ((CsrWifiInterfaceMode) 0x05) -#define CSR_WIFI_MODE_WPS_ENROLLEE ((CsrWifiInterfaceMode) 0x06) -#define CSR_WIFI_MODE_IBSS ((CsrWifiInterfaceMode) 0x07) - -#endif - diff --git a/drivers/staging/csr/csr_wifi_result.h b/drivers/staging/csr/csr_wifi_result.h deleted file mode 100644 index 3c394c7e5fa9..000000000000 --- a/drivers/staging/csr/csr_wifi_result.h +++ /dev/null @@ -1,27 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_RESULT_H__ -#define CSR_WIFI_RESULT_H__ - -#include "csr_result.h" - -/* THIS FILE SHOULD CONTAIN ONLY RESULT CODES */ - -/* Result Codes */ -#define CSR_WIFI_HIP_RESULT_INVALID_VALUE ((CsrResult) 1) /* Invalid argument value */ -#define CSR_WIFI_HIP_RESULT_NO_DEVICE ((CsrResult) 2) /* The specified device is no longer present */ -#define CSR_WIFI_HIP_RESULT_NO_SPACE ((CsrResult) 3) /* A queue or buffer is full */ -#define CSR_WIFI_HIP_RESULT_NO_MEMORY ((CsrResult) 4) /* Fatal error, no memory */ -#define CSR_WIFI_HIP_RESULT_RANGE ((CsrResult) 5) /* Request exceeds the range of a file or a buffer */ -#define CSR_WIFI_HIP_RESULT_NOT_FOUND ((CsrResult) 6) /* A file (typically a f/w patch) is not found */ - -#endif /* CSR_WIFI_RESULT_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.c b/drivers/staging/csr/csr_wifi_router_converter_init.c deleted file mode 100644 index 775c013d0514..000000000000 --- a/drivers/staging/csr/csr_wifi_router_converter_init.c +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_msgconv.h" -#include "csr_macro.h" - - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" -#endif - -#ifndef EXCLUDE_CSR_WIFI_ROUTER_MODULE -#include "csr_wifi_router_serialize.h" -#include "csr_wifi_router_prim.h" - -static CsrMsgConvMsgEntry csrwifirouter_conv_lut[] = { - { CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ, CsrWifiRouterMaPacketSubscribeReqSizeof, CsrWifiRouterMaPacketSubscribeReqSer, CsrWifiRouterMaPacketSubscribeReqDes, CsrWifiRouterMaPacketSubscribeReqSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ, CsrWifiRouterMaPacketUnsubscribeReqSizeof, CsrWifiRouterMaPacketUnsubscribeReqSer, CsrWifiRouterMaPacketUnsubscribeReqDes, CsrWifiRouterMaPacketUnsubscribeReqSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_REQ, CsrWifiRouterMaPacketReqSizeof, CsrWifiRouterMaPacketReqSer, CsrWifiRouterMaPacketReqDes, CsrWifiRouterMaPacketReqSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_RES, CsrWifiRouterMaPacketResSizeof, CsrWifiRouterMaPacketResSer, CsrWifiRouterMaPacketResDes, CsrWifiRouterMaPacketResSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ, CsrWifiRouterMaPacketCancelReqSizeof, CsrWifiRouterMaPacketCancelReqSer, CsrWifiRouterMaPacketCancelReqDes, CsrWifiRouterMaPacketCancelReqSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM, CsrWifiRouterMaPacketSubscribeCfmSizeof, CsrWifiRouterMaPacketSubscribeCfmSer, CsrWifiRouterMaPacketSubscribeCfmDes, CsrWifiRouterMaPacketSubscribeCfmSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM, CsrWifiRouterMaPacketUnsubscribeCfmSizeof, CsrWifiRouterMaPacketUnsubscribeCfmSer, CsrWifiRouterMaPacketUnsubscribeCfmDes, CsrWifiRouterMaPacketUnsubscribeCfmSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_CFM, CsrWifiRouterMaPacketCfmSizeof, CsrWifiRouterMaPacketCfmSer, CsrWifiRouterMaPacketCfmDes, CsrWifiRouterMaPacketCfmSerFree }, - { CSR_WIFI_ROUTER_MA_PACKET_IND, CsrWifiRouterMaPacketIndSizeof, CsrWifiRouterMaPacketIndSer, CsrWifiRouterMaPacketIndDes, CsrWifiRouterMaPacketIndSerFree }, - - { 0, NULL, NULL, NULL, NULL }, -}; - -CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, u16 msgType) -{ - if (msgType & CSR_PRIM_UPSTREAM) - { - u16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT; - if (idx < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) && - csrwifirouter_conv_lut[idx].msgType == msgType) - { - return &csrwifirouter_conv_lut[idx]; - } - } - else - { - if (msgType < CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT && - csrwifirouter_conv_lut[msgType].msgType == msgType) - { - return &csrwifirouter_conv_lut[msgType]; - } - } - return NULL; -} - - -void CsrWifiRouterConverterInit(void) -{ - CsrMsgConvInsert(CSR_WIFI_ROUTER_PRIM, csrwifirouter_conv_lut); - CsrMsgConvCustomLookupRegister(CSR_WIFI_ROUTER_PRIM, CsrWifiRouterConverterLookup); -} - - -#ifdef CSR_LOG_ENABLE -static const CsrLogPrimitiveInformation csrwifirouter_conv_info = { - CSR_WIFI_ROUTER_PRIM, - (char *)"CSR_WIFI_ROUTER_PRIM", - csrwifirouter_conv_lut -}; -const CsrLogPrimitiveInformation* CsrWifiRouterTechInfoGet(void) -{ - return &csrwifirouter_conv_info; -} - - -#endif /* CSR_LOG_ENABLE */ -#endif /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_router_converter_init.h b/drivers/staging/csr/csr_wifi_router_converter_init.h deleted file mode 100644 index 478327b75c18..000000000000 --- a/drivers/staging/csr/csr_wifi_router_converter_init.h +++ /dev/null @@ -1,34 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_CONVERTER_INIT_H__ -#define CSR_WIFI_ROUTER_CONVERTER_INIT_H__ - -#ifndef EXCLUDE_CSR_WIFI_ROUTER_MODULE - -#include "csr_msgconv.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" - -extern const CsrLogPrimitiveInformation* CsrWifiRouterTechInfoGet(void); -#endif /* CSR_LOG_ENABLE */ - -extern void CsrWifiRouterConverterInit(void); - -#else /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ - -#define CsrWifiRouterConverterInit() - -#endif /* EXCLUDE_CSR_WIFI_ROUTER_MODULE */ - -#endif /* CSR_WIFI_ROUTER_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c deleted file mode 100644 index a02e307e5a88..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c +++ /dev/null @@ -1,134 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_msgconv.h" -#include "csr_macro.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" -#endif - -#ifndef EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE -#include "csr_wifi_router_ctrl_serialize.h" -#include "csr_wifi_router_ctrl_prim.h" - -static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = { - { CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ, CsrWifiRouterCtrlConfigurePowerModeReqSizeof, CsrWifiRouterCtrlConfigurePowerModeReqSer, CsrWifiRouterCtrlConfigurePowerModeReqDes, CsrWifiRouterCtrlConfigurePowerModeReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_HIP_REQ, CsrWifiRouterCtrlHipReqSizeof, CsrWifiRouterCtrlHipReqSer, CsrWifiRouterCtrlHipReqDes, CsrWifiRouterCtrlHipReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ, CsrWifiRouterCtrlMediaStatusReqSizeof, CsrWifiRouterCtrlMediaStatusReqSer, CsrWifiRouterCtrlMediaStatusReqDes, CsrWifiRouterCtrlMediaStatusReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES, CsrWifiRouterCtrlMulticastAddressResSizeof, CsrWifiRouterCtrlMulticastAddressResSer, CsrWifiRouterCtrlMulticastAddressResDes, CsrWifiRouterCtrlMulticastAddressResSerFree }, - { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ, CsrWifiRouterCtrlPortConfigureReqSizeof, CsrWifiRouterCtrlPortConfigureReqSer, CsrWifiRouterCtrlPortConfigureReqDes, CsrWifiRouterCtrlPortConfigureReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ, CsrWifiRouterCtrlQosControlReqSizeof, CsrWifiRouterCtrlQosControlReqSer, CsrWifiRouterCtrlQosControlReqDes, CsrWifiRouterCtrlQosControlReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_SUSPEND_RES, CsrWifiRouterCtrlSuspendResSizeof, CsrWifiRouterCtrlSuspendResSer, CsrWifiRouterCtrlSuspendResDes, CsrWifiRouterCtrlSuspendResSerFree }, - { CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ, CsrWifiRouterCtrlTclasAddReqSizeof, CsrWifiRouterCtrlTclasAddReqSer, CsrWifiRouterCtrlTclasAddReqDes, CsrWifiRouterCtrlTclasAddReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_RESUME_RES, CsrWifiRouterCtrlResumeResSizeof, CsrWifiRouterCtrlResumeResSer, CsrWifiRouterCtrlResumeResDes, CsrWifiRouterCtrlResumeResSerFree }, - { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ, CsrWifiRouterCtrlRawSdioDeinitialiseReqSizeof, CsrWifiRouterCtrlRawSdioDeinitialiseReqSer, CsrWifiRouterCtrlRawSdioDeinitialiseReqDes, CsrWifiRouterCtrlRawSdioDeinitialiseReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ, CsrWifiRouterCtrlRawSdioInitialiseReqSizeof, CsrWifiRouterCtrlRawSdioInitialiseReqSer, CsrWifiRouterCtrlRawSdioInitialiseReqDes, CsrWifiRouterCtrlRawSdioInitialiseReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ, CsrWifiRouterCtrlTclasDelReqSizeof, CsrWifiRouterCtrlTclasDelReqSer, CsrWifiRouterCtrlTclasDelReqDes, CsrWifiRouterCtrlTclasDelReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ, CsrWifiRouterCtrlTrafficClassificationReqSizeof, CsrWifiRouterCtrlTrafficClassificationReqSer, CsrWifiRouterCtrlTrafficClassificationReqDes, CsrWifiRouterCtrlTrafficClassificationReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ, CsrWifiRouterCtrlTrafficConfigReqSizeof, CsrWifiRouterCtrlTrafficConfigReqSer, CsrWifiRouterCtrlTrafficConfigReqDes, CsrWifiRouterCtrlTrafficConfigReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ, CsrWifiRouterCtrlWifiOffReqSizeof, CsrWifiRouterCtrlWifiOffReqSer, CsrWifiRouterCtrlWifiOffReqDes, CsrWifiRouterCtrlWifiOffReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES, CsrWifiRouterCtrlWifiOffResSizeof, CsrWifiRouterCtrlWifiOffResSer, CsrWifiRouterCtrlWifiOffResDes, CsrWifiRouterCtrlWifiOffResSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, CsrWifiRouterCtrlWifiOnReqSizeof, CsrWifiRouterCtrlWifiOnReqSer, CsrWifiRouterCtrlWifiOnReqDes, CsrWifiRouterCtrlWifiOnReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES, CsrWifiRouterCtrlWifiOnResSizeof, CsrWifiRouterCtrlWifiOnResSer, CsrWifiRouterCtrlWifiOnResDes, CsrWifiRouterCtrlWifiOnResSerFree }, - { CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ, CsrWifiRouterCtrlM4TransmitReqSizeof, CsrWifiRouterCtrlM4TransmitReqSer, CsrWifiRouterCtrlM4TransmitReqDes, CsrWifiRouterCtrlM4TransmitReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ, CsrWifiRouterCtrlModeSetReqSizeof, CsrWifiRouterCtrlModeSetReqSer, CsrWifiRouterCtrlModeSetReqDes, CsrWifiRouterCtrlModeSetReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ, CsrWifiRouterCtrlPeerAddReqSizeof, CsrWifiRouterCtrlPeerAddReqSer, CsrWifiRouterCtrlPeerAddReqDes, CsrWifiRouterCtrlPeerAddReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ, CsrWifiRouterCtrlPeerDelReqSizeof, CsrWifiRouterCtrlPeerDelReqSer, CsrWifiRouterCtrlPeerDelReqDes, CsrWifiRouterCtrlPeerDelReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ, CsrWifiRouterCtrlPeerUpdateReqSizeof, CsrWifiRouterCtrlPeerUpdateReqSer, CsrWifiRouterCtrlPeerUpdateReqDes, CsrWifiRouterCtrlPeerUpdateReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, CsrWifiRouterCtrlBlockAckDisableReqSizeof, CsrWifiRouterCtrlBlockAckDisableReqSer, CsrWifiRouterCtrlBlockAckDisableReqDes, CsrWifiRouterCtrlBlockAckDisableReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, CsrWifiRouterCtrlWapiRxPktReqSizeof, CsrWifiRouterCtrlWapiRxPktReqSer, CsrWifiRouterCtrlWapiRxPktReqDes, CsrWifiRouterCtrlWapiRxPktReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, CsrWifiRouterCtrlWapiMulticastFilterReqSizeof, CsrWifiRouterCtrlWapiMulticastFilterReqSer, CsrWifiRouterCtrlWapiMulticastFilterReqDes, CsrWifiRouterCtrlWapiMulticastFilterReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, CsrWifiRouterCtrlWapiUnicastFilterReqSizeof, CsrWifiRouterCtrlWapiUnicastFilterReqSer, CsrWifiRouterCtrlWapiUnicastFilterReqDes, CsrWifiRouterCtrlWapiUnicastFilterReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof, CsrWifiRouterCtrlWapiUnicastTxPktReqSer, CsrWifiRouterCtrlWapiUnicastTxPktReqDes, CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, CsrWifiRouterCtrlWapiFilterReqSizeof, CsrWifiRouterCtrlWapiFilterReqSer, CsrWifiRouterCtrlWapiFilterReqDes, CsrWifiRouterCtrlWapiFilterReqSerFree }, - { CSR_WIFI_ROUTER_CTRL_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_RESUME_IND, CsrWifiRouterCtrlResumeIndSizeof, CsrWifiRouterCtrlResumeIndSer, CsrWifiRouterCtrlResumeIndDes, CsrWifiRouterCtrlResumeIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_SUSPEND_IND, CsrWifiRouterCtrlSuspendIndSizeof, CsrWifiRouterCtrlSuspendIndSer, CsrWifiRouterCtrlSuspendIndDes, CsrWifiRouterCtrlSuspendIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM, CsrWifiRouterCtrlTclasAddCfmSizeof, CsrWifiRouterCtrlTclasAddCfmSer, CsrWifiRouterCtrlTclasAddCfmDes, CsrWifiRouterCtrlTclasAddCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer, CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes, CsrWifiRouterCtrlRawSdioDeinitialiseCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM, CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof, CsrWifiRouterCtrlRawSdioInitialiseCfmSer, CsrWifiRouterCtrlRawSdioInitialiseCfmDes, CsrWifiRouterCtrlRawSdioInitialiseCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM, CsrWifiRouterCtrlTclasDelCfmSizeof, CsrWifiRouterCtrlTclasDelCfmSer, CsrWifiRouterCtrlTclasDelCfmDes, CsrWifiRouterCtrlTclasDelCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND, CsrWifiRouterCtrlTrafficProtocolIndSizeof, CsrWifiRouterCtrlTrafficProtocolIndSer, CsrWifiRouterCtrlTrafficProtocolIndDes, CsrWifiRouterCtrlTrafficProtocolIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND, CsrWifiRouterCtrlTrafficSampleIndSizeof, CsrWifiRouterCtrlTrafficSampleIndSer, CsrWifiRouterCtrlTrafficSampleIndDes, CsrWifiRouterCtrlTrafficSampleIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND, CsrWifiRouterCtrlWifiOffIndSizeof, CsrWifiRouterCtrlWifiOffIndSer, CsrWifiRouterCtrlWifiOffIndDes, CsrWifiRouterCtrlWifiOffIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM, CsrWifiRouterCtrlWifiOffCfmSizeof, CsrWifiRouterCtrlWifiOffCfmSer, CsrWifiRouterCtrlWifiOffCfmDes, CsrWifiRouterCtrlWifiOffCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND, CsrWifiRouterCtrlWifiOnIndSizeof, CsrWifiRouterCtrlWifiOnIndSer, CsrWifiRouterCtrlWifiOnIndDes, CsrWifiRouterCtrlWifiOnIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM, CsrWifiRouterCtrlWifiOnCfmSizeof, CsrWifiRouterCtrlWifiOnCfmSer, CsrWifiRouterCtrlWifiOnCfmDes, CsrWifiRouterCtrlWifiOnCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND, CsrWifiRouterCtrlM4ReadyToSendIndSizeof, CsrWifiRouterCtrlM4ReadyToSendIndSer, CsrWifiRouterCtrlM4ReadyToSendIndDes, CsrWifiRouterCtrlM4ReadyToSendIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND, CsrWifiRouterCtrlM4TransmittedIndSizeof, CsrWifiRouterCtrlM4TransmittedIndSer, CsrWifiRouterCtrlM4TransmittedIndDes, CsrWifiRouterCtrlM4TransmittedIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND, CsrWifiRouterCtrlMicFailureIndSizeof, CsrWifiRouterCtrlMicFailureIndSer, CsrWifiRouterCtrlMicFailureIndDes, CsrWifiRouterCtrlMicFailureIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_CONNECTED_IND, CsrWifiRouterCtrlConnectedIndSizeof, CsrWifiRouterCtrlConnectedIndSer, CsrWifiRouterCtrlConnectedIndDes, CsrWifiRouterCtrlConnectedIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM, CsrWifiRouterCtrlPeerAddCfmSizeof, CsrWifiRouterCtrlPeerAddCfmSer, CsrWifiRouterCtrlPeerAddCfmDes, CsrWifiRouterCtrlPeerAddCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM, CsrWifiRouterCtrlPeerDelCfmSizeof, CsrWifiRouterCtrlPeerDelCfmSer, CsrWifiRouterCtrlPeerDelCfmDes, CsrWifiRouterCtrlPeerDelCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND, CsrWifiRouterCtrlUnexpectedFrameIndSizeof, CsrWifiRouterCtrlUnexpectedFrameIndSer, CsrWifiRouterCtrlUnexpectedFrameIndDes, CsrWifiRouterCtrlUnexpectedFrameIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM, CsrWifiRouterCtrlPeerUpdateCfmSizeof, CsrWifiRouterCtrlPeerUpdateCfmSer, CsrWifiRouterCtrlPeerUpdateCfmDes, CsrWifiRouterCtrlPeerUpdateCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM, CsrWifiRouterCtrlCapabilitiesCfmSizeof, CsrWifiRouterCtrlCapabilitiesCfmSer, CsrWifiRouterCtrlCapabilitiesCfmDes, CsrWifiRouterCtrlCapabilitiesCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM, CsrWifiRouterCtrlBlockAckEnableCfmSizeof, CsrWifiRouterCtrlBlockAckEnableCfmSer, CsrWifiRouterCtrlBlockAckEnableCfmDes, CsrWifiRouterCtrlBlockAckEnableCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, CsrWifiRouterCtrlStaInactiveIndSizeof, CsrWifiRouterCtrlStaInactiveIndSer, CsrWifiRouterCtrlStaInactiveIndDes, CsrWifiRouterCtrlStaInactiveIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, CsrWifiRouterCtrlWapiRxMicCheckIndSizeof, CsrWifiRouterCtrlWapiRxMicCheckIndSer, CsrWifiRouterCtrlWapiRxMicCheckIndDes, CsrWifiRouterCtrlWapiRxMicCheckIndSerFree }, - { CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, CsrWifiRouterCtrlModeSetCfmSizeof, CsrWifiRouterCtrlModeSetCfmSer, CsrWifiRouterCtrlModeSetCfmDes, CsrWifiRouterCtrlModeSetCfmSerFree }, - { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer, CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree }, - - { 0, NULL, NULL, NULL, NULL }, -}; - -CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, u16 msgType) -{ - if (msgType & CSR_PRIM_UPSTREAM) - { - u16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT; - if (idx < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) && - csrwifirouterctrl_conv_lut[idx].msgType == msgType) - { - return &csrwifirouterctrl_conv_lut[idx]; - } - } - else - { - if (msgType < CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT && - csrwifirouterctrl_conv_lut[msgType].msgType == msgType) - { - return &csrwifirouterctrl_conv_lut[msgType]; - } - } - return NULL; -} - - -void CsrWifiRouterCtrlConverterInit(void) -{ - CsrMsgConvInsert(CSR_WIFI_ROUTER_CTRL_PRIM, csrwifirouterctrl_conv_lut); - CsrMsgConvCustomLookupRegister(CSR_WIFI_ROUTER_CTRL_PRIM, CsrWifiRouterCtrlConverterLookup); -} - - -#ifdef CSR_LOG_ENABLE -static const CsrLogPrimitiveInformation csrwifirouterctrl_conv_info = { - CSR_WIFI_ROUTER_CTRL_PRIM, - (char *)"CSR_WIFI_ROUTER_CTRL_PRIM", - csrwifirouterctrl_conv_lut -}; -const CsrLogPrimitiveInformation* CsrWifiRouterCtrlTechInfoGet(void) -{ - return &csrwifirouterctrl_conv_info; -} - - -#endif /* CSR_LOG_ENABLE */ -#endif /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h b/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h deleted file mode 100644 index c98458912825..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_converter_init.h +++ /dev/null @@ -1,34 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ -#define CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ - -#ifndef EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE - -#include "csr_msgconv.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" - -extern const CsrLogPrimitiveInformation* CsrWifiRouterCtrlTechInfoGet(void); -#endif /* CSR_LOG_ENABLE */ - -extern void CsrWifiRouterCtrlConverterInit(void); - -#else /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ - -#define CsrWifiRouterCtrlConverterInit() - -#endif /* EXCLUDE_CSR_WIFI_ROUTER_CTRL_MODULE */ - -#endif /* CSR_WIFI_ROUTER_CTRL_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c deleted file mode 100644 index 7fa85fb4d6c0..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c +++ /dev/null @@ -1,108 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_router_ctrl_prim.h" -#include "csr_wifi_router_ctrl_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiRouterCtrlFreeDownstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_ROUTER_CTRL_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiRouterCtrlFreeDownstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_ROUTER_CTRL_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiRouterCtrlPrim *) message)) - { - case CSR_WIFI_ROUTER_CTRL_HIP_REQ: - { - CsrWifiRouterCtrlHipReq *p = (CsrWifiRouterCtrlHipReq *)message; - kfree(p->mlmeCommand); - p->mlmeCommand = NULL; - kfree(p->dataRef1); - p->dataRef1 = NULL; - kfree(p->dataRef2); - p->dataRef2 = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES: - { - CsrWifiRouterCtrlMulticastAddressRes *p = (CsrWifiRouterCtrlMulticastAddressRes *)message; - kfree(p->getAddresses); - p->getAddresses = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ: - { - CsrWifiRouterCtrlTclasAddReq *p = (CsrWifiRouterCtrlTclasAddReq *)message; - kfree(p->tclas); - p->tclas = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ: - { - CsrWifiRouterCtrlTclasDelReq *p = (CsrWifiRouterCtrlTclasDelReq *)message; - kfree(p->tclas); - p->tclas = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ: - { - CsrWifiRouterCtrlWifiOnReq *p = (CsrWifiRouterCtrlWifiOnReq *)message; - kfree(p->data); - p->data = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES: - { - CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message; - kfree(p->smeVersions.smeBuild); - p->smeVersions.smeBuild = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ: - { - CsrWifiRouterCtrlWapiRxPktReq *p = (CsrWifiRouterCtrlWapiRxPktReq *)message; - kfree(p->signal); - p->signal = NULL; - kfree(p->data); - p->data = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ: - { - CsrWifiRouterCtrlWapiUnicastTxPktReq *p = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)message; - kfree(p->data); - p->data = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c deleted file mode 100644 index 954b3defc49c..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c +++ /dev/null @@ -1,87 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_router_ctrl_prim.h" -#include "csr_wifi_router_ctrl_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiRouterCtrlFreeUpstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_ROUTER_CTRL_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiRouterCtrlFreeUpstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_ROUTER_CTRL_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiRouterCtrlPrim *) message)) - { - case CSR_WIFI_ROUTER_CTRL_HIP_IND: - { - CsrWifiRouterCtrlHipInd *p = (CsrWifiRouterCtrlHipInd *)message; - kfree(p->mlmeCommand); - p->mlmeCommand = NULL; - kfree(p->dataRef1); - p->dataRef1 = NULL; - kfree(p->dataRef2); - p->dataRef2 = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND: - { - CsrWifiRouterCtrlMulticastAddressInd *p = (CsrWifiRouterCtrlMulticastAddressInd *)message; - kfree(p->setAddresses); - p->setAddresses = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND: - { - CsrWifiRouterCtrlWifiOnInd *p = (CsrWifiRouterCtrlWifiOnInd *)message; - kfree(p->versions.routerBuild); - p->versions.routerBuild = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND: - { - CsrWifiRouterCtrlWapiRxMicCheckInd *p = (CsrWifiRouterCtrlWapiRxMicCheckInd *)message; - kfree(p->signal); - p->signal = NULL; - kfree(p->data); - p->data = NULL; - break; - } - case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND: - { - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *p = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)message; - kfree(p->data); - p->data = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h b/drivers/staging/csr/csr_wifi_router_ctrl_lib.h deleted file mode 100644 index f235153c42af..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_lib.h +++ /dev/null @@ -1,2082 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_CTRL_LIB_H__ -#define CSR_WIFI_ROUTER_CTRL_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_router_ctrl_prim.h" -#include "csr_wifi_router_task.h" - -/*----------------------------------------------------------------------------* - * CsrWifiRouterCtrlFreeUpstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_ROUTER_CTRL upstream message. Does not - * free the message itself, and can only be used for upstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_ROUTER_CTRL upstream message - *----------------------------------------------------------------------------*/ -void CsrWifiRouterCtrlFreeUpstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * CsrWifiRouterCtrlFreeDownstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_ROUTER_CTRL downstream message. Does not - * free the message itself, and can only be used for downstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_ROUTER_CTRL downstream message - *----------------------------------------------------------------------------*/ -void CsrWifiRouterCtrlFreeDownstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * Enum to string functions - *----------------------------------------------------------------------------*/ -const char* CsrWifiRouterCtrlBlockAckRoleToString(CsrWifiRouterCtrlBlockAckRole value); -const char* CsrWifiRouterCtrlControlIndicationToString(CsrWifiRouterCtrlControlIndication value); -const char* CsrWifiRouterCtrlListActionToString(CsrWifiRouterCtrlListAction value); -const char* CsrWifiRouterCtrlLowPowerModeToString(CsrWifiRouterCtrlLowPowerMode value); -const char* CsrWifiRouterCtrlMediaStatusToString(CsrWifiRouterCtrlMediaStatus value); -const char* CsrWifiRouterCtrlModeToString(CsrWifiRouterCtrlMode value); -const char* CsrWifiRouterCtrlPeerStatusToString(CsrWifiRouterCtrlPeerStatus value); -const char* CsrWifiRouterCtrlPortActionToString(CsrWifiRouterCtrlPortAction value); -const char* CsrWifiRouterCtrlPowersaveTypeToString(CsrWifiRouterCtrlPowersaveType value); -const char* CsrWifiRouterCtrlProtocolDirectionToString(CsrWifiRouterCtrlProtocolDirection value); -const char* CsrWifiRouterCtrlQoSControlToString(CsrWifiRouterCtrlQoSControl value); -const char* CsrWifiRouterCtrlQueueConfigToString(CsrWifiRouterCtrlQueueConfig value); -const char* CsrWifiRouterCtrlTrafficConfigTypeToString(CsrWifiRouterCtrlTrafficConfigType value); -const char* CsrWifiRouterCtrlTrafficPacketTypeToString(CsrWifiRouterCtrlTrafficPacketType value); -const char* CsrWifiRouterCtrlTrafficTypeToString(CsrWifiRouterCtrlTrafficType value); - - -/*----------------------------------------------------------------------------* - * CsrPrim Type toString function. - * Converts a message type to the String name of the Message - *----------------------------------------------------------------------------*/ -const char* CsrWifiRouterCtrlPrimTypeToString(CsrPrim msgType); - -/*----------------------------------------------------------------------------* - * Lookup arrays for PrimType name Strings - *----------------------------------------------------------------------------*/ -extern const char *CsrWifiRouterCtrlUpstreamPrimNames[CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT]; -extern const char *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT]; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckDisableReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - macAddress - - trafficStreamID - - role - - -*******************************************************************************/ -#define CsrWifiRouterCtrlBlockAckDisableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckDisableReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->macAddress = (macAddress__); \ - msg__->trafficStreamID = (trafficStreamID__); \ - msg__->role = (role__); - -#define CsrWifiRouterCtrlBlockAckDisableReqSendTo(dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ - { \ - CsrWifiRouterCtrlBlockAckDisableReq *msg__; \ - CsrWifiRouterCtrlBlockAckDisableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlBlockAckDisableReqSend(src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) \ - CsrWifiRouterCtrlBlockAckDisableReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckDisableCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlBlockAckDisableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckDisableCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlBlockAckDisableCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlBlockAckDisableCfm *msg__; \ - CsrWifiRouterCtrlBlockAckDisableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlBlockAckDisableCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlBlockAckDisableCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckEnableReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - macAddress - - trafficStreamID - - role - - bufferSize - - timeout - - ssn - - -*******************************************************************************/ -#define CsrWifiRouterCtrlBlockAckEnableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckEnableReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->macAddress = (macAddress__); \ - msg__->trafficStreamID = (trafficStreamID__); \ - msg__->role = (role__); \ - msg__->bufferSize = (bufferSize__); \ - msg__->timeout = (timeout__); \ - msg__->ssn = (ssn__); - -#define CsrWifiRouterCtrlBlockAckEnableReqSendTo(dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ - { \ - CsrWifiRouterCtrlBlockAckEnableReq *msg__; \ - CsrWifiRouterCtrlBlockAckEnableReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlBlockAckEnableReqSend(src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) \ - CsrWifiRouterCtrlBlockAckEnableReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, macAddress__, trafficStreamID__, role__, bufferSize__, timeout__, ssn__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckEnableCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlBlockAckEnableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckEnableCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlBlockAckEnableCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlBlockAckEnableCfm *msg__; \ - CsrWifiRouterCtrlBlockAckEnableCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlBlockAckEnableCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlBlockAckEnableCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckErrorIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - trafficStreamID - - peerMacAddress - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlBlockAckErrorIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckErrorInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->trafficStreamID = (trafficStreamID__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlBlockAckErrorIndSendTo(dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ - { \ - CsrWifiRouterCtrlBlockAckErrorInd *msg__; \ - CsrWifiRouterCtrlBlockAckErrorIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlBlockAckErrorIndSend(dst__, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) \ - CsrWifiRouterCtrlBlockAckErrorIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, trafficStreamID__, peerMacAddress__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlCapabilitiesReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlCapabilitiesReqCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlCapabilitiesReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlCapabilitiesReqSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlCapabilitiesReq *msg__; \ - CsrWifiRouterCtrlCapabilitiesReqCreate(msg__, dst__, src__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlCapabilitiesReqSend(src__, clientData__) \ - CsrWifiRouterCtrlCapabilitiesReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlCapabilitiesCfmSend - - DESCRIPTION - The router sends this primitive to confirm the size of the queues of the - HIP. - - PARAMETERS - queue - Destination Task Queue - clientData - - commandQueueSize - Size of command queue - trafficQueueSize - Size of traffic queue (per AC) - -*******************************************************************************/ -#define CsrWifiRouterCtrlCapabilitiesCfmCreate(msg__, dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlCapabilitiesCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->commandQueueSize = (commandQueueSize__); \ - msg__->trafficQueueSize = (trafficQueueSize__); - -#define CsrWifiRouterCtrlCapabilitiesCfmSendTo(dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__) \ - { \ - CsrWifiRouterCtrlCapabilitiesCfm *msg__; \ - CsrWifiRouterCtrlCapabilitiesCfmCreate(msg__, dst__, src__, clientData__, commandQueueSize__, trafficQueueSize__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlCapabilitiesCfmSend(dst__, clientData__, commandQueueSize__, trafficQueueSize__) \ - CsrWifiRouterCtrlCapabilitiesCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, commandQueueSize__, trafficQueueSize__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlConfigurePowerModeReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - mode - - wakeHost - - -*******************************************************************************/ -#define CsrWifiRouterCtrlConfigurePowerModeReqCreate(msg__, dst__, src__, clientData__, mode__, wakeHost__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlConfigurePowerModeReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->mode = (mode__); \ - msg__->wakeHost = (wakeHost__); - -#define CsrWifiRouterCtrlConfigurePowerModeReqSendTo(dst__, src__, clientData__, mode__, wakeHost__) \ - { \ - CsrWifiRouterCtrlConfigurePowerModeReq *msg__; \ - CsrWifiRouterCtrlConfigurePowerModeReqCreate(msg__, dst__, src__, clientData__, mode__, wakeHost__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlConfigurePowerModeReqSend(src__, clientData__, mode__, wakeHost__) \ - CsrWifiRouterCtrlConfigurePowerModeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, mode__, wakeHost__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlConnectedIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - peerStatus - - -*******************************************************************************/ -#define CsrWifiRouterCtrlConnectedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlConnectedInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_CONNECTED_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->peerStatus = (peerStatus__); - -#define CsrWifiRouterCtrlConnectedIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ - { \ - CsrWifiRouterCtrlConnectedInd *msg__; \ - CsrWifiRouterCtrlConnectedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlConnectedIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) \ - CsrWifiRouterCtrlConnectedIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, peerStatus__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlHipReqSend - - DESCRIPTION - This primitive is used for transferring MLME messages to the HIP. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - mlmeCommandLength - Length of the MLME signal - mlmeCommand - Pointer to the MLME signal - dataRef1Length - Length of the dataRef1 bulk data - dataRef1 - Pointer to the bulk data 1 - dataRef2Length - Length of the dataRef2 bulk data - dataRef2 - Pointer to the bulk data 2 - -*******************************************************************************/ -#define CsrWifiRouterCtrlHipReqCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlHipReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_HIP_REQ, dst__, src__); \ - msg__->mlmeCommandLength = (mlmeCommandLength__); \ - msg__->mlmeCommand = (mlmeCommand__); \ - msg__->dataRef1Length = (dataRef1Length__); \ - msg__->dataRef1 = (dataRef1__); \ - msg__->dataRef2Length = (dataRef2Length__); \ - msg__->dataRef2 = (dataRef2__); - -#define CsrWifiRouterCtrlHipReqSendTo(dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - { \ - CsrWifiRouterCtrlHipReq *msg__; \ - CsrWifiRouterCtrlHipReqCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlHipReqSend(src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - CsrWifiRouterCtrlHipReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlHipIndSend - - DESCRIPTION - This primitive is used for transferring MLME messages from the HIP. - - PARAMETERS - queue - Destination Task Queue - mlmeCommandLength - Length of the MLME signal - mlmeCommand - Pointer to the MLME signal - dataRef1Length - Length of the dataRef1 bulk data - dataRef1 - Pointer to the bulk data 1 - dataRef2Length - Length of the dataRef2 bulk data - dataRef2 - Pointer to the bulk data 2 - -*******************************************************************************/ -#define CsrWifiRouterCtrlHipIndCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlHipInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_HIP_IND, dst__, src__); \ - msg__->mlmeCommandLength = (mlmeCommandLength__); \ - msg__->mlmeCommand = (mlmeCommand__); \ - msg__->dataRef1Length = (dataRef1Length__); \ - msg__->dataRef1 = (dataRef1__); \ - msg__->dataRef2Length = (dataRef2Length__); \ - msg__->dataRef2 = (dataRef2__); - -#define CsrWifiRouterCtrlHipIndSendTo(dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - { \ - CsrWifiRouterCtrlHipInd *msg__; \ - CsrWifiRouterCtrlHipIndCreate(msg__, dst__, src__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlHipIndSend(dst__, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) \ - CsrWifiRouterCtrlHipIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, mlmeCommandLength__, mlmeCommand__, dataRef1Length__, dataRef1__, dataRef2Length__, dataRef2__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4ReadyToSendIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -#define CsrWifiRouterCtrlM4ReadyToSendIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlM4ReadyToSendInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); - -#define CsrWifiRouterCtrlM4ReadyToSendIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ - { \ - CsrWifiRouterCtrlM4ReadyToSendInd *msg__; \ - CsrWifiRouterCtrlM4ReadyToSendIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlM4ReadyToSendIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \ - CsrWifiRouterCtrlM4ReadyToSendIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4TransmitReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlM4TransmitReqCreate(msg__, dst__, src__, interfaceTag__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlM4TransmitReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlM4TransmitReqSendTo(dst__, src__, interfaceTag__, clientData__) \ - { \ - CsrWifiRouterCtrlM4TransmitReq *msg__; \ - CsrWifiRouterCtrlM4TransmitReqCreate(msg__, dst__, src__, interfaceTag__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlM4TransmitReqSend(src__, interfaceTag__, clientData__) \ - CsrWifiRouterCtrlM4TransmitReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4TransmittedIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlM4TransmittedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlM4TransmittedInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlM4TransmittedIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__) \ - { \ - CsrWifiRouterCtrlM4TransmittedInd *msg__; \ - CsrWifiRouterCtrlM4TransmittedIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlM4TransmittedIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, status__) \ - CsrWifiRouterCtrlM4TransmittedIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMediaStatusReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - mediaStatus - - -*******************************************************************************/ -#define CsrWifiRouterCtrlMediaStatusReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mediaStatus__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlMediaStatusReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->mediaStatus = (mediaStatus__); - -#define CsrWifiRouterCtrlMediaStatusReqSendTo(dst__, src__, interfaceTag__, clientData__, mediaStatus__) \ - { \ - CsrWifiRouterCtrlMediaStatusReq *msg__; \ - CsrWifiRouterCtrlMediaStatusReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mediaStatus__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlMediaStatusReqSend(src__, interfaceTag__, clientData__, mediaStatus__) \ - CsrWifiRouterCtrlMediaStatusReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mediaStatus__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMicFailureIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - unicastPdu - - -*******************************************************************************/ -#define CsrWifiRouterCtrlMicFailureIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlMicFailureInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->unicastPdu = (unicastPdu__); - -#define CsrWifiRouterCtrlMicFailureIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ - { \ - CsrWifiRouterCtrlMicFailureInd *msg__; \ - CsrWifiRouterCtrlMicFailureIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlMicFailureIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) \ - CsrWifiRouterCtrlMicFailureIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, unicastPdu__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlModeSetReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - mode - - bssid - BSSID of the network the device is going to be a part - of - protection - Set to TRUE if encryption is enabled for the - connection/broadcast frames - intraBssDistEnabled - If set to TRUE, intra BSS destribution will be - enabled. If set to FALSE, any unicast PDU which does - not have the RA as the the local MAC address, shall be - ignored. This field is interpreted by the receive if - mode is set to CSR_WIFI_ROUTER_CTRL_MODE_P2PGO - -*******************************************************************************/ -#define CsrWifiRouterCtrlModeSetReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlModeSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->mode = (mode__); \ - msg__->bssid = (bssid__); \ - msg__->protection = (protection__); \ - msg__->intraBssDistEnabled = (intraBssDistEnabled__); - -#define CsrWifiRouterCtrlModeSetReqSendTo(dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ - { \ - CsrWifiRouterCtrlModeSetReq *msg__; \ - CsrWifiRouterCtrlModeSetReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \ - CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlModeSetCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - mode - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlModeSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->mode = (mode__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlModeSetCfmSendTo(dst__, src__, clientData__, interfaceTag__, mode__, status__) \ - { \ - CsrWifiRouterCtrlModeSetCfm *msg__; \ - CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlModeSetCfmSend(dst__, clientData__, interfaceTag__, mode__, status__) \ - CsrWifiRouterCtrlModeSetCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, mode__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMulticastAddressIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - action - - setAddressesCount - - setAddresses - - -*******************************************************************************/ -#define CsrWifiRouterCtrlMulticastAddressIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlMulticastAddressInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->setAddressesCount = (setAddressesCount__); \ - msg__->setAddresses = (setAddresses__); - -#define CsrWifiRouterCtrlMulticastAddressIndSendTo(dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - { \ - CsrWifiRouterCtrlMulticastAddressInd *msg__; \ - CsrWifiRouterCtrlMulticastAddressIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlMulticastAddressIndSend(dst__, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - CsrWifiRouterCtrlMulticastAddressIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, action__, setAddressesCount__, setAddresses__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMulticastAddressResSend - - DESCRIPTION - - PARAMETERS - interfaceTag - - clientData - - status - - action - - getAddressesCount - - getAddresses - - -*******************************************************************************/ -#define CsrWifiRouterCtrlMulticastAddressResCreate(msg__, dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlMulticastAddressRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); \ - msg__->action = (action__); \ - msg__->getAddressesCount = (getAddressesCount__); \ - msg__->getAddresses = (getAddresses__); - -#define CsrWifiRouterCtrlMulticastAddressResSendTo(dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ - { \ - CsrWifiRouterCtrlMulticastAddressRes *msg__; \ - CsrWifiRouterCtrlMulticastAddressResCreate(msg__, dst__, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlMulticastAddressResSend(src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) \ - CsrWifiRouterCtrlMulticastAddressResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, status__, action__, getAddressesCount__, getAddresses__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerAddReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - peerMacAddress - - associationId - - staInfo - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerAddReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->associationId = (associationId__); \ - msg__->staInfo = (staInfo__); - -#define CsrWifiRouterCtrlPeerAddReqSendTo(dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ - { \ - CsrWifiRouterCtrlPeerAddReq *msg__; \ - CsrWifiRouterCtrlPeerAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerAddReqSend(src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) \ - CsrWifiRouterCtrlPeerAddReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerMacAddress__, associationId__, staInfo__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerAddCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - peerRecordHandle - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerAddCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->peerRecordHandle = (peerRecordHandle__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlPeerAddCfmSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ - { \ - CsrWifiRouterCtrlPeerAddCfm *msg__; \ - CsrWifiRouterCtrlPeerAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerAddCfmSend(dst__, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) \ - CsrWifiRouterCtrlPeerAddCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__, peerRecordHandle__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerDelReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - peerRecordHandle - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerDelReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->peerRecordHandle = (peerRecordHandle__); - -#define CsrWifiRouterCtrlPeerDelReqSendTo(dst__, src__, interfaceTag__, clientData__, peerRecordHandle__) \ - { \ - CsrWifiRouterCtrlPeerDelReq *msg__; \ - CsrWifiRouterCtrlPeerDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerDelReqSend(src__, interfaceTag__, clientData__, peerRecordHandle__) \ - CsrWifiRouterCtrlPeerDelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerRecordHandle__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerDelCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerDelCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlPeerDelCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlPeerDelCfm *msg__; \ - CsrWifiRouterCtrlPeerDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerDelCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlPeerDelCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerUpdateReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - peerRecordHandle - - powersaveMode - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerUpdateReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerUpdateReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->peerRecordHandle = (peerRecordHandle__); \ - msg__->powersaveMode = (powersaveMode__); - -#define CsrWifiRouterCtrlPeerUpdateReqSendTo(dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ - { \ - CsrWifiRouterCtrlPeerUpdateReq *msg__; \ - CsrWifiRouterCtrlPeerUpdateReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerUpdateReqSend(src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) \ - CsrWifiRouterCtrlPeerUpdateReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, peerRecordHandle__, powersaveMode__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerUpdateCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPeerUpdateCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPeerUpdateCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlPeerUpdateCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlPeerUpdateCfm *msg__; \ - CsrWifiRouterCtrlPeerUpdateCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPeerUpdateCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlPeerUpdateCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPortConfigureReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - uncontrolledPortAction - - controlledPortAction - - macAddress - - setProtection - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPortConfigureReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPortConfigureReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->uncontrolledPortAction = (uncontrolledPortAction__); \ - msg__->controlledPortAction = (controlledPortAction__); \ - msg__->macAddress = (macAddress__); \ - msg__->setProtection = (setProtection__); - -#define CsrWifiRouterCtrlPortConfigureReqSendTo(dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ - { \ - CsrWifiRouterCtrlPortConfigureReq *msg__; \ - CsrWifiRouterCtrlPortConfigureReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPortConfigureReqSend(src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) \ - CsrWifiRouterCtrlPortConfigureReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, uncontrolledPortAction__, controlledPortAction__, macAddress__, setProtection__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPortConfigureCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - macAddress - - -*******************************************************************************/ -#define CsrWifiRouterCtrlPortConfigureCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__, macAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlPortConfigureCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->macAddress = (macAddress__); - -#define CsrWifiRouterCtrlPortConfigureCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__, macAddress__) \ - { \ - CsrWifiRouterCtrlPortConfigureCfm *msg__; \ - CsrWifiRouterCtrlPortConfigureCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__, macAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlPortConfigureCfmSend(dst__, clientData__, interfaceTag__, status__, macAddress__) \ - CsrWifiRouterCtrlPortConfigureCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__, macAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlQosControlReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - control - - queueConfig - - -*******************************************************************************/ -#define CsrWifiRouterCtrlQosControlReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, control__, queueConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlQosControlReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->control = (control__); \ - msg__->queueConfig = (queueConfig__); - -#define CsrWifiRouterCtrlQosControlReqSendTo(dst__, src__, interfaceTag__, clientData__, control__, queueConfig__) \ - { \ - CsrWifiRouterCtrlQosControlReq *msg__; \ - CsrWifiRouterCtrlQosControlReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, control__, queueConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlQosControlReqSend(src__, interfaceTag__, clientData__, control__, queueConfig__) \ - CsrWifiRouterCtrlQosControlReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, control__, queueConfig__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioDeinitialiseReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlRawSdioDeinitialiseReq *msg__; \ - CsrWifiRouterCtrlRawSdioDeinitialiseReqCreate(msg__, dst__, src__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSend(src__, clientData__) \ - CsrWifiRouterCtrlRawSdioDeinitialiseReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioDeinitialiseCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - result - - -*******************************************************************************/ -#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmCreate(msg__, dst__, src__, clientData__, result__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->result = (result__); - -#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSendTo(dst__, src__, clientData__, result__) \ - { \ - CsrWifiRouterCtrlRawSdioDeinitialiseCfm *msg__; \ - CsrWifiRouterCtrlRawSdioDeinitialiseCfmCreate(msg__, dst__, src__, clientData__, result__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSend(dst__, clientData__, result__) \ - CsrWifiRouterCtrlRawSdioDeinitialiseCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, result__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioInitialiseReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlRawSdioInitialiseReqCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlRawSdioInitialiseReqSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlRawSdioInitialiseReq *msg__; \ - CsrWifiRouterCtrlRawSdioInitialiseReqCreate(msg__, dst__, src__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlRawSdioInitialiseReqSend(src__, clientData__) \ - CsrWifiRouterCtrlRawSdioInitialiseReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioInitialiseCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - result - - byteRead - - byteWrite - - firmwareDownload - - reset - - coreDumpPrepare - - byteBlockRead - - gpRead16 - - gpWrite16 - - -*******************************************************************************/ -#define CsrWifiRouterCtrlRawSdioInitialiseCfmCreate(msg__, dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->result = (result__); \ - msg__->byteRead = (byteRead__); \ - msg__->byteWrite = (byteWrite__); \ - msg__->firmwareDownload = (firmwareDownload__); \ - msg__->reset = (reset__); \ - msg__->coreDumpPrepare = (coreDumpPrepare__); \ - msg__->byteBlockRead = (byteBlockRead__); \ - msg__->gpRead16 = (gpRead16__); \ - msg__->gpWrite16 = (gpWrite16__); - -#define CsrWifiRouterCtrlRawSdioInitialiseCfmSendTo(dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ - { \ - CsrWifiRouterCtrlRawSdioInitialiseCfm *msg__; \ - CsrWifiRouterCtrlRawSdioInitialiseCfmCreate(msg__, dst__, src__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlRawSdioInitialiseCfmSend(dst__, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) \ - CsrWifiRouterCtrlRawSdioInitialiseCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, result__, byteRead__, byteWrite__, firmwareDownload__, reset__, coreDumpPrepare__, byteBlockRead__, gpRead16__, gpWrite16__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlResumeIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - powerMaintained - - -*******************************************************************************/ -#define CsrWifiRouterCtrlResumeIndCreate(msg__, dst__, src__, clientData__, powerMaintained__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlResumeInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RESUME_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->powerMaintained = (powerMaintained__); - -#define CsrWifiRouterCtrlResumeIndSendTo(dst__, src__, clientData__, powerMaintained__) \ - { \ - CsrWifiRouterCtrlResumeInd *msg__; \ - CsrWifiRouterCtrlResumeIndCreate(msg__, dst__, src__, clientData__, powerMaintained__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlResumeIndSend(dst__, clientData__, powerMaintained__) \ - CsrWifiRouterCtrlResumeIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, powerMaintained__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlResumeResSend - - DESCRIPTION - - PARAMETERS - clientData - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlResumeResCreate(msg__, dst__, src__, clientData__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlResumeRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_RESUME_RES, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlResumeResSendTo(dst__, src__, clientData__, status__) \ - { \ - CsrWifiRouterCtrlResumeRes *msg__; \ - CsrWifiRouterCtrlResumeResCreate(msg__, dst__, src__, clientData__, status__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlResumeResSend(src__, clientData__, status__) \ - CsrWifiRouterCtrlResumeResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlStaInactiveIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - staAddress - - -*******************************************************************************/ -#define CsrWifiRouterCtrlStaInactiveIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, staAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlStaInactiveInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->staAddress = (staAddress__); - -#define CsrWifiRouterCtrlStaInactiveIndSendTo(dst__, src__, clientData__, interfaceTag__, staAddress__) \ - { \ - CsrWifiRouterCtrlStaInactiveInd *msg__; \ - CsrWifiRouterCtrlStaInactiveIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, staAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlStaInactiveIndSend(dst__, clientData__, interfaceTag__, staAddress__) \ - CsrWifiRouterCtrlStaInactiveIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, staAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlSuspendIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - hardSuspend - - d3Suspend - - -*******************************************************************************/ -#define CsrWifiRouterCtrlSuspendIndCreate(msg__, dst__, src__, clientData__, hardSuspend__, d3Suspend__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlSuspendInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_SUSPEND_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->hardSuspend = (hardSuspend__); \ - msg__->d3Suspend = (d3Suspend__); - -#define CsrWifiRouterCtrlSuspendIndSendTo(dst__, src__, clientData__, hardSuspend__, d3Suspend__) \ - { \ - CsrWifiRouterCtrlSuspendInd *msg__; \ - CsrWifiRouterCtrlSuspendIndCreate(msg__, dst__, src__, clientData__, hardSuspend__, d3Suspend__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlSuspendIndSend(dst__, clientData__, hardSuspend__, d3Suspend__) \ - CsrWifiRouterCtrlSuspendIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, hardSuspend__, d3Suspend__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlSuspendResSend - - DESCRIPTION - - PARAMETERS - clientData - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlSuspendResCreate(msg__, dst__, src__, clientData__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlSuspendRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_SUSPEND_RES, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlSuspendResSendTo(dst__, src__, clientData__, status__) \ - { \ - CsrWifiRouterCtrlSuspendRes *msg__; \ - CsrWifiRouterCtrlSuspendResCreate(msg__, dst__, src__, clientData__, status__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlSuspendResSend(src__, clientData__, status__) \ - CsrWifiRouterCtrlSuspendResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasAddReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - tclasLength - - tclas - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTclasAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTclasAddReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->tclasLength = (tclasLength__); \ - msg__->tclas = (tclas__); - -#define CsrWifiRouterCtrlTclasAddReqSendTo(dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - { \ - CsrWifiRouterCtrlTclasAddReq *msg__; \ - CsrWifiRouterCtrlTclasAddReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTclasAddReqSend(src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - CsrWifiRouterCtrlTclasAddReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, tclasLength__, tclas__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasAddCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTclasAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTclasAddCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlTclasAddCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlTclasAddCfm *msg__; \ - CsrWifiRouterCtrlTclasAddCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTclasAddCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlTclasAddCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasDelReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - tclasLength - - tclas - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTclasDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTclasDelReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->tclasLength = (tclasLength__); \ - msg__->tclas = (tclas__); - -#define CsrWifiRouterCtrlTclasDelReqSendTo(dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - { \ - CsrWifiRouterCtrlTclasDelReq *msg__; \ - CsrWifiRouterCtrlTclasDelReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, tclasLength__, tclas__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTclasDelReqSend(src__, interfaceTag__, clientData__, tclasLength__, tclas__) \ - CsrWifiRouterCtrlTclasDelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, tclasLength__, tclas__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasDelCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTclasDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTclasDelCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlTclasDelCfmSendTo(dst__, src__, clientData__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlTclasDelCfm *msg__; \ - CsrWifiRouterCtrlTclasDelCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTclasDelCfmSend(dst__, clientData__, interfaceTag__, status__) \ - CsrWifiRouterCtrlTclasDelCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficClassificationReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - trafficType - - period - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTrafficClassificationReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficType__, period__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTrafficClassificationReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->trafficType = (trafficType__); \ - msg__->period = (period__); - -#define CsrWifiRouterCtrlTrafficClassificationReqSendTo(dst__, src__, interfaceTag__, clientData__, trafficType__, period__) \ - { \ - CsrWifiRouterCtrlTrafficClassificationReq *msg__; \ - CsrWifiRouterCtrlTrafficClassificationReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficType__, period__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTrafficClassificationReqSend(src__, interfaceTag__, clientData__, trafficType__, period__) \ - CsrWifiRouterCtrlTrafficClassificationReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, trafficType__, period__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficConfigReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - clientData - - trafficConfigType - - config - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTrafficConfigReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTrafficConfigReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->clientData = (clientData__); \ - msg__->trafficConfigType = (trafficConfigType__); \ - msg__->config = (config__); - -#define CsrWifiRouterCtrlTrafficConfigReqSendTo(dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ - { \ - CsrWifiRouterCtrlTrafficConfigReq *msg__; \ - CsrWifiRouterCtrlTrafficConfigReqCreate(msg__, dst__, src__, interfaceTag__, clientData__, trafficConfigType__, config__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTrafficConfigReqSend(src__, interfaceTag__, clientData__, trafficConfigType__, config__) \ - CsrWifiRouterCtrlTrafficConfigReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, trafficConfigType__, config__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficProtocolIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - packetType - - direction - - srcAddress - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTrafficProtocolIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTrafficProtocolInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->packetType = (packetType__); \ - msg__->direction = (direction__); \ - msg__->srcAddress = (srcAddress__); - -#define CsrWifiRouterCtrlTrafficProtocolIndSendTo(dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ - { \ - CsrWifiRouterCtrlTrafficProtocolInd *msg__; \ - CsrWifiRouterCtrlTrafficProtocolIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTrafficProtocolIndSend(dst__, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) \ - CsrWifiRouterCtrlTrafficProtocolIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, packetType__, direction__, srcAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficSampleIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - stats - - -*******************************************************************************/ -#define CsrWifiRouterCtrlTrafficSampleIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, stats__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlTrafficSampleInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->stats = (stats__); - -#define CsrWifiRouterCtrlTrafficSampleIndSendTo(dst__, src__, clientData__, interfaceTag__, stats__) \ - { \ - CsrWifiRouterCtrlTrafficSampleInd *msg__; \ - CsrWifiRouterCtrlTrafficSampleIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, stats__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlTrafficSampleIndSend(dst__, clientData__, interfaceTag__, stats__) \ - CsrWifiRouterCtrlTrafficSampleIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, stats__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlUnexpectedFrameIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -#define CsrWifiRouterCtrlUnexpectedFrameIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlUnexpectedFrameInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); - -#define CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, src__, clientData__, interfaceTag__, peerMacAddress__) \ - { \ - CsrWifiRouterCtrlUnexpectedFrameInd *msg__; \ - CsrWifiRouterCtrlUnexpectedFrameIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, peerMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \ - CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiFilterReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - isWapiConnected - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiFilterReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->isWapiConnected = (isWapiConnected__); - -#define CsrWifiRouterCtrlWapiFilterReqSendTo(dst__, src__, interfaceTag__, isWapiConnected__) \ - { \ - CsrWifiRouterCtrlWapiFilterReq *msg__; \ - CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiFilterReqSend(src__, interfaceTag__, isWapiConnected__) \ - CsrWifiRouterCtrlWapiFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, isWapiConnected__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiMulticastFilterReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \ - CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, interfaceTag__, status__) \ - CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiRxMicCheckIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - signalLength - - signal - - dataLength - - data - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->signalLength = (signalLength__); \ - msg__->signal = (signal__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - { \ - CsrWifiRouterCtrlWapiRxMicCheckInd *msg__; \ - CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiRxMicCheckIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiRxPktReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - signalLength - - signal - - dataLength - - data - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->signalLength = (signalLength__); \ - msg__->signal = (signal__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiRouterCtrlWapiRxPktReqSendTo(dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - { \ - CsrWifiRouterCtrlWapiRxPktReq *msg__; \ - CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiRxPktReqSend(src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiRxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastFilterReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \ - CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, interfaceTag__, status__) \ - CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - interfaceTag - - dataLength - - data - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \ - { \ - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *msg__; \ - CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(dst__, clientData__, interfaceTag__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastTxPktReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - dataLength - - data - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(dst__, src__, interfaceTag__, dataLength__, data__) \ - { \ - CsrWifiRouterCtrlWapiUnicastTxPktReq *msg__; \ - CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWapiUnicastTxPktReqSend(src__, interfaceTag__, dataLength__, data__) \ - CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOffReqCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOffReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlWifiOffReqSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlWifiOffReq *msg__; \ - CsrWifiRouterCtrlWifiOffReqCreate(msg__, dst__, src__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOffReqSend(src__, clientData__) \ - CsrWifiRouterCtrlWifiOffReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - controlIndication - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOffIndCreate(msg__, dst__, src__, clientData__, controlIndication__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOffInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->controlIndication = (controlIndication__); - -#define CsrWifiRouterCtrlWifiOffIndSendTo(dst__, src__, clientData__, controlIndication__) \ - { \ - CsrWifiRouterCtrlWifiOffInd *msg__; \ - CsrWifiRouterCtrlWifiOffIndCreate(msg__, dst__, src__, clientData__, controlIndication__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOffIndSend(dst__, clientData__, controlIndication__) \ - CsrWifiRouterCtrlWifiOffIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, controlIndication__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffResSend - - DESCRIPTION - - PARAMETERS - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOffResCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOffRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlWifiOffResSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlWifiOffRes *msg__; \ - CsrWifiRouterCtrlWifiOffResCreate(msg__, dst__, src__, clientData__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOffResSend(src__, clientData__) \ - CsrWifiRouterCtrlWifiOffResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOffCfmCreate(msg__, dst__, src__, clientData__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOffCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM, dst__, src__); \ - msg__->clientData = (clientData__); - -#define CsrWifiRouterCtrlWifiOffCfmSendTo(dst__, src__, clientData__) \ - { \ - CsrWifiRouterCtrlWifiOffCfm *msg__; \ - CsrWifiRouterCtrlWifiOffCfmCreate(msg__, dst__, src__, clientData__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOffCfmSend(dst__, clientData__) \ - CsrWifiRouterCtrlWifiOffCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnReqSend - - DESCRIPTION - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - clientData - - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__, dataLength__, data__) \ - { \ - CsrWifiRouterCtrlWifiOnReq *msg__; \ - CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__, dataLength__, data__) \ - CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnIndSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - status - - versions - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOnIndCreate(msg__, dst__, src__, clientData__, status__, versions__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); \ - msg__->versions = (versions__); - -#define CsrWifiRouterCtrlWifiOnIndSendTo(dst__, src__, clientData__, status__, versions__) \ - { \ - CsrWifiRouterCtrlWifiOnInd *msg__; \ - CsrWifiRouterCtrlWifiOnIndCreate(msg__, dst__, src__, clientData__, status__, versions__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOnIndSend(dst__, clientData__, status__, versions__) \ - CsrWifiRouterCtrlWifiOnIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, status__, versions__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnResSend - - DESCRIPTION - - PARAMETERS - clientData - - status - - numInterfaceAddress - - stationMacAddress - array size 1 MUST match CSR_WIFI_NUM_INTERFACES - smeVersions - - scheduledInterrupt - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOnResCreate(msg__, dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); \ - msg__->numInterfaceAddress = (numInterfaceAddress__); \ - memcpy(msg__->stationMacAddress, (stationMacAddress__), sizeof(CsrWifiMacAddress) * 2); \ - msg__->smeVersions = (smeVersions__); \ - msg__->scheduledInterrupt = (scheduledInterrupt__); - -#define CsrWifiRouterCtrlWifiOnResSendTo(dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ - { \ - CsrWifiRouterCtrlWifiOnRes *msg__; \ - CsrWifiRouterCtrlWifiOnResCreate(msg__, dst__, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOnResSend(src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) \ - CsrWifiRouterCtrlWifiOnResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, status__, numInterfaceAddress__, stationMacAddress__, smeVersions__, scheduledInterrupt__) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnCfmSend - - DESCRIPTION - - PARAMETERS - queue - Destination Task Queue - clientData - - status - - -*******************************************************************************/ -#define CsrWifiRouterCtrlWifiOnCfmCreate(msg__, dst__, src__, clientData__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM, dst__, src__); \ - msg__->clientData = (clientData__); \ - msg__->status = (status__); - -#define CsrWifiRouterCtrlWifiOnCfmSendTo(dst__, src__, clientData__, status__) \ - { \ - CsrWifiRouterCtrlWifiOnCfm *msg__; \ - CsrWifiRouterCtrlWifiOnCfmCreate(msg__, dst__, src__, clientData__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \ - } - -#define CsrWifiRouterCtrlWifiOnCfmSend(dst__, clientData__, status__) \ - CsrWifiRouterCtrlWifiOnCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, status__) - -#endif /* CSR_WIFI_ROUTER_CTRL_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h b/drivers/staging/csr/csr_wifi_router_ctrl_prim.h deleted file mode 100644 index 1312a335dd76..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_prim.h +++ /dev/null @@ -1,2113 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_CTRL_PRIM_H__ -#define CSR_WIFI_ROUTER_CTRL_PRIM_H__ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" - -#define CSR_WIFI_ROUTER_CTRL_PRIM (0x0401) - -typedef CsrPrim CsrWifiRouterCtrlPrim; - -typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteWrite)(u8 func, u32 address, u8 data); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteRead)(u8 func, u32 address, u8 *pdata); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioFirmwareDownload)(u32 length, const u8 *pdata); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioReset)(void); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioCoreDumpPrepare)(u8 suspendSme); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioByteBlockRead)(u8 func, u32 address, u8 *pdata, u32 length); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioGpRead16)(u8 func, u32 address, u16 *pdata); -typedef CsrResult (*CsrWifiRouterCtrlRawSdioGpWrite16)(u8 func, u32 address, u16 data); - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckRole - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR - - - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlBlockAckRole; -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR ((CsrWifiRouterCtrlBlockAckRole) 0x00) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT ((CsrWifiRouterCtrlBlockAckRole) 0x01) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlControlIndication - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_ERROR - - - CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_EXIT - - - CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_USER_REQUESTED - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlControlIndication; -#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_ERROR ((CsrWifiRouterCtrlControlIndication) 0x01) -#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_EXIT ((CsrWifiRouterCtrlControlIndication) 0x02) -#define CSR_WIFI_ROUTER_CTRL_CONTROL_INDICATION_USER_REQUESTED ((CsrWifiRouterCtrlControlIndication) 0x03) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlListAction - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_LIST_ACTION_GET - - - CSR_WIFI_ROUTER_CTRL_LIST_ACTION_ADD - - - CSR_WIFI_ROUTER_CTRL_LIST_ACTION_REMOVE - - - CSR_WIFI_ROUTER_CTRL_LIST_ACTION_FLUSH - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlListAction; -#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_GET ((CsrWifiRouterCtrlListAction) 0x00) -#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_ADD ((CsrWifiRouterCtrlListAction) 0x01) -#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_REMOVE ((CsrWifiRouterCtrlListAction) 0x02) -#define CSR_WIFI_ROUTER_CTRL_LIST_ACTION_FLUSH ((CsrWifiRouterCtrlListAction) 0x03) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlLowPowerMode - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED - - - CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_ENABLED - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlLowPowerMode; -#define CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED ((CsrWifiRouterCtrlLowPowerMode) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_ENABLED ((CsrWifiRouterCtrlLowPowerMode) 0x0001) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMediaStatus - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_CONNECTED - - - CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_DISCONNECTED - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlMediaStatus; -#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_CONNECTED ((CsrWifiRouterCtrlMediaStatus) 0x00) -#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_DISCONNECTED ((CsrWifiRouterCtrlMediaStatus) 0x01) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMode - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_MODE_NONE - - CSR_WIFI_ROUTER_CTRL_MODE_IBSS - - CSR_WIFI_ROUTER_CTRL_MODE_STA - - CSR_WIFI_ROUTER_CTRL_MODE_AP - - CSR_WIFI_ROUTER_CTRL_MODE_MONITOR - - CSR_WIFI_ROUTER_CTRL_MODE_AMP - - CSR_WIFI_ROUTER_CTRL_MODE_P2P - - CSR_WIFI_ROUTER_CTRL_MODE_P2PGO - - CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlMode; -#define CSR_WIFI_ROUTER_CTRL_MODE_NONE ((CsrWifiRouterCtrlMode) 0x00) -#define CSR_WIFI_ROUTER_CTRL_MODE_IBSS ((CsrWifiRouterCtrlMode) 0x01) -#define CSR_WIFI_ROUTER_CTRL_MODE_STA ((CsrWifiRouterCtrlMode) 0x02) -#define CSR_WIFI_ROUTER_CTRL_MODE_AP ((CsrWifiRouterCtrlMode) 0x03) -#define CSR_WIFI_ROUTER_CTRL_MODE_MONITOR ((CsrWifiRouterCtrlMode) 0x04) -#define CSR_WIFI_ROUTER_CTRL_MODE_AMP ((CsrWifiRouterCtrlMode) 0x05) -#define CSR_WIFI_ROUTER_CTRL_MODE_P2P ((CsrWifiRouterCtrlMode) 0x06) -#define CSR_WIFI_ROUTER_CTRL_MODE_P2PGO ((CsrWifiRouterCtrlMode) 0x07) -#define CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI ((CsrWifiRouterCtrlMode) 0x08) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerStatus - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE - - - CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE - - - CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlPeerStatus; -#define CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE ((CsrWifiRouterCtrlPeerStatus) 0x00) -#define CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE ((CsrWifiRouterCtrlPeerStatus) 0x01) -#define CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED ((CsrWifiRouterCtrlPeerStatus) 0x02) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPortAction - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN - - - CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD - - - CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlPortAction; -#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN ((CsrWifiRouterCtrlPortAction) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD ((CsrWifiRouterCtrlPortAction) 0x0001) -#define CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK ((CsrWifiRouterCtrlPortAction) 0x0002) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPowersaveType - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_AC_BK_PS_INFO_PRESENT - - If set, AC BK PS info is present in b4 and b5 - CSR_WIFI_ROUTER_CTRL_AC_BE_PS_INFO_PRESENT - - If set, AC BE PS info is present in b6 and b7 - CSR_WIFI_ROUTER_CTRL_AC_VI_PS_INFO_PRESENT - - If set, AC VI PS info is present in b8 and b9 - CSR_WIFI_ROUTER_CTRL_AC_VO_PS_INFO_PRESENT - - If set, AC VO PS info is present in b10 and b11 - CSR_WIFI_ROUTER_CTRL_AC_BK_TRIGGER_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_BK_DELIVERY_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_BE_TRIGGER_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_BE_DELIVERY_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_VI_TRIGGER_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_VI_DELIVERY_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_VO_TRIGGER_ENABLED - - - CSR_WIFI_ROUTER_CTRL_AC_VO_DELIVERY_ENABLED - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlPowersaveType; -#define CSR_WIFI_ROUTER_CTRL_AC_BK_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0001) -#define CSR_WIFI_ROUTER_CTRL_AC_BE_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0002) -#define CSR_WIFI_ROUTER_CTRL_AC_VI_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0004) -#define CSR_WIFI_ROUTER_CTRL_AC_VO_PS_INFO_PRESENT ((CsrWifiRouterCtrlPowersaveType) 0x0008) -#define CSR_WIFI_ROUTER_CTRL_AC_BK_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0010) -#define CSR_WIFI_ROUTER_CTRL_AC_BK_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0020) -#define CSR_WIFI_ROUTER_CTRL_AC_BE_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0040) -#define CSR_WIFI_ROUTER_CTRL_AC_BE_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0080) -#define CSR_WIFI_ROUTER_CTRL_AC_VI_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0100) -#define CSR_WIFI_ROUTER_CTRL_AC_VI_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0200) -#define CSR_WIFI_ROUTER_CTRL_AC_VO_TRIGGER_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0400) -#define CSR_WIFI_ROUTER_CTRL_AC_VO_DELIVERY_ENABLED ((CsrWifiRouterCtrlPowersaveType) 0x0800) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlProtocolDirection - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX - - - CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlProtocolDirection; -#define CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX ((CsrWifiRouterCtrlProtocolDirection) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX ((CsrWifiRouterCtrlProtocolDirection) 0x0001) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlQoSControl - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_OFF - - - CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON - - - CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_80211_ON - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlQoSControl; -#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_OFF ((CsrWifiRouterCtrlQoSControl) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON ((CsrWifiRouterCtrlQoSControl) 0x0001) -#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_80211_ON ((CsrWifiRouterCtrlQoSControl) 0x0002) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlQueueConfig - - DESCRIPTION - Defines which Queues are enabled for use. - - VALUES - CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE - - - CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE - - - CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE - - - CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlQueueConfig; -#define CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x01) -#define CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x02) -#define CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x04) -#define CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE ((CsrWifiRouterCtrlQueueConfig) 0x08) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficConfigType - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_CLS - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlTrafficConfigType; -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_RESET ((CsrWifiRouterCtrlTrafficConfigType) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER ((CsrWifiRouterCtrlTrafficConfigType) 0x0001) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_CLS ((CsrWifiRouterCtrlTrafficConfigType) 0x0002) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficPacketType - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ALL - - - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlTrafficPacketType; -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_NONE ((CsrWifiRouterCtrlTrafficPacketType) 0x0000) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL ((CsrWifiRouterCtrlTrafficPacketType) 0x0001) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP ((CsrWifiRouterCtrlTrafficPacketType) 0x0002) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_DHCP_ACK ((CsrWifiRouterCtrlTrafficPacketType) 0x0004) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP ((CsrWifiRouterCtrlTrafficPacketType) 0x0008) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET ((CsrWifiRouterCtrlTrafficPacketType) 0x0010) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM ((CsrWifiRouterCtrlTrafficPacketType) 0x0020) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ALL ((CsrWifiRouterCtrlTrafficPacketType) 0x00FF) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficType - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_BURSTY - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC - - - CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_CONTINUOUS - - - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlTrafficType; -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_OCCASIONAL ((CsrWifiRouterCtrlTrafficType) 0x00) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_BURSTY ((CsrWifiRouterCtrlTrafficType) 0x01) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC ((CsrWifiRouterCtrlTrafficType) 0x02) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_CONTINUOUS ((CsrWifiRouterCtrlTrafficType) 0x03) - - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerRecordHandle - - DESCRIPTION - -*******************************************************************************/ -typedef u32 CsrWifiRouterCtrlPeerRecordHandle; -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPowersaveTypeMask - - DESCRIPTION - Mask type for use with the values defined by - CsrWifiRouterCtrlPowersaveType - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlPowersaveTypeMask; -/******************************************************************************* - - NAME - CsrWifiRouterCtrlQueueConfigMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiRouterCtrlQueueConfig - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlQueueConfigMask; -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRequestorInfo - - DESCRIPTION - -*******************************************************************************/ -typedef u16 CsrWifiRouterCtrlRequestorInfo; -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficStreamId - - DESCRIPTION - -*******************************************************************************/ -typedef u8 CsrWifiRouterCtrlTrafficStreamId; - - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlSmeVersions - - DESCRIPTION - - MEMBERS - firmwarePatch - - smeBuild - - smeHip - - -*******************************************************************************/ -typedef struct -{ - u32 firmwarePatch; - char *smeBuild; - u32 smeHip; -} CsrWifiRouterCtrlSmeVersions; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlStaInfo - - DESCRIPTION - - MEMBERS - wmmOrQosEnabled - - powersaveMode - - maxSpLength - - listenIntervalInTus - - -*******************************************************************************/ -typedef struct -{ - u8 wmmOrQosEnabled; - CsrWifiRouterCtrlPowersaveTypeMask powersaveMode; - u8 maxSpLength; - u16 listenIntervalInTus; -} CsrWifiRouterCtrlStaInfo; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficFilter - - DESCRIPTION - - MEMBERS - etherType - - ipType - - udpSourcePort - - udpDestPort - - -*******************************************************************************/ -typedef struct -{ - u32 etherType; - u8 ipType; - u32 udpSourcePort; - u32 udpDestPort; -} CsrWifiRouterCtrlTrafficFilter; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficStats - - DESCRIPTION - - MEMBERS - rxMeanRate - Mean rx data rate over the interval - rxFramesNum - Keep number of Rx frames per second, for CYCLE_3. - txFramesNum - Keep number of Tx frames per second, for CYCLE_3. - rxBytesCount - Keep calculated Rx throughput per second, for CYCLE_2. - txBytesCount - Keep calculated Tx throughput per second, for CYCLE_2. - intervals - array size 11 MUST match TA_INTERVALS_NUM - -*******************************************************************************/ -typedef struct -{ - u32 rxMeanRate; - u32 rxFramesNum; - u32 txFramesNum; - u32 rxBytesCount; - u32 txBytesCount; - u8 intervals[11]; -} CsrWifiRouterCtrlTrafficStats; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlVersions - - DESCRIPTION - - MEMBERS - chipId - - chipVersion - - firmwareBuild - - firmwareHip - - routerBuild - - routerHip - - -*******************************************************************************/ -typedef struct -{ - u32 chipId; - u32 chipVersion; - u32 firmwareBuild; - u32 firmwareHip; - char *routerBuild; - u32 routerHip; -} CsrWifiRouterCtrlVersions; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficConfig - - DESCRIPTION - - MEMBERS - packetFilter - - customFilter - - -*******************************************************************************/ -typedef struct -{ - u16 packetFilter; - CsrWifiRouterCtrlTrafficFilter customFilter; -} CsrWifiRouterCtrlTrafficConfig; - - -/* Downstream */ -#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_ROUTER_CTRL_CONFIGURE_POWER_MODE_REQ ((CsrWifiRouterCtrlPrim) (0x0000 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_HIP_REQ ((CsrWifiRouterCtrlPrim) (0x0001 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MEDIA_STATUS_REQ ((CsrWifiRouterCtrlPrim) (0x0002 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_RES ((CsrWifiRouterCtrlPrim) (0x0003 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_REQ ((CsrWifiRouterCtrlPrim) (0x0004 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_REQ ((CsrWifiRouterCtrlPrim) (0x0005 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_SUSPEND_RES ((CsrWifiRouterCtrlPrim) (0x0006 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_REQ ((CsrWifiRouterCtrlPrim) (0x0007 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RESUME_RES ((CsrWifiRouterCtrlPrim) (0x0008 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_REQ ((CsrWifiRouterCtrlPrim) (0x0009 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_REQ ((CsrWifiRouterCtrlPrim) (0x000A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_REQ ((CsrWifiRouterCtrlPrim) (0x000B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CLASSIFICATION_REQ ((CsrWifiRouterCtrlPrim) (0x000C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_REQ ((CsrWifiRouterCtrlPrim) (0x000D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_REQ ((CsrWifiRouterCtrlPrim) (0x000E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_RES ((CsrWifiRouterCtrlPrim) (0x000F + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ ((CsrWifiRouterCtrlPrim) (0x0010 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES ((CsrWifiRouterCtrlPrim) (0x0011 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_M4_TRANSMIT_REQ ((CsrWifiRouterCtrlPrim) (0x0012 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MODE_SET_REQ ((CsrWifiRouterCtrlPrim) (0x0013 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_ADD_REQ ((CsrWifiRouterCtrlPrim) (0x0014 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_DEL_REQ ((CsrWifiRouterCtrlPrim) (0x0015 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_REQ ((CsrWifiRouterCtrlPrim) (0x0016 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ ((CsrWifiRouterCtrlPrim) (0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ ((CsrWifiRouterCtrlPrim) (0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ ((CsrWifiRouterCtrlPrim) (0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ ((CsrWifiRouterCtrlPrim) (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_ROUTER_CTRL_HIP_IND ((CsrWifiRouterCtrlPrim)(0x0000 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND ((CsrWifiRouterCtrlPrim)(0x0001 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM ((CsrWifiRouterCtrlPrim)(0x0002 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RESUME_IND ((CsrWifiRouterCtrlPrim)(0x0003 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_SUSPEND_IND ((CsrWifiRouterCtrlPrim)(0x0004 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TCLAS_ADD_CFM ((CsrWifiRouterCtrlPrim)(0x0005 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_DEINITIALISE_CFM ((CsrWifiRouterCtrlPrim)(0x0006 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_RAW_SDIO_INITIALISE_CFM ((CsrWifiRouterCtrlPrim)(0x0007 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TCLAS_DEL_CFM ((CsrWifiRouterCtrlPrim)(0x0008 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_PROTOCOL_IND ((CsrWifiRouterCtrlPrim)(0x0009 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_TRAFFIC_SAMPLE_IND ((CsrWifiRouterCtrlPrim)(0x000A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_IND ((CsrWifiRouterCtrlPrim)(0x000B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_OFF_CFM ((CsrWifiRouterCtrlPrim)(0x000C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_IND ((CsrWifiRouterCtrlPrim)(0x000D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WIFI_ON_CFM ((CsrWifiRouterCtrlPrim)(0x000E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_M4_READY_TO_SEND_IND ((CsrWifiRouterCtrlPrim)(0x000F + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_M4_TRANSMITTED_IND ((CsrWifiRouterCtrlPrim)(0x0010 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MIC_FAILURE_IND ((CsrWifiRouterCtrlPrim)(0x0011 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_CONNECTED_IND ((CsrWifiRouterCtrlPrim)(0x0012 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_ADD_CFM ((CsrWifiRouterCtrlPrim)(0x0013 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_DEL_CFM ((CsrWifiRouterCtrlPrim)(0x0014 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_UNEXPECTED_FRAME_IND ((CsrWifiRouterCtrlPrim)(0x0015 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_PEER_UPDATE_CFM ((CsrWifiRouterCtrlPrim)(0x0016 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_CFM ((CsrWifiRouterCtrlPrim)(0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_CFM ((CsrWifiRouterCtrlPrim)(0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM ((CsrWifiRouterCtrlPrim)(0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND ((CsrWifiRouterCtrlPrim)(0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND ((CsrWifiRouterCtrlPrim)(0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM ((CsrWifiRouterCtrlPrim)(0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND ((CsrWifiRouterCtrlPrim)(0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlConfigurePowerModeReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - mode - - wakeHost - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlLowPowerMode mode; - u8 wakeHost; -} CsrWifiRouterCtrlConfigurePowerModeReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlHipReq - - DESCRIPTION - This primitive is used for transferring MLME messages to the HIP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mlmeCommandLength - Length of the MLME signal - mlmeCommand - Pointer to the MLME signal - dataRef1Length - Length of the dataRef1 bulk data - dataRef1 - Pointer to the bulk data 1 - dataRef2Length - Length of the dataRef2 bulk data - dataRef2 - Pointer to the bulk data 2 - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 mlmeCommandLength; - u8 *mlmeCommand; - u16 dataRef1Length; - u8 *dataRef1; - u16 dataRef2Length; - u8 *dataRef2; -} CsrWifiRouterCtrlHipReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMediaStatusReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - mediaStatus - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlMediaStatus mediaStatus; -} CsrWifiRouterCtrlMediaStatusReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMulticastAddressRes - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - status - - action - - getAddressesCount - - getAddresses - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; - CsrWifiRouterCtrlListAction action; - u8 getAddressesCount; - CsrWifiMacAddress *getAddresses; -} CsrWifiRouterCtrlMulticastAddressRes; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPortConfigureReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - uncontrolledPortAction - - controlledPortAction - - macAddress - - setProtection - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlPortAction uncontrolledPortAction; - CsrWifiRouterCtrlPortAction controlledPortAction; - CsrWifiMacAddress macAddress; - u8 setProtection; -} CsrWifiRouterCtrlPortConfigureReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlQosControlReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - control - - queueConfig - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlQoSControl control; - CsrWifiRouterCtrlQueueConfigMask queueConfig; -} CsrWifiRouterCtrlQosControlReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlSuspendRes - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; -} CsrWifiRouterCtrlSuspendRes; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasAddReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - tclasLength - - tclas - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 tclasLength; - u8 *tclas; -} CsrWifiRouterCtrlTclasAddReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlResumeRes - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; -} CsrWifiRouterCtrlResumeRes; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioDeinitialiseReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlRawSdioDeinitialiseReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioInitialiseReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlRawSdioInitialiseReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasDelReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - tclasLength - - tclas - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 tclasLength; - u8 *tclas; -} CsrWifiRouterCtrlTclasDelReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficClassificationReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - trafficType - - period - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlTrafficType trafficType; - u16 period; -} CsrWifiRouterCtrlTrafficClassificationReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficConfigReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - trafficConfigType - - config - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlTrafficConfigType trafficConfigType; - CsrWifiRouterCtrlTrafficConfig config; -} CsrWifiRouterCtrlTrafficConfigReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlWifiOffReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffRes - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlWifiOffRes; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u32 dataLength; - u8 *data; -} CsrWifiRouterCtrlWifiOnReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnRes - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - status - - numInterfaceAddress - - stationMacAddress - array size 1 MUST match CSR_WIFI_NUM_INTERFACES - smeVersions - - scheduledInterrupt - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; - u16 numInterfaceAddress; - CsrWifiMacAddress stationMacAddress[2]; - CsrWifiRouterCtrlSmeVersions smeVersions; - u8 scheduledInterrupt; -} CsrWifiRouterCtrlWifiOnRes; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4TransmitReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlM4TransmitReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlModeSetReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - mode - - bssid - BSSID of the network the device is going to be a part - of - protection - Set to TRUE if encryption is enabled for the - connection/broadcast frames - intraBssDistEnabled - If set to TRUE, intra BSS destribution will be - enabled. If set to FALSE, any unicast PDU which does - not have the RA as the the local MAC address, shall be - ignored. This field is interpreted by the receive if - mode is set to CSR_WIFI_ROUTER_CTRL_MODE_P2PGO - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlMode mode; - CsrWifiMacAddress bssid; - u8 protection; - u8 intraBssDistEnabled; -} CsrWifiRouterCtrlModeSetReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerAddReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - peerMacAddress - - associationId - - staInfo - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiMacAddress peerMacAddress; - u16 associationId; - CsrWifiRouterCtrlStaInfo staInfo; -} CsrWifiRouterCtrlPeerAddReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerDelReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - peerRecordHandle - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; -} CsrWifiRouterCtrlPeerDelReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerUpdateReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - peerRecordHandle - - powersaveMode - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; - CsrWifiRouterCtrlPowersaveTypeMask powersaveMode; -} CsrWifiRouterCtrlPeerUpdateReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlCapabilitiesReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlCapabilitiesReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckEnableReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - macAddress - - trafficStreamID - - role - - bufferSize - - timeout - - ssn - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiMacAddress macAddress; - CsrWifiRouterCtrlTrafficStreamId trafficStreamID; - CsrWifiRouterCtrlBlockAckRole role; - u16 bufferSize; - u16 timeout; - u16 ssn; -} CsrWifiRouterCtrlBlockAckEnableReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckDisableReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - clientData - - macAddress - - trafficStreamID - - role - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiMacAddress macAddress; - CsrWifiRouterCtrlTrafficStreamId trafficStreamID; - CsrWifiRouterCtrlBlockAckRole role; -} CsrWifiRouterCtrlBlockAckDisableReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiRxPktReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - signalLength - - signal - - dataLength - - data - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u16 signalLength; - u8 *signal; - u16 dataLength; - u8 *data; -} CsrWifiRouterCtrlWapiRxPktReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiMulticastFilterReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 status; -} CsrWifiRouterCtrlWapiMulticastFilterReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastFilterReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 status; -} CsrWifiRouterCtrlWapiUnicastFilterReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastTxPktReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - dataLength - - data - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u16 dataLength; - u8 *data; -} CsrWifiRouterCtrlWapiUnicastTxPktReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiFilterReq - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - isWapiConnected - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 isWapiConnected; -} CsrWifiRouterCtrlWapiFilterReq; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlHipInd - - DESCRIPTION - This primitive is used for transferring MLME messages from the HIP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mlmeCommandLength - Length of the MLME signal - mlmeCommand - Pointer to the MLME signal - dataRef1Length - Length of the dataRef1 bulk data - dataRef1 - Pointer to the bulk data 1 - dataRef2Length - Length of the dataRef2 bulk data - dataRef2 - Pointer to the bulk data 2 - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 mlmeCommandLength; - u8 *mlmeCommand; - u16 dataRef1Length; - u8 *dataRef1; - u16 dataRef2Length; - u8 *dataRef2; -} CsrWifiRouterCtrlHipInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMulticastAddressInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - action - - setAddressesCount - - setAddresses - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiRouterCtrlListAction action; - u8 setAddressesCount; - CsrWifiMacAddress *setAddresses; -} CsrWifiRouterCtrlMulticastAddressInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPortConfigureCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - macAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; - CsrWifiMacAddress macAddress; -} CsrWifiRouterCtrlPortConfigureCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlResumeInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - powerMaintained - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u8 powerMaintained; -} CsrWifiRouterCtrlResumeInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlSuspendInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - hardSuspend - - d3Suspend - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u8 hardSuspend; - u8 d3Suspend; -} CsrWifiRouterCtrlSuspendInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasAddCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlTclasAddCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioDeinitialiseCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - result - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult result; -} CsrWifiRouterCtrlRawSdioDeinitialiseCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlRawSdioInitialiseCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - result - - byteRead - - byteWrite - - firmwareDownload - - reset - - coreDumpPrepare - - byteBlockRead - - gpRead16 - - gpWrite16 - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult result; - CsrWifiRouterCtrlRawSdioByteRead byteRead; - CsrWifiRouterCtrlRawSdioByteWrite byteWrite; - CsrWifiRouterCtrlRawSdioFirmwareDownload firmwareDownload; - CsrWifiRouterCtrlRawSdioReset reset; - CsrWifiRouterCtrlRawSdioCoreDumpPrepare coreDumpPrepare; - CsrWifiRouterCtrlRawSdioByteBlockRead byteBlockRead; - CsrWifiRouterCtrlRawSdioGpRead16 gpRead16; - CsrWifiRouterCtrlRawSdioGpWrite16 gpWrite16; -} CsrWifiRouterCtrlRawSdioInitialiseCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTclasDelCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlTclasDelCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficProtocolInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - packetType - - direction - - srcAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiRouterCtrlTrafficPacketType packetType; - CsrWifiRouterCtrlProtocolDirection direction; - CsrWifiMacAddress srcAddress; -} CsrWifiRouterCtrlTrafficProtocolInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlTrafficSampleInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - stats - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiRouterCtrlTrafficStats stats; -} CsrWifiRouterCtrlTrafficSampleInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - controlIndication - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrWifiRouterCtrlControlIndication controlIndication; -} CsrWifiRouterCtrlWifiOffInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOffCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; -} CsrWifiRouterCtrlWifiOffCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - status - - versions - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; - CsrWifiRouterCtrlVersions versions; -} CsrWifiRouterCtrlWifiOnInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWifiOnCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - CsrResult status; -} CsrWifiRouterCtrlWifiOnCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4ReadyToSendInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; -} CsrWifiRouterCtrlM4ReadyToSendInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlM4TransmittedInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; - CsrResult status; -} CsrWifiRouterCtrlM4TransmittedInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlMicFailureInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - unicastPdu - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; - u8 unicastPdu; -} CsrWifiRouterCtrlMicFailureInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlConnectedInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - peerStatus - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; - CsrWifiRouterCtrlPeerStatus peerStatus; -} CsrWifiRouterCtrlConnectedInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerAddCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - peerRecordHandle - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; - CsrWifiRouterCtrlPeerRecordHandle peerRecordHandle; - CsrResult status; -} CsrWifiRouterCtrlPeerAddCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerDelCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlPeerDelCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlUnexpectedFrameInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; -} CsrWifiRouterCtrlUnexpectedFrameInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlPeerUpdateCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlPeerUpdateCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlCapabilitiesCfm - - DESCRIPTION - The router sends this primitive to confirm the size of the queues of the - HIP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - commandQueueSize - Size of command queue - trafficQueueSize - Size of traffic queue (per AC) - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 commandQueueSize; - u16 trafficQueueSize; -} CsrWifiRouterCtrlCapabilitiesCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckEnableCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlBlockAckEnableCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckDisableCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterCtrlBlockAckDisableCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlBlockAckErrorInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - trafficStreamID - - peerMacAddress - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiRouterCtrlTrafficStreamId trafficStreamID; - CsrWifiMacAddress peerMacAddress; - CsrResult status; -} CsrWifiRouterCtrlBlockAckErrorInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlStaInactiveInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - staAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiMacAddress staAddress; -} CsrWifiRouterCtrlStaInactiveInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiRxMicCheckInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - signalLength - - signal - - dataLength - - data - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - u16 signalLength; - u8 *signal; - u16 dataLength; - u8 *data; -} CsrWifiRouterCtrlWapiRxMicCheckInd; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlModeSetCfm - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - mode - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - CsrWifiRouterCtrlMode mode; - CsrResult status; -} CsrWifiRouterCtrlModeSetCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterCtrlWapiUnicastTxEncryptInd - - DESCRIPTION - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - clientData - - interfaceTag - - dataLength - - data - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiRouterCtrlRequestorInfo clientData; - u16 interfaceTag; - u16 dataLength; - u8 *data; -} CsrWifiRouterCtrlWapiUnicastTxEncryptInd; - -#endif /* CSR_WIFI_ROUTER_CTRL_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c b/drivers/staging/csr/csr_wifi_router_ctrl_sef.c deleted file mode 100644 index 99cf93061d1b..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.c +++ /dev/null @@ -1,46 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#include "csr_wifi_router_ctrl_sef.h" - -const CsrWifiRouterCtrlStateHandlerType - CsrWifiRouterCtrlDownstreamStateHandlers - [CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT] = { - /* 0x0000 */ CsrWifiRouterCtrlConfigurePowerModeReqHandler, - /* 0x0001 */ CsrWifiRouterCtrlHipReqHandler, - /* 0x0002 */ CsrWifiRouterCtrlMediaStatusReqHandler, - /* 0x0003 */ CsrWifiRouterCtrlMulticastAddressResHandler, - /* 0x0004 */ CsrWifiRouterCtrlPortConfigureReqHandler, - /* 0x0005 */ CsrWifiRouterCtrlQosControlReqHandler, - /* 0x0006 */ CsrWifiRouterCtrlSuspendResHandler, - /* 0x0007 */ CsrWifiRouterCtrlTclasAddReqHandler, - /* 0x0008 */ CsrWifiRouterCtrlResumeResHandler, - /* 0x0009 */ CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler, - /* 0x000A */ CsrWifiRouterCtrlRawSdioInitialiseReqHandler, - /* 0x000B */ CsrWifiRouterCtrlTclasDelReqHandler, - /* 0x000C */ CsrWifiRouterCtrlTrafficClassificationReqHandler, - /* 0x000D */ CsrWifiRouterCtrlTrafficConfigReqHandler, - /* 0x000E */ CsrWifiRouterCtrlWifiOffReqHandler, - /* 0x000F */ CsrWifiRouterCtrlWifiOffResHandler, - /* 0x0010 */ CsrWifiRouterCtrlWifiOnReqHandler, - /* 0x0011 */ CsrWifiRouterCtrlWifiOnResHandler, - /* 0x0012 */ CsrWifiRouterCtrlM4TransmitReqHandler, - /* 0x0013 */ CsrWifiRouterCtrlModeSetReqHandler, - /* 0x0014 */ CsrWifiRouterCtrlPeerAddReqHandler, - /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler, - /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler, - /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler, - /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler, - /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler, - /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler, - /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler, - /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler, - /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler, - /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler, -}; diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h b/drivers/staging/csr/csr_wifi_router_ctrl_sef.h deleted file mode 100644 index 2fb4937bc909..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_sef.h +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ -#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ - -#include "csr_wifi_router_ctrl_prim.h" - - typedef void (*CsrWifiRouterCtrlStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg); - - extern const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers[CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT]; - - extern void CsrWifiRouterCtrlConfigurePowerModeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlHipReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlMulticastAddressResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlPortConfigureReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlQosControlReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlSuspendResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlTclasAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlRawSdioInitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlTclasDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlTrafficClassificationReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlTrafficConfigReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWifiOffResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlM4TransmitReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlPeerAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlPeerDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlPeerUpdateReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlCapabilitiesReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - -#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_CTRL_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c deleted file mode 100644 index 3eda1b66b336..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.c +++ /dev/null @@ -1,2591 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include -#include "csr_msgconv.h" -#include "csr_wifi_router_ctrl_prim.h" -#include "csr_wifi_router_ctrl_serialize.h" - -void CsrWifiRouterCtrlPfree(void *ptr) -{ - kfree(ptr); -} - - -size_t CsrWifiRouterCtrlConfigurePowerModeReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrWifiRouterCtrlLowPowerMode primitive->mode */ - bufferSize += 1; /* u8 primitive->wakeHost */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlConfigurePowerModeReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlConfigurePowerModeReq *primitive = (CsrWifiRouterCtrlConfigurePowerModeReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->mode); - CsrUint8Ser(ptr, len, (u8) primitive->wakeHost); - return(ptr); -} - - -void* CsrWifiRouterCtrlConfigurePowerModeReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlConfigurePowerModeReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlConfigurePowerModeReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mode, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wakeHost, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlHipReqSizeof(void *msg) -{ - CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ - bufferSize += 2; /* u16 primitive->mlmeCommandLength */ - bufferSize += primitive->mlmeCommandLength; /* u8 primitive->mlmeCommand */ - bufferSize += 2; /* u16 primitive->dataRef1Length */ - bufferSize += primitive->dataRef1Length; /* u8 primitive->dataRef1 */ - bufferSize += 2; /* u16 primitive->dataRef2Length */ - bufferSize += primitive->dataRef2Length; /* u8 primitive->dataRef2 */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlHipReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->mlmeCommandLength); - if (primitive->mlmeCommandLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mlmeCommand, ((u16) (primitive->mlmeCommandLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataRef1Length); - if (primitive->dataRef1Length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->dataRef1, ((u16) (primitive->dataRef1Length))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataRef2Length); - if (primitive->dataRef2Length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->dataRef2, ((u16) (primitive->dataRef2Length))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlHipReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlHipReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlHipReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mlmeCommandLength, buffer, &offset); - if (primitive->mlmeCommandLength) - { - primitive->mlmeCommand = kmalloc(primitive->mlmeCommandLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mlmeCommand, buffer, &offset, ((u16) (primitive->mlmeCommandLength))); - } - else - { - primitive->mlmeCommand = NULL; - } - CsrUint16Des((u16 *) &primitive->dataRef1Length, buffer, &offset); - if (primitive->dataRef1Length) - { - primitive->dataRef1 = kmalloc(primitive->dataRef1Length, GFP_KERNEL); - CsrMemCpyDes(primitive->dataRef1, buffer, &offset, ((u16) (primitive->dataRef1Length))); - } - else - { - primitive->dataRef1 = NULL; - } - CsrUint16Des((u16 *) &primitive->dataRef2Length, buffer, &offset); - if (primitive->dataRef2Length) - { - primitive->dataRef2 = kmalloc(primitive->dataRef2Length, GFP_KERNEL); - CsrMemCpyDes(primitive->dataRef2, buffer, &offset, ((u16) (primitive->dataRef2Length))); - } - else - { - primitive->dataRef2 = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlHipReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlHipReq *primitive = (CsrWifiRouterCtrlHipReq *) voidPrimitivePointer; - kfree(primitive->mlmeCommand); - kfree(primitive->dataRef1); - kfree(primitive->dataRef2); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlMediaStatusReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 1; /* CsrWifiRouterCtrlMediaStatus primitive->mediaStatus */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlMediaStatusReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlMediaStatusReq *primitive = (CsrWifiRouterCtrlMediaStatusReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint8Ser(ptr, len, (u8) primitive->mediaStatus); - return(ptr); -} - - -void* CsrWifiRouterCtrlMediaStatusReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlMediaStatusReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlMediaStatusReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mediaStatus, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlMulticastAddressResSizeof(void *msg) -{ - CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiRouterCtrlListAction primitive->action */ - bufferSize += 1; /* u8 primitive->getAddressesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - bufferSize += 6; /* u8 primitive->getAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiRouterCtrlMulticastAddressResSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->getAddressesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiRouterCtrlMulticastAddressResDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlMulticastAddressRes *primitive = kmalloc(sizeof(CsrWifiRouterCtrlMulticastAddressRes), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->getAddressesCount, buffer, &offset); - primitive->getAddresses = NULL; - if (primitive->getAddressesCount) - { - primitive->getAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->getAddressesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiRouterCtrlMulticastAddressResSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlMulticastAddressRes *primitive = (CsrWifiRouterCtrlMulticastAddressRes *) voidPrimitivePointer; - kfree(primitive->getAddresses); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlPortConfigureReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 18) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrWifiRouterCtrlPortAction primitive->uncontrolledPortAction */ - bufferSize += 2; /* CsrWifiRouterCtrlPortAction primitive->controlledPortAction */ - bufferSize += 6; /* u8 primitive->macAddress.a[6] */ - bufferSize += 1; /* u8 primitive->setProtection */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPortConfigureReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPortConfigureReq *primitive = (CsrWifiRouterCtrlPortConfigureReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->uncontrolledPortAction); - CsrUint16Ser(ptr, len, (u16) primitive->controlledPortAction); - CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->setProtection); - return(ptr); -} - - -void* CsrWifiRouterCtrlPortConfigureReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPortConfigureReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPortConfigureReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->uncontrolledPortAction, buffer, &offset); - CsrUint16Des((u16 *) &primitive->controlledPortAction, buffer, &offset); - CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->setProtection, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlQosControlReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrWifiRouterCtrlQoSControl primitive->control */ - bufferSize += 1; /* CsrWifiRouterCtrlQueueConfigMask primitive->queueConfig */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlQosControlReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlQosControlReq *primitive = (CsrWifiRouterCtrlQosControlReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->control); - CsrUint8Ser(ptr, len, (u8) primitive->queueConfig); - return(ptr); -} - - -void* CsrWifiRouterCtrlQosControlReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlQosControlReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlQosControlReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->control, buffer, &offset); - CsrUint8Des((u8 *) &primitive->queueConfig, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlSuspendResSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlSuspendResSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlSuspendRes *primitive = (CsrWifiRouterCtrlSuspendRes *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlSuspendResDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlSuspendRes *primitive = kmalloc(sizeof(CsrWifiRouterCtrlSuspendRes), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTclasAddReqSizeof(void *msg) -{ - CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->tclasLength */ - bufferSize += primitive->tclasLength; /* u8 primitive->tclas */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTclasAddReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->tclasLength); - if (primitive->tclasLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((u16) (primitive->tclasLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlTclasAddReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTclasAddReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTclasAddReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->tclasLength, buffer, &offset); - if (primitive->tclasLength) - { - primitive->tclas = kmalloc(primitive->tclasLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tclas, buffer, &offset, ((u16) (primitive->tclasLength))); - } - else - { - primitive->tclas = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlTclasAddReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlTclasAddReq *primitive = (CsrWifiRouterCtrlTclasAddReq *) voidPrimitivePointer; - kfree(primitive->tclas); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlResumeResSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlResumeResSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlResumeRes *primitive = (CsrWifiRouterCtrlResumeRes *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlResumeResDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlResumeRes *primitive = kmalloc(sizeof(CsrWifiRouterCtrlResumeRes), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTclasDelReqSizeof(void *msg) -{ - CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->tclasLength */ - bufferSize += primitive->tclasLength; /* u8 primitive->tclas */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTclasDelReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->tclasLength); - if (primitive->tclasLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((u16) (primitive->tclasLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlTclasDelReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTclasDelReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTclasDelReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->tclasLength, buffer, &offset); - if (primitive->tclasLength) - { - primitive->tclas = kmalloc(primitive->tclasLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tclas, buffer, &offset, ((u16) (primitive->tclasLength))); - } - else - { - primitive->tclas = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlTclasDelReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlTclasDelReq *primitive = (CsrWifiRouterCtrlTclasDelReq *) voidPrimitivePointer; - kfree(primitive->tclas); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlTrafficClassificationReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 1; /* CsrWifiRouterCtrlTrafficType primitive->trafficType */ - bufferSize += 2; /* u16 primitive->period */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTrafficClassificationReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTrafficClassificationReq *primitive = (CsrWifiRouterCtrlTrafficClassificationReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint8Ser(ptr, len, (u8) primitive->trafficType); - CsrUint16Ser(ptr, len, (u16) primitive->period); - return(ptr); -} - - -void* CsrWifiRouterCtrlTrafficClassificationReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTrafficClassificationReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTrafficClassificationReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint8Des((u8 *) &primitive->trafficType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->period, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 24) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrWifiRouterCtrlTrafficConfigType primitive->trafficConfigType */ - bufferSize += 2; /* u16 primitive->config.packetFilter */ - bufferSize += 4; /* u32 primitive->config.customFilter.etherType */ - bufferSize += 1; /* u8 primitive->config.customFilter.ipType */ - bufferSize += 4; /* u32 primitive->config.customFilter.udpSourcePort */ - bufferSize += 4; /* u32 primitive->config.customFilter.udpDestPort */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTrafficConfigReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTrafficConfigReq *primitive = (CsrWifiRouterCtrlTrafficConfigReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->trafficConfigType); - CsrUint16Ser(ptr, len, (u16) primitive->config.packetFilter); - CsrUint32Ser(ptr, len, (u32) primitive->config.customFilter.etherType); - CsrUint8Ser(ptr, len, (u8) primitive->config.customFilter.ipType); - CsrUint32Ser(ptr, len, (u32) primitive->config.customFilter.udpSourcePort); - CsrUint32Ser(ptr, len, (u32) primitive->config.customFilter.udpDestPort); - return(ptr); -} - - -void* CsrWifiRouterCtrlTrafficConfigReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTrafficConfigReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTrafficConfigReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->trafficConfigType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->config.packetFilter, buffer, &offset); - CsrUint32Des((u32 *) &primitive->config.customFilter.etherType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->config.customFilter.ipType, buffer, &offset); - CsrUint32Des((u32 *) &primitive->config.customFilter.udpSourcePort, buffer, &offset); - CsrUint32Des((u32 *) &primitive->config.customFilter.udpDestPort, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlWifiOnReqSizeof(void *msg) -{ - CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 4; /* u32 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWifiOnReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint32Ser(ptr, len, (u32) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlWifiOnReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWifiOnReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint32Des((u32 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlWifiOnReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) voidPrimitivePointer; - kfree(primitive->data); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlWifiOnResSizeof(void *msg) -{ - CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 30) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->numInterfaceAddress */ - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - bufferSize += 6; /* u8 primitive->stationMacAddress[i1].a[6] */ - } - } - bufferSize += 4; /* u32 primitive->smeVersions.firmwarePatch */ - bufferSize += (primitive->smeVersions.smeBuild ? strlen(primitive->smeVersions.smeBuild) : 0) + 1; /* char* primitive->smeVersions.smeBuild (0 byte len + 1 for NULL Term) */ - bufferSize += 4; /* u32 primitive->smeVersions.smeHip */ - bufferSize += 1; /* u8 primitive->scheduledInterrupt */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWifiOnResSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->numInterfaceAddress); - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->stationMacAddress[i1].a, ((u16) (6))); - } - } - CsrUint32Ser(ptr, len, (u32) primitive->smeVersions.firmwarePatch); - CsrCharStringSer(ptr, len, primitive->smeVersions.smeBuild); - CsrUint32Ser(ptr, len, (u32) primitive->smeVersions.smeHip); - CsrUint8Ser(ptr, len, (u8) primitive->scheduledInterrupt); - return(ptr); -} - - -void* CsrWifiRouterCtrlWifiOnResDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWifiOnRes *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnRes), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->numInterfaceAddress, buffer, &offset); - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - CsrMemCpyDes(primitive->stationMacAddress[i1].a, buffer, &offset, ((u16) (6))); - } - } - CsrUint32Des((u32 *) &primitive->smeVersions.firmwarePatch, buffer, &offset); - CsrCharStringDes(&primitive->smeVersions.smeBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->smeVersions.smeHip, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scheduledInterrupt, buffer, &offset); - - return primitive; -} - - -void CsrWifiRouterCtrlWifiOnResSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) voidPrimitivePointer; - kfree(primitive->smeVersions.smeBuild); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlM4TransmitReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlM4TransmitReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlM4TransmitReq *primitive = (CsrWifiRouterCtrlM4TransmitReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - return(ptr); -} - - -void* CsrWifiRouterCtrlM4TransmitReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlM4TransmitReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlM4TransmitReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlModeSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 16) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */ - bufferSize += 6; /* u8 primitive->bssid.a[6] */ - bufferSize += 1; /* u8 primitive->protection */ - bufferSize += 1; /* u8 primitive->intraBssDistEnabled */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlModeSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlModeSetReq *primitive = (CsrWifiRouterCtrlModeSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint8Ser(ptr, len, (u8) primitive->mode); - CsrMemCpySer(ptr, len, (const void *) primitive->bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->protection); - CsrUint8Ser(ptr, len, (u8) primitive->intraBssDistEnabled); - return(ptr); -} - - -void* CsrWifiRouterCtrlModeSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlModeSetReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlModeSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mode, buffer, &offset); - CsrMemCpyDes(primitive->bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->protection, buffer, &offset); - CsrUint8Des((u8 *) &primitive->intraBssDistEnabled, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerAddReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 2; /* u16 primitive->associationId */ - bufferSize += 1; /* u8 primitive->staInfo.wmmOrQosEnabled */ - bufferSize += 2; /* CsrWifiRouterCtrlPowersaveTypeMask primitive->staInfo.powersaveMode */ - bufferSize += 1; /* u8 primitive->staInfo.maxSpLength */ - bufferSize += 2; /* u16 primitive->staInfo.listenIntervalInTus */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerAddReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerAddReq *primitive = (CsrWifiRouterCtrlPeerAddReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->associationId); - CsrUint8Ser(ptr, len, (u8) primitive->staInfo.wmmOrQosEnabled); - CsrUint16Ser(ptr, len, (u16) primitive->staInfo.powersaveMode); - CsrUint8Ser(ptr, len, (u8) primitive->staInfo.maxSpLength); - CsrUint16Ser(ptr, len, (u16) primitive->staInfo.listenIntervalInTus); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerAddReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerAddReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerAddReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->associationId, buffer, &offset); - CsrUint8Des((u8 *) &primitive->staInfo.wmmOrQosEnabled, buffer, &offset); - CsrUint16Des((u16 *) &primitive->staInfo.powersaveMode, buffer, &offset); - CsrUint8Des((u8 *) &primitive->staInfo.maxSpLength, buffer, &offset); - CsrUint16Des((u16 *) &primitive->staInfo.listenIntervalInTus, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerDelReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerDelReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerDelReq *primitive = (CsrWifiRouterCtrlPeerDelReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint32Ser(ptr, len, (u32) primitive->peerRecordHandle); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerDelReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerDelReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerDelReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint32Des((u32 *) &primitive->peerRecordHandle, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerUpdateReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ - bufferSize += 2; /* CsrWifiRouterCtrlPowersaveTypeMask primitive->powersaveMode */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerUpdateReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerUpdateReq *primitive = (CsrWifiRouterCtrlPeerUpdateReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint32Ser(ptr, len, (u32) primitive->peerRecordHandle); - CsrUint16Ser(ptr, len, (u16) primitive->powersaveMode); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerUpdateReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerUpdateReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerUpdateReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint32Des((u32 *) &primitive->peerRecordHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->powersaveMode, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlBlockAckEnableReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 6; /* u8 primitive->macAddress.a[6] */ - bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ - bufferSize += 1; /* CsrWifiRouterCtrlBlockAckRole primitive->role */ - bufferSize += 2; /* u16 primitive->bufferSize */ - bufferSize += 2; /* u16 primitive->timeout */ - bufferSize += 2; /* u16 primitive->ssn */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlBlockAckEnableReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlBlockAckEnableReq *primitive = (CsrWifiRouterCtrlBlockAckEnableReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->trafficStreamID); - CsrUint8Ser(ptr, len, (u8) primitive->role); - CsrUint16Ser(ptr, len, (u16) primitive->bufferSize); - CsrUint16Ser(ptr, len, (u16) primitive->timeout); - CsrUint16Ser(ptr, len, (u16) primitive->ssn); - return(ptr); -} - - -void* CsrWifiRouterCtrlBlockAckEnableReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlBlockAckEnableReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckEnableReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->trafficStreamID, buffer, &offset); - CsrUint8Des((u8 *) &primitive->role, buffer, &offset); - CsrUint16Des((u16 *) &primitive->bufferSize, buffer, &offset); - CsrUint16Des((u16 *) &primitive->timeout, buffer, &offset); - CsrUint16Des((u16 *) &primitive->ssn, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 6; /* u8 primitive->macAddress.a[6] */ - bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ - bufferSize += 1; /* CsrWifiRouterCtrlBlockAckRole primitive->role */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlBlockAckDisableReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlBlockAckDisableReq *primitive = (CsrWifiRouterCtrlBlockAckDisableReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->trafficStreamID); - CsrUint8Ser(ptr, len, (u8) primitive->role); - return(ptr); -} - - -void* CsrWifiRouterCtrlBlockAckDisableReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlBlockAckDisableReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckDisableReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->trafficStreamID, buffer, &offset); - CsrUint8Des((u8 *) &primitive->role, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg) -{ - CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* u16 primitive->signalLength */ - bufferSize += primitive->signalLength; /* u8 primitive->signal */ - bufferSize += 2; /* u16 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWapiRxPktReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->signalLength); - if (primitive->signalLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->signal, ((u16) (primitive->signalLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlWapiRxPktReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWapiRxPktReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->signalLength, buffer, &offset); - if (primitive->signalLength) - { - primitive->signal = kmalloc(primitive->signalLength, GFP_KERNEL); - CsrMemCpyDes(primitive->signal, buffer, &offset, ((u16) (primitive->signalLength))); - } - else - { - primitive->signal = NULL; - } - CsrUint16Des((u16 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) voidPrimitivePointer; - kfree(primitive->signal); - kfree(primitive->data); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg) -{ - CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* u16 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) voidPrimitivePointer; - kfree(primitive->data); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlHipIndSizeof(void *msg) -{ - CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ - bufferSize += 2; /* u16 primitive->mlmeCommandLength */ - bufferSize += primitive->mlmeCommandLength; /* u8 primitive->mlmeCommand */ - bufferSize += 2; /* u16 primitive->dataRef1Length */ - bufferSize += primitive->dataRef1Length; /* u8 primitive->dataRef1 */ - bufferSize += 2; /* u16 primitive->dataRef2Length */ - bufferSize += primitive->dataRef2Length; /* u8 primitive->dataRef2 */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlHipIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->mlmeCommandLength); - if (primitive->mlmeCommandLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mlmeCommand, ((u16) (primitive->mlmeCommandLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataRef1Length); - if (primitive->dataRef1Length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->dataRef1, ((u16) (primitive->dataRef1Length))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataRef2Length); - if (primitive->dataRef2Length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->dataRef2, ((u16) (primitive->dataRef2Length))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlHipIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlHipInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlHipInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mlmeCommandLength, buffer, &offset); - if (primitive->mlmeCommandLength) - { - primitive->mlmeCommand = kmalloc(primitive->mlmeCommandLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mlmeCommand, buffer, &offset, ((u16) (primitive->mlmeCommandLength))); - } - else - { - primitive->mlmeCommand = NULL; - } - CsrUint16Des((u16 *) &primitive->dataRef1Length, buffer, &offset); - if (primitive->dataRef1Length) - { - primitive->dataRef1 = kmalloc(primitive->dataRef1Length, GFP_KERNEL); - CsrMemCpyDes(primitive->dataRef1, buffer, &offset, ((u16) (primitive->dataRef1Length))); - } - else - { - primitive->dataRef1 = NULL; - } - CsrUint16Des((u16 *) &primitive->dataRef2Length, buffer, &offset); - if (primitive->dataRef2Length) - { - primitive->dataRef2 = kmalloc(primitive->dataRef2Length, GFP_KERNEL); - CsrMemCpyDes(primitive->dataRef2, buffer, &offset, ((u16) (primitive->dataRef2Length))); - } - else - { - primitive->dataRef2 = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlHipIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) voidPrimitivePointer; - kfree(primitive->mlmeCommand); - kfree(primitive->dataRef1); - kfree(primitive->dataRef2); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlMulticastAddressIndSizeof(void *msg) -{ - CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiRouterCtrlListAction primitive->action */ - bufferSize += 1; /* u8 primitive->setAddressesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - bufferSize += 6; /* u8 primitive->setAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiRouterCtrlMulticastAddressIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->setAddressesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiRouterCtrlMulticastAddressIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlMulticastAddressInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlMulticastAddressInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->setAddressesCount, buffer, &offset); - primitive->setAddresses = NULL; - if (primitive->setAddressesCount) - { - primitive->setAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->setAddressesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiRouterCtrlMulticastAddressIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlMulticastAddressInd *primitive = (CsrWifiRouterCtrlMulticastAddressInd *) voidPrimitivePointer; - kfree(primitive->setAddresses); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlPortConfigureCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 6; /* u8 primitive->macAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPortConfigureCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPortConfigureCfm *primitive = (CsrWifiRouterCtrlPortConfigureCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->macAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterCtrlPortConfigureCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPortConfigureCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPortConfigureCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->macAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlSuspendIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 1; /* u8 primitive->hardSuspend */ - bufferSize += 1; /* u8 primitive->d3Suspend */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlSuspendIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlSuspendInd *primitive = (CsrWifiRouterCtrlSuspendInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint8Ser(ptr, len, (u8) primitive->hardSuspend); - CsrUint8Ser(ptr, len, (u8) primitive->d3Suspend); - return(ptr); -} - - -void* CsrWifiRouterCtrlSuspendIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlSuspendInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlSuspendInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint8Des((u8 *) &primitive->hardSuspend, buffer, &offset); - CsrUint8Des((u8 *) &primitive->d3Suspend, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTclasAddCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTclasAddCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTclasAddCfm *primitive = (CsrWifiRouterCtrlTclasAddCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlTclasAddCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTclasAddCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTclasAddCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->result */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlRawSdioDeinitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioDeinitialiseCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->result); - return(ptr); -} - - -void* CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlRawSdioDeinitialiseCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioDeinitialiseCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 39) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->result */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteRead primitive->byteRead */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteWrite primitive->byteWrite */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioFirmwareDownload primitive->firmwareDownload */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioReset primitive->reset */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioCoreDumpPrepare primitive->coreDumpPrepare */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioByteBlockRead primitive->byteBlockRead */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioGpRead16 primitive->gpRead16 */ - bufferSize += 4; /* CsrWifiRouterCtrlRawSdioGpWrite16 primitive->gpWrite16 */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlRawSdioInitialiseCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlRawSdioInitialiseCfm *primitive = (CsrWifiRouterCtrlRawSdioInitialiseCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->result); - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteRead */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteWrite */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->firmwareDownload */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->reset */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->coreDumpPrepare */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->byteBlockRead */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->gpRead16 */ - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->gpWrite16 */ - return(ptr); -} - - -void* CsrWifiRouterCtrlRawSdioInitialiseCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlRawSdioInitialiseCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlRawSdioInitialiseCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result, buffer, &offset); - primitive->byteRead = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->byteWrite = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->firmwareDownload = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->reset = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->coreDumpPrepare = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->byteBlockRead = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->gpRead16 = NULL; /* Special for Function Pointers... */ - offset += 4; - primitive->gpWrite16 = NULL; /* Special for Function Pointers... */ - offset += 4; - - return primitive; -} - - -size_t CsrWifiRouterCtrlTclasDelCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTclasDelCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTclasDelCfm *primitive = (CsrWifiRouterCtrlTclasDelCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlTclasDelCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTclasDelCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTclasDelCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTrafficProtocolIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrWifiRouterCtrlTrafficPacketType primitive->packetType */ - bufferSize += 2; /* CsrWifiRouterCtrlProtocolDirection primitive->direction */ - bufferSize += 6; /* u8 primitive->srcAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTrafficProtocolIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTrafficProtocolInd *primitive = (CsrWifiRouterCtrlTrafficProtocolInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->packetType); - CsrUint16Ser(ptr, len, (u16) primitive->direction); - CsrMemCpySer(ptr, len, (const void *) primitive->srcAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterCtrlTrafficProtocolIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTrafficProtocolInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTrafficProtocolInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->packetType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->direction, buffer, &offset); - CsrMemCpyDes(primitive->srcAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlTrafficSampleIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 38) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 4; /* u32 primitive->stats.rxMeanRate */ - bufferSize += 4; /* u32 primitive->stats.rxFramesNum */ - bufferSize += 4; /* u32 primitive->stats.txFramesNum */ - bufferSize += 4; /* u32 primitive->stats.rxBytesCount */ - bufferSize += 4; /* u32 primitive->stats.txBytesCount */ - bufferSize += 11; /* u8 primitive->stats.intervals[11] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlTrafficSampleIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlTrafficSampleInd *primitive = (CsrWifiRouterCtrlTrafficSampleInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint32Ser(ptr, len, (u32) primitive->stats.rxMeanRate); - CsrUint32Ser(ptr, len, (u32) primitive->stats.rxFramesNum); - CsrUint32Ser(ptr, len, (u32) primitive->stats.txFramesNum); - CsrUint32Ser(ptr, len, (u32) primitive->stats.rxBytesCount); - CsrUint32Ser(ptr, len, (u32) primitive->stats.txBytesCount); - CsrMemCpySer(ptr, len, (const void *) primitive->stats.intervals, ((u16) (11))); - return(ptr); -} - - -void* CsrWifiRouterCtrlTrafficSampleIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlTrafficSampleInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlTrafficSampleInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint32Des((u32 *) &primitive->stats.rxMeanRate, buffer, &offset); - CsrUint32Des((u32 *) &primitive->stats.rxFramesNum, buffer, &offset); - CsrUint32Des((u32 *) &primitive->stats.txFramesNum, buffer, &offset); - CsrUint32Des((u32 *) &primitive->stats.rxBytesCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->stats.txBytesCount, buffer, &offset); - CsrMemCpyDes(primitive->stats.intervals, buffer, &offset, ((u16) (11))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlWifiOnIndSizeof(void *msg) -{ - CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 27) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 4; /* u32 primitive->versions.chipId */ - bufferSize += 4; /* u32 primitive->versions.chipVersion */ - bufferSize += 4; /* u32 primitive->versions.firmwareBuild */ - bufferSize += 4; /* u32 primitive->versions.firmwareHip */ - bufferSize += (primitive->versions.routerBuild ? strlen(primitive->versions.routerBuild) : 0) + 1; /* char* primitive->versions.routerBuild (0 byte len + 1 for NULL Term) */ - bufferSize += 4; /* u32 primitive->versions.routerHip */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWifiOnIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint32Ser(ptr, len, (u32) primitive->versions.chipId); - CsrUint32Ser(ptr, len, (u32) primitive->versions.chipVersion); - CsrUint32Ser(ptr, len, (u32) primitive->versions.firmwareBuild); - CsrUint32Ser(ptr, len, (u32) primitive->versions.firmwareHip); - CsrCharStringSer(ptr, len, primitive->versions.routerBuild); - CsrUint32Ser(ptr, len, (u32) primitive->versions.routerHip); - return(ptr); -} - - -void* CsrWifiRouterCtrlWifiOnIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWifiOnInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.chipId, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.chipVersion, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.firmwareBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.firmwareHip, buffer, &offset); - CsrCharStringDes(&primitive->versions.routerBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.routerHip, buffer, &offset); - - return primitive; -} - - -void CsrWifiRouterCtrlWifiOnIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWifiOnInd *primitive = (CsrWifiRouterCtrlWifiOnInd *) voidPrimitivePointer; - kfree(primitive->versions.routerBuild); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlWifiOnCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWifiOnCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWifiOnCfm *primitive = (CsrWifiRouterCtrlWifiOnCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlWifiOnCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWifiOnCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWifiOnCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlM4ReadyToSendIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlM4ReadyToSendIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlM4ReadyToSendInd *primitive = (CsrWifiRouterCtrlM4ReadyToSendInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterCtrlM4ReadyToSendIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlM4ReadyToSendInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlM4ReadyToSendInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlM4TransmittedIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlM4TransmittedIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlM4TransmittedInd *primitive = (CsrWifiRouterCtrlM4TransmittedInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlM4TransmittedIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlM4TransmittedInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlM4TransmittedInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlMicFailureIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 1; /* u8 primitive->unicastPdu */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlMicFailureIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlMicFailureInd *primitive = (CsrWifiRouterCtrlMicFailureInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->unicastPdu); - return(ptr); -} - - -void* CsrWifiRouterCtrlMicFailureIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlMicFailureInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlMicFailureInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->unicastPdu, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlConnectedIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 1; /* CsrWifiRouterCtrlPeerStatus primitive->peerStatus */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlConnectedIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlConnectedInd *primitive = (CsrWifiRouterCtrlConnectedInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->peerStatus); - return(ptr); -} - - -void* CsrWifiRouterCtrlConnectedIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlConnectedInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlConnectedInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->peerStatus, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerAddCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 19) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 4; /* CsrWifiRouterCtrlPeerRecordHandle primitive->peerRecordHandle */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerAddCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerAddCfm *primitive = (CsrWifiRouterCtrlPeerAddCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint32Ser(ptr, len, (u32) primitive->peerRecordHandle); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerAddCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerAddCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerAddCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint32Des((u32 *) &primitive->peerRecordHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerDelCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerDelCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerDelCfm *primitive = (CsrWifiRouterCtrlPeerDelCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerDelCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerDelCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerDelCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlUnexpectedFrameIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlUnexpectedFrameIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlUnexpectedFrameInd *primitive = (CsrWifiRouterCtrlUnexpectedFrameInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterCtrlUnexpectedFrameIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlUnexpectedFrameInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlUnexpectedFrameInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlPeerUpdateCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlPeerUpdateCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlPeerUpdateCfm *primitive = (CsrWifiRouterCtrlPeerUpdateCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlPeerUpdateCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlPeerUpdateCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlPeerUpdateCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlCapabilitiesCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->commandQueueSize */ - bufferSize += 2; /* u16 primitive->trafficQueueSize */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlCapabilitiesCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlCapabilitiesCfm *primitive = (CsrWifiRouterCtrlCapabilitiesCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->commandQueueSize); - CsrUint16Ser(ptr, len, (u16) primitive->trafficQueueSize); - return(ptr); -} - - -void* CsrWifiRouterCtrlCapabilitiesCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlCapabilitiesCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlCapabilitiesCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->commandQueueSize, buffer, &offset); - CsrUint16Des((u16 *) &primitive->trafficQueueSize, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlBlockAckEnableCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlBlockAckEnableCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlBlockAckEnableCfm *primitive = (CsrWifiRouterCtrlBlockAckEnableCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlBlockAckEnableCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlBlockAckEnableCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckEnableCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlBlockAckDisableCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlBlockAckDisableCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlBlockAckDisableCfm *primitive = (CsrWifiRouterCtrlBlockAckDisableCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlBlockAckDisableCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlBlockAckDisableCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckDisableCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlBlockAckErrorIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 16) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiRouterCtrlTrafficStreamId primitive->trafficStreamID */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlBlockAckErrorIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlBlockAckErrorInd *primitive = (CsrWifiRouterCtrlBlockAckErrorInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->trafficStreamID); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlBlockAckErrorIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlBlockAckErrorInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlBlockAckErrorInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->trafficStreamID, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->staAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlStaInactiveIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlStaInactiveInd *primitive = (CsrWifiRouterCtrlStaInactiveInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->staAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterCtrlStaInactiveIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlStaInactiveInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlStaInactiveInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->staAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg) -{ - CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* u16 primitive->signalLength */ - bufferSize += primitive->signalLength; /* u8 primitive->signal */ - bufferSize += 2; /* u16 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->signalLength); - if (primitive->signalLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->signal, ((u16) (primitive->signalLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->signalLength, buffer, &offset); - if (primitive->signalLength) - { - primitive->signal = kmalloc(primitive->signalLength, GFP_KERNEL); - CsrMemCpyDes(primitive->signal, buffer, &offset, ((u16) (primitive->signalLength))); - } - else - { - primitive->signal = NULL; - } - CsrUint16Des((u16 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) voidPrimitivePointer; - kfree(primitive->signal); - kfree(primitive->data); - kfree(primitive); -} - - -size_t CsrWifiRouterCtrlModeSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlModeSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->mode); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterCtrlModeSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlModeSetCfm *primitive = kmalloc(sizeof(CsrWifiRouterCtrlModeSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg) -{ - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* u16 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->clientData); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = kmalloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->clientData, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) voidPrimitivePointer; - kfree(primitive->data); - kfree(primitive); -} - - diff --git a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h b/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h deleted file mode 100644 index c9048386cfcb..000000000000 --- a/drivers/staging/csr/csr_wifi_router_ctrl_serialize.h +++ /dev/null @@ -1,333 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ -#define CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ - -#include "csr_wifi_msgconv.h" - -#include "csr_wifi_router_ctrl_prim.h" - -extern void CsrWifiRouterCtrlPfree(void *ptr); - -extern u8* CsrWifiRouterCtrlConfigurePowerModeReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlConfigurePowerModeReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlConfigurePowerModeReqSizeof(void *msg); -#define CsrWifiRouterCtrlConfigurePowerModeReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlHipReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlHipReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlHipReqSizeof(void *msg); -extern void CsrWifiRouterCtrlHipReqSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlMediaStatusReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlMediaStatusReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlMediaStatusReqSizeof(void *msg); -#define CsrWifiRouterCtrlMediaStatusReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlMulticastAddressResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlMulticastAddressResDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlMulticastAddressResSizeof(void *msg); -extern void CsrWifiRouterCtrlMulticastAddressResSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlPortConfigureReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPortConfigureReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPortConfigureReqSizeof(void *msg); -#define CsrWifiRouterCtrlPortConfigureReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlQosControlReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlQosControlReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlQosControlReqSizeof(void *msg); -#define CsrWifiRouterCtrlQosControlReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlSuspendResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlSuspendResDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlSuspendResSizeof(void *msg); -#define CsrWifiRouterCtrlSuspendResSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTclasAddReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTclasAddReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTclasAddReqSizeof(void *msg); -extern void CsrWifiRouterCtrlTclasAddReqSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlResumeResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlResumeResDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlResumeResSizeof(void *msg); -#define CsrWifiRouterCtrlResumeResSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlRawSdioDeinitialiseReqSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlRawSdioInitialiseReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlRawSdioInitialiseReqDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlRawSdioInitialiseReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlRawSdioInitialiseReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTclasDelReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTclasDelReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTclasDelReqSizeof(void *msg); -extern void CsrWifiRouterCtrlTclasDelReqSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlTrafficClassificationReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTrafficClassificationReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTrafficClassificationReqSizeof(void *msg); -#define CsrWifiRouterCtrlTrafficClassificationReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTrafficConfigReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTrafficConfigReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg); -#define CsrWifiRouterCtrlTrafficConfigReqSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlWifiOffReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlWifiOffReqDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlWifiOffReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlWifiOffReqSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlWifiOffResSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlWifiOffResDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWifiOnReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWifiOnReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWifiOnReqSizeof(void *msg); -extern void CsrWifiRouterCtrlWifiOnReqSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlWifiOnResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWifiOnResDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWifiOnResSizeof(void *msg); -extern void CsrWifiRouterCtrlWifiOnResSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlM4TransmitReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlM4TransmitReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlM4TransmitReqSizeof(void *msg); -#define CsrWifiRouterCtrlM4TransmitReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlModeSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlModeSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlModeSetReqSizeof(void *msg); -#define CsrWifiRouterCtrlModeSetReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerAddReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerAddReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerAddReqSizeof(void *msg); -#define CsrWifiRouterCtrlPeerAddReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerDelReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerDelReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerDelReqSizeof(void *msg); -#define CsrWifiRouterCtrlPeerDelReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerUpdateReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerUpdateReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerUpdateReqSizeof(void *msg); -#define CsrWifiRouterCtrlPeerUpdateReqSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlCapabilitiesReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlCapabilitiesReqDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlCapabilitiesReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlCapabilitiesReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlBlockAckEnableReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlBlockAckEnableReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlBlockAckEnableReqSizeof(void *msg); -#define CsrWifiRouterCtrlBlockAckEnableReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlBlockAckDisableReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg); -#define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWapiRxPktReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWapiRxPktReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *msg); - -#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *msg); - -#define CsrWifiRouterCtrlWapiFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterCtrlWapiFilterReqDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterCtrlWapiFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterCtrlWapiFilterReqSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlHipIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlHipIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlHipIndSizeof(void *msg); -extern void CsrWifiRouterCtrlHipIndSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlMulticastAddressIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlMulticastAddressIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlMulticastAddressIndSizeof(void *msg); -extern void CsrWifiRouterCtrlMulticastAddressIndSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlPortConfigureCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPortConfigureCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPortConfigureCfmSizeof(void *msg); -#define CsrWifiRouterCtrlPortConfigureCfmSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlResumeIndSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterCtrlResumeIndDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterCtrlResumeIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterCtrlResumeIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlSuspendIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlSuspendIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlSuspendIndSizeof(void *msg); -#define CsrWifiRouterCtrlSuspendIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTclasAddCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTclasAddCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTclasAddCfmSizeof(void *msg); -#define CsrWifiRouterCtrlTclasAddCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlRawSdioDeinitialiseCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlRawSdioDeinitialiseCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlRawSdioDeinitialiseCfmSizeof(void *msg); -#define CsrWifiRouterCtrlRawSdioDeinitialiseCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlRawSdioInitialiseCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlRawSdioInitialiseCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlRawSdioInitialiseCfmSizeof(void *msg); -#define CsrWifiRouterCtrlRawSdioInitialiseCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTclasDelCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTclasDelCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTclasDelCfmSizeof(void *msg); -#define CsrWifiRouterCtrlTclasDelCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTrafficProtocolIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTrafficProtocolIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTrafficProtocolIndSizeof(void *msg); -#define CsrWifiRouterCtrlTrafficProtocolIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlTrafficSampleIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlTrafficSampleIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlTrafficSampleIndSizeof(void *msg); -#define CsrWifiRouterCtrlTrafficSampleIndSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlWifiOffIndSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterCtrlWifiOffIndDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterCtrlWifiOffIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterCtrlWifiOffIndSerFree CsrWifiRouterCtrlPfree - -#define CsrWifiRouterCtrlWifiOffCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiRouterCtrlWifiOffCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiRouterCtrlWifiOffCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiRouterCtrlWifiOffCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWifiOnIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWifiOnIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWifiOnIndSizeof(void *msg); -extern void CsrWifiRouterCtrlWifiOnIndSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlWifiOnCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWifiOnCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWifiOnCfmSizeof(void *msg); -#define CsrWifiRouterCtrlWifiOnCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlM4ReadyToSendIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlM4ReadyToSendIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlM4ReadyToSendIndSizeof(void *msg); -#define CsrWifiRouterCtrlM4ReadyToSendIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlM4TransmittedIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlM4TransmittedIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlM4TransmittedIndSizeof(void *msg); -#define CsrWifiRouterCtrlM4TransmittedIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlMicFailureIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlMicFailureIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlMicFailureIndSizeof(void *msg); -#define CsrWifiRouterCtrlMicFailureIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlConnectedIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlConnectedIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlConnectedIndSizeof(void *msg); -#define CsrWifiRouterCtrlConnectedIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerAddCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerAddCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerAddCfmSizeof(void *msg); -#define CsrWifiRouterCtrlPeerAddCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerDelCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerDelCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerDelCfmSizeof(void *msg); -#define CsrWifiRouterCtrlPeerDelCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlUnexpectedFrameIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlUnexpectedFrameIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlUnexpectedFrameIndSizeof(void *msg); -#define CsrWifiRouterCtrlUnexpectedFrameIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlPeerUpdateCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlPeerUpdateCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlPeerUpdateCfmSizeof(void *msg); -#define CsrWifiRouterCtrlPeerUpdateCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlCapabilitiesCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlCapabilitiesCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlCapabilitiesCfmSizeof(void *msg); -#define CsrWifiRouterCtrlCapabilitiesCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlBlockAckEnableCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlBlockAckEnableCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlBlockAckEnableCfmSizeof(void *msg); -#define CsrWifiRouterCtrlBlockAckEnableCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlBlockAckDisableCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlBlockAckDisableCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlBlockAckDisableCfmSizeof(void *msg); -#define CsrWifiRouterCtrlBlockAckDisableCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlBlockAckErrorIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlBlockAckErrorIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlBlockAckErrorIndSizeof(void *msg); -#define CsrWifiRouterCtrlBlockAckErrorIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlStaInactiveIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlStaInactiveIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg); -#define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *msg); - -extern u8* CsrWifiRouterCtrlModeSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlModeSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlModeSetCfmSizeof(void *msg); -#define CsrWifiRouterCtrlModeSetCfmSerFree CsrWifiRouterCtrlPfree - -extern u8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg); -extern void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *msg); - -#endif /* CSR_WIFI_ROUTER_CTRL_SERIALIZE_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c deleted file mode 100644 index c4badc565a91..000000000000 --- a/drivers/staging/csr/csr_wifi_router_free_downstream_contents.c +++ /dev/null @@ -1,53 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_router_prim.h" -#include "csr_wifi_router_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiRouterFreeDownstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_ROUTER_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiRouterFreeDownstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_ROUTER_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiRouterPrim *) message)) - { - case CSR_WIFI_ROUTER_MA_PACKET_REQ: - { - CsrWifiRouterMaPacketReq *p = (CsrWifiRouterMaPacketReq *)message; - kfree(p->frame); - p->frame = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c deleted file mode 100644 index 4cd126338e27..000000000000 --- a/drivers/staging/csr/csr_wifi_router_free_upstream_contents.c +++ /dev/null @@ -1,47 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_router_prim.h" -#include "csr_wifi_router_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiRouterFreeUpstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_ROUTER_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiRouterFreeUpstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_ROUTER_PRIM) - return; - if (NULL == message) - return; - switch (*((CsrWifiRouterPrim *) message)) { - case CSR_WIFI_ROUTER_MA_PACKET_IND: - { - CsrWifiRouterMaPacketInd *p = - (CsrWifiRouterMaPacketInd *) message; - kfree(p->frame); - p->frame = NULL; - break; - } - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_router_lib.h b/drivers/staging/csr/csr_wifi_router_lib.h deleted file mode 100644 index b0477c413aae..000000000000 --- a/drivers/staging/csr/csr_wifi_router_lib.h +++ /dev/null @@ -1,417 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_LIB_H__ -#define CSR_WIFI_ROUTER_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_router_prim.h" -#include "csr_wifi_router_task.h" - -/*----------------------------------------------------------------------------* - * CsrWifiRouterFreeUpstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_ROUTER upstream message. Does not - * free the message itself, and can only be used for upstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_ROUTER upstream message - *----------------------------------------------------------------------------*/ -void CsrWifiRouterFreeUpstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * CsrWifiRouterFreeDownstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_ROUTER downstream message. Does not - * free the message itself, and can only be used for downstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_ROUTER downstream message - *----------------------------------------------------------------------------*/ -void CsrWifiRouterFreeDownstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * Enum to string functions - *----------------------------------------------------------------------------*/ -const char* CsrWifiRouterAppTypeToString(CsrWifiRouterAppType value); -const char* CsrWifiRouterEncapsulationToString(CsrWifiRouterEncapsulation value); -const char* CsrWifiRouterOuiToString(CsrWifiRouterOui value); -const char* CsrWifiRouterPriorityToString(CsrWifiRouterPriority value); - - -/*----------------------------------------------------------------------------* - * CsrPrim Type toString function. - * Converts a message type to the String name of the Message - *----------------------------------------------------------------------------*/ -const char* CsrWifiRouterPrimTypeToString(CsrPrim msgType); - -/*----------------------------------------------------------------------------* - * Lookup arrays for PrimType name Strings - *----------------------------------------------------------------------------*/ -extern const char *CsrWifiRouterUpstreamPrimNames[CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT]; -extern const char *CsrWifiRouterDownstreamPrimNames[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT]; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketCancelReqSend - - DESCRIPTION - This primitive is used to request cancellation of a previously send - CsrWifiRouterMaPacketReq. - The frame may already have been transmitted so there is no guarantees - that the CsrWifiRouterMaPacketCancelReq actually cancels the transmission - of the frame in question. - If the cancellation fails, the Router will send, if required, - CsrWifiRouterMaPacketCfm. - If the cancellation succeeds, the Router will not send - CsrWifiRouterMaPacketCfm. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - hostTag - The hostTag for the frame, which should be cancelled. - priority - Priority of the frame, which should be cancelled - peerMacAddress - Destination MAC address of the frame, which should be - cancelled - -*******************************************************************************/ -#define CsrWifiRouterMaPacketCancelReqCreate(msg__, dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketCancelReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->hostTag = (hostTag__); \ - msg__->priority = (priority__); \ - msg__->peerMacAddress = (peerMacAddress__); - -#define CsrWifiRouterMaPacketCancelReqSendTo(dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ - { \ - CsrWifiRouterMaPacketCancelReq *msg__; \ - CsrWifiRouterMaPacketCancelReqCreate(msg__, dst__, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketCancelReqSend(src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) \ - CsrWifiRouterMaPacketCancelReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, hostTag__, priority__, peerMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketReqSend - - DESCRIPTION - A task sends this primitive to transmit a frame. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - frameLength - Length of the frame to be sent in bytes - frame - Pointer to the frame to be sent - freeFunction - Pointer to function to be used to free the frame - priority - Priority of the frame, which should be sent - hostTag - An application shall set the bits b31..b28 using one of - the CSR_WIFI_ROUTER_APP_TYPE_* masks. Bits b0..b27 can - be used by the requestor without any restrictions, but - the hostTag shall be unique so the hostTag for - CSR_WIFI_ROUTER_APP _TYPE_OTHER should be constructured - in the following way [ CSR_WIFI_ROUTER_APP_TYPE_OTHER - (4 bits) | SubscriptionHandle (8 bits) | Sequence no. - (20 bits) ]. If the hostTag is not unique, the - behaviour of the system is unpredicatable with respect - to data/management frame transfer. - cfmRequested - Indicates if the requestor needs a confirm for packet - requests sent under this subscription. If set to TRUE, - the router will send a confirm, else it will not send - any confirm - -*******************************************************************************/ -#define CsrWifiRouterMaPacketReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->subscriptionHandle = (subscriptionHandle__); \ - msg__->frameLength = (frameLength__); \ - msg__->frame = (frame__); \ - msg__->freeFunction = (freeFunction__); \ - msg__->priority = (priority__); \ - msg__->hostTag = (hostTag__); \ - msg__->cfmRequested = (cfmRequested__); - -#define CsrWifiRouterMaPacketReqSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ - { \ - CsrWifiRouterMaPacketReq *msg__; \ - CsrWifiRouterMaPacketReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketReqSend(src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) \ - CsrWifiRouterMaPacketReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__, frameLength__, frame__, freeFunction__, priority__, hostTag__, cfmRequested__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketIndSend - - DESCRIPTION - The router sends the primitive to a subscribed task when it receives a - frame matching the subscription. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - result - Status of the operation - frameLength - Length of the received frame in bytes - frame - Pointer to the received frame - freeFunction - Pointer to function to be used to free the frame - rssi - Received signal strength indication in dBm - snr - Signal to Noise Ratio - rate - Transmission/Reception rate - -*******************************************************************************/ -#define CsrWifiRouterMaPacketIndCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->subscriptionHandle = (subscriptionHandle__); \ - msg__->result = (result__); \ - msg__->frameLength = (frameLength__); \ - msg__->frame = (frame__); \ - msg__->freeFunction = (freeFunction__); \ - msg__->rssi = (rssi__); \ - msg__->snr = (snr__); \ - msg__->rate = (rate__); - -#define CsrWifiRouterMaPacketIndSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ - { \ - CsrWifiRouterMaPacketInd *msg__; \ - CsrWifiRouterMaPacketIndCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketIndSend(dst__, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) \ - CsrWifiRouterMaPacketIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, subscriptionHandle__, result__, frameLength__, frame__, freeFunction__, rssi__, snr__, rate__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketResSend - - DESCRIPTION - A task send this primitive to confirm the reception of the received - frame. - - PARAMETERS - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - result - Status of the operation - -*******************************************************************************/ -#define CsrWifiRouterMaPacketResCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketRes), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_RES, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->subscriptionHandle = (subscriptionHandle__); \ - msg__->result = (result__); - -#define CsrWifiRouterMaPacketResSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, result__) \ - { \ - CsrWifiRouterMaPacketRes *msg__; \ - CsrWifiRouterMaPacketResCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, result__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketResSend(src__, interfaceTag__, subscriptionHandle__, result__) \ - CsrWifiRouterMaPacketResSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__, result__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketCfmSend - - DESCRIPTION - The router sends the primitive to confirm the result of the transmission - of the packet of the corresponding CSR_WIFI_ROUTER MA_PACKET_REQ request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - result - Status of the operation - hostTag - The hostTrag will match the hostTag sent in the request. - rate - Transmission/Reception rate - -*******************************************************************************/ -#define CsrWifiRouterMaPacketCfmCreate(msg__, dst__, src__, interfaceTag__, result__, hostTag__, rate__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->result = (result__); \ - msg__->hostTag = (hostTag__); \ - msg__->rate = (rate__); - -#define CsrWifiRouterMaPacketCfmSendTo(dst__, src__, interfaceTag__, result__, hostTag__, rate__) \ - { \ - CsrWifiRouterMaPacketCfm *msg__; \ - CsrWifiRouterMaPacketCfmCreate(msg__, dst__, src__, interfaceTag__, result__, hostTag__, rate__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketCfmSend(dst__, interfaceTag__, result__, hostTag__, rate__) \ - CsrWifiRouterMaPacketCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, result__, hostTag__, rate__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketSubscribeReqSend - - DESCRIPTION - A task can use this primitive to subscribe for a particular OUI/protocol - and transmit and receive frames matching the subscription. - NOTE: Multiple subscriptions for a given protocol and OUI will result in - the first subscription receiving the data and not the subsequent - subscriptions. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - encapsulation - Specifies the encapsulation type, which will be used for the - subscription - protocol - Together with the OUI, specifies the protocol, which a task - wants to subscribe to - oui - Specifies the OUI for the protocol, which a task wants to - subscribe to - -*******************************************************************************/ -#define CsrWifiRouterMaPacketSubscribeReqCreate(msg__, dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketSubscribeReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->encapsulation = (encapsulation__); \ - msg__->protocol = (protocol__); \ - msg__->oui = (oui__); - -#define CsrWifiRouterMaPacketSubscribeReqSendTo(dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__) \ - { \ - CsrWifiRouterMaPacketSubscribeReq *msg__; \ - CsrWifiRouterMaPacketSubscribeReqCreate(msg__, dst__, src__, interfaceTag__, encapsulation__, protocol__, oui__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketSubscribeReqSend(src__, interfaceTag__, encapsulation__, protocol__, oui__) \ - CsrWifiRouterMaPacketSubscribeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, encapsulation__, protocol__, oui__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketSubscribeCfmSend - - DESCRIPTION - The router sends this primitive to confirm the result of the - subscription. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - Handle to the subscription - This handle must be used in all subsequent requests - status - Status of the operation - allocOffset - Size of the offset for the frames of the subscription - -*******************************************************************************/ -#define CsrWifiRouterMaPacketSubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketSubscribeCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->subscriptionHandle = (subscriptionHandle__); \ - msg__->status = (status__); \ - msg__->allocOffset = (allocOffset__); - -#define CsrWifiRouterMaPacketSubscribeCfmSendTo(dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ - { \ - CsrWifiRouterMaPacketSubscribeCfm *msg__; \ - CsrWifiRouterMaPacketSubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__, status__, allocOffset__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketSubscribeCfmSend(dst__, interfaceTag__, subscriptionHandle__, status__, allocOffset__) \ - CsrWifiRouterMaPacketSubscribeCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, subscriptionHandle__, status__, allocOffset__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketUnsubscribeReqSend - - DESCRIPTION - A task sends this primitive to unsubscribe a subscription - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - -*******************************************************************************/ -#define CsrWifiRouterMaPacketUnsubscribeReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketUnsubscribeReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->subscriptionHandle = (subscriptionHandle__); - -#define CsrWifiRouterMaPacketUnsubscribeReqSendTo(dst__, src__, interfaceTag__, subscriptionHandle__) \ - { \ - CsrWifiRouterMaPacketUnsubscribeReq *msg__; \ - CsrWifiRouterMaPacketUnsubscribeReqCreate(msg__, dst__, src__, interfaceTag__, subscriptionHandle__); \ - CsrMsgTransport(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketUnsubscribeReqSend(src__, interfaceTag__, subscriptionHandle__) \ - CsrWifiRouterMaPacketUnsubscribeReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, subscriptionHandle__) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketUnsubscribeCfmSend - - DESCRIPTION - The router sends this primitive to confirm the result of the - unsubscription. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Status of the operation - -*******************************************************************************/ -#define CsrWifiRouterMaPacketUnsubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiRouterMaPacketUnsubscribeCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_PRIM, CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiRouterMaPacketUnsubscribeCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiRouterMaPacketUnsubscribeCfm *msg__; \ - CsrWifiRouterMaPacketUnsubscribeCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_PRIM, msg__); \ - } - -#define CsrWifiRouterMaPacketUnsubscribeCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiRouterMaPacketUnsubscribeCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, interfaceTag__, status__) - -#endif /* CSR_WIFI_ROUTER_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_prim.h b/drivers/staging/csr/csr_wifi_router_prim.h deleted file mode 100644 index c52344b51f2f..000000000000 --- a/drivers/staging/csr/csr_wifi_router_prim.h +++ /dev/null @@ -1,421 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_PRIM_H__ -#define CSR_WIFI_ROUTER_PRIM_H__ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" - -#define CSR_WIFI_ROUTER_PRIM (0x0400) - -typedef CsrPrim CsrWifiRouterPrim; - -typedef void (*CsrWifiRouterFrameFreeFunction)(void *frame); - -/******************************************************************************* - - NAME - CsrWifiRouterAppType - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_APP_TYPE_SME - - CSR_WIFI_ROUTER_APP_TYPE_PAL - - CSR_WIFI_ROUTER_APP_TYPE_NME - - CSR_WIFI_ROUTER_APP_TYPE_OTHER - - -*******************************************************************************/ -typedef u8 CsrWifiRouterAppType; -#define CSR_WIFI_ROUTER_APP_TYPE_SME ((CsrWifiRouterAppType) 0x0) -#define CSR_WIFI_ROUTER_APP_TYPE_PAL ((CsrWifiRouterAppType) 0x1) -#define CSR_WIFI_ROUTER_APP_TYPE_NME ((CsrWifiRouterAppType) 0x2) -#define CSR_WIFI_ROUTER_APP_TYPE_OTHER ((CsrWifiRouterAppType) 0x3) - -/******************************************************************************* - - NAME - CsrWifiRouterEncapsulation - - DESCRIPTION - Indicates the type of encapsulation used for the subscription - - VALUES - CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET - - Ethernet encapsulation - CSR_WIFI_ROUTER_ENCAPSULATION_LLC_SNAP - - LLC/SNAP encapsulation - -*******************************************************************************/ -typedef u8 CsrWifiRouterEncapsulation; -#define CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET ((CsrWifiRouterEncapsulation) 0x00) -#define CSR_WIFI_ROUTER_ENCAPSULATION_LLC_SNAP ((CsrWifiRouterEncapsulation) 0x01) - -/******************************************************************************* - - NAME - CsrWifiRouterOui - - DESCRIPTION - - VALUES - CSR_WIFI_ROUTER_OUI_RFC_1042 - - CSR_WIFI_ROUTER_OUI_BT - - -*******************************************************************************/ -typedef u32 CsrWifiRouterOui; -#define CSR_WIFI_ROUTER_OUI_RFC_1042 ((CsrWifiRouterOui) 0x000000) -#define CSR_WIFI_ROUTER_OUI_BT ((CsrWifiRouterOui) 0x001958) - -/******************************************************************************* - - NAME - CsrWifiRouterPriority - - DESCRIPTION - As defined in the IEEE 802.11 standards - - VALUES - CSR_WIFI_ROUTER_PRIORITY_QOS_UP0 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP1 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP2 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP3 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP4 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP5 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP6 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_QOS_UP7 - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_CONTENTION - - See IEEE 802.11 Standard - CSR_WIFI_ROUTER_PRIORITY_MANAGEMENT - - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef u16 CsrWifiRouterPriority; -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP0 ((CsrWifiRouterPriority) 0x0000) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP1 ((CsrWifiRouterPriority) 0x0001) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP2 ((CsrWifiRouterPriority) 0x0002) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP3 ((CsrWifiRouterPriority) 0x0003) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP4 ((CsrWifiRouterPriority) 0x0004) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP5 ((CsrWifiRouterPriority) 0x0005) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP6 ((CsrWifiRouterPriority) 0x0006) -#define CSR_WIFI_ROUTER_PRIORITY_QOS_UP7 ((CsrWifiRouterPriority) 0x0007) -#define CSR_WIFI_ROUTER_PRIORITY_CONTENTION ((CsrWifiRouterPriority) 0x8000) -#define CSR_WIFI_ROUTER_PRIORITY_MANAGEMENT ((CsrWifiRouterPriority) 0x8010) - - -/* Downstream */ -#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_REQ ((CsrWifiRouterPrim) (0x0000 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_REQ ((CsrWifiRouterPrim) (0x0001 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_REQ ((CsrWifiRouterPrim) (0x0002 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_RES ((CsrWifiRouterPrim) (0x0003 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_CANCEL_REQ ((CsrWifiRouterPrim) (0x0004 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_HIGHEST (0x0004 + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_ROUTER_MA_PACKET_SUBSCRIBE_CFM ((CsrWifiRouterPrim)(0x0000 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_UNSUBSCRIBE_CFM ((CsrWifiRouterPrim)(0x0001 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_CFM ((CsrWifiRouterPrim)(0x0002 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_ROUTER_MA_PACKET_IND ((CsrWifiRouterPrim)(0x0003 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_HIGHEST (0x0003 + CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT (CSR_WIFI_ROUTER_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketSubscribeReq - - DESCRIPTION - A task can use this primitive to subscribe for a particular OUI/protocol - and transmit and receive frames matching the subscription. - NOTE: Multiple subscriptions for a given protocol and OUI will result in - the first subscription receiving the data and not the subsequent - subscriptions. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - encapsulation - Specifies the encapsulation type, which will be used for the - subscription - protocol - Together with the OUI, specifies the protocol, which a task - wants to subscribe to - oui - Specifies the OUI for the protocol, which a task wants to - subscribe to - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiRouterEncapsulation encapsulation; - u16 protocol; - u32 oui; -} CsrWifiRouterMaPacketSubscribeReq; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketUnsubscribeReq - - DESCRIPTION - A task sends this primitive to unsubscribe a subscription - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 subscriptionHandle; -} CsrWifiRouterMaPacketUnsubscribeReq; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketReq - - DESCRIPTION - A task sends this primitive to transmit a frame. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - frameLength - Length of the frame to be sent in bytes - frame - Pointer to the frame to be sent - freeFunction - Pointer to function to be used to free the frame - priority - Priority of the frame, which should be sent - hostTag - An application shall set the bits b31..b28 using one of - the CSR_WIFI_ROUTER_APP_TYPE_* masks. Bits b0..b27 can - be used by the requestor without any restrictions, but - the hostTag shall be unique so the hostTag for - CSR_WIFI_ROUTER_APP _TYPE_OTHER should be constructured - in the following way [ CSR_WIFI_ROUTER_APP_TYPE_OTHER - (4 bits) | SubscriptionHandle (8 bits) | Sequence no. - (20 bits) ]. If the hostTag is not unique, the - behaviour of the system is unpredicatable with respect - to data/management frame transfer. - cfmRequested - Indicates if the requestor needs a confirm for packet - requests sent under this subscription. If set to TRUE, - the router will send a confirm, else it will not send - any confirm - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 subscriptionHandle; - u16 frameLength; - u8 *frame; - CsrWifiRouterFrameFreeFunction freeFunction; - CsrWifiRouterPriority priority; - u32 hostTag; - u8 cfmRequested; -} CsrWifiRouterMaPacketReq; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketRes - - DESCRIPTION - A task send this primitive to confirm the reception of the received - frame. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - result - Status of the operation - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 subscriptionHandle; - CsrResult result; -} CsrWifiRouterMaPacketRes; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketCancelReq - - DESCRIPTION - This primitive is used to request cancellation of a previously send - CsrWifiRouterMaPacketReq. - The frame may already have been transmitted so there is no guarantees - that the CsrWifiRouterMaPacketCancelReq actually cancels the transmission - of the frame in question. - If the cancellation fails, the Router will send, if required, - CsrWifiRouterMaPacketCfm. - If the cancellation succeeds, the Router will not send - CsrWifiRouterMaPacketCfm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - hostTag - The hostTag for the frame, which should be cancelled. - priority - Priority of the frame, which should be cancelled - peerMacAddress - Destination MAC address of the frame, which should be - cancelled - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u32 hostTag; - CsrWifiRouterPriority priority; - CsrWifiMacAddress peerMacAddress; -} CsrWifiRouterMaPacketCancelReq; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketSubscribeCfm - - DESCRIPTION - The router sends this primitive to confirm the result of the - subscription. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - Handle to the subscription - This handle must be used in all subsequent requests - status - Status of the operation - allocOffset - Size of the offset for the frames of the subscription - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 subscriptionHandle; - CsrResult status; - u16 allocOffset; -} CsrWifiRouterMaPacketSubscribeCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketUnsubscribeCfm - - DESCRIPTION - The router sends this primitive to confirm the result of the - unsubscription. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Status of the operation - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiRouterMaPacketUnsubscribeCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketCfm - - DESCRIPTION - The router sends the primitive to confirm the result of the transmission - of the packet of the corresponding CSR_WIFI_ROUTER MA_PACKET_REQ request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - result - Status of the operation - hostTag - The hostTrag will match the hostTag sent in the request. - rate - Transmission/Reception rate - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult result; - u32 hostTag; - u16 rate; -} CsrWifiRouterMaPacketCfm; - -/******************************************************************************* - - NAME - CsrWifiRouterMaPacketInd - - DESCRIPTION - The router sends the primitive to a subscribed task when it receives a - frame matching the subscription. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - subscriptionHandle - The handle of the subscription - result - Status of the operation - frameLength - Length of the received frame in bytes - frame - Pointer to the received frame - freeFunction - Pointer to function to be used to free the frame - rssi - Received signal strength indication in dBm - snr - Signal to Noise Ratio - rate - Transmission/Reception rate - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 subscriptionHandle; - CsrResult result; - u16 frameLength; - u8 *frame; - CsrWifiRouterFrameFreeFunction freeFunction; - s16 rssi; - s16 snr; - u16 rate; -} CsrWifiRouterMaPacketInd; - -#endif /* CSR_WIFI_ROUTER_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_sef.c b/drivers/staging/csr/csr_wifi_router_sef.c deleted file mode 100644 index 45a10fb77296..000000000000 --- a/drivers/staging/csr/csr_wifi_router_sef.c +++ /dev/null @@ -1,19 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#include "csr_wifi_router_sef.h" - -const CsrWifiRouterStateHandlerType CsrWifiRouterDownstreamStateHandlers[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT] = -{ - /* 0x0000 */ CsrWifiRouterMaPacketSubscribeReqHandler, - /* 0x0001 */ CsrWifiRouterMaPacketUnsubscribeReqHandler, - /* 0x0002 */ CsrWifiRouterMaPacketReqHandler, - /* 0x0003 */ CsrWifiRouterMaPacketResHandler, - /* 0x0004 */ CsrWifiRouterMaPacketCancelReqHandler, -}; diff --git a/drivers/staging/csr/csr_wifi_router_sef.h b/drivers/staging/csr/csr_wifi_router_sef.h deleted file mode 100644 index 86692c7780c9..000000000000 --- a/drivers/staging/csr/csr_wifi_router_sef.h +++ /dev/null @@ -1,25 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ -#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ - -#include "csr_wifi_router_prim.h" - - typedef void (*CsrWifiRouterStateHandlerType)(void* drvpriv, CsrWifiFsmEvent* msg); - - extern const CsrWifiRouterStateHandlerType CsrWifiRouterDownstreamStateHandlers[CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT]; - - extern void CsrWifiRouterMaPacketSubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterMaPacketUnsubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg); - extern void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg); - -#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_ROUTER_H__ */ diff --git a/drivers/staging/csr/csr_wifi_router_serialize.c b/drivers/staging/csr/csr_wifi_router_serialize.c deleted file mode 100644 index 4eccf5d6c289..000000000000 --- a/drivers/staging/csr/csr_wifi_router_serialize.c +++ /dev/null @@ -1,418 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_msgconv.h" -#include "csr_wifi_router_prim.h" -#include "csr_wifi_router_serialize.h" - -void CsrWifiRouterPfree(void *ptr) -{ - kfree(ptr); -} - - -size_t CsrWifiRouterMaPacketSubscribeReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 12) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiRouterEncapsulation primitive->encapsulation */ - bufferSize += 2; /* u16 primitive->protocol */ - bufferSize += 4; /* u32 primitive->oui */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketSubscribeReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketSubscribeReq *primitive = (CsrWifiRouterMaPacketSubscribeReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->encapsulation); - CsrUint16Ser(ptr, len, (u16) primitive->protocol); - CsrUint32Ser(ptr, len, (u32) primitive->oui); - return(ptr); -} - - -void* CsrWifiRouterMaPacketSubscribeReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketSubscribeReq *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketSubscribeReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->encapsulation, buffer, &offset); - CsrUint16Des((u16 *) &primitive->protocol, buffer, &offset); - CsrUint32Des((u32 *) &primitive->oui, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketReqSizeof(void *msg) -{ - CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 20) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->subscriptionHandle */ - bufferSize += 2; /* u16 primitive->frameLength */ - bufferSize += primitive->frameLength; /* u8 primitive->frame */ - bufferSize += 4; /* CsrWifiRouterFrameFreeFunction primitive->freeFunction */ - bufferSize += 2; /* CsrWifiRouterPriority primitive->priority */ - bufferSize += 4; /* u32 primitive->hostTag */ - bufferSize += 1; /* u8 primitive->cfmRequested */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->subscriptionHandle); - CsrUint16Ser(ptr, len, (u16) primitive->frameLength); - if (primitive->frameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->frame, ((u16) (primitive->frameLength))); - } - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->freeFunction */ - CsrUint16Ser(ptr, len, (u16) primitive->priority); - CsrUint32Ser(ptr, len, (u32) primitive->hostTag); - CsrUint8Ser(ptr, len, (u8) primitive->cfmRequested); - return(ptr); -} - - -void* CsrWifiRouterMaPacketReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketReq *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->subscriptionHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->frameLength, buffer, &offset); - if (primitive->frameLength) - { - primitive->frame = kmalloc(primitive->frameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->frame, buffer, &offset, ((u16) (primitive->frameLength))); - } - else - { - primitive->frame = NULL; - } - primitive->freeFunction = NULL; /* Special for Function Pointers... */ - offset += 4; - CsrUint16Des((u16 *) &primitive->priority, buffer, &offset); - CsrUint32Des((u32 *) &primitive->hostTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->cfmRequested, buffer, &offset); - - return primitive; -} - - -void CsrWifiRouterMaPacketReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterMaPacketReq *primitive = (CsrWifiRouterMaPacketReq *) voidPrimitivePointer; - kfree(primitive->frame); - kfree(primitive); -} - - -size_t CsrWifiRouterMaPacketResSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->subscriptionHandle */ - bufferSize += 2; /* CsrResult primitive->result */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketResSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketRes *primitive = (CsrWifiRouterMaPacketRes *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->subscriptionHandle); - CsrUint16Ser(ptr, len, (u16) primitive->result); - return(ptr); -} - - -void* CsrWifiRouterMaPacketResDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketRes *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketRes), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->subscriptionHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketCancelReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 4; /* u32 primitive->hostTag */ - bufferSize += 2; /* CsrWifiRouterPriority primitive->priority */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketCancelReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketCancelReq *primitive = (CsrWifiRouterMaPacketCancelReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint32Ser(ptr, len, (u32) primitive->hostTag); - CsrUint16Ser(ptr, len, (u16) primitive->priority); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiRouterMaPacketCancelReqDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketCancelReq *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketCancelReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint32Des((u32 *) &primitive->hostTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->priority, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketSubscribeCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->subscriptionHandle */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->allocOffset */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketSubscribeCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketSubscribeCfm *primitive = (CsrWifiRouterMaPacketSubscribeCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->subscriptionHandle); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->allocOffset); - return(ptr); -} - - -void* CsrWifiRouterMaPacketSubscribeCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketSubscribeCfm *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketSubscribeCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->subscriptionHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->allocOffset, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketUnsubscribeCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketUnsubscribeCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketUnsubscribeCfm *primitive = (CsrWifiRouterMaPacketUnsubscribeCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiRouterMaPacketUnsubscribeCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketUnsubscribeCfm *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketUnsubscribeCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->result */ - bufferSize += 4; /* u32 primitive->hostTag */ - bufferSize += 2; /* u16 primitive->rate */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketCfm *primitive = (CsrWifiRouterMaPacketCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->result); - CsrUint32Ser(ptr, len, (u32) primitive->hostTag); - CsrUint16Ser(ptr, len, (u16) primitive->rate); - return(ptr); -} - - -void* CsrWifiRouterMaPacketCfmDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketCfm *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result, buffer, &offset); - CsrUint32Des((u32 *) &primitive->hostTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->rate, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiRouterMaPacketIndSizeof(void *msg) -{ - CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 21) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->subscriptionHandle */ - bufferSize += 2; /* CsrResult primitive->result */ - bufferSize += 2; /* u16 primitive->frameLength */ - bufferSize += primitive->frameLength; /* u8 primitive->frame */ - bufferSize += 4; /* CsrWifiRouterFrameFreeFunction primitive->freeFunction */ - bufferSize += 2; /* s16 primitive->rssi */ - bufferSize += 2; /* s16 primitive->snr */ - bufferSize += 2; /* u16 primitive->rate */ - return bufferSize; -} - - -u8* CsrWifiRouterMaPacketIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->subscriptionHandle); - CsrUint16Ser(ptr, len, (u16) primitive->result); - CsrUint16Ser(ptr, len, (u16) primitive->frameLength); - if (primitive->frameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->frame, ((u16) (primitive->frameLength))); - } - CsrUint32Ser(ptr, len, 0); /* Special for Function Pointers... primitive->freeFunction */ - CsrUint16Ser(ptr, len, (u16) primitive->rssi); - CsrUint16Ser(ptr, len, (u16) primitive->snr); - CsrUint16Ser(ptr, len, (u16) primitive->rate); - return(ptr); -} - - -void* CsrWifiRouterMaPacketIndDes(u8 *buffer, size_t length) -{ - CsrWifiRouterMaPacketInd *primitive = kmalloc(sizeof(CsrWifiRouterMaPacketInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->subscriptionHandle, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result, buffer, &offset); - CsrUint16Des((u16 *) &primitive->frameLength, buffer, &offset); - if (primitive->frameLength) - { - primitive->frame = kmalloc(primitive->frameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->frame, buffer, &offset, ((u16) (primitive->frameLength))); - } - else - { - primitive->frame = NULL; - } - primitive->freeFunction = NULL; /* Special for Function Pointers... */ - offset += 4; - CsrUint16Des((u16 *) &primitive->rssi, buffer, &offset); - CsrUint16Des((u16 *) &primitive->snr, buffer, &offset); - CsrUint16Des((u16 *) &primitive->rate, buffer, &offset); - - return primitive; -} - - -void CsrWifiRouterMaPacketIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiRouterMaPacketInd *primitive = (CsrWifiRouterMaPacketInd *) voidPrimitivePointer; - kfree(primitive->frame); - kfree(primitive); -} - - diff --git a/drivers/staging/csr/csr_wifi_router_serialize.h b/drivers/staging/csr/csr_wifi_router_serialize.h deleted file mode 100644 index 94ccdac5606f..000000000000 --- a/drivers/staging/csr/csr_wifi_router_serialize.h +++ /dev/null @@ -1,67 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_SERIALIZE_H__ -#define CSR_WIFI_ROUTER_SERIALIZE_H__ - -#include "csr_wifi_msgconv.h" -#include "csr_wifi_router_prim.h" - -extern void CsrWifiRouterPfree(void *ptr); - -extern u8* CsrWifiRouterMaPacketSubscribeReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketSubscribeReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketSubscribeReqSizeof(void *msg); -#define CsrWifiRouterMaPacketSubscribeReqSerFree CsrWifiRouterPfree - -#define CsrWifiRouterMaPacketUnsubscribeReqSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiRouterMaPacketUnsubscribeReqDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiRouterMaPacketUnsubscribeReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiRouterMaPacketUnsubscribeReqSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketReqSizeof(void *msg); -extern void CsrWifiRouterMaPacketReqSerFree(void *msg); - -extern u8* CsrWifiRouterMaPacketResSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketResDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketResSizeof(void *msg); -#define CsrWifiRouterMaPacketResSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketCancelReqSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketCancelReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketCancelReqSizeof(void *msg); -#define CsrWifiRouterMaPacketCancelReqSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketSubscribeCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketSubscribeCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketSubscribeCfmSizeof(void *msg); -#define CsrWifiRouterMaPacketSubscribeCfmSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketUnsubscribeCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketUnsubscribeCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketUnsubscribeCfmSizeof(void *msg); -#define CsrWifiRouterMaPacketUnsubscribeCfmSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketCfmSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketCfmSizeof(void *msg); -#define CsrWifiRouterMaPacketCfmSerFree CsrWifiRouterPfree - -extern u8* CsrWifiRouterMaPacketIndSer(u8 *ptr, size_t *len, void *msg); -extern void* CsrWifiRouterMaPacketIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiRouterMaPacketIndSizeof(void *msg); -extern void CsrWifiRouterMaPacketIndSerFree(void *msg); - -#endif /* CSR_WIFI_ROUTER_SERIALIZE_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_task.h b/drivers/staging/csr/csr_wifi_router_task.h deleted file mode 100644 index 9ba892f34e6d..000000000000 --- a/drivers/staging/csr/csr_wifi_router_task.h +++ /dev/null @@ -1,25 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_ROUTER_TASK_H__ -#define CSR_WIFI_ROUTER_TASK_H__ - -#include "csr_sched.h" - -#define CSR_WIFI_ROUTER_LOG_ID 0x1201FFFF -extern CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE; -void CsrWifiRouterInit(void **gash); -void CsrWifiRouterDeinit(void **gash); -void CsrWifiRouterHandler(void **gash); - -#endif /* CSR_WIFI_ROUTER_TASK_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_router_transport.c b/drivers/staging/csr/csr_wifi_router_transport.c deleted file mode 100644 index e905ead9389b..000000000000 --- a/drivers/staging/csr/csr_wifi_router_transport.c +++ /dev/null @@ -1,199 +0,0 @@ -/** @file router_transport.c - * - * - * Copyright (C) Cambridge Silicon Radio Ltd 2006-2010. All rights reserved. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - ****************************************************************************/ - -#include "unifi_priv.h" - -#include "csr_sched.h" -#include "csr_msgconv.h" - -#include "sme_userspace.h" - -#include "csr_wifi_hostio_prim.h" -#include "csr_wifi_router_lib.h" -#include "csr_wifi_router_sef.h" -#include "csr_wifi_router_converter_init.h" -#include "csr_wifi_router_ctrl_lib.h" -#include "csr_wifi_router_ctrl_sef.h" -#include "csr_wifi_router_ctrl_converter_init.h" -#include "csr_wifi_sme_prim.h" -#include "csr_wifi_sme_sef.h" -#include "csr_wifi_sme_converter_init.h" -#ifdef CSR_SUPPORT_WEXT -#ifdef CSR_SUPPORT_WEXT_AP -#include "csr_wifi_nme_ap_prim.h" -#include "csr_wifi_nme_ap_sef.h" -#include "csr_wifi_nme_ap_converter_init.h" -#endif -#endif - -static unifi_priv_t *drvpriv = NULL; -void CsrWifiRouterTransportInit(unifi_priv_t *priv) -{ - unifi_trace(priv, UDBG1, "CsrWifiRouterTransportInit: \n"); - - drvpriv = priv; - (void)CsrMsgConvInit(); - CsrWifiRouterConverterInit(); - CsrWifiRouterCtrlConverterInit(); - CsrWifiSmeConverterInit(); -#ifdef CSR_SUPPORT_WEXT -#ifdef CSR_SUPPORT_WEXT_AP - CsrWifiNmeApConverterInit(); -#endif -#endif -} - -void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8* buffer, size_t bufferLength) -{ - CsrMsgConvMsgEntry* msgEntry; - u16 primType; - CsrSchedQid src; - CsrSchedQid dest; - u16 msgType; - size_t offset = 0; - CsrWifiFsmEvent* msg; - - /* Decode the prim and message type */ - CsrUint16Des(&primType, buffer, &offset); - CsrUint16Des(&src, buffer, &offset); - CsrUint16Des(&dest, buffer, &offset); - CsrUint16Des(&msgType, buffer, &offset); - offset -= 2; /* Adjust as the Deserialise Function will read this as well */ - - unifi_trace(priv, UDBG4, "CsrWifiRouterTransportRecv: primType=0x%.4X, msgType=0x%.4X, bufferLength=%d\n", - primType, msgType, bufferLength); - - /* Special handling for HOSTIO messages.... */ - if (primType == CSR_WIFI_HOSTIO_PRIM) - { - CsrWifiRouterCtrlHipReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, CSR_WIFI_ROUTER_CTRL_PRIM, dest, src, NULL}, 0, NULL, 0, NULL, 0, NULL}; - - req.mlmeCommandLength = bufferLength; - req.mlmeCommand = buffer; - - offset += 8;/* Skip the id, src, dest and slot number */ - CsrUint16Des(&req.dataRef1Length, buffer, &offset); - offset += 2; /* Skip the slot number */ - CsrUint16Des(&req.dataRef2Length, buffer, &offset); - - if (req.dataRef1Length) - { - u16 dr1Offset = (bufferLength - req.dataRef2Length) - req.dataRef1Length; - req.dataRef1 = &buffer[dr1Offset]; - } - - if (req.dataRef2Length) - { - u16 dr2Offset = bufferLength - req.dataRef2Length; - req.dataRef2 = &buffer[dr2Offset]; - } - - /* Copy the hip data but strip off the prim type */ - req.mlmeCommandLength -= (req.dataRef1Length + req.dataRef2Length + 6); - req.mlmeCommand = &buffer[6]; - - CsrWifiRouterCtrlHipReqHandler(priv, &req.common); - return; - } - - msgEntry = CsrMsgConvFindEntry(primType, msgType); - if (!msgEntry) - { - unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n", - primType, msgType); - dump(buffer, bufferLength); - return; - } - - msg = (CsrWifiFsmEvent*)(msgEntry->deserFunc)(&buffer[offset], bufferLength - offset); - - msg->primtype = primType; - msg->type = msgType; - msg->source = src; - msg->destination = dest; - - switch(primType) - { - case CSR_WIFI_ROUTER_CTRL_PRIM: - CsrWifiRouterCtrlDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST](priv, msg); - CsrWifiRouterCtrlFreeDownstreamMessageContents(CSR_WIFI_ROUTER_CTRL_PRIM, msg); - break; - case CSR_WIFI_ROUTER_PRIM: - CsrWifiRouterDownstreamStateHandlers[msg->type - CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_LOWEST](priv, msg); - CsrWifiRouterFreeDownstreamMessageContents(CSR_WIFI_ROUTER_PRIM, msg); - break; - case CSR_WIFI_SME_PRIM: - CsrWifiSmeUpstreamStateHandlers[msg->type - CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST](priv, msg); - CsrWifiSmeFreeUpstreamMessageContents(CSR_WIFI_SME_PRIM, msg); - break; -#ifdef CSR_SUPPORT_WEXT -#ifdef CSR_SUPPORT_WEXT_AP - case CSR_WIFI_NME_AP_PRIM: - CsrWifiNmeApUpstreamStateHandlers(priv, msg); - CsrWifiNmeApFreeUpstreamMessageContents(CSR_WIFI_NME_AP_PRIM, msg); - break; -#endif -#endif - default: - unifi_error(priv, "CsrWifiRouterTransportDeserialiseAndSend unhandled prim type 0x%.4X\n", primType); - break; - } - kfree(msg); -} - -static void CsrWifiRouterTransportSerialiseAndSend(u16 primType, void* msg) -{ - CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)msg; - CsrMsgConvMsgEntry* msgEntry; - size_t msgSize; - size_t encodeBufferLen = 0; - size_t offset = 0; - u8* encodeBuffer; - - unifi_trace(drvpriv, UDBG4, "CsrWifiRouterTransportSerialiseAndSend: primType=0x%.4X, msgType=0x%.4X\n", - primType, evt->type); - - msgEntry = CsrMsgConvFindEntry(primType, evt->type); - if (!msgEntry) - { - unifi_error(drvpriv, "CsrWifiRouterTransportSerialiseAndSend can not process the message. primType=0x%.4X, msgType=0x%.4X\n", - primType, evt->type); - return; - } - - msgSize = 6 + (msgEntry->sizeofFunc)((void*)msg); - - encodeBuffer = kmalloc(msgSize, GFP_KERNEL); - - /* Encode PrimType */ - CsrUint16Ser(encodeBuffer, &encodeBufferLen, primType); - CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->source); - CsrUint16Ser(encodeBuffer, &encodeBufferLen, evt->destination); - - (void)(msgEntry->serFunc)(&encodeBuffer[encodeBufferLen], &offset, msg); - encodeBufferLen += offset; - - uf_sme_queue_message(drvpriv, encodeBuffer, encodeBufferLen); - - /* Do not use msgEntry->freeFunc because the memory is owned by the driver */ - kfree(msg); -} - -#if defined(CSR_LOG_ENABLE) && defined(CSR_LOG_INCLUDE_FILE_NAME_AND_LINE_NUMBER) -void CsrSchedMessagePutStringLog(CsrSchedQid q, u16 mi, void *mv, u32 line, char *file) -#else -void CsrSchedMessagePut(CsrSchedQid q, u16 mi, void *mv) -#endif -{ - CsrWifiFsmEvent* evt = (CsrWifiFsmEvent*)mv; - evt->destination = q; - CsrWifiRouterTransportSerialiseAndSend(mi, mv); -} - diff --git a/drivers/staging/csr/csr_wifi_serialize_primitive_types.c b/drivers/staging/csr/csr_wifi_serialize_primitive_types.c deleted file mode 100644 index dd93d0061190..000000000000 --- a/drivers/staging/csr/csr_wifi_serialize_primitive_types.c +++ /dev/null @@ -1,256 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#include -#include -#include "csr_macro.h" -#include "csr_msgconv.h" -#include "csr_wifi_msgconv.h" -#include "csr_wifi_lib.h" - -void CsrUint24Des(u32 *v, u8 *buffer, size_t *offset) -{ - u32 val; - - val = ((buffer[(*offset) + 2] << 16) | - (buffer[(*offset) + 1] << 8) | - (buffer[(*offset)])); - - *offset += 3; - *v = val; -} - - -/* Big endian :e.g WSC, TCLAS */ -void CsrUint16DesBigEndian(u16 *v, u8 *buffer, size_t *offset) -{ - u16 val; - - val = (buffer[(*offset)] << 8) | (buffer[(*offset) + 1]); - *offset += 2; - - *v = val; -} - - -void CsrUint24DesBigEndian(u32 *v, u8 *buffer, size_t *offset) -{ - u32 val; - - val = ((buffer[(*offset)] << 16) | - (buffer[(*offset) + 1] << 8) | - (buffer[(*offset) + 2])); - - *offset += 3; - *v = val; -} - - -void CsrUint32DesBigEndian(u32 *v, u8 *buffer, size_t *offset) -{ - u32 val; - - val = ((buffer[(*offset)] << 24) | - (buffer[(*offset) + 1] << 16) | - (buffer[(*offset) + 2] << 8) | - (buffer[(*offset) + 3])); - - *offset += 4; - *v = val; -} - - -void CsrUint24Ser(u8 *ptr, size_t *len, u32 v) -{ - ptr[(*len) + 2] = (u8)((v & 0x00ff0000) >> 16); - ptr[(*len) + 1] = (u8)((v & 0x0000ff00) >> 8); - ptr[(*len)] = (u8)((v & 0x000000ff)); - - *len += 3; -} - - -/* Big endian :e.g WSC, TCLAS */ -void CsrUint16SerBigEndian(u8 *ptr, size_t *len, u16 v) -{ - ptr[(*len)] = (u8)((v & 0xff00) >> 8); - ptr[(*len) + 1] = (u8)((v & 0x00ff)); - - *len += 2; -} - - -void CsrUint32SerBigEndian(u8 *ptr, size_t *len, u32 v) -{ - ptr[(*len)] = (u8)((v & 0xff000000) >> 24); - ptr[(*len) + 1] = (u8)((v & 0x00ff0000) >> 16); - ptr[(*len) + 2] = (u8)((v & 0x0000ff00) >> 8); - ptr[(*len) + 3] = (u8)((v & 0x000000ff)); - - *len += 4; -} - - -void CsrUint24SerBigEndian(u8 *ptr, size_t *len, u32 v) -{ - ptr[(*len)] = (u8)((v & 0x00ff0000) >> 16); - ptr[(*len) + 1] = (u8)((v & 0x0000ff00) >> 8); - ptr[(*len) + 2] = (u8)((v & 0x000000ff)); - - *len += 3; -} - - -size_t CsrWifiEventSizeof(void *msg) -{ - return 2; -} -EXPORT_SYMBOL_GPL(CsrWifiEventSizeof); - -u8* CsrWifiEventSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiFsmEvent *primitive = (CsrWifiFsmEvent *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->type); - return(ptr); -} -EXPORT_SYMBOL_GPL(CsrWifiEventSer); - -void* CsrWifiEventDes(u8 *buffer, size_t length) -{ - CsrWifiFsmEvent *primitive = kmalloc(sizeof(CsrWifiFsmEvent), GFP_KERNEL); - size_t offset = 0; - CsrUint16Des(&primitive->type, buffer, &offset); - - return primitive; -} -EXPORT_SYMBOL_GPL(CsrWifiEventDes); - -size_t CsrWifiEventCsrUint8Sizeof(void *msg) -{ - return 3; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Sizeof); - -u8* CsrWifiEventCsrUint8Ser(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiEventCsrUint8 *primitive = (CsrWifiEventCsrUint8 *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, primitive->value); - return(ptr); -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Ser); - - -void* CsrWifiEventCsrUint8Des(u8 *buffer, size_t length) -{ - CsrWifiEventCsrUint8 *primitive = kmalloc(sizeof(CsrWifiEventCsrUint8), GFP_KERNEL); - - size_t offset = 0; - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des(&primitive->value, buffer, &offset); - - return primitive; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint8Des); - - -size_t CsrWifiEventCsrUint16Sizeof(void *msg) -{ - return 4; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Sizeof); - - -u8* CsrWifiEventCsrUint16Ser(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiEventCsrUint16 *primitive = (CsrWifiEventCsrUint16 *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, primitive->value); - return(ptr); -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Ser); - -void* CsrWifiEventCsrUint16Des(u8 *buffer, size_t length) -{ - CsrWifiEventCsrUint16 *primitive = kmalloc(sizeof(CsrWifiEventCsrUint16), GFP_KERNEL); - - size_t offset = 0; - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des(&primitive->value, buffer, &offset); - - return primitive; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16Des); - - -size_t CsrWifiEventCsrUint32Sizeof(void *msg) -{ - return 6; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Sizeof); - -u8* CsrWifiEventCsrUint32Ser(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiEventCsrUint32 *primitive = (CsrWifiEventCsrUint32 *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint32Ser(ptr, len, primitive->value); - return(ptr); -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Ser); - - -void* CsrWifiEventCsrUint32Des(u8 *buffer, size_t length) -{ - CsrWifiEventCsrUint32 *primitive = kmalloc(sizeof(CsrWifiEventCsrUint32), GFP_KERNEL); - - size_t offset = 0; - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint32Des(&primitive->value, buffer, &offset); - - return primitive; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint32Des); - -size_t CsrWifiEventCsrUint16CsrUint8Sizeof(void *msg) -{ - return 5; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Sizeof); - -u8* CsrWifiEventCsrUint16CsrUint8Ser(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiEventCsrUint16CsrUint8 *primitive = (CsrWifiEventCsrUint16CsrUint8 *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, primitive->value16); - CsrUint8Ser(ptr, len, primitive->value8); - return(ptr); -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Ser); - - -void* CsrWifiEventCsrUint16CsrUint8Des(u8 *buffer, size_t length) -{ - CsrWifiEventCsrUint16CsrUint8 *primitive = kmalloc(sizeof(CsrWifiEventCsrUint16CsrUint8), GFP_KERNEL); - - size_t offset = 0; - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des(&primitive->value16, buffer, &offset); - CsrUint8Des(&primitive->value8, buffer, &offset); - - return primitive; -} -EXPORT_SYMBOL_GPL(CsrWifiEventCsrUint16CsrUint8Des); - - diff --git a/drivers/staging/csr/csr_wifi_sme_ap_lib.h b/drivers/staging/csr/csr_wifi_sme_ap_lib.h deleted file mode 100644 index 48ea9143f591..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_ap_lib.h +++ /dev/null @@ -1,774 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_AP_LIB_H__ -#define CSR_WIFI_SME_AP_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_sme_ap_prim.h" -#include "csr_wifi_sme_task.h" - -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_lib.h -#endif - -/*----------------------------------------------------------------------------* - * CsrWifiSmeApFreeUpstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_SME_AP upstream message. Does not - * free the message itself, and can only be used for upstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_SME_AP upstream message - *----------------------------------------------------------------------------*/ -void CsrWifiSmeApFreeUpstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * CsrWifiSmeApFreeDownstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_SME_AP downstream message. Does not - * free the message itself, and can only be used for downstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_SME_AP downstream message - *----------------------------------------------------------------------------*/ -void CsrWifiSmeApFreeDownstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * Enum to string functions - *----------------------------------------------------------------------------*/ -const char* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value); -const char* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value); -const char* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value); -const char* CsrWifiSmeApDirectionToString(CsrWifiSmeApDirection value); -const char* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value); -const char* CsrWifiSmeApTypeToString(CsrWifiSmeApType value); - - -/*----------------------------------------------------------------------------* - * CsrPrim Type toString function. - * Converts a message type to the String name of the Message - *----------------------------------------------------------------------------*/ -const char* CsrWifiSmeApPrimTypeToString(CsrPrim msgType); - -/*----------------------------------------------------------------------------* - * Lookup arrays for PrimType name Strings - *----------------------------------------------------------------------------*/ -extern const char *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT]; -extern const char *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT]; - -/******************************************************************************* - - NAME - CsrWifiSmeApActiveBaGetReqSend - - DESCRIPTION - This primitive used to retrieve information related to the active block - ack sessions - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - -*******************************************************************************/ -#define CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApActiveBaGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeApActiveBaGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeApActiveBaGetReq *msg__; \ - CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApActiveBaGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeApActiveBaGetReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeApActiveBaGetCfmSend - - DESCRIPTION - This primitive carries the information related to the active ba sessions - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - Reports the result of the request - activeBaCount - Number of active block ack session - activeBaSessions - Points to a buffer containing an array of - CsrWifiSmeApBaSession structures. - -*******************************************************************************/ -#define CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApActiveBaGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->activeBaCount = (activeBaCount__); \ - msg__->activeBaSessions = (activeBaSessions__); - -#define CsrWifiSmeApActiveBaGetCfmSendTo(dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ - { \ - CsrWifiSmeApActiveBaGetCfm *msg__; \ - CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApActiveBaGetCfmSend(dst__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \ - CsrWifiSmeApActiveBaGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, activeBaCount__, activeBaSessions__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBaDeleteReqSend - - DESCRIPTION - This primitive is used to delete an active block ack session - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - reason - - baSession - BA session to be deleted - -*******************************************************************************/ -#define CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBaDeleteReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->reason = (reason__); \ - msg__->baSession = (baSession__); - -#define CsrWifiSmeApBaDeleteReqSendTo(dst__, src__, interfaceTag__, reason__, baSession__) \ - { \ - CsrWifiSmeApBaDeleteReq *msg__; \ - CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBaDeleteReqSend(src__, interfaceTag__, reason__, baSession__) \ - CsrWifiSmeApBaDeleteReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, reason__, baSession__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBaDeleteCfmSend - - DESCRIPTION - This primitive confirms the BA is deleted - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - Reports the result of the request - baSession - deleted BA session - -*******************************************************************************/ -#define CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBaDeleteCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->baSession = (baSession__); - -#define CsrWifiSmeApBaDeleteCfmSendTo(dst__, src__, interfaceTag__, status__, baSession__) \ - { \ - CsrWifiSmeApBaDeleteCfm *msg__; \ - CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBaDeleteCfmSend(dst__, interfaceTag__, status__, baSession__) \ - CsrWifiSmeApBaDeleteCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, baSession__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStartReqSend - - DESCRIPTION - This primitive requests the SME to start AP or GO functionality - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - initialPresence - Set to 0, if Not in a group fomration phase, set to 1 , - during group formation phase - apType - apType : Legacy AP or P2PGO - cloakSsid - cloakSsid flag. - ssid - ssid. - ifIndex - Radio Interface - channel - channel. - maxConnections - Maximum Stations + P2PClients allowed - apCredentials - AP security credeitals used to advertise in beacon /probe - response - smeApConfig - AP configuration - p2pGoParam - P2P specific GO parameters. Ignored if it is a leagacy AP - -*******************************************************************************/ -#define CsrWifiSmeApBeaconingStartReqCreate(msg__, dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBeaconingStartReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_START_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->initialPresence = (initialPresence__); \ - msg__->apType = (apType__); \ - msg__->cloakSsid = (cloakSsid__); \ - msg__->ssid = (ssid__); \ - msg__->ifIndex = (ifIndex__); \ - msg__->channel = (channel__); \ - msg__->maxConnections = (maxConnections__); \ - msg__->apCredentials = (apCredentials__); \ - msg__->smeApConfig = (smeApConfig__); \ - msg__->p2pGoParam = (p2pGoParam__); - -#define CsrWifiSmeApBeaconingStartReqSendTo(dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ - { \ - CsrWifiSmeApBeaconingStartReq *msg__; \ - CsrWifiSmeApBeaconingStartReqCreate(msg__, dst__, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBeaconingStartReqSend(src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) \ - CsrWifiSmeApBeaconingStartReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, initialPresence__, apType__, cloakSsid__, ssid__, ifIndex__, channel__, maxConnections__, apCredentials__, smeApConfig__, p2pGoParam__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStartCfmSend - - DESCRIPTION - This primitive confirms the completion of the request along with the - status - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - secIeLength - - secIe - - -*******************************************************************************/ -#define CsrWifiSmeApBeaconingStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, secIeLength__, secIe__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBeaconingStartCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_START_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->secIeLength = (secIeLength__); \ - msg__->secIe = (secIe__); - -#define CsrWifiSmeApBeaconingStartCfmSendTo(dst__, src__, interfaceTag__, status__, secIeLength__, secIe__) \ - { \ - CsrWifiSmeApBeaconingStartCfm *msg__; \ - CsrWifiSmeApBeaconingStartCfmCreate(msg__, dst__, src__, interfaceTag__, status__, secIeLength__, secIe__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBeaconingStartCfmSend(dst__, interfaceTag__, status__, secIeLength__, secIe__) \ - CsrWifiSmeApBeaconingStartCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, secIeLength__, secIe__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStopReqSend - - DESCRIPTION - This primitive requests the SME to STOP AP or P2PGO operation - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - -*******************************************************************************/ -#define CsrWifiSmeApBeaconingStopReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBeaconingStopReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_STOP_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeApBeaconingStopReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeApBeaconingStopReq *msg__; \ - CsrWifiSmeApBeaconingStopReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBeaconingStopReqSend(src__, interfaceTag__) \ - CsrWifiSmeApBeaconingStopReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStopCfmSend - - DESCRIPTION - This primitive confirms AP or P2PGO operation is terminated - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiSmeApBeaconingStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApBeaconingStopCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BEACONING_STOP_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeApBeaconingStopCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeApBeaconingStopCfm *msg__; \ - CsrWifiSmeApBeaconingStopCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApBeaconingStopCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeApBeaconingStopCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeApErrorIndSend - - DESCRIPTION - This primitve is sent by SME to indicate some error in AP operationi - after AP operations were started successfully and continuing the AP - operation may lead to undesired behaviour. It is the responsibility of - the upper layers to stop AP operation if needed - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Range 0-1 - apType - - status - Contains the error status - -*******************************************************************************/ -#define CsrWifiSmeApErrorIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApErrorInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ERROR_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->apType = (apType__); \ - msg__->status = (status__); - -#define CsrWifiSmeApErrorIndSendTo(dst__, src__, interfaceTag__, apType__, status__) \ - { \ - CsrWifiSmeApErrorInd *msg__; \ - CsrWifiSmeApErrorIndCreate(msg__, dst__, src__, interfaceTag__, apType__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApErrorIndSend(dst__, interfaceTag__, apType__, status__) \ - CsrWifiSmeApErrorIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, apType__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeApStaConnectStartIndSend - - DESCRIPTION - This primitive indicates that a stations request to join the group/BSS is - accepted - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -#define CsrWifiSmeApStaConnectStartIndCreate(msg__, dst__, src__, interfaceTag__, peerMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApStaConnectStartInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_CONNECT_START_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->peerMacAddress = (peerMacAddress__); - -#define CsrWifiSmeApStaConnectStartIndSendTo(dst__, src__, interfaceTag__, peerMacAddress__) \ - { \ - CsrWifiSmeApStaConnectStartInd *msg__; \ - CsrWifiSmeApStaConnectStartIndCreate(msg__, dst__, src__, interfaceTag__, peerMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApStaConnectStartIndSend(dst__, interfaceTag__, peerMacAddress__) \ - CsrWifiSmeApStaConnectStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, peerMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiSmeApStaDisconnectReqSend - - DESCRIPTION - This primitive tells SME to deauth ot disassociate a particular station - within BSS - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - deauthReason - - disassocReason - - peerMacaddress - - keepBlocking - If TRUE, the station is blocked. If FALSE and the station - is connected, disconnect the station. If FALSE and the - station is not connected, no action is taken. - -*******************************************************************************/ -#define CsrWifiSmeApStaDisconnectReqCreate(msg__, dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApStaDisconnectReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_DISCONNECT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->deauthReason = (deauthReason__); \ - msg__->disassocReason = (disassocReason__); \ - msg__->peerMacaddress = (peerMacaddress__); \ - msg__->keepBlocking = (keepBlocking__); - -#define CsrWifiSmeApStaDisconnectReqSendTo(dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ - { \ - CsrWifiSmeApStaDisconnectReq *msg__; \ - CsrWifiSmeApStaDisconnectReqCreate(msg__, dst__, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApStaDisconnectReqSend(src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) \ - CsrWifiSmeApStaDisconnectReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, deauthReason__, disassocReason__, peerMacaddress__, keepBlocking__) - -/******************************************************************************* - - NAME - CsrWifiSmeApStaDisconnectCfmSend - - DESCRIPTION - This primitive confirms the station is disconnected - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - peerMacaddress - - -*******************************************************************************/ -#define CsrWifiSmeApStaDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, peerMacaddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApStaDisconnectCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_DISCONNECT_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->peerMacaddress = (peerMacaddress__); - -#define CsrWifiSmeApStaDisconnectCfmSendTo(dst__, src__, interfaceTag__, status__, peerMacaddress__) \ - { \ - CsrWifiSmeApStaDisconnectCfm *msg__; \ - CsrWifiSmeApStaDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__, peerMacaddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApStaDisconnectCfmSend(dst__, interfaceTag__, status__, peerMacaddress__) \ - CsrWifiSmeApStaDisconnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, peerMacaddress__) - -/******************************************************************************* - - NAME - CsrWifiSmeApStaNotifyIndSend - - DESCRIPTION - This primitive indicates that a station has joined or a previously joined - station has left the BSS/group - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - mediaStatus - - peerMacAddress - - peerDeviceAddress - - disassocReason - - deauthReason - - WpsRegistration - - secIeLength - - secIe - - groupKeyId - - seqNumber - - -*******************************************************************************/ -#define CsrWifiSmeApStaNotifyIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApStaNotifyInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_STA_NOTIFY_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->mediaStatus = (mediaStatus__); \ - msg__->peerMacAddress = (peerMacAddress__); \ - msg__->peerDeviceAddress = (peerDeviceAddress__); \ - msg__->disassocReason = (disassocReason__); \ - msg__->deauthReason = (deauthReason__); \ - msg__->WpsRegistration = (WpsRegistration__); \ - msg__->secIeLength = (secIeLength__); \ - msg__->secIe = (secIe__); \ - msg__->groupKeyId = (groupKeyId__); \ - memcpy(msg__->seqNumber, (seqNumber__), sizeof(u16) * 8); - -#define CsrWifiSmeApStaNotifyIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ - { \ - CsrWifiSmeApStaNotifyInd *msg__; \ - CsrWifiSmeApStaNotifyIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApStaNotifyIndSend(dst__, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) \ - CsrWifiSmeApStaNotifyIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, mediaStatus__, peerMacAddress__, peerDeviceAddress__, disassocReason__, deauthReason__, WpsRegistration__, secIeLength__, secIe__, groupKeyId__, seqNumber__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWmmParamUpdateReqSend - - DESCRIPTION - Application uses this primitive to update the WMM parameters on the fly - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - wmmApParams - WMM parameters to be used for local firmware queue - configuration - wmmApBcParams - WMM parameters to be advertised in beacon/probe response - -*******************************************************************************/ -#define CsrWifiSmeApWmmParamUpdateReqCreate(msg__, dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWmmParamUpdateReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - memcpy(msg__->wmmApParams, (wmmApParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); \ - memcpy(msg__->wmmApBcParams, (wmmApBcParams__), sizeof(CsrWifiSmeWmmAcParams) * 4); - -#define CsrWifiSmeApWmmParamUpdateReqSendTo(dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ - { \ - CsrWifiSmeApWmmParamUpdateReq *msg__; \ - CsrWifiSmeApWmmParamUpdateReqCreate(msg__, dst__, src__, interfaceTag__, wmmApParams__, wmmApBcParams__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWmmParamUpdateReqSend(src__, interfaceTag__, wmmApParams__, wmmApBcParams__) \ - CsrWifiSmeApWmmParamUpdateReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, wmmApParams__, wmmApBcParams__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWmmParamUpdateCfmSend - - DESCRIPTION - A confirm for CSR_WIFI_SME_AP_WMM_PARAM_UPDATE.request - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiSmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWmmParamUpdateCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeApWmmParamUpdateCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeApWmmParamUpdateCfm *msg__; \ - CsrWifiSmeApWmmParamUpdateCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWmmParamUpdateCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeApWmmParamUpdateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsConfigurationReqSend - - DESCRIPTION - This primitive passes the WPS information for the device to SME. This may - be accepted only if no interface is active. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - wpsConfig - WPS config. - -*******************************************************************************/ -#define CsrWifiSmeApWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsConfigurationReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ, dst__, src__); \ - msg__->wpsConfig = (wpsConfig__); - -#define CsrWifiSmeApWpsConfigurationReqSendTo(dst__, src__, wpsConfig__) \ - { \ - CsrWifiSmeApWpsConfigurationReq *msg__; \ - CsrWifiSmeApWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsConfigurationReqSend(src__, wpsConfig__) \ - CsrWifiSmeApWpsConfigurationReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, wpsConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsConfigurationCfmSend - - DESCRIPTION - Confirm. - - PARAMETERS - queue - Destination Task Queue - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiSmeApWpsConfigurationCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsConfigurationCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeApWpsConfigurationCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeApWpsConfigurationCfm *msg__; \ - CsrWifiSmeApWpsConfigurationCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsConfigurationCfmSend(dst__, status__) \ - CsrWifiSmeApWpsConfigurationCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationFinishedReqSend - - DESCRIPTION - This primitive tells SME that WPS registration procedure has finished - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - -*******************************************************************************/ -#define CsrWifiSmeApWpsRegistrationFinishedReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsRegistrationFinishedReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeApWpsRegistrationFinishedReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeApWpsRegistrationFinishedReq *msg__; \ - CsrWifiSmeApWpsRegistrationFinishedReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsRegistrationFinishedReqSend(src__, interfaceTag__) \ - CsrWifiSmeApWpsRegistrationFinishedReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationFinishedCfmSend - - DESCRIPTION - A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_FINISHED.request - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiSmeApWpsRegistrationFinishedCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsRegistrationFinishedCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeApWpsRegistrationFinishedCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeApWpsRegistrationFinishedCfm *msg__; \ - CsrWifiSmeApWpsRegistrationFinishedCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsRegistrationFinishedCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeApWpsRegistrationFinishedCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationStartedReqSend - - DESCRIPTION - This primitive tells SME that WPS registration procedure has started - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - - SelectedDevicePasswordId - - SelectedconfigMethod - - -*******************************************************************************/ -#define CsrWifiSmeApWpsRegistrationStartedReqCreate(msg__, dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsRegistrationStartedReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->SelectedDevicePasswordId = (SelectedDevicePasswordId__); \ - msg__->SelectedconfigMethod = (SelectedconfigMethod__); - -#define CsrWifiSmeApWpsRegistrationStartedReqSendTo(dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ - { \ - CsrWifiSmeApWpsRegistrationStartedReq *msg__; \ - CsrWifiSmeApWpsRegistrationStartedReqCreate(msg__, dst__, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsRegistrationStartedReqSend(src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) \ - CsrWifiSmeApWpsRegistrationStartedReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, SelectedDevicePasswordId__, SelectedconfigMethod__) - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationStartedCfmSend - - DESCRIPTION - A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_STARTED.request - - PARAMETERS - queue - Destination Task Queue - interfaceTag - - status - - -*******************************************************************************/ -#define CsrWifiSmeApWpsRegistrationStartedCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeApWpsRegistrationStartedCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeApWpsRegistrationStartedCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeApWpsRegistrationStartedCfm *msg__; \ - CsrWifiSmeApWpsRegistrationStartedCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \ - } - -#define CsrWifiSmeApWpsRegistrationStartedCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeApWpsRegistrationStartedCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - - -#endif /* CSR_WIFI_SME_AP_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_ap_prim.h b/drivers/staging/csr/csr_wifi_sme_ap_prim.h deleted file mode 100644 index 3c4bcbc16126..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_ap_prim.h +++ /dev/null @@ -1,1030 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_AP_PRIM_H__ -#define CSR_WIFI_SME_AP_PRIM_H__ - -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" -#include "csr_wifi_sme_prim.h" - -#ifndef CSR_WIFI_AP_ENABLE -#error CSR_WIFI_AP_ENABLE MUST be defined inorder to use csr_wifi_sme_ap_prim.h -#endif - -#define CSR_WIFI_SME_AP_PRIM (0x0407) - -typedef CsrPrim CsrWifiSmeApPrim; - - -/******************************************************************************* - - NAME - CsrWifiSmeApAccessType - - DESCRIPTION - Allow or deny STAs based on MAC address - - VALUES - CSR_WIFI_AP_ACCESS_TYPE_NONE - None - CSR_WIFI_AP_ACCESS_TYPE_ALLOW - Allow only if MAC address is from the list - CSR_WIFI_AP_ACCESS_TYPE_DENY - Disallow if MAC address is from the list - -*******************************************************************************/ -typedef u8 CsrWifiSmeApAccessType; -#define CSR_WIFI_AP_ACCESS_TYPE_NONE ((CsrWifiSmeApAccessType) 0x00) -#define CSR_WIFI_AP_ACCESS_TYPE_ALLOW ((CsrWifiSmeApAccessType) 0x01) -#define CSR_WIFI_AP_ACCESS_TYPE_DENY ((CsrWifiSmeApAccessType) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeApAuthSupport - - DESCRIPTION - Define bits for AP authentication support - - VALUES - CSR_WIFI_SME_RSN_AUTH_WPAPSK - RSN WPA-PSK Support - CSR_WIFI_SME_RSN_AUTH_WPA2PSK - RSN WPA2-PSK Support - CSR_WIFI_SME_AUTH_WAPIPSK - WAPI-PSK Support - -*******************************************************************************/ -typedef u8 CsrWifiSmeApAuthSupport; -#define CSR_WIFI_SME_RSN_AUTH_WPAPSK ((CsrWifiSmeApAuthSupport) 0x01) -#define CSR_WIFI_SME_RSN_AUTH_WPA2PSK ((CsrWifiSmeApAuthSupport) 0x02) -#define CSR_WIFI_SME_AUTH_WAPIPSK ((CsrWifiSmeApAuthSupport) 0x04) - -/******************************************************************************* - - NAME - CsrWifiSmeApAuthType - - DESCRIPTION - Definition of the SME AP Authentication Options - - VALUES - CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM - - Open authentication - CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL - - Personal authentication using a passphrase or a pre-shared - key. - CSR_WIFI_SME_AP_AUTH_TYPE_WEP - - WEP authentication. This can be either open or shared key - -*******************************************************************************/ -typedef u8 CsrWifiSmeApAuthType; -#define CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM ((CsrWifiSmeApAuthType) 0x00) -#define CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL ((CsrWifiSmeApAuthType) 0x01) -#define CSR_WIFI_SME_AP_AUTH_TYPE_WEP ((CsrWifiSmeApAuthType) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeApDirection - - DESCRIPTION - Definition of Direction - - VALUES - CSR_WIFI_AP_DIRECTION_RECEIPIENT - Receipient - CSR_WIFI_AP_DIRECTION_ORIGINATOR - Originator - -*******************************************************************************/ -typedef u8 CsrWifiSmeApDirection; -#define CSR_WIFI_AP_DIRECTION_RECEIPIENT ((CsrWifiSmeApDirection) 0x00) -#define CSR_WIFI_AP_DIRECTION_ORIGINATOR ((CsrWifiSmeApDirection) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeApPhySupport - - DESCRIPTION - Define bits for CsrWifiSmeApPhySupportMask - - VALUES - CSR_WIFI_SME_AP_PHY_SUPPORT_A - 802.11a. It is not supported in the current - release. - CSR_WIFI_SME_AP_PHY_SUPPORT_B - 802.11b - CSR_WIFI_SME_AP_PHY_SUPPORT_G - 802.11g - CSR_WIFI_SME_AP_PHY_SUPPORT_N - 802.11n - -*******************************************************************************/ -typedef u8 CsrWifiSmeApPhySupport; -#define CSR_WIFI_SME_AP_PHY_SUPPORT_A ((CsrWifiSmeApPhySupport) 0x01) -#define CSR_WIFI_SME_AP_PHY_SUPPORT_B ((CsrWifiSmeApPhySupport) 0x02) -#define CSR_WIFI_SME_AP_PHY_SUPPORT_G ((CsrWifiSmeApPhySupport) 0x04) -#define CSR_WIFI_SME_AP_PHY_SUPPORT_N ((CsrWifiSmeApPhySupport) 0x08) - -/******************************************************************************* - - NAME - CsrWifiSmeApType - - DESCRIPTION - Definition of AP types - - VALUES - CSR_WIFI_AP_TYPE_LEGACY - Legacy AP - CSR_WIFI_AP_TYPE_P2P - P2P Group Owner(GO) - -*******************************************************************************/ -typedef u8 CsrWifiSmeApType; -#define CSR_WIFI_AP_TYPE_LEGACY ((CsrWifiSmeApType) 0x00) -#define CSR_WIFI_AP_TYPE_P2P ((CsrWifiSmeApType) 0x01) - - -/******************************************************************************* - - NAME - CsrWifiSmeApAuthSupportMask - - DESCRIPTION - See CsrWifiSmeApAuthSupport for bit definitions - -*******************************************************************************/ -typedef u8 CsrWifiSmeApAuthSupportMask; -/******************************************************************************* - - NAME - CsrWifiSmeApPhySupportMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeApPhySupport - -*******************************************************************************/ -typedef u8 CsrWifiSmeApPhySupportMask; -/******************************************************************************* - - NAME - CsrWifiSmeApRsnCapabilities - - DESCRIPTION - Set to 0 for the current release - -*******************************************************************************/ -typedef u16 CsrWifiSmeApRsnCapabilities; -/******************************************************************************* - - NAME - CsrWifiSmeApRsnCapabilitiesMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeApRsnCapabilities - -*******************************************************************************/ -typedef u16 CsrWifiSmeApRsnCapabilitiesMask; -/******************************************************************************* - - NAME - CsrWifiSmeApWapiCapabilities - - DESCRIPTION - Ignored by the stack as WAPI is not supported for AP operations in the - current release - -*******************************************************************************/ -typedef u16 CsrWifiSmeApWapiCapabilities; -/******************************************************************************* - - NAME - CsrWifiSmeApWapiCapabilitiesMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeApWapiCapabilities - -*******************************************************************************/ -typedef u16 CsrWifiSmeApWapiCapabilitiesMask; - - -/******************************************************************************* - - NAME - CsrWifiSmeApHtParams - - DESCRIPTION - Structure holding HT parameters - - MEMBERS - greenfieldSupported - Indicates if the AP supports Htgreenfield operation - subject to the chip capability. If the chip does not - support Htgreenfield operation, this parameter will be - ignored. - NOTE: if shortGi20MHz is set to TRUE and the chip - supports short GI operation for 20MHz this field will - be be ignored and the AP will not support Htgreenfield - operation. - NOTE: This field is ignored by the Wi-Fi stack for the - current release. It implies that AP does not support - greenfield operation. - shortGi20MHz - Indicates if the AP support short GI operation for - 20MHz subject to the chip capability.If the chip does - not support short GI for 20MHz, this parameter is - ignored - rxStbc - Support for STBC for receive. 0 => No support for STBC - , 1=> Use STBC for Rx - rifsModeAllowed - RIFS Mode is allowed to protect overlapping non-HT BSS - htProtection - Deprecated - dualCtsProtection - Dual CTS Protection enabled - -*******************************************************************************/ -typedef struct -{ - u8 greenfieldSupported; - u8 shortGi20MHz; - u8 rxStbc; - u8 rifsModeAllowed; - u8 htProtection; - u8 dualCtsProtection; -} CsrWifiSmeApHtParams; - -/******************************************************************************* - - NAME - CsrWifiSmeApP2pOperatingChanEntry - - DESCRIPTION - - MEMBERS - operatingClass - Channel operating class - operatingChannelCount - Number of channels in this entry - operatingChannel - List of channels - -*******************************************************************************/ -typedef struct -{ - u8 operatingClass; - u8 operatingChannelCount; - u8 *operatingChannel; -} CsrWifiSmeApP2pOperatingChanEntry; - -/******************************************************************************* - - NAME - CsrWifiSmeApP2pOperatingChanList - - DESCRIPTION - This structure contains the lists of P2P operating channels - - MEMBERS - country - Country - channelEntryListCount - Number of entries - channelEntryList - List of entries - -*******************************************************************************/ -typedef struct -{ - u8 country[3]; - u8 channelEntryListCount; - CsrWifiSmeApP2pOperatingChanEntry *channelEntryList; -} CsrWifiSmeApP2pOperatingChanList; - -/******************************************************************************* - - NAME - CsrWifiSmeApAuthPers - - DESCRIPTION - - MEMBERS - authSupport - - encryptionModeMask - - rsnCapabilities - - wapiCapabilities - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApAuthSupportMask authSupport; - CsrWifiSmeEncryptionMask encryptionModeMask; - CsrWifiSmeApRsnCapabilitiesMask rsnCapabilities; - CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities; -} CsrWifiSmeApAuthPers; - -/******************************************************************************* - - NAME - CsrWifiSmeApBaSession - - DESCRIPTION - - MEMBERS - peerMacAddress - Indicates MAC address of the peer station - tid - Specifies the TID of the MSDUs for which this Block Ack has - been set up. Range: 0-15 - direction - Specifies if the AP is the originator or the recipient of - the data stream that uses the Block Ack. - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress peerMacAddress; - u8 tid; - CsrWifiSmeApDirection direction; -} CsrWifiSmeApBaSession; - -/******************************************************************************* - - NAME - CsrWifiSmeApMacConfig - - DESCRIPTION - Structure holding AP MAC configuration. - - MEMBERS - phySupportedBitmap - Indicates supported physical layers - beaconInterval - Beacon interval in terms of TUs - dtimPeriod - DTIM period in terms of number of beacon intervals - maxListenInterval - Maximum allowed listen interval as number of beacon - intervals - supportedRatesCount - Number of supported rates. Range : 0 to 20 - supportedRates - List of supportedRates. A rate is specied in the - units of 500kbps. An entry for a basic rate shall - have the MSB set to 1. - preamble - Preamble to be advertised in beacons and probe - responses - shortSlotTimeEnabled - TRUE indicates the AP shall use short slot time if - all the stations use short slot operation. - ctsProtectionType - CTS protection to be used - wmmEnabled - Indicate whether WMM is enabled or not. If set to - FALSE,the WMM parameters shall be ignored by the - receiver. - wmmApParams - WMM parameters to be used for local firmware queue - configuration. Array index corresponds to the ACI. - wmmApBcParams - WMM parameters to be advertised in beacon/probe - response. Array index corresponds to the ACI - accessType - Specifies whether the MAC addresses from the list - should be allowed or denied - macAddressListCount - Number of MAC addresses - macAddressList - List of MAC addresses - apHtParams - AP HT parameters. The stack shall use these - parameters only if phySupportedBitmap indicates - support for IEEE 802.11n - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApPhySupportMask phySupportedBitmap; - u16 beaconInterval; - u8 dtimPeriod; - u16 maxListenInterval; - u8 supportedRatesCount; - u8 supportedRates[20]; - CsrWifiSmePreambleType preamble; - u8 shortSlotTimeEnabled; - CsrWifiSmeCtsProtectionType ctsProtectionType; - u8 wmmEnabled; - CsrWifiSmeWmmAcParams wmmApParams[4]; - CsrWifiSmeWmmAcParams wmmApBcParams[4]; - CsrWifiSmeApAccessType accessType; - u8 macAddressListCount; - CsrWifiMacAddress *macAddressList; - CsrWifiSmeApHtParams apHtParams; -} CsrWifiSmeApMacConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeApP2pGoConfig - - DESCRIPTION - - MEMBERS - groupCapability - Indicates the P2P group capabilities - operatingChanList - List of operating channels in the order of - decreasing priority. It may contain channel - entry/entries not supported by the wifi stack. - These shall be filtered out by the wifi stack - opPsEnabled - Indicates whether opportunistic power save can - be used. - Note: This parameter is ignored by the WiFi - stack for the current release - ctWindow - Define Client Traffic window to be used in terms - of number of TUs. Range: 0 to 127. - Note: This parameter is ignored by the WiFi - stack for the current release. - noaConfigMethod - Notice of Absence configuration method. - Note: This parameter is ignored by the WiFi - stack for the current release. - allowNoaWithNonP2pDevices - Indicates if NOA should be allowed if non P2P - devices are connected. If allowed the non P2P - devices may suffer in throughput. - Note: This parameter is ignored by the WiFi - stack for the current release. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeP2pGroupCapabilityMask groupCapability; - CsrWifiSmeApP2pOperatingChanList operatingChanList; - u8 opPsEnabled; - u8 ctWindow; - CsrWifiSmeP2pNoaConfigMethod noaConfigMethod; - u8 allowNoaWithNonP2pDevices; -} CsrWifiSmeApP2pGoConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeApCredentials - - DESCRIPTION - - MEMBERS - authType - - smeAuthType - - smeAuthTypeopenSystemEmpty - - smeAuthTypeauthwep - - smeAuthTypeauthPers - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApAuthType authType; - union { - CsrWifiSmeEmpty openSystemEmpty; - CsrWifiSmeWepAuth authwep; - CsrWifiSmeApAuthPers authPers; - } smeAuthType; -} CsrWifiSmeApCredentials; - -/******************************************************************************* - - NAME - CsrWifiSmeApSecConfig - - DESCRIPTION - - MEMBERS - apCredentials - - wpsEnabled - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeApCredentials apCredentials; - u8 wpsEnabled; -} CsrWifiSmeApSecConfig; - - -/* Downstream */ -#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_SME_AP_BEACONING_START_REQ ((CsrWifiSmeApPrim) (0x0000 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_BEACONING_STOP_REQ ((CsrWifiSmeApPrim) (0x0001 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_REQ ((CsrWifiSmeApPrim) (0x0002 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_REQ ((CsrWifiSmeApPrim) (0x0003 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ ((CsrWifiSmeApPrim) (0x0004 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_STA_DISCONNECT_REQ ((CsrWifiSmeApPrim) (0x0005 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ ((CsrWifiSmeApPrim) (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ ((CsrWifiSmeApPrim) (0x0007 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_BA_DELETE_REQ ((CsrWifiSmeApPrim) (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_SME_AP_BEACONING_START_CFM ((CsrWifiSmeApPrim)(0x0000 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_BEACONING_STOP_CFM ((CsrWifiSmeApPrim)(0x0001 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_STA_NOTIFY_IND ((CsrWifiSmeApPrim)(0x0002 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_STA_CONNECT_START_IND ((CsrWifiSmeApPrim)(0x0003 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_REGISTRATION_STARTED_CFM ((CsrWifiSmeApPrim)(0x0004 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_REGISTRATION_FINISHED_CFM ((CsrWifiSmeApPrim)(0x0005 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_CFM ((CsrWifiSmeApPrim)(0x0006 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_STA_DISCONNECT_CFM ((CsrWifiSmeApPrim)(0x0007 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM ((CsrWifiSmeApPrim)(0x0008 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_ERROR_IND ((CsrWifiSmeApPrim)(0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM ((CsrWifiSmeApPrim)(0x000A + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AP_BA_DELETE_CFM ((CsrWifiSmeApPrim)(0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST (0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT (CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStartReq - - DESCRIPTION - This primitive requests the SME to start AP or GO functionality - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - initialPresence - Set to 0, if Not in a group fomration phase, set to 1 , - during group formation phase - apType - apType : Legacy AP or P2PGO - cloakSsid - cloakSsid flag. - ssid - ssid. - ifIndex - Radio Interface - channel - channel. - maxConnections - Maximum Stations + P2PClients allowed - apCredentials - AP security credeitals used to advertise in beacon /probe - response - smeApConfig - AP configuration - p2pGoParam - P2P specific GO parameters. Ignored if it is a leagacy AP - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 initialPresence; - CsrWifiSmeApType apType; - u8 cloakSsid; - CsrWifiSsid ssid; - CsrWifiSmeRadioIF ifIndex; - u8 channel; - u8 maxConnections; - CsrWifiSmeApSecConfig apCredentials; - CsrWifiSmeApMacConfig smeApConfig; - CsrWifiSmeApP2pGoConfig p2pGoParam; -} CsrWifiSmeApBeaconingStartReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStopReq - - DESCRIPTION - This primitive requests the SME to STOP AP or P2PGO operation - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeApBeaconingStopReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationStartedReq - - DESCRIPTION - This primitive tells SME that WPS registration procedure has started - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - SelectedDevicePasswordId - - SelectedconfigMethod - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeWpsDpid SelectedDevicePasswordId; - CsrWifiSmeWpsConfigType SelectedconfigMethod; -} CsrWifiSmeApWpsRegistrationStartedReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationFinishedReq - - DESCRIPTION - This primitive tells SME that WPS registration procedure has finished - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeApWpsRegistrationFinishedReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApWmmParamUpdateReq - - DESCRIPTION - Application uses this primitive to update the WMM parameters on the fly - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - wmmApParams - WMM parameters to be used for local firmware queue - configuration - wmmApBcParams - WMM parameters to be advertised in beacon/probe response - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeWmmAcParams wmmApParams[4]; - CsrWifiSmeWmmAcParams wmmApBcParams[4]; -} CsrWifiSmeApWmmParamUpdateReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApStaDisconnectReq - - DESCRIPTION - This primitive tells SME to deauth ot disassociate a particular station - within BSS - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - deauthReason - - disassocReason - - peerMacaddress - - keepBlocking - If TRUE, the station is blocked. If FALSE and the station - is connected, disconnect the station. If FALSE and the - station is not connected, no action is taken. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeIEEE80211Reason deauthReason; - CsrWifiSmeIEEE80211Reason disassocReason; - CsrWifiMacAddress peerMacaddress; - u8 keepBlocking; -} CsrWifiSmeApStaDisconnectReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsConfigurationReq - - DESCRIPTION - This primitive passes the WPS information for the device to SME. This may - be accepted only if no interface is active. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - wpsConfig - WPS config. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeWpsConfig wpsConfig; -} CsrWifiSmeApWpsConfigurationReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApActiveBaGetReq - - DESCRIPTION - This primitive used to retrieve information related to the active block - ack sessions - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeApActiveBaGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApBaDeleteReq - - DESCRIPTION - This primitive is used to delete an active block ack session - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - reason - - baSession - BA session to be deleted - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeIEEE80211Reason reason; - CsrWifiSmeApBaSession baSession; -} CsrWifiSmeApBaDeleteReq; - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStartCfm - - DESCRIPTION - This primitive confirms the completion of the request along with the - status - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - secIeLength - - secIe - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - u16 secIeLength; - u8 *secIe; -} CsrWifiSmeApBeaconingStartCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApBeaconingStopCfm - - DESCRIPTION - This primitive confirms AP or P2PGO operation is terminated - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeApBeaconingStopCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApStaNotifyInd - - DESCRIPTION - This primitive indicates that a station has joined or a previously joined - station has left the BSS/group - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - mediaStatus - - peerMacAddress - - peerDeviceAddress - - disassocReason - - deauthReason - - WpsRegistration - - secIeLength - - secIe - - groupKeyId - - seqNumber - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeMediaStatus mediaStatus; - CsrWifiMacAddress peerMacAddress; - CsrWifiMacAddress peerDeviceAddress; - CsrWifiSmeIEEE80211Reason disassocReason; - CsrWifiSmeIEEE80211Reason deauthReason; - CsrWifiSmeWpsRegistration WpsRegistration; - u8 secIeLength; - u8 *secIe; - u8 groupKeyId; - u16 seqNumber[8]; -} CsrWifiSmeApStaNotifyInd; - -/******************************************************************************* - - NAME - CsrWifiSmeApStaConnectStartInd - - DESCRIPTION - This primitive indicates that a stations request to join the group/BSS is - accepted - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - peerMacAddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiMacAddress peerMacAddress; -} CsrWifiSmeApStaConnectStartInd; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationStartedCfm - - DESCRIPTION - A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_STARTED.request - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeApWpsRegistrationStartedCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsRegistrationFinishedCfm - - DESCRIPTION - A confirm for UNIFI_MGT_AP_WPS_REGISTRATION_FINISHED.request - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeApWpsRegistrationFinishedCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApWmmParamUpdateCfm - - DESCRIPTION - A confirm for CSR_WIFI_SME_AP_WMM_PARAM_UPDATE.request - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeApWmmParamUpdateCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApStaDisconnectCfm - - DESCRIPTION - This primitive confirms the station is disconnected - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - - peerMacaddress - - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiMacAddress peerMacaddress; -} CsrWifiSmeApStaDisconnectCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApWpsConfigurationCfm - - DESCRIPTION - Confirm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeApWpsConfigurationCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApErrorInd - - DESCRIPTION - This primitve is sent by SME to indicate some error in AP operationi - after AP operations were started successfully and continuing the AP - operation may lead to undesired behaviour. It is the responsibility of - the upper layers to stop AP operation if needed - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Range 0-1 - apType - - status - Contains the error status - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeApType apType; - CsrResult status; -} CsrWifiSmeApErrorInd; - -/******************************************************************************* - - NAME - CsrWifiSmeApActiveBaGetCfm - - DESCRIPTION - This primitive carries the information related to the active ba sessions - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - Reports the result of the request - activeBaCount - Number of active block ack session - activeBaSessions - Points to a buffer containing an array of - CsrWifiSmeApBaSession structures. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - u16 activeBaCount; - CsrWifiSmeApBaSession *activeBaSessions; -} CsrWifiSmeApActiveBaGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeApBaDeleteCfm - - DESCRIPTION - This primitive confirms the BA is deleted - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - - status - Reports the result of the request - baSession - deleted BA session - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeApBaSession baSession; -} CsrWifiSmeApBaDeleteCfm; - - -#endif /* CSR_WIFI_SME_AP_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.c b/drivers/staging/csr/csr_wifi_sme_converter_init.c deleted file mode 100644 index 31835f06bbc2..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_converter_init.c +++ /dev/null @@ -1,201 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#include "csr_msgconv.h" -#include "csr_macro.h" - - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" -#endif - -#ifndef EXCLUDE_CSR_WIFI_SME_MODULE -#include "csr_wifi_sme_serialize.h" -#include "csr_wifi_sme_prim.h" - -static CsrMsgConvMsgEntry csrwifisme_conv_lut[] = { - { CSR_WIFI_SME_ACTIVATE_REQ, CsrWifiSmeActivateReqSizeof, CsrWifiSmeActivateReqSer, CsrWifiSmeActivateReqDes, CsrWifiSmeActivateReqSerFree }, - { CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ, CsrWifiSmeAdhocConfigGetReqSizeof, CsrWifiSmeAdhocConfigGetReqSer, CsrWifiSmeAdhocConfigGetReqDes, CsrWifiSmeAdhocConfigGetReqSerFree }, - { CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ, CsrWifiSmeAdhocConfigSetReqSizeof, CsrWifiSmeAdhocConfigSetReqSer, CsrWifiSmeAdhocConfigSetReqDes, CsrWifiSmeAdhocConfigSetReqSerFree }, - { CSR_WIFI_SME_BLACKLIST_REQ, CsrWifiSmeBlacklistReqSizeof, CsrWifiSmeBlacklistReqSer, CsrWifiSmeBlacklistReqDes, CsrWifiSmeBlacklistReqSerFree }, - { CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ, CsrWifiSmeCalibrationDataGetReqSizeof, CsrWifiSmeCalibrationDataGetReqSer, CsrWifiSmeCalibrationDataGetReqDes, CsrWifiSmeCalibrationDataGetReqSerFree }, - { CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ, CsrWifiSmeCalibrationDataSetReqSizeof, CsrWifiSmeCalibrationDataSetReqSer, CsrWifiSmeCalibrationDataSetReqDes, CsrWifiSmeCalibrationDataSetReqSerFree }, - { CSR_WIFI_SME_CCX_CONFIG_GET_REQ, CsrWifiSmeCcxConfigGetReqSizeof, CsrWifiSmeCcxConfigGetReqSer, CsrWifiSmeCcxConfigGetReqDes, CsrWifiSmeCcxConfigGetReqSerFree }, - { CSR_WIFI_SME_CCX_CONFIG_SET_REQ, CsrWifiSmeCcxConfigSetReqSizeof, CsrWifiSmeCcxConfigSetReqSer, CsrWifiSmeCcxConfigSetReqDes, CsrWifiSmeCcxConfigSetReqSerFree }, - { CSR_WIFI_SME_COEX_CONFIG_GET_REQ, CsrWifiSmeCoexConfigGetReqSizeof, CsrWifiSmeCoexConfigGetReqSer, CsrWifiSmeCoexConfigGetReqDes, CsrWifiSmeCoexConfigGetReqSerFree }, - { CSR_WIFI_SME_COEX_CONFIG_SET_REQ, CsrWifiSmeCoexConfigSetReqSizeof, CsrWifiSmeCoexConfigSetReqSer, CsrWifiSmeCoexConfigSetReqDes, CsrWifiSmeCoexConfigSetReqSerFree }, - { CSR_WIFI_SME_COEX_INFO_GET_REQ, CsrWifiSmeCoexInfoGetReqSizeof, CsrWifiSmeCoexInfoGetReqSer, CsrWifiSmeCoexInfoGetReqDes, CsrWifiSmeCoexInfoGetReqSerFree }, - { CSR_WIFI_SME_CONNECT_REQ, CsrWifiSmeConnectReqSizeof, CsrWifiSmeConnectReqSer, CsrWifiSmeConnectReqDes, CsrWifiSmeConnectReqSerFree }, - { CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ, CsrWifiSmeConnectionConfigGetReqSizeof, CsrWifiSmeConnectionConfigGetReqSer, CsrWifiSmeConnectionConfigGetReqDes, CsrWifiSmeConnectionConfigGetReqSerFree }, - { CSR_WIFI_SME_CONNECTION_INFO_GET_REQ, CsrWifiSmeConnectionInfoGetReqSizeof, CsrWifiSmeConnectionInfoGetReqSer, CsrWifiSmeConnectionInfoGetReqDes, CsrWifiSmeConnectionInfoGetReqSerFree }, - { CSR_WIFI_SME_CONNECTION_STATS_GET_REQ, CsrWifiSmeConnectionStatsGetReqSizeof, CsrWifiSmeConnectionStatsGetReqSer, CsrWifiSmeConnectionStatsGetReqDes, CsrWifiSmeConnectionStatsGetReqSerFree }, - { CSR_WIFI_SME_DEACTIVATE_REQ, CsrWifiSmeDeactivateReqSizeof, CsrWifiSmeDeactivateReqSer, CsrWifiSmeDeactivateReqDes, CsrWifiSmeDeactivateReqSerFree }, - { CSR_WIFI_SME_DISCONNECT_REQ, CsrWifiSmeDisconnectReqSizeof, CsrWifiSmeDisconnectReqSer, CsrWifiSmeDisconnectReqDes, CsrWifiSmeDisconnectReqSerFree }, - { CSR_WIFI_SME_EVENT_MASK_SET_REQ, CsrWifiSmeEventMaskSetReqSizeof, CsrWifiSmeEventMaskSetReqSer, CsrWifiSmeEventMaskSetReqDes, CsrWifiSmeEventMaskSetReqSerFree }, - { CSR_WIFI_SME_HOST_CONFIG_GET_REQ, CsrWifiSmeHostConfigGetReqSizeof, CsrWifiSmeHostConfigGetReqSer, CsrWifiSmeHostConfigGetReqDes, CsrWifiSmeHostConfigGetReqSerFree }, - { CSR_WIFI_SME_HOST_CONFIG_SET_REQ, CsrWifiSmeHostConfigSetReqSizeof, CsrWifiSmeHostConfigSetReqSer, CsrWifiSmeHostConfigSetReqDes, CsrWifiSmeHostConfigSetReqSerFree }, - { CSR_WIFI_SME_KEY_REQ, CsrWifiSmeKeyReqSizeof, CsrWifiSmeKeyReqSer, CsrWifiSmeKeyReqDes, CsrWifiSmeKeyReqSerFree }, - { CSR_WIFI_SME_LINK_QUALITY_GET_REQ, CsrWifiSmeLinkQualityGetReqSizeof, CsrWifiSmeLinkQualityGetReqSer, CsrWifiSmeLinkQualityGetReqDes, CsrWifiSmeLinkQualityGetReqSerFree }, - { CSR_WIFI_SME_MIB_CONFIG_GET_REQ, CsrWifiSmeMibConfigGetReqSizeof, CsrWifiSmeMibConfigGetReqSer, CsrWifiSmeMibConfigGetReqDes, CsrWifiSmeMibConfigGetReqSerFree }, - { CSR_WIFI_SME_MIB_CONFIG_SET_REQ, CsrWifiSmeMibConfigSetReqSizeof, CsrWifiSmeMibConfigSetReqSer, CsrWifiSmeMibConfigSetReqDes, CsrWifiSmeMibConfigSetReqSerFree }, - { CSR_WIFI_SME_MIB_GET_NEXT_REQ, CsrWifiSmeMibGetNextReqSizeof, CsrWifiSmeMibGetNextReqSer, CsrWifiSmeMibGetNextReqDes, CsrWifiSmeMibGetNextReqSerFree }, - { CSR_WIFI_SME_MIB_GET_REQ, CsrWifiSmeMibGetReqSizeof, CsrWifiSmeMibGetReqSer, CsrWifiSmeMibGetReqDes, CsrWifiSmeMibGetReqSerFree }, - { CSR_WIFI_SME_MIB_SET_REQ, CsrWifiSmeMibSetReqSizeof, CsrWifiSmeMibSetReqSer, CsrWifiSmeMibSetReqDes, CsrWifiSmeMibSetReqSerFree }, - { CSR_WIFI_SME_MULTICAST_ADDRESS_REQ, CsrWifiSmeMulticastAddressReqSizeof, CsrWifiSmeMulticastAddressReqSer, CsrWifiSmeMulticastAddressReqDes, CsrWifiSmeMulticastAddressReqSerFree }, - { CSR_WIFI_SME_PACKET_FILTER_SET_REQ, CsrWifiSmePacketFilterSetReqSizeof, CsrWifiSmePacketFilterSetReqSer, CsrWifiSmePacketFilterSetReqDes, CsrWifiSmePacketFilterSetReqSerFree }, - { CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ, CsrWifiSmePermanentMacAddressGetReqSizeof, CsrWifiSmePermanentMacAddressGetReqSer, CsrWifiSmePermanentMacAddressGetReqDes, CsrWifiSmePermanentMacAddressGetReqSerFree }, - { CSR_WIFI_SME_PMKID_REQ, CsrWifiSmePmkidReqSizeof, CsrWifiSmePmkidReqSer, CsrWifiSmePmkidReqDes, CsrWifiSmePmkidReqSerFree }, - { CSR_WIFI_SME_POWER_CONFIG_GET_REQ, CsrWifiSmePowerConfigGetReqSizeof, CsrWifiSmePowerConfigGetReqSer, CsrWifiSmePowerConfigGetReqDes, CsrWifiSmePowerConfigGetReqSerFree }, - { CSR_WIFI_SME_POWER_CONFIG_SET_REQ, CsrWifiSmePowerConfigSetReqSizeof, CsrWifiSmePowerConfigSetReqSer, CsrWifiSmePowerConfigSetReqDes, CsrWifiSmePowerConfigSetReqSerFree }, - { CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ, CsrWifiSmeRegulatoryDomainInfoGetReqSizeof, CsrWifiSmeRegulatoryDomainInfoGetReqSer, CsrWifiSmeRegulatoryDomainInfoGetReqDes, CsrWifiSmeRegulatoryDomainInfoGetReqSerFree }, - { CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ, CsrWifiSmeRoamingConfigGetReqSizeof, CsrWifiSmeRoamingConfigGetReqSer, CsrWifiSmeRoamingConfigGetReqDes, CsrWifiSmeRoamingConfigGetReqSerFree }, - { CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ, CsrWifiSmeRoamingConfigSetReqSizeof, CsrWifiSmeRoamingConfigSetReqSer, CsrWifiSmeRoamingConfigSetReqDes, CsrWifiSmeRoamingConfigSetReqSerFree }, - { CSR_WIFI_SME_SCAN_CONFIG_GET_REQ, CsrWifiSmeScanConfigGetReqSizeof, CsrWifiSmeScanConfigGetReqSer, CsrWifiSmeScanConfigGetReqDes, CsrWifiSmeScanConfigGetReqSerFree }, - { CSR_WIFI_SME_SCAN_CONFIG_SET_REQ, CsrWifiSmeScanConfigSetReqSizeof, CsrWifiSmeScanConfigSetReqSer, CsrWifiSmeScanConfigSetReqDes, CsrWifiSmeScanConfigSetReqSerFree }, - { CSR_WIFI_SME_SCAN_FULL_REQ, CsrWifiSmeScanFullReqSizeof, CsrWifiSmeScanFullReqSer, CsrWifiSmeScanFullReqDes, CsrWifiSmeScanFullReqSerFree }, - { CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ, CsrWifiSmeScanResultsFlushReqSizeof, CsrWifiSmeScanResultsFlushReqSer, CsrWifiSmeScanResultsFlushReqDes, CsrWifiSmeScanResultsFlushReqSerFree }, - { CSR_WIFI_SME_SCAN_RESULTS_GET_REQ, CsrWifiSmeScanResultsGetReqSizeof, CsrWifiSmeScanResultsGetReqSer, CsrWifiSmeScanResultsGetReqDes, CsrWifiSmeScanResultsGetReqSerFree }, - { CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ, CsrWifiSmeSmeStaConfigGetReqSizeof, CsrWifiSmeSmeStaConfigGetReqSer, CsrWifiSmeSmeStaConfigGetReqDes, CsrWifiSmeSmeStaConfigGetReqSerFree }, - { CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ, CsrWifiSmeSmeStaConfigSetReqSizeof, CsrWifiSmeSmeStaConfigSetReqSer, CsrWifiSmeSmeStaConfigSetReqDes, CsrWifiSmeSmeStaConfigSetReqSerFree }, - { CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ, CsrWifiSmeStationMacAddressGetReqSizeof, CsrWifiSmeStationMacAddressGetReqSer, CsrWifiSmeStationMacAddressGetReqDes, CsrWifiSmeStationMacAddressGetReqSerFree }, - { CSR_WIFI_SME_TSPEC_REQ, CsrWifiSmeTspecReqSizeof, CsrWifiSmeTspecReqSer, CsrWifiSmeTspecReqDes, CsrWifiSmeTspecReqSerFree }, - { CSR_WIFI_SME_VERSIONS_GET_REQ, CsrWifiSmeVersionsGetReqSizeof, CsrWifiSmeVersionsGetReqSer, CsrWifiSmeVersionsGetReqDes, CsrWifiSmeVersionsGetReqSerFree }, - { CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ, CsrWifiSmeWifiFlightmodeReqSizeof, CsrWifiSmeWifiFlightmodeReqSer, CsrWifiSmeWifiFlightmodeReqDes, CsrWifiSmeWifiFlightmodeReqSerFree }, - { CSR_WIFI_SME_WIFI_OFF_REQ, CsrWifiSmeWifiOffReqSizeof, CsrWifiSmeWifiOffReqSer, CsrWifiSmeWifiOffReqDes, CsrWifiSmeWifiOffReqSerFree }, - { CSR_WIFI_SME_WIFI_ON_REQ, CsrWifiSmeWifiOnReqSizeof, CsrWifiSmeWifiOnReqSer, CsrWifiSmeWifiOnReqDes, CsrWifiSmeWifiOnReqSerFree }, - { CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ, CsrWifiSmeCloakedSsidsSetReqSizeof, CsrWifiSmeCloakedSsidsSetReqSer, CsrWifiSmeCloakedSsidsSetReqDes, CsrWifiSmeCloakedSsidsSetReqSerFree }, - { CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ, CsrWifiSmeCloakedSsidsGetReqSizeof, CsrWifiSmeCloakedSsidsGetReqSer, CsrWifiSmeCloakedSsidsGetReqDes, CsrWifiSmeCloakedSsidsGetReqSerFree }, - { CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ, CsrWifiSmeSmeCommonConfigGetReqSizeof, CsrWifiSmeSmeCommonConfigGetReqSer, CsrWifiSmeSmeCommonConfigGetReqDes, CsrWifiSmeSmeCommonConfigGetReqSerFree }, - { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree }, - { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree }, - { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree }, - { CSR_WIFI_SME_SET_REQ, CsrWifiSmeSetReqSizeof, CsrWifiSmeSetReqSer, CsrWifiSmeSetReqDes, CsrWifiSmeSetReqSerFree }, - { CSR_WIFI_SME_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree }, - { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree }, - { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree }, - { CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND, CsrWifiSmeAssociationCompleteIndSizeof, CsrWifiSmeAssociationCompleteIndSer, CsrWifiSmeAssociationCompleteIndDes, CsrWifiSmeAssociationCompleteIndSerFree }, - { CSR_WIFI_SME_ASSOCIATION_START_IND, CsrWifiSmeAssociationStartIndSizeof, CsrWifiSmeAssociationStartIndSer, CsrWifiSmeAssociationStartIndDes, CsrWifiSmeAssociationStartIndSerFree }, - { CSR_WIFI_SME_BLACKLIST_CFM, CsrWifiSmeBlacklistCfmSizeof, CsrWifiSmeBlacklistCfmSer, CsrWifiSmeBlacklistCfmDes, CsrWifiSmeBlacklistCfmSerFree }, - { CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM, CsrWifiSmeCalibrationDataGetCfmSizeof, CsrWifiSmeCalibrationDataGetCfmSer, CsrWifiSmeCalibrationDataGetCfmDes, CsrWifiSmeCalibrationDataGetCfmSerFree }, - { CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM, CsrWifiSmeCalibrationDataSetCfmSizeof, CsrWifiSmeCalibrationDataSetCfmSer, CsrWifiSmeCalibrationDataSetCfmDes, CsrWifiSmeCalibrationDataSetCfmSerFree }, - { CSR_WIFI_SME_CCX_CONFIG_GET_CFM, CsrWifiSmeCcxConfigGetCfmSizeof, CsrWifiSmeCcxConfigGetCfmSer, CsrWifiSmeCcxConfigGetCfmDes, CsrWifiSmeCcxConfigGetCfmSerFree }, - { CSR_WIFI_SME_CCX_CONFIG_SET_CFM, CsrWifiSmeCcxConfigSetCfmSizeof, CsrWifiSmeCcxConfigSetCfmSer, CsrWifiSmeCcxConfigSetCfmDes, CsrWifiSmeCcxConfigSetCfmSerFree }, - { CSR_WIFI_SME_COEX_CONFIG_GET_CFM, CsrWifiSmeCoexConfigGetCfmSizeof, CsrWifiSmeCoexConfigGetCfmSer, CsrWifiSmeCoexConfigGetCfmDes, CsrWifiSmeCoexConfigGetCfmSerFree }, - { CSR_WIFI_SME_COEX_CONFIG_SET_CFM, CsrWifiSmeCoexConfigSetCfmSizeof, CsrWifiSmeCoexConfigSetCfmSer, CsrWifiSmeCoexConfigSetCfmDes, CsrWifiSmeCoexConfigSetCfmSerFree }, - { CSR_WIFI_SME_COEX_INFO_GET_CFM, CsrWifiSmeCoexInfoGetCfmSizeof, CsrWifiSmeCoexInfoGetCfmSer, CsrWifiSmeCoexInfoGetCfmDes, CsrWifiSmeCoexInfoGetCfmSerFree }, - { CSR_WIFI_SME_CONNECT_CFM, CsrWifiSmeConnectCfmSizeof, CsrWifiSmeConnectCfmSer, CsrWifiSmeConnectCfmDes, CsrWifiSmeConnectCfmSerFree }, - { CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM, CsrWifiSmeConnectionConfigGetCfmSizeof, CsrWifiSmeConnectionConfigGetCfmSer, CsrWifiSmeConnectionConfigGetCfmDes, CsrWifiSmeConnectionConfigGetCfmSerFree }, - { CSR_WIFI_SME_CONNECTION_INFO_GET_CFM, CsrWifiSmeConnectionInfoGetCfmSizeof, CsrWifiSmeConnectionInfoGetCfmSer, CsrWifiSmeConnectionInfoGetCfmDes, CsrWifiSmeConnectionInfoGetCfmSerFree }, - { CSR_WIFI_SME_CONNECTION_QUALITY_IND, CsrWifiSmeConnectionQualityIndSizeof, CsrWifiSmeConnectionQualityIndSer, CsrWifiSmeConnectionQualityIndDes, CsrWifiSmeConnectionQualityIndSerFree }, - { CSR_WIFI_SME_CONNECTION_STATS_GET_CFM, CsrWifiSmeConnectionStatsGetCfmSizeof, CsrWifiSmeConnectionStatsGetCfmSer, CsrWifiSmeConnectionStatsGetCfmDes, CsrWifiSmeConnectionStatsGetCfmSerFree }, - { CSR_WIFI_SME_DEACTIVATE_CFM, CsrWifiSmeDeactivateCfmSizeof, CsrWifiSmeDeactivateCfmSer, CsrWifiSmeDeactivateCfmDes, CsrWifiSmeDeactivateCfmSerFree }, - { CSR_WIFI_SME_DISCONNECT_CFM, CsrWifiSmeDisconnectCfmSizeof, CsrWifiSmeDisconnectCfmSer, CsrWifiSmeDisconnectCfmDes, CsrWifiSmeDisconnectCfmSerFree }, - { CSR_WIFI_SME_EVENT_MASK_SET_CFM, CsrWifiSmeEventMaskSetCfmSizeof, CsrWifiSmeEventMaskSetCfmSer, CsrWifiSmeEventMaskSetCfmDes, CsrWifiSmeEventMaskSetCfmSerFree }, - { CSR_WIFI_SME_HOST_CONFIG_GET_CFM, CsrWifiSmeHostConfigGetCfmSizeof, CsrWifiSmeHostConfigGetCfmSer, CsrWifiSmeHostConfigGetCfmDes, CsrWifiSmeHostConfigGetCfmSerFree }, - { CSR_WIFI_SME_HOST_CONFIG_SET_CFM, CsrWifiSmeHostConfigSetCfmSizeof, CsrWifiSmeHostConfigSetCfmSer, CsrWifiSmeHostConfigSetCfmDes, CsrWifiSmeHostConfigSetCfmSerFree }, - { CSR_WIFI_SME_IBSS_STATION_IND, CsrWifiSmeIbssStationIndSizeof, CsrWifiSmeIbssStationIndSer, CsrWifiSmeIbssStationIndDes, CsrWifiSmeIbssStationIndSerFree }, - { CSR_WIFI_SME_KEY_CFM, CsrWifiSmeKeyCfmSizeof, CsrWifiSmeKeyCfmSer, CsrWifiSmeKeyCfmDes, CsrWifiSmeKeyCfmSerFree }, - { CSR_WIFI_SME_LINK_QUALITY_GET_CFM, CsrWifiSmeLinkQualityGetCfmSizeof, CsrWifiSmeLinkQualityGetCfmSer, CsrWifiSmeLinkQualityGetCfmDes, CsrWifiSmeLinkQualityGetCfmSerFree }, - { CSR_WIFI_SME_MEDIA_STATUS_IND, CsrWifiSmeMediaStatusIndSizeof, CsrWifiSmeMediaStatusIndSer, CsrWifiSmeMediaStatusIndDes, CsrWifiSmeMediaStatusIndSerFree }, - { CSR_WIFI_SME_MIB_CONFIG_GET_CFM, CsrWifiSmeMibConfigGetCfmSizeof, CsrWifiSmeMibConfigGetCfmSer, CsrWifiSmeMibConfigGetCfmDes, CsrWifiSmeMibConfigGetCfmSerFree }, - { CSR_WIFI_SME_MIB_CONFIG_SET_CFM, CsrWifiSmeMibConfigSetCfmSizeof, CsrWifiSmeMibConfigSetCfmSer, CsrWifiSmeMibConfigSetCfmDes, CsrWifiSmeMibConfigSetCfmSerFree }, - { CSR_WIFI_SME_MIB_GET_CFM, CsrWifiSmeMibGetCfmSizeof, CsrWifiSmeMibGetCfmSer, CsrWifiSmeMibGetCfmDes, CsrWifiSmeMibGetCfmSerFree }, - { CSR_WIFI_SME_MIB_GET_NEXT_CFM, CsrWifiSmeMibGetNextCfmSizeof, CsrWifiSmeMibGetNextCfmSer, CsrWifiSmeMibGetNextCfmDes, CsrWifiSmeMibGetNextCfmSerFree }, - { CSR_WIFI_SME_MIB_SET_CFM, CsrWifiSmeMibSetCfmSizeof, CsrWifiSmeMibSetCfmSer, CsrWifiSmeMibSetCfmDes, CsrWifiSmeMibSetCfmSerFree }, - { CSR_WIFI_SME_MIC_FAILURE_IND, CsrWifiSmeMicFailureIndSizeof, CsrWifiSmeMicFailureIndSer, CsrWifiSmeMicFailureIndDes, CsrWifiSmeMicFailureIndSerFree }, - { CSR_WIFI_SME_MULTICAST_ADDRESS_CFM, CsrWifiSmeMulticastAddressCfmSizeof, CsrWifiSmeMulticastAddressCfmSer, CsrWifiSmeMulticastAddressCfmDes, CsrWifiSmeMulticastAddressCfmSerFree }, - { CSR_WIFI_SME_PACKET_FILTER_SET_CFM, CsrWifiSmePacketFilterSetCfmSizeof, CsrWifiSmePacketFilterSetCfmSer, CsrWifiSmePacketFilterSetCfmDes, CsrWifiSmePacketFilterSetCfmSerFree }, - { CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM, CsrWifiSmePermanentMacAddressGetCfmSizeof, CsrWifiSmePermanentMacAddressGetCfmSer, CsrWifiSmePermanentMacAddressGetCfmDes, CsrWifiSmePermanentMacAddressGetCfmSerFree }, - { CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND, CsrWifiSmePmkidCandidateListIndSizeof, CsrWifiSmePmkidCandidateListIndSer, CsrWifiSmePmkidCandidateListIndDes, CsrWifiSmePmkidCandidateListIndSerFree }, - { CSR_WIFI_SME_PMKID_CFM, CsrWifiSmePmkidCfmSizeof, CsrWifiSmePmkidCfmSer, CsrWifiSmePmkidCfmDes, CsrWifiSmePmkidCfmSerFree }, - { CSR_WIFI_SME_POWER_CONFIG_GET_CFM, CsrWifiSmePowerConfigGetCfmSizeof, CsrWifiSmePowerConfigGetCfmSer, CsrWifiSmePowerConfigGetCfmDes, CsrWifiSmePowerConfigGetCfmSerFree }, - { CSR_WIFI_SME_POWER_CONFIG_SET_CFM, CsrWifiSmePowerConfigSetCfmSizeof, CsrWifiSmePowerConfigSetCfmSer, CsrWifiSmePowerConfigSetCfmDes, CsrWifiSmePowerConfigSetCfmSerFree }, - { CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM, CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof, CsrWifiSmeRegulatoryDomainInfoGetCfmSer, CsrWifiSmeRegulatoryDomainInfoGetCfmDes, CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree }, - { CSR_WIFI_SME_ROAM_COMPLETE_IND, CsrWifiSmeRoamCompleteIndSizeof, CsrWifiSmeRoamCompleteIndSer, CsrWifiSmeRoamCompleteIndDes, CsrWifiSmeRoamCompleteIndSerFree }, - { CSR_WIFI_SME_ROAM_START_IND, CsrWifiSmeRoamStartIndSizeof, CsrWifiSmeRoamStartIndSer, CsrWifiSmeRoamStartIndDes, CsrWifiSmeRoamStartIndSerFree }, - { CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM, CsrWifiSmeRoamingConfigGetCfmSizeof, CsrWifiSmeRoamingConfigGetCfmSer, CsrWifiSmeRoamingConfigGetCfmDes, CsrWifiSmeRoamingConfigGetCfmSerFree }, - { CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM, CsrWifiSmeRoamingConfigSetCfmSizeof, CsrWifiSmeRoamingConfigSetCfmSer, CsrWifiSmeRoamingConfigSetCfmDes, CsrWifiSmeRoamingConfigSetCfmSerFree }, - { CSR_WIFI_SME_SCAN_CONFIG_GET_CFM, CsrWifiSmeScanConfigGetCfmSizeof, CsrWifiSmeScanConfigGetCfmSer, CsrWifiSmeScanConfigGetCfmDes, CsrWifiSmeScanConfigGetCfmSerFree }, - { CSR_WIFI_SME_SCAN_CONFIG_SET_CFM, CsrWifiSmeScanConfigSetCfmSizeof, CsrWifiSmeScanConfigSetCfmSer, CsrWifiSmeScanConfigSetCfmDes, CsrWifiSmeScanConfigSetCfmSerFree }, - { CSR_WIFI_SME_SCAN_FULL_CFM, CsrWifiSmeScanFullCfmSizeof, CsrWifiSmeScanFullCfmSer, CsrWifiSmeScanFullCfmDes, CsrWifiSmeScanFullCfmSerFree }, - { CSR_WIFI_SME_SCAN_RESULT_IND, CsrWifiSmeScanResultIndSizeof, CsrWifiSmeScanResultIndSer, CsrWifiSmeScanResultIndDes, CsrWifiSmeScanResultIndSerFree }, - { CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM, CsrWifiSmeScanResultsFlushCfmSizeof, CsrWifiSmeScanResultsFlushCfmSer, CsrWifiSmeScanResultsFlushCfmDes, CsrWifiSmeScanResultsFlushCfmSerFree }, - { CSR_WIFI_SME_SCAN_RESULTS_GET_CFM, CsrWifiSmeScanResultsGetCfmSizeof, CsrWifiSmeScanResultsGetCfmSer, CsrWifiSmeScanResultsGetCfmDes, CsrWifiSmeScanResultsGetCfmSerFree }, - { CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM, CsrWifiSmeSmeStaConfigGetCfmSizeof, CsrWifiSmeSmeStaConfigGetCfmSer, CsrWifiSmeSmeStaConfigGetCfmDes, CsrWifiSmeSmeStaConfigGetCfmSerFree }, - { CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM, CsrWifiSmeSmeStaConfigSetCfmSizeof, CsrWifiSmeSmeStaConfigSetCfmSer, CsrWifiSmeSmeStaConfigSetCfmDes, CsrWifiSmeSmeStaConfigSetCfmSerFree }, - { CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM, CsrWifiSmeStationMacAddressGetCfmSizeof, CsrWifiSmeStationMacAddressGetCfmSer, CsrWifiSmeStationMacAddressGetCfmDes, CsrWifiSmeStationMacAddressGetCfmSerFree }, - { CSR_WIFI_SME_TSPEC_IND, CsrWifiSmeTspecIndSizeof, CsrWifiSmeTspecIndSer, CsrWifiSmeTspecIndDes, CsrWifiSmeTspecIndSerFree }, - { CSR_WIFI_SME_TSPEC_CFM, CsrWifiSmeTspecCfmSizeof, CsrWifiSmeTspecCfmSer, CsrWifiSmeTspecCfmDes, CsrWifiSmeTspecCfmSerFree }, - { CSR_WIFI_SME_VERSIONS_GET_CFM, CsrWifiSmeVersionsGetCfmSizeof, CsrWifiSmeVersionsGetCfmSer, CsrWifiSmeVersionsGetCfmDes, CsrWifiSmeVersionsGetCfmSerFree }, - { CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM, CsrWifiSmeWifiFlightmodeCfmSizeof, CsrWifiSmeWifiFlightmodeCfmSer, CsrWifiSmeWifiFlightmodeCfmDes, CsrWifiSmeWifiFlightmodeCfmSerFree }, - { CSR_WIFI_SME_WIFI_OFF_IND, CsrWifiSmeWifiOffIndSizeof, CsrWifiSmeWifiOffIndSer, CsrWifiSmeWifiOffIndDes, CsrWifiSmeWifiOffIndSerFree }, - { CSR_WIFI_SME_WIFI_OFF_CFM, CsrWifiSmeWifiOffCfmSizeof, CsrWifiSmeWifiOffCfmSer, CsrWifiSmeWifiOffCfmDes, CsrWifiSmeWifiOffCfmSerFree }, - { CSR_WIFI_SME_WIFI_ON_CFM, CsrWifiSmeWifiOnCfmSizeof, CsrWifiSmeWifiOnCfmSer, CsrWifiSmeWifiOnCfmDes, CsrWifiSmeWifiOnCfmSerFree }, - { CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM, CsrWifiSmeCloakedSsidsSetCfmSizeof, CsrWifiSmeCloakedSsidsSetCfmSer, CsrWifiSmeCloakedSsidsSetCfmDes, CsrWifiSmeCloakedSsidsSetCfmSerFree }, - { CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM, CsrWifiSmeCloakedSsidsGetCfmSizeof, CsrWifiSmeCloakedSsidsGetCfmSer, CsrWifiSmeCloakedSsidsGetCfmDes, CsrWifiSmeCloakedSsidsGetCfmSerFree }, - { CSR_WIFI_SME_WIFI_ON_IND, CsrWifiSmeWifiOnIndSizeof, CsrWifiSmeWifiOnIndSer, CsrWifiSmeWifiOnIndDes, CsrWifiSmeWifiOnIndSerFree }, - { CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM, CsrWifiSmeSmeCommonConfigGetCfmSizeof, CsrWifiSmeSmeCommonConfigGetCfmSer, CsrWifiSmeSmeCommonConfigGetCfmDes, CsrWifiSmeSmeCommonConfigGetCfmSerFree }, - { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM, CsrWifiSmeSmeCommonConfigSetCfmSizeof, CsrWifiSmeSmeCommonConfigSetCfmSer, CsrWifiSmeSmeCommonConfigSetCfmDes, CsrWifiSmeSmeCommonConfigSetCfmSerFree }, - { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM, CsrWifiSmeInterfaceCapabilityGetCfmSizeof, CsrWifiSmeInterfaceCapabilityGetCfmSer, CsrWifiSmeInterfaceCapabilityGetCfmDes, CsrWifiSmeInterfaceCapabilityGetCfmSerFree }, - { CSR_WIFI_SME_ERROR_IND, CsrWifiSmeErrorIndSizeof, CsrWifiSmeErrorIndSer, CsrWifiSmeErrorIndDes, CsrWifiSmeErrorIndSerFree }, - { CSR_WIFI_SME_INFO_IND, CsrWifiSmeInfoIndSizeof, CsrWifiSmeInfoIndSer, CsrWifiSmeInfoIndDes, CsrWifiSmeInfoIndSerFree }, - { CSR_WIFI_SME_CORE_DUMP_IND, CsrWifiSmeCoreDumpIndSizeof, CsrWifiSmeCoreDumpIndSer, CsrWifiSmeCoreDumpIndDes, CsrWifiSmeCoreDumpIndSerFree }, - { CSR_WIFI_SME_AMP_STATUS_CHANGE_IND, CsrWifiSmeAmpStatusChangeIndSizeof, CsrWifiSmeAmpStatusChangeIndSer, CsrWifiSmeAmpStatusChangeIndDes, CsrWifiSmeAmpStatusChangeIndSerFree }, - { CSR_WIFI_SME_WPS_CONFIGURATION_CFM, CsrWifiSmeWpsConfigurationCfmSizeof, CsrWifiSmeWpsConfigurationCfmSer, CsrWifiSmeWpsConfigurationCfmDes, CsrWifiSmeWpsConfigurationCfmSerFree }, - - { 0, NULL, NULL, NULL, NULL }, -}; - -CsrMsgConvMsgEntry* CsrWifiSmeConverterLookup(CsrMsgConvMsgEntry *ce, u16 msgType) -{ - if (msgType & CSR_PRIM_UPSTREAM) - { - u16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT; - if (idx < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) && - csrwifisme_conv_lut[idx].msgType == msgType) - { - return &csrwifisme_conv_lut[idx]; - } - } - else - { - if (msgType < CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT && - csrwifisme_conv_lut[msgType].msgType == msgType) - { - return &csrwifisme_conv_lut[msgType]; - } - } - return NULL; -} - - -void CsrWifiSmeConverterInit(void) -{ - CsrMsgConvInsert(CSR_WIFI_SME_PRIM, csrwifisme_conv_lut); - CsrMsgConvCustomLookupRegister(CSR_WIFI_SME_PRIM, CsrWifiSmeConverterLookup); -} - - -#ifdef CSR_LOG_ENABLE -static const CsrLogPrimitiveInformation csrwifisme_conv_info = { - CSR_WIFI_SME_PRIM, - (char *)"CSR_WIFI_SME_PRIM", - csrwifisme_conv_lut -}; -const CsrLogPrimitiveInformation* CsrWifiSmeTechInfoGet(void) -{ - return &csrwifisme_conv_info; -} - - -#endif /* CSR_LOG_ENABLE */ -#endif /* EXCLUDE_CSR_WIFI_SME_MODULE */ diff --git a/drivers/staging/csr/csr_wifi_sme_converter_init.h b/drivers/staging/csr/csr_wifi_sme_converter_init.h deleted file mode 100644 index ba5e4b44bb6b..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_converter_init.h +++ /dev/null @@ -1,34 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_CONVERTER_INIT_H__ -#define CSR_WIFI_SME_CONVERTER_INIT_H__ - -#ifndef EXCLUDE_CSR_WIFI_SME_MODULE - -#include "csr_msgconv.h" - -#ifdef CSR_LOG_ENABLE -#include "csr_log.h" - -extern const CsrLogPrimitiveInformation* CsrWifiSmeTechInfoGet(void); -#endif /* CSR_LOG_ENABLE */ - -extern void CsrWifiSmeConverterInit(void); - -#else /* EXCLUDE_CSR_WIFI_SME_MODULE */ - -#define CsrWifiSmeConverterInit() - -#endif /* EXCLUDE_CSR_WIFI_SME_MODULE */ - -#endif /* CSR_WIFI_SME_CONVERTER_INIT_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c b/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c deleted file mode 100644 index 03b5ddb22cd7..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c +++ /dev/null @@ -1,187 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_sme_prim.h" -#include "csr_wifi_sme_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiSmeFreeDownstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_SME_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiSmeFreeDownstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_SME_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiSmePrim *) message)) - { - case CSR_WIFI_SME_BLACKLIST_REQ: - { - CsrWifiSmeBlacklistReq *p = (CsrWifiSmeBlacklistReq *)message; - kfree(p->setAddresses); - p->setAddresses = NULL; - break; - } - case CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ: - { - CsrWifiSmeCalibrationDataSetReq *p = (CsrWifiSmeCalibrationDataSetReq *)message; - kfree(p->calibrationData); - p->calibrationData = NULL; - break; - } - case CSR_WIFI_SME_CONNECT_REQ: - { - CsrWifiSmeConnectReq *p = (CsrWifiSmeConnectReq *)message; - kfree(p->connectionConfig.mlmeAssociateReqInformationElements); - p->connectionConfig.mlmeAssociateReqInformationElements = NULL; - break; - } - case CSR_WIFI_SME_MIB_GET_NEXT_REQ: - { - CsrWifiSmeMibGetNextReq *p = (CsrWifiSmeMibGetNextReq *)message; - kfree(p->mibAttribute); - p->mibAttribute = NULL; - break; - } - case CSR_WIFI_SME_MIB_GET_REQ: - { - CsrWifiSmeMibGetReq *p = (CsrWifiSmeMibGetReq *)message; - kfree(p->mibAttribute); - p->mibAttribute = NULL; - break; - } - case CSR_WIFI_SME_MIB_SET_REQ: - { - CsrWifiSmeMibSetReq *p = (CsrWifiSmeMibSetReq *)message; - kfree(p->mibAttribute); - p->mibAttribute = NULL; - break; - } - case CSR_WIFI_SME_MULTICAST_ADDRESS_REQ: - { - CsrWifiSmeMulticastAddressReq *p = (CsrWifiSmeMulticastAddressReq *)message; - kfree(p->setAddresses); - p->setAddresses = NULL; - break; - } - case CSR_WIFI_SME_PACKET_FILTER_SET_REQ: - { - CsrWifiSmePacketFilterSetReq *p = (CsrWifiSmePacketFilterSetReq *)message; - kfree(p->filter); - p->filter = NULL; - break; - } - case CSR_WIFI_SME_PMKID_REQ: - { - CsrWifiSmePmkidReq *p = (CsrWifiSmePmkidReq *)message; - kfree(p->setPmkids); - p->setPmkids = NULL; - break; - } - case CSR_WIFI_SME_SCAN_CONFIG_SET_REQ: - { - CsrWifiSmeScanConfigSetReq *p = (CsrWifiSmeScanConfigSetReq *)message; - kfree(p->scanConfig.passiveChannelList); - p->scanConfig.passiveChannelList = NULL; - break; - } - case CSR_WIFI_SME_SCAN_FULL_REQ: - { - CsrWifiSmeScanFullReq *p = (CsrWifiSmeScanFullReq *)message; - kfree(p->ssid); - p->ssid = NULL; - kfree(p->channelList); - p->channelList = NULL; - kfree(p->probeIe); - p->probeIe = NULL; - break; - } - case CSR_WIFI_SME_TSPEC_REQ: - { - CsrWifiSmeTspecReq *p = (CsrWifiSmeTspecReq *)message; - kfree(p->tspec); - p->tspec = NULL; - kfree(p->tclas); - p->tclas = NULL; - break; - } - case CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ: - { - CsrWifiSmeWifiFlightmodeReq *p = (CsrWifiSmeWifiFlightmodeReq *)message; - { - u16 i1; - for (i1 = 0; i1 < p->mibFilesCount; i1++) - { - kfree(p->mibFiles[i1].data); - p->mibFiles[i1].data = NULL; - } - } - kfree(p->mibFiles); - p->mibFiles = NULL; - break; - } - case CSR_WIFI_SME_WIFI_ON_REQ: - { - CsrWifiSmeWifiOnReq *p = (CsrWifiSmeWifiOnReq *)message; - { - u16 i1; - for (i1 = 0; i1 < p->mibFilesCount; i1++) - { - kfree(p->mibFiles[i1].data); - p->mibFiles[i1].data = NULL; - } - } - kfree(p->mibFiles); - p->mibFiles = NULL; - break; - } - case CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ: - { - CsrWifiSmeCloakedSsidsSetReq *p = (CsrWifiSmeCloakedSsidsSetReq *)message; - kfree(p->cloakedSsids.cloakedSsids); - p->cloakedSsids.cloakedSsids = NULL; - break; - } - case CSR_WIFI_SME_WPS_CONFIGURATION_REQ: - { - CsrWifiSmeWpsConfigurationReq *p = (CsrWifiSmeWpsConfigurationReq *)message; - kfree(p->wpsConfig.secondaryDeviceType); - p->wpsConfig.secondaryDeviceType = NULL; - break; - } - case CSR_WIFI_SME_SET_REQ: - { - CsrWifiSmeSetReq *p = (CsrWifiSmeSetReq *)message; - kfree(p->data); - p->data = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c b/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c deleted file mode 100644 index c04767baaa5b..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_free_upstream_contents.c +++ /dev/null @@ -1,275 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include "csr_wifi_sme_prim.h" -#include "csr_wifi_sme_lib.h" - -/*----------------------------------------------------------------------------* - * NAME - * CsrWifiSmeFreeUpstreamMessageContents - * - * DESCRIPTION - * - * - * PARAMETERS - * eventClass: only the value CSR_WIFI_SME_PRIM will be handled - * message: the message to free - *----------------------------------------------------------------------------*/ -void CsrWifiSmeFreeUpstreamMessageContents(u16 eventClass, void *message) -{ - if (eventClass != CSR_WIFI_SME_PRIM) - { - return; - } - if (NULL == message) - { - return; - } - - switch (*((CsrWifiSmePrim *) message)) - { - case CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND: - { - CsrWifiSmeAssociationCompleteInd *p = (CsrWifiSmeAssociationCompleteInd *)message; - kfree(p->connectionInfo.beaconFrame); - p->connectionInfo.beaconFrame = NULL; - kfree(p->connectionInfo.associationReqFrame); - p->connectionInfo.associationReqFrame = NULL; - kfree(p->connectionInfo.associationRspFrame); - p->connectionInfo.associationRspFrame = NULL; - kfree(p->connectionInfo.assocScanInfoElements); - p->connectionInfo.assocScanInfoElements = NULL; - kfree(p->connectionInfo.assocReqInfoElements); - p->connectionInfo.assocReqInfoElements = NULL; - kfree(p->connectionInfo.assocRspInfoElements); - p->connectionInfo.assocRspInfoElements = NULL; - break; - } - case CSR_WIFI_SME_BLACKLIST_CFM: - { - CsrWifiSmeBlacklistCfm *p = (CsrWifiSmeBlacklistCfm *)message; - kfree(p->getAddresses); - p->getAddresses = NULL; - break; - } - case CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM: - { - CsrWifiSmeCalibrationDataGetCfm *p = (CsrWifiSmeCalibrationDataGetCfm *)message; - kfree(p->calibrationData); - p->calibrationData = NULL; - break; - } - case CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM: - { - CsrWifiSmeConnectionConfigGetCfm *p = (CsrWifiSmeConnectionConfigGetCfm *)message; - kfree(p->connectionConfig.mlmeAssociateReqInformationElements); - p->connectionConfig.mlmeAssociateReqInformationElements = NULL; - break; - } - case CSR_WIFI_SME_CONNECTION_INFO_GET_CFM: - { - CsrWifiSmeConnectionInfoGetCfm *p = (CsrWifiSmeConnectionInfoGetCfm *)message; - kfree(p->connectionInfo.beaconFrame); - p->connectionInfo.beaconFrame = NULL; - kfree(p->connectionInfo.associationReqFrame); - p->connectionInfo.associationReqFrame = NULL; - kfree(p->connectionInfo.associationRspFrame); - p->connectionInfo.associationRspFrame = NULL; - kfree(p->connectionInfo.assocScanInfoElements); - p->connectionInfo.assocScanInfoElements = NULL; - kfree(p->connectionInfo.assocReqInfoElements); - p->connectionInfo.assocReqInfoElements = NULL; - kfree(p->connectionInfo.assocRspInfoElements); - p->connectionInfo.assocRspInfoElements = NULL; - break; - } - case CSR_WIFI_SME_MEDIA_STATUS_IND: - { - CsrWifiSmeMediaStatusInd *p = (CsrWifiSmeMediaStatusInd *)message; - kfree(p->connectionInfo.beaconFrame); - p->connectionInfo.beaconFrame = NULL; - kfree(p->connectionInfo.associationReqFrame); - p->connectionInfo.associationReqFrame = NULL; - kfree(p->connectionInfo.associationRspFrame); - p->connectionInfo.associationRspFrame = NULL; - kfree(p->connectionInfo.assocScanInfoElements); - p->connectionInfo.assocScanInfoElements = NULL; - kfree(p->connectionInfo.assocReqInfoElements); - p->connectionInfo.assocReqInfoElements = NULL; - kfree(p->connectionInfo.assocRspInfoElements); - p->connectionInfo.assocRspInfoElements = NULL; - break; - } - case CSR_WIFI_SME_MIB_GET_CFM: - { - CsrWifiSmeMibGetCfm *p = (CsrWifiSmeMibGetCfm *)message; - kfree(p->mibAttribute); - p->mibAttribute = NULL; - break; - } - case CSR_WIFI_SME_MIB_GET_NEXT_CFM: - { - CsrWifiSmeMibGetNextCfm *p = (CsrWifiSmeMibGetNextCfm *)message; - kfree(p->mibAttribute); - p->mibAttribute = NULL; - break; - } - case CSR_WIFI_SME_MULTICAST_ADDRESS_CFM: - { - CsrWifiSmeMulticastAddressCfm *p = (CsrWifiSmeMulticastAddressCfm *)message; - kfree(p->getAddresses); - p->getAddresses = NULL; - break; - } - case CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND: - { - CsrWifiSmePmkidCandidateListInd *p = (CsrWifiSmePmkidCandidateListInd *)message; - kfree(p->pmkidCandidates); - p->pmkidCandidates = NULL; - break; - } - case CSR_WIFI_SME_PMKID_CFM: - { - CsrWifiSmePmkidCfm *p = (CsrWifiSmePmkidCfm *)message; - kfree(p->getPmkids); - p->getPmkids = NULL; - break; - } - case CSR_WIFI_SME_SCAN_CONFIG_GET_CFM: - { - CsrWifiSmeScanConfigGetCfm *p = (CsrWifiSmeScanConfigGetCfm *)message; - kfree(p->scanConfig.passiveChannelList); - p->scanConfig.passiveChannelList = NULL; - break; - } - case CSR_WIFI_SME_SCAN_RESULT_IND: - { - CsrWifiSmeScanResultInd *p = (CsrWifiSmeScanResultInd *)message; - kfree(p->result.informationElements); - p->result.informationElements = NULL; - switch (p->result.p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_GO: - { - u16 i4; - for (i4 = 0; i4 < p->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - kfree(p->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); - p->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; - } - } - kfree(p->result.deviceInfo.groupInfo.p2PClientInfo); - p->result.deviceInfo.groupInfo.p2PClientInfo = NULL; - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - kfree(p->result.deviceInfo.standalonedevInfo.secDeviceType); - p->result.deviceInfo.standalonedevInfo.secDeviceType = NULL; - break; - default: - break; - } - break; - } - case CSR_WIFI_SME_SCAN_RESULTS_GET_CFM: - { - CsrWifiSmeScanResultsGetCfm *p = (CsrWifiSmeScanResultsGetCfm *)message; - { - u16 i1; - for (i1 = 0; i1 < p->scanResultsCount; i1++) - { - kfree(p->scanResults[i1].informationElements); - p->scanResults[i1].informationElements = NULL; - switch (p->scanResults[i1].p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_GO: - { - u16 i4; - for (i4 = 0; i4 < p->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - kfree(p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); - p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; - } - } - kfree(p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo); - p->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = NULL; - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - kfree(p->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType); - p->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = NULL; - break; - default: - break; - } - } - } - kfree(p->scanResults); - p->scanResults = NULL; - break; - } - case CSR_WIFI_SME_TSPEC_IND: - { - CsrWifiSmeTspecInd *p = (CsrWifiSmeTspecInd *)message; - kfree(p->tspec); - p->tspec = NULL; - break; - } - case CSR_WIFI_SME_TSPEC_CFM: - { - CsrWifiSmeTspecCfm *p = (CsrWifiSmeTspecCfm *)message; - kfree(p->tspec); - p->tspec = NULL; - break; - } - case CSR_WIFI_SME_VERSIONS_GET_CFM: - { - CsrWifiSmeVersionsGetCfm *p = (CsrWifiSmeVersionsGetCfm *)message; - kfree(p->versions.routerBuild); - p->versions.routerBuild = NULL; - kfree(p->versions.smeBuild); - p->versions.smeBuild = NULL; - break; - } - case CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM: - { - CsrWifiSmeCloakedSsidsGetCfm *p = (CsrWifiSmeCloakedSsidsGetCfm *)message; - kfree(p->cloakedSsids.cloakedSsids); - p->cloakedSsids.cloakedSsids = NULL; - break; - } - case CSR_WIFI_SME_ERROR_IND: - { - CsrWifiSmeErrorInd *p = (CsrWifiSmeErrorInd *)message; - kfree(p->errorMessage); - p->errorMessage = NULL; - break; - } - case CSR_WIFI_SME_INFO_IND: - { - CsrWifiSmeInfoInd *p = (CsrWifiSmeInfoInd *)message; - kfree(p->infoMessage); - p->infoMessage = NULL; - break; - } - case CSR_WIFI_SME_CORE_DUMP_IND: - { - CsrWifiSmeCoreDumpInd *p = (CsrWifiSmeCoreDumpInd *)message; - kfree(p->data); - p->data = NULL; - break; - } - - default: - break; - } -} - - diff --git a/drivers/staging/csr/csr_wifi_sme_lib.h b/drivers/staging/csr/csr_wifi_sme_lib.h deleted file mode 100644 index 53cf1268286e..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_lib.h +++ /dev/null @@ -1,4303 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_LIB_H__ -#define CSR_WIFI_SME_LIB_H__ - -#include "csr_sched.h" -#include "csr_macro.h" -#include "csr_msg_transport.h" - -#include "csr_wifi_lib.h" - -#include "csr_wifi_sme_prim.h" -#include "csr_wifi_sme_task.h" - - -#ifndef CSR_WIFI_SME_LIB_DESTINATION_QUEUE -# ifdef CSR_WIFI_NME_ENABLE -# include "csr_wifi_nme_task.h" -# define CSR_WIFI_SME_LIB_DESTINATION_QUEUE CSR_WIFI_NME_IFACEQUEUE -# else -# define CSR_WIFI_SME_LIB_DESTINATION_QUEUE CSR_WIFI_SME_IFACEQUEUE -# endif -#endif - -/*----------------------------------------------------------------------------* - * CsrWifiSmeFreeUpstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_SME upstream message. Does not - * free the message itself, and can only be used for upstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_SME upstream message - *----------------------------------------------------------------------------*/ -void CsrWifiSmeFreeUpstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * CsrWifiSmeFreeDownstreamMessageContents - * - * DESCRIPTION - * Free the allocated memory in a CSR_WIFI_SME downstream message. Does not - * free the message itself, and can only be used for downstream messages. - * - * PARAMETERS - * Deallocates the resources in a CSR_WIFI_SME downstream message - *----------------------------------------------------------------------------*/ -void CsrWifiSmeFreeDownstreamMessageContents(u16 eventClass, void *message); - -/*----------------------------------------------------------------------------* - * Enum to string functions - *----------------------------------------------------------------------------*/ -const char* CsrWifiSme80211NetworkTypeToString(CsrWifiSme80211NetworkType value); -const char* CsrWifiSme80211PrivacyModeToString(CsrWifiSme80211PrivacyMode value); -const char* CsrWifiSme80211dTrustLevelToString(CsrWifiSme80211dTrustLevel value); -const char* CsrWifiSmeAmpStatusToString(CsrWifiSmeAmpStatus value); -const char* CsrWifiSmeAuthModeToString(CsrWifiSmeAuthMode value); -const char* CsrWifiSmeBasicUsabilityToString(CsrWifiSmeBasicUsability value); -const char* CsrWifiSmeBssTypeToString(CsrWifiSmeBssType value); -const char* CsrWifiSmeCoexSchemeToString(CsrWifiSmeCoexScheme value); -const char* CsrWifiSmeControlIndicationToString(CsrWifiSmeControlIndication value); -const char* CsrWifiSmeCtsProtectionTypeToString(CsrWifiSmeCtsProtectionType value); -const char* CsrWifiSmeD3AutoScanModeToString(CsrWifiSmeD3AutoScanMode value); -const char* CsrWifiSmeEncryptionToString(CsrWifiSmeEncryption value); -const char* CsrWifiSmeFirmwareDriverInterfaceToString(CsrWifiSmeFirmwareDriverInterface value); -const char* CsrWifiSmeHostPowerModeToString(CsrWifiSmeHostPowerMode value); -const char* CsrWifiSmeIEEE80211ReasonToString(CsrWifiSmeIEEE80211Reason value); -const char* CsrWifiSmeIEEE80211ResultToString(CsrWifiSmeIEEE80211Result value); -const char* CsrWifiSmeIndicationsToString(CsrWifiSmeIndications value); -const char* CsrWifiSmeKeyTypeToString(CsrWifiSmeKeyType value); -const char* CsrWifiSmeListActionToString(CsrWifiSmeListAction value); -const char* CsrWifiSmeMediaStatusToString(CsrWifiSmeMediaStatus value); -const char* CsrWifiSmeP2pCapabilityToString(CsrWifiSmeP2pCapability value); -const char* CsrWifiSmeP2pGroupCapabilityToString(CsrWifiSmeP2pGroupCapability value); -const char* CsrWifiSmeP2pNoaConfigMethodToString(CsrWifiSmeP2pNoaConfigMethod value); -const char* CsrWifiSmeP2pRoleToString(CsrWifiSmeP2pRole value); -const char* CsrWifiSmeP2pStatusToString(CsrWifiSmeP2pStatus value); -const char* CsrWifiSmePacketFilterModeToString(CsrWifiSmePacketFilterMode value); -const char* CsrWifiSmePowerSaveLevelToString(CsrWifiSmePowerSaveLevel value); -const char* CsrWifiSmePreambleTypeToString(CsrWifiSmePreambleType value); -const char* CsrWifiSmeRadioIFToString(CsrWifiSmeRadioIF value); -const char* CsrWifiSmeRegulatoryDomainToString(CsrWifiSmeRegulatoryDomain value); -const char* CsrWifiSmeRoamReasonToString(CsrWifiSmeRoamReason value); -const char* CsrWifiSmeScanTypeToString(CsrWifiSmeScanType value); -const char* CsrWifiSmeTrafficTypeToString(CsrWifiSmeTrafficType value); -const char* CsrWifiSmeTspecCtrlToString(CsrWifiSmeTspecCtrl value); -const char* CsrWifiSmeTspecResultCodeToString(CsrWifiSmeTspecResultCode value); -const char* CsrWifiSmeWepAuthModeToString(CsrWifiSmeWepAuthMode value); -const char* CsrWifiSmeWepCredentialTypeToString(CsrWifiSmeWepCredentialType value); -const char* CsrWifiSmeWmmModeToString(CsrWifiSmeWmmMode value); -const char* CsrWifiSmeWmmQosInfoToString(CsrWifiSmeWmmQosInfo value); -const char* CsrWifiSmeWpsConfigTypeToString(CsrWifiSmeWpsConfigType value); -const char* CsrWifiSmeWpsDeviceCategoryToString(CsrWifiSmeWpsDeviceCategory value); -const char* CsrWifiSmeWpsDeviceSubCategoryToString(CsrWifiSmeWpsDeviceSubCategory value); -const char* CsrWifiSmeWpsDpidToString(CsrWifiSmeWpsDpid value); -const char* CsrWifiSmeWpsRegistrationToString(CsrWifiSmeWpsRegistration value); - - -/*----------------------------------------------------------------------------* - * CsrPrim Type toString function. - * Converts a message type to the String name of the Message - *----------------------------------------------------------------------------*/ -const char* CsrWifiSmePrimTypeToString(CsrPrim msgType); - -/*----------------------------------------------------------------------------* - * Lookup arrays for PrimType name Strings - *----------------------------------------------------------------------------*/ -extern const char *CsrWifiSmeUpstreamPrimNames[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT]; -extern const char *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT]; - -/******************************************************************************* - - NAME - CsrWifiSmeActivateReqSend - - DESCRIPTION - The WMA sends this primitive to activate the SME. - The WMA must activate the SME before it can send any other primitive. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeActivateReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeActivateReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ACTIVATE_REQ, dst__, src__); - -#define CsrWifiSmeActivateReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeActivateReq *msg__; \ - CsrWifiSmeActivateReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeActivateReqSend(src__) \ - CsrWifiSmeActivateReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeActivateCfmSend - - DESCRIPTION - The SME sends this primitive when the activation is complete. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeActivateCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeActivateCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ACTIVATE_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeActivateCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeActivateCfm *msg__; \ - CsrWifiSmeActivateCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeActivateCfmSend(dst__, status__) \ - CsrWifiSmeActivateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the adHocConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeAdhocConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAdhocConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmeAdhocConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeAdhocConfigGetReq *msg__; \ - CsrWifiSmeAdhocConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAdhocConfigGetReqSend(src__) \ - CsrWifiSmeAdhocConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - adHocConfig - Contains the values used when starting an Ad-hoc (IBSS) - connection. - -*******************************************************************************/ -#define CsrWifiSmeAdhocConfigGetCfmCreate(msg__, dst__, src__, status__, adHocConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAdhocConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->adHocConfig = (adHocConfig__); - -#define CsrWifiSmeAdhocConfigGetCfmSendTo(dst__, src__, status__, adHocConfig__) \ - { \ - CsrWifiSmeAdhocConfigGetCfm *msg__; \ - CsrWifiSmeAdhocConfigGetCfmCreate(msg__, dst__, src__, status__, adHocConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAdhocConfigGetCfmSend(dst__, status__, adHocConfig__) \ - CsrWifiSmeAdhocConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, adHocConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the adHocConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - adHocConfig - Sets the values to use when starting an ad hoc network. - -*******************************************************************************/ -#define CsrWifiSmeAdhocConfigSetReqCreate(msg__, dst__, src__, adHocConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAdhocConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ, dst__, src__); \ - msg__->adHocConfig = (adHocConfig__); - -#define CsrWifiSmeAdhocConfigSetReqSendTo(dst__, src__, adHocConfig__) \ - { \ - CsrWifiSmeAdhocConfigSetReq *msg__; \ - CsrWifiSmeAdhocConfigSetReqCreate(msg__, dst__, src__, adHocConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAdhocConfigSetReqSend(src__, adHocConfig__) \ - CsrWifiSmeAdhocConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, adHocConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeAdhocConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAdhocConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeAdhocConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeAdhocConfigSetCfm *msg__; \ - CsrWifiSmeAdhocConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAdhocConfigSetCfmSend(dst__, status__) \ - CsrWifiSmeAdhocConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeAmpStatusChangeIndSend - - DESCRIPTION - Indication of change to AMP activity. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface on which the AMP activity changed. - ampStatus - The new status of AMP activity.Range: {AMP_ACTIVE, - AMP_INACTIVE}. - -*******************************************************************************/ -#define CsrWifiSmeAmpStatusChangeIndCreate(msg__, dst__, src__, interfaceTag__, ampStatus__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAmpStatusChangeInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_AMP_STATUS_CHANGE_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->ampStatus = (ampStatus__); - -#define CsrWifiSmeAmpStatusChangeIndSendTo(dst__, src__, interfaceTag__, ampStatus__) \ - { \ - CsrWifiSmeAmpStatusChangeInd *msg__; \ - CsrWifiSmeAmpStatusChangeIndCreate(msg__, dst__, src__, interfaceTag__, ampStatus__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAmpStatusChangeIndSend(dst__, interfaceTag__, ampStatus__) \ - CsrWifiSmeAmpStatusChangeIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, ampStatus__) - -/******************************************************************************* - - NAME - CsrWifiSmeAssociationCompleteIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it completes an attempt to associate with an AP. If - the association was successful, status will be set to - CSR_WIFI_SME_STATUS_SUCCESS, otherwise status and deauthReason shall be - set to appropriate error codes. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the association procedure - connectionInfo - This parameter is relevant only if result is - CSR_WIFI_SME_STATUS_SUCCESS: - it points to the connection information for the new network - deauthReason - This parameter is relevant only if result is not - CSR_WIFI_SME_STATUS_SUCCESS: - if the AP deauthorised the station, it gives the reason of - the deauthorization - -*******************************************************************************/ -#define CsrWifiSmeAssociationCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAssociationCompleteInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectionInfo = (connectionInfo__); \ - msg__->deauthReason = (deauthReason__); - -#define CsrWifiSmeAssociationCompleteIndSendTo(dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ - { \ - CsrWifiSmeAssociationCompleteInd *msg__; \ - CsrWifiSmeAssociationCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__, deauthReason__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAssociationCompleteIndSend(dst__, interfaceTag__, status__, connectionInfo__, deauthReason__) \ - CsrWifiSmeAssociationCompleteIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionInfo__, deauthReason__) - -/******************************************************************************* - - NAME - CsrWifiSmeAssociationStartIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it begins an attempt to associate with an AP. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - address - BSSID of the associating network - ssid - Service Set identifier of the associating network - -*******************************************************************************/ -#define CsrWifiSmeAssociationStartIndCreate(msg__, dst__, src__, interfaceTag__, address__, ssid__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeAssociationStartInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ASSOCIATION_START_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->address = (address__); \ - msg__->ssid = (ssid__); - -#define CsrWifiSmeAssociationStartIndSendTo(dst__, src__, interfaceTag__, address__, ssid__) \ - { \ - CsrWifiSmeAssociationStartInd *msg__; \ - CsrWifiSmeAssociationStartIndCreate(msg__, dst__, src__, interfaceTag__, address__, ssid__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeAssociationStartIndSend(dst__, interfaceTag__, address__, ssid__) \ - CsrWifiSmeAssociationStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, address__, ssid__) - -/******************************************************************************* - - NAME - CsrWifiSmeBlacklistReqSend - - DESCRIPTION - The wireless manager application should call this primitive to notify the - driver of any networks that should not be connected to. The interface - allows the wireless manager application to query, add, remove, and flush - the BSSIDs that the driver may not connect or roam to. - When this primitive adds to the black list the BSSID to which the SME is - currently connected, the SME will try to roam, if applicable, to another - BSSID in the same ESS; if the roaming procedure fails, the SME will - disconnect. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs - the driver to modify or provide the list of blacklisted - networks. - setAddressCount - Number of BSSIDs sent with this primitive - setAddresses - Pointer to the list of BBSIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmeBlacklistReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeBlacklistReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_BLACKLIST_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->setAddressCount = (setAddressCount__); \ - msg__->setAddresses = (setAddresses__); - -#define CsrWifiSmeBlacklistReqSendTo(dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ - { \ - CsrWifiSmeBlacklistReq *msg__; \ - CsrWifiSmeBlacklistReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressCount__, setAddresses__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeBlacklistReqSend(src__, interfaceTag__, action__, setAddressCount__, setAddresses__) \ - CsrWifiSmeBlacklistReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setAddressCount__, setAddresses__) - -/******************************************************************************* - - NAME - CsrWifiSmeBlacklistCfmSend - - DESCRIPTION - The SME will call this primitive when the action on the blacklist has - completed. For a GET action, this primitive also reports the list of - BBSIDs in the blacklist. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getAddressCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of BSSIDs sent with this primitive - getAddresses - Pointer to the list of BBSIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmeBlacklistCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeBlacklistCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_BLACKLIST_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->action = (action__); \ - msg__->getAddressCount = (getAddressCount__); \ - msg__->getAddresses = (getAddresses__); - -#define CsrWifiSmeBlacklistCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ - { \ - CsrWifiSmeBlacklistCfm *msg__; \ - CsrWifiSmeBlacklistCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeBlacklistCfmSend(dst__, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) \ - CsrWifiSmeBlacklistCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getAddressCount__, getAddresses__) - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataGetReqSend - - DESCRIPTION - This primitive retrieves the Wi-Fi radio calibration data. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeCalibrationDataGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCalibrationDataGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ, dst__, src__); - -#define CsrWifiSmeCalibrationDataGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeCalibrationDataGetReq *msg__; \ - CsrWifiSmeCalibrationDataGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCalibrationDataGetReqSend(src__) \ - CsrWifiSmeCalibrationDataGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - calibrationDataLength - Number of bytes in the buffer pointed by - calibrationData - calibrationData - Pointer to a buffer of length calibrationDataLength - containing the calibration data - -*******************************************************************************/ -#define CsrWifiSmeCalibrationDataGetCfmCreate(msg__, dst__, src__, status__, calibrationDataLength__, calibrationData__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCalibrationDataGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->calibrationDataLength = (calibrationDataLength__); \ - msg__->calibrationData = (calibrationData__); - -#define CsrWifiSmeCalibrationDataGetCfmSendTo(dst__, src__, status__, calibrationDataLength__, calibrationData__) \ - { \ - CsrWifiSmeCalibrationDataGetCfm *msg__; \ - CsrWifiSmeCalibrationDataGetCfmCreate(msg__, dst__, src__, status__, calibrationDataLength__, calibrationData__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCalibrationDataGetCfmSend(dst__, status__, calibrationDataLength__, calibrationData__) \ - CsrWifiSmeCalibrationDataGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, calibrationDataLength__, calibrationData__) - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataSetReqSend - - DESCRIPTION - This primitive sets the Wi-Fi radio calibration data. - The usage of the primitive with proper calibration data will avoid - time-consuming configuration after power-up. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - calibrationDataLength - Number of bytes in the buffer pointed by - calibrationData - calibrationData - Pointer to a buffer of length calibrationDataLength - containing the calibration data - -*******************************************************************************/ -#define CsrWifiSmeCalibrationDataSetReqCreate(msg__, dst__, src__, calibrationDataLength__, calibrationData__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCalibrationDataSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ, dst__, src__); \ - msg__->calibrationDataLength = (calibrationDataLength__); \ - msg__->calibrationData = (calibrationData__); - -#define CsrWifiSmeCalibrationDataSetReqSendTo(dst__, src__, calibrationDataLength__, calibrationData__) \ - { \ - CsrWifiSmeCalibrationDataSetReq *msg__; \ - CsrWifiSmeCalibrationDataSetReqCreate(msg__, dst__, src__, calibrationDataLength__, calibrationData__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCalibrationDataSetReqSend(src__, calibrationDataLength__, calibrationData__) \ - CsrWifiSmeCalibrationDataSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, calibrationDataLength__, calibrationData__) - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeCalibrationDataSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCalibrationDataSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeCalibrationDataSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeCalibrationDataSetCfm *msg__; \ - CsrWifiSmeCalibrationDataSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCalibrationDataSetCfmSend(dst__, status__) \ - CsrWifiSmeCalibrationDataSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the CcxConfig parameter. - CURRENTLY NOT SUPPORTED. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeCcxConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCcxConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeCcxConfigGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeCcxConfigGetReq *msg__; \ - CsrWifiSmeCcxConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCcxConfigGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeCcxConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - ccxConfig - Currently not supported - -*******************************************************************************/ -#define CsrWifiSmeCcxConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ccxConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCcxConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->ccxConfig = (ccxConfig__); - -#define CsrWifiSmeCcxConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, ccxConfig__) \ - { \ - CsrWifiSmeCcxConfigGetCfm *msg__; \ - CsrWifiSmeCcxConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, ccxConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCcxConfigGetCfmSend(dst__, interfaceTag__, status__, ccxConfig__) \ - CsrWifiSmeCcxConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, ccxConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the CcxConfig parameter. - CURRENTLY NOT SUPPORTED. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - ccxConfig - Currently not supported - -*******************************************************************************/ -#define CsrWifiSmeCcxConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, ccxConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCcxConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->ccxConfig = (ccxConfig__); - -#define CsrWifiSmeCcxConfigSetReqSendTo(dst__, src__, interfaceTag__, ccxConfig__) \ - { \ - CsrWifiSmeCcxConfigSetReq *msg__; \ - CsrWifiSmeCcxConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, ccxConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCcxConfigSetReqSend(src__, interfaceTag__, ccxConfig__) \ - CsrWifiSmeCcxConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, ccxConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeCcxConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCcxConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CCX_CONFIG_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeCcxConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeCcxConfigSetCfm *msg__; \ - CsrWifiSmeCcxConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCcxConfigSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeCcxConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsGetReqSend - - DESCRIPTION - This primitive gets the value of the CloakedSsids parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeCloakedSsidsGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCloakedSsidsGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ, dst__, src__); - -#define CsrWifiSmeCloakedSsidsGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeCloakedSsidsGetReq *msg__; \ - CsrWifiSmeCloakedSsidsGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCloakedSsidsGetReqSend(src__) \ - CsrWifiSmeCloakedSsidsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - cloakedSsids - Reports list of cloaked SSIDs that are explicitly scanned for - by the driver - -*******************************************************************************/ -#define CsrWifiSmeCloakedSsidsGetCfmCreate(msg__, dst__, src__, status__, cloakedSsids__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCloakedSsidsGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->cloakedSsids = (cloakedSsids__); - -#define CsrWifiSmeCloakedSsidsGetCfmSendTo(dst__, src__, status__, cloakedSsids__) \ - { \ - CsrWifiSmeCloakedSsidsGetCfm *msg__; \ - CsrWifiSmeCloakedSsidsGetCfmCreate(msg__, dst__, src__, status__, cloakedSsids__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCloakedSsidsGetCfmSend(dst__, status__, cloakedSsids__) \ - CsrWifiSmeCloakedSsidsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, cloakedSsids__) - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsSetReqSend - - DESCRIPTION - This primitive sets the list of cloaked SSIDs for which the WMA possesses - profiles. - When the driver detects a cloaked AP, the SME will explicitly scan for it - using the list of cloaked SSIDs provided it, and, if the scan succeeds, - it will report the AP to the WMA either via CSR_WIFI_SME_SCAN_RESULT_IND - (if registered) or via CSR_WIFI_SCAN_RESULT_GET_CFM. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - cloakedSsids - Sets the list of cloaked SSIDs - -*******************************************************************************/ -#define CsrWifiSmeCloakedSsidsSetReqCreate(msg__, dst__, src__, cloakedSsids__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCloakedSsidsSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ, dst__, src__); \ - msg__->cloakedSsids = (cloakedSsids__); - -#define CsrWifiSmeCloakedSsidsSetReqSendTo(dst__, src__, cloakedSsids__) \ - { \ - CsrWifiSmeCloakedSsidsSetReq *msg__; \ - CsrWifiSmeCloakedSsidsSetReqCreate(msg__, dst__, src__, cloakedSsids__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCloakedSsidsSetReqSend(src__, cloakedSsids__) \ - CsrWifiSmeCloakedSsidsSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, cloakedSsids__) - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeCloakedSsidsSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCloakedSsidsSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeCloakedSsidsSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeCloakedSsidsSetCfm *msg__; \ - CsrWifiSmeCloakedSsidsSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCloakedSsidsSetCfmSend(dst__, status__) \ - CsrWifiSmeCloakedSsidsSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the CoexConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeCoexConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmeCoexConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeCoexConfigGetReq *msg__; \ - CsrWifiSmeCoexConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexConfigGetReqSend(src__) \ - CsrWifiSmeCoexConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - coexConfig - Reports the parameters used to configure the coexistence - behaviour - -*******************************************************************************/ -#define CsrWifiSmeCoexConfigGetCfmCreate(msg__, dst__, src__, status__, coexConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->coexConfig = (coexConfig__); - -#define CsrWifiSmeCoexConfigGetCfmSendTo(dst__, src__, status__, coexConfig__) \ - { \ - CsrWifiSmeCoexConfigGetCfm *msg__; \ - CsrWifiSmeCoexConfigGetCfmCreate(msg__, dst__, src__, status__, coexConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexConfigGetCfmSend(dst__, status__, coexConfig__) \ - CsrWifiSmeCoexConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, coexConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the CoexConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - coexConfig - Configures the coexistence behaviour - -*******************************************************************************/ -#define CsrWifiSmeCoexConfigSetReqCreate(msg__, dst__, src__, coexConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_SET_REQ, dst__, src__); \ - msg__->coexConfig = (coexConfig__); - -#define CsrWifiSmeCoexConfigSetReqSendTo(dst__, src__, coexConfig__) \ - { \ - CsrWifiSmeCoexConfigSetReq *msg__; \ - CsrWifiSmeCoexConfigSetReqCreate(msg__, dst__, src__, coexConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexConfigSetReqSend(src__, coexConfig__) \ - CsrWifiSmeCoexConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, coexConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeCoexConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeCoexConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeCoexConfigSetCfm *msg__; \ - CsrWifiSmeCoexConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexConfigSetCfmSend(dst__, status__) \ - CsrWifiSmeCoexConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexInfoGetReqSend - - DESCRIPTION - This primitive gets the value of the CoexInfo parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeCoexInfoGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexInfoGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_INFO_GET_REQ, dst__, src__); - -#define CsrWifiSmeCoexInfoGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeCoexInfoGetReq *msg__; \ - CsrWifiSmeCoexInfoGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexInfoGetReqSend(src__) \ - CsrWifiSmeCoexInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexInfoGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - coexInfo - Reports information and state related to coexistence. - -*******************************************************************************/ -#define CsrWifiSmeCoexInfoGetCfmCreate(msg__, dst__, src__, status__, coexInfo__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoexInfoGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_COEX_INFO_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->coexInfo = (coexInfo__); - -#define CsrWifiSmeCoexInfoGetCfmSendTo(dst__, src__, status__, coexInfo__) \ - { \ - CsrWifiSmeCoexInfoGetCfm *msg__; \ - CsrWifiSmeCoexInfoGetCfmCreate(msg__, dst__, src__, status__, coexInfo__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoexInfoGetCfmSend(dst__, status__, coexInfo__) \ - CsrWifiSmeCoexInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, coexInfo__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectReqSend - - DESCRIPTION - The wireless manager application calls this primitive to start the - process of joining an 802.11 wireless network or to start an ad hoc - network. - The structure pointed by connectionConfig contains parameters describing - the network to join or, in case of an ad hoc network, to host or join. - The SME will select a network, perform the IEEE 802.11 Join, Authenticate - and Associate exchanges. - The SME selects the networks from the current scan list that match both - the SSID and BSSID, however either or both of these may be the wildcard - value. Using this rule, the following operations are possible: - * To connect to a network by name, specify the SSID and set the BSSID to - 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF. If there are two or more networks visible, - the SME will select the one with the strongest signal. - * To connect to a specific network, specify the BSSID. The SSID is - optional, but if given it must match the SSID of the network. An empty - SSID may be specified by setting the SSID length to zero. Please note - that if the BSSID is specified (i.e. not equal to 0xFF 0xFF 0xFF 0xFF - 0xFF 0xFF), the SME will not attempt to roam if signal conditions become - poor, even if there is an alternative AP with an SSID that matches the - current network SSID. - * To connect to any network matching the other parameters (i.e. security, - etc), set the SSID length to zero and set the BSSID to 0xFF 0xFF 0xFF - 0xFF 0xFF 0xFF. In this case, the SME will order all available networks - by their signal strengths and will iterate through this list until it - successfully connects. - NOTE: Specifying the BSSID will restrict the selection to one specific - network. If SSID and BSSID are given, they must both match the network - for it to be selected. To select a network based on the SSID only, the - wireless manager application must set the BSSID to 0xFF 0xFF 0xFF 0xFF - 0xFF 0xFF. - The SME will try to connect to each network that matches the provided - parameters, one by one, until it succeeds or has tried unsuccessfully - with all the matching networks. - If there is no network that matches the parameters and the request allows - to host an ad hoc network, the SME will advertise a new ad hoc network - instead. - If the SME cannot connect, it will notify the failure in the confirm. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - connectionConfig - Describes the candidate network to join or to host. - -*******************************************************************************/ -#define CsrWifiSmeConnectReqCreate(msg__, dst__, src__, interfaceTag__, connectionConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->connectionConfig = (connectionConfig__); - -#define CsrWifiSmeConnectReqSendTo(dst__, src__, interfaceTag__, connectionConfig__) \ - { \ - CsrWifiSmeConnectReq *msg__; \ - CsrWifiSmeConnectReqCreate(msg__, dst__, src__, interfaceTag__, connectionConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectReqSend(src__, interfaceTag__, connectionConfig__) \ - CsrWifiSmeConnectReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, connectionConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectCfmSend - - DESCRIPTION - The SME calls this primitive when the connection exchange is complete or - all connection attempts fail. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request. - CSR_WIFI_SME_STATUS_NOT_FOUND: all attempts by the SME to - locate the requested AP failed - -*******************************************************************************/ -#define CsrWifiSmeConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECT_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeConnectCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeConnectCfm *msg__; \ - CsrWifiSmeConnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeConnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the ConnectionConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeConnectionConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeConnectionConfigGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeConnectionConfigGetReq *msg__; \ - CsrWifiSmeConnectionConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionConfigGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeConnectionConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionConfig - Parameters used by the SME for selecting a network - -*******************************************************************************/ -#define CsrWifiSmeConnectionConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectionConfig = (connectionConfig__); - -#define CsrWifiSmeConnectionConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionConfig__) \ - { \ - CsrWifiSmeConnectionConfigGetCfm *msg__; \ - CsrWifiSmeConnectionConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionConfigGetCfmSend(dst__, interfaceTag__, status__, connectionConfig__) \ - CsrWifiSmeConnectionConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionInfoGetReqSend - - DESCRIPTION - This primitive gets the value of the ConnectionInfo parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeConnectionInfoGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionInfoGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_INFO_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeConnectionInfoGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeConnectionInfoGetReq *msg__; \ - CsrWifiSmeConnectionInfoGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionInfoGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeConnectionInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionInfoGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionInfo - Information about the current connection - -*******************************************************************************/ -#define CsrWifiSmeConnectionInfoGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionInfoGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_INFO_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectionInfo = (connectionInfo__); - -#define CsrWifiSmeConnectionInfoGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionInfo__) \ - { \ - CsrWifiSmeConnectionInfoGetCfm *msg__; \ - CsrWifiSmeConnectionInfoGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionInfo__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionInfoGetCfmSend(dst__, interfaceTag__, status__, connectionInfo__) \ - CsrWifiSmeConnectionInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionInfo__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionQualityIndSend - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever the value of the current connection quality - parameters change by more than a certain configurable amount. - The wireless manager application may configure the trigger thresholds for - this indication using the field in smeConfig parameter of - CSR_WIFI_SME_SME_CONFIG_SET_REQ. - Connection quality messages can be suppressed by setting both thresholds - to zero. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - linkQuality - Indicates the quality of the link - -*******************************************************************************/ -#define CsrWifiSmeConnectionQualityIndCreate(msg__, dst__, src__, interfaceTag__, linkQuality__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionQualityInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_QUALITY_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->linkQuality = (linkQuality__); - -#define CsrWifiSmeConnectionQualityIndSendTo(dst__, src__, interfaceTag__, linkQuality__) \ - { \ - CsrWifiSmeConnectionQualityInd *msg__; \ - CsrWifiSmeConnectionQualityIndCreate(msg__, dst__, src__, interfaceTag__, linkQuality__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionQualityIndSend(dst__, interfaceTag__, linkQuality__) \ - CsrWifiSmeConnectionQualityIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, linkQuality__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionStatsGetReqSend - - DESCRIPTION - This primitive gets the value of the ConnectionStats parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeConnectionStatsGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionStatsGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_STATS_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeConnectionStatsGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeConnectionStatsGetReq *msg__; \ - CsrWifiSmeConnectionStatsGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionStatsGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeConnectionStatsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionStatsGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionStats - Statistics for current connection. - -*******************************************************************************/ -#define CsrWifiSmeConnectionStatsGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStats__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeConnectionStatsGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CONNECTION_STATS_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->connectionStats = (connectionStats__); - -#define CsrWifiSmeConnectionStatsGetCfmSendTo(dst__, src__, interfaceTag__, status__, connectionStats__) \ - { \ - CsrWifiSmeConnectionStatsGetCfm *msg__; \ - CsrWifiSmeConnectionStatsGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, connectionStats__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeConnectionStatsGetCfmSend(dst__, interfaceTag__, status__, connectionStats__) \ - CsrWifiSmeConnectionStatsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, connectionStats__) - -/******************************************************************************* - - NAME - CsrWifiSmeCoreDumpIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive Wi-Fi Chip core dump data. - The core dump data may be fragmented and sent using more than one - indication. - To indicate that all the data has been sent, the last indication contains - a 'length' of 0 and 'data' of NULL. - - PARAMETERS - queue - Destination Task Queue - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes of core - dump data - -*******************************************************************************/ -#define CsrWifiSmeCoreDumpIndCreate(msg__, dst__, src__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeCoreDumpInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_CORE_DUMP_IND, dst__, src__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiSmeCoreDumpIndSendTo(dst__, src__, dataLength__, data__) \ - { \ - CsrWifiSmeCoreDumpInd *msg__; \ - CsrWifiSmeCoreDumpIndCreate(msg__, dst__, src__, dataLength__, data__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeCoreDumpIndSend(dst__, dataLength__, data__) \ - CsrWifiSmeCoreDumpIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiSmeDeactivateReqSend - - DESCRIPTION - The WMA sends this primitive to deactivate the SME. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeDeactivateReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeDeactivateReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DEACTIVATE_REQ, dst__, src__); - -#define CsrWifiSmeDeactivateReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeDeactivateReq *msg__; \ - CsrWifiSmeDeactivateReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeDeactivateReqSend(src__) \ - CsrWifiSmeDeactivateReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeDeactivateCfmSend - - DESCRIPTION - The SME sends this primitive when the deactivation is complete. - The WMA cannot send any more primitives until it actives the SME again - sending another CSR_WIFI_SME_ACTIVATE_REQ. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeDeactivateCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeDeactivateCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DEACTIVATE_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeDeactivateCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeDeactivateCfm *msg__; \ - CsrWifiSmeDeactivateCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeDeactivateCfmSend(dst__, status__) \ - CsrWifiSmeDeactivateCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeDisconnectReqSend - - DESCRIPTION - The wireless manager application may disconnect from the current network - by calling this primitive - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeDisconnectReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeDisconnectReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DISCONNECT_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeDisconnectReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeDisconnectReq *msg__; \ - CsrWifiSmeDisconnectReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeDisconnectReqSend(src__, interfaceTag__) \ - CsrWifiSmeDisconnectReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeDisconnectCfmSend - - DESCRIPTION - On reception of CSR_WIFI_SME_DISCONNECT_REQ the SME will perform a - disconnect operation, sending a CsrWifiSmeMediaStatusInd with - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED and then call this primitive when - disconnection is complete. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeDisconnectCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_DISCONNECT_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeDisconnectCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeDisconnectCfm *msg__; \ - CsrWifiSmeDisconnectCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeDisconnectCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeDisconnectCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeErrorIndSend - - DESCRIPTION - Important error message indicating a error of some importance - - PARAMETERS - queue - Destination Task Queue - errorMessage - Contains the error message. - -*******************************************************************************/ -#define CsrWifiSmeErrorIndCreate(msg__, dst__, src__, errorMessage__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeErrorInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ERROR_IND, dst__, src__); \ - msg__->errorMessage = (errorMessage__); - -#define CsrWifiSmeErrorIndSendTo(dst__, src__, errorMessage__) \ - { \ - CsrWifiSmeErrorInd *msg__; \ - CsrWifiSmeErrorIndCreate(msg__, dst__, src__, errorMessage__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeErrorIndSend(dst__, errorMessage__) \ - CsrWifiSmeErrorIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, errorMessage__) - -/******************************************************************************* - - NAME - CsrWifiSmeEventMaskSetReqSend - - DESCRIPTION - The wireless manager application may register with the SME to receive - notification of interesting events. Indications will be sent only if the - wireless manager explicitly registers to be notified of that event. - indMask is a bit mask of values defined in CsrWifiSmeIndicationsMask. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - indMask - Set mask with values from CsrWifiSmeIndications - -*******************************************************************************/ -#define CsrWifiSmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeEventMaskSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_EVENT_MASK_SET_REQ, dst__, src__); \ - msg__->indMask = (indMask__); - -#define CsrWifiSmeEventMaskSetReqSendTo(dst__, src__, indMask__) \ - { \ - CsrWifiSmeEventMaskSetReq *msg__; \ - CsrWifiSmeEventMaskSetReqCreate(msg__, dst__, src__, indMask__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeEventMaskSetReqSend(src__, indMask__) \ - CsrWifiSmeEventMaskSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, indMask__) - -/******************************************************************************* - - NAME - CsrWifiSmeEventMaskSetCfmSend - - DESCRIPTION - The SME calls the primitive to report the result of the request - primitive. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeEventMaskSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeEventMaskSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_EVENT_MASK_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeEventMaskSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeEventMaskSetCfm *msg__; \ - CsrWifiSmeEventMaskSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeEventMaskSetCfmSend(dst__, status__) \ - CsrWifiSmeEventMaskSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the hostConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeHostConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeHostConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeHostConfigGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeHostConfigGetReq *msg__; \ - CsrWifiSmeHostConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeHostConfigGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeHostConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - hostConfig - Current host power state. - -*******************************************************************************/ -#define CsrWifiSmeHostConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, hostConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeHostConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->hostConfig = (hostConfig__); - -#define CsrWifiSmeHostConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, hostConfig__) \ - { \ - CsrWifiSmeHostConfigGetCfm *msg__; \ - CsrWifiSmeHostConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, hostConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeHostConfigGetCfmSend(dst__, interfaceTag__, status__, hostConfig__) \ - CsrWifiSmeHostConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, hostConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the hostConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - hostConfig - Communicates a change of host power state (for example, on - mains power, on battery power etc) and of the periodicity of - traffic data - -*******************************************************************************/ -#define CsrWifiSmeHostConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, hostConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeHostConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->hostConfig = (hostConfig__); - -#define CsrWifiSmeHostConfigSetReqSendTo(dst__, src__, interfaceTag__, hostConfig__) \ - { \ - CsrWifiSmeHostConfigSetReq *msg__; \ - CsrWifiSmeHostConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, hostConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeHostConfigSetReqSend(src__, interfaceTag__, hostConfig__) \ - CsrWifiSmeHostConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, hostConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeHostConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeHostConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_HOST_CONFIG_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeHostConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeHostConfigSetCfm *msg__; \ - CsrWifiSmeHostConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeHostConfigSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeHostConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeIbssStationIndSend - - DESCRIPTION - The SME will send this primitive to indicate that a station has joined or - left the ad-hoc network. - - PARAMETERS - queue - Destination Task Queue - address - MAC address of the station that has joined or left - isconnected - TRUE if the station joined, FALSE if the station left - -*******************************************************************************/ -#define CsrWifiSmeIbssStationIndCreate(msg__, dst__, src__, address__, isconnected__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeIbssStationInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_IBSS_STATION_IND, dst__, src__); \ - msg__->address = (address__); \ - msg__->isconnected = (isconnected__); - -#define CsrWifiSmeIbssStationIndSendTo(dst__, src__, address__, isconnected__) \ - { \ - CsrWifiSmeIbssStationInd *msg__; \ - CsrWifiSmeIbssStationIndCreate(msg__, dst__, src__, address__, isconnected__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeIbssStationIndSend(dst__, address__, isconnected__) \ - CsrWifiSmeIbssStationIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, address__, isconnected__) - -/******************************************************************************* - - NAME - CsrWifiSmeInfoIndSend - - DESCRIPTION - Message indicating a some info about current activity. Mostly of interest - in testing but may be useful in the field. - - PARAMETERS - queue - Destination Task Queue - infoMessage - Contains the message. - -*******************************************************************************/ -#define CsrWifiSmeInfoIndCreate(msg__, dst__, src__, infoMessage__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeInfoInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INFO_IND, dst__, src__); \ - msg__->infoMessage = (infoMessage__); - -#define CsrWifiSmeInfoIndSendTo(dst__, src__, infoMessage__) \ - { \ - CsrWifiSmeInfoInd *msg__; \ - CsrWifiSmeInfoIndCreate(msg__, dst__, src__, infoMessage__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeInfoIndSend(dst__, infoMessage__) \ - CsrWifiSmeInfoIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, infoMessage__) - -/******************************************************************************* - - NAME - CsrWifiSmeInterfaceCapabilityGetReqSend - - DESCRIPTION - The Wireless Manager calls this primitive to ask the SME for the - capabilities of the supported interfaces - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeInterfaceCapabilityGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeInterfaceCapabilityGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, dst__, src__); - -#define CsrWifiSmeInterfaceCapabilityGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeInterfaceCapabilityGetReq *msg__; \ - CsrWifiSmeInterfaceCapabilityGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeInterfaceCapabilityGetReqSend(src__) \ - CsrWifiSmeInterfaceCapabilityGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeInterfaceCapabilityGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Result of the request - numInterfaces - Number of the interfaces supported - capBitmap - Points to the list of capabilities bitmaps provided for each - interface. - The bits represent the following capabilities: - -bits 7 to 4-Reserved - -bit 3-AMP - -bit 2-P2P - -bit 1-AP - -bit 0-STA - -*******************************************************************************/ -#define CsrWifiSmeInterfaceCapabilityGetCfmCreate(msg__, dst__, src__, status__, numInterfaces__, capBitmap__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeInterfaceCapabilityGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->numInterfaces = (numInterfaces__); \ - memcpy(msg__->capBitmap, (capBitmap__), sizeof(u8) * 2); - -#define CsrWifiSmeInterfaceCapabilityGetCfmSendTo(dst__, src__, status__, numInterfaces__, capBitmap__) \ - { \ - CsrWifiSmeInterfaceCapabilityGetCfm *msg__; \ - CsrWifiSmeInterfaceCapabilityGetCfmCreate(msg__, dst__, src__, status__, numInterfaces__, capBitmap__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeInterfaceCapabilityGetCfmSend(dst__, status__, numInterfaces__, capBitmap__) \ - CsrWifiSmeInterfaceCapabilityGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, numInterfaces__, capBitmap__) - -/******************************************************************************* - - NAME - CsrWifiSmeKeyReqSend - - DESCRIPTION - The wireless manager application calls this primitive to add or remove - keys that the chip should use for encryption of data. - The interface allows the wireless manager application to add and remove - keys according to the specified action. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs the - driver to modify or provide the list of keys. - CSR_WIFI_SME_LIST_ACTION_GET is not supported here. - key - Key to be added or removed - -*******************************************************************************/ -#define CsrWifiSmeKeyReqCreate(msg__, dst__, src__, interfaceTag__, action__, key__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeKeyReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_KEY_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->key = (key__); - -#define CsrWifiSmeKeyReqSendTo(dst__, src__, interfaceTag__, action__, key__) \ - { \ - CsrWifiSmeKeyReq *msg__; \ - CsrWifiSmeKeyReqCreate(msg__, dst__, src__, interfaceTag__, action__, key__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeKeyReqSend(src__, interfaceTag__, action__, key__) \ - CsrWifiSmeKeyReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, key__) - -/******************************************************************************* - - NAME - CsrWifiSmeKeyCfmSend - - DESCRIPTION - The SME calls the primitive to report the result of the request - primitive. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - keyType - Type of the key added/deleted - peerMacAddress - Peer MAC Address of the key added/deleted - -*******************************************************************************/ -#define CsrWifiSmeKeyCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeKeyCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_KEY_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->action = (action__); \ - msg__->keyType = (keyType__); \ - msg__->peerMacAddress = (peerMacAddress__); - -#define CsrWifiSmeKeyCfmSendTo(dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ - { \ - CsrWifiSmeKeyCfm *msg__; \ - CsrWifiSmeKeyCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, keyType__, peerMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeKeyCfmSend(dst__, interfaceTag__, status__, action__, keyType__, peerMacAddress__) \ - CsrWifiSmeKeyCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, keyType__, peerMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiSmeLinkQualityGetReqSend - - DESCRIPTION - This primitive gets the value of the LinkQuality parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeLinkQualityGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeLinkQualityGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_LINK_QUALITY_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeLinkQualityGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeLinkQualityGetReq *msg__; \ - CsrWifiSmeLinkQualityGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeLinkQualityGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeLinkQualityGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeLinkQualityGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - linkQuality - Indicates the quality of the link - -*******************************************************************************/ -#define CsrWifiSmeLinkQualityGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, linkQuality__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeLinkQualityGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_LINK_QUALITY_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->linkQuality = (linkQuality__); - -#define CsrWifiSmeLinkQualityGetCfmSendTo(dst__, src__, interfaceTag__, status__, linkQuality__) \ - { \ - CsrWifiSmeLinkQualityGetCfm *msg__; \ - CsrWifiSmeLinkQualityGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, linkQuality__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeLinkQualityGetCfmSend(dst__, interfaceTag__, status__, linkQuality__) \ - CsrWifiSmeLinkQualityGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, linkQuality__) - -/******************************************************************************* - - NAME - CsrWifiSmeMediaStatusIndSend - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it when a network connection is established, lost or has moved to - another AP. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - mediaStatus - Indicates the media status - connectionInfo - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_CONNECTED: - it points to the connection information for the new network - disassocReason - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: - if a disassociation has occurred it gives the reason of the - disassociation - deauthReason - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: - if a deauthentication has occurred it gives the reason of - the deauthentication - -*******************************************************************************/ -#define CsrWifiSmeMediaStatusIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMediaStatusInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MEDIA_STATUS_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->mediaStatus = (mediaStatus__); \ - msg__->connectionInfo = (connectionInfo__); \ - msg__->disassocReason = (disassocReason__); \ - msg__->deauthReason = (deauthReason__); - -#define CsrWifiSmeMediaStatusIndSendTo(dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ - { \ - CsrWifiSmeMediaStatusInd *msg__; \ - CsrWifiSmeMediaStatusIndCreate(msg__, dst__, src__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMediaStatusIndSend(dst__, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) \ - CsrWifiSmeMediaStatusIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, mediaStatus__, connectionInfo__, disassocReason__, deauthReason__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the MibConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeMibConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmeMibConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeMibConfigGetReq *msg__; \ - CsrWifiSmeMibConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibConfigGetReqSend(src__) \ - CsrWifiSmeMibConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - mibConfig - Reports various IEEE 802.11 attributes as currently configured - -*******************************************************************************/ -#define CsrWifiSmeMibConfigGetCfmCreate(msg__, dst__, src__, status__, mibConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->mibConfig = (mibConfig__); - -#define CsrWifiSmeMibConfigGetCfmSendTo(dst__, src__, status__, mibConfig__) \ - { \ - CsrWifiSmeMibConfigGetCfm *msg__; \ - CsrWifiSmeMibConfigGetCfmCreate(msg__, dst__, src__, status__, mibConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibConfigGetCfmSend(dst__, status__, mibConfig__) \ - CsrWifiSmeMibConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the MibConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - mibConfig - Conveys the desired value of various IEEE 802.11 attributes as - currently configured - -*******************************************************************************/ -#define CsrWifiSmeMibConfigSetReqCreate(msg__, dst__, src__, mibConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_SET_REQ, dst__, src__); \ - msg__->mibConfig = (mibConfig__); - -#define CsrWifiSmeMibConfigSetReqSendTo(dst__, src__, mibConfig__) \ - { \ - CsrWifiSmeMibConfigSetReq *msg__; \ - CsrWifiSmeMibConfigSetReqCreate(msg__, dst__, src__, mibConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibConfigSetReqSend(src__, mibConfig__) \ - CsrWifiSmeMibConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeMibConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeMibConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeMibConfigSetCfm *msg__; \ - CsrWifiSmeMibConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibConfigSetCfmSend(dst__, status__) \ - CsrWifiSmeMibConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetCfmSend - - DESCRIPTION - The SME calls this primitive to return the requested MIB variable values. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names and values of the MIB variables requested - -*******************************************************************************/ -#define CsrWifiSmeMibGetCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->mibAttributeLength = (mibAttributeLength__); \ - msg__->mibAttribute = (mibAttribute__); - -#define CsrWifiSmeMibGetCfmSendTo(dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ - { \ - CsrWifiSmeMibGetCfm *msg__; \ - CsrWifiSmeMibGetCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibGetCfmSend(dst__, status__, mibAttributeLength__, mibAttribute__) \ - CsrWifiSmeMibGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibAttributeLength__, mibAttribute__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetNextReqSend - - DESCRIPTION - To read a sequence of MIB parameters, for example a table, call this - primitive to find the name of the next MIB variable - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to a VarBind or VarBindList containing the - name(s) of the MIB variable(s) to search from. - -*******************************************************************************/ -#define CsrWifiSmeMibGetNextReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibGetNextReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_NEXT_REQ, dst__, src__); \ - msg__->mibAttributeLength = (mibAttributeLength__); \ - msg__->mibAttribute = (mibAttribute__); - -#define CsrWifiSmeMibGetNextReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ - { \ - CsrWifiSmeMibGetNextReq *msg__; \ - CsrWifiSmeMibGetNextReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibGetNextReqSend(src__, mibAttributeLength__, mibAttribute__) \ - CsrWifiSmeMibGetNextReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetNextCfmSend - - DESCRIPTION - The SME calls this primitive to return the requested MIB name(s). - The wireless manager application can then read the value of the MIB - variable using CSR_WIFI_SME_MIB_GET_REQ, using the names provided. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to a VarBind or VarBindList containing the - name(s) of the MIB variable(s) lexicographically - following the name(s) given in the request - -*******************************************************************************/ -#define CsrWifiSmeMibGetNextCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibGetNextCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_NEXT_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->mibAttributeLength = (mibAttributeLength__); \ - msg__->mibAttribute = (mibAttribute__); - -#define CsrWifiSmeMibGetNextCfmSendTo(dst__, src__, status__, mibAttributeLength__, mibAttribute__) \ - { \ - CsrWifiSmeMibGetNextCfm *msg__; \ - CsrWifiSmeMibGetNextCfmCreate(msg__, dst__, src__, status__, mibAttributeLength__, mibAttribute__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibGetNextCfmSend(dst__, status__, mibAttributeLength__, mibAttribute__) \ - CsrWifiSmeMibGetNextCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, mibAttributeLength__, mibAttribute__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetReqSend - - DESCRIPTION - The wireless manager application calls this primitive to retrieve one or - more MIB variables. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names of the MIB variables to be retrieved - -*******************************************************************************/ -#define CsrWifiSmeMibGetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_GET_REQ, dst__, src__); \ - msg__->mibAttributeLength = (mibAttributeLength__); \ - msg__->mibAttribute = (mibAttribute__); - -#define CsrWifiSmeMibGetReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ - { \ - CsrWifiSmeMibGetReq *msg__; \ - CsrWifiSmeMibGetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibGetReqSend(src__, mibAttributeLength__, mibAttribute__) \ - CsrWifiSmeMibGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibSetReqSend - - DESCRIPTION - The SME provides raw access to the MIB on the chip, which may be used by - some configuration or diagnostic utilities, but is not normally needed by - the wireless manager application. - The MIB access functions use BER encoded names (OID) of the MIB - parameters and BER encoded values, as described in the chip Host - Interface Protocol Specification. - The MIB parameters are described in 'Wi-Fi 5.0.0 Management Information - Base Reference Guide'. - The wireless manager application calls this primitive to set one or more - MIB variables - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names and values of the MIB variables to set - -*******************************************************************************/ -#define CsrWifiSmeMibSetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_SET_REQ, dst__, src__); \ - msg__->mibAttributeLength = (mibAttributeLength__); \ - msg__->mibAttribute = (mibAttribute__); - -#define CsrWifiSmeMibSetReqSendTo(dst__, src__, mibAttributeLength__, mibAttribute__) \ - { \ - CsrWifiSmeMibSetReq *msg__; \ - CsrWifiSmeMibSetReqCreate(msg__, dst__, src__, mibAttributeLength__, mibAttribute__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibSetReqSend(src__, mibAttributeLength__, mibAttribute__) \ - CsrWifiSmeMibSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, mibAttributeLength__, mibAttribute__) - -/******************************************************************************* - - NAME - CsrWifiSmeMibSetCfmSend - - DESCRIPTION - The SME calls the primitive to report the result of the set primitive. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeMibSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMibSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIB_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeMibSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeMibSetCfm *msg__; \ - CsrWifiSmeMibSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMibSetCfmSend(dst__, status__) \ - CsrWifiSmeMibSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeMicFailureIndSend - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever the chip firmware reports a MIC failure. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - secondFailure - TRUE if this indication is for a second failure in 60 - seconds - count - The number of MIC failure events since the connection was - established - address - MAC address of the transmitter that caused the MIC failure - keyType - Type of key for which the failure occurred - -*******************************************************************************/ -#define CsrWifiSmeMicFailureIndCreate(msg__, dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMicFailureInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MIC_FAILURE_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->secondFailure = (secondFailure__); \ - msg__->count = (count__); \ - msg__->address = (address__); \ - msg__->keyType = (keyType__); - -#define CsrWifiSmeMicFailureIndSendTo(dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ - { \ - CsrWifiSmeMicFailureInd *msg__; \ - CsrWifiSmeMicFailureIndCreate(msg__, dst__, src__, interfaceTag__, secondFailure__, count__, address__, keyType__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMicFailureIndSend(dst__, interfaceTag__, secondFailure__, count__, address__, keyType__) \ - CsrWifiSmeMicFailureIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, secondFailure__, count__, address__, keyType__) - -/******************************************************************************* - - NAME - CsrWifiSmeMulticastAddressReqSend - - DESCRIPTION - The wireless manager application calls this primitive to specify the - multicast addresses which the chip should recognise. The interface allows - the wireless manager application to query, add, remove and flush the - multicast addresses for the network interface according to the specified - action. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter - instructs the driver to modify or provide the list of - MAC addresses. - setAddressesCount - Number of MAC addresses sent with the primitive - setAddresses - Pointer to the list of MAC Addresses sent with the - primitive, set to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmeMulticastAddressReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMulticastAddressReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MULTICAST_ADDRESS_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->setAddressesCount = (setAddressesCount__); \ - msg__->setAddresses = (setAddresses__); - -#define CsrWifiSmeMulticastAddressReqSendTo(dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - { \ - CsrWifiSmeMulticastAddressReq *msg__; \ - CsrWifiSmeMulticastAddressReqCreate(msg__, dst__, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMulticastAddressReqSend(src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) \ - CsrWifiSmeMulticastAddressReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setAddressesCount__, setAddresses__) - -/******************************************************************************* - - NAME - CsrWifiSmeMulticastAddressCfmSend - - DESCRIPTION - The SME will call this primitive when the operation is complete. For a - GET action, this primitive reports the current list of MAC addresses. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getAddressesCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of MAC addresses sent with the primitive - getAddresses - Pointer to the list of MAC Addresses sent with the - primitive, set to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmeMulticastAddressCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeMulticastAddressCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_MULTICAST_ADDRESS_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->action = (action__); \ - msg__->getAddressesCount = (getAddressesCount__); \ - msg__->getAddresses = (getAddresses__); - -#define CsrWifiSmeMulticastAddressCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ - { \ - CsrWifiSmeMulticastAddressCfm *msg__; \ - CsrWifiSmeMulticastAddressCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeMulticastAddressCfmSend(dst__, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) \ - CsrWifiSmeMulticastAddressCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getAddressesCount__, getAddresses__) - -/******************************************************************************* - - NAME - CsrWifiSmePacketFilterSetReqSend - - DESCRIPTION - The wireless manager application should call this primitive to enable or - disable filtering of broadcast packets: uninteresting broadcast packets - will be dropped by the Wi-Fi chip, instead of passing them up to the - host. - This has the advantage of saving power in the host application processor - as it removes the need to process unwanted packets. - All broadcast packets are filtered according to the filter and the filter - mode provided, except ARP packets, which are filtered using - arpFilterAddress. - Filters are not cumulative: only the parameters specified in the most - recent successful request are significant. - For more information, see 'UniFi Firmware API Specification'. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - filterLength - Length of the filter in bytes. - filterLength=0 disables the filter previously set - filter - Points to the first byte of the filter provided, if any. - This shall include zero or more instance of the - information elements of one of these types - * Traffic Classification (TCLAS) elements - * WMM-SA TCLAS elements - mode - Specifies whether the filter selects or excludes packets - matching the filter - arpFilterAddress - IPv4 address to be used for filtering the ARP packets. - * If the specified address is the IPv4 broadcast address - (255.255.255.255), all ARP packets are reported to the - host, - * If the specified address is NOT the IPv4 broadcast - address, only ARP packets with the specified address in - the Source or Target Protocol Address fields are reported - to the host - -*******************************************************************************/ -#define CsrWifiSmePacketFilterSetReqCreate(msg__, dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePacketFilterSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PACKET_FILTER_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->filterLength = (filterLength__); \ - msg__->filter = (filter__); \ - msg__->mode = (mode__); \ - msg__->arpFilterAddress = (arpFilterAddress__); - -#define CsrWifiSmePacketFilterSetReqSendTo(dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ - { \ - CsrWifiSmePacketFilterSetReq *msg__; \ - CsrWifiSmePacketFilterSetReqCreate(msg__, dst__, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePacketFilterSetReqSend(src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) \ - CsrWifiSmePacketFilterSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, filterLength__, filter__, mode__, arpFilterAddress__) - -/******************************************************************************* - - NAME - CsrWifiSmePacketFilterSetCfmSend - - DESCRIPTION - The SME calls the primitive to report the result of the set primitive. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmePacketFilterSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePacketFilterSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PACKET_FILTER_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmePacketFilterSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmePacketFilterSetCfm *msg__; \ - CsrWifiSmePacketFilterSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePacketFilterSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmePacketFilterSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmePermanentMacAddressGetReqSend - - DESCRIPTION - This primitive retrieves the MAC address stored in EEPROM - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmePermanentMacAddressGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePermanentMacAddressGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ, dst__, src__); - -#define CsrWifiSmePermanentMacAddressGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmePermanentMacAddressGetReq *msg__; \ - CsrWifiSmePermanentMacAddressGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePermanentMacAddressGetReqSend(src__) \ - CsrWifiSmePermanentMacAddressGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmePermanentMacAddressGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - permanentMacAddress - MAC address stored in the EEPROM - -*******************************************************************************/ -#define CsrWifiSmePermanentMacAddressGetCfmCreate(msg__, dst__, src__, status__, permanentMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePermanentMacAddressGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->permanentMacAddress = (permanentMacAddress__); - -#define CsrWifiSmePermanentMacAddressGetCfmSendTo(dst__, src__, status__, permanentMacAddress__) \ - { \ - CsrWifiSmePermanentMacAddressGetCfm *msg__; \ - CsrWifiSmePermanentMacAddressGetCfmCreate(msg__, dst__, src__, status__, permanentMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePermanentMacAddressGetCfmSend(dst__, status__, permanentMacAddress__) \ - CsrWifiSmePermanentMacAddressGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, permanentMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiSmePmkidCandidateListIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it when a new network supporting preauthentication and/or PMK - caching is seen. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an - interface - pmkidCandidatesCount - Number of PMKID candidates provided - pmkidCandidates - Points to the first PMKID candidate - -*******************************************************************************/ -#define CsrWifiSmePmkidCandidateListIndCreate(msg__, dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePmkidCandidateListInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->pmkidCandidatesCount = (pmkidCandidatesCount__); \ - msg__->pmkidCandidates = (pmkidCandidates__); - -#define CsrWifiSmePmkidCandidateListIndSendTo(dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ - { \ - CsrWifiSmePmkidCandidateListInd *msg__; \ - CsrWifiSmePmkidCandidateListIndCreate(msg__, dst__, src__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePmkidCandidateListIndSend(dst__, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) \ - CsrWifiSmePmkidCandidateListIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, pmkidCandidatesCount__, pmkidCandidates__) - -/******************************************************************************* - - NAME - CsrWifiSmePmkidReqSend - - DESCRIPTION - The wireless manager application calls this primitive to request an - operation on the SME PMKID list. - The action argument specifies the operation to perform. - When the connection is complete, the wireless manager application may - then send and receive EAPOL packets to complete WPA or WPA2 - authentication if appropriate. - The wireless manager application can then pass the resulting encryption - keys using this primitive. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs - the driver to modify or provide the list of PMKIDs. - setPmkidsCount - Number of PMKIDs sent with the primitive - setPmkids - Pointer to the list of PMKIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmePmkidReqCreate(msg__, dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePmkidReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->setPmkidsCount = (setPmkidsCount__); \ - msg__->setPmkids = (setPmkids__); - -#define CsrWifiSmePmkidReqSendTo(dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ - { \ - CsrWifiSmePmkidReq *msg__; \ - CsrWifiSmePmkidReqCreate(msg__, dst__, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePmkidReqSend(src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) \ - CsrWifiSmePmkidReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, setPmkidsCount__, setPmkids__) - -/******************************************************************************* - - NAME - CsrWifiSmePmkidCfmSend - - DESCRIPTION - The SME will call this primitive when the operation is complete. For a - GET action, this primitive reports the current list of PMKIDs - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getPmkidsCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of PMKIDs sent with the primitive - getPmkids - Pointer to the list of PMKIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -#define CsrWifiSmePmkidCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePmkidCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_PMKID_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->action = (action__); \ - msg__->getPmkidsCount = (getPmkidsCount__); \ - msg__->getPmkids = (getPmkids__); - -#define CsrWifiSmePmkidCfmSendTo(dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ - { \ - CsrWifiSmePmkidCfm *msg__; \ - CsrWifiSmePmkidCfmCreate(msg__, dst__, src__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePmkidCfmSend(dst__, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) \ - CsrWifiSmePmkidCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, action__, getPmkidsCount__, getPmkids__) - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the PowerConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmePowerConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePowerConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmePowerConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmePowerConfigGetReq *msg__; \ - CsrWifiSmePowerConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePowerConfigGetReqSend(src__) \ - CsrWifiSmePowerConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - powerConfig - Returns the current parameters for the power configuration of - the firmware - -*******************************************************************************/ -#define CsrWifiSmePowerConfigGetCfmCreate(msg__, dst__, src__, status__, powerConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePowerConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->powerConfig = (powerConfig__); - -#define CsrWifiSmePowerConfigGetCfmSendTo(dst__, src__, status__, powerConfig__) \ - { \ - CsrWifiSmePowerConfigGetCfm *msg__; \ - CsrWifiSmePowerConfigGetCfmCreate(msg__, dst__, src__, status__, powerConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePowerConfigGetCfmSend(dst__, status__, powerConfig__) \ - CsrWifiSmePowerConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, powerConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the PowerConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - powerConfig - Power saving configuration - -*******************************************************************************/ -#define CsrWifiSmePowerConfigSetReqCreate(msg__, dst__, src__, powerConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePowerConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_SET_REQ, dst__, src__); \ - msg__->powerConfig = (powerConfig__); - -#define CsrWifiSmePowerConfigSetReqSendTo(dst__, src__, powerConfig__) \ - { \ - CsrWifiSmePowerConfigSetReq *msg__; \ - CsrWifiSmePowerConfigSetReqCreate(msg__, dst__, src__, powerConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePowerConfigSetReqSend(src__, powerConfig__) \ - CsrWifiSmePowerConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, powerConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmePowerConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmePowerConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_POWER_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmePowerConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmePowerConfigSetCfm *msg__; \ - CsrWifiSmePowerConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmePowerConfigSetCfmSend(dst__, status__) \ - CsrWifiSmePowerConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomainInfoGetReqSend - - DESCRIPTION - This primitive gets the value of the RegulatoryDomainInfo parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeRegulatoryDomainInfoGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ, dst__, src__); - -#define CsrWifiSmeRegulatoryDomainInfoGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeRegulatoryDomainInfoGetReq *msg__; \ - CsrWifiSmeRegulatoryDomainInfoGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRegulatoryDomainInfoGetReqSend(src__) \ - CsrWifiSmeRegulatoryDomainInfoGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomainInfoGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - regDomInfo - Reports information and state related to regulatory domain - operation. - -*******************************************************************************/ -#define CsrWifiSmeRegulatoryDomainInfoGetCfmCreate(msg__, dst__, src__, status__, regDomInfo__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->regDomInfo = (regDomInfo__); - -#define CsrWifiSmeRegulatoryDomainInfoGetCfmSendTo(dst__, src__, status__, regDomInfo__) \ - { \ - CsrWifiSmeRegulatoryDomainInfoGetCfm *msg__; \ - CsrWifiSmeRegulatoryDomainInfoGetCfmCreate(msg__, dst__, src__, status__, regDomInfo__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRegulatoryDomainInfoGetCfmSend(dst__, status__, regDomInfo__) \ - CsrWifiSmeRegulatoryDomainInfoGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, regDomInfo__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamCompleteIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it completes an attempt to roam to an AP. If the roam - attempt was successful, status will be set to CSR_WIFI_SME_SUCCESS, - otherwise it shall be set to the appropriate error code. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the roaming procedure - -*******************************************************************************/ -#define CsrWifiSmeRoamCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamCompleteInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAM_COMPLETE_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeRoamCompleteIndSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeRoamCompleteInd *msg__; \ - CsrWifiSmeRoamCompleteIndCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamCompleteIndSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeRoamCompleteIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamStartIndSend - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it begins an attempt to roam to an AP. - If the wireless manager application connect request specified the SSID - and the BSSID was set to the broadcast address (0xFF 0xFF 0xFF 0xFF 0xFF - 0xFF), the SME monitors the signal quality and maintains a list of - candidates to roam to. When the signal quality of the current connection - falls below a threshold, and there is a candidate with better quality, - the SME will attempt to the candidate AP. - If the roaming procedure succeeds, the SME will also issue a Media - Connect indication to inform the wireless manager application of the - change. - NOTE: to prevent the SME from initiating roaming the WMA must specify the - BSSID in the connection request; this forces the SME to connect only to - that AP. - The wireless manager application can obtain statistics for roaming - purposes using CSR_WIFI_SME_CONNECTION_QUALITY_IND and - CSR_WIFI_SME_CONNECTION_STATS_GET_REQ. - When the wireless manager application wishes to roam to another AP, it - must issue a connection request specifying the BSSID of the desired AP. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - roamReason - Indicates the reason for starting the roaming procedure - reason80211 - Indicates the reason for deauthentication or disassociation - -*******************************************************************************/ -#define CsrWifiSmeRoamStartIndCreate(msg__, dst__, src__, interfaceTag__, roamReason__, reason80211__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamStartInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAM_START_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->roamReason = (roamReason__); \ - msg__->reason80211 = (reason80211__); - -#define CsrWifiSmeRoamStartIndSendTo(dst__, src__, interfaceTag__, roamReason__, reason80211__) \ - { \ - CsrWifiSmeRoamStartInd *msg__; \ - CsrWifiSmeRoamStartIndCreate(msg__, dst__, src__, interfaceTag__, roamReason__, reason80211__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamStartIndSend(dst__, interfaceTag__, roamReason__, reason80211__) \ - CsrWifiSmeRoamStartIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, roamReason__, reason80211__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the RoamingConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeRoamingConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamingConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeRoamingConfigGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeRoamingConfigGetReq *msg__; \ - CsrWifiSmeRoamingConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamingConfigGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeRoamingConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - roamingConfig - Reports the roaming behaviour of the driver and firmware - -*******************************************************************************/ -#define CsrWifiSmeRoamingConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, roamingConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamingConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->roamingConfig = (roamingConfig__); - -#define CsrWifiSmeRoamingConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, roamingConfig__) \ - { \ - CsrWifiSmeRoamingConfigGetCfm *msg__; \ - CsrWifiSmeRoamingConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, roamingConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamingConfigGetCfmSend(dst__, interfaceTag__, status__, roamingConfig__) \ - CsrWifiSmeRoamingConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, roamingConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the RoamingConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - roamingConfig - Desired roaming behaviour values - -*******************************************************************************/ -#define CsrWifiSmeRoamingConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, roamingConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamingConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->roamingConfig = (roamingConfig__); - -#define CsrWifiSmeRoamingConfigSetReqSendTo(dst__, src__, interfaceTag__, roamingConfig__) \ - { \ - CsrWifiSmeRoamingConfigSetReq *msg__; \ - CsrWifiSmeRoamingConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, roamingConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamingConfigSetReqSend(src__, interfaceTag__, roamingConfig__) \ - CsrWifiSmeRoamingConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, roamingConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigSetCfmSend - - DESCRIPTION - This primitive sets the value of the RoamingConfig parameter. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeRoamingConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeRoamingConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeRoamingConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeRoamingConfigSetCfm *msg__; \ - CsrWifiSmeRoamingConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeRoamingConfigSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeRoamingConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the ScanConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeScanConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmeScanConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeScanConfigGetReq *msg__; \ - CsrWifiSmeScanConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanConfigGetReqSend(src__) \ - CsrWifiSmeScanConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - scanConfig - Returns the current parameters for the autonomous scanning - behaviour of the firmware - -*******************************************************************************/ -#define CsrWifiSmeScanConfigGetCfmCreate(msg__, dst__, src__, status__, scanConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->scanConfig = (scanConfig__); - -#define CsrWifiSmeScanConfigGetCfmSendTo(dst__, src__, status__, scanConfig__) \ - { \ - CsrWifiSmeScanConfigGetCfm *msg__; \ - CsrWifiSmeScanConfigGetCfmCreate(msg__, dst__, src__, status__, scanConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanConfigGetCfmSend(dst__, status__, scanConfig__) \ - CsrWifiSmeScanConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the ScanConfig parameter. - The SME normally configures the firmware to perform autonomous scanning - without involving the host. - The firmware passes beacon / probe response or indicates loss of beacon - on certain changes of state, for example: - * A new AP is seen for the first time - * An AP is no longer visible - * The signal strength of an AP changes by more than a certain amount, as - configured by the thresholds in the scanConfig parameter - In addition to the autonomous scan, the wireless manager application may - request a scan at any time using CSR_WIFI_SME_SCAN_FULL_REQ. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - scanConfig - Reports the configuration for the autonomous scanning behaviour - of the firmware - -*******************************************************************************/ -#define CsrWifiSmeScanConfigSetReqCreate(msg__, dst__, src__, scanConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_SET_REQ, dst__, src__); \ - msg__->scanConfig = (scanConfig__); - -#define CsrWifiSmeScanConfigSetReqSendTo(dst__, src__, scanConfig__) \ - { \ - CsrWifiSmeScanConfigSetReq *msg__; \ - CsrWifiSmeScanConfigSetReqCreate(msg__, dst__, src__, scanConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanConfigSetReqSend(src__, scanConfig__) \ - CsrWifiSmeScanConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, scanConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeScanConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeScanConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeScanConfigSetCfm *msg__; \ - CsrWifiSmeScanConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanConfigSetCfmSend(dst__, status__) \ - CsrWifiSmeScanConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanFullReqSend - - DESCRIPTION - The wireless manager application should call this primitive to request a - full scan. - Channels are scanned actively or passively according to the requirement - set by regulatory domain. - If the SME receives this primitive while a full scan is going on, the new - request is buffered and it will be served after the current full scan is - completed. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - ssidCount - Number of SSIDs provided. - If it is 0, the SME will attempt to detect any network - ssid - Points to the first SSID provided, if any. - bssid - BSS identifier. - If it is equal to FF-FF-FF-FF-FF, the SME will listen for - messages from any BSS. - If it is different from FF-FF-FF-FF-FF and any SSID is - provided, one SSID must match the network of the BSS. - forceScan - Forces the scan even if the SME is in a state which would - normally prevent it (e.g. autonomous scan is running). - bssType - Type of BSS to scan for - scanType - Type of scan to perform - channelListCount - Number of channels provided. - If it is 0, the SME will initiate a scan of all the - supported channels that are permitted by the current - regulatory domain. - channelList - Points to the first channel , or NULL if channelListCount - is zero. - probeIeLength - Length of the information element in bytes to be sent - with the probe message. - probeIe - Points to the first byte of the information element to be - sent with the probe message. - -*******************************************************************************/ -#define CsrWifiSmeScanFullReqCreate(msg__, dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanFullReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_FULL_REQ, dst__, src__); \ - msg__->ssidCount = (ssidCount__); \ - msg__->ssid = (ssid__); \ - msg__->bssid = (bssid__); \ - msg__->forceScan = (forceScan__); \ - msg__->bssType = (bssType__); \ - msg__->scanType = (scanType__); \ - msg__->channelListCount = (channelListCount__); \ - msg__->channelList = (channelList__); \ - msg__->probeIeLength = (probeIeLength__); \ - msg__->probeIe = (probeIe__); - -#define CsrWifiSmeScanFullReqSendTo(dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ - { \ - CsrWifiSmeScanFullReq *msg__; \ - CsrWifiSmeScanFullReqCreate(msg__, dst__, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanFullReqSend(src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) \ - CsrWifiSmeScanFullReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, ssidCount__, ssid__, bssid__, forceScan__, bssType__, scanType__, channelListCount__, channelList__, probeIeLength__, probeIe__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanFullCfmSend - - DESCRIPTION - The SME calls this primitive when the results from the scan are - available. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeScanFullCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanFullCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_FULL_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeScanFullCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeScanFullCfm *msg__; \ - CsrWifiSmeScanFullCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanFullCfmSend(dst__, status__) \ - CsrWifiSmeScanFullCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultIndSend - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever a scan indication is received from the firmware. - - PARAMETERS - queue - Destination Task Queue - result - Points to a buffer containing a scan result. - -*******************************************************************************/ -#define CsrWifiSmeScanResultIndCreate(msg__, dst__, src__, result__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanResultInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULT_IND, dst__, src__); \ - msg__->result = (result__); - -#define CsrWifiSmeScanResultIndSendTo(dst__, src__, result__) \ - { \ - CsrWifiSmeScanResultInd *msg__; \ - CsrWifiSmeScanResultIndCreate(msg__, dst__, src__, result__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanResultIndSend(dst__, result__) \ - CsrWifiSmeScanResultIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, result__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsFlushReqSend - - DESCRIPTION - The Wireless Manager calls this primitive to ask the SME to delete all - scan results from its cache, except for the scan result of any currently - connected network. - As scan results are received by the SME from the firmware, they are - cached in the SME memory. - Any time the Wireless Manager requests scan results, they are returned - from the SME internal cache. - For some applications it may be desirable to clear this cache prior to - requesting that a scan be performed; this will ensure that the cache then - only contains the networks detected in the most recent scan. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeScanResultsFlushReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanResultsFlushReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ, dst__, src__); - -#define CsrWifiSmeScanResultsFlushReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeScanResultsFlushReq *msg__; \ - CsrWifiSmeScanResultsFlushReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanResultsFlushReqSend(src__) \ - CsrWifiSmeScanResultsFlushReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsFlushCfmSend - - DESCRIPTION - The SME will call this primitive when the cache has been cleared. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeScanResultsFlushCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanResultsFlushCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeScanResultsFlushCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeScanResultsFlushCfm *msg__; \ - CsrWifiSmeScanResultsFlushCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanResultsFlushCfmSend(dst__, status__) \ - CsrWifiSmeScanResultsFlushCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsGetReqSend - - DESCRIPTION - The wireless manager application calls this primitive to retrieve the - current set of scan results, either after receiving a successful - CSR_WIFI_SME_SCAN_FULL_CFM, or to get autonomous scan results. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeScanResultsGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanResultsGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_GET_REQ, dst__, src__); - -#define CsrWifiSmeScanResultsGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeScanResultsGetReq *msg__; \ - CsrWifiSmeScanResultsGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanResultsGetReqSend(src__) \ - CsrWifiSmeScanResultsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsGetCfmSend - - DESCRIPTION - The SME sends this primitive to provide the current set of scan results. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - scanResultsCount - Number of scan results - scanResults - Points to a buffer containing an array of - CsrWifiSmeScanResult structures. - -*******************************************************************************/ -#define CsrWifiSmeScanResultsGetCfmCreate(msg__, dst__, src__, status__, scanResultsCount__, scanResults__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeScanResultsGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SCAN_RESULTS_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->scanResultsCount = (scanResultsCount__); \ - msg__->scanResults = (scanResults__); - -#define CsrWifiSmeScanResultsGetCfmSendTo(dst__, src__, status__, scanResultsCount__, scanResults__) \ - { \ - CsrWifiSmeScanResultsGetCfm *msg__; \ - CsrWifiSmeScanResultsGetCfmCreate(msg__, dst__, src__, status__, scanResultsCount__, scanResults__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \ - CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanResultsCount__, scanResults__) - -/******************************************************************************* - - NAME - CsrWifiSmeSetReqSend - - DESCRIPTION - Used to pass custom data to the SME. Format is the same as 802.11 Info - Elements => | Id | Length | Data - 1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01 - (0x00|0x01)" - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes - -*******************************************************************************/ -#define CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SET_REQ, dst__, src__); \ - msg__->dataLength = (dataLength__); \ - msg__->data = (data__); - -#define CsrWifiSmeSetReqSendTo(dst__, src__, dataLength__, data__) \ - { \ - CsrWifiSmeSetReq *msg__; \ - CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSetReqSend(src__, dataLength__, data__) \ - CsrWifiSmeSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, dataLength__, data__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the Sme common parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeSmeCommonConfigGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ, dst__, src__); - -#define CsrWifiSmeSmeCommonConfigGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeSmeCommonConfigGetReq *msg__; \ - CsrWifiSmeSmeCommonConfigGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeCommonConfigGetReqSend(src__) \ - CsrWifiSmeSmeCommonConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - deviceConfig - Configuration options in the SME - -*******************************************************************************/ -#define CsrWifiSmeSmeCommonConfigGetCfmCreate(msg__, dst__, src__, status__, deviceConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->deviceConfig = (deviceConfig__); - -#define CsrWifiSmeSmeCommonConfigGetCfmSendTo(dst__, src__, status__, deviceConfig__) \ - { \ - CsrWifiSmeSmeCommonConfigGetCfm *msg__; \ - CsrWifiSmeSmeCommonConfigGetCfmCreate(msg__, dst__, src__, status__, deviceConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeCommonConfigGetCfmSend(dst__, status__, deviceConfig__) \ - CsrWifiSmeSmeCommonConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, deviceConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the Sme common. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - deviceConfig - Configuration options in the SME - -*******************************************************************************/ -#define CsrWifiSmeSmeCommonConfigSetReqCreate(msg__, dst__, src__, deviceConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, dst__, src__); \ - msg__->deviceConfig = (deviceConfig__); - -#define CsrWifiSmeSmeCommonConfigSetReqSendTo(dst__, src__, deviceConfig__) \ - { \ - CsrWifiSmeSmeCommonConfigSetReq *msg__; \ - CsrWifiSmeSmeCommonConfigSetReqCreate(msg__, dst__, src__, deviceConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeCommonConfigSetReqSend(src__, deviceConfig__) \ - CsrWifiSmeSmeCommonConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, deviceConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigSetCfmSend - - DESCRIPTION - Reports the result of the request - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeSmeCommonConfigSetCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeSmeCommonConfigSetCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeSmeCommonConfigSetCfm *msg__; \ - CsrWifiSmeSmeCommonConfigSetCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeCommonConfigSetCfmSend(dst__, status__) \ - CsrWifiSmeSmeCommonConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigGetReqSend - - DESCRIPTION - This primitive gets the value of the SmeStaConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -#define CsrWifiSmeSmeStaConfigGetReqCreate(msg__, dst__, src__, interfaceTag__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeStaConfigGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); - -#define CsrWifiSmeSmeStaConfigGetReqSendTo(dst__, src__, interfaceTag__) \ - { \ - CsrWifiSmeSmeStaConfigGetReq *msg__; \ - CsrWifiSmeSmeStaConfigGetReqCreate(msg__, dst__, src__, interfaceTag__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeStaConfigGetReqSend(src__, interfaceTag__) \ - CsrWifiSmeSmeStaConfigGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - smeConfig - Current SME Station Parameters - -*******************************************************************************/ -#define CsrWifiSmeSmeStaConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, smeConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeStaConfigGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->smeConfig = (smeConfig__); - -#define CsrWifiSmeSmeStaConfigGetCfmSendTo(dst__, src__, interfaceTag__, status__, smeConfig__) \ - { \ - CsrWifiSmeSmeStaConfigGetCfm *msg__; \ - CsrWifiSmeSmeStaConfigGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, smeConfig__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeStaConfigGetCfmSend(dst__, interfaceTag__, status__, smeConfig__) \ - CsrWifiSmeSmeStaConfigGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, smeConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigSetReqSend - - DESCRIPTION - This primitive sets the value of the SmeConfig parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - smeConfig - SME Station Parameters to be set - -*******************************************************************************/ -#define CsrWifiSmeSmeStaConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, smeConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeStaConfigSetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->smeConfig = (smeConfig__); - -#define CsrWifiSmeSmeStaConfigSetReqSendTo(dst__, src__, interfaceTag__, smeConfig__) \ - { \ - CsrWifiSmeSmeStaConfigSetReq *msg__; \ - CsrWifiSmeSmeStaConfigSetReqCreate(msg__, dst__, src__, interfaceTag__, smeConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeStaConfigSetReqSend(src__, interfaceTag__, smeConfig__) \ - CsrWifiSmeSmeStaConfigSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, smeConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigSetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeSmeStaConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeSmeStaConfigSetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); - -#define CsrWifiSmeSmeStaConfigSetCfmSendTo(dst__, src__, interfaceTag__, status__) \ - { \ - CsrWifiSmeSmeStaConfigSetCfm *msg__; \ - CsrWifiSmeSmeStaConfigSetCfmCreate(msg__, dst__, src__, interfaceTag__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeSmeStaConfigSetCfmSend(dst__, interfaceTag__, status__) \ - CsrWifiSmeSmeStaConfigSetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeStationMacAddressGetReqSend - - DESCRIPTION - This primitives is used to retrieve the current MAC address used by the - station. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeStationMacAddressGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeStationMacAddressGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ, dst__, src__); - -#define CsrWifiSmeStationMacAddressGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeStationMacAddressGetReq *msg__; \ - CsrWifiSmeStationMacAddressGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeStationMacAddressGetReqSend(src__) \ - CsrWifiSmeStationMacAddressGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeStationMacAddressGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - stationMacAddress - Current MAC address of the station. - -*******************************************************************************/ -#define CsrWifiSmeStationMacAddressGetCfmCreate(msg__, dst__, src__, status__, stationMacAddress__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeStationMacAddressGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - memcpy(msg__->stationMacAddress, (stationMacAddress__), sizeof(CsrWifiMacAddress) * 2); - -#define CsrWifiSmeStationMacAddressGetCfmSendTo(dst__, src__, status__, stationMacAddress__) \ - { \ - CsrWifiSmeStationMacAddressGetCfm *msg__; \ - CsrWifiSmeStationMacAddressGetCfmCreate(msg__, dst__, src__, status__, stationMacAddress__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeStationMacAddressGetCfmSend(dst__, status__, stationMacAddress__) \ - CsrWifiSmeStationMacAddressGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, stationMacAddress__) - -/******************************************************************************* - - NAME - CsrWifiSmeTspecReqSend - - DESCRIPTION - The wireless manager application should call this primitive to use the - TSPEC feature. - The chip supports the use of TSPECs and TCLAS for the use of IEEE - 802.11/WMM Quality of Service features. - The API allows the wireless manager application to supply a correctly - formatted TSPEC and TCLAS pair to the driver. - After performing basic validation, the driver negotiates the installation - of the TSPEC with the AP as defined by the 802.11 specification. - The driver retains all TSPEC and TCLAS pairs until they are specifically - removed. - It is not compulsory for a TSPEC to have a TCLAS (NULL is used to - indicate that no TCLAS is supplied), while a TCLASS always require a - TSPEC. - The format of the TSPEC element is specified in 'WMM (including WMM Power - Save) Specification - Version 1.1' and 'ANSI/IEEE Std 802.11-REVmb/D3.0'. - For more information, see 'UniFi Configuring WMM and WMM-PS'. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - interfaceTag - Interface Identifier; unique identifier of an interface - action - Specifies the action to be carried out on the list of TSPECs. - CSR_WIFI_SME_LIST_ACTION_FLUSH is not applicable here. - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - strict - If it set to false, allows the SME to perform automatic - TSPEC negotiation - ctrlMask - Additional TSPEC configuration for CCX. - Set mask with values from CsrWifiSmeTspecCtrl. - CURRENTLY NOT SUPPORTED - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - tclasLength - Length of the TCLAS. - If it is equal to 0, no TCLASS is provided for the TSPEC - tclas - Points to the first byte of the TCLAS, if any. - -*******************************************************************************/ -#define CsrWifiSmeTspecReqCreate(msg__, dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeTspecReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_REQ, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->action = (action__); \ - msg__->transactionId = (transactionId__); \ - msg__->strict = (strict__); \ - msg__->ctrlMask = (ctrlMask__); \ - msg__->tspecLength = (tspecLength__); \ - msg__->tspec = (tspec__); \ - msg__->tclasLength = (tclasLength__); \ - msg__->tclas = (tclas__); - -#define CsrWifiSmeTspecReqSendTo(dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ - { \ - CsrWifiSmeTspecReq *msg__; \ - CsrWifiSmeTspecReqCreate(msg__, dst__, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeTspecReqSend(src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) \ - CsrWifiSmeTspecReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, interfaceTag__, action__, transactionId__, strict__, ctrlMask__, tspecLength__, tspec__, tclasLength__, tclas__) - -/******************************************************************************* - - NAME - CsrWifiSmeTspecIndSend - - DESCRIPTION - The SME will send this primitive to all the task that have registered to - receive it when a status change in the TSPEC occurs. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - tspecResultCode - Specifies the TSPEC operation requested by the peer - station - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - -*******************************************************************************/ -#define CsrWifiSmeTspecIndCreate(msg__, dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeTspecInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_IND, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->transactionId = (transactionId__); \ - msg__->tspecResultCode = (tspecResultCode__); \ - msg__->tspecLength = (tspecLength__); \ - msg__->tspec = (tspec__); - -#define CsrWifiSmeTspecIndSendTo(dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - { \ - CsrWifiSmeTspecInd *msg__; \ - CsrWifiSmeTspecIndCreate(msg__, dst__, src__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeTspecIndSend(dst__, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - CsrWifiSmeTspecIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, transactionId__, tspecResultCode__, tspecLength__, tspec__) - -/******************************************************************************* - - NAME - CsrWifiSmeTspecCfmSend - - DESCRIPTION - The SME calls the primitive to report the result of the TSpec primitive - request. - - PARAMETERS - queue - Destination Task Queue - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - tspecResultCode - Specifies the result of the negotiated TSPEC operation - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - -*******************************************************************************/ -#define CsrWifiSmeTspecCfmCreate(msg__, dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeTspecCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_TSPEC_CFM, dst__, src__); \ - msg__->interfaceTag = (interfaceTag__); \ - msg__->status = (status__); \ - msg__->transactionId = (transactionId__); \ - msg__->tspecResultCode = (tspecResultCode__); \ - msg__->tspecLength = (tspecLength__); \ - msg__->tspec = (tspec__); - -#define CsrWifiSmeTspecCfmSendTo(dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - { \ - CsrWifiSmeTspecCfm *msg__; \ - CsrWifiSmeTspecCfmCreate(msg__, dst__, src__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeTspecCfmSend(dst__, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) \ - CsrWifiSmeTspecCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, transactionId__, tspecResultCode__, tspecLength__, tspec__) - -/******************************************************************************* - - NAME - CsrWifiSmeVersionsGetReqSend - - DESCRIPTION - This primitive gets the value of the Versions parameter. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeVersionsGetReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeVersionsGetReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_VERSIONS_GET_REQ, dst__, src__); - -#define CsrWifiSmeVersionsGetReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeVersionsGetReq *msg__; \ - CsrWifiSmeVersionsGetReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeVersionsGetReqSend(src__) \ - CsrWifiSmeVersionsGetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeVersionsGetCfmSend - - DESCRIPTION - This primitive reports the result of the request. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - versions - Version IDs of the product - -*******************************************************************************/ -#define CsrWifiSmeVersionsGetCfmCreate(msg__, dst__, src__, status__, versions__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeVersionsGetCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_VERSIONS_GET_CFM, dst__, src__); \ - msg__->status = (status__); \ - msg__->versions = (versions__); - -#define CsrWifiSmeVersionsGetCfmSendTo(dst__, src__, status__, versions__) \ - { \ - CsrWifiSmeVersionsGetCfm *msg__; \ - CsrWifiSmeVersionsGetCfmCreate(msg__, dst__, src__, status__, versions__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeVersionsGetCfmSend(dst__, status__, versions__) \ - CsrWifiSmeVersionsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, versions__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiFlightmodeReqSend - - DESCRIPTION - The wireless manager application may call this primitive on boot-up of - the platform to ensure that the chip is placed in a mode that prevents - any emission of RF energy. - This primitive is an alternative to CSR_WIFI_SME_WIFI_ON_REQ. - As in CSR_WIFI_SME_WIFI_ON_REQ, it causes the download of the patch file - (if any) and the programming of the initial MIB settings (if supplied by - the WMA), but it also ensures that the chip is left in its lowest - possible power-mode with the radio subsystems disabled. - This feature is useful on platforms where power cannot be removed from - the chip (leaving the chip not initialised will cause it to consume more - power so calling this function ensures that the chip is initialised into - a low power mode but without entering a state where it could emit any RF - energy). - NOTE: this primitive does not cause the Wi-Fi to change state: Wi-Fi - stays conceptually off. Configuration primitives can be sent after - CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ and the configuration will be maintained. - Requests that require the state of the Wi-Fi to be ON will return - CSR_WIFI_SME_STATUS_WIFI_OFF in their confirms. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - address - Optionally specifies a station MAC address. - In normal use, the manager should set the address to 0xFF - 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use - the MAC address in the MIB. - mibFilesCount - Number of provided data blocks with initial MIB values - mibFiles - Points to the first data block with initial MIB values. - These data blocks are typically the contents of the provided - files ufmib.dat and localmib.dat, available from the host - file system, if they exist. - These files typically contain radio tuning and calibration - values. - More values can be created using the Host Tools. - -*******************************************************************************/ -#define CsrWifiSmeWifiFlightmodeReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiFlightmodeReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ, dst__, src__); \ - msg__->address = (address__); \ - msg__->mibFilesCount = (mibFilesCount__); \ - msg__->mibFiles = (mibFiles__); - -#define CsrWifiSmeWifiFlightmodeReqSendTo(dst__, src__, address__, mibFilesCount__, mibFiles__) \ - { \ - CsrWifiSmeWifiFlightmodeReq *msg__; \ - CsrWifiSmeWifiFlightmodeReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiFlightmodeReqSend(src__, address__, mibFilesCount__, mibFiles__) \ - CsrWifiSmeWifiFlightmodeReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, address__, mibFilesCount__, mibFiles__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiFlightmodeCfmSend - - DESCRIPTION - The SME calls this primitive when the chip is initialised for low power - mode and with the radio subsystem disabled. To leave flight mode, and - enable Wi-Fi, the wireless manager application should call - CSR_WIFI_SME_WIFI_ON_REQ. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeWifiFlightmodeCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiFlightmodeCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeWifiFlightmodeCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeWifiFlightmodeCfm *msg__; \ - CsrWifiSmeWifiFlightmodeCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiFlightmodeCfmSend(dst__, status__) \ - CsrWifiSmeWifiFlightmodeCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffReqSend - - DESCRIPTION - The wireless manager application calls this primitive to turn off the - chip, thus saving power when Wi-Fi is not in use. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - -*******************************************************************************/ -#define CsrWifiSmeWifiOffReqCreate(msg__, dst__, src__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOffReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_REQ, dst__, src__); - -#define CsrWifiSmeWifiOffReqSendTo(dst__, src__) \ - { \ - CsrWifiSmeWifiOffReq *msg__; \ - CsrWifiSmeWifiOffReqCreate(msg__, dst__, src__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOffReqSend(src__) \ - CsrWifiSmeWifiOffReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffIndSend - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it to report that the chip has been turned off. - - PARAMETERS - queue - Destination Task Queue - reason - Indicates the reason why the Wi-Fi has been switched off. - -*******************************************************************************/ -#define CsrWifiSmeWifiOffIndCreate(msg__, dst__, src__, reason__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOffInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_IND, dst__, src__); \ - msg__->reason = (reason__); - -#define CsrWifiSmeWifiOffIndSendTo(dst__, src__, reason__) \ - { \ - CsrWifiSmeWifiOffInd *msg__; \ - CsrWifiSmeWifiOffIndCreate(msg__, dst__, src__, reason__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOffIndSend(dst__, reason__) \ - CsrWifiSmeWifiOffIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, reason__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffCfmSend - - DESCRIPTION - After receiving CSR_WIFI_SME_WIFI_OFF_REQ, if the chip is connected to a - network, the SME will perform a disconnect operation, will send a - CSR_WIFI_SME_MEDIA_STATUS_IND with - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED, and then will call - CSR_WIFI_SME_WIFI_OFF_CFM when the chip is off. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeWifiOffCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOffCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_OFF_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeWifiOffCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeWifiOffCfm *msg__; \ - CsrWifiSmeWifiOffCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOffCfmSend(dst__, status__) \ - CsrWifiSmeWifiOffCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnReqSend - - DESCRIPTION - The wireless manager application calls this primitive to turn on the - Wi-Fi chip. - If the Wi-Fi chip is currently off, the SME turns the Wi-Fi chip on, - downloads the patch file (if any), and programs the initial MIB settings - (if supplied by the WMA). - The patch file is not provided with the SME API; its downloading is - automatic and handled internally by the system. - The MIB settings, when provided, override the default values that the - firmware loads from EEPROM. - If the Wi-Fi chip is already on, the SME takes no action and returns a - successful status in the confirm. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - address - Optionally specifies a station MAC address. - In normal use, the manager should set the address to 0xFF - 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use - the MAC address in the MIB - mibFilesCount - Number of provided data blocks with initial MIB values - mibFiles - Points to the first data block with initial MIB values. - These data blocks are typically the contents of the provided - files ufmib.dat and localmib.dat, available from the host - file system, if they exist. - These files typically contain radio tuning and calibration - values. - More values can be created using the Host Tools. - -*******************************************************************************/ -#define CsrWifiSmeWifiOnReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOnReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_REQ, dst__, src__); \ - msg__->address = (address__); \ - msg__->mibFilesCount = (mibFilesCount__); \ - msg__->mibFiles = (mibFiles__); - -#define CsrWifiSmeWifiOnReqSendTo(dst__, src__, address__, mibFilesCount__, mibFiles__) \ - { \ - CsrWifiSmeWifiOnReq *msg__; \ - CsrWifiSmeWifiOnReqCreate(msg__, dst__, src__, address__, mibFilesCount__, mibFiles__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOnReqSend(src__, address__, mibFilesCount__, mibFiles__) \ - CsrWifiSmeWifiOnReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, address__, mibFilesCount__, mibFiles__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnIndSend - - DESCRIPTION - The SME sends this primitive to all tasks that have registered to receive - it once the chip becomes available and ready to use. - - PARAMETERS - queue - Destination Task Queue - address - Current MAC address - -*******************************************************************************/ -#define CsrWifiSmeWifiOnIndCreate(msg__, dst__, src__, address__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOnInd), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_IND, dst__, src__); \ - msg__->address = (address__); - -#define CsrWifiSmeWifiOnIndSendTo(dst__, src__, address__) \ - { \ - CsrWifiSmeWifiOnInd *msg__; \ - CsrWifiSmeWifiOnIndCreate(msg__, dst__, src__, address__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOnIndSend(dst__, address__) \ - CsrWifiSmeWifiOnIndSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, address__) - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnCfmSend - - DESCRIPTION - The SME sends this primitive to the task that has sent the request once - the chip has been initialised and is available for use. - - PARAMETERS - queue - Destination Task Queue - status - Reports the result of the request - -*******************************************************************************/ -#define CsrWifiSmeWifiOnCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWifiOnCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WIFI_ON_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeWifiOnCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeWifiOnCfm *msg__; \ - CsrWifiSmeWifiOnCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWifiOnCfmSend(dst__, status__) \ - CsrWifiSmeWifiOnCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigurationReqSend - - DESCRIPTION - This primitive passes the WPS information for the device to SME. This may - be accepted only if no interface is active. - - PARAMETERS - queue - Message Source Task Queue (Cfm's will be sent to this Queue) - wpsConfig - WPS config. - -*******************************************************************************/ -#define CsrWifiSmeWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWpsConfigurationReq), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WPS_CONFIGURATION_REQ, dst__, src__); \ - msg__->wpsConfig = (wpsConfig__); - -#define CsrWifiSmeWpsConfigurationReqSendTo(dst__, src__, wpsConfig__) \ - { \ - CsrWifiSmeWpsConfigurationReq *msg__; \ - CsrWifiSmeWpsConfigurationReqCreate(msg__, dst__, src__, wpsConfig__); \ - CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWpsConfigurationReqSend(src__, wpsConfig__) \ - CsrWifiSmeWpsConfigurationReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, wpsConfig__) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigurationCfmSend - - DESCRIPTION - Confirm. - - PARAMETERS - queue - Destination Task Queue - status - Status of the request. - -*******************************************************************************/ -#define CsrWifiSmeWpsConfigurationCfmCreate(msg__, dst__, src__, status__) \ - msg__ = kmalloc(sizeof(CsrWifiSmeWpsConfigurationCfm), GFP_KERNEL); \ - CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_WPS_CONFIGURATION_CFM, dst__, src__); \ - msg__->status = (status__); - -#define CsrWifiSmeWpsConfigurationCfmSendTo(dst__, src__, status__) \ - { \ - CsrWifiSmeWpsConfigurationCfm *msg__; \ - CsrWifiSmeWpsConfigurationCfmCreate(msg__, dst__, src__, status__); \ - CsrSchedMessagePut(dst__, CSR_WIFI_SME_PRIM, msg__); \ - } - -#define CsrWifiSmeWpsConfigurationCfmSend(dst__, status__) \ - CsrWifiSmeWpsConfigurationCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__) - -#endif /* CSR_WIFI_SME_LIB_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_prim.h b/drivers/staging/csr/csr_wifi_sme_prim.h deleted file mode 100644 index 17ec79c77e54..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_prim.h +++ /dev/null @@ -1,6510 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_PRIM_H__ -#define CSR_WIFI_SME_PRIM_H__ - -#include -#include "csr_prim_defs.h" -#include "csr_sched.h" -#include "csr_wifi_common.h" -#include "csr_result.h" -#include "csr_wifi_fsm_event.h" - -#define CSR_WIFI_SME_PRIM (0x0404) - -typedef CsrPrim CsrWifiSmePrim; - - -/******************************************************************************* - - NAME - CsrWifiSme80211NetworkType - - DESCRIPTION - Indicates the physical layer of the network - - VALUES - CSR_WIFI_SME_80211_NETWORK_TYPE_DS - - Direct-sequence spread spectrum - CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM24 - - Orthogonal Frequency Division Multiplexing at 2.4 GHz - CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM5 - - Orthogonal Frequency Division Multiplexing at 5 GHz - CSR_WIFI_SME_80211_NETWORK_TYPE_AUTO - - Automatic - -*******************************************************************************/ -typedef u8 CsrWifiSme80211NetworkType; -#define CSR_WIFI_SME_80211_NETWORK_TYPE_DS ((CsrWifiSme80211NetworkType) 0x00) -#define CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM24 ((CsrWifiSme80211NetworkType) 0x01) -#define CSR_WIFI_SME_80211_NETWORK_TYPE_OFDM5 ((CsrWifiSme80211NetworkType) 0x02) -#define CSR_WIFI_SME_80211_NETWORK_TYPE_AUTO ((CsrWifiSme80211NetworkType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSme80211PrivacyMode - - DESCRIPTION - Bits to enable or disable the privacy mode - - VALUES - CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED - - Privacy mode is enabled: use of WEP for confidentiality is - required. - CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED - - Privacy mode is disabled - -*******************************************************************************/ -typedef u8 CsrWifiSme80211PrivacyMode; -#define CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED ((CsrWifiSme80211PrivacyMode) 0x00) -#define CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED ((CsrWifiSme80211PrivacyMode) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSme80211dTrustLevel - - DESCRIPTION - Level of trust for the information coming from the network - - VALUES - CSR_WIFI_SME_80211D_TRUST_LEVEL_STRICT - - Start with passive scanning and only accept country IE for - updating channel lists - CSR_WIFI_SME_80211D_TRUST_LEVEL_ADJUNCT - - As above plus accept adjunct technology location - information - CSR_WIFI_SME_80211D_TRUST_LEVEL_BSS - - As above accept plus receiving channel from infrastructure - networks - CSR_WIFI_SME_80211D_TRUST_LEVEL_IBSS - - As above accept plus receiving channel from the ad hoc - networks - CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB - - Start with active scanning with list of active channels - from the MIB and accept as above - CSR_WIFI_SME_80211D_TRUST_LEVEL_DISABLED - - Start with active scanning with list of active channels - from the MIB and ignore any channel information from the - network - -*******************************************************************************/ -typedef u8 CsrWifiSme80211dTrustLevel; -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_STRICT ((CsrWifiSme80211dTrustLevel) 0x01) -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_ADJUNCT ((CsrWifiSme80211dTrustLevel) 0x02) -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_BSS ((CsrWifiSme80211dTrustLevel) 0x03) -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_IBSS ((CsrWifiSme80211dTrustLevel) 0x04) -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB ((CsrWifiSme80211dTrustLevel) 0x05) -#define CSR_WIFI_SME_80211D_TRUST_LEVEL_DISABLED ((CsrWifiSme80211dTrustLevel) 0x06) - -/******************************************************************************* - - NAME - CsrWifiSmeAmpStatus - - DESCRIPTION - AMP Current Status - - VALUES - CSR_WIFI_SME_AMP_ACTIVE - AMP ACTIVE. - CSR_WIFI_SME_AMP_INACTIVE - AMP INACTIVE - -*******************************************************************************/ -typedef u8 CsrWifiSmeAmpStatus; -#define CSR_WIFI_SME_AMP_ACTIVE ((CsrWifiSmeAmpStatus) 0x00) -#define CSR_WIFI_SME_AMP_INACTIVE ((CsrWifiSmeAmpStatus) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeAuthMode - - DESCRIPTION - Define bits for CsrWifiSmeAuthMode - - VALUES - CSR_WIFI_SME_AUTH_MODE_80211_OPEN - - Connects to an open system network (i.e. no authentication, - no encryption) or to a WEP enabled network. - CSR_WIFI_SME_AUTH_MODE_80211_SHARED - - Connect to a WEP enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_WPA - - Connects to a WPA Enterprise enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK - - Connects to a WPA with Pre-Shared Key enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 - - Connects to a WPA2 Enterprise enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK - - Connects to a WPA2 with Pre-Shared Key enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_CCKM - - Connects to a CCKM enabled network. - CSR_WIFI_SME_AUTH_MODE_WAPI_WAI - - Connects to a WAPI Enterprise enabled network. - CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK - - Connects to a WAPI with Pre-Shared Key enabled network. - CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X - - For future use. - -*******************************************************************************/ -typedef u16 CsrWifiSmeAuthMode; -#define CSR_WIFI_SME_AUTH_MODE_80211_OPEN ((CsrWifiSmeAuthMode) 0x0001) -#define CSR_WIFI_SME_AUTH_MODE_80211_SHARED ((CsrWifiSmeAuthMode) 0x0002) -#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA ((CsrWifiSmeAuthMode) 0x0004) -#define CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK ((CsrWifiSmeAuthMode) 0x0008) -#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 ((CsrWifiSmeAuthMode) 0x0010) -#define CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK ((CsrWifiSmeAuthMode) 0x0020) -#define CSR_WIFI_SME_AUTH_MODE_8021X_CCKM ((CsrWifiSmeAuthMode) 0x0040) -#define CSR_WIFI_SME_AUTH_MODE_WAPI_WAI ((CsrWifiSmeAuthMode) 0x0080) -#define CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK ((CsrWifiSmeAuthMode) 0x0100) -#define CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X ((CsrWifiSmeAuthMode) 0x0200) - -/******************************************************************************* - - NAME - CsrWifiSmeBasicUsability - - DESCRIPTION - Indicates the usability level of a channel - - VALUES - CSR_WIFI_SME_BASIC_USABILITY_UNUSABLE - - Not usable; connection not recommended - CSR_WIFI_SME_BASIC_USABILITY_POOR - - Poor quality; connect only if nothing better is available - CSR_WIFI_SME_BASIC_USABILITY_SATISFACTORY - - Quality is satisfactory - CSR_WIFI_SME_BASIC_USABILITY_NOT_CONNECTED - - Not connected - -*******************************************************************************/ -typedef u8 CsrWifiSmeBasicUsability; -#define CSR_WIFI_SME_BASIC_USABILITY_UNUSABLE ((CsrWifiSmeBasicUsability) 0x00) -#define CSR_WIFI_SME_BASIC_USABILITY_POOR ((CsrWifiSmeBasicUsability) 0x01) -#define CSR_WIFI_SME_BASIC_USABILITY_SATISFACTORY ((CsrWifiSmeBasicUsability) 0x02) -#define CSR_WIFI_SME_BASIC_USABILITY_NOT_CONNECTED ((CsrWifiSmeBasicUsability) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeBssType - - DESCRIPTION - Indicates the BSS type - - VALUES - CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE - - Infrastructure BSS. - CSR_WIFI_SME_BSS_TYPE_ADHOC - - Ad hoc or Independent BSS. - CSR_WIFI_SME_BSS_TYPE_ANY_BSS - - Specifies any type of BSS - CSR_WIFI_SME_BSS_TYPE_P2P - - Specifies P2P - -*******************************************************************************/ -typedef u8 CsrWifiSmeBssType; -#define CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE ((CsrWifiSmeBssType) 0x00) -#define CSR_WIFI_SME_BSS_TYPE_ADHOC ((CsrWifiSmeBssType) 0x01) -#define CSR_WIFI_SME_BSS_TYPE_ANY_BSS ((CsrWifiSmeBssType) 0x02) -#define CSR_WIFI_SME_BSS_TYPE_P2P ((CsrWifiSmeBssType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeCoexScheme - - DESCRIPTION - Options for the coexistence signalling - Same as MibValues - - VALUES - CSR_WIFI_SME_COEX_SCHEME_DISABLED - - The coexistence signalling is disabled - CSR_WIFI_SME_COEX_SCHEME_CSR - - Basic CSR coexistence signalling - CSR_WIFI_SME_COEX_SCHEME_CSR_CHANNEL - - Full CSR coexistence signalling - CSR_WIFI_SME_COEX_SCHEME_PTA - - Packet Traffic Arbitrator coexistence signalling - -*******************************************************************************/ -typedef u8 CsrWifiSmeCoexScheme; -#define CSR_WIFI_SME_COEX_SCHEME_DISABLED ((CsrWifiSmeCoexScheme) 0x00) -#define CSR_WIFI_SME_COEX_SCHEME_CSR ((CsrWifiSmeCoexScheme) 0x01) -#define CSR_WIFI_SME_COEX_SCHEME_CSR_CHANNEL ((CsrWifiSmeCoexScheme) 0x02) -#define CSR_WIFI_SME_COEX_SCHEME_PTA ((CsrWifiSmeCoexScheme) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeControlIndication - - DESCRIPTION - Indicates the reason why the Wi-Fi has been switched off. - The values of this type are used across the NME/SME/Router API's and they - must be kept consistent with the corresponding types in the .xml of the - ottherinterfaces - - VALUES - CSR_WIFI_SME_CONTROL_INDICATION_ERROR - - An unrecoverable error (for example, an unrecoverable SDIO - error) has occurred. - The wireless manager application should reinitialise the - chip by calling CSR_WIFI_SME_WIFI_ON_REQ. - CSR_WIFI_SME_CONTROL_INDICATION_EXIT - - The chip became unavailable due to an external action, for - example, when a plug-in card is ejected or the driver is - unloaded. - CSR_WIFI_SME_CONTROL_INDICATION_USER_REQUESTED - - The Wi-Fi has been switched off as the wireless manager - application has sent CSR_WIFI_SME_WIFI_OFF_REQ - -*******************************************************************************/ -typedef u8 CsrWifiSmeControlIndication; -#define CSR_WIFI_SME_CONTROL_INDICATION_ERROR ((CsrWifiSmeControlIndication) 0x01) -#define CSR_WIFI_SME_CONTROL_INDICATION_EXIT ((CsrWifiSmeControlIndication) 0x02) -#define CSR_WIFI_SME_CONTROL_INDICATION_USER_REQUESTED ((CsrWifiSmeControlIndication) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeCtsProtectionType - - DESCRIPTION - SME CTS Protection Types - - VALUES - CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC - - AP CTS Protection automatic based on non-ERP station in own - BSS or neighbouring BSS on the same channel based on OLBC. - This requires monitoring of beacons from other APs. - CSR_WIFI_SME_CTS_PROTECTION_FORCE_ENABLED - - AP CTS Protection Force enabled - CSR_WIFI_SME_CTS_PROTECTION_FORCE_DISABLED - - AP CTS Protection Force disabled. - CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC_NO_OLBC - - AP CTS Protection automatic without considering OLBC but - considering non-ERP station in the own BSS Valid only if AP - is configured to work in 802.11bg or 802.11g mode otherwise - this option specifies the same behaviour as AUTOMATIC - -*******************************************************************************/ -typedef u8 CsrWifiSmeCtsProtectionType; -#define CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC ((CsrWifiSmeCtsProtectionType) 0x00) -#define CSR_WIFI_SME_CTS_PROTECTION_FORCE_ENABLED ((CsrWifiSmeCtsProtectionType) 0x01) -#define CSR_WIFI_SME_CTS_PROTECTION_FORCE_DISABLED ((CsrWifiSmeCtsProtectionType) 0x02) -#define CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC_NO_OLBC ((CsrWifiSmeCtsProtectionType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeD3AutoScanMode - - DESCRIPTION - Autonomous scan status while in D3 suspended period - - VALUES - CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSON - - Autonomous scan stays on - CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSOFF - - Autonomous scan is switched off - CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSAUTO - - Automatically select autoscanning behaviour. - CURRENTLY NOT SUPPORTED - -*******************************************************************************/ -typedef u8 CsrWifiSmeD3AutoScanMode; -#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSON ((CsrWifiSmeD3AutoScanMode) 0x00) -#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSOFF ((CsrWifiSmeD3AutoScanMode) 0x01) -#define CSR_WIFI_SME_D3AUTO_SCAN_MODE_PSAUTO ((CsrWifiSmeD3AutoScanMode) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeEncryption - - DESCRIPTION - Defines bits for CsrWifiSmeEncryption - For a WEP enabled network, the caller must specify the correct - combination of flags in the encryptionModeMask. - - VALUES - CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE - - No encryption set - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 - - Selects 40 byte key WEP for unicast communication - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 - - Selects 104 byte key WEP for unicast communication - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP - - Selects TKIP for unicast communication - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP - - Selects CCMP for unicast communication - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 - - Selects SMS4 for unicast communication - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 - - Selects 40 byte key WEP for broadcast messages - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 - - Selects 104 byte key WEP for broadcast messages - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP - - Selects a TKIP for broadcast messages - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP - - Selects CCMP for broadcast messages - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4 - - Selects SMS4 for broadcast messages - -*******************************************************************************/ -typedef u16 CsrWifiSmeEncryption; -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE ((CsrWifiSmeEncryption) 0x0000) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 ((CsrWifiSmeEncryption) 0x0001) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 ((CsrWifiSmeEncryption) 0x0002) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP ((CsrWifiSmeEncryption) 0x0004) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP ((CsrWifiSmeEncryption) 0x0008) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 ((CsrWifiSmeEncryption) 0x0010) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 ((CsrWifiSmeEncryption) 0x0020) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 ((CsrWifiSmeEncryption) 0x0040) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP ((CsrWifiSmeEncryption) 0x0080) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP ((CsrWifiSmeEncryption) 0x0100) -#define CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4 ((CsrWifiSmeEncryption) 0x0200) - -/******************************************************************************* - - NAME - CsrWifiSmeFirmwareDriverInterface - - DESCRIPTION - Type of communication between Host and Firmware - - VALUES - CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_UNIT_DATA_INTERFACE - - No preformated header. NOT SUPPORTED in the current release - CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_PACKET_INTERFACE - - Preformated IEEE 802.11 header for user plane - -*******************************************************************************/ -typedef u8 CsrWifiSmeFirmwareDriverInterface; -#define CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_UNIT_DATA_INTERFACE ((CsrWifiSmeFirmwareDriverInterface) 0x00) -#define CSR_WIFI_SME_FIRMWARE_DRIVER_INTERFACE_PACKET_INTERFACE ((CsrWifiSmeFirmwareDriverInterface) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeHostPowerMode - - DESCRIPTION - Defines the power mode - - VALUES - CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE - - Host device is running on external power. - CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE - - Host device is running on (internal) battery power. - CSR_WIFI_SME_HOST_POWER_MODE_FULL_POWER_SAVE - - For future use. - -*******************************************************************************/ -typedef u8 CsrWifiSmeHostPowerMode; -#define CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE ((CsrWifiSmeHostPowerMode) 0x00) -#define CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE ((CsrWifiSmeHostPowerMode) 0x01) -#define CSR_WIFI_SME_HOST_POWER_MODE_FULL_POWER_SAVE ((CsrWifiSmeHostPowerMode) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeIEEE80211Reason - - DESCRIPTION - As definined in the IEEE 802.11 standards - - VALUES - CSR_WIFI_SME_IEEE80211_REASON_SUCCESS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNSPECIFIED_REASON - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_AUTHENTICATION_NOT_VALID - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DEAUTHENTICATED_LEAVE_BSS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_INACTIVITY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_AP_OVERLOAD - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_CLASS_2FRAME_ERROR - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_CLASS_3FRAME_ERROR - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_LEAVE_BSS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_ASSOCIATION_NOT_AUTHENTICATED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_POWER_CAPABILITY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_SUPPORTED_CHANNELS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_INFORMATION_ELEMENT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_MICHAEL_MIC_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_FOURWAY_HANDSHAKE_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_HANDSHAKE_ELEMENT_DIFFERENT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_GROUP_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_PAIRWISE_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_AKMP - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_RSN_IEVERSION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_RSN_IECAPABILITIES - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_DOT1X_AUTH_FAILED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_CIPHER_REJECTED_BY_POLICY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_SERVICE_CHANGE_PRECLUDES_TS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_QOS_UNSPECIFIED_REASON - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_QOS_INSUFFICIENT_BANDWIDTH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_QOS_EXCESSIVE_NOT_ACK - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_QOS_TXOPLIMIT_EXCEEDED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_QSTA_LEAVING - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_END_TS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_END_DLS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_END_BA - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_TS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_BA - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_DLS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_STAKEY_MISMATCH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNICAST_KEY_NEGOTIATION_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_MULTICAST_KEY_ANNOUNCEMENT_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INCOMPATIBLE_UNICAST_KEY_NEGOTIATION_IE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_MULTICAST_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_UNICAST_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_WAPI_IE_VERSION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_INVALID_WAPI_CAPABILITY_IE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_REASON_WAI_CERTIFICATE_AUTHENTICATION_FAILED - - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef u16 CsrWifiSmeIEEE80211Reason; -#define CSR_WIFI_SME_IEEE80211_REASON_SUCCESS ((CsrWifiSmeIEEE80211Reason) 0x0000) -#define CSR_WIFI_SME_IEEE80211_REASON_UNSPECIFIED_REASON ((CsrWifiSmeIEEE80211Reason) 0x0001) -#define CSR_WIFI_SME_IEEE80211_REASON_AUTHENTICATION_NOT_VALID ((CsrWifiSmeIEEE80211Reason) 0x0002) -#define CSR_WIFI_SME_IEEE80211_REASON_DEAUTHENTICATED_LEAVE_BSS ((CsrWifiSmeIEEE80211Reason) 0x0003) -#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_INACTIVITY ((CsrWifiSmeIEEE80211Reason) 0x0004) -#define CSR_WIFI_SME_IEEE80211_REASON_AP_OVERLOAD ((CsrWifiSmeIEEE80211Reason) 0x0005) -#define CSR_WIFI_SME_IEEE80211_REASON_CLASS_2FRAME_ERROR ((CsrWifiSmeIEEE80211Reason) 0x0006) -#define CSR_WIFI_SME_IEEE80211_REASON_CLASS_3FRAME_ERROR ((CsrWifiSmeIEEE80211Reason) 0x0007) -#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_LEAVE_BSS ((CsrWifiSmeIEEE80211Reason) 0x0008) -#define CSR_WIFI_SME_IEEE80211_REASON_ASSOCIATION_NOT_AUTHENTICATED ((CsrWifiSmeIEEE80211Reason) 0x0009) -#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_POWER_CAPABILITY ((CsrWifiSmeIEEE80211Reason) 0x000a) -#define CSR_WIFI_SME_IEEE80211_REASON_DISASSOCIATED_SUPPORTED_CHANNELS ((CsrWifiSmeIEEE80211Reason) 0x000b) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_INFORMATION_ELEMENT ((CsrWifiSmeIEEE80211Reason) 0x000d) -#define CSR_WIFI_SME_IEEE80211_REASON_MICHAEL_MIC_FAILURE ((CsrWifiSmeIEEE80211Reason) 0x000e) -#define CSR_WIFI_SME_IEEE80211_REASON_FOURWAY_HANDSHAKE_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x000f) -#define CSR_WIFI_SME_IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x0010) -#define CSR_WIFI_SME_IEEE80211_REASON_HANDSHAKE_ELEMENT_DIFFERENT ((CsrWifiSmeIEEE80211Reason) 0x0011) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_GROUP_CIPHER ((CsrWifiSmeIEEE80211Reason) 0x0012) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_PAIRWISE_CIPHER ((CsrWifiSmeIEEE80211Reason) 0x0013) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_AKMP ((CsrWifiSmeIEEE80211Reason) 0x0014) -#define CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_RSN_IEVERSION ((CsrWifiSmeIEEE80211Reason) 0x0015) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_RSN_IECAPABILITIES ((CsrWifiSmeIEEE80211Reason) 0x0016) -#define CSR_WIFI_SME_IEEE80211_REASON_DOT1X_AUTH_FAILED ((CsrWifiSmeIEEE80211Reason) 0x0017) -#define CSR_WIFI_SME_IEEE80211_REASON_CIPHER_REJECTED_BY_POLICY ((CsrWifiSmeIEEE80211Reason) 0x0018) -#define CSR_WIFI_SME_IEEE80211_REASON_SERVICE_CHANGE_PRECLUDES_TS ((CsrWifiSmeIEEE80211Reason) 0x001F) -#define CSR_WIFI_SME_IEEE80211_REASON_QOS_UNSPECIFIED_REASON ((CsrWifiSmeIEEE80211Reason) 0x0020) -#define CSR_WIFI_SME_IEEE80211_REASON_QOS_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeIEEE80211Reason) 0x0021) -#define CSR_WIFI_SME_IEEE80211_REASON_QOS_EXCESSIVE_NOT_ACK ((CsrWifiSmeIEEE80211Reason) 0x0022) -#define CSR_WIFI_SME_IEEE80211_REASON_QOS_TXOPLIMIT_EXCEEDED ((CsrWifiSmeIEEE80211Reason) 0x0023) -#define CSR_WIFI_SME_IEEE80211_REASON_QSTA_LEAVING ((CsrWifiSmeIEEE80211Reason) 0x0024) -#define CSR_WIFI_SME_IEEE80211_REASON_END_TS ((CsrWifiSmeIEEE80211Reason) 0x0025) -#define CSR_WIFI_SME_IEEE80211_REASON_END_DLS ((CsrWifiSmeIEEE80211Reason) 0x0025) -#define CSR_WIFI_SME_IEEE80211_REASON_END_BA ((CsrWifiSmeIEEE80211Reason) 0x0025) -#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_TS ((CsrWifiSmeIEEE80211Reason) 0x0026) -#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_BA ((CsrWifiSmeIEEE80211Reason) 0x0026) -#define CSR_WIFI_SME_IEEE80211_REASON_UNKNOWN_DLS ((CsrWifiSmeIEEE80211Reason) 0x0026) -#define CSR_WIFI_SME_IEEE80211_REASON_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0x0027) -#define CSR_WIFI_SME_IEEE80211_REASON_STAKEY_MISMATCH ((CsrWifiSmeIEEE80211Reason) 0x002d) -#define CSR_WIFI_SME_IEEE80211_REASON_UNICAST_KEY_NEGOTIATION_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0xf019) -#define CSR_WIFI_SME_IEEE80211_REASON_MULTICAST_KEY_ANNOUNCEMENT_TIMEOUT ((CsrWifiSmeIEEE80211Reason) 0xf01a) -#define CSR_WIFI_SME_IEEE80211_REASON_INCOMPATIBLE_UNICAST_KEY_NEGOTIATION_IE ((CsrWifiSmeIEEE80211Reason) 0xf01b) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_MULTICAST_CIPHER ((CsrWifiSmeIEEE80211Reason) 0xf01c) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_UNICAST_CIPHER ((CsrWifiSmeIEEE80211Reason) 0xf01d) -#define CSR_WIFI_SME_IEEE80211_REASON_UNSUPPORTED_WAPI_IE_VERSION ((CsrWifiSmeIEEE80211Reason) 0xf01e) -#define CSR_WIFI_SME_IEEE80211_REASON_INVALID_WAPI_CAPABILITY_IE ((CsrWifiSmeIEEE80211Reason) 0xf01f) -#define CSR_WIFI_SME_IEEE80211_REASON_WAI_CERTIFICATE_AUTHENTICATION_FAILED ((CsrWifiSmeIEEE80211Reason) 0xf020) - -/******************************************************************************* - - NAME - CsrWifiSmeIEEE80211Result - - DESCRIPTION - As definined in the IEEE 802.11 standards - - VALUES - CSR_WIFI_SME_IEEE80211_RESULT_SUCCESS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CAPABILITIES_MISMATCH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REASSOCIATION_DENIED_NO_ASSOCIATION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_EXTERNAL_REASON - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_MISMATCH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_INVALID_AUTHENTICATION_SEQUENCE_NUMBER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHALLENGE_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_OUT_OF_MEMORY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_BASIC_RATES_MISMATCH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_PREAMBLE_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PBCC_MODULATION_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHANNEL_AGILITY_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SPECTRUM_MANAGEMENT_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POWER_CAPABILITY_UNACCEPTABLE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SUPPORTED_CHANNELS_UNACCEPTABLE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_SLOT_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_DSSS_OFDMREQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NO_HT_SUPPORT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_R0KH_UNREACHABLE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PCO_TRANSITION_SUPPORT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_ASSOCIATION_REQUEST_REJECTED_TEMPORARILY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_ROBUST_MANAGEMENT_FRAME_POLICY_VIOLATION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_BANDWIDTH_INSUFFICIENT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POOR_OPERATING_CHANNEL - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_QOS_REQUIRED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_REASON_UNSPECIFIED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PARAMETERS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_WITH_SUGGESTED_TSPEC_CHANGES - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_IE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_GROUP_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_PAIRWISE_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_AKMP - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_UNSUPPORTED_RSN_VERSION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_RSN_CAPABILITY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_SECURITY_POLICY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_FOR_DELAY_PERIOD - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_NOT_ALLOWED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_NOT_PRESENT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_NOT_QSTA - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_LISTEN_INTERVAL_TOO_LARGE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FT_ACTION_FRAME_COUNT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PMKID - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MDIE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FTIE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_QOS_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_WRONG_POLICY - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INSUFFICIENT_BANDWIDTH - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_TSPEC_PARAMETERS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_TIMEOUT - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_TOO_MANY_SIMULTANEOUS_REQUESTS - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_BSS_ALREADY_STARTED_OR_JOINED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_NOT_SUPPORTED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_TRANSMISSION_FAILURE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NOT_AUTHENTICATED - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_RESET_REQUIRED_BEFORE_START - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_LM_INFO_UNAVAILABLE - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_UNICAST_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MULTICAST_CIPHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_UNSUPPORTED_WAPI_IE_VERSION - - See IEEE 802.11 Standard - CSR_WIFI_SME_IEEE80211_RESULT_INVALID_WAPI_CAPABILITY_IE - - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef u16 CsrWifiSmeIEEE80211Result; -#define CSR_WIFI_SME_IEEE80211_RESULT_SUCCESS ((CsrWifiSmeIEEE80211Result) 0x0000) -#define CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_FAILURE ((CsrWifiSmeIEEE80211Result) 0x0001) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CAPABILITIES_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x000a) -#define CSR_WIFI_SME_IEEE80211_RESULT_REASSOCIATION_DENIED_NO_ASSOCIATION ((CsrWifiSmeIEEE80211Result) 0x000b) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_EXTERNAL_REASON ((CsrWifiSmeIEEE80211Result) 0x000c) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x000d) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_INVALID_AUTHENTICATION_SEQUENCE_NUMBER ((CsrWifiSmeIEEE80211Result) 0x000e) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHALLENGE_FAILURE ((CsrWifiSmeIEEE80211Result) 0x000f) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AUTHENTICATION_TIMEOUT ((CsrWifiSmeIEEE80211Result) 0x0010) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_OUT_OF_MEMORY ((CsrWifiSmeIEEE80211Result) 0x0011) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_BASIC_RATES_MISMATCH ((CsrWifiSmeIEEE80211Result) 0x0012) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_PREAMBLE_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0013) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PBCC_MODULATION_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0014) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_CHANNEL_AGILITY_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0015) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SPECTRUM_MANAGEMENT_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0016) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POWER_CAPABILITY_UNACCEPTABLE ((CsrWifiSmeIEEE80211Result) 0x0017) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SUPPORTED_CHANNELS_UNACCEPTABLE ((CsrWifiSmeIEEE80211Result) 0x0018) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_SHORT_SLOT_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0019) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_DSSS_OFDMREQUIRED ((CsrWifiSmeIEEE80211Result) 0x001a) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NO_HT_SUPPORT ((CsrWifiSmeIEEE80211Result) 0x001b) -#define CSR_WIFI_SME_IEEE80211_RESULT_R0KH_UNREACHABLE ((CsrWifiSmeIEEE80211Result) 0x001c) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_PCO_TRANSITION_SUPPORT ((CsrWifiSmeIEEE80211Result) 0x001d) -#define CSR_WIFI_SME_IEEE80211_RESULT_ASSOCIATION_REQUEST_REJECTED_TEMPORARILY ((CsrWifiSmeIEEE80211Result) 0x001e) -#define CSR_WIFI_SME_IEEE80211_RESULT_ROBUST_MANAGEMENT_FRAME_POLICY_VIOLATION ((CsrWifiSmeIEEE80211Result) 0x001f) -#define CSR_WIFI_SME_IEEE80211_RESULT_FAILURE ((CsrWifiSmeIEEE80211Result) 0x0020) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_AP_BANDWIDTH_INSUFFICIENT ((CsrWifiSmeIEEE80211Result) 0x0021) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_POOR_OPERATING_CHANNEL ((CsrWifiSmeIEEE80211Result) 0x0022) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_QOS_REQUIRED ((CsrWifiSmeIEEE80211Result) 0x0023) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_REASON_UNSPECIFIED ((CsrWifiSmeIEEE80211Result) 0x0025) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED ((CsrWifiSmeIEEE80211Result) 0x0025) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PARAMETERS ((CsrWifiSmeIEEE80211Result) 0x0026) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_WITH_SUGGESTED_TSPEC_CHANGES ((CsrWifiSmeIEEE80211Result) 0x0027) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_IE ((CsrWifiSmeIEEE80211Result) 0x0028) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_GROUP_CIPHER ((CsrWifiSmeIEEE80211Result) 0x0029) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_PAIRWISE_CIPHER ((CsrWifiSmeIEEE80211Result) 0x002a) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_AKMP ((CsrWifiSmeIEEE80211Result) 0x002b) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_UNSUPPORTED_RSN_VERSION ((CsrWifiSmeIEEE80211Result) 0x002c) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_INVALID_RSN_CAPABILITY ((CsrWifiSmeIEEE80211Result) 0x002d) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_SECURITY_POLICY ((CsrWifiSmeIEEE80211Result) 0x002e) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_FOR_DELAY_PERIOD ((CsrWifiSmeIEEE80211Result) 0x002f) -#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_ALLOWED ((CsrWifiSmeIEEE80211Result) 0x0030) -#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_PRESENT ((CsrWifiSmeIEEE80211Result) 0x0031) -#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_QSTA ((CsrWifiSmeIEEE80211Result) 0x0032) -#define CSR_WIFI_SME_IEEE80211_RESULT_REJECTED_LISTEN_INTERVAL_TOO_LARGE ((CsrWifiSmeIEEE80211Result) 0x0033) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FT_ACTION_FRAME_COUNT ((CsrWifiSmeIEEE80211Result) 0x0034) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_PMKID ((CsrWifiSmeIEEE80211Result) 0x0035) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MDIE ((CsrWifiSmeIEEE80211Result) 0x0036) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_FTIE ((CsrWifiSmeIEEE80211Result) 0x0037) -#define CSR_WIFI_SME_IEEE80211_RESULT_UNSPECIFIED_QOS_FAILURE ((CsrWifiSmeIEEE80211Result) 0x00c8) -#define CSR_WIFI_SME_IEEE80211_RESULT_WRONG_POLICY ((CsrWifiSmeIEEE80211Result) 0x00c9) -#define CSR_WIFI_SME_IEEE80211_RESULT_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeIEEE80211Result) 0x00ca) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_TSPEC_PARAMETERS ((CsrWifiSmeIEEE80211Result) 0x00cb) -#define CSR_WIFI_SME_IEEE80211_RESULT_TIMEOUT ((CsrWifiSmeIEEE80211Result) 0x8000) -#define CSR_WIFI_SME_IEEE80211_RESULT_TOO_MANY_SIMULTANEOUS_REQUESTS ((CsrWifiSmeIEEE80211Result) 0x8001) -#define CSR_WIFI_SME_IEEE80211_RESULT_BSS_ALREADY_STARTED_OR_JOINED ((CsrWifiSmeIEEE80211Result) 0x8002) -#define CSR_WIFI_SME_IEEE80211_RESULT_NOT_SUPPORTED ((CsrWifiSmeIEEE80211Result) 0x8003) -#define CSR_WIFI_SME_IEEE80211_RESULT_TRANSMISSION_FAILURE ((CsrWifiSmeIEEE80211Result) 0x8004) -#define CSR_WIFI_SME_IEEE80211_RESULT_REFUSED_NOT_AUTHENTICATED ((CsrWifiSmeIEEE80211Result) 0x8005) -#define CSR_WIFI_SME_IEEE80211_RESULT_RESET_REQUIRED_BEFORE_START ((CsrWifiSmeIEEE80211Result) 0x8006) -#define CSR_WIFI_SME_IEEE80211_RESULT_LM_INFO_UNAVAILABLE ((CsrWifiSmeIEEE80211Result) 0x8007) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_UNICAST_CIPHER ((CsrWifiSmeIEEE80211Result) 0xf02f) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_MULTICAST_CIPHER ((CsrWifiSmeIEEE80211Result) 0xf030) -#define CSR_WIFI_SME_IEEE80211_RESULT_UNSUPPORTED_WAPI_IE_VERSION ((CsrWifiSmeIEEE80211Result) 0xf031) -#define CSR_WIFI_SME_IEEE80211_RESULT_INVALID_WAPI_CAPABILITY_IE ((CsrWifiSmeIEEE80211Result) 0xf032) - -/******************************************************************************* - - NAME - CsrWifiSmeIndications - - DESCRIPTION - Defines bits for CsrWifiSmeIndicationsMask - - VALUES - CSR_WIFI_SME_INDICATIONS_NONE - - Used to cancel the registrations for receiving indications - CSR_WIFI_SME_INDICATIONS_WIFIOFF - - Used to register for CSR_WIFI_SME_WIFI_OFF_IND events - CSR_WIFI_SME_INDICATIONS_SCANRESULT - - Used to register for CSR_WIFI_SME_SCAN_RESULT_IND events - CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY - - Used to register for CSR_WIFI_SME_CONNECTION_QUALITY_IND - events - CSR_WIFI_SME_INDICATIONS_MEDIASTATUS - - Used to register for CSR_WIFI_SME_MEDIA_STATUS_IND events - CSR_WIFI_SME_INDICATIONS_MICFAILURE - - Used to register for CSR_WIFI_SME_MICFAILURE_IND events - CSR_WIFI_SME_INDICATIONS_PMKIDCANDIDATELIST - - Used to register for CSR_WIFI_SME_PMKIDCANDIDATE_LIST_IND - events - CSR_WIFI_SME_INDICATIONS_TSPEC - - Used to register for CSR_WIFI_SME_TSPEC_IND events - CSR_WIFI_SME_INDICATIONS_ROAMSTART - - Used to register for CSR_WIFI_SME_ROAM_START_IND events - CSR_WIFI_SME_INDICATIONS_ROAMCOMPLETE - - Used to register for CSR_WIFI_SME_ROAM_COMPLETE_IND events - CSR_WIFI_SME_INDICATIONS_ASSOCIATIONSTART - - Used to register for CSR_WIFI_SME_ASSOCIATION_START_IND - events - CSR_WIFI_SME_INDICATIONS_ASSOCIATIONCOMPLETE - - Used to register for CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND - events - CSR_WIFI_SME_INDICATIONS_IBSSSTATION - - Used to register for CSR_WIFI_SME_IBSS_STATION_IND events - CSR_WIFI_SME_INDICATIONS_WIFION - - Used to register for CSR_WIFI_SME_WIFI_ON_IND events - CSR_WIFI_SME_INDICATIONS_ERROR - - Used to register for CSR_WIFI_SME_ERROR_IND events - CSR_WIFI_SME_INDICATIONS_INFO - - Used to register for CSR_WIFI_SME_INFO_IND events - CSR_WIFI_SME_INDICATIONS_COREDUMP - - Used to register for CSR_WIFI_SME_CORE_DUMP_IND events - CSR_WIFI_SME_INDICATIONS_ALL - - Used to register for all available indications - -*******************************************************************************/ -typedef u32 CsrWifiSmeIndications; -#define CSR_WIFI_SME_INDICATIONS_NONE ((CsrWifiSmeIndications) 0x00000000) -#define CSR_WIFI_SME_INDICATIONS_WIFIOFF ((CsrWifiSmeIndications) 0x00000001) -#define CSR_WIFI_SME_INDICATIONS_SCANRESULT ((CsrWifiSmeIndications) 0x00000002) -#define CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY ((CsrWifiSmeIndications) 0x00000004) -#define CSR_WIFI_SME_INDICATIONS_MEDIASTATUS ((CsrWifiSmeIndications) 0x00000008) -#define CSR_WIFI_SME_INDICATIONS_MICFAILURE ((CsrWifiSmeIndications) 0x00000010) -#define CSR_WIFI_SME_INDICATIONS_PMKIDCANDIDATELIST ((CsrWifiSmeIndications) 0x00000020) -#define CSR_WIFI_SME_INDICATIONS_TSPEC ((CsrWifiSmeIndications) 0x00000040) -#define CSR_WIFI_SME_INDICATIONS_ROAMSTART ((CsrWifiSmeIndications) 0x00000080) -#define CSR_WIFI_SME_INDICATIONS_ROAMCOMPLETE ((CsrWifiSmeIndications) 0x00000100) -#define CSR_WIFI_SME_INDICATIONS_ASSOCIATIONSTART ((CsrWifiSmeIndications) 0x00000200) -#define CSR_WIFI_SME_INDICATIONS_ASSOCIATIONCOMPLETE ((CsrWifiSmeIndications) 0x00000400) -#define CSR_WIFI_SME_INDICATIONS_IBSSSTATION ((CsrWifiSmeIndications) 0x00000800) -#define CSR_WIFI_SME_INDICATIONS_WIFION ((CsrWifiSmeIndications) 0x00001000) -#define CSR_WIFI_SME_INDICATIONS_ERROR ((CsrWifiSmeIndications) 0x00002000) -#define CSR_WIFI_SME_INDICATIONS_INFO ((CsrWifiSmeIndications) 0x00004000) -#define CSR_WIFI_SME_INDICATIONS_COREDUMP ((CsrWifiSmeIndications) 0x00008000) -#define CSR_WIFI_SME_INDICATIONS_ALL ((CsrWifiSmeIndications) 0xFFFFFFFF) - -/******************************************************************************* - - NAME - CsrWifiSmeKeyType - - DESCRIPTION - Indicates the type of the key - - VALUES - CSR_WIFI_SME_KEY_TYPE_GROUP - Key for broadcast communication - CSR_WIFI_SME_KEY_TYPE_PAIRWISE - Key for unicast communication - CSR_WIFI_SME_KEY_TYPE_STAKEY - Key for direct link communication to - another station in infrastructure networks - CSR_WIFI_SME_KEY_TYPE_IGTK - Integrity Group Temporal Key - CSR_WIFI_SME_KEY_TYPE_CCKM - Key for Cisco Centralized Key Management - -*******************************************************************************/ -typedef u8 CsrWifiSmeKeyType; -#define CSR_WIFI_SME_KEY_TYPE_GROUP ((CsrWifiSmeKeyType) 0x00) -#define CSR_WIFI_SME_KEY_TYPE_PAIRWISE ((CsrWifiSmeKeyType) 0x01) -#define CSR_WIFI_SME_KEY_TYPE_STAKEY ((CsrWifiSmeKeyType) 0x02) -#define CSR_WIFI_SME_KEY_TYPE_IGTK ((CsrWifiSmeKeyType) 0x03) -#define CSR_WIFI_SME_KEY_TYPE_CCKM ((CsrWifiSmeKeyType) 0x04) - -/******************************************************************************* - - NAME - CsrWifiSmeListAction - - DESCRIPTION - Identifies the type of action to be performed on a list of items - The values of this type are used across the NME/SME/Router API's and they - must be kept consistent with the corresponding types in the .xml of the - ottherinterfaces - - VALUES - CSR_WIFI_SME_LIST_ACTION_GET - Retrieve the current list of items - CSR_WIFI_SME_LIST_ACTION_ADD - Add one or more items - CSR_WIFI_SME_LIST_ACTION_REMOVE - Remove one or more items - CSR_WIFI_SME_LIST_ACTION_FLUSH - Remove all items - -*******************************************************************************/ -typedef u8 CsrWifiSmeListAction; -#define CSR_WIFI_SME_LIST_ACTION_GET ((CsrWifiSmeListAction) 0x00) -#define CSR_WIFI_SME_LIST_ACTION_ADD ((CsrWifiSmeListAction) 0x01) -#define CSR_WIFI_SME_LIST_ACTION_REMOVE ((CsrWifiSmeListAction) 0x02) -#define CSR_WIFI_SME_LIST_ACTION_FLUSH ((CsrWifiSmeListAction) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeMediaStatus - - DESCRIPTION - Indicates the connection status - The values of this type are used across the NME/SME/Router API's and they - must be kept consistent with the corresponding types in the .xml of the - ottherinterfaces - - VALUES - CSR_WIFI_SME_MEDIA_STATUS_CONNECTED - - Value CSR_WIFI_SME_MEDIA_STATUS_CONNECTED can happen in two - situations: - * A network connection is established. Specifically, this is - when the MLME_ASSOCIATION completes or the first peer - relationship is established in an IBSS. In a WPA/WPA2 - network, this indicates that the stack is ready to perform - the 4-way handshake or 802.1x authentication if CSR NME - security library is not used. If CSR NME security library - is used this indicates, completion of 4way handshake or - 802.1x authentication - * The SME roams to another AP on the same ESS - During the AP operation, it indicates that the peer station - is connected to the AP and is ready for data transfer. - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED - - Value CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED can happen in - two situations: - * when the connection to a network is lost and there is no - alternative on the same ESS to roam to - * when a CSR_WIFI_SME_DISCONNECT_REQ request is issued - During AP or P2PGO operation, it indicates that the peer - station has disconnected from the AP - -*******************************************************************************/ -typedef u8 CsrWifiSmeMediaStatus; -#define CSR_WIFI_SME_MEDIA_STATUS_CONNECTED ((CsrWifiSmeMediaStatus) 0x00) -#define CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED ((CsrWifiSmeMediaStatus) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeP2pCapability - - DESCRIPTION - Defines P2P Device Capabilities - - VALUES - CSR_WIFI_SME_P2P_SERVICE_DISCOVERY_CAPABILITY - - This field is set to 1 if the P2P Device supports Service - Discovery, and to 0 otherwise - CSR_WIFI_SME_P2P_CLIENT_DISCOVERABILITY_CAPABILITY - - This field is set to 1 when the P2P Device supports P2P - Client Discoverability, and to 0 otherwise. - CSR_WIFI_SME_P2P_CONCURRENT_OPERATION_CAPABILITY - - This field is set to 1 when the P2P Device supports - Concurrent Operation with WLAN, and to 0 otherwise. - CSR_WIFI_SME_P2P_MANAGED_DEVICE_CAPABILITY - - This field is set to 1 when the P2P interface of the P2P - Device is capable of being managed by the WLAN - (infrastructure network) based on P2P coexistence - parameters, and to 0 otherwise - CSR_WIFI_SME_P2P_INVITAION_CAPABILITY - - This field is set to 1 if the P2P Device is capable of - processing P2P Invitation Procedure signaling, and to 0 - otherwise. - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pCapability; -#define CSR_WIFI_SME_P2P_SERVICE_DISCOVERY_CAPABILITY ((CsrWifiSmeP2pCapability) 0x01) -#define CSR_WIFI_SME_P2P_CLIENT_DISCOVERABILITY_CAPABILITY ((CsrWifiSmeP2pCapability) 0x02) -#define CSR_WIFI_SME_P2P_CONCURRENT_OPERATION_CAPABILITY ((CsrWifiSmeP2pCapability) 0x04) -#define CSR_WIFI_SME_P2P_MANAGED_DEVICE_CAPABILITY ((CsrWifiSmeP2pCapability) 0x08) -#define CSR_WIFI_SME_P2P_INVITAION_CAPABILITY ((CsrWifiSmeP2pCapability) 0x20) - -/******************************************************************************* - - NAME - CsrWifiSmeP2pGroupCapability - - DESCRIPTION - Define bits for P2P Group Capability - - VALUES - CSR_WIFI_P2P_GRP_CAP_GO - - Indicates if the local device has become a GO after GO - negotiation - CSR_WIFI_P2P_GRP_CAP_PERSISTENT - - Persistent group - CSR_WIFI_P2P_GRP_CAP_INTRABSS_DIST - - Intra-BSS data distribution support - CSR_WIFI_P2P_GRP_CAP_CROSS_CONN - - Support of cross connection - CSR_WIFI_P2P_GRP_CAP_PERSISTENT_RECONNECT - - Support of persistent reconnect - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pGroupCapability; -#define CSR_WIFI_P2P_GRP_CAP_GO ((CsrWifiSmeP2pGroupCapability) 0x01) -#define CSR_WIFI_P2P_GRP_CAP_PERSISTENT ((CsrWifiSmeP2pGroupCapability) 0x02) -#define CSR_WIFI_P2P_GRP_CAP_INTRABSS_DIST ((CsrWifiSmeP2pGroupCapability) 0x08) -#define CSR_WIFI_P2P_GRP_CAP_CROSS_CONN ((CsrWifiSmeP2pGroupCapability) 0x10) -#define CSR_WIFI_P2P_GRP_CAP_PERSISTENT_RECONNECT ((CsrWifiSmeP2pGroupCapability) 0x20) - -/******************************************************************************* - - NAME - CsrWifiSmeP2pNoaConfigMethod - - DESCRIPTION - Notice of Absece Configuration - - VALUES - CSR_WIFI_P2P_NOA_NONE - Do not use NOA - CSR_WIFI_P2P_NOA_AUTONOMOUS - NOA based on the traffic analysis - CSR_WIFI_P2P_NOA_USER_DEFINED - NOA as specified by the user - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pNoaConfigMethod; -#define CSR_WIFI_P2P_NOA_NONE ((CsrWifiSmeP2pNoaConfigMethod) 0x00) -#define CSR_WIFI_P2P_NOA_AUTONOMOUS ((CsrWifiSmeP2pNoaConfigMethod) 0x01) -#define CSR_WIFI_P2P_NOA_USER_DEFINED ((CsrWifiSmeP2pNoaConfigMethod) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeP2pRole - - DESCRIPTION - Definition of roles for a P2P Device - - VALUES - CSR_WIFI_SME_P2P_ROLE_NONE - A non-P2PDevice device - CSR_WIFI_SME_P2P_ROLE_STANDALONE - A Standalone P2P device - CSR_WIFI_SME_P2P_ROLE_GO - Role Assumed is that of a Group Owner - within a P2P Group - CSR_WIFI_SME_P2P_ROLE_CLI - Role Assumed is that of a P2P Client - within a P2P Group - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pRole; -#define CSR_WIFI_SME_P2P_ROLE_NONE ((CsrWifiSmeP2pRole) 0x00) -#define CSR_WIFI_SME_P2P_ROLE_STANDALONE ((CsrWifiSmeP2pRole) 0x01) -#define CSR_WIFI_SME_P2P_ROLE_GO ((CsrWifiSmeP2pRole) 0x02) -#define CSR_WIFI_SME_P2P_ROLE_CLI ((CsrWifiSmeP2pRole) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeP2pStatus - - DESCRIPTION - This data type enumerates the outcome of P2P procedure - - VALUES - CSR_WIFI_SME_P2P_STATUS_SUCCESS - - Success - CSR_WIFI_SME_P2P_STATUS_FAIL_INFO_UNAVAILABLE - - Fail; information is currently unavailable - CSR_WIFI_SME_P2P_STATUS_FAIL_INCOMPATIBLE_PARAM - - Fail; incompatible parameters - CSR_WIFI_SME_P2P_STATUS_FAIL_LIMIT_REACHED - - Fail; limit reached - CSR_WIFI_SME_P2P_STATUS_FAIL_INVALID_PARAM - - Fail; invalid parameters - CSR_WIFI_SME_P2P_STATUS_FAIL_ACCOMODATE - - Fail; unable to accommodate request - CSR_WIFI_SME_P2P_STATUS_FAIL_PREV_ERROR - - Fail; previous protocol error, or disruptive behavior - CSR_WIFI_SME_P2P_STATUS_FAIL_COMMON_CHANNELS - - Fail; no common channels - CSR_WIFI_SME_P2P_STATUS_FAIL_UNKNOWN_GROUP - - Fail; unknown P2P Group - CSR_WIFI_SME_P2P_STATUS_FAIL_GO_INTENT - - Fail: both P2P Devices indicated an Intent of 15 in Group - Owner Negotiation - CSR_WIFI_SME_P2P_STATUS_FAIL_PROVISION_METHOD_INCOMPATIBLE - - Fail; incompatible provisioning method - CSR_WIFI_SME_P2P_STATUS_FAIL_REJECT - - Fail: rejected by user - CSR_WIFI_SME_P2P_STATUS_FAIL_RESERVED - - Fail; Status Reserved - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pStatus; -#define CSR_WIFI_SME_P2P_STATUS_SUCCESS ((CsrWifiSmeP2pStatus) 0x00) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_INFO_UNAVAILABLE ((CsrWifiSmeP2pStatus) 0x01) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_INCOMPATIBLE_PARAM ((CsrWifiSmeP2pStatus) 0x02) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_LIMIT_REACHED ((CsrWifiSmeP2pStatus) 0x03) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_INVALID_PARAM ((CsrWifiSmeP2pStatus) 0x04) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_ACCOMODATE ((CsrWifiSmeP2pStatus) 0x05) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_PREV_ERROR ((CsrWifiSmeP2pStatus) 0x06) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_COMMON_CHANNELS ((CsrWifiSmeP2pStatus) 0x07) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_UNKNOWN_GROUP ((CsrWifiSmeP2pStatus) 0x08) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_GO_INTENT ((CsrWifiSmeP2pStatus) 0x09) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_PROVISION_METHOD_INCOMPATIBLE ((CsrWifiSmeP2pStatus) 0x0A) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_REJECT ((CsrWifiSmeP2pStatus) 0x0B) -#define CSR_WIFI_SME_P2P_STATUS_FAIL_RESERVED ((CsrWifiSmeP2pStatus) 0xFF) - -/******************************************************************************* - - NAME - CsrWifiSmePacketFilterMode - - DESCRIPTION - Options for the filter mode parameter. - The Values here match the HIP interface - - VALUES - CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_OUT - - Broadcast packets are always reported to the host unless - they match at least one of the specified TCLAS IEs. - CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_IN - - Broadcast packets are reported to the host only if they - match at least one of the specified TCLAS IEs. - -*******************************************************************************/ -typedef u8 CsrWifiSmePacketFilterMode; -#define CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_OUT ((CsrWifiSmePacketFilterMode) 0x00) -#define CSR_WIFI_SME_PACKET_FILTER_MODE_OPT_IN ((CsrWifiSmePacketFilterMode) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmePowerSaveLevel - - DESCRIPTION - Power Save Level options as defined in the IEEE 802.11 standards - First 3 values are set to match the mlme PowerManagementMode - - VALUES - CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW - No power save: the driver will remain - active at all times - CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH - Enter power save after all packets in - the queues are transmitted and received - CSR_WIFI_SME_POWER_SAVE_LEVEL_MED - Enter power save after all packets in - the queues are transmitted and received - and a further configurable delay - (default 1s) has elapsed - CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO - The SME will decide when to enter power - save mode according to the traffic - analysis - -*******************************************************************************/ -typedef u8 CsrWifiSmePowerSaveLevel; -#define CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW ((CsrWifiSmePowerSaveLevel) 0x00) -#define CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH ((CsrWifiSmePowerSaveLevel) 0x01) -#define CSR_WIFI_SME_POWER_SAVE_LEVEL_MED ((CsrWifiSmePowerSaveLevel) 0x02) -#define CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO ((CsrWifiSmePowerSaveLevel) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmePreambleType - - DESCRIPTION - SME Preamble Types - - VALUES - CSR_WIFI_SME_USE_LONG_PREAMBLE - Use legacy (long) preamble - CSR_WIFI_SME_USE_SHORT_PREAMBLE - Use short PPDU format - -*******************************************************************************/ -typedef u8 CsrWifiSmePreambleType; -#define CSR_WIFI_SME_USE_LONG_PREAMBLE ((CsrWifiSmePreambleType) 0x00) -#define CSR_WIFI_SME_USE_SHORT_PREAMBLE ((CsrWifiSmePreambleType) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeRadioIF - - DESCRIPTION - Indicates the frequency - - VALUES - CSR_WIFI_SME_RADIO_IF_GHZ_2_4 - Indicates the 2.4 GHZ frequency - CSR_WIFI_SME_RADIO_IF_GHZ_5_0 - Future use: currently not supported - CSR_WIFI_SME_RADIO_IF_BOTH - Future use: currently not supported - -*******************************************************************************/ -typedef u8 CsrWifiSmeRadioIF; -#define CSR_WIFI_SME_RADIO_IF_GHZ_2_4 ((CsrWifiSmeRadioIF) 0x01) -#define CSR_WIFI_SME_RADIO_IF_GHZ_5_0 ((CsrWifiSmeRadioIF) 0x02) -#define CSR_WIFI_SME_RADIO_IF_BOTH ((CsrWifiSmeRadioIF) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomain - - DESCRIPTION - Indicates the regulatory domain as defined in IEEE 802.11 standards - - VALUES - CSR_WIFI_SME_REGULATORY_DOMAIN_OTHER - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_FCC - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_IC - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_ETSI - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_SPAIN - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_FRANCE - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_JAPAN - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_JAPANBIS - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_CHINA - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_CHINABIS - - See IEEE 802.11 Standard - CSR_WIFI_SME_REGULATORY_DOMAIN_NONE - - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef u8 CsrWifiSmeRegulatoryDomain; -#define CSR_WIFI_SME_REGULATORY_DOMAIN_OTHER ((CsrWifiSmeRegulatoryDomain) 0x00) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_FCC ((CsrWifiSmeRegulatoryDomain) 0x10) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_IC ((CsrWifiSmeRegulatoryDomain) 0x20) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_ETSI ((CsrWifiSmeRegulatoryDomain) 0x30) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_SPAIN ((CsrWifiSmeRegulatoryDomain) 0x31) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_FRANCE ((CsrWifiSmeRegulatoryDomain) 0x32) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_JAPAN ((CsrWifiSmeRegulatoryDomain) 0x40) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_JAPANBIS ((CsrWifiSmeRegulatoryDomain) 0x41) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_CHINA ((CsrWifiSmeRegulatoryDomain) 0x50) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_CHINABIS ((CsrWifiSmeRegulatoryDomain) 0x51) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_NONE ((CsrWifiSmeRegulatoryDomain) 0xFF) - -/******************************************************************************* - - NAME - CsrWifiSmeRoamReason - - DESCRIPTION - Indicates the reason for roaming - - VALUES - CSR_WIFI_SME_ROAM_REASON_BEACONLOST - - The station cannot receive the beacon signal any more - CSR_WIFI_SME_ROAM_REASON_DISASSOCIATED - - The station has been disassociated - CSR_WIFI_SME_ROAM_REASON_DEAUTHENTICATED - - The station has been deauthenticated - CSR_WIFI_SME_ROAM_REASON_BETTERAPFOUND - - A better AP has been found - -*******************************************************************************/ -typedef u8 CsrWifiSmeRoamReason; -#define CSR_WIFI_SME_ROAM_REASON_BEACONLOST ((CsrWifiSmeRoamReason) 0x00) -#define CSR_WIFI_SME_ROAM_REASON_DISASSOCIATED ((CsrWifiSmeRoamReason) 0x01) -#define CSR_WIFI_SME_ROAM_REASON_DEAUTHENTICATED ((CsrWifiSmeRoamReason) 0x02) -#define CSR_WIFI_SME_ROAM_REASON_BETTERAPFOUND ((CsrWifiSmeRoamReason) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeScanType - - DESCRIPTION - Identifies the type of scan to be performed - - VALUES - CSR_WIFI_SME_SCAN_TYPE_ALL - Scan actively or passively according to the - regulatory domain restrictions - CSR_WIFI_SME_SCAN_TYPE_ACTIVE - Scan actively only: send probes and listen - for answers - CSR_WIFI_SME_SCAN_TYPE_PASSIVE - Scan passively only: listen for beacon - messages - -*******************************************************************************/ -typedef u8 CsrWifiSmeScanType; -#define CSR_WIFI_SME_SCAN_TYPE_ALL ((CsrWifiSmeScanType) 0x00) -#define CSR_WIFI_SME_SCAN_TYPE_ACTIVE ((CsrWifiSmeScanType) 0x01) -#define CSR_WIFI_SME_SCAN_TYPE_PASSIVE ((CsrWifiSmeScanType) 0x02) - -/******************************************************************************* - - NAME - CsrWifiSmeTrafficType - - DESCRIPTION - Identifies the type of traffic going on on the connection. - The values of this type are used across the NME/SME/Router API's and they - must be kept consistent with the corresponding types in the .xml of the - ottherinterfaces - - VALUES - CSR_WIFI_SME_TRAFFIC_TYPE_OCCASIONAL - - During the last 30 seconds there were fewer than 20 packets - per seconds in each second in both directions - CSR_WIFI_SME_TRAFFIC_TYPE_BURSTY - - During the last 30 seconds there was at least one second - during which more than 20 packets were received in either - direction - CSR_WIFI_SME_TRAFFIC_TYPE_PERIODIC - - During the last 5 seconds there were at least 10 packets - received each second and a defined period for the traffic - can be recognized - CSR_WIFI_SME_TRAFFIC_TYPE_CONTINUOUS - - During the last 5 seconds there were at least 20 packets - received each second in either direction - -*******************************************************************************/ -typedef u8 CsrWifiSmeTrafficType; -#define CSR_WIFI_SME_TRAFFIC_TYPE_OCCASIONAL ((CsrWifiSmeTrafficType) 0x00) -#define CSR_WIFI_SME_TRAFFIC_TYPE_BURSTY ((CsrWifiSmeTrafficType) 0x01) -#define CSR_WIFI_SME_TRAFFIC_TYPE_PERIODIC ((CsrWifiSmeTrafficType) 0x02) -#define CSR_WIFI_SME_TRAFFIC_TYPE_CONTINUOUS ((CsrWifiSmeTrafficType) 0x03) - -/******************************************************************************* - - NAME - CsrWifiSmeTspecCtrl - - DESCRIPTION - Defines bits for CsrWifiSmeTspecCtrlMask for additional CCX configuration. - CURRENTLY NOT SUPPORTED. - - VALUES - CSR_WIFI_SME_TSPEC_CTRL_STRICT - - No automatic negotiation - CSR_WIFI_SME_TSPEC_CTRL_CCX_SIGNALLING - - Signalling TSPEC - CSR_WIFI_SME_TSPEC_CTRL_CCX_VOICE - - Voice traffic TSPEC - -*******************************************************************************/ -typedef u8 CsrWifiSmeTspecCtrl; -#define CSR_WIFI_SME_TSPEC_CTRL_STRICT ((CsrWifiSmeTspecCtrl) 0x01) -#define CSR_WIFI_SME_TSPEC_CTRL_CCX_SIGNALLING ((CsrWifiSmeTspecCtrl) 0x02) -#define CSR_WIFI_SME_TSPEC_CTRL_CCX_VOICE ((CsrWifiSmeTspecCtrl) 0x04) - -/******************************************************************************* - - NAME - CsrWifiSmeTspecResultCode - - DESCRIPTION - Defines the result of the TSPEC exchanges with the AP - - VALUES - CSR_WIFI_SME_TSPEC_RESULT_SUCCESS - - TSPEC command has been processed correctly - CSR_WIFI_SME_TSPEC_RESULT_UNSPECIFIED_QOS_FAILURE - - The Access Point reported a failure - CSR_WIFI_SME_TSPEC_RESULT_FAILURE - - Internal failure in the SME - CSR_WIFI_SME_TSPEC_RESULT_INVALID_TSPEC_PARAMETERS - - The TSPEC parameters are invalid - CSR_WIFI_SME_TSPEC_RESULT_INVALID_TCLAS_PARAMETERS - - The TCLASS parameters are invalid - CSR_WIFI_SME_TSPEC_RESULT_INSUFFICIENT_BANDWIDTH - - As specified by the WMM Spec - CSR_WIFI_SME_TSPEC_RESULT_WRONG_POLICY - - As specified by the WMM Spec - CSR_WIFI_SME_TSPEC_RESULT_REJECTED_WITH_SUGGESTED_CHANGES - - As specified by the WMM Spec - CSR_WIFI_SME_TSPEC_RESULT_TIMEOUT - - The TSPEC negotiation timed out - CSR_WIFI_SME_TSPEC_RESULT_NOT_SUPPORTED - - The Access Point does not support the TSPEC - CSR_WIFI_SME_TSPEC_RESULT_IE_LENGTH_INCORRECT - - The length of the TSPEC is not correct - CSR_WIFI_SME_TSPEC_RESULT_INVALID_TRANSACTION_ID - - The TSPEC transaction id is not in the list - CSR_WIFI_SME_TSPEC_RESULT_INSTALLED - - The TSPEC has been installed and it is now active. - CSR_WIFI_SME_TSPEC_RESULT_TID_ALREADY_INSTALLED - - The Traffic ID has already been installed - CSR_WIFI_SME_TSPEC_RESULT_TSPEC_REMOTELY_DELETED - - The AP has deleted the TSPEC - -*******************************************************************************/ -typedef u8 CsrWifiSmeTspecResultCode; -#define CSR_WIFI_SME_TSPEC_RESULT_SUCCESS ((CsrWifiSmeTspecResultCode) 0x00) -#define CSR_WIFI_SME_TSPEC_RESULT_UNSPECIFIED_QOS_FAILURE ((CsrWifiSmeTspecResultCode) 0x01) -#define CSR_WIFI_SME_TSPEC_RESULT_FAILURE ((CsrWifiSmeTspecResultCode) 0x02) -#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TSPEC_PARAMETERS ((CsrWifiSmeTspecResultCode) 0x05) -#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TCLAS_PARAMETERS ((CsrWifiSmeTspecResultCode) 0x06) -#define CSR_WIFI_SME_TSPEC_RESULT_INSUFFICIENT_BANDWIDTH ((CsrWifiSmeTspecResultCode) 0x07) -#define CSR_WIFI_SME_TSPEC_RESULT_WRONG_POLICY ((CsrWifiSmeTspecResultCode) 0x08) -#define CSR_WIFI_SME_TSPEC_RESULT_REJECTED_WITH_SUGGESTED_CHANGES ((CsrWifiSmeTspecResultCode) 0x09) -#define CSR_WIFI_SME_TSPEC_RESULT_TIMEOUT ((CsrWifiSmeTspecResultCode) 0x0D) -#define CSR_WIFI_SME_TSPEC_RESULT_NOT_SUPPORTED ((CsrWifiSmeTspecResultCode) 0x0E) -#define CSR_WIFI_SME_TSPEC_RESULT_IE_LENGTH_INCORRECT ((CsrWifiSmeTspecResultCode) 0x10) -#define CSR_WIFI_SME_TSPEC_RESULT_INVALID_TRANSACTION_ID ((CsrWifiSmeTspecResultCode) 0x11) -#define CSR_WIFI_SME_TSPEC_RESULT_INSTALLED ((CsrWifiSmeTspecResultCode) 0x12) -#define CSR_WIFI_SME_TSPEC_RESULT_TID_ALREADY_INSTALLED ((CsrWifiSmeTspecResultCode) 0x13) -#define CSR_WIFI_SME_TSPEC_RESULT_TSPEC_REMOTELY_DELETED ((CsrWifiSmeTspecResultCode) 0x14) - -/******************************************************************************* - - NAME - CsrWifiSmeWepAuthMode - - DESCRIPTION - Define bits for CsrWifiSmeWepAuthMode - - VALUES - CSR_WIFI_SME_WEP_AUTH_MODE_OPEN - Open-WEP enabled network - CSR_WIFI_SME_WEP_AUTH_MODE_SHARED - Shared-key WEP enabled network. - -*******************************************************************************/ -typedef u8 CsrWifiSmeWepAuthMode; -#define CSR_WIFI_SME_WEP_AUTH_MODE_OPEN ((CsrWifiSmeWepAuthMode) 0x00) -#define CSR_WIFI_SME_WEP_AUTH_MODE_SHARED ((CsrWifiSmeWepAuthMode) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeWepCredentialType - - DESCRIPTION - Definition of types of WEP Credentials - - VALUES - CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64 - - WEP 64 credential - CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128 - - WEP 128 credential - -*******************************************************************************/ -typedef u8 CsrWifiSmeWepCredentialType; -#define CSR_WIFI_SME_CREDENTIAL_TYPE_WEP64 ((CsrWifiSmeWepCredentialType) 0x00) -#define CSR_WIFI_SME_CREDENTIAL_TYPE_WEP128 ((CsrWifiSmeWepCredentialType) 0x01) - -/******************************************************************************* - - NAME - CsrWifiSmeWmmMode - - DESCRIPTION - Defines bits for CsrWifiSmeWmmModeMask: enable/disable WMM features. - - VALUES - CSR_WIFI_SME_WMM_MODE_DISABLED - Disables the WMM features. - CSR_WIFI_SME_WMM_MODE_AC_ENABLED - Enables support for WMM-AC. - CSR_WIFI_SME_WMM_MODE_PS_ENABLED - Enables support for WMM Power Save. - CSR_WIFI_SME_WMM_MODE_SA_ENABLED - Currently not supported - CSR_WIFI_SME_WMM_MODE_ENABLED - Enables support for all currently - available WMM features. - -*******************************************************************************/ -typedef u8 CsrWifiSmeWmmMode; -#define CSR_WIFI_SME_WMM_MODE_DISABLED ((CsrWifiSmeWmmMode) 0x00) -#define CSR_WIFI_SME_WMM_MODE_AC_ENABLED ((CsrWifiSmeWmmMode) 0x01) -#define CSR_WIFI_SME_WMM_MODE_PS_ENABLED ((CsrWifiSmeWmmMode) 0x02) -#define CSR_WIFI_SME_WMM_MODE_SA_ENABLED ((CsrWifiSmeWmmMode) 0x04) -#define CSR_WIFI_SME_WMM_MODE_ENABLED ((CsrWifiSmeWmmMode) 0xFF) - -/******************************************************************************* - - NAME - CsrWifiSmeWmmQosInfo - - DESCRIPTION - Defines bits for the QoS Info Octect as defined in the WMM specification. - The first four values define one bit each that can be set or cleared. - Each of the last four values define all the remaining 4 bits and only one - of them at the time shall be used. - For more information, see 'WMM (including WMM Power Save) Specification - - Version 1.1' and 'UniFi Configuring WMM and WMM-PS, Application Note'. - - VALUES - CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_ALL - - WMM AP may deliver all buffered frames - CSR_WIFI_SME_WMM_QOS_INFO_AC_VO - - Enable UAPSD(both trigger and delivery) for Voice Access - Category - CSR_WIFI_SME_WMM_QOS_INFO_AC_VI - - Enable UAPSD(both trigger and delivery) for Video Access - Category - CSR_WIFI_SME_WMM_QOS_INFO_AC_BK - - Enable UAPSD(both trigger and delivery) for Background - Access Category - CSR_WIFI_SME_WMM_QOS_INFO_AC_BE - - Enable UAPSD(both trigger and delivery) for Best Effort - Access Category - CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_TWO - - WMM AP may deliver a maximum of 2 buffered frames (MSDUs - and MMPDUs) per USP - CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_FOUR - - WMM AP may deliver a maximum of 4 buffered frames (MSDUs - and MMPDUs) per USP - CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_SIX - - WMM AP may deliver a maximum of 6 buffered frames (MSDUs - and MMPDUs) per USP - -*******************************************************************************/ -typedef u8 CsrWifiSmeWmmQosInfo; -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_ALL ((CsrWifiSmeWmmQosInfo) 0x00) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_VO ((CsrWifiSmeWmmQosInfo) 0x01) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_VI ((CsrWifiSmeWmmQosInfo) 0x02) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_BK ((CsrWifiSmeWmmQosInfo) 0x04) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_BE ((CsrWifiSmeWmmQosInfo) 0x08) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_TWO ((CsrWifiSmeWmmQosInfo) 0x20) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_FOUR ((CsrWifiSmeWmmQosInfo) 0x40) -#define CSR_WIFI_SME_WMM_QOS_INFO_AC_MAX_SP_SIX ((CsrWifiSmeWmmQosInfo) 0x60) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigType - - DESCRIPTION - WPS config methods supported/used by a device - - VALUES - CSR_WIFI_WPS_CONFIG_LABEL - - Label - CSR_WIFI_WPS_CONFIG_DISPLAY - - Display - CSR_WIFI_WPS_CONFIG_EXT_NFC - - External NFC : Not supported in this release - CSR_WIFI_WPS_CONFIG_INT_NFC - - Internal NFC : Not supported in this release - CSR_WIFI_WPS_CONFIG_NFC_IFACE - - NFC interface : Not supported in this release - CSR_WIFI_WPS_CONFIG_PBC - - PBC - CSR_WIFI_WPS_CONFIG_KEYPAD - - KeyPad - CSR_WIFI_WPS_CONFIG_VIRTUAL_PBC - - PBC through software user interface - CSR_WIFI_WPS_CONFIG_PHYSICAL_PBC - - Physical PBC - CSR_WIFI_WPS_CONFIG_VIRTUAL_DISPLAY - - Virtual Display : via html config page etc - CSR_WIFI_WPS_CONFIG_PHYSICAL_DISPLAY - - Physical Display : Attached to the device - -*******************************************************************************/ -typedef u16 CsrWifiSmeWpsConfigType; -#define CSR_WIFI_WPS_CONFIG_LABEL ((CsrWifiSmeWpsConfigType) 0x0004) -#define CSR_WIFI_WPS_CONFIG_DISPLAY ((CsrWifiSmeWpsConfigType) 0x0008) -#define CSR_WIFI_WPS_CONFIG_EXT_NFC ((CsrWifiSmeWpsConfigType) 0x0010) -#define CSR_WIFI_WPS_CONFIG_INT_NFC ((CsrWifiSmeWpsConfigType) 0x0020) -#define CSR_WIFI_WPS_CONFIG_NFC_IFACE ((CsrWifiSmeWpsConfigType) 0x0040) -#define CSR_WIFI_WPS_CONFIG_PBC ((CsrWifiSmeWpsConfigType) 0x0080) -#define CSR_WIFI_WPS_CONFIG_KEYPAD ((CsrWifiSmeWpsConfigType) 0x0100) -#define CSR_WIFI_WPS_CONFIG_VIRTUAL_PBC ((CsrWifiSmeWpsConfigType) 0x0280) -#define CSR_WIFI_WPS_CONFIG_PHYSICAL_PBC ((CsrWifiSmeWpsConfigType) 0x0480) -#define CSR_WIFI_WPS_CONFIG_VIRTUAL_DISPLAY ((CsrWifiSmeWpsConfigType) 0x2008) -#define CSR_WIFI_WPS_CONFIG_PHYSICAL_DISPLAY ((CsrWifiSmeWpsConfigType) 0x4008) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsDeviceCategory - - DESCRIPTION - Wps Primary Device Types - - VALUES - CSR_WIFI_SME_WPS_CATEGORY_UNSPECIFIED - - Unspecified. - CSR_WIFI_SME_WPS_CATEGORY_COMPUTER - - Computer. - CSR_WIFI_SME_WPS_CATEGORY_INPUT_DEV - - Input device - CSR_WIFI_SME_WPS_CATEGORY_PRT_SCAN_FX_CP - - Printer Scanner Fax Copier etc - CSR_WIFI_SME_WPS_CATEGORY_CAMERA - - Camera - CSR_WIFI_SME_WPS_CATEGORY_STORAGE - - Storage - CSR_WIFI_SME_WPS_CATEGORY_NET_INFRA - - Net Infra - CSR_WIFI_SME_WPS_CATEGORY_DISPLAY - - Display - CSR_WIFI_SME_WPS_CATEGORY_MULTIMEDIA - - Multimedia - CSR_WIFI_SME_WPS_CATEGORY_GAMING - - Gaming. - CSR_WIFI_SME_WPS_CATEGORY_TELEPHONE - - Telephone. - CSR_WIFI_SME_WPS_CATEGORY_AUDIO - - Audio - CSR_WIFI_SME_WPS_CATEOARY_OTHERS - - Others. - -*******************************************************************************/ -typedef u8 CsrWifiSmeWpsDeviceCategory; -#define CSR_WIFI_SME_WPS_CATEGORY_UNSPECIFIED ((CsrWifiSmeWpsDeviceCategory) 0x00) -#define CSR_WIFI_SME_WPS_CATEGORY_COMPUTER ((CsrWifiSmeWpsDeviceCategory) 0x01) -#define CSR_WIFI_SME_WPS_CATEGORY_INPUT_DEV ((CsrWifiSmeWpsDeviceCategory) 0x02) -#define CSR_WIFI_SME_WPS_CATEGORY_PRT_SCAN_FX_CP ((CsrWifiSmeWpsDeviceCategory) 0x03) -#define CSR_WIFI_SME_WPS_CATEGORY_CAMERA ((CsrWifiSmeWpsDeviceCategory) 0x04) -#define CSR_WIFI_SME_WPS_CATEGORY_STORAGE ((CsrWifiSmeWpsDeviceCategory) 0x05) -#define CSR_WIFI_SME_WPS_CATEGORY_NET_INFRA ((CsrWifiSmeWpsDeviceCategory) 0x06) -#define CSR_WIFI_SME_WPS_CATEGORY_DISPLAY ((CsrWifiSmeWpsDeviceCategory) 0x07) -#define CSR_WIFI_SME_WPS_CATEGORY_MULTIMEDIA ((CsrWifiSmeWpsDeviceCategory) 0x08) -#define CSR_WIFI_SME_WPS_CATEGORY_GAMING ((CsrWifiSmeWpsDeviceCategory) 0x09) -#define CSR_WIFI_SME_WPS_CATEGORY_TELEPHONE ((CsrWifiSmeWpsDeviceCategory) 0x0A) -#define CSR_WIFI_SME_WPS_CATEGORY_AUDIO ((CsrWifiSmeWpsDeviceCategory) 0x0B) -#define CSR_WIFI_SME_WPS_CATEOARY_OTHERS ((CsrWifiSmeWpsDeviceCategory) 0xFF) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsDeviceSubCategory - - DESCRIPTION - Wps Secondary Device Types - - VALUES - CSR_WIFI_SME_WPS_SUB_CATEGORY_UNSPECIFIED - - Unspecied - CSR_WIFI_SME_WPS_STORAGE_SUB_CATEGORY_NAS - - Network Associated Storage - CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_PRNTR - - Printer or print server - CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_WM - - Windows mobile - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_TUNER - - Audio tuner/receiver - CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_DIG_STL - - Digital still camera - CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_AP - - Access Point - CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_TV - - TV. - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_DAR - - DAR. - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_KEYBD - - Keyboard. - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_PC - - PC. - CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX - - Xbox. - CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_SCNR - - Scanner - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_SERVER - - Server - CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_ROUTER - - Router - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_PVR - - PVR - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_SPEAKER - - Speaker - CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_SM - - Feature phone - Single mode - CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_VIDEO - - Video camera - CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PIC_FRM - - Picture frame - CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX_360 - - Xbox360 - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_MOUSE - - Mouse - CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_SWITCH - - Switch - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_PMP - - Portable music player - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_JOYSTK - - Joy stick - CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PLAY_STN - - Play-station - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MED_CENT - - Media Center - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MCX - - MCX - CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_DM - - Feature phone - Dual mode - CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_WEB - - Web camera - CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_FAX - - Fax - CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PROJECTOR - - Projector - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TRKBL - - Track Ball - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_ST_BOX - - Set-Top-Box - CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_GATEWAY - - GateWay. - CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_SECURITY - - Security camera - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_ULTRA_MOB_PC - - Ultra mobile PC. - CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_CONSOLE - - Game console/Game console adapter - CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_CPR - - Copier - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADSET - - Headset(headphones + microphone) - CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_SM - - Smart phone - Single mode - CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_MONITOR - - Monitor. - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_GAME_CTRL - - Game control. - CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_ALL - - All-in-One - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MEDIA - - Media Server/Media Adapter/Media Extender - CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_DM - - Smart phone - Dual mode - CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PORT_DEV - - Portable gaming device - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADPHONE - - Headphone. - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NOTEBOOK - - Notebook. - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_REMOTE - - Remote control - CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_MIC - - Microphone - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_DESKTOP - - Desktop. - CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_VP - - Portable video player - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MID - - Mobile internet device - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TOUCH_SCRN - - Touch screen - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BIOMET_RDR - - Biometric reader - CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NETBOOK - - Netbook - CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BRCD_RDR - - Bar code reader. - -*******************************************************************************/ -typedef u8 CsrWifiSmeWpsDeviceSubCategory; -#define CSR_WIFI_SME_WPS_SUB_CATEGORY_UNSPECIFIED ((CsrWifiSmeWpsDeviceSubCategory) 0x00) -#define CSR_WIFI_SME_WPS_STORAGE_SUB_CATEGORY_NAS ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_PRNTR ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_WM ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_TUNER ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_DIG_STL ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_AP ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_TV ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_DAR ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_KEYBD ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_PC ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX ((CsrWifiSmeWpsDeviceSubCategory) 0x01) -#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_SCNR ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_SERVER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_ROUTER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_PVR ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_SPEAKER ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_SM ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_VIDEO ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PIC_FRM ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_XBOX_360 ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_MOUSE ((CsrWifiSmeWpsDeviceSubCategory) 0x02) -#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_SWITCH ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_PMP ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_JOYSTK ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PLAY_STN ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MED_CENT ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MCX ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_FP_DM ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_WEB ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_FAX ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_PROJECTOR ((CsrWifiSmeWpsDeviceSubCategory) 0x03) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TRKBL ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_ST_BOX ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_NET_INFRA_SUB_CATEGORY_GATEWAY ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_CAMERA_SUB_CATEGORY_SECURITY ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_ULTRA_MOB_PC ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_CONSOLE ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_CPR ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADSET ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_SM ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_DISPLAY_SUB_CATEGORY_MONITOR ((CsrWifiSmeWpsDeviceSubCategory) 0x04) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_GAME_CTRL ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_PSFC_SUB_CATEGORY_ALL ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_MEDIA ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_TELEPHONE_SUB_CATEGORY_SP_DM ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_GAMING_SUB_CATEGORY_PORT_DEV ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_HEADPHONE ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NOTEBOOK ((CsrWifiSmeWpsDeviceSubCategory) 0x05) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_REMOTE ((CsrWifiSmeWpsDeviceSubCategory) 0x06) -#define CSR_WIFI_SME_WPS_AUDIO_SUB_CATEGORY_MIC ((CsrWifiSmeWpsDeviceSubCategory) 0x06) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_DESKTOP ((CsrWifiSmeWpsDeviceSubCategory) 0x06) -#define CSR_WIFI_SME_WPS_MM_SUB_CATEGORY_VP ((CsrWifiSmeWpsDeviceSubCategory) 0x06) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_MID ((CsrWifiSmeWpsDeviceSubCategory) 0x07) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_TOUCH_SCRN ((CsrWifiSmeWpsDeviceSubCategory) 0x07) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BIOMET_RDR ((CsrWifiSmeWpsDeviceSubCategory) 0x08) -#define CSR_WIFI_SME_WPS_COMPUTER_SUB_CATEGORY_NETBOOK ((CsrWifiSmeWpsDeviceSubCategory) 0x08) -#define CSR_WIFI_SME_WPS_INPUT_DEV_SUB_CATEGORY_BRCD_RDR ((CsrWifiSmeWpsDeviceSubCategory) 0x09) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsDpid - - DESCRIPTION - Device Password ID for the chosen config method - - VALUES - CSR_WIFI_SME_WPS_DPID_PIN - PIN - CSR_WIFI_SME_WPS_DPID_USER - User specified : Used only during P2P GO - negotiation procedure - CSR_WIFI_SME_WPS_DPID_MACHINE - Machine specified i: Not used in this - release - CSR_WIFI_SME_WPS_DPID_REKEY - Rekey : Not used in this release - CSR_WIFI_SME_WPS_DPID_PBC - PBC - CSR_WIFI_SME_WPS_DPID_REGISTRAR - Registrar specified : Used only in P2P Go - negotiation procedure - -*******************************************************************************/ -typedef u16 CsrWifiSmeWpsDpid; -#define CSR_WIFI_SME_WPS_DPID_PIN ((CsrWifiSmeWpsDpid) 0x0000) -#define CSR_WIFI_SME_WPS_DPID_USER ((CsrWifiSmeWpsDpid) 0x0001) -#define CSR_WIFI_SME_WPS_DPID_MACHINE ((CsrWifiSmeWpsDpid) 0x0002) -#define CSR_WIFI_SME_WPS_DPID_REKEY ((CsrWifiSmeWpsDpid) 0x0003) -#define CSR_WIFI_SME_WPS_DPID_PBC ((CsrWifiSmeWpsDpid) 0x0004) -#define CSR_WIFI_SME_WPS_DPID_REGISTRAR ((CsrWifiSmeWpsDpid) 0x0005) - -/******************************************************************************* - - NAME - CsrWifiSmeWpsRegistration - - DESCRIPTION - - VALUES - CSR_WIFI_SME_WPS_REG_NOT_REQUIRED - No encryption set - CSR_WIFI_SME_WPS_REG_REQUIRED - No encryption set - CSR_WIFI_SME_WPS_REG_UNKNOWN - No encryption set - -*******************************************************************************/ -typedef u8 CsrWifiSmeWpsRegistration; -#define CSR_WIFI_SME_WPS_REG_NOT_REQUIRED ((CsrWifiSmeWpsRegistration) 0x00) -#define CSR_WIFI_SME_WPS_REG_REQUIRED ((CsrWifiSmeWpsRegistration) 0x01) -#define CSR_WIFI_SME_WPS_REG_UNKNOWN ((CsrWifiSmeWpsRegistration) 0x02) - - -/******************************************************************************* - - NAME - CsrWifiSmeAuthModeMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeAuthMode - -*******************************************************************************/ -typedef u16 CsrWifiSmeAuthModeMask; -/******************************************************************************* - - NAME - CsrWifiSmeEncryptionMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeEncryption - -*******************************************************************************/ -typedef u16 CsrWifiSmeEncryptionMask; -/******************************************************************************* - - NAME - CsrWifiSmeIndicationsMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeIndications - -*******************************************************************************/ -typedef u32 CsrWifiSmeIndicationsMask; -/******************************************************************************* - - NAME - CsrWifiSmeP2pCapabilityMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeP2pCapability - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pCapabilityMask; -/******************************************************************************* - - NAME - CsrWifiSmeP2pGroupCapabilityMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeP2pGroupCapability - -*******************************************************************************/ -typedef u8 CsrWifiSmeP2pGroupCapabilityMask; -/******************************************************************************* - - NAME - CsrWifiSmeTspecCtrlMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeTspecCtrl - -*******************************************************************************/ -typedef u8 CsrWifiSmeTspecCtrlMask; -/******************************************************************************* - - NAME - CsrWifiSmeWmmModeMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeWmmMode - -*******************************************************************************/ -typedef u8 CsrWifiSmeWmmModeMask; -/******************************************************************************* - - NAME - CsrWifiSmeWmmQosInfoMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeWmmQosInfo - -*******************************************************************************/ -typedef u8 CsrWifiSmeWmmQosInfoMask; -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigTypeMask - - DESCRIPTION - Mask type for use with the values defined by CsrWifiSmeWpsConfigType - -*******************************************************************************/ -typedef u16 CsrWifiSmeWpsConfigTypeMask; - - -/******************************************************************************* - - NAME - CsrWifiSmeAdHocConfig - - DESCRIPTION - Defines values to use when starting an Ad-hoc (IBSS) network. - - MEMBERS - atimWindowTu - ATIM window specified for IBSS - beaconPeriodTu - Interval between beacon packets - joinOnlyAttempts - Maximum number of attempts to join an ad-hoc network. - The default value is 1. - Set to 0 for infinite attempts. - joinAttemptIntervalMs - Time between scans for joining the requested IBSS. - -*******************************************************************************/ -typedef struct -{ - u16 atimWindowTu; - u16 beaconPeriodTu; - u16 joinOnlyAttempts; - u16 joinAttemptIntervalMs; -} CsrWifiSmeAdHocConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeAvailabilityConfig - - DESCRIPTION - - MEMBERS - listenChannel - - availabilityDuration - - avalabilityPeriod - - -*******************************************************************************/ -typedef struct -{ - u8 listenChannel; - u16 availabilityDuration; - u16 avalabilityPeriod; -} CsrWifiSmeAvailabilityConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfig - - DESCRIPTION - This type is reserved for future use and should not be used. - - MEMBERS - keepAliveTimeMs - NOT USED - apRoamingEnabled - NOT USED - measurementsMask - NOT USED - ccxRadioMgtEnabled - NOT USED - -*******************************************************************************/ -typedef struct -{ - u8 keepAliveTimeMs; - u8 apRoamingEnabled; - u8 measurementsMask; - u8 ccxRadioMgtEnabled; -} CsrWifiSmeCcxConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfig - - DESCRIPTION - Parameters for the coexistence behaviour. - - MEMBERS - coexEnableSchemeManagement - Enables the Coexistence Management Scheme - coexPeriodicWakeHost - If TRUE the firmware wakes up the host - periodically according to the traffic - period and latency parameters; the host - will then send the data to transmit only - when woken up. - If FALSE, the firmware does not wake up the - host and the host will send the data to - transmit to the firmware whenever there is - data to transmit - coexTrafficBurstyLatencyMs - Period of awakening for the firmware used - when bursty traffic is detected - coexTrafficContinuousLatencyMs - Period of awakening for the firmware used - when continuous traffic is detected - coexObexBlackoutDurationMs - Blackout Duration when a Obex Connection is - used - coexObexBlackoutPeriodMs - Blackout Period when a Obex Connection is - used - coexA2dpBrBlackoutDurationMs - Blackout Duration when a Basic Rate A2DP - Connection streaming data - coexA2dpBrBlackoutPeriodMs - Blackout Period when a Basic Rate A2DP - Connection streaming data - coexA2dpEdrBlackoutDurationMs - Blackout Duration when an Enhanced Data - Rate A2DP Connection streaming data - coexA2dpEdrBlackoutPeriodMs - Blackout Period when an Enhanced Data Rate - A2DP Connection streaming data - coexPagingBlackoutDurationMs - Blackout Duration when a BT page is active - coexPagingBlackoutPeriodMs - Blackout Period when a BT page is active - coexInquiryBlackoutDurationMs - Blackout Duration when a BT inquiry is - active - coexInquiryBlackoutPeriodMs - Blackout Period when a BT inquiry is active - -*******************************************************************************/ -typedef struct -{ - u8 coexEnableSchemeManagement; - u8 coexPeriodicWakeHost; - u16 coexTrafficBurstyLatencyMs; - u16 coexTrafficContinuousLatencyMs; - u16 coexObexBlackoutDurationMs; - u16 coexObexBlackoutPeriodMs; - u16 coexA2dpBrBlackoutDurationMs; - u16 coexA2dpBrBlackoutPeriodMs; - u16 coexA2dpEdrBlackoutDurationMs; - u16 coexA2dpEdrBlackoutPeriodMs; - u16 coexPagingBlackoutDurationMs; - u16 coexPagingBlackoutPeriodMs; - u16 coexInquiryBlackoutDurationMs; - u16 coexInquiryBlackoutPeriodMs; -} CsrWifiSmeCoexConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionStats - - DESCRIPTION - Indicates the statistics of the connection. - The dot11 fields are defined in the Annex D of the IEEE 802.11 standard. - - MEMBERS - unifiTxDataRate - - The bit rate currently in use for transmissions of unicast - data frames; a data rate in units of 500kbit/s. - On an infrastructure BSS, this is the data rate used in - communicating with the associated access point; if there is - none, an error is returned. - On an IBSS, this is the data rate used for the last - transmission of a unicast data frame to any station in the - IBSS. If no such transmission has been made, an error is - returned. - unifiRxDataRate - - As above for receiving data - dot11RetryCount - - See IEEE 802.11 Standard - dot11MultipleRetryCount - - See IEEE 802.11 Standard - dot11AckFailureCount - - See IEEE 802.11 Standard - dot11FrameDuplicateCount - - See IEEE 802.11 Standard - dot11FcsErrorCount - - See IEEE 802.11 Standard - dot11RtsSuccessCount - - See IEEE 802.11 Standard - dot11RtsFailureCount - - See IEEE 802.11 Standard - dot11FailedCount - - See IEEE 802.11 Standard - dot11TransmittedFragmentCount - - See IEEE 802.11 Standard - dot11TransmittedFrameCount - - See IEEE 802.11 Standard - dot11WepExcludedCount - - See IEEE 802.11 Standard - dot11WepIcvErrorCount - - See IEEE 802.11 Standard - dot11WepUndecryptableCount - - See IEEE 802.11 Standard - dot11MulticastReceivedFrameCount - - See IEEE 802.11 Standard - dot11MulticastTransmittedFrameCount - - See IEEE 802.11 Standard - dot11ReceivedFragmentCount - - See IEEE 802.11 Standard - dot11Rsna4WayHandshakeFailures - - See IEEE 802.11 Standard - dot11RsnaTkipCounterMeasuresInvoked - - See IEEE 802.11 Standard - dot11RsnaStatsTkipLocalMicFailures - - See IEEE 802.11 Standard - dot11RsnaStatsTkipReplays - - See IEEE 802.11 Standard - dot11RsnaStatsTkipIcvErrors - - See IEEE 802.11 Standard - dot11RsnaStatsCcmpReplays - - See IEEE 802.11 Standard - dot11RsnaStatsCcmpDecryptErrors - - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef struct -{ - u8 unifiTxDataRate; - u8 unifiRxDataRate; - u32 dot11RetryCount; - u32 dot11MultipleRetryCount; - u32 dot11AckFailureCount; - u32 dot11FrameDuplicateCount; - u32 dot11FcsErrorCount; - u32 dot11RtsSuccessCount; - u32 dot11RtsFailureCount; - u32 dot11FailedCount; - u32 dot11TransmittedFragmentCount; - u32 dot11TransmittedFrameCount; - u32 dot11WepExcludedCount; - u32 dot11WepIcvErrorCount; - u32 dot11WepUndecryptableCount; - u32 dot11MulticastReceivedFrameCount; - u32 dot11MulticastTransmittedFrameCount; - u32 dot11ReceivedFragmentCount; - u32 dot11Rsna4WayHandshakeFailures; - u32 dot11RsnaTkipCounterMeasuresInvoked; - u32 dot11RsnaStatsTkipLocalMicFailures; - u32 dot11RsnaStatsTkipReplays; - u32 dot11RsnaStatsTkipIcvErrors; - u32 dot11RsnaStatsCcmpReplays; - u32 dot11RsnaStatsCcmpDecryptErrors; -} CsrWifiSmeConnectionStats; - -/******************************************************************************* - - NAME - CsrWifiSmeDataBlock - - DESCRIPTION - Holds a generic data block to be passed through the interface - - MEMBERS - length - Length of the data block - data - Points to the first byte of the data block - -*******************************************************************************/ -typedef struct -{ - u16 length; - u8 *data; -} CsrWifiSmeDataBlock; - -/******************************************************************************* - - NAME - CsrWifiSmeEmpty - - DESCRIPTION - Empty Structure to indicate that no parameters are available. - - MEMBERS - empty - Only element of the empty structure (always set to 0). - -*******************************************************************************/ -typedef struct -{ - u8 empty; -} CsrWifiSmeEmpty; - -/******************************************************************************* - - NAME - CsrWifiSmeLinkQuality - - DESCRIPTION - Indicates the quality of the link - - MEMBERS - unifiRssi - Indicates the received signal strength indication of the link in - dBm - unifiSnr - Indicates the signal to noise ratio of the link in dB - -*******************************************************************************/ -typedef struct -{ - s16 unifiRssi; - s16 unifiSnr; -} CsrWifiSmeLinkQuality; - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfig - - DESCRIPTION - Allows low level configuration in the chip. - - MEMBERS - unifiFixMaxTxDataRate - This attribute is used in combination with - unifiFixTxDataRate. If it is FALSE, then - unifiFixTxDataRate specifies a specific data - rate to use. If it is TRUE, unifiFixTxDataRate - instead specifies a maximum data rate. - unifiFixTxDataRate - Transmit rate for unicast data. - See MIB description for more details - dot11RtsThreshold - See IEEE 802.11 Standard - dot11FragmentationThreshold - See IEEE 802.11 Standard - dot11CurrentTxPowerLevel - See IEEE 802.11 Standard - -*******************************************************************************/ -typedef struct -{ - u8 unifiFixMaxTxDataRate; - u8 unifiFixTxDataRate; - u16 dot11RtsThreshold; - u16 dot11FragmentationThreshold; - u16 dot11CurrentTxPowerLevel; -} CsrWifiSmeMibConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeP2pProfileIdentity - - DESCRIPTION - Details to be filled in - - MEMBERS - listenChannel - - availabilityDuration - - avalabilityPeriod - - -*******************************************************************************/ -typedef struct -{ - u8 listenChannel; - u16 availabilityDuration; - u16 avalabilityPeriod; -} CsrWifiSmeP2pProfileIdentity; - -/******************************************************************************* - - NAME - CsrWifiSmePmkid - - DESCRIPTION - Defines a PMKID association with BSS - - MEMBERS - bssid - BSS identifier - pmkid - PMKID - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress bssid; - u8 pmkid[16]; -} CsrWifiSmePmkid; - -/******************************************************************************* - - NAME - CsrWifiSmePmkidCandidate - - DESCRIPTION - Information for a PMKID candidate - - MEMBERS - bssid - BSS identifier - preAuthAllowed - Indicates whether preauthentication is allowed - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress bssid; - u8 preAuthAllowed; -} CsrWifiSmePmkidCandidate; - -/******************************************************************************* - - NAME - CsrWifiSmePmkidList - - DESCRIPTION - NOT USED - Used in the Sync access API - - MEMBERS - pmkidsCount - Number of PMKIDs in the list - pmkids - Points to the first PMKID in the list - -*******************************************************************************/ -typedef struct -{ - u8 pmkidsCount; - CsrWifiSmePmkid *pmkids; -} CsrWifiSmePmkidList; - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomainInfo - - DESCRIPTION - Regulatory domain options. - - MEMBERS - dot11MultiDomainCapabilityImplemented - - TRUE is the multi domain capability is implemented - dot11MultiDomainCapabilityEnabled - - TRUE is the multi domain capability is enabled - currentRegulatoryDomain - - Current regulatory domain - currentCountryCode - - Current country code as defined by the IEEE 802.11 - standards - -*******************************************************************************/ -typedef struct -{ - u8 dot11MultiDomainCapabilityImplemented; - u8 dot11MultiDomainCapabilityEnabled; - CsrWifiSmeRegulatoryDomain currentRegulatoryDomain; - u8 currentCountryCode[2]; -} CsrWifiSmeRegulatoryDomainInfo; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingBandData - - DESCRIPTION - Thresholds to define one usability level category for the received signal - - MEMBERS - rssiHighThreshold - Received Signal Strength Indication upper bound in dBm - for the usability level - rssiLowThreshold - Received Signal Strength Indication lower bound in dBm - for the usability level - snrHighThreshold - Signal to Noise Ratio upper bound in dB for the - usability level - snrLowThreshold - Signal to Noise Ratio lower bound in dB for the - usability level - -*******************************************************************************/ -typedef struct -{ - s16 rssiHighThreshold; - s16 rssiLowThreshold; - s16 snrHighThreshold; - s16 snrLowThreshold; -} CsrWifiSmeRoamingBandData; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigData - - DESCRIPTION - Configures the scanning behaviour of the driver and firmware - - MEMBERS - intervalSeconds - All the channels will be scanned once in this time - interval. - If connected, the channel scans are spread across - the interval. - If disconnected, all the channels will be scanned - together - validitySeconds - How long the scan result are cached - minActiveChannelTimeTu - Minimum time of listening on a channel being - actively scanned before leaving if no probe - responses or beacon frames have been received - maxActiveChannelTimeTu - Maximum time of listening on a channel being - actively scanned - minPassiveChannelTimeTu - Minimum time of listening on a channel being - passive scanned before leaving if no beacon frames - have been received - maxPassiveChannelTimeTu - Maximum time of listening on a channel being - passively scanned - -*******************************************************************************/ -typedef struct -{ - u16 intervalSeconds; - u16 validitySeconds; - u16 minActiveChannelTimeTu; - u16 maxActiveChannelTimeTu; - u16 minPassiveChannelTimeTu; - u16 maxPassiveChannelTimeTu; -} CsrWifiSmeScanConfigData; - -/******************************************************************************* - - NAME - CsrWifiSmeTsfTime - - DESCRIPTION - Time stamp representation - - MEMBERS - data - TSF Bytes - -*******************************************************************************/ -typedef struct -{ - u8 data[8]; -} CsrWifiSmeTsfTime; - -/******************************************************************************* - - NAME - CsrWifiSmeVersions - - DESCRIPTION - Reports version information for the chip, the firmware and the driver and - the SME. - - MEMBERS - chipId - Chip ID - chipVersion - Chip version ID - firmwareBuild - Firmware Rom build number - firmwarePatch - Firmware Patch build number (if applicable) - firmwareHip - Firmware HIP protocol version number - routerBuild - Router build number - routerHip - Router HIP protocol version number - smeBuild - SME build number - smeHip - SME HIP protocol version number - -*******************************************************************************/ -typedef struct -{ - u32 chipId; - u32 chipVersion; - u32 firmwareBuild; - u32 firmwarePatch; - u32 firmwareHip; - char *routerBuild; - u32 routerHip; - char *smeBuild; - u32 smeHip; -} CsrWifiSmeVersions; - -/******************************************************************************* - - NAME - CsrWifiSmeWmmAcParams - - DESCRIPTION - Structure holding WMM AC params data. - - MEMBERS - cwMin - Exponent for the calculation of CWmin. Range: 0 - to 15 - cwMax - Exponent for the calculation of CWmax. Range: 0 - to15 - aifs - Arbitration Inter Frame Spacing in terms of - number of timeslots. Range 2 to 15 - txopLimit - TXOP Limit in the units of 32 microseconds - admissionControlMandatory - Indicates whether the admission control is - mandatory or not. Current release does not - support admission control , hence shall be set - to FALSE. - -*******************************************************************************/ -typedef struct -{ - u8 cwMin; - u8 cwMax; - u8 aifs; - u16 txopLimit; - u8 admissionControlMandatory; -} CsrWifiSmeWmmAcParams; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsDeviceType - - DESCRIPTION - Structure holding AP WPS device type data. - - MEMBERS - deviceDetails - category , sub category etc - -*******************************************************************************/ -typedef struct -{ - u8 deviceDetails[8]; -} CsrWifiSmeWpsDeviceType; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsDeviceTypeCommon - - DESCRIPTION - - MEMBERS - spportWps - - deviceType - - -*******************************************************************************/ -typedef struct -{ - u8 spportWps; - u8 deviceType; -} CsrWifiSmeWpsDeviceTypeCommon; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsInfo - - DESCRIPTION - - MEMBERS - version - - configMethods - - devicePassworId - - -*******************************************************************************/ -typedef struct -{ - u16 version; - u16 configMethods; - u16 devicePassworId; -} CsrWifiSmeWpsInfo; - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidConfig - - DESCRIPTION - List of cloaked SSIDs . - - MEMBERS - cloakedSsidsCount - Number of cloaked SSID - cloakedSsids - Points to the first byte of the first SSID provided - -*******************************************************************************/ -typedef struct -{ - u8 cloakedSsidsCount; - CsrWifiSsid *cloakedSsids; -} CsrWifiSmeCloakedSsidConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexInfo - - DESCRIPTION - Information and state related to coexistence. - - MEMBERS - hasTrafficData - TRUE if any Wi-Fi traffic is detected - currentTrafficType - Current type of traffic - currentPeriodMs - Period of the traffic as detected by the traffic - analysis. - If the traffic is not periodic, it is set to 0. - currentPowerSave - Current power save level - currentCoexPeriodMs - Period of awakening for the firmware used when - periodic traffic is detected. - If the traffic is not periodic, it is set to 0. - currentCoexLatencyMs - Period of awakening for the firmware used when - non-periodic traffic is detected - hasBtDevice - TRUE if there is a Bluetooth device connected - currentBlackoutDurationUs - Current blackout duration for protecting - Bluetooth - currentBlackoutPeriodUs - Current blackout period - currentCoexScheme - Defines the scheme for the coexistence - signalling - -*******************************************************************************/ -typedef struct -{ - u8 hasTrafficData; - CsrWifiSmeTrafficType currentTrafficType; - u16 currentPeriodMs; - CsrWifiSmePowerSaveLevel currentPowerSave; - u16 currentCoexPeriodMs; - u16 currentCoexLatencyMs; - u8 hasBtDevice; - u32 currentBlackoutDurationUs; - u32 currentBlackoutPeriodUs; - CsrWifiSmeCoexScheme currentCoexScheme; -} CsrWifiSmeCoexInfo; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionConfig - - DESCRIPTION - Specifies the parameters that the SME should use in selecting a network. - - MEMBERS - ssid - - Service Set identifier - bssid - - BSS identifier - bssType - - Indicates the type of BSS - ifIndex - - Indicates the radio interface - privacyMode - - Specifies whether the privacy mode is enabled or disabled. - authModeMask - - Sets the authentication options that the SME can use while - associating to the AP - Set mask with values from CsrWifiSmeAuthMode - encryptionModeMask - - Sets the encryption options that the SME can use while - associating to the AP - Set mask with values from CsrWifiSmeEncryption - mlmeAssociateReqInformationElementsLength - - Length in bytes of information elements to be sent in the - Association Request. - mlmeAssociateReqInformationElements - - Points to the first byte of the information elements, if - any. - wmmQosInfo - - This parameter allows the driver's WMM behaviour to be - configured. - To enable support for WMM, use - CSR_WIFI_SME_SME_CONFIG_SET_REQ with the - CSR_WIFI_SME_WMM_MODE_AC_ENABLED bit set in wmmModeMask - field in smeConfig parameter. - Set mask with values from CsrWifiSmeWmmQosInfo - adhocJoinOnly - - This parameter is relevant only if bssType is NOT set to - CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: - if TRUE the SME will only try to join an ad-hoc network if - there is one already established; - if FALSE the SME will try to join an ad-hoc network if - there is one already established or it will try to - establish a new one - adhocChannel - - This parameter is relevant only if bssType is NOT set to - CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: - it indicates the channel to use joining an ad hoc network. - Setting this to 0 causes the SME to select a channel from - those permitted in the regulatory domain. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSsid ssid; - CsrWifiMacAddress bssid; - CsrWifiSmeBssType bssType; - CsrWifiSmeRadioIF ifIndex; - CsrWifiSme80211PrivacyMode privacyMode; - CsrWifiSmeAuthModeMask authModeMask; - CsrWifiSmeEncryptionMask encryptionModeMask; - u16 mlmeAssociateReqInformationElementsLength; - u8 *mlmeAssociateReqInformationElements; - CsrWifiSmeWmmQosInfoMask wmmQosInfo; - u8 adhocJoinOnly; - u8 adhocChannel; -} CsrWifiSmeConnectionConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionInfo - - DESCRIPTION - Parameters that the SME should use in selecting a network - - MEMBERS - ssid - Service set identifier - bssid - BSS identifier - networkType80211 - Physical layer used for the connection - channelNumber - Channel number - channelFrequency - Channel frequency - authMode - Authentication mode used for the connection - pairwiseCipher - Encryption type for peer to peer communication - groupCipher - Encryption type for broadcast and multicast - communication - ifIndex - Indicates the radio interface - atimWindowTu - ATIM window specified for IBSS - beaconPeriodTu - Interval between beacon packets - reassociation - Indicates whether a reassociation occurred - beaconFrameLength - Indicates the number of bytes of the beacon - frame - beaconFrame - Points at the first byte of the beacon frame - associationReqFrameLength - Indicates the number of bytes of the - association request frame - associationReqFrame - Points at the first byte of the association - request frame - associationRspFrameLength - Indicates the number of bytes of the - association response frame - associationRspFrame - Points at the first byte of the association - response frame - assocScanInfoElementsLength - Indicates the number of bytes in the buffer - pointed by assocScanInfoElements - assocScanInfoElements - Pointer to the buffer containing the - information elements of the probe response - received after the probe requests sent before - attempting to authenticate to the network - assocReqCapabilities - Reports the content of the Capability - information element as specified in the - association request. - assocReqListenIntervalTu - Listen Interval specified in the association - request - assocReqApAddress - AP address to which the association requests - has been sent - assocReqInfoElementsLength - Indicates the number of bytes of the - association request information elements - assocReqInfoElements - Points at the first byte of the association - request information elements - assocRspResult - Result reported in the association response - assocRspCapabilityInfo - Reports the content of the Capability - information element as received in the - association response. - assocRspAssociationId - Reports the association ID received in the - association response. - assocRspInfoElementsLength - Indicates the number of bytes of the - association response information elements - assocRspInfoElements - Points at the first byte of the association - response information elements - -*******************************************************************************/ -typedef struct -{ - CsrWifiSsid ssid; - CsrWifiMacAddress bssid; - CsrWifiSme80211NetworkType networkType80211; - u8 channelNumber; - u16 channelFrequency; - CsrWifiSmeAuthMode authMode; - CsrWifiSmeEncryption pairwiseCipher; - CsrWifiSmeEncryption groupCipher; - CsrWifiSmeRadioIF ifIndex; - u16 atimWindowTu; - u16 beaconPeriodTu; - u8 reassociation; - u16 beaconFrameLength; - u8 *beaconFrame; - u16 associationReqFrameLength; - u8 *associationReqFrame; - u16 associationRspFrameLength; - u8 *associationRspFrame; - u16 assocScanInfoElementsLength; - u8 *assocScanInfoElements; - u16 assocReqCapabilities; - u16 assocReqListenIntervalTu; - CsrWifiMacAddress assocReqApAddress; - u16 assocReqInfoElementsLength; - u8 *assocReqInfoElements; - CsrWifiSmeIEEE80211Result assocRspResult; - u16 assocRspCapabilityInfo; - u16 assocRspAssociationId; - u16 assocRspInfoElementsLength; - u8 *assocRspInfoElements; -} CsrWifiSmeConnectionInfo; - -/******************************************************************************* - - NAME - CsrWifiSmeDeviceConfig - - DESCRIPTION - General configuration options in the SME - - MEMBERS - trustLevel - Level of trust of the information coming from the - network - countryCode - Country code as specified by IEEE 802.11 standard - firmwareDriverInterface - Specifies the type of communication between Host - and Firmware - enableStrictDraftN - If TRUE TKIP is disallowed when connecting to - 802.11n enabled access points - -*******************************************************************************/ -typedef struct -{ - CsrWifiSme80211dTrustLevel trustLevel; - u8 countryCode[2]; - CsrWifiSmeFirmwareDriverInterface firmwareDriverInterface; - u8 enableStrictDraftN; -} CsrWifiSmeDeviceConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeDeviceInfo - - DESCRIPTION - P2P Information for a P2P Device - - MEMBERS - deviceAddress - Device Address of the P2P device - configMethods - Supported WPS configuration methods. - p2PDeviceCap - P2P device capabilities - primDeviceType - Primary WPS device type - secondaryDeviceTypeCount - Number of secondary device types - secDeviceType - list of secondary WPS device types - deviceName - Device name without up to 32 characters'\0'. - deviceNameLength - Number of characters of the device name - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress deviceAddress; - CsrWifiSmeWpsConfigTypeMask configMethods; - CsrWifiSmeP2pCapabilityMask p2PDeviceCap; - CsrWifiSmeWpsDeviceType primDeviceType; - u8 secondaryDeviceTypeCount; - CsrWifiSmeWpsDeviceType *secDeviceType; - u8 deviceName[32]; - u8 deviceNameLength; -} CsrWifiSmeDeviceInfo; - -/******************************************************************************* - - NAME - CsrWifiSmeDeviceInfoCommon - - DESCRIPTION - Structure holding device information. - - MEMBERS - p2pDeviceAddress - - primaryDeviceType - - secondaryDeviceTypesCount - - secondaryDeviceTypes - - deviceNameLength - - deviceName - - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress p2pDeviceAddress; - CsrWifiSmeWpsDeviceTypeCommon primaryDeviceType; - u8 secondaryDeviceTypesCount; - u8 secondaryDeviceTypes[10]; - u8 deviceNameLength; - u8 deviceName[32]; -} CsrWifiSmeDeviceInfoCommon; - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfig - - DESCRIPTION - Defines the host power state (for example, on mains power, on battery - power etc) and the periodicity of the traffic data. - - MEMBERS - powerMode - The wireless manager application should use the - powerMode parameter to inform the SME of the host - power state. - applicationDataPeriodMs - The applicationDataPeriodMs parameter allows a - wireless manager application to inform the SME - that an application is running that generates - periodic network traffic and the period of the - traffic. - An example of such an application is a VoIP client. - The wireless manager application should set - applicationDataPeriodMs to the period in - milliseconds between data packets or zero if no - periodic application is running. - Voip etc 0 = No Periodic Data - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeHostPowerMode powerMode; - u16 applicationDataPeriodMs; -} CsrWifiSmeHostConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeKey - - DESCRIPTION - Information for a key to be used for encryption - - MEMBERS - keyType - Specifies whether the key is a pairwise or group key; it - should be set to CSR_WIFI_SME_GROUP_KEY or - CSR_WIFI_SME_PAIRWISE_KEY, as required. - keyIndex - Specifies which WEP key (0-3) to set; it should be set to 0 - for a WPA/WPA2 pairwise key and non-zero for a WPA/WPA2 - group key. - wepTxKey - If wepTxKey is TRUE, and the key is a WEP key, the key will - be selected for encrypting transmitted packets. - To select a previously defined key as the transmit - encryption key, set keyIndex to the required key, wepTxKey - to TRUE and the keyLength to 0. - keyRsc - Key Receive Sequence Counter - authenticator - If TRUE the WMA will act as authenticator. - CURRENTLY NOT SUPPORTED - address - BSS identifier of the AP - keyLength - Length of the key in bytes - key - Points to the first byte of the key - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeKeyType keyType; - u8 keyIndex; - u8 wepTxKey; - u16 keyRsc[8]; - u8 authenticator; - CsrWifiMacAddress address; - u8 keyLength; - u8 key[32]; -} CsrWifiSmeKey; - -/******************************************************************************* - - NAME - CsrWifiSmeP2pClientInfoType - - DESCRIPTION - P2P Information for a P2P Client - - MEMBERS - p2PClientInterfaceAddress - MAC address of the P2P Client - clientDeviceInfo - Device Information - -*******************************************************************************/ -typedef struct -{ - CsrWifiMacAddress p2PClientInterfaceAddress; - CsrWifiSmeDeviceInfo clientDeviceInfo; -} CsrWifiSmeP2pClientInfoType; - -/******************************************************************************* - - NAME - CsrWifiSmeP2pGroupInfo - - DESCRIPTION - P2P Information for a P2P Group - - MEMBERS - groupCapability - P2P group capabilities - p2pDeviceAddress - Device Address of the GO - p2pClientInfoCount - Number of P2P Clients that belong to the group. - p2PClientInfo - Pointer to the list containing client information for - each client in the group - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeP2pGroupCapabilityMask groupCapability; - CsrWifiMacAddress p2pDeviceAddress; - u8 p2pClientInfoCount; - CsrWifiSmeP2pClientInfoType *p2PClientInfo; -} CsrWifiSmeP2pGroupInfo; - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfig - - DESCRIPTION - Configures the power-save behaviour of the driver and firmware. - - MEMBERS - powerSaveLevel - Power Save Level option - listenIntervalTu - Interval for waking to receive beacon frames - rxDtims - If TRUE, wake for DTIM every beacon period, to - allow the reception broadcast packets - d3AutoScanMode - Defines whether the autonomous scanning will be - turned off or will stay on during a D3 suspended - period - clientTrafficWindow - Deprecated - opportunisticPowerSave - Deprecated - noticeOfAbsence - Deprecated - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmePowerSaveLevel powerSaveLevel; - u16 listenIntervalTu; - u8 rxDtims; - CsrWifiSmeD3AutoScanMode d3AutoScanMode; - u8 clientTrafficWindow; - u8 opportunisticPowerSave; - u8 noticeOfAbsence; -} CsrWifiSmePowerConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfig - - DESCRIPTION - Configures the roaming behaviour of the driver and firmware - - MEMBERS - roamingBands - Defines the thresholds to determine the usability - level of the current connection. - roamingBands is indexed by the first 3 entries of - the CsrWifiSmeBasicUsability enum - disableSmoothRoaming - Disable the RSSI/SNR triggers from the Firmware - that the SME uses to detect the quality of the - connection. - This implicitly disables disableRoamScans - disableRoamScans - Disables the scanning for the roaming operation - reconnectLimit - Maximum number of times SME may reconnect in the - given interval - reconnectLimitIntervalMs - Interval for maximum number of times SME may - reconnect to the same Access Point - roamScanCfg - Scanning behaviour for the specifically aimed at - improving roaming performance. - roamScanCfg is indexed by the first 3 entries of - the CsrWifiSmeBasicUsability enum - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeRoamingBandData roamingBands[3]; - u8 disableSmoothRoaming; - u8 disableRoamScans; - u8 reconnectLimit; - u16 reconnectLimitIntervalMs; - CsrWifiSmeScanConfigData roamScanCfg[3]; -} CsrWifiSmeRoamingConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfig - - DESCRIPTION - Parameters for the autonomous scanning behaviour of the system - - MEMBERS - scanCfg - Scan configuration data. - Indexed by the CsrWifiSmeBasicUsability enum - disableAutonomousScans - Enables or disables the autonomous scan - maxResults - Maximum number of results to be cached in the SME - highRssiThreshold - High received signal strength indication threshold - in dBm for an AP above which the system will - report scan indications - lowRssiThreshold - Low received signal strength indication threshold - in dBm for an AP below which the system will - report scan indications - deltaRssiThreshold - Minimum difference for received signal strength - indication in dBm for an AP which trigger a scan - indication to be sent. - highSnrThreshold - High Signal to Noise Ratio threshold in dB for an - AP above which the system will report scan - indications - lowSnrThreshold - Low Signal to Noise Ratio threshold in dB for an - AP below which the system will report scan - indications - deltaSnrThreshold - Minimum difference for Signal to Noise Ratio in dB - for an AP which trigger a scan indication to be - sent. - passiveChannelListCount - Number of channels to be scanned passively. - passiveChannelList - Points to the first channel to be scanned - passively , if any. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeScanConfigData scanCfg[4]; - u8 disableAutonomousScans; - u16 maxResults; - s8 highRssiThreshold; - s8 lowRssiThreshold; - s8 deltaRssiThreshold; - s8 highSnrThreshold; - s8 lowSnrThreshold; - s8 deltaSnrThreshold; - u16 passiveChannelListCount; - u8 *passiveChannelList; -} CsrWifiSmeScanConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResult - - DESCRIPTION - This structure defines the scan result for each BSS found - - MEMBERS - ssid - Service set identifier - bssid - BSS identifier - rssi - Received signal strength indication in dBm - snr - Signal to noise ratio in dB - ifIndex - Indicates the radio interface - beaconPeriodTu - Interval between beacon frames - timeStamp - Timestamp in the BSS - localTime - Timestamp in the Access Point - channelFrequency - Channel frequency - capabilityInformation - Capabilities of the BSS. - channelNumber - Channel number - usability - Indicates the usability level. - bssType - Type of BSS. - informationElementsLength - Number of bytes of the information elements - received as part of the beacon or probe - response. - informationElements - Points to the first byte of the IEs received - as part of the beacon or probe response. - The format of the IEs is as specified in the - IEEE 802.11 specification. - p2pDeviceRole - Role of the P2P device. - Relevant only if bssType is - CSR_WIFI_SME_BSS_TYPE_P2P - deviceInfo - Union containing P2P device info which - depends on p2pDeviceRole parameter. - deviceInforeservedCli - - deviceInfogroupInfo - - deviceInforeservedNone - - deviceInfostandalonedevInfo - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSsid ssid; - CsrWifiMacAddress bssid; - s16 rssi; - s16 snr; - CsrWifiSmeRadioIF ifIndex; - u16 beaconPeriodTu; - CsrWifiSmeTsfTime timeStamp; - CsrWifiSmeTsfTime localTime; - u16 channelFrequency; - u16 capabilityInformation; - u8 channelNumber; - CsrWifiSmeBasicUsability usability; - CsrWifiSmeBssType bssType; - u16 informationElementsLength; - u8 *informationElements; - CsrWifiSmeP2pRole p2pDeviceRole; - union { - CsrWifiSmeEmpty reservedCli; - CsrWifiSmeP2pGroupInfo groupInfo; - CsrWifiSmeEmpty reservedNone; - CsrWifiSmeDeviceInfo standalonedevInfo; - } deviceInfo; -} CsrWifiSmeScanResult; - -/******************************************************************************* - - NAME - CsrWifiSmeStaConfig - - DESCRIPTION - Station configuration options in the SME - - MEMBERS - connectionQualityRssiChangeTrigger - Sets the difference of RSSI - measurements which triggers reports - from the Firmware - connectionQualitySnrChangeTrigger - Sets the difference of SNR measurements - which triggers reports from the - Firmware - wmmModeMask - Mask containing one or more values from - CsrWifiSmeWmmMode - ifIndex - Indicates the band of frequencies used - allowUnicastUseGroupCipher - If TRUE, it allows to use groupwise - keys if no pairwise key is specified - enableOpportunisticKeyCaching - If TRUE, enables the Opportunistic Key - Caching feature - -*******************************************************************************/ -typedef struct -{ - u8 connectionQualityRssiChangeTrigger; - u8 connectionQualitySnrChangeTrigger; - CsrWifiSmeWmmModeMask wmmModeMask; - CsrWifiSmeRadioIF ifIndex; - u8 allowUnicastUseGroupCipher; - u8 enableOpportunisticKeyCaching; -} CsrWifiSmeStaConfig; - -/******************************************************************************* - - NAME - CsrWifiSmeWep128Keys - - DESCRIPTION - Structure holding WEP Authentication Type and WEP keys that can be used - when using WEP128. - - MEMBERS - wepAuthType - Mask to select the WEP authentication type (Open or Shared) - selectedWepKey - Index to one of the four keys below indicating the - currently used WEP key. Mapping From SME/User -> firmware. - Key 1 -> Index 0. Key 2 -> Index 1. key 3 -> Index 2. Key - 4-> Index 3. - key1 - Value for key number 1. - key2 - Value for key number 2. - key3 - Value for key number 3. - key4 - Value for key number 4. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeWepAuthMode wepAuthType; - u8 selectedWepKey; - u8 key1[13]; - u8 key2[13]; - u8 key3[13]; - u8 key4[13]; -} CsrWifiSmeWep128Keys; - -/******************************************************************************* - - NAME - CsrWifiSmeWep64Keys - - DESCRIPTION - Structure holding WEP Authentication Type and WEP keys that can be used - when using WEP64. - - MEMBERS - wepAuthType - Mask to select the WEP authentication type (Open or Shared) - selectedWepKey - Index to one of the four keys below indicating the - currently used WEP key. Mapping From SME/User -> firmware. - Key 1 -> Index 0. Key 2 -> Index 1. key 3 -> Index 2. Key - 4-> Index 3. - key1 - Value for key number 1. - key2 - Value for key number 2. - key3 - Value for key number 3. - key4 - Value for key number 4. - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeWepAuthMode wepAuthType; - u8 selectedWepKey; - u8 key1[5]; - u8 key2[5]; - u8 key3[5]; - u8 key4[5]; -} CsrWifiSmeWep64Keys; - -/******************************************************************************* - - NAME - CsrWifiSmeWepAuth - - DESCRIPTION - WEP authentication parameter structure - - MEMBERS - wepKeyType - WEP key try (128 bit or 64 bit) - wepCredentials - Union containing credentials which depends on - wepKeyType parameter. - wepCredentialswep128Key - - wepCredentialswep64Key - - -*******************************************************************************/ -typedef struct -{ - CsrWifiSmeWepCredentialType wepKeyType; - union { - CsrWifiSmeWep128Keys wep128Key; - CsrWifiSmeWep64Keys wep64Key; - } wepCredentials; -} CsrWifiSmeWepAuth; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfig - - DESCRIPTION - Structure holding AP WPS Config data. - - MEMBERS - wpsVersion - wpsVersion should be 0x10 for WPS1.0h or 0x20 for - WSC2.0 - uuid - uuid. - deviceName - Device name upto 32 characters without '\0'. - deviceNameLength - deviceNameLen. - manufacturer - manufacturer: CSR - manufacturerLength - manufacturerLen. - modelName - modelName Unifi - modelNameLength - modelNameLen. - modelNumber - modelNumber - modelNumberLength - modelNumberLen. - serialNumber - serialNumber - primDeviceType - Primary WPS device type - secondaryDeviceTypeCount - Number of secondary device types - secondaryDeviceType - list of secondary WPS device types - configMethods - Supported WPS config methods - rfBands - RfBands. - osVersion - Os version on which the device is running - -*******************************************************************************/ -typedef struct -{ - u8 wpsVersion; - u8 uuid[16]; - u8 deviceName[32]; - u8 deviceNameLength; - u8 manufacturer[64]; - u8 manufacturerLength; - u8 modelName[32]; - u8 modelNameLength; - u8 modelNumber[32]; - u8 modelNumberLength; - u8 serialNumber[32]; - CsrWifiSmeWpsDeviceType primDeviceType; - u8 secondaryDeviceTypeCount; - CsrWifiSmeWpsDeviceType *secondaryDeviceType; - CsrWifiSmeWpsConfigTypeMask configMethods; - u8 rfBands; - u8 osVersion[4]; -} CsrWifiSmeWpsConfig; - - -/* Downstream */ -#define CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST (0x0000) - -#define CSR_WIFI_SME_ACTIVATE_REQ ((CsrWifiSmePrim) (0x0000 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_ADHOC_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0001 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_ADHOC_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0002 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_BLACKLIST_REQ ((CsrWifiSmePrim) (0x0003 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CALIBRATION_DATA_GET_REQ ((CsrWifiSmePrim) (0x0004 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CALIBRATION_DATA_SET_REQ ((CsrWifiSmePrim) (0x0005 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CCX_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0006 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CCX_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0007 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0008 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0009 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_INFO_GET_REQ ((CsrWifiSmePrim) (0x000A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECT_REQ ((CsrWifiSmePrim) (0x000B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x000C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_INFO_GET_REQ ((CsrWifiSmePrim) (0x000D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_STATS_GET_REQ ((CsrWifiSmePrim) (0x000E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_DEACTIVATE_REQ ((CsrWifiSmePrim) (0x000F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_DISCONNECT_REQ ((CsrWifiSmePrim) (0x0010 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_EVENT_MASK_SET_REQ ((CsrWifiSmePrim) (0x0011 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_HOST_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0012 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_HOST_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0013 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_KEY_REQ ((CsrWifiSmePrim) (0x0014 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_LINK_QUALITY_GET_REQ ((CsrWifiSmePrim) (0x0015 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0016 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0017 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_GET_NEXT_REQ ((CsrWifiSmePrim) (0x0018 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_GET_REQ ((CsrWifiSmePrim) (0x0019 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_SET_REQ ((CsrWifiSmePrim) (0x001A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_MULTICAST_ADDRESS_REQ ((CsrWifiSmePrim) (0x001B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_PACKET_FILTER_SET_REQ ((CsrWifiSmePrim) (0x001C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_REQ ((CsrWifiSmePrim) (0x001D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_PMKID_REQ ((CsrWifiSmePrim) (0x001E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_POWER_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x001F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_POWER_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0020 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_REQ ((CsrWifiSmePrim) (0x0021 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAMING_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0022 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAMING_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0023 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0024 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0025 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_FULL_REQ ((CsrWifiSmePrim) (0x0026 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_RESULTS_FLUSH_REQ ((CsrWifiSmePrim) (0x0027 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_RESULTS_GET_REQ ((CsrWifiSmePrim) (0x0028 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_STA_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0029 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_STA_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x002A + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_REQ ((CsrWifiSmePrim) (0x002B + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_TSPEC_REQ ((CsrWifiSmePrim) (0x002C + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_VERSIONS_GET_REQ ((CsrWifiSmePrim) (0x002D + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ ((CsrWifiSmePrim) (0x002E + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_OFF_REQ ((CsrWifiSmePrim) (0x002F + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_ON_REQ ((CsrWifiSmePrim) (0x0030 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CLOAKED_SSIDS_SET_REQ ((CsrWifiSmePrim) (0x0031 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_CLOAKED_SSIDS_GET_REQ ((CsrWifiSmePrim) (0x0032 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_COMMON_CONFIG_GET_REQ ((CsrWifiSmePrim) (0x0033 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ ((CsrWifiSmePrim) (0x0034 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ ((CsrWifiSmePrim) (0x0035 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_WPS_CONFIGURATION_REQ ((CsrWifiSmePrim) (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) -#define CSR_WIFI_SME_SET_REQ ((CsrWifiSmePrim) (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)) - - -#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) - -/* Upstream */ -#define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST (0x0000 + CSR_PRIM_UPSTREAM) - -#define CSR_WIFI_SME_ACTIVATE_CFM ((CsrWifiSmePrim)(0x0000 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0001 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0002 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ASSOCIATION_COMPLETE_IND ((CsrWifiSmePrim)(0x0003 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ASSOCIATION_START_IND ((CsrWifiSmePrim)(0x0004 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_BLACKLIST_CFM ((CsrWifiSmePrim)(0x0005 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CALIBRATION_DATA_GET_CFM ((CsrWifiSmePrim)(0x0006 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CALIBRATION_DATA_SET_CFM ((CsrWifiSmePrim)(0x0007 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CCX_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0008 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CCX_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0009 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x000A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x000B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_COEX_INFO_GET_CFM ((CsrWifiSmePrim)(0x000C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECT_CFM ((CsrWifiSmePrim)(0x000D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x000E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_INFO_GET_CFM ((CsrWifiSmePrim)(0x000F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_QUALITY_IND ((CsrWifiSmePrim)(0x0010 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CONNECTION_STATS_GET_CFM ((CsrWifiSmePrim)(0x0011 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_DEACTIVATE_CFM ((CsrWifiSmePrim)(0x0012 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_DISCONNECT_CFM ((CsrWifiSmePrim)(0x0013 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_EVENT_MASK_SET_CFM ((CsrWifiSmePrim)(0x0014 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_HOST_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0015 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_HOST_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0016 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_IBSS_STATION_IND ((CsrWifiSmePrim)(0x0017 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_KEY_CFM ((CsrWifiSmePrim)(0x0018 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_LINK_QUALITY_GET_CFM ((CsrWifiSmePrim)(0x0019 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MEDIA_STATUS_IND ((CsrWifiSmePrim)(0x001A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x001B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x001C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_GET_CFM ((CsrWifiSmePrim)(0x001D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_GET_NEXT_CFM ((CsrWifiSmePrim)(0x001E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIB_SET_CFM ((CsrWifiSmePrim)(0x001F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MIC_FAILURE_IND ((CsrWifiSmePrim)(0x0020 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_MULTICAST_ADDRESS_CFM ((CsrWifiSmePrim)(0x0021 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_PACKET_FILTER_SET_CFM ((CsrWifiSmePrim)(0x0022 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_PERMANENT_MAC_ADDRESS_GET_CFM ((CsrWifiSmePrim)(0x0023 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_PMKID_CANDIDATE_LIST_IND ((CsrWifiSmePrim)(0x0024 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_PMKID_CFM ((CsrWifiSmePrim)(0x0025 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_POWER_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0026 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_POWER_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0027 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_REGULATORY_DOMAIN_INFO_GET_CFM ((CsrWifiSmePrim)(0x0028 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAM_COMPLETE_IND ((CsrWifiSmePrim)(0x0029 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAM_START_IND ((CsrWifiSmePrim)(0x002A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAMING_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x002B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ROAMING_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x002C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x002D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x002E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_FULL_CFM ((CsrWifiSmePrim)(0x002F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_RESULT_IND ((CsrWifiSmePrim)(0x0030 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_RESULTS_FLUSH_CFM ((CsrWifiSmePrim)(0x0031 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SCAN_RESULTS_GET_CFM ((CsrWifiSmePrim)(0x0032 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_STA_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0033 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_STA_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0034 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_STATION_MAC_ADDRESS_GET_CFM ((CsrWifiSmePrim)(0x0035 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_TSPEC_IND ((CsrWifiSmePrim)(0x0036 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_TSPEC_CFM ((CsrWifiSmePrim)(0x0037 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_VERSIONS_GET_CFM ((CsrWifiSmePrim)(0x0038 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_FLIGHTMODE_CFM ((CsrWifiSmePrim)(0x0039 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_OFF_IND ((CsrWifiSmePrim)(0x003A + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_OFF_CFM ((CsrWifiSmePrim)(0x003B + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_ON_CFM ((CsrWifiSmePrim)(0x003C + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CLOAKED_SSIDS_SET_CFM ((CsrWifiSmePrim)(0x003D + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CLOAKED_SSIDS_GET_CFM ((CsrWifiSmePrim)(0x003E + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WIFI_ON_IND ((CsrWifiSmePrim)(0x003F + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_COMMON_CONFIG_GET_CFM ((CsrWifiSmePrim)(0x0040 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_CFM ((CsrWifiSmePrim)(0x0041 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_CFM ((CsrWifiSmePrim)(0x0042 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_ERROR_IND ((CsrWifiSmePrim)(0x0043 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_INFO_IND ((CsrWifiSmePrim)(0x0044 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_CORE_DUMP_IND ((CsrWifiSmePrim)(0x0045 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_AMP_STATUS_CHANGE_IND ((CsrWifiSmePrim)(0x0046 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) -#define CSR_WIFI_SME_WPS_CONFIGURATION_CFM ((CsrWifiSmePrim)(0x0047 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST)) - -#define CSR_WIFI_SME_PRIM_UPSTREAM_HIGHEST (0x0047 + CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST) - -#define CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT (CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST) -#define CSR_WIFI_SME_PRIM_UPSTREAM_COUNT (CSR_WIFI_SME_PRIM_UPSTREAM_HIGHEST + 1 - CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST) - -/******************************************************************************* - - NAME - CsrWifiSmeActivateReq - - DESCRIPTION - The WMA sends this primitive to activate the SME. - The WMA must activate the SME before it can send any other primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeActivateReq; - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigGetReq - - DESCRIPTION - This primitive gets the value of the adHocConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeAdhocConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigSetReq - - DESCRIPTION - This primitive sets the value of the adHocConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - adHocConfig - Sets the values to use when starting an ad hoc network. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeAdHocConfig adHocConfig; -} CsrWifiSmeAdhocConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeBlacklistReq - - DESCRIPTION - The wireless manager application should call this primitive to notify the - driver of any networks that should not be connected to. The interface - allows the wireless manager application to query, add, remove, and flush - the BSSIDs that the driver may not connect or roam to. - When this primitive adds to the black list the BSSID to which the SME is - currently connected, the SME will try to roam, if applicable, to another - BSSID in the same ESS; if the roaming procedure fails, the SME will - disconnect. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs - the driver to modify or provide the list of blacklisted - networks. - setAddressCount - Number of BSSIDs sent with this primitive - setAddresses - Pointer to the list of BBSIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeListAction action; - u8 setAddressCount; - CsrWifiMacAddress *setAddresses; -} CsrWifiSmeBlacklistReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataGetReq - - DESCRIPTION - This primitive retrieves the Wi-Fi radio calibration data. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeCalibrationDataGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataSetReq - - DESCRIPTION - This primitive sets the Wi-Fi radio calibration data. - The usage of the primitive with proper calibration data will avoid - time-consuming configuration after power-up. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - calibrationDataLength - Number of bytes in the buffer pointed by - calibrationData - calibrationData - Pointer to a buffer of length calibrationDataLength - containing the calibration data - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 calibrationDataLength; - u8 *calibrationData; -} CsrWifiSmeCalibrationDataSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigGetReq - - DESCRIPTION - This primitive gets the value of the CcxConfig parameter. - CURRENTLY NOT SUPPORTED. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeCcxConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigSetReq - - DESCRIPTION - This primitive sets the value of the CcxConfig parameter. - CURRENTLY NOT SUPPORTED. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - ccxConfig - Currently not supported - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeCcxConfig ccxConfig; -} CsrWifiSmeCcxConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigGetReq - - DESCRIPTION - This primitive gets the value of the CoexConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeCoexConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigSetReq - - DESCRIPTION - This primitive sets the value of the CoexConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - coexConfig - Configures the coexistence behaviour - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeCoexConfig coexConfig; -} CsrWifiSmeCoexConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexInfoGetReq - - DESCRIPTION - This primitive gets the value of the CoexInfo parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeCoexInfoGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectReq - - DESCRIPTION - The wireless manager application calls this primitive to start the - process of joining an 802.11 wireless network or to start an ad hoc - network. - The structure pointed by connectionConfig contains parameters describing - the network to join or, in case of an ad hoc network, to host or join. - The SME will select a network, perform the IEEE 802.11 Join, Authenticate - and Associate exchanges. - The SME selects the networks from the current scan list that match both - the SSID and BSSID, however either or both of these may be the wildcard - value. Using this rule, the following operations are possible: - * To connect to a network by name, specify the SSID and set the BSSID to - 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF. If there are two or more networks visible, - the SME will select the one with the strongest signal. - * To connect to a specific network, specify the BSSID. The SSID is - optional, but if given it must match the SSID of the network. An empty - SSID may be specified by setting the SSID length to zero. Please note - that if the BSSID is specified (i.e. not equal to 0xFF 0xFF 0xFF 0xFF - 0xFF 0xFF), the SME will not attempt to roam if signal conditions become - poor, even if there is an alternative AP with an SSID that matches the - current network SSID. - * To connect to any network matching the other parameters (i.e. security, - etc), set the SSID length to zero and set the BSSID to 0xFF 0xFF 0xFF - 0xFF 0xFF 0xFF. In this case, the SME will order all available networks - by their signal strengths and will iterate through this list until it - successfully connects. - NOTE: Specifying the BSSID will restrict the selection to one specific - network. If SSID and BSSID are given, they must both match the network - for it to be selected. To select a network based on the SSID only, the - wireless manager application must set the BSSID to 0xFF 0xFF 0xFF 0xFF - 0xFF 0xFF. - The SME will try to connect to each network that matches the provided - parameters, one by one, until it succeeds or has tried unsuccessfully - with all the matching networks. - If there is no network that matches the parameters and the request allows - to host an ad hoc network, the SME will advertise a new ad hoc network - instead. - If the SME cannot connect, it will notify the failure in the confirm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - connectionConfig - Describes the candidate network to join or to host. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeConnectionConfig connectionConfig; -} CsrWifiSmeConnectReq; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionConfigGetReq - - DESCRIPTION - This primitive gets the value of the ConnectionConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeConnectionConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionInfoGetReq - - DESCRIPTION - This primitive gets the value of the ConnectionInfo parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeConnectionInfoGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionStatsGetReq - - DESCRIPTION - This primitive gets the value of the ConnectionStats parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeConnectionStatsGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeDeactivateReq - - DESCRIPTION - The WMA sends this primitive to deactivate the SME. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeDeactivateReq; - -/******************************************************************************* - - NAME - CsrWifiSmeDisconnectReq - - DESCRIPTION - The wireless manager application may disconnect from the current network - by calling this primitive - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeDisconnectReq; - -/******************************************************************************* - - NAME - CsrWifiSmeEventMaskSetReq - - DESCRIPTION - The wireless manager application may register with the SME to receive - notification of interesting events. Indications will be sent only if the - wireless manager explicitly registers to be notified of that event. - indMask is a bit mask of values defined in CsrWifiSmeIndicationsMask. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - indMask - Set mask with values from CsrWifiSmeIndications - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeIndicationsMask indMask; -} CsrWifiSmeEventMaskSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigGetReq - - DESCRIPTION - This primitive gets the value of the hostConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeHostConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigSetReq - - DESCRIPTION - This primitive sets the value of the hostConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - hostConfig - Communicates a change of host power state (for example, on - mains power, on battery power etc) and of the periodicity of - traffic data - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeHostConfig hostConfig; -} CsrWifiSmeHostConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeKeyReq - - DESCRIPTION - The wireless manager application calls this primitive to add or remove - keys that the chip should use for encryption of data. - The interface allows the wireless manager application to add and remove - keys according to the specified action. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs the - driver to modify or provide the list of keys. - CSR_WIFI_SME_LIST_ACTION_GET is not supported here. - key - Key to be added or removed - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeListAction action; - CsrWifiSmeKey key; -} CsrWifiSmeKeyReq; - -/******************************************************************************* - - NAME - CsrWifiSmeLinkQualityGetReq - - DESCRIPTION - This primitive gets the value of the LinkQuality parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeLinkQualityGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigGetReq - - DESCRIPTION - This primitive gets the value of the MibConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeMibConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigSetReq - - DESCRIPTION - This primitive sets the value of the MibConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mibConfig - Conveys the desired value of various IEEE 802.11 attributes as - currently configured - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeMibConfig mibConfig; -} CsrWifiSmeMibConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetNextReq - - DESCRIPTION - To read a sequence of MIB parameters, for example a table, call this - primitive to find the name of the next MIB variable - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to a VarBind or VarBindList containing the - name(s) of the MIB variable(s) to search from. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 mibAttributeLength; - u8 *mibAttribute; -} CsrWifiSmeMibGetNextReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetReq - - DESCRIPTION - The wireless manager application calls this primitive to retrieve one or - more MIB variables. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names of the MIB variables to be retrieved - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 mibAttributeLength; - u8 *mibAttribute; -} CsrWifiSmeMibGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMibSetReq - - DESCRIPTION - The SME provides raw access to the MIB on the chip, which may be used by - some configuration or diagnostic utilities, but is not normally needed by - the wireless manager application. - The MIB access functions use BER encoded names (OID) of the MIB - parameters and BER encoded values, as described in the chip Host - Interface Protocol Specification. - The MIB parameters are described in 'Wi-Fi 5.0.0 Management Information - Base Reference Guide'. - The wireless manager application calls this primitive to set one or more - MIB variables - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names and values of the MIB variables to set - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 mibAttributeLength; - u8 *mibAttribute; -} CsrWifiSmeMibSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeMulticastAddressReq - - DESCRIPTION - The wireless manager application calls this primitive to specify the - multicast addresses which the chip should recognise. The interface allows - the wireless manager application to query, add, remove and flush the - multicast addresses for the network interface according to the specified - action. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter - instructs the driver to modify or provide the list of - MAC addresses. - setAddressesCount - Number of MAC addresses sent with the primitive - setAddresses - Pointer to the list of MAC Addresses sent with the - primitive, set to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeListAction action; - u8 setAddressesCount; - CsrWifiMacAddress *setAddresses; -} CsrWifiSmeMulticastAddressReq; - -/******************************************************************************* - - NAME - CsrWifiSmePacketFilterSetReq - - DESCRIPTION - The wireless manager application should call this primitive to enable or - disable filtering of broadcast packets: uninteresting broadcast packets - will be dropped by the Wi-Fi chip, instead of passing them up to the - host. - This has the advantage of saving power in the host application processor - as it removes the need to process unwanted packets. - All broadcast packets are filtered according to the filter and the filter - mode provided, except ARP packets, which are filtered using - arpFilterAddress. - Filters are not cumulative: only the parameters specified in the most - recent successful request are significant. - For more information, see 'UniFi Firmware API Specification'. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - filterLength - Length of the filter in bytes. - filterLength=0 disables the filter previously set - filter - Points to the first byte of the filter provided, if any. - This shall include zero or more instance of the - information elements of one of these types - * Traffic Classification (TCLAS) elements - * WMM-SA TCLAS elements - mode - Specifies whether the filter selects or excludes packets - matching the filter - arpFilterAddress - IPv4 address to be used for filtering the ARP packets. - * If the specified address is the IPv4 broadcast address - (255.255.255.255), all ARP packets are reported to the - host, - * If the specified address is NOT the IPv4 broadcast - address, only ARP packets with the specified address in - the Source or Target Protocol Address fields are reported - to the host - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u16 filterLength; - u8 *filter; - CsrWifiSmePacketFilterMode mode; - CsrWifiIp4Address arpFilterAddress; -} CsrWifiSmePacketFilterSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmePermanentMacAddressGetReq - - DESCRIPTION - This primitive retrieves the MAC address stored in EEPROM - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmePermanentMacAddressGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmePmkidReq - - DESCRIPTION - The wireless manager application calls this primitive to request an - operation on the SME PMKID list. - The action argument specifies the operation to perform. - When the connection is complete, the wireless manager application may - then send and receive EAPOL packets to complete WPA or WPA2 - authentication if appropriate. - The wireless manager application can then pass the resulting encryption - keys using this primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - action - The value of the CsrWifiSmeListAction parameter instructs - the driver to modify or provide the list of PMKIDs. - setPmkidsCount - Number of PMKIDs sent with the primitive - setPmkids - Pointer to the list of PMKIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeListAction action; - u8 setPmkidsCount; - CsrWifiSmePmkid *setPmkids; -} CsrWifiSmePmkidReq; - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigGetReq - - DESCRIPTION - This primitive gets the value of the PowerConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmePowerConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigSetReq - - DESCRIPTION - This primitive sets the value of the PowerConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - powerConfig - Power saving configuration - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmePowerConfig powerConfig; -} CsrWifiSmePowerConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomainInfoGetReq - - DESCRIPTION - This primitive gets the value of the RegulatoryDomainInfo parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeRegulatoryDomainInfoGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigGetReq - - DESCRIPTION - This primitive gets the value of the RoamingConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeRoamingConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigSetReq - - DESCRIPTION - This primitive sets the value of the RoamingConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - roamingConfig - Desired roaming behaviour values - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeRoamingConfig roamingConfig; -} CsrWifiSmeRoamingConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigGetReq - - DESCRIPTION - This primitive gets the value of the ScanConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeScanConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigSetReq - - DESCRIPTION - This primitive sets the value of the ScanConfig parameter. - The SME normally configures the firmware to perform autonomous scanning - without involving the host. - The firmware passes beacon / probe response or indicates loss of beacon - on certain changes of state, for example: - * A new AP is seen for the first time - * An AP is no longer visible - * The signal strength of an AP changes by more than a certain amount, as - configured by the thresholds in the scanConfig parameter - In addition to the autonomous scan, the wireless manager application may - request a scan at any time using CSR_WIFI_SME_SCAN_FULL_REQ. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - scanConfig - Reports the configuration for the autonomous scanning behaviour - of the firmware - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeScanConfig scanConfig; -} CsrWifiSmeScanConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeScanFullReq - - DESCRIPTION - The wireless manager application should call this primitive to request a - full scan. - Channels are scanned actively or passively according to the requirement - set by regulatory domain. - If the SME receives this primitive while a full scan is going on, the new - request is buffered and it will be served after the current full scan is - completed. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - ssidCount - Number of SSIDs provided. - If it is 0, the SME will attempt to detect any network - ssid - Points to the first SSID provided, if any. - bssid - BSS identifier. - If it is equal to FF-FF-FF-FF-FF, the SME will listen for - messages from any BSS. - If it is different from FF-FF-FF-FF-FF and any SSID is - provided, one SSID must match the network of the BSS. - forceScan - Forces the scan even if the SME is in a state which would - normally prevent it (e.g. autonomous scan is running). - bssType - Type of BSS to scan for - scanType - Type of scan to perform - channelListCount - Number of channels provided. - If it is 0, the SME will initiate a scan of all the - supported channels that are permitted by the current - regulatory domain. - channelList - Points to the first channel , or NULL if channelListCount - is zero. - probeIeLength - Length of the information element in bytes to be sent - with the probe message. - probeIe - Points to the first byte of the information element to be - sent with the probe message. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u8 ssidCount; - CsrWifiSsid *ssid; - CsrWifiMacAddress bssid; - u8 forceScan; - CsrWifiSmeBssType bssType; - CsrWifiSmeScanType scanType; - u16 channelListCount; - u8 *channelList; - u16 probeIeLength; - u8 *probeIe; -} CsrWifiSmeScanFullReq; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsFlushReq - - DESCRIPTION - The Wireless Manager calls this primitive to ask the SME to delete all - scan results from its cache, except for the scan result of any currently - connected network. - As scan results are received by the SME from the firmware, they are - cached in the SME memory. - Any time the Wireless Manager requests scan results, they are returned - from the SME internal cache. - For some applications it may be desirable to clear this cache prior to - requesting that a scan be performed; this will ensure that the cache then - only contains the networks detected in the most recent scan. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeScanResultsFlushReq; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsGetReq - - DESCRIPTION - The wireless manager application calls this primitive to retrieve the - current set of scan results, either after receiving a successful - CSR_WIFI_SME_SCAN_FULL_CFM, or to get autonomous scan results. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeScanResultsGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigGetReq - - DESCRIPTION - This primitive gets the value of the SmeStaConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; -} CsrWifiSmeSmeStaConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigSetReq - - DESCRIPTION - This primitive sets the value of the SmeConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - smeConfig - SME Station Parameters to be set - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeStaConfig smeConfig; -} CsrWifiSmeSmeStaConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeStationMacAddressGetReq - - DESCRIPTION - This primitives is used to retrieve the current MAC address used by the - station. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeStationMacAddressGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeTspecReq - - DESCRIPTION - The wireless manager application should call this primitive to use the - TSPEC feature. - The chip supports the use of TSPECs and TCLAS for the use of IEEE - 802.11/WMM Quality of Service features. - The API allows the wireless manager application to supply a correctly - formatted TSPEC and TCLAS pair to the driver. - After performing basic validation, the driver negotiates the installation - of the TSPEC with the AP as defined by the 802.11 specification. - The driver retains all TSPEC and TCLAS pairs until they are specifically - removed. - It is not compulsory for a TSPEC to have a TCLAS (NULL is used to - indicate that no TCLAS is supplied), while a TCLASS always require a - TSPEC. - The format of the TSPEC element is specified in 'WMM (including WMM Power - Save) Specification - Version 1.1' and 'ANSI/IEEE Std 802.11-REVmb/D3.0'. - For more information, see 'UniFi Configuring WMM and WMM-PS'. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - action - Specifies the action to be carried out on the list of TSPECs. - CSR_WIFI_SME_LIST_ACTION_FLUSH is not applicable here. - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - strict - If it set to false, allows the SME to perform automatic - TSPEC negotiation - ctrlMask - Additional TSPEC configuration for CCX. - Set mask with values from CsrWifiSmeTspecCtrl. - CURRENTLY NOT SUPPORTED - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - tclasLength - Length of the TCLAS. - If it is equal to 0, no TCLASS is provided for the TSPEC - tclas - Points to the first byte of the TCLAS, if any. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeListAction action; - u32 transactionId; - u8 strict; - CsrWifiSmeTspecCtrlMask ctrlMask; - u16 tspecLength; - u8 *tspec; - u16 tclasLength; - u8 *tclas; -} CsrWifiSmeTspecReq; - -/******************************************************************************* - - NAME - CsrWifiSmeVersionsGetReq - - DESCRIPTION - This primitive gets the value of the Versions parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeVersionsGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiFlightmodeReq - - DESCRIPTION - The wireless manager application may call this primitive on boot-up of - the platform to ensure that the chip is placed in a mode that prevents - any emission of RF energy. - This primitive is an alternative to CSR_WIFI_SME_WIFI_ON_REQ. - As in CSR_WIFI_SME_WIFI_ON_REQ, it causes the download of the patch file - (if any) and the programming of the initial MIB settings (if supplied by - the WMA), but it also ensures that the chip is left in its lowest - possible power-mode with the radio subsystems disabled. - This feature is useful on platforms where power cannot be removed from - the chip (leaving the chip not initialised will cause it to consume more - power so calling this function ensures that the chip is initialised into - a low power mode but without entering a state where it could emit any RF - energy). - NOTE: this primitive does not cause the Wi-Fi to change state: Wi-Fi - stays conceptually off. Configuration primitives can be sent after - CSR_WIFI_SME_WIFI_FLIGHTMODE_REQ and the configuration will be maintained. - Requests that require the state of the Wi-Fi to be ON will return - CSR_WIFI_SME_STATUS_WIFI_OFF in their confirms. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - address - Optionally specifies a station MAC address. - In normal use, the manager should set the address to 0xFF - 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use - the MAC address in the MIB. - mibFilesCount - Number of provided data blocks with initial MIB values - mibFiles - Points to the first data block with initial MIB values. - These data blocks are typically the contents of the provided - files ufmib.dat and localmib.dat, available from the host - file system, if they exist. - These files typically contain radio tuning and calibration - values. - More values can be created using the Host Tools. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiMacAddress address; - u16 mibFilesCount; - CsrWifiSmeDataBlock *mibFiles; -} CsrWifiSmeWifiFlightmodeReq; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffReq - - DESCRIPTION - The wireless manager application calls this primitive to turn off the - chip, thus saving power when Wi-Fi is not in use. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeWifiOffReq; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnReq - - DESCRIPTION - The wireless manager application calls this primitive to turn on the - Wi-Fi chip. - If the Wi-Fi chip is currently off, the SME turns the Wi-Fi chip on, - downloads the patch file (if any), and programs the initial MIB settings - (if supplied by the WMA). - The patch file is not provided with the SME API; its downloading is - automatic and handled internally by the system. - The MIB settings, when provided, override the default values that the - firmware loads from EEPROM. - If the Wi-Fi chip is already on, the SME takes no action and returns a - successful status in the confirm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - address - Optionally specifies a station MAC address. - In normal use, the manager should set the address to 0xFF - 0xFF 0xFF 0xFF 0xFF 0xFF, which will cause the chip to use - the MAC address in the MIB - mibFilesCount - Number of provided data blocks with initial MIB values - mibFiles - Points to the first data block with initial MIB values. - These data blocks are typically the contents of the provided - files ufmib.dat and localmib.dat, available from the host - file system, if they exist. - These files typically contain radio tuning and calibration - values. - More values can be created using the Host Tools. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiMacAddress address; - u16 mibFilesCount; - CsrWifiSmeDataBlock *mibFiles; -} CsrWifiSmeWifiOnReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsSetReq - - DESCRIPTION - This primitive sets the list of cloaked SSIDs for which the WMA possesses - profiles. - When the driver detects a cloaked AP, the SME will explicitly scan for it - using the list of cloaked SSIDs provided it, and, if the scan succeeds, - it will report the AP to the WMA either via CSR_WIFI_SME_SCAN_RESULT_IND - (if registered) or via CSR_WIFI_SCAN_RESULT_GET_CFM. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - cloakedSsids - Sets the list of cloaked SSIDs - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeCloakedSsidConfig cloakedSsids; -} CsrWifiSmeCloakedSsidsSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsGetReq - - DESCRIPTION - This primitive gets the value of the CloakedSsids parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeCloakedSsidsGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigGetReq - - DESCRIPTION - This primitive gets the value of the Sme common parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeSmeCommonConfigGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigSetReq - - DESCRIPTION - This primitive sets the value of the Sme common. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - deviceConfig - Configuration options in the SME - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeDeviceConfig deviceConfig; -} CsrWifiSmeSmeCommonConfigSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeInterfaceCapabilityGetReq - - DESCRIPTION - The Wireless Manager calls this primitive to ask the SME for the - capabilities of the supported interfaces - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; -} CsrWifiSmeInterfaceCapabilityGetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigurationReq - - DESCRIPTION - This primitive passes the WPS information for the device to SME. This may - be accepted only if no interface is active. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - wpsConfig - WPS config. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeWpsConfig wpsConfig; -} CsrWifiSmeWpsConfigurationReq; - -/******************************************************************************* - - NAME - CsrWifiSmeSetReq - - DESCRIPTION - Used to pass custom data to the SME. Format is the same as 802.11 Info - Elements => | Id | Length | Data - 1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01 - (0x00|0x01)" - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u32 dataLength; - u8 *data; -} CsrWifiSmeSetReq; - -/******************************************************************************* - - NAME - CsrWifiSmeActivateCfm - - DESCRIPTION - The SME sends this primitive when the activation is complete. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeActivateCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - adHocConfig - Contains the values used when starting an Ad-hoc (IBSS) - connection. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeAdHocConfig adHocConfig; -} CsrWifiSmeAdhocConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeAdhocConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeAdhocConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeAssociationCompleteInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it completes an attempt to associate with an AP. If - the association was successful, status will be set to - CSR_WIFI_SME_STATUS_SUCCESS, otherwise status and deauthReason shall be - set to appropriate error codes. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the association procedure - connectionInfo - This parameter is relevant only if result is - CSR_WIFI_SME_STATUS_SUCCESS: - it points to the connection information for the new network - deauthReason - This parameter is relevant only if result is not - CSR_WIFI_SME_STATUS_SUCCESS: - if the AP deauthorised the station, it gives the reason of - the deauthorization - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeConnectionInfo connectionInfo; - CsrWifiSmeIEEE80211Reason deauthReason; -} CsrWifiSmeAssociationCompleteInd; - -/******************************************************************************* - - NAME - CsrWifiSmeAssociationStartInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it begins an attempt to associate with an AP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - address - BSSID of the associating network - ssid - Service Set identifier of the associating network - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiMacAddress address; - CsrWifiSsid ssid; -} CsrWifiSmeAssociationStartInd; - -/******************************************************************************* - - NAME - CsrWifiSmeBlacklistCfm - - DESCRIPTION - The SME will call this primitive when the action on the blacklist has - completed. For a GET action, this primitive also reports the list of - BBSIDs in the blacklist. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getAddressCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of BSSIDs sent with this primitive - getAddresses - Pointer to the list of BBSIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeListAction action; - u8 getAddressCount; - CsrWifiMacAddress *getAddresses; -} CsrWifiSmeBlacklistCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - calibrationDataLength - Number of bytes in the buffer pointed by - calibrationData - calibrationData - Pointer to a buffer of length calibrationDataLength - containing the calibration data - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u16 calibrationDataLength; - u8 *calibrationData; -} CsrWifiSmeCalibrationDataGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCalibrationDataSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeCalibrationDataSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - ccxConfig - Currently not supported - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeCcxConfig ccxConfig; -} CsrWifiSmeCcxConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCcxConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeCcxConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - coexConfig - Reports the parameters used to configure the coexistence - behaviour - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeCoexConfig coexConfig; -} CsrWifiSmeCoexConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeCoexConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCoexInfoGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - coexInfo - Reports information and state related to coexistence. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeCoexInfo coexInfo; -} CsrWifiSmeCoexInfoGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectCfm - - DESCRIPTION - The SME calls this primitive when the connection exchange is complete or - all connection attempts fail. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request. - CSR_WIFI_SME_STATUS_NOT_FOUND: all attempts by the SME to - locate the requested AP failed - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeConnectCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionConfig - Parameters used by the SME for selecting a network - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeConnectionConfig connectionConfig; -} CsrWifiSmeConnectionConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionInfoGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionInfo - Information about the current connection - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeConnectionInfo connectionInfo; -} CsrWifiSmeConnectionInfoGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionQualityInd - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever the value of the current connection quality - parameters change by more than a certain configurable amount. - The wireless manager application may configure the trigger thresholds for - this indication using the field in smeConfig parameter of - CSR_WIFI_SME_SME_CONFIG_SET_REQ. - Connection quality messages can be suppressed by setting both thresholds - to zero. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - linkQuality - Indicates the quality of the link - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeLinkQuality linkQuality; -} CsrWifiSmeConnectionQualityInd; - -/******************************************************************************* - - NAME - CsrWifiSmeConnectionStatsGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - connectionStats - Statistics for current connection. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeConnectionStats connectionStats; -} CsrWifiSmeConnectionStatsGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeDeactivateCfm - - DESCRIPTION - The SME sends this primitive when the deactivation is complete. - The WMA cannot send any more primitives until it actives the SME again - sending another CSR_WIFI_SME_ACTIVATE_REQ. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeDeactivateCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeDisconnectCfm - - DESCRIPTION - On reception of CSR_WIFI_SME_DISCONNECT_REQ the SME will perform a - disconnect operation, sending a CsrWifiSmeMediaStatusInd with - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED and then call this primitive when - disconnection is complete. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeDisconnectCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeEventMaskSetCfm - - DESCRIPTION - The SME calls the primitive to report the result of the request - primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeEventMaskSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - hostConfig - Current host power state. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeHostConfig hostConfig; -} CsrWifiSmeHostConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeHostConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeHostConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeIbssStationInd - - DESCRIPTION - The SME will send this primitive to indicate that a station has joined or - left the ad-hoc network. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - address - MAC address of the station that has joined or left - isconnected - TRUE if the station joined, FALSE if the station left - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiMacAddress address; - u8 isconnected; -} CsrWifiSmeIbssStationInd; - -/******************************************************************************* - - NAME - CsrWifiSmeKeyCfm - - DESCRIPTION - The SME calls the primitive to report the result of the request - primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - keyType - Type of the key added/deleted - peerMacAddress - Peer MAC Address of the key added/deleted - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeListAction action; - CsrWifiSmeKeyType keyType; - CsrWifiMacAddress peerMacAddress; -} CsrWifiSmeKeyCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeLinkQualityGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - linkQuality - Indicates the quality of the link - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeLinkQuality linkQuality; -} CsrWifiSmeLinkQualityGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMediaStatusInd - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it when a network connection is established, lost or has moved to - another AP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - mediaStatus - Indicates the media status - connectionInfo - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_CONNECTED: - it points to the connection information for the new network - disassocReason - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: - if a disassociation has occurred it gives the reason of the - disassociation - deauthReason - This parameter is relevant only if the mediaStatus is - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED: - if a deauthentication has occurred it gives the reason of - the deauthentication - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeMediaStatus mediaStatus; - CsrWifiSmeConnectionInfo connectionInfo; - CsrWifiSmeIEEE80211Reason disassocReason; - CsrWifiSmeIEEE80211Reason deauthReason; -} CsrWifiSmeMediaStatusInd; - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - mibConfig - Reports various IEEE 802.11 attributes as currently configured - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeMibConfig mibConfig; -} CsrWifiSmeMibConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMibConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeMibConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetCfm - - DESCRIPTION - The SME calls this primitive to return the requested MIB variable values. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to the VarBind or VarBindList containing the - names and values of the MIB variables requested - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u16 mibAttributeLength; - u8 *mibAttribute; -} CsrWifiSmeMibGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMibGetNextCfm - - DESCRIPTION - The SME calls this primitive to return the requested MIB name(s). - The wireless manager application can then read the value of the MIB - variable using CSR_WIFI_SME_MIB_GET_REQ, using the names provided. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - mibAttributeLength - Length of mibAttribute - mibAttribute - Points to a VarBind or VarBindList containing the - name(s) of the MIB variable(s) lexicographically - following the name(s) given in the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u16 mibAttributeLength; - u8 *mibAttribute; -} CsrWifiSmeMibGetNextCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMibSetCfm - - DESCRIPTION - The SME calls the primitive to report the result of the set primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeMibSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeMicFailureInd - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever the chip firmware reports a MIC failure. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - secondFailure - TRUE if this indication is for a second failure in 60 - seconds - count - The number of MIC failure events since the connection was - established - address - MAC address of the transmitter that caused the MIC failure - keyType - Type of key for which the failure occurred - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 secondFailure; - u16 count; - CsrWifiMacAddress address; - CsrWifiSmeKeyType keyType; -} CsrWifiSmeMicFailureInd; - -/******************************************************************************* - - NAME - CsrWifiSmeMulticastAddressCfm - - DESCRIPTION - The SME will call this primitive when the operation is complete. For a - GET action, this primitive reports the current list of MAC addresses. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getAddressesCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of MAC addresses sent with the primitive - getAddresses - Pointer to the list of MAC Addresses sent with the - primitive, set to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeListAction action; - u8 getAddressesCount; - CsrWifiMacAddress *getAddresses; -} CsrWifiSmeMulticastAddressCfm; - -/******************************************************************************* - - NAME - CsrWifiSmePacketFilterSetCfm - - DESCRIPTION - The SME calls the primitive to report the result of the set primitive. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmePacketFilterSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmePermanentMacAddressGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - permanentMacAddress - MAC address stored in the EEPROM - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiMacAddress permanentMacAddress; -} CsrWifiSmePermanentMacAddressGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmePmkidCandidateListInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it when a new network supporting preauthentication and/or PMK - caching is seen. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an - interface - pmkidCandidatesCount - Number of PMKID candidates provided - pmkidCandidates - Points to the first PMKID candidate - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u8 pmkidCandidatesCount; - CsrWifiSmePmkidCandidate *pmkidCandidates; -} CsrWifiSmePmkidCandidateListInd; - -/******************************************************************************* - - NAME - CsrWifiSmePmkidCfm - - DESCRIPTION - The SME will call this primitive when the operation is complete. For a - GET action, this primitive reports the current list of PMKIDs - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - action - Action in the request - getPmkidsCount - This parameter is only relevant if action is - CSR_WIFI_SME_LIST_ACTION_GET: - number of PMKIDs sent with the primitive - getPmkids - Pointer to the list of PMKIDs sent with the primitive, set - to NULL if none is sent. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeListAction action; - u8 getPmkidsCount; - CsrWifiSmePmkid *getPmkids; -} CsrWifiSmePmkidCfm; - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - powerConfig - Returns the current parameters for the power configuration of - the firmware - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmePowerConfig powerConfig; -} CsrWifiSmePowerConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmePowerConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmePowerConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeRegulatoryDomainInfoGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - regDomInfo - Reports information and state related to regulatory domain - operation. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeRegulatoryDomainInfo regDomInfo; -} CsrWifiSmeRegulatoryDomainInfoGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamCompleteInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it completes an attempt to roam to an AP. If the roam - attempt was successful, status will be set to CSR_WIFI_SME_SUCCESS, - otherwise it shall be set to the appropriate error code. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the roaming procedure - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeRoamCompleteInd; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamStartInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive it whenever it begins an attempt to roam to an AP. - If the wireless manager application connect request specified the SSID - and the BSSID was set to the broadcast address (0xFF 0xFF 0xFF 0xFF 0xFF - 0xFF), the SME monitors the signal quality and maintains a list of - candidates to roam to. When the signal quality of the current connection - falls below a threshold, and there is a candidate with better quality, - the SME will attempt to the candidate AP. - If the roaming procedure succeeds, the SME will also issue a Media - Connect indication to inform the wireless manager application of the - change. - NOTE: to prevent the SME from initiating roaming the WMA must specify the - BSSID in the connection request; this forces the SME to connect only to - that AP. - The wireless manager application can obtain statistics for roaming - purposes using CSR_WIFI_SME_CONNECTION_QUALITY_IND and - CSR_WIFI_SME_CONNECTION_STATS_GET_REQ. - When the wireless manager application wishes to roam to another AP, it - must issue a connection request specifying the BSSID of the desired AP. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - roamReason - Indicates the reason for starting the roaming procedure - reason80211 - Indicates the reason for deauthentication or disassociation - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeRoamReason roamReason; - CsrWifiSmeIEEE80211Reason reason80211; -} CsrWifiSmeRoamStartInd; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - roamingConfig - Reports the roaming behaviour of the driver and firmware - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeRoamingConfig roamingConfig; -} CsrWifiSmeRoamingConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeRoamingConfigSetCfm - - DESCRIPTION - This primitive sets the value of the RoamingConfig parameter. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeRoamingConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - scanConfig - Returns the current parameters for the autonomous scanning - behaviour of the firmware - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeScanConfig scanConfig; -} CsrWifiSmeScanConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeScanConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeScanConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeScanFullCfm - - DESCRIPTION - The SME calls this primitive when the results from the scan are - available. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeScanFullCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultInd - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it whenever a scan indication is received from the firmware. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - result - Points to a buffer containing a scan result. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeScanResult result; -} CsrWifiSmeScanResultInd; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsFlushCfm - - DESCRIPTION - The SME will call this primitive when the cache has been cleared. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeScanResultsFlushCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeScanResultsGetCfm - - DESCRIPTION - The SME sends this primitive to provide the current set of scan results. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - scanResultsCount - Number of scan results - scanResults - Points to a buffer containing an array of - CsrWifiSmeScanResult structures. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u16 scanResultsCount; - CsrWifiSmeScanResult *scanResults; -} CsrWifiSmeScanResultsGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - smeConfig - Current SME Station Parameters - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - CsrWifiSmeStaConfig smeConfig; -} CsrWifiSmeSmeStaConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeStaConfigSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; -} CsrWifiSmeSmeStaConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeStationMacAddressGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - stationMacAddress - Current MAC address of the station. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiMacAddress stationMacAddress[2]; -} CsrWifiSmeStationMacAddressGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeTspecInd - - DESCRIPTION - The SME will send this primitive to all the task that have registered to - receive it when a status change in the TSPEC occurs. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - tspecResultCode - Specifies the TSPEC operation requested by the peer - station - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - u32 transactionId; - CsrWifiSmeTspecResultCode tspecResultCode; - u16 tspecLength; - u8 *tspec; -} CsrWifiSmeTspecInd; - -/******************************************************************************* - - NAME - CsrWifiSmeTspecCfm - - DESCRIPTION - The SME calls the primitive to report the result of the TSpec primitive - request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface Identifier; unique identifier of an interface - status - Reports the result of the request - transactionId - Unique Transaction ID for the TSPEC, as assigned by the - driver - tspecResultCode - Specifies the result of the negotiated TSPEC operation - tspecLength - Length of the TSPEC. - tspec - Points to the first byte of the TSPEC - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrResult status; - u32 transactionId; - CsrWifiSmeTspecResultCode tspecResultCode; - u16 tspecLength; - u8 *tspec; -} CsrWifiSmeTspecCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeVersionsGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - versions - Version IDs of the product - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeVersions versions; -} CsrWifiSmeVersionsGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiFlightmodeCfm - - DESCRIPTION - The SME calls this primitive when the chip is initialised for low power - mode and with the radio subsystem disabled. To leave flight mode, and - enable Wi-Fi, the wireless manager application should call - CSR_WIFI_SME_WIFI_ON_REQ. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeWifiFlightmodeCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffInd - - DESCRIPTION - The SME sends this primitive to all the tasks that have registered to - receive it to report that the chip has been turned off. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - reason - Indicates the reason why the Wi-Fi has been switched off. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiSmeControlIndication reason; -} CsrWifiSmeWifiOffInd; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOffCfm - - DESCRIPTION - After receiving CSR_WIFI_SME_WIFI_OFF_REQ, if the chip is connected to a - network, the SME will perform a disconnect operation, will send a - CSR_WIFI_SME_MEDIA_STATUS_IND with - CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED, and then will call - CSR_WIFI_SME_WIFI_OFF_CFM when the chip is off. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeWifiOffCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnCfm - - DESCRIPTION - The SME sends this primitive to the task that has sent the request once - the chip has been initialised and is available for use. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeWifiOnCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsSetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeCloakedSsidsSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeCloakedSsidsGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - cloakedSsids - Reports list of cloaked SSIDs that are explicitly scanned for - by the driver - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeCloakedSsidConfig cloakedSsids; -} CsrWifiSmeCloakedSsidsGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeWifiOnInd - - DESCRIPTION - The SME sends this primitive to all tasks that have registered to receive - it once the chip becomes available and ready to use. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - address - Current MAC address - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrWifiMacAddress address; -} CsrWifiSmeWifiOnInd; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - deviceConfig - Configuration options in the SME - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - CsrWifiSmeDeviceConfig deviceConfig; -} CsrWifiSmeSmeCommonConfigGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeSmeCommonConfigSetCfm - - DESCRIPTION - Reports the result of the request - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Reports the result of the request - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeSmeCommonConfigSetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeInterfaceCapabilityGetCfm - - DESCRIPTION - This primitive reports the result of the request. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Result of the request - numInterfaces - Number of the interfaces supported - capBitmap - Points to the list of capabilities bitmaps provided for each - interface. - The bits represent the following capabilities: - -bits 7 to 4-Reserved - -bit 3-AMP - -bit 2-P2P - -bit 1-AP - -bit 0-STA - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; - u16 numInterfaces; - u8 capBitmap[2]; -} CsrWifiSmeInterfaceCapabilityGetCfm; - -/******************************************************************************* - - NAME - CsrWifiSmeErrorInd - - DESCRIPTION - Important error message indicating a error of some importance - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - errorMessage - Contains the error message. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - char *errorMessage; -} CsrWifiSmeErrorInd; - -/******************************************************************************* - - NAME - CsrWifiSmeInfoInd - - DESCRIPTION - Message indicating a some info about current activity. Mostly of interest - in testing but may be useful in the field. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - infoMessage - Contains the message. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - char *infoMessage; -} CsrWifiSmeInfoInd; - -/******************************************************************************* - - NAME - CsrWifiSmeCoreDumpInd - - DESCRIPTION - The SME will send this primitive to all the tasks that have registered to - receive Wi-Fi Chip core dump data. - The core dump data may be fragmented and sent using more than one - indication. - To indicate that all the data has been sent, the last indication contains - a 'length' of 0 and 'data' of NULL. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - dataLength - Number of bytes in the buffer pointed to by 'data' - data - Pointer to the buffer containing 'dataLength' bytes of core - dump data - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u32 dataLength; - u8 *data; -} CsrWifiSmeCoreDumpInd; - -/******************************************************************************* - - NAME - CsrWifiSmeAmpStatusChangeInd - - DESCRIPTION - Indication of change to AMP activity. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - interfaceTag - Interface on which the AMP activity changed. - ampStatus - The new status of AMP activity.Range: {AMP_ACTIVE, - AMP_INACTIVE}. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - u16 interfaceTag; - CsrWifiSmeAmpStatus ampStatus; -} CsrWifiSmeAmpStatusChangeInd; - -/******************************************************************************* - - NAME - CsrWifiSmeWpsConfigurationCfm - - DESCRIPTION - Confirm. - - MEMBERS - common - Common header for use with the CsrWifiFsm Module - status - Status of the request. - -*******************************************************************************/ -typedef struct -{ - CsrWifiFsmEvent common; - CsrResult status; -} CsrWifiSmeWpsConfigurationCfm; - -#endif /* CSR_WIFI_SME_PRIM_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_sme_sef.c b/drivers/staging/csr/csr_wifi_sme_sef.c deleted file mode 100644 index cf32254335c4..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_sef.c +++ /dev/null @@ -1,85 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - - *****************************************************************************/ -#include "csr_wifi_sme_sef.h" - -const CsrWifiSmeStateHandlerType CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT] = -{ - /* 0x8000 */ CsrWifiSmeActivateCfmHandler, - /* 0x8001 */ CsrWifiSmeAdhocConfigGetCfmHandler, - /* 0x8002 */ CsrWifiSmeAdhocConfigSetCfmHandler, - /* 0x8003 */ CsrWifiSmeAssociationCompleteIndHandler, - /* 0x8004 */ CsrWifiSmeAssociationStartIndHandler, - /* 0x8005 */ CsrWifiSmeBlacklistCfmHandler, - /* 0x8006 */ CsrWifiSmeCalibrationDataGetCfmHandler, - /* 0x8007 */ CsrWifiSmeCalibrationDataSetCfmHandler, - /* 0x8008 */ CsrWifiSmeCcxConfigGetCfmHandler, - /* 0x8009 */ CsrWifiSmeCcxConfigSetCfmHandler, - /* 0x800A */ CsrWifiSmeCoexConfigGetCfmHandler, - /* 0x800B */ CsrWifiSmeCoexConfigSetCfmHandler, - /* 0x800C */ CsrWifiSmeCoexInfoGetCfmHandler, - /* 0x800D */ CsrWifiSmeConnectCfmHandler, - /* 0x800E */ CsrWifiSmeConnectionConfigGetCfmHandler, - /* 0x800F */ CsrWifiSmeConnectionInfoGetCfmHandler, - /* 0x8010 */ CsrWifiSmeConnectionQualityIndHandler, - /* 0x8011 */ CsrWifiSmeConnectionStatsGetCfmHandler, - /* 0x8012 */ CsrWifiSmeDeactivateCfmHandler, - /* 0x8013 */ CsrWifiSmeDisconnectCfmHandler, - /* 0x8014 */ CsrWifiSmeEventMaskSetCfmHandler, - /* 0x8015 */ CsrWifiSmeHostConfigGetCfmHandler, - /* 0x8016 */ CsrWifiSmeHostConfigSetCfmHandler, - /* 0x8017 */ CsrWifiSmeIbssStationIndHandler, - /* 0x8018 */ CsrWifiSmeKeyCfmHandler, - /* 0x8019 */ CsrWifiSmeLinkQualityGetCfmHandler, - /* 0x801A */ CsrWifiSmeMediaStatusIndHandler, - /* 0x801B */ CsrWifiSmeMibConfigGetCfmHandler, - /* 0x801C */ CsrWifiSmeMibConfigSetCfmHandler, - /* 0x801D */ CsrWifiSmeMibGetCfmHandler, - /* 0x801E */ CsrWifiSmeMibGetNextCfmHandler, - /* 0x801F */ CsrWifiSmeMibSetCfmHandler, - /* 0x8020 */ CsrWifiSmeMicFailureIndHandler, - /* 0x8021 */ CsrWifiSmeMulticastAddressCfmHandler, - /* 0x8022 */ CsrWifiSmePacketFilterSetCfmHandler, - /* 0x8023 */ CsrWifiSmePermanentMacAddressGetCfmHandler, - /* 0x8024 */ CsrWifiSmePmkidCandidateListIndHandler, - /* 0x8025 */ CsrWifiSmePmkidCfmHandler, - /* 0x8026 */ CsrWifiSmePowerConfigGetCfmHandler, - /* 0x8027 */ CsrWifiSmePowerConfigSetCfmHandler, - /* 0x8028 */ CsrWifiSmeRegulatoryDomainInfoGetCfmHandler, - /* 0x8029 */ CsrWifiSmeRoamCompleteIndHandler, - /* 0x802A */ CsrWifiSmeRoamStartIndHandler, - /* 0x802B */ CsrWifiSmeRoamingConfigGetCfmHandler, - /* 0x802C */ CsrWifiSmeRoamingConfigSetCfmHandler, - /* 0x802D */ CsrWifiSmeScanConfigGetCfmHandler, - /* 0x802E */ CsrWifiSmeScanConfigSetCfmHandler, - /* 0x802F */ CsrWifiSmeScanFullCfmHandler, - /* 0x8030 */ CsrWifiSmeScanResultIndHandler, - /* 0x8031 */ CsrWifiSmeScanResultsFlushCfmHandler, - /* 0x8032 */ CsrWifiSmeScanResultsGetCfmHandler, - /* 0x8033 */ CsrWifiSmeSmeStaConfigGetCfmHandler, - /* 0x8034 */ CsrWifiSmeSmeStaConfigSetCfmHandler, - /* 0x8035 */ CsrWifiSmeStationMacAddressGetCfmHandler, - /* 0x8036 */ CsrWifiSmeTspecIndHandler, - /* 0x8037 */ CsrWifiSmeTspecCfmHandler, - /* 0x8038 */ CsrWifiSmeVersionsGetCfmHandler, - /* 0x8039 */ CsrWifiSmeWifiFlightmodeCfmHandler, - /* 0x803A */ CsrWifiSmeWifiOffIndHandler, - /* 0x803B */ CsrWifiSmeWifiOffCfmHandler, - /* 0x803C */ CsrWifiSmeWifiOnCfmHandler, - /* 0x803D */ CsrWifiSmeCloakedSsidsSetCfmHandler, - /* 0x803E */ CsrWifiSmeCloakedSsidsGetCfmHandler, - /* 0x803F */ CsrWifiSmeWifiOnIndHandler, - /* 0x8040 */ CsrWifiSmeSmeCommonConfigGetCfmHandler, - /* 0x8041 */ CsrWifiSmeSmeCommonConfigSetCfmHandler, - /* 0x8042 */ CsrWifiSmeGetInterfaceCapabilityCfmHandler, - /* 0x8043 */ CsrWifiSmeErrorIndHandler, - /* 0x8044 */ CsrWifiSmeInfoIndHandler, - /* 0x8045 */ CsrWifiSmeCoreDumpIndHandler, - /* 0x8046 */ CsrWifiSmeAmpStatusChangeIndHandler, -}; diff --git a/drivers/staging/csr/csr_wifi_sme_sef.h b/drivers/staging/csr/csr_wifi_sme_sef.h deleted file mode 100644 index 78b88c067236..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_sef.h +++ /dev/null @@ -1,142 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2010 - Confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ -#ifndef CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ -#define CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ - -#include "csr_wifi_sme_prim.h" - -typedef void (*CsrWifiSmeStateHandlerType)(void *drvpriv, CsrWifiFsmEvent *msg); - -extern const CsrWifiSmeStateHandlerType - CsrWifiSmeUpstreamStateHandlers[CSR_WIFI_SME_PRIM_UPSTREAM_COUNT]; - - -extern void CsrWifiSmeActivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeAdhocConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeAdhocConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeAssociationCompleteIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeAssociationStartIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeBlacklistCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCalibrationDataGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCalibrationDataSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCcxConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCcxConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCoexConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCoexConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCoexInfoGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeConnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeConnectionConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeConnectionInfoGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeConnectionQualityIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeConnectionStatsGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeDeactivateCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeDisconnectCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeEventMaskSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeHostConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeHostConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeIbssStationIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeKeyCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeLinkQualityGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMediaStatusIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMibConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMibConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMibGetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMibGetNextCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMibSetCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMicFailureIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeMulticastAddressCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmePacketFilterSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmePermanentMacAddressGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmePmkidCandidateListIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmePmkidCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmePowerConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmePowerConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeRoamCompleteIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeRoamStartIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeRoamingConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeRoamingConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanFullCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanResultIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanResultsFlushCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeScanResultsGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeSmeStaConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeSmeStaConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeStationMacAddressGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeTspecIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeTspecCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeVersionsGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeWifiFlightmodeCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeWifiOffIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeWifiOffCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeWifiOnCfmHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCloakedSsidsSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCloakedSsidsGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeWifiOnIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeSmeCommonConfigGetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeSmeCommonConfigSetCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void *drvpriv, - CsrWifiFsmEvent *msg); -extern void CsrWifiSmeErrorIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeInfoIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeCoreDumpIndHandler(void *drvpriv, CsrWifiFsmEvent *msg); -extern void CsrWifiSmeAmpStatusChangeIndHandler(void *drvpriv, - CsrWifiFsmEvent *msg); - -#endif /* CSR_WIFI_ROUTER_SEF_CSR_WIFI_SME_H__ */ diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.c b/drivers/staging/csr/csr_wifi_sme_serialize.c deleted file mode 100644 index 7d7e1d8b5ed3..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_serialize.c +++ /dev/null @@ -1,5809 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ -#include -#include -#include "csr_msgconv.h" -#include "csr_wifi_sme_prim.h" -#include "csr_wifi_sme_serialize.h" - -void CsrWifiSmePfree(void *ptr) -{ - kfree(ptr); -} - - -size_t CsrWifiSmeAdhocConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->adHocConfig.atimWindowTu */ - bufferSize += 2; /* u16 primitive->adHocConfig.beaconPeriodTu */ - bufferSize += 2; /* u16 primitive->adHocConfig.joinOnlyAttempts */ - bufferSize += 2; /* u16 primitive->adHocConfig.joinAttemptIntervalMs */ - return bufferSize; -} - - -u8* CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeAdhocConfigSetReq *primitive = (CsrWifiSmeAdhocConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.atimWindowTu); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.beaconPeriodTu); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.joinOnlyAttempts); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.joinAttemptIntervalMs); - return(ptr); -} - - -void* CsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeAdhocConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeAdhocConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.atimWindowTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.beaconPeriodTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.joinOnlyAttempts, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.joinAttemptIntervalMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeBlacklistReqSizeof(void *msg) -{ - CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->setAddressCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressCount; i1++) - { - bufferSize += 6; /* u8 primitive->setAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->setAddressCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiSmeBlacklistReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeBlacklistReq *primitive = kmalloc(sizeof(CsrWifiSmeBlacklistReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->setAddressCount, buffer, &offset); - primitive->setAddresses = NULL; - if (primitive->setAddressCount) - { - primitive->setAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->setAddressCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressCount; i1++) - { - CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiSmeBlacklistReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeBlacklistReq *primitive = (CsrWifiSmeBlacklistReq *) voidPrimitivePointer; - kfree(primitive->setAddresses); - kfree(primitive); -} - - -size_t CsrWifiSmeCalibrationDataSetReqSizeof(void *msg) -{ - CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ - bufferSize += 2; /* u16 primitive->calibrationDataLength */ - bufferSize += primitive->calibrationDataLength; /* u8 primitive->calibrationData */ - return bufferSize; -} - - -u8* CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->calibrationDataLength); - if (primitive->calibrationDataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->calibrationData, ((u16) (primitive->calibrationDataLength))); - } - return(ptr); -} - - -void* CsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCalibrationDataSetReq *primitive = kmalloc(sizeof(CsrWifiSmeCalibrationDataSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->calibrationDataLength, buffer, &offset); - if (primitive->calibrationDataLength) - { - primitive->calibrationData = kmalloc(primitive->calibrationDataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->calibrationData, buffer, &offset, ((u16) (primitive->calibrationDataLength))); - } - else - { - primitive->calibrationData = NULL; - } - - return primitive; -} - - -void CsrWifiSmeCalibrationDataSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeCalibrationDataSetReq *primitive = (CsrWifiSmeCalibrationDataSetReq *) voidPrimitivePointer; - kfree(primitive->calibrationData); - kfree(primitive); -} - - -size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->ccxConfig.keepAliveTimeMs */ - bufferSize += 1; /* u8 primitive->ccxConfig.apRoamingEnabled */ - bufferSize += 1; /* u8 primitive->ccxConfig.measurementsMask */ - bufferSize += 1; /* u8 primitive->ccxConfig.ccxRadioMgtEnabled */ - return bufferSize; -} - - -u8* CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCcxConfigSetReq *primitive = (CsrWifiSmeCcxConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.keepAliveTimeMs); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.apRoamingEnabled); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.measurementsMask); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.ccxRadioMgtEnabled); - return(ptr); -} - - -void* CsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCcxConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeCcxConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.keepAliveTimeMs, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.apRoamingEnabled, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.measurementsMask, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.ccxRadioMgtEnabled, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 29) */ - bufferSize += 1; /* u8 primitive->coexConfig.coexEnableSchemeManagement */ - bufferSize += 1; /* u8 primitive->coexConfig.coexPeriodicWakeHost */ - bufferSize += 2; /* u16 primitive->coexConfig.coexTrafficBurstyLatencyMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexTrafficContinuousLatencyMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexObexBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexObexBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpBrBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpBrBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpEdrBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexPagingBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexPagingBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexInquiryBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexInquiryBlackoutPeriodMs */ - return bufferSize; -} - - -u8* CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCoexConfigSetReq *primitive = (CsrWifiSmeCoexConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->coexConfig.coexEnableSchemeManagement); - CsrUint8Ser(ptr, len, (u8) primitive->coexConfig.coexPeriodicWakeHost); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexTrafficBurstyLatencyMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexTrafficContinuousLatencyMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexObexBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexObexBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpBrBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpBrBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpEdrBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexPagingBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexPagingBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexInquiryBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexInquiryBlackoutPeriodMs); - return(ptr); -} - - -void* CsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCoexConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeCoexConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexConfig.coexEnableSchemeManagement, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexConfig.coexPeriodicWakeHost, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexTrafficBurstyLatencyMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexTrafficContinuousLatencyMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexObexBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexObexBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpBrBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpBrBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpEdrBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexPagingBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexPagingBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexInquiryBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexInquiryBlackoutPeriodMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeConnectReqSizeof(void *msg) -{ - CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 57) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 32; /* u8 primitive->connectionConfig.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->connectionConfig.ssid.length */ - bufferSize += 6; /* u8 primitive->connectionConfig.bssid.a[6] */ - bufferSize += 1; /* CsrWifiSmeBssType primitive->connectionConfig.bssType */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionConfig.ifIndex */ - bufferSize += 1; /* CsrWifiSme80211PrivacyMode primitive->connectionConfig.privacyMode */ - bufferSize += 2; /* CsrWifiSmeAuthModeMask primitive->connectionConfig.authModeMask */ - bufferSize += 2; /* CsrWifiSmeEncryptionMask primitive->connectionConfig.encryptionModeMask */ - bufferSize += 2; /* u16 primitive->connectionConfig.mlmeAssociateReqInformationElementsLength */ - bufferSize += primitive->connectionConfig.mlmeAssociateReqInformationElementsLength; /* u8 primitive->connectionConfig.mlmeAssociateReqInformationElements */ - bufferSize += 1; /* CsrWifiSmeWmmQosInfoMask primitive->connectionConfig.wmmQosInfo */ - bufferSize += 1; /* u8 primitive->connectionConfig.adhocJoinOnly */ - bufferSize += 1; /* u8 primitive->connectionConfig.adhocChannel */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.bssType); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.ifIndex); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.privacyMode); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.authModeMask); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.encryptionModeMask); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); - if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.mlmeAssociateReqInformationElements, ((u16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); - } - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.wmmQosInfo); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.adhocJoinOnly); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.adhocChannel); - return(ptr); -} - - -void* CsrWifiSmeConnectReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectReq *primitive = kmalloc(sizeof(CsrWifiSmeConnectReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->connectionConfig.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->connectionConfig.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->connectionConfig.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->connectionConfig.bssType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.ifIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.privacyMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.authModeMask, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.encryptionModeMask, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, buffer, &offset); - if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) - { - primitive->connectionConfig.mlmeAssociateReqInformationElements = kmalloc(primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionConfig.mlmeAssociateReqInformationElements, buffer, &offset, ((u16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); - } - else - { - primitive->connectionConfig.mlmeAssociateReqInformationElements = NULL; - } - CsrUint8Des((u8 *) &primitive->connectionConfig.wmmQosInfo, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.adhocJoinOnly, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.adhocChannel, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeConnectReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeConnectReq *primitive = (CsrWifiSmeConnectReq *) voidPrimitivePointer; - kfree(primitive->connectionConfig.mlmeAssociateReqInformationElements); - kfree(primitive); -} - - -size_t CsrWifiSmeHostConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeHostPowerMode primitive->hostConfig.powerMode */ - bufferSize += 2; /* u16 primitive->hostConfig.applicationDataPeriodMs */ - return bufferSize; -} - - -u8* CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeHostConfigSetReq *primitive = (CsrWifiSmeHostConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->hostConfig.powerMode); - CsrUint16Ser(ptr, len, (u16) primitive->hostConfig.applicationDataPeriodMs); - return(ptr); -} - - -void* CsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeHostConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeHostConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->hostConfig.powerMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->hostConfig.applicationDataPeriodMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeKeyReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 65) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* CsrWifiSmeKeyType primitive->key.keyType */ - bufferSize += 1; /* u8 primitive->key.keyIndex */ - bufferSize += 1; /* u8 primitive->key.wepTxKey */ - { - u16 i2; - for (i2 = 0; i2 < 8; i2++) - { - bufferSize += 2; /* u16 primitive->key.keyRsc[8] */ - } - } - bufferSize += 1; /* u8 primitive->key.authenticator */ - bufferSize += 6; /* u8 primitive->key.address.a[6] */ - bufferSize += 1; /* u8 primitive->key.keyLength */ - bufferSize += 32; /* u8 primitive->key.key[32] */ - return bufferSize; -} - - -u8* CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeKeyReq *primitive = (CsrWifiSmeKeyReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->key.keyType); - CsrUint8Ser(ptr, len, (u8) primitive->key.keyIndex); - CsrUint8Ser(ptr, len, (u8) primitive->key.wepTxKey); - { - u16 i2; - for (i2 = 0; i2 < 8; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->key.keyRsc[i2]); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->key.authenticator); - CsrMemCpySer(ptr, len, (const void *) primitive->key.address.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->key.keyLength); - CsrMemCpySer(ptr, len, (const void *) primitive->key.key, ((u16) (32))); - return(ptr); -} - - -void* CsrWifiSmeKeyReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeKeyReq *primitive = kmalloc(sizeof(CsrWifiSmeKeyReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->key.keyType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->key.keyIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->key.wepTxKey, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 8; i2++) - { - CsrUint16Des((u16 *) &primitive->key.keyRsc[i2], buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->key.authenticator, buffer, &offset); - CsrMemCpyDes(primitive->key.address.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->key.keyLength, buffer, &offset); - CsrMemCpyDes(primitive->key.key, buffer, &offset, ((u16) (32))); - - return primitive; -} - - -size_t CsrWifiSmeMibConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 1; /* u8 primitive->mibConfig.unifiFixMaxTxDataRate */ - bufferSize += 1; /* u8 primitive->mibConfig.unifiFixTxDataRate */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11RtsThreshold */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11FragmentationThreshold */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11CurrentTxPowerLevel */ - return bufferSize; -} - - -u8* CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibConfigSetReq *primitive = (CsrWifiSmeMibConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->mibConfig.unifiFixMaxTxDataRate); - CsrUint8Ser(ptr, len, (u8) primitive->mibConfig.unifiFixTxDataRate); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11RtsThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11FragmentationThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11CurrentTxPowerLevel); - return(ptr); -} - - -void* CsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeMibConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mibConfig.unifiFixMaxTxDataRate, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mibConfig.unifiFixTxDataRate, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11RtsThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11FragmentationThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11CurrentTxPowerLevel, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeMibGetNextReqSizeof(void *msg) -{ - CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ - bufferSize += 2; /* u16 primitive->mibAttributeLength */ - bufferSize += primitive->mibAttributeLength; /* u8 primitive->mibAttribute */ - return bufferSize; -} - - -u8* CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->mibAttributeLength); - if (primitive->mibAttributeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((u16) (primitive->mibAttributeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibGetNextReq *primitive = kmalloc(sizeof(CsrWifiSmeMibGetNextReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibAttributeLength, buffer, &offset); - if (primitive->mibAttributeLength) - { - primitive->mibAttribute = kmalloc(primitive->mibAttributeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((u16) (primitive->mibAttributeLength))); - } - else - { - primitive->mibAttribute = NULL; - } - - return primitive; -} - - -void CsrWifiSmeMibGetNextReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMibGetNextReq *primitive = (CsrWifiSmeMibGetNextReq *) voidPrimitivePointer; - kfree(primitive->mibAttribute); - kfree(primitive); -} - - -size_t CsrWifiSmeMibGetReqSizeof(void *msg) -{ - CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ - bufferSize += 2; /* u16 primitive->mibAttributeLength */ - bufferSize += primitive->mibAttributeLength; /* u8 primitive->mibAttribute */ - return bufferSize; -} - - -u8* CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->mibAttributeLength); - if (primitive->mibAttributeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((u16) (primitive->mibAttributeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeMibGetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibGetReq *primitive = kmalloc(sizeof(CsrWifiSmeMibGetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibAttributeLength, buffer, &offset); - if (primitive->mibAttributeLength) - { - primitive->mibAttribute = kmalloc(primitive->mibAttributeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((u16) (primitive->mibAttributeLength))); - } - else - { - primitive->mibAttribute = NULL; - } - - return primitive; -} - - -void CsrWifiSmeMibGetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMibGetReq *primitive = (CsrWifiSmeMibGetReq *) voidPrimitivePointer; - kfree(primitive->mibAttribute); - kfree(primitive); -} - - -size_t CsrWifiSmeMibSetReqSizeof(void *msg) -{ - CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 6) */ - bufferSize += 2; /* u16 primitive->mibAttributeLength */ - bufferSize += primitive->mibAttributeLength; /* u8 primitive->mibAttribute */ - return bufferSize; -} - - -u8* CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->mibAttributeLength); - if (primitive->mibAttributeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((u16) (primitive->mibAttributeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeMibSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibSetReq *primitive = kmalloc(sizeof(CsrWifiSmeMibSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibAttributeLength, buffer, &offset); - if (primitive->mibAttributeLength) - { - primitive->mibAttribute = kmalloc(primitive->mibAttributeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((u16) (primitive->mibAttributeLength))); - } - else - { - primitive->mibAttribute = NULL; - } - - return primitive; -} - - -void CsrWifiSmeMibSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMibSetReq *primitive = (CsrWifiSmeMibSetReq *) voidPrimitivePointer; - kfree(primitive->mibAttribute); - kfree(primitive); -} - - -size_t CsrWifiSmeMulticastAddressReqSizeof(void *msg) -{ - CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->setAddressesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - bufferSize += 6; /* u8 primitive->setAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->setAddressesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->setAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMulticastAddressReq *primitive = kmalloc(sizeof(CsrWifiSmeMulticastAddressReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->setAddressesCount, buffer, &offset); - primitive->setAddresses = NULL; - if (primitive->setAddressesCount) - { - primitive->setAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->setAddressesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->setAddressesCount; i1++) - { - CsrMemCpyDes(primitive->setAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiSmeMulticastAddressReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMulticastAddressReq *primitive = (CsrWifiSmeMulticastAddressReq *) voidPrimitivePointer; - kfree(primitive->setAddresses); - kfree(primitive); -} - - -size_t CsrWifiSmePacketFilterSetReqSizeof(void *msg) -{ - CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* u16 primitive->filterLength */ - bufferSize += primitive->filterLength; /* u8 primitive->filter */ - bufferSize += 1; /* CsrWifiSmePacketFilterMode primitive->mode */ - bufferSize += 4; /* u8 primitive->arpFilterAddress.a[4] */ - return bufferSize; -} - - -u8* CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->filterLength); - if (primitive->filterLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->filter, ((u16) (primitive->filterLength))); - } - CsrUint8Ser(ptr, len, (u8) primitive->mode); - CsrMemCpySer(ptr, len, (const void *) primitive->arpFilterAddress.a, ((u16) (4))); - return(ptr); -} - - -void* CsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmePacketFilterSetReq *primitive = kmalloc(sizeof(CsrWifiSmePacketFilterSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->filterLength, buffer, &offset); - if (primitive->filterLength) - { - primitive->filter = kmalloc(primitive->filterLength, GFP_KERNEL); - CsrMemCpyDes(primitive->filter, buffer, &offset, ((u16) (primitive->filterLength))); - } - else - { - primitive->filter = NULL; - } - CsrUint8Des((u8 *) &primitive->mode, buffer, &offset); - CsrMemCpyDes(primitive->arpFilterAddress.a, buffer, &offset, ((u16) (4))); - - return primitive; -} - - -void CsrWifiSmePacketFilterSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmePacketFilterSetReq *primitive = (CsrWifiSmePacketFilterSetReq *) voidPrimitivePointer; - kfree(primitive->filter); - kfree(primitive); -} - - -size_t CsrWifiSmePmkidReqSizeof(void *msg) -{ - CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 29) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->setPmkidsCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) - { - bufferSize += 6; /* u8 primitive->setPmkids[i1].bssid.a[6] */ - bufferSize += 16; /* u8 primitive->setPmkids[i1].pmkid[16] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->setPmkidsCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->setPmkids[i1].bssid.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->setPmkids[i1].pmkid, ((u16) (16))); - } - } - return(ptr); -} - - -void* CsrWifiSmePmkidReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmePmkidReq *primitive = kmalloc(sizeof(CsrWifiSmePmkidReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->setPmkidsCount, buffer, &offset); - primitive->setPmkids = NULL; - if (primitive->setPmkidsCount) - { - primitive->setPmkids = kmalloc(sizeof(CsrWifiSmePmkid) * primitive->setPmkidsCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->setPmkidsCount; i1++) - { - CsrMemCpyDes(primitive->setPmkids[i1].bssid.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->setPmkids[i1].pmkid, buffer, &offset, ((u16) (16))); - } - } - - return primitive; -} - - -void CsrWifiSmePmkidReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmePmkidReq *primitive = (CsrWifiSmePmkidReq *) voidPrimitivePointer; - kfree(primitive->setPmkids); - kfree(primitive); -} - - -size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->powerConfig.powerSaveLevel */ - bufferSize += 2; /* u16 primitive->powerConfig.listenIntervalTu */ - bufferSize += 1; /* u8 primitive->powerConfig.rxDtims */ - bufferSize += 1; /* CsrWifiSmeD3AutoScanMode primitive->powerConfig.d3AutoScanMode */ - bufferSize += 1; /* u8 primitive->powerConfig.clientTrafficWindow */ - bufferSize += 1; /* u8 primitive->powerConfig.opportunisticPowerSave */ - bufferSize += 1; /* u8 primitive->powerConfig.noticeOfAbsence */ - return bufferSize; -} - - -u8* CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePowerConfigSetReq *primitive = (CsrWifiSmePowerConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.powerSaveLevel); - CsrUint16Ser(ptr, len, (u16) primitive->powerConfig.listenIntervalTu); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.rxDtims); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.d3AutoScanMode); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.clientTrafficWindow); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.opportunisticPowerSave); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.noticeOfAbsence); - return(ptr); -} - - -void* CsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmePowerConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmePowerConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.powerSaveLevel, buffer, &offset); - CsrUint16Des((u16 *) &primitive->powerConfig.listenIntervalTu, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.rxDtims, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.d3AutoScanMode, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.clientTrafficWindow, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.opportunisticPowerSave, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.noticeOfAbsence, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 70) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].rssiHighThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].rssiLowThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].snrHighThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].snrLowThreshold */ - } - } - bufferSize += 1; /* u8 primitive->roamingConfig.disableSmoothRoaming */ - bufferSize += 1; /* u8 primitive->roamingConfig.disableRoamScans */ - bufferSize += 1; /* u8 primitive->roamingConfig.reconnectLimit */ - bufferSize += 2; /* u16 primitive->roamingConfig.reconnectLimitIntervalMs */ - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].intervalSeconds */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].validitySeconds */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRoamingConfigSetReq *primitive = (CsrWifiSmeRoamingConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].rssiHighThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].rssiLowThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].snrHighThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].snrLowThreshold); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.disableSmoothRoaming); - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.disableRoamScans); - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.reconnectLimit); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.reconnectLimitIntervalMs); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].intervalSeconds); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].validitySeconds); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu); - } - } - return(ptr); -} - - -void* CsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRoamingConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeRoamingConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].rssiHighThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].rssiLowThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].snrHighThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].snrLowThreshold, buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->roamingConfig.disableSmoothRoaming, buffer, &offset); - CsrUint8Des((u8 *) &primitive->roamingConfig.disableRoamScans, buffer, &offset); - CsrUint8Des((u8 *) &primitive->roamingConfig.reconnectLimit, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.reconnectLimitIntervalMs, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].intervalSeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].validitySeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); - } - } - - return primitive; -} - - -size_t CsrWifiSmeScanConfigSetReqSizeof(void *msg) -{ - CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 63) */ - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].intervalSeconds */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].validitySeconds */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu */ - } - } - bufferSize += 1; /* u8 primitive->scanConfig.disableAutonomousScans */ - bufferSize += 2; /* u16 primitive->scanConfig.maxResults */ - bufferSize += 1; /* s8 primitive->scanConfig.highRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.lowRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.deltaRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.highSnrThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.lowSnrThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.deltaSnrThreshold */ - bufferSize += 2; /* u16 primitive->scanConfig.passiveChannelListCount */ - bufferSize += primitive->scanConfig.passiveChannelListCount; /* u8 primitive->scanConfig.passiveChannelList */ - return bufferSize; -} - - -u8* CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].intervalSeconds); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].validitySeconds); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.disableAutonomousScans); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.maxResults); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.highRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.lowRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.deltaRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.highSnrThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.lowSnrThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.deltaSnrThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.passiveChannelListCount); - if (primitive->scanConfig.passiveChannelListCount) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanConfig.passiveChannelList, ((u16) (primitive->scanConfig.passiveChannelListCount))); - } - return(ptr); -} - - -void* CsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeScanConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeScanConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].intervalSeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].validitySeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->scanConfig.disableAutonomousScans, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.maxResults, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.highRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.lowRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.deltaRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.highSnrThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.lowSnrThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.deltaSnrThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.passiveChannelListCount, buffer, &offset); - if (primitive->scanConfig.passiveChannelListCount) - { - primitive->scanConfig.passiveChannelList = kmalloc(primitive->scanConfig.passiveChannelListCount, GFP_KERNEL); - CsrMemCpyDes(primitive->scanConfig.passiveChannelList, buffer, &offset, ((u16) (primitive->scanConfig.passiveChannelListCount))); - } - else - { - primitive->scanConfig.passiveChannelList = NULL; - } - - return primitive; -} - - -void CsrWifiSmeScanConfigSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeScanConfigSetReq *primitive = (CsrWifiSmeScanConfigSetReq *) voidPrimitivePointer; - kfree(primitive->scanConfig.passiveChannelList); - kfree(primitive); -} - - -size_t CsrWifiSmeScanFullReqSizeof(void *msg) -{ - CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 52) */ - bufferSize += 1; /* u8 primitive->ssidCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->ssidCount; i1++) - { - bufferSize += 32; /* u8 primitive->ssid[i1].ssid[32] */ - bufferSize += 1; /* u8 primitive->ssid[i1].length */ - } - } - bufferSize += 6; /* u8 primitive->bssid.a[6] */ - bufferSize += 1; /* u8 primitive->forceScan */ - bufferSize += 1; /* CsrWifiSmeBssType primitive->bssType */ - bufferSize += 1; /* CsrWifiSmeScanType primitive->scanType */ - bufferSize += 2; /* u16 primitive->channelListCount */ - bufferSize += primitive->channelListCount; /* u8 primitive->channelList */ - bufferSize += 2; /* u16 primitive->probeIeLength */ - bufferSize += primitive->probeIeLength; /* u8 primitive->probeIe */ - return bufferSize; -} - - -u8* CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->ssidCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->ssidCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->ssid[i1].ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->ssid[i1].length); - } - } - CsrMemCpySer(ptr, len, (const void *) primitive->bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->forceScan); - CsrUint8Ser(ptr, len, (u8) primitive->bssType); - CsrUint8Ser(ptr, len, (u8) primitive->scanType); - CsrUint16Ser(ptr, len, (u16) primitive->channelListCount); - if (primitive->channelListCount) - { - CsrMemCpySer(ptr, len, (const void *) primitive->channelList, ((u16) (primitive->channelListCount))); - } - CsrUint16Ser(ptr, len, (u16) primitive->probeIeLength); - if (primitive->probeIeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->probeIe, ((u16) (primitive->probeIeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeScanFullReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeScanFullReq *primitive = kmalloc(sizeof(CsrWifiSmeScanFullReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ssidCount, buffer, &offset); - primitive->ssid = NULL; - if (primitive->ssidCount) - { - primitive->ssid = kmalloc(sizeof(CsrWifiSsid) * primitive->ssidCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->ssidCount; i1++) - { - CsrMemCpyDes(primitive->ssid[i1].ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->ssid[i1].length, buffer, &offset); - } - } - CsrMemCpyDes(primitive->bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->forceScan, buffer, &offset); - CsrUint8Des((u8 *) &primitive->bssType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->channelListCount, buffer, &offset); - if (primitive->channelListCount) - { - primitive->channelList = kmalloc(primitive->channelListCount, GFP_KERNEL); - CsrMemCpyDes(primitive->channelList, buffer, &offset, ((u16) (primitive->channelListCount))); - } - else - { - primitive->channelList = NULL; - } - CsrUint16Des((u16 *) &primitive->probeIeLength, buffer, &offset); - if (primitive->probeIeLength) - { - primitive->probeIe = kmalloc(primitive->probeIeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->probeIe, buffer, &offset, ((u16) (primitive->probeIeLength))); - } - else - { - primitive->probeIe = NULL; - } - - return primitive; -} - - -void CsrWifiSmeScanFullReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeScanFullReq *primitive = (CsrWifiSmeScanFullReq *) voidPrimitivePointer; - kfree(primitive->ssid); - kfree(primitive->channelList); - kfree(primitive->probeIe); - kfree(primitive); -} - - -size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ - bufferSize += 1; /* u8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ - bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ - bufferSize += 1; /* u8 primitive->smeConfig.allowUnicastUseGroupCipher */ - bufferSize += 1; /* u8 primitive->smeConfig.enableOpportunisticKeyCaching */ - return bufferSize; -} - - -u8* CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSmeStaConfigSetReq *primitive = (CsrWifiSmeSmeStaConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.connectionQualityRssiChangeTrigger); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.connectionQualitySnrChangeTrigger); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.wmmModeMask); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.ifIndex); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.allowUnicastUseGroupCipher); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.enableOpportunisticKeyCaching); - return(ptr); -} - - -void* CsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSmeStaConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeSmeStaConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.connectionQualityRssiChangeTrigger, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.connectionQualitySnrChangeTrigger, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.wmmModeMask, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.ifIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.allowUnicastUseGroupCipher, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.enableOpportunisticKeyCaching, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeTspecReqSizeof(void *msg) -{ - CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 18) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 4; /* u32 primitive->transactionId */ - bufferSize += 1; /* u8 primitive->strict */ - bufferSize += 1; /* CsrWifiSmeTspecCtrlMask primitive->ctrlMask */ - bufferSize += 2; /* u16 primitive->tspecLength */ - bufferSize += primitive->tspecLength; /* u8 primitive->tspec */ - bufferSize += 2; /* u16 primitive->tclasLength */ - bufferSize += primitive->tclasLength; /* u8 primitive->tclas */ - return bufferSize; -} - - -u8* CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint32Ser(ptr, len, (u32) primitive->transactionId); - CsrUint8Ser(ptr, len, (u8) primitive->strict); - CsrUint8Ser(ptr, len, (u8) primitive->ctrlMask); - CsrUint16Ser(ptr, len, (u16) primitive->tspecLength); - if (primitive->tspecLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((u16) (primitive->tspecLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->tclasLength); - if (primitive->tclasLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tclas, ((u16) (primitive->tclasLength))); - } - return(ptr); -} - - -void* CsrWifiSmeTspecReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeTspecReq *primitive = kmalloc(sizeof(CsrWifiSmeTspecReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint32Des((u32 *) &primitive->transactionId, buffer, &offset); - CsrUint8Des((u8 *) &primitive->strict, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ctrlMask, buffer, &offset); - CsrUint16Des((u16 *) &primitive->tspecLength, buffer, &offset); - if (primitive->tspecLength) - { - primitive->tspec = kmalloc(primitive->tspecLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tspec, buffer, &offset, ((u16) (primitive->tspecLength))); - } - else - { - primitive->tspec = NULL; - } - CsrUint16Des((u16 *) &primitive->tclasLength, buffer, &offset); - if (primitive->tclasLength) - { - primitive->tclas = kmalloc(primitive->tclasLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tclas, buffer, &offset, ((u16) (primitive->tclasLength))); - } - else - { - primitive->tclas = NULL; - } - - return primitive; -} - - -void CsrWifiSmeTspecReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeTspecReq *primitive = (CsrWifiSmeTspecReq *) voidPrimitivePointer; - kfree(primitive->tspec); - kfree(primitive->tclas); - kfree(primitive); -} - - -size_t CsrWifiSmeWifiFlightmodeReqSizeof(void *msg) -{ - CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - bufferSize += 2; /* u16 primitive->mibFilesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - bufferSize += 2; /* u16 primitive->mibFiles[i1].length */ - bufferSize += primitive->mibFiles[i1].length; /* u8 primitive->mibFiles[i1].data */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->mibFilesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - CsrUint16Ser(ptr, len, (u16) primitive->mibFiles[i1].length); - if (primitive->mibFiles[i1].length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibFiles[i1].data, ((u16) (primitive->mibFiles[i1].length))); - } - } - } - return(ptr); -} - - -void* CsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeWifiFlightmodeReq *primitive = kmalloc(sizeof(CsrWifiSmeWifiFlightmodeReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->mibFilesCount, buffer, &offset); - primitive->mibFiles = NULL; - if (primitive->mibFilesCount) - { - primitive->mibFiles = kmalloc(sizeof(CsrWifiSmeDataBlock) * primitive->mibFilesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - CsrUint16Des((u16 *) &primitive->mibFiles[i1].length, buffer, &offset); - if (primitive->mibFiles[i1].length) - { - primitive->mibFiles[i1].data = kmalloc(primitive->mibFiles[i1].length, GFP_KERNEL); - CsrMemCpyDes(primitive->mibFiles[i1].data, buffer, &offset, ((u16) (primitive->mibFiles[i1].length))); - } - else - { - primitive->mibFiles[i1].data = NULL; - } - } - } - - return primitive; -} - - -void CsrWifiSmeWifiFlightmodeReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeWifiFlightmodeReq *primitive = (CsrWifiSmeWifiFlightmodeReq *) voidPrimitivePointer; - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - kfree(primitive->mibFiles[i1].data); - } - } - kfree(primitive->mibFiles); - kfree(primitive); -} - - -size_t CsrWifiSmeWifiOnReqSizeof(void *msg) -{ - CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 14) */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - bufferSize += 2; /* u16 primitive->mibFilesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - bufferSize += 2; /* u16 primitive->mibFiles[i1].length */ - bufferSize += primitive->mibFiles[i1].length; /* u8 primitive->mibFiles[i1].data */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->mibFilesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - CsrUint16Ser(ptr, len, (u16) primitive->mibFiles[i1].length); - if (primitive->mibFiles[i1].length) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibFiles[i1].data, ((u16) (primitive->mibFiles[i1].length))); - } - } - } - return(ptr); -} - - -void* CsrWifiSmeWifiOnReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeWifiOnReq *primitive = kmalloc(sizeof(CsrWifiSmeWifiOnReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->mibFilesCount, buffer, &offset); - primitive->mibFiles = NULL; - if (primitive->mibFilesCount) - { - primitive->mibFiles = kmalloc(sizeof(CsrWifiSmeDataBlock) * primitive->mibFilesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - CsrUint16Des((u16 *) &primitive->mibFiles[i1].length, buffer, &offset); - if (primitive->mibFiles[i1].length) - { - primitive->mibFiles[i1].data = kmalloc(primitive->mibFiles[i1].length, GFP_KERNEL); - CsrMemCpyDes(primitive->mibFiles[i1].data, buffer, &offset, ((u16) (primitive->mibFiles[i1].length))); - } - else - { - primitive->mibFiles[i1].data = NULL; - } - } - } - - return primitive; -} - - -void CsrWifiSmeWifiOnReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeWifiOnReq *primitive = (CsrWifiSmeWifiOnReq *) voidPrimitivePointer; - { - u16 i1; - for (i1 = 0; i1 < primitive->mibFilesCount; i1++) - { - kfree(primitive->mibFiles[i1].data); - } - } - kfree(primitive->mibFiles); - kfree(primitive); -} - - -size_t CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg) -{ - CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 37) */ - bufferSize += 1; /* u8 primitive->cloakedSsids.cloakedSsidsCount */ - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - bufferSize += 32; /* u8 primitive->cloakedSsids.cloakedSsids[i2].ssid[32] */ - bufferSize += 1; /* u8 primitive->cloakedSsids.cloakedSsids[i2].length */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->cloakedSsids.cloakedSsidsCount); - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->cloakedSsids.cloakedSsids[i2].ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->cloakedSsids.cloakedSsids[i2].length); - } - } - return(ptr); -} - - -void* CsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCloakedSsidsSetReq *primitive = kmalloc(sizeof(CsrWifiSmeCloakedSsidsSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->cloakedSsids.cloakedSsidsCount, buffer, &offset); - primitive->cloakedSsids.cloakedSsids = NULL; - if (primitive->cloakedSsids.cloakedSsidsCount) - { - primitive->cloakedSsids.cloakedSsids = kmalloc(sizeof(CsrWifiSsid) * primitive->cloakedSsids.cloakedSsidsCount, GFP_KERNEL); - } - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - CsrMemCpyDes(primitive->cloakedSsids.cloakedSsids[i2].ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->cloakedSsids.cloakedSsids[i2].length, buffer, &offset); - } - } - - return primitive; -} - - -void CsrWifiSmeCloakedSsidsSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeCloakedSsidsSetReq *primitive = (CsrWifiSmeCloakedSsidsSetReq *) voidPrimitivePointer; - kfree(primitive->cloakedSsids.cloakedSsids); - kfree(primitive); -} - - -size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 1; /* CsrWifiSme80211dTrustLevel primitive->deviceConfig.trustLevel */ - bufferSize += 2; /* u8 primitive->deviceConfig.countryCode[2] */ - bufferSize += 1; /* CsrWifiSmeFirmwareDriverInterface primitive->deviceConfig.firmwareDriverInterface */ - bufferSize += 1; /* u8 primitive->deviceConfig.enableStrictDraftN */ - return bufferSize; -} - - -u8* CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSmeCommonConfigSetReq *primitive = (CsrWifiSmeSmeCommonConfigSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.trustLevel); - CsrMemCpySer(ptr, len, (const void *) primitive->deviceConfig.countryCode, ((u16) (2))); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.firmwareDriverInterface); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.enableStrictDraftN); - return(ptr); -} - - -void* CsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSmeCommonConfigSetReq *primitive = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->deviceConfig.trustLevel, buffer, &offset); - CsrMemCpyDes(primitive->deviceConfig.countryCode, buffer, &offset, ((u16) (2))); - CsrUint8Des((u8 *) &primitive->deviceConfig.firmwareDriverInterface, buffer, &offset); - CsrUint8Des((u8 *) &primitive->deviceConfig.enableStrictDraftN, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeWpsConfigurationReqSizeof(void *msg) -{ - CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 240) */ - bufferSize += 1; /* u8 primitive->wpsConfig.wpsVersion */ - bufferSize += 16; /* u8 primitive->wpsConfig.uuid[16] */ - bufferSize += 32; /* u8 primitive->wpsConfig.deviceName[32] */ - bufferSize += 1; /* u8 primitive->wpsConfig.deviceNameLength */ - bufferSize += 64; /* u8 primitive->wpsConfig.manufacturer[64] */ - bufferSize += 1; /* u8 primitive->wpsConfig.manufacturerLength */ - bufferSize += 32; /* u8 primitive->wpsConfig.modelName[32] */ - bufferSize += 1; /* u8 primitive->wpsConfig.modelNameLength */ - bufferSize += 32; /* u8 primitive->wpsConfig.modelNumber[32] */ - bufferSize += 1; /* u8 primitive->wpsConfig.modelNumberLength */ - bufferSize += 32; /* u8 primitive->wpsConfig.serialNumber[32] */ - bufferSize += 8; /* u8 primitive->wpsConfig.primDeviceType.deviceDetails[8] */ - bufferSize += 1; /* u8 primitive->wpsConfig.secondaryDeviceTypeCount */ - { - u16 i2; - for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) - { - bufferSize += 8; /* u8 primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails[8] */ - } - } - bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->wpsConfig.configMethods */ - bufferSize += 1; /* u8 primitive->wpsConfig.rfBands */ - bufferSize += 4; /* u8 primitive->wpsConfig.osVersion[4] */ - return bufferSize; -} - - -u8* CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.wpsVersion); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.uuid, ((u16) (16))); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.deviceName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.deviceNameLength); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.manufacturer, ((u16) (64))); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.manufacturerLength); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.modelName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.modelNameLength); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.modelNumber, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.modelNumberLength); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.serialNumber, ((u16) (32))); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.primDeviceType.deviceDetails, ((u16) (8))); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.secondaryDeviceTypeCount); - { - u16 i2; - for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails, ((u16) (8))); - } - } - CsrUint16Ser(ptr, len, (u16) primitive->wpsConfig.configMethods); - CsrUint8Ser(ptr, len, (u8) primitive->wpsConfig.rfBands); - CsrMemCpySer(ptr, len, (const void *) primitive->wpsConfig.osVersion, ((u16) (4))); - return(ptr); -} - - -void* CsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeWpsConfigurationReq *primitive = kmalloc(sizeof(CsrWifiSmeWpsConfigurationReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wpsConfig.wpsVersion, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.uuid, buffer, &offset, ((u16) (16))); - CsrMemCpyDes(primitive->wpsConfig.deviceName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->wpsConfig.deviceNameLength, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.manufacturer, buffer, &offset, ((u16) (64))); - CsrUint8Des((u8 *) &primitive->wpsConfig.manufacturerLength, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.modelName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->wpsConfig.modelNameLength, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.modelNumber, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->wpsConfig.modelNumberLength, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.serialNumber, buffer, &offset, ((u16) (32))); - CsrMemCpyDes(primitive->wpsConfig.primDeviceType.deviceDetails, buffer, &offset, ((u16) (8))); - CsrUint8Des((u8 *) &primitive->wpsConfig.secondaryDeviceTypeCount, buffer, &offset); - primitive->wpsConfig.secondaryDeviceType = NULL; - if (primitive->wpsConfig.secondaryDeviceTypeCount) - { - primitive->wpsConfig.secondaryDeviceType = kmalloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->wpsConfig.secondaryDeviceTypeCount, GFP_KERNEL); - } - { - u16 i2; - for (i2 = 0; i2 < primitive->wpsConfig.secondaryDeviceTypeCount; i2++) - { - CsrMemCpyDes(primitive->wpsConfig.secondaryDeviceType[i2].deviceDetails, buffer, &offset, ((u16) (8))); - } - } - CsrUint16Des((u16 *) &primitive->wpsConfig.configMethods, buffer, &offset); - CsrUint8Des((u8 *) &primitive->wpsConfig.rfBands, buffer, &offset); - CsrMemCpyDes(primitive->wpsConfig.osVersion, buffer, &offset, ((u16) (4))); - - return primitive; -} - - -void CsrWifiSmeWpsConfigurationReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeWpsConfigurationReq *primitive = (CsrWifiSmeWpsConfigurationReq *) voidPrimitivePointer; - kfree(primitive->wpsConfig.secondaryDeviceType); - kfree(primitive); -} - - -size_t CsrWifiSmeSetReqSizeof(void *msg) -{ - CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 4; /* u32 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint32Ser(ptr, len, (u32) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiSmeSetReqDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSetReq *primitive = kmalloc(sizeof(CsrWifiSmeSetReq), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint32Des((u32 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiSmeSetReqSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) voidPrimitivePointer; - kfree(primitive->data); - kfree(primitive); -} - - -size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->adHocConfig.atimWindowTu */ - bufferSize += 2; /* u16 primitive->adHocConfig.beaconPeriodTu */ - bufferSize += 2; /* u16 primitive->adHocConfig.joinOnlyAttempts */ - bufferSize += 2; /* u16 primitive->adHocConfig.joinAttemptIntervalMs */ - return bufferSize; -} - - -u8* CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeAdhocConfigGetCfm *primitive = (CsrWifiSmeAdhocConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.atimWindowTu); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.beaconPeriodTu); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.joinOnlyAttempts); - CsrUint16Ser(ptr, len, (u16) primitive->adHocConfig.joinAttemptIntervalMs); - return(ptr); -} - - -void* CsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeAdhocConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeAdhocConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.atimWindowTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.beaconPeriodTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.joinOnlyAttempts, buffer, &offset); - CsrUint16Des((u16 *) &primitive->adHocConfig.joinAttemptIntervalMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeAssociationCompleteIndSizeof(void *msg) -{ - CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 98) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 32; /* u8 primitive->connectionInfo.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->connectionInfo.ssid.length */ - bufferSize += 6; /* u8 primitive->connectionInfo.bssid.a[6] */ - bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ - bufferSize += 1; /* u8 primitive->connectionInfo.channelNumber */ - bufferSize += 2; /* u16 primitive->connectionInfo.channelFrequency */ - bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ - bufferSize += 2; /* u16 primitive->connectionInfo.atimWindowTu */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconPeriodTu */ - bufferSize += 1; /* u8 primitive->connectionInfo.reassociation */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconFrameLength */ - bufferSize += primitive->connectionInfo.beaconFrameLength; /* u8 primitive->connectionInfo.beaconFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationReqFrameLength */ - bufferSize += primitive->connectionInfo.associationReqFrameLength; /* u8 primitive->connectionInfo.associationReqFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationRspFrameLength */ - bufferSize += primitive->connectionInfo.associationRspFrameLength; /* u8 primitive->connectionInfo.associationRspFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocScanInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* u8 primitive->connectionInfo.assocScanInfoElements */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqCapabilities */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqListenIntervalTu */ - bufferSize += 6; /* u8 primitive->connectionInfo.assocReqApAddress.a[6] */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* u8 primitive->connectionInfo.assocReqInfoElements */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspCapabilityInfo */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspAssociationId */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* u8 primitive->connectionInfo.assocRspInfoElements */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->deauthReason */ - return bufferSize; -} - - -u8* CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.networkType80211); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.channelNumber); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.channelFrequency); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.authMode); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.pairwiseCipher); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.groupCipher); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ifIndex); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.atimWindowTu); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconPeriodTu); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.reassociation); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconFrameLength); - if (primitive->connectionInfo.beaconFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationReqFrameLength); - if (primitive->connectionInfo.associationReqFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationRspFrameLength); - if (primitive->connectionInfo.associationRspFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocScanInfoElementsLength); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqCapabilities); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqListenIntervalTu); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqInfoElementsLength); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspResult); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspCapabilityInfo); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspAssociationId); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspInfoElementsLength); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->deauthReason); - return(ptr); -} - - -void* CsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeAssociationCompleteInd *primitive = kmalloc(sizeof(CsrWifiSmeAssociationCompleteInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.authMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.reassociation, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); - if (primitive->connectionInfo.beaconFrameLength) - { - primitive->connectionInfo.beaconFrame = kmalloc(primitive->connectionInfo.beaconFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - else - { - primitive->connectionInfo.beaconFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationReqFrameLength) - { - primitive->connectionInfo.associationReqFrame = kmalloc(primitive->connectionInfo.associationReqFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - else - { - primitive->connectionInfo.associationReqFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationRspFrameLength) - { - primitive->connectionInfo.associationRspFrame = kmalloc(primitive->connectionInfo.associationRspFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - else - { - primitive->connectionInfo.associationRspFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - primitive->connectionInfo.assocScanInfoElements = kmalloc(primitive->connectionInfo.assocScanInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocScanInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - primitive->connectionInfo.assocReqInfoElements = kmalloc(primitive->connectionInfo.assocReqInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocReqInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - primitive->connectionInfo.assocRspInfoElements = kmalloc(primitive->connectionInfo.assocRspInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocRspInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->deauthReason, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeAssociationCompleteIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeAssociationCompleteInd *primitive = (CsrWifiSmeAssociationCompleteInd *) voidPrimitivePointer; - kfree(primitive->connectionInfo.beaconFrame); - kfree(primitive->connectionInfo.associationReqFrame); - kfree(primitive->connectionInfo.associationRspFrame); - kfree(primitive->connectionInfo.assocScanInfoElements); - kfree(primitive->connectionInfo.assocReqInfoElements); - kfree(primitive->connectionInfo.assocRspInfoElements); - kfree(primitive); -} - - -size_t CsrWifiSmeAssociationStartIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 44) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - bufferSize += 32; /* u8 primitive->ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->ssid.length */ - return bufferSize; -} - - -u8* CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeAssociationStartInd *primitive = (CsrWifiSmeAssociationStartInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->ssid.length); - return(ptr); -} - - -void* CsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeAssociationStartInd *primitive = kmalloc(sizeof(CsrWifiSmeAssociationStartInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->ssid.length, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeBlacklistCfmSizeof(void *msg) -{ - CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->getAddressCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressCount; i1++) - { - bufferSize += 6; /* u8 primitive->getAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->getAddressCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeBlacklistCfm *primitive = kmalloc(sizeof(CsrWifiSmeBlacklistCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->getAddressCount, buffer, &offset); - primitive->getAddresses = NULL; - if (primitive->getAddressCount) - { - primitive->getAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->getAddressCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressCount; i1++) - { - CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiSmeBlacklistCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeBlacklistCfm *primitive = (CsrWifiSmeBlacklistCfm *) voidPrimitivePointer; - kfree(primitive->getAddresses); - kfree(primitive); -} - - -size_t CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg) -{ - CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->calibrationDataLength */ - bufferSize += primitive->calibrationDataLength; /* u8 primitive->calibrationData */ - return bufferSize; -} - - -u8* CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->calibrationDataLength); - if (primitive->calibrationDataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->calibrationData, ((u16) (primitive->calibrationDataLength))); - } - return(ptr); -} - - -void* CsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCalibrationDataGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCalibrationDataGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->calibrationDataLength, buffer, &offset); - if (primitive->calibrationDataLength) - { - primitive->calibrationData = kmalloc(primitive->calibrationDataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->calibrationData, buffer, &offset, ((u16) (primitive->calibrationDataLength))); - } - else - { - primitive->calibrationData = NULL; - } - - return primitive; -} - - -void CsrWifiSmeCalibrationDataGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeCalibrationDataGetCfm *primitive = (CsrWifiSmeCalibrationDataGetCfm *) voidPrimitivePointer; - kfree(primitive->calibrationData); - kfree(primitive); -} - - -size_t CsrWifiSmeCcxConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->ccxConfig.keepAliveTimeMs */ - bufferSize += 1; /* u8 primitive->ccxConfig.apRoamingEnabled */ - bufferSize += 1; /* u8 primitive->ccxConfig.measurementsMask */ - bufferSize += 1; /* u8 primitive->ccxConfig.ccxRadioMgtEnabled */ - return bufferSize; -} - - -u8* CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCcxConfigGetCfm *primitive = (CsrWifiSmeCcxConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.keepAliveTimeMs); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.apRoamingEnabled); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.measurementsMask); - CsrUint8Ser(ptr, len, (u8) primitive->ccxConfig.ccxRadioMgtEnabled); - return(ptr); -} - - -void* CsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCcxConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCcxConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.keepAliveTimeMs, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.apRoamingEnabled, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.measurementsMask, buffer, &offset); - CsrUint8Des((u8 *) &primitive->ccxConfig.ccxRadioMgtEnabled, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeCcxConfigSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCcxConfigSetCfm *primitive = (CsrWifiSmeCcxConfigSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCcxConfigSetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCcxConfigSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 31) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->coexConfig.coexEnableSchemeManagement */ - bufferSize += 1; /* u8 primitive->coexConfig.coexPeriodicWakeHost */ - bufferSize += 2; /* u16 primitive->coexConfig.coexTrafficBurstyLatencyMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexTrafficContinuousLatencyMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexObexBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexObexBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpBrBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpBrBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpEdrBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexPagingBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexPagingBlackoutPeriodMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexInquiryBlackoutDurationMs */ - bufferSize += 2; /* u16 primitive->coexConfig.coexInquiryBlackoutPeriodMs */ - return bufferSize; -} - - -u8* CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCoexConfigGetCfm *primitive = (CsrWifiSmeCoexConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->coexConfig.coexEnableSchemeManagement); - CsrUint8Ser(ptr, len, (u8) primitive->coexConfig.coexPeriodicWakeHost); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexTrafficBurstyLatencyMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexTrafficContinuousLatencyMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexObexBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexObexBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpBrBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpBrBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpEdrBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexPagingBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexPagingBlackoutPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexInquiryBlackoutDurationMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexConfig.coexInquiryBlackoutPeriodMs); - return(ptr); -} - - -void* CsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCoexConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCoexConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexConfig.coexEnableSchemeManagement, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexConfig.coexPeriodicWakeHost, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexTrafficBurstyLatencyMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexTrafficContinuousLatencyMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexObexBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexObexBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpBrBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpBrBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpEdrBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexA2dpEdrBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexPagingBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexPagingBlackoutPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexInquiryBlackoutDurationMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexConfig.coexInquiryBlackoutPeriodMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeCoexInfoGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 24) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->coexInfo.hasTrafficData */ - bufferSize += 1; /* CsrWifiSmeTrafficType primitive->coexInfo.currentTrafficType */ - bufferSize += 2; /* u16 primitive->coexInfo.currentPeriodMs */ - bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->coexInfo.currentPowerSave */ - bufferSize += 2; /* u16 primitive->coexInfo.currentCoexPeriodMs */ - bufferSize += 2; /* u16 primitive->coexInfo.currentCoexLatencyMs */ - bufferSize += 1; /* u8 primitive->coexInfo.hasBtDevice */ - bufferSize += 4; /* u32 primitive->coexInfo.currentBlackoutDurationUs */ - bufferSize += 4; /* u32 primitive->coexInfo.currentBlackoutPeriodUs */ - bufferSize += 1; /* CsrWifiSmeCoexScheme primitive->coexInfo.currentCoexScheme */ - return bufferSize; -} - - -u8* CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCoexInfoGetCfm *primitive = (CsrWifiSmeCoexInfoGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->coexInfo.hasTrafficData); - CsrUint8Ser(ptr, len, (u8) primitive->coexInfo.currentTrafficType); - CsrUint16Ser(ptr, len, (u16) primitive->coexInfo.currentPeriodMs); - CsrUint8Ser(ptr, len, (u8) primitive->coexInfo.currentPowerSave); - CsrUint16Ser(ptr, len, (u16) primitive->coexInfo.currentCoexPeriodMs); - CsrUint16Ser(ptr, len, (u16) primitive->coexInfo.currentCoexLatencyMs); - CsrUint8Ser(ptr, len, (u8) primitive->coexInfo.hasBtDevice); - CsrUint32Ser(ptr, len, (u32) primitive->coexInfo.currentBlackoutDurationUs); - CsrUint32Ser(ptr, len, (u32) primitive->coexInfo.currentBlackoutPeriodUs); - CsrUint8Ser(ptr, len, (u8) primitive->coexInfo.currentCoexScheme); - return(ptr); -} - - -void* CsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCoexInfoGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCoexInfoGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexInfo.hasTrafficData, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexInfo.currentTrafficType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexInfo.currentPeriodMs, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexInfo.currentPowerSave, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexInfo.currentCoexPeriodMs, buffer, &offset); - CsrUint16Des((u16 *) &primitive->coexInfo.currentCoexLatencyMs, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexInfo.hasBtDevice, buffer, &offset); - CsrUint32Des((u32 *) &primitive->coexInfo.currentBlackoutDurationUs, buffer, &offset); - CsrUint32Des((u32 *) &primitive->coexInfo.currentBlackoutPeriodUs, buffer, &offset); - CsrUint8Des((u8 *) &primitive->coexInfo.currentCoexScheme, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeConnectCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectCfm *primitive = (CsrWifiSmeConnectCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeConnectCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectCfm *primitive = kmalloc(sizeof(CsrWifiSmeConnectCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg) -{ - CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 59) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 32; /* u8 primitive->connectionConfig.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->connectionConfig.ssid.length */ - bufferSize += 6; /* u8 primitive->connectionConfig.bssid.a[6] */ - bufferSize += 1; /* CsrWifiSmeBssType primitive->connectionConfig.bssType */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionConfig.ifIndex */ - bufferSize += 1; /* CsrWifiSme80211PrivacyMode primitive->connectionConfig.privacyMode */ - bufferSize += 2; /* CsrWifiSmeAuthModeMask primitive->connectionConfig.authModeMask */ - bufferSize += 2; /* CsrWifiSmeEncryptionMask primitive->connectionConfig.encryptionModeMask */ - bufferSize += 2; /* u16 primitive->connectionConfig.mlmeAssociateReqInformationElementsLength */ - bufferSize += primitive->connectionConfig.mlmeAssociateReqInformationElementsLength; /* u8 primitive->connectionConfig.mlmeAssociateReqInformationElements */ - bufferSize += 1; /* CsrWifiSmeWmmQosInfoMask primitive->connectionConfig.wmmQosInfo */ - bufferSize += 1; /* u8 primitive->connectionConfig.adhocJoinOnly */ - bufferSize += 1; /* u8 primitive->connectionConfig.adhocChannel */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.bssType); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.ifIndex); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.privacyMode); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.authModeMask); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.encryptionModeMask); - CsrUint16Ser(ptr, len, (u16) primitive->connectionConfig.mlmeAssociateReqInformationElementsLength); - if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionConfig.mlmeAssociateReqInformationElements, ((u16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); - } - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.wmmQosInfo); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.adhocJoinOnly); - CsrUint8Ser(ptr, len, (u8) primitive->connectionConfig.adhocChannel); - return(ptr); -} - - -void* CsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectionConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeConnectionConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->connectionConfig.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->connectionConfig.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->connectionConfig.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->connectionConfig.bssType, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.ifIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.privacyMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.authModeMask, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.encryptionModeMask, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, buffer, &offset); - if (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength) - { - primitive->connectionConfig.mlmeAssociateReqInformationElements = kmalloc(primitive->connectionConfig.mlmeAssociateReqInformationElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionConfig.mlmeAssociateReqInformationElements, buffer, &offset, ((u16) (primitive->connectionConfig.mlmeAssociateReqInformationElementsLength))); - } - else - { - primitive->connectionConfig.mlmeAssociateReqInformationElements = NULL; - } - CsrUint8Des((u8 *) &primitive->connectionConfig.wmmQosInfo, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.adhocJoinOnly, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionConfig.adhocChannel, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeConnectionConfigGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeConnectionConfigGetCfm *primitive = (CsrWifiSmeConnectionConfigGetCfm *) voidPrimitivePointer; - kfree(primitive->connectionConfig.mlmeAssociateReqInformationElements); - kfree(primitive); -} - - -size_t CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg) -{ - CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 96) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 32; /* u8 primitive->connectionInfo.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->connectionInfo.ssid.length */ - bufferSize += 6; /* u8 primitive->connectionInfo.bssid.a[6] */ - bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ - bufferSize += 1; /* u8 primitive->connectionInfo.channelNumber */ - bufferSize += 2; /* u16 primitive->connectionInfo.channelFrequency */ - bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ - bufferSize += 2; /* u16 primitive->connectionInfo.atimWindowTu */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconPeriodTu */ - bufferSize += 1; /* u8 primitive->connectionInfo.reassociation */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconFrameLength */ - bufferSize += primitive->connectionInfo.beaconFrameLength; /* u8 primitive->connectionInfo.beaconFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationReqFrameLength */ - bufferSize += primitive->connectionInfo.associationReqFrameLength; /* u8 primitive->connectionInfo.associationReqFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationRspFrameLength */ - bufferSize += primitive->connectionInfo.associationRspFrameLength; /* u8 primitive->connectionInfo.associationRspFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocScanInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* u8 primitive->connectionInfo.assocScanInfoElements */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqCapabilities */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqListenIntervalTu */ - bufferSize += 6; /* u8 primitive->connectionInfo.assocReqApAddress.a[6] */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* u8 primitive->connectionInfo.assocReqInfoElements */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspCapabilityInfo */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspAssociationId */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* u8 primitive->connectionInfo.assocRspInfoElements */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.networkType80211); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.channelNumber); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.channelFrequency); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.authMode); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.pairwiseCipher); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.groupCipher); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ifIndex); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.atimWindowTu); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconPeriodTu); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.reassociation); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconFrameLength); - if (primitive->connectionInfo.beaconFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationReqFrameLength); - if (primitive->connectionInfo.associationReqFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationRspFrameLength); - if (primitive->connectionInfo.associationRspFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocScanInfoElementsLength); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqCapabilities); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqListenIntervalTu); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqInfoElementsLength); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspResult); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspCapabilityInfo); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspAssociationId); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspInfoElementsLength); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - return(ptr); -} - - -void* CsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectionInfoGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeConnectionInfoGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.authMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.reassociation, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); - if (primitive->connectionInfo.beaconFrameLength) - { - primitive->connectionInfo.beaconFrame = kmalloc(primitive->connectionInfo.beaconFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - else - { - primitive->connectionInfo.beaconFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationReqFrameLength) - { - primitive->connectionInfo.associationReqFrame = kmalloc(primitive->connectionInfo.associationReqFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - else - { - primitive->connectionInfo.associationReqFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationRspFrameLength) - { - primitive->connectionInfo.associationRspFrame = kmalloc(primitive->connectionInfo.associationRspFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - else - { - primitive->connectionInfo.associationRspFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - primitive->connectionInfo.assocScanInfoElements = kmalloc(primitive->connectionInfo.assocScanInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocScanInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - primitive->connectionInfo.assocReqInfoElements = kmalloc(primitive->connectionInfo.assocReqInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocReqInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - primitive->connectionInfo.assocRspInfoElements = kmalloc(primitive->connectionInfo.assocRspInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocRspInfoElements = NULL; - } - - return primitive; -} - - -void CsrWifiSmeConnectionInfoGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeConnectionInfoGetCfm *primitive = (CsrWifiSmeConnectionInfoGetCfm *) voidPrimitivePointer; - kfree(primitive->connectionInfo.beaconFrame); - kfree(primitive->connectionInfo.associationReqFrame); - kfree(primitive->connectionInfo.associationRspFrame); - kfree(primitive->connectionInfo.assocScanInfoElements); - kfree(primitive->connectionInfo.assocReqInfoElements); - kfree(primitive->connectionInfo.assocRspInfoElements); - kfree(primitive); -} - - -size_t CsrWifiSmeConnectionQualityIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* s16 primitive->linkQuality.unifiRssi */ - bufferSize += 2; /* s16 primitive->linkQuality.unifiSnr */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectionQualityInd *primitive = (CsrWifiSmeConnectionQualityInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->linkQuality.unifiRssi); - CsrUint16Ser(ptr, len, (u16) primitive->linkQuality.unifiSnr); - return(ptr); -} - - -void* CsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectionQualityInd *primitive = kmalloc(sizeof(CsrWifiSmeConnectionQualityInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->linkQuality.unifiRssi, buffer, &offset); - CsrUint16Des((u16 *) &primitive->linkQuality.unifiSnr, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 101) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->connectionStats.unifiTxDataRate */ - bufferSize += 1; /* u8 primitive->connectionStats.unifiRxDataRate */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RetryCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11MultipleRetryCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11AckFailureCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11FrameDuplicateCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11FcsErrorCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RtsSuccessCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RtsFailureCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11FailedCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11TransmittedFragmentCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11TransmittedFrameCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11WepExcludedCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11WepIcvErrorCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11WepUndecryptableCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11MulticastReceivedFrameCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11MulticastTransmittedFrameCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11ReceivedFragmentCount */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11Rsna4WayHandshakeFailures */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaStatsTkipReplays */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaStatsTkipIcvErrors */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaStatsCcmpReplays */ - bufferSize += 4; /* u32 primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors */ - return bufferSize; -} - - -u8* CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeConnectionStatsGetCfm *primitive = (CsrWifiSmeConnectionStatsGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->connectionStats.unifiTxDataRate); - CsrUint8Ser(ptr, len, (u8) primitive->connectionStats.unifiRxDataRate); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RetryCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11MultipleRetryCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11AckFailureCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11FrameDuplicateCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11FcsErrorCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RtsSuccessCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RtsFailureCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11FailedCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11TransmittedFragmentCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11TransmittedFrameCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11WepExcludedCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11WepIcvErrorCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11WepUndecryptableCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11MulticastReceivedFrameCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11MulticastTransmittedFrameCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11ReceivedFragmentCount); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11Rsna4WayHandshakeFailures); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaStatsTkipReplays); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaStatsTkipIcvErrors); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaStatsCcmpReplays); - CsrUint32Ser(ptr, len, (u32) primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors); - return(ptr); -} - - -void* CsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeConnectionStatsGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeConnectionStatsGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionStats.unifiTxDataRate, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionStats.unifiRxDataRate, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RetryCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11MultipleRetryCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11AckFailureCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11FrameDuplicateCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11FcsErrorCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RtsSuccessCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RtsFailureCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11FailedCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11TransmittedFragmentCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11TransmittedFrameCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11WepExcludedCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11WepIcvErrorCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11WepUndecryptableCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11MulticastReceivedFrameCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11MulticastTransmittedFrameCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11ReceivedFragmentCount, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11Rsna4WayHandshakeFailures, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaTkipCounterMeasuresInvoked, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaStatsTkipLocalMicFailures, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaStatsTkipReplays, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaStatsTkipIcvErrors, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaStatsCcmpReplays, buffer, &offset); - CsrUint32Des((u32 *) &primitive->connectionStats.dot11RsnaStatsCcmpDecryptErrors, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeDisconnectCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeDisconnectCfm *primitive = (CsrWifiSmeDisconnectCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeDisconnectCfm *primitive = kmalloc(sizeof(CsrWifiSmeDisconnectCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeHostConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmeHostPowerMode primitive->hostConfig.powerMode */ - bufferSize += 2; /* u16 primitive->hostConfig.applicationDataPeriodMs */ - return bufferSize; -} - - -u8* CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeHostConfigGetCfm *primitive = (CsrWifiSmeHostConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->hostConfig.powerMode); - CsrUint16Ser(ptr, len, (u16) primitive->hostConfig.applicationDataPeriodMs); - return(ptr); -} - - -void* CsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeHostConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeHostConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->hostConfig.powerMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->hostConfig.applicationDataPeriodMs, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeHostConfigSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeHostConfigSetCfm *primitive = (CsrWifiSmeHostConfigSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeHostConfigSetCfm *primitive = kmalloc(sizeof(CsrWifiSmeHostConfigSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeIbssStationIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - bufferSize += 1; /* u8 primitive->isconnected */ - return bufferSize; -} - - -u8* CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeIbssStationInd *primitive = (CsrWifiSmeIbssStationInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->isconnected); - return(ptr); -} - - -void* CsrWifiSmeIbssStationIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeIbssStationInd *primitive = kmalloc(sizeof(CsrWifiSmeIbssStationInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->isconnected, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeKeyCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* CsrWifiSmeKeyType primitive->keyType */ - bufferSize += 6; /* u8 primitive->peerMacAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeKeyCfm *primitive = (CsrWifiSmeKeyCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->keyType); - CsrMemCpySer(ptr, len, (const void *) primitive->peerMacAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiSmeKeyCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeKeyCfm *primitive = kmalloc(sizeof(CsrWifiSmeKeyCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->keyType, buffer, &offset); - CsrMemCpyDes(primitive->peerMacAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiSmeLinkQualityGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* s16 primitive->linkQuality.unifiRssi */ - bufferSize += 2; /* s16 primitive->linkQuality.unifiSnr */ - return bufferSize; -} - - -u8* CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeLinkQualityGetCfm *primitive = (CsrWifiSmeLinkQualityGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->linkQuality.unifiRssi); - CsrUint16Ser(ptr, len, (u16) primitive->linkQuality.unifiSnr); - return(ptr); -} - - -void* CsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeLinkQualityGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeLinkQualityGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->linkQuality.unifiRssi, buffer, &offset); - CsrUint16Des((u16 *) &primitive->linkQuality.unifiSnr, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeMediaStatusIndSizeof(void *msg) -{ - CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 99) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeMediaStatus primitive->mediaStatus */ - bufferSize += 32; /* u8 primitive->connectionInfo.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->connectionInfo.ssid.length */ - bufferSize += 6; /* u8 primitive->connectionInfo.bssid.a[6] */ - bufferSize += 1; /* CsrWifiSme80211NetworkType primitive->connectionInfo.networkType80211 */ - bufferSize += 1; /* u8 primitive->connectionInfo.channelNumber */ - bufferSize += 2; /* u16 primitive->connectionInfo.channelFrequency */ - bufferSize += 2; /* CsrWifiSmeAuthMode primitive->connectionInfo.authMode */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.pairwiseCipher */ - bufferSize += 2; /* CsrWifiSmeEncryption primitive->connectionInfo.groupCipher */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->connectionInfo.ifIndex */ - bufferSize += 2; /* u16 primitive->connectionInfo.atimWindowTu */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconPeriodTu */ - bufferSize += 1; /* u8 primitive->connectionInfo.reassociation */ - bufferSize += 2; /* u16 primitive->connectionInfo.beaconFrameLength */ - bufferSize += primitive->connectionInfo.beaconFrameLength; /* u8 primitive->connectionInfo.beaconFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationReqFrameLength */ - bufferSize += primitive->connectionInfo.associationReqFrameLength; /* u8 primitive->connectionInfo.associationReqFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.associationRspFrameLength */ - bufferSize += primitive->connectionInfo.associationRspFrameLength; /* u8 primitive->connectionInfo.associationRspFrame */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocScanInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocScanInfoElementsLength; /* u8 primitive->connectionInfo.assocScanInfoElements */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqCapabilities */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqListenIntervalTu */ - bufferSize += 6; /* u8 primitive->connectionInfo.assocReqApAddress.a[6] */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocReqInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocReqInfoElementsLength; /* u8 primitive->connectionInfo.assocReqInfoElements */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Result primitive->connectionInfo.assocRspResult */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspCapabilityInfo */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspAssociationId */ - bufferSize += 2; /* u16 primitive->connectionInfo.assocRspInfoElementsLength */ - bufferSize += primitive->connectionInfo.assocRspInfoElementsLength; /* u8 primitive->connectionInfo.assocRspInfoElements */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->disassocReason */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->deauthReason */ - return bufferSize; -} - - -u8* CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->mediaStatus); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.networkType80211); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.channelNumber); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.channelFrequency); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.authMode); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.pairwiseCipher); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.groupCipher); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.ifIndex); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.atimWindowTu); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconPeriodTu); - CsrUint8Ser(ptr, len, (u8) primitive->connectionInfo.reassociation); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.beaconFrameLength); - if (primitive->connectionInfo.beaconFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.beaconFrame, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationReqFrameLength); - if (primitive->connectionInfo.associationReqFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationReqFrame, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.associationRspFrameLength); - if (primitive->connectionInfo.associationRspFrameLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.associationRspFrame, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocScanInfoElementsLength); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocScanInfoElements, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqCapabilities); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqListenIntervalTu); - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqApAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocReqInfoElementsLength); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocReqInfoElements, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspResult); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspCapabilityInfo); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspAssociationId); - CsrUint16Ser(ptr, len, (u16) primitive->connectionInfo.assocRspInfoElementsLength); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->connectionInfo.assocRspInfoElements, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - CsrUint16Ser(ptr, len, (u16) primitive->disassocReason); - CsrUint16Ser(ptr, len, (u16) primitive->deauthReason); - return(ptr); -} - - -void* CsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMediaStatusInd *primitive = kmalloc(sizeof(CsrWifiSmeMediaStatusInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mediaStatus, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->connectionInfo.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->connectionInfo.networkType80211, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.channelNumber, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.channelFrequency, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.authMode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.pairwiseCipher, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.groupCipher, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.ifIndex, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.atimWindowTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconPeriodTu, buffer, &offset); - CsrUint8Des((u8 *) &primitive->connectionInfo.reassociation, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.beaconFrameLength, buffer, &offset); - if (primitive->connectionInfo.beaconFrameLength) - { - primitive->connectionInfo.beaconFrame = kmalloc(primitive->connectionInfo.beaconFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.beaconFrame, buffer, &offset, ((u16) (primitive->connectionInfo.beaconFrameLength))); - } - else - { - primitive->connectionInfo.beaconFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationReqFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationReqFrameLength) - { - primitive->connectionInfo.associationReqFrame = kmalloc(primitive->connectionInfo.associationReqFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationReqFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationReqFrameLength))); - } - else - { - primitive->connectionInfo.associationReqFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.associationRspFrameLength, buffer, &offset); - if (primitive->connectionInfo.associationRspFrameLength) - { - primitive->connectionInfo.associationRspFrame = kmalloc(primitive->connectionInfo.associationRspFrameLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.associationRspFrame, buffer, &offset, ((u16) (primitive->connectionInfo.associationRspFrameLength))); - } - else - { - primitive->connectionInfo.associationRspFrame = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocScanInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocScanInfoElementsLength) - { - primitive->connectionInfo.assocScanInfoElements = kmalloc(primitive->connectionInfo.assocScanInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocScanInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocScanInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocScanInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqCapabilities, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqListenIntervalTu, buffer, &offset); - CsrMemCpyDes(primitive->connectionInfo.assocReqApAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocReqInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocReqInfoElementsLength) - { - primitive->connectionInfo.assocReqInfoElements = kmalloc(primitive->connectionInfo.assocReqInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocReqInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocReqInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocReqInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspResult, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspCapabilityInfo, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspAssociationId, buffer, &offset); - CsrUint16Des((u16 *) &primitive->connectionInfo.assocRspInfoElementsLength, buffer, &offset); - if (primitive->connectionInfo.assocRspInfoElementsLength) - { - primitive->connectionInfo.assocRspInfoElements = kmalloc(primitive->connectionInfo.assocRspInfoElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->connectionInfo.assocRspInfoElements, buffer, &offset, ((u16) (primitive->connectionInfo.assocRspInfoElementsLength))); - } - else - { - primitive->connectionInfo.assocRspInfoElements = NULL; - } - CsrUint16Des((u16 *) &primitive->disassocReason, buffer, &offset); - CsrUint16Des((u16 *) &primitive->deauthReason, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeMediaStatusIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMediaStatusInd *primitive = (CsrWifiSmeMediaStatusInd *) voidPrimitivePointer; - kfree(primitive->connectionInfo.beaconFrame); - kfree(primitive->connectionInfo.associationReqFrame); - kfree(primitive->connectionInfo.associationRspFrame); - kfree(primitive->connectionInfo.assocScanInfoElements); - kfree(primitive->connectionInfo.assocReqInfoElements); - kfree(primitive->connectionInfo.assocRspInfoElements); - kfree(primitive); -} - - -size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->mibConfig.unifiFixMaxTxDataRate */ - bufferSize += 1; /* u8 primitive->mibConfig.unifiFixTxDataRate */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11RtsThreshold */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11FragmentationThreshold */ - bufferSize += 2; /* u16 primitive->mibConfig.dot11CurrentTxPowerLevel */ - return bufferSize; -} - - -u8* CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibConfigGetCfm *primitive = (CsrWifiSmeMibConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->mibConfig.unifiFixMaxTxDataRate); - CsrUint8Ser(ptr, len, (u8) primitive->mibConfig.unifiFixTxDataRate); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11RtsThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11FragmentationThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->mibConfig.dot11CurrentTxPowerLevel); - return(ptr); -} - - -void* CsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeMibConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mibConfig.unifiFixMaxTxDataRate, buffer, &offset); - CsrUint8Des((u8 *) &primitive->mibConfig.unifiFixTxDataRate, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11RtsThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11FragmentationThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibConfig.dot11CurrentTxPowerLevel, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeMibGetCfmSizeof(void *msg) -{ - CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->mibAttributeLength */ - bufferSize += primitive->mibAttributeLength; /* u8 primitive->mibAttribute */ - return bufferSize; -} - - -u8* CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->mibAttributeLength); - if (primitive->mibAttributeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((u16) (primitive->mibAttributeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeMibGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeMibGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibAttributeLength, buffer, &offset); - if (primitive->mibAttributeLength) - { - primitive->mibAttribute = kmalloc(primitive->mibAttributeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((u16) (primitive->mibAttributeLength))); - } - else - { - primitive->mibAttribute = NULL; - } - - return primitive; -} - - -void CsrWifiSmeMibGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMibGetCfm *primitive = (CsrWifiSmeMibGetCfm *) voidPrimitivePointer; - kfree(primitive->mibAttribute); - kfree(primitive); -} - - -size_t CsrWifiSmeMibGetNextCfmSizeof(void *msg) -{ - CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->mibAttributeLength */ - bufferSize += primitive->mibAttributeLength; /* u8 primitive->mibAttribute */ - return bufferSize; -} - - -u8* CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->mibAttributeLength); - if (primitive->mibAttributeLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->mibAttribute, ((u16) (primitive->mibAttributeLength))); - } - return(ptr); -} - - -void* CsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMibGetNextCfm *primitive = kmalloc(sizeof(CsrWifiSmeMibGetNextCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->mibAttributeLength, buffer, &offset); - if (primitive->mibAttributeLength) - { - primitive->mibAttribute = kmalloc(primitive->mibAttributeLength, GFP_KERNEL); - CsrMemCpyDes(primitive->mibAttribute, buffer, &offset, ((u16) (primitive->mibAttributeLength))); - } - else - { - primitive->mibAttribute = NULL; - } - - return primitive; -} - - -void CsrWifiSmeMibGetNextCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMibGetNextCfm *primitive = (CsrWifiSmeMibGetNextCfm *) voidPrimitivePointer; - kfree(primitive->mibAttribute); - kfree(primitive); -} - - -size_t CsrWifiSmeMicFailureIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->secondFailure */ - bufferSize += 2; /* u16 primitive->count */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - bufferSize += 1; /* CsrWifiSmeKeyType primitive->keyType */ - return bufferSize; -} - - -u8* CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMicFailureInd *primitive = (CsrWifiSmeMicFailureInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->secondFailure); - CsrUint16Ser(ptr, len, (u16) primitive->count); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->keyType); - return(ptr); -} - - -void* CsrWifiSmeMicFailureIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMicFailureInd *primitive = kmalloc(sizeof(CsrWifiSmeMicFailureInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->secondFailure, buffer, &offset); - CsrUint16Des((u16 *) &primitive->count, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->keyType, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeMulticastAddressCfmSizeof(void *msg) -{ - CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->getAddressesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - bufferSize += 6; /* u8 primitive->getAddresses[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->getAddressesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->getAddresses[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeMulticastAddressCfm *primitive = kmalloc(sizeof(CsrWifiSmeMulticastAddressCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->getAddressesCount, buffer, &offset); - primitive->getAddresses = NULL; - if (primitive->getAddressesCount) - { - primitive->getAddresses = kmalloc(sizeof(CsrWifiMacAddress) * primitive->getAddressesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->getAddressesCount; i1++) - { - CsrMemCpyDes(primitive->getAddresses[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -void CsrWifiSmeMulticastAddressCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeMulticastAddressCfm *primitive = (CsrWifiSmeMulticastAddressCfm *) voidPrimitivePointer; - kfree(primitive->getAddresses); - kfree(primitive); -} - - -size_t CsrWifiSmePacketFilterSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePacketFilterSetCfm *primitive = (CsrWifiSmePacketFilterSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmePacketFilterSetCfm *primitive = kmalloc(sizeof(CsrWifiSmePacketFilterSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 6; /* u8 primitive->permanentMacAddress.a[6] */ - return bufferSize; -} - - -u8* CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePermanentMacAddressGetCfm *primitive = (CsrWifiSmePermanentMacAddressGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrMemCpySer(ptr, len, (const void *) primitive->permanentMacAddress.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmePermanentMacAddressGetCfm *primitive = kmalloc(sizeof(CsrWifiSmePermanentMacAddressGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrMemCpyDes(primitive->permanentMacAddress.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiSmePmkidCandidateListIndSizeof(void *msg) -{ - CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* u8 primitive->pmkidCandidatesCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) - { - bufferSize += 6; /* u8 primitive->pmkidCandidates[i1].bssid.a[6] */ - bufferSize += 1; /* u8 primitive->pmkidCandidates[i1].preAuthAllowed */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->pmkidCandidatesCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->pmkidCandidates[i1].bssid.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->pmkidCandidates[i1].preAuthAllowed); - } - } - return(ptr); -} - - -void* CsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmePmkidCandidateListInd *primitive = kmalloc(sizeof(CsrWifiSmePmkidCandidateListInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->pmkidCandidatesCount, buffer, &offset); - primitive->pmkidCandidates = NULL; - if (primitive->pmkidCandidatesCount) - { - primitive->pmkidCandidates = kmalloc(sizeof(CsrWifiSmePmkidCandidate) * primitive->pmkidCandidatesCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->pmkidCandidatesCount; i1++) - { - CsrMemCpyDes(primitive->pmkidCandidates[i1].bssid.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->pmkidCandidates[i1].preAuthAllowed, buffer, &offset); - } - } - - return primitive; -} - - -void CsrWifiSmePmkidCandidateListIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmePmkidCandidateListInd *primitive = (CsrWifiSmePmkidCandidateListInd *) voidPrimitivePointer; - kfree(primitive->pmkidCandidates); - kfree(primitive); -} - - -size_t CsrWifiSmePmkidCfmSizeof(void *msg) -{ - CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 31) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmeListAction primitive->action */ - bufferSize += 1; /* u8 primitive->getPmkidsCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) - { - bufferSize += 6; /* u8 primitive->getPmkids[i1].bssid.a[6] */ - bufferSize += 16; /* u8 primitive->getPmkids[i1].pmkid[16] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->action); - CsrUint8Ser(ptr, len, (u8) primitive->getPmkidsCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->getPmkids[i1].bssid.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->getPmkids[i1].pmkid, ((u16) (16))); - } - } - return(ptr); -} - - -void* CsrWifiSmePmkidCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmePmkidCfm *primitive = kmalloc(sizeof(CsrWifiSmePmkidCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->action, buffer, &offset); - CsrUint8Des((u8 *) &primitive->getPmkidsCount, buffer, &offset); - primitive->getPmkids = NULL; - if (primitive->getPmkidsCount) - { - primitive->getPmkids = kmalloc(sizeof(CsrWifiSmePmkid) * primitive->getPmkidsCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->getPmkidsCount; i1++) - { - CsrMemCpyDes(primitive->getPmkids[i1].bssid.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->getPmkids[i1].pmkid, buffer, &offset, ((u16) (16))); - } - } - - return primitive; -} - - -void CsrWifiSmePmkidCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmePmkidCfm *primitive = (CsrWifiSmePmkidCfm *) voidPrimitivePointer; - kfree(primitive->getPmkids); - kfree(primitive); -} - - -size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSmePowerSaveLevel primitive->powerConfig.powerSaveLevel */ - bufferSize += 2; /* u16 primitive->powerConfig.listenIntervalTu */ - bufferSize += 1; /* u8 primitive->powerConfig.rxDtims */ - bufferSize += 1; /* CsrWifiSmeD3AutoScanMode primitive->powerConfig.d3AutoScanMode */ - bufferSize += 1; /* u8 primitive->powerConfig.clientTrafficWindow */ - bufferSize += 1; /* u8 primitive->powerConfig.opportunisticPowerSave */ - bufferSize += 1; /* u8 primitive->powerConfig.noticeOfAbsence */ - return bufferSize; -} - - -u8* CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmePowerConfigGetCfm *primitive = (CsrWifiSmePowerConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.powerSaveLevel); - CsrUint16Ser(ptr, len, (u16) primitive->powerConfig.listenIntervalTu); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.rxDtims); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.d3AutoScanMode); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.clientTrafficWindow); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.opportunisticPowerSave); - CsrUint8Ser(ptr, len, (u8) primitive->powerConfig.noticeOfAbsence); - return(ptr); -} - - -void* CsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmePowerConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmePowerConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.powerSaveLevel, buffer, &offset); - CsrUint16Des((u16 *) &primitive->powerConfig.listenIntervalTu, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.rxDtims, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.d3AutoScanMode, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.clientTrafficWindow, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.opportunisticPowerSave, buffer, &offset); - CsrUint8Des((u8 *) &primitive->powerConfig.noticeOfAbsence, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->regDomInfo.dot11MultiDomainCapabilityImplemented */ - bufferSize += 1; /* u8 primitive->regDomInfo.dot11MultiDomainCapabilityEnabled */ - bufferSize += 1; /* CsrWifiSmeRegulatoryDomain primitive->regDomInfo.currentRegulatoryDomain */ - bufferSize += 2; /* u8 primitive->regDomInfo.currentCountryCode[2] */ - return bufferSize; -} - - -u8* CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRegulatoryDomainInfoGetCfm *primitive = (CsrWifiSmeRegulatoryDomainInfoGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->regDomInfo.dot11MultiDomainCapabilityImplemented); - CsrUint8Ser(ptr, len, (u8) primitive->regDomInfo.dot11MultiDomainCapabilityEnabled); - CsrUint8Ser(ptr, len, (u8) primitive->regDomInfo.currentRegulatoryDomain); - CsrMemCpySer(ptr, len, (const void *) primitive->regDomInfo.currentCountryCode, ((u16) (2))); - return(ptr); -} - - -void* CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRegulatoryDomainInfoGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeRegulatoryDomainInfoGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->regDomInfo.dot11MultiDomainCapabilityImplemented, buffer, &offset); - CsrUint8Des((u8 *) &primitive->regDomInfo.dot11MultiDomainCapabilityEnabled, buffer, &offset); - CsrUint8Des((u8 *) &primitive->regDomInfo.currentRegulatoryDomain, buffer, &offset); - CsrMemCpyDes(primitive->regDomInfo.currentCountryCode, buffer, &offset, ((u16) (2))); - - return primitive; -} - - -size_t CsrWifiSmeRoamCompleteIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRoamCompleteInd *primitive = (CsrWifiSmeRoamCompleteInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRoamCompleteInd *primitive = kmalloc(sizeof(CsrWifiSmeRoamCompleteInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeRoamStartIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 1; /* CsrWifiSmeRoamReason primitive->roamReason */ - bufferSize += 2; /* CsrWifiSmeIEEE80211Reason primitive->reason80211 */ - return bufferSize; -} - - -u8* CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRoamStartInd *primitive = (CsrWifiSmeRoamStartInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint8Ser(ptr, len, (u8) primitive->roamReason); - CsrUint16Ser(ptr, len, (u16) primitive->reason80211); - return(ptr); -} - - -void* CsrWifiSmeRoamStartIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRoamStartInd *primitive = kmalloc(sizeof(CsrWifiSmeRoamStartInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint8Des((u8 *) &primitive->roamReason, buffer, &offset); - CsrUint16Des((u16 *) &primitive->reason80211, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 72) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].rssiHighThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].rssiLowThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].snrHighThreshold */ - bufferSize += 2; /* s16 primitive->roamingConfig.roamingBands[i2].snrLowThreshold */ - } - } - bufferSize += 1; /* u8 primitive->roamingConfig.disableSmoothRoaming */ - bufferSize += 1; /* u8 primitive->roamingConfig.disableRoamScans */ - bufferSize += 1; /* u8 primitive->roamingConfig.reconnectLimit */ - bufferSize += 2; /* u16 primitive->roamingConfig.reconnectLimitIntervalMs */ - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].intervalSeconds */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].validitySeconds */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRoamingConfigGetCfm *primitive = (CsrWifiSmeRoamingConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].rssiHighThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].rssiLowThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].snrHighThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamingBands[i2].snrLowThreshold); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.disableSmoothRoaming); - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.disableRoamScans); - CsrUint8Ser(ptr, len, (u8) primitive->roamingConfig.reconnectLimit); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.reconnectLimitIntervalMs); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].intervalSeconds); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].validitySeconds); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu); - } - } - return(ptr); -} - - -void* CsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRoamingConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeRoamingConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].rssiHighThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].rssiLowThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].snrHighThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamingBands[i2].snrLowThreshold, buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->roamingConfig.disableSmoothRoaming, buffer, &offset); - CsrUint8Des((u8 *) &primitive->roamingConfig.disableRoamScans, buffer, &offset); - CsrUint8Des((u8 *) &primitive->roamingConfig.reconnectLimit, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.reconnectLimitIntervalMs, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 3; i2++) - { - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].intervalSeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].validitySeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].minActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->roamingConfig.roamScanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); - } - } - - return primitive; -} - - -size_t CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeRoamingConfigSetCfm *primitive = (CsrWifiSmeRoamingConfigSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeRoamingConfigSetCfm *primitive = kmalloc(sizeof(CsrWifiSmeRoamingConfigSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeScanConfigGetCfmSizeof(void *msg) -{ - CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 65) */ - bufferSize += 2; /* CsrResult primitive->status */ - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].intervalSeconds */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].validitySeconds */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu */ - bufferSize += 2; /* u16 primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu */ - } - } - bufferSize += 1; /* u8 primitive->scanConfig.disableAutonomousScans */ - bufferSize += 2; /* u16 primitive->scanConfig.maxResults */ - bufferSize += 1; /* s8 primitive->scanConfig.highRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.lowRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.deltaRssiThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.highSnrThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.lowSnrThreshold */ - bufferSize += 1; /* s8 primitive->scanConfig.deltaSnrThreshold */ - bufferSize += 2; /* u16 primitive->scanConfig.passiveChannelListCount */ - bufferSize += primitive->scanConfig.passiveChannelListCount; /* u8 primitive->scanConfig.passiveChannelList */ - return bufferSize; -} - - -u8* CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].intervalSeconds); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].validitySeconds); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu); - } - } - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.disableAutonomousScans); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.maxResults); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.highRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.lowRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.deltaRssiThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.highSnrThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.lowSnrThreshold); - CsrUint8Ser(ptr, len, (u8) primitive->scanConfig.deltaSnrThreshold); - CsrUint16Ser(ptr, len, (u16) primitive->scanConfig.passiveChannelListCount); - if (primitive->scanConfig.passiveChannelListCount) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanConfig.passiveChannelList, ((u16) (primitive->scanConfig.passiveChannelListCount))); - } - return(ptr); -} - - -void* CsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeScanConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeScanConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - { - u16 i2; - for (i2 = 0; i2 < 4; i2++) - { - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].intervalSeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].validitySeconds, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].minActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].maxActiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].minPassiveChannelTimeTu, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.scanCfg[i2].maxPassiveChannelTimeTu, buffer, &offset); - } - } - CsrUint8Des((u8 *) &primitive->scanConfig.disableAutonomousScans, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.maxResults, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.highRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.lowRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.deltaRssiThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.highSnrThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.lowSnrThreshold, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanConfig.deltaSnrThreshold, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanConfig.passiveChannelListCount, buffer, &offset); - if (primitive->scanConfig.passiveChannelListCount) - { - primitive->scanConfig.passiveChannelList = kmalloc(primitive->scanConfig.passiveChannelListCount, GFP_KERNEL); - CsrMemCpyDes(primitive->scanConfig.passiveChannelList, buffer, &offset, ((u16) (primitive->scanConfig.passiveChannelListCount))); - } - else - { - primitive->scanConfig.passiveChannelList = NULL; - } - - return primitive; -} - - -void CsrWifiSmeScanConfigGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeScanConfigGetCfm *primitive = (CsrWifiSmeScanConfigGetCfm *) voidPrimitivePointer; - kfree(primitive->scanConfig.passiveChannelList); - kfree(primitive); -} - - -size_t CsrWifiSmeScanResultIndSizeof(void *msg) -{ - CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 149) */ - bufferSize += 32; /* u8 primitive->result.ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->result.ssid.length */ - bufferSize += 6; /* u8 primitive->result.bssid.a[6] */ - bufferSize += 2; /* s16 primitive->result.rssi */ - bufferSize += 2; /* s16 primitive->result.snr */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->result.ifIndex */ - bufferSize += 2; /* u16 primitive->result.beaconPeriodTu */ - bufferSize += 8; /* u8 primitive->result.timeStamp.data[8] */ - bufferSize += 8; /* u8 primitive->result.localTime.data[8] */ - bufferSize += 2; /* u16 primitive->result.channelFrequency */ - bufferSize += 2; /* u16 primitive->result.capabilityInformation */ - bufferSize += 1; /* u8 primitive->result.channelNumber */ - bufferSize += 1; /* CsrWifiSmeBasicUsability primitive->result.usability */ - bufferSize += 1; /* CsrWifiSmeBssType primitive->result.bssType */ - bufferSize += 2; /* u16 primitive->result.informationElementsLength */ - bufferSize += primitive->result.informationElementsLength; /* u8 primitive->result.informationElements */ - bufferSize += 1; /* CsrWifiSmeP2pRole primitive->result.p2pDeviceRole */ - switch (primitive->result.p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - bufferSize += 1; /* u8 primitive->result.deviceInfo.reservedCli.empty */ - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - bufferSize += 1; /* CsrWifiSmeP2pGroupCapabilityMask primitive->result.deviceInfo.groupInfo.groupCapability */ - bufferSize += 6; /* u8 primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a[6] */ - bufferSize += 1; /* u8 primitive->result.deviceInfo.groupInfo.p2pClientInfoCount */ - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - bufferSize += 6; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a[6] */ - bufferSize += 6; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a[6] */ - bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods */ - bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap */ - bufferSize += 8; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails[8] */ - bufferSize += 1; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount */ - { - u16 i6; - for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - bufferSize += 8; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails[8] */ - } - } - bufferSize += 32; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName[32] */ - bufferSize += 1; /* u8 primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength */ - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - bufferSize += 1; /* u8 primitive->result.deviceInfo.reservedNone.empty */ - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - bufferSize += 6; /* u8 primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a[6] */ - bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->result.deviceInfo.standalonedevInfo.configMethods */ - bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap */ - bufferSize += 8; /* u8 primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails[8] */ - bufferSize += 1; /* u8 primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount */ - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - bufferSize += 8; /* u8 primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails[8] */ - } - } - bufferSize += 32; /* u8 primitive->result.deviceInfo.standalonedevInfo.deviceName[32] */ - bufferSize += 1; /* u8 primitive->result.deviceInfo.standalonedevInfo.deviceNameLength */ - break; - default: - break; - } - return bufferSize; -} - - -u8* CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrMemCpySer(ptr, len, (const void *) primitive->result.ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->result.ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->result.bssid.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->result.rssi); - CsrUint16Ser(ptr, len, (u16) primitive->result.snr); - CsrUint8Ser(ptr, len, (u8) primitive->result.ifIndex); - CsrUint16Ser(ptr, len, (u16) primitive->result.beaconPeriodTu); - CsrMemCpySer(ptr, len, (const void *) primitive->result.timeStamp.data, ((u16) (8))); - CsrMemCpySer(ptr, len, (const void *) primitive->result.localTime.data, ((u16) (8))); - CsrUint16Ser(ptr, len, (u16) primitive->result.channelFrequency); - CsrUint16Ser(ptr, len, (u16) primitive->result.capabilityInformation); - CsrUint8Ser(ptr, len, (u8) primitive->result.channelNumber); - CsrUint8Ser(ptr, len, (u8) primitive->result.usability); - CsrUint8Ser(ptr, len, (u8) primitive->result.bssType); - CsrUint16Ser(ptr, len, (u16) primitive->result.informationElementsLength); - if (primitive->result.informationElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->result.informationElements, ((u16) (primitive->result.informationElementsLength))); - } - CsrUint8Ser(ptr, len, (u8) primitive->result.p2pDeviceRole); - switch (primitive->result.p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.reservedCli.empty); - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.groupInfo.groupCapability); - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.groupInfo.p2pClientInfoCount); - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap); - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, ((u16) (8))); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); - { - u16 i6; - for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, ((u16) (8))); - } - } - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength); - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.reservedNone.empty); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->result.deviceInfo.standalonedevInfo.configMethods); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap); - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, ((u16) (8))); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, ((u16) (8))); - } - } - CsrMemCpySer(ptr, len, (const void *) primitive->result.deviceInfo.standalonedevInfo.deviceName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->result.deviceInfo.standalonedevInfo.deviceNameLength); - break; - default: - break; - } - return(ptr); -} - - -void* CsrWifiSmeScanResultIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeScanResultInd *primitive = kmalloc(sizeof(CsrWifiSmeScanResultInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrMemCpyDes(primitive->result.ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->result.ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->result.bssid.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->result.rssi, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result.snr, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.ifIndex, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result.beaconPeriodTu, buffer, &offset); - CsrMemCpyDes(primitive->result.timeStamp.data, buffer, &offset, ((u16) (8))); - CsrMemCpyDes(primitive->result.localTime.data, buffer, &offset, ((u16) (8))); - CsrUint16Des((u16 *) &primitive->result.channelFrequency, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result.capabilityInformation, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.channelNumber, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.usability, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.bssType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->result.informationElementsLength, buffer, &offset); - if (primitive->result.informationElementsLength) - { - primitive->result.informationElements = kmalloc(primitive->result.informationElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->result.informationElements, buffer, &offset, ((u16) (primitive->result.informationElementsLength))); - } - else - { - primitive->result.informationElements = NULL; - } - CsrUint8Des((u8 *) &primitive->result.p2pDeviceRole, buffer, &offset); - switch (primitive->result.p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - CsrUint8Des((u8 *) &primitive->result.deviceInfo.reservedCli.empty, buffer, &offset); - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - CsrUint8Des((u8 *) &primitive->result.deviceInfo.groupInfo.groupCapability, buffer, &offset); - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2pDeviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.groupInfo.p2pClientInfoCount, buffer, &offset); - primitive->result.deviceInfo.groupInfo.p2PClientInfo = NULL; - if (primitive->result.deviceInfo.groupInfo.p2pClientInfoCount) - { - primitive->result.deviceInfo.groupInfo.p2PClientInfo = kmalloc(sizeof(CsrWifiSmeP2pClientInfoType) * primitive->result.deviceInfo.groupInfo.p2pClientInfoCount, GFP_KERNEL); - } - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap, buffer, &offset); - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, buffer, &offset, ((u16) (8))); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, buffer, &offset); - primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; - if (primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount) - { - primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = kmalloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, GFP_KERNEL); - } - { - u16 i6; - for (i6 = 0; i6 < primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, buffer, &offset, ((u16) (8))); - } - } - CsrMemCpyDes(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength, buffer, &offset); - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - CsrUint8Des((u8 *) &primitive->result.deviceInfo.reservedNone.empty, buffer, &offset); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.deviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->result.deviceInfo.standalonedevInfo.configMethods, buffer, &offset); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.standalonedevInfo.p2PDeviceCap, buffer, &offset); - CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, buffer, &offset, ((u16) (8))); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, buffer, &offset); - primitive->result.deviceInfo.standalonedevInfo.secDeviceType = NULL; - if (primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount) - { - primitive->result.deviceInfo.standalonedevInfo.secDeviceType = kmalloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, GFP_KERNEL); - } - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, buffer, &offset, ((u16) (8))); - } - } - CsrMemCpyDes(primitive->result.deviceInfo.standalonedevInfo.deviceName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->result.deviceInfo.standalonedevInfo.deviceNameLength, buffer, &offset); - break; - default: - break; - } - - return primitive; -} - - -void CsrWifiSmeScanResultIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeScanResultInd *primitive = (CsrWifiSmeScanResultInd *) voidPrimitivePointer; - kfree(primitive->result.informationElements); - switch (primitive->result.p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_GO: - { - u16 i4; - for (i4 = 0; i4 < primitive->result.deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - kfree(primitive->result.deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); - } - } - kfree(primitive->result.deviceInfo.groupInfo.p2PClientInfo); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - kfree(primitive->result.deviceInfo.standalonedevInfo.secDeviceType); - break; - default: - break; - } - kfree(primitive); -} - - -size_t CsrWifiSmeScanResultsGetCfmSizeof(void *msg) -{ - CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 153) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->scanResultsCount */ - { - u16 i1; - for (i1 = 0; i1 < primitive->scanResultsCount; i1++) - { - bufferSize += 32; /* u8 primitive->scanResults[i1].ssid.ssid[32] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].ssid.length */ - bufferSize += 6; /* u8 primitive->scanResults[i1].bssid.a[6] */ - bufferSize += 2; /* s16 primitive->scanResults[i1].rssi */ - bufferSize += 2; /* s16 primitive->scanResults[i1].snr */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->scanResults[i1].ifIndex */ - bufferSize += 2; /* u16 primitive->scanResults[i1].beaconPeriodTu */ - bufferSize += 8; /* u8 primitive->scanResults[i1].timeStamp.data[8] */ - bufferSize += 8; /* u8 primitive->scanResults[i1].localTime.data[8] */ - bufferSize += 2; /* u16 primitive->scanResults[i1].channelFrequency */ - bufferSize += 2; /* u16 primitive->scanResults[i1].capabilityInformation */ - bufferSize += 1; /* u8 primitive->scanResults[i1].channelNumber */ - bufferSize += 1; /* CsrWifiSmeBasicUsability primitive->scanResults[i1].usability */ - bufferSize += 1; /* CsrWifiSmeBssType primitive->scanResults[i1].bssType */ - bufferSize += 2; /* u16 primitive->scanResults[i1].informationElementsLength */ - bufferSize += primitive->scanResults[i1].informationElementsLength; /* u8 primitive->scanResults[i1].informationElements */ - bufferSize += 1; /* CsrWifiSmeP2pRole primitive->scanResults[i1].p2pDeviceRole */ - switch (primitive->scanResults[i1].p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.reservedCli.empty */ - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - bufferSize += 1; /* CsrWifiSmeP2pGroupCapabilityMask primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability */ - bufferSize += 6; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a[6] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount */ - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - bufferSize += 6; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a[6] */ - bufferSize += 6; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a[6] */ - bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods */ - bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap */ - bufferSize += 8; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails[8] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount */ - { - u16 i6; - for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - bufferSize += 8; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails[8] */ - } - } - bufferSize += 32; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName[32] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength */ - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.reservedNone.empty */ - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - bufferSize += 6; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a[6] */ - bufferSize += 2; /* CsrWifiSmeWpsConfigTypeMask primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods */ - bufferSize += 1; /* CsrWifiSmeP2pCapabilityMask primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap */ - bufferSize += 8; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails[8] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount */ - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - bufferSize += 8; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails[8] */ - } - } - bufferSize += 32; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName[32] */ - bufferSize += 1; /* u8 primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength */ - break; - default: - break; - } - } - } - return bufferSize; -} - - -u8* CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->scanResultsCount); - { - u16 i1; - for (i1 = 0; i1 < primitive->scanResultsCount; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].ssid.ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].ssid.length); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].bssid.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].rssi); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].snr); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].ifIndex); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].beaconPeriodTu); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].timeStamp.data, ((u16) (8))); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].localTime.data, ((u16) (8))); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].channelFrequency); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].capabilityInformation); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].channelNumber); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].usability); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].bssType); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].informationElementsLength); - if (primitive->scanResults[i1].informationElementsLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].informationElements, ((u16) (primitive->scanResults[i1].informationElementsLength))); - } - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].p2pDeviceRole); - switch (primitive->scanResults[i1].p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.reservedCli.empty); - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a, ((u16) (6))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount); - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, ((u16) (6))); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, ((u16) (8))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount); - { - u16 i6; - for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, ((u16) (8))); - } - } - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength); - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.reservedNone.empty); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a, ((u16) (6))); - CsrUint16Ser(ptr, len, (u16) primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap); - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, ((u16) (8))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount); - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, ((u16) (8))); - } - } - CsrMemCpySer(ptr, len, (const void *) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength); - break; - default: - break; - } - } - } - return(ptr); -} - - -void* CsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeScanResultsGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeScanResultsGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanResultsCount, buffer, &offset); - primitive->scanResults = NULL; - if (primitive->scanResultsCount) - { - primitive->scanResults = kmalloc(sizeof(CsrWifiSmeScanResult) * primitive->scanResultsCount, GFP_KERNEL); - } - { - u16 i1; - for (i1 = 0; i1 < primitive->scanResultsCount; i1++) - { - CsrMemCpyDes(primitive->scanResults[i1].ssid.ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].ssid.length, buffer, &offset); - CsrMemCpyDes(primitive->scanResults[i1].bssid.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->scanResults[i1].rssi, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanResults[i1].snr, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].ifIndex, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanResults[i1].beaconPeriodTu, buffer, &offset); - CsrMemCpyDes(primitive->scanResults[i1].timeStamp.data, buffer, &offset, ((u16) (8))); - CsrMemCpyDes(primitive->scanResults[i1].localTime.data, buffer, &offset, ((u16) (8))); - CsrUint16Des((u16 *) &primitive->scanResults[i1].channelFrequency, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanResults[i1].capabilityInformation, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].channelNumber, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].usability, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].bssType, buffer, &offset); - CsrUint16Des((u16 *) &primitive->scanResults[i1].informationElementsLength, buffer, &offset); - if (primitive->scanResults[i1].informationElementsLength) - { - primitive->scanResults[i1].informationElements = kmalloc(primitive->scanResults[i1].informationElementsLength, GFP_KERNEL); - CsrMemCpyDes(primitive->scanResults[i1].informationElements, buffer, &offset, ((u16) (primitive->scanResults[i1].informationElementsLength))); - } - else - { - primitive->scanResults[i1].informationElements = NULL; - } - CsrUint8Des((u8 *) &primitive->scanResults[i1].p2pDeviceRole, buffer, &offset); - switch (primitive->scanResults[i1].p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_CLI: - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.reservedCli.empty, buffer, &offset); - break; - case CSR_WIFI_SME_P2P_ROLE_GO: - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.groupCapability, buffer, &offset); - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2pDeviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount, buffer, &offset); - primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = NULL; - if (primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount) - { - primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo = kmalloc(sizeof(CsrWifiSmeP2pClientInfoType) * primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount, GFP_KERNEL); - } - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].p2PClientInterfaceAddress.a, buffer, &offset, ((u16) (6))); - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.configMethods, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.p2PDeviceCap, buffer, &offset); - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.primDeviceType.deviceDetails, buffer, &offset, ((u16) (8))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, buffer, &offset); - primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = NULL; - if (primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount) - { - primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType = kmalloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount, GFP_KERNEL); - } - { - u16 i6; - for (i6 = 0; i6 < primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secondaryDeviceTypeCount; i6++) - { - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType[i6].deviceDetails, buffer, &offset, ((u16) (8))); - } - } - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.deviceNameLength, buffer, &offset); - } - } - break; - case CSR_WIFI_SME_P2P_ROLE_NONE: - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.reservedNone.empty, buffer, &offset); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceAddress.a, buffer, &offset, ((u16) (6))); - CsrUint16Des((u16 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.configMethods, buffer, &offset); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.p2PDeviceCap, buffer, &offset); - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.primDeviceType.deviceDetails, buffer, &offset, ((u16) (8))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, buffer, &offset); - primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = NULL; - if (primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount) - { - primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType = kmalloc(sizeof(CsrWifiSmeWpsDeviceType) * primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount, GFP_KERNEL); - } - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.standalonedevInfo.secondaryDeviceTypeCount; i4++) - { - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType[i4].deviceDetails, buffer, &offset, ((u16) (8))); - } - } - CsrMemCpyDes(primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceName, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->scanResults[i1].deviceInfo.standalonedevInfo.deviceNameLength, buffer, &offset); - break; - default: - break; - } - } - } - - return primitive; -} - - -void CsrWifiSmeScanResultsGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeScanResultsGetCfm *primitive = (CsrWifiSmeScanResultsGetCfm *) voidPrimitivePointer; - { - u16 i1; - for (i1 = 0; i1 < primitive->scanResultsCount; i1++) - { - kfree(primitive->scanResults[i1].informationElements); - switch (primitive->scanResults[i1].p2pDeviceRole) - { - case CSR_WIFI_SME_P2P_ROLE_GO: - { - u16 i4; - for (i4 = 0; i4 < primitive->scanResults[i1].deviceInfo.groupInfo.p2pClientInfoCount; i4++) - { - kfree(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo[i4].clientDeviceInfo.secDeviceType); - } - } - kfree(primitive->scanResults[i1].deviceInfo.groupInfo.p2PClientInfo); - break; - case CSR_WIFI_SME_P2P_ROLE_STANDALONE: - kfree(primitive->scanResults[i1].deviceInfo.standalonedevInfo.secDeviceType); - break; - default: - break; - } - } - } - kfree(primitive->scanResults); - kfree(primitive); -} - - -size_t CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->smeConfig.connectionQualityRssiChangeTrigger */ - bufferSize += 1; /* u8 primitive->smeConfig.connectionQualitySnrChangeTrigger */ - bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */ - bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */ - bufferSize += 1; /* u8 primitive->smeConfig.allowUnicastUseGroupCipher */ - bufferSize += 1; /* u8 primitive->smeConfig.enableOpportunisticKeyCaching */ - return bufferSize; -} - - -u8* CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSmeStaConfigGetCfm *primitive = (CsrWifiSmeSmeStaConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.connectionQualityRssiChangeTrigger); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.connectionQualitySnrChangeTrigger); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.wmmModeMask); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.ifIndex); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.allowUnicastUseGroupCipher); - CsrUint8Ser(ptr, len, (u8) primitive->smeConfig.enableOpportunisticKeyCaching); - return(ptr); -} - - -void* CsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSmeStaConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeSmeStaConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.connectionQualityRssiChangeTrigger, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.connectionQualitySnrChangeTrigger, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.wmmModeMask, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.ifIndex, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.allowUnicastUseGroupCipher, buffer, &offset); - CsrUint8Des((u8 *) &primitive->smeConfig.enableOpportunisticKeyCaching, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 7) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - return bufferSize; -} - - -u8* CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSmeStaConfigSetCfm *primitive = (CsrWifiSmeSmeStaConfigSetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - return(ptr); -} - - -void* CsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSmeStaConfigSetCfm *primitive = kmalloc(sizeof(CsrWifiSmeSmeStaConfigSetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 17) */ - bufferSize += 2; /* CsrResult primitive->status */ - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - bufferSize += 6; /* u8 primitive->stationMacAddress[i1].a[6] */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeStationMacAddressGetCfm *primitive = (CsrWifiSmeStationMacAddressGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->stationMacAddress[i1].a, ((u16) (6))); - } - } - return(ptr); -} - - -void* CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeStationMacAddressGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeStationMacAddressGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - { - u16 i1; - for (i1 = 0; i1 < 2; i1++) - { - CsrMemCpyDes(primitive->stationMacAddress[i1].a, buffer, &offset, ((u16) (6))); - } - } - - return primitive; -} - - -size_t CsrWifiSmeTspecIndSizeof(void *msg) -{ - CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 4; /* u32 primitive->transactionId */ - bufferSize += 1; /* CsrWifiSmeTspecResultCode primitive->tspecResultCode */ - bufferSize += 2; /* u16 primitive->tspecLength */ - bufferSize += primitive->tspecLength; /* u8 primitive->tspec */ - return bufferSize; -} - - -u8* CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint32Ser(ptr, len, (u32) primitive->transactionId); - CsrUint8Ser(ptr, len, (u8) primitive->tspecResultCode); - CsrUint16Ser(ptr, len, (u16) primitive->tspecLength); - if (primitive->tspecLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((u16) (primitive->tspecLength))); - } - return(ptr); -} - - -void* CsrWifiSmeTspecIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeTspecInd *primitive = kmalloc(sizeof(CsrWifiSmeTspecInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint32Des((u32 *) &primitive->transactionId, buffer, &offset); - CsrUint8Des((u8 *) &primitive->tspecResultCode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->tspecLength, buffer, &offset); - if (primitive->tspecLength) - { - primitive->tspec = kmalloc(primitive->tspecLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tspec, buffer, &offset, ((u16) (primitive->tspecLength))); - } - else - { - primitive->tspec = NULL; - } - - return primitive; -} - - -void CsrWifiSmeTspecIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeTspecInd *primitive = (CsrWifiSmeTspecInd *) voidPrimitivePointer; - kfree(primitive->tspec); - kfree(primitive); -} - - -size_t CsrWifiSmeTspecCfmSizeof(void *msg) -{ - CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 15) */ - bufferSize += 2; /* u16 primitive->interfaceTag */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 4; /* u32 primitive->transactionId */ - bufferSize += 1; /* CsrWifiSmeTspecResultCode primitive->tspecResultCode */ - bufferSize += 2; /* u16 primitive->tspecLength */ - bufferSize += primitive->tspecLength; /* u8 primitive->tspec */ - return bufferSize; -} - - -u8* CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->interfaceTag); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint32Ser(ptr, len, (u32) primitive->transactionId); - CsrUint8Ser(ptr, len, (u8) primitive->tspecResultCode); - CsrUint16Ser(ptr, len, (u16) primitive->tspecLength); - if (primitive->tspecLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->tspec, ((u16) (primitive->tspecLength))); - } - return(ptr); -} - - -void* CsrWifiSmeTspecCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeTspecCfm *primitive = kmalloc(sizeof(CsrWifiSmeTspecCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->interfaceTag, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint32Des((u32 *) &primitive->transactionId, buffer, &offset); - CsrUint8Des((u8 *) &primitive->tspecResultCode, buffer, &offset); - CsrUint16Des((u16 *) &primitive->tspecLength, buffer, &offset); - if (primitive->tspecLength) - { - primitive->tspec = kmalloc(primitive->tspecLength, GFP_KERNEL); - CsrMemCpyDes(primitive->tspec, buffer, &offset, ((u16) (primitive->tspecLength))); - } - else - { - primitive->tspec = NULL; - } - - return primitive; -} - - -void CsrWifiSmeTspecCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeTspecCfm *primitive = (CsrWifiSmeTspecCfm *) voidPrimitivePointer; - kfree(primitive->tspec); - kfree(primitive); -} - - -size_t CsrWifiSmeVersionsGetCfmSizeof(void *msg) -{ - CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 33) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 4; /* u32 primitive->versions.chipId */ - bufferSize += 4; /* u32 primitive->versions.chipVersion */ - bufferSize += 4; /* u32 primitive->versions.firmwareBuild */ - bufferSize += 4; /* u32 primitive->versions.firmwarePatch */ - bufferSize += 4; /* u32 primitive->versions.firmwareHip */ - bufferSize += (primitive->versions.routerBuild ? strlen(primitive->versions.routerBuild) : 0) + 1; /* char* primitive->versions.routerBuild (0 byte len + 1 for NULL Term) */ - bufferSize += 4; /* u32 primitive->versions.routerHip */ - bufferSize += (primitive->versions.smeBuild ? strlen(primitive->versions.smeBuild) : 0) + 1; /* char* primitive->versions.smeBuild (0 byte len + 1 for NULL Term) */ - bufferSize += 4; /* u32 primitive->versions.smeHip */ - return bufferSize; -} - - -u8* CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint32Ser(ptr, len, (u32) primitive->versions.chipId); - CsrUint32Ser(ptr, len, (u32) primitive->versions.chipVersion); - CsrUint32Ser(ptr, len, (u32) primitive->versions.firmwareBuild); - CsrUint32Ser(ptr, len, (u32) primitive->versions.firmwarePatch); - CsrUint32Ser(ptr, len, (u32) primitive->versions.firmwareHip); - CsrCharStringSer(ptr, len, primitive->versions.routerBuild); - CsrUint32Ser(ptr, len, (u32) primitive->versions.routerHip); - CsrCharStringSer(ptr, len, primitive->versions.smeBuild); - CsrUint32Ser(ptr, len, (u32) primitive->versions.smeHip); - return(ptr); -} - - -void* CsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeVersionsGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeVersionsGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.chipId, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.chipVersion, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.firmwareBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.firmwarePatch, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.firmwareHip, buffer, &offset); - CsrCharStringDes(&primitive->versions.routerBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.routerHip, buffer, &offset); - CsrCharStringDes(&primitive->versions.smeBuild, buffer, &offset); - CsrUint32Des((u32 *) &primitive->versions.smeHip, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeVersionsGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeVersionsGetCfm *primitive = (CsrWifiSmeVersionsGetCfm *) voidPrimitivePointer; - kfree(primitive->versions.routerBuild); - kfree(primitive->versions.smeBuild); - kfree(primitive); -} - - -size_t CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg) -{ - CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 39) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* u8 primitive->cloakedSsids.cloakedSsidsCount */ - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - bufferSize += 32; /* u8 primitive->cloakedSsids.cloakedSsids[i2].ssid[32] */ - bufferSize += 1; /* u8 primitive->cloakedSsids.cloakedSsids[i2].length */ - } - } - return bufferSize; -} - - -u8* CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->cloakedSsids.cloakedSsidsCount); - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - CsrMemCpySer(ptr, len, (const void *) primitive->cloakedSsids.cloakedSsids[i2].ssid, ((u16) (32))); - CsrUint8Ser(ptr, len, (u8) primitive->cloakedSsids.cloakedSsids[i2].length); - } - } - return(ptr); -} - - -void* CsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCloakedSsidsGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeCloakedSsidsGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->cloakedSsids.cloakedSsidsCount, buffer, &offset); - primitive->cloakedSsids.cloakedSsids = NULL; - if (primitive->cloakedSsids.cloakedSsidsCount) - { - primitive->cloakedSsids.cloakedSsids = kmalloc(sizeof(CsrWifiSsid) * primitive->cloakedSsids.cloakedSsidsCount, GFP_KERNEL); - } - { - u16 i2; - for (i2 = 0; i2 < primitive->cloakedSsids.cloakedSsidsCount; i2++) - { - CsrMemCpyDes(primitive->cloakedSsids.cloakedSsids[i2].ssid, buffer, &offset, ((u16) (32))); - CsrUint8Des((u8 *) &primitive->cloakedSsids.cloakedSsids[i2].length, buffer, &offset); - } - } - - return primitive; -} - - -void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeCloakedSsidsGetCfm *primitive = (CsrWifiSmeCloakedSsidsGetCfm *) voidPrimitivePointer; - kfree(primitive->cloakedSsids.cloakedSsids); - kfree(primitive); -} - - -size_t CsrWifiSmeWifiOnIndSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 6; /* u8 primitive->address.a[6] */ - return bufferSize; -} - - -u8* CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeWifiOnInd *primitive = (CsrWifiSmeWifiOnInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrMemCpySer(ptr, len, (const void *) primitive->address.a, ((u16) (6))); - return(ptr); -} - - -void* CsrWifiSmeWifiOnIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeWifiOnInd *primitive = kmalloc(sizeof(CsrWifiSmeWifiOnInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrMemCpyDes(primitive->address.a, buffer, &offset, ((u16) (6))); - - return primitive; -} - - -size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 1; /* CsrWifiSme80211dTrustLevel primitive->deviceConfig.trustLevel */ - bufferSize += 2; /* u8 primitive->deviceConfig.countryCode[2] */ - bufferSize += 1; /* CsrWifiSmeFirmwareDriverInterface primitive->deviceConfig.firmwareDriverInterface */ - bufferSize += 1; /* u8 primitive->deviceConfig.enableStrictDraftN */ - return bufferSize; -} - - -u8* CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeSmeCommonConfigGetCfm *primitive = (CsrWifiSmeSmeCommonConfigGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.trustLevel); - CsrMemCpySer(ptr, len, (const void *) primitive->deviceConfig.countryCode, ((u16) (2))); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.firmwareDriverInterface); - CsrUint8Ser(ptr, len, (u8) primitive->deviceConfig.enableStrictDraftN); - return(ptr); -} - - -void* CsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeSmeCommonConfigGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeSmeCommonConfigGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint8Des((u8 *) &primitive->deviceConfig.trustLevel, buffer, &offset); - CsrMemCpyDes(primitive->deviceConfig.countryCode, buffer, &offset, ((u16) (2))); - CsrUint8Des((u8 *) &primitive->deviceConfig.firmwareDriverInterface, buffer, &offset); - CsrUint8Des((u8 *) &primitive->deviceConfig.enableStrictDraftN, buffer, &offset); - - return primitive; -} - - -size_t CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg) -{ - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */ - bufferSize += 2; /* CsrResult primitive->status */ - bufferSize += 2; /* u16 primitive->numInterfaces */ - bufferSize += 2; /* u8 primitive->capBitmap[2] */ - return bufferSize; -} - - -u8* CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeInterfaceCapabilityGetCfm *primitive = (CsrWifiSmeInterfaceCapabilityGetCfm *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint16Ser(ptr, len, (u16) primitive->status); - CsrUint16Ser(ptr, len, (u16) primitive->numInterfaces); - CsrMemCpySer(ptr, len, (const void *) primitive->capBitmap, ((u16) (2))); - return(ptr); -} - - -void* CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t length) -{ - CsrWifiSmeInterfaceCapabilityGetCfm *primitive = kmalloc(sizeof(CsrWifiSmeInterfaceCapabilityGetCfm), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint16Des((u16 *) &primitive->status, buffer, &offset); - CsrUint16Des((u16 *) &primitive->numInterfaces, buffer, &offset); - CsrMemCpyDes(primitive->capBitmap, buffer, &offset, ((u16) (2))); - - return primitive; -} - - -size_t CsrWifiSmeErrorIndSizeof(void *msg) -{ - CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 3) */ - bufferSize += (primitive->errorMessage ? strlen(primitive->errorMessage) : 0) + 1; /* char* primitive->errorMessage (0 byte len + 1 for NULL Term) */ - return bufferSize; -} - - -u8* CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrCharStringSer(ptr, len, primitive->errorMessage); - return(ptr); -} - - -void* CsrWifiSmeErrorIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeErrorInd *primitive = kmalloc(sizeof(CsrWifiSmeErrorInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrCharStringDes(&primitive->errorMessage, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeErrorIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeErrorInd *primitive = (CsrWifiSmeErrorInd *) voidPrimitivePointer; - kfree(primitive->errorMessage); - kfree(primitive); -} - - -size_t CsrWifiSmeInfoIndSizeof(void *msg) -{ - CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 3) */ - bufferSize += (primitive->infoMessage ? strlen(primitive->infoMessage) : 0) + 1; /* char* primitive->infoMessage (0 byte len + 1 for NULL Term) */ - return bufferSize; -} - - -u8* CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrCharStringSer(ptr, len, primitive->infoMessage); - return(ptr); -} - - -void* CsrWifiSmeInfoIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeInfoInd *primitive = kmalloc(sizeof(CsrWifiSmeInfoInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrCharStringDes(&primitive->infoMessage, buffer, &offset); - - return primitive; -} - - -void CsrWifiSmeInfoIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeInfoInd *primitive = (CsrWifiSmeInfoInd *) voidPrimitivePointer; - kfree(primitive->infoMessage); - kfree(primitive); -} - - -size_t CsrWifiSmeCoreDumpIndSizeof(void *msg) -{ - CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *) msg; - size_t bufferSize = 2; - - /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */ - bufferSize += 4; /* u32 primitive->dataLength */ - bufferSize += primitive->dataLength; /* u8 primitive->data */ - return bufferSize; -} - - -u8* CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg) -{ - CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *)msg; - *len = 0; - CsrUint16Ser(ptr, len, primitive->common.type); - CsrUint32Ser(ptr, len, (u32) primitive->dataLength); - if (primitive->dataLength) - { - CsrMemCpySer(ptr, len, (const void *) primitive->data, ((u16) (primitive->dataLength))); - } - return(ptr); -} - - -void* CsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t length) -{ - CsrWifiSmeCoreDumpInd *primitive = kmalloc(sizeof(CsrWifiSmeCoreDumpInd), GFP_KERNEL); - size_t offset; - offset = 0; - - CsrUint16Des(&primitive->common.type, buffer, &offset); - CsrUint32Des((u32 *) &primitive->dataLength, buffer, &offset); - if (primitive->dataLength) - { - primitive->data = kmalloc(primitive->dataLength, GFP_KERNEL); - CsrMemCpyDes(primitive->data, buffer, &offset, ((u16) (primitive->dataLength))); - } - else - { - primitive->data = NULL; - } - - return primitive; -} - - -void CsrWifiSmeCoreDumpIndSerFree(void *voidPrimitivePointer) -{ - CsrWifiSmeCoreDumpInd *primitive = (CsrWifiSmeCoreDumpInd *) voidPrimitivePointer; - kfree(primitive->data); - kfree(primitive); -} - - diff --git a/drivers/staging/csr/csr_wifi_sme_serialize.h b/drivers/staging/csr/csr_wifi_sme_serialize.h deleted file mode 100644 index f8526269b203..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_serialize.h +++ /dev/null @@ -1,666 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2012 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_SERIALIZE_H__ -#define CSR_WIFI_SME_SERIALIZE_H__ - -#include "csr_wifi_msgconv.h" -#include "csr_wifi_sme_prim.h" - -extern void CsrWifiSmePfree(void *ptr); - -#define CsrWifiSmeActivateReqSer CsrWifiEventSer -#define CsrWifiSmeActivateReqDes CsrWifiEventDes -#define CsrWifiSmeActivateReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeActivateReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeAdhocConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmeAdhocConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmeAdhocConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeAdhocConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeAdhocConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeAdhocConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeAdhocConfigSetReqSizeof(void *msg); -#define CsrWifiSmeAdhocConfigSetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeBlacklistReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeBlacklistReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeBlacklistReqSizeof(void *msg); -extern void CsrWifiSmeBlacklistReqSerFree(void *msg); - -#define CsrWifiSmeCalibrationDataGetReqSer CsrWifiEventSer -#define CsrWifiSmeCalibrationDataGetReqDes CsrWifiEventDes -#define CsrWifiSmeCalibrationDataGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeCalibrationDataGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCalibrationDataSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCalibrationDataSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCalibrationDataSetReqSizeof(void *msg); -extern void CsrWifiSmeCalibrationDataSetReqSerFree(void *msg); - -#define CsrWifiSmeCcxConfigGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeCcxConfigGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeCcxConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeCcxConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCcxConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCcxConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCcxConfigSetReqSizeof(void *msg); -#define CsrWifiSmeCcxConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeCoexConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmeCoexConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmeCoexConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeCoexConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCoexConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCoexConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCoexConfigSetReqSizeof(void *msg); -#define CsrWifiSmeCoexConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeCoexInfoGetReqSer CsrWifiEventSer -#define CsrWifiSmeCoexInfoGetReqDes CsrWifiEventDes -#define CsrWifiSmeCoexInfoGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeCoexInfoGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeConnectReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectReqSizeof(void *msg); -extern void CsrWifiSmeConnectReqSerFree(void *msg); - -#define CsrWifiSmeConnectionConfigGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeConnectionConfigGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeConnectionConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeConnectionConfigGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeConnectionInfoGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeConnectionInfoGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeConnectionInfoGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeConnectionInfoGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeConnectionStatsGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeConnectionStatsGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeConnectionStatsGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeConnectionStatsGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeDeactivateReqSer CsrWifiEventSer -#define CsrWifiSmeDeactivateReqDes CsrWifiEventDes -#define CsrWifiSmeDeactivateReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeDeactivateReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeDisconnectReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeDisconnectReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeDisconnectReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeDisconnectReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeEventMaskSetReqSer CsrWifiEventCsrUint32Ser -#define CsrWifiSmeEventMaskSetReqDes CsrWifiEventCsrUint32Des -#define CsrWifiSmeEventMaskSetReqSizeof CsrWifiEventCsrUint32Sizeof -#define CsrWifiSmeEventMaskSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeHostConfigGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeHostConfigGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeHostConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeHostConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeHostConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeHostConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeHostConfigSetReqSizeof(void *msg); -#define CsrWifiSmeHostConfigSetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeKeyReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeKeyReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeKeyReqSizeof(void *msg); -#define CsrWifiSmeKeyReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeLinkQualityGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeLinkQualityGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeLinkQualityGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeLinkQualityGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeMibConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmeMibConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmeMibConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeMibConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMibConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibConfigSetReqSizeof(void *msg); -#define CsrWifiSmeMibConfigSetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMibGetNextReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibGetNextReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibGetNextReqSizeof(void *msg); -extern void CsrWifiSmeMibGetNextReqSerFree(void *msg); - -extern u8 *CsrWifiSmeMibGetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibGetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibGetReqSizeof(void *msg); -extern void CsrWifiSmeMibGetReqSerFree(void *msg); - -extern u8 *CsrWifiSmeMibSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibSetReqSizeof(void *msg); -extern void CsrWifiSmeMibSetReqSerFree(void *msg); - -extern u8 *CsrWifiSmeMulticastAddressReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMulticastAddressReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMulticastAddressReqSizeof(void *msg); -extern void CsrWifiSmeMulticastAddressReqSerFree(void *msg); - -extern u8 *CsrWifiSmePacketFilterSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePacketFilterSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePacketFilterSetReqSizeof(void *msg); -extern void CsrWifiSmePacketFilterSetReqSerFree(void *msg); - -#define CsrWifiSmePermanentMacAddressGetReqSer CsrWifiEventSer -#define CsrWifiSmePermanentMacAddressGetReqDes CsrWifiEventDes -#define CsrWifiSmePermanentMacAddressGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmePermanentMacAddressGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmePmkidReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePmkidReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePmkidReqSizeof(void *msg); -extern void CsrWifiSmePmkidReqSerFree(void *msg); - -#define CsrWifiSmePowerConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmePowerConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmePowerConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmePowerConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmePowerConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePowerConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePowerConfigSetReqSizeof(void *msg); -#define CsrWifiSmePowerConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeRegulatoryDomainInfoGetReqSer CsrWifiEventSer -#define CsrWifiSmeRegulatoryDomainInfoGetReqDes CsrWifiEventDes -#define CsrWifiSmeRegulatoryDomainInfoGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeRegulatoryDomainInfoGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeRoamingConfigGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeRoamingConfigGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeRoamingConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeRoamingConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRoamingConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeRoamingConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRoamingConfigSetReqSizeof(void *msg); -#define CsrWifiSmeRoamingConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeScanConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmeScanConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmeScanConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeScanConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeScanConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeScanConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeScanConfigSetReqSizeof(void *msg); -extern void CsrWifiSmeScanConfigSetReqSerFree(void *msg); - -extern u8 *CsrWifiSmeScanFullReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeScanFullReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeScanFullReqSizeof(void *msg); -extern void CsrWifiSmeScanFullReqSerFree(void *msg); - -#define CsrWifiSmeScanResultsFlushReqSer CsrWifiEventSer -#define CsrWifiSmeScanResultsFlushReqDes CsrWifiEventDes -#define CsrWifiSmeScanResultsFlushReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeScanResultsFlushReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeScanResultsGetReqSer CsrWifiEventSer -#define CsrWifiSmeScanResultsGetReqDes CsrWifiEventDes -#define CsrWifiSmeScanResultsGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeScanResultsGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeSmeStaConfigGetReqSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeSmeStaConfigGetReqDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeSmeStaConfigGetReqSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeSmeStaConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeSmeStaConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSmeStaConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg); -#define CsrWifiSmeSmeStaConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeStationMacAddressGetReqSer CsrWifiEventSer -#define CsrWifiSmeStationMacAddressGetReqDes CsrWifiEventDes -#define CsrWifiSmeStationMacAddressGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeStationMacAddressGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeTspecReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeTspecReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeTspecReqSizeof(void *msg); -extern void CsrWifiSmeTspecReqSerFree(void *msg); - -#define CsrWifiSmeVersionsGetReqSer CsrWifiEventSer -#define CsrWifiSmeVersionsGetReqDes CsrWifiEventDes -#define CsrWifiSmeVersionsGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeVersionsGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeWifiFlightmodeReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeWifiFlightmodeReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeWifiFlightmodeReqSizeof(void *msg); -extern void CsrWifiSmeWifiFlightmodeReqSerFree(void *msg); - -#define CsrWifiSmeWifiOffReqSer CsrWifiEventSer -#define CsrWifiSmeWifiOffReqDes CsrWifiEventDes -#define CsrWifiSmeWifiOffReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeWifiOffReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeWifiOnReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeWifiOnReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeWifiOnReqSizeof(void *msg); -extern void CsrWifiSmeWifiOnReqSerFree(void *msg); - -extern u8 *CsrWifiSmeCloakedSsidsSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCloakedSsidsSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCloakedSsidsSetReqSizeof(void *msg); -extern void CsrWifiSmeCloakedSsidsSetReqSerFree(void *msg); - -#define CsrWifiSmeCloakedSsidsGetReqSer CsrWifiEventSer -#define CsrWifiSmeCloakedSsidsGetReqDes CsrWifiEventDes -#define CsrWifiSmeCloakedSsidsGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeCloakedSsidsGetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeSmeCommonConfigGetReqSer CsrWifiEventSer -#define CsrWifiSmeSmeCommonConfigGetReqDes CsrWifiEventDes -#define CsrWifiSmeSmeCommonConfigGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeSmeCommonConfigGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeSmeCommonConfigSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSmeCommonConfigSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSmeCommonConfigSetReqSizeof(void *msg); -#define CsrWifiSmeSmeCommonConfigSetReqSerFree CsrWifiSmePfree - -#define CsrWifiSmeInterfaceCapabilityGetReqSer CsrWifiEventSer -#define CsrWifiSmeInterfaceCapabilityGetReqDes CsrWifiEventDes -#define CsrWifiSmeInterfaceCapabilityGetReqSizeof CsrWifiEventSizeof -#define CsrWifiSmeInterfaceCapabilityGetReqSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeWpsConfigurationReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeWpsConfigurationReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeWpsConfigurationReqSizeof(void *msg); -extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg); - -extern u8 *CsrWifiSmeSetReqSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSetReqDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSetReqSizeof(void *msg); -extern void CsrWifiSmeSetReqSerFree(void *msg); - -#define CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeActivateCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeAdhocConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeAdhocConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeAdhocConfigGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeAdhocConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeAdhocConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeAdhocConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeAdhocConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeAssociationCompleteIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeAssociationCompleteIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeAssociationCompleteIndSizeof(void *msg); -extern void CsrWifiSmeAssociationCompleteIndSerFree(void *msg); - -extern u8 *CsrWifiSmeAssociationStartIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeAssociationStartIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeAssociationStartIndSizeof(void *msg); -#define CsrWifiSmeAssociationStartIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeBlacklistCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeBlacklistCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeBlacklistCfmSizeof(void *msg); -extern void CsrWifiSmeBlacklistCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeCalibrationDataGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCalibrationDataGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCalibrationDataGetCfmSizeof(void *msg); -extern void CsrWifiSmeCalibrationDataGetCfmSerFree(void *msg); - -#define CsrWifiSmeCalibrationDataSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeCalibrationDataSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeCalibrationDataSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeCalibrationDataSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCcxConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCcxConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCcxConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeCcxConfigGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCcxConfigSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCcxConfigSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCcxConfigSetCfmSizeof(void *msg); -#define CsrWifiSmeCcxConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCoexConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCoexConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCoexConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeCoexConfigGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeCoexConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeCoexConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeCoexConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeCoexConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCoexInfoGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCoexInfoGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCoexInfoGetCfmSizeof(void *msg); -#define CsrWifiSmeCoexInfoGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeConnectCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectCfmSizeof(void *msg); -#define CsrWifiSmeConnectCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeConnectionConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectionConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectionConfigGetCfmSizeof(void *msg); -extern void CsrWifiSmeConnectionConfigGetCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeConnectionInfoGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectionInfoGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectionInfoGetCfmSizeof(void *msg); -extern void CsrWifiSmeConnectionInfoGetCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeConnectionQualityIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectionQualityIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectionQualityIndSizeof(void *msg); -#define CsrWifiSmeConnectionQualityIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeConnectionStatsGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeConnectionStatsGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeConnectionStatsGetCfmSizeof(void *msg); -#define CsrWifiSmeConnectionStatsGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeDeactivateCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeDeactivateCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeDeactivateCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeDeactivateCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeDisconnectCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeDisconnectCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeDisconnectCfmSizeof(void *msg); -#define CsrWifiSmeDisconnectCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeEventMaskSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeEventMaskSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeEventMaskSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeEventMaskSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeHostConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeHostConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeHostConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeHostConfigGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeHostConfigSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeHostConfigSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeHostConfigSetCfmSizeof(void *msg); -#define CsrWifiSmeHostConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeIbssStationIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeIbssStationIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeIbssStationIndSizeof(void *msg); -#define CsrWifiSmeIbssStationIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeKeyCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeKeyCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeKeyCfmSizeof(void *msg); -#define CsrWifiSmeKeyCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeLinkQualityGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeLinkQualityGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeLinkQualityGetCfmSizeof(void *msg); -#define CsrWifiSmeLinkQualityGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMediaStatusIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMediaStatusIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMediaStatusIndSizeof(void *msg); -extern void CsrWifiSmeMediaStatusIndSerFree(void *msg); - -extern u8 *CsrWifiSmeMibConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeMibConfigGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeMibConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeMibConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeMibConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeMibConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMibGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibGetCfmSizeof(void *msg); -extern void CsrWifiSmeMibGetCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeMibGetNextCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMibGetNextCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMibGetNextCfmSizeof(void *msg); -extern void CsrWifiSmeMibGetNextCfmSerFree(void *msg); - -#define CsrWifiSmeMibSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeMibSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeMibSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeMibSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMicFailureIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMicFailureIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMicFailureIndSizeof(void *msg); -#define CsrWifiSmeMicFailureIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeMulticastAddressCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeMulticastAddressCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeMulticastAddressCfmSizeof(void *msg); -extern void CsrWifiSmeMulticastAddressCfmSerFree(void *msg); - -extern u8 *CsrWifiSmePacketFilterSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePacketFilterSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePacketFilterSetCfmSizeof(void *msg); -#define CsrWifiSmePacketFilterSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmePermanentMacAddressGetCfmSer(u8 *ptr, size_t *len, - void *msg); -extern void *CsrWifiSmePermanentMacAddressGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePermanentMacAddressGetCfmSizeof(void *msg); -#define CsrWifiSmePermanentMacAddressGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmePmkidCandidateListIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePmkidCandidateListIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePmkidCandidateListIndSizeof(void *msg); -extern void CsrWifiSmePmkidCandidateListIndSerFree(void *msg); - -extern u8 *CsrWifiSmePmkidCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePmkidCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePmkidCfmSizeof(void *msg); -extern void CsrWifiSmePmkidCfmSerFree(void *msg); - -extern u8 *CsrWifiSmePowerConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmePowerConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmePowerConfigGetCfmSizeof(void *msg); -#define CsrWifiSmePowerConfigGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmePowerConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmePowerConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmePowerConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmePowerConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRegulatoryDomainInfoGetCfmSer(u8 *ptr, size_t *len, - void *msg); -extern void *CsrWifiSmeRegulatoryDomainInfoGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRegulatoryDomainInfoGetCfmSizeof(void *msg); -#define CsrWifiSmeRegulatoryDomainInfoGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRoamCompleteIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeRoamCompleteIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRoamCompleteIndSizeof(void *msg); -#define CsrWifiSmeRoamCompleteIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRoamStartIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeRoamStartIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRoamStartIndSizeof(void *msg); -#define CsrWifiSmeRoamStartIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRoamingConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeRoamingConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRoamingConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeRoamingConfigGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeRoamingConfigSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeRoamingConfigSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeRoamingConfigSetCfmSizeof(void *msg); -#define CsrWifiSmeRoamingConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeScanConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeScanConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeScanConfigGetCfmSizeof(void *msg); -extern void CsrWifiSmeScanConfigGetCfmSerFree(void *msg); - -#define CsrWifiSmeScanConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeScanConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeScanConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeScanConfigSetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeScanFullCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeScanFullCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeScanFullCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeScanFullCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeScanResultIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeScanResultIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeScanResultIndSizeof(void *msg); -extern void CsrWifiSmeScanResultIndSerFree(void *msg); - -#define CsrWifiSmeScanResultsFlushCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeScanResultsFlushCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeScanResultsFlushCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeScanResultsFlushCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeScanResultsGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeScanResultsGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeScanResultsGetCfmSizeof(void *msg); -extern void CsrWifiSmeScanResultsGetCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeSmeStaConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSmeStaConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeSmeStaConfigGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeSmeStaConfigSetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSmeStaConfigSetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSmeStaConfigSetCfmSizeof(void *msg); -#define CsrWifiSmeSmeStaConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeStationMacAddressGetCfmSer(u8 *ptr, size_t *len, - void *msg); -extern void *CsrWifiSmeStationMacAddressGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeStationMacAddressGetCfmSizeof(void *msg); -#define CsrWifiSmeStationMacAddressGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeTspecIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeTspecIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeTspecIndSizeof(void *msg); -extern void CsrWifiSmeTspecIndSerFree(void *msg); - -extern u8 *CsrWifiSmeTspecCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeTspecCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeTspecCfmSizeof(void *msg); -extern void CsrWifiSmeTspecCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeVersionsGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeVersionsGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeVersionsGetCfmSizeof(void *msg); -extern void CsrWifiSmeVersionsGetCfmSerFree(void *msg); - -#define CsrWifiSmeWifiFlightmodeCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeWifiFlightmodeCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeWifiFlightmodeCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeWifiFlightmodeCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeWifiOffIndSer CsrWifiEventCsrUint8Ser -#define CsrWifiSmeWifiOffIndDes CsrWifiEventCsrUint8Des -#define CsrWifiSmeWifiOffIndSizeof CsrWifiEventCsrUint8Sizeof -#define CsrWifiSmeWifiOffIndSerFree CsrWifiSmePfree - -#define CsrWifiSmeWifiOffCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeWifiOffCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeWifiOffCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeWifiOffCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeWifiOnCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeWifiOnCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeWifiOnCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeWifiOnCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeCloakedSsidsSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeCloakedSsidsSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeCloakedSsidsSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeCloakedSsidsSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeCloakedSsidsGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCloakedSsidsGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCloakedSsidsGetCfmSizeof(void *msg); -extern void CsrWifiSmeCloakedSsidsGetCfmSerFree(void *msg); - -extern u8 *CsrWifiSmeWifiOnIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeWifiOnIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeWifiOnIndSizeof(void *msg); -#define CsrWifiSmeWifiOnIndSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeSmeCommonConfigGetCfmSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeSmeCommonConfigGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeSmeCommonConfigGetCfmSizeof(void *msg); -#define CsrWifiSmeSmeCommonConfigGetCfmSerFree CsrWifiSmePfree - -#define CsrWifiSmeSmeCommonConfigSetCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeSmeCommonConfigSetCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeSmeCommonConfigSetCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeSmeCommonConfigSetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeInterfaceCapabilityGetCfmSer(u8 *ptr, size_t *len, - void *msg); -extern void *CsrWifiSmeInterfaceCapabilityGetCfmDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeInterfaceCapabilityGetCfmSizeof(void *msg); -#define CsrWifiSmeInterfaceCapabilityGetCfmSerFree CsrWifiSmePfree - -extern u8 *CsrWifiSmeErrorIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeErrorIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeErrorIndSizeof(void *msg); -extern void CsrWifiSmeErrorIndSerFree(void *msg); - -extern u8 *CsrWifiSmeInfoIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeInfoIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeInfoIndSizeof(void *msg); -extern void CsrWifiSmeInfoIndSerFree(void *msg); - -extern u8 *CsrWifiSmeCoreDumpIndSer(u8 *ptr, size_t *len, void *msg); -extern void *CsrWifiSmeCoreDumpIndDes(u8 *buffer, size_t len); -extern size_t CsrWifiSmeCoreDumpIndSizeof(void *msg); -extern void CsrWifiSmeCoreDumpIndSerFree(void *msg); - -#define CsrWifiSmeAmpStatusChangeIndSer CsrWifiEventCsrUint16CsrUint8Ser -#define CsrWifiSmeAmpStatusChangeIndDes CsrWifiEventCsrUint16CsrUint8Des -#define CsrWifiSmeAmpStatusChangeIndSizeof CsrWifiEventCsrUint16CsrUint8Sizeof -#define CsrWifiSmeAmpStatusChangeIndSerFree CsrWifiSmePfree - -#define CsrWifiSmeWpsConfigurationCfmSer CsrWifiEventCsrUint16Ser -#define CsrWifiSmeWpsConfigurationCfmDes CsrWifiEventCsrUint16Des -#define CsrWifiSmeWpsConfigurationCfmSizeof CsrWifiEventCsrUint16Sizeof -#define CsrWifiSmeWpsConfigurationCfmSerFree CsrWifiSmePfree - -#endif /* CSR_WIFI_SME_SERIALIZE_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_sme_task.h b/drivers/staging/csr/csr_wifi_sme_task.h deleted file mode 100644 index 1e938c1fa964..000000000000 --- a/drivers/staging/csr/csr_wifi_sme_task.h +++ /dev/null @@ -1,25 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -/* Note: this is an auto-generated file. */ - -#ifndef CSR_WIFI_SME_TASK_H__ -#define CSR_WIFI_SME_TASK_H__ - -#include "csr_sched.h" - -#define CSR_WIFI_SME_LOG_ID 0x1202FFFF -extern CsrSchedQid CSR_WIFI_SME_IFACEQUEUE; -void CsrWifiSmeInit(void **gash); -void CsrWifiSmeDeinit(void **gash); -void CsrWifiSmeHandler(void **gash); - -#endif /* CSR_WIFI_SME_TASK_H__ */ - diff --git a/drivers/staging/csr/csr_wifi_vif_utils.h b/drivers/staging/csr/csr_wifi_vif_utils.h deleted file mode 100644 index 8ff97888996d..000000000000 --- a/drivers/staging/csr/csr_wifi_vif_utils.h +++ /dev/null @@ -1,27 +0,0 @@ -/***************************************************************************** - - (c) Cambridge Silicon Radio Limited 2011 - All rights reserved and confidential information of CSR - - Refer to LICENSE.txt included with this source for details - on the license terms. - -*****************************************************************************/ - -#ifndef CSR_WIFI_VIF_UTILS_H -#define CSR_WIFI_VIF_UTILS_H - -/* STANDARD INCLUDES ********************************************************/ - -/* PROJECT INCLUDES *********************************************************/ -/* including this file for CsrWifiInterfaceMode*/ -#include "csr_wifi_private_common.h" - -/* MACROS *******************************************************************/ - -/* Common macros for NME and SME to be used temporarily until SoftMAC changes are made */ -#define CSR_WIFI_NUM_INTERFACES (u8)0x1 -#define CSR_WIFI_INTERFACE_IN_USE (u16)0x0 - -#endif /* CSR_WIFI_VIF_UTILS_H */ - diff --git a/drivers/staging/csr/data_tx.c b/drivers/staging/csr/data_tx.c deleted file mode 100644 index 9e3d8b8ab02c..000000000000 --- a/drivers/staging/csr/data_tx.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: data_tx.c - * - * PURPOSE: - * This file provides functions to send data requests to the UniFi. - * - * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include "csr_wifi_hip_unifi.h" -#include "unifi_priv.h" - -int -uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length) -{ - const unsigned char *p = packet; - u16 keyinfo; - - - if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8)) - return 1; - - p += 8; - keyinfo = p[5] << 8 | p[6]; /* big-endian */ - if ( - (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ && - p[1] == 3 /* EAPOL-Key */ && - /* don't bother checking p[2] p[3] (hh ll, packet body length) */ - (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ && - ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ && - (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */ - (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */ - p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0) - ) { - unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected\n"); - return 0; - } else { - return 1; - } -} - -/* - * --------------------------------------------------------------------------- - * - * Data transport signals. - * - * --------------------------------------------------------------------------- - */ - diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c deleted file mode 100644 index 92898de921f5..000000000000 --- a/drivers/staging/csr/drv.c +++ /dev/null @@ -1,2193 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: drv.c - * - * PURPOSE: - * Conventional device interface for debugging/monitoring of the - * driver and h/w using unicli. This interface is also being used - * by the SME linux implementation and the helper apps. - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -/* - * Porting Notes: - * Part of this file contains an example for how to glue the OS layer - * with the HIP core lib, the SDIO glue layer, and the SME. - * - * When the unifi_sdio.ko modules loads, the linux kernel calls unifi_load(). - * unifi_load() calls uf_sdio_load() which is exported by the SDIO glue - * layer. uf_sdio_load() registers this driver with the underlying SDIO driver. - * When a card is detected, the SDIO glue layer calls register_unifi_sdio() - * to pass the SDIO function context and ask the OS layer to initialise - * the card. register_unifi_sdio() allocates all the private data of the OS - * layer and calls uf_run_unifihelper() to start the SME. The SME calls - * unifi_sys_wifi_on_req() which uses the HIP core lib to initialise the card. - */ - -#include -#include -#include -#include -#include -#include - -#include "csr_wifi_hip_unifiversion.h" -#include "unifi_priv.h" -#include "csr_wifi_hip_conversions.h" -#include "unifi_native.h" - -/* Module parameter variables */ -int buswidth = 0; /* 0 means use default, values 1,4 */ -int sdio_clock = 50000; /* kHz */ -int unifi_debug = 0; -/* fw_init prevents f/w initialisation on error. */ -int fw_init[MAX_UNIFI_DEVS] = {-1, -1}; -int use_5g = 0; -int led_mask = 0; /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */ -int disable_hw_reset = 0; -int disable_power_control = 0; -int enable_wol = UNIFI_WOL_OFF; /* 0 for none, 1 for SDIO IRQ, 2 for PIO */ -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) -int tl_80211d = (int)CSR_WIFI_SME_80211D_TRUST_LEVEL_MIB; -#endif -int sdio_block_size = -1; /* Override SDIO block size */ -int sdio_byte_mode = 0; /* 0 for block mode + padding, 1 for byte mode */ -int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; -int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ -int bh_priority = -1; -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -#define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1) -#define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2) -int log_hip_signals = 0; -#endif - -MODULE_DESCRIPTION("CSR UniFi (SDIO)"); - -module_param(buswidth, int, S_IRUGO|S_IWUSR); -module_param(sdio_clock, int, S_IRUGO|S_IWUSR); -module_param(unifi_debug, int, S_IRUGO|S_IWUSR); -module_param_array(fw_init, int, NULL, S_IRUGO|S_IWUSR); -module_param(use_5g, int, S_IRUGO|S_IWUSR); -module_param(led_mask, int, S_IRUGO|S_IWUSR); -module_param(disable_hw_reset, int, S_IRUGO|S_IWUSR); -module_param(disable_power_control, int, S_IRUGO|S_IWUSR); -module_param(enable_wol, int, S_IRUGO|S_IWUSR); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) -module_param(tl_80211d, int, S_IRUGO|S_IWUSR); -#endif -module_param(sdio_block_size, int, S_IRUGO|S_IWUSR); -module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR); -module_param(coredump_max, int, S_IRUGO|S_IWUSR); -module_param(run_bh_once, int, S_IRUGO|S_IWUSR); -module_param(bh_priority, int, S_IRUGO|S_IWUSR); -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -module_param(log_hip_signals, int, S_IRUGO|S_IWUSR); -#endif - -MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode"); -MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)"); -MODULE_PARM_DESC(unifi_debug, "Diagnostic reporting level"); -MODULE_PARM_DESC(fw_init, "Set to 0 to prevent f/w initialization on error"); -MODULE_PARM_DESC(use_5g, "Use the 5G (802.11a) radio band"); -MODULE_PARM_DESC(led_mask, "LED mask flags"); -MODULE_PARM_DESC(disable_hw_reset, "Set to 1 to disable hardware reset"); -MODULE_PARM_DESC(disable_power_control, "Set to 1 to disable SDIO power control"); -MODULE_PARM_DESC(enable_wol, "Enable wake-on-wlan function 0=off, 1=SDIO, 2=PIO"); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) -MODULE_PARM_DESC(tl_80211d, "802.11d Trust Level (1-6, default = 5)"); -#endif -MODULE_PARM_DESC(sdio_block_size, "Set to override SDIO block size"); -MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO"); -MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate"); -MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts"); -MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority"); -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging"); -#endif - - -/* Callback for event logging to UDI clients */ -static void udi_log_event(ul_client_t *client, - const u8 *signal, int signal_len, - const bulk_data_param_t *bulkdata, - int dir); - -static void udi_set_log_filter(ul_client_t *pcli, - unifiio_filter_t *udi_filter); - - -/* Mutex to protect access to priv->sme_cli */ -DEFINE_SEMAPHORE(udi_mutex); - -s32 CsrHipResultToStatus(CsrResult csrResult) -{ - s32 r = -EIO; - - switch (csrResult) - { - case CSR_RESULT_SUCCESS: - r = 0; - break; - case CSR_WIFI_HIP_RESULT_RANGE: - r = -ERANGE; - break; - case CSR_WIFI_HIP_RESULT_NO_DEVICE: - r = -ENODEV; - break; - case CSR_WIFI_HIP_RESULT_INVALID_VALUE: - r = -EINVAL; - break; - case CSR_WIFI_HIP_RESULT_NOT_FOUND: - r = -ENOENT; - break; - case CSR_WIFI_HIP_RESULT_NO_SPACE: - r = -ENOSPC; - break; - case CSR_WIFI_HIP_RESULT_NO_MEMORY: - r = -ENOMEM; - break; - case CSR_RESULT_FAILURE: - r = -EIO; - break; - default: - /*unifi_warning(card->ospriv, "CsrHipResultToStatus: Unrecognised csrResult error code: %d\n", csrResult);*/ - r = -EIO; - } - return r; -} - - -static const char* -trace_putest_cmdid(unifi_putest_command_t putest_cmd) -{ - switch (putest_cmd) { - case UNIFI_PUTEST_START: - return "START"; - case UNIFI_PUTEST_STOP: - return "STOP"; - case UNIFI_PUTEST_SET_SDIO_CLOCK: - return "SET CLOCK"; - case UNIFI_PUTEST_CMD52_READ: - return "CMD52R"; - case UNIFI_PUTEST_CMD52_BLOCK_READ: - return "CMD52BR"; - case UNIFI_PUTEST_CMD52_WRITE: - return "CMD52W"; - case UNIFI_PUTEST_DL_FW: - return "D/L FW"; - case UNIFI_PUTEST_DL_FW_BUFF: - return "D/L FW BUFFER"; - case UNIFI_PUTEST_COREDUMP_PREPARE: - return "PREPARE COREDUMP"; - case UNIFI_PUTEST_GP_READ16: - return "GP16R"; - case UNIFI_PUTEST_GP_WRITE16: - return "GP16W"; - default: - return "ERROR: unrecognised command"; - } - } - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -int uf_register_hip_offline_debug(unifi_priv_t *priv) -{ - ul_client_t *udi_cli; - int i; - - udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); - if (udi_cli == NULL) { - /* Too many clients already using this device */ - unifi_error(priv, "Too many UDI clients already open\n"); - return -ENOSPC; - } - unifi_trace(priv, UDBG1, "Offline HIP client is registered\n"); - - down(&priv->udi_logging_mutex); - udi_cli->event_hook = udi_log_event; - unifi_set_udi_hook(priv->card, logging_handler); - /* Log all signals by default */ - for (i = 0; i < SIG_FILTER_SIZE; i++) { - udi_cli->signal_filter[i] = 0xFFFF; - } - priv->logging_client = udi_cli; - up(&priv->udi_logging_mutex); - - return 0; -} - -int uf_unregister_hip_offline_debug(unifi_priv_t *priv) -{ - ul_client_t *udi_cli = priv->logging_client; - if (udi_cli == NULL) - { - unifi_error(priv, "Unknown HIP client unregister request\n"); - return -ERANGE; - } - - unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n"); - - down(&priv->udi_logging_mutex); - priv->logging_client = NULL; - udi_cli->event_hook = NULL; - up(&priv->udi_logging_mutex); - - ul_deregister_client(udi_cli); - - return 0; -} -#endif - - -/* - * --------------------------------------------------------------------------- - * unifi_open - * unifi_release - * - * Open and release entry points for the UniFi debug driver. - * - * Arguments: - * Normal linux driver args. - * - * Returns: - * Linux error code. - * --------------------------------------------------------------------------- - */ -static int -unifi_open(struct inode *inode, struct file *file) -{ - int devno; - unifi_priv_t *priv; - ul_client_t *udi_cli; - - devno = MINOR(inode->i_rdev) >> 1; - - /* - * Increase the ref_count for the char device clients. - * Make sure you call uf_put_instance() to decreace it if - * unifi_open returns an error. - */ - priv = uf_get_instance(devno); - if (priv == NULL) { - unifi_error(NULL, "unifi_open: No device present\n"); - return -ENODEV; - } - - /* Register this instance in the client's list. */ - /* The minor number determines the nature of the client (Unicli or SME). */ - if (MINOR(inode->i_rdev) & 0x1) { - udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event); - if (udi_cli == NULL) { - /* Too many clients already using this device */ - unifi_error(priv, "Too many clients already open\n"); - uf_put_instance(devno); - return -ENOSPC; - } - unifi_trace(priv, UDBG1, "Client is registered to /dev/unifiudi%d\n", devno); - } else { - /* - * Even-numbered device nodes are the control application. - * This is the userspace helper containing SME or - * unifi_manager. - */ - - down(&udi_mutex); - -#ifdef CSR_SME_USERSPACE - /* Check if a config client is already attached */ - if (priv->sme_cli) { - up(&udi_mutex); - uf_put_instance(devno); - - unifi_info(priv, "There is already a configuration client using the character device\n"); - return -EBUSY; - } -#endif /* CSR_SME_USERSPACE */ - -#ifdef CSR_SUPPORT_SME - udi_cli = ul_register_client(priv, - CLI_USING_WIRE_FORMAT | CLI_SME_USERSPACE, - sme_log_event); -#else - /* Config client for native driver */ - udi_cli = ul_register_client(priv, - 0, - sme_native_log_event); -#endif - if (udi_cli == NULL) { - /* Too many clients already using this device */ - up(&udi_mutex); - uf_put_instance(devno); - - unifi_error(priv, "Too many clients already open\n"); - return -ENOSPC; - } - - /* - * Fill-in the pointer to the configuration client. - * This is the SME userspace helper or unifi_manager. - * Not used in the SME embedded version. - */ - unifi_trace(priv, UDBG1, "SME client (id:%d s:0x%X) is registered\n", - udi_cli->client_id, udi_cli->sender_id); - /* Store the SME UniFi Linux Client */ - if (priv->sme_cli == NULL) { - priv->sme_cli = udi_cli; - } - - up(&udi_mutex); - } - - - /* - * Store the pointer to the client. - * All char driver's entry points will pass this pointer. - */ - file->private_data = udi_cli; - - return 0; -} /* unifi_open() */ - - -static int -unifi_release(struct inode *inode, struct file *filp) -{ - ul_client_t *udi_cli = (void*)filp->private_data; - int devno; - unifi_priv_t *priv; - - priv = uf_find_instance(udi_cli->instance); - if (!priv) { - unifi_error(priv, "unifi_close: instance for device not found\n"); - return -ENODEV; - } - - devno = MINOR(inode->i_rdev) >> 1; - - /* Even device nodes are the config client (i.e. SME or unifi_manager) */ - if ((MINOR(inode->i_rdev) & 0x1) == 0) { - - if (priv->sme_cli != udi_cli) { - unifi_notice(priv, "Surprise closing config device: not the sme client\n"); - } - unifi_notice(priv, "SME client close (unifi%d)\n", devno); - - /* - * Clear sme_cli before calling unifi_sys_... so it doesn't try to - * queue a reply to the (now gone) SME. - */ - down(&udi_mutex); - priv->sme_cli = NULL; - up(&udi_mutex); - -#ifdef CSR_SME_USERSPACE - /* Power-down when config client closes */ - { - CsrWifiRouterCtrlWifiOffReq req = {{CSR_WIFI_ROUTER_CTRL_HIP_REQ, 0, 0, 0, NULL}}; - CsrWifiRouterCtrlWifiOffReqHandler(priv, &req.common); - } - - uf_sme_deinit(priv); - - /* It is possible that a blocking SME request was made from another process - * which did not get read by the SME before the WifiOffReq. - * So check for a pending request which will go unanswered and cancel - * the wait for event. As only one blocking request can be in progress at - * a time, up to one event should be completed. - */ - uf_sme_cancel_request(priv, 0); - -#endif /* CSR_SME_USERSPACE */ - } else { - - unifi_trace(priv, UDBG2, "UDI client close (unifiudi%d)\n", devno); - - /* If the pointer matches the logging client, stop logging. */ - down(&priv->udi_logging_mutex); - if (udi_cli == priv->logging_client) { - priv->logging_client = NULL; - } - up(&priv->udi_logging_mutex); - - if (udi_cli == priv->amp_client) { - priv->amp_client = NULL; - } - } - - /* Deregister this instance from the client's list. */ - ul_deregister_client(udi_cli); - - uf_put_instance(devno); - - return 0; -} /* unifi_release() */ - - - -/* - * --------------------------------------------------------------------------- - * unifi_read - * - * The read() driver entry point. - * - * Arguments: - * filp The file descriptor returned by unifi_open() - * p The user space buffer to copy the read data - * len The size of the p buffer - * poff - * - * Returns: - * number of bytes read or an error code on failure - * --------------------------------------------------------------------------- - */ -static ssize_t -unifi_read(struct file *filp, char *p, size_t len, loff_t *poff) -{ - ul_client_t *pcli = (void*)filp->private_data; - unifi_priv_t *priv; - udi_log_t *logptr = NULL; - udi_msg_t *msgptr; - struct list_head *l; - int msglen; - - priv = uf_find_instance(pcli->instance); - if (!priv) { - unifi_error(priv, "invalid priv\n"); - return -ENODEV; - } - - if (!pcli->udi_enabled) { - unifi_error(priv, "unifi_read: unknown client."); - return -EINVAL; - } - - if (list_empty(&pcli->udi_log)) { - if (filp->f_flags & O_NONBLOCK) { - /* Non-blocking - just return if the udi_log is empty */ - return 0; - } else { - /* Blocking - wait on the UDI wait queue */ - if (wait_event_interruptible(pcli->udi_wq, - !list_empty(&pcli->udi_log))) - { - unifi_error(priv, "unifi_read: wait_event_interruptible failed."); - return -ERESTARTSYS; - } - } - } - - /* Read entry from list head and remove it from the list */ - if (down_interruptible(&pcli->udi_sem)) { - return -ERESTARTSYS; - } - l = pcli->udi_log.next; - list_del(l); - up(&pcli->udi_sem); - - /* Get a pointer to whole struct */ - logptr = list_entry(l, udi_log_t, q); - if (logptr == NULL) { - unifi_error(priv, "unifi_read: failed to get event.\n"); - return -EINVAL; - } - - /* Get the real message */ - msgptr = &logptr->msg; - msglen = msgptr->length; - if (msglen > len) { - printk(KERN_WARNING "truncated read to %d actual msg len is %lu\n", msglen, (long unsigned int)len); - msglen = len; - } - - /* and pass it to the client (SME or Unicli). */ - if (copy_to_user(p, msgptr, msglen)) - { - printk(KERN_ERR "Failed to copy UDI log to user\n"); - kfree(logptr); - return -EFAULT; - } - - /* It is our resposibility to free the message buffer. */ - kfree(logptr); - - return msglen; - -} /* unifi_read() */ - - - -/* - * --------------------------------------------------------------------------- - * udi_send_signal_unpacked - * - * Sends an unpacked signal to UniFi. - * - * Arguments: - * priv Pointer to private context struct - * data Pointer to request structure and data to send - * data_len Length of data in data pointer. - * - * Returns: - * Number of bytes written, error otherwise. - * - * Notes: - * All clients that use this function to send a signal to the unifi - * must use the host formatted structures. - * --------------------------------------------------------------------------- - */ -static int -udi_send_signal_unpacked(unifi_priv_t *priv, unsigned char* data, uint data_len) -{ - CSR_SIGNAL *sigptr = (CSR_SIGNAL*)data; - CSR_DATAREF *datarefptr; - bulk_data_param_t bulk_data; - uint signal_size, i; - uint bulk_data_offset = 0; - int bytecount, r; - CsrResult csrResult; - - /* Number of bytes in the signal */ - signal_size = SigGetSize(sigptr); - if (!signal_size || (signal_size > data_len)) { - unifi_error(priv, "unifi_sme_mlme_req - Invalid signal 0x%x size should be %d bytes\n", - sigptr->SignalPrimitiveHeader.SignalId, - signal_size); - return -EINVAL; - } - bytecount = signal_size; - - /* Get a pointer to the information of the first data reference */ - datarefptr = (CSR_DATAREF*)&sigptr->u; - - /* Initialize the offset in the data buffer, bulk data is right after the signal. */ - bulk_data_offset = signal_size; - - /* store the references and the size of the bulk data to the bulkdata structure */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - /* the length of the bulk data is in the signal */ - if ((datarefptr+i)->DataLength) { - void *dest; - - csrResult = unifi_net_data_malloc(priv, &bulk_data.d[i], (datarefptr+i)->DataLength); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "udi_send_signal_unpacked: failed to allocate request_data.\n"); - return -EIO; - } - - dest = (void*)bulk_data.d[i].os_data_ptr; - memcpy(dest, data + bulk_data_offset, bulk_data.d[i].data_length); - } else { - bulk_data.d[i].data_length = 0; - } - - bytecount += bulk_data.d[i].data_length; - /* advance the offset, to point the next bulk data */ - bulk_data_offset += bulk_data.d[i].data_length; - } - - - unifi_trace(priv, UDBG3, "SME Send: signal 0x%.4X\n", sigptr->SignalPrimitiveHeader.SignalId); - - /* Send the signal. */ - r = ul_send_signal_unpacked(priv, sigptr, &bulk_data); - if (r < 0) { - unifi_error(priv, "udi_send_signal_unpacked: send failed (%d)\n", r); - for(i=0;i buflen)) { - unifi_error(priv, "udi_send_signal_raw - Couldn't find length of signal 0x%x\n", - sig_id); - return -EINVAL; - } - unifi_trace(priv, UDBG2, "udi_send_signal_raw: signal 0x%.4X len:%d\n", - sig_id, signal_size); - /* Zero the data ref arrays */ - memset(&data_ptrs, 0, sizeof(data_ptrs)); - - /* - * Find the number of associated bulk data packets. Scan through - * the data refs to check that we have enough data and pick out - * pointers to appended bulk data. - */ - num_data_refs = 0; - bytecount = signal_size; - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) - { - unsigned int len = GET_PACKED_DATAREF_LEN(buf, i); - unifi_trace(priv, UDBG3, "udi_send_signal_raw: data_ref length = %d\n", len); - - if (len != 0) { - void *dest; - - csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[i], len); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "udi_send_signal_raw: failed to allocate request_data.\n"); - return -EIO; - } - - dest = (void*)data_ptrs.d[i].os_data_ptr; - memcpy(dest, buf + bytecount, len); - - bytecount += len; - num_data_refs++; - } - data_ptrs.d[i].data_length = len; - } - - unifi_trace(priv, UDBG3, "Queueing signal 0x%.4X from UDI with %u data refs\n", - sig_id, - num_data_refs); - - if (bytecount > buflen) { - unifi_error(priv, "udi_send_signal_raw: Not enough data (%d instead of %d)\n", buflen, bytecount); - return -EINVAL; - } - - /* Send the signal calling the function that uses the wire-formatted signals. */ - r = ul_send_signal_raw(priv, buf, signal_size, &data_ptrs); - if (r < 0) { - unifi_error(priv, "udi_send_signal_raw: send failed (%d)\n", r); - return -EIO; - } - -#ifdef CSR_NATIVE_LINUX - if (sig_id == CSR_MLME_POWERMGT_REQUEST_ID) { - int power_mode = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((buf + - SIZEOF_SIGNAL_HEADER + (UNIFI_MAX_DATA_REFERENCES*SIZEOF_DATAREF))); -#ifdef CSR_SUPPORT_WEXT - /* Overide the wext power mode to the new value */ - priv->wext_conf.power_mode = power_mode; -#endif - /* Configure deep sleep signaling */ - if (power_mode || (priv->interfacePriv[0]->connected == UnifiNotConnected)) { - csrResult = unifi_configure_low_power_mode(priv->card, - UNIFI_LOW_POWER_ENABLED, - UNIFI_PERIODIC_WAKE_HOST_DISABLED); - } else { - csrResult = unifi_configure_low_power_mode(priv->card, - UNIFI_LOW_POWER_DISABLED, - UNIFI_PERIODIC_WAKE_HOST_DISABLED); - } - } -#endif - - return bytecount; -} /* udi_send_signal_raw */ - -/* - * --------------------------------------------------------------------------- - * unifi_write - * - * The write() driver entry point. - * A UniFi Debug Interface client such as unicli can write a signal - * plus bulk data to the driver for sending to the UniFi chip. - * - * Only one signal may be sent per write operation. - * - * Arguments: - * filp The file descriptor returned by unifi_open() - * p The user space buffer to get the data from - * len The size of the p buffer - * poff - * - * Returns: - * number of bytes written or an error code on failure - * --------------------------------------------------------------------------- - */ -static ssize_t -unifi_write(struct file *filp, const char *p, size_t len, loff_t *poff) -{ - ul_client_t *pcli = (ul_client_t*)filp->private_data; - unifi_priv_t *priv; - unsigned char *buf; - unsigned char *bufptr; - int remaining; - int bytes_written; - int r; - bulk_data_param_t bulkdata; - CsrResult csrResult; - - priv = uf_find_instance(pcli->instance); - if (!priv) { - unifi_error(priv, "invalid priv\n"); - return -ENODEV; - } - - unifi_trace(priv, UDBG5, "unifi_write: len = %d\n", len); - - if (!pcli->udi_enabled) { - unifi_error(priv, "udi disabled\n"); - return -EINVAL; - } - - /* - * AMP client sends only one signal at a time, so we can use - * unifi_net_data_malloc to save the extra copy. - */ - if (pcli == priv->amp_client) { - int signal_size; - int sig_id; - unsigned char *signal_buf; - char *user_data_buf; - - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], len); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "unifi_write: failed to allocate request_data.\n"); - return -ENOMEM; - } - - user_data_buf = (char*)bulkdata.d[0].os_data_ptr; - - /* Get the data from the AMP client. */ - if (copy_from_user((void*)user_data_buf, p, len)) { - unifi_error(priv, "unifi_write: copy from user failed\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -EFAULT; - } - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - - /* Number of bytes in the signal */ - sig_id = GET_SIGNAL_ID(bulkdata.d[0].os_data_ptr); - signal_size = len; - signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 0); - signal_size -= GET_PACKED_DATAREF_LEN(bulkdata.d[0].os_data_ptr, 1); - if ((signal_size <= 0) || (signal_size > len)) { - unifi_error(priv, "unifi_write - Couldn't find length of signal 0x%x\n", - sig_id); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -EINVAL; - } - - unifi_trace(priv, UDBG2, "unifi_write: signal 0x%.4X len:%d\n", - sig_id, signal_size); - - /* Allocate a buffer for the signal */ - signal_buf = kmemdup(bulkdata.d[0].os_data_ptr, signal_size, - GFP_KERNEL); - if (!signal_buf) { - unifi_net_data_free(priv, &bulkdata.d[0]); - return -ENOMEM; - } - - /* Get the signal from the os_data_ptr */ - signal_buf[5] = (pcli->sender_id >> 8) & 0xff; - - if (signal_size < len) { - /* Remove the signal from the os_data_ptr */ - bulkdata.d[0].data_length -= signal_size; - bulkdata.d[0].os_data_ptr += signal_size; - } else { - bulkdata.d[0].data_length = 0; - bulkdata.d[0].os_data_ptr = NULL; - } - - /* Send the signal calling the function that uses the wire-formatted signals. */ - r = ul_send_signal_raw(priv, signal_buf, signal_size, &bulkdata); - if (r < 0) { - unifi_error(priv, "unifi_write: send failed (%d)\n", r); - if (bulkdata.d[0].os_data_ptr != NULL) { - unifi_net_data_free(priv, &bulkdata.d[0]); - } - } - - /* Free the signal buffer and return */ - kfree(signal_buf); - return len; - } - - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - return -ENOMEM; - } - - /* Get the data from the client (SME or Unicli). */ - if (copy_from_user((void*)buf, p, len)) { - unifi_error(priv, "copy from user failed\n"); - kfree(buf); - return -EFAULT; - } - - /* - * In SME userspace build read() contains a SYS or MGT message. - * Note that even though the SME sends one signal at a time, we can not - * use unifi_net_data_malloc because in the early stages, before having - * initialised the core, it will fail since the I/O block size is unknown. - */ -#ifdef CSR_SME_USERSPACE - if (pcli->configuration & CLI_SME_USERSPACE) { - CsrWifiRouterTransportRecv(priv, buf, len); - kfree(buf); - return len; - } -#endif - - /* ul_send_signal_raw will do a sanity check of len against signal content */ - - /* - * udi_send_signal_raw() and udi_send_signal_unpacked() return the number of bytes consumed. - * A write call can pass multiple signal concatenated together. - */ - bytes_written = 0; - remaining = len; - bufptr = buf; - while (remaining > 0) - { - int r; - - /* - * Set the SenderProcessId. - * The SignalPrimitiveHeader is the first 3 16-bit words of the signal, - * the SenderProcessId is bytes 4,5. - * The MSB of the sender ID needs to be set to the client ID. - * The LSB is controlled by the SME. - */ - bufptr[5] = (pcli->sender_id >> 8) & 0xff; - - /* use the appropriate interface, depending on the clients' configuration */ - if (pcli->configuration & CLI_USING_WIRE_FORMAT) { - unifi_trace(priv, UDBG1, "unifi_write: call udi_send_signal().\n"); - r = udi_send_signal_raw(priv, bufptr, remaining); - } else { - r = udi_send_signal_unpacked(priv, bufptr, remaining); - } - if (r < 0) { - /* Set the return value to the error code */ - unifi_error(priv, "unifi_write: (udi or sme)_send_signal() returns %d\n", r); - bytes_written = r; - break; - } - bufptr += r; - remaining -= r; - bytes_written += r; - } - - kfree(buf); - - return bytes_written; -} /* unifi_write() */ - - -static const char* build_type_to_string(unsigned char build_type) -{ - switch (build_type) - { - case UNIFI_BUILD_NME: return "NME"; - case UNIFI_BUILD_WEXT: return "WEXT"; - case UNIFI_BUILD_AP: return "AP"; - } - return "unknown"; -} - - -/* - * ---------------------------------------------------------------- - * unifi_ioctl - * - * Ioctl handler for unifi driver. - * - * Arguments: - * inodep Pointer to inode structure. - * filp Pointer to file structure. - * cmd Ioctl cmd passed by user. - * arg Ioctl arg passed by user. - * - * Returns: - * 0 on success, -ve error code on error. - * ---------------------------------------------------------------- - */ -static long -unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - ul_client_t *pcli = (ul_client_t*)filp->private_data; - unifi_priv_t *priv; - struct net_device *dev; - int r = 0; - int int_param, i; - u8* buf; - CsrResult csrResult; -#if (defined CSR_SUPPORT_SME) - unifi_cfg_command_t cfg_cmd; -#if (defined CSR_SUPPORT_WEXT) - CsrWifiSmeCoexConfig coex_config; - unsigned char uchar_param; - unsigned char varbind[MAX_VARBIND_LENGTH]; - int vblen; -#endif -#endif - unifi_putest_command_t putest_cmd; - - priv = uf_find_instance(pcli->instance); - if (!priv) { - unifi_error(priv, "ioctl error: unknown instance=%d\n", pcli->instance); - r = -ENODEV; - goto out; - } - unifi_trace(priv, UDBG5, "unifi_ioctl: cmd=0x%X, arg=0x%lX\n", cmd, arg); - - switch (cmd) { - - case UNIFI_GET_UDI_ENABLE: - unifi_trace(priv, UDBG4, "UniFi Get UDI Enable\n"); - - down(&priv->udi_logging_mutex); - int_param = (priv->logging_client == NULL) ? 0 : 1; - up(&priv->udi_logging_mutex); - - if (put_user(int_param, (int*)arg)) - { - unifi_error(priv, "UNIFI_GET_UDI_ENABLE: Failed to copy to user\n"); - r = -EFAULT; - goto out; - } - break; - - case UNIFI_SET_UDI_ENABLE: - unifi_trace(priv, UDBG4, "UniFi Set UDI Enable\n"); - if (get_user(int_param, (int*)arg)) - { - unifi_error(priv, "UNIFI_SET_UDI_ENABLE: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - if (log_hip_signals) { - unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n"); - r = -EFAULT; - goto out; - } -#endif - - down(&priv->udi_logging_mutex); - if (int_param) { - pcli->event_hook = udi_log_event; - unifi_set_udi_hook(priv->card, logging_handler); - /* Log all signals by default */ - for (i = 0; i < SIG_FILTER_SIZE; i++) { - pcli->signal_filter[i] = 0xFFFF; - } - priv->logging_client = pcli; - - } else { - priv->logging_client = NULL; - pcli->event_hook = NULL; - } - up(&priv->udi_logging_mutex); - - break; - - case UNIFI_SET_MIB: - unifi_trace(priv, UDBG4, "UniFi Set MIB\n"); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - /* Read first 2 bytes and check length */ - if (copy_from_user((void*)varbind, (void*)arg, 2)) { - unifi_error(priv, - "UNIFI_SET_MIB: Failed to copy in varbind header\n"); - r = -EFAULT; - goto out; - } - vblen = varbind[1]; - if ((vblen + 2) > MAX_VARBIND_LENGTH) { - unifi_error(priv, - "UNIFI_SET_MIB: Varbind too long (%d, limit %d)\n", - (vblen+2), MAX_VARBIND_LENGTH); - r = -EINVAL; - goto out; - } - /* Read rest of varbind */ - if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { - unifi_error(priv, "UNIFI_SET_MIB: Failed to copy in varbind\n"); - r = -EFAULT; - goto out; - } - - /* send to SME */ - vblen += 2; - r = sme_mgt_mib_set(priv, varbind, vblen); - if (r) { - goto out; - } -#else - unifi_notice(priv, "UNIFI_SET_MIB: Unsupported.\n"); -#endif /* CSR_SUPPORT_WEXT */ - break; - - case UNIFI_GET_MIB: - unifi_trace(priv, UDBG4, "UniFi Get MIB\n"); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - /* Read first 2 bytes and check length */ - if (copy_from_user((void*)varbind, (void*)arg, 2)) { - unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind header\n"); - r = -EFAULT; - goto out; - } - vblen = varbind[1]; - if ((vblen+2) > MAX_VARBIND_LENGTH) { - unifi_error(priv, "UNIFI_GET_MIB: Varbind too long (%d, limit %d)\n", - (vblen+2), MAX_VARBIND_LENGTH); - r = -EINVAL; - goto out; - } - /* Read rest of varbind */ - if (copy_from_user((void*)(varbind+2), (void*)(arg+2), vblen)) { - unifi_error(priv, "UNIFI_GET_MIB: Failed to copy in varbind\n"); - r = -EFAULT; - goto out; - } - - vblen += 2; - r = sme_mgt_mib_get(priv, varbind, &vblen); - if (r) { - goto out; - } - /* copy out varbind */ - if (vblen > MAX_VARBIND_LENGTH) { - unifi_error(priv, - "UNIFI_GET_MIB: Varbind result too long (%d, limit %d)\n", - vblen, MAX_VARBIND_LENGTH); - r = -EINVAL; - goto out; - } - if (copy_to_user((void*)arg, varbind, vblen)) { - r = -EFAULT; - goto out; - } -#else - unifi_notice(priv, "UNIFI_GET_MIB: Unsupported.\n"); -#endif /* CSR_SUPPORT_WEXT */ - break; - - case UNIFI_CFG: -#if (defined CSR_SUPPORT_SME) - if (get_user(cfg_cmd, (unifi_cfg_command_t*)arg)) - { - unifi_error(priv, "UNIFI_CFG: Failed to get the command\n"); - r = -EFAULT; - goto out; - } - - unifi_trace(priv, UDBG1, "UNIFI_CFG: Command is %d (t=%u) sz=%d\n", - cfg_cmd, jiffies_to_msecs(jiffies), sizeof(unifi_cfg_command_t)); - switch (cfg_cmd) { - case UNIFI_CFG_POWER: - r = unifi_cfg_power(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_POWERSAVE: - r = unifi_cfg_power_save(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_POWERSUPPLY: - r = unifi_cfg_power_supply(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_FILTER: - r = unifi_cfg_packet_filters(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_GET: - r = unifi_cfg_get_info(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_WMM_QOSINFO: - r = unifi_cfg_wmm_qos_info(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_WMM_ADDTS: - r = unifi_cfg_wmm_addts(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_WMM_DELTS: - r = unifi_cfg_wmm_delts(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_STRICT_DRAFT_N: - r = unifi_cfg_strict_draft_n(priv, (unsigned char*)arg); - break; - case UNIFI_CFG_ENABLE_OKC: - r = unifi_cfg_enable_okc(priv, (unsigned char*)arg); - break; -#ifdef CSR_SUPPORT_SME - case UNIFI_CFG_CORE_DUMP: - CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, CSR_WIFI_SME_CONTROL_INDICATION_ERROR); - unifi_trace(priv, UDBG2, "UNIFI_CFG_CORE_DUMP: sent wifi off indication\n"); - break; -#endif -#ifdef CSR_SUPPORT_WEXT_AP - case UNIFI_CFG_SET_AP_CONFIG: - r= unifi_cfg_set_ap_config(priv, (unsigned char*)arg); - break; -#endif - default: - unifi_error(priv, "UNIFI_CFG: Unknown Command (%d)\n", cfg_cmd); - r = -EINVAL; - goto out; - } -#endif - - break; - - case UNIFI_PUTEST: - if (get_user(putest_cmd, (unifi_putest_command_t*)arg)) - { - unifi_error(priv, "UNIFI_PUTEST: Failed to get the command\n"); - r = -EFAULT; - goto out; - } - - unifi_trace(priv, UDBG1, "UNIFI_PUTEST: Command is %s\n", - trace_putest_cmdid(putest_cmd)); - switch (putest_cmd) { - case UNIFI_PUTEST_START: - r = unifi_putest_start(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_STOP: - r = unifi_putest_stop(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_SET_SDIO_CLOCK: - r = unifi_putest_set_sdio_clock(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_CMD52_READ: - r = unifi_putest_cmd52_read(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_CMD52_BLOCK_READ: - r = unifi_putest_cmd52_block_read(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_CMD52_WRITE: - r = unifi_putest_cmd52_write(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_DL_FW: - r = unifi_putest_dl_fw(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_DL_FW_BUFF: - r = unifi_putest_dl_fw_buff(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_COREDUMP_PREPARE: - r = unifi_putest_coredump_prepare(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_GP_READ16: - r = unifi_putest_gp_read16(priv, (unsigned char*)arg); - break; - case UNIFI_PUTEST_GP_WRITE16: - r = unifi_putest_gp_write16(priv, (unsigned char*)arg); - break; - default: - unifi_error(priv, "UNIFI_PUTEST: Unknown Command (%d)\n", putest_cmd); - r = -EINVAL; - goto out; - } - - break; - case UNIFI_BUILD_TYPE: - unifi_trace(priv, UDBG2, "UNIFI_BUILD_TYPE userspace=%s\n", build_type_to_string(*(unsigned char*)arg)); -#ifndef CSR_SUPPORT_WEXT_AP - if (UNIFI_BUILD_AP == *(unsigned char*)arg) - { - unifi_error(priv, "Userspace has AP support, which is incompatible\n"); - } -#endif - -#ifndef CSR_SUPPORT_WEXT - if (UNIFI_BUILD_WEXT == *(unsigned char*)arg) - { - unifi_error(priv, "Userspace has WEXT support, which is incompatible\n"); - } -#endif - break; - case UNIFI_INIT_HW: - unifi_trace(priv, UDBG2, "UNIFI_INIT_HW.\n"); - priv->init_progress = UNIFI_INIT_NONE; - -#if defined(CSR_SUPPORT_WEXT) || defined (CSR_NATIVE_LINUX) - /* At this point we are ready to start the SME. */ - r = sme_mgt_wifi_on(priv); - if (r) { - goto out; - } -#endif - - break; - - case UNIFI_INIT_NETDEV: - { - /* get the proper interfaceTagId */ - u16 interfaceTag=0; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - dev = priv->netdev[interfaceTag]; - unifi_trace(priv, UDBG2, "UNIFI_INIT_NETDEV.\n"); - - if (copy_from_user((void*)dev->dev_addr, (void*)arg, 6)) { - r = -EFAULT; - goto out; - } - - /* Attach the network device to the stack */ - if (!interfacePriv->netdev_registered) - { - r = uf_register_netdev(priv, interfaceTag); - if (r) { - unifi_error(priv, "Failed to register the network device.\n"); - goto out; - } - } - - /* Apply scheduled interrupt mode, if requested by module param */ - if (run_bh_once != -1) { - unifi_set_interrupt_mode(priv->card, (u32)run_bh_once); - } - - priv->init_progress = UNIFI_INIT_COMPLETED; - - /* Firmware initialisation is complete, so let the SDIO bus - * clock be raised when convienent to the core. - */ - unifi_request_max_sdio_clock(priv->card); - -#ifdef CSR_SUPPORT_WEXT - /* Notify the Android wpa_supplicant that we are ready */ - wext_send_started_event(priv); -#endif - - unifi_info(priv, "UniFi ready\n"); - -#ifdef ANDROID_BUILD - /* Release the wakelock */ - unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n"); - wake_unlock(&unifi_sdio_wake_lock); -#endif -#ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */ - { - struct net_device *dev = priv->netdev[interfaceTag]; -#ifdef CSR_SUPPORT_WEXT - interfacePriv->wait_netdev_change = TRUE; -#endif - netif_carrier_on(dev); - } -#endif - } - break; - case UNIFI_GET_INIT_STATUS: - unifi_trace(priv, UDBG2, "UNIFI_GET_INIT_STATUS.\n"); - if (put_user(priv->init_progress, (int*)arg)) - { - printk(KERN_ERR "UNIFI_GET_INIT_STATUS: Failed to copy to user\n"); - r = -EFAULT; - goto out; - } - break; - - case UNIFI_KICK: - unifi_trace(priv, UDBG4, "Kick UniFi\n"); - unifi_sdio_interrupt_handler(priv->card); - break; - - case UNIFI_SET_DEBUG: - unifi_debug = arg; - unifi_trace(priv, UDBG4, "unifi_debug set to %d\n", unifi_debug); - break; - - case UNIFI_SET_TRACE: - /* no longer supported */ - r = -EINVAL; - break; - - - case UNIFI_SET_UDI_LOG_MASK: - { - unifiio_filter_t udi_filter; - uint16_t *sig_ids_addr; -#define UF_MAX_SIG_IDS 128 /* Impose a sensible limit */ - - if (copy_from_user((void*)(&udi_filter), (void*)arg, sizeof(udi_filter))) { - r = -EFAULT; - goto out; - } - if ((udi_filter.action < UfSigFil_AllOn) || - (udi_filter.action > UfSigFil_SelectOff)) - { - printk(KERN_WARNING - "UNIFI_SET_UDI_LOG_MASK: Bad action value: %d\n", - udi_filter.action); - r = -EINVAL; - goto out; - } - /* No signal list for "All" actions */ - if ((udi_filter.action == UfSigFil_AllOn) || - (udi_filter.action == UfSigFil_AllOff)) - { - udi_filter.num_sig_ids = 0; - } - - if (udi_filter.num_sig_ids > UF_MAX_SIG_IDS) { - printk(KERN_WARNING - "UNIFI_SET_UDI_LOG_MASK: too many signal ids (%d, max %d)\n", - udi_filter.num_sig_ids, UF_MAX_SIG_IDS); - r = -EINVAL; - goto out; - } - - /* Copy in signal id list if given */ - if (udi_filter.num_sig_ids > 0) { - /* Preserve userspace address of sig_ids array */ - sig_ids_addr = udi_filter.sig_ids; - /* Allocate kernel memory for sig_ids and copy to it */ - udi_filter.sig_ids = - kmalloc(udi_filter.num_sig_ids * sizeof(uint16_t), GFP_KERNEL); - if (!udi_filter.sig_ids) { - r = -ENOMEM; - goto out; - } - if (copy_from_user((void*)udi_filter.sig_ids, - (void*)sig_ids_addr, - udi_filter.num_sig_ids * sizeof(uint16_t))) - { - kfree(udi_filter.sig_ids); - r = -EFAULT; - goto out; - } - } - - udi_set_log_filter(pcli, &udi_filter); - - if (udi_filter.num_sig_ids > 0) { - kfree(udi_filter.sig_ids); - } - } - break; - - case UNIFI_SET_AMP_ENABLE: - unifi_trace(priv, UDBG4, "UniFi Set AMP Enable\n"); - if (get_user(int_param, (int*)arg)) - { - unifi_error(priv, "UNIFI_SET_AMP_ENABLE: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - - if (int_param) { - priv->amp_client = pcli; - } else { - priv->amp_client = NULL; - } - - int_param = 0; - buf = (u8*)&int_param; - buf[0] = UNIFI_SOFT_COMMAND_Q_LENGTH - 1; - buf[1] = UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1; - if (copy_to_user((void*)arg, &int_param, sizeof(int))) { - r = -EFAULT; - goto out; - } - break; - - case UNIFI_SET_UDI_SNAP_MASK: - { - unifiio_snap_filter_t snap_filter; - - if (copy_from_user((void*)(&snap_filter), (void*)arg, sizeof(snap_filter))) { - r = -EFAULT; - goto out; - } - - if (pcli->snap_filter.count) { - pcli->snap_filter.count = 0; - kfree(pcli->snap_filter.protocols); - } - - if (snap_filter.count == 0) { - break; - } - - pcli->snap_filter.protocols = kmalloc(snap_filter.count * sizeof(u16), GFP_KERNEL); - if (!pcli->snap_filter.protocols) { - r = -ENOMEM; - goto out; - } - if (copy_from_user((void*)pcli->snap_filter.protocols, - (void*)snap_filter.protocols, - snap_filter.count * sizeof(u16))) - { - kfree(pcli->snap_filter.protocols); - r = -EFAULT; - goto out; - } - - pcli->snap_filter.count = snap_filter.count; - - } - break; - - case UNIFI_SME_PRESENT: - { - u8 ind; - unifi_trace(priv, UDBG4, "UniFi SME Present IOCTL.\n"); - if (copy_from_user((void*)(&int_param), (void*)arg, sizeof(int))) - { - printk(KERN_ERR "UNIFI_SME_PRESENT: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - - priv->sme_is_present = int_param; - if (priv->sme_is_present == 1) { - ind = CONFIG_SME_PRESENT; - } else { - ind = CONFIG_SME_NOT_PRESENT; - } - /* Send an indication to the helper app. */ - ul_log_config_ind(priv, &ind, sizeof(u8)); - } - break; - - case UNIFI_CFG_PERIOD_TRAFFIC: - { -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - CsrWifiSmeCoexConfig coexConfig; -#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ - unifi_trace(priv, UDBG4, "UniFi Configure Periodic Traffic.\n"); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { - unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - - if (uchar_param == 0) { - r = sme_mgt_coex_config_get(priv, &coexConfig); - if (r) { - unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Get unifi_CoexInfoValue failed.\n"); - goto out; - } - if (copy_to_user((void*)(arg + 1), - (void*)&coexConfig, - sizeof(CsrWifiSmeCoexConfig))) { - r = -EFAULT; - goto out; - } - goto out; - } - - if (copy_from_user((void*)(&coex_config), (void*)(arg + 1), sizeof(CsrWifiSmeCoexConfig))) - { - unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - - coexConfig = coex_config; - r = sme_mgt_coex_config_set(priv, &coexConfig); - if (r) { - unifi_error(priv, "UNIFI_CFG_PERIOD_TRAFFIC: Set unifi_CoexInfoValue failed.\n"); - goto out; - } - -#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ - break; - } - case UNIFI_CFG_UAPSD_TRAFFIC: - unifi_trace(priv, UDBG4, "UniFi Configure U-APSD Mask.\n"); -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - if (copy_from_user((void*)(&uchar_param), (void*)arg, sizeof(unsigned char))) { - unifi_error(priv, "UNIFI_CFG_UAPSD_TRAFFIC: Failed to copy from user\n"); - r = -EFAULT; - goto out; - } - unifi_trace(priv, UDBG4, "New U-APSD Mask: 0x%x\n", uchar_param); -#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT */ - break; - -#ifndef UNIFI_DISABLE_COREDUMP - case UNIFI_COREDUMP_GET_REG: - unifi_trace(priv, UDBG4, "Mini-coredump data request\n"); - { - unifiio_coredump_req_t dump_req; /* Public OS layer structure */ - unifi_coredump_req_t priv_req; /* Private HIP structure */ - - if (copy_from_user((void*)(&dump_req), (void*)arg, sizeof(dump_req))) { - r = -EFAULT; - goto out; - } - memset(&priv_req, 0, sizeof(priv_req)); - priv_req.index = dump_req.index; - priv_req.offset = dump_req.offset; - - /* Convert OS-layer's XAP memory space ID to HIP's ID in case they differ */ - switch (dump_req.space) { - case UNIFIIO_COREDUMP_MAC_REG: priv_req.space = UNIFI_COREDUMP_MAC_REG; break; - case UNIFIIO_COREDUMP_PHY_REG: priv_req.space = UNIFI_COREDUMP_PHY_REG; break; - case UNIFIIO_COREDUMP_SH_DMEM: priv_req.space = UNIFI_COREDUMP_SH_DMEM; break; - case UNIFIIO_COREDUMP_MAC_DMEM: priv_req.space = UNIFI_COREDUMP_MAC_DMEM; break; - case UNIFIIO_COREDUMP_PHY_DMEM: priv_req.space = UNIFI_COREDUMP_PHY_DMEM; break; - case UNIFIIO_COREDUMP_TRIGGER_MAGIC: priv_req.space = UNIFI_COREDUMP_TRIGGER_MAGIC; break; - default: - r = -EINVAL; - goto out; - } - - if (priv_req.space == UNIFI_COREDUMP_TRIGGER_MAGIC) { - /* Force a coredump grab now */ - unifi_trace(priv, UDBG2, "UNIFI_COREDUMP_GET_REG: Force capture\n"); - csrResult = unifi_coredump_capture(priv->card, &priv_req); - r = CsrHipResultToStatus(csrResult); - unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: status %d\n", r); - } else { - /* Retrieve the appropriate register entry */ - csrResult = unifi_coredump_get_value(priv->card, &priv_req); - r = CsrHipResultToStatus(csrResult); - if (r) { - unifi_trace(priv, UDBG5, "UNIFI_COREDUMP_GET_REG: Status %d\n", r); - goto out; - } - /* Update the OS-layer structure with values returned in the private */ - dump_req.value = priv_req.value; - dump_req.timestamp = priv_req.timestamp; - dump_req.requestor = priv_req.requestor; - dump_req.serial = priv_req.serial; - dump_req.chip_ver = priv_req.chip_ver; - dump_req.fw_ver = priv_req.fw_ver; - dump_req.drv_build = 0; - - unifi_trace(priv, UDBG6, - "Dump: %d (seq %d): V:0x%04x (%d) @0x%02x:%04x = 0x%04x\n", - dump_req.index, dump_req.serial, - dump_req.chip_ver, dump_req.drv_build, - dump_req.space, dump_req.offset, dump_req.value); - } - if (copy_to_user((void*)arg, (void*)&dump_req, sizeof(dump_req))) { - r = -EFAULT; - goto out; - } - } - break; -#endif - default: - r = -EINVAL; - } - -out: - return (long)r; -} /* unifi_ioctl() */ - - - -static unsigned int -unifi_poll(struct file *filp, poll_table *wait) -{ - ul_client_t *pcli = (ul_client_t*)filp->private_data; - unsigned int mask = 0; - int ready; - - ready = !list_empty(&pcli->udi_log); - - poll_wait(filp, &pcli->udi_wq, wait); - - if (ready) { - mask |= POLLIN | POLLRDNORM; /* readable */ - } - - return mask; -} /* unifi_poll() */ - - - -/* - * --------------------------------------------------------------------------- - * udi_set_log_filter - * - * Configure the bit mask that determines which signal primitives are - * passed to the logging process. - * - * Arguments: - * pcli Pointer to the client to configure. - * udi_filter Pointer to a unifiio_filter_t containing instructions. - * - * Returns: - * None. - * - * Notes: - * SigGetFilterPos() returns a 32-bit value that contains an index and a - * mask for accessing a signal_filter array. The top 16 bits specify an - * index into a signal_filter, the bottom 16 bits specify a mask to - * apply. - * --------------------------------------------------------------------------- - */ -static void -udi_set_log_filter(ul_client_t *pcli, unifiio_filter_t *udi_filter) -{ - u32 filter_pos; - int i; - - if (udi_filter->action == UfSigFil_AllOn) - { - for (i = 0; i < SIG_FILTER_SIZE; i++) { - pcli->signal_filter[i] = 0xFFFF; - } - } - else if (udi_filter->action == UfSigFil_AllOff) - { - for (i = 0; i < SIG_FILTER_SIZE; i++) { - pcli->signal_filter[i] = 0; - } - } - else if (udi_filter->action == UfSigFil_SelectOn) - { - for (i = 0; i < udi_filter->num_sig_ids; i++) { - filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); - if (filter_pos == 0xFFFFFFFF) - { - printk(KERN_WARNING - "Unrecognised signal id (0x%X) specifed in logging filter\n", - udi_filter->sig_ids[i]); - } else { - pcli->signal_filter[filter_pos >> 16] |= (filter_pos & 0xFFFF); - } - } - } - else if (udi_filter->action == UfSigFil_SelectOff) - { - for (i = 0; i < udi_filter->num_sig_ids; i++) { - filter_pos = SigGetFilterPos(udi_filter->sig_ids[i]); - if (filter_pos == 0xFFFFFFFF) - { - printk(KERN_WARNING - "Unrecognised signal id (0x%X) specifed in logging filter\n", - udi_filter->sig_ids[i]); - } else { - pcli->signal_filter[filter_pos >> 16] &= ~(filter_pos & 0xFFFF); - } - } - } - -} /* udi_set_log_filter() */ - - -/* - * --------------------------------------------------------------------------- - * udi_log_event - * - * Callback function to be registered as the UDI hook callback. - * Copies the signal content into a new udi_log_t struct and adds - * it to the read queue for this UDI client. - * - * Arguments: - * pcli A pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointers to any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -udi_log_event(ul_client_t *pcli, - const u8 *signal, int signal_len, - const bulk_data_param_t *bulkdata, - int dir) -{ - udi_log_t *logptr; - u8 *p; - int i; - int total_len; - udi_msg_t *msgptr; - u32 filter_pos; -#ifdef OMNICLI_LINUX_EXTRA_LOG - static volatile unsigned int printk_cpu = UINT_MAX; - unsigned long long t; - unsigned long nanosec_rem; - unsigned long n_1000; -#endif - - /* Just a sanity check */ - if ((signal == NULL) || (signal_len <= 0)) { - return; - } - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - /* When HIP offline signal logging is enabled, omnicli cannot run */ - if (log_hip_signals) - { - /* Add timestamp */ - if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP) - { - int timestamp = jiffies_to_msecs(jiffies); - unifi_debug_log_to_buf("T:"); - unifi_debug_log_to_buf("%04X%04X ", *(((u16*)×tamp) + 1), - *(u16*)×tamp); - } - - /* Add signal */ - unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ", - dir ? "T" : "F", - *(u16*)signal, - *(u16*)(signal + 2), - *(u16*)(signal + 4)); - unifi_debug_hex_to_buf(signal + 6, signal_len - 6); - - /* Add bulk data (assume 1 bulk data per signal) */ - if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) && - (bulkdata->d[0].data_length > 0)) - { - unifi_debug_log_to_buf("\nD:"); - unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length); - } - unifi_debug_log_to_buf("\n"); - - return; - } -#endif - -#ifdef CSR_NATIVE_LINUX - uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir); -#endif - - /* - * Apply the logging filter - only report signals that have their - * bit set in the filter mask. - */ - filter_pos = SigGetFilterPos(GET_SIGNAL_ID(signal)); - - if ((filter_pos != 0xFFFFFFFF) && - ((pcli->signal_filter[filter_pos >> 16] & (filter_pos & 0xFFFF)) == 0)) - { - /* Signal is not wanted by client */ - return; - } - - - /* Calculate the buffer we need to store signal plus bulk data */ - total_len = signal_len; - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - total_len += bulkdata->d[i].data_length; - } - - /* Allocate log structure plus actual signal. */ - logptr = kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL); - - if (logptr == NULL) { - printk(KERN_ERR - "Failed to allocate %lu bytes for a UDI log record\n", - (long unsigned int)(sizeof(udi_log_t) + total_len)); - return; - } - - /* Fill in udi_log struct */ - INIT_LIST_HEAD(&logptr->q); - msgptr = &logptr->msg; - msgptr->length = sizeof(udi_msg_t) + total_len; -#ifdef OMNICLI_LINUX_EXTRA_LOG - t = cpu_clock(printk_cpu); - nanosec_rem = do_div(t, 1000000000); - n_1000 = nanosec_rem/1000; - msgptr->timestamp = (t <<10 ) | ((unsigned long)(n_1000 >> 10) & 0x3ff); -#else - msgptr->timestamp = jiffies_to_msecs(jiffies); -#endif - msgptr->direction = dir; - msgptr->signal_length = signal_len; - - /* Copy signal and bulk data to the log */ - p = (u8 *)(msgptr + 1); - memcpy(p, signal, signal_len); - p += signal_len; - - /* Append any bulk data */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - int len = bulkdata->d[i].data_length; - - /* - * Len here might not be the same as the length in the bulk data slot. - * The slot length will always be even, but len could be odd. - */ - if (len > 0) { - if (bulkdata->d[i].os_data_ptr) { - memcpy(p, bulkdata->d[i].os_data_ptr, len); - } else { - memset(p, 0, len); - } - p += len; - } - } - - /* Add to tail of log queue */ - if (down_interruptible(&pcli->udi_sem)) { - printk(KERN_WARNING "udi_log_event_q: Failed to get udi sem\n"); - kfree(logptr); - return; - } - list_add_tail(&logptr->q, &pcli->udi_log); - up(&pcli->udi_sem); - - /* Wake any waiting user process */ - wake_up_interruptible(&pcli->udi_wq); - -} /* udi_log_event() */ - -#ifdef CSR_SME_USERSPACE -int -uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length) -{ - udi_log_t *logptr; - udi_msg_t *msgptr; - u8 *p; - - /* Just a sanity check */ - if ((buffer == NULL) || (length <= 0)) { - return -EINVAL; - } - - /* Allocate log structure plus actual signal. */ - logptr = kmalloc(sizeof(udi_log_t) + length, GFP_ATOMIC); - if (logptr == NULL) { - unifi_error(priv, "Failed to allocate %d bytes for an SME message\n", - sizeof(udi_log_t) + length); - kfree(buffer); - return -ENOMEM; - } - - /* Fill in udi_log struct */ - INIT_LIST_HEAD(&logptr->q); - msgptr = &logptr->msg; - msgptr->length = sizeof(udi_msg_t) + length; - msgptr->signal_length = length; - - /* Copy signal and bulk data to the log */ - p = (u8 *)(msgptr + 1); - memcpy(p, buffer, length); - - /* Add to tail of log queue */ - down(&udi_mutex); - if (priv->sme_cli == NULL) { - kfree(logptr); - kfree(buffer); - up(&udi_mutex); - unifi_info(priv, "Message for the SME dropped, SME has gone away\n"); - return 0; - } - - down(&priv->sme_cli->udi_sem); - list_add_tail(&logptr->q, &priv->sme_cli->udi_log); - up(&priv->sme_cli->udi_sem); - - /* Wake any waiting user process */ - wake_up_interruptible(&priv->sme_cli->udi_wq); - up(&udi_mutex); - - /* It is our responsibility to free the buffer allocated in build_packed_*() */ - kfree(buffer); - - return 0; - -} /* uf_sme_queue_message() */ -#endif - -/* - **************************************************************************** - * - * Driver instantiation - * - **************************************************************************** - */ -static const struct file_operations unifi_fops = { - .owner = THIS_MODULE, - .open = unifi_open, - .release = unifi_release, - .read = unifi_read, - .write = unifi_write, - .unlocked_ioctl = unifi_ioctl, - .poll = unifi_poll, -}; - -static dev_t unifi_first_devno; -static struct class *unifi_class; - - -int uf_create_device_nodes(unifi_priv_t *priv, int bus_id) -{ - dev_t devno; - int r; - - cdev_init(&priv->unifi_cdev, &unifi_fops); - - /* cdev_init() should set the cdev owner, but it does not */ - priv->unifi_cdev.owner = THIS_MODULE; - - devno = MKDEV(MAJOR(unifi_first_devno), - MINOR(unifi_first_devno) + (bus_id * 2)); - r = cdev_add(&priv->unifi_cdev, devno, 1); - if (r) { - return r; - } - -#ifdef SDIO_EXPORTS_STRUCT_DEVICE - if (!device_create(unifi_class, priv->unifi_device, - devno, priv, "unifi%d", bus_id)) { -#else - priv->unifi_device = device_create(unifi_class, NULL, - devno, priv, "unifi%d", bus_id); - if (priv->unifi_device == NULL) { -#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ - - cdev_del(&priv->unifi_cdev); - return -EINVAL; - } - - cdev_init(&priv->unifiudi_cdev, &unifi_fops); - - /* cdev_init() should set the cdev owner, but it does not */ - priv->unifiudi_cdev.owner = THIS_MODULE; - - devno = MKDEV(MAJOR(unifi_first_devno), - MINOR(unifi_first_devno) + (bus_id * 2) + 1); - r = cdev_add(&priv->unifiudi_cdev, devno, 1); - if (r) { - device_destroy(unifi_class, priv->unifi_cdev.dev); - cdev_del(&priv->unifi_cdev); - return r; - } - - if (!device_create(unifi_class, -#ifdef SDIO_EXPORTS_STRUCT_DEVICE - priv->unifi_device, -#else - NULL, -#endif /* SDIO_EXPORTS_STRUCT_DEVICE */ - devno, priv, "unifiudi%d", bus_id)) { - device_destroy(unifi_class, priv->unifi_cdev.dev); - cdev_del(&priv->unifiudi_cdev); - cdev_del(&priv->unifi_cdev); - return -EINVAL; - } - - return 0; -} - - -void uf_destroy_device_nodes(unifi_priv_t *priv) -{ - device_destroy(unifi_class, priv->unifiudi_cdev.dev); - device_destroy(unifi_class, priv->unifi_cdev.dev); - cdev_del(&priv->unifiudi_cdev); - cdev_del(&priv->unifi_cdev); -} - - - -/* - * ---------------------------------------------------------------- - * uf_create_debug_device - * - * Allocates device numbers for unifi character device nodes - * and creates a unifi class in sysfs - * - * Arguments: - * fops Pointer to the char device operations structure. - * - * Returns: - * 0 on success, -ve error code on error. - * ---------------------------------------------------------------- - */ -static int -uf_create_debug_device(const struct file_operations *fops) -{ - int ret; - - /* Allocate two device numbers for each device. */ - ret = alloc_chrdev_region(&unifi_first_devno, 0, MAX_UNIFI_DEVS*2, UNIFI_NAME); - if (ret) { - unifi_error(NULL, "Failed to add alloc dev numbers: %d\n", ret); - return ret; - } - - /* Create a UniFi class */ - unifi_class = class_create(THIS_MODULE, UNIFI_NAME); - if (IS_ERR(unifi_class)) { - unifi_error(NULL, "Failed to create UniFi class\n"); - - /* Release device numbers */ - unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); - unifi_first_devno = 0; - return -EINVAL; - } - - return 0; -} /* uf_create_debug_device() */ - - -/* - * ---------------------------------------------------------------- - * uf_remove_debug_device - * - * Destroys the unifi class and releases the allocated - * device numbers for unifi character device nodes. - * - * Arguments: - * - * Returns: - * ---------------------------------------------------------------- - */ -static void -uf_remove_debug_device(void) -{ - /* Destroy the UniFi class */ - class_destroy(unifi_class); - - /* Release device numbers */ - unregister_chrdev_region(unifi_first_devno, MAX_UNIFI_DEVS*2); - unifi_first_devno = 0; - -} /* uf_remove_debug_device() */ - - -/* - * --------------------------------------------------------------------------- - * - * Module loading. - * - * --------------------------------------------------------------------------- - */ -int __init -unifi_load(void) -{ - int r; - - printk("UniFi SDIO Driver: %s %s %s\n", - CSR_WIFI_VERSION, - __DATE__, __TIME__); - -#ifdef CSR_SME_USERSPACE -#ifdef CSR_SUPPORT_WEXT - printk("CSR SME with WEXT support\n"); -#else - printk("CSR SME no WEXT support\n"); -#endif /* CSR_SUPPORT_WEXT */ -#endif /* CSR_SME_USERSPACE */ - -#ifdef CSR_NATIVE_LINUX -#ifdef CSR_SUPPORT_WEXT -#error WEXT unsupported in the native driver -#endif - printk("CSR native no WEXT support\n"); -#endif -#ifdef CSR_WIFI_SPLIT_PATCH - printk("Split patch support\n"); -#endif - printk("Kernel %d.%d.%d\n", - ((LINUX_VERSION_CODE) >> 16) & 0xff, - ((LINUX_VERSION_CODE) >> 8) & 0xff, - (LINUX_VERSION_CODE) & 0xff); - /* - * Instantiate the /dev/unifi* device nodes. - * We must do this before registering with the SDIO driver because it - * will immediately call the "insert" callback if the card is - * already present. - */ - r = uf_create_debug_device(&unifi_fops); - if (r) { - return r; - } - - /* Now register with the SDIO driver */ - r = uf_sdio_load(); - if (r) { - uf_remove_debug_device(); - return r; - } - - if (sdio_block_size > -1) { - unifi_info(NULL, "sdio_block_size %d\n", sdio_block_size); - } - - if (sdio_byte_mode) { - unifi_info(NULL, "sdio_byte_mode\n"); - } - - if (disable_power_control) { - unifi_info(NULL, "disable_power_control\n"); - } - - if (disable_hw_reset) { - unifi_info(NULL, "disable_hw_reset\n"); - } - - if (enable_wol) { - unifi_info(NULL, "enable_wol %d\n", enable_wol); - } - - if (run_bh_once != -1) { - unifi_info(NULL, "run_bh_once %d\n", run_bh_once); - } - - return 0; -} /* unifi_load() */ - - -void __exit -unifi_unload(void) -{ - /* The SDIO remove hook will call unifi_disconnect(). */ - uf_sdio_unload(); - - uf_remove_debug_device(); - -} /* unifi_unload() */ - -module_init(unifi_load); -module_exit(unifi_unload); - -MODULE_DESCRIPTION("UniFi Device driver"); -MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c deleted file mode 100644 index b42a4d6a0c36..000000000000 --- a/drivers/staging/csr/firmware.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: firmware.c - * - * PURPOSE: - * Implements the f/w related HIP core lib API. - * It is part of the porting exercise in Linux. - * - * Also, it contains example code for reading the loader and f/w files - * from the userspace and starting the SME in Linux. - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include -#include -#include -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifi_udi.h" -#include "unifiio.h" -#include "unifi_priv.h" - -/* - * --------------------------------------------------------------------------- - * - * F/W download. Part of the HIP core API - * - * --------------------------------------------------------------------------- - */ - - -/* - * --------------------------------------------------------------------------- - * unifi_fw_read_start - * - * Returns a structure to be passed in unifi_fw_read(). - * This structure is an OS specific description of the f/w file. - * In the linux implementation it is a buffer with the f/w and its' length. - * The HIP driver calls this functions to request for the loader or - * the firmware file. - * The structure pointer can be freed when unifi_fw_read_stop() is called. - * - * Arguments: - * ospriv Pointer to driver context. - * is_fw Type of firmware to retrieve - * info Versions information. Can be used to determine - * the appropriate f/w file to load. - * - * Returns: - * O on success, non-zero otherwise. - * - * --------------------------------------------------------------------------- - */ -void* -unifi_fw_read_start(void *ospriv, s8 is_fw, const card_info_t *info) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - CSR_UNUSED(info); - - if (is_fw == UNIFI_FW_STA) { - /* F/w may have been released after a previous successful download. */ - if (priv->fw_sta.dl_data == NULL) { - unifi_trace(priv, UDBG2, "Attempt reload of sta f/w\n"); - uf_request_firmware_files(priv, UNIFI_FW_STA); - } - /* Set up callback struct for readfunc() */ - if (priv->fw_sta.dl_data != NULL) { - return &priv->fw_sta; - } - - } else { - unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw); - } - - return NULL; -} /* unifi_fw_read_start() */ - - - -/* - * --------------------------------------------------------------------------- - * unifi_fw_read_stop - * - * Called when the HIP driver has finished using the loader or - * the firmware file. - * The firmware buffer may be released now. - * - * Arguments: - * ospriv Pointer to driver context. - * dlpriv The pointer returned by unifi_fw_read_start() - * - * --------------------------------------------------------------------------- - */ -void -unifi_fw_read_stop(void *ospriv, void *dlpriv) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - struct dlpriv *dl_struct = (struct dlpriv *)dlpriv; - - if (dl_struct != NULL) { - if (dl_struct->dl_data != NULL) { - unifi_trace(priv, UDBG2, "Release f/w buffer %p, %d bytes\n", - dl_struct->dl_data, dl_struct->dl_len); - } - uf_release_firmware(priv, dl_struct); - } - -} /* unifi_fw_read_stop() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_fw_open_buffer - * - * Returns a handle for a buffer dynamically allocated by the driver, - * e.g. into which a firmware file may have been converted from another format - * which is the case with some production test images. - * - * The handle may then be used by unifi_fw_read() to access the contents of - * the buffer. - * - * Arguments: - * ospriv Pointer to driver context. - * fwbuf Buffer containing firmware image - * len Length of buffer in bytes - * - * Returns - * Handle for buffer, or NULL on error - * --------------------------------------------------------------------------- - */ -void * -unifi_fw_open_buffer(void *ospriv, void *fwbuf, u32 len) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - if (fwbuf == NULL) { - return NULL; - } - priv->fw_conv.dl_data = fwbuf; - priv->fw_conv.dl_len = len; - priv->fw_conv.fw_desc = NULL; /* No OS f/w resource is associated */ - - return &priv->fw_conv; -} - -/* - * --------------------------------------------------------------------------- - * unifi_fw_close_buffer - * - * Releases any handle for a buffer dynamically allocated by the driver, - * e.g. into which a firmware file may have been converted from another format - * which is the case with some production test images. - * - * - * Arguments: - * ospriv Pointer to driver context. - * fwbuf Buffer containing firmware image - * - * Returns - * Handle for buffer, or NULL on error - * --------------------------------------------------------------------------- - */ -void unifi_fw_close_buffer(void *ospriv, void *fwbuf) -{ -} - -/* - * --------------------------------------------------------------------------- - * unifi_fw_read - * - * The HIP driver calls this function to ask for a part of the loader or - * the firmware file. - * - * Arguments: - * ospriv Pointer to driver context. - * arg The pointer returned by unifi_fw_read_start(). - * offset The offset in the file to return from. - * buf A buffer to store the requested data. - * len The size of the buf and the size of the requested data. - * - * Returns - * The number of bytes read from the firmware image, or -ve on error - * --------------------------------------------------------------------------- - */ -s32 -unifi_fw_read(void *ospriv, void *arg, u32 offset, void *buf, u32 len) -{ - const struct dlpriv *dlpriv = arg; - - if (offset >= dlpriv->dl_len) { - /* at end of file */ - return 0; - } - - if ((offset + len) > dlpriv->dl_len) { - /* attempt to read past end of file */ - return -1; - } - - memcpy(buf, dlpriv->dl_data+offset, len); - - return len; - -} /* unifi_fw_read() */ - - - - -#define UNIFIHELPER_INIT_MODE_SMEUSER 2 -#define UNIFIHELPER_INIT_MODE_NATIVE 1 - -/* - * --------------------------------------------------------------------------- - * uf_run_unifihelper - * - * Ask userspace to send us firmware for download by running - * '/usr/sbin/unififw'. - * The same script starts the SME userspace application. - * Derived from net_run_sbin_hotplug(). - * - * Arguments: - * priv Pointer to OS private struct. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int -uf_run_unifihelper(unifi_priv_t *priv) -{ -#ifdef ANDROID_BUILD - char *prog = "/system/bin/unififw"; -#else - char *prog = "/usr/sbin/unififw"; -#endif /* ANDROID_BUILD */ - - char *argv[6], *envp[4]; - char inst_str[8]; - char init_mode[8]; - int i, r; - -#if (defined CSR_SME_USERSPACE) && (!defined CSR_SUPPORT_WEXT) - unifi_trace(priv, UDBG1, "SME userspace build: run unifi_helper manually\n"); - return 0; -#endif - - unifi_trace(priv, UDBG1, "starting %s\n", prog); - - snprintf(inst_str, 8, "%d", priv->instance); -#if (defined CSR_SME_USERSPACE) - snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_SMEUSER); -#else - snprintf(init_mode, 8, "%d", UNIFIHELPER_INIT_MODE_NATIVE); -#endif /* CSR_SME_USERSPACE */ - - i = 0; - argv[i++] = prog; - argv[i++] = inst_str; - argv[i++] = init_mode; - argv[i++] = 0; - argv[i] = 0; - /* Don't add more args without making argv bigger */ - - /* minimal command environment */ - i = 0; - envp[i++] = "HOME=/"; - envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - envp[i] = 0; - /* Don't add more without making envp bigger */ - - unifi_trace(priv, UDBG2, "running %s %s %s\n", argv[0], argv[1], argv[2]); - - r = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); - - return r; -} /* uf_run_unifihelper() */ - -#ifdef CSR_WIFI_SPLIT_PATCH -static u8 is_ap_mode(unifi_priv_t *priv) -{ - if (priv == NULL || priv->interfacePriv[0] == NULL) - { - return FALSE; - } - - /* Test for mode requiring AP patch */ - return(CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode)); -} -#endif - -/* - * --------------------------------------------------------------------------- - * uf_request_firmware_files - * - * Get the firmware files from userspace. - * - * Arguments: - * priv Pointer to OS private struct. - * is_fw type of firmware to load (UNIFI_FW_STA/LOADER) - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int uf_request_firmware_files(unifi_priv_t *priv, int is_fw) -{ - /* uses the default method to get the firmware */ - const struct firmware *fw_entry; - int postfix; -#define UNIFI_MAX_FW_PATH_LEN 32 - char fw_name[UNIFI_MAX_FW_PATH_LEN]; - int r; - -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - if (priv->mib_data.length) { - vfree(priv->mib_data.data); - priv->mib_data.data = NULL; - priv->mib_data.length = 0; - } -#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/ - - postfix = priv->instance; - - if (is_fw == UNIFI_FW_STA) { - /* Free kernel buffer and reload */ - uf_release_firmware(priv, &priv->fw_sta); -#ifdef CSR_WIFI_SPLIT_PATCH - scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", - postfix, (is_ap_mode(priv) ? "ap.xbv" : "staonly.xbv") ); -#else - scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", - postfix, "sta.xbv" ); -#endif - r = request_firmware(&fw_entry, fw_name, priv->unifi_device); - if (r == 0) { - priv->fw_sta.dl_data = fw_entry->data; - priv->fw_sta.dl_len = fw_entry->size; - priv->fw_sta.fw_desc = (void *)fw_entry; - } else { - unifi_trace(priv, UDBG2, "Firmware file not available\n"); - } - } - - return 0; - -} /* uf_request_firmware_files() */ - -/* - * --------------------------------------------------------------------------- - * uf_release_firmware_files - * - * Release all buffers used to store firmware files - * - * Arguments: - * priv Pointer to OS private struct. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int uf_release_firmware_files(unifi_priv_t *priv) -{ - uf_release_firmware(priv, &priv->fw_sta); - - return 0; -} - -/* - * --------------------------------------------------------------------------- - * uf_release_firmware - * - * Release specific buffer used to store firmware - * - * Arguments: - * priv Pointer to OS private struct. - * to_free Pointer to specific buffer to release - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free) -{ - if (to_free != NULL) { - release_firmware((const struct firmware *)to_free->fw_desc); - to_free->fw_desc = NULL; - to_free->dl_data = NULL; - to_free->dl_len = 0; - } - return 0; -} diff --git a/drivers/staging/csr/inet.c b/drivers/staging/csr/inet.c deleted file mode 100644 index b3ef818fef35..000000000000 --- a/drivers/staging/csr/inet.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: inet.c - * - * PURPOSE: - * Routines related to IP address changes. - * Optional part of the porting exercise. It uses system network - * handlers to obtain the UniFi IP address and pass it to the SME - * using the unifi_sys_ip_configured_ind(). - * - * Copyright (C) 2008-2009 Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include -#include - -#include "unifi_priv.h" -#include "csr_wifi_hip_conversions.h" - -/* - * The inet notifier is global and not per-netdev. To avoid having a - * notifier registered when there are no unifi devices present, it's - * registered after the first unifi network device is registered, and - * unregistered when the last unifi network device is unregistered. - */ - -static atomic_t inet_notif_refs = ATOMIC_INIT(0); - -static int uf_inetaddr_event(struct notifier_block *notif, unsigned long event, void *ifa) -{ - struct net_device *ndev; - unifi_priv_t *priv; - struct in_ifaddr *if_addr; - netInterface_priv_t *InterfacePriv = (netInterface_priv_t *)NULL; - - if (!ifa || !((struct in_ifaddr *)ifa)->ifa_dev) { - unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ifa=%p\n", event, ifa); - return NOTIFY_DONE; - } - - ndev = ((struct in_ifaddr *)ifa)->ifa_dev->dev; - InterfacePriv = (netInterface_priv_t*) netdev_priv(ndev); - - /* As the notifier is global, the call may be for a non-UniFi netdev. - * Therefore check the netdev_priv to make sure it's a known UniFi one. - */ - if (uf_find_netdev_priv(InterfacePriv) == -1) { - unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ndev=%p, other netdev_priv=%p\n", - event, ndev, InterfacePriv); - return NOTIFY_DONE; - } - - if (!InterfacePriv->privPtr) { - unifi_error(NULL, "uf_inetaddr_event null priv (%lu) ndev=%p, InterfacePriv=%p\n", - event, ndev, InterfacePriv); - return NOTIFY_DONE; - } - - priv = InterfacePriv->privPtr; - if_addr = (struct in_ifaddr *)ifa; - - /* If this event is for a UniFi device, notify the SME that an IP - * address has been added or removed. */ - if (uf_find_priv(priv) != -1) { - switch (event) { - case NETDEV_UP: - unifi_info(priv, "IP address assigned for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); - priv->sta_ip_address = if_addr->ifa_address; -#ifdef CSR_SUPPORT_WEXT - sme_mgt_packet_filter_set(priv); -#endif - break; - case NETDEV_DOWN: - unifi_info(priv, "IP address removed for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); - priv->sta_ip_address = 0xFFFFFFFF; -#ifdef CSR_SUPPORT_WEXT - sme_mgt_packet_filter_set(priv); -#endif - break; - } - } - - return NOTIFY_DONE; -} - -static struct notifier_block uf_inetaddr_notifier = { - .notifier_call = uf_inetaddr_event, -}; - -void uf_register_inet_notifier(void) -{ - if (atomic_inc_return(&inet_notif_refs) == 1) - register_inetaddr_notifier(&uf_inetaddr_notifier); -} - -void uf_unregister_inet_notifier(void) -{ - if (atomic_dec_return(&inet_notif_refs) == 0) - unregister_inetaddr_notifier(&uf_inetaddr_notifier); -} diff --git a/drivers/staging/csr/init_hw.c b/drivers/staging/csr/init_hw.c deleted file mode 100644 index 3b8a4babf9a6..000000000000 --- a/drivers/staging/csr/init_hw.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: init_hw.c - * - * PURPOSE: - * Use the HIP core lib to initialise the UniFi chip. - * It is part of the porting exercise in Linux. - * - * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include "csr_wifi_hip_unifi.h" -#include "unifi_priv.h" - - -#define MAX_INIT_ATTEMPTS 4 - -extern int led_mask; - - -/* - * --------------------------------------------------------------------------- - * uf_init_hw - * - * Resets hardware, downloads and initialises f/w. - * This function demonstrates how to use the HIP core lib API - * to implement the SME unifi_sys_wifi_on_req() part of the SYS API. - * - * In a simple implementation, all this function needs to do is call - * unifi_init_card() and then unifi_card_info(). - * In the Linux implementation, it will retry to initialise UniFi or - * try to debug the reasons if unifi_init_card() returns an error. - * - * Arguments: - * ospriv Pointer to OS driver structure for the device. - * - * Returns: - * O on success, non-zero otherwise. - * - * --------------------------------------------------------------------------- - */ -int -uf_init_hw(unifi_priv_t *priv) -{ - int attempts = 0; - int priv_instance; - CsrResult csrResult = CSR_RESULT_FAILURE; - - priv_instance = uf_find_priv(priv); - if (priv_instance == -1) { - unifi_warning(priv, "uf_init_hw: Unknown priv instance, will use fw_init[0]\n"); - priv_instance = 0; - } - - while (1) { - if (attempts > MAX_INIT_ATTEMPTS) { - unifi_error(priv, "Failed to initialise UniFi after %d attempts, " - "giving up.\n", - attempts); - break; - } - attempts++; - - unifi_info(priv, "Initialising UniFi, attempt %d\n", attempts); - - if (fw_init[priv_instance] > 0) { - unifi_notice(priv, "f/w init prevented by module parameter\n"); - break; - } else if (fw_init[priv_instance] == 0) { - fw_init[priv_instance] ++; - } - - /* - * Initialise driver core. This will perform a reset of UniFi - * internals, but not the SDIO CCCR. - */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_init_card(priv->card, led_mask); - CsrSdioRelease(priv->sdio); - - if (csrResult == CSR_WIFI_HIP_RESULT_NO_DEVICE) { - return CsrHipResultToStatus(csrResult); - } - if (csrResult == CSR_WIFI_HIP_RESULT_NOT_FOUND) { - unifi_error(priv, "Firmware file required, but not found.\n"); - return CsrHipResultToStatus(csrResult); - } - if (csrResult != CSR_RESULT_SUCCESS) { - /* failed. Reset h/w and try again */ - unifi_error(priv, "Failed to initialise UniFi chip.\n"); - continue; - } - - /* Get the version information from the lib_hip */ - unifi_card_info(priv->card, &priv->card_info); - - return CsrHipResultToStatus(csrResult); - } - - return CsrHipResultToStatus(csrResult); - -} /* uf_init_hw */ - - diff --git a/drivers/staging/csr/io.c b/drivers/staging/csr/io.c deleted file mode 100644 index f903022b4079..000000000000 --- a/drivers/staging/csr/io.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: io.c - * - * PURPOSE: - * This file contains routines that the SDIO driver can call when a - * UniFi card is first inserted (or detected) and removed. - * - * When used with sdioemb, the udev scripts (at least on Ubuntu) don't - * recognise a UniFi being added to the system. This is because sdioemb - * does not register itself as a device_driver, it uses it's own code - * to handle insert and remove. - * To have Ubuntu recognise UniFi, edit /etc/udev/rules.d/85-ifupdown.rules - * to change this line: - * SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" - * to these: - * #SUBSYSTEM=="net", DRIVERS=="?*", GOTO="net_start" - * SUBSYSTEM=="net", GOTO="net_start" - * - * Then you can add a stanza to /etc/network/interfaces like this: - * auto eth1 - * iface eth1 inet dhcp - * wpa-conf /etc/wpa_supplicant.conf - * This will then automatically associate when a car dis inserted. - * - * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include -#include - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifiversion.h" -#include "csr_wifi_hip_unifi_udi.h" /* for unifi_print_status() */ -#include "unifiio.h" -#include "unifi_priv.h" - -/* - * Array of pointers to context structs for unifi devices that are present. - * The index in the array corresponds to the wlan interface number - * (if "wlan*" is used). If "eth*" is used, the eth* numbers are allocated - * after any Ethernet cards. - * - * The Arasan PCI-SDIO controller card supported by this driver has 2 slots, - * hence a max of 2 devices. - */ -static unifi_priv_t *Unifi_instances[MAX_UNIFI_DEVS]; - -/* Array of pointers to netdev objects used by the UniFi driver, as there - * are now many per instance. This is used to determine which netdev events - * are for UniFi as opposed to other net interfaces. - */ -static netInterface_priv_t *Unifi_netdev_instances[MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES]; - -/* - * Array to hold the status of each unifi device in each slot. - * We only process an insert event when In_use[] for the slot is - * UNIFI_DEV_NOT_IN_USE. Otherwise, it means that the slot is in use or - * we are in the middle of a cleanup (the action on unplug). - */ -#define UNIFI_DEV_NOT_IN_USE 0 -#define UNIFI_DEV_IN_USE 1 -#define UNIFI_DEV_CLEANUP 2 -static int In_use[MAX_UNIFI_DEVS]; -/* - * Mutex to prevent UDI clients to open the character device before the priv - * is created and initialised. - */ -DEFINE_SEMAPHORE(Unifi_instance_mutex); -/* - * When the device is removed, unregister waits on Unifi_cleanup_wq - * until all the UDI clients release the character device. - */ -DECLARE_WAIT_QUEUE_HEAD(Unifi_cleanup_wq); - -#ifdef CONFIG_PROC_FS -/* - * seq_file wrappers for procfile show routines. - */ -static int uf_proc_show(struct seq_file *m, void *v); - -#define UNIFI_DEBUG_TXT_BUFFER (8 * 1024) - -static int uf_proc_open(struct inode *inode, struct file *file) -{ - return single_open_size(file, uf_proc_show, PDE_DATA(inode), - UNIFI_DEBUG_TXT_BUFFER); -} - -static const struct file_operations uf_proc_fops = { - .open = uf_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* CONFIG_PROC_FS */ - -#ifdef CSR_WIFI_RX_PATH_SPLIT - -static CsrResult signal_buffer_init(unifi_priv_t * priv, int size) -{ - int i; - - priv->rxSignalBuffer.writePointer = - priv->rxSignalBuffer.readPointer = 0; - priv->rxSignalBuffer.size = size; - /* Allocating Memory for Signal primitive pointer */ - for(i=0; irxSignalBuffer.rx_buff[i].sig_len=0; - priv->rxSignalBuffer.rx_buff[i].bufptr = kmalloc(UNIFI_PACKED_SIGBUF_SIZE, GFP_KERNEL); - if (priv->rxSignalBuffer.rx_buff[i].bufptr == NULL) - { - int j; - unifi_error(priv, "signal_buffer_init:Failed to Allocate shared memory for T-H signals \n"); - for(j=0;jrxSignalBuffer.rx_buff[j].sig_len=0; - kfree(priv->rxSignalBuffer.rx_buff[j].bufptr); - priv->rxSignalBuffer.rx_buff[j].bufptr = NULL; - } - return -1; - } - } - return 0; -} - - -static void signal_buffer_free(unifi_priv_t * priv, int size) -{ - int i; - - for(i=0; irxSignalBuffer.rx_buff[i].sig_len=0; - kfree(priv->rxSignalBuffer.rx_buff[i].bufptr); - priv->rxSignalBuffer.rx_buff[i].bufptr = NULL; - } -} -#endif -/* - * --------------------------------------------------------------------------- - * uf_register_netdev - * - * Registers the network interface, installes the qdisc, - * and registers the inet handler. - * In the porting exercise, register the driver to the network - * stack if necessary. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * O on success, non-zero otherwise. - * - * Notes: - * We will only unregister when the card is ejected, so we must - * only do it once. - * --------------------------------------------------------------------------- - */ -int -uf_register_netdev(unifi_priv_t *priv, int interfaceTag) -{ - int r; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_register_netdev bad interfaceTag\n"); - return -EINVAL; - } - - /* - * Allocates a device number and registers device with the network - * stack. - */ - unifi_trace(priv, UDBG5, "uf_register_netdev: netdev %d - 0x%p\n", - interfaceTag, priv->netdev[interfaceTag]); - r = register_netdev(priv->netdev[interfaceTag]); - if (r) { - unifi_error(priv, "Failed to register net device\n"); - return -EINVAL; - } - - /* The device is registed */ - interfacePriv->netdev_registered = 1; - -#ifdef CSR_SUPPORT_SME - /* - * Register the inet handler; it notifies us for changes in the IP address. - */ - uf_register_inet_notifier(); -#endif /* CSR_SUPPORT_SME */ - - unifi_notice(priv, "unifi%d is %s\n", - priv->instance, priv->netdev[interfaceTag]->name); - - return 0; -} /* uf_register_netdev */ - - -/* - * --------------------------------------------------------------------------- - * uf_unregister_netdev - * - * Unregisters the network interface and the inet handler. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * None. - * - * --------------------------------------------------------------------------- - */ -void -uf_unregister_netdev(unifi_priv_t *priv) -{ - int i=0; - -#ifdef CSR_SUPPORT_SME - /* Unregister the inet handler... */ - uf_unregister_inet_notifier(); -#endif /* CSR_SUPPORT_SME */ - - for (i=0; iinterfacePriv[i]; - if (interfacePriv->netdev_registered) { - unifi_trace(priv, UDBG5, - "uf_unregister_netdev: netdev %d - 0x%p\n", - i, priv->netdev[i]); - - /* ... and the netdev */ - unregister_netdev(priv->netdev[i]); - interfacePriv->netdev_registered = 0; - } - - interfacePriv->interfaceMode = 0; - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - } - - priv->totalInterfaceCount = 0; -} /* uf_unregister_netdev() */ - - -/* - * --------------------------------------------------------------------------- - * register_unifi_sdio - * - * This function is called from the Probe (or equivalent) method of - * the SDIO driver when a UniFi card is detected. - * We allocate the Linux net_device struct, initialise the HIP core - * lib, create the char device nodes and start the userspace helper - * to initialise the device. - * - * Arguments: - * sdio_dev Pointer to SDIO context handle to use for all - * SDIO ops. - * bus_id A small number indicating the SDIO card position on the - * bus. Typically this is the slot number, e.g. 0, 1 etc. - * Valid values are 0 to MAX_UNIFI_DEVS-1. - * dev Pointer to kernel device manager struct. - * - * Returns: - * Pointer to the unifi instance, or NULL on error. - * --------------------------------------------------------------------------- - */ -static unifi_priv_t * -register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev) -{ - unifi_priv_t *priv = NULL; - int r = -1; - CsrResult csrResult; - - if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { - unifi_error(priv, "register_unifi_sdio: invalid device %d\n", - bus_id); - return NULL; - } - - down(&Unifi_instance_mutex); - - if (In_use[bus_id] != UNIFI_DEV_NOT_IN_USE) { - unifi_error(priv, "register_unifi_sdio: device %d is already in use\n", - bus_id); - goto failed0; - } - - - /* Allocate device private and net_device structs */ - priv = uf_alloc_netdevice(sdio_dev, bus_id); - if (priv == NULL) { - unifi_error(priv, "Failed to allocate driver private\n"); - goto failed0; - } - - priv->unifi_device = dev; - - SET_NETDEV_DEV(priv->netdev[0], dev); - - /* We are not ready to send data yet. */ - netif_carrier_off(priv->netdev[0]); - - /* Allocate driver context. */ - priv->card = unifi_alloc_card(priv->sdio, priv); - if (priv->card == NULL) { - unifi_error(priv, "Failed to allocate UniFi driver card struct.\n"); - goto failed1; - } - - if (Unifi_instances[bus_id]) { - unifi_error(priv, "Internal error: instance for slot %d is already taken\n", - bus_id); - } - Unifi_instances[bus_id] = priv; - In_use[bus_id] = UNIFI_DEV_IN_USE; - - /* Save the netdev_priv for use by the netdev event callback mechanism */ - Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES] = netdev_priv(priv->netdev[0]); - - /* Initialise the mini-coredump capture buffers */ - csrResult = unifi_coredump_init(priv->card, (u16)coredump_max); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Couldn't allocate mini-coredump buffers\n"); - } - - /* Create the character device nodes */ - r = uf_create_device_nodes(priv, bus_id); - if (r) { - goto failed1; - } - - /* - * We use the slot number as unifi device index. - */ - scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance); - /* - * The following complex casting is in place in order to eliminate 64-bit compilation warning - * "cast to/from pointer from/to integer of different size" - */ - if (!proc_create_data(priv->proc_entry_name, 0, NULL, - &uf_proc_fops, (void *)(long)priv->instance)) - { - unifi_error(priv, "unifi: can't create /proc/driver/unifi\n"); - } - - /* Allocate the net_device for interfaces other than 0. */ - { - int i; - priv->totalInterfaceCount =0; - - for(i=1;inetdev[i], dev); - - /* We are not ready to send data yet. */ - netif_carrier_off(priv->netdev[i]); - - /* Save the netdev_priv for use by the netdev event callback mechanism */ - Unifi_netdev_instances[bus_id * CSR_WIFI_NUM_INTERFACES + i] = netdev_priv(priv->netdev[i]); - } - } - - for(i=0;iinterfacePriv[i]; - interfacePriv->netdev_registered=0; - } - } - -#ifdef CSR_WIFI_RX_PATH_SPLIT - if (signal_buffer_init(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE)) - { - unifi_error(priv, "Failed to allocate shared memory for T-H signals\n"); - goto failed2; - } - priv->rx_workqueue = create_singlethread_workqueue("rx_workq"); - if (priv->rx_workqueue == NULL) { - unifi_error(priv, "create_singlethread_workqueue failed \n"); - goto failed3; - } - INIT_WORK(&priv->rx_work_struct, rx_wq_handler); -#endif - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - if (log_hip_signals) - { - uf_register_hip_offline_debug(priv); - } -#endif - - /* Initialise the SME related threads and parameters */ - r = uf_sme_init(priv); - if (r) { - unifi_error(priv, "SME initialisation failed.\n"); - goto failed4; - } - - /* - * Run the userspace helper program (unififw) to perform - * the device initialisation. - */ - unifi_trace(priv, UDBG1, "run UniFi helper app...\n"); - r = uf_run_unifihelper(priv); - if (r) { - unifi_notice(priv, "unable to run UniFi helper app\n"); - /* Not a fatal error. */ - } - - up(&Unifi_instance_mutex); - - return priv; - -failed4: -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -if (log_hip_signals) -{ - uf_unregister_hip_offline_debug(priv); -} -#endif -#ifdef CSR_WIFI_RX_PATH_SPLIT - flush_workqueue(priv->rx_workqueue); - destroy_workqueue(priv->rx_workqueue); -failed3: - signal_buffer_free(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); -failed2: -#endif - /* Remove the device nodes */ - uf_destroy_device_nodes(priv); -failed1: - /* Deregister priv->netdev_client */ - ul_deregister_client(priv->netdev_client); - -failed0: - if (priv && priv->card) { - unifi_coredump_free(priv->card); - unifi_free_card(priv->card); - } - if (priv) { - uf_free_netdevice(priv); - } - - up(&Unifi_instance_mutex); - - return NULL; -} /* register_unifi_sdio() */ - - -/* - * --------------------------------------------------------------------------- - * ask_unifi_sdio_cleanup - * - * We can not free our private context, until all the char device - * clients have closed the file handles. unregister_unifi_sdio() which - * is called when a card is removed, waits on Unifi_cleanup_wq until - * the reference count becomes zero. It is time to wake it up now. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -ask_unifi_sdio_cleanup(unifi_priv_t *priv) -{ - - /* - * Now clear the flag that says the old instance is in use. - * This is used to prevent a new instance being started before old - * one has finshed closing down, for example if bounce makes the card - * appear to be ejected and re-inserted quickly. - */ - In_use[priv->instance] = UNIFI_DEV_CLEANUP; - - unifi_trace(NULL, UDBG5, "ask_unifi_sdio_cleanup: wake up cleanup workqueue.\n"); - wake_up(&Unifi_cleanup_wq); - -} /* ask_unifi_sdio_cleanup() */ - - -/* - * --------------------------------------------------------------------------- - * cleanup_unifi_sdio - * - * Release any resources owned by a unifi instance. - * - * Arguments: - * priv Pointer to the instance to free. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -cleanup_unifi_sdio(unifi_priv_t *priv) -{ - int priv_instance; - int i; - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - - /* Remove the device nodes */ - uf_destroy_device_nodes(priv); - - /* Mark this device as gone away by NULLing the entry in Unifi_instances */ - Unifi_instances[priv->instance] = NULL; - - unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: remove_proc_entry\n"); - /* - * Free the children of priv before unifi_free_netdevice() frees - * the priv struct - */ - remove_proc_entry(priv->proc_entry_name, 0); - - - /* Unregister netdev as a client. */ - if (priv->netdev_client) { - unifi_trace(priv, UDBG2, "Netdev client (id:%d s:0x%X) is unregistered\n", - priv->netdev_client->client_id, priv->netdev_client->sender_id); - ul_deregister_client(priv->netdev_client); - } - - /* Destroy the SME related threads and parameters */ - uf_sme_deinit(priv); - -#ifdef CSR_SME_USERSPACE - priv->smepriv = NULL; -#endif - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - if (log_hip_signals) - { - uf_unregister_hip_offline_debug(priv); - } -#endif - - /* Free any packets left in the Rx queues */ - for(i=0;icard) { - unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: free card\n"); - unifi_coredump_free(priv->card); - unifi_free_card(priv->card); - priv->card = NULL; - } - - /* - * Unregister the network device. - * We can not unregister the netdev before we release - * all pending packets in the core. - */ - uf_unregister_netdev(priv); - priv->totalInterfaceCount = 0; - - /* Clear the table of registered netdev_priv's */ - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - Unifi_netdev_instances[priv->instance * CSR_WIFI_NUM_INTERFACES + i] = NULL; - } - - unifi_trace(priv, UDBG5, "cleanup_unifi_sdio: uf_free_netdevice\n"); - /* - * When uf_free_netdevice() returns, the priv is invalid - * so we need to remember the instance to clear the global flag later. - */ - priv_instance = priv->instance; - -#ifdef CSR_WIFI_RX_PATH_SPLIT - flush_workqueue(priv->rx_workqueue); - destroy_workqueue(priv->rx_workqueue); - signal_buffer_free(priv, CSR_WIFI_RX_SIGNAL_BUFFER_SIZE); -#endif - - /* Priv is freed as part of the net_device */ - uf_free_netdevice(priv); - - /* - * Now clear the flag that says the old instance is in use. - * This is used to prevent a new instance being started before old - * one has finshed closing down, for example if bounce makes the card - * appear to be ejected and re-inserted quickly. - */ - In_use[priv_instance] = UNIFI_DEV_NOT_IN_USE; - - unifi_trace(NULL, UDBG5, "cleanup_unifi_sdio: DONE.\n"); - -} /* cleanup_unifi_sdio() */ - - -/* - * --------------------------------------------------------------------------- - * unregister_unifi_sdio - * - * Call from SDIO driver when it detects that UniFi has been removed. - * - * Arguments: - * bus_id Number of the card that was ejected. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -unregister_unifi_sdio(int bus_id) -{ - unifi_priv_t *priv; - int interfaceTag=0; - u8 reason = CONFIG_IND_EXIT; - - if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { - unifi_error(NULL, "unregister_unifi_sdio: invalid device %d\n", - bus_id); - return; - } - - priv = Unifi_instances[bus_id]; - if (priv == NULL) { - unifi_error(priv, "unregister_unifi_sdio: device %d is not registered\n", - bus_id); - return; - } - - /* Stop the network traffic before freeing the core. */ - for(interfaceTag=0;interfaceTagtotalInterfaceCount;interfaceTag++) - { - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - if(interfacePriv->netdev_registered) - { - netif_carrier_off(priv->netdev[interfaceTag]); - netif_tx_stop_all_queues(priv->netdev[interfaceTag]); - } - } - -#ifdef CSR_NATIVE_LINUX - /* - * If the unifi thread was started, signal it to stop. This - * should cause any userspace processes with open unifi device to - * close them. - */ - uf_stop_thread(priv, &priv->bh_thread); - - /* Unregister the interrupt handler */ - if (csr_sdio_linux_remove_irq(priv->sdio)) { - unifi_notice(priv, - "csr_sdio_linux_remove_irq failed to talk to card.\n"); - } - - /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ - uf_abort_mlme(priv); -#endif /* CSR_NATIVE_LINUX */ - - ul_log_config_ind(priv, &reason, sizeof(u8)); - - /* Deregister the UDI hook from the core. */ - unifi_remove_udi_hook(priv->card, logging_handler); - - uf_put_instance(bus_id); - - /* - * Wait until the device is cleaned up. i.e., when all userspace - * processes have closed any open unifi devices. - */ - wait_event(Unifi_cleanup_wq, In_use[bus_id] == UNIFI_DEV_CLEANUP); - unifi_trace(NULL, UDBG5, "Received clean up event\n"); - - /* Now we can free the private context and the char device nodes */ - cleanup_unifi_sdio(priv); - -} /* unregister_unifi_sdio() */ - - -/* - * --------------------------------------------------------------------------- - * uf_find_instance - * - * Find the context structure for a given UniFi device instance. - * - * Arguments: - * inst The instance number to look for. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -unifi_priv_t * -uf_find_instance(int inst) -{ - if ((inst < 0) || (inst >= MAX_UNIFI_DEVS)) { - return NULL; - } - return Unifi_instances[inst]; -} /* uf_find_instance() */ - - -/* - * --------------------------------------------------------------------------- - * uf_find_priv - * - * Find the device instance for a given context structure. - * - * Arguments: - * priv The context structure pointer to look for. - * - * Returns: - * index of instance, -1 otherwise. - * --------------------------------------------------------------------------- - */ -int -uf_find_priv(unifi_priv_t *priv) -{ - int inst; - - if (!priv) { - return -1; - } - - for (inst = 0; inst < MAX_UNIFI_DEVS; inst++) { - if (Unifi_instances[inst] == priv) { - return inst; - } - } - - return -1; -} /* uf_find_priv() */ - -/* - * --------------------------------------------------------------------------- - * uf_find_netdev_priv - * - * Find the device instance for a given netdev context structure. - * - * Arguments: - * priv The context structure pointer to look for. - * - * Returns: - * index of instance, -1 otherwise. - * --------------------------------------------------------------------------- - */ -int -uf_find_netdev_priv(netInterface_priv_t *priv) -{ - int inst; - - if (!priv) { - return -1; - } - - for (inst = 0; inst < MAX_UNIFI_DEVS * CSR_WIFI_NUM_INTERFACES; inst++) { - if (Unifi_netdev_instances[inst] == priv) { - return inst; - } - } - - return -1; -} /* uf_find_netdev_priv() */ - -/* - * --------------------------------------------------------------------------- - * uf_get_instance - * - * Find the context structure for a given UniFi device instance - * and increment the reference count. - * - * Arguments: - * inst The instance number to look for. - * - * Returns: - * Pointer to the instance or NULL if no instance exists. - * --------------------------------------------------------------------------- - */ -unifi_priv_t * -uf_get_instance(int inst) -{ - unifi_priv_t *priv; - - down(&Unifi_instance_mutex); - - priv = uf_find_instance(inst); - if (priv) { - priv->ref_count++; - } - - up(&Unifi_instance_mutex); - - return priv; -} - -/* - * --------------------------------------------------------------------------- - * uf_put_instance - * - * Decrement the context reference count, freeing resources and - * shutting down the driver when the count reaches zero. - * - * Arguments: - * inst The instance number to look for. - * - * Returns: - * Pointer to the instance or NULL if no instance exists. - * --------------------------------------------------------------------------- - */ -void -uf_put_instance(int inst) -{ - unifi_priv_t *priv; - - down(&Unifi_instance_mutex); - - priv = uf_find_instance(inst); - if (priv) { - priv->ref_count--; - if (priv->ref_count == 0) { - ask_unifi_sdio_cleanup(priv); - } - } - - up(&Unifi_instance_mutex); -} - - -/* - * --------------------------------------------------------------------------- - * uf_proc_show - * - * Read method for driver node in /proc/driver/unifi0 - * - * Arguments: - * page - * start - * offset - * count - * eof - * data - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -#ifdef CONFIG_PROC_FS -static int uf_proc_show(struct seq_file *m, void *v) -{ - unifi_priv_t *priv; - int i; - - /* - * The following complex casting is in place in order to eliminate - * 64-bit compilation warning "cast to/from pointer from/to integer of - * different size" - */ - priv = uf_find_instance((long)m->private); - if (!priv) - return 0; - - seq_printf(m, "UniFi SDIO Driver: %s %s %s\n", - CSR_WIFI_VERSION, __DATE__, __TIME__); -#ifdef CSR_SME_USERSPACE - seq_puts(m, "SME: CSR userspace "); -#ifdef CSR_SUPPORT_WEXT - seq_puts(m, "with WEXT support\n"); -#else - seq_putc(m, '\n'); -#endif /* CSR_SUPPORT_WEXT */ -#endif /* CSR_SME_USERSPACE */ -#ifdef CSR_NATIVE_LINUX - seq_puts(m, "SME: native\n"); -#endif - -#ifdef CSR_SUPPORT_SME - seq_printf(m, "Firmware (ROM) build:%u, Patch:%u\n", - priv->card_info.fw_build, - priv->sme_versions.firmwarePatch); -#endif - - unifi_print_status(priv->card, m); - - seq_printf(m, "Last dbg str: %s\n", priv->last_debug_string); - - seq_puts(m, "Last dbg16:"); - for (i = 0; i < 8; i++) - seq_printf(m, " %04X", priv->last_debug_word16[i]); - seq_putc(m, '\n'); - seq_puts(m, " "); - for (; i < 16; i++) - seq_printf(m, " %04X", priv->last_debug_word16[i]); - seq_putc(m, '\n'); - return 0; -} -#endif - - - - -static void -uf_lx_suspend(CsrSdioFunction *sdio_ctx) -{ - unifi_priv_t *priv = sdio_ctx->driverData; - unifi_suspend(priv); - - CsrSdioSuspendAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); -} - -static void -uf_lx_resume(CsrSdioFunction *sdio_ctx) -{ - unifi_priv_t *priv = sdio_ctx->driverData; - unifi_resume(priv); - - CsrSdioResumeAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); -} - -static int active_slot = MAX_UNIFI_DEVS; -static struct device *os_devices[MAX_UNIFI_DEVS]; - -void -uf_add_os_device(int bus_id, struct device *os_device) -{ - if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { - unifi_error(NULL, "uf_add_os_device: invalid device %d\n", - bus_id); - return; - } - - active_slot = bus_id; - os_devices[bus_id] = os_device; -} /* uf_add_os_device() */ - -void -uf_remove_os_device(int bus_id) -{ - if ((bus_id < 0) || (bus_id >= MAX_UNIFI_DEVS)) { - unifi_error(NULL, "uf_remove_os_device: invalid device %d\n", - bus_id); - return; - } - - active_slot = bus_id; - os_devices[bus_id] = NULL; -} /* uf_remove_os_device() */ - -static void -uf_sdio_inserted(CsrSdioFunction *sdio_ctx) -{ - unifi_priv_t *priv; - - unifi_trace(NULL, UDBG5, "uf_sdio_inserted(0x%p), slot_id=%d, dev=%p\n", - sdio_ctx, active_slot, os_devices[active_slot]); - - priv = register_unifi_sdio(sdio_ctx, active_slot, os_devices[active_slot]); - if (priv == NULL) { - CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_FAILURE); - return; - } - - sdio_ctx->driverData = priv; - - CsrSdioInsertedAcknowledge(sdio_ctx, CSR_RESULT_SUCCESS); -} /* uf_sdio_inserted() */ - - -static void -uf_sdio_removed(CsrSdioFunction *sdio_ctx) -{ - unregister_unifi_sdio(active_slot); - CsrSdioRemovedAcknowledge(sdio_ctx); -} /* uf_sdio_removed() */ - - -static void -uf_sdio_dsr_handler(CsrSdioFunction *sdio_ctx) -{ - unifi_priv_t *priv = sdio_ctx->driverData; - - unifi_sdio_interrupt_handler(priv->card); -} /* uf_sdio_dsr_handler() */ - -/* - * --------------------------------------------------------------------------- - * uf_sdio_int_handler - * - * Interrupt callback function for SDIO interrupts. - * This is called in kernel context (i.e. not interrupt context). - * We retrieve the unifi context pointer and call the main UniFi - * interrupt handler. - * - * Arguments: - * fdev SDIO context pointer - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static CsrSdioInterruptDsrCallback -uf_sdio_int_handler(CsrSdioFunction *sdio_ctx) -{ - return uf_sdio_dsr_handler; -} /* uf_sdio_int_handler() */ - - - - -static CsrSdioFunctionId unifi_ids[] = -{ - { - .manfId = SDIO_MANF_ID_CSR, - .cardId = SDIO_CARD_ID_UNIFI_3, - .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_3, - .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, - }, - { - .manfId = SDIO_MANF_ID_CSR, - .cardId = SDIO_CARD_ID_UNIFI_4, - .sdioFunction = SDIO_WLAN_FUNC_ID_UNIFI_4, - .sdioInterface = CSR_SDIO_ANY_SDIO_INTERFACE, - } -}; - - -/* - * Structure to register with the glue layer. - */ -static CsrSdioFunctionDriver unifi_sdioFunction_drv = -{ - .inserted = uf_sdio_inserted, - .removed = uf_sdio_removed, - .intr = uf_sdio_int_handler, - .suspend = uf_lx_suspend, - .resume = uf_lx_resume, - - .ids = unifi_ids, - .idsCount = sizeof(unifi_ids) / sizeof(unifi_ids[0]) -}; - - -/* - * --------------------------------------------------------------------------- - * uf_sdio_load - * uf_sdio_unload - * - * These functions are called from the main module load and unload - * functions. They perform the appropriate operations for the monolithic - * driver. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int __init -uf_sdio_load(void) -{ - CsrResult csrResult; - - csrResult = CsrSdioFunctionDriverRegister(&unifi_sdioFunction_drv); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(NULL, "Failed to register UniFi SDIO driver: csrResult=%d\n", csrResult); - return -EIO; - } - - return 0; -} /* uf_sdio_load() */ - - - -void __exit -uf_sdio_unload(void) -{ - CsrSdioFunctionDriverUnregister(&unifi_sdioFunction_drv); -} /* uf_sdio_unload() */ - diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c deleted file mode 100644 index 861d6b7687c7..000000000000 --- a/drivers/staging/csr/mlme.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: mlme.c - * - * PURPOSE: - * This file provides functions to send MLME requests to the UniFi. - * - * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include "csr_wifi_hip_unifi.h" -#include "unifi_priv.h" - -/* - * --------------------------------------------------------------------------- - * unifi_mlme_wait_for_reply - * - * Wait for a reply after sending a signal. - * - * Arguments: - * priv Pointer to device private context struct - * ul_client Pointer to linux client - * sig_reply_id ID of the expected reply (defined in sigs.h). - * timeout timeout in ms - * - * Returns: - * 0 on success, -ve POSIX code on error. - * - * Notes: - * This function waits for a specific (sig_reply_id) signal from UniFi. - * It also match the sequence number of the received (cfm) signal, with - * the latest sequence number of the signal (req) we have sent. - * These two number match be equal. - * Should only be used for waiting xxx.cfm signals and only after - * we have sent the matching xxx.req signal to UniFi. - * If no response is received within the expected time (timeout), we assume - * that the UniFi is busy and return an error. - * If the wait is aborted by a kernel signal arriving, we stop waiting. - * If a response from UniFi is not what we expected, we discard it and - * wait again. This could be a response from an aborted request. If we - * see several bad responses we assume we have lost synchronisation with - * UniFi. - * --------------------------------------------------------------------------- - */ -static int -unifi_mlme_wait_for_reply(unifi_priv_t *priv, ul_client_t *pcli, int sig_reply_id, int timeout) -{ - int retries = 0; - long r; - long t = timeout; - unsigned int sent_seq_no; - - /* Convert t in ms to jiffies */ - t = msecs_to_jiffies(t); - - do { - /* Wait for the confirm or timeout. */ - r = wait_event_interruptible_timeout(pcli->udi_wq, - (pcli->wake_up_wq_id) || (priv->io_aborted == 1), - t); - /* Check for general i/o error */ - if (priv->io_aborted) { - unifi_error(priv, "MLME operation aborted\n"); - return -EIO; - } - - /* - * If r=0 the request has timed-out. - * If r>0 the request has completed successfully. - * If r=-ERESTARTSYS an event (kill signal) has interrupted the wait_event. - */ - if ((r == 0) && (pcli->wake_up_wq_id == 0)) { - unifi_error(priv, "mlme_wait: timed-out waiting for 0x%.4X, after %lu msec.\n", - sig_reply_id, jiffies_to_msecs(t)); - pcli->wake_up_wq_id = 0; - return -ETIMEDOUT; - } else if (r == -ERESTARTSYS) { - unifi_error(priv, "mlme_wait: waiting for 0x%.4X was aborted.\n", sig_reply_id); - pcli->wake_up_wq_id = 0; - return -EINTR; - } else { - /* Get the sequence number of the signal that we previously set. */ - if (pcli->seq_no != 0) { - sent_seq_no = pcli->seq_no - 1; - } else { - sent_seq_no = 0x0F; - } - - unifi_trace(priv, UDBG5, "Received 0x%.4X, seq: (r:%d, s:%d)\n", - pcli->wake_up_wq_id, - pcli->wake_seq_no, sent_seq_no); - - /* The two sequence ids must match. */ - if (pcli->wake_seq_no == sent_seq_no) { - /* and the signal ids must match. */ - if (sig_reply_id == pcli->wake_up_wq_id) { - /* Found the expected signal */ - break; - } else { - /* This should never happen ... */ - unifi_error(priv, "mlme_wait: mismatching signal id (0x%.4X - exp 0x%.4X) (seq %d)\n", - pcli->wake_up_wq_id, - sig_reply_id, - pcli->wake_seq_no); - pcli->wake_up_wq_id = 0; - return -EIO; - } - } - /* Wait for the next signal. */ - pcli->wake_up_wq_id = 0; - - retries ++; - if (retries >= 3) { - unifi_error(priv, "mlme_wait: confirm wait retries exhausted (0x%.4X - exp 0x%.4X)\n", - pcli->wake_up_wq_id, - sig_reply_id); - pcli->wake_up_wq_id = 0; - return -EIO; - } - } - } while (1); - - pcli->wake_up_wq_id = 0; - - return 0; -} /* unifi_mlme_wait_for_reply() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_mlme_blocking_request - * - * Send a MLME request signal to UniFi. - * - * Arguments: - * priv Pointer to device private context struct - * pcli Pointer to context of calling process - * sig Pointer to the signal to send - * data_ptrs Pointer to the bulk data of the signal - * timeout The request's timeout. - * - * Returns: - * 0 on success, 802.11 result code on error. - * --------------------------------------------------------------------------- - */ -int -unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli, - CSR_SIGNAL *sig, bulk_data_param_t *data_ptrs, - int timeout) -{ - int r; - - if (sig->SignalPrimitiveHeader.SignalId == 0) { - unifi_error(priv, "unifi_mlme_blocking_request: Invalid Signal Id (0x%x)\n", - sig->SignalPrimitiveHeader.SignalId); - return -EINVAL; - } - - down(&priv->mlme_blocking_mutex); - - sig->SignalPrimitiveHeader.ReceiverProcessId = 0; - sig->SignalPrimitiveHeader.SenderProcessId = pcli->sender_id | pcli->seq_no; - - unifi_trace(priv, UDBG2, "Send client=%d, S:0x%04X, sig 0x%.4X\n", - pcli->client_id, - sig->SignalPrimitiveHeader.SenderProcessId, - sig->SignalPrimitiveHeader.SignalId); - /* Send the signal to UniFi */ - r = ul_send_signal_unpacked(priv, sig, data_ptrs); - if (r) { - up(&priv->mlme_blocking_mutex); - unifi_error(priv, "Error queueing MLME REQUEST signal\n"); - return r; - } - - unifi_trace(priv, UDBG5, "Send 0x%.4X, seq = %d\n", - sig->SignalPrimitiveHeader.SignalId, pcli->seq_no); - - /* - * Advance the sequence number of the last sent signal, only - * if the signal has been successfully set. - */ - pcli->seq_no++; - if (pcli->seq_no > 0x0F) { - pcli->seq_no = 0; - } - - r = unifi_mlme_wait_for_reply(priv, pcli, (sig->SignalPrimitiveHeader.SignalId + 1), timeout); - up(&priv->mlme_blocking_mutex); - - if (r) { - unifi_error(priv, "Error waiting for MLME CONFIRM signal\n"); - return r; - } - - return 0; -} /* unifi_mlme_blocking_request() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_mlme_copy_reply_and_wakeup_client - * - * Copy the reply signal from UniFi to the client's structure - * and wake up the waiting client. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -unifi_mlme_copy_reply_and_wakeup_client(ul_client_t *pcli, - CSR_SIGNAL *signal, int signal_len, - const bulk_data_param_t *bulkdata) -{ - int i; - - /* Copy the signal to the reply */ - memcpy(pcli->reply_signal, signal, signal_len); - - /* Get the sequence number of the signal that woke us up. */ - pcli->wake_seq_no = pcli->reply_signal->SignalPrimitiveHeader.ReceiverProcessId & 0x0F; - - /* Append any bulk data */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length > 0) { - if (bulkdata->d[i].os_data_ptr) { - memcpy(pcli->reply_bulkdata[i]->ptr, bulkdata->d[i].os_data_ptr, bulkdata->d[i].data_length); - pcli->reply_bulkdata[i]->length = bulkdata->d[i].data_length; - } else { - pcli->reply_bulkdata[i]->length = 0; - } - } - } - - /* Wake the requesting MLME function. */ - pcli->wake_up_wq_id = pcli->reply_signal->SignalPrimitiveHeader.SignalId; - wake_up_interruptible(&pcli->udi_wq); - -} /* unifi_mlme_copy_reply_and_wakeup_client() */ - - -/* - * --------------------------------------------------------------------------- - * uf_abort_mlme - * - * Abort any MLME operation in progress. - * This is used in the error recovery mechanism. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * 0 on success. - * --------------------------------------------------------------------------- - */ -int -uf_abort_mlme(unifi_priv_t *priv) -{ - ul_client_t *ul_cli; - - /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ - priv->io_aborted = 1; - - ul_cli = priv->netdev_client; - if (ul_cli) { - wake_up_interruptible(&ul_cli->udi_wq); - } - - ul_cli = priv->wext_client; - if (ul_cli) { - wake_up_interruptible(&ul_cli->udi_wq); - } - - return 0; -} /* uf_abort_mlme() */ - - - -/* - * --------------------------------------------------------------------------- - * - * Human-readable decoding of Reason and Result codes. - * - * --------------------------------------------------------------------------- - */ - -struct mlme_code { - const char *name; - int id; -}; - -static const struct mlme_code Result_codes[] = { - { "Success", 0x0000 }, - { "Unspecified Failure", 0x0001 }, - /* (Reserved) 0x0002 - 0x0009 */ - { "Refused Capabilities Mismatch", 0x000A }, - /* (Reserved) 0x000B */ - { "Refused External Reason", 0x000C }, - /* (Reserved) 0x000D - 0x0010 */ - { "Refused AP Out Of Memory", 0x0011 }, - { "Refused Basic Rates Mismatch", 0x0012 }, - /* (Reserved) 0x0013 - 0x001F */ - { "Failure", 0x0020 }, - /* (Reserved) 0x0021 - 0x0024 */ - { "Refused Reason Unspecified", 0x0025 }, - { "Invalid Parameters", 0x0026 }, - { "Rejected With Suggested Changes", 0x0027 }, - /* (Reserved) 0x0028 - 0x002E */ - { "Rejected For Delay Period", 0x002F }, - { "Not Allowed", 0x0030 }, - { "Not Present", 0x0031 }, - { "Not QSTA", 0x0032 }, - /* (Reserved) 0x0033 - 0x7FFF */ - { "Timeout", 0x8000 }, - { "Too Many Simultaneous Requests", 0x8001 }, - { "BSS Already Started Or Joined", 0x8002 }, - { "Not Supported", 0x8003 }, - { "Transmission Failure", 0x8004 }, - { "Refused Not Authenticated", 0x8005 }, - { "Reset Required Before Start", 0x8006 }, - { "LM Info Unavailable", 0x8007 }, - { NULL, -1 } -}; - -static const struct mlme_code Reason_codes[] = { - /* (Reserved) 0x0000 */ - { "Unspecified Reason", 0x0001 }, - { "Authentication Not Valid", 0x0002 }, - { "Deauthenticated Leave BSS", 0x0003 }, - { "Disassociated Inactivity", 0x0004 }, - { "AP Overload", 0x0005 }, - { "Class2 Frame Error", 0x0006 }, - { "Class3 Frame Error", 0x0007 }, - { "Disassociated Leave BSS", 0x0008 }, - { "Association Not Authenticated", 0x0009 }, - { "Disassociated Power Capability", 0x000A }, - { "Disassociated Supported Channels", 0x000B }, - /* (Reserved) 0x000C */ - { "Invalid Information Element", 0x000D }, - { "Michael MIC Failure", 0x000E }, - { "Fourway Handshake Timeout", 0x000F }, - { "Group Key Update Timeout", 0x0010 }, - { "Handshake Element Different", 0x0011 }, - { "Invalid Group Cipher", 0x0012 }, - { "Invalid Pairwise Cipher", 0x0013 }, - { "Invalid AKMP", 0x0014 }, - { "Unsupported RSN IE Version", 0x0015 }, - { "Invalid RSN IE Capabilities", 0x0016 }, - { "Dot1X Auth Failed", 0x0017 }, - { "Cipher Rejected By Policy", 0x0018 }, - /* (Reserved) 0x0019 - 0x001F */ - { "QoS Unspecified Reason", 0x0020 }, - { "QoS Insufficient Bandwidth", 0x0021 }, - { "QoS Excessive Not Ack", 0x0022 }, - { "QoS TXOP Limit Exceeded", 0x0023 }, - { "QSTA Leaving", 0x0024 }, - { "End TS, End DLS, End BA", 0x0025 }, - { "Unknown TS, Unknown DLS, Unknown BA", 0x0026 }, - { "Timeout", 0x0027 }, - /* (Reserved) 0x0028 - 0x002C */ - { "STAKey Mismatch", 0x002D }, - { NULL, -1 } -}; - - -static const char * -lookup_something(const struct mlme_code *n, int id) -{ - for (; n->name; n++) { - if (n->id == id) { - return n->name; - } - } - - /* not found */ - return NULL; -} /* lookup_something() */ - - -const char * -lookup_result_code(int result) -{ - static char fallback[16]; - const char *str; - - str = lookup_something(Result_codes, result); - - if (str == NULL) { - snprintf(fallback, 16, "%d", result); - str = fallback; - } - - return str; -} /* lookup_result_code() */ - - -/* - * --------------------------------------------------------------------------- - * lookup_reason - * - * Return a description string for a WiFi MLME ReasonCode. - * - * Arguments: - * reason The ReasonCode to interpret. - * - * Returns: - * Pointer to description string. - * --------------------------------------------------------------------------- - */ -const char * -lookup_reason_code(int reason) -{ - static char fallback[16]; - const char *str; - - str = lookup_something(Reason_codes, reason); - - if (str == NULL) { - snprintf(fallback, 16, "%d", reason); - str = fallback; - } - - return str; -} /* lookup_reason_code() */ - diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c deleted file mode 100644 index e11f6cba8266..000000000000 --- a/drivers/staging/csr/monitor.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: monitor.c - * - * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include "unifi_priv.h" - -#ifdef UNIFI_SNIFF_ARPHRD - - -#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) -#include -#endif - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW ETH_P_ALL -#endif - -/* - * --------------------------------------------------------------------------- - * uf_start_sniff - * - * Start UniFi capture in SNIFF mode, i.e capture everything it hears. - * - * Arguments: - * priv Pointer to device private context struct - * - * Returns: - * 0 on success or kernel error code - * --------------------------------------------------------------------------- - */ -int -uf_start_sniff(unifi_priv_t *priv) -{ - ul_client_t *pcli = priv->wext_client; - CSR_SIGNAL signal; - CSR_MLME_SNIFFJOIN_REQUEST *req = &signal.u.MlmeSniffjoinRequest; - int timeout = 1000; - int r; - - req->Ifindex = priv->if_index; - req->Channel = priv->wext_conf.channel; - req->ChannelStartingFactor = 0; - - signal.SignalPrimitiveHeader.SignalId = CSR_MLME_SNIFFJOIN_REQUEST_ID; - - r = unifi_mlme_blocking_request(priv, pcli, &signal, NULL, timeout); - if (r < 0) { - unifi_error(priv, "failed to send SNIFFJOIN request, error %d\n", r); - return r; - } - - r = pcli->reply_signal->u.MlmeSniffjoinConfirm.Resultcode; - if (r) { - unifi_notice(priv, "SNIFFJOIN request was rejected with result 0x%X (%s)\n", - r, lookup_result_code(r)); - return -EIO; - } - - return 0; -} /* uf_start_sniff() */ - - - -/* - * --------------------------------------------------------------------------- - * netrx_radiotap - * - * Reformat a UniFi SNIFFDATA signal into a radiotap packet. - * - * Arguments: - * priv OS private context pointer. - * ind Pointer to a MA_UNITDATA_INDICATION or - * DS_UNITDATA_INDICATION indication structure. - * - * Notes: - * Radiotap header values are all little-endian, UniFi signals will have - * been converted to host-endian. - * --------------------------------------------------------------------------- - */ -#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) -static void -netrx_radiotap(unifi_priv_t *priv, - const CSR_MA_SNIFFDATA_INDICATION *ind, - struct sk_buff *skb_orig) -{ - struct net_device *dev = priv->netdev; - struct sk_buff *skb = NULL; - unsigned char *ptr; - unsigned char *base; - int ind_data_len = skb_orig->len - 2 - ETH_HLEN; - struct unifi_rx_radiotap_header { - struct ieee80211_radiotap_header rt_hdr; - /* IEEE80211_RADIOTAP_TSFT */ - u64 rt_tsft; - /* IEEE80211_RADIOTAP_FLAGS */ - u8 rt_flags; - /* IEEE80211_RADIOTAP_RATE */ - u8 rt_rate; - /* IEEE80211_RADIOTAP_CHANNEL */ - u16 rt_chan; - u16 rt_chan_flags; - /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ - u8 rt_dbm_antsignal; - /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ - u8 rt_dbm_antnoise; - /* IEEE80211_RADIOTAP_ANTENNA */ - u8 rt_antenna; - - /* pad to 4-byte boundary */ - u8 pad[3]; - } __attribute__((__packed__)); - - struct unifi_rx_radiotap_header *unifi_rt; - int signal, noise, snr; - - if (ind_data_len <= 0) { - unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n"); - return; - } - - /* - * Allocate a SKB for the received data packet, including radiotap - * header. - */ - skb = dev_alloc_skb(ind_data_len + sizeof(struct unifi_rx_radiotap_header) + 4); - if (! skb) { - unifi_error(priv, "alloc_skb failed.\n"); - priv->stats.rx_errors++; - return; - } - - base = skb->data; - - /* Reserve the radiotap header at the front of skb */ - unifi_rt = (struct unifi_rx_radiotap_header *) - skb_put(skb, sizeof(struct unifi_rx_radiotap_header)); - - /* Copy in the 802.11 frame */ - ptr = skb_put(skb, ind_data_len); - memcpy(ptr, skb_orig->data, ind_data_len); - - unifi_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - unifi_rt->rt_hdr.it_pad = 0; /* always good to zero */ - unifi_rt->rt_hdr.it_len = sizeof(struct unifi_rx_radiotap_header); - - /* Big bitfield of all the fields we provide in radiotap */ - unifi_rt->rt_hdr.it_present = 0 - | (1 << IEEE80211_RADIOTAP_TSFT) - | (1 << IEEE80211_RADIOTAP_FLAGS) - | (1 << IEEE80211_RADIOTAP_RATE) - | (1 << IEEE80211_RADIOTAP_CHANNEL) - | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) - | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) - | (1 << IEEE80211_RADIOTAP_ANTENNA) - ; - - - /* No flags to set */ - unifi_rt->rt_tsft = (((u64)ind->Timestamp.x[7]) | (((u64)ind->Timestamp.x[6]) << 8) | - (((u64)ind->Timestamp.x[5]) << 16) | (((u64)ind->Timestamp.x[4]) << 24) | - (((u64)ind->Timestamp.x[3]) << 32) | (((u64)ind->Timestamp.x[2]) << 40) | - (((u64)ind->Timestamp.x[1]) << 48) | (((u64)ind->Timestamp.x[0]) << 56)); - - unifi_rt->rt_flags = 0; - - unifi_rt->rt_rate = ind->Rate; - - unifi_rt->rt_chan = cpu_to_le16(ieee80211chan2mhz(priv->wext_conf.channel)); - unifi_rt->rt_chan_flags = 0; - - /* Convert signal to dBm */ - signal = (s16)unifi2host_16(ind->Rssi); /* in dBm */ - snr = (s16)unifi2host_16(ind->Snr); /* in dB */ - noise = signal - snr; - - unifi_rt->rt_dbm_antsignal = signal; - unifi_rt->rt_dbm_antnoise = noise; - - unifi_rt->rt_antenna = ind->AntennaId; - - - skb->dev = dev; - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - - /* Pass up to Linux network stack */ - netif_rx_ni(skb); - - dev->last_rx = jiffies; - - /* Bump the rx stats */ - priv->stats.rx_packets++; - priv->stats.rx_bytes += ind_data_len; - -} /* netrx_radiotap() */ -#endif /* RADIOTAP */ - - -/* - * --------------------------------------------------------------------------- - * netrx_prism - * - * Reformat a UniFi SNIFFDATA signal into a Prism format sniff packet. - * - * Arguments: - * priv OS private context pointer. - * ind Pointer to a MA_UNITDATA_INDICATION or - * DS_UNITDATA_INDICATION indication structure. - * - * Notes: - * Radiotap header values are all little-endian, UniFi signals will have - * been converted to host-endian. - * --------------------------------------------------------------------------- - */ -#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_PRISM) -static void -netrx_prism(unifi_priv_t *priv, - const CSR_MA_SNIFFDATA_INDICATION *ind, - struct sk_buff *skb_orig) -{ - struct net_device *dev = priv->netdev; - struct sk_buff *skb = NULL; - unsigned char *ptr; - unsigned char *base; - int ind_data_len = skb_orig->len - 2 - ETH_HLEN; -#define WLANCAP_MAGIC_COOKIE_V1 0x80211001 - struct avs_header_v1 { - uint32 version; - uint32 length; - uint64 mactime; - uint64 hosttime; - uint32 phytype; - uint32 channel; - uint32 datarate; - uint32 antenna; - uint32 priority; - uint32 ssi_type; - int32 ssi_signal; - int32 ssi_noise; - uint32 preamble; - uint32 encoding; - } *avs; - int signal, noise, snr; - - if (ind_data_len <= 0) { - unifi_error(priv, "Invalid length in CSR_MA_SNIFFDATA_INDICATION.\n"); - return; - } - - /* - * Allocate a SKB for the received data packet, including radiotap - * header. - */ - skb = dev_alloc_skb(ind_data_len + sizeof(struct avs_header_v1) + 4); - if (! skb) { - unifi_error(priv, "alloc_skb failed.\n"); - priv->stats.rx_errors++; - return; - } - - base = skb->data; - - /* Reserve the radiotap header at the front of skb */ - avs = (struct avs_header_v1 *)skb_put(skb, sizeof(struct avs_header_v1)); - - /* Copy in the 802.11 frame */ - ptr = skb_put(skb, ind_data_len); - memcpy(ptr, skb_orig->data, ind_data_len); - - /* Convert signal to dBm */ - signal = 0x10000 - ((s16)unifi2host_16(ind->Rssi)); /* in dBm */ - snr = (s16)unifi2host_16(ind->Snr); /* in dB */ - noise = signal - snr; - - avs->version = htonl(WLANCAP_MAGIC_COOKIE_V1); - avs->length = htonl(sizeof(struct avs_header_v1)); - avs->mactime = __cpu_to_be64(ind->Timestamp); - avs->hosttime = __cpu_to_be64(jiffies); - avs->phytype = htonl(9); /* dss_ofdm_dot11_g */ - avs->channel = htonl(priv->wext_conf.channel); - avs->datarate = htonl(ind->Rate * 5); - avs->antenna = htonl(ind->Antenna); - avs->priority = htonl(0); /* unknown */ - avs->ssi_type = htonl(2); /* dBm */ - avs->ssi_signal = htonl(signal); - avs->ssi_noise = htonl(noise); - avs->preamble = htonl(0); /* unknown */ - avs->encoding = htonl(0); /* unknown */ - - - skb->dev = dev; - skb->mac.raw = skb->data; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - - /* Pass up to Linux network stack */ - netif_rx_ni(skb); - - dev->last_rx = jiffies; - - /* Bump the rx stats */ - priv->stats.rx_packets++; - priv->stats.rx_bytes += ind_data_len; - -} /* netrx_prism() */ -#endif /* PRISM */ - - -/* - * --------------------------------------------------------------------------- - * ma_sniffdata_ind - * - * Reformat a UniFi SNIFFDATA signal into a network - * - * Arguments: - * ospriv OS private context pointer. - * ind Pointer to a MA_UNITDATA_INDICATION or - * DS_UNITDATA_INDICATION indication structure. - * bulkdata Pointer to a bulk data structure, describing - * the data received. - * - * Notes: - * Radiotap header values are all little-endian, UniFi signals will have - * been converted to host-endian. - * --------------------------------------------------------------------------- - */ -void -ma_sniffdata_ind(void *ospriv, - const CSR_MA_SNIFFDATA_INDICATION *ind, - const bulk_data_param_t *bulkdata) -{ - unifi_priv_t *priv = ospriv; - struct net_device *dev = priv->netdev; - struct sk_buff *skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - - if (bulkdata->d[0].data_length == 0) { - unifi_warning(priv, "rx: MA-SNIFFDATA indication with zero bulk data\n"); - return; - } - - skb->len = bulkdata->d[0].data_length; - - /* We only process data packets if the interface is open */ - if (unlikely(!netif_running(dev))) { - priv->stats.rx_dropped++; - priv->wext_conf.wireless_stats.discard.misc++; - dev_kfree_skb(skb); - return; - } - - if (ind->ReceptionStatus) { - priv->stats.rx_dropped++; - priv->wext_conf.wireless_stats.discard.misc++; - printk(KERN_INFO "unifi: Dropping corrupt sniff packet\n"); - dev_kfree_skb(skb); - return; - } - -#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_PRISM) - netrx_prism(priv, ind, skb); -#endif /* PRISM */ - -#if (UNIFI_SNIFF_ARPHRD == ARPHRD_IEEE80211_RADIOTAP) - netrx_radiotap(priv, ind, skb); -#endif /* RADIOTAP */ - - dev_kfree_skb(skb); - -} /* ma_sniffdata_ind() */ - - -#endif /* UNIFI_SNIFF_ARPHRD */ - diff --git a/drivers/staging/csr/netdev.c b/drivers/staging/csr/netdev.c deleted file mode 100644 index 9c716c162c24..000000000000 --- a/drivers/staging/csr/netdev.c +++ /dev/null @@ -1,3307 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: netdev.c - * - * PURPOSE: - * This file provides the upper edge interface to the linux netdevice - * and wireless extensions. - * It is part of the porting exercise. - * - * Copyright (C) 2005-2010 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -/* - * Porting Notes: - * This file implements the data plane of the UniFi linux driver. - * - * All the Tx packets are passed to the HIP core lib, using the - * unifi_send_signal() API. For EAPOL packets use the MLME-EAPOL.req - * signal, for all other use the MLME-UNITDATA.req. The unifi_send_signal() - * expects the wire-formatted (packed) signal. For convenience, in the OS - * layer we only use the native (unpacked) signal structures. The HIP core lib - * provides the write_pack() helper function to convert to the packed signal. - * The packet is stored in the bulk data of the signal. We do not need to - * allocate new memory to store the packet, because unifi_net_data_malloc() - * is implemented to return a skb, which is the format of packet in Linux. - * The HIP core lib frees the bulk data buffers, so we do not need to do - * this in the OS layer. - * - * All the Rx packets are MLME-UNITDATA.ind signals, passed by the HIP core lib - * in unifi_receive_event(). We do not need to allocate an skb and copy the - * received packet because the HIP core lib has stored in memory allocated by - * unifi_net_data_malloc(). Also, we can perform the 802.11 to Ethernet - * translation in-place because we allocate the extra memory allocated in - * unifi_net_data_malloc(). - * - * If possible, the porting exercise should appropriately implement - * unifi_net_data_malloc() and unifi_net_data_free() to save copies between - * network and driver buffers. - */ - -#include -#include -#include -#include -#include -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "unifi_priv.h" -#include - - -/* Wext handler is supported only if CSR_SUPPORT_WEXT is defined */ -#ifdef CSR_SUPPORT_WEXT -extern struct iw_handler_def unifi_iw_handler_def; -#endif /* CSR_SUPPORT_WEXT */ -static void check_ba_frame_age_timeout( unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session); -static void process_ba_frame(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - frame_desc_struct *frame_desc); -static void process_ba_complete(unifi_priv_t *priv, netInterface_priv_t *interfacePriv); -static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata); -static void process_amsdu(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata); -static int uf_net_open(struct net_device *dev); -static int uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static int uf_net_stop(struct net_device *dev); -static struct net_device_stats *uf_net_get_stats(struct net_device *dev); -static u16 uf_net_select_queue(struct net_device *dev, struct sk_buff *skb); -static netdev_tx_t uf_net_xmit(struct sk_buff *skb, struct net_device *dev); -static void uf_set_multicast_list(struct net_device *dev); - - -typedef int (*tx_signal_handler)(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, CSR_PRIORITY priority); - -#ifdef CONFIG_NET_SCHED -/* - * Queueing Discipline Interface - * Only used if kernel is configured with CONFIG_NET_SCHED - */ - -/* - * The driver uses the qdisc interface to buffer and control all - * outgoing traffic. We create a root qdisc, register our qdisc operations - * and later we create two subsidiary pfifo queues for the uncontrolled - * and controlled ports. - * - * The network stack delivers all outgoing packets in our enqueue handler. - * There, we classify the packet and decide whether to store it or drop it - * (if the controlled port state is set to "discard"). - * If the packet is enqueued, the network stack call our dequeue handler. - * There, we decide whether we can send the packet, delay it or drop it - * (the controlled port configuration might have changed meanwhile). - * If a packet is dequeued, then the network stack calls our hard_start_xmit - * handler where finally we send the packet. - * - * If the hard_start_xmit handler fails to send the packet, we return - * NETDEV_TX_BUSY and the network stack call our requeue handler where - * we put the packet back in the same queue in came from. - * - */ - -struct uf_sched_data -{ - /* Traffic Classifier TBD */ - struct tcf_proto *filter_list; - /* Our two queues */ - struct Qdisc *queues[UNIFI_TRAFFIC_Q_MAX]; -}; - -struct uf_tx_packet_data { - /* Queue the packet is stored in */ - unifi_TrafficQueue queue; - /* QoS Priority determined when enqueing packet */ - CSR_PRIORITY priority; - /* Debug */ - unsigned long host_tag; -}; - -#endif /* CONFIG_NET_SCHED */ - -static const struct net_device_ops uf_netdev_ops = -{ - .ndo_open = uf_net_open, - .ndo_stop = uf_net_stop, - .ndo_start_xmit = uf_net_xmit, - .ndo_do_ioctl = uf_net_ioctl, - .ndo_get_stats = uf_net_get_stats, /* called by /proc/net/dev */ - .ndo_set_rx_mode = uf_set_multicast_list, - .ndo_select_queue = uf_net_select_queue, -}; - -static u8 oui_rfc1042[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; -static u8 oui_8021h[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; - - -/* Callback for event logging to blocking clients */ -static void netdev_mlme_event_handler(ul_client_t *client, - const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata, - int dir); - -#ifdef CSR_SUPPORT_WEXT -/* Declare netdev_notifier block which will contain the state change - * handler callback function - */ -static struct notifier_block uf_netdev_notifier; -#endif - -/* - * --------------------------------------------------------------------------- - * uf_alloc_netdevice - * - * Allocate memory for the net_device and device private structs - * for this interface. - * Fill in the fields, but don't register the interface yet. - * We need to configure the UniFi first. - * - * Arguments: - * sdio_dev Pointer to SDIO context handle to use for all - * SDIO ops. - * bus_id A small number indicating the SDIO card position on the - * bus. Typically this is the slot number, e.g. 0, 1 etc. - * Valid values are 0 to MAX_UNIFI_DEVS-1. - * - * Returns: - * Pointer to device private struct. - * - * Notes: - * The net_device and device private structs are allocated together - * and should be freed by freeing the net_device pointer. - * --------------------------------------------------------------------------- - */ -unifi_priv_t * -uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id) -{ - struct net_device *dev; - unifi_priv_t *priv; - netInterface_priv_t *interfacePriv; -#ifdef CSR_SUPPORT_WEXT - int rc; -#endif - unsigned char i; /* loop index */ - - /* - * Allocate netdevice struct, assign name template and - * setup as an ethernet device. - * The net_device and private structs are zeroed. Ether_setup() then - * sets up ethernet handlers and values. - * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, - * so use "eth*" (like other wireless extns drivers). - */ - dev = alloc_etherdev_mq(sizeof(unifi_priv_t) + sizeof(netInterface_priv_t), UNIFI_TRAFFIC_Q_MAX); - - if (dev == NULL) { - return NULL; - } - - /* Set up back pointer from priv to netdev */ - interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - priv = (unifi_priv_t *)(interfacePriv + 1); - interfacePriv->privPtr = priv; - interfacePriv->InterfaceTag = 0; - - - /* Initialize all supported netdev interface to be NULL */ - for(i=0; inetdev[i] = NULL; - priv->interfacePriv[i] = NULL; - } - priv->netdev[0] = dev; - priv->interfacePriv[0] = interfacePriv; - - /* Setup / override net_device fields */ - dev->netdev_ops = &uf_netdev_ops; - -#ifdef CSR_SUPPORT_WEXT - dev->wireless_handlers = &unifi_iw_handler_def; -#if IW_HANDLER_VERSION < 6 - dev->get_wireless_stats = unifi_get_wireless_stats; -#endif /* IW_HANDLER_VERSION */ -#endif /* CSR_SUPPORT_WEXT */ - - /* This gives us enough headroom to add the 802.11 header */ - dev->needed_headroom = 32; - - /* Use bus_id as instance number */ - priv->instance = bus_id; - /* Store SDIO pointer to pass in the core */ - priv->sdio = sdio_dev; - - sdio_dev->driverData = (void*)priv; - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; - - priv->prev_queue = 0; - - /* - * Initialise the clients structure array. - * We do not need protection around ul_init_clients() because - * the character device can not be used until uf_alloc_netdevice() - * returns and Unifi_instances[bus_id]=priv is set, since unifi_open() - * will return -ENODEV. - */ - ul_init_clients(priv); - - /* - * Register a new ul client to send the multicast list signals. - * Note: priv->instance must be set before calling this. - */ - priv->netdev_client = ul_register_client(priv, - 0, - netdev_mlme_event_handler); - if (priv->netdev_client == NULL) { - unifi_error(priv, - "Failed to register a unifi client for background netdev processing\n"); - free_netdev(priv->netdev[0]); - return NULL; - } - unifi_trace(priv, UDBG2, "Netdev %p client (id:%d s:0x%X) is registered\n", - dev, priv->netdev_client->client_id, priv->netdev_client->sender_id); - - priv->sta_wmm_capabilities = 0; - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_SUPPORT_SME)) - priv->wapi_multicast_filter = 0; - priv->wapi_unicast_filter = 0; - priv->wapi_unicast_queued_pkt_filter = 0; -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - priv->isWapiConnection = FALSE; -#endif -#endif - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - -#ifdef CSR_SUPPORT_SME - priv->allPeerDozing = 0; -#endif - /* - * Initialise the OS private struct. - */ - /* - * Instead of deciding in advance to use 11bg or 11a, we could do a more - * clever scan on both radios. - */ - if (use_5g) { - priv->if_index = CSR_INDEX_5G; - unifi_info(priv, "Using the 802.11a radio\n"); - } else { - priv->if_index = CSR_INDEX_2G4; - } - - /* Initialise bh thread structure */ - priv->bh_thread.thread_task = NULL; - priv->bh_thread.block_thread = 1; - init_waitqueue_head(&priv->bh_thread.wakeup_q); - priv->bh_thread.wakeup_flag = 0; - sprintf(priv->bh_thread.name, "uf_bh_thread"); - - /* reset the connected state for the interface */ - interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ - -#ifdef USE_DRIVER_LOCK - sema_init(&priv->lock, 1); -#endif /* USE_DRIVER_LOCK */ - - spin_lock_init(&priv->send_signal_lock); - - spin_lock_init(&priv->m4_lock); - sema_init(&priv->ba_mutex, 1); - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - spin_lock_init(&priv->wapi_lock); -#endif - -#ifdef CSR_SUPPORT_SME - spin_lock_init(&priv->staRecord_lock); - spin_lock_init(&priv->tx_q_lock); -#endif - - /* Create the Traffic Analysis workqueue */ - priv->unifi_workqueue = create_singlethread_workqueue("unifi_workq"); - if (priv->unifi_workqueue == NULL) { - /* Deregister priv->netdev_client */ - ul_deregister_client(priv->netdev_client); - free_netdev(priv->netdev[0]); - return NULL; - } - -#ifdef CSR_SUPPORT_SME - /* Create the Multicast Addresses list work structure */ - INIT_WORK(&priv->multicast_list_task, uf_multicast_list_wq); - - /* Create m4 buffering work structure */ - INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq); - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - /* Create work structure to buffer the WAPI data packets to be sent to SME for encryption */ - INIT_WORK(&interfacePriv->send_pkt_to_encrypt, uf_send_pkt_to_encrypt); -#endif -#endif - - priv->ref_count = 1; - - priv->amp_client = NULL; - priv->coredump_mode = 0; - priv->ptest_mode = 0; - priv->wol_suspend = FALSE; - INIT_LIST_HEAD(&interfacePriv->rx_uncontrolled_list); - INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); - sema_init(&priv->rx_q_sem, 1); - -#ifdef CSR_SUPPORT_WEXT - interfacePriv->netdev_callback_registered = FALSE; - interfacePriv->wait_netdev_change = FALSE; - /* Register callback for netdevice state changes */ - if ((rc = register_netdevice_notifier(&uf_netdev_notifier)) == 0) { - interfacePriv->netdev_callback_registered = TRUE; - } - else { - unifi_warning(priv, "Failed to register netdevice notifier : %d %p\n", rc, dev); - } -#endif /* CSR_SUPPORT_WEXT */ - -#ifdef CSR_WIFI_SPLIT_PATCH - /* set it to some invalid value */ - priv->pending_mode_set.common.destination = 0xaaaa; -#endif - - return priv; -} /* uf_alloc_netdevice() */ - -/* - *--------------------------------------------------------------------------- - * uf_alloc_netdevice_for_other_interfaces - * - * Allocate memory for the net_device and device private structs - * for this interface. - * Fill in the fields, but don't register the interface yet. - * We need to configure the UniFi first. - * - * Arguments: - * interfaceTag Interface number. - * sdio_dev Pointer to SDIO context handle to use for all - * SDIO ops. - * bus_id A small number indicating the SDIO card position on the - * bus. Typically this is the slot number, e.g. 0, 1 etc. - * Valid values are 0 to MAX_UNIFI_DEVS-1. - * - * Returns: - * Pointer to device private struct. - * - * Notes: - * The device private structure contains the interfaceTag and pointer to the unifi_priv - * structure created allocated by net_device od interface0. - * The net_device and device private structs are allocated together - * and should be freed by freeing the net_device pointer. - * --------------------------------------------------------------------------- - */ -u8 -uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag) -{ - struct net_device *dev; - netInterface_priv_t *interfacePriv; - - /* - * Allocate netdevice struct, assign name template and - * setup as an ethernet device. - * The net_device and private structs are zeroed. Ether_setup() then - * sets up ethernet handlers and values. - * The RedHat 9 redhat-config-network tool doesn't recognise wlan* devices, - * so use "eth*" (like other wireless extns drivers). - */ - dev = alloc_etherdev_mq(sizeof(netInterface_priv_t), 1); - if (dev == NULL) { - return FALSE; - } - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_alloc_netdevice_for_other_interfaces bad interfaceTag\n"); - return FALSE; - } - - /* Set up back pointer from priv to netdev */ - interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - interfacePriv->privPtr = priv; - interfacePriv->InterfaceTag = interfaceTag; - priv->netdev[interfaceTag] = dev; - priv->interfacePriv[interfacePriv->InterfaceTag] = interfacePriv; - - /* reset the connected state for the interface */ - interfacePriv->connected = UnifiConnectedUnknown; /* -1 unknown, 0 no, 1 yes */ - INIT_LIST_HEAD(&interfacePriv->rx_uncontrolled_list); - INIT_LIST_HEAD(&interfacePriv->rx_controlled_list); - - /* Setup / override net_device fields */ - dev->netdev_ops = &uf_netdev_ops; - -#ifdef CSR_SUPPORT_WEXT - dev->wireless_handlers = &unifi_iw_handler_def; -#if IW_HANDLER_VERSION < 6 - dev->get_wireless_stats = unifi_get_wireless_stats; -#endif /* IW_HANDLER_VERSION */ -#endif /* CSR_SUPPORT_WEXT */ - return TRUE; -} /* uf_alloc_netdevice() */ - - - -/* - * --------------------------------------------------------------------------- - * uf_free_netdevice - * - * Unregister the network device and free the memory allocated for it. - * NB This includes the memory for the priv struct. - * - * Arguments: - * priv Device private pointer. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -int -uf_free_netdevice(unifi_priv_t *priv) -{ - int i; - unsigned long flags; - - unifi_trace(priv, UDBG1, "uf_free_netdevice\n"); - - if (!priv) { - return -EINVAL; - } - - /* - * Free any buffers used for holding firmware - */ - uf_release_firmware_files(priv); - -#if (defined CSR_SUPPORT_SME) && (defined CSR_SUPPORT_WEXT) - if (priv->connection_config.mlmeAssociateReqInformationElements) { - kfree(priv->connection_config.mlmeAssociateReqInformationElements); - } - priv->connection_config.mlmeAssociateReqInformationElements = NULL; - priv->connection_config.mlmeAssociateReqInformationElementsLength = 0; - - if (priv->mib_data.length) { - vfree(priv->mib_data.data); - } - priv->mib_data.data = NULL; - priv->mib_data.length = 0; - -#endif /* CSR_SUPPORT_SME && CSR_SUPPORT_WEXT*/ - - /* Free any bulkdata buffers allocated for M4 caching */ - spin_lock_irqsave(&priv->m4_lock, flags); - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - if (interfacePriv->m4_bulk_data.data_length > 0) { - unifi_trace(priv, UDBG5, "uf_free_netdevice: free M4 bulkdata %d\n", i); - unifi_net_data_free(priv, &interfacePriv->m4_bulk_data); - } - } - spin_unlock_irqrestore(&priv->m4_lock, flags); - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - /* Free any bulkdata buffers allocated for M4 caching */ - spin_lock_irqsave(&priv->wapi_lock, flags); - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - if (interfacePriv->wapi_unicast_bulk_data.data_length > 0) { - unifi_trace(priv, UDBG5, "uf_free_netdevice: free WAPI PKT bulk data %d\n", i); - unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data); - } - } - spin_unlock_irqrestore(&priv->wapi_lock, flags); -#endif - -#ifdef CSR_SUPPORT_WEXT - /* Unregister callback for netdevice state changes */ - unregister_netdevice_notifier(&uf_netdev_notifier); -#endif /* CSR_SUPPORT_WEXT */ - -#ifdef CSR_SUPPORT_SME - /* Cancel work items and destroy the workqueue */ - cancel_work_sync(&priv->multicast_list_task); -#endif -/* Destroy the workqueues. */ - flush_workqueue(priv->unifi_workqueue); - destroy_workqueue(priv->unifi_workqueue); - - /* Free up netdev in reverse order: priv is allocated with netdev[0]. - * So, netdev[0] should be freed after all other netdevs are freed up - */ - for (i=CSR_WIFI_NUM_INTERFACES-1; i>=0; i--) { - /*Free the netdev struct and priv, which are all one lump*/ - if (priv->netdev[i]) { - unifi_error(priv, "uf_free_netdevice: netdev %d %p\n", i, priv->netdev[i]); - free_netdev(priv->netdev[i]); - } - } - - return 0; -} /* uf_free_netdevice() */ - - -/* - * --------------------------------------------------------------------------- - * uf_net_open - * - * Called when userland does "ifconfig wlan0 up". - * - * Arguments: - * dev Device pointer. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static int -uf_net_open(struct net_device *dev) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - /* If we haven't finished UniFi initialisation, we can't start */ - if (priv->init_progress != UNIFI_INIT_COMPLETED) { - unifi_warning(priv, "%s: unifi not ready, failing net_open\n", __FUNCTION__); - return -EINVAL; - } - -#if (defined CSR_NATIVE_LINUX) && (defined UNIFI_SNIFF_ARPHRD) && defined(CSR_SUPPORT_WEXT) - /* - * To sniff, the user must do "iwconfig mode monitor", which sets - * priv->wext_conf.mode to IW_MODE_MONITOR. - * Then he/she must do "ifconfig ethn up", which calls this fn. - * There is no point in starting the sniff with SNIFFJOIN until - * this point. - */ - if (priv->wext_conf.mode == IW_MODE_MONITOR) { - int err; - err = uf_start_sniff(priv); - if (err) { - return err; - } - netif_carrier_on(dev); - } -#endif - -#ifdef CSR_SUPPORT_WEXT - if (interfacePriv->wait_netdev_change) { - unifi_trace(priv, UDBG1, "%s: Waiting for NETDEV_CHANGE, assume connected\n", - __FUNCTION__); - interfacePriv->connected = UnifiConnected; - interfacePriv->wait_netdev_change = FALSE; - } -#endif - - netif_tx_start_all_queues(dev); - - return 0; -} /* uf_net_open() */ - - -static int -uf_net_stop(struct net_device *dev) -{ -#if defined(CSR_NATIVE_LINUX) && defined(UNIFI_SNIFF_ARPHRD) && defined(CSR_SUPPORT_WEXT) - netInterface_priv_t *interfacePriv = (netInterface_priv_t*)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - /* Stop sniffing if in Monitor mode */ - if (priv->wext_conf.mode == IW_MODE_MONITOR) { - if (priv->card) { - int err; - err = unifi_reset_state(priv, dev->dev_addr, 1); - if (err) { - return err; - } - } - } -#endif - - netif_tx_stop_all_queues(dev); - - return 0; -} /* uf_net_stop() */ - - -/* This is called after the WE handlers */ -static int -uf_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int rc; - - rc = -EOPNOTSUPP; - - return rc; -} /* uf_net_ioctl() */ - - - -static struct net_device_stats * -uf_net_get_stats(struct net_device *dev) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - - return &interfacePriv->stats; -} /* uf_net_get_stats() */ - -static CSR_PRIORITY uf_get_packet_priority(unifi_priv_t *priv, netInterface_priv_t *interfacePriv, struct sk_buff *skb, const int proto) -{ - CSR_PRIORITY priority = CSR_CONTENTION; - - priority = (CSR_PRIORITY) (skb->priority >> 5); - - if (priority == CSR_QOS_UP0) { /* 0 */ - - unifi_trace(priv, UDBG5, "uf_get_packet_priority: proto = 0x%.4X\n", proto); - - switch (proto) { - case 0x0800: /* IPv4 */ - case 0x814C: /* SNMP */ - case 0x880C: /* GSMP */ - priority = (CSR_PRIORITY) (skb->data[1 + ETH_HLEN] >> 5); - break; - - case 0x8100: /* VLAN */ - priority = (CSR_PRIORITY) (skb->data[0 + ETH_HLEN] >> 5); - break; - - case 0x86DD: /* IPv6 */ - priority = (CSR_PRIORITY) ((skb->data[0 + ETH_HLEN] & 0x0E) >> 1); - break; - - default: - priority = CSR_QOS_UP0; - break; - } - } - - /* Check if we are allowed to transmit on this AC. Because of ACM we may have to downgrade to a lower - * priority */ - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) { - unifi_TrafficQueue queue; - - /* Keep trying lower priorities until we find a queue - * Priority to queue mapping is 1,2 - BK, 0,3 - BE, 4,5 - VI, 6,7 - VO */ - queue = unifi_frame_priority_to_queue(priority); - - while (queue > UNIFI_TRAFFIC_Q_BK && !interfacePriv->queueEnabled[queue]) { - queue--; - priority = unifi_get_default_downgrade_priority(queue); - } - } - - unifi_trace(priv, UDBG5, "Packet priority = %d\n", priority); - - return priority; -} - -/* - */ -/* - * --------------------------------------------------------------------------- - * get_packet_priority - * - * Arguments: - * priv private data area of functional driver - * skb socket buffer - * ehdr ethernet header to fetch protocol - * interfacePriv For accessing station record database - * - * - * Returns: - * CSR_PRIORITY. - * --------------------------------------------------------------------------- - */ -CSR_PRIORITY -get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, netInterface_priv_t *interfacePriv) -{ - CSR_PRIORITY priority = CSR_CONTENTION; - const int proto = ntohs(ehdr->h_proto); - - u8 interfaceMode = interfacePriv->interfaceMode; - - /* Priority Mapping for all the Modes */ - switch(interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - unifi_trace(priv, UDBG4, "mode is STA \n"); - if ((priv->sta_wmm_capabilities & QOS_CAPABILITY_WMM_ENABLED) == 1) { - priority = uf_get_packet_priority(priv, interfacePriv, skb, proto); - } else { - priority = CSR_CONTENTION; - } - break; -#ifdef CSR_SUPPORT_SME - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - { - CsrWifiRouterCtrlStaInfo_t * dstStaInfo = - CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfacePriv->InterfaceTag); - unifi_trace(priv, UDBG4, "mode is AP \n"); - if (!(ehdr->h_dest[0] & 0x01) && dstStaInfo && dstStaInfo->wmmOrQosEnabled) { - /* If packet is not Broadcast/multicast */ - priority = uf_get_packet_priority(priv, interfacePriv, skb, proto); - } else { - /* Since packet destination is not QSTA, set priority to CSR_CONTENTION */ - unifi_trace(priv, UDBG4, "Destination is not QSTA or BroadCast/Multicast\n"); - priority = CSR_CONTENTION; - } - } - break; -#endif - default: - unifi_trace(priv, UDBG3, " mode unknown in %s func, mode=%x\n", __FUNCTION__, interfaceMode); - } - unifi_trace(priv, UDBG5, "priority = %x\n", priority); - - return priority; -} - -/* - * --------------------------------------------------------------------------- - * uf_net_select_queue - * - * Called by the kernel to select which queue to put the packet in - * - * Arguments: - * dev Device pointer - * skb Packet - * - * Returns: - * Queue index - * --------------------------------------------------------------------------- - */ -static u16 -uf_net_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = (unifi_priv_t *)interfacePriv->privPtr; - struct ethhdr ehdr; - unifi_TrafficQueue queue; - int proto; - CSR_PRIORITY priority; - - memcpy(&ehdr, skb->data, ETH_HLEN); - proto = ntohs(ehdr.h_proto); - - /* 802.1x - apply controlled/uncontrolled port rules */ - if ((proto != ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - && (proto != ETH_P_WAI) -#endif - ) { - /* queues 0 - 3 */ - priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); - queue = unifi_frame_priority_to_queue(priority); - } else { - /* queue 4 */ - queue = UNIFI_TRAFFIC_Q_EAPOL; - } - - - return (u16)queue; -} /* uf_net_select_queue() */ - -int -skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto) -{ - llc_snap_hdr_t *snap; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int headroom; - - /* get the headroom available in skb */ - headroom = skb_headroom(skb); - /* step 1: classify ether frame, DIX or 802.3? */ - - if (proto < 0x600) { - /* codes <= 1500 reserved for 802.3 lengths */ - /* it's 802.3, pass ether payload unchanged, */ - unifi_trace(priv, UDBG3, "802.3 len: %d\n", skb->len); - - /* leave off any PAD octets. */ - skb_trim(skb, proto); - } else if (proto == ETH_P_8021Q) { - - /* Store the VLAN SNAP (should be 87-65). */ - u16 vlan_snap = *(u16*)skb->data; - /* check for headroom availability before skb_push 14 = (4 + 10) */ - if (headroom < 14) { - unifi_trace(priv, UDBG3, "cant append vlan snap: debug\n"); - return -1; - } - /* Add AA-AA-03-00-00-00 */ - snap = (llc_snap_hdr_t *)skb_push(skb, 4); - snap->dsap = snap->ssap = 0xAA; - snap->ctrl = 0x03; - memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); - - /* Add AA-AA-03-00-00-00 */ - snap = (llc_snap_hdr_t *)skb_push(skb, 10); - snap->dsap = snap->ssap = 0xAA; - snap->ctrl = 0x03; - memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); - - /* Add the VLAN specific information */ - snap->protocol = htons(proto); - *(u16*)(snap + 1) = vlan_snap; - - } else - { - /* it's DIXII, time for some conversion */ - unifi_trace(priv, UDBG3, "DIXII len: %d\n", skb->len); - - /* check for headroom availability before skb_push */ - if (headroom < sizeof(llc_snap_hdr_t)) { - unifi_trace(priv, UDBG3, "cant append snap: debug\n"); - return -1; - } - /* tack on SNAP */ - snap = (llc_snap_hdr_t *)skb_push(skb, sizeof(llc_snap_hdr_t)); - snap->dsap = snap->ssap = 0xAA; - snap->ctrl = 0x03; - /* Use the appropriate OUI. */ - if ((proto == ETH_P_AARP) || (proto == ETH_P_IPX)) { - memcpy(snap->oui, oui_8021h, P80211_OUI_LEN); - } else { - memcpy(snap->oui, oui_rfc1042, P80211_OUI_LEN); - } - snap->protocol = htons(proto); - } - - return 0; -} /* skb_add_llc_snap() */ - -#ifdef CSR_SUPPORT_SME -static int -_identify_sme_ma_pkt_ind(unifi_priv_t *priv, - const s8 *oui, u16 protocol, - const CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata, - const unsigned char *daddr, - const unsigned char *saddr) -{ - CSR_MA_PACKET_INDICATION *pkt_ind = (CSR_MA_PACKET_INDICATION*)&signal->u.MaPacketIndication; - int r; - u8 i; - - unifi_trace(priv, UDBG5, - "_identify_sme_ma_pkt_ind -->\n"); - for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { - if (priv->sme_unidata_ind_filters[i].in_use) { - if (!memcmp(oui, priv->sme_unidata_ind_filters[i].oui, 3) && - (protocol == priv->sme_unidata_ind_filters[i].protocol)) { - - /* Send to client */ - if (priv->sme_cli) { - /* - * Pass the packet to the SME, using unifi_sys_ma_unitdata_ind(). - * The frame needs to be converted according to the encapsulation. - */ - unifi_trace(priv, UDBG1, - "_identify_sme_ma_pkt_ind: handle=%d, encap=%d, proto=%x\n", - i, priv->sme_unidata_ind_filters[i].encapsulation, - priv->sme_unidata_ind_filters[i].protocol); - if (priv->sme_unidata_ind_filters[i].encapsulation == CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET) { - struct sk_buff *skb; - /* The translation is performed on skb... */ - skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - skb->len = bulkdata->d[0].data_length; - - unifi_trace(priv, UDBG1, - "_identify_sme_ma_pkt_ind: skb_80211_to_ether -->\n"); - r = skb_80211_to_ether(priv, skb, daddr, saddr, - signal, bulkdata); - unifi_trace(priv, UDBG1, - "_identify_sme_ma_pkt_ind: skb_80211_to_ether <--\n"); - if (r) { - return -EINVAL; - } - - /* ... but we indicate buffer and length */ - bulkdata->d[0].os_data_ptr = skb->data; - bulkdata->d[0].data_length = skb->len; - } else { - /* Add the MAC addresses before the SNAP */ - bulkdata->d[0].os_data_ptr -= 2*ETH_ALEN; - bulkdata->d[0].data_length += 2*ETH_ALEN; - memcpy((void*)bulkdata->d[0].os_data_ptr, daddr, ETH_ALEN); - memcpy((void*)bulkdata->d[0].os_data_ptr + ETH_ALEN, saddr, ETH_ALEN); - } - - unifi_trace(priv, UDBG1, - "_identify_sme_ma_pkt_ind: unifi_sys_ma_pkt_ind -->\n"); - CsrWifiRouterMaPacketIndSend(priv->sme_unidata_ind_filters[i].appHandle, - (pkt_ind->VirtualInterfaceIdentifier & 0xff), - i, - pkt_ind->ReceptionStatus, - bulkdata->d[0].data_length, - (u8*)bulkdata->d[0].os_data_ptr, - NULL, - pkt_ind->Rssi, - pkt_ind->Snr, - pkt_ind->ReceivedRate); - - - unifi_trace(priv, UDBG1, - "_identify_sme_ma_pkt_ind: unifi_sys_ma_pkt_ind <--\n"); - } - - return 1; - } - } - } - - return -1; -} -#endif /* CSR_SUPPORT_SME */ - -/* - * --------------------------------------------------------------------------- - * skb_80211_to_ether - * - * Make sure the received frame is in Ethernet (802.3) form. - * De-encapsulates SNAP if necessary, adds a ethernet header. - * The source buffer should not contain an 802.11 MAC header - * - * Arguments: - * payload Pointer to packet data received from UniFi. - * payload_length Number of bytes of data received from UniFi. - * daddr Destination MAC address. - * saddr Source MAC address. - * - * Returns: - * 0 on success, -1 if the packet is bad and should be dropped, - * 1 if the packet was forwarded to the SME or AMP client. - * --------------------------------------------------------------------------- - */ -int -skb_80211_to_ether(unifi_priv_t *priv, struct sk_buff *skb, - const unsigned char *daddr, const unsigned char *saddr, - const CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata) -{ - unsigned char *payload; - int payload_length; - struct ethhdr *eth; - llc_snap_hdr_t *snap; - int headroom; -#define UF_VLAN_LLC_HEADER_SIZE 18 - static const u8 vlan_inner_snap[] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 }; -#if defined(CSR_NATIVE_SOFTMAC) && defined(CSR_SUPPORT_SME) - const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; -#endif - - if(skb== NULL || daddr == NULL || saddr == NULL){ - unifi_error(priv, "skb_80211_to_ether: PBC fail\n"); - return 1; - } - - payload = skb->data; - payload_length = skb->len; - - snap = (llc_snap_hdr_t *)payload; - eth = (struct ethhdr *)payload; - - /* get the skb headroom size */ - headroom = skb_headroom(skb); - - /* - * Test for the various encodings - */ - if ((payload_length >= sizeof(llc_snap_hdr_t)) && - (snap->dsap == 0xAA) && - (snap->ssap == 0xAA) && - (snap->ctrl == 0x03) && - (snap->oui[0] == 0) && - (snap->oui[1] == 0) && - ((snap->oui[2] == 0) || (snap->oui[2] == 0xF8))) - { - /* AppleTalk AARP (2) or IPX SNAP */ - if ((snap->oui[2] == 0) && - ((ntohs(snap->protocol) == ETH_P_AARP) || (ntohs(snap->protocol) == ETH_P_IPX))) - { - u16 len; - - unifi_trace(priv, UDBG3, "%s len: %d\n", - (ntohs(snap->protocol) == ETH_P_AARP) ? "ETH_P_AARP" : "ETH_P_IPX", - payload_length); - - /* check for headroom availability before skb_push */ - if (headroom < (2 * ETH_ALEN + 2)) { - unifi_warning(priv, "headroom not available to skb_push ether header\n"); - return -1; - } - - /* Add 802.3 header and leave full payload */ - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), saddr, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), daddr, ETH_ALEN); - - return 0; - } - /* VLAN-tagged IP */ - if ((snap->oui[2] == 0) && (ntohs(snap->protocol) == ETH_P_8021Q)) - { - /* - * The translation doesn't change the packet length, so is done in-place. - * - * Example header (from Std 802.11-2007 Annex M): - * AA-AA-03-00-00-00-81-00-87-65-AA-AA-03-00-00-00-08-06 - * -------SNAP-------p1-p1-ll-ll-------SNAP--------p2-p2 - * dd-dd-dd-dd-dd-dd-aa-aa-aa-aa-aa-aa-p1-p1-ll-ll-p2-p2 - * dd-dd-dd-dd-dd-dd-aa-aa-aa-aa-aa-aa-81-00-87-65-08-06 - */ - u16 vlan_snap; - - if (payload_length < UF_VLAN_LLC_HEADER_SIZE) { - unifi_warning(priv, "VLAN SNAP header too short: %d bytes\n", payload_length); - return -1; - } - - if (memcmp(payload + 10, vlan_inner_snap, 6)) { - unifi_warning(priv, "VLAN malformatted SNAP header.\n"); - return -1; - } - - unifi_trace(priv, UDBG3, "VLAN SNAP: %02x-%02x\n", payload[8], payload[9]); - unifi_trace(priv, UDBG3, "VLAN len: %d\n", payload_length); - - /* Create the 802.3 header */ - - vlan_snap = *((u16*)(payload + 8)); - - /* Create LLC header without byte-swapping */ - eth->h_proto = snap->protocol; - - memcpy(eth->h_dest, daddr, ETH_ALEN); - memcpy(eth->h_source, saddr, ETH_ALEN); - *(u16*)(eth + 1) = vlan_snap; - return 0; - } - - /* it's a SNAP + RFC1042 frame */ - unifi_trace(priv, UDBG3, "SNAP+RFC1042 len: %d\n", payload_length); - - /* chop SNAP+llc header from skb. */ - skb_pull(skb, sizeof(llc_snap_hdr_t)); - - /* Since skb_pull called above to chop snap+llc, no need to check for headroom - * availability before skb_push - */ - /* create 802.3 header at beginning of skb. */ - eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); - memcpy(eth->h_dest, daddr, ETH_ALEN); - memcpy(eth->h_source, saddr, ETH_ALEN); - /* Copy protocol field without byte-swapping */ - eth->h_proto = snap->protocol; - } else { - u16 len; - - /* check for headroom availability before skb_push */ - if (headroom < (2 * ETH_ALEN + 2)) { - unifi_warning(priv, "headroom not available to skb_push ether header\n"); - return -1; - } - /* Add 802.3 header and leave full payload */ - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), saddr, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), daddr, ETH_ALEN); - - return 1; - } - - return 0; -} /* skb_80211_to_ether() */ - - -static CsrWifiRouterCtrlPortAction verify_port(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag) -{ -#ifdef CSR_NATIVE_LINUX -#ifdef CSR_SUPPORT_WEXT - if (queue == UF_CONTROLLED_PORT_Q) { - return priv->wext_conf.block_controlled_port; - } else { - return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; - } -#else - return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; /* default to open for softmac dev */ -#endif -#else - return uf_sme_port_state(priv, address, queue, interfaceTag); -#endif -} - -/* - * --------------------------------------------------------------------------- - * prepare_and_add_macheader - * - * - * These functions adds mac header for packet from netdev - * to UniFi for transmission. - * EAP protocol packets are also appended with Mac header & - * sent using send_ma_pkt_request(). - * - * Arguments: - * priv Pointer to device private context struct - * skb Socket buffer containing data packet to transmit - * newSkb Socket buffer containing data packet + Mac header if no sufficient headroom in skb - * serviceClass to append QOS control header in Mac header - * bulkdata if newSkb allocated then bulkdata updated to send to unifi - * interfaceTag the interfaceID on which activity going on - * daddr destination address - * saddr source address - * protection protection bit set in framce control of mac header - * - * Returns: - * Zero on success or error code. - * --------------------------------------------------------------------------- - */ - -int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk_buff *newSkb, - CSR_PRIORITY priority, - bulk_data_param_t *bulkdata, - u16 interfaceTag, - const u8 *daddr, - const u8 *saddr, - u8 protection) -{ - u16 fc = 0; - u8 qc = 0; - u8 macHeaderLengthInBytes = MAC_HEADER_SIZE, *bufPtr = NULL; - bulk_data_param_t data_ptrs; - CsrResult csrResult; - int headroom =0; - u8 direction = 0; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - u8 *addressOne; - u8 bQosNull = false; - - if (skb == NULL) { - unifi_error(priv, "prepare_and_add_macheader: Invalid SKB reference\n"); - return -1; - } - - /* add a MAC header refer: 7.1.3.1 Frame Control field in P802.11REVmb.book */ - if (priority != CSR_CONTENTION) { - /* EAPOL packets don't go as QOS_DATA */ - if (priority == CSR_MANAGEMENT) { - fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); - } else { - /* Qos Control Field */ - macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; - - if (skb->len) { - - fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_DATA); - } else { - fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_NULL); - bQosNull = true; - } - } - } else { - if(skb->len == 0) { - fc |= cpu_to_le16(IEEE802_11_FC_TYPE_NULL); - } else { - fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); - } - } - - switch (interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - direction = 2; - fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - direction = 0; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - direction = 1; - fc |= cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - if (priority == CSR_MANAGEMENT ) { - - direction = 2; - fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK); - } else { - /* Data frames have to use WDS 4 address frames */ - direction = 3; - fc |= cpu_to_le16(IEEE802_11_FC_TO_DS_MASK | IEEE802_11_FC_FROM_DS_MASK); - macHeaderLengthInBytes += 6; - } - break; - default: - unifi_warning(priv, "prepare_and_add_macheader: Unknown mode %d\n", - interfacePriv->interfaceMode); - } - - - /* If Sta is QOS & HTC is supported then need to set 'order' bit */ - /* We don't support HT Control for now */ - - if(protection) { - fc |= cpu_to_le16(IEEE802_11_FC_PROTECTED_MASK); - } - - /* check the skb headroom before pushing mac header */ - headroom = skb_headroom(skb); - - if (headroom < macHeaderLengthInBytes) { - unifi_trace(priv, UDBG5, - "prepare_and_add_macheader: Allocate headroom extra %d bytes\n", - macHeaderLengthInBytes); - - csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, " failed to allocate request_data. in %s func\n", __FUNCTION__); - return -1; - } - newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); - newSkb->len = skb->len + macHeaderLengthInBytes; - - memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, - skb->data, skb->len); - - bulkdata->d[0].os_data_ptr = newSkb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; - bulkdata->d[0].data_length = newSkb->len; - - bufPtr = (u8*)data_ptrs.d[0].os_data_ptr; - - /* The old skb will not be used again */ - kfree_skb(skb); - } else { - - /* headroom has sufficient size, so will get proper pointer */ - bufPtr = (u8*)skb_push(skb, macHeaderLengthInBytes); - bulkdata->d[0].os_data_ptr = skb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata->d[0].data_length = skb->len; - } - - /* Frame the actual MAC header */ - - memset(bufPtr, 0, macHeaderLengthInBytes); - - /* copy frameControl field */ - memcpy(bufPtr, &fc, sizeof(fc)); - bufPtr += sizeof(fc); - macHeaderLengthInBytes -= sizeof(fc); - - /* Duration/ID field which is 2 bytes */ - bufPtr += 2; - macHeaderLengthInBytes -= 2; - - switch(direction) - { - case 0: - /* Its an Ad-Hoc no need to route it through AP */ - /* Address1: MAC address of the destination from eth header */ - memcpy(bufPtr, daddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address2: MAC address of the source */ - memcpy(bufPtr, saddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address3: the BSSID (locally generated in AdHoc (creators Bssid)) */ - memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - break; - case 1: - /* Address1: MAC address of the actual destination */ - memcpy(bufPtr, daddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - /* Address2: The MAC address of the AP */ - memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address3: MAC address of the source from eth header */ - memcpy(bufPtr, saddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - break; - case 2: - /* Address1: To AP is the MAC address of the AP to which its associated */ - memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address2: MAC address of the source from eth header */ - memcpy(bufPtr, saddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address3: MAC address of the actual destination on the distribution system */ - memcpy(bufPtr, daddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - break; - case 3: - memcpy(bufPtr, &interfacePriv->bssid, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address2: MAC address of the source from eth header */ - memcpy(bufPtr, saddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - - /* Address3: MAC address of the actual destination on the distribution system */ - memcpy(bufPtr, daddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - break; - default: - unifi_error(priv, "Unknown direction =%d : Not handled now\n", direction); - return -1; - } - /* 2 bytes of frame control field, appended by firmware */ - bufPtr += 2; - macHeaderLengthInBytes -= 2; - - if (3 == direction) { - /* Address4: MAC address of the source */ - memcpy(bufPtr, saddr, ETH_ALEN); - bufPtr += ETH_ALEN; - macHeaderLengthInBytes -= ETH_ALEN; - } - - /* IF Qos Data or Qos Null Data then set QosControl field */ - if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) { - - if (priority > 7) { - unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority); - qc |= 7; - } else { - qc |= priority; - } - /*assigning address1 - * Address1 offset taken fromm bufPtr(currently bufPtr pointing to Qos contorl) variable in reverse direction - * Address4 don't exit - */ - - addressOne = bufPtr- ADDRESS_ONE_OFFSET; - - if (addressOne[0] & 0x1) { - /* multicast/broadcast frames, no acknowledgement needed */ - qc |= 1 << 5; - } - /* non-AP mode only for now */ - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) { - /* In case of STA and IBSS case eosp and txop limit is 0. */ - } else { - if(bQosNull) { - qc |= 1 << 4; - } - } - - /* append Qos control field to mac header */ - bufPtr[0] = qc; - /* txop limit is 0 */ - bufPtr[1] = 0; - macHeaderLengthInBytes -= QOS_CONTROL_HEADER_SIZE; - } - if (macHeaderLengthInBytes) { - unifi_warning(priv, " Mac header not appended properly\n"); - return -1; - } - return 0; -} - -/* - * --------------------------------------------------------------------------- - * send_ma_pkt_request - * - * These functions send a data packet to UniFi for transmission. - * EAP protocol packets are also sent as send_ma_pkt_request(). - * - * Arguments: - * priv Pointer to device private context struct - * skb Socket buffer containing data packet to transmit - * ehdr Pointer to Ethernet header within skb. - * - * Returns: - * Zero on success or error code. - * --------------------------------------------------------------------------- - */ - -static int -send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, CSR_PRIORITY priority) -{ - int r; - u16 i; - u8 eapolStore = FALSE; - struct sk_buff *newSkb = NULL; - bulk_data_param_t bulkdata; - const int proto = ntohs(ehdr->h_proto); - u16 interfaceTag; - CsrWifiMacAddress peerAddress; - CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED; - s8 protection; - netInterface_priv_t *interfacePriv = NULL; - CSR_RATE TransmitRate = (CSR_RATE)0; - - unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n"); - - /* Get the interface Tag by means of source Mac address */ - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - if (!memcmp(priv->netdev[i]->dev_addr, ehdr->h_source, ETH_ALEN)) { - interfaceTag = i; - interfacePriv = priv->interfacePriv[interfaceTag]; - break; - } - } - - if (interfacePriv == NULL) { - /* No match found - error */ - interfaceTag = 0; - interfacePriv = priv->interfacePriv[interfaceTag]; - unifi_warning(priv, "Mac address not matching ... debugging needed\n"); - interfacePriv->stats.tx_dropped++; - kfree_skb(skb); - return -1; - } - - /* Add a SNAP header if necessary */ - if (skb_add_llc_snap(priv->netdev[interfaceTag], skb, proto) != 0) { - /* convert failed */ - unifi_error(priv, "skb_add_llc_snap failed.\n"); - kfree_skb(skb); - return -1; - } - - bulkdata.d[0].os_data_ptr = skb->data; - bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; - -#ifdef CSR_SUPPORT_SME - /* Notify the TA module for the Tx frame for non AP/P2PGO mode*/ - if ((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AP) && - (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) { - unifi_ta_sample(priv->card, CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX, - &bulkdata.d[0], ehdr->h_source, - priv->netdev[interfaceTag]->dev_addr, - jiffies_to_msecs(jiffies), - 0); /* rate is unknown on tx */ - } -#endif /* CSR_SUPPORT_SME */ - - if ((proto == ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - || (proto == ETH_P_WAI) -#endif - ) - { - /* check for m4 detection */ - if (0 == uf_verify_m4(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length)) { - eapolStore = TRUE; - } - } - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - if (proto == ETH_P_WAI) - { - protection = 0; /*WAI packets always sent unencrypted*/ - } - else - { -#endif -#ifdef CSR_SUPPORT_SME - if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, ehdr->h_dest)) < 0) { - unifi_warning(priv, "unicast address, but destination not in station record database\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } -#else - protection = 0; -#endif -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - } -#endif - - /* append Mac header for Eapol as well as data packet */ - if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, ehdr->h_dest, ehdr->h_source, protection)) { - unifi_error(priv, "failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } - - /* RA address must contain the immediate destination MAC address that is similar to - * the Address 1 field of 802.11 Mac header here 4 is: (sizeof(framecontrol) + sizeof (durationID)) - * which is address 1 field - */ - memcpy(peerAddress.a, ((u8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); - - unifi_trace(priv, UDBG5, "RA[0]=%x, RA[1]=%x, RA[2]=%x, RA[3]=%x, RA[4]=%x, RA[5]=%x\n", - peerAddress.a[0], peerAddress.a[1], peerAddress.a[2], peerAddress.a[3], - peerAddress.a[4], peerAddress.a[5]); - - - if ((proto == ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - || (proto == ETH_P_WAI) -#endif - ) - { - CSR_SIGNAL signal; - CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; - - /* initialize signal to zero */ - memset(&signal, 0, sizeof(CSR_SIGNAL)); - - /* Frame MA_PACKET request */ - signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; - - transmissionControl = req->TransmissionControl = 0; -#ifdef CSR_SUPPORT_SME - if (eapolStore) - { - netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]); - - /* Fill the MA-PACKET.req */ - - req->Priority = priority; - unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority); - - /* rate selected by firmware */ - req->TransmitRate = 0; - req->HostTag = CSR_WIFI_EAPOL_M4_HOST_TAG; - /* RA address matching with address 1 of Mac header */ - memcpy(req->Ra.x, ((u8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); - - spin_lock(&priv->m4_lock); - /* Store the M4-PACKET.req for later */ - interfacePriv->m4_signal = signal; - interfacePriv->m4_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; - interfacePriv->m4_bulk_data.data_length = bulkdata.d[0].data_length; - interfacePriv->m4_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; - interfacePriv->m4_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; - spin_unlock(&priv->m4_lock); - - /* Signal the workqueue to call CsrWifiRouterCtrlM4ReadyToSendIndSend(). - * It cannot be called directly from the tx path because it - * does a non-atomic kmalloc via the framework's CsrPmemAlloc(). - */ - queue_work(priv->unifi_workqueue, &netpriv->send_m4_ready_task); - - return 0; - } -#endif - }/*EAPOL or WAI packet*/ - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && \ - (priv->wapi_unicast_filter) && \ - (proto != ETH_P_PAE) && \ - (proto != ETH_P_WAI) && \ - (skb->len > 0)) - { - CSR_SIGNAL signal; - CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; - netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]); - - unifi_trace(priv, UDBG4, "send_ma_pkt_request() - WAPI unicast data packet when USKID = 1 \n"); - - /* initialize signal to zero */ - memset(&signal, 0, sizeof(CSR_SIGNAL)); - /* Frame MA_PACKET request */ - signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; - - /* Fill the MA-PACKET.req */ - req->TransmissionControl = 0; - req->Priority = priority; - unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority); - req->TransmitRate = (CSR_RATE) 0; /* rate selected by firmware */ - req->HostTag = 0xffffffff; /* Ask for a new HostTag */ - /* RA address matching with address 1 of Mac header */ - memcpy(req->Ra.x, ((u8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); - - /* Store the M4-PACKET.req for later */ - spin_lock(&priv->wapi_lock); - interfacePriv->wapi_unicast_ma_pkt_sig = signal; - interfacePriv->wapi_unicast_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; - interfacePriv->wapi_unicast_bulk_data.data_length = bulkdata.d[0].data_length; - interfacePriv->wapi_unicast_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; - interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; - spin_unlock(&priv->wapi_lock); - - /* Signal the workqueue to call CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(). - * It cannot be called directly from the tx path because it - * does a non-atomic kmalloc via the framework's CsrPmemAlloc(). - */ - queue_work(priv->unifi_workqueue, &netpriv->send_pkt_to_encrypt); - - return 0; - } -#endif - - if(priv->cmanrTestMode) - { - TransmitRate = priv->cmanrTestModeTransmitRate; - unifi_trace(priv, UDBG2, "send_ma_pkt_request: cmanrTestModeTransmitRate = %d TransmitRate=%d\n", - priv->cmanrTestModeTransmitRate, - TransmitRate - ); - } - - /* Send UniFi msg */ - /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */ - r = uf_process_ma_packet_req(priv, - peerAddress.a, - 0xffffffff, /* Ask for a new HostTag */ - interfaceTag, - transmissionControl, - TransmitRate, - priority, - priv->netdev_client->sender_id, - &bulkdata); - - if (r) { - unifi_trace(priv, UDBG1, "(HIP validation failure) r = %x\n", r); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } - - unifi_trace(priv, UDBG3, "leaving send_ma_pkt_request, UNITDATA result code = %d\n", r); - - return r; -} /* send_ma_pkt_request() */ - -/* - * --------------------------------------------------------------------------- - * uf_net_xmit - * - * This function is called by the higher level stack to transmit an - * ethernet packet. - * - * Arguments: - * skb Ethernet packet to send. - * dev Pointer to the linux net device. - * - * Returns: - * 0 on success (packet was consumed, not necessarily transmitted) - * 1 if packet was requeued - * -1 on error - * - * - * Notes: - * The controlled port is handled in the qdisc dequeue handler. - * --------------------------------------------------------------------------- - */ -static netdev_tx_t -uf_net_xmit(struct sk_buff *skb, struct net_device *dev) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct ethhdr ehdr; - int proto, port; - int result; - static tx_signal_handler tx_handler; - CSR_PRIORITY priority; - CsrWifiRouterCtrlPortAction port_action; - - unifi_trace(priv, UDBG5, "unifi_net_xmit: skb = %x\n", skb); - - memcpy(&ehdr, skb->data, ETH_HLEN); - proto = ntohs(ehdr.h_proto); - priority = get_packet_priority(priv, skb, &ehdr, interfacePriv); - - /* All frames are sent as MA-PACKET.req (EAPOL also) */ - tx_handler = send_ma_pkt_request; - - /* 802.1x - apply controlled/uncontrolled port rules */ - if ((proto != ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - && (proto != ETH_P_WAI) -#endif - ) { - port = UF_CONTROLLED_PORT_Q; - } else { - /* queue 4 */ - port = UF_UNCONTROLLED_PORT_Q; - } - - /* Uncontrolled port rules apply */ - port_action = verify_port(priv - , (((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode)||(CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI== interfacePriv->interfaceMode))? interfacePriv->bssid.a: ehdr.h_dest) - , port - , interfacePriv->InterfaceTag); - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - unifi_trace(priv, UDBG5, - "uf_net_xmit: %s controlled port open\n", - port ? "" : "un"); - /* Remove the ethernet header */ - skb_pull(skb, ETH_HLEN); - result = tx_handler(priv, skb, &ehdr, priority); - } else { - - /* Discard the packet if necessary */ - unifi_trace(priv, UDBG2, - "uf_net_xmit: %s controlled port %s\n", - port ? "" : "un", port_action==CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK ? "blocked" : "closed"); - interfacePriv->stats.tx_dropped++; - kfree_skb(skb); - - return NETDEV_TX_OK; - } - - if (result == NETDEV_TX_OK) { -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - /* Don't update the tx stats when the pkt is to be sent for sw encryption*/ - if (!((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && - (priv->wapi_unicast_filter == 1))) - { - dev->trans_start = jiffies; - /* Should really count tx stats in the UNITDATA.status signal but - * that doesn't have the length. - */ - interfacePriv->stats.tx_packets++; - /* count only the packet payload */ - interfacePriv->stats.tx_bytes += skb->len; - - } -#else - dev->trans_start = jiffies; - - /* - * Should really count tx stats in the UNITDATA.status signal but - * that doesn't have the length. - */ - interfacePriv->stats.tx_packets++; - /* count only the packet payload */ - interfacePriv->stats.tx_bytes += skb->len; -#endif - } else if (result < 0) { - - /* Failed to send: fh queue was full, and the skb was discarded. - * Return OK to indicate that the buffer was consumed, to stop the - * kernel re-transmitting the freed buffer. - */ - interfacePriv->stats.tx_dropped++; - unifi_trace(priv, UDBG1, "unifi_net_xmit: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped); - result = NETDEV_TX_OK; - } - - /* The skb will have been freed by send_XXX_request() */ - - return result; -} /* uf_net_xmit() */ - -/* - * --------------------------------------------------------------------------- - * unifi_pause_xmit - * unifi_restart_xmit - * - * These functions are called from the UniFi core to control the flow - * of packets from the upper layers. - * unifi_pause_xmit() is called when the internal queue is full and - * should take action to stop unifi_ma_unitdata() being called. - * When the queue has drained, unifi_restart_xmit() will be called to - * re-enable the flow of packets for transmission. - * - * Arguments: - * ospriv OS private context pointer. - * - * Returns: - * unifi_pause_xmit() is called from interrupt context. - * --------------------------------------------------------------------------- - */ -void -unifi_pause_xmit(void *ospriv, unifi_TrafficQueue queue) -{ - unifi_priv_t *priv = ospriv; - int i; /* used as a loop counter */ - - unifi_trace(priv, UDBG2, "Stopping queue %d\n", queue); - - for(i=0;inetdev[i])) - { - netif_stop_subqueue(priv->netdev[i], (u16)queue); - } - } - -#ifdef CSR_SUPPORT_SME - if(queue<=3) { - routerStartBuffering(priv, queue); - unifi_trace(priv, UDBG2, "Start buffering %d\n", queue); - } else { - routerStartBuffering(priv, 0); - unifi_error(priv, "Start buffering %d defaulting to 0\n", queue); - } -#endif - -} /* unifi_pause_xmit() */ - -void -unifi_restart_xmit(void *ospriv, unifi_TrafficQueue queue) -{ - unifi_priv_t *priv = ospriv; - int i=0; /* used as a loop counter */ - - unifi_trace(priv, UDBG2, "Waking queue %d\n", queue); - - for(i=0;inetdev[i])) - { - netif_wake_subqueue(priv->netdev[i], (u16)queue); - } - } - -#ifdef CSR_SUPPORT_SME - if(queue <=3) { - routerStopBuffering(priv, queue); - uf_send_buffered_frames(priv, queue); - } else { - routerStopBuffering(priv, 0); - uf_send_buffered_frames(priv, 0); - } -#endif -} /* unifi_restart_xmit() */ - - -static void -indicate_rx_skb(unifi_priv_t *priv, u16 ifTag, u8* dst_a, u8* src_a, struct sk_buff *skb, CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata) -{ - int r, sr = 0; - struct net_device *dev; - -#ifdef CSR_SUPPORT_SME - llc_snap_hdr_t *snap; - - snap = (llc_snap_hdr_t *)skb->data; - - sr = _identify_sme_ma_pkt_ind(priv, - snap->oui, ntohs(snap->protocol), - signal, - bulkdata, - dst_a, src_a ); -#endif - - /* - * Decapsulate any SNAP header and - * prepend an ethernet header so that the skb manipulation and ARP - * stuff works. - */ - r = skb_80211_to_ether(priv, skb, dst_a, src_a, - signal, bulkdata); - if (r == -1) { - /* Drop the packet and return */ - priv->interfacePriv[ifTag]->stats.rx_errors++; - priv->interfacePriv[ifTag]->stats.rx_frame_errors++; - unifi_net_data_free(priv, &bulkdata->d[0]); - unifi_notice(priv, "indicate_rx_skb: Discard unknown frame.\n"); - return; - } - - /* Handle the case where packet is sent up through the subscription - * API but should not be given to the network stack (AMP PAL case) - * LLC header is different from WiFi and the packet has been subscribed for - */ - if (r == 1 && sr == 1) { - unifi_net_data_free(priv, &bulkdata->d[0]); - unifi_trace(priv, UDBG5, "indicate_rx_skb: Data given to subscription" - "API, not being given to kernel\n"); - return; - } - - dev = priv->netdev[ifTag]; - /* Now we look like a regular ethernet frame */ - /* Fill in SKB meta data */ - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Test for an overlength frame */ - if (skb->len > (dev->mtu + ETH_HLEN)) { - /* A bogus length ethfrm has been encap'd. */ - /* Is someone trying an oflow attack? */ - unifi_error(priv, "%s: oversize frame (%d > %d)\n", - dev->name, - skb->len, dev->mtu + ETH_HLEN); - - /* Drop the packet and return */ - priv->interfacePriv[ifTag]->stats.rx_errors++; - priv->interfacePriv[ifTag]->stats.rx_length_errors++; - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - - if(priv->cmanrTestMode) - { - const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; - priv->cmanrTestModeTransmitRate = pkt_ind->ReceivedRate; - unifi_trace(priv, UDBG2, "indicate_rx_skb: cmanrTestModeTransmitRate=%d\n", priv->cmanrTestModeTransmitRate); - } - - /* Pass SKB up the stack */ -#ifdef CSR_WIFI_USE_NETIF_RX - netif_rx(skb); -#else - netif_rx_ni(skb); -#endif - - if (dev != NULL) { - dev->last_rx = jiffies; - } - - /* Bump rx stats */ - priv->interfacePriv[ifTag]->stats.rx_packets++; - priv->interfacePriv[ifTag]->stats.rx_bytes += bulkdata->d[0].data_length; - - return; -} - -void -uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, - CsrWifiMacAddress source_address, - int indicate, u16 interfaceTag) -{ - rx_buffered_packets_t *rx_q_item; - struct list_head *rx_list; - struct list_head *n; - struct list_head *l_h; - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_process_rx_pending_queue bad interfaceTag\n"); - return; - } - - if (queue == UF_CONTROLLED_PORT_Q) { - rx_list = &interfacePriv->rx_controlled_list; - } else { - rx_list = &interfacePriv->rx_uncontrolled_list; - } - - down(&priv->rx_q_sem); - list_for_each_safe(l_h, n, rx_list) { - rx_q_item = list_entry(l_h, rx_buffered_packets_t, q); - - /* Validate against the source address */ - if (memcmp(broadcast_address.a, source_address.a, ETH_ALEN) && - memcmp(rx_q_item->sa.a, source_address.a, ETH_ALEN)) { - - unifi_trace(priv, UDBG2, - "uf_process_rx_pending_queue: Skipping sa=%02X%02X%02X%02X%02X%02X skb=%p, bulkdata=%p\n", - rx_q_item->sa.a[0], rx_q_item->sa.a[1], - rx_q_item->sa.a[2], rx_q_item->sa.a[3], - rx_q_item->sa.a[4], rx_q_item->sa.a[5], - rx_q_item->skb, &rx_q_item->bulkdata.d[0]); - continue; - } - - list_del(l_h); - - - unifi_trace(priv, UDBG2, - "uf_process_rx_pending_queue: Was Blocked skb=%p, bulkdata=%p\n", - rx_q_item->skb, &rx_q_item->bulkdata); - - if (indicate) { - indicate_rx_skb(priv, interfaceTag, rx_q_item->da.a, rx_q_item->sa.a, rx_q_item->skb, &rx_q_item->signal, &rx_q_item->bulkdata); - } else { - interfacePriv->stats.rx_dropped++; - unifi_net_data_free(priv, &rx_q_item->bulkdata.d[0]); - } - - /* It is our resposibility to free the Rx structure object. */ - kfree(rx_q_item); - } - up(&priv->rx_q_sem); -} - -/* - * --------------------------------------------------------------------------- - * uf_resume_data_plane - * - * Is called when the (un)controlled port is set to open, - * to notify the network stack to schedule for transmission - * any packets queued in the qdisk while port was closed and - * indicated to the stack any packets buffered in the Rx queues. - * - * Arguments: - * priv Pointer to device private struct - * - * Returns: - * --------------------------------------------------------------------------- - */ -void -uf_resume_data_plane(unifi_priv_t *priv, int queue, - CsrWifiMacAddress peer_address, - u16 interfaceTag) -{ -#ifdef CSR_SUPPORT_WEXT - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; -#endif - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_resume_data_plane bad interfaceTag\n"); - return; - } - - unifi_trace(priv, UDBG2, "Resuming netif\n"); - - /* - * If we are waiting for the net device to enter the up state, don't - * process the rx queue yet as it will be done by the callback when - * the device is ready. - */ -#ifdef CSR_SUPPORT_WEXT - if (!interfacePriv->wait_netdev_change) -#endif - { -#ifdef CONFIG_NET_SCHED - if (netif_running(priv->netdev[interfaceTag])) { - netif_tx_schedule_all(priv->netdev[interfaceTag]); - } -#endif - uf_process_rx_pending_queue(priv, queue, peer_address, 1, interfaceTag); - } -} /* uf_resume_data_plane() */ - - -void uf_free_pending_rx_packets(unifi_priv_t *priv, int queue, CsrWifiMacAddress peer_address, u16 interfaceTag) -{ - uf_process_rx_pending_queue(priv, queue, peer_address, 0, interfaceTag); - -} /* uf_free_pending_rx_packets() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_rx - * - * Reformat a UniFi data received packet into a p80211 packet and - * pass it up the protocol stack. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -unifi_rx(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) -{ - u16 interfaceTag; - bulk_data_desc_t *pData; - const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication; - struct sk_buff *skb; - CsrWifiRouterCtrlPortAction port_action; - u8 dataFrameType; - int proto; - int queue; - - u8 da[ETH_ALEN], sa[ETH_ALEN]; - u8 toDs, fromDs, frameType, macHeaderLengthInBytes = MAC_HEADER_SIZE; - u16 frameControl; - netInterface_priv_t *interfacePriv; - struct ethhdr ehdr; - - interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff); - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Sanity check that the VIF refers to a sensible interface */ - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - /* Sanity check that the VIF refers to an allocated netdev */ - if (!interfacePriv->netdev_registered) - { - unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - if (bulkdata->d[0].data_length == 0) { - unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - - skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - skb->len = bulkdata->d[0].data_length; - - /* Point to the addresses */ - toDs = (skb->data[1] & 0x01) ? 1 : 0; - fromDs = (skb->data[1] & 0x02) ? 1 : 0; - - memcpy(da, (skb->data+4+toDs*12), ETH_ALEN);/* Address1 or 3 */ - memcpy(sa, (skb->data+10+fromDs*(6+toDs*8)), ETH_ALEN); /* Address2, 3 or 4 */ - - - pData = &bulkdata->d[0]; - frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr); - frameType = ((frameControl & 0x000C) >> 2); - - dataFrameType =((frameControl & 0x00f0) >> 4); - unifi_trace(priv, UDBG6, - "%s: Receive Data Frame Type %d \n", __FUNCTION__, dataFrameType); - - switch(dataFrameType) - { - case QOS_DATA: - case QOS_DATA_NULL: - /* If both are set then the Address4 exists (only for AP) */ - if (fromDs && toDs) - { - /* 6 is the size of Address4 field */ - macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6); - } - else - { - macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; - } - - /* If order bit set then HT control field is the part of MAC header */ - if (frameControl & FRAME_CONTROL_ORDER_BIT) - macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE; - break; - default: - if (fromDs && toDs) - macHeaderLengthInBytes += 6; - } - - /* Prepare the ethernet header from snap header of skb data */ - switch(dataFrameType) - { - case DATA_NULL: - case QOS_DATA_NULL: - /* This is for only queue info fetching, EAPOL wont come as - * null data so the proto is initialized as zero - */ - proto = 0x0; - break; - default: - { - llc_snap_hdr_t *snap; - /* Fetch a snap header to find protocol (for IPV4/IPV6 packets - * the snap header fetching offset is same) - */ - snap = (llc_snap_hdr_t *) (skb->data + macHeaderLengthInBytes); - - /* prepare the ethernet header from the snap header & addresses */ - ehdr.h_proto = snap->protocol; - memcpy(ehdr.h_dest, da, ETH_ALEN); - memcpy(ehdr.h_source, sa, ETH_ALEN); - } - proto = ntohs(ehdr.h_proto); - } - unifi_trace(priv, UDBG3, "in unifi_rx protocol from snap header = 0x%x\n", proto); - - if ((proto != ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - && (proto != ETH_P_WAI) -#endif - ) { - queue = UF_CONTROLLED_PORT_Q; - } else { - queue = UF_UNCONTROLLED_PORT_Q; - } - - port_action = verify_port(priv, (unsigned char*)sa, queue, interfaceTag); - unifi_trace(priv, UDBG3, "in unifi_rx port action is = 0x%x & queue = %x\n", port_action, queue); - -#ifdef CSR_SUPPORT_SME - /* Notify the TA module for the Rx frame for non P2PGO and AP cases*/ - if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AP) && - (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) - { - /* Remove MAC header of length(macHeaderLengthInBytes) before sampling */ - skb_pull(skb, macHeaderLengthInBytes); - pData->os_data_ptr = skb->data; - pData->data_length -= macHeaderLengthInBytes; - - if (pData->data_length) { - unifi_ta_sample(priv->card, CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX, - &bulkdata->d[0], - sa, priv->netdev[interfaceTag]->dev_addr, - jiffies_to_msecs(jiffies), - pkt_ind->ReceivedRate); - } - } else { - - /* AP/P2PGO specific handling here */ - CsrWifiRouterCtrlStaInfo_t * srcStaInfo = - CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, sa, interfaceTag); - - /* Defensive check only; Source address is already checked in - process_ma_packet_ind and we should have a valid source address here */ - - if(srcStaInfo == NULL) { - CsrWifiMacAddress peerMacAddress; - /* Unknown data PDU */ - memcpy(peerMacAddress.a, sa, ETH_ALEN); - unifi_trace(priv, UDBG1, "%s: Unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", __FUNCTION__, - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - /* For AP GO mode, don't store the PDUs */ - if (port_action != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - /* Drop the packet and return */ - CsrWifiMacAddress peerMacAddress; - memcpy(peerMacAddress.a, sa, ETH_ALEN); - unifi_trace(priv, UDBG3, "%s: Port is not open: unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", - __FUNCTION__, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - - CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - interfacePriv->stats.rx_dropped++; - unifi_net_data_free(priv, &bulkdata->d[0]); - unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n", __FUNCTION__, - proto, queue ? "Controlled" : "Un-controlled"); - return; - } - - /* Qos NULL/Data NULL are freed here and not processed further */ - if((dataFrameType == QOS_DATA_NULL) || (dataFrameType == DATA_NULL)){ - unifi_trace(priv, UDBG5, "%s: Null Frame Received and Freed\n", __FUNCTION__); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - /* Now we have done with MAC header so proceed with the real data part*/ - /* This function takes care of appropriate routing for AP/P2PGO case*/ - /* the function hadnles following things - 2. Routing the PDU to appropriate location - 3. Error case handling - */ - if(!(uf_ap_process_data_pdu(priv, skb, &ehdr, srcStaInfo, - signal, - bulkdata, - macHeaderLengthInBytes))) - { - return; - } - unifi_trace(priv, UDBG5, "unifi_rx: no specific AP handling process as normal frame, MAC Header len %d\n", macHeaderLengthInBytes); - /* Remove the MAC header for subsequent conversion */ - skb_pull(skb, macHeaderLengthInBytes); - pData->os_data_ptr = skb->data; - pData->data_length -= macHeaderLengthInBytes; - pData->os_net_buf_ptr = (unsigned char*)skb; - pData->net_buf_length = skb->len; - } -#endif /* CSR_SUPPORT_SME */ - - - /* Now that the MAC header is removed, null-data frames have zero length - * and can be dropped - */ - if (pData->data_length == 0) { - if (((frameControl & 0x00f0) >> 4) != QOS_DATA_NULL && - ((frameControl & 0x00f0) >> 4) != DATA_NULL) { - unifi_trace(priv, UDBG1, "Zero length frame, but not null-data %04x\n", frameControl); - } - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - /* Drop the packet and return */ - interfacePriv->stats.rx_dropped++; - unifi_net_data_free(priv, &bulkdata->d[0]); - unifi_notice(priv, "%s: Dropping packet, proto=0x%04x, %s port\n", - __FUNCTION__, proto, queue ? "controlled" : "uncontrolled"); - return; - } else if ( (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK) || - (interfacePriv->connected != UnifiConnected) ) { - - /* Buffer the packet into the Rx queues */ - rx_buffered_packets_t *rx_q_item; - struct list_head *rx_list; - - rx_q_item = kmalloc(sizeof(rx_buffered_packets_t), - GFP_KERNEL); - if (rx_q_item == NULL) { - unifi_error(priv, "%s: Failed to allocate %d bytes for rx packet record\n", - __FUNCTION__, sizeof(rx_buffered_packets_t)); - interfacePriv->stats.rx_dropped++; - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - INIT_LIST_HEAD(&rx_q_item->q); - rx_q_item->bulkdata = *bulkdata; - rx_q_item->skb = skb; - rx_q_item->signal = *signal; - memcpy(rx_q_item->sa.a, sa, ETH_ALEN); - memcpy(rx_q_item->da.a, da, ETH_ALEN); - unifi_trace(priv, UDBG2, "%s: Blocked skb=%p, bulkdata=%p\n", - __FUNCTION__, rx_q_item->skb, &rx_q_item->bulkdata); - - if (queue == UF_CONTROLLED_PORT_Q) { - rx_list = &interfacePriv->rx_controlled_list; - } else { - rx_list = &interfacePriv->rx_uncontrolled_list; - } - - /* Add to tail of packets queue */ - down(&priv->rx_q_sem); - list_add_tail(&rx_q_item->q, rx_list); - up(&priv->rx_q_sem); - - return; - - } - - indicate_rx_skb(priv, interfaceTag, da, sa, skb, signal, bulkdata); - -} /* unifi_rx() */ - -static void process_ma_packet_cfm(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) -{ - u16 interfaceTag; - const CSR_MA_PACKET_CONFIRM *pkt_cfm = &signal->u.MaPacketConfirm; - netInterface_priv_t *interfacePriv; - - interfaceTag = (pkt_cfm->VirtualInterfaceIdentifier & 0xff); - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Sanity check that the VIF refers to a sensible interface */ - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "%s: MA-PACKET confirm with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); - return; - } -#ifdef CSR_SUPPORT_SME - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - - uf_process_ma_pkt_cfm_for_ap(priv, interfaceTag, pkt_cfm); - } else if (interfacePriv->m4_sent && (pkt_cfm->HostTag == interfacePriv->m4_hostTag)) { - /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/ - CsrResult result = pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE; - CsrWifiMacAddress peerMacAddress; - memcpy(peerMacAddress.a, interfacePriv->m4_signal.u.MaPacketRequest.Ra.x, ETH_ALEN); - - unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__); - CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, - interfaceTag, - peerMacAddress, - result); - interfacePriv->m4_sent = FALSE; - interfacePriv->m4_hostTag = 0xffffffff; - } -#endif - return; -} - - -/* - * --------------------------------------------------------------------------- - * unifi_rx - * - * Reformat a UniFi data received packet into a p80211 packet and - * pass it up the protocol stack. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) -{ - u16 interfaceTag; - bulk_data_desc_t *pData; - CSR_MA_PACKET_INDICATION *pkt_ind = (CSR_MA_PACKET_INDICATION*)&signal->u.MaPacketIndication; - struct sk_buff *skb; - u16 frameControl; - netInterface_priv_t *interfacePriv; - u8 da[ETH_ALEN], sa[ETH_ALEN]; - u8 *bssid = NULL, *ba_addr = NULL; - u8 toDs, fromDs, frameType; - u8 i =0; - -#ifdef CSR_SUPPORT_SME - u8 dataFrameType = 0; - u8 powerSaveChanged = FALSE; - u8 pmBit = 0; - CsrWifiRouterCtrlStaInfo_t *srcStaInfo = NULL; - u16 qosControl; - -#endif - - interfaceTag = (pkt_ind->VirtualInterfaceIdentifier & 0xff); - interfacePriv = priv->interfacePriv[interfaceTag]; - - - /* Sanity check that the VIF refers to a sensible interface */ - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "%s: MA-PACKET indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - /* Sanity check that the VIF refers to an allocated netdev */ - if (!interfacePriv->netdev_registered) - { - unifi_error(priv, "%s: MA-PACKET indication with unallocated interfaceTag %d\n", __FUNCTION__, interfaceTag); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - if (bulkdata->d[0].data_length == 0) { - unifi_warning(priv, "%s: MA-PACKET indication with zero bulk data\n", __FUNCTION__); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - /* For monitor mode we need to pass this indication to the registered application - handle this separately*/ - /* MIC failure is already taken care of so no need to send the PDUs which are not successfully received in non-monitor mode*/ - if(pkt_ind->ReceptionStatus != CSR_RX_SUCCESS) - { - unifi_warning(priv, "%s: MA-PACKET indication with status = %d\n", __FUNCTION__, pkt_ind->ReceptionStatus); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - - skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - skb->len = bulkdata->d[0].data_length; - - /* Point to the addresses */ - toDs = (skb->data[1] & 0x01) ? 1 : 0; - fromDs = (skb->data[1] & 0x02) ? 1 : 0; - - memcpy(da, (skb->data+4+toDs*12), ETH_ALEN);/* Address1 or 3 */ - memcpy(sa, (skb->data+10+fromDs*(6+toDs*8)), ETH_ALEN); /* Address2, 3 or 4 */ - - /* Find the BSSID, which will be used to match the BA session */ - if (toDs && fromDs) - { - unifi_trace(priv, UDBG6, "4 address frame - don't try to find BSSID\n"); - bssid = NULL; - } - else - { - bssid = (u8 *) (skb->data + 4 + 12 - (fromDs * 6) - (toDs * 12)); - } - - pData = &bulkdata->d[0]; - frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr); - frameType = ((frameControl & 0x000C) >> 2); - - unifi_trace(priv, UDBG3, "Rx Frame Type: %d sn: %d\n", frameType, - (le16_to_cpu(*((u16*)(bulkdata->d[0].os_data_ptr + IEEE802_11_SEQUENCE_CONTROL_OFFSET))) >> 4) & 0xfff); - if(frameType == IEEE802_11_FRAMETYPE_CONTROL){ -#ifdef CSR_SUPPORT_SME - unifi_trace(priv, UDBG6, "%s: Received Control Frame\n", __FUNCTION__); - - if((frameControl & 0x00f0) == 0x00A0){ - /* This is a PS-POLL request */ - u8 pmBit = (frameControl & 0x1000)?0x01:0x00; - unifi_trace(priv, UDBG6, "%s: Received PS-POLL Frame\n", __FUNCTION__); - - uf_process_ps_poll(priv, sa, da, pmBit, interfaceTag); - } - else { - unifi_warning(priv, "%s: Non PS-POLL control frame is received\n", __FUNCTION__); - } -#endif - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - if(frameType != IEEE802_11_FRAMETYPE_DATA) { - unifi_warning(priv, "%s: Non control Non Data frame is received\n", __FUNCTION__); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - -#ifdef CSR_SUPPORT_SME - if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || - (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)){ - - srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, sa, interfaceTag); - - if(srcStaInfo == NULL) { - CsrWifiMacAddress peerMacAddress; - /* Unknown data PDU */ - memcpy(peerMacAddress.a, sa, ETH_ALEN); - unifi_trace(priv, UDBG1, "%s: Unexpected frame from peer = %x:%x:%x:%x:%x:%x\n", __FUNCTION__, - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - unifi_net_data_free(priv, &bulkdata->d[0]); - return; - } - - /* - verify power management bit here so as to ensure host and unifi are always - in sync with power management status of peer. - - If we do it later, it may so happen we have stored the frame in BA re-ordering - buffer and hence host and unifi are out of sync for power management status - */ - - pmBit = (frameControl & 0x1000)?0x01:0x00; - powerSaveChanged = uf_process_pm_bit_for_peer(priv, srcStaInfo, pmBit, interfaceTag); - - /* Update station last activity time */ - srcStaInfo->activity_flag = TRUE; - - /* For Qos Frame if PM bit is toggled to indicate the change in power save state then it shall not be - considered as Trigger Frame. Enter only if WMM STA and peer is in Power save */ - - dataFrameType = ((frameControl & 0x00f0) >> 4); - - if((powerSaveChanged == FALSE)&&(srcStaInfo->wmmOrQosEnabled == TRUE)&& - (srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)){ - - if((dataFrameType == QOS_DATA) || (dataFrameType == QOS_DATA_NULL)){ - - /* - * QoS control field is offset from frame control by 2 (frame control) - * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN - */ - if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){ - qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30); - } - else{ - qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24); - } - unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n", __FUNCTION__, qosControl); - uf_process_wmm_deliver_ac_uapsd(priv, srcStaInfo, qosControl, interfaceTag); - } - } - } - -#endif - - if( ((frameControl & 0x00f0) >> 4) == QOS_DATA) { - u8 *qos_control_ptr = (u8*)bulkdata->d[0].os_data_ptr + (((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK))?30: 24); - int tID = *qos_control_ptr & IEEE802_11_QC_TID_MASK; /* using ls octet of qos control */ - ba_session_rx_struct *ba_session; - u8 ba_session_idx = 0; - /* Get the BA originator address */ - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO){ - ba_addr = sa; - }else{ - ba_addr = bssid; - } - - down(&priv->ba_mutex); - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session = interfacePriv->ba_session_rx[ba_session_idx]; - if (ba_session){ - unifi_trace(priv, UDBG6, "found ba_session=0x%x ba_session_idx=%d", ba_session, ba_session_idx); - if ((!memcmp(ba_session->macAddress.a, ba_addr, ETH_ALEN)) && (ba_session->tID == tID)){ - frame_desc_struct frame_desc; - frame_desc.bulkdata = *bulkdata; - frame_desc.signal = *signal; - frame_desc.sn = (le16_to_cpu(*((u16*)(bulkdata->d[0].os_data_ptr + IEEE802_11_SEQUENCE_CONTROL_OFFSET))) >> 4) & 0xfff; - frame_desc.active = TRUE; - unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx); - process_ba_frame(priv, interfacePriv, ba_session, &frame_desc); - up(&priv->ba_mutex); - process_ba_complete(priv, interfacePriv); - break; - } - } - } - if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ - up(&priv->ba_mutex); - unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__); - process_amsdu(priv, signal, bulkdata); - } - } else { - unifi_trace(priv, UDBG6, "calling unifi_rx()"); - unifi_rx(priv, signal, bulkdata); - } - - /* check if the frames in reorder buffer has aged, the check - * is done after receive processing so that if the missing frame - * has arrived in this receive process, then it is handled cleanly. - * - * And also this code here takes care that timeout check is made for all - * the receive indications - */ - down(&priv->ba_mutex); - for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){ - ba_session_rx_struct *ba_session; - ba_session = interfacePriv->ba_session_rx[i]; - if (ba_session){ - check_ba_frame_age_timeout(priv, interfacePriv, ba_session); - } - } - up(&priv->ba_mutex); - process_ba_complete(priv, interfacePriv); - -} -/* - * --------------------------------------------------------------------------- - * uf_set_multicast_list - * - * This function is called by the higher level stack to set - * a list of multicast rx addresses. - * - * Arguments: - * dev Network Device pointer. - * - * Returns: - * None. - * - * Notes: - * --------------------------------------------------------------------------- - */ - -static void -uf_set_multicast_list(struct net_device *dev) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - -#ifdef CSR_NATIVE_LINUX - unifi_trace(priv, UDBG3, "uf_set_multicast_list unsupported\n"); - return; -#else - - u8 *mc_list = interfacePriv->mc_list; - struct netdev_hw_addr *mc_addr; - int mc_addr_count; - - if (priv->init_progress != UNIFI_INIT_COMPLETED) { - return; - } - - mc_addr_count = netdev_mc_count(dev); - - unifi_trace(priv, UDBG3, - "uf_set_multicast_list (count=%d)\n", mc_addr_count); - - - /* Not enough space? */ - if (mc_addr_count > UNIFI_MAX_MULTICAST_ADDRESSES) { - return; - } - - /* Store the list to be processed by the work item. */ - interfacePriv->mc_list_count = mc_addr_count; - netdev_hw_addr_list_for_each(mc_addr, &dev->mc) { - memcpy(mc_list, mc_addr->addr, ETH_ALEN); - mc_list += ETH_ALEN; - } - - /* Send a message to the workqueue */ - queue_work(priv->unifi_workqueue, &priv->multicast_list_task); -#endif - -} /* uf_set_multicast_list() */ - -/* - * --------------------------------------------------------------------------- - * netdev_mlme_event_handler - * - * Callback function to be used as the udi_event_callback when registering - * as a netdev client. - * To use it, a client specifies this function as the udi_event_callback - * to ul_register_client(). The signal dispatcher in - * unifi_receive_event() will call this function to deliver a signal. - * - * Arguments: - * pcli Pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointer to structure containing any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -netdev_mlme_event_handler(ul_client_t *pcli, const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata_o, int dir) -{ - CSR_SIGNAL signal; - unifi_priv_t *priv = uf_find_instance(pcli->instance); - int id, r; - bulk_data_param_t bulkdata; - - /* Just a sanity check */ - if (sig_packed == NULL) { - return; - } - - /* - * This copy is to silence a compiler warning about discarding the - * const qualifier. - */ - bulkdata = *bulkdata_o; - - /* Get the unpacked signal */ - r = read_unpack_signal(sig_packed, &signal); - if (r) { - /* - * The CSR_MLME_CONNECTED_INDICATION_ID has a receiverID=0 so will - * fall through this case. It is safe to ignore this signal. - */ - unifi_trace(priv, UDBG1, - "Netdev - Received unknown signal 0x%.4X.\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); - return; - } - - id = signal.SignalPrimitiveHeader.SignalId; - unifi_trace(priv, UDBG3, "Netdev - Process signal 0x%.4X\n", id); - - /* - * Take the appropriate action for the signal. - */ - switch (id) { - case CSR_MA_PACKET_ERROR_INDICATION_ID: - process_ma_packet_error_ind(priv, &signal, &bulkdata); - break; - case CSR_MA_PACKET_INDICATION_ID: - process_ma_packet_ind(priv, &signal, &bulkdata); - break; - case CSR_MA_PACKET_CONFIRM_ID: - process_ma_packet_cfm(priv, &signal, &bulkdata); - break; -#ifdef CSR_SUPPORT_SME - case CSR_MLME_SET_TIM_CONFIRM_ID: - /* Handle TIM confirms from FW & set the station record's TIM state appropriately, - * In case of failures, tries with max_retransmit limit - */ - uf_handle_tim_cfm(priv, &signal.u.MlmeSetTimConfirm, signal.SignalPrimitiveHeader.ReceiverProcessId); - break; -#endif - case CSR_DEBUG_STRING_INDICATION_ID: - debug_string_indication(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length); - break; - - case CSR_DEBUG_WORD16_INDICATION_ID: - debug_word16_indication(priv, &signal); - break; - - case CSR_DEBUG_GENERIC_CONFIRM_ID: - case CSR_DEBUG_GENERIC_INDICATION_ID: - debug_generic_indication(priv, &signal); - break; - default: - break; - } - -} /* netdev_mlme_event_handler() */ - - -/* - * --------------------------------------------------------------------------- - * uf_net_get_name - * - * Retrieve the name (e.g. eth1) associated with this network device - * - * Arguments: - * dev Pointer to the network device. - * name Buffer to write name - * len Size of buffer in bytes - * - * Returns: - * None - * - * Notes: - * --------------------------------------------------------------------------- - */ -void uf_net_get_name(struct net_device *dev, char *name, int len) -{ - *name = '\0'; - if (dev) { - strlcpy(name, dev->name, (len > IFNAMSIZ) ? IFNAMSIZ : len); - } - -} /* uf_net_get_name */ - -#ifdef CSR_SUPPORT_WEXT - -/* - * --------------------------------------------------------------------------- - * uf_netdev_event - * - * Callback function to handle netdev state changes - * - * Arguments: - * notif Pointer to a notifier_block. - * event Event prompting notification - * ptr net_device pointer - * - * Returns: - * None - * - * Notes: - * The event handler is global, and may occur on non-UniFi netdevs. - * --------------------------------------------------------------------------- - */ -static int -uf_netdev_event(struct notifier_block *notif, unsigned long event, void* ptr) { - struct net_device *netdev = netdev_notifier_info_to_dev(ptr); - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(netdev); - unifi_priv_t *priv = NULL; - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - - /* Check that the event is for a UniFi netdev. If it's not, the netdev_priv - * structure is not safe to use. - */ - if (uf_find_netdev_priv(interfacePriv) == -1) { - unifi_trace(NULL, UDBG1, "uf_netdev_event: ignore e=%d, ptr=%p, priv=%p %s\n", - event, ptr, interfacePriv, netdev->name); - return 0; - } - - switch(event) { - case NETDEV_CHANGE: - priv = interfacePriv->privPtr; - unifi_trace(priv, UDBG1, "NETDEV_CHANGE: %p %s %s waiting for it\n", - ptr, - netdev->name, - interfacePriv->wait_netdev_change ? "" : "not"); - - if (interfacePriv->wait_netdev_change) { - netif_tx_wake_all_queues(priv->netdev[interfacePriv->InterfaceTag]); - interfacePriv->connected = UnifiConnected; - interfacePriv->wait_netdev_change = FALSE; - /* Note: passing the broadcast address here will allow anyone to attempt to join our adhoc network */ - uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - } - break; - - default: - break; - } - return 0; -} - -static struct notifier_block uf_netdev_notifier = { - .notifier_call = uf_netdev_event, -}; -#endif /* CSR_SUPPORT_WEXT */ - - -static void - process_amsdu(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) -{ - u32 offset; - u32 length = bulkdata->d[0].data_length; - u32 subframe_length, subframe_body_length, dot11_hdr_size; - u8 *ptr; - bulk_data_param_t subframe_bulkdata; - u8 *dot11_hdr_ptr = (u8*)bulkdata->d[0].os_data_ptr; - CsrResult csrResult; - u16 frameControl; - u8 *qos_control_ptr; - - frameControl = le16_to_cpu(*((u16*)dot11_hdr_ptr)); - qos_control_ptr = dot11_hdr_ptr + (((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK))?30: 24); - if(!(*qos_control_ptr & IEEE802_11_QC_A_MSDU_PRESENT)) { - unifi_trace(priv, UDBG6, "%s: calling unifi_rx()", __FUNCTION__); - unifi_rx(priv, signal, bulkdata); - return; - } - *qos_control_ptr &= ~(IEEE802_11_QC_A_MSDU_PRESENT); - - ptr = qos_control_ptr + 2; - offset = dot11_hdr_size = ptr - dot11_hdr_ptr; - - while(length > (offset + sizeof(struct ethhdr) + sizeof(llc_snap_hdr_t))) { - subframe_body_length = ntohs(((struct ethhdr*)ptr)->h_proto); - if(subframe_body_length > IEEE802_11_MAX_DATA_LEN) { - unifi_error(priv, "%s: bad subframe_body_length = %d\n", __FUNCTION__, subframe_body_length); - break; - } - subframe_length = sizeof(struct ethhdr) + subframe_body_length; - memset(&subframe_bulkdata, 0, sizeof(bulk_data_param_t)); - - csrResult = unifi_net_data_malloc(priv, &subframe_bulkdata.d[0], dot11_hdr_size + subframe_body_length); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "%s: unifi_net_data_malloc failed\n", __FUNCTION__); - break; - } - - memcpy((u8*)subframe_bulkdata.d[0].os_data_ptr, dot11_hdr_ptr, dot11_hdr_size); - - - /* When to DS=0 and from DS=0, address 3 will already have BSSID so no need to re-program */ - if ((frameControl & IEEE802_11_FC_TO_DS_MASK) && !(frameControl & IEEE802_11_FC_FROM_DS_MASK)){ - memcpy((u8*)subframe_bulkdata.d[0].os_data_ptr + IEEE802_11_ADDR3_OFFSET, ((struct ethhdr*)ptr)->h_dest, ETH_ALEN); - } - else if (!(frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){ - memcpy((u8*)subframe_bulkdata.d[0].os_data_ptr + IEEE802_11_ADDR3_OFFSET, - ((struct ethhdr*)ptr)->h_source, - ETH_ALEN); - } - - memcpy((u8*)subframe_bulkdata.d[0].os_data_ptr + dot11_hdr_size, - ptr + sizeof(struct ethhdr), - subframe_body_length); - unifi_trace(priv, UDBG6, "%s: calling unifi_rx. length = %d subframe_length = %d\n", __FUNCTION__, length, subframe_length); - unifi_rx(priv, signal, &subframe_bulkdata); - - subframe_length = (subframe_length + 3)&(~0x3); - ptr += subframe_length; - offset += subframe_length; - } - unifi_net_data_free(priv, &bulkdata->d[0]); -} - - -#define SN_TO_INDEX(__ba_session, __sn) (((__sn - __ba_session->start_sn) & 0xFFF) % __ba_session->wind_size) - - -#define ADVANCE_EXPECTED_SN(__ba_session) \ -{ \ - __ba_session->expected_sn++; \ - __ba_session->expected_sn &= 0xFFF; \ -} - -#define FREE_BUFFER_SLOT(__ba_session, __index) \ -{ \ - __ba_session->occupied_slots--; \ - __ba_session->buffer[__index].active = FALSE; \ - ADVANCE_EXPECTED_SN(__ba_session); \ -} - -static void add_frame_to_ba_complete(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - frame_desc_struct *frame_desc) -{ - interfacePriv->ba_complete[interfacePriv->ba_complete_index] = *frame_desc; - interfacePriv->ba_complete_index++; -} - - -static void update_expected_sn(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - u16 sn) -{ - int i, j; - u16 gap; - - gap = (sn - ba_session->expected_sn) & 0xFFF; - unifi_trace(priv, UDBG6, "%s: process the frames up to new_expected_sn = %d gap = %d\n", __FUNCTION__, sn, gap); - for(j = 0; j < gap && j < ba_session->wind_size; j++) { - i = SN_TO_INDEX(ba_session, ba_session->expected_sn); - unifi_trace(priv, UDBG6, "%s: process the slot index = %d\n", __FUNCTION__, i); - if(ba_session->buffer[i].active) { - add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); - unifi_trace(priv, UDBG6, "%s: process the frame at index = %d expected_sn = %d\n", __FUNCTION__, i, ba_session->expected_sn); - FREE_BUFFER_SLOT(ba_session, i); - } else { - unifi_trace(priv, UDBG6, "%s: empty slot at index = %d\n", __FUNCTION__, i); - ADVANCE_EXPECTED_SN(ba_session); - } - } - ba_session->expected_sn = sn; -} - - -static void complete_ready_sequence(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session) -{ - int i; - - i = SN_TO_INDEX(ba_session, ba_session->expected_sn); - while (ba_session->buffer[i].active) { - add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); - unifi_trace(priv, UDBG6, "%s: completed stored frame(expected_sn=%d) at i = %d\n", __FUNCTION__, ba_session->expected_sn, i); - FREE_BUFFER_SLOT(ba_session, i); - i = SN_TO_INDEX(ba_session, ba_session->expected_sn); - } -} - - -void scroll_ba_window(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - u16 sn) -{ - if(((sn - ba_session->expected_sn) & 0xFFF) <= 2048) { - update_expected_sn(priv, interfacePriv, ba_session, sn); - complete_ready_sequence(priv, interfacePriv, ba_session); - } -} - - -static int consume_frame_or_get_buffer_index(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - u16 sn, - frame_desc_struct *frame_desc) { - int i; - u16 sn_temp; - - if(((sn - ba_session->expected_sn) & 0xFFF) <= 2048) { - - /* once we are in BA window, set the flag for BA trigger */ - if(!ba_session->trigger_ba_after_ssn){ - ba_session->trigger_ba_after_ssn = TRUE; - } - - sn_temp = ba_session->expected_sn + ba_session->wind_size; - unifi_trace(priv, UDBG6, "%s: new frame: sn=%d\n", __FUNCTION__, sn); - if(!(((sn - sn_temp) & 0xFFF) > 2048)) { - u16 new_expected_sn; - unifi_trace(priv, UDBG6, "%s: frame is out of window\n", __FUNCTION__); - sn_temp = (sn - ba_session->wind_size) & 0xFFF; - new_expected_sn = (sn_temp + 1) & 0xFFF; - update_expected_sn(priv, interfacePriv, ba_session, new_expected_sn); - } - i = -1; - if (sn == ba_session->expected_sn) { - unifi_trace(priv, UDBG6, "%s: sn = ba_session->expected_sn = %d\n", __FUNCTION__, sn); - ADVANCE_EXPECTED_SN(ba_session); - add_frame_to_ba_complete(priv, interfacePriv, frame_desc); - } else { - i = SN_TO_INDEX(ba_session, sn); - unifi_trace(priv, UDBG6, "%s: sn(%d) != ba_session->expected_sn(%d), i = %d\n", __FUNCTION__, sn, ba_session->expected_sn, i); - if (ba_session->buffer[i].active) { - unifi_trace(priv, UDBG6, "%s: free frame at i = %d\n", __FUNCTION__, i); - i = -1; - unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); - } - } - } else { - i = -1; - if(!ba_session->trigger_ba_after_ssn){ - unifi_trace(priv, UDBG6, "%s: frame before ssn, pass it up: sn=%d\n", __FUNCTION__, sn); - add_frame_to_ba_complete(priv, interfacePriv, frame_desc); - }else{ - unifi_trace(priv, UDBG6, "%s: old frame, drop: sn=%d, expected_sn=%d\n", __FUNCTION__, sn, ba_session->expected_sn); - unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); - } - } - return i; -} - - - -static void process_ba_frame(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - frame_desc_struct *frame_desc) -{ - int i; - u16 sn = frame_desc->sn; - - if (ba_session->timeout) { - mod_timer(&ba_session->timer, (jiffies + usecs_to_jiffies((ba_session->timeout) * 1024))); - } - unifi_trace(priv, UDBG6, "%s: got frame(sn=%d)\n", __FUNCTION__, sn); - - i = consume_frame_or_get_buffer_index(priv, interfacePriv, ba_session, sn, frame_desc); - if(i >= 0) { - unifi_trace(priv, UDBG6, "%s: store frame(sn=%d) at i = %d\n", __FUNCTION__, sn, i); - ba_session->buffer[i] = *frame_desc; - ba_session->buffer[i].recv_time = CsrTimeGet(NULL); - ba_session->occupied_slots++; - } else { - unifi_trace(priv, UDBG6, "%s: frame consumed - sn = %d\n", __FUNCTION__, sn); - } - complete_ready_sequence(priv, interfacePriv, ba_session); -} - - -static void process_ba_complete(unifi_priv_t *priv, netInterface_priv_t *interfacePriv) -{ - frame_desc_struct *frame_desc; - u8 i; - - for(i = 0; i < interfacePriv->ba_complete_index; i++) { - frame_desc = &interfacePriv->ba_complete[i]; - unifi_trace(priv, UDBG6, "%s: calling process_amsdu()\n", __FUNCTION__); - process_amsdu(priv, &frame_desc->signal, &frame_desc->bulkdata); - } - interfacePriv->ba_complete_index = 0; - -} - - -/* Check if the frames in BA reoder buffer has aged and - * if so release the frames to upper processes and move - * the window - */ -static void check_ba_frame_age_timeout( unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session) -{ - u32 now; - u32 age; - u8 i, j; - u16 sn_temp; - - /* gap is started at 1 because we have buffered frames and - * hence a minimum gap of 1 exists - */ - u8 gap=1; - - now = CsrTimeGet(NULL); - - if (ba_session->occupied_slots) - { - /* expected sequence has not arrived so start searching from next - * sequence number until a frame is available and determine the gap. - * Check if the frame available has timedout, if so advance the - * expected sequence number and release the frames - */ - sn_temp = (ba_session->expected_sn + 1) & 0xFFF; - - for(j = 0; j < ba_session->wind_size; j++) - { - i = SN_TO_INDEX(ba_session, sn_temp); - - if(ba_session->buffer[i].active) - { - unifi_trace(priv, UDBG6, "check age at slot index = %d sn = %d recv_time = %u now = %u\n", - i, - ba_session->buffer[i].sn, - ba_session->buffer[i].recv_time, - now); - - if (ba_session->buffer[i].recv_time > now) - { - /* timer wrap */ - age = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, ba_session->buffer[i].recv_time), now); - } - else - { - age = (u32)CsrTimeSub(now, ba_session->buffer[i].recv_time); - } - - if (age >= CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT) - { - unifi_trace(priv, UDBG2, "release the frame at index = %d gap = %d expected_sn = %d sn = %d\n", - i, - gap, - ba_session->expected_sn, - ba_session->buffer[i].sn); - - /* if it has timedout don't wait for missing frames, move the window */ - while (gap--) - { - ADVANCE_EXPECTED_SN(ba_session); - } - add_frame_to_ba_complete(priv, interfacePriv, &ba_session->buffer[i]); - FREE_BUFFER_SLOT(ba_session, i); - complete_ready_sequence(priv, interfacePriv, ba_session); - } - break; - - } - else - { - /* advance temp sequence number and frame gap */ - sn_temp = (sn_temp + 1) & 0xFFF; - gap++; - } - } - } -} - - -static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_data_param_t *bulkdata) -{ - u16 interfaceTag; - const CSR_MA_PACKET_ERROR_INDICATION *pkt_err_ind = &signal->u.MaPacketErrorIndication; - netInterface_priv_t *interfacePriv; - ba_session_rx_struct *ba_session; - u8 ba_session_idx = 0; - CSR_PRIORITY UserPriority; - CSR_SEQUENCE_NUMBER sn; - - interfaceTag = (pkt_err_ind->VirtualInterfaceIdentifier & 0xff); - - - /* Sanity check that the VIF refers to a sensible interface */ - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "%s: MaPacketErrorIndication indication with bad interfaceTag %d\n", __FUNCTION__, interfaceTag); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - UserPriority = pkt_err_ind->UserPriority; - if(UserPriority > 15) { - unifi_error(priv, "%s: MaPacketErrorIndication indication with bad UserPriority=%d\n", __FUNCTION__, UserPriority); - } - sn = pkt_err_ind->SequenceNumber; - - down(&priv->ba_mutex); - /* To find the right ba_session loop through the BA sessions, compare MAC address and tID */ - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session = interfacePriv->ba_session_rx[ba_session_idx]; - if (ba_session){ - if ((!memcmp(ba_session->macAddress.a, pkt_err_ind->PeerQstaAddress.x, ETH_ALEN)) && (ba_session->tID == UserPriority)){ - if (ba_session->timeout) { - mod_timer(&ba_session->timer, (jiffies + usecs_to_jiffies((ba_session->timeout) * 1024))); - } - scroll_ba_window(priv, interfacePriv, ba_session, sn); - break; - } - } - } - - up(&priv->ba_mutex); - process_ba_complete(priv, interfacePriv); -} - - diff --git a/drivers/staging/csr/os.c b/drivers/staging/csr/os.c deleted file mode 100644 index 37ec59df3581..000000000000 --- a/drivers/staging/csr/os.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: os.c - * - * PURPOSE: - * Routines to fulfil the OS-abstraction for the HIP lib. - * It is part of the porting exercise. - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -/** - * The HIP lib OS abstraction consists of the implementation - * of the functions in this file. It is part of the porting exercise. - */ - -#include "unifi_priv.h" - - -/* - * --------------------------------------------------------------------------- - * unifi_net_data_malloc - * - * Allocate an OS specific net data buffer of "size" bytes. - * The bulk_data_slot.os_data_ptr must be initialised to point - * to the buffer allocated. The bulk_data_slot.length must be - * initialised to the requested size, zero otherwise. - * The bulk_data_slot.os_net_buf_ptr can be initialised to - * an OS specific pointer to be used in the unifi_net_data_free(). - * - * - * Arguments: - * ospriv Pointer to device private context struct. - * bulk_data_slot Pointer to the bulk data structure to initialise. - * size Size of the buffer to be allocated. - * - * Returns: - * CSR_RESULT_SUCCESS on success, CSR_RESULT_FAILURE otherwise. - * --------------------------------------------------------------------------- - */ -CsrResult -unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size) -{ - struct sk_buff *skb; - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - int rounded_length; - - if (priv->card_info.sdio_block_size == 0) { - unifi_error(priv, "unifi_net_data_malloc: Invalid SDIO block size\n"); - return CSR_RESULT_FAILURE; - } - - rounded_length = (size + priv->card_info.sdio_block_size - 1) & ~(priv->card_info.sdio_block_size - 1); - - /* - * (ETH_HLEN + 2) bytes tailroom for header manipulation - * CSR_WIFI_ALIGN_BYTES bytes headroom for alignment manipulation - */ - skb = dev_alloc_skb(rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES); - if (! skb) { - unifi_error(ospriv, "alloc_skb failed.\n"); - bulk_data_slot->os_net_buf_ptr = NULL; - bulk_data_slot->net_buf_length = 0; - bulk_data_slot->os_data_ptr = NULL; - bulk_data_slot->data_length = 0; - return CSR_RESULT_FAILURE; - } - - bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb; - bulk_data_slot->net_buf_length = rounded_length + 2 + ETH_HLEN + CSR_WIFI_ALIGN_BYTES; - bulk_data_slot->os_data_ptr = (const void*)skb->data; - bulk_data_slot->data_length = size; - - return CSR_RESULT_SUCCESS; -} /* unifi_net_data_malloc() */ - -/* - * --------------------------------------------------------------------------- - * unifi_net_data_free - * - * Free an OS specific net data buffer. - * The bulk_data_slot.length must be initialised to 0. - * - * - * Arguments: - * ospriv Pointer to device private context struct. - * bulk_data_slot Pointer to the bulk data structure that - * holds the data to be freed. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot) -{ - struct sk_buff *skb; - CSR_UNUSED(ospriv); - - skb = (struct sk_buff *)bulk_data_slot->os_net_buf_ptr; - dev_kfree_skb(skb); - - bulk_data_slot->net_buf_length = 0; - bulk_data_slot->data_length = 0; - bulk_data_slot->os_data_ptr = bulk_data_slot->os_net_buf_ptr = NULL; - -} /* unifi_net_data_free() */ - - -/* -* --------------------------------------------------------------------------- -* unifi_net_dma_align -* -* DMA align an OS specific net data buffer. -* The buffer must be empty. -* -* -* Arguments: -* ospriv Pointer to device private context struct. -* bulk_data_slot Pointer to the bulk data structure that -* holds the data to be aligned. -* -* Returns: -* None. -* --------------------------------------------------------------------------- -*/ -CsrResult -unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot) -{ - struct sk_buff *skb; - unsigned long buf_address; - int offset; - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - if ((bulk_data_slot == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) { - return CSR_RESULT_SUCCESS; - } - - if ((bulk_data_slot->os_data_ptr == NULL) || (bulk_data_slot->data_length == 0)) { - return CSR_RESULT_SUCCESS; - } - - buf_address = (unsigned long)(bulk_data_slot->os_data_ptr) & (CSR_WIFI_ALIGN_BYTES - 1); - - unifi_trace(priv, UDBG5, - "unifi_net_dma_align: Allign buffer (0x%p) by %d bytes\n", - bulk_data_slot->os_data_ptr, buf_address); - - offset = CSR_WIFI_ALIGN_BYTES - buf_address; - if (offset < 0) { - unifi_error(priv, "unifi_net_dma_align: Failed (offset=%d)\n", offset); - return CSR_RESULT_FAILURE; - } - - skb = (struct sk_buff*)(bulk_data_slot->os_net_buf_ptr); - skb_reserve(skb, offset); - bulk_data_slot->os_net_buf_ptr = (const unsigned char*)skb; - bulk_data_slot->os_data_ptr = (const void*)(skb->data); - - return CSR_RESULT_SUCCESS; - -} /* unifi_net_dma_align() */ - -#ifdef ANDROID_TIMESTAMP -static volatile unsigned int printk_cpu = UINT_MAX; -char tbuf[30]; - -char* print_time(void ) -{ - unsigned long long t; - unsigned long nanosec_rem; - - t = cpu_clock(printk_cpu); - nanosec_rem = do_div(t, 1000000000); - sprintf(tbuf, "[%5lu.%06lu] ", - (unsigned long) t, - nanosec_rem / 1000); - - return tbuf; -} -#endif - - -/* Module parameters */ -extern int unifi_debug; - -#ifdef UNIFI_DEBUG -#define DEBUG_BUFFER_SIZE 120 - -#define FORMAT_TRACE(_s, _len, _args, _fmt) \ - do { \ - va_start(_args, _fmt); \ - _len += vsnprintf(&(_s)[_len], \ - (DEBUG_BUFFER_SIZE - _len), \ - _fmt, _args); \ - va_end(_args); \ - if (_len >= DEBUG_BUFFER_SIZE) { \ - (_s)[DEBUG_BUFFER_SIZE - 2] = '\n'; \ - (_s)[DEBUG_BUFFER_SIZE - 1] = 0; \ - } \ - } while (0) - -void -unifi_error(void* ospriv, const char *fmt, ...) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - char s[DEBUG_BUFFER_SIZE]; - va_list args; - unsigned int len; -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time()); - } -#else - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: "); - } -#endif /* ANDROID_TIMESTAMP */ - FORMAT_TRACE(s, len, args, fmt); - - printk("%s", s); -} - -void -unifi_warning(void* ospriv, const char *fmt, ...) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - char s[DEBUG_BUFFER_SIZE]; - va_list args; - unsigned int len; - -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi%d: ", print_time(), priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "%s unifi: ", print_time()); - } -#else - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi%d: ", priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_WARNING "unifi: "); - } -#endif /* ANDROID_TIMESTAMP */ - - FORMAT_TRACE(s, len, args, fmt); - - printk("%s", s); -} - - -void -unifi_notice(void* ospriv, const char *fmt, ...) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - char s[DEBUG_BUFFER_SIZE]; - va_list args; - unsigned int len; - -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi%d: ", print_time(), priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "%s unifi: ", print_time()); - } -#else - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi%d: ", priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_NOTICE "unifi: "); - } -#endif /* ANDROID_TIMESTAMP */ - - FORMAT_TRACE(s, len, args, fmt); - - printk("%s", s); -} - - -void -unifi_info(void* ospriv, const char *fmt, ...) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - char s[DEBUG_BUFFER_SIZE]; - va_list args; - unsigned int len; - -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi%d: ", print_time(), priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "%s unifi: ", print_time()); - } -#else - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi%d: ", priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_INFO "unifi: "); - } -#endif /* ANDROID_TIMESTAMP */ - - FORMAT_TRACE(s, len, args, fmt); - - printk("%s", s); -} - -/* debugging */ -void -unifi_trace(void* ospriv, int level, const char *fmt, ...) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - char s[DEBUG_BUFFER_SIZE]; - va_list args; - unsigned int len; - - if (unifi_debug >= level) { -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi%d: ", print_time(), priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "%s unifi: ", print_time()); - } -#else - if (priv != NULL) { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi%d: ", priv->instance); - } else { - len = snprintf(s, DEBUG_BUFFER_SIZE, KERN_ERR "unifi: "); - } -#endif /* ANDROID_TIMESTAMP */ - - FORMAT_TRACE(s, len, args, fmt); - - printk("%s", s); - } -} - -#else - -void -unifi_error_nop(void* ospriv, const char *fmt, ...) -{ -} - -void -unifi_trace_nop(void* ospriv, int level, const char *fmt, ...) -{ -} - -#endif /* UNIFI_DEBUG */ - - -/* - * --------------------------------------------------------------------------- - * - * Debugging support. - * - * --------------------------------------------------------------------------- - */ - -#ifdef UNIFI_DEBUG - -/* Memory dump with level filter controlled by unifi_debug */ -void -unifi_dump(void *ospriv, int level, const char *msg, void *mem, u16 len) -{ - unifi_priv_t *priv = (unifi_priv_t*) ospriv; - - if (unifi_debug >= level) { -#ifdef ANDROID_TIMESTAMP - if (priv != NULL) { - printk(KERN_ERR "%s unifi%d: --- dump: %s ---\n", print_time(), priv->instance, msg ? msg : ""); - } else { - printk(KERN_ERR "%s unifi: --- dump: %s ---\n", print_time(), msg ? msg : ""); - } -#else - if (priv != NULL) { - printk(KERN_ERR "unifi%d: --- dump: %s ---\n", priv->instance, msg ? msg : ""); - } else { - printk(KERN_ERR "unifi: --- dump: %s ---\n", msg ? msg : ""); - } -#endif /* ANDROID_TIMESTAMP */ - dump(mem, len); - - if (priv != NULL) { - printk(KERN_ERR "unifi%d: --- end of dump ---\n", priv->instance); - } else { - printk(KERN_ERR "unifi: --- end of dump ---\n"); - } - } -} - -/* Memory dump that appears all the time, use sparingly */ -void -dump(void *mem, u16 len) -{ - int i, col = 0; - unsigned char *pdata = (unsigned char *)mem; -#ifdef ANDROID_TIMESTAMP - printk("timestamp %s \n", print_time()); -#endif /* ANDROID_TIMESTAMP */ - if (mem == NULL) { - printk("(null dump)\n"); - return; - } - for (i = 0; i < len; i++) { - if (col == 0) - printk("0x%02X: ", i); - - printk(" %02X", pdata[i]); - - if (++col == 16) { - printk("\n"); - col = 0; - } - } - if (col) - printk("\n"); -} /* dump() */ - - -void -dump16(void *mem, u16 len) -{ - int i, col=0; - unsigned short *p = (unsigned short *)mem; -#ifdef ANDROID_TIMESTAMP - printk("timestamp %s \n", print_time()); -#endif /* ANDROID_TIMESTAMP */ - for (i = 0; i < len; i+=2) { - if (col == 0) - printk("0x%02X: ", i); - - printk(" %04X", *p++); - - if (++col == 8) { - printk("\n"); - col = 0; - } - } - if (col) - printk("\n"); -} - - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -void -dump_str(void *mem, u16 len) -{ - int i; - unsigned char *pdata = (unsigned char *)mem; -#ifdef ANDROID_TIMESTAMP - printk("timestamp %s \n", print_time()); -#endif /* ANDROID_TIMESTAMP */ - for (i = 0; i < len; i++) { - printk("%c", pdata[i]); - } - printk("\n"); - -} /* dump_str() */ -#endif /* CSR_ONLY_NOTES */ - - -#endif /* UNIFI_DEBUG */ - - -/* --------------------------------------------------------------------------- - * - End - - * ------------------------------------------------------------------------- */ diff --git a/drivers/staging/csr/putest.c b/drivers/staging/csr/putest.c deleted file mode 100644 index 5613cf0e16b0..000000000000 --- a/drivers/staging/csr/putest.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * *************************************************************************** - * FILE: putest.c - * - * PURPOSE: putest related functions. - * - * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ - -#include -#include - -#include "unifi_priv.h" -#include "csr_wifi_hip_chiphelper.h" - -#define UNIFI_PROC_BOTH 3 - - -int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg) -{ - struct unifi_putest_cmd52 cmd52_params; - u8 *arg_pos; - unsigned int cmd_param_size; - int r; - CsrResult csrResult; - unsigned char ret_buffer[32]; - u8 *ret_buffer_pos; - u8 retries; - - arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); - if (get_user(cmd_param_size, (int*)arg_pos)) { - unifi_error(priv, - "unifi_putest_cmd52_read: Failed to get the argument\n"); - return -EFAULT; - } - - if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { - unifi_error(priv, - "unifi_putest_cmd52_read: cmd52 struct mismatch\n"); - return -EINVAL; - } - - arg_pos += sizeof(unsigned int); - if (copy_from_user(&cmd52_params, - (void*)arg_pos, - sizeof(struct unifi_putest_cmd52))) { - unifi_error(priv, - "unifi_putest_cmd52_read: Failed to get the cmd52 params\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "cmd52r: func=%d addr=0x%x ", - cmd52_params.funcnum, cmd52_params.addr); - - retries = 3; - CsrSdioClaim(priv->sdio); - do { - if (cmd52_params.funcnum == 0) { - csrResult = CsrSdioF0Read8(priv->sdio, cmd52_params.addr, &cmd52_params.data); - } else { - csrResult = CsrSdioRead8(priv->sdio, cmd52_params.addr, &cmd52_params.data); - } - } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); - CsrSdioRelease(priv->sdio); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "\nunifi_putest_cmd52_read: Read8() failed (csrResult=0x%x)\n", csrResult); - return -EFAULT; - } - unifi_trace(priv, UDBG2, "data=%d\n", cmd52_params.data); - - /* Copy the info to the out buffer */ - *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_CMD52_READ; - ret_buffer_pos = (u8*)(((unifi_putest_command_t*)ret_buffer) + 1); - *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_cmd52); - ret_buffer_pos += sizeof(unsigned int); - memcpy(ret_buffer_pos, &cmd52_params, sizeof(struct unifi_putest_cmd52)); - ret_buffer_pos += sizeof(struct unifi_putest_cmd52); - - r = copy_to_user((void*)arg, - ret_buffer, - ret_buffer_pos - ret_buffer); - if (r) { - unifi_error(priv, - "unifi_putest_cmd52_read: Failed to return the data\n"); - return -EFAULT; - } - - return 0; -} - - -int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg) -{ - struct unifi_putest_cmd52 cmd52_params; - u8 *arg_pos; - unsigned int cmd_param_size; - CsrResult csrResult; - u8 retries; - - arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); - if (get_user(cmd_param_size, (int*)arg_pos)) { - unifi_error(priv, - "unifi_putest_cmd52_write: Failed to get the argument\n"); - return -EFAULT; - } - - if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { - unifi_error(priv, - "unifi_putest_cmd52_write: cmd52 struct mismatch\n"); - return -EINVAL; - } - - arg_pos += sizeof(unsigned int); - if (copy_from_user(&cmd52_params, - (void*)(arg_pos), - sizeof(struct unifi_putest_cmd52))) { - unifi_error(priv, - "unifi_putest_cmd52_write: Failed to get the cmd52 params\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "cmd52w: func=%d addr=0x%x data=%d\n", - cmd52_params.funcnum, cmd52_params.addr, cmd52_params.data); - - retries = 3; - CsrSdioClaim(priv->sdio); - do { - if (cmd52_params.funcnum == 0) { - csrResult = CsrSdioF0Write8(priv->sdio, cmd52_params.addr, cmd52_params.data); - } else { - csrResult = CsrSdioWrite8(priv->sdio, cmd52_params.addr, cmd52_params.data); - } - } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); - CsrSdioRelease(priv->sdio); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_cmd52_write: Write8() failed (csrResult=0x%x)\n", csrResult); - return -EFAULT; - } - - return 0; -} - -int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg) -{ - struct unifi_putest_gp_rw16 gp_r16_params; - u8 *arg_pos; - unsigned int cmd_param_size; - int r; - CsrResult csrResult; - unsigned char ret_buffer[32]; - u8 *ret_buffer_pos; - - arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); - if (get_user(cmd_param_size, (int*)arg_pos)) { - unifi_error(priv, - "unifi_putest_gp_read16: Failed to get the argument\n"); - return -EFAULT; - } - - if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { - unifi_error(priv, - "unifi_putest_gp_read16: struct mismatch\n"); - return -EINVAL; - } - - arg_pos += sizeof(unsigned int); - if (copy_from_user(&gp_r16_params, - (void*)arg_pos, - sizeof(struct unifi_putest_gp_rw16))) { - unifi_error(priv, - "unifi_putest_gp_read16: Failed to get the params\n"); - return -EFAULT; - } - CsrSdioClaim(priv->sdio); - csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "gp_r16: GP=0x%08x, data=0x%04x\n", gp_r16_params.addr, gp_r16_params.data); - - /* Copy the info to the out buffer */ - *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_GP_READ16; - ret_buffer_pos = (u8*)(((unifi_putest_command_t*)ret_buffer) + 1); - *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_gp_rw16); - ret_buffer_pos += sizeof(unsigned int); - memcpy(ret_buffer_pos, &gp_r16_params, sizeof(struct unifi_putest_gp_rw16)); - ret_buffer_pos += sizeof(struct unifi_putest_gp_rw16); - - r = copy_to_user((void*)arg, - ret_buffer, - ret_buffer_pos - ret_buffer); - if (r) { - unifi_error(priv, - "unifi_putest_gp_read16: Failed to return the data\n"); - return -EFAULT; - } - - return 0; -} - -int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg) -{ - struct unifi_putest_gp_rw16 gp_w16_params; - u8 *arg_pos; - unsigned int cmd_param_size; - CsrResult csrResult; - - arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); - if (get_user(cmd_param_size, (int*)arg_pos)) { - unifi_error(priv, - "unifi_putest_gp_write16: Failed to get the argument\n"); - return -EFAULT; - } - - if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { - unifi_error(priv, - "unifi_putest_gp_write16: struct mismatch\n"); - return -EINVAL; - } - - arg_pos += sizeof(unsigned int); - if (copy_from_user(&gp_w16_params, - (void*)(arg_pos), - sizeof(struct unifi_putest_gp_rw16))) { - unifi_error(priv, - "unifi_putest_gp_write16: Failed to get the params\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data); - CsrSdioClaim(priv->sdio); - csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult); - return -EFAULT; - } - - return 0; -} - -int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg) -{ - int sdio_clock_speed; - CsrResult csrResult; - - if (get_user(sdio_clock_speed, (int*)(((unifi_putest_command_t*)arg) + 1))) { - unifi_error(priv, - "unifi_putest_set_sdio_clock: Failed to get the argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed); - - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_set_sdio_clock: Set clock failed (csrResult=0x%x)\n", csrResult); - return -EFAULT; - } - - return 0; -} - - -int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg) -{ - int r; - CsrResult csrResult; - int already_in_test = priv->ptest_mode; - - /* Ensure that sme_sys_suspend() doesn't power down the chip because: - * 1) Power is needed anyway for ptest. - * 2) The app code uses the START ioctl as a reset, so it gets called - * multiple times. If the app stops the XAPs, but the power_down/up - * sequence doesn't actually power down the chip, there can be problems - * resetting, because part of the power_up sequence disables function 1 - */ - priv->ptest_mode = 1; - - /* Suspend the SME and UniFi */ - if (priv->sme_cli) { - r = sme_sys_suspend(priv); - if (r) { - unifi_error(priv, - "unifi_putest_start: failed to suspend UniFi\n"); - return r; - } - } - - /* Application may have stopped the XAPs, but they are needed for reset */ - if (already_in_test) { - CsrSdioClaim(priv->sdio); - csrResult = unifi_start_processors(priv->card); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); - } - } else { - /* Ensure chip is powered for the case where there's no unifi_helper */ - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioPowerOn(priv->sdio); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult); - } - } - CsrSdioClaim(priv->sdio); - csrResult = unifi_init(priv->card); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_start: failed to init UniFi\n"); - return CsrHipResultToStatus(csrResult); - } - - return 0; -} - - -int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg) -{ - int r = 0; - CsrResult csrResult; - - /* Application may have stopped the XAPs, but they are needed for reset */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_start_processors(priv->card); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); - } - - /* PUTEST_STOP is also used to resume the XAPs after SME coredump. - * Don't power off the chip, leave that to the normal wifi-off which is - * about to carry on. No need to resume the SME either, as it wasn't suspended. - */ - if (priv->coredump_mode) { - priv->coredump_mode = 0; - return 0; - } - - /* At this point function 1 is enabled and the XAPs are running, so it is - * safe to let the card power down. Power is restored later, asynchronously, - * during the wifi_on requested by the SME. - */ - CsrSdioClaim(priv->sdio); - CsrSdioPowerOff(priv->sdio); - CsrSdioRelease(priv->sdio); - - /* Resume the SME and UniFi */ - if (priv->sme_cli) { - r = sme_sys_resume(priv); - if (r) { - unifi_error(priv, - "unifi_putest_stop: failed to resume SME\n"); - } - } - priv->ptest_mode = 0; - - return r; -} - - -int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) -{ -#define UF_PUTEST_MAX_FW_FILE_NAME 16 -#define UNIFI_MAX_FW_PATH_LEN 32 - unsigned int fw_name_length; - unsigned char fw_name[UF_PUTEST_MAX_FW_FILE_NAME+1]; - unsigned char *name_buffer; - int postfix; - char fw_path[UNIFI_MAX_FW_PATH_LEN]; - const struct firmware *fw_entry; - struct dlpriv temp_fw_sta; - int r; - CsrResult csrResult; - - /* Get the f/w file name length */ - if (get_user(fw_name_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { - unifi_error(priv, - "unifi_putest_dl_fw: Failed to get the length argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file name size = %d\n", fw_name_length); - - /* Sanity check for the f/w file name length */ - if (fw_name_length > UF_PUTEST_MAX_FW_FILE_NAME) { - unifi_error(priv, - "unifi_putest_dl_fw: F/W file name is too long\n"); - return -EINVAL; - } - - /* Get the f/w file name */ - name_buffer = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); - if (copy_from_user(fw_name, (void*)name_buffer, fw_name_length)) { - unifi_error(priv, "unifi_putest_dl_fw: Failed to get the file name\n"); - return -EFAULT; - } - fw_name[fw_name_length] = '\0'; - unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file = %s\n", fw_name); - - /* Keep the existing f/w to a temp, we need to restore it later */ - temp_fw_sta = priv->fw_sta; - - /* Get the putest f/w */ - postfix = priv->instance; - scnprintf(fw_path, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", - postfix, fw_name); - r = request_firmware(&fw_entry, fw_path, priv->unifi_device); - if (r == 0) { - priv->fw_sta.fw_desc = (void *)fw_entry; - priv->fw_sta.dl_data = fw_entry->data; - priv->fw_sta.dl_len = fw_entry->size; - } else { - unifi_error(priv, "Firmware file not available\n"); - return -EINVAL; - } - - /* Application may have stopped the XAPs, but they are needed for reset */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_start_processors(priv->card); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); - } - - /* Download the f/w. On UF6xxx this will cause the f/w file to convert - * into patch format and download via the ROM boot loader - */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_download(priv->card, 0x0c00); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_dl_fw: failed to download the f/w\n"); - goto free_fw; - } - - /* Free the putest f/w... */ -free_fw: - uf_release_firmware(priv, &priv->fw_sta); - /* ... and restore the original f/w */ - priv->fw_sta = temp_fw_sta; - - return CsrHipResultToStatus(csrResult); -} - - -int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg) -{ - unsigned int fw_length; - unsigned char *fw_buf = NULL; - unsigned char *fw_user_ptr; - struct dlpriv temp_fw_sta; - CsrResult csrResult; - - /* Get the f/w buffer length */ - if (get_user(fw_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { - unifi_error(priv, - "unifi_putest_dl_fw_buff: Failed to get the length arg\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "unifi_putest_dl_fw_buff: size = %d\n", fw_length); - - /* Sanity check for the buffer length */ - if (fw_length == 0 || fw_length > 0xfffffff) { - unifi_error(priv, - "unifi_putest_dl_fw_buff: buffer length bad %u\n", fw_length); - return -EINVAL; - } - - /* Buffer for kernel copy of the f/w image */ - fw_buf = kmalloc(fw_length, GFP_KERNEL); - if (!fw_buf) { - unifi_error(priv, "unifi_putest_dl_fw_buff: malloc fail\n"); - return -ENOMEM; - } - - /* Get the f/w image */ - fw_user_ptr = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); - if (copy_from_user(fw_buf, (void*)fw_user_ptr, fw_length)) { - unifi_error(priv, "unifi_putest_dl_fw_buff: Failed to get the buffer\n"); - kfree(fw_buf); - return -EFAULT; - } - - /* Save the existing f/w to a temp, we need to restore it later */ - temp_fw_sta = priv->fw_sta; - - /* Setting fw_desc NULL indicates to the core that no f/w file was loaded - * via the kernel request_firmware() mechanism. This indicates to the core - * that it shouldn't call release_firmware() after the download is done. - */ - priv->fw_sta.fw_desc = NULL; /* No OS f/w resource */ - priv->fw_sta.dl_data = fw_buf; - priv->fw_sta.dl_len = fw_length; - - /* Application may have stopped the XAPs, but they are needed for reset */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_start_processors(priv->card); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); - } - - /* Download the f/w. On UF6xxx this will cause the f/w file to convert - * into patch format and download via the ROM boot loader - */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_download(priv->card, 0x0c00); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, - "unifi_putest_dl_fw_buff: failed to download the f/w\n"); - goto free_fw; - } - -free_fw: - /* Finished with the putest f/w, so restore the station f/w */ - priv->fw_sta = temp_fw_sta; - kfree(fw_buf); - - return CsrHipResultToStatus(csrResult); -} - - -int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg) -{ - u16 data_u16; - s32 i; - CsrResult r; - - unifi_info(priv, "Preparing for SDIO coredump\n"); -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) - unifi_debug_buf_dump(); -#endif - - /* Sanity check that userspace hasn't called a PUTEST_START, because that - * would have reset UniFi, potentially power cycling it and losing context - */ - if (priv->ptest_mode) { - unifi_error(priv, "PUTEST_START shouldn't be used before a coredump\n"); - } - - /* Flag that the userspace has requested coredump. Even if this preparation - * fails, the SME will call PUTEST_STOP to tidy up. - */ - priv->coredump_mode = 1; - - for (i = 0; i < 3; i++) { - CsrSdioClaim(priv->sdio); - r = CsrSdioRead16(priv->sdio, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION*2, &data_u16); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_info(priv, "Failed to read chip version! Try %d\n", i); - - /* First try, re-enable function which may have been disabled by f/w panic */ - if (i == 0) { - unifi_info(priv, "Try function enable\n"); - CsrSdioClaim(priv->sdio); - r = CsrSdioFunctionEnable(priv->sdio); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrSdioFunctionEnable failed %d\n", r); - } - continue; - } - - /* Subsequent tries, reset */ - - /* Set clock speed low */ - CsrSdioClaim(priv->sdio); - r = CsrSdioMaxBusClockFrequencySet(priv->sdio, UNIFI_SDIO_CLOCK_SAFE_HZ); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrSdioMaxBusClockFrequencySet() failed %d\n", r); - } - - /* Card software reset */ - CsrSdioClaim(priv->sdio); - r = unifi_card_hard_reset(priv->card); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r); - } - } else { - unifi_info(priv, "Read chip version of 0x%04x\n", data_u16); - break; - } - } - - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to prepare chip\n"); - return -EIO; - } - - /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at - * Raw SDIO deinit, to resume them. - */ - CsrSdioClaim(priv->sdio); - r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Failed to stop processors\n"); - } - - return 0; -} - -int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg) -{ - struct unifi_putest_block_cmd52_r block_cmd52; - u8 *arg_pos; - unsigned int cmd_param_size; - CsrResult r; - u8 *block_local_buffer; - - arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); - if (get_user(cmd_param_size, (int*)arg_pos)) { - unifi_error(priv, - "cmd52r_block: Failed to get the argument\n"); - return -EFAULT; - } - - if (cmd_param_size != sizeof(struct unifi_putest_block_cmd52_r)) { - unifi_error(priv, - "cmd52r_block: cmd52 struct mismatch\n"); - return -EINVAL; - } - - arg_pos += sizeof(unsigned int); - if (copy_from_user(&block_cmd52, - (void*)arg_pos, - sizeof(struct unifi_putest_block_cmd52_r))) { - unifi_error(priv, - "cmd52r_block: Failed to get the cmd52 params\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG2, "cmd52r_block: func=%d addr=0x%x len=0x%x ", - block_cmd52.funcnum, block_cmd52.addr, block_cmd52.length); - - block_local_buffer = vmalloc(block_cmd52.length); - if (block_local_buffer == NULL) { - unifi_error(priv, "cmd52r_block: Failed to allocate buffer\n"); - return -ENOMEM; - } - - CsrSdioClaim(priv->sdio); - r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length); - CsrSdioRelease(priv->sdio); - if (r != CSR_RESULT_SUCCESS) { - unifi_error(priv, "cmd52r_block: unifi_readn failed\n"); - return -EIO; - } - - if (copy_to_user((void*)block_cmd52.data, - block_local_buffer, - block_cmd52.length)) { - unifi_error(priv, - "cmd52r_block: Failed to return the data\n"); - return -EFAULT; - } - - return 0; -} diff --git a/drivers/staging/csr/sdio_events.c b/drivers/staging/csr/sdio_events.c deleted file mode 100644 index 2a80b9eb0200..000000000000 --- a/drivers/staging/csr/sdio_events.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sdio_events.c - * - * PURPOSE: - * Process the events received by the SDIO glue layer. - * Optional part of the porting exercise. - * - * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include "unifi_priv.h" - - -/* - * Porting Notes: - * There are two ways to support the suspend/resume system events in a driver. - * In some operating systems these events are delivered to the OS driver - * directly from the system. In this case, the OS driver needs to pass these - * events to the API described in the CSR SDIO Abstration API document. - * In Linux, and other embedded operating systems, the suspend/resume events - * come from the SDIO driver. In this case, simply get these events in the - * SDIO glue layer and notify the OS layer. - * - * In either case, typically, the events are processed by the SME. - * Use the unifi_sys_suspend_ind() and unifi_sys_resume_ind() to pass - * the events to the SME. - */ - -/* - * --------------------------------------------------------------------------- - * unifi_suspend - * - * Handles a suspend request from the SDIO driver. - * - * Arguments: - * ospriv Pointer to OS driver context. - * - * --------------------------------------------------------------------------- - */ -void unifi_suspend(void *ospriv) -{ - unifi_priv_t *priv = ospriv; - int interfaceTag=0; - - /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ - priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; - - unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d", - priv->wol_suspend, enable_wol ); - - /* Stop network traffic. */ - /* need to stop all the netdevices*/ - for( interfaceTag=0;interfaceTaginterfacePriv[interfaceTag]; - if (interfacePriv->netdev_registered == 1) - { - if( priv->wol_suspend ) { - unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off"); - } else { - unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off"); - netif_carrier_off(priv->netdev[interfaceTag]); - } - netif_tx_stop_all_queues(priv->netdev[interfaceTag]); - } - } - - unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME"); - - sme_sys_suspend(priv); - -} /* unifi_suspend() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_resume - * - * Handles a resume request from the SDIO driver. - * - * Arguments: - * ospriv Pointer to OS driver context. - * - * --------------------------------------------------------------------------- - */ -void unifi_resume(void *ospriv) -{ - unifi_priv_t *priv = ospriv; - int interfaceTag=0; - int r; - int wol = priv->wol_suspend; - - unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol); - - /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */ - r = sme_sys_resume(priv); - if (r) { - unifi_error(priv, "Failed to resume UniFi\n"); - } - - /* Resume the network interfaces. For the cold resume case, this will - * happen upon reconnection. - */ - if (wol) { - unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier"); - - /* need to start all the netdevices*/ - for( interfaceTag=0;interfaceTaginterfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n", - interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode); - - if (interfacePriv->netdev_registered == 1) - { - netif_carrier_on(priv->netdev[interfaceTag]); - netif_tx_start_all_queues(priv->netdev[interfaceTag]); - } - } - - /* Kick the BH thread (with reason=host) to poll for data that may have - * arrived during a powered suspend. This caters for the case where the SME - * doesn't interact with the chip (e.g install autonomous scans) during resume. - */ - unifi_send_signal(priv->card, NULL, 0, NULL); - } - -} /* unifi_resume() */ - diff --git a/drivers/staging/csr/sdio_mmc.c b/drivers/staging/csr/sdio_mmc.c deleted file mode 100644 index 2b503c23efae..000000000000 --- a/drivers/staging/csr/sdio_mmc.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * - * FILE: sdio_mmc.c - * - * PURPOSE: SDIO driver interface for generic MMC stack. - * - * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. - * - * --------------------------------------------------------------------------- - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "unifi_priv.h" - -#ifdef ANDROID_BUILD -struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */ -#endif - -static CsrSdioFunctionDriver *sdio_func_drv; - -#ifdef CONFIG_PM -static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr); -#endif - -/* - * We need to keep track of the power on/off because we can not call - * mmc_power_restore_host() when the card is already powered. - * Even then, we need to patch the MMC driver to add a power_restore handler - * in the mmc_sdio_ops structure. If the MMC driver before 2.6.37 is not patched, - * mmc_power_save_host() and mmc_power_restore_host() are no-ops in the kernel, - * returning immediately (at least on x86). - */ -static int card_is_powered = 1; - -/* MMC uses ENOMEDIUM to indicate card gone away */ - -static CsrResult -ConvertSdioToCsrSdioResult(int r) -{ - CsrResult csrResult = CSR_RESULT_FAILURE; - - switch (r) { - case 0: - csrResult = CSR_RESULT_SUCCESS; - break; - case -EIO: - case -EILSEQ: - csrResult = CSR_SDIO_RESULT_CRC_ERROR; - break; - /* Timeout errors */ - case -ETIMEDOUT: - case -EBUSY: - csrResult = CSR_SDIO_RESULT_TIMEOUT; - break; - case -ENODEV: - case -ENOMEDIUM: - csrResult = CSR_SDIO_RESULT_NO_DEVICE; - break; - case -EINVAL: - csrResult = CSR_SDIO_RESULT_INVALID_VALUE; - break; - case -ENOMEM: - case -ENOSYS: - case -ERANGE: - case -ENXIO: - csrResult = CSR_RESULT_FAILURE; - break; - default: - unifi_warning(NULL, "Unrecognised SDIO error code: %d\n", r); - break; - } - - return csrResult; -} - - -static int -csr_io_rw_direct(struct mmc_card *card, int write, uint8_t fn, - uint32_t addr, uint8_t in, uint8_t* out) -{ - struct mmc_command cmd; - int err; - - BUG_ON(!card); - BUG_ON(fn > 7); - - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = SD_IO_RW_DIRECT; - cmd.arg = write ? 0x80000000 : 0x00000000; - cmd.arg |= fn << 28; - cmd.arg |= (write && out) ? 0x08000000 : 0x00000000; - cmd.arg |= addr << 9; - cmd.arg |= in; - cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; - - err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (err) - return err; - - /* this function is not exported, so we will need to sort it out here - * for now, lets hard code it to sdio */ - if (0) { - /* old arg (mmc_host_is_spi(card->host)) { */ - /* host driver already reported errors */ - } else { - if (cmd.resp[0] & R5_ERROR) { - printk(KERN_ERR "%s: r5 error 0x%02x\n", - __FUNCTION__, cmd.resp[0]); - return -EIO; - } - if (cmd.resp[0] & R5_FUNCTION_NUMBER) - return -EINVAL; - if (cmd.resp[0] & R5_OUT_OF_RANGE) - return -ERANGE; - } - - if (out) { - if (0) { /* old argument (mmc_host_is_spi(card->host)) */ - *out = (cmd.resp[0] >> 8) & 0xFF; - } - else { - *out = cmd.resp[0] & 0xFF; - } - } - - return CSR_RESULT_SUCCESS; -} - - -CsrResult -CsrSdioRead8(CsrSdioFunction *function, u32 address, u8 *data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - - _sdio_claim_host(func); - *data = sdio_readb(func, address, &err); - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioRead8() */ - -CsrResult -CsrSdioWrite8(CsrSdioFunction *function, u32 address, u8 data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - - _sdio_claim_host(func); - sdio_writeb(func, data, address, &err); - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioWrite8() */ - -CsrResult -CsrSdioRead16(CsrSdioFunction *function, u32 address, u16 *data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - uint8_t b0, b1; - - _sdio_claim_host(func); - b0 = sdio_readb(func, address, &err); - if (err) { - _sdio_release_host(func); - return ConvertSdioToCsrSdioResult(err); - } - - b1 = sdio_readb(func, address+1, &err); - if (err) { - _sdio_release_host(func); - return ConvertSdioToCsrSdioResult(err); - } - _sdio_release_host(func); - - *data = ((uint16_t)b1 << 8) | b0; - - return CSR_RESULT_SUCCESS; -} /* CsrSdioRead16() */ - - -CsrResult -CsrSdioWrite16(CsrSdioFunction *function, u32 address, u16 data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - uint8_t b0, b1; - - _sdio_claim_host(func); - b1 = (data >> 8) & 0xFF; - sdio_writeb(func, b1, address+1, &err); - if (err) { - _sdio_release_host(func); - return ConvertSdioToCsrSdioResult(err); - } - - b0 = data & 0xFF; - sdio_writeb(func, b0, address, &err); - if (err) { - _sdio_release_host(func); - return ConvertSdioToCsrSdioResult(err); - } - - _sdio_release_host(func); - return CSR_RESULT_SUCCESS; -} /* CsrSdioWrite16() */ - - -CsrResult -CsrSdioF0Read8(CsrSdioFunction *function, u32 address, u8 *data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - - _sdio_claim_host(func); -#ifdef MMC_QUIRK_LENIENT_FN0 - *data = sdio_f0_readb(func, address, &err); -#else - err = csr_io_rw_direct(func->card, 0, 0, address, 0, data); -#endif - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioF0Read8() */ - -CsrResult -CsrSdioF0Write8(CsrSdioFunction *function, u32 address, u8 data) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - - _sdio_claim_host(func); -#ifdef MMC_QUIRK_LENIENT_FN0 - sdio_f0_writeb(func, data, address, &err); -#else - err = csr_io_rw_direct(func->card, 1, 0, address, data, NULL); -#endif - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioF0Write8() */ - - -CsrResult -CsrSdioRead(CsrSdioFunction *function, u32 address, void *data, u32 length) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - - _sdio_claim_host(func); - err = sdio_readsb(func, data, address, length); - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioRead() */ - -CsrResult -CsrSdioWrite(CsrSdioFunction *function, u32 address, const void *data, u32 length) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - - _sdio_claim_host(func); - err = sdio_writesb(func, address, (void*)data, length); - _sdio_release_host(func); - - if (err) { - return ConvertSdioToCsrSdioResult(err); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioWrite() */ - - -static int -csr_sdio_enable_hs(struct mmc_card *card) -{ - int ret; - u8 speed; - - if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) { - /* We've asked for HS clock rates, but controller doesn't - * claim to support it. We should limit the clock - * to 25MHz via module parameter. - */ - printk(KERN_INFO "unifi: request HS but not MMC_CAP_SD_HIGHSPEED"); - return 0; - } - - if (!card->cccr.high_speed) - return 0; - -#if 1 - ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); - if (ret) - return ret; - - speed |= SDIO_SPEED_EHS; -#else - /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */ - speed = SDIO_SPEED_EHS | SDIO_SPEED_SHS; -#endif - - ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); - if (ret) - return ret; - - mmc_card_set_highspeed(card); - card->host->ios.timing = MMC_TIMING_SD_HS; - card->host->ops->set_ios(card->host, &card->host->ios); - - return 0; -} - -static int -csr_sdio_disable_hs(struct mmc_card *card) -{ - int ret; - u8 speed; - - if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) - return 0; - - if (!card->cccr.high_speed) - return 0; -#if 1 - ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); - if (ret) - return ret; - - speed &= ~SDIO_SPEED_EHS; -#else - /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */ - speed = SDIO_SPEED_SHS; /* clear SDIO_SPEED_EHS */ -#endif - - ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); - if (ret) - return ret; - - card->state &= ~MMC_STATE_HIGHSPEED; - card->host->ios.timing = MMC_TIMING_LEGACY; - card->host->ops->set_ios(card->host, &card->host->ios); - - return 0; -} - - -/* - * --------------------------------------------------------------------------- - * CsrSdioMaxBusClockFrequencySet - * - * Set the maximum SDIO bus clock speed to use. - * - * Arguments: - * sdio SDIO context pointer - * maxFrequency maximum clock speed in Hz - * - * Returns: - * an error code. - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioMaxBusClockFrequencySet(CsrSdioFunction *function, u32 maxFrequency) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - struct mmc_host *host = func->card->host; - struct mmc_ios *ios = &host->ios; - unsigned int max_hz; - int err; - u32 max_khz = maxFrequency/1000; - - if (!max_khz || max_khz > sdio_clock) { - max_khz = sdio_clock; - } - - _sdio_claim_host(func); - max_hz = 1000 * max_khz; - if (max_hz > host->f_max) { - max_hz = host->f_max; - } - - if (max_hz > 25000000) { - err = csr_sdio_enable_hs(func->card); - } else { - err = csr_sdio_disable_hs(func->card); - } - if (err) { - printk(KERN_ERR "SDIO warning: Failed to configure SDIO clock mode\n"); - _sdio_release_host(func); - return CSR_RESULT_SUCCESS; - } - - ios->clock = max_hz; - host->ops->set_ios(host, ios); - - _sdio_release_host(func); - - return CSR_RESULT_SUCCESS; -} /* CsrSdioMaxBusClockFrequencySet() */ - - -/* - * --------------------------------------------------------------------------- - * CsrSdioInterruptEnable - * CsrSdioInterruptDisable - * - * Enable or disable the SDIO interrupt. - * The driver disables the SDIO interrupt until the i/o thread can - * process it. - * The SDIO interrupt can be disabled by modifying the SDIO_INT_ENABLE - * register in the Card Common Control Register block, but this requires - * two CMD52 operations. A better solution is to mask the interrupt at - * the host controller. - * - * Arguments: - * sdio SDIO context pointer - * - * Returns: - * Zero on success or a UniFi driver error code. - * - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioInterruptEnable(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - -#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD - sdio_unblock_card_irq(func); -#else - _sdio_claim_host(func); - /* Write the Int Enable in CCCR block */ -#ifdef MMC_QUIRK_LENIENT_FN0 - sdio_f0_writeb(func, 0x3, SDIO_CCCR_IENx, &err); -#else - err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x03, NULL); -#endif - _sdio_release_host(func); - - if (err) { - printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err); - return ConvertSdioToCsrSdioResult(err); - } -#endif - return CSR_RESULT_SUCCESS; -} /* CsrSdioInterruptEnable() */ - -CsrResult -CsrSdioInterruptDisable(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err = 0; - -#ifdef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD - sdio_block_card_irq(func); -#else - _sdio_claim_host(func); - /* Write the Int Enable in CCCR block */ -#ifdef MMC_QUIRK_LENIENT_FN0 - sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &err); -#else - err = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL); -#endif - _sdio_release_host(func); - - if (err) { - printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err); - return ConvertSdioToCsrSdioResult(err); - } -#endif - return CSR_RESULT_SUCCESS; -} /* CsrSdioInterruptDisable() */ - - -void CsrSdioInterruptAcknowledge(CsrSdioFunction *function) -{ -} - - -/* - * --------------------------------------------------------------------------- - * CsrSdioFunctionEnable - * - * Enable i/o on function 1. - * - * Arguments: - * sdio SDIO context pointer - * - * Returns: - * UniFi driver error code. - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioFunctionEnable(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - - /* Enable UniFi function 1 (the 802.11 part). */ - _sdio_claim_host(func); - err = sdio_enable_func(func); - _sdio_release_host(func); - if (err) { - unifi_error(NULL, "Failed to enable SDIO function %d\n", func->num); - } - - return ConvertSdioToCsrSdioResult(err); -} /* CsrSdioFunctionEnable() */ - - -/* - * --------------------------------------------------------------------------- - * CsrSdioFunctionDisable - * - * Enable i/o on function 1. - * - * Arguments: - * sdio SDIO context pointer - * - * Returns: - * UniFi driver error code. - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioFunctionDisable(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int err; - - /* Disable UniFi function 1 (the 802.11 part). */ - _sdio_claim_host(func); - err = sdio_disable_func(func); - _sdio_release_host(func); - if (err) { - unifi_error(NULL, "Failed to disable SDIO function %d\n", func->num); - } - - return ConvertSdioToCsrSdioResult(err); -} /* CsrSdioFunctionDisable() */ - - -/* - * --------------------------------------------------------------------------- - * CsrSdioFunctionActive - * - * No-op as the bus goes to an active state at the start of every - * command. - * - * Arguments: - * sdio SDIO context pointer - * --------------------------------------------------------------------------- - */ -void -CsrSdioFunctionActive(CsrSdioFunction *function) -{ -} /* CsrSdioFunctionActive() */ - -/* - * --------------------------------------------------------------------------- - * CsrSdioFunctionIdle - * - * Set the function as idle. - * - * Arguments: - * sdio SDIO context pointer - * --------------------------------------------------------------------------- - */ -void -CsrSdioFunctionIdle(CsrSdioFunction *function) -{ -} /* CsrSdioFunctionIdle() */ - - -/* - * --------------------------------------------------------------------------- - * CsrSdioPowerOn - * - * Power on UniFi. - * - * Arguments: - * sdio SDIO context pointer - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioPowerOn(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - struct mmc_host *host = func->card->host; - - _sdio_claim_host(func); - if (!card_is_powered) { - mmc_power_restore_host(host); - card_is_powered = 1; - } else { - printk(KERN_INFO "SDIO: Skip power on; card is already powered.\n"); - } - _sdio_release_host(func); - - return CSR_RESULT_SUCCESS; -} /* CsrSdioPowerOn() */ - -/* - * --------------------------------------------------------------------------- - * CsrSdioPowerOff - * - * Power off UniFi. - * - * Arguments: - * sdio SDIO context pointer - * --------------------------------------------------------------------------- - */ -void -CsrSdioPowerOff(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - struct mmc_host *host = func->card->host; - - _sdio_claim_host(func); - if (card_is_powered) { - mmc_power_save_host(host); - card_is_powered = 0; - } else { - printk(KERN_INFO "SDIO: Skip power off; card is already powered off.\n"); - } - _sdio_release_host(func); -} /* CsrSdioPowerOff() */ - - -static int -sdio_set_block_size_ignore_first_error(struct sdio_func *func, unsigned blksz) -{ - int ret; - - if (blksz > func->card->host->max_blk_size) - return -EINVAL; - - if (blksz == 0) { - blksz = min(func->max_blksize, func->card->host->max_blk_size); - blksz = min(blksz, 512u); - } - - /* - * Ignore -ERANGE (OUT_OF_RANGE in R5) on the first byte as - * the block size may be invalid until both bytes are written. - */ - ret = csr_io_rw_direct(func->card, 1, 0, - SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE, - blksz & 0xff, NULL); - if (ret && ret != -ERANGE) - return ret; - ret = csr_io_rw_direct(func->card, 1, 0, - SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1, - (blksz >> 8) & 0xff, NULL); - if (ret) - return ret; - func->cur_blksize = blksz; - - return 0; -} - -CsrResult -CsrSdioBlockSizeSet(CsrSdioFunction *function, u16 blockSize) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int r = 0; - - /* Module parameter overrides */ - if (sdio_block_size > -1) { - blockSize = sdio_block_size; - } - - unifi_trace(NULL, UDBG1, "Set SDIO function block size to %d\n", - blockSize); - - _sdio_claim_host(func); - r = sdio_set_block_size(func, blockSize); - _sdio_release_host(func); - - /* - * The MMC driver for kernels prior to 2.6.32 may fail this request - * with -ERANGE. In this case use our workaround. - */ - if (r == -ERANGE) { - _sdio_claim_host(func); - r = sdio_set_block_size_ignore_first_error(func, blockSize); - _sdio_release_host(func); - } - if (r) { - unifi_error(NULL, "Error %d setting block size\n", r); - } - - /* Determine the achieved block size to pass to the core */ - function->blockSize = func->cur_blksize; - - return ConvertSdioToCsrSdioResult(r); -} /* CsrSdioBlockSizeSet() */ - - -/* - * --------------------------------------------------------------------------- - * CsrSdioHardReset - * - * Hard Resets UniFi is possible. - * - * Arguments: - * sdio SDIO context pointer - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioHardReset(CsrSdioFunction *function) -{ - return CSR_RESULT_FAILURE; -} /* CsrSdioHardReset() */ - - - -/* - * --------------------------------------------------------------------------- - * uf_glue_sdio_int_handler - * - * Interrupt callback function for SDIO interrupts. - * This is called in kernel context (i.e. not interrupt context). - * - * Arguments: - * func SDIO context pointer - * - * Returns: - * None. - * - * Note: Called with host already claimed. - * --------------------------------------------------------------------------- - */ -static void -uf_glue_sdio_int_handler(struct sdio_func *func) -{ - CsrSdioFunction *sdio_ctx; - CsrSdioInterruptDsrCallback func_dsr_callback; - int r; - - sdio_ctx = sdio_get_drvdata(func); - if (!sdio_ctx) { - return; - } - -#ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD - /* - * Normally, we are not allowed to do any SDIO commands here. - * However, this is called in a thread context and with the SDIO lock - * so we disable the interrupts here instead of trying to do complicated - * things with the SDIO lock. - */ -#ifdef MMC_QUIRK_LENIENT_FN0 - sdio_f0_writeb(func, 0, SDIO_CCCR_IENx, &r); -#else - r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL); -#endif - if (r) { - printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts %d\n", r); - } -#endif - - /* If the function driver has registered a handler, call it */ - if (sdio_func_drv && sdio_func_drv->intr) { - - func_dsr_callback = sdio_func_drv->intr(sdio_ctx); - - /* If interrupt handle returns a DSR handle, call it */ - if (func_dsr_callback) { - func_dsr_callback(sdio_ctx); - } - } - -} /* uf_glue_sdio_int_handler() */ - - - -/* - * --------------------------------------------------------------------------- - * csr_sdio_linux_remove_irq - * - * Unregister the interrupt handler. - * This means that the linux layer can not process interrupts any more. - * - * Arguments: - * sdio SDIO context pointer - * - * Returns: - * Status of the removal. - * --------------------------------------------------------------------------- - */ -int csr_sdio_linux_remove_irq(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int r; - - unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n"); - - sdio_claim_host(func); - r = sdio_release_irq(func); - sdio_release_host(func); - - return r; - -} /* csr_sdio_linux_remove_irq() */ - - -/* - * --------------------------------------------------------------------------- - * csr_sdio_linux_install_irq - * - * Register the interrupt handler. - * This means that the linux layer can process interrupts. - * - * Arguments: - * sdio SDIO context pointer - * - * Returns: - * Status of the removal. - * --------------------------------------------------------------------------- - */ -int csr_sdio_linux_install_irq(CsrSdioFunction *function) -{ - struct sdio_func *func = (struct sdio_func *)function->priv; - int r; - - unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n"); - - /* Register our interrupt handle */ - sdio_claim_host(func); - r = sdio_claim_irq(func, uf_glue_sdio_int_handler); - sdio_release_host(func); - - /* If the interrupt was installed earlier, is fine */ - if (r == -EBUSY) - r = 0; - - return r; -} /* csr_sdio_linux_install_irq() */ - -#ifdef CONFIG_PM - -/* - * Power Management notifier - */ -struct uf_sdio_mmc_pm_notifier -{ - struct list_head list; - - CsrSdioFunction *sdio_ctx; - struct notifier_block pm_notifier; -}; - -/* PM notifier list head */ -static struct uf_sdio_mmc_pm_notifier uf_sdio_mmc_pm_notifiers = { - .sdio_ctx = NULL, -}; - -/* - * --------------------------------------------------------------------------- - * uf_sdio_mmc_register_pm_notifier - * uf_sdio_mmc_unregister_pm_notifier - * - * Register/unregister for power management events. A list is used to - * allow multiple card instances to be supported. - * - * Arguments: - * sdio_ctx - CSR SDIO context to associate PM notifier to - * - * Returns: - * Register function returns NULL on error - * --------------------------------------------------------------------------- - */ -static struct uf_sdio_mmc_pm_notifier * -uf_sdio_mmc_register_pm_notifier(CsrSdioFunction *sdio_ctx) -{ - /* Allocate notifier context for this card instance */ - struct uf_sdio_mmc_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_mmc_pm_notifier), GFP_KERNEL); - - if (notifier_ctx) - { - notifier_ctx->sdio_ctx = sdio_ctx; - notifier_ctx->pm_notifier.notifier_call = uf_sdio_mmc_power_event; - - list_add(¬ifier_ctx->list, &uf_sdio_mmc_pm_notifiers.list); - - if (register_pm_notifier(¬ifier_ctx->pm_notifier)) { - printk(KERN_ERR "unifi: register_pm_notifier failed\n"); - } - } - - return notifier_ctx; -} - -static void -uf_sdio_mmc_unregister_pm_notifier(CsrSdioFunction *sdio_ctx) -{ - struct uf_sdio_mmc_pm_notifier *notifier_ctx; - struct list_head *node, *q; - - list_for_each_safe(node, q, &uf_sdio_mmc_pm_notifiers.list) { - notifier_ctx = list_entry(node, struct uf_sdio_mmc_pm_notifier, list); - - /* If it matches, unregister and free the notifier context */ - if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx) - { - if (unregister_pm_notifier(¬ifier_ctx->pm_notifier)) { - printk(KERN_ERR "unifi: unregister_pm_notifier failed\n"); - } - - /* Remove from list */ - notifier_ctx->sdio_ctx = NULL; - list_del(node); - kfree(notifier_ctx); - } - } -} - -/* - * --------------------------------------------------------------------------- - * uf_sdio_mmc_power_event - * - * Handler for power management events. - * - * We need to handle suspend/resume events while the userspace is unsuspended - * to allow the SME to run its suspend/resume state machines. - * - * Arguments: - * event event ID - * - * Returns: - * Status of the event handling - * --------------------------------------------------------------------------- - */ -static int -uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct uf_sdio_mmc_pm_notifier *notifier_ctx = container_of(this, - struct uf_sdio_mmc_pm_notifier, - pm_notifier); - - /* Call the CSR SDIO function driver's suspend/resume method - * while the userspace is unsuspended. - */ - switch (event) { - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ ); - if (sdio_func_drv && sdio_func_drv->resume) { - sdio_func_drv->resume(notifier_ctx->sdio_ctx); - } - break; - - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ ); - if (sdio_func_drv && sdio_func_drv->suspend) { - sdio_func_drv->suspend(notifier_ctx->sdio_ctx); - } - break; - } - return NOTIFY_DONE; -} - -#endif /* CONFIG_PM */ - -/* - * --------------------------------------------------------------------------- - * uf_glue_sdio_probe - * - * Card insert callback. - * - * Arguments: - * func Our (glue layer) context pointer. - * - * Returns: - * UniFi driver error code. - * --------------------------------------------------------------------------- - */ -static int -uf_glue_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - int instance; - CsrSdioFunction *sdio_ctx; - - /* First of all claim the SDIO driver */ - sdio_claim_host(func); - - /* Assume that the card is already powered */ - card_is_powered = 1; - - /* Assumes one card per host, which is true for SDIO */ - instance = func->card->host->index; - printk("sdio bus_id: %16s - UniFi card 0x%X inserted\n", - sdio_func_id(func), instance); - - /* Allocate context */ - sdio_ctx = kmalloc(sizeof(CsrSdioFunction), GFP_KERNEL); - if (sdio_ctx == NULL) { - sdio_release_host(func); - return -ENOMEM; - } - - /* Initialise the context */ - sdio_ctx->sdioId.manfId = func->vendor; - sdio_ctx->sdioId.cardId = func->device; - sdio_ctx->sdioId.sdioFunction = func->num; - sdio_ctx->sdioId.sdioInterface = func->class; - sdio_ctx->blockSize = func->cur_blksize; - sdio_ctx->priv = (void *)func; - sdio_ctx->features = 0; - - /* Module parameter enables byte mode */ - if (sdio_byte_mode) { - sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE; - } - - if (func->card->host->caps & MMC_CAP_SD_HIGHSPEED) { - unifi_trace(NULL, UDBG1, "MMC_CAP_SD_HIGHSPEED is available\n"); - } - -#ifdef MMC_QUIRK_LENIENT_FN0 - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; -#endif - - /* Pass context to the SDIO driver */ - sdio_set_drvdata(func, sdio_ctx); - -#ifdef CONFIG_PM - /* Register to get PM events */ - if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) { - unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__); - } -#endif - - /* Register this device with the SDIO function driver */ - /* Call the main UniFi driver inserted handler */ - if (sdio_func_drv && sdio_func_drv->inserted) { - uf_add_os_device(instance, &func->dev); - sdio_func_drv->inserted(sdio_ctx); - } - - /* We have finished, so release the SDIO driver */ - sdio_release_host(func); - -#ifdef ANDROID_BUILD - /* Take the wakelock */ - unifi_trace(NULL, UDBG1, "probe: take wake lock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - - return 0; -} /* uf_glue_sdio_probe() */ - - -/* - * --------------------------------------------------------------------------- - * uf_glue_sdio_remove - * - * Card removal callback. - * - * Arguments: - * func Our (glue layer) context pointer. - * - * Returns: - * UniFi driver error code. - * --------------------------------------------------------------------------- - */ -static void -uf_glue_sdio_remove(struct sdio_func *func) -{ - CsrSdioFunction *sdio_ctx; - - sdio_ctx = sdio_get_drvdata(func); - if (!sdio_ctx) { - return; - } - - unifi_info(NULL, "UniFi card removed\n"); - - /* Clean up the SDIO function driver */ - if (sdio_func_drv && sdio_func_drv->removed) { - uf_remove_os_device(func->card->host->index); - sdio_func_drv->removed(sdio_ctx); - } - -#ifdef CONFIG_PM - /* Unregister for PM events */ - uf_sdio_mmc_unregister_pm_notifier(sdio_ctx); -#endif - - kfree(sdio_ctx); - -} /* uf_glue_sdio_remove */ - - -/* - * SDIO ids *must* be statically declared, so we can't take - * them from the list passed in csr_sdio_register_driver(). - */ -static const struct sdio_device_id unifi_ids[] = { - { SDIO_DEVICE(SDIO_MANF_ID_CSR, SDIO_CARD_ID_UNIFI_3) }, - { SDIO_DEVICE(SDIO_MANF_ID_CSR, SDIO_CARD_ID_UNIFI_4) }, - { /* end: all zeroes */ }, -}; - -MODULE_DEVICE_TABLE(sdio, unifi_ids); - -#ifdef CONFIG_PM - -/* - * --------------------------------------------------------------------------- - * uf_glue_sdio_suspend - * - * Card suspend callback. The userspace will already be suspended. - * - * Arguments: - * dev The struct device owned by the MMC driver - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -static int -uf_glue_sdio_suspend(struct device *dev) -{ - unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend"); - - return 0; -} /* uf_glue_sdio_suspend */ - - -/* - * --------------------------------------------------------------------------- - * uf_glue_sdio_resume - * - * Card resume callback. The userspace will still be suspended. - * - * Arguments: - * dev The struct device owned by the MMC driver - * - * Returns: - * None - * --------------------------------------------------------------------------- - */ -static int -uf_glue_sdio_resume(struct device *dev) -{ - unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume"); - -#ifdef ANDROID_BUILD - unifi_trace(NULL, UDBG1, "resume: take wakelock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - - return 0; - -} /* uf_glue_sdio_resume */ - -static struct dev_pm_ops unifi_pm_ops = { - .suspend = uf_glue_sdio_suspend, - .resume = uf_glue_sdio_resume, -}; - -#define UNIFI_PM_OPS (&unifi_pm_ops) - -#else - -#define UNIFI_PM_OPS NULL - -#endif /* CONFIG_PM */ - -static struct sdio_driver unifi_driver = { - .probe = uf_glue_sdio_probe, - .remove = uf_glue_sdio_remove, - .name = "unifi", - .id_table = unifi_ids, - .drv.pm = UNIFI_PM_OPS, -}; - - -/* - * --------------------------------------------------------------------------- - * CsrSdioFunctionDriverRegister - * CsrSdioFunctionDriverUnregister - * - * These functions are called from the main module load and unload - * functions. They perform the appropriate operations for the - * linux MMC/SDIO driver. - * - * Arguments: - * sdio_drv Pointer to the function driver's SDIO structure. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -CsrResult -CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv) -{ - int r; - - printk("UniFi: Using native Linux MMC driver for SDIO.\n"); - - if (sdio_func_drv) { - unifi_error(NULL, "sdio_mmc: UniFi driver already registered\n"); - return CSR_SDIO_RESULT_INVALID_VALUE; - } - -#ifdef ANDROID_BUILD - wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work"); -#endif - - /* Save the registered driver description */ - /* - * FIXME: - * Need a table here to handle a call to register for just one function. - * mmc only allows us to register for the whole device - */ - sdio_func_drv = sdio_drv; - -#ifdef CONFIG_PM - /* Initialise PM notifier list */ - INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list); -#endif - - /* Register ourself with mmc_core */ - r = sdio_register_driver(&unifi_driver); - if (r) { - printk(KERN_ERR "unifi_sdio: Failed to register UniFi SDIO driver: %d\n", r); - return ConvertSdioToCsrSdioResult(r); - } - - return CSR_RESULT_SUCCESS; -} /* CsrSdioFunctionDriverRegister() */ - - - -void -CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv) -{ - printk(KERN_INFO "UniFi: unregister from MMC sdio\n"); - -#ifdef ANDROID_BUILD - wake_lock_destroy(&unifi_sdio_wake_lock); -#endif - sdio_unregister_driver(&unifi_driver); - - sdio_func_drv = NULL; - -} /* CsrSdioFunctionDriverUnregister() */ - diff --git a/drivers/staging/csr/sdio_stubs.c b/drivers/staging/csr/sdio_stubs.c deleted file mode 100644 index 839fae01d96c..000000000000 --- a/drivers/staging/csr/sdio_stubs.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Stubs for some of the bottom edge functions. - * - * These stubs are optional functions in the bottom edge (SDIO driver - * interface) API that not all platforms or SDIO drivers may support. - * - * They're declared as weak symbols so they can be overridden by - * simply providing a non-weak declaration. - * - * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - */ -#include "csr_wifi_hip_unifi.h" - -void __attribute__((weak)) CsrSdioFunctionIdle(CsrSdioFunction *function) -{ -} - -void __attribute__((weak)) CsrSdioFunctionActive(CsrSdioFunction *function) -{ -} - -CsrResult __attribute__((weak)) CsrSdioPowerOn(CsrSdioFunction *function) -{ - return CSR_RESULT_SUCCESS; -} - -void __attribute__((weak)) CsrSdioPowerOff(CsrSdioFunction *function) -{ -} - -CsrResult __attribute__((weak)) CsrSdioHardReset(CsrSdioFunction *function) -{ - return CSR_SDIO_RESULT_NOT_RESET; -} - -CsrResult __attribute__((weak)) CsrSdioBlockSizeSet(CsrSdioFunction *function, - u16 blockSize) -{ - return CSR_RESULT_SUCCESS; -} - -CsrResult __attribute__((weak)) CsrSdioSuspend(CsrSdioFunction *function) -{ - return CSR_RESULT_SUCCESS; -} - -CsrResult __attribute__((weak)) CsrSdioResume(CsrSdioFunction *function) -{ - return CSR_RESULT_SUCCESS; -} - -int __attribute__((weak)) csr_sdio_linux_install_irq(CsrSdioFunction *function) -{ - return 0; -} - -int __attribute__((weak)) csr_sdio_linux_remove_irq(CsrSdioFunction *function) -{ - return 0; -} - -void __attribute__((weak)) CsrSdioInsertedAcknowledge(CsrSdioFunction *function, CsrResult result) -{ -} - -void __attribute__((weak)) CsrSdioRemovedAcknowledge(CsrSdioFunction *function) -{ -} - -void __attribute__((weak)) CsrSdioSuspendAcknowledge(CsrSdioFunction *function, CsrResult result) -{ -} - -void __attribute__((weak)) CsrSdioResumeAcknowledge(CsrSdioFunction *function, CsrResult result) -{ -} - - diff --git a/drivers/staging/csr/sme_blocking.c b/drivers/staging/csr/sme_blocking.c deleted file mode 100644 index 0c6e21636e7f..000000000000 --- a/drivers/staging/csr/sme_blocking.c +++ /dev/null @@ -1,1466 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sme_mgt_blocking.c - * - * PURPOSE: - * This file contains the driver specific implementation of - * the WEXT <==> SME MGT interface for all SME builds that support WEXT. - * - * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include "unifi_priv.h" - - -/* - * This file also contains the implementation of the asynchronous - * requests to the SME. - * - * Before calling an asynchronous SME function, we call sme_init_request() - * which gets hold of the SME semaphore and updates the request status. - * The semaphore makes sure that there is only one pending request to - * the SME at a time. - * - * Now we are ready to call the SME function, but only if - * sme_init_request() has returned 0. - * - * When the SME function returns, we need to wait - * for the reply. This is done in sme_wait_for_reply(). - * If the request times-out, the request status is set to SME_REQUEST_TIMEDOUT - * and the sme_wait_for_reply() returns. - * - * If the SME replies in time, we call sme_complete_request(). - * There we change the request status to SME_REQUEST_RECEIVED. This will - * wake up the process waiting on sme_wait_for_reply(). - * It is important that we copy the reply data in priv->sme_reply - * before calling sme_complete_request(). - * - * Handling the wext requests, we need to block - * until the SME sends the response to our request. - * We use the sme_init_request() and sme_wait_for_reply() - * to implement this behavior in the following functions: - * sme_mgt_wifi_on() - * sme_mgt_wifi_off() - * sme_mgt_scan_full() - * sme_mgt_scan_results_get_async() - * sme_mgt_connect() - * unifi_mgt_media_status_ind() - * sme_mgt_disconnect() - * sme_mgt_pmkid() - * sme_mgt_key() - * sme_mgt_mib_get() - * sme_mgt_mib_set() - * sme_mgt_versions_get() - * sme_mgt_set_value() - * sme_mgt_get_value() - * sme_mgt_set_value_async() - * sme_mgt_get_value_async() - * sme_mgt_packet_filter_set() - * sme_mgt_tspec() - */ - - -/* - * Handling the suspend and resume system events, we need to block - * until the SME sends the response to our indication. - * We use the sme_init_request() and sme_wait_for_reply() - * to implement this behavior in the following functions: - * sme_sys_suspend() - * sme_sys_resume() - */ - -#define UNIFI_SME_MGT_SHORT_TIMEOUT 10000 -#define UNIFI_SME_MGT_LONG_TIMEOUT 19000 -#define UNIFI_SME_SYS_LONG_TIMEOUT 10000 - -#ifdef UNIFI_DEBUG -# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, __func__) -#else -# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, NULL) -#endif - -static int -sme_init_request(unifi_priv_t *priv) -{ - if (priv == NULL) { - unifi_error(priv, "sme_init_request: Invalid priv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n"); - - /* Grab the SME semaphore until the reply comes, or timeout */ - if (down_interruptible(&priv->sme_sem)) { - unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n"); - return -EIO; - } - unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n"); - - priv->sme_reply.request_status = SME_REQUEST_PENDING; - - return 0; - -} /* sme_init_request() */ - - -void -uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func) -{ - if (priv == NULL) { - unifi_error(priv, "sme_complete_request: Invalid priv\n"); - return; - } - - if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { - unifi_notice(priv, - "sme_complete_request: request not pending %s (s:%d)\n", - (func ? func : ""), priv->sme_reply.request_status); - return; - } - unifi_trace(priv, UDBG5, - "sme_complete_request: completed %s (s:%d)\n", - (func ? func : ""), priv->sme_reply.request_status); - - priv->sme_reply.request_status = SME_REQUEST_RECEIVED; - priv->sme_reply.reply_status = reply_status; - - wake_up_interruptible(&priv->sme_request_wq); - - return; -} - - -void -uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status) -{ - /* Check for a blocking SME request in progress, and cancel the wait. - * This should be used when the character device is closed. - */ - - if (priv == NULL) { - unifi_error(priv, "sme_cancel_request: Invalid priv\n"); - return; - } - - /* If no request is pending, nothing to wake up */ - if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { - unifi_trace(priv, UDBG5, - "sme_cancel_request: no request was pending (s:%d)\n", - priv->sme_reply.request_status); - /* Nothing to do */ - return; - } - unifi_trace(priv, UDBG5, - "sme_cancel_request: request cancelled (s:%d)\n", - priv->sme_reply.request_status); - - /* Wake up the wait with an error status */ - priv->sme_reply.request_status = SME_REQUEST_CANCELLED; - priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */ - - wake_up_interruptible(&priv->sme_request_wq); - - return; -} - - -static int -_sme_wait_for_reply(unifi_priv_t *priv, - unsigned long timeout, const char *func) -{ - long r; - - unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : ""); - r = wait_event_interruptible_timeout(priv->sme_request_wq, - (priv->sme_reply.request_status != SME_REQUEST_PENDING), - msecs_to_jiffies(timeout)); - unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r); - - if (r == -ERESTARTSYS) { - /* The thread was killed */ - unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n"); - up(&priv->sme_sem); - return r; - } - if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) { - unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n", - (func ? func : ""), priv->sme_reply.request_status, timeout, r); - - /* Release the SME semaphore that was downed in sme_init_request() */ - up(&priv->sme_sem); - return -EIO; /* fail the ioctl */ - } - if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) { - unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n", - (func ? func : ""), priv->sme_reply.request_status, timeout); - - priv->sme_reply.request_status = SME_REQUEST_TIMEDOUT; - - /* Release the SME semaphore that was downed in sme_init_request() */ - up(&priv->sme_sem); - - return -ETIMEDOUT; - } - - unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n", - func ? func : "", r); - - /* Release the SME semaphore that was downed in sme_init_request() */ - up(&priv->sme_sem); - - return 0; -} /* sme_wait_for_reply() */ - - - - -#ifdef CSR_SUPPORT_WEXT -int sme_mgt_wifi_on(unifi_priv_t *priv) -{ - u16 numElements; - CsrWifiSmeDataBlock* dataList; -#ifdef CSR_SUPPORT_WEXT_AP - int r; -#endif - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_wifi_on: invalid smepriv\n"); - return -EIO; - } - - if (priv->mib_data.length) { - numElements = 1; - dataList = &priv->mib_data; - } else { - numElements = 0; - dataList = NULL; - } - /* Start the SME */ -#ifdef CSR_SUPPORT_WEXT_AP - r = sme_init_request(priv); - if (r) { - return -EIO; - } -#endif - CsrWifiSmeWifiOnReqSend(0, priv->sta_mac_address, numElements, dataList); -#ifdef CSR_SUPPORT_WEXT_AP - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); - unifi_trace(priv, UDBG4, - "sme_mgt_wifi_on: unifi_mgt_wifi_oo_req <-- (r=%d, status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -#else - return 0; -#endif -} /* sme_mgt_wifi_on() */ - - -int sme_mgt_wifi_off(unifi_priv_t *priv) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_wifi_off: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - /* Stop the SME */ - CsrWifiSmeWifiOffReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); - -} /* sme_mgt_wifi_off */ - -int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key, - CsrWifiSmeListAction action) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_key: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_mgt_scan_full(unifi_priv_t *priv, - CsrWifiSsid *specific_ssid, - int num_channels, - unsigned char *channel_list) -{ - CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; - u8 is_active = (num_channels > 0) ? TRUE : FALSE; - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n"); - - r = sme_init_request(priv); - if (r) - return -EIO; - - /* If a channel list is provided, do an active scan */ - if (is_active) { - unifi_trace(priv, UDBG1, - "channel list - num_channels: %d, active scan\n", - num_channels); - } - - CsrWifiSmeScanFullReqSend(0, - specific_ssid->length?1:0, /* 0 or 1 SSIDS */ - specific_ssid, - bcastAddress, - is_active, - CSR_WIFI_SME_BSS_TYPE_ANY_BSS, - CSR_WIFI_SME_SCAN_TYPE_ALL, - (u16)num_channels, channel_list, - 0, NULL); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status); - if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE) - return 0; /* initial scan already underway */ - else - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_mgt_scan_results_get_async(unifi_priv_t *priv, - struct iw_request_info *info, - char *scan_results, - long scan_results_len) -{ - u16 scan_result_list_count; - CsrWifiSmeScanResult *scan_result_list; - CsrWifiSmeScanResult *scan_result; - int r; - int i; - char *current_ev = scan_results; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_scan_results_get_async: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeScanResultsGetReqSend(0); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); - if (r) - return r; - - scan_result_list_count = priv->sme_reply.reply_scan_results_count; - scan_result_list = priv->sme_reply.reply_scan_results; - unifi_trace(priv, UDBG2, - "scan_results: Scan returned %d, numElements=%d\n", - r, scan_result_list_count); - - /* OK, now we have the scan results */ - for (i = 0; i < scan_result_list_count; ++i) { - scan_result = &scan_result_list[i]; - - unifi_trace(priv, UDBG2, "Scan Result: %.*s\n", - scan_result->ssid.length, - scan_result->ssid.ssid); - - r = unifi_translate_scan(priv->netdev[0], info, - current_ev, - scan_results + scan_results_len, - scan_result, i+1); - - if (r < 0) { - kfree(scan_result_list); - priv->sme_reply.reply_scan_results_count = 0; - priv->sme_reply.reply_scan_results = NULL; - return r; - } - - current_ev += r; - } - - /* - * Free the scan results allocated in unifi_mgt_scan_results_get_cfm() - * and invalidate the reply_scan_results to avoid re-using - * the freed pointers. - */ - kfree(scan_result_list); - priv->sme_reply.reply_scan_results_count = 0; - priv->sme_reply.reply_scan_results = NULL; - - unifi_trace(priv, UDBG2, - "scan_results: Scan translated to %d bytes\n", - current_ev - scan_results); - return (current_ev - scan_results); -} - - -int sme_mgt_connect(unifi_priv_t *priv) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_connect: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n", - priv->connection_config.ssid.length, - priv->connection_config.ssid.ssid); - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - if (priv->sme_reply.reply_status) - unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n", - priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_mgt_disconnect(unifi_priv_t *priv) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_disconnect: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_mgt_pmkid(unifi_priv_t *priv, - CsrWifiSmeListAction action, - CsrWifiSmePmkidList *pmkid_list) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, - pmkid_list->pmkidsCount, pmkid_list->pmkids); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_mgt_mib_get(unifi_priv_t *priv, - unsigned char *varbind, int *length) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - priv->mib_cfm_buffer = varbind; - priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH; - - CsrWifiSmeMibGetReqSend(0, *length, varbind); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) { - priv->mib_cfm_buffer_length = 0; - priv->mib_cfm_buffer = NULL; - return r; - } - - *length = priv->mib_cfm_buffer_length; - - priv->mib_cfm_buffer_length = 0; - priv->mib_cfm_buffer = NULL; - unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - -int sme_mgt_mib_set(unifi_priv_t *priv, - unsigned char *varbind, int length) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeMibSetReqSend(0, length, varbind); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - -#endif /* CSR_SUPPORT_WEXT */ - -int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_set_value_async: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmePowerConfigSetReqSend(0, *powerConfig); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_set_value: invalid smepriv\n"); - return -EIO; - } - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtPowerConfigSetReq(priv->smepriv, *powerConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); - return -EIO; - } - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig); - status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#ifdef CSR_SUPPORT_WEXT - -int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeMibConfigSetReqSend(0, *mibConfig); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n"); - return -EIO; - } - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtMibConfigSetReq(priv->smepriv, *mibConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n"); - return -EIO; - } - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtCoexConfigSetReq(priv->smepriv, *coexConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#endif /* CSR_SUPPORT_WEXT */ - -int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n"); - return -EIO; - } - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtHostConfigSetReq(priv->smepriv, *hostConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#ifdef CSR_SUPPORT_WEXT - -int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeVersionsGetReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (versions != NULL) { - memcpy((unsigned char*)versions, - (unsigned char*)&priv->sme_reply.versions, - sizeof(CsrWifiSmeVersions)); - } - - unifi_trace(priv, UDBG4, - "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#endif /* CSR_SUPPORT_WEXT */ - -int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_power_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmePowerConfigGetReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (powerConfig != NULL) { - memcpy((unsigned char*)powerConfig, - (unsigned char*)&priv->sme_reply.powerConfig, - sizeof(CsrWifiSmePowerConfig)); - } - - unifi_trace(priv, UDBG4, - "sme_mgt_get_versions: unifi_mgt_power_config_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtPowerConfigGetReq(priv->smepriv, powerConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (hostConfig != NULL) - memcpy((unsigned char*)hostConfig, - (unsigned char*)&priv->sme_reply.hostConfig, - sizeof(CsrWifiSmeHostConfig)); - - unifi_trace(priv, UDBG4, - "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_sme_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req -->\n"); - - /* Common device config */ - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeSmeCommonConfigGetReqSend(0); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (deviceConfig != NULL) - memcpy((unsigned char*)deviceConfig, - (unsigned char*)&priv->sme_reply.deviceConfig, - sizeof(CsrWifiSmeDeviceConfig)); - - /* STA config */ - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (staConfig != NULL) - memcpy((unsigned char*)staConfig, - (unsigned char*)&priv->sme_reply.staConfig, - sizeof(CsrWifiSmeStaConfig)); - - unifi_trace(priv, UDBG4, - "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtSmeConfigGetReq(priv->smepriv, staConfig); - status = CsrWifiSmeMgtDeviceConfigGetReq(priv->smepriv, deviceConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_coex_info_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeCoexInfoGetReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (coexInfo != NULL) - memcpy((unsigned char*)coexInfo, - (unsigned char*)&priv->sme_reply.coexInfo, - sizeof(CsrWifiSmeCoexInfo)); - - unifi_trace(priv, UDBG4, - "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtCoexInfoGetReq(priv->smepriv, coexInfo); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#ifdef CSR_SUPPORT_WEXT - -int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_coex_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeCoexConfigGetReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (coexConfig != NULL) - memcpy((unsigned char*)coexConfig, - (unsigned char*)&priv->sme_reply.coexConfig, - sizeof(CsrWifiSmeCoexConfig)); - - unifi_trace(priv, UDBG4, - "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtCoexConfigGetReq(priv->smepriv, coexConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_mib_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeMibConfigGetReqSend(0); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (mibConfig != NULL) - memcpy((unsigned char*)mibConfig, - (unsigned char*)&priv->sme_reply.mibConfig, - sizeof(CsrWifiSmeMibConfig)); - - unifi_trace(priv, UDBG4, - "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtMibConfigGetReq(priv->smepriv, mibConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_connection_info_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (connectionInfo != NULL) - memcpy((unsigned char*)connectionInfo, - (unsigned char*)&priv->sme_reply.connectionInfo, - sizeof(CsrWifiSmeConnectionInfo)); - - unifi_trace(priv, UDBG4, - "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtConnectionInfoGetReq(priv->smepriv, connectionInfo); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_connection_config_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (connectionConfig != NULL) - memcpy((unsigned char*)connectionConfig, - (unsigned char*)&priv->sme_reply.connectionConfig, - sizeof(CsrWifiSmeConnectionConfig)); - - unifi_trace(priv, UDBG4, - "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtConnectionConfigGetReq(priv->smepriv, connectionConfig); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats) -{ -#ifdef CSR_SME_USERSPACE - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_connection_stats_get: invalid smepriv\n"); - return -EIO; - } - - unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n"); - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - /* store the reply */ - if (connectionStats != NULL) - memcpy((unsigned char*)connectionStats, - (unsigned char*)&priv->sme_reply.connectionStats, - sizeof(CsrWifiSmeConnectionStats)); - - unifi_trace(priv, UDBG4, - "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - - return convert_sme_error(priv->sme_reply.reply_status); -#else - CsrResult status; - CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); - status = CsrWifiSmeMgtConnectionStatsGetReq(priv->smepriv, connectionStats); - CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); - return convert_sme_error(status); -#endif -} - -#endif /* CSR_SUPPORT_WEXT */ - -int sme_mgt_packet_filter_set(unifi_priv_t *priv) -{ - CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }}; - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n"); - return -EIO; - } - if (priv->packet_filters.arp_filter) { - ipAddress.a[0] = (priv->sta_ip_address ) & 0xFF; - ipAddress.a[1] = (priv->sta_ip_address >> 8) & 0xFF; - ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF; - ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF; - } - - unifi_trace(priv, UDBG5, - "sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n", - ipAddress.a[0], ipAddress.a[1], - ipAddress.a[2], ipAddress.a[3]); - - /* Doesn't block for a confirm */ - CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, - priv->packet_filters.tclas_ies_length, - priv->filter_tclas_ies, - priv->packet_filters.filter_mode, - ipAddress); - return 0; -} - -int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action, - u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE, - action, tid, TRUE, 0, - tspec->length, tspec->data, - tclas->length, tclas->data); - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - - - -int sme_sys_suspend(unifi_priv_t *priv) -{ - int r; - CsrResult csrResult; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_sys_suspend: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - /* Suspend the SME, which MAY cause it to power down UniFi */ - CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, 0, priv->wol_suspend); - r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); - if (r) { - /* No reply - forcibly power down in case the request wasn't processed */ - unifi_notice(priv, - "suspend: SME did not reply %s, ", - (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n"); - - /* Leave power on for production test, though */ - if (!priv->ptest_mode) { - /* Put UniFi to deep sleep, in case we can not power it off */ - CsrSdioClaim(priv->sdio); - unifi_trace(priv, UDBG1, "Force deep sleep"); - csrResult = unifi_force_low_power_mode(priv->card); - - /* For WOL, the UniFi must stay powered */ - if (!priv->wol_suspend) { - unifi_trace(priv, UDBG1, "Power off\n"); - CsrSdioPowerOff(priv->sdio); - } - CsrSdioRelease(priv->sdio); - } - } - - if (priv->wol_suspend) { - unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n"); - - /* Remove the IRQ, which also disables the card SDIO interrupt. - * Disabling the card SDIO interrupt enables the PIO WOL source. - * Removal of the of the handler ensures that in both SDIO and PIO cases - * the card interrupt only wakes the host. The card will be polled - * after resume to handle any pending data. - */ - if (csr_sdio_linux_remove_irq(priv->sdio)) { - unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n"); - } - - if (enable_wol == UNIFI_WOL_SDIO) { - /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt, - * it must be left enabled to wake-on-SDIO. - */ - unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n"); - - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioInterruptEnable(priv->sdio); - CsrSdioRelease(priv->sdio); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult); - } - } else { - unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n"); - } - - /* Prevent the BH thread from running during the suspend. - * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause - * the BH thread to be re-enabled and reinstall the ISR. - */ - priv->bh_thread.block_thread = 1; - - unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH"); - } - - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; - - unifi_trace(priv, UDBG1, "sme_sys_suspend: <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - - -int sme_sys_resume(unifi_priv_t *priv) -{ - int r; - - unifi_trace(priv, UDBG1, "sme_sys_resume %s\n", priv->wol_suspend ? "warm" : ""); - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_sys_resume: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, priv->wol_suspend); - - r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT); - if (r) - unifi_notice(priv, - "resume: SME did not reply, return success anyway\n"); - - return 0; -} - -#ifdef CSR_SUPPORT_WEXT_AP -int sme_ap_stop(unifi_priv_t *priv, u16 interface_tag) -{ - int r; - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_ap_stop: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiNmeApStopReqSend(0, interface_tag); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_ap_stop <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); - -} - -int sme_ap_start(unifi_priv_t *priv, u16 interface_tag, - CsrWifiSmeApConfig_t * ap_config) -{ - int r; - CsrWifiSmeApP2pGoConfig p2p_go_param; - memset(&p2p_go_param, 0, sizeof(CsrWifiSmeApP2pGoConfig)); - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_ap_start: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiNmeApStartReqSend(0, interface_tag, CSR_WIFI_AP_TYPE_LEGACY, FALSE, - ap_config->ssid, 1, ap_config->channel, - ap_config->credentials, ap_config->max_connections, - p2p_go_param, FALSE); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_ap_start <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} - -int sme_ap_config(unifi_priv_t *priv, - CsrWifiSmeApMacConfig *ap_mac_config, - CsrWifiNmeApConfig *group_security_config) -{ - int r; - CsrWifiSmeApP2pGoConfig p2p_go_param; - memset(&p2p_go_param, 0, sizeof(CsrWifiSmeApP2pGoConfig)); - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_ap_config: invalid smepriv\n"); - return -EIO; - } - - r = sme_init_request(priv); - if (r) - return -EIO; - - CsrWifiNmeApConfigSetReqSend(0, *group_security_config, - *ap_mac_config); - - r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); - if (r) - return r; - - unifi_trace(priv, UDBG4, - "sme_ap_config <-- (r=%d status=%d)\n", - r, priv->sme_reply.reply_status); - return convert_sme_error(priv->sme_reply.reply_status); -} -#endif diff --git a/drivers/staging/csr/sme_mgt.c b/drivers/staging/csr/sme_mgt.c deleted file mode 100644 index 58d1b3b72932..000000000000 --- a/drivers/staging/csr/sme_mgt.c +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sme_mgt.c - * - * PURPOSE: - * This file contains the driver specific implementation of - * the SME MGT SAP. - * It is part of the porting exercise. - * - * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include "csr_wifi_hip_unifiversion.h" -#include "unifi_priv.h" -#include "csr_wifi_hip_conversions.h" -/* - * This file implements the SME MGT API. It contains the following functions: - * CsrWifiSmeWifiFlightmodeCfmSend() - * CsrWifiSmeWifiOnCfmSend() - * CsrWifiSmeWifiOffCfmSend() - * CsrWifiSmeWifiOffIndSend() - * CsrWifiSmeScanFullCfmSend() - * CsrWifiSmeScanResultsGetCfmSend() - * CsrWifiSmeScanResultIndSend() - * CsrWifiSmeScanResultsFlushCfmSend() - * CsrWifiSmeConnectCfmSend() - * CsrWifiSmeMediaStatusIndSend() - * CsrWifiSmeDisconnectCfmSend() - * CsrWifiSmeKeyCfmSend() - * CsrWifiSmeMulticastAddressCfmSend() - * CsrWifiSmeSetValueCfmSend() - * CsrWifiSmeGetValueCfmSend() - * CsrWifiSmeMicFailureIndSend() - * CsrWifiSmePmkidCfmSend() - * CsrWifiSmePmkidCandidateListIndSend() - * CsrWifiSmeMibSetCfmSend() - * CsrWifiSmeMibGetCfmSend() - * CsrWifiSmeMibGetNextCfmSend() - * CsrWifiSmeConnectionQualityIndSend() - * CsrWifiSmePacketFilterSetCfmSend() - * CsrWifiSmeTspecCfmSend() - * CsrWifiSmeTspecIndSend() - * CsrWifiSmeBlacklistCfmSend() - * CsrWifiSmeEventMaskSetCfmSend() - * CsrWifiSmeRoamStartIndSend() - * CsrWifiSmeRoamCompleteIndSend() - * CsrWifiSmeAssociationStartIndSend() - * CsrWifiSmeAssociationCompleteIndSend() - * CsrWifiSmeIbssStationIndSend() - */ - - -void CsrWifiSmeMicFailureIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMicFailureInd* ind = (CsrWifiSmeMicFailureInd*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMicFailureIndSend: invalid priv\n"); - return; - } - - unifi_trace(priv, UDBG1, - "CsrWifiSmeMicFailureIndSend: count=%d, KeyType=%d\n", - ind->count, ind->keyType); - - wext_send_michaelmicfailure_event(priv, ind->count, ind->address, ind->keyType, ind->interfaceTag); -#endif -} - - -void CsrWifiSmePmkidCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmePmkidCfm* cfm = (CsrWifiSmePmkidCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmePmkidCfmSend: Invalid ospriv.\n"); - return; - } - - /* - * WEXT never does a GET operation the PMKIDs, so we don't need - * handle data returned in pmkids. - */ - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmePmkidCandidateListIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmePmkidCandidateListInd* ind = (CsrWifiSmePmkidCandidateListInd*)msg; - int i; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiSmePmkidCandidateListIndSend: invalid smepriv\n"); - return; - } - - for (i = 0; i < ind->pmkidCandidatesCount; i++) - { - wext_send_pmkid_candidate_event(priv, ind->pmkidCandidates[i].bssid, ind->pmkidCandidates[i].preAuthAllowed, ind->interfaceTag); - } -#endif -} - -void CsrWifiSmeScanResultsFlushCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeScanResultsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeScanResultsGetCfm* cfm = (CsrWifiSmeScanResultsGetCfm*)msg; - int bytesRequired = cfm->scanResultsCount * sizeof(CsrWifiSmeScanResult); - int i; - u8* current_buff; - CsrWifiSmeScanResult* scanCopy; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeScanResultsGetCfmSend: Invalid ospriv.\n"); - return; - } - - /* Calc the size of the buffer reuired */ - for (i = 0; i < cfm->scanResultsCount; ++i) { - const CsrWifiSmeScanResult *scan_result = &cfm->scanResults[i]; - bytesRequired += scan_result->informationElementsLength; - } - - /* Take a Copy of the scan Results :-) */ - scanCopy = kmalloc(bytesRequired, GFP_KERNEL); - memcpy(scanCopy, cfm->scanResults, sizeof(CsrWifiSmeScanResult) * cfm->scanResultsCount); - - /* Take a Copy of the Info Elements AND update the scan result pointers */ - current_buff = (u8*)&scanCopy[cfm->scanResultsCount]; - for (i = 0; i < cfm->scanResultsCount; ++i) - { - CsrWifiSmeScanResult *scan_result = &scanCopy[i]; - memcpy(current_buff, scan_result->informationElements, scan_result->informationElementsLength); - scan_result->informationElements = current_buff; - current_buff += scan_result->informationElementsLength; - } - - priv->sme_reply.reply_scan_results_count = cfm->scanResultsCount; - priv->sme_reply.reply_scan_results = scanCopy; - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeScanFullCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeScanFullCfm* cfm = (CsrWifiSmeScanFullCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeScanFullCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeScanResultIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - -} - - -void CsrWifiSmeConnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeConnectCfm* cfm = (CsrWifiSmeConnectCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeConnectCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeDisconnectCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeDisconnectCfm* cfm = (CsrWifiSmeDisconnectCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeDisconnectCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeKeyCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeKeyCfm* cfm = (CsrWifiSmeKeyCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeKeyCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeMulticastAddressCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMulticastAddressCfm* cfm = (CsrWifiSmeMulticastAddressCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMulticastAddressCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeWifiFlightmodeCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeWifiFlightmodeCfm* cfm = (CsrWifiSmeWifiFlightmodeCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeWifiFlightmodeCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeWifiOnCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeWifiOnCfm* cfm = (CsrWifiSmeWifiOnCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeWifiOnCfmSend: Invalid ospriv.\n"); - return; - } - - unifi_trace(priv, UDBG4, - "CsrWifiSmeWifiOnCfmSend: wake up status %d\n", cfm->status); -#ifdef CSR_SUPPORT_WEXT_AP - sme_complete_request(priv, cfm->status); -#endif - -#endif -} - -void CsrWifiSmeWifiOffCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeWifiOffCfm* cfm = (CsrWifiSmeWifiOffCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeWifiOffCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeWifiOffIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeWifiOffInd* ind = (CsrWifiSmeWifiOffInd*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiRouterCtrlStoppedReqSend: Invalid ospriv.\n"); - return; - } - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlStoppedReqSend: invalid smepriv\n"); - return; - } - - /* - * If the status indicates an error, the SME is in a stopped state. - * We need to start it again in order to reinitialise UniFi. - */ - switch (ind->reason) { - case CSR_WIFI_SME_CONTROL_INDICATION_ERROR: - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlStoppedReqSend: Restarting SME (ind:%d)\n", - ind->reason); - - /* On error, restart the SME */ - sme_mgt_wifi_on(priv); - break; - case CSR_WIFI_SME_CONTROL_INDICATION_EXIT: -#ifdef CSR_SUPPORT_WEXT_AP - sme_complete_request(priv, 0); -#endif - break; - default: - break; - } - -#endif -} - -void CsrWifiSmeVersionsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeVersionsGetCfm* cfm = (CsrWifiSmeVersionsGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeVersionsGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.versions = cfm->versions; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmePowerConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmePowerConfigGetCfm* cfm = (CsrWifiSmePowerConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmePowerConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.powerConfig = cfm->powerConfig; - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeHostConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeHostConfigGetCfm* cfm = (CsrWifiSmeHostConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeHostConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.hostConfig = cfm->hostConfig; - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeCoexInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCoexInfoGetCfm* cfm = (CsrWifiSmeCoexInfoGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeCoexInfoGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.coexInfo = cfm->coexInfo; - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeCoexConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCoexConfigGetCfm* cfm = (CsrWifiSmeCoexConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeCoexConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.coexConfig = cfm->coexConfig; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeMibConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMibConfigGetCfm* cfm = (CsrWifiSmeMibConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMibConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.mibConfig = cfm->mibConfig; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeConnectionInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeConnectionInfoGetCfm* cfm = (CsrWifiSmeConnectionInfoGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeConnectionInfoGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.connectionInfo = cfm->connectionInfo; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeConnectionConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeConnectionConfigGetCfm* cfm = (CsrWifiSmeConnectionConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeConnectionConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.connectionConfig = cfm->connectionConfig; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeConnectionStatsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeConnectionStatsGetCfm* cfm = (CsrWifiSmeConnectionStatsGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeConnectionStatsGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.connectionStats = cfm->connectionStats; - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeMibSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMibSetCfm* cfm = (CsrWifiSmeMibSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMibSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeMibGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMibGetCfm* cfm = (CsrWifiSmeMibGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMibGetCfmSend: Invalid ospriv.\n"); - return; - } - - if (cfm->mibAttribute == NULL) { - unifi_error(priv, "CsrWifiSmeMibGetCfmSend: Empty reply.\n"); - sme_complete_request(priv, cfm->status); - return; - } - - if ((priv->mib_cfm_buffer != NULL) && - (priv->mib_cfm_buffer_length >= cfm->mibAttributeLength)) { - memcpy(priv->mib_cfm_buffer, cfm->mibAttribute, cfm->mibAttributeLength); - priv->mib_cfm_buffer_length = cfm->mibAttributeLength; - } else { - unifi_error(priv, - "CsrWifiSmeMibGetCfmSend: No room to store MIB data (have=%d need=%d).\n", - priv->mib_cfm_buffer_length, cfm->mibAttributeLength); - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeMibGetNextCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMibGetNextCfm* cfm = (CsrWifiSmeMibGetNextCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeMibGetNextCfmSend: Invalid ospriv.\n"); - return; - } - - /* Need to copy MIB data */ - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeConnectionQualityIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeConnectionQualityInd* ind = (CsrWifiSmeConnectionQualityInd*)msg; - int signal, noise, snr; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeConnectionQualityIndSend: Invalid ospriv.\n"); - return; - } - - /* - * level and noise below are mapped into an unsigned 8 bit number, - * ranging from [-192; 63]. The way this is achieved is simply to - * add 0x100 onto the number if it is negative, - * once clipped to the correct range. - */ - signal = ind->linkQuality.unifiRssi; - /* Clip range of snr */ - snr = (ind->linkQuality.unifiSnr > 0) ? ind->linkQuality.unifiSnr : 0; /* In dB relative, from 0 - 255 */ - snr = (snr < 255) ? snr : 255; - noise = signal - snr; - - /* Clip range of signal */ - signal = (signal < 63) ? signal : 63; - signal = (signal > -192) ? signal : -192; - - /* Clip range of noise */ - noise = (noise < 63) ? noise : 63; - noise = (noise > -192) ? noise : -192; - - /* Make u8 */ - signal = ( signal < 0 ) ? signal + 0x100 : signal; - noise = ( noise < 0 ) ? noise + 0x100 : noise; - - priv->wext_wireless_stats.qual.level = (u8)signal; /* -192 : 63 */ - priv->wext_wireless_stats.qual.noise = (u8)noise; /* -192 : 63 */ - priv->wext_wireless_stats.qual.qual = snr; /* 0 : 255 */ - priv->wext_wireless_stats.qual.updated = 0; - -#if WIRELESS_EXT > 16 - priv->wext_wireless_stats.qual.updated |= IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED | - IW_QUAL_QUAL_UPDATED; -#if WIRELESS_EXT > 18 - priv->wext_wireless_stats.qual.updated |= IW_QUAL_DBM; -#endif -#endif -#endif -} - -void CsrWifiSmePacketFilterSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmePacketFilterSetCfmSend: Invalid ospriv.\n"); - return; - } - - /* The packet filter set request does not block for a reply */ -} - -void CsrWifiSmeTspecCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeTspecCfm* cfm = (CsrWifiSmeTspecCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeTspecCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeTspecIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeBlacklistCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeEventMaskSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiSmeRoamStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeRoamCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - /* This is called when the association completes, before any 802.1x authentication */ -} - -void CsrWifiSmeAssociationStartIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeAssociationCompleteIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeIbssStationIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeWifiOnIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeRestrictedAccessEnableCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeRestrictedAccessDisableCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiSmeAdhocConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeAdhocConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeAdhocConfigSetCfm* cfm = (CsrWifiSmeAdhocConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeCalibrationDataGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeCalibrationDataSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCalibrationDataSetCfm* cfm = (CsrWifiSmeCalibrationDataSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeCcxConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeCcxConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCcxConfigSetCfm* cfm = (CsrWifiSmeCcxConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeCloakedSsidsGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeCloakedSsidsSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCloakedSsidsSetCfm* cfm = (CsrWifiSmeCloakedSsidsSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - - -void CsrWifiSmeCoexConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeCoexConfigSetCfm* cfm = (CsrWifiSmeCoexConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeHostConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeHostConfigSetCfm* cfm = (CsrWifiSmeHostConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeLinkQualityGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiSmeMibConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMibConfigSetCfm* cfm = (CsrWifiSmeMibConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmePermanentMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmePowerConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmePowerConfigSetCfm* cfm = (CsrWifiSmePowerConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeRegulatoryDomainInfoGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeRoamingConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeMediaStatusIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeMediaStatusInd* ind = (CsrWifiSmeMediaStatusInd*)msg; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiSmeMediaStatusIndSend: invalid smepriv\n"); - return; - } - - if (ind->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) { - /* - * Send wireless-extension event up to userland to announce - * connection. - */ - wext_send_assoc_event(priv, - (unsigned char *)ind->connectionInfo.bssid.a, - (unsigned char *)ind->connectionInfo.assocReqInfoElements, - ind->connectionInfo.assocReqInfoElementsLength, - (unsigned char *)ind->connectionInfo.assocRspInfoElements, - ind->connectionInfo.assocRspInfoElementsLength, - (unsigned char *)ind->connectionInfo.assocScanInfoElements, - ind->connectionInfo.assocScanInfoElementsLength); - - unifi_trace(priv, UDBG2, "CsrWifiSmeMediaStatusIndSend: IBSS=%pM\n", - ind->connectionInfo.bssid.a); - - sme_mgt_packet_filter_set(priv); - - } else { - /* - * Send wireless-extension event up to userland to announce - * connection lost to a BSS. - */ - wext_send_disassoc_event(priv); - } -#endif -} - -void CsrWifiSmeRoamingConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeRoamingConfigSetCfm* cfm = (CsrWifiSmeRoamingConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeRoamingConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeScanConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeScanConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_SUPPORT_WEXT - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeScanConfigSetCfm* cfm = (CsrWifiSmeScanConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -#endif -} - -void CsrWifiSmeStationMacAddressGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeSmeCommonConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeSmeCommonConfigGetCfm* cfm = (CsrWifiSmeSmeCommonConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeCommonConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.deviceConfig = cfm->deviceConfig; - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeSmeStaConfigGetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeSmeStaConfigGetCfm* cfm = (CsrWifiSmeSmeStaConfigGetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeStaConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - priv->sme_reply.staConfig = cfm->smeConfig; - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeSmeCommonConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeSmeCommonConfigSetCfm* cfm = (CsrWifiSmeSmeCommonConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeCommonConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeSmeStaConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiSmeSmeStaConfigSetCfm* cfm = (CsrWifiSmeSmeStaConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiSmeSmeStaConfigGetCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiSmeGetInterfaceCapabilityCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeErrorIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeInfoIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeCoreDumpIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} -void CsrWifiSmeAmpStatusChangeIndHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiSmeActivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} -void CsrWifiSmeDeactivateCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -#ifdef CSR_SUPPORT_WEXT -#ifdef CSR_SUPPORT_WEXT_AP -void CsrWifiNmeApStartCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiNmeApStartCfm* cfm = (CsrWifiNmeApStartCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiNmeApStartCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiNmeApStopCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiNmeApStopCfm* cfm = (CsrWifiNmeApStopCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiNmeApStopCfmSend: Invalid ospriv.\n"); - return; - } - - sme_complete_request(priv, cfm->status); -} - -void CsrWifiNmeApConfigSetCfmHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiNmeApConfigSetCfm* cfm = (CsrWifiNmeApConfigSetCfm*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiNmeApConfigSetCfmSend: Invalid ospriv.\n"); - return; - } - sme_complete_request(priv, cfm->status); -} -#endif -#endif diff --git a/drivers/staging/csr/sme_native.c b/drivers/staging/csr/sme_native.c deleted file mode 100644 index d0b9be31e12c..000000000000 --- a/drivers/staging/csr/sme_native.c +++ /dev/null @@ -1,566 +0,0 @@ -/* - * *************************************************************************** - * - * FILE: sme_native.c - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ - -#include -#include "unifi_priv.h" -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" - -static const unsigned char wildcard_address[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -int -uf_sme_init(unifi_priv_t *priv) -{ - sema_init(&priv->mlme_blocking_mutex, 1); - -#ifdef CSR_SUPPORT_WEXT - { - int r = uf_init_wext_interface(priv); - if (r != 0) { - return r; - } - } -#endif - - return 0; -} /* uf_sme_init() */ - - -void -uf_sme_deinit(unifi_priv_t *priv) -{ - - /* Free memory allocated for the scan table */ -/* unifi_clear_scan_table(priv); */ - - /* Cancel any pending workqueue tasks */ - flush_workqueue(priv->unifi_workqueue); - -#ifdef CSR_SUPPORT_WEXT - uf_deinit_wext_interface(priv); -#endif - -} /* uf_sme_deinit() */ - - -int sme_mgt_wifi_on(unifi_priv_t *priv) -{ - int r, i; - s32 csrResult; - - if (priv == NULL) { - return -EINVAL; - } - /* Initialize the interface mode to None */ - for (i=0; iinterfacePriv[i]->interfaceMode = 0; - } - - /* Set up interface mode so that get_packet_priority() can - * select the right QOS priority when WMM is enabled. - */ - priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA; - - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n"); - return r; - } - - /* - * The request to initialise UniFi might come while UniFi is running. - * We need to block all I/O activity until the reset completes, otherwise - * an SDIO error might occur resulting an indication to the SME which - * makes it think that the initialisation has failed. - */ - priv->bh_thread.block_thread = 1; - - /* Power on UniFi */ - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioPowerOn(priv->sdio); - CsrSdioRelease(priv->sdio); - if(csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) { - return -EIO; - } - - if (csrResult == CSR_RESULT_SUCCESS) { - /* Initialise UniFi hardware */ - r = uf_init_hw(priv); - if (r) { - return r; - } - } - - /* Re-enable the I/O thread */ - priv->bh_thread.block_thread = 0; - - /* Disable deep sleep signalling during the firmware initialisation, to - * prevent the wakeup mechanism raising the SDIO clock beyond INIT before - * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind, - * immediately after the MLME-RESET.ind - */ - csrResult = unifi_configure_low_power_mode(priv->card, - UNIFI_LOW_POWER_DISABLED, - UNIFI_PERIODIC_WAKE_HOST_DISABLED); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_warning(priv, - "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n"); - } - - - /* Start the I/O thread */ - CsrSdioClaim(priv->sdio); - r = uf_init_bh(priv); - if (r) { - CsrSdioPowerOff(priv->sdio); - CsrSdioRelease(priv->sdio); - return r; - } - CsrSdioRelease(priv->sdio); - - priv->init_progress = UNIFI_INIT_FW_DOWNLOADED; - - return 0; -} - -int -sme_sys_suspend(unifi_priv_t *priv) -{ - const int interfaceNum = 0; /* FIXME */ - CsrResult csrResult; - - /* Abort any pending requests. */ - uf_abort_mlme(priv); - - /* Allow our mlme request to go through. */ - priv->io_aborted = 0; - - /* Send MLME-RESET.req to UniFi. */ - unifi_reset_state(priv, priv->netdev[interfaceNum]->dev_addr, 0); - - /* Stop the network traffic */ - netif_carrier_off(priv->netdev[interfaceNum]); - - /* Put UniFi to deep sleep */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_force_low_power_mode(priv->card); - CsrSdioRelease(priv->sdio); - - return 0; -} /* sme_sys_suspend() */ - - -int -sme_sys_resume(unifi_priv_t *priv) -{ -#ifdef CSR_SUPPORT_WEXT - /* Send disconnect event so clients will re-initialise connection. */ - memset(priv->wext_conf.current_ssid, 0, UNIFI_MAX_SSID_LEN); - memset((void*)priv->wext_conf.current_bssid, 0, ETH_ALEN); - priv->wext_conf.capability = 0; - wext_send_disassoc_event(priv); -#endif - return 0; -} /* sme_sys_resume() */ - - -/* - * --------------------------------------------------------------------------- - * sme_native_log_event - * - * Callback function to be registered as the SME event callback. - * Copies the signal content into a new udi_log_t struct and adds - * it to the read queue for the SME client. - * - * Arguments: - * arg This is the value given to unifi_add_udi_hook, in - * this case a pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointers to any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -sme_native_log_event(ul_client_t *pcli, - const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata, - int dir) -{ - unifi_priv_t *priv; - udi_log_t *logptr; - u8 *p; - int i, r; - int signal_len; - int total_len; - udi_msg_t *msgptr; - CSR_SIGNAL signal; - ul_client_t *client = pcli; - - if (client == NULL) { - unifi_error(NULL, "sme_native_log_event: client has exited\n"); - return; - } - - priv = uf_find_instance(client->instance); - if (!priv) { - unifi_error(priv, "invalid priv\n"); - return; - } - - /* Just a sanity check */ - if ((sig_packed == NULL) || (sig_len <= 0)) { - return; - } - - /* Get the unpacked signal */ - r = read_unpack_signal(sig_packed, &signal); - if (r == 0) { - signal_len = SigGetSize(&signal); - } else { - u16 receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed) + sizeof(u16)) & 0xFF00; - - /* The control indications are 1 byte, pass them to client. */ - if (sig_len == 1) { - unifi_trace(priv, UDBG5, - "Control indication (0x%x) for native SME.\n", - *sig_packed); - - *(u8*)&signal = *sig_packed; - signal_len = sig_len; - } else if (receiver_id == 0) { - /* - * Also "unknown" signals with a ReceiverId of 0 are passed to the client - * without unpacking. (This is a code size optimisation to allow signals - * that the driver not interested in to be dropped from the unpack code). - */ - unifi_trace(priv, UDBG5, - "Signal 0x%.4X with ReceiverId 0 for native SME.\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); - - *(u8*)&signal = *sig_packed; - signal_len = sig_len; - } else { - unifi_error(priv, - "sme_native_log_event - Received unknown signal 0x%.4X.\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); - return; - } - } - - unifi_trace(priv, UDBG3, "sme_native_log_event: signal 0x%.4X for %d\n", - signal.SignalPrimitiveHeader.SignalId, - client->client_id); - - total_len = signal_len; - /* Calculate the buffer we need to store signal plus bulk data */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - total_len += bulkdata->d[i].data_length; - } - - /* Allocate log structure plus actual signal. */ - logptr = kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL); - - if (logptr == NULL) { - unifi_error(priv, - "Failed to allocate %d bytes for a UDI log record\n", - sizeof(udi_log_t) + total_len); - return; - } - - /* Fill in udi_log struct */ - INIT_LIST_HEAD(&logptr->q); - msgptr = &logptr->msg; - msgptr->length = sizeof(udi_msg_t) + total_len; - msgptr->timestamp = jiffies_to_msecs(jiffies); - msgptr->direction = dir; - msgptr->signal_length = signal_len; - - /* Copy signal and bulk data to the log */ - p = (u8 *)(msgptr + 1); - memcpy(p, &signal, signal_len); - p += signal_len; - - /* Append any bulk data */ - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - int len = bulkdata->d[i].data_length; - - /* - * Len here might not be the same as the length in the bulk data slot. - * The slot length will always be even, but len could be odd. - */ - if (len > 0) { - if (bulkdata->d[i].os_data_ptr) { - memcpy(p, bulkdata->d[i].os_data_ptr, len); - } else { - memset(p, 0, len); - } - p += len; - } - } - - /* Add to tail of log queue */ - down(&client->udi_sem); - list_add_tail(&logptr->q, &client->udi_log); - up(&client->udi_sem); - - /* Wake any waiting user process */ - wake_up_interruptible(&client->udi_wq); - -} /* sme_native_log_event() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_ta_indicate_protocol - * - * Report that a packet of a particular type has been seen - * - * Arguments: - * drv_priv The device context pointer passed to ta_init. - * protocol The protocol type enum value. - * direction Whether the packet was a tx or rx. - * src_addr The source MAC address from the data packet. - * - * Returns: - * None. - * - * Notes: - * We defer the actual sending to a background workqueue, - * see uf_ta_ind_wq(). - * --------------------------------------------------------------------------- - */ -void -unifi_ta_indicate_protocol(void *ospriv, - CsrWifiRouterCtrlTrafficPacketType packet_type, - CsrWifiRouterCtrlProtocolDirection direction, - const CsrWifiMacAddress *src_addr) -{ - -} /* unifi_ta_indicate_protocol */ - -/* - * --------------------------------------------------------------------------- - * unifi_ta_indicate_sampling - * - * Send the TA sampling information to the SME. - * - * Arguments: - * drv_priv The device context pointer passed to ta_init. - * stats The TA sampling data to send. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats) -{ - -} /* unifi_ta_indicate_sampling() */ - - -void -unifi_ta_indicate_l4stats(void *ospriv, - u32 rxTcpThroughput, - u32 txTcpThroughput, - u32 rxUdpThroughput, - u32 txUdpThroughput) -{ - -} /* unifi_ta_indicate_l4stats() */ - -/* - * --------------------------------------------------------------------------- - * uf_native_process_udi_signal - * - * Process interesting signals from the UDI interface. - * - * Arguments: - * pcli A pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointers to any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -uf_native_process_udi_signal(ul_client_t *pcli, - const u8 *packed_signal, int packed_signal_len, - const bulk_data_param_t *bulkdata, int dir) -{ - -} /* uf_native_process_udi_signal() */ - - -/* - * --------------------------------------------------------------------------- - * sme_native_mlme_event_handler - * - * Callback function to be used as the udi_event_callback when registering - * as a client. - * This function implements a blocking request-reply interface for WEXT. - * To use it, a client specifies this function as the udi_event_callback - * to ul_register_client(). The signal dispatcher in - * unifi_receive_event() will call this function to deliver a signal. - * - * Arguments: - * pcli Pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointer to structure containing any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -sme_native_mlme_event_handler(ul_client_t *pcli, - const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata, - int dir) -{ - CSR_SIGNAL signal; - int signal_len; - unifi_priv_t *priv = uf_find_instance(pcli->instance); - int id, r; - - /* Just a sanity check */ - if ((sig_packed == NULL) || (sig_len <= 0)) { - return; - } - - /* Get the unpacked signal */ - r = read_unpack_signal(sig_packed, &signal); - if (r == 0) { - signal_len = SigGetSize(&signal); - } else { - unifi_error(priv, - "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed)); - return; - } - - id = signal.SignalPrimitiveHeader.SignalId; - unifi_trace(priv, UDBG4, "wext - Process signal 0x%.4X\n", id); - - /* - * Take the appropriate action for the signal. - */ - switch (id) { - /* - * Confirm replies from UniFi. - * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac) - */ - case CSR_MA_PACKET_CONFIRM_ID: - case CSR_MLME_RESET_CONFIRM_ID: - case CSR_MLME_GET_CONFIRM_ID: - case CSR_MLME_SET_CONFIRM_ID: - case CSR_MLME_GET_NEXT_CONFIRM_ID: - case CSR_MLME_POWERMGT_CONFIRM_ID: - case CSR_MLME_SCAN_CONFIRM_ID: - case CSR_MLME_HL_SYNC_CONFIRM_ID: - case CSR_MLME_MEASURE_CONFIRM_ID: - case CSR_MLME_SETKEYS_CONFIRM_ID: - case CSR_MLME_DELETEKEYS_CONFIRM_ID: - case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID: - case CSR_MLME_ADD_PERIODIC_CONFIRM_ID: - case CSR_MLME_DEL_PERIODIC_CONFIRM_ID: - case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID: - case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID: - case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID: - case CSR_MLME_STOP_MEASURE_CONFIRM_ID: - case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID: - case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID: - case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID: - case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID: - case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID: - case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID: - case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID: - case CSR_MLME_CONNECT_STATUS_CONFIRM_ID: - case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID: - case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID: - case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID: - case CSR_MLME_ADD_TSPEC_CONFIRM_ID: - case CSR_MLME_DEL_TSPEC_CONFIRM_ID: - case CSR_MLME_START_AGGREGATION_CONFIRM_ID: - case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID: - case CSR_MLME_SM_START_CONFIRM_ID: - case CSR_MLME_LEAVE_CONFIRM_ID: - case CSR_MLME_SET_TIM_CONFIRM_ID: - case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID: - case CSR_MLME_SET_CHANNEL_CONFIRM_ID: - case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID: - case CSR_DEBUG_GENERIC_CONFIRM_ID: - unifi_mlme_copy_reply_and_wakeup_client(pcli, &signal, signal_len, bulkdata); - break; - - case CSR_MLME_CONNECTED_INDICATION_ID: - /* We currently ignore the connected-ind for softmac f/w development */ - unifi_info(priv, "CSR_MLME_CONNECTED_INDICATION_ID ignored\n"); - break; - - default: - break; - } - -} /* sme_native_mlme_event_handler() */ - - - -/* - * ------------------------------------------------------------------------- - * unifi_reset_state - * - * Ensure that a MAC address has been set. - * Send the MLME-RESET signal. - * This must be called at least once before starting to do any - * network activities (e.g. scan, join etc). - * - * Arguments: - * priv Pointer to device private context struct - * macaddr Pointer to chip MAC address. - * If this is FF:FF:FF:FF:FF:FF it will be replaced - * with the MAC address from the chip. - * set_default_mib 1 if the f/w must reset the MIB to the default values - * 0 otherwise - * - * Returns: - * 0 on success, an error code otherwise. - * ------------------------------------------------------------------------- - */ -int -unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr, - unsigned char set_default_mib) -{ - int r = 0; - -#ifdef CSR_SUPPORT_WEXT - /* The reset clears any 802.11 association. */ - priv->wext_conf.flag_associated = 0; -#endif - - return r; -} /* unifi_reset_state() */ - diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c deleted file mode 100644 index b5258d71d250..000000000000 --- a/drivers/staging/csr/sme_sys.c +++ /dev/null @@ -1,3260 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sme_sys.c - * - * PURPOSE: - * Driver specific implementation of the SME SYS SAP. - * It is part of the porting exercise. - * - * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include "csr_wifi_hip_unifiversion.h" -#include "unifi_priv.h" -#include "csr_wifi_hip_conversions.h" -#ifdef CSR_SUPPORT_WEXT_AP -#include "csr_wifi_sme_sef.h" -#endif - -/* - * This file implements the SME SYS API and contains the following functions: - * CsrWifiRouterCtrlMediaStatusReqHandler() - * CsrWifiRouterCtrlHipReqHandler() - * CsrWifiRouterCtrlPortConfigureReqHandler() - * CsrWifiRouterCtrlWifiOnReqHandler() - * CsrWifiRouterCtrlWifiOffReqHandler() - * CsrWifiRouterCtrlSuspendResHandler() - * CsrWifiRouterCtrlResumeResHandler() - * CsrWifiRouterCtrlQosControlReqHandler() - * CsrWifiRouterCtrlConfigurePowerModeReqHandler() - * CsrWifiRouterCtrlWifiOnResHandler() - * CsrWifiRouterCtrlWifiOffRspHandler() - * CsrWifiRouterCtrlMulticastAddressResHandler() - * CsrWifiRouterCtrlTrafficConfigReqHandler() - * CsrWifiRouterCtrlTrafficClassificationReqHandler() - * CsrWifiRouterCtrlTclasAddReqHandler() - * CsrWifiRouterCtrlTclasDelReqHandler() - * CsrWifiRouterCtrlSetModeReqHandler() - * CsrWifiRouterCtrlWapiMulticastFilterReqHandler() - * CsrWifiRouterCtrlWapiUnicastFilterReqHandler() - * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler() - * CsrWifiRouterCtrlWapiRxPktReqHandler() - * CsrWifiRouterCtrlWapiFilterReqHandler() - */ - -#ifdef CSR_SUPPORT_SME -static void check_inactivity_timer_expire_func(unsigned long data); -void uf_send_disconnected_ind_wq(struct work_struct *work); -#endif - -void send_auto_ma_packet_confirm(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - struct list_head *buffered_frames_list) -{ - tx_buffered_packets_t *buffered_frame_item = NULL; - struct list_head *listHead; - struct list_head *placeHolder; - int client_id; - - CSR_SIGNAL unpacked_signal; - u8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; - u16 packed_siglen; - - - list_for_each_safe(listHead, placeHolder, buffered_frames_list) - { - buffered_frame_item = list_entry(listHead, tx_buffered_packets_t, q); - - if(!buffered_frame_item) { - unifi_error(priv, "Entry should exist, otherwise it is a (BUG)\n"); - continue; - } - - if ((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_NONE) && - (priv->wifi_on_state == wifi_on_done)) - { - - unifi_warning(priv, "Send MA_PACKET_CONFIRM to SenderProcessId = %x for (HostTag = %x TransmissionControl = %x)\n", - (buffered_frame_item->leSenderProcessId), - buffered_frame_item->hostTag, - buffered_frame_item->transmissionControl); - - client_id = buffered_frame_item->leSenderProcessId & 0xFF00; - - if (client_id == priv->sme_cli->sender_id) - { - /* construct a MA-PACKET.confirm message for SME */ - memset(&unpacked_signal, 0, sizeof(unpacked_signal)); - unpacked_signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_CONFIRM_ID; - unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId = buffered_frame_item->leSenderProcessId; - unpacked_signal.SignalPrimitiveHeader.SenderProcessId = CSR_WIFI_ROUTER_IFACEQUEUE; - - unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, - interfacePriv->InterfaceTag); - unpacked_signal.u.MaPacketConfirm.TransmissionStatus = CSR_RESULT_FAILURE; - unpacked_signal.u.MaPacketConfirm.RetryCount = 0; - unpacked_signal.u.MaPacketConfirm.Rate = buffered_frame_item->rate; - unpacked_signal.u.MaPacketConfirm.HostTag = buffered_frame_item->hostTag; - - write_pack(&unpacked_signal, sigbuf, &packed_siglen); - unifi_warning(priv, "MA_PACKET_CONFIRM for SME (0x%x, 0x%x, 0x%x, 0x%x)\n", - unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId, - unpacked_signal.SignalPrimitiveHeader.SenderProcessId, - unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier, - unpacked_signal.u.MaPacketConfirm.HostTag); - - CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - packed_siglen, - (u8 *)sigbuf, - 0, NULL, - 0, NULL); - } - else if((buffered_frame_item->hostTag & 0x80000000)) - { - /* construct a MA-PACKET.confirm message for NME */ - unifi_warning(priv, "MA_PACKET_CONFIRM for NME (0x%x, 0x%x, 0x%x, 0x%x)\n", - buffered_frame_item->leSenderProcessId, - buffered_frame_item->interfaceTag, - buffered_frame_item->transmissionControl, - (buffered_frame_item->hostTag & 0x3FFFFFFF)); - - CsrWifiRouterMaPacketCfmSend((buffered_frame_item->leSenderProcessId & 0xFF), - buffered_frame_item->interfaceTag, - CSR_RESULT_FAILURE, - (buffered_frame_item->hostTag & 0x3FFFFFFF), - buffered_frame_item->rate); - - } - else - { - unifi_warning(priv, "Buffered packet dropped without sending a confirm\n"); - } - - } - - list_del(listHead); - kfree(buffered_frame_item); - buffered_frame_item = NULL; - } -} - -void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlMediaStatusReq* req = (CsrWifiRouterCtrlMediaStatusReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - unsigned long flags; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid smepriv\n"); - return; - } - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid interfaceTag\n"); - return; - } - unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlMediaStatusReqHandler: Mode = %d req->mediaStatus = %d\n", interfacePriv->interfaceMode, req->mediaStatus); - if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AMP) { - bulk_data_desc_t bulk_data; - - bulk_data.data_length = 0; - - spin_lock_irqsave(&priv->m4_lock, flags); - if (interfacePriv->m4_bulk_data.data_length > 0) { - bulk_data = interfacePriv->m4_bulk_data; - interfacePriv->m4_bulk_data.net_buf_length = 0; - interfacePriv->m4_bulk_data.data_length = 0; - interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; - } - spin_unlock_irqrestore(&priv->m4_lock, flags); - - if (bulk_data.data_length != 0) { - unifi_trace(priv, UDBG5, "CsrWifiRouterCtrlMediaStatusReqHandler: free M4\n"); - unifi_net_data_free(priv, &bulk_data); - } - - if ((req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) && - (interfacePriv->connected != UnifiConnected)) { - - switch(interfacePriv->interfaceMode){ - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - interfacePriv->connected = UnifiConnected; - netif_carrier_on(priv->netdev[req->interfaceTag]); -#ifdef CSR_SUPPORT_WEXT - wext_send_started_event(priv); -#endif - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: AP/P2PGO setting netif_carrier_on\n"); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); - break; - - default: -#ifdef CSR_SUPPORT_WEXT - /* In the WEXT builds (sme and native), the userspace is not ready - * to process any EAPOL or WAPI packets, until it has been informed - * of the NETDEV_CHANGE. - */ - if (interfacePriv->netdev_callback_registered && (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI)) { - interfacePriv->wait_netdev_change = TRUE; - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: waiting for NETDEV_CHANGE\n"); - /* - * Carrier can go to on, only after wait_netdev_change is set to TRUE. - * Otherwise there can be a race in uf_netdev_event(). - */ - netif_carrier_on(priv->netdev[req->interfaceTag]); - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: STA/P2PCLI setting netif_carrier_on\n"); - } - else -#endif - { - /* In the NME build, the userspace does not wait for the NETDEV_CHANGE - * so it is ready to process all the EAPOL or WAPI packets. - * At this point, we enable all the Tx queues, and we indicate any packets - * that are queued (and the respective port is opened). - */ - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - interfacePriv->connected = UnifiConnected; - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: UnifiConnected && netif_carrier_on\n"); - netif_carrier_on(priv->netdev[req->interfaceTag]); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); - uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - } - break; - } - } - - if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED) { -#ifdef CSR_SUPPORT_WEXT - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: cancel waiting for NETDEV_CHANGE\n"); - interfacePriv->wait_netdev_change = FALSE; -#endif - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: setting netif_carrier_off\n"); - netif_carrier_off(priv->netdev[req->interfaceTag]); -#ifdef CSR_SUPPORT_WEXT - switch(interfacePriv->interfaceMode){ - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - wext_send_started_event(priv); - break; - default: - break; - } -#endif - interfacePriv->connected = UnifiNotConnected; - } - } else { - /* For AMP, just update the L2 connected flag */ - if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP connected\n"); - interfacePriv->connected = UnifiConnected; - } else { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP disconnected\n"); - interfacePriv->connected = UnifiNotConnected; - } - } -} - - -void CsrWifiRouterCtrlHipReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlHipReq* hipreq = (CsrWifiRouterCtrlHipReq*)msg; - bulk_data_param_t bulkdata; - u8 *signal_ptr; - int signal_length; - int r=0; - void *dest; - CsrResult csrResult; - CSR_SIGNAL *signal; - u16 interfaceTag = 0; - CSR_MA_PACKET_REQUEST *req; - netInterface_priv_t *interfacePriv; - - if (priv == NULL) { - return; - } - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid smepriv\n"); - return; - } - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Initialize bulkdata to avoid os_net_buf is garbage */ - memset(&bulkdata, 0, sizeof(bulk_data_param_t)); - - signal = (CSR_SIGNAL *)hipreq->mlmeCommand; - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: 0x04%X ---->\n", - *((u16*)hipreq->mlmeCommand)); - - /* Construct the signal. */ - signal_ptr = (u8*)hipreq->mlmeCommand; - signal_length = hipreq->mlmeCommandLength; - - /* - * The MSB of the sender ID needs to be set to the client ID. - * The LSB is controlled by the SME. - */ - signal_ptr[5] = (priv->sme_cli->sender_id >> 8) & 0xff; - - /* Allocate buffers for the bulk data. */ - if (hipreq->dataRef1Length) { - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], hipreq->dataRef1Length); - if (csrResult == CSR_RESULT_SUCCESS) { - dest = (void*)bulkdata.d[0].os_data_ptr; - memcpy(dest, hipreq->dataRef1, hipreq->dataRef1Length); - bulkdata.d[0].data_length = hipreq->dataRef1Length; - } else { - unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); - return; - } - } else { - bulkdata.d[0].os_data_ptr = NULL; - bulkdata.d[0].data_length = 0; - } - if (hipreq->dataRef2Length) { - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[1], hipreq->dataRef2Length); - if (csrResult == CSR_RESULT_SUCCESS) { - dest = (void*)bulkdata.d[1].os_data_ptr; - memcpy(dest, hipreq->dataRef2, hipreq->dataRef2Length); - bulkdata.d[1].data_length = hipreq->dataRef2Length; - } else { - if (bulkdata.d[0].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[0]); - } - unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); - return; - } - } else { - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - } - - unifi_trace(priv, UDBG3, "SME SEND: Signal 0x%.4X \n", - *((u16*)signal_ptr)); - if (signal->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) - { - CSR_SIGNAL unpacked_signal; - read_unpack_signal((u8 *) signal, &unpacked_signal); - req = &unpacked_signal.u.MaPacketRequest; - interfaceTag = req->VirtualInterfaceIdentifier & 0xff; - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_NONE: - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid mode: NONE \n"); - break; - default: - unifi_trace(priv, UDBG5, "mode is %x\n", interfacePriv->interfaceMode); - } - /* While sending ensure that first 2 bits b31 and b30 are 00. These are used for local routing*/ - r = uf_process_ma_packet_req(priv, req->Ra.x, (req->HostTag & 0x3FFFFFFF), interfaceTag, - req->TransmissionControl, req->TransmitRate, - req->Priority, signal->SignalPrimitiveHeader.SenderProcessId, - &bulkdata); - if (r) - { - if (bulkdata.d[0].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[0]); - } - if (bulkdata.d[1].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[1]); - } - } - } else { - /* ul_send_signal_raw frees the bulk data if it fails */ - r = ul_send_signal_raw(priv, signal_ptr, signal_length, &bulkdata); - } - - if (r) { - unifi_error(priv, - "CsrWifiRouterCtrlHipReqHandler: Failed to send signal (0x%.4X - %u)\n", - *((u16*)signal_ptr), r); - CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, CSR_WIFI_SME_CONTROL_INDICATION_ERROR); - } - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: <----\n"); -} - -#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP -static void -uf_send_gratuitous_arp(unifi_priv_t *priv, u16 interfaceTag) -{ - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CSR_PRIORITY priority; - CSR_SIGNAL signal; - bulk_data_param_t bulkdata; - CsrResult csrResult; - struct sk_buff *skb, *newSkb = NULL; - s8 protection; - int r; - static const u8 arp_req[36] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, - 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, - 0x00, 0x02, 0x5f, 0x20, 0x2f, 0x02, - 0xc0, 0xa8, 0x00, 0x02, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xa8, 0x00, 0x02}; - - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], sizeof(arp_req)); - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(priv, "Failed to allocate bulk data in CsrWifiSmeRoamCompleteIndHandler()\n"); - return; - } - skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); - skb->len = bulkdata.d[0].data_length; - - memcpy(skb->data, arp_req, sizeof(arp_req)); - /* add MAC and IP address */ - memcpy(skb->data + 16, priv->netdev[interfaceTag]->dev_addr, ETH_ALEN); - skb->data[22] = (priv->sta_ip_address ) & 0xFF; - skb->data[23] = (priv->sta_ip_address >> 8) & 0xFF; - skb->data[24] = (priv->sta_ip_address >> 16) & 0xFF; - skb->data[25] = (priv->sta_ip_address >> 24) & 0xFF; - skb->data[32] = (priv->sta_ip_address ) & 0xFF; - skb->data[33] = (priv->sta_ip_address >> 8) & 0xFF; - skb->data[34] = (priv->sta_ip_address >> 16) & 0xFF; - skb->data[35] = (priv->sta_ip_address >> 24) & 0xFF; - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; - - if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, &arp_req[26])) < 0) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: Failed to determine protection mode\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - - if ((priv->sta_wmm_capabilities & QOS_CAPABILITY_WMM_ENABLED) == 1) - { - priority = CSR_QOS_UP0; - } - else - { - priority = CSR_CONTENTION; - } - - if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, - interfaceTag, &arp_req[26], - priv->netdev[interfaceTag]->dev_addr, protection)) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - bulkdata.d[0].os_data_ptr = skb->data; - bulkdata.d[0].os_net_buf_ptr = skb; - bulkdata.d[0].data_length = skb->len; - - unifi_frame_ma_packet_req(priv, priority, 0, 0xffffffff, interfaceTag, - CSR_NO_CONFIRM_REQUIRED, priv->netdev_client->sender_id, - interfacePriv->bssid.a, &signal); - - r = ul_send_signal_unpacked(priv, &signal, &bulkdata); - if (r) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to send QOS data null packet result: %d\n", r); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - -} -#endif /* CSR_WIFI_SEND_GRATUITOUS_ARP */ - -/* - * --------------------------------------------------------------------------- - * configure_data_port - * - * Store the new controlled port configuration. - * - * Arguments: - * priv Pointer to device private context struct - * port_cfg Pointer to the port configuration - * - * Returns: - * An unifi_ControlledPortAction value. - * --------------------------------------------------------------------------- - */ -static int -configure_data_port(unifi_priv_t *priv, - CsrWifiRouterCtrlPortAction port_action, - const CsrWifiMacAddress *macAddress, - const int queue, - u16 interfaceTag) -{ - const u8 broadcast_mac_address[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - unifi_port_config_t *port; - netInterface_priv_t *interfacePriv; - int i; - const char* controlled_string; /* cosmetic "controlled"/"uncontrolled" for trace */ - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "configure_data_port: bad interfaceTag\n"); - return -EFAULT; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if (queue == UF_CONTROLLED_PORT_Q) { - port = &interfacePriv->controlled_data_port; - controlled_string = "controlled"; - } else { - port = &interfacePriv->uncontrolled_data_port; - controlled_string = "uncontrolled"; - } - - unifi_trace(priv, UDBG2, - "port config request %pM %s with port_action %d.\n", - macAddress->a, controlled_string, port_action); - - /* If the new configuration has the broadcast MAC address or if we are in infrastructure mode then clear the list first and set port overide mode */ - if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) || - !memcmp(macAddress->a, broadcast_mac_address, ETH_ALEN)) { - - port->port_cfg[0].port_action = port_action; - port->port_cfg[0].mac_address = *macAddress; - port->port_cfg[0].in_use = TRUE; - port->entries_in_use = 1; - port->overide_action = UF_DATA_PORT_OVERIDE; - - unifi_trace(priv, UDBG2, "%s port override on\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - - /* Discard the remaining entries in the port config table */ - for (i = 1; i < UNIFI_MAX_CONNECTIONS; i++) { - port->port_cfg[i].in_use = FALSE; - } - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - unifi_trace(priv, UDBG1, "%s port broadcast set to open.\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - - /* - * Ask stack to schedule for transmission any packets queued - * while controlled port was not open. - * Use netif_schedule() instead of netif_wake_queue() because - * transmission should be already enabled at this point. If it - * is not, probably the interface is down and should remain as is. - */ - uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); - -#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP - if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && - (queue == UF_CONTROLLED_PORT_Q) && (priv->sta_ip_address != 0xFFFFFFFF)) - { - uf_send_gratuitous_arp(priv, interfaceTag); - } -#endif - } else { - unifi_trace(priv, UDBG1, "%s port broadcast set to %s.\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled", - (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) ? "discard": "closed"); - - /* If port is closed, discard all the pending Rx packets */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - uf_free_pending_rx_packets(priv, queue, *macAddress, interfaceTag); - } - } - } else { - /* store the new configuration, either in the entry with matching mac address (if already present), - * otherwise in a new entry - */ - - int found_entry_flag; - int first_free_slot = -1; - - /* If leaving override mode, free the port entry used for override */ - if (port->overide_action == UF_DATA_PORT_OVERIDE) { - port->port_cfg[0].in_use = FALSE; - port->entries_in_use = 0; - port->overide_action = UF_DATA_PORT_NOT_OVERIDE; - - unifi_trace(priv, UDBG2, "%s port override off\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - } - - found_entry_flag = 0; - for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if (port->port_cfg[i].in_use) { - if (!memcmp(&port->port_cfg[i].mac_address.a, macAddress->a, ETH_ALEN)) { - /* We've seen this address before, reconfigure it */ - port->port_cfg[i].port_action = port_action; - found_entry_flag = 1; - break; - } - } else if (first_free_slot == -1) { - /* Remember the first free slot on the way past so it can be claimed - * if this turns out to be a new MAC address (to save walking the list again). - */ - first_free_slot = i; - } - } - - /* At this point we found an existing entry and have updated it, or need to - * add a new entry. If all slots are allocated, give up and return an error. - */ - if (!found_entry_flag) { - if (first_free_slot == -1) { - unifi_error(priv, "no free slot found in port config array (%d used)\n", port->entries_in_use); - return -EFAULT; - } else { - port->entries_in_use++; - } - - unifi_trace(priv, UDBG3, "port config index assigned in config_data_port = %d\n", first_free_slot); - port->port_cfg[first_free_slot].in_use = TRUE; - port->port_cfg[first_free_slot].port_action = port_action; - port->port_cfg[first_free_slot].mac_address = *macAddress; - } - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - /* - * Ask stack to schedule for transmission any packets queued - * while controlled port was not open. - * Use netif_schedule() instead of netif_wake_queue() because - * transmission should be already enabled at this point. If it - * is not, probably the interface is down and should remain as is. - */ - uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); - } - - /* - * If port is closed, discard all the pending Rx packets - * coming from the peer station. - */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - uf_free_pending_rx_packets(priv, queue, *macAddress, interfaceTag); - } - - unifi_trace(priv, UDBG2, - "port config %pM with port_action %d.\n", - macAddress->a, port_action); - } - return 0; -} /* configure_data_port() */ - - -void CsrWifiRouterCtrlPortConfigureReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlPortConfigureReq* req = (CsrWifiRouterCtrlPortConfigureReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - unifi_trace(priv, UDBG3, "entering CsrWifiRouterCtrlPortConfigureReqHandler\n"); - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlPortConfigureReqHandler: invalid smepriv\n"); - return; - } - - /* To update the protection status of the peer/station */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - /* Since for Unifi as a station, the station record not maintained & interfaceID is - * only needed to update the peer protection status - */ - interfacePriv->protect = req->setProtection; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - { - u8 i; - CsrWifiRouterCtrlStaInfo_t *staRecord; - /* Ifscontrolled port is open means, The peer has been added to station record - * so that the protection corresponding to the peer is valid in this req - */ - if (req->controlledPortAction == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { - staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); - if (staRecord) { - /* Find the matching station record & set the protection type */ - if (!memcmp(req->macAddress.a, staRecord->peerMacAddress.a, ETH_ALEN)) { - staRecord->protection = req->setProtection; - break; - } - } - } - } - } - break; - default: - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlPortConfigureReqHandler(0x%.4X) Uncaught mode %d\n", - msg->source, interfacePriv->interfaceMode); - } - - configure_data_port(priv, req->uncontrolledPortAction, (const CsrWifiMacAddress *)&req->macAddress, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - configure_data_port(priv, req->controlledPortAction, (const CsrWifiMacAddress *)&req->macAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - - CsrWifiRouterCtrlPortConfigureCfmSend(msg->source, req->clientData, req->interfaceTag, - CSR_RESULT_SUCCESS, req->macAddress); - unifi_trace(priv, UDBG3, "leaving CsrWifiRouterCtrlPortConfigureReqHandler\n"); -} - - -void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlVersions versions; - CsrWifiRouterCtrlWifiOnReq* req = (CsrWifiRouterCtrlWifiOnReq*)msg; - int r, i; - CsrResult csrResult; - - if (priv == NULL) { - return; - } - if( priv->wol_suspend ) { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Don't reset mode\n"); - } else { -#ifdef ANDROID_BUILD - /* Take the wakelock while Wi-Fi On is in progress */ - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: take wake lock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - for (i=0; iinterfacePriv[i]->interfaceMode = 0; - } - } - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X) req->dataLength=%d req->data=0x%x\n", msg->source, req->dataLength, req->data); - - if(req->dataLength==3 && req->data && req->data[0]==0 && req->data[1]==1 && req->data[2]==1) - { - priv->cmanrTestMode = TRUE; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: cmanrTestMode=%d\n", priv->cmanrTestMode); - } - else - { - priv->cmanrTestMode = FALSE; - } - - /* - * The request to initialise UniFi might come while UniFi is running. - * We need to block all I/O activity until the reset completes, otherwise - * an SDIO error might occur resulting an indication to the SME which - * makes it think that the initialisation has failed. - */ - priv->bh_thread.block_thread = 1; - - /* Update the wifi_on state */ - priv->wifi_on_state = wifi_on_in_progress; - - /* If UniFi was unpowered, acquire the firmware for download to chip */ - if (!priv->wol_suspend) { - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - } else { - unifi_trace(priv, UDBG1, "Don't need firmware\n"); - } - - /* Power on UniFi (which may not necessarily have been off) */ - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioPowerOn(priv->sdio); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to power on UniFi\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - - /* If CsrSdioPowerOn() returns CSR_RESULT_SUCCESS, it means that we need to initialise UniFi */ - if (csrResult == CSR_RESULT_SUCCESS && !priv->wol_suspend) { - /* Initialise UniFi hardware */ - r = uf_init_hw(priv); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - } else { - unifi_trace(priv, UDBG1, "UniFi already initialised\n"); - } - - /* Completed handling of wake up from suspend with UniFi powered */ - priv->wol_suspend = FALSE; - - /* Re-enable the I/O thread */ - priv->bh_thread.block_thread = 0; - - /* - * Start the I/O thread. The thread might be already running. - * This fine, just carry on with the request. - */ - r = uf_init_bh(priv); - if (r) { - CsrSdioClaim(priv->sdio); - CsrSdioPowerOff(priv->sdio); - CsrSdioRelease(priv->sdio); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - - /* Get the version information from the core */ - unifi_card_info(priv->card, &priv->card_info); - - /* Set the sme queue id */ - priv->CSR_WIFI_SME_IFACEQUEUE = msg->source; - CSR_WIFI_SME_IFACEQUEUE = msg->source; - - - /* Copy to the unifiio_card_info structure. */ - versions.chipId = priv->card_info.chip_id; - versions.chipVersion = priv->card_info.chip_version; - versions.firmwareBuild = priv->card_info.fw_build; - versions.firmwareHip = priv->card_info.fw_hip_version; - versions.routerBuild = (char*)CSR_WIFI_VERSION; - versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; - - CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); - - /* Update the wifi_on state */ - priv->wifi_on_state = wifi_on_done; -} - - -/* - * wifi_off: - * Common code for CsrWifiRouterCtrlWifiOffReqHandler() and - * CsrWifiRouterCtrlWifiOffRspHandler(). - */ -static void -wifi_off(unifi_priv_t *priv) -{ - int power_off; - int priv_instance; - int i; - CsrResult csrResult; - - - /* Already off? */ - if (priv->wifi_on_state == wifi_on_unspecified) { - unifi_trace(priv, UDBG1, "wifi_off already\n"); - return; - } - - unifi_trace(priv, UDBG1, "wifi_off\n"); - - /* Destroy the Traffic Analysis Module */ - cancel_work_sync(&priv->ta_ind_work.task); - cancel_work_sync(&priv->ta_sample_ind_work.task); -#ifdef CSR_SUPPORT_WEXT - cancel_work_sync(&priv->sme_config_task); - wext_send_disassoc_event(priv); -#endif - - /* Cancel pending M4 stuff */ - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - if (priv->netdev[i]) { - netInterface_priv_t *netpriv = (netInterface_priv_t *) netdev_priv(priv->netdev[i]); - cancel_work_sync(&netpriv->send_m4_ready_task); - } - } - flush_workqueue(priv->unifi_workqueue); - - /* fw_init parameter can prevent power off UniFi, for debugging */ - priv_instance = uf_find_priv(priv); - if (priv_instance == -1) { - unifi_warning(priv, - "CsrWifiRouterCtrlStopReqHandler: Unknown priv instance, will power off card.\n"); - power_off = 1; - } else { - power_off = (fw_init[priv_instance] > 0) ? 0 : 1; - } - - /* Production test mode requires power to the chip, too */ - if (priv->ptest_mode) { - power_off = 0; - } - - /* Stop the bh_thread */ - uf_stop_thread(priv, &priv->bh_thread); - - /* Read the f/w panic codes, if any. Protect against second wifi_off() call, - * which may happen if SME requests a wifi_off and closes the char device */ - if (priv->init_progress != UNIFI_INIT_NONE) { - CsrSdioClaim(priv->sdio); - unifi_capture_panic(priv->card); - CsrSdioRelease(priv->sdio); - } - - /* Unregister the interrupt handler */ - if (csr_sdio_linux_remove_irq(priv->sdio)) { - unifi_notice(priv, - "csr_sdio_linux_remove_irq failed to talk to card.\n"); - } - - if (power_off) { - unifi_trace(priv, UDBG2, - "Force low power and try to power off\n"); - /* Put UniFi to deep sleep, in case we can not power it off */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_force_low_power_mode(priv->card); - CsrSdioRelease(priv->sdio); - - CsrSdioPowerOff(priv->sdio); - } - - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; - priv->wifi_on_state = wifi_on_unspecified; - - -} /* wifi_off() */ - - -void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg; - int i = 0; - - if (priv == NULL) { - return; - } - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOffReqHandler(0x%.4X)\n", msg->source); - - /* Stop the network traffic on all interfaces before freeing the core. */ - for (i=0; iinterfacePriv[i]; - if (interfacePriv->netdev_registered == 1) { - netif_carrier_off(priv->netdev[i]); - netif_tx_stop_all_queues(priv->netdev[i]); - interfacePriv->connected = UnifiConnectedUnknown; - } - interfacePriv->interfaceMode = 0; - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - } - wifi_off(priv); - - CsrWifiRouterCtrlWifiOffCfmSend(msg->source, req->clientData); - - /* If this is called in response to closing the character device, the - * caller must use uf_sme_cancel_request() to terminate any pending SME - * blocking request or there will be a delay while the operation times out. - */ -} - - -void CsrWifiRouterCtrlQosControlReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlQosControlReq* req = (CsrWifiRouterCtrlQosControlReq*)msg; - netInterface_priv_t *interfacePriv; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: invalid smepriv\n"); - return; - } - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlQosControlReqHandler:scontrol = %d", req->control); - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return; - } - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (req->control == CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON) { - priv->sta_wmm_capabilities |= QOS_CAPABILITY_WMM_ENABLED; - unifi_trace(priv, UDBG1, "WMM enabled\n"); - - unifi_trace(priv, UDBG1, "Queue Config %x\n", req->queueConfig); - - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BK] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BE] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VI] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VO] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE)?1:0; - - } else { - priv->sta_wmm_capabilities = 0; - unifi_trace(priv, UDBG1, "WMM disabled\n"); - } -} - - -void CsrWifiRouterCtrlTclasAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTclasAddReq* req = (CsrWifiRouterCtrlTclasAddReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTclasAddReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlTclasAddCfmSend(msg->source, req->clientData, req->interfaceTag , CSR_RESULT_SUCCESS); -} - -void CsrWifiRouterCtrlTclasDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTclasDelReq* req = (CsrWifiRouterCtrlTclasDelReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTclasDelReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlTclasDelCfmSend(msg->source, req->clientData, req->interfaceTag, CSR_RESULT_SUCCESS); -} - - -void CsrWifiRouterCtrlConfigurePowerModeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlConfigurePowerModeReq* req = (CsrWifiRouterCtrlConfigurePowerModeReq*)msg; - enum unifi_low_power_mode pm; - CsrResult csrResult; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlConfigurePowerModeReqHandler: invalid smepriv\n"); - return; - } - - if (req->mode == CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED) { - pm = UNIFI_LOW_POWER_DISABLED; - } else { - pm = UNIFI_LOW_POWER_ENABLED; - } - - unifi_trace(priv, UDBG2, - "CsrWifiRouterCtrlConfigurePowerModeReqHandler (mode=%d, wake=%d)\n", - req->mode, req->wakeHost); - csrResult = unifi_configure_low_power_mode(priv->card, pm, - (req->wakeHost ? UNIFI_PERIODIC_WAKE_HOST_ENABLED : UNIFI_PERIODIC_WAKE_HOST_DISABLED)); -} - - -void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWifiOnRes* res = (CsrWifiRouterCtrlWifiOnRes*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiRouterCtrlWifiOnResHandler: Invalid ospriv.\n"); - return; - } - - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlWifiOnResHandler: status %d (patch %u)\n", res->status, res->smeVersions.firmwarePatch); - - if (res->smeVersions.firmwarePatch != 0) { - unifi_info(priv, "Firmware patch %d\n", res->smeVersions.firmwarePatch); - } - - if (res->numInterfaceAddress > CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "WifiOnResHandler bad numInterfaceAddress %d\n", res->numInterfaceAddress); - return; - } - - /* UniFi is now initialised, complete the init. */ - if (res->status == CSR_RESULT_SUCCESS) - { - int i; /* used as a loop counter */ - u32 intmode = CSR_WIFI_INTMODE_DEFAULT; -#ifdef CSR_WIFI_SPLIT_PATCH - u8 switching_ap_fw = FALSE; -#endif - /* Register the UniFi device with the OS network manager */ - unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n"); - - /* Store the MAC address in the netdev */ - for(i=0;inumInterfaceAddress;i++) - { - memcpy(priv->netdev[i]->dev_addr, res->stationMacAddress[i].a, ETH_ALEN); - } - - /* Copy version structure into the private versions field */ - priv->sme_versions = res->smeVersions; - - unifi_trace(priv, UDBG2, "network interfaces count = %d\n", - res->numInterfaceAddress); - - /* Register the netdevs for each interface. */ - for(i=0;inumInterfaceAddress;i++) - { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - if(!interfacePriv->netdev_registered) - { - int r; - unifi_trace(priv, UDBG3, "registering net device %d\n", i); - r = uf_register_netdev(priv, i); - if (r) - { - /* unregister the net_device that are registered in the previous iterations */ - uf_unregister_netdev(priv); - unifi_error(priv, "Failed to register the network device.\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); - return; - } - } -#ifdef CSR_WIFI_SPLIT_PATCH - else - { - /* If a netdev is already registered, we have received this WifiOnRes - * in response to switching AP/STA firmware in a ModeSetReq. - * Rememeber this in order to send a ModeSetCfm once - */ - switching_ap_fw = TRUE; - } -#endif - } - priv->totalInterfaceCount = res->numInterfaceAddress; - - /* If the MIB has selected f/w scheduled interrupt mode, apply it now - * but let module param override. - */ - if (run_bh_once != -1) { - intmode = (u32)run_bh_once; - } else if (res->scheduledInterrupt) { - intmode = CSR_WIFI_INTMODE_RUN_BH_ONCE; - } - unifi_set_interrupt_mode(priv->card, intmode); - - priv->init_progress = UNIFI_INIT_COMPLETED; - - /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS); - -#ifdef CSR_WIFI_SPLIT_PATCH - if (switching_ap_fw && (priv->pending_mode_set.common.destination != 0xaaaa)) { - unifi_info(priv, "Completed firmware reload with %s patch\n", - CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode) ? "AP" : "STA"); - - /* Confirm the ModeSetReq that requested the AP/STA patch switch */ - CsrWifiRouterCtrlModeSetCfmSend(priv->pending_mode_set.common.source, - priv->pending_mode_set.clientData, - priv->pending_mode_set.interfaceTag, - priv->pending_mode_set.mode, - CSR_RESULT_SUCCESS); - priv->pending_mode_set.common.destination = 0xaaaa; - } -#endif - unifi_info(priv, "UniFi ready\n"); - -#ifdef ANDROID_BUILD - /* Release the wakelock */ - unifi_trace(priv, UDBG1, "ready: release wake lock\n"); - wake_unlock(&unifi_sdio_wake_lock); -#endif - /* Firmware initialisation is complete, so let the SDIO bus - * clock be raised when convienent to the core. - */ - unifi_request_max_sdio_clock(priv->card); - -#ifdef CSR_SUPPORT_WEXT - /* Notify the Android wpa_supplicant that we are ready */ - wext_send_started_event(priv); - - queue_work(priv->unifi_workqueue, &priv->sme_config_task); -#endif - - } else { - /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); - } -} - - -void CsrWifiRouterCtrlWifiOffResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiRouterCtrlMulticastAddressResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiRouterMaPacketSubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketSubscribeReq* req = (CsrWifiRouterMaPacketSubscribeReq*)msg; - u8 i; - CsrResult result; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterMaPacketSubscribeReqHandler: invalid priv\n"); - return; - } - - /* Look for an unused filter */ - - result = CSR_WIFI_RESULT_NO_ROOM; - for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { - - if (!priv->sme_unidata_ind_filters[i].in_use) { - - priv->sme_unidata_ind_filters[i].in_use = 1; - priv->sme_unidata_ind_filters[i].appHandle = msg->source; - priv->sme_unidata_ind_filters[i].encapsulation = req->encapsulation; - priv->sme_unidata_ind_filters[i].protocol = req->protocol; - - priv->sme_unidata_ind_filters[i].oui[2] = (u8) (req->oui & 0xFF); - priv->sme_unidata_ind_filters[i].oui[1] = (u8) ((req->oui >> 8) & 0xFF); - priv->sme_unidata_ind_filters[i].oui[0] = (u8) ((req->oui >> 16) & 0xFF); - - result = CSR_RESULT_SUCCESS; - break; - } - } - - unifi_trace(priv, UDBG1, - "subscribe_req: encap=%d, handle=%d, result=%d\n", - req->encapsulation, i, result); - CsrWifiRouterMaPacketSubscribeCfmSend(msg->source, req->interfaceTag, i, result, 0); -} - - -void CsrWifiRouterMaPacketUnsubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketUnsubscribeReq* req = (CsrWifiRouterMaPacketUnsubscribeReq*)msg; - CsrResult result; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterMaPacketUnsubscribeReqHandler: invalid priv\n"); - return; - } - - result = CSR_WIFI_RESULT_NOT_FOUND; - - if (req->subscriptionHandle < MAX_MA_UNIDATA_IND_FILTERS) { - if (priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use) { - priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use = 0; - result = CSR_RESULT_SUCCESS; - } else { - result = CSR_WIFI_RESULT_NOT_FOUND; - } - } - - unifi_trace(priv, UDBG1, - "unsubscribe_req: handle=%d, result=%d\n", - req->subscriptionHandle, result); - CsrWifiRouterMaPacketUnsubscribeCfmSend(msg->source, req->interfaceTag, result); -} - - -void CsrWifiRouterCtrlCapabilitiesReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlCapabilitiesReq* req = (CsrWifiRouterCtrlCapabilitiesReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlCapabilitiesReqHandler: invalid priv\n"); - return; - } - - CsrWifiRouterCtrlCapabilitiesCfmSend(msg->source, req->clientData, - UNIFI_SOFT_COMMAND_Q_LENGTH - 1, - UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1); -} - - -void CsrWifiRouterCtrlSuspendResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlSuspendRes* res = (CsrWifiRouterCtrlSuspendRes*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlSuspendResHandler: invalid priv\n"); - return; - } - - sme_complete_request(priv, res->status); -} - - -void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlResumeRes* res = (CsrWifiRouterCtrlResumeRes*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlResumeResHandler: invalid priv\n"); - return; - } - - sme_complete_request(priv, res->status); -} - - -void CsrWifiRouterCtrlTrafficConfigReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTrafficConfigReq* req = (CsrWifiRouterCtrlTrafficConfigReq*)msg; - CsrResult csrResult; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTrafficConfigReqHandler: invalid smepriv\n"); - return; - } - if (req->trafficConfigType == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER) - { - req->config.packetFilter |= CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM; - } - csrResult = unifi_ta_configure(priv->card, req->trafficConfigType, (const CsrWifiRouterCtrlTrafficConfig *)&req->config); -} - -void CsrWifiRouterCtrlTrafficClassificationReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTrafficClassificationReq* req = (CsrWifiRouterCtrlTrafficClassificationReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTrafficClassificationReqHandler: invalid smepriv\n"); - return; - } - - unifi_ta_classification(priv->card, req->trafficType, req->period); -} - -static int -_sys_packet_req(unifi_priv_t *priv, const CSR_SIGNAL *signal, - u8 subscriptionHandle, - u16 frameLength, u8 *frame, - int proto) -{ - int r; - const sme_ma_unidata_ind_filter_t *subs; - bulk_data_param_t bulkdata; - CSR_MA_PACKET_REQUEST req = signal->u.MaPacketRequest; - struct sk_buff *skb, *newSkb = NULL; - CsrWifiMacAddress peerMacAddress; - CsrResult csrResult; - u16 interfaceTag = req.VirtualInterfaceIdentifier & 0xff; - u8 eapolStore = FALSE; - s8 protection = 0; - netInterface_priv_t *interfacePriv; - unsigned long flags; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "_sys_packet_req: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return -EINVAL; - } - interfacePriv = priv->interfacePriv[interfaceTag]; - if (!priv->sme_unidata_ind_filters[subscriptionHandle].in_use) { - unifi_error(priv, "_sys_packet_req: unknown subscription.\n"); - return -EINVAL; - } - - subs = &priv->sme_unidata_ind_filters[subscriptionHandle]; - unifi_trace(priv, UDBG1, - "_sys_packet_req: handle=%d, subs=%p, encap=%d\n", - subscriptionHandle, subs, subs->encapsulation); - - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], frameLength); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "_sys_packet_req: failed to allocate bulkdata.\n"); - return (int)CsrHipResultToStatus(csrResult); - } - - /* get the peer Mac address */ - memcpy(&peerMacAddress, frame, ETH_ALEN); - - /* Determine if we need to add encapsulation header */ - if (subs->encapsulation == CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET) { - memcpy((void*)bulkdata.d[0].os_data_ptr, frame, frameLength); - - /* The translation is performed on the skb */ - skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; - - unifi_trace(priv, UDBG1, - "_sys_packet_req: skb_add_llc_snap -->\n"); - r = skb_add_llc_snap(priv->netdev[interfaceTag], skb, proto); - unifi_trace(priv, UDBG1, - "_sys_packet_req: skb_add_llc_snap <--\n"); - if (r) { - unifi_error(priv, - "_sys_packet_req: failed to translate eth frame.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return r; - } - - bulkdata.d[0].data_length = skb->len; - } else { - /* Crop the MAC addresses from the packet */ - memcpy((void*)bulkdata.d[0].os_data_ptr, frame + 2*ETH_ALEN, frameLength - 2*ETH_ALEN); - bulkdata.d[0].data_length = frameLength - 2*ETH_ALEN; - skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; - skb->len = bulkdata.d[0].data_length; - - } - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].data_length = 0; - - /* check for m4 detection */ - if (0 == uf_verify_m4(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length)) { - eapolStore = TRUE; - } - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - if (proto == ETH_P_WAI) - { - protection = 0; /*WAI packets always sent unencrypted*/ - } - else - { -#endif - -#ifdef CSR_SUPPORT_SME - if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, peerMacAddress.a)) < 0) { - unifi_error(priv, "unicast address, but destination not in station record database\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } -#else - protection = 0; -#endif - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - } -#endif - - /* add Mac header */ - if (prepare_and_add_macheader(priv, skb, newSkb, req.Priority, &bulkdata, interfaceTag, frame, frame + ETH_ALEN, protection)) { - unifi_error(priv, "failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } - - if (eapolStore) { - spin_lock_irqsave(&priv->m4_lock, flags); - /* Store the EAPOL M4 packet for later */ - interfacePriv->m4_signal = *signal; - interfacePriv->m4_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; - interfacePriv->m4_bulk_data.data_length = bulkdata.d[0].data_length; - interfacePriv->m4_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; - interfacePriv->m4_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; - spin_unlock_irqrestore(&priv->m4_lock, flags); - /* Send a signal to SME */ - unifi_trace(priv, UDBG1, "_sys_packet_req: Sending CsrWifiRouterCtrlM4ReadyToSendInd\n"); - CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - return 0; - } - - /* Send the signal to UniFi */ - /* Set the B31 to 1 for local routing*/ - r= uf_process_ma_packet_req(priv, peerMacAddress.a, (req.HostTag | 0x80000000), interfaceTag, 0, - (CSR_RATE)0, req.Priority, signal->SignalPrimitiveHeader.SenderProcessId, &bulkdata); - if (r) { - unifi_error(priv, - "_sys_packet_req: failed to send signal.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return r; - } - /* The final CsrWifiRouterMaPacketCfmSend() will called when the actual MA-PACKET.cfm is received from the chip */ - - return 0; -} - -void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - int r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketReq* mareq = (CsrWifiRouterMaPacketReq*)msg; - llc_snap_hdr_t *snap; - u16 snap_protocol; - CSR_SIGNAL signal; - CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; - CsrWifiRouterCtrlPortAction controlPortaction; - u8 *daddr, *saddr; - u16 interfaceTag = mareq->interfaceTag & 0x00ff; - int queue; - netInterface_priv_t *interfacePriv; - - if (!mareq->frame || !priv || !priv->smepriv) - { - unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: invalid frame/priv/priv->smepriv\n"); - return; - } - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - /* get a pointer to dest & source Mac address */ - daddr = mareq->frame; - saddr = (mareq->frame + ETH_ALEN); - /* point to the proper position of frame, since frame has MAC header */ - snap = (llc_snap_hdr_t *) (mareq->frame + 2 * ETH_ALEN); - snap_protocol = ntohs(snap->protocol); - if((snap_protocol == ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - || (snap_protocol == ETH_P_WAI) -#endif - ) - { - queue = UF_UNCONTROLLED_PORT_Q; - } - else - { - queue = UF_CONTROLLED_PORT_Q; - } - - /* Controlled port restrictions apply to the packets */ - controlPortaction = uf_sme_port_state(priv, daddr, queue, interfaceTag); - if (controlPortaction != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) - { - unifi_warning(priv, "CsrWifiRouterMaPacketReqHandler: (%s)controlled port is closed.\n", (queue == UF_CONTROLLED_PORT_Q)?"":"un"); - if(mareq->cfmRequested) - { - CsrWifiRouterMaPacketCfmSend(msg->source, - interfaceTag, - CSR_RESULT_FAILURE, - mareq->hostTag, 0); - } - return; - } - - signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; - /* Store the appHandle in the LSB of the SenderId. */ - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(((priv->sme_cli->sender_id & 0xff00) | (unsigned int)msg->source), - (u8*)&signal.SignalPrimitiveHeader.SenderProcessId); - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - - /* Fill in the MA-PACKET.req signal */ - memcpy(req->Ra.x, daddr, ETH_ALEN); - req->Priority = mareq->priority; - req->TransmitRate = 0; /* Let firmware select the rate*/ - req->VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag); - req->HostTag = mareq->hostTag; - - if(mareq->cfmRequested) - req->TransmissionControl = 0; - else - req->TransmissionControl = CSR_NO_CONFIRM_REQUIRED; - - r = _sys_packet_req(priv, &signal, mareq->subscriptionHandle, - mareq->frameLength, mareq->frame, snap_protocol); - - if (r && mareq->cfmRequested) - { - CsrWifiRouterMaPacketCfmSend(msg->source, interfaceTag, - CSR_RESULT_FAILURE, - mareq->hostTag, 0); - } - return; -} - -void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiRouterCtrlM4TransmitReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlM4TransmitReq* req = (CsrWifiRouterCtrlM4TransmitReq*)msg; - int r; - bulk_data_param_t bulkdata; - netInterface_priv_t *interfacePriv; - CSR_SIGNAL m4_signal; - unsigned long flags; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid smepriv\n"); - return; - } - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "M4TransmitReqHandler: interfaceTag >= CSR_WIFI_NUM_INTERFACES\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - spin_lock_irqsave(&priv->m4_lock, flags); - if (interfacePriv->m4_bulk_data.data_length == 0) { - spin_unlock_irqrestore(&priv->m4_lock, flags); - unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid buffer\n"); - return; - } - - memcpy(&bulkdata.d[0], &interfacePriv->m4_bulk_data, sizeof(bulk_data_desc_t)); - - interfacePriv->m4_bulk_data.net_buf_length = 0; - interfacePriv->m4_bulk_data.data_length = 0; - interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; - m4_signal = interfacePriv->m4_signal; - spin_unlock_irqrestore(&priv->m4_lock, flags); - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - - interfacePriv->m4_sent = TRUE; - m4_signal.u.MaPacketRequest.HostTag |= 0x80000000; - /* Store the hostTag for later varification */ - interfacePriv->m4_hostTag = m4_signal.u.MaPacketRequest.HostTag; - r = ul_send_signal_unpacked(priv, &m4_signal, &bulkdata); - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlM4TransmitReqHandler: sent\n"); - if (r) { - unifi_error(priv, - "CsrWifiRouterCtrlM4TransmitReqHandler: failed to send signal.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - } -} - -/* reset the station records when the mode is set as CSR_WIFI_ROUTER_CTRL_MODE_NONE */ -static void CsrWifiRouterCtrlResetStationRecordList(unifi_priv_t *priv, u16 interfaceTag) -{ - u8 i, j; - CsrWifiRouterCtrlStaInfo_t *staInfo=NULL; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - unsigned long lock_flags; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlResetStationRecordList: bad interfaceTag\n"); - return; - } - - INIT_LIST_HEAD(&send_cfm_list); - - /* Reset the station record to NULL if mode is NONE */ - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if ((staInfo=interfacePriv->staInfo[i]) != NULL) { - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - uf_flush_list(priv, &(staInfo->mgtFrames)); - for(j=0;jdataPdu[j])); - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Removing station record information from port config array */ - memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerControlledPort->in_use = FALSE; - interfacePriv->controlled_data_port.entries_in_use--; - - memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerUnControlledPort->in_use = FALSE; - interfacePriv->uncontrolled_data_port.entries_in_use--; - - kfree(interfacePriv->staInfo[i]); - interfacePriv->staInfo[i] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - /* after the critical region process the list of frames that requested cfm - * and send cfm to requestor one by one - */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - -#ifdef CSR_SUPPORT_SME - /* Interface Independent, no of packet queued, incase of mode is None or AP set to 0 */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - case CSR_WIFI_ROUTER_CTRL_MODE_NONE: - if (priv->noOfPktQueuedInDriver) { - unifi_warning(priv, "After reset the noOfPktQueuedInDriver = %x\n", priv->noOfPktQueuedInDriver); - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - priv->noOfPktQueuedInDriver = 0; - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } - break; - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - break; - default: - unifi_error(priv, "interfacemode is not correct in CsrWifiRouterCtrlResetStationRecordList: debug\n"); - } -#endif - - if (((interfacePriv->controlled_data_port.entries_in_use != 0) || (interfacePriv->uncontrolled_data_port.entries_in_use != 0)) - && (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_NONE)) { - /* Print in case if the value of entries goes to -ve/+ve (apart from 0) - * we expect the entries should be zero here if mode is set as NONE - */ - unifi_trace(priv, UDBG3, "In %s controlled port entries = %d, uncontrolled port entries = %d\n", - __FUNCTION__, interfacePriv->controlled_data_port.entries_in_use, - interfacePriv->uncontrolled_data_port.entries_in_use); - } -} - -void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, u16 interfaceTag) -{ - netInterface_priv_t *interfacePriv; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlInterfaceReset: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - INIT_LIST_HEAD(&send_cfm_list); - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMgtFrames)); - uf_flush_list(priv, &(interfacePriv->genericMgtFrames)); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMulticastOrBroadCastMgtFrames)); - uf_flush_list(priv, &(interfacePriv->genericMulticastOrBroadCastMgtFrames)); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMulticastOrBroadCastFrames)); - - uf_flush_list(priv, &(interfacePriv->genericMulticastOrBroadCastFrames)); - - /* process the list of frames that requested cfm - and send cfm to requestor one by one */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - - /* Reset the station record to NULL if mode is tried to set as NONE */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - case CSR_WIFI_ROUTER_CTRL_MODE_MONITOR: - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - /* station records not available in these modes */ - break; - default: - CsrWifiRouterCtrlResetStationRecordList(priv, interfaceTag); - } - - interfacePriv->num_stations_joined = 0; - interfacePriv->sta_activity_check_enabled = FALSE; -} - - -void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlModeSetReq* req = (CsrWifiRouterCtrlModeSetReq*)msg; - - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES) - { - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; -#ifdef CSR_WIFI_SPLIT_PATCH - u8 old_mode = interfacePriv->interfaceMode; -#endif - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n", - interfacePriv->interfaceMode); - - interfacePriv->interfaceMode = req->mode; - -#ifdef CSR_WIFI_SPLIT_PATCH - /* Detect a change in mode that requires a switch to/from the AP firmware patch. - * This should only happen when transitioning in/out of AP modes. - */ - if (CSR_WIFI_HIP_IS_AP_FW(req->mode) != CSR_WIFI_HIP_IS_AP_FW(old_mode)) - { - CsrWifiRouterCtrlVersions versions; - int r; - -#ifdef ANDROID_BUILD - /* Take the wakelock while switching patch */ - unifi_trace(priv, UDBG1, "patch switch: take wake lock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - unifi_info(priv, "Resetting UniFi with %s patch\n", CSR_WIFI_HIP_IS_AP_FW(req->mode) ? "AP" : "STA"); - - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: Failed to get f/w\n"); - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_FAILURE); - return; - } - - /* Block the I/O thread */ - priv->bh_thread.block_thread = 1; - - /* Reset and download the new patch */ - r = uf_init_hw(priv); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_FAILURE); - return; - } - - /* Re-enable the I/O thread */ - priv->bh_thread.block_thread = 0; - - /* Get the version information from the core */ - unifi_card_info(priv->card, &priv->card_info); - - /* Copy to the unifiio_card_info structure. */ - versions.chipId = priv->card_info.chip_id; - versions.chipVersion = priv->card_info.chip_version; - versions.firmwareBuild = priv->card_info.fw_build; - versions.firmwareHip = priv->card_info.fw_hip_version; - versions.routerBuild = (char*)CSR_WIFI_VERSION; - versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; - - /* Now that new firmware is running, send a WifiOnInd to the NME. This will - * cause it to retransfer the MIB. - */ - CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); - - /* Store the request so we know where to send the ModeSetCfm */ - priv->pending_mode_set = *req; - } - else -#endif - { - /* No patch switch, confirm straightaway */ - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_SUCCESS); - } - - interfacePriv->bssid = req->bssid; - /* For modes other than AP/P2PGO, set below member FALSE */ - interfacePriv->intraBssEnabled = FALSE; - /* Initialise the variable bcTimSet with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - interfacePriv->bcTimSet = 0xFF; - interfacePriv->bcTimSetReqPendingFlag = FALSE; - /* Initialise the variable bcTimSetReqQueued with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - interfacePriv->bcTimSetReqQueued =0xFF; - CsrWifiRouterCtrlInterfaceReset(priv, req->interfaceTag); - - if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - interfacePriv->protect = req->protection; - interfacePriv->dtimActive=FALSE; - interfacePriv->multicastPduHostTag = 0xffffffff; - /* For AP/P2PGO mode SME sending intraBssDistEnabled - * i.e. for AP: intraBssDistEnabled = TRUE, for P2PGO - * intraBssDistEnabled = TRUE/FALSE on requirement - */ - interfacePriv->intraBssEnabled = req->intraBssDistEnabled; - unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlModeSetReqHandler: IntraBssDisEnabled = %d\n", - req->intraBssDistEnabled); - } else if (req->mode == CSR_WIFI_ROUTER_CTRL_MODE_NONE) { - netif_carrier_off(priv->netdev[req->interfaceTag]); - interfacePriv->connected = UnifiConnectedUnknown; - } - } - else { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid interfaceTag :%d\n", req->interfaceTag); - } -} - -void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -/* delete the station record from the station record data base */ -static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *req) -{ - u8 j; - CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; - unifi_port_config_t *controlledPort; - unifi_port_config_t *unControlledPort; - netInterface_priv_t *interfacePriv; - - u8 ba_session_idx = 0; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - unsigned long lock_flags; - - if ((req->peerRecordHandle >= UNIFI_MAX_CONNECTIONS) || (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES)) { - unifi_error(priv, "handle/interfaceTag is not proper, handle = %d, interfaceTag = %d\n", req->peerRecordHandle, req->interfaceTag); - return CSR_RESULT_FAILURE; - } - - INIT_LIST_HEAD(&send_cfm_list); - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - /* remove the station record & make it NULL */ - if ((staInfo=interfacePriv->staInfo[req->peerRecordHandle])!=NULL) { - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - - uf_flush_list(priv, &(staInfo->mgtFrames)); - for(j=0;jdataPdu[j])); - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* clear the port configure array info, for the corresponding peer entry */ - controlledPort = &interfacePriv->controlled_data_port; - unControlledPort = &interfacePriv->uncontrolled_data_port; - - unifi_trace(priv, UDBG1, "peer_delete_record: Peer found handle = %d, port in use: cont(%d), unCont(%d)\n", - req->peerRecordHandle, controlledPort->entries_in_use, unControlledPort->entries_in_use); - - memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerControlledPort->in_use = FALSE; - if (controlledPort->entries_in_use) { - controlledPort->entries_in_use--; - } else { - unifi_warning(priv, "number of controlled port entries is zero, trying to decrement: debug\n"); - } - - memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerUnControlledPort->in_use = FALSE; - if (unControlledPort->entries_in_use) { - unControlledPort->entries_in_use--; - } else { - unifi_warning(priv, "number of uncontrolled port entries is zero, trying to decrement: debug\n"); - } - - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - /* update the TIM with zero */ - if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS && - staInfo->timSet == CSR_WIFI_TIM_SET) { - unifi_trace(priv, UDBG3, "peer is deleted so TIM updated to 0, in firmware\n"); - update_tim(priv, staInfo->aid, 0, req->interfaceTag, req->peerRecordHandle); - } - - - /* Stop BA session if it is active, for this peer address all BA sessions - (per tID per role) are closed */ - - down(&priv->ba_mutex); - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx]; - if(ba_session_rx) { - if(!memcmp(ba_session_rx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ - blockack_session_stop(priv, - req->interfaceTag, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT, - ba_session_rx->tID, - ba_session_rx->macAddress); - } - } - } - - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = priv->interfacePriv[req->interfaceTag]->ba_session_tx[ba_session_idx]; - if(ba_session_tx) { - if(!memcmp(ba_session_tx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ - blockack_session_stop(priv, - req->interfaceTag, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR, - ba_session_tx->tID, - ba_session_tx->macAddress); - } - } - } - - up(&priv->ba_mutex); - -#ifdef CSR_SUPPORT_SME - unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid); - cancel_work_sync(&staInfo->send_disconnected_ind_task); -#endif - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); -#ifdef CSR_SUPPORT_SME - interfacePriv->num_stations_joined--; - - staInfo->nullDataHostTag = INVALID_HOST_TAG; - - if ((interfacePriv->sta_activity_check_enabled) && - (interfacePriv->num_stations_joined < STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)) - { - unifi_trace(priv, UDBG1, "STOPPING the Inactivity Timer (num of stations = %d)\n", interfacePriv->num_stations_joined); - interfacePriv->sta_activity_check_enabled = FALSE; - del_timer_sync(&interfacePriv->sta_activity_check_timer); - } -#endif - - /* Free the station record for corresponding peer */ - kfree(interfacePriv->staInfo[req->peerRecordHandle]); - interfacePriv->staInfo[req->peerRecordHandle] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - /* after the critical region process the list of frames that requested cfm - and send cfm to requestor one by one */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - - - } - else - { - unifi_trace(priv, UDBG3, " peer not found: Delete request Peer handle[%d]\n", req->peerRecordHandle); - } - - return CSR_RESULT_SUCCESS; -} - -void CsrWifiRouterCtrlPeerDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerDelReq* req = (CsrWifiRouterCtrlPeerDelReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerDelReqHandler\n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - /* remove the station from station record data base */ - status = peer_delete_record(priv, req); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - default: - /* No station record to maintain in these modes */ - break; - } - - CsrWifiRouterCtrlPeerDelCfmSend(msg->source, req->clientData, req->interfaceTag, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerDelReqHandler \n"); -} - -/* Add the new station to the station record data base */ -static int peer_add_new_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerAddReq *req, u32 *handle) -{ - u8 i, powerModeTemp = 0; - u8 freeSlotFound = FALSE; - CsrWifiRouterCtrlStaInfo_t *newRecord = NULL; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - u32 currentTime, currentTimeHi; - unsigned long lock_flags; - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "peer_add_new_record: bad interfaceTag\n"); - return CSR_RESULT_FAILURE; - } - - currentTime = CsrTimeGet(¤tTimeHi); - - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if(interfacePriv->staInfo[i] == NULL) { - /* Slot is empty, so can be used for station record */ - freeSlotFound = TRUE; - *handle = i; - - /* Allocate for the new station record , to avoid race condition would happen between ADD_PEER & - * DEL_PEER the allocation made atomic memory rather than kernel memory - */ - newRecord = kmalloc(sizeof(CsrWifiRouterCtrlStaInfo_t), GFP_ATOMIC); - if (!newRecord) { - unifi_error(priv, "failed to allocate the %d bytes of mem for station record\n", - sizeof(CsrWifiRouterCtrlStaInfo_t)); - return CSR_RESULT_FAILURE; - } - - unifi_trace(priv, UDBG1, "peer_add_new_record: handle = %d AID = %d addr = %x:%x:%x:%x:%x:%x LI=%u\n", - *handle, req->associationId, req->peerMacAddress.a[0], req->peerMacAddress.a[1], req->peerMacAddress.a[2], - req->peerMacAddress.a[3], req->peerMacAddress.a[4], req->peerMacAddress.a[5], - req->staInfo.listenIntervalInTus); - - /* disable the preemption until station record updated */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - - interfacePriv->staInfo[i] = newRecord; - /* Initialize the record*/ - memset(newRecord, 0, sizeof(CsrWifiRouterCtrlStaInfo_t)); - /* update the station record */ - memcpy(newRecord->peerMacAddress.a, req->peerMacAddress.a, ETH_ALEN); - newRecord->wmmOrQosEnabled = req->staInfo.wmmOrQosEnabled; - - /* maxSpLength is bit map in qosInfo field, so converting accordingly */ - newRecord->maxSpLength = req->staInfo.maxSpLength * 2; - - /*Max SP 0 mean any number of packets. since we buffer only 512 - packets we are hard coding this to zero for the moment */ - - if(newRecord->maxSpLength == 0) - newRecord->maxSpLength=512; - - newRecord->assignedHandle = i; - - /* copy power save mode of all access catagory (Trigger/Delivery/both enabled/disabled) */ - powerModeTemp = (u8) ((req->staInfo.powersaveMode >> 4) & 0xff); - - if(!(req->staInfo.powersaveMode & 0x0001)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= powerModeTemp & 0x03; - - if(!(req->staInfo.powersaveMode & 0x0002)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= ((powerModeTemp & 0x0C)>> 2); - - if(!(req->staInfo.powersaveMode & 0x0004)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= ((powerModeTemp & 0x30)>> 4); - - if(!(req->staInfo.powersaveMode & 0x0008)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= ((powerModeTemp & 0xC0)>> 6); - - { - u8 k; - for(k=0; k< MAX_ACCESS_CATOGORY ;k++) - unifi_trace(priv, UDBG2, "peer_add_new_record: WMM : %d ,AC %d, powersaveMode %x \n", - req->staInfo.wmmOrQosEnabled, k, newRecord->powersaveMode[k]); - } - - unifi_trace(priv, UDBG3, "newRecord->wmmOrQosEnabled : %d , MAX SP : %d\n", - newRecord->wmmOrQosEnabled, newRecord->maxSpLength); - - /* Initialize the mgtFrames & data Pdu list */ - { - u8 j; - INIT_LIST_HEAD(&newRecord->mgtFrames); - for(j = 0; j < MAX_ACCESS_CATOGORY; j++) { - INIT_LIST_HEAD(&newRecord->dataPdu[j]); - } - } - - newRecord->lastActivity = currentTime; - newRecord->activity_flag = TRUE; - - /* enable the preemption as station record updated */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - /* First time port actions are set for the peer with below information */ - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - } else { - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD, &newRecord->peerMacAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - } - - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Port status must be already set before calling the Add Peer request */ - newRecord->peerControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - newRecord->peerUnControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - - if (!newRecord->peerControlledPort || !newRecord->peerUnControlledPort) { - /* enable the preemption as station record failed to update */ - unifi_warning(priv, "Un/ControlledPort record not found in port configuration array index = %d\n", i); - kfree(interfacePriv->staInfo[i]); - interfacePriv->staInfo[i] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - return CSR_RESULT_FAILURE; - } - - newRecord->currentPeerState = CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE; - - /* changes done during block ack handling */ - newRecord->txSuspend = FALSE; - - /*U-APSD related data structure*/ - newRecord->timRequestPendingFlag = FALSE; - - /* Initialise the variable updateTimReqQueued with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - newRecord->updateTimReqQueued = 0xFF; - newRecord->timSet = CSR_WIFI_TIM_RESET; - newRecord->uapsdActive = FALSE; - newRecord->noOfSpFramesSent =0; - newRecord->triggerFramePriority = CSR_QOS_UP0; - - /* The protection bit is updated once the port opens for corresponding peer in - * routerPortConfigure request */ - - /* update the association ID */ - newRecord->aid = req->associationId; - -#ifdef CSR_SUPPORT_SME - interfacePriv->num_stations_joined++; - newRecord->interfacePriv = interfacePriv; - newRecord->listenIntervalInTus = req->staInfo.listenIntervalInTus; - newRecord->nullDataHostTag = INVALID_HOST_TAG; - - INIT_WORK(&newRecord->send_disconnected_ind_task, uf_send_disconnected_ind_wq); - - if(!(interfacePriv->sta_activity_check_enabled) && - (interfacePriv->num_stations_joined >= STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)){ - unifi_trace(priv, UDBG1, - "peer_add_new_record: STARTING the Inactivity Timer (num of stations = %d)", - interfacePriv->num_stations_joined); - - interfacePriv->sta_activity_check_enabled = TRUE; - interfacePriv->sta_activity_check_timer.function = check_inactivity_timer_expire_func; - interfacePriv->sta_activity_check_timer.data = (unsigned long)interfacePriv; - - init_timer(&interfacePriv->sta_activity_check_timer); - mod_timer(&interfacePriv->sta_activity_check_timer, - (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); - - } -#endif - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - break; - } - } - - if(!freeSlotFound) { - unifi_error(priv, "Limited connectivity, Free slot not found for station record addition\n"); - return CSR_RESULT_FAILURE; - } - return CSR_RESULT_SUCCESS; -} - -#ifdef CSR_SUPPORT_SME -static void check_inactivity_timer_expire_func(unsigned long data) -{ - struct unifi_priv *priv; - CsrWifiRouterCtrlStaInfo_t *sta_record = NULL; - u8 i = 0; - u32 now; - u32 inactive_time; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *) data; - - if (!interfacePriv) - { - return; - } - - priv = interfacePriv->privPtr; - - if (interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "check_inactivity_timer_expire_func: Invalid interfaceTag\n"); - return; - } - - /* RUN Algorithm to check inactivity for each connected station */ - now = CsrTimeGet(NULL); - - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if(interfacePriv->staInfo[i] != NULL) { - sta_record = interfacePriv->staInfo[i]; - - if (sta_record->activity_flag == TRUE){ - sta_record->activity_flag = FALSE; - sta_record->lastActivity = now; - continue; - } - - if (sta_record->lastActivity > now) - { - /* simple timer wrap (for 1 wrap) */ - inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now); - } - else - { - inactive_time = (u32)CsrTimeSub(now, sta_record->lastActivity); - } - - if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) - { - unifi_trace(priv, UDBG1, "STA is Inactive - AID = %d inactive_time = %d\n", - sta_record->aid, - inactive_time); - - /* station is in-active, if it is in active mode send a null frame - * and the station should acknowledge the null frame, if acknowledgement - * is not received throw out the station. - * If the station is in Power Save, update TIM for the station so - * that it wakes up and register some activity through PS-Poll or - * trigger frame. - */ - if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - { - unifi_trace(priv, UDBG1, "STA power save state - Active, send a NULL frame to check if it is ALIVE\n"); - uf_send_nulldata ( priv, - sta_record->interfacePriv->InterfaceTag, - sta_record->peerMacAddress.a, - CSR_CONTENTION, - sta_record); - } - else if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - { - if((sta_record->timSet == CSR_WIFI_TIM_SET) || - (sta_record->timSet == CSR_WIFI_TIM_SETTING)) - { - unifi_trace(priv, UDBG1, "STA power save state - PS, TIM is already SET\n"); - - /* If TIM is set and we do not have any activity for - * more than 3 listen intervals then send a disconnected - * indication to SME, to delete the station from station - * record list. - * The inactivity is already more than STA_INACTIVE_TIMEOUT_VAL - * and this check ensures if the listen interval is a larger - * value than STA_INACTIVE_TIMEOUT_VAL. - */ - if (inactive_time > (3 * (sta_record->listenIntervalInTus * 1024))) - { - unifi_trace(priv, UDBG1, "STA is inactive for more than 3 listen intervals\n"); - queue_work( priv->unifi_workqueue, - &sta_record->send_disconnected_ind_task); - } - - } - else - { - unifi_trace(priv, UDBG1, "STA power save state - PS, update TIM to see if it is ALIVE\n"); - update_tim(priv, - sta_record->aid, - CSR_WIFI_TIM_SET, - interfacePriv->InterfaceTag, - sta_record->assignedHandle); - } - } - } - } - } - - /* re-run the timer interrupt */ - mod_timer(&interfacePriv->sta_activity_check_timer, - (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); - -} - - -void uf_send_disconnected_ind_wq(struct work_struct *work) -{ - - CsrWifiRouterCtrlStaInfo_t *staInfo = container_of(work, CsrWifiRouterCtrlStaInfo_t, send_disconnected_ind_task); - unifi_priv_t *priv; - u16 interfaceTag; - struct list_head send_cfm_list; - u8 j; - - if(!staInfo) { - return; - } - - if(!staInfo->interfacePriv) { - return; - } - - priv = staInfo->interfacePriv->privPtr; - interfaceTag = staInfo->interfacePriv->InterfaceTag; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_send_disconnected_ind_wq: invalid interfaceTag\n"); - return; - } - - /* The SME/NME may be waiting for confirmation for requested frames to this station. - * So loop through buffered frames for this station and if confirmation is - * requested, send auto confirmation with failure status. Also flush the frames so - * that these are not processed again in PEER_DEL_REQ handler. - */ - INIT_LIST_HEAD(&send_cfm_list); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - - uf_flush_list(priv, &(staInfo->mgtFrames)); - - for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->dataPdu[j])); - - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - send_auto_ma_packet_confirm(priv, staInfo->interfacePriv, &send_cfm_list); - - unifi_warning(priv, "uf_send_disconnected_ind_wq: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", - staInfo->peerMacAddress.a[0], - staInfo->peerMacAddress.a[1], - staInfo->peerMacAddress.a[2], - staInfo->peerMacAddress.a[3], - staInfo->peerMacAddress.a[4], - staInfo->peerMacAddress.a[5]); - - CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - staInfo->interfacePriv->InterfaceTag, - staInfo->peerMacAddress, - CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); - - - return; -} - - -#endif -void CsrWifiRouterCtrlPeerAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerAddReq* req = (CsrWifiRouterCtrlPeerAddReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - u32 handle = 0; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerAddReqHandler \n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - /* Add station record */ - status = peer_add_new_record(priv, req, &handle); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - default: - /* No station record to maintain in these modes */ - break; - } - - CsrWifiRouterCtrlPeerAddCfmSend(msg->source, req->clientData, req->interfaceTag, req->peerMacAddress, handle, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerAddReqHandler \n"); -} - -void CsrWifiRouterCtrlPeerUpdateReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerUpdateReq* req = (CsrWifiRouterCtrlPeerUpdateReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerUpdateReqHandler \n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerUpdateReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlPeerUpdateCfmSend(msg->source, req->clientData, req->interfaceTag, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerUpdateReqHandler \n"); -} - - - void CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - /* This will never be called as it is intercepted in the Userspace */ -} - -void CsrWifiRouterCtrlRawSdioInitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - /* This will never be called as it is intercepted in the Userspace */ -} - -void -uf_send_ba_err_wq(struct work_struct *work) -{ - ba_session_rx_struct *ba_session = container_of(work, ba_session_rx_struct, send_ba_err_task); - unifi_priv_t *priv; - - if(!ba_session) { - return; - } - - if(!ba_session->interfacePriv) { - return; - } - - priv = ba_session->interfacePriv->privPtr; - - if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); - return; - } - - unifi_warning(priv, "%s: Calling CsrWifiRouterCtrlBlockAckErrorIndSend(%d, %d, %d, %d, %x:%x:%x:%x:%x:%x, %d)\n", - __FUNCTION__, - priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - ba_session->interfacePriv->InterfaceTag, - ba_session->tID, - ba_session->macAddress.a[0], - ba_session->macAddress.a[1], - ba_session->macAddress.a[2], - ba_session->macAddress.a[3], - ba_session->macAddress.a[4], - ba_session->macAddress.a[5], - CSR_RESULT_SUCCESS - ); - CsrWifiRouterCtrlBlockAckErrorIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - ba_session->interfacePriv->InterfaceTag, - ba_session->tID, - ba_session->macAddress, - CSR_RESULT_SUCCESS); -} - - -static void ba_session_terminate_timer_func(unsigned long data) -{ - ba_session_rx_struct *ba_session = (ba_session_rx_struct*)data; - struct unifi_priv *priv; - - if(!ba_session) { - return; - } - - if(!ba_session->interfacePriv) { - return; - } - - priv = ba_session->interfacePriv->privPtr; - - if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); - return; - } - - queue_work(priv->unifi_workqueue, &ba_session->send_ba_err_task); -} - - -u8 blockack_session_stop(unifi_priv_t *priv, - u16 interfaceTag, - CsrWifiRouterCtrlBlockAckRole role, - u16 tID, - CsrWifiMacAddress macAddress) -{ - netInterface_priv_t *interfacePriv; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - u8 ba_session_idx = 0; - int i; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); - return FALSE; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if(!interfacePriv) { - unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); - return FALSE; - } - - if(tID > 15) { - unifi_error(priv, "%s: bad tID = %d\n", __FUNCTION__, tID); - return FALSE; - } - - if((role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR) && - (role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT)) { - unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); - return FALSE; - } - - unifi_warning(priv, - "%s: stopping ba_session for peer = %pM role = %d tID = %d\n", - __func__, macAddress.a, role, tID); - - /* find out the appropriate ba session (/station /tid /role) for which stop is requested */ - if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - - ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; - - if(ba_session_rx){ - if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ - break; - } - } - } - - if (!ba_session_rx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX)) { - unifi_error(priv, "%s: bad ba_session for Rx [tID=%d]\n", __FUNCTION__, tID); - return FALSE; - } - - - if(ba_session_rx->timeout) { - del_timer_sync(&ba_session_rx->timer); - } - cancel_work_sync(&ba_session_rx->send_ba_err_task); - for (i = 0; i < ba_session_rx->wind_size; i++) { - if(ba_session_rx->buffer[i].active) { - frame_desc_struct *frame_desc = &ba_session_rx->buffer[i]; - unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); - } - } - kfree(ba_session_rx->buffer); - - interfacePriv->ba_session_rx[ba_session_idx] = NULL; - kfree(ba_session_rx); - }else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; - if(ba_session_tx){ - if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ - break; - } - } - } - - if (!ba_session_tx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX)) { - unifi_error(priv, "%s: bad ba_session for Tx [tID=%d]\n", __FUNCTION__, tID); - return FALSE; - } - interfacePriv->ba_session_tx[ba_session_idx] = NULL; - kfree(ba_session_tx); - - } - - return TRUE; -} - - -void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlBlockAckDisableReq* req = (CsrWifiRouterCtrlBlockAckDisableReq*)msg; - u8 r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__); - - down(&priv->ba_mutex); - r = blockack_session_stop(priv, - req->interfaceTag, - req->role, - req->trafficStreamID, - req->macAddress); - up(&priv->ba_mutex); - - CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source, - req->clientData, - req->interfaceTag, - r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); - - unifi_trace(priv, UDBG6, "%s: out ok\n", __FUNCTION__); -} - - -u8 blockack_session_start(unifi_priv_t *priv, - u16 interfaceTag, - u16 tID, - u16 timeout, - CsrWifiRouterCtrlBlockAckRole role, - u16 wind_size, - u16 start_sn, - CsrWifiMacAddress macAddress - ) -{ - netInterface_priv_t *interfacePriv; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - u8 ba_session_idx = 0; - - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); - return FALSE; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if(!interfacePriv) { - unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); - return FALSE; - } - - if(tID > 15) - { - unifi_error(priv, "%s: bad tID=%d\n", __FUNCTION__, tID); - return FALSE; - } - - if(wind_size > MAX_BA_WIND_SIZE) { - unifi_error(priv, "%s: bad wind_size = %d\n", __FUNCTION__, wind_size); - return FALSE; - } - - if(role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR && - role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT) { - unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); - return FALSE; - } - - unifi_warning(priv, - "%s: ba session with peer= (%pM)\n", __func__, - macAddress.a); - - unifi_warning(priv, "%s: ba session for tID=%d timeout=%d role=%d wind_size=%d start_sn=%d\n", __FUNCTION__, - tID, - timeout, - role, - wind_size, - start_sn); - - /* Check if BA session exists for per station, per TID, per role or not. - if BA session exists update parameters and if it does not exist - create a new BA session */ - if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; - if (ba_session_tx) { - if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ - unifi_warning(priv, "%s: ba_session for Tx already exists\n", __FUNCTION__); - return TRUE; - } - } - } - - /* we have to create new ba_session_tx struct */ - ba_session_tx = NULL; - - /* loop through until an empty BA session slot is there and save the session there */ - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX ; ba_session_idx++){ - if (!(interfacePriv->ba_session_tx[ba_session_idx])){ - break; - } - } - if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX){ - unifi_error(priv, "%s: All ba_session used for Tx, NO free session available\n", __FUNCTION__); - return FALSE; - } - - /* create and populate the new BA session structure */ - ba_session_tx = kzalloc(sizeof(ba_session_tx_struct), GFP_KERNEL); - if (!ba_session_tx) { - unifi_error(priv, "%s: kmalloc failed for ba_session_tx\n", __FUNCTION__); - return FALSE; - } - - ba_session_tx->interfacePriv = interfacePriv; - ba_session_tx->tID = tID; - ba_session_tx->macAddress = macAddress; - - interfacePriv->ba_session_tx[ba_session_idx] = ba_session_tx; - - } else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ - - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; - if (ba_session_rx) { - if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ - unifi_warning(priv, "%s: ba_session for Rx[tID = %d] already exists\n", __FUNCTION__, tID); - - if(ba_session_rx->wind_size == wind_size && - ba_session_rx->timeout == timeout && - ba_session_rx->expected_sn == start_sn) { - return TRUE; - } - - if(ba_session_rx->timeout) { - del_timer_sync(&ba_session_rx->timer); - ba_session_rx->timeout = 0; - } - - if(ba_session_rx->wind_size != wind_size) { - blockack_session_stop(priv, interfaceTag, role, tID, macAddress); - } else { - if (timeout) { - ba_session_rx->timeout = timeout; - ba_session_rx->timer.function = ba_session_terminate_timer_func; - ba_session_rx->timer.data = (unsigned long)ba_session_rx; - init_timer(&ba_session_rx->timer); - mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); - } - /* - * The starting sequence number shall remain same if the BA - * enable request is issued to update BA parameters only. If - * it is not same, then we scroll our window to the new starting - * sequence number. This could happen if the DELBA frame from - * originator is lost and then we receive ADDBA frame with new SSN. - */ - if(ba_session_rx->start_sn != start_sn) { - scroll_ba_window(priv, interfacePriv, ba_session_rx, start_sn); - } - return TRUE; - } - } - } - } - - /* we could have a valid BA session pointer here or un-initialized - ba session pointer. but in any case we have to create a new session. - so re-initialize the ba_session pointer */ - ba_session_rx = NULL; - - /* loop through until an empty BA session slot is there and save the session there */ - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX ; ba_session_idx++){ - if (!(interfacePriv->ba_session_rx[ba_session_idx])){ - break; - } - } - if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ - unifi_error(priv, "%s: All ba_session used for Rx, NO free session available\n", __FUNCTION__); - return FALSE; - } - - /* It is observed that with some devices there is a race between - * EAPOL exchanges and BA session establishment. This results in - * some EAPOL authentication packets getting stuck in BA reorder - * buffer and hence the conection cannot be established. To avoid - * this we check here if the EAPOL authentication is complete and - * if so then only allow the BA session to establish. - * - * It is verified that the peers normally re-establish - * the BA session after the initial rejection. - */ - if (CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN != uf_sme_port_state(priv, macAddress.a, UF_CONTROLLED_PORT_Q, interfacePriv->InterfaceTag)) - { - unifi_warning(priv, "blockack_session_start: Controlled port not opened, Reject BA request\n"); - return FALSE; - } - - ba_session_rx = kzalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); - if (!ba_session_rx) { - unifi_error(priv, "%s: kmalloc failed for ba_session_rx\n", __FUNCTION__); - return FALSE; - } - - ba_session_rx->wind_size = wind_size; - ba_session_rx->start_sn = ba_session_rx->expected_sn = start_sn; - ba_session_rx->trigger_ba_after_ssn = FALSE; - - ba_session_rx->buffer = kzalloc(ba_session_rx->wind_size*sizeof(frame_desc_struct), GFP_KERNEL); - if (!ba_session_rx->buffer) { - kfree(ba_session_rx); - unifi_error(priv, "%s: kmalloc failed for buffer\n", __FUNCTION__); - return FALSE; - } - - INIT_WORK(&ba_session_rx->send_ba_err_task, uf_send_ba_err_wq); - if (timeout) { - ba_session_rx->timeout = timeout; - ba_session_rx->timer.function = ba_session_terminate_timer_func; - ba_session_rx->timer.data = (unsigned long)ba_session_rx; - init_timer(&ba_session_rx->timer); - mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); - } - - ba_session_rx->interfacePriv = interfacePriv; - ba_session_rx->tID = tID; - ba_session_rx->macAddress = macAddress; - - interfacePriv->ba_session_rx[ba_session_idx] = ba_session_rx; - } - return TRUE; -} - -void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlBlockAckEnableReq* req = (CsrWifiRouterCtrlBlockAckEnableReq*)msg; - u8 r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - down(&priv->ba_mutex); - r = blockack_session_start(priv, - req->interfaceTag, - req->trafficStreamID, - req->timeout, - req->role, - req->bufferSize, - req->ssn, - req->macAddress - ); - up(&priv->ba_mutex); - - CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source, - req->clientData, - req->interfaceTag, - r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); - unifi_trace(priv, UDBG6, "<<%s: r=%d\n", __FUNCTION__, r); - -} - -void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status); - - /* status 1 - Filter on - * status 0 - Filter off */ - priv->wapi_multicast_filter = req->status; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastFilterReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status); - - if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) { - /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */ - priv->wapi_unicast_queued_pkt_filter = 1; - } - - /* status 1 - Filter ON - * status 0 - Filter OFF */ - priv->wapi_unicast_filter = req->status; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastFilterReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiRxPktReq* req = (CsrWifiRouterCtrlWapiRxPktReq*)msg; - int client_id, receiver_id; - bulk_data_param_t bulkdata; - CsrResult res; - ul_client_t *client; - CSR_SIGNAL signal; - CSR_MA_PACKET_INDICATION *pkt_ind; - netInterface_priv_t *interfacePriv; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid priv\n", __func__); - return; - } - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid sme priv\n", __func__); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - - if (req->dataLength == 0 || req->data == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: invalid request\n", __FUNCTION__); - return; - } - - res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); - if (res != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: Could not allocate net data\n", __FUNCTION__); - return; - } - - /* This function is expected to be called only when the MIC has been verified by SME to be correct - * So reset the reception status to rx_success */ - res = read_unpack_signal(req->signal, &signal); - if (res) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: Received unknown or corrupted signal.\n"); - return; - } - pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication); - if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: Unknown signal with reception status = %d\n", pkt_ind->ReceptionStatus); - return; - } else { - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiRxPktReqHandler: MIC verified , RX_SUCCESS \n", __FUNCTION__); - pkt_ind->ReceptionStatus = CSR_RX_SUCCESS; - write_pack(&signal, req->signal, &(req->signalLength)); - } - - memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); - - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(s16)) & 0xFFF0; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; - - client = &priv->ul_clients[client_id]; - - if (client && client->event_hook) { - unifi_trace(priv, UDBG3, - "CsrWifiRouterCtrlWapiRxPktReq: " - "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n", - client->client_id, client->sender_id, receiver_id, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal)); - - client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST); - } else { - unifi_trace(priv, UDBG4, "No client to give the packet to\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - } - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - - unifi_priv_t *priv = (unifi_priv_t*) drvpriv; - CsrWifiRouterCtrlWapiUnicastTxPktReq *req = (CsrWifiRouterCtrlWapiUnicastTxPktReq*) msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - bulk_data_param_t bulkdata; - u8 macHeaderLengthInBytes = MAC_HEADER_SIZE; - /*KeyID, Reserved, PN, MIC*/ - u8 appendedCryptoFields = 1 + 1 + 16 + 16; - CsrResult result; - /* Retrieve the MA PACKET REQ fields from the Signal retained from send_ma_pkt_request() */ - CSR_MA_PACKET_REQUEST *storedSignalMAPktReq = &interfacePriv->wapi_unicast_ma_pkt_sig.u.MaPacketRequest; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid priv\n", __FUNCTION__); - return; - } - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid sme priv\n", __FUNCTION__); - return; - } - if (req->data == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid request\n", __FUNCTION__); - return; - } else { - /* If it is QoS data (type = data subtype = QoS), frame header contains QoS control field */ - if ((req->data[0] & 0x88) == 0x88) { - macHeaderLengthInBytes = macHeaderLengthInBytes + QOS_CONTROL_HEADER_SIZE; - } - } - if ( !(req->dataLength>(macHeaderLengthInBytes+appendedCryptoFields)) ) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid dataLength\n", __FUNCTION__); - return; - } - - /* Encrypted DATA Packet contained in (req->data) - * ------------------------------------------------------------------- - * |MAC Header| KeyId | Reserved | PN | xxDataxx | xxMICxxx | - * ------------------------------------------------------------------- - * (<-----Encrypted----->) - * ------------------------------------------------------------------- - * |24/26(QoS)| 1 | 1 | 16 | x | 16 | - * ------------------------------------------------------------------- - */ - result = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); - if (result != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: Could not allocate net data\n", __FUNCTION__); - return; - } - memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); - bulkdata.d[0].data_length = req->dataLength; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - - /* Send UniFi msg */ - /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */ - result = uf_process_ma_packet_req(priv, - storedSignalMAPktReq->Ra.x, - storedSignalMAPktReq->HostTag,/* Ask for a new HostTag */ - req->interfaceTag, - storedSignalMAPktReq->TransmissionControl, - storedSignalMAPktReq->TransmitRate, - storedSignalMAPktReq->Priority, /* Retained value */ - interfacePriv->wapi_unicast_ma_pkt_sig.SignalPrimitiveHeader.SenderProcessId, /*FIXME AP: VALIDATE ???*/ - &bulkdata); - - if (result == NETDEV_TX_OK) { - (priv->netdev[req->interfaceTag])->trans_start = jiffies; - /* Should really count tx stats in the UNITDATA.status signal but - * that doesn't have the length. - */ - interfacePriv->stats.tx_packets++; - - /* count only the packet payload */ - interfacePriv->stats.tx_bytes += req->dataLength - macHeaderLengthInBytes - appendedCryptoFields; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Sent), sent count = %x\n", interfacePriv->stats.tx_packets); - } else { - /* Failed to send: fh queue was full, and the skb was discarded*/ - unifi_trace(priv, UDBG1, "(HIP validation failure) Result = %d\n", result); - unifi_net_data_free(priv, &bulkdata.d[0]); - - interfacePriv->stats.tx_dropped++; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped); - } - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: called when WAPI SW ENCRYPTION isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiFilterReq* req = (CsrWifiRouterCtrlWapiFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiFilterReq: req->isWapiConnected [0/1] = %d \n", req->isWapiConnected); - - priv->isWapiConnection = req->isWapiConnected; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#endif - -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiFilterReq: called when WAPI isn't enabled\n"); -#endif -} diff --git a/drivers/staging/csr/sme_userspace.c b/drivers/staging/csr/sme_userspace.c deleted file mode 100644 index b919b001ef7c..000000000000 --- a/drivers/staging/csr/sme_userspace.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - ***************************************************************************** - * - * FILE : sme_userspace.c - * - * PURPOSE : Support functions for userspace SME helper application. - * - * - * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - ***************************************************************************** - */ - -#include "unifi_priv.h" - -/* - * Fix Me..... These need to be the correct values... - * Dynamic from the user space. - */ -CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE = 0xFFFF; -CsrSchedQid CSR_WIFI_SME_IFACEQUEUE = 0xFFFF; -#ifdef CSR_SUPPORT_WEXT_AP -CsrSchedQid CSR_WIFI_NME_IFACEQUEUE = 0xFFFF; -#endif -int -uf_sme_init(unifi_priv_t *priv) -{ - int i, j; - - CsrWifiRouterTransportInit(priv); - - priv->smepriv = priv; - - init_waitqueue_head(&priv->sme_request_wq); - - priv->filter_tclas_ies = NULL; - memset(&priv->packet_filters, 0, sizeof(uf_cfg_bcast_packet_filter_t)); - -#ifdef CSR_SUPPORT_WEXT - priv->ignore_bssid_join = FALSE; - priv->mib_data.length = 0; - - uf_sme_wext_set_defaults(priv); -#endif /* CSR_SUPPORT_WEXT*/ - - priv->sta_ip_address = 0xFFFFFFFF; - - priv->wifi_on_state = wifi_on_unspecified; - - sema_init(&priv->sme_sem, 1); - memset(&priv->sme_reply, 0, sizeof(sme_reply_t)); - - priv->ta_ind_work.in_use = 0; - priv->ta_sample_ind_work.in_use = 0; - - priv->CSR_WIFI_SME_IFACEQUEUE = 0xFFFF; - - for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { - priv->sme_unidata_ind_filters[i].in_use = 0; - } - - /* Create a work queue item for Traffic Analysis indications to SME */ - INIT_WORK(&priv->ta_ind_work.task, uf_ta_ind_wq); - INIT_WORK(&priv->ta_sample_ind_work.task, uf_ta_sample_ind_wq); -#ifdef CSR_SUPPORT_WEXT - INIT_WORK(&priv->sme_config_task, uf_sme_config_wq); -#endif - - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - interfacePriv->m4_sent = FALSE; - interfacePriv->m4_bulk_data.net_buf_length = 0; - interfacePriv->m4_bulk_data.data_length = 0; - interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; - - memset(&interfacePriv->controlled_data_port, 0, sizeof(unifi_port_config_t)); - interfacePriv->controlled_data_port.entries_in_use = 1; - interfacePriv->controlled_data_port.port_cfg[0].in_use = TRUE; - interfacePriv->controlled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - interfacePriv->controlled_data_port.overide_action = UF_DATA_PORT_OVERIDE; - - memset(&interfacePriv->uncontrolled_data_port, 0, sizeof(unifi_port_config_t)); - interfacePriv->uncontrolled_data_port.entries_in_use = 1; - interfacePriv->uncontrolled_data_port.port_cfg[0].in_use = TRUE; - interfacePriv->uncontrolled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - interfacePriv->uncontrolled_data_port.overide_action = UF_DATA_PORT_OVERIDE; - - /* Mark the remainder of the port config table as unallocated */ - for(j = 1; j < UNIFI_MAX_CONNECTIONS; j++) { - interfacePriv->controlled_data_port.port_cfg[j].in_use = FALSE; - interfacePriv->controlled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - - interfacePriv->uncontrolled_data_port.port_cfg[j].in_use = FALSE; - interfacePriv->uncontrolled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - } - - /* intializing the lists */ - INIT_LIST_HEAD(&interfacePriv->genericMgtFrames); - INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames); - INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames); - - for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { - interfacePriv->staInfo[j] = NULL; - } - - interfacePriv->num_stations_joined = 0; - interfacePriv->sta_activity_check_enabled = FALSE; - } - - - return 0; -} /* uf_sme_init() */ - - -void -uf_sme_deinit(unifi_priv_t *priv) -{ - int i, j; - u8 ba_session_idx; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; - netInterface_priv_t *interfacePriv = NULL; - - /* Free any TCLASs previously allocated */ - if (priv->packet_filters.tclas_ies_length) { - priv->packet_filters.tclas_ies_length = 0; - kfree(priv->filter_tclas_ies); - priv->filter_tclas_ies = NULL; - } - - for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { - priv->sme_unidata_ind_filters[i].in_use = 0; - } - - /* Remove all the Peer database, before going down */ - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - down(&priv->ba_mutex); - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx]; - if(ba_session_rx) { - blockack_session_stop(priv, - i, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT, - ba_session_rx->tID, - ba_session_rx->macAddress); - } - } - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = priv->interfacePriv[i]->ba_session_tx[ba_session_idx]; - if(ba_session_tx) { - blockack_session_stop(priv, - i, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR, - ba_session_tx->tID, - ba_session_tx->macAddress); - } - } - - up(&priv->ba_mutex); - interfacePriv = priv->interfacePriv[i]; - if(interfacePriv){ - for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) { - if ((staInfo=interfacePriv->staInfo[j]) != NULL) { - /* Clear the STA activity parameters before freeing station Record */ - unifi_trace(priv, UDBG1, "uf_sme_deinit: Canceling work queue for STA with AID: %d\n", staInfo->aid); - cancel_work_sync(&staInfo->send_disconnected_ind_task); - staInfo->nullDataHostTag = INVALID_HOST_TAG; - } - } - if (interfacePriv->sta_activity_check_enabled){ - interfacePriv->sta_activity_check_enabled = FALSE; - del_timer_sync(&interfacePriv->sta_activity_check_timer); - } - } - CsrWifiRouterCtrlInterfaceReset(priv, i); - priv->interfacePriv[i]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_NONE; - } - - -} /* uf_sme_deinit() */ - - - - - -/* - * --------------------------------------------------------------------------- - * unifi_ta_indicate_protocol - * - * Report that a packet of a particular type has been seen - * - * Arguments: - * drv_priv The device context pointer passed to ta_init. - * protocol The protocol type enum value. - * direction Whether the packet was a tx or rx. - * src_addr The source MAC address from the data packet. - * - * Returns: - * None. - * - * Notes: - * We defer the actual sending to a background workqueue, - * see uf_ta_ind_wq(). - * --------------------------------------------------------------------------- - */ -void -unifi_ta_indicate_protocol(void *ospriv, - CsrWifiRouterCtrlTrafficPacketType packet_type, - CsrWifiRouterCtrlProtocolDirection direction, - const CsrWifiMacAddress *src_addr) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - if (priv->ta_ind_work.in_use) { - unifi_warning(priv, - "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n"); - return; - } - - if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX == direction) - { - u16 interfaceTag = 0; - CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, - interfaceTag, - packet_type, - direction, - *src_addr); - } - else - { - priv->ta_ind_work.packet_type = packet_type; - priv->ta_ind_work.direction = direction; - priv->ta_ind_work.src_addr = *src_addr; - - queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task); - } - -} /* unifi_ta_indicate_protocol() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_ta_indicate_sampling - * - * Send the TA sampling information to the SME. - * - * Arguments: - * drv_priv The device context pointer passed to ta_init. - * stats The TA sampling data to send. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - if (!priv) { - return; - } - - if (priv->ta_sample_ind_work.in_use) { - unifi_warning(priv, - "unifi_ta_indicate_sampling: workqueue item still in use, not sending\n"); - return; - } - - priv->ta_sample_ind_work.stats = *stats; - - queue_work(priv->unifi_workqueue, &priv->ta_sample_ind_work.task); - -} /* unifi_ta_indicate_sampling() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_ta_indicate_l4stats - * - * Send the TA TCP/UDP throughput information to the driver. - * - * Arguments: - * drv_priv The device context pointer passed to ta_init. - * rxTcpThroughput TCP RX throughput in KiloBytes - * txTcpThroughput TCP TX throughput in KiloBytes - * rxUdpThroughput UDP RX throughput in KiloBytes - * txUdpThroughput UDP TX throughput in KiloBytes - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -unifi_ta_indicate_l4stats(void *ospriv, - u32 rxTcpThroughput, - u32 txTcpThroughput, - u32 rxUdpThroughput, - u32 txUdpThroughput) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - if (!priv) { - return; - } - /* Save the info. The actual action will be taken in unifi_ta_indicate_sampling() */ - priv->rxTcpThroughput = rxTcpThroughput; - priv->txTcpThroughput = txTcpThroughput; - priv->rxUdpThroughput = rxUdpThroughput; - priv->txUdpThroughput = txUdpThroughput; -} /* unifi_ta_indicate_l4stats() */ diff --git a/drivers/staging/csr/sme_userspace.h b/drivers/staging/csr/sme_userspace.h deleted file mode 100644 index ebe371c732b2..000000000000 --- a/drivers/staging/csr/sme_userspace.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * *************************************************************************** - * FILE: sme_userspace.h - * - * PURPOSE: SME related definitions. - * - * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ -#ifndef __LINUX_SME_USERSPACE_H__ -#define __LINUX_SME_USERSPACE_H__ 1 - -#include - -int uf_sme_init(unifi_priv_t *priv); -void uf_sme_deinit(unifi_priv_t *priv); -int uf_sme_queue_message(unifi_priv_t *priv, u8 *buffer, int length); - - -#include "csr_wifi_router_lib.h" -#include "csr_wifi_router_sef.h" -#include "csr_wifi_router_ctrl_lib.h" -#include "csr_wifi_router_ctrl_sef.h" -#include "csr_wifi_sme_task.h" -#ifdef CSR_SUPPORT_WEXT_AP -#include "csr_wifi_nme_ap_lib.h" -#endif -#include "csr_wifi_sme_lib.h" - -void CsrWifiRouterTransportInit(unifi_priv_t *priv); -void CsrWifiRouterTransportRecv(unifi_priv_t *priv, u8 *buffer, size_t bufferLength); -void CsrWifiRouterTransportDeInit(unifi_priv_t *priv); - -#endif /* __LINUX_SME_USERSPACE_H__ */ diff --git a/drivers/staging/csr/sme_wext.c b/drivers/staging/csr/sme_wext.c deleted file mode 100644 index 84f11cb53596..000000000000 --- a/drivers/staging/csr/sme_wext.c +++ /dev/null @@ -1,3327 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sme_wext.c - * - * PURPOSE: - * Handlers for ioctls from iwconfig. - * These provide the control plane operations. - * - * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include -#include -#include -#include -#include -#include "unifi_priv.h" -#include - -#define CHECK_INITED(_priv) \ - do { \ - if (_priv->init_progress != UNIFI_INIT_COMPLETED) { \ - unifi_trace(_priv, UDBG2, "%s unifi not ready, failing wext call\n", __FUNCTION__); \ - return -ENODEV; \ - } \ - } while (0) - -/* Workaround for the wpa_supplicant hanging issue - disabled on Android */ -#ifndef ANDROID_BUILD -#define CSR_WIFI_WEXT_HANG_WORKAROUND -#endif - -#ifdef CSR_WIFI_WEXT_HANG_WORKAROUND -# define UF_RTNL_LOCK() rtnl_lock() -# define UF_RTNL_UNLOCK() rtnl_unlock() -#else -# define UF_RTNL_LOCK() -# define UF_RTNL_UNLOCK() -#endif - - -/* - * --------------------------------------------------------------------------- - * Helper functions - * --------------------------------------------------------------------------- - */ - -/* - * --------------------------------------------------------------------------- - * wext_freq_to_channel - * channel_to_mhz - * - * These functions convert between channel number and frequency. - * - * Arguments: - * ch Channel number, as defined in 802.11 specs - * m, e Mantissa and exponent as provided by wireless extension. - * - * Returns: - * channel or frequency (in MHz) value - * --------------------------------------------------------------------------- - */ -static int -wext_freq_to_channel(int m, int e) -{ - int mhz; - - mhz = m; - while (e < 6) { - mhz /= 10; - e++; - } - while (e > 6) { - mhz *= 10; - e--; - } - - if (mhz >= 5000) { - return ((mhz - 5000) / 5); - } - - if (mhz == 2482) { - return 14; - } - - if (mhz >= 2407) { - return ((mhz - 2407) / 5); - } - - return 0; -} /* wext_freq_to_channel() */ - -static int -channel_to_mhz(int ch, int dot11a) -{ - - if (ch == 0) return 0; - if (ch > 200) return 0; - - /* 5G */ - if (dot11a) { - return (5000 + (5 * ch)); - } - - /* 2.4G */ - if (ch == 14) { - return 2484; - } - - if ((ch < 14) && (ch > 0)) { - return (2407 + (5 * ch)); - } - - return 0; -} -#ifdef CSR_SUPPORT_WEXT_AP -void uf_sme_wext_ap_set_defaults(unifi_priv_t *priv) -{ - memcpy(priv->ap_config.ssid.ssid, "defaultssid", sizeof("defaultssid")); - - priv->ap_config.ssid.length = 8; - priv->ap_config.channel = 6; - priv->ap_config.if_index = 1; - priv->ap_config.credentials.authType = 0; - priv->ap_config.max_connections=8; - - priv->group_sec_config.apGroupkeyTimeout = 0; - priv->group_sec_config.apStrictGtkRekey = 0; - priv->group_sec_config.apGmkTimeout = 0; - priv->group_sec_config.apResponseTimeout = 100; /* Default*/ - priv->group_sec_config.apRetransLimit = 3; /* Default*/ - /* Set default params even if they may not be used*/ - /* Until Here*/ - - priv->ap_mac_config.preamble = CSR_WIFI_SME_USE_LONG_PREAMBLE; - priv->ap_mac_config.shortSlotTimeEnabled = FALSE; - priv->ap_mac_config.ctsProtectionType=CSR_WIFI_SME_CTS_PROTECTION_AUTOMATIC; - - priv->ap_mac_config.wmmEnabled = TRUE; - priv->ap_mac_config.wmmApParams[0].cwMin=4; - priv->ap_mac_config.wmmApParams[0].cwMax=10; - priv->ap_mac_config.wmmApParams[0].aifs=3; - priv->ap_mac_config.wmmApParams[0].txopLimit=0; - priv->ap_mac_config.wmmApParams[0].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApParams[1].cwMin=4; - priv->ap_mac_config.wmmApParams[1].cwMax=10; - priv->ap_mac_config.wmmApParams[1].aifs=7; - priv->ap_mac_config.wmmApParams[1].txopLimit=0; - priv->ap_mac_config.wmmApParams[1].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApParams[2].cwMin=3; - priv->ap_mac_config.wmmApParams[2].cwMax=4; - priv->ap_mac_config.wmmApParams[2].aifs=1; - priv->ap_mac_config.wmmApParams[2].txopLimit=94; - priv->ap_mac_config.wmmApParams[2].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApParams[3].cwMin=2; - priv->ap_mac_config.wmmApParams[3].cwMax=3; - priv->ap_mac_config.wmmApParams[3].aifs=1; - priv->ap_mac_config.wmmApParams[3].txopLimit=47; - priv->ap_mac_config.wmmApParams[3].admissionControlMandatory=FALSE; - - priv->ap_mac_config.wmmApBcParams[0].cwMin=4; - priv->ap_mac_config.wmmApBcParams[0].cwMax=10; - priv->ap_mac_config.wmmApBcParams[0].aifs=3; - priv->ap_mac_config.wmmApBcParams[0].txopLimit=0; - priv->ap_mac_config.wmmApBcParams[0].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApBcParams[1].cwMin=4; - priv->ap_mac_config.wmmApBcParams[1].cwMax=10; - priv->ap_mac_config.wmmApBcParams[1].aifs=7; - priv->ap_mac_config.wmmApBcParams[1].txopLimit=0; - priv->ap_mac_config.wmmApBcParams[1].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApBcParams[2].cwMin=3; - priv->ap_mac_config.wmmApBcParams[2].cwMax=4; - priv->ap_mac_config.wmmApBcParams[2].aifs=2; - priv->ap_mac_config.wmmApBcParams[2].txopLimit=94; - priv->ap_mac_config.wmmApBcParams[2].admissionControlMandatory=FALSE; - priv->ap_mac_config.wmmApBcParams[3].cwMin=2; - priv->ap_mac_config.wmmApBcParams[3].cwMax=3; - priv->ap_mac_config.wmmApBcParams[3].aifs=2; - priv->ap_mac_config.wmmApBcParams[3].txopLimit=47; - priv->ap_mac_config.wmmApBcParams[3].admissionControlMandatory=FALSE; - - priv->ap_mac_config.accessType=CSR_WIFI_AP_ACCESS_TYPE_NONE; - priv->ap_mac_config.macAddressListCount=0; - priv->ap_mac_config.macAddressList=NULL; - - priv->ap_mac_config.apHtParams.rxStbc=1; - priv->ap_mac_config.apHtParams.rifsModeAllowed=TRUE; - priv->ap_mac_config.apHtParams.greenfieldSupported=FALSE; - priv->ap_mac_config.apHtParams.shortGi20MHz=TRUE; - priv->ap_mac_config.apHtParams.htProtection=0; - priv->ap_mac_config.apHtParams.dualCtsProtection=FALSE; - - priv->ap_mac_config.phySupportedBitmap = - (CSR_WIFI_SME_AP_PHY_SUPPORT_B|CSR_WIFI_SME_AP_PHY_SUPPORT_G|CSR_WIFI_SME_AP_PHY_SUPPORT_N); - priv->ap_mac_config.beaconInterval= 100; - priv->ap_mac_config.dtimPeriod=3; - priv->ap_mac_config.maxListenInterval=0x00ff;/* Set it to a large value - to enable different types of - devices to join us */ - priv->ap_mac_config.supportedRatesCount = - uf_configure_supported_rates(priv->ap_mac_config.supportedRates, priv->ap_mac_config.phySupportedBitmap); -} -#endif -/* - * --------------------------------------------------------------------------- - * uf_sme_wext_set_defaults - * - * Set up power-on defaults for driver config. - * - * Note: The SME Management API *cannot* be used in this function. - * - * Arguments: - * priv Pointer to device private context struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -uf_sme_wext_set_defaults(unifi_priv_t *priv) -{ - memset(&priv->connection_config, 0, sizeof(CsrWifiSmeConnectionConfig)); - - priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE; - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; - priv->connection_config.privacyMode = CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; - priv->connection_config.wmmQosInfo = 0xFF; - priv->connection_config.ifIndex = CSR_WIFI_SME_RADIO_IF_BOTH; - priv->connection_config.adhocJoinOnly = FALSE; - priv->connection_config.adhocChannel = 6; - - priv->wep_tx_key_index = 0; - - priv->wext_wireless_stats.qual.qual = 0; - priv->wext_wireless_stats.qual.level = 0; - priv->wext_wireless_stats.qual.noise = 0; - priv->wext_wireless_stats.qual.updated = 0x70; -#ifdef CSR_SUPPORT_WEXT_AP - /* Initialize the default configuration for AP */ - uf_sme_wext_ap_set_defaults(priv); -#endif - - -} /* uf_sme_wext_set_defaults() */ - - -/* - * --------------------------------------------------------------------------- - * WEXT methods - * --------------------------------------------------------------------------- - */ - -/* - * --------------------------------------------------------------------------- - * unifi_giwname - handler for SIOCGIWNAME - * unifi_siwfreq - handler for SIOCSIWFREQ - * unifi_giwfreq - handler for SIOCGIWFREQ - * unifi_siwmode - handler for SIOCSIWMODE - * unifi_giwmode - handler for SIOCGIWMODE - * unifi_giwrange - handler for SIOCGIWRANGE - * unifi_siwap - handler for SIOCSIWAP - * unifi_giwap - handler for SIOCGIWAP - * unifi_siwscan - handler for SIOCSIWSCAN - * unifi_giwscan - handler for SIOCGIWSCAN - * unifi_siwessid - handler for SIOCSIWESSID - * unifi_giwessid - handler for SIOCGIWESSID - * unifi_siwencode - handler for SIOCSIWENCODE - * unifi_giwencode - handler for SIOCGIWENCODE - * - * Handler functions for IW extensions. - * These are registered via the unifi_iw_handler_def struct below - * and called by the generic IW driver support code. - * See include/net/iw_handler.h. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static int -iwprivsdefs(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int r; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - CsrWifiSmeMibConfig mibConfig; - CsrWifiSmePowerConfig powerConfig; - - unifi_trace(priv, UDBG1, "iwprivs80211defaults: reload defaults\n"); - - uf_sme_wext_set_defaults(priv); - - /* Get, modify and set the MIB data */ - r = sme_mgt_mib_config_get(priv, &mibConfig); - if (r) { - unifi_error(priv, "iwprivs80211defaults: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - mibConfig.dot11RtsThreshold = 2347; - mibConfig.dot11FragmentationThreshold = 2346; - r = sme_mgt_mib_config_set(priv, &mibConfig); - if (r) { - unifi_error(priv, "iwprivs80211defaults: Set CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; - powerConfig.listenIntervalTu = 100; - powerConfig.rxDtims = 1; - - r = sme_mgt_power_config_set(priv, &powerConfig); - if (r) { - unifi_error(priv, "iwprivs80211defaults: Set unifi_PowerConfigValue failed.\n"); - return r; - } - - return 0; -} /* iwprivsdefs() */ - -static int -iwprivs80211ps(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int r = 0; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - int ps_mode = (int)(*extra); - CsrWifiSmePowerConfig powerConfig; - - unifi_trace(priv, UDBG1, "iwprivs80211ps: power save mode = %d\n", ps_mode); - - r = sme_mgt_power_config_get(priv, &powerConfig); - if (r) { - unifi_error(priv, "iwprivs80211ps: Get unifi_PowerConfigValue failed.\n"); - return r; - } - - switch (ps_mode) { - case CSR_PMM_ACTIVE_MODE: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; - break; - case CSR_PMM_POWER_SAVE: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; - break; - case CSR_PMM_FAST_POWER_SAVE: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED; - break; - default: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO; - break; - } - - r = sme_mgt_power_config_set(priv, &powerConfig); - if (r) { - unifi_error(priv, "iwprivs80211ps: Set unifi_PowerConfigValue failed.\n"); - } - - return r; -} - -static int -iwprivg80211ps(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - CsrWifiSmePowerConfig powerConfig; - int r; - - r = sme_mgt_power_config_get(priv, &powerConfig); - if (r) { - unifi_error(priv, "iwprivg80211ps: Get 802.11 power mode failed.\n"); - return r; - } - - switch (powerConfig.powerSaveLevel) { - case CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW: - snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, - "Power save mode: %d (Active)", - powerConfig.powerSaveLevel); - break; - case CSR_WIFI_SME_POWER_SAVE_LEVEL_MED: - snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, - "Power save mode: %d (Fast)", - powerConfig.powerSaveLevel); - break; - case CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH: - snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, - "Power save mode: %d (Full)", - powerConfig.powerSaveLevel); - break; - case CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO: - snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, - "Power save mode: %d (Auto)", - powerConfig.powerSaveLevel); - break; - default: - snprintf(extra, IWPRIV_POWER_SAVE_MAX_STRING, - "Power save mode: %d (Unknown)", - powerConfig.powerSaveLevel); - break; - } - - wrqu->data.length = strlen(extra) + 1; - - return 0; -} - -static int -iwprivssmedebug(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* No longer supported on the API */ -#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) - unifi_debug_buf_dump(); -#endif - - return 0; -} - -#ifdef CSR_SUPPORT_WEXT_AP -#define PARAM_TYPE_INT 0 -#define PARAM_TYPE_STRING 1 -#define CSR_WIFI_MAX_SSID_LEN 32 -#define CSR_WIFI_MAX_SEC_LEN 16 -#define CSR_WIFI_MAX_KEY_LEN 65 - -static int hex_look_up(char x) -{ - if(x>='0' && x<='9') - return (x-48); - if(x>= 'a' && x <= 'f') - return (x-87); - return -1; -} - -static int power (int a, int b) -{ - int i; - int num =1; - for(i=0;i param_max_len) { - unifi_notice(priv, "extracted param len:%d is > MAX:%d\n", param_str_len, param_max_len); - param_str_len = param_max_len; - } - switch (param_type) { - case PARAM_TYPE_INT: - { - u32 *pdst_int = dst, num =0; - int i, j=0; - if (param_str_len > sizeof(int_str)) { - param_str_len = sizeof(int_str); - } - memcpy(int_str, param_str_begin, param_str_len); - for(i = param_str_len; i>0;i--) { - if(int_str[i-1] >= '0' && int_str[i-1] <='9') { - num += ((int_str[i-1]-'0')*power(10, j)); - j++; - } else { - unifi_error(priv, "decode_parameter_from_string:not a number %c\n", (int_str[i-1])); - return -1; - } - } - *pdst_int = num; - unifi_trace(priv, UDBG2, "decode_parameter_from_string:decoded int = %d\n", *pdst_int); - } - break; - default: - memcpy(dst, param_str_begin, param_str_len); - *((char *)dst + param_str_len) = 0; - unifi_trace(priv, UDBG2, "decode_parameter_from_string:decoded string = %s\n", (char *)dst); - break; - } - } else { - unifi_error(priv, "decode_parameter_from_string: Token:%s not found in %s \n", token, orig_str); - return -1; - } - return 0; -} -static int store_ap_advanced_config_from_string(unifi_priv_t *priv, char *param_str) -{ - char * str_ptr=param_str; - int ret = 0, tmp_var; - char phy_mode[6]; - CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config; - - /* Check for BI */ - ret = decode_parameter_from_string(priv, &str_ptr, "BI=", - PARAM_TYPE_INT, &tmp_var, 5); - if(ret) { - unifi_error(priv, "store_ap_advanced_config_from_string: BI not found\n"); - return -1; - } - ap_mac_config->beaconInterval = tmp_var; - ret = decode_parameter_from_string(priv, &str_ptr, "DTIM_PER=", - PARAM_TYPE_INT, &tmp_var, 5); - if(ret) { - unifi_error(priv, "store_ap_advanced_config_from_string: DTIM_PER not found\n"); - return -1; - } - ap_mac_config->dtimPeriod = tmp_var; - ret = decode_parameter_from_string(priv, &str_ptr, "WMM=", - PARAM_TYPE_INT, &tmp_var, 5); - if(ret) { - unifi_error(priv, "store_ap_advanced_config_from_string: WMM not found\n"); - return -1; - } - ap_mac_config->wmmEnabled = tmp_var; - ret = decode_parameter_from_string(priv, &str_ptr, "PHY=", - PARAM_TYPE_STRING, phy_mode, 5); - if(ret) { - unifi_error(priv, "store_ap_advanced_config_from_string: PHY not found\n"); - } else { - if(strstr(phy_mode, "b")){ - ap_mac_config->phySupportedBitmap = CSR_WIFI_SME_AP_PHY_SUPPORT_B; - } - if(strstr(phy_mode, "g")) { - ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_G; - } - if(strstr(phy_mode, "n")) { - ap_mac_config->phySupportedBitmap |= CSR_WIFI_SME_AP_PHY_SUPPORT_N; - } - ap_mac_config->supportedRatesCount = - uf_configure_supported_rates(ap_mac_config->supportedRates, ap_mac_config->phySupportedBitmap); - } - return ret; -} - -static int store_ap_config_from_string( unifi_priv_t * priv, char *param_str) - -{ - char *str_ptr = param_str; - char sub_cmd[16]; - char sec[CSR_WIFI_MAX_SEC_LEN]; - char key[CSR_WIFI_MAX_KEY_LEN]; - int ret = 0, tmp_var; - CsrWifiSmeApConfig_t *ap_config = &priv->ap_config; - CsrWifiSmeApMacConfig * ap_mac_config = &priv->ap_mac_config; - memset(sub_cmd, 0, sizeof(sub_cmd)); - if(!strstr(param_str, "END")) { - unifi_error(priv, "store_ap_config_from_string:Invalid config string:%s\n", param_str); - return -1; - } - if (decode_parameter_from_string(priv, &str_ptr, "ASCII_CMD=", - PARAM_TYPE_STRING, sub_cmd, 6) != 0) { - return -1; - } - if (strncmp(sub_cmd, "AP_CFG", 6)) { - - if(!strncmp(sub_cmd , "ADVCFG", 6)) { - return store_ap_advanced_config_from_string(priv, str_ptr); - } - unifi_error(priv, "store_ap_config_from_string: sub_cmd:%s != 'AP_CFG or ADVCFG'!\n", sub_cmd); - return -1; - } - memset(ap_config, 0, sizeof(CsrWifiSmeApConfig_t)); - ret = decode_parameter_from_string(priv, &str_ptr, "SSID=", - PARAM_TYPE_STRING, ap_config->ssid.ssid, - CSR_WIFI_MAX_SSID_LEN); - if(ret) { - unifi_error(priv, "store_ap_config_from_string: SSID not found\n"); - return -1; - } - ap_config->ssid.length = strlen(ap_config->ssid.ssid); - - ret = decode_parameter_from_string(priv, &str_ptr, "SEC=", - PARAM_TYPE_STRING, sec, CSR_WIFI_MAX_SEC_LEN); - if(ret) { - unifi_error(priv, "store_ap_config_from_string: SEC not found\n"); - return -1; - } - ret = decode_parameter_from_string(priv, &str_ptr, "KEY=", - PARAM_TYPE_STRING, key, CSR_WIFI_MAX_KEY_LEN); - if(!strcasecmp(sec, "open")) { - unifi_trace(priv, UDBG2, "store_ap_config_from_string: security open"); - ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM; - if(ret) { - unifi_notice(priv, "store_ap_config_from_string: KEY not found:fine with Open\n"); - } - } - else if(!strcasecmp(sec, "wpa2-psk")) { - int i, j=0; - CsrWifiNmeApAuthPers *pers = - ((CsrWifiNmeApAuthPers *)&(ap_config->credentials.nmeAuthType.authTypePersonal)); - u8 *psk = pers->authPers_credentials.psk.psk; - - unifi_trace(priv, UDBG2, "store_ap_config_from_string: security WPA2"); - if(ret) { - unifi_error(priv, "store_ap_config_from_string: KEY not found for WPA2\n"); - return -1; - } - ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL; - pers->authSupport = CSR_WIFI_SME_RSN_AUTH_WPA2PSK; - pers->rsnCapabilities =0; - pers->wapiCapabilities =0; - pers->pskOrPassphrase=CSR_WIFI_NME_AP_CREDENTIAL_TYPE_PSK; - pers->authPers_credentials.psk.encryptionMode = - (CSR_WIFI_NME_ENCRYPTION_CIPHER_PAIRWISE_CCMP |CSR_WIFI_NME_ENCRYPTION_CIPHER_GROUP_CCMP) ; - for(i=0;i<32;i++){ - psk[i] = (16*hex_look_up(key[j]))+hex_look_up(key[j+1]); - j+=2; - } - - } else { - unifi_notice(priv, "store_ap_config_from_string: Unknown security: Assuming Open"); - ap_config->credentials.authType = CSR_WIFI_SME_AP_AUTH_TYPE_OPEN_SYSTEM; - return -1; - } - /* Get the decoded value in a temp int variable to ensure that other fields within the struct - which are of type other than int are not over written */ - ret = decode_parameter_from_string(priv, &str_ptr, "CHANNEL=", PARAM_TYPE_INT, &tmp_var, 5); - if(ret) - return -1; - ap_config->channel = tmp_var; - ret = decode_parameter_from_string(priv, &str_ptr, "PREAMBLE=", PARAM_TYPE_INT, &tmp_var, 5); - if(ret) - return -1; - ap_mac_config->preamble = tmp_var; - ret = decode_parameter_from_string(priv, &str_ptr, "MAX_SCB=", PARAM_TYPE_INT, &tmp_var, 5); - ap_config->max_connections = tmp_var; - return ret; -} - -static int -iwprivsapstart(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r; - - unifi_trace(priv, UDBG1, "iwprivsapstart\n" ); - r = sme_ap_start(priv, interfacePriv->InterfaceTag, &priv->ap_config); - if(r) { - unifi_error(priv, "iwprivsapstart AP START failed : %d\n", -r); - } - return r; -} - -static int -iwprivsapconfig(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - char *cfg_str = NULL; - int r; - - unifi_trace(priv, UDBG1, "iwprivsapconfig\n" ); - if (wrqu->data.length != 0) { - char *str; - if (!(cfg_str = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - { - return -ENOMEM; - } - if (copy_from_user(cfg_str, wrqu->data.pointer, wrqu->data.length)) { - kfree(cfg_str); - return -EFAULT; - } - cfg_str[wrqu->data.length] = 0; - unifi_trace(priv, UDBG2, "length:%d\n", wrqu->data.length); - unifi_trace(priv, UDBG2, "AP configuration string:%s\n", cfg_str); - str = cfg_str; - if ((r = store_ap_config_from_string(priv, str))) { - unifi_error(priv, "iwprivsapconfig:Failed to decode the string %d\n", r); - kfree(cfg_str); - return -EIO; - - } - } else { - unifi_error(priv, "iwprivsapconfig argument length = 0 \n"); - return -EIO; - } - r = sme_ap_config(priv, &priv->ap_mac_config, &priv->group_sec_config); - if(r) { - unifi_error(priv, "iwprivsapstop AP Config failed : %d\n", -r); - } else if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_trace(priv, UDBG1, "iwprivsapconfig: Starting the AP"); - r = sme_ap_start(priv, interfacePriv->InterfaceTag, &priv->ap_config); - if(r) { - unifi_error(priv, "iwprivsapstart AP START failed : %d\n", -r); - } - } - kfree(cfg_str); - return r; -} - -static int -iwprivsapstop(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r; - u16 interface_tag = interfacePriv->InterfaceTag; - - unifi_trace(priv, UDBG1, "iwprivsapstop\n" ); - r = sme_ap_stop(priv, interface_tag); - if(r) { - unifi_error(priv, "iwprivsapstop AP STOP failed : %d\n", -r); - } - return r; -} - -#ifdef ANDROID_BUILD -static int -iwprivsapfwreload(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - unifi_trace(priv, UDBG1, "iwprivsapfwreload\n" ); - return 0; -} - -static int -iwprivsstackstart(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - unifi_trace(priv, UDBG1, "iwprivsstackstart\n" ); - return 0; -} - -static int -iwprivsstackstop(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r = 0; - u16 interface_tag = interfacePriv->InterfaceTag; - - unifi_trace(priv, UDBG1, "iwprivsstackstop\n" ); - - switch(interfacePriv->interfaceMode) { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - r = sme_mgt_disconnect(priv); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - r = sme_ap_stop(priv, interface_tag); - break; - default : - break; - } - - if(r) { - unifi_error(priv, "iwprivsstackstop Stack stop failed : %d\n", -r); - } - return 0; -} -#endif /* ANDROID_BUILD */ -#endif /* CSR_SUPPORT_WEXT_AP */ - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE -static int -iwprivsconfwapi(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u8 enable; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - unifi_trace(priv, UDBG1, "iwprivsconfwapi\n" ); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "iwprivsconfwapi: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - enable = *(u8*)(extra); - - if (enable) { - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI); - priv->connection_config.encryptionModeMask |= - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4; - } else { - priv->connection_config.authModeMask &= ~(CSR_WIFI_SME_AUTH_MODE_WAPI_WAIPSK | CSR_WIFI_SME_AUTH_MODE_WAPI_WAI); - priv->connection_config.encryptionModeMask &= - ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_SMS4 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_SMS4); - } - - return 0; -} - -static int -iwprivswpikey(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int r = 0, i; - CsrWifiSmeKey key; - unifiio_wapi_key_t inKey; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - unifi_trace(priv, UDBG1, "iwprivswpikey\n" ); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - inKey = *(unifiio_wapi_key_t*)(extra); - - if (inKey.unicastKey) { - key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; - } else { - key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; - } - - key.keyIndex = inKey.keyIndex; - - /* memcpy(key.keyRsc, inKey.keyRsc, 16); */ - for (i = 0; i < 16; i+= 2) - { - key.keyRsc[i/2] = inKey.keyRsc[i+1] << 8 | inKey.keyRsc[i]; - } - - memcpy(key.address.a, inKey.address, 6); - key.keyLength = 32; - memcpy(key.key, inKey.key, 32); - key.authenticator = 0; - key.wepTxKey = 0; - - unifi_trace(priv, UDBG1, "keyType = %d, keyIndex = %d, wepTxKey = %d, keyRsc = %x:%x, auth = %d, address = %x:%x, " - "keylength = %d, key = %x:%x\n", key.keyType, key.keyIndex, key.wepTxKey, - key.keyRsc[0], key.keyRsc[7], key.authenticator, - key.address.a[0], key.address.a[5], key.keyLength, key.key[0], - key.key[15]); - - r = sme_mgt_key(priv, &key, CSR_WIFI_SME_LIST_ACTION_ADD); - if (r) { - unifi_error(priv, "SETKEYS request was rejected with result %d\n", r); - return convert_sme_error(r); - } - - return r; -} -#endif - - -static int -unifi_giwname(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - char *name = wrqu->name; - unifi_trace(priv, UDBG2, "unifi_giwname\n"); - - if (priv->if_index == CSR_INDEX_5G) { - strcpy(name, "IEEE 802.11-a"); - } else { - strcpy(name, "IEEE 802.11-bgn"); - } - return 0; -} /* unifi_giwname() */ - - -static int -unifi_siwfreq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_freq *freq = (struct iw_freq *)wrqu; - - unifi_trace(priv, UDBG2, "unifi_siwfreq\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwfreq: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - /* - * Channel is stored in the connection configuration, - * and set later when ask for a connection. - */ - if ((freq->e == 0) && (freq->m <= 1000)) { - priv->connection_config.adhocChannel = freq->m; - } else { - priv->connection_config.adhocChannel = wext_freq_to_channel(freq->m, freq->e); - } - - return 0; -} /* unifi_siwfreq() */ - - -static int -unifi_giwfreq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_freq *freq = (struct iw_freq *)wrqu; - int err = 0; - CsrWifiSmeConnectionInfo connectionInfo; - - unifi_trace(priv, UDBG2, "unifi_giwfreq\n"); - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwfreq: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - UF_RTNL_UNLOCK(); - err = sme_mgt_connection_info_get(priv, &connectionInfo); - UF_RTNL_LOCK(); - - freq->m = channel_to_mhz(connectionInfo.channelNumber, - (connectionInfo.networkType80211 == CSR_WIFI_SME_RADIO_IF_GHZ_5_0)); - freq->e = 6; - - return convert_sme_error(err); -} /* unifi_giwfreq() */ - - -static int -unifi_siwmode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - unifi_trace(priv, UDBG2, "unifi_siwmode\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwmode: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - switch(wrqu->mode) { - case IW_MODE_ADHOC: - priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ADHOC; - break; - case IW_MODE_INFRA: - priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE; - break; - case IW_MODE_AUTO: - priv->connection_config.bssType = CSR_WIFI_SME_BSS_TYPE_ANY_BSS; - break; - default: - unifi_notice(priv, "Unknown IW MODE value.\n"); - } - - /* Clear the SSID and BSSID configuration */ - priv->connection_config.ssid.length = 0; - memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN); - - return 0; -} /* unifi_siwmode() */ - - - -static int -unifi_giwmode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int r = 0; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - CsrWifiSmeConnectionConfig connectionConfig; - - unifi_trace(priv, UDBG2, "unifi_giwmode\n"); - CHECK_INITED(priv); - - unifi_trace(priv, UDBG2, "unifi_giwmode: Exisitng mode = 0x%x\n", - interfacePriv->interfaceMode); - switch(interfacePriv->interfaceMode) { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - wrqu->mode = IW_MODE_INFRA; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - wrqu->mode = IW_MODE_MASTER; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - wrqu->mode = IW_MODE_ADHOC; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_P2P: - case CSR_WIFI_ROUTER_CTRL_MODE_NONE: - UF_RTNL_UNLOCK(); - r = sme_mgt_connection_config_get(priv, &connectionConfig); - UF_RTNL_LOCK(); - if (r == 0) { - switch(connectionConfig.bssType) { - case CSR_WIFI_SME_BSS_TYPE_ADHOC: - wrqu->mode = IW_MODE_ADHOC; - break; - case CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE: - wrqu->mode = IW_MODE_INFRA; - break; - default: - wrqu->mode = IW_MODE_AUTO; - unifi_notice(priv, "Unknown IW MODE value.\n"); - } - } - break; - default: - wrqu->mode = IW_MODE_AUTO; - unifi_notice(priv, "Unknown IW MODE value.\n"); - - } - unifi_trace(priv, UDBG4, "unifi_giwmode: mode = 0x%x\n", wrqu->mode); - return r; -} /* unifi_giwmode() */ - - - -static int -unifi_giwrange(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_point *dwrq = &wrqu->data; - struct iw_range *range = (struct iw_range *) extra; - int i; - - unifi_trace(NULL, UDBG2, "unifi_giwrange\n"); - - dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(*range)); - range->min_nwid = 0x0000; - range->max_nwid = 0x0000; - - /* - * Don't report the frequency/channel table, then the channel - * number returned elsewhere will be printed as a channel number. - */ - - /* Ranges of values reported in quality structs */ - range->max_qual.qual = 40; /* Max expected qual value */ - range->max_qual.level = -120; /* Noise floor in dBm */ - range->max_qual.noise = -120; /* Noise floor in dBm */ - - - /* space for IW_MAX_BITRATES (8 up to WE15, 32 later) */ - i = 0; -#if WIRELESS_EXT > 15 - range->bitrate[i++] = 2 * 500000; - range->bitrate[i++] = 4 * 500000; - range->bitrate[i++] = 11 * 500000; - range->bitrate[i++] = 22 * 500000; - range->bitrate[i++] = 12 * 500000; - range->bitrate[i++] = 18 * 500000; - range->bitrate[i++] = 24 * 500000; - range->bitrate[i++] = 36 * 500000; - range->bitrate[i++] = 48 * 500000; - range->bitrate[i++] = 72 * 500000; - range->bitrate[i++] = 96 * 500000; - range->bitrate[i++] = 108 * 500000; -#else - range->bitrate[i++] = 2 * 500000; - range->bitrate[i++] = 4 * 500000; - range->bitrate[i++] = 11 * 500000; - range->bitrate[i++] = 22 * 500000; - range->bitrate[i++] = 24 * 500000; - range->bitrate[i++] = 48 * 500000; - range->bitrate[i++] = 96 * 500000; - range->bitrate[i++] = 108 * 500000; -#endif /* WIRELESS_EXT < 16 */ - range->num_bitrates = i; - - range->max_encoding_tokens = NUM_WEPKEYS; - range->num_encoding_sizes = 2; - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - - range->we_version_source = 20; - range->we_version_compiled = WIRELESS_EXT; - - /* Number of channels available in h/w */ - range->num_channels = 14; - /* Number of entries in freq[] array */ - range->num_frequency = 14; - for (i = 0; (i < range->num_frequency) && (i < IW_MAX_FREQUENCIES); i++) { - int chan = i + 1; - range->freq[i].i = chan; - range->freq[i].m = channel_to_mhz(chan, 0); - range->freq[i].e = 6; - } - if ((i+3) < IW_MAX_FREQUENCIES) { - range->freq[i].i = 36; - range->freq[i].m = channel_to_mhz(36, 1); - range->freq[i].e = 6; - range->freq[i+1].i = 40; - range->freq[i+1].m = channel_to_mhz(40, 1); - range->freq[i+1].e = 6; - range->freq[i+2].i = 44; - range->freq[i+2].m = channel_to_mhz(44, 1); - range->freq[i+2].e = 6; - range->freq[i+3].i = 48; - range->freq[i+3].m = channel_to_mhz(48, 1); - range->freq[i+3].e = 6; - } - -#if WIRELESS_EXT > 16 - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | - IW_EVENT_CAPA_MASK(IWEVCUSTOM) | - IW_EVENT_CAPA_MASK(IWEVREGISTERED) | - IW_EVENT_CAPA_MASK(IWEVEXPIRED)); -#endif /* WIRELESS_EXT > 16 */ - -#if WIRELESS_EXT > 17 - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; -#endif /* WIRELESS_EXT > 17 */ - - - return 0; -} /* unifi_giwrange() */ - - -static int -unifi_siwap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int err = 0; - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwap: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) { - return -EINVAL; - } - - unifi_trace(priv, UDBG1, "unifi_siwap: asked for %pM\n", - wrqu->ap_addr.sa_data); - - if (is_zero_ether_addr(wrqu->ap_addr.sa_data)) { - priv->ignore_bssid_join = FALSE; - err = sme_mgt_disconnect(priv); - if (err) { - unifi_trace(priv, UDBG4, "unifi_siwap: Disconnect failed, status %d\n", err); - } - return 0; - } - - if (priv->ignore_bssid_join) { - unifi_trace(priv, UDBG4, "unifi_siwap: ignoring second join\n"); - priv->ignore_bssid_join = FALSE; - } else { - memcpy(priv->connection_config.bssid.a, wrqu->ap_addr.sa_data, ETH_ALEN); - unifi_trace(priv, UDBG1, "unifi_siwap: Joining %X:%X:%X:%X:%X:%X\n", - priv->connection_config.bssid.a[0], - priv->connection_config.bssid.a[1], - priv->connection_config.bssid.a[2], - priv->connection_config.bssid.a[3], - priv->connection_config.bssid.a[4], - priv->connection_config.bssid.a[5]); - err = sme_mgt_connect(priv); - if (err) { - unifi_error(priv, "unifi_siwap: Join failed, status %d\n", err); - return convert_sme_error(err); - } - } - - return 0; -} /* unifi_siwap() */ - - -static int -unifi_giwap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - CsrWifiSmeConnectionInfo connectionInfo; - int r = 0; - u8 *bssid; - - CHECK_INITED(priv); - unifi_trace(priv, UDBG2, "unifi_giwap\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "iwprivswpikey: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - UF_RTNL_UNLOCK(); - r = sme_mgt_connection_info_get(priv, &connectionInfo); - UF_RTNL_LOCK(); - - if (r == 0) { - bssid = connectionInfo.bssid.a; - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - unifi_trace(priv, UDBG4, "unifi_giwap: BSSID = %pM\n", bssid); - - memcpy(wrqu->ap_addr.sa_data, bssid, ETH_ALEN); - } else { - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - } - - return 0; -} /* unifi_giwap() */ - - -static int -unifi_siwscan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r; - CsrWifiSsid scan_ssid; - unsigned char *channel_list = NULL; - int chans_good = 0; -#if WIRELESS_EXT > 17 - struct iw_point *data = &wrqu->data; - struct iw_scan_req *req = (struct iw_scan_req *) extra; -#endif - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwscan: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - -#if WIRELESS_EXT > 17 - /* Providing a valid channel list will force an active scan */ - if (req) { - if ((req->num_channels > 0) && (req->num_channels < IW_MAX_FREQUENCIES)) { - channel_list = kmalloc(req->num_channels, GFP_KERNEL); - if (channel_list) { - int i; - for (i = 0; i < req->num_channels; i++) { - /* Convert frequency to channel number */ - int ch = wext_freq_to_channel(req->channel_list[i].m, - req->channel_list[i].e); - if (ch) { - channel_list[chans_good++] = ch; - } - } - unifi_trace(priv, UDBG1, - "SIWSCAN: Scanning %d channels\n", chans_good); - } else { - /* Fall back to scanning all */ - unifi_error(priv, "SIWSCAN: Can't alloc channel_list (%d)\n", - req->num_channels); - } - } - } - - if (req && (data->flags & IW_SCAN_THIS_ESSID)) { - memcpy(scan_ssid.ssid, req->essid, req->essid_len); - scan_ssid.length = req->essid_len; - unifi_trace(priv, UDBG1, - "SIWSCAN: Scanning for %.*s\n", - scan_ssid.length, scan_ssid.ssid); - } else -#endif - { - unifi_trace(priv, UDBG1, "SIWSCAN: Scanning for all APs\n"); - scan_ssid.length = 0; - } - - r = sme_mgt_scan_full(priv, &scan_ssid, chans_good, channel_list); - if (r) { - unifi_error(priv, "SIWSCAN: Scan returned error %d\n", r); - } else { - unifi_trace(priv, UDBG1, "SIWSCAN: Scan done\n"); - wext_send_scan_results_event(priv); - } - - if (channel_list) { - kfree(channel_list); - } - - return r; - -} /* unifi_siwscan() */ - - -static const unsigned char * -unifi_find_info_element(int id, const unsigned char *info, int len) -{ - const unsigned char *ie = info; - - while (len > 1) - { - int e_id, e_len; - e_id = ie[0]; - e_len = ie[1]; - - /* Return if we find a match */ - if (e_id == id) - { - return ie; - } - - len -= (e_len + 2); - ie += (e_len + 2); - } - - return NULL; -} /* unifi_find_info_element() */ - - -/* - * Translate scan data returned from the card to a card independent - * format that the Wireless Tools will understand - Jean II - */ -int -unifi_translate_scan(struct net_device *dev, - struct iw_request_info *info, - char *current_ev, char *end_buf, - CsrWifiSmeScanResult *scan_data, - int scan_index) -{ - struct iw_event iwe; /* Temporary buffer */ - unsigned char *info_elems; - int info_elem_len; - const unsigned char *elem; - u16 capabilities; - int signal, noise, snr; - char *start_buf = current_ev; - char *current_val; /* For rates */ - int i, r; - - info_elems = scan_data->informationElements; - info_elem_len = scan_data->informationElementsLength; - - if (!scan_data->informationElementsLength || !scan_data->informationElements) { - unifi_error(NULL, "*** NULL SCAN IEs ***\n"); - return -EIO; - } - - /* get capinfo bits */ - capabilities = scan_data->capabilityInformation; - - unifi_trace(NULL, UDBG5, "Capabilities: 0x%x\n", capabilities); - - /* First entry *MUST* be the AP MAC address */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, scan_data->bssid.a, ETH_ALEN); - iwe.len = IW_EV_ADDR_LEN; - r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_ADDR_LEN); - if (r < 0) { - return r; - } - start_buf += r; - - /* Other entries will be displayed in the order we give them */ - - /* Add the ESSID */ - /* find SSID in Info Elems */ - elem = unifi_find_info_element(IE_SSID_ID, info_elems, info_elem_len); - if (elem) { - int e_len = elem[1]; - const unsigned char *e_ptr = elem + 2; - unsigned char buf[33]; - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.essid.length = e_len; - if (iwe.u.essid.length > 32) { - iwe.u.essid.length = 32; - } - iwe.u.essid.flags = scan_index; - memcpy(buf, e_ptr, iwe.u.essid.length); - buf[iwe.u.essid.length] = '\0'; - r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, buf); - if (r < 0) { - return r; - } - start_buf += r; - - } - - /* Add mode */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (scan_data->bssType == CSR_WIFI_SME_BSS_TYPE_INFRASTRUCTURE) { - iwe.u.mode = IW_MODE_INFRA; - } else { - iwe.u.mode = IW_MODE_ADHOC; - } - iwe.len = IW_EV_UINT_LEN; - r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_UINT_LEN); - if (r < 0) { - return r; - } - start_buf += r; - - /* Add frequency. iwlist will convert to channel using table given in giwrange */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = scan_data->channelFrequency; - iwe.u.freq.e = 6; - r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_FREQ_LEN); - if (r < 0) { - return r; - } - start_buf += r; - - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - /* - * level and noise below are mapped into an unsigned 8 bit number, - * ranging from [-192; 63]. The way this is achieved is simply to - * add 0x100 onto the number if it is negative, - * once clipped to the correct range. - */ - signal = scan_data->rssi; /* This value is in dBm */ - /* Clip range of snr */ - snr = (scan_data->snr > 0) ? scan_data->snr : 0; /* In dB relative, from 0 - 255 */ - snr = (snr < 255) ? snr : 255; - noise = signal - snr; - - /* Clip range of signal */ - signal = (signal < 63) ? signal : 63; - signal = (signal > -192) ? signal : -192; - - /* Clip range of noise */ - noise = (noise < 63) ? noise : 63; - noise = (noise > -192) ? noise : -192; - - /* Make u8 */ - signal = ( signal < 0 ) ? signal + 0x100 : signal; - noise = ( noise < 0 ) ? noise + 0x100 : noise; - - iwe.u.qual.level = (u8)signal; /* -192 : 63 */ - iwe.u.qual.noise = (u8)noise; /* -192 : 63 */ - iwe.u.qual.qual = snr; /* 0 : 255 */ - iwe.u.qual.updated = 0; -#if WIRELESS_EXT > 16 - iwe.u.qual.updated |= IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED | - IW_QUAL_QUAL_UPDATED; -#if WIRELESS_EXT > 18 - iwe.u.qual.updated |= IW_QUAL_DBM; -#endif -#endif - r = uf_iwe_stream_add_event(info, start_buf, end_buf, &iwe, IW_EV_QUAL_LEN); - if (r < 0) { - return r; - } - start_buf += r; - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (capabilities & SIG_CAP_PRIVACY) { - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - } else { - iwe.u.data.flags = IW_ENCODE_DISABLED; - } - iwe.u.data.length = 0; - iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, ""); - if (r < 0) { - return r; - } - start_buf += r; - - - /* - * Rate : stuffing multiple values in a single event require a bit - * more of magic - Jean II - */ - current_val = start_buf + IW_EV_LCP_LEN; - - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - - elem = unifi_find_info_element(IE_SUPPORTED_RATES_ID, - info_elems, info_elem_len); - if (elem) { - int e_len = elem[1]; - const unsigned char *e_ptr = elem + 2; - - /* - * Count how many rates we have. - * Zero marks the end of the list, if the list is not truncated. - */ - /* Max 8 values */ - for (i = 0; i < e_len; i++) { - if (e_ptr[i] == 0) { - break; - } - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000); - /* Add new value to event */ - r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); - if (r < 0) { - return r; - } - current_val +=r; - - } - } - elem = unifi_find_info_element(IE_EXTENDED_SUPPORTED_RATES_ID, - info_elems, info_elem_len); - if (elem) { - int e_len = elem[1]; - const unsigned char *e_ptr = elem + 2; - - /* - * Count how many rates we have. - * Zero marks the end of the list, if the list is not truncated. - */ - /* Max 8 values */ - for (i = 0; i < e_len; i++) { - if (e_ptr[i] == 0) { - break; - } - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((e_ptr[i] & 0x7f) * 500000); - /* Add new value to event */ - r = uf_iwe_stream_add_value(info, start_buf, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); - if (r < 0) { - return r; - } - current_val +=r; - } - } - /* Check if we added any rates event */ - if ((current_val - start_buf) > IW_EV_LCP_LEN) { - start_buf = current_val; - } - - -#if WIRELESS_EXT > 17 - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = info_elem_len; - - r = uf_iwe_stream_add_point(info, start_buf, end_buf, &iwe, info_elems); - if (r < 0) { - return r; - } - - start_buf += r; -#endif /* WE > 17 */ - - return (start_buf - current_ev); -} /* unifi_translate_scan() */ - - - -static int -unifi_giwscan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_point *dwrq = &wrqu->data; - int r; - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwscan: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - unifi_trace(priv, UDBG1, - "unifi_giwscan: buffer (%d bytes) \n", - dwrq->length); - UF_RTNL_UNLOCK(); - r = sme_mgt_scan_results_get_async(priv, info, extra, dwrq->length); - UF_RTNL_LOCK(); - if (r < 0) { - unifi_trace(priv, UDBG1, - "unifi_giwscan: buffer (%d bytes) not big enough.\n", - dwrq->length); - return r; - } - - dwrq->length = r; - dwrq->flags = 0; - - return 0; -} /* unifi_giwscan() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_siwessid - * - * Request to join a network or start and AdHoc. - * - * Arguments: - * dev Pointer to network device struct. - * info Pointer to broken-out ioctl request. - * data Pointer to argument data. - * essid Pointer to string giving name of network to join - * or start - * - * Returns: - * 0 on success and everything complete - * -EINPROGRESS to have the higher level call the commit method. - * --------------------------------------------------------------------------- - */ -static int -unifi_siwessid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int len; - int err = 0; - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwessid: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - len = 0; - if (data->flags & 1) { - /* Limit length */ - len = data->length; - if (len > UNIFI_MAX_SSID_LEN) { - len = UNIFI_MAX_SSID_LEN; - } - } - -#ifdef UNIFI_DEBUG - { - char essid_str[UNIFI_MAX_SSID_LEN+1]; - int i; - - for (i = 0; i < len; i++) { - essid_str[i] = (isprint(essid[i]) ? essid[i] : '?'); - } - essid_str[i] = '\0'; - - unifi_trace(priv, UDBG1, "unifi_siwessid: asked for '%*s' (%d)\n", len, essid_str, len); - unifi_trace(priv, UDBG2, " with authModeMask = %d", priv->connection_config.authModeMask); - } -#endif - - memset(priv->connection_config.bssid.a, 0xFF, ETH_ALEN); - if (len) { - if (essid[len - 1] == 0) { - len --; - } - - memcpy(priv->connection_config.ssid.ssid, essid, len); - priv->connection_config.ssid.length = len; - - } else { - priv->connection_config.ssid.length = 0; - } - - UF_RTNL_UNLOCK(); - err = sme_mgt_connect(priv); - UF_RTNL_LOCK(); - if (err) { - unifi_error(priv, "unifi_siwessid: Join failed, status %d\n", err); - return convert_sme_error(err); - } - - return 0; -} /* unifi_siwessid() */ - - -static int -unifi_giwessid(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *essid) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_point *data = &wrqu->essid; - CsrWifiSmeConnectionInfo connectionInfo; - int r = 0; - - unifi_trace(priv, UDBG2, "unifi_giwessid\n"); - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwessid: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - UF_RTNL_UNLOCK(); - r = sme_mgt_connection_info_get(priv, &connectionInfo); - UF_RTNL_LOCK(); - - if (r == 0) { - data->length = connectionInfo.ssid.length; - strncpy(essid, - connectionInfo.ssid.ssid, - data->length); - data->flags = 1; /* active */ - - unifi_trace(priv, UDBG2, "unifi_giwessid: %.*s\n", - data->length, essid); - } - - - return 0; -} /* unifi_giwessid() */ - - -static int -unifi_siwrate(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_param *args = &wrqu->bitrate; - CsrWifiSmeMibConfig mibConfig; - int r; - - CHECK_INITED(priv); - unifi_trace(priv, UDBG2, "unifi_siwrate\n"); - - /* - * If args->fixed == 0, value is max rate or -1 for best - * If args->fixed == 1, value is rate to set or -1 for best - * args->disabled and args->flags are not used in SIOCSIWRATE - */ - - /* Get, modify and set the MIB data */ - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwrate: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - /* Default to auto rate algorithm */ - /* in 500Kbit/s, 0 means auto */ - mibConfig.unifiFixTxDataRate = 0; - - if (args->value != -1) { - mibConfig.unifiFixTxDataRate = args->value / 500000; - } - - /* 1 means rate is a maximum, 2 means rate is a set value */ - if (args->fixed == 1) { - mibConfig.unifiFixMaxTxDataRate = 0; - } else { - mibConfig.unifiFixMaxTxDataRate = 1; - } - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_set(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwrate: Set CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - - return 0; -} /* unifi_siwrate() */ - - - -static int -unifi_giwrate(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_param *args = &wrqu->bitrate; - int r; - int bitrate, flag; - CsrWifiSmeMibConfig mibConfig; - CsrWifiSmeConnectionStats connectionStats; - - unifi_trace(priv, UDBG2, "unifi_giwrate\n"); - CHECK_INITED(priv); - - flag = 0; - bitrate = 0; - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_giwrate: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - bitrate = mibConfig.unifiFixTxDataRate; - flag = mibConfig.unifiFixMaxTxDataRate; - - /* Used the value returned by the SME if MIB returns 0 */ - if (bitrate == 0) { - UF_RTNL_UNLOCK(); - r = sme_mgt_connection_stats_get(priv, &connectionStats); - UF_RTNL_LOCK(); - /* Ignore errors, we may be disconnected */ - if (r == 0) { - bitrate = connectionStats.unifiTxDataRate; - } - } - - args->value = bitrate * 500000; - args->fixed = !flag; - - return 0; -} /* unifi_giwrate() */ - - -static int -unifi_siwrts(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int val = wrqu->rts.value; - int r = 0; - CsrWifiSmeMibConfig mibConfig; - - unifi_trace(priv, UDBG2, "unifi_siwrts\n"); - CHECK_INITED(priv); - - if (wrqu->rts.disabled) { - val = 2347; - } - - if ( (val < 0) || (val > 2347) ) - { - return -EINVAL; - } - - /* Get, modify and set the MIB data */ - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwrts: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - mibConfig.dot11RtsThreshold = val; - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_set(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwrts: Set CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - return 0; -} - - -static int -unifi_giwrts(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r; - int rts_thresh; - CsrWifiSmeMibConfig mibConfig; - - unifi_trace(priv, UDBG2, "unifi_giwrts\n"); - CHECK_INITED(priv); - - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_giwrts: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - rts_thresh = mibConfig.dot11RtsThreshold; - if (rts_thresh > 2347) { - rts_thresh = 2347; - } - - wrqu->rts.value = rts_thresh; - wrqu->rts.disabled = (rts_thresh == 2347); - wrqu->rts.fixed = 1; - - return 0; -} - - -static int -unifi_siwfrag(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int val = wrqu->frag.value; - int r = 0; - CsrWifiSmeMibConfig mibConfig; - - unifi_trace(priv, UDBG2, "unifi_siwfrag\n"); - CHECK_INITED(priv); - - if (wrqu->frag.disabled) - val = 2346; - - if ( (val < 256) || (val > 2347) ) - return -EINVAL; - - /* Get, modify and set the MIB data */ - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwfrag: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - /* Fragmentation Threashold must be even */ - mibConfig.dot11FragmentationThreshold = (val & ~0x1); - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_set(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwfrag: Set CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - return 0; -} - - -static int -unifi_giwfrag(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int r; - int frag_thresh; - CsrWifiSmeMibConfig mibConfig; - - unifi_trace(priv, UDBG2, "unifi_giwfrag\n"); - CHECK_INITED(priv); - - UF_RTNL_UNLOCK(); - r = sme_mgt_mib_config_get(priv, &mibConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_giwfrag: Get CsrWifiSmeMibConfigValue failed.\n"); - return r; - } - - frag_thresh = mibConfig.dot11FragmentationThreshold; - - /* Build the return structure */ - wrqu->frag.value = frag_thresh; - wrqu->frag.disabled = (frag_thresh >= 2346); - wrqu->frag.fixed = 1; - - return 0; -} - - -static int -unifi_siwencode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_point *erq = &wrqu->encoding; - int index; - int rc = 0; - int privacy = -1; - CsrWifiSmeKey sme_key; - - unifi_trace(priv, UDBG2, "unifi_siwencode\n"); - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwencode: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - /* - * Key index is encoded in the flags. - * 0 - use current default, - * 1-4 - if a key value is given set that key - * if not use that key - */ - index = (erq->flags & IW_ENCODE_INDEX); /* key number, 1-4 */ - if ((index < 0) || (index > 4)) { - unifi_error(priv, "unifi_siwencode: Request to set an invalid key (index:%d)", index); - return -EINVAL; - } - - /* - * Basic checking: do we have a key to set ? - * The IW_ENCODE_NOKEY flag is set when no key is present (only change flags), - * but older versions rely on sending a key id 1-4. - */ - if (erq->length > 0) { - - /* Check the size of the key */ - if ((erq->length > LARGE_KEY_SIZE) || (erq->length < SMALL_KEY_SIZE)) { - unifi_error(priv, "unifi_siwencode: Request to set an invalid key (length:%d)", - erq->length); - return -EINVAL; - } - - /* Check the index (none (i.e. 0) means use current) */ - if ((index < 1) || (index > 4)) { - /* If we do not have a previous key, use 1 as default */ - if (!priv->wep_tx_key_index) { - priv->wep_tx_key_index = 1; - } - index = priv->wep_tx_key_index; - } - - /* If we didn't have a key and a valid index is set, we want to remember it*/ - if (!priv->wep_tx_key_index) { - priv->wep_tx_key_index = index; - } - - unifi_trace(priv, UDBG1, "Tx key Index is %d\n", priv->wep_tx_key_index); - - privacy = 1; - - /* Check if the key is not marked as invalid */ - if ((erq->flags & IW_ENCODE_NOKEY) == 0) { - - unifi_trace(priv, UDBG1, "New %s key (len=%d, index=%d)\n", - (priv->wep_tx_key_index == index) ? "tx" : "", - erq->length, index); - - sme_key.wepTxKey = (priv->wep_tx_key_index == index); - if (priv->wep_tx_key_index == index) { - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; - } else { - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; - } - /* Key index is zero based in SME but 1 based in wext */ - sme_key.keyIndex = (index - 1); - sme_key.keyLength = erq->length; - sme_key.authenticator = 0; - memset(sme_key.address.a, 0xFF, ETH_ALEN); - memcpy(sme_key.key, extra, erq->length); - - UF_RTNL_UNLOCK(); - rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); - UF_RTNL_LOCK(); - if (rc) { - unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc); - return convert_sme_error(rc); - } - - /* Store the key to be reported by the SIOCGIWENCODE handler */ - priv->wep_keys[index - 1].len = erq->length; - memcpy(priv->wep_keys[index - 1].key, extra, erq->length); - } - } else { - /* - * No additional key data, so it must be a request to change the - * active key. - */ - if (index != 0) { - unifi_trace(priv, UDBG1, "Tx key Index is %d\n", index - 1); - - /* Store the index to be reported by the SIOCGIWENCODE handler */ - priv->wep_tx_key_index = index; - - sme_key.wepTxKey = 1; - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; - - /* Key index is zero based in SME but 1 based in wext */ - sme_key.keyIndex = (index - 1); - sme_key.keyLength = 0; - sme_key.authenticator = 0; - UF_RTNL_UNLOCK(); - rc = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); - UF_RTNL_LOCK(); - if (rc) { - unifi_error(priv, "unifi_siwencode: Set key failed (%d)", rc); - return convert_sme_error(rc); - } - - /* Turn on encryption */ - privacy = 1; - } - } - - /* Read the flags */ - if (erq->flags & IW_ENCODE_DISABLED) { - /* disable encryption */ - unifi_trace(priv, UDBG1, "disable WEP encryption\n"); - privacy = 0; - - priv->wep_tx_key_index = 0; - - unifi_trace(priv, UDBG1, "IW_ENCODE_DISABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - } - - if (erq->flags & IW_ENCODE_RESTRICTED) { - /* Use shared key auth */ - unifi_trace(priv, UDBG1, "IW_ENCODE_RESTRICTED: CSR_WIFI_SME_AUTH_MODE_80211_SHARED\n"); - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_SHARED; - - /* Turn on encryption */ - privacy = 1; - } - if (erq->flags & IW_ENCODE_OPEN) { - unifi_trace(priv, UDBG1, "IW_ENCODE_OPEN: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - } - - /* Commit the changes to flags if needed */ - if (privacy != -1) { - priv->connection_config.privacyMode = privacy ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; - priv->connection_config.encryptionModeMask = privacy ? (CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 | - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104) : - CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; - } - - return convert_sme_error(rc); - -} /* unifi_siwencode() */ - - - -static int -unifi_giwencode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_point *erq = &wrqu->encoding; - - unifi_trace(priv, UDBG2, "unifi_giwencode\n"); - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwencode: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - if (priv->connection_config.authModeMask == CSR_WIFI_SME_AUTH_MODE_80211_SHARED) { - erq->flags = IW_ENCODE_RESTRICTED; - } - else { - if (priv->connection_config.privacyMode == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) { - erq->flags = IW_ENCODE_DISABLED; - } else { - erq->flags = IW_ENCODE_OPEN; - } - } - - erq->length = 0; - - if (erq->flags != IW_ENCODE_DISABLED) { - int index = priv->wep_tx_key_index; - - if ((index > 0) && (index <= NUM_WEPKEYS)) { - erq->flags |= (index & IW_ENCODE_INDEX); - erq->length = priv->wep_keys[index - 1].len; - memcpy(extra, priv->wep_keys[index - 1].key, erq->length); - } else { - unifi_notice(priv, "unifi_giwencode: Surprise, do not have a valid key index (%d)\n", - index); - } - } - - return 0; -} /* unifi_giwencode() */ - - -static int -unifi_siwpower(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_param *args = &wrqu->power; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int listen_interval, wake_for_dtim; - int r = 0; - CsrWifiSmePowerConfig powerConfig; - - unifi_trace(priv, UDBG2, "unifi_siwpower\n"); - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwpower: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - UF_RTNL_UNLOCK(); - r = sme_mgt_power_config_get(priv, &powerConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwpower: Get unifi_PowerConfigValue failed.\n"); - return r; - } - - listen_interval = -1; - wake_for_dtim = -1; - if (args->disabled) { - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; - } - else - { - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; - - switch (args->flags & IW_POWER_TYPE) { - case 0: - /* not specified */ - break; - case IW_POWER_PERIOD: - listen_interval = args->value / 1000; - break; - default: - return -EINVAL; - } - - switch (args->flags & IW_POWER_MODE) { - case 0: - /* not specified */ - break; - case IW_POWER_UNICAST_R: - /* not interested in broadcast packets */ - wake_for_dtim = 0; - break; - case IW_POWER_ALL_R: - /* yes, we are interested in broadcast packets */ - wake_for_dtim = 1; - break; - default: - return -EINVAL; - } - } - - if (listen_interval > 0) { - powerConfig.listenIntervalTu = listen_interval; - unifi_trace(priv, UDBG4, "unifi_siwpower: new Listen Interval = %d.\n", - powerConfig.listenIntervalTu); - } - - if (wake_for_dtim >= 0) { - powerConfig.rxDtims = wake_for_dtim; - } - UF_RTNL_UNLOCK(); - r = sme_mgt_power_config_set(priv, &powerConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_siwpower: Set unifi_PowerConfigValue failed.\n"); - return r; - } - - return 0; -} /* unifi_siwpower() */ - - -static int -unifi_giwpower(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_param *args = &wrqu->power; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - CsrWifiSmePowerConfig powerConfig; - int r; - - unifi_trace(priv, UDBG2, "unifi_giwpower\n"); - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwpower: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - args->flags = 0; - UF_RTNL_UNLOCK(); - r = sme_mgt_power_config_get(priv, &powerConfig); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "unifi_giwpower: Get unifi_PowerConfigValue failed.\n"); - return r; - } - - unifi_trace(priv, UDBG4, "unifi_giwpower: mode=%d\n", - powerConfig.powerSaveLevel); - - args->disabled = (powerConfig.powerSaveLevel == CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW); - if (args->disabled) { - args->flags = 0; - return 0; - } - - args->value = powerConfig.listenIntervalTu * 1000; - args->flags |= IW_POWER_PERIOD; - - if (powerConfig.rxDtims) { - args->flags |= IW_POWER_ALL_R; - } else { - args->flags |= IW_POWER_UNICAST_R; - } - - return 0; -} /* unifi_giwpower() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_siwcommit - handler for SIOCSIWCOMMIT - * - * Apply all the parameters that have been set. - * In practice this means: - * - do a scan - * - join a network or start an AdHoc - * - authenticate and associate. - * - * Arguments: - * None. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static int -unifi_siwcommit(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - return 0; -} /* unifi_siwcommit() */ - - - -static int -unifi_siwmlme(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_mlme *mlme = (struct iw_mlme *)extra; - - unifi_trace(priv, UDBG2, "unifi_siwmlme\n"); - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwmlme: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - case IW_MLME_DISASSOC: - UF_RTNL_UNLOCK(); - sme_mgt_disconnect(priv); - UF_RTNL_LOCK(); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} /* unifi_siwmlme() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_siwgenie - * unifi_giwgenie - * - * WPA : Generic IEEE 802.11 information element (e.g., for WPA/RSN/WMM). - * Handlers for SIOCSIWGENIE, SIOCGIWGENIE - set/get generic IE - * - * The host program (e.g. wpa_supplicant) uses this call to set the - * additional IEs to accompany the next (Associate?) request. - * - * Arguments: - * None. - * - * Returns: - * None. - * Notes: - * From wireless.h: - * This ioctl uses struct iw_point and data buffer that includes IE id - * and len fields. More than one IE may be included in the - * request. Setting the generic IE to empty buffer (len=0) removes the - * generic IE from the driver. - * --------------------------------------------------------------------------- - */ -static int -unifi_siwgenie(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int len; - - unifi_trace(priv, UDBG2, "unifi_siwgenie\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwgenie: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - if ( priv->connection_config.mlmeAssociateReqInformationElements) { - kfree( priv->connection_config.mlmeAssociateReqInformationElements); - } - priv->connection_config.mlmeAssociateReqInformationElementsLength = 0; - priv->connection_config.mlmeAssociateReqInformationElements = NULL; - - len = wrqu->data.length; - if (len == 0) { - return 0; - } - - priv->connection_config.mlmeAssociateReqInformationElements = kmalloc(len, GFP_KERNEL); - if (priv->connection_config.mlmeAssociateReqInformationElements == NULL) { - return -ENOMEM; - } - - priv->connection_config.mlmeAssociateReqInformationElementsLength = len; - memcpy( priv->connection_config.mlmeAssociateReqInformationElements, extra, len); - - return 0; -} /* unifi_siwgenie() */ - - -static int -unifi_giwgenie(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - int len; - - unifi_trace(priv, UDBG2, "unifi_giwgenie\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_giwgenie: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - len = priv->connection_config.mlmeAssociateReqInformationElementsLength; - - if (len == 0) { - wrqu->data.length = 0; - return 0; - } - - if (wrqu->data.length < len) { - return -E2BIG; - } - - wrqu->data.length = len; - memcpy(extra, priv->connection_config.mlmeAssociateReqInformationElements, len); - - return 0; -} /* unifi_giwgenie() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_siwauth - * unifi_giwauth - * - * Handlers for SIOCSIWAUTH, SIOCGIWAUTH - * Set/get various authentication parameters. - * - * Arguments: - * - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static int -_unifi_siwauth(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - CsrWifiSmeAuthModeMask new_auth; - - unifi_trace(priv, UDBG2, "unifi_siwauth\n"); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwauth: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - /* - * This ioctl is safe to call even when UniFi is powered off. - * wpa_supplicant calls it to test whether we support WPA. - */ - - switch (wrqu->param.flags & IW_AUTH_INDEX) { - - case IW_AUTH_WPA_ENABLED: - unifi_trace(priv, UDBG1, "IW_AUTH_WPA_ENABLED: %d\n", wrqu->param.value); - - if (wrqu->param.value == 0) { - unifi_trace(priv, UDBG5, "IW_AUTH_WPA_ENABLED: CSR_WIFI_SME_AUTH_MODE_80211_OPEN\n"); - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - } - break; - - case IW_AUTH_PRIVACY_INVOKED: - unifi_trace(priv, UDBG1, "IW_AUTH_PRIVACY_INVOKED: %d\n", wrqu->param.value); - - priv->connection_config.privacyMode = wrqu->param.value ? CSR_WIFI_SME_80211_PRIVACY_MODE_ENABLED : CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED; - if (wrqu->param.value == CSR_WIFI_SME_80211_PRIVACY_MODE_DISABLED) - { - priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; - } - break; - - case IW_AUTH_80211_AUTH_ALG: - /* - IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 - IW_AUTH_ALG_SHARED_KEY 0x00000002 - IW_AUTH_ALG_LEAP 0x00000004 - */ - new_auth = 0; - if (wrqu->param.value & IW_AUTH_ALG_OPEN_SYSTEM) { - unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_OPEN_SYSTEM)\n", wrqu->param.value); - new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - } - if (wrqu->param.value & IW_AUTH_ALG_SHARED_KEY) { - unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_SHARED_KEY)\n", wrqu->param.value); - new_auth |= CSR_WIFI_SME_AUTH_MODE_80211_SHARED; - } - if (wrqu->param.value & IW_AUTH_ALG_LEAP) { - /* Initial exchanges using open-system to set EAP */ - unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: %d (IW_AUTH_ALG_LEAP)\n", wrqu->param.value); - new_auth |= CSR_WIFI_SME_AUTH_MODE_8021X_OTHER1X; - } - if (new_auth == 0) { - unifi_trace(priv, UDBG1, "IW_AUTH_80211_AUTH_ALG: invalid value %d\n", - wrqu->param.value); - return -EINVAL; - } else { - priv->connection_config.authModeMask = new_auth; - } - break; - - case IW_AUTH_WPA_VERSION: - unifi_trace(priv, UDBG1, "IW_AUTH_WPA_VERSION: %d\n", wrqu->param.value); - priv->ignore_bssid_join = TRUE; - /* - IW_AUTH_WPA_VERSION_DISABLED 0x00000001 - IW_AUTH_WPA_VERSION_WPA 0x00000002 - IW_AUTH_WPA_VERSION_WPA2 0x00000004 - */ - - if (!(wrqu->param.value & IW_AUTH_WPA_VERSION_DISABLED)) { - - priv->connection_config.authModeMask = CSR_WIFI_SME_AUTH_MODE_80211_OPEN; - - if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA) { - unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA, WPA-PSK\n"); - priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK); - } - if (wrqu->param.value & IW_AUTH_WPA_VERSION_WPA2) { - unifi_trace(priv, UDBG4, "IW_AUTH_WPA_VERSION: WPA2, WPA2-PSK\n"); - priv->connection_config.authModeMask |= (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK); - } - } - break; - - case IW_AUTH_CIPHER_PAIRWISE: - unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_PAIRWISE: %d\n", wrqu->param.value); - /* - * one of: - IW_AUTH_CIPHER_NONE 0x00000001 - IW_AUTH_CIPHER_WEP40 0x00000002 - IW_AUTH_CIPHER_TKIP 0x00000004 - IW_AUTH_CIPHER_CCMP 0x00000008 - IW_AUTH_CIPHER_WEP104 0x00000010 - */ - - priv->connection_config.encryptionModeMask = CSR_WIFI_SME_ENCRYPTION_CIPHER_NONE; - - if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) { - priv->connection_config.encryptionModeMask |= - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP40 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40; - } - if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) { - priv->connection_config.encryptionModeMask |= - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_WEP104 | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104; - } - if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) { - priv->connection_config.encryptionModeMask |= - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_TKIP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP; - } - if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) { - priv->connection_config.encryptionModeMask |= - CSR_WIFI_SME_ENCRYPTION_CIPHER_PAIRWISE_CCMP | CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP; - } - - break; - - case IW_AUTH_CIPHER_GROUP: - unifi_trace(priv, UDBG1, "IW_AUTH_CIPHER_GROUP: %d\n", wrqu->param.value); - /* - * Use the WPA version and the group cipher suite to set the permitted - * group key in the MIB. f/w uses this value to validate WPA and RSN IEs - * in the probe responses from the desired BSS(ID) - */ - - priv->connection_config.encryptionModeMask &= ~(CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40 | - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104 | - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP | - CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP); - if (wrqu->param.value & IW_AUTH_CIPHER_WEP40) { - priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP40; - } - if (wrqu->param.value & IW_AUTH_CIPHER_WEP104) { - priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_WEP104; - } - if (wrqu->param.value & IW_AUTH_CIPHER_TKIP) { - priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_TKIP; - } - if (wrqu->param.value & IW_AUTH_CIPHER_CCMP) { - priv->connection_config.encryptionModeMask |= CSR_WIFI_SME_ENCRYPTION_CIPHER_GROUP_CCMP; - } - - break; - - case IW_AUTH_KEY_MGMT: - unifi_trace(priv, UDBG1, "IW_AUTH_KEY_MGMT: %d\n", wrqu->param.value); - /* - IW_AUTH_KEY_MGMT_802_1X 1 - IW_AUTH_KEY_MGMT_PSK 2 - */ - if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA | CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK)) { - /* Check for explicitly set mode. */ - if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) { - priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPAPSK; - } - if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) { - priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA; - } - unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA: %d\n", - priv->connection_config.authModeMask); - } - if (priv->connection_config.authModeMask & (CSR_WIFI_SME_AUTH_MODE_8021X_WPA2 | CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK)) { - /* Check for explicitly set mode. */ - if (wrqu->param.value == IW_AUTH_KEY_MGMT_802_1X) { - priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2PSK; - } - if (wrqu->param.value == IW_AUTH_KEY_MGMT_PSK) { - priv->connection_config.authModeMask &= ~CSR_WIFI_SME_AUTH_MODE_8021X_WPA2; - } - unifi_trace(priv, UDBG5, "IW_AUTH_KEY_MGMT: WPA2: %d\n", - priv->connection_config.authModeMask); - } - - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - /* - * Set to true at the start of the 60 second backup-off period - * following 2 MichaelMIC failures within 60s. - */ - unifi_trace(priv, UDBG1, "IW_AUTH_TKIP_COUNTERMEASURES: %d\n", wrqu->param.value); - break; - - case IW_AUTH_DROP_UNENCRYPTED: - /* - * Set to true on init. - * Set to false just before associate if encryption will not be - * required. - * - * Note this is not the same as the 802.1X controlled port - */ - unifi_trace(priv, UDBG1, "IW_AUTH_DROP_UNENCRYPTED: %d\n", wrqu->param.value); - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - /* - * This is set by wpa_supplicant to allow unencrypted EAPOL messages - * even if pairwise keys are set when not using WPA. IEEE 802.1X - * specifies that these frames are not encrypted, but WPA encrypts - * them when pairwise keys are in use. - * I think the UniFi f/w handles this decision for us. - */ - unifi_trace(priv, UDBG1, "IW_AUTH_RX_UNENCRYPTED_EAPOL: %d\n", wrqu->param.value); - break; - - case IW_AUTH_ROAMING_CONTROL: - unifi_trace(priv, UDBG1, "IW_AUTH_ROAMING_CONTROL: %d\n", wrqu->param.value); - break; - - default: - unifi_trace(priv, UDBG1, "Unsupported auth param %d to 0x%X\n", - wrqu->param.flags & IW_AUTH_INDEX, - wrqu->param.value); - return -EOPNOTSUPP; - } - - unifi_trace(priv, UDBG2, "authModeMask = %d", priv->connection_config.authModeMask); - - return 0; -} /* _unifi_siwauth() */ - - -static int -unifi_siwauth(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int err = 0; - - UF_RTNL_UNLOCK(); - err = _unifi_siwauth(dev, info, wrqu, extra); - UF_RTNL_LOCK(); - - return err; -} /* unifi_siwauth() */ - - -static int -unifi_giwauth(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - unifi_trace(NULL, UDBG2, "unifi_giwauth\n"); - return -EOPNOTSUPP; -} /* unifi_giwauth() */ - -/* - * --------------------------------------------------------------------------- - * unifi_siwencodeext - * unifi_giwencodeext - * - * Handlers for SIOCSIWENCODEEXT, SIOCGIWENCODEEXT - set/get - * encoding token & mode - * - * Arguments: - * None. - * - * Returns: - * None. - * - * Notes: - * For WPA/WPA2 we don't take note of the IW_ENCODE_EXT_SET_TX_KEY flag. - * This flag means "use this key to encode transmissions"; we just - * assume only one key will be set and that is the one to use. - * --------------------------------------------------------------------------- - */ -static int -_unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int r = 0; - unsigned char *keydata; - unsigned char tkip_key[32]; - int keyid; - unsigned char *a = (unsigned char *)ext->addr.sa_data; - CsrWifiSmeKey sme_key; - CsrWifiSmeKeyType key_type; - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwencodeext: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - unifi_trace(priv, UDBG1, "siwencodeext: flags=0x%X, alg=%d, ext_flags=0x%X, len=%d, index=%d,\n", - wrqu->encoding.flags, ext->alg, ext->ext_flags, - ext->key_len, (wrqu->encoding.flags & IW_ENCODE_INDEX)); - unifi_trace(priv, UDBG3, " addr=%pM\n", a); - - if ((ext->key_len == 0) && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { - /* This means use a different key (given by key_idx) for Tx. */ - /* NYI */ - unifi_trace(priv, UDBG1, KERN_ERR "unifi_siwencodeext: NYI should change tx key id here!!\n"); - return -ENOTSUPP; - } - - memset(&sme_key, 0, sizeof(sme_key)); - - keydata = (unsigned char *)(ext + 1); - keyid = (wrqu->encoding.flags & IW_ENCODE_INDEX); - - /* - * Check for request to delete keys for an address. - */ - /* Pick out request for no privacy. */ - if (ext->alg == IW_ENCODE_ALG_NONE) { - - unifi_trace(priv, UDBG1, "Deleting %s key %d\n", - (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? "GROUP" : "PAIRWISE", - keyid); - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; - } else { - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; - } - sme_key.keyIndex = (keyid - 1); - sme_key.keyLength = 0; - sme_key.authenticator = 0; - memcpy(sme_key.address.a, a, ETH_ALEN); - UF_RTNL_UNLOCK(); - r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_REMOVE); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "Delete key request was rejected with result %d\n", r); - return convert_sme_error(r); - } - - return 0; - } - - /* - * Request is to set a key, not delete - */ - - /* Pick out WEP and use set_wep_key(). */ - if (ext->alg == IW_ENCODE_ALG_WEP) { - /* WEP-40, WEP-104 */ - - /* Check for valid key length */ - if (!((ext->key_len == 5) || (ext->key_len == 13))) { - unifi_trace(priv, UDBG1, KERN_ERR "Invalid length for WEP key: %d\n", ext->key_len); - return -EINVAL; - } - - unifi_trace(priv, UDBG1, "Setting WEP key %d tx:%d\n", - keyid, ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY); - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - sme_key.wepTxKey = TRUE; - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_PAIRWISE; - } else { - sme_key.wepTxKey = FALSE; - sme_key.keyType = CSR_WIFI_SME_KEY_TYPE_GROUP; - } - sme_key.keyIndex = (keyid - 1); - sme_key.keyLength = ext->key_len; - sme_key.authenticator = 0; - memset(sme_key.address.a, 0xFF, ETH_ALEN); - memcpy(sme_key.key, keydata, ext->key_len); - UF_RTNL_UNLOCK(); - r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "siwencodeext: Set key failed (%d)", r); - return convert_sme_error(r); - } - - return 0; - } - - /* - * - * If we reach here, we are dealing with a WPA/WPA2 key - * - */ - if (ext->key_len > 32) { - return -EINVAL; - } - - /* - * TKIP keys from wpa_supplicant need swapping. - * What about other supplicants (when they come along)? - */ - if ((ext->alg == IW_ENCODE_ALG_TKIP) && (ext->key_len == 32)) { - memcpy(tkip_key, keydata, 16); - memcpy(tkip_key + 16, keydata + 24, 8); - memcpy(tkip_key + 24, keydata + 16, 8); - keydata = tkip_key; - } - - key_type = (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ? - CSR_WIFI_SME_KEY_TYPE_GROUP : /* Group Key */ - CSR_WIFI_SME_KEY_TYPE_PAIRWISE; /* Pairwise Key */ - - sme_key.keyType = key_type; - sme_key.keyIndex = (keyid - 1); - sme_key.keyLength = ext->key_len; - sme_key.authenticator = 0; - memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN); - if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - - unifi_trace(priv, UDBG5, "RSC first 6 bytes = %*phC\n", - 6, ext->rx_seq); - - /* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */ - sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0]; - sme_key.keyRsc[1] = ext->rx_seq[3] << 8 | ext->rx_seq[2]; - sme_key.keyRsc[2] = ext->rx_seq[5] << 8 | ext->rx_seq[4]; - sme_key.keyRsc[3] = ext->rx_seq[7] << 8 | ext->rx_seq[6]; - - } - - memcpy(sme_key.key, keydata, ext->key_len); - UF_RTNL_UNLOCK(); - r = sme_mgt_key(priv, &sme_key, CSR_WIFI_SME_LIST_ACTION_ADD); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "SETKEYS request was rejected with result %d\n", r); - return convert_sme_error(r); - } - - return r; -} /* _unifi_siwencodeext() */ - - -static int -unifi_siwencodeext(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int err = 0; - - err = _unifi_siwencodeext(dev, info, wrqu, extra); - - return err; -} /* unifi_siwencodeext() */ - - -static int -unifi_giwencodeext(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - return -EOPNOTSUPP; -} /* unifi_giwencodeext() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_siwpmksa - * - * SIOCSIWPMKSA - PMKSA cache operation - * The caller passes a pmksa structure: - * - cmd one of ADD, REMOVE, FLUSH - * - bssid MAC address - * - pmkid ID string (16 bytes) - * - * Arguments: - * None. - * - * Returns: - * None. - * - * Notes: - * This is not needed since we provide a siwgenie method. - * --------------------------------------------------------------------------- - */ -#define UNIFI_PMKID_KEY_SIZE 16 -static int -unifi_siwpmksa(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; - CsrResult r = 0; - CsrWifiSmePmkidList pmkid_list; - CsrWifiSmePmkid pmkid; - CsrWifiSmeListAction action; - - CHECK_INITED(priv); - - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - unifi_error(priv, "unifi_siwpmksa: not permitted in Mode %d\n", - interfacePriv->interfaceMode); - return -EPERM; - } - - - unifi_trace(priv, UDBG1, "SIWPMKSA: cmd %d, %pM\n", pmksa->cmd, - pmksa->bssid.sa_data); - - pmkid_list.pmkids = NULL; - switch (pmksa->cmd) { - case IW_PMKSA_ADD: - pmkid_list.pmkids = &pmkid; - action = CSR_WIFI_SME_LIST_ACTION_ADD; - pmkid_list.pmkidsCount = 1; - memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN); - memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE); - break; - case IW_PMKSA_REMOVE: - pmkid_list.pmkids = &pmkid; - action = CSR_WIFI_SME_LIST_ACTION_REMOVE; - pmkid_list.pmkidsCount = 1; - memcpy(pmkid.bssid.a, pmksa->bssid.sa_data, ETH_ALEN); - memcpy(pmkid.pmkid, pmksa->pmkid, UNIFI_PMKID_KEY_SIZE); - break; - case IW_PMKSA_FLUSH: - /* Replace current PMKID's with an empty list */ - pmkid_list.pmkidsCount = 0; - action = CSR_WIFI_SME_LIST_ACTION_FLUSH; - break; - default: - unifi_notice(priv, "SIWPMKSA: Unknown command (0x%x)\n", pmksa->cmd); - return -EINVAL; - } - - /* Set the Value the pmkid's will have 1 added OR 1 removed OR be cleared at this point */ - UF_RTNL_UNLOCK(); - r = sme_mgt_pmkid(priv, action, &pmkid_list); - UF_RTNL_LOCK(); - if (r) { - unifi_error(priv, "SIWPMKSA: Set PMKID's Failed.\n"); - } - - return r; - -} /* unifi_siwpmksa() */ - - -/* - * --------------------------------------------------------------------------- - * unifi_get_wireless_stats - * - * get_wireless_stats method for Linux wireless extensions. - * - * Arguments: - * dev Pointer to associated netdevice. - * - * Returns: - * Pointer to iw_statistics struct. - * --------------------------------------------------------------------------- - */ -struct iw_statistics * -unifi_get_wireless_stats(struct net_device *dev) -{ - netInterface_priv_t *interfacePriv = (netInterface_priv_t *)netdev_priv(dev); - unifi_priv_t *priv = interfacePriv->privPtr; - - if (priv->init_progress != UNIFI_INIT_COMPLETED) { - return NULL; - } - - return &priv->wext_wireless_stats; -} /* unifi_get_wireless_stats() */ - - -/* - * Structures to export the Wireless Handlers - */ - -static const struct iw_priv_args unifi_private_args[] = { - /*{ cmd, set_args, get_args, name } */ - { SIOCIWS80211POWERSAVEPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "iwprivs80211ps" }, - { SIOCIWG80211POWERSAVEPRIV, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IWPRIV_POWER_SAVE_MAX_STRING, "iwprivg80211ps" }, - { SIOCIWS80211RELOADDEFAULTSPRIV, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, "iwprivsdefs" }, - { SIOCIWSSMEDEBUGPRIV, IW_PRIV_TYPE_CHAR | IWPRIV_SME_DEBUG_MAX_STRING, IW_PRIV_TYPE_NONE, "iwprivssmedebug" }, -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - { SIOCIWSCONFWAPIPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "iwprivsconfwapi" }, - { SIOCIWSWAPIKEYPRIV, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(unifiio_wapi_key_t), - IW_PRIV_TYPE_NONE, "iwprivswpikey" }, -#endif -#ifdef CSR_SUPPORT_WEXT_AP - { SIOCIWSAPCFGPRIV, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_NONE, "AP_SET_CFG" }, - { SIOCIWSAPSTARTPRIV, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "AP_BSS_START" }, - { SIOCIWSAPSTOPPRIV, IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, - IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "AP_BSS_STOP" }, -#ifdef ANDROID_BUILD - { SIOCIWSFWRELOADPRIV, IW_PRIV_TYPE_CHAR |256, - IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|0, "WL_FW_RELOAD" }, - { SIOCIWSSTACKSTART, 0, - IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "START" }, - { SIOCIWSSTACKSTOP, 0, - IW_PRIV_TYPE_CHAR |IW_PRIV_SIZE_FIXED|IWPRIV_SME_MAX_STRING, "STOP" }, -#endif /* ANDROID_BUILD */ -#endif /* CSR_SUPPORT_WEXT_AP */ -}; - -static const iw_handler unifi_handler[] = -{ - (iw_handler) unifi_siwcommit, /* SIOCSIWCOMMIT */ - (iw_handler) unifi_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) unifi_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) unifi_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) unifi_siwmode, /* SIOCSIWMODE */ - (iw_handler) unifi_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) unifi_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) unifi_siwap, /* SIOCSIWAP */ - (iw_handler) unifi_giwap, /* SIOCGIWAP */ -#if WIRELESS_EXT > 17 - /* WPA : IEEE 802.11 MLME requests */ - unifi_siwmlme, /* SIOCSIWMLME, request MLME operation */ -#else - (iw_handler) NULL, /* -- hole -- */ -#endif - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) unifi_siwscan, /* SIOCSIWSCAN */ - (iw_handler) unifi_giwscan, /* SIOCGIWSCAN */ - (iw_handler) unifi_siwessid, /* SIOCSIWESSID */ - (iw_handler) unifi_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - unifi_siwrate, /* SIOCSIWRATE */ - unifi_giwrate, /* SIOCGIWRATE */ - unifi_siwrts, /* SIOCSIWRTS */ - unifi_giwrts, /* SIOCGIWRTS */ - unifi_siwfrag, /* SIOCSIWFRAG */ - unifi_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) NULL, /* SIOCSIWRETRY */ - (iw_handler) NULL, /* SIOCGIWRETRY */ - unifi_siwencode, /* SIOCSIWENCODE */ - unifi_giwencode, /* SIOCGIWENCODE */ - unifi_siwpower, /* SIOCSIWPOWER */ - unifi_giwpower, /* SIOCGIWPOWER */ -#if WIRELESS_EXT > 17 - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - - /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). */ - unifi_siwgenie, /* SIOCSIWGENIE */ /* set generic IE */ - unifi_giwgenie, /* SIOCGIWGENIE */ /* get generic IE */ - - /* WPA : Authentication mode parameters */ - unifi_siwauth, /* SIOCSIWAUTH */ /* set authentication mode params */ - unifi_giwauth, /* SIOCGIWAUTH */ /* get authentication mode params */ - - /* WPA : Extended version of encoding configuration */ - unifi_siwencodeext, /* SIOCSIWENCODEEXT */ /* set encoding token & mode */ - unifi_giwencodeext, /* SIOCGIWENCODEEXT */ /* get encoding token & mode */ - - /* WPA2 : PMKSA cache management */ - unifi_siwpmksa, /* SIOCSIWPMKSA */ /* PMKSA cache operation */ - (iw_handler) NULL, /* -- hole -- */ -#endif /* WIRELESS_EXT > 17 */ -}; - - -static const iw_handler unifi_private_handler[] = -{ - iwprivs80211ps, /* SIOCIWFIRSTPRIV */ - iwprivg80211ps, /* SIOCIWFIRSTPRIV + 1 */ - iwprivsdefs, /* SIOCIWFIRSTPRIV + 2 */ - (iw_handler) NULL, -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - iwprivsconfwapi, /* SIOCIWFIRSTPRIV + 4 */ - (iw_handler) NULL, /* SIOCIWFIRSTPRIV + 5 */ - iwprivswpikey, /* SIOCIWFIRSTPRIV + 6 */ -#else - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, -#endif - (iw_handler) NULL, - iwprivssmedebug, /* SIOCIWFIRSTPRIV + 8 */ -#ifdef CSR_SUPPORT_WEXT_AP - (iw_handler) NULL, - iwprivsapconfig, - (iw_handler) NULL, - iwprivsapstart, - (iw_handler) NULL, - iwprivsapstop, - (iw_handler) NULL, -#ifdef ANDROID_BUILD - iwprivsapfwreload, - (iw_handler) NULL, - iwprivsstackstart, - (iw_handler) NULL, - iwprivsstackstop, -#else - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, -#endif /* ANDROID_BUILD */ -#else - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, -#endif /* CSR_SUPPORT_WEXT_AP */ -}; - -struct iw_handler_def unifi_iw_handler_def = -{ - .num_standard = sizeof(unifi_handler) / sizeof(iw_handler), - .num_private = sizeof(unifi_private_handler) / sizeof(iw_handler), - .num_private_args = sizeof(unifi_private_args) / sizeof(struct iw_priv_args), - .standard = (iw_handler *) unifi_handler, - .private = (iw_handler *) unifi_private_handler, - .private_args = (struct iw_priv_args *) unifi_private_args, -#if IW_HANDLER_VERSION >= 6 - .get_wireless_stats = unifi_get_wireless_stats, -#endif -}; - - diff --git a/drivers/staging/csr/ul_int.c b/drivers/staging/csr/ul_int.c deleted file mode 100644 index eb286e5f7467..000000000000 --- a/drivers/staging/csr/ul_int.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * *************************************************************************** - * FILE: ul_int.c - * - * PURPOSE: - * Manage list of client applications using UniFi. - * - * Copyright (C) 2006-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "unifi_priv.h" -#include "unifiio.h" -#include "unifi_os.h" - -static void free_bulkdata_buffers(unifi_priv_t *priv, bulk_data_param_t *bulkdata); -static void reset_driver_status(unifi_priv_t *priv); - -/* - * --------------------------------------------------------------------------- - * ul_init_clients - * - * Initialise the clients array to empty. - * - * Arguments: - * priv Pointer to device private context struct - * - * Returns: - * None. - * - * Notes: - * This function needs to be called before priv is stored in - * Unifi_instances[]. - * --------------------------------------------------------------------------- - */ -void -ul_init_clients(unifi_priv_t *priv) -{ - int id; - ul_client_t *ul_clients; - - sema_init(&priv->udi_logging_mutex, 1); - priv->logging_client = NULL; - - ul_clients = priv->ul_clients; - - for (id = 0; id < MAX_UDI_CLIENTS; id++) { - memset(&ul_clients[id], 0, sizeof(ul_client_t)); - - ul_clients[id].client_id = id; - ul_clients[id].sender_id = UDI_SENDER_ID_BASE + (id << UDI_SENDER_ID_SHIFT); - ul_clients[id].instance = -1; - ul_clients[id].event_hook = NULL; - - INIT_LIST_HEAD(&ul_clients[id].udi_log); - init_waitqueue_head(&ul_clients[id].udi_wq); - sema_init(&ul_clients[id].udi_sem, 1); - - ul_clients[id].wake_up_wq_id = 0; - ul_clients[id].seq_no = 0; - ul_clients[id].wake_seq_no = 0; - ul_clients[id].snap_filter.count = 0; - } -} /* ul_init_clients() */ - - -/* - * --------------------------------------------------------------------------- - * ul_register_client - * - * This function registers a new ul client. - * - * Arguments: - * priv Pointer to device private context struct - * configuration Special configuration for the client. - * udi_event_clbk Callback for receiving event from unifi. - * - * Returns: - * 0 if a new clients is registered, -1 otherwise. - * --------------------------------------------------------------------------- - */ -ul_client_t * -ul_register_client(unifi_priv_t *priv, unsigned int configuration, - udi_event_t udi_event_clbk) -{ - unsigned char id, ref; - ul_client_t *ul_clients; - - ul_clients = priv->ul_clients; - - /* check for an unused entry */ - for (id = 0; id < MAX_UDI_CLIENTS; id++) { - if (ul_clients[id].udi_enabled == 0) { - ul_clients[id].instance = priv->instance; - ul_clients[id].udi_enabled = 1; - ul_clients[id].configuration = configuration; - - /* Allocate memory for the reply signal.. */ - ul_clients[id].reply_signal = kmalloc(sizeof(CSR_SIGNAL), GFP_KERNEL); - if (ul_clients[id].reply_signal == NULL) { - unifi_error(priv, "Failed to allocate reply signal for client.\n"); - return NULL; - } - /* .. and the bulk data of the reply signal. */ - for (ref = 0; ref < UNIFI_MAX_DATA_REFERENCES; ref ++) { - ul_clients[id].reply_bulkdata[ref] = kmalloc(sizeof(bulk_data_t), GFP_KERNEL); - /* If allocation fails, free allocated memory. */ - if (ul_clients[id].reply_bulkdata[ref] == NULL) { - for (; ref > 0; ref --) { - kfree(ul_clients[id].reply_bulkdata[ref - 1]); - } - kfree(ul_clients[id].reply_signal); - unifi_error(priv, "Failed to allocate bulk data buffers for client.\n"); - return NULL; - } - } - - /* Set the event callback. */ - ul_clients[id].event_hook = udi_event_clbk; - - unifi_trace(priv, UDBG2, "UDI %d (0x%x) registered. configuration = 0x%x\n", - id, &ul_clients[id], configuration); - return &ul_clients[id]; - } - } - return NULL; -} /* ul_register_client() */ - - -/* - * --------------------------------------------------------------------------- - * ul_deregister_client - * - * This function deregisters a blocking UDI client. - * - * Arguments: - * client Pointer to the client we deregister. - * - * Returns: - * 0 if a new clients is deregistered. - * --------------------------------------------------------------------------- - */ -int -ul_deregister_client(ul_client_t *ul_client) -{ - struct list_head *pos, *n; - udi_log_t *logptr; - unifi_priv_t *priv = uf_find_instance(ul_client->instance); - int ref; - - ul_client->instance = -1; - ul_client->event_hook = NULL; - ul_client->udi_enabled = 0; - unifi_trace(priv, UDBG5, "UDI (0x%x) deregistered.\n", ul_client); - - /* Free memory allocated for the reply signal and its bulk data. */ - kfree(ul_client->reply_signal); - for (ref = 0; ref < UNIFI_MAX_DATA_REFERENCES; ref ++) { - kfree(ul_client->reply_bulkdata[ref]); - } - - if (ul_client->snap_filter.count) { - ul_client->snap_filter.count = 0; - kfree(ul_client->snap_filter.protocols); - } - - /* Free anything pending on the udi_log list */ - down(&ul_client->udi_sem); - list_for_each_safe(pos, n, &ul_client->udi_log) - { - logptr = list_entry(pos, udi_log_t, q); - list_del(pos); - kfree(logptr); - } - up(&ul_client->udi_sem); - - return 0; -} /* ul_deregister_client() */ - - - -/* - * --------------------------------------------------------------------------- - * logging_handler - * - * This function is registered with the driver core. - * It is called every time a UniFi HIP Signal is sent. It iterates over - * the list of processes interested in receiving log events and - * delivers the events to them. - * - * Arguments: - * ospriv Pointer to driver's private data. - * sigdata Pointer to the packed signal buffer. - * signal_len Length of the packed signal. - * bulkdata Pointer to the signal's bulk data. - * dir Direction of the signal - * 0 = from-host - * 1 = to-host - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -logging_handler(void *ospriv, - u8 *sigdata, u32 signal_len, - const bulk_data_param_t *bulkdata, - enum udi_log_direction direction) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - ul_client_t *client; - int dir; - - dir = (direction == UDI_LOG_FROM_HOST) ? UDI_FROM_HOST : UDI_TO_HOST; - - down(&priv->udi_logging_mutex); - client = priv->logging_client; - if (client != NULL) { - client->event_hook(client, sigdata, signal_len, - bulkdata, dir); - } - up(&priv->udi_logging_mutex); - -} /* logging_handler() */ - - - -/* - * --------------------------------------------------------------------------- - * ul_log_config_ind - * - * This function uses the client's register callback - * to indicate configuration information e.g core errors. - * - * Arguments: - * priv Pointer to driver's private data. - * conf_param Pointer to the configuration data. - * len Length of the configuration data. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len) -{ -#ifdef CSR_SUPPORT_SME - if (priv->smepriv == NULL) - { - return; - } - if ((CONFIG_IND_ERROR == (*conf_param)) && (priv->wifi_on_state == wifi_on_in_progress)) { - unifi_notice(priv, "ul_log_config_ind: wifi on in progress, suppress error\n"); - } else { - /* wifi_off_ind (error or exit) */ - CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, (CsrWifiRouterCtrlControlIndication)(*conf_param)); - } -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE - unifi_debug_buf_dump(); -#endif -#else - bulk_data_param_t bulkdata; - - /* - * If someone killed unifi_managed before the driver was unloaded - * the g_drvpriv pointer is going to be NULL. In this case it is - * safe to assume that there is no client to get the indication. - */ - if (!priv) { - unifi_notice(NULL, "uf_sme_event_ind: NULL priv\n"); - return; - } - - /* Create a null bulkdata structure. */ - bulkdata.d[0].data_length = 0; - bulkdata.d[1].data_length = 0; - - sme_native_log_event(priv->sme_cli, conf_param, sizeof(u8), - &bulkdata, UDI_CONFIG_IND); - -#endif /* CSR_SUPPORT_SME */ - -} /* ul_log_config_ind */ - - -/* - * --------------------------------------------------------------------------- - * free_bulkdata_buffers - * - * Free the bulkdata buffers e.g. after a failed unifi_send_signal(). - * - * Arguments: - * priv Pointer to device private struct - * bulkdata Pointer to bulkdata parameter table - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -free_bulkdata_buffers(unifi_priv_t *priv, bulk_data_param_t *bulkdata) -{ - int i; - - if (bulkdata) { - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (bulk_data_desc_t *)(&bulkdata->d[i])); - /* data_length is now 0 */ - } - } - } - -} /* free_bulkdata_buffers */ - -static int -_align_bulk_data_buffers(unifi_priv_t *priv, u8 *signal, - bulk_data_param_t *bulkdata) -{ - unsigned int i; - - if ((bulkdata == NULL) || (CSR_WIFI_ALIGN_BYTES == 0)) { - return 0; - } - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) - { - struct sk_buff *skb; - /* - * The following complex casting is in place in order to eliminate 64-bit compilation warning - * "cast to/from pointer from/to integer of different size" - */ - u32 align_offset = (u32)(long)(bulkdata->d[i].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); - if (align_offset) - { - skb = (struct sk_buff*)bulkdata->d[i].os_net_buf_ptr; - if (skb == NULL) { - unifi_warning(priv, - "_align_bulk_data_buffers: Align offset found (%d) but skb is NULL!\n", - align_offset); - return -EINVAL; - } - if (bulkdata->d[i].data_length == 0) { - unifi_warning(priv, - "_align_bulk_data_buffers: Align offset found (%d) but length is zero\n", - align_offset); - return CSR_RESULT_SUCCESS; - } - unifi_trace(priv, UDBG5, - "Align f-h buffer (0x%p) by %d bytes (skb->data: 0x%p)\n", - bulkdata->d[i].os_data_ptr, align_offset, skb->data); - - - /* Check if there is enough headroom... */ - if (unlikely(skb_headroom(skb) < align_offset)) - { - struct sk_buff *tmp = skb; - - unifi_trace(priv, UDBG5, "Headroom not enough - realloc it\n"); - skb = skb_realloc_headroom(skb, align_offset); - if (skb == NULL) { - unifi_error(priv, - "_align_bulk_data_buffers: skb_realloc_headroom failed - signal is dropped\n"); - return -EFAULT; - } - /* Free the old bulk data only if allocation succeeds */ - kfree_skb(tmp); - /* Bulkdata needs to point to the new skb */ - bulkdata->d[i].os_net_buf_ptr = (const unsigned char*)skb; - bulkdata->d[i].os_data_ptr = (const void*)skb->data; - } - /* ... before pushing the data to the right alignment offset */ - skb_push(skb, align_offset); - - } - /* The direction bit is zero for the from-host */ - signal[SIZEOF_SIGNAL_HEADER + (i * SIZEOF_DATAREF) + 1] = align_offset; - - } - return 0; -} /* _align_bulk_data_buffers() */ - - -/* - * --------------------------------------------------------------------------- - * ul_send_signal_unpacked - * - * This function sends a host formatted signal to unifi. - * - * Arguments: - * priv Pointer to driver's private data. - * sigptr Pointer to the signal. - * bulkdata Pointer to the signal's bulk data. - * - * Returns: - * O on success, error code otherwise. - * - * Notes: - * The signals have to be sent in the format described in the host interface - * specification, i.e wire formatted. Certain clients use the host formatted - * structures. The write_pack() transforms the host formatted signal - * into the wired formatted signal. The code is in the core, since the signals - * are defined therefore binded to the host interface specification. - * --------------------------------------------------------------------------- - */ -int -ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, - bulk_data_param_t *bulkdata) -{ - u8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; - u16 packed_siglen; - CsrResult csrResult; - unsigned long lock_flags; - int r; - - - csrResult = write_pack(sigptr, sigbuf, &packed_siglen); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n"); - return CsrHipResultToStatus(csrResult); - } - r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata); - if (r) { - return r; - } - - spin_lock_irqsave(&priv->send_signal_lock, lock_flags); - csrResult = unifi_send_signal(priv->card, sigbuf, packed_siglen, bulkdata); - if (csrResult != CSR_RESULT_SUCCESS) { - /* free_bulkdata_buffers(priv, (bulk_data_param_t *)bulkdata); */ - spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); - return CsrHipResultToStatus(csrResult); - } - spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); - - return 0; -} /* ul_send_signal_unpacked() */ - - -/* - * --------------------------------------------------------------------------- - * reset_driver_status - * - * This function is called from ul_send_signal_raw() when it detects - * that the SME has sent a MLME-RESET request. - * - * Arguments: - * priv Pointer to device private struct - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -static void -reset_driver_status(unifi_priv_t *priv) -{ - priv->sta_wmm_capabilities = 0; -#ifdef CSR_NATIVE_LINUX -#ifdef CSR_SUPPORT_WEXT - priv->wext_conf.flag_associated = 0; - priv->wext_conf.block_controlled_port = CSR_WIFI_ROUTER_PORT_ACTION_8021X_PORT_OPEN; - priv->wext_conf.bss_wmm_capabilities = 0; - priv->wext_conf.disable_join_on_ssid_set = 0; -#endif -#endif -} /* reset_driver_status() */ - - -/* - * --------------------------------------------------------------------------- - * ul_send_signal_raw - * - * This function sends a wire formatted data signal to unifi. - * - * Arguments: - * priv Pointer to driver's private data. - * sigptr Pointer to the signal. - * siglen Length of the signal. - * bulkdata Pointer to the signal's bulk data. - * - * Returns: - * O on success, error code otherwise. - * --------------------------------------------------------------------------- - */ -int -ul_send_signal_raw(unifi_priv_t *priv, unsigned char *sigptr, int siglen, - bulk_data_param_t *bulkdata) -{ - CsrResult csrResult; - unsigned long lock_flags; - int r; - - /* - * Make sure that the signal is updated with the bulk data - * alignment for DMA. - */ - r = _align_bulk_data_buffers(priv, (u8*)sigptr, bulkdata); - if (r) { - return r; - } - - spin_lock_irqsave(&priv->send_signal_lock, lock_flags); - csrResult = unifi_send_signal(priv->card, sigptr, siglen, bulkdata); - if (csrResult != CSR_RESULT_SUCCESS) { - free_bulkdata_buffers(priv, bulkdata); - spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); - return CsrHipResultToStatus(csrResult); - } - spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags); - - /* - * Since this is use by unicli, if we get an MLME reset request - * we need to initialize a few status parameters - * that the driver uses to make decisions. - */ - if (GET_SIGNAL_ID(sigptr) == CSR_MLME_RESET_REQUEST_ID) { - reset_driver_status(priv); - } - - return 0; -} /* ul_send_signal_raw() */ - - diff --git a/drivers/staging/csr/unifi_clients.h b/drivers/staging/csr/unifi_clients.h deleted file mode 100644 index df853e160ea5..000000000000 --- a/drivers/staging/csr/unifi_clients.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - ***************************************************************************** - * - * FILE : unifi_clients.h - * - * PURPOSE : Private header file for unifi clients. - * - * UDI = UniFi Debug Interface - * - * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - ***************************************************************************** - */ -#ifndef __LINUX_UNIFI_CLIENTS_H__ -#define __LINUX_UNIFI_CLIENTS_H__ 1 - -#include - -#define MAX_UDI_CLIENTS 8 - -/* The start of the range of process ids allocated for ul clients */ -#define UDI_SENDER_ID_BASE 0xC000 -#define UDI_SENDER_ID_SHIFT 8 - - -/* Structure to hold a UDI logged signal */ -typedef struct { - - /* List link structure */ - struct list_head q; - - /* The message that will be passed to the user app */ - udi_msg_t msg; - - /* Signal body and data follow */ - -} udi_log_t; - - - -typedef struct ul_client ul_client_t; - -typedef void (*udi_event_t)(ul_client_t *client, - const u8 *sigdata, int signal_len, - const bulk_data_param_t *bulkdata, - int dir); - -void logging_handler(void *ospriv, - u8 *sigdata, u32 signal_len, - const bulk_data_param_t *bulkdata, - enum udi_log_direction direction); - - -/* - * Structure describing a bulk data slot. - * The length field is used to indicate empty/occupied state. - */ -typedef struct _bulk_data -{ - unsigned char ptr[2000]; - unsigned int length; -} bulk_data_t; - - -struct ul_client { - /* Index of this client in the ul_clients array. */ - int client_id; - - /* Index of UniFi device to which this client is attached. */ - int instance; - - /* Flag to say whether this client has been enabled. */ - int udi_enabled; - - /* Value to use in signal->SenderProcessId */ - int sender_id; - - /* Configuration flags, e.g blocking, logging, etc. */ - unsigned int configuration; - - udi_event_t event_hook; - - /* A list to hold signals received from UniFi for reading by read() */ - struct list_head udi_log; - - /* Semaphore to protect the udi_log list */ - struct semaphore udi_sem; - - /* - * Linux waitqueue to support blocking read and poll. - * Logging clients should wait on udi_log. while - * blocking clients should wait on wake_up_wq. - */ - wait_queue_head_t udi_wq; - CSR_SIGNAL* reply_signal; - bulk_data_t* reply_bulkdata[UNIFI_MAX_DATA_REFERENCES]; - - u16 signal_filter[SIG_FILTER_SIZE]; - - - /* ------------------------------------------------------------------- */ - /* Code below here is used by the sme_native configuration only */ - - /* Flag to wake up blocking clients waiting on udi_wq. */ - int wake_up_wq_id; - - /* - * A 0x00 - 0x0F mask to apply in signal->SenderProcessId. - * Every time we do a blocking mlme request we increase this value. - * The mlme_wait_for_reply() will wait for this sequence number. - * Only the MLME blocking functions update this field. - */ - unsigned char seq_no; - - /* - * A 0x00 - 0x0F counter, containing the sequence number of - * the signal that this client has last received. - * Only the MLME blocking functions update this field. - */ - unsigned char wake_seq_no; - - unifiio_snap_filter_t snap_filter; -}; /* struct ul_client */ - - -#endif /* __LINUX_UNIFI_CLIENTS_H__ */ diff --git a/drivers/staging/csr/unifi_config.h b/drivers/staging/csr/unifi_config.h deleted file mode 100644 index fe119707844a..000000000000 --- a/drivers/staging/csr/unifi_config.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * - * FILE: unifi_config.h - * - * PURPOSE: - * This header file provides parameters that configure the operation - * of the driver. - * - * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#ifndef __UNIFI_CONFIG_H__ -#define __UNIFI_CONFIG_H__ 1 - -/* - * Override for the SDIO function block size on this host. When byte mode CMD53s - * are not used/supported by the SD host controller, transfers are padded up to - * the next block boundary. The 512-byte default on UF6xxx wastes too much space - * on the chip, so the block size is reduced to support this configuration. - */ -#define CSR_WIFI_HIP_SDIO_BLOCK_SIZE 64 - -/* Define the number of mini-coredump buffers to allocate at startup. These are - * used to record chip status for the last n unexpected resets. - */ -#define CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS 5 - - -#endif /* __UNIFI_CONFIG_H__ */ diff --git a/drivers/staging/csr/unifi_dbg.c b/drivers/staging/csr/unifi_dbg.c deleted file mode 100644 index 38d57085a26a..000000000000 --- a/drivers/staging/csr/unifi_dbg.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * *************************************************************************** - * FILE: unifi_dbg.c - * - * PURPOSE: - * Handle debug signals received from UniFi. - * - * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ -#include "unifi_priv.h" - -/* - * --------------------------------------------------------------------------- - * debug_string_indication - * debug_word16_indication - * - * Handlers for debug indications. - * - * Arguments: - * priv Pointer to private context structure. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -debug_string_indication(unifi_priv_t *priv, const unsigned char *extra, unsigned int extralen) -{ - const unsigned int maxlen = sizeof(priv->last_debug_string) - 1; - - if (extralen > maxlen) { - extralen = maxlen; - } - - strncpy(priv->last_debug_string, extra, extralen); - - /* Make sure the string is terminated */ - priv->last_debug_string[extralen] = '\0'; - - unifi_info(priv, "unifi debug: %s\n", priv->last_debug_string); - -} /* debug_string_indication() */ - - - -void -debug_word16_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr) -{ - int i; - - if (priv == NULL) { - unifi_info(priv, "Priv is NULL\n"); - return; - } - - for (i = 0; i < 16; i++) { - priv->last_debug_word16[i] = - sigptr->u.DebugWord16Indication.DebugWords[i]; - } - - if (priv->last_debug_word16[0] == 0xFA11) { - unsigned long ts; - ts = (priv->last_debug_word16[6] << 16) | priv->last_debug_word16[5]; - unifi_info(priv, " %10lu: %s fault %04x, arg %04x (x%d)\n", - ts, - priv->last_debug_word16[3] == 0x8000 ? "MAC" : - priv->last_debug_word16[3] == 0x4000 ? "PHY" : - "???", - priv->last_debug_word16[1], - priv->last_debug_word16[2], - priv->last_debug_word16[4]); - } - else if (priv->last_debug_word16[0] != 0xDBAC) - /* suppress SDL Trace output (note: still available to unicli). */ - { - unifi_info(priv, "unifi debug: %04X %04X %04X %04X %04X %04X %04X %04X\n", - priv->last_debug_word16[0], priv->last_debug_word16[1], - priv->last_debug_word16[2], priv->last_debug_word16[3], - priv->last_debug_word16[4], priv->last_debug_word16[5], - priv->last_debug_word16[6], priv->last_debug_word16[7]); - unifi_info(priv, " %04X %04X %04X %04X %04X %04X %04X %04X\n", - priv->last_debug_word16[8], priv->last_debug_word16[9], - priv->last_debug_word16[10], priv->last_debug_word16[11], - priv->last_debug_word16[12], priv->last_debug_word16[13], - priv->last_debug_word16[14], priv->last_debug_word16[15]); - } - -} /* debug_word16_indication() */ - - -void -debug_generic_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr) -{ - unifi_info(priv, "debug: %04X %04X %04X %04X %04X %04X %04X %04X\n", - sigptr->u.DebugGenericIndication.DebugWords[0], - sigptr->u.DebugGenericIndication.DebugWords[1], - sigptr->u.DebugGenericIndication.DebugWords[2], - sigptr->u.DebugGenericIndication.DebugWords[3], - sigptr->u.DebugGenericIndication.DebugWords[4], - sigptr->u.DebugGenericIndication.DebugWords[5], - sigptr->u.DebugGenericIndication.DebugWords[6], - sigptr->u.DebugGenericIndication.DebugWords[7]); - -} /* debug_generic_indication() */ - diff --git a/drivers/staging/csr/unifi_event.c b/drivers/staging/csr/unifi_event.c deleted file mode 100644 index 71fdb2180e3d..000000000000 --- a/drivers/staging/csr/unifi_event.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * *************************************************************************** - * FILE: unifi_event.c - * - * PURPOSE: - * Process the signals received by UniFi. - * It is part of the porting exercise. - * - * Copyright (C) 2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ - - -/* - * Porting notes: - * The implementation of unifi_receive_event() in Linux is fairly complicated. - * The linux driver support multiple userspace applications and several - * build configurations, so the received signals are processed by different - * processes and multiple times. - * In a simple implementation, this function needs to deliver: - * - The MLME-UNITDATA.ind signals to the Rx data plane and to the Traffic - * Analysis using unifi_ta_sample(). - * - The MLME-UNITDATA-STATUS.ind signals to the Tx data plane. - * - All the other signals to the SME using unifi_sys_hip_ind(). - */ - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "unifi_priv.h" - - -/* - * --------------------------------------------------------------------------- - * send_to_client - * - * Helper for unifi_receive_event. - * - * This function forwards a signal to one client. - * - * Arguments: - * priv Pointer to driver's private data. - * client Pointer to the client structure. - * receiver_id The reciever id of the signal. - * sigdata Pointer to the packed signal buffer. - * siglen Length of the packed signal. - * bulkdata Pointer to the signal's bulk data. - * - * Returns: - * None. - * - * --------------------------------------------------------------------------- - */ -static void send_to_client(unifi_priv_t *priv, ul_client_t *client, - int receiver_id, - unsigned char *sigdata, int siglen, - const bulk_data_param_t *bulkdata) -{ - if (client && client->event_hook) { - /*unifi_trace(priv, UDBG3, - "Receive: client %d, (s:0x%X, r:0x%X) - Signal 0x%.4X \n", - client->client_id, client->sender_id, receiver_id, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));*/ - - client->event_hook(client, sigdata, siglen, bulkdata, UDI_TO_HOST); - } -} - -/* - * --------------------------------------------------------------------------- - * process_pkt_data_ind - * - * Dispatcher for received signals. - * - * This function receives the 'to host' signals and forwards - * them to the unifi linux clients. - * - * Arguments: - * priv Context - * sigdata Pointer to the packed signal buffer(Its in form of MA-PACKET.ind). - * bulkdata Pointer to signal's bulkdata - * freeBulkData Pointer to a flag which gets set if the bulkdata needs to - * be freed after calling the logging handlers. If it is not - * set the bulkdata must be freed by the MLME handler or - * passed to the network stack. - * Returns: - * TRUE if the packet should be routed to the SME etc. - * FALSE if the packet is for the driver or network stack - * --------------------------------------------------------------------------- - */ -static u8 check_routing_pkt_data_ind(unifi_priv_t *priv, - u8 *sigdata, - const bulk_data_param_t* bulkdata, - u8 *freeBulkData, - netInterface_priv_t *interfacePriv) -{ - u16 frmCtrl, receptionStatus, frmCtrlSubType; - u8 *macHdrLocation; - u8 interfaceTag; - u8 isDataFrame; - u8 isProtocolVerInvalid = FALSE; - u8 isDataFrameSubTypeNoData = FALSE; - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - static const u8 wapiProtocolIdSNAPHeader[] = {0x88, 0xb4}; - static const u8 wapiProtocolIdSNAPHeaderOffset = 6; - u8 *destAddr; - u8 *srcAddr; - u8 isWapiUnicastPkt = FALSE; - -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - u16 qosControl; -#endif - - u8 llcSnapHeaderOffset = 0; - - destAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - srcAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; - - /*Individual/Group bit - Bit 0 of first byte*/ - isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; -#endif - -#define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 - - *freeBulkData = FALSE; - - /* Fetch the MAC header location from MA_PKT_IND packet */ - macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr; - /* Fetch the Frame Control value from MAC header */ - frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); - - /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; - - /* check for MIC failure before processing the signal */ - receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET); - - /* To discard any spurious MIC failures that could be reported by the firmware */ - isDataFrame = ((frmCtrl & IEEE80211_FC_TYPE_MASK) == (IEEE802_11_FC_TYPE_DATA & IEEE80211_FC_TYPE_MASK)) ? TRUE : FALSE; - /* 0x00 is the only valid protocol version*/ - isProtocolVerInvalid = (frmCtrl & IEEE80211_FC_PROTO_VERSION_MASK) ? TRUE : FALSE; - frmCtrlSubType = (frmCtrl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET; - /*Exclude the no data & reserved sub-types from MIC failure processing*/ - isDataFrameSubTypeNoData = (((frmCtrlSubType>0x03)&&(frmCtrlSubType<0x08)) || (frmCtrlSubType>0x0B)) ? TRUE : FALSE; - if ((receptionStatus == CSR_MICHAEL_MIC_ERROR) && - ((!isDataFrame) || isProtocolVerInvalid || (isDataFrame && isDataFrameSubTypeNoData))) { - /* Currently MIC errors are discarded for frames other than data frames. This might need changing when we start - * supporting 802.11w (Protected Management frames) - */ - *freeBulkData = TRUE; - unifi_trace(priv, UDBG4, "Discarding this frame and ignoring the MIC failure as this is a garbage/non-data/no data frame\n"); - return FALSE; - } - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - if (receptionStatus == CSR_MICHAEL_MIC_ERROR) { - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { - -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - if ((isDataFrame) && - ((IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK) == (frmCtrl & IEEE80211_FC_SUBTYPE_MASK)) && - (priv->isWapiConnection)) - { - qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation + (((frmCtrl & IEEE802_11_FC_TO_DS_MASK) && (frmCtrl & IEEE802_11_FC_FROM_DS_MASK)) ? 30 : 24) ); - - unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind() :: Value of the QoS control field - 0x%04x \n", qosControl); - - if (qosControl & IEEE802_11_QC_NON_TID_BITS_MASK) - { - unifi_trace(priv, UDBG4, "Ignore the MIC failure and pass the MPDU to the stack when any of bits [4-15] is set in the QoS control field\n"); - - /*Exclude the MIC [16] and the PN [16] that are appended by the firmware*/ - ((bulk_data_param_t*)bulkdata)->d[0].data_length = bulkdata->d[0].data_length - 32; - - /*Clear the reception status of the signal (CSR_RX_SUCCESS)*/ - *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET) = 0x00; - *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET+1) = 0x00; - - *freeBulkData = FALSE; - - return FALSE; - } - } -#endif - /* If this MIC ERROR reported by the firmware is either for - * [1] a WAPI Multicast MPDU and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR - * [2] a WAPI Unicast MPDU and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set - * then report a MIC FAILURE indication to the SME. - */ -#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION - if ((priv->wapi_multicast_filter == 0) || isWapiUnicastPkt) { -#else - /*When SW encryption is enabled and USKID=1 (wapi_unicast_filter = 1), we are expected - *to receive MIC failure INDs for unicast MPDUs*/ - if ( ((priv->wapi_multicast_filter == 0) && !isWapiUnicastPkt) || - ((priv->wapi_unicast_filter == 0) && isWapiUnicastPkt) ) { -#endif - /*Discard the frame*/ - *freeBulkData = TRUE; - unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n"); - - if (isWapiUnicastPkt && - ((uf_sme_port_state(priv, srcAddr, UF_CONTROLLED_PORT_Q, interfaceTag) != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN)|| -#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION - (priv->wapi_unicast_filter) || -#endif - (priv->wapi_unicast_queued_pkt_filter))) { - - /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP - * while we are in the process of re-association induced by unsupported WAPI Unicast key index - * - Discard the packets with MIC failures "until" we have - * a. negotiated a key, - * b. opened the CONTROL PORT and - * c. the AP has started using the new key - */ - unifi_trace(priv, UDBG4, "Ignoring the MIC failure as either a. CONTROL PORT isn't OPEN or b. Unicast filter is set or c. WAPI AP using old key for buffered pkts\n"); - - /*Ignore this MIC failure*/ - return FALSE; - - }/*WAPI re-key specific workaround*/ - - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", - interfaceTag, srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3], srcAddr[4], srcAddr[5]); - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Dest Addr %x:%x:%x:%x:%x:%x\n", - destAddr[0], destAddr[1], destAddr[2], destAddr[3], destAddr[4], destAddr[5]); - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Control Port State - 0x%.4X \n", - uf_sme_port_state(priv, srcAddr, UF_CONTROLLED_PORT_Q, interfaceTag)); - - unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); - - /*Report the MIC failure to the SME*/ - return TRUE; - } - }/* STA mode */ - else { - /* Its AP Mode . Just Return */ - *freeBulkData = TRUE; - unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); - return TRUE; - } /* AP mode */ - }/* MIC error */ -#else - if (receptionStatus == CSR_MICHAEL_MIC_ERROR) { - *freeBulkData = TRUE; - unifi_error(priv, "MIC failure in %s\n", __FUNCTION__); - return TRUE; - } -#endif /*CSR_WIFI_SECURITY_WAPI_ENABLE*/ - - unifi_trace(priv, UDBG4, "frmCtrl = 0x%04x %s\n", - frmCtrl, - (((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) == IEEE802_11_FRAMETYPE_MANAGEMENT) ? - "Mgt" : "Ctrl/Data"); - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /* To ignore MIC failures reported due to the WAPI AP using the old key for queued packets before - * starting to use the new key negotiated as part of unicast re-keying - */ - if ((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA)&& - isWapiUnicastPkt && - (receptionStatus == CSR_RX_SUCCESS) && - (priv->wapi_unicast_queued_pkt_filter==1)) { - - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI unicast pkt received when the (wapi_unicast_queued_pkt_filter) is set\n"); - - if (isDataFrame) { - switch(frmCtrl & IEEE80211_FC_SUBTYPE_MASK) { - case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: - llcSnapHeaderOffset = MAC_HEADER_SIZE + 2; - break; - case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK: - case IEEE802_11_FC_TYPE_NULL & IEEE80211_FC_SUBTYPE_MASK: - break; - default: - llcSnapHeaderOffset = MAC_HEADER_SIZE; - } - } - - if (llcSnapHeaderOffset > 0) { - /* QoS data or Data */ - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): SNAP header found & its offset %d\n", llcSnapHeaderOffset); - if (memcmp((u8 *)(bulkdata->d[0].os_data_ptr+llcSnapHeaderOffset+wapiProtocolIdSNAPHeaderOffset), - wapiProtocolIdSNAPHeader, sizeof(wapiProtocolIdSNAPHeader))) { - - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): This is a data & NOT a WAI protocol packet\n"); - /* On the first unicast data pkt that is decrypted successfully after re-keying, reset the filter */ - priv->wapi_unicast_queued_pkt_filter = 0; - unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind(): WAPI AP has started using the new unicast key, no more MIC failures expected (reset filter)\n"); - } - else { - unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI - This is a WAI protocol packet\n"); - } - } - } -#endif - - - switch ((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) { - case IEEE802_11_FRAMETYPE_MANAGEMENT: - *freeBulkData = TRUE; /* Free (after SME handler copies it) */ - - /* In P2P device mode, filter the legacy AP beacons here */ - if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2P)&&\ - ((CSR_WIFI_80211_GET_FRAME_SUBTYPE(macHdrLocation)) == CSR_WIFI_80211_FRAME_SUBTYPE_BEACON)){ - - u8 *pSsid, *pSsidLen; - static u8 P2PWildCardSsid[CSR_WIFI_P2P_WILDCARD_SSID_LENGTH] = {'D', 'I', 'R', 'E', 'C', 'T', '-'}; - - pSsidLen = macHdrLocation + MAC_HEADER_SIZE + CSR_WIFI_BEACON_FIXED_LENGTH; - pSsid = pSsidLen + 2; - - if(*(pSsidLen + 1) >= CSR_WIFI_P2P_WILDCARD_SSID_LENGTH){ - if(memcmp(pSsid, P2PWildCardSsid, CSR_WIFI_P2P_WILDCARD_SSID_LENGTH) == 0){ - unifi_trace(priv, UDBG6, "Received a P2P Beacon, pass it to SME\n"); - return TRUE; - } - } - unifi_trace(priv, UDBG6, "Received a Legacy AP beacon in P2P mode, drop it\n"); - return FALSE; - } - return TRUE; /* Route to SME */ - case IEEE802_11_FRAMETYPE_DATA: - case IEEE802_11_FRAMETYPE_CONTROL: - *freeBulkData = FALSE; /* Network stack or MLME handler frees */ - return FALSE; - default: - unifi_error(priv, "Unhandled frame type %04x\n", frmCtrl); - *freeBulkData = TRUE; /* Not interested, but must free it */ - return FALSE; - } -} - -/* - * --------------------------------------------------------------------------- - * unifi_process_receive_event - * - * Dispatcher for received signals. - * - * This function receives the 'to host' signals and forwards - * them to the unifi linux clients. - * - * Arguments: - * ospriv Pointer to driver's private data. - * sigdata Pointer to the packed signal buffer. - * siglen Length of the packed signal. - * bulkdata Pointer to the signal's bulk data. - * - * Returns: - * None. - * - * Notes: - * The signals are received in the format described in the host interface - * specification, i.e wire formatted. Certain clients use the same format - * to interpret them and other clients use the host formatted structures. - * Each client has to call read_unpack_signal() to transform the wire - * formatted signal into the host formatted signal, if necessary. - * The code is in the core, since the signals are defined therefore - * binded to the host interface specification. - * --------------------------------------------------------------------------- - */ -static void -unifi_process_receive_event(void *ospriv, - u8 *sigdata, u32 siglen, - const bulk_data_param_t *bulkdata) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - int i, receiver_id; - int client_id; - s16 signal_id; - u8 pktIndToSme = FALSE, freeBulkData = FALSE; - - unifi_trace(priv, UDBG5, "unifi_process_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF, - siglen); - - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)) & 0xFF00; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; - signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); - - - - /* check for the type of frame received (checks for 802.11 management frames) */ - if (signal_id == CSR_MA_PACKET_INDICATION_ID) - { -#define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14 - u8 interfaceTag; - netInterface_priv_t *interfacePriv; - - /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Update activity for this station in case of IBSS */ -#ifdef CSR_SUPPORT_SME - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) - { - u8 *saddr; - /* Fetch the source address from mac header */ - saddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; - unifi_trace(priv, UDBG5, - "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", - interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]); - - uf_update_sta_activity(priv, interfaceTag, saddr); - } -#endif - - pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); - - unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); - - } - - if (pktIndToSme) - { - /* Management MA_PACKET_IND for SME */ - if(sigdata != NULL && bulkdata != NULL){ - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); - } - else{ - unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); - } -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif - } - else - { - /* Signals with ReceiverId==0 are also reported to SME / WEXT, - * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs - */ - if (!receiver_id) { - if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) { - uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); - } - else if (signal_id != CSR_MA_PACKET_INDICATION_ID) { - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif - } - else - { - -#if (defined(CSR_SUPPORT_SME) && defined(CSR_WIFI_SECURITY_WAPI_ENABLE)) - #define CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 - netInterface_priv_t *interfacePriv; - u8 interfaceTag; - u16 receptionStatus = CSR_RX_SUCCESS; - - /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* check for MIC failure */ - receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET); - - /* Send a WAPI MPDU to SME for re-check MIC if the respective filter has been set*/ - if ((!freeBulkData) && - (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) && - (receptionStatus == CSR_MICHAEL_MIC_ERROR) && - ((priv->wapi_multicast_filter == 1) -#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION - || (priv->wapi_unicast_filter == 1) -#endif - )) - { - CSR_SIGNAL signal; - u8 *destAddr; - CsrResult res; - u16 interfaceTag = 0; - u8 isMcastPkt = TRUE; - - unifi_trace(priv, UDBG6, "Received a WAPI data packet when the Unicast/Multicast filter is set\n"); - res = read_unpack_signal(sigdata, &signal); - if (res) { - unifi_error(priv, "Received unknown or corrupted signal (0x%x).\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata)); - return; - } - - /* Check if the type of MPDU and the respective filter status*/ - destAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - isMcastPkt = (destAddr[0] & 0x01) ? TRUE : FALSE; - unifi_trace(priv, UDBG6, - "1.MPDU type: (%s), 2.Multicast filter: (%s), 3. Unicast filter: (%s)\n", - ((isMcastPkt) ? "Multiast":"Unicast"), - ((priv->wapi_multicast_filter) ? "Enabled":"Disabled"), - ((priv->wapi_unicast_filter) ? "Enabled":"Disabled")); - - if (((isMcastPkt) && (priv->wapi_multicast_filter == 1)) -#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION - || ((!isMcastPkt) && (priv->wapi_unicast_filter == 1)) -#endif - ) - { - unifi_trace(priv, UDBG4, "Sending the WAPI MPDU for MIC check\n"); - CsrWifiRouterCtrlWapiRxMicCheckIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (u8*)bulkdata->d[0].os_data_ptr); - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - return; - } - } /* CSR_MA_PACKET_INDICATION_ID */ -#endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/ - } - } - - /* calls the registered clients handler callback func. - * netdev_mlme_event_handler is one of the registered handler used to route - * data packet to network stack or AMP/EAPOL related data to SME - * - * The freeBulkData check ensures that, it has received a management frame and - * the frame needs to be freed here. So not to be passed to netdev handler - */ - if(!freeBulkData){ - if ((client_id < MAX_UDI_CLIENTS) && - (&priv->ul_clients[client_id] != priv->logging_client)) { - unifi_trace(priv, UDBG6, "Call the registered clients handler callback func\n"); - send_to_client(priv, &priv->ul_clients[client_id], - receiver_id, - sigdata, siglen, bulkdata); - } - } - } - - /* - * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION - */ - switch (signal_id) - { -#ifdef UNIFI_SNIFF_ARPHRD - case CSR_MA_SNIFFDATA_INDICATION_ID: -#endif - break; - - case CSR_MA_PACKET_INDICATION_ID: - if (!freeBulkData) - { - break; - } - /* FALLS THROUGH... */ - default: - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - } - -} /* unifi_process_receive_event() */ - - -#ifdef CSR_WIFI_RX_PATH_SPLIT -static u8 signal_buffer_is_full(unifi_priv_t* priv) -{ - return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); -} - -void unifi_rx_queue_flush(void *ospriv) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - priv->rxSignalBuffer.readPointer, priv->rxSignalBuffer.writePointer); - if(priv != NULL) { - u8 readPointer = priv->rxSignalBuffer.readPointer; - while (readPointer != priv->rxSignalBuffer.writePointer) - { - rx_buff_struct_t *buf = &priv->rxSignalBuffer.rx_buff[readPointer]; - unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - readPointer, priv->rxSignalBuffer.writePointer); - unifi_process_receive_event(priv, buf->bufptr, buf->sig_len, &buf->data_ptrs); - readPointer ++; - if(readPointer >= priv->rxSignalBuffer.size) { - readPointer = 0; - } - } - priv->rxSignalBuffer.readPointer = readPointer; - } -} - -void rx_wq_handler(struct work_struct *work) -{ - unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct); - unifi_rx_queue_flush(priv); -} -#endif - - - -/* - * --------------------------------------------------------------------------- - * unifi_receive_event - * - * Dispatcher for received signals. - * - * This function receives the 'to host' signals and forwards - * them to the unifi linux clients. - * - * Arguments: - * ospriv Pointer to driver's private data. - * sigdata Pointer to the packed signal buffer. - * siglen Length of the packed signal. - * bulkdata Pointer to the signal's bulk data. - * - * Returns: - * None. - * - * Notes: - * The signals are received in the format described in the host interface - * specification, i.e wire formatted. Certain clients use the same format - * to interpret them and other clients use the host formatted structures. - * Each client has to call read_unpack_signal() to transform the wire - * formatted signal into the host formatted signal, if necessary. - * The code is in the core, since the signals are defined therefore - * binded to the host interface specification. - * --------------------------------------------------------------------------- - */ -void -unifi_receive_event(void *ospriv, - u8 *sigdata, u32 siglen, - const bulk_data_param_t *bulkdata) -{ -#ifdef CSR_WIFI_RX_PATH_SPLIT - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - u8 writePointer; - int i; - rx_buff_struct_t * rx_buff; - - unifi_trace(priv, UDBG5, "unifi_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF, siglen); - if(signal_buffer_is_full(priv)) { - unifi_error(priv, "TO HOST signal queue FULL dropping the PDU\n"); - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - return; - } - writePointer = priv->rxSignalBuffer.writePointer; - rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; - memcpy(rx_buff->bufptr, sigdata, siglen); - rx_buff->sig_len = siglen; - rx_buff->data_ptrs = *bulkdata; - writePointer++; - if(writePointer >= priv->rxSignalBuffer.size) { - writePointer =0; - } - unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n", priv->rxSignalBuffer.writePointer); - priv->rxSignalBuffer.writePointer = writePointer; - -#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ - queue_work(priv->rx_workqueue, &priv->rx_work_struct); -#endif - -#else - unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata); -#endif -} /* unifi_receive_event() */ - diff --git a/drivers/staging/csr/unifi_native.h b/drivers/staging/csr/unifi_native.h deleted file mode 100644 index a73b38e5e480..000000000000 --- a/drivers/staging/csr/unifi_native.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - ***************************************************************************** - * - * FILE : unifi_native.h - * - * PURPOSE : Private header file for unifi driver support to wireless extensions. - * - * UDI = UniFi Debug Interface - * - * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - ***************************************************************************** - */ -#ifndef __LINUX_UNIFI_NATIVE_H__ -#define __LINUX_UNIFI_NATIVE_H__ 1 - -#include -#include - - -/* - * scan.c wext.c autojoin.c - */ -/* Structure to hold results of a scan */ -typedef struct scan_info { - -/* CSR_MLME_SCAN_INDICATION msi; */ - - unsigned char *info_elems; - int info_elem_length; - -} scan_info_t; - - -#define IE_VECTOR_MAXLEN 1024 - -#ifdef CSR_SUPPORT_WEXT -/* - * Structre to hold the wireless network configuration info. - */ -struct wext_config { - - /* Requested channel when setting up an adhoc network */ - int channel; - - /* wireless extns mode: IW_MODE_AUTO, ADHOC, INFRA, MASTER ... MONITOR */ - int mode; - - /* The capabilities of the currently joined network */ - int capability; - - /* The interval between beacons if we create an IBSS */ - int beacon_period; - - /* - * Power-save parameters - */ - /* The listen interval to ask for in Associate req. */ - int assoc_listen_interval; - /* Power-mode to put UniFi into */ - - unsigned char desired_ssid[UNIFI_MAX_SSID_LEN]; /* the last ESSID set by SIOCSIWESSID */ - int power_mode; - /* Whether to wake for broadcast packets (using DTIM interval) */ - int wakeup_for_dtims; - - /* Currently selected WEP Key ID (0..3) */ - int wep_key_id; - - wep_key_t wep_keys[NUM_WEPKEYS]; - -/* CSR_AUTHENTICATION_TYPE auth_type; */ - int privacy; - - u32 join_failure_timeout; - u32 auth_failure_timeout; - u32 assoc_failure_timeout; - - unsigned char generic_ie[IE_VECTOR_MAXLEN]; - int generic_ie_len; - - struct iw_statistics wireless_stats; - - - /* the ESSID we are currently associated to */ - unsigned char current_ssid[UNIFI_MAX_SSID_LEN]; - /* the BSSID we are currently associated to */ - unsigned char current_bssid[6]; - - /* - * IW_AUTH_WPA_VERSION_DISABLED 0x00000001 - * IW_AUTH_WPA_VERSION_WPA 0x00000002 - * IW_AUTH_WPA_VERSION_WPA2 0x00000004 - */ - unsigned char wpa_version; - - /* - * cipher selection: - * IW_AUTH_CIPHER_NONE 0x00000001 - * IW_AUTH_CIPHER_WEP40 0x00000002 - * IW_AUTH_CIPHER_TKIP 0x00000004 - * IW_AUTH_CIPHER_CCMP 0x00000008 - * IW_AUTH_CIPHER_WEP104 0x00000010 - */ - unsigned char pairwise_cipher_used; - unsigned char group_cipher_used; - - unsigned int frag_thresh; - unsigned int rts_thresh; - - /* U-APSD value, send with Association Request to WMM Enabled APs */ - unsigned char wmm_bss_uapsd_mask; - /* The WMM capabilities of the selected BSS */ - unsigned int bss_wmm_capabilities; - - /* Flag to prevent a join when the ssid is set */ - int disable_join_on_ssid_set; - - /* Scan info */ -#define UNIFI_MAX_SCANS 32 - scan_info_t scan_list[UNIFI_MAX_SCANS]; - int num_scan_info; - - /* Flag on whether non-802.1x packets are allowed out */ -/* CsrWifiRouterPortAction block_controlled_port;*/ - - /* Flag on whether we have completed an authenticate/associate process */ - unsigned int flag_associated : 1; -}; /* struct wext_config */ - -#endif /* CSR_SUPPORT_WEXT */ - - -/* - * wext.c - */ -/*int mlme_set_protection(unifi_priv_t *priv, unsigned char *addr, - CSR_PROTECT_TYPE prot, CSR_KEY_TYPE key_type); -*/ - -/* - * scan.c - */ -/* -void unifi_scan_indication_handler(unifi_priv_t *priv, - const CSR_MLME_SCAN_INDICATION *msg, - const unsigned char *extra, - unsigned int len); -*/ -void unifi_clear_scan_table(unifi_priv_t *priv); -scan_info_t *unifi_get_scan_report(unifi_priv_t *priv, int index); - - -/* - * Utility functions - */ -const unsigned char *unifi_find_info_element(int id, - const unsigned char *info, - int len); -int unifi_add_info_element(unsigned char *info, - int ie_id, - const unsigned char *ie_data, - int ie_len); - -/* - * autojoin.c - */ -/* Higher level fns */ -int unifi_autojoin(unifi_priv_t *priv, const char *ssid); -/* -int unifi_do_scan(unifi_priv_t *priv, int scantype, CSR_BSS_TYPE bsstype, - const char *ssid, int ssid_len); -*/ -int unifi_set_powermode(unifi_priv_t *priv); -int unifi_join_ap(unifi_priv_t *priv, scan_info_t *si); -int unifi_join_bss(unifi_priv_t *priv, unsigned char *macaddr); -int unifi_leave(unifi_priv_t *priv); -unsigned int unifi_get_wmm_bss_capabilities(unifi_priv_t *priv, - unsigned char *ie_vector, - int ie_len, int *ap_capabilities); - -/* - * Status and management. - */ -int uf_init_wext_interface(unifi_priv_t *priv); -void uf_deinit_wext_interface(unifi_priv_t *priv); - -/* - * Function to reset UniFi's 802.11 state by sending MLME-RESET.req - */ -int unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr, unsigned char set_default_mib); - - -/* - * mlme.c - */ -/* Abort an MLME operation - useful in error recovery */ -int uf_abort_mlme(unifi_priv_t *priv); - -int unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli, - CSR_SIGNAL *sig, bulk_data_param_t *data_ptrs, - int timeout); -void unifi_mlme_copy_reply_and_wakeup_client(ul_client_t *pcli, - CSR_SIGNAL *signal, int signal_len, - const bulk_data_param_t *bulkdata); - -/* - * Utility functions - */ -const char *lookup_reason_code(int reason); -const char *lookup_result_code(int result); - - -/* - * sme_native.c - */ -int uf_sme_init(unifi_priv_t *priv); -void uf_sme_deinit(unifi_priv_t *priv); -int sme_sys_suspend(unifi_priv_t *priv); -int sme_sys_resume(unifi_priv_t *priv); -int sme_mgt_wifi_on(unifi_priv_t *priv); - -/* Callback for event logging to SME clients (unifi_manager) */ -void sme_native_log_event(ul_client_t *client, - const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata, - int dir); - -void sme_native_mlme_event_handler(ul_client_t *pcli, - const u8 *sig_packed, int sig_len, - const bulk_data_param_t *bulkdata, - int dir); - -/* Task to query statistics from the MIB */ -#define UF_SME_STATS_WQ_TIMEOUT 2000 /* in msecs */ -void uf_sme_stats_wq(struct work_struct *work); - -void uf_native_process_udi_signal(ul_client_t *pcli, - const u8 *packed_signal, - int packed_signal_len, - const bulk_data_param_t *bulkdata, int dir); -#ifdef UNIFI_SNIFF_ARPHRD -/* - * monitor.c - */ -int uf_start_sniff(unifi_priv_t *priv); -/* -void ma_sniffdata_ind(void *ospriv, - const CSR_MA_SNIFFDATA_INDICATION *ind, - const bulk_data_param_t *bulkdata); -*/ -#endif /* ARPHRD_IEEE80211_PRISM */ - -#endif /* __LINUX_UNIFI_NATIVE_H__ */ diff --git a/drivers/staging/csr/unifi_os.h b/drivers/staging/csr/unifi_os.h deleted file mode 100644 index 56a26982070e..000000000000 --- a/drivers/staging/csr/unifi_os.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * - * FILE: os_linux/unifi_os.h - * - * PURPOSE: - * This header file provides the OS-dependent facilities for a linux - * environment. - * - * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#ifndef __UNIFI_OS_LINUX_H__ -#define __UNIFI_OS_LINUX_H__ 1 - -#include -#include -#include -#include -#include - -/* - * Needed for core/signals.c - */ -#include - - -/* Define INLINE directive*/ -#define INLINE inline - -/* Malloc and free */ -CsrResult unifi_net_data_malloc(void *ospriv, bulk_data_desc_t *bulk_data_slot, unsigned int size); -void unifi_net_data_free(void *ospriv, bulk_data_desc_t *bulk_data_slot); -#define CSR_WIFI_ALIGN_BYTES 4 -CsrResult unifi_net_dma_align(void *ospriv, bulk_data_desc_t *bulk_data_slot); - -/* - * Byte Order - * Note that __le*_to_cpu and __cpu_to_le* return an unsigned value! - */ -#ifdef __KERNEL__ -#define unifi2host_16(n) (__le16_to_cpu((n))) -#define unifi2host_32(n) (__le32_to_cpu((n))) -#define host2unifi_16(n) (__cpu_to_le16((n))) -#define host2unifi_32(n) (__cpu_to_le32((n))) -#endif - -/* Module parameters */ -extern int unifi_debug; - -/* debugging */ -#ifdef UNIFI_DEBUG -/* - * unifi_debug is a verbosity level for debug messages - * UDBG0 msgs are always printed if UNIFI_DEBUG is defined - * UDBG1 msgs are printed if UNIFI_DEBUG is defined and unifi_debug > 0 - * etc. - */ - -#define ASSERT(cond) \ - do { \ - if (!(cond)) { \ - printk("Assertion failed in %s at %s:%d: %s\n", \ - __FUNCTION__, __FILE__, __LINE__, #cond); \ - } \ - } while (0) - - -void unifi_dump(void *ospriv, int lvl, const char *msg, void *mem, u16 len); -void dump(void *mem, u16 len); -void dump16(void *mem, u16 len); -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -void dump_str(void *mem, u16 len); -#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ - -void unifi_error(void* ospriv, const char *fmt, ...); -void unifi_warning(void* ospriv, const char *fmt, ...); -void unifi_notice(void* ospriv, const char *fmt, ...); -void unifi_info(void* ospriv, const char *fmt, ...); - -void unifi_trace(void* ospriv, int level, const char *fmt, ...); - -#else - -/* Stubs */ - -#define ASSERT(cond) - -static inline void unifi_dump(void *ospriv, int lvl, const char *msg, void *mem, u16 len) {} -static inline void dump(void *mem, u16 len) {} -static inline void dump16(void *mem, u16 len) {} -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -static inline void dump_str(void *mem, u16 len) {} -#endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */ - -void unifi_error_nop(void* ospriv, const char *fmt, ...); -void unifi_trace_nop(void* ospriv, int level, const char *fmt, ...); -#define unifi_error if(1);else unifi_error_nop -#define unifi_warning if(1);else unifi_error_nop -#define unifi_notice if(1);else unifi_error_nop -#define unifi_info if(1);else unifi_error_nop -#define unifi_trace if(1);else unifi_trace_nop - -#endif /* UNIFI_DEBUG */ - - -/* Different levels of diagnostic detail... */ -#define UDBG0 0 /* always prints in debug build */ -#define UDBG1 1 -#define UDBG2 2 -#define UDBG3 3 -#define UDBG4 4 -#define UDBG5 5 -#define UDBG6 6 -#define UDBG7 7 - - -#endif /* __UNIFI_OS_LINUX_H__ */ diff --git a/drivers/staging/csr/unifi_pdu_processing.c b/drivers/staging/csr/unifi_pdu_processing.c deleted file mode 100644 index 04fe9e2acf0e..000000000000 --- a/drivers/staging/csr/unifi_pdu_processing.c +++ /dev/null @@ -1,3729 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: unifi_pdu_processing.c - * - * PURPOSE: - * This file provides the PDU handling functionality before it gets sent to unfi and after - * receiving a PDU from unifi - * - * Copyright (C) 2010 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include -#include -#include - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include "csr_time.h" -#include "unifi_priv.h" -#include - -#ifdef CSR_SUPPORT_SME -static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata, - tx_buffered_packets_t* buffered_pkt) -{ - struct sk_buff *skb ; - u32 align_offset; - - if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){ - return; - } - - skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr; - align_offset = (u32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1); - if(align_offset){ - skb_pull(skb, align_offset); - } - - buffered_pkt->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; - buffered_pkt->bulkdata.data_length = bulkdata->d[0].data_length; - buffered_pkt->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; - buffered_pkt->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; -} -#endif - -void -unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, - CSR_RATE TransmitRate, CSR_CLIENT_TAG hostTag, - u16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, - CSR_PROCESS_ID leSenderProcessId, u8 *peerMacAddress, - CSR_SIGNAL *signal) -{ - - CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; - netInterface_priv_t *interfacePriv; - u8 ba_session_idx = 0; - ba_session_tx_struct *ba_session = NULL; - u8 *ba_addr = NULL; - - interfacePriv = priv->interfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG5, - "In unifi_frame_ma_packet_req, Frame for Peer: %pMF\n", - peerMacAddress); - signal->SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; - signal->SignalPrimitiveHeader.ReceiverProcessId = 0; - signal->SignalPrimitiveHeader.SenderProcessId = leSenderProcessId; - - /* Fill the MA-PACKET.req */ - req->Priority = priority; - unifi_trace(priv, UDBG3, "Tx Frame with Priority: 0x%x\n", req->Priority); - - /* A value of 0 is used for auto selection of rates. But for P2P GO case - * for action frames the rate is governed by SME. Hence instead of 0, - * the rate is filled in with the value passed here - */ - req->TransmitRate = TransmitRate; - - /* packets from netdev then no confirm required but packets from - * Nme/Sme eapol data frames requires the confirmation - */ - req->TransmissionControl = transmissionControl; - req->VirtualInterfaceIdentifier = - uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag); - memcpy(req->Ra.x, peerMacAddress, ETH_ALEN); - - if (hostTag == 0xffffffff) { - req->HostTag = interfacePriv->tag++; - req->HostTag |= 0x40000000; - unifi_trace(priv, UDBG3, "new host tag assigned = 0x%x\n", req->HostTag); - interfacePriv->tag &= 0x0fffffff; - } else { - req->HostTag = hostTag; - unifi_trace(priv, UDBG3, "host tag got from SME = 0x%x\n", req->HostTag); - } - /* check if BA session exists for the peer MAC address on same tID */ - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO){ - ba_addr = peerMacAddress; - }else{ - ba_addr = interfacePriv->bssid.a; - } - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session = interfacePriv->ba_session_tx[ba_session_idx]; - if (ba_session){ - if ((!memcmp(ba_session->macAddress.a, ba_addr, ETH_ALEN)) && (ba_session->tID == priority)){ - req->TransmissionControl |= CSR_ALLOW_BA; - break; - } - } - } - - unifi_trace(priv, UDBG5, "leaving unifi_frame_ma_packet_req\n"); -} - -#ifdef CSR_SUPPORT_SME - -#define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001 -#define TRANSMISSION_CONTROL_EOSP_MASK 0x0002 - -static -int frame_and_send_queued_pdu(unifi_priv_t* priv, tx_buffered_packets_t* buffered_pkt, - CsrWifiRouterCtrlStaInfo_t *staRecord, u8 moreData , u8 eosp) -{ - - CSR_SIGNAL signal; - bulk_data_param_t bulkdata; - int result; - u8 toDs, fromDs, macHeaderLengthInBytes = MAC_HEADER_SIZE; - u8 *qc; - u16 *fc = (u16*)(buffered_pkt->bulkdata.os_data_ptr); - unsigned long lock_flags; - unifi_trace(priv, UDBG3, "frame_and_send_queued_pdu with moreData: %d , EOSP: %d\n", moreData, eosp); - unifi_frame_ma_packet_req(priv, buffered_pkt->priority, buffered_pkt->rate, buffered_pkt->hostTag, - buffered_pkt->interfaceTag, buffered_pkt->transmissionControl, - buffered_pkt->leSenderProcessId, buffered_pkt->peerMacAddress.a, &signal); - bulkdata.d[0].os_data_ptr = buffered_pkt->bulkdata.os_data_ptr; - bulkdata.d[0].data_length = buffered_pkt->bulkdata.data_length; - bulkdata.d[0].os_net_buf_ptr = buffered_pkt->bulkdata.os_net_buf_ptr; - bulkdata.d[0].net_buf_length = buffered_pkt->bulkdata.net_buf_length; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - bulkdata.d[1].os_net_buf_ptr =0; - bulkdata.d[1].net_buf_length =0; - - if(moreData) { - *fc |= cpu_to_le16(IEEE802_11_FC_MOREDATA_MASK); - } else { - *fc &= cpu_to_le16(~IEEE802_11_FC_MOREDATA_MASK); - } - - if((staRecord != NULL)&& (staRecord->wmmOrQosEnabled == TRUE)) - { - unifi_trace(priv, UDBG3, "frame_and_send_queued_pdu WMM Enabled: %d \n", staRecord->wmmOrQosEnabled); - - toDs = (*fc & cpu_to_le16(IEEE802_11_FC_TO_DS_MASK))?1 : 0; - fromDs = (*fc & cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK))? 1: 0; - - switch(le16_to_cpu(*fc) & IEEE80211_FC_SUBTYPE_MASK) - { - case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: - case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK: - /* If both are set then the Address4 exists (only for AP) */ - if (fromDs && toDs) { - /* 6 is the size of Address4 field */ - macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6); - } else { - macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE; - } - - /* If order bit set then HT control field is the part of MAC header */ - if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { - macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE; - qc = (u8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6)); - } else { - qc = (u8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2)); - } - *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4)); - break; - default: - if (fromDs && toDs) - macHeaderLengthInBytes += 6; - } - - } - result = ul_send_signal_unpacked(priv, &signal, &bulkdata); - if(result){ - _update_buffered_pkt_params_after_alignment(priv, &bulkdata, buffered_pkt); - } - - /* Decrement the packet counts queued in driver */ - if (result != -ENOSPC) { - /* protect entire counter updation by disabling preemption */ - if (!priv->noOfPktQueuedInDriver) { - unifi_error(priv, "packets queued in driver 0 still decrementing\n"); - } else { - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - priv->noOfPktQueuedInDriver--; - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } - /* Sta Record is available for all unicast (except genericMgt Frames) & in other case its NULL */ - if (staRecord) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - if (!staRecord->noOfPktQueued) { - unifi_error(priv, "packets queued in driver per station is 0 still decrementing\n"); - } else { - staRecord->noOfPktQueued--; - } - /* if the STA alive probe frame has failed then reset the saved host tag */ - if (result){ - if (staRecord->nullDataHostTag == buffered_pkt->hostTag){ - staRecord->nullDataHostTag = INVALID_HOST_TAG; - } - } - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - - } - return result; -} -#ifdef CSR_SUPPORT_SME -static -void set_eosp_transmit_ctrl(unifi_priv_t *priv, struct list_head *txList) -{ - /* dequeue the tx data packets from the appropriate queue */ - tx_buffered_packets_t *tx_q_item = NULL; - struct list_head *listHead; - struct list_head *placeHolder; - unsigned long lock_flags; - - - unifi_trace(priv, UDBG5, "entering set_eosp_transmit_ctrl\n"); - /* check for list empty */ - if (list_empty(txList)) { - unifi_warning(priv, "In set_eosp_transmit_ctrl, the list is empty\n"); - return; - } - - /* return the last node , and modify it. */ - - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_for_each_prev_safe(listHead, placeHolder, txList) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; - tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); - unifi_trace(priv, UDBG1, - "set_eosp_transmit_ctrl Transmission Control = 0x%x hostTag = 0x%x \n", tx_q_item->transmissionControl, tx_q_item->hostTag); - unifi_trace(priv, UDBG3, "in set_eosp_transmit_ctrl no.of buffered frames %d\n", priv->noOfPktQueuedInDriver); - break; - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - unifi_trace(priv, UDBG1, "List Empty %d\n", list_empty(txList)); - unifi_trace(priv, UDBG5, "leaving set_eosp_transmit_ctrl\n"); - return; -} - -static -void send_vif_availibility_rsp(unifi_priv_t *priv, CSR_VIF_IDENTIFIER vif, CSR_RESULT_CODE resultCode) -{ - CSR_SIGNAL signal; - CSR_MA_VIF_AVAILABILITY_RESPONSE *rsp; - bulk_data_param_t *bulkdata = NULL; - int r; - - unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : invoked with resultCode = %d \n", resultCode); - - memset(&signal, 0, sizeof(CSR_SIGNAL)); - rsp = &signal.u.MaVifAvailabilityResponse; - rsp->VirtualInterfaceIdentifier = vif; - rsp->ResultCode = resultCode; - signal.SignalPrimitiveHeader.SignalId = CSR_MA_VIF_AVAILABILITY_RESPONSE_ID; - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id; - - /* Send the signal to UniFi */ - r = ul_send_signal_unpacked(priv, &signal, bulkdata); - if(r) { - unifi_error(priv, "Availibility response sending failed %x status %d\n", vif, r); - } - else { - unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : status = %d \n", r); - } -} -#endif - -static -void verify_and_accomodate_tx_packet(unifi_priv_t *priv) -{ - tx_buffered_packets_t *tx_q_item; - unsigned long lock_flags; - struct list_head *listHead, *list; - struct list_head *placeHolder; - u8 i, j, eospFramedeleted=0; - u8 thresholdExcedeDueToBroadcast = TRUE; - /* it will be made it interface Specific in the future when multi interfaces are supported , - right now interface 0 is considered */ - netInterface_priv_t *interfacePriv = priv->interfacePriv[0]; - CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; - - unifi_trace(priv, UDBG3, "entering verify_and_accomodate_tx_packet\n"); - - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - staInfo = interfacePriv->staInfo[i]; - if (staInfo && (staInfo->noOfPktQueued >= CSR_WIFI_DRIVER_MAX_PKT_QUEUING_THRESHOLD_PER_PEER)) { - /* remove the first(oldest) packet from the all the access catogory, since data - * packets for station record crossed the threshold limit (64 for AP supporting - * 8 peers) - */ - unifi_trace(priv, UDBG3, "number of station pkts queued= %d for sta id = %d\n", staInfo->noOfPktQueued, staInfo->aid); - for(j = 0; j < MAX_ACCESS_CATOGORY; j++) { - list = &staInfo->dataPdu[j]; - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_for_each_safe(listHead, placeHolder, list) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - list_del(listHead); - thresholdExcedeDueToBroadcast = FALSE; - unifi_net_data_free(priv, &tx_q_item->bulkdata); - kfree(tx_q_item); - tx_q_item = NULL; - if (!priv->noOfPktQueuedInDriver) { - unifi_error(priv, "packets queued in driver 0 still decrementing in %s\n", __FUNCTION__); - } else { - /* protection provided by spinlock */ - priv->noOfPktQueuedInDriver--; - - } - /* Sta Record is available for all unicast (except genericMgt Frames) & in other case its NULL */ - if (!staInfo->noOfPktQueued) { - unifi_error(priv, "packets queued in driver per station is 0 still decrementing in %s\n", __FUNCTION__); - } else { - spin_lock(&priv->staRecord_lock); - staInfo->noOfPktQueued--; - spin_unlock(&priv->staRecord_lock); - } - break; - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } - } - } - if (thresholdExcedeDueToBroadcast && interfacePriv->noOfbroadcastPktQueued > CSR_WIFI_DRIVER_MINIMUM_BROADCAST_PKT_THRESHOLD ) { - /* Remove the packets from genericMulticastOrBroadCastFrames queue - * (the max packets in driver is reached due to broadcast/multicast frames) - */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - if(eospFramedeleted){ - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; - tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); - unifi_trace(priv, UDBG1, "updating eosp for next packet hostTag:= 0x%x ", tx_q_item->hostTag); - eospFramedeleted =0; - break; - } - - if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK ){ - eospFramedeleted = 1; - } - unifi_trace(priv, UDBG1, "freeing of multicast packets ToC = 0x%x hostTag = 0x%x \n", tx_q_item->transmissionControl, tx_q_item->hostTag); - list_del(listHead); - unifi_net_data_free(priv, &tx_q_item->bulkdata); - kfree(tx_q_item); - priv->noOfPktQueuedInDriver--; - spin_lock(&priv->staRecord_lock); - interfacePriv->noOfbroadcastPktQueued--; - spin_unlock(&priv->staRecord_lock); - if(!eospFramedeleted){ - break; - } - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } - unifi_trace(priv, UDBG3, "leaving verify_and_accomodate_tx_packet\n"); -} - -static -CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata, - struct list_head *list, CSR_SIGNAL *signal, - u8 requeueOnSamePos) -{ - - /* queue the tx data packets on to appropriate queue */ - CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest; - tx_buffered_packets_t *tx_q_item; - unsigned long lock_flags; - - unifi_trace(priv, UDBG5, "entering enque_tx_data_pdu\n"); - if(!list) { - unifi_error(priv, "List is not specified\n"); - return CSR_RESULT_FAILURE; - } - - /* Removes aged packets & adds the incoming packet */ - if (priv->noOfPktQueuedInDriver >= CSR_WIFI_DRIVER_SUPPORT_FOR_MAX_PKT_QUEUEING) { - unifi_trace(priv, UDBG3, "number of pkts queued= %d \n", priv->noOfPktQueuedInDriver); - verify_and_accomodate_tx_packet(priv); - } - - - - tx_q_item = kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); - if (tx_q_item == NULL) { - unifi_error(priv, - "Failed to allocate %d bytes for tx packet record\n", - sizeof(tx_buffered_packets_t)); - return CSR_RESULT_FAILURE; - } - - /* disable the preemption */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - INIT_LIST_HEAD(&tx_q_item->q); - /* fill the tx_q structure members */ - tx_q_item->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr; - tx_q_item->bulkdata.data_length = bulkdata->d[0].data_length; - tx_q_item->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr; - tx_q_item->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length; - tx_q_item->interfaceTag = req->VirtualInterfaceIdentifier & 0xff; - tx_q_item->hostTag = req->HostTag; - tx_q_item->leSenderProcessId = signal->SignalPrimitiveHeader.SenderProcessId; - tx_q_item->transmissionControl = req->TransmissionControl; - tx_q_item->priority = req->Priority; - tx_q_item->rate = req->TransmitRate; - memcpy(tx_q_item->peerMacAddress.a, req->Ra.x, ETH_ALEN); - - - - if (requeueOnSamePos) { - list_add(&tx_q_item->q, list); - } else { - list_add_tail(&tx_q_item->q, list); - } - - /* Count of packet queued in driver */ - priv->noOfPktQueuedInDriver++; - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n"); - return CSR_RESULT_SUCCESS; -} - -#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL -CsrResult unifi_reque_ma_packet_request (void *ospriv, u32 host_tag, - u16 txStatus, bulk_data_desc_t *bulkDataDesc) -{ - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - netInterface_priv_t *interfacePriv; - struct list_head *list = NULL; - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - bulk_data_param_t bulkData; - CSR_SIGNAL signal; - CSR_PRIORITY priority = 0; - u16 interfaceTag = 0; - unifi_TrafficQueue priority_q; - u16 frameControl = 0, frameType = 0; - unsigned long lock_flags; - - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* If the current mode is not AP or P2PGO then just return failure - * to clear the hip slot - */ - if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || - (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO))) { - return CSR_RESULT_FAILURE; - } - - unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: host_tag = 0x%x\n", host_tag); - - staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, - (((u8 *) bulkDataDesc->os_data_ptr) + 4), - interfaceTag); - if (NULL == staRecord) { - unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid STA record \n"); - return CSR_RESULT_FAILURE; - } - - /* Update TIM if MA-PACKET.cfm fails with status as Tx-retry-limit or No-BSS and then just return failure - * to clear the hip slot associated with the Packet - */ - if (CSR_TX_RETRY_LIMIT == txStatus || CSR_TX_NO_BSS == txStatus) { - if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) - { - unifi_trace(priv, UDBG2, "unifi_reque_ma_packet_request: CFM failed with Retry Limit or No BSS-->update TIM\n"); - if (!staRecord->timRequestPendingFlag) { - update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle); - } - else { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 1; - unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: One more UpdateTim Request(:%d)Queued for AID %x\n", - staRecord->updateTimReqQueued, staRecord->aid); - } - } - return CSR_RESULT_FAILURE; - } - else if ((CSR_TX_LIFETIME == txStatus) || (CSR_TX_BLOCK_ACK_TIMEOUT == txStatus) || - (CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED == txStatus) || - (CSR_TX_REJECTED_PEER_STATION_SLEEPING == txStatus) || - (CSR_TX_REJECTED_DTIM_STARTED == txStatus)) { - /* Extract the Frame control and the frame type */ - frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr); - frameType = ((frameControl & IEEE80211_FC_TYPE_MASK) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); - - /* Mgmt frames will not be re-queued for Tx - * so just return failure to clear the hip slot - */ - if (IEEE802_11_FRAMETYPE_MANAGEMENT == frameType) { - return CSR_RESULT_FAILURE; - } - else if (IEEE802_11_FRAMETYPE_DATA == frameType) { - /* QOS NULL and DATA NULL frames will not be re-queued for Tx - * so just return failure to clear the hip slot - */ - if ((((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET) == QOS_DATA_NULL) || - (((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET)== DATA_NULL )) { - return CSR_RESULT_FAILURE; - } - } - - /* Extract the Packet priority */ - if (TRUE == staRecord->wmmOrQosEnabled) { - u16 qosControl = 0; - u8 dataFrameType = 0; - - dataFrameType =((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> 4); - - if (dataFrameType == QOS_DATA) { - /* QoS control field is offset from frame control by 2 (frame control) - * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN - */ - if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)) { - qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 30); - } - else { - qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 24); - } - } - - priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); - - if (priority < CSR_QOS_UP0 || priority > CSR_QOS_UP7) { - unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid priority:%x \n", priority); - return CSR_RESULT_FAILURE; - } - } - else { - priority = CSR_CONTENTION; - } - - /* Frame Bulk data to requeue it back to HAL Queues */ - bulkData.d[0].os_data_ptr = bulkDataDesc->os_data_ptr; - bulkData.d[0].data_length = bulkDataDesc->data_length; - bulkData.d[0].os_net_buf_ptr = bulkDataDesc->os_net_buf_ptr; - bulkData.d[0].net_buf_length = bulkDataDesc->net_buf_length; - - bulkData.d[1].os_data_ptr = NULL; - bulkData.d[1].os_net_buf_ptr = NULL; - bulkData.d[1].data_length = bulkData.d[1].net_buf_length = 0; - - /* Initialize signal to zero */ - memset(&signal, 0, sizeof(CSR_SIGNAL)); - - /* Frame MA Packet Req */ - unifi_frame_ma_packet_req(priv, priority, 0, host_tag, - interfaceTag, CSR_NO_CONFIRM_REQUIRED, - priv->netdev_client->sender_id, - staRecord->peerMacAddress.a, &signal); - - /* Find the Q-Priority */ - priority_q = unifi_frame_priority_to_queue(priority); - list = &staRecord->dataPdu[priority_q]; - - /* Place the Packet on to HAL Queue */ - status = enque_tx_data_pdu(priv, &bulkData, list, &signal, TRUE); - - /* Update the Per-station queued packet counter */ - if (!status) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staRecord->noOfPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - else { - /* Packet will not be re-queued for any of the other MA Packet Tx failure - * reasons so just return failure to clear the hip slot - */ - return CSR_RESULT_FAILURE; - } - - return status; -} -#endif - -static void is_all_ac_deliver_enabled_and_moredata(CsrWifiRouterCtrlStaInfo_t *staRecord, u8 *allDeliveryEnabled, u8 *dataAvailable) -{ - u8 i; - *allDeliveryEnabled = TRUE; - for (i = 0 ;i < MAX_ACCESS_CATOGORY; i++) { - if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) { - /* One is is not Delivery Enabled */ - *allDeliveryEnabled = FALSE; - break; - } - } - if (*allDeliveryEnabled) { - *dataAvailable = (!list_empty(&staRecord->dataPdu[0]) || !list_empty(&staRecord->dataPdu[1]) - ||!list_empty(&staRecord->dataPdu[2]) ||!list_empty(&staRecord->dataPdu[3]) - ||!list_empty(&staRecord->mgtFrames)); - } -} - -/* - * --------------------------------------------------------------------------- - * uf_handle_tim_cfm - * - * - * This function updates tim status in host depending confirm status from firmware - * - * Arguments: - * priv Pointer to device private context struct - * cfm CSR_MLME_SET_TIM_CONFIRM - * receiverProcessId SenderProcessID to fetch handle & timSet status - * - * --------------------------------------------------------------------------- - */ -void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, u16 receiverProcessId) -{ - u8 handle = CSR_WIFI_GET_STATION_HANDLE_FROM_RECEIVER_ID(receiverProcessId); - u8 timSetStatus = CSR_WIFI_GET_TIMSET_STATE_FROM_RECEIVER_ID(receiverProcessId); - u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff); - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - /* This variable holds what TIM value we wanted to set in firmware */ - u16 timSetValue = 0; - /* Irrespective of interface the count maintained */ - static u8 retryCount = 0; - unsigned long lock_flags; - unifi_trace(priv, UDBG3, "entering %s, handle = %x, timSetStatus = %x\n", __FUNCTION__, handle, timSetStatus); - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_warning(priv, "bad interfaceTag = %x\n", interfaceTag); - return; - } - - if ((handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) && (handle >= UNIFI_MAX_CONNECTIONS)) { - unifi_warning(priv, "bad station Handle = %x\n", handle); - return; - } - - if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - if ((staRecord = ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle]))) == NULL) { - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - unifi_warning(priv, "uf_handle_tim_cfm: station record is NULL handle = %x\n", handle); - return; - } - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - switch(timSetStatus) - { - case CSR_WIFI_TIM_SETTING: - timSetValue = CSR_WIFI_TIM_SET; - break; - case CSR_WIFI_TIM_RESETTING: - timSetValue = CSR_WIFI_TIM_RESET; - break; - default: - unifi_warning(priv, "timSet state is %x: Debug\n", timSetStatus); - return; - } - - /* check TIM confirm for success/failures */ - switch(cfm->ResultCode) - { - case CSR_RC_SUCCESS: - if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { - /* Unicast frame & station record available */ - if (timSetStatus == staRecord->timSet) { - staRecord->timSet = timSetValue; - /* fh_cmd_q can also be full at some point of time!, - * resetting count as queue is cleaned by firmware at this point - */ - retryCount = 0; - unifi_trace(priv, UDBG2, "tim (%s) successfully in firmware\n", (timSetValue)?"SET":"RESET"); - } else { - unifi_trace(priv, UDBG3, "receiver processID = %x, success: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x, handle = %x\n", - receiverProcessId, timSetStatus, staRecord->timSet, handle); - } - - /* Reset TIM pending flag to send next TIM request */ - staRecord->timRequestPendingFlag = FALSE; - - /* Make sure that one more UpdateTim request is queued, if Queued its value - * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET - */ - if (0xFF != staRecord->updateTimReqQueued) - { - /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */ - if (staRecord->timSet != staRecord->updateTimReqQueued) - { - unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateTimReq \n"); - - update_tim(priv, staRecord->aid, staRecord->updateTimReqQueued, interfaceTag, handle); - - staRecord->updateTimReqQueued = 0xFF; - } - } - } else { - - interfacePriv->bcTimSet = timSetValue; - /* fh_cmd_q can also be full at some point of time!, - * resetting count as queue is cleaned by firmware at this point - */ - retryCount = 0; - unifi_trace(priv, UDBG3, "tim (%s) successfully for broadcast frame in firmware\n", (timSetValue)?"SET":"RESET"); - - /* Reset DTIM pending flag to send next DTIM request */ - interfacePriv->bcTimSetReqPendingFlag = FALSE; - - /* Make sure that one more UpdateDTim request is queued, if Queued its value - * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET - */ - if (0xFF != interfacePriv->bcTimSetReqQueued) - { - /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */ - if (interfacePriv->bcTimSet != interfacePriv->bcTimSetReqQueued) - { - unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateDTimReq \n"); - - update_tim(priv, 0, interfacePriv->bcTimSetReqQueued, interfaceTag, 0xFFFFFFFF); - - interfacePriv->bcTimSetReqQueued = 0xFF; - } - } - - } - break; - case CSR_RC_INVALID_PARAMETERS: - case CSR_RC_INSUFFICIENT_RESOURCE: - /* check for max retry limit & send again - * MAX_RETRY_LIMIT is not maintained for each set of transactions..Its generic - * If failure crosses this Limit, we have to take a call to FIX - */ - if (retryCount > UNIFI_MAX_RETRY_LIMIT) { - u8 moreData = FALSE; - retryCount = 0; - /* Because of continuos traffic in fh_cmd_q the tim set request is failing (exceeding retry limit) - * but if we didn't synchronize our timSet varible state with firmware then it can cause below issues - * cond 1. We want to SET tim in firmware if its fails & max retry limit reached - * -> If host set's the timSet to 1, we wont try to send(as max retry reached) update tim but - * firmware is not updated with queue(TIM) status so it wont set TIM in beacon finally host start piling - * up data & wont try to set tim in firmware (This can cause worser performance) - * cond 2. We want to reset tim in firmware it fails & reaches max retry limit - * -> If host sets the timSet to Zero, it wont try to set a TIM request unless we wont have any packets - * to be queued, so beacon unnecessarily advertizes the TIM - */ - - if(staRecord) { - if(!staRecord->wmmOrQosEnabled) { - moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || - !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || - !list_empty(&staRecord->mgtFrames)); - } else { - /* Peer is QSTA */ - u8 allDeliveryEnabled = 0, dataAvailable = 0; - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - /*check for more data in non-delivery enabled queues*/ - moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)); - - } - /* To avoid cond 1 & 2, check internal Queues status, if we have more Data then set RESET the timSet(0), - * so we are trying to be in sync with firmware & next packets before queuing atleast try to - * set TIM in firmware otherwise it SET timSet(1) - */ - if (moreData) { - staRecord->timSet = CSR_WIFI_TIM_RESET; - } else { - staRecord->timSet = CSR_WIFI_TIM_SET; - } - } else { - /* Its a broadcast frames */ - moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || - !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); - if (moreData) { - update_tim(priv, 0, CSR_WIFI_TIM_SET, interfaceTag, 0xFFFFFFFF); - } else { - update_tim(priv, 0, CSR_WIFI_TIM_RESET, interfaceTag, 0xFFFFFFFF); - } - } - - unifi_error(priv, "no of error's for TIM setting crossed the Limit: verify\n"); - return; - } - retryCount++; - - if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { - if (timSetStatus == staRecord->timSet) { - unifi_warning(priv, "tim request failed, retry for AID = %x\n", staRecord->aid); - update_tim(priv, staRecord->aid, timSetValue, interfaceTag, handle); - } else { - unifi_trace(priv, UDBG1, "failure: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x\n", - timSetStatus, staRecord->timSet); - } - } else { - unifi_warning(priv, "tim request failed, retry for broadcast frames\n"); - update_tim(priv, 0, timSetValue, interfaceTag, 0xFFFFFFFF); - } - break; - default: - unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode); - } - - unifi_trace(priv, UDBG2, "leaving %s\n", __FUNCTION__); -} - -/* - * --------------------------------------------------------------------------- - * update_tim - * - * - * This function updates tim status in firmware for AID[1 to UNIFI_MAX_CONNECTIONS] or - * AID[0] for broadcast/multicast packets. - * - * NOTE: The LSB (least significant BYTE) of senderId while sending this MLME premitive - * has been modified(utilized) as below - * - * SenderID in signal's SignalPrimitiveHeader is 2 byte the lowe byte bitmap is below - * - * station handle(6 bits) timSet Status (2 bits) - * --------------------- ---------------------- - * 0 0 0 0 0 0 | 0 0 - * - * timSet Status can be one of below: - * - * CSR_WIFI_TIM_RESET - * CSR_WIFI_TIM_RESETTING - * CSR_WIFI_TIM_SET - * CSR_WIFI_TIM_SETTING - * - * Arguments: - * priv Pointer to device private context struct - * aid can be 1 t0 UNIFI_MAX_CONNECTIONS & 0 means multicast/broadcast - * setTim value SET(1) / RESET(0) - * interfaceTag the interfaceID on which activity going on - * handle from (0 <= handle < UNIFI_MAX_CONNECTIONS) - * - * --------------------------------------------------------------------------- - */ -void update_tim(unifi_priv_t * priv, u16 aid, u8 setTim, u16 interfaceTag, u32 handle) -{ - CSR_SIGNAL signal; - s32 r; - CSR_MLME_SET_TIM_REQUEST *req = &signal.u.MlmeSetTimRequest; - bulk_data_param_t *bulkdata = NULL; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - u8 senderIdLsb = 0; - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - u32 oldTimSetStatus = 0, timSetStatus = 0; - - unifi_trace(priv, UDBG5, "entering the update_tim routine\n"); - - - if (handle == 0xFFFFFFFF) { - handle &= CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE; - if (setTim == interfacePriv->bcTimSet) - { - unifi_trace(priv, UDBG3, "update_tim, Drop:Hdl=%x, timval=%d, globalTim=%d\n", handle, setTim, interfacePriv->bcTimSet); - return; - } - } else if ((handle != 0xFFFFFFFF) && (handle >= UNIFI_MAX_CONNECTIONS)) { - unifi_warning(priv, "bad station Handle = %x\n", handle); - return; - } - - if (setTim) { - timSetStatus = CSR_WIFI_TIM_SETTING; - } else { - timSetStatus = CSR_WIFI_TIM_RESETTING; - } - - if (handle != CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE) { - if ((staRecord = ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle]))) == NULL) { - unifi_warning(priv, "station record is NULL in update_tim: handle = %x :debug\n", handle); - return; - } - /* In case of signal sending failed, revert back to old state */ - oldTimSetStatus = staRecord->timSet; - staRecord->timSet = timSetStatus; - } - - /* pack senderID LSB */ - senderIdLsb = CSR_WIFI_PACK_SENDER_ID_LSB_FOR_TIM_REQ(handle, timSetStatus); - - /* initialize signal to zero */ - memset(&signal, 0, sizeof(CSR_SIGNAL)); - - /* Frame the MLME-SET-TIM request */ - signal.SignalPrimitiveHeader.SignalId = CSR_MLME_SET_TIM_REQUEST_ID; - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(((priv->netdev_client->sender_id & 0xff00) | senderIdLsb), - (u8*)&signal.SignalPrimitiveHeader.SenderProcessId); - - /* set The virtual interfaceIdentifier, aid, tim value */ - req->VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag); - req->AssociationId = aid; - req->TimValue = setTim; - - - unifi_trace(priv, UDBG2, "update_tim:AID %x,senderIdLsb = 0x%x, handle = 0x%x, timSetStatus = %x, sender proceesID = %x \n", - aid, senderIdLsb, handle, timSetStatus, signal.SignalPrimitiveHeader.SenderProcessId); - - /* Send the signal to UniFi */ - r = ul_send_signal_unpacked(priv, &signal, bulkdata); - if (r) { - /* No need to free bulk data, as TIM request doesn't carries any data */ - unifi_error(priv, "Error queueing CSR_MLME_SET_TIM_REQUEST signal\n"); - if (staRecord) { - staRecord->timSet = oldTimSetStatus ; - } - else - { - /* MLME_SET_TIM.req sending failed here for AID0, so revert back our bcTimSet status */ - interfacePriv->bcTimSet = !setTim; - } - } - else { - /* Update tim request pending flag and ensure no more TIM set requests are send - for the same station until TIM confirm is received */ - if (staRecord) { - staRecord->timRequestPendingFlag = TRUE; - } - else - { - /* Update tim request (for AID 0) pending flag and ensure no more DTIM set requests are send - * for the same station until TIM confirm is received - */ - interfacePriv->bcTimSetReqPendingFlag = TRUE; - } - } - unifi_trace(priv, UDBG5, "leaving the update_tim routine\n"); -} - -static -void process_peer_active_transition(unifi_priv_t * priv, - CsrWifiRouterCtrlStaInfo_t *staRecord, - u16 interfaceTag) -{ - int r, i; - u8 spaceAvail[4] = {TRUE, TRUE, TRUE, TRUE}; - tx_buffered_packets_t * buffered_pkt = NULL; - unsigned long lock_flags; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG5, "entering process_peer_active_transition\n"); - - if(IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag)) { - /* giving more priority to multicast packets so delaying unicast packets*/ - unifi_trace(priv, UDBG2, "Multicast transmission is going on so resume unicast transmission after DTIM over\n"); - - /* As station is active now, even though AP is not able to send frames to it - * because of DTIM, it needs to reset the TIM here - */ - if (!staRecord->timRequestPendingFlag){ - if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){ - update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); - } - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 0; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - return; - } - while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, 0, FALSE)) == -ENOSPC) { - unifi_trace(priv, UDBG2, "p_p_a_t:(ENOSPC) Mgt Frame queueing \n"); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->mgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[3]=(u8)(staRecord->assignedHandle); - spaceAvail[3] = FALSE; - break; - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - if (!staRecord->timRequestPendingFlag) { - if (staRecord->txSuspend) { - if(staRecord->timSet == CSR_WIFI_TIM_SET) { - update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); - } - return; - } - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 0; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - for(i=3;i>=0;i--) { - if(!spaceAvail[i]) - continue; - unifi_trace(priv, UDBG6, "p_p_a_t:data pkt sending for AC %d \n", i); - while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, 0, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->dataPdu[i]); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[i]=(u8)(staRecord->assignedHandle); - break; - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - } - if (!staRecord->timRequestPendingFlag){ - if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)) { - unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n"); - update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); - } - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 0; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - unifi_trace(priv, UDBG5, "leaving process_peer_active_transition\n"); -} - - - -void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv, u16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm) -{ - netInterface_priv_t *interfacePriv; - u8 i; - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - interfacePriv = priv->interfacePriv[interfaceTag]; - - - if(pkt_cfm->HostTag == interfacePriv->multicastPduHostTag) { - unifi_trace(priv, UDBG2, "CFM for marked Multicast Tag = %x\n", interfacePriv->multicastPduHostTag); - interfacePriv->multicastPduHostTag = 0xffffffff; - resume_suspended_uapsd(priv, interfaceTag); - resume_unicast_buffered_frames(priv, interfaceTag); - if(list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) && - list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { - unifi_trace(priv, UDBG1, "Resetting multicastTIM"); - if (!interfacePriv->bcTimSetReqPendingFlag) - { - update_tim(priv, 0, CSR_WIFI_TIM_RESET, interfaceTag, 0xFFFFFFFF); - } - else - { - /* Cache the DTimSet value so that it will processed immidiatly after - * completing the current setDTim Request - */ - interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; - unifi_trace(priv, UDBG2, "uf_process_ma_pkt_cfm_for_ap : One more UpdateDTim Request(%d) Queued \n", - interfacePriv->bcTimSetReqQueued); - } - - } - return; - } - - /* Check if it is a Confirm for null data frame used - * for probing station activity - */ - for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { - staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); - if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) { - - unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n", - pkt_cfm->HostTag, - pkt_cfm->TransmissionStatus - ); - staRecord->nullDataHostTag = INVALID_HOST_TAG; - - if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){ - u32 now; - u32 inactive_time; - - unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n"); - /* Recheck if there is some activity after null data is sent. - * - * If still there is no activity then send a disconnected indication - * to SME to delete the station record. - */ - if (staRecord->activity_flag){ - return; - } - now = CsrTimeGet(NULL); - - if (staRecord->lastActivity > now) - { - /* simple timer wrap (for 1 wrap) */ - inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity), - now); - } - else - { - inactive_time = (u32)CsrTimeSub(now, staRecord->lastActivity); - } - - if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) - { - struct list_head send_cfm_list; - u8 j; - - /* The SME/NME may be waiting for confirmation for requested frames to this station. - * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a - * a defensive check, it loops through buffered frames for this station and if confirmation - * is requested, send auto confirmation with failure status. Also flush the frames so - * that these are not processed again in PEER_DEL_REQ handler. - */ - INIT_LIST_HEAD(&send_cfm_list); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staRecord->mgtFrames)); - - uf_flush_list(priv, &(staRecord->mgtFrames)); - - for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staRecord->dataPdu[j])); - - uf_flush_list(priv, &(staRecord->dataPdu[j])); - } - - send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list); - - - - unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", - staRecord->peerMacAddress.a[0], - staRecord->peerMacAddress.a[1], - staRecord->peerMacAddress.a[2], - staRecord->peerMacAddress.a[3], - staRecord->peerMacAddress.a[4], - staRecord->peerMacAddress.a[5]); - - CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - staRecord->interfacePriv->InterfaceTag, - staRecord->peerMacAddress, - CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); - } - - } - else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL) - { - staRecord->activity_flag = TRUE; - } - } - } -} - -#endif -u16 uf_get_vif_identifier (CsrWifiRouterCtrlMode mode, u16 tag) -{ - switch(mode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - return (0x02<<8|tag); - - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - return (0x03<<8|tag); - - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - return (0x01<<8|tag); - - case CSR_WIFI_ROUTER_CTRL_MODE_MONITOR: - return (0x04<<8|tag); - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - return (0x05<<8|tag); - default: - return tag; - } -} - -#ifdef CSR_SUPPORT_SME - -/* - * --------------------------------------------------------------------------- - * update_macheader - * - * - * These functions updates mac header for intra BSS packet - * routing. - * NOTE: This function always has to be called in rx context which - * is in bh thread context since GFP_KERNEL is used. In soft IRQ/ Interrupt - * context shouldn't be used - * - * Arguments: - * priv Pointer to device private context struct - * skb Socket buffer containing data packet to transmit - * newSkb Socket buffer containing data packet + Mac header if no sufficient headroom in skb - * priority to append QOS control header in Mac header - * bulkdata if newSkb allocated then bulkdata updated to send to unifi - * interfaceTag the interfaceID on which activity going on - * macHeaderLengthInBytes no. of bytes of mac header in received frame - * qosDestination used to append Qos control field - * - * Returns: - * Zero on success or -1 on error. - * --------------------------------------------------------------------------- - */ - -static int update_macheader(unifi_priv_t *priv, struct sk_buff *skb, - struct sk_buff *newSkb, CSR_PRIORITY *priority, - bulk_data_param_t *bulkdata, u16 interfaceTag, - u8 macHeaderLengthInBytes, - u8 qosDestination) -{ - - u16 *fc = NULL; - u8 direction = 0, toDs, fromDs; - u8 *bufPtr = NULL; - u8 sa[ETH_ALEN], da[ETH_ALEN]; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - int headroom; - u8 macHeaderBuf[IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE] = {0}; - - unifi_trace(priv, UDBG5, "entering the update_macheader function\n"); - - /* temporary buffer for the Mac header storage */ - memcpy(macHeaderBuf, skb->data, macHeaderLengthInBytes); - - /* remove the Macheader from the skb */ - skb_pull(skb, macHeaderLengthInBytes); - - /* get the skb headroom for skb_push check */ - headroom = skb_headroom(skb); - - /* pointer to frame control field */ - fc = (u16*) macHeaderBuf; - - toDs = (*fc & cpu_to_le16(IEEE802_11_FC_TO_DS_MASK))?1 : 0; - fromDs = (*fc & cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK))? 1: 0; - unifi_trace(priv, UDBG5, "In update_macheader function, fromDs = %x, toDs = %x\n", fromDs, toDs); - direction = ((fromDs | (toDs << 1)) & 0x3); - - /* Address1 or 3 from the macheader */ - memcpy(da, macHeaderBuf+4+toDs*12, ETH_ALEN); - /* Address2, 3 or 4 from the mac header */ - memcpy(sa, macHeaderBuf+10+fromDs*(6+toDs*8), ETH_ALEN); - - unifi_trace(priv, UDBG3, "update_macheader:direction = %x\n", direction); - /* update the toDs, fromDs & address fields in Mac header */ - switch(direction) - { - case 2: - /* toDs = 1 & fromDs = 0 , toAp when frames received from peer - * while sending this packet to Destination the Mac header changed - * as fromDs = 1 & toDs = 0, fromAp - */ - *fc &= cpu_to_le16(~IEEE802_11_FC_TO_DS_MASK); - *fc |= cpu_to_le16(IEEE802_11_FC_FROM_DS_MASK); - /* Address1: MAC address of the actual destination (4 = 2+2) */ - memcpy(macHeaderBuf + 4, da, ETH_ALEN); - /* Address2: The MAC address of the AP (10 = 2+2+6) */ - memcpy(macHeaderBuf + 10, &interfacePriv->bssid, ETH_ALEN); - /* Address3: MAC address of the actual source from mac header (16 = 2+2+6+6) */ - memcpy(macHeaderBuf + 16, sa, ETH_ALEN); - break; - case 3: - unifi_trace(priv, UDBG3, "when both the toDs & fromDS set, NOT SUPPORTED\n"); - break; - default: - unifi_trace(priv, UDBG3, "problem in decoding packet in update_macheader \n"); - return -1; - } - - /* frameType is Data always, Validation is done before calling this function */ - - /* check for the souce station type */ - switch(le16_to_cpu(*fc) & IEEE80211_FC_SUBTYPE_MASK) - { - case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK: - /* No need to modify the qos control field */ - if (!qosDestination) { - - /* If source Sta is QOS enabled & if this bit set, then HTC is supported by - * peer station & htc field present in macHeader - */ - if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { - /* HT control field present in Mac header - * 6 = sizeof(qosControl) + sizeof(htc) - */ - macHeaderLengthInBytes -= 6; - } else { - macHeaderLengthInBytes -= 2; - } - /* Destination STA is non qos so change subtype to DATA */ - *fc &= cpu_to_le16(~IEEE80211_FC_SUBTYPE_MASK); - *fc |= cpu_to_le16(IEEE802_11_FC_TYPE_DATA); - /* remove the qos control field & HTC(if present). new macHeaderLengthInBytes is less than old - * macHeaderLengthInBytes so no need to verify skb headroom - */ - if (headroom < macHeaderLengthInBytes) { - unifi_trace(priv, UDBG1, " sufficient headroom not there to push updated mac header \n"); - return -1; - } - bufPtr = (u8 *) skb_push(skb, macHeaderLengthInBytes); - - /* update bulk data os_data_ptr */ - bulkdata->d[0].os_data_ptr = skb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata->d[0].data_length = skb->len; - - } else { - /* pointing to QOS control field */ - u8 qc; - if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) { - qc = *((u8*)(macHeaderBuf + (macHeaderLengthInBytes - 4 - 2))); - } else { - qc = *((u8*)(macHeaderBuf + (macHeaderLengthInBytes - 2))); - } - - if ((qc & IEEE802_11_QC_TID_MASK) > 7) { - *priority = 7; - } else { - *priority = qc & IEEE802_11_QC_TID_MASK; - } - - unifi_trace(priv, UDBG1, "Incoming packet priority from QSTA is %x\n", *priority); - - if (headroom < macHeaderLengthInBytes) { - unifi_trace(priv, UDBG3, " sufficient headroom not there to push updated mac header \n"); - return -1; - } - bufPtr = (u8 *) skb_push(skb, macHeaderLengthInBytes); - } - break; - default: - { - bulk_data_param_t data_ptrs; - CsrResult csrResult; - unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n"); - - if (qosDestination) { - u8 qc = 0; - unifi_trace(priv, UDBG3, "destination is QOS station \n"); - - /* Set Ma-Packet.req UP to UP0 */ - *priority = CSR_QOS_UP0; - - /* prepare the qos control field */ - qc |= CSR_QOS_UP0; - /* no Amsdu is in ap buffer so eosp is left 0 */ - if (da[0] & 0x1) { - /* multicast/broadcast frames, no acknowledgement needed */ - qc |= 1 << 5; - } - - /* update new Mac header Length with 2 = sizeof(qos control) */ - macHeaderLengthInBytes += 2; - - /* received DATA frame but destiantion is QOS station so update subtype to QOS*/ - *fc &= cpu_to_le16(~IEEE80211_FC_SUBTYPE_MASK); - *fc |= cpu_to_le16(IEEE802_11_FC_TYPE_QOS_DATA); - - /* appendQosControlOffset = macHeaderLengthInBytes - 2, since source sta is not QOS */ - macHeaderBuf[macHeaderLengthInBytes - 2] = qc; - /* txopLimit is 0 */ - macHeaderBuf[macHeaderLengthInBytes - 1] = 0; - if (headroom < macHeaderLengthInBytes) { - csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, " failed to allocate request_data. in update_macheader func\n"); - return -1; - } - newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); - newSkb->len = skb->len + macHeaderLengthInBytes; - - memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, - skb->data, skb->len); - - bulkdata->d[0].os_data_ptr = newSkb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; - bulkdata->d[0].data_length = newSkb->len; - - bufPtr = (u8*)data_ptrs.d[0].os_data_ptr; - - /* The old skb will not be used again */ - kfree_skb(skb); - } else { - /* skb headroom is sufficient to append Macheader */ - bufPtr = (u8*)skb_push(skb, macHeaderLengthInBytes); - bulkdata->d[0].os_data_ptr = skb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata->d[0].data_length = skb->len; - } - } else { - unifi_trace(priv, UDBG3, "destination is not a QSTA\n"); - if (headroom < macHeaderLengthInBytes) { - csrResult = unifi_net_data_malloc(priv, &data_ptrs.d[0], skb->len + macHeaderLengthInBytes); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, " failed to allocate request_data. in update_macheader func\n"); - return -1; - } - newSkb = (struct sk_buff *)(data_ptrs.d[0].os_net_buf_ptr); - newSkb->len = skb->len + macHeaderLengthInBytes; - - memcpy((void*)data_ptrs.d[0].os_data_ptr + macHeaderLengthInBytes, - skb->data, skb->len); - - bulkdata->d[0].os_data_ptr = newSkb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)newSkb; - bulkdata->d[0].data_length = newSkb->len; - - bufPtr = (u8*)data_ptrs.d[0].os_data_ptr; - - /* The old skb will not be used again */ - kfree_skb(skb); - } else { - /* skb headroom is sufficient to append Macheader */ - bufPtr = (u8*)skb_push(skb, macHeaderLengthInBytes); - bulkdata->d[0].os_data_ptr = skb->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata->d[0].data_length = skb->len; - } - } - } - } - - /* prepare the complete skb, by pushing the MAC header to the beginning of the skb->data */ - unifi_trace(priv, UDBG5, "updated Mac Header: %d \n", macHeaderLengthInBytes); - memcpy(bufPtr, macHeaderBuf, macHeaderLengthInBytes); - - unifi_trace(priv, UDBG5, "leaving the update_macheader function\n"); - return 0; -} -/* - * --------------------------------------------------------------------------- - * uf_ap_process_data_pdu - * - * - * Takes care of intra BSS admission control & routing packets within BSS - * - * Arguments: - * priv Pointer to device private context struct - * skb Socket buffer containing data packet to transmit - * ehdr ethernet header to fetch priority of packet - * srcStaInfo source stations record for connection verification - * packed_signal - * signal_len - * signal MA-PACKET.indication signal - * bulkdata if newSkb allocated then bulkdata updated to send to unifi - * macHeaderLengthInBytes no. of bytes of mac header in received frame - * - * Returns: - * Zero on success(ap processing complete) or -1 if packet also have to be sent to NETDEV. - * --------------------------------------------------------------------------- - */ -int -uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, - struct ethhdr *ehdr, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - const CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata, - u8 macHeaderLengthInBytes) -{ - const CSR_MA_PACKET_INDICATION *ind = &(signal->u.MaPacketIndication); - u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0x00ff); - struct sk_buff *newSkb = NULL; - /* pointer to skb or private skb created using skb_copy() */ - struct sk_buff *skbPtr = skb; - u8 sendToNetdev = FALSE; - u8 qosDestination = FALSE; - CSR_PRIORITY priority = CSR_CONTENTION; - CsrWifiRouterCtrlStaInfo_t *dstStaInfo = NULL; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG5, "entering uf_ap_process_data_pdu %d\n", macHeaderLengthInBytes); - /* InterfaceTag validation from MA_PACKET.indication */ - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_trace(priv, UDBG1, "Interface Tag is Invalid in uf_ap_process_data_pdu\n"); - unifi_net_data_free(priv, &bulkdata->d[0]); - return 0; - } - interfacePriv = priv->interfacePriv[interfaceTag]; - - if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) && - (interfacePriv->intraBssEnabled == FALSE)) { - unifi_trace(priv, UDBG2, "uf_ap_process_data_pdu:P2P GO intrabssEnabled?= %d\n", interfacePriv->intraBssEnabled); - - /*In P2P GO case, if intraBSS distribution Disabled then don't do IntraBSS routing */ - /* If destination in our BSS then drop otherwise give packet to netdev */ - dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfaceTag); - if (dstStaInfo) { - unifi_net_data_free(priv, &bulkdata->d[0]); - return 0; - } - /* May be associated P2PCLI trying to send the packets on backbone (Netdev) */ - return -1; - } - - if(!memcmp(ehdr->h_dest, interfacePriv->bssid.a, ETH_ALEN)) { - /* This packet will be given to the TCP/IP stack since this packet is for us(AP) - * No routing needed */ - unifi_trace(priv, UDBG4, "destination address is csr_ap\n"); - return -1; - } - - /* fetch the destination record from station record database */ - dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, ehdr->h_dest, interfaceTag); - - /* AP mode processing, & if packet is unicast */ - if(!dstStaInfo) { - if (!(ehdr->h_dest[0] & 0x1)) { - /* destination not in station record & its a unicast packet, so pass the packet to network stack */ - unifi_trace(priv, UDBG3, "unicast frame & destination record not exist, send to netdev proto = %x\n", htons(skb->protocol)); - return -1; - } else { - /* packet is multicast/broadcast */ - /* copy the skb to skbPtr, send skb to netdev & skbPtr to multicast/broad cast list */ - unifi_trace(priv, UDBG5, "skb_copy, in uf_ap_process_data_pdu, protocol = %x\n", htons(skb->protocol)); - skbPtr = skb_copy(skb, GFP_KERNEL); - if(skbPtr == NULL) { - /* We don't have memory to don't send the frame in BSS*/ - unifi_notice(priv, "broacast/multicast frame can't be sent in BSS No memeory: proto = %x\n", htons(skb->protocol)); - return -1; - } - sendToNetdev = TRUE; - } - } else { - - /* validate the Peer & Destination Station record */ - if (uf_process_station_records_for_sending_data(priv, interfaceTag, srcStaInfo, dstStaInfo)) { - unifi_notice(priv, "uf_ap_process_data_pdu: station record validation failed \n"); - interfacePriv->stats.rx_errors++; - unifi_net_data_free(priv, &bulkdata->d[0]); - return 0; - } - } - - /* BroadCast packet received and it's been sent as non QOS packets. - * Since WMM spec not mandates broadcast/multicast to be sent as QOS data only, - * if all Peers are QSTA - */ - if(sendToNetdev) { - /* BroadCast packet and it's been sent as non QOS packets */ - qosDestination = FALSE; - } else if(dstStaInfo && (dstStaInfo->wmmOrQosEnabled == TRUE)) { - qosDestination = TRUE; - } - - unifi_trace(priv, UDBG3, "uf_ap_process_data_pdu QoS destination = %s\n", (qosDestination)? "TRUE": "FALSE"); - - /* packet is allowed to send to unifi, update the Mac header */ - if (update_macheader(priv, skbPtr, newSkb, &priority, bulkdata, interfaceTag, macHeaderLengthInBytes, qosDestination)) { - interfacePriv->stats.rx_errors++; - unifi_notice(priv, "(Packet Drop) failed to update the Mac header in uf_ap_process_data_pdu\n"); - if (sendToNetdev) { - /* Free's the skb_copy(skbPtr) data since packet processing failed */ - bulkdata->d[0].os_data_ptr = skbPtr->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skbPtr; - bulkdata->d[0].data_length = skbPtr->len; - unifi_net_data_free(priv, &bulkdata->d[0]); - } - return -1; - } - - unifi_trace(priv, UDBG3, "Mac Header updated...calling uf_process_ma_packet_req \n"); - - /* Packet is ready to send to unifi ,transmissionControl = 0x0004, confirmation is not needed for data packets */ - if (uf_process_ma_packet_req(priv, ehdr->h_dest, 0xffffffff, interfaceTag, CSR_NO_CONFIRM_REQUIRED, (CSR_RATE)0, priority, priv->netdev_client->sender_id, bulkdata)) { - if (sendToNetdev) { - unifi_trace(priv, UDBG1, "In uf_ap_process_data_pdu, (Packet Drop) uf_process_ma_packet_req failed. freeing skb_copy data (original data sent to Netdev)\n"); - /* Free's the skb_copy(skbPtr) data since packet processing failed */ - bulkdata->d[0].os_data_ptr = skbPtr->data; - bulkdata->d[0].os_net_buf_ptr = (unsigned char*)skbPtr; - bulkdata->d[0].data_length = skbPtr->len; - unifi_net_data_free(priv, &bulkdata->d[0]); - } else { - /* This free's the skb data */ - unifi_trace(priv, UDBG1, "In uf_ap_process_data_pdu, (Packet Drop). Unicast data so freeing original skb \n"); - unifi_net_data_free(priv, &bulkdata->d[0]); - } - } - unifi_trace(priv, UDBG5, "leaving uf_ap_process_data_pdu\n"); - - if (sendToNetdev) { - /* The packet is multicast/broadcast, so after AP processing packet has to - * be sent to netdev, if peer port state is open - */ - unifi_trace(priv, UDBG4, "Packet will be routed to NetDev\n"); - return -1; - } - /* Ap handled the packet & its a unicast packet, no need to send to netdev */ - return 0; -} - -#endif - -CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, - u8 *peerMacAddress, - CSR_CLIENT_TAG hostTag, - u16 interfaceTag, - CSR_TRANSMISSION_CONTROL transmissionControl, - CSR_RATE TransmitRate, - CSR_PRIORITY priority, - CSR_PROCESS_ID leSenderProcessId, - bulk_data_param_t *bulkdata) -{ - CsrResult status = CSR_RESULT_SUCCESS; - CSR_SIGNAL signal; - int result; -#ifdef CSR_SUPPORT_SME - CsrWifiRouterCtrlStaInfo_t *staRecord = NULL; - const u8 *macHdrLocation = bulkdata->d[0].os_data_ptr; - CsrWifiPacketType pktType; - int frameType = 0; - u8 queuePacketDozing = FALSE; - u32 priority_q; - u16 frmCtrl; - struct list_head * list = NULL; /* List to which buffered PDUs are to be enqueued*/ - u8 setBcTim=FALSE; - netInterface_priv_t *interfacePriv; - u8 requeueOnSamePos = FALSE; - u32 handle = 0xFFFFFFFF; - unsigned long lock_flags; - - unifi_trace(priv, UDBG5, - "entering uf_process_ma_packet_req, peer: %pMF\n", - peerMacAddress); - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "interfaceTag >= CSR_WIFI_NUM_INTERFACES, interfacetag = %d\n", interfaceTag); - return CSR_RESULT_FAILURE; - } - interfacePriv = priv->interfacePriv[interfaceTag]; - - - /* fetch the station record for corresponding peer mac address */ - if ((staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, peerMacAddress, interfaceTag))) { - handle = staRecord->assignedHandle; - } - - /* Frame ma-packet.req, this is saved/transmitted depend on queue state */ - unifi_frame_ma_packet_req(priv, priority, TransmitRate, hostTag, - interfaceTag, transmissionControl, leSenderProcessId, - peerMacAddress, &signal); - - /* Since it's common path between STA & AP mode, in case of STA packet - * need not to be queued but in AP case we have to queue PDU's in - * different scenarios - */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - /* For this mode processing done below */ - break; - default: - /* In case of STA/IBSS/P2PCLI/AMP, no checks needed send the packet down & return */ - unifi_trace(priv, UDBG5, "In %s, interface mode is %x \n", __FUNCTION__, interfacePriv->interfaceMode); - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_NONE) { - unifi_warning(priv, "In %s, interface mode NONE \n", __FUNCTION__); - } - if ((result = ul_send_signal_unpacked(priv, &signal, bulkdata))) { - status = CSR_RESULT_FAILURE; - } - return status; - } - - /* -----Only AP/P2pGO mode handling falls below----- */ - - /* convert priority to queue */ - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - - /* check the powersave status of the peer */ - if (staRecord && (staRecord->currentPeerState == - CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)) { - /* Peer is dozing & packet have to be delivered, so buffer the packet & - * update the TIM - */ - queuePacketDozing = TRUE; - } - - /* find the type of frame unicast or mulicast/broadcast */ - if (*peerMacAddress & 0x1) { - /* Multicast/broadCast data are always triggered by vif_availability.ind - * at the DTIM - */ - pktType = CSR_WIFI_MULTICAST_PDU; - } else { - pktType = CSR_WIFI_UNICAST_PDU; - } - - /* Fetch the frame control field from mac header & check for frame type */ - frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); - - /* Processing done according to Frame/Packet type */ - frameType = ((frmCtrl & 0x000c) >> FRAME_CONTROL_TYPE_FIELD_OFFSET); - switch(frameType) - { - case IEEE802_11_FRAMETYPE_MANAGEMENT: - - switch(pktType) - { - case CSR_WIFI_UNICAST_PDU: - unifi_trace(priv, UDBG5, "management unicast PDU in uf_process_ma_packet_req \n"); - /* push the packet in to the queue with appropriate mgt list */ - if (!staRecord) { - /* push the packet to the unifi if list is empty (if packet lost how to re-enque) */ - if (list_empty(&interfacePriv->genericMgtFrames)) { -#ifdef CSR_SUPPORT_SME - if(!(IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag))) { -#endif - - unifi_trace(priv, UDBG3, "genericMgtFrames list is empty uf_process_ma_packet_req \n"); - result = ul_send_signal_unpacked(priv, &signal, bulkdata); - /* reque only on ENOSPC */ - if(result == -ENOSPC) { - /* requeue the failed packet to genericMgtFrame with same position */ - unifi_trace(priv, UDBG1, "(ENOSPC) Sending genericMgtFrames Failed so buffering\n"); - list = &interfacePriv->genericMgtFrames; - requeueOnSamePos = TRUE; - } -#ifdef CSR_SUPPORT_SME - }else{ - list = &interfacePriv->genericMgtFrames; - unifi_trace(priv, UDBG3, "genericMgtFrames queue empty and dtim started\n hosttag is 0x%x,\n", signal.u.MaPacketRequest.HostTag); - update_eosp_to_head_of_broadcast_list_head(priv, interfaceTag); - } -#endif - } else { - /* Queue the packet to genericMgtFrame of unifi_priv_t data structure */ - list = &interfacePriv->genericMgtFrames; - unifi_trace(priv, UDBG2, "genericMgtFrames queue not empty\n"); - } - } else { - /* check peer power state */ - if (queuePacketDozing || !list_empty(&staRecord->mgtFrames) || IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag)) { - /* peer is in dozing mode, so queue packet in mgt frame list of station record */ - /*if multicast traffic is going on, buffer the unicast packets*/ - list = &staRecord->mgtFrames; - - unifi_trace(priv, UDBG1, "staRecord->MgtFrames list empty? = %s, handle = %d, queuePacketDozing = %d\n", - (list_empty(&staRecord->mgtFrames))? "YES": "NO", staRecord->assignedHandle, queuePacketDozing); - if(IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag)){ - update_eosp_to_head_of_broadcast_list_head(priv, interfaceTag); - } - - } else { - unifi_trace(priv, UDBG5, "staRecord->mgtFrames list is empty uf_process_ma_packet_req \n"); - result = ul_send_signal_unpacked(priv, &signal, bulkdata); - if(result == -ENOSPC) { - /* requeue the failed packet to staRecord->mgtFrames with same position */ - list = &staRecord->mgtFrames; - requeueOnSamePos = TRUE; - unifi_trace(priv, UDBG1, "(ENOSPC) Sending MgtFrames Failed handle = %d so buffering\n", staRecord->assignedHandle); - priv->pausedStaHandle[0]=(u8)(staRecord->assignedHandle); - } else if (result) { - status = CSR_RESULT_FAILURE; - } - } - } - break; - case CSR_WIFI_MULTICAST_PDU: - unifi_trace(priv, UDBG5, "management multicast/broadcast PDU in uf_process_ma_packet_req 'QUEUE it' \n"); - /* Queue the packet to genericMulticastOrBroadCastMgtFrames of unifi_priv_t data structure - * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM - */ - - list = &interfacePriv->genericMulticastOrBroadCastMgtFrames; - if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS) && - (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) { - setBcTim=TRUE; - } - break; - default: - unifi_error(priv, "condition never meets: packet type unrecognized\n"); - } - break; - case IEEE802_11_FRAMETYPE_DATA: - switch(pktType) - { - case CSR_WIFI_UNICAST_PDU: - unifi_trace(priv, UDBG5, "data unicast PDU in uf_process_ma_packet_req \n"); - /* check peer power state, list status & peer port status */ - if(!staRecord) { - unifi_error(priv, "In %s unicast but staRecord = NULL\n", __FUNCTION__); - return CSR_RESULT_FAILURE; - } else if (queuePacketDozing || isRouterBufferEnabled(priv, priority_q)|| !list_empty(&staRecord->dataPdu[priority_q]) || IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag)) { - /* peer is in dozing mode, so queue packet in mgt frame list of station record */ - /* if multicast traffic is going on, buffet the unicast packets */ - unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\ - Buffering enabled = %d \n", priority_q, queuePacketDozing, isRouterBufferEnabled(priv, priority_q)); - list = &staRecord->dataPdu[priority_q]; - } else { - unifi_trace(priv, UDBG5, "staRecord->dataPdu[%d] list is empty uf_process_ma_packet_req \n", priority_q); - /* Pdu allowed to send to unifi */ - result = ul_send_signal_unpacked(priv, &signal, bulkdata); - if(result == -ENOSPC) { - /* requeue the failed packet to staRecord->dataPdu[priority_q] with same position */ - unifi_trace(priv, UDBG1, "(ENOSPC) Sending Unicast DataPDU to queue %d Failed so buffering\n", priority_q); - requeueOnSamePos = TRUE; - list = &staRecord->dataPdu[priority_q]; - priv->pausedStaHandle[priority_q]=(u8)(staRecord->assignedHandle); - if(!isRouterBufferEnabled(priv, priority_q)) { - unifi_error(priv, "Buffering Not enabled for queue %d \n", priority_q); - } - } else if (result) { - status = CSR_RESULT_FAILURE; - } - } - break; - case CSR_WIFI_MULTICAST_PDU: - unifi_trace(priv, UDBG5, "data multicast/broadcast PDU in uf_process_ma_packet_req \n"); - /* Queue the packet to genericMulticastOrBroadCastFrames list of unifi_priv_t data structure - * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM - */ - list = &interfacePriv->genericMulticastOrBroadCastFrames; - if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { - setBcTim = TRUE; - } - break; - default: - unifi_error(priv, "condition never meets: packet type un recognized\n"); - } - break; - default: - unifi_error(priv, "unrecognized frame type\n"); - } - if(list) { - status = enque_tx_data_pdu(priv, bulkdata, list, &signal, requeueOnSamePos); - /* Record no. of packet queued for each peer */ - if (staRecord && (pktType == CSR_WIFI_UNICAST_PDU) && (!status)) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staRecord->noOfPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - else if ((pktType == CSR_WIFI_MULTICAST_PDU) && (!status)) - { - /* If broadcast Tim is set && queuing is successful, then only update TIM */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - interfacePriv->noOfbroadcastPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - /* If broadcast Tim is set && queuing is successful, then only update TIM */ - if(setBcTim && !status) { - unifi_trace(priv, UDBG3, "tim set due to broadcast pkt\n"); - if (!interfacePriv->bcTimSetReqPendingFlag) - { - update_tim(priv, 0, CSR_WIFI_TIM_SET, interfaceTag, handle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_SET; - unifi_trace(priv, UDBG2, "uf_process_ma_packet_req : One more UpdateDTim Request(:%d) Queued \n", - interfacePriv->bcTimSetReqQueued); - } - } else if(staRecord && staRecord->currentPeerState == - CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) { - if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) { - if(!staRecord->wmmOrQosEnabled) { - if(!list_empty(&staRecord->mgtFrames) || - !list_empty(&staRecord->dataPdu[3]) || - !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) { - unifi_trace(priv, UDBG3, "tim set due to unicast pkt & peer in powersave\n"); - if (!staRecord->timRequestPendingFlag){ - update_tim(priv, staRecord->aid, 1, interfaceTag, handle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 1; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - } - } else { - /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */ - u8 allDeliveryEnabled = 0, dataAvailable = 0; - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable) - || (!list_empty(&staRecord->mgtFrames))) { - if (!staRecord->timRequestPendingFlag) { - update_tim(priv, staRecord->aid, 1, interfaceTag, handle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 1; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - } - } - } - } - - if((list) && (pktType == CSR_WIFI_UNICAST_PDU && !queuePacketDozing) && !(isRouterBufferEnabled(priv, priority_q)) && !(IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag))) { - unifi_trace(priv, UDBG2, "buffering cleared for queue = %d So resending buffered frames\n", priority_q); - uf_send_buffered_frames(priv, priority_q); - } - unifi_trace(priv, UDBG5, "leaving uf_process_ma_packet_req \n"); - return status; -#else -#ifdef CSR_NATIVE_LINUX - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "interfaceTag >= CSR_WIFI_NUM_INTERFACES, interfacetag = %d\n", interfaceTag); - return CSR_RESULT_FAILURE; - } - /* Frame ma-packet.req, this is saved/transmitted depend on queue state */ - unifi_frame_ma_packet_req(priv, priority, TransmitRate, hostTag, interfaceTag, - transmissionControl, leSenderProcessId, - peerMacAddress, &signal); - result = ul_send_signal_unpacked(priv, &signal, bulkdata); - if (result) { - return CSR_RESULT_FAILURE; - } -#endif - return status; -#endif -} - -#ifdef CSR_SUPPORT_SME -s8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, u16 interfaceTag, const u8 *daddr) -{ - s8 protection = 0; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - protection = interfacePriv->protect; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - { - CsrWifiRouterCtrlStaInfo_t *dstStaInfo = NULL; - if (daddr[0] & 0x1) { - unifi_trace(priv, UDBG3, "broadcast/multicast packet in send_ma_pkt_request\n"); - /* In this mode, the protect member of priv structure has an information of how - * AP/P2PGO has started, & the member updated in set mode request for AP/P2PGO - */ - protection = interfacePriv->protect; - } else { - /* fetch the destination record from station record database */ - dstStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, daddr, interfaceTag); - if (!dstStaInfo) { - unifi_trace(priv, UDBG3, "peer not found in station record in send_ma_pkt_request\n"); - return -1; - } - protection = dstStaInfo->protection; - } - } - break; - default: - unifi_trace(priv, UDBG2, "mode unknown in send_ma_pkt_request\n"); - } - return protection; -} -#endif -#ifdef CSR_SUPPORT_SME -u8 send_multicast_frames(unifi_priv_t *priv, u16 interfaceTag) -{ - int r; - tx_buffered_packets_t * buffered_pkt = NULL; - u8 moreData = FALSE; - u8 pduSent =0; - unsigned long lock_flags; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - u32 hostTag = 0xffffffff; - - if(!isRouterBufferEnabled(priv, UNIFI_TRAFFIC_Q_VO)) { - while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv, &interfacePriv->genericMulticastOrBroadCastMgtFrames))) { - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK); - moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE; - - - unifi_trace(priv, UDBG2, "DTIM Occurred for interface:sending Mgt packet %d\n", interfaceTag); - - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, NULL, moreData, FALSE)) == -ENOSPC) { - unifi_trace(priv, UDBG1, "frame_and_send_queued_pdu failed with ENOSPC for host tag = %x\n", buffered_pkt->hostTag); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &interfacePriv->genericMulticastOrBroadCastMgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - break; - } else { - unifi_trace(priv, UDBG1, "send_multicast_frames: Send genericMulticastOrBroadCastMgtFrames (%x, %x)\n", - buffered_pkt->hostTag, - r); - if(r) { - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - if(!moreData) { - - interfacePriv->dtimActive = FALSE; - if(!r) { - hostTag = buffered_pkt->hostTag; - pduSent++; - } else { - send_vif_availibility_rsp(priv, uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag), CSR_RC_UNSPECIFIED_FAILURE); - } - } - /* Buffered frame sent successfully */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - interfacePriv->noOfbroadcastPktQueued--; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - kfree(buffered_pkt); - } - - } - } - if(!isRouterBufferEnabled(priv, UNIFI_TRAFFIC_Q_CONTENTION)) { - while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv, &interfacePriv->genericMulticastOrBroadCastFrames))) { - buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; - moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE; - - - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, NULL, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &interfacePriv->genericMulticastOrBroadCastFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - break; - } else { - if(r) { - unifi_trace(priv, UDBG1, "send_multicast_frames: Send genericMulticastOrBroadCastFrame failed (%x, %x)\n", - buffered_pkt->hostTag, - r); - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - if(!moreData) { - interfacePriv->dtimActive = FALSE; - if(!r) { - pduSent ++; - hostTag = buffered_pkt->hostTag; - } else { - send_vif_availibility_rsp(priv, uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag), CSR_RC_UNSPECIFIED_FAILURE); - } - } - /* Buffered frame sent successfully */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - interfacePriv->noOfbroadcastPktQueued--; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - kfree(buffered_pkt); - } - } - } - if((interfacePriv->dtimActive == FALSE)) { - /* Record the host Tag*/ - unifi_trace(priv, UDBG2, "send_multicast_frames: Recorded hostTag of EOSP packet: = 0x%x\n", hostTag); - interfacePriv->multicastPduHostTag = hostTag; - } - return pduSent; -} -#endif -void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv, u8 *sigdata, - u32 siglen) -{ -#ifdef CSR_SUPPORT_SME - CSR_SIGNAL signal; - CSR_MA_VIF_AVAILABILITY_INDICATION *ind; - int r; - u16 interfaceTag; - u8 pduSent =0; - CSR_RESULT_CODE resultCode = CSR_RC_SUCCESS; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG3, - "uf_process_ma_vif_availibility_ind: Process signal 0x%.4X\n", - *((u16*)sigdata)); - - r = read_unpack_signal(sigdata, &signal); - if (r) { - unifi_error(priv, - "uf_process_ma_vif_availibility_ind: Received unknown signal 0x%.4X.\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata)); - return; - } - ind = &signal.u.MaVifAvailabilityIndication; - interfaceTag=ind->VirtualInterfaceIdentifier & 0xff; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "in vif_availability_ind interfaceTag is wrong\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if(ind->Multicast) { - if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames) && - list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames)) { - /* This condition can occur because of a potential race where the - TIM is not yet reset as host is waiting for confirm but it is sent - by firmware and DTIM occurs*/ - unifi_notice(priv, "ma_vif_availibility_ind recevied for multicast but queues are empty%d\n", interfaceTag); - send_vif_availibility_rsp(priv, ind->VirtualInterfaceIdentifier, CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES); - interfacePriv->dtimActive = FALSE; - if(interfacePriv->multicastPduHostTag == 0xffffffff) { - unifi_notice(priv, "ma_vif_availibility_ind recevied for multicast but queues are empty%d\n", interfaceTag); - /* This may be an extra request in very rare race conditions but it is fine as it would atleast remove the potential lock up */ - if (!interfacePriv->bcTimSetReqPendingFlag) - { - update_tim(priv, 0, CSR_WIFI_TIM_RESET, interfaceTag, 0xFFFFFFFF); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; - unifi_trace(priv, UDBG2, "uf_process_ma_vif_availibility_ind : One more UpdateDTim Request(%d) Queued \n", - interfacePriv->bcTimSetReqQueued); - } - } - return; - } - if(interfacePriv->dtimActive) { - unifi_trace(priv, UDBG2, "DTIM Occurred for already active DTIM interface %d\n", interfaceTag); - return; - } else { - unifi_trace(priv, UDBG2, "DTIM Occurred for interface %d\n", interfaceTag); - if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) { - set_eosp_transmit_ctrl(priv, &interfacePriv->genericMulticastOrBroadCastMgtFrames); - } else { - set_eosp_transmit_ctrl(priv, &interfacePriv->genericMulticastOrBroadCastFrames); - } - } - interfacePriv->dtimActive = TRUE; - pduSent = send_multicast_frames(priv, interfaceTag); - } - else { - unifi_error(priv, "Interface switching is not supported %d\n", interfaceTag); - resultCode = CSR_RC_NOT_SUPPORTED; - send_vif_availibility_rsp(priv, ind->VirtualInterfaceIdentifier, CSR_RC_NOT_SUPPORTED); - } -#endif -} -#ifdef CSR_SUPPORT_SME - -#define GET_ACTIVE_INTERFACE_TAG(priv) 0 - -static u8 uf_is_more_data_for_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord) -{ - s8 i; - - for(i=UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--) - { - if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - &&(!list_empty(&staRecord->dataPdu[i]))) { - unifi_trace(priv, UDBG2, "uf_is_more_data_for_delivery_ac: Data Available AC = %d\n", i); - return TRUE; - } - } - - unifi_trace(priv, UDBG2, "uf_is_more_data_for_delivery_ac: Data NOT Available \n"); - return FALSE; -} - -static u8 uf_is_more_data_for_usp_delivery(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord, unifi_TrafficQueue queue) -{ - s8 i; - - for(i = queue; i >= UNIFI_TRAFFIC_Q_BK; i--) - { - if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - &&(!list_empty(&staRecord->dataPdu[i]))) { - unifi_trace(priv, UDBG2, "uf_is_more_data_for_usp_delivery: Data Available AC = %d\n", i); - return TRUE; - } - } - - unifi_trace(priv, UDBG2, "uf_is_more_data_for_usp_delivery: Data NOT Available \n"); - return FALSE; -} - -/* - * --------------------------------------------------------------------------- - * uf_send_buffered_data_from_delivery_ac - * - * This function takes care of - * -> Parsing the delivery enabled queue & sending frame down to HIP - * -> Setting EOSP=1 when USP to be terminated - * -> Depending on MAX SP length services the USP - * - * NOTE:This function always called from uf_handle_uspframes_delivery(), Dont - * call this function from any other location in code - * - * Arguments: - * priv Pointer to device private context struct - * vif interface specific HIP vif instance - * staInfo peer for which UAPSD to be scheduled - * queue AC from which Data to be sent in USP - * txList access category for processing list - * --------------------------------------------------------------------------- - */ -void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, - CsrWifiRouterCtrlStaInfo_t * staInfo, - u8 queue, - struct list_head *txList) -{ - - u16 interfaceTag = GET_ACTIVE_INTERFACE_TAG(priv); - tx_buffered_packets_t * buffered_pkt = NULL; - unsigned long lock_flags; - u8 eosp=FALSE; - s8 r =0; - u8 moreData = FALSE; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG2, "++uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive); - - if (queue > UNIFI_TRAFFIC_Q_VO) - { - return; - } - while((buffered_pkt=dequeue_tx_data_pdu(priv, txList))) { - if((IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag))) { - unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: DTIM Active, suspend UAPSD, staId: 0x%x\n", - staInfo->aid); - - /* Once resume called, the U-APSD delivery operation will resume */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->uspSuspend = TRUE; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - /* re-queueing the packet as DTIM started */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, txList); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - break; - } - - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - - - if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)) { - - buffered_pkt->transmissionControl = TRANSMISSION_CONTROL_TRIGGER_MASK; - - /* Check All delivery enables Ac for more data, because caller of this - * function not aware about last packet - * (First check in moreData fetching helps in draining out Mgt frames Q) - */ - moreData = (!list_empty(txList) || uf_is_more_data_for_usp_delivery(priv, staInfo, queue)); - - if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength - 1)) { - moreData = FALSE; - } - - if(moreData == FALSE) { - eosp = TRUE; - buffered_pkt->transmissionControl = - (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - } - } else { - /* Non QoS and non U-APSD */ - unifi_warning(priv, "uf_send_buffered_data_from_delivery_ac: non U-APSD !!! \n"); - } - - unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac : MoreData:%d, EOSP:%d\n", moreData, eosp); - - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staInfo, moreData, eosp)) == -ENOSPC) { - - unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: UASPD suspended, ENOSPC in hipQ=%x\n", queue); - - /* Once resume called, the U-APSD delivery operation will resume */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->uspSuspend = TRUE; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, txList); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[queue]=(u8)(staInfo->assignedHandle); - break; - } else { - if(r){ - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->noOfSpFramesSent++; - if((!moreData) || (staInfo->noOfSpFramesSent == staInfo->maxSpLength)) { - unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: Terminating USP\n"); - staInfo->uapsdActive = FALSE; - staInfo->uspSuspend = FALSE; - staInfo->noOfSpFramesSent = 0; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - break; - } - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - unifi_trace(priv, UDBG2, "--uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive); -} - -void uf_send_buffered_data_from_ac(unifi_priv_t *priv, - CsrWifiRouterCtrlStaInfo_t * staInfo, - u8 queue, - struct list_head *txList) -{ - tx_buffered_packets_t * buffered_pkt = NULL; - unsigned long lock_flags; - u8 eosp=FALSE; - u8 moreData = FALSE; - s8 r =0; - - unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_ac :\n"); - - while(!isRouterBufferEnabled(priv, queue) && - ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){ - - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - - unifi_trace(priv, UDBG3, "uf_send_buffered_data_from_ac : MoreData:%d, EOSP:%d\n", moreData, eosp); - - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staInfo, moreData, eosp)) == -ENOSPC) { - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, txList); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - if(staInfo != NULL){ - priv->pausedStaHandle[queue]=(u8)(staInfo->assignedHandle); - } - unifi_trace(priv, UDBG3, " uf_send_buffered_data_from_ac: PDU sending failed .. no space for queue %d \n", queue); - } else { - if(r){ - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - -} - -void uf_send_buffered_frames(unifi_priv_t *priv, unifi_TrafficQueue q) -{ - u16 interfaceTag = GET_ACTIVE_INTERFACE_TAG(priv); - u32 startIndex=0, endIndex=0; - CsrWifiRouterCtrlStaInfo_t * staInfo = NULL; - u8 queue; - u8 moreData = FALSE; - - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) || - (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO))) - return; - - queue = (q<=3)?q:0; - - if(interfacePriv->dtimActive) { - /* this function updates dtimActive*/ - send_multicast_frames(priv, interfaceTag); - if(!interfacePriv->dtimActive) { - moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || - !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); - if(!moreData) { - if (!interfacePriv->bcTimSetReqPendingFlag) - { - update_tim(priv, 0, CSR_WIFI_TIM_RESET, interfaceTag, 0XFFFFFFFF); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET; - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : One more UpdateDTim Request(%d) Queued \n", - interfacePriv->bcTimSetReqQueued); - } - } - } else { - moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) || - !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)); - if(!moreData) { - /* This should never happen but if it happens, we need a way out */ - unifi_error(priv, "ERROR: No More Data but DTIM is active sending Response\n"); - send_vif_availibility_rsp(priv, uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag), CSR_RC_NO_BUFFERED_BROADCAST_MULTICAST_FRAMES); - interfacePriv->dtimActive = FALSE; - } - } - return; - } - if(priv->pausedStaHandle[queue] > 7) { - priv->pausedStaHandle[queue] = 0; - } - - if(queue == UNIFI_TRAFFIC_Q_VO) { - - - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : trying mgt from queue=%d\n", queue); - for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { - staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv, startIndex, interfaceTag); - if(!staInfo ) { - continue; - } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == FALSE) ) { - continue; - } - - if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - &&(staInfo->uapsdActive == FALSE)){ - /*Non-UAPSD case push the management frames out*/ - if(!list_empty(&staInfo->mgtFrames)){ - uf_send_buffered_data_from_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); - } - } - - if(isRouterBufferEnabled(priv, queue)) { - unifi_notice(priv, "uf_send_buffered_frames : No space Left for queue = %d\n", queue); - break; - } - } - /*push generic management frames out*/ - if(!list_empty(&interfacePriv->genericMgtFrames)) { - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : trying generic mgt from queue=%d\n", queue); - uf_send_buffered_data_from_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames); - } - } - - - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : Resume called for Queue=%d\n", queue); - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : start=%d end=%d\n", startIndex, endIndex); - - startIndex = priv->pausedStaHandle[queue]; - endIndex = (startIndex + UNIFI_MAX_CONNECTIONS -1) % UNIFI_MAX_CONNECTIONS; - - while(startIndex != endIndex) { - staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv, startIndex, interfaceTag); - if(!staInfo) { - startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS) { - startIndex = 0; - } - continue; - } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&(staInfo->uapsdActive == FALSE)) { - startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS) { - startIndex = 0; - } - continue; - } - /* Peer is active or U-APSD is active so send PDUs to the peer */ - unifi_trace(priv, UDBG2, "uf_send_buffered_frames : trying data from queue=%d\n", queue); - - - if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - &&(staInfo->uapsdActive == FALSE)) { - if(!list_empty(&staInfo->dataPdu[queue])) { - - /*Non-UAPSD case push the AC frames out*/ - uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue])); - } - } - startIndex ++; - if(startIndex >= UNIFI_MAX_CONNECTIONS) { - startIndex = 0; - } - } - if(isRouterBufferEnabled(priv, queue)) { - priv->pausedStaHandle[queue] = endIndex; - } else { - priv->pausedStaHandle[queue] = 0; - } - - /* U-APSD might have stopped because of ENOSPC in lib_hip (pause activity). - * So restart it if U-APSD was active with any of the station - */ - unifi_trace(priv, UDBG4, "csrWifiHipSendBufferedFrames: UAPSD Resume Q=%x\n", queue); - resume_suspended_uapsd(priv, interfaceTag); -} - - -u8 uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord) -{ - u8 i; - - for(i=0;i<=3;i++) - { - if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) - ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_LEGACY_POWER_SAVE)) - &&(!list_empty(&staRecord->dataPdu[i]))){ - - return TRUE; - } - } - - if(((staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) - ||(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_LEGACY_POWER_SAVE)) - &&(!list_empty(&staRecord->mgtFrames))){ - - return TRUE; - } - - - - return FALSE; -} - - -int uf_process_station_records_for_sending_data(unifi_priv_t *priv, u16 interfaceTag, - CsrWifiRouterCtrlStaInfo_t *srcStaInfo, - CsrWifiRouterCtrlStaInfo_t *dstStaInfo) -{ - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG5, "entering uf_process_station_records_for_sending_data\n"); - - if (srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED) { - unifi_error(priv, "Peer State not connected AID = %x, handle = %x, control port state = %x\n", - srcStaInfo->aid, srcStaInfo->assignedHandle, srcStaInfo->peerControlledPort->port_action); - return -1; - } - switch (interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - unifi_trace(priv, UDBG5, "mode is AP/P2PGO\n"); - break; - default: - unifi_warning(priv, "mode is nor AP neither P2PGO, packet cant be xmit\n"); - return -1; - } - - switch(dstStaInfo->peerControlledPort->port_action) - { - case CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD: - case CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_BLOCK: - unifi_trace(priv, UDBG5, "destination port is closed/blocked, discarding the packet\n"); - return -1; - default: - unifi_trace(priv, UDBG5, "destination port state is open\n"); - } - - /* port state is open, destination station record is valid, Power save state is - * validated in uf_process_ma_packet_req function - */ - unifi_trace(priv, UDBG5, "leaving uf_process_station_records_for_sending_data\n"); - return 0; -} - - -/* - * --------------------------------------------------------------------------- - * uf_handle_uspframes_delivery - * - * This function takes care of handling USP session for peer, when - * -> trigger frame from peer - * -> suspended USP to be processed (resumed) - * - * NOTE: uf_send_buffered_data_from_delivery_ac() always called from this function, Dont - * make a direct call to uf_send_buffered_data_from_delivery_ac() from any other part of - * code - * - * Arguments: - * priv Pointer to device private context struct - * staInfo peer for which UAPSD to be scheduled - * interfaceTag virtual interface tag - * --------------------------------------------------------------------------- - */ -static void uf_handle_uspframes_delivery(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t *staInfo, u16 interfaceTag) -{ - - s8 i; - u8 allDeliveryEnabled = 0, dataAvailable = 0; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - unsigned long lock_flags; - - unifi_trace(priv, UDBG2, " ++ uf_handle_uspframes_delivery, uapsd active=%x, suspended?=%x\n", - staInfo->uapsdActive, staInfo->uspSuspend); - - /* Check for Buffered frames according to priority order & deliver it - * 1. AC_VO delivery enable & Mgt frames available - * 2. Process remaining Ac's from order AC_VO to AC_BK - */ - - /* USP initiated by WMMPS enabled peer & SET the status flag to TRUE */ - if (!staInfo->uspSuspend && staInfo->uapsdActive) - { - unifi_notice(priv, "uf_handle_uspframes_delivery: U-APSD already active! STA=%x:%x:%x:%x:%x:%x\n", - staInfo->peerMacAddress.a[0], staInfo->peerMacAddress.a[1], - staInfo->peerMacAddress.a[2], staInfo->peerMacAddress.a[3], - staInfo->peerMacAddress.a[4], staInfo->peerMacAddress.a[5]); - return; - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->uapsdActive = TRUE; - staInfo->uspSuspend = FALSE; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)|| - (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)) - && (!list_empty(&staInfo->mgtFrames))) { - - /* Management queue has data && UNIFI_TRAFFIC_Q_VO is delivery enable */ - unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Sending buffered management frames\n"); - uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames); - } - - if (!uf_is_more_data_for_delivery_ac(priv, staInfo)) { - /* All delivery enable AC's are empty, so QNULL to be sent to terminate the USP - * NOTE: If we have sent Mgt frame also, we must send QNULL followed to terminate USP - */ - if (!staInfo->uspSuspend) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->uapsdActive = FALSE; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: sending QNull for trigger\n"); - uf_send_qos_null(priv, interfaceTag, staInfo->peerMacAddress.a, (CSR_PRIORITY) staInfo->triggerFramePriority, staInfo); - staInfo->triggerFramePriority = CSR_QOS_UP0; - } else { - unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: MgtQ xfer suspended\n"); - } - } else { - for(i = UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--) { - if(((staInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE) - ||(staInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) - && (!list_empty(&staInfo->dataPdu[i]))) { - /* Deliver Data according to AC priority (from VO to BK) as part of USP */ - unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Buffered data frames from Queue (%d) for USP\n", i); - uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]); - } - - if ((!staInfo->uapsdActive) || - (staInfo->uspSuspend && IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag))) { - /* If DTIM active found on one AC, No need to parse the remaining AC's - * as USP suspended. Break out of loop - */ - unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: suspend=%x, DTIM=%x, USP terminated=%s\n", - staInfo->uspSuspend, IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag), - staInfo->uapsdActive?"NO":"YES"); - break; - } - } - } - - /* Depending on the USP status, update the TIM accordingly for delivery enabled AC only - * (since we are not manipulating any Non-delivery list(AC)) - */ - is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable); - if ((allDeliveryEnabled && !dataAvailable)) { - if ((staInfo->timSet != CSR_WIFI_TIM_RESET) && (staInfo->timSet != CSR_WIFI_TIM_RESETTING)) { - staInfo->updateTimReqQueued = (u8) CSR_WIFI_TIM_RESET; - unifi_trace(priv, UDBG4, " --uf_handle_uspframes_delivery, UAPSD timset\n"); - if (!staInfo->timRequestPendingFlag) { - update_tim(priv, staInfo->aid, 0, interfaceTag, staInfo->assignedHandle); - } - } - } - unifi_trace(priv, UDBG2, " --uf_handle_uspframes_delivery, uapsd active=%x, suspend?=%x\n", - staInfo->uapsdActive, staInfo->uspSuspend); -} - -void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv, - CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - u16 qosControl, - u16 interfaceTag) -{ - CSR_PRIORITY priority; - unifi_TrafficQueue priority_q; - unsigned long lock_flags; - - unifi_trace(priv, UDBG2, "++uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive); - /* If recceived Frames trigger Frame and Devlivery enabled AC has data - * then transmit from High priorty delivery enabled AC - */ - priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK); - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - - if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED) - ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - srcStaInfo->triggerFramePriority = priority; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - unifi_trace(priv, UDBG2, "uf_process_wmm_deliver_ac_uapsd: trigger frame, Begin U-APSD, triggerQ=%x\n", priority_q); - uf_handle_uspframes_delivery(priv, srcStaInfo, interfaceTag); - } - unifi_trace(priv, UDBG2, "--uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive); -} - - -void uf_send_qos_null(unifi_priv_t * priv, u16 interfaceTag, const u8 *da, CSR_PRIORITY priority, CsrWifiRouterCtrlStaInfo_t * srcStaInfo) -{ - bulk_data_param_t bulkdata; - CsrResult csrResult; - struct sk_buff *skb, *newSkb = NULL; - CsrWifiMacAddress peerAddress; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_EOSP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK); - int r; - CSR_SIGNAL signal; - u32 priority_q; - CSR_RATE transmitRate = 0; - - - /* Send a Null Frame to Peer, - * 32= size of mac header */ - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE + QOS_CONTROL_HEADER_SIZE); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, " failed to allocate request_data. in uf_send_qos_null func\n"); - return ; - } - skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); - skb->len = 0; - bulkdata.d[0].os_data_ptr = skb->data; - bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; - - /* For null frames protection bit should not be set in MAC header, so passing value 0 below for protection field */ - - if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, da, interfacePriv->bssid.a, 0)) { - unifi_error(priv, "failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - memcpy(peerAddress.a, ((u8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); - /* convert priority to queue */ - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - - /* Frame ma-packet.req, this is saved/transmitted depend on queue state - * send the null frame at data rate of 1 Mb/s for AP or 6 Mb/s for P2PGO - */ - switch (interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - transmitRate = 2; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - transmitRate = 12; - break; - default: - transmitRate = 0; - } - unifi_frame_ma_packet_req(priv, priority, transmitRate, 0xffffffff, interfaceTag, - transmissionControl, priv->netdev_client->sender_id, - peerAddress.a, &signal); - - r = ul_send_signal_unpacked(priv, &signal, &bulkdata); - if(r) { - unifi_error(priv, "failed to send QOS data null packet result: %d\n", r); - unifi_net_data_free(priv, &bulkdata.d[0]); - } - - return; - -} -void uf_send_nulldata(unifi_priv_t * priv, u16 interfaceTag, const u8 *da, CSR_PRIORITY priority, CsrWifiRouterCtrlStaInfo_t * srcStaInfo) -{ - bulk_data_param_t bulkdata; - CsrResult csrResult; - struct sk_buff *skb, *newSkb = NULL; - CsrWifiMacAddress peerAddress; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CSR_TRANSMISSION_CONTROL transmissionControl = 0; - int r; - CSR_SIGNAL signal; - u32 priority_q; - CSR_RATE transmitRate = 0; - CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; - unsigned long lock_flags; - - /* Send a Null Frame to Peer, size = 24 for MAC header */ - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], MAC_HEADER_SIZE); - - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "uf_send_nulldata: Failed to allocate memory for NULL frame\n"); - return ; - } - skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); - skb->len = 0; - bulkdata.d[0].os_data_ptr = skb->data; - bulkdata.d[0].os_net_buf_ptr = (unsigned char*)skb; - bulkdata.d[0].net_buf_length = bulkdata.d[0].data_length = skb->len; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; - - /* For null frames protection bit should not be set in MAC header, so passing value 0 below for protection field */ - if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, interfaceTag, da, interfacePriv->bssid.a, 0)) { - unifi_error(priv, "uf_send_nulldata: Failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - memcpy(peerAddress.a, ((u8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN); - /* convert priority to queue */ - priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority); - transmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED); - - /* Frame ma-packet.req, this is saved/transmitted depend on queue state - * send the null frame at data rate of 1 Mb/s for AP or 6 Mb/s for P2PGO - */ - switch (interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - transmitRate = 2; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - transmitRate = 12; - break; - default: - transmitRate = 0; - } - unifi_frame_ma_packet_req(priv, priority, transmitRate, INVALID_HOST_TAG, interfaceTag, - transmissionControl, priv->netdev_client->sender_id, - peerAddress.a, &signal); - - /* Save host tag to check the status on reception of MA packet confirm */ - srcStaInfo->nullDataHostTag = req->HostTag; - unifi_trace(priv, UDBG1, "uf_send_nulldata: STA AID = %d hostTag = %x\n", srcStaInfo->aid, req->HostTag); - - r = ul_send_signal_unpacked(priv, &signal, &bulkdata); - - if(r == -ENOSPC) { - unifi_trace(priv, UDBG1, "uf_send_nulldata: ENOSPC Requeue the Null frame\n"); - enque_tx_data_pdu(priv, &bulkdata, &srcStaInfo->dataPdu[priority_q], &signal, 1); - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - srcStaInfo->noOfPktQueued++; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - - } - if(r && r != -ENOSPC){ - unifi_error(priv, "uf_send_nulldata: Failed to send Null frame Error = %d\n", r); - unifi_net_data_free(priv, &bulkdata.d[0]); - srcStaInfo->nullDataHostTag = INVALID_HOST_TAG; - } - - return; -} - -u8 uf_check_broadcast_bssid(unifi_priv_t *priv, const bulk_data_param_t *bulkdata) -{ - u8 *bssid = NULL; - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - u8 toDs, fromDs; - - toDs = (((bulkdata->d[0].os_data_ptr)[1]) & 0x01) ? 1 : 0; - fromDs =(((bulkdata->d[0].os_data_ptr)[1]) & 0x02) ? 1 : 0; - - if (toDs && fromDs) - { - unifi_trace(priv, UDBG6, "Address 4 present, Don't try to find BSSID\n"); - bssid = NULL; - } - else if((toDs == 0) && (fromDs ==0)) - { - /* BSSID is Address 3 */ - bssid = (u8 *) (bulkdata->d[0].os_data_ptr + 4 + (2 * ETH_ALEN)); - } - else if(toDs) - { - /* BSSID is Address 1 */ - bssid = (u8 *) (bulkdata->d[0].os_data_ptr + 4); - } - else if(fromDs) - { - /* BSSID is Address 2 */ - bssid = (u8 *) (bulkdata->d[0].os_data_ptr + 4 + ETH_ALEN); - } - - if (memcmp(broadcast_address.a, bssid, ETH_ALEN)== 0) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -u8 uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - u8 pmBit, u16 interfaceTag) -{ - u8 moreData = FALSE; - u8 powerSaveChanged = FALSE; - unsigned long lock_flags; - - unifi_trace(priv, UDBG3, "entering uf_process_pm_bit_for_peer\n"); - if (pmBit) { - priv->allPeerDozing |= (0x01 << (srcStaInfo->assignedHandle)); - } else { - priv->allPeerDozing &= ~(0x01 << (srcStaInfo->assignedHandle)); - } - if(pmBit) { - if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) { - - /* disable the preemption */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - srcStaInfo->currentPeerState =CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE; - powerSaveChanged = TRUE; - /* enable the preemption */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } else { - return powerSaveChanged; - } - } else { - if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) { - /* disable the preemption */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - srcStaInfo->currentPeerState = CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE; - powerSaveChanged = TRUE; - /* enable the preemption */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - }else { - return powerSaveChanged; - } - } - - - if(srcStaInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) { - unifi_trace(priv, UDBG3, "Peer with AID = %d is active now\n", srcStaInfo->aid); - process_peer_active_transition(priv, srcStaInfo, interfaceTag); - } else { - unifi_trace(priv, UDBG3, "Peer with AID = %d is in PS Now\n", srcStaInfo->aid); - /* Set TIM if needed */ - if(!srcStaInfo->wmmOrQosEnabled) { - moreData = (!list_empty(&srcStaInfo->mgtFrames) || - !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_VO])|| - !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])); - if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { - unifi_trace(priv, UDBG3, "This condition should not occur\n"); - if (!srcStaInfo->timRequestPendingFlag){ - update_tim(priv, srcStaInfo->aid, 1, interfaceTag, srcStaInfo->assignedHandle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - srcStaInfo->updateTimReqQueued = 1; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued, - srcStaInfo->aid); - } - - } - } else { - u8 allDeliveryEnabled = 0, dataAvailable = 0; - unifi_trace(priv, UDBG5, "Qos in AP Mode\n"); - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(srcStaInfo, &allDeliveryEnabled, &dataAvailable); - /*check for more data in non-delivery enabled queues*/ - moreData = (uf_is_more_data_for_non_delivery_ac(srcStaInfo) || (allDeliveryEnabled && dataAvailable)); - - if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) { - if (!srcStaInfo->timRequestPendingFlag){ - update_tim(priv, srcStaInfo->aid, 1, interfaceTag, srcStaInfo->assignedHandle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - srcStaInfo->updateTimReqQueued = 1; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued, - srcStaInfo->aid); - } - } - } - } - unifi_trace(priv, UDBG3, "leaving uf_process_pm_bit_for_peer\n"); - return powerSaveChanged; -} - - - -void uf_process_ps_poll(unifi_priv_t *priv, u8* sa, u8* da, u8 pmBit, u16 interfaceTag) -{ - CsrWifiRouterCtrlStaInfo_t *staRecord = - CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, sa, interfaceTag); - tx_buffered_packets_t * buffered_pkt = NULL; - CsrWifiMacAddress peerMacAddress; - unsigned long lock_flags; - s8 r =0; - u8 moreData = FALSE; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - unifi_trace(priv, UDBG3, "entering uf_process_ps_poll\n"); - if(!staRecord) { - memcpy(peerMacAddress.a, sa, ETH_ALEN); - unifi_trace(priv, UDBG3, "In uf_process_ps_poll, sta record not found:unexpected frame addr = %x:%x:%x:%x:%x:%x\n", - sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - CsrWifiRouterCtrlUnexpectedFrameIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - return; - } - - uf_process_pm_bit_for_peer(priv, staRecord, pmBit, interfaceTag); - - /* Update station last activity time */ - staRecord->activity_flag = TRUE; - - /* This should not change the PM bit as PS-POLL has PM bit always set */ - if(!pmBit) { - unifi_notice (priv, " PM bit reset in PS-POLL\n"); - return; - } - - if(IS_DTIM_ACTIVE(interfacePriv->dtimActive, interfacePriv->multicastPduHostTag)) { - /* giving more priority to multicast packets so dropping ps-poll*/ - unifi_notice (priv, " multicast transmission is going on so don't take action on PS-POLL\n"); - return; - } - - if(!staRecord->wmmOrQosEnabled) { - if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { - buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; - moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || - !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || - !list_empty(&staRecord->mgtFrames)); - - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->mgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - priv->pausedStaHandle[3]=(u8)(staRecord->assignedHandle); - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } else if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]))) { - buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; - moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || - !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO])); - - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[3]=(u8)(staRecord->assignedHandle); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } else if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]))) { - buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK; - moreData = !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); - - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[0]=(u8)(staRecord->assignedHandle); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } else { - /* Actually since we have sent an ACK, there - * there is no need to send a NULL frame*/ - } - moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || - !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) || - !list_empty(&staRecord->mgtFrames)); - if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { - unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); - if (!staRecord->timRequestPendingFlag){ - update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 0; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - } - } else { - - u8 allDeliveryEnabled = 0, dataAvailable = 0; - unifi_trace(priv, UDBG3, "Qos Support station.Processing PS-Poll\n"); - - /*Send Data From Management Frames*/ - /* Priority orders for delivering the buffered packets are - * 1. Deliver the Management frames if there - * 2. Other access category frames which are non deliver enable including UNIFI_TRAFFIC_Q_VO - * priority is from VO->BK - */ - - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - - if (allDeliveryEnabled) { - unifi_trace(priv, UDBG3, "uf_process_ps_poll: All ACs are delivery enable so Sending QOS Null in response of Ps-poll\n"); - uf_send_qos_null(priv, interfaceTag, sa, CSR_QOS_UP0, staRecord); - return; - } - - if (!list_empty(&staRecord->mgtFrames)) { - if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) { - /* We dont have packets in non delivery enabled UNIFI_TRAFFIC_Q_VO, So we are looking in management - * queue of the station record - */ - moreData = uf_is_more_data_for_non_delivery_ac(staRecord); - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - - /* Last parameter is EOSP & its false always for PS-POLL processing */ - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->mgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[0]=(u8)(staRecord->assignedHandle); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } else { - unifi_error(priv, "uf_process_ps_poll: Mgt frame list empty!! \n"); - } - - } else { - s8 i; - /* We dont have buffered packet in mangement frame queue (1 failed), So proceed with condition 2 - * UNIFI_TRAFFIC_Q_VO -> VI -> BE -> BK - */ - for(i= 3; i>=0; i--) { - if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) { - /* Send One packet, if queue is NULL then continue */ - if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) { - moreData = uf_is_more_data_for_non_delivery_ac(staRecord); - - buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - - /* Last parameter is EOSP & its false always for PS-POLL processing */ - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staRecord, moreData, FALSE)) == -ENOSPC) { - /* Clear the trigger bit transmission control*/ - buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staRecord->dataPdu[i]); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[0]=(u8)(staRecord->assignedHandle); - unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n"); - } else { - if(r) { - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - break; - } - } - } - } - /* Check if all AC's are Delivery Enabled */ - is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable); - /*check for more data in non-delivery enabled queues*/ - moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)); - if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) { - unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n"); - if (!staRecord->timRequestPendingFlag){ - update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle); - } - else - { - /* Cache the TimSet value so that it will processed immidiatly after - * completing the current setTim Request - */ - staRecord->updateTimReqQueued = 0; - unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued, - staRecord->aid); - } - - } - } - - unifi_trace(priv, UDBG3, "leaving uf_process_ps_poll\n"); -} - - - -void add_to_send_cfm_list(unifi_priv_t * priv, - tx_buffered_packets_t *tx_q_item, - struct list_head *frames_need_cfm_list) -{ - tx_buffered_packets_t *send_cfm_list_item = NULL; - - send_cfm_list_item = kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC); - - if(send_cfm_list_item == NULL){ - unifi_warning(priv, "%s: Failed to allocate memory for new list item \n"); - return; - } - - INIT_LIST_HEAD(&send_cfm_list_item->q); - - send_cfm_list_item->hostTag = tx_q_item->hostTag; - send_cfm_list_item->interfaceTag = tx_q_item->interfaceTag; - send_cfm_list_item->transmissionControl = tx_q_item->transmissionControl; - send_cfm_list_item->leSenderProcessId = tx_q_item->leSenderProcessId; - send_cfm_list_item->rate = tx_q_item->rate; - memcpy(send_cfm_list_item->peerMacAddress.a, tx_q_item->peerMacAddress.a, ETH_ALEN); - send_cfm_list_item->priority = tx_q_item->priority; - - list_add_tail(&send_cfm_list_item->q, frames_need_cfm_list); -} - -void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv, - struct list_head *frames_need_cfm_list, - struct list_head * list) -{ - tx_buffered_packets_t *tx_q_item = NULL; - struct list_head *listHead; - struct list_head *placeHolder; - unsigned long lock_flags; - - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - - /* Search through the list and if confirmation required for any frames, - add it to the send_cfm list */ - list_for_each_safe(listHead, placeHolder, list) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - - if(!tx_q_item) { - unifi_error(priv, "Entry should exist, otherwise it is a (BUG)\n"); - continue; - } - - /* check if confirmation is requested and if the sender ID - is not netdevice client then save the entry in the list for need cfms */ - if (!(tx_q_item->transmissionControl & CSR_NO_CONFIRM_REQUIRED) && - (tx_q_item->leSenderProcessId != priv->netdev_client->sender_id)){ - unifi_trace(priv, UDBG1, "%s: SenderProcessID=%x host tag=%x transmission control=%x\n", - __FUNCTION__, - tx_q_item->leSenderProcessId, - tx_q_item->hostTag, - tx_q_item->transmissionControl); - - add_to_send_cfm_list(priv, tx_q_item, frames_need_cfm_list); - } - } - - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - -} - - - -void uf_flush_list(unifi_priv_t * priv, struct list_head * list) -{ - tx_buffered_packets_t *tx_q_item; - struct list_head *listHead; - struct list_head *placeHolder; - unsigned long lock_flags; - - unifi_trace(priv, UDBG5, "entering the uf_flush_list \n"); - - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - /* go through list, delete & free memory */ - list_for_each_safe(listHead, placeHolder, list) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - - if(!tx_q_item) { - unifi_error(priv, "entry should exists, otherwise crashes (bug)\n"); - } - unifi_trace(priv, UDBG5, - "proccess_tx: in uf_flush_list peerMacAddress=%02X%02X%02X%02X%02X%02X senderProcessId=%x\n", - tx_q_item->peerMacAddress.a[0], tx_q_item->peerMacAddress.a[1], - tx_q_item->peerMacAddress.a[2], tx_q_item->peerMacAddress.a[3], - tx_q_item->peerMacAddress.a[4], tx_q_item->peerMacAddress.a[5], - tx_q_item->leSenderProcessId); - - list_del(listHead); - /* free the allocated memory */ - unifi_net_data_free(priv, &tx_q_item->bulkdata); - kfree(tx_q_item); - tx_q_item = NULL; - if (!priv->noOfPktQueuedInDriver) { - unifi_error(priv, "packets queued in driver 0 still decrementing in %s\n", __FUNCTION__); - } else { - priv->noOfPktQueuedInDriver--; - } - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); -} - -tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList) -{ - /* dequeue the tx data packets from the appropriate queue */ - tx_buffered_packets_t *tx_q_item = NULL; - struct list_head *listHead; - struct list_head *placeHolder; - unsigned long lock_flags; - - unifi_trace(priv, UDBG5, "entering dequeue_tx_data_pdu\n"); - /* check for list empty */ - if (list_empty(txList)) { - unifi_trace(priv, UDBG5, "In dequeue_tx_data_pdu, the list is empty\n"); - return NULL; - } - - /* Verification, if packet count is negetive */ - if (priv->noOfPktQueuedInDriver == 0xFFFF) { - unifi_warning(priv, "no packet available in queue: debug"); - return NULL; - } - - /* return first node after header, & delete from the list && atleast one item exist */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_for_each_safe(listHead, placeHolder, txList) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - list_del(listHead); - break; - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - - if (tx_q_item) { - unifi_trace(priv, UDBG5, - "proccess_tx: In dequeue_tx_data_pdu peerMacAddress=%02X%02X%02X%02X%02X%02X senderProcessId=%x\n", - tx_q_item->peerMacAddress.a[0], tx_q_item->peerMacAddress.a[1], - tx_q_item->peerMacAddress.a[2], tx_q_item->peerMacAddress.a[3], - tx_q_item->peerMacAddress.a[4], tx_q_item->peerMacAddress.a[5], - tx_q_item->leSenderProcessId); - } - - unifi_trace(priv, UDBG5, "leaving dequeue_tx_data_pdu\n"); - return tx_q_item; -} -/* generic function to get the station record handler */ -CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(unifi_priv_t *priv, - const u8 *peerMacAddress, - u16 interfaceTag) -{ - u8 i; - netInterface_priv_t *interfacePriv; - unsigned long lock_flags; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "interfaceTag is not proper, interfaceTag = %d\n", interfaceTag); - return NULL; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* disable the preemption until station record is fetched */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - - for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if (interfacePriv->staInfo[i]!= NULL) { - if (!memcmp(((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]))->peerMacAddress.a, peerMacAddress, ETH_ALEN)) { - /* enable the preemption as station record is fetched */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - unifi_trace(priv, UDBG5, "peer entry found in station record\n"); - return ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i])); - } - } - } - /* enable the preemption as station record is fetched */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - unifi_trace(priv, UDBG5, "peer entry not found in station record\n"); - return NULL; -} -/* generic function to get the station record handler from the handle */ -CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_priv_t *priv, - u32 handle, - u16 interfaceTag) -{ - netInterface_priv_t *interfacePriv; - - if ((handle >= UNIFI_MAX_CONNECTIONS) || (interfaceTag >= CSR_WIFI_NUM_INTERFACES)) { - unifi_error(priv, "handle/interfaceTag is not proper, handle = %d, interfaceTag = %d\n", handle, interfaceTag); - return NULL; - } - interfacePriv = priv->interfacePriv[interfaceTag]; - return ((CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[handle])); -} - -/* Function to do inactivity */ -void uf_check_inactivity(unifi_priv_t *priv, u16 interfaceTag, u32 currentTime) -{ - u32 i; - CsrWifiRouterCtrlStaInfo_t *staInfo; - u32 elapsedTime; /* Time in microseconds */ - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CsrWifiMacAddress peerMacAddress; - unsigned long lock_flags; - - if (interfacePriv == NULL) { - unifi_trace(priv, UDBG3, "uf_check_inactivity: Interface priv is NULL \n"); - return; - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Go through the list of stations to check for inactivity */ - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv, i, interfaceTag); - if(!staInfo ) { - continue; - } - - unifi_trace(priv, UDBG3, "Running Inactivity handler Time %xus station's last activity %xus\n", - currentTime, staInfo->lastActivity); - - - elapsedTime = (currentTime >= staInfo->lastActivity)? - (currentTime - staInfo->lastActivity): - (~((u32)0) - staInfo->lastActivity + currentTime); - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - if (elapsedTime > MAX_INACTIVITY_INTERVAL) { - memcpy((u8*)&peerMacAddress, (u8*)&staInfo->peerMacAddress, sizeof(CsrWifiMacAddress)); - - /* Indicate inactivity for the station */ - unifi_trace(priv, UDBG3, "Station %x:%x:%x:%x:%x:%x inactive since %xus\n sending Inactive Ind\n", - peerMacAddress.a[0], peerMacAddress.a[1], - peerMacAddress.a[2], peerMacAddress.a[3], - peerMacAddress.a[4], peerMacAddress.a[5], - elapsedTime); - - CsrWifiRouterCtrlStaInactiveIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - } - } - - interfacePriv->last_inactivity_check = currentTime; -} - -/* Function to update activity of a station */ -void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress) -{ - u32 elapsedTime, currentTime; /* Time in microseconds */ - u32 timeHi; /* Not used - Time in microseconds */ - CsrWifiRouterCtrlStaInfo_t *staInfo; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - unsigned long lock_flags; - - if (interfacePriv == NULL) { - unifi_trace(priv, UDBG3, "uf_check_inactivity: Interface priv is NULL \n"); - return; - } - - currentTime = CsrTimeGet(&timeHi); - - - staInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, peerMacAddress, interfaceTag); - - if (staInfo == NULL) { - unifi_trace(priv, UDBG4, "Sta does not exist yet"); - return; - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Update activity */ - staInfo->lastActivity = currentTime; - - /* See if inactivity handler needs to be run - * Here it is theoretically possible that the counter may have wrapped around. But - * since we just want to know when to run the inactivity handler it does not really matter. - * Especially since this is data path it makes sense in keeping it simple and avoiding - * 64 bit handling */ - elapsedTime = (currentTime >= interfacePriv->last_inactivity_check)? - (currentTime - interfacePriv->last_inactivity_check): - (~((u32)0) - interfacePriv->last_inactivity_check + currentTime); - - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - /* Check if it is time to run the inactivity handler */ - if (elapsedTime > INACTIVITY_CHECK_INTERVAL) { - uf_check_inactivity(priv, interfaceTag, currentTime); - } -} -void resume_unicast_buffered_frames(unifi_priv_t *priv, u16 interfaceTag) -{ - - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - u8 i; - int j; - tx_buffered_packets_t * buffered_pkt = NULL; - u8 hipslotFree[4] = {TRUE, TRUE, TRUE, TRUE}; - int r; - unsigned long lock_flags; - - while(!isRouterBufferEnabled(priv, 3) && - ((buffered_pkt=dequeue_tx_data_pdu(priv, &interfacePriv->genericMgtFrames))!=NULL)) { - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, NULL, 0, FALSE)) == -ENOSPC) { - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &interfacePriv->genericMgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - hipslotFree[3]=FALSE; - break; - }else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - CsrWifiRouterCtrlStaInfo_t *staInfo = interfacePriv->staInfo[i]; - if(!hipslotFree[0] && !hipslotFree[1] && !hipslotFree[2] && !hipslotFree[3]) { - unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full \n"); - break; - } - if (staInfo && (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)) { - while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) { - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staInfo, 0, FALSE)) == -ENOSPC) { - unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full for voice queue\n"); - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staInfo->mgtFrames); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[3]=(u8)(staInfo->assignedHandle); - hipslotFree[3] = FALSE; - break; - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - - for(j=3;j>=0;j--) { - if(!hipslotFree[j]) - continue; - - while((buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->dataPdu[j]))) { - buffered_pkt->transmissionControl &= - ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK); - if((r=frame_and_send_queued_pdu(priv, buffered_pkt, staInfo, 0, FALSE)) == -ENOSPC) { - /* Enqueue at the head of the queue */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_add(&buffered_pkt->q, &staInfo->dataPdu[j]); - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - priv->pausedStaHandle[j]=(u8)(staInfo->assignedHandle); - hipslotFree[j]=FALSE; - break; - } else { - if(r){ - unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n"); - /* the PDU failed where we can't do any thing so free the storage */ - unifi_net_data_free(priv, &buffered_pkt->bulkdata); - } - kfree(buffered_pkt); - } - } - } - } - } -} -void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv, u16 interfaceTag) -{ - - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - unsigned long lock_flags; - struct list_head *listHead; - struct list_head *placeHolder; - tx_buffered_packets_t *tx_q_item; - - if (interfacePriv->noOfbroadcastPktQueued) { - - /* Update the EOSP to the HEAD of b/c list - * because we have received any mgmt packet so it should not hold for long time - * peer may time out. - */ - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) { - tx_q_item = list_entry(listHead, tx_buffered_packets_t, q); - tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK; - tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED)); - unifi_trace(priv, UDBG1, "updating eosp for list Head hostTag:= 0x%x ", tx_q_item->hostTag); - break; - } - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } -} - -/* - * --------------------------------------------------------------------------- - * resume_suspended_uapsd - * - * This function takes care processing packets of Unscheduled Service Period, - * which been suspended earlier due to DTIM/HIP ENOSPC scenarios - * - * Arguments: - * priv Pointer to device private context struct - * interfaceTag For which resume should happen - * --------------------------------------------------------------------------- - */ -void resume_suspended_uapsd(unifi_priv_t* priv, u16 interfaceTag) -{ - - u8 startIndex; - CsrWifiRouterCtrlStaInfo_t * staInfo = NULL; - unsigned long lock_flags; - - unifi_trace(priv, UDBG2, "++resume_suspended_uapsd: \n"); - for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) { - staInfo = CsrWifiRouterCtrlGetStationRecordFromHandle(priv, startIndex, interfaceTag); - - if(!staInfo || !staInfo->wmmOrQosEnabled) { - continue; - } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - &&staInfo->uapsdActive && staInfo->uspSuspend) { - /* U-APSD Still active & previously suspended either ENOSPC of FH queues OR - * due to DTIM activity - */ - uf_handle_uspframes_delivery(priv, staInfo, interfaceTag); - } else { - unifi_trace(priv, UDBG2, "resume_suspended_uapsd: PS state=%x, uapsdActive?=%x, suspend?=%x\n", - staInfo->currentPeerState, staInfo->uapsdActive, staInfo->uspSuspend); - if (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - { - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - staInfo->uapsdActive = FALSE; - staInfo->uspSuspend = FALSE; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - } - unifi_trace(priv, UDBG2, "--resume_suspended_uapsd:\n"); -} - -#endif diff --git a/drivers/staging/csr/unifi_priv.h b/drivers/staging/csr/unifi_priv.h deleted file mode 100644 index 37302f3c2f6c..000000000000 --- a/drivers/staging/csr/unifi_priv.h +++ /dev/null @@ -1,1136 +0,0 @@ -/* - ***************************************************************************** - * - * FILE : unifi_priv.h - * - * PURPOSE : Private header file for unifi driver. - * - * UDI = UniFi Debug Interface - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - ***************************************************************************** - */ -#ifndef __LINUX_UNIFI_PRIV_H__ -#define __LINUX_UNIFI_PRIV_H__ 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CSR_WIFI_SUPPORT_MMC_DRIVER -#include -#include -#include -#include -#include -#include -#endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ - -#include - -#ifdef ANDROID_BUILD -#include -#endif - -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_unifi_udi.h" -#include "csr_wifi_router_lib.h" -#include "unifiio.h" -#ifndef CSR_WIFI_HIP_TA_DISABLE -#include "csr_wifi_vif_utils.h" -#endif - -/* Define the unifi_priv_t before include the unifi_native.h */ -struct unifi_priv; -typedef struct unifi_priv unifi_priv_t; -#ifdef CSR_SUPPORT_WEXT_AP -struct CsrWifiSmeApConfig; -typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; -#endif -#ifdef CSR_SUPPORT_WEXT -#include "unifi_wext.h" -#endif - -#ifdef ANDROID_BUILD -extern struct wake_lock unifi_sdio_wake_lock; -#endif - -#include "unifi_clients.h" - -#ifdef CSR_NATIVE_LINUX -#include "sme_native/unifi_native.h" -#else -#include "unifi_sme.h" -#endif - -/* The device major number to use when registering the udi driver */ -#define UNIFI_NAME "unifi" -/* - * MAX_UNIFI_DEVS defines the maximum number of UniFi devices that can be present. - * This number should be set to the number of SDIO slots supported by the SDIO - * host controller on the platform. - * Note: If MAX_UNIFI_DEVS value changes, fw_init[] needs to be corrected in drv.c - */ -#define MAX_UNIFI_DEVS 2 - -/* 802.11 Mac header offsets */ -#define MAC_HEADER_SIZE 24 -#define QOS_CONTROL_HEADER_SIZE 2 -#define HT_CONTROL_HEADER_SIZE 4 -#define QOS_DATA 0x8 -#define QOS_DATA_NULL 0xc -#define DATA_NULL 0x04 -#define FRAME_CONTROL_ORDER_BIT 0x8000 -#define FRAME_CONTROL_TYPE_FIELD_OFFSET 2 -#define FRAME_CONTROL_SUBTYPE_FIELD_OFFSET 4 -#define IEEE802_11_FRAMETYPE_DATA 0x02 -#define IEEE802_11_FRAMETYPE_CONTROL 0x01 -#define IEEE802_11_FRAMETYPE_MANAGEMENT 0x00 -#define IEEE802_11_FRAMETYPE_RESERVED 0x03 - -/* octet offset from start of mac header for certain fields */ -#define IEEE802_11_ADDR3_OFFSET 16 -#define IEEE802_11_SEQUENCE_CONTROL_OFFSET 22 -#define IEEE802_11_MAX_DATA_LEN 2304 - -/* frame control (FC) masks, for frame control as 16 bit integer */ -#define IEEE802_11_FC_TO_DS_MASK 0x100 -#define IEEE802_11_FC_FROM_DS_MASK 0x200 -#define IEEE802_11_FC_MOREDATA_MASK 0x2000 -#define IEEE802_11_FC_PROTECTED_MASK 0x4000 -#define IEEE80211_FC_ORDER_MASK 0x8000 -#define IEEE80211_FC_SUBTYPE_MASK 0x00f0 -#define IEEE80211_FC_TYPE_MASK 0x000c -#define IEEE80211_FC_PROTO_VERSION_MASK 0x0003 - -/* selected type and subtype combinations as in 7.1.3.1 table 1 - For frame control as 16 bit integer, or for ls octet -*/ -#define IEEE802_11_FC_TYPE_DATA 0x08 -#define IEEE802_11_FC_TYPE_NULL 0x48 -#define IEEE802_11_FC_TYPE_QOS_NULL 0xc8 -#define IEEE802_11_FC_TYPE_QOS_DATA 0x88 - -#define IEEE802_11_FC_TYPE_DATA_SUBTYPE_RESERVED 0x0D - -/* qos control (QC) masks for qos control as 16 bit integer, or for ls octet */ -#define IEEE802_11_QC_TID_MASK 0x0f -#define IEEE802_11_QC_A_MSDU_PRESENT 0x80 - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND)) -#define IEEE802_11_QC_NON_TID_BITS_MASK 0xFFF0 -#endif - -#define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000 -#define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36 -#define MAX_ACCESS_CATOGORY 4 - -/* Time in us to check for inactivity of stations 5 mins */ -#define INACTIVITY_CHECK_INTERVAL 300000000 -/* Time in us before a station is flagged as inactive */ -#define MAX_INACTIVITY_INTERVAL 300000000 - - -/* Define for maximum BA session */ -#define MAX_SUPPORTED_BA_SESSIONS_TX 1 -#define MAX_SUPPORTED_BA_SESSIONS_RX 4 - -#define MAX_BA_WIND_SIZE 64 -#define MAC_HEADER_ADDR1_OFFSET 4 -#define MAC_HEADER_ADDR2_OFFSET 10 - -/* Define for age (in us) value for frames in MPDU reorder buffer */ -#define CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT 30000 /* 30 milli seconds */ - -/* This macro used in prepare_and_add_macheader*/ -#define ADDRESS_ONE_OFFSET 20 - -/* Defines for STA inactivity detection */ -#define STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD 1 /* in number of stations */ -#define STA_INACTIVE_DETECTION_TIMER_INTERVAL 30 /* in seconds */ -#define STA_INACTIVE_TIMEOUT_VAL 120*1000*1000 /* 120 seconds */ - -/* Test for modes requiring AP firmware patch */ -#define CSR_WIFI_HIP_IS_AP_FW(mode) ((((mode) == CSR_WIFI_ROUTER_CTRL_MODE_AP) || \ - ((mode) == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) ? TRUE : FALSE) - -/* Defines used in beacon filtering in case of P2P */ -#define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH 0x7 -#define CSR_WIFI_80211_FRAME_SUBTYPE_BEACON 0x8 -#define CSR_WIFI_BEACON_FIXED_LENGTH 12 -#define CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET 4 -#define CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK ((u8)(0xF << CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET)) - -#define CSR_WIFI_80211_GET_FRAME_SUBTYPE(frameBuffer) \ - ((u8)(((u8 *)frameBuffer)[0] & CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK) >> CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET) - -/* For M4 request received via netdev*/ - -typedef u8 CsrWifiPacketType; -#define CSR_WIFI_UNICAST_PDU ((CsrWifiPacketType) 0x00) -#define CSR_WIFI_MULTICAST_PDU ((CsrWifiPacketType) 0x1) -#define CSR_WIFI_BROADCAST_PDU ((CsrWifiPacketType) 0x2) - -#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) - -/* Module parameter variables */ -extern int buswidth; -extern int sdio_clock; -extern int use_5g; -extern int disable_hw_reset; -extern int disable_power_control; -extern int enable_wol; -extern int sme_debug; -extern int fw_init[MAX_UNIFI_DEVS]; -extern int tl_80211d; -extern int sdio_byte_mode; -extern int sdio_block_size; -extern int coredump_max; -extern int run_bh_once; -extern int bh_priority; -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -extern int log_hip_signals; -#endif - -struct dlpriv { - const unsigned char *dl_data; - int dl_len; - void *fw_desc; -}; - - -struct uf_thread { - - struct task_struct *thread_task; - - /* wait_queue for waking the unifi_thread kernel thread */ - wait_queue_head_t wakeup_q; - unsigned int wakeup_flag; - - /* - * Use it to block the I/O thread when - * an error occurs or UniFi is reinitialised. - */ - int block_thread; - - char name[16]; - int prio; -}; - -/* - * Link list to hold the received packets for the period the port - * remains closed. - */ -typedef struct rx_buffered_packets { - /* List link structure */ - struct list_head q; - /* Packet to indicate when the port reopens */ - struct sk_buff *skb; - /* Bulkdata to free in case the port closes and need to discard the packet */ - bulk_data_param_t bulkdata; - /* The source address of the packet */ - CsrWifiMacAddress sa; - /* The destination address of the packet */ - CsrWifiMacAddress da; - /* Corresponding signal */ - CSR_SIGNAL signal; -} rx_buffered_packets_t; - - -typedef u8 CsrWifiAcPowersaveMode; -#define CSR_WIFI_AC_TRIGGER_ONLY_ENABLED 0x00 -#define CSR_WIFI_AC_DELIVERY_ONLY_ENABLE 0X01 -#define CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED 0X03 -#define CSR_WIFI_AC_LEGACY_POWER_SAVE 0X02 - - -#define IS_DELIVERY_ENABLED(mode) (mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)? 1: 0 -#define IS_DELIVERY_AND_TRIGGER_ENABLED(mode) ((mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)||(mode & CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))? 1: 0 -#define IS_DTIM_ACTIVE(flag, hostTag) ((flag == TRUE || hostTag != INVALID_HOST_TAG)) -#define INVALID_HOST_TAG 0xFFFFFFFF -#define UNIFI_TRAFFIC_Q_CONTENTION UNIFI_TRAFFIC_Q_BE - - - - -/* Queue to be used for contention priority */ - -/* - * Link list to hold the tx packets for the period the peer - * powersave/free slots in unifi - */ -typedef struct tx_buffered_packets { - /* List link structure */ - struct list_head q; - u16 interfaceTag; - CSR_CLIENT_TAG hostTag; - CSR_PROCESS_ID leSenderProcessId; - CSR_TRANSMISSION_CONTROL transmissionControl; - CSR_RATE rate; - /* Bulkdata to free in case the port closes and need to discard the packet */ - bulk_data_desc_t bulkdata; - /* The source address of the packet */ - CsrWifiMacAddress peerMacAddress; - CSR_PRIORITY priority; -} tx_buffered_packets_t; - -/* station record has this data structure */ -typedef struct CsrWifiRouterCtrlStaInfo_t { - - /* Sme sends these parameters */ - CsrWifiMacAddress peerMacAddress; - u32 assignedHandle; - u8 wmmOrQosEnabled; - CsrWifiAcPowersaveMode powersaveMode[MAX_ACCESS_CATOGORY]; - u16 maxSpLength; - u8 uapsdActive; - u16 noOfSpFramesSent; - - /* Router/Driver database */ -#ifdef CSR_SUPPORT_SME - unifi_port_cfg_t *peerControlledPort; - unifi_port_cfg_t *peerUnControlledPort; - - /* Inactivity feature parameters */ - struct netInterface_priv *interfacePriv; - struct work_struct send_disconnected_ind_task; - u8 activity_flag; - u16 listenIntervalInTus; - CSR_CLIENT_TAG nullDataHostTag; - - /* Activity timestamps for the station */ - u32 lastActivity; - - /* during m/c transmission sp suspended */ - u8 uspSuspend; - CSR_PRIORITY triggerFramePriority; -#endif - CsrWifiRouterCtrlPeerStatus currentPeerState; - struct list_head dataPdu[MAX_ACCESS_CATOGORY]; - struct list_head mgtFrames; - u8 spStatus; - u8 prevFrmType; - u8 prevFrmAccessCatogory; - u8 protection; - u16 aid; - u8 txSuspend; - u8 timSet; - /* Dont change the value of below macro for SET & RESET */ -#define CSR_WIFI_TIM_RESET 0 -#define CSR_WIFI_TIM_SET 1 -#define CSR_WIFI_TIM_RESETTING 2 -#define CSR_WIFI_TIM_SETTING 3 - - u8 timRequestPendingFlag; - u8 updateTimReqQueued; - u16 noOfPktQueued; -}CsrWifiRouterCtrlStaInfo_t; - -#ifdef CSR_SUPPORT_WEXT_AP -struct CsrWifiSmeApConfig { - CsrWifiSsid ssid; - u16 channel; - CsrWifiNmeApCredentials credentials; - u8 max_connections; - u8 if_index; -}; -#endif - -#ifdef CSR_WIFI_RX_PATH_SPLIT -/* This is a test code and may be removed later*/ -#define CSR_WIFI_RX_SIGNAL_BUFFER_SIZE (60+1) - -typedef struct -{ - u8 *bufptr; /* Signal Primitive */ - bulk_data_param_t data_ptrs; /* Bulk Data pointers */ - u16 sig_len; -}rx_buff_struct_t; - -typedef struct -{ - u8 writePointer; /**< write pointer */ - u8 readPointer; /**< read pointer */ - u8 size; /**< size of circular buffer */ - rx_buff_struct_t rx_buff[CSR_WIFI_RX_SIGNAL_BUFFER_SIZE]; /**< Element of ciruclar buffer */ -} rxCircularBuffer_t; - -void rx_wq_handler(struct work_struct *work); -#endif - -struct unifi_priv { - - card_t *card; - CsrSdioFunction *sdio; - - /* Index into Unifi_instances[] for this device. */ - int instance; - /* Reference count for this instance */ - int ref_count; - - /* Firmware images */ - struct dlpriv fw_sta; - struct dlpriv fw_conv; /* used for conversion of production test image */ - - /* Char device related structures */ - struct cdev unifi_cdev; - struct cdev unifiudi_cdev; - struct device *unifi_device; - - /* Which wireless interface to use (1 - 2.4GHz, 2 - 5GHz) */ - CSR_IFINTERFACE if_index; - - /* For multiple interface support */ - struct net_device *netdev[CSR_WIFI_NUM_INTERFACES]; - struct netInterface_priv *interfacePriv[CSR_WIFI_NUM_INTERFACES]; - - u8 totalInterfaceCount; - - int prev_queue; - - /* Name of node under /proc */ - char proc_entry_name[64]; - - /* - * Flags: - * drop_unencrypted - * - Not used? - * netdev_registered - * - whether the netdev has been registered. - */ - unsigned int drop_unencrypted : 1; - - /* Our list of unifi linux clients. */ - ul_client_t ul_clients[MAX_UDI_CLIENTS]; - - /* Mutex to protect using the logging hook after UDI client is gone */ - struct semaphore udi_logging_mutex; - /* Pointer to the ul_clients[] array */ - ul_client_t *logging_client; - - /* A ul_client_t* used to send the netdev related MIB requests. */ - ul_client_t *netdev_client; - - /* The SME ul_client_t pointer. */ - ul_client_t *sme_cli; - - /* The AMP ul_client_t pointer. */ - ul_client_t *amp_client; - - /* - * Semaphore for locking the top-half to one user process. - * This is necessary to prevent multiple processes calling driver - * operations. This can happen because the network driver entry points - * can be called from multiple processes. - */ -#ifdef USE_DRIVER_LOCK - struct semaphore lock; -#endif /* USE_DRIVER_LOCK */ - - /* Flag to say that an operation was aborted */ - int io_aborted; - - struct uf_thread bh_thread; - -#define UNIFI_INIT_NONE 0x00 -#define UNIFI_INIT_IN_PROGRESS 0x01 -#define UNIFI_INIT_FW_DOWNLOADED 0x02 -#define UNIFI_INIT_COMPLETED 0x04 - unsigned char init_progress; - - int sme_is_present; - - /* The WMM features that UniFi uses in the current BSS */ - unsigned int sta_wmm_capabilities; - - /* Debug only */ - char last_debug_string[256]; - unsigned short last_debug_word16[16]; - -#ifdef CSR_SUPPORT_SME - /* lock to protect the tx queues list */ - spinlock_t tx_q_lock; - u8 allPeerDozing; - u8 pausedStaHandle[MAX_ACCESS_CATOGORY]; - /* Max packet the driver can queue, irrespective of interface number */ - u16 noOfPktQueuedInDriver; -#define CSR_WIFI_DRIVER_SUPPORT_FOR_MAX_PKT_QUEUEING 512 -#define CSR_WIFI_DRIVER_MAX_PKT_QUEUING_THRESHOLD_PER_PEER 64 -#define CSR_WIFI_DRIVER_MINIMUM_BROADCAST_PKT_THRESHOLD 3 - - u8 routerBufferEnable[MAX_ACCESS_CATOGORY]; - /* lock to protect stainfo members and priv members*/ - spinlock_t staRecord_lock; -#endif -#ifdef CSR_NATIVE_LINUX -#ifdef CSR_SUPPORT_WEXT - /* wireless config */ - struct wext_config wext_conf; -#endif - - /* Mutex to protect the MLME blocking requests */ - struct semaphore mlme_blocking_mutex; - - /* The ul_client that provides the blocking API for WEXT calls */ - ul_client_t *wext_client; - -#endif /* CSR_NATIVE_LINUX */ - -#ifdef CSR_SUPPORT_SME - wait_queue_head_t sme_request_wq; - /* Semaphore to protect the SME blocking requests */ - struct semaphore sme_sem; - /* Structure to hold the SME blocking requests data*/ - sme_reply_t sme_reply; - - /* Structure to hold a traffic protocol indication */ - struct ta_ind { - struct work_struct task; - CsrWifiRouterCtrlTrafficPacketType packet_type; - CsrWifiRouterCtrlProtocolDirection direction; - CsrWifiMacAddress src_addr; - int in_use; - } ta_ind_work; - - struct ta_sample_ind { - struct work_struct task; - CsrWifiRouterCtrlTrafficStats stats; - int in_use; - } ta_sample_ind_work; - - __be32 sta_ip_address; - CsrWifiRouterCtrlSmeVersions sme_versions; - - /* - * Flag to reflect state of unifi_sys_wifi_on_*() progress. - * This indicates whether we are in an "wifi on" state when we are - * allowed to indication errors with unifi_mgt_wifi_off_ind() - */ - enum { - wifi_on_unspecified = -1, - wifi_on_in_progress = 0, - wifi_on_done = 1, - } wifi_on_state; - - /* Userspace TaskId for the SME Set when a wifi on req is received */ - CsrSchedQid CSR_WIFI_SME_IFACEQUEUE; - - struct work_struct multicast_list_task; - /* - * The SME installs filters to ask for specific MA-UNITDATA.req - * to be passed to different SME components. - */ -#define MAX_MA_UNIDATA_IND_FILTERS 8 - sme_ma_unidata_ind_filter_t sme_unidata_ind_filters[MAX_MA_UNIDATA_IND_FILTERS]; - -/* UNIFI_CFG related parameters */ - uf_cfg_bcast_packet_filter_t packet_filters; - unsigned char *filter_tclas_ies; - /* The structure that holds all the connection configuration. */ - CsrWifiSmeConnectionConfig connection_config; -#ifdef CSR_SUPPORT_WEXT - - int ignore_bssid_join; - struct iw_statistics wext_wireless_stats; - - /* The MIB and MAC address files contents, read from userspace */ - CsrWifiSmeDataBlock mib_data; - CsrWifiMacAddress sta_mac_address; - - int wep_tx_key_index; - wep_key_t wep_keys[NUM_WEPKEYS]; - - -#ifdef CSR_SUPPORT_WEXT_AP - CsrWifiSmeApMacConfig ap_mac_config; - CsrWifiNmeApConfig group_sec_config; - CsrWifiSmeApConfig_t ap_config; -#endif - struct work_struct sme_config_task; - -#endif /* CSR_SUPPORT_WEXT */ - -#endif /* CSR_SUPPORT_SME */ - -#ifdef CSR_SME_USERSPACE - void *smepriv; -#endif /* CSR_SME_USERSPACE */ - - card_info_t card_info; - - /* Mutex to protect unifi_send_signal() */ - spinlock_t send_signal_lock; - - - /* - * The workqueue to offload the TA run - * and the multicast addresses list set - */ - struct workqueue_struct *unifi_workqueue; - - unsigned char *mib_cfm_buffer; - unsigned int mib_cfm_buffer_length; - - int ptest_mode; /* Set when in production test mode */ - int coredump_mode; /* Set when SME has requested a coredump */ - u8 wol_suspend; /* Set when suspending with UniFi powered */ - -#define UF_UNCONTROLLED_PORT_Q 0 -#define UF_CONTROLLED_PORT_Q 1 - - /* Semaphore to protect the rx queues list */ - struct semaphore rx_q_sem; - - /* Spinlock to protect M4 data */ - spinlock_t m4_lock; - /* Mutex to protect BA RX data */ - struct semaphore ba_mutex; - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - /* Spinlock to protect the WAPI data */ - spinlock_t wapi_lock; -#endif - - /* Array to indicate if a particular Tx queue is paused, this may not be - * required in a multiqueue implementation since we can directly stop kernel - * queues */ - u8 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX]; - -#ifdef CSR_WIFI_RX_PATH_SPLIT - struct workqueue_struct *rx_workqueue; - struct work_struct rx_work_struct; - rxCircularBuffer_t rxSignalBuffer; - -#endif - - u32 rxTcpThroughput; - u32 txTcpThroughput; - u32 rxUdpThroughput; - u32 txUdpThroughput; - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /*Set if multicast KeyID = 1*/ - u8 wapi_multicast_filter; - /*Set if unicast KeyID = 1*/ - u8 wapi_unicast_filter; - u8 wapi_unicast_queued_pkt_filter; -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - u8 isWapiConnection; -#endif -#endif - -#ifdef CSR_WIFI_SPLIT_PATCH - CsrWifiRouterCtrlModeSetReq pending_mode_set; -#endif - - u8 cmanrTestMode; - CSR_RATE cmanrTestModeTransmitRate; - -}; - -typedef struct { - u16 queue_length[4]; - u8 os_queue_paused; -} unifi_OsQosInfo; - - -typedef struct { - u8 active; - bulk_data_param_t bulkdata; - CSR_SIGNAL signal; - u16 sn; - u32 recv_time; -} frame_desc_struct; - -typedef struct { - frame_desc_struct *buffer; - u16 wind_size; - u16 occupied_slots; - struct timer_list timer; - u16 timeout; - u16 expected_sn; - u16 start_sn; - u8 trigger_ba_after_ssn; - struct netInterface_priv *interfacePriv; - u16 tID; - CsrWifiMacAddress macAddress; - struct work_struct send_ba_err_task; -} ba_session_rx_struct; - - -typedef struct { - struct netInterface_priv *interfacePriv; - u16 tID; - CsrWifiMacAddress macAddress; -} ba_session_tx_struct; - -typedef struct netInterface_priv -{ - u16 InterfaceTag; - struct unifi_priv *privPtr; - ba_session_tx_struct *ba_session_tx[MAX_SUPPORTED_BA_SESSIONS_TX]; - ba_session_rx_struct *ba_session_rx[MAX_SUPPORTED_BA_SESSIONS_RX]; - frame_desc_struct ba_complete[MAX_BA_WIND_SIZE]; - u8 ba_complete_index; - u8 queueEnabled[UNIFI_NO_OF_TX_QS]; - struct work_struct send_m4_ready_task; -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - struct work_struct send_pkt_to_encrypt; -#endif - struct net_device_stats stats; - u8 interfaceMode; - u8 protect; - CsrWifiMacAddress bssid; - /* - * Flag to reflect state of CONNECTED indication signal. - * This indicates whether we are "joined" an Access Point (i.e. have - * nominated an AP and are receiving beacons) but give no indication - * of whether we are authenticated and/or associated. - */ - enum { - UnifiConnectedUnknown = -1, - UnifiNotConnected = 0, - UnifiConnected = 1, - } connected; -#ifdef CSR_SUPPORT_WEXT - /* Tracks when we are waiting for a netdevice state change callback */ - u8 wait_netdev_change; - /* True if we have successfully registered for netdev callbacks */ - u8 netdev_callback_registered; -#endif /* CSR_SUPPORT_WEXT */ - unsigned int netdev_registered; -#define UNIFI_MAX_MULTICAST_ADDRESSES 10 - /* The multicast addresses list that the thread needs to set. */ - u8 mc_list[UNIFI_MAX_MULTICAST_ADDRESSES*ETH_ALEN]; - /* The multicast addresses count that the thread needs to set. */ - int mc_list_count; - u32 tag; -#ifdef CSR_SUPPORT_SME - /* (un)controlled port configuration */ - unifi_port_config_t controlled_data_port; - unifi_port_config_t uncontrolled_data_port; - - /* station record maintenance related data structures */ - u8 num_stations_joined; - CsrWifiRouterCtrlStaInfo_t *(staInfo)[UNIFI_MAX_CONNECTIONS]; - struct list_head genericMgtFrames; - struct list_head genericMulticastOrBroadCastFrames; - struct list_head genericMulticastOrBroadCastMgtFrames; - - /* Timer for detecting station inactivity */ - struct timer_list sta_activity_check_timer; - u8 sta_activity_check_enabled; - - /* Timestamp when the last inactivity check was done */ - u32 last_inactivity_check; - - /*number of multicast or borad cast packets queued*/ - u16 noOfbroadcastPktQueued; -#endif - /* A list to hold the buffered uncontrolled port packets */ - struct list_head rx_uncontrolled_list; - /* A list to hold the buffered controlled port packets */ - struct list_head rx_controlled_list; - /* Buffered M4 signal to take care of WPA race condition */ - CSR_SIGNAL m4_signal; - bulk_data_desc_t m4_bulk_data; - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - /* Buffered WAPI Unicast MA Packet Request for encryption in Sme */ - CSR_SIGNAL wapi_unicast_ma_pkt_sig; - bulk_data_desc_t wapi_unicast_bulk_data; -#endif - - /* This should be removed and m4_hostTag should be used for checking*/ - u8 m4_sent; - CSR_CLIENT_TAG m4_hostTag; - u8 dtimActive; - u8 intraBssEnabled; - u32 multicastPduHostTag; /* Used to set the tim after getting - a confirm for it */ - u8 bcTimSet; - u8 bcTimSetReqPendingFlag; - u8 bcTimSetReqQueued; -} netInterface_priv_t; - -#ifdef CSR_SUPPORT_SME -#define routerStartBuffering(priv, queue) priv->routerBufferEnable[(queue)] = TRUE; -#define routerStopBuffering(priv, queue) priv->routerBufferEnable[(queue)] = FALSE; -#define isRouterBufferEnabled(priv, queue) priv->routerBufferEnable[(queue)] -#endif - -#ifdef USE_DRIVER_LOCK -#define LOCK_DRIVER(_p) down_interruptible(&(_p)->lock) -#define UNLOCK_DRIVER(_p) up(&(_p)->lock) -#else -#define LOCK_DRIVER(_p) (void)(_p); /* as nothing */ -#define UNLOCK_DRIVER(_p) (void)(_p); /* as nothing */ -#endif /* USE_DRIVER_LOCK */ - -s32 CsrHipResultToStatus(CsrResult csrResult); - - -/* - * SDIO related functions and callbacks - */ -int uf_sdio_load(void); -void uf_sdio_unload(void); -unifi_priv_t *uf_find_instance(int inst); -int uf_find_priv(unifi_priv_t *priv); -int uf_find_netdev_priv(netInterface_priv_t *priv); -unifi_priv_t *uf_get_instance(int inst); -void uf_put_instance(int inst); -int csr_sdio_linux_install_irq(CsrSdioFunction *sdio); -int csr_sdio_linux_remove_irq(CsrSdioFunction *sdio); - -void uf_add_os_device(int bus_id, struct device *os_device); -void uf_remove_os_device(int bus_id); - - - -/* - * Claim/release SDIO - * - * For multifunction cards, we cannot grub the SDIO lock around the unifi_bh() - * as this prevents other functions using SDIO. - * Since some of CSR SDIO API is used regardless of trying to lock unifi_bh() - * we have followed this scheme: - * 1. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is defined - * then we call CsrSdioClaim/CsrSdioRelease(). - * 2. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is not defined - * then we call _sdio_claim_host/_sdio_claim_host(). Use of this should be restricted - * to the SDIO glue layer only (e.g. sdio_mmc.c). - * 3. If a function needs protection, regardless of the CSR_WIFI_SINGLE_FUNCTION - * then we call directly the sdio_claim_host/sdio_release_host(). - * Use of this must be restricted to the SDIO glue layer only (e.g. sdio_mmc.c). - * - * Note: The _func and function pointers are _not_ the same. - * The former is the (struct sdio_func*) context, which restricts the use to the SDIO glue layer. - * The latter is the (CsrSdioFunction*) context, which allows calls from all layers. - */ - -#ifdef CSR_WIFI_SUPPORT_MMC_DRIVER - -#ifdef CSR_WIFI_SINGLE_FUNCTION -#define CsrSdioClaim(function) sdio_claim_host((function)->priv); -#define CsrSdioRelease(function) sdio_release_host((function)->priv); - -#define _sdio_claim_host(_func) -#define _sdio_release_host(_func) - -#else -#define CsrSdioClaim(function) -#define CsrSdioRelease(function) - -#define _sdio_claim_host(_func) sdio_claim_host(_func) -#define _sdio_release_host(_func) sdio_release_host(_func) - -#endif /* CSR_WIFI_SINGLE_FUNCTION */ - -#else -#define _sdio_claim_host(_func) -#define _sdio_release_host(_func) - -#define CsrSdioClaim(function) -#define CsrSdioRelease(function) - -#endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ - - -/* - * Functions to allocate and free an ethernet device. - */ -unifi_priv_t *uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id); -int uf_free_netdevice(unifi_priv_t *priv); - -/* Allocating function for other interfaces */ -u8 uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag); - -/* - * Firmware download related functions. - */ -int uf_run_unifihelper(unifi_priv_t *priv); -int uf_request_firmware_files(unifi_priv_t *priv, int is_fw); -int uf_release_firmware_files(unifi_priv_t *priv); -int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free); - -/* - * Functions to create and delete the device nodes. - */ -int uf_create_device_nodes(unifi_priv_t *priv, int bus_id); -void uf_destroy_device_nodes(unifi_priv_t *priv); - -/* - * Upper Edge Initialisation functions - */ -int uf_init_bh(unifi_priv_t *priv); -int uf_init_hw(unifi_priv_t *priv); - -/* Thread related helper functions */ -int uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *)); -void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread); -void uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread); - - -/* - * Unifi Linux functions - */ -void ul_init_clients(unifi_priv_t *priv); - -/* Configuration flags */ -#define CLI_USING_WIRE_FORMAT 0x0002 -#define CLI_SME_USERSPACE 0x0020 -ul_client_t *ul_register_client(unifi_priv_t *priv, - unsigned int configuration, - udi_event_t udi_event_clbk); -int ul_deregister_client(ul_client_t *pcli); - -int ul_send_signal_unpacked(unifi_priv_t *priv, - CSR_SIGNAL *sigptr, - bulk_data_param_t *bulkdata); -int ul_send_signal_raw(unifi_priv_t *priv, - unsigned char *sigptr, int siglen, - bulk_data_param_t *bulkdata); - -void ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len); - - -/* - * Data plane operations - */ -/* - * data_tx.c - */ -int uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, - unsigned int length); - -#ifdef CSR_SUPPORT_SME -u8 uf_check_broadcast_bssid(unifi_priv_t *priv, const bulk_data_param_t *bulkdata); -u8 uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, u8 pmBit, u16 interfaceTag); -void uf_process_ps_poll(unifi_priv_t *priv, u8* sa, u8* da, u8 pmBit, u16 interfaceTag); -int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, - struct ethhdr *ehdr, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - const CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata, - u8 macHeaderLengthInBytes); -u8 uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord); -void uf_process_wmm_deliver_ac_uapsd ( unifi_priv_t * priv, - CsrWifiRouterCtrlStaInfo_t * srcStaInfo, - u16 qosControl, - u16 interfaceTag); - -void uf_send_buffered_data_from_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, u8 queue, struct list_head *txList); -void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, u8 queue, struct list_head *txList); - -void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo); -void uf_send_qos_null(unifi_priv_t * priv, u16 interfaceTag, const u8 *da, CSR_PRIORITY priority, CsrWifiRouterCtrlStaInfo_t * srcStaInfo); -void uf_send_nulldata(unifi_priv_t * priv, u16 interfaceTag, const u8 *da, CSR_PRIORITY priority, CsrWifiRouterCtrlStaInfo_t * srcStaInfo); - - - -#endif -CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, u8 *peerMacAddress, CSR_CLIENT_TAG hostTag, u16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, CSR_RATE TransmitRate, CSR_PRIORITY priority, CSR_PROCESS_ID senderId, bulk_data_param_t *bulkdata); -void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv, u8 *sigdata, u32 siglen); -#ifdef CSR_SUPPORT_SME -void uf_send_buffered_frames(unifi_priv_t *priv, unifi_TrafficQueue queue); -int uf_process_station_records_for_sending_data(unifi_priv_t *priv, u16 interfaceTag, - CsrWifiRouterCtrlStaInfo_t *srcStaInfo, - CsrWifiRouterCtrlStaInfo_t *dstStaInfo); -void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv, - struct list_head *frames_need_cfm_list, - struct list_head * list); -void send_auto_ma_packet_confirm(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - struct list_head *buffered_frames_list); -void uf_flush_list(unifi_priv_t * priv, struct list_head * list); -tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList); -void resume_unicast_buffered_frames(unifi_priv_t *priv, u16 interfaceTag); -void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv, u16 interfaceTag); -void resume_suspended_uapsd(unifi_priv_t* priv, u16 interfaceTag); -#endif -/* - * netdev.c - */ - -#ifndef P80211_OUI_LEN -#define P80211_OUI_LEN 3 -#endif -typedef struct { - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - u16 protocol; -} __attribute__ ((packed)) llc_snap_hdr_t; -int skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto); -int skb_80211_to_ether(unifi_priv_t *priv, struct sk_buff *skb, - const unsigned char *daddr, const unsigned char *saddr, - const CSR_SIGNAL *signal, - bulk_data_param_t *bulkdata); - -const char *result_code_str(int result); - - -/* prepares & appends the Mac header for the payload */ -int prepare_and_add_macheader(unifi_priv_t *priv, - struct sk_buff *skb, - struct sk_buff *newSkb, - CSR_PRIORITY priority, - bulk_data_param_t *bulkdata, - u16 interfaceTag, - const u8 *daddr, - const u8 *saddr, - u8 protection); -CSR_PRIORITY -get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, netInterface_priv_t *interfacePriv); - -void -unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, - CSR_RATE TransmitRate, CSR_CLIENT_TAG hostTag, - u16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, - CSR_PROCESS_ID leSenderProcessId, u8 *peerMacAddress, - CSR_SIGNAL *signal); - - -/* Pack the LSB to include station handle & status of tim set */ -#define CSR_WIFI_PACK_SENDER_ID_LSB_FOR_TIM_REQ(handle, timState) ((handle << 2) | timState) -/* get the station record handle from the sender ID */ -#define CSR_WIFI_GET_STATION_HANDLE_FROM_RECEIVER_ID(receiverProcessId) (u8) ((receiverProcessId & 0xff) >> 2) -/* get the timSet status from the sender ID */ -#define CSR_WIFI_GET_TIMSET_STATE_FROM_RECEIVER_ID(receiverProcessId) (u8) (receiverProcessId & 0x03) - -/* handle is 6 bits to accomodate in senderId LSB (only 64 station can be associated) */ -#define CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE 0x3F - -void update_tim(unifi_priv_t * priv, u16 aid, u8 setTim, u16 interfaceTag, u32 handle); -void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, u16 senderProcessId); - -/* Clear the Peer station Record, in case of wifioff/unexpected card removal */ -void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, u16 interfaceTag); - -void scroll_ba_window(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - ba_session_rx_struct *ba_session, - u16 sn); - -u8 blockack_session_stop(unifi_priv_t *priv, - u16 interfaceTag, - CsrWifiRouterCtrlBlockAckRole role, - u16 tID, - CsrWifiMacAddress macAddress); -#ifdef CSR_SUPPORT_SME -/* Fetch the protection information from interface Mode */ -s8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, u16 interfaceTag, const u8 *daddr); -#endif - -/* Fetch the station record handler from data base for matching Mac address */ -#ifdef CSR_SUPPORT_SME -CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(unifi_priv_t *priv, - const u8 *peerMacAddress, - u16 interfaceTag); - -/* Fetch the station record handler from data base for matching handle */ -CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_priv_t *priv, - u32 handle, - u16 interfaceTag); - -void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress); -void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv, u16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm); -#endif - -void uf_resume_data_plane(unifi_priv_t *priv, int queue, - CsrWifiMacAddress peer_address, - u16 interfaceTag); -void uf_free_pending_rx_packets(unifi_priv_t *priv, int queue, - CsrWifiMacAddress peer_address, u16 interfaceTag); - -int uf_register_netdev(unifi_priv_t *priv, int numOfInterface); -void uf_unregister_netdev(unifi_priv_t *priv); - -void uf_net_get_name(struct net_device *dev, char *name, int len); - -void uf_send_queue_info(unifi_priv_t *priv); -u16 uf_get_vif_identifier(CsrWifiRouterCtrlMode mode, u16 tag); - -void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, - CsrWifiMacAddress source_address, - int indicate, u16 interfaceTag); - -#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -int uf_register_hip_offline_debug(unifi_priv_t *priv); -int uf_unregister_hip_offline_debug(unifi_priv_t *priv); -#endif - -/* - * inet.c - */ -void uf_register_inet_notifier(void); -void uf_unregister_inet_notifier(void); - - -/* - * Suspend / Resume handlers - */ -void unifi_resume(void *ospriv); -void unifi_suspend(void *ospriv); - - -#define QOS_CAPABILITY_WMM_ENABLED 0x0001 -#define QOS_CAPABILITY_WMM_UAPSD 0x0002 -#define QOS_CAPABILITY_ACM_BE_ENABLED 0x0010 -#define QOS_CAPABILITY_ACM_BK_ENABLED 0x0020 -#define QOS_CAPABILITY_ACM_VI_ENABLED 0x0040 -#define QOS_CAPABILITY_ACM_VO_ENABLED 0x0080 -#define QOS_CAPABILITY_TS_BE_ENABLED 0x0100 -#define QOS_CAPABILITY_TS_BK_ENABLED 0x0200 -#define QOS_CAPABILITY_TS_VI_ENABLED 0x0400 -#define QOS_CAPABILITY_TS_VO_ENABLED 0x0800 - - -/* EAPOL PDUS */ -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888e -#endif -#ifndef ETH_P_WAI -#define ETH_P_WAI 0x88b4 -#endif -/* - * unifi_dbg.c - */ -void debug_string_indication(unifi_priv_t *priv, - const unsigned char *extra, - unsigned int extralen); -void debug_word16_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); -void debug_generic_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); - - -/* - * putest.c - */ -int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg); - -int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg); -int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg); - -#endif /* __LINUX_UNIFI_PRIV_H__ */ diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c deleted file mode 100644 index 50908822b3c8..000000000000 --- a/drivers/staging/csr/unifi_sme.c +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * *************************************************************************** - * FILE: unifi_sme.c - * - * PURPOSE: SME related functions. - * - * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ - -#include "unifi_priv.h" -#include "csr_wifi_hip_unifi.h" -#include "csr_wifi_hip_conversions.h" -#include - - - - int -convert_sme_error(CsrResult error) -{ - switch (error) { - case CSR_RESULT_SUCCESS: - return 0; - case CSR_RESULT_FAILURE: - case CSR_WIFI_RESULT_NOT_FOUND: - case CSR_WIFI_RESULT_TIMED_OUT: - case CSR_WIFI_RESULT_CANCELLED: - case CSR_WIFI_RESULT_UNAVAILABLE: - return -EIO; - case CSR_WIFI_RESULT_NO_ROOM: - return -EBUSY; - case CSR_WIFI_RESULT_INVALID_PARAMETER: - return -EINVAL; - case CSR_WIFI_RESULT_UNSUPPORTED: - return -EOPNOTSUPP; - default: - return -EIO; - } -} - - -/* - * --------------------------------------------------------------------------- - * sme_log_event - * - * Callback function to be registered as the SME event callback. - * Copies the signal content into a new udi_log_t struct and adds - * it to the read queue for the SME client. - * - * Arguments: - * arg This is the value given to unifi_add_udi_hook, in - * this case a pointer to the client instance. - * signal Pointer to the received signal. - * signal_len Size of the signal structure in bytes. - * bulkdata Pointers to any associated bulk data. - * dir Direction of the signal. Zero means from host, - * non-zero means to host. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ - void -sme_log_event(ul_client_t *pcli, - const u8 *signal, int signal_len, - const bulk_data_param_t *bulkdata, - int dir) -{ - unifi_priv_t *priv; - CSR_SIGNAL unpacked_signal; - CsrWifiSmeDataBlock mlmeCommand; - CsrWifiSmeDataBlock dataref1; - CsrWifiSmeDataBlock dataref2; - CsrResult result = CSR_RESULT_SUCCESS; - int r; - - /* Just a sanity check */ - if ((signal == NULL) || (signal_len <= 0)) { - return; - } - - priv = uf_find_instance(pcli->instance); - if (!priv) { - unifi_error(priv, "sme_log_event: invalid priv\n"); - return; - } - - if (priv->smepriv == NULL) { - unifi_error(priv, "sme_log_event: invalid smepriv\n"); - return; - } - - unifi_trace(priv, UDBG3, - "sme_log_event: Process signal 0x%.4X\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal)); - - - /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */ - r = read_unpack_signal(signal, &unpacked_signal); - if (r == CSR_RESULT_SUCCESS) { - if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) || - (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID)) - { - return; - } - if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID) - { - u16 frmCtrl; - u8 unicastPdu = TRUE; - u8 *macHdrLocation; - u8 *raddr = NULL, *taddr = NULL; - CsrWifiMacAddress peerMacAddress; - /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/ - CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication; - - macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr; - /* Fetch the frame control value from mac header */ - frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation); - - /* Point to the addresses */ - raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET; - taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET; - - memcpy(peerMacAddress.a, taddr, ETH_ALEN); - - if(ind->ReceptionStatus == CSR_MICHAEL_MIC_ERROR) - { - if (*raddr & 0x1) - unicastPdu = FALSE; - - CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0, - (ind->VirtualInterfaceIdentifier & 0xff), peerMacAddress, - unicastPdu); - return; - } - else - { - if(ind->ReceptionStatus == CSR_RX_SUCCESS) - { - u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00; - u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff); - CsrWifiRouterCtrlStaInfo_t *srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, taddr, interfaceTag); - if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE)) - { - uf_process_pm_bit_for_peer(priv, srcStaInfo, pmBit, interfaceTag); - - /* Update station last activity flag */ - srcStaInfo->activity_flag = TRUE; - } - } - } - } - - if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_CONFIRM_ID) - { - CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm; - u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff); - netInterface_priv_t *interfacePriv; - CSR_MA_PACKET_REQUEST *req; - CsrWifiMacAddress peerMacAddress; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag); - return; - } - - unifi_trace(priv, UDBG1, "MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus); - - interfacePriv = priv->interfacePriv[interfaceTag]; -#ifdef CSR_SUPPORT_SME - if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - - if(cfm->HostTag == interfacePriv->multicastPduHostTag){ - uf_process_ma_pkt_cfm_for_ap(priv, interfaceTag, cfm); - } - } -#endif - - req = &interfacePriv->m4_signal.u.MaPacketRequest; - - if(cfm->HostTag & 0x80000000) - { - if (cfm->TransmissionStatus != CSR_TX_SUCCESSFUL) - { - result = CSR_RESULT_FAILURE; - } -#ifdef CSR_SUPPORT_SME - memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN); - /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/ - if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag)) - { - unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__); - CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, - interfaceTag, - peerMacAddress, - result); - interfacePriv->m4_sent = FALSE; - interfacePriv->m4_hostTag = 0xffffffff; - } -#endif - /* If EAPOL was requested via router APIs then send cfm else ignore*/ - if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) { - CsrWifiRouterMaPacketCfmSend((u16)signal[2], - cfm->VirtualInterfaceIdentifier, - result, - (cfm->HostTag & 0x3fffffff), cfm->Rate); - } else { - unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__); - } - return; - } - } - } - - mlmeCommand.length = signal_len; - mlmeCommand.data = (u8*)signal; - - dataref1.length = bulkdata->d[0].data_length; - if (dataref1.length > 0) { - dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr; - } else - { - dataref1.data = NULL; - } - - dataref2.length = bulkdata->d[1].data_length; - if (dataref2.length > 0) { - dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr; - } else - { - dataref2.data = NULL; - } - - CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data, - dataref1.length, dataref1.data, - dataref2.length, dataref2.data); - -} /* sme_log_event() */ - - -/* - * --------------------------------------------------------------------------- - * uf_sme_port_state - * - * Return the state of the controlled port. - * - * Arguments: - * priv Pointer to device private context struct - * address Pointer to the destination for tx or sender for rx address - * queue Controlled or uncontrolled queue - * - * Returns: - * An unifi_ControlledPortAction value. - * --------------------------------------------------------------------------- - */ -CsrWifiRouterCtrlPortAction -uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag) -{ - int i; - unifi_port_config_t *port; - netInterface_priv_t *interfacePriv; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n"); - return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if (queue == UF_CONTROLLED_PORT_Q) { - port = &interfacePriv->controlled_data_port; - } else { - port = &interfacePriv->uncontrolled_data_port; - } - - if (!port->entries_in_use) { - unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); - return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - } - - /* If the port configuration is common for all destinations, return it. */ - if (port->overide_action == UF_DATA_PORT_OVERIDE) { - unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", - port->port_cfg[0].port_action); - return port->port_cfg[0].port_action; - } - - unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use); - - /* If multiple configurations exist.. */ - for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - /* .. go through the list and match the destination address. */ - if (port->port_cfg[i].in_use && - memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { - /* Return the desired action. */ - return port->port_cfg[i].port_action; - } - } - - /* Could not find any information, return Open. */ - unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n"); - return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; -} /* uf_sme_port_state() */ - -/* - * --------------------------------------------------------------------------- - * uf_sme_port_config_handle - * - * Return the port config handle of the controlled/uncontrolled port. - * - * Arguments: - * priv Pointer to device private context struct - * address Pointer to the destination for tx or sender for rx address - * queue Controlled or uncontrolled queue - * - * Returns: - * An unifi_port_cfg_t* . - * --------------------------------------------------------------------------- - */ -unifi_port_cfg_t* -uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag) -{ - int i; - unifi_port_config_t *port; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n"); - return NULL; - } - - if (queue == UF_CONTROLLED_PORT_Q) { - port = &interfacePriv->controlled_data_port; - } else { - port = &interfacePriv->uncontrolled_data_port; - } - - if (!port->entries_in_use) { - unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); - return NULL; - } - - /* If the port configuration is common for all destinations, return it. */ - if (port->overide_action == UF_DATA_PORT_OVERIDE) { - unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", - port->port_cfg[0].port_action); - if (address) { - unifi_trace(priv, UDBG5, "addr[0] = %x, addr[1] = %x, addr[2] = %x, addr[3] = %x\n", address[0], address[1], address[2], address[3]); - } - return &port->port_cfg[0]; - } - - unifi_trace(priv, UDBG5, "Multiple port configurations.\n"); - - /* If multiple configurations exist.. */ - for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - /* .. go through the list and match the destination address. */ - if (port->port_cfg[i].in_use && - memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { - /* Return the desired action. */ - return &port->port_cfg[i]; - } - } - - /* Could not find any information, return Open. */ - unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n"); - return NULL; -} /* uf_sme_port_config_handle */ - -void -uf_multicast_list_wq(struct work_struct *work) -{ - unifi_priv_t *priv = container_of(work, unifi_priv_t, - multicast_list_task); - int i; - u16 interfaceTag = 0; - CsrWifiMacAddress* multicast_address_list = NULL; - int mc_count; - u8 *mc_list; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n"); - return; - } - - unifi_trace(priv, UDBG5, - "uf_multicast_list_wq: list count = %d\n", - interfacePriv->mc_list_count); - - /* Flush the current list */ - CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL); - - mc_count = interfacePriv->mc_list_count; - mc_list = interfacePriv->mc_list; - /* - * Allocate a new list, need to free it later - * in unifi_mgt_multicast_address_cfm(). - */ - multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL); - - if (multicast_address_list == NULL) { - return; - } - - for (i = 0; i < mc_count; i++) { - memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN); - mc_list += ETH_ALEN; - } - - if (priv->smepriv == NULL) { - kfree(multicast_address_list); - return; - } - - CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, - interfaceTag, - CSR_WIFI_SME_LIST_ACTION_ADD, - mc_count, multicast_address_list); - - /* The SME will take a copy of the addreses*/ - kfree(multicast_address_list); -} - - -int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg) -{ - unifi_cfg_power_t cfg_power; - int rc; - int wol; - - if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); - return -EFAULT; - } - - switch (cfg_power) { - case UNIFI_CFG_POWER_OFF: - priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; - rc = sme_sys_suspend(priv); - if (rc) { - return rc; - } - break; - case UNIFI_CFG_POWER_ON: - wol = priv->wol_suspend; - rc = sme_sys_resume(priv); - if (rc) { - return rc; - } - if (wol) { - /* Kick the BH to ensure pending transfers are handled when - * a suspend happened with card powered. - */ - unifi_send_signal(priv->card, NULL, 0, NULL); - } - break; - default: - unifi_error(priv, "WIFI POWER: Unknown value.\n"); - return -EINVAL; - } - - return 0; -} - - -int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg) -{ - unifi_cfg_powersave_t cfg_power_save; - CsrWifiSmePowerConfig powerConfig; - int rc; - - if (get_user(cfg_power_save, (unifi_cfg_powersave_t*)(((unifi_cfg_command_t*)arg) + 1))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); - return -EFAULT; - } - - /* Get the coex info from the SME */ - rc = sme_mgt_power_config_get(priv, &powerConfig); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n"); - return rc; - } - - switch (cfg_power_save) { - case UNIFI_CFG_POWERSAVE_NONE: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW; - break; - case UNIFI_CFG_POWERSAVE_FAST: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED; - break; - case UNIFI_CFG_POWERSAVE_FULL: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH; - break; - case UNIFI_CFG_POWERSAVE_AUTO: - powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO; - break; - default: - unifi_error(priv, "POWERSAVE: Unknown value.\n"); - return -EINVAL; - } - - rc = sme_mgt_power_config_set(priv, &powerConfig); - - if (rc) { - unifi_error(priv, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n"); - } - - return rc; -} - - -int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg) -{ - unifi_cfg_powersupply_t cfg_power_supply; - CsrWifiSmeHostConfig hostConfig; - int rc; - - if (get_user(cfg_power_supply, (unifi_cfg_powersupply_t*)(((unifi_cfg_command_t*)arg) + 1))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); - return -EFAULT; - } - - /* Get the coex info from the SME */ - rc = sme_mgt_host_config_get(priv, &hostConfig); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n"); - return rc; - } - - switch (cfg_power_supply) { - case UNIFI_CFG_POWERSUPPLY_MAINS: - hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE; - break; - case UNIFI_CFG_POWERSUPPLY_BATTERIES: - hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE; - break; - default: - unifi_error(priv, "POWERSUPPLY: Unknown value.\n"); - return -EINVAL; - } - - rc = sme_mgt_host_config_set(priv, &hostConfig); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n"); - } - - return rc; -} - - -int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg) -{ - unsigned char *tclas_buffer; - unsigned int tclas_buffer_length; - tclas_t *dhcp_tclas; - int rc; - - /* Free any TCLASs previously allocated */ - if (priv->packet_filters.tclas_ies_length) { - kfree(priv->filter_tclas_ies); - priv->filter_tclas_ies = NULL; - } - - tclas_buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int); - if (copy_from_user(&priv->packet_filters, (void*)tclas_buffer, - sizeof(uf_cfg_bcast_packet_filter_t))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the filter struct\n"); - return -EFAULT; - } - - tclas_buffer_length = priv->packet_filters.tclas_ies_length; - - /* Allocate TCLASs if necessary */ - if (priv->packet_filters.dhcp_filter) { - priv->packet_filters.tclas_ies_length += sizeof(tclas_t); - } - if (priv->packet_filters.tclas_ies_length > 0) { - priv->filter_tclas_ies = kmalloc(priv->packet_filters.tclas_ies_length, GFP_KERNEL); - if (priv->filter_tclas_ies == NULL) { - return -ENOMEM; - } - if (tclas_buffer_length) { - tclas_buffer += sizeof(uf_cfg_bcast_packet_filter_t) - sizeof(unsigned char*); - if (copy_from_user(priv->filter_tclas_ies, - tclas_buffer, - tclas_buffer_length)) { - unifi_error(priv, "UNIFI_CFG: Failed to get the TCLAS buffer\n"); - return -EFAULT; - } - } - } - - if(priv->packet_filters.dhcp_filter) - { - /* Append the DHCP tclas IE */ - dhcp_tclas = (tclas_t*)(priv->filter_tclas_ies + tclas_buffer_length); - memset(dhcp_tclas, 0, sizeof(tclas_t)); - dhcp_tclas->element_id = 14; - dhcp_tclas->length = sizeof(tcpip_clsfr_t) + 1; - dhcp_tclas->user_priority = 0; - dhcp_tclas->tcp_ip_cls_fr.cls_fr_type = 1; - dhcp_tclas->tcp_ip_cls_fr.version = 4; - ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[0] = 0x00; - ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[1] = 0x44; - ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[0] = 0x00; - ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[1] = 0x43; - dhcp_tclas->tcp_ip_cls_fr.protocol = 0x11; - dhcp_tclas->tcp_ip_cls_fr.cls_fr_mask = 0x58; //bits: 3,4,6 - } - - rc = sme_mgt_packet_filter_set(priv); - - return rc; -} - - -int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg) -{ - u8 wmm_qos_info; - int rc = 0; - - if (get_user(wmm_qos_info, (u8*)(((unifi_cfg_command_t*)arg) + 1))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); - return -EFAULT; - } - - /* Store the value in the connection info */ - priv->connection_config.wmmQosInfo = wmm_qos_info; - - return rc; -} - - -int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg) -{ - u32 addts_tid; - u8 addts_ie_length; - u8 *addts_ie; - u8 *addts_params; - CsrWifiSmeDataBlock tspec; - CsrWifiSmeDataBlock tclas; - int rc; - - addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); - if (get_user(addts_tid, (u32*)addts_params)) { - unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); - return -EFAULT; - } - - addts_params += sizeof(u32); - if (get_user(addts_ie_length, (u8*)addts_params)) { - unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n", - addts_tid, addts_ie_length); - - addts_ie = kmalloc(addts_ie_length, GFP_KERNEL); - if (addts_ie == NULL) { - unifi_error(priv, - "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n", - addts_ie_length); - return -ENOMEM; - } - - addts_params += sizeof(u8); - rc = copy_from_user(addts_ie, addts_params, addts_ie_length); - if (rc) { - unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n"); - kfree(addts_ie); - return -EFAULT; - } - - tspec.data = addts_ie; - tspec.length = addts_ie_length; - tclas.data = NULL; - tclas.length = 0; - - rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid, - &tspec, &tclas); - - kfree(addts_ie); - return rc; -} - - -int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg) -{ - u32 delts_tid; - u8 *delts_params; - CsrWifiSmeDataBlock tspec; - CsrWifiSmeDataBlock tclas; - int rc; - - delts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); - if (get_user(delts_tid, (u32*)delts_params)) { - unifi_error(priv, "unifi_cfg_wmm_delts: Failed to get the argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG4, "delts: tid = 0x%x\n", delts_tid); - - tspec.data = tclas.data = NULL; - tspec.length = tclas.length = 0; - - rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_REMOVE, delts_tid, - &tspec, &tclas); - - return rc; -} - -int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg) -{ - u8 strict_draft_n; - u8 *strict_draft_n_params; - int rc; - - CsrWifiSmeStaConfig staConfig; - CsrWifiSmeDeviceConfig deviceConfig; - - strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); - if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) { - unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no")); - - rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); - - if (rc) { - unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n"); - return -EFAULT; - } - - deviceConfig.enableStrictDraftN = strict_draft_n; - - rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); - if (rc) { - unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n"); - rc = -EFAULT; - } - - return rc; -} - - -int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg) -{ - u8 enable_okc; - u8 *enable_okc_params; - int rc; - - CsrWifiSmeStaConfig staConfig; - CsrWifiSmeDeviceConfig deviceConfig; - - enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); - if (get_user(enable_okc, (u8*)enable_okc_params)) { - unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n"); - return -EFAULT; - } - - unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no")); - - rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); - if (rc) { - unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n"); - return -EFAULT; - } - - staConfig.enableOpportunisticKeyCaching = enable_okc; - - rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); - if (rc) { - unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n"); - rc = -EFAULT; - } - - return rc; -} - - -int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg) -{ - unifi_cfg_get_t get_cmd; - char inst_name[IFNAMSIZ]; - int rc; - - if (get_user(get_cmd, (unifi_cfg_get_t*)(((unifi_cfg_command_t*)arg) + 1))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n"); - return -EFAULT; - } - - switch (get_cmd) { - case UNIFI_CFG_GET_COEX: - { - CsrWifiSmeCoexInfo coexInfo; - /* Get the coex info from the SME */ - rc = sme_mgt_coex_info_get(priv, &coexInfo); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n"); - return rc; - } - - /* Copy the info to the out buffer */ - if (copy_to_user((void*)arg, - &coexInfo, - sizeof(CsrWifiSmeCoexInfo))) { - unifi_error(priv, "UNIFI_CFG: Failed to copy the coex info\n"); - return -EFAULT; - } - break; - } - case UNIFI_CFG_GET_POWER_MODE: - { - CsrWifiSmePowerConfig powerConfig; - rc = sme_mgt_power_config_get(priv, &powerConfig); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n"); - return rc; - } - - /* Copy the info to the out buffer */ - if (copy_to_user((void*)arg, - &powerConfig.powerSaveLevel, - sizeof(CsrWifiSmePowerSaveLevel))) { - unifi_error(priv, "UNIFI_CFG: Failed to copy the power save info\n"); - return -EFAULT; - } - break; - } - case UNIFI_CFG_GET_POWER_SUPPLY: - { - CsrWifiSmeHostConfig hostConfig; - rc = sme_mgt_host_config_get(priv, &hostConfig); - if (rc) { - unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n"); - return rc; - } - - /* Copy the info to the out buffer */ - if (copy_to_user((void*)arg, - &hostConfig.powerMode, - sizeof(CsrWifiSmeHostPowerMode))) { - unifi_error(priv, "UNIFI_CFG: Failed to copy the host power mode\n"); - return -EFAULT; - } - break; - } - case UNIFI_CFG_GET_VERSIONS: - break; - case UNIFI_CFG_GET_INSTANCE: - { - u16 InterfaceId=0; - uf_net_get_name(priv->netdev[InterfaceId], &inst_name[0], sizeof(inst_name)); - - /* Copy the info to the out buffer */ - if (copy_to_user((void*)arg, - &inst_name[0], - sizeof(inst_name))) { - unifi_error(priv, "UNIFI_CFG: Failed to copy the instance name\n"); - return -EFAULT; - } - } - break; - - case UNIFI_CFG_GET_AP_CONFIG: - { -#ifdef CSR_SUPPORT_WEXT_AP - uf_cfg_ap_config_t cfg_ap_config; - - memset(&cfg_ap_config, 0, sizeof(cfg_ap_config)); - cfg_ap_config.channel = priv->ap_config.channel; - cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval; - cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled; - cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod; - cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap; - if (copy_to_user((void*)arg, - &cfg_ap_config, - sizeof(uf_cfg_ap_config_t))) { - unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n"); - return -EFAULT; - } -#else - return -EPERM; -#endif - } - break; - - - default: - unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n"); - return -EINVAL; - } - - return 0; -} -#ifdef CSR_SUPPORT_WEXT_AP -int - uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap) -{ - int i=0; - u8 b=FALSE, g = FALSE, n = FALSE; - b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B; - n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N; - g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G; - if(b || g) { - supportedRates[i++]=0x82; - supportedRates[i++]=0x84; - supportedRates[i++]=0x8b; - supportedRates[i++]=0x96; - } else if(n) { - /* For some strange reasons WiFi stack needs both b and g rates*/ - supportedRates[i++]=0x02; - supportedRates[i++]=0x04; - supportedRates[i++]=0x0b; - supportedRates[i++]=0x16; - supportedRates[i++]=0x0c; - supportedRates[i++]=0x12; - supportedRates[i++]=0x18; - supportedRates[i++]=0x24; - supportedRates[i++]=0x30; - supportedRates[i++]=0x48; - supportedRates[i++]=0x60; - supportedRates[i++]=0x6c; - } - if(g) { - if(!b) { - supportedRates[i++]=0x8c; - supportedRates[i++]=0x98; - supportedRates[i++]=0xb0; - } else { - supportedRates[i++]=0x0c; - supportedRates[i++]=0x18; - supportedRates[i++]=0x30; - } - supportedRates[i++]=0x48; - supportedRates[i++]=0x12; - supportedRates[i++]=0x24; - supportedRates[i++]=0x60; - supportedRates[i++]=0x6c; - } - return i; -} -int unifi_cfg_set_ap_config(unifi_priv_t * priv, unsigned char* arg) -{ - uf_cfg_ap_config_t cfg_ap_config; - char *buffer; - - buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int); - if (copy_from_user(&cfg_ap_config, (void*)buffer, - sizeof(uf_cfg_ap_config_t))) { - unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n"); - return -EFAULT; - } - priv->ap_config.channel = cfg_ap_config.channel; - priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod; - priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval; - priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout; - priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled; - priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout; - priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout; - priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit; - - priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled; - priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType; - - priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled; - - priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc; - priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed; - - priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap; - priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval; - - priv->ap_mac_config.supportedRatesCount= uf_configure_supported_rates(priv->ap_mac_config.supportedRates, priv->ap_mac_config.phySupportedBitmap); - - return 0; -} - -#endif -#ifdef CSR_SUPPORT_WEXT - - void -uf_sme_config_wq(struct work_struct *work) -{ - CsrWifiSmeStaConfig staConfig; - CsrWifiSmeDeviceConfig deviceConfig; - unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task); - - /* Register to receive indications from the SME */ - CsrWifiSmeEventMaskSetReqSend(0, - CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY | - CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE); - - if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) { - unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n"); - return; - } - - if (priv->if_index == CSR_INDEX_5G) { - staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0; - } else { - staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4; - } - - deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d; - if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) { - unifi_warning(priv, - "SME config for 802.11d Trust Level and Radio Band failed.\n"); - return; - } - -} /* uf_sme_config_wq() */ - -#endif /* CSR_SUPPORT_WEXT */ - - -/* - * --------------------------------------------------------------------------- - * uf_ta_ind_wq - * - * Deferred work queue function to send Traffic Analysis protocols - * indications to the SME. - * These are done in a deferred work queue for two reasons: - * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context - * - we want to load the main driver data path as lightly as possible - * - * The TA classifications already come from a workqueue. - * - * Arguments: - * work Pointer to work queue item. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ - void -uf_ta_ind_wq(struct work_struct *work) -{ - struct ta_ind *ind = container_of(work, struct ta_ind, task); - unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work); - u16 interfaceTag = 0; - - - CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, - interfaceTag, - ind->packet_type, - ind->direction, - ind->src_addr); - ind->in_use = 0; - -} /* uf_ta_ind_wq() */ - - -/* - * --------------------------------------------------------------------------- - * uf_ta_sample_ind_wq - * - * Deferred work queue function to send Traffic Analysis sample - * indications to the SME. - * These are done in a deferred work queue for two reasons: - * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context - * - we want to load the main driver data path as lightly as possible - * - * The TA classifications already come from a workqueue. - * - * Arguments: - * work Pointer to work queue item. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ - void -uf_ta_sample_ind_wq(struct work_struct *work) -{ - struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task); - unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work); - u16 interfaceTag = 0; - - unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n", - priv->rxTcpThroughput, - priv->txTcpThroughput, - priv->rxUdpThroughput, - priv->txUdpThroughput, - priv->bh_thread.prio); - - if(priv->rxTcpThroughput > 1000) - { - if (bh_priority == -1 && priv->bh_thread.prio != 1) - { - struct sched_param param; - priv->bh_thread.prio = 1; - unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n", - priv->bh_thread.name, priv->bh_thread.prio); - param.sched_priority = priv->bh_thread.prio; - sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, ¶m); - } - } else - { - if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO) - { - struct sched_param param; - param.sched_priority = 0; - sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, ¶m); - priv->bh_thread.prio = DEFAULT_PRIO; - unifi_trace(priv, UDBG1, "%s new thread priority = %d\n", - priv->bh_thread.name, priv->bh_thread.prio); - set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio)); - } - } - - CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, ind->stats); - - ind->in_use = 0; - -} /* uf_ta_sample_ind_wq() */ - - -/* - * --------------------------------------------------------------------------- - * uf_send_m4_ready_wq - * - * Deferred work queue function to send M4 ReadyToSend inds to the SME. - * These are done in a deferred work queue for two reasons: - * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context - * - we want to load the main driver data path as lightly as possible - * - * Arguments: - * work Pointer to work queue item. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void -uf_send_m4_ready_wq(struct work_struct *work) -{ - netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task); - u16 iface = InterfacePriv->InterfaceTag; - unifi_priv_t *priv = InterfacePriv->privPtr; - CSR_MA_PACKET_REQUEST *req = &InterfacePriv->m4_signal.u.MaPacketRequest; - CsrWifiMacAddress peer; - unsigned long flags; - - /* The peer address was stored in the signal */ - spin_lock_irqsave(&priv->m4_lock, flags); - memcpy(peer.a, req->Ra.x, sizeof(peer.a)); - spin_unlock_irqrestore(&priv->m4_lock, flags); - - /* Send a signal to SME */ - CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer); - - unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n", - peer.a); - -} /* uf_send_m4_ready_wq() */ - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) -/* - * --------------------------------------------------------------------------- - * uf_send_pkt_to_encrypt - * - * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1 - * These are done in a deferred work queue for two reasons: - * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context - * - we want to load the main driver data path as lightly as possible - * - * Arguments: - * work Pointer to work queue item. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -void uf_send_pkt_to_encrypt(struct work_struct *work) -{ - netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt); - u16 interfaceTag = interfacePriv->InterfaceTag; - unifi_priv_t *priv = interfacePriv->privPtr; - - u32 pktBulkDataLength; - u8 *pktBulkData; - unsigned long flags; - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { - - pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length; - - if (pktBulkDataLength > 0) { - pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL); - } else { - unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n"); - return; - } - - spin_lock_irqsave(&priv->wapi_lock, flags); - /* Copy over the MA PKT REQ bulk data */ - memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength); - /* Free any bulk data buffers allocated for the WAPI Data pkt */ - unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data); - interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0; - interfacePriv->wapi_unicast_bulk_data.data_length = 0; - interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL; - spin_unlock_irqrestore(&priv->wapi_lock, flags); - - CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData); - unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n"); - - kfree(pktBulkData); /* Would have been copied over by the SME Handler */ - - } else { - unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n", interfacePriv->interfaceMode); - } -}/* uf_send_pkt_to_encrypt() */ -#endif diff --git a/drivers/staging/csr/unifi_sme.h b/drivers/staging/csr/unifi_sme.h deleted file mode 100644 index aff9aa178124..000000000000 --- a/drivers/staging/csr/unifi_sme.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * *************************************************************************** - * FILE: unifi_sme.h - * - * PURPOSE: SME related definitions. - * - * Copyright (C) 2007-2011 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * *************************************************************************** - */ -#ifndef __LINUX_UNIFI_SME_H__ -#define __LINUX_UNIFI_SME_H__ 1 - -#include - -#ifdef CSR_SME_USERSPACE -#include "sme_userspace.h" -#endif - -#include "csr_wifi_sme_lib.h" - -typedef int unifi_data_port_action; - -typedef struct unifi_port_cfg -{ - /* TRUE if this port entry is allocated */ - u8 in_use; - CsrWifiRouterCtrlPortAction port_action; - CsrWifiMacAddress mac_address; -} unifi_port_cfg_t; - -#define UNIFI_MAX_CONNECTIONS 8 -#define UNIFI_MAX_RETRY_LIMIT 5 -#define UF_DATA_PORT_NOT_OVERIDE 0 -#define UF_DATA_PORT_OVERIDE 1 - -typedef struct unifi_port_config -{ - int entries_in_use; - int overide_action; - unifi_port_cfg_t port_cfg[UNIFI_MAX_CONNECTIONS]; -} unifi_port_config_t; - - -enum sme_request_status { - SME_REQUEST_EMPTY, - SME_REQUEST_PENDING, - SME_REQUEST_RECEIVED, - SME_REQUEST_TIMEDOUT, - SME_REQUEST_CANCELLED, -}; - -/* Structure to hold a UDI logged signal */ -typedef struct { - - /* The current status of the request */ - enum sme_request_status request_status; - - /* The status the SME has passed to us */ - CsrResult reply_status; - - /* SME's reply to a get request */ - CsrWifiSmeVersions versions; - CsrWifiSmePowerConfig powerConfig; - CsrWifiSmeHostConfig hostConfig; - CsrWifiSmeStaConfig staConfig; - CsrWifiSmeDeviceConfig deviceConfig; - CsrWifiSmeCoexInfo coexInfo; - CsrWifiSmeCoexConfig coexConfig; - CsrWifiSmeMibConfig mibConfig; - CsrWifiSmeConnectionInfo connectionInfo; - CsrWifiSmeConnectionConfig connectionConfig; - CsrWifiSmeConnectionStats connectionStats; - - - /* SME's reply to a scan request */ - u16 reply_scan_results_count; - CsrWifiSmeScanResult* reply_scan_results; - -} sme_reply_t; - - -typedef struct { - u16 appHandle; - CsrWifiRouterEncapsulation encapsulation; - u16 protocol; - u8 oui[3]; - u8 in_use; -} sme_ma_unidata_ind_filter_t; - - -CsrWifiRouterCtrlPortAction uf_sme_port_state(unifi_priv_t *priv, - unsigned char *address, - int queue, - u16 interfaceTag); -unifi_port_cfg_t *uf_sme_port_config_handle(unifi_priv_t *priv, - unsigned char *address, - int queue, - u16 interfaceTag); - - - -/* Callback for event logging to SME clients */ -void sme_log_event(ul_client_t *client, const u8 *signal, int signal_len, - const bulk_data_param_t *bulkdata, int dir); - -/* The workqueue task to the set the multicast addresses list */ -void uf_multicast_list_wq(struct work_struct *work); - -/* The workqueue task to execute the TA module */ -void uf_ta_wq(struct work_struct *work); - - -/* - * SME blocking helper functions - */ -#ifdef UNIFI_DEBUG -# define sme_complete_request(priv, status) uf_sme_complete_request(priv, status, __func__) -#else -# define sme_complete_request(priv, status) uf_sme_complete_request(priv, status, NULL) -#endif - -void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func); -void uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status); - - -/* - * Blocking functions using the SME SYS API. - */ -int sme_sys_suspend(unifi_priv_t *priv); -int sme_sys_resume(unifi_priv_t *priv); - - -/* - * Traffic Analysis workqueue jobs - */ -void uf_ta_ind_wq(struct work_struct *work); -void uf_ta_sample_ind_wq(struct work_struct *work); - -/* - * SME config workqueue job - */ -void uf_sme_config_wq(struct work_struct *work); - -/* - * To send M4 read to send IND - */ -void uf_send_m4_ready_wq(struct work_struct *work); - -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) -/* - * To send data pkt to Sme for encryption - */ -void uf_send_pkt_to_encrypt(struct work_struct *work); -#endif - -int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); -int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig); -int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig); -int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig); -int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig); -int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig); -int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo); -int sme_mgt_packet_filter_set(unifi_priv_t *priv); -int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action, - u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas); - -#ifdef CSR_SUPPORT_WEXT -/* - * Blocking functions using the SME MGT API. - */ -int sme_mgt_wifi_on(unifi_priv_t *priv); -int sme_mgt_wifi_off(unifi_priv_t *priv); -/*int sme_mgt_set_value_async(unifi_priv_t *priv, unifi_AppValue *app_value); -int sme_mgt_get_value_async(unifi_priv_t *priv, unifi_AppValue *app_value); -int sme_mgt_get_value(unifi_priv_t *priv, unifi_AppValue *app_value); -int sme_mgt_set_value(unifi_priv_t *priv, unifi_AppValue *app_value); -*/ -int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig); -int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig); -int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig); -int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig); - -int sme_mgt_connection_info_set(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo); -int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo); -int sme_mgt_connection_config_set(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig); -int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig); -int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats); - -int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions); - - -int sme_mgt_scan_full(unifi_priv_t *priv, CsrWifiSsid *specific_ssid, - int num_channels, unsigned char *channel_list); -int sme_mgt_scan_results_get_async(unifi_priv_t *priv, - struct iw_request_info *info, - char *scan_results, - long scan_results_len); -int sme_mgt_disconnect(unifi_priv_t *priv); -int sme_mgt_connect(unifi_priv_t *priv); -int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key, - CsrWifiSmeListAction action); -int sme_mgt_pmkid(unifi_priv_t *priv, CsrWifiSmeListAction action, - CsrWifiSmePmkidList *pmkid_list); -int sme_mgt_mib_get(unifi_priv_t *priv, - unsigned char *varbind, int *length); -int sme_mgt_mib_set(unifi_priv_t *priv, - unsigned char *varbind, int length); -#ifdef CSR_SUPPORT_WEXT_AP -int sme_ap_start(unifi_priv_t *priv, u16 interface_tag, CsrWifiSmeApConfig_t *ap_config); -int sme_ap_stop(unifi_priv_t *priv, u16 interface_tag); -int sme_ap_config(unifi_priv_t *priv, CsrWifiSmeApMacConfig *ap_mac_config, CsrWifiNmeApConfig *group_security_config); -int uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap); -#endif -int unifi_translate_scan(struct net_device *dev, - struct iw_request_info *info, - char *current_ev, char *end_buf, - CsrWifiSmeScanResult *scan_data, - int scan_index); - -#endif /* CSR_SUPPORT_WEXT */ - -int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg); -int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg); -#ifdef CSR_SUPPORT_WEXT_AP -int unifi_cfg_set_ap_config(unifi_priv_t * priv, unsigned char* arg); -#endif - - - -int convert_sme_error(CsrResult error); - - -#endif /* __LINUX_UNIFI_SME_H__ */ diff --git a/drivers/staging/csr/unifi_wext.h b/drivers/staging/csr/unifi_wext.h deleted file mode 100644 index beba089e2e35..000000000000 --- a/drivers/staging/csr/unifi_wext.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - ***************************************************************************** - * - * FILE : unifi_wext.h - * - * PURPOSE : Private header file for unifi driver support to wireless extensions. - * - * Copyright (C) 2005-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * -***************************************************************************** - */ -#ifndef __LINUX_UNIFI_WEXT_H__ -#define __LINUX_UNIFI_WEXT_H__ 1 - -#include -#include -#include "csr_wifi_sme_prim.h" - -/* - * wext.c - */ -/* A few details needed for WEP (Wireless Equivalent Privacy) */ -#define UNIFI_MAX_KEY_SIZE 16 -#define NUM_WEPKEYS 4 -#define SMALL_KEY_SIZE 5 -#define LARGE_KEY_SIZE 13 -typedef struct wep_key_t { - int len; - unsigned char key[UNIFI_MAX_KEY_SIZE]; /* 40-bit and 104-bit keys */ -} wep_key_t; - -#define UNIFI_SCAN_ACTIVE 0 -#define UNIFI_SCAN_PASSIVE 1 -#define UNIFI_MAX_SSID_LEN 32 - -#define MAX_WPA_IE_LEN 64 -#define MAX_RSN_IE_LEN 255 - -/* - * Function to register in the netdev to report wireless stats. - */ -struct iw_statistics *unifi_get_wireless_stats(struct net_device *dev); - -void uf_sme_wext_set_defaults(unifi_priv_t *priv); - - -/* - * wext_events.c - */ -/* Functions to generate Wireless Extension events */ -void wext_send_scan_results_event(unifi_priv_t *priv); -void wext_send_assoc_event(unifi_priv_t *priv, unsigned char *bssid, - unsigned char *req_ie, int req_ie_len, - unsigned char *resp_ie, int resp_ie_len, - unsigned char *scan_ie, unsigned int scan_ie_len); -void wext_send_disassoc_event(unifi_priv_t *priv); -void wext_send_michaelmicfailure_event(unifi_priv_t *priv, - u16 count, CsrWifiMacAddress address, - CsrWifiSmeKeyType keyType, u16 interfaceTag); -void wext_send_pmkid_candidate_event(unifi_priv_t *priv, CsrWifiMacAddress bssid, u8 preauth_allowed, u16 interfaceTag); -void wext_send_started_event(unifi_priv_t *priv); - - -static inline int -uf_iwe_stream_add_point(struct iw_request_info *info, char *start, char *stop, - struct iw_event *piwe, char *extra) -{ - char *new_start; - - new_start = iwe_stream_add_point(info, start, stop, piwe, extra); - if (unlikely(new_start == start)) - return -E2BIG; - - return (new_start - start); -} - - -static inline int -uf_iwe_stream_add_event(struct iw_request_info *info, char *start, char *stop, - struct iw_event *piwe, int len) -{ - char *new_start; - - new_start = iwe_stream_add_event(info, start, stop, piwe, len); - if (unlikely(new_start == start)) - return -E2BIG; - - return (new_start - start); -} - -static inline int -uf_iwe_stream_add_value(struct iw_request_info *info, char *stream, char *start, - char *stop, struct iw_event *piwe, int len) -{ - char *new_start; - - new_start = iwe_stream_add_value(info, stream, start, stop, piwe, len); - if (unlikely(new_start == start)) - return -E2BIG; - - return (new_start - start); -} - - -#endif /* __LINUX_UNIFI_WEXT_H__ */ diff --git a/drivers/staging/csr/unifiio.h b/drivers/staging/csr/unifiio.h deleted file mode 100644 index b9de0cb94e9a..000000000000 --- a/drivers/staging/csr/unifiio.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * - * FILE: unifiio.h - * - * Public definitions for the UniFi linux driver. - * This is mostly ioctl command values and structs. - * - * Include or similar before this file - * - * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#ifndef __UNIFIIO_H__ -#define __UNIFIIO_H__ - -#include - -#define UNIFI_GET_UDI_ENABLE _IOR('u', 1, int) -#define UNIFI_SET_UDI_ENABLE _IOW('u', 2, int) -/* Values for UDI_ENABLE */ -#define UDI_ENABLE_DATA 0x1 -#define UDI_ENABLE_CONTROL 0x2 - -/* MIB set/get. Arg is a pointer to a varbind */ -#define UNIFI_GET_MIB _IOWR('u', 3, unsigned char *) -#define UNIFI_SET_MIB _IOW ('u', 4, unsigned char *) -#define MAX_VARBIND_LENGTH 127 - -/* Private IOCTLs */ -#define SIOCIWS80211POWERSAVEPRIV SIOCIWFIRSTPRIV -#define SIOCIWG80211POWERSAVEPRIV SIOCIWFIRSTPRIV + 1 -#define SIOCIWS80211RELOADDEFAULTSPRIV SIOCIWFIRSTPRIV + 2 -#define SIOCIWSCONFWAPIPRIV SIOCIWFIRSTPRIV + 4 -#define SIOCIWSWAPIKEYPRIV SIOCIWFIRSTPRIV + 6 -#define SIOCIWSSMEDEBUGPRIV SIOCIWFIRSTPRIV + 8 -#define SIOCIWSAPCFGPRIV SIOCIWFIRSTPRIV + 10 -#define SIOCIWSAPSTARTPRIV SIOCIWFIRSTPRIV + 12 -#define SIOCIWSAPSTOPPRIV SIOCIWFIRSTPRIV + 14 -#define SIOCIWSFWRELOADPRIV SIOCIWFIRSTPRIV + 16 -#define SIOCIWSSTACKSTART SIOCIWFIRSTPRIV + 18 -#define SIOCIWSSTACKSTOP SIOCIWFIRSTPRIV + 20 - - - -#define IWPRIV_POWER_SAVE_MAX_STRING 32 -#define IWPRIV_SME_DEBUG_MAX_STRING 32 -#define IWPRIV_SME_MAX_STRING 120 - - -/* Private configuration commands */ -#define UNIFI_CFG _IOWR('u', 5, unsigned char *) -/* - * <------------------ Read/Write Buffer --------------------> - * _____________________________________________________________ - * | Cmd | Arg | ... Buffer (opt) ... | - * ------------------------------------------------------------- - * <-- uint --><-- uint --><----- unsigned char buffer ------> - * - * Cmd: A unifi_cfg_command_t command. - * Arg: Out:Length if Cmd==UNIFI_CFG_GET - * In:PowerOnOff if Cmd==UNIFI_CFG_POWER - * In:PowerMode if Cmd==UNIFI_CFG_POWERSAVE - * In:Length if Cmd==UNIFI_CFG_FILTER - * In:WMM Qos Info if Cmd==UNIFI_CFG_WMM_QOS_INFO - * Buffer: Out:Data if Cmd==UNIFI_CFG_GET - * NULL if Cmd==UNIFI_CFG_POWER - * NULL if Cmd==UNIFI_CFG_POWERSAVE - * In:Filters if Cmd==UNIFI_CFG_FILTER - * - * where Filters is a uf_cfg_bcast_packet_filter_t structure - * followed by 0 - n tclas_t structures. The length of the tclas_t - * structures is obtained by uf_cfg_bcast_packet_filter_t::tclas_ies_length. - */ - - -#define UNIFI_PUTEST _IOWR('u', 6, unsigned char *) -/* - * <------------------ Read/Write Buffer --------------------> - * _____________________________________________________________ - * | Cmd | Arg | ... Buffer (opt) ... | - * ------------------------------------------------------------- - * <-- uint --><-- uint --><----- unsigned char buffer ------> - * - * Cmd: A unifi_putest_command_t command. - * Arg: N/A if Cmd==UNIFI_PUTEST_START - * N/A if Cmd==UNIFI_PUTEST_STOP - * In:int (Clock Speed) if Cmd==UNIFI_PUTEST_SET_SDIO_CLOCK - * In/Out:sizeof(unifi_putest_cmd52) if Cmd==UNIFI_PUTEST_CMD52_READ - * In:sizeof(unifi_putest_cmd52) if Cmd==UNIFI_PUTEST_CMD52_WRITE - * In:uint (f/w file name length) if Cmd==UNIFI_PUTEST_DL_FW - * Buffer: NULL if Cmd==UNIFI_PUTEST_START - * NULL if Cmd==UNIFI_PUTEST_STOP - * NULL if Cmd==UNIFI_PUTEST_SET_SDIO_CLOCK - * In/Out:unifi_putest_cmd52 if Cmd==UNIFI_PUTEST_CMD52_READ - * In:unifi_putest_cmd52 if Cmd==UNIFI_PUTEST_CMD52_WRITE - * In:f/w file name if Cmd==UNIFI_PUTEST_DL_FW - */ - -#define UNIFI_BUILD_TYPE _IOWR('u', 7, unsigned char) -#define UNIFI_BUILD_NME 1 -#define UNIFI_BUILD_WEXT 2 -#define UNIFI_BUILD_AP 3 - -/* debugging */ -#define UNIFI_KICK _IO ('u', 0x10) -#define UNIFI_SET_DEBUG _IO ('u', 0x11) -#define UNIFI_SET_TRACE _IO ('u', 0x12) - -#define UNIFI_GET_INIT_STATUS _IOR ('u', 0x15, int) -#define UNIFI_SET_UDI_LOG_MASK _IOR('u', 0x18, unifiio_filter_t) -#define UNIFI_SET_UDI_SNAP_MASK _IOW('u', 0x1a, unifiio_snap_filter_t) -#define UNIFI_SET_AMP_ENABLE _IOWR('u', 0x1b, int) - -#define UNIFI_INIT_HW _IOR ('u', 0x13, unsigned char) -#define UNIFI_INIT_NETDEV _IOW ('u', 0x14, unsigned char[6]) -#define UNIFI_SME_PRESENT _IOW ('u', 0x19, int) - -#define UNIFI_CFG_PERIOD_TRAFFIC _IOW ('u', 0x21, unsigned char *) -#define UNIFI_CFG_UAPSD_TRAFFIC _IOW ('u', 0x22, unsigned char) - -#define UNIFI_COREDUMP_GET_REG _IOWR('u', 0x23, unifiio_coredump_req_t) - - -/* - * Following reset, f/w may only be downloaded using CMD52. - * This is slow, so there is a facility to download a secondary - * loader first which supports CMD53. - * If loader_len is > 0, then loader_data is assumed to point to - * a suitable secondary loader that can be used to download the - * main image. - * - * The driver will run the host protocol initialisation sequence - * after downloading the image. - * - * If both lengths are zero, then the f/w is assumed to have been - * booted from Flash and the host protocol initialisation sequence - * is run. - */ -typedef struct { - - /* Number of bytes in the image */ - int img_len; - - /* Pointer to image data. */ - unsigned char *img_data; - - - /* Number of bytes in the loader image */ - int loader_len; - - /* Pointer to loader image data. */ - unsigned char *loader_data; - -} unifiio_img_t; - - -/* Structure of data read from the unifi device. */ -typedef struct -{ - /* Length (in bytes) of entire structure including appended bulk data */ - int length; - - /* System time (in milliseconds) that signal was transferred */ - int timestamp; - - /* Direction in which signal was transferred. */ - int direction; -#define UDI_FROM_HOST 0 -#define UDI_TO_HOST 1 -#define UDI_CONFIG_IND 2 - - /* The length of the signal (in bytes) not including bulk data */ - int signal_length; - - /* Signal body follows, then any bulk data */ - -} udi_msg_t; - - -typedef enum -{ - UfSigFil_AllOn = 0, /* Log all signal IDs */ - UfSigFil_AllOff = 1, /* Don't log any signal IDs */ - UfSigFil_SelectOn = 2, /* Log these signal IDs */ - UfSigFil_SelectOff = 3 /* Don't log these signal IDs */ -} uf_sigfilter_action_t; - -typedef struct { - - /* Number of 16-bit ints in the sig_ids array */ - int num_sig_ids; - /* The action to perform */ - uf_sigfilter_action_t action; - /* List of signal IDs to pass or block */ - unsigned short *sig_ids; - -} unifiio_filter_t; - - -typedef struct { - /* Number of 16-bit ints in the protocols array */ - u16 count; - /* List of protocol ids to pass */ - u16 *protocols; -} unifiio_snap_filter_t; - - - -typedef u8 unifi_putest_command_t; - -#define UNIFI_PUTEST_START 0 -#define UNIFI_PUTEST_STOP 1 -#define UNIFI_PUTEST_SET_SDIO_CLOCK 2 -#define UNIFI_PUTEST_CMD52_READ 3 -#define UNIFI_PUTEST_CMD52_WRITE 4 -#define UNIFI_PUTEST_DL_FW 5 -#define UNIFI_PUTEST_DL_FW_BUFF 6 -#define UNIFI_PUTEST_CMD52_BLOCK_READ 7 -#define UNIFI_PUTEST_COREDUMP_PREPARE 8 -#define UNIFI_PUTEST_GP_READ16 9 -#define UNIFI_PUTEST_GP_WRITE16 10 - - -struct unifi_putest_cmd52 { - int funcnum; - unsigned long addr; - unsigned char data; -}; - - -struct unifi_putest_block_cmd52_r { - int funcnum; - unsigned long addr; - unsigned int length; - unsigned char *data; -}; - -struct unifi_putest_gp_rw16 { - unsigned long addr; /* generic address */ - unsigned short data; -}; - -typedef enum unifi_cfg_command { - UNIFI_CFG_GET, - UNIFI_CFG_POWER, - UNIFI_CFG_POWERSAVE, - UNIFI_CFG_FILTER, - UNIFI_CFG_POWERSUPPLY, - UNIFI_CFG_WMM_QOSINFO, - UNIFI_CFG_WMM_ADDTS, - UNIFI_CFG_WMM_DELTS, - UNIFI_CFG_STRICT_DRAFT_N, - UNIFI_CFG_ENABLE_OKC, - UNIFI_CFG_SET_AP_CONFIG, - UNIFI_CFG_CORE_DUMP /* request to take a fw core dump */ -} unifi_cfg_command_t; - -typedef enum unifi_cfg_power { - UNIFI_CFG_POWER_UNSPECIFIED, - UNIFI_CFG_POWER_OFF, - UNIFI_CFG_POWER_ON -} unifi_cfg_power_t; - -typedef enum unifi_cfg_powersupply { - UNIFI_CFG_POWERSUPPLY_UNSPECIFIED, - UNIFI_CFG_POWERSUPPLY_MAINS, - UNIFI_CFG_POWERSUPPLY_BATTERIES -} unifi_cfg_powersupply_t; - -typedef enum unifi_cfg_powersave { - UNIFI_CFG_POWERSAVE_UNSPECIFIED, - UNIFI_CFG_POWERSAVE_NONE, - UNIFI_CFG_POWERSAVE_FAST, - UNIFI_CFG_POWERSAVE_FULL, - UNIFI_CFG_POWERSAVE_AUTO -} unifi_cfg_powersave_t; - -typedef enum unifi_cfg_get { - UNIFI_CFG_GET_COEX, - UNIFI_CFG_GET_POWER_MODE, - UNIFI_CFG_GET_VERSIONS, - UNIFI_CFG_GET_POWER_SUPPLY, - UNIFI_CFG_GET_INSTANCE, - UNIFI_CFG_GET_AP_CONFIG -} unifi_cfg_get_t; - -#define UNIFI_CFG_FILTER_NONE 0x0000 -#define UNIFI_CFG_FILTER_DHCP 0x0001 -#define UNIFI_CFG_FILTER_ARP 0x0002 -#define UNIFI_CFG_FILTER_NBNS 0x0004 -#define UNIFI_CFG_FILTER_NBDS 0x0008 -#define UNIFI_CFG_FILTER_CUPS 0x0010 -#define UNIFI_CFG_FILTER_ALL 0xFFFF - - -typedef struct uf_cfg_bcast_packet_filter -{ - unsigned long filter_mode; //as defined by HIP protocol - unsigned char arp_filter; - unsigned char dhcp_filter; - unsigned long tclas_ies_length; // length of tclas_ies in bytes - unsigned char tclas_ies[1]; // variable length depending on above field -} uf_cfg_bcast_packet_filter_t; - -typedef struct uf_cfg_ap_config -{ - u8 phySupportedBitmap; - u8 channel; - u16 beaconInterval; - u8 dtimPeriod; - u8 wmmEnabled; - u8 shortSlotTimeEnabled; - u16 groupkeyTimeout; - u8 strictGtkRekeyEnabled; - u16 gmkTimeout; - u16 responseTimeout; - u8 retransLimit; - u8 rxStbc; - u8 rifsModeAllowed; - u8 dualCtsProtection; - u8 ctsProtectionType; - u16 maxListenInterval; -}uf_cfg_ap_config_t; - -typedef struct tcpic_clsfr -{ - __u8 cls_fr_type; - __u8 cls_fr_mask; - __u8 version; - __u8 source_ip_addr[4]; - __u8 dest_ip_addr[4]; - __u16 source_port; - __u16 dest_port; - __u8 dscp; - __u8 protocol; - __u8 reserved; -} __attribute__ ((packed)) tcpip_clsfr_t; - -typedef struct tclas { - __u8 element_id; - __u8 length; - __u8 user_priority; - tcpip_clsfr_t tcp_ip_cls_fr; -} __attribute__ ((packed)) tclas_t; - - -#define CONFIG_IND_ERROR 0x01 -#define CONFIG_IND_EXIT 0x02 -#define CONFIG_SME_NOT_PRESENT 0x10 -#define CONFIG_SME_PRESENT 0x20 - -/* WAPI Key */ -typedef struct -{ - u8 unicastKey; - /* If non zero, then unicast key otherwise group key */ - u8 keyIndex; - u8 keyRsc[16]; - u8 authenticator; - /* If non zero, then authenticator otherwise supplicant */ - u8 address[6]; - u8 key[32]; -} unifiio_wapi_key_t; - -/* Values describing XAP memory regions captured by the mini-coredump system */ -typedef enum unifiio_coredump_space { - UNIFIIO_COREDUMP_MAC_REG, - UNIFIIO_COREDUMP_PHY_REG, - UNIFIIO_COREDUMP_SH_DMEM, - UNIFIIO_COREDUMP_MAC_DMEM, - UNIFIIO_COREDUMP_PHY_DMEM, - UNIFIIO_COREDUMP_TRIGGER_MAGIC = 0xFEED -} unifiio_coredump_space_t; - -/* Userspace tool uses this structure to retrieve a register value from a - * mini-coredump buffer previously saved by the HIP - */ -typedef struct unifiio_coredump_req { - /* From user */ - int index; /* 0=newest, -1=oldest */ - unsigned int offset; /* register offset in space */ - unifiio_coredump_space_t space; /* memory space */ - /* Filled by driver */ - unsigned int drv_build; /* driver build id */ - unsigned int chip_ver; /* chip version */ - unsigned int fw_ver; /* firmware version */ - int requestor; /* requestor: 0=auto dump, 1=manual */ - unsigned int timestamp; /* time of capture by driver */ - unsigned int serial; /* capture serial number */ - int value; /* 16 bit register value, -ve for error */ -} unifiio_coredump_req_t; /* Core-dumped register value request */ - -#endif /* __UNIFIIO_H__ */ diff --git a/drivers/staging/csr/wext_events.c b/drivers/staging/csr/wext_events.c deleted file mode 100644 index 9860ea30da25..000000000000 --- a/drivers/staging/csr/wext_events.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: wext_events.c - * - * PURPOSE: - * Code to generate iwevents. - * - * Copyright (C) 2006-2008 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ -#include -#include -#include -#include "csr_wifi_hip_unifi.h" -#include "unifi_priv.h" - - - -/* - * --------------------------------------------------------------------------- - * wext_send_assoc_event - * - * Send wireless-extension events up to userland to announce - * successful association with an AP. - * - * Arguments: - * priv Pointer to driver context. - * bssid MAC address of AP we associated with - * req_ie, req_ie_len IEs in the original request - * resp_ie, resp_ie_len IEs in the response - * - * Returns: - * None. - * - * Notes: - * This is sent on first successful association, and again if we - * roam to another AP. - * --------------------------------------------------------------------------- - */ -void -wext_send_assoc_event(unifi_priv_t *priv, unsigned char *bssid, - unsigned char *req_ie, int req_ie_len, - unsigned char *resp_ie, int resp_ie_len, - unsigned char *scan_ie, unsigned int scan_ie_len) -{ -#if WIRELESS_EXT > 17 - union iwreq_data wrqu; - - if (req_ie_len == 0) req_ie = NULL; - wrqu.data.length = req_ie_len; - wrqu.data.flags = 0; - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCREQIE, &wrqu, req_ie); - - if (resp_ie_len == 0) resp_ie = NULL; - wrqu.data.length = resp_ie_len; - wrqu.data.flags = 0; - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVASSOCRESPIE, &wrqu, resp_ie); - - if (scan_ie_len > 0) { - wrqu.data.length = scan_ie_len; - wrqu.data.flags = 0; - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVGENIE, &wrqu, scan_ie); - } - - memcpy(&wrqu.ap_addr.sa_data, bssid, ETH_ALEN); - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL); -#endif -} /* wext_send_assoc_event() */ - - - -/* - * --------------------------------------------------------------------------- - * wext_send_disassoc_event - * - * Send a wireless-extension event up to userland to announce - * that we disassociated from an AP. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * None. - * - * Notes: - * The semantics of wpa_supplicant (the userland SME application) are - * that a SIOCGIWAP event with MAC address of all zero means - * disassociate. - * --------------------------------------------------------------------------- - */ -void -wext_send_disassoc_event(unifi_priv_t *priv) -{ -#if WIRELESS_EXT > 17 - union iwreq_data wrqu; - - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWAP, &wrqu, NULL); -#endif -} /* wext_send_disassoc_event() */ - - - -/* - * --------------------------------------------------------------------------- - * wext_send_scan_results_event - * - * Send wireless-extension events up to userland to announce - * completion of a scan. - * - * Arguments: - * priv Pointer to driver context. - * - * Returns: - * None. - * - * Notes: - * This doesn't actually report the results, they are retrieved - * using the SIOCGIWSCAN ioctl command. - * --------------------------------------------------------------------------- - */ -void -wext_send_scan_results_event(unifi_priv_t *priv) -{ -#if WIRELESS_EXT > 17 - union iwreq_data wrqu; - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], SIOCGIWSCAN, &wrqu, NULL); - -#endif -} /* wext_send_scan_results_event() */ - - - -/* - * --------------------------------------------------------------------------- - * wext_send_michaelmicfailure_event - * - * Send wireless-extension events up to userland to announce - * completion of a scan. - * - * Arguments: - * priv Pointer to driver context. - * count, macaddr, key_type, key_idx, tsc - * Parameters from report from UniFi. - * - * Returns: - * None. - * --------------------------------------------------------------------------- - */ -#if WIRELESS_EXT >= 18 -static inline void -_send_michaelmicfailure_event(struct net_device *dev, - int count, const unsigned char *macaddr, - int key_type, int key_idx, - unsigned char *tsc) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure mmf; - - memset(&mmf, 0, sizeof(mmf)); - - mmf.flags = key_idx & IW_MICFAILURE_KEY_ID; - if (key_type == CSR_GROUP) { - mmf.flags |= IW_MICFAILURE_GROUP; - } else { - mmf.flags |= IW_MICFAILURE_PAIRWISE; - } - mmf.flags |= ((count << 5) & IW_MICFAILURE_COUNT); - - mmf.src_addr.sa_family = ARPHRD_ETHER; - memcpy(mmf.src_addr.sa_data, macaddr, ETH_ALEN); - - memcpy(mmf.tsc, tsc, IW_ENCODE_SEQ_MAX_SIZE); - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(mmf); - - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&mmf); -} -#elif WIRELESS_EXT >= 15 -static inline void -_send_michaelmicfailure_event(struct net_device *dev, - int count, const unsigned char *macaddr, - int key_type, int key_idx, - unsigned char *tsc) -{ - union iwreq_data wrqu; - char buf[128]; - - sprintf(buf, - "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%pM)", - key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", macaddr); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); -} -#else /* WIRELESS_EXT >= 15 */ -static inline void -_send_michaelmicfailure_event(struct net_device *dev, - int count, const unsigned char *macaddr, - int key_type, int key_idx, - unsigned char *tsc) -{ - /* Not supported before WEXT 15 */ -} -#endif /* WIRELESS_EXT >= 15 */ - - -void -wext_send_michaelmicfailure_event(unifi_priv_t *priv, - u16 count, - CsrWifiMacAddress address, - CsrWifiSmeKeyType keyType, - u16 interfaceTag) -{ - unsigned char tsc[8] = {0}; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "wext_send_michaelmicfailure_event bad interfaceTag\n"); - return; - } - - _send_michaelmicfailure_event(priv->netdev[interfaceTag], - count, - address.a, - keyType, - 0, - tsc); -} /* wext_send_michaelmicfailure_event() */ - -void -wext_send_pmkid_candidate_event(unifi_priv_t *priv, CsrWifiMacAddress bssid, u8 preauth_allowed, u16 interfaceTag) -{ -#if WIRELESS_EXT > 17 - union iwreq_data wrqu; - struct iw_pmkid_cand pmkid_cand; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "wext_send_pmkid_candidate_event bad interfaceTag\n"); - return; - } - - memset(&pmkid_cand, 0, sizeof(pmkid_cand)); - - if (preauth_allowed) { - pmkid_cand.flags |= IW_PMKID_CAND_PREAUTH; - } - pmkid_cand.bssid.sa_family = ARPHRD_ETHER; - memcpy(pmkid_cand.bssid.sa_data, bssid.a, ETH_ALEN); - /* Used as priority, smaller the number higher the priority, not really used in our case */ - pmkid_cand.index = 1; - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(pmkid_cand); - - wireless_send_event(priv->netdev[interfaceTag], IWEVPMKIDCAND, &wrqu, (char *)&pmkid_cand); -#endif -} /* wext_send_pmkid_candidate_event() */ - -/* - * Send a custom WEXT event to say we have completed initialisation - * and are now ready for WEXT ioctls. Used by Android wpa_supplicant. - */ -void -wext_send_started_event(unifi_priv_t *priv) -{ -#if WIRELESS_EXT > 17 - union iwreq_data wrqu; - char data[] = "STARTED"; - - wrqu.data.length = sizeof(data); - wrqu.data.flags = 0; - wireless_send_event(priv->netdev[CSR_WIFI_INTERFACE_IN_USE], IWEVCUSTOM, &wrqu, data); -#endif -} /* wext_send_started_event() */ - -- GitLab From 08801f966571b522f0581de0fd400abdf295b16b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 14 Jul 2013 17:43:06 -0700 Subject: [PATCH 2836/2900] driver-core: fix new kernel-doc warning in base/platform.c Fix new kernel-doc warning in drivers/base/platform.c: Warning(drivers/base/platform.c:528): No description found for parameter 'owner' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 15789875128e..3c3197a8de41 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -522,6 +522,7 @@ static void platform_drv_shutdown(struct device *_dev) /** * __platform_driver_register - register a driver for platform-level devices * @drv: platform driver structure + * @owner: owning module/driver */ int __platform_driver_register(struct platform_driver *drv, struct module *owner) -- GitLab From f45708209dc445bac0844f6ce86e315a2ffe8a29 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Tue, 16 Jul 2013 23:01:20 -0700 Subject: [PATCH 2837/2900] hyperv: Fix the NETIF_F_SG flag setting in netvsc SG mode is not currently supported by netvsc, so remove this flag for now. Otherwise, it will be unconditionally enabled by commit ec5f0615642 "Kill link between CSUM and SG features" Previously, the SG feature is disabled because CSUM is not set here. Signed-off-by: Haiyang Zhang Reviewed-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 4dccead586be..23a0fff0df52 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -431,8 +431,8 @@ static int netvsc_probe(struct hv_device *dev, net->netdev_ops = &device_ops; /* TODO: Add GSO and Checksum offload */ - net->hw_features = NETIF_F_SG; - net->features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX; + net->hw_features = 0; + net->features = NETIF_F_HW_VLAN_CTAG_TX; SET_ETHTOOL_OPS(net, ðtool_ops); SET_NETDEV_DEV(net, &dev->device); -- GitLab From 256ca9c3ad5013ff8a8f165e5a82fab437628c8e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 16 Jul 2013 12:17:49 +0200 Subject: [PATCH 2838/2900] ALSA: seq-oss: Initialize MIDI clients asynchronously We've got bug reports that the module loading stuck on Debian system with 3.10 kernel. The debugging session revealed that the initial registration of OSS sequencer clients stuck at module loading time, which involves again with request_module() at the init phase. This is triggered only by special --install stuff Debian is using, but it's still not good to have such loops. As a workaround, call the registration part asynchronously. This is a better approach irrespective of the hang fix, in anyway. Reported-and-tested-by: Philipp Matthias Hahn Cc: Signed-off-by: Takashi Iwai --- sound/core/seq/oss/seq_oss_init.c | 16 +++++++++++++--- sound/core/seq/oss/seq_oss_midi.c | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index e3cb46fef2c7..b3f39b5ed742 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -31,6 +31,7 @@ #include #include #include +#include /* * common variables @@ -60,6 +61,14 @@ static void free_devinfo(void *private); #define call_ctl(type,rec) snd_seq_kernel_client_ctl(system_client, type, rec) +/* call snd_seq_oss_midi_lookup_ports() asynchronously */ +static void async_call_lookup_ports(struct work_struct *work) +{ + snd_seq_oss_midi_lookup_ports(system_client); +} + +static DECLARE_WORK(async_lookup_work, async_call_lookup_ports); + /* * create sequencer client for OSS sequencer */ @@ -85,9 +94,6 @@ snd_seq_oss_create_client(void) system_client = rc; debug_printk(("new client = %d\n", rc)); - /* look up midi devices */ - snd_seq_oss_midi_lookup_ports(system_client); - /* create annoucement receiver port */ memset(port, 0, sizeof(*port)); strcpy(port->name, "Receiver"); @@ -115,6 +121,9 @@ snd_seq_oss_create_client(void) } rc = 0; + /* look up midi devices */ + schedule_work(&async_lookup_work); + __error: kfree(port); return rc; @@ -160,6 +169,7 @@ receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic int snd_seq_oss_delete_client(void) { + cancel_work_sync(&async_lookup_work); if (system_client >= 0) snd_seq_delete_kernel_client(system_client); diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 677dc84590c7..862d84893ee8 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -72,7 +72,7 @@ static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, * look up the existing ports * this looks a very exhausting job. */ -int __init +int snd_seq_oss_midi_lookup_ports(int client) { struct snd_seq_client_info *clinfo; -- GitLab From 58cbd3ac09b939ac613dfd4ac9d10bc6f7769f48 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Jul 2013 15:28:15 +0200 Subject: [PATCH 2839/2900] drm/shmobile: Use the GEM PRIME helpers The GEM CMA PRIME import/export helpers have been removed in favor of generic GEM PRIME helpers with GEM CMA low-level operations. Fix the driver accordingly. Reported-by: Mark Brown Signed-off-by: Laurent Pinchart Tested-by: Mark Brown --- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index edc10181f551..5f83f9a3ef59 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -276,8 +276,13 @@ static struct drm_driver shmob_drm_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_cma_dmabuf_import, - .gem_prime_export = drm_gem_cma_dmabuf_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_cma_dumb_destroy, -- GitLab From ffb40400762d86a34318160e8f2169b66f01473d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 10 Jul 2013 15:23:35 +0200 Subject: [PATCH 2840/2900] drm/rcar-du: Use the GEM PRIME helpers The GEM CMA PRIME import/export helpers have been removed in favor of generic GEM PRIME helpers with GEM CMA low-level operations. Fix the driver accordingly. Reported-by: Mark Brown Signed-off-by: Laurent Pinchart Tested-by: Mark Brown --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index ff82877de876..dc0fe09b2ba1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -249,8 +249,13 @@ static struct drm_driver rcar_du_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_cma_dmabuf_import, - .gem_prime_export = drm_gem_cma_dmabuf_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, .dumb_create = rcar_du_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_cma_dumb_destroy, -- GitLab From a47bde9b7cbeb87dbb1c5554e90b770d3cc06c5c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 17 Jul 2013 17:28:48 +0200 Subject: [PATCH 2841/2900] MIPS: Delete dead invocation of exception_exit(). panic() doesn't return so this call was useless. Signed-off-by: Ralf Baechle Reported-by: Alexander Sverdlin --- arch/mips/kernel/traps.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 0903d70b2cfe..3035a40c4559 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1242,7 +1242,6 @@ asmlinkage void do_mcheck(struct pt_regs *regs) panic("Caught Machine Check exception - %scaused by multiple " "matching entries in the TLB.", (multi_match) ? "" : "not "); - exception_exit(prev_state); } asmlinkage void do_mt(struct pt_regs *regs) -- GitLab From 1294d4a36d1e0dacfc37c1f269d78ff58f0cd8bc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 16 Jul 2013 15:58:50 -0400 Subject: [PATCH 2842/2900] drm/radeon: add a module parameter to disable aspm Can cause hangs when enabled in certain motherboards. Set radeon.aspm=0 to disable aspm. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen.c | 3 +++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_drv.c | 4 ++++ drivers/gpu/drm/radeon/rv6xx_dpm.c | 14 ++++++++------ drivers/gpu/drm/radeon/rv770_dpm.c | 14 ++++++++------ drivers/gpu/drm/radeon/si.c | 3 +++ 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 526e428cb4d0..038dcac7670c 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -5515,6 +5515,9 @@ void evergreen_program_aspm(struct radeon_device *rdev) */ bool fusion_platform = false; + if (radeon_aspm == 0) + return; + if (!(rdev->flags & RADEON_IS_PCIE)) return; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 001081757895..2f08219c39b6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -97,6 +97,7 @@ extern int radeon_msi; extern int radeon_lockup_timeout; extern int radeon_fastfb; extern int radeon_dpm; +extern int radeon_aspm; /* * Copy from radeon_drv.h so we don't have to include both and have conflicting diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index e5419b350170..29876b1be8ec 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -167,6 +167,7 @@ int radeon_msi = -1; int radeon_lockup_timeout = 10000; int radeon_fastfb = 0; int radeon_dpm = -1; +int radeon_aspm = -1; MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -225,6 +226,9 @@ module_param_named(fastfb, radeon_fastfb, int, 0444); MODULE_PARM_DESC(dpm, "DPM support (1 = enable, 0 = disable, -1 = auto)"); module_param_named(dpm, radeon_dpm, int, 0444); +MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = auto)"); +module_param_named(aspm, radeon_aspm, int, 0444); + static struct pci_device_id pciidlist[] = { radeon_PCI_IDS }; diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index 8303de267ee5..65e33f387341 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c @@ -1763,12 +1763,14 @@ void rv6xx_setup_asic(struct radeon_device *rdev) { r600_enable_acpi_pm(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) - rv6xx_enable_l0s(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) - rv6xx_enable_l1(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) - rv6xx_enable_pll_sleep_in_l1(rdev); + if (radeon_aspm != 0) { + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) + rv6xx_enable_l0s(rdev); + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) + rv6xx_enable_l1(rdev); + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) + rv6xx_enable_pll_sleep_in_l1(rdev); + } } void rv6xx_dpm_display_configuration_changed(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index d914e04ea39a..2d347925f77d 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2099,12 +2099,14 @@ void rv770_dpm_setup_asic(struct radeon_device *rdev) rv770_enable_acpi_pm(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) - rv770_enable_l0s(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) - rv770_enable_l1(rdev); - if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) - rv770_enable_pll_sleep_in_l1(rdev); + if (radeon_aspm != 0) { + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s) + rv770_enable_l0s(rdev); + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1) + rv770_enable_l1(rdev); + if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1) + rv770_enable_pll_sleep_in_l1(rdev); + } } void rv770_dpm_display_configuration_changed(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d3f05076f385..d325280e2f9f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -7053,6 +7053,9 @@ static void si_program_aspm(struct radeon_device *rdev) bool disable_l0s = false, disable_l1 = false, disable_plloff_in_l1 = false; bool disable_clkreq = false; + if (radeon_aspm == 0) + return; + if (!(rdev->flags & RADEON_IS_PCIE)) return; -- GitLab From 1fa4252af760560f77ca3d5d360fd62df3292c7f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Jul 2013 10:18:52 -0400 Subject: [PATCH 2843/2900] drm/radeon: fix an endian bug in atom table parsing Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index fbdaff55556b..0c3455a73992 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3638,7 +3638,7 @@ int radeon_atom_get_mclk_range_table(struct radeon_device *rdev, p += le16_to_cpu(vram_module->usModuleSize); } mclk_range_table->num_entries = (u8) - ((vram_module->usModuleSize - offsetof(ATOM_VRAM_MODULE_V4, asMemTiming)) / + ((le16_to_cpu(vram_module->usModuleSize) - offsetof(ATOM_VRAM_MODULE_V4, asMemTiming)) / mem_timing_size); p = (u8 *)vram_module->asMemTiming; for (i = 0; i < mclk_range_table->num_entries; i++) { -- GitLab From 77c7d50a4a9f1fa3aa42adad00e7b44aa70ec910 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Jul 2013 10:52:43 -0400 Subject: [PATCH 2844/2900] drm/radeon/dpm: fix atom vram table parsing Parsing the table in incorrectly led to problems with certain asics with mclk switching. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 26 +++++++++--------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 0c3455a73992..a2e324188bc9 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3513,7 +3513,6 @@ int radeon_atom_get_memory_info(struct radeon_device *rdev, u8 frev, crev, i; u16 data_offset, size; union vram_info *vram_info; - u8 *p; memset(mem_info, 0, sizeof(struct atom_memory_info)); @@ -3529,13 +3528,12 @@ int radeon_atom_get_memory_info(struct radeon_device *rdev, if (module_index < vram_info->v1_3.ucNumOfVRAMModule) { ATOM_VRAM_MODULE_V3 *vram_module = (ATOM_VRAM_MODULE_V3 *)vram_info->v1_3.aVramInfo; - p = (u8 *)vram_info->v1_3.aVramInfo; for (i = 0; i < module_index; i++) { - vram_module = (ATOM_VRAM_MODULE_V3 *)p; if (le16_to_cpu(vram_module->usSize) == 0) return -EINVAL; - p += le16_to_cpu(vram_module->usSize); + vram_module = (ATOM_VRAM_MODULE_V3 *) + ((u8 *)vram_module + le16_to_cpu(vram_module->usSize)); } mem_info->mem_vendor = vram_module->asMemory.ucMemoryVenderID & 0xf; mem_info->mem_type = vram_module->asMemory.ucMemoryType & 0xf0; @@ -3547,13 +3545,12 @@ int radeon_atom_get_memory_info(struct radeon_device *rdev, if (module_index < vram_info->v1_4.ucNumOfVRAMModule) { ATOM_VRAM_MODULE_V4 *vram_module = (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo; - p = (u8 *)vram_info->v1_4.aVramInfo; for (i = 0; i < module_index; i++) { - vram_module = (ATOM_VRAM_MODULE_V4 *)p; if (le16_to_cpu(vram_module->usModuleSize) == 0) return -EINVAL; - p += le16_to_cpu(vram_module->usModuleSize); + vram_module = (ATOM_VRAM_MODULE_V4 *) + ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize)); } mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf; mem_info->mem_type = vram_module->ucMemoryType & 0xf0; @@ -3572,13 +3569,12 @@ int radeon_atom_get_memory_info(struct radeon_device *rdev, if (module_index < vram_info->v2_1.ucNumOfVRAMModule) { ATOM_VRAM_MODULE_V7 *vram_module = (ATOM_VRAM_MODULE_V7 *)vram_info->v2_1.aVramInfo; - p = (u8 *)vram_info->v2_1.aVramInfo; for (i = 0; i < module_index; i++) { - vram_module = (ATOM_VRAM_MODULE_V7 *)p; if (le16_to_cpu(vram_module->usModuleSize) == 0) return -EINVAL; - p += le16_to_cpu(vram_module->usModuleSize); + vram_module = (ATOM_VRAM_MODULE_V7 *) + ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize)); } mem_info->mem_vendor = vram_module->ucMemoryVenderID & 0xf; mem_info->mem_type = vram_module->ucMemoryType & 0xf0; @@ -3628,21 +3624,19 @@ int radeon_atom_get_mclk_range_table(struct radeon_device *rdev, if (module_index < vram_info->v1_4.ucNumOfVRAMModule) { ATOM_VRAM_MODULE_V4 *vram_module = (ATOM_VRAM_MODULE_V4 *)vram_info->v1_4.aVramInfo; - ATOM_MEMORY_TIMING_FORMAT *format; - p = (u8 *)vram_info->v1_4.aVramInfo; for (i = 0; i < module_index; i++) { - vram_module = (ATOM_VRAM_MODULE_V4 *)p; if (le16_to_cpu(vram_module->usModuleSize) == 0) return -EINVAL; - p += le16_to_cpu(vram_module->usModuleSize); + vram_module = (ATOM_VRAM_MODULE_V4 *) + ((u8 *)vram_module + le16_to_cpu(vram_module->usModuleSize)); } mclk_range_table->num_entries = (u8) ((le16_to_cpu(vram_module->usModuleSize) - offsetof(ATOM_VRAM_MODULE_V4, asMemTiming)) / mem_timing_size); - p = (u8 *)vram_module->asMemTiming; + p = (u8 *)&vram_module->asMemTiming[0]; for (i = 0; i < mclk_range_table->num_entries; i++) { - format = (ATOM_MEMORY_TIMING_FORMAT *)p; + ATOM_MEMORY_TIMING_FORMAT *format = (ATOM_MEMORY_TIMING_FORMAT *)p; mclk_range_table->mclk[i] = le32_to_cpu(format->ulClkRange); p += mem_timing_size; } -- GitLab From 48fa04c3fcdb4f6ac041976bedaf19ca5bee20c0 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Wed, 17 Jul 2013 14:02:23 -0400 Subject: [PATCH 2845/2900] drm/radeon/dpm/atom: restructure logic to work around a compiler bug It seems gcc 4.8.1 generates bogus code for the old logic causing part of the function to get skipped. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66932 https://bugs.freedesktop.org/show_bug.cgi?id=66972 https://bugs.freedesktop.org/show_bug.cgi?id=66945 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index a2e324188bc9..2606ec680ae3 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3703,8 +3703,9 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1; if (num_entries > VBIOS_MC_REGISTER_ARRAY_SIZE) return -EINVAL; - while (!(reg_block->asRegIndexBuf[i].ucPreRegDataLength & ACCESS_PLACEHOLDER) && - (i < num_entries)) { + while (i < num_entries) { + if (reg_block->asRegIndexBuf[i].ucPreRegDataLength & ACCESS_PLACEHOLDER) + break; reg_table->mc_reg_address[i].s1 = (u16)(le16_to_cpu(reg_block->asRegIndexBuf[i].usRegIndex)); reg_table->mc_reg_address[i].pre_reg_data = -- GitLab From fe5c3561e6f0ac7c9546209f01351113c1b77ec8 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sat, 13 Jul 2013 10:18:18 -0700 Subject: [PATCH 2846/2900] vxlan: add necessary locking on device removal The socket management is now done in workqueue (outside of RTNL) and protected by vn->sock_lock. There were two possible bugs, first the vxlan device was removed from the VNI hash table per socket without holding lock. And there was a race when device is created and the workqueue could run after deletion. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0ba1e7edbb1b..a5ba8dd7e6be 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1767,9 +1767,15 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, static void vxlan_dellink(struct net_device *dev, struct list_head *head) { + struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); + flush_workqueue(vxlan_wq); + + spin_lock(&vn->sock_lock); hlist_del_rcu(&vxlan->hlist); + spin_unlock(&vn->sock_lock); + list_del(&vxlan->next); unregister_netdevice_queue(dev, head); } -- GitLab From 093b9c71b6e450e375f4646ba86faed0195ec7df Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 17 Jul 2013 08:09:37 +0100 Subject: [PATCH 2847/2900] xen-netfront: pull on receive skb may need to happen earlier Due to commit 3683243b ("xen-netfront: use __pskb_pull_tail to ensure linear area is big enough on RX") xennet_fill_frags() may end up filling MAX_SKB_FRAGS + 1 fragments in a receive skb, and only reduce the fragment count subsequently via __pskb_pull_tail(). That's a result of xennet_get_responses() allowing a maximum of one more slot to be consumed (and intermediately transformed into a fragment) if the head slot has a size less than or equal to RX_COPY_THRESHOLD. Hence we need to adjust xennet_fill_frags() to pull earlier if we reached the maximum fragment count - due to the described behavior of xennet_get_responses() this guarantees that at least the first fragment will get completely consumed, and hence the fragment count reduced. In order to not needlessly call __pskb_pull_tail() twice, make the original call conditional upon the pull target not having been reached yet, and defer the newly added one as much as possible (an alternative would have been to always call the function right before the call to xennet_fill_frags(), but that would imply more frequent cases of needing to call it twice). Signed-off-by: Jan Beulich Acked-by: Wei Liu Cc: Ian Campbell Cc: stable@vger.kernel.org (3.6 onwards) Acked-by: Ian Campbell Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index ff7f111fffee..36808bf25677 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -286,8 +286,7 @@ static void xennet_alloc_rx_buffers(struct net_device *dev) break; } - __skb_fill_page_desc(skb, 0, page, 0, 0); - skb_shinfo(skb)->nr_frags = 1; + skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE); __skb_queue_tail(&np->rx_batch, skb); } @@ -831,7 +830,6 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np, struct sk_buff_head *list) { struct skb_shared_info *shinfo = skb_shinfo(skb); - int nr_frags = shinfo->nr_frags; RING_IDX cons = np->rx.rsp_cons; struct sk_buff *nskb; @@ -840,19 +838,21 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np, RING_GET_RESPONSE(&np->rx, ++cons); skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; - __skb_fill_page_desc(skb, nr_frags, - skb_frag_page(nfrag), - rx->offset, rx->status); + if (shinfo->nr_frags == MAX_SKB_FRAGS) { + unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - skb->data_len += rx->status; + BUG_ON(pull_to <= skb_headlen(skb)); + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + } + BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS); + + skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag), + rx->offset, rx->status, PAGE_SIZE); skb_shinfo(nskb)->nr_frags = 0; kfree_skb(nskb); - - nr_frags++; } - shinfo->nr_frags = nr_frags; return cons; } @@ -933,7 +933,8 @@ static int handle_incoming_queue(struct net_device *dev, while ((skb = __skb_dequeue(rxq)) != NULL) { int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); + if (pull_to > skb_headlen(skb)) + __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); /* Ethernet work: Delayed to here as it peeks the header. */ skb->protocol = eth_type_trans(skb, dev); @@ -1019,16 +1020,10 @@ static int xennet_poll(struct napi_struct *napi, int budget) skb_shinfo(skb)->frags[0].page_offset = rx->offset; skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status); skb->data_len = rx->status; + skb->len += rx->status; i = xennet_fill_frags(np, skb, &tmpq); - /* - * Truesize is the actual allocation size, even if the - * allocation is only partially used. - */ - skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags; - skb->len += skb->data_len; - if (rx->flags & XEN_NETRXF_csum_blank) skb->ip_summed = CHECKSUM_PARTIAL; else if (rx->flags & XEN_NETRXF_data_validated) -- GitLab From f90555cbe629e14c6af1dcec1933a3833ecd321f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 17 Jul 2013 16:34:12 -0400 Subject: [PATCH 2848/2900] drm/radeon/dpm/atom: fix broken gcc harder See bugs: https://bugs.freedesktop.org/show_bug.cgi?id=66932 https://bugs.freedesktop.org/show_bug.cgi?id=66972 https://bugs.freedesktop.org/show_bug.cgi?id=66945 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_atombios.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 2606ec680ae3..e3f3e8841789 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3699,18 +3699,21 @@ int radeon_atom_init_mc_reg_table(struct radeon_device *rdev, (ATOM_MEMORY_SETTING_DATA_BLOCK *) ((u8 *)reg_block + (2 * sizeof(u16)) + le16_to_cpu(reg_block->usRegIndexTblSize)); + ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0]; num_entries = (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) / sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1; if (num_entries > VBIOS_MC_REGISTER_ARRAY_SIZE) return -EINVAL; while (i < num_entries) { - if (reg_block->asRegIndexBuf[i].ucPreRegDataLength & ACCESS_PLACEHOLDER) + if (format->ucPreRegDataLength & ACCESS_PLACEHOLDER) break; reg_table->mc_reg_address[i].s1 = - (u16)(le16_to_cpu(reg_block->asRegIndexBuf[i].usRegIndex)); + (u16)(le16_to_cpu(format->usRegIndex)); reg_table->mc_reg_address[i].pre_reg_data = - (u8)(reg_block->asRegIndexBuf[i].ucPreRegDataLength); + (u8)(format->ucPreRegDataLength); i++; + format = (ATOM_INIT_REG_INDEX_FORMAT *) + ((u8 *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT)); } reg_table->last = i; while ((*(u32 *)reg_data != END_OF_REG_DATA_BLOCK) && -- GitLab From 444bddc4b9b3313a562cd3ba40f780fb82570f7d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Jul 2013 13:05:23 -0400 Subject: [PATCH 2849/2900] drm/radeon/dpm: add debugfs support for RS780/RS880 (v3) This allows you to look at the current DPM state via debugfs. Due to the way the hardware works on these asics, there's no way to look up exactly what power state we are in, so we make the best guess we can based on the current sclk. v2: Anthoine's version v3: fix ref div Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 2 ++ drivers/gpu/drm/radeon/rs780_dpm.c | 25 +++++++++++++++++++++++++ drivers/gpu/drm/radeon/rs780d.h | 3 +++ 4 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index fea997e247ba..78bec1a58ed1 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1270,6 +1270,7 @@ static struct radeon_asic rs780_asic = { .get_sclk = &rs780_dpm_get_sclk, .get_mclk = &rs780_dpm_get_mclk, .print_power_state = &rs780_dpm_print_power_state, + .debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index b04b5789f4a8..ca1895709908 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -433,6 +433,8 @@ u32 rs780_dpm_get_sclk(struct radeon_device *rdev, bool low); u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low); void rs780_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); +void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m); /* uvd */ int r600_uvd_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index bef832a62fee..d1a1ce73bd45 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -28,6 +28,7 @@ #include "r600_dpm.h" #include "rs780_dpm.h" #include "atom.h" +#include static struct igp_ps *rs780_get_ps(struct radeon_ps *rps) { @@ -961,3 +962,27 @@ u32 rs780_dpm_get_mclk(struct radeon_device *rdev, bool low) return pi->bootup_uma_clk; } + +void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, + struct seq_file *m) +{ + struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct igp_ps *ps = rs780_get_ps(rps); + u32 current_fb_div = RREG32(FVTHROT_STATUS_REG0) & CURRENT_FEEDBACK_DIV_MASK; + u32 func_cntl = RREG32(CG_SPLL_FUNC_CNTL); + u32 ref_div = ((func_cntl & SPLL_REF_DIV_MASK) >> SPLL_REF_DIV_SHIFT) + 1; + u32 post_div = ((func_cntl & SPLL_SW_HILEN_MASK) >> SPLL_SW_HILEN_SHIFT) + 1 + + ((func_cntl & SPLL_SW_LOLEN_MASK) >> SPLL_SW_LOLEN_SHIFT) + 1; + u32 sclk = (rdev->clock.spll.reference_freq * current_fb_div) / + (post_div * ref_div); + + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + + /* guess based on the current sclk */ + if (sclk < (ps->sclk_low + 500)) + seq_printf(m, "power level 0 sclk: %u vddc_index: %d\n", + ps->sclk_low, ps->min_voltage); + else + seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", + ps->sclk_high, ps->max_voltage); +} diff --git a/drivers/gpu/drm/radeon/rs780d.h b/drivers/gpu/drm/radeon/rs780d.h index b1142ed1c628..cfbe9a43d97b 100644 --- a/drivers/gpu/drm/radeon/rs780d.h +++ b/drivers/gpu/drm/radeon/rs780d.h @@ -28,6 +28,7 @@ # define SPLL_SLEEP (1 << 1) # define SPLL_REF_DIV(x) ((x) << 2) # define SPLL_REF_DIV_MASK (7 << 2) +# define SPLL_REF_DIV_SHIFT 2 # define SPLL_FB_DIV(x) ((x) << 5) # define SPLL_FB_DIV_MASK (0xff << 2) # define SPLL_FB_DIV_SHIFT 2 @@ -36,8 +37,10 @@ # define SPLL_PULSENUM_MASK (3 << 14) # define SPLL_SW_HILEN(x) ((x) << 16) # define SPLL_SW_HILEN_MASK (0xf << 16) +# define SPLL_SW_HILEN_SHIFT 16 # define SPLL_SW_LOLEN(x) ((x) << 20) # define SPLL_SW_LOLEN_MASK (0xf << 20) +# define SPLL_SW_LOLEN_SHIFT 20 # define SPLL_DIVEN (1 << 24) # define SPLL_BYPASS_EN (1 << 25) # define SPLL_CHG_STATUS (1 << 29) -- GitLab From b4a2cf76ab7c08628c62b2062dacefa496b59dfd Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 17 Jul 2013 16:43:16 -0400 Subject: [PATCH 2850/2900] NFSv4: Fix a regression against the FreeBSD server Technically, the Linux client is allowed by the NFSv4 spec to send 3 word bitmaps as part of an OPEN request. However, this causes the current FreeBSD server to return NFS4ERR_ATTRNOTSUPP errors. Fix the regression by making the Linux client use a 2 word bitmap unless doing NFSv4.2 with labeled NFS. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4xdr.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0abfb8466e79..c74d6168db99 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -999,6 +999,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, __be32 *p; __be32 *q; int len; + uint32_t bmval_len = 2; uint32_t bmval0 = 0; uint32_t bmval1 = 0; uint32_t bmval2 = 0; @@ -1010,7 +1011,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, * = 40 bytes, plus any contribution from variable-length fields * such as owner/group. */ - len = 20; + len = 8; /* Sigh */ if (iap->ia_valid & ATTR_SIZE) @@ -1040,8 +1041,6 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, } len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); } - if (label) - len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); if (iap->ia_valid & ATTR_ATIME_SET) len += 16; else if (iap->ia_valid & ATTR_ATIME) @@ -1050,15 +1049,22 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, len += 16; else if (iap->ia_valid & ATTR_MTIME) len += 4; + if (label) { + len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); + bmval_len = 3; + } + + len += bmval_len << 2; p = reserve_space(xdr, len); /* * We write the bitmap length now, but leave the bitmap and the attribute * buffer length to be backfilled at the end of this routine. */ - *p++ = cpu_to_be32(3); + *p++ = cpu_to_be32(bmval_len); q = p; - p += 4; + /* Skip bitmap entries + attrlen */ + p += bmval_len + 1; if (iap->ia_valid & ATTR_SIZE) { bmval0 |= FATTR4_WORD0_SIZE; @@ -1112,10 +1118,11 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, len, ((char *)p - (char *)q) + 4); BUG(); } - len = (char *)p - (char *)q - 16; + len = (char *)p - (char *)q - (bmval_len << 2); *q++ = htonl(bmval0); *q++ = htonl(bmval1); - *q++ = htonl(bmval2); + if (bmval_len == 3) + *q++ = htonl(bmval2); *q = htonl(len); /* out: */ -- GitLab From 242b2287cd7f27521c8b54a4101d569e53e7a0ca Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 2 Jul 2013 21:59:10 +0800 Subject: [PATCH 2851/2900] ACPICA: expose OSI version Expose acpi_gbl_osi_data so that code outside of ACPICA can check the value of the last successfull _OSI call. The definitions for OSI versions are moved to actypes.h so that other components can access them too. Based on a patch from Matthew Garrett which in turn was based on an earlier patch from Seth Forshee. [rjw: Changelog] Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/aclocal.h | 13 ------------- include/acpi/acpixf.h | 1 + include/acpi/actypes.h | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index dfed26545ba2..d4a4901637cd 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -931,19 +931,6 @@ struct acpi_bit_register_info { /* Structs and definitions for _OSI support and I/O port validation */ -#define ACPI_OSI_WIN_2000 0x01 -#define ACPI_OSI_WIN_XP 0x02 -#define ACPI_OSI_WIN_XP_SP1 0x03 -#define ACPI_OSI_WINSRV_2003 0x04 -#define ACPI_OSI_WIN_XP_SP2 0x05 -#define ACPI_OSI_WINSRV_2003_SP1 0x06 -#define ACPI_OSI_WIN_VISTA 0x07 -#define ACPI_OSI_WINSRV_2008 0x08 -#define ACPI_OSI_WIN_VISTA_SP1 0x09 -#define ACPI_OSI_WIN_VISTA_SP2 0x0A -#define ACPI_OSI_WIN_7 0x0B -#define ACPI_OSI_WIN_8 0x0C - #define ACPI_ALWAYS_ILLEGAL 0x00 struct acpi_interface_info { diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 1b09300810e6..22d497ee6ef9 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -62,6 +62,7 @@ extern u32 acpi_current_gpe_count; extern struct acpi_table_fadt acpi_gbl_FADT; extern u8 acpi_gbl_system_awake_and_running; extern u8 acpi_gbl_reduced_hardware; /* ACPI 5.0 */ +extern u8 acpi_gbl_osi_data; /* Runtime configuration of debug print levels */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index a64adcc29ae5..22b03c9286e9 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1144,4 +1144,19 @@ struct acpi_memory_list { #endif }; +/* Definitions for _OSI support */ + +#define ACPI_OSI_WIN_2000 0x01 +#define ACPI_OSI_WIN_XP 0x02 +#define ACPI_OSI_WIN_XP_SP1 0x03 +#define ACPI_OSI_WINSRV_2003 0x04 +#define ACPI_OSI_WIN_XP_SP2 0x05 +#define ACPI_OSI_WINSRV_2003_SP1 0x06 +#define ACPI_OSI_WIN_VISTA 0x07 +#define ACPI_OSI_WINSRV_2008 0x08 +#define ACPI_OSI_WIN_VISTA_SP1 0x09 +#define ACPI_OSI_WIN_VISTA_SP2 0x0A +#define ACPI_OSI_WIN_7 0x0B +#define ACPI_OSI_WIN_8 0x0C + #endif /* __ACTYPES_H__ */ -- GitLab From c04c697cf1fe8f0962ccd3c2392a9b637a5307aa Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 16 Jul 2013 17:08:16 +0000 Subject: [PATCH 2852/2900] ACPI / video: Always call acpi_video_init_brightness() on init We have to call acpi_video_init_brightness() even if we're not going to initialise the backlight - Thinkpads seem to use this as the trigger for enabling ACPI notifications rather than handling it in firmware. [rjw: Drop the brightness object created by acpi_video_init_brightness() if we are not going to use it.] Signed-off-by: Matthew Garrett Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5d7075d25700..f236e172d948 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -898,6 +898,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DDC = 1; } + if (acpi_video_init_brightness(device)) + return; + if (acpi_video_backlight_support()) { struct backlight_properties props; struct pci_dev *pdev; @@ -907,9 +910,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) static int count = 0; char *name; - result = acpi_video_init_brightness(device); - if (result) - return; name = kasprintf(GFP_KERNEL, "acpi_video%d", count); if (!name) return; @@ -969,6 +969,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); + } else { + /* Remove the brightness object. */ + kfree(device->brightness->levels); + kfree(device->brightness); + device->brightness = NULL; } } -- GitLab From 3c0fc0710185e618a661528eed2183102e25c2f8 Mon Sep 17 00:00:00 2001 From: Liu ShuoX Date: Tue, 16 Jul 2013 16:23:44 +0800 Subject: [PATCH 2853/2900] PNP / ACPI: avoid garbage in resource name Set temporary variable as 0 to avoid garbage string output from /proc/iomem after register resources and reset to PNP dev name later. Signed-off-by: Liu ShuoX Signed-off-by: Rafael J. Wysocki --- drivers/pnp/pnpacpi/rsparser.c | 2 +- drivers/pnp/resource.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 9847ab163829..167f3d00c916 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -180,7 +180,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, struct pnp_dev *dev = data; struct acpi_resource_dma *dma; struct acpi_resource_vendor_typed *vendor_typed; - struct resource r; + struct resource r = {0}; int i, flags; if (acpi_dev_resource_memory(res, &r) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 3e6db1c1dc29..d95e101ffb43 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -515,6 +515,7 @@ struct pnp_resource *pnp_add_resource(struct pnp_dev *dev, } pnp_res->res = *res; + pnp_res->res.name = dev->name; dev_dbg(&dev->dev, "%pR\n", res); return pnp_res; } -- GitLab From 8c5bd7adb2ce47e6aa39d17b2375f69b0c0aa255 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 18 Jul 2013 02:08:06 +0200 Subject: [PATCH 2854/2900] ACPI / video / i915: No ACPI backlight if firmware expects Windows 8 According to Matthew Garrett, "Windows 8 leaves backlight control up to individual graphics drivers rather than making ACPI calls itself. There's plenty of evidence to suggest that the Intel driver for Windows [8] doesn't use the ACPI interface, including the fact that it's broken on a bunch of machines when the OS claims to support Windows 8. The simplest thing to do appears to be to disable the ACPI backlight interface on these systems". There's a problem with that approach, however, because simply avoiding to register the ACPI backlight interface if the firmware calls _OSI for Windows 8 may not work in the following situations: (1) The ACPI backlight interface actually works on the given system and the i915 driver is not loaded (e.g. another graphics driver is used). (2) The ACPI backlight interface doesn't work on the given system, but there is a vendor platform driver that will register its own, equally broken, backlight interface if not prevented from doing so by the ACPI subsystem. Therefore we need to allow the ACPI backlight interface to be registered until the i915 driver is loaded which then will unregister it if the firmware has called _OSI for Windows 8 (or will register the ACPI video driver without backlight support if not already present). For this reason, introduce an alternative function for registering ACPI video, acpi_video_register_with_quirks(), that will check whether or not the ACPI video driver has already been registered and whether or not the backlight Windows 8 quirk has to be applied. If the quirk has to be applied, it will block the ACPI backlight support and either unregister the backlight interface if the ACPI video driver has already been registered, or register the ACPI video driver without the backlight interface otherwise. Make the i915 driver use acpi_video_register_with_quirks() instead of acpi_video_register() in i915_driver_load(). This change is based on earlier patches from Matthew Garrett, Chun-Yi Lee and Seth Forshee and includes a fix from Aaron Lu's. References: https://bugzilla.kernel.org/show_bug.cgi?id=51231 Tested-by: Aaron Lu Tested-by: Igor Gnatenko Tested-by: Yves-Alexis Perez Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu Acked-by: Matthew Garrett --- drivers/acpi/internal.h | 11 ++++++ drivers/acpi/video.c | 69 +++++++++++++++++++++++++++++---- drivers/acpi/video_detect.c | 21 ++++++++++ drivers/gpu/drm/i915/i915_dma.c | 2 +- include/acpi/video.h | 11 +++++- include/linux/acpi.h | 1 + 6 files changed, 105 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 3a50a34fe176..227aca77ee1e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -164,4 +164,15 @@ struct platform_device; int acpi_create_platform_device(struct acpi_device *adev, const struct acpi_device_id *id); +/*-------------------------------------------------------------------------- + Video + -------------------------------------------------------------------------- */ +#if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) +bool acpi_video_backlight_quirks(void); +bool acpi_video_verify_backlight_support(void); +#else +static inline bool acpi_video_backlight_quirks(void) { return false; } +static inline bool acpi_video_verify_backlight_support(void) { return false; } +#endif + #endif /* _ACPI_INTERNAL_H_ */ diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f236e172d948..e9d4bb60c35c 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -44,6 +44,8 @@ #include #include +#include "internal.h" + #define PREFIX "ACPI: " #define ACPI_VIDEO_BUS_NAME "Video Bus" @@ -901,7 +903,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (acpi_video_init_brightness(device)) return; - if (acpi_video_backlight_support()) { + if (acpi_video_verify_backlight_support()) { struct backlight_properties props; struct pci_dev *pdev; acpi_handle acpi_parent; @@ -1356,8 +1358,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; - /* no warning message if acpi_backlight=vendor is used */ - if (!acpi_video_backlight_support()) + /* no warning message if acpi_backlight=vendor or a quirk is used */ + if (!acpi_video_verify_backlight_support()) return 0; if (!device->brightness) @@ -1859,6 +1861,46 @@ static int acpi_video_bus_remove(struct acpi_device *device) return 0; } +static acpi_status video_unregister_backlight(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + struct acpi_device *acpi_dev; + struct acpi_video_bus *video; + struct acpi_video_device *dev, *next; + + if (acpi_bus_get_device(handle, &acpi_dev)) + return AE_OK; + + if (acpi_match_device_ids(acpi_dev, video_device_ids)) + return AE_OK; + + video = acpi_driver_data(acpi_dev); + if (!video) + return AE_OK; + + acpi_video_bus_stop_devices(video); + mutex_lock(&video->device_list_lock); + list_for_each_entry_safe(dev, next, &video->video_device_list, entry) { + if (dev->backlight) { + backlight_device_unregister(dev->backlight); + dev->backlight = NULL; + kfree(dev->brightness->levels); + kfree(dev->brightness); + } + if (dev->cooling_dev) { + sysfs_remove_link(&dev->dev->dev.kobj, + "thermal_cooling"); + sysfs_remove_link(&dev->cooling_dev->device.kobj, + "device"); + thermal_cooling_device_unregister(dev->cooling_dev); + dev->cooling_dev = NULL; + } + } + mutex_unlock(&video->device_list_lock); + acpi_video_bus_start_devices(video); + return AE_OK; +} + static int __init is_i740(struct pci_dev *dev) { if (dev->device == 0x00D1) @@ -1890,14 +1932,25 @@ static int __init intel_opregion_present(void) return opregion; } -int acpi_video_register(void) +int __acpi_video_register(bool backlight_quirks) { - int result = 0; + bool no_backlight; + int result; + + no_backlight = backlight_quirks ? acpi_video_backlight_quirks() : false; + if (register_count) { /* - * if the function of acpi_video_register is already called, - * don't register the acpi_vide_bus again and return no error. + * If acpi_video_register() has been called already, don't try + * to register acpi_video_bus, but unregister backlight devices + * if no backlight support is requested. */ + if (no_backlight) + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + video_unregister_backlight, + NULL, NULL, NULL); + return 0; } @@ -1913,7 +1966,7 @@ int acpi_video_register(void) return 0; } -EXPORT_SYMBOL(acpi_video_register); +EXPORT_SYMBOL(__acpi_video_register); void acpi_video_unregister(void) { diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index e6bd910bc6ed..826e52def080 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -38,6 +38,8 @@ #include #include +#include "internal.h" + #define PREFIX "ACPI: " ACPI_MODULE_NAME("video"); @@ -234,6 +236,17 @@ static void acpi_video_caps_check(void) acpi_video_get_capabilities(NULL); } +bool acpi_video_backlight_quirks(void) +{ + if (acpi_gbl_osi_data >= ACPI_OSI_WIN_8) { + acpi_video_caps_check(); + acpi_video_support |= ACPI_VIDEO_SKIP_BACKLIGHT; + return true; + } + return false; +} +EXPORT_SYMBOL(acpi_video_backlight_quirks); + /* Promote the vendor interface instead of the generic video module. * This function allow DMI blacklists to be implemented by externals * platform drivers instead of putting a big blacklist in video_detect.c @@ -278,6 +291,14 @@ int acpi_video_backlight_support(void) } EXPORT_SYMBOL(acpi_video_backlight_support); +/* For the ACPI video driver use only. */ +bool acpi_video_verify_backlight_support(void) +{ + return (acpi_video_support & ACPI_VIDEO_SKIP_BACKLIGHT) ? + false : acpi_video_backlight_support(); +} +EXPORT_SYMBOL(acpi_video_verify_backlight_support); + /* * Use acpi_backlight=vendor/video to force that backlight switching * is processed by vendor specific acpi drivers or video.ko driver. diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index adb319b53ecd..cf188ab7051a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1648,7 +1648,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (INTEL_INFO(dev)->num_pipes) { /* Must be done after probing outputs */ intel_opregion_init(dev); - acpi_video_register(); + acpi_video_register_with_quirks(); } if (IS_GEN5(dev)) diff --git a/include/acpi/video.h b/include/acpi/video.h index 61109f2609fc..b26dc4fb7ba8 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -17,12 +17,21 @@ struct acpi_device; #define ACPI_VIDEO_DISPLAY_LEGACY_TV 0x0200 #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) -extern int acpi_video_register(void); +extern int __acpi_video_register(bool backlight_quirks); +static inline int acpi_video_register(void) +{ + return __acpi_video_register(false); +} +static inline int acpi_video_register_with_quirks(void) +{ + return __acpi_video_register(true); +} extern void acpi_video_unregister(void); extern int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, void **edid); #else static inline int acpi_video_register(void) { return 0; } +static inline int acpi_video_register_with_quirks(void) { return 0; } static inline void acpi_video_unregister(void) { return; } static inline int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, void **edid) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 353ba256f368..6ad72f92469c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -191,6 +191,7 @@ extern bool wmi_has_guid(const char *guid); #define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400 #define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800 +#define ACPI_VIDEO_SKIP_BACKLIGHT 0x1000 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE) -- GitLab From efaa14c7e981bdf8d3c8d39d3ed12bdc60faabb8 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Tue, 16 Jul 2013 13:08:05 +0800 Subject: [PATCH 2855/2900] ACPI / video: no automatic brightness changes by win8-compatible firmware Starting from win8, MS backlight control driver will set bit 2 of the parameter of control method _DOS, to inform firmware it should not perform any automatic brightness changes. This mostly affects hotkey notification deliver - if we do not set this bit, on hotkey press, firmware may choose to adjust brightness level instead of sending out notification and doing nothing. So this patch sets bit 2 when calling _DOS so that GUIs can show the notification window on hotkey press. This behavior change is only necessary for win8 systems. The MS document on win8 backlight control is here: http://msdn.microsoft.com/en-US/library/windows/hardware/jj159305 References: https://bugzilla.kernel.org/show_bug.cgi?id=52951 References: https://bugzilla.kernel.org/show_bug.cgi?id=56711 Reported-by: Micael Dias Reported-by: Dan Garton Reported-by: Bob Ziuchkovski Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index e9d4bb60c35c..c9fa4621ed25 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1539,14 +1539,20 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) /* acpi_video interface */ +/* + * Win8 requires setting bit2 of _DOS to let firmware know it shouldn't + * preform any automatic brightness change on receiving a notification. + */ static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { - return acpi_video_bus_DOS(video, 0, 0); + return acpi_video_bus_DOS(video, 0, + acpi_video_backlight_quirks() ? 1 : 0); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) { - return acpi_video_bus_DOS(video, 0, 1); + return acpi_video_bus_DOS(video, 0, + acpi_video_backlight_quirks() ? 0 : 1); } static void acpi_video_bus_notify(struct acpi_device *device, u32 event) -- GitLab From 7bb23c4934059c64cbee2e41d5d24ce122285176 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 16 Jul 2013 16:50:47 +1000 Subject: [PATCH 2856/2900] md/raid10: fix two problems with RAID10 resync. 1/ When an different between blocks is found, data is copied from one bio to the other. However bv_len is used as the length to copy and this could be zero. So use r10_bio->sectors to calculate length instead. Using bv_len was probably always a bit dubious, but the introduction of bio_advance made it much more likely to be a problem. 2/ When preparing some blocks for sync, we don't set BIO_UPTODATE except on bios that we schedule for a read. This ensures that missing/failed devices don't confuse the loop at the top of sync_request write. Commit 8be185f2c9d54d6 "raid10: Use bio_reset()" removed a loop which set BIO_UPTDATE on all appropriate bios. So we need to re-add that flag. These bugs were introduced in 3.10, so this patch is suitable for 3.10-stable, and can remove a potential for data corruption. Cc: stable@vger.kernel.org (3.10) Reported-by: Brassow Jonathan Signed-off-by: NeilBrown --- drivers/md/raid10.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index cd066b63bdaf..957a719e8c2f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2097,11 +2097,17 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) * both 'first' and 'i', so we just compare them. * All vec entries are PAGE_SIZE; */ - for (j = 0; j < vcnt; j++) + int sectors = r10_bio->sectors; + for (j = 0; j < vcnt; j++) { + int len = PAGE_SIZE; + if (sectors < (len / 512)) + len = sectors * 512; if (memcmp(page_address(fbio->bi_io_vec[j].bv_page), page_address(tbio->bi_io_vec[j].bv_page), - fbio->bi_io_vec[j].bv_len)) + len)) break; + sectors -= len/512; + } if (j == vcnt) continue; atomic64_add(r10_bio->sectors, &mddev->resync_mismatches); @@ -3407,6 +3413,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, if (bio->bi_end_io == end_sync_read) { md_sync_acct(bio->bi_bdev, nr_sectors); + set_bit(BIO_UPTODATE, &bio->bi_flags); generic_make_request(bio); } } -- GitLab From 5024c298311f3b97c85cb034f9edaa333fdb9338 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 17 Jul 2013 14:55:31 +1000 Subject: [PATCH 2857/2900] md: Remove recent change which allows devices to skip recovery. commit 7ceb17e87bde79d285a8b988cfed9eaeebe60b86 md: Allow devices to be re-added to a read-only array. allowed a bit more than just that. It also allows devices to be added to a read-write array and to end up skipping recovery. This patch removes the offending piece of code pending a rewrite for a subsequent release. More specifically: If the array has a bitmap, then the device will still need a bitmap based resync ('saved_raid_disk' is set under different conditions is a bitmap is present). If the array doesn't have a bitmap, then this is correct as long as nothing has been written to the array since the metadata was checked by ->validate_super. However there is no locking to ensure that there was no write. Bug was introduced in 3.10 and causes data corruption so patch is suitable for 3.10-stable. Cc: stable@vger.kernel.org (3.10) Reported-by: Joe Lawrence Signed-off-by: NeilBrown --- drivers/md/md.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index dddc87bcf64a..9f13e13506ef 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7716,20 +7716,6 @@ static int remove_and_add_spares(struct mddev *mddev, continue; rdev->recovery_offset = 0; - if (rdev->saved_raid_disk >= 0 && mddev->in_sync) { - spin_lock_irq(&mddev->write_lock); - if (mddev->in_sync) - /* OK, this device, which is in_sync, - * will definitely be noticed before - * the next write, so recovery isn't - * needed. - */ - rdev->recovery_offset = mddev->recovery_cp; - spin_unlock_irq(&mddev->write_lock); - } - if (mddev->ro && rdev->recovery_offset != MaxSector) - /* not safe to add this disk now */ - continue; if (mddev->pers-> hot_add_disk(mddev, rdev) == 0) { if (sysfs_link_rdev(mddev, rdev)) -- GitLab From 30bc9b53878a9921b02e3b5bc4283ac1c6de102a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 17 Jul 2013 15:19:29 +1000 Subject: [PATCH 2858/2900] md/raid1: fix bio handling problems in process_checks() Recent change to use bio_copy_data() in raid1 when repairing an array is faulty. The underlying may have changed the bio in various ways using bio_advance and these need to be undone not just for the 'sbio' which is being copied to, but also the 'pbio' (primary) which is being copied from. So perform the reset on all bios that were read from and do it early. This also ensure that the sbio->bi_io_vec[j].bv_len passed to memcmp is correct. This fixes a crash during a 'check' of a RAID1 array. The crash was introduced in 3.10 so this is suitable for 3.10-stable. Cc: stable@vger.kernel.org (3.10) Reported-by: Joe Lawrence Signed-off-by: NeilBrown --- drivers/md/raid1.c | 53 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index ec734588a1c6..d60412c7f995 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1849,6 +1849,36 @@ static int process_checks(struct r1bio *r1_bio) int i; int vcnt; + /* Fix variable parts of all bios */ + vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9); + for (i = 0; i < conf->raid_disks * 2; i++) { + int j; + int size; + struct bio *b = r1_bio->bios[i]; + if (b->bi_end_io != end_sync_read) + continue; + /* fixup the bio for reuse */ + bio_reset(b); + b->bi_vcnt = vcnt; + b->bi_size = r1_bio->sectors << 9; + b->bi_sector = r1_bio->sector + + conf->mirrors[i].rdev->data_offset; + b->bi_bdev = conf->mirrors[i].rdev->bdev; + b->bi_end_io = end_sync_read; + b->bi_private = r1_bio; + + size = b->bi_size; + for (j = 0; j < vcnt ; j++) { + struct bio_vec *bi; + bi = &b->bi_io_vec[j]; + bi->bv_offset = 0; + if (size > PAGE_SIZE) + bi->bv_len = PAGE_SIZE; + else + bi->bv_len = size; + size -= PAGE_SIZE; + } + } for (primary = 0; primary < conf->raid_disks * 2; primary++) if (r1_bio->bios[primary]->bi_end_io == end_sync_read && test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) { @@ -1857,12 +1887,10 @@ static int process_checks(struct r1bio *r1_bio) break; } r1_bio->read_disk = primary; - vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9); for (i = 0; i < conf->raid_disks * 2; i++) { int j; struct bio *pbio = r1_bio->bios[primary]; struct bio *sbio = r1_bio->bios[i]; - int size; if (sbio->bi_end_io != end_sync_read) continue; @@ -1888,27 +1916,6 @@ static int process_checks(struct r1bio *r1_bio) rdev_dec_pending(conf->mirrors[i].rdev, mddev); continue; } - /* fixup the bio for reuse */ - bio_reset(sbio); - sbio->bi_vcnt = vcnt; - sbio->bi_size = r1_bio->sectors << 9; - sbio->bi_sector = r1_bio->sector + - conf->mirrors[i].rdev->data_offset; - sbio->bi_bdev = conf->mirrors[i].rdev->bdev; - sbio->bi_end_io = end_sync_read; - sbio->bi_private = r1_bio; - - size = sbio->bi_size; - for (j = 0; j < vcnt ; j++) { - struct bio_vec *bi; - bi = &sbio->bi_io_vec[j]; - bi->bv_offset = 0; - if (size > PAGE_SIZE) - bi->bv_len = PAGE_SIZE; - else - bi->bv_len = size; - size -= PAGE_SIZE; - } bio_copy_data(sbio, pbio); } -- GitLab From 1c118b8226922d225a7df4127926ed2a2d73baaf Mon Sep 17 00:00:00 2001 From: Xiao Guangrong Date: Thu, 18 Jul 2013 12:52:37 +0800 Subject: [PATCH 2859/2900] KVM: MMU: avoid fast page fault fixing mmio page fault Currently, fast page fault incorrectly tries to fix mmio page fault when the generation number is invalid (spte.gen != kvm.gen). It then returns to guest to retry the fault since it sees the last spte is nonpresent. This causes an infinite loop. Since fast page fault only works for direct mmu, the issue exists when 1) tdp is enabled. It is only triggered only on AMD host since on Intel host the mmio page fault is recognized as ept-misconfig whose handler call fault-page path with error_code = 0 2) guest paging is disabled. Under this case, the issue is hardly discovered since paging disable is short-lived and the sptes will be invalid after memslot changed for 150 times Fix it by filtering out MMIO page faults in page_fault_can_be_fast. Reported-by: Markus Trippelsdorf Tested-by: Markus Trippelsdorf Signed-off-by: Xiao Guangrong Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 0d094da49541..9e9285ae9b94 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2810,6 +2810,13 @@ static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn, static bool page_fault_can_be_fast(struct kvm_vcpu *vcpu, u32 error_code) { + /* + * Do not fix the mmio spte with invalid generation number which + * need to be updated by slow page fault path. + */ + if (unlikely(error_code & PFERR_RSVD_MASK)) + return false; + /* * #PF can be fast only if the shadow page table is present and it * is caused by write-protect, that means we just need change the -- GitLab From 1eeb74782d354175ef9f3bff02fae62c6e0aef24 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 16 Jul 2013 10:24:48 +0200 Subject: [PATCH 2860/2900] s390/bpf,jit: call module_free() from any context The workqueue workaround is no longer needed. Same as 5199dfe531 "sparc: bpf_jit_comp: can call module_free() from any context". Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/net/bpf_jit_comp.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 82f165f8078c..a41f0b15faa1 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -772,8 +772,7 @@ void bpf_jit_compile(struct sk_filter *fp) } else if (jit.prg == cjit.prg && jit.lit == cjit.lit) { prg_len = jit.prg - jit.start; lit_len = jit.lit - jit.mid; - size = max_t(unsigned long, prg_len + lit_len, - sizeof(struct work_struct)); + size = prg_len + lit_len; if (size >= BPF_SIZE_MAX) goto out; jit.start = module_alloc(size); @@ -804,21 +803,8 @@ void bpf_jit_compile(struct sk_filter *fp) kfree(addrs); } -static void jit_free_defer(struct work_struct *arg) -{ - module_free(NULL, arg); -} - -/* run from softirq, we must use a work_struct to call - * module_free() from process context - */ void bpf_jit_free(struct sk_filter *fp) { - struct work_struct *work; - - if (fp->bpf_func == sk_run_filter) - return; - work = (struct work_struct *)fp->bpf_func; - INIT_WORK(work, jit_free_defer); - schedule_work(work); + if (fp->bpf_func != sk_run_filter) + module_free(NULL, fp->bpf_func); } -- GitLab From fee1b5488d76396d8f95989624d37f436b3fba44 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 16 Jul 2013 10:36:06 +0200 Subject: [PATCH 2861/2900] s390/bpf,jit: use generic jit dumper This is the s390 backend of 79617801 "filter: bpf_jit_comp: refactor and unify BPF JIT image dump output". Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/net/bpf_jit_comp.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index a41f0b15faa1..80828bfee2ec 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -787,15 +787,9 @@ void bpf_jit_compile(struct sk_filter *fp) cjit = jit; } if (bpf_jit_enable > 1) { - pr_err("flen=%d proglen=%lu pass=%d image=%p\n", - fp->len, jit.end - jit.start, pass, jit.start); - if (jit.start) { - printk(KERN_ERR "JIT code:\n"); + bpf_jit_dump(fp->len, jit.end - jit.start, pass, jit.start); + if (jit.start) print_fn_code(jit.start, jit.mid - jit.start); - print_hex_dump(KERN_ERR, "JIT literals:\n", - DUMP_PREFIX_ADDRESS, 16, 1, - jit.mid, jit.end - jit.mid, false); - } } if (jit.start) fp->bpf_func = (void *) jit.start; -- GitLab From aa2d2c73c21f22ce4c643128b671aa7e7bbff54f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 16 Jul 2013 13:25:49 +0200 Subject: [PATCH 2862/2900] s390/bpf,jit: address randomize and write protect jit code This is the s390 variant of 314beb9b "x86: bpf_jit_comp: secure bpf jit against spraying attacks". With this change the whole jit code and literal pool will be write protected after creation. In addition the start address of the jit code won't be always on a page boundary anymore. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/net/bpf_jit_comp.c | 51 ++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 80828bfee2ec..788e22395acd 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -738,8 +739,41 @@ load_abs: if ((int) K < 0) return -1; } +/* + * Note: for security reasons, bpf code will follow a randomly + * sized amount of illegal instructions. + */ +struct bpf_binary_header { + unsigned int pages; + u8 image[]; +}; + +static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize, + u8 **image_ptr) +{ + struct bpf_binary_header *header; + unsigned int sz, hole; + + /* Most BPF filters are really small, but if some of them fill a page, + * allow at least 128 extra bytes for illegal instructions. + */ + sz = round_up(bpfsize + sizeof(*header) + 128, PAGE_SIZE); + header = module_alloc(sz); + if (!header) + return NULL; + memset(header, 0, sz); + header->pages = sz / PAGE_SIZE; + hole = sz - bpfsize + sizeof(*header); + /* Insert random number of illegal instructions before BPF code + * and make sure the first instruction starts at an even address. + */ + *image_ptr = &header->image[(prandom_u32() % hole) & -2]; + return header; +} + void bpf_jit_compile(struct sk_filter *fp) { + struct bpf_binary_header *header = NULL; unsigned long size, prg_len, lit_len; struct bpf_jit jit, cjit; unsigned int *addrs; @@ -775,8 +809,8 @@ void bpf_jit_compile(struct sk_filter *fp) size = prg_len + lit_len; if (size >= BPF_SIZE_MAX) goto out; - jit.start = module_alloc(size); - if (!jit.start) + header = bpf_alloc_binary(size, &jit.start); + if (!header) goto out; jit.prg = jit.mid = jit.start + prg_len; jit.lit = jit.end = jit.start + prg_len + lit_len; @@ -791,14 +825,21 @@ void bpf_jit_compile(struct sk_filter *fp) if (jit.start) print_fn_code(jit.start, jit.mid - jit.start); } - if (jit.start) + if (jit.start) { + set_memory_ro((unsigned long)header, header->pages); fp->bpf_func = (void *) jit.start; + } out: kfree(addrs); } void bpf_jit_free(struct sk_filter *fp) { - if (fp->bpf_func != sk_run_filter) - module_free(NULL, fp->bpf_func); + unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK; + struct bpf_binary_header *header = (void *)addr; + + if (fp->bpf_func == sk_run_filter) + return; + set_memory_rw(addr, header->pages); + module_free(NULL, header); } -- GitLab From c9a7afa380ecaeb0fbeec2e82f86ec5548ad2963 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 17 Jul 2013 14:26:50 +0200 Subject: [PATCH 2863/2900] s390/bpf,jit: add pkt_type support s390 version of 3b58908a "x86: bpf_jit_comp: add pkt_type support". Signed-off-by: Heiko Carstens --- arch/s390/net/bpf_jit_comp.c | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 788e22395acd..d5f10a43a58f 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -222,6 +223,37 @@ static void bpf_jit_epilogue(struct bpf_jit *jit) EMIT2(0x07fe); } +/* Helper to find the offset of pkt_type in sk_buff + * Make sure its still a 3bit field starting at the MSBs within a byte. + */ +#define PKT_TYPE_MAX 0xe0 +static int pkt_type_offset; + +static int __init bpf_pkt_type_offset_init(void) +{ + struct sk_buff skb_probe = { + .pkt_type = ~0, + }; + char *ct = (char *)&skb_probe; + int off; + + pkt_type_offset = -1; + for (off = 0; off < sizeof(struct sk_buff); off++) { + if (!ct[off]) + continue; + if (ct[off] == PKT_TYPE_MAX) + pkt_type_offset = off; + else { + /* Found non matching bit pattern, fix needed. */ + WARN_ON_ONCE(1); + pkt_type_offset = -1; + return -1; + } + } + return 0; +} +device_initcall(bpf_pkt_type_offset_init); + /* * make sure we dont leak kernel information to user */ @@ -721,6 +753,16 @@ load_abs: if ((int) K < 0) EMIT4_DISP(0x88500000, 12); } break; + case BPF_S_ANC_PKTTYPE: + if (pkt_type_offset < 0) + goto out; + /* lhi %r5,0 */ + EMIT4(0xa7580000); + /* ic %r5,(%r2) */ + EMIT4_DISP(0x43502000, pkt_type_offset); + /* srl %r5,5 */ + EMIT4_DISP(0x88500000, 5); + break; case BPF_S_ANC_CPU: /* A = smp_processor_id() */ #ifdef CONFIG_SMP /* l %r5, */ -- GitLab From 5a74953ff56aa870d6913ef4d81934f5c620c59d Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 18 Jul 2013 12:17:57 +0200 Subject: [PATCH 2864/2900] s390/kdump: Disable mmap for s390 The kdump mmap patch series (git commit 83086978c63afd7c73e1c) directly map the PT_LOADs to memory. On s390 this does not work because the copy_from_oldmem() function swaps [0,crashkernel size] with [crashkernel base, crashkernel base+crashkernel size]. The swap int copy_from_oldmem() was done in order correctly implement /dev/oldmem. See: http://marc.info/?l=kexec&m=136940802511603&w=2 Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- fs/proc/vmcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 28503172f2e4..a1a16eb97c7b 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -223,7 +223,7 @@ static inline char *alloc_elfnotes_buf(size_t notes_sz) * regions in the 1st kernel pointed to by PT_LOAD entries) into * virtually contiguous user-space in ELF layout. */ -#ifdef CONFIG_MMU +#if defined(CONFIG_MMU) && !defined(CONFIG_S390) static int mmap_vmcore(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; -- GitLab From 191a2fa0a8d2bbb64c98f9b1976fcb37ee5eae6b Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 18 Jul 2013 12:18:27 +0200 Subject: [PATCH 2865/2900] s390/kdump: Allow copy_oldmem_page() copy to virtual memory The kdump mmap patch series (git commit 83086978c63afd7c73e1c) changed the requirements for copy_oldmem_page(). Now this function is used for copying to virtual memory. So implement vmalloc support for the s390 version of copy_oldmem_page(). Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/crash_dump.c | 51 ++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index f703d91bf720..d8f355657171 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c @@ -21,6 +21,48 @@ #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y)))) + +/* + * Return physical address for virtual address + */ +static inline void *load_real_addr(void *addr) +{ + unsigned long real_addr; + + asm volatile( + " lra %0,0(%1)\n" + " jz 0f\n" + " la %0,0\n" + "0:" + : "=a" (real_addr) : "a" (addr) : "cc"); + return (void *)real_addr; +} + +/* + * Copy up to one page to vmalloc or real memory + */ +static ssize_t copy_page_real(void *buf, void *src, size_t csize) +{ + size_t size; + + if (is_vmalloc_addr(buf)) { + BUG_ON(csize >= PAGE_SIZE); + /* If buf is not page aligned, copy first part */ + size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize); + if (size) { + if (memcpy_real(load_real_addr(buf), src, size)) + return -EFAULT; + buf += size; + src += size; + } + /* Copy second part */ + size = csize - size; + return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0; + } else { + return memcpy_real(buf, src, csize); + } +} + /* * Copy one page from "oldmem" * @@ -32,6 +74,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize, unsigned long offset, int userbuf) { unsigned long src; + int rc; if (!csize) return 0; @@ -43,11 +86,11 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, src < OLDMEM_BASE + OLDMEM_SIZE) src -= OLDMEM_BASE; if (userbuf) - copy_to_user_real((void __force __user *) buf, (void *) src, - csize); + rc = copy_to_user_real((void __force __user *) buf, + (void *) src, csize); else - memcpy_real(buf, (void *) src, csize); - return csize; + rc = copy_page_real(buf, (void *) src, csize); + return (rc == 0) ? csize : rc; } /* -- GitLab From 9657a565a476d517451c10b0bcc106e300785aff Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Tue, 16 Jul 2013 10:07:21 +0800 Subject: [PATCH 2866/2900] ACPI / video: ignore BIOS initial backlight value for Fujitsu E753 The BIOS of FUjitsu E753 reports an incorrect initial backlight value for WIN8 compatible OS, causing backlight to be dark during startup. This change causes the incorrect initial value from BIOS to be ignored. References: https://bugzilla.kernel.org/show_bug.cgi?id=60161 Reported-and-tested-by: Jan Hinnerk Stosch Signed-off-by: Lan Tianyu Cc: 3.7+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/video.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5d7075d25700..e441876f5d5b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -448,6 +448,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "Fujitsu E753", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E753"), + }, + }, { .callback = video_ignore_initial_backlight, .ident = "HP Pavilion dm4", -- GitLab From 87f40dd6ce7042caca0b3b557e8923127f51f902 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Tue, 16 Jul 2013 08:52:30 +0200 Subject: [PATCH 2867/2900] pkt_sched: sch_qfq: remove a source of high packet delay/jitter QFQ+ inherits from QFQ a design choice that may cause a high packet delay/jitter and a severe short-term unfairness. As QFQ, QFQ+ uses a special quantity, the system virtual time, to track the service provided by the ideal system it approximates. When a packet is dequeued, this quantity must be incremented by the size of the packet, divided by the sum of the weights of the aggregates waiting to be served. Tracking this sum correctly is a non-trivial task, because, to preserve tight service guarantees, the decrement of this sum must be delayed in a special way [1]: this sum can be decremented only after that its value would decrease also in the ideal system approximated by QFQ+. For efficiency, QFQ+ keeps track only of the 'instantaneous' weight sum, increased and decreased immediately as the weight of an aggregate changes, and as an aggregate is created or destroyed (which, in its turn, happens as a consequence of some class being created/destroyed/changed). However, to avoid the problems caused to service guarantees by these immediate decreases, QFQ+ increments the system virtual time using the maximum value allowed for the weight sum, 2^10, in place of the dynamic, instantaneous value. The instantaneous value of the weight sum is used only to check whether a request of weight increase or a class creation can be satisfied. Unfortunately, the problems caused by this choice are worse than the temporary degradation of the service guarantees that may occur, when a class is changed or destroyed, if the instantaneous value of the weight sum was used to update the system virtual time. In fact, the fraction of the link bandwidth guaranteed by QFQ+ to each aggregate is equal to the ratio between the weight of the aggregate and the sum of the weights of the competing aggregates. The packet delay guaranteed to the aggregate is instead inversely proportional to the guaranteed bandwidth. By using the maximum possible value, and not the actual value of the weight sum, QFQ+ provides each aggregate with the worst possible service guarantees, and not with service guarantees related to the actual set of competing aggregates. To see the consequences of this fact, consider the following simple example. Suppose that only the following aggregates are backlogged, i.e., that only the classes in the following aggregates have packets to transmit: one aggregate with weight 10, say A, and ten aggregates with weight 1, say B1, B2, ..., B10. In particular, suppose that these aggregates are always backlogged. Given the weight distribution, the smoothest and fairest service order would be: A B1 A B2 A B3 A B4 A B5 A B6 A B7 A B8 A B9 A B10 A B1 A B2 ... QFQ+ would provide exactly this optimal service if it used the actual value for the weight sum instead of the maximum possible value, i.e., 11 instead of 2^10. In contrast, since QFQ+ uses the latter value, it serves aggregates as follows (easy to prove and to reproduce experimentally): A B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 A A A A A A A A A A B1 B2 ... B10 A A ... By replacing 10 with N in the above example, and by increasing N, one can increase at will the maximum packet delay and the jitter experienced by the classes in aggregate A. This patch addresses this issue by just using the above 'instantaneous' value of the weight sum, instead of the maximum possible value, when updating the system virtual time. After the instantaneous weight sum is decreased, QFQ+ may deviate from the ideal service for a time interval in the order of the time to serve one maximum-size packet for each backlogged class. The worst-case extent of the deviation exhibited by QFQ+ during this time interval [1] is basically the same as of the deviation described above (but, without this patch, QFQ+ suffers from such a deviation all the time). Finally, this patch modifies the comment to the function qfq_slot_insert, to make it coherent with the fact that the weight sum used by QFQ+ can now be lower than the maximum possible value. [1] P. Valente, "Extending WF2Q+ to support a dynamic traffic mix", Proceedings of AAA-IDEA'05, June 2005. Signed-off-by: Paolo Valente Signed-off-by: David S. Miller --- net/sched/sch_qfq.c | 85 +++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index a7ab323849b6..8056fb4e618a 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -113,7 +113,6 @@ #define FRAC_BITS 30 /* fixed point arithmetic */ #define ONE_FP (1UL << FRAC_BITS) -#define IWSUM (ONE_FP/QFQ_MAX_WSUM) #define QFQ_MTU_SHIFT 16 /* to support TSO/GSO */ #define QFQ_MIN_LMAX 512 /* see qfq_slot_insert */ @@ -189,6 +188,7 @@ struct qfq_sched { struct qfq_aggregate *in_serv_agg; /* Aggregate being served. */ u32 num_active_agg; /* Num. of active aggregates */ u32 wsum; /* weight sum */ + u32 iwsum; /* inverse weight sum */ unsigned long bitmaps[QFQ_MAX_STATE]; /* Group bitmaps. */ struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */ @@ -314,6 +314,7 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg, q->wsum += (int) agg->class_weight * (new_num_classes - agg->num_classes); + q->iwsum = ONE_FP / q->wsum; agg->num_classes = new_num_classes; } @@ -340,6 +341,10 @@ static void qfq_destroy_agg(struct qfq_sched *q, struct qfq_aggregate *agg) { if (!hlist_unhashed(&agg->nonfull_next)) hlist_del_init(&agg->nonfull_next); + q->wsum -= agg->class_weight; + if (q->wsum != 0) + q->iwsum = ONE_FP / q->wsum; + if (q->in_serv_agg == agg) q->in_serv_agg = qfq_choose_next_agg(q); kfree(agg); @@ -834,38 +839,60 @@ static void qfq_make_eligible(struct qfq_sched *q) } } - /* - * The index of the slot in which the aggregate is to be inserted must - * not be higher than QFQ_MAX_SLOTS-2. There is a '-2' and not a '-1' - * because the start time of the group may be moved backward by one - * slot after the aggregate has been inserted, and this would cause - * non-empty slots to be right-shifted by one position. + * The index of the slot in which the input aggregate agg is to be + * inserted must not be higher than QFQ_MAX_SLOTS-2. There is a '-2' + * and not a '-1' because the start time of the group may be moved + * backward by one slot after the aggregate has been inserted, and + * this would cause non-empty slots to be right-shifted by one + * position. + * + * QFQ+ fully satisfies this bound to the slot index if the parameters + * of the classes are not changed dynamically, and if QFQ+ never + * happens to postpone the service of agg unjustly, i.e., it never + * happens that the aggregate becomes backlogged and eligible, or just + * eligible, while an aggregate with a higher approximated finish time + * is being served. In particular, in this case QFQ+ guarantees that + * the timestamps of agg are low enough that the slot index is never + * higher than 2. Unfortunately, QFQ+ cannot provide the same + * guarantee if it happens to unjustly postpone the service of agg, or + * if the parameters of some class are changed. + * + * As for the first event, i.e., an out-of-order service, the + * upper bound to the slot index guaranteed by QFQ+ grows to + * 2 + + * QFQ_MAX_AGG_CLASSES * ((1<budget -= len; - q->V += (u64)len * IWSUM; + q->V += (u64)len * q->iwsum; pr_debug("qfq dequeue: len %u F %lld now %lld\n", len, (unsigned long long) in_serv_agg->F, (unsigned long long) q->V); -- GitLab From 885291761dba2bfe04df4c0f7bb75e4c920ab82e Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 18 Jul 2013 10:55:15 +0800 Subject: [PATCH 2868/2900] tuntap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS We try to linearize part of the skb when the number of iov is greater than MAX_SKB_FRAGS. This is not enough since each single vector may occupy more than one pages, so zerocopy_sg_fromiovec() may still fail and may break the guest network. Solve this problem by calculate the pages needed for iov before trying to do zerocopy and switch to use copy instead of zerocopy if it needs more than MAX_SKB_FRAGS. This is done through introducing a new helper to count the pages for iov, and call uarg->callback() manually when switching from zerocopy to copy to notify vhost. We can do further optimization on top. The bug were introduced from commit 0690899b4d4501b3505be069b9a687e68ccbe15b (tun: experimental zero copy tx support) Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/tun.c | 62 +++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5cdcf92eb310..db690a372260 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1035,6 +1035,29 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, return 0; } +static unsigned long iov_pages(const struct iovec *iv, int offset, + unsigned long nr_segs) +{ + unsigned long seg, base; + int pages = 0, len, size; + + while (nr_segs && (offset >= iv->iov_len)) { + offset -= iv->iov_len; + ++iv; + --nr_segs; + } + + for (seg = 0; seg < nr_segs; seg++) { + base = (unsigned long)iv[seg].iov_base + offset; + len = iv[seg].iov_len - offset; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + pages += size; + offset = 0; + } + + return pages; +} + /* Get packet from user space buffer */ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, void *msg_control, const struct iovec *iv, @@ -1082,32 +1105,18 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, return -EINVAL; } - if (msg_control) - zerocopy = true; - - if (zerocopy) { - /* Userspace may produce vectors with count greater than - * MAX_SKB_FRAGS, so we need to linearize parts of the skb - * to let the rest of data to be fit in the frags. - */ - if (count > MAX_SKB_FRAGS) { - copylen = iov_length(iv, count - MAX_SKB_FRAGS); - if (copylen < offset) - copylen = 0; - else - copylen -= offset; - } else - copylen = 0; - /* There are 256 bytes to be copied in skb, so there is enough - * room for skb expand head in case it is used. + if (msg_control) { + /* There are 256 bytes to be copied in skb, so there is + * enough room for skb expand head in case it is used. * The rest of the buffer is mapped from userspace. */ - if (copylen < gso.hdr_len) - copylen = gso.hdr_len; - if (!copylen) - copylen = GOODCOPY_LEN; + copylen = gso.hdr_len ? gso.hdr_len : GOODCOPY_LEN; linear = copylen; - } else { + if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { copylen = len; linear = gso.hdr_len; } @@ -1121,8 +1130,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (zerocopy) err = zerocopy_sg_from_iovec(skb, iv, offset, count); - else + else { err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); + if (!err && msg_control) { + struct ubuf_info *uarg = msg_control; + uarg->callback(uarg, false); + } + } if (err) { tun->dev->stats.rx_dropped++; -- GitLab From ece793fcfc417b3925844be88a6a6dc82ae8f7c6 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 18 Jul 2013 10:55:16 +0800 Subject: [PATCH 2869/2900] macvtap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS We try to linearize part of the skb when the number of iov is greater than MAX_SKB_FRAGS. This is not enough since each single vector may occupy more than one pages, so zerocopy_sg_fromiovec() may still fail and may break the guest network. Solve this problem by calculate the pages needed for iov before trying to do zerocopy and switch to use copy instead of zerocopy if it needs more than MAX_SKB_FRAGS. This is done through introducing a new helper to count the pages for iov, and call uarg->callback() manually when switching from zerocopy to copy to notify vhost. We can do further optimization on top. This bug were introduced from b92946e2919134ebe2a4083e4302236295ea2a73 (macvtap: zerocopy: validate vectors before building skb). Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index a7c5654a2e5c..a98fb0ed6aef 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -698,6 +698,28 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, return 0; } +static unsigned long iov_pages(const struct iovec *iv, int offset, + unsigned long nr_segs) +{ + unsigned long seg, base; + int pages = 0, len, size; + + while (nr_segs && (offset >= iv->iov_len)) { + offset -= iv->iov_len; + ++iv; + --nr_segs; + } + + for (seg = 0; seg < nr_segs; seg++) { + base = (unsigned long)iv[seg].iov_base + offset; + len = iv[seg].iov_len - offset; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + pages += size; + offset = 0; + } + + return pages; +} /* Get packet from user space buffer */ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, @@ -744,31 +766,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (unlikely(count > UIO_MAXIOV)) goto err; - if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) - zerocopy = true; - - if (zerocopy) { - /* Userspace may produce vectors with count greater than - * MAX_SKB_FRAGS, so we need to linearize parts of the skb - * to let the rest of data to be fit in the frags. - */ - if (count > MAX_SKB_FRAGS) { - copylen = iov_length(iv, count - MAX_SKB_FRAGS); - if (copylen < vnet_hdr_len) - copylen = 0; - else - copylen -= vnet_hdr_len; - } - /* There are 256 bytes to be copied in skb, so there is enough - * room for skb expand head in case it is used. - * The rest buffer is mapped from userspace. - */ - if (copylen < vnet_hdr.hdr_len) - copylen = vnet_hdr.hdr_len; - if (!copylen) - copylen = GOODCOPY_LEN; + if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { + copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; linear = copylen; - } else { + if (iov_pages(iv, vnet_hdr_len + copylen, count) + <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { copylen = len; linear = vnet_hdr.hdr_len; } @@ -780,9 +786,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (zerocopy) err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); - else + else { err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len); + if (!err && m && m->msg_control) { + struct ubuf_info *uarg = m->msg_control; + uarg->callback(uarg, false); + } + } + if (err) goto err_kfree; -- GitLab From d4b812dea4a236f729526facf97df1a9d18e191c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Jul 2013 07:19:26 -0700 Subject: [PATCH 2870/2900] vlan: mask vlan prio bits In commit 48cc32d38a52d0b68f91a171a8d00531edc6a46e ("vlan: don't deliver frames for unknown vlans to protocols") Florian made sure we set pkt_type to PACKET_OTHERHOST if the vlan id is set and we could find a vlan device for this particular id. But we also have a problem if prio bits are set. Steinar reported an issue on a router receiving IPv6 frames with a vlan tag of 4000 (id 0, prio 2), and tunneled into a sit device, because skb->vlan_tci is set. Forwarded frame is completely corrupted : We can see (8100:4000) being inserted in the middle of IPv6 source address : 16:48:00.780413 IP6 2001:16d8:8100:4000:ee1c:0:9d9:bc87 > 9f94:4d95:2001:67c:29f4::: ICMP6, unknown icmp6 type (0), length 64 0x0000: 0000 0029 8000 c7c3 7103 0001 a0ae e651 0x0010: 0000 0000 ccce 0b00 0000 0000 1011 1213 0x0020: 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 0x0030: 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233 It seems we are not really ready to properly cope with this right now. We can probably do better in future kernels : vlan_get_ingress_priority() should be a netdev property instead of a per vlan_dev one. For stable kernels, lets clear vlan_tci to fix the bugs. Reported-by: Steinar H. Gunderson Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/if_vlan.h | 3 +-- net/8021q/vlan_core.c | 2 +- net/core/dev.c | 11 +++++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index cdcbafa9b39a..715c343f7c00 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -79,9 +79,8 @@ static inline int is_vlan_dev(struct net_device *dev) } #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) -#define vlan_tx_nonzero_tag_present(__skb) \ - (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK)) #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) +#define vlan_tx_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 8a15eaadc4bd..4a78c4de9f20 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -9,7 +9,7 @@ bool vlan_do_receive(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; __be16 vlan_proto = skb->vlan_proto; - u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; + u16 vlan_id = vlan_tx_tag_get_id(skb); struct net_device *vlan_dev; struct vlan_pcpu_stats *rx_stats; diff --git a/net/core/dev.c b/net/core/dev.c index a3d8d44cb7f4..26755dd40daa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3580,8 +3580,15 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) } } - if (vlan_tx_nonzero_tag_present(skb)) - skb->pkt_type = PACKET_OTHERHOST; + if (unlikely(vlan_tx_tag_present(skb))) { + if (vlan_tx_tag_get_id(skb)) + skb->pkt_type = PACKET_OTHERHOST; + /* Note: we might in the future use prio bits + * and set skb->priority like in vlan_do_receive() + * For the time being, just ignore Priority Code Point + */ + skb->vlan_tci = 0; + } /* deliver only exact match when indicated */ null_or_dev = deliver_exact ? skb->dev : NULL; -- GitLab From 3e3aac497513c669e1c62c71e1d552ea85c1d974 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 18 Jul 2013 09:35:10 -0700 Subject: [PATCH 2871/2900] vlan: fix a race in egress prio management egress_priority_map[] hash table updates are protected by rtnl, and we never remove elements until device is dismantled. We have to make sure that before inserting an new element in hash table, all its fields are committed to memory or else another cpu could find corrupt values and crash. Signed-off-by: Eric Dumazet Cc: Patrick McHardy Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 3a8c8fd63c88..1cd3d2a406f5 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -73,6 +73,8 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) { struct vlan_priority_tci_mapping *mp; + smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */ + mp = vlan_dev_priv(dev)->egress_priority_map[(skb->priority & 0xF)]; while (mp) { if (mp->priority == skb->priority) { @@ -249,6 +251,11 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, np->next = mp; np->priority = skb_prio; np->vlan_qos = vlan_qos; + /* Before inserting this element in hash table, make sure all its fields + * are committed to memory. + * coupled with smp_rmb() in vlan_dev_get_egress_qos_mask() + */ + smp_wmb(); vlan->egress_priority_map[skb_prio & 0xF] = np; if (vlan_qos) vlan->nr_egress_mappings++; -- GitLab From 9da3545d827cdb9163697a1dc4471fbb5540e85f Mon Sep 17 00:00:00 2001 From: Ingo Tuchscherer Date: Thu, 18 Jul 2013 16:28:26 +0200 Subject: [PATCH 2872/2900] s390/zcrypt: Alias for new zcrypt device driver base module The zcrypt device driver has been split into base/bus module, api-module, card modules and message type modules. The base module has been renamed from z90crypt to ap. A module alias (with the well-known z90crypt identifier) will be introduced that enable users to use their existing way to load the zcrypt device driver. Signed-off-by: Ingo Tuchscherer Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index f446a7705c3b..d4174b82a1a9 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -71,6 +71,7 @@ MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ "Copyright IBM Corp. 2006, 2012"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("z90crypt"); /* * Module parameter -- GitLab From 976f39b139cdd06a88a5aadd8202b0c30cac9cda Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 17 Jul 2013 17:56:31 +0000 Subject: [PATCH 2873/2900] MIPS: BMIPS: Fix thinko to release slave TP from reset Commit 4df715aa ["MIPS: BMIPS: support booting from physical CPU other than 0"] introduced a thinko which will prevents slave CPUs from being released from reset on systems where we boot from TP0. The problem is that we are checking whether the slave CPU logical CPU map is 0, which is never true for systems booting from TP0, so we do not release the slave TP from reset and we are just stuck. Fix this by properly checking that the CPU we intend to boot really is the physical slave CPU (logical and physical value being 1). Signed-off-by: Florian Fainelli Cc: linux-mips@linux-mips.org Cc: blogic@openwrt.org Cc: jogo@openwrt.org Cc: cernekee@gmail.com Cc: Florian Fainelli Patchwork: https://patchwork.linux-mips.org/patch/5598/ Signed-off-by: Ralf Baechle --- arch/mips/kernel/smp-bmips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index aea6c0885838..67445374014f 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -173,7 +173,7 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle) else { #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380) /* Reset slave TP1 if booting from TP0 */ - if (cpu_logical_map(cpu) == 0) + if (cpu_logical_map(cpu) == 1) set_c0_brcm_cmt_ctrl(0x01); #elif defined(CONFIG_CPU_BMIPS5000) if (cpu & 0x01) -- GitLab From afc813ae6d01eb4bb03fe67ed74c76608e3db089 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Thu, 18 Jul 2013 09:45:47 +0000 Subject: [PATCH 2874/2900] MIPS: tlbex: Fix typo in r3000 tlb store handler commit 6ba045f (MIPS: Move generated code to .text for microMIPS) causes a panic at boot. The handler builder should test against handle_tlbs_end, not handle_tlbs. Signed-off-by: Tony Wu Acked-by: Jayachandran C. Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5600/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 9ab0f907a52c..605b6fc13697 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1803,7 +1803,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void) uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff); uasm_i_nop(&p); - if (p >= handle_tlbs) + if (p >= handle_tlbs_end) panic("TLB store handler fastpath space exceeded"); uasm_resolve_relocs(relocs, labels); -- GitLab From 35ac7840bca23a0fcfb53cc433ae1fd6dc6d35c0 Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Wed, 17 Jul 2013 10:27:25 +0000 Subject: [PATCH 2875/2900] MIPS: Netlogic: Fix USB block's coherent DMA mask The on-chip USB controller on Netlogic XLP does not suppport DMA beyond 32-bit physical address. Set the coherent_dma_mask of the USB in its PCI fixup to support this. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C. Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5596/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/xlp/usb-init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c index 9c401dd78337..ef3897ef0dc7 100644 --- a/arch/mips/netlogic/xlp/usb-init.c +++ b/arch/mips/netlogic/xlp/usb-init.c @@ -119,7 +119,7 @@ static u64 xlp_usb_dmamask = ~(u32)0; static void nlm_usb_fixup_final(struct pci_dev *dev) { dev->dev.dma_mask = &xlp_usb_dmamask; - dev->dev.coherent_dma_mask = DMA_BIT_MASK(64); + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); switch (dev->devfn) { case 0x10: dev->irq = PIC_EHCI_0_IRQ; -- GitLab From 628f0650ea65ef2ec0a2bde141c271dea1d18904 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Wed, 17 Jul 2013 10:27:26 +0000 Subject: [PATCH 2876/2900] MIPS: Netlogic: Add XLP PIC irqdomain Add a legacy irq domain for the XLP PIC interrupts. This will be used when interrupts are assigned from the device tree. This change is required after commit c5cdc67 "irqdomain: Remove temporary MIPS workaround code". Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Cc: Jayachandran C Patchwork: https://patchwork.linux-mips.org/patch/5597/ Signed-off-by: Ralf Baechle --- arch/mips/netlogic/common/irq.c | 68 +++++++++++++++++++++++++----- arch/mips/netlogic/dts/xlp_evp.dts | 3 +- arch/mips/netlogic/dts/xlp_svp.dts | 3 +- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 73facb2b33bb..1c7e3a1b81ab 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -40,6 +40,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -223,17 +227,6 @@ static void nlm_init_node_irqs(int node) nodep->irqmask = irqmask; } -void __init arch_init_irq(void) -{ - /* Initialize the irq descriptors */ - nlm_init_percpu_irqs(); - nlm_init_node_irqs(0); - write_c0_eimr(nlm_current_node()->irqmask); -#if defined(CONFIG_CPU_XLR) - nlm_setup_fmn_irq(); -#endif -} - void nlm_smp_irq_init(int hwcpuid) { int node, cpu; @@ -266,3 +259,56 @@ asmlinkage void plat_irq_dispatch(void) /* top level irq handling */ do_IRQ(nlm_irq_to_xirq(node, i)); } + +#ifdef CONFIG_OF +static struct irq_domain *xlp_pic_domain; + +static const struct irq_domain_ops xlp_pic_irq_domain_ops = { + .xlate = irq_domain_xlate_onetwocell, +}; + +static int __init xlp_of_pic_init(struct device_node *node, + struct device_node *parent) +{ + const int n_picirqs = PIC_IRT_LAST_IRQ - PIC_IRQ_BASE + 1; + struct resource res; + int socid, ret; + + /* we need a hack to get the PIC's SoC chip id */ + ret = of_address_to_resource(node, 0, &res); + if (ret < 0) { + pr_err("PIC %s: reg property not found!\n", node->name); + return -EINVAL; + } + socid = (res.start >> 18) & 0x3; + xlp_pic_domain = irq_domain_add_legacy(node, n_picirqs, + nlm_irq_to_xirq(socid, PIC_IRQ_BASE), PIC_IRQ_BASE, + &xlp_pic_irq_domain_ops, NULL); + if (xlp_pic_domain == NULL) { + pr_err("PIC %s: Creating legacy domain failed!\n", node->name); + return -EINVAL; + } + pr_info("Node %d: IRQ domain created for PIC@%pa\n", socid, + &res.start); + return 0; +} + +static struct of_device_id __initdata xlp_pic_irq_ids[] = { + { .compatible = "netlogic,xlp-pic", .data = xlp_of_pic_init }, + {}, +}; +#endif + +void __init arch_init_irq(void) +{ + /* Initialize the irq descriptors */ + nlm_init_percpu_irqs(); + nlm_init_node_irqs(0); + write_c0_eimr(nlm_current_node()->irqmask); +#if defined(CONFIG_CPU_XLR) + nlm_setup_fmn_irq(); +#endif +#if defined(CONFIG_OF) + of_irq_init(xlp_pic_irq_ids); +#endif +} diff --git a/arch/mips/netlogic/dts/xlp_evp.dts b/arch/mips/netlogic/dts/xlp_evp.dts index e14f42308064..06407033678e 100644 --- a/arch/mips/netlogic/dts/xlp_evp.dts +++ b/arch/mips/netlogic/dts/xlp_evp.dts @@ -76,10 +76,11 @@ }; }; pic: pic@4000 { - interrupt-controller; + compatible = "netlogic,xlp-pic"; #address-cells = <0>; #interrupt-cells = <1>; reg = <0 0x4000 0x200>; + interrupt-controller; }; nor_flash@1,0 { diff --git a/arch/mips/netlogic/dts/xlp_svp.dts b/arch/mips/netlogic/dts/xlp_svp.dts index 8af4bdbe5d99..9c5db102df53 100644 --- a/arch/mips/netlogic/dts/xlp_svp.dts +++ b/arch/mips/netlogic/dts/xlp_svp.dts @@ -76,10 +76,11 @@ }; }; pic: pic@4000 { - interrupt-controller; + compatible = "netlogic,xlp-pic"; #address-cells = <0>; #interrupt-cells = <1>; reg = <0 0x4000 0x200>; + interrupt-controller; }; nor_flash@1,0 { -- GitLab From 38a997a70e6cf0ee9fc26de146601ba10fa552a4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 15 Jul 2013 07:21:57 +0000 Subject: [PATCH 2877/2900] MIPS: tlbex: fix broken build in v3.11-rc1 Commit 6ba045f9fbdafb48da42aa8576ea7a3980443136 (MIPS: Move generated code to .text for microMIPS) deleted tlbmiss_handler_setup_pgd_array, but some references were not converted. Fix that to enable building a MIPS kernel. Signed-off-by: Aaro Koskinen Acked-by: Jayachandran C. Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5589/ Signed-off-by: Ralf Baechle --- arch/mips/mm/tlbex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 605b6fc13697..523775d7a20e 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1466,7 +1466,7 @@ static void __cpuinit build_r4000_setup_pgd(void) { const int a0 = 4; const int a1 = 5; - u32 *p = tlbmiss_handler_setup_pgd_array; + u32 *p = tlbmiss_handler_setup_pgd; const int tlbmiss_handler_setup_pgd_size = tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd; struct uasm_label *l = labels; -- GitLab From f2a5b1d78c076c525d20176d227faf2e6a20257c Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 12 Jul 2013 10:26:11 +0000 Subject: [PATCH 2878/2900] MIPS: KVM: Mark KVM_GUEST (T&E KVM) as BROKEN_ON_SMP Make KVM_GUEST depend on BROKEN_ON_SMP so that it cannot be enabled with SMP. SMP kernels use ll/sc instructions for an atomic section in the tlb fill handler, with a tlbp instruction contained in the middle. This cannot be emulated with trap & emulate KVM because the tlbp instruction traps and the eret to return to the guest code clears the LLbit which makes the sc instruction always fail. Signed-off-by: James Hogan Cc: Sanjay Lal Cc: Ralf Baechle Cc: David Daney Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/5588/ Signed-off-by: Ralf Baechle --- arch/mips/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4758a8fd3e99..c3abed332301 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1702,6 +1702,7 @@ endchoice config KVM_GUEST bool "KVM Guest Kernel" + depends on BROKEN_ON_SMP help Select this option if building a guest kernel for KVM (Trap & Emulate) mode -- GitLab From 3179ce7254ffa43f3ba4409f31a954ecc4a8d408 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 11 May 2013 15:35:32 +0200 Subject: [PATCH 2879/2900] um: Fix return value of strnlen_user() In case of an error it must not return -EFAULT. Return 0 like all other archs do. Reported-by: toralf.foerster@gmx.de Signed-off-by: Richard Weinberger --- arch/um/kernel/skas/uaccess.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 1d3e0c17340b..4ffb644d6c07 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -254,6 +254,6 @@ int strnlen_user(const void __user *str, int len) n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); if (n == 0) return count + 1; - return -EFAULT; + return 0; } EXPORT_SYMBOL(strnlen_user); -- GitLab From dee20035b42d569984d2c16041b51e4d75e233b5 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 12 May 2013 23:26:03 +0200 Subject: [PATCH 2880/2900] um: Mark stub pages mapping with VM_PFNMAP Ensure that a process cannot destroy his stub pages with using MADV_DONTNEED and friends. Reported-by: toralf.foerster@gmx.de Signed-off-by: Richard Weinberger --- arch/um/kernel/skas/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index ff03067a3b14..007d5503f49b 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -123,7 +123,7 @@ void uml_setup_stubs(struct mm_struct *mm) /* dup_mmap already holds mmap_sem */ err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START, VM_READ | VM_MAYREAD | VM_EXEC | - VM_MAYEXEC | VM_DONTCOPY, + VM_MAYEXEC | VM_DONTCOPY | VM_PFNMAP, mm->context.stub_pages); if (err) { printk(KERN_ERR "install_special_mapping returned %d\n", err); -- GitLab From 0974a9cadc7886f7baaa458bb0c89f5c5f9d458e Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 17 May 2013 14:21:01 +0200 Subject: [PATCH 2881/2900] um: Fix wait_stub_done() error handling If we die within a stub handler we only way to reliable kill the (obviously) dying uml guest process is killing it's host twin on the host side. Signed-off-by: Richard Weinberger --- arch/um/os-Linux/skas/process.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 4625949bf1e4..441e4ba074f4 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -54,7 +54,7 @@ static int ptrace_dump_regs(int pid) void wait_stub_done(int pid) { - int n, status, err; + int n, status, err, bad_stop = 0; while (1) { CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL)); @@ -74,6 +74,8 @@ void wait_stub_done(int pid) if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0) return; + else + bad_stop = 1; bad_wait: err = ptrace_dump_regs(pid); @@ -83,7 +85,10 @@ void wait_stub_done(int pid) printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, " "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status); - fatal_sigsegv(); + if (bad_stop) + kill(pid, SIGKILL); + else + fatal_sigsegv(); } extern unsigned long current_stub_stack(void); -- GitLab From 7473534130c3156d199512c99ff1b796233e8547 Mon Sep 17 00:00:00 2001 From: Tristan Schmelcher Date: Mon, 8 Jul 2013 16:19:49 -0400 Subject: [PATCH 2882/2900] uml: Fix which_tmpdir failure when /dev/shm is a symlink, and in other edge cases which_tmpdir did the wrong thing if /dev/shm was a symlink (e.g., to /run/shm), if there were multiple mounts on top of each other, if the mount(s) were obscured by a later mount, or if /dev/shm was a prefix of another mount point. This fixes these cases. Applies to 3.9.6. Signed-off-by: Tristan Schmelcher Signed-off-by: Richard Weinberger --- arch/um/os-Linux/mem.c | 230 +++++++++++++++++++++++++++++++++-------- 1 file changed, 189 insertions(+), 41 deletions(-) diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index ba4398056fe9..3c4af77e51a2 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -52,6 +52,25 @@ static void __init find_tempdir(void) strcat(tempdir, "/"); } +/* + * Remove bytes from the front of the buffer and refill it so that if there's a + * partial string that we care about, it will be completed, and we can recognize + * it. + */ +static int pop(int fd, char *buf, size_t size, size_t npop) +{ + ssize_t n; + size_t len = strlen(&buf[npop]); + + memmove(buf, &buf[npop], len + 1); + n = read(fd, &buf[len], size - len - 1); + if (n < 0) + return -errno; + + buf[len + n] = '\0'; + return 1; +} + /* * This will return 1, with the first character in buf being the * character following the next instance of c in the file. This will @@ -61,7 +80,6 @@ static void __init find_tempdir(void) static int next(int fd, char *buf, size_t size, char c) { ssize_t n; - size_t len; char *ptr; while ((ptr = strchr(buf, c)) == NULL) { @@ -74,20 +92,129 @@ static int next(int fd, char *buf, size_t size, char c) buf[n] = '\0'; } - ptr++; - len = strlen(ptr); - memmove(buf, ptr, len + 1); + return pop(fd, buf, size, ptr - buf + 1); +} + +/* + * Decode an octal-escaped and space-terminated path of the form used by + * /proc/mounts. May be used to decode a path in-place. "out" must be at least + * as large as the input. The output is always null-terminated. "len" gets the + * length of the output, excluding the trailing null. Returns 0 if a full path + * was successfully decoded, otherwise an error. + */ +static int decode_path(const char *in, char *out, size_t *len) +{ + char *first = out; + int c; + int i; + int ret = -EINVAL; + while (1) { + switch (*in) { + case '\0': + goto out; + + case ' ': + ret = 0; + goto out; + + case '\\': + in++; + c = 0; + for (i = 0; i < 3; i++) { + if (*in < '0' || *in > '7') + goto out; + c = (c << 3) | (*in++ - '0'); + } + *(unsigned char *)out++ = (unsigned char) c; + break; + + default: + *out++ = *in++; + break; + } + } + +out: + *out = '\0'; + *len = out - first; + return ret; +} + +/* + * Computes the length of s when encoded with three-digit octal escape sequences + * for the characters in chars. + */ +static size_t octal_encoded_length(const char *s, const char *chars) +{ + size_t len = strlen(s); + while ((s = strpbrk(s, chars)) != NULL) { + len += 3; + s++; + } + + return len; +} + +enum { + OUTCOME_NOTHING_MOUNTED, + OUTCOME_TMPFS_MOUNT, + OUTCOME_NON_TMPFS_MOUNT, +}; + +/* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */ +static int read_mount(int fd, char *buf, size_t bufsize, const char *path, + int *outcome) +{ + int found; + int match; + char *space; + size_t len; + + enum { + MATCH_NONE, + MATCH_EXACT, + MATCH_PARENT, + }; + + found = next(fd, buf, bufsize, ' '); + if (found != 1) + return found; /* - * Refill the buffer so that if there's a partial string that we care - * about, it will be completed, and we can recognize it. + * If there's no following space in the buffer, then this path is + * truncated, so it can't be the one we're looking for. */ - n = read(fd, &buf[len], size - len - 1); - if (n < 0) - return -errno; + space = strchr(buf, ' '); + if (space) { + match = MATCH_NONE; + if (!decode_path(buf, buf, &len)) { + if (!strcmp(buf, path)) + match = MATCH_EXACT; + else if (!strncmp(buf, path, len) + && (path[len] == '/' || !strcmp(buf, "/"))) + match = MATCH_PARENT; + } + + found = pop(fd, buf, bufsize, space - buf + 1); + if (found != 1) + return found; + + switch (match) { + case MATCH_EXACT: + if (!strncmp(buf, "tmpfs", strlen("tmpfs"))) + *outcome = OUTCOME_TMPFS_MOUNT; + else + *outcome = OUTCOME_NON_TMPFS_MOUNT; + break; - buf[len + n] = '\0'; - return 1; + case MATCH_PARENT: + /* This mount obscures any previous ones. */ + *outcome = OUTCOME_NOTHING_MOUNTED; + break; + } + } + + return next(fd, buf, bufsize, '\n'); } /* which_tmpdir is called only during early boot */ @@ -106,8 +233,12 @@ static int checked_tmpdir = 0; */ static void which_tmpdir(void) { - int fd, found; - char buf[128] = { '\0' }; + int fd; + int found; + int outcome; + char *path; + char *buf; + size_t bufsize; if (checked_tmpdir) return; @@ -116,49 +247,66 @@ static void which_tmpdir(void) printf("Checking for tmpfs mount on /dev/shm..."); + path = realpath("/dev/shm", NULL); + if (!path) { + printf("failed to check real path, errno = %d\n", errno); + return; + } + printf("%s...", path); + + /* + * The buffer needs to be able to fit the full octal-escaped path, a + * space, and a trailing null in order to successfully decode it. + */ + bufsize = octal_encoded_length(path, " \t\n\\") + 2; + + if (bufsize < 128) + bufsize = 128; + + buf = malloc(bufsize); + if (!buf) { + printf("malloc failed, errno = %d\n", errno); + goto out; + } + buf[0] = '\0'; + fd = open("/proc/mounts", O_RDONLY); if (fd < 0) { printf("failed to open /proc/mounts, errno = %d\n", errno); - return; + goto out1; } + outcome = OUTCOME_NOTHING_MOUNTED; while (1) { - found = next(fd, buf, ARRAY_SIZE(buf), ' '); - if (found != 1) - break; - - if (!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) - goto found; - - found = next(fd, buf, ARRAY_SIZE(buf), '\n'); + found = read_mount(fd, buf, bufsize, path, &outcome); if (found != 1) break; } -err: - if (found == 0) - printf("nothing mounted on /dev/shm\n"); - else if (found < 0) + if (found < 0) { printf("read returned errno %d\n", -found); + } else { + switch (outcome) { + case OUTCOME_TMPFS_MOUNT: + printf("OK\n"); + default_tmpdir = "/dev/shm"; + break; -out: - close(fd); - - return; - -found: - found = next(fd, buf, ARRAY_SIZE(buf), ' '); - if (found != 1) - goto err; + case OUTCOME_NON_TMPFS_MOUNT: + printf("not tmpfs\n"); + break; - if (strncmp(buf, "tmpfs", strlen("tmpfs"))) { - printf("not tmpfs\n"); - goto out; + default: + printf("nothing mounted on /dev/shm\n"); + break; + } } - printf("OK\n"); - default_tmpdir = "/dev/shm"; - goto out; + close(fd); +out1: + free(buf); +out: + free(path); } static int __init make_tempfile(const char *template, char **out_tempname, -- GitLab From ab2bb148c5932712d2717a7f3a452846f07a660a Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Thu, 11 Jul 2013 21:08:09 +0000 Subject: [PATCH 2883/2900] MIPS: Octeon: Fix DT pruning bug with pip ports During the pruning of the device tree octeon_fdt_pip_iface() is called for each PIP interface and every port up to the port count is removed from the device tree. However, the count was set to the return value of cvmx_helper_interface_enumerate() which doesn't actually return the count but just returns zero on success. This effectively removed *all* ports from the tree. Use cvmx_helper_ports_on_interface() instead to fix this. This successfully restores the 3 ports of my ERLite-3 and fixes the "kernel assigns random MAC addresses" issue. Signed-off-by: Faidon Liambotis Tested-by: Aaro Koskinen Acked-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5587/ Signed-off-by: Ralf Baechle --- arch/mips/cavium-octeon/octeon-platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index 7b746e7bf7a1..1830874ff1e2 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -334,9 +334,10 @@ static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) char name_buffer[20]; int iface; int p; - int count; + int count = 0; - count = cvmx_helper_interface_enumerate(idx); + if (cvmx_helper_interface_enumerate(idx) == 0) + count = cvmx_helper_ports_on_interface(idx); snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx); iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer); -- GitLab From 9a8c1359571c5d5e2fbc43cf457a6486b70a70cb Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 19 Jul 2013 11:31:36 +0200 Subject: [PATCH 2884/2900] um: siginfo cleanup Currently we use both struct siginfo and siginfo_t. Let's use struct siginfo internally to avoid ongoing compiler warning. We are allowed to do so because struct siginfo and siginfo_t are equivalent. Signed-off-by: Richard Weinberger --- arch/um/include/shared/frame_kern.h | 8 ++++---- arch/um/kernel/signal.c | 4 ++-- arch/um/os-Linux/signal.c | 8 ++++---- arch/um/os-Linux/skas/process.c | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/um/include/shared/frame_kern.h b/arch/um/include/shared/frame_kern.h index e584e40ee832..f2ca5702a4e2 100644 --- a/arch/um/include/shared/frame_kern.h +++ b/arch/um/include/shared/frame_kern.h @@ -6,13 +6,13 @@ #ifndef __FRAME_KERN_H_ #define __FRAME_KERN_H_ -extern int setup_signal_stack_sc(unsigned long stack_top, int sig, +extern int setup_signal_stack_sc(unsigned long stack_top, int sig, struct k_sigaction *ka, - struct pt_regs *regs, + struct pt_regs *regs, sigset_t *mask); -extern int setup_signal_stack_si(unsigned long stack_top, int sig, +extern int setup_signal_stack_si(unsigned long stack_top, int sig, struct k_sigaction *ka, - struct pt_regs *regs, siginfo_t *info, + struct pt_regs *regs, struct siginfo *info, sigset_t *mask); #endif diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 3e831b3fd07b..f57e02e7910f 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -19,7 +19,7 @@ EXPORT_SYMBOL(unblock_signals); * OK, we're invoking a handler */ static void handle_signal(struct pt_regs *regs, unsigned long signr, - struct k_sigaction *ka, siginfo_t *info) + struct k_sigaction *ka, struct siginfo *info) { sigset_t *oldset = sigmask_to_save(); int singlestep = 0; @@ -71,7 +71,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, static int kern_do_signal(struct pt_regs *regs) { struct k_sigaction ka_copy; - siginfo_t info; + struct siginfo info; int sig, handled_sig = 0; while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 9d9f1b4bf826..905924b773d3 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -25,7 +25,7 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = { [SIGIO] = sigio_handler, [SIGVTALRM] = timer_handler }; -static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) +static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -61,7 +61,7 @@ static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) +void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) { int enabled; @@ -120,7 +120,7 @@ void set_sigstack(void *sig_stack, int size) panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { +static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = { [SIGSEGV] = sig_handler, [SIGBUS] = sig_handler, [SIGILL] = sig_handler, @@ -162,7 +162,7 @@ static void hard_handler(int sig, siginfo_t *si, void *p) while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, si, mc); + (*handlers[sig])(sig, (struct siginfo *)si, mc); } /* diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 441e4ba074f4..d531879a4617 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -414,7 +414,7 @@ void userspace(struct uml_pt_regs *regs) if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); - ptrace(PTRACE_GETSIGINFO, pid, 0, &si); + ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si); switch (sig) { case SIGSEGV: @@ -422,7 +422,7 @@ void userspace(struct uml_pt_regs *regs) !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, &si, + (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, regs); } else handle_segv(pid, regs); @@ -431,14 +431,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, &si, regs); + relay_signal(SIGTRAP, (struct siginfo *)&si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, &si, regs); + (*sig_info[sig])(sig, (struct siginfo *)&si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -452,7 +452,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, &si, regs); + (*sig_info[sig])(sig, (struct siginfo *)&si, regs); unblock_signals(); break; default: -- GitLab From 9e82d450531c79b18ab18c9b9645cdd9db31ee98 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 19 Jul 2013 11:35:32 +0200 Subject: [PATCH 2885/2900] um: remove dead code "me" is not used. Signed-off-by: Richard Weinberger --- arch/x86/um/signal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c index ae7319db18ee..5e04a1c899fa 100644 --- a/arch/x86/um/signal.c +++ b/arch/x86/um/signal.c @@ -508,7 +508,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, { struct rt_sigframe __user *frame; int err = 0; - struct task_struct *me = current; frame = (struct rt_sigframe __user *) round_down(stack_top - sizeof(struct rt_sigframe), 16); -- GitLab From f1b7001903dd5a80bdc9f777d2a741ccfd22ed4e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 11 Jun 2013 09:02:33 +0000 Subject: [PATCH 2886/2900] MIPS: kvm: Kconfig: Drop HAVE_KVM dependency from VIRTUALIZATION Virtualization does not always need KVM capabilities so drop the dependency. The KVM symbol already depends on HAVE_KVM. Fixes the following problem on a randconfig: warning: (REMOTEPROC && RPMSG) selects VIRTUALIZATION which has unmet direct dependencies (HAVE_KVM) warning: (REMOTEPROC && RPMSG) selects VIRTUALIZATION which has unmet direct dependencies (HAVE_KVM) Signed-off-by: Markos Chandras Acked-by: Steven J. Hill Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5443/ Signed-off-by: Ralf Baechle --- arch/mips/kvm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig index 2c15590e55f7..30e334e823bd 100644 --- a/arch/mips/kvm/Kconfig +++ b/arch/mips/kvm/Kconfig @@ -5,7 +5,6 @@ source "virt/kvm/Kconfig" menuconfig VIRTUALIZATION bool "Virtualization" - depends on HAVE_KVM ---help--- Say Y here to get to see options for using your Linux host to run other operating systems inside virtual machines (guests). -- GitLab From 53ae3acd4390ffeecb3a11dbd5be347b5a3d98f2 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 19 Jul 2013 15:08:15 +0100 Subject: [PATCH 2887/2900] arm64: Only enable local interrupts after the CPU is marked online There is a slight chance that (timer) interrupts are triggered before a secondary CPU has been marked online with implications on softirq thread affinity. Signed-off-by: Catalin Marinas Reported-by: Kirill Tkhai --- arch/arm64/kernel/smp.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5d54e3717bf8..9c93e126328c 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -199,13 +199,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) raw_spin_lock(&boot_lock); raw_spin_unlock(&boot_lock); - /* - * Enable local interrupts. - */ - notify_cpu_starting(cpu); - local_irq_enable(); - local_fiq_enable(); - /* * OK, now it's safe to let the boot CPU continue. Wait for * the CPU migration code to notice that the CPU is online @@ -214,6 +207,14 @@ asmlinkage void __cpuinit secondary_start_kernel(void) set_cpu_online(cpu, true); complete(&cpu_running); + /* + * Enable GIC and timers. + */ + notify_cpu_starting(cpu); + + local_irq_enable(); + local_fiq_enable(); + /* * OK, it's off to the idle thread for us */ -- GitLab From c783c2815e13bbb0c0b99997cc240bd7e91b6bb8 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 24 Jun 2013 10:27:49 +0100 Subject: [PATCH 2888/2900] arm64: add '#ifdef CONFIG_COMPAT' for aarch32_break_handler() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If 'COMPAT' not defined, aarch32_break_handler() cannot pass compiling, and it can work independent with 'COMPAT', so remove dummy definition. The related error: arch/arm64/kernel/debug-monitors.c:249:5: error: redefinition of ‘aarch32_break_handler’ In file included from arch/arm64/kernel/debug-monitors.c:29:0: /root/linux-next/arch/arm64/include/asm/debug-monitors.h:89:12: note: previous definition of ‘aarch32_break_handler’ was here Signed-off-by: Chen Gang Acked-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/debug-monitors.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index ef8235c68c09..a2232d07be9d 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -83,14 +83,7 @@ static inline int reinstall_suspended_bps(struct pt_regs *regs) } #endif -#ifdef CONFIG_COMPAT int aarch32_break_handler(struct pt_regs *regs); -#else -static int aarch32_break_handler(struct pt_regs *regs) -{ - return -EFAULT; -} -#endif #endif /* __ASSEMBLY */ #endif /* __KERNEL__ */ -- GitLab From db6f41063cbdb58b14846e600e6bc3f4e4c2e888 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 19 Jul 2013 15:37:12 +0100 Subject: [PATCH 2889/2900] arm64: mm: don't treat user cache maintenance faults as writes On arm64, cache maintenance faults appear as data aborts with the CM bit set in the ESR. The WnR bit, usually used to distinguish between faulting loads and stores, always reads as 1 and (slightly confusingly) the instructions are treated as reads by the architecture. This patch fixes our fault handling code to treat cache maintenance faults in the same way as loads. Signed-off-by: Will Deacon Cc: Signed-off-by: Catalin Marinas --- arch/arm64/mm/fault.c | 46 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 0ecac8980aae..6c8ba25bf6bb 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -152,25 +152,8 @@ void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) #define ESR_CM (1 << 8) #define ESR_LNX_EXEC (1 << 24) -/* - * Check that the permissions on the VMA allow for the fault which occurred. - * If we encountered a write fault, we must have write permission, otherwise - * we allow any permission. - */ -static inline bool access_error(unsigned int esr, struct vm_area_struct *vma) -{ - unsigned int mask = VM_READ | VM_WRITE | VM_EXEC; - - if (esr & ESR_WRITE) - mask = VM_WRITE; - if (esr & ESR_LNX_EXEC) - mask = VM_EXEC; - - return vma->vm_flags & mask ? false : true; -} - static int __do_page_fault(struct mm_struct *mm, unsigned long addr, - unsigned int esr, unsigned int flags, + unsigned int mm_flags, unsigned long vm_flags, struct task_struct *tsk) { struct vm_area_struct *vma; @@ -188,12 +171,17 @@ static int __do_page_fault(struct mm_struct *mm, unsigned long addr, * it. */ good_area: - if (access_error(esr, vma)) { + /* + * Check that the permissions on the VMA allow for the fault which + * occurred. If we encountered a write or exec fault, we must have + * appropriate permissions, otherwise we allow any permission. + */ + if (!(vma->vm_flags & vm_flags)) { fault = VM_FAULT_BADACCESS; goto out; } - return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); + return handle_mm_fault(mm, vma, addr & PAGE_MASK, mm_flags); check_stack: if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) @@ -208,9 +196,15 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; - bool write = (esr & ESR_WRITE) && !(esr & ESR_CM); - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | - (write ? FAULT_FLAG_WRITE : 0); + unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC; + unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + + if (esr & ESR_LNX_EXEC) { + vm_flags = VM_EXEC; + } else if ((esr & ESR_WRITE) && !(esr & ESR_CM)) { + vm_flags = VM_WRITE; + mm_flags |= FAULT_FLAG_WRITE; + } tsk = current; mm = tsk->mm; @@ -248,7 +242,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, #endif } - fault = __do_page_fault(mm, addr, esr, flags, tsk); + fault = __do_page_fault(mm, addr, mm_flags, vm_flags, tsk); /* * If we need to retry but a fatal signal is pending, handle the @@ -265,7 +259,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, */ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); - if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (mm_flags & FAULT_FLAG_ALLOW_RETRY) { if (fault & VM_FAULT_MAJOR) { tsk->maj_flt++; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, @@ -280,7 +274,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of * starvation. */ - flags &= ~FAULT_FLAG_ALLOW_RETRY; + mm_flags &= ~FAULT_FLAG_ALLOW_RETRY; goto retry; } } -- GitLab From ff701306cd49aaff80fb852323b387812bc76491 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 11 Jul 2013 12:13:00 +0100 Subject: [PATCH 2890/2900] arm64: use common reboot infrastructure Commit 7b6d864b48d9 (reboot: arm: change reboot_mode to use enum reboot_mode) changed the way reboot is handled on arm, which has a direct impact on arm64 as we share the reset driver on the VE platform. The obvious fix is to move arm64 to use the same infrastructure. Signed-off-by: Marc Zyngier [catalin.marinas@arm.com: removed reboot_mode = REBOOT_HARD default setting] Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/system_misc.h | 3 ++- arch/arm64/kernel/process.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index a6e1750369ef..7a18fabbe0f6 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -23,6 +23,7 @@ #include #include #include +#include struct pt_regs; @@ -41,7 +42,7 @@ extern void show_pte(struct mm_struct *mm, unsigned long addr); extern void __show_regs(struct pt_regs *); void soft_restart(unsigned long); -extern void (*arm_pm_restart)(char str, const char *cmd); +extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); #define UDBG_UNDEFINED (1 << 0) #define UDBG_SYSCALL (1 << 1) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 46f02c3b5015..1788bf6b471f 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -132,7 +132,7 @@ void machine_restart(char *cmd) /* Now call the architecture specific reboot code. */ if (arm_pm_restart) - arm_pm_restart('h', cmd); + arm_pm_restart(reboot_mode, cmd); /* * Whoops - the architecture was unable to reboot. -- GitLab From 3c8f24225752fba30f7265202ce6092318ed9fac Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 15 Jul 2013 11:57:06 -0400 Subject: [PATCH 2891/2900] Btrfs: update drop progress before stopping snapshot dropping Alex pointed out a problem and fix that exists in the drop one snapshot at a time patch. If we decide we need to exit for whatever reason (umount for example) we will just exit the snapshot dropping without updating the drop progress. So the next time we go to resume we will BUG_ON() because we can't find the extent we left off at because we never updated it. This patch fixes the problem. Cc: stable@vger.kernel.org Reported-by: Alex Lyakas Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0236de711989..a429704dd95f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7552,11 +7552,6 @@ int btrfs_drop_snapshot(struct btrfs_root *root, wc->reada_count = BTRFS_NODEPTRS_PER_BLOCK(root); while (1) { - if (!for_reloc && btrfs_need_cleaner_sleep(root)) { - pr_debug("btrfs: drop snapshot early exit\n"); - err = -EAGAIN; - goto out_end_trans; - } ret = walk_down_tree(trans, root, path, wc); if (ret < 0) { @@ -7584,7 +7579,8 @@ int btrfs_drop_snapshot(struct btrfs_root *root, } BUG_ON(wc->level == 0); - if (btrfs_should_end_transaction(trans, tree_root)) { + if (btrfs_should_end_transaction(trans, tree_root) || + (!for_reloc && btrfs_need_cleaner_sleep(root))) { ret = btrfs_update_root(trans, tree_root, &root->root_key, root_item); @@ -7595,6 +7591,12 @@ int btrfs_drop_snapshot(struct btrfs_root *root, } btrfs_end_transaction_throttle(trans, tree_root); + if (!for_reloc && btrfs_need_cleaner_sleep(root)) { + pr_debug("btrfs: drop snapshot early exit\n"); + err = -EAGAIN; + goto out_free; + } + trans = btrfs_start_transaction(tree_root, 0); if (IS_ERR(trans)) { err = PTR_ERR(trans); -- GitLab From fec386ac1428f9c0e672df952cbca5cebd4e4e2f Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 15 Jul 2013 12:41:42 -0400 Subject: [PATCH 2892/2900] Btrfs: fix lock leak when resuming snapshot deletion We aren't setting path->locks[level] when we resume a snapshot deletion which means we won't unlock the buffer when we free the path. This causes deadlocks if we happen to re-allocate the block before we've evicted the extent buffer from cache. Thanks, Cc: stable@vger.kernel.org Reported-by: Alex Lyakas Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a429704dd95f..e814b1312511 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7523,6 +7523,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, while (1) { btrfs_tree_lock(path->nodes[level]); btrfs_set_lock_blocking(path->nodes[level]); + path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; ret = btrfs_lookup_extent_info(trans, root, path->nodes[level]->start, @@ -7538,6 +7539,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, break; btrfs_tree_unlock(path->nodes[level]); + path->locks[level] = 0; WARN_ON(wc->refs[level] != 1); level--; } -- GitLab From d29a9f629e009c9b90e5859bce581070fd6247fc Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 17 Jul 2013 19:30:20 -0400 Subject: [PATCH 2893/2900] Btrfs: re-add root to dead root list if we stop dropping it If we stop dropping a root for whatever reason we need to add it back to the dead root list so that we will re-start the dropping next transaction commit. The other case this happens is if we recover a drop because we will add a root without adding it to the fs radix tree, so we can leak it's root and commit root extent buffer, adding this to the dead root list makes this cleanup happen. Thanks, Cc: stable@vger.kernel.org Reported-by: Alex Lyakas Signed-off-by: Josef Bacik --- fs/btrfs/extent-tree.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e814b1312511..1204c8ef6f32 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7466,6 +7466,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int err = 0; int ret; int level; + bool root_dropped = false; path = btrfs_alloc_path(); if (!path) { @@ -7643,12 +7644,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root, free_extent_buffer(root->commit_root); btrfs_put_fs_root(root); } + root_dropped = true; out_end_trans: btrfs_end_transaction_throttle(trans, tree_root); out_free: kfree(wc); btrfs_free_path(path); out: + /* + * So if we need to stop dropping the snapshot for whatever reason we + * need to make sure to add it back to the dead root list so that we + * keep trying to do the work later. This also cleans up roots if we + * don't have it in the radix (like when we recover after a power fail + * or unmount) so we don't leak memory. + */ + if (root_dropped == false) + btrfs_add_dead_root(root); if (err) btrfs_std_error(root->fs_info, err); return err; -- GitLab From 115930cb2d444a684975cf2325759cb48ebf80cc Mon Sep 17 00:00:00 2001 From: Stefan Behrens Date: Thu, 4 Jul 2013 16:14:23 +0200 Subject: [PATCH 2894/2900] Btrfs: fix wrong write offset when replacing a device Miao Xie reported the following issue: The filesystem was corrupted after we did a device replace. Steps to reproduce: # mkfs.btrfs -f -m single -d raid10 .. # mount # btrfs replace start -rfB 1 # umount # btrfsck The reason for the issue is that we changed the write offset by mistake, introduced by commit 625f1c8dc. We read the data from the source device at first, and then write the data into the corresponding place of the new device. In order to implement the "-r" option, the source location is remapped using btrfs_map_block(). The read takes place on the mapped location, and the write needs to take place on the unmapped location. Currently the write is using the mapped location, and this commit changes it back by undoing the change to the write address that the aforementioned commit added by mistake. Reported-by: Miao Xie Cc: # 3.10+ Signed-off-by: Stefan Behrens Signed-off-by: Josef Bacik --- fs/btrfs/scrub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 4ba2a69a60ad..64a157becbe5 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -2495,7 +2495,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx, ret = scrub_extent(sctx, extent_logical, extent_len, extent_physical, extent_dev, flags, generation, extent_mirror_num, - extent_physical); + extent_logical - logical + physical); if (ret) goto out; -- GitLab From ba57ea64cb1820deb37637de0fdb107f0dc90089 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 20 Jul 2013 03:11:32 +0400 Subject: [PATCH 2895/2900] allow O_TMPFILE to work with O_WRONLY Signed-off-by: Al Viro --- fs/open.c | 2 ++ include/uapi/asm-generic/fcntl.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/open.c b/fs/open.c index 9156cb050d08..d53e29895082 100644 --- a/fs/open.c +++ b/fs/open.c @@ -844,6 +844,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o if ((flags & O_TMPFILE_MASK) != O_TMPFILE) return -EINVAL; acc_mode = MAY_OPEN | ACC_MODE(flags); + if (!(acc_mode & MAY_WRITE)) + return -EINVAL; } else if (flags & O_PATH) { /* * If we have O_PATH in the open flag. Then we diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index 05ac354e124d..95e46c8e05f9 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -89,8 +89,8 @@ #endif /* a horrid kludge trying to make sure that this will fail on old kernels */ -#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY | O_RDWR) -#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT | O_ACCMODE) +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) +#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT) #ifndef O_NDELAY #define O_NDELAY O_NONBLOCK -- GitLab From acfec9a5a892f98461f52ed5770de99a3e571ae2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 20 Jul 2013 03:13:55 +0400 Subject: [PATCH 2896/2900] livelock avoidance in sget() Eric Sandeen has found a nasty livelock in sget() - take a mount(2) about to fail. The superblock is on ->fs_supers, ->s_umount is held exclusive, ->s_active is 1. Along comes two more processes, trying to mount the same thing; sget() in each is picking that superblock, bumping ->s_count and trying to grab ->s_umount. ->s_active is 3 now. Original mount(2) finally gets to deactivate_locked_super() on failure; ->s_active is 2, superblock is still ->fs_supers because shutdown will *not* happen until ->s_active hits 0. ->s_umount is dropped and now we have two processes chasing each other: s_active = 2, A acquired ->s_umount, B blocked A sees that the damn thing is stillborn, does deactivate_locked_super() s_active = 1, A drops ->s_umount, B gets it A restarts the search and finds the same superblock. And bumps it ->s_active. s_active = 2, B holds ->s_umount, A blocked on trying to get it ... and we are in the earlier situation with A and B switched places. The root cause, of course, is that ->s_active should not grow until we'd got MS_BORN. Then failing ->mount() will have deactivate_locked_super() shut the damn thing down. Fortunately, it's easy to do - the key point is that grab_super() is called only for superblocks currently on ->fs_supers, so it can bump ->s_count and grab ->s_umount first, then check MS_BORN and bump ->s_active; we must never increment ->s_count for superblocks past ->kill_sb(), but grab_super() is never called for those. The bug is pretty old; we would've caught it by now, if not for accidental exclusion between sget() for block filesystems; the things like cgroup or e.g. mtd-based filesystems don't have anything of that sort, so they get bitten. The right way to deal with that is obviously to fix sget()... Signed-off-by: Al Viro --- fs/super.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/fs/super.c b/fs/super.c index 7465d4364208..68307c029228 100644 --- a/fs/super.c +++ b/fs/super.c @@ -336,19 +336,19 @@ EXPORT_SYMBOL(deactivate_super); * and want to turn it into a full-blown active reference. grab_super() * is called with sb_lock held and drops it. Returns 1 in case of * success, 0 if we had failed (superblock contents was already dead or - * dying when grab_super() had been called). + * dying when grab_super() had been called). Note that this is only + * called for superblocks not in rundown mode (== ones still on ->fs_supers + * of their type), so increment of ->s_count is OK here. */ static int grab_super(struct super_block *s) __releases(sb_lock) { - if (atomic_inc_not_zero(&s->s_active)) { - spin_unlock(&sb_lock); - return 1; - } - /* it's going away */ s->s_count++; spin_unlock(&sb_lock); - /* wait for it to die */ down_write(&s->s_umount); + if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) { + put_super(s); + return 1; + } up_write(&s->s_umount); put_super(s); return 0; @@ -463,11 +463,6 @@ struct super_block *sget(struct file_system_type *type, destroy_super(s); s = NULL; } - down_write(&old->s_umount); - if (unlikely(!(old->s_flags & MS_BORN))) { - deactivate_locked_super(old); - goto retry; - } return old; } } @@ -660,10 +655,10 @@ struct super_block *get_active_super(struct block_device *bdev) if (hlist_unhashed(&sb->s_instances)) continue; if (sb->s_bdev == bdev) { - if (grab_super(sb)) /* drops sb_lock */ - return sb; - else + if (!grab_super(sb)) goto restart; + up_write(&sb->s_umount); + return sb; } } spin_unlock(&sb_lock); -- GitLab From 24924a20dab603089011f9d3eb7622f0f6ef93c0 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 18 Jul 2013 22:09:08 +0800 Subject: [PATCH 2897/2900] vfs: constify dentry parameter in d_count() so that it can be used in places like d_compare/d_hash without causing a compiler warning. Signed-off-by: Peng Tao Signed-off-by: Al Viro --- include/linux/dcache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 3092df3614ae..b90337c9d468 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -324,7 +324,7 @@ static inline int __d_rcu_to_refcount(struct dentry *dentry, unsigned seq) return ret; } -static inline unsigned d_count(struct dentry *dentry) +static inline unsigned d_count(const struct dentry *dentry) { return dentry->d_count; } -- GitLab From e94bd3490f4ef342801cfc76b33d8baf9ccc9437 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Sat, 20 Jul 2013 21:58:38 -0400 Subject: [PATCH 2898/2900] ext4: fix a BUG when opening a file with O_TMPFILE flag When we try to open a file with O_TMPFILE flag, we will trigger a bug. The root cause is that in ext4_orphan_add() we check ->i_nlink == 0 and this check always fails because we set ->i_nlink = 1 in inode_init_always(). We can use the following program to trigger it: int main(int argc, char *argv[]) { int fd; fd = open(argv[1], O_TMPFILE, 0666); if (fd < 0) { perror("open "); return -1; } close(fd); return 0; } The oops message looks like this: kernel BUG at fs/ext4/namei.c:2572! invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: dlci bridge stp hidp cmtp kernelcapi l2tp_ppp l2tp_netlink l2tp_core sctp libcrc32c rfcomm tun fuse nfnetli nk can_raw ipt_ULOG can_bcm x25 scsi_transport_iscsi ipx p8023 p8022 appletalk phonet psnap vmw_vsock_vmci_transport af_key vmw_vmci rose vsock atm can netrom ax25 af_rxrpc ir da pppoe pppox ppp_generic slhc bluetooth nfc rfkill rds caif_socket caif crc_ccitt af_802154 llc2 llc snd_hda_codec_realtek snd_hda_intel snd_hda_codec serio_raw snd_pcm pcsp kr edac_core snd_page_alloc snd_timer snd soundcore r8169 mii sr_mod cdrom pata_atiixp radeon backlight drm_kms_helper ttm CPU: 1 PID: 1812571 Comm: trinity-child2 Not tainted 3.11.0-rc1+ #12 Hardware name: Gigabyte Technology Co., Ltd. GA-MA78GM-S2H/GA-MA78GM-S2H, BIOS F12a 04/23/2010 task: ffff88007dfe69a0 ti: ffff88010f7b6000 task.ti: ffff88010f7b6000 RIP: 0010:[] [] ext4_orphan_add+0x299/0x2b0 RSP: 0018:ffff88010f7b7cf8 EFLAGS: 00010202 RAX: 0000000000000000 RBX: ffff8800966d3020 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff88007dfe70b8 RDI: 0000000000000001 RBP: ffff88010f7b7d40 R08: ffff880126a3c4e0 R09: ffff88010f7b7ca0 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8801271fd668 R13: ffff8800966d2f78 R14: ffff88011d7089f0 R15: ffff88007dfe69a0 FS: 00007f70441a3740(0000) GS:ffff88012a800000(0000) knlGS:00000000f77c96c0 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000002834000 CR3: 0000000107964000 CR4: 00000000000007e0 DR0: 0000000000780000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600 Stack: 0000000000002000 00000020810b6dde 0000000000000000 ffff88011d46db00 ffff8800966d3020 ffff88011d7089f0 ffff88009c7f4c10 ffff88010f7b7f2c ffff88007dfe69a0 ffff88010f7b7da8 ffffffff8125cfac ffff880100000004 Call Trace: [] ext4_tmpfile+0x12c/0x180 [] path_openat+0x238/0x700 [] ? native_sched_clock+0x24/0x80 [] do_filp_open+0x47/0xa0 [] ? __alloc_fd+0xaf/0x200 [] do_sys_open+0x124/0x210 [] ? syscall_trace_enter+0x25/0x290 [] SyS_open+0x1e/0x20 [] tracesys+0xdd/0xe2 [] ? start_thread_common.constprop.6+0x1/0xa0 Code: 04 00 00 00 89 04 24 31 c0 e8 c4 77 04 00 e9 43 fe ff ff 66 25 00 d0 66 3d 00 80 0f 84 0e fe ff ff 83 7b 48 00 0f 84 04 fe ff ff <0f> 0b 49 8b 8c 24 50 07 00 00 e9 88 fe ff ff 0f 1f 84 00 00 00 Here we couldn't call clear_nlink() directly because in d_tmpfile() we will call inode_dec_link_count() to decrease ->i_nlink. So this commit tries to call d_tmpfile() before ext4_orphan_add() to fix this problem. Reported-by: Dave Jones Signed-off-by: Zheng Liu Tested-by: Darrick J. Wong Tested-by: Dave Jones Signed-off-by: "Theodore Ts'o" Acked-by: Al Viro --- fs/ext4/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 234b834d5a97..35f55a0dbc4b 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2316,11 +2316,11 @@ static int ext4_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_op = &ext4_file_inode_operations; inode->i_fop = &ext4_file_operations; ext4_set_aops(inode); + d_tmpfile(dentry, inode); err = ext4_orphan_add(handle, inode); if (err) goto err_drop_inode; mark_inode_dirty(inode); - d_tmpfile(dentry, inode); unlock_new_inode(inode); } if (handle) -- GitLab From dda5690defe4af62ee120f055e98e40d97e4c760 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Sat, 20 Jul 2013 22:03:20 -0400 Subject: [PATCH 2899/2900] ext3: fix a BUG when opening a file with O_TMPFILE flag When we try to open a file with O_TMPFILE flag, we will trigger a bug. The root cause is that in ext4_orphan_add() we check ->i_nlink == 0 and this check always fails because we set ->i_nlink = 1 in inode_init_always(). We can use the following program to trigger it: int main(int argc, char *argv[]) { int fd; fd = open(argv[1], O_TMPFILE, 0666); if (fd < 0) { perror("open "); return -1; } close(fd); return 0; } The oops message looks like this: kernel: kernel BUG at fs/ext3/namei.c:1992! kernel: invalid opcode: 0000 [#1] SMP kernel: Modules linked in: ext4 jbd2 crc16 cpufreq_ondemand ipv6 dm_mirror dm_region_hash dm_log dm_mod parport_pc parport serio_raw sg dcdbas pcspkr i2c_i801 ehci_pci ehci_hcd button acpi_cpufreq mperf e1000e ptp pps_core ttm drm_kms_helper drm hwmon i2c_algo_bit i2c_core ext3 jbd sd_mod ahci libahci libata scsi_mod uhci_hcd kernel: CPU: 0 PID: 2882 Comm: tst_tmpfile Not tainted 3.11.0-rc1+ #4 kernel: Hardware name: Dell Inc. OptiPlex 780 /0V4W66, BIOS A05 08/11/2010 kernel: task: ffff880112d30050 ti: ffff8801124d4000 task.ti: ffff8801124d4000 kernel: RIP: 0010:[] [] ext3_orphan_add+0x6a/0x1eb [ext3] kernel: RSP: 0018:ffff8801124d5cc8 EFLAGS: 00010202 kernel: RAX: 0000000000000000 RBX: ffff880111510128 RCX: ffff8801114683a0 kernel: RDX: 0000000000000000 RSI: ffff880111510128 RDI: ffff88010fcf65a8 kernel: RBP: ffff8801124d5d18 R08: 0080000000000000 R09: ffffffffa00d3b7f kernel: R10: ffff8801114683a0 R11: ffff8801032a2558 R12: 0000000000000000 kernel: R13: ffff88010fcf6800 R14: ffff8801032a2558 R15: ffff8801115100d8 kernel: FS: 00007f5d172b5700(0000) GS:ffff880117c00000(0000) knlGS:0000000000000000 kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b kernel: CR2: 00007f5d16df15d0 CR3: 0000000110b1d000 CR4: 00000000000407f0 kernel: Stack: kernel: 000000000000000c ffff8801048a7dc8 ffff8801114685a8 ffffffffa00b80d7 kernel: ffff8801124d5e38 ffff8801032a2558 ffff88010ce24d68 0000000000000000 kernel: ffff88011146b300 ffff8801124d5d44 ffff8801124d5d78 ffffffffa00db7e1 kernel: Call Trace: kernel: [] ? journal_start+0x8c/0xbd [jbd] kernel: [] ext3_tmpfile+0xb2/0x13b [ext3] kernel: [] path_openat+0x11f/0x5e7 kernel: [] ? list_del+0x11/0x30 kernel: [] ? __dequeue_entity+0x33/0x38 kernel: [] do_filp_open+0x3f/0x8d kernel: [] ? __alloc_fd+0x50/0x102 kernel: [] do_sys_open+0x13b/0x1cd kernel: [] SyS_open+0x1e/0x20 kernel: [] system_call_fastpath+0x16/0x1b kernel: Code: 39 c7 0f 85 67 01 00 00 0f b7 03 25 00 f0 00 00 3d 00 40 00 00 74 18 3d 00 80 00 00 74 11 3d 00 a0 00 00 74 0a 83 7b 48 00 74 04 <0f> 0b eb fe 49 8b 85 50 03 00 00 4c 89 f6 48 c7 c7 c0 99 0e a0 kernel: RIP [] ext3_orphan_add+0x6a/0x1eb [ext3] kernel: RSP Here we couldn't call clear_nlink() directly because in d_tmpfile() we will call inode_dec_link_count() to decrease ->i_nlink. So this commit tries to call d_tmpfile() before ext4_orphan_add() to fix this problem. Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" Cc: Jan Kara Cc: Al Viro --- fs/ext3/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 998ea111e537..1194b1f0f839 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1780,11 +1780,11 @@ static int ext3_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; ext3_set_aops(inode); + d_tmpfile(dentry, inode); err = ext3_orphan_add(handle, inode); if (err) goto err_drop_inode; mark_inode_dirty(inode); - d_tmpfile(dentry, inode); unlock_new_inode(inode); } ext3_journal_stop(handle); -- GitLab From 3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 Jul 2013 12:05:29 -0700 Subject: [PATCH 2900/2900] Linux 3.11-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9262ba8da4f9..a35f72a420c0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 11 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Linux for Workgroups # *DOCUMENTATION* -- GitLab